dependency-cruiser 16.2.4 → 16.3.1
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 +3 -3
- package/src/cache/options-compatible.mjs +1 -0
- package/src/enrich/derive/folders/aggregate-to-folders.mjs +28 -10
- package/src/extract/{ast-extractors → acorn}/estree-helpers.mjs +3 -3
- package/src/extract/acorn/extract-stats.mjs +6 -0
- package/src/extract/acorn/extract.mjs +32 -0
- package/src/extract/clear-caches.mjs +6 -6
- package/src/extract/{get-dependencies.mjs → extract-dependencies.mjs} +37 -109
- package/src/extract/extract-stats.mjs +48 -0
- package/src/extract/helpers.mjs +20 -1
- package/src/extract/index.mjs +13 -3
- package/src/extract/resolve/merge-manifests.mjs +6 -8
- package/src/extract/{ast-extractors → swc}/extract-swc-deps.mjs +1 -1
- package/src/extract/swc/extract.mjs +20 -0
- package/src/extract/transpile/index.mjs +3 -3
- package/src/extract/tsc/extract-stats.mjs +6 -0
- package/src/extract/tsc/extract.mjs +29 -0
- package/src/graph-utl/consolidate-module-dependencies.mjs +3 -6
- package/src/graph-utl/rule-set.mjs +3 -2
- package/src/main/options/normalize.mjs +1 -4
- package/src/main/report-wrap.mjs +7 -2
- package/src/meta.cjs +1 -1
- package/src/report/dot/default-theme.mjs +4 -0
- package/src/report/dot-webpage/dot-module.mjs +2 -3
- package/src/report/metrics.mjs +226 -72
- package/src/report/utl/index.mjs +3 -0
- package/src/schema/configuration.schema.mjs +1 -1
- package/src/schema/cruise-result.schema.mjs +1 -1
- package/src/utl/array-util.mjs +4 -0
- package/types/cruise-result.d.mts +11 -0
- package/types/options.d.mts +10 -1
- package/types/shared-types.d.mts +15 -0
- /package/src/extract/{ast-extractors → acorn}/extract-amd-deps.mjs +0 -0
- /package/src/extract/{ast-extractors → acorn}/extract-cjs-deps.mjs +0 -0
- /package/src/extract/{ast-extractors → acorn}/extract-es6-deps.mjs +0 -0
- /package/src/extract/{parse/to-javascript-ast.mjs → acorn/parse.mjs} +0 -0
- /package/src/extract/{ast-extractors/swc-dependency-visitor.mjs → swc/dependency-visitor.mjs} +0 -0
- /package/src/extract/{parse/to-swc-ast.mjs → swc/parse.mjs} +0 -0
- /package/src/extract/{ast-extractors → tsc}/extract-typescript-deps.mjs +0 -0
- /package/src/extract/{parse/to-typescript-ast.mjs → tsc/parse.mjs} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dependency-cruiser",
|
|
3
|
-
"version": "16.
|
|
3
|
+
"version": "16.3.1",
|
|
4
4
|
"description": "Validate and visualize dependencies. With your rules. JavaScript, TypeScript, CoffeeScript. ES6, CommonJS, AMD.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"static analysis",
|
|
@@ -148,7 +148,7 @@
|
|
|
148
148
|
"json5": "2.2.3",
|
|
149
149
|
"lodash": "4.17.21",
|
|
150
150
|
"memoize": "10.0.0",
|
|
151
|
-
"picomatch": "4.0.
|
|
151
|
+
"picomatch": "4.0.2",
|
|
152
152
|
"prompts": "2.4.2",
|
|
153
153
|
"rechoir": "^0.8.0",
|
|
154
154
|
"safe-regex": "2.1.1",
|
|
@@ -156,7 +156,7 @@
|
|
|
156
156
|
"semver-try-require": "6.2.3",
|
|
157
157
|
"teamcity-service-messages": "0.1.14",
|
|
158
158
|
"tsconfig-paths-webpack-plugin": "4.1.0",
|
|
159
|
-
"watskeburt": "4.0.
|
|
159
|
+
"watskeburt": "4.0.2",
|
|
160
160
|
"wrap-ansi": "9.0.0"
|
|
161
161
|
},
|
|
162
162
|
"overrides": {
|
|
@@ -104,6 +104,7 @@ export function optionsAreCompatible(pOldOptions, pNewOptions) {
|
|
|
104
104
|
pOldOptions.tsPreCompilationDeps === pNewOptions.tsPreCompilationDeps &&
|
|
105
105
|
pOldOptions.preserveSymlinks === pNewOptions.preserveSymlinks &&
|
|
106
106
|
pOldOptions.combinedDependencies === pNewOptions.combinedDependencies &&
|
|
107
|
+
pOldOptions.experimentalStats === pNewOptions.experimentalStats &&
|
|
107
108
|
metricsIsCompatible(pOldOptions.metrics, pNewOptions.metrics) &&
|
|
108
109
|
// includeOnly suffers from a backwards compatibility disease
|
|
109
110
|
includeOnlyIsCompatible(pOldOptions.includeOnly, pNewOptions.includeOnly) &&
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
object2Array,
|
|
11
11
|
} from "./utl.mjs";
|
|
12
12
|
import IndexedModuleGraph from "#graph-utl/indexed-module-graph.mjs";
|
|
13
|
+
import { uniq } from "#utl/array-util.mjs";
|
|
13
14
|
|
|
14
15
|
function upsertCouplings(pAllDependents, pNewDependents) {
|
|
15
16
|
pNewDependents.forEach((pNewDependent) => {
|
|
@@ -20,6 +21,14 @@ function upsertCouplings(pAllDependents, pNewDependents) {
|
|
|
20
21
|
});
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
/**
|
|
25
|
+
*
|
|
26
|
+
* @param {any} pAllMetrics
|
|
27
|
+
* @param {import("../../../../types/cruise-result.d.mts").IModule} pModule
|
|
28
|
+
* @param {string} pDirname
|
|
29
|
+
* @returns {any}
|
|
30
|
+
*/
|
|
31
|
+
|
|
23
32
|
function upsertFolderAttributes(pAllMetrics, pModule, pDirname) {
|
|
24
33
|
pAllMetrics[pDirname] = pAllMetrics[pDirname] || {
|
|
25
34
|
dependencies: {},
|
|
@@ -38,6 +47,19 @@ function upsertFolderAttributes(pAllMetrics, pModule, pDirname) {
|
|
|
38
47
|
),
|
|
39
48
|
);
|
|
40
49
|
pAllMetrics[pDirname].moduleCount += 1;
|
|
50
|
+
|
|
51
|
+
if (pModule.experimentalStats) {
|
|
52
|
+
if (!Object.hasOwn(pAllMetrics[pDirname], "experimentalStats")) {
|
|
53
|
+
pAllMetrics[pDirname].experimentalStats = {
|
|
54
|
+
size: 0,
|
|
55
|
+
topLevelStatementCount: 0,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
pAllMetrics[pDirname].experimentalStats.size +=
|
|
59
|
+
pModule.experimentalStats.size;
|
|
60
|
+
pAllMetrics[pDirname].experimentalStats.topLevelStatementCount +=
|
|
61
|
+
pModule.experimentalStats.topLevelStatementCount;
|
|
62
|
+
}
|
|
41
63
|
return pAllMetrics;
|
|
42
64
|
}
|
|
43
65
|
|
|
@@ -53,13 +75,11 @@ function sumCounts(pAll, pCurrent) {
|
|
|
53
75
|
}
|
|
54
76
|
|
|
55
77
|
function getFolderLevelCouplings(pCouplingArray) {
|
|
56
|
-
return
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
: dirname(pCoupling.name),
|
|
62
|
-
),
|
|
78
|
+
return uniq(
|
|
79
|
+
pCouplingArray.map((pCoupling) =>
|
|
80
|
+
dirname(pCoupling.name) === "."
|
|
81
|
+
? pCoupling.name
|
|
82
|
+
: dirname(pCoupling.name),
|
|
63
83
|
),
|
|
64
84
|
).map((pCoupling) => ({ name: pCoupling }));
|
|
65
85
|
}
|
|
@@ -95,9 +115,7 @@ function deNormalizeInstability(pFolder, _, pAllFolders) {
|
|
|
95
115
|
}),
|
|
96
116
|
};
|
|
97
117
|
}
|
|
98
|
-
|
|
99
|
-
return [...new Set(pArray)];
|
|
100
|
-
}
|
|
118
|
+
|
|
101
119
|
function getSinks(pFolders) {
|
|
102
120
|
const lKnownFolders = new Set(pFolders.map(({ name }) => name));
|
|
103
121
|
const lAllFolders = uniq(
|
|
@@ -10,7 +10,7 @@ function firstArgumentIsAString(pArgumentsNode) {
|
|
|
10
10
|
);
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
function
|
|
13
|
+
function isPlaceholderLessTemplateLiteral(pArgument) {
|
|
14
14
|
return (
|
|
15
15
|
pArgument.type === "TemplateLiteral" &&
|
|
16
16
|
pArgument.quasis.length === 1 &&
|
|
@@ -22,7 +22,7 @@ function firstArgumentIsATemplateLiteral(pArgumentsNode) {
|
|
|
22
22
|
return (
|
|
23
23
|
Boolean(pArgumentsNode) &&
|
|
24
24
|
pArgumentsNode[0] &&
|
|
25
|
-
|
|
25
|
+
isPlaceholderLessTemplateLiteral(pArgumentsNode[0])
|
|
26
26
|
);
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -70,7 +70,7 @@ export default {
|
|
|
70
70
|
firstArgumentIsAString,
|
|
71
71
|
firstArgumentIsATemplateLiteral,
|
|
72
72
|
isStringLiteral,
|
|
73
|
-
isPlaceholderlessTemplateLiteral,
|
|
73
|
+
isPlaceholderlessTemplateLiteral: isPlaceholderLessTemplateLiteral,
|
|
74
74
|
isMemberCallExpression,
|
|
75
75
|
isCalleeIdentifier,
|
|
76
76
|
isRequireOfSomeSort,
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import extractES6Deps from "./extract-es6-deps.mjs";
|
|
3
|
+
import extractCommonJSDeps from "./extract-cjs-deps.mjs";
|
|
4
|
+
import extractAMDDeps from "./extract-amd-deps.mjs";
|
|
5
|
+
import parse from "./parse.mjs";
|
|
6
|
+
import extractStats from "./extract-stats.mjs";
|
|
7
|
+
|
|
8
|
+
export function extract(
|
|
9
|
+
{ baseDir, moduleSystems, exoticRequireStrings },
|
|
10
|
+
pFileName,
|
|
11
|
+
pTranspileOptions,
|
|
12
|
+
) {
|
|
13
|
+
let lDependencies = [];
|
|
14
|
+
const lAST = parse.getASTCached(join(baseDir, pFileName), pTranspileOptions);
|
|
15
|
+
|
|
16
|
+
if (moduleSystems.includes("cjs")) {
|
|
17
|
+
extractCommonJSDeps(lAST, lDependencies, "cjs", exoticRequireStrings);
|
|
18
|
+
}
|
|
19
|
+
if (moduleSystems.includes("es6")) {
|
|
20
|
+
extractES6Deps(lAST, lDependencies);
|
|
21
|
+
}
|
|
22
|
+
if (moduleSystems.includes("amd")) {
|
|
23
|
+
extractAMDDeps(lAST, lDependencies, exoticRequireStrings);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return lDependencies;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function getStats({ baseDir }, pFileName, pTranspileOptions) {
|
|
30
|
+
const lAST = parse.getASTCached(join(baseDir, pFileName), pTranspileOptions);
|
|
31
|
+
return extractStats(lAST);
|
|
32
|
+
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import tscParse from "./tsc/parse.mjs";
|
|
2
|
+
import acornParse from "./acorn/parse.mjs";
|
|
3
|
+
import swcParse from "./swc/parse.mjs";
|
|
4
4
|
import { clearCache as externalModuleHelpers_clearCache } from "./resolve/external-module-helpers.mjs";
|
|
5
5
|
import { clearCache as getManifest_clearCache } from "./resolve/get-manifest.mjs";
|
|
6
6
|
import { clearCache as resolveAMD_clearCache } from "./resolve/resolve-amd.mjs";
|
|
7
7
|
import { clearCache as resolve_clearCache } from "./resolve/resolve.mjs";
|
|
8
8
|
|
|
9
9
|
export default function clearCaches() {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
tscParse.clearCache();
|
|
11
|
+
acornParse.clearCache();
|
|
12
|
+
swcParse.clearCache();
|
|
13
13
|
externalModuleHelpers_clearCache();
|
|
14
14
|
getManifest_clearCache();
|
|
15
15
|
resolveAMD_clearCache();
|
|
@@ -1,117 +1,51 @@
|
|
|
1
1
|
import { join, extname, dirname } from "node:path";
|
|
2
2
|
import uniqBy from "lodash/uniqBy.js";
|
|
3
|
+
import { extract as acornExtract } from "./acorn/extract.mjs";
|
|
4
|
+
import {
|
|
5
|
+
extract as tscExtract,
|
|
6
|
+
shouldUse as tscShouldUse,
|
|
7
|
+
} from "./tsc/extract.mjs";
|
|
8
|
+
import {
|
|
9
|
+
extract as swcExtract,
|
|
10
|
+
shouldUse as swcShouldUse,
|
|
11
|
+
} from "./swc/extract.mjs";
|
|
3
12
|
import resolve from "./resolve/index.mjs";
|
|
4
|
-
import extractES6Deps from "./ast-extractors/extract-es6-deps.mjs";
|
|
5
|
-
import extractCommonJSDeps from "./ast-extractors/extract-cjs-deps.mjs";
|
|
6
|
-
import extractAMDDeps from "./ast-extractors/extract-amd-deps.mjs";
|
|
7
|
-
import extractTypeScriptDeps from "./ast-extractors/extract-typescript-deps.mjs";
|
|
8
|
-
import extractSwcDeps from "./ast-extractors/extract-swc-deps.mjs";
|
|
9
|
-
import toJavascriptAST from "./parse/to-javascript-ast.mjs";
|
|
10
|
-
import toTypescriptAST from "./parse/to-typescript-ast.mjs";
|
|
11
|
-
import toSwcAST from "./parse/to-swc-ast.mjs";
|
|
12
13
|
import {
|
|
13
14
|
detectPreCompilationNess,
|
|
14
15
|
extractModuleAttributes,
|
|
15
16
|
} from "./helpers.mjs";
|
|
16
17
|
import { intersects } from "#utl/array-util.mjs";
|
|
17
18
|
|
|
18
|
-
function extractFromSwcAST({ baseDir, exoticRequireStrings }, pFileName) {
|
|
19
|
-
return extractSwcDeps(
|
|
20
|
-
toSwcAST.getASTCached(join(baseDir, pFileName)),
|
|
21
|
-
exoticRequireStrings,
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function extractFromTypeScriptAST(
|
|
26
|
-
{ baseDir, exoticRequireStrings },
|
|
27
|
-
pFileName,
|
|
28
|
-
pTranspileOptions,
|
|
29
|
-
) {
|
|
30
|
-
return extractTypeScriptDeps(
|
|
31
|
-
toTypescriptAST.getASTCached(join(baseDir, pFileName), pTranspileOptions),
|
|
32
|
-
exoticRequireStrings,
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function isTypeScriptCompatible(pFileName) {
|
|
37
|
-
return [
|
|
38
|
-
".ts",
|
|
39
|
-
".tsx",
|
|
40
|
-
".mts",
|
|
41
|
-
".cts",
|
|
42
|
-
".js",
|
|
43
|
-
".mjs",
|
|
44
|
-
".cjs",
|
|
45
|
-
".vue",
|
|
46
|
-
].includes(extname(pFileName));
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function shouldUseTsc({ tsPreCompilationDeps, parser }, pFileName) {
|
|
50
|
-
return (
|
|
51
|
-
(tsPreCompilationDeps || parser === "tsc") &&
|
|
52
|
-
toTypescriptAST.isAvailable() &&
|
|
53
|
-
isTypeScriptCompatible(pFileName)
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function shouldUseSwc({ parser }, pFileName) {
|
|
58
|
-
return (
|
|
59
|
-
parser === "swc" &&
|
|
60
|
-
toSwcAST.isAvailable() &&
|
|
61
|
-
isTypeScriptCompatible(pFileName)
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function extractFromJavaScriptAST(
|
|
66
|
-
{ baseDir, moduleSystems, exoticRequireStrings },
|
|
67
|
-
pFileName,
|
|
68
|
-
pTranspileOptions,
|
|
69
|
-
) {
|
|
70
|
-
let lDependencies = [];
|
|
71
|
-
const lAST = toJavascriptAST.getASTCached(
|
|
72
|
-
join(baseDir, pFileName),
|
|
73
|
-
pTranspileOptions,
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
if (moduleSystems.includes("cjs")) {
|
|
77
|
-
extractCommonJSDeps(lAST, lDependencies, "cjs", exoticRequireStrings);
|
|
78
|
-
}
|
|
79
|
-
if (moduleSystems.includes("es6")) {
|
|
80
|
-
extractES6Deps(lAST, lDependencies);
|
|
81
|
-
}
|
|
82
|
-
if (moduleSystems.includes("amd")) {
|
|
83
|
-
extractAMDDeps(lAST, lDependencies, exoticRequireStrings);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return lDependencies;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
function extractWithSwc(pCruiseOptions, pFileName) {
|
|
90
|
-
return extractFromSwcAST(pCruiseOptions, pFileName).filter(
|
|
91
|
-
({ moduleSystem }) => pCruiseOptions.moduleSystems.includes(moduleSystem),
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
19
|
function extractWithTsc(pCruiseOptions, pFileName, pTranspileOptions) {
|
|
96
|
-
let lDependencies =
|
|
97
|
-
pCruiseOptions,
|
|
98
|
-
pFileName,
|
|
99
|
-
pTranspileOptions,
|
|
100
|
-
).filter(({ moduleSystem }) =>
|
|
101
|
-
pCruiseOptions.moduleSystems.includes(moduleSystem),
|
|
102
|
-
);
|
|
20
|
+
let lDependencies = tscExtract(pCruiseOptions, pFileName, pTranspileOptions);
|
|
103
21
|
|
|
104
22
|
if (pCruiseOptions.tsPreCompilationDeps === "specify") {
|
|
105
23
|
lDependencies = detectPreCompilationNess(
|
|
106
24
|
lDependencies,
|
|
107
|
-
|
|
25
|
+
acornExtract(pCruiseOptions, pFileName, pTranspileOptions),
|
|
108
26
|
);
|
|
109
27
|
}
|
|
110
28
|
return lDependencies;
|
|
111
29
|
}
|
|
112
30
|
|
|
113
31
|
/**
|
|
114
|
-
*
|
|
32
|
+
* @param {IStrictCruiseOptions} pCruiseOptions
|
|
33
|
+
* @param {string} pFileName
|
|
34
|
+
* @returns {(IStrictCruiseOptions, string, any) => import("../../types/cruise-result.mjs").IDependency[]}
|
|
35
|
+
*/
|
|
36
|
+
function determineExtractionFunction(pCruiseOptions, pFileName) {
|
|
37
|
+
let lExtractionFunction = acornExtract;
|
|
38
|
+
|
|
39
|
+
if (tscShouldUse(pCruiseOptions, pFileName)) {
|
|
40
|
+
lExtractionFunction = extractWithTsc;
|
|
41
|
+
} else if (swcShouldUse(pCruiseOptions, pFileName)) {
|
|
42
|
+
lExtractionFunction = swcExtract;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return lExtractionFunction;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
115
49
|
* @param {import('../../types/dependency-cruiser.js').IStrictCruiseOptions} pCruiseOptions
|
|
116
50
|
* @param {string} pFileName
|
|
117
51
|
* @param {any} pTranspileOptions
|
|
@@ -122,21 +56,15 @@ function extractDependencies(pCruiseOptions, pFileName, pTranspileOptions) {
|
|
|
122
56
|
let lDependencies = [];
|
|
123
57
|
|
|
124
58
|
if (!pCruiseOptions.extraExtensionsToScan.includes(extname(pFileName))) {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
lDependencies = extractFromJavaScriptAST(
|
|
135
|
-
pCruiseOptions,
|
|
136
|
-
pFileName,
|
|
137
|
-
pTranspileOptions,
|
|
138
|
-
);
|
|
139
|
-
}
|
|
59
|
+
const lExtractionFunction = determineExtractionFunction(
|
|
60
|
+
pCruiseOptions,
|
|
61
|
+
pFileName,
|
|
62
|
+
);
|
|
63
|
+
lDependencies = lExtractionFunction(
|
|
64
|
+
pCruiseOptions,
|
|
65
|
+
pFileName,
|
|
66
|
+
pTranspileOptions,
|
|
67
|
+
);
|
|
140
68
|
}
|
|
141
69
|
|
|
142
70
|
return lDependencies.map((pDependency) => ({
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getStats as tscStats,
|
|
3
|
+
shouldUse as tscShouldUse,
|
|
4
|
+
} from "./tsc/extract.mjs";
|
|
5
|
+
import { getStats as acornStats } from "./acorn/extract.mjs";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {IStrictCruiseOptions} pCruiseOptions
|
|
9
|
+
* @param {string} pFileName
|
|
10
|
+
* @returns {(IStrictCruiseOptions, string, any) => import("../../types/cruise-result.mjs").IDependency[]}
|
|
11
|
+
*/
|
|
12
|
+
function determineExtractionFunction(pCruiseOptions, pFileName) {
|
|
13
|
+
let lExtractionFunction = acornStats;
|
|
14
|
+
|
|
15
|
+
if (tscShouldUse(pCruiseOptions, pFileName)) {
|
|
16
|
+
lExtractionFunction = tscStats;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return lExtractionFunction;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Returns some stats for the module in pFileName
|
|
24
|
+
*
|
|
25
|
+
* @param {string} pFileName path to the file
|
|
26
|
+
* @param {import("../../types/dependency-cruiser.js").IStrictCruiseOptions} pCruiseOptions cruise options
|
|
27
|
+
* @param {import("../../types/dependency-cruiser.js").ITranspileOptions} pTranspileOptions an object with tsconfig ('typescript project') options
|
|
28
|
+
* ('flattened' so there's no need for file access on any
|
|
29
|
+
* 'extends' option in there)
|
|
30
|
+
* @return {import("../../types/dependency-cruiser.js").IDependency[]} an array of dependency objects (see above)
|
|
31
|
+
*/
|
|
32
|
+
export default function extractStats(
|
|
33
|
+
pFileName,
|
|
34
|
+
pCruiseOptions,
|
|
35
|
+
pTranspileOptions,
|
|
36
|
+
) {
|
|
37
|
+
try {
|
|
38
|
+
return determineExtractionFunction(pCruiseOptions, pFileName)(
|
|
39
|
+
pCruiseOptions,
|
|
40
|
+
pFileName,
|
|
41
|
+
pTranspileOptions,
|
|
42
|
+
);
|
|
43
|
+
} catch (pError) {
|
|
44
|
+
throw new Error(
|
|
45
|
+
`Extracting stats ran afoul of...\n\n ${pError.message}\n... in ${pFileName}\n\n`,
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
package/src/extract/helpers.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { extname } from "node:path";
|
|
2
|
+
|
|
1
3
|
export function dependenciesEqual(pLeftDependency) {
|
|
2
4
|
// As we're using this to compare (typescript) pre-compilation dependencies
|
|
3
5
|
// with post-compilation dependencies we do not consider the moduleSystem.
|
|
@@ -77,6 +79,23 @@ export function extractModuleAttributes(pString) {
|
|
|
77
79
|
*/
|
|
78
80
|
export function stripQueryParameters(pFilenameString) {
|
|
79
81
|
// url.parse(pFilenameString).pathname did this quite admirably, but it's
|
|
80
|
-
// deprecated, hence this
|
|
82
|
+
// deprecated, hence this funky RE replace. And accompanying unit test :-/
|
|
81
83
|
return pFilenameString.replace(/\?.+$/, "");
|
|
82
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Returns true if the file name has a TypeScript compatible extension
|
|
87
|
+
* @param {string} pFileName
|
|
88
|
+
* @returns {boolean}
|
|
89
|
+
*/
|
|
90
|
+
export function isTypeScriptCompatible(pFileName) {
|
|
91
|
+
return [
|
|
92
|
+
".ts",
|
|
93
|
+
".tsx",
|
|
94
|
+
".mts",
|
|
95
|
+
".cts",
|
|
96
|
+
".js",
|
|
97
|
+
".mjs",
|
|
98
|
+
".cjs",
|
|
99
|
+
".vue",
|
|
100
|
+
].includes(extname(pFileName));
|
|
101
|
+
}
|
package/src/extract/index.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import extractDependencies from "./extract-dependencies.mjs";
|
|
2
|
+
import extractStats from "./extract-stats.mjs";
|
|
2
3
|
import gatherInitialSources from "./gather-initial-sources.mjs";
|
|
3
4
|
import clearCaches from "./clear-caches.mjs";
|
|
4
5
|
import { bus } from "#utl/bus.mjs";
|
|
5
6
|
|
|
6
|
-
/* eslint max-params:0 */
|
|
7
|
+
/* eslint max-params:0 , max-lines-per-function:0*/
|
|
7
8
|
function extractRecursive(
|
|
8
9
|
pFileName,
|
|
9
10
|
pCruiseOptions,
|
|
@@ -15,7 +16,7 @@ function extractRecursive(
|
|
|
15
16
|
pVisited.add(pFileName);
|
|
16
17
|
const lDependencies =
|
|
17
18
|
pCruiseOptions.maxDepth <= 0 || pDepth < pCruiseOptions.maxDepth
|
|
18
|
-
?
|
|
19
|
+
? extractDependencies(
|
|
19
20
|
pFileName,
|
|
20
21
|
pCruiseOptions,
|
|
21
22
|
pResolveOptions,
|
|
@@ -46,6 +47,15 @@ function extractRecursive(
|
|
|
46
47
|
[
|
|
47
48
|
{
|
|
48
49
|
source: pFileName,
|
|
50
|
+
...(pCruiseOptions.experimentalStats
|
|
51
|
+
? {
|
|
52
|
+
experimentalStats: extractStats(
|
|
53
|
+
pFileName,
|
|
54
|
+
pCruiseOptions,
|
|
55
|
+
pTranspileOptions,
|
|
56
|
+
),
|
|
57
|
+
}
|
|
58
|
+
: {}),
|
|
49
59
|
dependencies: lDependencies,
|
|
50
60
|
},
|
|
51
61
|
],
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { uniq } from "#utl/array-util.mjs";
|
|
2
|
+
|
|
1
3
|
/* eslint-disable security/detect-object-injection */
|
|
2
4
|
function normalizeManifestKeys(pManifest) {
|
|
3
5
|
let lReturnValue = pManifest;
|
|
@@ -19,9 +21,7 @@ function mergeDependencyKey(pClosestDependencyKey, pFurtherDependencyKey) {
|
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
function mergeDependencyArray(pClosestDependencyKey, pFurtherDependencyKey) {
|
|
22
|
-
return
|
|
23
|
-
new Set(pClosestDependencyKey.concat(pFurtherDependencyKey)),
|
|
24
|
-
);
|
|
24
|
+
return uniq(pClosestDependencyKey.concat(pFurtherDependencyKey));
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
function isInterestingKey(pKey) {
|
|
@@ -35,11 +35,9 @@ function getDependencyKeys(pPackage) {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
function getJointUniqueDependencyKeys(pClosestPackage, pFurtherPackage) {
|
|
38
|
-
return
|
|
39
|
-
|
|
40
|
-
getDependencyKeys(
|
|
41
|
-
getDependencyKeys(pFurtherPackage),
|
|
42
|
-
),
|
|
38
|
+
return uniq(
|
|
39
|
+
getDependencyKeys(pClosestPackage).concat(
|
|
40
|
+
getDependencyKeys(pFurtherPackage),
|
|
43
41
|
),
|
|
44
42
|
);
|
|
45
43
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { join } from "node:path/posix";
|
|
2
|
+
import { isTypeScriptCompatible } from "../helpers.mjs";
|
|
3
|
+
import extractSwcDeps from "./extract-swc-deps.mjs";
|
|
4
|
+
import parse from "./parse.mjs";
|
|
5
|
+
|
|
6
|
+
export function shouldUse({ parser }, pFileName) {
|
|
7
|
+
return (
|
|
8
|
+
parser === "swc" && parse.isAvailable() && isTypeScriptCompatible(pFileName)
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function extract(
|
|
13
|
+
{ baseDir, exoticRequireStrings, moduleSystems },
|
|
14
|
+
pFileName,
|
|
15
|
+
) {
|
|
16
|
+
return extractSwcDeps(
|
|
17
|
+
parse.getASTCached(join(baseDir, pFileName)),
|
|
18
|
+
exoticRequireStrings,
|
|
19
|
+
).filter(({ moduleSystem }) => moduleSystems.includes(moduleSystem));
|
|
20
|
+
}
|
|
@@ -35,7 +35,7 @@ export const EXTENSION2WRAPPER = new Map([
|
|
|
35
35
|
[".cjsx", coffeeVanillaWrap],
|
|
36
36
|
]);
|
|
37
37
|
|
|
38
|
-
const
|
|
38
|
+
const BABEL_ABLE_EXTENSIONS = [
|
|
39
39
|
".js",
|
|
40
40
|
".cjs",
|
|
41
41
|
".mjs",
|
|
@@ -47,7 +47,7 @@ const BABELEABLE_EXTENSIONS = [
|
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
49
|
* returns the babel wrapper if there's a babelConfig in the transpiler
|
|
50
|
-
* options for
|
|
50
|
+
* options for babel- able extensions (javascript and typescript - currently
|
|
51
51
|
* not configurable)
|
|
52
52
|
*
|
|
53
53
|
* returns the wrapper module configured for the extension pExtension if
|
|
@@ -63,7 +63,7 @@ const BABELEABLE_EXTENSIONS = [
|
|
|
63
63
|
export function getWrapper(pExtension, pTranspilerOptions) {
|
|
64
64
|
if (
|
|
65
65
|
Object.keys(pTranspilerOptions?.babelConfig ?? {}).length > 0 &&
|
|
66
|
-
|
|
66
|
+
BABEL_ABLE_EXTENSIONS.includes(pExtension)
|
|
67
67
|
) {
|
|
68
68
|
return babelWrap;
|
|
69
69
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { isTypeScriptCompatible } from "../helpers.mjs";
|
|
3
|
+
import extractTypeScriptDeps from "./extract-typescript-deps.mjs";
|
|
4
|
+
import parse from "./parse.mjs";
|
|
5
|
+
import extractStats from "./extract-stats.mjs";
|
|
6
|
+
|
|
7
|
+
export function shouldUse({ tsPreCompilationDeps, parser }, pFileName) {
|
|
8
|
+
return (
|
|
9
|
+
(tsPreCompilationDeps || parser === "tsc") &&
|
|
10
|
+
parse.isAvailable() &&
|
|
11
|
+
isTypeScriptCompatible(pFileName)
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function extract(
|
|
16
|
+
{ baseDir, exoticRequireStrings, moduleSystems },
|
|
17
|
+
pFileName,
|
|
18
|
+
pTranspileOptions,
|
|
19
|
+
) {
|
|
20
|
+
return extractTypeScriptDeps(
|
|
21
|
+
parse.getASTCached(join(baseDir, pFileName), pTranspileOptions),
|
|
22
|
+
exoticRequireStrings,
|
|
23
|
+
).filter(({ moduleSystem }) => moduleSystems.includes(moduleSystem));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function getStats({ baseDir }, pFileName, pTranspileOptions) {
|
|
27
|
+
const lAST = parse.getASTCached(join(baseDir, pFileName), pTranspileOptions);
|
|
28
|
+
return extractStats(lAST);
|
|
29
|
+
}
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
import reject from "lodash/reject.js";
|
|
2
2
|
import compare from "./compare.mjs";
|
|
3
|
+
import { uniq } from "#utl/array-util.mjs";
|
|
3
4
|
|
|
4
5
|
function mergeDependency(pLeftDependency, pRightDependency) {
|
|
5
6
|
return {
|
|
6
7
|
...pLeftDependency,
|
|
7
8
|
...pRightDependency,
|
|
8
|
-
dependencyTypes:
|
|
9
|
-
|
|
10
|
-
pLeftDependency.dependencyTypes.concat(
|
|
11
|
-
pRightDependency.dependencyTypes,
|
|
12
|
-
),
|
|
13
|
-
),
|
|
9
|
+
dependencyTypes: uniq(
|
|
10
|
+
pLeftDependency.dependencyTypes.concat(pRightDependency.dependencyTypes),
|
|
14
11
|
),
|
|
15
12
|
rules: pLeftDependency.rules
|
|
16
13
|
.concat(pRightDependency?.rules ?? [])
|
|
@@ -10,9 +10,10 @@
|
|
|
10
10
|
* @return {import("../../types/rule-set").IForbiddenRuleType|undefined} - a rule (or 'undefined' if nothing found)
|
|
11
11
|
*/
|
|
12
12
|
export function findRuleByName(pRuleSet, pName) {
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
const lNamedRules = (pRuleSet?.forbidden ?? []).concat(
|
|
14
|
+
pRuleSet?.required ?? [],
|
|
15
15
|
);
|
|
16
|
+
return lNamedRules.find((pRule) => pRule.name === pName);
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
function ruleHasALicenseLikeAttribute(pRule) {
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
/* eslint-disable security/detect-object-injection */
|
|
2
2
|
import { normalizeREProperties } from "../helpers.mjs";
|
|
3
3
|
import defaults from "./defaults.mjs";
|
|
4
|
+
import { uniq } from "#utl/array-util.mjs";
|
|
4
5
|
|
|
5
6
|
const DEFAULT_CACHE_FOLDER = "node_modules/.cache/dependency-cruiser";
|
|
6
7
|
const DEFAULT_CACHE_STRATEGY = "metadata";
|
|
7
8
|
|
|
8
|
-
function uniq(pArray) {
|
|
9
|
-
return [...new Set(pArray)];
|
|
10
|
-
}
|
|
11
|
-
|
|
12
9
|
function normalizeFilterOption(pFilterOption) {
|
|
13
10
|
let lReturnValue = pFilterOption || {};
|
|
14
11
|
|