dependency-tree 11.5.0 → 12.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,7 +18,10 @@ npm install dependency-tree
18
18
  ## Usage
19
19
 
20
20
  ```js
21
- const dependencyTree = require('dependency-tree');
21
+ // ESM
22
+ import dependencyTree from 'dependency-tree';
23
+ // CommonJS
24
+ const { default: dependencyTree } = require('dependency-tree');
22
25
 
23
26
  // Returns a nested dependency tree object for the given file
24
27
  const tree = dependencyTree({
@@ -30,7 +33,7 @@ const tree = dependencyTree({
30
33
  nodeModulesConfig: {
31
34
  entry: 'module'
32
35
  }, // optional
33
- filter: path => !path.includes('node_modules'), // optional
36
+ filter: (dependencyPath, parentPath) => !dependencyPath.includes('node_modules'), // optional
34
37
  nonExistent: [], // optional
35
38
  noTypeDefinitions: false // optional
36
39
  });
@@ -49,15 +52,19 @@ const list = dependencyTree.toList({
49
52
  |---|---|---|---|
50
53
  | `filename` | `string` | - | **Required.** Absolute path to the entry file |
51
54
  | `directory` | `string` | - | **Required.** Root directory used to resolve relative paths |
55
+ | `root` | `string` | `undefined` | Alias for `directory` |
52
56
  | `requireConfig` | `string` | `undefined` | Path to a RequireJS config for AMD modules (resolves aliased paths) |
57
+ | `config` | `string` | `undefined` | Alias for `requireConfig` |
53
58
  | `webpackConfig` | `string` | `undefined` | Path to a webpack config for aliased modules |
54
59
  | `tsConfig` | `string \| object` | `undefined` | Path to a TypeScript config file, or a preloaded config object |
55
60
  | `tsConfigPath` | `string` | `undefined` | Virtual path for the TypeScript config when `tsConfig` is an object. Required for [Path Mapping](https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping); ignored when `tsConfig` is a string path |
56
61
  | `nodeModulesConfig` | `object` | `undefined` | Config for resolving `node_modules` entry files (e.g. `{ entry: 'module' }`) |
57
- | `visited` | `object` | `{}` | Memoization cache (`filename subtree`) to skip already-processed files |
62
+ | `visited` | `object` | `{}` | Memoization cache (filename to subtree) to skip already-processed files |
58
63
  | `nonExistent` | `string[]` | `[]` | Array populated with partial paths that could not be resolved |
59
- | `filter` | `(depPath, parentPath) => boolean` | `undefined` | Return `true` to include a dependency (and its subtree) in the tree |
60
- | `detective` | `object` | `undefined` | Detector options passed to [precinct](https://github.com/dependents/node-precinct#usage) - e.g. `{ amd: { skipLazyLoaded: true } }` |
64
+ | `isListForm` | `boolean` | `false` | Return a flat post-order list of paths instead of a nested tree (same as calling `dependencyTree.toList()`) |
65
+ | `filter` | `(dependencyPath: string, parentPath: string) => boolean` | `undefined` | Return `true` to include a dependency (and its subtree) in the tree |
66
+ | `detectiveConfig` | `object` | `{}` | Options passed to [precinct](https://github.com/dependents/node-precinct#usage) for dependency extraction - e.g. `{ amd: { skipLazyLoaded: true } }`, `{ ts: { skipTypeImports: true } }` |
67
+ | `detective` | `object` | `{}` | Alias for `detectiveConfig` |
61
68
  | `noTypeDefinitions` | `boolean` | `false` | Resolve TypeScript imports to `*.js` instead of `*.d.ts` |
62
69
 
63
70
  ### Output format
package/bin/cli.js CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- 'use strict';
3
+ import process from 'node:process';
4
+ import { stringifyChunked } from '@discoveryjs/json-ext';
5
+ import { program } from 'commander';
6
+ import dependencyTree from '../index.js';
7
+ import pkg from '../package.json' with { type: 'json' };
4
8
 
5
- const process = require('node:process');
6
- const { program } = require('commander');
7
- const { stringifyChunked } = require('@discoveryjs/json-ext');
8
- const dependencyTree = require('../index.js');
9
- const { name, description, version } = require('../package.json');
9
+ const { name, description, version } = pkg;
10
10
 
11
11
  program
12
12
  .name(name)
package/index.js CHANGED
@@ -1,32 +1,19 @@
1
- 'use strict';
2
-
3
- const fs = require('node:fs');
4
- const path = require('node:path');
5
- const { debuglog } = require('node:util');
6
- const cabinet = require('filing-cabinet');
7
- const precinct = require('precinct');
8
- const Config = require('./lib/config.js');
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { debuglog } from 'node:util';
4
+ import cabinet from 'filing-cabinet';
5
+ import precinct from 'precinct';
6
+ import Config from './lib/config.js';
9
7
 
10
8
  const debug = debuglog('tree');
11
9
 
12
10
  /**
13
11
  * Returns the dependency tree of a module as a nested object
14
12
  *
15
- * @param {Object} options
16
- * @param {string} options.filename - Entry module path
17
- * @param {string} options.directory - Root directory containing all files
18
- * @param {string} [options.requireConfig] - Path to a RequireJS config
19
- * @param {string} [options.webpackConfig] - Path to a webpack config
20
- * @param {string} [options.nodeModulesConfig] - Config for resolving node_modules entry files
21
- * @param {Object} [options.visited] - Memoization cache: filename ? subtree
22
- * @param {Array} [options.nonExistent] - Accumulator for unresolvable partials
23
- * @param {boolean} [options.isListForm=false] - Return a flat list instead of a tree
24
- * @param {string|Object} [options.tsConfig] - Path to (or preloaded) TypeScript config
25
- * @param {string} [options.tsConfigPath] - (Virtual) path to tsconfig when tsConfig is an object; needed for Path Mapping
26
- * @param {boolean} [options.noTypeDefinitions] - Resolve TS imports to `*.js` instead of `*.d.ts`
27
- * @returns {Object}
13
+ * @param {import('./lib/config.js').ConfigOptions} [options]
14
+ * @returns {object}
28
15
  */
29
- module.exports = function(options = {}) {
16
+ function dependencyTree(options = {}) {
30
17
  const config = new Config(options);
31
18
 
32
19
  if (!fs.existsSync(config.filename)) {
@@ -46,34 +33,34 @@ module.exports = function(options = {}) {
46
33
  tree = [...results];
47
34
  } else {
48
35
  debug('object form of results requested');
49
- tree = {};
50
- tree[config.filename] = results;
36
+ tree = {
37
+ [config.filename]: results
38
+ };
51
39
  }
52
40
 
53
41
  debug('final tree', tree);
54
42
  return tree;
55
- };
43
+ }
56
44
 
57
45
  /**
58
46
  * Returns a post-order flat list of absolute file paths (dependencies before dependents).
59
47
  * Every file's dependencies appear at lower indices, so the root entry point is last.
60
48
  * The list contains no duplicates. Accepts the same options as the default export.
61
49
  *
62
- * @param {Object} options - Same as the default export
63
- * @returns {Array<string>}
50
+ * @param {Parameters<typeof dependencyTree>[0]} options - Same as the default export
51
+ * @returns {string[]}
64
52
  */
65
- module.exports.toList = function(options = {}) {
66
- return module.exports({ ...options, isListForm: true });
53
+ dependencyTree.toList = function(options = {}) {
54
+ return dependencyTree({ ...options, isListForm: true });
67
55
  };
68
56
 
69
57
  /**
70
58
  * Returns resolved dependency paths for the file described by `config`.
71
- * Exposed for testing.
72
59
  *
73
60
  * @param {Config} config
74
- * @returns {Array<string>}
61
+ * @returns {string[]}
75
62
  */
76
- module.exports._getDependencies = function(config = {}) {
63
+ function getDependencies(config) {
77
64
  const precinctOptions = config.detectiveConfig;
78
65
  precinctOptions.includeCore = false;
79
66
  let dependencies;
@@ -81,7 +68,7 @@ module.exports._getDependencies = function(config = {}) {
81
68
  try {
82
69
  dependencies = precinct.paperwork(config.filename, precinctOptions);
83
70
  debug(`extracted ${dependencies.length} dependencies: `, dependencies);
84
- } catch (error) {
71
+ } catch(error) {
85
72
  debug(`error getting dependencies: ${error.message}`);
86
73
  debug(error.stack);
87
74
  return [];
@@ -121,13 +108,13 @@ module.exports._getDependencies = function(config = {}) {
121
108
  }
122
109
 
123
110
  return resolvedDependencies;
124
- };
111
+ }
125
112
 
126
113
  /**
127
114
  * @param {Config} config
128
- * @returns {Object|Set}
115
+ * @returns {Object|Set<string>}
129
116
  */
130
- function traverse(config = {}) {
117
+ function traverse(config) {
131
118
  const subTree = config.isListForm ? new Set() : {};
132
119
 
133
120
  debug(`traversing ${config.filename}`);
@@ -137,7 +124,7 @@ function traverse(config = {}) {
137
124
  return config.visited[config.filename];
138
125
  }
139
126
 
140
- let dependencies = module.exports._getDependencies(config);
127
+ let dependencies = getDependencies(config);
141
128
 
142
129
  debug('cabinet-resolved all dependencies: ', dependencies);
143
130
  // Eagerly mark the current file before recursing so any re-entrant visit exits early
@@ -176,6 +163,9 @@ function traverse(config = {}) {
176
163
  }
177
164
 
178
165
  // Dedupe in-place so the caller's array reference stays valid
166
+ /**
167
+ * @param {string[]} nonExistent
168
+ */
179
169
  function dedupeNonExistent(nonExistent) {
180
170
  const deduped = new Set(nonExistent);
181
171
  nonExistent.length = deduped.size;
@@ -190,6 +180,10 @@ function dedupeNonExistent(nonExistent) {
190
180
  // If the file is in a node_modules directory, we want to resolve the root of the package,
191
181
  // not the file itself, since the file may be buried in a subdirectory and not contain all
192
182
  // of the package's dependencies
183
+ /**
184
+ * @param {Config} localConfig
185
+ * @returns {string}
186
+ */
193
187
  function getLocalConfigDirectory(localConfig) {
194
188
  const { filename, directory } = localConfig;
195
189
 
@@ -219,3 +213,5 @@ function getLocalConfigDirectory(localConfig) {
219
213
 
220
214
  return projectPath;
221
215
  }
216
+
217
+ export default dependencyTree;
package/lib/config.js CHANGED
@@ -1,22 +1,46 @@
1
- 'use strict';
1
+ import path from 'node:path';
2
+ import process from 'node:process';
3
+ import { debuglog } from 'node:util';
4
+ import { createRequire } from 'node:module';
2
5
 
3
- const path = require('node:path');
4
- const process = require('node:process');
5
- const { debuglog } = require('node:util');
6
+ const require = createRequire(import.meta.url);
6
7
 
7
8
  const debug = debuglog('tree');
8
9
 
9
- module.exports = class Config {
10
+ /**
11
+ * @typedef {object} ConfigOptions
12
+ * @property {string} [filename] - Entry module path
13
+ * @property {string} [directory] - Root directory containing all files
14
+ * @property {string} [root] - Alias for `directory`
15
+ * @property {string} [requireConfig] - Path to a RequireJS config for AMD modules
16
+ * @property {string} [config] - Alias for `requireConfig`
17
+ * @property {string} [webpackConfig] - Path to a webpack config for aliased modules
18
+ * @property {Record<string, unknown>} [nodeModulesConfig] - Config for resolving node_modules entry files
19
+ * @property {Record<string, object>} [visited] - Memoization cache: filename to subtree
20
+ * @property {string[]} [nonExistent] - Accumulator for unresolvable partials
21
+ * @property {boolean} [isListForm] - Return a flat list instead of a tree
22
+ * @property {string | Record<string, unknown>} [tsConfig] - Path to (or preloaded) TypeScript config
23
+ * @property {string} [tsConfigPath] - Virtual path for the tsConfig object; required for Path Mapping
24
+ * @property {boolean} [noTypeDefinitions] - Resolve TS imports to `*.js` instead of `*.d.ts`
25
+ * @property {Record<string, unknown>} [detectiveConfig] - Options passed to precinct for dependency extraction
26
+ * @property {Record<string, unknown>} [detective] - Alias for `detectiveConfig`
27
+ * @property {(dependencyPath: string, parentPath: string) => boolean} [filter] - Return `true` to include a dependency
28
+ */
29
+
30
+ export default class Config {
31
+ /**
32
+ * @param {ConfigOptions} [options]
33
+ */
10
34
  constructor(options = {}) {
11
35
  this.filename = options.filename;
12
36
  this.directory = options.directory || options.root;
13
- this.visited = options.visited || {};
14
- this.nonExistent = options.nonExistent || [];
15
- this.isListForm = options.isListForm;
16
- this.requireConfig = options.config || options.requireConfig;
37
+ this.visited = options.visited ?? {};
38
+ this.nonExistent = options.nonExistent ?? [];
39
+ this.isListForm = options.isListForm ?? false;
40
+ this.requireConfig = options.config ?? options.requireConfig;
17
41
  this.webpackConfig = options.webpackConfig;
18
42
  this.nodeModulesConfig = options.nodeModulesConfig;
19
- this.detectiveConfig = options.detective || options.detectiveConfig || {};
43
+ this.detectiveConfig = options.detective ?? options.detectiveConfig ?? {};
20
44
  this.tsConfig = options.tsConfig;
21
45
  this.tsConfigPath = options.tsConfigPath;
22
46
  this.noTypeDefinitions = options.noTypeDefinitions;
@@ -47,4 +71,4 @@ module.exports = class Config {
47
71
  clone() {
48
72
  return new Config(this);
49
73
  }
50
- };
74
+ }
package/package.json CHANGED
@@ -1,23 +1,30 @@
1
1
  {
2
2
  "name": "dependency-tree",
3
- "version": "11.5.0",
3
+ "version": "12.0.0",
4
4
  "description": "Get the dependency tree of a module",
5
- "main": "index.js",
6
- "types": "index.d.ts",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./types/index.d.ts",
9
+ "default": "./index.js"
10
+ }
11
+ },
7
12
  "files": [
8
13
  "bin/cli.js",
9
14
  "lib/*.js",
10
- "index.d.ts",
15
+ "types/",
11
16
  "index.js"
12
17
  ],
13
18
  "bin": {
14
19
  "dependency-tree": "bin/cli.js"
15
20
  },
16
21
  "scripts": {
22
+ "generate:types": "tsc --allowJs --declaration --emitDeclarationOnly --declarationDir types index.js",
23
+ "check:types": "npm run generate:types && git diff HEAD --exit-code types/index.d.ts",
17
24
  "lint": "xo",
18
25
  "fix": "xo --fix",
19
26
  "mocha": "mocha \"test/*.test.mjs\"",
20
- "test": "npm run lint && npm run mocha",
27
+ "test": "npm run lint && npm run check:types && npm run mocha",
21
28
  "test:ci": "c8 npm run mocha"
22
29
  },
23
30
  "repository": {
@@ -46,72 +53,22 @@
46
53
  },
47
54
  "homepage": "https://github.com/dependents/node-dependency-tree",
48
55
  "engines": {
49
- "node": ">=18"
56
+ "node": ">=20.19.0 || >=22.12.0"
50
57
  },
51
58
  "dependencies": {
52
59
  "@discoveryjs/json-ext": "^1.1.0",
53
- "commander": "^12.1.0",
54
- "filing-cabinet": "^5.5.1",
55
- "precinct": "^12.3.2",
56
- "typescript": "^5.9.3"
60
+ "commander": "^14.0.3",
61
+ "filing-cabinet": "^6.0.0",
62
+ "precinct": "^13.0.0",
63
+ "typescript": "^6.0.3"
57
64
  },
58
65
  "devDependencies": {
59
- "c8": "^10.1.3",
66
+ "c8": "^11.0.0",
60
67
  "debug": "^4.4.3",
68
+ "globals": "^17.6.0",
61
69
  "mocha": "^11.7.5",
62
70
  "mock-fs": "^5.5.0",
63
- "resolve": "^1.22.12",
64
- "sinon": "^19.0.5",
65
- "xo": "^0.60.0"
66
- },
67
- "xo": {
68
- "space": true,
69
- "ignores": [
70
- "index.d.ts",
71
- "test/fixtures/*"
72
- ],
73
- "rules": {
74
- "arrow-body-style": "off",
75
- "camelcase": [
76
- "error",
77
- {
78
- "properties": "never"
79
- }
80
- ],
81
- "capitalized-comments": "off",
82
- "comma-dangle": [
83
- "error",
84
- "never"
85
- ],
86
- "curly": [
87
- "error",
88
- "multi-line"
89
- ],
90
- "operator-linebreak": [
91
- "error",
92
- "after"
93
- ],
94
- "object-curly-spacing": [
95
- "error",
96
- "always"
97
- ],
98
- "prefer-template": "error",
99
- "space-before-function-paren": [
100
- "error",
101
- "never"
102
- ],
103
- "unicorn/no-anonymous-default-export": "off",
104
- "unicorn/prefer-module": "off",
105
- "unicorn/prefer-top-level-await": "off",
106
- "unicorn/prevent-abbreviations": "off"
107
- },
108
- "overrides": [
109
- {
110
- "files": "test/**/*.{c,m}js",
111
- "envs": [
112
- "mocha"
113
- ]
114
- }
115
- ]
71
+ "sinon": "^22.0.0",
72
+ "xo": "^2.0.2"
116
73
  }
117
74
  }
@@ -0,0 +1,19 @@
1
+ export default dependencyTree;
2
+ /**
3
+ * Returns the dependency tree of a module as a nested object
4
+ *
5
+ * @param {import('./lib/config.js').ConfigOptions} [options]
6
+ * @returns {object}
7
+ */
8
+ declare function dependencyTree(options?: import("./lib/config.js").ConfigOptions): object;
9
+ declare namespace dependencyTree {
10
+ /**
11
+ * Returns a post-order flat list of absolute file paths (dependencies before dependents).
12
+ * Every file's dependencies appear at lower indices, so the root entry point is last.
13
+ * The list contains no duplicates. Accepts the same options as the default export.
14
+ *
15
+ * @param {Parameters<typeof dependencyTree>[0]} options - Same as the default export
16
+ * @returns {string[]}
17
+ */
18
+ function toList(options?: Parameters<typeof dependencyTree>[0]): string[];
19
+ }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * @typedef {object} ConfigOptions
3
+ * @property {string} [filename] - Entry module path
4
+ * @property {string} [directory] - Root directory containing all files
5
+ * @property {string} [root] - Alias for `directory`
6
+ * @property {string} [requireConfig] - Path to a RequireJS config for AMD modules
7
+ * @property {string} [config] - Alias for `requireConfig`
8
+ * @property {string} [webpackConfig] - Path to a webpack config for aliased modules
9
+ * @property {Record<string, unknown>} [nodeModulesConfig] - Config for resolving node_modules entry files
10
+ * @property {Record<string, object>} [visited] - Memoization cache: filename to subtree
11
+ * @property {string[]} [nonExistent] - Accumulator for unresolvable partials
12
+ * @property {boolean} [isListForm] - Return a flat list instead of a tree
13
+ * @property {string | Record<string, unknown>} [tsConfig] - Path to (or preloaded) TypeScript config
14
+ * @property {string} [tsConfigPath] - Virtual path for the tsConfig object; required for Path Mapping
15
+ * @property {boolean} [noTypeDefinitions] - Resolve TS imports to `*.js` instead of `*.d.ts`
16
+ * @property {Record<string, unknown>} [detectiveConfig] - Options passed to precinct for dependency extraction
17
+ * @property {Record<string, unknown>} [detective] - Alias for `detectiveConfig`
18
+ * @property {(dependencyPath: string, parentPath: string) => boolean} [filter] - Return `true` to include a dependency
19
+ */
20
+ export default class Config {
21
+ /**
22
+ * @param {ConfigOptions} [options]
23
+ */
24
+ constructor(options?: ConfigOptions);
25
+ filename: any;
26
+ directory: string;
27
+ visited: Record<string, object>;
28
+ nonExistent: string[];
29
+ isListForm: boolean;
30
+ requireConfig: string | undefined;
31
+ webpackConfig: string | undefined;
32
+ nodeModulesConfig: Record<string, unknown> | undefined;
33
+ detectiveConfig: Record<string, unknown>;
34
+ tsConfig: any;
35
+ tsConfigPath: string | undefined;
36
+ noTypeDefinitions: boolean | undefined;
37
+ filter: ((dependencyPath: string, parentPath: string) => boolean) | undefined;
38
+ clone(): Config;
39
+ }
40
+ export type ConfigOptions = {
41
+ /**
42
+ * - Entry module path
43
+ */
44
+ filename?: string | undefined;
45
+ /**
46
+ * - Root directory containing all files
47
+ */
48
+ directory?: string | undefined;
49
+ /**
50
+ * - Alias for `directory`
51
+ */
52
+ root?: string | undefined;
53
+ /**
54
+ * - Path to a RequireJS config for AMD modules
55
+ */
56
+ requireConfig?: string | undefined;
57
+ /**
58
+ * - Alias for `requireConfig`
59
+ */
60
+ config?: string | undefined;
61
+ /**
62
+ * - Path to a webpack config for aliased modules
63
+ */
64
+ webpackConfig?: string | undefined;
65
+ /**
66
+ * - Config for resolving node_modules entry files
67
+ */
68
+ nodeModulesConfig?: Record<string, unknown> | undefined;
69
+ /**
70
+ * - Memoization cache: filename to subtree
71
+ */
72
+ visited?: Record<string, object> | undefined;
73
+ /**
74
+ * - Accumulator for unresolvable partials
75
+ */
76
+ nonExistent?: string[] | undefined;
77
+ /**
78
+ * - Return a flat list instead of a tree
79
+ */
80
+ isListForm?: boolean | undefined;
81
+ /**
82
+ * - Path to (or preloaded) TypeScript config
83
+ */
84
+ tsConfig?: string | Record<string, unknown> | undefined;
85
+ /**
86
+ * - Virtual path for the tsConfig object; required for Path Mapping
87
+ */
88
+ tsConfigPath?: string | undefined;
89
+ /**
90
+ * - Resolve TS imports to `*.js` instead of `*.d.ts`
91
+ */
92
+ noTypeDefinitions?: boolean | undefined;
93
+ /**
94
+ * - Options passed to precinct for dependency extraction
95
+ */
96
+ detectiveConfig?: Record<string, unknown> | undefined;
97
+ /**
98
+ * - Alias for `detectiveConfig`
99
+ */
100
+ detective?: Record<string, unknown> | undefined;
101
+ /**
102
+ * - Return `true` to include a dependency
103
+ */
104
+ filter?: ((dependencyPath: string, parentPath: string) => boolean) | undefined;
105
+ };
package/index.d.ts DELETED
@@ -1,34 +0,0 @@
1
- declare namespace dependencyTree {
2
- interface TreeInnerNode {
3
- [parent: string]: TreeInnerNode | string;
4
- }
5
- type Tree = TreeInnerNode | string;
6
-
7
- export interface Options {
8
- filename: string;
9
- directory: string;
10
- visited?: Tree;
11
- nonExistent?: string[];
12
- isListForm?: boolean;
13
- requireConfig?: string;
14
- webpackConfig?: string;
15
- nodeModulesConfig?: any;
16
- detectiveConfig?: any;
17
- tsConfig?: string | Record<string, any>;
18
- noTypeDefinitions?: boolean;
19
- filter?: (path: string) => boolean;
20
- }
21
-
22
- interface Config extends Options {
23
- clone: () => Config;
24
- }
25
-
26
- function toList(options: Options): string[];
27
- function _getDependencies(config: Config): string[];
28
- }
29
-
30
- declare function dependencyTree(
31
- options: dependencyTree.Options
32
- ): dependencyTree.Tree;
33
-
34
- export = dependencyTree;