Skip to content

Commit 104e0d1

Browse files
committed
Added depth limit
1 parent 715f1a0 commit 104e0d1

File tree

4 files changed

+59
-18
lines changed

4 files changed

+59
-18
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ Property | Type | Default | Description
228228
`requireConfig` | String | null | RequireJS config for resolving aliased modules
229229
`webpackConfig` | String | null | Webpack config for resolving aliased modules
230230
`tsConfig` | String\|Object | null | TypeScript config for resolving aliased modules - Either a path to a tsconfig file or an object containing the config
231+
`depth` | Number | null | Maximum dependency depth from source files to display
231232
`layout` | String | dot | Layout to use in the graph
232233
`rankdir` | String | LR | Sets the [direction](https://graphviz.gitlab.io/_pages/doc/info/attrs.html#d:rankdir) of the graph layout
233234
`fontName` | String | Arial | Font name to use in the graph

bin/cli.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ program
3131
.option('--require-config <file>', 'path to RequireJS config')
3232
.option('--webpack-config <file>', 'path to webpack config')
3333
.option('--ts-config <file>', 'path to typescript config')
34+
.option('--depth <integer>', 'maximum depth from source files to draw')
3435
.option('--include-npm', 'include shallow NPM modules', false)
3536
.option('--no-color', 'disable color in output and image', false)
3637
.option('--no-spinner', 'disable progress spinner', false)
@@ -118,6 +119,19 @@ if (config.tsConfig) {
118119
config.tsConfig = obj.raw;
119120
}
120121

122+
if ('depth' in program) {
123+
config.depth = program.depth;
124+
}
125+
126+
if ('depth' in config) {
127+
config.depth = Number(config.depth);
128+
129+
if (!Number.isInteger(config.depth) || config.depth < 0) {
130+
console.log('%s %s', chalk.red('✖'), 'Invalid depth');
131+
process.exit(1);
132+
}
133+
}
134+
121135
if (program.includeNpm) {
122136
config.includeNpm = program.includeNpm;
123137
}

lib/api.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const defaultConfig = {
1313
requireConfig: null,
1414
webpackConfig: null,
1515
tsConfig: null,
16+
depth: null,
1617
rankdir: 'LR',
1718
layout: 'dot',
1819
fontName: 'Arial',

lib/tree.js

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,6 @@ class Tree {
114114
const pathCache = {};
115115

116116
files.forEach((file) => {
117-
if (visited[file]) {
118-
return;
119-
}
120-
121117
Object.assign(depTree, dependencyTree({
122118
filename: file,
123119
directory: this.baseDir,
@@ -148,7 +144,7 @@ class Tree {
148144
}));
149145
});
150146

151-
let tree = this.convertTree(depTree, {}, pathCache, npmPaths);
147+
let tree = this.convertTree(visited, depTree, this.config.depth);
152148

153149
for (const npmKey in npmPaths) {
154150
const id = this.processPath(npmKey, pathCache);
@@ -171,27 +167,56 @@ class Tree {
171167
/**
172168
* Convert deep tree produced by dependency-tree to a
173169
* shallow (one level deep) tree used by madge.
174-
* @param {Object} depTree
170+
* @param {Object} modules
175171
* @param {Object} tree
176-
* @param {Object} pathCache
172+
* @param {number?} depthLimit
177173
* @return {Object}
178174
*/
179-
convertTree(depTree, tree, pathCache) {
180-
for (const key in depTree) {
181-
const id = this.processPath(key, pathCache);
182-
183-
if (!tree[id]) {
184-
tree[id] = [];
185-
186-
for (const dep in depTree[key]) {
187-
tree[id].push(this.processPath(dep, pathCache));
175+
convertTree(modules, tree, depthLimit) {
176+
const self = this;
177+
const depths = {};
178+
const deepDependencies = {};
179+
180+
function calculateDepths(tree, depth) {
181+
if (depth <= depthLimit) {
182+
for (const dependency in tree) {
183+
depths[dependency] = true;
184+
calculateDepths(modules[dependency], depth + 1);
188185
}
186+
}
187+
}
188+
189+
function getDeepDependencies(dependency) {
190+
if (deepDependencies[dependency] === null) {
191+
return [];
192+
}
189193

190-
this.convertTree(depTree[key], tree, pathCache);
194+
if (!(dependency in deepDependencies)) {
195+
deepDependencies[dependency] = null;
196+
deepDependencies[dependency] = [...new Set(Object.keys(modules[dependency]).flatMap(
197+
(dependency) => dependency in depths ? [dependency] : getDeepDependencies(dependency)
198+
))];
191199
}
200+
201+
return deepDependencies[dependency];
202+
}
203+
204+
const pathCache = {};
205+
const result = {};
206+
207+
if (!Number.isInteger(depthLimit)) {
208+
Object.entries(modules).forEach(([module, dependencies]) => {
209+
result[self.processPath(module, pathCache)] = Object.keys(dependencies).map((dependency) => self.processPath(dependency, pathCache));
210+
});
211+
} else {
212+
calculateDepths(tree, 0);
213+
214+
Object.keys(depths).forEach((module) => {
215+
result[self.processPath(module, pathCache)] = getDeepDependencies(module).map((dependency) => self.processPath(dependency, pathCache));
216+
});
192217
}
193218

194-
return tree;
219+
return result;
195220
}
196221

197222
/**

0 commit comments

Comments
 (0)