dependency-cruiser 16.4.1 → 16.4.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/package.json +4 -4
- package/src/enrich/add-validations.mjs +3 -3
- package/src/enrich/derive/folders/index.mjs +2 -2
- package/src/enrich/derive/reachable.mjs +6 -3
- package/src/enrich/summarize/index.mjs +2 -2
- package/src/enrich/summarize/summarize-modules.mjs +2 -2
- package/src/extract/acorn/extract.mjs +3 -3
- package/src/extract/acorn/parse.mjs +0 -6
- package/src/extract/clear-caches.mjs +6 -6
- package/src/extract/swc/extract.mjs +3 -5
- package/src/extract/swc/parse.mjs +14 -22
- package/src/extract/tsc/extract.mjs +4 -4
- package/src/extract/tsc/parse.mjs +14 -22
- package/src/graph-utl/compare.mjs +10 -14
- package/src/graph-utl/consolidate-module-dependencies.mjs +2 -2
- package/src/graph-utl/consolidate-modules.mjs +2 -2
- package/src/main/options/assert-validity.mjs +2 -2
- package/src/main/report-wrap.mjs +4 -4
- package/src/meta.cjs +1 -1
- package/src/report/dot/index.mjs +6 -12
- package/src/report/dot/module-utl.mjs +5 -35
- package/src/report/dot/prepare-custom-level.mjs +8 -7
- package/src/report/dot/prepare-flat-level.mjs +8 -7
- package/src/report/dot/prepare-folder-level.mjs +9 -7
- package/src/report/dot/theming.mjs +20 -6
- package/src/report/error-html/utl.mjs +2 -11
- package/src/report/index.mjs +2 -7
- package/src/report/markdown.mjs +5 -3
- package/src/utl/regex-util.mjs +2 -7
- package/src/validate/index.mjs +14 -17
- package/src/validate/match-dependency-rule.mjs +34 -25
- package/src/validate/match-folder-dependency-rule.mjs +3 -3
- package/src/validate/match-module-rule-helpers.mjs +132 -0
- package/src/validate/match-module-rule.mjs +6 -130
- package/src/validate/matchers.mjs +22 -38
- package/src/validate/rule-classifiers.mjs +0 -2
- package/src/validate/violates-required-rule.mjs +8 -4
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { folderify, extractFirstTransgression, addURL } from "./module-utl.mjs";
|
|
2
|
+
import { applyTheme } from "./theming.mjs";
|
|
2
3
|
import consolidateToFolder from "#graph-utl/consolidate-to-folder.mjs";
|
|
3
|
-
import
|
|
4
|
+
import { compareModules } from "#graph-utl/compare.mjs";
|
|
4
5
|
import stripSelfTransitions from "#graph-utl/strip-self-transitions.mjs";
|
|
6
|
+
// fuk eslint
|
|
5
7
|
|
|
6
8
|
export default function prepareFolderLevel(pResults, pTheme, _, pShowMetrics) {
|
|
7
9
|
return consolidateToFolder(pResults.modules)
|
|
8
|
-
.sort(
|
|
9
|
-
.map(
|
|
10
|
-
.map(
|
|
10
|
+
.sort(compareModules)
|
|
11
|
+
.map(extractFirstTransgression)
|
|
12
|
+
.map(folderify(pShowMetrics))
|
|
11
13
|
.map(stripSelfTransitions)
|
|
12
|
-
.map(
|
|
13
|
-
.map(
|
|
14
|
+
.map(applyTheme(pTheme))
|
|
15
|
+
.map(addURL(pResults.summary.optionsUsed?.prefix ?? ""));
|
|
14
16
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import DEFAULT_THEME from "./default-theme.mjs";
|
|
2
|
+
import { attributizeObject } from "./module-utl.mjs";
|
|
2
3
|
import { has, get } from "#utl/object-util.mjs";
|
|
3
4
|
|
|
4
5
|
function matchesRE(pValue, pRE) {
|
|
@@ -48,7 +49,7 @@ function moduleOrDependencyMatchesCriteria(pSchemeEntry, pModule) {
|
|
|
48
49
|
});
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
function
|
|
52
|
+
export function getThemeAttributes(pModuleOrDependency, pAttributeCriteria) {
|
|
52
53
|
return (pAttributeCriteria || [])
|
|
53
54
|
.filter((pSchemeEntry) =>
|
|
54
55
|
moduleOrDependencyMatchesCriteria(pSchemeEntry, pModuleOrDependency),
|
|
@@ -57,7 +58,7 @@ function determineAttributes(pModuleOrDependency, pAttributeCriteria) {
|
|
|
57
58
|
.reduce((pAll, pCurrent) => ({ ...pCurrent, ...pAll }), {});
|
|
58
59
|
}
|
|
59
60
|
|
|
60
|
-
function normalizeTheme(pTheme) {
|
|
61
|
+
export function normalizeTheme(pTheme) {
|
|
61
62
|
let lReturnValue = structuredClone(DEFAULT_THEME);
|
|
62
63
|
|
|
63
64
|
if (pTheme) {
|
|
@@ -78,7 +79,20 @@ function normalizeTheme(pTheme) {
|
|
|
78
79
|
return lReturnValue;
|
|
79
80
|
}
|
|
80
81
|
|
|
81
|
-
export
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
export function applyTheme(pTheme) {
|
|
83
|
+
return (pModule) => ({
|
|
84
|
+
...pModule,
|
|
85
|
+
dependencies: pModule.dependencies
|
|
86
|
+
.map((pDependency) => ({
|
|
87
|
+
...pDependency,
|
|
88
|
+
themeAttrs: attributizeObject(
|
|
89
|
+
getThemeAttributes(pDependency, pTheme.dependencies),
|
|
90
|
+
),
|
|
91
|
+
}))
|
|
92
|
+
.map((pDependency) => ({
|
|
93
|
+
...pDependency,
|
|
94
|
+
hasExtraAttributes: Boolean(pDependency.rule || pDependency.themeAttrs),
|
|
95
|
+
})),
|
|
96
|
+
themeAttrs: attributizeObject(getThemeAttributes(pModule, pTheme.modules)),
|
|
97
|
+
});
|
|
98
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { formatViolation, formatPercentage } from "../utl/index.mjs";
|
|
2
2
|
import meta from "#meta.cjs";
|
|
3
3
|
|
|
4
|
-
function getFormattedAllowedRule(pRuleSetUsed) {
|
|
4
|
+
export function getFormattedAllowedRule(pRuleSetUsed) {
|
|
5
5
|
const lAllowed = pRuleSetUsed?.allowed ?? [];
|
|
6
6
|
const lCommentedRule = lAllowed.find((pRule) =>
|
|
7
7
|
Object.hasOwn(pRule, "comment"),
|
|
@@ -17,7 +17,7 @@ function getFormattedAllowedRule(pRuleSetUsed) {
|
|
|
17
17
|
: [];
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
function mergeCountsIntoRule(pRule, pViolationCounts) {
|
|
20
|
+
export function mergeCountsIntoRule(pRule, pViolationCounts) {
|
|
21
21
|
const lCounts = pViolationCounts[pRule.name]
|
|
22
22
|
? pViolationCounts[pRule.name]
|
|
23
23
|
: { count: 0, ignoredCount: 0 };
|
|
@@ -138,12 +138,3 @@ export function aggregateViolations(pViolations, pRuleSetUsed) {
|
|
|
138
138
|
pFirst.name.localeCompare(pSecond.name),
|
|
139
139
|
);
|
|
140
140
|
}
|
|
141
|
-
|
|
142
|
-
export default {
|
|
143
|
-
aggregateViolations,
|
|
144
|
-
getFormattedAllowedRule,
|
|
145
|
-
mergeCountsIntoRule,
|
|
146
|
-
formatSummaryForReport,
|
|
147
|
-
determineFromExtras,
|
|
148
|
-
determineTo,
|
|
149
|
-
};
|
package/src/report/index.mjs
CHANGED
|
@@ -35,7 +35,7 @@ const TYPE2MODULE = new Map([
|
|
|
35
35
|
* an options object (specific to that function)
|
|
36
36
|
* and returns an IReporterOutput
|
|
37
37
|
*/
|
|
38
|
-
async function getReporter(pOutputType) {
|
|
38
|
+
export async function getReporter(pOutputType) {
|
|
39
39
|
let lReturnValue = {};
|
|
40
40
|
if (pOutputType?.startsWith("plugin:")) {
|
|
41
41
|
lReturnValue = await getExternalPluginReporter(pOutputType);
|
|
@@ -52,11 +52,6 @@ async function getReporter(pOutputType) {
|
|
|
52
52
|
*
|
|
53
53
|
* @returns {import("../../types/shared-types.js").OutputType[]} -
|
|
54
54
|
*/
|
|
55
|
-
function getAvailableReporters() {
|
|
55
|
+
export function getAvailableReporters() {
|
|
56
56
|
return Array.from(TYPE2MODULE.keys());
|
|
57
57
|
}
|
|
58
|
-
|
|
59
|
-
export default {
|
|
60
|
-
getAvailableReporters,
|
|
61
|
-
getReporter,
|
|
62
|
-
};
|
package/src/report/markdown.mjs
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
aggregateViolations,
|
|
3
|
+
determineTo,
|
|
4
|
+
determineFromExtras,
|
|
5
|
+
} from "./error-html/utl.mjs";
|
|
2
6
|
import meta from "#meta.cjs";
|
|
3
7
|
|
|
4
|
-
const { aggregateViolations, determineTo, determineFromExtras } = errorHtmlUtl;
|
|
5
|
-
|
|
6
8
|
const REPORT_DEFAULTS = {
|
|
7
9
|
showTitle: true,
|
|
8
10
|
title: "## Forbidden dependency check - results",
|
package/src/utl/regex-util.mjs
CHANGED
|
@@ -23,7 +23,7 @@ export function extractGroups(pFromRestriction, pActualPath) {
|
|
|
23
23
|
|
|
24
24
|
if (lMatchResult && lMatchResult.length > 1) {
|
|
25
25
|
lReturnValue = lMatchResult.filter(
|
|
26
|
-
(pResult) => typeof pResult === "string"
|
|
26
|
+
(pResult) => typeof pResult === "string",
|
|
27
27
|
);
|
|
28
28
|
}
|
|
29
29
|
}
|
|
@@ -51,11 +51,6 @@ export function replaceGroupPlaceholders(pString, pExtractedGroups) {
|
|
|
51
51
|
(pAll, pThis, pIndex) =>
|
|
52
52
|
// eslint-disable-next-line security/detect-non-literal-regexp
|
|
53
53
|
pAll.replace(new RegExp(`\\$${pIndex}`, "g"), pThis),
|
|
54
|
-
pString
|
|
54
|
+
pString,
|
|
55
55
|
);
|
|
56
56
|
}
|
|
57
|
-
|
|
58
|
-
export default {
|
|
59
|
-
extractGroups,
|
|
60
|
-
replaceGroupPlaceholders,
|
|
61
|
-
};
|
package/src/validate/index.mjs
CHANGED
|
@@ -89,22 +89,19 @@ function validateAgainstRules(pRuleSet, pFrom, pTo, pMatchModule) {
|
|
|
89
89
|
}
|
|
90
90
|
return lReturnValue;
|
|
91
91
|
}
|
|
92
|
+
export function validateModule(pRuleSet, pModule) {
|
|
93
|
+
return validateAgainstRules(pRuleSet, pModule, {}, matchModuleRule);
|
|
94
|
+
}
|
|
92
95
|
|
|
93
|
-
export
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
},
|
|
97
|
-
|
|
98
|
-
dependency: function dependency(pRuleSet, pFrom, pTo) {
|
|
99
|
-
return validateAgainstRules(pRuleSet, pFrom, pTo, matchDependencyRule);
|
|
100
|
-
},
|
|
96
|
+
export function validateDependency(pRuleSet, pFrom, pTo) {
|
|
97
|
+
return validateAgainstRules(pRuleSet, pFrom, pTo, matchDependencyRule);
|
|
98
|
+
}
|
|
101
99
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
};
|
|
100
|
+
export function validateFolder(pRuleSet, pFromFolder, pToFolder) {
|
|
101
|
+
return validateAgainstRules(
|
|
102
|
+
pRuleSet,
|
|
103
|
+
pFromFolder,
|
|
104
|
+
pToFolder,
|
|
105
|
+
matchFolderRule,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import { isModuleOnlyRule, isFolderScope } from "./rule-classifiers.mjs";
|
|
3
|
-
import
|
|
3
|
+
import {
|
|
4
|
+
propertyEquals,
|
|
5
|
+
propertyMatches,
|
|
6
|
+
propertyMatchesNot,
|
|
7
|
+
matchesFromPath,
|
|
8
|
+
matchesFromPathNot,
|
|
9
|
+
matchesToPath,
|
|
10
|
+
matchesToPathNot,
|
|
11
|
+
matchesToDependencyTypes,
|
|
12
|
+
matchesToDependencyTypesNot,
|
|
13
|
+
matchesToVia,
|
|
14
|
+
matchesToViaOnly,
|
|
15
|
+
matchesToIsMoreUnstable,
|
|
16
|
+
matchesMoreThanOneDependencyType,
|
|
17
|
+
} from "./matchers.mjs";
|
|
4
18
|
import { extractGroups } from "#utl/regex-util.mjs";
|
|
5
19
|
|
|
6
20
|
/**
|
|
@@ -15,34 +29,29 @@ function match(pFrom, pTo) {
|
|
|
15
29
|
const lGroups = extractGroups(pRule.from, pFrom.source);
|
|
16
30
|
|
|
17
31
|
return (
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
32
|
+
matchesFromPath(pRule, pFrom) &&
|
|
33
|
+
matchesFromPathNot(pRule, pFrom) &&
|
|
34
|
+
matchesToPath(pRule, pTo, lGroups) &&
|
|
35
|
+
matchesToPathNot(pRule, pTo, lGroups) &&
|
|
36
|
+
matchesToDependencyTypes(pRule, pTo) &&
|
|
37
|
+
matchesToDependencyTypesNot(pRule, pTo) &&
|
|
38
|
+
matchesMoreThanOneDependencyType(pRule, pTo) &&
|
|
25
39
|
// preCompilationOnly is not a mandatory attribute, but if the attribute
|
|
26
40
|
// is in the rule but not in the dependency there won't be a match
|
|
27
41
|
// anyway, so we can use the default propertyEquals method regardless
|
|
28
|
-
|
|
42
|
+
propertyEquals(pRule, pTo, "preCompilationOnly") &&
|
|
29
43
|
// couldNotResolve, circular, dynamic and exoticallyRequired _are_ mandatory
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"exoticRequire",
|
|
42
|
-
) &&
|
|
43
|
-
matchers.toVia(pRule, pTo, lGroups) &&
|
|
44
|
-
matchers.toViaOnly(pRule, pTo, lGroups) &&
|
|
45
|
-
matchers.toIsMoreUnstable(pRule, pFrom, pTo)
|
|
44
|
+
propertyEquals(pRule, pTo, "couldNotResolve") &&
|
|
45
|
+
propertyEquals(pRule, pTo, "circular") &&
|
|
46
|
+
propertyEquals(pRule, pTo, "dynamic") &&
|
|
47
|
+
propertyEquals(pRule, pTo, "exoticallyRequired") &&
|
|
48
|
+
propertyMatches(pRule, pTo, "license", "license") &&
|
|
49
|
+
propertyMatchesNot(pRule, pTo, "licenseNot", "license") &&
|
|
50
|
+
propertyMatches(pRule, pTo, "exoticRequire", "exoticRequire") &&
|
|
51
|
+
propertyMatchesNot(pRule, pTo, "exoticRequireNot", "exoticRequire") &&
|
|
52
|
+
matchesToVia(pRule, pTo, lGroups) &&
|
|
53
|
+
matchesToViaOnly(pRule, pTo, lGroups) &&
|
|
54
|
+
matchesToIsMoreUnstable(pRule, pFrom, pTo)
|
|
46
55
|
);
|
|
47
56
|
};
|
|
48
57
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isModuleOnlyRule, isFolderScope } from "./rule-classifiers.mjs";
|
|
2
|
-
import
|
|
2
|
+
import { propertyEquals, matchesToIsMoreUnstable } from "./matchers.mjs";
|
|
3
3
|
import { extractGroups, replaceGroupPlaceholders } from "#utl/regex-util.mjs";
|
|
4
4
|
|
|
5
5
|
function fromFolderPath(pRule, pFromFolder) {
|
|
@@ -44,8 +44,8 @@ function match(pFromFolder, pToFolder) {
|
|
|
44
44
|
fromFolderPathNot(pRule, pFromFolder) &&
|
|
45
45
|
toFolderPath(pRule, pToFolder, lGroups) &&
|
|
46
46
|
toFolderPathNot(pRule, pToFolder, lGroups) &&
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
matchesToIsMoreUnstable(pRule, pFromFolder, pToFolder) &&
|
|
48
|
+
propertyEquals(pRule, pToFolder, "circular")
|
|
49
49
|
);
|
|
50
50
|
};
|
|
51
51
|
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import {
|
|
2
|
+
matchToModulePath,
|
|
3
|
+
matchToModulePathNot,
|
|
4
|
+
matchesFromPath,
|
|
5
|
+
matchesFromPathNot,
|
|
6
|
+
matchesModulePath,
|
|
7
|
+
matchesModulePathNot,
|
|
8
|
+
} from "./matchers.mjs";
|
|
9
|
+
import { extractGroups } from "#utl/regex-util.mjs";
|
|
10
|
+
/**
|
|
11
|
+
* Returns true if pRule is an orphan rule and pModule is an orphan.
|
|
12
|
+
* Returns false in all other cases
|
|
13
|
+
*
|
|
14
|
+
* @param {import("../../types/rule-set.mjs").IAnyRuleType} pRule
|
|
15
|
+
* @param {import("../../types/cruise-result.mjs").IModule} pModule
|
|
16
|
+
* @returns {boolean}
|
|
17
|
+
*/
|
|
18
|
+
export function matchesOrphanRule(pRule, pModule) {
|
|
19
|
+
return (
|
|
20
|
+
Object.hasOwn(pRule?.from ?? {}, "orphan") &&
|
|
21
|
+
// @ts-expect-error the 'hasOwn' above guarantees there's a 'from.orphan' attribute
|
|
22
|
+
pModule.orphan === pRule.from.orphan &&
|
|
23
|
+
matchesFromPath(pRule, pModule) &&
|
|
24
|
+
matchesFromPathNot(pRule, pModule)
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Returns true if pRule is a 'reachable' rule and pModule matches the reachability
|
|
30
|
+
* criteria.
|
|
31
|
+
* Returns false in all other cases
|
|
32
|
+
*
|
|
33
|
+
* @param {import("../../types/rule-set.mjs").IAnyRuleType} pRule
|
|
34
|
+
* @param {import("../../types/cruise-result.mjs").IModule} pModule
|
|
35
|
+
* @returns {boolean}
|
|
36
|
+
*/
|
|
37
|
+
export function matchesReachableRule(pRule, pModule) {
|
|
38
|
+
if (
|
|
39
|
+
Object.hasOwn(pRule?.to ?? {}, "reachable") &&
|
|
40
|
+
Object.hasOwn(pModule, "reachable")
|
|
41
|
+
) {
|
|
42
|
+
// @ts-expect-error the 'hasOwn' above ensures the 'reachable' exists
|
|
43
|
+
const lReachableRecord = pModule.reachable.find(
|
|
44
|
+
(pReachable) =>
|
|
45
|
+
pReachable.asDefinedInRule === pRule.name &&
|
|
46
|
+
// @ts-expect-error the 'hasOwn' above ensures the 'to.reachable' exists
|
|
47
|
+
pReachable.value === pRule.to.reachable,
|
|
48
|
+
);
|
|
49
|
+
if (lReachableRecord) {
|
|
50
|
+
const lGroups = extractGroups(pRule.from, lReachableRecord.matchedFrom);
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
matchToModulePath(pRule, pModule, lGroups) &&
|
|
54
|
+
matchToModulePathNot(pRule, pModule, lGroups)
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Returns true if pRule is a 'reaches' rule and pModule matches the reachability
|
|
63
|
+
* criteria.
|
|
64
|
+
* Returns false in all other cases
|
|
65
|
+
*
|
|
66
|
+
* @param {import("../../types/rule-set.mjs").IAnyRuleType} pRule
|
|
67
|
+
* @param {import("../../types/cruise-result.mjs").IModule} pModule
|
|
68
|
+
* @returns {boolean}
|
|
69
|
+
*/
|
|
70
|
+
export function matchesReachesRule(pRule, pModule) {
|
|
71
|
+
return (
|
|
72
|
+
Object.hasOwn(pRule?.to ?? {}, "reachable") &&
|
|
73
|
+
Object.hasOwn(pModule, "reaches") &&
|
|
74
|
+
// @ts-expect-error the 'hasOwn' above guarantees the .reaches exists
|
|
75
|
+
pModule.reaches.some(
|
|
76
|
+
(pReaches) =>
|
|
77
|
+
pReaches.asDefinedInRule === pRule.name &&
|
|
78
|
+
pReaches.modules.some(
|
|
79
|
+
(pReachesModule) =>
|
|
80
|
+
matchToModulePath(pRule, pReachesModule) &&
|
|
81
|
+
matchToModulePathNot(pRule, pReachesModule),
|
|
82
|
+
),
|
|
83
|
+
)
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
*
|
|
88
|
+
* @param {import("../../types/rule-set.mjs").IAnyRuleType} pRule
|
|
89
|
+
* @param {string[]} pDependents
|
|
90
|
+
* @returns {boolean}
|
|
91
|
+
*/
|
|
92
|
+
function dependentsCountsMatch(pRule, pDependents) {
|
|
93
|
+
const lMatchingDependentsCount = pDependents.filter(
|
|
94
|
+
(pDependent) =>
|
|
95
|
+
Boolean(!pRule.from.path || pDependent.match(pRule.from.path)) &&
|
|
96
|
+
Boolean(!pRule.from.pathNot || !pDependent.match(pRule.from.pathNot)),
|
|
97
|
+
).length;
|
|
98
|
+
return (
|
|
99
|
+
(!pRule.module.numberOfDependentsLessThan ||
|
|
100
|
+
lMatchingDependentsCount < pRule.module.numberOfDependentsLessThan) &&
|
|
101
|
+
(!pRule.module.numberOfDependentsMoreThan ||
|
|
102
|
+
lMatchingDependentsCount > pRule.module.numberOfDependentsMoreThan)
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
*
|
|
108
|
+
* @param {import("../../types/rule-set.mjs").IAnyRuleType} pRule
|
|
109
|
+
* @param {import("../../types/cruise-result.mjs").IModule} pModule
|
|
110
|
+
* @returns {boolean}
|
|
111
|
+
*/
|
|
112
|
+
// eslint-disable-next-line complexity
|
|
113
|
+
export function matchesDependentsRule(pRule, pModule) {
|
|
114
|
+
if (
|
|
115
|
+
(Object.hasOwn(pModule, "dependents") &&
|
|
116
|
+
Object.hasOwn(pRule?.module ?? {}, "numberOfDependentsLessThan")) ||
|
|
117
|
+
Object.hasOwn(pRule?.module ?? {}, "numberOfDependentsMoreThan")
|
|
118
|
+
) {
|
|
119
|
+
return (
|
|
120
|
+
// group matching seems like a nice idea, however, the 'from' part of the
|
|
121
|
+
// rule is going to match not one module (as with regular dependency rules)
|
|
122
|
+
// but a whole bunch of them, being the 'dependents'. So that match is going
|
|
123
|
+
// to produce not one result, but one per matching dependent. To get meaningful
|
|
124
|
+
// results we'd probably have to loop over these and or the
|
|
125
|
+
// matchToModulePath together.
|
|
126
|
+
matchesModulePath(pRule, pModule) &&
|
|
127
|
+
matchesModulePathNot(pRule, pModule) &&
|
|
128
|
+
dependentsCountsMatch(pRule, pModule.dependents)
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
@@ -1,130 +1,10 @@
|
|
|
1
1
|
import { isModuleOnlyRule, isFolderScope } from "./rule-classifiers.mjs";
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
*
|
|
9
|
-
* @param {import("../../types/rule-set.mjs").IAnyRuleType} pRule
|
|
10
|
-
* @param {import("../../types/cruise-result.mjs").IModule} pModule
|
|
11
|
-
* @returns {boolean}
|
|
12
|
-
*/
|
|
13
|
-
function matchesOrphanRule(pRule, pModule) {
|
|
14
|
-
return (
|
|
15
|
-
Object.hasOwn(pRule?.from ?? {}, "orphan") &&
|
|
16
|
-
// @ts-expect-error the 'hasOwn' above guarantees there's a 'from.orphan' attribute
|
|
17
|
-
pModule.orphan === pRule.from.orphan &&
|
|
18
|
-
matchers.fromPath(pRule, pModule) &&
|
|
19
|
-
matchers.fromPathNot(pRule, pModule)
|
|
20
|
-
);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Returns true if pRule is a 'reachable' rule and pModule matches the reachability
|
|
25
|
-
* criteria.
|
|
26
|
-
* Returns false in all other cases
|
|
27
|
-
*
|
|
28
|
-
* @param {import("../../types/rule-set.mjs").IAnyRuleType} pRule
|
|
29
|
-
* @param {import("../../types/cruise-result.mjs").IModule} pModule
|
|
30
|
-
* @returns {boolean}
|
|
31
|
-
*/
|
|
32
|
-
function matchesReachableRule(pRule, pModule) {
|
|
33
|
-
if (
|
|
34
|
-
Object.hasOwn(pRule?.to ?? {}, "reachable") &&
|
|
35
|
-
Object.hasOwn(pModule, "reachable")
|
|
36
|
-
) {
|
|
37
|
-
// @ts-expect-error the 'hasOwn' above ensures the 'reachable' exists
|
|
38
|
-
const lReachableRecord = pModule.reachable.find(
|
|
39
|
-
(pReachable) =>
|
|
40
|
-
pReachable.asDefinedInRule === pRule.name &&
|
|
41
|
-
// @ts-expect-error the 'hasOwn' above ensures the 'to.reachable' exists
|
|
42
|
-
pReachable.value === pRule.to.reachable,
|
|
43
|
-
);
|
|
44
|
-
if (lReachableRecord) {
|
|
45
|
-
const lGroups = extractGroups(pRule.from, lReachableRecord.matchedFrom);
|
|
46
|
-
|
|
47
|
-
return (
|
|
48
|
-
matchers.toModulePath(pRule, pModule, lGroups) &&
|
|
49
|
-
matchers.toModulePathNot(pRule, pModule, lGroups)
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Returns true if pRule is a 'reaches' rule and pModule matches the reachability
|
|
58
|
-
* criteria.
|
|
59
|
-
* Returns false in all other cases
|
|
60
|
-
*
|
|
61
|
-
* @param {import("../../types/rule-set.mjs").IAnyRuleType} pRule
|
|
62
|
-
* @param {import("../../types/cruise-result.mjs").IModule} pModule
|
|
63
|
-
* @returns {boolean}
|
|
64
|
-
*/
|
|
65
|
-
function matchesReachesRule(pRule, pModule) {
|
|
66
|
-
return (
|
|
67
|
-
Object.hasOwn(pRule?.to ?? {}, "reachable") &&
|
|
68
|
-
Object.hasOwn(pModule, "reaches") &&
|
|
69
|
-
// @ts-expect-error the 'hasOwn' above guarantees the .reaches exists
|
|
70
|
-
pModule.reaches.some(
|
|
71
|
-
(pReaches) =>
|
|
72
|
-
pReaches.asDefinedInRule === pRule.name &&
|
|
73
|
-
pReaches.modules.some(
|
|
74
|
-
(pReachesModule) =>
|
|
75
|
-
matchers.toModulePath(pRule, pReachesModule) &&
|
|
76
|
-
matchers.toModulePathNot(pRule, pReachesModule),
|
|
77
|
-
),
|
|
78
|
-
)
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
*
|
|
83
|
-
* @param {import("../../types/rule-set.mjs").IAnyRuleType} pRule
|
|
84
|
-
* @param {string[]} pDependents
|
|
85
|
-
* @returns {boolean}
|
|
86
|
-
*/
|
|
87
|
-
function dependentsCountsMatch(pRule, pDependents) {
|
|
88
|
-
const lMatchingDependentsCount = pDependents.filter(
|
|
89
|
-
(pDependent) =>
|
|
90
|
-
Boolean(!pRule.from.path || pDependent.match(pRule.from.path)) &&
|
|
91
|
-
Boolean(!pRule.from.pathNot || !pDependent.match(pRule.from.pathNot)),
|
|
92
|
-
).length;
|
|
93
|
-
return (
|
|
94
|
-
(!pRule.module.numberOfDependentsLessThan ||
|
|
95
|
-
lMatchingDependentsCount < pRule.module.numberOfDependentsLessThan) &&
|
|
96
|
-
(!pRule.module.numberOfDependentsMoreThan ||
|
|
97
|
-
lMatchingDependentsCount > pRule.module.numberOfDependentsMoreThan)
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
*
|
|
103
|
-
* @param {import("../../types/rule-set.mjs").IAnyRuleType} pRule
|
|
104
|
-
* @param {import("../../types/cruise-result.mjs").IModule} pModule
|
|
105
|
-
* @returns {boolean}
|
|
106
|
-
*/
|
|
107
|
-
// eslint-disable-next-line complexity
|
|
108
|
-
function matchesDependentsRule(pRule, pModule) {
|
|
109
|
-
if (
|
|
110
|
-
(Object.hasOwn(pModule, "dependents") &&
|
|
111
|
-
Object.hasOwn(pRule?.module ?? {}, "numberOfDependentsLessThan")) ||
|
|
112
|
-
Object.hasOwn(pRule?.module ?? {}, "numberOfDependentsMoreThan")
|
|
113
|
-
) {
|
|
114
|
-
return (
|
|
115
|
-
// group matching seems like a nice idea, however, the 'from' part of the
|
|
116
|
-
// rule is going to match not one module (as with regular dependency rules)
|
|
117
|
-
// but a whole bunch of them, being the 'dependents'. So that match is going
|
|
118
|
-
// to produce not one result, but one per matching dependent. To get meaningful
|
|
119
|
-
// results we'd probably have to loop over these and or the
|
|
120
|
-
// matchers.toModulePath together.
|
|
121
|
-
matchers.modulePath(pRule, pModule) &&
|
|
122
|
-
matchers.modulePathNot(pRule, pModule) &&
|
|
123
|
-
dependentsCountsMatch(pRule, pModule.dependents)
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
return false;
|
|
127
|
-
}
|
|
2
|
+
import {
|
|
3
|
+
matchesOrphanRule,
|
|
4
|
+
matchesReachableRule,
|
|
5
|
+
matchesReachesRule,
|
|
6
|
+
matchesDependentsRule,
|
|
7
|
+
} from "./match-module-rule-helpers.mjs";
|
|
128
8
|
|
|
129
9
|
/**
|
|
130
10
|
*
|
|
@@ -148,10 +28,6 @@ const isInteresting = (pRule) =>
|
|
|
148
28
|
isModuleOnlyRule(pRule) && !isFolderScope(pRule);
|
|
149
29
|
|
|
150
30
|
export default {
|
|
151
|
-
matchesOrphanRule,
|
|
152
|
-
matchesReachableRule,
|
|
153
|
-
matchesReachesRule,
|
|
154
|
-
matchesDependentsRule,
|
|
155
31
|
match,
|
|
156
32
|
isInteresting,
|
|
157
33
|
};
|