@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.
Files changed (129) hide show
  1. package/.gitattributes +1 -0
  2. package/.github/actionlint.yaml +9 -0
  3. package/.github/workflows/release.yml +19 -9
  4. package/.github/workflows/send-sarif-to-slack.yml +15 -12
  5. package/.pre-commit-config.yaml +2 -1
  6. package/.tool-versions +1 -1
  7. package/README.md +47 -12
  8. package/biome.json +5 -52
  9. package/dist/Logger.js +51 -22
  10. package/dist/SarifToSlackClient.d.ts +12 -10
  11. package/dist/SarifToSlackClient.d.ts.map +1 -1
  12. package/dist/SarifToSlackClient.js +28 -15
  13. package/dist/index.cjs +603 -237
  14. package/dist/index.d.ts +1 -8
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +2 -8
  17. package/dist/model/Finding.js +4 -3
  18. package/dist/model/SlackMessage.d.ts +0 -16
  19. package/dist/model/SlackMessage.d.ts.map +1 -1
  20. package/dist/model/color/ColorIdentification.js +50 -46
  21. package/dist/model/color/ColorOptions.d.ts +1 -1
  22. package/dist/model/color/ColorOptions.d.ts.map +1 -1
  23. package/dist/representations/CompactGroupByRepresentation.js +2 -2
  24. package/dist/representations/Representation.js +6 -2
  25. package/dist/representations/RepresentationFactory.js +19 -1
  26. package/dist/representations/TableGroupByRunPerLevelRepresentation.d.ts +6 -0
  27. package/dist/representations/TableGroupByRunPerLevelRepresentation.d.ts.map +1 -0
  28. package/dist/representations/TableGroupByRunPerLevelRepresentation.js +8 -0
  29. package/dist/representations/TableGroupByRunPerSeverityRepresentation.d.ts +6 -0
  30. package/dist/representations/TableGroupByRunPerSeverityRepresentation.d.ts.map +1 -0
  31. package/dist/representations/TableGroupByRunPerSeverityRepresentation.js +8 -0
  32. package/dist/representations/TableGroupByRunRepresentation.d.ts +7 -0
  33. package/dist/representations/TableGroupByRunRepresentation.d.ts.map +1 -0
  34. package/dist/representations/TableGroupByRunRepresentation.js +7 -0
  35. package/dist/representations/TableGroupBySarifPerLevelRepresentation.d.ts +6 -0
  36. package/dist/representations/TableGroupBySarifPerLevelRepresentation.d.ts.map +1 -0
  37. package/dist/representations/TableGroupBySarifPerLevelRepresentation.js +8 -0
  38. package/dist/representations/TableGroupBySarifPerSeverityRepresentation.d.ts +6 -0
  39. package/dist/representations/TableGroupBySarifPerSeverityRepresentation.d.ts.map +1 -0
  40. package/dist/representations/TableGroupBySarifPerSeverityRepresentation.js +8 -0
  41. package/dist/representations/TableGroupBySarifRepresentation.d.ts +9 -0
  42. package/dist/representations/TableGroupBySarifRepresentation.d.ts.map +1 -0
  43. package/dist/representations/TableGroupBySarifRepresentation.js +15 -0
  44. package/dist/representations/TableGroupByToolNamePerLevelRepresentation.d.ts +6 -0
  45. package/dist/representations/TableGroupByToolNamePerLevelRepresentation.d.ts.map +1 -0
  46. package/dist/representations/TableGroupByToolNamePerLevelRepresentation.js +8 -0
  47. package/dist/representations/TableGroupByToolNamePerSeverityRepresentation.d.ts +6 -0
  48. package/dist/representations/TableGroupByToolNamePerSeverityRepresentation.d.ts.map +1 -0
  49. package/dist/representations/TableGroupByToolNamePerSeverityRepresentation.js +8 -0
  50. package/dist/representations/TableGroupByToolNameRepresentation.d.ts +7 -0
  51. package/dist/representations/TableGroupByToolNameRepresentation.d.ts.map +1 -0
  52. package/dist/representations/TableGroupByToolNameRepresentation.js +7 -0
  53. package/dist/representations/TableGroupRepresentation.d.ts +16 -0
  54. package/dist/representations/TableGroupRepresentation.d.ts.map +1 -0
  55. package/dist/representations/TableGroupRepresentation.js +62 -0
  56. package/dist/representations/table/Cell.d.ts +10 -0
  57. package/dist/representations/table/Cell.d.ts.map +1 -0
  58. package/dist/representations/table/Cell.js +23 -0
  59. package/dist/representations/table/Column.d.ts +11 -0
  60. package/dist/representations/table/Column.d.ts.map +1 -0
  61. package/dist/representations/table/Column.js +31 -0
  62. package/dist/representations/table/Row.d.ts +15 -0
  63. package/dist/representations/table/Row.d.ts.map +1 -0
  64. package/dist/representations/table/Row.js +45 -0
  65. package/dist/representations/table/Table.d.ts +14 -0
  66. package/dist/representations/table/Table.d.ts.map +1 -0
  67. package/dist/representations/table/Table.js +66 -0
  68. package/dist/sarif-to-slack.d.ts +98 -88
  69. package/dist/system.d.ts +2 -0
  70. package/dist/system.d.ts.map +1 -0
  71. package/dist/system.js +24 -0
  72. package/dist/tsdoc-metadata.json +1 -1
  73. package/dist/types.d.ts +90 -56
  74. package/dist/types.d.ts.map +1 -1
  75. package/dist/types.js +89 -42
  76. package/dist/utils/FileUtils.js +8 -7
  77. package/dist/utils/StringUtils.d.ts +2 -0
  78. package/dist/utils/StringUtils.d.ts.map +1 -0
  79. package/dist/utils/StringUtils.js +5 -0
  80. package/etc/sarif-to-slack.api.md +8 -36
  81. package/package.json +10 -10
  82. package/src/Logger.ts +64 -26
  83. package/src/SarifToSlackClient.ts +42 -29
  84. package/src/index.ts +0 -9
  85. package/src/model/Finding.ts +14 -13
  86. package/src/model/FindingArray.ts +1 -1
  87. package/src/model/SlackMessage.ts +5 -5
  88. package/src/model/color/ColorIdentification.ts +66 -50
  89. package/src/model/color/ColorOptions.ts +1 -1
  90. package/src/processors/CodeQLProcessor.ts +1 -1
  91. package/src/representations/CompactGroupByRepresentation.ts +2 -2
  92. package/src/representations/CompactGroupByRunRepresentation.ts +2 -2
  93. package/src/representations/CompactGroupBySarifRepresentation.ts +2 -2
  94. package/src/representations/CompactGroupByToolNameRepresentation.ts +2 -2
  95. package/src/representations/CompactTotalRepresentation.ts +1 -1
  96. package/src/representations/Representation.ts +9 -4
  97. package/src/representations/RepresentationFactory.ts +26 -2
  98. package/src/representations/TableGroupByRunPerLevelRepresentation.ts +9 -0
  99. package/src/representations/TableGroupByRunPerSeverityRepresentation.ts +9 -0
  100. package/src/representations/TableGroupByRunRepresentation.ts +15 -0
  101. package/src/representations/TableGroupBySarifPerLevelRepresentation.ts +9 -0
  102. package/src/representations/TableGroupBySarifPerSeverityRepresentation.ts +9 -0
  103. package/src/representations/TableGroupBySarifRepresentation.ts +25 -0
  104. package/src/representations/TableGroupByToolNamePerLevelRepresentation.ts +10 -0
  105. package/src/representations/TableGroupByToolNamePerSeverityRepresentation.ts +10 -0
  106. package/src/representations/TableGroupByToolNameRepresentation.ts +15 -0
  107. package/src/representations/TableGroupRepresentation.ts +78 -0
  108. package/src/representations/table/Cell.ts +25 -0
  109. package/src/representations/table/Column.ts +39 -0
  110. package/src/representations/table/Row.ts +50 -0
  111. package/src/representations/table/Table.ts +93 -0
  112. package/src/system.ts +27 -0
  113. package/src/types.ts +98 -58
  114. package/src/utils/Comparators.ts +1 -1
  115. package/src/utils/FileUtils.ts +20 -19
  116. package/src/utils/StringUtils.ts +7 -0
  117. package/test-data/sarif/codeql-go.sarif +1 -1
  118. package/test-data/sarif/runs-1-extensions-1-results-0.sarif +2 -2
  119. package/test-data/sarif/snyk-hex.sarif +1 -1
  120. package/tests/integration/SendSarifToSlack.spec.ts +73 -83
  121. package/tests/representations/table/Table.spec.ts +174 -0
  122. package/dist/System.d.ts +0 -2
  123. package/dist/System.d.ts.map +0 -1
  124. package/dist/System.js +0 -15
  125. package/src/System.ts +0 -16
  126. /package/test-data/sarif/{tmp → multiple}/codeql-csharp.sarif +0 -0
  127. /package/test-data/sarif/{tmp → multiple}/grype-container.sarif +0 -0
  128. /package/test-data/sarif/{tmp → multiple}/runs-1-tools-1-results-0.sarif +0 -0
  129. /package/test-data/sarif/{tmp → multiple}/runs-2-tools-2.sarif +0 -0
package/.gitattributes CHANGED
@@ -1 +1,2 @@
1
+ dist/** linguist-generated=true
1
2
  *.json linguist-language=JSON-with-Comments
@@ -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: "${{ secrets.GH_TOKEN }}"
39
+ token: "${{ steps.github-app.outputs.token }}"
33
40
 
34
41
  - name: Setup Node
35
- uses: actions/setup-node@v4
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
- git config user.email "fabasoad@gmail.com"
49
- git config user.name "fabasoad"
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@v3
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@v3
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@v4
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
@@ -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.1
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.6.0
1
+ nodejs 24.9.0
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  ![unit-tests](https://github.com/fabasoad/sarif-to-slack/actions/workflows/unit-tests.yml/badge.svg)
6
6
  ![security](https://github.com/fabasoad/sarif-to-slack/actions/workflows/security.yml/badge.svg)
7
7
  ![linting](https://github.com/fabasoad/sarif-to-slack/actions/workflows/linting.yml/badge.svg)
8
- [![codecov](https://codecov.io/github/fabasoad/sarif-to-slack/graph/badge.svg?token=I4FV5Q328I)](https://codecov.io/github/fabasoad/sarif-to-slack)
8
+ [![codecov](https://codecov.io/gh/fabasoad/sarif-to-slack/graph/badge.svg?token=I4FV5Q328I)](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 { SarifToSlackService, FooterType } from '@fabasoad/sarif-to-slack';
32
+ import {
33
+ Color,
34
+ FooterType,
35
+ RepresentationType,
36
+ SarifToSlackClient,
37
+ SendIf
38
+ } from '@fabasoad/sarif-to-slack';
27
39
 
28
- const service = await SarifToSlackService.create({
40
+ const client: SarifToSlackClient = await SarifToSlackClient.create({
29
41
  webhookUrl: 'https://hooks.slack.com/services/your/webhook/url',
30
- sarifPath: 'path/to/your/sarif/file.sarif',
31
- logLevel: 'info',
32
- username: 'SARIF Bot',
42
+ username: 'SARIF to Slack Bot',
33
43
  iconUrl: 'https://example.com/icon.png',
34
- color: '#36a64f',
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 service.sendAll();
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": false,
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": "off",
35
- "useIsNan": "error",
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
- "noClassAssign": "error",
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
- "noWith": "error",
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 { LogLevel } from './types';
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 DEFAULT_LOG_LEVEL = LogLevel.Info;
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
- static instance;
12
- static initialize(opts) {
13
- if (!Logger.instance) {
14
- Logger.instance = new TSLogger({
15
- name: '@fabasoad/sarif-to-slack',
16
- minLevel: process.env.ACTIONS_STEP_DEBUG === 'true' ? LogLevel.Silly : (opts?.level ?? Logger.DEFAULT_LOG_LEVEL),
17
- type: 'pretty',
18
- prettyLogTimeZone: 'UTC',
19
- prettyLogTemplate: opts?.template ?? Logger.DEFAULT_LOG_TEMPLATE,
20
- stylePrettyLogs: opts?.colored ?? Logger.DEFAULT_LOG_COLORED,
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
- static warn(...args) {
25
- Logger.instance.warn(...args);
53
+ info(...args) {
54
+ this._instance.info(...args);
26
55
  }
27
- static info(...args) {
28
- Logger.instance.info(...args);
56
+ warn(...args) {
57
+ this._instance.warn(...args);
29
58
  }
30
- static debug(...args) {
31
- Logger.instance.debug(...args);
59
+ trace(...args) {
60
+ this._instance.trace(...args);
32
61
  }
33
- static trace(...args) {
34
- Logger.instance.trace(...args);
62
+ debug(...args) {
63
+ this._instance.debug(...args);
35
64
  }
36
65
  }
37
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTG9nZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL0xvZ2dlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQVcsTUFBTSxJQUFJLFFBQVEsRUFBRSxNQUFNLE9BQU8sQ0FBQTtBQUNuRCxPQUFPLEVBQUUsUUFBUSxFQUFjLE1BQU0sU0FBUyxDQUFBO0FBRTlDOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQU8sTUFBTTtJQUNqQixNQUFNLENBQUMsaUJBQWlCLEdBQWEsUUFBUSxDQUFDLElBQUksQ0FBQTtJQUNsRCxNQUFNLENBQUMsb0JBQW9CLEdBQVcsK0NBQStDLENBQUE7SUFDckYsTUFBTSxDQUFDLG1CQUFtQixHQUFZLElBQUksQ0FBQTtJQUUxQyxNQUFNLENBQUMsUUFBUSxDQUFtQjtJQUVuQyxNQUFNLENBQUMsVUFBVSxDQUFDLElBQWlCO1FBQ3hDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDckIsTUFBTSxDQUFDLFFBQVEsR0FBRyxJQUFJLFFBQVEsQ0FBQztnQkFDN0IsSUFBSSxFQUFFLDBCQUEwQjtnQkFDaEMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsa0JBQWtCLEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxLQUFLLElBQUksTUFBTSxDQUFDLGlCQUFpQixDQUFDO2dCQUNoSCxJQUFJLEVBQUUsUUFBUTtnQkFDZCxpQkFBaUIsRUFBRSxLQUFLO2dCQUN4QixpQkFBaUIsRUFBRSxJQUFJLEVBQUUsUUFBUSxJQUFJLE1BQU0sQ0FBQyxvQkFBb0I7Z0JBQ2hFLGVBQWUsRUFBRSxJQUFJLEVBQUUsT0FBTyxJQUFJLE1BQU0sQ0FBQyxtQkFBbUI7YUFDN0QsQ0FBQyxDQUFBO1FBQ0osQ0FBQztJQUNILENBQUM7SUFFTSxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBZTtRQUNuQyxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFBO0lBQy9CLENBQUM7SUFFTSxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBZTtRQUNuQyxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFBO0lBQy9CLENBQUM7SUFFTSxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsSUFBZTtRQUNwQyxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFBO0lBQ2hDLENBQUM7SUFFTSxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsSUFBZTtRQUNwQyxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFBO0lBQ2hDLENBQUMifQ==
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
- * The main function to initialize a list of {@link SlackMessage} objects based
16
- * on the given SARIF file(s).
17
- * @param sarifModel - An instance of SarifModel object.
18
- * @param opts - An instance of {@link SarifToSlackClientOptions} object.
19
- * @returns A map where key is the SARIF file and value is an instance of
20
- * {@link SlackMessage} object.
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
- private static initialize;
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,EAKL,yBAAyB,EAG1B,MAAM,SAAS,CAAA;AAWhB;;;GAGG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,CAAc;IAC/B,OAAO,CAAC,WAAW,CAAC,CAAY;IAEhC,OAAO,CAAC,OAAO,CAAwB;IAEvC,OAAO;IAKP,OAAO,CAAC,MAAM,CAAE,oBAAoB;WAOhB,MAAM,CAAC,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,kBAAkB,CAAC;mBAQnE,UAAU;IAgC/B;;;;;;;OAOG;mBACkB,UAAU;IAyB/B;;;;;OAKG;IACU,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAelC,OAAO,KAAK,iBAAiB,GAyD5B;CACF"}
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 System from './System';
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(log) {
22
- Logger.initialize(log);
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
- static async create(opts) {
32
- const instance = new SarifToSlackClient(opts.log);
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, opts);
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 = undefined;
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 sarifModel - An instance of SarifModel object.
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(sarifModel, opts) {
76
- const message = createSlackMessage(opts.webhookUrl, {
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
- Logger.info('Message sent. Status:', text);
124
+ this._logger.info('Message sent. Status:', text);
112
125
  }
113
126
  else {
114
- Logger.info(sendIfLogMessage(this._sendIf));
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2FyaWZUb1NsYWNrQ2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL1NhcmlmVG9TbGFja0NsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxJQUFJLEVBQUUsRUFBRSxNQUFNLElBQUksQ0FBQTtBQUVuQyxPQUFPLE1BQU0sTUFBTSxVQUFVLENBQUE7QUFDN0IsT0FBTyxFQU1MLGFBQWEsRUFDYixnQkFBZ0IsRUFDakIsTUFBTSxTQUFTLENBQUE7QUFDaEIsT0FBTyxNQUFNLE1BQU0sVUFBVSxDQUFBO0FBQzdCLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBQ3RELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLHlDQUF5QyxDQUFBO0FBQzlFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQTtBQUMvQyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQTtBQUMvRSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sbUNBQW1DLENBQUE7QUFDakUsT0FBTyxZQUFZLE1BQU0sc0JBQXNCLENBQUE7QUFDL0MsT0FBTyxFQUFFLGtCQUFrQixFQUFnQixNQUFNLHNCQUFzQixDQUFBO0FBQ3ZFLE9BQU8sRUFBRSxNQUFNLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQTtBQUV6RDs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sa0JBQWtCO0lBQ3JCLFFBQVEsQ0FBZTtJQUN2QixXQUFXLENBQWE7SUFFeEIsT0FBTyxHQUFXLE1BQU0sQ0FBQyxNQUFNLENBQUE7SUFFdkMsWUFBb0IsR0FBZ0I7UUFDbEMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQTtRQUN0QixNQUFNLENBQUMsVUFBVSxFQUFFLENBQUE7SUFDckIsQ0FBQztJQUVPLE1BQU0sQ0FBQyxDQUFDLG9CQUFvQjtRQUNsQyxJQUFJ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
188
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2FyaWZUb1NsYWNrQ2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL1NhcmlmVG9TbGFja0NsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxJQUFJLEVBQUUsRUFBRSxNQUFNLFNBQVMsQ0FBQTtBQUV4QyxPQUFPLE1BQU0sTUFBTSxVQUFVLENBQUE7QUFDN0IsT0FBTyxFQUtMLGFBQWEsRUFDYixnQkFBZ0IsRUFDakIsTUFBTSxTQUFTLENBQUE7QUFDaEIsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLFVBQVUsQ0FBQTtBQUN0QyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQTtBQUN0RCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx5Q0FBeUMsQ0FBQTtBQUM5RSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0saUJBQWlCLENBQUE7QUFDL0MsT0FBTyxFQUFFLGlCQUFpQixFQUFFLHVCQUF1QixFQUFFLE1BQU0sb0JBQW9CLENBQUE7QUFDL0UsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLG1DQUFtQyxDQUFBO0FBQ2pFLE9BQU8sWUFBWSxNQUFNLHNCQUFzQixDQUFBO0FBQy9DLE9BQU8sRUFBRSxrQkFBa0IsRUFBcUIsTUFBTSxzQkFBc0IsQ0FBQTtBQUM1RSxPQUFPLEVBQUUsTUFBTSxFQUFFLGdCQUFnQixFQUFFLE1BQU0sZ0JBQWdCLENBQUE7QUFFekQ7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLGtCQUFrQjtJQUNaLE9BQU8sR0FBRyxJQUFJLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO0lBQ3BELFFBQVEsQ0FBZ0I7SUFDeEIsV0FBVyxDQUFjO0lBRXpCLE9BQU8sR0FBVyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBRXhDO1FBQ0UsV0FBVyxFQUFFLENBQUM7SUFDaEIsQ0FBQztJQUVPLE1BQU0sQ0FBQyxDQUFDLG9CQUFvQjtRQUNsQyxJQUFJLEtBQUss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