dependency-cruiser 17.3.2 → 17.3.3-beta-2
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/bin/depcruise-baseline.mjs +43 -43
- package/bin/depcruise-fmt.mjs +89 -89
- package/bin/dependency-cruise.mjs +171 -171
- package/configs/plugins/3d-reporter-plugin.mjs +36 -36
- package/configs/plugins/stats-reporter-plugin.mjs +51 -51
- package/configs/recommended-strict.cjs +5 -5
- package/configs/recommended-warn-only.cjs +5 -5
- package/configs/recommended.cjs +22 -22
- package/configs/rules/no-circular.cjs +10 -10
- package/configs/rules/no-deprecated-core.cjs +10 -10
- package/configs/rules/no-duplicate-dependency-types.cjs +17 -17
- package/configs/rules/no-non-package-json.cjs +11 -11
- package/configs/rules/no-orphans.cjs +18 -18
- package/configs/rules/not-to-deprecated.cjs +10 -10
- package/configs/rules/not-to-unresolvable.cjs +10 -10
- package/package.json +170 -170
- package/src/cache/cache.mjs +139 -139
- package/src/cache/content-strategy.mjs +88 -88
- package/src/cache/find-content-changes.mjs +58 -58
- package/src/cache/helpers.mjs +52 -52
- package/src/cache/metadata-strategy.mjs +83 -83
- package/src/cache/options-compatible.mjs +56 -109
- package/src/cli/assert-node-environment-suitable.mjs +7 -7
- package/src/cli/defaults.mjs +5 -5
- package/src/cli/format-meta-info.mjs +22 -22
- package/src/cli/format.mjs +28 -28
- package/src/cli/index.mjs +145 -145
- package/src/cli/init-config/build-config.mjs +94 -94
- package/src/cli/init-config/environment-helpers.mjs +77 -77
- package/src/cli/init-config/find-extensions.mjs +27 -27
- package/src/cli/init-config/get-user-input.mjs +151 -151
- package/src/cli/init-config/index.mjs +88 -88
- package/src/cli/init-config/normalize-init-options.mjs +47 -47
- package/src/cli/init-config/utl.mjs +4 -4
- package/src/cli/init-config/validators.mjs +10 -10
- package/src/cli/init-config/write-config.mjs +21 -21
- package/src/cli/init-config/write-run-scripts-to-manifest.mjs +103 -107
- package/src/cli/listeners/cli-feedback.mjs +49 -49
- package/src/cli/listeners/ndjson.mjs +66 -66
- package/src/cli/listeners/performance-log/format-helpers.mjs +63 -63
- package/src/cli/listeners/performance-log/handlers.mjs +56 -56
- package/src/cli/listeners/performance-log/index.mjs +37 -37
- package/src/cli/normalize-cli-options.mjs +182 -182
- package/src/cli/tools/wrap-stream-in-html.mjs +37 -37
- package/src/cli/utl/assert-file-existence.mjs +7 -7
- package/src/cli/utl/io.mjs +28 -31
- package/src/config-utl/extract-babel-config.mjs +69 -69
- package/src/config-utl/extract-depcruise-config/index.mjs +54 -54
- package/src/config-utl/extract-depcruise-config/merge-configs.mjs +63 -63
- package/src/config-utl/extract-depcruise-config/read-config.mjs +9 -9
- package/src/config-utl/extract-depcruise-options.mjs +9 -9
- package/src/config-utl/extract-known-violations.mjs +49 -49
- package/src/config-utl/extract-ts-config.mjs +46 -48
- package/src/config-utl/extract-webpack-resolve-config.mjs +88 -88
- package/src/config-utl/make-absolute.mjs +5 -5
- package/src/enrich/add-validations.mjs +13 -13
- package/src/enrich/derive/circular.mjs +49 -49
- package/src/enrich/derive/dependents.mjs +27 -27
- package/src/enrich/derive/folders/aggregate-to-folders.mjs +104 -104
- package/src/enrich/derive/folders/index.mjs +19 -19
- package/src/enrich/derive/folders/utl.mjs +18 -18
- package/src/enrich/derive/metrics/get-module-metrics.mjs +27 -27
- package/src/enrich/derive/metrics/index.mjs +8 -8
- package/src/enrich/derive/module-utl.mjs +18 -18
- package/src/enrich/derive/orphan/index.mjs +18 -18
- package/src/enrich/derive/orphan/is-orphan.mjs +9 -9
- package/src/enrich/derive/reachable.mjs +165 -168
- package/src/enrich/enrich-modules.mjs +25 -25
- package/src/enrich/index.mjs +15 -15
- package/src/enrich/soften-known-violations.mjs +90 -90
- package/src/enrich/summarize/add-rule-set-used.mjs +13 -13
- package/src/enrich/summarize/get-stats.mjs +17 -17
- package/src/enrich/summarize/index.mjs +18 -18
- package/src/enrich/summarize/is-same-violation.mjs +30 -30
- package/src/enrich/summarize/summarize-folders.mjs +35 -35
- package/src/enrich/summarize/summarize-modules.mjs +97 -97
- package/src/enrich/summarize/summarize-options.mjs +71 -71
- package/src/extract/acorn/estree-helpers.mjs +66 -66
- package/src/extract/acorn/extract-amd-deps.mjs +63 -64
- package/src/extract/acorn/extract-cjs-deps.mjs +83 -83
- package/src/extract/acorn/extract-es6-deps.mjs +54 -54
- package/src/extract/acorn/extract-stats.mjs +4 -4
- package/src/extract/acorn/extract.mjs +28 -28
- package/src/extract/acorn/parse.mjs +37 -37
- package/src/extract/clear-caches.mjs +7 -7
- package/src/extract/extract-dependencies.mjs +109 -109
- package/src/extract/extract-stats.mjs +21 -21
- package/src/extract/gather-initial-sources.mjs +64 -64
- package/src/extract/helpers.mjs +73 -71
- package/src/extract/index.mjs +120 -120
- package/src/extract/resolve/determine-dependency-types.mjs +166 -169
- package/src/extract/resolve/external-module-helpers.mjs +76 -76
- package/src/extract/resolve/get-manifest.mjs +79 -79
- package/src/extract/resolve/index.mjs +175 -164
- package/src/extract/resolve/is-built-in.mjs +22 -24
- package/src/extract/resolve/merge-manifests.mjs +43 -43
- package/src/extract/resolve/module-classifiers.mjs +229 -229
- package/src/extract/resolve/resolve-amd.mjs +44 -44
- package/src/extract/resolve/resolve-cjs.mjs +40 -40
- package/src/extract/resolve/resolve-helpers.mjs +20 -20
- package/src/extract/resolve/resolve.mjs +26 -26
- package/src/extract/swc/dependency-visitor.mjs +211 -211
- package/src/extract/swc/extract-swc-deps.mjs +4 -4
- package/src/extract/swc/extract.mjs +7 -7
- package/src/extract/swc/parse.mjs +12 -12
- package/src/extract/transpile/babel-wrap.mjs +9 -9
- package/src/extract/transpile/coffeescript-wrap.mjs +21 -21
- package/src/extract/transpile/index.mjs +47 -47
- package/src/extract/transpile/javascript-wrap.mjs +6 -6
- package/src/extract/transpile/livescript-wrap.mjs +5 -5
- package/src/extract/transpile/meta.mjs +80 -80
- package/src/extract/transpile/svelte-preprocess.mjs +73 -73
- package/src/extract/transpile/svelte-wrap.mjs +19 -19
- package/src/extract/transpile/try-import-available.mjs +26 -27
- package/src/extract/transpile/typescript-wrap.mjs +39 -39
- package/src/extract/transpile/vue-template-wrap.cjs +43 -43
- package/src/extract/tsc/extract-stats.mjs +4 -4
- package/src/extract/tsc/extract-typescript-deps.mjs +429 -398
- package/src/extract/tsc/extract.mjs +22 -22
- package/src/extract/tsc/parse.mjs +21 -21
- package/src/graph-utl/add-focus.mjs +35 -35
- package/src/graph-utl/compare.mjs +24 -24
- package/src/graph-utl/consolidate-module-dependencies.mjs +35 -35
- package/src/graph-utl/consolidate-modules.mjs +33 -33
- package/src/graph-utl/consolidate-to-folder.mjs +13 -13
- package/src/graph-utl/consolidate-to-pattern.mjs +34 -34
- package/src/graph-utl/filter-bank.mjs +74 -69
- package/src/graph-utl/indexed-module-graph.mjs +227 -225
- package/src/graph-utl/match-facade.mjs +3 -3
- package/src/graph-utl/rule-set.mjs +20 -20
- package/src/graph-utl/strip-self-transitions.mjs +6 -6
- package/src/main/cruise.mjs +81 -81
- package/src/main/files-and-dirs/normalize.mjs +7 -7
- package/src/main/format.mjs +11 -14
- package/src/main/helpers.mjs +25 -25
- package/src/main/index.mjs +8 -8
- package/src/main/options/assert-validity.mjs +100 -100
- package/src/main/options/defaults.mjs +11 -11
- package/src/main/options/normalize.mjs +158 -160
- package/src/main/report-wrap.mjs +37 -37
- package/src/main/resolve-options/normalize.mjs +127 -128
- package/src/main/rule-set/assert-validity.mjs +67 -73
- package/src/main/rule-set/normalize.mjs +81 -79
- package/src/meta.cjs +15 -16
- package/src/report/anon/anonymize-path-element.mjs +20 -34
- package/src/report/anon/anonymize-path.mjs +11 -11
- package/src/report/anon/index.mjs +119 -119
- package/src/report/anon/random-string.mjs +23 -23
- package/src/report/azure-devops.mjs +75 -99
- package/src/report/baseline.mjs +9 -9
- package/src/report/csv.mjs +13 -13
- package/src/report/d2.mjs +105 -105
- package/src/report/dot/default-theme.mjs +152 -152
- package/src/report/dot/index.mjs +146 -146
- package/src/report/dot/module-utl.mjs +72 -72
- package/src/report/dot/prepare-custom-level.mjs +20 -20
- package/src/report/dot/prepare-flat-level.mjs +11 -11
- package/src/report/dot/prepare-folder-level.mjs +12 -13
- package/src/report/dot/theming.mjs +73 -73
- package/src/report/dot-webpage/dot-module.mjs +36 -36
- package/src/report/dot-webpage/svg-in-html-snippets/script.cjs +208 -210
- package/src/report/dot-webpage/svg-in-html-snippets/style.css +51 -51
- package/src/report/dot-webpage/wrap-in-html.mjs +7 -7
- package/src/report/error-html/index.mjs +49 -49
- package/src/report/error-html/utl.mjs +99 -99
- package/src/report/error-long.mjs +1 -1
- package/src/report/error.mjs +93 -93
- package/src/report/html/index.mjs +48 -48
- package/src/report/identity.mjs +4 -4
- package/src/report/index.mjs +33 -33
- package/src/report/json.mjs +4 -4
- package/src/report/markdown.mjs +120 -120
- package/src/report/mermaid.mjs +111 -111
- package/src/report/metrics.mjs +185 -185
- package/src/report/null.mjs +4 -4
- package/src/report/plugins.mjs +41 -41
- package/src/report/teamcity.mjs +150 -150
- package/src/report/text.mjs +42 -42
- package/src/report/utl/dependency-to-incidence-transformer.mjs +32 -32
- package/src/report/utl/index.mjs +53 -53
- package/src/schema/configuration.validate.mjs +1 -0
- package/src/schema/cruise-result.validate.mjs +1 -0
- package/src/schema/utl.mjs +6 -0
- package/src/utl/array-util.mjs +25 -25
- package/src/utl/bus.mjs +12 -12
- package/src/utl/extract-root-module-name.cjs +8 -8
- package/src/utl/find-all-files.mjs +54 -54
- package/src/utl/get-extension.mjs +2 -2
- package/src/utl/object-util.mjs +21 -22
- package/src/utl/path-to-posix.mjs +5 -5
- package/src/utl/regex-util.mjs +20 -20
- package/src/utl/try-import.mjs +42 -41
- package/src/utl/try-require.cjs +23 -23
- package/src/utl/wrap-and-indent.mjs +33 -33
- package/src/validate/index.mjs +65 -65
- package/src/validate/match-dependency-rule.mjs +47 -47
- package/src/validate/match-folder-dependency-rule.mjs +27 -27
- package/src/validate/match-module-rule-helpers.mjs +76 -76
- package/src/validate/match-module-rule.mjs +12 -12
- package/src/validate/matchers.mjs +162 -162
- package/src/validate/rule-classifiers.mjs +9 -9
- package/src/validate/violates-required-rule.mjs +23 -23
- package/types/cache-options.d.mts +27 -27
- package/types/config-utl/extract-babel-config.d.mts +1 -1
- package/types/config-utl/extract-depcruise-config.d.mts +3 -3
- package/types/config-utl/extract-depcruise-options.d.mts +1 -1
- package/types/config-utl/extract-ts-config.d.mts +1 -1
- package/types/config-utl/extract-webpack-resolve-config.d.mts +3 -3
- package/types/configuration.d.mts +10 -10
- package/types/cruise-result.d.mts +414 -414
- package/types/dependency-cruiser.d.mts +52 -52
- package/types/filter-types.d.mts +45 -45
- package/types/options.d.mts +430 -430
- package/types/plugins/3d-reporter-plugin.d.mts +9 -9
- package/types/plugins/mermaid-reporter-plugin.d.mts +10 -10
- package/types/plugins/stats-reporter-plugin.d.mts +9 -9
- package/types/reporter-options.d.mts +196 -196
- package/types/resolve-options.d.mts +23 -23
- package/types/restrictions.d.mts +174 -174
- package/types/rule-set.d.mts +132 -132
- package/types/rule-summary.d.mts +14 -14
- package/types/shared-types.d.mts +89 -89
- package/types/strict-filter-types.d.mts +52 -52
- package/types/strict-options.d.mts +34 -34
- package/types/strict-restrictions.d.mts +25 -25
- package/types/strict-rule-set.d.mts +36 -36
- package/types/violations.d.mts +40 -40
- package/src/schema/README.md +0 -5
- package/src/schema/baseline-violations.schema.mjs +0 -1
- package/src/schema/configuration.schema.mjs +0 -1
- package/src/schema/cruise-result.schema.mjs +0 -1
- package/types/README.md +0 -1
|
@@ -2,48 +2,48 @@ import { uniq } from "#utl/array-util.mjs";
|
|
|
2
2
|
|
|
3
3
|
/* eslint-disable security/detect-object-injection */
|
|
4
4
|
function normalizeManifestKeys(pManifest) {
|
|
5
|
-
|
|
5
|
+
let lReturnValue = pManifest;
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
if (pManifest.bundleDependencies) {
|
|
8
|
+
pManifest.bundledDependencies = structuredClone(
|
|
9
|
+
pManifest.bundleDependencies,
|
|
10
|
+
);
|
|
11
|
+
Reflect.deleteProperty(pManifest, "bundleDependencies");
|
|
12
|
+
}
|
|
13
|
+
return lReturnValue;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
function mergeDependencyKey(pClosestDependencyKey, pFurtherDependencyKey) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
return {
|
|
18
|
+
...pFurtherDependencyKey,
|
|
19
|
+
...pClosestDependencyKey,
|
|
20
|
+
};
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
function mergeDependencyArray(pClosestDependencyKey, pFurtherDependencyKey) {
|
|
24
|
-
|
|
24
|
+
return uniq(pClosestDependencyKey.concat(pFurtherDependencyKey));
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
function isInterestingKey(pKey) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
return (
|
|
29
|
+
pKey.endsWith("ependencies") || pKey === "workspaces" || pKey === "imports"
|
|
30
|
+
);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
function getDependencyKeys(pPackage) {
|
|
34
|
-
|
|
34
|
+
return Object.keys(pPackage).filter(isInterestingKey);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
function getJointUniqueDependencyKeys(pClosestPackage, pFurtherPackage) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
return uniq(
|
|
39
|
+
getDependencyKeys(pClosestPackage).concat(
|
|
40
|
+
getDependencyKeys(pFurtherPackage),
|
|
41
|
+
),
|
|
42
|
+
);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
function isAnArrayKey(pKey) {
|
|
46
|
-
|
|
46
|
+
return pKey.startsWith("bundle") || pKey === "workspaces";
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
/**
|
|
@@ -63,24 +63,24 @@ function isAnArrayKey(pKey) {
|
|
|
63
63
|
* @return {any} the combined dependency-keys within those manifests
|
|
64
64
|
*/
|
|
65
65
|
export default function mergeManifests(pClosestManifest, pFurtherManifest) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
66
|
+
return getJointUniqueDependencyKeys(
|
|
67
|
+
normalizeManifestKeys(pClosestManifest),
|
|
68
|
+
normalizeManifestKeys(pFurtherManifest),
|
|
69
|
+
)
|
|
70
|
+
.map((pKey) => ({
|
|
71
|
+
key: pKey,
|
|
72
|
+
value: isAnArrayKey(pKey)
|
|
73
|
+
? mergeDependencyArray(
|
|
74
|
+
pClosestManifest?.[pKey] ?? [],
|
|
75
|
+
pFurtherManifest?.[pKey] ?? [],
|
|
76
|
+
)
|
|
77
|
+
: mergeDependencyKey(
|
|
78
|
+
pClosestManifest?.[pKey] ?? {},
|
|
79
|
+
pFurtherManifest?.[pKey] ?? {},
|
|
80
|
+
),
|
|
81
|
+
}))
|
|
82
|
+
.reduce((pJoinedObject, pJoinedKey) => {
|
|
83
|
+
pJoinedObject[pJoinedKey.key] = pJoinedKey.value;
|
|
84
|
+
return pJoinedObject;
|
|
85
|
+
}, {});
|
|
86
86
|
}
|
|
@@ -13,85 +13,85 @@ let gFollowableExtensionsCache = new Set();
|
|
|
13
13
|
let gFollowableExtensionsCacheInitialized = false;
|
|
14
14
|
|
|
15
15
|
export function isScoped(pModuleName) {
|
|
16
|
-
|
|
16
|
+
return pModuleName.startsWith("@");
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export function isRelativeModuleName(pModuleName) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
return (
|
|
21
|
+
pModuleName.startsWith("./") ||
|
|
22
|
+
pModuleName.startsWith("../") ||
|
|
23
|
+
pModuleName === "." ||
|
|
24
|
+
pModuleName === ".."
|
|
25
|
+
// note ".blah" and "..blah" are _not_ relative
|
|
26
|
+
);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export function isExternalModule(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
pResolvedModuleName,
|
|
31
|
+
pModuleFolderNames = ["node_modules"],
|
|
32
|
+
pBaseDirectory = ".",
|
|
33
33
|
) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
34
|
+
return (
|
|
35
|
+
Boolean(pResolvedModuleName) &&
|
|
36
|
+
pModuleFolderNames.some(
|
|
37
|
+
// pModules can contain relative paths, but also absolute ones.
|
|
38
|
+
// WebPack treats these differently:
|
|
39
|
+
// - absolute paths only match that exact path
|
|
40
|
+
// - relative paths get a node lookup treatment so "turtle" matches
|
|
41
|
+
// "turtle", "../turtle", "../../turtle"
|
|
42
|
+
// hence we'll have to test for them in different fashion as well.
|
|
43
|
+
// reference: https://webpack.js.org/configuration/resolve/#resolve-modules
|
|
44
|
+
(pModuleFolderName) => {
|
|
45
|
+
if (isAbsolute(pModuleFolderName)) {
|
|
46
|
+
return path_resolve(pBaseDirectory, pResolvedModuleName).startsWith(
|
|
47
|
+
pModuleFolderName,
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
return pResolvedModuleName.includes(pModuleFolderName);
|
|
51
|
+
},
|
|
52
|
+
)
|
|
53
|
+
);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
function determineFollowableExtensions(pResolveOptions) {
|
|
57
|
-
|
|
57
|
+
let lReturnValue = new Set(pResolveOptions.extensions);
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
59
|
+
// we could include things like pictures, movies, html, xml etc in
|
|
60
|
+
// lKnownUnfollowables as well. Ijavascript-like sources you don't
|
|
61
|
+
// import non-javascript stuff without mentioning the extension
|
|
62
|
+
// (`import 'styles.scss` is more clear than`import 'styles'` as you'd expect
|
|
63
|
+
// that to resolve to something javascript-like. Defensively added the
|
|
64
|
+
// stylesheetlanguages here explicitly nonetheless - they can contain import
|
|
65
|
+
// statements and the fallback javascript parser will happily parse them, which
|
|
66
|
+
// will result in false positives.
|
|
67
|
+
const lKnownUnfollowables = [
|
|
68
|
+
".json",
|
|
69
|
+
".node",
|
|
70
|
+
".css",
|
|
71
|
+
".sass",
|
|
72
|
+
".scss",
|
|
73
|
+
".stylus",
|
|
74
|
+
".less",
|
|
75
|
+
];
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
for (const lUnfollowable of lKnownUnfollowables) {
|
|
78
|
+
lReturnValue.delete(lUnfollowable);
|
|
79
|
+
}
|
|
80
|
+
return lReturnValue;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
function getFollowableExtensions(pResolveOptions) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
84
|
+
if (!gFollowableExtensionsCacheInitialized || pResolveOptions.bustTheCache) {
|
|
85
|
+
gFollowableExtensionsCache = determineFollowableExtensions(pResolveOptions);
|
|
86
|
+
gFollowableExtensionsCacheInitialized = true;
|
|
87
|
+
}
|
|
88
|
+
return gFollowableExtensionsCache;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
export function isFollowable(pResolvedFilename, pResolveOptions) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
92
|
+
return getFollowableExtensions(pResolveOptions).has(
|
|
93
|
+
getExtension(pResolvedFilename),
|
|
94
|
+
);
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
/**
|
|
@@ -100,20 +100,20 @@ export function isFollowable(pResolvedFilename, pResolveOptions) {
|
|
|
100
100
|
* @returns {boolean}
|
|
101
101
|
*/
|
|
102
102
|
function isSubpathImport(pModuleName, pManifest) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
103
|
+
return (
|
|
104
|
+
pModuleName.startsWith("#") &&
|
|
105
|
+
Object.keys(pManifest?.imports ?? {}).some((pImportLHS) => {
|
|
106
|
+
// Although they might look as such, the LHS of an import statement
|
|
107
|
+
// (a 'subpath pattern') is not a glob. The * functions as string
|
|
108
|
+
// replacement only.
|
|
109
|
+
// Quoting https://nodejs.org/api/packages.html#subpath-imports :
|
|
110
|
+
// > "* maps expose nested subpaths as it is a string replacement syntax only"
|
|
111
|
+
const lMatchREasString = pImportLHS.replace(/\*/g, ".+");
|
|
112
|
+
// eslint-disable-next-line security/detect-non-literal-regexp
|
|
113
|
+
const lMatchRE = new RegExp(`^${lMatchREasString}$`);
|
|
114
|
+
return lMatchRE.test(pModuleName);
|
|
115
|
+
})
|
|
116
|
+
);
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
/**
|
|
@@ -122,19 +122,19 @@ function isSubpathImport(pModuleName, pManifest) {
|
|
|
122
122
|
* @returns {boolean}
|
|
123
123
|
*/
|
|
124
124
|
function isWebPackAliased(pModuleName, pAliasObject) {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
125
|
+
return Object.keys(pAliasObject || {}).some((pAliasLHS) =>
|
|
126
|
+
pModuleName.startsWith(pAliasLHS),
|
|
127
|
+
);
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
function getWorkspacesArray(pManifestWorkspacesField) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
131
|
+
if (Array.isArray(pManifestWorkspacesField)) {
|
|
132
|
+
return pManifestWorkspacesField;
|
|
133
|
+
}
|
|
134
|
+
if (pManifestWorkspacesField?.packages) {
|
|
135
|
+
return pManifestWorkspacesField.packages;
|
|
136
|
+
}
|
|
137
|
+
return [];
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
/**
|
|
@@ -145,68 +145,68 @@ function getWorkspacesArray(pManifestWorkspacesField) {
|
|
|
145
145
|
*/
|
|
146
146
|
// eslint-disable-next-line max-lines-per-function
|
|
147
147
|
function isWorkspaceAliased(pModuleName, pResolvedModuleName, pManifest) {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
148
|
+
// reference: https://docs.npmjs.com/cli/v10/using-npm/workspaces
|
|
149
|
+
// for yarn the workspaces field might be either an array or
|
|
150
|
+
// an object. To prevent the code from borking we check whether it's an array
|
|
151
|
+
// see https://github.com/sverweij/dependency-cruiser/issues/919
|
|
152
|
+
const lWorkspaces = getWorkspacesArray(pManifest?.workspaces);
|
|
153
|
+
if (lWorkspaces.length > 0) {
|
|
154
|
+
// workspaces are an array of globs that match the (sub) workspace
|
|
155
|
+
// folder itself only.
|
|
156
|
+
//
|
|
157
|
+
// workspaces: [
|
|
158
|
+
// "packages/*", -> matches packages/a, packages/b, packages/c, ...
|
|
159
|
+
// "libs/x", -> matches libs/x
|
|
160
|
+
// "libs/y", -> matches libs/y
|
|
161
|
+
// "apps" -> matches apps
|
|
162
|
+
// ]
|
|
163
|
+
//
|
|
164
|
+
// By definition this will _never_ match resolved module names.
|
|
165
|
+
// E.g. in packages/a => packages/a/dist/main/index.js or
|
|
166
|
+
// in libs/x => libs/x/index.js
|
|
167
|
+
//
|
|
168
|
+
// This is why we chuck a `/**` at the end of each workspace glob, which
|
|
169
|
+
// transforms it into a 'starts with' glob. And yeah, you can have a /
|
|
170
|
+
// at the end of a glob. And because double slashes are taken literally
|
|
171
|
+
// we have a ternary operator to prevent those.
|
|
172
|
+
//
|
|
173
|
+
// oh and: ```picomatch.isMatch('asdf', 'asdf/**') === true``` so
|
|
174
|
+
// in case it's only 'asdf' that's in the resolved module name for some reason
|
|
175
|
+
// we're good as well.
|
|
176
|
+
//
|
|
177
|
+
// workspaces is supposed to be array of strings, where each string is
|
|
178
|
+
// a glob pattern. However, in the field there's occasions where it's
|
|
179
|
+
// not a string. We'll just ignore those for now, hence the presence of
|
|
180
|
+
// the `typeof pWorkspace === "string"` check.
|
|
181
|
+
const lModuleFriendlyWorkspaceGlobs = lWorkspaces.map((pWorkspace) =>
|
|
182
|
+
typeof pWorkspace === "string" && pWorkspace.endsWith("/")
|
|
183
|
+
? `${pWorkspace}**`
|
|
184
|
+
: `${pWorkspace}/**`,
|
|
185
|
+
);
|
|
186
|
+
if (picomatch.isMatch(pResolvedModuleName, lModuleFriendlyWorkspaceGlobs)) {
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
// it's possible to run node with --preserve-symlinks. The symlinked workspace folders
|
|
190
|
+
// then are not resolved to their realpath.
|
|
191
|
+
// So we need to check both the thing in node_modules _and_ the resolved
|
|
192
|
+
// thing. Annoyingly, the symlink in node_modules is the `name` attribute
|
|
193
|
+
// of the workspace, not the path of the workspace itself. So if it's
|
|
194
|
+
// in node_modules we need to check against the unresolved modulename.
|
|
195
|
+
//
|
|
196
|
+
// Other than the detection for when symlinks are resolved to their realpath
|
|
197
|
+
// (the if above), this is a 'best effort' detection only for now; there's
|
|
198
|
+
// guaranteed to be scenarios where this will fail. How often is the
|
|
199
|
+
// --preserve-symlinks flag used in practice, though?
|
|
200
|
+
const lModuleFriendlyWorkspaceGlobsWithNodeModules =
|
|
201
|
+
lModuleFriendlyWorkspaceGlobs.map(
|
|
202
|
+
(pWorkspace) => `(node_modules/)?${pWorkspace}`,
|
|
203
|
+
);
|
|
204
|
+
return picomatch.isMatch(
|
|
205
|
+
pModuleName,
|
|
206
|
+
lModuleFriendlyWorkspaceGlobsWithNodeModules,
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
return false;
|
|
210
210
|
}
|
|
211
211
|
|
|
212
212
|
/**
|
|
@@ -216,32 +216,32 @@ function isWorkspaceAliased(pModuleName, pResolvedModuleName, pManifest) {
|
|
|
216
216
|
* @returns {boolean}
|
|
217
217
|
*/
|
|
218
218
|
function matchesTSConfigPaths(pModuleName, pPaths) {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
219
|
+
// "paths patterns can contain a single * wildcard, which matches any string.
|
|
220
|
+
// The * token can then be used in the file path values to substitute the
|
|
221
|
+
// matched string."
|
|
222
|
+
// https://www.typescriptlang.org/docs/handbook/modules/reference.html#wildcard-substitutions
|
|
223
|
+
//
|
|
224
|
+
// So, just like with subpath imports, the LHS of a path pattern is not a glob
|
|
225
|
+
// and the '*' functions as a string replacement only.
|
|
226
|
+
//
|
|
227
|
+
// TODO: 'any string' - does this include the empty string as well? Checks seem
|
|
228
|
+
// to indicate it doesn't, so we use `.+` instead of `.*`
|
|
229
|
+
return Object.keys(pPaths).some((pPathLHS) => {
|
|
230
|
+
// eslint-disable-next-line security/detect-non-literal-regexp
|
|
231
|
+
const lMatchRE = new RegExp(`^${pPathLHS.replace(/\*/g, ".+")}$`);
|
|
232
|
+
return lMatchRE.test(pModuleName);
|
|
233
|
+
});
|
|
234
234
|
}
|
|
235
235
|
|
|
236
236
|
function stripExtension(pModulePath) {
|
|
237
|
-
|
|
238
|
-
|
|
237
|
+
const lExtension = getExtension(pModulePath);
|
|
238
|
+
return lExtension ? pModulePath.slice(0, -lExtension.length) : pModulePath;
|
|
239
239
|
}
|
|
240
240
|
|
|
241
241
|
function stripIndex(pModulePath) {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
242
|
+
return pModulePath.endsWith("/index")
|
|
243
|
+
? pModulePath.slice(0, -"/index".length)
|
|
244
|
+
: pModulePath;
|
|
245
245
|
}
|
|
246
246
|
|
|
247
247
|
/**
|
|
@@ -255,29 +255,29 @@ function stripIndex(pModulePath) {
|
|
|
255
255
|
* @param {string} pTSConfigBaseURL
|
|
256
256
|
*/
|
|
257
257
|
function matchesTSConfigBaseURL(
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
258
|
+
pModuleName,
|
|
259
|
+
pResolvedModuleName,
|
|
260
|
+
pTSConfigBaseURL,
|
|
261
261
|
) {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
262
|
+
// the pModuleName === pResolvedModuleName check is there to prevent
|
|
263
|
+
// false positives for core modules ('fs' resolved === 'fs') and modules that
|
|
264
|
+
// we couldn't resolve at all (e.g. 'this/does/not/exist' => 'this/does/not/exist')
|
|
265
|
+
//
|
|
266
|
+
// we could also check whether the moduleName is relative, but that's
|
|
267
|
+
// not efficient as that was already done before this function was called.
|
|
268
|
+
if (!pTSConfigBaseURL || pModuleName === pResolvedModuleName) {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
// "If baseUrl is set, TypeScript will resolve non-relative module names
|
|
272
|
+
// relative to the baseUrl."
|
|
273
|
+
// https://www.typescriptlang.org/docs/handbook/modules.html#base-url
|
|
274
|
+
const strippedModuleNameJoinedToBaseURL = stripIndex(
|
|
275
|
+
stripExtension(posix_join(pTSConfigBaseURL, pModuleName)),
|
|
276
|
+
);
|
|
277
|
+
const strippedResolvedModuleName = stripIndex(
|
|
278
|
+
stripExtension(pResolvedModuleName),
|
|
279
|
+
);
|
|
280
|
+
return strippedModuleNameJoinedToBaseURL.endsWith(strippedResolvedModuleName);
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
/**
|
|
@@ -290,45 +290,45 @@ function matchesTSConfigBaseURL(
|
|
|
290
290
|
*/
|
|
291
291
|
// eslint-disable-next-line max-params, complexity
|
|
292
292
|
export function getAliasTypes(
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
293
|
+
pModuleName,
|
|
294
|
+
pResolvedModuleName,
|
|
295
|
+
pResolveOptions,
|
|
296
|
+
pManifest,
|
|
297
|
+
pTranspileOptions,
|
|
298
298
|
) {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
299
|
+
if (isRelativeModuleName(pModuleName)) {
|
|
300
|
+
return [];
|
|
301
|
+
}
|
|
302
|
+
// the order of these ifs is deliberate. First stuff bolted on by bundlers & transpilers.
|
|
303
|
+
if (isWebPackAliased(pModuleName, pResolveOptions.alias)) {
|
|
304
|
+
return ["aliased", "aliased-webpack"];
|
|
305
|
+
}
|
|
306
|
+
if (
|
|
307
|
+
matchesTSConfigBaseURL(
|
|
308
|
+
pModuleName,
|
|
309
|
+
pResolvedModuleName,
|
|
310
|
+
pTranspileOptions?.tsConfig?.options?.baseUrl,
|
|
311
|
+
)
|
|
312
|
+
) {
|
|
313
|
+
return ["aliased", "aliased-tsconfig", "aliased-tsconfig-base-url"];
|
|
314
|
+
}
|
|
315
|
+
if (
|
|
316
|
+
matchesTSConfigPaths(
|
|
317
|
+
pModuleName,
|
|
318
|
+
pTranspileOptions?.tsConfig?.options?.paths ?? {},
|
|
319
|
+
)
|
|
320
|
+
) {
|
|
321
|
+
return ["aliased", "aliased-tsconfig", "aliased-tsconfig-paths"];
|
|
322
|
+
}
|
|
323
|
+
// The order of subpath imports and workspaces isn't _that_ important, as they
|
|
324
|
+
// can't be confused
|
|
325
|
+
// - subpath imports _must_ start with a #
|
|
326
|
+
// - workspaces (or, more precise: package names) are forbidden to even _contain_ a #
|
|
327
|
+
if (isSubpathImport(pModuleName, pManifest)) {
|
|
328
|
+
return ["aliased", "aliased-subpath-import"];
|
|
329
|
+
}
|
|
330
|
+
if (isWorkspaceAliased(pModuleName, pResolvedModuleName, pManifest)) {
|
|
331
|
+
return ["aliased", "aliased-workspace"];
|
|
332
|
+
}
|
|
333
|
+
return [];
|
|
334
334
|
}
|