@fabasoad/sarif-to-slack 0.2.4 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/release.yml +1 -1
- package/.github/workflows/security.yml +0 -1
- package/.github/workflows/send-sarif-to-slack.yml +148 -76
- package/.gitleaksignore +8 -0
- package/.pre-commit-config.yaml +3 -3
- package/.tool-versions +1 -1
- package/dist/Logger.js +4 -1
- package/dist/SarifToSlackClient.d.ts +33 -0
- package/dist/SarifToSlackClient.d.ts.map +1 -0
- package/dist/SarifToSlackClient.js +178 -0
- package/dist/SlackMessageBuilder.js +34 -82
- package/dist/System.d.ts +2 -0
- package/dist/System.d.ts.map +1 -0
- package/dist/System.js +15 -0
- package/dist/index.cjs +843 -467
- package/dist/index.d.ts +35 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +36 -12
- package/dist/model/Color.d.ts +70 -0
- package/dist/model/Color.d.ts.map +1 -0
- package/dist/model/Color.js +119 -0
- package/dist/model/Finding.d.ts +2 -0
- package/dist/model/Finding.d.ts.map +1 -0
- package/dist/model/Finding.js +93 -0
- package/dist/model/FindingsArray.d.ts +2 -0
- package/dist/model/FindingsArray.d.ts.map +1 -0
- package/dist/model/FindingsArray.js +24 -0
- package/dist/processors/CodeQLProcessor.d.ts +2 -0
- package/dist/processors/CodeQLProcessor.d.ts.map +1 -0
- package/dist/processors/CodeQLProcessor.js +17 -0
- package/dist/processors/CommonProcessor.d.ts +2 -0
- package/dist/processors/CommonProcessor.d.ts.map +1 -0
- package/dist/processors/CommonProcessor.js +84 -0
- package/dist/processors/ProcessorFactory.d.ts +2 -0
- package/dist/processors/ProcessorFactory.d.ts.map +1 -0
- package/dist/processors/ProcessorFactory.js +22 -0
- package/dist/processors/SnykProcessor.d.ts +2 -0
- package/dist/processors/SnykProcessor.d.ts.map +1 -0
- package/dist/processors/SnykProcessor.js +18 -0
- package/dist/representations/CompactGroupByRepresentation.d.ts +2 -0
- package/dist/representations/CompactGroupByRepresentation.d.ts.map +1 -0
- package/dist/representations/CompactGroupByRepresentation.js +58 -0
- package/dist/representations/CompactGroupByRunPerLevelRepresentation.d.ts +2 -0
- package/dist/representations/CompactGroupByRunPerLevelRepresentation.d.ts.map +1 -0
- package/dist/representations/CompactGroupByRunPerLevelRepresentation.js +13 -0
- package/dist/representations/CompactGroupByRunPerSeverityRepresentation.d.ts +2 -0
- package/dist/representations/CompactGroupByRunPerSeverityRepresentation.d.ts.map +1 -0
- package/dist/representations/CompactGroupByRunPerSeverityRepresentation.js +13 -0
- package/dist/representations/CompactGroupByRunRepresentation.d.ts +2 -0
- package/dist/representations/CompactGroupByRunRepresentation.d.ts.map +1 -0
- package/dist/representations/CompactGroupByRunRepresentation.js +39 -0
- package/dist/representations/CompactGroupBySarifPerLevelRepresentation.d.ts +2 -0
- package/dist/representations/CompactGroupBySarifPerLevelRepresentation.d.ts.map +1 -0
- package/dist/representations/CompactGroupBySarifPerLevelRepresentation.js +13 -0
- package/dist/representations/CompactGroupBySarifPerSeverityRepresentation.d.ts +2 -0
- package/dist/representations/CompactGroupBySarifPerSeverityRepresentation.d.ts.map +1 -0
- package/dist/representations/CompactGroupBySarifPerSeverityRepresentation.js +13 -0
- package/dist/representations/CompactGroupBySarifRepresentation.d.ts +2 -0
- package/dist/representations/CompactGroupBySarifRepresentation.d.ts.map +1 -0
- package/dist/representations/CompactGroupBySarifRepresentation.js +40 -0
- package/dist/representations/CompactGroupByToolNamePerLevelRepresentation.d.ts +2 -0
- package/dist/representations/CompactGroupByToolNamePerLevelRepresentation.d.ts.map +1 -0
- package/dist/representations/CompactGroupByToolNamePerLevelRepresentation.js +13 -0
- package/dist/representations/CompactGroupByToolNamePerSeverityRepresentation.d.ts +2 -0
- package/dist/representations/CompactGroupByToolNamePerSeverityRepresentation.d.ts.map +1 -0
- package/dist/representations/CompactGroupByToolNamePerSeverityRepresentation.js +13 -0
- package/dist/representations/CompactGroupByToolNameRepresentation.d.ts +2 -0
- package/dist/representations/CompactGroupByToolNameRepresentation.d.ts.map +1 -0
- package/dist/representations/CompactGroupByToolNameRepresentation.js +39 -0
- package/dist/representations/CompactTotalPerLevelRepresentation.d.ts +2 -0
- package/dist/representations/CompactTotalPerLevelRepresentation.d.ts.map +1 -0
- package/dist/representations/CompactTotalPerLevelRepresentation.js +13 -0
- package/dist/representations/CompactTotalPerSeverityRepresentation.d.ts +2 -0
- package/dist/representations/CompactTotalPerSeverityRepresentation.d.ts.map +1 -0
- package/dist/representations/CompactTotalPerSeverityRepresentation.js +13 -0
- package/dist/representations/CompactTotalRepresentation.d.ts +2 -0
- package/dist/representations/CompactTotalRepresentation.d.ts.map +1 -0
- package/dist/representations/CompactTotalRepresentation.js +25 -0
- package/dist/representations/Representation.d.ts +2 -0
- package/dist/representations/Representation.d.ts.map +1 -0
- package/dist/representations/Representation.js +28 -0
- package/dist/representations/RepresentationFactory.d.ts +2 -0
- package/dist/representations/RepresentationFactory.d.ts.map +1 -0
- package/dist/representations/RepresentationFactory.js +37 -0
- package/dist/sarif-to-slack.d.ts +337 -85
- package/dist/tsdoc-metadata.json +1 -1
- package/dist/types.d.ts +215 -51
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +225 -33
- package/dist/utils/Comparators.d.ts +2 -0
- package/dist/utils/Comparators.d.ts.map +1 -0
- package/dist/utils/Comparators.js +18 -0
- package/dist/utils/ExtendedArray.d.ts +2 -0
- package/dist/utils/ExtendedArray.d.ts.map +1 -0
- package/dist/utils/ExtendedArray.js +11 -0
- package/dist/utils/FileUtils.d.ts +2 -0
- package/dist/utils/FileUtils.d.ts.map +1 -0
- package/dist/utils/FileUtils.js +51 -0
- package/dist/utils/SarifUtils.js +19 -53
- package/etc/sarif-to-slack.api.md +161 -99
- package/jest.config.json +2 -2
- package/package.json +9 -9
- package/scripts/save-metadata.sh +15 -0
- package/src/Logger.ts +4 -0
- package/src/SarifToSlackClient.ts +202 -0
- package/src/SlackMessageBuilder.ts +35 -115
- package/src/System.ts +16 -0
- package/src/index.ts +47 -20
- package/src/model/Color.ts +201 -0
- package/src/model/Finding.ts +137 -0
- package/src/model/FindingsArray.ts +27 -0
- package/src/processors/CodeQLProcessor.ts +19 -0
- package/src/processors/CommonProcessor.ts +103 -0
- package/src/processors/ProcessorFactory.ts +23 -0
- package/src/processors/SnykProcessor.ts +19 -0
- package/src/representations/CompactGroupByRepresentation.ts +67 -0
- package/src/representations/CompactGroupByRunPerLevelRepresentation.ts +14 -0
- package/src/representations/CompactGroupByRunPerSeverityRepresentation.ts +14 -0
- package/src/representations/CompactGroupByRunRepresentation.ts +44 -0
- package/src/representations/CompactGroupBySarifPerLevelRepresentation.ts +15 -0
- package/src/representations/CompactGroupBySarifPerSeverityRepresentation.ts +15 -0
- package/src/representations/CompactGroupBySarifRepresentation.ts +45 -0
- package/src/representations/CompactGroupByToolNamePerLevelRepresentation.ts +15 -0
- package/src/representations/CompactGroupByToolNamePerSeverityRepresentation.ts +15 -0
- package/src/representations/CompactGroupByToolNameRepresentation.ts +44 -0
- package/src/representations/CompactTotalPerLevelRepresentation.ts +14 -0
- package/src/representations/CompactTotalPerSeverityRepresentation.ts +14 -0
- package/src/representations/CompactTotalRepresentation.ts +27 -0
- package/src/representations/Representation.ts +35 -0
- package/src/representations/RepresentationFactory.ts +49 -0
- package/src/types.ts +270 -53
- package/src/utils/Comparators.ts +19 -0
- package/src/utils/ExtendedArray.ts +11 -0
- package/src/utils/FileUtils.ts +60 -0
- package/src/utils/SarifUtils.ts +19 -71
- package/test-data/sarif/codeql-python.sarif +1448 -1
- package/test-data/sarif/codeql-typescript.sarif +3474 -1
- package/test-data/sarif/grype-github-actions.sarif +65 -0
- package/test-data/sarif/osv-scanner-composer.sarif +972 -0
- package/test-data/sarif/osv-scanner-container.sarif +2278 -0
- package/test-data/sarif/osv-scanner-gomodules.sarif +813 -0
- package/test-data/sarif/osv-scanner-hex.sarif +147 -0
- package/test-data/sarif/osv-scanner-maven.sarif +171 -0
- package/test-data/sarif/osv-scanner-npm.sarif +627 -0
- package/test-data/sarif/osv-scanner-pip.sarif +206 -0
- package/test-data/sarif/osv-scanner-pipenv.sarif +243 -0
- package/test-data/sarif/osv-scanner-pnpm.sarif +174 -0
- package/test-data/sarif/osv-scanner-poetry.sarif +1893 -0
- package/test-data/sarif/osv-scanner-rubygems.sarif +402 -0
- package/test-data/sarif/osv-scanner-uv.sarif +206 -0
- package/test-data/sarif/osv-scanner-yarn.sarif +5207 -0
- package/test-data/sarif/runs-0.sarif +5 -0
- package/test-data/sarif/runs-2-tools-2-results-0.sarif +1 -1
- package/test-data/sarif/runs-2-tools-2.sarif +1 -1
- package/test-data/sarif/runs-3-tools-2-results-0.sarif +1 -1
- package/test-data/sarif/runs-3-tools-2.sarif +1 -1
- package/test-data/sarif/tmp/codeql-csharp.sarif +1 -0
- package/test-data/sarif/tmp/grype-container.sarif +1774 -0
- package/test-data/sarif/tmp/runs-1-tools-1-results-0.sarif +18 -0
- package/test-data/sarif/tmp/runs-2-tools-2.sarif +686 -0
- package/test-data/sarif/trivy-iac.sarif +1 -1
- package/tests/integration/SendSarifToSlack.spec.ts +95 -27
- package/tsconfig.json +2 -0
- package/dist/Processors.d.ts +0 -2
- package/dist/Processors.d.ts.map +0 -1
- package/dist/Processors.js +0 -61
- package/dist/SarifToSlackService.d.ts +0 -39
- package/dist/SarifToSlackService.d.ts.map +0 -1
- package/dist/SarifToSlackService.js +0 -102
- package/dist/model/SarifModelPerRun.d.ts +0 -2
- package/dist/model/SarifModelPerRun.d.ts.map +0 -1
- package/dist/model/SarifModelPerRun.js +0 -90
- package/dist/model/SarifModelPerSarif.d.ts +0 -2
- package/dist/model/SarifModelPerSarif.d.ts.map +0 -1
- package/dist/model/SarifModelPerSarif.js +0 -102
- package/dist/model/types.d.ts +0 -2
- package/dist/model/types.d.ts.map +0 -1
- package/dist/model/types.js +0 -49
- package/dist/utils/SortUtils.d.ts +0 -2
- package/dist/utils/SortUtils.d.ts.map +0 -1
- package/dist/utils/SortUtils.js +0 -20
- package/dist/version.d.ts +0 -2
- package/dist/version.d.ts.map +0 -1
- package/dist/version.js +0 -11
- package/scripts/save-version.sh +0 -13
- package/src/Processors.ts +0 -68
- package/src/SarifToSlackService.ts +0 -115
- package/src/model/SarifModelPerRun.ts +0 -123
- package/src/model/SarifModelPerSarif.ts +0 -126
- package/src/model/types.ts +0 -50
- package/src/utils/SortUtils.ts +0 -33
- package/src/version.ts +0 -10
- package/tests/Processors.spec.ts +0 -76
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SnykProcessor.d.ts","sourceRoot":"","sources":["../../src/processors/SnykProcessor.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { CommonProcessor } from './CommonProcessor';
|
|
2
|
+
/**
|
|
3
|
+
* This class has extra logic for processing SARIF files produced by Snyk Open
|
|
4
|
+
* Source tool.
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
export class SnykProcessor extends CommonProcessor {
|
|
8
|
+
/**
|
|
9
|
+
* Rules in SARIF files produced by Snyk Open Source has additional "cvssv3_baseScore"
|
|
10
|
+
* property where CVSS score is also defined. This method tries to get level
|
|
11
|
+
* from this "cvssv3_baseScore" property and if it fails to do so, then it tries
|
|
12
|
+
* to get CVSS score in a common way.
|
|
13
|
+
*/
|
|
14
|
+
tryFindCvssScore() {
|
|
15
|
+
return this.tryFindRuleProperty('cvssv3_baseScore') ?? super.tryFindCvssScore();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU255a1Byb2Nlc3Nvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wcm9jZXNzb3JzL1NueWtQcm9jZXNzb3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBRW5EOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8sYUFBYyxTQUFRLGVBQWU7SUFFaEQ7Ozs7O09BS0c7SUFDYSxnQkFBZ0I7UUFDOUIsT0FBTyxJQUFJLENBQUMsbUJBQW1CLENBQVMsa0JBQWtCLENBQUMsSUFBSSxLQUFLLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQTtJQUN6RixDQUFDO0NBQ0YifQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompactGroupByRepresentation.d.ts","sourceRoot":"","sources":["../../src/representations/CompactGroupByRepresentation.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import Representation from './Representation';
|
|
2
|
+
import { findingsComparatorByKey } from '../utils/Comparators';
|
|
3
|
+
import { SecurityLevel, SecuritySeverity } from '../types';
|
|
4
|
+
const NO_VULNS_FOUND_TEXT = 'No vulnerabilities found';
|
|
5
|
+
/**
|
|
6
|
+
* Base class of all compact representation types. By "compact" means that it
|
|
7
|
+
* groups findings by the {@link Finding} property, such as "severity" or "level".
|
|
8
|
+
* So, in fact it already prepares this in case of "severity":
|
|
9
|
+
* @example
|
|
10
|
+
* ```text
|
|
11
|
+
* Critical: 1, High: 5, Medium: 2, Low: 20, None: 1, Unknown: 120
|
|
12
|
+
* ```
|
|
13
|
+
* or this in case of "level":
|
|
14
|
+
* @example
|
|
15
|
+
* ```text
|
|
16
|
+
* Error: 6, Warning: 2, Note: 20, None: 1, Unknown: 120
|
|
17
|
+
* ```
|
|
18
|
+
* It is an abstract class, so the only question that derived classes should
|
|
19
|
+
* "answer" is how to group finding to show the compact representation.
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
export default class CompactGroupByRepresentation extends Representation {
|
|
23
|
+
composeByProperty(key) {
|
|
24
|
+
const grouped = this.groupFindings();
|
|
25
|
+
if (grouped.size === 0) {
|
|
26
|
+
return NO_VULNS_FOUND_TEXT;
|
|
27
|
+
}
|
|
28
|
+
return Array.from(grouped)
|
|
29
|
+
.map(([title, findings]) => {
|
|
30
|
+
findings.sort(findingsComparatorByKey(key));
|
|
31
|
+
const summary = findings.length === 0
|
|
32
|
+
? NO_VULNS_FOUND_TEXT
|
|
33
|
+
: this.composeCompactReport(findings, key);
|
|
34
|
+
return `${title}\n${summary}`;
|
|
35
|
+
})
|
|
36
|
+
.join('\n\n');
|
|
37
|
+
}
|
|
38
|
+
composeCompactReport(findings, key) {
|
|
39
|
+
return Object
|
|
40
|
+
.entries(Object.groupBy(findings, (f) => f[key]))
|
|
41
|
+
.map(([prop, findings2]) => {
|
|
42
|
+
if (findings2 == null) {
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
return `${this.bold(this.extractEnumValue(key, prop))}: ${findings2.length}`;
|
|
46
|
+
})
|
|
47
|
+
.filter((v) => v != null)
|
|
48
|
+
.join(', ');
|
|
49
|
+
}
|
|
50
|
+
extractEnumValue(key, prop) {
|
|
51
|
+
switch (key) {
|
|
52
|
+
case 'level': return SecurityLevel[Number(prop)];
|
|
53
|
+
case 'severity': return SecuritySeverity[Number(prop)];
|
|
54
|
+
default: throw new Error('Unknown property:', key);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29tcGFjdEdyb3VwQnlSZXByZXNlbnRhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9yZXByZXNlbnRhdGlvbnMvQ29tcGFjdEdyb3VwQnlSZXByZXNlbnRhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLGNBQWMsTUFBTSxrQkFBa0IsQ0FBQTtBQUU3QyxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQTtBQUM5RCxPQUFPLEVBQUUsYUFBYSxFQUFFLGdCQUFnQixFQUFFLE1BQU0sVUFBVSxDQUFDO0FBRTNELE1BQU0sbUJBQW1CLEdBQUcsMEJBQTBCLENBQUE7QUFFdEQ7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFDSCxNQUFNLENBQUMsT0FBTyxPQUFnQiw0QkFBNkIsU0FBUSxjQUFjO0lBSXJFLGlCQUFpQixDQUFzRCxHQUFNO1FBQ3JGLE1BQU0sT0FBTyxHQUEyQixJQUFJLENBQUMsYUFBYSxFQUFFLENBQUE7UUFDNUQsSUFBSSxPQUFPLENBQUMsSUFBSSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3ZCLE9BQU8sbUJBQW1CLENBQUE7UUFDNUIsQ0FBQztRQUVELE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7YUFDdkIsR0FBRyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFzQixFQUFVLEVBQUU7WUFDdEQsUUFBUSxDQUFDLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFBO1lBQzNDLE1BQU0sT0FBTyxHQUNYLFFBQVEsQ0FBQyxNQUFNLEtBQUssQ0FBQztnQkFDckIsQ0FBQyxDQUFDLG1CQUFtQjtnQkFDckIsQ0FBQyxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxRQUFRLEVBQUUsR0FBRyxDQUFDLENBQUE7WUFDNUMsT0FBTyxHQUFHLEtBQUssS0FBSyxPQUFPLEVBQUUsQ0FBQTtRQUMvQixDQUFDLENBQUM7YUFDRCxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUE7SUFDakIsQ0FBQztJQUVPLG9CQUFvQixDQUFzRCxRQUFtQixFQUFFLEdBQU07UUFDM0csT0FBTyxNQUFNO2FBQ1YsT0FBTyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBVSxFQUFlLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFnQixDQUFDLENBQUM7YUFDckYsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsU0FBUyxDQUFrQyxFQUFzQixFQUFFO1lBQzlFLElBQUksU0FBUyxJQUFJLElBQUksRUFBRSxDQUFDO2dCQUN0QixPQUFPLFNBQVMsQ0FBQTtZQUNsQixDQUFDO1lBQ0QsT0FBTyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQyxLQUFLLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQTtRQUM5RSxDQUFDLENBQUM7YUFDRCxNQUFNLENBQUMsQ0FBQyxDQUFxQixFQUFlLEVBQUUsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDO2FBQ3pELElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQTtJQUNmLENBQUM7SUFFTyxnQkFBZ0IsQ0FBc0QsR0FBTSxFQUFFLElBQVk7UUFDaEcsUUFBUSxHQUFHLEVBQUUsQ0FBQztZQUNaLEtBQUssT0FBTyxDQUFDLENBQUMsT0FBTyxhQUFhLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUE7WUFDaEQsS0FBSyxVQUFVLENBQUMsQ0FBQyxPQUFPLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFBO1lBQ3RELE9BQU8sQ0FBQyxDQUFDLE1BQU0sSUFBSSxLQUFLLENBQUMsbUJBQW1CLEVBQUUsR0FBRyxDQUFDLENBQUE7UUFDcEQsQ0FBQztJQUNILENBQUM7Q0FDRiJ9
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompactGroupByRunPerLevelRepresentation.d.ts","sourceRoot":"","sources":["../../src/representations/CompactGroupByRunPerLevelRepresentation.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import CompactGroupByRunRepresentation from './CompactGroupByRunRepresentation';
|
|
2
|
+
/**
|
|
3
|
+
* Since {@link CompactGroupByRunRepresentation} is an abstract class, the only
|
|
4
|
+
* question that this class should "answer" is what property should be used in
|
|
5
|
+
* the compact representation. In this case it is "level".
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export default class CompactGroupByRunPerLevelRepresentation extends CompactGroupByRunRepresentation {
|
|
9
|
+
compose() {
|
|
10
|
+
return this.composeByProperty('level');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29tcGFjdEdyb3VwQnlSdW5QZXJMZXZlbFJlcHJlc2VudGF0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3JlcHJlc2VudGF0aW9ucy9Db21wYWN0R3JvdXBCeVJ1blBlckxldmVsUmVwcmVzZW50YXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTywrQkFBK0IsTUFBTSxtQ0FBbUMsQ0FBQztBQUVoRjs7Ozs7R0FLRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQU8sdUNBQXdDLFNBQVEsK0JBQStCO0lBRWxGLE9BQU87UUFDckIsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxDQUFDLENBQUE7SUFDeEMsQ0FBQztDQUNGIn0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompactGroupByRunPerSeverityRepresentation.d.ts","sourceRoot":"","sources":["../../src/representations/CompactGroupByRunPerSeverityRepresentation.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import CompactGroupByRunRepresentation from './CompactGroupByRunRepresentation';
|
|
2
|
+
/**
|
|
3
|
+
* Since {@link CompactGroupByRunRepresentation} is an abstract class, the only
|
|
4
|
+
* question that this class should "answer" is what property should be used in
|
|
5
|
+
* the compact representation. In this case it is "severity".
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export default class CompactGroupByRunPerSeverityRepresentation extends CompactGroupByRunRepresentation {
|
|
9
|
+
compose() {
|
|
10
|
+
return this.composeByProperty('severity');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29tcGFjdEdyb3VwQnlSdW5QZXJTZXZlcml0eVJlcHJlc2VudGF0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3JlcHJlc2VudGF0aW9ucy9Db21wYWN0R3JvdXBCeVJ1blBlclNldmVyaXR5UmVwcmVzZW50YXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTywrQkFBK0IsTUFBTSxtQ0FBbUMsQ0FBQztBQUVoRjs7Ozs7R0FLRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQU8sMENBQTJDLFNBQVEsK0JBQStCO0lBRXJGLE9BQU87UUFDckIsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUMsVUFBVSxDQUFDLENBQUE7SUFDM0MsQ0FBQztDQUNGIn0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompactGroupByRunRepresentation.d.ts","sourceRoot":"","sources":["../../src/representations/CompactGroupByRunRepresentation.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import CompactGroupByRepresentation from './CompactGroupByRepresentation';
|
|
2
|
+
/**
|
|
3
|
+
* Since {@link CompactGroupByRepresentation} already prepares compact representation
|
|
4
|
+
* of findings, this class defines a grouping rule. In this case it groups
|
|
5
|
+
* findings by run. Every run will be grouped separately, such as:
|
|
6
|
+
* @example
|
|
7
|
+
* ```text
|
|
8
|
+
* [Run 1] Grype
|
|
9
|
+
* Error: 1, Warning: 4
|
|
10
|
+
* [Run 2] Grype
|
|
11
|
+
* Warning: 1, Note: 20
|
|
12
|
+
* ```
|
|
13
|
+
* @internal
|
|
14
|
+
* It is an abstract class, so the only question that derived classes should
|
|
15
|
+
* "answer" is what property should be used in the compact representation, such
|
|
16
|
+
* as "level" and "severity".
|
|
17
|
+
*/
|
|
18
|
+
export default class CompactGroupByRunRepresentation extends CompactGroupByRepresentation {
|
|
19
|
+
constructor(model) {
|
|
20
|
+
super(model, 'runId');
|
|
21
|
+
}
|
|
22
|
+
groupFindings() {
|
|
23
|
+
const result = new Map();
|
|
24
|
+
for (const run of this._model.runs) {
|
|
25
|
+
const key = this.composeGroupTitle(run.id, run.toolName);
|
|
26
|
+
if (result.get(key) == null) {
|
|
27
|
+
result.set(key, []);
|
|
28
|
+
}
|
|
29
|
+
this._model.findings
|
|
30
|
+
.filter((f) => f.runId === run.id)
|
|
31
|
+
.forEach((f) => result.get(key)?.push(f));
|
|
32
|
+
}
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
composeGroupTitle(runId, toolName) {
|
|
36
|
+
return `${this.italic(`[Run ${runId}]`)} ${this.bold(toolName)}`;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29tcGFjdEdyb3VwQnlSdW5SZXByZXNlbnRhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9yZXByZXNlbnRhdGlvbnMvQ29tcGFjdEdyb3VwQnlSdW5SZXByZXNlbnRhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLDRCQUE0QixNQUFNLGdDQUFnQyxDQUFBO0FBR3pFOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQWdCLCtCQUFnQyxTQUFRLDRCQUE0QjtJQUVoRyxZQUFtQixLQUFpQjtRQUNsQyxLQUFLLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFBO0lBQ3ZCLENBQUM7SUFFa0IsYUFBYTtRQUM5QixNQUFNLE1BQU0sR0FBRyxJQUFJLEdBQUcsRUFBcUIsQ0FBQTtRQUMzQyxLQUFLLE1BQU0sR0FBRyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDbkMsTUFBTSxHQUFHLEdBQVcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFBO1lBQ2hFLElBQUksTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQztnQkFDNUIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLENBQUE7WUFDckIsQ0FBQztZQUNELElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUTtpQkFDakIsTUFBTSxDQUFDLENBQUMsQ0FBVSxFQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxLQUFLLEdBQUcsQ0FBQyxFQUFFLENBQUM7aUJBQ25ELE9BQU8sQ0FBQyxDQUFDLENBQVUsRUFBc0IsRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFDMUUsQ0FBQztRQUNELE9BQU8sTUFBTSxDQUFBO0lBQ2YsQ0FBQztJQUVPLGlCQUFpQixDQUFDLEtBQWEsRUFBRSxRQUFnQjtRQUN2RCxPQUFPLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEtBQUssR0FBRyxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFBO0lBQ2xFLENBQUM7Q0FDRiJ9
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompactGroupBySarifPerLevelRepresentation.d.ts","sourceRoot":"","sources":["../../src/representations/CompactGroupBySarifPerLevelRepresentation.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import CompactGroupBySarifRepresentation from './CompactGroupBySarifRepresentation';
|
|
2
|
+
/**
|
|
3
|
+
* Since {@link CompactGroupBySarifRepresentation} is an abstract class, the only
|
|
4
|
+
* question that this class should "answer" is what property should be used in
|
|
5
|
+
* the compact representation. In this case it is "level".
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export default class CompactGroupBySarifPerLevelRepresentation extends CompactGroupBySarifRepresentation {
|
|
9
|
+
compose() {
|
|
10
|
+
return this.composeByProperty('level');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29tcGFjdEdyb3VwQnlTYXJpZlBlckxldmVsUmVwcmVzZW50YXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcmVwcmVzZW50YXRpb25zL0NvbXBhY3RHcm91cEJ5U2FyaWZQZXJMZXZlbFJlcHJlc2VudGF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8saUNBQWlDLE1BQ2pDLHFDQUFxQyxDQUFBO0FBRTVDOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLE9BQU8sT0FBTyx5Q0FBMEMsU0FBUSxpQ0FBaUM7SUFFdEYsT0FBTztRQUNyQixPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsQ0FBQTtJQUN4QyxDQUFDO0NBQ0YifQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompactGroupBySarifPerSeverityRepresentation.d.ts","sourceRoot":"","sources":["../../src/representations/CompactGroupBySarifPerSeverityRepresentation.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import CompactGroupBySarifRepresentation from './CompactGroupBySarifRepresentation';
|
|
2
|
+
/**
|
|
3
|
+
* Since {@link CompactGroupBySarifRepresentation} is an abstract class, the only
|
|
4
|
+
* question that this class should "answer" is what property should be used in
|
|
5
|
+
* the compact representation. In this case it is "severity".
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export default class CompactGroupBySarifPerSeverityRepresentation extends CompactGroupBySarifRepresentation {
|
|
9
|
+
compose() {
|
|
10
|
+
return this.composeByProperty('severity');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29tcGFjdEdyb3VwQnlTYXJpZlBlclNldmVyaXR5UmVwcmVzZW50YXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcmVwcmVzZW50YXRpb25zL0NvbXBhY3RHcm91cEJ5U2FyaWZQZXJTZXZlcml0eVJlcHJlc2VudGF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8saUNBQWlDLE1BQ2pDLHFDQUFxQyxDQUFBO0FBRTVDOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLE9BQU8sT0FBTyw0Q0FBNkMsU0FBUSxpQ0FBaUM7SUFFekYsT0FBTztRQUNyQixPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxVQUFVLENBQUMsQ0FBQTtJQUMzQyxDQUFDO0NBQ0YifQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompactGroupBySarifRepresentation.d.ts","sourceRoot":"","sources":["../../src/representations/CompactGroupBySarifRepresentation.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import CompactGroupByRepresentation from './CompactGroupByRepresentation';
|
|
3
|
+
/**
|
|
4
|
+
* Since {@link CompactGroupByRepresentation} already prepares compact representation
|
|
5
|
+
* of findings, this class defines a grouping rule. In this case it groups
|
|
6
|
+
* findings by SARIF file. Every SARIF file will be grouped separately, such as:
|
|
7
|
+
* @example
|
|
8
|
+
* ```text
|
|
9
|
+
* grype-results-01.sarif
|
|
10
|
+
* Error: 1, Warning: 4
|
|
11
|
+
* grype-results-02.sarif
|
|
12
|
+
* Warning: 1, Note: 20
|
|
13
|
+
* ```
|
|
14
|
+
* @internal
|
|
15
|
+
* It is an abstract class, so the only question that derived classes should
|
|
16
|
+
* "answer" is what property should be used in the compact representation, such
|
|
17
|
+
* as "level" and "severity".
|
|
18
|
+
*/
|
|
19
|
+
export default class CompactGroupBySarifRepresentation extends CompactGroupByRepresentation {
|
|
20
|
+
constructor(model) {
|
|
21
|
+
super(model, 'sarifPath');
|
|
22
|
+
}
|
|
23
|
+
groupFindings() {
|
|
24
|
+
const result = new Map();
|
|
25
|
+
for (let index = 0; index < this._model.sarifFiles.length; index++) {
|
|
26
|
+
const key = this.composeGroupTitle(this._model.sarifFiles[index], index);
|
|
27
|
+
if (result.get(key) == null) {
|
|
28
|
+
result.set(key, []);
|
|
29
|
+
}
|
|
30
|
+
this._model.findings
|
|
31
|
+
.filter((f) => f.sarifPath === this._model.sarifFiles[index])
|
|
32
|
+
.forEach((f) => result.get(key)?.push(f));
|
|
33
|
+
}
|
|
34
|
+
return result;
|
|
35
|
+
}
|
|
36
|
+
composeGroupTitle(sarifPath, index) {
|
|
37
|
+
return `${this.italic(`[File ${index + 1}]`)} ${this.bold(path.basename(sarifPath))}`;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29tcGFjdEdyb3VwQnlTYXJpZlJlcHJlc2VudGF0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3JlcHJlc2VudGF0aW9ucy9Db21wYWN0R3JvdXBCeVNhcmlmUmVwcmVzZW50YXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxJQUFJLE1BQU0sV0FBVyxDQUFBO0FBRTVCLE9BQU8sNEJBQTRCLE1BQU0sZ0NBQWdDLENBQUE7QUFHekU7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBQ0gsTUFBTSxDQUFDLE9BQU8sT0FBZ0IsaUNBQWtDLFNBQVEsNEJBQTRCO0lBRWxHLFlBQW1CLEtBQWlCO1FBQ2xDLEtBQUssQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDLENBQUE7SUFDM0IsQ0FBQztJQUVrQixhQUFhO1FBQzlCLE1BQU0sTUFBTSxHQUFHLElBQUksR0FBRyxFQUFxQixDQUFBO1FBQzNDLEtBQUssSUFBSSxLQUFLLEdBQUcsQ0FBQyxFQUFFLEtBQUssR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQztZQUNuRSxNQUFNLEdBQUcsR0FBVyxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUE7WUFDaEYsSUFBSSxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDO2dCQUM1QixNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FBQTtZQUNyQixDQUFDO1lBQ0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRO2lCQUNqQixNQUFNLENBQUMsQ0FBQyxDQUFVLEVBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTLEtBQUssSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7aUJBQzlFLE9BQU8sQ0FBQyxDQUFDLENBQVUsRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUN0RCxDQUFDO1FBQ0QsT0FBTyxNQUFNLENBQUE7SUFDZixDQUFDO0lBRU8saUJBQWlCLENBQUMsU0FBaUIsRUFBRSxLQUFhO1FBQ3hELE9BQU8sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsS0FBSyxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsQ0FBQTtJQUN2RixDQUFDO0NBQ0YifQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompactGroupByToolNamePerLevelRepresentation.d.ts","sourceRoot":"","sources":["../../src/representations/CompactGroupByToolNamePerLevelRepresentation.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import CompactGroupByToolNameRepresentation from './CompactGroupByToolNameRepresentation';
|
|
2
|
+
/**
|
|
3
|
+
* Since {@link CompactGroupByToolNameRepresentation} is an abstract class, the
|
|
4
|
+
* only question that this class should "answer" is what property should be used
|
|
5
|
+
* in the compact representation. In this case it is "level".
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export default class CompactGroupByToolNamePerLevelRepresentation extends CompactGroupByToolNameRepresentation {
|
|
9
|
+
compose() {
|
|
10
|
+
return this.composeByProperty('level');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29tcGFjdEdyb3VwQnlUb29sTmFtZVBlckxldmVsUmVwcmVzZW50YXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcmVwcmVzZW50YXRpb25zL0NvbXBhY3RHcm91cEJ5VG9vbE5hbWVQZXJMZXZlbFJlcHJlc2VudGF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sb0NBQW9DLE1BQ3BDLHdDQUF3QyxDQUFBO0FBRS9DOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLE9BQU8sT0FBTyw0Q0FBNkMsU0FBUSxvQ0FBb0M7SUFFNUYsT0FBTztRQUNyQixPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsQ0FBQTtJQUN4QyxDQUFDO0NBQ0YifQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompactGroupByToolNamePerSeverityRepresentation.d.ts","sourceRoot":"","sources":["../../src/representations/CompactGroupByToolNamePerSeverityRepresentation.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import CompactGroupByToolNameRepresentation from './CompactGroupByToolNameRepresentation';
|
|
2
|
+
/**
|
|
3
|
+
* Since {@link CompactGroupByToolNameRepresentation} is an abstract class, the
|
|
4
|
+
* only question that this class should "answer" is what property should be used
|
|
5
|
+
* in the compact representation. In this case it is "severity".
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export default class CompactGroupByToolNamePerSeverityRepresentation extends CompactGroupByToolNameRepresentation {
|
|
9
|
+
compose() {
|
|
10
|
+
return this.composeByProperty('severity');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29tcGFjdEdyb3VwQnlUb29sTmFtZVBlclNldmVyaXR5UmVwcmVzZW50YXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcmVwcmVzZW50YXRpb25zL0NvbXBhY3RHcm91cEJ5VG9vbE5hbWVQZXJTZXZlcml0eVJlcHJlc2VudGF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sb0NBQW9DLE1BQ3BDLHdDQUF3QyxDQUFBO0FBRS9DOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLE9BQU8sT0FBTywrQ0FBZ0QsU0FBUSxvQ0FBb0M7SUFFL0YsT0FBTztRQUNyQixPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxVQUFVLENBQUMsQ0FBQTtJQUMzQyxDQUFDO0NBQ0YifQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompactGroupByToolNameRepresentation.d.ts","sourceRoot":"","sources":["../../src/representations/CompactGroupByToolNameRepresentation.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import CompactGroupByRepresentation from './CompactGroupByRepresentation';
|
|
2
|
+
/**
|
|
3
|
+
* Since {@link CompactGroupByRepresentation} already prepares compact representation
|
|
4
|
+
* of findings, this class defines a grouping rule. In this case it groups
|
|
5
|
+
* findings by tool name. Every tool name will be grouped separately, such as:
|
|
6
|
+
* @example
|
|
7
|
+
* ```text
|
|
8
|
+
* Grype
|
|
9
|
+
* Error: 1, Warning: 4
|
|
10
|
+
* Trivy
|
|
11
|
+
* Warning: 1, Note: 20
|
|
12
|
+
* ```
|
|
13
|
+
* @internal
|
|
14
|
+
* It is an abstract class, so the only question that derived classes should
|
|
15
|
+
* "answer" is what property should be used in the compact representation, such
|
|
16
|
+
* as "level" and "severity".
|
|
17
|
+
*/
|
|
18
|
+
export default class CompactGroupByToolNameRepresentation extends CompactGroupByRepresentation {
|
|
19
|
+
constructor(model) {
|
|
20
|
+
super(model, 'toolName');
|
|
21
|
+
}
|
|
22
|
+
groupFindings() {
|
|
23
|
+
const result = new Map();
|
|
24
|
+
for (const run of this._model.runs) {
|
|
25
|
+
const key = this.composeGroupTitle(run.toolName);
|
|
26
|
+
if (result.get(key) == null) {
|
|
27
|
+
result.set(key, []);
|
|
28
|
+
}
|
|
29
|
+
this._model.findings
|
|
30
|
+
.filter((f) => f.runId === run.id)
|
|
31
|
+
.forEach((f) => result.get(key)?.push(f));
|
|
32
|
+
}
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
composeGroupTitle(toolName) {
|
|
36
|
+
return this.bold(toolName);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29tcGFjdEdyb3VwQnlUb29sTmFtZVJlcHJlc2VudGF0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3JlcHJlc2VudGF0aW9ucy9Db21wYWN0R3JvdXBCeVRvb2xOYW1lUmVwcmVzZW50YXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyw0QkFBNEIsTUFBTSxnQ0FBZ0MsQ0FBQTtBQUd6RTs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFDSCxNQUFNLENBQUMsT0FBTyxPQUFnQixvQ0FBcUMsU0FBUSw0QkFBNEI7SUFFckcsWUFBbUIsS0FBaUI7UUFDbEMsS0FBSyxDQUFDLEtBQUssRUFBRSxVQUFVLENBQUMsQ0FBQTtJQUMxQixDQUFDO0lBRWtCLGFBQWE7UUFDOUIsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLEVBQXFCLENBQUE7UUFDM0MsS0FBSyxNQUFNLEdBQUcsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ25DLE1BQU0sR0FBRyxHQUFXLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUE7WUFDeEQsSUFBSSxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDO2dCQUM1QixNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FBQTtZQUNyQixDQUFDO1lBQ0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRO2lCQUNqQixNQUFNLENBQUMsQ0FBQyxDQUFVLEVBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLEtBQUssR0FBRyxDQUFDLEVBQUUsQ0FBQztpQkFDbkQsT0FBTyxDQUFDLENBQUMsQ0FBVSxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQ3RELENBQUM7UUFDRCxPQUFPLE1BQU0sQ0FBQTtJQUNmLENBQUM7SUFFTyxpQkFBaUIsQ0FBQyxRQUFnQjtRQUN4QyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUE7SUFDNUIsQ0FBQztDQUNGIn0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompactTotalPerLevelRepresentation.d.ts","sourceRoot":"","sources":["../../src/representations/CompactTotalPerLevelRepresentation.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import CompactTotalRepresentation from './CompactTotalRepresentation';
|
|
2
|
+
/**
|
|
3
|
+
* Since {@link CompactTotalRepresentation} is an abstract class, the only
|
|
4
|
+
* question that this class should "answer" is what property should be used in
|
|
5
|
+
* the compact representation. In this case it is "level".
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export default class CompactTotalPerLevelRepresentation extends CompactTotalRepresentation {
|
|
9
|
+
compose() {
|
|
10
|
+
return this.composeByProperty('level');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29tcGFjdFRvdGFsUGVyTGV2ZWxSZXByZXNlbnRhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9yZXByZXNlbnRhdGlvbnMvQ29tcGFjdFRvdGFsUGVyTGV2ZWxSZXByZXNlbnRhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLDBCQUEwQixNQUFNLDhCQUE4QixDQUFBO0FBRXJFOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLE9BQU8sT0FBTyxrQ0FBbUMsU0FBUSwwQkFBMEI7SUFFeEUsT0FBTztRQUNyQixPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsQ0FBQTtJQUN4QyxDQUFDO0NBQ0YifQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompactTotalPerSeverityRepresentation.d.ts","sourceRoot":"","sources":["../../src/representations/CompactTotalPerSeverityRepresentation.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import CompactTotalRepresentation from './CompactTotalRepresentation';
|
|
2
|
+
/**
|
|
3
|
+
* Since {@link CompactTotalRepresentation} is an abstract class, the only
|
|
4
|
+
* question that this class should "answer" is what property should be used in
|
|
5
|
+
* the compact representation. In this case it is "severity".
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export default class CompactTotalPerSeverityRepresentation extends CompactTotalRepresentation {
|
|
9
|
+
compose() {
|
|
10
|
+
return this.composeByProperty('severity');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29tcGFjdFRvdGFsUGVyU2V2ZXJpdHlSZXByZXNlbnRhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9yZXByZXNlbnRhdGlvbnMvQ29tcGFjdFRvdGFsUGVyU2V2ZXJpdHlSZXByZXNlbnRhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLDBCQUEwQixNQUFNLDhCQUE4QixDQUFBO0FBRXJFOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLE9BQU8sT0FBTyxxQ0FBc0MsU0FBUSwwQkFBMEI7SUFFM0UsT0FBTztRQUNyQixPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxVQUFVLENBQUMsQ0FBQTtJQUMzQyxDQUFDO0NBQ0YifQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CompactTotalRepresentation.d.ts","sourceRoot":"","sources":["../../src/representations/CompactTotalRepresentation.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import CompactGroupByRepresentation from './CompactGroupByRepresentation';
|
|
2
|
+
/**
|
|
3
|
+
* Since {@link CompactGroupByRepresentation} already prepares compact representation
|
|
4
|
+
* of findings, this class defines a grouping rule. In this case it does not really
|
|
5
|
+
* group, but just add everything under the same "Total" group, such as:
|
|
6
|
+
* @example
|
|
7
|
+
* ```text
|
|
8
|
+
* Total
|
|
9
|
+
* Warning: 1, Note: 20
|
|
10
|
+
* ```
|
|
11
|
+
* @internal
|
|
12
|
+
* It is an abstract class, so the only question that derived classes should
|
|
13
|
+
* "answer" is what property should be used in the compact representation, such
|
|
14
|
+
* as "level" and "severity".
|
|
15
|
+
*/
|
|
16
|
+
export default class CompactTotalRepresentation extends CompactGroupByRepresentation {
|
|
17
|
+
groupFindings() {
|
|
18
|
+
const result = new Map();
|
|
19
|
+
if (this._model.findings.length > 0) {
|
|
20
|
+
result.set('Total', this._model.findings);
|
|
21
|
+
}
|
|
22
|
+
return result;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29tcGFjdFRvdGFsUmVwcmVzZW50YXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcmVwcmVzZW50YXRpb25zL0NvbXBhY3RUb3RhbFJlcHJlc2VudGF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sNEJBQTRCLE1BQU0sZ0NBQWdDLENBQUE7QUFHekU7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQWdCLDBCQUEyQixTQUFRLDRCQUE0QjtJQUV4RSxhQUFhO1FBQzlCLE1BQU0sTUFBTSxHQUFHLElBQUksR0FBRyxFQUFxQixDQUFBO1FBQzNDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3BDLE1BQU0sQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUE7UUFDM0MsQ0FBQztRQUNELE9BQU8sTUFBTSxDQUFBO0lBQ2YsQ0FBQztDQUNGIn0=
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Representation.d.ts","sourceRoot":"","sources":["../../src/representations/Representation.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { findingsComparatorByKey } from '../utils/Comparators';
|
|
2
|
+
import FindingsArray from '../model/FindingsArray';
|
|
3
|
+
/**
|
|
4
|
+
* The most base abstract class for the representation. Every representation class
|
|
5
|
+
* must be derived from this class implicitly or explicitly.
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export default class Representation {
|
|
9
|
+
_model;
|
|
10
|
+
constructor(model, findingSortKey = 'level') {
|
|
11
|
+
this._model = model;
|
|
12
|
+
this._model.findings = model
|
|
13
|
+
.findings
|
|
14
|
+
.map((f) => f.clone())
|
|
15
|
+
.sort(findingsComparatorByKey(findingSortKey))
|
|
16
|
+
.reduce((arr, f) => {
|
|
17
|
+
arr.push(f);
|
|
18
|
+
return arr;
|
|
19
|
+
}, new FindingsArray());
|
|
20
|
+
}
|
|
21
|
+
bold(text) {
|
|
22
|
+
return `*${text}*`;
|
|
23
|
+
}
|
|
24
|
+
italic(text) {
|
|
25
|
+
return `_${text}_`;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUmVwcmVzZW50YXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcmVwcmVzZW50YXRpb25zL1JlcHJlc2VudGF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLHNCQUFzQixDQUFBO0FBQzlELE9BQU8sYUFBYSxNQUFNLHdCQUF3QixDQUFBO0FBRWxEOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsT0FBTyxPQUFnQixjQUFjO0lBQ3ZCLE1BQU0sQ0FBWTtJQUVyQyxZQUFtQixLQUFpQixFQUFFLGlCQUFnQyxPQUFPO1FBQzNFLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFBO1FBQ25CLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxHQUFHLEtBQUs7YUFDekIsUUFBUTthQUNSLEdBQUcsQ0FBQyxDQUFDLENBQVUsRUFBVyxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDO2FBQ3ZDLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxjQUFjLENBQUMsQ0FBQzthQUM3QyxNQUFNLENBQUMsQ0FBQyxHQUFrQixFQUFFLENBQVUsRUFBaUIsRUFBRTtZQUN4RCxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFBO1lBQ1gsT0FBTyxHQUFHLENBQUE7UUFDWixDQUFDLEVBQUUsSUFBSSxhQUFhLEVBQUUsQ0FBQyxDQUFBO0lBQzNCLENBQUM7SUFFUyxJQUFJLENBQUMsSUFBWTtRQUN6QixPQUFPLElBQUksSUFBSSxHQUFHLENBQUE7SUFDcEIsQ0FBQztJQUVTLE1BQU0sQ0FBQyxJQUFZO1FBQzNCLE9BQU8sSUFBSSxJQUFJLEdBQUcsQ0FBQTtJQUNwQixDQUFDO0NBR0YifQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RepresentationFactory.d.ts","sourceRoot":"","sources":["../../src/representations/RepresentationFactory.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { RepresentationType } from '../types';
|
|
2
|
+
import CompactGroupByRunPerLevelRepresentation from './CompactGroupByRunPerLevelRepresentation';
|
|
3
|
+
import CompactGroupByRunPerSeverityRepresentation from './CompactGroupByRunPerSeverityRepresentation';
|
|
4
|
+
import CompactGroupByToolNamePerLevelRepresentation from './CompactGroupByToolNamePerLevelRepresentation';
|
|
5
|
+
import CompactGroupByToolNamePerSeverityRepresentation from './CompactGroupByToolNamePerSeverityRepresentation';
|
|
6
|
+
import CompactGroupBySarifPerLevelRepresentation from './CompactGroupBySarifPerLevelRepresentation';
|
|
7
|
+
import CompactGroupBySarifPerSeverityRepresentation from './CompactGroupBySarifPerSeverityRepresentation';
|
|
8
|
+
import CompactTotalPerSeverityRepresentation from './CompactTotalPerSeverityRepresentation';
|
|
9
|
+
import CompactTotalPerLevelRepresentation from './CompactTotalPerLevelRepresentation';
|
|
10
|
+
/**
|
|
11
|
+
* Factory class that creates a {@link Representation} class based on the provided
|
|
12
|
+
* {@link RepresentationType}.
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
export function createRepresentation(model, type = RepresentationType.CompactGroupByToolNamePerSeverity) {
|
|
16
|
+
switch (type) {
|
|
17
|
+
case RepresentationType.CompactGroupByRunPerLevel:
|
|
18
|
+
return new CompactGroupByRunPerLevelRepresentation(model);
|
|
19
|
+
case RepresentationType.CompactGroupByRunPerSeverity:
|
|
20
|
+
return new CompactGroupByRunPerSeverityRepresentation(model);
|
|
21
|
+
case RepresentationType.CompactGroupByToolNamePerLevel:
|
|
22
|
+
return new CompactGroupByToolNamePerLevelRepresentation(model);
|
|
23
|
+
case RepresentationType.CompactGroupByToolNamePerSeverity:
|
|
24
|
+
return new CompactGroupByToolNamePerSeverityRepresentation(model);
|
|
25
|
+
case RepresentationType.CompactGroupBySarifPerLevel:
|
|
26
|
+
return new CompactGroupBySarifPerLevelRepresentation(model);
|
|
27
|
+
case RepresentationType.CompactGroupBySarifPerSeverity:
|
|
28
|
+
return new CompactGroupBySarifPerSeverityRepresentation(model);
|
|
29
|
+
case RepresentationType.CompactTotalPerLevel:
|
|
30
|
+
return new CompactTotalPerLevelRepresentation(model);
|
|
31
|
+
case RepresentationType.CompactTotalPerSeverity:
|
|
32
|
+
return new CompactTotalPerSeverityRepresentation(model);
|
|
33
|
+
default:
|
|
34
|
+
throw new Error(`Unknown representation type: ${type}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUmVwcmVzZW50YXRpb25GYWN0b3J5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3JlcHJlc2VudGF0aW9ucy9SZXByZXNlbnRhdGlvbkZhY3RvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLGtCQUFrQixFQUFjLE1BQU0sVUFBVSxDQUFBO0FBQ3pELE9BQU8sdUNBQXVDLE1BQ3ZDLDJDQUEyQyxDQUFBO0FBQ2xELE9BQU8sMENBQTBDLE1BQzFDLDhDQUE4QyxDQUFBO0FBQ3JELE9BQU8sNENBQTRDLE1BQzVDLGdEQUFnRCxDQUFBO0FBQ3ZELE9BQU8sK0NBQStDLE1BQy9DLG1EQUFtRCxDQUFBO0FBQzFELE9BQU8seUNBQXlDLE1BQ3pDLDZDQUE2QyxDQUFBO0FBQ3BELE9BQU8sNENBQTRDLE1BQzVDLGdEQUFnRCxDQUFBO0FBQ3ZELE9BQU8scUNBQXFDLE1BQ3JDLHlDQUF5QyxDQUFBO0FBQ2hELE9BQU8sa0NBQWtDLE1BQ2xDLHNDQUFzQyxDQUFBO0FBRTdDOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsb0JBQW9CLENBQ2xDLEtBQWlCLEVBQ2pCLE9BQTJCLGtCQUFrQixDQUFDLGlDQUFpQztJQUUvRSxRQUFRLElBQUksRUFBRSxDQUFDO1FBQ2IsS0FBSyxrQkFBa0IsQ0FBQyx5QkFBeUI7WUFDL0MsT0FBTyxJQUFJLHVDQUF1QyxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQzNELEtBQUssa0JBQWtCLENBQUMsNEJBQTRCO1lBQ2xELE9BQU8sSUFBSSwwQ0FBMEMsQ0FBQyxLQUFLLENBQUMsQ0FBQTtRQUM5RCxLQUFLLGtCQUFrQixDQUFDLDhCQUE4QjtZQUNwRCxPQUFPLElBQUksNENBQTRDLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDaEUsS0FBSyxrQkFBa0IsQ0FBQyxpQ0FBaUM7WUFDdkQsT0FBTyxJQUFJLCtDQUErQyxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQ25FLEtBQUssa0JBQWtCLENBQUMsMkJBQTJCO1lBQ2pELE9BQU8sSUFBSSx5Q0FBeUMsQ0FBQyxLQUFLLENBQUMsQ0FBQTtRQUM3RCxLQUFLLGtCQUFrQixDQUFDLDhCQUE4QjtZQUNwRCxPQUFPLElBQUksNENBQTRDLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDaEUsS0FBSyxrQkFBa0IsQ0FBQyxvQkFBb0I7WUFDMUMsT0FBTyxJQUFJLGtDQUFrQyxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQ3RELEtBQUssa0JBQWtCLENBQUMsdUJBQXVCO1lBQzdDLE9BQU8sSUFBSSxxQ0FBcUMsQ0FBQyxLQUFLLENBQUMsQ0FBQTtRQUN6RDtZQUNFLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0NBQWdDLElBQUksRUFBRSxDQUFDLENBQUE7SUFDM0QsQ0FBQztBQUNILENBQUMifQ==
|