Skip to content

Commit c314ce9

Browse files
authored
Merge branch 'main' into master
2 parents 0e8edde + 4591469 commit c314ce9

File tree

11 files changed

+4519
-8700
lines changed

11 files changed

+4519
-8700
lines changed

.github/workflows/ci.yml

+4-5
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ name: CI
33
on:
44
push:
55
branches:
6-
- "**"
7-
- "!dependabot/**"
6+
- "main"
87
pull_request:
98
workflow_dispatch:
109

@@ -23,16 +22,16 @@ jobs:
2322
fail-fast: false
2423
matrix:
2524
os: [ubuntu-latest, windows-latest]
26-
node: [14, 16, 18, 20]
25+
node: [18, 20, 22]
2726

2827
steps:
2928
- name: Clone repository
30-
uses: actions/checkout@v3
29+
uses: actions/checkout@v4
3130
with:
3231
persist-credentials: false
3332

3433
- name: Set up Node.js
35-
uses: actions/setup-node@v3
34+
uses: actions/setup-node@v4
3635
with:
3736
node-version: ${{ matrix.node }}
3837
cache: npm

.github/workflows/codeql.yml

+4-6
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,9 @@ on:
44
push:
55
branches:
66
- main
7-
- "!dependabot/**"
87
pull_request:
98
branches:
109
- main
11-
- "!dependabot/**"
1210
schedule:
1311
- cron: "0 0 * * 0"
1412
workflow_dispatch:
@@ -24,21 +22,21 @@ jobs:
2422

2523
steps:
2624
- name: Clone repository
27-
uses: actions/checkout@v3
25+
uses: actions/checkout@v4
2826
with:
2927
persist-credentials: false
3028

3129
- name: Initialize CodeQL
32-
uses: github/codeql-action/init@v2
30+
uses: github/codeql-action/init@v3
3331
with:
3432
config-file: ./.github/codeql/codeql-config.yml
3533
languages: "javascript"
3634
queries: +security-and-quality
3735

3836
- name: Autobuild
39-
uses: github/codeql-action/autobuild@v2
37+
uses: github/codeql-action/autobuild@v3
4038

4139
- name: Perform CodeQL Analysis
42-
uses: github/codeql-action/analyze@v2
40+
uses: github/codeql-action/analyze@v3
4341
with:
4442
category: "/language:javascript"

.github/workflows/lint.yml

+4-5
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@ name: Lint
33
on:
44
push:
55
branches:
6-
- "**"
7-
- "!dependabot/**"
6+
- "main"
87
pull_request:
98
workflow_dispatch:
109

1110
env:
1211
FORCE_COLOR: 2
13-
NODE: 18
12+
NODE: 20
1413

1514
permissions:
1615
contents: read
@@ -21,12 +20,12 @@ jobs:
2120

2221
steps:
2322
- name: Clone repository
24-
uses: actions/checkout@v3
23+
uses: actions/checkout@v4
2524
with:
2625
persist-credentials: false
2726

2827
- name: Set up Node.js
29-
uses: actions/setup-node@v3
28+
uses: actions/setup-node@v4
3029
with:
3130
node-version: ${{ env.NODE }}
3231
cache: npm

.npmrc

-1
This file was deleted.

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
npm install dependency-tree
1111
```
1212

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).
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).
1414
- For CommonJS modules, 3rd party dependencies (npm installed dependencies) are included in the tree by default
1515
- Dependency path resolutions are handled by [filing-cabinet](https://github.com/dependents/node-filing-cabinet)
1616
- Supports RequireJS and Webpack loaders
@@ -50,6 +50,7 @@ const list = dependencyTree.toList({
5050
* `requireConfig`: path to a requirejs config for AMD modules (allows for the result of aliased module paths)
5151
* `webpackConfig`: path to a webpack config for aliased modules
5252
* `tsConfig`: path to a typescript config (or a preloaded object representing the typescript config)
53+
* `tsConfigPath`: a (virtual) path to typescript config file when `tsConfig` option is given as an object, not a string. Needed to calculate [Path Mapping](https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping). If not given when `tsConfig` is an object, **Path Mapping** is ignored. This is not needed when `tsConfig` is given as a path string.
5354
* `nodeModulesConfig`: config for resolving entry file for node_modules
5455
* `visited`: object used for avoiding redundant subtree generations via memoization.
5556
* `nonExistent`: array used for storing the list of partial paths that do not exist

bin/cli.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
'use strict';
44

5-
const program = require('commander');
5+
const { program } = require('commander');
66
const dependencyTree = require('../index.js');
77
const { name, description, version } = require('../package.json');
88

index.js

+34-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
const fs = require('node:fs');
4+
const path = require('node:path');
45
const { debuglog } = require('node:util');
56
const cabinet = require('filing-cabinet');
67
const precinct = require('precinct');
@@ -94,30 +95,31 @@ module.exports._getDependencies = function(config = {}) {
9495

9596
const resolvedDependencies = [];
9697

97-
for (const dep of dependencies) {
98+
for (const dependency of dependencies) {
9899
const result = cabinet({
99-
partial: dep,
100+
partial: dependency,
100101
filename: config.filename,
101102
directory: config.directory,
102103
ast: precinct.ast,
103104
config: config.requireConfig,
104105
webpackConfig: config.webpackConfig,
105106
nodeModulesConfig: config.nodeModulesConfig,
106107
tsConfig: config.tsConfig,
108+
tsConfigPath: config.tsConfigPath,
107109
noTypeDefinitions: config.noTypeDefinitions
108110
});
109111

110112
if (!result) {
111-
debug(`skipping an empty filepath resolution for partial: ${dep}`);
112-
config.nonExistent.push(dep);
113+
debug(`skipping an empty filepath resolution for partial: ${dependency}`);
114+
config.nonExistent.push(dependency);
113115
continue;
114116
}
115117

116118
const exists = fs.existsSync(result);
117119

118120
if (!exists) {
119-
config.nonExistent.push(dep);
120-
debug(`skipping non-empty but non-existent resolution: ${result} for partial: ${dep}`);
121+
config.nonExistent.push(dependency);
122+
debug(`skipping non-empty but non-existent resolution: ${result} for partial: ${dependency}`);
121123
continue;
122124
}
123125

@@ -156,16 +158,17 @@ function traverse(config = {}) {
156158
debug(`filtered number of dependencies: ${dependencies.length}`);
157159
}
158160

159-
for (const dep of dependencies) {
161+
for (const dependency of dependencies) {
160162
const localConfig = config.clone();
161-
localConfig.filename = dep;
163+
localConfig.filename = dependency;
164+
localConfig.directory = getDirectory(localConfig);
162165

163166
if (localConfig.isListForm) {
164167
for (const item of traverse(localConfig)) {
165168
subTree.add(item);
166169
}
167170
} else {
168-
subTree[dep] = traverse(localConfig);
171+
subTree[dependency] = traverse(localConfig);
169172
}
170173
}
171174

@@ -190,3 +193,25 @@ function dedupeNonExistent(nonExistent) {
190193
i++;
191194
}
192195
}
196+
197+
// If the file is in a node module, use the root directory of the module
198+
function getDirectory(localConfig) {
199+
if (!localConfig.filename.includes('node_modules')) {
200+
return localConfig.directory;
201+
}
202+
203+
return getProjectPath(path.dirname(localConfig.filename)) || localConfig.directory;
204+
}
205+
206+
function getProjectPath(filename) {
207+
try {
208+
const nodeModuleParts = filename.split('node_modules');
209+
const packageSubPathPath = nodeModuleParts.pop().split(path.sep).filter(Boolean);
210+
const packageName = packageSubPathPath[0].startsWith('@') ? `${packageSubPathPath[0]}${path.sep}${packageSubPathPath[1]}` : packageSubPathPath[0];
211+
212+
return path.normalize([...nodeModuleParts, `${path.sep}${packageName}`].join('node_modules'));
213+
} catch {
214+
debug(`Could not determine the root directory of package file ${filename}. Using default`);
215+
return null;
216+
}
217+
}

lib/config.js

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ module.exports = class Config {
1818
this.nodeModulesConfig = options.nodeModulesConfig;
1919
this.detectiveConfig = options.detective || options.detectiveConfig || { includeCore: false };
2020
this.tsConfig = options.tsConfig;
21+
this.tsConfigPath = options.tsConfigPath;
2122
this.noTypeDefinitions = options.noTypeDefinitions;
2223
this.filter = options.filter;
2324

@@ -30,6 +31,7 @@ module.exports = class Config {
3031
const ts = require('typescript');
3132
const tsParsedConfig = ts.readJsonConfigFile(this.tsConfig, ts.sys.readFile);
3233
const obj = ts.parseJsonSourceFileConfigFileContent(tsParsedConfig, ts.sys, path.dirname(this.tsConfig));
34+
this.tsConfigPath ||= this.tsConfig;
3335
this.tsConfig = obj.raw;
3436
}
3537

0 commit comments

Comments
 (0)