@digitraffic/common 2022.10.5

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 (199) hide show
  1. package/LICENSE +291 -0
  2. package/aws/infra/api/integration.d.ts +21 -0
  3. package/aws/infra/api/integration.js +52 -0
  4. package/aws/infra/api/response.d.ts +22 -0
  5. package/aws/infra/api/response.js +61 -0
  6. package/aws/infra/api/responses.d.ts +39 -0
  7. package/aws/infra/api/responses.js +79 -0
  8. package/aws/infra/api/static-integration.d.ts +15 -0
  9. package/aws/infra/api/static-integration.js +54 -0
  10. package/aws/infra/canaries/canary-alarm.d.ts +6 -0
  11. package/aws/infra/canaries/canary-alarm.js +26 -0
  12. package/aws/infra/canaries/canary-parameters.d.ts +18 -0
  13. package/aws/infra/canaries/canary-parameters.js +3 -0
  14. package/aws/infra/canaries/canary-role.d.ts +6 -0
  15. package/aws/infra/canaries/canary-role.js +46 -0
  16. package/aws/infra/canaries/canary.d.ts +8 -0
  17. package/aws/infra/canaries/canary.js +29 -0
  18. package/aws/infra/canaries/database-canary.d.ts +18 -0
  19. package/aws/infra/canaries/database-canary.js +55 -0
  20. package/aws/infra/canaries/database-checker.d.ts +21 -0
  21. package/aws/infra/canaries/database-checker.js +109 -0
  22. package/aws/infra/canaries/url-canary.d.ts +19 -0
  23. package/aws/infra/canaries/url-canary.js +46 -0
  24. package/aws/infra/canaries/url-checker.d.ts +46 -0
  25. package/aws/infra/canaries/url-checker.js +238 -0
  26. package/aws/infra/documentation.d.ts +56 -0
  27. package/aws/infra/documentation.js +95 -0
  28. package/aws/infra/scheduler.d.ts +12 -0
  29. package/aws/infra/scheduler.js +31 -0
  30. package/aws/infra/security-rule.d.ts +12 -0
  31. package/aws/infra/security-rule.js +39 -0
  32. package/aws/infra/sqs-integration.d.ts +7 -0
  33. package/aws/infra/sqs-integration.js +93 -0
  34. package/aws/infra/sqs-queue.d.ts +16 -0
  35. package/aws/infra/sqs-queue.js +130 -0
  36. package/aws/infra/stack/lambda-configs.d.ts +72 -0
  37. package/aws/infra/stack/lambda-configs.js +93 -0
  38. package/aws/infra/stack/monitoredfunction.d.ts +84 -0
  39. package/aws/infra/stack/monitoredfunction.js +135 -0
  40. package/aws/infra/stack/rest_apis.d.ts +40 -0
  41. package/aws/infra/stack/rest_apis.js +179 -0
  42. package/aws/infra/stack/stack-checking-aspect.d.ts +20 -0
  43. package/aws/infra/stack/stack-checking-aspect.js +163 -0
  44. package/aws/infra/stack/stack.d.ts +41 -0
  45. package/aws/infra/stack/stack.js +58 -0
  46. package/aws/infra/stack/subscription.d.ts +17 -0
  47. package/aws/infra/stack/subscription.js +41 -0
  48. package/aws/infra/usage-plans.d.ts +15 -0
  49. package/aws/infra/usage-plans.js +42 -0
  50. package/aws/runtime/apikey.d.ts +2 -0
  51. package/aws/runtime/apikey.js +13 -0
  52. package/aws/runtime/digitraffic-integration-response.d.ts +8 -0
  53. package/aws/runtime/digitraffic-integration-response.js +26 -0
  54. package/aws/runtime/messaging.d.ts +10 -0
  55. package/aws/runtime/messaging.js +31 -0
  56. package/aws/runtime/s3.d.ts +2 -0
  57. package/aws/runtime/s3.js +30 -0
  58. package/aws/runtime/secrets/dbsecret.d.ts +54 -0
  59. package/aws/runtime/secrets/dbsecret.js +96 -0
  60. package/aws/runtime/secrets/proxy-holder.d.ts +9 -0
  61. package/aws/runtime/secrets/proxy-holder.js +26 -0
  62. package/aws/runtime/secrets/rds-holder.d.ts +9 -0
  63. package/aws/runtime/secrets/rds-holder.js +26 -0
  64. package/aws/runtime/secrets/secret-holder.d.ts +26 -0
  65. package/aws/runtime/secrets/secret-holder.js +73 -0
  66. package/aws/runtime/secrets/secret.d.ts +8 -0
  67. package/aws/runtime/secrets/secret.js +43 -0
  68. package/aws/types/errors.d.ts +4 -0
  69. package/aws/types/errors.js +9 -0
  70. package/aws/types/lambda-response.d.ts +12 -0
  71. package/aws/types/lambda-response.js +28 -0
  72. package/aws/types/mediatypes.d.ts +10 -0
  73. package/aws/types/mediatypes.js +15 -0
  74. package/aws/types/model-with-reference.d.ts +7 -0
  75. package/aws/types/model-with-reference.js +3 -0
  76. package/aws/types/proxytypes.d.ts +26 -0
  77. package/aws/types/proxytypes.js +3 -0
  78. package/aws/types/tags.d.ts +2 -0
  79. package/aws/types/tags.js +7 -0
  80. package/database/cached.d.ts +7 -0
  81. package/database/cached.js +32 -0
  82. package/database/database.d.ts +19 -0
  83. package/database/database.js +62 -0
  84. package/database/last-updated.d.ts +16 -0
  85. package/database/last-updated.js +54 -0
  86. package/index.d.ts +1 -0
  87. package/index.js +18 -0
  88. package/marine/id_utils.d.ts +3 -0
  89. package/marine/id_utils.js +33 -0
  90. package/marine/rtz.d.ts +48 -0
  91. package/marine/rtz.js +3 -0
  92. package/package.json +55 -0
  93. package/src/aws/infra/api/integration.js +52 -0
  94. package/src/aws/infra/api/response.js +61 -0
  95. package/src/aws/infra/api/responses.js +79 -0
  96. package/src/aws/infra/api/static-integration.js +54 -0
  97. package/src/aws/infra/canaries/canary-alarm.js +26 -0
  98. package/src/aws/infra/canaries/canary-parameters.js +3 -0
  99. package/src/aws/infra/canaries/canary-role.js +46 -0
  100. package/src/aws/infra/canaries/canary.js +29 -0
  101. package/src/aws/infra/canaries/database-canary.js +55 -0
  102. package/src/aws/infra/canaries/database-checker.js +109 -0
  103. package/src/aws/infra/canaries/url-canary.js +46 -0
  104. package/src/aws/infra/canaries/url-checker.js +238 -0
  105. package/src/aws/infra/documentation.js +95 -0
  106. package/src/aws/infra/scheduler.js +31 -0
  107. package/src/aws/infra/security-rule.js +39 -0
  108. package/src/aws/infra/sqs-integration.js +93 -0
  109. package/src/aws/infra/sqs-queue.js +130 -0
  110. package/src/aws/infra/stack/lambda-configs.js +93 -0
  111. package/src/aws/infra/stack/monitoredfunction.js +135 -0
  112. package/src/aws/infra/stack/rest_apis.js +179 -0
  113. package/src/aws/infra/stack/stack-checking-aspect.js +163 -0
  114. package/src/aws/infra/stack/stack.js +58 -0
  115. package/src/aws/infra/stack/subscription.js +41 -0
  116. package/src/aws/infra/usage-plans.js +42 -0
  117. package/src/aws/runtime/apikey.js +13 -0
  118. package/src/aws/runtime/digitraffic-integration-response.js +26 -0
  119. package/src/aws/runtime/messaging.js +31 -0
  120. package/src/aws/runtime/s3.js +30 -0
  121. package/src/aws/runtime/secrets/dbsecret.js +96 -0
  122. package/src/aws/runtime/secrets/proxy-holder.js +26 -0
  123. package/src/aws/runtime/secrets/rds-holder.js +26 -0
  124. package/src/aws/runtime/secrets/secret-holder.js +73 -0
  125. package/src/aws/runtime/secrets/secret.js +43 -0
  126. package/src/aws/types/errors.js +9 -0
  127. package/src/aws/types/lambda-response.js +28 -0
  128. package/src/aws/types/mediatypes.js +15 -0
  129. package/src/aws/types/model-with-reference.js +3 -0
  130. package/src/aws/types/proxytypes.js +3 -0
  131. package/src/aws/types/tags.js +7 -0
  132. package/src/database/cached.js +32 -0
  133. package/src/database/database.js +62 -0
  134. package/src/database/last-updated.js +54 -0
  135. package/src/marine/id_utils.js +33 -0
  136. package/src/marine/rtz.js +3 -0
  137. package/src/test/asserter.js +45 -0
  138. package/src/test/db-testutils.js +31 -0
  139. package/src/test/httpserver.js +67 -0
  140. package/src/test/secret.js +25 -0
  141. package/src/test/secrets-manager.js +59 -0
  142. package/src/test/testutils.js +44 -0
  143. package/src/types/input-error.js +7 -0
  144. package/src/types/language.js +10 -0
  145. package/src/types/traffictype.js +13 -0
  146. package/src/types/validator.js +14 -0
  147. package/src/utils/api-model.js +129 -0
  148. package/src/utils/base64.js +21 -0
  149. package/src/utils/date-utils.js +34 -0
  150. package/src/utils/geojson-types.js +18 -0
  151. package/src/utils/geometry.js +140 -0
  152. package/src/utils/retry.js +50 -0
  153. package/src/utils/slack.js +25 -0
  154. package/src/utils/utils.js +40 -0
  155. package/test/asserter.d.ts +11 -0
  156. package/test/asserter.js +45 -0
  157. package/test/db-testutils.d.ts +2 -0
  158. package/test/db-testutils.js +31 -0
  159. package/test/httpserver.d.ts +18 -0
  160. package/test/httpserver.js +67 -0
  161. package/test/marine/id_utils.test.js +69 -0
  162. package/test/promise/promise.test.js +125 -0
  163. package/test/secret.d.ts +3 -0
  164. package/test/secret.js +25 -0
  165. package/test/secrets/dbsecret.test.js +71 -0
  166. package/test/secrets/secret-holder.test.js +124 -0
  167. package/test/secrets/secret.test.js +66 -0
  168. package/test/secrets-manager.d.ts +9 -0
  169. package/test/secrets-manager.js +59 -0
  170. package/test/test/httpserver.test.js +87 -0
  171. package/test/testutils.d.ts +12 -0
  172. package/test/testutils.js +44 -0
  173. package/test/utils/date-utils.test.js +51 -0
  174. package/test/utils/geometry.test.js +49 -0
  175. package/test/utils/utils.test.js +49 -0
  176. package/types/input-error.d.ts +2 -0
  177. package/types/input-error.js +7 -0
  178. package/types/language.d.ts +5 -0
  179. package/types/language.js +10 -0
  180. package/types/traffictype.d.ts +8 -0
  181. package/types/traffictype.js +13 -0
  182. package/types/validator.d.ts +4 -0
  183. package/types/validator.js +14 -0
  184. package/utils/api-model.d.ts +87 -0
  185. package/utils/api-model.js +129 -0
  186. package/utils/base64.d.ts +12 -0
  187. package/utils/base64.js +21 -0
  188. package/utils/date-utils.d.ts +17 -0
  189. package/utils/date-utils.js +34 -0
  190. package/utils/geojson-types.d.ts +14 -0
  191. package/utils/geojson-types.js +18 -0
  192. package/utils/geometry.d.ts +36 -0
  193. package/utils/geometry.js +140 -0
  194. package/utils/retry.d.ts +13 -0
  195. package/utils/retry.js +50 -0
  196. package/utils/slack.d.ts +5 -0
  197. package/utils/slack.js +25 -0
  198. package/utils/utils.d.ts +22 -0
  199. package/utils/utils.js +40 -0
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DigitrafficStaticIntegration = void 0;
4
+ const aws_apigateway_1 = require("aws-cdk-lib/aws-apigateway");
5
+ const mediatypes_1 = require("../../types/mediatypes");
6
+ const responses_1 = require("./responses");
7
+ const INTEGRATION_RESPONSE_200 = `{
8
+ "statusCode": 200
9
+ }`;
10
+ const METHOD_RESPONSE_200 = {
11
+ statusCode: '200',
12
+ };
13
+ /**
14
+ * Static integration, that returns the given response with given mediaType from given resource.
15
+ *
16
+ * @param resource
17
+ * @param mediaType
18
+ * @param response
19
+ */
20
+ class DigitrafficStaticIntegration extends aws_apigateway_1.MockIntegration {
21
+ constructor(resource, mediaType, response, enableCors = true, apiKeyRequired = true) {
22
+ const integrationResponse = DigitrafficStaticIntegration.createIntegrationResponse(response, mediaType, enableCors);
23
+ super({
24
+ passthroughBehavior: aws_apigateway_1.PassthroughBehavior.WHEN_NO_TEMPLATES,
25
+ requestTemplates: {
26
+ [mediaType]: INTEGRATION_RESPONSE_200,
27
+ },
28
+ integrationResponses: [integrationResponse],
29
+ });
30
+ ['GET', 'HEAD'].forEach((httpMethod) => {
31
+ resource.addMethod(httpMethod, this, {
32
+ apiKeyRequired,
33
+ methodResponses: [DigitrafficStaticIntegration.createMethodResponse(enableCors)],
34
+ });
35
+ });
36
+ }
37
+ static json(resource, response, enableCors = true, apiKeyRequired = true) {
38
+ return new DigitrafficStaticIntegration(resource, mediatypes_1.MediaType.APPLICATION_JSON, JSON.stringify(response), enableCors, apiKeyRequired);
39
+ }
40
+ static createIntegrationResponse(response, mediaType, enableCors) {
41
+ const integrationResponse = {
42
+ statusCode: '200',
43
+ responseTemplates: {
44
+ [mediaType]: response,
45
+ },
46
+ };
47
+ return enableCors ? { ...integrationResponse, ...responses_1.RESPONSE_CORS_INTEGRATION } : integrationResponse;
48
+ }
49
+ static createMethodResponse(enableCors) {
50
+ return enableCors ? (0, responses_1.corsMethod)(METHOD_RESPONSE_200) : METHOD_RESPONSE_200;
51
+ }
52
+ }
53
+ exports.DigitrafficStaticIntegration = DigitrafficStaticIntegration;
54
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdGljLWludGVncmF0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2F3cy9pbmZyYS9hcGkvc3RhdGljLWludGVncmF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLCtEQUEwRjtBQUMxRix1REFBaUQ7QUFDakQsMkNBQWtFO0FBRWxFLE1BQU0sd0JBQXdCLEdBQUc7O0VBRS9CLENBQUM7QUFFSCxNQUFNLG1CQUFtQixHQUFHO0lBQ3hCLFVBQVUsRUFBRSxLQUFLO0NBQ3BCLENBQUM7QUFFRjs7Ozs7O0dBTUc7QUFDSCxNQUFhLDRCQUE2QixTQUFRLGdDQUFlO0lBQzdELFlBQ0ksUUFBa0IsRUFBRSxTQUFvQixFQUFFLFFBQWdCLEVBQUUsVUFBVSxHQUFHLElBQUksRUFBRSxjQUFjLEdBQUcsSUFBSTtRQUVwRyxNQUFNLG1CQUFtQixHQUFHLDRCQUE0QixDQUFDLHlCQUF5QixDQUFDLFFBQVEsRUFBRSxTQUFTLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFFcEgsS0FBSyxDQUFDO1lBQ0YsbUJBQW1CLEVBQUUsb0NBQW1CLENBQUMsaUJBQWlCO1lBQzFELGdCQUFnQixFQUFFO2dCQUNkLENBQUMsU0FBUyxDQUFDLEVBQUUsd0JBQXdCO2FBQ3hDO1lBQ0Qsb0JBQW9CLEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQztTQUM5QyxDQUFDLENBQUM7UUFFSCxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxVQUFVLEVBQUUsRUFBRTtZQUNuQyxRQUFRLENBQUMsU0FBUyxDQUFDLFVBQVUsRUFBRSxJQUFJLEVBQUU7Z0JBQ2pDLGNBQWM7Z0JBQ2QsZUFBZSxFQUFFLENBQUMsNEJBQTRCLENBQUMsb0JBQW9CLENBQUMsVUFBVSxDQUFDLENBQUM7YUFDbkYsQ0FBQyxDQUFDO1FBQ1AsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQsTUFBTSxDQUFDLElBQUksQ0FBSSxRQUFrQixFQUFFLFFBQVcsRUFBRSxVQUFVLEdBQUcsSUFBSSxFQUFFLGNBQWMsR0FBRyxJQUFJO1FBQ3BGLE9BQU8sSUFBSSw0QkFBNEIsQ0FDbkMsUUFBUSxFQUFFLHNCQUFTLENBQUMsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsRUFBRSxVQUFVLEVBQUUsY0FBYyxDQUM3RixDQUFDO0lBQ04sQ0FBQztJQUVPLE1BQU0sQ0FBQyx5QkFBeUIsQ0FBQyxRQUFnQixFQUFFLFNBQW9CLEVBQUUsVUFBbUI7UUFDaEcsTUFBTSxtQkFBbUIsR0FBRztZQUN4QixVQUFVLEVBQUUsS0FBSztZQUNqQixpQkFBaUIsRUFBRTtnQkFDZixDQUFDLFNBQVMsQ0FBQyxFQUFFLFFBQVE7YUFDeEI7U0FDSixDQUFDO1FBRUYsT0FBTyxVQUFVLENBQUMsQ0FBQyxDQUFDLEVBQUMsR0FBRyxtQkFBbUIsRUFBRSxHQUFHLHFDQUF5QixFQUFDLENBQUMsQ0FBQyxDQUFDLG1CQUFtQixDQUFDO0lBQ3JHLENBQUM7SUFFTyxNQUFNLENBQUMsb0JBQW9CLENBQUMsVUFBbUI7UUFDbkQsT0FBTyxVQUFVLENBQUMsQ0FBQyxDQUFDLElBQUEsc0JBQVUsRUFBQyxtQkFBbUIsQ0FBQyxDQUFDLENBQUMsQ0FBQyxtQkFBbUIsQ0FBQztJQUM5RSxDQUFDO0NBQ0o7QUExQ0Qsb0VBMENDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtNb2NrSW50ZWdyYXRpb24sIFBhc3N0aHJvdWdoQmVoYXZpb3IsIFJlc291cmNlfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWFwaWdhdGV3YXlcIjtcbmltcG9ydCB7TWVkaWFUeXBlfSBmcm9tIFwiLi4vLi4vdHlwZXMvbWVkaWF0eXBlc1wiO1xuaW1wb3J0IHtjb3JzTWV0aG9kLCBSRVNQT05TRV9DT1JTX0lOVEVHUkFUSU9OfSBmcm9tIFwiLi9yZXNwb25zZXNcIjtcblxuY29uc3QgSU5URUdSQVRJT05fUkVTUE9OU0VfMjAwID0gYHtcbiAgICBcInN0YXR1c0NvZGVcIjogMjAwXG59YDtcblxuY29uc3QgTUVUSE9EX1JFU1BPTlNFXzIwMCA9IHtcbiAgICBzdGF0dXNDb2RlOiAnMjAwJyxcbn07XG5cbi8qKlxuICogU3RhdGljIGludGVncmF0aW9uLCB0aGF0IHJldHVybnMgdGhlIGdpdmVuIHJlc3BvbnNlIHdpdGggZ2l2ZW4gbWVkaWFUeXBlIGZyb20gZ2l2ZW4gcmVzb3VyY2UuXG4gKlxuICogQHBhcmFtIHJlc291cmNlXG4gKiBAcGFyYW0gbWVkaWFUeXBlXG4gKiBAcGFyYW0gcmVzcG9uc2VcbiAqL1xuZXhwb3J0IGNsYXNzIERpZ2l0cmFmZmljU3RhdGljSW50ZWdyYXRpb24gZXh0ZW5kcyBNb2NrSW50ZWdyYXRpb24ge1xuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICByZXNvdXJjZTogUmVzb3VyY2UsIG1lZGlhVHlwZTogTWVkaWFUeXBlLCByZXNwb25zZTogc3RyaW5nLCBlbmFibGVDb3JzID0gdHJ1ZSwgYXBpS2V5UmVxdWlyZWQgPSB0cnVlLFxuICAgICkge1xuICAgICAgICBjb25zdCBpbnRlZ3JhdGlvblJlc3BvbnNlID0gRGlnaXRyYWZmaWNTdGF0aWNJbnRlZ3JhdGlvbi5jcmVhdGVJbnRlZ3JhdGlvblJlc3BvbnNlKHJlc3BvbnNlLCBtZWRpYVR5cGUsIGVuYWJsZUNvcnMpO1xuXG4gICAgICAgIHN1cGVyKHtcbiAgICAgICAgICAgIHBhc3N0aHJvdWdoQmVoYXZpb3I6IFBhc3N0aHJvdWdoQmVoYXZpb3IuV0hFTl9OT19URU1QTEFURVMsXG4gICAgICAgICAgICByZXF1ZXN0VGVtcGxhdGVzOiB7XG4gICAgICAgICAgICAgICAgW21lZGlhVHlwZV06IElOVEVHUkFUSU9OX1JFU1BPTlNFXzIwMCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpbnRlZ3JhdGlvblJlc3BvbnNlczogW2ludGVncmF0aW9uUmVzcG9uc2VdLFxuICAgICAgICB9KTtcblxuICAgICAgICBbJ0dFVCcsICdIRUFEJ10uZm9yRWFjaCgoaHR0cE1ldGhvZCkgPT4ge1xuICAgICAgICAgICAgcmVzb3VyY2UuYWRkTWV0aG9kKGh0dHBNZXRob2QsIHRoaXMsIHtcbiAgICAgICAgICAgICAgICBhcGlLZXlSZXF1aXJlZCxcbiAgICAgICAgICAgICAgICBtZXRob2RSZXNwb25zZXM6IFtEaWdpdHJhZmZpY1N0YXRpY0ludGVncmF0aW9uLmNyZWF0ZU1ldGhvZFJlc3BvbnNlKGVuYWJsZUNvcnMpXSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBzdGF0aWMganNvbjxLPihyZXNvdXJjZTogUmVzb3VyY2UsIHJlc3BvbnNlOiBLLCBlbmFibGVDb3JzID0gdHJ1ZSwgYXBpS2V5UmVxdWlyZWQgPSB0cnVlKSB7XG4gICAgICAgIHJldHVybiBuZXcgRGlnaXRyYWZmaWNTdGF0aWNJbnRlZ3JhdGlvbihcbiAgICAgICAgICAgIHJlc291cmNlLCBNZWRpYVR5cGUuQVBQTElDQVRJT05fSlNPTiwgSlNPTi5zdHJpbmdpZnkocmVzcG9uc2UpLCBlbmFibGVDb3JzLCBhcGlLZXlSZXF1aXJlZCxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHN0YXRpYyBjcmVhdGVJbnRlZ3JhdGlvblJlc3BvbnNlKHJlc3BvbnNlOiBzdHJpbmcsIG1lZGlhVHlwZTogTWVkaWFUeXBlLCBlbmFibGVDb3JzOiBib29sZWFuKSB7XG4gICAgICAgIGNvbnN0IGludGVncmF0aW9uUmVzcG9uc2UgPSB7XG4gICAgICAgICAgICBzdGF0dXNDb2RlOiAnMjAwJyxcbiAgICAgICAgICAgIHJlc3BvbnNlVGVtcGxhdGVzOiB7XG4gICAgICAgICAgICAgICAgW21lZGlhVHlwZV06IHJlc3BvbnNlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgfTtcblxuICAgICAgICByZXR1cm4gZW5hYmxlQ29ycyA/IHsuLi5pbnRlZ3JhdGlvblJlc3BvbnNlLCAuLi5SRVNQT05TRV9DT1JTX0lOVEVHUkFUSU9OfSA6IGludGVncmF0aW9uUmVzcG9uc2U7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgY3JlYXRlTWV0aG9kUmVzcG9uc2UoZW5hYmxlQ29yczogYm9vbGVhbikge1xuICAgICAgICByZXR1cm4gZW5hYmxlQ29ycyA/IGNvcnNNZXRob2QoTUVUSE9EX1JFU1BPTlNFXzIwMCkgOiBNRVRIT0RfUkVTUE9OU0VfMjAwO1xuICAgIH1cbn1cbiJdfQ==
@@ -0,0 +1,6 @@
1
+ import { Construct } from "constructs";
2
+ import { CanaryParameters } from "./canary-parameters";
3
+ import { Canary } from "@aws-cdk/aws-synthetics-alpha";
4
+ export declare class CanaryAlarm {
5
+ constructor(stack: Construct, canary: Canary, params: CanaryParameters);
6
+ }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CanaryAlarm = void 0;
4
+ const aws_cloudwatch_1 = require("aws-cdk-lib/aws-cloudwatch");
5
+ const aws_cloudwatch_actions_1 = require("aws-cdk-lib/aws-cloudwatch-actions");
6
+ const aws_sns_1 = require("aws-cdk-lib/aws-sns");
7
+ class CanaryAlarm {
8
+ constructor(stack, canary, params) {
9
+ if (params.alarm ?? true) {
10
+ const alarmName = params.alarm?.alarmName ?? `${params.name}-alarm`;
11
+ const alarm = new aws_cloudwatch_1.Alarm(stack, alarmName, {
12
+ alarmName,
13
+ alarmDescription: params.alarm?.description ?? '',
14
+ metric: canary.metricSuccessPercent(),
15
+ evaluationPeriods: params.alarm?.evalutionPeriods ?? 1,
16
+ threshold: params.alarm?.threshold ?? 100,
17
+ comparisonOperator: aws_cloudwatch_1.ComparisonOperator.LESS_THAN_THRESHOLD,
18
+ });
19
+ if (params.alarm?.topicArn) {
20
+ alarm.addAlarmAction(new aws_cloudwatch_actions_1.SnsAction(aws_sns_1.Topic.fromTopicArn(stack, `${alarmName}-action`, params.alarm.topicArn)));
21
+ }
22
+ }
23
+ }
24
+ }
25
+ exports.CanaryAlarm = CanaryAlarm;
26
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FuYXJ5LWFsYXJtLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2F3cy9pbmZyYS9jYW5hcmllcy9jYW5hcnktYWxhcm0udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBRUEsK0RBQXFFO0FBRXJFLCtFQUE2RDtBQUM3RCxpREFBMEM7QUFFMUMsTUFBYSxXQUFXO0lBQ3BCLFlBQVksS0FBZ0IsRUFDeEIsTUFBYyxFQUNkLE1BQXdCO1FBQ3hCLElBQUksTUFBTSxDQUFDLEtBQUssSUFBSSxJQUFJLEVBQUU7WUFDdEIsTUFBTSxTQUFTLEdBQUcsTUFBTSxDQUFDLEtBQUssRUFBRSxTQUFTLElBQUksR0FBRyxNQUFNLENBQUMsSUFBSSxRQUFRLENBQUM7WUFFcEUsTUFBTSxLQUFLLEdBQUcsSUFBSSxzQkFBSyxDQUFDLEtBQUssRUFBRSxTQUFTLEVBQUU7Z0JBQ3RDLFNBQVM7Z0JBQ1QsZ0JBQWdCLEVBQUUsTUFBTSxDQUFDLEtBQUssRUFBRSxXQUFXLElBQUksRUFBRTtnQkFDakQsTUFBTSxFQUFFLE1BQU0sQ0FBQyxvQkFBb0IsRUFBRTtnQkFDckMsaUJBQWlCLEVBQUUsTUFBTSxDQUFDLEtBQUssRUFBRSxnQkFBZ0IsSUFBSSxDQUFDO2dCQUN0RCxTQUFTLEVBQUUsTUFBTSxDQUFDLEtBQUssRUFBRSxTQUFTLElBQUksR0FBRztnQkFDekMsa0JBQWtCLEVBQUUsbUNBQWtCLENBQUMsbUJBQW1CO2FBQzdELENBQUMsQ0FBQztZQUVILElBQUksTUFBTSxDQUFDLEtBQUssRUFBRSxRQUFRLEVBQUU7Z0JBQ3hCLEtBQUssQ0FBQyxjQUFjLENBQUMsSUFBSSxrQ0FBUyxDQUFDLGVBQUssQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUN2RCxHQUFHLFNBQVMsU0FBUyxFQUNyQixNQUFNLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUNoQztTQUNKO0lBQ0wsQ0FBQztDQUNKO0FBdkJELGtDQXVCQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7Q29uc3RydWN0fSBmcm9tIFwiY29uc3RydWN0c1wiO1xuaW1wb3J0IHtDYW5hcnlQYXJhbWV0ZXJzfSBmcm9tIFwiLi9jYW5hcnktcGFyYW1ldGVyc1wiO1xuaW1wb3J0IHtBbGFybSwgQ29tcGFyaXNvbk9wZXJhdG9yfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWNsb3Vkd2F0Y2hcIjtcbmltcG9ydCB7Q2FuYXJ5fSBmcm9tIFwiQGF3cy1jZGsvYXdzLXN5bnRoZXRpY3MtYWxwaGFcIjtcbmltcG9ydCB7U25zQWN0aW9ufSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWNsb3Vkd2F0Y2gtYWN0aW9uc1wiO1xuaW1wb3J0IHtUb3BpY30gZnJvbSBcImF3cy1jZGstbGliL2F3cy1zbnNcIjtcblxuZXhwb3J0IGNsYXNzIENhbmFyeUFsYXJtIHtcbiAgICBjb25zdHJ1Y3RvcihzdGFjazogQ29uc3RydWN0LFxuICAgICAgICBjYW5hcnk6IENhbmFyeSxcbiAgICAgICAgcGFyYW1zOiBDYW5hcnlQYXJhbWV0ZXJzKSB7XG4gICAgICAgIGlmIChwYXJhbXMuYWxhcm0gPz8gdHJ1ZSkge1xuICAgICAgICAgICAgY29uc3QgYWxhcm1OYW1lID0gcGFyYW1zLmFsYXJtPy5hbGFybU5hbWUgPz8gYCR7cGFyYW1zLm5hbWV9LWFsYXJtYDtcblxuICAgICAgICAgICAgY29uc3QgYWxhcm0gPSBuZXcgQWxhcm0oc3RhY2ssIGFsYXJtTmFtZSwge1xuICAgICAgICAgICAgICAgIGFsYXJtTmFtZSxcbiAgICAgICAgICAgICAgICBhbGFybURlc2NyaXB0aW9uOiBwYXJhbXMuYWxhcm0/LmRlc2NyaXB0aW9uID8/ICcnLFxuICAgICAgICAgICAgICAgIG1ldHJpYzogY2FuYXJ5Lm1ldHJpY1N1Y2Nlc3NQZXJjZW50KCksXG4gICAgICAgICAgICAgICAgZXZhbHVhdGlvblBlcmlvZHM6IHBhcmFtcy5hbGFybT8uZXZhbHV0aW9uUGVyaW9kcyA/PyAxLFxuICAgICAgICAgICAgICAgIHRocmVzaG9sZDogcGFyYW1zLmFsYXJtPy50aHJlc2hvbGQgPz8gMTAwLFxuICAgICAgICAgICAgICAgIGNvbXBhcmlzb25PcGVyYXRvcjogQ29tcGFyaXNvbk9wZXJhdG9yLkxFU1NfVEhBTl9USFJFU0hPTEQsXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgaWYgKHBhcmFtcy5hbGFybT8udG9waWNBcm4pIHtcbiAgICAgICAgICAgICAgICBhbGFybS5hZGRBbGFybUFjdGlvbihuZXcgU25zQWN0aW9uKFRvcGljLmZyb21Ub3BpY0FybihzdGFjayxcbiAgICAgICAgICAgICAgICAgICAgYCR7YWxhcm1OYW1lfS1hY3Rpb25gLFxuICAgICAgICAgICAgICAgICAgICBwYXJhbXMuYWxhcm0udG9waWNBcm4pKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG4iXX0=
@@ -0,0 +1,18 @@
1
+ import { Schedule } from "@aws-cdk/aws-synthetics-alpha";
2
+ /** Optional env parameters for canary */
3
+ declare type CanaryEnv = Record<string, string>;
4
+ export declare type CanaryParameters = {
5
+ readonly name: string;
6
+ readonly schedule?: Schedule;
7
+ readonly secret?: string;
8
+ readonly handler: string;
9
+ readonly alarm?: {
10
+ readonly alarmName?: string;
11
+ readonly description?: string;
12
+ readonly evalutionPeriods?: number;
13
+ readonly threshold?: number;
14
+ readonly topicArn?: string;
15
+ };
16
+ readonly canaryEnv?: CanaryEnv;
17
+ };
18
+ export {};
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FuYXJ5LXBhcmFtZXRlcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvYXdzL2luZnJhL2NhbmFyaWVzL2NhbmFyeS1wYXJhbWV0ZXJzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1NjaGVkdWxlfSBmcm9tIFwiQGF3cy1jZGsvYXdzLXN5bnRoZXRpY3MtYWxwaGFcIjtcblxuLyoqIE9wdGlvbmFsIGVudiBwYXJhbWV0ZXJzIGZvciBjYW5hcnkgKi9cbnR5cGUgQ2FuYXJ5RW52ID0gUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcblxuZXhwb3J0IHR5cGUgQ2FuYXJ5UGFyYW1ldGVycyA9IHtcbiAgICByZWFkb25seSBuYW1lOiBzdHJpbmc7XG4gICAgcmVhZG9ubHkgc2NoZWR1bGU/OiBTY2hlZHVsZTtcbiAgICByZWFkb25seSBzZWNyZXQ/OiBzdHJpbmc7XG4gICAgcmVhZG9ubHkgaGFuZGxlcjogc3RyaW5nO1xuICAgIHJlYWRvbmx5IGFsYXJtPzoge1xuICAgICAgICByZWFkb25seSBhbGFybU5hbWU/OiBzdHJpbmc7XG4gICAgICAgIHJlYWRvbmx5IGRlc2NyaXB0aW9uPzogc3RyaW5nO1xuICAgICAgICByZWFkb25seSBldmFsdXRpb25QZXJpb2RzPzogbnVtYmVyO1xuICAgICAgICByZWFkb25seSB0aHJlc2hvbGQ/OiBudW1iZXI7XG4gICAgICAgIHJlYWRvbmx5IHRvcGljQXJuPzogc3RyaW5nO1xuICAgIH1cbiAgICByZWFkb25seSBjYW5hcnlFbnY/OiBDYW5hcnlFbnY7XG59XG4iXX0=
@@ -0,0 +1,6 @@
1
+ import { Role } from "aws-cdk-lib/aws-iam";
2
+ import { Construct } from "constructs";
3
+ export declare class DigitrafficCanaryRole extends Role {
4
+ constructor(stack: Construct, canaryName: string);
5
+ withDatabaseAccess(): DigitrafficCanaryRole;
6
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DigitrafficCanaryRole = void 0;
4
+ const aws_iam_1 = require("aws-cdk-lib/aws-iam");
5
+ const BASE_POLICY_STATEMENT_PROPS = {
6
+ actions: [
7
+ "logs:CreateLogStream",
8
+ "logs:PutLogEvents",
9
+ "logs:CreateLogGroup",
10
+ "logs:DescribeLogGroups",
11
+ "logs:DescribeLogStreams",
12
+ ],
13
+ resources: ["*"],
14
+ };
15
+ const CLOUDWATCH_STATEMENT_PROPS = {
16
+ actions: [
17
+ "cloudwatch:PutMetricData",
18
+ ],
19
+ resources: ["*"],
20
+ conditions: {
21
+ "StringEquals": {
22
+ "cloudwatch:namespace": "CloudWatchSynthetics",
23
+ },
24
+ },
25
+ };
26
+ class DigitrafficCanaryRole extends aws_iam_1.Role {
27
+ constructor(stack, canaryName) {
28
+ super(stack, 'canary-role-' + canaryName, {
29
+ assumedBy: new aws_iam_1.ServicePrincipal("lambda.amazonaws.com"),
30
+ managedPolicies: [
31
+ aws_iam_1.ManagedPolicy.fromAwsManagedPolicyName("CloudWatchSyntheticsFullAccess"),
32
+ ],
33
+ });
34
+ this.addToPolicy(new aws_iam_1.PolicyStatement(BASE_POLICY_STATEMENT_PROPS));
35
+ this.addToPolicy(new aws_iam_1.PolicyStatement(CLOUDWATCH_STATEMENT_PROPS));
36
+ }
37
+ withDatabaseAccess() {
38
+ // Won't work :(
39
+ // this.addToPolicy(new PolicyStatement(DB_STATEMENT_PROPS));
40
+ // Works
41
+ this.addManagedPolicy(aws_iam_1.ManagedPolicy.fromAwsManagedPolicyName("service-role/AWSLambdaVPCAccessExecutionRole"));
42
+ return this;
43
+ }
44
+ }
45
+ exports.DigitrafficCanaryRole = DigitrafficCanaryRole;
46
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FuYXJ5LXJvbGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvYXdzL2luZnJhL2NhbmFyaWVzL2NhbmFyeS1yb2xlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLGlEQUFpSDtBQUdqSCxNQUFNLDJCQUEyQixHQUF5QjtJQUN0RCxPQUFPLEVBQUU7UUFDTCxzQkFBc0I7UUFDdEIsbUJBQW1CO1FBQ25CLHFCQUFxQjtRQUNyQix3QkFBd0I7UUFDeEIseUJBQXlCO0tBQzVCO0lBQ0QsU0FBUyxFQUFFLENBQUMsR0FBRyxDQUFDO0NBQ25CLENBQUM7QUFFRixNQUFNLDBCQUEwQixHQUF5QjtJQUNyRCxPQUFPLEVBQUU7UUFDTCwwQkFBMEI7S0FDN0I7SUFDRCxTQUFTLEVBQUUsQ0FBQyxHQUFHLENBQUM7SUFDaEIsVUFBVSxFQUFFO1FBQ1IsY0FBYyxFQUFFO1lBQ1osc0JBQXNCLEVBQUUsc0JBQXNCO1NBQ2pEO0tBQ0o7Q0FDSixDQUFDO0FBRUYsTUFBYSxxQkFBc0IsU0FBUSxjQUFJO0lBQzNDLFlBQVksS0FBZ0IsRUFBRSxVQUFrQjtRQUM1QyxLQUFLLENBQUMsS0FBSyxFQUFFLGNBQWMsR0FBRyxVQUFVLEVBQUU7WUFDdEMsU0FBUyxFQUFFLElBQUksMEJBQWdCLENBQUMsc0JBQXNCLENBQUM7WUFDdkQsZUFBZSxFQUFFO2dCQUNiLHVCQUFhLENBQUMsd0JBQXdCLENBQUMsZ0NBQWdDLENBQUM7YUFDM0U7U0FDSixDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUkseUJBQWUsQ0FBQywyQkFBMkIsQ0FBQyxDQUFDLENBQUM7UUFDbkUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLHlCQUFlLENBQUMsMEJBQTBCLENBQUMsQ0FBQyxDQUFDO0lBQ3RFLENBQUM7SUFFRCxrQkFBa0I7UUFDZCxnQkFBZ0I7UUFDaEIsNkRBQTZEO1FBQzdELFFBQVE7UUFDUixJQUFJLENBQUMsZ0JBQWdCLENBQUMsdUJBQWEsQ0FBQyx3QkFBd0IsQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDLENBQUM7UUFDOUcsT0FBTyxJQUFJLENBQUM7SUFDaEIsQ0FBQztDQUNKO0FBcEJELHNEQW9CQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7TWFuYWdlZFBvbGljeSwgUG9saWN5U3RhdGVtZW50LCBQb2xpY3lTdGF0ZW1lbnRQcm9wcywgUm9sZSwgU2VydmljZVByaW5jaXBhbH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1pYW1cIjtcbmltcG9ydCB7Q29uc3RydWN0fSBmcm9tIFwiY29uc3RydWN0c1wiO1xuXG5jb25zdCBCQVNFX1BPTElDWV9TVEFURU1FTlRfUFJPUFM6IFBvbGljeVN0YXRlbWVudFByb3BzID0ge1xuICAgIGFjdGlvbnM6IFtcbiAgICAgICAgXCJsb2dzOkNyZWF0ZUxvZ1N0cmVhbVwiLFxuICAgICAgICBcImxvZ3M6UHV0TG9nRXZlbnRzXCIsXG4gICAgICAgIFwibG9nczpDcmVhdGVMb2dHcm91cFwiLFxuICAgICAgICBcImxvZ3M6RGVzY3JpYmVMb2dHcm91cHNcIixcbiAgICAgICAgXCJsb2dzOkRlc2NyaWJlTG9nU3RyZWFtc1wiLFxuICAgIF0sXG4gICAgcmVzb3VyY2VzOiBbXCIqXCJdLFxufTtcblxuY29uc3QgQ0xPVURXQVRDSF9TVEFURU1FTlRfUFJPUFM6IFBvbGljeVN0YXRlbWVudFByb3BzID0ge1xuICAgIGFjdGlvbnM6IFtcbiAgICAgICAgXCJjbG91ZHdhdGNoOlB1dE1ldHJpY0RhdGFcIixcbiAgICBdLFxuICAgIHJlc291cmNlczogW1wiKlwiXSxcbiAgICBjb25kaXRpb25zOiB7XG4gICAgICAgIFwiU3RyaW5nRXF1YWxzXCI6IHtcbiAgICAgICAgICAgIFwiY2xvdWR3YXRjaDpuYW1lc3BhY2VcIjogXCJDbG91ZFdhdGNoU3ludGhldGljc1wiLFxuICAgICAgICB9LFxuICAgIH0sXG59O1xuXG5leHBvcnQgY2xhc3MgRGlnaXRyYWZmaWNDYW5hcnlSb2xlIGV4dGVuZHMgUm9sZSB7XG4gICAgY29uc3RydWN0b3Ioc3RhY2s6IENvbnN0cnVjdCwgY2FuYXJ5TmFtZTogc3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKHN0YWNrLCAnY2FuYXJ5LXJvbGUtJyArIGNhbmFyeU5hbWUsIHtcbiAgICAgICAgICAgIGFzc3VtZWRCeTogbmV3IFNlcnZpY2VQcmluY2lwYWwoXCJsYW1iZGEuYW1hem9uYXdzLmNvbVwiKSxcbiAgICAgICAgICAgIG1hbmFnZWRQb2xpY2llczogW1xuICAgICAgICAgICAgICAgIE1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKFwiQ2xvdWRXYXRjaFN5bnRoZXRpY3NGdWxsQWNjZXNzXCIpLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5hZGRUb1BvbGljeShuZXcgUG9saWN5U3RhdGVtZW50KEJBU0VfUE9MSUNZX1NUQVRFTUVOVF9QUk9QUykpO1xuICAgICAgICB0aGlzLmFkZFRvUG9saWN5KG5ldyBQb2xpY3lTdGF0ZW1lbnQoQ0xPVURXQVRDSF9TVEFURU1FTlRfUFJPUFMpKTtcbiAgICB9XG5cbiAgICB3aXRoRGF0YWJhc2VBY2Nlc3MoKTogRGlnaXRyYWZmaWNDYW5hcnlSb2xlIHtcbiAgICAgICAgLy8gV29uJ3Qgd29yayA6KFxuICAgICAgICAvLyB0aGlzLmFkZFRvUG9saWN5KG5ldyBQb2xpY3lTdGF0ZW1lbnQoREJfU1RBVEVNRU5UX1BST1BTKSk7XG4gICAgICAgIC8vIFdvcmtzXG4gICAgICAgIHRoaXMuYWRkTWFuYWdlZFBvbGljeShNYW5hZ2VkUG9saWN5LmZyb21Bd3NNYW5hZ2VkUG9saWN5TmFtZShcInNlcnZpY2Utcm9sZS9BV1NMYW1iZGFWUENBY2Nlc3NFeGVjdXRpb25Sb2xlXCIpKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxufVxuIl19
@@ -0,0 +1,8 @@
1
+ import { Canary } from "@aws-cdk/aws-synthetics-alpha";
2
+ import { Role } from "aws-cdk-lib/aws-iam";
3
+ import { CanaryParameters } from "./canary-parameters";
4
+ import { Construct } from "constructs";
5
+ import { LambdaEnvironment } from "../stack/lambda-configs";
6
+ export declare class DigitrafficCanary extends Canary {
7
+ constructor(scope: Construct, canaryName: string, role: Role, params: CanaryParameters, environmentVariables: LambdaEnvironment);
8
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DigitrafficCanary = void 0;
4
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
5
+ const aws_synthetics_alpha_1 = require("@aws-cdk/aws-synthetics-alpha");
6
+ const canary_alarm_1 = require("./canary-alarm");
7
+ class DigitrafficCanary extends aws_synthetics_alpha_1.Canary {
8
+ constructor(scope, canaryName, role, params, environmentVariables) {
9
+ super(scope, canaryName, {
10
+ runtime: aws_synthetics_alpha_1.Runtime.SYNTHETICS_NODEJS_PUPPETEER_3_5,
11
+ role,
12
+ test: aws_synthetics_alpha_1.Test.custom({
13
+ code: new aws_synthetics_alpha_1.AssetCode("dist", {
14
+ exclude: ["lambda"],
15
+ }),
16
+ handler: params.handler,
17
+ }),
18
+ environmentVariables: { ...environmentVariables, ...params?.canaryEnv },
19
+ canaryName,
20
+ schedule: params.schedule ?? aws_synthetics_alpha_1.Schedule.rate(aws_cdk_lib_1.Duration.minutes(15)),
21
+ });
22
+ this.artifactsBucket.grantWrite(role);
23
+ if (params.alarm ?? true) {
24
+ new canary_alarm_1.CanaryAlarm(scope, this, params);
25
+ }
26
+ }
27
+ }
28
+ exports.DigitrafficCanary = DigitrafficCanary;
29
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FuYXJ5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2F3cy9pbmZyYS9jYW5hcmllcy9jYW5hcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkNBQXFDO0FBQ3JDLHdFQUF5RjtBQUV6RixpREFBMkM7QUFLM0MsTUFBYSxpQkFBa0IsU0FBUSw2QkFBTTtJQUN6QyxZQUNJLEtBQWdCLEVBQ2hCLFVBQWtCLEVBQ2xCLElBQVUsRUFDVixNQUF3QixFQUN4QixvQkFBdUM7UUFFdkMsS0FBSyxDQUFDLEtBQUssRUFBRSxVQUFVLEVBQUU7WUFDckIsT0FBTyxFQUFFLDhCQUFPLENBQUMsK0JBQStCO1lBQ2hELElBQUk7WUFDSixJQUFJLEVBQUUsMkJBQUksQ0FBQyxNQUFNLENBQUM7Z0JBQ2QsSUFBSSxFQUFFLElBQUksZ0NBQVMsQ0FBQyxNQUFNLEVBQUU7b0JBQ3hCLE9BQU8sRUFBRSxDQUFDLFFBQVEsQ0FBQztpQkFDdEIsQ0FBQztnQkFDRixPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU87YUFDMUIsQ0FBQztZQUNGLG9CQUFvQixFQUFFLEVBQUUsR0FBRyxvQkFBb0IsRUFBRSxHQUFHLE1BQU0sRUFBRSxTQUFTLEVBQUU7WUFDdkUsVUFBVTtZQUNWLFFBQVEsRUFBRSxNQUFNLENBQUMsUUFBUSxJQUFJLCtCQUFRLENBQUMsSUFBSSxDQUFDLHNCQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1NBQ25FLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRXRDLElBQUksTUFBTSxDQUFDLEtBQUssSUFBSSxJQUFJLEVBQUU7WUFDdEIsSUFBSSwwQkFBVyxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7U0FDeEM7SUFDTCxDQUFDO0NBQ0o7QUE1QkQsOENBNEJDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtEdXJhdGlvbn0gZnJvbSBcImF3cy1jZGstbGliXCI7XG5pbXBvcnQge0Fzc2V0Q29kZSwgQ2FuYXJ5LCBSdW50aW1lLCBTY2hlZHVsZSwgVGVzdH0gZnJvbSBcIkBhd3MtY2RrL2F3cy1zeW50aGV0aWNzLWFscGhhXCI7XG5pbXBvcnQge1JvbGV9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtaWFtXCI7XG5pbXBvcnQge0NhbmFyeUFsYXJtfSBmcm9tIFwiLi9jYW5hcnktYWxhcm1cIjtcbmltcG9ydCB7Q2FuYXJ5UGFyYW1ldGVyc30gZnJvbSBcIi4vY2FuYXJ5LXBhcmFtZXRlcnNcIjtcbmltcG9ydCB7Q29uc3RydWN0fSBmcm9tIFwiY29uc3RydWN0c1wiO1xuaW1wb3J0IHtMYW1iZGFFbnZpcm9ubWVudH0gZnJvbSBcIi4uL3N0YWNrL2xhbWJkYS1jb25maWdzXCI7XG5cbmV4cG9ydCBjbGFzcyBEaWdpdHJhZmZpY0NhbmFyeSBleHRlbmRzIENhbmFyeSB7XG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHNjb3BlOiBDb25zdHJ1Y3QsXG4gICAgICAgIGNhbmFyeU5hbWU6IHN0cmluZyxcbiAgICAgICAgcm9sZTogUm9sZSxcbiAgICAgICAgcGFyYW1zOiBDYW5hcnlQYXJhbWV0ZXJzLFxuICAgICAgICBlbnZpcm9ubWVudFZhcmlhYmxlczogTGFtYmRhRW52aXJvbm1lbnQsXG4gICAgKSB7XG4gICAgICAgIHN1cGVyKHNjb3BlLCBjYW5hcnlOYW1lLCB7XG4gICAgICAgICAgICBydW50aW1lOiBSdW50aW1lLlNZTlRIRVRJQ1NfTk9ERUpTX1BVUFBFVEVFUl8zXzUsXG4gICAgICAgICAgICByb2xlLFxuICAgICAgICAgICAgdGVzdDogVGVzdC5jdXN0b20oe1xuICAgICAgICAgICAgICAgIGNvZGU6IG5ldyBBc3NldENvZGUoXCJkaXN0XCIsIHtcbiAgICAgICAgICAgICAgICAgICAgZXhjbHVkZTogW1wibGFtYmRhXCJdLFxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgIGhhbmRsZXI6IHBhcmFtcy5oYW5kbGVyLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBlbnZpcm9ubWVudFZhcmlhYmxlczogeyAuLi5lbnZpcm9ubWVudFZhcmlhYmxlcywgLi4ucGFyYW1zPy5jYW5hcnlFbnYgfSxcbiAgICAgICAgICAgIGNhbmFyeU5hbWUsXG4gICAgICAgICAgICBzY2hlZHVsZTogcGFyYW1zLnNjaGVkdWxlID8/IFNjaGVkdWxlLnJhdGUoRHVyYXRpb24ubWludXRlcygxNSkpLFxuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLmFydGlmYWN0c0J1Y2tldC5ncmFudFdyaXRlKHJvbGUpO1xuXG4gICAgICAgIGlmIChwYXJhbXMuYWxhcm0gPz8gdHJ1ZSkge1xuICAgICAgICAgICAgbmV3IENhbmFyeUFsYXJtKHNjb3BlLCB0aGlzLCBwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfVxufVxuIl19
@@ -0,0 +1,18 @@
1
+ import { Role } from "aws-cdk-lib/aws-iam";
2
+ import { ISecret } from "aws-cdk-lib/aws-secretsmanager";
3
+ import { CanaryParameters } from "./canary-parameters";
4
+ import { DigitrafficCanary } from "./canary";
5
+ import { DigitrafficStack } from "../stack/stack";
6
+ export declare class DatabaseCanary extends DigitrafficCanary {
7
+ constructor(stack: DigitrafficStack, role: Role, secret: ISecret, params: CanaryParameters);
8
+ static create(stack: DigitrafficStack, role: Role, params: CanaryParameters): DatabaseCanary;
9
+ /**
10
+ *
11
+ * @param stack
12
+ * @param role
13
+ * @param name name of the typescipt file without -db -suffix. Max len is 10 char if @param canaryName is not given.
14
+ * @param params
15
+ * @param canaryName Optional name for canary if multiple canaries is made from same ${name}-db.ts canary file.
16
+ */
17
+ static createV2(stack: DigitrafficStack, role: Role, name: string, params?: Partial<CanaryParameters>, canaryName?: string): DatabaseCanary;
18
+ }
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DatabaseCanary = void 0;
4
+ const aws_synthetics_1 = require("aws-cdk-lib/aws-synthetics");
5
+ const aws_events_1 = require("aws-cdk-lib/aws-events");
6
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
7
+ const canary_1 = require("./canary");
8
+ class DatabaseCanary extends canary_1.DigitrafficCanary {
9
+ constructor(stack, role, secret, params) {
10
+ const canaryName = `${params.name}-db`;
11
+ const environmentVariables = stack.createDefaultLambdaEnvironment(`Synthetics-${canaryName}`);
12
+ // the handler code is defined at the actual project using this
13
+ super(stack, canaryName, role, params, environmentVariables);
14
+ this.artifactsBucket.grantWrite(this.role);
15
+ secret.grantRead(this.role);
16
+ // need to override vpc and security group, can't do this with cdk
17
+ if (this.node.defaultChild instanceof aws_synthetics_1.CfnCanary) {
18
+ const subnetIds = stack.vpc.privateSubnets.map(subnet => subnet.subnetId);
19
+ this.node.defaultChild.vpcConfig = {
20
+ vpcId: stack.vpc.vpcId,
21
+ securityGroupIds: [stack.lambdaDbSg.securityGroupId],
22
+ subnetIds: subnetIds,
23
+ };
24
+ }
25
+ }
26
+ static create(stack, role, params) {
27
+ return new DatabaseCanary(stack, role, stack.secret, { ...{
28
+ secret: stack.configuration.secretId,
29
+ schedule: aws_events_1.Schedule.rate(aws_cdk_lib_1.Duration.hours(1)),
30
+ handler: `${params.name}.handler`,
31
+ }, ...params });
32
+ }
33
+ /**
34
+ *
35
+ * @param stack
36
+ * @param role
37
+ * @param name name of the typescipt file without -db -suffix. Max len is 10 char if @param canaryName is not given.
38
+ * @param params
39
+ * @param canaryName Optional name for canary if multiple canaries is made from same ${name}-db.ts canary file.
40
+ */
41
+ static createV2(stack, role, name, params = {}, canaryName = name) {
42
+ return new DatabaseCanary(stack, role, stack.secret, { ...{
43
+ secret: stack.configuration.secretId,
44
+ schedule: aws_events_1.Schedule.rate(aws_cdk_lib_1.Duration.hours(1)),
45
+ handler: `${name}-db.handler`,
46
+ name: canaryName,
47
+ alarm: {
48
+ alarmName: (canaryName === name ? `${stack.configuration.shortName}-DB-Alarm` : `${canaryName}-DB-Alarm`),
49
+ topicArn: stack.configuration.alarmTopicArn,
50
+ },
51
+ }, ...params });
52
+ }
53
+ }
54
+ exports.DatabaseCanary = DatabaseCanary;
55
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YWJhc2UtY2FuYXJ5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2F3cy9pbmZyYS9jYW5hcmllcy9kYXRhYmFzZS1jYW5hcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBRUEsK0RBQXFEO0FBQ3JELHVEQUFnRDtBQUNoRCw2Q0FBcUM7QUFHckMscUNBQTJDO0FBRzNDLE1BQWEsY0FBZSxTQUFRLDBCQUFpQjtJQUNqRCxZQUFZLEtBQXVCLEVBQy9CLElBQVUsRUFDVixNQUFlLEVBQ2YsTUFBd0I7UUFDeEIsTUFBTSxVQUFVLEdBQUcsR0FBRyxNQUFNLENBQUMsSUFBSSxLQUFLLENBQUM7UUFDdkMsTUFBTSxvQkFBb0IsR0FBRyxLQUFLLENBQUMsOEJBQThCLENBQUMsY0FBYyxVQUFVLEVBQUUsQ0FBQyxDQUFDO1FBRTlGLCtEQUErRDtRQUMvRCxLQUFLLENBQ0QsS0FBSyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQ3ZCLE1BQU0sRUFBRSxvQkFBb0IsQ0FDL0IsQ0FBQztRQUVGLElBQUksQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUMzQyxNQUFNLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUU1QixrRUFBa0U7UUFDbEUsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksWUFBWSwwQkFBUyxFQUFFO1lBQzdDLE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUUxRSxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxTQUFTLEdBQUc7Z0JBQy9CLEtBQUssRUFBRSxLQUFLLENBQUMsR0FBRyxDQUFDLEtBQUs7Z0JBQ3RCLGdCQUFnQixFQUFFLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxlQUFlLENBQUM7Z0JBQ3BELFNBQVMsRUFBRSxTQUFTO2FBQ3ZCLENBQUM7U0FDTDtJQUNMLENBQUM7SUFFRCxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQXVCLEVBQ2pDLElBQVUsRUFDVixNQUF3QjtRQUN4QixPQUFPLElBQUksY0FBYyxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDLE1BQU0sRUFDL0MsRUFBQyxHQUFHO2dCQUNBLE1BQU0sRUFBRSxLQUFLLENBQUMsYUFBYSxDQUFDLFFBQVE7Z0JBQ3BDLFFBQVEsRUFBRSxxQkFBUSxDQUFDLElBQUksQ0FBQyxzQkFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDMUMsT0FBTyxFQUFFLEdBQUcsTUFBTSxDQUFDLElBQUksVUFBVTthQUNwQyxFQUFFLEdBQUcsTUFBTSxFQUFDLENBQUMsQ0FBQztJQUN2QixDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILE1BQU0sQ0FBQyxRQUFRLENBQ1gsS0FBdUIsRUFDdkIsSUFBVSxFQUNWLElBQVksRUFDWixTQUFvQyxFQUFFLEVBQ3RDLFVBQVUsR0FBQyxJQUFJO1FBRWYsT0FBTyxJQUFJLGNBQWMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQyxNQUFNLEVBQy9DLEVBQUMsR0FBRztnQkFDQSxNQUFNLEVBQUUsS0FBSyxDQUFDLGFBQWEsQ0FBQyxRQUFRO2dCQUNwQyxRQUFRLEVBQUUscUJBQVEsQ0FBQyxJQUFJLENBQUMsc0JBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQzFDLE9BQU8sRUFBRSxHQUFHLElBQUksYUFBYTtnQkFDN0IsSUFBSSxFQUFHLFVBQVU7Z0JBQ2pCLEtBQUssRUFBRTtvQkFDSCxTQUFTLEVBQUUsQ0FBQyxVQUFVLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxhQUFhLENBQUMsU0FBUyxXQUFXLENBQUMsQ0FBQyxDQUFDLEdBQUcsVUFBVSxXQUFXLENBQUM7b0JBQ3pHLFFBQVEsRUFBRSxLQUFLLENBQUMsYUFBYSxDQUFDLGFBQWE7aUJBQzlDO2FBQ0osRUFBRSxHQUFHLE1BQU0sRUFBQyxDQUFDLENBQUM7SUFDdkIsQ0FBQztDQUNKO0FBbkVELHdDQW1FQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7Um9sZX0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1pYW1cIjtcbmltcG9ydCB7SVNlY3JldH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1zZWNyZXRzbWFuYWdlclwiO1xuaW1wb3J0IHtDZm5DYW5hcnl9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3Mtc3ludGhldGljc1wiO1xuaW1wb3J0IHtTY2hlZHVsZX0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1ldmVudHNcIjtcbmltcG9ydCB7RHVyYXRpb259IGZyb20gXCJhd3MtY2RrLWxpYlwiO1xuXG5pbXBvcnQge0NhbmFyeVBhcmFtZXRlcnN9IGZyb20gXCIuL2NhbmFyeS1wYXJhbWV0ZXJzXCI7XG5pbXBvcnQge0RpZ2l0cmFmZmljQ2FuYXJ5fSBmcm9tIFwiLi9jYW5hcnlcIjtcbmltcG9ydCB7RGlnaXRyYWZmaWNTdGFja30gZnJvbSBcIi4uL3N0YWNrL3N0YWNrXCI7XG5cbmV4cG9ydCBjbGFzcyBEYXRhYmFzZUNhbmFyeSBleHRlbmRzIERpZ2l0cmFmZmljQ2FuYXJ5IHtcbiAgICBjb25zdHJ1Y3RvcihzdGFjazogRGlnaXRyYWZmaWNTdGFjayxcbiAgICAgICAgcm9sZTogUm9sZSxcbiAgICAgICAgc2VjcmV0OiBJU2VjcmV0LFxuICAgICAgICBwYXJhbXM6IENhbmFyeVBhcmFtZXRlcnMpIHtcbiAgICAgICAgY29uc3QgY2FuYXJ5TmFtZSA9IGAke3BhcmFtcy5uYW1lfS1kYmA7XG4gICAgICAgIGNvbnN0IGVudmlyb25tZW50VmFyaWFibGVzID0gc3RhY2suY3JlYXRlRGVmYXVsdExhbWJkYUVudmlyb25tZW50KGBTeW50aGV0aWNzLSR7Y2FuYXJ5TmFtZX1gKTtcblxuICAgICAgICAvLyB0aGUgaGFuZGxlciBjb2RlIGlzIGRlZmluZWQgYXQgdGhlIGFjdHVhbCBwcm9qZWN0IHVzaW5nIHRoaXNcbiAgICAgICAgc3VwZXIoXG4gICAgICAgICAgICBzdGFjaywgY2FuYXJ5TmFtZSwgcm9sZSxcbiAgICAgICAgICAgIHBhcmFtcywgZW52aXJvbm1lbnRWYXJpYWJsZXMsXG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5hcnRpZmFjdHNCdWNrZXQuZ3JhbnRXcml0ZSh0aGlzLnJvbGUpO1xuICAgICAgICBzZWNyZXQuZ3JhbnRSZWFkKHRoaXMucm9sZSk7XG5cbiAgICAgICAgLy8gbmVlZCB0byBvdmVycmlkZSB2cGMgYW5kIHNlY3VyaXR5IGdyb3VwLCBjYW4ndCBkbyB0aGlzIHdpdGggY2RrXG4gICAgICAgIGlmICh0aGlzLm5vZGUuZGVmYXVsdENoaWxkIGluc3RhbmNlb2YgQ2ZuQ2FuYXJ5KSB7XG4gICAgICAgICAgICBjb25zdCBzdWJuZXRJZHMgPSBzdGFjay52cGMucHJpdmF0ZVN1Ym5ldHMubWFwKHN1Ym5ldCA9PiBzdWJuZXQuc3VibmV0SWQpO1xuXG4gICAgICAgICAgICB0aGlzLm5vZGUuZGVmYXVsdENoaWxkLnZwY0NvbmZpZyA9IHtcbiAgICAgICAgICAgICAgICB2cGNJZDogc3RhY2sudnBjLnZwY0lkLFxuICAgICAgICAgICAgICAgIHNlY3VyaXR5R3JvdXBJZHM6IFtzdGFjay5sYW1iZGFEYlNnLnNlY3VyaXR5R3JvdXBJZF0sXG4gICAgICAgICAgICAgICAgc3VibmV0SWRzOiBzdWJuZXRJZHMsXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZShzdGFjazogRGlnaXRyYWZmaWNTdGFjayxcbiAgICAgICAgcm9sZTogUm9sZSxcbiAgICAgICAgcGFyYW1zOiBDYW5hcnlQYXJhbWV0ZXJzKTogRGF0YWJhc2VDYW5hcnkge1xuICAgICAgICByZXR1cm4gbmV3IERhdGFiYXNlQ2FuYXJ5KHN0YWNrLCByb2xlLCBzdGFjay5zZWNyZXQsXG4gICAgICAgICAgICB7Li4ue1xuICAgICAgICAgICAgICAgIHNlY3JldDogc3RhY2suY29uZmlndXJhdGlvbi5zZWNyZXRJZCxcbiAgICAgICAgICAgICAgICBzY2hlZHVsZTogU2NoZWR1bGUucmF0ZShEdXJhdGlvbi5ob3VycygxKSksXG4gICAgICAgICAgICAgICAgaGFuZGxlcjogYCR7cGFyYW1zLm5hbWV9LmhhbmRsZXJgLFxuICAgICAgICAgICAgfSwgLi4ucGFyYW1zfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAcGFyYW0gc3RhY2tcbiAgICAgKiBAcGFyYW0gcm9sZVxuICAgICAqIEBwYXJhbSBuYW1lIG5hbWUgb2YgdGhlIHR5cGVzY2lwdCBmaWxlIHdpdGhvdXQgLWRiIC1zdWZmaXguIE1heCBsZW4gaXMgMTAgY2hhciBpZiBAcGFyYW0gY2FuYXJ5TmFtZSBpcyBub3QgZ2l2ZW4uXG4gICAgICogQHBhcmFtIHBhcmFtc1xuICAgICAqIEBwYXJhbSBjYW5hcnlOYW1lIE9wdGlvbmFsIG5hbWUgZm9yIGNhbmFyeSBpZiBtdWx0aXBsZSBjYW5hcmllcyBpcyBtYWRlIGZyb20gc2FtZSAke25hbWV9LWRiLnRzIGNhbmFyeSBmaWxlLlxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVWMihcbiAgICAgICAgc3RhY2s6IERpZ2l0cmFmZmljU3RhY2ssXG4gICAgICAgIHJvbGU6IFJvbGUsXG4gICAgICAgIG5hbWU6IHN0cmluZyxcbiAgICAgICAgcGFyYW1zOiBQYXJ0aWFsPENhbmFyeVBhcmFtZXRlcnM+ID0ge30sXG4gICAgICAgIGNhbmFyeU5hbWU9bmFtZSxcbiAgICApOiBEYXRhYmFzZUNhbmFyeSB7XG4gICAgICAgIHJldHVybiBuZXcgRGF0YWJhc2VDYW5hcnkoc3RhY2ssIHJvbGUsIHN0YWNrLnNlY3JldCxcbiAgICAgICAgICAgIHsuLi57XG4gICAgICAgICAgICAgICAgc2VjcmV0OiBzdGFjay5jb25maWd1cmF0aW9uLnNlY3JldElkLFxuICAgICAgICAgICAgICAgIHNjaGVkdWxlOiBTY2hlZHVsZS5yYXRlKER1cmF0aW9uLmhvdXJzKDEpKSxcbiAgICAgICAgICAgICAgICBoYW5kbGVyOiBgJHtuYW1lfS1kYi5oYW5kbGVyYCxcbiAgICAgICAgICAgICAgICBuYW1lIDogY2FuYXJ5TmFtZSxcbiAgICAgICAgICAgICAgICBhbGFybToge1xuICAgICAgICAgICAgICAgICAgICBhbGFybU5hbWU6IChjYW5hcnlOYW1lID09PSBuYW1lID8gYCR7c3RhY2suY29uZmlndXJhdGlvbi5zaG9ydE5hbWV9LURCLUFsYXJtYCA6IGAke2NhbmFyeU5hbWV9LURCLUFsYXJtYCksXG4gICAgICAgICAgICAgICAgICAgIHRvcGljQXJuOiBzdGFjay5jb25maWd1cmF0aW9uLmFsYXJtVG9waWNBcm4sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sIC4uLnBhcmFtc30pO1xuICAgIH1cbn1cbiJdfQ==
@@ -0,0 +1,21 @@
1
+ declare abstract class DatabaseCheck<T> {
2
+ readonly name: string;
3
+ readonly sql: string;
4
+ failed: boolean;
5
+ protected constructor(name: string, sql: string);
6
+ abstract check(value: T): void;
7
+ }
8
+ declare class BaseResponse {
9
+ }
10
+ export declare class DatabaseChecker {
11
+ credentialsFunction: (() => Promise<void>);
12
+ checks: DatabaseCheck<BaseResponse>[];
13
+ private constructor();
14
+ static createForProxy(): DatabaseChecker;
15
+ static createForRds(): DatabaseChecker;
16
+ one(name: string, sql: string): this;
17
+ empty(name: string, sql: string): this;
18
+ notEmpty(name: string, sql: string): this;
19
+ expect(): Promise<string>;
20
+ }
21
+ export {};
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DatabaseChecker = void 0;
4
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
5
+ const database_1 = require("../../../database/database");
6
+ const proxy_holder_1 = require("../../runtime/secrets/proxy-holder");
7
+ const rds_holder_1 = require("../../runtime/secrets/rds-holder");
8
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
9
+ const synthetics = require('Synthetics');
10
+ class DatabaseCheck {
11
+ constructor(name, sql) {
12
+ this.name = name;
13
+ this.sql = sql;
14
+ this.failed = false;
15
+ }
16
+ }
17
+ class BaseResponse {
18
+ }
19
+ class CountResponse extends BaseResponse {
20
+ }
21
+ class CountDatabaseCheck extends DatabaseCheck {
22
+ constructor(name, sql, minCount, maxCount) {
23
+ super(name, sql);
24
+ if (minCount == null && maxCount == null) {
25
+ throw new Error('no max or min given!');
26
+ }
27
+ this.minCount = minCount;
28
+ this.maxCount = maxCount;
29
+ }
30
+ check(value) {
31
+ if (!value) {
32
+ this.failed = true;
33
+ throw new Error('no return value');
34
+ }
35
+ else {
36
+ if ('count' in value) {
37
+ if (this.minCount && value.count < this.minCount) {
38
+ this.failed = true;
39
+ throw new Error(`count was ${value.count}, minimum is ${this.minCount}`);
40
+ }
41
+ if (this.maxCount && value.count > this.maxCount) {
42
+ this.failed = true;
43
+ throw new Error(`count was ${value.count}, max is ${this.maxCount}`);
44
+ }
45
+ }
46
+ else {
47
+ this.failed = true;
48
+ console.info("received " + JSON.stringify(value));
49
+ throw new Error('no count available');
50
+ }
51
+ }
52
+ }
53
+ }
54
+ const stepConfig = {
55
+ 'continueOnStepFailure': true,
56
+ 'screenshotOnStepStart': false,
57
+ 'screenshotOnStepSuccess': false,
58
+ 'screenshotOnStepFailure': false,
59
+ };
60
+ class DatabaseChecker {
61
+ constructor(credentialsFunction) {
62
+ this.credentialsFunction = credentialsFunction;
63
+ this.checks = [];
64
+ synthetics.getConfiguration()
65
+ .disableRequestMetrics();
66
+ synthetics.getConfiguration()
67
+ .withFailedCanaryMetric(true);
68
+ }
69
+ static createForProxy() {
70
+ return new DatabaseChecker(() => new proxy_holder_1.ProxyHolder(process.env.SECRET_ID).setCredentials());
71
+ }
72
+ static createForRds() {
73
+ return new DatabaseChecker(() => new rds_holder_1.RdsHolder(process.env.SECRET_ID).setCredentials());
74
+ }
75
+ one(name, sql) {
76
+ this.checks.push(new CountDatabaseCheck(name, sql, 1, 1));
77
+ return this;
78
+ }
79
+ empty(name, sql) {
80
+ this.checks.push(new CountDatabaseCheck(name, sql, null, 0));
81
+ return this;
82
+ }
83
+ notEmpty(name, sql) {
84
+ this.checks.push(new CountDatabaseCheck(name, sql, 1, null));
85
+ return this;
86
+ }
87
+ async expect() {
88
+ if (!this.checks.length) {
89
+ throw new Error('No checks');
90
+ }
91
+ await this.credentialsFunction();
92
+ await (0, database_1.inDatabaseReadonly)(async (db) => {
93
+ for (const check of this.checks) {
94
+ console.info("canary checking sql " + check.sql);
95
+ const value = await db.oneOrNone(check.sql);
96
+ const checkFunction = () => {
97
+ check.check(value);
98
+ };
99
+ synthetics.executeStep(check.name, checkFunction, stepConfig);
100
+ }
101
+ });
102
+ if (this.checks.some(check => check.failed)) {
103
+ throw new Error('Failed');
104
+ }
105
+ return 'OK';
106
+ }
107
+ }
108
+ exports.DatabaseChecker = DatabaseChecker;
109
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YWJhc2UtY2hlY2tlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9hd3MvaW5mcmEvY2FuYXJpZXMvZGF0YWJhc2UtY2hlY2tlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw4REFBOEQ7QUFDOUQseURBQTBFO0FBQzFFLHFFQUErRDtBQUMvRCxpRUFBMkQ7QUFFM0QsOERBQThEO0FBQzlELE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQztBQUV6QyxNQUFlLGFBQWE7SUFLeEIsWUFBc0IsSUFBWSxFQUFFLEdBQVc7UUFDM0MsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUM7UUFDZixJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQztJQUN4QixDQUFDO0NBR0o7QUFFRCxNQUFNLFlBQVk7Q0FBRztBQUVyQixNQUFNLGFBQWMsU0FBUSxZQUFZO0NBRXZDO0FBRUQsTUFBTSxrQkFBbUIsU0FBUSxhQUE0QjtJQUl6RCxZQUFZLElBQVksRUFDcEIsR0FBVyxFQUNYLFFBQXFCLEVBQ3JCLFFBQXFCO1FBQ3JCLEtBQUssQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFFakIsSUFBSSxRQUFRLElBQUksSUFBSSxJQUFJLFFBQVEsSUFBSSxJQUFJLEVBQUU7WUFDdEMsTUFBTSxJQUFJLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1NBQzNDO1FBRUQsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7UUFDekIsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7SUFDN0IsQ0FBQztJQUVELEtBQUssQ0FBQyxLQUFvQjtRQUN0QixJQUFJLENBQUMsS0FBSyxFQUFFO1lBQ1IsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUM7WUFDbkIsTUFBTSxJQUFJLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1NBQ3RDO2FBQU07WUFDSCxJQUFJLE9BQU8sSUFBSSxLQUFLLEVBQUU7Z0JBQ2xCLElBQUksSUFBSSxDQUFDLFFBQVEsSUFBSSxLQUFLLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxRQUFRLEVBQUU7b0JBQzlDLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO29CQUNuQixNQUFNLElBQUksS0FBSyxDQUFDLGFBQWEsS0FBSyxDQUFDLEtBQUssZ0JBQWdCLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO2lCQUM1RTtnQkFDRCxJQUFJLElBQUksQ0FBQyxRQUFRLElBQUksS0FBSyxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsUUFBUSxFQUFFO29CQUM5QyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztvQkFDbkIsTUFBTSxJQUFJLEtBQUssQ0FBQyxhQUFhLEtBQUssQ0FBQyxLQUFLLFlBQVksSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7aUJBQ3hFO2FBQ0o7aUJBQU07Z0JBQ0gsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUM7Z0JBRW5CLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztnQkFFbEQsTUFBTSxJQUFJLEtBQUssQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO2FBQ3pDO1NBQ0o7SUFDTCxDQUFDO0NBQ0o7QUFFRCxNQUFNLFVBQVUsR0FBRztJQUNmLHVCQUF1QixFQUFFLElBQUk7SUFDN0IsdUJBQXVCLEVBQUUsS0FBSztJQUM5Qix5QkFBeUIsRUFBRSxLQUFLO0lBQ2hDLHlCQUF5QixFQUFFLEtBQUs7Q0FDbkMsQ0FBQztBQUVGLE1BQWEsZUFBZTtJQUl4QixZQUFvQixtQkFBMEM7UUFDMUQsSUFBSSxDQUFDLG1CQUFtQixHQUFHLG1CQUFtQixDQUFDO1FBQy9DLElBQUksQ0FBQyxNQUFNLEdBQUcsRUFBRSxDQUFDO1FBRWpCLFVBQVUsQ0FBQyxnQkFBZ0IsRUFBRTthQUN4QixxQkFBcUIsRUFBRSxDQUFDO1FBRTdCLFVBQVUsQ0FBQyxnQkFBZ0IsRUFBRTthQUN4QixzQkFBc0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN0QyxDQUFDO0lBRUQsTUFBTSxDQUFDLGNBQWM7UUFDakIsT0FBTyxJQUFJLGVBQWUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLDBCQUFXLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxTQUFtQixDQUFDLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQztJQUN4RyxDQUFDO0lBRUQsTUFBTSxDQUFDLFlBQVk7UUFDZixPQUFPLElBQUksZUFBZSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksc0JBQVMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQW1CLENBQUMsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDO0lBQ3RHLENBQUM7SUFFRCxHQUFHLENBQUMsSUFBWSxFQUFFLEdBQVc7UUFDekIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxrQkFBa0IsQ0FBQyxJQUFJLEVBQ3hDLEdBQUcsRUFDSCxDQUFDLEVBQ0QsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUVSLE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFFRCxLQUFLLENBQUMsSUFBWSxFQUFFLEdBQVc7UUFDM0IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxrQkFBa0IsQ0FBQyxJQUFJLEVBQ3hDLEdBQUcsRUFDSCxJQUFJLEVBQ0osQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUVSLE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFFRCxRQUFRLENBQUMsSUFBWSxFQUFFLEdBQVc7UUFDOUIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxrQkFBa0IsQ0FBQyxJQUFJLEVBQ3hDLEdBQUcsRUFDSCxDQUFDLEVBQ0QsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUVYLE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFFRCxLQUFLLENBQUMsTUFBTTtRQUNSLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRTtZQUNyQixNQUFNLElBQUksS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1NBQ2hDO1FBRUQsTUFBTSxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztRQUNqQyxNQUFNLElBQUEsNkJBQWtCLEVBQUMsS0FBSyxFQUFFLEVBQWMsRUFBRSxFQUFFO1lBQzlDLEtBQUssTUFBTSxLQUFLLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRTtnQkFDN0IsT0FBTyxDQUFDLElBQUksQ0FBQyxzQkFBc0IsR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBRWpELE1BQU0sS0FBSyxHQUFHLE1BQU0sRUFBRSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQzVDLE1BQU0sYUFBYSxHQUFHLEdBQUcsRUFBRTtvQkFDdkIsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDdkIsQ0FBQyxDQUFDO2dCQUVGLFVBQVUsQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLElBQUksRUFDN0IsYUFBYSxFQUNiLFVBQVUsQ0FBQyxDQUFDO2FBQ25CO1FBQ0wsQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxFQUFFO1lBQ3pDLE1BQU0sSUFBSSxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7U0FDN0I7UUFFRCxPQUFPLElBQUksQ0FBQztJQUNoQixDQUFDO0NBQ0o7QUE3RUQsMENBNkVDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby12YXItcmVxdWlyZXNcbmltcG9ydCB7RFREYXRhYmFzZSwgaW5EYXRhYmFzZVJlYWRvbmx5fSBmcm9tIFwiLi4vLi4vLi4vZGF0YWJhc2UvZGF0YWJhc2VcIjtcbmltcG9ydCB7UHJveHlIb2xkZXJ9IGZyb20gXCIuLi8uLi9ydW50aW1lL3NlY3JldHMvcHJveHktaG9sZGVyXCI7XG5pbXBvcnQge1Jkc0hvbGRlcn0gZnJvbSBcIi4uLy4uL3J1bnRpbWUvc2VjcmV0cy9yZHMtaG9sZGVyXCI7XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdmFyLXJlcXVpcmVzXG5jb25zdCBzeW50aGV0aWNzID0gcmVxdWlyZSgnU3ludGhldGljcycpO1xuXG5hYnN0cmFjdCBjbGFzcyBEYXRhYmFzZUNoZWNrPFQ+IHtcbiAgICByZWFkb25seSBuYW1lOiBzdHJpbmc7XG4gICAgcmVhZG9ubHkgc3FsOiBzdHJpbmc7XG4gICAgZmFpbGVkOiBib29sZWFuO1xuXG4gICAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKG5hbWU6IHN0cmluZywgc3FsOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgdGhpcy5zcWwgPSBzcWw7XG4gICAgICAgIHRoaXMuZmFpbGVkID0gZmFsc2U7XG4gICAgfVxuXG4gICAgYWJzdHJhY3QgY2hlY2sodmFsdWU6IFQpOiB2b2lkO1xufVxuXG5jbGFzcyBCYXNlUmVzcG9uc2Uge31cblxuY2xhc3MgQ291bnRSZXNwb25zZSBleHRlbmRzIEJhc2VSZXNwb25zZSB7XG4gICAgY291bnQ6IG51bWJlcjtcbn1cblxuY2xhc3MgQ291bnREYXRhYmFzZUNoZWNrIGV4dGVuZHMgRGF0YWJhc2VDaGVjazxDb3VudFJlc3BvbnNlPiB7XG4gICAgcmVhZG9ubHkgbWluQ291bnQ6IG51bWJlcnxudWxsO1xuICAgIHJlYWRvbmx5IG1heENvdW50OiBudW1iZXJ8bnVsbDtcblxuICAgIGNvbnN0cnVjdG9yKG5hbWU6IHN0cmluZyxcbiAgICAgICAgc3FsOiBzdHJpbmcsXG4gICAgICAgIG1pbkNvdW50OiBudW1iZXJ8bnVsbCxcbiAgICAgICAgbWF4Q291bnQ6IG51bWJlcnxudWxsKSB7XG4gICAgICAgIHN1cGVyKG5hbWUsIHNxbCk7XG5cbiAgICAgICAgaWYgKG1pbkNvdW50ID09IG51bGwgJiYgbWF4Q291bnQgPT0gbnVsbCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdubyBtYXggb3IgbWluIGdpdmVuIScpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5taW5Db3VudCA9IG1pbkNvdW50O1xuICAgICAgICB0aGlzLm1heENvdW50ID0gbWF4Q291bnQ7XG4gICAgfVxuXG4gICAgY2hlY2sodmFsdWU6IENvdW50UmVzcG9uc2UpIHtcbiAgICAgICAgaWYgKCF2YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5mYWlsZWQgPSB0cnVlO1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdubyByZXR1cm4gdmFsdWUnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICgnY291bnQnIGluIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubWluQ291bnQgJiYgdmFsdWUuY291bnQgPCB0aGlzLm1pbkNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZmFpbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBjb3VudCB3YXMgJHt2YWx1ZS5jb3VudH0sIG1pbmltdW0gaXMgJHt0aGlzLm1pbkNvdW50fWApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5tYXhDb3VudCAmJiB2YWx1ZS5jb3VudCA+IHRoaXMubWF4Q291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5mYWlsZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGNvdW50IHdhcyAke3ZhbHVlLmNvdW50fSwgbWF4IGlzICR7dGhpcy5tYXhDb3VudH1gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuZmFpbGVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcInJlY2VpdmVkIFwiICsgSlNPTi5zdHJpbmdpZnkodmFsdWUpKTtcblxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignbm8gY291bnQgYXZhaWxhYmxlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmNvbnN0IHN0ZXBDb25maWcgPSB7XG4gICAgJ2NvbnRpbnVlT25TdGVwRmFpbHVyZSc6IHRydWUsXG4gICAgJ3NjcmVlbnNob3RPblN0ZXBTdGFydCc6IGZhbHNlLFxuICAgICdzY3JlZW5zaG90T25TdGVwU3VjY2Vzcyc6IGZhbHNlLFxuICAgICdzY3JlZW5zaG90T25TdGVwRmFpbHVyZSc6IGZhbHNlLFxufTtcblxuZXhwb3J0IGNsYXNzIERhdGFiYXNlQ2hlY2tlciB7XG4gICAgY3JlZGVudGlhbHNGdW5jdGlvbjogKCgpID0+IFByb21pc2U8dm9pZD4pO1xuICAgIGNoZWNrczogRGF0YWJhc2VDaGVjazxCYXNlUmVzcG9uc2U+W107XG5cbiAgICBwcml2YXRlIGNvbnN0cnVjdG9yKGNyZWRlbnRpYWxzRnVuY3Rpb246ICgoKSA9PiBQcm9taXNlPHZvaWQ+KSkge1xuICAgICAgICB0aGlzLmNyZWRlbnRpYWxzRnVuY3Rpb24gPSBjcmVkZW50aWFsc0Z1bmN0aW9uO1xuICAgICAgICB0aGlzLmNoZWNrcyA9IFtdO1xuXG4gICAgICAgIHN5bnRoZXRpY3MuZ2V0Q29uZmlndXJhdGlvbigpXG4gICAgICAgICAgICAuZGlzYWJsZVJlcXVlc3RNZXRyaWNzKCk7XG5cbiAgICAgICAgc3ludGhldGljcy5nZXRDb25maWd1cmF0aW9uKClcbiAgICAgICAgICAgIC53aXRoRmFpbGVkQ2FuYXJ5TWV0cmljKHRydWUpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGVGb3JQcm94eSgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBEYXRhYmFzZUNoZWNrZXIoKCkgPT4gbmV3IFByb3h5SG9sZGVyKHByb2Nlc3MuZW52LlNFQ1JFVF9JRCBhcyBzdHJpbmcpLnNldENyZWRlbnRpYWxzKCkpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGVGb3JSZHMoKSB7XG4gICAgICAgIHJldHVybiBuZXcgRGF0YWJhc2VDaGVja2VyKCgpID0+IG5ldyBSZHNIb2xkZXIocHJvY2Vzcy5lbnYuU0VDUkVUX0lEIGFzIHN0cmluZykuc2V0Q3JlZGVudGlhbHMoKSk7XG4gICAgfVxuXG4gICAgb25lKG5hbWU6IHN0cmluZywgc3FsOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5jaGVja3MucHVzaChuZXcgQ291bnREYXRhYmFzZUNoZWNrKG5hbWUsXG4gICAgICAgICAgICBzcWwsXG4gICAgICAgICAgICAxLFxuICAgICAgICAgICAgMSkpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGVtcHR5KG5hbWU6IHN0cmluZywgc3FsOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5jaGVja3MucHVzaChuZXcgQ291bnREYXRhYmFzZUNoZWNrKG5hbWUsXG4gICAgICAgICAgICBzcWwsXG4gICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAgMCkpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIG5vdEVtcHR5KG5hbWU6IHN0cmluZywgc3FsOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5jaGVja3MucHVzaChuZXcgQ291bnREYXRhYmFzZUNoZWNrKG5hbWUsXG4gICAgICAgICAgICBzcWwsXG4gICAgICAgICAgICAxLFxuICAgICAgICAgICAgbnVsbCkpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGFzeW5jIGV4cGVjdCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmNoZWNrcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gY2hlY2tzJyk7XG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCB0aGlzLmNyZWRlbnRpYWxzRnVuY3Rpb24oKTtcbiAgICAgICAgYXdhaXQgaW5EYXRhYmFzZVJlYWRvbmx5KGFzeW5jIChkYjogRFREYXRhYmFzZSkgPT4ge1xuICAgICAgICAgICAgZm9yIChjb25zdCBjaGVjayBvZiB0aGlzLmNoZWNrcykge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuaW5mbyhcImNhbmFyeSBjaGVja2luZyBzcWwgXCIgKyBjaGVjay5zcWwpO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBhd2FpdCBkYi5vbmVPck5vbmUoY2hlY2suc3FsKTtcbiAgICAgICAgICAgICAgICBjb25zdCBjaGVja0Z1bmN0aW9uID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjaGVjay5jaGVjayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHN5bnRoZXRpY3MuZXhlY3V0ZVN0ZXAoY2hlY2submFtZSxcbiAgICAgICAgICAgICAgICAgICAgY2hlY2tGdW5jdGlvbixcbiAgICAgICAgICAgICAgICAgICAgc3RlcENvbmZpZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICh0aGlzLmNoZWNrcy5zb21lKGNoZWNrID0+IGNoZWNrLmZhaWxlZCkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignRmFpbGVkJyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gJ09LJztcbiAgICB9XG59XG4iXX0=
@@ -0,0 +1,19 @@
1
+ import { Construct } from "constructs";
2
+ import { CanaryParameters } from "./canary-parameters";
3
+ import { Role } from "aws-cdk-lib/aws-iam";
4
+ import { DigitrafficCanary } from "./canary";
5
+ import { ISecret } from "aws-cdk-lib/aws-secretsmanager";
6
+ import { DigitrafficStack } from "../stack/stack";
7
+ import { DigitrafficRestApi } from "../stack/rest_apis";
8
+ export declare const ENV_API_KEY = "apiKeyId";
9
+ export declare const ENV_HOSTNAME = "hostname";
10
+ export declare const ENV_SECRET = "secret";
11
+ export interface UrlCanaryParameters extends CanaryParameters {
12
+ readonly hostname: string;
13
+ readonly apiKeyId?: string;
14
+ }
15
+ export declare class UrlCanary extends DigitrafficCanary {
16
+ constructor(stack: Construct, role: Role, params: UrlCanaryParameters, secret?: ISecret);
17
+ static create(stack: DigitrafficStack, role: Role, publicApi: DigitrafficRestApi, params: Partial<UrlCanaryParameters>): UrlCanary;
18
+ static getApiKey(publicApi: DigitrafficRestApi): string | undefined;
19
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UrlCanary = exports.ENV_SECRET = exports.ENV_HOSTNAME = exports.ENV_API_KEY = void 0;
4
+ const canary_1 = require("./canary");
5
+ exports.ENV_API_KEY = "apiKeyId";
6
+ exports.ENV_HOSTNAME = "hostname";
7
+ exports.ENV_SECRET = "secret";
8
+ class UrlCanary extends canary_1.DigitrafficCanary {
9
+ constructor(stack, role, params, secret) {
10
+ const canaryName = `${params.name}-url`;
11
+ const environmentVariables = {};
12
+ environmentVariables[exports.ENV_HOSTNAME] = params.hostname;
13
+ if (params.secret) {
14
+ environmentVariables[exports.ENV_SECRET] = params.secret;
15
+ }
16
+ if (params.apiKeyId) {
17
+ environmentVariables[exports.ENV_API_KEY] = params.apiKeyId;
18
+ }
19
+ if (secret) {
20
+ secret.grantRead(role);
21
+ }
22
+ // the handler code is defined at the actual project using this
23
+ super(stack, canaryName, role, params, environmentVariables);
24
+ }
25
+ static create(stack, role, publicApi, params) {
26
+ return new UrlCanary(stack, role, { ...{
27
+ handler: `${params.name}.handler`,
28
+ hostname: publicApi.hostname(),
29
+ apiKeyId: this.getApiKey(publicApi),
30
+ }, ...params });
31
+ }
32
+ static getApiKey(publicApi) {
33
+ const apiKeys = publicApi.apiKeyIds;
34
+ if (apiKeys.length > 1) {
35
+ console.info("rest api has more than one api key");
36
+ }
37
+ if (apiKeys.length === 0) {
38
+ console.info("rest api has no api keys");
39
+ return undefined;
40
+ }
41
+ // always use first api key
42
+ return publicApi.apiKeyIds[0];
43
+ }
44
+ }
45
+ exports.UrlCanary = UrlCanary;
46
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXJsLWNhbmFyeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9hd3MvaW5mcmEvY2FuYXJpZXMvdXJsLWNhbmFyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFHQSxxQ0FBMkM7QUFNOUIsUUFBQSxXQUFXLEdBQUcsVUFBVSxDQUFDO0FBQ3pCLFFBQUEsWUFBWSxHQUFHLFVBQVUsQ0FBQztBQUMxQixRQUFBLFVBQVUsR0FBRyxRQUFRLENBQUM7QUFPbkMsTUFBYSxTQUFVLFNBQVEsMEJBQWlCO0lBQzVDLFlBQVksS0FBZ0IsRUFDeEIsSUFBVSxFQUNWLE1BQTJCLEVBQzNCLE1BQWdCO1FBQ2hCLE1BQU0sVUFBVSxHQUFHLEdBQUcsTUFBTSxDQUFDLElBQUksTUFBTSxDQUFDO1FBQ3hDLE1BQU0sb0JBQW9CLEdBQXNCLEVBQUUsQ0FBQztRQUNuRCxvQkFBb0IsQ0FBQyxvQkFBWSxDQUFDLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQztRQUVyRCxJQUFJLE1BQU0sQ0FBQyxNQUFNLEVBQUU7WUFDZixvQkFBb0IsQ0FBQyxrQkFBVSxDQUFDLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztTQUNwRDtRQUVELElBQUksTUFBTSxDQUFDLFFBQVEsRUFBRTtZQUNqQixvQkFBb0IsQ0FBQyxtQkFBVyxDQUFDLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQztTQUN2RDtRQUVELElBQUksTUFBTSxFQUFFO1lBQ1IsTUFBTSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUMxQjtRQUVELCtEQUErRDtRQUMvRCxLQUFLLENBQ0QsS0FBSyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLG9CQUFvQixDQUN4RCxDQUFDO0lBQ04sQ0FBQztJQUVELE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBdUIsRUFDakMsSUFBVSxFQUNWLFNBQTZCLEVBQzdCLE1BQW9DO1FBQ3BDLE9BQU8sSUFBSSxTQUFTLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxFQUFDLEdBQUc7Z0JBQ2xDLE9BQU8sRUFBRSxHQUFHLE1BQU0sQ0FBQyxJQUFJLFVBQVU7Z0JBQ2pDLFFBQVEsRUFBRSxTQUFTLENBQUMsUUFBUSxFQUFFO2dCQUM5QixRQUFRLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUM7YUFDdEMsRUFBRSxHQUFHLE1BQU0sRUFBd0IsQ0FBQyxDQUFDO0lBQzFDLENBQUM7SUFFRCxNQUFNLENBQUMsU0FBUyxDQUFDLFNBQTZCO1FBQzFDLE1BQU0sT0FBTyxHQUFHLFNBQVMsQ0FBQyxTQUFTLENBQUM7UUFFcEMsSUFBSSxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUNwQixPQUFPLENBQUMsSUFBSSxDQUFDLG9DQUFvQyxDQUFDLENBQUM7U0FDdEQ7UUFFRCxJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1lBQ3RCLE9BQU8sQ0FBQyxJQUFJLENBQUMsMEJBQTBCLENBQUMsQ0FBQztZQUN6QyxPQUFPLFNBQVMsQ0FBQztTQUNwQjtRQUVELDJCQUEyQjtRQUMzQixPQUFPLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbEMsQ0FBQztDQUNKO0FBckRELDhCQXFEQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7Q29uc3RydWN0fSBmcm9tIFwiY29uc3RydWN0c1wiO1xuaW1wb3J0IHtDYW5hcnlQYXJhbWV0ZXJzfSBmcm9tIFwiLi9jYW5hcnktcGFyYW1ldGVyc1wiO1xuaW1wb3J0IHtSb2xlfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWlhbVwiO1xuaW1wb3J0IHtEaWdpdHJhZmZpY0NhbmFyeX0gZnJvbSBcIi4vY2FuYXJ5XCI7XG5pbXBvcnQge0lTZWNyZXR9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3Mtc2VjcmV0c21hbmFnZXJcIjtcbmltcG9ydCB7RGlnaXRyYWZmaWNTdGFja30gZnJvbSBcIi4uL3N0YWNrL3N0YWNrXCI7XG5pbXBvcnQge0xhbWJkYUVudmlyb25tZW50fSBmcm9tIFwiLi4vc3RhY2svbGFtYmRhLWNvbmZpZ3NcIjtcbmltcG9ydCB7RGlnaXRyYWZmaWNSZXN0QXBpfSBmcm9tIFwiLi4vc3RhY2svcmVzdF9hcGlzXCI7XG5cbmV4cG9ydCBjb25zdCBFTlZfQVBJX0tFWSA9IFwiYXBpS2V5SWRcIjtcbmV4cG9ydCBjb25zdCBFTlZfSE9TVE5BTUUgPSBcImhvc3RuYW1lXCI7XG5leHBvcnQgY29uc3QgRU5WX1NFQ1JFVCA9IFwic2VjcmV0XCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgVXJsQ2FuYXJ5UGFyYW1ldGVycyBleHRlbmRzIENhbmFyeVBhcmFtZXRlcnMge1xuICAgIHJlYWRvbmx5IGhvc3RuYW1lOiBzdHJpbmc7XG4gICAgcmVhZG9ubHkgYXBpS2V5SWQ/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjbGFzcyBVcmxDYW5hcnkgZXh0ZW5kcyBEaWdpdHJhZmZpY0NhbmFyeSB7XG4gICAgY29uc3RydWN0b3Ioc3RhY2s6IENvbnN0cnVjdCxcbiAgICAgICAgcm9sZTogUm9sZSxcbiAgICAgICAgcGFyYW1zOiBVcmxDYW5hcnlQYXJhbWV0ZXJzLFxuICAgICAgICBzZWNyZXQ/OiBJU2VjcmV0KSB7XG4gICAgICAgIGNvbnN0IGNhbmFyeU5hbWUgPSBgJHtwYXJhbXMubmFtZX0tdXJsYDtcbiAgICAgICAgY29uc3QgZW52aXJvbm1lbnRWYXJpYWJsZXM6IExhbWJkYUVudmlyb25tZW50ID0ge307XG4gICAgICAgIGVudmlyb25tZW50VmFyaWFibGVzW0VOVl9IT1NUTkFNRV0gPSBwYXJhbXMuaG9zdG5hbWU7XG5cbiAgICAgICAgaWYgKHBhcmFtcy5zZWNyZXQpIHtcbiAgICAgICAgICAgIGVudmlyb25tZW50VmFyaWFibGVzW0VOVl9TRUNSRVRdID0gcGFyYW1zLnNlY3JldDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwYXJhbXMuYXBpS2V5SWQpIHtcbiAgICAgICAgICAgIGVudmlyb25tZW50VmFyaWFibGVzW0VOVl9BUElfS0VZXSA9IHBhcmFtcy5hcGlLZXlJZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzZWNyZXQpIHtcbiAgICAgICAgICAgIHNlY3JldC5ncmFudFJlYWQocm9sZSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB0aGUgaGFuZGxlciBjb2RlIGlzIGRlZmluZWQgYXQgdGhlIGFjdHVhbCBwcm9qZWN0IHVzaW5nIHRoaXNcbiAgICAgICAgc3VwZXIoXG4gICAgICAgICAgICBzdGFjaywgY2FuYXJ5TmFtZSwgcm9sZSwgcGFyYW1zLCBlbnZpcm9ubWVudFZhcmlhYmxlcyxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHN0YWNrOiBEaWdpdHJhZmZpY1N0YWNrLFxuICAgICAgICByb2xlOiBSb2xlLFxuICAgICAgICBwdWJsaWNBcGk6IERpZ2l0cmFmZmljUmVzdEFwaSxcbiAgICAgICAgcGFyYW1zOiBQYXJ0aWFsPFVybENhbmFyeVBhcmFtZXRlcnM+KTogVXJsQ2FuYXJ5IHtcbiAgICAgICAgcmV0dXJuIG5ldyBVcmxDYW5hcnkoc3RhY2ssIHJvbGUsIHsuLi57XG4gICAgICAgICAgICBoYW5kbGVyOiBgJHtwYXJhbXMubmFtZX0uaGFuZGxlcmAsXG4gICAgICAgICAgICBob3N0bmFtZTogcHVibGljQXBpLmhvc3RuYW1lKCksXG4gICAgICAgICAgICBhcGlLZXlJZDogdGhpcy5nZXRBcGlLZXkocHVibGljQXBpKSxcbiAgICAgICAgfSwgLi4ucGFyYW1zfSBhcyBVcmxDYW5hcnlQYXJhbWV0ZXJzKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgZ2V0QXBpS2V5KHB1YmxpY0FwaTogRGlnaXRyYWZmaWNSZXN0QXBpKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICAgICAgY29uc3QgYXBpS2V5cyA9IHB1YmxpY0FwaS5hcGlLZXlJZHM7XG5cbiAgICAgICAgaWYgKGFwaUtleXMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgY29uc29sZS5pbmZvKFwicmVzdCBhcGkgaGFzIG1vcmUgdGhhbiBvbmUgYXBpIGtleVwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChhcGlLZXlzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgY29uc29sZS5pbmZvKFwicmVzdCBhcGkgaGFzIG5vIGFwaSBrZXlzXCIpO1xuICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGFsd2F5cyB1c2UgZmlyc3QgYXBpIGtleVxuICAgICAgICByZXR1cm4gcHVibGljQXBpLmFwaUtleUlkc1swXTtcbiAgICB9XG59XG4iXX0=
@@ -0,0 +1,46 @@
1
+ /// <reference types="node" />
2
+ import { IncomingMessage } from "http";
3
+ import { MediaType } from "../../types/mediatypes";
4
+ import { FeatureCollection } from "geojson";
5
+ export declare const API_KEY_HEADER = "x-api-key";
6
+ declare type CheckerFunction = (Res: IncomingMessage) => void;
7
+ declare type JsonCheckerFunction<T> = (json: T, body: string, message: IncomingMessage) => void;
8
+ export declare class UrlChecker {
9
+ private readonly requestOptions;
10
+ constructor(hostname: string, apiKey?: string);
11
+ static create(hostname: string, apiKeyId: string): Promise<UrlChecker>;
12
+ static createV2(): Promise<UrlChecker>;
13
+ expectStatus<T>(statusCode: number, url: string, callback: JsonCheckerFunction<T>): Promise<void>;
14
+ expect200<T>(url: string, ...callbacks: JsonCheckerFunction<T>[]): Promise<void>;
15
+ expect404(url: string): Promise<void>;
16
+ expect400(url: string): Promise<void>;
17
+ expect403WithoutApiKey(url: string, mediaType?: MediaType): Promise<void>;
18
+ done(): string;
19
+ }
20
+ export declare class ResponseChecker {
21
+ private readonly contentType;
22
+ private checkCors;
23
+ constructor(contentType: string);
24
+ static forJson(): ResponseChecker;
25
+ static forCSV(): ResponseChecker;
26
+ static forGeojson(): ResponseChecker;
27
+ static forJpeg(): ResponseChecker;
28
+ check(): CheckerFunction;
29
+ checkJson<T>(fn: (json: T, body: string, res: IncomingMessage) => void): CheckerFunction;
30
+ responseChecker(fn: (body: string, res: IncomingMessage) => void): CheckerFunction;
31
+ }
32
+ export declare class ContentChecker {
33
+ static checkJson<T>(fn: (json: T, body: string, res: IncomingMessage) => void): CheckerFunction;
34
+ static checkResponse(fn: (body: string, res: IncomingMessage) => void): CheckerFunction;
35
+ }
36
+ export declare class ContentTypeChecker {
37
+ static checkContentType(contentType: MediaType): (res: IncomingMessage) => void;
38
+ }
39
+ export declare class GeoJsonChecker {
40
+ static validFeatureCollection(fn?: (json: FeatureCollection) => void): CheckerFunction;
41
+ }
42
+ export declare class HeaderChecker {
43
+ static checkHeaderExists(headerName: string): CheckerFunction;
44
+ static checkHeaderMissing(headerName: string): CheckerFunction;
45
+ }
46
+ export {};