@fabasoad/sarif-to-slack 0.2.5 → 1.0.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.
Files changed (192) hide show
  1. package/.github/workflows/release.yml +1 -1
  2. package/.github/workflows/security.yml +0 -1
  3. package/.github/workflows/send-sarif-to-slack.yml +145 -73
  4. package/.gitleaksignore +8 -0
  5. package/.pre-commit-config.yaml +3 -3
  6. package/.tool-versions +1 -1
  7. package/dist/Logger.js +4 -1
  8. package/dist/SarifToSlackClient.d.ts +33 -0
  9. package/dist/SarifToSlackClient.d.ts.map +1 -0
  10. package/dist/SarifToSlackClient.js +178 -0
  11. package/dist/SlackMessageBuilder.js +34 -82
  12. package/dist/System.d.ts +1 -3
  13. package/dist/System.d.ts.map +1 -1
  14. package/dist/System.js +10 -3
  15. package/dist/index.cjs +840 -472
  16. package/dist/index.d.ts +35 -12
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +36 -12
  19. package/dist/model/Color.d.ts +70 -0
  20. package/dist/model/Color.d.ts.map +1 -0
  21. package/dist/model/Color.js +119 -0
  22. package/dist/model/Finding.d.ts +2 -0
  23. package/dist/model/Finding.d.ts.map +1 -0
  24. package/dist/model/Finding.js +93 -0
  25. package/dist/model/FindingsArray.d.ts +2 -0
  26. package/dist/model/FindingsArray.d.ts.map +1 -0
  27. package/dist/model/FindingsArray.js +24 -0
  28. package/dist/processors/CodeQLProcessor.d.ts +2 -0
  29. package/dist/processors/CodeQLProcessor.d.ts.map +1 -0
  30. package/dist/processors/CodeQLProcessor.js +17 -0
  31. package/dist/processors/CommonProcessor.d.ts +2 -0
  32. package/dist/processors/CommonProcessor.d.ts.map +1 -0
  33. package/dist/processors/CommonProcessor.js +84 -0
  34. package/dist/processors/ProcessorFactory.d.ts +2 -0
  35. package/dist/processors/ProcessorFactory.d.ts.map +1 -0
  36. package/dist/processors/ProcessorFactory.js +22 -0
  37. package/dist/processors/SnykProcessor.d.ts +2 -0
  38. package/dist/processors/SnykProcessor.d.ts.map +1 -0
  39. package/dist/processors/SnykProcessor.js +18 -0
  40. package/dist/representations/CompactGroupByRepresentation.d.ts +2 -0
  41. package/dist/representations/CompactGroupByRepresentation.d.ts.map +1 -0
  42. package/dist/representations/CompactGroupByRepresentation.js +58 -0
  43. package/dist/representations/CompactGroupByRunPerLevelRepresentation.d.ts +2 -0
  44. package/dist/representations/CompactGroupByRunPerLevelRepresentation.d.ts.map +1 -0
  45. package/dist/representations/CompactGroupByRunPerLevelRepresentation.js +13 -0
  46. package/dist/representations/CompactGroupByRunPerSeverityRepresentation.d.ts +2 -0
  47. package/dist/representations/CompactGroupByRunPerSeverityRepresentation.d.ts.map +1 -0
  48. package/dist/representations/CompactGroupByRunPerSeverityRepresentation.js +13 -0
  49. package/dist/representations/CompactGroupByRunRepresentation.d.ts +2 -0
  50. package/dist/representations/CompactGroupByRunRepresentation.d.ts.map +1 -0
  51. package/dist/representations/CompactGroupByRunRepresentation.js +39 -0
  52. package/dist/representations/CompactGroupBySarifPerLevelRepresentation.d.ts +2 -0
  53. package/dist/representations/CompactGroupBySarifPerLevelRepresentation.d.ts.map +1 -0
  54. package/dist/representations/CompactGroupBySarifPerLevelRepresentation.js +13 -0
  55. package/dist/representations/CompactGroupBySarifPerSeverityRepresentation.d.ts +2 -0
  56. package/dist/representations/CompactGroupBySarifPerSeverityRepresentation.d.ts.map +1 -0
  57. package/dist/representations/CompactGroupBySarifPerSeverityRepresentation.js +13 -0
  58. package/dist/representations/CompactGroupBySarifRepresentation.d.ts +2 -0
  59. package/dist/representations/CompactGroupBySarifRepresentation.d.ts.map +1 -0
  60. package/dist/representations/CompactGroupBySarifRepresentation.js +40 -0
  61. package/dist/representations/CompactGroupByToolNamePerLevelRepresentation.d.ts +2 -0
  62. package/dist/representations/CompactGroupByToolNamePerLevelRepresentation.d.ts.map +1 -0
  63. package/dist/representations/CompactGroupByToolNamePerLevelRepresentation.js +13 -0
  64. package/dist/representations/CompactGroupByToolNamePerSeverityRepresentation.d.ts +2 -0
  65. package/dist/representations/CompactGroupByToolNamePerSeverityRepresentation.d.ts.map +1 -0
  66. package/dist/representations/CompactGroupByToolNamePerSeverityRepresentation.js +13 -0
  67. package/dist/representations/CompactGroupByToolNameRepresentation.d.ts +2 -0
  68. package/dist/representations/CompactGroupByToolNameRepresentation.d.ts.map +1 -0
  69. package/dist/representations/CompactGroupByToolNameRepresentation.js +39 -0
  70. package/dist/representations/CompactTotalPerLevelRepresentation.d.ts +2 -0
  71. package/dist/representations/CompactTotalPerLevelRepresentation.d.ts.map +1 -0
  72. package/dist/representations/CompactTotalPerLevelRepresentation.js +13 -0
  73. package/dist/representations/CompactTotalPerSeverityRepresentation.d.ts +2 -0
  74. package/dist/representations/CompactTotalPerSeverityRepresentation.d.ts.map +1 -0
  75. package/dist/representations/CompactTotalPerSeverityRepresentation.js +13 -0
  76. package/dist/representations/CompactTotalRepresentation.d.ts +2 -0
  77. package/dist/representations/CompactTotalRepresentation.d.ts.map +1 -0
  78. package/dist/representations/CompactTotalRepresentation.js +25 -0
  79. package/dist/representations/Representation.d.ts +2 -0
  80. package/dist/representations/Representation.d.ts.map +1 -0
  81. package/dist/representations/Representation.js +28 -0
  82. package/dist/representations/RepresentationFactory.d.ts +2 -0
  83. package/dist/representations/RepresentationFactory.d.ts.map +1 -0
  84. package/dist/representations/RepresentationFactory.js +37 -0
  85. package/dist/sarif-to-slack.d.ts +337 -85
  86. package/dist/tsdoc-metadata.json +1 -1
  87. package/dist/types.d.ts +215 -51
  88. package/dist/types.d.ts.map +1 -1
  89. package/dist/types.js +225 -33
  90. package/dist/utils/Comparators.d.ts +2 -0
  91. package/dist/utils/Comparators.d.ts.map +1 -0
  92. package/dist/utils/Comparators.js +18 -0
  93. package/dist/utils/ExtendedArray.d.ts +2 -0
  94. package/dist/utils/ExtendedArray.d.ts.map +1 -0
  95. package/dist/utils/ExtendedArray.js +11 -0
  96. package/dist/utils/FileUtils.d.ts +2 -0
  97. package/dist/utils/FileUtils.d.ts.map +1 -0
  98. package/dist/utils/FileUtils.js +51 -0
  99. package/dist/utils/SarifUtils.js +20 -54
  100. package/etc/sarif-to-slack.api.md +161 -99
  101. package/jest.config.json +2 -2
  102. package/package.json +7 -7
  103. package/scripts/save-metadata.sh +12 -10
  104. package/src/Logger.ts +4 -0
  105. package/src/SarifToSlackClient.ts +202 -0
  106. package/src/SlackMessageBuilder.ts +35 -115
  107. package/src/System.ts +9 -2
  108. package/src/index.ts +47 -20
  109. package/src/model/Color.ts +201 -0
  110. package/src/model/Finding.ts +137 -0
  111. package/src/model/FindingsArray.ts +27 -0
  112. package/src/processors/CodeQLProcessor.ts +19 -0
  113. package/src/processors/CommonProcessor.ts +103 -0
  114. package/src/processors/ProcessorFactory.ts +23 -0
  115. package/src/processors/SnykProcessor.ts +19 -0
  116. package/src/representations/CompactGroupByRepresentation.ts +67 -0
  117. package/src/representations/CompactGroupByRunPerLevelRepresentation.ts +14 -0
  118. package/src/representations/CompactGroupByRunPerSeverityRepresentation.ts +14 -0
  119. package/src/representations/CompactGroupByRunRepresentation.ts +44 -0
  120. package/src/representations/CompactGroupBySarifPerLevelRepresentation.ts +15 -0
  121. package/src/representations/CompactGroupBySarifPerSeverityRepresentation.ts +15 -0
  122. package/src/representations/CompactGroupBySarifRepresentation.ts +45 -0
  123. package/src/representations/CompactGroupByToolNamePerLevelRepresentation.ts +15 -0
  124. package/src/representations/CompactGroupByToolNamePerSeverityRepresentation.ts +15 -0
  125. package/src/representations/CompactGroupByToolNameRepresentation.ts +44 -0
  126. package/src/representations/CompactTotalPerLevelRepresentation.ts +14 -0
  127. package/src/representations/CompactTotalPerSeverityRepresentation.ts +14 -0
  128. package/src/representations/CompactTotalRepresentation.ts +27 -0
  129. package/src/representations/Representation.ts +35 -0
  130. package/src/representations/RepresentationFactory.ts +49 -0
  131. package/src/types.ts +270 -53
  132. package/src/utils/Comparators.ts +19 -0
  133. package/src/utils/ExtendedArray.ts +11 -0
  134. package/src/utils/FileUtils.ts +60 -0
  135. package/src/utils/SarifUtils.ts +20 -72
  136. package/test-data/sarif/codeql-python.sarif +1448 -1
  137. package/test-data/sarif/codeql-typescript.sarif +3474 -1
  138. package/test-data/sarif/grype-github-actions.sarif +65 -0
  139. package/test-data/sarif/osv-scanner-composer.sarif +972 -0
  140. package/test-data/sarif/osv-scanner-container.sarif +2278 -0
  141. package/test-data/sarif/osv-scanner-gomodules.sarif +813 -0
  142. package/test-data/sarif/osv-scanner-hex.sarif +147 -0
  143. package/test-data/sarif/osv-scanner-maven.sarif +171 -0
  144. package/test-data/sarif/osv-scanner-npm.sarif +627 -0
  145. package/test-data/sarif/osv-scanner-pip.sarif +206 -0
  146. package/test-data/sarif/osv-scanner-pipenv.sarif +243 -0
  147. package/test-data/sarif/osv-scanner-pnpm.sarif +174 -0
  148. package/test-data/sarif/osv-scanner-poetry.sarif +1893 -0
  149. package/test-data/sarif/osv-scanner-rubygems.sarif +402 -0
  150. package/test-data/sarif/osv-scanner-uv.sarif +206 -0
  151. package/test-data/sarif/osv-scanner-yarn.sarif +5207 -0
  152. package/test-data/sarif/runs-0.sarif +5 -0
  153. package/test-data/sarif/runs-2-tools-2-results-0.sarif +1 -1
  154. package/test-data/sarif/runs-2-tools-2.sarif +1 -1
  155. package/test-data/sarif/runs-3-tools-2-results-0.sarif +1 -1
  156. package/test-data/sarif/runs-3-tools-2.sarif +1 -1
  157. package/test-data/sarif/tmp/codeql-csharp.sarif +1 -0
  158. package/test-data/sarif/tmp/grype-container.sarif +1774 -0
  159. package/test-data/sarif/tmp/runs-1-tools-1-results-0.sarif +18 -0
  160. package/test-data/sarif/tmp/runs-2-tools-2.sarif +686 -0
  161. package/test-data/sarif/trivy-iac.sarif +1 -1
  162. package/tests/integration/SendSarifToSlack.spec.ts +95 -27
  163. package/tsconfig.json +2 -0
  164. package/dist/Processors.d.ts +0 -2
  165. package/dist/Processors.d.ts.map +0 -1
  166. package/dist/Processors.js +0 -61
  167. package/dist/SarifToSlackService.d.ts +0 -39
  168. package/dist/SarifToSlackService.d.ts.map +0 -1
  169. package/dist/SarifToSlackService.js +0 -104
  170. package/dist/metadata.d.ts +0 -2
  171. package/dist/metadata.d.ts.map +0 -1
  172. package/dist/metadata.js +0 -11
  173. package/dist/model/SarifModelPerRun.d.ts +0 -2
  174. package/dist/model/SarifModelPerRun.d.ts.map +0 -1
  175. package/dist/model/SarifModelPerRun.js +0 -90
  176. package/dist/model/SarifModelPerSarif.d.ts +0 -2
  177. package/dist/model/SarifModelPerSarif.d.ts.map +0 -1
  178. package/dist/model/SarifModelPerSarif.js +0 -102
  179. package/dist/model/types.d.ts +0 -2
  180. package/dist/model/types.d.ts.map +0 -1
  181. package/dist/model/types.js +0 -49
  182. package/dist/utils/SortUtils.d.ts +0 -2
  183. package/dist/utils/SortUtils.d.ts.map +0 -1
  184. package/dist/utils/SortUtils.js +0 -20
  185. package/src/Processors.ts +0 -68
  186. package/src/SarifToSlackService.ts +0 -117
  187. package/src/metadata.ts +0 -10
  188. package/src/model/SarifModelPerRun.ts +0 -120
  189. package/src/model/SarifModelPerSarif.ts +0 -126
  190. package/src/model/types.ts +0 -50
  191. package/src/utils/SortUtils.ts +0 -33
  192. package/tests/Processors.spec.ts +0 -76
package/dist/index.cjs CHANGED
@@ -30,20 +30,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
- CalculateResultsBy: () => CalculateResultsBy,
33
+ Color: () => Color,
34
34
  FooterType: () => FooterType,
35
- GroupResultsBy: () => GroupResultsBy,
36
35
  LogLevel: () => LogLevel,
37
- SarifToSlackService: () => SarifToSlackService
36
+ RepresentationType: () => RepresentationType,
37
+ SarifToSlackClient: () => SarifToSlackClient,
38
+ SendIf: () => SendIf
38
39
  });
39
40
  module.exports = __toCommonJS(index_exports);
40
41
 
41
- // src/SarifToSlackService.ts
42
- var import_fs = require("fs");
43
-
44
- // src/Logger.ts
45
- var import_tslog = require("tslog");
46
-
47
42
  // src/types.ts
48
43
  var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
49
44
  LogLevel2[LogLevel2["Silly"] = 0] = "Silly";
@@ -60,19 +55,175 @@ var FooterType = /* @__PURE__ */ ((FooterType2) => {
60
55
  FooterType2["Markdown"] = "mrkdwn";
61
56
  return FooterType2;
62
57
  })(FooterType || {});
63
- var GroupResultsBy = /* @__PURE__ */ ((GroupResultsBy2) => {
64
- GroupResultsBy2[GroupResultsBy2["ToolName"] = 0] = "ToolName";
65
- GroupResultsBy2[GroupResultsBy2["Run"] = 1] = "Run";
66
- GroupResultsBy2[GroupResultsBy2["Total"] = 2] = "Total";
67
- return GroupResultsBy2;
68
- })(GroupResultsBy || {});
69
- var CalculateResultsBy = /* @__PURE__ */ ((CalculateResultsBy2) => {
70
- CalculateResultsBy2[CalculateResultsBy2["Level"] = 0] = "Level";
71
- CalculateResultsBy2[CalculateResultsBy2["Severity"] = 1] = "Severity";
72
- return CalculateResultsBy2;
73
- })(CalculateResultsBy || {});
58
+ var RepresentationType = /* @__PURE__ */ ((RepresentationType2) => {
59
+ RepresentationType2[RepresentationType2["CompactGroupByRunPerLevel"] = 0] = "CompactGroupByRunPerLevel";
60
+ RepresentationType2[RepresentationType2["CompactGroupByRunPerSeverity"] = 1] = "CompactGroupByRunPerSeverity";
61
+ RepresentationType2[RepresentationType2["CompactGroupByToolNamePerLevel"] = 2] = "CompactGroupByToolNamePerLevel";
62
+ RepresentationType2[RepresentationType2["CompactGroupByToolNamePerSeverity"] = 3] = "CompactGroupByToolNamePerSeverity";
63
+ RepresentationType2[RepresentationType2["CompactGroupBySarifPerLevel"] = 4] = "CompactGroupBySarifPerLevel";
64
+ RepresentationType2[RepresentationType2["CompactGroupBySarifPerSeverity"] = 5] = "CompactGroupBySarifPerSeverity";
65
+ RepresentationType2[RepresentationType2["CompactTotalPerLevel"] = 6] = "CompactTotalPerLevel";
66
+ RepresentationType2[RepresentationType2["CompactTotalPerSeverity"] = 7] = "CompactTotalPerSeverity";
67
+ return RepresentationType2;
68
+ })(RepresentationType || {});
69
+ var SendIf = /* @__PURE__ */ ((SendIf2) => {
70
+ SendIf2[SendIf2["SeverityCritical"] = 0] = "SeverityCritical";
71
+ SendIf2[SendIf2["SeverityHigh"] = 1] = "SeverityHigh";
72
+ SendIf2[SendIf2["SeverityHighOrHigher"] = 2] = "SeverityHighOrHigher";
73
+ SendIf2[SendIf2["SeverityMedium"] = 3] = "SeverityMedium";
74
+ SendIf2[SendIf2["SeverityMediumOrHigher"] = 4] = "SeverityMediumOrHigher";
75
+ SendIf2[SendIf2["SeverityLow"] = 5] = "SeverityLow";
76
+ SendIf2[SendIf2["SeverityLowOrHigher"] = 6] = "SeverityLowOrHigher";
77
+ SendIf2[SendIf2["SeverityNone"] = 7] = "SeverityNone";
78
+ SendIf2[SendIf2["SeverityNoneOrHigher"] = 8] = "SeverityNoneOrHigher";
79
+ SendIf2[SendIf2["SeverityUnknown"] = 9] = "SeverityUnknown";
80
+ SendIf2[SendIf2["SeverityUnknownOrHigher"] = 10] = "SeverityUnknownOrHigher";
81
+ SendIf2[SendIf2["LevelError"] = 11] = "LevelError";
82
+ SendIf2[SendIf2["LevelWarning"] = 12] = "LevelWarning";
83
+ SendIf2[SendIf2["LevelWarningOrHigher"] = 13] = "LevelWarningOrHigher";
84
+ SendIf2[SendIf2["LevelNote"] = 14] = "LevelNote";
85
+ SendIf2[SendIf2["LevelNoteOrHigher"] = 15] = "LevelNoteOrHigher";
86
+ SendIf2[SendIf2["LevelNone"] = 16] = "LevelNone";
87
+ SendIf2[SendIf2["LevelNoneOrHigher"] = 17] = "LevelNoneOrHigher";
88
+ SendIf2[SendIf2["LevelUnknown"] = 18] = "LevelUnknown";
89
+ SendIf2[SendIf2["LevelUnknownOrHigher"] = 19] = "LevelUnknownOrHigher";
90
+ SendIf2[SendIf2["Always"] = 20] = "Always";
91
+ SendIf2[SendIf2["Some"] = 21] = "Some";
92
+ SendIf2[SendIf2["Empty"] = 22] = "Empty";
93
+ SendIf2[SendIf2["Never"] = 23] = "Never";
94
+ return SendIf2;
95
+ })(SendIf || {});
96
+ var SecuritySeverity = /* @__PURE__ */ ((SecuritySeverity2) => {
97
+ SecuritySeverity2[SecuritySeverity2["Unknown"] = 0] = "Unknown";
98
+ SecuritySeverity2[SecuritySeverity2["None"] = 1] = "None";
99
+ SecuritySeverity2[SecuritySeverity2["Low"] = 2] = "Low";
100
+ SecuritySeverity2[SecuritySeverity2["Medium"] = 3] = "Medium";
101
+ SecuritySeverity2[SecuritySeverity2["High"] = 4] = "High";
102
+ SecuritySeverity2[SecuritySeverity2["Critical"] = 5] = "Critical";
103
+ return SecuritySeverity2;
104
+ })(SecuritySeverity || {});
105
+ var SecurityLevel = /* @__PURE__ */ ((SecurityLevel2) => {
106
+ SecurityLevel2[SecurityLevel2["Unknown"] = 0] = "Unknown";
107
+ SecurityLevel2[SecurityLevel2["None"] = 1] = "None";
108
+ SecurityLevel2[SecurityLevel2["Note"] = 2] = "Note";
109
+ SecurityLevel2[SecurityLevel2["Warning"] = 3] = "Warning";
110
+ SecurityLevel2[SecurityLevel2["Error"] = 4] = "Error";
111
+ return SecurityLevel2;
112
+ })(SecurityLevel || {});
113
+
114
+ // src/model/Color.ts
115
+ var Color = class {
116
+ _color;
117
+ /**
118
+ * Creates an instance of {@link Color} class. Before creating an instance of
119
+ * {@link Color} class, it (if applicable) maps CI status into the hex color,
120
+ * and also validates {@param color} to be a valid string that represents a
121
+ * color in hex format.
122
+ * @param color Can be either undefined, valid color in hex format or GitHub
123
+ * CI status (one of: success, failure, cancelled, skipped)
124
+ * @public
125
+ */
126
+ constructor(color) {
127
+ this._color = this.mapColor(color);
128
+ this.validateHexColor();
129
+ }
130
+ /**
131
+ * Returns a valid string that represents a color in hex format, or undefined.
132
+ */
133
+ get value() {
134
+ return this._color;
135
+ }
136
+ validateHexColor() {
137
+ if (this._color != null) {
138
+ const hexColorRegex = /^#(?:[0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/;
139
+ if (!hexColorRegex.test(this._color)) {
140
+ throw new Error(`Invalid hex color: "${this._color}"`);
141
+ }
142
+ }
143
+ }
144
+ mapColor(from) {
145
+ switch (from) {
146
+ case "success":
147
+ return "#008000";
148
+ case "failure":
149
+ return "#ff0000";
150
+ case "cancelled":
151
+ return "#0047ab";
152
+ case "skipped":
153
+ return "#808080";
154
+ default:
155
+ return from;
156
+ }
157
+ }
158
+ };
159
+ function isColor(color) {
160
+ return color != null && color instanceof Color;
161
+ }
162
+ function isColorOptions(color) {
163
+ return color != null;
164
+ }
165
+ function identifyColorCommon(findings, prop, none, unknown, color) {
166
+ if (color.none != null && findings.findByProperty(prop, none) != null) {
167
+ return color.none.value;
168
+ }
169
+ if (color.unknown != null && findings.findByProperty(prop, unknown) != null) {
170
+ return color.unknown.value;
171
+ }
172
+ if (color.empty != null && findings.length === 0) {
173
+ return color.empty.value;
174
+ }
175
+ return void 0;
176
+ }
177
+ function identifyColorBySeverity(findings, color) {
178
+ if (color.critical != null && findings.findByProperty("severity", 5 /* Critical */) != null) {
179
+ return color.critical.value;
180
+ }
181
+ if (color.high != null && findings.findByProperty("severity", 4 /* High */) != null) {
182
+ return color.high.value;
183
+ }
184
+ if (color.medium != null && findings.findByProperty("severity", 3 /* Medium */) != null) {
185
+ return color.medium.value;
186
+ }
187
+ if (color.low != null && findings.findByProperty("severity", 2 /* Low */) != null) {
188
+ return color.low.value;
189
+ }
190
+ return identifyColorCommon(findings, "severity", 1 /* None */, 0 /* Unknown */, color);
191
+ }
192
+ function identifyColorByLevel(findings, color) {
193
+ if (color.error != null && findings.findByProperty("level", 4 /* Error */) != null) {
194
+ return color.error.value;
195
+ }
196
+ if (color.warning != null && findings.findByProperty("level", 3 /* Warning */) != null) {
197
+ return color.warning.value;
198
+ }
199
+ if (color.note != null && findings.findByProperty("level", 2 /* Note */) != null) {
200
+ return color.note.value;
201
+ }
202
+ return identifyColorCommon(findings, "level", 1 /* None */, 0 /* Unknown */, color);
203
+ }
204
+ function identifyColor(findings, color) {
205
+ if (color == null) {
206
+ return void 0;
207
+ }
208
+ if (isColor(color)) {
209
+ return color.value;
210
+ }
211
+ if (isColorOptions(color)) {
212
+ if (color.bySeverity != null) {
213
+ return identifyColorBySeverity(findings, color.bySeverity);
214
+ }
215
+ if (color.byLevel != null) {
216
+ return identifyColorByLevel(findings, color.byLevel);
217
+ }
218
+ }
219
+ return void 0;
220
+ }
221
+
222
+ // src/SarifToSlackClient.ts
223
+ var import_fs2 = require("fs");
74
224
 
75
225
  // src/Logger.ts
226
+ var import_tslog = require("tslog");
76
227
  var Logger = class _Logger {
77
228
  static DEFAULT_LOG_LEVEL = 3 /* Info */;
78
229
  static DEFAULT_LOG_TEMPLATE = "[{{logLevelName}}] [{{name}}] {{dateIsoStr}} ";
@@ -99,345 +250,40 @@ var Logger = class _Logger {
99
250
  static debug(...args) {
100
251
  _Logger.instance.debug(...args);
101
252
  }
102
- };
103
-
104
- // src/Processors.ts
105
- var fs = __toESM(require("fs"));
106
- var path = __toESM(require("path"));
107
- function processColor(color) {
108
- switch (color) {
109
- case "success":
110
- Logger.info(`Converting "${color}" to #008000`);
111
- return "#008000";
112
- case "failure":
113
- Logger.info(`Converting "${color}" to #ff0000`);
114
- return "#ff0000";
115
- case "cancelled":
116
- Logger.info(`Converting "${color}" to #0047ab`);
117
- return "#0047ab";
118
- case "skipped":
119
- Logger.info(`Converting "${color}" to #808080`);
120
- return "#808080";
121
- default:
122
- Logger.debug(`"${color}" color is not a CI status identifier. Returning as is.`);
123
- return color;
253
+ static trace(...args) {
254
+ _Logger.instance.trace(...args);
124
255
  }
125
- }
126
- function processSarifPath(sarifPath) {
127
- if (!fs.existsSync(sarifPath)) {
128
- throw new Error(`"sarif-path" does not exist: ${sarifPath}`);
129
- }
130
- const sarifStats = fs.statSync(sarifPath);
131
- if (sarifStats.isDirectory()) {
132
- Logger.info(`"sarif-path" is a directory: ${sarifPath}`);
133
- const files = fs.readdirSync(sarifPath);
134
- const filteredFiles = files.filter(
135
- (file) => path.extname(file).toLowerCase() === ".sarif"
136
- );
137
- Logger.info(`Found ${filteredFiles.length} SARIF files in ${sarifPath} directory`);
138
- Logger.debug(`Filtered SARIF files: ${filteredFiles.join(", ")}`);
139
- return filteredFiles.map((file) => path.join(sarifPath, file));
140
- }
141
- if (sarifStats.isFile()) {
142
- Logger.info(`"sarif-path" is a file: ${sarifPath}`);
143
- return [sarifPath];
144
- }
145
- throw new Error(`"sarif-path" is neither a file nor a directory: ${sarifPath}`);
146
- }
256
+ };
147
257
 
148
258
  // src/SlackMessageBuilder.ts
149
259
  var import_webhook = require("@slack/webhook");
150
260
 
151
- // src/metadata.ts
152
- var LIB_VERSION = "0.2.5";
153
-
154
- // src/model/SarifModelPerSarif.ts
155
- var import_immutable2 = require("immutable");
156
-
157
- // src/utils/SarifUtils.ts
158
- function findToolComponentByResult(run, result) {
159
- let tool;
160
- if (result.rule?.toolComponent?.index != null) {
161
- tool = run.tool.extensions?.[result.rule.toolComponent.index];
162
- }
163
- if (!tool) {
164
- tool = run.tool.driver;
165
- }
166
- return tool;
167
- }
168
- function findRuleByResult(run, result) {
169
- const ruleData = {};
170
- if (result.rule) {
171
- if (result.rule?.index != null) {
172
- ruleData.index = result.rule.index;
173
- }
174
- if (result.rule?.id) {
175
- ruleData.id = result.rule.id;
176
- }
177
- }
178
- if (ruleData.index == null && result.ruleIndex != null) {
179
- ruleData.index = result.ruleIndex;
180
- }
181
- if (!ruleData.id && result.ruleId) {
182
- ruleData.id = result.ruleId;
183
- }
184
- const tool = findToolComponentByResult(run, result);
185
- if (ruleData.index != null && tool?.rules && ruleData.index < tool.rules.length) {
186
- return tool.rules[ruleData.index];
187
- }
188
- if (ruleData.id && tool?.rules) {
189
- return tool.rules.find(
190
- (r) => r.id === ruleData.id
191
- );
192
- }
193
- return void 0;
194
- }
195
- function tryGetRulePropertyByResult(run, result, propertyName) {
196
- const rule = findRuleByResult(run, result);
197
- if (rule && rule.properties && propertyName in rule.properties) {
198
- return rule.properties[propertyName];
199
- }
200
- return void 0;
201
- }
202
-
203
- // src/model/types.ts
204
- var SecuritySeverityOrder = [
205
- "Critical" /* Critical */,
206
- "High" /* High */,
207
- "Medium" /* Medium */,
208
- "Low" /* Low */,
209
- "None" /* None */,
210
- "Unknown" /* Unknown */
211
- ];
212
- var SecurityLevelOrder = [
213
- "Error" /* Error */,
214
- "Warning" /* Warning */,
215
- "Note" /* Note */,
216
- "Unknown" /* Unknown */
217
- ];
218
-
219
- // src/model/SarifModelPerRun.ts
220
- var import_immutable = require("immutable");
221
-
222
- // src/utils/SortUtils.ts
223
- function sortSecurityLevelMap(map) {
224
- return map.sortBy(
225
- (_, level) => level,
226
- (a, b) => SecurityLevelOrder.indexOf(a) - SecurityLevelOrder.indexOf(b)
227
- ).asImmutable();
228
- }
229
- function sortSecuritySeverityMap(map) {
230
- return map.sortBy(
231
- (_, severity) => severity,
232
- (a, b) => SecuritySeverityOrder.indexOf(a) - SecuritySeverityOrder.indexOf(b)
233
- ).asImmutable();
234
- }
235
-
236
- // src/model/SarifModelPerRun.ts
237
- var SarifModelPerRun = class {
238
- toolName;
239
- _securitySeverityMap;
240
- _securityLevelMap;
241
- constructor(run) {
242
- this.toolName = run.tool.driver.name;
243
- this._securitySeverityMap = (0, import_immutable.Map)().asMutable();
244
- this._securityLevelMap = (0, import_immutable.Map)().asMutable();
245
- this.buildSecuritySeverityMap(run);
246
- this.buildSecurityLevelMap(run);
247
- }
248
- identifySecuritySeverity(score) {
249
- if (score === void 0) {
250
- return "Unknown" /* Unknown */;
251
- }
252
- if (score >= 9 && score <= 10) {
253
- return "Critical" /* Critical */;
254
- }
255
- if (score >= 7) {
256
- return "High" /* High */;
257
- }
258
- if (score >= 4) {
259
- return "Medium" /* Medium */;
260
- }
261
- if (score >= 0.1) {
262
- return "Low" /* Low */;
263
- }
264
- if (score == 0) {
265
- return "None" /* None */;
266
- }
267
- Logger.warn(`Unsupported "${score}" security severity. Saving as "Unknown".`);
268
- return "Unknown" /* Unknown */;
269
- }
270
- identifySecurityLevel(level) {
271
- if (level === void 0) {
272
- return "Unknown" /* Unknown */;
273
- }
274
- if (level.toLowerCase() === "error") {
275
- return "Error" /* Error */;
276
- }
277
- if (level.toLowerCase() === "warning") {
278
- return "Warning" /* Warning */;
279
- }
280
- if (level.toLowerCase() === "note") {
281
- return "Note" /* Note */;
282
- }
283
- Logger.warn(`Unsupported ${level} security level. Saving as "Unknown".`);
284
- return "Unknown" /* Unknown */;
285
- }
286
- buildSecuritySeverityMap(run) {
287
- const results = run.results ?? [];
288
- for (const result of results) {
289
- const severity = this.identifySecuritySeverity(
290
- tryGetRulePropertyByResult(run, result, "security-severity")
291
- );
292
- const count = this._securitySeverityMap.get(severity) || 0;
293
- this._securitySeverityMap.set(severity, count + 1);
294
- }
295
- }
296
- tryGetSecurityLevel(run, result) {
297
- if (result.level) {
298
- return result.level;
299
- }
300
- return tryGetRulePropertyByResult(run, result, "problem.severity");
301
- }
302
- buildSecurityLevelMap(run) {
303
- const results = run.results ?? [];
304
- for (const result of results) {
305
- const level = this.identifySecurityLevel(
306
- this.tryGetSecurityLevel(run, result)
307
- );
308
- const count = this._securityLevelMap.get(level) || 0;
309
- this._securityLevelMap.set(level, count + 1);
310
- }
311
- }
312
- get securitySeverityMap() {
313
- return sortSecuritySeverityMap(this._securitySeverityMap);
314
- }
315
- get securityLevelMap() {
316
- return sortSecurityLevelMap(this._securityLevelMap);
317
- }
318
- };
319
-
320
- // src/model/SarifModelPerSarif.ts
321
- var SarifModelPerSarif = class {
322
- sarifModelPerRunList;
323
- constructor(sarif) {
324
- this.sarifModelPerRunList = new Array();
325
- this.buildRunsList(sarif);
326
- }
327
- buildRunsList(sarif) {
328
- for (const run of sarif.runs) {
329
- this.sarifModelPerRunList.push(new SarifModelPerRun(run));
330
- }
331
- }
332
- groupByToolNameWithSecurityLevel() {
333
- const result = /* @__PURE__ */ new Map();
334
- for (const sarifModelPerRun of this.sarifModelPerRunList) {
335
- if (!result.has(sarifModelPerRun.toolName)) {
336
- result.set(sarifModelPerRun.toolName, (0, import_immutable2.Map)().asMutable());
337
- }
338
- for (const [k, v] of sarifModelPerRun.securityLevelMap.entries()) {
339
- const count = result.get(sarifModelPerRun.toolName)?.get(k) || 0;
340
- result.get(sarifModelPerRun.toolName)?.set(k, count + v);
341
- }
342
- }
343
- for (const [k, v] of result) {
344
- result.set(k, sortSecurityLevelMap(v));
345
- }
346
- return result;
347
- }
348
- groupByRunWithSecurityLevel() {
349
- const result = new Array();
350
- for (const sarifModelPerRun of this.sarifModelPerRunList) {
351
- result.push({
352
- toolName: sarifModelPerRun.toolName,
353
- data: sarifModelPerRun.securityLevelMap
354
- });
355
- }
356
- return result;
357
- }
358
- groupByTotalWithSecurityLevel() {
359
- const result = (0, import_immutable2.Map)().asMutable();
360
- for (const sarifModelPerRun of this.sarifModelPerRunList) {
361
- for (const [k, v] of sarifModelPerRun.securityLevelMap.entries()) {
362
- const count = result.get(k) || 0;
363
- result.set(k, count + v);
364
- }
365
- }
366
- return sortSecurityLevelMap(result);
367
- }
368
- groupByToolNameWithSecuritySeverity() {
369
- const result = /* @__PURE__ */ new Map();
370
- for (const sarifModelPerRun of this.sarifModelPerRunList) {
371
- if (!result.has(sarifModelPerRun.toolName)) {
372
- result.set(sarifModelPerRun.toolName, (0, import_immutable2.Map)().asMutable());
373
- }
374
- for (const [k, v] of sarifModelPerRun.securitySeverityMap.entries()) {
375
- const count = result.get(sarifModelPerRun.toolName)?.get(k) || 0;
376
- result.get(sarifModelPerRun.toolName)?.set(k, count + v);
377
- }
378
- }
379
- for (const [k, v] of result.entries()) {
380
- result.set(k, sortSecuritySeverityMap(v));
381
- }
382
- return result;
383
- }
384
- groupByRunWithSecuritySeverity() {
385
- const result = new Array();
386
- for (const sarifModelPerRun of this.sarifModelPerRunList) {
387
- result.push({
388
- toolName: sarifModelPerRun.toolName,
389
- data: sarifModelPerRun.securitySeverityMap
390
- });
391
- }
392
- return result;
393
- }
394
- groupByTotalWithSecuritySeverity() {
395
- const result = (0, import_immutable2.Map)().asMutable();
396
- for (const sarifModelPerRun of this.sarifModelPerRunList) {
397
- for (const [k, v] of sarifModelPerRun.securitySeverityMap.entries()) {
398
- const count = result.get(k) || 0;
399
- result.set(k, count + v);
400
- }
401
- }
402
- return sortSecuritySeverityMap(result);
403
- }
404
- listToolNames() {
405
- const toolNames = /* @__PURE__ */ new Set();
406
- for (const sarifModelPerRun of this.sarifModelPerRunList) {
407
- toolNames.add(sarifModelPerRun.toolName);
408
- }
409
- return toolNames;
410
- }
411
- };
261
+ // src/metadata.json
262
+ var version = "1.0.0";
263
+ var sha = "ecb376dd9ebf5c0364498348436504722dc73e74";
264
+ var buildAt = "2025-08-15T04:39:16Z";
412
265
 
413
266
  // src/SlackMessageBuilder.ts
414
267
  var SlackMessageBuilder = class {
415
- webhook;
416
- gitHubServerUrl;
417
- color;
418
- sarifModelPerSarif;
419
- output;
420
- header;
421
- footer;
422
- actor;
423
- runId;
424
- sarif;
268
+ _webhook;
269
+ _gitHubServerUrl;
270
+ _color;
271
+ _representation;
272
+ _header;
273
+ _footer;
274
+ _actor;
275
+ _runId;
425
276
  constructor(url, opts) {
426
- this.webhook = new import_webhook.IncomingWebhook(url, {
277
+ this._webhook = new import_webhook.IncomingWebhook(url, {
427
278
  username: opts.username || "SARIF results",
428
279
  icon_url: opts.iconUrl
429
280
  });
430
- this.gitHubServerUrl = process.env.GITHUB_SERVER_URL || "https://github.com";
431
- this.color = opts.color;
432
- this.sarif = opts.sarif;
433
- this.sarifModelPerSarif = new SarifModelPerSarif(opts.sarif);
434
- this.output = opts.output || {
435
- groupBy: 0 /* ToolName */,
436
- calculateBy: 0 /* Level */
437
- };
281
+ this._gitHubServerUrl = process.env.GITHUB_SERVER_URL || "https://github.com";
282
+ this._color = opts.color;
283
+ this._representation = opts.representation;
438
284
  }
439
285
  withHeader(header) {
440
- this.header = {
286
+ this._header = {
441
287
  type: "header",
442
288
  text: {
443
289
  type: "plain_text",
@@ -446,23 +292,23 @@ var SlackMessageBuilder = class {
446
292
  };
447
293
  }
448
294
  withActor(actor) {
449
- this.actor = actor || process.env.GITHUB_ACTOR;
295
+ this._actor = actor || process.env.GITHUB_ACTOR;
450
296
  }
451
297
  withRun() {
452
- this.runId = process.env.GITHUB_RUN_ID;
298
+ this._runId = process.env.GITHUB_RUN_ID;
453
299
  }
454
300
  withFooter(text, type) {
455
301
  const repoName = "fabasoad/sarif-to-slack";
456
- const element = text ? { type: type || "plain_text" /* PlainText */, text } : { type: "mrkdwn" /* Markdown */, text: `Generated by <${this.gitHubServerUrl}/${repoName}|@${repoName}@${LIB_VERSION}>` };
457
- this.footer = {
302
+ const element = text ? { type: type || "plain_text" /* PlainText */, text } : { type: "mrkdwn" /* Markdown */, text: `Generated by <${this._gitHubServerUrl}/${repoName}|@${repoName}@${version}>` };
303
+ this._footer = {
458
304
  type: "context",
459
305
  elements: [element]
460
306
  };
461
307
  }
462
308
  async send() {
463
309
  const blocks = [];
464
- if (this.header) {
465
- blocks.push(this.header);
310
+ if (this._header) {
311
+ blocks.push(this._header);
466
312
  }
467
313
  blocks.push({
468
314
  type: "section",
@@ -471,181 +317,703 @@ var SlackMessageBuilder = class {
471
317
  text: this.buildText()
472
318
  }
473
319
  });
474
- if (this.footer) {
475
- blocks.push(this.footer);
320
+ if (this._footer) {
321
+ blocks.push(this._footer);
476
322
  }
477
- const { text } = await this.webhook.send({
478
- attachments: [{ color: this.color, blocks }]
323
+ const { text } = await this._webhook.send({
324
+ attachments: [{ color: this._color, blocks }]
479
325
  });
480
326
  return text;
481
327
  }
482
328
  buildText() {
483
329
  const text = [];
484
- if (this.actor) {
485
- const actorUrl = `${this.gitHubServerUrl}/${this.actor}`;
486
- text.push(`_Triggered by <${actorUrl}|${this.actor}>_`);
330
+ if (this._actor) {
331
+ const actorUrl = `${this._gitHubServerUrl}/${this._actor}`;
332
+ text.push(`_Triggered by <${actorUrl}|${this._actor}>_`);
487
333
  }
488
- text.push(this.composeSummary());
489
- if (this.runId) {
334
+ text.push(this._representation.compose());
335
+ if (this._runId) {
490
336
  let runText = "Job ";
491
337
  if (process.env.GITHUB_REPOSITORY) {
492
- runText += `<${this.gitHubServerUrl}/${process.env.GITHUB_REPOSITORY}/actions/runs/${this.runId}|#${this.runId}>`;
338
+ runText += `<${this._gitHubServerUrl}/${process.env.GITHUB_REPOSITORY}/actions/runs/${this._runId}|#${this._runId}>`;
493
339
  } else {
494
- runText += `#${this.runId}`;
340
+ runText += `#${this._runId}`;
495
341
  }
496
342
  text.push(runText);
497
343
  }
498
344
  return text.join("\n\n");
499
345
  }
500
- composeSummaryWith(map, resultProcessor = (result) => result) {
501
- const stats = new Array();
502
- for (const [key, count] of map.entries()) {
503
- stats.push(`*${key}*: ${count}`);
504
- }
505
- return resultProcessor(
506
- stats.length == 0 ? "No issues found" : stats.join(", ")
507
- );
508
- }
509
- composeSummary() {
510
- const summaries = new Array();
511
- switch (this.output.groupBy) {
512
- case 0 /* ToolName */: {
513
- const dataGroupedByToolName = this.output.calculateBy === 0 /* Level */ ? this.sarifModelPerSarif.groupByToolNameWithSecurityLevel() : this.sarifModelPerSarif.groupByToolNameWithSecuritySeverity();
514
- for (const [toolName, map] of dataGroupedByToolName.entries()) {
515
- summaries.push(this.composeSummaryWith(
516
- map,
517
- (result) => `*${toolName}*
518
- ${result}`
519
- ));
520
- }
521
- break;
346
+ };
347
+
348
+ // src/System.ts
349
+ var System = class {
350
+ static initialize() {
351
+ Logger.info(`@fabasoad/sarif-to-slack version: ${version}`);
352
+ Logger.info(`@fabasoad/sarif-to-slack sha: ${sha}`);
353
+ Logger.info(`@fabasoad/sarif-to-slack built at: ${buildAt}`);
354
+ }
355
+ };
356
+
357
+ // src/utils/FileUtils.ts
358
+ var import_fs = __toESM(require("fs"));
359
+ var path = __toESM(require("path"));
360
+ function listFilesRecursively(dir, extension, fileList = []) {
361
+ const entries = import_fs.default.readdirSync(dir);
362
+ entries.forEach((entry) => {
363
+ const fullPath = path.join(dir, entry);
364
+ if (import_fs.default.statSync(fullPath).isDirectory()) {
365
+ listFilesRecursively(fullPath, extension, fileList);
366
+ } else if (path.extname(fullPath).toLowerCase() === `.${extension}`) {
367
+ fileList.push(fullPath);
368
+ }
369
+ });
370
+ return fileList;
371
+ }
372
+ function extractListOfFiles(opts) {
373
+ if (!import_fs.default.existsSync(opts.path)) {
374
+ throw new Error(`Provided path does not exist: ${opts.path}`);
375
+ }
376
+ const stats = import_fs.default.statSync(opts.path);
377
+ if (stats.isDirectory()) {
378
+ Logger.info(`Provided path is a directory: ${opts.path}`);
379
+ const files = opts.recursive && listFilesRecursively(opts.path, opts.extension ?? "sarif") || import_fs.default.readdirSync(opts.path);
380
+ Logger.info(`Found ${files.length} files in ${opts.path} directory with ${opts.extension} extension`);
381
+ Logger.debug(`Found files: ${files.join(", ")}`);
382
+ return files;
383
+ }
384
+ if (stats.isFile()) {
385
+ Logger.info(`Provided path is a file: ${opts.path}`);
386
+ return [opts.path];
387
+ }
388
+ throw new Error(`Provided path is neither a file nor a directory: ${opts.path}`);
389
+ }
390
+
391
+ // src/utils/Comparators.ts
392
+ function findingsComparatorByKey(key) {
393
+ return (a, b) => {
394
+ switch (key) {
395
+ case "severity":
396
+ return b.severity - a.severity;
397
+ case "level":
398
+ return b.level - a.level;
399
+ case "runId":
400
+ return a.runId - b.runId;
401
+ case "toolName":
402
+ return a.toolName.toLowerCase().localeCompare(b.toolName.toLowerCase());
403
+ default:
404
+ return 1;
405
+ }
406
+ };
407
+ }
408
+
409
+ // src/utils/ExtendedArray.ts
410
+ var ExtendedArray = class extends Array {
411
+ findByProperty(prop, value) {
412
+ return this.find((v) => v[prop] === value);
413
+ }
414
+ };
415
+
416
+ // src/model/FindingsArray.ts
417
+ var FindingsArray = class extends ExtendedArray {
418
+ hasSeverityOrHigher(severity) {
419
+ return Object.values(SecuritySeverity).filter((v) => typeof v === "number").filter((v) => v >= severity).some((v) => this.findByProperty("severity", v) != null);
420
+ }
421
+ hasLevelOrHigher(level) {
422
+ return Object.values(SecurityLevel).filter((v) => typeof v === "number").filter((v) => v >= level).some((v) => this.findByProperty("level", v) != null);
423
+ }
424
+ };
425
+
426
+ // src/representations/Representation.ts
427
+ var Representation = class {
428
+ _model;
429
+ constructor(model, findingSortKey = "level") {
430
+ this._model = model;
431
+ this._model.findings = model.findings.map((f) => f.clone()).sort(findingsComparatorByKey(findingSortKey)).reduce((arr, f) => {
432
+ arr.push(f);
433
+ return arr;
434
+ }, new FindingsArray());
435
+ }
436
+ bold(text) {
437
+ return `*${text}*`;
438
+ }
439
+ italic(text) {
440
+ return `_${text}_`;
441
+ }
442
+ };
443
+
444
+ // src/representations/CompactGroupByRepresentation.ts
445
+ var NO_VULNS_FOUND_TEXT = "No vulnerabilities found";
446
+ var CompactGroupByRepresentation = class extends Representation {
447
+ composeByProperty(key) {
448
+ const grouped = this.groupFindings();
449
+ if (grouped.size === 0) {
450
+ return NO_VULNS_FOUND_TEXT;
451
+ }
452
+ return Array.from(grouped).map(([title, findings]) => {
453
+ findings.sort(findingsComparatorByKey(key));
454
+ const summary = findings.length === 0 ? NO_VULNS_FOUND_TEXT : this.composeCompactReport(findings, key);
455
+ return `${title}
456
+ ${summary}`;
457
+ }).join("\n\n");
458
+ }
459
+ composeCompactReport(findings, key) {
460
+ return Object.entries(Object.groupBy(findings, (f) => f[key])).map(([prop, findings2]) => {
461
+ if (findings2 == null) {
462
+ return void 0;
522
463
  }
523
- case 1 /* Run */: {
524
- const dataGroupedByRun = this.output.calculateBy === 0 /* Level */ ? this.sarifModelPerSarif.groupByRunWithSecurityLevel() : this.sarifModelPerSarif.groupByRunWithSecuritySeverity();
525
- for (let i = 0; i < dataGroupedByRun.length; i++) {
526
- const { data, toolName } = dataGroupedByRun[i];
527
- summaries.push(this.composeSummaryWith(
528
- data,
529
- (result) => `_[Run ${i + 1}]_: *${toolName}*
530
- ${result}`
531
- ));
532
- }
533
- break;
464
+ return `${this.bold(this.extractEnumValue(key, prop))}: ${findings2.length}`;
465
+ }).filter((v) => v != null).join(", ");
466
+ }
467
+ extractEnumValue(key, prop) {
468
+ switch (key) {
469
+ case "level":
470
+ return SecurityLevel[Number(prop)];
471
+ case "severity":
472
+ return SecuritySeverity[Number(prop)];
473
+ default:
474
+ throw new Error("Unknown property:", key);
475
+ }
476
+ }
477
+ };
478
+
479
+ // src/representations/CompactGroupByRunRepresentation.ts
480
+ var CompactGroupByRunRepresentation = class extends CompactGroupByRepresentation {
481
+ constructor(model) {
482
+ super(model, "runId");
483
+ }
484
+ groupFindings() {
485
+ const result = /* @__PURE__ */ new Map();
486
+ for (const run of this._model.runs) {
487
+ const key = this.composeGroupTitle(run.id, run.toolName);
488
+ if (result.get(key) == null) {
489
+ result.set(key, []);
534
490
  }
535
- default: {
536
- const dataTotal = this.output.calculateBy === 0 /* Level */ ? this.sarifModelPerSarif.groupByTotalWithSecurityLevel() : this.sarifModelPerSarif.groupByTotalWithSecuritySeverity();
537
- const toolNames = this.sarifModelPerSarif.listToolNames();
538
- summaries.push(this.composeSummaryWith(
539
- dataTotal,
540
- (result) => `*${Array.from(toolNames).join("*, *")}*
541
- ${result}`
542
- ));
543
- break;
491
+ this._model.findings.filter((f) => f.runId === run.id).forEach((f) => result.get(key)?.push(f));
492
+ }
493
+ return result;
494
+ }
495
+ composeGroupTitle(runId, toolName) {
496
+ return `${this.italic(`[Run ${runId}]`)} ${this.bold(toolName)}`;
497
+ }
498
+ };
499
+
500
+ // src/representations/CompactGroupByRunPerLevelRepresentation.ts
501
+ var CompactGroupByRunPerLevelRepresentation = class extends CompactGroupByRunRepresentation {
502
+ compose() {
503
+ return this.composeByProperty("level");
504
+ }
505
+ };
506
+
507
+ // src/representations/CompactGroupByRunPerSeverityRepresentation.ts
508
+ var CompactGroupByRunPerSeverityRepresentation = class extends CompactGroupByRunRepresentation {
509
+ compose() {
510
+ return this.composeByProperty("severity");
511
+ }
512
+ };
513
+
514
+ // src/representations/CompactGroupByToolNameRepresentation.ts
515
+ var CompactGroupByToolNameRepresentation = class extends CompactGroupByRepresentation {
516
+ constructor(model) {
517
+ super(model, "toolName");
518
+ }
519
+ groupFindings() {
520
+ const result = /* @__PURE__ */ new Map();
521
+ for (const run of this._model.runs) {
522
+ const key = this.composeGroupTitle(run.toolName);
523
+ if (result.get(key) == null) {
524
+ result.set(key, []);
544
525
  }
526
+ this._model.findings.filter((f) => f.runId === run.id).forEach((f) => result.get(key)?.push(f));
545
527
  }
546
- return summaries.join("\n\n");
528
+ return result;
529
+ }
530
+ composeGroupTitle(toolName) {
531
+ return this.bold(toolName);
547
532
  }
548
533
  };
549
534
 
550
- // src/System.ts
551
- var System = class {
552
- static initialize() {
553
- Logger.info(`Version: ${LIB_VERSION}`);
535
+ // src/representations/CompactGroupByToolNamePerLevelRepresentation.ts
536
+ var CompactGroupByToolNamePerLevelRepresentation = class extends CompactGroupByToolNameRepresentation {
537
+ compose() {
538
+ return this.composeByProperty("level");
554
539
  }
555
540
  };
556
541
 
557
- // src/SarifToSlackService.ts
558
- async function initialize(opts) {
559
- const slackMessages = /* @__PURE__ */ new Map();
560
- const sarifFiles = processSarifPath(opts.sarifPath);
561
- if (sarifFiles.length === 0) {
562
- throw new Error(`No SARIF files found at the provided path: ${opts.sarifPath}`);
542
+ // src/representations/CompactGroupByToolNamePerSeverityRepresentation.ts
543
+ var CompactGroupByToolNamePerSeverityRepresentation = class extends CompactGroupByToolNameRepresentation {
544
+ compose() {
545
+ return this.composeByProperty("severity");
563
546
  }
564
- for (const sarifFile of sarifFiles) {
565
- const jsonString = await import_fs.promises.readFile(sarifFile, "utf8");
566
- const messageBuilder = new SlackMessageBuilder(opts.webhookUrl, {
567
- username: opts.username,
568
- iconUrl: opts.iconUrl,
569
- color: processColor(opts.color),
570
- sarif: JSON.parse(jsonString),
571
- output: opts.output
572
- });
573
- if (opts.header?.include) {
574
- messageBuilder.withHeader(opts.header?.value);
547
+ };
548
+
549
+ // src/representations/CompactGroupBySarifRepresentation.ts
550
+ var import_node_path = __toESM(require("path"));
551
+ var CompactGroupBySarifRepresentation = class extends CompactGroupByRepresentation {
552
+ constructor(model) {
553
+ super(model, "sarifPath");
554
+ }
555
+ groupFindings() {
556
+ const result = /* @__PURE__ */ new Map();
557
+ for (let index = 0; index < this._model.sarifFiles.length; index++) {
558
+ const key = this.composeGroupTitle(this._model.sarifFiles[index], index);
559
+ if (result.get(key) == null) {
560
+ result.set(key, []);
561
+ }
562
+ this._model.findings.filter((f) => f.sarifPath === this._model.sarifFiles[index]).forEach((f) => result.get(key)?.push(f));
575
563
  }
576
- if (opts.footer?.include) {
577
- messageBuilder.withFooter(opts.footer?.value, opts.footer?.type);
564
+ return result;
565
+ }
566
+ composeGroupTitle(sarifPath, index) {
567
+ return `${this.italic(`[File ${index + 1}]`)} ${this.bold(import_node_path.default.basename(sarifPath))}`;
568
+ }
569
+ };
570
+
571
+ // src/representations/CompactGroupBySarifPerLevelRepresentation.ts
572
+ var CompactGroupBySarifPerLevelRepresentation = class extends CompactGroupBySarifRepresentation {
573
+ compose() {
574
+ return this.composeByProperty("level");
575
+ }
576
+ };
577
+
578
+ // src/representations/CompactGroupBySarifPerSeverityRepresentation.ts
579
+ var CompactGroupBySarifPerSeverityRepresentation = class extends CompactGroupBySarifRepresentation {
580
+ compose() {
581
+ return this.composeByProperty("severity");
582
+ }
583
+ };
584
+
585
+ // src/representations/CompactTotalRepresentation.ts
586
+ var CompactTotalRepresentation = class extends CompactGroupByRepresentation {
587
+ groupFindings() {
588
+ const result = /* @__PURE__ */ new Map();
589
+ if (this._model.findings.length > 0) {
590
+ result.set("Total", this._model.findings);
578
591
  }
579
- if (opts.actor?.include) {
580
- messageBuilder.withActor(opts.actor?.value);
592
+ return result;
593
+ }
594
+ };
595
+
596
+ // src/representations/CompactTotalPerSeverityRepresentation.ts
597
+ var CompactTotalPerSeverityRepresentation = class extends CompactTotalRepresentation {
598
+ compose() {
599
+ return this.composeByProperty("severity");
600
+ }
601
+ };
602
+
603
+ // src/representations/CompactTotalPerLevelRepresentation.ts
604
+ var CompactTotalPerLevelRepresentation = class extends CompactTotalRepresentation {
605
+ compose() {
606
+ return this.composeByProperty("level");
607
+ }
608
+ };
609
+
610
+ // src/representations/RepresentationFactory.ts
611
+ function createRepresentation(model, type = 3 /* CompactGroupByToolNamePerSeverity */) {
612
+ switch (type) {
613
+ case 0 /* CompactGroupByRunPerLevel */:
614
+ return new CompactGroupByRunPerLevelRepresentation(model);
615
+ case 1 /* CompactGroupByRunPerSeverity */:
616
+ return new CompactGroupByRunPerSeverityRepresentation(model);
617
+ case 2 /* CompactGroupByToolNamePerLevel */:
618
+ return new CompactGroupByToolNamePerLevelRepresentation(model);
619
+ case 3 /* CompactGroupByToolNamePerSeverity */:
620
+ return new CompactGroupByToolNamePerSeverityRepresentation(model);
621
+ case 4 /* CompactGroupBySarifPerLevel */:
622
+ return new CompactGroupBySarifPerLevelRepresentation(model);
623
+ case 5 /* CompactGroupBySarifPerSeverity */:
624
+ return new CompactGroupBySarifPerSeverityRepresentation(model);
625
+ case 6 /* CompactTotalPerLevel */:
626
+ return new CompactTotalPerLevelRepresentation(model);
627
+ case 7 /* CompactTotalPerSeverity */:
628
+ return new CompactTotalPerSeverityRepresentation(model);
629
+ default:
630
+ throw new Error(`Unknown representation type: ${type}`);
631
+ }
632
+ }
633
+
634
+ // src/utils/SarifUtils.ts
635
+ function findToolComponentDriver(run) {
636
+ return run.tool.driver;
637
+ }
638
+ function tryFindToolComponentExtension(run, result) {
639
+ let tool;
640
+ if (result.rule?.toolComponent?.index != null) {
641
+ tool = run.tool.extensions?.[result.rule.toolComponent.index];
642
+ }
643
+ return tool;
644
+ }
645
+ function findToolComponent(run, result) {
646
+ return tryFindToolComponentExtension(run, result) ?? findToolComponentDriver(run);
647
+ }
648
+
649
+ // src/processors/CommonProcessor.ts
650
+ var CommonProcessor = class {
651
+ _run;
652
+ _result;
653
+ /**
654
+ * Creates an instance of {@link CommonProcessor} class.
655
+ * @param run An instance of {@link Run} object.
656
+ * @param result An instance of {@link Result} object.
657
+ */
658
+ constructor(run, result) {
659
+ this._run = run;
660
+ this._result = result;
661
+ }
662
+ tryFindCvssScore() {
663
+ return this.tryFindRuleProperty("security-severity");
664
+ }
665
+ tryFindLevel() {
666
+ return this._result.level ?? this.tryFindRule()?.defaultConfiguration?.level;
667
+ }
668
+ findToolComponentDriver() {
669
+ return findToolComponentDriver(this._run);
670
+ }
671
+ tryFindToolComponentExtension() {
672
+ return tryFindToolComponentExtension(this._run, this._result);
673
+ }
674
+ findToolComponent() {
675
+ return findToolComponent(this._run, this._result);
676
+ }
677
+ /**
678
+ * This function tries to find the respective rule for the given result.
679
+ * @internal
680
+ */
681
+ tryFindRule() {
682
+ const ruleData = {};
683
+ if (this._result.rule) {
684
+ if (this._result.rule?.index != null) {
685
+ ruleData.index = this._result.rule.index;
686
+ }
687
+ if (this._result.rule?.id) {
688
+ ruleData.id = this._result.rule.id;
689
+ }
581
690
  }
582
- if (opts.run?.include) {
583
- messageBuilder.withRun();
691
+ if (ruleData.index == null && this._result.ruleIndex != null) {
692
+ ruleData.index = this._result.ruleIndex;
693
+ }
694
+ if (!ruleData.id && this._result.ruleId) {
695
+ ruleData.id = this._result.ruleId;
696
+ }
697
+ const tool = this.findToolComponent();
698
+ if (ruleData.index != null && tool?.rules && ruleData.index < tool.rules.length) {
699
+ return tool.rules[ruleData.index];
584
700
  }
585
- slackMessages.set(sarifFile, messageBuilder);
701
+ if (ruleData.id && tool?.rules) {
702
+ return tool.rules.find(
703
+ (r) => r.id === ruleData.id
704
+ );
705
+ }
706
+ return void 0;
586
707
  }
587
- return slackMessages;
588
- }
589
- var SarifToSlackService = class _SarifToSlackService {
590
- _slackMessages;
591
- constructor() {
592
- this._slackMessages = /* @__PURE__ */ new Map();
708
+ /**
709
+ * This function searches respective rule for the given result, and then gets
710
+ * the property of interest from it.
711
+ * @param propertyName The property name that you want to get the value from.
712
+ * @protected
713
+ */
714
+ tryFindRuleProperty(propertyName) {
715
+ const rule = this.tryFindRule();
716
+ if (rule?.properties && propertyName in rule.properties) {
717
+ return rule.properties[propertyName];
718
+ }
719
+ return void 0;
593
720
  }
721
+ };
722
+
723
+ // src/processors/SnykProcessor.ts
724
+ var SnykProcessor = class extends CommonProcessor {
594
725
  /**
595
- * Gets the Slack messages prepared for each SARIF file.
596
- * @returns A read-only map where keys are SARIF file paths and values are SlackMessage instances.
597
- * @public
726
+ * Rules in SARIF files produced by Snyk Open Source has additional "cvssv3_baseScore"
727
+ * property where CVSS score is also defined. This method tries to get level
728
+ * from this "cvssv3_baseScore" property and if it fails to do so, then it tries
729
+ * to get CVSS score in a common way.
598
730
  */
599
- get slackMessages() {
600
- return this._slackMessages;
731
+ tryFindCvssScore() {
732
+ return this.tryFindRuleProperty("cvssv3_baseScore") ?? super.tryFindCvssScore();
601
733
  }
734
+ };
735
+
736
+ // src/processors/CodeQLProcessor.ts
737
+ var CodeQLProcessor = class extends CommonProcessor {
602
738
  /**
603
- * Creates an instance of SarifToSlackService.
604
- * @param opts - Options for the service, including webhook URL, SARIF path, and other configurations.
605
- * @returns A promise that resolves to an instance of SarifToSlackService.
606
- * @throws Error if no SARIF files are found at the provided path.
607
- * @public
739
+ * Rules in SARIF files produced by CodeQL has additional "problem.severity"
740
+ * property where level is also defined. This method tries to get level in a
741
+ * common way but if it fails to do so, then it tries to get level from
742
+ * "problem.severity" property.
608
743
  */
609
- static async create(opts) {
610
- Logger.initialize(opts.log);
744
+ tryFindLevel() {
745
+ return super.tryFindLevel() ?? this.tryFindRuleProperty("problem.severity");
746
+ }
747
+ };
748
+
749
+ // src/processors/ProcessorFactory.ts
750
+ function createProcessor(run, result) {
751
+ const toolComponent = findToolComponent(run, result);
752
+ switch (toolComponent.name) {
753
+ case "CodeQL":
754
+ return new CodeQLProcessor(run, result);
755
+ case "Snyk Open Source":
756
+ return new SnykProcessor(run, result);
757
+ default:
758
+ return new CommonProcessor(run, result);
759
+ }
760
+ }
761
+
762
+ // src/model/Finding.ts
763
+ function createFinding(opts) {
764
+ return new SarifFinding(opts);
765
+ }
766
+ var SarifFinding = class {
767
+ _runMetadata;
768
+ _result;
769
+ _sarifPath;
770
+ _rule;
771
+ _processor;
772
+ _cvssScoreCacheProcessed = false;
773
+ _cvssScoreCache = void 0;
774
+ _levelCacheProcessed = false;
775
+ _levelCache = void 0;
776
+ constructor(opts) {
777
+ this._processor = createProcessor(opts.runMetadata.run, opts.result);
778
+ this._sarifPath = opts.sarifPath;
779
+ this._runMetadata = opts.runMetadata;
780
+ this._result = opts.result;
781
+ this._rule = this._processor.tryFindRule();
782
+ }
783
+ clone() {
784
+ return createFinding({
785
+ sarifPath: this._sarifPath,
786
+ runMetadata: this._runMetadata,
787
+ result: this._result
788
+ });
789
+ }
790
+ get sarifPath() {
791
+ return this._sarifPath;
792
+ }
793
+ get runId() {
794
+ return this._runMetadata.id;
795
+ }
796
+ get toolName() {
797
+ return this._processor.findToolComponent().name;
798
+ }
799
+ get cvssScore() {
800
+ if (!this._cvssScoreCacheProcessed) {
801
+ this._cvssScoreCacheProcessed = true;
802
+ this._cvssScoreCache = this._processor.tryFindCvssScore();
803
+ }
804
+ return this._cvssScoreCache;
805
+ }
806
+ get level() {
807
+ if (!this._levelCacheProcessed) {
808
+ this._levelCacheProcessed = true;
809
+ this._levelCache = this._processor.tryFindLevel();
810
+ }
811
+ if (this._levelCache === void 0) {
812
+ Logger.debug(`Unknown level of ${this._rule?.id} rule`);
813
+ return 0 /* Unknown */;
814
+ }
815
+ switch (this._levelCache) {
816
+ case "error":
817
+ return 4 /* Error */;
818
+ case "warning":
819
+ return 3 /* Warning */;
820
+ case "note":
821
+ return 2 /* Note */;
822
+ default:
823
+ return 1 /* None */;
824
+ }
825
+ }
826
+ get severity() {
827
+ if (this.cvssScore == null || this.cvssScore < 0 || this.cvssScore > 10) {
828
+ Logger.debug(`Unsupported CVSS score ${this.cvssScore} in ${this._rule?.id} rule`);
829
+ return 0 /* Unknown */;
830
+ }
831
+ if (this.cvssScore >= 9) {
832
+ return 5 /* Critical */;
833
+ }
834
+ if (this.cvssScore >= 7) {
835
+ return 4 /* High */;
836
+ }
837
+ if (this.cvssScore >= 4) {
838
+ return 3 /* Medium */;
839
+ }
840
+ if (this.cvssScore >= 0.1) {
841
+ return 2 /* Low */;
842
+ }
843
+ return 1 /* None */;
844
+ }
845
+ };
846
+
847
+ // src/SarifToSlackClient.ts
848
+ var SarifToSlackClient = class _SarifToSlackClient {
849
+ _message;
850
+ _sarifModel;
851
+ _sendIf = 20 /* Always */;
852
+ constructor(log) {
853
+ Logger.initialize(log);
611
854
  System.initialize();
612
- const instance = new _SarifToSlackService();
613
- const map = await initialize(opts);
614
- map.forEach((val, key) => instance._slackMessages.set(key, val));
855
+ }
856
+ static *createRunIdGenerator() {
857
+ let runId = 1;
858
+ while (true) {
859
+ yield runId++;
860
+ }
861
+ }
862
+ static async create(opts) {
863
+ const instance = new _SarifToSlackClient(opts.log);
864
+ Logger.trace("opts", opts);
865
+ instance._sendIf = opts.sendIf ?? instance._sendIf;
866
+ instance._sarifModel = await _SarifToSlackClient.buildModel(opts.sarif);
867
+ Logger.trace("instance._sarifModel", instance._sarifModel);
868
+ instance._message = await _SarifToSlackClient.initialize(instance._sarifModel, opts);
869
+ Logger.trace("instance._message", instance._message);
615
870
  return instance;
616
871
  }
872
+ static async buildModel(sarifOpts) {
873
+ const sarifFiles = extractListOfFiles(sarifOpts);
874
+ if (sarifFiles.length === 0) {
875
+ throw new Error(`No SARIF files found at the provided path: ${sarifOpts.path}`);
876
+ }
877
+ const model = { sarifFiles, runs: [], findings: new FindingsArray() };
878
+ const runIdGenerator = _SarifToSlackClient.createRunIdGenerator();
879
+ for (const sarifPath of sarifFiles) {
880
+ const sarifJson = await import_fs2.promises.readFile(sarifPath, "utf8");
881
+ const sarifLog = JSON.parse(sarifJson);
882
+ for (const run of sarifLog.runs) {
883
+ const runId = runIdGenerator.next();
884
+ let runMetadata = void 0;
885
+ for (const result of run.results ?? []) {
886
+ runMetadata = {
887
+ id: runId.value,
888
+ run,
889
+ toolName: findToolComponent(run, result).name
890
+ };
891
+ model.findings.push(createFinding({ sarifPath, result, runMetadata }));
892
+ }
893
+ runMetadata ??= {
894
+ id: runId.value,
895
+ run,
896
+ toolName: findToolComponentDriver(run).name
897
+ };
898
+ model.runs.push(runMetadata);
899
+ }
900
+ }
901
+ return model;
902
+ }
617
903
  /**
618
- * Sends all prepared Slack messages.
619
- * @returns A promise that resolves when all messages have been sent.
620
- * @throws Error if a Slack message was not prepared for a SARIF path.
621
- * @public
904
+ * The main function to initialize a list of {@link SlackMessage} objects based
905
+ * on the given SARIF file(s).
906
+ * @param sarifModel An instance of {@link SarifModel} object.
907
+ * @param opts An instance of {@link SarifToSlackClientOptions} object.
908
+ * @returns A map where key is the SARIF file and value is an instance of
909
+ * {@link SlackMessage} object
910
+ * @private
622
911
  */
623
- async sendAll() {
624
- for (const sarifPath of this._slackMessages.keys()) {
625
- await this.send(sarifPath);
912
+ static async initialize(sarifModel, opts) {
913
+ const message = new SlackMessageBuilder(opts.webhookUrl, {
914
+ username: opts.username,
915
+ iconUrl: opts.iconUrl,
916
+ color: identifyColor(sarifModel.findings, opts.color),
917
+ representation: createRepresentation(sarifModel, opts.representation)
918
+ });
919
+ if (opts.header?.include) {
920
+ message.withHeader(opts.header?.value);
626
921
  }
922
+ if (opts.footer?.include) {
923
+ message.withFooter(opts.footer?.value, opts.footer?.type);
924
+ }
925
+ if (opts.actor?.include) {
926
+ message.withActor(opts.actor?.value);
927
+ }
928
+ if (opts.run?.include) {
929
+ message.withRun();
930
+ }
931
+ return message;
627
932
  }
628
933
  /**
629
- * Sends a Slack message for a specific SARIF path.
630
- * @param sarifPath - The path of the SARIF file for which the message should be sent.
934
+ * Sends a Slack message.
631
935
  * @returns A promise that resolves when the message has been sent.
632
936
  * @throws Error if a Slack message was not prepared for the given SARIF path.
633
937
  * @public
634
938
  */
635
- async send(sarifPath) {
636
- const message = this._slackMessages.get(sarifPath);
637
- if (!message) {
638
- throw new Error(`Slack message was not prepared for SARIF path: ${sarifPath}.`);
939
+ async send() {
940
+ if (this._sarifModel == null) {
941
+ throw new Error("Could not parse SARIF file(s).");
942
+ }
943
+ if (this.shouldSendMessage) {
944
+ if (this._message == null) {
945
+ throw new Error("Slack message was not prepared.");
946
+ }
947
+ const text = await this._message.send();
948
+ Logger.info("Message sent. Status:", text);
949
+ } else {
950
+ Logger.info("Message was not sent based on the sendIf parameter:", SendIf[this._sendIf]);
951
+ }
952
+ }
953
+ get shouldSendMessage() {
954
+ if (this._sendIf == null) {
955
+ return true;
956
+ }
957
+ switch (this._sendIf) {
958
+ case 0 /* SeverityCritical */:
959
+ return this._sarifModel?.findings.findByProperty("severity", 5 /* Critical */) != null;
960
+ case 1 /* SeverityHigh */:
961
+ return this._sarifModel?.findings.findByProperty("severity", 4 /* High */) != null;
962
+ case 2 /* SeverityHighOrHigher */:
963
+ return !!this._sarifModel?.findings.hasSeverityOrHigher(4 /* High */);
964
+ case 3 /* SeverityMedium */:
965
+ return this._sarifModel?.findings.findByProperty("severity", 3 /* Medium */) != null;
966
+ case 4 /* SeverityMediumOrHigher */:
967
+ return !!this._sarifModel?.findings.hasSeverityOrHigher(3 /* Medium */);
968
+ case 5 /* SeverityLow */:
969
+ return this._sarifModel?.findings.findByProperty("severity", 2 /* Low */) != null;
970
+ case 6 /* SeverityLowOrHigher */:
971
+ return !!this._sarifModel?.findings.hasSeverityOrHigher(2 /* Low */);
972
+ case 7 /* SeverityNone */:
973
+ return this._sarifModel?.findings.findByProperty("severity", 1 /* None */) != null;
974
+ case 8 /* SeverityNoneOrHigher */:
975
+ return !!this._sarifModel?.findings.hasSeverityOrHigher(1 /* None */);
976
+ case 9 /* SeverityUnknown */:
977
+ return this._sarifModel?.findings.findByProperty("severity", 0 /* Unknown */) != null;
978
+ case 10 /* SeverityUnknownOrHigher */:
979
+ return !!this._sarifModel?.findings.hasSeverityOrHigher(0 /* Unknown */);
980
+ case 11 /* LevelError */:
981
+ return this._sarifModel?.findings.findByProperty("level", 4 /* Error */) != null;
982
+ case 12 /* LevelWarning */:
983
+ return this._sarifModel?.findings.findByProperty("level", 3 /* Warning */) != null;
984
+ case 13 /* LevelWarningOrHigher */:
985
+ return !!this._sarifModel?.findings.hasLevelOrHigher(3 /* Warning */);
986
+ case 14 /* LevelNote */:
987
+ return this._sarifModel?.findings.findByProperty("level", 2 /* Note */) != null;
988
+ case 15 /* LevelNoteOrHigher */:
989
+ return !!this._sarifModel?.findings.hasLevelOrHigher(2 /* Note */);
990
+ case 16 /* LevelNone */:
991
+ return this._sarifModel?.findings.findByProperty("level", 1 /* None */) != null;
992
+ case 17 /* LevelNoneOrHigher */:
993
+ return !!this._sarifModel?.findings.hasLevelOrHigher(1 /* None */);
994
+ case 18 /* LevelUnknown */:
995
+ return this._sarifModel?.findings.findByProperty("level", 0 /* Unknown */) != null;
996
+ case 19 /* LevelUnknownOrHigher */:
997
+ return !!this._sarifModel?.findings.hasLevelOrHigher(0 /* Unknown */);
998
+ case 20 /* Always */:
999
+ return true;
1000
+ case 21 /* Some */:
1001
+ return (this._sarifModel?.findings.length ?? 0) > 0;
1002
+ case 22 /* Empty */:
1003
+ return (this._sarifModel?.findings.length ?? 0) === 0;
1004
+ case 23 /* Never */:
1005
+ return false;
1006
+ default:
1007
+ throw new Error(`Unknown sendIf parameter: ${this._sendIf}`);
639
1008
  }
640
- const text = await message.send();
641
- Logger.info(`Message sent for ${sarifPath} file. Status:`, text);
642
1009
  }
643
1010
  };
644
1011
  // Annotate the CommonJS export names for ESM import in node:
645
1012
  0 && (module.exports = {
646
- CalculateResultsBy,
1013
+ Color,
647
1014
  FooterType,
648
- GroupResultsBy,
649
1015
  LogLevel,
650
- SarifToSlackService
1016
+ RepresentationType,
1017
+ SarifToSlackClient,
1018
+ SendIf
651
1019
  });