dependency-cruiser 16.6.0 → 16.7.0-beta-1
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/cache.mjs +3 -4
- package/src/cache/content-strategy.mjs +5 -7
- package/src/cache/find-content-changes.mjs +11 -5
- package/src/cache/helpers.mjs +8 -8
- package/src/cache/metadata-strategy.mjs +6 -8
- package/src/cache/options-compatible.mjs +2 -1
- package/src/cli/init-config/build-config.mjs +13 -9
- package/src/cli/init-config/config-template.mjs +11 -0
- package/src/cli/init-config/index.mjs +10 -6
- package/src/cli/init-config/normalize-init-options.mjs +10 -6
- package/src/config-utl/extract-depcruise-options.mjs +8 -4
- package/src/config-utl/extract-known-violations.mjs +2 -2
- package/src/enrich/summarize/summarize-options.mjs +2 -0
- package/src/extract/extract-dependencies.mjs +14 -9
- package/src/extract/extract-stats.mjs +9 -4
- package/src/extract/gather-initial-sources.mjs +7 -5
- package/src/extract/index.mjs +9 -4
- package/src/extract/resolve/determine-dependency-types.mjs +20 -13
- package/src/extract/resolve/index.mjs +11 -5
- package/src/extract/resolve/module-classifiers.mjs +7 -2
- package/src/extract/swc/parse.mjs +8 -4
- package/src/extract/tsc/extract-typescript-deps.mjs +85 -13
- package/src/extract/tsc/extract.mjs +2 -1
- package/src/graph-utl/consolidate-module-dependencies.mjs +8 -4
- package/src/graph-utl/filter-bank.mjs +8 -3
- package/src/graph-utl/indexed-module-graph.mjs +7 -11
- package/src/graph-utl/rule-set.mjs +9 -5
- package/src/main/options/assert-validity.mjs +6 -2
- package/src/main/options/defaults.mjs +1 -0
- package/src/main/options/normalize.mjs +23 -13
- package/src/main/report-wrap.mjs +12 -7
- package/src/main/resolve-options/normalize.mjs +9 -4
- package/src/main/rule-set/assert-validity.mjs +5 -2
- package/src/main/rule-set/normalize.mjs +18 -8
- package/src/meta.cjs +1 -1
- package/src/schema/baseline-violations.schema.mjs +1 -1
- package/src/schema/configuration.schema.mjs +1 -1
- package/src/schema/cruise-result.schema.mjs +1 -1
- package/src/validate/index.mjs +6 -2
- package/src/validate/match-dependency-rule.mjs +8 -4
- package/src/validate/match-module-rule-helpers.mjs +15 -9
- package/src/validate/match-module-rule.mjs +8 -5
- package/types/options.d.mts +5 -0
- package/types/shared-types.d.mts +3 -0
|
@@ -9,6 +9,13 @@ import {
|
|
|
9
9
|
getPackageRoot,
|
|
10
10
|
} from "./external-module-helpers.mjs";
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* @import { DependencyType } from "../../../types/shared-types.mjs"
|
|
14
|
+
* @import { IResolveOptions, ITranspileOptions } from "../../../types/dependency-cruiser.mjs"
|
|
15
|
+
* @import { IDependency } from "../../../types/cruise-result.mjs"
|
|
16
|
+
* @import { IResolveOptions } from "../../../types/resolve-options.mjs"
|
|
17
|
+
*/
|
|
18
|
+
|
|
12
19
|
function dependencyKeyHasModuleName(
|
|
13
20
|
pPackageDependencies,
|
|
14
21
|
pModuleName,
|
|
@@ -49,7 +56,7 @@ function determineManifestDependencyTypes(
|
|
|
49
56
|
pPackageDependencies,
|
|
50
57
|
pResolverModulePaths,
|
|
51
58
|
) {
|
|
52
|
-
/** @type {
|
|
59
|
+
/** @type {DependencyType[]} */
|
|
53
60
|
let lReturnValue = ["npm-unknown"];
|
|
54
61
|
|
|
55
62
|
if (Boolean(pPackageDependencies)) {
|
|
@@ -98,8 +105,8 @@ function dependencyIsBundled(pModule, pPackageDeps) {
|
|
|
98
105
|
* @param {string} pModuleName
|
|
99
106
|
* @param {string} pPackageDeps
|
|
100
107
|
* @param {string} pFileDirectory
|
|
101
|
-
* @param {
|
|
102
|
-
* @returns {
|
|
108
|
+
* @param {IResolveOptions} pResolveOptions
|
|
109
|
+
* @returns {DependencyType[]}
|
|
103
110
|
*/
|
|
104
111
|
function determineNodeModuleDependencyTypes(
|
|
105
112
|
pModuleName,
|
|
@@ -107,7 +114,7 @@ function determineNodeModuleDependencyTypes(
|
|
|
107
114
|
pFileDirectory,
|
|
108
115
|
pResolveOptions,
|
|
109
116
|
) {
|
|
110
|
-
/** @type {
|
|
117
|
+
/** @type { DependencyType[] } */
|
|
111
118
|
let lReturnValue = determineManifestDependencyTypes(
|
|
112
119
|
getPackageRoot(pModuleName),
|
|
113
120
|
pPackageDeps,
|
|
@@ -127,13 +134,13 @@ function determineNodeModuleDependencyTypes(
|
|
|
127
134
|
|
|
128
135
|
/**
|
|
129
136
|
*
|
|
130
|
-
* @param {
|
|
137
|
+
* @param {IDependency} pDependency
|
|
131
138
|
* @param {string} pModuleName
|
|
132
139
|
* @param {any} pPackageDeps
|
|
133
140
|
* @param {string} pFileDirectory
|
|
134
|
-
* @param {
|
|
141
|
+
* @param {IResolveOptions} pResolveOptions
|
|
135
142
|
* @param {string} pBaseDirectory
|
|
136
|
-
* @returns {
|
|
143
|
+
* @returns {DependencyType[]}
|
|
137
144
|
*/
|
|
138
145
|
function determineExternalModuleDependencyTypes(
|
|
139
146
|
pDependency,
|
|
@@ -143,7 +150,7 @@ function determineExternalModuleDependencyTypes(
|
|
|
143
150
|
pResolveOptions,
|
|
144
151
|
pBaseDirectory,
|
|
145
152
|
) {
|
|
146
|
-
/** @type {
|
|
153
|
+
/** @type { DependencyType[] } */
|
|
147
154
|
let lReturnValue = [];
|
|
148
155
|
|
|
149
156
|
if (
|
|
@@ -164,15 +171,15 @@ function determineExternalModuleDependencyTypes(
|
|
|
164
171
|
/* eslint max-params:0, complexity:0 */
|
|
165
172
|
/**
|
|
166
173
|
*
|
|
167
|
-
* @param {
|
|
174
|
+
* @param {IDependency} pDependency the dependency object with all information found hitherto
|
|
168
175
|
* @param {string} pModuleName the module name as found in the source
|
|
169
176
|
* @param {any} pManifest a package.json, in object format
|
|
170
177
|
* @param {string} pFileDirectory the directory relative to which to resolve (only used for npm deps here)
|
|
171
|
-
* @param {
|
|
178
|
+
* @param {IResolveOptions} pResolveOptions an enhanced resolve 'resolve' key
|
|
172
179
|
* @param {string} pBaseDirectory the base directory dependency cruise is run on
|
|
173
|
-
* @param {
|
|
180
|
+
* @param {ITranspileOptions} pTranspileOptions
|
|
174
181
|
*
|
|
175
|
-
* @return {
|
|
182
|
+
* @return { DependencyType[] }an array of dependency types for the dependency
|
|
176
183
|
*/
|
|
177
184
|
// eslint-disable-next-line max-lines-per-function
|
|
178
185
|
export default function determineDependencyTypes(
|
|
@@ -184,7 +191,7 @@ export default function determineDependencyTypes(
|
|
|
184
191
|
pBaseDirectory,
|
|
185
192
|
pTranspileOptions,
|
|
186
193
|
) {
|
|
187
|
-
/** @type {
|
|
194
|
+
/** @type {DependencyType[]}*/
|
|
188
195
|
let lReturnValue = [];
|
|
189
196
|
const lResolveOptions = pResolveOptions || {};
|
|
190
197
|
|
|
@@ -8,12 +8,18 @@ import determineDependencyTypes from "./determine-dependency-types.mjs";
|
|
|
8
8
|
import { getManifest } from "./get-manifest.mjs";
|
|
9
9
|
import pathToPosix from "#utl/path-to-posix.mjs";
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* @import { IModule, IResolveOptions } from "../../../types/dependency-cruiser.mjs";
|
|
13
|
+
* @import { IResolveOptions } from "../../../types/resolve-options.mjs";
|
|
14
|
+
* @import { IDependency } from "../../../types/cruise-result.mjs";
|
|
15
|
+
*/
|
|
16
|
+
|
|
11
17
|
/**
|
|
12
18
|
*
|
|
13
|
-
* @param {
|
|
19
|
+
* @param {IModule} pModule
|
|
14
20
|
* @param {string} pBaseDirectory
|
|
15
21
|
* @param {string} pFileDirectory
|
|
16
|
-
* @param {
|
|
22
|
+
* @param {IResolveOptions} pResolveOptions
|
|
17
23
|
* @returns {any}
|
|
18
24
|
*/
|
|
19
25
|
function resolveModule(
|
|
@@ -154,14 +160,14 @@ function resolveWithRetry(
|
|
|
154
160
|
/**
|
|
155
161
|
* resolves the module name of the pDependency to a file on disk.
|
|
156
162
|
*
|
|
157
|
-
* @param {Partial <
|
|
163
|
+
* @param {Partial <IDependency>} pDependency
|
|
158
164
|
* @param {string} pBaseDirectory the directory to consider as base (or 'root')
|
|
159
165
|
* for resolved files.
|
|
160
166
|
* @param {string} pFileDirectory the directory of the file the dependency was
|
|
161
167
|
* detected in
|
|
162
|
-
* @param {
|
|
168
|
+
* @param {IResolveOptions} pResolveOptions
|
|
163
169
|
* @param {any} pTranspileOptions
|
|
164
|
-
* @return {Partial <
|
|
170
|
+
* @return {Partial <IDependency>}
|
|
165
171
|
*
|
|
166
172
|
*
|
|
167
173
|
*/
|
|
@@ -4,6 +4,11 @@ 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
6
|
|
|
7
|
+
/**
|
|
8
|
+
* @import { IResolveOptions } from "../../../types/resolve-options.mjs"
|
|
9
|
+
* @import { ITranspileOptions } from "../../../types/dependency-cruiser.mjs"
|
|
10
|
+
*/
|
|
11
|
+
|
|
7
12
|
let gFollowableExtensionsCache = new Set();
|
|
8
13
|
let gFollowableExtensionsCacheInitialized = false;
|
|
9
14
|
|
|
@@ -278,9 +283,9 @@ function matchesTSConfigBaseURL(
|
|
|
278
283
|
/**
|
|
279
284
|
* @param {string} pModuleName
|
|
280
285
|
* @param {string} pResolvedModuleName
|
|
281
|
-
* @param {
|
|
286
|
+
* @param {importIResolveOptions} pResolveOptions
|
|
282
287
|
* @param {any} pManifest
|
|
283
|
-
* @param {
|
|
288
|
+
* @param {ITranspileOptions} pTranspileOptions
|
|
284
289
|
* @returns {string[]}
|
|
285
290
|
*/
|
|
286
291
|
// eslint-disable-next-line max-params, complexity
|
|
@@ -2,10 +2,14 @@ import memoize, { memoizeClear } from "memoize";
|
|
|
2
2
|
import tryImport from "#utl/try-import.mjs";
|
|
3
3
|
import meta from "#meta.cjs";
|
|
4
4
|
|
|
5
|
-
/**
|
|
5
|
+
/**
|
|
6
|
+
* @import swcCore, { ParseOptions, ModuleItem } from "@swc/core";
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** @type {swcCore} */
|
|
6
10
|
const swc = await tryImport("@swc/core", meta.supportedTranspilers.swc);
|
|
7
11
|
|
|
8
|
-
/** @type {
|
|
12
|
+
/** @type {ParseOptions} */
|
|
9
13
|
const SWC_PARSE_OPTIONS = {
|
|
10
14
|
dynamicImport: true,
|
|
11
15
|
// typescript is a superset of ecmascript, so we use typescript always
|
|
@@ -22,7 +26,7 @@ export function getASTFromSource(pSource) {
|
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
function getAST(pFileName) {
|
|
25
|
-
/** @type {
|
|
29
|
+
/** @type {swcCore swc} */
|
|
26
30
|
return swc.parseFileSync(pFileName, SWC_PARSE_OPTIONS);
|
|
27
31
|
}
|
|
28
32
|
|
|
@@ -32,7 +36,7 @@ function getAST(pFileName) {
|
|
|
32
36
|
* return the result from a cache
|
|
33
37
|
*
|
|
34
38
|
* @param {string} pFileName - the name of the file to compile
|
|
35
|
-
* @return {
|
|
39
|
+
* @return {ModuleItem[]} - an (swc) AST
|
|
36
40
|
*/
|
|
37
41
|
export const getASTCached = memoize(getAST);
|
|
38
42
|
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
/* eslint-disable unicorn/prevent-abbreviations */
|
|
1
2
|
/* eslint-disable max-lines */
|
|
2
3
|
/* eslint-disable no-inline-comments */
|
|
3
4
|
import tryImport from "#utl/try-import.mjs";
|
|
4
5
|
import meta from "#meta.cjs";
|
|
5
6
|
|
|
6
|
-
/**
|
|
7
|
+
/**
|
|
8
|
+
* @import typescript, {Node} from "typescript"
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** @type {typescript} */
|
|
7
12
|
const typescript = await tryImport(
|
|
8
13
|
"typescript",
|
|
9
14
|
meta.supportedTranspilers.typescript,
|
|
@@ -24,7 +29,7 @@ function isTypeOnlyImport(pStatement) {
|
|
|
24
29
|
function isTypeOnlyExport(pStatement) {
|
|
25
30
|
return (
|
|
26
31
|
// for some reason the isTypeOnly indicator is on _statement_ level
|
|
27
|
-
// and not in exportClause as it is in the importClause ¯\_
|
|
32
|
+
// and not in exportClause as it is in the importClause ¯\_(ツ)_/¯.
|
|
28
33
|
// Also in the case of the omission of an alias the exportClause
|
|
29
34
|
// is not there entirely. So regardless whether there is a
|
|
30
35
|
// pStatement.exportClause or not, we can directly test for the
|
|
@@ -46,7 +51,7 @@ function isTypeOnlyExport(pStatement) {
|
|
|
46
51
|
/**
|
|
47
52
|
* Get all import statements from the top level AST node
|
|
48
53
|
*
|
|
49
|
-
* @param {
|
|
54
|
+
* @param {Node} pAST - the (top-level in this case) AST node
|
|
50
55
|
* @returns {{module: string; moduleSystem: string; exoticallyRequired: boolean; dependencyTypes?: string[];}[]} -
|
|
51
56
|
* all import statements in the (top level) AST node
|
|
52
57
|
*/
|
|
@@ -70,7 +75,7 @@ function extractImports(pAST) {
|
|
|
70
75
|
/**
|
|
71
76
|
* Get all export statements from the top level AST node
|
|
72
77
|
*
|
|
73
|
-
* @param {
|
|
78
|
+
* @param {Node} pAST - the (top-level in this case) AST node
|
|
74
79
|
* @returns {{module: string; moduleSystem: string; exoticallyRequired: boolean; dependencyTypes?: string[];}[]} -
|
|
75
80
|
* all export statements in the (top level) AST node
|
|
76
81
|
*/
|
|
@@ -98,7 +103,7 @@ function extractExports(pAST) {
|
|
|
98
103
|
* Ignores import equals of variables (e.g. import protocol = ts.server.protocol
|
|
99
104
|
* which happens in typescript/lib/protocol.d.ts)
|
|
100
105
|
*
|
|
101
|
-
* @param {
|
|
106
|
+
* @param {Node} pAST - the (top-level in this case) AST node
|
|
102
107
|
* @returns {{module: string, moduleSystem: string;exoticallyRequired: boolean;}[]} - all import equals statements in the
|
|
103
108
|
* (top level) AST node
|
|
104
109
|
*/
|
|
@@ -123,7 +128,7 @@ function extractImportEquals(pAST) {
|
|
|
123
128
|
* might be wise to distinguish the three types of /// directive that
|
|
124
129
|
* can come out of this as the resolution algorithm might differ
|
|
125
130
|
*
|
|
126
|
-
* @param {
|
|
131
|
+
* @param {Node} pAST - typescript syntax tree
|
|
127
132
|
* @returns {{module: string, moduleSystem: string}[]} - 'tripple slash' dependencies
|
|
128
133
|
*/
|
|
129
134
|
function extractTripleSlashDirectives(pAST) {
|
|
@@ -252,7 +257,41 @@ function isTypeImport(pASTNode) {
|
|
|
252
257
|
"FirstTemplateToken")
|
|
253
258
|
);
|
|
254
259
|
}
|
|
255
|
-
|
|
260
|
+
|
|
261
|
+
function extractJSDocImportTags(pJSDocTags) {
|
|
262
|
+
return pJSDocTags
|
|
263
|
+
.filter(
|
|
264
|
+
(pTag) =>
|
|
265
|
+
pTag.tagName.escapedText === "import" &&
|
|
266
|
+
pTag.moduleSpecifier?.kind &&
|
|
267
|
+
typescript.SyntaxKind[pTag.moduleSpecifier.kind] === "StringLiteral" &&
|
|
268
|
+
Boolean(pTag.moduleSpecifier.text),
|
|
269
|
+
)
|
|
270
|
+
.map((pTag) => ({
|
|
271
|
+
module: pTag.moduleSpecifier.text,
|
|
272
|
+
moduleSystem: "es6",
|
|
273
|
+
exoticallyRequired: false,
|
|
274
|
+
dependencyTypes: ["type-only", "import", "jsdoc", "jsdoc-import-tag"],
|
|
275
|
+
}));
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function extractJSDocImports(pJSDocNodes) {
|
|
279
|
+
return pJSDocNodes
|
|
280
|
+
.filter((pJSDocLine) => Boolean(pJSDocLine.tags))
|
|
281
|
+
.flatMap((pJSDocLine) => extractJSDocImportTags(pJSDocLine.tags));
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Walks the AST and collects all dependencies
|
|
286
|
+
*
|
|
287
|
+
* @param {Node} pASTNode - the AST node to start from
|
|
288
|
+
* @param {string[]} pExoticRequireStrings - exotic require strings to look for
|
|
289
|
+
* @param {boolean} pDetectJSDocImports - whether to detect jsdoc imports
|
|
290
|
+
* @returns {(pASTNode: Node) => void} - the walker function
|
|
291
|
+
*/
|
|
292
|
+
// eslint-disable-next-line max-lines-per-function
|
|
293
|
+
function walk(pResult, pExoticRequireStrings, pDetectJSDocImports) {
|
|
294
|
+
// eslint-disable-next-line max-lines-per-function
|
|
256
295
|
return (pASTNode) => {
|
|
257
296
|
// require('a-string'), require(`a-template-literal`)
|
|
258
297
|
if (isRequireCallExpression(pASTNode)) {
|
|
@@ -298,7 +337,28 @@ function walk(pResult, pExoticRequireStrings) {
|
|
|
298
337
|
dependencyTypes: ["type-import"],
|
|
299
338
|
});
|
|
300
339
|
}
|
|
301
|
-
|
|
340
|
+
|
|
341
|
+
// /** @import thing from './module' */
|
|
342
|
+
// /** @import {thing} from './module' */
|
|
343
|
+
// /** @import * as thing from './module' */
|
|
344
|
+
// see https://devblogs.microsoft.com/typescript/announcing-typescript-5-5/#the-jsdoc-import-tag
|
|
345
|
+
//
|
|
346
|
+
// TODO: all the kinds of tags that can have import statements as type declarations
|
|
347
|
+
// (e.g. @type, @param, @returns, @typedef, @property, @prop, @arg, ...)
|
|
348
|
+
// https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html
|
|
349
|
+
if (pDetectJSDocImports && Boolean(pASTNode.jsDoc)) {
|
|
350
|
+
const lJSDocImports = extractJSDocImports(pASTNode.jsDoc);
|
|
351
|
+
|
|
352
|
+
// pResult = pResult.concat(lJSDocImports) looks like the more obvious
|
|
353
|
+
// way to do this, but it re-assigns the pResult parameter
|
|
354
|
+
lJSDocImports.forEach((pImport) => {
|
|
355
|
+
pResult.push(pImport);
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
typescript.forEachChild(
|
|
359
|
+
pASTNode,
|
|
360
|
+
walk(pResult, pExoticRequireStrings, pDetectJSDocImports),
|
|
361
|
+
);
|
|
302
362
|
};
|
|
303
363
|
}
|
|
304
364
|
|
|
@@ -306,13 +366,19 @@ function walk(pResult, pExoticRequireStrings) {
|
|
|
306
366
|
* returns an array of dependencies that come potentially nested within
|
|
307
367
|
* a source file, like commonJS or dynamic imports
|
|
308
368
|
*
|
|
309
|
-
* @param {
|
|
369
|
+
* @param {Node} pAST - typescript syntax tree
|
|
370
|
+
* @param {string[]} pExoticRequireStrings - exotic require strings to look for
|
|
371
|
+
* @param {boolean} pDetectJSDocImports - whether to detect jsdoc imports
|
|
310
372
|
* @returns {{module: string, moduleSystem: string}[]} - all commonJS dependencies
|
|
311
373
|
*/
|
|
312
|
-
function extractNestedDependencies(
|
|
374
|
+
function extractNestedDependencies(
|
|
375
|
+
pAST,
|
|
376
|
+
pExoticRequireStrings,
|
|
377
|
+
pDetectJSDocImports,
|
|
378
|
+
) {
|
|
313
379
|
let lResult = [];
|
|
314
380
|
|
|
315
|
-
walk(lResult, pExoticRequireStrings)(pAST);
|
|
381
|
+
walk(lResult, pExoticRequireStrings, pDetectJSDocImports)(pAST);
|
|
316
382
|
|
|
317
383
|
return lResult;
|
|
318
384
|
}
|
|
@@ -320,19 +386,25 @@ function extractNestedDependencies(pAST, pExoticRequireStrings) {
|
|
|
320
386
|
/**
|
|
321
387
|
* returns all dependencies in the AST
|
|
322
388
|
*
|
|
323
|
-
* @type {(pTypeScriptAST: (
|
|
389
|
+
* @type {(pTypeScriptAST: (Node), pExoticRequireStrings: string[], pDetectJSDocImports: boolean) => {module: string, moduleSystem: string, dynamic: boolean}[]}
|
|
324
390
|
*/
|
|
325
391
|
export default function extractTypeScriptDependencies(
|
|
326
392
|
pTypeScriptAST,
|
|
327
393
|
pExoticRequireStrings,
|
|
394
|
+
pDetectJSDocImports,
|
|
328
395
|
) {
|
|
396
|
+
// console.dir(pTypeScriptAST, { depth: 100 });
|
|
329
397
|
return Boolean(typescript)
|
|
330
398
|
? extractImports(pTypeScriptAST)
|
|
331
399
|
.concat(extractExports(pTypeScriptAST))
|
|
332
400
|
.concat(extractImportEquals(pTypeScriptAST))
|
|
333
401
|
.concat(extractTripleSlashDirectives(pTypeScriptAST))
|
|
334
402
|
.concat(
|
|
335
|
-
extractNestedDependencies(
|
|
403
|
+
extractNestedDependencies(
|
|
404
|
+
pTypeScriptAST,
|
|
405
|
+
pExoticRequireStrings,
|
|
406
|
+
pDetectJSDocImports,
|
|
407
|
+
),
|
|
336
408
|
)
|
|
337
409
|
.map((pModule) => ({ dynamic: false, ...pModule }))
|
|
338
410
|
: /* c8 ignore next */ [];
|
|
@@ -13,13 +13,14 @@ export function shouldUse({ tsPreCompilationDeps, parser }, pFileName) {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export function extract(
|
|
16
|
-
{ baseDir, exoticRequireStrings, moduleSystems },
|
|
16
|
+
{ baseDir, exoticRequireStrings, moduleSystems, detectJSDocImports },
|
|
17
17
|
pFileName,
|
|
18
18
|
pTranspileOptions,
|
|
19
19
|
) {
|
|
20
20
|
return extractTypeScriptDeps(
|
|
21
21
|
getASTCached(join(baseDir, pFileName), pTranspileOptions),
|
|
22
22
|
exoticRequireStrings,
|
|
23
|
+
detectJSDocImports,
|
|
23
24
|
).filter(({ moduleSystem }) => moduleSystems.includes(moduleSystem));
|
|
24
25
|
}
|
|
25
26
|
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { compareRules } from "./compare.mjs";
|
|
2
2
|
import { uniq } from "#utl/array-util.mjs";
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @import { IDependency, IModule } from "../../types/cruise-result.mjs";
|
|
6
|
+
*/
|
|
7
|
+
|
|
4
8
|
function mergeDependency(pLeftDependency, pRightDependency) {
|
|
5
9
|
return {
|
|
6
10
|
...pLeftDependency,
|
|
@@ -30,8 +34,8 @@ function mergeDependencies(pResolvedName, pDependencies) {
|
|
|
30
34
|
}
|
|
31
35
|
|
|
32
36
|
/**
|
|
33
|
-
* @param {
|
|
34
|
-
* @returns {
|
|
37
|
+
* @param {IDependency[]} pDependencies
|
|
38
|
+
* @returns {IDependency[]}
|
|
35
39
|
*/
|
|
36
40
|
function consolidateDependencies(pDependencies) {
|
|
37
41
|
let lDependencies = structuredClone(pDependencies);
|
|
@@ -51,8 +55,8 @@ function consolidateDependencies(pDependencies) {
|
|
|
51
55
|
}
|
|
52
56
|
|
|
53
57
|
/**
|
|
54
|
-
* @param {
|
|
55
|
-
* @returns {
|
|
58
|
+
* @param {IModule} pModule
|
|
59
|
+
* @returns {IModule}
|
|
56
60
|
*/
|
|
57
61
|
export default function consolidateModuleDependencies(pModule) {
|
|
58
62
|
return {
|
|
@@ -5,6 +5,11 @@ import {
|
|
|
5
5
|
dependencyMatchesFilter,
|
|
6
6
|
} from "./match-facade.mjs";
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* @import { IModule } from "../../types/cruise-result.mjs";
|
|
10
|
+
* @import { IStrictReachesType } from "../../types/strict-filter-types.mjs";
|
|
11
|
+
*/
|
|
12
|
+
|
|
8
13
|
function includeOnly(pModules, pIncludeFilter) {
|
|
9
14
|
return pIncludeFilter.path
|
|
10
15
|
? pModules
|
|
@@ -33,9 +38,9 @@ function exclude(pModules, pExcludeFilter) {
|
|
|
33
38
|
}
|
|
34
39
|
/**
|
|
35
40
|
*
|
|
36
|
-
* @param {
|
|
37
|
-
* @param {
|
|
38
|
-
* @returns {
|
|
41
|
+
* @param {IModule[]} pModules
|
|
42
|
+
* @param {IStrictReachesType} pReachesFilter
|
|
43
|
+
* @returns {IModule[]}
|
|
39
44
|
*/
|
|
40
45
|
function filterReaches(pModules, pReachesFilter) {
|
|
41
46
|
const lModuleNamesToReach = pModules
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
/* eslint-disable security/detect-object-injection */
|
|
3
3
|
/**
|
|
4
|
-
* @
|
|
5
|
-
* @
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
* @typedef {import("../../types/shared-types.d.mts").DependencyType} DependencyType
|
|
9
|
-
* @typedef {import("../../types/shared-types.d.mjs").IMiniDependency} IMiniDependency
|
|
10
|
-
*
|
|
11
|
-
* @typedef {(IDependency|IFolderDependency) & {name:string; dependencyTypes?: DependencyType[]}} IEdge
|
|
4
|
+
* @import { IFolderDependency, IDependency, IFolder, IModule } from "../../types/cruise-result.mjs"
|
|
5
|
+
* @import { DependencyType, IMiniDependency } from "../../types/shared-types.mjs"
|
|
6
|
+
|
|
7
|
+
* @typedef {(IDependency|IFolderDependency) & {name:string; dependencyTypes?: DependencyType[]}} IEdge
|
|
12
8
|
* @typedef {IModule|IFolder} IModuleOrFolder
|
|
13
9
|
* @typedef {IModuleOrFolder & {dependencies: IEdge[]}} IVertex
|
|
14
10
|
*/
|
|
@@ -201,7 +197,7 @@ export default class IndexedModuleGraph {
|
|
|
201
197
|
* @param {Set<string>=} pVisited Technical parameter - best to leave out of direct calls
|
|
202
198
|
* @return {Array<IMiniDependency>} see description above
|
|
203
199
|
*/
|
|
204
|
-
#
|
|
200
|
+
#getCycle(pInitialSource, pCurrentDependency, pVisited) {
|
|
205
201
|
let lVisited = pVisited || new Set();
|
|
206
202
|
const lCurrentVertex = this.findVertexByName(pCurrentDependency.name);
|
|
207
203
|
const lEdges = lCurrentVertex.dependencies.filter(
|
|
@@ -226,7 +222,7 @@ export default class IndexedModuleGraph {
|
|
|
226
222
|
*/
|
|
227
223
|
(pAll, pDependency) => {
|
|
228
224
|
if (!pAll.some((pSome) => pSome.name === pCurrentDependency.name)) {
|
|
229
|
-
const lCycle = this.#
|
|
225
|
+
const lCycle = this.#getCycle(
|
|
230
226
|
pInitialSource,
|
|
231
227
|
pDependency,
|
|
232
228
|
lVisited.add(pDependency.name),
|
|
@@ -266,6 +262,6 @@ export default class IndexedModuleGraph {
|
|
|
266
262
|
if (!lCurrentDependency) {
|
|
267
263
|
return [];
|
|
268
264
|
}
|
|
269
|
-
return this.#
|
|
265
|
+
return this.#getCycle(pInitialSource, lCurrentDependency);
|
|
270
266
|
}
|
|
271
267
|
}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import {IFlattenedRuleSet, IForbiddenRuleType} from '../../types/rule-set.mjs';
|
|
3
|
+
*/
|
|
4
|
+
|
|
1
5
|
/**
|
|
2
6
|
* Finds the first rule in the rule set that has name pName,
|
|
3
7
|
* and undefined if no such rule exists/ the rule is an 'allowed'
|
|
@@ -5,9 +9,9 @@
|
|
|
5
9
|
*
|
|
6
10
|
* (this thing probably belongs in a model-like folder and not in utl)
|
|
7
11
|
*
|
|
8
|
-
* @param {
|
|
12
|
+
* @param {IFlattenedRuleSet} pRuleSet - The rule set to search in
|
|
9
13
|
* @param {string} pName - The rule name to look for
|
|
10
|
-
* @return {
|
|
14
|
+
* @return {IForbiddenRuleType|undefined} - a rule (or 'undefined' if nothing found)
|
|
11
15
|
*/
|
|
12
16
|
export function findRuleByName(pRuleSet, pName) {
|
|
13
17
|
const lNamedRules = (pRuleSet?.forbidden ?? []).concat(
|
|
@@ -29,7 +33,7 @@ function ruleHasALicenseLikeAttribute(pRule) {
|
|
|
29
33
|
*
|
|
30
34
|
* Returns false in all other cases
|
|
31
35
|
*
|
|
32
|
-
* @param {
|
|
36
|
+
* @param {IFlattenedRuleSet} pRuleSet
|
|
33
37
|
* @return {boolean}
|
|
34
38
|
*/
|
|
35
39
|
export function ruleSetHasLicenseRule(pRuleSet) {
|
|
@@ -38,9 +42,9 @@ export function ruleSetHasLicenseRule(pRuleSet) {
|
|
|
38
42
|
(pRuleSet?.allowed ?? []).some(ruleHasALicenseLikeAttribute)
|
|
39
43
|
);
|
|
40
44
|
}
|
|
45
|
+
|
|
41
46
|
/**
|
|
42
|
-
*
|
|
43
|
-
* @param {import('../../types/dependency-cruiser').IFlattenedRuleSet} pRuleSet
|
|
47
|
+
* @param {IFlattenedRuleSet} pRuleSet
|
|
44
48
|
* @return {boolean}
|
|
45
49
|
*/
|
|
46
50
|
export function ruleSetHasDeprecationRule(pRuleSet) {
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
import safeRegex from "safe-regex";
|
|
3
3
|
import { getAvailableReporters } from "#report/index.mjs";
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* @import { ICruiseOptions, IFormatOptions } from "../../../types/options.mjs";
|
|
7
|
+
*/
|
|
8
|
+
|
|
5
9
|
const MODULE_SYSTEM_LIST_RE = /^(?:(?:cjs|amd|es6|tsd)(?:,|$)){1,4}/gi;
|
|
6
10
|
const VALID_DEPTH_RE = /^\d{1,2}$/g;
|
|
7
11
|
|
|
@@ -96,7 +100,7 @@ function assertPathsSafety(pFilterOption) {
|
|
|
96
100
|
/**
|
|
97
101
|
* @param {any} pOptions
|
|
98
102
|
* @throws {Error}
|
|
99
|
-
* @returns {
|
|
103
|
+
* @returns {ICruiseOptions}
|
|
100
104
|
*/
|
|
101
105
|
export function assertCruiseOptionsValid(pOptions) {
|
|
102
106
|
let lReturnValue = {};
|
|
@@ -132,7 +136,7 @@ export function assertCruiseOptionsValid(pOptions) {
|
|
|
132
136
|
|
|
133
137
|
/**
|
|
134
138
|
*
|
|
135
|
-
* @param {
|
|
139
|
+
* @param {IFormatOptions} pFormatOptions
|
|
136
140
|
* @throws {Error}
|
|
137
141
|
*/
|
|
138
142
|
export function assertFormatOptionsValid(pFormatOptions) {
|