dependency-cruiser 14.0.0 → 14.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.
Files changed (38) hide show
  1. package/bin/depcruise-baseline.mjs +2 -2
  2. package/bin/depcruise-fmt.mjs +2 -2
  3. package/bin/dependency-cruise.mjs +2 -2
  4. package/package.json +18 -16
  5. package/src/cli/{validate-node-environment.mjs → assert-node-environment-suitable.mjs} +1 -1
  6. package/src/cli/index.mjs +1 -2
  7. package/src/cli/init-config/build-config.mjs +4 -3
  8. package/src/cli/init-config/get-user-input.mjs +8 -1
  9. package/src/cli/init-config/index.mjs +2 -0
  10. package/src/cli/init-config/types.d.ts +6 -0
  11. package/src/cli/normalize-cli-options.mjs +9 -10
  12. package/src/config-utl/extract-depcruise-config/index.mjs +10 -11
  13. package/src/config-utl/extract-depcruise-config/merge-configs.mjs +9 -9
  14. package/src/enrich/derive/reachable.mjs +12 -13
  15. package/src/enrich/summarize/add-rule-set-used.mjs +2 -4
  16. package/src/extract/gather-initial-sources.mjs +6 -8
  17. package/src/extract/resolve/index.mjs +19 -18
  18. package/src/extract/resolve/is-built-in.mjs +28 -0
  19. package/src/extract/resolve/merge-manifests.mjs +8 -7
  20. package/src/extract/resolve/resolve-amd.mjs +4 -11
  21. package/src/extract/resolve/resolve-cjs.mjs +2 -10
  22. package/src/graph-utl/consolidate-module-dependencies.mjs +4 -5
  23. package/src/graph-utl/consolidate-modules.mjs +3 -4
  24. package/src/graph-utl/filter-bank.mjs +5 -6
  25. package/src/main/cruise.mjs +12 -12
  26. package/src/main/format.mjs +3 -3
  27. package/src/main/helpers.mjs +3 -4
  28. package/src/main/options/{validate.mjs → assert-validity.mjs} +35 -35
  29. package/src/main/options/normalize.mjs +6 -7
  30. package/src/main/resolve-options/normalize.mjs +9 -5
  31. package/src/main/rule-set/{validate.mjs → assert-validity.mjs} +14 -13
  32. package/src/main/rule-set/normalize.mjs +1 -2
  33. package/src/meta.js +1 -1
  34. package/src/report/anon/index.mjs +5 -6
  35. package/src/report/dot/theming.mjs +5 -6
  36. package/src/schema/configuration.schema.mjs +1 -1
  37. package/src/schema/cruise-result.schema.mjs +1 -1
  38. 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 validateNodeEnvironment from "../src/cli/validate-node-environment.mjs";
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
- validateNodeEnvironment();
13
+ assertNodeEnvironmentSuitable();
14
14
 
15
15
  program
16
16
  .description(
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { program } from "commander";
4
- import validateNodeEnvironment from "../src/cli/validate-node-environment.mjs";
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
- validateNodeEnvironment();
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 validateNodeEnvironment from "../src/cli/validate-node-environment.mjs";
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
- validateNodeEnvironment();
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": "14.0.0",
3
+ "version": "14.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",
@@ -29,7 +29,7 @@
29
29
  "license": "MIT",
30
30
  "repository": {
31
31
  "type": "git",
32
- "url": "git+https://github.com/sverweij/dependency-cruiser"
32
+ "url": "git+https://github.com/sverweij/dependency-cruiser.git"
33
33
  },
34
34
  "bugs": {
35
35
  "url": "https://github.com/sverweij/dependency-cruiser/issues"
@@ -172,29 +172,29 @@
172
172
  "semver-try-require": "6.2.3",
173
173
  "teamcity-service-messages": "0.1.14",
174
174
  "tsconfig-paths-webpack-plugin": "4.1.0",
175
- "watskeburt": "1.0.1",
175
+ "watskeburt": "2.0.0",
176
176
  "wrap-ansi": "8.1.0"
177
177
  },
178
178
  "devDependencies": {
179
- "@babel/core": "7.22.20",
180
- "@babel/plugin-transform-modules-commonjs": "7.22.15",
181
- "@babel/preset-typescript": "7.22.15",
182
- "@swc/core": "1.3.87",
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.92",
183
183
  "@types/lodash": "4.14.199",
184
- "@types/node": "20.6.3",
185
- "@types/prompts": "2.4.4",
186
- "@typescript-eslint/eslint-plugin": "6.7.2",
187
- "@typescript-eslint/parser": "6.7.2",
184
+ "@types/node": "20.8.3",
185
+ "@types/prompts": "2.4.5",
186
+ "@typescript-eslint/eslint-plugin": "6.7.4",
187
+ "@typescript-eslint/parser": "6.7.4",
188
188
  "@vue/compiler-sfc": "3.3.4",
189
189
  "c8": "8.0.1",
190
190
  "coffeescript": "2.7.0",
191
- "eslint": "8.50.0",
191
+ "eslint": "8.51.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.1.0",
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",
@@ -210,15 +210,17 @@
210
210
  "svelte": "3.59.1",
211
211
  "symlink-dir": "5.2.0",
212
212
  "typescript": "5.2.2",
213
- "upem": "8.0.0",
213
+ "upem": "9.0.2",
214
214
  "vue-template-compiler": "2.7.14",
215
215
  "yarn": "1.22.19"
216
216
  },
217
217
  "overrides": {
218
- "semver": "^7.5.4"
218
+ "semver": "^7.5.4",
219
+ "postcss": "^8.4.31"
219
220
  },
220
221
  "resolutions": {
221
- "semver": "^7.5.4"
222
+ "semver": "^7.5.4",
223
+ "postcss": "^8.4.31"
222
224
  },
223
225
  "upem": {
224
226
  "policies": [
@@ -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 validateNodeEnvironment(pNodeVersion) {
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/index.mjs CHANGED
@@ -1,6 +1,5 @@
1
1
  import { join } from "node:path";
2
2
  import picomatch from "picomatch";
3
- import cloneDeep from "lodash/cloneDeep.js";
4
3
  import set from "lodash/set.js";
5
4
  import isInstalledGlobally from "is-installed-globally";
6
5
  import chalk from "chalk";
@@ -44,7 +43,7 @@ async function addKnownViolations(pCruiseOptions) {
44
43
 
45
44
  // Check against json schema is already done in src/main/options/validate
46
45
  // so here we can just concentrate on the io
47
- let lCruiseOptions = cloneDeep(pCruiseOptions);
46
+ let lCruiseOptions = structuredClone(pCruiseOptions);
48
47
  set(lCruiseOptions, "ruleSet.options.knownViolations", lKnownViolations);
49
48
  return lCruiseOptions;
50
49
  }
@@ -135,9 +135,10 @@ function buildExtensionsAttribute(pInitOptions) {
135
135
  * @returns {string}
136
136
  */
137
137
  function buildMainFieldsAttribute(pInitOptions) {
138
- return pInitOptions.usesTypeScript
139
- ? `mainFields: ["main", "types", "typings"],`
140
- : `// mainFields: ["main", "types", "typings"],`;
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
@@ -3,7 +3,6 @@ import { isAbsolute } from "node:path";
3
3
  import set from "lodash/set.js";
4
4
  import get from "lodash/get.js";
5
5
  import has from "lodash/has.js";
6
- import clone from "lodash/clone.js";
7
6
  import loadConfig from "../config-utl/extract-depcruise-config/index.mjs";
8
7
  import {
9
8
  RULES_FILE_NAME_SEARCH_ARRAY,
@@ -21,13 +20,13 @@ function getOptionValue(pDefault) {
21
20
  }
22
21
 
23
22
  function normalizeConfigFileName(pCliOptions, pConfigWrapperName, pDefault) {
24
- let lOptions = clone(pCliOptions);
23
+ let lOptions = structuredClone(pCliOptions);
25
24
 
26
25
  if (has(lOptions, pConfigWrapperName)) {
27
26
  set(
28
27
  lOptions,
29
28
  `ruleSet.options.${pConfigWrapperName}.fileName`,
30
- getOptionValue(pDefault)(lOptions[pConfigWrapperName])
29
+ getOptionValue(pDefault)(lOptions[pConfigWrapperName]),
31
30
  /* eslint security/detect-object-injection: 0 */
32
31
  );
33
32
  Reflect.deleteProperty(lOptions, pConfigWrapperName);
@@ -61,7 +60,7 @@ function validateAndGetCustomRulesFileName(pValidate) {
61
60
  throw new Error(
62
61
  `Can't open config file '${pValidate}' for reading. Does it exist?\n` +
63
62
  ` - You can create a config file by running 'npx dependency-cruiser --init'\n` +
64
- ` - If you intended to run without a config file use --no-config\n`
63
+ ` - If you intended to run without a config file use --no-config\n`,
65
64
  );
66
65
  }
67
66
  return lReturnValue;
@@ -74,7 +73,7 @@ function validateAndGetDefaultRulesFileName() {
74
73
  throw new TypeError(
75
74
  `Can't open a config file (.dependency-cruiser.(c)js) at the default location. Does it exist?\n` +
76
75
  ` - You can create one by running 'npx dependency-cruiser --init'\n` +
77
- ` - Want to run a without a config file? Use --no-config\n`
76
+ ` - Want to run a without a config file? Use --no-config\n`,
78
77
  );
79
78
  }
80
79
  return lReturnValue;
@@ -103,7 +102,7 @@ function validateAndGetKnownViolationsFileName(pKnownViolations) {
103
102
  } else {
104
103
  throw new Error(
105
104
  `Can't open '${lKnownViolationsFileName}' for reading. Does it exist?\n` +
106
- ` (You can create a .dependency-cruiser-known-violations.json with --output-type baseline)\n`
105
+ ` (You can create a .dependency-cruiser-known-violations.json with --output-type baseline)\n`,
107
106
  );
108
107
  }
109
108
  }
@@ -114,7 +113,7 @@ function normalizeKnownViolationsOption(pCliOptions) {
114
113
  }
115
114
  return {
116
115
  knownViolationsFile: validateAndGetKnownViolationsFileName(
117
- pCliOptions.ignoreKnown
116
+ pCliOptions.ignoreKnown,
118
117
  ),
119
118
  };
120
119
  }
@@ -129,7 +128,7 @@ async function normalizeValidationOption(pCliOptions) {
129
128
  return {
130
129
  rulesFile,
131
130
  ruleSet: await loadConfig(
132
- isAbsolute(rulesFile) ? rulesFile : `./${rulesFile}`
131
+ isAbsolute(rulesFile) ? rulesFile : `./${rulesFile}`,
133
132
  ),
134
133
  validate: true,
135
134
  };
@@ -157,7 +156,7 @@ function normalizeCacheStrategy(pCliOptions) {
157
156
  let lReturnValue = {};
158
157
 
159
158
  if (pCliOptions.cache && typeof pCliOptions.cache === "object") {
160
- lReturnValue.cache = clone(pCliOptions.cache);
159
+ lReturnValue.cache = structuredClone(pCliOptions.cache);
161
160
  lReturnValue.cache.strategy = lStrategy;
162
161
  } else {
163
162
  lReturnValue = {
@@ -227,5 +226,5 @@ export default async function normalizeOptions(pOptionsAsPassedFromCommander) {
227
226
  }
228
227
 
229
228
  export const determineRulesFileName = getOptionValue(
230
- OLD_DEFAULT_RULES_FILE_NAME
229
+ OLD_DEFAULT_RULES_FILE_NAME,
231
230
  );
@@ -1,5 +1,4 @@
1
1
  import { dirname } from "node:path";
2
- import cloneDeep from "lodash/cloneDeep.js";
3
2
  import has from "lodash/has.js";
4
3
  import { resolve } from "../../extract/resolve/resolve.mjs";
5
4
  import normalizeResolveOptions from "../../main/resolve-options/normalize.mjs";
@@ -8,7 +7,7 @@ import mergeConfigs from "./merge-configs.mjs";
8
7
 
9
8
  /* eslint no-use-before-define: 0 */
10
9
  async function processExtends(pReturnValue, pAlreadyVisited, pBaseDirectory) {
11
- let lReturnValue = cloneDeep(pReturnValue);
10
+ let lReturnValue = structuredClone(pReturnValue);
12
11
 
13
12
  if (typeof lReturnValue.extends === "string") {
14
13
  lReturnValue = mergeConfigs(
@@ -16,8 +15,8 @@ async function processExtends(pReturnValue, pAlreadyVisited, pBaseDirectory) {
16
15
  await extractDepcruiseConfig(
17
16
  lReturnValue.extends,
18
17
  pAlreadyVisited,
19
- pBaseDirectory
20
- )
18
+ pBaseDirectory,
19
+ ),
21
20
  );
22
21
  }
23
22
 
@@ -26,7 +25,7 @@ async function processExtends(pReturnValue, pAlreadyVisited, pBaseDirectory) {
26
25
  lReturnValue = mergeConfigs(
27
26
  lReturnValue,
28
27
  // eslint-disable-next-line no-await-in-loop
29
- await extractDepcruiseConfig(lExtends, pAlreadyVisited, pBaseDirectory)
28
+ await extractDepcruiseConfig(lExtends, pAlreadyVisited, pBaseDirectory),
30
29
  );
31
30
  }
32
31
  }
@@ -54,7 +53,7 @@ async function processExtends(pReturnValue, pAlreadyVisited, pBaseDirectory) {
54
53
  export default async function extractDepcruiseConfig(
55
54
  pConfigFileName,
56
55
  pAlreadyVisited = new Set(),
57
- pBaseDirectory = process.cwd()
56
+ pBaseDirectory = process.cwd(),
58
57
  ) {
59
58
  const lResolvedFileName = resolve(
60
59
  pConfigFileName,
@@ -63,17 +62,17 @@ export default async function extractDepcruiseConfig(
63
62
  {
64
63
  extensions: [".js", ".json", ".cjs", ".mjs"],
65
64
  },
66
- {}
65
+ {},
67
66
  ),
68
- "cli"
67
+ "cli",
69
68
  );
70
69
  const lBaseDirectory = dirname(lResolvedFileName);
71
70
 
72
71
  if (pAlreadyVisited.has(lResolvedFileName)) {
73
72
  throw new Error(
74
73
  `config is circular - ${[...pAlreadyVisited].join(
75
- " -> "
76
- )} -> ${lResolvedFileName}.\n`
74
+ " -> ",
75
+ )} -> ${lResolvedFileName}.\n`,
77
76
  );
78
77
  }
79
78
  pAlreadyVisited.add(lResolvedFileName);
@@ -84,7 +83,7 @@ export default async function extractDepcruiseConfig(
84
83
  lReturnValue = await processExtends(
85
84
  lReturnValue,
86
85
  pAlreadyVisited,
87
- lBaseDirectory
86
+ lBaseDirectory,
88
87
  );
89
88
  }
90
89
 
@@ -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 'fobidden' rules that extend the ...
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,5 +1,4 @@
1
1
  /* eslint-disable security/detect-object-injection, no-inline-comments */
2
- import cloneDeep from "lodash/cloneDeep.js";
3
2
  import has from "lodash/has.js";
4
3
  import matchers from "../../validate/matchers.mjs";
5
4
  import { extractGroups } from "../../utl/regex-util.mjs";
@@ -9,7 +8,7 @@ function getReachableRules(pRuleSet) {
9
8
  return (pRuleSet?.forbidden ?? [])
10
9
  .filter((pRule) => has(pRule.to, "reachable"))
11
10
  .concat(
12
- (pRuleSet?.allowed ?? []).filter((pRule) => has(pRule.to, "reachable"))
11
+ (pRuleSet?.allowed ?? []).filter((pRule) => has(pRule.to, "reachable")),
13
12
  );
14
13
  }
15
14
 
@@ -33,7 +32,7 @@ function isModuleInRuleTo(pRule, pModuleTo, pModuleFrom) {
33
32
  function mergeReachableProperties(pModule, pRule, pPath, pModuleFrom) {
34
33
  const lReachables = pModule.reachable || [];
35
34
  const lIndexExistingReachable = lReachables.findIndex(
36
- (pReachable) => pReachable.asDefinedInRule === pRule.name
35
+ (pReachable) => pReachable.asDefinedInRule === pRule.name,
37
36
  );
38
37
  const lIsReachable = pPath.length > 1;
39
38
 
@@ -53,7 +52,7 @@ function mergeReachableProperties(pModule, pRule, pPath, pModuleFrom) {
53
52
  function mergeReachesProperties(pFromModule, pToModule, pRule, pPath) {
54
53
  const lReaches = pFromModule.reaches || [];
55
54
  const lIndexExistingReachable = lReaches.findIndex(
56
- (pReachable) => pReachable.asDefinedInRule === pRule.name
55
+ (pReachable) => pReachable.asDefinedInRule === pRule.name,
57
56
  );
58
57
 
59
58
  if (lIndexExistingReachable > -1) {
@@ -84,7 +83,7 @@ function hasCapturingGroups(pRule) {
84
83
 
85
84
  return Boolean(
86
85
  (pRule?.to?.path ?? "").match(lCapturingGroupPlaceholderRe) ||
87
- (pRule?.to?.pathNot ?? "").match(lCapturingGroupPlaceholderRe)
86
+ (pRule?.to?.pathNot ?? "").match(lCapturingGroupPlaceholderRe),
88
87
  );
89
88
  }
90
89
  function shouldAddReachable(pRule, pModuleTo, pGraph) {
@@ -95,7 +94,7 @@ function shouldAddReachable(pRule, pModuleTo, pGraph) {
95
94
  const lModulesFrom = pGraph.filter(isModuleInRuleFrom(pRule));
96
95
 
97
96
  lReturnValue = lModulesFrom.some((pModuleFrom) =>
98
- isModuleInRuleTo(pRule, pModuleTo, pModuleFrom)
97
+ isModuleInRuleTo(pRule, pModuleTo, pModuleFrom),
99
98
  );
100
99
  } else {
101
100
  lReturnValue = isModuleInRuleTo(pRule, pModuleTo);
@@ -106,7 +105,7 @@ function shouldAddReachable(pRule, pModuleTo, pGraph) {
106
105
 
107
106
  function addReachesToModule(pModule, pGraph, pIndexedGraph, pReachableRule) {
108
107
  const lToModules = pGraph.filter((pToModule) =>
109
- isModuleInRuleTo(pReachableRule, pToModule, pModule)
108
+ isModuleInRuleTo(pReachableRule, pToModule, pModule),
110
109
  );
111
110
 
112
111
  for (let lToModule of lToModules) {
@@ -118,7 +117,7 @@ function addReachesToModule(pModule, pGraph, pIndexedGraph, pReachableRule) {
118
117
  pModule,
119
118
  lToModule,
120
119
  pReachableRule,
121
- lPath
120
+ lPath,
122
121
  );
123
122
  }
124
123
  }
@@ -143,7 +142,7 @@ function addReachableToModule(pModule, pGraph, pIndexedGraph, pReachableRule) {
143
142
  pModule,
144
143
  pReachableRule,
145
144
  lPath,
146
- lFromModule.source
145
+ lFromModule.source,
147
146
  );
148
147
  }
149
148
  }
@@ -152,14 +151,14 @@ function addReachableToModule(pModule, pGraph, pIndexedGraph, pReachableRule) {
152
151
 
153
152
  function addReachabilityToGraph(pGraph, pIndexedGraph, pReachableRule) {
154
153
  return pGraph.map((pModule) => {
155
- let lClonedModule = cloneDeep(pModule);
154
+ let lClonedModule = structuredClone(pModule);
156
155
 
157
156
  if (shouldAddReaches(pReachableRule, lClonedModule)) {
158
157
  lClonedModule = addReachesToModule(
159
158
  lClonedModule,
160
159
  pGraph,
161
160
  pIndexedGraph,
162
- pReachableRule
161
+ pReachableRule,
163
162
  );
164
163
  }
165
164
  if (shouldAddReachable(pReachableRule, lClonedModule, pGraph)) {
@@ -167,7 +166,7 @@ function addReachabilityToGraph(pGraph, pIndexedGraph, pReachableRule) {
167
166
  lClonedModule,
168
167
  pGraph,
169
168
  pIndexedGraph,
170
- pReachableRule
169
+ pReachableRule,
171
170
  );
172
171
  }
173
172
  return lClonedModule;
@@ -182,6 +181,6 @@ export default function deriveReachables(pGraph, pRuleSet) {
182
181
  return lReachableRules.reduce(
183
182
  (pReturnGraph, pRule) =>
184
183
  addReachabilityToGraph(pReturnGraph, lIndexedGraph, pRule),
185
- cloneDeep(pGraph)
184
+ structuredClone(pGraph),
186
185
  );
187
186
  }
@@ -1,9 +1,7 @@
1
- import clone from "lodash/clone.js";
2
-
3
1
  // the fixed name for allowed rules served a purpose during the extraction
4
2
  // process - but it's not necessary to reflect it in the output.
5
3
  function removeNames(pRule) {
6
- const lReturnValue = clone(pRule);
4
+ const lReturnValue = structuredClone(pRule);
7
5
 
8
6
  Reflect.deleteProperty(lReturnValue, "name");
9
7
  return lReturnValue;
@@ -19,6 +17,6 @@ export default function addRuleSetUsed(pOptions) {
19
17
  lForbidden ? { forbidden: lForbidden } : {},
20
18
  lAllowed ? { allowed: lAllowed.map(removeNames) } : {},
21
19
  lAllowedSeverity ? { allowedSeverity: lAllowedSeverity } : {},
22
- lRequired ? { required: lRequired } : {}
20
+ lRequired ? { required: lRequired } : {},
23
21
  );
24
22
  }
@@ -47,23 +47,21 @@ function gatherScannableFilesFromDirectory(pDirectoryName, pOptions) {
47
47
  .filter((pFullPathToFile) =>
48
48
  shouldNotBeExcluded(pathToPosix(pFullPathToFile), pOptions),
49
49
  )
50
- .reduce((pSum, pFullPathToFile) => {
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 pSum.concat(
58
- gatherScannableFilesFromDirectory(pFullPathToFile, pOptions),
59
- );
57
+ return gatherScannableFilesFromDirectory(pFullPathToFile, pOptions);
60
58
  }
61
59
  if (fileIsScannable(pOptions, pFullPathToFile)) {
62
- return pSum.concat(pFullPathToFile);
60
+ return pFullPathToFile;
63
61
  }
64
62
  }
65
- return pSum;
66
- }, [])
63
+ return [];
64
+ })
67
65
  .map((pFullPathToFile) => pathToPosix(pFullPathToFile))
68
66
  .filter((pFullPathToFile) => shouldBeIncluded(pFullPathToFile, pOptions));
69
67
  }
@@ -108,7 +106,7 @@ export default function gatherInitialSources(
108
106
  if (lScannedGlob.isGlob) {
109
107
  return expandGlob(lOptions.baseDir, lScannedGlob);
110
108
  }
111
- return pathToPosix(normalize(pFileDirectoryOrGlob));
109
+ return normalize(pFileDirectoryOrGlob);
112
110
  })
113
111
  .flatMap((pFileOrDirectory) => {
114
112
  if (statSync(join(lOptions.baseDir, pFileOrDirectory)).isDirectory()) {