dependency-cruiser 17.0.0 → 17.0.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dependency-cruiser",
3
- "version": "17.0.0",
3
+ "version": "17.0.1",
4
4
  "description": "Validate and visualize dependencies. With your rules. JavaScript, TypeScript, CoffeeScript. ES6, CommonJS, AMD.",
5
5
  "keywords": [
6
6
  "static analysis",
@@ -158,7 +158,6 @@
158
158
  "rechoir": "^0.8.0",
159
159
  "safe-regex": "^2.1.1",
160
160
  "semver": "^7.7.2",
161
- "teamcity-service-messages": "^0.1.14",
162
161
  "tsconfig-paths-webpack-plugin": "^4.2.0",
163
162
  "watskeburt": "^4.2.3"
164
163
  },
package/src/meta.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  /* generated - don't edit */
2
2
 
3
3
  module.exports = {
4
- version: "17.0.0",
4
+ version: "17.0.1",
5
5
  engines: {
6
6
  node: "^20.12||^22||>=24",
7
7
  },
@@ -1,6 +1,100 @@
1
- import tsm from "teamcity-service-messages";
1
+ import { randomInt } from "node:crypto";
2
+ import memoize, { memoizeClear } from "memoize";
3
+
2
4
  import { formatPercentage, formatViolation } from "./utl/index.mjs";
3
5
 
6
+ /**
7
+ * Escape string for TeamCity output.
8
+ * @see https://confluence.jetbrains.com/display/TCD65/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-servMsgsServiceMessages
9
+ * Copied from https://github.com/pifantastic/teamcity-service-messages/blob/master/lib/message.js#L72
10
+ *
11
+ * @param {String} pMessageString the string to escape
12
+ * @return {String}
13
+ */
14
+ function escape(pMessageString) {
15
+ if (pMessageString === null) {
16
+ return "";
17
+ }
18
+
19
+ return (
20
+ pMessageString
21
+ .toString()
22
+ .replace(/\|/g, "||")
23
+ .replace(/\n/g, "|n")
24
+ .replace(/\r/g, "|r")
25
+ .replace(/\[/g, "|[")
26
+ .replace(/\]/g, "|]")
27
+ // next line
28
+ .replace(/\u0085/g, "|x")
29
+ // line separator
30
+ .replace(/\u2028/g, "|l")
31
+ // paragraph separator
32
+ .replace(/\u2029/g, "|p")
33
+ .replace(/'/g, "|'")
34
+ );
35
+ }
36
+
37
+ /**
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.
42
+ *
43
+ * @return {string} a random flowId consisting of 10 numeric digits
44
+ */
45
+ function getRandomFlowIdBare() {
46
+ const lFlowIdLength = 10;
47
+ // eslint-disable-next-line no-magic-numbers
48
+ const lFlowIdMax = 10 ** lFlowIdLength;
49
+
50
+ return randomInt(1, lFlowIdMax).toString().padStart(lFlowIdLength, "0");
51
+ }
52
+
53
+ const getRandomFlowId = memoize(getRandomFlowIdBare);
54
+
55
+ /**
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 this is what we do to be on the safe side.
60
+ *
61
+ * @returns {string} a timestamp in ISO format without the trailing 'Z'
62
+ */
63
+ function getTimeStamp() {
64
+ return new Date().toISOString().slice(0, -1);
65
+ }
66
+
67
+ function inspectionType(pData) {
68
+ const lAttributes = [];
69
+ lAttributes.push(
70
+ `id='${pData.id}'`,
71
+ `name='${pData.name}'`,
72
+ `description='${escape(pData.description)}'`,
73
+ `category='${pData.category}'`,
74
+ `flowId='${getRandomFlowId()}'`,
75
+ `timestamp='${getTimeStamp()}'`,
76
+ );
77
+ return `##teamcity[inspectionType ${lAttributes.join(" ")}]`;
78
+ }
79
+
80
+ function inspection(pData) {
81
+ const lAttributes = [];
82
+ lAttributes.push(
83
+ `typeId='${pData.typeId}'`,
84
+ `message='${escape(pData.message)}'`,
85
+ );
86
+ if (pData.file) {
87
+ lAttributes.push(`file='${pData.file}'`);
88
+ }
89
+ lAttributes.push(
90
+ `SEVERITY='${pData.SEVERITY}'`,
91
+ `flowId='${getRandomFlowId()}'`,
92
+ `timestamp='${getTimeStamp()}'`,
93
+ );
94
+
95
+ return `##teamcity[inspection ${lAttributes.join(" ")}]`;
96
+ }
97
+
4
98
  const CATEGORY = "dependency-cruiser";
5
99
  const SEVERITY2TEAMCITY_SEVERITY = new Map([
6
100
  ["error", "ERROR"],
@@ -19,7 +113,7 @@ function reportRules(pRules, pViolations) {
19
113
  pViolations.some((pViolation) => pRule.name === pViolation.rule.name),
20
114
  )
21
115
  .map((pRule) =>
22
- tsm.inspectionType({
116
+ inspectionType({
23
117
  id: pRule.name,
24
118
  name: pRule.name,
25
119
  description: pRule.comment || pRule.name,
@@ -35,7 +129,7 @@ function reportAllowedRule(pAllowedRule, pViolations) {
35
129
  pAllowedRule.length > 0 &&
36
130
  pViolations.some((pViolation) => pViolation.rule.name === "not-in-allowed")
37
131
  ) {
38
- lReturnValue = tsm.inspectionType({
132
+ lReturnValue = inspectionType({
39
133
  id: "not-in-allowed",
40
134
  name: "not-in-allowed",
41
135
  description: "dependency is not in the 'allowed' set of rules",
@@ -49,7 +143,7 @@ function reportIgnoredRules(pIgnoredCount) {
49
143
  let lReturnValue = [];
50
144
 
51
145
  if (pIgnoredCount > 0) {
52
- lReturnValue = tsm.inspectionType({
146
+ lReturnValue = inspectionType({
53
147
  id: "ignored-known-violations",
54
148
  name: "ignored-known-violations",
55
149
  description:
@@ -114,7 +208,7 @@ function reportIgnoredViolation(pIgnoredCount) {
114
208
  let lReturnValue = [];
115
209
 
116
210
  if (pIgnoredCount > 0) {
117
- lReturnValue = tsm.inspection({
211
+ lReturnValue = inspection({
118
212
  typeId: "ignored-known-violations",
119
213
  message: `${pIgnoredCount} known violations ignored. Run with --no-ignore-known to see them.`,
120
214
  SEVERITY: "WARNING",
@@ -126,7 +220,7 @@ function reportIgnoredViolation(pIgnoredCount) {
126
220
  function reportViolations(pViolations, pIgnoredCount) {
127
221
  return pViolations
128
222
  .map((pViolation) =>
129
- tsm.inspection({
223
+ inspection({
130
224
  typeId: pViolation.rule.name,
131
225
  message: bakeViolationMessage(pViolation),
132
226
  file: pViolation.from,
@@ -138,21 +232,17 @@ function reportViolations(pViolations, pIgnoredCount) {
138
232
 
139
233
  /**
140
234
  * Returns a bunch of TeamCity service messages:
141
- * - for each violated rule in the passed results: an `inspectionType` with the name and comment of that rule
142
- * - for each violation in the passed results: an `inspection` with the violated rule name and the tos and froms
235
+ * - for each violated rule in the passed results: an `inspectionType` with the
236
+ * name and comment of that rule
237
+ * - for each violation in the passed results: an `inspection` with the
238
+ * violated rule name and the tos and froms
143
239
  *
144
240
  * @param {import("../../types/dependency-cruiser.js").ICruiseResult} pResults
145
241
  * @returns {import("../../types/dependency-cruiser.js").IReporterOutput}
146
242
  */
147
243
  // eslint-disable-next-line complexity
148
244
  export default function teamcity(pResults) {
149
- // this is the documented way to get tsm to emit strings
150
- // Alternatively we could've used the 'low level API', which
151
- // involves creating new `Message`s and stringifying those.
152
- // The abstraction of the 'higher level API' makes this
153
- // reporter more easy to implement and maintain, despite
154
- // setting this property directly
155
- tsm.stdout = false;
245
+ memoizeClear(getRandomFlowId);
156
246
 
157
247
  const lRuleSet = pResults?.summary?.ruleSetUsed ?? [];
158
248
  const lViolations = (pResults?.summary?.violations ?? []).filter(
@@ -2,10 +2,6 @@
2
2
  export type ModuleSystemType = "cjs" | "amd" | "es6" | "tsd";
3
3
 
4
4
  // cruise options, dependency-cruiser
5
- /* as we don't care about types beyond code completion, we ignore the
6
- * eslint warning that the 'string' type is redundant here.
7
- */
8
- /* eslint-disable @typescript-eslint/no-redundant-type-constituents */
9
5
  export type OutputType =
10
6
  | "json"
11
7
  | "html"
@@ -29,7 +25,7 @@ export type OutputType =
29
25
  | "null"
30
26
  // for plugins: string. TODO: research whether it's possible to
31
27
  // tie this down to the `^plugin:[^:]+-reporter-plugin.[cm]?js$` regex
32
- | string;
28
+ | (string & {}); // autocompletion hack
33
29
 
34
30
  export type SeverityType = "error" | "warn" | "info" | "ignore";
35
31