dependency-cruiser 17.3.5 → 17.3.7

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 (46) hide show
  1. package/LICENSE +1 -1
  2. package/package.json +6 -4
  3. package/src/{enrich/enrich-modules.mjs → analyze/analyze-modules.mjs} +1 -1
  4. package/src/{enrich → analyze}/derive/dependents.mjs +14 -3
  5. package/src/{enrich → analyze}/index.mjs +3 -3
  6. package/src/cache/cache.mjs +9 -27
  7. package/src/cache/content-strategy.mjs +1 -1
  8. package/src/cache/helpers.mjs +16 -6
  9. package/src/cli/init-config/config-template.mjs +112 -145
  10. package/src/cli/init-config/find-extensions.mjs +4 -0
  11. package/src/cli/listeners/ndjson.mjs +16 -1
  12. package/src/config-utl/extract-depcruise-config/merge-configs.mjs +2 -2
  13. package/src/extract/acorn/parse.mjs +18 -25
  14. package/src/extract/resolve/external-module-helpers.mjs +9 -7
  15. package/src/extract/resolve/get-manifest.mjs +25 -13
  16. package/src/extract/resolve/resolve-amd.mjs +10 -5
  17. package/src/extract/resolve/resolve.mjs +4 -5
  18. package/src/extract/swc/parse.mjs +12 -8
  19. package/src/extract/tsc/parse.mjs +12 -15
  20. package/src/main/cruise.mjs +6 -6
  21. package/src/main/report-wrap.mjs +1 -1
  22. package/src/meta.cjs +1 -1
  23. package/src/report/anon/anonymize-path-element.mjs +11 -3
  24. package/src/report/dot/prepare-flat-level.mjs +12 -2
  25. package/src/report/plugins.mjs +1 -1
  26. package/src/report/teamcity.mjs +76 -58
  27. package/src/report/text.mjs +7 -7
  28. /package/src/{enrich → analyze}/add-validations.mjs +0 -0
  29. /package/src/{enrich → analyze}/derive/circular.mjs +0 -0
  30. /package/src/{enrich → analyze}/derive/folders/aggregate-to-folders.mjs +0 -0
  31. /package/src/{enrich → analyze}/derive/folders/index.mjs +0 -0
  32. /package/src/{enrich → analyze}/derive/folders/utl.mjs +0 -0
  33. /package/src/{enrich → analyze}/derive/metrics/get-module-metrics.mjs +0 -0
  34. /package/src/{enrich → analyze}/derive/metrics/index.mjs +0 -0
  35. /package/src/{enrich → analyze}/derive/module-utl.mjs +0 -0
  36. /package/src/{enrich → analyze}/derive/orphan/index.mjs +0 -0
  37. /package/src/{enrich → analyze}/derive/orphan/is-orphan.mjs +0 -0
  38. /package/src/{enrich → analyze}/derive/reachable.mjs +0 -0
  39. /package/src/{enrich → analyze}/soften-known-violations.mjs +0 -0
  40. /package/src/{enrich → analyze}/summarize/add-rule-set-used.mjs +0 -0
  41. /package/src/{enrich → analyze}/summarize/get-stats.mjs +0 -0
  42. /package/src/{enrich → analyze}/summarize/index.mjs +0 -0
  43. /package/src/{enrich → analyze}/summarize/is-same-violation.mjs +0 -0
  44. /package/src/{enrich → analyze}/summarize/summarize-folders.mjs +0 -0
  45. /package/src/{enrich → analyze}/summarize/summarize-modules.mjs +0 -0
  46. /package/src/{enrich → analyze}/summarize/summarize-options.mjs +0 -0
@@ -1,7 +1,14 @@
1
1
  import { randomInt } from "node:crypto";
2
- import memoize, { memoizeClear } from "memoize";
3
-
4
2
  import { formatPercentage, formatViolation } from "./utl/index.mjs";
3
+ /** @import { IInspection, IInspectionType } from "./teamcity.types.ts" */
4
+
5
+ const CATEGORY = "dependency-cruiser";
6
+ const SEVERITY2TEAMCITY_SEVERITY = new Map([
7
+ ["error", "ERROR"],
8
+ ["warn", "WARNING"],
9
+ ["info", "INFO"],
10
+ ]);
11
+ const EOL = "\n";
5
12
 
6
13
  /**
7
14
  * Escape string for TeamCity output.
@@ -35,14 +42,15 @@ function escape(pMessageString) {
35
42
  }
36
43
 
37
44
  /**
38
- * Returns a random flowId consisting of 10 numeric digits. TeamCity doesn't
39
- * currently seem to have demands on the format (it's just a string as far
40
- * as I can tell), but this is what teamcity-service-messages used, so as
41
- * per the rule of least surprise, this is what we use.
45
+ * Returns a random flowId consisting of 10 numeric digits.
46
+ *
47
+ * TeamCity doesn't seem to have demands on the format (it's just a string),
48
+ * but this is what teamcity-service-messages used, so as
49
+ * per the rule of least surprise, this is what we use as well.
42
50
  *
43
- * @return {string} a random flowId consisting of 10 numeric digits
51
+ * @return {string} 10 random numeric digits
44
52
  */
45
- function getRandomFlowIdBare() {
53
+ function getRandomFlowId() {
46
54
  const lFlowIdLength = 10;
47
55
  // eslint-disable-next-line no-magic-numbers
48
56
  const lFlowIdMax = 10 ** lFlowIdLength;
@@ -50,13 +58,10 @@ function getRandomFlowIdBare() {
50
58
  return randomInt(1, lFlowIdMax).toString().padStart(lFlowIdLength, "0");
51
59
  }
52
60
 
53
- const getRandomFlowId = memoize(getRandomFlowIdBare);
54
-
55
61
  /**
56
- * Returns a timestamp in ISO format without the trailing 'Z'. It used to be
57
- * an issue with TeamCity that it didn't use the trailing 'Z' (this is
58
- * documented in the teamcity-service-messages source code) - not sure whether
59
- * this is still the case, but better safe than sorry.
62
+ * Returns a timestamp in ISO format without the trailing 'Z'. TeamCity
63
+ * didn't use the trailing 'Z' (documented in the teamcity-service-messages
64
+ * source) - not sure whether still the case, but better safe than sorry.
60
65
  *
61
66
  * @returns {string} a timestamp in ISO format without the trailing 'Z'
62
67
  */
@@ -64,101 +69,113 @@ function getTimeStamp() {
64
69
  return new Date().toISOString().slice(0, -1);
65
70
  }
66
71
 
67
- function inspectionType(pData) {
72
+ /**
73
+ * formats an inspection type TeamCity service message
74
+ * @param {IInspectionType} pInspectionTypeData
75
+ * @returns {string}
76
+ */
77
+ function formatInspectionType(pInspectionTypeData) {
68
78
  const lAttributes = [];
69
79
  lAttributes.push(
70
- `id='${pData.id}'`,
71
- `name='${pData.name}'`,
72
- `description='${escape(pData.description)}'`,
73
- `category='${pData.category}'`,
74
- `flowId='${getRandomFlowId()}'`,
80
+ `id='${pInspectionTypeData.id}'`,
81
+ `name='${pInspectionTypeData.name}'`,
82
+ `description='${escape(pInspectionTypeData.description)}'`,
83
+ `category='${pInspectionTypeData.category}'`,
84
+ `flowId='${pInspectionTypeData.flowId}'`,
75
85
  `timestamp='${getTimeStamp()}'`,
76
86
  );
77
87
  return `##teamcity[inspectionType ${lAttributes.join(" ")}]`;
78
88
  }
79
89
 
80
- function inspection(pData) {
90
+ /**
91
+ * formats an inspection TeamCity service message
92
+ * @param {IInspection} pInspectionData
93
+ * @returns {string}
94
+ */
95
+ function formatInspection(pInspectionData) {
81
96
  const lAttributes = [];
82
97
  lAttributes.push(
83
- `typeId='${pData.typeId}'`,
84
- `message='${escape(pData.message)}'`,
98
+ `typeId='${pInspectionData.typeId}'`,
99
+ `message='${escape(pInspectionData.message)}'`,
85
100
  );
86
- if (pData.file) {
87
- lAttributes.push(`file='${pData.file}'`);
101
+ if (pInspectionData.file) {
102
+ lAttributes.push(`file='${pInspectionData.file}'`);
88
103
  }
89
104
  lAttributes.push(
90
- `SEVERITY='${pData.SEVERITY}'`,
91
- `flowId='${getRandomFlowId()}'`,
105
+ `SEVERITY='${pInspectionData.SEVERITY}'`,
106
+ `flowId='${pInspectionData.flowId}'`,
92
107
  `timestamp='${getTimeStamp()}'`,
93
108
  );
94
109
 
95
110
  return `##teamcity[inspection ${lAttributes.join(" ")}]`;
96
111
  }
97
112
 
98
- const CATEGORY = "dependency-cruiser";
99
- const SEVERITY2TEAMCITY_SEVERITY = new Map([
100
- ["error", "ERROR"],
101
- ["warn", "WARNING"],
102
- ["info", "INFO"],
103
- ]);
104
- const EOL = "\n";
105
-
106
113
  function severity2teamcitySeverity(pSeverity) {
107
114
  return SEVERITY2TEAMCITY_SEVERITY.get(pSeverity) || "INFO";
108
115
  }
109
116
 
110
- function reportRules(pRules, pViolations) {
117
+ function reportRules(pRules, pViolations, pFlowId) {
111
118
  return pRules
112
119
  .filter((pRule) =>
113
120
  pViolations.some((pViolation) => pRule.name === pViolation.rule.name),
114
121
  )
115
122
  .map((pRule) =>
116
- inspectionType({
123
+ formatInspectionType({
117
124
  id: pRule.name,
118
125
  name: pRule.name,
119
126
  description: pRule.comment || pRule.name,
120
127
  category: CATEGORY,
128
+ flowId: pFlowId,
121
129
  }),
122
130
  );
123
131
  }
124
132
 
125
- function reportAllowedRule(pAllowedRule, pViolations) {
133
+ function reportAllowedRule(pAllowedRule, pViolations, pFlowId) {
126
134
  let lReturnValue = [];
127
135
 
128
136
  if (
129
137
  pAllowedRule.length > 0 &&
130
138
  pViolations.some((pViolation) => pViolation.rule.name === "not-in-allowed")
131
139
  ) {
132
- lReturnValue = inspectionType({
140
+ lReturnValue = formatInspectionType({
133
141
  id: "not-in-allowed",
134
142
  name: "not-in-allowed",
135
143
  description: "dependency is not in the 'allowed' set of rules",
136
144
  category: CATEGORY,
145
+ flowId: pFlowId,
137
146
  });
138
147
  }
139
148
  return lReturnValue;
140
149
  }
141
150
 
142
- function reportIgnoredRules(pIgnoredCount) {
151
+ function reportIgnoredRules(pIgnoredCount, pFlowId) {
143
152
  let lReturnValue = [];
144
153
 
145
154
  if (pIgnoredCount > 0) {
146
- lReturnValue = inspectionType({
155
+ lReturnValue = formatInspectionType({
147
156
  id: "ignored-known-violations",
148
157
  name: "ignored-known-violations",
149
158
  description:
150
159
  "some dependency violations were ignored; run with --no-ignore-known to see them",
151
160
  category: CATEGORY,
161
+ flowId: pFlowId,
152
162
  });
153
163
  }
154
164
  return lReturnValue;
155
165
  }
156
166
 
157
- function reportViolatedRules(pRuleSetUsed, pViolations, pIgnoredCount) {
158
- return reportRules(pRuleSetUsed?.forbidden ?? [], pViolations)
159
- .concat(reportAllowedRule(pRuleSetUsed?.allowed ?? [], pViolations))
160
- .concat(reportRules(pRuleSetUsed?.required ?? [], pViolations))
161
- .concat(reportIgnoredRules(pIgnoredCount));
167
+ function reportViolatedRules(
168
+ pRuleSetUsed,
169
+ pViolations,
170
+ pIgnoredCount,
171
+ pFlowId,
172
+ ) {
173
+ return reportRules(pRuleSetUsed?.forbidden ?? [], pViolations, pFlowId)
174
+ .concat(
175
+ reportAllowedRule(pRuleSetUsed?.allowed ?? [], pViolations, pFlowId),
176
+ )
177
+ .concat(reportRules(pRuleSetUsed?.required ?? [], pViolations, pFlowId))
178
+ .concat(reportIgnoredRules(pIgnoredCount, pFlowId));
162
179
  }
163
180
 
164
181
  function formatModuleViolation(pViolation) {
@@ -204,12 +221,13 @@ function bakeViolationMessage(pViolation) {
204
221
  );
205
222
  }
206
223
 
207
- function reportIgnoredViolation(pIgnoredCount) {
224
+ function reportIgnoredViolation(pIgnoredCount, pFlowId) {
208
225
  let lReturnValue = [];
209
226
 
210
227
  if (pIgnoredCount > 0) {
211
- lReturnValue = inspection({
228
+ lReturnValue = formatInspection({
212
229
  typeId: "ignored-known-violations",
230
+ flowId: pFlowId,
213
231
  message: `${pIgnoredCount} known violations ignored. Run with --no-ignore-known to see them.`,
214
232
  SEVERITY: "WARNING",
215
233
  });
@@ -217,17 +235,18 @@ function reportIgnoredViolation(pIgnoredCount) {
217
235
  return lReturnValue;
218
236
  }
219
237
 
220
- function reportViolations(pViolations, pIgnoredCount) {
238
+ function reportViolations(pViolations, pIgnoredCount, pFlowId) {
221
239
  return pViolations
222
240
  .map((pViolation) =>
223
- inspection({
241
+ formatInspection({
224
242
  typeId: pViolation.rule.name,
243
+ flowId: pFlowId,
225
244
  message: bakeViolationMessage(pViolation),
226
245
  file: pViolation.from,
227
246
  SEVERITY: severity2teamcitySeverity(pViolation.rule.severity),
228
247
  }),
229
248
  )
230
- .concat(reportIgnoredViolation(pIgnoredCount));
249
+ .concat(reportIgnoredViolation(pIgnoredCount, pFlowId));
231
250
  }
232
251
 
233
252
  /**
@@ -237,13 +256,12 @@ function reportViolations(pViolations, pIgnoredCount) {
237
256
  * - for each violation in the passed results: an `inspection` with the
238
257
  * violated rule name and the tos and froms
239
258
  *
240
- * @param {import("../../types/dependency-cruiser.js").ICruiseResult} pResults
241
- * @returns {import("../../types/dependency-cruiser.js").IReporterOutput}
259
+ * @param {import("../../types/dependency-cruiser.mjs").ICruiseResult} pResults
260
+ * @returns {import("../../types/dependency-cruiser.mjs").IReporterOutput}
242
261
  */
243
262
  // eslint-disable-next-line complexity
244
263
  export default function teamcity(pResults) {
245
- memoizeClear(getRandomFlowId);
246
-
264
+ const lFlowId = getRandomFlowId();
247
265
  const lRuleSet = pResults?.summary?.ruleSetUsed ?? [];
248
266
  const lViolations = (pResults?.summary?.violations ?? []).filter(
249
267
  (pViolation) => pViolation.rule.severity !== "ignore",
@@ -252,9 +270,9 @@ export default function teamcity(pResults) {
252
270
 
253
271
  return {
254
272
  output:
255
- reportViolatedRules(lRuleSet, lViolations, lIgnoredCount)
256
- .concat(reportViolations(lViolations, lIgnoredCount))
257
- .reduce((pAll, pCurrent) => `${pAll}${pCurrent}\n`, "") || EOL,
273
+ reportViolatedRules(lRuleSet, lViolations, lIgnoredCount, lFlowId)
274
+ .concat(reportViolations(lViolations, lIgnoredCount, lFlowId))
275
+ .reduce((pAll, pCurrent) => `${pAll}${pCurrent}${EOL}`, "") || EOL,
258
276
  exitCode: pResults.summary.error,
259
277
  };
260
278
  }
@@ -7,7 +7,7 @@ const EOL = "\n";
7
7
 
8
8
  /**
9
9
  *
10
- * @param {import("../../types/cruise-result").IModule} pModule
10
+ * @param {import("../../types/cruise-result.mjs").IModule} pModule
11
11
  * @param {Set<string>} pModulesInFocus
12
12
  * @param {boolean} pHighlightFocused
13
13
  * @returns {any}
@@ -47,7 +47,7 @@ function stringify(pFlatDependency) {
47
47
 
48
48
  /**
49
49
  *
50
- * @param {import("../../types/cruise-result").IModule[]} pModules
50
+ * @param {import("../../types/cruise-result.mjs").IModule[]} pModules
51
51
  * @returns {Set<string>}
52
52
  */
53
53
  function getModulesInFocus(pModules) {
@@ -60,8 +60,8 @@ function getModulesInFocus(pModules) {
60
60
 
61
61
  /**
62
62
  *
63
- * @param {import("../../types/cruise-result").ICruiseResult} pResults
64
- * @param {import("../../types/reporter-options").ITextReporterOptions} pOptions
63
+ * @param {import("../../types/cruise-result.mjs").ICruiseResult} pResults
64
+ * @param {import("../../types/reporter-options.mjs").ITextReporterOptions} pOptions
65
65
  * @returns {string}
66
66
  */
67
67
  function report(pResults, pOptions) {
@@ -82,9 +82,9 @@ function report(pResults, pOptions) {
82
82
  /**
83
83
  * Returns the results of a cruise in a text only format
84
84
  * - for each dependency the from and the two, separated by an arrow.
85
- * @param {import("../../types/cruise-result").ICruiseResult} pResults
86
- * @param {import("../../types/reporter-options").ITextReporterOptions} pOptions
87
- * @returns {import("../../types/dependency-cruiser").IReporterOutput}
85
+ * @param {import("../../types/cruise-result.mjs").ICruiseResult} pResults
86
+ * @param {import("../../types/reporter-options.mjs").ITextReporterOptions} pOptions
87
+ * @returns {import("../../types/dependency-cruiser.mjs").IReporterOutput}
88
88
  */
89
89
  export default function text(pResults, pOptions) {
90
90
  return {
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes