dependency-cruiser 17.3.3-beta-3 → 17.3.3-beta-4
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 +1 -1
- package/src/cache/find-content-changes.mjs +4 -1
- package/src/cli/init-config/build-config.mjs +6 -6
- package/src/cli/init-config/utl.mjs +1 -1
- package/src/enrich/derive/reachable.mjs +18 -10
- package/src/extract/resolve/index.mjs +3 -4
- package/src/extract/resolve/module-classifiers.mjs +6 -10
- package/src/extract/tsc/extract-typescript-deps.mjs +0 -1
- package/src/graph-utl/consolidate-to-pattern.mjs +7 -2
- package/src/graph-utl/match-facade.mjs +3 -1
- package/src/main/cruise.mjs +7 -1
- package/src/meta.cjs +1 -1
- package/src/report/anon/index.mjs +5 -2
- package/src/report/dot-webpage/svg-in-html-snippets/script.cjs +1 -1
- package/src/report/mermaid.mjs +4 -4
- package/src/report/plugins.mjs +1 -1
- package/src/report/teamcity.mjs +9 -9
- package/src/report/utl/index.mjs +2 -2
- package/src/utl/get-extension.mjs +1 -1
- package/src/utl/regex-util.mjs +24 -3
- package/src/utl/wrap-and-indent.mjs +1 -3
- package/src/validate/match-folder-dependency-rule.mjs +11 -6
- package/src/validate/match-module-rule-helpers.mjs +4 -4
- package/src/validate/matchers.mjs +21 -16
package/package.json
CHANGED
|
@@ -98,7 +98,10 @@ export default function findContentChanges(
|
|
|
98
98
|
);
|
|
99
99
|
|
|
100
100
|
bus.debug("cache: - get (new - cached)");
|
|
101
|
-
|
|
101
|
+
// eslint-disable-next-line budapestian/local-variable-pattern
|
|
102
|
+
for (const { name } of lDiffCachedVsNew) {
|
|
103
|
+
lFileSet.delete(name);
|
|
104
|
+
}
|
|
102
105
|
|
|
103
106
|
const lDiffNewVsCached = [];
|
|
104
107
|
for (const lFileName of lFileSet) {
|
|
@@ -45,8 +45,8 @@ function buildNotToTestRule(pInitOptions) {
|
|
|
45
45
|
}
|
|
46
46
|
},`;
|
|
47
47
|
return pInitOptions.hasTestsOutsideSource
|
|
48
|
-
? lNotToTestRule.
|
|
49
|
-
|
|
48
|
+
? lNotToTestRule.replaceAll(
|
|
49
|
+
"{{testLocationRE}}",
|
|
50
50
|
folderNameArrayToRE(pInitOptions?.testLocation ?? []),
|
|
51
51
|
)
|
|
52
52
|
: "";
|
|
@@ -211,12 +211,12 @@ function buildBuiltInModulesAttribute(pInitOptions) {
|
|
|
211
211
|
*/
|
|
212
212
|
export default function buildConfig(pInitOptions) {
|
|
213
213
|
return configTemplate
|
|
214
|
-
.
|
|
215
|
-
|
|
214
|
+
.replaceAll(
|
|
215
|
+
"{{sourceLocationRE}}",
|
|
216
216
|
folderNameArrayToRE(pInitOptions.sourceLocation),
|
|
217
217
|
)
|
|
218
|
-
.
|
|
219
|
-
|
|
218
|
+
.replaceAll(
|
|
219
|
+
"{{resolutionExtensionsAsString}}",
|
|
220
220
|
extensionsToString(pInitOptions.resolutionExtensions),
|
|
221
221
|
)
|
|
222
222
|
.replace("{{notToTestRule}}", buildNotToTestRule(pInitOptions))
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export function folderNameArrayToRE(pArrayOfStrings) {
|
|
7
7
|
const lFoldersInARE = pArrayOfStrings
|
|
8
|
-
.map((pName) => pName.
|
|
8
|
+
.map((pName) => pName.replaceAll("\\", "\\\\").replaceAll(".", "\\."))
|
|
9
9
|
.join("|");
|
|
10
10
|
|
|
11
11
|
return `^(${lFoldersInARE})`;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
/* eslint-disable security/detect-non-literal-regexp */
|
|
2
1
|
/* eslint-disable security/detect-object-injection, no-inline-comments */
|
|
3
2
|
import {
|
|
4
3
|
matchToModulePath,
|
|
5
4
|
matchToModulePathNot,
|
|
6
5
|
} from "#validate/matchers.mjs";
|
|
7
6
|
import IndexedModuleGraph from "#graph-utl/indexed-module-graph.mjs";
|
|
8
|
-
import { extractGroups } from "#utl/regex-util.mjs";
|
|
7
|
+
import { getCachedRegExp, extractGroups } from "#utl/regex-util.mjs";
|
|
9
8
|
|
|
10
9
|
function isReachableRule(pRule) {
|
|
11
10
|
return Object.hasOwn(pRule?.to ?? {}, "reachable");
|
|
@@ -19,16 +18,25 @@ function getReachableRules(pRuleSet) {
|
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
function isModuleInRuleFrom(pRule) {
|
|
21
|
+
const lRuleFrom = pRule.from ?? pRule.module;
|
|
22
|
+
if (!lRuleFrom) {
|
|
23
|
+
return () => false;
|
|
24
|
+
}
|
|
25
|
+
const lRuleFromPathRE = lRuleFrom.path
|
|
26
|
+
? getCachedRegExp(lRuleFrom.path)
|
|
27
|
+
: null;
|
|
28
|
+
const lRuleFromPathNotRE = lRuleFrom.pathNot
|
|
29
|
+
? getCachedRegExp(lRuleFrom.pathNot)
|
|
30
|
+
: null;
|
|
31
|
+
|
|
22
32
|
return (pModule) => {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
!new RegExp(lRuleFrom.pathNot).test(pModule.source))
|
|
29
|
-
);
|
|
33
|
+
if (lRuleFromPathRE && !lRuleFromPathRE.test(pModule.source)) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
if (lRuleFromPathNotRE && lRuleFromPathNotRE.test(pModule.source)) {
|
|
37
|
+
return false;
|
|
30
38
|
}
|
|
31
|
-
return
|
|
39
|
+
return true;
|
|
32
40
|
};
|
|
33
41
|
}
|
|
34
42
|
|
|
@@ -146,7 +146,7 @@ function resolveWithRetry(
|
|
|
146
146
|
lReturnValue.couldNotResolve &&
|
|
147
147
|
canBeResolvedToTsVariant(lStrippedModuleName)
|
|
148
148
|
) {
|
|
149
|
-
const lModuleWithoutExtension = lStrippedModuleName.
|
|
149
|
+
const lModuleWithoutExtension = lStrippedModuleName.replaceAll(
|
|
150
150
|
/\.(js|jsx|cjs|mjs)$/g,
|
|
151
151
|
"",
|
|
152
152
|
);
|
|
@@ -225,9 +225,8 @@ export default function resolve(
|
|
|
225
225
|
// enhanced-resolve inserts a NULL character in front of any `#` character.
|
|
226
226
|
// This wonky replace corrects that so the filename again corresponds
|
|
227
227
|
// with a real file on disk
|
|
228
|
-
const lResolvedEHRCorrected = lResolvedDependency.resolved.
|
|
229
|
-
|
|
230
|
-
/\u0000#/g,
|
|
228
|
+
const lResolvedEHRCorrected = lResolvedDependency.resolved.replaceAll(
|
|
229
|
+
"\u0000#",
|
|
231
230
|
"#",
|
|
232
231
|
);
|
|
233
232
|
const lResolvedYarnVirtual = resolveYarnVirtual(
|
|
@@ -3,9 +3,9 @@ import { isAbsolute, resolve as path_resolve } from "node:path";
|
|
|
3
3
|
import { join as posix_join } from "node:path/posix";
|
|
4
4
|
import picomatch from "picomatch";
|
|
5
5
|
import getExtension from "#utl/get-extension.mjs";
|
|
6
|
+
import { getCachedRegExp } from "#utl/regex-util.mjs";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
|
-
* @import { IResolveOptions } from "../../../types/resolve-options.mjs"
|
|
9
9
|
* @import { ITranspileOptions } from "../../../types/dependency-cruiser.mjs"
|
|
10
10
|
*/
|
|
11
11
|
|
|
@@ -108,10 +108,8 @@ function isSubpathImport(pModuleName, pManifest) {
|
|
|
108
108
|
// replacement only.
|
|
109
109
|
// Quoting https://nodejs.org/api/packages.html#subpath-imports :
|
|
110
110
|
// > "* maps expose nested subpaths as it is a string replacement syntax only"
|
|
111
|
-
const lMatchREasString = pImportLHS.
|
|
112
|
-
|
|
113
|
-
const lMatchRE = new RegExp(`^${lMatchREasString}$`);
|
|
114
|
-
return lMatchRE.test(pModuleName);
|
|
111
|
+
const lMatchREasString = pImportLHS.replaceAll("*", ".+");
|
|
112
|
+
return getCachedRegExp(`^${lMatchREasString}$`).test(pModuleName);
|
|
115
113
|
})
|
|
116
114
|
);
|
|
117
115
|
}
|
|
@@ -226,11 +224,9 @@ function matchesTSConfigPaths(pModuleName, pPaths) {
|
|
|
226
224
|
//
|
|
227
225
|
// TODO: 'any string' - does this include the empty string as well? Checks seem
|
|
228
226
|
// to indicate it doesn't, so we use `.+` instead of `.*`
|
|
229
|
-
return Object.keys(pPaths).some((pPathLHS) =>
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
return lMatchRE.test(pModuleName);
|
|
233
|
-
});
|
|
227
|
+
return Object.keys(pPaths).some((pPathLHS) =>
|
|
228
|
+
getCachedRegExp(`^${pPathLHS.replaceAll("*", ".+")}$`).test(pModuleName),
|
|
229
|
+
);
|
|
234
230
|
}
|
|
235
231
|
|
|
236
232
|
function stripExtension(pModulePath) {
|
|
@@ -560,7 +560,6 @@ export default function extractTypeScriptDependencies(
|
|
|
560
560
|
pDetectJSDocImports,
|
|
561
561
|
pDetectProcessBuiltinModuleCalls,
|
|
562
562
|
) {
|
|
563
|
-
// console.dir(pTypeScriptAST, { depth: 100 });
|
|
564
563
|
return typescript
|
|
565
564
|
? extractImports(pTypeScriptAST)
|
|
566
565
|
.concat(extractExports(pTypeScriptAST))
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import consolidateModules from "./consolidate-modules.mjs";
|
|
2
2
|
import consolidateModuleDependencies from "./consolidate-module-dependencies.mjs";
|
|
3
|
+
import { getCachedRegExp } from "#utl/regex-util.mjs";
|
|
3
4
|
|
|
4
5
|
function squashDependencyToPattern(pCollapsePattern) {
|
|
5
6
|
return (pDependency) => {
|
|
6
|
-
const lCollapseMatch =
|
|
7
|
+
const lCollapseMatch = getCachedRegExp(pCollapsePattern).exec(
|
|
8
|
+
pDependency.resolved,
|
|
9
|
+
);
|
|
7
10
|
|
|
8
11
|
return {
|
|
9
12
|
...pDependency,
|
|
@@ -27,7 +30,9 @@ function determineConsolidatedness(pConsolidated, pCollapseMatch, pSource) {
|
|
|
27
30
|
|
|
28
31
|
function squashModuleToPattern(pCollapsePattern) {
|
|
29
32
|
return (pModule) => {
|
|
30
|
-
const lCollapseMatch =
|
|
33
|
+
const lCollapseMatch = getCachedRegExp(pCollapsePattern).exec(
|
|
34
|
+
pModule.source,
|
|
35
|
+
);
|
|
31
36
|
|
|
32
37
|
return {
|
|
33
38
|
...pModule,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { getCachedRegExp } from "#utl/regex-util.mjs";
|
|
2
|
+
|
|
1
3
|
export function filenameMatchesPattern(pFullPathToFile, pPattern) {
|
|
2
|
-
return
|
|
4
|
+
return getCachedRegExp(pPattern).test(pFullPathToFile);
|
|
3
5
|
}
|
|
4
6
|
|
|
5
7
|
export function moduleMatchesFilter(pModule, pFilter) {
|
package/src/main/cruise.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import { assertCruiseOptionsValid } from "./options/assert-validity.mjs";
|
|
|
3
3
|
import { normalizeCruiseOptions } from "./options/normalize.mjs";
|
|
4
4
|
import reportWrap from "./report-wrap.mjs";
|
|
5
5
|
import { bus } from "#utl/bus.mjs";
|
|
6
|
+
import { clearRegExpCache } from "#utl/regex-util.mjs";
|
|
6
7
|
|
|
7
8
|
const TOTAL_STEPS = 10;
|
|
8
9
|
|
|
@@ -104,5 +105,10 @@ export default async function cruise(
|
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
bus.summary("report", c(9));
|
|
107
|
-
|
|
108
|
+
const lResult = await reportWrap(lCruiseResult, lCruiseOptions);
|
|
109
|
+
|
|
110
|
+
bus.debug("clear regex cache");
|
|
111
|
+
clearRegExpCache();
|
|
112
|
+
|
|
113
|
+
return lResult;
|
|
108
114
|
}
|
package/src/meta.cjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { clearCache } from "./anonymize-path-element.mjs";
|
|
1
2
|
import { anonymizePath, WHITELIST_RE } from "./anonymize-path.mjs";
|
|
2
3
|
|
|
3
4
|
const EOL = "\n";
|
|
@@ -148,7 +149,7 @@ function anonymize(pResults, pWordList) {
|
|
|
148
149
|
|
|
149
150
|
function sanitizeWordList(pWordList) {
|
|
150
151
|
return pWordList
|
|
151
|
-
.map((pString) => pString.
|
|
152
|
+
.map((pString) => pString.replaceAll(/[^a-zA-Z-]/g, "_"))
|
|
152
153
|
.filter(
|
|
153
154
|
(pString) =>
|
|
154
155
|
/^[a-zA-Z-_]+$/g.test(pString) && !WHITELIST_RE.test(pString),
|
|
@@ -184,7 +185,7 @@ export default function reportAnonymous(pResults, pAnonymousReporterOptions) {
|
|
|
184
185
|
lAnonymousReporterOptions.wordlist =
|
|
185
186
|
pResults?.summary?.optionsUsed?.reporterOptions?.anon?.wordlist ?? [];
|
|
186
187
|
}
|
|
187
|
-
|
|
188
|
+
const lReturnValue = {
|
|
188
189
|
output:
|
|
189
190
|
JSON.stringify(
|
|
190
191
|
anonymize(
|
|
@@ -196,4 +197,6 @@ export default function reportAnonymous(pResults, pAnonymousReporterOptions) {
|
|
|
196
197
|
) + EOL,
|
|
197
198
|
exitCode: 0,
|
|
198
199
|
};
|
|
200
|
+
clearCache();
|
|
201
|
+
return lReturnValue;
|
|
199
202
|
}
|
|
@@ -270,7 +270,7 @@ function skewLineABit(lDrawingInstructions) {
|
|
|
270
270
|
// Even this value is so small that it is not visible to the
|
|
271
271
|
// human eye (tested with the two I have at my disposal).
|
|
272
272
|
var lIncrement = 0.001;
|
|
273
|
-
var lNewLastValue = parseFloat(lLastValue) + lIncrement;
|
|
273
|
+
var lNewLastValue = Number.parseFloat(lLastValue) + lIncrement;
|
|
274
274
|
|
|
275
275
|
return lDrawingInstructions.replace(lLastValue, lNewLastValue);
|
|
276
276
|
}
|
package/src/report/mermaid.mjs
CHANGED
|
@@ -106,10 +106,10 @@ function focusHighlights(pModules, pNamesHashMap) {
|
|
|
106
106
|
|
|
107
107
|
const hashToReadableNodeName = (pNode) =>
|
|
108
108
|
pNode
|
|
109
|
-
.
|
|
110
|
-
.
|
|
111
|
-
.
|
|
112
|
-
.
|
|
109
|
+
.replaceAll(ACORN_DUMMY_VALUE, "__unknown__")
|
|
110
|
+
.replaceAll(/^\.$|^\.\//g, "__currentPath__")
|
|
111
|
+
.replaceAll(/^\.{2}$|^\.{2}\//g, "__prevPath__")
|
|
112
|
+
.replaceAll(/[[\]/.@~-]/g, "_");
|
|
113
113
|
|
|
114
114
|
/**
|
|
115
115
|
* @param {import("../../types/cruise-result").IModule[]} pModules
|
package/src/report/plugins.mjs
CHANGED
|
@@ -43,7 +43,7 @@ async function getPluginReporter(pOutputType) {
|
|
|
43
43
|
|
|
44
44
|
export function getExternalPluginReporter(pOutputType) {
|
|
45
45
|
const lPluginPatternRE = /^plugin:(?<pluginName>.+)$/;
|
|
46
|
-
const lPluginMatch = (pOutputType || "")
|
|
46
|
+
const lPluginMatch = lPluginPatternRE.exec(pOutputType || "");
|
|
47
47
|
|
|
48
48
|
if (lPluginMatch?.groups) {
|
|
49
49
|
return getPluginReporter(lPluginMatch.groups.pluginName);
|
package/src/report/teamcity.mjs
CHANGED
|
@@ -19,18 +19,18 @@ function escape(pMessageString) {
|
|
|
19
19
|
return (
|
|
20
20
|
pMessageString
|
|
21
21
|
.toString()
|
|
22
|
-
.
|
|
23
|
-
.
|
|
24
|
-
.
|
|
25
|
-
.
|
|
26
|
-
.
|
|
22
|
+
.replaceAll("|", "||")
|
|
23
|
+
.replaceAll("\n", "|n")
|
|
24
|
+
.replaceAll("\r", "|r")
|
|
25
|
+
.replaceAll("[", "|[")
|
|
26
|
+
.replaceAll("]", "|]")
|
|
27
27
|
// next line
|
|
28
|
-
.
|
|
28
|
+
.replaceAll("\u0085", "|x")
|
|
29
29
|
// line separator
|
|
30
|
-
.
|
|
30
|
+
.replaceAll("\u2028", "|l")
|
|
31
31
|
// paragraph separator
|
|
32
|
-
.
|
|
33
|
-
.
|
|
32
|
+
.replaceAll("\u2029", "|p")
|
|
33
|
+
.replaceAll("'", "|'")
|
|
34
34
|
);
|
|
35
35
|
}
|
|
36
36
|
|
package/src/report/utl/index.mjs
CHANGED
|
@@ -48,7 +48,7 @@ function smartURIConcat(pPrefix, pSource) {
|
|
|
48
48
|
function deriveExternalPackageName(pSource) {
|
|
49
49
|
const lRE =
|
|
50
50
|
/node_modules\/(?<packageName>[^@][^/]+)|(?<atPackageName>@[^/]+\/[^/]+)/;
|
|
51
|
-
const lMatch =
|
|
51
|
+
const lMatch = lRE.exec(pSource);
|
|
52
52
|
if (lMatch) {
|
|
53
53
|
return lMatch.groups.packageName || lMatch.groups.atPackageName;
|
|
54
54
|
}
|
|
@@ -72,7 +72,7 @@ function deriveCorePackageName(pSource) {
|
|
|
72
72
|
*/
|
|
73
73
|
export function getURLForModule(pModule, pPrefix, pSuffix) {
|
|
74
74
|
// TODO: derive the URLs from configuration
|
|
75
|
-
if (pModule.dependencyTypes?.
|
|
75
|
+
if (pModule.dependencyTypes?.includes("core")) {
|
|
76
76
|
const lPackageName = deriveCorePackageName(pModule.source);
|
|
77
77
|
// Check if it's a Bun core module (starts with bun:)
|
|
78
78
|
if (lPackageName.startsWith("bun:")) {
|
|
@@ -16,7 +16,7 @@ const EXTENSION_RE = /(?<extension>(?:(?:\.d\.(?:[cm])?ts)|\.coffee\.md)$)/;
|
|
|
16
16
|
* @return {string} extension
|
|
17
17
|
*/
|
|
18
18
|
export default function getExtension(pFileName) {
|
|
19
|
-
const lMatchResult =
|
|
19
|
+
const lMatchResult = EXTENSION_RE.exec(pFileName);
|
|
20
20
|
|
|
21
21
|
return lMatchResult?.groups?.extension ?? extname(pFileName);
|
|
22
22
|
}
|
package/src/utl/regex-util.mjs
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
/* eslint-disable security/detect-non-literal-regexp */
|
|
2
|
+
const REGEXP_CACHE = new Map();
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Returns a cached RegExp instance for the given pattern.
|
|
6
|
+
*
|
|
7
|
+
* See ./regex-cache.md for design considerations
|
|
8
|
+
*
|
|
9
|
+
* @param {string} pPattern
|
|
10
|
+
* @returns {RegExp}
|
|
11
|
+
*/
|
|
12
|
+
export function getCachedRegExp(pPattern) {
|
|
13
|
+
if (!REGEXP_CACHE.has(pPattern)) {
|
|
14
|
+
REGEXP_CACHE.set(pPattern, new RegExp(pPattern));
|
|
15
|
+
}
|
|
16
|
+
return REGEXP_CACHE.get(pPattern);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function clearRegExpCache() {
|
|
20
|
+
REGEXP_CACHE.clear();
|
|
21
|
+
}
|
|
22
|
+
|
|
1
23
|
/**
|
|
2
24
|
* If there is at least one group expression in the given pRulePath
|
|
3
25
|
* return the first matched one.
|
|
@@ -19,7 +41,7 @@ export function extractGroups(pFromRestriction, pActualPath) {
|
|
|
19
41
|
// except before it enters here it has already been 'normalized' to a string
|
|
20
42
|
// so it can be safely passed to match. The right solution here (TODO)
|
|
21
43
|
// is to create a separate type for NormalizedFromRestriction
|
|
22
|
-
let lMatchResult =
|
|
44
|
+
let lMatchResult = getCachedRegExp(pFromRestriction.path).exec(pActualPath);
|
|
23
45
|
|
|
24
46
|
if (lMatchResult && lMatchResult.length > 1) {
|
|
25
47
|
lReturnValue = lMatchResult.filter(
|
|
@@ -49,8 +71,7 @@ export function extractGroups(pFromRestriction, pActualPath) {
|
|
|
49
71
|
export function replaceGroupPlaceholders(pString, pExtractedGroups) {
|
|
50
72
|
return pExtractedGroups.reduce(
|
|
51
73
|
(pAll, pThis, pIndex) =>
|
|
52
|
-
|
|
53
|
-
pAll.replace(new RegExp(`\\$${pIndex}`, "g"), pThis),
|
|
74
|
+
pAll.replaceAll(new RegExp(`\\$${pIndex}`, "g"), pThis),
|
|
54
75
|
pString,
|
|
55
76
|
);
|
|
56
77
|
}
|
|
@@ -1,23 +1,28 @@
|
|
|
1
|
-
/* eslint-disable security/detect-non-literal-regexp */
|
|
2
1
|
import { isModuleOnlyRule, isFolderScope } from "./rule-classifiers.mjs";
|
|
3
2
|
import { propertyEquals, matchesToIsMoreUnstable } from "./matchers.mjs";
|
|
4
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
getCachedRegExp,
|
|
5
|
+
extractGroups,
|
|
6
|
+
replaceGroupPlaceholders,
|
|
7
|
+
} from "#utl/regex-util.mjs";
|
|
5
8
|
|
|
6
9
|
function fromFolderPath(pRule, pFromFolder) {
|
|
7
|
-
return
|
|
10
|
+
return (
|
|
11
|
+
!pRule.from.path || getCachedRegExp(pRule.from.path).test(pFromFolder.name)
|
|
12
|
+
);
|
|
8
13
|
}
|
|
9
14
|
|
|
10
15
|
function fromFolderPathNot(pRule, pFromFolder) {
|
|
11
16
|
return (
|
|
12
17
|
!pRule.from.pathNot ||
|
|
13
|
-
!
|
|
18
|
+
!getCachedRegExp(pRule.from.pathNot).test(pFromFolder.name)
|
|
14
19
|
);
|
|
15
20
|
}
|
|
16
21
|
|
|
17
22
|
function toFolderPath(pRule, pToFolder, pGroups) {
|
|
18
23
|
return (
|
|
19
24
|
!pRule.to.path ||
|
|
20
|
-
|
|
25
|
+
getCachedRegExp(replaceGroupPlaceholders(pRule.to.path, pGroups)).test(
|
|
21
26
|
pToFolder.name,
|
|
22
27
|
)
|
|
23
28
|
);
|
|
@@ -26,7 +31,7 @@ function toFolderPath(pRule, pToFolder, pGroups) {
|
|
|
26
31
|
function toFolderPathNot(pRule, pToFolder, pGroups) {
|
|
27
32
|
return (
|
|
28
33
|
!pRule.to.pathNot ||
|
|
29
|
-
!
|
|
34
|
+
!getCachedRegExp(replaceGroupPlaceholders(pRule.to.pathNot, pGroups)).test(
|
|
30
35
|
pToFolder.name,
|
|
31
36
|
)
|
|
32
37
|
);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable security/detect-non-literal-regexp */
|
|
2
1
|
import {
|
|
3
2
|
matchToModulePath,
|
|
4
3
|
matchToModulePathNot,
|
|
@@ -7,7 +6,7 @@ import {
|
|
|
7
6
|
matchesModulePath,
|
|
8
7
|
matchesModulePathNot,
|
|
9
8
|
} from "./matchers.mjs";
|
|
10
|
-
import { extractGroups } from "#utl/regex-util.mjs";
|
|
9
|
+
import { getCachedRegExp, extractGroups } from "#utl/regex-util.mjs";
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* @import { IModule } from "../../types/cruise-result.mjs";
|
|
@@ -99,8 +98,9 @@ export function matchesReachesRule(pRule, pModule) {
|
|
|
99
98
|
function dependentsCountsMatch(pRule, pDependents) {
|
|
100
99
|
const lMatchingDependentsCount = pDependents.filter(
|
|
101
100
|
(pDependent) =>
|
|
102
|
-
(!pRule.from.path ||
|
|
103
|
-
(!pRule.from.pathNot ||
|
|
101
|
+
(!pRule.from.path || getCachedRegExp(pRule.from.path).test(pDependent)) &&
|
|
102
|
+
(!pRule.from.pathNot ||
|
|
103
|
+
!getCachedRegExp(pRule.from.pathNot).test(pDependent)),
|
|
104
104
|
).length;
|
|
105
105
|
return (
|
|
106
106
|
(!pRule.module.numberOfDependentsLessThan ||
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
/* eslint-disable security/detect-non-literal-regexp */
|
|
2
1
|
/* eslint-disable security/detect-object-injection */
|
|
3
2
|
import { dirname, resolve, sep } from "node:path/posix";
|
|
4
|
-
import { replaceGroupPlaceholders } from "#utl/regex-util.mjs";
|
|
3
|
+
import { getCachedRegExp, replaceGroupPlaceholders } from "#utl/regex-util.mjs";
|
|
5
4
|
import { intersects } from "#utl/array-util.mjs";
|
|
6
5
|
|
|
7
6
|
// by their nature some dependency types always occur alongside other
|
|
@@ -33,7 +32,7 @@ export function propertyMatches(pRule, pDependency, pRuleProperty, pProperty) {
|
|
|
33
32
|
return (
|
|
34
33
|
!pRule.to[pRuleProperty] ||
|
|
35
34
|
(pDependency[pProperty] &&
|
|
36
|
-
|
|
35
|
+
getCachedRegExp(pRule.to[pRuleProperty]).test(pDependency[pProperty]))
|
|
37
36
|
);
|
|
38
37
|
}
|
|
39
38
|
|
|
@@ -46,37 +45,43 @@ export function propertyMatchesNot(
|
|
|
46
45
|
return (
|
|
47
46
|
!pRule.to[pRuleProperty] ||
|
|
48
47
|
(pDependency[pProperty] &&
|
|
49
|
-
!
|
|
48
|
+
!getCachedRegExp(pRule.to[pRuleProperty]).test(pDependency[pProperty]))
|
|
50
49
|
);
|
|
51
50
|
}
|
|
52
51
|
|
|
53
52
|
export function matchesFromPath(pRule, pModule) {
|
|
54
|
-
return
|
|
53
|
+
return (
|
|
54
|
+
!pRule.from.path || getCachedRegExp(pRule.from.path).test(pModule.source)
|
|
55
|
+
);
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
export function matchesFromPathNot(pRule, pModule) {
|
|
58
59
|
return (
|
|
59
|
-
!pRule.from.pathNot ||
|
|
60
|
+
!pRule.from.pathNot ||
|
|
61
|
+
!getCachedRegExp(pRule.from.pathNot).test(pModule.source)
|
|
60
62
|
);
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
export function matchesModulePath(pRule, pModule) {
|
|
64
66
|
return (
|
|
65
|
-
!pRule.module.path ||
|
|
67
|
+
!pRule.module.path ||
|
|
68
|
+
getCachedRegExp(pRule.module.path).test(pModule.source)
|
|
66
69
|
);
|
|
67
70
|
}
|
|
68
71
|
|
|
69
72
|
export function matchesModulePathNot(pRule, pModule) {
|
|
70
73
|
return (
|
|
71
74
|
!pRule.module.pathNot ||
|
|
72
|
-
!
|
|
75
|
+
!getCachedRegExp(pRule.module.pathNot).test(pModule.source)
|
|
73
76
|
);
|
|
74
77
|
}
|
|
75
78
|
|
|
76
79
|
function _matchesToPath(pRule, pString, pGroups = []) {
|
|
77
80
|
return (
|
|
78
81
|
!pRule.to.path ||
|
|
79
|
-
|
|
82
|
+
getCachedRegExp(replaceGroupPlaceholders(pRule.to.path, pGroups)).test(
|
|
83
|
+
pString,
|
|
84
|
+
)
|
|
80
85
|
);
|
|
81
86
|
}
|
|
82
87
|
|
|
@@ -91,7 +96,7 @@ export function matchToModulePath(pRule, pModule, pGroups) {
|
|
|
91
96
|
function _matchesToPathNot(pRule, pString, pGroups = []) {
|
|
92
97
|
return (
|
|
93
98
|
!pRule.to.pathNot ||
|
|
94
|
-
!
|
|
99
|
+
!getCachedRegExp(replaceGroupPlaceholders(pRule.to.pathNot, pGroups)).test(
|
|
95
100
|
pString,
|
|
96
101
|
)
|
|
97
102
|
);
|
|
@@ -124,14 +129,14 @@ export function matchesToVia(pRule, pDependency, pGroups) {
|
|
|
124
129
|
if (pRule.to.via && pDependency.cycle) {
|
|
125
130
|
if (pRule.to.via.path) {
|
|
126
131
|
lReturnValue = pDependency.cycle.some(({ name }) =>
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
),
|
|
132
|
+
getCachedRegExp(
|
|
133
|
+
replaceGroupPlaceholders(pRule.to.via.path, pGroups),
|
|
134
|
+
).test(name),
|
|
130
135
|
);
|
|
131
136
|
}
|
|
132
137
|
if (pRule.to.via.pathNot) {
|
|
133
138
|
lReturnValue = !pDependency.cycle.every(({ name }) =>
|
|
134
|
-
|
|
139
|
+
getCachedRegExp(
|
|
135
140
|
replaceGroupPlaceholders(pRule.to.via.pathNot, pGroups),
|
|
136
141
|
).test(name),
|
|
137
142
|
);
|
|
@@ -159,14 +164,14 @@ export function matchesToViaOnly(pRule, pDependency, pGroups) {
|
|
|
159
164
|
if (pRule.to.viaOnly && pDependency.cycle) {
|
|
160
165
|
if (pRule.to.viaOnly.path) {
|
|
161
166
|
lReturnValue = pDependency.cycle.every(({ name }) =>
|
|
162
|
-
|
|
167
|
+
getCachedRegExp(
|
|
163
168
|
replaceGroupPlaceholders(pRule.to.viaOnly.path, pGroups),
|
|
164
169
|
).test(name),
|
|
165
170
|
);
|
|
166
171
|
}
|
|
167
172
|
if (pRule.to.viaOnly.pathNot) {
|
|
168
173
|
lReturnValue = !pDependency.cycle.some(({ name }) =>
|
|
169
|
-
|
|
174
|
+
getCachedRegExp(
|
|
170
175
|
replaceGroupPlaceholders(pRule.to.viaOnly.pathNot, pGroups),
|
|
171
176
|
).test(name),
|
|
172
177
|
);
|