@fabasoad/sarif-to-slack 1.3.1 → 1.3.3
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/.gitattributes +1 -0
- package/.github/actionlint.yaml +9 -0
- package/.github/workflows/release.yml +19 -9
- package/.github/workflows/send-sarif-to-slack.yml +15 -12
- package/.pre-commit-config.yaml +2 -1
- package/.tool-versions +1 -1
- package/README.md +47 -12
- package/biome.json +5 -52
- package/dist/Logger.js +51 -22
- package/dist/SarifToSlackClient.d.ts +12 -10
- package/dist/SarifToSlackClient.d.ts.map +1 -1
- package/dist/SarifToSlackClient.js +28 -15
- package/dist/index.cjs +603 -237
- package/dist/index.d.ts +1 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -8
- package/dist/model/Finding.js +4 -3
- package/dist/model/SlackMessage.d.ts +0 -16
- package/dist/model/SlackMessage.d.ts.map +1 -1
- package/dist/model/color/ColorIdentification.js +50 -46
- package/dist/model/color/ColorOptions.d.ts +1 -1
- package/dist/model/color/ColorOptions.d.ts.map +1 -1
- package/dist/representations/CompactGroupByRepresentation.js +2 -2
- package/dist/representations/Representation.js +6 -2
- package/dist/representations/RepresentationFactory.js +19 -1
- package/dist/representations/TableGroupByRunPerLevelRepresentation.d.ts +6 -0
- package/dist/representations/TableGroupByRunPerLevelRepresentation.d.ts.map +1 -0
- package/dist/representations/TableGroupByRunPerLevelRepresentation.js +8 -0
- package/dist/representations/TableGroupByRunPerSeverityRepresentation.d.ts +6 -0
- package/dist/representations/TableGroupByRunPerSeverityRepresentation.d.ts.map +1 -0
- package/dist/representations/TableGroupByRunPerSeverityRepresentation.js +8 -0
- package/dist/representations/TableGroupByRunRepresentation.d.ts +7 -0
- package/dist/representations/TableGroupByRunRepresentation.d.ts.map +1 -0
- package/dist/representations/TableGroupByRunRepresentation.js +7 -0
- package/dist/representations/TableGroupBySarifPerLevelRepresentation.d.ts +6 -0
- package/dist/representations/TableGroupBySarifPerLevelRepresentation.d.ts.map +1 -0
- package/dist/representations/TableGroupBySarifPerLevelRepresentation.js +8 -0
- package/dist/representations/TableGroupBySarifPerSeverityRepresentation.d.ts +6 -0
- package/dist/representations/TableGroupBySarifPerSeverityRepresentation.d.ts.map +1 -0
- package/dist/representations/TableGroupBySarifPerSeverityRepresentation.js +8 -0
- package/dist/representations/TableGroupBySarifRepresentation.d.ts +9 -0
- package/dist/representations/TableGroupBySarifRepresentation.d.ts.map +1 -0
- package/dist/representations/TableGroupBySarifRepresentation.js +15 -0
- package/dist/representations/TableGroupByToolNamePerLevelRepresentation.d.ts +6 -0
- package/dist/representations/TableGroupByToolNamePerLevelRepresentation.d.ts.map +1 -0
- package/dist/representations/TableGroupByToolNamePerLevelRepresentation.js +8 -0
- package/dist/representations/TableGroupByToolNamePerSeverityRepresentation.d.ts +6 -0
- package/dist/representations/TableGroupByToolNamePerSeverityRepresentation.d.ts.map +1 -0
- package/dist/representations/TableGroupByToolNamePerSeverityRepresentation.js +8 -0
- package/dist/representations/TableGroupByToolNameRepresentation.d.ts +7 -0
- package/dist/representations/TableGroupByToolNameRepresentation.d.ts.map +1 -0
- package/dist/representations/TableGroupByToolNameRepresentation.js +7 -0
- package/dist/representations/TableGroupRepresentation.d.ts +16 -0
- package/dist/representations/TableGroupRepresentation.d.ts.map +1 -0
- package/dist/representations/TableGroupRepresentation.js +62 -0
- package/dist/representations/table/Cell.d.ts +10 -0
- package/dist/representations/table/Cell.d.ts.map +1 -0
- package/dist/representations/table/Cell.js +23 -0
- package/dist/representations/table/Column.d.ts +11 -0
- package/dist/representations/table/Column.d.ts.map +1 -0
- package/dist/representations/table/Column.js +31 -0
- package/dist/representations/table/Row.d.ts +15 -0
- package/dist/representations/table/Row.d.ts.map +1 -0
- package/dist/representations/table/Row.js +45 -0
- package/dist/representations/table/Table.d.ts +14 -0
- package/dist/representations/table/Table.d.ts.map +1 -0
- package/dist/representations/table/Table.js +66 -0
- package/dist/sarif-to-slack.d.ts +98 -88
- package/dist/system.d.ts +2 -0
- package/dist/system.d.ts.map +1 -0
- package/dist/system.js +24 -0
- package/dist/tsdoc-metadata.json +1 -1
- package/dist/types.d.ts +90 -56
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +89 -42
- package/dist/utils/FileUtils.js +8 -7
- package/dist/utils/StringUtils.d.ts +2 -0
- package/dist/utils/StringUtils.d.ts.map +1 -0
- package/dist/utils/StringUtils.js +5 -0
- package/etc/sarif-to-slack.api.md +8 -36
- package/package.json +10 -10
- package/src/Logger.ts +64 -26
- package/src/SarifToSlackClient.ts +42 -29
- package/src/index.ts +0 -9
- package/src/model/Finding.ts +14 -13
- package/src/model/FindingArray.ts +1 -1
- package/src/model/SlackMessage.ts +5 -5
- package/src/model/color/ColorIdentification.ts +66 -50
- package/src/model/color/ColorOptions.ts +1 -1
- package/src/processors/CodeQLProcessor.ts +1 -1
- package/src/representations/CompactGroupByRepresentation.ts +2 -2
- package/src/representations/CompactGroupByRunRepresentation.ts +2 -2
- package/src/representations/CompactGroupBySarifRepresentation.ts +2 -2
- package/src/representations/CompactGroupByToolNameRepresentation.ts +2 -2
- package/src/representations/CompactTotalRepresentation.ts +1 -1
- package/src/representations/Representation.ts +9 -4
- package/src/representations/RepresentationFactory.ts +26 -2
- package/src/representations/TableGroupByRunPerLevelRepresentation.ts +9 -0
- package/src/representations/TableGroupByRunPerSeverityRepresentation.ts +9 -0
- package/src/representations/TableGroupByRunRepresentation.ts +15 -0
- package/src/representations/TableGroupBySarifPerLevelRepresentation.ts +9 -0
- package/src/representations/TableGroupBySarifPerSeverityRepresentation.ts +9 -0
- package/src/representations/TableGroupBySarifRepresentation.ts +25 -0
- package/src/representations/TableGroupByToolNamePerLevelRepresentation.ts +10 -0
- package/src/representations/TableGroupByToolNamePerSeverityRepresentation.ts +10 -0
- package/src/representations/TableGroupByToolNameRepresentation.ts +15 -0
- package/src/representations/TableGroupRepresentation.ts +78 -0
- package/src/representations/table/Cell.ts +25 -0
- package/src/representations/table/Column.ts +39 -0
- package/src/representations/table/Row.ts +50 -0
- package/src/representations/table/Table.ts +93 -0
- package/src/system.ts +27 -0
- package/src/types.ts +98 -58
- package/src/utils/Comparators.ts +1 -1
- package/src/utils/FileUtils.ts +20 -19
- package/src/utils/StringUtils.ts +7 -0
- package/test-data/sarif/codeql-go.sarif +1 -1
- package/test-data/sarif/runs-1-extensions-1-results-0.sarif +2 -2
- package/test-data/sarif/snyk-hex.sarif +1 -1
- package/tests/integration/SendSarifToSlack.spec.ts +73 -83
- package/tests/representations/table/Table.spec.ts +174 -0
- package/dist/System.d.ts +0 -2
- package/dist/System.d.ts.map +0 -1
- package/dist/System.js +0 -15
- package/src/System.ts +0 -16
- /package/test-data/sarif/{tmp → multiple}/codeql-csharp.sarif +0 -0
- /package/test-data/sarif/{tmp → multiple}/grype-container.sarif +0 -0
- /package/test-data/sarif/{tmp → multiple}/runs-1-tools-1-results-0.sarif +0 -0
- /package/test-data/sarif/{tmp → multiple}/runs-2-tools-2.sarif +0 -0
package/.gitattributes
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
self-hosted-runner:
|
|
3
|
+
# Labels of self-hosted runner in array of strings.
|
|
4
|
+
labels: []
|
|
5
|
+
# Configuration variables in array of strings defined in your repository or
|
|
6
|
+
# organization. `null` means disabling configuration variables check.
|
|
7
|
+
# Empty array means no configuration variable is allowed.
|
|
8
|
+
config-variables:
|
|
9
|
+
- GH_APP_CONTENTS_CRUD_APP_ID
|
|
@@ -26,13 +26,20 @@ jobs:
|
|
|
26
26
|
ref: ${{ steps.metadata.outputs.ref }}
|
|
27
27
|
ref-name: ${{ steps.metadata.outputs.ref-name }}
|
|
28
28
|
steps:
|
|
29
|
+
- name: Get GitHub token
|
|
30
|
+
uses: actions/create-github-app-token@v2
|
|
31
|
+
id: github-app
|
|
32
|
+
with:
|
|
33
|
+
app-id: ${{ vars.GH_APP_CONTENTS_CRUD_APP_ID }}
|
|
34
|
+
private-key: ${{ secrets.GH_APP_CONTENTS_CRUD_PRIVATE_KEY }}
|
|
35
|
+
|
|
29
36
|
- name: Checkout ${{ github.repository }}
|
|
30
37
|
uses: actions/checkout@v5
|
|
31
38
|
with:
|
|
32
|
-
token: "${{
|
|
39
|
+
token: "${{ steps.github-app.outputs.token }}"
|
|
33
40
|
|
|
34
41
|
- name: Setup Node
|
|
35
|
-
uses: actions/setup-node@
|
|
42
|
+
uses: actions/setup-node@v5
|
|
36
43
|
with:
|
|
37
44
|
node-version-file: ".tool-versions"
|
|
38
45
|
cache: "npm"
|
|
@@ -41,17 +48,20 @@ jobs:
|
|
|
41
48
|
- name: Install dependencies
|
|
42
49
|
run: npm ci
|
|
43
50
|
|
|
51
|
+
- name: Install jq
|
|
52
|
+
uses: dcarbone/install-jq-action@v3
|
|
53
|
+
|
|
44
54
|
- name: Bump version
|
|
45
55
|
env:
|
|
46
56
|
BUMP_STRATEGY: "${{ github.event.inputs.bump-strategy }}"
|
|
57
|
+
GH_TOKEN: "${{ steps.github-app.outputs.token }}"
|
|
47
58
|
run: |
|
|
48
|
-
|
|
49
|
-
|
|
59
|
+
app_slug="${{ steps.github-app.outputs.app-slug }}"
|
|
60
|
+
user_id="$(gh api "/users/${app_slug}[bot]" --jq .id)"
|
|
61
|
+
git config user.email "${user_id}+${app_slug}[bot]@users.noreply.github.com"
|
|
62
|
+
git config user.name "${app_slug}[bot]"
|
|
50
63
|
npm run version:${BUMP_STRATEGY}
|
|
51
64
|
|
|
52
|
-
- name: Install jq
|
|
53
|
-
uses: dcarbone/install-jq-action@v3
|
|
54
|
-
|
|
55
65
|
- name: Get metadata
|
|
56
66
|
id: metadata
|
|
57
67
|
run: |
|
|
@@ -60,12 +70,12 @@ jobs:
|
|
|
60
70
|
echo "ref-name=v${version}" >> "$GITHUB_OUTPUT"
|
|
61
71
|
|
|
62
72
|
- name: Publish to npm registry
|
|
63
|
-
uses: JS-DevTools/npm-publish@
|
|
73
|
+
uses: JS-DevTools/npm-publish@v4
|
|
64
74
|
with:
|
|
65
75
|
token: "${{ secrets.NPM_TOKEN }}"
|
|
66
76
|
|
|
67
77
|
- name: Publish to GitHub Packages
|
|
68
|
-
uses: JS-DevTools/npm-publish@
|
|
78
|
+
uses: JS-DevTools/npm-publish@v4
|
|
69
79
|
with:
|
|
70
80
|
token: "${{ secrets.GITHUB_TOKEN }}"
|
|
71
81
|
registry: "https://npm.pkg.github.com"
|
|
@@ -58,6 +58,7 @@ on: # yamllint disable-line rule:truthy
|
|
|
58
58
|
- "Runs: 2, Tools: 2, Results: 0"
|
|
59
59
|
- "Runs: 3, Tools: 2, Results > 0"
|
|
60
60
|
- "Runs: 3, Tools: 2, Results: 0"
|
|
61
|
+
- "Files: 4, Runs: 5, Tools: 5, Results > 0"
|
|
61
62
|
- "All"
|
|
62
63
|
representation:
|
|
63
64
|
description: "Representation:"
|
|
@@ -157,7 +158,7 @@ defaults:
|
|
|
157
158
|
|
|
158
159
|
jobs:
|
|
159
160
|
send-sarif:
|
|
160
|
-
name: ${{ inputs.sarif }}
|
|
161
|
+
name: ${{ github.event.inputs.sarif }}
|
|
161
162
|
timeout-minutes: 5
|
|
162
163
|
runs-on: ubuntu-latest
|
|
163
164
|
steps:
|
|
@@ -166,7 +167,7 @@ jobs:
|
|
|
166
167
|
- name: Determine SARIF file
|
|
167
168
|
id: sarif-file
|
|
168
169
|
env:
|
|
169
|
-
INPUT_SARIF: "${{ inputs.sarif }}"
|
|
170
|
+
INPUT_SARIF: "${{ github.event.inputs.sarif }}"
|
|
170
171
|
run: |
|
|
171
172
|
if [ "${INPUT_SARIF}" = "CodeQL C# (High: 1)1)" ]; then
|
|
172
173
|
value="codeql-csharp.sarif"
|
|
@@ -264,13 +265,15 @@ jobs:
|
|
|
264
265
|
value="runs-3-tools-2.sarif"
|
|
265
266
|
elif [ "${INPUT_SARIF}" = "Runs: 3, Tools: 2, Results: 0" ]; then
|
|
266
267
|
value="runs-3-tools-2-results-0.sarif"
|
|
268
|
+
elif [ "${INPUT_SARIF}" = "Files: 4, Runs: 5, Tools: 5, Results > 0" ]; then
|
|
269
|
+
value="multiple"
|
|
267
270
|
else
|
|
268
271
|
# All
|
|
269
272
|
value=""
|
|
270
273
|
fi
|
|
271
274
|
echo "value=${value}" >> "$GITHUB_OUTPUT"
|
|
272
275
|
- name: Setup node
|
|
273
|
-
uses: actions/setup-node@
|
|
276
|
+
uses: actions/setup-node@v5
|
|
274
277
|
with:
|
|
275
278
|
node-version-file: ".tool-versions"
|
|
276
279
|
- name: Install dependencies
|
|
@@ -278,20 +281,20 @@ jobs:
|
|
|
278
281
|
- name: Send message
|
|
279
282
|
env:
|
|
280
283
|
SARIF_TO_SLACK_WEBHOOK_URL: "${{ secrets.TMP_EUGENE_SLACK_WEBHOOK }}"
|
|
281
|
-
SARIF_TO_SLACK_USERNAME: "${{ inputs.username }}"
|
|
284
|
+
SARIF_TO_SLACK_USERNAME: "${{ github.event.inputs.username }}"
|
|
282
285
|
SARIF_TO_SLACK_ICON_URL: "https://cdn-icons-png.flaticon.com/512/9070/9070006.png"
|
|
283
|
-
SARIF_TO_SLACK_COLOR: "${{ inputs.color }}"
|
|
286
|
+
SARIF_TO_SLACK_COLOR: "${{ github.event.inputs.color }}"
|
|
284
287
|
SARIF_TO_SLACK_COLOR_EMPTY: "#008000"
|
|
285
288
|
SARIF_TO_SLACK_SARIF_PATH: "test-data/sarif/${{ steps.sarif-file.outputs.value }}"
|
|
286
289
|
SARIF_TO_SLACK_SARIF_PATH_RECURSIVE: "false"
|
|
287
290
|
SARIF_TO_SLACK_SARIF_FILE_EXTENSION: "sarif"
|
|
288
|
-
SARIF_TO_SLACK_LOG_LEVEL: "${{ inputs.log-level }}"
|
|
291
|
+
SARIF_TO_SLACK_LOG_LEVEL: "${{ github.event.inputs.log-level }}"
|
|
289
292
|
SARIF_TO_SLACK_LOG_TEMPLATE: "[{{logLevelName}}] [{{name}}] {{dateIsoStr}} "
|
|
290
293
|
SARIF_TO_SLACK_LOG_COLORED: "true"
|
|
291
|
-
SARIF_TO_SLACK_HEADER: "${{ inputs.header }}"
|
|
292
|
-
SARIF_TO_SLACK_FOOTER: "${{ inputs.footer }}"
|
|
293
|
-
SARIF_TO_SLACK_ACTOR: "${{ inputs.actor }}"
|
|
294
|
-
SARIF_TO_SLACK_INCLUDE_RUN: "${{ inputs.include-run }}"
|
|
295
|
-
SARIF_TO_SLACK_REPRESENTATION: "${{ inputs.representation }}"
|
|
296
|
-
SARIF_TO_SLACK_SEND_IF: "${{ inputs.send-if }}"
|
|
294
|
+
SARIF_TO_SLACK_HEADER: "${{ github.event.inputs.header }}"
|
|
295
|
+
SARIF_TO_SLACK_FOOTER: "${{ github.event.inputs.footer }}"
|
|
296
|
+
SARIF_TO_SLACK_ACTOR: "${{ github.event.inputs.actor }}"
|
|
297
|
+
SARIF_TO_SLACK_INCLUDE_RUN: "${{ github.event.inputs.include-run }}"
|
|
298
|
+
SARIF_TO_SLACK_REPRESENTATION: "${{ github.event.inputs.representation }}"
|
|
299
|
+
SARIF_TO_SLACK_SEND_IF: "${{ github.event.inputs.send-if }}"
|
|
297
300
|
run: make test/integration
|
package/.pre-commit-config.yaml
CHANGED
|
@@ -60,7 +60,7 @@ repos:
|
|
|
60
60
|
- --hook-args=--log-level debug
|
|
61
61
|
stages: ["pre-push"]
|
|
62
62
|
- repo: https://github.com/google/osv-scanner
|
|
63
|
-
rev: v2.2.
|
|
63
|
+
rev: v2.2.3
|
|
64
64
|
hooks:
|
|
65
65
|
- id: osv-scanner
|
|
66
66
|
args:
|
|
@@ -103,3 +103,4 @@ repos:
|
|
|
103
103
|
- id: no-commit-to-branch
|
|
104
104
|
stages: ["pre-commit"]
|
|
105
105
|
- id: trailing-whitespace
|
|
106
|
+
exclude: ^(tests/representations/table/Table.spec.ts)$
|
package/.tool-versions
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
nodejs 24.
|
|
1
|
+
nodejs 24.9.0
|
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|

|
|
6
6
|

|
|
7
7
|

|
|
8
|
-
[](https://codecov.io/gh/fabasoad/sarif-to-slack)
|
|
9
9
|
|
|
10
10
|
TypeScript library to send results of SARIF file to Slack webhook URL.
|
|
11
11
|
|
|
@@ -22,34 +22,69 @@ TypeScript library to send results of SARIF file to Slack webhook URL.
|
|
|
22
22
|
|
|
23
23
|
## How to use
|
|
24
24
|
|
|
25
|
+
```shell
|
|
26
|
+
export SARIF_TO_SLACK_LOG_LEVEL="debug"
|
|
27
|
+
export SARIF_TO_SLACK_LOG_TEMPLATE="[{{logLevelName}}] [{{name}}] {{dateIsoStr}} "
|
|
28
|
+
export SARIF_TO_SLACK_LOG_COLORED="true"
|
|
29
|
+
```
|
|
30
|
+
|
|
25
31
|
```typescript
|
|
26
|
-
import {
|
|
32
|
+
import {
|
|
33
|
+
Color,
|
|
34
|
+
FooterType,
|
|
35
|
+
RepresentationType,
|
|
36
|
+
SarifToSlackClient,
|
|
37
|
+
SendIf
|
|
38
|
+
} from '@fabasoad/sarif-to-slack';
|
|
27
39
|
|
|
28
|
-
const
|
|
40
|
+
const client: SarifToSlackClient = await SarifToSlackClient.create({
|
|
29
41
|
webhookUrl: 'https://hooks.slack.com/services/your/webhook/url',
|
|
30
|
-
|
|
31
|
-
logLevel: 'info',
|
|
32
|
-
username: 'SARIF Bot',
|
|
42
|
+
username: 'SARIF to Slack Bot',
|
|
33
43
|
iconUrl: 'https://example.com/icon.png',
|
|
34
|
-
color:
|
|
44
|
+
color: {
|
|
45
|
+
default: new Color('failure'),
|
|
46
|
+
empty: new Color('success'),
|
|
47
|
+
bySeverity: {
|
|
48
|
+
critical: new Color('#ff0000'),
|
|
49
|
+
high: new Color('#ff4500'),
|
|
50
|
+
medium: new Color('#ffa500'),
|
|
51
|
+
low: new Color('#ffff00'),
|
|
52
|
+
none: new Color('#808080'),
|
|
53
|
+
unknown: new Color('#800080'),
|
|
54
|
+
},
|
|
55
|
+
byLevel: {
|
|
56
|
+
error: new Color('#ff0000'),
|
|
57
|
+
warning: new Color('#ffa500'),
|
|
58
|
+
note: new Color('#ffff00'),
|
|
59
|
+
none: new Color('#808080'),
|
|
60
|
+
unknown: new Color('#800080'),
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
sarif: {
|
|
64
|
+
path: 'path/to/your/sarif-files',
|
|
65
|
+
recursive: true,
|
|
66
|
+
extension: 'sarif',
|
|
67
|
+
},
|
|
35
68
|
header: {
|
|
36
69
|
include: true,
|
|
37
|
-
value: 'SARIF Analysis Results'
|
|
70
|
+
value: 'SARIF Analysis Results'
|
|
38
71
|
},
|
|
39
72
|
footer: {
|
|
40
73
|
include: true,
|
|
41
74
|
type: FooterType.PLAIN_TEXT,
|
|
42
|
-
value: 'Generated by @fabasoad/sarif-to-slack'
|
|
75
|
+
value: 'Generated by @fabasoad/sarif-to-slack'
|
|
43
76
|
},
|
|
44
77
|
actor: {
|
|
45
78
|
include: true,
|
|
46
|
-
value: 'fabasoad'
|
|
79
|
+
value: 'fabasoad'
|
|
47
80
|
},
|
|
48
81
|
run: {
|
|
49
|
-
include: true
|
|
82
|
+
include: true
|
|
50
83
|
},
|
|
84
|
+
representation: RepresentationType.CompactGroupByToolNamePerSeverity,
|
|
85
|
+
sendIf: SendIf.MediumOrHigher,
|
|
51
86
|
});
|
|
52
|
-
await
|
|
87
|
+
await client.send();
|
|
53
88
|
```
|
|
54
89
|
|
|
55
90
|
## Sample
|
package/biome.json
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
"linter": {
|
|
3
3
|
"enabled": true,
|
|
4
4
|
"rules": {
|
|
5
|
-
"recommended":
|
|
6
|
-
"a11y": "off",
|
|
5
|
+
"recommended": true,
|
|
7
6
|
"complexity": {
|
|
8
7
|
"noAdjacentSpacesInRegex": "error",
|
|
9
8
|
"noArguments": "error",
|
|
@@ -11,36 +10,10 @@
|
|
|
11
10
|
"noUselessCatch": "error"
|
|
12
11
|
},
|
|
13
12
|
"correctness": {
|
|
14
|
-
"noChildrenProp": "error",
|
|
15
|
-
"noConstAssign": "error",
|
|
16
|
-
"noConstantCondition": "error",
|
|
17
|
-
"noEmptyCharacterClassInRegex": "error",
|
|
18
|
-
"noEmptyPattern": "error",
|
|
19
|
-
"noGlobalObjectCalls": "error",
|
|
20
|
-
"noInnerDeclarations": "error",
|
|
21
|
-
"noInvalidConstructorSuper": "error",
|
|
22
|
-
"noInvalidBuiltinInstantiation": "error",
|
|
23
|
-
"noNonoctalDecimalEscape": "error",
|
|
24
|
-
"noPrecisionLoss": "error",
|
|
25
|
-
"noSelfAssign": "error",
|
|
26
|
-
"noSetterReturn": "error",
|
|
27
|
-
"noSwitchDeclarations": "error",
|
|
28
13
|
"noUndeclaredVariables": "error",
|
|
29
|
-
"noUnreachable": "error",
|
|
30
|
-
"noUnreachableSuper": "error",
|
|
31
|
-
"noUnsafeFinally": "error",
|
|
32
|
-
"noUnsafeOptionalChaining": "error",
|
|
33
14
|
"noUnusedLabels": "error",
|
|
34
|
-
"noUnusedVariables": "
|
|
35
|
-
"
|
|
36
|
-
"useJsxKeyInIterable": "error",
|
|
37
|
-
"useValidForDirection": "error",
|
|
38
|
-
"useValidTypeof": "error",
|
|
39
|
-
"useYield": "error"
|
|
40
|
-
},
|
|
41
|
-
"security": {
|
|
42
|
-
"noBlankTarget": "error",
|
|
43
|
-
"noDangerouslySetInnerHtml": "error"
|
|
15
|
+
"noUnusedVariables": "error",
|
|
16
|
+
"useJsxKeyInIterable": "error"
|
|
44
17
|
},
|
|
45
18
|
"style": {
|
|
46
19
|
"useBlockStatements": "error",
|
|
@@ -48,31 +21,11 @@
|
|
|
48
21
|
"useSingleVarDeclarator": "error"
|
|
49
22
|
},
|
|
50
23
|
"suspicious": {
|
|
51
|
-
"noAsyncPromiseExecutor": "error",
|
|
52
24
|
"noCatchAssign": "error",
|
|
53
|
-
"
|
|
54
|
-
"noCommentText": "error",
|
|
55
|
-
"noCompareNegZero": "error",
|
|
56
|
-
"noControlCharactersInRegex": "error",
|
|
57
|
-
"noDebugger": "error",
|
|
58
|
-
"noDuplicateCase": "error",
|
|
59
|
-
"noDuplicateClassMembers": "error",
|
|
60
|
-
"noDuplicateJsxProps": "error",
|
|
61
|
-
"noDuplicateObjectKeys": "error",
|
|
62
|
-
"noDuplicateParameters": "error",
|
|
63
|
-
"noEmptyBlockStatements": "error",
|
|
64
|
-
"noFallthroughSwitchClause": "error",
|
|
65
|
-
"noFunctionAssign": "error",
|
|
66
|
-
"noGlobalAssign": "error",
|
|
67
|
-
"noImportAssign": "error",
|
|
68
|
-
"noMisleadingCharacterClass": "error",
|
|
25
|
+
"noEmptyBlockStatements": "warn",
|
|
69
26
|
"noPrototypeBuiltins": "error",
|
|
70
|
-
"noRedeclare": "error",
|
|
71
|
-
"noShadowRestrictedNames": "error",
|
|
72
27
|
"noVar": "error",
|
|
73
|
-
"
|
|
74
|
-
"noUnsafeNegation": "error",
|
|
75
|
-
"useGetterReturn": "error"
|
|
28
|
+
"useIterableCallbackReturn": "off"
|
|
76
29
|
}
|
|
77
30
|
},
|
|
78
31
|
"includes": ["src/**", "tests/**"]
|
package/dist/Logger.js
CHANGED
|
@@ -1,37 +1,66 @@
|
|
|
1
1
|
import { Logger as TSLogger } from 'tslog';
|
|
2
|
-
import {
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { isDebug } from './system';
|
|
4
|
+
const LogLevelItems = ['silly', 'trace', 'debug', 'info', 'warning', 'error', 'fatal'];
|
|
3
5
|
/**
|
|
4
6
|
* Logger class for managing logging operations.
|
|
5
7
|
* @internal
|
|
6
8
|
*/
|
|
7
9
|
export default class Logger {
|
|
8
|
-
static
|
|
10
|
+
static APP_NAME = '@fabasoad/sarif-to-slack';
|
|
11
|
+
static DEFAULT_LOG_LEVEL = 'info';
|
|
9
12
|
static DEFAULT_LOG_TEMPLATE = '[{{logLevelName}}] [{{name}}] {{dateIsoStr}} ';
|
|
10
13
|
static DEFAULT_LOG_COLORED = true;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
_instance;
|
|
15
|
+
isLogLevel(v) {
|
|
16
|
+
return LogLevelItems.includes(v);
|
|
17
|
+
}
|
|
18
|
+
getMinLevel() {
|
|
19
|
+
let result = Logger.DEFAULT_LOG_LEVEL;
|
|
20
|
+
if (isDebug()) {
|
|
21
|
+
result = 'silly';
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
const parseResult = z
|
|
25
|
+
.string()
|
|
26
|
+
.refine((v) => this.isLogLevel(v))
|
|
27
|
+
.transform((v) => v)
|
|
28
|
+
.safeParse(process.env.SARIF_TO_SLACK_LOG_LEVEL);
|
|
29
|
+
if (parseResult.success) {
|
|
30
|
+
result = parseResult.data;
|
|
31
|
+
}
|
|
22
32
|
}
|
|
33
|
+
return LogLevelItems.findIndex((v) => v === result);
|
|
34
|
+
}
|
|
35
|
+
getLogTemplate() {
|
|
36
|
+
const result = z.string().safeParse(process.env.SARIF_TO_SLACK_LOG_TEMPLATE);
|
|
37
|
+
return result.success ? result.data : Logger.DEFAULT_LOG_TEMPLATE;
|
|
38
|
+
}
|
|
39
|
+
getLogColored() {
|
|
40
|
+
const result = z.stringbool().safeParse(process.env.SARIF_TO_SLACK_LOG_COLORED);
|
|
41
|
+
return result.success ? result.data : Logger.DEFAULT_LOG_COLORED;
|
|
42
|
+
}
|
|
43
|
+
constructor(memberName) {
|
|
44
|
+
this._instance = new TSLogger({
|
|
45
|
+
name: `${Logger.APP_NAME}${memberName === undefined ? '' : `::${memberName}`}`,
|
|
46
|
+
minLevel: this.getMinLevel(),
|
|
47
|
+
type: 'pretty',
|
|
48
|
+
prettyLogTimeZone: 'UTC',
|
|
49
|
+
prettyLogTemplate: this.getLogTemplate(),
|
|
50
|
+
stylePrettyLogs: this.getLogColored(),
|
|
51
|
+
});
|
|
23
52
|
}
|
|
24
|
-
|
|
25
|
-
|
|
53
|
+
info(...args) {
|
|
54
|
+
this._instance.info(...args);
|
|
26
55
|
}
|
|
27
|
-
|
|
28
|
-
|
|
56
|
+
warn(...args) {
|
|
57
|
+
this._instance.warn(...args);
|
|
29
58
|
}
|
|
30
|
-
|
|
31
|
-
|
|
59
|
+
trace(...args) {
|
|
60
|
+
this._instance.trace(...args);
|
|
32
61
|
}
|
|
33
|
-
|
|
34
|
-
|
|
62
|
+
debug(...args) {
|
|
63
|
+
this._instance.debug(...args);
|
|
35
64
|
}
|
|
36
65
|
}
|
|
37
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
66
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTG9nZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL0xvZ2dlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQWdCLE1BQU0sSUFBSSxRQUFRLEVBQUUsTUFBTSxPQUFPLENBQUE7QUFDeEQsT0FBTyxFQUFFLENBQUMsRUFBMkIsTUFBTSxLQUFLLENBQUM7QUFDakQsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUVuQyxNQUFNLGFBQWEsR0FBRyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBVSxDQUFDO0FBR2hHOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQU8sTUFBTTtJQUNqQixNQUFNLENBQUMsUUFBUSxHQUFXLDBCQUEwQixDQUFDO0lBQ3JELE1BQU0sQ0FBQyxpQkFBaUIsR0FBYSxNQUFNLENBQUM7SUFDNUMsTUFBTSxDQUFDLG9CQUFvQixHQUFXLCtDQUErQyxDQUFDO0lBQ3RGLE1BQU0sQ0FBQyxtQkFBbUIsR0FBWSxJQUFJLENBQUM7SUFFbEMsU0FBUyxDQUFvQjtJQUV0QyxVQUFVLENBQUMsQ0FBUztRQUMxQixPQUFRLGFBQXVDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzlELENBQUM7SUFFTyxXQUFXO1FBQ2pCLElBQUksTUFBTSxHQUFhLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQztRQUVoRCxJQUFJLE9BQU8sRUFBRSxFQUFFLENBQUM7WUFDZCxNQUFNLEdBQUcsT0FBTyxDQUFDO1FBQ25CLENBQUM7YUFBTSxDQUFDO1lBQ04sTUFBTSxXQUFXLEdBQWlDLENBQUM7aUJBQ2hELE1BQU0sRUFBRTtpQkFDUixNQUFNLENBQUMsQ0FBQyxDQUFTLEVBQVcsRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7aUJBQ2xELFNBQVMsQ0FBQyxDQUFDLENBQVMsRUFBWSxFQUFFLENBQUMsQ0FBYSxDQUFDO2lCQUNqRCxTQUFTLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO1lBQ25ELElBQUksV0FBVyxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUN4QixNQUFNLEdBQUcsV0FBVyxDQUFDLElBQUksQ0FBQztZQUM1QixDQUFDO1FBQ0gsQ0FBQztRQUVELE9BQU8sYUFBYSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQVcsRUFBVyxFQUFFLENBQUMsQ0FBQyxLQUFLLE1BQU0sQ0FBQyxDQUFDO0lBQ3pFLENBQUM7SUFFTyxjQUFjO1FBQ3BCLE1BQU0sTUFBTSxHQUNWLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO1FBQ2hFLE9BQU8sTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLG9CQUFvQixDQUFDO0lBQ3BFLENBQUM7SUFFTyxhQUFhO1FBQ25CLE1BQU0sTUFBTSxHQUNWLENBQUMsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO1FBQ25FLE9BQU8sTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLG1CQUFtQixDQUFDO0lBQ25FLENBQUM7SUFFRCxZQUFtQixVQUFtQjtRQUNwQyxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksUUFBUSxDQUFDO1lBQzVCLElBQUksRUFBRSxHQUFHLE1BQU0sQ0FBQyxRQUFRLEdBQUcsVUFBVSxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLFVBQVUsRUFBRSxFQUFFO1lBQzlFLFFBQVEsRUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFO1lBQzVCLElBQUksRUFBRSxRQUFRO1lBQ2QsaUJBQWlCLEVBQUUsS0FBSztZQUN4QixpQkFBaUIsRUFBRSxJQUFJLENBQUMsY0FBYyxFQUFFO1lBQ3hDLGVBQWUsRUFBRSxJQUFJLENBQUMsYUFBYSxFQUFFO1NBQ3RDLENBQUMsQ0FBQTtJQUNKLENBQUM7SUFFTSxJQUFJLENBQUMsR0FBRyxJQUFlO1FBQzVCLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDL0IsQ0FBQztJQUVNLElBQUksQ0FBQyxHQUFHLElBQWU7UUFDNUIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQztJQUMvQixDQUFDO0lBRU0sS0FBSyxDQUFDLEdBQUcsSUFBZTtRQUM3QixJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ2hDLENBQUM7SUFFTSxLQUFLLENBQUMsR0FBRyxJQUFlO1FBQzdCLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDaEMsQ0FBQyJ9
|
|
@@ -1,25 +1,27 @@
|
|
|
1
|
-
import { SarifToSlackClientOptions } from './types';
|
|
1
|
+
import { type SarifToSlackClientOptions } from './types';
|
|
2
2
|
/**
|
|
3
3
|
* Service to convert SARIF files to Slack messages and send them.
|
|
4
4
|
* @public
|
|
5
5
|
*/
|
|
6
6
|
export declare class SarifToSlackClient {
|
|
7
|
+
private readonly _logger;
|
|
7
8
|
private _message?;
|
|
8
9
|
private _sarifModel?;
|
|
9
10
|
private _sendIf;
|
|
10
11
|
private constructor();
|
|
11
12
|
private static createRunIdGenerator;
|
|
12
|
-
static create(opts: SarifToSlackClientOptions): Promise<SarifToSlackClient>;
|
|
13
|
-
private static buildModel;
|
|
14
13
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* @param
|
|
18
|
-
* @param opts - An instance of {@link SarifToSlackClientOptions}
|
|
19
|
-
*
|
|
20
|
-
*
|
|
14
|
+
* Creates an instance of {@link SarifToSlackClient} class. It already has all
|
|
15
|
+
* properties and fields initialized.
|
|
16
|
+
* @param webhookUrl - Slack webhook URL.
|
|
17
|
+
* @param opts - An instance of {@link SarifToSlackClientOptions} type.
|
|
18
|
+
*
|
|
19
|
+
* @see SarifToSlackClientOptions
|
|
20
|
+
*
|
|
21
|
+
* @public
|
|
21
22
|
*/
|
|
22
|
-
|
|
23
|
+
static create(webhookUrl: string, opts: SarifToSlackClientOptions): Promise<SarifToSlackClient>;
|
|
24
|
+
private static buildModel;
|
|
23
25
|
/**
|
|
24
26
|
* Sends a Slack message.
|
|
25
27
|
* @returns A promise that resolves when the message has been sent.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SarifToSlackClient.d.ts","sourceRoot":"","sources":["../src/SarifToSlackClient.ts"],"names":[],"mappings":"AAGA,OAAO,
|
|
1
|
+
{"version":3,"file":"SarifToSlackClient.d.ts","sourceRoot":"","sources":["../src/SarifToSlackClient.ts"],"names":[],"mappings":"AAGA,OAAO,EAIL,KAAK,yBAAyB,EAG/B,MAAM,SAAS,CAAA;AAWhB;;;GAGG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;IAC5D,OAAO,CAAC,QAAQ,CAAC,CAAe;IAChC,OAAO,CAAC,WAAW,CAAC,CAAa;IAEjC,OAAO,CAAC,OAAO,CAAyB;IAExC,OAAO;IAIP,OAAO,CAAC,MAAM,CAAE,oBAAoB;IAOpC;;;;;;;;;OASG;WACiB,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,kBAAkB,CAAC;mBASvF,UAAU;IAoE/B;;;;;OAKG;IACU,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAelC,OAAO,KAAK,iBAAiB,GAyD5B;CACF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { promises as fs } from 'fs';
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
2
|
import Logger from './Logger';
|
|
3
3
|
import { SecurityLevel, SecuritySeverity } from './types';
|
|
4
|
-
import
|
|
4
|
+
import { logMetadata } from './system';
|
|
5
5
|
import { extractListOfFiles } from './utils/FileUtils';
|
|
6
6
|
import { createRepresentation } from './representations/RepresentationFactory';
|
|
7
7
|
import { createFinding } from './model/Finding';
|
|
@@ -15,12 +15,12 @@ import { SendIf, sendIfLogMessage } from './model/SendIf';
|
|
|
15
15
|
* @public
|
|
16
16
|
*/
|
|
17
17
|
export class SarifToSlackClient {
|
|
18
|
+
_logger = new Logger('SarifToSlackClient');
|
|
18
19
|
_message;
|
|
19
20
|
_sarifModel;
|
|
20
21
|
_sendIf = SendIf.Always;
|
|
21
|
-
constructor(
|
|
22
|
-
|
|
23
|
-
System.initialize();
|
|
22
|
+
constructor() {
|
|
23
|
+
logMetadata();
|
|
24
24
|
}
|
|
25
25
|
static *createRunIdGenerator() {
|
|
26
26
|
let runId = 1;
|
|
@@ -28,11 +28,22 @@ export class SarifToSlackClient {
|
|
|
28
28
|
yield runId++;
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Creates an instance of {@link SarifToSlackClient} class. It already has all
|
|
33
|
+
* properties and fields initialized.
|
|
34
|
+
* @param webhookUrl - Slack webhook URL.
|
|
35
|
+
* @param opts - An instance of {@link SarifToSlackClientOptions} type.
|
|
36
|
+
*
|
|
37
|
+
* @see SarifToSlackClientOptions
|
|
38
|
+
*
|
|
39
|
+
* @public
|
|
40
|
+
*/
|
|
41
|
+
static async create(webhookUrl, opts) {
|
|
42
|
+
const instance = new SarifToSlackClient();
|
|
43
|
+
instance._logger.trace(opts);
|
|
33
44
|
instance._sendIf = opts.sendIf ?? instance._sendIf;
|
|
34
45
|
instance._sarifModel = await SarifToSlackClient.buildModel(opts.sarif);
|
|
35
|
-
instance._message = await SarifToSlackClient.initialize(instance._sarifModel
|
|
46
|
+
instance._message = await SarifToSlackClient.initialize(webhookUrl, opts, instance._sarifModel);
|
|
36
47
|
return instance;
|
|
37
48
|
}
|
|
38
49
|
static async buildModel(sarifOpts) {
|
|
@@ -47,7 +58,7 @@ export class SarifToSlackClient {
|
|
|
47
58
|
const sarifLog = JSON.parse(sarifJson);
|
|
48
59
|
for (const run of sarifLog.runs) {
|
|
49
60
|
const runId = runIdGenerator.next();
|
|
50
|
-
let runMetadata
|
|
61
|
+
let runMetadata;
|
|
51
62
|
for (const result of run.results ?? []) {
|
|
52
63
|
runMetadata = {
|
|
53
64
|
id: runId.value,
|
|
@@ -67,13 +78,15 @@ export class SarifToSlackClient {
|
|
|
67
78
|
/**
|
|
68
79
|
* The main function to initialize a list of {@link SlackMessage} objects based
|
|
69
80
|
* on the given SARIF file(s).
|
|
70
|
-
* @param
|
|
81
|
+
* @param webhookUrl - Slack webhook URL.
|
|
71
82
|
* @param opts - An instance of {@link SarifToSlackClientOptions} object.
|
|
83
|
+
* @param sarifModel - An instance of SarifModel object.
|
|
72
84
|
* @returns A map where key is the SARIF file and value is an instance of
|
|
73
85
|
* {@link SlackMessage} object.
|
|
86
|
+
* @internal
|
|
74
87
|
*/
|
|
75
|
-
static async initialize(
|
|
76
|
-
const message = createSlackMessage(
|
|
88
|
+
static async initialize(webhookUrl, opts, sarifModel) {
|
|
89
|
+
const message = createSlackMessage(webhookUrl, {
|
|
77
90
|
username: opts.username,
|
|
78
91
|
iconUrl: opts.iconUrl,
|
|
79
92
|
color: identifyColor(sarifModel.findings, opts.color),
|
|
@@ -108,10 +121,10 @@ export class SarifToSlackClient {
|
|
|
108
121
|
throw new Error('Slack message was not prepared.');
|
|
109
122
|
}
|
|
110
123
|
const text = await this._message.send();
|
|
111
|
-
|
|
124
|
+
this._logger.info('Message sent. Status:', text);
|
|
112
125
|
}
|
|
113
126
|
else {
|
|
114
|
-
|
|
127
|
+
this._logger.info(sendIfLogMessage(this._sendIf));
|
|
115
128
|
}
|
|
116
129
|
}
|
|
117
130
|
get shouldSendMessage() {
|
|
@@ -172,4 +185,4 @@ export class SarifToSlackClient {
|
|
|
172
185
|
}
|
|
173
186
|
}
|
|
174
187
|
}
|
|
175
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
188
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2FyaWZUb1NsYWNrQ2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL1NhcmlmVG9TbGFja0NsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxJQUFJLEVBQUUsRUFBRSxNQUFNLFNBQVMsQ0FBQTtBQUV4QyxPQUFPLE1BQU0sTUFBTSxVQUFVLENBQUE7QUFDN0IsT0FBTyxFQUtMLGFBQWEsRUFDYixnQkFBZ0IsRUFDakIsTUFBTSxTQUFTLENBQUE7QUFDaEIsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLFVBQVUsQ0FBQTtBQUN0QyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQTtBQUN0RCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx5Q0FBeUMsQ0FBQTtBQUM5RSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0saUJBQWlCLENBQUE7QUFDL0MsT0FBTyxFQUFFLGlCQUFpQixFQUFFLHVCQUF1QixFQUFFLE1BQU0sb0JBQW9CLENBQUE7QUFDL0UsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLG1DQUFtQyxDQUFBO0FBQ2pFLE9BQU8sWUFBWSxNQUFNLHNCQUFzQixDQUFBO0FBQy9DLE9BQU8sRUFBRSxrQkFBa0IsRUFBcUIsTUFBTSxzQkFBc0IsQ0FBQTtBQUM1RSxPQUFPLEVBQUUsTUFBTSxFQUFFLGdCQUFnQixFQUFFLE1BQU0sZ0JBQWdCLENBQUE7QUFFekQ7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLGtCQUFrQjtJQUNaLE9BQU8sR0FBRyxJQUFJLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO0lBQ3BELFFBQVEsQ0FBZ0I7SUFDeEIsV0FBVyxDQUFjO0lBRXpCLE9BQU8sR0FBVyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBRXhDO1FBQ0UsV0FBVyxFQUFFLENBQUM7SUFDaEIsQ0FBQztJQUVPLE1BQU0sQ0FBQyxDQUFDLG9CQUFvQjtRQUNsQyxJQUFJLEtBQUss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
|