dependency-cruiser 13.1.5 → 14.1.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/depcruise-baseline.mjs +2 -2
- package/bin/depcruise-fmt.mjs +2 -2
- package/bin/dependency-cruise.mjs +2 -2
- package/package.json +16 -16
- package/src/cli/{validate-node-environment.mjs → assert-node-environment-suitable.mjs} +1 -1
- package/src/cli/format.mjs +4 -4
- package/src/cli/index.mjs +13 -13
- package/src/cli/init-config/build-config.mjs +4 -3
- package/src/cli/init-config/get-user-input.mjs +8 -1
- package/src/cli/init-config/index.mjs +2 -0
- package/src/cli/init-config/types.d.ts +6 -0
- package/src/cli/utl/{validate-file-existence.mjs → assert-file-existence.mjs} +2 -2
- package/src/config-utl/extract-depcruise-config/merge-configs.mjs +9 -9
- package/src/extract/gather-initial-sources.mjs +35 -33
- package/src/extract/resolve/index.mjs +19 -18
- package/src/extract/resolve/is-built-in.mjs +28 -0
- package/src/extract/resolve/resolve-amd.mjs +4 -11
- package/src/extract/resolve/resolve-cjs.mjs +2 -10
- package/src/main/cruise.mjs +12 -12
- package/src/main/format.mjs +3 -3
- package/src/main/options/{validate.mjs → assert-validity.mjs} +35 -35
- package/src/main/resolve-options/normalize.mjs +9 -5
- package/src/main/rule-set/{validate.mjs → assert-validity.mjs} +14 -13
- package/src/meta.js +2 -2
- package/src/schema/configuration.schema.mjs +1 -1
- package/src/schema/cruise-result.schema.mjs +1 -1
- package/types/options.d.ts +21 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { program } from "commander";
|
|
3
|
-
import
|
|
3
|
+
import assertNodeEnvironmentSuitable from "../src/cli/assert-node-environment-suitable.mjs";
|
|
4
4
|
import meta from "../src/meta.js";
|
|
5
5
|
import cli from "../src/cli/index.mjs";
|
|
6
6
|
|
|
@@ -10,7 +10,7 @@ function formatError(pError) {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
try {
|
|
13
|
-
|
|
13
|
+
assertNodeEnvironmentSuitable();
|
|
14
14
|
|
|
15
15
|
program
|
|
16
16
|
.description(
|
package/bin/depcruise-fmt.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { program } from "commander";
|
|
4
|
-
import
|
|
4
|
+
import assertNodeEnvironmentSuitable from "../src/cli/assert-node-environment-suitable.mjs";
|
|
5
5
|
import meta from "../src/meta.js";
|
|
6
6
|
import format from "../src/cli/format.mjs";
|
|
7
7
|
|
|
@@ -11,7 +11,7 @@ function formatError(pError) {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
try {
|
|
14
|
-
|
|
14
|
+
assertNodeEnvironmentSuitable();
|
|
15
15
|
|
|
16
16
|
program
|
|
17
17
|
.description(
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { EOL } from "node:os";
|
|
3
3
|
import { program } from "commander";
|
|
4
|
-
import
|
|
4
|
+
import assertNodeEnvironmentSuitable from "../src/cli/assert-node-environment-suitable.mjs";
|
|
5
5
|
import meta from "../src/meta.js";
|
|
6
6
|
import cli from "../src/cli/index.mjs";
|
|
7
7
|
|
|
8
8
|
try {
|
|
9
|
-
|
|
9
|
+
assertNodeEnvironmentSuitable();
|
|
10
10
|
|
|
11
11
|
program
|
|
12
12
|
.description(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dependency-cruiser",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "14.1.0",
|
|
4
4
|
"description": "Validate and visualize dependencies. With your rules. JavaScript, TypeScript, CoffeeScript. ES6, CommonJS, AMD.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"static analysis",
|
|
@@ -158,13 +158,13 @@
|
|
|
158
158
|
"commander": "11.0.0",
|
|
159
159
|
"enhanced-resolve": "5.15.0",
|
|
160
160
|
"figures": "5.0.0",
|
|
161
|
-
"glob": "10.3.3",
|
|
162
161
|
"ignore": "5.2.4",
|
|
163
162
|
"indent-string": "5.0.0",
|
|
164
163
|
"interpret": "^3.1.1",
|
|
165
164
|
"is-installed-globally": "0.4.0",
|
|
166
165
|
"json5": "2.2.3",
|
|
167
166
|
"lodash": "4.17.21",
|
|
167
|
+
"picomatch": "2.3.1",
|
|
168
168
|
"prompts": "2.4.2",
|
|
169
169
|
"rechoir": "^0.8.0",
|
|
170
170
|
"safe-regex": "2.1.1",
|
|
@@ -176,25 +176,25 @@
|
|
|
176
176
|
"wrap-ansi": "8.1.0"
|
|
177
177
|
},
|
|
178
178
|
"devDependencies": {
|
|
179
|
-
"@babel/core": "7.
|
|
180
|
-
"@babel/plugin-transform-modules-commonjs": "7.
|
|
181
|
-
"@babel/preset-typescript": "7.
|
|
182
|
-
"@swc/core": "1.3.
|
|
183
|
-
"@types/lodash": "4.14.
|
|
184
|
-
"@types/node": "20.
|
|
185
|
-
"@types/prompts": "2.4.
|
|
186
|
-
"@typescript-eslint/eslint-plugin": "6.
|
|
187
|
-
"@typescript-eslint/parser": "6.
|
|
179
|
+
"@babel/core": "7.23.0",
|
|
180
|
+
"@babel/plugin-transform-modules-commonjs": "7.23.0",
|
|
181
|
+
"@babel/preset-typescript": "7.23.0",
|
|
182
|
+
"@swc/core": "1.3.90",
|
|
183
|
+
"@types/lodash": "4.14.199",
|
|
184
|
+
"@types/node": "20.8.0",
|
|
185
|
+
"@types/prompts": "2.4.5",
|
|
186
|
+
"@typescript-eslint/eslint-plugin": "6.7.3",
|
|
187
|
+
"@typescript-eslint/parser": "6.7.3",
|
|
188
188
|
"@vue/compiler-sfc": "3.3.4",
|
|
189
189
|
"c8": "8.0.1",
|
|
190
190
|
"coffeescript": "2.7.0",
|
|
191
|
-
"eslint": "8.
|
|
191
|
+
"eslint": "8.50.0",
|
|
192
192
|
"eslint-config-moving-meadow": "4.0.2",
|
|
193
193
|
"eslint-config-prettier": "9.0.0",
|
|
194
194
|
"eslint-plugin-budapestian": "5.0.1",
|
|
195
195
|
"eslint-plugin-eslint-comments": "3.2.0",
|
|
196
196
|
"eslint-plugin-import": "2.28.1",
|
|
197
|
-
"eslint-plugin-mocha": "10.
|
|
197
|
+
"eslint-plugin-mocha": "10.2.0",
|
|
198
198
|
"eslint-plugin-node": "11.1.0",
|
|
199
199
|
"eslint-plugin-security": "1.7.1",
|
|
200
200
|
"eslint-plugin-unicorn": "^48.0.1",
|
|
@@ -204,11 +204,11 @@
|
|
|
204
204
|
"mocha": "10.2.0",
|
|
205
205
|
"normalize-newline": "4.1.0",
|
|
206
206
|
"npm-run-all": "4.1.5",
|
|
207
|
-
"prettier": "3.0.
|
|
207
|
+
"prettier": "3.0.3",
|
|
208
208
|
"proxyquire": "2.1.3",
|
|
209
209
|
"shx": "0.3.4",
|
|
210
210
|
"svelte": "3.59.1",
|
|
211
|
-
"symlink-dir": "5.
|
|
211
|
+
"symlink-dir": "5.2.0",
|
|
212
212
|
"typescript": "5.2.2",
|
|
213
213
|
"upem": "8.0.0",
|
|
214
214
|
"vue-template-compiler": "2.7.14",
|
|
@@ -240,7 +240,7 @@
|
|
|
240
240
|
]
|
|
241
241
|
},
|
|
242
242
|
"engines": {
|
|
243
|
-
"node": "^
|
|
243
|
+
"node": "^18.17||>=20"
|
|
244
244
|
},
|
|
245
245
|
"supportedTranspilers": {
|
|
246
246
|
"babel": ">=7.0.0 <8.0.0",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import satisfies from "semver/functions/satisfies.js";
|
|
2
2
|
import meta from "../meta.js";
|
|
3
3
|
|
|
4
|
-
export default function
|
|
4
|
+
export default function assertNodeEnvironmentSuitable(pNodeVersion) {
|
|
5
5
|
// not using default parameter here because the check should run
|
|
6
6
|
// run on node 4 as well
|
|
7
7
|
const lNodeVersion = pNodeVersion || process.versions.node;
|
package/src/cli/format.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _format from "../main/format.mjs";
|
|
2
|
-
import
|
|
2
|
+
import assertFileExistence from "./utl/assert-file-existence.mjs";
|
|
3
3
|
import normalizeOptions from "./normalize-cli-options.mjs";
|
|
4
4
|
import { getInStream, write } from "./utl/io.mjs";
|
|
5
5
|
|
|
@@ -13,7 +13,7 @@ export default async function format(pResultFile, pOptions) {
|
|
|
13
13
|
const lOptions = await normalizeOptions(pOptions);
|
|
14
14
|
|
|
15
15
|
if (pResultFile !== "-") {
|
|
16
|
-
|
|
16
|
+
assertFileExistence(pResultFile);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
return new Promise((pResolve, pReject) => {
|
|
@@ -29,13 +29,13 @@ export default async function format(pResultFile, pOptions) {
|
|
|
29
29
|
/* c8 ignore start */
|
|
30
30
|
(pError) => {
|
|
31
31
|
pReject(pError);
|
|
32
|
-
}
|
|
32
|
+
},
|
|
33
33
|
/* c8 ignore stop */
|
|
34
34
|
)
|
|
35
35
|
.on("end", async () => {
|
|
36
36
|
const lReportingResult = await _format(
|
|
37
37
|
JSON.parse(lInputAsString),
|
|
38
|
-
lOptions
|
|
38
|
+
lOptions,
|
|
39
39
|
);
|
|
40
40
|
|
|
41
41
|
write(lOptions.outputTo, lReportingResult.output);
|
package/src/cli/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
|
-
import
|
|
2
|
+
import picomatch from "picomatch";
|
|
3
3
|
import cloneDeep from "lodash/cloneDeep.js";
|
|
4
4
|
import set from "lodash/set.js";
|
|
5
5
|
import isInstalledGlobally from "is-installed-globally";
|
|
@@ -8,7 +8,7 @@ import chalk from "chalk";
|
|
|
8
8
|
import cruise from "../main/cruise.mjs";
|
|
9
9
|
import { INFO, bus } from "../utl/bus.mjs";
|
|
10
10
|
|
|
11
|
-
import
|
|
11
|
+
import assertFileExistence from "./utl/assert-file-existence.mjs";
|
|
12
12
|
import normalizeCliOptions from "./normalize-cli-options.mjs";
|
|
13
13
|
import { write } from "./utl/io.mjs";
|
|
14
14
|
import setUpCliFeedbackListener from "./listeners/cli-feedback.mjs";
|
|
@@ -27,7 +27,7 @@ async function extractResolveOptions(pCruiseOptions) {
|
|
|
27
27
|
lResolveOptions = await extractWebpackResolveConfig(
|
|
28
28
|
lWebPackConfigFileName,
|
|
29
29
|
pCruiseOptions?.ruleSet?.options?.webpackConfig?.env ?? null,
|
|
30
|
-
pCruiseOptions?.ruleSet?.options?.webpackConfig?.arguments ?? null
|
|
30
|
+
pCruiseOptions?.ruleSet?.options?.webpackConfig?.arguments ?? null,
|
|
31
31
|
);
|
|
32
32
|
}
|
|
33
33
|
return lResolveOptions;
|
|
@@ -39,7 +39,7 @@ async function addKnownViolations(pCruiseOptions) {
|
|
|
39
39
|
"../config-utl/extract-known-violations.mjs"
|
|
40
40
|
);
|
|
41
41
|
const lKnownViolations = await extractKnownViolations(
|
|
42
|
-
pCruiseOptions.knownViolationsFile
|
|
42
|
+
pCruiseOptions.knownViolationsFile,
|
|
43
43
|
);
|
|
44
44
|
|
|
45
45
|
// Check against json schema is already done in src/main/options/validate
|
|
@@ -95,24 +95,24 @@ function setUpListener(pCruiseOptions) {
|
|
|
95
95
|
if (Boolean(lListenerFunction)) {
|
|
96
96
|
lListenerFunction(
|
|
97
97
|
bus,
|
|
98
|
-
pCruiseOptions?.ruleSet?.options?.progress?.maximumLevel ?? INFO
|
|
98
|
+
pCruiseOptions?.ruleSet?.options?.progress?.maximumLevel ?? INFO,
|
|
99
99
|
);
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
async function runCruise(pFileDirectoryArray, pCruiseOptions) {
|
|
104
104
|
const lCruiseOptions = await addKnownViolations(
|
|
105
|
-
await normalizeCliOptions(pCruiseOptions)
|
|
105
|
+
await normalizeCliOptions(pCruiseOptions),
|
|
106
106
|
);
|
|
107
107
|
|
|
108
108
|
pFileDirectoryArray
|
|
109
|
-
.filter((pFileOrDirectory) => !
|
|
109
|
+
.filter((pFileOrDirectory) => !picomatch.scan(pFileOrDirectory).isGlob)
|
|
110
110
|
.map((pFileOrDirectory) =>
|
|
111
111
|
lCruiseOptions?.ruleSet?.options?.baseDir
|
|
112
112
|
? join(lCruiseOptions.ruleSet.options.baseDir, pFileOrDirectory)
|
|
113
|
-
: pFileOrDirectory
|
|
113
|
+
: pFileOrDirectory,
|
|
114
114
|
)
|
|
115
|
-
.forEach(
|
|
115
|
+
.forEach(assertFileExistence);
|
|
116
116
|
|
|
117
117
|
setUpListener(lCruiseOptions);
|
|
118
118
|
|
|
@@ -126,7 +126,7 @@ async function runCruise(pFileDirectoryArray, pCruiseOptions) {
|
|
|
126
126
|
pFileDirectoryArray,
|
|
127
127
|
lCruiseOptions,
|
|
128
128
|
lResolveOptions,
|
|
129
|
-
{ tsConfig, babelConfig }
|
|
129
|
+
{ tsConfig, babelConfig },
|
|
130
130
|
);
|
|
131
131
|
|
|
132
132
|
bus.progress("cli: writing results", { complete: 1 });
|
|
@@ -151,14 +151,14 @@ export default async function executeCli(pFileDirectoryArray, pCruiseOptions) {
|
|
|
151
151
|
if (isInstalledGlobally) {
|
|
152
152
|
process.stderr.write(
|
|
153
153
|
`\n ${chalk.yellow(
|
|
154
|
-
"WARNING"
|
|
154
|
+
"WARNING",
|
|
155
155
|
)}: You're running a globally installed dependency-cruiser.\n\n` +
|
|
156
156
|
` We recommend to ${chalk.bold.italic.underline(
|
|
157
|
-
"install and run it as a local devDependency"
|
|
157
|
+
"install and run it as a local devDependency",
|
|
158
158
|
)} in\n` +
|
|
159
159
|
` your project instead. There it has your project's environment and\n` +
|
|
160
160
|
` transpilers at its disposal. That will ensure it can find e.g.\n` +
|
|
161
|
-
` TypeScript, Vue or Svelte modules and dependencies.\n\n
|
|
161
|
+
` TypeScript, Vue or Svelte modules and dependencies.\n\n`,
|
|
162
162
|
);
|
|
163
163
|
}
|
|
164
164
|
/* c8 ignore stop */
|
|
@@ -135,9 +135,10 @@ function buildExtensionsAttribute(pInitOptions) {
|
|
|
135
135
|
* @returns {string}
|
|
136
136
|
*/
|
|
137
137
|
function buildMainFieldsAttribute(pInitOptions) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
if (pInitOptions.isTypeModule) {
|
|
139
|
+
return `mainFields: ["module", "main", "types", "typings"],`;
|
|
140
|
+
}
|
|
141
|
+
return `mainFields: ["main", "types", "typings"],`;
|
|
141
142
|
}
|
|
142
143
|
|
|
143
144
|
/**
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import prompts from "prompts";
|
|
3
3
|
import {
|
|
4
4
|
isLikelyMonoRepo,
|
|
5
|
+
isTypeModule,
|
|
5
6
|
getMonoRepoPackagesCandidates,
|
|
6
7
|
getSourceFolderCandidates,
|
|
7
8
|
getTestFolderCandidates,
|
|
@@ -33,6 +34,12 @@ const QUESTIONS = [
|
|
|
33
34
|
message: "This looks like mono repo. Is that correct?",
|
|
34
35
|
initial: isLikelyMonoRepo(),
|
|
35
36
|
},
|
|
37
|
+
{
|
|
38
|
+
name: "isTypeModule",
|
|
39
|
+
type: () => (isTypeModule() ? "confirm" : false),
|
|
40
|
+
message: "It looks like this is an ESM package. Is that correct?",
|
|
41
|
+
initial: isTypeModule(),
|
|
42
|
+
},
|
|
36
43
|
{
|
|
37
44
|
name: "sourceLocation",
|
|
38
45
|
type: (_, pAnswers) => (pAnswers.isMonoRepo ? "list" : false),
|
|
@@ -61,7 +68,7 @@ const QUESTIONS = [
|
|
|
61
68
|
initial: (_, pAnswers) => {
|
|
62
69
|
return !hasTestsWithinSource(
|
|
63
70
|
getTestFolderCandidates(),
|
|
64
|
-
toSourceLocationArray(pAnswers.sourceLocation)
|
|
71
|
+
toSourceLocationArray(pAnswers.sourceLocation),
|
|
65
72
|
);
|
|
66
73
|
},
|
|
67
74
|
},
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
getDefaultConfigFileName,
|
|
17
17
|
hasJSConfigCandidates,
|
|
18
18
|
getJSConfigCandidates,
|
|
19
|
+
isTypeModule,
|
|
19
20
|
} from "./environment-helpers.mjs";
|
|
20
21
|
import { writeRunScriptsToManifest } from "./write-run-scripts-to-manifest.mjs";
|
|
21
22
|
|
|
@@ -32,6 +33,7 @@ function getOneShotConfig(pOneShotConfigId) {
|
|
|
32
33
|
/** @type {import("./types").IPartialInitConfig} */
|
|
33
34
|
const lBaseConfig = {
|
|
34
35
|
isMonoRepo: isLikelyMonoRepo(),
|
|
36
|
+
isTypeModule: isTypeModule(),
|
|
35
37
|
combinedDependencies: false,
|
|
36
38
|
useJsConfig: hasJSConfigCandidates() && !hasTSConfigCandidates(),
|
|
37
39
|
jsConfig: getJSConfigCandidates().shift(),
|
|
@@ -5,6 +5,12 @@ export interface IInitConfig {
|
|
|
5
5
|
* Whether or not the current folder houses a mono repo
|
|
6
6
|
*/
|
|
7
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;
|
|
8
14
|
/**
|
|
9
15
|
* Whether or not you allow usage of external dependencies declared in
|
|
10
16
|
* package.jsons of parent folders
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { accessSync, R_OK } from "node:fs";
|
|
2
2
|
|
|
3
|
-
export default function
|
|
3
|
+
export default function assertFileExistence(pDirectoryOrFile) {
|
|
4
4
|
try {
|
|
5
5
|
accessSync(pDirectoryOrFile, R_OK);
|
|
6
6
|
} catch (pError) {
|
|
7
7
|
throw new Error(
|
|
8
|
-
`Can't open '${pDirectoryOrFile}' for reading. Does it exist?\n
|
|
8
|
+
`Can't open '${pDirectoryOrFile}' for reading. Does it exist?\n`,
|
|
9
9
|
);
|
|
10
10
|
}
|
|
11
11
|
}
|
|
@@ -10,7 +10,7 @@ function extendNamedRule(pExtendedRule, pForbiddenArrayBase) {
|
|
|
10
10
|
...pBaseRule,
|
|
11
11
|
...pAll,
|
|
12
12
|
}),
|
|
13
|
-
pExtendedRule
|
|
13
|
+
pExtendedRule,
|
|
14
14
|
);
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -23,7 +23,7 @@ function extendNamedRule(pExtendedRule, pForbiddenArrayBase) {
|
|
|
23
23
|
* rules get merged, where individual attributes of the named rules
|
|
24
24
|
* in pForbiddenArrayExtended win)
|
|
25
25
|
*
|
|
26
|
-
* @param {*} pRuleArrayExtended - array of '
|
|
26
|
+
* @param {*} pRuleArrayExtended - array of 'forbidden' rules that extend the ...
|
|
27
27
|
* @param {*} pRuleArrayBase - array of 'forbidden' rules to extend
|
|
28
28
|
*
|
|
29
29
|
* @return {Array} - the merged array
|
|
@@ -32,7 +32,7 @@ function mergeRules(pRuleArrayExtended, pRuleArrayBase) {
|
|
|
32
32
|
// merge anonymous on 100% equality
|
|
33
33
|
let lAnonymousRules = uniqWith(
|
|
34
34
|
pRuleArrayExtended.concat(pRuleArrayBase).filter(({ name }) => !name),
|
|
35
|
-
isDeepStrictEqual
|
|
35
|
+
isDeepStrictEqual,
|
|
36
36
|
);
|
|
37
37
|
|
|
38
38
|
let lNamedRules = pRuleArrayExtended
|
|
@@ -48,7 +48,7 @@ function mergeRules(pRuleArrayExtended, pRuleArrayBase) {
|
|
|
48
48
|
// the other concats (anonymous, allowed) don't need it
|
|
49
49
|
// but have it to be consistent with this
|
|
50
50
|
lNamedRules.concat(pRuleArrayBase).filter(({ name }) => name),
|
|
51
|
-
({ name }) => name
|
|
51
|
+
({ name }) => name,
|
|
52
52
|
);
|
|
53
53
|
|
|
54
54
|
return lNamedRules.concat(lAnonymousRules);
|
|
@@ -67,7 +67,7 @@ function mergeRules(pRuleArrayExtended, pRuleArrayBase) {
|
|
|
67
67
|
function mergeAllowedRules(pAllowedArrayExtended, pAllowedArrayBase) {
|
|
68
68
|
return uniqWith(
|
|
69
69
|
pAllowedArrayExtended.concat(pAllowedArrayBase),
|
|
70
|
-
isDeepStrictEqual
|
|
70
|
+
isDeepStrictEqual,
|
|
71
71
|
);
|
|
72
72
|
}
|
|
73
73
|
|
|
@@ -109,15 +109,15 @@ function mergeAllowedSeverities(pConfigExtended, pConfigBase) {
|
|
|
109
109
|
export default (pConfigExtended, pConfigBase) => {
|
|
110
110
|
const lForbidden = mergeRules(
|
|
111
111
|
pConfigExtended?.forbidden ?? [],
|
|
112
|
-
pConfigBase?.forbidden ?? []
|
|
112
|
+
pConfigBase?.forbidden ?? [],
|
|
113
113
|
);
|
|
114
114
|
const lRequired = mergeRules(
|
|
115
115
|
pConfigExtended?.required ?? [],
|
|
116
|
-
pConfigBase?.required ?? []
|
|
116
|
+
pConfigBase?.required ?? [],
|
|
117
117
|
);
|
|
118
118
|
const lAllowed = mergeAllowedRules(
|
|
119
119
|
pConfigExtended?.allowed ?? [],
|
|
120
|
-
pConfigBase?.allowed ?? []
|
|
120
|
+
pConfigBase?.allowed ?? [],
|
|
121
121
|
);
|
|
122
122
|
|
|
123
123
|
return {
|
|
@@ -131,7 +131,7 @@ export default (pConfigExtended, pConfigBase) => {
|
|
|
131
131
|
: {}),
|
|
132
132
|
options: mergeOptions(
|
|
133
133
|
pConfigExtended?.options ?? {},
|
|
134
|
-
pConfigBase?.options ?? {}
|
|
134
|
+
pConfigBase?.options ?? {},
|
|
135
135
|
),
|
|
136
136
|
};
|
|
137
137
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readdirSync, statSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import
|
|
2
|
+
import { join, normalize } from "node:path";
|
|
3
|
+
import picomatch from "picomatch";
|
|
4
4
|
import { filenameMatchesPattern } from "../graph-utl/match-facade.mjs";
|
|
5
5
|
import getExtension from "../utl/get-extension.mjs";
|
|
6
6
|
import pathToPosix from "../utl/path-to-posix.mjs";
|
|
@@ -45,29 +45,36 @@ function gatherScannableFilesFromDirectory(pDirectoryName, pOptions) {
|
|
|
45
45
|
return readdirSync(join(pOptions.baseDir, pDirectoryName))
|
|
46
46
|
.map((pFileName) => join(pDirectoryName, pFileName))
|
|
47
47
|
.filter((pFullPathToFile) =>
|
|
48
|
-
shouldNotBeExcluded(pathToPosix(pFullPathToFile), pOptions)
|
|
48
|
+
shouldNotBeExcluded(pathToPosix(pFullPathToFile), pOptions),
|
|
49
49
|
)
|
|
50
|
-
.
|
|
50
|
+
.flatMap((pFullPathToFile) => {
|
|
51
51
|
let lStat = statSync(join(pOptions.baseDir, pFullPathToFile), {
|
|
52
52
|
throwIfNoEntry: false,
|
|
53
53
|
});
|
|
54
54
|
|
|
55
55
|
if (lStat) {
|
|
56
56
|
if (lStat.isDirectory()) {
|
|
57
|
-
return
|
|
58
|
-
gatherScannableFilesFromDirectory(pFullPathToFile, pOptions)
|
|
59
|
-
);
|
|
57
|
+
return gatherScannableFilesFromDirectory(pFullPathToFile, pOptions);
|
|
60
58
|
}
|
|
61
59
|
if (fileIsScannable(pOptions, pFullPathToFile)) {
|
|
62
|
-
return
|
|
60
|
+
return pFullPathToFile;
|
|
63
61
|
}
|
|
64
62
|
}
|
|
65
|
-
return
|
|
66
|
-
}
|
|
63
|
+
return [];
|
|
64
|
+
})
|
|
67
65
|
.map((pFullPathToFile) => pathToPosix(pFullPathToFile))
|
|
68
66
|
.filter((pFullPathToFile) => shouldBeIncluded(pFullPathToFile, pOptions));
|
|
69
67
|
}
|
|
70
68
|
|
|
69
|
+
function expandGlob(pBaseDirectory, pScannedGlob) {
|
|
70
|
+
const isMatch = picomatch(pathToPosix(pScannedGlob.glob));
|
|
71
|
+
return readdirSync(join(pBaseDirectory, pScannedGlob.base), {
|
|
72
|
+
recursive: true,
|
|
73
|
+
})
|
|
74
|
+
.filter((pFile) => isMatch(pFile))
|
|
75
|
+
.map((pFile) => pathToPosix(join(pScannedGlob.base, pFile)));
|
|
76
|
+
}
|
|
77
|
+
|
|
71
78
|
/**
|
|
72
79
|
* Returns an array of strings, representing paths to files to be gathered
|
|
73
80
|
*
|
|
@@ -78,7 +85,7 @@ function gatherScannableFilesFromDirectory(pDirectoryName, pOptions) {
|
|
|
78
85
|
* Files and directories are assumed to be either absolute, or relative to the
|
|
79
86
|
* current working directory.
|
|
80
87
|
*
|
|
81
|
-
* @param {string[]}
|
|
88
|
+
* @param {string[]} pFileDirectoryAndGlobArray globs and/ or paths to files or
|
|
82
89
|
* directories to be gathered
|
|
83
90
|
* @param {import('../../types/dependency-cruiser.js').IStrictCruiseOptions} pOptions options that
|
|
84
91
|
* influence what needs to be gathered/ scanned
|
|
@@ -87,31 +94,26 @@ function gatherScannableFilesFromDirectory(pDirectoryName, pOptions) {
|
|
|
87
94
|
* - includeOnly - regexp what to include
|
|
88
95
|
* @return {string[]} paths to files to be gathered.
|
|
89
96
|
*/
|
|
90
|
-
export default function gatherInitialSources(
|
|
97
|
+
export default function gatherInitialSources(
|
|
98
|
+
pFileDirectoryAndGlobArray,
|
|
99
|
+
pOptions,
|
|
100
|
+
) {
|
|
91
101
|
const lOptions = { baseDir: process.cwd(), ...pOptions };
|
|
92
102
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
(
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
cwd: pathToPosix(lOptions.baseDir),
|
|
103
|
-
})
|
|
104
|
-
),
|
|
105
|
-
[]
|
|
106
|
-
)
|
|
107
|
-
.reduce((pAll, pFileOrDirectory) => {
|
|
103
|
+
return pFileDirectoryAndGlobArray
|
|
104
|
+
.flatMap((pFileDirectoryOrGlob) => {
|
|
105
|
+
const lScannedGlob = picomatch.scan(pFileDirectoryOrGlob);
|
|
106
|
+
if (lScannedGlob.isGlob) {
|
|
107
|
+
return expandGlob(lOptions.baseDir, lScannedGlob);
|
|
108
|
+
}
|
|
109
|
+
return normalize(pFileDirectoryOrGlob);
|
|
110
|
+
})
|
|
111
|
+
.flatMap((pFileOrDirectory) => {
|
|
108
112
|
if (statSync(join(lOptions.baseDir, pFileOrDirectory)).isDirectory()) {
|
|
109
|
-
return
|
|
110
|
-
gatherScannableFilesFromDirectory(pFileOrDirectory, lOptions)
|
|
111
|
-
);
|
|
112
|
-
} else {
|
|
113
|
-
return pAll.concat(pathToPosix(pFileOrDirectory));
|
|
113
|
+
return gatherScannableFilesFromDirectory(pFileOrDirectory, lOptions);
|
|
114
114
|
}
|
|
115
|
-
|
|
115
|
+
// Not a glob anymore, and not a directory => it's a file
|
|
116
|
+
return pathToPosix(pFileOrDirectory);
|
|
117
|
+
})
|
|
116
118
|
.sort();
|
|
117
119
|
}
|
|
@@ -21,7 +21,7 @@ function resolveModule(
|
|
|
21
21
|
pModule,
|
|
22
22
|
pBaseDirectory,
|
|
23
23
|
pFileDirectory,
|
|
24
|
-
pResolveOptions
|
|
24
|
+
pResolveOptions,
|
|
25
25
|
) {
|
|
26
26
|
let lReturnValue = null;
|
|
27
27
|
|
|
@@ -34,13 +34,14 @@ function resolveModule(
|
|
|
34
34
|
lStrippedModuleName,
|
|
35
35
|
pBaseDirectory,
|
|
36
36
|
pFileDirectory,
|
|
37
|
-
pResolveOptions
|
|
37
|
+
pResolveOptions,
|
|
38
38
|
);
|
|
39
39
|
} else {
|
|
40
40
|
lReturnValue = resolveAMD(
|
|
41
41
|
lStrippedModuleName,
|
|
42
42
|
pBaseDirectory,
|
|
43
|
-
pFileDirectory
|
|
43
|
+
pFileDirectory,
|
|
44
|
+
pResolveOptions,
|
|
44
45
|
);
|
|
45
46
|
}
|
|
46
47
|
return lReturnValue;
|
|
@@ -89,13 +90,13 @@ function resolveWithRetry(
|
|
|
89
90
|
pModule,
|
|
90
91
|
pBaseDirectory,
|
|
91
92
|
pFileDirectory,
|
|
92
|
-
pResolveOptions
|
|
93
|
+
pResolveOptions,
|
|
93
94
|
) {
|
|
94
95
|
let lReturnValue = resolveModule(
|
|
95
96
|
pModule,
|
|
96
97
|
pBaseDirectory,
|
|
97
98
|
pFileDirectory,
|
|
98
|
-
pResolveOptions
|
|
99
|
+
pResolveOptions,
|
|
99
100
|
);
|
|
100
101
|
const lStrippedModuleName = stripToModuleName(pModule.module);
|
|
101
102
|
|
|
@@ -123,17 +124,17 @@ function resolveWithRetry(
|
|
|
123
124
|
) {
|
|
124
125
|
const lModuleWithoutExtension = lStrippedModuleName.replace(
|
|
125
126
|
/\.(js|jsx|cjs|mjs)$/g,
|
|
126
|
-
""
|
|
127
|
+
"",
|
|
127
128
|
);
|
|
128
129
|
const lExtensionsToTry = getTypeScriptExtensionsToTry(
|
|
129
|
-
extname(lStrippedModuleName)
|
|
130
|
+
extname(lStrippedModuleName),
|
|
130
131
|
);
|
|
131
132
|
|
|
132
133
|
const lReturnValueCandidate = resolveModule(
|
|
133
134
|
{ ...pModule, module: lModuleWithoutExtension },
|
|
134
135
|
pBaseDirectory,
|
|
135
136
|
pFileDirectory,
|
|
136
|
-
{ ...pResolveOptions, extensions: lExtensionsToTry }
|
|
137
|
+
{ ...pResolveOptions, extensions: lExtensionsToTry },
|
|
137
138
|
);
|
|
138
139
|
|
|
139
140
|
if (isTypeScriptIshExtension(lReturnValueCandidate.resolved)) {
|
|
@@ -160,13 +161,13 @@ export default function resolve(
|
|
|
160
161
|
pDependency,
|
|
161
162
|
pBaseDirectory,
|
|
162
163
|
pFileDirectory,
|
|
163
|
-
pResolveOptions
|
|
164
|
+
pResolveOptions,
|
|
164
165
|
) {
|
|
165
166
|
let lResolvedDependency = resolveWithRetry(
|
|
166
167
|
pDependency,
|
|
167
168
|
pBaseDirectory,
|
|
168
169
|
pFileDirectory,
|
|
169
|
-
pResolveOptions
|
|
170
|
+
pResolveOptions,
|
|
170
171
|
);
|
|
171
172
|
const lStrippedModuleName = stripToModuleName(pDependency.module);
|
|
172
173
|
|
|
@@ -176,7 +177,7 @@ export default function resolve(
|
|
|
176
177
|
lStrippedModuleName,
|
|
177
178
|
lResolvedDependency.resolved,
|
|
178
179
|
{ baseDirectory: pBaseDirectory, fileDirectory: pFileDirectory },
|
|
179
|
-
pResolveOptions
|
|
180
|
+
pResolveOptions,
|
|
180
181
|
),
|
|
181
182
|
dependencyTypes: determineDependencyTypes(
|
|
182
183
|
{ ...pDependency, ...lResolvedDependency },
|
|
@@ -184,11 +185,11 @@ export default function resolve(
|
|
|
184
185
|
getManifest(
|
|
185
186
|
pFileDirectory,
|
|
186
187
|
pBaseDirectory,
|
|
187
|
-
pResolveOptions.combinedDependencies
|
|
188
|
+
pResolveOptions.combinedDependencies,
|
|
188
189
|
),
|
|
189
190
|
pFileDirectory,
|
|
190
191
|
pResolveOptions,
|
|
191
|
-
pBaseDirectory
|
|
192
|
+
pBaseDirectory,
|
|
192
193
|
),
|
|
193
194
|
};
|
|
194
195
|
|
|
@@ -210,11 +211,11 @@ export default function resolve(
|
|
|
210
211
|
again corresponds with a real file on disk
|
|
211
212
|
*/
|
|
212
213
|
// eslint-disable-next-line no-control-regex
|
|
213
|
-
lResolvedDependency.resolved.replace(/\u0000#/g, "#")
|
|
214
|
-
)
|
|
215
|
-
)
|
|
216
|
-
)
|
|
217
|
-
)
|
|
214
|
+
lResolvedDependency.resolved.replace(/\u0000#/g, "#"),
|
|
215
|
+
),
|
|
216
|
+
),
|
|
217
|
+
),
|
|
218
|
+
),
|
|
218
219
|
);
|
|
219
220
|
} catch (pError) {
|
|
220
221
|
lResolvedDependency.couldNotResolve = true;
|