dependency-tree 8.1.2 → 10.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
@@ -1,22 +1,28 @@
1
- ### dependency-tree [![npm](http://img.shields.io/npm/v/dependency-tree.svg)](https://npmjs.org/package/dependency-tree) [![npm](http://img.shields.io/npm/dm/dependency-tree.svg)](https://npmjs.org/package/dependency-tree)
1
+ # dependency-tree
2
+
3
+ [![CI](https://img.shields.io/github/actions/workflow/status/dependents/node-dependency-tree/ci.yml?branch=main&label=CI&logo=github)](https://github.com/dependents/node-dependency-tree/actions/workflows/ci.yml?query=branch%3Amain)
4
+ [![npm version](https://img.shields.io/npm/v/dependency-tree?logo=npm&logoColor=fff)](https://www.npmjs.com/package/dependency-tree)
5
+ [![npm downloads](https://img.shields.io/npm/dm/dependency-tree)](https://www.npmjs.com/package/dependency-tree)
2
6
 
3
7
  > Get the dependency tree of a module
4
8
 
5
- `npm install --save dependency-tree`
9
+ ```sh
10
+ npm install dependency-tree
11
+ ```
6
12
 
7
- * Works for JS (AMD, CommonJS, ES6 modules), Typescript, and CSS preprocessors (CSS (PostCSS), Sass, Stylus, and Less); basically, any module type supported by [Precinct](https://github.com/mrjoelkemp/node-precinct).
13
+ * Works for JS (AMD, CommonJS, ES6 modules), Typescript, and CSS preprocessors (CSS (PostCSS), Sass, Stylus, and Less); basically, any module type supported by [Precinct](https://github.com/dependents/node-precinct).
8
14
  - For CommonJS modules, 3rd party dependencies (npm installed dependencies) are included in the tree by default
9
- - Dependency path resolutions are handled by [filing-cabinet](https://github.com/mrjoelkemp/node-filing-cabinet)
15
+ - Dependency path resolutions are handled by [filing-cabinet](https://github.com/dependents/node-filing-cabinet)
10
16
  - Supports RequireJS and Webpack loaders
11
17
  * All core Node modules (assert, path, fs, etc) are removed from the dependency list by default
12
18
 
13
- ### Usage
19
+ ## Usage
14
20
 
15
21
  ```js
16
- var dependencyTree = require('dependency-tree');
22
+ const dependencyTree = require('dependency-tree');
17
23
 
18
24
  // Returns a dependency tree object for the given file
19
- var tree = dependencyTree({
25
+ const tree = dependencyTree({
20
26
  filename: 'path/to/a/file',
21
27
  directory: 'path/to/all/files',
22
28
  requireConfig: 'path/to/requirejs/config', // optional
@@ -33,13 +39,13 @@ var tree = dependencyTree({
33
39
  // Returns a post-order traversal (list form) of the tree with duplicate sub-trees pruned.
34
40
  // This is useful for bundling source files, because the list gives the concatenation order.
35
41
  // Note: you can pass the same arguments as you would to dependencyTree()
36
- var list = dependencyTree.toList({
42
+ const list = dependencyTree.toList({
37
43
  filename: 'path/to/a/file',
38
44
  directory: 'path/to/all/files'
39
45
  });
40
46
  ```
41
47
 
42
- #### Options
48
+ ### Options
43
49
 
44
50
  * `requireConfig`: path to a requirejs config for AMD modules (allows for the result of aliased module paths)
45
51
  * `webpackConfig`: path to a webpack config for aliased modules
@@ -54,7 +60,7 @@ var list = dependencyTree.toList({
54
60
  - See [precinct's usage docs](https://github.com/dependents/node-precinct#usage) for the list of module types you can pass options to.
55
61
  * `noTypeDefinitions`: For TypeScript imports, whether to resolve to `*.js` instead of `*.d.ts`.
56
62
 
57
- #### Format Details
63
+ ### Format Details
58
64
 
59
65
  The object form is a mapping of the dependency tree to the filesystem –
60
66
  where every key is an absolute filepath and the value is another object/subtree.
@@ -79,7 +85,7 @@ Example:
79
85
  This structure was chosen to serve as a visual representation of the dependency tree
80
86
  for use in the [Dependents](https://github.com/mrjoelkemp/sublime-dependents) plugin.
81
87
 
82
- ##### CLI version
88
+ ### CLI version
83
89
 
84
90
  * Assumes a global install: `npm install -g dependency-tree`
85
91
 
@@ -91,9 +97,9 @@ Prints the dependency tree of the given filename as stringified json (by default
91
97
 
92
98
  * You can alternatively print out the list form one element per line using the `--list-form` option.
93
99
 
94
- ### How does this work?
100
+ ## How does this work?
95
101
 
96
- Dependency tree takes in a starting file, extracts its declared dependencies via [precinct](https://github.com/dependents/node-precinct/), resolves each of those dependencies to a file on the filesystem via [filing-cabinet](https://github.com/dependents/node-filing-cabinet), then recursively performs those steps until there are no more dependencies to process.
102
+ Dependency tree takes in a starting file, extracts its declared dependencies via [precinct](https://github.com/dependents/node-precinct/), resolves each of those dependencies to a file on the filesystem via [filing-cabinet](https://github.com/dependents/node-filing-cabinet), then recursively performs those steps until there are no more dependencies to process.
97
103
 
98
104
  In more detail, the starting file is passed to precinct to extract dependencies. Dependency-tree doesn't care about how to extract dependencies, so it delegates that work to precinct: which is a multi-language dependency extractor; we'll focus on JavaScript tree generation for this example. To do the extraction, precinct delegates the abstract-syntax-tree (AST) generation to the default parser for [node-source-walk](https://github.com/dependents/node-source-walk). Precinct uses the AST to determine what type of JS module the file is (Commonjs, AMD, or ES6) and then delegates to the "detective" that's appropriate for that module type. The "detective" contains the logic for how to extract dependencies based on the module syntax format; i.e., the way dependencies are declared in commonjs is different than in AMD (which has 4 ways of doing that, for example).
99
105
 
@@ -105,13 +111,13 @@ So after the appropriate resolver finds the file on the filesystem, filing-cabin
105
111
 
106
112
  At the end of traversing every file (in a depth-first fashion), we have a fully populated dependency tree. :dancers:
107
113
 
108
- ### FAQ
114
+ ## FAQ
109
115
 
110
- #### Why aren't some some dependencies being detected?
116
+ ### Why aren't some some dependencies being detected?
111
117
 
112
118
  If there are bugs in [precinct](https://github.com/dependents/node-precinct) or if the `requireConfig`/`webpackConfig`/`tsConfig` options are incomplete,
113
119
  some dependencies may not be resolved. The optional array passed to the `nonExistent` option will be populated with paths
114
120
  that could not be resolved. You can check this array to see where problems might exist.
115
121
 
116
- You can also use the `DEBUG=*` env variable along with the cli version to see debugging information explaining where resolution went wrong.
117
- Example: `DEBUG=* dependency-tree -w path/to/webpack.config.json path/to/a/file`
122
+ You can also use the `NODE_DEBUG=*` env variable along with the cli version to see debugging information explaining where resolution went wrong.
123
+ Example: `NODE_DEBUG=* dependency-tree -w path/to/webpack.config.json path/to/a/file`
package/bin/cli.js CHANGED
@@ -2,36 +2,39 @@
2
2
 
3
3
  'use strict';
4
4
 
5
- const dependencyTree = require('../');
6
5
  const program = require('commander');
6
+ const dependencyTree = require('../index.js');
7
+ const { name, description, version } = require('../package.json');
7
8
 
8
9
  program
9
- .version(require('../package.json').version)
10
+ .name(name)
11
+ .description(description)
12
+ .version(version)
10
13
  .usage('[options] <filename>')
11
14
  .option('-d, --directory <path>', 'location of files of supported filetypes')
12
15
  .option('-c, --require-config <path>', 'path to a requirejs config')
13
16
  .option('-w, --webpack-config <path>', 'path to a webpack config')
14
17
  .option('-t, --ts-config <path>', 'path to a typescript config')
15
18
  .option('--list-form', 'output the list form of the tree (one element per line)')
16
- .parse(process.argv);
17
-
18
- let tree;
19
+ .parse();
19
20
 
21
+ const cliOptions = program.opts();
20
22
  const options = {
21
23
  filename: program.args[0],
22
- root: program.directory,
23
- config: program.requireConfig,
24
- webpackConfig: program.webpackConfig,
25
- tsConfig: program.tsConfig
24
+ root: cliOptions.directory,
25
+ config: cliOptions.requireConfig,
26
+ webpackConfig: cliOptions.webpackConfig,
27
+ tsConfig: cliOptions.tsConfig
26
28
  };
27
29
 
28
- if (program.listForm) {
30
+ let tree;
31
+
32
+ if (cliOptions.listForm) {
29
33
  tree = dependencyTree.toList(options);
30
34
 
31
- tree.forEach(function(node) {
35
+ for (const node of tree) {
32
36
  console.log(node);
33
- });
34
-
37
+ }
35
38
  } else {
36
39
  tree = dependencyTree(options);
37
40
 
package/index.js CHANGED
@@ -1,11 +1,12 @@
1
1
  'use strict';
2
2
 
3
- const precinct = require('precinct');
4
- const path = require('path');
5
- const fs = require('fs');
3
+ const fs = require('node:fs');
4
+ const { debuglog } = require('node:util');
6
5
  const cabinet = require('filing-cabinet');
7
- const debug = require('debug')('tree');
8
- const Config = require('./lib/Config');
6
+ const precinct = require('precinct');
7
+ const Config = require('./lib/config.js');
8
+
9
+ const debug = debuglog('tree');
9
10
 
10
11
  /**
11
12
  * Recursively find all dependencies (avoiding circular) traversing the entire dependency tree
@@ -18,18 +19,18 @@ const Config = require('./lib/Config');
18
19
  * @param {String} [options.webpackConfig] - The path to a webpack config
19
20
  * @param {String} [options.nodeModulesConfig] - config for resolving entry file for node_modules
20
21
  * @param {Object} [options.visited] - Cache of visited, absolutely pathed files that should not be reprocessed.
21
- * Format is a filename -> tree as list lookup table
22
+ * Format is a filename -> tree as list lookup table
22
23
  * @param {Array} [options.nonExistent] - List of partials that do not exist
23
24
  * @param {Boolean} [options.isListForm=false]
24
25
  * @param {String|Object} [options.tsConfig] Path to a typescript config (or a preloaded one).
25
26
  * @param {Boolean} [options.noTypeDefinitions] For TypeScript imports, whether to resolve to `*.js` instead of `*.d.ts`.
26
27
  * @return {Object}
27
28
  */
28
- module.exports = function(options) {
29
+ module.exports = function(options = {}) {
29
30
  const config = new Config(options);
30
31
 
31
32
  if (!fs.existsSync(config.filename)) {
32
- debug('file ' + config.filename + ' does not exist');
33
+ debug(`file ${config.filename} does not exist`);
33
34
  return config.isListForm ? [] : {};
34
35
  }
35
36
 
@@ -42,11 +43,9 @@ module.exports = function(options) {
42
43
  let tree;
43
44
  if (config.isListForm) {
44
45
  debug('list form of results requested');
45
-
46
- tree = Array.from(results);
46
+ tree = [...results];
47
47
  } else {
48
48
  debug('object form of results requested');
49
-
50
49
  tree = {};
51
50
  tree[config.filename] = results;
52
51
  }
@@ -67,7 +66,7 @@ module.exports = function(options) {
67
66
  *
68
67
  * Params are those of module.exports
69
68
  */
70
- module.exports.toList = function(options) {
69
+ module.exports.toList = function(options = {}) {
71
70
  options.isListForm = true;
72
71
 
73
72
  return module.exports(options);
@@ -81,27 +80,23 @@ module.exports.toList = function(options) {
81
80
  * @param {Config} config
82
81
  * @return {Array}
83
82
  */
84
- module.exports._getDependencies = function(config) {
85
- let dependencies;
83
+ module.exports._getDependencies = function(config = {}) {
86
84
  const precinctOptions = config.detectiveConfig;
87
85
  precinctOptions.includeCore = false;
86
+ let dependencies;
88
87
 
89
88
  try {
90
89
  dependencies = precinct.paperwork(config.filename, precinctOptions);
91
-
92
- debug('extracted ' + dependencies.length + ' dependencies: ', dependencies);
93
-
94
- } catch (e) {
95
- debug('error getting dependencies: ' + e.message);
96
- debug(e.stack);
90
+ debug(`extracted ${dependencies.length} dependencies: `, dependencies);
91
+ } catch (error) {
92
+ debug(`error getting dependencies: ${error.message}`);
93
+ debug(error.stack);
97
94
  return [];
98
95
  }
99
96
 
100
97
  const resolvedDependencies = [];
101
98
 
102
- for (let i = 0, l = dependencies.length; i < l; i++) {
103
- const dep = dependencies[i];
104
-
99
+ for (const dep of dependencies) {
105
100
  const result = cabinet({
106
101
  partial: dep,
107
102
  filename: config.filename,
@@ -115,7 +110,7 @@ module.exports._getDependencies = function(config) {
115
110
  });
116
111
 
117
112
  if (!result) {
118
- debug('skipping an empty filepath resolution for partial: ' + dep);
113
+ debug(`skipping an empty filepath resolution for partial: ${dep}`);
119
114
  config.nonExistent.push(dep);
120
115
  continue;
121
116
  }
@@ -124,7 +119,7 @@ module.exports._getDependencies = function(config) {
124
119
 
125
120
  if (!exists) {
126
121
  config.nonExistent.push(dep);
127
- debug('skipping non-empty but non-existent resolution: ' + result + ' for partial: ' + dep);
122
+ debug(`skipping non-empty but non-existent resolution: ${result} for partial: ${dep}`);
128
123
  continue;
129
124
  }
130
125
 
@@ -138,13 +133,13 @@ module.exports._getDependencies = function(config) {
138
133
  * @param {Config} config
139
134
  * @return {Object|Set}
140
135
  */
141
- function traverse(config) {
142
- let subTree = config.isListForm ? new Set() : {};
136
+ function traverse(config = {}) {
137
+ const subTree = config.isListForm ? new Set() : {};
143
138
 
144
- debug('traversing ' + config.filename);
139
+ debug(`traversing ${config.filename}`);
145
140
 
146
141
  if (config.visited[config.filename]) {
147
- debug('already visited ' + config.filename);
142
+ debug(`already visited ${config.filename}`);
148
143
  return config.visited[config.filename];
149
144
  }
150
145
 
@@ -157,24 +152,22 @@ function traverse(config) {
157
152
 
158
153
  if (config.filter) {
159
154
  debug('using filter function to filter out dependencies');
160
- debug('unfiltered number of dependencies: ' + dependencies.length);
161
- dependencies = dependencies.filter(function(filePath) {
162
- return config.filter(filePath, config.filename);
163
- });
164
- debug('filtered number of dependencies: ' + dependencies.length);
155
+ debug(`unfiltered number of dependencies: ${dependencies.length}`);
156
+ // eslint-disable-next-line unicorn/no-array-method-this-argument, unicorn/no-array-callback-reference
157
+ dependencies = dependencies.filter(filePath => config.filter(filePath, config.filename));
158
+ debug(`filtered number of dependencies: ${dependencies.length}`);
165
159
  }
166
160
 
167
- for (let i = 0, l = dependencies.length; i < l; i++) {
168
- const d = dependencies[i];
161
+ for (const dep of dependencies) {
169
162
  const localConfig = config.clone();
170
- localConfig.filename = d;
163
+ localConfig.filename = dep;
171
164
 
172
165
  if (localConfig.isListForm) {
173
- for (let item of traverse(localConfig)) {
166
+ for (const item of traverse(localConfig)) {
174
167
  subTree.add(item);
175
168
  }
176
169
  } else {
177
- subTree[d] = traverse(localConfig);
170
+ subTree[dep] = traverse(localConfig);
178
171
  }
179
172
  }
180
173
 
package/package.json CHANGED
@@ -1,18 +1,26 @@
1
1
  {
2
2
  "name": "dependency-tree",
3
- "version": "8.1.2",
3
+ "version": "10.0.0",
4
4
  "description": "Get the dependency tree of a module",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
7
- "scripts": {
8
- "test": "jscs index.js test/test.js && ./node_modules/.bin/mocha --require esm test/test.js"
9
- },
7
+ "files": [
8
+ "bin/cli.js",
9
+ "index.js"
10
+ ],
10
11
  "bin": {
11
12
  "dependency-tree": "bin/cli.js"
12
13
  },
14
+ "scripts": {
15
+ "lint": "xo",
16
+ "fix": "xo --fix",
17
+ "mocha": "mocha",
18
+ "test": "npm run lint && npm run mocha",
19
+ "test:ci": "c8 npm run mocha"
20
+ },
13
21
  "repository": {
14
22
  "type": "git",
15
- "url": "git@github.com:mrjoelkemp/node-dependency-tree.git"
23
+ "url": "git+https://github.com/dependents/node-dependency-tree.git"
16
24
  },
17
25
  "keywords": [
18
26
  "dependency",
@@ -32,27 +40,72 @@
32
40
  "author": "Joel Kemp <joel@mrjoelkemp.com>",
33
41
  "license": "MIT",
34
42
  "bugs": {
35
- "url": "https://github.com/mrjoelkemp/node-dependency-tree/issues"
43
+ "url": "https://github.com/dependents/node-dependency-tree/issues"
36
44
  },
45
+ "homepage": "https://github.com/dependents/node-dependency-tree",
37
46
  "engines": {
38
- "node": "^10.13 || ^12 || >=14"
47
+ "node": ">=14"
39
48
  },
40
- "homepage": "https://github.com/mrjoelkemp/node-dependency-tree",
41
49
  "dependencies": {
42
- "commander": "^2.20.3",
43
- "debug": "^4.3.1",
44
- "filing-cabinet": "^3.0.1",
45
- "precinct": "^8.0.0",
46
- "typescript": "^3.9.7"
50
+ "commander": "^10.0.1",
51
+ "filing-cabinet": "^4.1.0",
52
+ "precinct": "^11.0.0",
53
+ "typescript": "^5.0.4"
47
54
  },
48
55
  "devDependencies": {
49
- "esm": "^3.2.25",
50
- "jscs": "^3.0.7",
51
- "jscs-preset-mrjoelkemp": "~2.0.0",
52
- "mocha": "^8.2.1",
53
- "mock-fs": "^4.13.0",
54
- "resolve": "^1.19.0",
55
- "rewire": "^5.0.0",
56
- "sinon": "^9.2.1"
56
+ "c8": "^7.13.0",
57
+ "debug": "^4.3.4",
58
+ "mocha": "^10.2.0",
59
+ "mock-fs": "^5.2.0",
60
+ "resolve": "^1.22.3",
61
+ "sinon": "^15.0.4",
62
+ "xo": "^0.54.2"
63
+ },
64
+ "xo": {
65
+ "space": true,
66
+ "ignores": [
67
+ "index.d.ts",
68
+ "test/fixtures/*"
69
+ ],
70
+ "rules": {
71
+ "arrow-body-style": "off",
72
+ "capitalized-comments": "off",
73
+ "comma-dangle": [
74
+ "error",
75
+ "never"
76
+ ],
77
+ "curly": [
78
+ "error",
79
+ "multi-line"
80
+ ],
81
+ "max-nested-callbacks": [
82
+ "error",
83
+ 5
84
+ ],
85
+ "operator-linebreak": [
86
+ "error",
87
+ "after"
88
+ ],
89
+ "object-curly-spacing": [
90
+ "error",
91
+ "always"
92
+ ],
93
+ "prefer-template": "error",
94
+ "space-before-function-paren": [
95
+ "error",
96
+ "never"
97
+ ],
98
+ "unicorn/prefer-module": "off",
99
+ "unicorn/prefer-top-level-await": "off",
100
+ "unicorn/prevent-abbreviations": "off"
101
+ },
102
+ "overrides": [
103
+ {
104
+ "files": "test/**",
105
+ "envs": [
106
+ "mocha"
107
+ ]
108
+ }
109
+ ]
57
110
  }
58
111
  }
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;
package/lib/Config.js DELETED
@@ -1,47 +0,0 @@
1
- 'use strict';
2
-
3
- const path = require('path');
4
- const debug = require('debug')('tree');
5
-
6
- class Config {
7
- constructor(options) {
8
- this.filename = options.filename;
9
- this.directory = options.directory || options.root;
10
- this.visited = options.visited || {};
11
- this.nonExistent = options.nonExistent || [];
12
- this.isListForm = options.isListForm;
13
- this.requireConfig = options.config || options.requireConfig;
14
- this.webpackConfig = options.webpackConfig;
15
- this.nodeModulesConfig = options.nodeModulesConfig;
16
- this.detectiveConfig = options.detective || options.detectiveConfig || {};
17
- this.tsConfig = options.tsConfig;
18
- this.noTypeDefinitions = options.noTypeDefinitions;
19
-
20
- this.filter = options.filter;
21
-
22
- if (!this.filename) { throw new Error('filename not given'); }
23
- if (!this.directory) { throw new Error('directory not given'); }
24
- if (this.filter && typeof this.filter !== 'function') { throw new Error('filter must be a function'); }
25
-
26
- if ('string' === typeof this.tsConfig) {
27
- debug('preparsing the ts config into an object for performance');
28
- const ts = require('typescript');
29
- const tsParsedConfig = ts.readJsonConfigFile(this.tsConfig, ts.sys.readFile);
30
- const obj = ts.parseJsonSourceFileConfigFileContent(tsParsedConfig, ts.sys, path.dirname(this.tsConfig));
31
- this.tsConfig = obj.raw;
32
- }
33
-
34
- debug('given filename: ' + this.filename);
35
-
36
- this.filename = path.resolve(process.cwd(), this.filename);
37
-
38
- debug('resolved filename: ' + this.filename);
39
- debug('visited: ', this.visited);
40
- }
41
-
42
- clone () {
43
- return new Config(this);
44
- }
45
- }
46
-
47
- module.exports = Config;