dependency-cruiser 17.3.2 → 17.3.3-beta-2

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 (232) hide show
  1. package/bin/depcruise-baseline.mjs +43 -43
  2. package/bin/depcruise-fmt.mjs +89 -89
  3. package/bin/dependency-cruise.mjs +171 -171
  4. package/configs/plugins/3d-reporter-plugin.mjs +36 -36
  5. package/configs/plugins/stats-reporter-plugin.mjs +51 -51
  6. package/configs/recommended-strict.cjs +5 -5
  7. package/configs/recommended-warn-only.cjs +5 -5
  8. package/configs/recommended.cjs +22 -22
  9. package/configs/rules/no-circular.cjs +10 -10
  10. package/configs/rules/no-deprecated-core.cjs +10 -10
  11. package/configs/rules/no-duplicate-dependency-types.cjs +17 -17
  12. package/configs/rules/no-non-package-json.cjs +11 -11
  13. package/configs/rules/no-orphans.cjs +18 -18
  14. package/configs/rules/not-to-deprecated.cjs +10 -10
  15. package/configs/rules/not-to-unresolvable.cjs +10 -10
  16. package/package.json +170 -170
  17. package/src/cache/cache.mjs +139 -139
  18. package/src/cache/content-strategy.mjs +88 -88
  19. package/src/cache/find-content-changes.mjs +58 -58
  20. package/src/cache/helpers.mjs +52 -52
  21. package/src/cache/metadata-strategy.mjs +83 -83
  22. package/src/cache/options-compatible.mjs +56 -109
  23. package/src/cli/assert-node-environment-suitable.mjs +7 -7
  24. package/src/cli/defaults.mjs +5 -5
  25. package/src/cli/format-meta-info.mjs +22 -22
  26. package/src/cli/format.mjs +28 -28
  27. package/src/cli/index.mjs +145 -145
  28. package/src/cli/init-config/build-config.mjs +94 -94
  29. package/src/cli/init-config/environment-helpers.mjs +77 -77
  30. package/src/cli/init-config/find-extensions.mjs +27 -27
  31. package/src/cli/init-config/get-user-input.mjs +151 -151
  32. package/src/cli/init-config/index.mjs +88 -88
  33. package/src/cli/init-config/normalize-init-options.mjs +47 -47
  34. package/src/cli/init-config/utl.mjs +4 -4
  35. package/src/cli/init-config/validators.mjs +10 -10
  36. package/src/cli/init-config/write-config.mjs +21 -21
  37. package/src/cli/init-config/write-run-scripts-to-manifest.mjs +103 -107
  38. package/src/cli/listeners/cli-feedback.mjs +49 -49
  39. package/src/cli/listeners/ndjson.mjs +66 -66
  40. package/src/cli/listeners/performance-log/format-helpers.mjs +63 -63
  41. package/src/cli/listeners/performance-log/handlers.mjs +56 -56
  42. package/src/cli/listeners/performance-log/index.mjs +37 -37
  43. package/src/cli/normalize-cli-options.mjs +182 -182
  44. package/src/cli/tools/wrap-stream-in-html.mjs +37 -37
  45. package/src/cli/utl/assert-file-existence.mjs +7 -7
  46. package/src/cli/utl/io.mjs +28 -31
  47. package/src/config-utl/extract-babel-config.mjs +69 -69
  48. package/src/config-utl/extract-depcruise-config/index.mjs +54 -54
  49. package/src/config-utl/extract-depcruise-config/merge-configs.mjs +63 -63
  50. package/src/config-utl/extract-depcruise-config/read-config.mjs +9 -9
  51. package/src/config-utl/extract-depcruise-options.mjs +9 -9
  52. package/src/config-utl/extract-known-violations.mjs +49 -49
  53. package/src/config-utl/extract-ts-config.mjs +46 -48
  54. package/src/config-utl/extract-webpack-resolve-config.mjs +88 -88
  55. package/src/config-utl/make-absolute.mjs +5 -5
  56. package/src/enrich/add-validations.mjs +13 -13
  57. package/src/enrich/derive/circular.mjs +49 -49
  58. package/src/enrich/derive/dependents.mjs +27 -27
  59. package/src/enrich/derive/folders/aggregate-to-folders.mjs +104 -104
  60. package/src/enrich/derive/folders/index.mjs +19 -19
  61. package/src/enrich/derive/folders/utl.mjs +18 -18
  62. package/src/enrich/derive/metrics/get-module-metrics.mjs +27 -27
  63. package/src/enrich/derive/metrics/index.mjs +8 -8
  64. package/src/enrich/derive/module-utl.mjs +18 -18
  65. package/src/enrich/derive/orphan/index.mjs +18 -18
  66. package/src/enrich/derive/orphan/is-orphan.mjs +9 -9
  67. package/src/enrich/derive/reachable.mjs +165 -168
  68. package/src/enrich/enrich-modules.mjs +25 -25
  69. package/src/enrich/index.mjs +15 -15
  70. package/src/enrich/soften-known-violations.mjs +90 -90
  71. package/src/enrich/summarize/add-rule-set-used.mjs +13 -13
  72. package/src/enrich/summarize/get-stats.mjs +17 -17
  73. package/src/enrich/summarize/index.mjs +18 -18
  74. package/src/enrich/summarize/is-same-violation.mjs +30 -30
  75. package/src/enrich/summarize/summarize-folders.mjs +35 -35
  76. package/src/enrich/summarize/summarize-modules.mjs +97 -97
  77. package/src/enrich/summarize/summarize-options.mjs +71 -71
  78. package/src/extract/acorn/estree-helpers.mjs +66 -66
  79. package/src/extract/acorn/extract-amd-deps.mjs +63 -64
  80. package/src/extract/acorn/extract-cjs-deps.mjs +83 -83
  81. package/src/extract/acorn/extract-es6-deps.mjs +54 -54
  82. package/src/extract/acorn/extract-stats.mjs +4 -4
  83. package/src/extract/acorn/extract.mjs +28 -28
  84. package/src/extract/acorn/parse.mjs +37 -37
  85. package/src/extract/clear-caches.mjs +7 -7
  86. package/src/extract/extract-dependencies.mjs +109 -109
  87. package/src/extract/extract-stats.mjs +21 -21
  88. package/src/extract/gather-initial-sources.mjs +64 -64
  89. package/src/extract/helpers.mjs +73 -71
  90. package/src/extract/index.mjs +120 -120
  91. package/src/extract/resolve/determine-dependency-types.mjs +166 -169
  92. package/src/extract/resolve/external-module-helpers.mjs +76 -76
  93. package/src/extract/resolve/get-manifest.mjs +79 -79
  94. package/src/extract/resolve/index.mjs +175 -164
  95. package/src/extract/resolve/is-built-in.mjs +22 -24
  96. package/src/extract/resolve/merge-manifests.mjs +43 -43
  97. package/src/extract/resolve/module-classifiers.mjs +229 -229
  98. package/src/extract/resolve/resolve-amd.mjs +44 -44
  99. package/src/extract/resolve/resolve-cjs.mjs +40 -40
  100. package/src/extract/resolve/resolve-helpers.mjs +20 -20
  101. package/src/extract/resolve/resolve.mjs +26 -26
  102. package/src/extract/swc/dependency-visitor.mjs +211 -211
  103. package/src/extract/swc/extract-swc-deps.mjs +4 -4
  104. package/src/extract/swc/extract.mjs +7 -7
  105. package/src/extract/swc/parse.mjs +12 -12
  106. package/src/extract/transpile/babel-wrap.mjs +9 -9
  107. package/src/extract/transpile/coffeescript-wrap.mjs +21 -21
  108. package/src/extract/transpile/index.mjs +47 -47
  109. package/src/extract/transpile/javascript-wrap.mjs +6 -6
  110. package/src/extract/transpile/livescript-wrap.mjs +5 -5
  111. package/src/extract/transpile/meta.mjs +80 -80
  112. package/src/extract/transpile/svelte-preprocess.mjs +73 -73
  113. package/src/extract/transpile/svelte-wrap.mjs +19 -19
  114. package/src/extract/transpile/try-import-available.mjs +26 -27
  115. package/src/extract/transpile/typescript-wrap.mjs +39 -39
  116. package/src/extract/transpile/vue-template-wrap.cjs +43 -43
  117. package/src/extract/tsc/extract-stats.mjs +4 -4
  118. package/src/extract/tsc/extract-typescript-deps.mjs +429 -398
  119. package/src/extract/tsc/extract.mjs +22 -22
  120. package/src/extract/tsc/parse.mjs +21 -21
  121. package/src/graph-utl/add-focus.mjs +35 -35
  122. package/src/graph-utl/compare.mjs +24 -24
  123. package/src/graph-utl/consolidate-module-dependencies.mjs +35 -35
  124. package/src/graph-utl/consolidate-modules.mjs +33 -33
  125. package/src/graph-utl/consolidate-to-folder.mjs +13 -13
  126. package/src/graph-utl/consolidate-to-pattern.mjs +34 -34
  127. package/src/graph-utl/filter-bank.mjs +74 -69
  128. package/src/graph-utl/indexed-module-graph.mjs +227 -225
  129. package/src/graph-utl/match-facade.mjs +3 -3
  130. package/src/graph-utl/rule-set.mjs +20 -20
  131. package/src/graph-utl/strip-self-transitions.mjs +6 -6
  132. package/src/main/cruise.mjs +81 -81
  133. package/src/main/files-and-dirs/normalize.mjs +7 -7
  134. package/src/main/format.mjs +11 -14
  135. package/src/main/helpers.mjs +25 -25
  136. package/src/main/index.mjs +8 -8
  137. package/src/main/options/assert-validity.mjs +100 -100
  138. package/src/main/options/defaults.mjs +11 -11
  139. package/src/main/options/normalize.mjs +158 -160
  140. package/src/main/report-wrap.mjs +37 -37
  141. package/src/main/resolve-options/normalize.mjs +127 -128
  142. package/src/main/rule-set/assert-validity.mjs +67 -73
  143. package/src/main/rule-set/normalize.mjs +81 -79
  144. package/src/meta.cjs +15 -16
  145. package/src/report/anon/anonymize-path-element.mjs +20 -34
  146. package/src/report/anon/anonymize-path.mjs +11 -11
  147. package/src/report/anon/index.mjs +119 -119
  148. package/src/report/anon/random-string.mjs +23 -23
  149. package/src/report/azure-devops.mjs +75 -99
  150. package/src/report/baseline.mjs +9 -9
  151. package/src/report/csv.mjs +13 -13
  152. package/src/report/d2.mjs +105 -105
  153. package/src/report/dot/default-theme.mjs +152 -152
  154. package/src/report/dot/index.mjs +146 -146
  155. package/src/report/dot/module-utl.mjs +72 -72
  156. package/src/report/dot/prepare-custom-level.mjs +20 -20
  157. package/src/report/dot/prepare-flat-level.mjs +11 -11
  158. package/src/report/dot/prepare-folder-level.mjs +12 -13
  159. package/src/report/dot/theming.mjs +73 -73
  160. package/src/report/dot-webpage/dot-module.mjs +36 -36
  161. package/src/report/dot-webpage/svg-in-html-snippets/script.cjs +208 -210
  162. package/src/report/dot-webpage/svg-in-html-snippets/style.css +51 -51
  163. package/src/report/dot-webpage/wrap-in-html.mjs +7 -7
  164. package/src/report/error-html/index.mjs +49 -49
  165. package/src/report/error-html/utl.mjs +99 -99
  166. package/src/report/error-long.mjs +1 -1
  167. package/src/report/error.mjs +93 -93
  168. package/src/report/html/index.mjs +48 -48
  169. package/src/report/identity.mjs +4 -4
  170. package/src/report/index.mjs +33 -33
  171. package/src/report/json.mjs +4 -4
  172. package/src/report/markdown.mjs +120 -120
  173. package/src/report/mermaid.mjs +111 -111
  174. package/src/report/metrics.mjs +185 -185
  175. package/src/report/null.mjs +4 -4
  176. package/src/report/plugins.mjs +41 -41
  177. package/src/report/teamcity.mjs +150 -150
  178. package/src/report/text.mjs +42 -42
  179. package/src/report/utl/dependency-to-incidence-transformer.mjs +32 -32
  180. package/src/report/utl/index.mjs +53 -53
  181. package/src/schema/configuration.validate.mjs +1 -0
  182. package/src/schema/cruise-result.validate.mjs +1 -0
  183. package/src/schema/utl.mjs +6 -0
  184. package/src/utl/array-util.mjs +25 -25
  185. package/src/utl/bus.mjs +12 -12
  186. package/src/utl/extract-root-module-name.cjs +8 -8
  187. package/src/utl/find-all-files.mjs +54 -54
  188. package/src/utl/get-extension.mjs +2 -2
  189. package/src/utl/object-util.mjs +21 -22
  190. package/src/utl/path-to-posix.mjs +5 -5
  191. package/src/utl/regex-util.mjs +20 -20
  192. package/src/utl/try-import.mjs +42 -41
  193. package/src/utl/try-require.cjs +23 -23
  194. package/src/utl/wrap-and-indent.mjs +33 -33
  195. package/src/validate/index.mjs +65 -65
  196. package/src/validate/match-dependency-rule.mjs +47 -47
  197. package/src/validate/match-folder-dependency-rule.mjs +27 -27
  198. package/src/validate/match-module-rule-helpers.mjs +76 -76
  199. package/src/validate/match-module-rule.mjs +12 -12
  200. package/src/validate/matchers.mjs +162 -162
  201. package/src/validate/rule-classifiers.mjs +9 -9
  202. package/src/validate/violates-required-rule.mjs +23 -23
  203. package/types/cache-options.d.mts +27 -27
  204. package/types/config-utl/extract-babel-config.d.mts +1 -1
  205. package/types/config-utl/extract-depcruise-config.d.mts +3 -3
  206. package/types/config-utl/extract-depcruise-options.d.mts +1 -1
  207. package/types/config-utl/extract-ts-config.d.mts +1 -1
  208. package/types/config-utl/extract-webpack-resolve-config.d.mts +3 -3
  209. package/types/configuration.d.mts +10 -10
  210. package/types/cruise-result.d.mts +414 -414
  211. package/types/dependency-cruiser.d.mts +52 -52
  212. package/types/filter-types.d.mts +45 -45
  213. package/types/options.d.mts +430 -430
  214. package/types/plugins/3d-reporter-plugin.d.mts +9 -9
  215. package/types/plugins/mermaid-reporter-plugin.d.mts +10 -10
  216. package/types/plugins/stats-reporter-plugin.d.mts +9 -9
  217. package/types/reporter-options.d.mts +196 -196
  218. package/types/resolve-options.d.mts +23 -23
  219. package/types/restrictions.d.mts +174 -174
  220. package/types/rule-set.d.mts +132 -132
  221. package/types/rule-summary.d.mts +14 -14
  222. package/types/shared-types.d.mts +89 -89
  223. package/types/strict-filter-types.d.mts +52 -52
  224. package/types/strict-options.d.mts +34 -34
  225. package/types/strict-restrictions.d.mts +25 -25
  226. package/types/strict-rule-set.d.mts +36 -36
  227. package/types/violations.d.mts +40 -40
  228. package/src/schema/README.md +0 -5
  229. package/src/schema/baseline-violations.schema.mjs +0 -1
  230. package/src/schema/configuration.schema.mjs +0 -1
  231. package/src/schema/cruise-result.schema.mjs +0 -1
  232. package/types/README.md +0 -1
@@ -17,34 +17,34 @@ import stripSelfTransitions from "#graph-utl/strip-self-transitions.mjs";
17
17
  * @returns {ICruiseResult}
18
18
  */
19
19
  function reSummarizeResults(pResult, pFormatOptions) {
20
- let lModules = applyFilters(pResult.modules, pFormatOptions);
20
+ let lModules = applyFilters(pResult.modules, pFormatOptions);
21
21
 
22
- if (Object.hasOwn(pFormatOptions, "collapse")) {
23
- lModules = consolidateToPattern(lModules, pFormatOptions.collapse)
24
- .sort(compareModules)
25
- .map(stripSelfTransitions);
26
- }
27
- return {
28
- ...pResult,
29
- summary: {
30
- ...pResult.summary,
31
- ...summarize(
32
- lModules,
33
- {
34
- ...pResult.summary.optionsUsed,
35
- ...pFormatOptions,
36
- },
37
- (pResult.summary.optionsUsed.args || "").split(" "),
38
- // TODO: apply filters to the folders too
39
- pResult.folders,
40
- ),
41
- },
42
- modules: lModules,
43
- };
22
+ if (Object.hasOwn(pFormatOptions, "collapse")) {
23
+ lModules = consolidateToPattern(lModules, pFormatOptions.collapse)
24
+ .sort(compareModules)
25
+ .map(stripSelfTransitions);
26
+ }
27
+ return {
28
+ ...pResult,
29
+ summary: {
30
+ ...pResult.summary,
31
+ ...summarize(
32
+ lModules,
33
+ {
34
+ ...pResult.summary.optionsUsed,
35
+ ...pFormatOptions,
36
+ },
37
+ (pResult.summary.optionsUsed.args || "").split(" "),
38
+ // TODO: apply filters to the folders too
39
+ pResult.folders,
40
+ ),
41
+ },
42
+ modules: lModules,
43
+ };
44
44
  }
45
45
 
46
46
  function getReporterSection(pOutputType) {
47
- return pOutputType === "x-dot-webpage" ? "dot" : pOutputType;
47
+ return pOutputType === "x-dot-webpage" ? "dot" : pOutputType;
48
48
  }
49
49
 
50
50
  /**
@@ -54,18 +54,18 @@ function getReporterSection(pOutputType) {
54
54
  * @returns {IReporterOutput}
55
55
  */
56
56
  export default async function reportWrap(pResult, pFormatOptions) {
57
- const lReportFunction = await getReporter(pFormatOptions.outputType);
58
- const lReportOptions =
59
- pResult.summary.optionsUsed?.reporterOptions?.[
60
- getReporterSection(pFormatOptions.outputType)
61
- ] ?? {};
57
+ const lReportFunction = await getReporter(pFormatOptions.outputType);
58
+ const lReportOptions =
59
+ pResult.summary.optionsUsed?.reporterOptions?.[
60
+ getReporterSection(pFormatOptions.outputType)
61
+ ] ?? {};
62
62
 
63
- return lReportFunction(
64
- reSummarizeResults(pResult, pFormatOptions),
65
- // passing format options here so reporters that read collapse patterns
66
- // from the result take the one passed in the format options instead
67
- Object.hasOwn(pFormatOptions, "collapse")
68
- ? { ...lReportOptions, collapsePattern: pFormatOptions.collapse }
69
- : lReportOptions,
70
- );
63
+ return lReportFunction(
64
+ reSummarizeResults(pResult, pFormatOptions),
65
+ // passing format options here so reporters that read collapse patterns
66
+ // from the result take the one passed in the format options instead
67
+ Object.hasOwn(pFormatOptions, "collapse")
68
+ ? { ...lReportOptions, collapsePattern: pFormatOptions.collapse }
69
+ : lReportOptions,
70
+ );
71
71
  }
@@ -2,8 +2,8 @@ import fs from "node:fs";
2
2
  import enhancedResolve from "enhanced-resolve";
3
3
  import { scannableExtensions } from "#extract/transpile/meta.mjs";
4
4
  import {
5
- ruleSetHasDeprecationRule,
6
- ruleSetHasLicenseRule,
5
+ ruleSetHasDeprecationRule,
6
+ ruleSetHasLicenseRule,
7
7
  } from "#graph-utl/rule-set.mjs";
8
8
 
9
9
  /**
@@ -14,33 +14,32 @@ import {
14
14
  const DEFAULT_CACHE_DURATION = 4000;
15
15
  /** @type {Partial<IResolveOptions>} */
16
16
  const DEFAULT_RESOLVE_OPTIONS = {
17
- symlinks: true,
18
- // if a webpack config overrides extensions, there's probably
19
- // good cause. The scannableExtensions are an educated guess
20
- // anyway, that works well in most circumstances.
21
- // Note that if extract/transpile/index gets an unknown extension
22
- // passed, it'll fall back to the javascript parser
23
- extensions: scannableExtensions,
24
- // for typescript projects that import stuff that's only in
25
- // node_modules/@types we need:
26
- // - the inclusion of .d.ts to the extensions (see above)
27
- // - an explicit inclusion of node_modules/@types to the spots
28
- // to look for modules (in addition to "node_modules" which
29
- // is the default for enhanced-resolve)
30
- modules: ["node_modules", "node_modules/@types"],
31
- // this overrides the default exports fields enhanced-resolve uses
32
- // (being ["exports"]) to keep backwards compatibility between enhanced-resolve
33
- // 4 and 5 (4 didn't heed them at all and the empty array has the same
34
- // effect).
35
- // Also see https://github.com/sverweij/dependency-cruiser/issues/338
36
- exportsFields: [],
17
+ symlinks: true,
18
+ // if a webpack config overrides extensions, there's probably
19
+ // good cause. The scannableExtensions are an educated guess
20
+ // anyway.Note: if extract/transpile/index gets an unknown extension
21
+ // it'll fall back to the javascript parser
22
+ extensions: scannableExtensions,
23
+ // for typescript projects that import stuff that's only in
24
+ // node_modules/@types we need:
25
+ // - the inclusion of .d.ts to the extensions (see above)
26
+ // - an explicit inclusion of node_modules/@types to the spots
27
+ // to look for modules (in addition to "node_modules" which
28
+ // is the default for enhanced-resolve)
29
+ modules: ["node_modules", "node_modules/@types"],
30
+ // this overrides the default exports fields enhanced-resolve uses
31
+ // (being ["exports"]) to keep backwards compatibility between enhanced-resolve
32
+ // 4 and 5 (4 didn't heed them at all and the empty array has the same
33
+ // effect).
34
+ // Also see https://github.com/sverweij/dependency-cruiser/issues/338
35
+ exportsFields: [],
37
36
  };
38
37
 
39
38
  function omit(pObject, pProperty) {
40
- const lObject = structuredClone(pObject);
41
- // eslint-disable-next-line security/detect-object-injection
42
- delete lObject[pProperty];
43
- return lObject;
39
+ const lObject = structuredClone(pObject);
40
+ // eslint-disable-next-line security/detect-object-injection
41
+ delete lObject[pProperty];
42
+ return lObject;
44
43
  }
45
44
 
46
45
  /**
@@ -49,89 +48,89 @@ function omit(pObject, pProperty) {
49
48
  * @returns {Partial<IResolveOptions>}
50
49
  */
51
50
  function getNonOverridableResolveOptions(pCacheDuration) {
52
- return {
53
- // This should cover most of the bases of dependency-cruiser's
54
- // uses. Not overridable for now because for other
55
- // file systems it's not sure we can use sync system calls
56
- // Also: passing a non-cached filesystem makes performance
57
- // worse.
58
- fileSystem: new enhancedResolve.CachedInputFileSystem(fs, pCacheDuration),
59
- // our code depends on sync behavior, so having this
60
- // overridden is not an option
61
- useSyncFileSystemCalls: true,
62
- };
51
+ return {
52
+ // This should cover most of the bases of dependency-cruiser's
53
+ // uses. Not overridable for now because for other
54
+ // file systems it's not sure we can use sync system calls
55
+ // Also: passing a non-cached filesystem makes performance
56
+ // worse.
57
+ fileSystem: new enhancedResolve.CachedInputFileSystem(fs, pCacheDuration),
58
+ // our code depends on sync behavior, so having this
59
+ // overridden is not an option
60
+ useSyncFileSystemCalls: true,
61
+ };
63
62
  }
64
63
 
65
64
  function pushPlugin(pPlugins, pPluginToPush) {
66
- return (pPlugins || []).concat(pPluginToPush);
65
+ return (pPlugins || []).concat(pPluginToPush);
67
66
  }
68
67
 
69
68
  // eslint-disable-next-line max-lines-per-function
70
69
  async function compileResolveOptions(
71
- pResolveOptions,
72
- pTSConfig,
73
- pResolveOptionsFromDCConfig,
70
+ pResolveOptions,
71
+ pTSConfig,
72
+ pResolveOptionsFromDCConfig,
74
73
  ) {
75
- let lResolveOptions = {};
74
+ let lResolveOptions = {};
76
75
 
77
- // There's a performance impact of ~1 ms per resolve even when there
78
- // are 0 paths in the tsconfig, so not loading it when not necessary
79
- // will be a win.
80
- // Also: requiring the plugin only when it's necessary will save some
81
- // startup time (especially on a cold require cache)
82
- if (pResolveOptions.tsConfig) {
83
- const { default: TsConfigPathsPlugin } =
84
- await import("tsconfig-paths-webpack-plugin");
85
- lResolveOptions.plugins = pushPlugin(
86
- lResolveOptions.plugins,
87
- // @ts-expect-error TS2351 "TsConfPathsPlugin is not constructable" - is unjustified
88
- new TsConfigPathsPlugin({
89
- configFile: pResolveOptions.tsConfig,
90
- // TsConfigPathsPlugin requires a baseUrl to be present in the tsconfig,
91
- // otherwise it prints scary messages that it didn't and read the tsConfig
92
- // (potentially making users think it's dependency-cruiser disregarding the
93
- // tsconfig). Hence up till version 13.0.4 dependency-cruiser only loaded
94
- // TsConfigPathsPlugin when an options.baseUrl existed. However, this
95
- // isn't necessary anymore:
96
- // - [tsconfig#baseUrl documentation](https://www.typescriptlang.org/tsconfig#baseUrl)
97
- // UNrecommends the use of the baseUrl for non-AMD projects
98
- // - [tsconfig-paths PR #207](https://github.com/dividab/tsconfig-paths/pull/208)
99
- // 'tolerates' undefined baseUrls
100
- //
101
- // Hence, until
102
- // [tpwp issue #99](https://github.com/dividab/tsconfig-paths-webpack-plugin/issues/99)
103
- // lands:
104
- // - pass a default baseUrl to TsConfigPathsPlugin if the baseUrl isn't available
105
- // - pass undefined in all other cases; TsConfigPathsPlugin will read
106
- // it from the tsconfig.json in that case. Passing the processed baseUrl
107
- // (pTSConfig?.options?.baseUrl) instead would've been more obvious, but
108
- // doesn't work, as that is an absolute path and tsconfig-paths(-wpp)
109
- // seems to process that again resulting in invalid paths and unresolved
110
- // or erroneous dependencies
111
- // eslint-disable-next-line no-undefined
112
- baseUrl: pTSConfig?.options?.baseUrl ? undefined : "./",
113
- // TsConfigPathsPlugin doesn't (can't) read enhanced-resolve's
114
- // list of extensions, and the default it uses for extensions
115
- // so we do it ourselves - either with the extensions passed
116
- // or with the supported ones.
117
- extensions:
118
- pResolveOptionsFromDCConfig.extensions ||
119
- pResolveOptions.extensions ||
120
- DEFAULT_RESOLVE_OPTIONS.extensions,
121
- }),
122
- );
123
- }
76
+ // There's a performance impact of ~1 ms per resolve even when there
77
+ // are 0 paths in the tsconfig, so not loading it when not necessary
78
+ // will be a win.
79
+ // Also: requiring the plugin only when it's necessary will save some
80
+ // startup time (especially on a cold require cache)
81
+ if (pResolveOptions.tsConfig) {
82
+ const { default: TsConfigPathsPlugin } =
83
+ await import("tsconfig-paths-webpack-plugin");
84
+ lResolveOptions.plugins = pushPlugin(
85
+ lResolveOptions.plugins,
86
+ // @ts-expect-error TS2351 "TsConfPathsPlugin is not constructable" - is unjustified
87
+ new TsConfigPathsPlugin({
88
+ configFile: pResolveOptions.tsConfig,
89
+ // TsConfigPathsPlugin requires a baseUrl to be present in the tsconfig,
90
+ // otherwise it prints scary messages that it didn't and read the tsConfig
91
+ // (potentially making users think it's dependency-cruiser disregarding the
92
+ // tsconfig). Hence up till version 13.0.4 dependency-cruiser only loaded
93
+ // TsConfigPathsPlugin when an options.baseUrl existed. However, this
94
+ // isn't necessary anymore:
95
+ // - [tsconfig#baseUrl documentation](https://www.typescriptlang.org/tsconfig#baseUrl)
96
+ // UNrecommends the use of the baseUrl for non-AMD projects
97
+ // - [tsconfig-paths PR #207](https://github.com/dividab/tsconfig-paths/pull/208)
98
+ // 'tolerates' undefined baseUrls
99
+ //
100
+ // Hence, until
101
+ // [tpwp issue #99](https://github.com/dividab/tsconfig-paths-webpack-plugin/issues/99)
102
+ // lands:
103
+ // - pass a default baseUrl to TsConfigPathsPlugin if the baseUrl isn't available
104
+ // - pass undefined in all other cases; TsConfigPathsPlugin will read
105
+ // it from the tsconfig.json in that case. Passing the processed baseUrl
106
+ // (pTSConfig?.options?.baseUrl) instead would've been more obvious, but
107
+ // doesn't work, as that is an absolute path and tsconfig-paths(-wpp)
108
+ // seems to process that again resulting in invalid paths and unresolved
109
+ // or erroneous dependencies
110
+ // eslint-disable-next-line no-undefined
111
+ baseUrl: pTSConfig?.options?.baseUrl ? undefined : "./",
112
+ // TsConfigPathsPlugin doesn't (can't) read enhanced-resolve's
113
+ // list of extensions, and the default it uses for extensions
114
+ // so we do it ourselves - either with the extensions passed
115
+ // or with the supported ones.
116
+ extensions:
117
+ pResolveOptionsFromDCConfig.extensions ||
118
+ pResolveOptions.extensions ||
119
+ DEFAULT_RESOLVE_OPTIONS.extensions,
120
+ }),
121
+ );
122
+ }
124
123
 
125
- return {
126
- ...DEFAULT_RESOLVE_OPTIONS,
127
- ...lResolveOptions,
128
- ...omit(pResolveOptionsFromDCConfig, "cachedInputFileSystem"),
129
- ...pResolveOptions,
130
- ...getNonOverridableResolveOptions(
131
- pResolveOptionsFromDCConfig?.cachedInputFileSystem?.cacheDuration ??
132
- DEFAULT_CACHE_DURATION,
133
- ),
134
- };
124
+ return {
125
+ ...DEFAULT_RESOLVE_OPTIONS,
126
+ ...lResolveOptions,
127
+ ...omit(pResolveOptionsFromDCConfig, "cachedInputFileSystem"),
128
+ ...pResolveOptions,
129
+ ...getNonOverridableResolveOptions(
130
+ pResolveOptionsFromDCConfig?.cachedInputFileSystem?.cacheDuration ??
131
+ DEFAULT_CACHE_DURATION,
132
+ ),
133
+ };
135
134
  }
136
135
 
137
136
  /**
@@ -142,40 +141,40 @@ async function compileResolveOptions(
142
141
  */
143
142
  // eslint-disable-next-line complexity
144
143
  export default async function normalizeResolveOptions(
145
- pResolveOptions,
146
- pOptions,
147
- pTSConfig,
144
+ pResolveOptions,
145
+ pOptions,
146
+ pTSConfig,
148
147
  ) {
149
- const lRuleSet = pOptions?.ruleSet ?? {};
148
+ const lRuleSet = pOptions?.ruleSet ?? {};
150
149
 
151
- return await compileResolveOptions(
152
- {
153
- // EnhancedResolve's symlinks:
154
- // - true => symlinks are followed (vv)
155
- // node's --preserve-symlinks:
156
- // - true => symlinks are NOT followed (vv)
157
- // => symlinks = !preserveSymlinks
158
- symlinks: !pOptions?.preserveSymlinks,
159
- tsConfig:
160
- pOptions?.tsConfig?.fileName ??
161
- pOptions?.ruleSet?.options?.tsConfig?.fileName ??
162
- null,
150
+ return await compileResolveOptions(
151
+ {
152
+ // EnhancedResolve's symlinks:
153
+ // - true => symlinks are followed (vv)
154
+ // node's --preserve-symlinks:
155
+ // - true => symlinks are NOT followed (vv)
156
+ // => symlinks = !preserveSymlinks
157
+ symlinks: !pOptions?.preserveSymlinks,
158
+ tsConfig:
159
+ pOptions?.tsConfig?.fileName ??
160
+ pOptions?.ruleSet?.options?.tsConfig?.fileName ??
161
+ null,
163
162
 
164
- /* squirrel the externalModuleResolutionStrategy and combinedDependencies
163
+ /* squirrel the externalModuleResolutionStrategy and combinedDependencies
165
164
  thing into the resolve options
166
165
  - they're not for enhanced resolve, but they are for what we consider
167
166
  resolve options ...
168
167
  */
169
- combinedDependencies: pOptions?.combinedDependencies ?? false,
170
- /* Same for the builtInModules override/ add option ...*/
171
- ...(pOptions?.builtInModules?.override || pOptions?.builtInModules?.add
172
- ? { builtInModules: pOptions?.builtInModules }
173
- : {}),
174
- resolveLicenses: ruleSetHasLicenseRule(lRuleSet),
175
- resolveDeprecations: ruleSetHasDeprecationRule(lRuleSet),
176
- ...pResolveOptions,
177
- },
178
- pTSConfig || {},
179
- pOptions?.enhancedResolveOptions ?? {},
180
- );
168
+ combinedDependencies: pOptions?.combinedDependencies ?? false,
169
+ /* Same for the builtInModules override/ add option ...*/
170
+ ...(pOptions?.builtInModules?.override || pOptions?.builtInModules?.add
171
+ ? { builtInModules: pOptions?.builtInModules }
172
+ : {}),
173
+ resolveLicenses: ruleSetHasLicenseRule(lRuleSet),
174
+ resolveDeprecations: ruleSetHasDeprecationRule(lRuleSet),
175
+ ...pResolveOptions,
176
+ },
177
+ pTSConfig || {},
178
+ pOptions?.enhancedResolveOptions ?? {},
179
+ );
181
180
  }
@@ -1,105 +1,99 @@
1
- import Ajv from "ajv";
2
1
  import safeRegex from "safe-regex";
3
2
  import { assertCruiseOptionsValid } from "../options/assert-validity.mjs";
4
3
  import { normalizeToREAsString } from "../helpers.mjs";
5
- import configurationSchema from "#configuration-schema";
4
+ import { bus } from "#utl/bus.mjs";
6
5
  import { has, get } from "#utl/object-util.mjs";
6
+ import validateConfigurationSchema from "#schema/configuration.validate.mjs";
7
+ import { validateErrorsToString } from "#schema/utl.mjs";
8
+
7
9
  /**
8
10
  * @import { IConfiguration } from "../../../types/configuration.mjs";
9
11
  */
10
12
 
11
- const ajv = new Ajv();
12
- // the default for this is 25 - as noted in the safe-regex source code already,
13
- // the repeat limit is not the best of heuristics for indicating exponential time
14
- // regular expressions - and it leads to false positives. E.g. if you use rules
15
- // 'generated' from rules it could be the generated 'from' or 'to' have a list
16
- // of file patterns that's easily > 25 of length. It's currently not possible
17
- // to disable this check in safe-regex (e.g. by setting it to an odd value like
18
- // 0 or -1, or by passing a 'switch this thing off please' option), so the only
19
- // option is to increase the repeat limit to something fairly high.
20
- //
21
- // This does _not_ influence the star height algorithm, which is the main value
22
- // of the safe-regex package.
13
+ // Bump safe-regex repeat limit to 10000 to avoid false positives
14
+ // for long pattern lists. This does not affect the star-height safety check.
23
15
  const MAX_SAFE_REGEX_STAR_REPEAT_LIMIT = 10000;
24
16
 
25
- function assertSchemaCompliance(pSchema, pConfiguration) {
26
- if (!ajv.validate(pSchema, pConfiguration)) {
27
- throw new Error(
28
- `The supplied configuration is not valid: ${ajv.errorsText()}.\n`,
29
- );
30
- }
17
+ function assertSchemaCompliance(pConfiguration) {
18
+ if (!validateConfigurationSchema(pConfiguration)) {
19
+ throw new Error(
20
+ `The supplied configuration is not valid: ${validateErrorsToString(validateConfigurationSchema.errors)}.\n`,
21
+ );
22
+ }
31
23
  }
32
24
 
33
25
  function hasPath(pObject, pSection, pCondition) {
34
- // pCondition can be nested properties, so we use a bespoke
35
- // 'has' function instead of simple elvis operators
36
- return has(pObject, pSection) && has(pObject[pSection], pCondition);
26
+ // pCondition can be nested properties, so we use a bespoke
27
+ // 'has' function instead of simple elvis operators
28
+ return has(pObject, pSection) && has(pObject[pSection], pCondition);
37
29
  }
38
30
 
39
31
  function safeRule(pRule, pSection, pCondition) {
40
- return (
41
- !hasPath(pRule, pSection, pCondition) ||
42
- safeRegex(normalizeToREAsString(get(pRule[pSection], pCondition)), {
43
- limit: MAX_SAFE_REGEX_STAR_REPEAT_LIMIT,
44
- })
45
- );
32
+ if (hasPath(pRule, pSection, pCondition)) {
33
+ return safeRegex(normalizeToREAsString(get(pRule[pSection], pCondition)), {
34
+ limit: MAX_SAFE_REGEX_STAR_REPEAT_LIMIT,
35
+ });
36
+ }
37
+ return true;
46
38
  }
47
39
 
48
40
  function assertRuleSafety(pRule) {
49
- const lRegexConditions = [
50
- { section: "from", condition: "path" },
51
- { section: "to", condition: "path" },
52
- { section: "from", condition: "pathNot" },
53
- { section: "to", condition: "pathNot" },
54
- { section: "to", condition: "license" },
55
- { section: "to", condition: "licenseNot" },
56
- { section: "to", condition: "via" },
57
- { section: "to", condition: "via.path" },
58
- { section: "to", condition: "viaNot" },
59
- { section: "to", condition: "viaNot.path" },
60
- { section: "to", condition: "viaOnly" },
61
- { section: "to", condition: "viaOnly.path" },
62
- { section: "to", condition: "viaSomeNot" },
63
- { section: "to", condition: "viaSomeNot.path" },
64
- ];
41
+ const lRegexConditions = [
42
+ { section: "from", condition: "path" },
43
+ { section: "to", condition: "path" },
44
+ { section: "from", condition: "pathNot" },
45
+ { section: "to", condition: "pathNot" },
46
+ { section: "to", condition: "license" },
47
+ { section: "to", condition: "licenseNot" },
48
+ { section: "to", condition: "via" },
49
+ { section: "to", condition: "via.path" },
50
+ { section: "to", condition: "viaNot" },
51
+ { section: "to", condition: "viaNot.path" },
52
+ { section: "to", condition: "viaOnly" },
53
+ { section: "to", condition: "viaOnly.path" },
54
+ { section: "to", condition: "viaSomeNot" },
55
+ { section: "to", condition: "viaSomeNot.path" },
56
+ ];
65
57
 
66
- if (
67
- lRegexConditions.some(
68
- (pCondition) =>
69
- !safeRule(pRule, pCondition.section, pCondition.condition),
70
- )
71
- ) {
72
- throw new Error(
73
- `rule ${JSON.stringify(
74
- pRule,
75
- null,
76
- "",
77
- )} has an unsafe regular expression. Bailing out.\n`,
78
- );
79
- }
58
+ if (
59
+ lRegexConditions.some(
60
+ (pCondition) =>
61
+ !safeRule(pRule, pCondition.section, pCondition.condition),
62
+ )
63
+ ) {
64
+ throw new Error(
65
+ `rule ${JSON.stringify(
66
+ pRule,
67
+ null,
68
+ "",
69
+ )} has an unsafe regular expression. Bailing out.\n`,
70
+ );
71
+ }
80
72
  }
81
73
 
82
74
  /**
83
75
  * Returns the passed configuration pConfiguration when it is valid.
84
76
  * Throws an Error in all other cases.
85
77
  *
86
- * Validations:
87
- * - the rule set adheres to the [config json schema](../../schema/configuration.schema.json)
88
- * - any regular expression in the rule set is 'safe' (~= won't be too slow)
89
- *
90
78
  * @param {IConfiguration} pConfiguration The configuration to validate
91
- * @return {IConfiguration} The configuration as passed
92
- * @throws {Error} An error with the reason for the error as
93
- * a message
79
+ * @return {IConfiguration} The configuration as passed
80
+ * @throws {Error} An error with the reason for the error as a message
94
81
  */
95
82
  export default function assertRuleSetValid(pConfiguration) {
96
- assertSchemaCompliance(configurationSchema, pConfiguration);
97
- (pConfiguration.allowed || []).forEach(assertRuleSafety);
98
- (pConfiguration.forbidden || []).forEach(assertRuleSafety);
99
- if (pConfiguration?.options) {
100
- assertCruiseOptionsValid(pConfiguration.options);
101
- }
102
- return pConfiguration;
83
+ bus.info("parse rule set: validate");
84
+
85
+ bus.debug("parse rule set: validate: schema compliance");
86
+ assertSchemaCompliance(pConfiguration);
87
+
88
+ bus.debug("parse rule set: validate: rule safety");
89
+ (pConfiguration.allowed || []).forEach(assertRuleSafety);
90
+ (pConfiguration.forbidden || []).forEach(assertRuleSafety);
91
+
92
+ bus.debug("parse rule set: validate: cruise options validity");
93
+ if (pConfiguration?.options) {
94
+ assertCruiseOptionsValid(pConfiguration.options);
95
+ }
96
+ return pConfiguration;
103
97
  }
104
98
 
105
99
  /* think we can ignore object injection here because it's not a public function */