dependency-cruiser 16.9.0 → 16.10.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/package.json +6 -6
- package/src/cache/cache.mjs +1 -1
- package/src/cache/find-content-changes.mjs +4 -4
- package/src/cache/metadata-strategy.mjs +3 -3
- package/src/cli/init-config/build-config.mjs +34 -0
- package/src/cli/init-config/config-template.mjs +12 -14
- package/src/cli/init-config/environment-helpers.mjs +24 -0
- package/src/cli/init-config/get-user-input.mjs +7 -0
- package/src/cli/init-config/index.mjs +2 -0
- package/src/enrich/enrich-modules.mjs +7 -7
- package/src/enrich/index.mjs +4 -1
- package/src/enrich/soften-known-violations.mjs +1 -1
- package/src/extract/helpers.mjs +38 -2
- package/src/extract/index.mjs +2 -2
- package/src/extract/resolve/is-built-in.mjs +22 -20
- package/src/main/cruise.mjs +10 -10
- package/src/meta.cjs +1 -1
- package/src/report/dot/index.mjs +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dependency-cruiser",
|
|
3
|
-
"version": "16.
|
|
3
|
+
"version": "16.10.0",
|
|
4
4
|
"description": "Validate and visualize dependencies. With your rules. JavaScript, TypeScript, CoffeeScript. ES6, CommonJS, AMD.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"static analysis",
|
|
@@ -145,9 +145,9 @@
|
|
|
145
145
|
"acorn-loose": "^8.4.0",
|
|
146
146
|
"acorn-walk": "^8.3.4",
|
|
147
147
|
"ajv": "^8.17.1",
|
|
148
|
-
"commander": "^13.
|
|
149
|
-
"enhanced-resolve": "^5.18.
|
|
150
|
-
"ignore": "^7.0.
|
|
148
|
+
"commander": "^13.1.0",
|
|
149
|
+
"enhanced-resolve": "^5.18.1",
|
|
150
|
+
"ignore": "^7.0.3",
|
|
151
151
|
"interpret": "^3.1.1",
|
|
152
152
|
"is-installed-globally": "^1.0.0",
|
|
153
153
|
"json5": "^2.2.3",
|
|
@@ -157,10 +157,10 @@
|
|
|
157
157
|
"prompts": "^2.4.2",
|
|
158
158
|
"rechoir": "^0.8.0",
|
|
159
159
|
"safe-regex": "^2.1.1",
|
|
160
|
-
"semver": "^7.
|
|
160
|
+
"semver": "^7.7.1",
|
|
161
161
|
"teamcity-service-messages": "^0.1.14",
|
|
162
162
|
"tsconfig-paths-webpack-plugin": "^4.2.0",
|
|
163
|
-
"watskeburt": "^4.2.
|
|
163
|
+
"watskeburt": "^4.2.3"
|
|
164
164
|
},
|
|
165
165
|
"overrides": {
|
|
166
166
|
"cross-spawn": ">=6.0.6"
|
package/src/cache/cache.mjs
CHANGED
|
@@ -87,7 +87,7 @@ export default class Cache {
|
|
|
87
87
|
},
|
|
88
88
|
));
|
|
89
89
|
this.#revisionData.cacheFormatVersion = CACHE_FORMAT_VERSION;
|
|
90
|
-
bus.debug("cache: -
|
|
90
|
+
bus.debug("cache: - compare");
|
|
91
91
|
return (
|
|
92
92
|
this.cacheFormatVersionCompatible(pCachedCruiseResult) &&
|
|
93
93
|
this.#cacheStrategy.revisionDataEqual(
|
|
@@ -82,7 +82,7 @@ export default function findContentChanges(
|
|
|
82
82
|
pCachedCruiseResult,
|
|
83
83
|
pOptions,
|
|
84
84
|
) {
|
|
85
|
-
bus.debug("cache: -
|
|
85
|
+
bus.debug("cache: - get revision data");
|
|
86
86
|
const lFileSet = new Set(
|
|
87
87
|
findAllFiles(pDirectory, {
|
|
88
88
|
baseDir: pOptions.baseDir,
|
|
@@ -91,12 +91,12 @@ export default function findContentChanges(
|
|
|
91
91
|
}).filter(hasInterestingExtension(pOptions.extensions)),
|
|
92
92
|
);
|
|
93
93
|
|
|
94
|
-
bus.debug("cache: -
|
|
94
|
+
bus.debug("cache: - get (cached - new)");
|
|
95
95
|
const lDiffCachedVsNew = pCachedCruiseResult.modules.map(
|
|
96
96
|
diffCachedModuleAgainstFileSet(lFileSet, pOptions.baseDir),
|
|
97
97
|
);
|
|
98
98
|
|
|
99
|
-
bus.debug("cache: -
|
|
99
|
+
bus.debug("cache: - get (new - cached)");
|
|
100
100
|
lDiffCachedVsNew.forEach(({ name }) => lFileSet.delete(name));
|
|
101
101
|
|
|
102
102
|
const lDiffNewVsCached = [];
|
|
@@ -108,6 +108,6 @@ export default function findContentChanges(
|
|
|
108
108
|
});
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
bus.debug("cache: -
|
|
111
|
+
bus.debug("cache: - return revision data");
|
|
112
112
|
return lDiffCachedVsNew.concat(lDiffNewVsCached);
|
|
113
113
|
}
|
|
@@ -42,9 +42,9 @@ export default class MetaDataStrategy {
|
|
|
42
42
|
...pOptions,
|
|
43
43
|
};
|
|
44
44
|
try {
|
|
45
|
-
bus.debug("cache: -
|
|
45
|
+
bus.debug("cache: - get sha");
|
|
46
46
|
const lSHA = await lOptions.shaRetrievalFn();
|
|
47
|
-
bus.debug("cache: -
|
|
47
|
+
bus.debug("cache: - get diff");
|
|
48
48
|
const lDiff = /** @type {IChange[]} */ (
|
|
49
49
|
await lOptions.diffListFn({ oldRevision: lSHA })
|
|
50
50
|
);
|
|
@@ -55,7 +55,7 @@ export default class MetaDataStrategy {
|
|
|
55
55
|
)
|
|
56
56
|
.filter(changeHasInterestingExtension(lOptions.extensions))
|
|
57
57
|
.filter(isInterestingChangeType(lOptions.interestingChangeTypes));
|
|
58
|
-
bus.debug("cache: - sha-
|
|
58
|
+
bus.debug("cache: - sha-sum diff");
|
|
59
59
|
return {
|
|
60
60
|
SHA1: lSHA,
|
|
61
61
|
changes: lChanges.map(lOptions.checksumFn),
|
|
@@ -160,6 +160,36 @@ function buildMainFieldsAttribute(pInitOptions) {
|
|
|
160
160
|
mainFields: ["main", "types", "typings"],`;
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
+
/**
|
|
164
|
+
* @param {IInitConfig} pInitOptions
|
|
165
|
+
* @returns {string}
|
|
166
|
+
*/
|
|
167
|
+
function buildBuiltInModulesAttribute(pInitOptions) {
|
|
168
|
+
if (pInitOptions.usesBun) {
|
|
169
|
+
return `
|
|
170
|
+
/* List of built-in modules to use on top of the ones node declares.
|
|
171
|
+
|
|
172
|
+
See https://github.com/sverweij/dependency-cruiser/blob/main/doc/options-reference.md#builtinmodules-influencing-what-to-consider-built-in--core-modules
|
|
173
|
+
for details
|
|
174
|
+
*/
|
|
175
|
+
builtInModules: {
|
|
176
|
+
add: [
|
|
177
|
+
"bun",
|
|
178
|
+
"bun:ffi",
|
|
179
|
+
"bun:jsc",
|
|
180
|
+
"bun:sqlite",
|
|
181
|
+
"bun:test",
|
|
182
|
+
"bun:wrap",
|
|
183
|
+
"detect-libc",
|
|
184
|
+
"undici",
|
|
185
|
+
"ws"
|
|
186
|
+
]
|
|
187
|
+
},
|
|
188
|
+
`;
|
|
189
|
+
}
|
|
190
|
+
return "";
|
|
191
|
+
}
|
|
192
|
+
|
|
163
193
|
/**
|
|
164
194
|
* Creates a .dependency-cruiser config with a set of basic validations
|
|
165
195
|
* to the current directory.
|
|
@@ -203,6 +233,10 @@ export default function buildConfig(pInitOptions) {
|
|
|
203
233
|
"{{babelConfigAttribute}}",
|
|
204
234
|
buildBabelConfigAttribute(pInitOptions),
|
|
205
235
|
)
|
|
236
|
+
.replace(
|
|
237
|
+
"{{builtInModulesAttribute}}",
|
|
238
|
+
buildBuiltInModulesAttribute(pInitOptions),
|
|
239
|
+
)
|
|
206
240
|
.replace("{{extensionsAttribute}}", buildExtensionsAttribute(pInitOptions))
|
|
207
241
|
.replace("{{mainFieldsAttribute}}", buildMainFieldsAttribute(pInitOptions))
|
|
208
242
|
.replace("{{version}}", pInitOptions.version)
|
|
@@ -314,8 +314,7 @@ module.exports = {
|
|
|
314
314
|
Only works when the 'exportsFields' array is non-empty.
|
|
315
315
|
*/
|
|
316
316
|
conditionNames: ["import", "require", "node", "default", "types"],
|
|
317
|
-
/*
|
|
318
|
-
The extensions, by default are the same as the ones dependency-cruiser
|
|
317
|
+
/* The extensions, by default are the same as the ones dependency-cruiser
|
|
319
318
|
can access (run \`npx depcruise --info\` to see which ones that are in
|
|
320
319
|
_your_ environment). If that list is larger than you need you can pass
|
|
321
320
|
the extensions you actually use (e.g. [".js", ".jsx"]). This can speed
|
|
@@ -324,26 +323,25 @@ module.exports = {
|
|
|
324
323
|
{{extensionsAttribute}}
|
|
325
324
|
/* What to consider a 'main' field in package.json */
|
|
326
325
|
{{mainFieldsAttribute}}
|
|
327
|
-
/*
|
|
328
|
-
|
|
326
|
+
/* A list of alias fields in package.jsons
|
|
327
|
+
|
|
329
328
|
See [this specification](https://github.com/defunctzombie/package-browser-field-spec) and
|
|
330
329
|
the webpack [resolve.alias](https://webpack.js.org/configuration/resolve/#resolvealiasfields)
|
|
331
|
-
documentation
|
|
330
|
+
documentation.
|
|
332
331
|
|
|
333
332
|
Defaults to an empty array (= don't use alias fields).
|
|
334
333
|
*/
|
|
335
334
|
// aliasFields: ["browser"],
|
|
336
335
|
},
|
|
337
336
|
|
|
338
|
-
/*
|
|
339
|
-
|
|
340
|
-
analysis strictly necessary for checking the rule set only.
|
|
337
|
+
/* skipAnalysisNotInRules will make dependency-cruiser execute
|
|
338
|
+
analysis strictly necessary for checking the rule set only.
|
|
341
339
|
|
|
342
|
-
|
|
343
|
-
|
|
340
|
+
See https://github.com/sverweij/dependency-cruiser/blob/main/doc/options-reference.md#skipanalysisnotinrules
|
|
341
|
+
for details
|
|
344
342
|
*/
|
|
345
343
|
skipAnalysisNotInRules: true,
|
|
346
|
-
|
|
344
|
+
{{builtInModulesAttribute}}
|
|
347
345
|
reporterOptions: {
|
|
348
346
|
dot: {
|
|
349
347
|
/* pattern of modules that can be consolidated in the detailed
|
|
@@ -369,9 +367,9 @@ module.exports = {
|
|
|
369
367
|
},
|
|
370
368
|
archi: {
|
|
371
369
|
/* pattern of modules that can be consolidated in the high level
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
370
|
+
graphical dependency graph. If you use the high level graphical
|
|
371
|
+
dependency graph reporter (\`archi\`) you probably want to tweak
|
|
372
|
+
this collapsePattern to your situation.
|
|
375
373
|
*/
|
|
376
374
|
collapsePattern: '^(?:packages|src|lib(s?)|app(s?)|bin|test(s?)|spec(s?))/[^/]+|node_modules/(?:@[^/]+/[^/]+|[^/]+)',
|
|
377
375
|
|
|
@@ -99,6 +99,30 @@ export function isLikelyMonoRepo(pFolderNames = getFolderNames(process.cwd())) {
|
|
|
99
99
|
return pFolderNames.includes("packages");
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
function getPackageManager(pManifest) {
|
|
103
|
+
let lReturnValue = "";
|
|
104
|
+
try {
|
|
105
|
+
const lManifest = pManifest ?? readManifest();
|
|
106
|
+
if (Object.hasOwn(lManifest, "packageManager")) {
|
|
107
|
+
lReturnValue = lManifest.packageManager;
|
|
108
|
+
}
|
|
109
|
+
} catch (pError) {
|
|
110
|
+
// silently ignore - we'll return the empty string anyway then
|
|
111
|
+
}
|
|
112
|
+
return lReturnValue;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* @param {Record<string,any>} pManifest
|
|
117
|
+
* @returns {boolean}
|
|
118
|
+
*/
|
|
119
|
+
export function likelyUsesBun(pManifest) {
|
|
120
|
+
const bunIsPackageManager = getPackageManager(pManifest).startsWith("bun");
|
|
121
|
+
return (
|
|
122
|
+
bunIsPackageManager || fileExists("bun.lockb") || fileExists("bunfig.toml")
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
102
126
|
export function hasTestsWithinSource(pTestLocations, pSourceLocations) {
|
|
103
127
|
return pTestLocations.every((pTestLocation) =>
|
|
104
128
|
pSourceLocations.includes(pTestLocation),
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
getBabelConfigCandidates,
|
|
17
17
|
hasWebpackConfigCandidates,
|
|
18
18
|
getWebpackConfigCandidates,
|
|
19
|
+
likelyUsesBun,
|
|
19
20
|
} from "./environment-helpers.mjs";
|
|
20
21
|
import { validateLocation } from "./validators.mjs";
|
|
21
22
|
import { isAvailable as tscIsAvailable } from "#extract/tsc/parse.mjs";
|
|
@@ -146,6 +147,12 @@ const QUESTIONS = [
|
|
|
146
147
|
message: "Full path to your webpack config:",
|
|
147
148
|
choices: getWebpackConfigCandidates().map(toPromptChoice),
|
|
148
149
|
},
|
|
150
|
+
{
|
|
151
|
+
name: "usesBun",
|
|
152
|
+
type: () => (likelyUsesBun() ? "confirm" : false),
|
|
153
|
+
message: "Looks like you're using bun. Detect its builtins?",
|
|
154
|
+
initial: true,
|
|
155
|
+
},
|
|
149
156
|
];
|
|
150
157
|
|
|
151
158
|
/**
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
getDefaultConfigFileName,
|
|
17
17
|
hasJSConfigCandidates,
|
|
18
18
|
getJSConfigCandidates,
|
|
19
|
+
likelyUsesBun,
|
|
19
20
|
isTypeModule,
|
|
20
21
|
} from "./environment-helpers.mjs";
|
|
21
22
|
import { writeRunScriptsToManifest } from "./write-run-scripts-to-manifest.mjs";
|
|
@@ -50,6 +51,7 @@ function getOneShotConfig(pOneShotConfigId) {
|
|
|
50
51
|
useBabelConfig: hasBabelConfigCandidates(),
|
|
51
52
|
babelConfig: getBabelConfigCandidates().shift(),
|
|
52
53
|
specifyResolutionExtensions: true,
|
|
54
|
+
usesBun: likelyUsesBun(),
|
|
53
55
|
};
|
|
54
56
|
/** @type {Map<OneShotConfigIDType, IPartialInitConfig>} */
|
|
55
57
|
const lOneShotConfigs = new Map([
|
|
@@ -17,7 +17,7 @@ import { bus } from "#utl/bus.mjs";
|
|
|
17
17
|
* @returns {IModule[]}
|
|
18
18
|
*/
|
|
19
19
|
export default function enrichModules(pModules, pOptions) {
|
|
20
|
-
bus.info("
|
|
20
|
+
bus.info("analyze: cycles");
|
|
21
21
|
const lIndexedModules = new IndexedModuleGraph(pModules);
|
|
22
22
|
let lModules = deriveCycles(pModules, lIndexedModules, {
|
|
23
23
|
pSourceAttribute: "source",
|
|
@@ -25,21 +25,21 @@ export default function enrichModules(pModules, pOptions) {
|
|
|
25
25
|
pSkipAnalysisNotInRules: pOptions.skipAnalysisNotInRules,
|
|
26
26
|
pRuleSet: pOptions.ruleSet,
|
|
27
27
|
});
|
|
28
|
-
bus.info("
|
|
28
|
+
bus.info("analyze: dependents");
|
|
29
29
|
lModules = addDependents(lModules, pOptions);
|
|
30
|
-
bus.info("
|
|
30
|
+
bus.info("analyze: orphans");
|
|
31
31
|
lModules = deriveOrphans(lModules, pOptions);
|
|
32
|
-
bus.info("
|
|
32
|
+
bus.info("analyze: reachables");
|
|
33
33
|
lModules = deriveReachable(lModules, pOptions.ruleSet);
|
|
34
|
-
bus.info("
|
|
34
|
+
bus.info("analyze: module metrics");
|
|
35
35
|
lModules = deriveModuleMetrics(lModules, pOptions);
|
|
36
|
-
bus.info("
|
|
36
|
+
bus.info("analyze: focus");
|
|
37
37
|
lModules = addFocus(lModules, pOptions.focus);
|
|
38
38
|
|
|
39
39
|
// when validate === false we might want to skip the addValidations.
|
|
40
40
|
// We don't at this time, however, as "valid" is a mandatory
|
|
41
41
|
// attribute (to simplify reporter logic)
|
|
42
|
-
bus.info("
|
|
42
|
+
bus.info("analyze: validations");
|
|
43
43
|
lModules = addValidations(lModules, pOptions.ruleSet, pOptions.validate);
|
|
44
44
|
|
|
45
45
|
lModules = softenKnownViolations(lModules, pOptions.knownViolations);
|
package/src/enrich/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import enrichModules from "./enrich-modules.mjs";
|
|
2
2
|
import aggregateToFolders from "./derive/folders/index.mjs";
|
|
3
3
|
import summarize from "./summarize/index.mjs";
|
|
4
|
+
import { bus } from "#utl/bus.mjs";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Enriches the passed modules with things like cycle detection, validations,
|
|
@@ -17,8 +18,10 @@ import summarize from "./summarize/index.mjs";
|
|
|
17
18
|
*/
|
|
18
19
|
export default function enrich(pModules, pOptions, pFileAndDirectoryArray) {
|
|
19
20
|
const lModules = enrichModules(pModules, pOptions);
|
|
21
|
+
bus.info("analyze: aggregate to folders");
|
|
20
22
|
const lFolders = aggregateToFolders(lModules, pOptions);
|
|
21
23
|
|
|
24
|
+
bus.info("analyze: summary");
|
|
22
25
|
const lReturnValue = {
|
|
23
26
|
modules: lModules,
|
|
24
27
|
...lFolders,
|
|
@@ -26,7 +29,7 @@ export default function enrich(pModules, pOptions, pFileAndDirectoryArray) {
|
|
|
26
29
|
lModules,
|
|
27
30
|
pOptions,
|
|
28
31
|
pFileAndDirectoryArray,
|
|
29
|
-
lFolders.folders
|
|
32
|
+
lFolders.folders,
|
|
30
33
|
),
|
|
31
34
|
};
|
|
32
35
|
|
|
@@ -117,7 +117,7 @@ export default function softenKnownViolations(
|
|
|
117
117
|
pSoftenedSeverity = "ignore",
|
|
118
118
|
) {
|
|
119
119
|
if (pKnownViolations) {
|
|
120
|
-
bus.info("
|
|
120
|
+
bus.info("analyze: compare to known errors");
|
|
121
121
|
return pModules.map((pModule) =>
|
|
122
122
|
softenKnownViolation(pModule, pKnownViolations, pSoftenedSeverity),
|
|
123
123
|
);
|
package/src/extract/helpers.mjs
CHANGED
|
@@ -28,6 +28,37 @@ export function detectPreCompilationNess(pTSDependencies, pJSDependencies) {
|
|
|
28
28
|
);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
const PROTOCOL_ONLY_BUILTINS = new Set([
|
|
32
|
+
// module.builtinModules.filter(m=>m.startsWith('node:'))
|
|
33
|
+
"node:sea",
|
|
34
|
+
"node:sqlite",
|
|
35
|
+
"node:test",
|
|
36
|
+
"node:test/reporters",
|
|
37
|
+
// module.builtinModules.filter(m=>m.startsWith('bun:'))
|
|
38
|
+
"bun:ffi",
|
|
39
|
+
"bun:jsc",
|
|
40
|
+
"bun:sqlite",
|
|
41
|
+
"bun:test",
|
|
42
|
+
"bun:wrap",
|
|
43
|
+
]);
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Given a module name returns the canonical module name.
|
|
47
|
+
* @param {string} pProtocol
|
|
48
|
+
* @param {string} pModuleName
|
|
49
|
+
* @returns {string}
|
|
50
|
+
*/
|
|
51
|
+
function getCanonicalModuleName(pModuleName, pProtocol) {
|
|
52
|
+
const lModuleWithProtocol = pProtocol + pModuleName;
|
|
53
|
+
const lIsJsIshProtocol = pProtocol === "node:" || pProtocol === "bun:";
|
|
54
|
+
const lIsProtocolOnlyModule = PROTOCOL_ONLY_BUILTINS.has(lModuleWithProtocol);
|
|
55
|
+
|
|
56
|
+
if (!lIsJsIshProtocol || lIsProtocolOnlyModule) {
|
|
57
|
+
return lModuleWithProtocol;
|
|
58
|
+
}
|
|
59
|
+
return pModuleName;
|
|
60
|
+
}
|
|
61
|
+
|
|
31
62
|
/**
|
|
32
63
|
* Given a module string returns in an object
|
|
33
64
|
* - the module name
|
|
@@ -42,15 +73,19 @@ export function detectPreCompilationNess(pTSDependencies, pJSDependencies) {
|
|
|
42
73
|
* @param {string} pString
|
|
43
74
|
* @returns {{module:string; protocol?:string; mimeType?:string}}
|
|
44
75
|
*/
|
|
76
|
+
// eslint-disable-next-line complexity
|
|
45
77
|
export function extractModuleAttributes(pString) {
|
|
46
78
|
let lReturnValue = { module: pString };
|
|
47
79
|
const lModuleAttributes = pString.match(
|
|
48
80
|
// eslint-disable-next-line security/detect-unsafe-regex
|
|
49
|
-
/^(?<protocol>node:|file:|data:)(?:(?<mimeType>[^,]+),)?(?<module>.+)$/,
|
|
81
|
+
/^(?<protocol>node:|file:|data:|bun:)(?:(?<mimeType>[^,]+),)?(?<module>.+)$/,
|
|
50
82
|
);
|
|
51
83
|
|
|
52
84
|
if (lModuleAttributes?.groups) {
|
|
53
|
-
lReturnValue.module =
|
|
85
|
+
lReturnValue.module = getCanonicalModuleName(
|
|
86
|
+
lModuleAttributes?.groups.module,
|
|
87
|
+
lModuleAttributes?.groups.protocol,
|
|
88
|
+
);
|
|
54
89
|
if (lModuleAttributes?.groups?.protocol) {
|
|
55
90
|
lReturnValue.protocol = lModuleAttributes.groups.protocol;
|
|
56
91
|
}
|
|
@@ -77,6 +112,7 @@ export function stripQueryParameters(pFilenameString) {
|
|
|
77
112
|
// deprecated, hence this funky RE replace. And accompanying unit test :-/
|
|
78
113
|
return pFilenameString.replace(/\?.+$/, "");
|
|
79
114
|
}
|
|
115
|
+
|
|
80
116
|
/**
|
|
81
117
|
* Returns true if the file name has a TypeScript compatible extension
|
|
82
118
|
* @param {string} pFileName
|
package/src/extract/index.mjs
CHANGED
|
@@ -75,13 +75,13 @@ function extractFileDirectoryArray(
|
|
|
75
75
|
) {
|
|
76
76
|
let lVisited = new Set();
|
|
77
77
|
|
|
78
|
-
bus.info("
|
|
78
|
+
bus.info("read files: gather initial sources");
|
|
79
79
|
const lInitialSources = gatherInitialSources(
|
|
80
80
|
pFileDirectoryArray,
|
|
81
81
|
pCruiseOptions,
|
|
82
82
|
);
|
|
83
83
|
|
|
84
|
-
bus.info("
|
|
84
|
+
bus.info("read files: visit dependencies");
|
|
85
85
|
return lInitialSources.reduce((pDependencies, pFilename) => {
|
|
86
86
|
if (!lVisited.has(pFilename)) {
|
|
87
87
|
lVisited.add(pFilename);
|
|
@@ -1,28 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
function getBuiltIns(pResolveOptions) {
|
|
4
|
-
// builtinModules does not expose all builtin modules for #reasons -
|
|
5
|
-
// see https://github.com/nodejs/node/issues/42785. In stead we could use
|
|
6
|
-
// isBuiltin, but that is not available in node 16.14, the lowest version
|
|
7
|
-
// of node dependency-cruiser currently supports. So we add the missing
|
|
8
|
-
// modules here.
|
|
9
|
-
let lReturnValue = builtinModules.concat(["test", "node:test"]);
|
|
10
|
-
|
|
11
|
-
if (pResolveOptions?.builtInModules?.override) {
|
|
12
|
-
lReturnValue = pResolveOptions?.builtInModules?.override;
|
|
13
|
-
}
|
|
14
|
-
if (pResolveOptions?.builtInModules?.add) {
|
|
15
|
-
lReturnValue = lReturnValue.concat(pResolveOptions.builtInModules.add);
|
|
16
|
-
}
|
|
17
|
-
return lReturnValue;
|
|
18
|
-
}
|
|
1
|
+
import { isBuiltin as moduleIsBuiltin } from "node:module";
|
|
19
2
|
|
|
20
3
|
/**
|
|
21
|
-
*
|
|
22
4
|
* @param {string} pModuleName - the unresolved module name
|
|
23
5
|
* @param {*} pResolveOptions
|
|
24
6
|
* @returns {boolean} - true if the module is a built-in module
|
|
25
7
|
*/
|
|
26
8
|
export function isBuiltin(pModuleName, pResolveOptions) {
|
|
27
|
-
|
|
9
|
+
if (pResolveOptions?.builtInModules?.override) {
|
|
10
|
+
return pResolveOptions.builtInModules.override.includes(pModuleName);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// bun, as it turns out, has some additional builtin modules. Even when running
|
|
14
|
+
// dependency-cruiser with bunx, bunx will use node by default. To cover that scenario
|
|
15
|
+
// there's three options
|
|
16
|
+
// - tell everyone to run bunx with the --bun option, so bun uses bun instead of node
|
|
17
|
+
// and hope everyone actually does that and it doesn't lead to a bunch of questions
|
|
18
|
+
// in the issues section. I don't expect that to happen anytime soon => other options
|
|
19
|
+
// - add the bun builtins here.
|
|
20
|
+
// this sounds attractive, but some of the modules ('undici', 'ws') are
|
|
21
|
+
// also npm packages. In nodejs context that will lead to a.o. false
|
|
22
|
+
// classifications.
|
|
23
|
+
// - add the bun builtins in dependency-cruiser.js
|
|
24
|
+
// Current approach. The --init command will try to detect whether it's
|
|
25
|
+
// in a bun repo and add the bun builtins to the config.
|
|
26
|
+
return (
|
|
27
|
+
moduleIsBuiltin(pModuleName) ||
|
|
28
|
+
(pResolveOptions?.builtInModules?.add ?? []).includes(pModuleName)
|
|
29
|
+
);
|
|
28
30
|
}
|
package/src/main/cruise.mjs
CHANGED
|
@@ -18,7 +18,7 @@ export default async function cruise(
|
|
|
18
18
|
pResolveOptions,
|
|
19
19
|
pTranspileOptions,
|
|
20
20
|
) {
|
|
21
|
-
bus.summary("
|
|
21
|
+
bus.summary("parse options", c(1));
|
|
22
22
|
const lCruiseOptionsValid = assertCruiseOptionsValid(pCruiseOptions);
|
|
23
23
|
/** @type {import("../../types/strict-options.js").IStrictCruiseOptions} */
|
|
24
24
|
let lCruiseOptions = normalizeCruiseOptions(
|
|
@@ -29,7 +29,7 @@ export default async function cruise(
|
|
|
29
29
|
|
|
30
30
|
if (lCruiseOptions.cache) {
|
|
31
31
|
bus.summary(
|
|
32
|
-
`cache:
|
|
32
|
+
`cache: check freshness with ${lCruiseOptions.cache.strategy}`,
|
|
33
33
|
c(2),
|
|
34
34
|
);
|
|
35
35
|
|
|
@@ -41,12 +41,12 @@ export default async function cruise(
|
|
|
41
41
|
const lCachedResults = await lCache.read(lCruiseOptions.cache.folder);
|
|
42
42
|
|
|
43
43
|
if (await lCache.canServeFromCache(lCruiseOptions, lCachedResults)) {
|
|
44
|
-
bus.summary("cache:
|
|
44
|
+
bus.summary("cache: report from cache", c(8));
|
|
45
45
|
return await reportWrap(lCachedResults, lCruiseOptions);
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
bus.summary("
|
|
49
|
+
bus.summary("import analytical modules", c(3));
|
|
50
50
|
const [
|
|
51
51
|
{ default: normalizeRuleSet },
|
|
52
52
|
{ default: assertRuleSetValid },
|
|
@@ -66,7 +66,7 @@ export default async function cruise(
|
|
|
66
66
|
]);
|
|
67
67
|
|
|
68
68
|
if (lCruiseOptions.ruleSet) {
|
|
69
|
-
bus.summary("
|
|
69
|
+
bus.summary("parse rule set", c(4));
|
|
70
70
|
lCruiseOptions.ruleSet = normalizeRuleSet(
|
|
71
71
|
assertRuleSetValid(lCruiseOptions.ruleSet),
|
|
72
72
|
);
|
|
@@ -76,14 +76,14 @@ export default async function cruise(
|
|
|
76
76
|
pFileAndDirectoryArray,
|
|
77
77
|
);
|
|
78
78
|
|
|
79
|
-
bus.summary("
|
|
79
|
+
bus.summary("determine how to resolve", c(5));
|
|
80
80
|
const lNormalizedResolveOptions = await normalizeResolveOptions(
|
|
81
81
|
pResolveOptions,
|
|
82
82
|
lCruiseOptions,
|
|
83
83
|
pTranspileOptions?.tsConfig,
|
|
84
84
|
);
|
|
85
85
|
|
|
86
|
-
bus.summary("
|
|
86
|
+
bus.summary("read files", c(6));
|
|
87
87
|
const lExtractionResult = extract(
|
|
88
88
|
lNormalizedFileAndDirectoryArray,
|
|
89
89
|
lCruiseOptions,
|
|
@@ -91,7 +91,7 @@ export default async function cruise(
|
|
|
91
91
|
pTranspileOptions,
|
|
92
92
|
);
|
|
93
93
|
|
|
94
|
-
bus.summary("
|
|
94
|
+
bus.summary("analyze", c(7));
|
|
95
95
|
const lCruiseResult = enrich(
|
|
96
96
|
lExtractionResult,
|
|
97
97
|
lCruiseOptions,
|
|
@@ -99,10 +99,10 @@ export default async function cruise(
|
|
|
99
99
|
);
|
|
100
100
|
|
|
101
101
|
if (lCruiseOptions.cache) {
|
|
102
|
-
bus.summary("cache:
|
|
102
|
+
bus.summary("cache: save", c(8));
|
|
103
103
|
await lCache.write(lCruiseOptions.cache.folder, lCruiseResult);
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
bus.summary("
|
|
106
|
+
bus.summary("report", c(9));
|
|
107
107
|
return await reportWrap(lCruiseResult, lCruiseOptions);
|
|
108
108
|
}
|
package/src/meta.cjs
CHANGED
package/src/report/dot/index.mjs
CHANGED
|
@@ -25,15 +25,15 @@ const GRANULARITY2REPORTER_OPTIONS = new Map([
|
|
|
25
25
|
]);
|
|
26
26
|
|
|
27
27
|
function buildGraphAttributes(pGraph) {
|
|
28
|
-
return pGraph ? ` ${attributizeObject(pGraph
|
|
28
|
+
return pGraph ? ` ${attributizeObject(pGraph)}` : "";
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
function buildNodeAttributes(pNode) {
|
|
32
|
-
return pNode ? ` node [${attributizeObject(pNode
|
|
32
|
+
return pNode ? ` node [${attributizeObject(pNode)}]` : "";
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
function buildEdgeAttributes(pEdge) {
|
|
36
|
-
return pEdge ? ` edge [${attributizeObject(pEdge
|
|
36
|
+
return pEdge ? ` edge [${attributizeObject(pEdge)}]` : "";
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
function buildGeneralAttributes(pTheme) {
|