dependency-cruiser 17.3.1 → 17.3.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 +1 -9
- package/src/cache/content-strategy.mjs +9 -9
- package/src/cache/find-content-changes.mjs +1 -0
- package/src/cli/index.mjs +10 -15
- package/src/cli/init-config/normalize-init-options.mjs +5 -5
- package/src/enrich/derive/{dependents/index.mjs → dependents.mjs} +9 -2
- package/src/enrich/derive/reachable.mjs +18 -14
- package/src/enrich/enrich-modules.mjs +1 -1
- package/src/extract/gather-initial-sources.mjs +16 -14
- package/src/graph-utl/indexed-module-graph.mjs +21 -19
- package/src/main/resolve-options/normalize.mjs +2 -3
- package/src/meta.cjs +1 -1
- package/src/utl/find-all-files.mjs +20 -28
- package/src/validate/match-folder-dependency-rule.mjs +2 -4
- package/src/validate/matchers.mjs +7 -7
- package/types/strict-restrictions.d.mts +4 -8
- package/types/strict-rule-set.d.mts +2 -4
- package/src/enrich/derive/dependents/get-dependents.mjs +0 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dependency-cruiser",
|
|
3
|
-
"version": "17.3.
|
|
3
|
+
"version": "17.3.2",
|
|
4
4
|
"description": "Validate and visualize dependencies. With your rules. JavaScript, TypeScript, CoffeeScript. ES6, CommonJS, AMD.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"static analysis",
|
|
@@ -163,14 +163,6 @@
|
|
|
163
163
|
"tsconfig-paths-webpack-plugin": "4.2.0",
|
|
164
164
|
"watskeburt": "5.0.0"
|
|
165
165
|
},
|
|
166
|
-
"overrides": {
|
|
167
|
-
"cross-spawn": ">=6.0.6",
|
|
168
|
-
"nanoid": "^3.3.8"
|
|
169
|
-
},
|
|
170
|
-
"resolutions": {
|
|
171
|
-
"cross-spawn": ">=6.0.6",
|
|
172
|
-
"nanoid": "^3.3.8"
|
|
173
|
-
},
|
|
174
166
|
"engines": {
|
|
175
167
|
"node": "^20.12||^22||>=24"
|
|
176
168
|
},
|
|
@@ -87,15 +87,15 @@ export default class ContentStrategy {
|
|
|
87
87
|
revisionDataEqual(pExistingRevisionData, pNewRevisionData) {
|
|
88
88
|
return Boolean(
|
|
89
89
|
pExistingRevisionData &&
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
90
|
+
pNewRevisionData &&
|
|
91
|
+
// Even though we don't really have a SHA1, it might be the previous version
|
|
92
|
+
// of the cache did, e.g. because it was rendered with the metadata cache
|
|
93
|
+
// strategy. In that case the SHA1 comparison is a reliable, fast bailout.
|
|
94
|
+
pExistingRevisionData.SHA1 === pNewRevisionData.SHA1 &&
|
|
95
|
+
isDeepStrictEqual(
|
|
96
|
+
pExistingRevisionData.changes,
|
|
97
|
+
pNewRevisionData.changes,
|
|
98
|
+
),
|
|
99
99
|
);
|
|
100
100
|
}
|
|
101
101
|
|
package/src/cli/index.mjs
CHANGED
|
@@ -20,9 +20,8 @@ async function extractResolveOptions(pCruiseOptions) {
|
|
|
20
20
|
pCruiseOptions?.ruleSet?.options?.webpackConfig?.fileName ?? null;
|
|
21
21
|
|
|
22
22
|
if (lWebPackConfigFileName) {
|
|
23
|
-
const { default: extractWebpackResolveConfig } =
|
|
24
|
-
"#config-utl/extract-webpack-resolve-config.mjs"
|
|
25
|
-
);
|
|
23
|
+
const { default: extractWebpackResolveConfig } =
|
|
24
|
+
await import("#config-utl/extract-webpack-resolve-config.mjs");
|
|
26
25
|
lResolveOptions = await extractWebpackResolveConfig(
|
|
27
26
|
lWebPackConfigFileName,
|
|
28
27
|
pCruiseOptions?.ruleSet?.options?.webpackConfig?.env ?? null,
|
|
@@ -34,9 +33,8 @@ async function extractResolveOptions(pCruiseOptions) {
|
|
|
34
33
|
|
|
35
34
|
async function addKnownViolations(pCruiseOptions) {
|
|
36
35
|
if (pCruiseOptions.knownViolationsFile) {
|
|
37
|
-
const { default: extractKnownViolations } =
|
|
38
|
-
"#config-utl/extract-known-violations.mjs"
|
|
39
|
-
);
|
|
36
|
+
const { default: extractKnownViolations } =
|
|
37
|
+
await import("#config-utl/extract-known-violations.mjs");
|
|
40
38
|
const lKnownViolations = await extractKnownViolations(
|
|
41
39
|
pCruiseOptions.knownViolationsFile,
|
|
42
40
|
);
|
|
@@ -56,9 +54,8 @@ async function extractTSConfigOptions(pCruiseOptions) {
|
|
|
56
54
|
pCruiseOptions?.ruleSet?.options?.tsConfig?.fileName ?? null;
|
|
57
55
|
|
|
58
56
|
if (lTSConfigFileName) {
|
|
59
|
-
const { default: extractTSConfig } =
|
|
60
|
-
"#config-utl/extract-ts-config.mjs"
|
|
61
|
-
);
|
|
57
|
+
const { default: extractTSConfig } =
|
|
58
|
+
await import("#config-utl/extract-ts-config.mjs");
|
|
62
59
|
lReturnValue = extractTSConfig(lTSConfigFileName);
|
|
63
60
|
}
|
|
64
61
|
|
|
@@ -70,9 +67,8 @@ async function extractBabelConfigOptions(pCruiseOptions) {
|
|
|
70
67
|
const lBabelConfigFileName =
|
|
71
68
|
pCruiseOptions?.ruleSet?.options?.babelConfig?.fileName ?? null;
|
|
72
69
|
if (lBabelConfigFileName) {
|
|
73
|
-
const { default: extractBabelConfig } =
|
|
74
|
-
"#config-utl/extract-babel-config.mjs"
|
|
75
|
-
);
|
|
70
|
+
const { default: extractBabelConfig } =
|
|
71
|
+
await import("#config-utl/extract-babel-config.mjs");
|
|
76
72
|
lReturnValue = extractBabelConfig(lBabelConfigFileName);
|
|
77
73
|
}
|
|
78
74
|
|
|
@@ -177,9 +173,8 @@ export default async function executeCli(
|
|
|
177
173
|
}
|
|
178
174
|
/* c8 ignore stop */
|
|
179
175
|
if (lCruiseOptions.info === true) {
|
|
180
|
-
const { default: formatMetaInfo } =
|
|
181
|
-
"./format-meta-info.mjs"
|
|
182
|
-
);
|
|
176
|
+
const { default: formatMetaInfo } =
|
|
177
|
+
await import("./format-meta-info.mjs");
|
|
183
178
|
lStreams.stdout.write(await formatMetaInfo());
|
|
184
179
|
} else if (lCruiseOptions.init) {
|
|
185
180
|
const { default: initConfig } = await import("./init-config/index.mjs");
|
|
@@ -19,12 +19,12 @@ import meta from "#meta.cjs";
|
|
|
19
19
|
function usesTypeScript(pInitOptions, pExtensions) {
|
|
20
20
|
return Boolean(
|
|
21
21
|
pInitOptions.tsConfig ||
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
),
|
|
22
|
+
pInitOptions.tsPreCompilationDeps ||
|
|
23
|
+
(pExtensions || []).some((pExtension) =>
|
|
24
|
+
[".ts", ".tsx", ".d.ts", ".mts", ".d.mts", ".cts", ".d.cts"].includes(
|
|
25
|
+
pExtension,
|
|
27
26
|
),
|
|
27
|
+
),
|
|
28
28
|
);
|
|
29
29
|
}
|
|
30
30
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { isDependent } from "./module-utl.mjs";
|
|
2
2
|
|
|
3
|
-
/** @import { IFlattenedRuleSet } from "
|
|
3
|
+
/** @import { IFlattenedRuleSet } from "../../../types/rule-set.mjs" */
|
|
4
4
|
|
|
5
5
|
function isDependentsRule(pRule) {
|
|
6
6
|
// used in folder rules and when moreUnstable is in the 'to' => governed by
|
|
@@ -16,6 +16,13 @@ function isDependentsRule(pRule) {
|
|
|
16
16
|
);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
export function getDependents(pModule, pModules) {
|
|
20
|
+
// perf between O(n) in an unconnected graph and O(n^2) in a fully connected one
|
|
21
|
+
return pModules
|
|
22
|
+
.filter(isDependent(pModule.source))
|
|
23
|
+
.map((pDependentModule) => pDependentModule.source);
|
|
24
|
+
}
|
|
25
|
+
|
|
19
26
|
/**
|
|
20
27
|
* @param {IFlattenedRuleSet} pRuleSet
|
|
21
28
|
* @returns {boolean}
|
|
@@ -171,25 +171,29 @@ function addReachabilityToGraph(pGraph, pIndexedGraph, pReachableRule) {
|
|
|
171
171
|
const lFromModules = pGraph.filter(isModuleInRuleFrom(pReachableRule));
|
|
172
172
|
|
|
173
173
|
return pGraph.map((pModule) => {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
174
|
+
// strictly speaking we should clone pModule to prevent mutating it,
|
|
175
|
+
// but in practice this function is called with a structuredClone'd graph
|
|
176
|
+
// anyway and the (reference only) copy we use now is faster (observable
|
|
177
|
+
// even on dependency-cruiser's self scan) and less memory intentsive.
|
|
178
|
+
let lModule = pModule;
|
|
179
|
+
|
|
180
|
+
if (shouldAddReaches(pReachableRule, lModule)) {
|
|
181
|
+
lModule = addReachesToModule(
|
|
182
|
+
lModule,
|
|
179
183
|
pGraph,
|
|
180
184
|
pIndexedGraph,
|
|
181
185
|
pReachableRule,
|
|
182
186
|
);
|
|
183
187
|
}
|
|
184
|
-
if (shouldAddReachable(pReachableRule,
|
|
185
|
-
|
|
186
|
-
|
|
188
|
+
if (shouldAddReachable(pReachableRule, lModule, pGraph)) {
|
|
189
|
+
lModule = addReachableToModule(
|
|
190
|
+
lModule,
|
|
187
191
|
pIndexedGraph,
|
|
188
192
|
pReachableRule,
|
|
189
193
|
lFromModules,
|
|
190
194
|
);
|
|
191
195
|
}
|
|
192
|
-
return
|
|
196
|
+
return lModule;
|
|
193
197
|
});
|
|
194
198
|
}
|
|
195
199
|
|
|
@@ -199,11 +203,11 @@ export default function deriveReachables(pGraph, pRuleSet) {
|
|
|
199
203
|
if (lReachableRules.length > 0) {
|
|
200
204
|
const lIndexedGraph = new IndexedModuleGraph(pGraph);
|
|
201
205
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
206
|
+
let lResultGraph = structuredClone(pGraph);
|
|
207
|
+
for (const lRule of lReachableRules) {
|
|
208
|
+
lResultGraph = addReachabilityToGraph(lResultGraph, lIndexedGraph, lRule);
|
|
209
|
+
}
|
|
210
|
+
return lResultGraph;
|
|
207
211
|
}
|
|
208
212
|
return pGraph;
|
|
209
213
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import deriveCycles from "./derive/circular.mjs";
|
|
2
2
|
import deriveOrphans from "./derive/orphan/index.mjs";
|
|
3
|
-
import addDependents from "./derive/dependents
|
|
3
|
+
import addDependents from "./derive/dependents.mjs";
|
|
4
4
|
import deriveReachable from "./derive/reachable.mjs";
|
|
5
5
|
import addValidations from "./add-validations.mjs";
|
|
6
6
|
import softenKnownViolations from "./soften-known-violations.mjs";
|
|
@@ -31,12 +31,12 @@ function shouldBeIncluded(pFullPathToFile, pOptions) {
|
|
|
31
31
|
);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
function
|
|
34
|
+
function shouldBeExcluded(pFullPathToFile, pOptions) {
|
|
35
35
|
return (
|
|
36
|
-
(
|
|
37
|
-
|
|
38
|
-
(
|
|
39
|
-
|
|
36
|
+
(pOptions?.exclude?.path &&
|
|
37
|
+
filenameMatchesPattern(pFullPathToFile, pOptions.exclude.path)) ||
|
|
38
|
+
(pOptions?.doNotFollow?.path &&
|
|
39
|
+
filenameMatchesPattern(pFullPathToFile, pOptions.doNotFollow.path))
|
|
40
40
|
);
|
|
41
41
|
}
|
|
42
42
|
|
|
@@ -48,11 +48,12 @@ function shouldNotBeExcluded(pFullPathToFile, pOptions) {
|
|
|
48
48
|
function gatherScannableFilesFromDirectory(pDirectoryName, pOptions) {
|
|
49
49
|
return readdirSync(join(pOptions.baseDir, pDirectoryName))
|
|
50
50
|
.map((pFileName) => join(pDirectoryName, pFileName))
|
|
51
|
-
.filter((pFullPathToFile) =>
|
|
52
|
-
shouldNotBeExcluded(pathToPosix(pFullPathToFile), pOptions),
|
|
53
|
-
)
|
|
54
51
|
.flatMap((pFullPathToFile) => {
|
|
55
|
-
|
|
52
|
+
const lPosixPath = pathToPosix(pFullPathToFile);
|
|
53
|
+
if (shouldBeExcluded(lPosixPath, pOptions)) {
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
const lStat = statSync(join(pOptions.baseDir, pFullPathToFile), {
|
|
56
57
|
throwIfNoEntry: false,
|
|
57
58
|
});
|
|
58
59
|
|
|
@@ -60,14 +61,15 @@ function gatherScannableFilesFromDirectory(pDirectoryName, pOptions) {
|
|
|
60
61
|
if (lStat.isDirectory()) {
|
|
61
62
|
return gatherScannableFilesFromDirectory(pFullPathToFile, pOptions);
|
|
62
63
|
}
|
|
63
|
-
if (
|
|
64
|
-
|
|
64
|
+
if (
|
|
65
|
+
fileIsScannable(pOptions, pFullPathToFile) &&
|
|
66
|
+
shouldBeIncluded(lPosixPath, pOptions)
|
|
67
|
+
) {
|
|
68
|
+
return lPosixPath;
|
|
65
69
|
}
|
|
66
70
|
}
|
|
67
71
|
return [];
|
|
68
|
-
})
|
|
69
|
-
.map((pFullPathToFile) => pathToPosix(pFullPathToFile))
|
|
70
|
-
.filter((pFullPathToFile) => shouldBeIncluded(pFullPathToFile, pOptions));
|
|
72
|
+
});
|
|
71
73
|
}
|
|
72
74
|
|
|
73
75
|
function expandGlob(pBaseDirectory, pScannedGlob) {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @ts-check
|
|
2
1
|
/* eslint-disable security/detect-object-injection */
|
|
3
2
|
/**
|
|
4
3
|
* @import { IFolderDependency, IDependency, IFolder, IModule } from "../../types/cruise-result.mjs"
|
|
@@ -68,7 +67,7 @@ export default class IndexedModuleGraph {
|
|
|
68
67
|
) {
|
|
69
68
|
/** @type {string[]} */
|
|
70
69
|
let lReturnValue = [];
|
|
71
|
-
const lModule = this.
|
|
70
|
+
const lModule = this.#indexedGraph.get(pName);
|
|
72
71
|
|
|
73
72
|
if (lModule && (!pMaxDepth || pDepth <= pMaxDepth)) {
|
|
74
73
|
let lDependents = lModule.dependents || [];
|
|
@@ -110,24 +109,26 @@ export default class IndexedModuleGraph {
|
|
|
110
109
|
) {
|
|
111
110
|
/** @type {string[]} */
|
|
112
111
|
let lReturnValue = [];
|
|
113
|
-
|
|
112
|
+
/** @type {IVertex} */
|
|
113
|
+
const lModule = this.#indexedGraph.get(pName);
|
|
114
114
|
|
|
115
115
|
if (lModule && (!pMaxDepth || pDepth <= pMaxDepth)) {
|
|
116
116
|
let lDependencies = lModule.dependencies;
|
|
117
117
|
const lVisited = pVisited.add(pName);
|
|
118
118
|
|
|
119
119
|
if (lDependencies.length > 0) {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
.
|
|
120
|
+
// eslint-disable-next-line budapestian/local-variable-pattern
|
|
121
|
+
for (const { name } of lDependencies) {
|
|
122
|
+
// eslint-disable-next-line max-depth
|
|
123
|
+
if (!lVisited.has(name)) {
|
|
124
124
|
this.findTransitiveDependencies(
|
|
125
|
-
|
|
125
|
+
name,
|
|
126
126
|
pMaxDepth,
|
|
127
127
|
pDepth + 1,
|
|
128
128
|
lVisited,
|
|
129
|
-
)
|
|
130
|
-
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
131
132
|
}
|
|
132
133
|
lReturnValue = Array.from(lVisited);
|
|
133
134
|
}
|
|
@@ -140,12 +141,10 @@ export default class IndexedModuleGraph {
|
|
|
140
141
|
* @returns {IMiniDependency}
|
|
141
142
|
*/
|
|
142
143
|
#geldEdge(pEdge) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
: [];
|
|
148
|
-
return lReturnValue;
|
|
144
|
+
return {
|
|
145
|
+
name: pEdge.name,
|
|
146
|
+
dependencyTypes: pEdge.dependencyTypes ?? [],
|
|
147
|
+
};
|
|
149
148
|
}
|
|
150
149
|
|
|
151
150
|
/**
|
|
@@ -155,7 +154,8 @@ export default class IndexedModuleGraph {
|
|
|
155
154
|
* @returns {Array<IMiniDependency>}
|
|
156
155
|
*/
|
|
157
156
|
getPath(pFrom, pTo, pVisited = new Set()) {
|
|
158
|
-
|
|
157
|
+
/** @type {IVertex} */
|
|
158
|
+
const lFromNode = this.#indexedGraph.get(pFrom);
|
|
159
159
|
|
|
160
160
|
pVisited.add(pFrom);
|
|
161
161
|
|
|
@@ -195,7 +195,8 @@ export default class IndexedModuleGraph {
|
|
|
195
195
|
*/
|
|
196
196
|
#getCycle(pInitialSource, pCurrentDependency, pVisited) {
|
|
197
197
|
const lVisited = pVisited || new Set();
|
|
198
|
-
|
|
198
|
+
/** @type {IVertex} */
|
|
199
|
+
const lCurrentVertex = this.#indexedGraph.get(pCurrentDependency.name);
|
|
199
200
|
const lEdges = lCurrentVertex.dependencies.filter(
|
|
200
201
|
(pDependency) => !lVisited.has(pDependency.name),
|
|
201
202
|
);
|
|
@@ -245,7 +246,8 @@ export default class IndexedModuleGraph {
|
|
|
245
246
|
* @return {Array<IMiniDependency>} see description above
|
|
246
247
|
*/
|
|
247
248
|
getCycle(pInitialSource, pCurrentSource) {
|
|
248
|
-
|
|
249
|
+
/** @type {IVertex} */
|
|
250
|
+
const lInitialNode = this.#indexedGraph.get(pInitialSource);
|
|
249
251
|
const lCurrentDependency = lInitialNode.dependencies.find(
|
|
250
252
|
(pDependency) => pDependency.name === pCurrentSource,
|
|
251
253
|
);
|
|
@@ -80,9 +80,8 @@ async function compileResolveOptions(
|
|
|
80
80
|
// Also: requiring the plugin only when it's necessary will save some
|
|
81
81
|
// startup time (especially on a cold require cache)
|
|
82
82
|
if (pResolveOptions.tsConfig) {
|
|
83
|
-
const { default: TsConfigPathsPlugin } =
|
|
84
|
-
"tsconfig-paths-webpack-plugin"
|
|
85
|
-
);
|
|
83
|
+
const { default: TsConfigPathsPlugin } =
|
|
84
|
+
await import("tsconfig-paths-webpack-plugin");
|
|
86
85
|
lResolveOptions.plugins = pushPlugin(
|
|
87
86
|
lResolveOptions.plugins,
|
|
88
87
|
// @ts-expect-error TS2351 "TsConfPathsPlugin is not constructable" - is unjustified
|
package/src/meta.cjs
CHANGED
|
@@ -28,37 +28,29 @@ function walk(
|
|
|
28
28
|
pDirectoryName,
|
|
29
29
|
{ baseDir, ignoreFilterFn, excludeFilterFn, includeOnlyFilterFn },
|
|
30
30
|
) {
|
|
31
|
-
|
|
31
|
+
const lFilesInCurrentDirectory = readdirSync(join(baseDir, pDirectoryName))
|
|
32
32
|
.map((pFileName) => join(pDirectoryName, pFileName))
|
|
33
33
|
.filter(ignoreFilterFn)
|
|
34
34
|
.filter(excludeFilterFn)
|
|
35
|
-
.filter(includeOnlyFilterFn)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}),
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
return pSum.concat(fullPathToFile);
|
|
58
|
-
},
|
|
59
|
-
[],
|
|
60
|
-
)
|
|
61
|
-
.map((pFullPathToFile) => pathToPosix(pFullPathToFile));
|
|
35
|
+
.filter(includeOnlyFilterFn);
|
|
36
|
+
|
|
37
|
+
const lFiles = [];
|
|
38
|
+
for (const lFile of lFilesInCurrentDirectory) {
|
|
39
|
+
if (fileIsDirectory(lFile, baseDir)) {
|
|
40
|
+
lFiles.push(
|
|
41
|
+
...walk(lFile, {
|
|
42
|
+
baseDir,
|
|
43
|
+
ignoreFilterFn,
|
|
44
|
+
excludeFilterFn,
|
|
45
|
+
includeOnlyFilterFn,
|
|
46
|
+
}),
|
|
47
|
+
);
|
|
48
|
+
} else {
|
|
49
|
+
lFiles.push(pathToPosix(lFile));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return lFiles;
|
|
62
54
|
}
|
|
63
55
|
|
|
64
56
|
function readIgnoreFile(pFileName) {
|
|
@@ -15,16 +15,14 @@ function fromFolderPathNot(pRule, pFromFolder) {
|
|
|
15
15
|
function toFolderPath(pRule, pToFolder, pGroups) {
|
|
16
16
|
return Boolean(
|
|
17
17
|
!pRule.to.path ||
|
|
18
|
-
|
|
18
|
+
pToFolder.name.match(replaceGroupPlaceholders(pRule.to.path, pGroups)),
|
|
19
19
|
);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
function toFolderPathNot(pRule, pToFolder, pGroups) {
|
|
23
23
|
return Boolean(
|
|
24
24
|
!pRule.to.pathNot ||
|
|
25
|
-
|
|
26
|
-
replaceGroupPlaceholders(pRule.to.pathNot, pGroups),
|
|
27
|
-
),
|
|
25
|
+
!pToFolder.name.match(replaceGroupPlaceholders(pRule.to.pathNot, pGroups)),
|
|
28
26
|
);
|
|
29
27
|
}
|
|
30
28
|
|
|
@@ -31,8 +31,8 @@ export function propertyEquals(pRule, pDependency, pProperty) {
|
|
|
31
31
|
export function propertyMatches(pRule, pDependency, pRuleProperty, pProperty) {
|
|
32
32
|
return Boolean(
|
|
33
33
|
!pRule.to[pRuleProperty] ||
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
(pDependency[pProperty] &&
|
|
35
|
+
pDependency[pProperty].match(pRule.to[pRuleProperty])),
|
|
36
36
|
);
|
|
37
37
|
}
|
|
38
38
|
|
|
@@ -44,8 +44,8 @@ export function propertyMatchesNot(
|
|
|
44
44
|
) {
|
|
45
45
|
return Boolean(
|
|
46
46
|
!pRule.to[pRuleProperty] ||
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
(pDependency[pProperty] &&
|
|
48
|
+
!pDependency[pProperty].match(pRule.to[pRuleProperty])),
|
|
49
49
|
);
|
|
50
50
|
}
|
|
51
51
|
|
|
@@ -72,7 +72,7 @@ export function matchesModulePathNot(pRule, pModule) {
|
|
|
72
72
|
function _matchesToPath(pRule, pString, pGroups = []) {
|
|
73
73
|
return Boolean(
|
|
74
74
|
!pRule.to.path ||
|
|
75
|
-
|
|
75
|
+
pString.match(replaceGroupPlaceholders(pRule.to.path, pGroups)),
|
|
76
76
|
);
|
|
77
77
|
}
|
|
78
78
|
|
|
@@ -102,14 +102,14 @@ export function matchToModulePathNot(pRule, pModule, pGroups) {
|
|
|
102
102
|
export function matchesToDependencyTypes(pRule, pDependency) {
|
|
103
103
|
return Boolean(
|
|
104
104
|
!pRule.to.dependencyTypes ||
|
|
105
|
-
|
|
105
|
+
intersects(pDependency.dependencyTypes, pRule.to.dependencyTypes),
|
|
106
106
|
);
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
export function matchesToDependencyTypesNot(pRule, pDependency) {
|
|
110
110
|
return Boolean(
|
|
111
111
|
!pRule.to.dependencyTypesNot ||
|
|
112
|
-
|
|
112
|
+
!intersects(pDependency.dependencyTypes, pRule.to.dependencyTypesNot),
|
|
113
113
|
);
|
|
114
114
|
}
|
|
115
115
|
|
|
@@ -18,8 +18,7 @@ export interface IStrictFromRestriction extends IFromRestriction {
|
|
|
18
18
|
pathNot?: string;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
export interface IStrictMiniDependencyRestriction
|
|
22
|
-
extends IStrictBaseRestrictionType {
|
|
21
|
+
export interface IStrictMiniDependencyRestriction extends IStrictBaseRestrictionType {
|
|
23
22
|
dependencyTypes?: DependencyType[];
|
|
24
23
|
dependencyTypesNot?: DependencyType[];
|
|
25
24
|
}
|
|
@@ -35,19 +34,16 @@ interface IStrictToRestriction extends IToRestriction {
|
|
|
35
34
|
licenseNot?: string;
|
|
36
35
|
}
|
|
37
36
|
|
|
38
|
-
export interface IStrictReachabilityToRestrictionType
|
|
39
|
-
extends IReachabilityToRestrictionType {
|
|
37
|
+
export interface IStrictReachabilityToRestrictionType extends IReachabilityToRestrictionType {
|
|
40
38
|
path?: string;
|
|
41
39
|
pathNot?: string;
|
|
42
40
|
}
|
|
43
41
|
|
|
44
|
-
export interface IStrictRequiredToRestrictionType
|
|
45
|
-
extends IRequiredToRestrictionType {
|
|
42
|
+
export interface IStrictRequiredToRestrictionType extends IRequiredToRestrictionType {
|
|
46
43
|
path?: string;
|
|
47
44
|
}
|
|
48
45
|
|
|
49
|
-
export interface IStrictDependentsModuleRestrictionType
|
|
50
|
-
extends IDependentsModuleRestrictionType {
|
|
46
|
+
export interface IStrictDependentsModuleRestrictionType extends IDependentsModuleRestrictionType {
|
|
51
47
|
path?: string;
|
|
52
48
|
pathNot?: string;
|
|
53
49
|
}
|
|
@@ -24,14 +24,12 @@ export interface IStrictRegularForbiddenRuleType extends IStrictBaseRuleType {
|
|
|
24
24
|
scope: RuleScopeType;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export interface IStrictReachabilityForbiddenRuleType
|
|
28
|
-
extends IStrictBaseRuleType {
|
|
27
|
+
export interface IStrictReachabilityForbiddenRuleType extends IStrictBaseRuleType {
|
|
29
28
|
from: IStrictBaseRestrictionType;
|
|
30
29
|
to: IStrictReachabilityToRestrictionType;
|
|
31
30
|
}
|
|
32
31
|
|
|
33
|
-
export interface IStrictDependentsForbiddenRuleType
|
|
34
|
-
extends IStrictBaseRuleType {
|
|
32
|
+
export interface IStrictDependentsForbiddenRuleType extends IStrictBaseRuleType {
|
|
35
33
|
module: IStrictDependentsModuleRestrictionType;
|
|
36
34
|
from: IStrictBaseRestrictionType;
|
|
37
35
|
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { isDependent } from "../module-utl.mjs";
|
|
2
|
-
|
|
3
|
-
export default function getDependents(pModule, pModules) {
|
|
4
|
-
// perf between O(n) in an unconnected graph and O(n^2) in a fully connected one
|
|
5
|
-
return pModules
|
|
6
|
-
.filter(isDependent(pModule.source))
|
|
7
|
-
.map((pDependentModule) => pDependentModule.source);
|
|
8
|
-
}
|