dependency-cruiser 16.3.3 → 16.3.4
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 +4 -7
- package/package.json +5 -8
- package/src/cli/format-meta-info.mjs +2 -3
- package/src/cli/init-config/write-config.mjs +1 -4
- package/src/cli/init-config/write-run-scripts-to-manifest.mjs +21 -13
- package/src/cli/listeners/cli-feedback.mjs +2 -3
- package/src/config-utl/extract-babel-config.mjs +1 -1
- package/src/config-utl/extract-ts-config.mjs +1 -1
- package/src/extract/swc/dependency-visitor.mjs +1 -1
- package/src/extract/swc/parse.mjs +1 -1
- package/src/extract/transpile/babel-wrap.mjs +1 -1
- package/src/extract/transpile/coffeescript-wrap.mjs +1 -1
- package/src/extract/transpile/livescript-wrap.mjs +1 -1
- package/src/extract/transpile/svelte-wrap.mjs +1 -1
- package/src/extract/transpile/typescript-wrap.mjs +1 -1
- package/src/extract/transpile/vue-template-wrap.cjs +1 -1
- package/src/extract/tsc/extract-typescript-deps.mjs +1 -1
- package/src/extract/tsc/parse.mjs +1 -1
- package/src/meta.cjs +1 -1
- package/src/report/error.mjs +8 -19
- package/src/report/text.mjs +1 -4
- package/src/utl/extract-root-module-name.cjs +23 -0
- package/src/utl/try-import.mjs +67 -0
- package/src/utl/try-require.cjs +51 -0
- package/src/utl/wrap-and-indent.mjs +9 -4
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import * as path from "node:path";
|
|
2
|
-
import figures from "figures";
|
|
3
2
|
|
|
4
3
|
const TEMPLATE = `
|
|
5
4
|
<html>
|
|
@@ -74,9 +73,7 @@ function formatFileName(pFileName) {
|
|
|
74
73
|
return `${path.dirname(pFileName)}/<b>${path.basename(pFileName)}</b>`;
|
|
75
74
|
}
|
|
76
75
|
function formatDependency(pFrom, pTo) {
|
|
77
|
-
return `${formatFileName(pFrom)}
|
|
78
|
-
pTo
|
|
79
|
-
)}`;
|
|
76
|
+
return `${formatFileName(pFrom)} →</br>${formatFileName(pTo)}`;
|
|
80
77
|
}
|
|
81
78
|
|
|
82
79
|
/**
|
|
@@ -100,14 +97,14 @@ function render3DThing(pCruiseResult) {
|
|
|
100
97
|
source: pCurrentModule.source,
|
|
101
98
|
target: pDependency.resolved,
|
|
102
99
|
label: formatDependency(pCurrentModule.source, pDependency.resolved),
|
|
103
|
-
}))
|
|
100
|
+
})),
|
|
104
101
|
),
|
|
105
|
-
[]
|
|
102
|
+
[],
|
|
106
103
|
);
|
|
107
104
|
|
|
108
105
|
return TEMPLATE.replace(/@@NODES@@/g, JSON.stringify(lNodes)).replace(
|
|
109
106
|
/@@LINKS@@/g,
|
|
110
|
-
JSON.stringify(lLinks)
|
|
107
|
+
JSON.stringify(lLinks),
|
|
111
108
|
);
|
|
112
109
|
}
|
|
113
110
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dependency-cruiser",
|
|
3
|
-
"version": "16.3.
|
|
3
|
+
"version": "16.3.4",
|
|
4
4
|
"description": "Validate and visualize dependencies. With your rules. JavaScript, TypeScript, CoffeeScript. ES6, CommonJS, AMD.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"static analysis",
|
|
@@ -59,6 +59,7 @@
|
|
|
59
59
|
"electrovir (https://github.com/electrovir)",
|
|
60
60
|
"fusheng (https://github.com/lin-hun)"
|
|
61
61
|
],
|
|
62
|
+
"type": "module",
|
|
62
63
|
"license": "MIT",
|
|
63
64
|
"repository": {
|
|
64
65
|
"type": "git",
|
|
@@ -136,18 +137,16 @@
|
|
|
136
137
|
"README.md"
|
|
137
138
|
],
|
|
138
139
|
"dependencies": {
|
|
139
|
-
"acorn": "8.
|
|
140
|
+
"acorn": "8.12.0",
|
|
140
141
|
"acorn-jsx": "5.3.2",
|
|
141
142
|
"acorn-jsx-walk": "2.0.0",
|
|
142
143
|
"acorn-loose": "8.4.0",
|
|
143
|
-
"acorn-walk": "8.3.
|
|
144
|
+
"acorn-walk": "8.3.3",
|
|
144
145
|
"ajv": "8.16.0",
|
|
145
146
|
"chalk": "5.3.0",
|
|
146
147
|
"commander": "12.1.0",
|
|
147
148
|
"enhanced-resolve": "5.17.0",
|
|
148
|
-
"figures": "6.1.0",
|
|
149
149
|
"ignore": "5.3.1",
|
|
150
|
-
"indent-string": "5.0.0",
|
|
151
150
|
"interpret": "^3.1.1",
|
|
152
151
|
"is-installed-globally": "1.0.0",
|
|
153
152
|
"json5": "2.2.3",
|
|
@@ -158,7 +157,6 @@
|
|
|
158
157
|
"rechoir": "^0.8.0",
|
|
159
158
|
"safe-regex": "2.1.1",
|
|
160
159
|
"semver": "^7.6.2",
|
|
161
|
-
"semver-try-require": "7.0.0",
|
|
162
160
|
"teamcity-service-messages": "0.1.14",
|
|
163
161
|
"tsconfig-paths-webpack-plugin": "4.1.0",
|
|
164
162
|
"watskeburt": "4.0.2",
|
|
@@ -177,6 +175,5 @@
|
|
|
177
175
|
},
|
|
178
176
|
"scripts": {
|
|
179
177
|
"test": "echo for test, build and static analysis scripts: see the github repository"
|
|
180
|
-
}
|
|
181
|
-
"type": "module"
|
|
178
|
+
}
|
|
182
179
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
-
import figures from "figures";
|
|
3
2
|
|
|
4
3
|
import { getAvailableTranspilers, allExtensions } from "#main/index.mjs";
|
|
5
4
|
|
|
6
5
|
function bool2Symbol(pBool) {
|
|
7
|
-
return pBool ? chalk.green(
|
|
6
|
+
return pBool ? chalk.green("✔") : chalk.red("x");
|
|
8
7
|
}
|
|
9
8
|
|
|
10
9
|
function formatTranspilers() {
|
|
@@ -30,7 +29,7 @@ export default function formatMetaInfo() {
|
|
|
30
29
|
Supported:
|
|
31
30
|
|
|
32
31
|
If you need a supported, but not enabled transpiler ('${chalk.red(
|
|
33
|
-
|
|
32
|
+
"x",
|
|
34
33
|
)}' below), just install
|
|
35
34
|
it in the same folder dependency-cruiser is installed. E.g. 'npm i livescript'
|
|
36
35
|
will enable livescript support if it's installed in your project folder.
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { writeFileSync } from "node:fs";
|
|
2
|
-
import figures from "figures";
|
|
3
2
|
import chalk from "chalk";
|
|
4
3
|
import {
|
|
5
4
|
fileExists,
|
|
@@ -30,9 +29,7 @@ export default function writeConfig(
|
|
|
30
29
|
try {
|
|
31
30
|
writeFileSync(pFileName, pConfig);
|
|
32
31
|
pOutStream.write(
|
|
33
|
-
`\n ${chalk.green(
|
|
34
|
-
figures.tick,
|
|
35
|
-
)} Successfully created '${pFileName}'\n\n`,
|
|
32
|
+
`\n ${chalk.green("✔")} Successfully created '${pFileName}'\n\n`,
|
|
36
33
|
);
|
|
37
34
|
/* c8 ignore start */
|
|
38
35
|
} catch (pError) {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
/* eslint-disable prefer-template */
|
|
1
2
|
/* eslint-disable security/detect-object-injection */
|
|
2
3
|
import { writeFileSync } from "node:fs";
|
|
3
|
-
import
|
|
4
|
+
import { EOL } from "node:os";
|
|
4
5
|
import chalk from "chalk";
|
|
5
6
|
import { PACKAGE_MANIFEST as _PACKAGE_MANIFEST } from "../defaults.mjs";
|
|
6
7
|
import { readManifest } from "./environment-helpers.mjs";
|
|
7
8
|
import { folderNameArrayToRE } from "./utl.mjs";
|
|
8
|
-
import wrapAndIndent from "#utl/wrap-and-indent.mjs";
|
|
9
9
|
|
|
10
10
|
const PACKAGE_MANIFEST = `./${_PACKAGE_MANIFEST}`;
|
|
11
11
|
|
|
@@ -14,37 +14,47 @@ const EXPERIMENTAL_SCRIPT_DOC = [
|
|
|
14
14
|
name: "depcruise",
|
|
15
15
|
headline: "npm run depcruise",
|
|
16
16
|
description:
|
|
17
|
-
"validates against the rules in .dependency-cruiser.js and writes the
|
|
17
|
+
" validates against the rules in .dependency-cruiser.js and writes the" +
|
|
18
|
+
EOL +
|
|
19
|
+
" outcome to stdout",
|
|
18
20
|
},
|
|
19
21
|
{
|
|
20
22
|
name: "depcruise:html",
|
|
21
23
|
headline: "npm run depcruise:html",
|
|
22
24
|
description:
|
|
23
|
-
"validates against the rules in .dependency-cruiser.js and writes it to
|
|
25
|
+
" validates against the rules in .dependency-cruiser.js and writes it to" +
|
|
26
|
+
EOL +
|
|
27
|
+
" 'dependency-violation-report.html' with a friendly layout",
|
|
24
28
|
},
|
|
25
29
|
{
|
|
26
30
|
name: "depcruise:graph",
|
|
27
31
|
headline: "npm run depcruise:graph",
|
|
28
32
|
description:
|
|
29
|
-
"writes a detailed internal graph of your app to 'dependency-graph.html'",
|
|
33
|
+
" writes a detailed internal graph of your app to 'dependency-graph.html'",
|
|
30
34
|
},
|
|
31
35
|
{
|
|
32
36
|
name: "depcruise:graph:dev",
|
|
33
37
|
headline: "npm run depcruise:graph:dev",
|
|
34
38
|
description:
|
|
35
|
-
"opens a detailed internal graph of your app in your default browser
|
|
39
|
+
" opens a detailed internal graph of your app in your default browser" +
|
|
40
|
+
EOL +
|
|
41
|
+
" (uses the 'browser' command line program)",
|
|
36
42
|
},
|
|
37
43
|
{
|
|
38
44
|
name: "depcruise:graph:archi",
|
|
39
45
|
headline: "depcruise:graph:archi",
|
|
40
46
|
description:
|
|
41
|
-
"writes a high-level internal graph of your app to
|
|
47
|
+
" writes a high-level internal graph of your app to" +
|
|
48
|
+
EOL +
|
|
49
|
+
" 'high-level-dependency-graph.html",
|
|
42
50
|
},
|
|
43
51
|
{
|
|
44
52
|
name: "depcruise:focus",
|
|
45
53
|
headline: "npm run depcruise:focus <regex>",
|
|
46
54
|
description:
|
|
47
|
-
"writes all dependencies to and from modules matching the given <regex>
|
|
55
|
+
" writes all dependencies to and from modules matching the given <regex>" +
|
|
56
|
+
EOL +
|
|
57
|
+
" to stdout - in simple text",
|
|
48
58
|
},
|
|
49
59
|
// {
|
|
50
60
|
// name: "depcruise:text",
|
|
@@ -121,13 +131,11 @@ function getSuccessMessage(pDestinationManifestFileName) {
|
|
|
121
131
|
return EXPERIMENTAL_SCRIPT_DOC.reduce(
|
|
122
132
|
(pAll, pScript) => {
|
|
123
133
|
return `${pAll}${
|
|
124
|
-
`\n ${chalk.green(
|
|
125
|
-
`\n${
|
|
134
|
+
`\n ${chalk.green("►")} ${pScript.headline}` +
|
|
135
|
+
`\n${pScript.description}\n\n`
|
|
126
136
|
}`;
|
|
127
137
|
},
|
|
128
|
-
` ${chalk.green(
|
|
129
|
-
figures.tick,
|
|
130
|
-
)} Run scripts added to '${pDestinationManifestFileName}':\n`,
|
|
138
|
+
` ${chalk.green("✔")} Run scripts added to '${pDestinationManifestFileName}':\n`,
|
|
131
139
|
);
|
|
132
140
|
}
|
|
133
141
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
-
import figures from "figures";
|
|
3
2
|
import { SUMMARY } from "#utl/bus.mjs";
|
|
4
3
|
|
|
5
4
|
const FULL_ON = 100;
|
|
@@ -7,8 +6,8 @@ const FULL_ON = 100;
|
|
|
7
6
|
function normalizeParameters(pParameters) {
|
|
8
7
|
return {
|
|
9
8
|
barSize: 10,
|
|
10
|
-
block:
|
|
11
|
-
blank:
|
|
9
|
+
block: "■",
|
|
10
|
+
blank: "□",
|
|
12
11
|
...(pParameters || {}),
|
|
13
12
|
};
|
|
14
13
|
}
|
|
@@ -2,8 +2,8 @@ import { readFile } from "node:fs/promises";
|
|
|
2
2
|
|
|
3
3
|
import { extname } from "node:path";
|
|
4
4
|
import json5 from "json5";
|
|
5
|
-
import tryImport from "semver-try-require";
|
|
6
5
|
import makeAbsolute from "./make-absolute.mjs";
|
|
6
|
+
import tryImport from "#utl/try-import.mjs";
|
|
7
7
|
import meta from "#meta.cjs";
|
|
8
8
|
|
|
9
9
|
async function getJSConfig(pBabelConfigFileName) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
|
-
import tryImport from "semver-try-require";
|
|
3
2
|
import memoize, { memoizeClear } from "memoize";
|
|
4
3
|
import transpile from "../transpile/index.mjs";
|
|
4
|
+
import tryImport from "#utl/try-import.mjs";
|
|
5
5
|
import meta from "#meta.cjs";
|
|
6
6
|
import getExtension from "#utl/get-extension.mjs";
|
|
7
7
|
|
package/src/meta.cjs
CHANGED
package/src/report/error.mjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { EOL } from "node:os";
|
|
2
2
|
import chalk from "chalk";
|
|
3
|
-
import figures from "figures";
|
|
4
3
|
import {
|
|
5
4
|
formatPercentage,
|
|
6
5
|
formatViolation as _formatViolation,
|
|
@@ -20,9 +19,7 @@ const EXTRA_PATH_INFORMATION_INDENT = 6;
|
|
|
20
19
|
function formatMiniDependency(pMiniDependency) {
|
|
21
20
|
return EOL.concat(
|
|
22
21
|
wrapAndIndent(
|
|
23
|
-
pMiniDependency
|
|
24
|
-
.map(({ name }) => name)
|
|
25
|
-
.join(` ${figures.arrowRight} ${EOL}`),
|
|
22
|
+
pMiniDependency.map(({ name }) => name).join(` → ${EOL}`),
|
|
26
23
|
EXTRA_PATH_INFORMATION_INDENT,
|
|
27
24
|
),
|
|
28
25
|
);
|
|
@@ -33,19 +30,15 @@ function formatModuleViolation(pViolation) {
|
|
|
33
30
|
}
|
|
34
31
|
|
|
35
32
|
function formatDependencyViolation(pViolation) {
|
|
36
|
-
return `${chalk.bold(pViolation.from)}
|
|
37
|
-
pViolation.to,
|
|
38
|
-
)}`;
|
|
33
|
+
return `${chalk.bold(pViolation.from)} → ${chalk.bold(pViolation.to)}`;
|
|
39
34
|
}
|
|
40
35
|
|
|
41
36
|
function formatCycleViolation(pViolation) {
|
|
42
|
-
return `${chalk.bold(pViolation.from)} ${
|
|
43
|
-
figures.arrowRight
|
|
44
|
-
} ${formatMiniDependency(pViolation.cycle)}`;
|
|
37
|
+
return `${chalk.bold(pViolation.from)} → ${formatMiniDependency(pViolation.cycle)}`;
|
|
45
38
|
}
|
|
46
39
|
|
|
47
40
|
function formatReachabilityViolation(pViolation) {
|
|
48
|
-
return `${chalk.bold(pViolation.from)}
|
|
41
|
+
return `${chalk.bold(pViolation.from)} → ${chalk.bold(
|
|
49
42
|
pViolation.to,
|
|
50
43
|
)}${formatMiniDependency(pViolation.via)}`;
|
|
51
44
|
}
|
|
@@ -53,9 +46,7 @@ function formatReachabilityViolation(pViolation) {
|
|
|
53
46
|
function formatInstabilityViolation(pViolation) {
|
|
54
47
|
return `${formatDependencyViolation(pViolation)}${EOL}${wrapAndIndent(
|
|
55
48
|
chalk.dim(
|
|
56
|
-
`instability: ${formatPercentage(pViolation.metrics.from.instability)} ${
|
|
57
|
-
figures.arrowRight
|
|
58
|
-
} ${formatPercentage(pViolation.metrics.to.instability)}`,
|
|
49
|
+
`instability: ${formatPercentage(pViolation.metrics.from.instability)} → ${formatPercentage(pViolation.metrics.to.instability)}`,
|
|
59
50
|
),
|
|
60
51
|
EXTRA_PATH_INFORMATION_INDENT,
|
|
61
52
|
)}`;
|
|
@@ -96,7 +87,7 @@ function sumMeta(pMeta) {
|
|
|
96
87
|
}
|
|
97
88
|
|
|
98
89
|
function formatSummary(pSummary) {
|
|
99
|
-
let lMessage = `${EOL}
|
|
90
|
+
let lMessage = `${EOL}x ${sumMeta(
|
|
100
91
|
pSummary,
|
|
101
92
|
)} dependency violations (${formatMeta(pSummary)}). ${
|
|
102
93
|
pSummary.totalCruised
|
|
@@ -117,7 +108,7 @@ function addExplanation(pRuleSet, pLong) {
|
|
|
117
108
|
function formatIgnoreWarning(pNumberOfIgnoredViolations) {
|
|
118
109
|
if (pNumberOfIgnoredViolations > 0) {
|
|
119
110
|
return chalk.yellow(
|
|
120
|
-
|
|
111
|
+
`‼ ${pNumberOfIgnoredViolations} known violations ignored. Run with --no-ignore-known to see them.${EOL}`,
|
|
121
112
|
);
|
|
122
113
|
}
|
|
123
114
|
return "";
|
|
@@ -129,9 +120,7 @@ function report(pResults, pLong) {
|
|
|
129
120
|
);
|
|
130
121
|
|
|
131
122
|
if (lNonIgnorableViolations.length === 0) {
|
|
132
|
-
return `${EOL}${chalk.green(
|
|
133
|
-
figures.tick,
|
|
134
|
-
)} no dependency violations found (${
|
|
123
|
+
return `${EOL}${chalk.green("✔")} no dependency violations found (${
|
|
135
124
|
pResults.summary.totalCruised
|
|
136
125
|
} modules, ${
|
|
137
126
|
pResults.summary.totalDependenciesCruised
|
package/src/report/text.mjs
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import figures from "figures";
|
|
2
1
|
import chalk from "chalk";
|
|
3
2
|
|
|
4
3
|
const DEFAULT_OPTIONS = {
|
|
@@ -41,9 +40,7 @@ function stringifyModule(pModule) {
|
|
|
41
40
|
}
|
|
42
41
|
|
|
43
42
|
function stringify(pFlatDependency) {
|
|
44
|
-
return `${stringifyModule(pFlatDependency.from)} ${
|
|
45
|
-
figures.arrowRight
|
|
46
|
-
} ${stringifyModule(pFlatDependency.to)}`;
|
|
43
|
+
return `${stringifyModule(pFlatDependency.from)} → ${stringifyModule(pFlatDependency.to)}`;
|
|
47
44
|
}
|
|
48
45
|
|
|
49
46
|
/**
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const LOCAL_MODULE_RE = /^[.]{1,2}($|\/.*)/g;
|
|
2
|
+
const ABSOLUTE_MODULE_RE = /^\/.*/g;
|
|
3
|
+
|
|
4
|
+
const PACKAGE_RE = "[^/]+";
|
|
5
|
+
const SCOPED_PACKAGE_RE = "@[^/]+(/[^/]+)";
|
|
6
|
+
const ROOT_MODULE_RE = new RegExp(`^(${SCOPED_PACKAGE_RE}|${PACKAGE_RE})`, "g");
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* returns the module name that likely contains the package.json
|
|
10
|
+
*
|
|
11
|
+
* @param {string} pModuleName module name string as you'd require it
|
|
12
|
+
* @returns {string|undefined} the module name that likely contains the package.json
|
|
13
|
+
*/
|
|
14
|
+
module.exports = function extractRootModuleName(pModuleName) {
|
|
15
|
+
if (
|
|
16
|
+
pModuleName.match(LOCAL_MODULE_RE) ||
|
|
17
|
+
pModuleName.match(ABSOLUTE_MODULE_RE)
|
|
18
|
+
) {
|
|
19
|
+
return pModuleName;
|
|
20
|
+
} else {
|
|
21
|
+
return (pModuleName.match(ROOT_MODULE_RE) || []).shift();
|
|
22
|
+
}
|
|
23
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { join } from "node:path/posix";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { coerce, satisfies } from "semver";
|
|
4
|
+
import extractRootModuleName from "./extract-root-module-name.cjs";
|
|
5
|
+
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @throws {Error}
|
|
10
|
+
* @param {string} pModuleName
|
|
11
|
+
* @returns {string}
|
|
12
|
+
*/
|
|
13
|
+
function getVersion(pModuleName) {
|
|
14
|
+
// // The 'proper' way to do this would be with a dynamic import with an
|
|
15
|
+
// // import assertion. Because it's 'experimental' since node 16 and prints
|
|
16
|
+
// // an ugly warning on stderr since node 19 we'll be using the require
|
|
17
|
+
// // hack below in stead.
|
|
18
|
+
// const lManifest = await import(
|
|
19
|
+
// // @ts-expect-error TS2345 extractRootModuleName can return either a string or
|
|
20
|
+
// // undefined. If undefined this function will throw. Which is _fine_, even
|
|
21
|
+
// // _expected_ in the context it's currently used
|
|
22
|
+
// path.join(extractRootModuleName(pModuleName), "package.json"),
|
|
23
|
+
// { assert: { type: "json" } }
|
|
24
|
+
// );
|
|
25
|
+
// // changes the return type to Promise<string>
|
|
26
|
+
// return lManifest.default.version;
|
|
27
|
+
// eslint-disable-next-line import/no-dynamic-require, security/detect-non-literal-require
|
|
28
|
+
const lManifest = require(
|
|
29
|
+
join(
|
|
30
|
+
// @ts-expect-error TS2345 extractRootModuleName can return either a string or
|
|
31
|
+
// undefined. If undefined this function will throw. Which is _fine_, even
|
|
32
|
+
// _expected_ in the context it's currently used
|
|
33
|
+
extractRootModuleName(pModuleName),
|
|
34
|
+
"package.json",
|
|
35
|
+
),
|
|
36
|
+
);
|
|
37
|
+
return lManifest.version;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Tries to import a module and optionally checks its version.
|
|
42
|
+
*
|
|
43
|
+
* @param {string} pModuleName - The name of the module to import.
|
|
44
|
+
* @param {string} [pSemanticVersion] - An semantic version to check against.
|
|
45
|
+
* @returns {Promise<NodeModule | false>} - The imported module or false if the import fails or the version does not satisfy the provided semantic version.
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
// eslint-disable-next-line complexity
|
|
49
|
+
export default async function tryImport(pModuleName, pSemanticVersion) {
|
|
50
|
+
try {
|
|
51
|
+
if (pSemanticVersion) {
|
|
52
|
+
const lVersion = getVersion(pModuleName);
|
|
53
|
+
const lCoerced = coerce(lVersion);
|
|
54
|
+
if (
|
|
55
|
+
lVersion &&
|
|
56
|
+
lCoerced &&
|
|
57
|
+
!satisfies(lCoerced.version, pSemanticVersion)
|
|
58
|
+
) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const lModule = await import(pModuleName);
|
|
63
|
+
return lModule.default ? lModule.default : lModule;
|
|
64
|
+
} catch (pError) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const { join } = require("node:path");
|
|
2
|
+
const satisfies = require("semver/functions/satisfies");
|
|
3
|
+
const coerce = require("semver/functions/coerce");
|
|
4
|
+
const extractRootModuleName = require("./extract-root-module-name.cjs");
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @throws {Error}
|
|
8
|
+
* @param pModuleName the name of the module to get the version for
|
|
9
|
+
* @return the version of the module identified by pModuleName
|
|
10
|
+
*/
|
|
11
|
+
function getVersion(pModuleName) {
|
|
12
|
+
// @ts-expect-error TS2345 extractRootModuleName can return either a string or
|
|
13
|
+
// undefined. If undefined this function will throw. Which is _fine_, even
|
|
14
|
+
// _expected_ in the context it's currently used
|
|
15
|
+
// eslint-disable-next-line import/no-dynamic-require, node/global-require, security/detect-non-literal-require
|
|
16
|
+
return require(join(extractRootModuleName(pModuleName), "package.json"))
|
|
17
|
+
.version;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* returns the (resolved) module identified by pModuleName:
|
|
22
|
+
* - if it is available, and
|
|
23
|
+
* - it satisfies the semantic version range specified by pSemVer
|
|
24
|
+
*
|
|
25
|
+
* returns false in all other cases
|
|
26
|
+
*
|
|
27
|
+
* @param {string} pModuleName the name of the module to resolve
|
|
28
|
+
* @param {string} [pSemanticVersion] (optional) a semantic version (range)
|
|
29
|
+
* @return {NodeModule | false }the (resolved) module identified by pModuleName or false
|
|
30
|
+
*/
|
|
31
|
+
function tryRequire(pModuleName, pSemanticVersion) {
|
|
32
|
+
try {
|
|
33
|
+
if (pSemanticVersion) {
|
|
34
|
+
const lVersion = getVersion(pModuleName);
|
|
35
|
+
const lCoerced = coerce(lVersion);
|
|
36
|
+
if (
|
|
37
|
+
lVersion &&
|
|
38
|
+
lCoerced &&
|
|
39
|
+
!satisfies(lCoerced.version, pSemanticVersion)
|
|
40
|
+
) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// eslint-disable-next-line import/no-dynamic-require, node/global-require, security/detect-non-literal-require
|
|
45
|
+
return require(pModuleName);
|
|
46
|
+
} catch (pError) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports = tryRequire;
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
import indentString from "indent-string";
|
|
2
1
|
import wrapAnsi from "wrap-ansi";
|
|
3
2
|
|
|
4
3
|
const DEFAULT_INDENT = 4;
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
function indentString(pString, pCount) {
|
|
6
|
+
const lRegex = /^(?!\s*$)/gm;
|
|
7
|
+
|
|
8
|
+
return pString.replace(lRegex, " ".repeat(pCount));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default function wrapAndIndent(pString, pCount = DEFAULT_INDENT) {
|
|
7
12
|
const lDogmaticMaxConsoleWidth = 78;
|
|
8
|
-
const lMaxWidth = lDogmaticMaxConsoleWidth -
|
|
13
|
+
const lMaxWidth = lDogmaticMaxConsoleWidth - pCount;
|
|
9
14
|
|
|
10
|
-
return indentString(wrapAnsi(pString, lMaxWidth),
|
|
15
|
+
return indentString(wrapAnsi(pString, lMaxWidth), pCount);
|
|
11
16
|
}
|