dependency-cruiser 17.3.10 → 17.4.0
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 +2 -2
- package/src/analyze/summarize/summarize-modules.mjs +2 -0
- package/src/cli/init-config/build-config.mjs +1 -1
- package/src/cli/init-config/check-and-warn-inconsistencies.mjs +111 -0
- package/src/cli/init-config/get-user-input.mjs +1 -1
- package/src/cli/init-config/index.mjs +6 -1
- package/src/cli/init-config/normalize-init-options.mjs +1 -1
- package/src/cli/init-config/types.d.mts +114 -0
- package/src/cli/init-config/write-run-scripts-to-manifest.mjs +1 -1
- package/src/extract/transpile/meta.mjs +32 -10
- package/src/meta.cjs +1 -1
- package/src/report/error-html/error-html-template.mjs +25 -0
- package/src/report/error-html/index.mjs +23 -10
- package/src/report/error-html/utl.mjs +9 -8
- package/src/report/error.mjs +20 -9
- package/src/report/markdown.mjs +8 -5
- package/src/report/utl/index.mjs +60 -0
- package/src/schema/configuration.validate.mjs +1 -1
- package/src/schema/cruise-result.validate.mjs +1 -1
- package/src/utl/try-import.mjs +0 -1
- package/types/reporter-options.d.mts +47 -2
- package/types/violations.d.mts +14 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dependency-cruiser",
|
|
3
|
-
"version": "17.
|
|
3
|
+
"version": "17.4.0",
|
|
4
4
|
"description": "Validate and visualize dependencies. With your rules. JavaScript, TypeScript, CoffeeScript. ES6, CommonJS, AMD.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"static analysis",
|
|
@@ -149,7 +149,7 @@
|
|
|
149
149
|
"acorn-loose": "8.5.2",
|
|
150
150
|
"acorn-walk": "8.3.5",
|
|
151
151
|
"commander": "14.0.3",
|
|
152
|
-
"enhanced-resolve": "5.
|
|
152
|
+
"enhanced-resolve": "5.21.0",
|
|
153
153
|
"ignore": "7.0.5",
|
|
154
154
|
"interpret": "3.1.1",
|
|
155
155
|
"is-installed-globally": "1.0.0",
|
|
@@ -17,6 +17,8 @@ function toDependencyViolationSummary(pRule, pModule, pDependency, pRuleSet) {
|
|
|
17
17
|
type: "dependency",
|
|
18
18
|
from: pModule.source,
|
|
19
19
|
to: pDependency.resolved,
|
|
20
|
+
unresolvedTo: pDependency.module,
|
|
21
|
+
dependencyTypes: pDependency.dependencyTypes,
|
|
20
22
|
rule: pRule,
|
|
21
23
|
};
|
|
22
24
|
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/* eslint-disable prefer-template */
|
|
2
|
+
/**
|
|
3
|
+
* @import { IInitConfig } from "./types.mjs";
|
|
4
|
+
* @import { IAvailableTranspiler } from "../../../types/dependency-cruiser.mjs"
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { EOL } from "node:os";
|
|
8
|
+
import { styleText } from "node:util";
|
|
9
|
+
import { getAvailableTranspilers } from "#extract/transpile/meta.mjs";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* returns true if
|
|
13
|
+
* - typescript features are detected _and_ a typescript compiler is present
|
|
14
|
+
* - no typescript features were detected
|
|
15
|
+
* returns false in all other cases
|
|
16
|
+
*
|
|
17
|
+
* @param {IInitConfig} pInitOptions
|
|
18
|
+
* @param {IAvailableTranspiler[]} pAvailableTranspilers
|
|
19
|
+
* @return {boolean}
|
|
20
|
+
*/
|
|
21
|
+
function typescriptIsConsistent(pInitOptions, pAvailableTranspilers) {
|
|
22
|
+
if (pInitOptions.usesTypeScript) {
|
|
23
|
+
return pAvailableTranspilers.some(
|
|
24
|
+
(pAvailableTranspiler) =>
|
|
25
|
+
pAvailableTranspiler.name === "typescript" &&
|
|
26
|
+
pAvailableTranspiler.available,
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* returns true if
|
|
34
|
+
* - babel features are detected _and_ the babel transpiler is present
|
|
35
|
+
* - no babel features were detected
|
|
36
|
+
* returns false in all other cases
|
|
37
|
+
*
|
|
38
|
+
* @param {IInitConfig} pInitOptions
|
|
39
|
+
* @param {IAvailableTranspiler[]} pAvailableTranspilers
|
|
40
|
+
* @return {boolean}
|
|
41
|
+
*/
|
|
42
|
+
function babelIsConsistent(pInitOptions, pAvailableTranspilers) {
|
|
43
|
+
if (pInitOptions.babelConfig) {
|
|
44
|
+
return pAvailableTranspilers.some(
|
|
45
|
+
(pAvailableTranspiler) =>
|
|
46
|
+
pAvailableTranspiler.name === "babel" && pAvailableTranspiler.available,
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Prints warnings to stderr if there's inconsistencies in the init options.
|
|
54
|
+
* E.g. typescript options are used, but the (microsoft) typescript compiler
|
|
55
|
+
* isn't installed.
|
|
56
|
+
*
|
|
57
|
+
* @param {IInitConfig} pInitOptions
|
|
58
|
+
* @param {NodeJS.WritableStream} [pErrorStream]
|
|
59
|
+
* @param {typeof getAvailableTranspilers} [pAvailableTranspilerFunction]
|
|
60
|
+
* @return {IInitConfig} pInitOptions
|
|
61
|
+
*/
|
|
62
|
+
export function checkAndWarnInconsistencies(
|
|
63
|
+
pInitOptions,
|
|
64
|
+
pErrorStream = process.stderr,
|
|
65
|
+
pAvailableTranspilerFunction = getAvailableTranspilers,
|
|
66
|
+
) {
|
|
67
|
+
const lAvailableTranspilers = pAvailableTranspilerFunction();
|
|
68
|
+
const lWarningMessages = [];
|
|
69
|
+
|
|
70
|
+
if (!typescriptIsConsistent(pInitOptions, lAvailableTranspilers)) {
|
|
71
|
+
lWarningMessages.push(
|
|
72
|
+
EOL +
|
|
73
|
+
" ‼ TypeScript compiler not found" +
|
|
74
|
+
EOL +
|
|
75
|
+
" TypeScript features are used but the TypeScript compiler isn't installed. " +
|
|
76
|
+
EOL +
|
|
77
|
+
" Install it to ensure dependency-cruiser cruises TypeScript sources e.g. by running" +
|
|
78
|
+
EOL +
|
|
79
|
+
EOL +
|
|
80
|
+
" npm i -D typescript" +
|
|
81
|
+
EOL,
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
if (!babelIsConsistent(pInitOptions, lAvailableTranspilers)) {
|
|
85
|
+
lWarningMessages.push(
|
|
86
|
+
EOL +
|
|
87
|
+
" ‼ Babel not found " +
|
|
88
|
+
EOL +
|
|
89
|
+
" Babel features are used but Babel isn't installed. " +
|
|
90
|
+
EOL +
|
|
91
|
+
" Install it to ensure dependency-cruiser takes them into account. E.g. by running" +
|
|
92
|
+
EOL +
|
|
93
|
+
EOL +
|
|
94
|
+
" npm i -D @babel/core" +
|
|
95
|
+
EOL,
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// future features: do the same for ...
|
|
100
|
+
// ... webpack
|
|
101
|
+
// ... svelte
|
|
102
|
+
// ... vue
|
|
103
|
+
// ... coffeescript
|
|
104
|
+
// ... livescript?
|
|
105
|
+
if (lWarningMessages.length > 0) {
|
|
106
|
+
pErrorStream.write(styleText("yellow", lWarningMessages.join("")));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// as it's used in a promise chain ...
|
|
110
|
+
return pInitOptions;
|
|
111
|
+
}
|
|
@@ -4,6 +4,7 @@ import normalizeInitOptions from "./normalize-init-options.mjs";
|
|
|
4
4
|
import buildConfig from "./build-config.mjs";
|
|
5
5
|
import writeConfig from "./write-config.mjs";
|
|
6
6
|
import getUserInput from "./get-user-input.mjs";
|
|
7
|
+
import { checkAndWarnInconsistencies } from "./check-and-warn-inconsistencies.mjs";
|
|
7
8
|
import {
|
|
8
9
|
isLikelyMonoRepo,
|
|
9
10
|
fileExists,
|
|
@@ -22,7 +23,7 @@ import {
|
|
|
22
23
|
import { writeRunScriptsToManifest } from "./write-run-scripts-to-manifest.mjs";
|
|
23
24
|
|
|
24
25
|
/**
|
|
25
|
-
* @import { IInitConfig, IPartialInitConfig, OneShotConfigIDType } from "./types.
|
|
26
|
+
* @import { IInitConfig, IPartialInitConfig, OneShotConfigIDType } from "./types.mjs";
|
|
26
27
|
*/
|
|
27
28
|
|
|
28
29
|
const PACKAGE_MANIFEST = `./${_PACKAGE_MANIFEST}`;
|
|
@@ -95,6 +96,9 @@ export default function initConfig(pInit, pConfigFileName, pStreams) {
|
|
|
95
96
|
if (pInit === true) {
|
|
96
97
|
getUserInput()
|
|
97
98
|
.then(normalizeInitOptions)
|
|
99
|
+
.then((pNormalizedInitOptions) =>
|
|
100
|
+
checkAndWarnInconsistencies(pNormalizedInitOptions, lStreams.stderr),
|
|
101
|
+
)
|
|
98
102
|
.then(buildConfig)
|
|
99
103
|
.then(writeConfig)
|
|
100
104
|
.catch((pError) => {
|
|
@@ -103,6 +107,7 @@ export default function initConfig(pInit, pConfigFileName, pStreams) {
|
|
|
103
107
|
/* c8 ignore stop */
|
|
104
108
|
} else if (pInit !== false) {
|
|
105
109
|
const lNormalizedInitConfig = normalizeInitOptions(getOneShotConfig(pInit));
|
|
110
|
+
checkAndWarnInconsistencies(lNormalizedInitConfig, lStreams.stderr);
|
|
106
111
|
const lConfigFileName = pConfigFileName || getDefaultConfigFileName();
|
|
107
112
|
|
|
108
113
|
if (manifestIsUpdatable(lNormalizedInitConfig)) {
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
export type OneShotConfigIDType = "yes" | "x-scripts";
|
|
2
|
+
|
|
3
|
+
export interface IInitConfig {
|
|
4
|
+
/**
|
|
5
|
+
* Whether or not the current folder houses a mono repo
|
|
6
|
+
*/
|
|
7
|
+
isMonoRepo: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Whether or not the current folder is a package is an ESM package
|
|
10
|
+
* by default (and resolutions of external dependencies should be
|
|
11
|
+
* treated as such)
|
|
12
|
+
*/
|
|
13
|
+
isTypeModule: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Whether or not you allow usage of external dependencies declared in
|
|
16
|
+
* package.jsons of parent folders
|
|
17
|
+
*/
|
|
18
|
+
combinedDependencies: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Whether or not to use a TypeScript config
|
|
21
|
+
*/
|
|
22
|
+
useJsConfig: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* The file name of the TypeScript config to use
|
|
25
|
+
*/
|
|
26
|
+
jsConfig?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Whether or not to use a TypeScript config
|
|
29
|
+
*/
|
|
30
|
+
useTsConfig: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* The file name of the TypeScript config to use
|
|
33
|
+
*/
|
|
34
|
+
tsConfig?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Whether or not to detect JSDoc imports
|
|
37
|
+
*/
|
|
38
|
+
detectJSDocImports?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Whether or not to detect calls to `process.getBuiltinModule`/
|
|
41
|
+
* `globalThis.process.getBuiltinModule` as imports
|
|
42
|
+
*/
|
|
43
|
+
detectProcessBuiltinModuleCalls?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Whether or not to take dependencies into account that only exist before
|
|
46
|
+
* compilation to javascript
|
|
47
|
+
*/
|
|
48
|
+
tsPreCompilationDeps: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Derived attribute. True if the current project likely uses typescript (has a
|
|
51
|
+
* tsconfig, has files with typescript extensions in source and/ or test
|
|
52
|
+
* folders, or has a truthy tsPreCompilationDeps)
|
|
53
|
+
*/
|
|
54
|
+
usesTypeScript: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Whether or not to use a Webpack config
|
|
57
|
+
*/
|
|
58
|
+
useWebpackConfig: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* The file name of the Webpack config to use
|
|
61
|
+
*/
|
|
62
|
+
webpackConfig?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Whether or not to use a Babel config
|
|
65
|
+
*/
|
|
66
|
+
useBabelConfig: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* The file name of the Babel config to use
|
|
69
|
+
*/
|
|
70
|
+
babelConfig?: string;
|
|
71
|
+
/**
|
|
72
|
+
* Whether or not to include some useful scripts in your package.json
|
|
73
|
+
*/
|
|
74
|
+
updateManifest: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* An array of (relative) paths to folders to understand as source code
|
|
77
|
+
*/
|
|
78
|
+
sourceLocation: string[];
|
|
79
|
+
/**
|
|
80
|
+
* Whether tests are housed in a folder separate from sources
|
|
81
|
+
* or are embedded within the source folder
|
|
82
|
+
*/
|
|
83
|
+
hasTestsOutsideSource: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* An array of (relative) paths to folders to understand as test code
|
|
86
|
+
*/
|
|
87
|
+
testLocation?: string[];
|
|
88
|
+
/**
|
|
89
|
+
* Whether or not to explicitly pass extensions to the resolver. When not
|
|
90
|
+
* set explicitly dependency-cruiser will pass it all extensions it knows
|
|
91
|
+
* to handle - which makes it more sure to catch everything, at the trade-off
|
|
92
|
+
* of potentially being slower if the number of extensions used in reality
|
|
93
|
+
* is (a lot) smaller.
|
|
94
|
+
*/
|
|
95
|
+
specifyResolutionExtensions: boolean;
|
|
96
|
+
/**
|
|
97
|
+
* An array of extensions the resolver should use when resolving dependencies
|
|
98
|
+
*/
|
|
99
|
+
resolutionExtensions?: string[];
|
|
100
|
+
/**
|
|
101
|
+
* Dependency-cruiser version used
|
|
102
|
+
*/
|
|
103
|
+
version: string;
|
|
104
|
+
/**
|
|
105
|
+
* (Formatted) date this config is created
|
|
106
|
+
*/
|
|
107
|
+
date: string;
|
|
108
|
+
/**
|
|
109
|
+
* bun is used as package manager cq runtime
|
|
110
|
+
*/
|
|
111
|
+
usesBun: boolean;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export type IPartialInitConfig = Partial<IInitConfig>;
|
|
@@ -59,7 +59,7 @@ const EXPERIMENTAL_SCRIPT_DOC = [
|
|
|
59
59
|
];
|
|
60
60
|
|
|
61
61
|
/**
|
|
62
|
-
* @param {import("./types").IInitConfig} pInitOptions
|
|
62
|
+
* @param {import("./types.d.mts").IInitConfig} pInitOptions
|
|
63
63
|
* @return {any} an bunch of key value pairs that can be plonked into a `scripts` attribute in a package.json
|
|
64
64
|
*/
|
|
65
65
|
export function compileRunScripts(pInitOptions) {
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
isAvailable as swcIsAvailable,
|
|
4
4
|
version as swcVersion,
|
|
5
5
|
} from "../swc/parse.mjs";
|
|
6
|
-
import
|
|
6
|
+
import tryImportAvailable from "./try-import-available.mjs";
|
|
7
7
|
import javascriptWrap from "./javascript-wrap.mjs";
|
|
8
8
|
import babelWrap from "./babel-wrap.mjs";
|
|
9
9
|
import coffeeScriptWrapFunction from "./coffeescript-wrap.mjs";
|
|
@@ -13,6 +13,10 @@ import typescriptWrapFunction from "./typescript-wrap.mjs";
|
|
|
13
13
|
import vueTemplateWrap from "./vue-template-wrap.cjs";
|
|
14
14
|
import meta from "#meta.cjs";
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* @import { IAvailableTranspiler } from "../../../types/dependency-cruiser.mjs";
|
|
18
|
+
*/
|
|
19
|
+
|
|
16
20
|
const swcWrap = {
|
|
17
21
|
isAvailable: () => swcIsAvailable(),
|
|
18
22
|
version: () => swcVersion(),
|
|
@@ -23,25 +27,43 @@ const typescriptWrap = typescriptWrapFunction("esm");
|
|
|
23
27
|
|
|
24
28
|
function gotCoffee() {
|
|
25
29
|
return (
|
|
26
|
-
|
|
27
|
-
|
|
30
|
+
tryImportAvailable(
|
|
31
|
+
"coffeescript",
|
|
32
|
+
meta.supportedTranspilers.coffeescript,
|
|
33
|
+
) ||
|
|
34
|
+
/* c8 ignore start */
|
|
35
|
+
// fallback for ancient versions of the coffeescript compilers
|
|
36
|
+
tryImportAvailable(
|
|
37
|
+
"coffee-script",
|
|
38
|
+
meta.supportedTranspilers["coffee-script"],
|
|
39
|
+
)
|
|
40
|
+
/* c8 ignore stop */
|
|
28
41
|
);
|
|
29
42
|
}
|
|
30
43
|
|
|
31
44
|
const TRANSPILER2AVAILABLE = {
|
|
32
|
-
babel:
|
|
45
|
+
babel: tryImportAvailable("@babel/core", meta.supportedTranspilers.babel),
|
|
33
46
|
javascript: true,
|
|
34
47
|
"coffee-script": gotCoffee(),
|
|
35
48
|
coffeescript: gotCoffee(),
|
|
36
|
-
livescript:
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
49
|
+
livescript: tryImportAvailable(
|
|
50
|
+
"livescript",
|
|
51
|
+
meta.supportedTranspilers.livescript,
|
|
52
|
+
),
|
|
53
|
+
svelte: tryImportAvailable(
|
|
54
|
+
"svelte/compiler",
|
|
55
|
+
meta.supportedTranspilers.svelte,
|
|
56
|
+
),
|
|
57
|
+
swc: tryImportAvailable("@swc/core", meta.supportedTranspilers.swc),
|
|
58
|
+
typescript: tryImportAvailable(
|
|
59
|
+
"typescript",
|
|
60
|
+
meta.supportedTranspilers.typescript,
|
|
61
|
+
),
|
|
62
|
+
"vue-template-compiler": tryImportAvailable(
|
|
41
63
|
"vue-template-compiler",
|
|
42
64
|
meta.supportedTranspilers["vue-template-compiler"],
|
|
43
65
|
),
|
|
44
|
-
"@vue/compiler-sfc":
|
|
66
|
+
"@vue/compiler-sfc": tryImportAvailable(
|
|
45
67
|
"@vue/compiler-sfc",
|
|
46
68
|
meta.supportedTranspilers["@vue/compiler-sfc"],
|
|
47
69
|
),
|
package/src/meta.cjs
CHANGED
|
@@ -159,6 +159,31 @@ export default `<!DOCTYPE html>
|
|
|
159
159
|
.extra {
|
|
160
160
|
color: gray;
|
|
161
161
|
}
|
|
162
|
+
.dependency-type {
|
|
163
|
+
font-family: courier;
|
|
164
|
+
padding: 4px;
|
|
165
|
+
border-radius: 3px;
|
|
166
|
+
}
|
|
167
|
+
.local {
|
|
168
|
+
background-color: lightgray;
|
|
169
|
+
color: black;
|
|
170
|
+
}
|
|
171
|
+
.npm-bundled, .npm-dev, .npm-no-pkg, .npm-optional, .npm-peer, .npm-unknown, .npm {
|
|
172
|
+
background-color: darkred;
|
|
173
|
+
color: white;
|
|
174
|
+
}
|
|
175
|
+
.aliased {
|
|
176
|
+
background-color: blue;
|
|
177
|
+
color: white;
|
|
178
|
+
}
|
|
179
|
+
.aliased-subpath-import, .core {
|
|
180
|
+
background-color: green;
|
|
181
|
+
color: white;
|
|
182
|
+
}
|
|
183
|
+
.type-import, .type-only {
|
|
184
|
+
background-color: blue;
|
|
185
|
+
color: white;
|
|
186
|
+
}
|
|
162
187
|
</style>
|
|
163
188
|
<style type="text/css" media="print">
|
|
164
189
|
th,
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
} from "./utl.mjs";
|
|
6
6
|
import template from "./error-html-template.mjs";
|
|
7
7
|
import meta from "#meta.cjs";
|
|
8
|
+
import { getOneLetterDependencyType } from "#report/utl/index.mjs";
|
|
8
9
|
|
|
9
10
|
function getViolatedRuleRowClass(pViolatedRule) {
|
|
10
11
|
return pViolatedRule.unviolated ? ' class="unviolated"' : "";
|
|
@@ -76,13 +77,13 @@ function constructViolatedRulesTable(pResults) {
|
|
|
76
77
|
function getViolationRowClass(pViolation) {
|
|
77
78
|
return pViolation.rule.severity === "ignore" ? ' class="ignored"' : "";
|
|
78
79
|
}
|
|
79
|
-
|
|
80
80
|
/**
|
|
81
81
|
* @param {import('../../../types/cruise-result.mjs').IViolation} pViolation
|
|
82
82
|
* @returns {string}
|
|
83
83
|
*/
|
|
84
|
-
function constructViolationRow(pPrefix) {
|
|
84
|
+
function constructViolationRow(pPrefix, pOptions) {
|
|
85
85
|
return (pViolation) => {
|
|
86
|
+
const lDependencyTypes = pViolation?.dependencyTypes ?? [];
|
|
86
87
|
return ` <tr${getViolationRowClass(pViolation)}>
|
|
87
88
|
<td class="${pViolation.rule.severity}">${pViolation.rule.severity}</td>
|
|
88
89
|
<td class="nowrap">
|
|
@@ -93,7 +94,8 @@ function constructViolationRow(pPrefix) {
|
|
|
93
94
|
<td><a href="${pPrefix}${pViolation.from}">${
|
|
94
95
|
pViolation.from
|
|
95
96
|
}</a>${determineFromExtras(pViolation)}</td>
|
|
96
|
-
<td>${
|
|
97
|
+
<td><span class="dependency-type ${lDependencyTypes.join(" ")}" title="dependency types: ${lDependencyTypes.join(", ")}">${getOneLetterDependencyType(lDependencyTypes)}</span></td>
|
|
98
|
+
<td>${determineTo(pViolation, pOptions)}</td>
|
|
97
99
|
</tr>`;
|
|
98
100
|
};
|
|
99
101
|
}
|
|
@@ -102,7 +104,7 @@ function constructViolationRow(pPrefix) {
|
|
|
102
104
|
* @param {import('../../../types/cruise-result.mjs').ICruiseResult} pResults
|
|
103
105
|
* @returns {string}
|
|
104
106
|
*/
|
|
105
|
-
function constructViolationsList(pResults) {
|
|
107
|
+
function constructViolationsList(pResults, pOptions) {
|
|
106
108
|
if (pResults.summary.violations.length > 0) {
|
|
107
109
|
return `<span id="show-ignored-violations">
|
|
108
110
|
<h2><svg class="p__svg--inline" viewBox="0 0 12 16" version="1.1" aria-hidden="true">
|
|
@@ -116,17 +118,23 @@ function constructViolationsList(pResults) {
|
|
|
116
118
|
<th>severity</th>
|
|
117
119
|
<th>rule</th>
|
|
118
120
|
<th>from</th>
|
|
121
|
+
<th>types</th>
|
|
119
122
|
<th>to</th>
|
|
120
123
|
</tr>
|
|
121
124
|
</thead>
|
|
122
125
|
<tbody>
|
|
123
126
|
${pResults.summary.violations
|
|
124
|
-
.map(
|
|
127
|
+
.map(
|
|
128
|
+
constructViolationRow(
|
|
129
|
+
pResults.summary.optionsUsed.prefix ?? "",
|
|
130
|
+
pOptions,
|
|
131
|
+
),
|
|
132
|
+
)
|
|
125
133
|
.join("\n")}
|
|
126
134
|
${
|
|
127
135
|
pResults.summary.ignore > 0
|
|
128
136
|
? `<tr>
|
|
129
|
-
<td colspan="
|
|
137
|
+
<td colspan="5" class="controls">
|
|
130
138
|
<div id="show-ignored">
|
|
131
139
|
↓ <a href="#show-ignored-violations">also show ignored violations</a>
|
|
132
140
|
</div>
|
|
@@ -149,7 +157,12 @@ function constructViolationsList(pResults) {
|
|
|
149
157
|
* @param {import('../../../types/cruise-result.mjs')} pResults
|
|
150
158
|
* @returns {string}
|
|
151
159
|
*/
|
|
152
|
-
function report(pResults) {
|
|
160
|
+
function report(pResults, pOptions) {
|
|
161
|
+
const lOptions = {
|
|
162
|
+
showExternalModulesUnresolved: false,
|
|
163
|
+
showAliasedModulesUnresolved: false,
|
|
164
|
+
...pOptions,
|
|
165
|
+
};
|
|
153
166
|
return template
|
|
154
167
|
.replace("{{totalCruised}}", pResults.summary.totalCruised)
|
|
155
168
|
.replace(
|
|
@@ -161,7 +174,7 @@ function report(pResults) {
|
|
|
161
174
|
.replace("{{info}}", pResults.summary.info)
|
|
162
175
|
.replace("{{ignore}}", pResults.summary.ignore ?? 0)
|
|
163
176
|
.replace("{{violatedRulesTable}}", constructViolatedRulesTable(pResults))
|
|
164
|
-
.replace("{{violationsList}}", constructViolationsList(pResults))
|
|
177
|
+
.replace("{{violationsList}}", constructViolationsList(pResults, lOptions))
|
|
165
178
|
.replace("{{depcruiseVersion}}", `dependency-cruiser@${meta.version}`)
|
|
166
179
|
.replace("{{runDate}}", new Date().toISOString());
|
|
167
180
|
}
|
|
@@ -173,9 +186,9 @@ function report(pResults) {
|
|
|
173
186
|
* @returns {import("../../../types/dependency-cruiser.js").IReporterOutput} - output: an html program showing the summary & the violations (if any)
|
|
174
187
|
* exitCode: 0
|
|
175
188
|
*/
|
|
176
|
-
export default function errorHtml(pResults) {
|
|
189
|
+
export default function errorHtml(pResults, pOptions) {
|
|
177
190
|
return {
|
|
178
|
-
output: report(pResults),
|
|
191
|
+
output: report(pResults, pOptions || {}),
|
|
179
192
|
exitCode: 0,
|
|
180
193
|
};
|
|
181
194
|
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
formatViolation,
|
|
3
|
+
formatPercentage,
|
|
4
|
+
formatDependencyTo,
|
|
5
|
+
} from "../utl/index.mjs";
|
|
2
6
|
import meta from "#meta.cjs";
|
|
3
7
|
|
|
4
8
|
export function getFormattedAllowedRule(pRuleSetUsed) {
|
|
@@ -40,21 +44,17 @@ function formatReachabilityTo(pViolation) {
|
|
|
40
44
|
.join(" →<br/>")}`;
|
|
41
45
|
}
|
|
42
46
|
|
|
43
|
-
function formatDependencyTo(pViolation) {
|
|
44
|
-
return pViolation.to;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
47
|
function formatModuleTo() {
|
|
48
48
|
return "";
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
function formatInstabilityTo(pViolation) {
|
|
52
|
-
return `${pViolation
|
|
51
|
+
function formatInstabilityTo(pViolation, pOptions) {
|
|
52
|
+
return `${formatDependencyTo(pViolation, pOptions)} <span class="extra">(I: ${formatPercentage(
|
|
53
53
|
pViolation.metrics.to.instability,
|
|
54
54
|
)})</span>`;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
export function determineTo(pViolation) {
|
|
57
|
+
export function determineTo(pViolation, pOptions) {
|
|
58
58
|
const lViolationType2Formatter = {
|
|
59
59
|
dependency: formatDependencyTo,
|
|
60
60
|
module: formatModuleTo,
|
|
@@ -66,6 +66,7 @@ export function determineTo(pViolation) {
|
|
|
66
66
|
pViolation,
|
|
67
67
|
lViolationType2Formatter,
|
|
68
68
|
formatDependencyTo,
|
|
69
|
+
pOptions,
|
|
69
70
|
);
|
|
70
71
|
}
|
|
71
72
|
|
package/src/report/error.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import { styleText } from "node:util";
|
|
|
3
3
|
import {
|
|
4
4
|
formatPercentage,
|
|
5
5
|
formatViolation as _formatViolation,
|
|
6
|
+
formatDependencyTo,
|
|
6
7
|
} from "./utl/index.mjs";
|
|
7
8
|
import { findRuleByName } from "#graph-utl/rule-set.mjs";
|
|
8
9
|
import wrapAndIndent from "#utl/wrap-and-indent.mjs";
|
|
@@ -29,8 +30,8 @@ function formatModuleViolation(pViolation) {
|
|
|
29
30
|
return styleText("bold", pViolation.from);
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
function formatDependencyViolation(pViolation) {
|
|
33
|
-
return `${styleText("bold", pViolation.from)} → ${styleText("bold", pViolation
|
|
33
|
+
function formatDependencyViolation(pViolation, pOptions) {
|
|
34
|
+
return `${styleText("bold", pViolation.from)} → ${styleText("bold", formatDependencyTo(pViolation, pOptions))}`;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
function formatCycleViolation(pViolation) {
|
|
@@ -41,8 +42,8 @@ function formatReachabilityViolation(pViolation) {
|
|
|
41
42
|
return `${styleText("bold", pViolation.from)} → ${styleText("bold", pViolation.to)}${formatMiniDependency(pViolation.via)}`;
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
function formatInstabilityViolation(pViolation) {
|
|
45
|
-
return `${formatDependencyViolation(pViolation)}${EOL}${styleText(
|
|
45
|
+
function formatInstabilityViolation(pViolation, pOptions) {
|
|
46
|
+
return `${formatDependencyViolation(pViolation, pOptions)}${EOL}${styleText(
|
|
46
47
|
"dim",
|
|
47
48
|
wrapAndIndent(
|
|
48
49
|
`instability: ${formatPercentage(pViolation.metrics.from.instability)} → ${formatPercentage(pViolation.metrics.to.instability)}`,
|
|
@@ -51,7 +52,7 @@ function formatInstabilityViolation(pViolation) {
|
|
|
51
52
|
)}`;
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
function formatViolation(pViolation) {
|
|
55
|
+
function formatViolation(pViolation, pOptions) {
|
|
55
56
|
const lViolationType2Formatter = {
|
|
56
57
|
module: formatModuleViolation,
|
|
57
58
|
dependency: formatDependencyViolation,
|
|
@@ -63,6 +64,7 @@ function formatViolation(pViolation) {
|
|
|
63
64
|
pViolation,
|
|
64
65
|
lViolationType2Formatter,
|
|
65
66
|
formatDependencyViolation,
|
|
67
|
+
pOptions,
|
|
66
68
|
);
|
|
67
69
|
|
|
68
70
|
return (
|
|
@@ -115,7 +117,13 @@ function formatIgnoreWarning(pNumberOfIgnoredViolations) {
|
|
|
115
117
|
return "";
|
|
116
118
|
}
|
|
117
119
|
|
|
118
|
-
function report(pResults,
|
|
120
|
+
function report(pResults, pOptions) {
|
|
121
|
+
const lOptions = {
|
|
122
|
+
long: false,
|
|
123
|
+
showExternalModulesUnresolved: false,
|
|
124
|
+
showAliasedModulesUnresolved: false,
|
|
125
|
+
...pOptions,
|
|
126
|
+
};
|
|
119
127
|
const lNonIgnorableViolations = pResults.summary.violations.filter(
|
|
120
128
|
(pViolation) => pViolation.rule.severity !== "ignore",
|
|
121
129
|
);
|
|
@@ -132,8 +140,11 @@ function report(pResults, pLong) {
|
|
|
132
140
|
|
|
133
141
|
return lNonIgnorableViolations
|
|
134
142
|
.reverse()
|
|
135
|
-
.map(addExplanation(pResults.summary.ruleSetUsed,
|
|
136
|
-
.reduce(
|
|
143
|
+
.map(addExplanation(pResults.summary.ruleSetUsed, lOptions.long))
|
|
144
|
+
.reduce(
|
|
145
|
+
(pAll, pThis) => `${pAll} ${formatViolation(pThis, lOptions)}${EOL}`,
|
|
146
|
+
EOL,
|
|
147
|
+
)
|
|
137
148
|
.concat(formatSummary(pResults.summary))
|
|
138
149
|
.concat(formatIgnoreWarning(pResults.summary.ignore))
|
|
139
150
|
.concat(EOL);
|
|
@@ -154,7 +165,7 @@ function report(pResults, pLong) {
|
|
|
154
165
|
*/
|
|
155
166
|
export default function error(pResults, pOptions) {
|
|
156
167
|
return {
|
|
157
|
-
output: report(pResults,
|
|
168
|
+
output: report(pResults, pOptions || {}),
|
|
158
169
|
exitCode: pResults.summary.error,
|
|
159
170
|
};
|
|
160
171
|
}
|