@fabasoad/sarif-to-slack 0.2.5 → 1.1.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 +826 -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 +80 -0
  20. package/dist/model/Color.d.ts.map +1 -0
  21. package/dist/model/Color.js +106 -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 +347 -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 +162 -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 +195 -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,161 @@ 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 identifyColorCommon(findings, prop, none, unknown, color, defaultColor) {
160
+ if (color.none != null && findings.findByProperty(prop, none) != null) {
161
+ return color.none.value;
162
+ }
163
+ if (color.unknown != null && findings.findByProperty(prop, unknown) != null) {
164
+ return color.unknown.value;
165
+ }
166
+ if (color.empty != null && findings.length === 0) {
167
+ return color.empty.value;
168
+ }
169
+ return defaultColor?.value;
170
+ }
171
+ function identifyColorBySeverity(findings, color, defaultColor) {
172
+ if (color.critical != null && findings.findByProperty("severity", 5 /* Critical */) != null) {
173
+ return color.critical.value;
174
+ }
175
+ if (color.high != null && findings.findByProperty("severity", 4 /* High */) != null) {
176
+ return color.high.value;
177
+ }
178
+ if (color.medium != null && findings.findByProperty("severity", 3 /* Medium */) != null) {
179
+ return color.medium.value;
180
+ }
181
+ if (color.low != null && findings.findByProperty("severity", 2 /* Low */) != null) {
182
+ return color.low.value;
183
+ }
184
+ return identifyColorCommon(findings, "severity", 1 /* None */, 0 /* Unknown */, color, defaultColor);
185
+ }
186
+ function identifyColorByLevel(findings, color, defaultColor) {
187
+ if (color.error != null && findings.findByProperty("level", 4 /* Error */) != null) {
188
+ return color.error.value;
189
+ }
190
+ if (color.warning != null && findings.findByProperty("level", 3 /* Warning */) != null) {
191
+ return color.warning.value;
192
+ }
193
+ if (color.note != null && findings.findByProperty("level", 2 /* Note */) != null) {
194
+ return color.note.value;
195
+ }
196
+ return identifyColorCommon(findings, "level", 1 /* None */, 0 /* Unknown */, color, defaultColor);
197
+ }
198
+ function identifyColor(findings, colorOpts) {
199
+ if (colorOpts?.bySeverity != null) {
200
+ return identifyColorBySeverity(findings, colorOpts.bySeverity, colorOpts.default);
201
+ }
202
+ if (colorOpts?.byLevel != null) {
203
+ return identifyColorByLevel(findings, colorOpts.byLevel, colorOpts.default);
204
+ }
205
+ return colorOpts?.default?.value;
206
+ }
207
+
208
+ // src/SarifToSlackClient.ts
209
+ var import_fs2 = require("fs");
74
210
 
75
211
  // src/Logger.ts
212
+ var import_tslog = require("tslog");
76
213
  var Logger = class _Logger {
77
214
  static DEFAULT_LOG_LEVEL = 3 /* Info */;
78
215
  static DEFAULT_LOG_TEMPLATE = "[{{logLevelName}}] [{{name}}] {{dateIsoStr}} ";
@@ -99,345 +236,40 @@ var Logger = class _Logger {
99
236
  static debug(...args) {
100
237
  _Logger.instance.debug(...args);
101
238
  }
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;
239
+ static trace(...args) {
240
+ _Logger.instance.trace(...args);
124
241
  }
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
- }
242
+ };
147
243
 
148
244
  // src/SlackMessageBuilder.ts
149
245
  var import_webhook = require("@slack/webhook");
150
246
 
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
- };
247
+ // src/metadata.json
248
+ var version = "1.1.0";
249
+ var sha = "cf8ff099965ca704d7e58bd11f6d4481f69e3125";
250
+ var buildAt = "2025-08-15T05:22:37Z";
412
251
 
413
252
  // src/SlackMessageBuilder.ts
414
253
  var SlackMessageBuilder = class {
415
- webhook;
416
- gitHubServerUrl;
417
- color;
418
- sarifModelPerSarif;
419
- output;
420
- header;
421
- footer;
422
- actor;
423
- runId;
424
- sarif;
254
+ _webhook;
255
+ _gitHubServerUrl;
256
+ _color;
257
+ _representation;
258
+ _header;
259
+ _footer;
260
+ _actor;
261
+ _runId;
425
262
  constructor(url, opts) {
426
- this.webhook = new import_webhook.IncomingWebhook(url, {
263
+ this._webhook = new import_webhook.IncomingWebhook(url, {
427
264
  username: opts.username || "SARIF results",
428
265
  icon_url: opts.iconUrl
429
266
  });
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
- };
267
+ this._gitHubServerUrl = process.env.GITHUB_SERVER_URL || "https://github.com";
268
+ this._color = opts.color;
269
+ this._representation = opts.representation;
438
270
  }
439
271
  withHeader(header) {
440
- this.header = {
272
+ this._header = {
441
273
  type: "header",
442
274
  text: {
443
275
  type: "plain_text",
@@ -446,23 +278,23 @@ var SlackMessageBuilder = class {
446
278
  };
447
279
  }
448
280
  withActor(actor) {
449
- this.actor = actor || process.env.GITHUB_ACTOR;
281
+ this._actor = actor || process.env.GITHUB_ACTOR;
450
282
  }
451
283
  withRun() {
452
- this.runId = process.env.GITHUB_RUN_ID;
284
+ this._runId = process.env.GITHUB_RUN_ID;
453
285
  }
454
286
  withFooter(text, type) {
455
287
  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 = {
288
+ const element = text ? { type: type || "plain_text" /* PlainText */, text } : { type: "mrkdwn" /* Markdown */, text: `Generated by <${this._gitHubServerUrl}/${repoName}|@${repoName}@${version}>` };
289
+ this._footer = {
458
290
  type: "context",
459
291
  elements: [element]
460
292
  };
461
293
  }
462
294
  async send() {
463
295
  const blocks = [];
464
- if (this.header) {
465
- blocks.push(this.header);
296
+ if (this._header) {
297
+ blocks.push(this._header);
466
298
  }
467
299
  blocks.push({
468
300
  type: "section",
@@ -471,181 +303,703 @@ var SlackMessageBuilder = class {
471
303
  text: this.buildText()
472
304
  }
473
305
  });
474
- if (this.footer) {
475
- blocks.push(this.footer);
306
+ if (this._footer) {
307
+ blocks.push(this._footer);
476
308
  }
477
- const { text } = await this.webhook.send({
478
- attachments: [{ color: this.color, blocks }]
309
+ const { text } = await this._webhook.send({
310
+ attachments: [{ color: this._color, blocks }]
479
311
  });
480
312
  return text;
481
313
  }
482
314
  buildText() {
483
315
  const text = [];
484
- if (this.actor) {
485
- const actorUrl = `${this.gitHubServerUrl}/${this.actor}`;
486
- text.push(`_Triggered by <${actorUrl}|${this.actor}>_`);
316
+ if (this._actor) {
317
+ const actorUrl = `${this._gitHubServerUrl}/${this._actor}`;
318
+ text.push(`_Triggered by <${actorUrl}|${this._actor}>_`);
487
319
  }
488
- text.push(this.composeSummary());
489
- if (this.runId) {
320
+ text.push(this._representation.compose());
321
+ if (this._runId) {
490
322
  let runText = "Job ";
491
323
  if (process.env.GITHUB_REPOSITORY) {
492
- runText += `<${this.gitHubServerUrl}/${process.env.GITHUB_REPOSITORY}/actions/runs/${this.runId}|#${this.runId}>`;
324
+ runText += `<${this._gitHubServerUrl}/${process.env.GITHUB_REPOSITORY}/actions/runs/${this._runId}|#${this._runId}>`;
493
325
  } else {
494
- runText += `#${this.runId}`;
326
+ runText += `#${this._runId}`;
495
327
  }
496
328
  text.push(runText);
497
329
  }
498
330
  return text.join("\n\n");
499
331
  }
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;
332
+ };
333
+
334
+ // src/System.ts
335
+ var System = class {
336
+ static initialize() {
337
+ Logger.info(`@fabasoad/sarif-to-slack version: ${version}`);
338
+ Logger.info(`@fabasoad/sarif-to-slack sha: ${sha}`);
339
+ Logger.info(`@fabasoad/sarif-to-slack built at: ${buildAt}`);
340
+ }
341
+ };
342
+
343
+ // src/utils/FileUtils.ts
344
+ var import_fs = __toESM(require("fs"));
345
+ var path = __toESM(require("path"));
346
+ function listFilesRecursively(dir, extension, fileList = []) {
347
+ const entries = import_fs.default.readdirSync(dir);
348
+ entries.forEach((entry) => {
349
+ const fullPath = path.join(dir, entry);
350
+ if (import_fs.default.statSync(fullPath).isDirectory()) {
351
+ listFilesRecursively(fullPath, extension, fileList);
352
+ } else if (path.extname(fullPath).toLowerCase() === `.${extension}`) {
353
+ fileList.push(fullPath);
354
+ }
355
+ });
356
+ return fileList;
357
+ }
358
+ function extractListOfFiles(opts) {
359
+ if (!import_fs.default.existsSync(opts.path)) {
360
+ throw new Error(`Provided path does not exist: ${opts.path}`);
361
+ }
362
+ const stats = import_fs.default.statSync(opts.path);
363
+ if (stats.isDirectory()) {
364
+ Logger.info(`Provided path is a directory: ${opts.path}`);
365
+ const files = opts.recursive && listFilesRecursively(opts.path, opts.extension ?? "sarif") || import_fs.default.readdirSync(opts.path);
366
+ Logger.info(`Found ${files.length} files in ${opts.path} directory with ${opts.extension} extension`);
367
+ Logger.debug(`Found files: ${files.join(", ")}`);
368
+ return files;
369
+ }
370
+ if (stats.isFile()) {
371
+ Logger.info(`Provided path is a file: ${opts.path}`);
372
+ return [opts.path];
373
+ }
374
+ throw new Error(`Provided path is neither a file nor a directory: ${opts.path}`);
375
+ }
376
+
377
+ // src/utils/Comparators.ts
378
+ function findingsComparatorByKey(key) {
379
+ return (a, b) => {
380
+ switch (key) {
381
+ case "severity":
382
+ return b.severity - a.severity;
383
+ case "level":
384
+ return b.level - a.level;
385
+ case "runId":
386
+ return a.runId - b.runId;
387
+ case "toolName":
388
+ return a.toolName.toLowerCase().localeCompare(b.toolName.toLowerCase());
389
+ default:
390
+ return 1;
391
+ }
392
+ };
393
+ }
394
+
395
+ // src/utils/ExtendedArray.ts
396
+ var ExtendedArray = class extends Array {
397
+ findByProperty(prop, value) {
398
+ return this.find((v) => v[prop] === value);
399
+ }
400
+ };
401
+
402
+ // src/model/FindingsArray.ts
403
+ var FindingsArray = class extends ExtendedArray {
404
+ hasSeverityOrHigher(severity) {
405
+ return Object.values(SecuritySeverity).filter((v) => typeof v === "number").filter((v) => v >= severity).some((v) => this.findByProperty("severity", v) != null);
406
+ }
407
+ hasLevelOrHigher(level) {
408
+ return Object.values(SecurityLevel).filter((v) => typeof v === "number").filter((v) => v >= level).some((v) => this.findByProperty("level", v) != null);
409
+ }
410
+ };
411
+
412
+ // src/representations/Representation.ts
413
+ var Representation = class {
414
+ _model;
415
+ constructor(model, findingSortKey = "level") {
416
+ this._model = model;
417
+ this._model.findings = model.findings.map((f) => f.clone()).sort(findingsComparatorByKey(findingSortKey)).reduce((arr, f) => {
418
+ arr.push(f);
419
+ return arr;
420
+ }, new FindingsArray());
421
+ }
422
+ bold(text) {
423
+ return `*${text}*`;
424
+ }
425
+ italic(text) {
426
+ return `_${text}_`;
427
+ }
428
+ };
429
+
430
+ // src/representations/CompactGroupByRepresentation.ts
431
+ var NO_VULNS_FOUND_TEXT = "No vulnerabilities found";
432
+ var CompactGroupByRepresentation = class extends Representation {
433
+ composeByProperty(key) {
434
+ const grouped = this.groupFindings();
435
+ if (grouped.size === 0) {
436
+ return NO_VULNS_FOUND_TEXT;
437
+ }
438
+ return Array.from(grouped).map(([title, findings]) => {
439
+ findings.sort(findingsComparatorByKey(key));
440
+ const summary = findings.length === 0 ? NO_VULNS_FOUND_TEXT : this.composeCompactReport(findings, key);
441
+ return `${title}
442
+ ${summary}`;
443
+ }).join("\n\n");
444
+ }
445
+ composeCompactReport(findings, key) {
446
+ return Object.entries(Object.groupBy(findings, (f) => f[key])).map(([prop, findings2]) => {
447
+ if (findings2 == null) {
448
+ return void 0;
522
449
  }
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;
450
+ return `${this.bold(this.extractEnumValue(key, prop))}: ${findings2.length}`;
451
+ }).filter((v) => v != null).join(", ");
452
+ }
453
+ extractEnumValue(key, prop) {
454
+ switch (key) {
455
+ case "level":
456
+ return SecurityLevel[Number(prop)];
457
+ case "severity":
458
+ return SecuritySeverity[Number(prop)];
459
+ default:
460
+ throw new Error("Unknown property:", key);
461
+ }
462
+ }
463
+ };
464
+
465
+ // src/representations/CompactGroupByRunRepresentation.ts
466
+ var CompactGroupByRunRepresentation = class extends CompactGroupByRepresentation {
467
+ constructor(model) {
468
+ super(model, "runId");
469
+ }
470
+ groupFindings() {
471
+ const result = /* @__PURE__ */ new Map();
472
+ for (const run of this._model.runs) {
473
+ const key = this.composeGroupTitle(run.id, run.toolName);
474
+ if (result.get(key) == null) {
475
+ result.set(key, []);
534
476
  }
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;
477
+ this._model.findings.filter((f) => f.runId === run.id).forEach((f) => result.get(key)?.push(f));
478
+ }
479
+ return result;
480
+ }
481
+ composeGroupTitle(runId, toolName) {
482
+ return `${this.italic(`[Run ${runId}]`)} ${this.bold(toolName)}`;
483
+ }
484
+ };
485
+
486
+ // src/representations/CompactGroupByRunPerLevelRepresentation.ts
487
+ var CompactGroupByRunPerLevelRepresentation = class extends CompactGroupByRunRepresentation {
488
+ compose() {
489
+ return this.composeByProperty("level");
490
+ }
491
+ };
492
+
493
+ // src/representations/CompactGroupByRunPerSeverityRepresentation.ts
494
+ var CompactGroupByRunPerSeverityRepresentation = class extends CompactGroupByRunRepresentation {
495
+ compose() {
496
+ return this.composeByProperty("severity");
497
+ }
498
+ };
499
+
500
+ // src/representations/CompactGroupByToolNameRepresentation.ts
501
+ var CompactGroupByToolNameRepresentation = class extends CompactGroupByRepresentation {
502
+ constructor(model) {
503
+ super(model, "toolName");
504
+ }
505
+ groupFindings() {
506
+ const result = /* @__PURE__ */ new Map();
507
+ for (const run of this._model.runs) {
508
+ const key = this.composeGroupTitle(run.toolName);
509
+ if (result.get(key) == null) {
510
+ result.set(key, []);
544
511
  }
512
+ this._model.findings.filter((f) => f.runId === run.id).forEach((f) => result.get(key)?.push(f));
545
513
  }
546
- return summaries.join("\n\n");
514
+ return result;
515
+ }
516
+ composeGroupTitle(toolName) {
517
+ return this.bold(toolName);
547
518
  }
548
519
  };
549
520
 
550
- // src/System.ts
551
- var System = class {
552
- static initialize() {
553
- Logger.info(`Version: ${LIB_VERSION}`);
521
+ // src/representations/CompactGroupByToolNamePerLevelRepresentation.ts
522
+ var CompactGroupByToolNamePerLevelRepresentation = class extends CompactGroupByToolNameRepresentation {
523
+ compose() {
524
+ return this.composeByProperty("level");
554
525
  }
555
526
  };
556
527
 
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}`);
528
+ // src/representations/CompactGroupByToolNamePerSeverityRepresentation.ts
529
+ var CompactGroupByToolNamePerSeverityRepresentation = class extends CompactGroupByToolNameRepresentation {
530
+ compose() {
531
+ return this.composeByProperty("severity");
563
532
  }
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);
533
+ };
534
+
535
+ // src/representations/CompactGroupBySarifRepresentation.ts
536
+ var import_node_path = __toESM(require("path"));
537
+ var CompactGroupBySarifRepresentation = class extends CompactGroupByRepresentation {
538
+ constructor(model) {
539
+ super(model, "sarifPath");
540
+ }
541
+ groupFindings() {
542
+ const result = /* @__PURE__ */ new Map();
543
+ for (let index = 0; index < this._model.sarifFiles.length; index++) {
544
+ const key = this.composeGroupTitle(this._model.sarifFiles[index], index);
545
+ if (result.get(key) == null) {
546
+ result.set(key, []);
547
+ }
548
+ this._model.findings.filter((f) => f.sarifPath === this._model.sarifFiles[index]).forEach((f) => result.get(key)?.push(f));
575
549
  }
576
- if (opts.footer?.include) {
577
- messageBuilder.withFooter(opts.footer?.value, opts.footer?.type);
550
+ return result;
551
+ }
552
+ composeGroupTitle(sarifPath, index) {
553
+ return `${this.italic(`[File ${index + 1}]`)} ${this.bold(import_node_path.default.basename(sarifPath))}`;
554
+ }
555
+ };
556
+
557
+ // src/representations/CompactGroupBySarifPerLevelRepresentation.ts
558
+ var CompactGroupBySarifPerLevelRepresentation = class extends CompactGroupBySarifRepresentation {
559
+ compose() {
560
+ return this.composeByProperty("level");
561
+ }
562
+ };
563
+
564
+ // src/representations/CompactGroupBySarifPerSeverityRepresentation.ts
565
+ var CompactGroupBySarifPerSeverityRepresentation = class extends CompactGroupBySarifRepresentation {
566
+ compose() {
567
+ return this.composeByProperty("severity");
568
+ }
569
+ };
570
+
571
+ // src/representations/CompactTotalRepresentation.ts
572
+ var CompactTotalRepresentation = class extends CompactGroupByRepresentation {
573
+ groupFindings() {
574
+ const result = /* @__PURE__ */ new Map();
575
+ if (this._model.findings.length > 0) {
576
+ result.set("Total", this._model.findings);
578
577
  }
579
- if (opts.actor?.include) {
580
- messageBuilder.withActor(opts.actor?.value);
578
+ return result;
579
+ }
580
+ };
581
+
582
+ // src/representations/CompactTotalPerSeverityRepresentation.ts
583
+ var CompactTotalPerSeverityRepresentation = class extends CompactTotalRepresentation {
584
+ compose() {
585
+ return this.composeByProperty("severity");
586
+ }
587
+ };
588
+
589
+ // src/representations/CompactTotalPerLevelRepresentation.ts
590
+ var CompactTotalPerLevelRepresentation = class extends CompactTotalRepresentation {
591
+ compose() {
592
+ return this.composeByProperty("level");
593
+ }
594
+ };
595
+
596
+ // src/representations/RepresentationFactory.ts
597
+ function createRepresentation(model, type = 3 /* CompactGroupByToolNamePerSeverity */) {
598
+ switch (type) {
599
+ case 0 /* CompactGroupByRunPerLevel */:
600
+ return new CompactGroupByRunPerLevelRepresentation(model);
601
+ case 1 /* CompactGroupByRunPerSeverity */:
602
+ return new CompactGroupByRunPerSeverityRepresentation(model);
603
+ case 2 /* CompactGroupByToolNamePerLevel */:
604
+ return new CompactGroupByToolNamePerLevelRepresentation(model);
605
+ case 3 /* CompactGroupByToolNamePerSeverity */:
606
+ return new CompactGroupByToolNamePerSeverityRepresentation(model);
607
+ case 4 /* CompactGroupBySarifPerLevel */:
608
+ return new CompactGroupBySarifPerLevelRepresentation(model);
609
+ case 5 /* CompactGroupBySarifPerSeverity */:
610
+ return new CompactGroupBySarifPerSeverityRepresentation(model);
611
+ case 6 /* CompactTotalPerLevel */:
612
+ return new CompactTotalPerLevelRepresentation(model);
613
+ case 7 /* CompactTotalPerSeverity */:
614
+ return new CompactTotalPerSeverityRepresentation(model);
615
+ default:
616
+ throw new Error(`Unknown representation type: ${type}`);
617
+ }
618
+ }
619
+
620
+ // src/utils/SarifUtils.ts
621
+ function findToolComponentDriver(run) {
622
+ return run.tool.driver;
623
+ }
624
+ function tryFindToolComponentExtension(run, result) {
625
+ let tool;
626
+ if (result.rule?.toolComponent?.index != null) {
627
+ tool = run.tool.extensions?.[result.rule.toolComponent.index];
628
+ }
629
+ return tool;
630
+ }
631
+ function findToolComponent(run, result) {
632
+ return tryFindToolComponentExtension(run, result) ?? findToolComponentDriver(run);
633
+ }
634
+
635
+ // src/processors/CommonProcessor.ts
636
+ var CommonProcessor = class {
637
+ _run;
638
+ _result;
639
+ /**
640
+ * Creates an instance of {@link CommonProcessor} class.
641
+ * @param run An instance of {@link Run} object.
642
+ * @param result An instance of {@link Result} object.
643
+ */
644
+ constructor(run, result) {
645
+ this._run = run;
646
+ this._result = result;
647
+ }
648
+ tryFindCvssScore() {
649
+ return this.tryFindRuleProperty("security-severity");
650
+ }
651
+ tryFindLevel() {
652
+ return this._result.level ?? this.tryFindRule()?.defaultConfiguration?.level;
653
+ }
654
+ findToolComponentDriver() {
655
+ return findToolComponentDriver(this._run);
656
+ }
657
+ tryFindToolComponentExtension() {
658
+ return tryFindToolComponentExtension(this._run, this._result);
659
+ }
660
+ findToolComponent() {
661
+ return findToolComponent(this._run, this._result);
662
+ }
663
+ /**
664
+ * This function tries to find the respective rule for the given result.
665
+ * @internal
666
+ */
667
+ tryFindRule() {
668
+ const ruleData = {};
669
+ if (this._result.rule) {
670
+ if (this._result.rule?.index != null) {
671
+ ruleData.index = this._result.rule.index;
672
+ }
673
+ if (this._result.rule?.id) {
674
+ ruleData.id = this._result.rule.id;
675
+ }
581
676
  }
582
- if (opts.run?.include) {
583
- messageBuilder.withRun();
677
+ if (ruleData.index == null && this._result.ruleIndex != null) {
678
+ ruleData.index = this._result.ruleIndex;
679
+ }
680
+ if (!ruleData.id && this._result.ruleId) {
681
+ ruleData.id = this._result.ruleId;
682
+ }
683
+ const tool = this.findToolComponent();
684
+ if (ruleData.index != null && tool?.rules && ruleData.index < tool.rules.length) {
685
+ return tool.rules[ruleData.index];
686
+ }
687
+ if (ruleData.id && tool?.rules) {
688
+ return tool.rules.find(
689
+ (r) => r.id === ruleData.id
690
+ );
584
691
  }
585
- slackMessages.set(sarifFile, messageBuilder);
692
+ return void 0;
586
693
  }
587
- return slackMessages;
588
- }
589
- var SarifToSlackService = class _SarifToSlackService {
590
- _slackMessages;
591
- constructor() {
592
- this._slackMessages = /* @__PURE__ */ new Map();
694
+ /**
695
+ * This function searches respective rule for the given result, and then gets
696
+ * the property of interest from it.
697
+ * @param propertyName The property name that you want to get the value from.
698
+ * @protected
699
+ */
700
+ tryFindRuleProperty(propertyName) {
701
+ const rule = this.tryFindRule();
702
+ if (rule?.properties && propertyName in rule.properties) {
703
+ return rule.properties[propertyName];
704
+ }
705
+ return void 0;
593
706
  }
707
+ };
708
+
709
+ // src/processors/SnykProcessor.ts
710
+ var SnykProcessor = class extends CommonProcessor {
594
711
  /**
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
712
+ * Rules in SARIF files produced by Snyk Open Source has additional "cvssv3_baseScore"
713
+ * property where CVSS score is also defined. This method tries to get level
714
+ * from this "cvssv3_baseScore" property and if it fails to do so, then it tries
715
+ * to get CVSS score in a common way.
598
716
  */
599
- get slackMessages() {
600
- return this._slackMessages;
717
+ tryFindCvssScore() {
718
+ return this.tryFindRuleProperty("cvssv3_baseScore") ?? super.tryFindCvssScore();
601
719
  }
720
+ };
721
+
722
+ // src/processors/CodeQLProcessor.ts
723
+ var CodeQLProcessor = class extends CommonProcessor {
602
724
  /**
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
725
+ * Rules in SARIF files produced by CodeQL has additional "problem.severity"
726
+ * property where level is also defined. This method tries to get level in a
727
+ * common way but if it fails to do so, then it tries to get level from
728
+ * "problem.severity" property.
608
729
  */
609
- static async create(opts) {
610
- Logger.initialize(opts.log);
730
+ tryFindLevel() {
731
+ return super.tryFindLevel() ?? this.tryFindRuleProperty("problem.severity");
732
+ }
733
+ };
734
+
735
+ // src/processors/ProcessorFactory.ts
736
+ function createProcessor(run, result) {
737
+ const toolComponent = findToolComponent(run, result);
738
+ switch (toolComponent.name) {
739
+ case "CodeQL":
740
+ return new CodeQLProcessor(run, result);
741
+ case "Snyk Open Source":
742
+ return new SnykProcessor(run, result);
743
+ default:
744
+ return new CommonProcessor(run, result);
745
+ }
746
+ }
747
+
748
+ // src/model/Finding.ts
749
+ function createFinding(opts) {
750
+ return new SarifFinding(opts);
751
+ }
752
+ var SarifFinding = class {
753
+ _runMetadata;
754
+ _result;
755
+ _sarifPath;
756
+ _rule;
757
+ _processor;
758
+ _cvssScoreCacheProcessed = false;
759
+ _cvssScoreCache = void 0;
760
+ _levelCacheProcessed = false;
761
+ _levelCache = void 0;
762
+ constructor(opts) {
763
+ this._processor = createProcessor(opts.runMetadata.run, opts.result);
764
+ this._sarifPath = opts.sarifPath;
765
+ this._runMetadata = opts.runMetadata;
766
+ this._result = opts.result;
767
+ this._rule = this._processor.tryFindRule();
768
+ }
769
+ clone() {
770
+ return createFinding({
771
+ sarifPath: this._sarifPath,
772
+ runMetadata: this._runMetadata,
773
+ result: this._result
774
+ });
775
+ }
776
+ get sarifPath() {
777
+ return this._sarifPath;
778
+ }
779
+ get runId() {
780
+ return this._runMetadata.id;
781
+ }
782
+ get toolName() {
783
+ return this._processor.findToolComponent().name;
784
+ }
785
+ get cvssScore() {
786
+ if (!this._cvssScoreCacheProcessed) {
787
+ this._cvssScoreCacheProcessed = true;
788
+ this._cvssScoreCache = this._processor.tryFindCvssScore();
789
+ }
790
+ return this._cvssScoreCache;
791
+ }
792
+ get level() {
793
+ if (!this._levelCacheProcessed) {
794
+ this._levelCacheProcessed = true;
795
+ this._levelCache = this._processor.tryFindLevel();
796
+ }
797
+ if (this._levelCache === void 0) {
798
+ Logger.debug(`Unknown level of ${this._rule?.id} rule`);
799
+ return 0 /* Unknown */;
800
+ }
801
+ switch (this._levelCache) {
802
+ case "error":
803
+ return 4 /* Error */;
804
+ case "warning":
805
+ return 3 /* Warning */;
806
+ case "note":
807
+ return 2 /* Note */;
808
+ default:
809
+ return 1 /* None */;
810
+ }
811
+ }
812
+ get severity() {
813
+ if (this.cvssScore == null || this.cvssScore < 0 || this.cvssScore > 10) {
814
+ Logger.debug(`Unsupported CVSS score ${this.cvssScore} in ${this._rule?.id} rule`);
815
+ return 0 /* Unknown */;
816
+ }
817
+ if (this.cvssScore >= 9) {
818
+ return 5 /* Critical */;
819
+ }
820
+ if (this.cvssScore >= 7) {
821
+ return 4 /* High */;
822
+ }
823
+ if (this.cvssScore >= 4) {
824
+ return 3 /* Medium */;
825
+ }
826
+ if (this.cvssScore >= 0.1) {
827
+ return 2 /* Low */;
828
+ }
829
+ return 1 /* None */;
830
+ }
831
+ };
832
+
833
+ // src/SarifToSlackClient.ts
834
+ var SarifToSlackClient = class _SarifToSlackClient {
835
+ _message;
836
+ _sarifModel;
837
+ _sendIf = 20 /* Always */;
838
+ constructor(log) {
839
+ Logger.initialize(log);
611
840
  System.initialize();
612
- const instance = new _SarifToSlackService();
613
- const map = await initialize(opts);
614
- map.forEach((val, key) => instance._slackMessages.set(key, val));
841
+ }
842
+ static *createRunIdGenerator() {
843
+ let runId = 1;
844
+ while (true) {
845
+ yield runId++;
846
+ }
847
+ }
848
+ static async create(opts) {
849
+ const instance = new _SarifToSlackClient(opts.log);
850
+ Logger.trace("opts", opts);
851
+ instance._sendIf = opts.sendIf ?? instance._sendIf;
852
+ instance._sarifModel = await _SarifToSlackClient.buildModel(opts.sarif);
853
+ Logger.trace("instance._sarifModel", instance._sarifModel);
854
+ instance._message = await _SarifToSlackClient.initialize(instance._sarifModel, opts);
855
+ Logger.trace("instance._message", instance._message);
615
856
  return instance;
616
857
  }
858
+ static async buildModel(sarifOpts) {
859
+ const sarifFiles = extractListOfFiles(sarifOpts);
860
+ if (sarifFiles.length === 0) {
861
+ throw new Error(`No SARIF files found at the provided path: ${sarifOpts.path}`);
862
+ }
863
+ const model = { sarifFiles, runs: [], findings: new FindingsArray() };
864
+ const runIdGenerator = _SarifToSlackClient.createRunIdGenerator();
865
+ for (const sarifPath of sarifFiles) {
866
+ const sarifJson = await import_fs2.promises.readFile(sarifPath, "utf8");
867
+ const sarifLog = JSON.parse(sarifJson);
868
+ for (const run of sarifLog.runs) {
869
+ const runId = runIdGenerator.next();
870
+ let runMetadata = void 0;
871
+ for (const result of run.results ?? []) {
872
+ runMetadata = {
873
+ id: runId.value,
874
+ run,
875
+ toolName: findToolComponent(run, result).name
876
+ };
877
+ model.findings.push(createFinding({ sarifPath, result, runMetadata }));
878
+ }
879
+ runMetadata ??= {
880
+ id: runId.value,
881
+ run,
882
+ toolName: findToolComponentDriver(run).name
883
+ };
884
+ model.runs.push(runMetadata);
885
+ }
886
+ }
887
+ return model;
888
+ }
617
889
  /**
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
890
+ * The main function to initialize a list of {@link SlackMessage} objects based
891
+ * on the given SARIF file(s).
892
+ * @param sarifModel An instance of {@link SarifModel} object.
893
+ * @param opts An instance of {@link SarifToSlackClientOptions} object.
894
+ * @returns A map where key is the SARIF file and value is an instance of
895
+ * {@link SlackMessage} object
896
+ * @private
622
897
  */
623
- async sendAll() {
624
- for (const sarifPath of this._slackMessages.keys()) {
625
- await this.send(sarifPath);
898
+ static async initialize(sarifModel, opts) {
899
+ const message = new SlackMessageBuilder(opts.webhookUrl, {
900
+ username: opts.username,
901
+ iconUrl: opts.iconUrl,
902
+ color: identifyColor(sarifModel.findings, opts.color),
903
+ representation: createRepresentation(sarifModel, opts.representation)
904
+ });
905
+ if (opts.header?.include) {
906
+ message.withHeader(opts.header?.value);
626
907
  }
908
+ if (opts.footer?.include) {
909
+ message.withFooter(opts.footer?.value, opts.footer?.type);
910
+ }
911
+ if (opts.actor?.include) {
912
+ message.withActor(opts.actor?.value);
913
+ }
914
+ if (opts.run?.include) {
915
+ message.withRun();
916
+ }
917
+ return message;
627
918
  }
628
919
  /**
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.
920
+ * Sends a Slack message.
631
921
  * @returns A promise that resolves when the message has been sent.
632
922
  * @throws Error if a Slack message was not prepared for the given SARIF path.
633
923
  * @public
634
924
  */
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}.`);
925
+ async send() {
926
+ if (this._sarifModel == null) {
927
+ throw new Error("Could not parse SARIF file(s).");
928
+ }
929
+ if (this.shouldSendMessage) {
930
+ if (this._message == null) {
931
+ throw new Error("Slack message was not prepared.");
932
+ }
933
+ const text = await this._message.send();
934
+ Logger.info("Message sent. Status:", text);
935
+ } else {
936
+ Logger.info("Message was not sent based on the sendIf parameter:", SendIf[this._sendIf]);
937
+ }
938
+ }
939
+ get shouldSendMessage() {
940
+ if (this._sendIf == null) {
941
+ return true;
942
+ }
943
+ switch (this._sendIf) {
944
+ case 0 /* SeverityCritical */:
945
+ return this._sarifModel?.findings.findByProperty("severity", 5 /* Critical */) != null;
946
+ case 1 /* SeverityHigh */:
947
+ return this._sarifModel?.findings.findByProperty("severity", 4 /* High */) != null;
948
+ case 2 /* SeverityHighOrHigher */:
949
+ return !!this._sarifModel?.findings.hasSeverityOrHigher(4 /* High */);
950
+ case 3 /* SeverityMedium */:
951
+ return this._sarifModel?.findings.findByProperty("severity", 3 /* Medium */) != null;
952
+ case 4 /* SeverityMediumOrHigher */:
953
+ return !!this._sarifModel?.findings.hasSeverityOrHigher(3 /* Medium */);
954
+ case 5 /* SeverityLow */:
955
+ return this._sarifModel?.findings.findByProperty("severity", 2 /* Low */) != null;
956
+ case 6 /* SeverityLowOrHigher */:
957
+ return !!this._sarifModel?.findings.hasSeverityOrHigher(2 /* Low */);
958
+ case 7 /* SeverityNone */:
959
+ return this._sarifModel?.findings.findByProperty("severity", 1 /* None */) != null;
960
+ case 8 /* SeverityNoneOrHigher */:
961
+ return !!this._sarifModel?.findings.hasSeverityOrHigher(1 /* None */);
962
+ case 9 /* SeverityUnknown */:
963
+ return this._sarifModel?.findings.findByProperty("severity", 0 /* Unknown */) != null;
964
+ case 10 /* SeverityUnknownOrHigher */:
965
+ return !!this._sarifModel?.findings.hasSeverityOrHigher(0 /* Unknown */);
966
+ case 11 /* LevelError */:
967
+ return this._sarifModel?.findings.findByProperty("level", 4 /* Error */) != null;
968
+ case 12 /* LevelWarning */:
969
+ return this._sarifModel?.findings.findByProperty("level", 3 /* Warning */) != null;
970
+ case 13 /* LevelWarningOrHigher */:
971
+ return !!this._sarifModel?.findings.hasLevelOrHigher(3 /* Warning */);
972
+ case 14 /* LevelNote */:
973
+ return this._sarifModel?.findings.findByProperty("level", 2 /* Note */) != null;
974
+ case 15 /* LevelNoteOrHigher */:
975
+ return !!this._sarifModel?.findings.hasLevelOrHigher(2 /* Note */);
976
+ case 16 /* LevelNone */:
977
+ return this._sarifModel?.findings.findByProperty("level", 1 /* None */) != null;
978
+ case 17 /* LevelNoneOrHigher */:
979
+ return !!this._sarifModel?.findings.hasLevelOrHigher(1 /* None */);
980
+ case 18 /* LevelUnknown */:
981
+ return this._sarifModel?.findings.findByProperty("level", 0 /* Unknown */) != null;
982
+ case 19 /* LevelUnknownOrHigher */:
983
+ return !!this._sarifModel?.findings.hasLevelOrHigher(0 /* Unknown */);
984
+ case 20 /* Always */:
985
+ return true;
986
+ case 21 /* Some */:
987
+ return (this._sarifModel?.findings.length ?? 0) > 0;
988
+ case 22 /* Empty */:
989
+ return (this._sarifModel?.findings.length ?? 0) === 0;
990
+ case 23 /* Never */:
991
+ return false;
992
+ default:
993
+ throw new Error(`Unknown sendIf parameter: ${this._sendIf}`);
639
994
  }
640
- const text = await message.send();
641
- Logger.info(`Message sent for ${sarifPath} file. Status:`, text);
642
995
  }
643
996
  };
644
997
  // Annotate the CommonJS export names for ESM import in node:
645
998
  0 && (module.exports = {
646
- CalculateResultsBy,
999
+ Color,
647
1000
  FooterType,
648
- GroupResultsBy,
649
1001
  LogLevel,
650
- SarifToSlackService
1002
+ RepresentationType,
1003
+ SarifToSlackClient,
1004
+ SendIf
651
1005
  });