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
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import addFocus from "./add-focus.mjs";
|
|
2
2
|
import IndexedModuleGraph from "./indexed-module-graph.mjs";
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
moduleMatchesFilter,
|
|
5
|
+
dependencyMatchesFilter,
|
|
6
6
|
} from "./match-facade.mjs";
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -11,30 +11,30 @@ import {
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
function includeOnly(pModules, pIncludeFilter) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
14
|
+
return pIncludeFilter.path
|
|
15
|
+
? pModules
|
|
16
|
+
.filter((pModule) => moduleMatchesFilter(pModule, pIncludeFilter))
|
|
17
|
+
.map((pModule) => ({
|
|
18
|
+
...pModule,
|
|
19
|
+
dependencies: pModule.dependencies.filter((pDependency) =>
|
|
20
|
+
dependencyMatchesFilter(pDependency, pIncludeFilter),
|
|
21
|
+
),
|
|
22
|
+
}))
|
|
23
|
+
: pModules;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
function exclude(pModules, pExcludeFilter) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
27
|
+
return pExcludeFilter.path
|
|
28
|
+
? pModules
|
|
29
|
+
.filter((pModule) => !moduleMatchesFilter(pModule, pExcludeFilter))
|
|
30
|
+
.map((pModule) => ({
|
|
31
|
+
...pModule,
|
|
32
|
+
dependencies: pModule.dependencies.filter(
|
|
33
|
+
(pDependency) =>
|
|
34
|
+
!dependencyMatchesFilter(pDependency, pExcludeFilter),
|
|
35
|
+
),
|
|
36
|
+
}))
|
|
37
|
+
: pModules;
|
|
38
38
|
}
|
|
39
39
|
/**
|
|
40
40
|
*
|
|
@@ -43,60 +43,65 @@ function exclude(pModules, pExcludeFilter) {
|
|
|
43
43
|
* @returns {IModule[]}
|
|
44
44
|
*/
|
|
45
45
|
function filterReaches(pModules, pReachesFilter) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
// TODO: optimize - avoid re-indexing for each reaches filter
|
|
47
|
+
/** @type {Set<string>} */
|
|
48
|
+
const lModuleNamesToReach = new Set();
|
|
49
|
+
for (const lModule of pModules) {
|
|
50
|
+
if (moduleMatchesFilter(lModule, pReachesFilter)) {
|
|
51
|
+
lModuleNamesToReach.add(lModule.source);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
49
54
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
55
|
+
/** @type {Set<string>} */
|
|
56
|
+
const lReachingModules = new Set();
|
|
57
|
+
const lIndexedModules = new IndexedModuleGraph(pModules);
|
|
53
58
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
for (const lModuleToReach of lModuleNamesToReach) {
|
|
60
|
+
for (const lDependent of lIndexedModules.findTransitiveDependents(
|
|
61
|
+
lModuleToReach,
|
|
62
|
+
)) {
|
|
63
|
+
lReachingModules.add(lDependent);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
61
66
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
return pModules
|
|
68
|
+
.filter(({ source }) => lReachingModules.has(source))
|
|
69
|
+
.map((pModule) => ({
|
|
70
|
+
...pModule,
|
|
71
|
+
matchesReaches: lModuleNamesToReach.has(pModule.source),
|
|
72
|
+
dependencies: pModule.dependencies.filter(({ resolved }) =>
|
|
73
|
+
lReachingModules.has(resolved),
|
|
74
|
+
),
|
|
75
|
+
}));
|
|
71
76
|
}
|
|
72
77
|
|
|
73
78
|
function tagHighlight(pModules, pHighlightFilter) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
return pModules.map((pModule) => ({
|
|
80
|
+
...pModule,
|
|
81
|
+
matchesHighlight: moduleMatchesFilter(pModule, pHighlightFilter),
|
|
82
|
+
}));
|
|
78
83
|
}
|
|
79
84
|
|
|
80
85
|
export function applyFilters(pModules, pFilters) {
|
|
81
|
-
|
|
82
|
-
|
|
86
|
+
if (pFilters) {
|
|
87
|
+
let lReturnValue = structuredClone(pModules);
|
|
83
88
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
89
|
+
if (pFilters.exclude) {
|
|
90
|
+
lReturnValue = exclude(lReturnValue, pFilters.exclude);
|
|
91
|
+
}
|
|
92
|
+
if (pFilters.includeOnly) {
|
|
93
|
+
lReturnValue = includeOnly(lReturnValue, pFilters.includeOnly);
|
|
94
|
+
}
|
|
95
|
+
if (pFilters.focus) {
|
|
96
|
+
lReturnValue = addFocus(lReturnValue, pFilters.focus);
|
|
97
|
+
}
|
|
98
|
+
if (pFilters.reaches) {
|
|
99
|
+
lReturnValue = filterReaches(lReturnValue, pFilters.reaches);
|
|
100
|
+
}
|
|
101
|
+
if (pFilters.highlight) {
|
|
102
|
+
lReturnValue = tagHighlight(lReturnValue, pFilters.highlight);
|
|
103
|
+
}
|
|
104
|
+
return lReturnValue;
|
|
105
|
+
}
|
|
106
|
+
return pModules;
|
|
102
107
|
}
|
|
@@ -9,252 +9,254 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
export default class IndexedModuleGraph {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
12
|
+
#indexedGraph;
|
|
13
|
+
/**
|
|
14
|
+
* @param {IModuleOrFolder} pModule
|
|
15
|
+
* @returns {IVertex}
|
|
16
|
+
*/
|
|
17
|
+
#normalizeModule(pModule) {
|
|
18
|
+
return {
|
|
19
|
+
...pModule,
|
|
20
|
+
dependencies: (pModule?.dependencies ?? []).map((pDependency) => ({
|
|
21
|
+
...pDependency,
|
|
22
|
+
name: pDependency.name ? pDependency.name : pDependency.resolved,
|
|
23
|
+
})),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
#init(pModules, pIndexAttribute) {
|
|
28
|
+
this.#indexedGraph = new Map(
|
|
29
|
+
pModules.map((pModule) => [
|
|
30
|
+
pModule[pIndexAttribute],
|
|
31
|
+
this.#normalizeModule(pModule),
|
|
32
|
+
]),
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
/**
|
|
37
|
+
* @param {import("../../types/dependency-cruiser.mjs").IModule[]} pModules
|
|
38
|
+
* @param {string} pIndexAttribute
|
|
39
|
+
*/
|
|
40
|
+
constructor(pModules, pIndexAttribute = "source") {
|
|
41
|
+
this.#init(pModules, pIndexAttribute);
|
|
42
|
+
}
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
44
|
+
/**
|
|
45
|
+
* @param {string} pName
|
|
46
|
+
* @return {IVertex}
|
|
47
|
+
*/
|
|
48
|
+
findVertexByName(pName) {
|
|
49
|
+
return this.#indexedGraph.get(pName);
|
|
50
|
+
}
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
52
|
+
/**
|
|
53
|
+
* @param {string} pName - the name of the module to find transitive dependents of.
|
|
54
|
+
* @param {number} pMaxDepth - the maximum depth to search for dependents.
|
|
55
|
+
* Defaults to 0 (no maximum). To only get direct dependents.
|
|
56
|
+
* specify 1. To get dependents of these dependents as well
|
|
57
|
+
* specify 2 - etc.
|
|
58
|
+
* @param {number} pDepth - technical parameter - best to leave out of direct calls
|
|
59
|
+
* @param {Set<string>} pVisited - technical parameter - best to leave out of direct calls
|
|
60
|
+
* @returns {Array<string>}
|
|
61
|
+
*/
|
|
62
|
+
// eslint-disable-next-line complexity
|
|
63
|
+
findTransitiveDependents(
|
|
64
|
+
pName,
|
|
65
|
+
pMaxDepth = 0,
|
|
66
|
+
pDepth = 0,
|
|
67
|
+
pVisited = new Set(),
|
|
68
|
+
) {
|
|
69
|
+
/** @type {string[]} */
|
|
70
|
+
let lReturnValue = [];
|
|
71
|
+
const lModule = this.#indexedGraph.get(pName);
|
|
71
72
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
if (lModule && (!pMaxDepth || pDepth <= pMaxDepth)) {
|
|
74
|
+
let lDependents = lModule.dependents || [];
|
|
75
|
+
const lVisited = pVisited.add(pName);
|
|
75
76
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
77
|
+
// @TODO this works for modules, but not for folders yet
|
|
78
|
+
if (lDependents.length > 0) {
|
|
79
|
+
for (const lDependent of lDependents) {
|
|
80
|
+
// eslint-disable-next-line max-depth
|
|
81
|
+
if (!lVisited.has(lDependent)) {
|
|
82
|
+
this.findTransitiveDependents(
|
|
83
|
+
lDependent,
|
|
84
|
+
pMaxDepth,
|
|
85
|
+
pDepth + 1,
|
|
86
|
+
lVisited,
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
lReturnValue = Array.from(lVisited);
|
|
92
|
+
}
|
|
93
|
+
return lReturnValue;
|
|
94
|
+
}
|
|
93
95
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
96
|
+
/**
|
|
97
|
+
* @param {string} pName - the name of the module to find transitive dependencies of.
|
|
98
|
+
* @param {number} pMaxDepth - the maximum depth to search for dependencies
|
|
99
|
+
* Defaults to 0 (no maximum). To only get direct dependencies.
|
|
100
|
+
* specify 1. To get dependencies of these dependencies as well
|
|
101
|
+
* specify 2 - etc.
|
|
102
|
+
* @param {number} pDepth - technical parameter - best to leave out of direct calls
|
|
103
|
+
* @param {Set<string>} pVisited - technical parameter - best to leave out of direct calls
|
|
104
|
+
* @returns {Array<string>}
|
|
105
|
+
*/
|
|
106
|
+
findTransitiveDependencies(
|
|
107
|
+
pName,
|
|
108
|
+
pMaxDepth = 0,
|
|
109
|
+
pDepth = 0,
|
|
110
|
+
pVisited = new Set(),
|
|
111
|
+
) {
|
|
112
|
+
/** @type {string[]} */
|
|
113
|
+
let lReturnValue = [];
|
|
114
|
+
/** @type {IVertex} */
|
|
115
|
+
const lModule = this.#indexedGraph.get(pName);
|
|
114
116
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
117
|
+
if (lModule && (!pMaxDepth || pDepth <= pMaxDepth)) {
|
|
118
|
+
let lDependencies = lModule.dependencies;
|
|
119
|
+
const lVisited = pVisited.add(pName);
|
|
118
120
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
121
|
+
if (lDependencies.length > 0) {
|
|
122
|
+
// eslint-disable-next-line budapestian/local-variable-pattern
|
|
123
|
+
for (const { name } of lDependencies) {
|
|
124
|
+
// eslint-disable-next-line max-depth
|
|
125
|
+
if (!lVisited.has(name)) {
|
|
126
|
+
this.findTransitiveDependencies(
|
|
127
|
+
name,
|
|
128
|
+
pMaxDepth,
|
|
129
|
+
pDepth + 1,
|
|
130
|
+
lVisited,
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
lReturnValue = Array.from(lVisited);
|
|
136
|
+
}
|
|
137
|
+
return lReturnValue;
|
|
138
|
+
}
|
|
137
139
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
140
|
+
/**
|
|
141
|
+
*
|
|
142
|
+
* @param {IEdge} pEdge
|
|
143
|
+
* @returns {IMiniDependency}
|
|
144
|
+
*/
|
|
145
|
+
#geldEdge(pEdge) {
|
|
146
|
+
return {
|
|
147
|
+
name: pEdge.name,
|
|
148
|
+
dependencyTypes: pEdge.dependencyTypes ?? [],
|
|
149
|
+
};
|
|
150
|
+
}
|
|
149
151
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
152
|
+
/**
|
|
153
|
+
* @param {string} pFrom
|
|
154
|
+
* @param {string} pTo
|
|
155
|
+
* @param {Set<string>} pVisited
|
|
156
|
+
* @returns {Array<IMiniDependency>}
|
|
157
|
+
*/
|
|
158
|
+
getPath(pFrom, pTo, pVisited = new Set()) {
|
|
159
|
+
/** @type {IVertex} */
|
|
160
|
+
const lFromNode = this.#indexedGraph.get(pFrom);
|
|
159
161
|
|
|
160
|
-
|
|
162
|
+
pVisited.add(pFrom);
|
|
161
163
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
164
|
+
if (!lFromNode) {
|
|
165
|
+
return [];
|
|
166
|
+
}
|
|
165
167
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
168
|
+
const lDirectUnvisitedDependencies = lFromNode.dependencies
|
|
169
|
+
.filter((pDependency) => !pVisited.has(pDependency.name))
|
|
170
|
+
.map(this.#geldEdge);
|
|
171
|
+
const lFoundDependency = lDirectUnvisitedDependencies.find(
|
|
172
|
+
(pDependency) => pDependency.name === pTo,
|
|
173
|
+
);
|
|
172
174
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
175
|
+
if (lFoundDependency) {
|
|
176
|
+
return [lFoundDependency];
|
|
177
|
+
}
|
|
176
178
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
+
for (const lNewFrom of lDirectUnvisitedDependencies) {
|
|
180
|
+
let lCandidatePath = this.getPath(lNewFrom.name, pTo, pVisited);
|
|
179
181
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
182
|
+
if (lCandidatePath.length > 0) {
|
|
183
|
+
return [lNewFrom].concat(lCandidatePath);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return [];
|
|
187
|
+
}
|
|
186
188
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
189
|
+
/**
|
|
190
|
+
* Returns the first non-zero length path from pInitialSource to pInitialSource
|
|
191
|
+
* Returns the empty array if there is no such path
|
|
192
|
+
*
|
|
193
|
+
* @param {string} pInitialSource The 'source' attribute of the node to be tested (source uniquely identifying a node)
|
|
194
|
+
* @param {IEdge} pCurrentDependency The 'to' node to be traversed as a dependency object of the previous 'from' traversed
|
|
195
|
+
* @param {Set<string>=} pVisited Technical parameter - best to leave out of direct calls
|
|
196
|
+
* @return {Array<IMiniDependency>} see description above
|
|
197
|
+
*/
|
|
198
|
+
#getCycle(pInitialSource, pCurrentDependency, pVisited) {
|
|
199
|
+
const lVisited = pVisited || new Set();
|
|
200
|
+
/** @type {IVertex} */
|
|
201
|
+
const lCurrentVertex = this.#indexedGraph.get(pCurrentDependency.name);
|
|
202
|
+
const lEdges = lCurrentVertex.dependencies.filter(
|
|
203
|
+
(pDependency) => !lVisited.has(pDependency.name),
|
|
204
|
+
);
|
|
205
|
+
const lInitialAsDependency = lEdges.find(
|
|
206
|
+
(pDependency) => pDependency.name === pInitialSource,
|
|
207
|
+
);
|
|
206
208
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
209
|
+
if (lInitialAsDependency) {
|
|
210
|
+
return pInitialSource === pCurrentDependency.name
|
|
211
|
+
? [this.#geldEdge(lInitialAsDependency)]
|
|
212
|
+
: [
|
|
213
|
+
this.#geldEdge(pCurrentDependency),
|
|
214
|
+
this.#geldEdge(lInitialAsDependency),
|
|
215
|
+
];
|
|
216
|
+
}
|
|
215
217
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
218
|
+
/** @type {Array<IMiniDependency>} */
|
|
219
|
+
const lResult = [];
|
|
220
|
+
for (const lDependency of lEdges) {
|
|
221
|
+
if (!lResult.some((pSome) => pSome.name === pCurrentDependency.name)) {
|
|
222
|
+
const lCycle = this.#getCycle(
|
|
223
|
+
pInitialSource,
|
|
224
|
+
lDependency,
|
|
225
|
+
lVisited.add(lDependency.name),
|
|
226
|
+
);
|
|
225
227
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
228
|
+
if (
|
|
229
|
+
lCycle.length > 0 &&
|
|
230
|
+
!lCycle.some((pSome) => pSome.name === pCurrentDependency.name)
|
|
231
|
+
) {
|
|
232
|
+
lResult.push(this.#geldEdge(pCurrentDependency), ...lCycle);
|
|
233
|
+
return lResult;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return lResult;
|
|
238
|
+
}
|
|
237
239
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
240
|
+
/**
|
|
241
|
+
* Returns the first non-zero length path from pInitialSource to pInitialSource
|
|
242
|
+
* Returns the empty array if there is no such path
|
|
243
|
+
*
|
|
244
|
+
* @param {string} pInitialSource The 'source' attribute of the node to be tested
|
|
245
|
+
* (source uniquely identifying a node)
|
|
246
|
+
* @param {string} pCurrentSource The 'source' attribute of the 'to' node to
|
|
247
|
+
* be traversed
|
|
248
|
+
* @return {Array<IMiniDependency>} see description above
|
|
249
|
+
*/
|
|
250
|
+
getCycle(pInitialSource, pCurrentSource) {
|
|
251
|
+
/** @type {IVertex} */
|
|
252
|
+
const lInitialNode = this.#indexedGraph.get(pInitialSource);
|
|
253
|
+
const lCurrentDependency = lInitialNode.dependencies.find(
|
|
254
|
+
(pDependency) => pDependency.name === pCurrentSource,
|
|
255
|
+
);
|
|
254
256
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
257
|
+
if (!lCurrentDependency) {
|
|
258
|
+
return [];
|
|
259
|
+
}
|
|
260
|
+
return this.#getCycle(pInitialSource, lCurrentDependency);
|
|
261
|
+
}
|
|
260
262
|
}
|