@fabasoad/sarif-to-slack 1.3.4 → 1.4.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.
- package/.github/workflows/release.yml +1 -1
- package/.github/workflows/security.yml +1 -0
- package/.github/workflows/send-sarif-to-slack.yml +39 -15
- package/.pre-commit-config.yaml +4 -4
- package/.tool-versions +1 -1
- package/Makefile +1 -1
- package/README.md +8 -7
- package/api-extractor.json +2 -2
- package/dist/Logger.js +40 -30
- package/dist/SarifToSlackClient.d.ts +0 -1
- package/dist/SarifToSlackClient.d.ts.map +1 -1
- package/dist/SarifToSlackClient.js +11 -8
- package/dist/globalState.d.ts +2 -0
- package/dist/globalState.d.ts.map +1 -0
- package/dist/globalState.js +2 -0
- package/dist/index.cjs +118 -81
- package/dist/index.d.ts +529 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -2
- package/dist/model/Finding.js +7 -5
- package/dist/model/FindingArray.js +1 -1
- package/dist/model/SendIf.js +1 -1
- package/dist/model/SlackMessage.js +6 -6
- package/dist/model/color/Color.d.ts.map +1 -1
- package/dist/model/color/Color.js +1 -1
- package/dist/model/color/ColorIdentification.js +5 -5
- package/dist/model/color/ColorOptions.d.ts.map +1 -1
- package/dist/processors/CodeQLProcessor.js +1 -1
- package/dist/processors/CommonProcessor.js +1 -1
- package/dist/processors/ProcessorFactory.js +1 -1
- package/dist/processors/SnykProcessor.js +2 -1
- package/dist/representations/CompactGroupByRepresentation.js +1 -1
- package/dist/representations/CompactGroupByRunPerLevelRepresentation.js +1 -1
- package/dist/representations/CompactGroupByRunPerSeverityRepresentation.js +1 -1
- package/dist/representations/CompactGroupByRunRepresentation.js +1 -1
- package/dist/representations/CompactGroupBySarifPerLevelRepresentation.js +1 -1
- package/dist/representations/CompactGroupBySarifPerSeverityRepresentation.js +1 -1
- package/dist/representations/CompactGroupBySarifRepresentation.js +1 -1
- package/dist/representations/CompactGroupByToolNamePerLevelRepresentation.js +1 -1
- package/dist/representations/CompactGroupByToolNamePerSeverityRepresentation.js +1 -1
- package/dist/representations/CompactGroupByToolNameRepresentation.js +1 -1
- package/dist/representations/CompactTotalPerLevelRepresentation.js +1 -1
- package/dist/representations/CompactTotalPerSeverityRepresentation.js +1 -1
- package/dist/representations/CompactTotalRepresentation.js +1 -1
- package/dist/representations/Representation.js +1 -1
- package/dist/representations/RepresentationFactory.js +1 -1
- package/dist/representations/TableGroupByRunPerLevelRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupByRunPerLevelRepresentation.js +1 -1
- package/dist/representations/TableGroupByRunPerSeverityRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupByRunPerSeverityRepresentation.js +1 -1
- package/dist/representations/TableGroupByRunRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupByRunRepresentation.js +1 -1
- package/dist/representations/TableGroupBySarifPerLevelRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupBySarifPerLevelRepresentation.js +1 -1
- package/dist/representations/TableGroupBySarifPerSeverityRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupBySarifPerSeverityRepresentation.js +1 -1
- package/dist/representations/TableGroupBySarifRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupBySarifRepresentation.js +1 -1
- package/dist/representations/TableGroupByToolNamePerLevelRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupByToolNamePerLevelRepresentation.js +1 -1
- package/dist/representations/TableGroupByToolNamePerSeverityRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupByToolNamePerSeverityRepresentation.js +1 -1
- package/dist/representations/TableGroupByToolNameRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupByToolNameRepresentation.js +1 -1
- package/dist/representations/TableGroupRepresentation.d.ts +0 -1
- package/dist/representations/TableGroupRepresentation.d.ts.map +1 -1
- package/dist/representations/TableGroupRepresentation.js +3 -3
- package/dist/representations/table/Cell.d.ts.map +1 -1
- package/dist/representations/table/Cell.js +1 -1
- package/dist/representations/table/Column.d.ts +0 -1
- package/dist/representations/table/Column.d.ts.map +1 -1
- package/dist/representations/table/Column.js +4 -3
- package/dist/representations/table/Row.d.ts +0 -1
- package/dist/representations/table/Row.d.ts.map +1 -1
- package/dist/representations/table/Row.js +3 -3
- package/dist/representations/table/Table.d.ts.map +1 -1
- package/dist/representations/table/Table.js +1 -1
- package/dist/system.js +5 -5
- package/dist/tsdoc-metadata.json +1 -1
- package/dist/types.d.ts +29 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +11 -1
- package/dist/utils/Comparators.js +1 -1
- package/dist/utils/ExtendedArray.js +1 -1
- package/dist/utils/FileUtils.js +2 -2
- package/dist/utils/SarifUtils.js +1 -1
- package/dist/utils/StringUtils.js +1 -1
- package/etc/sarif-to-slack.api.md +21 -1
- package/jest.config.json +4 -4
- package/package.json +10 -9
- package/src/Logger.ts +50 -34
- package/src/SarifToSlackClient.ts +73 -68
- package/src/globalState.ts +11 -0
- package/src/index.ts +23 -12
- package/src/model/Finding.ts +36 -35
- package/src/model/FindingArray.ts +5 -5
- package/src/model/SendIf.ts +25 -25
- package/src/model/SlackMessage.ts +49 -49
- package/src/model/color/Color.ts +7 -7
- package/src/model/color/ColorIdentification.ts +77 -77
- package/src/model/color/ColorOptions.ts +1 -1
- package/src/processors/CodeQLProcessor.ts +3 -3
- package/src/processors/CommonProcessor.ts +24 -24
- package/src/processors/ProcessorFactory.ts +9 -9
- package/src/processors/SnykProcessor.ts +3 -2
- package/src/representations/CompactGroupByRepresentation.ts +20 -20
- package/src/representations/CompactGroupByRunPerLevelRepresentation.ts +2 -2
- package/src/representations/CompactGroupByRunPerSeverityRepresentation.ts +2 -2
- package/src/representations/CompactGroupByRunRepresentation.ts +10 -10
- package/src/representations/CompactGroupBySarifPerLevelRepresentation.ts +2 -2
- package/src/representations/CompactGroupBySarifPerSeverityRepresentation.ts +2 -2
- package/src/representations/CompactGroupBySarifRepresentation.ts +11 -11
- package/src/representations/CompactGroupByToolNamePerLevelRepresentation.ts +2 -2
- package/src/representations/CompactGroupByToolNamePerSeverityRepresentation.ts +2 -2
- package/src/representations/CompactGroupByToolNameRepresentation.ts +10 -10
- package/src/representations/CompactTotalPerLevelRepresentation.ts +2 -2
- package/src/representations/CompactTotalPerSeverityRepresentation.ts +2 -2
- package/src/representations/CompactTotalRepresentation.ts +5 -5
- package/src/representations/Representation.ts +8 -8
- package/src/representations/RepresentationFactory.ts +32 -32
- package/src/representations/TableGroupByRunPerLevelRepresentation.ts +3 -3
- package/src/representations/TableGroupByRunPerSeverityRepresentation.ts +3 -3
- package/src/representations/TableGroupByRunRepresentation.ts +5 -5
- package/src/representations/TableGroupBySarifPerLevelRepresentation.ts +3 -3
- package/src/representations/TableGroupBySarifPerSeverityRepresentation.ts +3 -3
- package/src/representations/TableGroupBySarifRepresentation.ts +9 -9
- package/src/representations/TableGroupByToolNamePerLevelRepresentation.ts +3 -3
- package/src/representations/TableGroupByToolNamePerSeverityRepresentation.ts +3 -3
- package/src/representations/TableGroupByToolNameRepresentation.ts +4 -4
- package/src/representations/TableGroupRepresentation.ts +32 -32
- package/src/representations/table/Cell.ts +8 -8
- package/src/representations/table/Column.ts +13 -13
- package/src/representations/table/Row.ts +17 -17
- package/src/representations/table/Table.ts +21 -21
- package/src/system.ts +5 -5
- package/src/types.ts +43 -13
- package/src/utils/Comparators.ts +6 -6
- package/src/utils/ExtendedArray.ts +1 -1
- package/src/utils/FileUtils.ts +3 -3
- package/src/utils/SarifUtils.ts +6 -6
- package/src/utils/StringUtils.ts +3 -3
- package/tests/integration/SendSarifToSlack.spec.ts +73 -67
- package/tests/representations/CompactGroupByRunPerLevelRepresentation.spec.ts +121 -0
- package/tests/representations/CompactGroupByRunPerSeverityRepresentation.spec.ts +122 -0
- package/tests/representations/CompactGroupBySarifPerLevelRepresentation.spec.ts +132 -0
- package/tests/representations/CompactGroupBySarifPerSeverityRepresentation.spec.ts +133 -0
- package/tsconfig.json +3 -4
- package/dist/sarif-to-slack.d.ts +0 -562
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { CommonProcessor } from './CommonProcessor'
|
|
2
|
-
import type { Result, Run, ToolComponent } from 'sarif'
|
|
3
|
-
import { findToolComponent } from '../utils/SarifUtils'
|
|
4
|
-
import { SnykProcessor } from './SnykProcessor'
|
|
5
|
-
import { CodeQLProcessor } from './CodeQLProcessor'
|
|
1
|
+
import { CommonProcessor } from './CommonProcessor';
|
|
2
|
+
import type { Result, Run, ToolComponent } from 'sarif';
|
|
3
|
+
import { findToolComponent } from '../utils/SarifUtils';
|
|
4
|
+
import { SnykProcessor } from './SnykProcessor';
|
|
5
|
+
import { CodeQLProcessor } from './CodeQLProcessor';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Creates a new instance of {@link CommonProcessor} class. It tries to find specific
|
|
@@ -14,10 +14,10 @@ import { CodeQLProcessor } from './CodeQLProcessor'
|
|
|
14
14
|
* @internal
|
|
15
15
|
*/
|
|
16
16
|
export function createProcessor(run: Run, result: Result): CommonProcessor {
|
|
17
|
-
const toolComponent: ToolComponent = findToolComponent(run, result)
|
|
17
|
+
const toolComponent: ToolComponent = findToolComponent(run, result);
|
|
18
18
|
switch (toolComponent.name) {
|
|
19
|
-
case 'CodeQL': return new CodeQLProcessor(run, result)
|
|
20
|
-
case 'Snyk Open Source': return new SnykProcessor(run, result)
|
|
21
|
-
default: return new CommonProcessor(run, result)
|
|
19
|
+
case 'CodeQL': return new CodeQLProcessor(run, result);
|
|
20
|
+
case 'Snyk Open Source': return new SnykProcessor(run, result);
|
|
21
|
+
default: return new CommonProcessor(run, result);
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CommonProcessor } from './CommonProcessor'
|
|
1
|
+
import { CommonProcessor } from './CommonProcessor';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* This class has extra logic for processing SARIF files produced by Snyk Open
|
|
@@ -12,8 +12,9 @@ export class SnykProcessor extends CommonProcessor {
|
|
|
12
12
|
* property where CVSS score is also defined. This method tries to get level
|
|
13
13
|
* from this "cvssv3_baseScore" property and if it fails to do so, then it tries
|
|
14
14
|
* to get CVSS score in a common way.
|
|
15
|
+
* @internal
|
|
15
16
|
*/
|
|
16
17
|
public override tryFindCvssScore(): number | undefined {
|
|
17
|
-
return this.tryFindRuleProperty<number>('cvssv3_baseScore') ?? super.tryFindCvssScore()
|
|
18
|
+
return this.tryFindRuleProperty<number>('cvssv3_baseScore') ?? super.tryFindCvssScore();
|
|
18
19
|
}
|
|
19
20
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import Representation from './Representation'
|
|
2
|
-
import type Finding from '../model/Finding'
|
|
3
|
-
import { findingsComparatorByKey } from '../utils/Comparators'
|
|
4
|
-
import { SecurityLevel, SecuritySeverity } from '../types'
|
|
1
|
+
import Representation from './Representation';
|
|
2
|
+
import type Finding from '../model/Finding';
|
|
3
|
+
import { findingsComparatorByKey } from '../utils/Comparators';
|
|
4
|
+
import { SecurityLevel, SecuritySeverity } from '../types';
|
|
5
5
|
|
|
6
|
-
const NO_VULNS_FOUND_TEXT = 'No vulnerabilities found'
|
|
6
|
+
const NO_VULNS_FOUND_TEXT = 'No vulnerabilities found';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Base class of all compact representation types. By "compact" means that it
|
|
@@ -27,44 +27,44 @@ export default abstract class CompactGroupByRepresentation extends Representatio
|
|
|
27
27
|
protected abstract groupFindings(): Map<string, Finding[]>
|
|
28
28
|
|
|
29
29
|
protected composeByProperty<K extends keyof Pick<Finding, 'level' | 'severity'>>(key: K): string {
|
|
30
|
-
const grouped: Map<string, Finding[]> = this.groupFindings()
|
|
30
|
+
const grouped: Map<string, Finding[]> = this.groupFindings();
|
|
31
31
|
if (grouped.size === 0) {
|
|
32
|
-
return NO_VULNS_FOUND_TEXT
|
|
32
|
+
return NO_VULNS_FOUND_TEXT;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
return Array.from(grouped)
|
|
36
36
|
.map(([title, findings]: [string, Finding[]]): string => {
|
|
37
|
-
findings.sort(findingsComparatorByKey(key))
|
|
37
|
+
findings.sort(findingsComparatorByKey(key));
|
|
38
38
|
const summary: string =
|
|
39
39
|
findings.length === 0
|
|
40
40
|
? NO_VULNS_FOUND_TEXT
|
|
41
|
-
: this.composeCompactReport(findings, key)
|
|
42
|
-
return `${title}\n${summary}
|
|
41
|
+
: this.composeCompactReport(findings, key);
|
|
42
|
+
return `${title}\n${summary}`;
|
|
43
43
|
})
|
|
44
|
-
.join('\n\n')
|
|
44
|
+
.join('\n\n');
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
private composeCompactReport<K extends keyof Pick<Finding, 'level' | 'severity'>>(findings: Finding[], key: K): string {
|
|
48
|
-
const result: string[] = []
|
|
48
|
+
const result: string[] = [];
|
|
49
49
|
findings
|
|
50
50
|
.reduce((grouped: Map<Finding[K], Array<Finding>>, f: Finding): Map<Finding[K], Array<Finding>> => {
|
|
51
51
|
if (!grouped.get(f[key])) {
|
|
52
|
-
grouped.set(f[key], [] as Finding[])
|
|
52
|
+
grouped.set(f[key], [] as Finding[]);
|
|
53
53
|
}
|
|
54
|
-
grouped.get(f[key])?.push(f)
|
|
55
|
-
return grouped
|
|
54
|
+
grouped.get(f[key])?.push(f);
|
|
55
|
+
return grouped;
|
|
56
56
|
}, new Map<Finding[K], Array<Finding>>())
|
|
57
57
|
.forEach((v: Array<Finding>, k: Finding[K]): void => {
|
|
58
|
-
result.push(`${this.bold(this.extractEnumValue(key, k))}: ${v.length}`)
|
|
58
|
+
result.push(`${this.bold(this.extractEnumValue(key, k))}: ${v.length}`);
|
|
59
59
|
})
|
|
60
|
-
return result.join(', ')
|
|
60
|
+
return result.join(', ');
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
private extractEnumValue<K extends keyof Pick<Finding, 'level' | 'severity'>>(key: K, prop: Finding[K]): string {
|
|
64
64
|
switch (key) {
|
|
65
|
-
case 'level': return SecurityLevel[Number(prop)]
|
|
66
|
-
case 'severity': return SecuritySeverity[Number(prop)]
|
|
67
|
-
default: throw new Error('Unknown property:', key)
|
|
65
|
+
case 'level': return SecurityLevel[Number(prop)];
|
|
66
|
+
case 'severity': return SecuritySeverity[Number(prop)];
|
|
67
|
+
default: throw new Error('Unknown property:', key);
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
}
|
|
@@ -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
|
|
@@ -9,6 +9,6 @@ import CompactGroupByRunRepresentation from './CompactGroupByRunRepresentation'
|
|
|
9
9
|
export default class CompactGroupByRunPerLevelRepresentation extends CompactGroupByRunRepresentation {
|
|
10
10
|
|
|
11
11
|
public override compose(): string {
|
|
12
|
-
return this.composeByProperty('level')
|
|
12
|
+
return this.composeByProperty('level');
|
|
13
13
|
}
|
|
14
14
|
}
|
|
@@ -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
|
|
@@ -9,6 +9,6 @@ import CompactGroupByRunRepresentation from './CompactGroupByRunRepresentation'
|
|
|
9
9
|
export default class CompactGroupByRunPerSeverityRepresentation extends CompactGroupByRunRepresentation {
|
|
10
10
|
|
|
11
11
|
public override compose(): string {
|
|
12
|
-
return this.composeByProperty('severity')
|
|
12
|
+
return this.composeByProperty('severity');
|
|
13
13
|
}
|
|
14
14
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type Finding from '../model/Finding'
|
|
2
|
-
import CompactGroupByRepresentation from './CompactGroupByRepresentation'
|
|
3
|
-
import type { SarifModel } from '../types'
|
|
1
|
+
import type Finding from '../model/Finding';
|
|
2
|
+
import CompactGroupByRepresentation from './CompactGroupByRepresentation';
|
|
3
|
+
import type { SarifModel } from '../types';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Since {@link CompactGroupByRepresentation} already prepares compact representation
|
|
@@ -21,24 +21,24 @@ import type { SarifModel } from '../types'
|
|
|
21
21
|
export default abstract class CompactGroupByRunRepresentation extends CompactGroupByRepresentation {
|
|
22
22
|
|
|
23
23
|
public constructor(model: SarifModel) {
|
|
24
|
-
super(model, 'runId')
|
|
24
|
+
super(model, 'runId');
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
protected override groupFindings(): Map<string, Finding[]> {
|
|
28
|
-
const result = new Map<string, Finding[]>()
|
|
28
|
+
const result = new Map<string, Finding[]>();
|
|
29
29
|
for (const run of this._model.runs) {
|
|
30
|
-
const key: string = this.composeGroupTitle(run.id, run.toolName)
|
|
30
|
+
const key: string = this.composeGroupTitle(run.id, run.toolName);
|
|
31
31
|
if (result.get(key) == null) {
|
|
32
|
-
result.set(key, [])
|
|
32
|
+
result.set(key, []);
|
|
33
33
|
}
|
|
34
34
|
this._model.findings
|
|
35
35
|
.filter((f: Finding): boolean => f.runId === run.id)
|
|
36
|
-
.forEach((f: Finding): number | undefined => result.get(key)?.push(f))
|
|
36
|
+
.forEach((f: Finding): number | undefined => result.get(key)?.push(f));
|
|
37
37
|
}
|
|
38
|
-
return result
|
|
38
|
+
return result;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
private composeGroupTitle(runId: number, toolName: string): string {
|
|
42
|
-
return `${this.italic(`[Run ${runId}]`)} ${this.bold(toolName)}
|
|
42
|
+
return `${this.italic(`[Run ${runId}]`)} ${this.bold(toolName)}`;
|
|
43
43
|
}
|
|
44
44
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import CompactGroupBySarifRepresentation
|
|
2
|
-
from './CompactGroupBySarifRepresentation'
|
|
2
|
+
from './CompactGroupBySarifRepresentation';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Since {@link CompactGroupBySarifRepresentation} is an abstract class, the only
|
|
@@ -10,6 +10,6 @@ import CompactGroupBySarifRepresentation
|
|
|
10
10
|
export default class CompactGroupBySarifPerLevelRepresentation extends CompactGroupBySarifRepresentation {
|
|
11
11
|
|
|
12
12
|
public override compose(): string {
|
|
13
|
-
return this.composeByProperty('level')
|
|
13
|
+
return this.composeByProperty('level');
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import CompactGroupBySarifRepresentation
|
|
2
|
-
from './CompactGroupBySarifRepresentation'
|
|
2
|
+
from './CompactGroupBySarifRepresentation';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Since {@link CompactGroupBySarifRepresentation} is an abstract class, the only
|
|
@@ -10,6 +10,6 @@ import CompactGroupBySarifRepresentation
|
|
|
10
10
|
export default class CompactGroupBySarifPerSeverityRepresentation extends CompactGroupBySarifRepresentation {
|
|
11
11
|
|
|
12
12
|
public override compose(): string {
|
|
13
|
-
return this.composeByProperty('severity')
|
|
13
|
+
return this.composeByProperty('severity');
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import path from 'node:path'
|
|
2
|
-
import type Finding from '../model/Finding'
|
|
3
|
-
import CompactGroupByRepresentation from './CompactGroupByRepresentation'
|
|
4
|
-
import type { SarifModel } from '../types'
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import type Finding from '../model/Finding';
|
|
3
|
+
import CompactGroupByRepresentation from './CompactGroupByRepresentation';
|
|
4
|
+
import type { SarifModel } from '../types';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Since {@link CompactGroupByRepresentation} already prepares compact representation
|
|
@@ -22,24 +22,24 @@ import type { SarifModel } from '../types'
|
|
|
22
22
|
export default abstract class CompactGroupBySarifRepresentation extends CompactGroupByRepresentation {
|
|
23
23
|
|
|
24
24
|
public constructor(model: SarifModel) {
|
|
25
|
-
super(model, 'sarifPath')
|
|
25
|
+
super(model, 'sarifPath');
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
protected override groupFindings(): Map<string, Finding[]> {
|
|
29
|
-
const result = new Map<string, Finding[]>()
|
|
29
|
+
const result = new Map<string, Finding[]>();
|
|
30
30
|
for (let index = 0; index < this._model.sarifFiles.length; index++) {
|
|
31
|
-
const key: string = this.composeGroupTitle(this._model.sarifFiles[index], index)
|
|
31
|
+
const key: string = this.composeGroupTitle(this._model.sarifFiles[index], index);
|
|
32
32
|
if (result.get(key) == null) {
|
|
33
|
-
result.set(key, [])
|
|
33
|
+
result.set(key, []);
|
|
34
34
|
}
|
|
35
35
|
this._model.findings
|
|
36
36
|
.filter((f: Finding): boolean => f.sarifPath === this._model.sarifFiles[index])
|
|
37
|
-
.forEach((f: Finding) => result.get(key)?.push(f))
|
|
37
|
+
.forEach((f: Finding) => result.get(key)?.push(f));
|
|
38
38
|
}
|
|
39
|
-
return result
|
|
39
|
+
return result;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
private composeGroupTitle(sarifPath: string, index: number): string {
|
|
43
|
-
return `${this.italic(`[File ${index + 1}]`)} ${this.bold(path.basename(sarifPath))}
|
|
43
|
+
return `${this.italic(`[File ${index + 1}]`)} ${this.bold(path.basename(sarifPath))}`;
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import CompactGroupByToolNameRepresentation
|
|
2
|
-
from './CompactGroupByToolNameRepresentation'
|
|
2
|
+
from './CompactGroupByToolNameRepresentation';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Since {@link CompactGroupByToolNameRepresentation} is an abstract class, the
|
|
@@ -10,6 +10,6 @@ import CompactGroupByToolNameRepresentation
|
|
|
10
10
|
export default class CompactGroupByToolNamePerLevelRepresentation extends CompactGroupByToolNameRepresentation {
|
|
11
11
|
|
|
12
12
|
public override compose(): string {
|
|
13
|
-
return this.composeByProperty('level')
|
|
13
|
+
return this.composeByProperty('level');
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import CompactGroupByToolNameRepresentation
|
|
2
|
-
from './CompactGroupByToolNameRepresentation'
|
|
2
|
+
from './CompactGroupByToolNameRepresentation';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Since {@link CompactGroupByToolNameRepresentation} is an abstract class, the
|
|
@@ -10,6 +10,6 @@ import CompactGroupByToolNameRepresentation
|
|
|
10
10
|
export default class CompactGroupByToolNamePerSeverityRepresentation extends CompactGroupByToolNameRepresentation {
|
|
11
11
|
|
|
12
12
|
public override compose(): string {
|
|
13
|
-
return this.composeByProperty('severity')
|
|
13
|
+
return this.composeByProperty('severity');
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type Finding from '../model/Finding'
|
|
2
|
-
import CompactGroupByRepresentation from './CompactGroupByRepresentation'
|
|
3
|
-
import type { SarifModel } from '../types'
|
|
1
|
+
import type Finding from '../model/Finding';
|
|
2
|
+
import CompactGroupByRepresentation from './CompactGroupByRepresentation';
|
|
3
|
+
import type { SarifModel } from '../types';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Since {@link CompactGroupByRepresentation} already prepares compact representation
|
|
@@ -21,24 +21,24 @@ import type { SarifModel } from '../types'
|
|
|
21
21
|
export default abstract class CompactGroupByToolNameRepresentation extends CompactGroupByRepresentation {
|
|
22
22
|
|
|
23
23
|
public constructor(model: SarifModel) {
|
|
24
|
-
super(model, 'toolName')
|
|
24
|
+
super(model, 'toolName');
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
protected override groupFindings(): Map<string, Finding[]> {
|
|
28
|
-
const result = new Map<string, Finding[]>()
|
|
28
|
+
const result = new Map<string, Finding[]>();
|
|
29
29
|
for (const run of this._model.runs) {
|
|
30
|
-
const key: string = this.composeGroupTitle(run.toolName)
|
|
30
|
+
const key: string = this.composeGroupTitle(run.toolName);
|
|
31
31
|
if (result.get(key) == null) {
|
|
32
|
-
result.set(key, [])
|
|
32
|
+
result.set(key, []);
|
|
33
33
|
}
|
|
34
34
|
this._model.findings
|
|
35
35
|
.filter((f: Finding): boolean => f.runId === run.id)
|
|
36
|
-
.forEach((f: Finding) => result.get(key)?.push(f))
|
|
36
|
+
.forEach((f: Finding) => result.get(key)?.push(f));
|
|
37
37
|
}
|
|
38
|
-
return result
|
|
38
|
+
return result;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
private composeGroupTitle(toolName: string): string {
|
|
42
|
-
return this.bold(toolName)
|
|
42
|
+
return this.bold(toolName);
|
|
43
43
|
}
|
|
44
44
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import CompactTotalRepresentation from './CompactTotalRepresentation'
|
|
1
|
+
import CompactTotalRepresentation from './CompactTotalRepresentation';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Since {@link CompactTotalRepresentation} is an abstract class, the only
|
|
@@ -9,6 +9,6 @@ import CompactTotalRepresentation from './CompactTotalRepresentation'
|
|
|
9
9
|
export default class CompactTotalPerLevelRepresentation extends CompactTotalRepresentation {
|
|
10
10
|
|
|
11
11
|
public override compose(): string {
|
|
12
|
-
return this.composeByProperty('level')
|
|
12
|
+
return this.composeByProperty('level');
|
|
13
13
|
}
|
|
14
14
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import CompactTotalRepresentation from './CompactTotalRepresentation'
|
|
1
|
+
import CompactTotalRepresentation from './CompactTotalRepresentation';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Since {@link CompactTotalRepresentation} is an abstract class, the only
|
|
@@ -9,6 +9,6 @@ import CompactTotalRepresentation from './CompactTotalRepresentation'
|
|
|
9
9
|
export default class CompactTotalPerSeverityRepresentation extends CompactTotalRepresentation {
|
|
10
10
|
|
|
11
11
|
public override compose(): string {
|
|
12
|
-
return this.composeByProperty('severity')
|
|
12
|
+
return this.composeByProperty('severity');
|
|
13
13
|
}
|
|
14
14
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import CompactGroupByRepresentation from './CompactGroupByRepresentation'
|
|
2
|
-
import type Finding from '../model/Finding'
|
|
1
|
+
import CompactGroupByRepresentation from './CompactGroupByRepresentation';
|
|
2
|
+
import type Finding from '../model/Finding';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Since {@link CompactGroupByRepresentation} already prepares compact representation
|
|
@@ -18,10 +18,10 @@ import type Finding from '../model/Finding'
|
|
|
18
18
|
export default abstract class CompactTotalRepresentation extends CompactGroupByRepresentation {
|
|
19
19
|
|
|
20
20
|
protected override groupFindings(): Map<string, Finding[]> {
|
|
21
|
-
const result = new Map<string, Finding[]>()
|
|
21
|
+
const result = new Map<string, Finding[]>();
|
|
22
22
|
if (this._model.findings.length > 0) {
|
|
23
|
-
result.set('Total', this._model.findings)
|
|
23
|
+
result.set('Total', this._model.findings);
|
|
24
24
|
}
|
|
25
|
-
return result
|
|
25
|
+
return result;
|
|
26
26
|
}
|
|
27
27
|
}
|
|
@@ -9,31 +9,31 @@ import { findingsComparatorByKey } from '../utils/Comparators';
|
|
|
9
9
|
* @internal
|
|
10
10
|
*/
|
|
11
11
|
export default abstract class Representation {
|
|
12
|
-
protected readonly _model: SarifModel
|
|
12
|
+
protected readonly _model: SarifModel;
|
|
13
13
|
|
|
14
14
|
public constructor(model: SarifModel, findingSortKey: keyof Finding = 'level') {
|
|
15
|
-
this._model = model
|
|
15
|
+
this._model = model;
|
|
16
16
|
this._model.findings = model
|
|
17
17
|
.findings
|
|
18
18
|
.map((f: Finding): Finding => f.clone())
|
|
19
19
|
.sort(findingsComparatorByKey(findingSortKey))
|
|
20
20
|
.reduce((arr: FindingArray, f: Finding): FindingArray => {
|
|
21
|
-
arr.push(f)
|
|
22
|
-
return arr
|
|
23
|
-
}, new FindingArray())
|
|
21
|
+
arr.push(f);
|
|
22
|
+
return arr;
|
|
23
|
+
}, new FindingArray());
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
protected bold(text: string): string {
|
|
27
|
-
return `*${text}
|
|
27
|
+
return `*${text}*`;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
protected italic(text: string): string {
|
|
31
|
-
return `_${text}_
|
|
31
|
+
return `_${text}_`;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
protected codeBlock(text: string): string {
|
|
35
35
|
// biome-ignore lint/style/useTemplate: Template literals are unreadable here
|
|
36
|
-
return '```\n' + text + '\n```'
|
|
36
|
+
return '```\n' + text + '\n```';
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
abstract compose(): string
|
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
import type Representation from './Representation'
|
|
2
|
-
import { RepresentationType, type SarifModel } from '../types'
|
|
1
|
+
import type Representation from './Representation';
|
|
2
|
+
import { RepresentationType, type SarifModel } from '../types';
|
|
3
3
|
import CompactGroupByRunPerLevelRepresentation
|
|
4
|
-
from './CompactGroupByRunPerLevelRepresentation'
|
|
4
|
+
from './CompactGroupByRunPerLevelRepresentation';
|
|
5
5
|
import CompactGroupByRunPerSeverityRepresentation
|
|
6
|
-
from './CompactGroupByRunPerSeverityRepresentation'
|
|
6
|
+
from './CompactGroupByRunPerSeverityRepresentation';
|
|
7
7
|
import CompactGroupByToolNamePerLevelRepresentation
|
|
8
|
-
from './CompactGroupByToolNamePerLevelRepresentation'
|
|
8
|
+
from './CompactGroupByToolNamePerLevelRepresentation';
|
|
9
9
|
import CompactGroupByToolNamePerSeverityRepresentation
|
|
10
|
-
from './CompactGroupByToolNamePerSeverityRepresentation'
|
|
10
|
+
from './CompactGroupByToolNamePerSeverityRepresentation';
|
|
11
11
|
import CompactGroupBySarifPerLevelRepresentation
|
|
12
|
-
from './CompactGroupBySarifPerLevelRepresentation'
|
|
12
|
+
from './CompactGroupBySarifPerLevelRepresentation';
|
|
13
13
|
import CompactGroupBySarifPerSeverityRepresentation
|
|
14
|
-
from './CompactGroupBySarifPerSeverityRepresentation'
|
|
14
|
+
from './CompactGroupBySarifPerSeverityRepresentation';
|
|
15
15
|
import CompactTotalPerSeverityRepresentation
|
|
16
|
-
from './CompactTotalPerSeverityRepresentation'
|
|
16
|
+
from './CompactTotalPerSeverityRepresentation';
|
|
17
17
|
import CompactTotalPerLevelRepresentation
|
|
18
|
-
from './CompactTotalPerLevelRepresentation'
|
|
18
|
+
from './CompactTotalPerLevelRepresentation';
|
|
19
19
|
import TableGroupByToolNamePerLevelRepresentation
|
|
20
|
-
from './TableGroupByToolNamePerLevelRepresentation'
|
|
20
|
+
from './TableGroupByToolNamePerLevelRepresentation';
|
|
21
21
|
import TableGroupByToolNamePerSeverityRepresentation
|
|
22
|
-
from './TableGroupByToolNamePerSeverityRepresentation'
|
|
22
|
+
from './TableGroupByToolNamePerSeverityRepresentation';
|
|
23
23
|
import TableGroupByRunPerLevelRepresentation
|
|
24
|
-
from './TableGroupByRunPerLevelRepresentation'
|
|
24
|
+
from './TableGroupByRunPerLevelRepresentation';
|
|
25
25
|
import TableGroupByRunPerSeverityRepresentation
|
|
26
|
-
from './TableGroupByRunPerSeverityRepresentation'
|
|
26
|
+
from './TableGroupByRunPerSeverityRepresentation';
|
|
27
27
|
import TableGroupBySarifPerLevelRepresentation
|
|
28
|
-
from './TableGroupBySarifPerLevelRepresentation'
|
|
28
|
+
from './TableGroupBySarifPerLevelRepresentation';
|
|
29
29
|
import TableGroupBySarifPerSeverityRepresentation
|
|
30
|
-
from './TableGroupBySarifPerSeverityRepresentation'
|
|
30
|
+
from './TableGroupBySarifPerSeverityRepresentation';
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
33
|
* Factory class that creates a {@link Representation} class based on the provided
|
|
@@ -36,38 +36,38 @@ import TableGroupBySarifPerSeverityRepresentation
|
|
|
36
36
|
*/
|
|
37
37
|
export function createRepresentation(
|
|
38
38
|
model: SarifModel,
|
|
39
|
-
type: RepresentationType = RepresentationType.CompactGroupByToolNamePerSeverity
|
|
39
|
+
type: RepresentationType = RepresentationType.CompactGroupByToolNamePerSeverity,
|
|
40
40
|
): Representation {
|
|
41
41
|
switch (type) {
|
|
42
42
|
case RepresentationType.CompactGroupByRunPerLevel:
|
|
43
|
-
return new CompactGroupByRunPerLevelRepresentation(model)
|
|
43
|
+
return new CompactGroupByRunPerLevelRepresentation(model);
|
|
44
44
|
case RepresentationType.CompactGroupByRunPerSeverity:
|
|
45
|
-
return new CompactGroupByRunPerSeverityRepresentation(model)
|
|
45
|
+
return new CompactGroupByRunPerSeverityRepresentation(model);
|
|
46
46
|
case RepresentationType.CompactGroupByToolNamePerLevel:
|
|
47
|
-
return new CompactGroupByToolNamePerLevelRepresentation(model)
|
|
47
|
+
return new CompactGroupByToolNamePerLevelRepresentation(model);
|
|
48
48
|
case RepresentationType.CompactGroupByToolNamePerSeverity:
|
|
49
|
-
return new CompactGroupByToolNamePerSeverityRepresentation(model)
|
|
49
|
+
return new CompactGroupByToolNamePerSeverityRepresentation(model);
|
|
50
50
|
case RepresentationType.CompactGroupBySarifPerLevel:
|
|
51
|
-
return new CompactGroupBySarifPerLevelRepresentation(model)
|
|
51
|
+
return new CompactGroupBySarifPerLevelRepresentation(model);
|
|
52
52
|
case RepresentationType.CompactGroupBySarifPerSeverity:
|
|
53
|
-
return new CompactGroupBySarifPerSeverityRepresentation(model)
|
|
53
|
+
return new CompactGroupBySarifPerSeverityRepresentation(model);
|
|
54
54
|
case RepresentationType.CompactTotalPerLevel:
|
|
55
|
-
return new CompactTotalPerLevelRepresentation(model)
|
|
55
|
+
return new CompactTotalPerLevelRepresentation(model);
|
|
56
56
|
case RepresentationType.CompactTotalPerSeverity:
|
|
57
|
-
return new CompactTotalPerSeverityRepresentation(model)
|
|
57
|
+
return new CompactTotalPerSeverityRepresentation(model);
|
|
58
58
|
case RepresentationType.TableGroupByRunPerLevel:
|
|
59
|
-
return new TableGroupByRunPerLevelRepresentation(model)
|
|
59
|
+
return new TableGroupByRunPerLevelRepresentation(model);
|
|
60
60
|
case RepresentationType.TableGroupByRunPerSeverity:
|
|
61
|
-
return new TableGroupByRunPerSeverityRepresentation(model)
|
|
61
|
+
return new TableGroupByRunPerSeverityRepresentation(model);
|
|
62
62
|
case RepresentationType.TableGroupByToolNamePerLevel:
|
|
63
|
-
return new TableGroupByToolNamePerLevelRepresentation(model)
|
|
63
|
+
return new TableGroupByToolNamePerLevelRepresentation(model);
|
|
64
64
|
case RepresentationType.TableGroupByToolNamePerSeverity:
|
|
65
|
-
return new TableGroupByToolNamePerSeverityRepresentation(model)
|
|
65
|
+
return new TableGroupByToolNamePerSeverityRepresentation(model);
|
|
66
66
|
case RepresentationType.TableGroupBySarifPerLevel:
|
|
67
|
-
return new TableGroupBySarifPerLevelRepresentation(model)
|
|
67
|
+
return new TableGroupBySarifPerLevelRepresentation(model);
|
|
68
68
|
case RepresentationType.TableGroupBySarifPerSeverity:
|
|
69
|
-
return new TableGroupBySarifPerSeverityRepresentation(model)
|
|
69
|
+
return new TableGroupBySarifPerSeverityRepresentation(model);
|
|
70
70
|
default:
|
|
71
|
-
throw new Error(`Unknown representation type: ${type}`)
|
|
71
|
+
throw new Error(`Unknown representation type: ${type}`);
|
|
72
72
|
}
|
|
73
73
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { type SarifModel, SecurityLevelValues } from '../types'
|
|
2
|
-
import TableGroupByRunRepresentation from './TableGroupByRunRepresentation'
|
|
1
|
+
import { type SarifModel, SecurityLevelValues } from '../types';
|
|
2
|
+
import TableGroupByRunRepresentation from './TableGroupByRunRepresentation';
|
|
3
3
|
|
|
4
4
|
export default class TableGroupByRunPerLevelRepresentation extends TableGroupByRunRepresentation<'level'> {
|
|
5
5
|
|
|
6
6
|
public constructor(model: SarifModel) {
|
|
7
|
-
super('level', SecurityLevelValues, model)
|
|
7
|
+
super('level', SecurityLevelValues, model);
|
|
8
8
|
}
|
|
9
9
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { type SarifModel, SecuritySeverityValues } from '../types'
|
|
2
|
-
import TableGroupByRunRepresentation from './TableGroupByRunRepresentation'
|
|
1
|
+
import { type SarifModel, SecuritySeverityValues } from '../types';
|
|
2
|
+
import TableGroupByRunRepresentation from './TableGroupByRunRepresentation';
|
|
3
3
|
|
|
4
4
|
export default class TableGroupByRunPerSeverityRepresentation extends TableGroupByRunRepresentation<'severity'> {
|
|
5
5
|
|
|
6
6
|
public constructor(model: SarifModel) {
|
|
7
|
-
super('severity', SecuritySeverityValues, model)
|
|
7
|
+
super('severity', SecuritySeverityValues, model);
|
|
8
8
|
}
|
|
9
9
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { SarifModel } from '../types'
|
|
2
|
-
import type Finding from '../model/Finding'
|
|
3
|
-
import TableGroupRepresentation from './TableGroupRepresentation'
|
|
1
|
+
import type { SarifModel } from '../types';
|
|
2
|
+
import type Finding from '../model/Finding';
|
|
3
|
+
import TableGroupRepresentation from './TableGroupRepresentation';
|
|
4
4
|
|
|
5
5
|
export default abstract class TableGroupByRunRepresentation<
|
|
6
6
|
KPer extends keyof Pick<Finding, 'level' | 'severity'>
|
|
@@ -8,8 +8,8 @@ export default abstract class TableGroupByRunRepresentation<
|
|
|
8
8
|
protected constructor(
|
|
9
9
|
keyPer: KPer,
|
|
10
10
|
values: string[],
|
|
11
|
-
model: SarifModel
|
|
11
|
+
model: SarifModel,
|
|
12
12
|
) {
|
|
13
|
-
super('runId', keyPer, values, model)
|
|
13
|
+
super('runId', keyPer, values, model);
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { type SarifModel, SecurityLevelValues } from '../types'
|
|
2
|
-
import TableGroupBySarifRepresentation from './TableGroupBySarifRepresentation'
|
|
1
|
+
import { type SarifModel, SecurityLevelValues } from '../types';
|
|
2
|
+
import TableGroupBySarifRepresentation from './TableGroupBySarifRepresentation';
|
|
3
3
|
|
|
4
4
|
export default class TableGroupBySarifPerLevelRepresentation extends TableGroupBySarifRepresentation<'level'> {
|
|
5
5
|
|
|
6
6
|
public constructor(model: SarifModel) {
|
|
7
|
-
super('level', SecurityLevelValues, model)
|
|
7
|
+
super('level', SecurityLevelValues, model);
|
|
8
8
|
}
|
|
9
9
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { type SarifModel, SecuritySeverityValues } from '../types'
|
|
2
|
-
import TableGroupBySarifRepresentation from './TableGroupBySarifRepresentation'
|
|
1
|
+
import { type SarifModel, SecuritySeverityValues } from '../types';
|
|
2
|
+
import TableGroupBySarifRepresentation from './TableGroupBySarifRepresentation';
|
|
3
3
|
|
|
4
4
|
export default class TableGroupBySarifPerSeverityRepresentation extends TableGroupBySarifRepresentation<'severity'> {
|
|
5
5
|
|
|
6
6
|
public constructor(model: SarifModel) {
|
|
7
|
-
super('severity', SecuritySeverityValues, model)
|
|
7
|
+
super('severity', SecuritySeverityValues, model);
|
|
8
8
|
}
|
|
9
9
|
}
|