dependency-cruiser 18.0.0 → 18.1.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/configs/plugins/3d-reporter-plugin.mjs +1 -1
- package/configs/plugins/stats-reporter-plugin.mjs +2 -2
- package/package.json +5 -5
- package/src/analyze/add-validations.mjs +1 -1
- package/src/analyze/derive/folders/utl.mjs +2 -2
- package/src/analyze/summarize/index.mjs +121 -4
- package/src/analyze/summarize/summarize-modules.mjs +1 -1
- package/src/cache/cache.mjs +5 -5
- package/src/cache/helpers.mjs +2 -2
- package/src/cli/format-meta-info.mjs +12 -14
- package/src/cli/index.mjs +3 -4
- package/src/cli/init-config/check-and-warn-inconsistencies.mjs +3 -3
- package/src/cli/init-config/environment-helpers.mjs +4 -4
- package/src/cli/init-config/get-user-input.mjs +1 -1
- package/src/cli/init-config/index.mjs +1 -1
- package/src/cli/init-config/normalize-init-options.mjs +3 -3
- package/src/cli/init-config/validators.mjs +1 -1
- package/src/cli/init-config/write-run-scripts-to-manifest.mjs +2 -2
- package/src/cli/listeners/ndjson.mjs +1 -1
- package/src/cli/listeners/performance-log/index.mjs +1 -1
- package/src/cli/normalize-cli-options.mjs +6 -4
- package/src/cli/utl/assert-file-existence.mjs +1 -1
- package/src/config-utl/extract-babel-config.mjs +3 -1
- package/src/config-utl/extract-depcruise-config/index.mjs +1 -1
- package/src/config-utl/extract-depcruise-config/merge-configs.mjs +5 -3
- package/src/config-utl/extract-ts-config.mjs +1 -1
- package/src/config-utl/extract-webpack-resolve-config.mjs +2 -2
- package/src/environment.mjs +17 -0
- package/src/extract/acorn/extract.mjs +1 -1
- package/src/extract/acorn/parse.mjs +2 -2
- package/src/extract/extract-dependencies.mjs +1 -1
- package/src/extract/extract-stats.mjs +1 -1
- package/src/extract/gather-initial-sources.mjs +1 -1
- package/src/extract/helpers.mjs +1 -1
- package/src/extract/index.mjs +1 -1
- package/src/extract/resolve/determine-dependency-types.mjs +3 -2
- package/src/extract/resolve/external-module-helpers.mjs +8 -8
- package/src/extract/resolve/get-manifest.mjs +7 -7
- package/src/extract/resolve/index.mjs +2 -1
- package/src/extract/resolve/merge-manifests.mjs +2 -2
- package/src/extract/resolve/module-classifiers.mjs +1 -1
- package/src/extract/resolve/resolve-amd.mjs +1 -1
- package/src/extract/resolve/resolve-cjs.mjs +2 -2
- package/src/extract/resolve/resolve-helpers.mjs +1 -1
- package/src/extract/resolve/resolve.mjs +2 -2
- package/src/extract/swc/dependency-visitor.mjs +1 -0
- package/src/extract/swc/parse.mjs +2 -2
- package/src/extract/transpile/index.mjs +1 -1
- package/src/extract/transpile/meta.mjs +1 -1
- package/src/extract/transpile/try-import-available.mjs +1 -1
- package/src/extract/transpile/typescript-wrap.mjs +1 -1
- package/src/extract/tsc/extract-typescript-deps.mjs +1 -1
- package/src/extract/tsc/parse.mjs +3 -3
- package/src/graph-utl/add-focus.mjs +1 -1
- package/src/graph-utl/consolidate-to-pattern.mjs +1 -0
- package/src/graph-utl/indexed-module-graph.mjs +6 -6
- package/src/graph-utl/module-graph-with-dependency-set.mjs +1 -1
- package/src/graph-utl/rule-set.mjs +3 -3
- package/src/main/cruise.mjs +1 -1
- package/src/main/helpers.mjs +1 -1
- package/src/main/options/normalize.mjs +2 -2
- package/src/main/report-wrap.mjs +1 -0
- package/src/main/resolve-options/normalize.mjs +2 -2
- package/src/main/rule-set/assert-validity.mjs +1 -1
- package/src/main/rule-set/normalize.mjs +1 -1
- package/src/meta.cjs +1 -1
- package/src/report/anon/anonymize-path-element.mjs +1 -1
- package/src/report/anon/index.mjs +1 -1
- package/src/report/anon/random-string.mjs +1 -1
- package/src/report/azure-devops.mjs +2 -2
- package/src/report/baseline.mjs +1 -1
- package/src/report/d2.mjs +3 -3
- package/src/report/dot/index.mjs +1 -1
- package/src/report/dot/module-utl.mjs +2 -2
- package/src/report/dot/theming.mjs +12 -6
- package/src/report/dot-webpage/svg-in-html-snippets/script.cjs +7 -7
- package/src/report/error-html/error-html-template.mjs +7 -0
- package/src/report/error.mjs +33 -2
- package/src/report/html/index.mjs +2 -2
- package/src/report/index.mjs +1 -0
- package/src/report/markdown.mjs +3 -3
- package/src/report/mermaid.mjs +3 -3
- package/src/report/metrics.mjs +2 -2
- package/src/report/plugins.mjs +2 -1
- package/src/report/teamcity.mjs +2 -2
- package/src/report/utl/dependency-to-incidence-transformer.mjs +1 -1
- package/src/report/utl/index.mjs +1 -1
- package/src/schema/cruise-result.validate.mjs +1 -1
- package/src/utl/array-util.mjs +1 -1
- package/src/utl/find-all-files.mjs +1 -1
- package/src/utl/get-extension.mjs +1 -1
- package/src/utl/path-to-posix.mjs +1 -1
- package/src/utl/regex-util.mjs +4 -2
- package/src/utl/try-import.mjs +1 -1
- package/src/utl/try-require.cjs +3 -3
- package/src/validate/index.mjs +2 -2
- package/types/config-utl/extract-babel-config.d.mts +1 -1
- package/types/config-utl/extract-depcruise-config.d.mts +1 -1
- package/types/config-utl/extract-depcruise-options.d.mts +1 -1
- package/types/config-utl/extract-ts-config.d.mts +1 -1
- package/types/config-utl/extract-webpack-resolve-config.d.mts +1 -1
- package/types/cruise-result.d.mts +27 -0
- package/types/dependency-cruiser.d.mts +5 -26
- package/types/environment.d.mts +29 -0
- package/types/options.d.mts +1 -4
- package/types/plugins/3d-reporter-plugin.d.mts +1 -1
- package/types/plugins/mermaid-reporter-plugin.d.mts +1 -1
- package/types/plugins/stats-reporter-plugin.d.mts +1 -1
- package/types/rule-set.d.mts +2 -5
- package/types/shared-types.d.mts +1 -5
- package/types/strict-rule-set.d.mts +2 -5
|
@@ -114,7 +114,7 @@ function render3DThing(pCruiseResult) {
|
|
|
114
114
|
* @param {import('../../types/dependency-cruiser').ICruiseResult} pCruiseResult -
|
|
115
115
|
* the output of a dependency-cruise adhering to dependency-cruiser's
|
|
116
116
|
* cruise result schema
|
|
117
|
-
* @
|
|
117
|
+
* @returns {import('../../types/dependency-cruiser').IReporterOutput} -
|
|
118
118
|
* output: a string
|
|
119
119
|
* exitCode: 0
|
|
120
120
|
*/
|
|
@@ -34,7 +34,7 @@ function doMagic(pCruiseResult) {
|
|
|
34
34
|
* got passed
|
|
35
35
|
*
|
|
36
36
|
* @param {import('../../types/dependency-cruiser').ICruiseResult} pCruiseResult - a result from a cruise.
|
|
37
|
-
* @
|
|
37
|
+
* @returns {string} an object with some stats
|
|
38
38
|
*/
|
|
39
39
|
function samplePluginReporter(pCruiseResult) {
|
|
40
40
|
const lDependencyCounts = pCruiseResult.modules
|
|
@@ -68,7 +68,7 @@ function samplePluginReporter(pCruiseResult) {
|
|
|
68
68
|
* @param {import('../../types/dependency-cruiser').ICruiseResult} pCruiseResult -
|
|
69
69
|
* the output of a dependency-cruise adhering to dependency-cruiser's
|
|
70
70
|
* cruise result schema
|
|
71
|
-
* @
|
|
71
|
+
* @returns {import('../../types/dependency-cruiser').IReporterOutput} -
|
|
72
72
|
* output: some stats on modules and dependencies in json format
|
|
73
73
|
* exitCode: 0
|
|
74
74
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dependency-cruiser",
|
|
3
|
-
"version": "18.
|
|
3
|
+
"version": "18.1.1",
|
|
4
4
|
"description": "Validate and visualize dependencies. With your rules. JavaScript, TypeScript, CoffeeScript. ES6, CommonJS, AMD.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"static analysis",
|
|
@@ -143,18 +143,18 @@
|
|
|
143
143
|
"README.md"
|
|
144
144
|
],
|
|
145
145
|
"dependencies": {
|
|
146
|
-
"acorn": "8.
|
|
146
|
+
"acorn": "8.18.0",
|
|
147
147
|
"acorn-jsx": "5.3.2",
|
|
148
148
|
"acorn-jsx-walk": "2.0.0",
|
|
149
149
|
"acorn-loose": "8.5.2",
|
|
150
150
|
"acorn-walk": "8.3.5",
|
|
151
151
|
"commander": "15.0.0",
|
|
152
|
-
"enhanced-resolve": "5.24.
|
|
153
|
-
"ignore": "7.0.
|
|
152
|
+
"enhanced-resolve": "5.24.5",
|
|
153
|
+
"ignore": "7.0.6",
|
|
154
154
|
"interpret": "3.1.1",
|
|
155
155
|
"is-installed-globally": "1.0.0",
|
|
156
156
|
"json5": "2.2.3",
|
|
157
|
-
"picomatch": "4.0.
|
|
157
|
+
"picomatch": "4.0.5",
|
|
158
158
|
"prompts": "2.4.2",
|
|
159
159
|
"rechoir": "0.8.0",
|
|
160
160
|
"safe-regex": "2.1.1",
|
|
@@ -17,7 +17,7 @@ function addDependencyViolations(pModule, pDependency, pRuleSet, pValidate) {
|
|
|
17
17
|
* @param {Partial<import("../../types/cruise-result.mjs").IModule>[]} pModules array of modules
|
|
18
18
|
* @param {import("../../types/rule-set.mjs").IFlattenedRuleSet} pRuleSet normalized & validated rule set
|
|
19
19
|
* @param {boolean} pValidate - whether or not to validate (typically you want to pass 'true' here)
|
|
20
|
-
* @
|
|
20
|
+
* @returns {import("../../types/cruise-result.mjs").IModule[]} the same array of modules, with for each
|
|
21
21
|
* of them added whether or not it is
|
|
22
22
|
* valid and if not which rules were violated
|
|
23
23
|
*/
|
|
@@ -23,8 +23,8 @@ export function getEfferentCouplings(pModule, pDirname) {
|
|
|
23
23
|
* @returns string[]
|
|
24
24
|
*/
|
|
25
25
|
export function getParentFolders(pPath) {
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
const lFragments = pPath.split("/");
|
|
27
|
+
const lReturnValue = [];
|
|
28
28
|
|
|
29
29
|
while (lFragments.length > 0) {
|
|
30
30
|
lReturnValue.push(lFragments.join("/"));
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EOL } from "node:os";
|
|
1
2
|
import addRuleSetUsed from "./add-rule-set-used.mjs";
|
|
2
3
|
import summarizeModules from "./summarize-modules.mjs";
|
|
3
4
|
import summarizeFolders from "./summarize-folders.mjs";
|
|
@@ -8,31 +9,146 @@ import {
|
|
|
8
9
|
getDependenciesCruised,
|
|
9
10
|
} from "./get-stats.mjs";
|
|
10
11
|
import { compareViolations } from "#graph-utl/compare.mjs";
|
|
12
|
+
import { getEnvironmentInfo } from "#environment.mjs";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @import { IOptions, IEnvironmentIssue, ISummary, IModule, IFolder } from "../../../types/cruise-result.mjs"
|
|
16
|
+
* @import { IAvailableTranspiler } from "../../../types/environment.mjs"
|
|
17
|
+
* @import { IStrictCruiseOptions } from "../../../types/strict-options.mjs"
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param { IOptions } pOptions
|
|
22
|
+
* @param { IAvailableTranspiler[] } pAvailableTranspilers
|
|
23
|
+
* @returns { boolean }
|
|
24
|
+
*/
|
|
25
|
+
function swcIsConsistent(pOptions, pAvailableTranspilers) {
|
|
26
|
+
const lSWCNeeded = (pOptions?.parser ?? "acorn") === "swc";
|
|
27
|
+
return lSWCNeeded
|
|
28
|
+
? pAvailableTranspilers.some(
|
|
29
|
+
(pTranspiler) => pTranspiler.name === "swc" && pTranspiler.available,
|
|
30
|
+
)
|
|
31
|
+
: true;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param { IOptions } pOptions
|
|
36
|
+
* @param { IAvailableTranspiler[] } pAvailableTranspilers
|
|
37
|
+
* @returns { boolean }
|
|
38
|
+
*/
|
|
39
|
+
function typescriptIsConsistent(pOptions, pAvailableTranspilers) {
|
|
40
|
+
const lTypeScriptNeeded =
|
|
41
|
+
Boolean(pOptions?.tsConfig) ||
|
|
42
|
+
Boolean(pOptions?.tsPreCompilationDeps) ||
|
|
43
|
+
Boolean(pOptions?.detectJSDocImports) ||
|
|
44
|
+
(pOptions?.parser ?? "acorn") === "tsc";
|
|
45
|
+
return lTypeScriptNeeded
|
|
46
|
+
? pAvailableTranspilers.some(
|
|
47
|
+
(pTranspiler) =>
|
|
48
|
+
pTranspiler.name === "typescript" && pTranspiler.available,
|
|
49
|
+
)
|
|
50
|
+
: true;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* @param { IOptions } pOptions
|
|
54
|
+
* @param { IAvailableTranspiler[] } pAvailableTranspilers
|
|
55
|
+
* @returns { boolean }
|
|
56
|
+
*/
|
|
57
|
+
function babelIsConsistent(pOptions, pAvailableTranspilers) {
|
|
58
|
+
return Boolean(pOptions?.babelConfig)
|
|
59
|
+
? pAvailableTranspilers.some(
|
|
60
|
+
(pTranspiler) => pTranspiler.name === "babel" && pTranspiler.available,
|
|
61
|
+
)
|
|
62
|
+
: true;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @param {IOptions} pOptions
|
|
67
|
+
* @param {IAvailableTranspiler[]} pAvailableTranspilers
|
|
68
|
+
* @returns {{issues?: IEnvironmentIssue[]}}
|
|
69
|
+
*/
|
|
70
|
+
function determineEnvironmentIssues(pOptions, pAvailableTranspilers) {
|
|
71
|
+
const lIssues = [];
|
|
72
|
+
if (!typescriptIsConsistent(pOptions, pAvailableTranspilers)) {
|
|
73
|
+
const tsTranspiler = pAvailableTranspilers.find(
|
|
74
|
+
(pTranspiler) => pTranspiler.name === "typescript",
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
lIssues.push({
|
|
78
|
+
severity: "warn",
|
|
79
|
+
name: "missing-typescript-transpiler",
|
|
80
|
+
description:
|
|
81
|
+
`dependency-cruiser detected a TypeScript environment,${EOL}` +
|
|
82
|
+
` but not a compatible TypeScript compiler (${tsTranspiler.name}: ${tsTranspiler.version}). This means${EOL}` +
|
|
83
|
+
` it's likely to have missed TypeScript sources and dependencies.${EOL}${EOL}` +
|
|
84
|
+
` Install typescript to get better results (e.g. npm i -D typescript@^6).${EOL}${EOL}` +
|
|
85
|
+
` => Support for typescript@>=7 will follow when its API is published and stable.${EOL}`,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
if (!swcIsConsistent(pOptions, pAvailableTranspilers)) {
|
|
89
|
+
const swcTranspiler = pAvailableTranspilers.find(
|
|
90
|
+
(pTranspiler) => pTranspiler.name === "swc",
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
lIssues.push({
|
|
94
|
+
severity: "warn",
|
|
95
|
+
name: "missing-swc-transpiler",
|
|
96
|
+
description:
|
|
97
|
+
`dependency-cruiser found swc configured as parser, but ${EOL}` +
|
|
98
|
+
` it did not find a compatible version of swc (${swcTranspiler.name}: ${swcTranspiler.version}).${EOL}` +
|
|
99
|
+
` dependency-cruiser might have missed some sources or dependencies.${EOL}${EOL}` +
|
|
100
|
+
` Install swc (e.g. npm i -D @swc/core) to get better results.${EOL}`,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
if (!babelIsConsistent(pOptions, pAvailableTranspilers)) {
|
|
104
|
+
const babelTranspiler = pAvailableTranspilers.find(
|
|
105
|
+
(pTranspiler) => pTranspiler.name === "babel",
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
lIssues.push({
|
|
109
|
+
severity: "warn",
|
|
110
|
+
name: "missing-babel-transpiler",
|
|
111
|
+
description:
|
|
112
|
+
`dependency-cruiser detected a babel configuration, but not a${EOL}` +
|
|
113
|
+
` compatible babel transpiler (${babelTranspiler.name}: ${babelTranspiler.version}). If you indeed use babel,${EOL}` +
|
|
114
|
+
` dependency-cruiser might have missed some sources or dependencies.${EOL}${EOL}` +
|
|
115
|
+
` Install babel (e.g. npm i -D @babel/core@^7) to get better results.${EOL}`,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
return lIssues.length > 0 ? { issues: lIssues } : {};
|
|
119
|
+
}
|
|
11
120
|
|
|
12
121
|
/**
|
|
13
122
|
*
|
|
14
|
-
* @param {
|
|
123
|
+
* @param {IModule[]} pModules -
|
|
15
124
|
* cruised modules that have been enriched with mandatory attributes &
|
|
16
125
|
* have been validated against rules as passed in the options
|
|
17
|
-
* @param {
|
|
126
|
+
* @param {IStrictCruiseOptions} pOptions -
|
|
18
127
|
* @param {string[]} pFileDirectoryArray -
|
|
19
128
|
* the files/ directories originally passed to be cruised
|
|
20
|
-
* @param {
|
|
129
|
+
* @param {IFolder[]} pFolders -
|
|
21
130
|
* the pModules collapsed to folders, with their own metrics & deps
|
|
22
131
|
*
|
|
23
|
-
* @returns {
|
|
132
|
+
* @returns {ISummary} -
|
|
24
133
|
* a summary of the found modules, dependencies and any violations
|
|
25
134
|
*/
|
|
135
|
+
// eslint-disable-next-line max-params
|
|
26
136
|
export default function summarize(
|
|
27
137
|
pModules,
|
|
28
138
|
pOptions,
|
|
29
139
|
pFileDirectoryArray,
|
|
30
140
|
pFolders,
|
|
141
|
+
pGetEnvironmentInfoFunction = getEnvironmentInfo,
|
|
31
142
|
) {
|
|
32
143
|
const lViolations = summarizeModules(pModules, pOptions.ruleSet)
|
|
33
144
|
.concat(summarizeFolders(pFolders || [], pOptions.ruleSet))
|
|
34
145
|
.sort(compareViolations);
|
|
35
146
|
|
|
147
|
+
const lEnvironment = pGetEnvironmentInfoFunction();
|
|
148
|
+
const lEnvironmentWithIssues = {
|
|
149
|
+
...lEnvironment,
|
|
150
|
+
...determineEnvironmentIssues(pOptions, lEnvironment.transpilersFound),
|
|
151
|
+
};
|
|
36
152
|
return {
|
|
37
153
|
violations: lViolations,
|
|
38
154
|
...getViolationStats(lViolations),
|
|
@@ -40,5 +156,6 @@ export default function summarize(
|
|
|
40
156
|
totalDependenciesCruised: getDependenciesCruised(pModules),
|
|
41
157
|
...summarizeOptions(pFileDirectoryArray, pOptions),
|
|
42
158
|
...(pOptions.ruleSet ? { ruleSetUsed: addRuleSetUsed(pOptions) } : {}),
|
|
159
|
+
environment: lEnvironmentWithIssues,
|
|
43
160
|
};
|
|
44
161
|
}
|
|
@@ -69,7 +69,7 @@ function toDependencyViolationSummary(pRule, pModule, pDependency, pRuleSet) {
|
|
|
69
69
|
*
|
|
70
70
|
* @param {any} pModules an array of modules
|
|
71
71
|
* @param {any} pRuleSet? a rule set
|
|
72
|
-
* @
|
|
72
|
+
* @returns {any} an array of violations
|
|
73
73
|
*/
|
|
74
74
|
function extractDependencyViolations(pModules, pRuleSet) {
|
|
75
75
|
return pModules
|
package/src/cache/cache.mjs
CHANGED
|
@@ -33,7 +33,7 @@ const EMPTY_CACHE = {
|
|
|
33
33
|
};
|
|
34
34
|
|
|
35
35
|
// see ./cache-rationales.md#cache-format-versioning for rationale & bump instructions
|
|
36
|
-
const CACHE_FORMAT_VERSION =
|
|
36
|
+
const CACHE_FORMAT_VERSION = 18.1;
|
|
37
37
|
|
|
38
38
|
export default class Cache {
|
|
39
39
|
/** @type {(IRevisionData | null)=} */
|
|
@@ -115,7 +115,7 @@ export default class Cache {
|
|
|
115
115
|
lPayload = await readFile(join(pCacheFolder, CACHE_FILE_NAME), "utf8");
|
|
116
116
|
}
|
|
117
117
|
return JSON.parse(lPayload);
|
|
118
|
-
} catch
|
|
118
|
+
} catch {
|
|
119
119
|
return EMPTY_CACHE;
|
|
120
120
|
}
|
|
121
121
|
}
|
|
@@ -123,7 +123,7 @@ export default class Cache {
|
|
|
123
123
|
/**
|
|
124
124
|
* @param {string} pPayload
|
|
125
125
|
* @param {boolean} pCompress
|
|
126
|
-
* @
|
|
126
|
+
* @returns {Buffer|string}
|
|
127
127
|
*/
|
|
128
128
|
#compact(pPayload, pCompress) {
|
|
129
129
|
if (pCompress) {
|
|
@@ -144,7 +144,7 @@ export default class Cache {
|
|
|
144
144
|
* @param {IRevisionData=} pRevisionData
|
|
145
145
|
*/
|
|
146
146
|
async write(pCacheFolder, pCruiseResult, pRevisionData) {
|
|
147
|
-
|
|
147
|
+
const lRevisionData = pRevisionData ?? this.#revisionData;
|
|
148
148
|
|
|
149
149
|
await mkdir(pCacheFolder, { recursive: true });
|
|
150
150
|
const lUncompressedPayload = JSON.stringify(
|
|
@@ -153,7 +153,7 @@ export default class Cache {
|
|
|
153
153
|
lRevisionData,
|
|
154
154
|
),
|
|
155
155
|
);
|
|
156
|
-
|
|
156
|
+
const lPayload = this.#compact(lUncompressedPayload, this.#compress);
|
|
157
157
|
|
|
158
158
|
// relying on writeFile defaults to 'do the right thing' (i.e. utf8
|
|
159
159
|
// when the payload is a string; raw buffer otherwise)
|
package/src/cache/helpers.mjs
CHANGED
|
@@ -37,7 +37,7 @@ export function getFileHashSync(pFileName) {
|
|
|
37
37
|
let lHashedFileName = "file not found";
|
|
38
38
|
try {
|
|
39
39
|
lHashedFileName = hash(readFileSync(pFileName, "utf8"));
|
|
40
|
-
} catch
|
|
40
|
+
} catch {
|
|
41
41
|
// will return "file not found" as per default
|
|
42
42
|
}
|
|
43
43
|
HASHES_CACHE.set(pFileName, lHashedFileName);
|
|
@@ -46,7 +46,7 @@ export function getFileHashSync(pFileName) {
|
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
48
|
* @param {IChange} pChange
|
|
49
|
-
* @
|
|
49
|
+
* @returns {IRevisionChange}
|
|
50
50
|
*/
|
|
51
51
|
export function addCheckSumToChangeSync(pChange) {
|
|
52
52
|
return {
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import { release, platform, arch } from "node:os";
|
|
2
1
|
import { styleText } from "node:util";
|
|
3
|
-
|
|
4
|
-
import { getAvailableTranspilers, allExtensions } from "#main/index.mjs";
|
|
5
|
-
import meta from "#meta.cjs";
|
|
2
|
+
import { getEnvironmentInfo } from "#environment.mjs";
|
|
6
3
|
|
|
7
4
|
function bool2Symbol(pBool) {
|
|
8
5
|
return pBool ? styleText("green", "✔") : styleText("red", "x");
|
|
@@ -12,13 +9,13 @@ const MAX_VERSION_RANGE_STRING_LENGTH = 19;
|
|
|
12
9
|
const MAX_TRANSPILER_NAME_LENGTH = 22;
|
|
13
10
|
const MAX_VERSION_STRING_LENGTH = 24;
|
|
14
11
|
|
|
15
|
-
function formatTranspilers() {
|
|
16
|
-
|
|
12
|
+
function formatTranspilers(pAvailableTranspilers) {
|
|
13
|
+
const lTranspilerTableHeader = styleText(
|
|
17
14
|
"bold",
|
|
18
15
|
` ✔ ${"transpiler".padEnd(MAX_TRANSPILER_NAME_LENGTH)} ${"versions supported".padEnd(MAX_VERSION_RANGE_STRING_LENGTH)} version found`,
|
|
19
16
|
);
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
const lTranspilerTableDivider = ` - ${"-".repeat(MAX_TRANSPILER_NAME_LENGTH)} ${"-".repeat(MAX_VERSION_RANGE_STRING_LENGTH)} ${"-".repeat(MAX_VERSION_STRING_LENGTH)}`;
|
|
18
|
+
const lTranspilerTable = pAvailableTranspilers
|
|
22
19
|
.map(
|
|
23
20
|
(pTranspiler) =>
|
|
24
21
|
` ${bool2Symbol(pTranspiler.available)} ${pTranspiler.name.padEnd(MAX_TRANSPILER_NAME_LENGTH)} ${pTranspiler.version.padEnd(MAX_VERSION_RANGE_STRING_LENGTH)} ${pTranspiler.currentVersion}`,
|
|
@@ -36,12 +33,13 @@ function formatExtensions(pExtensions) {
|
|
|
36
33
|
}
|
|
37
34
|
|
|
38
35
|
export default function formatMetaInfo() {
|
|
36
|
+
const lMetaInfo = getEnvironmentInfo();
|
|
39
37
|
return `
|
|
40
|
-
${styleText("bold", "dependency-cruiser")}@${
|
|
38
|
+
${styleText("bold", "dependency-cruiser")}@${lMetaInfo.version}
|
|
41
39
|
|
|
42
|
-
node version supported : ${
|
|
43
|
-
node version found : ${
|
|
44
|
-
os version found : ${
|
|
40
|
+
node version supported : ${lMetaInfo.nodeVersionSupported}
|
|
41
|
+
node version found : ${lMetaInfo.nodeVersionFound}
|
|
42
|
+
os version found : ${lMetaInfo.osVersionFound}
|
|
45
43
|
|
|
46
44
|
If you need a supported, but not enabled transpiler ('${styleText(
|
|
47
45
|
"red",
|
|
@@ -50,10 +48,10 @@ export default function formatMetaInfo() {
|
|
|
50
48
|
it in the same folder dependency-cruiser is installed. E.g. 'npm i livescript'
|
|
51
49
|
will enable livescript support if it's installed in your project folder.
|
|
52
50
|
|
|
53
|
-
${formatTranspilers()}
|
|
51
|
+
${formatTranspilers(lMetaInfo.transpilersFound)}
|
|
54
52
|
${styleText("bold", "✔ extension")}
|
|
55
53
|
- ---------
|
|
56
|
-
${formatExtensions(
|
|
54
|
+
${formatExtensions(lMetaInfo.extensionsFound)}
|
|
57
55
|
`;
|
|
58
56
|
}
|
|
59
57
|
|
package/src/cli/index.mjs
CHANGED
|
@@ -41,7 +41,7 @@ async function addKnownViolations(pCruiseOptions) {
|
|
|
41
41
|
|
|
42
42
|
// Check against json schema is already done in src/main/options/validate
|
|
43
43
|
// so here we can just concentrate on the io
|
|
44
|
-
|
|
44
|
+
const lCruiseOptions = structuredClone(pCruiseOptions);
|
|
45
45
|
set(lCruiseOptions, "ruleSet.options.knownViolations", lKnownViolations);
|
|
46
46
|
return lCruiseOptions;
|
|
47
47
|
}
|
|
@@ -135,11 +135,10 @@ async function runCruise(pFileDirectoryArray, pCruiseOptions) {
|
|
|
135
135
|
/**
|
|
136
136
|
*
|
|
137
137
|
* @param {string[]} pFileDirectoryArray
|
|
138
|
-
* @param {import("../../types/options.mjs").ICruiseOptions}
|
|
138
|
+
* @param {import("../../types/options.mjs").ICruiseOptions} pCruiseOptions
|
|
139
139
|
* @param {{stdout: NodeJS.WritableStream, stderr: NodeJS.WritableStream}=} pStreams
|
|
140
140
|
* @returns {number}
|
|
141
141
|
*/
|
|
142
|
-
|
|
143
142
|
// eslint-disable-next-line max-lines-per-function
|
|
144
143
|
export default async function executeCli(
|
|
145
144
|
pFileDirectoryArray,
|
|
@@ -151,7 +150,7 @@ export default async function executeCli(
|
|
|
151
150
|
stderr: process.stderr,
|
|
152
151
|
...(pStreams || {}),
|
|
153
152
|
};
|
|
154
|
-
|
|
153
|
+
const lCruiseOptions = pCruiseOptions || {};
|
|
155
154
|
let lExitCode = 0;
|
|
156
155
|
|
|
157
156
|
try {
|
|
@@ -16,7 +16,7 @@ import { getAvailableTranspilers } from "#extract/transpile/meta.mjs";
|
|
|
16
16
|
*
|
|
17
17
|
* @param {IInitConfig} pInitOptions
|
|
18
18
|
* @param {IAvailableTranspiler[]} pAvailableTranspilers
|
|
19
|
-
* @
|
|
19
|
+
* @returns {boolean}
|
|
20
20
|
*/
|
|
21
21
|
function typescriptIsConsistent(pInitOptions, pAvailableTranspilers) {
|
|
22
22
|
if (pInitOptions.usesTypeScript) {
|
|
@@ -37,7 +37,7 @@ function typescriptIsConsistent(pInitOptions, pAvailableTranspilers) {
|
|
|
37
37
|
*
|
|
38
38
|
* @param {IInitConfig} pInitOptions
|
|
39
39
|
* @param {IAvailableTranspiler[]} pAvailableTranspilers
|
|
40
|
-
* @
|
|
40
|
+
* @returns {boolean}
|
|
41
41
|
*/
|
|
42
42
|
function babelIsConsistent(pInitOptions, pAvailableTranspilers) {
|
|
43
43
|
if (pInitOptions.babelConfig) {
|
|
@@ -57,7 +57,7 @@ function babelIsConsistent(pInitOptions, pAvailableTranspilers) {
|
|
|
57
57
|
* @param {IInitConfig} pInitOptions
|
|
58
58
|
* @param {NodeJS.WritableStream} [pErrorStream]
|
|
59
59
|
* @param {typeof getAvailableTranspilers} [pAvailableTranspilerFunction]
|
|
60
|
-
* @
|
|
60
|
+
* @returns {IInitConfig} pInitOptions
|
|
61
61
|
*/
|
|
62
62
|
export function checkAndWarnInconsistencies(
|
|
63
63
|
pInitOptions,
|
|
@@ -38,7 +38,7 @@ export function readManifest(pManifestFileName = "./package.json") {
|
|
|
38
38
|
export function fileExists(pFile) {
|
|
39
39
|
try {
|
|
40
40
|
accessSync(pFile, constants.R_OK);
|
|
41
|
-
} catch
|
|
41
|
+
} catch {
|
|
42
42
|
return false;
|
|
43
43
|
}
|
|
44
44
|
return true;
|
|
@@ -53,7 +53,7 @@ function babelIsConfiguredInManifest() {
|
|
|
53
53
|
try {
|
|
54
54
|
// @ts-expect-error defaultly tsc doesn't know about newfangled stuff like hasOwn
|
|
55
55
|
lReturnValue = Object.hasOwn(readManifest(), "babel");
|
|
56
|
-
} catch
|
|
56
|
+
} catch {
|
|
57
57
|
// silently ignore - we'll return false anyway then
|
|
58
58
|
}
|
|
59
59
|
return lReturnValue;
|
|
@@ -67,7 +67,7 @@ export function isTypeModule() {
|
|
|
67
67
|
|
|
68
68
|
try {
|
|
69
69
|
lReturnValue = (readManifest()?.type ?? "commonjs") === "module";
|
|
70
|
-
} catch
|
|
70
|
+
} catch {
|
|
71
71
|
// silently ignore - we'll return false anyway then
|
|
72
72
|
}
|
|
73
73
|
|
|
@@ -112,7 +112,7 @@ function getPackageManager(pManifest) {
|
|
|
112
112
|
if (Object.hasOwn(lManifest, "packageManager")) {
|
|
113
113
|
lReturnValue = lManifest.packageManager;
|
|
114
114
|
}
|
|
115
|
-
} catch
|
|
115
|
+
} catch {
|
|
116
116
|
// silently ignore - we'll return the empty string anyway then
|
|
117
117
|
}
|
|
118
118
|
return lReturnValue;
|
|
@@ -163,7 +163,7 @@ const QUESTIONS = [
|
|
|
163
163
|
];
|
|
164
164
|
|
|
165
165
|
/**
|
|
166
|
-
* @
|
|
166
|
+
* @returns {Promise<import("./types.d.mts").IPartialInitConfig>}
|
|
167
167
|
*/
|
|
168
168
|
export default function getUserInput() {
|
|
169
169
|
return prompts(QUESTIONS);
|
|
@@ -33,7 +33,7 @@ const PACKAGE_MANIFEST = `./${_PACKAGE_MANIFEST}`;
|
|
|
33
33
|
* (e.g. a tsconfig exists => use it and assume typescript is used)
|
|
34
34
|
*
|
|
35
35
|
* @param {OneShotConfigIDType} pOneShotConfigId
|
|
36
|
-
* @
|
|
36
|
+
* @returns {IPartialInitConfig} an initialization configuration
|
|
37
37
|
*/
|
|
38
38
|
function getOneShotConfig(pOneShotConfigId) {
|
|
39
39
|
/** @type {IPartialInitConfig} */
|
|
@@ -43,7 +43,7 @@ function getExtensions(pInitOptions) {
|
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* @param {IPartialInitConfig} pInitOptions
|
|
46
|
-
* @
|
|
46
|
+
* @returns {IPartialInitConfig}
|
|
47
47
|
*/
|
|
48
48
|
function populate(pInitOptions) {
|
|
49
49
|
const lReturnValue = {
|
|
@@ -71,10 +71,10 @@ function populate(pInitOptions) {
|
|
|
71
71
|
/**
|
|
72
72
|
*
|
|
73
73
|
* @param {IPartialInitConfig} pInitOptions
|
|
74
|
-
* @
|
|
74
|
+
* @returns {IInitConfig}
|
|
75
75
|
*/
|
|
76
76
|
export default function normalizeInitOptions(pInitOptions) {
|
|
77
|
-
|
|
77
|
+
const lReturnValue = populate(pInitOptions);
|
|
78
78
|
if (!Object.hasOwn(lReturnValue, "hasTestsOutsideSource")) {
|
|
79
79
|
lReturnValue.hasTestsOutsideSource =
|
|
80
80
|
!pInitOptions.isMonoRepo &&
|
|
@@ -7,7 +7,7 @@ export function validateLocation(pLocations) {
|
|
|
7
7
|
if (!statSync(lLocation).isDirectory()) {
|
|
8
8
|
return `'${lLocation}' doesn't seem to be a folder - please try again`;
|
|
9
9
|
}
|
|
10
|
-
} catch
|
|
10
|
+
} catch {
|
|
11
11
|
return `'${lLocation}' doesn't seem to exist - please try again`;
|
|
12
12
|
}
|
|
13
13
|
}
|
|
@@ -60,7 +60,7 @@ const EXPERIMENTAL_SCRIPT_DOC = [
|
|
|
60
60
|
|
|
61
61
|
/**
|
|
62
62
|
* @param {import("./types.d.mts").IInitConfig} pInitOptions
|
|
63
|
-
* @
|
|
63
|
+
* @returns {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) {
|
|
66
66
|
let lReturnValue = {};
|
|
@@ -91,7 +91,7 @@ export function compileRunScripts(pInitOptions) {
|
|
|
91
91
|
* @param {any} pAdditionalRunScripts
|
|
92
92
|
* @param {any} pExistingRunScripts
|
|
93
93
|
*
|
|
94
|
-
* @
|
|
94
|
+
* @returns {any} the scripts in pAdditionalRunScripts that don't yet exist in
|
|
95
95
|
* pExistingRunScripts
|
|
96
96
|
*/
|
|
97
97
|
function filterNewScriptEntries(pExistingRunScripts, pAdditionalRunScripts) {
|
|
@@ -88,7 +88,7 @@ export default function setUpNDJSONListener(
|
|
|
88
88
|
pMaxLevel = INFO,
|
|
89
89
|
pStream = process.stderr,
|
|
90
90
|
) {
|
|
91
|
-
|
|
91
|
+
const lState = {
|
|
92
92
|
runStartTime: new Date(Date.now()).toISOString(),
|
|
93
93
|
runId: randomInt(MIN_RUN_ID, MAX_RUN_ID),
|
|
94
94
|
previousMessage: "startup: nodejs loading",
|
|
@@ -19,7 +19,7 @@ function getOptionValue(pDefault) {
|
|
|
19
19
|
|
|
20
20
|
// eslint-disable-next-line complexity
|
|
21
21
|
function normalizeConfigFileName(pCliOptions, pConfigWrapperName, pDefault) {
|
|
22
|
-
|
|
22
|
+
const lOptions = structuredClone(pCliOptions);
|
|
23
23
|
|
|
24
24
|
if (Object.hasOwn(lOptions, pConfigWrapperName)) {
|
|
25
25
|
set(
|
|
@@ -45,12 +45,13 @@ function fileExists(pFileName) {
|
|
|
45
45
|
try {
|
|
46
46
|
accessSync(pFileName, constants.R_OK);
|
|
47
47
|
return true;
|
|
48
|
-
} catch
|
|
48
|
+
} catch {
|
|
49
49
|
return false;
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
function validateAndGetCustomRulesFileName(pValidate) {
|
|
54
|
+
/* oxlint-disable-next-line no-useless-assignment */
|
|
54
55
|
let lReturnValue = "";
|
|
55
56
|
|
|
56
57
|
if (fileExists(pValidate)) {
|
|
@@ -66,7 +67,7 @@ function validateAndGetCustomRulesFileName(pValidate) {
|
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
function validateAndGetDefaultRulesFileName() {
|
|
69
|
-
|
|
70
|
+
const lReturnValue = RULES_FILE_NAME_SEARCH_ARRAY.find(fileExists);
|
|
70
71
|
|
|
71
72
|
if (typeof lReturnValue === "undefined") {
|
|
72
73
|
throw new TypeError(
|
|
@@ -79,6 +80,7 @@ function validateAndGetDefaultRulesFileName() {
|
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
function validateAndNormalizeRulesFileName(pValidate) {
|
|
83
|
+
/* oxlint-disable-next-line no-useless-assignment */
|
|
82
84
|
let lReturnValue = "";
|
|
83
85
|
|
|
84
86
|
if (typeof pValidate === "string") {
|
|
@@ -196,7 +198,7 @@ function normalizeCache(pCliOptions) {
|
|
|
196
198
|
*
|
|
197
199
|
* @param {object} pOptionsAsPassedFromCommander [description]
|
|
198
200
|
* @param {any} pKnownCliOptions [description]
|
|
199
|
-
* @
|
|
201
|
+
* @returns {import("../../types/options.mjs").ICruiseOptions} [description]
|
|
200
202
|
*/
|
|
201
203
|
export default async function normalizeOptions(pOptionsAsPassedFromCommander) {
|
|
202
204
|
let lOptions = {
|
|
@@ -3,7 +3,7 @@ import { accessSync, constants } from "node:fs";
|
|
|
3
3
|
export default function assertFileExistence(pDirectoryOrFile) {
|
|
4
4
|
try {
|
|
5
5
|
accessSync(pDirectoryOrFile, constants.R_OK);
|
|
6
|
-
} catch
|
|
6
|
+
} catch {
|
|
7
7
|
throw new Error(
|
|
8
8
|
`Can't open '${pDirectoryOrFile}' for reading. Does it exist?\n`,
|
|
9
9
|
);
|
|
@@ -6,6 +6,7 @@ import tryImport from "#utl/try-import.mjs";
|
|
|
6
6
|
import meta from "#meta.cjs";
|
|
7
7
|
|
|
8
8
|
async function getJSConfig(pBabelConfigFileName) {
|
|
9
|
+
/* oxlint-disable-next-line no-useless-assignment */
|
|
9
10
|
let lReturnValue = {};
|
|
10
11
|
|
|
11
12
|
try {
|
|
@@ -34,6 +35,7 @@ async function getJSConfig(pBabelConfigFileName) {
|
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
async function getJSON5Config(pBabelConfigFileName) {
|
|
38
|
+
/* oxlint-disable-next-line no-useless-assignment */
|
|
37
39
|
let lReturnValue = {};
|
|
38
40
|
const { default: json5 } = await import("json5");
|
|
39
41
|
|
|
@@ -78,7 +80,7 @@ async function getConfig(pBabelConfigFileName) {
|
|
|
78
80
|
* Silently fails if a supported @babel/core version can't be found
|
|
79
81
|
*
|
|
80
82
|
* @param {string} pBabelConfigFileName
|
|
81
|
-
* @
|
|
83
|
+
* @returns {object} babel config as an object
|
|
82
84
|
* @throws {Error} when the babel config has an unknown extension OR
|
|
83
85
|
* when the babel config is invalid OR
|
|
84
86
|
* when dependency-cruiser can't yet process it
|
|
@@ -47,7 +47,7 @@ async function processExtends(pReturnValue, pAlreadyVisited, pBaseDirectory) {
|
|
|
47
47
|
* @param {string} pConfigFileName
|
|
48
48
|
* @param {Set?} pAlreadyVisited
|
|
49
49
|
* @param {string?} pBaseDirectory
|
|
50
|
-
* @
|
|
50
|
+
* @returns {import('../../../types/configuration.mjs').IConfiguration} dependency-cruiser options
|
|
51
51
|
* @throws {Error} when the config is not valid (/ does not exist/ isn't readable)
|
|
52
52
|
*/
|
|
53
53
|
export default async function extractDepcruiseConfig(
|