dependency-cruiser 16.1.0 → 16.2.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/bin/dependency-cruise.mjs +18 -23
- package/package.json +3 -3
- package/src/cli/init-config/index.mjs +1 -1
- package/src/cli/init-config/types.d.ts +1 -1
- package/src/cli/tools/wrap-stream-in-html.mjs +9 -42
- package/src/cli/utl/io.mjs +7 -5
- package/src/meta.js +1 -1
- package/src/report/anon/index.mjs +11 -5
- package/src/report/baseline.mjs +7 -5
- package/src/report/dot-webpage/dot-module.mjs +77 -0
- package/src/report/dot-webpage/wrap-in-html.mjs +62 -0
- package/src/report/error-html/error-html-template.mjs +2 -1
- package/src/report/html/html-template.mjs +2 -1
- package/src/report/index.mjs +1 -0
- package/src/report/json.mjs +2 -1
- package/src/report/teamcity.mjs +5 -3
- package/src/report/text.mjs +13 -11
- package/types/restrictions.d.mts +0 -2
- package/types/rule-set.d.mts +4 -7
- /package/src/{cli/tools → report/dot-webpage}/svg-in-html-snippets/script.js +0 -0
- /package/src/{cli/tools → report/dot-webpage}/svg-in-html-snippets/style.css +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { EOL } from "node:os";
|
|
3
|
-
import { program } from "commander";
|
|
3
|
+
import { program, Option } from "commander";
|
|
4
4
|
import assertNodeEnvironmentSuitable from "#cli/assert-node-environment-suitable.mjs";
|
|
5
5
|
import cli from "#cli/index.mjs";
|
|
6
6
|
import meta from "#meta.js";
|
|
@@ -22,7 +22,7 @@ try {
|
|
|
22
22
|
true,
|
|
23
23
|
)
|
|
24
24
|
.addOption(
|
|
25
|
-
new
|
|
25
|
+
new Option(
|
|
26
26
|
"--no-config",
|
|
27
27
|
"do not use a configuration file. " +
|
|
28
28
|
"Overrides any --config option set earlier",
|
|
@@ -34,7 +34,7 @@ try {
|
|
|
34
34
|
"err",
|
|
35
35
|
)
|
|
36
36
|
.option("-m, --metrics", "calculate stability metrics", false)
|
|
37
|
-
.addOption(new
|
|
37
|
+
.addOption(new Option("--no-metrics").hideHelp(true))
|
|
38
38
|
.option(
|
|
39
39
|
"-f, --output-to <file>",
|
|
40
40
|
"file to write output to; - for stdout",
|
|
@@ -71,21 +71,21 @@ try {
|
|
|
71
71
|
"--ignore-known [file]",
|
|
72
72
|
"ignore known violations as saved in [file] (default: .dependency-cruiser-known-violations.json)",
|
|
73
73
|
)
|
|
74
|
-
.addOption(new
|
|
74
|
+
.addOption(new Option("--no-ignore-known").hideHelp(true))
|
|
75
75
|
.addOption(
|
|
76
|
-
new
|
|
76
|
+
new Option(
|
|
77
77
|
"--ts-config [file]",
|
|
78
78
|
"use a TypeScript configuration (e.g. tsconfig.json) or it's JavaScript counterpart (e.g. jsconfig.json)",
|
|
79
79
|
).hideHelp(true),
|
|
80
80
|
)
|
|
81
81
|
.addOption(
|
|
82
|
-
new
|
|
82
|
+
new Option(
|
|
83
83
|
"--webpack-config [file]",
|
|
84
84
|
"use a webpack configuration (e.g. webpack.config.js)",
|
|
85
85
|
).hideHelp(true),
|
|
86
86
|
)
|
|
87
87
|
.addOption(
|
|
88
|
-
new
|
|
88
|
+
new Option(
|
|
89
89
|
"--ts-pre-compilation-deps",
|
|
90
90
|
"detect dependencies that only exist before typescript-to-javascript " +
|
|
91
91
|
"compilation (off by default)",
|
|
@@ -98,25 +98,23 @@ try {
|
|
|
98
98
|
"modules/ folders directly under your packages folder. ",
|
|
99
99
|
)
|
|
100
100
|
.addOption(
|
|
101
|
-
new
|
|
101
|
+
new Option(
|
|
102
102
|
"-p, --progress [type]",
|
|
103
103
|
"show progress while dependency-cruiser is busy",
|
|
104
104
|
).choices(["cli-feedback", "performance-log", "ndjson", "none"]),
|
|
105
105
|
)
|
|
106
106
|
.addOption(
|
|
107
|
-
new
|
|
108
|
-
true,
|
|
109
|
-
),
|
|
107
|
+
new Option("--no-progress", "Alias of --progress none").hideHelp(true),
|
|
110
108
|
)
|
|
111
109
|
.addOption(
|
|
112
|
-
new
|
|
110
|
+
new Option(
|
|
113
111
|
"-d, --max-depth <n>",
|
|
114
|
-
"
|
|
112
|
+
"you probably want to use --collapse instead of --max-depth. " +
|
|
115
113
|
"(max-depth would limit the cruise depth; 0 <= n <= 99 (default: 0 - no limit)).",
|
|
116
114
|
).hideHelp(true),
|
|
117
115
|
)
|
|
118
116
|
.addOption(
|
|
119
|
-
new
|
|
117
|
+
new Option(
|
|
120
118
|
"-M, --module-systems <items>",
|
|
121
119
|
"list of module systems (default: amd, cjs, es6, tsd)",
|
|
122
120
|
).hideHelp(true),
|
|
@@ -127,33 +125,30 @@ try {
|
|
|
127
125
|
)
|
|
128
126
|
.option(
|
|
129
127
|
"-C, --cache [cache-directory]",
|
|
130
|
-
"
|
|
128
|
+
"use a cache to speed up execution. " +
|
|
131
129
|
"The directory defaults to node_modules/.cache/dependency-cruiser",
|
|
132
130
|
)
|
|
133
131
|
.addOption(
|
|
134
|
-
new
|
|
132
|
+
new Option(
|
|
135
133
|
"--cache-strategy <strategy>",
|
|
136
|
-
"
|
|
134
|
+
"strategy to use for detecting changed files in the cache.",
|
|
137
135
|
).choices(["metadata", "content"]),
|
|
138
136
|
)
|
|
139
137
|
.addOption(
|
|
140
|
-
new
|
|
138
|
+
new Option(
|
|
141
139
|
"--no-cache",
|
|
142
140
|
"switch off caching. Overrides the 'cache' key in .dependency-cruiser.js " +
|
|
143
141
|
"and --cache options set earlier on the command line",
|
|
144
142
|
).hideHelp(true),
|
|
145
143
|
)
|
|
146
144
|
.addOption(
|
|
147
|
-
new
|
|
145
|
+
new Option(
|
|
148
146
|
"--preserve-symlinks",
|
|
149
147
|
"leave symlinks unchanged (off by default)",
|
|
150
148
|
).hideHelp(true),
|
|
151
149
|
)
|
|
152
150
|
.addOption(
|
|
153
|
-
new
|
|
154
|
-
"-v, --validate [file]",
|
|
155
|
-
`alias for --config`,
|
|
156
|
-
).hideHelp(true),
|
|
151
|
+
new Option("-v, --validate [file]", `alias for --config`).hideHelp(true),
|
|
157
152
|
)
|
|
158
153
|
.option(
|
|
159
154
|
"-i, --info",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dependency-cruiser",
|
|
3
|
-
"version": "16.
|
|
3
|
+
"version": "16.2.0",
|
|
4
4
|
"description": "Validate and visualize dependencies. With your rules. JavaScript, TypeScript, CoffeeScript. ES6, CommonJS, AMD.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"static analysis",
|
|
@@ -106,10 +106,10 @@
|
|
|
106
106
|
"acorn-walk": "8.3.2",
|
|
107
107
|
"ajv": "8.12.0",
|
|
108
108
|
"chalk": "5.3.0",
|
|
109
|
-
"commander": "
|
|
109
|
+
"commander": "12.0.0",
|
|
110
110
|
"enhanced-resolve": "5.15.0",
|
|
111
111
|
"figures": "6.0.1",
|
|
112
|
-
"ignore": "5.3.
|
|
112
|
+
"ignore": "5.3.1",
|
|
113
113
|
"indent-string": "5.0.0",
|
|
114
114
|
"interpret": "^3.1.1",
|
|
115
115
|
"is-installed-globally": "1.0.0",
|
|
@@ -1,53 +1,20 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
|
+
import { getHeader, getFooter } from "#report/dot-webpage/wrap-in-html.mjs";
|
|
3
4
|
|
|
4
5
|
const STYLESHEET_FILE = fileURLToPath(
|
|
5
|
-
new URL(
|
|
6
|
+
new URL(
|
|
7
|
+
"../../report/dot-webpage/svg-in-html-snippets/style.css",
|
|
8
|
+
import.meta.url,
|
|
9
|
+
),
|
|
6
10
|
);
|
|
7
11
|
const SCRIPT_FILE = fileURLToPath(
|
|
8
|
-
new URL(
|
|
12
|
+
new URL(
|
|
13
|
+
"../../report/dot-webpage/svg-in-html-snippets/script.js",
|
|
14
|
+
import.meta.url,
|
|
15
|
+
),
|
|
9
16
|
);
|
|
10
17
|
|
|
11
|
-
/**
|
|
12
|
-
* @param {string} pStylesheet
|
|
13
|
-
* @returns {string}
|
|
14
|
-
*/
|
|
15
|
-
function getHeader(pStylesheet) {
|
|
16
|
-
return `<!doctype html>
|
|
17
|
-
<html lang="en" dir="ltr">
|
|
18
|
-
<head>
|
|
19
|
-
<meta charset="utf-8" />
|
|
20
|
-
<title>dependency graph</title>
|
|
21
|
-
<style>
|
|
22
|
-
${pStylesheet}
|
|
23
|
-
</style>
|
|
24
|
-
</head>
|
|
25
|
-
<body>
|
|
26
|
-
<button id="button_help">?</button>
|
|
27
|
-
<div id="hints" class="hint" style="display: none">
|
|
28
|
-
<button id="close-hints">x</button>
|
|
29
|
-
<span id="hint-text"></span>
|
|
30
|
-
<ul>
|
|
31
|
-
<li><b>Hover</b> - highlight</li>
|
|
32
|
-
<li><b>Right-click</b> - pin highlight</li>
|
|
33
|
-
<li><b>ESC</b> - clear</li>
|
|
34
|
-
</ul>
|
|
35
|
-
</div>
|
|
36
|
-
`;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* @param {string} pScript
|
|
41
|
-
* @returns {string}
|
|
42
|
-
*/
|
|
43
|
-
function getFooter(pScript) {
|
|
44
|
-
return ` <script>
|
|
45
|
-
${pScript}
|
|
46
|
-
</script>
|
|
47
|
-
</body>
|
|
48
|
-
</html>`;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
18
|
/**
|
|
52
19
|
* Slaps the stuff in the passed stream in between the contents
|
|
53
20
|
* of the header and the footer and returns it as a string.
|
package/src/cli/utl/io.mjs
CHANGED
|
@@ -40,13 +40,15 @@ function writeToStdOut(pString, pBufferSize = PIPE_BUFFER_SIZE) {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
export function write(pOutputTo, pContent) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
// previously we checked here to ensure pContent ended on an EOL (and if it
|
|
44
|
+
// didn't we added one). As for one or two reporters we DON'T want this
|
|
45
|
+
// to happen automatically (e.g. the 'null' one) we've moved that check
|
|
46
|
+
// to the individual reporters and with a unit test ensured that all
|
|
47
|
+
// reporters (current and future) keep doing that.
|
|
46
48
|
if ("-" === pOutputTo) {
|
|
47
|
-
writeToStdOut(
|
|
49
|
+
writeToStdOut(pContent);
|
|
48
50
|
} else {
|
|
49
|
-
writeToFile(pOutputTo,
|
|
51
|
+
writeToFile(pOutputTo, pContent);
|
|
50
52
|
}
|
|
51
53
|
}
|
|
52
54
|
|
package/src/meta.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import has from "lodash/has.js";
|
|
2
2
|
import { anonymizePath, WHITELIST_RE } from "./anonymize-path.mjs";
|
|
3
3
|
|
|
4
|
+
const EOL = "\n";
|
|
5
|
+
|
|
4
6
|
function anonymizePathArray(pPathArray, pWordList) {
|
|
5
7
|
// the coverage ignore is here because the || [] branch isn't taken when running
|
|
6
8
|
// tests and with the current setup of the anonymize module that's not going
|
|
@@ -182,11 +184,15 @@ export default function reportAnonymous(pResults, pAnonymousReporterOptions) {
|
|
|
182
184
|
pResults?.summary?.optionsUsed?.reporterOptions?.anon?.wordlist ?? [];
|
|
183
185
|
}
|
|
184
186
|
return {
|
|
185
|
-
output:
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
187
|
+
output:
|
|
188
|
+
JSON.stringify(
|
|
189
|
+
anonymize(
|
|
190
|
+
pResults,
|
|
191
|
+
sanitizeWordList(lAnonymousReporterOptions.wordlist),
|
|
192
|
+
),
|
|
193
|
+
null,
|
|
194
|
+
" ",
|
|
195
|
+
) + EOL,
|
|
190
196
|
exitCode: 0,
|
|
191
197
|
};
|
|
192
198
|
}
|
package/src/report/baseline.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const DEFAULT_JSON_INDENT = 2;
|
|
2
|
+
const EOL = "\n";
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Sample plugin
|
|
@@ -12,11 +13,12 @@ const DEFAULT_JSON_INDENT = 2;
|
|
|
12
13
|
*/
|
|
13
14
|
export default function baseline(pCruiseResult) {
|
|
14
15
|
return {
|
|
15
|
-
output:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
output:
|
|
17
|
+
JSON.stringify(
|
|
18
|
+
pCruiseResult.summary.violations,
|
|
19
|
+
null,
|
|
20
|
+
DEFAULT_JSON_INDENT,
|
|
21
|
+
) + EOL,
|
|
20
22
|
exitCode: 0,
|
|
21
23
|
};
|
|
22
24
|
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import dotModuleReporter from "../dot/dot-module.mjs";
|
|
4
|
+
import { wrapInHTML } from "./wrap-in-html.mjs";
|
|
5
|
+
|
|
6
|
+
const CONSTANTS = {
|
|
7
|
+
exec: "dot",
|
|
8
|
+
format: "svg",
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {string} pDot Dot program
|
|
13
|
+
* @param {IDotWebpageReporterOptions} pOptions
|
|
14
|
+
* @returns {string} the dot program converted to svg, wrapped in html
|
|
15
|
+
*/
|
|
16
|
+
function convert(pDot, pOptions) {
|
|
17
|
+
/* c8 ignore next */
|
|
18
|
+
const lSpawnFunction = pOptions.spawnFunction || spawnSync;
|
|
19
|
+
const { stdout, status, error } = lSpawnFunction(
|
|
20
|
+
CONSTANTS.exec,
|
|
21
|
+
[`-T${CONSTANTS.format}`],
|
|
22
|
+
{
|
|
23
|
+
input: pDot,
|
|
24
|
+
},
|
|
25
|
+
);
|
|
26
|
+
if (status === 0) {
|
|
27
|
+
return stdout.toString("binary");
|
|
28
|
+
} else if (error) {
|
|
29
|
+
throw error;
|
|
30
|
+
} else {
|
|
31
|
+
throw new Error(`GraphViz' dot returned an error (exit code ${status})`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @param {IDotWebpageReporterOptions} pOptions
|
|
37
|
+
* @returns {boolean}
|
|
38
|
+
*/
|
|
39
|
+
function isAvailable(pOptions) {
|
|
40
|
+
/* c8 ignore next */
|
|
41
|
+
const lSpawnFunction = pOptions.spawnFunction || spawnSync;
|
|
42
|
+
const { status, stderr } = lSpawnFunction(CONSTANTS.exec, ["-V"]);
|
|
43
|
+
return (
|
|
44
|
+
status === 0 && stderr.toString("utf8").startsWith("dot - graphviz version")
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @typedef {import("../../../types/cruise-result.mjs").ICruiseResult} ICruiseResult
|
|
50
|
+
* @typedef {import("../../../types/reporter-options.mjs").IDotReporterOptions} IDotReporterOptions
|
|
51
|
+
* @typedef {import("../../../types/dependency-cruiser.mjs").IReporterOutput} IReporterOutput
|
|
52
|
+
* @typedef {IDotReporterOptions & { spawnFunction?: typeof spawnSync }} IDotWebpageReporterOptions
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Returns the results of a cruise as an svg picture, using the dot reporter
|
|
57
|
+
* and a system call to the GraphViz dot executable.
|
|
58
|
+
*
|
|
59
|
+
* @param {ICruiseResult} pResults
|
|
60
|
+
* @param {IDotWebpageReporterOptions} pDotWebpageReporterOptions
|
|
61
|
+
* @returns {IReporterOutput}
|
|
62
|
+
*/
|
|
63
|
+
export default function dotWebpage(pResults, pDotWebpageReporterOptions) {
|
|
64
|
+
const { output } = dotModuleReporter(pResults, pDotWebpageReporterOptions);
|
|
65
|
+
|
|
66
|
+
if (!isAvailable(pDotWebpageReporterOptions)) {
|
|
67
|
+
throw new Error(
|
|
68
|
+
"GraphViz dot, which is required for the 'x-dot-webpage' reporter doesn't " +
|
|
69
|
+
"seem to be available on this system. See the GraphViz download page for " +
|
|
70
|
+
"instruction on how to get it on your system: https://www.graphviz.org/download/",
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
output: wrapInHTML(convert(output, pDotWebpageReporterOptions)),
|
|
75
|
+
exitCode: 0,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
|
|
4
|
+
const STYLESHEET_FILE = fileURLToPath(
|
|
5
|
+
new URL("svg-in-html-snippets/style.css", import.meta.url),
|
|
6
|
+
);
|
|
7
|
+
const SCRIPT_FILE = fileURLToPath(
|
|
8
|
+
new URL("svg-in-html-snippets/script.js", import.meta.url),
|
|
9
|
+
);
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {string} pStylesheet
|
|
13
|
+
* @returns {string}
|
|
14
|
+
*/
|
|
15
|
+
export function getHeader(pStylesheet) {
|
|
16
|
+
return `<!doctype html>
|
|
17
|
+
<html lang="en" dir="ltr">
|
|
18
|
+
<head>
|
|
19
|
+
<meta charset="utf-8" />
|
|
20
|
+
<title>dependency graph</title>
|
|
21
|
+
<style>
|
|
22
|
+
${pStylesheet}
|
|
23
|
+
</style>
|
|
24
|
+
</head>
|
|
25
|
+
<body>
|
|
26
|
+
<button id="button_help">?</button>
|
|
27
|
+
<div id="hints" class="hint" style="display: none">
|
|
28
|
+
<button id="close-hints">x</button>
|
|
29
|
+
<span id="hint-text"></span>
|
|
30
|
+
<ul>
|
|
31
|
+
<li><b>Hover</b> - highlight</li>
|
|
32
|
+
<li><b>Right-click</b> - pin highlight</li>
|
|
33
|
+
<li><b>ESC</b> - clear</li>
|
|
34
|
+
</ul>
|
|
35
|
+
</div>
|
|
36
|
+
`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @param {string} pScript
|
|
41
|
+
* @returns {string}
|
|
42
|
+
*/
|
|
43
|
+
export function getFooter(pScript) {
|
|
44
|
+
return ` <script>
|
|
45
|
+
${pScript}
|
|
46
|
+
</script>
|
|
47
|
+
</body>
|
|
48
|
+
</html>
|
|
49
|
+
`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
*
|
|
54
|
+
* @param {string} pSVG
|
|
55
|
+
* @returns {string}
|
|
56
|
+
*/
|
|
57
|
+
export function wrapInHTML(pSVG) {
|
|
58
|
+
const lStylesheet = readFileSync(STYLESHEET_FILE, "utf8");
|
|
59
|
+
const lScript = readFileSync(SCRIPT_FILE, "utf8");
|
|
60
|
+
|
|
61
|
+
return getHeader(lStylesheet) + pSVG + getFooter(lScript);
|
|
62
|
+
}
|
package/src/report/index.mjs
CHANGED
package/src/report/json.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const EOL = "\n";
|
|
1
2
|
/**
|
|
2
3
|
* Returns the results of a cruise in JSON
|
|
3
4
|
*
|
|
@@ -6,7 +7,7 @@
|
|
|
6
7
|
*/
|
|
7
8
|
export default function json(pResults) {
|
|
8
9
|
return {
|
|
9
|
-
output: JSON.stringify(pResults, null, " "),
|
|
10
|
+
output: JSON.stringify(pResults, null, " ") + EOL,
|
|
10
11
|
exitCode: 0,
|
|
11
12
|
};
|
|
12
13
|
}
|
package/src/report/teamcity.mjs
CHANGED
|
@@ -7,6 +7,7 @@ const SEVERITY2TEAMCITY_SEVERITY = new Map([
|
|
|
7
7
|
["warn", "WARNING"],
|
|
8
8
|
["info", "INFO"],
|
|
9
9
|
]);
|
|
10
|
+
const EOL = "\n";
|
|
10
11
|
|
|
11
12
|
function severity2teamcitySeverity(pSeverity) {
|
|
12
13
|
return SEVERITY2TEAMCITY_SEVERITY.get(pSeverity) || "INFO";
|
|
@@ -159,9 +160,10 @@ export default function teamcity(pResults) {
|
|
|
159
160
|
const lIgnoredCount = pResults?.summary?.ignore ?? 0;
|
|
160
161
|
|
|
161
162
|
return {
|
|
162
|
-
output:
|
|
163
|
-
|
|
164
|
-
|
|
163
|
+
output:
|
|
164
|
+
reportViolatedRules(lRuleSet, lViolations, lIgnoredCount)
|
|
165
|
+
.concat(reportViolations(lViolations, lIgnoredCount))
|
|
166
|
+
.reduce((pAll, pCurrent) => `${pAll}${pCurrent}\n`, "") || EOL,
|
|
165
167
|
exitCode: pResults.summary.error,
|
|
166
168
|
};
|
|
167
169
|
}
|
package/src/report/text.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { EOL } from "node:os";
|
|
2
1
|
import figures from "figures";
|
|
3
2
|
import chalk from "chalk";
|
|
4
3
|
|
|
5
4
|
const DEFAULT_OPTIONS = {
|
|
6
5
|
highlightFocused: false,
|
|
7
6
|
};
|
|
7
|
+
const EOL = "\n";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
*
|
|
@@ -30,9 +30,9 @@ function toFlatDependencies(pModules, pModulesInFocus, pHighlightFocused) {
|
|
|
30
30
|
return pModules.reduce(
|
|
31
31
|
(pAll, pModule) =>
|
|
32
32
|
pAll.concat(
|
|
33
|
-
toFlatModuleDependencies(pModule, pModulesInFocus, pHighlightFocused)
|
|
33
|
+
toFlatModuleDependencies(pModule, pModulesInFocus, pHighlightFocused),
|
|
34
34
|
),
|
|
35
|
-
[]
|
|
35
|
+
[],
|
|
36
36
|
);
|
|
37
37
|
}
|
|
38
38
|
|
|
@@ -55,7 +55,7 @@ function getModulesInFocus(pModules) {
|
|
|
55
55
|
return new Set(
|
|
56
56
|
pModules
|
|
57
57
|
.filter((pModule) => pModule.matchesFocus || pModule.matchesReaches)
|
|
58
|
-
.map((pModule) => pModule.source)
|
|
58
|
+
.map((pModule) => pModule.source),
|
|
59
59
|
);
|
|
60
60
|
}
|
|
61
61
|
|
|
@@ -68,13 +68,15 @@ function getModulesInFocus(pModules) {
|
|
|
68
68
|
function report(pResults, pOptions) {
|
|
69
69
|
const lOptions = { ...DEFAULT_OPTIONS, ...pOptions };
|
|
70
70
|
|
|
71
|
-
return
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
71
|
+
return (
|
|
72
|
+
toFlatDependencies(
|
|
73
|
+
pResults.modules,
|
|
74
|
+
getModulesInFocus(pResults.modules),
|
|
75
|
+
lOptions.highlightFocused === true,
|
|
76
|
+
).reduce(
|
|
77
|
+
(pAll, pDependency) => pAll.concat(stringify(pDependency)).concat(EOL),
|
|
78
|
+
"",
|
|
79
|
+
) || EOL
|
|
78
80
|
);
|
|
79
81
|
}
|
|
80
82
|
|
package/types/restrictions.d.mts
CHANGED
|
@@ -173,7 +173,6 @@ export interface IDependentsModuleRestrictionType extends IBaseRestrictionType {
|
|
|
173
173
|
* Matches when the number of times the 'to' module is used falls below (<)
|
|
174
174
|
* this number. Caveat: only works in concert with path and pathNot restrictions
|
|
175
175
|
* in the from and to parts of the rule; other conditions will be ignored.
|
|
176
|
-
* (somewhat experimental; - syntax can change over time without a major bump)
|
|
177
176
|
* E.g. to flag modules that are used only once or not at all, use 2 here.
|
|
178
177
|
*/
|
|
179
178
|
numberOfDependentsLessThan?: number;
|
|
@@ -181,7 +180,6 @@ export interface IDependentsModuleRestrictionType extends IBaseRestrictionType {
|
|
|
181
180
|
* Matches when the number of times the 'to' module is used rises above (<)
|
|
182
181
|
* this number. Caveat: only works in concert with path and pathNot restrictions
|
|
183
182
|
* in the from and to parts of the rule; other conditions will be ignored.
|
|
184
|
-
* (somewhat experimental; - syntax can change over time without a major bump)
|
|
185
183
|
* E.g. to flag modules that are used more than 10 times, use 10 here.
|
|
186
184
|
*/
|
|
187
185
|
numberOfDependentsMoreThan?: number;
|
package/types/rule-set.d.mts
CHANGED
|
@@ -43,13 +43,10 @@ export interface IRegularForbiddenRuleType extends IBaseRuleType {
|
|
|
43
43
|
/**
|
|
44
44
|
* What to apply the rule to - modules (the default) or folders. Switching
|
|
45
45
|
* the scope to 'folder' can be useful in rules where this makes a difference
|
|
46
|
-
* like those regarding circular dependencies or instability.
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* the to.moreUnstable, to.circular, and path (both from and to) attributes
|
|
51
|
-
* work at the moment. Other attributes will follow suit in releases
|
|
52
|
-
* after 11.6.0.
|
|
46
|
+
* like those regarding circular dependencies or instability.
|
|
47
|
+
* Only the to.moreUnstable, to.circular, and path (both from and to)
|
|
48
|
+
* attributes work at the moment. Other attributes will follow suit in later
|
|
49
|
+
* releases (depending on demand).
|
|
53
50
|
*/
|
|
54
51
|
scope?: RuleScopeType;
|
|
55
52
|
}
|
|
File without changes
|
|
File without changes
|