@fabasoad/sarif-to-slack 1.1.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/.github/workflows/security.yml +10 -2
  2. package/.github/workflows/send-sarif-to-slack.yml +6 -1
  3. package/.tool-versions +1 -1
  4. package/dist/SarifToSlackClient.d.ts.map +1 -1
  5. package/dist/SarifToSlackClient.js +8 -10
  6. package/dist/index.cjs +158 -93
  7. package/dist/index.d.ts +12 -2
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +12 -3
  10. package/dist/model/Color.d.ts +5 -2
  11. package/dist/model/Color.d.ts.map +1 -1
  12. package/dist/model/Color.js +26 -17
  13. package/dist/model/Finding.js +3 -3
  14. package/dist/model/FindingArray.d.ts +2 -0
  15. package/dist/model/FindingArray.d.ts.map +1 -0
  16. package/dist/model/FindingArray.js +24 -0
  17. package/dist/model/SendIf.d.ts +116 -0
  18. package/dist/model/SendIf.d.ts.map +1 -0
  19. package/dist/model/SendIf.js +176 -0
  20. package/dist/model/SlackMessage.d.ts +23 -0
  21. package/dist/model/SlackMessage.d.ts.map +1 -0
  22. package/dist/model/SlackMessage.js +99 -0
  23. package/dist/representations/CompactGroupByRepresentation.js +1 -1
  24. package/dist/representations/CompactGroupByRunPerLevelRepresentation.js +1 -1
  25. package/dist/representations/CompactGroupByRunPerSeverityRepresentation.js +1 -1
  26. package/dist/representations/CompactGroupByRunRepresentation.js +1 -1
  27. package/dist/representations/CompactGroupBySarifRepresentation.js +1 -1
  28. package/dist/representations/CompactGroupByToolNameRepresentation.js +1 -1
  29. package/dist/representations/CompactTotalRepresentation.js +1 -1
  30. package/dist/representations/Representation.js +3 -3
  31. package/dist/sarif-to-slack.d.ts +14 -3
  32. package/dist/types.d.ts +1 -130
  33. package/dist/types.d.ts.map +1 -1
  34. package/dist/types.js +1 -117
  35. package/etc/sarif-to-slack.api.md +1 -0
  36. package/package.json +1 -1
  37. package/src/SarifToSlackClient.ts +8 -12
  38. package/src/index.ts +12 -4
  39. package/src/model/Color.ts +37 -25
  40. package/src/model/Finding.ts +3 -3
  41. package/src/model/{FindingsArray.ts → FindingArray.ts} +3 -3
  42. package/src/model/SendIf.ts +175 -0
  43. package/src/{SlackMessageBuilder.ts → model/SlackMessage.ts} +31 -6
  44. package/src/processors/CodeQLProcessor.ts +1 -1
  45. package/src/representations/CompactGroupByRepresentation.ts +2 -2
  46. package/src/representations/CompactGroupByRunPerLevelRepresentation.ts +1 -1
  47. package/src/representations/CompactGroupByRunPerSeverityRepresentation.ts +1 -1
  48. package/src/representations/CompactGroupByRunRepresentation.ts +2 -2
  49. package/src/representations/CompactGroupBySarifRepresentation.ts +2 -2
  50. package/src/representations/CompactGroupByToolNameRepresentation.ts +2 -2
  51. package/src/representations/CompactTotalRepresentation.ts +2 -2
  52. package/src/representations/Representation.ts +4 -4
  53. package/src/types.ts +3 -134
  54. package/src/utils/Comparators.ts +1 -1
  55. package/test-data/sarif/osv-scanner-yarn.sarif +4 -4
  56. package/tests/integration/SendSarifToSlack.spec.ts +21 -5
  57. package/dist/SlackMessageBuilder.d.ts +0 -2
  58. package/dist/SlackMessageBuilder.d.ts.map +0 -1
  59. package/dist/SlackMessageBuilder.js +0 -91
  60. package/dist/model/FindingsArray.d.ts +0 -2
  61. package/dist/model/FindingsArray.d.ts.map +0 -1
  62. package/dist/model/FindingsArray.js +0 -24
@@ -1,6 +1,6 @@
1
1
  import { SecurityLevel, SecuritySeverity } from '../types'
2
- import { Finding } from './Finding'
3
- import FindingsArray from './FindingsArray'
2
+ import Finding from './Finding'
3
+ import FindingArray from './FindingArray'
4
4
 
5
5
  /**
6
6
  * This class represents a color in hex format.
@@ -20,7 +20,7 @@ export class Color {
20
20
  */
21
21
  public constructor(color?: string) {
22
22
  this._color = this.mapColor(color)
23
- this.validateHexColor()
23
+ this.assertHexColor()
24
24
  }
25
25
 
26
26
  /**
@@ -30,12 +30,12 @@ export class Color {
30
30
  return this._color
31
31
  }
32
32
 
33
- private validateHexColor(): void {
33
+ private assertHexColor(): void {
34
34
  if (this._color != null) {
35
- const hexColorRegex = /^#(?:[0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/;
35
+ const hexColorRegex = /^#(?:[0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/
36
36
 
37
37
  if (!hexColorRegex.test(this._color)) {
38
- throw new Error(`Invalid hex color: "${this._color}"`);
38
+ throw new Error(`Invalid hex color: "${this._color}"`)
39
39
  }
40
40
  }
41
41
  }
@@ -64,7 +64,6 @@ export class Color {
64
64
  type ColorGroupCommon = {
65
65
  none?: Color,
66
66
  unknown?: Color,
67
- empty?: Color,
68
67
  }
69
68
 
70
69
  /**
@@ -113,15 +112,18 @@ export type ColorOptions = {
113
112
  * Color scheme for the findings where certain severity is presented.
114
113
  */
115
114
  bySeverity?: ColorGroupBySeverity,
115
+ /**
116
+ * Color when no findings are found.
117
+ */
118
+ empty?: Color,
116
119
  }
117
120
 
118
121
  function identifyColorCommon<K extends keyof Finding>(
119
- findings: FindingsArray,
122
+ findings: FindingArray,
120
123
  prop: K,
121
124
  none: Finding[K],
122
125
  unknown: Finding[K],
123
- color: ColorGroupCommon,
124
- defaultColor?: Color
126
+ color: ColorGroupCommon
125
127
  ): string | undefined {
126
128
  if (color.none != null && findings.findByProperty(prop, none) != null) {
127
129
  return color.none.value
@@ -131,14 +133,10 @@ function identifyColorCommon<K extends keyof Finding>(
131
133
  return color.unknown.value
132
134
  }
133
135
 
134
- if (color.empty != null && findings.length === 0) {
135
- return color.empty.value
136
- }
137
-
138
- return defaultColor?.value
136
+ return undefined
139
137
  }
140
138
 
141
- function identifyColorBySeverity(findings: FindingsArray, color: ColorGroupBySeverity, defaultColor?: Color): string | undefined {
139
+ function identifyColorBySeverity(findings: FindingArray, color: ColorGroupBySeverity): string | undefined {
142
140
  if (color.critical != null && findings.findByProperty('severity', SecuritySeverity.Critical) != null) {
143
141
  return color.critical.value
144
142
  }
@@ -155,10 +153,10 @@ function identifyColorBySeverity(findings: FindingsArray, color: ColorGroupBySev
155
153
  return color.low.value
156
154
  }
157
155
 
158
- return identifyColorCommon(findings, 'severity', SecuritySeverity.None, SecuritySeverity.Unknown, color, defaultColor)
156
+ return identifyColorCommon(findings, 'severity', SecuritySeverity.None, SecuritySeverity.Unknown, color)
159
157
  }
160
158
 
161
- function identifyColorByLevel(findings: FindingsArray, color: ColorGroupByLevel, defaultColor?: Color): string | undefined {
159
+ function identifyColorByLevel(findings: FindingArray, color: ColorGroupByLevel): string | undefined {
162
160
  if (color.error != null && findings.findByProperty('level', SecurityLevel.Error) != null) {
163
161
  return color.error.value
164
162
  }
@@ -171,24 +169,38 @@ function identifyColorByLevel(findings: FindingsArray, color: ColorGroupByLevel,
171
169
  return color.note.value
172
170
  }
173
171
 
174
- return identifyColorCommon(findings, 'level', SecurityLevel.None, SecurityLevel.Unknown, color, defaultColor)
172
+ return identifyColorCommon(findings, 'level', SecurityLevel.None, SecurityLevel.Unknown, color)
175
173
  }
176
174
 
177
175
  /**
178
176
  * Makes an ultimate decision on what color should be Slack message. The decision
179
177
  * is based on the provided {@param colorOpts} parameter and {@param findings}
180
178
  * list.
181
- * @param findings An instance of {@link FindingsArray} object.
179
+ * @param findings An instance of {@link FindingArray} object.
182
180
  * @param colorOpts An instance of {@link ColorOptions} type.
183
181
  * @internal
184
182
  */
185
- export function identifyColor(findings: FindingsArray, colorOpts?: ColorOptions): string | undefined {
186
- if (colorOpts?.bySeverity != null) {
187
- return identifyColorBySeverity(findings, colorOpts.bySeverity, colorOpts.default)
183
+ export function identifyColor(findings: FindingArray, colorOpts?: ColorOptions): string | undefined {
184
+ if (!colorOpts) {
185
+ return undefined
186
+ }
187
+
188
+ if (colorOpts.bySeverity) {
189
+ const color: string | undefined = identifyColorBySeverity(findings, colorOpts.bySeverity)
190
+ if (color !== undefined) {
191
+ return color
192
+ }
193
+ }
194
+
195
+ if (colorOpts.byLevel) {
196
+ const color: string | undefined = identifyColorByLevel(findings, colorOpts.byLevel)
197
+ if (color !== undefined) {
198
+ return color
199
+ }
188
200
  }
189
201
 
190
- if (colorOpts?.byLevel != null) {
191
- return identifyColorByLevel(findings, colorOpts.byLevel, colorOpts.default)
202
+ if (findings.length === 0 && colorOpts.empty?.value !== undefined) {
203
+ return colorOpts.empty.value
192
204
  }
193
205
 
194
206
  return colorOpts?.default?.value
@@ -18,7 +18,7 @@ export type FindingOptions = {
18
18
  * This interface represents a finding from SARIF file.
19
19
  * @internal
20
20
  */
21
- export interface Finding {
21
+ export default interface Finding {
22
22
  get sarifPath(): string,
23
23
  get runId(): number,
24
24
  get toolName(): string,
@@ -33,7 +33,7 @@ export interface Finding {
33
33
  * @internal
34
34
  */
35
35
  export function createFinding(opts: FindingOptions): Finding {
36
- return new SarifFinding(opts)
36
+ return new FindingImpl(opts)
37
37
  }
38
38
 
39
39
  /**
@@ -42,7 +42,7 @@ export function createFinding(opts: FindingOptions): Finding {
42
42
  * create a new {@link Finding}.
43
43
  * @private
44
44
  */
45
- class SarifFinding implements Finding {
45
+ class FindingImpl implements Finding {
46
46
  private readonly _runMetadata: RunData
47
47
  private readonly _result: Result
48
48
  private readonly _sarifPath: string
@@ -1,13 +1,13 @@
1
- import { Finding } from './Finding'
2
- import ExtendedArray from '../utils/ExtendedArray'
1
+ import Finding from './Finding'
3
2
  import { SecurityLevel, SecuritySeverity } from '../types'
3
+ import ExtendedArray from '../utils/ExtendedArray'
4
4
 
5
5
  /**
6
6
  * This class represents an array of {@link Finding} objects and adds additional
7
7
  * useful methods to it.
8
8
  * @internal
9
9
  */
10
- export default class FindingsArray extends ExtendedArray<Finding> {
10
+ export default class FindingArray extends ExtendedArray<Finding> {
11
11
 
12
12
  public hasSeverityOrHigher(severity: SecuritySeverity): boolean {
13
13
  return Object
@@ -0,0 +1,175 @@
1
+ /**
2
+ * This enum represents the condition on when message should be sent. If this
3
+ * condition is satisfied then message is sent, otherwise - message is not sent.
4
+ * @public
5
+ */
6
+ export enum SendIf {
7
+ /**
8
+ * Send message only if there is at least one finding with "Critical" severity.
9
+ * Since it is the higher possible severity, it is the same as "Critical" or
10
+ * higher.
11
+ */
12
+ SeverityCritical,
13
+ /**
14
+ * Send message only if there is at least one finding with "High" severity.
15
+ */
16
+ SeverityHigh,
17
+ /**
18
+ * Send message only if there is at least one finding with "High" severity or
19
+ * higher, that includes "High" and "Critical".
20
+ */
21
+ SeverityHighOrHigher,
22
+ /**
23
+ * Send message only if there is at least one finding with "Medium" severity.
24
+ */
25
+ SeverityMedium,
26
+ /**
27
+ * Send message only if there is at least one finding with "Medium" severity
28
+ * or higher, that includes "Medium", "High" and "Critical".
29
+ */
30
+ SeverityMediumOrHigher,
31
+ /**
32
+ * Send message only if there is at least one finding with "Low" severity.
33
+ */
34
+ SeverityLow,
35
+ /**
36
+ * Send message only if there is at least one finding with "Low" severity or
37
+ * higher, that includes "Low", "Medium", "High" and "Critical".
38
+ */
39
+ SeverityLowOrHigher,
40
+ /**
41
+ * Send message only if there is at least one finding with "None" severity.
42
+ */
43
+ SeverityNone,
44
+ /**
45
+ * Send message only if there is at least one finding with "None" severity or
46
+ * higher, that includes "None", "Low", "Medium", "High" and "Critical".
47
+ */
48
+ SeverityNoneOrHigher,
49
+ /**
50
+ * Send message only if there is at least one finding with "Unknown" severity.
51
+ */
52
+ SeverityUnknown,
53
+ /**
54
+ * Send message only if there is at least one finding with "Unknown" severity
55
+ * or higher, that includes "Unknown", "None", "Low", "Medium", "High" and "Critical".
56
+ */
57
+ SeverityUnknownOrHigher,
58
+ /**
59
+ * Send message only if there is at least one finding with "Error" level.
60
+ * Since it is the higher possible level, it is the same as "Error" or higher.
61
+ */
62
+ LevelError,
63
+ /**
64
+ * Send message only if there is at least one finding with "Warning" level.
65
+ */
66
+ LevelWarning,
67
+ /**
68
+ * Send message only if there is at least one finding with "Warning" level or
69
+ * higher, that includes "Warning" and "Error".
70
+ */
71
+ LevelWarningOrHigher,
72
+ /**
73
+ * Send message only if there is at least one finding with "Note" level.
74
+ */
75
+ LevelNote,
76
+ /**
77
+ * Send message only if there is at least one finding with "Note" level or
78
+ * higher, that includes "Note", "Warning" and "Error.
79
+ */
80
+ LevelNoteOrHigher,
81
+ /**
82
+ * Send message only if there is at least one finding with "None" level.
83
+ */
84
+ LevelNone,
85
+ /**
86
+ * Send message only if there is at least one finding with "None" level or
87
+ * higher, that includes "None", "Note", "Warning" and "Error.
88
+ */
89
+ LevelNoneOrHigher,
90
+ /**
91
+ * Send message only if there is at least one finding with "Unknown" level.
92
+ */
93
+ LevelUnknown,
94
+ /**
95
+ * Send message only if there is at least one finding with "Unknown" level or
96
+ * higher, that includes "Unknown", "None", "Note", "Warning" and "Error.
97
+ */
98
+ LevelUnknownOrHigher,
99
+ /**
100
+ * Always send a message.
101
+ */
102
+ Always,
103
+ /**
104
+ * Send a message if at least 1 vulnerability is found.
105
+ */
106
+ Some,
107
+ /**
108
+ * Send a message only if no vulnerabilities are found.
109
+ */
110
+ Empty,
111
+ /**
112
+ * Never send a message.
113
+ */
114
+ Never,
115
+ }
116
+
117
+ /**
118
+ * Returns log message based on the provided {@param sendIf} parameter.
119
+ * @param sendIf An instance of {@link SendIf} enum.
120
+ * @internal
121
+ */
122
+ export function sendIfLogMessage(sendIf: SendIf): string {
123
+ switch (sendIf) {
124
+ case SendIf.SeverityCritical:
125
+ return 'No message sent: no findings with "Critical" severity.'
126
+ case SendIf.SeverityHigh:
127
+ return 'No message sent: no findings with "High" severity.'
128
+ case SendIf.SeverityHighOrHigher:
129
+ return 'No message sent: no findings with "High" or higher severity.'
130
+ case SendIf.SeverityMedium:
131
+ return 'No message sent: no findings with "Medium" severity.'
132
+ case SendIf.SeverityMediumOrHigher:
133
+ return 'No message sent: no findings with "Medium" or higher severity.'
134
+ case SendIf.SeverityLow:
135
+ return 'No message sent: no findings with "Low" severity.'
136
+ case SendIf.SeverityLowOrHigher:
137
+ return 'No message sent: no findings with "Low" or higher severity.'
138
+ case SendIf.SeverityNone:
139
+ return 'No message sent: no findings with "None" severity.'
140
+ case SendIf.SeverityNoneOrHigher:
141
+ return 'No message sent: no findings with "None" or higher severity.'
142
+ case SendIf.SeverityUnknown:
143
+ return 'No message sent: no findings with "Unknown" severity.'
144
+ case SendIf.SeverityUnknownOrHigher:
145
+ return 'No message sent: no findings with "Unknown" or higher severity.'
146
+ case SendIf.LevelError:
147
+ return 'No message sent: no findings with "Error" level.'
148
+ case SendIf.LevelWarning:
149
+ return 'No message sent: no findings with "Warning" level.'
150
+ case SendIf.LevelWarningOrHigher:
151
+ return 'No message sent: no findings with "Warning" or higher level.'
152
+ case SendIf.LevelNote:
153
+ return 'No message sent: no findings with "Note" level.'
154
+ case SendIf.LevelNoteOrHigher:
155
+ return 'No message sent: no findings with "Note" or higher level.'
156
+ case SendIf.LevelNone:
157
+ return 'No message sent: no findings with "None" level.'
158
+ case SendIf.LevelNoneOrHigher:
159
+ return 'No message sent: no findings with "None" or higher level.'
160
+ case SendIf.LevelUnknown:
161
+ return 'No message sent: no findings with "Unknown" level.'
162
+ case SendIf.LevelUnknownOrHigher:
163
+ return 'No message sent: no findings with "Unknown" or higher level.'
164
+ case SendIf.Always:
165
+ return 'Message always sent.'
166
+ case SendIf.Some:
167
+ return 'No message sent: findings are not found.'
168
+ case SendIf.Empty:
169
+ return 'No message sent: some findings are found.'
170
+ case SendIf.Never:
171
+ return 'No message sent: sending is disabled.'
172
+ default:
173
+ return 'Unknown SendIf value.'
174
+ }
175
+ }
@@ -2,26 +2,51 @@ import { AnyBlock } from '@slack/types'
2
2
  import { ContextBlock, HeaderBlock } from '@slack/types/dist/block-kit/blocks'
3
3
  import { TextObject } from '@slack/types/dist/block-kit/composition-objects'
4
4
  import { IncomingWebhook } from '@slack/webhook'
5
- import { FooterType, SlackMessage } from './types'
6
- import { version } from './metadata.json'
7
- import Representation from './representations/Representation'
5
+ import { FooterType } from '../types'
6
+ import Representation from '../representations/Representation'
7
+ import { version } from '../metadata.json'
8
8
 
9
9
  /**
10
10
  * Options for the SlackMessageBuilder.
11
11
  * @internal
12
12
  */
13
- export type SlackMessageBuilderOptions = {
13
+ export type SlackMessageOptions = {
14
14
  username?: string
15
15
  iconUrl?: string
16
16
  color?: string
17
17
  representation: Representation,
18
18
  }
19
19
 
20
+ /**
21
+ * Interface for a Slack message that can be sent.
22
+ * @public
23
+ */
24
+ export interface SlackMessage {
25
+ /**
26
+ * Sends the Slack message.
27
+ * @returns A promise that resolves to the response from the Slack webhook.
28
+ */
29
+ send: () => Promise<string>
30
+ withActor(actor?: string): void
31
+ withFooter(text?: string, type?: FooterType): void
32
+ withHeader(header?: string): void
33
+ withRun(): void
34
+ }
35
+
36
+ /**
37
+ * Creates a new instance of {@link SlackMessage} class.
38
+ * @param url Slack webhook URL
39
+ * @param opts An instance of {@link SlackMessageOptions} type.
40
+ */
41
+ export function createSlackMessage(url: string, opts: SlackMessageOptions): SlackMessage {
42
+ return new SlackMessageImpl(url, opts)
43
+ }
44
+
20
45
  /**
21
46
  * Class for building and sending Slack messages based on SARIF logs.
22
47
  * @internal
23
48
  */
24
- export class SlackMessageBuilder implements SlackMessage {
49
+ class SlackMessageImpl implements SlackMessage {
25
50
  private readonly _webhook: IncomingWebhook
26
51
  private readonly _gitHubServerUrl: string
27
52
  private readonly _color?: string
@@ -32,7 +57,7 @@ export class SlackMessageBuilder implements SlackMessage {
32
57
  private _actor?: string
33
58
  private _runId?: string
34
59
 
35
- constructor(url: string, opts: SlackMessageBuilderOptions) {
60
+ constructor(url: string, opts: SlackMessageOptions) {
36
61
  this._webhook = new IncomingWebhook(url, {
37
62
  username: opts.username || 'SARIF results',
38
63
  icon_url: opts.iconUrl
@@ -1,5 +1,5 @@
1
1
  import { CommonProcessor } from './CommonProcessor'
2
- import { Result } from 'sarif';
2
+ import { Result } from 'sarif'
3
3
 
4
4
  /**
5
5
  * This class has extra logic for processing SARIF files produced by CodeQL tool.
@@ -1,7 +1,7 @@
1
1
  import Representation from './Representation'
2
- import { Finding } from '../model/Finding'
2
+ import Finding from '../model/Finding'
3
3
  import { findingsComparatorByKey } from '../utils/Comparators'
4
- import { SecurityLevel, SecuritySeverity } from '../types';
4
+ import { SecurityLevel, SecuritySeverity } from '../types'
5
5
 
6
6
  const NO_VULNS_FOUND_TEXT = 'No vulnerabilities found'
7
7
 
@@ -1,4 +1,4 @@
1
- import CompactGroupByRunRepresentation from './CompactGroupByRunRepresentation';
1
+ import CompactGroupByRunRepresentation from './CompactGroupByRunRepresentation'
2
2
 
3
3
  /**
4
4
  * Since {@link CompactGroupByRunRepresentation} is an abstract class, the only
@@ -1,4 +1,4 @@
1
- import CompactGroupByRunRepresentation from './CompactGroupByRunRepresentation';
1
+ import CompactGroupByRunRepresentation from './CompactGroupByRunRepresentation'
2
2
 
3
3
  /**
4
4
  * Since {@link CompactGroupByRunRepresentation} is an abstract class, the only
@@ -1,4 +1,4 @@
1
- import { Finding } from '../model/Finding'
1
+ import Finding from '../model/Finding'
2
2
  import CompactGroupByRepresentation from './CompactGroupByRepresentation'
3
3
  import { SarifModel } from '../types'
4
4
 
@@ -13,10 +13,10 @@ import { SarifModel } from '../types'
13
13
  * [Run 2] Grype
14
14
  * Warning: 1, Note: 20
15
15
  * ```
16
- * @internal
17
16
  * It is an abstract class, so the only question that derived classes should
18
17
  * "answer" is what property should be used in the compact representation, such
19
18
  * as "level" and "severity".
19
+ * @internal
20
20
  */
21
21
  export default abstract class CompactGroupByRunRepresentation extends CompactGroupByRepresentation {
22
22
 
@@ -1,5 +1,5 @@
1
1
  import path from 'node:path'
2
- import { Finding } from '../model/Finding'
2
+ import Finding from '../model/Finding'
3
3
  import CompactGroupByRepresentation from './CompactGroupByRepresentation'
4
4
  import { SarifModel } from '../types'
5
5
 
@@ -14,10 +14,10 @@ import { SarifModel } from '../types'
14
14
  * grype-results-02.sarif
15
15
  * Warning: 1, Note: 20
16
16
  * ```
17
- * @internal
18
17
  * It is an abstract class, so the only question that derived classes should
19
18
  * "answer" is what property should be used in the compact representation, such
20
19
  * as "level" and "severity".
20
+ * @internal
21
21
  */
22
22
  export default abstract class CompactGroupBySarifRepresentation extends CompactGroupByRepresentation {
23
23
 
@@ -1,4 +1,4 @@
1
- import { Finding } from '../model/Finding'
1
+ import Finding from '../model/Finding'
2
2
  import CompactGroupByRepresentation from './CompactGroupByRepresentation'
3
3
  import { SarifModel } from '../types'
4
4
 
@@ -13,10 +13,10 @@ import { SarifModel } from '../types'
13
13
  * Trivy
14
14
  * Warning: 1, Note: 20
15
15
  * ```
16
- * @internal
17
16
  * It is an abstract class, so the only question that derived classes should
18
17
  * "answer" is what property should be used in the compact representation, such
19
18
  * as "level" and "severity".
19
+ * @internal
20
20
  */
21
21
  export default abstract class CompactGroupByToolNameRepresentation extends CompactGroupByRepresentation {
22
22
 
@@ -1,5 +1,5 @@
1
1
  import CompactGroupByRepresentation from './CompactGroupByRepresentation'
2
- import { Finding } from '../model/Finding'
2
+ import Finding from '../model/Finding'
3
3
 
4
4
  /**
5
5
  * Since {@link CompactGroupByRepresentation} already prepares compact representation
@@ -10,10 +10,10 @@ import { Finding } from '../model/Finding'
10
10
  * Total
11
11
  * Warning: 1, Note: 20
12
12
  * ```
13
- * @internal
14
13
  * It is an abstract class, so the only question that derived classes should
15
14
  * "answer" is what property should be used in the compact representation, such
16
15
  * as "level" and "severity".
16
+ * @internal
17
17
  */
18
18
  export default abstract class CompactTotalRepresentation extends CompactGroupByRepresentation {
19
19
 
@@ -1,7 +1,7 @@
1
1
  import { SarifModel } from '../types'
2
- import { Finding } from '../model/Finding'
2
+ import Finding from '../model/Finding'
3
3
  import { findingsComparatorByKey } from '../utils/Comparators'
4
- import FindingsArray from '../model/FindingsArray'
4
+ import FindingArray from '../model/FindingArray'
5
5
 
6
6
  /**
7
7
  * The most base abstract class for the representation. Every representation class
@@ -17,10 +17,10 @@ export default abstract class Representation {
17
17
  .findings
18
18
  .map((f: Finding): Finding => f.clone())
19
19
  .sort(findingsComparatorByKey(findingSortKey))
20
- .reduce((arr: FindingsArray, f: Finding): FindingsArray => {
20
+ .reduce((arr: FindingArray, f: Finding): FindingArray => {
21
21
  arr.push(f)
22
22
  return arr
23
- }, new FindingsArray())
23
+ }, new FindingArray())
24
24
  }
25
25
 
26
26
  protected bold(text: string): string {