dependency-tree 11.4.3 → 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 +57 -62
- package/bin/cli.js +18 -6
- package/index.js +70 -72
- package/lib/config.js +36 -11
- package/package.json +22 -64
- package/types/index.d.ts +19 -0
- package/types/lib/config.d.ts +105 -0
- package/index.d.ts +0 -34
package/README.md
CHANGED
|
@@ -10,18 +10,20 @@
|
|
|
10
10
|
npm install dependency-tree
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
*
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
* All core Node modules (assert, path, fs, etc) are removed from the dependency list by default
|
|
13
|
+
* Supports JS (AMD, CommonJS, ES6), TypeScript, and CSS preprocessors (PostCSS, Sass, Stylus, Less) - any type handled by [precinct](https://github.com/dependents/node-precinct)
|
|
14
|
+
- CommonJS: third-party (npm) dependencies are included by default
|
|
15
|
+
- Path resolution is handled by [filing-cabinet](https://github.com/dependents/node-filing-cabinet); RequireJS and webpack loaders are supported
|
|
16
|
+
* Core Node built-ins (assert, path, fs, etc.) are excluded by default
|
|
18
17
|
|
|
19
18
|
## Usage
|
|
20
19
|
|
|
21
20
|
```js
|
|
22
|
-
|
|
21
|
+
// ESM
|
|
22
|
+
import dependencyTree from 'dependency-tree';
|
|
23
|
+
// CommonJS
|
|
24
|
+
const { default: dependencyTree } = require('dependency-tree');
|
|
23
25
|
|
|
24
|
-
// Returns a dependency tree object for the given file
|
|
26
|
+
// Returns a nested dependency tree object for the given file
|
|
25
27
|
const tree = dependencyTree({
|
|
26
28
|
filename: 'path/to/a/file',
|
|
27
29
|
directory: 'path/to/all/files',
|
|
@@ -31,14 +33,13 @@ const tree = dependencyTree({
|
|
|
31
33
|
nodeModulesConfig: {
|
|
32
34
|
entry: 'module'
|
|
33
35
|
}, // optional
|
|
34
|
-
filter:
|
|
36
|
+
filter: (dependencyPath, parentPath) => !dependencyPath.includes('node_modules'), // optional
|
|
35
37
|
nonExistent: [], // optional
|
|
36
38
|
noTypeDefinitions: false // optional
|
|
37
39
|
});
|
|
38
40
|
|
|
39
|
-
// Returns a post-order
|
|
40
|
-
//
|
|
41
|
-
// Note: you can pass the same arguments as you would to dependencyTree()
|
|
41
|
+
// Returns a post-order flat list of absolute paths (dependencies before dependents).
|
|
42
|
+
// Useful as a concatenation order for bundling.
|
|
42
43
|
const list = dependencyTree.toList({
|
|
43
44
|
filename: 'path/to/a/file',
|
|
44
45
|
directory: 'path/to/all/files'
|
|
@@ -47,78 +48,72 @@ const list = dependencyTree.toList({
|
|
|
47
48
|
|
|
48
49
|
### Options
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
51
|
+
| Option | Type | Default | Description |
|
|
52
|
+
|---|---|---|---|
|
|
53
|
+
| `filename` | `string` | - | **Required.** Absolute path to the entry file |
|
|
54
|
+
| `directory` | `string` | - | **Required.** Root directory used to resolve relative paths |
|
|
55
|
+
| `root` | `string` | `undefined` | Alias for `directory` |
|
|
56
|
+
| `requireConfig` | `string` | `undefined` | Path to a RequireJS config for AMD modules (resolves aliased paths) |
|
|
57
|
+
| `config` | `string` | `undefined` | Alias for `requireConfig` |
|
|
58
|
+
| `webpackConfig` | `string` | `undefined` | Path to a webpack config for aliased modules |
|
|
59
|
+
| `tsConfig` | `string \| object` | `undefined` | Path to a TypeScript config file, or a preloaded config object |
|
|
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 |
|
|
61
|
+
| `nodeModulesConfig` | `object` | `undefined` | Config for resolving `node_modules` entry files (e.g. `{ entry: 'module' }`) |
|
|
62
|
+
| `visited` | `object` | `{}` | Memoization cache (filename to subtree) to skip already-processed files |
|
|
63
|
+
| `nonExistent` | `string[]` | `[]` | Array populated with partial paths that could not be resolved |
|
|
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` |
|
|
68
|
+
| `noTypeDefinitions` | `boolean` | `false` | Resolve TypeScript imports to `*.js` instead of `*.d.ts` |
|
|
69
|
+
|
|
70
|
+
### Output format
|
|
71
|
+
|
|
72
|
+
The default output is a nested object where every key is an absolute file path and the value is its own subtree:
|
|
70
73
|
|
|
71
74
|
```js
|
|
72
75
|
{
|
|
73
|
-
'/
|
|
74
|
-
'/
|
|
75
|
-
'/
|
|
76
|
-
'/
|
|
76
|
+
'/path/to/a.js': {
|
|
77
|
+
'/path/to/b.js': {
|
|
78
|
+
'/path/to/d.js': {},
|
|
79
|
+
'/path/to/e.js': {}
|
|
77
80
|
},
|
|
78
|
-
'/
|
|
79
|
-
'/
|
|
80
|
-
'/
|
|
81
|
+
'/path/to/c.js': {
|
|
82
|
+
'/path/to/f.js': {},
|
|
83
|
+
'/path/to/g.js': {}
|
|
81
84
|
}
|
|
82
85
|
}
|
|
83
86
|
}
|
|
84
87
|
```
|
|
85
88
|
|
|
86
|
-
This
|
|
87
|
-
for use in the [Dependents](https://github.com/mrjoelkemp/sublime-dependents) plugin.
|
|
89
|
+
This format was designed for visual representation in the [Dependents](https://github.com/mrjoelkemp/sublime-dependents) plugin.
|
|
88
90
|
|
|
89
|
-
### CLI
|
|
91
|
+
### CLI
|
|
90
92
|
|
|
91
|
-
|
|
93
|
+
Requires a global install: `npm install -g dependency-tree`
|
|
92
94
|
|
|
93
95
|
```
|
|
94
|
-
dependency-tree --directory=path/to/
|
|
96
|
+
dependency-tree --directory=path/to/files [--list-form] [--es6-mixed-imports] [-c path/to/require/config] [-w path/to/webpack/config] filename
|
|
95
97
|
```
|
|
96
98
|
|
|
97
|
-
Prints the dependency tree
|
|
98
|
-
|
|
99
|
-
* You can alternatively print out the list form one element per line using the `--list-form` option.
|
|
100
|
-
|
|
101
|
-
## How does this work?
|
|
99
|
+
Prints the dependency tree as JSON. Use `--list-form` to print one path per line instead.
|
|
102
100
|
|
|
103
|
-
|
|
101
|
+
## How it works
|
|
104
102
|
|
|
105
|
-
|
|
103
|
+
dependency-tree passes the entry file to [precinct](https://github.com/dependents/node-precinct/) to extract raw dependency strings, then passes each to [filing-cabinet](https://github.com/dependents/node-filing-cabinet) to resolve them to real filesystem paths, and recurses until the full tree is built.
|
|
106
104
|
|
|
107
|
-
|
|
105
|
+
Precinct generates an AST via [node-source-walk](https://github.com/dependents/node-source-walk), detects the module format (CommonJS, AMD, or ES6), and delegates to the appropriate detective to extract dependency declarations.
|
|
108
106
|
|
|
109
|
-
Filing-cabinet reuses
|
|
110
|
-
|
|
111
|
-
So after the appropriate resolver finds the file on the filesystem, filing-cabinet has successfully mapped a raw dependency name to a file on the filesystem. Now, dependency-tree has a file that it can also traverse (repeating exactly what was done for the starting file).
|
|
112
|
-
|
|
113
|
-
At the end of traversing every file (in a depth-first fashion), we have a fully populated dependency tree. :dancers:
|
|
107
|
+
Filing-cabinet reuses that AST to detect the module format again, then delegates to the right resolver - necessary because AMD supports path aliasing via a RequireJS config, while CommonJS has its own resolution algorithm. The resolver returns an absolute path, which dependency-tree then recurses into.
|
|
114
108
|
|
|
115
109
|
## FAQ
|
|
116
110
|
|
|
117
|
-
### Why aren't some
|
|
111
|
+
### Why aren't some dependencies being detected?
|
|
112
|
+
|
|
113
|
+
Bugs in [precinct](https://github.com/dependents/node-precinct) or an incomplete `requireConfig`/`webpackConfig`/`tsConfig` are the most common causes. Any path that could not be resolved is appended to the array passed as `nonExistent`.
|
|
118
114
|
|
|
119
|
-
|
|
120
|
-
some dependencies may not be resolved. The optional array passed to the `nonExistent` option will be populated with paths
|
|
121
|
-
that could not be resolved. You can check this array to see where problems might exist.
|
|
115
|
+
For detailed resolution logs, set `NODE_DEBUG=*` when using the CLI:
|
|
122
116
|
|
|
123
|
-
|
|
124
|
-
|
|
117
|
+
```sh
|
|
118
|
+
NODE_DEBUG=* dependency-tree -w path/to/webpack.config.json path/to/a/file
|
|
119
|
+
```
|
package/bin/cli.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
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 {
|
|
6
|
-
const dependencyTree = require('../index.js');
|
|
7
|
-
const { name, description, version } = require('../package.json');
|
|
9
|
+
const { name, description, version } = pkg;
|
|
8
10
|
|
|
9
11
|
program
|
|
10
12
|
.name(name)
|
|
@@ -16,6 +18,7 @@ program
|
|
|
16
18
|
.option('-c, --require-config <path>', 'path to a requirejs config')
|
|
17
19
|
.option('-w, --webpack-config <path>', 'path to a webpack config')
|
|
18
20
|
.option('-t, --ts-config <path>', 'path to a typescript config')
|
|
21
|
+
.option('--es6-mixed-imports', 'detect dependencies from files that mix ES6 imports and CJS require() calls')
|
|
19
22
|
.option('--list-form', 'output the list form of the tree (one element per line)')
|
|
20
23
|
.showHelpAfterError()
|
|
21
24
|
.parse();
|
|
@@ -26,7 +29,12 @@ const options = {
|
|
|
26
29
|
root: cliOptions.directory,
|
|
27
30
|
config: cliOptions.requireConfig,
|
|
28
31
|
webpackConfig: cliOptions.webpackConfig,
|
|
29
|
-
tsConfig: cliOptions.tsConfig
|
|
32
|
+
tsConfig: cliOptions.tsConfig,
|
|
33
|
+
detective: {
|
|
34
|
+
es6: {
|
|
35
|
+
mixedImports: Boolean(cliOptions.es6MixedImports)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
30
38
|
};
|
|
31
39
|
|
|
32
40
|
if (cliOptions.listForm) {
|
|
@@ -38,5 +46,9 @@ if (cliOptions.listForm) {
|
|
|
38
46
|
} else {
|
|
39
47
|
const tree = dependencyTree(options);
|
|
40
48
|
|
|
41
|
-
|
|
49
|
+
for (const chunk of stringifyChunked(tree)) {
|
|
50
|
+
process.stdout.write(chunk);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
process.stdout.write('\n');
|
|
42
54
|
}
|
package/index.js
CHANGED
|
@@ -1,33 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
*
|
|
14
|
-
* and returns a flat list of all unique, visited nodes
|
|
11
|
+
* Returns the dependency tree of a module as a nested object
|
|
15
12
|
*
|
|
16
|
-
* @param {
|
|
17
|
-
* @
|
|
18
|
-
* @param {String} options.directory - The directory containing all JS files
|
|
19
|
-
* @param {String} [options.requireConfig] - The path to a requirejs config
|
|
20
|
-
* @param {String} [options.webpackConfig] - The path to a webpack config
|
|
21
|
-
* @param {String} [options.nodeModulesConfig] - config for resolving entry file for node_modules
|
|
22
|
-
* @param {Object} [options.visited] - Cache of visited, absolutely pathed files that should not be reprocessed.
|
|
23
|
-
* Format is a filename -> tree as list lookup table
|
|
24
|
-
* @param {Array} [options.nonExistent] - List of partials that do not exist
|
|
25
|
-
* @param {Boolean} [options.isListForm=false]
|
|
26
|
-
* @param {String|Object} [options.tsConfig] Path to a typescript config (or a preloaded one).
|
|
27
|
-
* @param {Boolean} [options.noTypeDefinitions] For TypeScript imports, whether to resolve to `*.js` instead of `*.d.ts`.
|
|
28
|
-
* @return {Object}
|
|
13
|
+
* @param {import('./lib/config.js').ConfigOptions} [options]
|
|
14
|
+
* @returns {object}
|
|
29
15
|
*/
|
|
30
|
-
|
|
16
|
+
function dependencyTree(options = {}) {
|
|
31
17
|
const config = new Config(options);
|
|
32
18
|
|
|
33
19
|
if (!fs.existsSync(config.filename)) {
|
|
@@ -47,41 +33,34 @@ module.exports = function(options = {}) {
|
|
|
47
33
|
tree = [...results];
|
|
48
34
|
} else {
|
|
49
35
|
debug('object form of results requested');
|
|
50
|
-
tree = {
|
|
51
|
-
|
|
36
|
+
tree = {
|
|
37
|
+
[config.filename]: results
|
|
38
|
+
};
|
|
52
39
|
}
|
|
53
40
|
|
|
54
41
|
debug('final tree', tree);
|
|
55
42
|
return tree;
|
|
56
|
-
}
|
|
43
|
+
}
|
|
57
44
|
|
|
58
45
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
46
|
+
* Returns a post-order flat list of absolute file paths (dependencies before dependents).
|
|
47
|
+
* Every file's dependencies appear at lower indices, so the root entry point is last.
|
|
48
|
+
* The list contains no duplicates. Accepts the same options as the default export.
|
|
62
49
|
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* The list will not contain duplicates.
|
|
67
|
-
*
|
|
68
|
-
* Params are those of module.exports
|
|
50
|
+
* @param {Parameters<typeof dependencyTree>[0]} options - Same as the default export
|
|
51
|
+
* @returns {string[]}
|
|
69
52
|
*/
|
|
70
|
-
|
|
71
|
-
options
|
|
72
|
-
|
|
73
|
-
return module.exports(options);
|
|
53
|
+
dependencyTree.toList = function(options = {}) {
|
|
54
|
+
return dependencyTree({ ...options, isListForm: true });
|
|
74
55
|
};
|
|
75
56
|
|
|
76
57
|
/**
|
|
77
|
-
* Returns
|
|
58
|
+
* Returns resolved dependency paths for the file described by `config`.
|
|
78
59
|
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* @param {Config} config
|
|
82
|
-
* @return {Array}
|
|
60
|
+
* @param {Config} config
|
|
61
|
+
* @returns {string[]}
|
|
83
62
|
*/
|
|
84
|
-
|
|
63
|
+
function getDependencies(config) {
|
|
85
64
|
const precinctOptions = config.detectiveConfig;
|
|
86
65
|
precinctOptions.includeCore = false;
|
|
87
66
|
let dependencies;
|
|
@@ -89,7 +68,7 @@ module.exports._getDependencies = function(config = {}) {
|
|
|
89
68
|
try {
|
|
90
69
|
dependencies = precinct.paperwork(config.filename, precinctOptions);
|
|
91
70
|
debug(`extracted ${dependencies.length} dependencies: `, dependencies);
|
|
92
|
-
} catch
|
|
71
|
+
} catch(error) {
|
|
93
72
|
debug(`error getting dependencies: ${error.message}`);
|
|
94
73
|
debug(error.stack);
|
|
95
74
|
return [];
|
|
@@ -129,13 +108,13 @@ module.exports._getDependencies = function(config = {}) {
|
|
|
129
108
|
}
|
|
130
109
|
|
|
131
110
|
return resolvedDependencies;
|
|
132
|
-
}
|
|
111
|
+
}
|
|
133
112
|
|
|
134
113
|
/**
|
|
135
|
-
* @param
|
|
136
|
-
* @
|
|
114
|
+
* @param {Config} config
|
|
115
|
+
* @returns {Object|Set<string>}
|
|
137
116
|
*/
|
|
138
|
-
function traverse(config
|
|
117
|
+
function traverse(config) {
|
|
139
118
|
const subTree = config.isListForm ? new Set() : {};
|
|
140
119
|
|
|
141
120
|
debug(`traversing ${config.filename}`);
|
|
@@ -145,11 +124,10 @@ function traverse(config = {}) {
|
|
|
145
124
|
return config.visited[config.filename];
|
|
146
125
|
}
|
|
147
126
|
|
|
148
|
-
let dependencies =
|
|
127
|
+
let dependencies = getDependencies(config);
|
|
149
128
|
|
|
150
129
|
debug('cabinet-resolved all dependencies: ', dependencies);
|
|
151
|
-
//
|
|
152
|
-
// so that any dependent dependencies exit
|
|
130
|
+
// Eagerly mark the current file before recursing so any re-entrant visit exits early
|
|
153
131
|
config.visited[config.filename] = config.isListForm ? [] : {};
|
|
154
132
|
|
|
155
133
|
if (config.filter) {
|
|
@@ -163,7 +141,7 @@ function traverse(config = {}) {
|
|
|
163
141
|
for (const dependency of dependencies) {
|
|
164
142
|
const localConfig = config.clone();
|
|
165
143
|
localConfig.filename = dependency;
|
|
166
|
-
localConfig.directory =
|
|
144
|
+
localConfig.directory = getLocalConfigDirectory(localConfig);
|
|
167
145
|
|
|
168
146
|
if (localConfig.isListForm) {
|
|
169
147
|
for (const item of traverse(localConfig)) {
|
|
@@ -184,7 +162,10 @@ function traverse(config = {}) {
|
|
|
184
162
|
return subTree;
|
|
185
163
|
}
|
|
186
164
|
|
|
187
|
-
//
|
|
165
|
+
// Dedupe in-place so the caller's array reference stays valid
|
|
166
|
+
/**
|
|
167
|
+
* @param {string[]} nonExistent
|
|
168
|
+
*/
|
|
188
169
|
function dedupeNonExistent(nonExistent) {
|
|
189
170
|
const deduped = new Set(nonExistent);
|
|
190
171
|
nonExistent.length = deduped.size;
|
|
@@ -196,24 +177,41 @@ function dedupeNonExistent(nonExistent) {
|
|
|
196
177
|
}
|
|
197
178
|
}
|
|
198
179
|
|
|
199
|
-
// If the file is in a
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
180
|
+
// If the file is in a node_modules directory, we want to resolve the root of the package,
|
|
181
|
+
// not the file itself, since the file may be buried in a subdirectory and not contain all
|
|
182
|
+
// of the package's dependencies
|
|
183
|
+
/**
|
|
184
|
+
* @param {Config} localConfig
|
|
185
|
+
* @returns {string}
|
|
186
|
+
*/
|
|
187
|
+
function getLocalConfigDirectory(localConfig) {
|
|
188
|
+
const { filename, directory } = localConfig;
|
|
189
|
+
|
|
190
|
+
if (!filename.includes('node_modules')) {
|
|
191
|
+
return directory;
|
|
203
192
|
}
|
|
204
193
|
|
|
205
|
-
|
|
206
|
-
|
|
194
|
+
const dir = path.dirname(filename);
|
|
195
|
+
const parts = dir.split('node_modules');
|
|
207
196
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
return
|
|
215
|
-
} catch {
|
|
216
|
-
debug(`Could not determine the root directory of package file ${filename}. Using default`);
|
|
217
|
-
return null;
|
|
197
|
+
if (parts.length < 2) {
|
|
198
|
+
return directory;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const afterNodeModules = parts.pop();
|
|
202
|
+
if (!afterNodeModules) {
|
|
203
|
+
return directory;
|
|
218
204
|
}
|
|
205
|
+
|
|
206
|
+
const segments = afterNodeModules.split(path.sep).filter(Boolean);
|
|
207
|
+
if (segments.length === 0) {
|
|
208
|
+
return directory;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const packageName = segments[0].startsWith('@') ? `${segments[0]}${path.sep}${segments[1]}` : segments[0];
|
|
212
|
+
const projectPath = path.normalize(`${parts.join('node_modules')}node_modules${path.sep}${packageName}`);
|
|
213
|
+
|
|
214
|
+
return projectPath;
|
|
219
215
|
}
|
|
216
|
+
|
|
217
|
+
export default dependencyTree;
|
package/lib/config.js
CHANGED
|
@@ -1,22 +1,46 @@
|
|
|
1
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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;
|
|
@@ -27,6 +51,7 @@ module.exports = class Config {
|
|
|
27
51
|
if (this.filter && typeof this.filter !== 'function') throw new Error('filter must be a function');
|
|
28
52
|
|
|
29
53
|
if (typeof this.tsConfig === 'string') {
|
|
54
|
+
// Pre-parse once so all recursive clones share the object form
|
|
30
55
|
debug('preparsing the ts config into an object for performance');
|
|
31
56
|
const ts = require('typescript');
|
|
32
57
|
const tsParsedConfig = ts.readJsonConfigFile(this.tsConfig, ts.sys.readFile);
|
|
@@ -46,4 +71,4 @@ module.exports = class Config {
|
|
|
46
71
|
clone() {
|
|
47
72
|
return new Config(this);
|
|
48
73
|
}
|
|
49
|
-
}
|
|
74
|
+
}
|
package/package.json
CHANGED
|
@@ -1,23 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dependency-tree",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "12.0.0",
|
|
4
4
|
"description": "Get the dependency tree of a module",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
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
|
-
"
|
|
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,71 +53,22 @@
|
|
|
46
53
|
},
|
|
47
54
|
"homepage": "https://github.com/dependents/node-dependency-tree",
|
|
48
55
|
"engines": {
|
|
49
|
-
"node": ">=
|
|
56
|
+
"node": ">=20.19.0 || >=22.12.0"
|
|
50
57
|
},
|
|
51
58
|
"dependencies": {
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
59
|
+
"@discoveryjs/json-ext": "^1.1.0",
|
|
60
|
+
"commander": "^14.0.3",
|
|
61
|
+
"filing-cabinet": "^6.0.0",
|
|
62
|
+
"precinct": "^13.0.0",
|
|
63
|
+
"typescript": "^6.0.3"
|
|
56
64
|
},
|
|
57
65
|
"devDependencies": {
|
|
58
|
-
"c8": "^
|
|
66
|
+
"c8": "^11.0.0",
|
|
59
67
|
"debug": "^4.4.3",
|
|
68
|
+
"globals": "^17.6.0",
|
|
60
69
|
"mocha": "^11.7.5",
|
|
61
70
|
"mock-fs": "^5.5.0",
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"xo": "^0.60.0"
|
|
65
|
-
},
|
|
66
|
-
"xo": {
|
|
67
|
-
"space": true,
|
|
68
|
-
"ignores": [
|
|
69
|
-
"index.d.ts",
|
|
70
|
-
"test/fixtures/*"
|
|
71
|
-
],
|
|
72
|
-
"rules": {
|
|
73
|
-
"arrow-body-style": "off",
|
|
74
|
-
"camelcase": [
|
|
75
|
-
"error",
|
|
76
|
-
{
|
|
77
|
-
"properties": "never"
|
|
78
|
-
}
|
|
79
|
-
],
|
|
80
|
-
"capitalized-comments": "off",
|
|
81
|
-
"comma-dangle": [
|
|
82
|
-
"error",
|
|
83
|
-
"never"
|
|
84
|
-
],
|
|
85
|
-
"curly": [
|
|
86
|
-
"error",
|
|
87
|
-
"multi-line"
|
|
88
|
-
],
|
|
89
|
-
"operator-linebreak": [
|
|
90
|
-
"error",
|
|
91
|
-
"after"
|
|
92
|
-
],
|
|
93
|
-
"object-curly-spacing": [
|
|
94
|
-
"error",
|
|
95
|
-
"always"
|
|
96
|
-
],
|
|
97
|
-
"prefer-template": "error",
|
|
98
|
-
"space-before-function-paren": [
|
|
99
|
-
"error",
|
|
100
|
-
"never"
|
|
101
|
-
],
|
|
102
|
-
"unicorn/no-anonymous-default-export": "off",
|
|
103
|
-
"unicorn/prefer-module": "off",
|
|
104
|
-
"unicorn/prefer-top-level-await": "off",
|
|
105
|
-
"unicorn/prevent-abbreviations": "off"
|
|
106
|
-
},
|
|
107
|
-
"overrides": [
|
|
108
|
-
{
|
|
109
|
-
"files": "test/**/*.{c,m}js",
|
|
110
|
-
"envs": [
|
|
111
|
-
"mocha"
|
|
112
|
-
]
|
|
113
|
-
}
|
|
114
|
-
]
|
|
71
|
+
"sinon": "^22.0.0",
|
|
72
|
+
"xo": "^2.0.2"
|
|
115
73
|
}
|
|
116
74
|
}
|
package/types/index.d.ts
ADDED
|
@@ -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;
|