@digitraffic/common 2026.2.4-4 → 2026.2.5-2

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 (43) hide show
  1. package/dist/__test__/imports.test.js +6 -2
  2. package/dist/__test__/infra/api/integration.test.js +1 -1
  3. package/dist/__test__/infra/api/response.test.js +21 -7
  4. package/dist/__test__/stack/dt-function.test.js +6 -30
  5. package/dist/__test__/types/lambda-response.test.d.ts +7 -8
  6. package/dist/__test__/types/lambda-response.test.js +65 -15
  7. package/dist/__test__/utils/base64.test.js +1 -11
  8. package/dist/__test__/utils/logging.test.js +1 -13
  9. package/dist/aws/infra/api/response.d.ts +1 -1
  10. package/dist/aws/infra/api/response.js +22 -18
  11. package/dist/aws/infra/canaries/canary.js +1 -1
  12. package/dist/aws/infra/canaries/url-checker.js +4 -11
  13. package/dist/aws/infra/sqs-queue.js +1 -1
  14. package/dist/aws/infra/stack/dt-function.d.ts +2 -5
  15. package/dist/aws/infra/stack/dt-function.js +4 -17
  16. package/dist/aws/infra/stack/lambda-configs.d.ts +0 -6
  17. package/dist/aws/infra/stack/lambda-configs.js +2 -8
  18. package/dist/aws/infra/stack/rest-api.js +1 -1
  19. package/dist/aws/infra/stack/stack-checking-aspect.d.ts +0 -1
  20. package/dist/aws/infra/stack/stack-checking-aspect.js +3 -7
  21. package/dist/aws/types/lambda-response.d.ts +19 -22
  22. package/dist/aws/types/lambda-response.js +73 -65
  23. package/dist/aws/types/proxytypes.d.ts +26 -0
  24. package/dist/aws/types/proxytypes.js +2 -0
  25. package/dist/database/cached.d.ts +19 -0
  26. package/dist/database/cached.js +40 -0
  27. package/dist/utils/base64.d.ts +3 -5
  28. package/dist/utils/base64.js +4 -12
  29. package/dist/utils/logging.d.ts +0 -12
  30. package/dist/utils/logging.js +0 -33
  31. package/package.json +34 -33
  32. package/dist/__test__/types/lambda-proxy-types.test.d.ts +0 -8
  33. package/dist/__test__/types/lambda-proxy-types.test.js +0 -154
  34. package/dist/__test__/types/lambda-response-builder.test.d.ts +0 -1
  35. package/dist/__test__/types/lambda-response-builder.test.js +0 -80
  36. package/dist/__test__/utils/lambda-proxy-event.test.d.ts +0 -1
  37. package/dist/__test__/utils/lambda-proxy-event.test.js +0 -44
  38. package/dist/aws/types/lambda-proxy-types.d.ts +0 -59
  39. package/dist/aws/types/lambda-proxy-types.js +0 -210
  40. package/dist/utils/lambda-proxy-event.d.ts +0 -9
  41. package/dist/utils/lambda-proxy-event.js +0 -31
  42. package/dist/utils/zod-utils.d.ts +0 -14
  43. package/dist/utils/zod-utils.js +0 -29
@@ -7,6 +7,10 @@ test("database import ok?", () => {
7
7
  const database = import("../database/database.js");
8
8
  return expect(database).resolves.toBeDefined();
9
9
  });
10
+ test("cached import ok?", () => {
11
+ const cached = import("../database/cached.js");
12
+ return expect(cached).resolves.toBeDefined();
13
+ });
10
14
  test("models import ok?", () => {
11
15
  const models = import("../database/models.js");
12
16
  return expect(models).resolves.toBeDefined();
@@ -239,8 +243,8 @@ test("canaryKeys import ok?", () => {
239
243
  const canaryKeys = import("../aws/infra/canaries/canary-keys.js");
240
244
  return expect(canaryKeys).resolves.toBeDefined();
241
245
  });
242
- test("lambda-proxy-types import ok?", () => {
243
- const proxytypes = import("../aws/types/lambda-proxy-types.js");
246
+ test("proxytypes import ok?", () => {
247
+ const proxytypes = import("../aws/types/proxytypes.js");
244
248
  return expect(proxytypes).resolves.toBeDefined();
245
249
  });
246
250
  test("tags import ok?", () => {
@@ -58,7 +58,7 @@ describe("integration tests", () => {
58
58
  const app = new App();
59
59
  const stack = new Stack(app);
60
60
  const f = new LambdaFunction(stack, "id", {
61
- runtime: Runtime.NODEJS_24_X,
61
+ runtime: Runtime.NODEJS_22_X,
62
62
  code: Code.fromInline("placeholder"),
63
63
  handler: "handler",
64
64
  });
@@ -1,6 +1,8 @@
1
1
  import etag from "etag";
2
2
  import velocity from "velocityjs";
3
3
  import { RESPONSE_DEFAULT_LAMBDA } from "../../../aws/infra/api/response.js";
4
+ import { compressBuffer, decodeBase64ToString, } from "../../../aws/types/lambda-response.js";
5
+ import { TEST_BIG_JSON } from "../../types/lambda-response.test.js";
4
6
  const TEST_BODY = "Hello world!";
5
7
  describe("response tests", () => {
6
8
  function generateEtagValueFromString(body) {
@@ -9,20 +11,24 @@ describe("response tests", () => {
9
11
  function generateEtagValueFromBase64String(bodyBase64) {
10
12
  return etag(bodyBase64);
11
13
  }
12
- function generateResponse(status, fileName, timestamp) {
14
+ function generateResponse(status, fileName, timestamp, compressBody = false, body = TEST_BODY) {
13
15
  const compile = new velocity.Compile(velocity.parse(RESPONSE_DEFAULT_LAMBDA));
16
+ const rawBuffer = Buffer.from(body, "utf8");
14
17
  const output = compile.render({
15
18
  input: {
16
19
  path: () => ({
17
- body: Buffer.from(TEST_BODY).toString("base64"),
20
+ body: (compressBody
21
+ ? compressBuffer(rawBuffer)
22
+ : rawBuffer).toString("base64"),
18
23
  status,
19
24
  fileName,
20
25
  timestamp: timestamp?.toUTCString(),
21
- etag: generateEtagValueFromString(TEST_BODY),
26
+ etag: generateEtagValueFromString(body),
27
+ compressed: compressBody,
22
28
  }),
23
29
  },
24
30
  util: {
25
- base64Decode: (data) => Buffer.from(data, "base64").toString(),
31
+ base64Decode: (data) => decodeBase64ToString(data, compressBody),
26
32
  },
27
33
  context: {
28
34
  responseOverride: {
@@ -33,6 +39,7 @@ describe("response tests", () => {
33
39
  ETag: undefined,
34
40
  "Last-Modified": undefined,
35
41
  "Content-Disposition": undefined,
42
+ "Content-Encoding": undefined,
36
43
  },
37
44
  },
38
45
  },
@@ -40,8 +47,8 @@ describe("response tests", () => {
40
47
  // @ts-expect-error: context is not in the type definition
41
48
  return [output, compile.context.context];
42
49
  }
43
- function assertOutputAndContext(output, context, status, contentType, fileName, timestamp) {
44
- expect(output).toEqual(TEST_BODY);
50
+ function assertOutputAndContext(output, context, status, contentType, fileName, timestamp, body = TEST_BODY, compressBody = false) {
51
+ expect(output).toEqual(body);
45
52
  expect(context).toMatchObject({
46
53
  responseOverride: {
47
54
  status,
@@ -50,7 +57,8 @@ describe("response tests", () => {
50
57
  "Access-Control-Allow-Origin": "*",
51
58
  "Content-Disposition": fileName,
52
59
  "Last-Modified": timestamp?.toUTCString(),
53
- ETag: generateEtagValueFromString(TEST_BODY),
60
+ ETag: generateEtagValueFromString(body),
61
+ "Content-Encoding": compressBody ? "gzip" : undefined,
54
62
  },
55
63
  },
56
64
  });
@@ -72,5 +80,11 @@ describe("response tests", () => {
72
80
  const [output, context] = generateResponse(204);
73
81
  assertOutputAndContext(output, context, 204, "text/plain");
74
82
  });
83
+ test("test 200 - compressed", () => {
84
+ const now = new Date();
85
+ const body = JSON.stringify(TEST_BIG_JSON);
86
+ const [output, context] = generateResponse(200, "test.json", now, true, body);
87
+ assertOutputAndContext(output, context, undefined, undefined, 'attachment; filename="test.json"', now, body, true);
88
+ });
75
89
  });
76
90
  //# sourceMappingURL=response.test.js.map
@@ -8,10 +8,8 @@ import { EnvKeys } from "../../aws/runtime/environment.js";
8
8
  import { TrafficType } from "../../types/traffictype.js";
9
9
  const TEST_ENV_VAR = "TEST_ENV_VAR";
10
10
  const TEST_ENV_VALUE = "testValue";
11
- // AWS::Lambda::Function Template Reference
12
- // https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-lambda-function.html
13
11
  describe("FunctionBuilder test", () => {
14
- function createTemplate(tester, plain = false, lambdaName = "test") {
12
+ function createTemplate(tester, plain = false) {
15
13
  const app = new App();
16
14
  const stack = new DigitrafficStack(app, "test-stack", {
17
15
  alarmTopicArn: "",
@@ -26,10 +24,10 @@ describe("FunctionBuilder test", () => {
26
24
  [TEST_ENV_VAR]: TEST_ENV_VALUE,
27
25
  };
28
26
  const builder = plain
29
- ? FunctionBuilder.plain(stack, lambdaName)
27
+ ? FunctionBuilder.plain(stack, "test")
30
28
  .withEnvironment(environment)
31
29
  .withCode(Code.fromInline("{}"))
32
- : FunctionBuilder.create(stack, lambdaName)
30
+ : FunctionBuilder.create(stack, "test")
33
31
  .withoutDatabaseAccess()
34
32
  .withEnvironment(environment)
35
33
  .withCode(Code.fromInline("{}"));
@@ -64,7 +62,7 @@ describe("FunctionBuilder test", () => {
64
62
  [TEST_ENV_VAR]: TEST_ENV_VALUE,
65
63
  },
66
64
  },
67
- Runtime: Runtime.NODEJS_24_X.name,
65
+ Runtime: Runtime.NODEJS_22_X.name,
68
66
  MemorySize: 128,
69
67
  Timeout: 60,
70
68
  Handler: "test.handler",
@@ -83,18 +81,10 @@ describe("FunctionBuilder test", () => {
83
81
  });
84
82
  test("Lambda runtime is set", () => {
85
83
  const template = createTemplate((builder) => {
86
- builder.withRuntime(Runtime.NODEJS_24_X);
84
+ builder.withRuntime(Runtime.NODEJS_20_X);
87
85
  });
88
86
  template.hasResourceProperties("AWS::Lambda::Function", {
89
- Runtime: Runtime.NODEJS_24_X.name,
90
- });
91
- });
92
- test("Lambda description is set", () => {
93
- const template = createTemplate((builder) => {
94
- builder.withDescription("Does something useful");
95
- });
96
- template.hasResourceProperties("AWS::Lambda::Function", {
97
- Description: "Does something useful",
87
+ Runtime: Runtime.NODEJS_20_X.name,
98
88
  });
99
89
  });
100
90
  test("Lambda memory size is set", () => {
@@ -137,20 +127,6 @@ describe("FunctionBuilder test", () => {
137
127
  Handler: "custom.main",
138
128
  });
139
129
  });
140
- test("Lambda handler module is resolved from path last element", () => {
141
- const template = createTemplate((_builder) => { }, false, "api/charging-network/v1/operators");
142
- // const lambdas = template.findResources("AWS::Lambda::Function");
143
- // console.debug(JSON.stringify(lambdas, null, 2));
144
- template.hasResourceProperties("AWS::Lambda::Function", {
145
- Handler: "operators.handler",
146
- });
147
- });
148
- test("Lambda handler module is same as lambda name", () => {
149
- const template = createTemplate((_builder) => { }, false, "operators");
150
- template.hasResourceProperties("AWS::Lambda::Function", {
151
- Handler: "operators.handler",
152
- });
153
- });
154
130
  test("withRolePolicies adds custom policy to lambda role", () => {
155
131
  const template = createTemplate((builder) => {
156
132
  builder.withRolePolicies(new PolicyStatement({
@@ -1,9 +1,8 @@
1
- export declare const TEST_MESSAGE = "HELLO";
2
- export declare const TEST_COUNT = 12;
3
- export declare const TEST_FILENAME = "file.txt";
4
- export declare const TEST_TIMESTAMP: Date;
5
- export declare const TEST_TIMESTAMP_STR: string;
6
- export declare const TEST_JSON: {
7
- message: string;
8
- count: number;
1
+ export declare const TEST_BIG_JSON: {
2
+ items: {
3
+ id: number;
4
+ name: string;
5
+ description: string;
6
+ value: number;
7
+ }[];
9
8
  };
@@ -1,24 +1,32 @@
1
- import { LambdaResponse, LambdaResponseBuilder, } from "../../aws/types/lambda-response.js";
2
- import { decodeBase64ToUtf8 } from "../../utils/base64.js";
3
- export const TEST_MESSAGE = "HELLO";
4
- export const TEST_COUNT = 12;
5
- export const TEST_FILENAME = "file.txt";
6
- export const TEST_TIMESTAMP = new Date();
7
- export const TEST_TIMESTAMP_STR = TEST_TIMESTAMP.toISOString();
8
- export const TEST_JSON = {
9
- message: TEST_MESSAGE,
10
- count: TEST_COUNT,
1
+ import { decodeBase64ToString, LambdaResponse, LambdaResponseBuilder, } from "../../aws/types/lambda-response.js";
2
+ // About 18 MB will be compressed to 2 MB
3
+ export const TEST_BIG_JSON = {
4
+ items: Array.from({ length: 10 }, (_, i) => ({
5
+ id: i,
6
+ name: `Item ${i}`,
7
+ description: "This is a test description that repeats to allow compression",
8
+ value: Math.random(),
9
+ })),
11
10
  };
12
11
  describe("lambda-response", () => {
12
+ const TEST_MESSAGE = "HELLO";
13
+ const TEST_COUNT = 12;
14
+ const TEST_FILENAME = "file.txt";
15
+ const TEST_TIMESTAMP = new Date();
16
+ const TEST_TIMESTAMP_STR = TEST_TIMESTAMP.toISOString();
17
+ const TEST_JSON = {
18
+ message: TEST_MESSAGE,
19
+ count: TEST_COUNT,
20
+ };
13
21
  function assertJson(response, expectedJson, expectedStatus, expectedFilename, expectedTimestamp) {
14
- const body = JSON.parse(decodeBase64ToUtf8(response.body));
22
+ const body = JSON.parse(decodeBase64ToString(response.body, response.compressed));
15
23
  expect(body).toEqual(expectedJson);
16
24
  expect(response.status).toEqual(expectedStatus);
17
25
  expect(response.fileName).toEqual(expectedFilename);
18
26
  expect(response.timestamp).toEqual(expectedTimestamp?.toUTCString());
19
27
  }
20
28
  function assertBinary(response, expectedString, expectedStatus, expectedFilename, expectedTimestamp) {
21
- const body = decodeBase64ToUtf8(response.body);
29
+ const body = decodeBase64ToString(response.body, response.compressed);
22
30
  expect(body).toEqual(expectedString);
23
31
  expect(response.status).toEqual(expectedStatus);
24
32
  expect(response.fileName).toEqual(expectedFilename);
@@ -46,15 +54,15 @@ describe("lambda-response", () => {
46
54
  });
47
55
  test("notFound", () => {
48
56
  const response = LambdaResponse.notFound();
49
- assertBinary(response, "Not Found", 404);
57
+ assertBinary(response, "Not found", 404);
50
58
  });
51
59
  test("internalError", () => {
52
60
  const response = LambdaResponse.internalError();
53
- assertBinary(response, "Internal Error", 500);
61
+ assertBinary(response, "Internal error", 500);
54
62
  });
55
63
  test("notImplemented", () => {
56
64
  const response = LambdaResponse.notImplemented();
57
- assertBinary(response, "Not Implemented", 501);
65
+ assertBinary(response, "Not implemented", 501);
58
66
  });
59
67
  // Builder
60
68
  test("Builder - okJson - without fileName", () => {
@@ -68,5 +76,47 @@ describe("lambda-response", () => {
68
76
  .build();
69
77
  assertJson(response, TEST_JSON, 200, TEST_FILENAME);
70
78
  });
79
+ test("Builder - okJson - with fileName and timestamp", () => {
80
+ const response = LambdaResponseBuilder.create()
81
+ .withBody(TEST_JSON)
82
+ .withFileName(TEST_FILENAME)
83
+ .withTimestamp(TEST_TIMESTAMP)
84
+ .build();
85
+ const response2 = LambdaResponseBuilder.create()
86
+ .withBody(TEST_JSON)
87
+ .withFileName(TEST_FILENAME)
88
+ .withTimestamp(TEST_TIMESTAMP_STR)
89
+ .build();
90
+ assertJson(response, TEST_JSON, 200, TEST_FILENAME, TEST_TIMESTAMP);
91
+ assertJson(response2, TEST_JSON, 200, TEST_FILENAME, TEST_TIMESTAMP);
92
+ });
93
+ test("Builder - okBinary - with fileName and timestamp", () => {
94
+ const response = LambdaResponseBuilder.create()
95
+ .withBody(TEST_MESSAGE)
96
+ .withFileName(TEST_FILENAME)
97
+ .withTimestamp(TEST_TIMESTAMP)
98
+ .build();
99
+ assertBinary(response, TEST_MESSAGE, 200, TEST_FILENAME, TEST_TIMESTAMP);
100
+ });
101
+ test("Builder - compression uneffective for small json", () => {
102
+ const response = LambdaResponseBuilder.create()
103
+ .withBody(TEST_JSON)
104
+ .withFileName(TEST_FILENAME)
105
+ .withCompression()
106
+ .withDebug()
107
+ .build();
108
+ expect(response.compressed).toBe(false);
109
+ assertJson(response, TEST_JSON, 200, TEST_FILENAME);
110
+ });
111
+ test("Builder - compression effective for large json", () => {
112
+ const response = LambdaResponseBuilder.create()
113
+ .withBody(TEST_BIG_JSON)
114
+ .withFileName(TEST_FILENAME)
115
+ .withCompression()
116
+ .withDebug()
117
+ .build();
118
+ expect(response.compressed).toBe(true);
119
+ assertJson(response, TEST_BIG_JSON, 200, TEST_FILENAME);
120
+ });
71
121
  });
72
122
  //# sourceMappingURL=lambda-response.test.js.map
@@ -1,4 +1,4 @@
1
- import { compressBuffer, decodeBase64ToAscii, decodeBase64ToUtf8, encodeAsciiToBase64, encodeUtf8ToBase64, } from "../../utils/base64.js";
1
+ import { decodeBase64ToAscii, decodeBase64ToUtf8, encodeAsciiToBase64, encodeUtf8ToBase64, } from "../../utils/base64.js";
2
2
  describe("Base64UtilTest", () => {
3
3
  const EXPECTED_ASCII = "0a9f4967-faaa-445a-ba11-078f7f9556b4";
4
4
  const EXPECTED_ASCII_BASE64 = "MGE5ZjQ5NjctZmFhYS00NDVhLWJhMTEtMDc4ZjdmOTU1NmI0";
@@ -23,15 +23,5 @@ describe("Base64UtilTest", () => {
23
23
  expect(encodedUtf8).toEqual(EXPECTED_UTF8_BASE64);
24
24
  expect(decodedUtf8).toEqual(EXPECTED_UTF8);
25
25
  });
26
- test("decode utf8 compressed", () => {
27
- const originalBody = { message: EXPECTED_UTF8 };
28
- const body = JSON.stringify(originalBody);
29
- const rawBuffer = Buffer.from(body, "utf8");
30
- const compressed = compressBuffer(rawBuffer);
31
- const compressedBase64 = compressed.toString("base64");
32
- const uncompressedBody = decodeBase64ToUtf8(compressedBase64, true);
33
- const restoredBody = JSON.parse(uncompressedBody);
34
- expect(originalBody).toEqual(restoredBody);
35
- });
36
26
  });
37
27
  //# sourceMappingURL=base64.test.js.map
@@ -1,6 +1,6 @@
1
1
  import { Writable } from "node:stream";
2
2
  import { DtLogger } from "../../aws/runtime/dt-logger.js";
3
- import { logException, truncateEnd, truncateMiddle, } from "../../utils/logging.js";
3
+ import { logException } from "../../utils/logging.js";
4
4
  const TEST_METHODNAME = "test.logException";
5
5
  describe("logging-test", () => {
6
6
  function assertLogError(error, expected, includeStack = false) {
@@ -58,17 +58,5 @@ describe("logging-test", () => {
58
58
  stack: true,
59
59
  }, true);
60
60
  });
61
- test("truncateEnd - not truncated as would be longer", () => {
62
- expect(truncateEnd("This is a test string", 10)).toBe("This is a test string");
63
- });
64
- test("truncateEnd", () => {
65
- expect(truncateEnd("This is a test string that is long enough", 10)).toBe("This is a [TRUNCATED 31 CHARS]");
66
- });
67
- test("truncateMiddle - not truncated as would be longer", () => {
68
- expect(truncateMiddle("This is a test string", 10)).toBe("This is a test string");
69
- });
70
- test("truncateMiddle", () => {
71
- expect(truncateMiddle("This is a test string that is long enough", 20)).toBe("This is a [TRUNCATED 21 CHARS] ong enough");
72
- });
73
61
  });
74
62
  //# sourceMappingURL=logging.test.js.map
@@ -11,7 +11,7 @@ import { MediaType } from "../../types/mediatypes.js";
11
11
  * If fileName is set, then Content-Disposition-header will be set to use it
12
12
  * If timestamp is set, then ETag & Last-Modified headers will be set
13
13
  */
14
- export declare const RESPONSE_DEFAULT_LAMBDA = "#set($inputRoot = $input.path('$'))##\n#if ($inputRoot.status != 200)##\n#set ($context.responseOverride.status = $inputRoot.status)##\n#set ($context.responseOverride.header.Content-Type = 'text/plain')##\n#end##\n#set ($context.responseOverride.header.Access-Control-Allow-Origin = '*')##\n#if (\"$!inputRoot.timestamp\" != \"\")##\n#set ($context.responseOverride.header.Last-Modified = $inputRoot.timestamp)##\n#end##\n#if (\"$!inputRoot.etag\" != \"\")##\n#set ($context.responseOverride.header.ETag = $inputRoot.etag)##\n#end##\n#if (\"$!inputRoot.fileName\" != \"\")##\n#set ($disposition = 'attachment; filename=\"FN\"')##\n#set ($context.responseOverride.header.Content-Disposition = $disposition.replaceAll('FN', $inputRoot.fileName))##\n#end##\n$util.base64Decode($inputRoot.body)";
14
+ export declare const RESPONSE_DEFAULT_LAMBDA = "#set($inputRoot = $input.path('$'))\n#if ($inputRoot.status != 200)\n#set ($context.responseOverride.status = $inputRoot.status)\n#set ($context.responseOverride.header.Content-Type = 'text/plain')\n#end\n#set ($context.responseOverride.header.Access-Control-Allow-Origin = '*')\n#if (\"$!inputRoot.timestamp\" != \"\")\n#set ($context.responseOverride.header.Last-Modified = $inputRoot.timestamp)\n#end\n#if (\"$!inputRoot.etag\" != \"\")\n#set ($context.responseOverride.header.ETag = $inputRoot.etag)\n#end\n#if (\"$!inputRoot.fileName\" != \"\")\n#set ($disposition = 'attachment; filename=\"FN\"')\n#set ($context.responseOverride.header.Content-Disposition = $disposition.replaceAll('FN', $inputRoot.fileName))\n#end\n#* Conditionally add Content-Encoding if compressed is true *#\n#if($!inputRoot.compressed == true)\n#set($context.responseOverride.header.Content-Encoding = \"gzip\")\n#end\n$util.base64Decode($inputRoot.body)";
15
15
  /**
16
16
  * Use this for deprecated integrations.
17
17
  * Will add HTTP headers Deprecation and Sunset to response.
@@ -12,22 +12,26 @@ import { MediaType } from "../../types/mediatypes.js";
12
12
  * If fileName is set, then Content-Disposition-header will be set to use it
13
13
  * If timestamp is set, then ETag & Last-Modified headers will be set
14
14
  */
15
- export const RESPONSE_DEFAULT_LAMBDA = `#set($inputRoot = $input.path('$'))##
16
- #if ($inputRoot.status != 200)##
17
- #set ($context.responseOverride.status = $inputRoot.status)##
18
- #set ($context.responseOverride.header.Content-Type = 'text/plain')##
19
- #end##
20
- #set ($context.responseOverride.header.Access-Control-Allow-Origin = '*')##
21
- #if ("$!inputRoot.timestamp" != "")##
22
- #set ($context.responseOverride.header.Last-Modified = $inputRoot.timestamp)##
23
- #end##
24
- #if ("$!inputRoot.etag" != "")##
25
- #set ($context.responseOverride.header.ETag = $inputRoot.etag)##
26
- #end##
27
- #if ("$!inputRoot.fileName" != "")##
28
- #set ($disposition = 'attachment; filename="FN"')##
29
- #set ($context.responseOverride.header.Content-Disposition = $disposition.replaceAll('FN', $inputRoot.fileName))##
30
- #end##
15
+ export const RESPONSE_DEFAULT_LAMBDA = `#set($inputRoot = $input.path('$'))
16
+ #if ($inputRoot.status != 200)
17
+ #set ($context.responseOverride.status = $inputRoot.status)
18
+ #set ($context.responseOverride.header.Content-Type = 'text/plain')
19
+ #end
20
+ #set ($context.responseOverride.header.Access-Control-Allow-Origin = '*')
21
+ #if ("$!inputRoot.timestamp" != "")
22
+ #set ($context.responseOverride.header.Last-Modified = $inputRoot.timestamp)
23
+ #end
24
+ #if ("$!inputRoot.etag" != "")
25
+ #set ($context.responseOverride.header.ETag = $inputRoot.etag)
26
+ #end
27
+ #if ("$!inputRoot.fileName" != "")
28
+ #set ($disposition = 'attachment; filename="FN"')
29
+ #set ($context.responseOverride.header.Content-Disposition = $disposition.replaceAll('FN', $inputRoot.fileName))
30
+ #end
31
+ #* Conditionally add Content-Encoding if compressed is true *#
32
+ #if($!inputRoot.compressed == true)
33
+ #set($context.responseOverride.header.Content-Encoding = "gzip")
34
+ #end
31
35
  $util.base64Decode($inputRoot.body)`;
32
36
  /**
33
37
  * Use this for deprecated integrations.
@@ -67,13 +71,13 @@ export const MessageModel = {
67
71
  modelName: "MessageResponseModel",
68
72
  schema: messageSchema,
69
73
  };
70
- const NotFoundMessage = "Not Found";
74
+ const NotFoundMessage = "Not found";
71
75
  export const NotFoundResponse = JSON.stringify({ message: NotFoundMessage });
72
76
  const InternalServerErrorMessage = "Error";
73
77
  const InternalServerErrorResponse = JSON.stringify({
74
78
  message: InternalServerErrorMessage,
75
79
  });
76
- const BadRequestMessage = "Bad Request";
80
+ const BadRequestMessage = "Bad request";
77
81
  const BadRequestResponse = JSON.stringify({ message: BadRequestMessage });
78
82
  /**
79
83
  * @deprecated
@@ -4,7 +4,7 @@ import { CanaryAlarm } from "./canary-alarm.js";
4
4
  export class DigitrafficCanary extends Canary {
5
5
  constructor(scope, canaryName, role, params, environmentVariables) {
6
6
  super(scope, canaryName, {
7
- runtime: params.runtime ?? Runtime.SYNTHETICS_NODEJS_PUPPETEER_13_0,
7
+ runtime: params.runtime ?? Runtime.SYNTHETICS_NODEJS_PUPPETEER_9_0,
8
8
  role,
9
9
  test: Test.custom({
10
10
  code: new AssetCode("dist", {
@@ -14,12 +14,6 @@ const baseHeaders = {
14
14
  "Accept-Encoding": "gzip",
15
15
  Accept: "*/*",
16
16
  };
17
- function sanitizeStepName(url) {
18
- return url
19
- .replace(/\//g, " ")
20
- .replace(/[?&=]/g, " ")
21
- .replace(/auth=.*/, "");
22
- }
23
17
  export class UrlChecker {
24
18
  requestOptions;
25
19
  constructor(hostname, apiKey) {
@@ -56,8 +50,7 @@ export class UrlChecker {
56
50
  path: url,
57
51
  },
58
52
  };
59
- // The step name can only contain letters, numbers, hyphens, underscores, periods, and spaces
60
- await synthetics.executeHttpStep(`Verify ${statusCode} for ${sanitizeStepName(url)}`, requestOptions, callback);
53
+ await synthetics.executeHttpStep(`Verify ${statusCode} for ${url.replace(/auth=.*/, "")}`, requestOptions, callback);
61
54
  }
62
55
  expect200(url, ...callbacks) {
63
56
  const callback = async (json, body, res) => {
@@ -72,7 +65,7 @@ export class UrlChecker {
72
65
  path: url,
73
66
  },
74
67
  };
75
- return synthetics.executeHttpStep(`Verify 404 for ${sanitizeStepName(url)}`, requestOptions, validateStatusCodeAndContentType(404, MediaType.TEXT_PLAIN));
68
+ return synthetics.executeHttpStep(`Verify 404 for ${url}`, requestOptions, validateStatusCodeAndContentType(404, MediaType.TEXT_PLAIN));
76
69
  }
77
70
  expect400(url) {
78
71
  const requestOptions = {
@@ -81,7 +74,7 @@ export class UrlChecker {
81
74
  path: url,
82
75
  },
83
76
  };
84
- return synthetics.executeHttpStep(`Verify 400 for ${sanitizeStepName(url)}`, requestOptions, validateStatusCodeAndContentType(400, MediaType.TEXT_PLAIN));
77
+ return synthetics.executeHttpStep(`Verify 400 for ${url}`, requestOptions, validateStatusCodeAndContentType(400, MediaType.TEXT_PLAIN));
85
78
  }
86
79
  expect403WithoutApiKey(url, mediaType) {
87
80
  if (!this.requestOptions.headers ||
@@ -99,7 +92,7 @@ export class UrlChecker {
99
92
  headers: baseHeaders,
100
93
  },
101
94
  };
102
- return synthetics.executeHttpStep(`Verify 403 for ${sanitizeStepName(url)}`, requestOptions, validateStatusCodeAndContentType(403, mediaType ?? MediaType.APPLICATION_JSON));
95
+ return synthetics.executeHttpStep(`Verify 403 for ${url}`, requestOptions, validateStatusCodeAndContentType(403, mediaType ?? MediaType.APPLICATION_JSON));
103
96
  }
104
97
  done() {
105
98
  return "Canary successful";
@@ -73,7 +73,7 @@ export const DigitrafficDLQueue = {
73
73
  functionName: dlqFunctionName,
74
74
  });
75
75
  const lambda = MonitoredFunction.create(stack, dlqFunctionName, {
76
- runtime: Runtime.NODEJS_24_X,
76
+ runtime: Runtime.NODEJS_22_X,
77
77
  logGroup: dlqLogGroup,
78
78
  functionName: dlqFunctionName,
79
79
  code: getDlqCode(dlqBucket.bucketName),
@@ -9,7 +9,6 @@ import type { DigitrafficStack } from "./stack.js";
9
9
  export declare class FunctionBuilder {
10
10
  private readonly _stack;
11
11
  private readonly _name;
12
- private description?;
13
12
  private runtime;
14
13
  private architecture;
15
14
  private role?;
@@ -46,13 +45,11 @@ export declare class FunctionBuilder {
46
45
  withAssetCode(path?: string): this;
47
46
  withCode(code: Code): this;
48
47
  /**
49
- * Use given handler(${name}.handler) to run the lambda. Default value is lambdaName.
48
+ * Use given handler(${name}.handler) to run the lambda. Default value is lambdaname.
50
49
  * @param name
51
- * @param handlerFunctionName
52
50
  * @returns
53
51
  */
54
52
  withHandler(name: string, handlerFunctionName?: string): this;
55
- withDescription(description: string): this;
56
53
  /**
57
54
  * Do not grant database access. Default is with database access.
58
55
  */
@@ -70,7 +67,7 @@ export declare class FunctionBuilder {
70
67
  */
71
68
  withMemorySize(memorySize: number): this;
72
69
  /**
73
- * Set runtime for the lambda. Default is Runtime.NODEJS_24_X.
70
+ * Set runtime for the lambda. Default is Runtime.NODEJS_22_X.
74
71
  */
75
72
  withRuntime(runtime: Runtime): this;
76
73
  /**
@@ -1,4 +1,3 @@
1
- import { basename } from "node:path";
2
1
  import { Duration } from "aws-cdk-lib";
3
2
  import { SnsAction } from "aws-cdk-lib/aws-cloudwatch-actions";
4
3
  import { Effect, PolicyStatement } from "aws-cdk-lib/aws-iam";
@@ -11,8 +10,7 @@ import { createLambdaLogGroup } from "./lambda-log-group.js";
11
10
  export class FunctionBuilder {
12
11
  _stack;
13
12
  _name;
14
- description;
15
- runtime = Runtime.NODEJS_24_X;
13
+ runtime = Runtime.NODEJS_22_X;
16
14
  architecture = Architecture.ARM_64;
17
15
  role;
18
16
  timeout = Duration.seconds(60);
@@ -39,13 +37,8 @@ export class FunctionBuilder {
39
37
  this.functionName = `${stack.configuration.shortName}-${startCase(camelCase(lambdaName)).replace(/\s/g, "")}`;
40
38
  this.environment = {};
41
39
  this.vpc = stack.vpc;
42
- // this calls withHandler as well but with full path
40
+ this.withHandler(lambdaName);
43
41
  this.withAssetCode(lambdaName);
44
- // Remove path from lambda to get module name.
45
- // e.g. for lambdaName "api/charging-network/v1/operators",
46
- // moduleName becomes "operators" and handler becomes "operators.handler"
47
- const moduleName = basename(lambdaName);
48
- this.withHandler(moduleName);
49
42
  }
50
43
  /**
51
44
  * Creates a new builder with defaults, using the lambdaName as a source for the lambda implementation (dist/lambdaName/lambdaName.js).
@@ -85,19 +78,14 @@ export class FunctionBuilder {
85
78
  return this;
86
79
  }
87
80
  /**
88
- * Use given handler(${name}.handler) to run the lambda. Default value is lambdaName.
81
+ * Use given handler(${name}.handler) to run the lambda. Default value is lambdaname.
89
82
  * @param name
90
- * @param handlerFunctionName
91
83
  * @returns
92
84
  */
93
85
  withHandler(name, handlerFunctionName = "handler") {
94
86
  this.handler = `${name}.${handlerFunctionName}`;
95
87
  return this;
96
88
  }
97
- withDescription(description) {
98
- this.description = description;
99
- return this;
100
- }
101
89
  /**
102
90
  * Do not grant database access. Default is with database access.
103
91
  */
@@ -127,7 +115,7 @@ export class FunctionBuilder {
127
115
  return this;
128
116
  }
129
117
  /**
130
- * Set runtime for the lambda. Default is Runtime.NODEJS_24_X.
118
+ * Set runtime for the lambda. Default is Runtime.NODEJS_22_X.
131
119
  */
132
120
  withRuntime(runtime) {
133
121
  this.runtime = runtime;
@@ -229,7 +217,6 @@ export class FunctionBuilder {
229
217
  functionName: this.functionName,
230
218
  securityGroups,
231
219
  environment: this.getEnvironment(),
232
- description: this.description,
233
220
  });
234
221
  if (this._features.secretAccess) {
235
222
  this._stack.grantSecret(createdFunction);
@@ -10,13 +10,7 @@ export type DBLambdaEnvironment = LambdaEnvironment & {
10
10
  SECRET_ID?: string;
11
11
  DB_APPLICATION: string;
12
12
  };
13
- /**
14
- * @deprecated use dt-function.ts: FunctionBuilder
15
- */
16
13
  export declare function databaseFunctionProps(stack: DigitrafficStack, environment: LambdaEnvironment, lambdaName: string, simpleLambdaName: string, logGroup: ILogGroup, config?: Partial<FunctionParameters>): FunctionProps;
17
- /**
18
- * @deprecated use dt-function.ts: FunctionBuilder
19
- */
20
14
  export declare function lambdaFunctionProps(_: DigitrafficStack, environment: LambdaEnvironment, lambdaName: string, simpleLambdaName: string, logGroup: ILogGroup, config?: Partial<FunctionParameters>): FunctionProps;
21
15
  export declare function defaultLambdaConfiguration(config: FunctionParameters): FunctionProps;
22
16
  export interface FunctionParameters {
@@ -1,8 +1,5 @@
1
1
  import { Duration } from "aws-cdk-lib";
2
2
  import { Architecture, AssetCode, Runtime } from "aws-cdk-lib/aws-lambda";
3
- /**
4
- * @deprecated use dt-function.ts: FunctionBuilder
5
- */
6
3
  export function databaseFunctionProps(stack, environment, lambdaName, simpleLambdaName, logGroup, config) {
7
4
  const vpcSubnets = stack.vpc
8
5
  ? {
@@ -18,12 +15,9 @@ export function databaseFunctionProps(stack, environment, lambdaName, simpleLamb
18
15
  },
19
16
  };
20
17
  }
21
- /**
22
- * @deprecated use dt-function.ts: FunctionBuilder
23
- */
24
18
  export function lambdaFunctionProps(_, environment, lambdaName, simpleLambdaName, logGroup, config) {
25
19
  return {
26
- runtime: config?.runtime ?? Runtime.NODEJS_24_X,
20
+ runtime: config?.runtime ?? Runtime.NODEJS_22_X,
27
21
  architecture: config?.architecture ?? Architecture.ARM_64,
28
22
  memorySize: config?.memorySize ?? 128,
29
23
  functionName: lambdaName,
@@ -44,7 +38,7 @@ function getAssetCode(simpleLambdaName, isSingleLambda) {
44
38
  }
45
39
  export function defaultLambdaConfiguration(config) {
46
40
  const props = {
47
- runtime: Runtime.NODEJS_24_X,
41
+ runtime: Runtime.NODEJS_22_X,
48
42
  memorySize: config.memorySize ?? 128,
49
43
  functionName: config.functionName,
50
44
  handler: config.handler,