@digitraffic/common 2026.3.17-1 → 2026.3.26-1-beta

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 (238) hide show
  1. package/README.md +18 -1
  2. package/dist/__test__/asserter.d.ts +13 -0
  3. package/dist/__test__/asserter.js +39 -0
  4. package/dist/__test__/db-testutils.d.ts +3 -0
  5. package/dist/__test__/db-testutils.js +38 -0
  6. package/dist/__test__/dependencies.test.d.ts +1 -0
  7. package/dist/__test__/dependencies.test.js +21 -0
  8. package/dist/__test__/imports.test.d.ts +1 -0
  9. package/dist/__test__/imports.test.js +318 -0
  10. package/dist/__test__/infra/acl-builder.test.d.ts +1 -0
  11. package/dist/__test__/infra/acl-builder.test.js +72 -0
  12. package/dist/__test__/infra/api/handler-factory.test.d.ts +1 -0
  13. package/dist/__test__/infra/api/handler-factory.test.js +42 -0
  14. package/dist/__test__/infra/api/integration.test.d.ts +1 -0
  15. package/dist/__test__/infra/api/integration.test.js +162 -0
  16. package/dist/__test__/infra/api/response.test.d.ts +1 -0
  17. package/dist/__test__/infra/api/response.test.js +77 -0
  18. package/dist/__test__/infra/api/static-integration.test.d.ts +1 -0
  19. package/dist/__test__/infra/api/static-integration.test.js +35 -0
  20. package/dist/__test__/infra/documentation.test.d.ts +1 -0
  21. package/dist/__test__/infra/documentation.test.js +38 -0
  22. package/dist/__test__/infra/scheduler.test.d.ts +1 -0
  23. package/dist/__test__/infra/scheduler.test.js +23 -0
  24. package/dist/__test__/infra/security-rule.test.d.ts +1 -0
  25. package/dist/__test__/infra/security-rule.test.js +21 -0
  26. package/dist/__test__/infra/stack/rest-apis.test.d.ts +1 -0
  27. package/dist/__test__/infra/stack/rest-apis.test.js +47 -0
  28. package/dist/__test__/marine/id_utils.test.d.ts +1 -0
  29. package/dist/__test__/marine/id_utils.test.js +45 -0
  30. package/dist/__test__/mock-ky.d.ts +2 -0
  31. package/dist/__test__/mock-ky.js +15 -0
  32. package/dist/__test__/promise/promise.test.d.ts +1 -0
  33. package/dist/__test__/promise/promise.test.js +126 -0
  34. package/dist/__test__/runtime/dt-logger.test.d.ts +1 -0
  35. package/dist/__test__/runtime/dt-logger.test.js +193 -0
  36. package/dist/__test__/secrets/secret-holder.test.d.ts +1 -0
  37. package/dist/__test__/secrets/secret-holder.test.js +96 -0
  38. package/dist/__test__/secrets/secret.test.d.ts +1 -0
  39. package/dist/__test__/secrets/secret.test.js +57 -0
  40. package/dist/__test__/stack/dt-function.test.d.ts +1 -0
  41. package/dist/__test__/stack/dt-function.test.js +340 -0
  42. package/dist/__test__/stack/rest-apis.test.d.ts +1 -0
  43. package/dist/__test__/stack/rest-apis.test.js +45 -0
  44. package/dist/__test__/test/mock-ky.test.d.ts +1 -0
  45. package/dist/__test__/test/mock-ky.test.js +46 -0
  46. package/dist/__test__/testutils.d.ts +12 -0
  47. package/dist/__test__/testutils.js +32 -0
  48. package/dist/__test__/types/lambda-proxy-types.test.d.ts +8 -0
  49. package/dist/__test__/types/lambda-proxy-types.test.js +155 -0
  50. package/dist/__test__/types/lambda-response-builder.test.d.ts +1 -0
  51. package/dist/__test__/types/lambda-response-builder.test.js +81 -0
  52. package/dist/__test__/types/lambda-response.test.d.ts +9 -0
  53. package/dist/__test__/types/lambda-response.test.js +73 -0
  54. package/dist/__test__/utils/base64.test.d.ts +1 -0
  55. package/dist/__test__/utils/base64.test.js +38 -0
  56. package/dist/__test__/utils/date-utils.test.d.ts +1 -0
  57. package/dist/__test__/utils/date-utils.test.js +32 -0
  58. package/dist/__test__/utils/geometry.test.d.ts +1 -0
  59. package/dist/__test__/utils/geometry.test.js +25 -0
  60. package/dist/__test__/utils/lambda-proxy-event.test.d.ts +1 -0
  61. package/dist/__test__/utils/lambda-proxy-event.test.js +45 -0
  62. package/dist/__test__/utils/logging.test.d.ts +1 -0
  63. package/dist/__test__/utils/logging.test.js +75 -0
  64. package/dist/__test__/utils/stop-watch.test.d.ts +1 -0
  65. package/dist/__test__/utils/stop-watch.test.js +118 -0
  66. package/dist/__test__/utils/utils.test.d.ts +1 -0
  67. package/dist/__test__/utils/utils.test.js +48 -0
  68. package/dist/aws/infra/acl-builder.d.ts +53 -0
  69. package/dist/aws/infra/acl-builder.js +407 -0
  70. package/dist/aws/infra/api/handler-factory.d.ts +22 -0
  71. package/dist/aws/infra/api/handler-factory.js +68 -0
  72. package/dist/aws/infra/api/integration.d.ts +49 -0
  73. package/dist/aws/infra/api/integration.js +162 -0
  74. package/dist/aws/infra/api/response.d.ts +62 -0
  75. package/dist/aws/infra/api/response.js +132 -0
  76. package/dist/aws/infra/api/responses.d.ts +60 -0
  77. package/dist/aws/infra/api/responses.js +90 -0
  78. package/dist/aws/infra/api/static-integration.d.ts +16 -0
  79. package/dist/aws/infra/api/static-integration.js +76 -0
  80. package/dist/aws/infra/bucket-policy.d.ts +38 -0
  81. package/dist/aws/infra/bucket-policy.js +30 -0
  82. package/dist/aws/infra/canaries/canary-alarm.d.ts +6 -0
  83. package/dist/aws/infra/canaries/canary-alarm.js +20 -0
  84. package/dist/aws/infra/canaries/canary-keys.d.ts +3 -0
  85. package/dist/aws/infra/canaries/canary-keys.js +4 -0
  86. package/dist/aws/infra/canaries/canary-parameters.d.ts +19 -0
  87. package/dist/aws/infra/canaries/canary-parameters.js +2 -0
  88. package/dist/aws/infra/canaries/canary-role.d.ts +14 -0
  89. package/dist/aws/infra/canaries/canary-role.js +51 -0
  90. package/dist/aws/infra/canaries/canary.d.ts +8 -0
  91. package/dist/aws/infra/canaries/canary.js +26 -0
  92. package/dist/aws/infra/canaries/database-canary.d.ts +17 -0
  93. package/dist/aws/infra/canaries/database-canary.js +65 -0
  94. package/dist/aws/infra/canaries/database-checker.d.ts +33 -0
  95. package/dist/aws/infra/canaries/database-checker.js +119 -0
  96. package/dist/aws/infra/canaries/url-canary.d.ts +16 -0
  97. package/dist/aws/infra/canaries/url-canary.js +55 -0
  98. package/dist/aws/infra/canaries/url-checker.d.ts +45 -0
  99. package/dist/aws/infra/canaries/url-checker.js +256 -0
  100. package/dist/aws/infra/documentation.d.ts +56 -0
  101. package/dist/aws/infra/documentation.js +90 -0
  102. package/dist/aws/infra/import-util.d.ts +17 -0
  103. package/dist/aws/infra/import-util.js +41 -0
  104. package/dist/aws/infra/scheduler.d.ts +12 -0
  105. package/dist/aws/infra/scheduler.js +27 -0
  106. package/dist/aws/infra/security-rule.d.ts +12 -0
  107. package/dist/aws/infra/security-rule.js +35 -0
  108. package/dist/aws/infra/sqs-integration.d.ts +4 -0
  109. package/dist/aws/infra/sqs-integration.js +85 -0
  110. package/dist/aws/infra/sqs-queue.d.ts +19 -0
  111. package/dist/aws/infra/sqs-queue.js +145 -0
  112. package/dist/aws/infra/stack/dt-function-alarms.d.ts +29 -0
  113. package/dist/aws/infra/stack/dt-function-alarms.js +54 -0
  114. package/dist/aws/infra/stack/dt-function.d.ts +124 -0
  115. package/dist/aws/infra/stack/dt-function.js +315 -0
  116. package/dist/aws/infra/stack/lambda-configs.d.ts +44 -0
  117. package/dist/aws/infra/stack/lambda-configs.js +71 -0
  118. package/dist/aws/infra/stack/lambda-log-group.d.ts +15 -0
  119. package/dist/aws/infra/stack/lambda-log-group.js +24 -0
  120. package/dist/aws/infra/stack/monitoredfunction.d.ts +85 -0
  121. package/dist/aws/infra/stack/monitoredfunction.js +147 -0
  122. package/dist/aws/infra/stack/parameters.d.ts +40 -0
  123. package/dist/aws/infra/stack/parameters.js +50 -0
  124. package/dist/aws/infra/stack/rest-api.d.ts +74 -0
  125. package/dist/aws/infra/stack/rest-api.js +235 -0
  126. package/dist/aws/infra/stack/stack-checking-aspect.d.ts +20 -0
  127. package/dist/aws/infra/stack/stack-checking-aspect.js +183 -0
  128. package/dist/aws/infra/stack/stack.d.ts +56 -0
  129. package/dist/aws/infra/stack/stack.js +71 -0
  130. package/dist/aws/infra/stack/subscription.d.ts +17 -0
  131. package/dist/aws/infra/stack/subscription.js +37 -0
  132. package/dist/aws/infra/stacks/db-dns-stack.d.ts +13 -0
  133. package/dist/aws/infra/stacks/db-dns-stack.js +60 -0
  134. package/dist/aws/infra/stacks/db-proxy-stack.d.ts +24 -0
  135. package/dist/aws/infra/stacks/db-proxy-stack.js +74 -0
  136. package/dist/aws/infra/stacks/db-stack.d.ts +65 -0
  137. package/dist/aws/infra/stacks/db-stack.js +189 -0
  138. package/dist/aws/infra/stacks/intra-stack-configuration.d.ts +5 -0
  139. package/dist/aws/infra/stacks/intra-stack-configuration.js +2 -0
  140. package/dist/aws/infra/stacks/network-stack.d.ts +14 -0
  141. package/dist/aws/infra/stacks/network-stack.js +45 -0
  142. package/dist/aws/infra/usage-plans.d.ts +16 -0
  143. package/dist/aws/infra/usage-plans.js +38 -0
  144. package/dist/aws/runtime/apikey.d.ts +2 -0
  145. package/dist/aws/runtime/apikey.js +13 -0
  146. package/dist/aws/runtime/digitraffic-integration-response.d.ts +8 -0
  147. package/dist/aws/runtime/digitraffic-integration-response.js +25 -0
  148. package/dist/aws/runtime/dt-logger-default.d.ts +9 -0
  149. package/dist/aws/runtime/dt-logger-default.js +6 -0
  150. package/dist/aws/runtime/dt-logger.d.ts +117 -0
  151. package/dist/aws/runtime/dt-logger.js +159 -0
  152. package/dist/aws/runtime/environment.d.ts +5 -0
  153. package/dist/aws/runtime/environment.js +7 -0
  154. package/dist/aws/runtime/s3.d.ts +3 -0
  155. package/dist/aws/runtime/s3.js +21 -0
  156. package/dist/aws/runtime/secrets/dbsecret.d.ts +16 -0
  157. package/dist/aws/runtime/secrets/dbsecret.js +26 -0
  158. package/dist/aws/runtime/secrets/proxy-holder.d.ts +9 -0
  159. package/dist/aws/runtime/secrets/proxy-holder.js +25 -0
  160. package/dist/aws/runtime/secrets/rds-holder.d.ts +9 -0
  161. package/dist/aws/runtime/secrets/rds-holder.js +25 -0
  162. package/dist/aws/runtime/secrets/secret-holder.d.ts +30 -0
  163. package/dist/aws/runtime/secrets/secret-holder.js +81 -0
  164. package/dist/aws/runtime/secrets/secret.d.ts +8 -0
  165. package/dist/aws/runtime/secrets/secret.js +61 -0
  166. package/dist/aws/types/errors.d.ts +8 -0
  167. package/dist/aws/types/errors.js +13 -0
  168. package/dist/aws/types/lambda-proxy-types.d.ts +59 -0
  169. package/dist/aws/types/lambda-proxy-types.js +210 -0
  170. package/dist/aws/types/lambda-response.d.ts +89 -0
  171. package/dist/aws/types/lambda-response.js +204 -0
  172. package/dist/aws/types/mediatypes.d.ts +11 -0
  173. package/dist/aws/types/mediatypes.js +14 -0
  174. package/dist/aws/types/model-with-reference.d.ts +7 -0
  175. package/dist/aws/types/model-with-reference.js +2 -0
  176. package/dist/aws/types/tags.d.ts +2 -0
  177. package/dist/aws/types/tags.js +4 -0
  178. package/dist/database/database.d.ts +27 -0
  179. package/dist/database/database.js +95 -0
  180. package/dist/database/last-updated.d.ts +15 -0
  181. package/dist/database/last-updated.js +46 -0
  182. package/dist/database/models.d.ts +6 -0
  183. package/dist/database/models.js +2 -0
  184. package/dist/index.d.ts +2 -0
  185. package/dist/index.js +2 -0
  186. package/dist/marine/id_utils.d.ts +3 -0
  187. package/dist/marine/id_utils.js +36 -0
  188. package/dist/marine/rtz.d.ts +48 -0
  189. package/dist/marine/rtz.js +2 -0
  190. package/dist/types/async-timeout-error.d.ts +3 -0
  191. package/dist/types/async-timeout-error.js +6 -0
  192. package/dist/types/either.d.ts +9 -0
  193. package/dist/types/either.js +2 -0
  194. package/dist/types/geojson.d.ts +47 -0
  195. package/dist/types/geojson.js +51 -0
  196. package/dist/types/http-error.d.ts +4 -0
  197. package/dist/types/http-error.js +8 -0
  198. package/dist/types/input-error.d.ts +2 -0
  199. package/dist/types/input-error.js +3 -0
  200. package/dist/types/language.d.ts +5 -0
  201. package/dist/types/language.js +7 -0
  202. package/dist/types/nullable.d.ts +24 -0
  203. package/dist/types/nullable.js +2 -0
  204. package/dist/types/openapi-schema.d.ts +932 -0
  205. package/dist/types/openapi-schema.js +151 -0
  206. package/dist/types/traffictype.d.ts +11 -0
  207. package/dist/types/traffictype.js +13 -0
  208. package/dist/types/urn.d.ts +1 -0
  209. package/dist/types/urn.js +2 -0
  210. package/dist/types/util-types.d.ts +11 -0
  211. package/dist/types/util-types.js +2 -0
  212. package/dist/types/validator.d.ts +4 -0
  213. package/dist/types/validator.js +9 -0
  214. package/dist/utils/api-model.d.ts +51 -0
  215. package/dist/utils/api-model.js +118 -0
  216. package/dist/utils/base64.d.ts +34 -0
  217. package/dist/utils/base64.js +53 -0
  218. package/dist/utils/date-utils.d.ts +27 -0
  219. package/dist/utils/date-utils.js +45 -0
  220. package/dist/utils/geojson-types.d.ts +14 -0
  221. package/dist/utils/geojson-types.js +15 -0
  222. package/dist/utils/geometry.d.ts +44 -0
  223. package/dist/utils/geometry.js +154 -0
  224. package/dist/utils/lambda-proxy-event.d.ts +9 -0
  225. package/dist/utils/lambda-proxy-event.js +31 -0
  226. package/dist/utils/logging.d.ts +40 -0
  227. package/dist/utils/logging.js +88 -0
  228. package/dist/utils/retry.d.ts +33 -0
  229. package/dist/utils/retry.js +135 -0
  230. package/dist/utils/slack.d.ts +5 -0
  231. package/dist/utils/slack.js +24 -0
  232. package/dist/utils/stop-watch.d.ts +46 -0
  233. package/dist/utils/stop-watch.js +114 -0
  234. package/dist/utils/utils.d.ts +95 -0
  235. package/dist/utils/utils.js +178 -0
  236. package/dist/utils/zod-utils.d.ts +27 -0
  237. package/dist/utils/zod-utils.js +57 -0
  238. package/package.json +30 -28
@@ -0,0 +1,20 @@
1
+ import { Alarm, ComparisonOperator } from "aws-cdk-lib/aws-cloudwatch";
2
+ import { SnsAction } from "aws-cdk-lib/aws-cloudwatch-actions";
3
+ import { Topic } from "aws-cdk-lib/aws-sns";
4
+ export class CanaryAlarm {
5
+ constructor(stack, canary, params) {
6
+ const alarmName = params.alarm?.alarmName ?? `${params.name}-alarm`;
7
+ const alarm = new Alarm(stack, alarmName, {
8
+ alarmName,
9
+ alarmDescription: params.alarm?.description ?? "",
10
+ metric: canary.metricSuccessPercent(),
11
+ evaluationPeriods: params.alarm?.evalutionPeriods ?? 1,
12
+ threshold: params.alarm?.threshold ?? 100,
13
+ comparisonOperator: ComparisonOperator.LESS_THAN_THRESHOLD,
14
+ });
15
+ if (params.alarm?.topicArn) {
16
+ alarm.addAlarmAction(new SnsAction(Topic.fromTopicArn(stack, `${alarmName}-action`, params.alarm.topicArn)));
17
+ }
18
+ }
19
+ }
20
+ //# sourceMappingURL=canary-alarm.js.map
@@ -0,0 +1,3 @@
1
+ export declare const ENV_API_KEY = "apiKeyId";
2
+ export declare const ENV_HOSTNAME = "hostname";
3
+ export declare const ENV_SECRET = "secret";
@@ -0,0 +1,4 @@
1
+ export const ENV_API_KEY = "apiKeyId";
2
+ export const ENV_HOSTNAME = "hostname";
3
+ export const ENV_SECRET = "secret";
4
+ //# sourceMappingURL=canary-keys.js.map
@@ -0,0 +1,19 @@
1
+ import type { Runtime, Schedule } from "aws-cdk-lib/aws-synthetics";
2
+ /** Optional env parameters for canary */
3
+ type CanaryEnv = Record<string, string>;
4
+ export interface 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
+ readonly runtime?: Runtime;
18
+ }
19
+ export {};
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=canary-parameters.js.map
@@ -0,0 +1,14 @@
1
+ import { Role } from "aws-cdk-lib/aws-iam";
2
+ import type { Construct } from "constructs";
3
+ export declare class DigitrafficCanaryRole extends Role {
4
+ constructor(stack: Construct, canaryName: string);
5
+ /**
6
+ * Provides permissions to access resources within a VPC.
7
+ */
8
+ withDatabaseAccess(): this;
9
+ /**
10
+ * Same as withDatabaseAccess() - renamed to avoid confusion if used with UrlCanary.
11
+ * A UrlCanary needs these permissions to e.g. access a private API Gateway endpoint in a VPC.
12
+ */
13
+ withVpcAccess(): this;
14
+ }
@@ -0,0 +1,51 @@
1
+ import { ManagedPolicy, PolicyStatement, Role, ServicePrincipal, } from "aws-cdk-lib/aws-iam";
2
+ const BASE_POLICY_STATEMENT_PROPS = {
3
+ actions: [
4
+ "logs:CreateLogStream",
5
+ "logs:PutLogEvents",
6
+ "logs:CreateLogGroup",
7
+ "logs:DescribeLogGroups",
8
+ "logs:DescribeLogStreams",
9
+ ],
10
+ resources: ["*"],
11
+ };
12
+ const CLOUDWATCH_STATEMENT_PROPS = {
13
+ actions: ["cloudwatch:PutMetricData"],
14
+ resources: ["*"],
15
+ conditions: {
16
+ StringEquals: {
17
+ "cloudwatch:namespace": "CloudWatchSynthetics",
18
+ },
19
+ },
20
+ };
21
+ export class DigitrafficCanaryRole extends Role {
22
+ constructor(stack, canaryName) {
23
+ super(stack, `canary-role-${canaryName}`, {
24
+ assumedBy: new ServicePrincipal("lambda.amazonaws.com"),
25
+ managedPolicies: [
26
+ ManagedPolicy.fromAwsManagedPolicyName("CloudWatchSyntheticsFullAccess"),
27
+ ],
28
+ });
29
+ this.addToPolicy(new PolicyStatement(BASE_POLICY_STATEMENT_PROPS));
30
+ this.addToPolicy(new PolicyStatement(CLOUDWATCH_STATEMENT_PROPS));
31
+ }
32
+ /**
33
+ * Provides permissions to access resources within a VPC.
34
+ */
35
+ withDatabaseAccess() {
36
+ // Won't work :(
37
+ // this.addToPolicy(new PolicyStatement(DB_STATEMENT_PROPS));
38
+ // Works
39
+ this.addManagedPolicy(ManagedPolicy.fromAwsManagedPolicyName("service-role/AWSLambdaVPCAccessExecutionRole"));
40
+ return this;
41
+ }
42
+ /**
43
+ * Same as withDatabaseAccess() - renamed to avoid confusion if used with UrlCanary.
44
+ * A UrlCanary needs these permissions to e.g. access a private API Gateway endpoint in a VPC.
45
+ */
46
+ withVpcAccess() {
47
+ this.addManagedPolicy(ManagedPolicy.fromAwsManagedPolicyName("service-role/AWSLambdaVPCAccessExecutionRole"));
48
+ return this;
49
+ }
50
+ }
51
+ //# sourceMappingURL=canary-role.js.map
@@ -0,0 +1,8 @@
1
+ import type { Role } from "aws-cdk-lib/aws-iam";
2
+ import { Canary } from "aws-cdk-lib/aws-synthetics";
3
+ import type { Construct } from "constructs";
4
+ import type { LambdaEnvironment } from "../stack/lambda-configs.js";
5
+ import type { CanaryParameters } from "./canary-parameters.js";
6
+ export declare class DigitrafficCanary extends Canary {
7
+ constructor(scope: Construct, canaryName: string, role: Role, params: CanaryParameters, environmentVariables: LambdaEnvironment);
8
+ }
@@ -0,0 +1,26 @@
1
+ import { Duration } from "aws-cdk-lib";
2
+ import { AssetCode, Canary, Runtime, Schedule, Test, } from "aws-cdk-lib/aws-synthetics";
3
+ import { CanaryAlarm } from "./canary-alarm.js";
4
+ export class DigitrafficCanary extends Canary {
5
+ constructor(scope, canaryName, role, params, environmentVariables) {
6
+ super(scope, canaryName, {
7
+ runtime: params.runtime ?? Runtime.SYNTHETICS_NODEJS_PUPPETEER_13_0,
8
+ role,
9
+ test: Test.custom({
10
+ code: new AssetCode("dist", {
11
+ exclude: ["lambda", "out", "canaries"],
12
+ }),
13
+ handler: params.handler,
14
+ }),
15
+ environmentVariables: {
16
+ ...environmentVariables,
17
+ ...params.canaryEnv,
18
+ },
19
+ canaryName,
20
+ schedule: params.schedule ?? Schedule.rate(Duration.minutes(15)),
21
+ });
22
+ this.artifactsBucket.grantWrite(role);
23
+ new CanaryAlarm(scope, this, params);
24
+ }
25
+ }
26
+ //# sourceMappingURL=canary.js.map
@@ -0,0 +1,17 @@
1
+ import type { Role } from "aws-cdk-lib/aws-iam";
2
+ import type { ISecret } from "aws-cdk-lib/aws-secretsmanager";
3
+ import type { DigitrafficStack } from "../stack/stack.js";
4
+ import { DigitrafficCanary } from "./canary.js";
5
+ import type { CanaryParameters } from "./canary-parameters.js";
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
+ * @param stack
11
+ * @param role
12
+ * @param name name of the typescipt file without -db -suffix. Max len is 10 char if @param canaryName is not given.
13
+ * @param params
14
+ * @param canaryName Optional name for canary if multiple canaries is made from same ${name}-db.ts canary file.
15
+ */
16
+ static createV2(stack: DigitrafficStack, role: Role, name: string, params?: Partial<CanaryParameters>, canaryName?: string): DatabaseCanary;
17
+ }
@@ -0,0 +1,65 @@
1
+ import { Duration } from "aws-cdk-lib";
2
+ import { Schedule } from "aws-cdk-lib/aws-events";
3
+ import { CfnCanary } from "aws-cdk-lib/aws-synthetics";
4
+ import { DigitrafficCanary } from "./canary.js";
5
+ export class DatabaseCanary extends DigitrafficCanary {
6
+ constructor(stack, role, secret, params) {
7
+ const canaryName = `${params.name}-db`;
8
+ const environmentVariables = stack.createDefaultLambdaEnvironment(`Synthetics-${canaryName}`);
9
+ // the handler code is defined at the actual project using this
10
+ super(stack, canaryName, role, params, environmentVariables);
11
+ this.artifactsBucket.grantWrite(this.role);
12
+ secret.grantRead(this.role);
13
+ // need to override vpc and security group, can't do this with cdk
14
+ if (this.node.defaultChild instanceof CfnCanary) {
15
+ const subnetIds = stack.vpc === undefined
16
+ ? []
17
+ : stack.vpc.privateSubnets.map((subnet) => subnet.subnetId);
18
+ const securityGroupIds = stack.lambdaDbSg === undefined
19
+ ? []
20
+ : [stack.lambdaDbSg.securityGroupId];
21
+ this.node.defaultChild.vpcConfig = {
22
+ vpcId: stack.vpc?.vpcId,
23
+ securityGroupIds,
24
+ subnetIds,
25
+ };
26
+ }
27
+ }
28
+ static create(stack, role, params) {
29
+ const secret = stack.getSecret();
30
+ return new DatabaseCanary(stack, role, secret, {
31
+ ...{
32
+ secret: stack.configuration.secretId,
33
+ schedule: Schedule.rate(Duration.hours(1)),
34
+ handler: `${params.name}.handler`,
35
+ },
36
+ ...params,
37
+ });
38
+ }
39
+ /**
40
+ * @param stack
41
+ * @param role
42
+ * @param name name of the typescipt file without -db -suffix. Max len is 10 char if @param canaryName is not given.
43
+ * @param params
44
+ * @param canaryName Optional name for canary if multiple canaries is made from same ${name}-db.ts canary file.
45
+ */
46
+ static createV2(stack, role, name, params = {}, canaryName = name) {
47
+ const secret = stack.getSecret();
48
+ return new DatabaseCanary(stack, role, secret, {
49
+ ...{
50
+ secret: stack.configuration.secretId,
51
+ schedule: Schedule.rate(Duration.hours(1)),
52
+ handler: `${name}-db.handler`,
53
+ name: canaryName,
54
+ alarm: {
55
+ alarmName: canaryName === name
56
+ ? `${stack.configuration.shortName}-DB-Alarm`
57
+ : `${canaryName}-DB-Alarm`,
58
+ topicArn: stack.configuration.alarmTopicArn,
59
+ },
60
+ },
61
+ ...params,
62
+ });
63
+ }
64
+ }
65
+ //# sourceMappingURL=database-canary.js.map
@@ -0,0 +1,33 @@
1
+ import type { Countable } from "../../../database/models.js";
2
+ declare abstract class DatabaseCheck<T> {
3
+ readonly name: string;
4
+ readonly sql: string;
5
+ failed: boolean;
6
+ protected constructor(name: string, sql: string);
7
+ abstract check(value: T): void;
8
+ }
9
+ /**
10
+ * Checker for sql that checks the count. Meaning that the
11
+ * sql must be structured as "select count(*) from <table> where <something>".
12
+ */
13
+ export declare class DatabaseCountChecker {
14
+ readonly credentialsFunction: () => Promise<void>;
15
+ readonly checks: DatabaseCheck<Countable>[];
16
+ private constructor();
17
+ static createForProxy(): DatabaseCountChecker;
18
+ static createForRds(): DatabaseCountChecker;
19
+ /**
20
+ * Expect that the count is 1
21
+ */
22
+ expectOne(name: string, sql: string): DatabaseCountChecker;
23
+ /**
24
+ * Expect that the count is 0
25
+ */
26
+ expectZero(name: string, sql: string): DatabaseCountChecker;
27
+ /**
28
+ * Expect that the count is 1 or more
29
+ */
30
+ expectOneOrMore(name: string, sql: string): DatabaseCountChecker;
31
+ expect(): Promise<"OK">;
32
+ }
33
+ export {};
@@ -0,0 +1,119 @@
1
+ import synthetics from "Synthetics";
2
+ import { inDatabaseReadonly } from "../../../database/database.js";
3
+ import { getEnvVariable } from "../../../utils/utils.js";
4
+ import { logger } from "../../runtime/dt-logger-default.js";
5
+ import { ProxyHolder } from "../../runtime/secrets/proxy-holder.js";
6
+ import { RdsHolder } from "../../runtime/secrets/rds-holder.js";
7
+ class DatabaseCheck {
8
+ name;
9
+ sql;
10
+ failed;
11
+ constructor(name, sql) {
12
+ this.name = name;
13
+ this.sql = sql;
14
+ this.failed = false;
15
+ }
16
+ }
17
+ class CountDatabaseCheck extends DatabaseCheck {
18
+ minCount;
19
+ maxCount;
20
+ constructor(name, sql, minCount, maxCount) {
21
+ super(name, sql);
22
+ if (!sql.toLowerCase().includes("select") ||
23
+ !sql.toLowerCase().includes("count")) {
24
+ throw new Error("sql must contain select count(*)");
25
+ }
26
+ if ((minCount === null || minCount === undefined) &&
27
+ (maxCount === null || maxCount === undefined)) {
28
+ throw new Error("no max or min given");
29
+ }
30
+ this.minCount = minCount;
31
+ this.maxCount = maxCount;
32
+ }
33
+ check(value) {
34
+ if ("count" in value) {
35
+ if (this.minCount && value.count < this.minCount) {
36
+ this.failed = true;
37
+ throw new Error(`count was ${value.count}, minimum is ${this.minCount}`);
38
+ }
39
+ if (this.maxCount && value.count > this.maxCount) {
40
+ this.failed = true;
41
+ throw new Error(`count was ${value.count}, max is ${this.maxCount}`);
42
+ }
43
+ }
44
+ else {
45
+ this.failed = true;
46
+ throw new Error("no count available");
47
+ }
48
+ }
49
+ }
50
+ const stepConfig = {
51
+ continueOnStepFailure: true,
52
+ screenshotOnStepStart: false,
53
+ screenshotOnStepSuccess: false,
54
+ screenshotOnStepFailure: false,
55
+ };
56
+ /**
57
+ * Checker for sql that checks the count. Meaning that the
58
+ * sql must be structured as "select count(*) from <table> where <something>".
59
+ */
60
+ export class DatabaseCountChecker {
61
+ credentialsFunction;
62
+ checks = [];
63
+ constructor(credentialsFunction) {
64
+ this.credentialsFunction = credentialsFunction;
65
+ synthetics.getConfiguration().disableRequestMetrics();
66
+ synthetics.getConfiguration().withFailedCanaryMetric(true);
67
+ }
68
+ static createForProxy() {
69
+ return new DatabaseCountChecker(() => new ProxyHolder(getEnvVariable("SECRET_ID")).setCredentials());
70
+ }
71
+ static createForRds() {
72
+ return new DatabaseCountChecker(() => new RdsHolder(getEnvVariable("SECRET_ID")).setCredentials());
73
+ }
74
+ /**
75
+ * Expect that the count is 1
76
+ */
77
+ expectOne(name, sql) {
78
+ this.checks.push(new CountDatabaseCheck(name, sql, 1, 1));
79
+ return this;
80
+ }
81
+ /**
82
+ * Expect that the count is 0
83
+ */
84
+ expectZero(name, sql) {
85
+ this.checks.push(new CountDatabaseCheck(name, sql, null, 0));
86
+ return this;
87
+ }
88
+ /**
89
+ * Expect that the count is 1 or more
90
+ */
91
+ expectOneOrMore(name, sql) {
92
+ this.checks.push(new CountDatabaseCheck(name, sql, 1, null));
93
+ return this;
94
+ }
95
+ async expect() {
96
+ if (!this.checks.length) {
97
+ throw new Error("No checks");
98
+ }
99
+ await this.credentialsFunction();
100
+ await inDatabaseReadonly(async (db) => {
101
+ for (const check of this.checks) {
102
+ logger.info({
103
+ method: "DatabaseCountChecker.expect",
104
+ message: `Running sql: ${check.sql}`,
105
+ });
106
+ const value = await db.one(check.sql);
107
+ const checkFunction = () => {
108
+ check.check(value);
109
+ };
110
+ synthetics.executeStep(check.name, checkFunction, stepConfig);
111
+ }
112
+ });
113
+ if (this.checks.some((check) => check.failed)) {
114
+ throw new Error("Failed");
115
+ }
116
+ return "OK";
117
+ }
118
+ }
119
+ //# sourceMappingURL=database-checker.js.map
@@ -0,0 +1,16 @@
1
+ import type { Role } from "aws-cdk-lib/aws-iam";
2
+ import type { ISecret } from "aws-cdk-lib/aws-secretsmanager";
3
+ import type { DigitrafficRestApi } from "../stack/rest-api.js";
4
+ import type { DigitrafficStack } from "../stack/stack.js";
5
+ import { DigitrafficCanary } from "./canary.js";
6
+ import type { CanaryParameters } from "./canary-parameters.js";
7
+ export interface UrlCanaryParameters extends CanaryParameters {
8
+ readonly hostname: string;
9
+ readonly apiKeyId: string;
10
+ readonly inVpc?: boolean;
11
+ }
12
+ export declare class UrlCanary extends DigitrafficCanary {
13
+ constructor(stack: DigitrafficStack, role: Role, params: UrlCanaryParameters, secret?: ISecret);
14
+ static create(stack: DigitrafficStack, role: Role, publicApi: DigitrafficRestApi, params: Partial<UrlCanaryParameters>, secret?: ISecret): UrlCanary;
15
+ static getApiKey(publicApi: DigitrafficRestApi): string | undefined;
16
+ }
@@ -0,0 +1,55 @@
1
+ import { CfnCanary } from "aws-cdk-lib/aws-synthetics";
2
+ import { DigitrafficCanary } from "./canary.js";
3
+ import { ENV_API_KEY, ENV_HOSTNAME, ENV_SECRET } from "./canary-keys.js";
4
+ export class UrlCanary extends DigitrafficCanary {
5
+ constructor(stack, role, params, secret) {
6
+ const canaryName = `${params.name}-url`;
7
+ const environmentVariables = {};
8
+ environmentVariables[ENV_HOSTNAME] = params.hostname;
9
+ if (params.secret) {
10
+ environmentVariables[ENV_SECRET] = params.secret;
11
+ }
12
+ if (params.apiKeyId) {
13
+ environmentVariables[ENV_API_KEY] = params.apiKeyId;
14
+ }
15
+ if (secret) {
16
+ secret.grantRead(role);
17
+ }
18
+ // the handler code is defined at the actual project using this
19
+ super(stack, canaryName, role, params, environmentVariables);
20
+ if (params.inVpc && this.node.defaultChild instanceof CfnCanary) {
21
+ const subnetIds = stack.vpc === undefined
22
+ ? []
23
+ : stack.vpc.privateSubnets.map((subnet) => subnet.subnetId);
24
+ const securityGroupIds = stack.lambdaDbSg === undefined
25
+ ? []
26
+ : [stack.lambdaDbSg.securityGroupId];
27
+ this.node.defaultChild.vpcConfig = {
28
+ vpcId: stack.vpc?.vpcId,
29
+ securityGroupIds,
30
+ subnetIds,
31
+ };
32
+ }
33
+ }
34
+ static create(stack, role, publicApi, params, secret) {
35
+ return new UrlCanary(stack, role, {
36
+ handler: `${params.name ?? undefined}.handler`,
37
+ hostname: publicApi.hostname(),
38
+ apiKeyId: UrlCanary.getApiKey(publicApi),
39
+ ...params,
40
+ }, secret);
41
+ }
42
+ static getApiKey(publicApi) {
43
+ const apiKeys = publicApi.apiKeyIds;
44
+ if (apiKeys.length > 1) {
45
+ console.info("rest api has more than one api key");
46
+ }
47
+ if (apiKeys.length === 0) {
48
+ console.info("rest api has no api keys");
49
+ return undefined;
50
+ }
51
+ // always use first api key
52
+ return publicApi.apiKeyIds[0];
53
+ }
54
+ }
55
+ //# sourceMappingURL=url-canary.js.map
@@ -0,0 +1,45 @@
1
+ import type { IncomingMessage } from "node:http";
2
+ import type { FeatureCollection } from "geojson";
3
+ import { MediaType } from "../../types/mediatypes.js";
4
+ export declare const API_KEY_HEADER = "x-api-key";
5
+ type CheckerFunction = (Res: IncomingMessage) => Promise<void>;
6
+ type JsonCheckerFunction<T> = (json: T, body: string, message: IncomingMessage) => Promise<void>;
7
+ export declare class UrlChecker {
8
+ private readonly requestOptions;
9
+ constructor(hostname: string, apiKey?: string);
10
+ static create(hostname: string, apiKeyId: string): Promise<UrlChecker>;
11
+ static createV2(): Promise<UrlChecker>;
12
+ expectStatus<T>(statusCode: number, url: string, callback: JsonCheckerFunction<T>): Promise<void>;
13
+ expect200<T>(url: string, ...callbacks: JsonCheckerFunction<T>[]): Promise<void>;
14
+ expect404(url: string): Promise<void>;
15
+ expect400(url: string): Promise<void>;
16
+ expect403WithoutApiKey(url: string, mediaType?: MediaType): Promise<void>;
17
+ done(): string;
18
+ }
19
+ export declare class ResponseChecker {
20
+ private readonly contentType;
21
+ private checkCors;
22
+ constructor(contentType: string);
23
+ static forJson(): ResponseChecker;
24
+ static forCSV(): ResponseChecker;
25
+ static forGeojson(): ResponseChecker;
26
+ static forJpeg(): ResponseChecker;
27
+ check(): CheckerFunction;
28
+ checkJson<T>(fn: (json: T, body: string, res: IncomingMessage) => void): CheckerFunction;
29
+ responseChecker(fn: (body: string, res: IncomingMessage) => void): CheckerFunction;
30
+ }
31
+ export declare const ContentChecker: {
32
+ checkJson<T>(fn: (json: T, body: string, res: IncomingMessage) => void): CheckerFunction;
33
+ checkResponse(fn: (body: string, res: IncomingMessage) => void): CheckerFunction;
34
+ };
35
+ export declare const ContentTypeChecker: {
36
+ checkContentType(contentType: MediaType): CheckerFunction;
37
+ };
38
+ export declare const GeoJsonChecker: {
39
+ validFeatureCollection(fn?: (json: FeatureCollection) => void): CheckerFunction;
40
+ };
41
+ export declare const HeaderChecker: {
42
+ checkHeaderExists(headerName: string): CheckerFunction;
43
+ checkHeaderMissing(headerName: string): CheckerFunction;
44
+ };
45
+ export {};