@digitraffic/common 2024.3.22-1 → 2024.3.28-1

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.
@@ -0,0 +1,25 @@
1
+ import { AclBuilder } from "../../aws/infra/acl-builder.mjs";
2
+ import { App, Stack } from "aws-cdk-lib";
3
+ describe("acl-builder tests", () => {
4
+ function createBuilder() {
5
+ const app = new App();
6
+ const stack = new Stack(app);
7
+ return new AclBuilder(stack);
8
+ }
9
+ test("no rules", () => {
10
+ expect(() => createBuilder().build()).toThrow();
11
+ });
12
+ test("default rules", () => {
13
+ const acl = createBuilder().withAWSManagedRules().build();
14
+ expect(acl.rules).toHaveLength(4);
15
+ });
16
+ test("two aws rules", () => {
17
+ const acl = createBuilder().withAWSManagedRules(["CommonRuleSet", "AmazonIpReputationList"]).build();
18
+ expect(acl.rules).toHaveLength(2);
19
+ });
20
+ test("ip restriction", () => {
21
+ const acl = createBuilder().withIpRestrictionRule(["1.2.3.4", "1.2.6.6"]).build();
22
+ expect(acl.rules).toHaveLength(1);
23
+ });
24
+ });
25
+ //# sourceMappingURL=acl-builder.test.mjs.map
@@ -1,6 +1,6 @@
1
- import { HandlerFactory } from "../../aws/infra/api/handler-factory.mjs";
2
- import { DtLogger } from "../../aws/runtime/dt-logger.mjs";
3
- import { LambdaResponse } from "../../aws/types/lambda-response.mjs";
1
+ import { HandlerFactory } from "../../../aws/infra/api/handler-factory.mjs";
2
+ import { DtLogger } from "../../../aws/runtime/dt-logger.mjs";
3
+ import { LambdaResponse } from "../../../aws/types/lambda-response.mjs";
4
4
  import { jest } from "@jest/globals";
5
5
  const logger = new DtLogger();
6
6
  describe("handler-factory tests", () => {
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,4 @@
1
- import { RESPONSE_DEFAULT_LAMBDA } from "../../aws/infra/api/response.mjs";
1
+ import { RESPONSE_DEFAULT_LAMBDA } from "../../../aws/infra/api/response.mjs";
2
2
  import etag from "etag";
3
3
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires
4
4
  //const velocity = require("velocityjs");
@@ -0,0 +1,26 @@
1
+ import { DigitrafficStaticIntegration } from "../../../aws/infra/api/static-integration.mjs";
2
+ import { MediaType } from "../../../aws/types/mediatypes.mjs";
3
+ describe("response tests", () => {
4
+ it("createIntegrationResponse works", () => {
5
+ const integrationResponse = DigitrafficStaticIntegration.createIntegrationResponse("FakeResource", MediaType.APPLICATION_JSON, { "test-header": "test-value" });
6
+ expect(integrationResponse).toEqual({
7
+ responseParameters: {
8
+ "method.response.header.test-header": "'test-value'"
9
+ },
10
+ responseTemplates: {
11
+ "application/json": "FakeResource"
12
+ },
13
+ statusCode: "200"
14
+ });
15
+ });
16
+ it("createMethodResponse works", () => {
17
+ const methodResponse = DigitrafficStaticIntegration.createMethodResponse({ "test-header": "test-value" });
18
+ expect(methodResponse).toEqual({
19
+ responseParameters: {
20
+ "method.response.header.test-header": true
21
+ },
22
+ statusCode: "200"
23
+ });
24
+ });
25
+ });
26
+ //# sourceMappingURL=static-integration.test.mjs.map
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,37 @@
1
+ import { DocumentationPart } from "../../aws/infra/documentation.mjs";
2
+ const METHOD_NAME = "test";
3
+ const SUMMARY = "summary";
4
+ const PARAMETER_NAME = "parameter";
5
+ const DESCRIPTION = "description";
6
+ const DEPRECATION_NOTE = "note";
7
+ describe("DocumentationPart tests", () => {
8
+ test("method", () => {
9
+ const part = DocumentationPart.method([], METHOD_NAME, SUMMARY);
10
+ expect(part.type).toEqual("METHOD");
11
+ expect(part.parameterName).toEqual(METHOD_NAME);
12
+ expect(part.documentationProperties.summary).toEqual(SUMMARY);
13
+ expect(part.documentationProperties.deprecated).toBeFalsy();
14
+ });
15
+ test("method - deprecated", () => {
16
+ const part = DocumentationPart.method([], METHOD_NAME, SUMMARY).deprecated(DEPRECATION_NOTE);
17
+ expect(part.type).toEqual("METHOD");
18
+ expect(part.parameterName).toEqual(METHOD_NAME);
19
+ expect(part.documentationProperties.summary).toEqual(`${SUMMARY}. ${DEPRECATION_NOTE}`);
20
+ expect(part.documentationProperties.deprecated).toBeTruthy();
21
+ });
22
+ test("queryparameter", () => {
23
+ const part = DocumentationPart.queryParameter(PARAMETER_NAME, DESCRIPTION);
24
+ expect(part.type).toEqual("QUERY_PARAMETER");
25
+ expect(part.parameterName).toEqual(PARAMETER_NAME);
26
+ expect(part.documentationProperties.description).toEqual(DESCRIPTION);
27
+ expect(part.documentationProperties.deprecated).toBeFalsy();
28
+ });
29
+ test("pathparameter", () => {
30
+ const part = DocumentationPart.pathParameter(PARAMETER_NAME, DESCRIPTION);
31
+ expect(part.type).toEqual("PATH_PARAMETER");
32
+ expect(part.parameterName).toEqual(PARAMETER_NAME);
33
+ expect(part.documentationProperties.description).toEqual(DESCRIPTION);
34
+ expect(part.documentationProperties.deprecated).toBeFalsy();
35
+ });
36
+ });
37
+ //# sourceMappingURL=documentation.test.mjs.map
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,22 @@
1
+ import { App, Stack } from "aws-cdk-lib";
2
+ import { Scheduler } from "../../aws/infra/scheduler.mjs";
3
+ import { Template } from "aws-cdk-lib/assertions";
4
+ describe("scheduler tests", () => {
5
+ function expectRate(createScheduler, expectedRate) {
6
+ const app = new App();
7
+ const stack = new Stack(app);
8
+ createScheduler(stack);
9
+ const template = Template.fromStack(stack);
10
+ template.hasResource("AWS::Events::Rule", {
11
+ Properties: {
12
+ ScheduleExpression: expectedRate,
13
+ State: "ENABLED"
14
+ }
15
+ });
16
+ }
17
+ test("everyMinute", () => expectRate((stack) => Scheduler.everyMinute(stack, "test"), "rate(1 minute)"));
18
+ test("everyMinutes", () => expectRate((stack) => Scheduler.everyMinutes(stack, "test", 12), "rate(12 minutes)"));
19
+ test("everyHour", () => expectRate((stack) => Scheduler.everyHour(stack, "test"), "rate(1 hour)"));
20
+ test("everyDay", () => expectRate((stack) => Scheduler.everyDay(stack, "test"), "rate(1 day)"));
21
+ });
22
+ //# sourceMappingURL=scheduler.test.mjs.map
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,20 @@
1
+ import { App, Stack } from "aws-cdk-lib";
2
+ import { Template } from "aws-cdk-lib/assertions";
3
+ import { DigitrafficSecurityRule } from "../../aws/infra/security-rule.mjs";
4
+ import { Topic } from "aws-cdk-lib/aws-sns";
5
+ describe("security-rule tests", () => {
6
+ test("create", () => {
7
+ const app = new App();
8
+ const stack = new Stack(app);
9
+ const topic = new Topic(stack, "test");
10
+ new DigitrafficSecurityRule(stack, topic);
11
+ const template = Template.fromStack(stack);
12
+ template.hasResource("AWS::Events::Rule", {
13
+ Properties: {
14
+ EventPattern: {},
15
+ State: "ENABLED"
16
+ }
17
+ });
18
+ });
19
+ });
20
+ //# sourceMappingURL=security-rule.test.mjs.map
@@ -0,0 +1,21 @@
1
+ import { CfnWebACL } from "aws-cdk-lib/aws-wafv2";
2
+ import type { Construct } from "constructs";
3
+ export type AWSManagedWafRule = "CommonRuleSet" | "AmazonIpReputationList" | "KnownBadInputsRuleSet" | "SQLiRuleSet";
4
+ /**
5
+ * Builder class for building CfnWebACL.
6
+ *
7
+ * Currently supports:
8
+ * * Some AWS managed WAF rules
9
+ * * IP blacklisting
10
+ */
11
+ export declare class AclBuilder {
12
+ readonly _construct: Construct;
13
+ readonly _rules: CfnWebACL.RuleProperty[];
14
+ _scope: string;
15
+ _name: string;
16
+ constructor(construct: Construct);
17
+ isRuleDefined(rules: AWSManagedWafRule[] | "all", rule: AWSManagedWafRule): boolean;
18
+ withAWSManagedRules(rules?: AWSManagedWafRule[] | "all"): AclBuilder;
19
+ withIpRestrictionRule(addresses: string[]): AclBuilder;
20
+ build(): CfnWebACL;
21
+ }
@@ -0,0 +1,136 @@
1
+ import { CfnIPSet, CfnWebACL } from "aws-cdk-lib/aws-wafv2";
2
+ /**
3
+ * Builder class for building CfnWebACL.
4
+ *
5
+ * Currently supports:
6
+ * * Some AWS managed WAF rules
7
+ * * IP blacklisting
8
+ */
9
+ export class AclBuilder {
10
+ _construct;
11
+ _rules = [];
12
+ _scope = "CLOUDFRONT";
13
+ _name = "WebACL";
14
+ constructor(construct) {
15
+ this._construct = construct;
16
+ }
17
+ isRuleDefined(rules, rule) {
18
+ return rules === "all" || rules.includes(rule);
19
+ }
20
+ withAWSManagedRules(rules = "all") {
21
+ if (this.isRuleDefined(rules, "CommonRuleSet")) {
22
+ this._rules.push(createAWSCommonRuleSet());
23
+ }
24
+ if (this.isRuleDefined(rules, "AmazonIpReputationList")) {
25
+ this._rules.push(createAWSReputationList());
26
+ }
27
+ if (this.isRuleDefined(rules, "KnownBadInputsRuleSet")) {
28
+ this._rules.push(createAWSKnownBadInput());
29
+ }
30
+ if (this.isRuleDefined(rules, "SQLiRuleSet")) {
31
+ this._rules.push(createAWSAntiSQLInjection());
32
+ }
33
+ return this;
34
+ }
35
+ withIpRestrictionRule(addresses) {
36
+ const blocklistIpSet = new CfnIPSet(this._construct, "BlocklistIpSet", {
37
+ ipAddressVersion: "IPV4",
38
+ scope: this._scope,
39
+ addresses,
40
+ });
41
+ this._rules.push({
42
+ name: "IpBlocklist",
43
+ priority: 10,
44
+ action: { block: {} },
45
+ statement: {
46
+ ipSetReferenceStatement: {
47
+ arn: blocklistIpSet.attrArn,
48
+ },
49
+ },
50
+ visibilityConfig: {
51
+ sampledRequestsEnabled: false,
52
+ cloudWatchMetricsEnabled: true,
53
+ metricName: "IpBlocklist",
54
+ },
55
+ });
56
+ return this;
57
+ }
58
+ build() {
59
+ if (this._rules.length === 0) {
60
+ throw new Error("No rules defined for WebACL");
61
+ }
62
+ const acl = new CfnWebACL(this._construct, this._name, {
63
+ defaultAction: { allow: {} },
64
+ scope: this._scope,
65
+ visibilityConfig: {
66
+ cloudWatchMetricsEnabled: true,
67
+ metricName: "WAF-Blocked",
68
+ sampledRequestsEnabled: false
69
+ },
70
+ rules: this._rules,
71
+ // customResponseBodies
72
+ });
73
+ return acl;
74
+ }
75
+ }
76
+ function createAWSCommonRuleSet() {
77
+ return createRuleProperty("AWS-AWSManagedRulesCommonRuleSet", 70, {
78
+ statement: {
79
+ managedRuleGroupStatement: {
80
+ vendorName: "AWS",
81
+ name: "AWSManagedRulesCommonRuleSet",
82
+ excludedRules: [
83
+ { name: "NoUserAgent_HEADER" },
84
+ { name: "SizeRestrictions_BODY" },
85
+ { name: "GenericRFI_BODY" }
86
+ ]
87
+ }
88
+ }
89
+ });
90
+ }
91
+ function createAWSReputationList() {
92
+ return createRuleProperty("AWS-AWSManagedRulesAmazonIpReputationList", 80, {
93
+ statement: {
94
+ managedRuleGroupStatement: {
95
+ vendorName: "AWS",
96
+ name: "AWSManagedRulesAmazonIpReputationList"
97
+ }
98
+ }
99
+ });
100
+ }
101
+ function createAWSKnownBadInput() {
102
+ return createRuleProperty("AWS-AWSManagedRulesKnownBadInputsRuleSet", 90, {
103
+ statement: {
104
+ managedRuleGroupStatement: {
105
+ vendorName: "AWS",
106
+ name: "AWSManagedRulesKnownBadInputsRuleSet"
107
+ }
108
+ }
109
+ });
110
+ }
111
+ function createAWSAntiSQLInjection() {
112
+ return createRuleProperty("AWS-AWSManagedRulesSQLiRuleSet", 100, {
113
+ statement: {
114
+ managedRuleGroupStatement: {
115
+ vendorName: "AWS",
116
+ name: "AWSManagedRulesSQLiRuleSet"
117
+ }
118
+ }
119
+ });
120
+ }
121
+ function createRuleProperty(name, priority, rule, overrideAction = true) {
122
+ return {
123
+ ...{
124
+ name,
125
+ priority,
126
+ visibilityConfig: {
127
+ sampledRequestsEnabled: true,
128
+ cloudWatchMetricsEnabled: true,
129
+ metricName: name
130
+ }
131
+ },
132
+ ...rule,
133
+ ...(overrideAction ? { overrideAction: { none: {} } } : {})
134
+ };
135
+ }
136
+ //# sourceMappingURL=acl-builder.mjs.map
@@ -8,8 +8,17 @@ import { MediaType } from "../../types/mediatypes.mjs";
8
8
  * @param response
9
9
  */
10
10
  export declare class DigitrafficStaticIntegration extends MockIntegration {
11
- constructor(resource: Resource, mediaType: MediaType, response: string, enableCors?: boolean, apiKeyRequired?: boolean);
12
- static json<K>(resource: Resource, response: K, enableCors?: boolean, apiKeyRequired?: boolean): DigitrafficStaticIntegration;
13
- private static createIntegrationResponse;
14
- private static createMethodResponse;
11
+ constructor(resource: Resource, mediaType: MediaType, response: string, enableCors?: boolean, apiKeyRequired?: boolean, headers?: Record<string, string>);
12
+ static json<K>(resource: Resource, response: K, enableCors?: boolean, apiKeyRequired?: boolean, headers?: Record<string, string>): DigitrafficStaticIntegration;
13
+ static createIntegrationResponse(response: string, mediaType: MediaType, headers?: Record<string, string>): {
14
+ statusCode: string;
15
+ responseTemplates: {
16
+ [x: string]: string;
17
+ };
18
+ responseParameters: Record<string, string>;
19
+ };
20
+ static createMethodResponse(headers: Record<string, string>): {
21
+ statusCode: string;
22
+ responseParameters: Record<string, boolean>;
23
+ };
15
24
  }
@@ -1,12 +1,8 @@
1
- import { MockIntegration, PassthroughBehavior, Resource, } from "aws-cdk-lib/aws-apigateway";
1
+ import { MockIntegration, PassthroughBehavior, Resource } from "aws-cdk-lib/aws-apigateway";
2
2
  import { MediaType } from "../../types/mediatypes.mjs";
3
- import { RESPONSE_CORS_INTEGRATION } from "./responses.mjs";
4
3
  const INTEGRATION_RESPONSE_200 = `{
5
4
  "statusCode": 200
6
5
  }`;
7
- const METHOD_RESPONSE_200 = {
8
- statusCode: "200",
9
- };
10
6
  /**
11
7
  * Static integration, that returns the given response with given mediaType from given resource.
12
8
  *
@@ -15,8 +11,11 @@ const METHOD_RESPONSE_200 = {
15
11
  * @param response
16
12
  */
17
13
  export class DigitrafficStaticIntegration extends MockIntegration {
18
- constructor(resource, mediaType, response, enableCors = true, apiKeyRequired = true) {
19
- const integrationResponse = DigitrafficStaticIntegration.createIntegrationResponse(response, mediaType, enableCors);
14
+ constructor(resource, mediaType, response, enableCors = true, apiKeyRequired = true, headers = {}) {
15
+ if (enableCors) {
16
+ headers = { ...headers, "Access-Control-Allow-Origin": "*" };
17
+ }
18
+ const integrationResponse = DigitrafficStaticIntegration.createIntegrationResponse(response, mediaType, headers);
20
19
  super({
21
20
  passthroughBehavior: PassthroughBehavior.WHEN_NO_TEMPLATES,
22
21
  requestTemplates: {
@@ -28,39 +27,44 @@ export class DigitrafficStaticIntegration extends MockIntegration {
28
27
  resource.addMethod(httpMethod, this, {
29
28
  apiKeyRequired,
30
29
  methodResponses: [
31
- DigitrafficStaticIntegration.createMethodResponse(enableCors),
30
+ DigitrafficStaticIntegration.createMethodResponse(headers),
32
31
  ],
33
32
  });
34
33
  });
35
34
  }
36
- static json(resource, response, enableCors = true, apiKeyRequired = true) {
37
- return new DigitrafficStaticIntegration(resource, MediaType.APPLICATION_JSON, JSON.stringify(response), enableCors, apiKeyRequired);
35
+ static json(resource, response, enableCors = true, apiKeyRequired = true, headers = {}) {
36
+ return new DigitrafficStaticIntegration(resource, MediaType.APPLICATION_JSON, JSON.stringify(response), enableCors, apiKeyRequired, headers);
38
37
  }
39
- static createIntegrationResponse(response, mediaType, enableCors) {
40
- const integrationResponse = {
38
+ static createIntegrationResponse(response, mediaType, headers = {}) {
39
+ const params = mapRecord(headers, (entry) => ["method.response.header." + entry[0], `'${entry[1]}'`]);
40
+ return {
41
41
  statusCode: "200",
42
42
  responseTemplates: {
43
43
  [mediaType]: response,
44
44
  },
45
+ responseParameters: params
45
46
  };
46
- return enableCors
47
- ? { ...integrationResponse, ...RESPONSE_CORS_INTEGRATION }
48
- : integrationResponse;
49
47
  }
50
- static createMethodResponse(enableCors) {
51
- return enableCors
52
- ? corsMethod(METHOD_RESPONSE_200)
53
- : METHOD_RESPONSE_200;
48
+ static createMethodResponse(headers) {
49
+ const allowedHeaders = Object.keys(headers);
50
+ const entries = Object.fromEntries(allowedHeaders.map((key) => [key, true]));
51
+ return {
52
+ statusCode: "200",
53
+ responseParameters: prefixKeys("method.response.header.", entries)
54
+ };
54
55
  }
55
56
  }
56
- function corsMethod(response) {
57
- return {
58
- ...response,
59
- ...{
60
- responseParameters: {
61
- "method.response.header.Access-Control-Allow-Origin": true,
62
- },
63
- },
64
- };
57
+ function mapRecord(obj, func) {
58
+ const mappedEntries = Object.entries(obj).map((entry) => func(entry));
59
+ return Object.fromEntries(mappedEntries);
60
+ }
61
+ /**
62
+ * Create a new Record with prefix added to each of the keys.
63
+ *
64
+ * @param prefix
65
+ * @param obj
66
+ */
67
+ function prefixKeys(prefix, obj) {
68
+ return mapRecord(obj, (entry) => [prefix + entry[0], entry[1]]);
65
69
  }
66
70
  //# sourceMappingURL=static-integration.mjs.map
@@ -9,11 +9,11 @@ import { SnsTopic } from "aws-cdk-lib/aws-events-targets";
9
9
  */
10
10
  export class DigitrafficSecurityRule extends Rule {
11
11
  constructor(scope, topic) {
12
- const ruleName = 'SecurityHubRule';
12
+ const ruleName = "SecurityHubRule";
13
13
  super(scope, ruleName, {
14
14
  ruleName,
15
15
  eventPattern: {
16
- source: ['aws.securityhub'],
16
+ source: ["aws.securityhub"],
17
17
  detailType: ["Security Hub Findings - Imported"],
18
18
  detail: {
19
19
  findings: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digitraffic/common",
3
- "version": "2024.3.22-1",
3
+ "version": "2024.3.28-1",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "repository": {
@@ -56,6 +56,7 @@
56
56
  "./dist/aws/infra/stacks/db-proxy-stack": "./dist/aws/infra/stacks/db-proxy-stack.mjs",
57
57
  "./dist/aws/infra/stacks/intra-stack-configuration": "./dist/aws/infra/stacks/intra-stack-configuration.mjs",
58
58
  "./dist/aws/infra/stacks/db-dns-stack": "./dist/aws/infra/stacks/db-dns-stack.mjs",
59
+ "./dist/aws/infra/acl-builder": "./dist/aws/infra/acl-builder.mjs",
59
60
  "./dist/aws/infra/documentation": "./dist/aws/infra/documentation.mjs",
60
61
  "./dist/aws/infra/usage-plans": "./dist/aws/infra/usage-plans.mjs",
61
62
  "./dist/aws/infra/scheduler": "./dist/aws/infra/scheduler.mjs",
@@ -103,32 +104,32 @@
103
104
  "./dist/aws/runtime/digitraffic-integration-response": "./dist/aws/runtime/digitraffic-integration-response.mjs"
104
105
  },
105
106
  "peerDependencies": {
106
- "@aws-sdk/client-s3": "^3.533.0",
107
- "@aws-sdk/lib-storage": "^3.533.0",
108
- "@aws-sdk/client-secrets-manager": "^3.533.0",
109
- "@aws-sdk/client-api-gateway": "^3.533.0",
110
- "@aws-sdk/client-sns": "^3.533.0",
107
+ "@aws-sdk/client-s3": "^3.540.0",
108
+ "@aws-sdk/lib-storage": "^3.540.0",
109
+ "@aws-sdk/client-secrets-manager": "^3.540.0",
110
+ "@aws-sdk/client-api-gateway": "^3.540.0",
111
+ "@aws-sdk/client-sns": "^3.540.0",
111
112
  "@types/geojson": "^7946.0.14",
112
- "aws-cdk-lib": "^2.133.0",
113
+ "aws-cdk-lib": "^2.134.0",
113
114
  "change-case": "5.0.0",
114
115
  "constructs": "^10.3.0",
115
116
  "date-fns": "~2.30.0",
116
117
  "date-fns-tz": "~2.0.0",
117
118
  "etag": "^1.8.1",
118
119
  "geojson-validation": "^1.0.2",
119
- "ky": "^1.2.2",
120
+ "ky": "^1.2.3",
120
121
  "lodash": "~4.17.21",
121
122
  "node-ttl": "^0.2.0",
122
123
  "pg-native": "^3.0.1",
123
124
  "pg-promise": "^11.5.4"
124
125
  },
125
126
  "devDependencies": {
126
- "aws-sdk": "2.1577.0",
127
- "@aws-sdk/client-s3": "3.533.0",
128
- "@aws-sdk/lib-storage": "3.533.0",
129
- "@aws-sdk/client-secrets-manager": "3.533.0",
130
- "@aws-sdk/client-api-gateway": "3.533.0",
131
- "@aws-sdk/client-sns": "3.533.0",
127
+ "aws-sdk": "2.1586.0",
128
+ "@aws-sdk/client-s3": "3.540.0",
129
+ "@aws-sdk/lib-storage": "3.540.0",
130
+ "@aws-sdk/client-secrets-manager": "3.540.0",
131
+ "@aws-sdk/client-api-gateway": "3.540.0",
132
+ "@aws-sdk/client-sns": "3.540.0",
132
133
  "@jest/globals": "^29.7.0",
133
134
  "@rushstack/eslint-config": "^3.6.4",
134
135
  "@rushstack/heft": "^0.66.0",
@@ -142,10 +143,9 @@
142
143
  "@types/jest": "29.5.12",
143
144
  "@types/lodash": "4.14.202",
144
145
  "@types/node": "20.11.27",
145
- "@types/sinon": "17.0.3",
146
146
  "@typescript-eslint/eslint-plugin": "~6.18.1",
147
147
  "@typescript-eslint/parser": "^6.20.0",
148
- "aws-cdk-lib": "^2.133.0",
148
+ "aws-cdk-lib": "^2.134.0",
149
149
  "change-case": "5.3.0",
150
150
  "constructs": "10.3.0",
151
151
  "date-fns": "~2.30.0",
@@ -157,13 +157,12 @@
157
157
  "geojson-validation": "^1.0.2",
158
158
  "jest": "^29.7.0",
159
159
  "jest-junit": "^16.0.0",
160
- "ky": "^1.2.2",
160
+ "ky": "^1.2.3",
161
161
  "lodash": "~4.17.21",
162
162
  "node-ttl": "^0.2.0",
163
163
  "pg-promise": "^11.5.4",
164
164
  "prettier": "^3.2.5",
165
165
  "rimraf": "^5.0.5",
166
- "sinon": "17.0.1",
167
166
  "ts-jest": "^29.1.2",
168
167
  "typescript": "~5.3.3",
169
168
  "velocityjs": "2.0.6"