dependency-cruiser 18.2.0 → 18.3.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.
@@ -1,14 +1,14 @@
1
1
  /** @import { IViolation } from "../../types/dependency-cruiser.mjs" */
2
2
  /* eslint-disable no-magic-numbers */
3
+ const SEVERITY2MUMBER = new Map([
4
+ ["error", 1],
5
+ ["warn", 2],
6
+ ["info", 3],
7
+ ["ignore", 4],
8
+ ]);
9
+
3
10
  function severity2number(pSeverity) {
4
- const lSeverity2Number = new Map([
5
- ["error", 1],
6
- ["warn", 2],
7
- ["info", 3],
8
- ["ignore", 4],
9
- ]);
10
-
11
- return lSeverity2Number.get(pSeverity) || -1;
11
+ return SEVERITY2MUMBER.get(pSeverity) || -1;
12
12
  }
13
13
 
14
14
  export function compareSeverities(pFirstSeverity, pSecondSeverity) {
@@ -71,15 +71,21 @@ function compareArrays(pFirstArray, pSecondArray) {
71
71
  *
72
72
  * @param {IViolation} pFirstViolation
73
73
  * @param {IViolation} pSecondViolation
74
- * @returns
74
+ * @param {boolean} pCompareSeverities
75
+ * @returns {number}
75
76
  */
76
77
  // eslint-disable-next-line complexity
77
- export function compareViolations(pFirstViolation, pSecondViolation) {
78
+ function compareViolationsBase(
79
+ pFirstViolation,
80
+ pSecondViolation,
81
+ pCompareSeverities,
82
+ ) {
78
83
  return (
79
- compareSeverities(
80
- pFirstViolation.rule.severity,
81
- pSecondViolation.rule.severity,
82
- ) ||
84
+ (pCompareSeverities &&
85
+ compareSeverities(
86
+ pFirstViolation.rule.severity,
87
+ pSecondViolation.rule.severity,
88
+ )) ||
83
89
  pFirstViolation.rule.name.localeCompare(pSecondViolation.rule.name) ||
84
90
  pFirstViolation.from.localeCompare(pSecondViolation.from) ||
85
91
  pFirstViolation.to.localeCompare(pSecondViolation.to) ||
@@ -96,6 +102,99 @@ export function compareViolations(pFirstViolation, pSecondViolation) {
96
102
  );
97
103
  }
98
104
 
105
+ /**
106
+ * Compares violations on all relevant fields _excluding_ severity
107
+ *
108
+ * @param {IViolation} pFirstViolation
109
+ * @param {IViolation} pSecondViolation
110
+ * @returns {number}
111
+ */
112
+ export function compareViolationsExSeverities(
113
+ pFirstViolation,
114
+ pSecondViolation,
115
+ ) {
116
+ return compareViolationsBase(pFirstViolation, pSecondViolation, false);
117
+ }
118
+
119
+ /**
120
+ * Compares violations on all relevant fields _including_ severity
121
+ *
122
+ * @param {IViolation} pFirstViolation
123
+ * @param {IViolation} pSecondViolation
124
+ * @returns {number}
125
+ */
126
+ export function compareViolations(pFirstViolation, pSecondViolation) {
127
+ return compareViolationsBase(pFirstViolation, pSecondViolation, true);
128
+ }
129
+
130
+ /**
131
+ * Compare two arrays of violations and return a diff by value.
132
+ *
133
+ * Use the project’s established scalar ordering, compareViolations(),
134
+ * rather than introducing a second comparison construct. This keeps the
135
+ * semantics in one place and makes the diff logic easier to maintain.
136
+ *
137
+ * @param {IViolation[]} pFirstViolationArray - First array of violations
138
+ * @param {IViolation[]} pSecondViolationArray - Second array of violations
139
+ * @returns {{
140
+ * new: IViolation[]; // only in the second array
141
+ * same: IViolation[]; // in both arrays
142
+ * old: IViolation[]; // only in the first array
143
+ * }}
144
+ */
145
+ export function diffViolationArrays(
146
+ pFirstViolationArray,
147
+ pSecondViolationArray,
148
+ ) {
149
+ const lFirstViolations = pFirstViolationArray.toSorted(
150
+ compareViolationsExSeverities,
151
+ );
152
+ const lSecondViolations = pSecondViolationArray.toSorted(
153
+ compareViolationsExSeverities,
154
+ );
155
+ const lNew = [];
156
+ const lSame = [];
157
+ const lOld = [];
158
+ let lFirstIndex = 0;
159
+ let lSecondIndex = 0;
160
+
161
+ while (
162
+ lFirstIndex < lFirstViolations.length ||
163
+ lSecondIndex < lSecondViolations.length
164
+ ) {
165
+ if (lFirstIndex >= lFirstViolations.length) {
166
+ lNew.push(lSecondViolations[lSecondIndex]);
167
+ lSecondIndex += 1;
168
+ continue;
169
+ }
170
+
171
+ if (lSecondIndex >= lSecondViolations.length) {
172
+ lOld.push(lFirstViolations[lFirstIndex]);
173
+ lFirstIndex += 1;
174
+ continue;
175
+ }
176
+
177
+ const lComparison = compareViolationsExSeverities(
178
+ lFirstViolations[lFirstIndex],
179
+ lSecondViolations[lSecondIndex],
180
+ );
181
+
182
+ if (lComparison === 0) {
183
+ lSame.push(lFirstViolations[lFirstIndex]);
184
+ lFirstIndex += 1;
185
+ lSecondIndex += 1;
186
+ } else if (lComparison < 0) {
187
+ lOld.push(lFirstViolations[lFirstIndex]);
188
+ lFirstIndex += 1;
189
+ } else {
190
+ lNew.push(lSecondViolations[lSecondIndex]);
191
+ lSecondIndex += 1;
192
+ }
193
+ }
194
+
195
+ return { new: lNew, same: lSame, old: lOld };
196
+ }
197
+
99
198
  export function compareRules(pLeftRule, pRightRule) {
100
199
  return (
101
200
  compareSeverities(pLeftRule.severity, pRightRule.severity) ||
@@ -4,7 +4,6 @@ import defaults from "./defaults.mjs";
4
4
  import { uniq } from "#utl/array-util.mjs";
5
5
 
6
6
  /**
7
- * @import { ICruiseResult } from "../../../types/cruise-result.mjs";
8
7
  * @import { ICruiseOptions, IFormatOptions } from "../../../types/options.mjs";
9
8
  * @import { IStrictCruiseOptions, IStrictFormatOptions } from "../../../types/strict-options.mjs";
10
9
  * @import { IForbiddenRuleType, IFlattenedRuleSet } from "../../../types/rule-set.mjs";
@@ -115,6 +114,13 @@ function ruleSetHasMetricsRule(pRuleSet) {
115
114
  );
116
115
  }
117
116
 
117
+ // TODO duplicated in ../report-wrap.mjs
118
+ function getReporterSection(pOutputType) {
119
+ return ["x-dot-webpage", "dot-webpage"].includes(pOutputType)
120
+ ? "dot"
121
+ : pOutputType;
122
+ }
123
+
118
124
  /**
119
125
  *
120
126
  * @param {ICruiseOptions} pOptions
@@ -122,8 +128,8 @@ function ruleSetHasMetricsRule(pRuleSet) {
122
128
  */
123
129
  function reporterShowsMetrics(pOptions) {
124
130
  return (
125
- (pOptions.reporterOptions?.[pOptions?.outputType]?.showMetrics ?? false) ===
126
- true
131
+ (pOptions.reporterOptions?.[getReporterSection(pOptions?.outputType)]
132
+ ?.showMetrics ?? false) === true
127
133
  );
128
134
  }
129
135
 
@@ -44,9 +44,11 @@ function reSummarizeResults(pResult, pFormatOptions) {
44
44
  modules: lModules,
45
45
  };
46
46
  }
47
-
47
+ // TODO duplicated in ./options/normalize.mjs
48
48
  function getReporterSection(pOutputType) {
49
- return pOutputType === "x-dot-webpage" ? "dot" : pOutputType;
49
+ return ["x-dot-webpage", "dot-webpage"].includes(pOutputType)
50
+ ? "dot"
51
+ : pOutputType;
50
52
  }
51
53
 
52
54
  /**
package/src/meta.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  /* generated - don't edit */
2
2
  module.exports = {
3
- version: "18.2.0",
3
+ version: "18.3.0",
4
4
  engines: {
5
5
  node: "^22||^24||>=26",
6
6
  },
@@ -1,24 +1,66 @@
1
+ import { diffViolationArrays } from "#graph-utl/compare.mjs";
2
+ /**
3
+ * @import { ICruiseResult, IReporterOutput } from "../../types/dependency-cruiser.mjs";
4
+ * @import { IViolation} from "../../types/violations.mjs"
5
+ * @import { BaselineModeType } from "../../types/options.mjs"
6
+ */
7
+
1
8
  const DEFAULT_JSON_INDENT = 2;
2
9
  const EOL = "\n";
10
+ const BASELINE_DEFAULT_MODE = "full";
11
+
12
+ /**
13
+ * @param {IViolation[]} pKnownViolations
14
+ * @param {IViolation[]} pCurrentViolations
15
+ * @param {BaselineModeType} pMode
16
+ * @returns {IReporterOutput}
17
+ */
18
+ function getBaseline(pKnownViolations, pCurrentViolations, pMode) {
19
+ const lReturnValue = {};
20
+ const lKnownViolations = pKnownViolations || [];
21
+ const lViolationArrayDiff = diffViolationArrays(
22
+ lKnownViolations,
23
+ pCurrentViolations,
24
+ );
25
+ let lViolationsToEmit = pCurrentViolations;
26
+ let lModeAddition = " (running in 'full' mode => added to the baseline)";
27
+
28
+ if (pMode === "shrink-only") {
29
+ lViolationsToEmit = lViolationArrayDiff.same;
30
+ lModeAddition =
31
+ " (running in 'shrink-only' mode => not added to the baseline)";
32
+ }
33
+ lReturnValue.meta =
34
+ `${EOL}baseline : ${lViolationsToEmit.length} violations${EOL}${EOL}` +
35
+ ` new : ${lViolationArrayDiff.new.length}${lViolationArrayDiff.new.length > 0 ? lModeAddition : ""}${EOL}` +
36
+ ` same : ${lViolationArrayDiff.same.length}${EOL}` +
37
+ ` removed : ${lViolationArrayDiff.old.length}${EOL}`;
38
+ lReturnValue.output =
39
+ JSON.stringify(lViolationsToEmit, null, DEFAULT_JSON_INDENT) + EOL;
40
+
41
+ return lReturnValue;
42
+ }
3
43
 
4
44
  /**
5
- * Sample plugin
45
+ * Returns the current 'baseline' of violations, which can be used
6
46
  *
7
- * @param {import('../../types/dependency-cruiser').ICruiseResult} pCruiseResult -
47
+ * @param {ICruiseResult} pCruiseResult -
8
48
  * the output of a dependency-cruise adhering to dependency-cruiser's
9
49
  * cruise result schema
10
- * @returns {import('../../types/dependency-cruiser').IReporterOutput} -
11
- * output: some stats on modules and dependencies in json format
50
+ * @returns {IReporterOutput} -
51
+ * output: known violations
52
+ * meta: information to print on a side channel (e.g. stderr)
12
53
  * exitCode: 0
13
54
  */
14
55
  export default function baseline(pCruiseResult) {
56
+ const { meta, output } = getBaseline(
57
+ pCruiseResult.summary.optionsUsed.knownViolations,
58
+ pCruiseResult.summary.violations,
59
+ pCruiseResult.summary.optionsUsed?.baseline?.mode ?? BASELINE_DEFAULT_MODE,
60
+ );
15
61
  return {
16
- output:
17
- JSON.stringify(
18
- pCruiseResult.summary.violations,
19
- null,
20
- DEFAULT_JSON_INDENT,
21
- ) + EOL,
62
+ output,
63
+ meta,
22
64
  exitCode: 0,
23
65
  };
24
66
  }
@@ -63,7 +63,7 @@ function isAvailable(pOptions) {
63
63
  export default function dotWebpage(pResults, pDotWebpageReporterOptions) {
64
64
  if (!isAvailable(pDotWebpageReporterOptions)) {
65
65
  throw new Error(
66
- "GraphViz dot, which is required for the 'x-dot-webpage' reporter doesn't " +
66
+ "GraphViz dot, which is required for the 'dot-webpage' reporter doesn't " +
67
67
  "seem to be available on this system. See the GraphViz download page for " +
68
68
  "instruction on how to get it on your system: https://www.graphviz.org/download/",
69
69
  );
@@ -23,6 +23,7 @@ const TYPE2MODULE = new Map([
23
23
  ["null", "./null.mjs"],
24
24
  ["teamcity", "./teamcity.mjs"],
25
25
  ["text", "./text.mjs"],
26
+ ["dot-webpage", "./dot-webpage/dot-module.mjs"],
26
27
  ["x-dot-webpage", "./dot-webpage/dot-module.mjs"],
27
28
  ]);
28
29