@digitraffic/common 2026.4.28-1 → 2026.5.26-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 @@
1
+ export {};
@@ -0,0 +1,70 @@
1
+ import { App } from "aws-cdk-lib";
2
+ import { AssetCode } from "aws-cdk-lib/aws-lambda";
3
+ import { describe, expect, test } from "vitest";
4
+ import { FunctionBuilder } from "../../../aws/infra/stack/dt-function.js";
5
+ import { DigitrafficStack } from "../../../aws/infra/stack/stack.js";
6
+ function createStack() {
7
+ const app = new App();
8
+ return new DigitrafficStack(app, "TestStack", {
9
+ shortName: "TEST",
10
+ });
11
+ }
12
+ function getCode(builder) {
13
+ return builder.code;
14
+ }
15
+ function getHandler(builder) {
16
+ return builder.handler;
17
+ }
18
+ describe("FunctionBuilder.withAssetCode", () => {
19
+ test("uses lambdaName as default path", () => {
20
+ const stack = createStack();
21
+ const builder = FunctionBuilder.create(stack, "feature/subfeature/lambda-implementation");
22
+ const code = getCode(builder);
23
+ expect(code).toBeInstanceOf(AssetCode);
24
+ expect(code.path).toBe("dist/lambda/feature/subfeature/lambda-implementation");
25
+ });
26
+ test("uses custom path when provided", () => {
27
+ const stack = createStack();
28
+ const builder = FunctionBuilder.create(stack, "feature/subfeature/lambda-implementation").withAssetCode("feature/subfeature/lambda-implementation");
29
+ const code = getCode(builder);
30
+ expect(code.path).toBe("dist/lambda/feature/subfeature/lambda-implementation");
31
+ });
32
+ test("returns this for chaining when called without exclude", () => {
33
+ const stack = createStack();
34
+ const builder = FunctionBuilder.create(stack, "feature/subfeature/lambda-implementation");
35
+ expect(builder.withAssetCode("feature/subfeature/lambda-implementation")).toBe(builder);
36
+ });
37
+ test("accepts exclude list and uses correct path", () => {
38
+ const stack = createStack();
39
+ const builder = FunctionBuilder.create(stack, "feature/shared").withAssetCode("feature/shared", [
40
+ "handler-a/**",
41
+ "handler-b/**",
42
+ "handler-c/**",
43
+ ]);
44
+ const code = getCode(builder);
45
+ expect(code).toBeInstanceOf(AssetCode);
46
+ expect(code.path).toBe("dist/lambda/feature/shared");
47
+ });
48
+ test("returns this for chaining when called with exclude", () => {
49
+ const stack = createStack();
50
+ const builder = FunctionBuilder.create(stack, "feature/shared");
51
+ expect(builder.withAssetCode("feature/shared", ["handler-a/**"])).toBe(builder);
52
+ });
53
+ test("exclude is optional — undefined behaves same as no exclude", () => {
54
+ const stack = createStack();
55
+ const builderWithout = FunctionBuilder.create(stack, "test/lambda");
56
+ const builderWithUndefined = FunctionBuilder.create(stack, "test/lambda2").withAssetCode("test/lambda2", undefined);
57
+ expect(getCode(builderWithout).path).toBe("dist/lambda/test/lambda");
58
+ expect(getCode(builderWithUndefined).path).toBe("dist/lambda/test/lambda2");
59
+ });
60
+ test("handler uses basename(path), not the full path", () => {
61
+ const stack = createStack();
62
+ // Without explicit withAssetCode — constructor default
63
+ const builderDefault = FunctionBuilder.create(stack, "feature/shared");
64
+ expect(getHandler(builderDefault)).toBe("shared.handler");
65
+ // With explicit withAssetCode (e.g. to pass exclude) — must also use basename
66
+ const builderExplicit = FunctionBuilder.create(stack, "feature/shared2").withAssetCode("feature/shared2", ["handler-a/**"]);
67
+ expect(getHandler(builderExplicit)).toBe("shared2.handler");
68
+ });
69
+ });
70
+ //# sourceMappingURL=dt-function.test.js.map
@@ -139,11 +139,9 @@ describe("FunctionBuilder test", () => {
139
139
  });
140
140
  });
141
141
  test("Lambda handler module is resolved from path last element", () => {
142
- const template = createTemplate((_builder) => { }, false, "api/charging-network/v1/operators");
143
- // const lambdas = template.findResources("AWS::Lambda::Function");
144
- // console.debug(JSON.stringify(lambdas, null, 2));
142
+ const template = createTemplate((_builder) => { }, false, "api/feature/v1/get-items");
145
143
  template.hasResourceProperties("AWS::Lambda::Function", {
146
- Handler: "operators.handler",
144
+ Handler: "get-items.handler",
147
145
  });
148
146
  });
149
147
  test("Lambda handler module is same as lambda name", () => {
@@ -40,9 +40,19 @@ export declare class FunctionBuilder {
40
40
  */
41
41
  static plain(stack: Stack & DigitrafficStackInterface, lambdaName: string): FunctionBuilder;
42
42
  /**
43
- * Use AssetCode from given path(dist/lambda/${path}). Default path is lambdaName. Also calls withHandler with the same value.
44
- */
45
- withAssetCode(path?: string): this;
43
+ * Sets the Lambda deployment package to the directory `dist/lambda/${path}` and configures
44
+ * the handler to `basename(path).handler`.
45
+ * @param path - subdirectory under `dist/lambda/` that contains the compiled Lambda code.
46
+ * The handler module name is derived from `basename(path)` (e.g. `"locations.handler"`).
47
+ * Defaults to `lambdaName`.
48
+ * Example: `"dump/locations"` → asset dir `dist/lambda/dump/locations/`, handler `locations.handler`.
49
+ * @param exclude - optional glob patterns to exclude from the asset bundle.
50
+ * Patterns are relative to the asset root (`dist/lambda/${path}/`) — do NOT use a leading slash.
51
+ * Use `**` to match files recursively.
52
+ * Example: `["datex2-36", "datex2-37", "statuses"]` excludes sibling lambda subdirectories
53
+ * that would otherwise be bundled into this lambda's deployment package.
54
+ */
55
+ withAssetCode(path?: string, exclude?: string[]): this;
46
56
  withCode(code: Code): this;
47
57
  /**
48
58
  * Use given handler(${name}.handler) to run the lambda. Default value is lambdaName.
@@ -39,13 +39,7 @@ export class FunctionBuilder {
39
39
  this.functionName = `${stack.configuration.shortName}-${startCase(camelCase(lambdaName)).replace(/\s/g, "")}`;
40
40
  this.environment = {};
41
41
  this.vpc = stack.vpc;
42
- // this calls withHandler as well but with full path
43
42
  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
43
  }
50
44
  /**
51
45
  * Creates a new builder with defaults, using the lambdaName as a source for the lambda implementation (dist/lambdaName/lambdaName.js).
@@ -63,11 +57,22 @@ export class FunctionBuilder {
63
57
  .withoutSecretAccess();
64
58
  }
65
59
  /**
66
- * Use AssetCode from given path(dist/lambda/${path}). Default path is lambdaName. Also calls withHandler with the same value.
60
+ * Sets the Lambda deployment package to the directory `dist/lambda/${path}` and configures
61
+ * the handler to `basename(path).handler`.
62
+ * @param path - subdirectory under `dist/lambda/` that contains the compiled Lambda code.
63
+ * The handler module name is derived from `basename(path)` (e.g. `"locations.handler"`).
64
+ * Defaults to `lambdaName`.
65
+ * Example: `"dump/locations"` → asset dir `dist/lambda/dump/locations/`, handler `locations.handler`.
66
+ * @param exclude - optional glob patterns to exclude from the asset bundle.
67
+ * Patterns are relative to the asset root (`dist/lambda/${path}/`) — do NOT use a leading slash.
68
+ * Use `**` to match files recursively.
69
+ * Example: `["datex2-36", "datex2-37", "statuses"]` excludes sibling lambda subdirectories
70
+ * that would otherwise be bundled into this lambda's deployment package.
67
71
  */
68
- withAssetCode(path = this._name) {
69
- this.code = new AssetCode(`dist/lambda/${path}`);
70
- this.withHandler(path);
72
+ withAssetCode(path = this._name, exclude) {
73
+ this.code = new AssetCode(`dist/lambda/${path}`, exclude ? { exclude } : undefined);
74
+ const moduleName = basename(path);
75
+ this.withHandler(moduleName);
71
76
  return this;
72
77
  }
73
78
  withCode(code) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digitraffic/common",
3
- "version": "2026.4.28-1",
3
+ "version": "2026.5.26-1",
4
4
  "private": false,
5
5
  "description": "",
6
6
  "repository": {
@@ -108,64 +108,64 @@
108
108
  "dist/**/*.d.ts"
109
109
  ],
110
110
  "devDependencies": {
111
- "@aws-sdk/client-api-gateway": "3.1028.0",
112
- "@aws-sdk/client-s3": "3.1028.0",
113
- "@aws-sdk/client-secrets-manager": "3.1028.0",
114
- "@aws-sdk/client-sns": "3.1028.0",
115
- "@aws-sdk/lib-storage": "3.1028.0",
116
- "@biomejs/biome": "2.4.11",
111
+ "@aws-sdk/client-api-gateway": "3.1047.0",
112
+ "@aws-sdk/client-s3": "3.1047.0",
113
+ "@aws-sdk/client-secrets-manager": "3.1047.0",
114
+ "@aws-sdk/client-sns": "3.1047.0",
115
+ "@aws-sdk/lib-storage": "3.1047.0",
116
+ "@biomejs/biome": "2.4.15",
117
117
  "@date-fns/tz": "1.4.1",
118
- "@rushstack/heft": "1.2.11",
119
- "@rushstack/heft-typescript-plugin": "1.3.6",
120
- "@smithy/fetch-http-handler": "5.3.16",
121
- "@smithy/node-http-handler": "4.5.2",
122
- "@smithy/types": "4.14.0",
118
+ "@rushstack/heft": "1.2.17",
119
+ "@rushstack/heft-typescript-plugin": "1.3.12",
120
+ "@smithy/fetch-http-handler": "5.4.2",
121
+ "@smithy/node-http-handler": "4.7.2",
122
+ "@smithy/types": "4.14.1",
123
123
  "@types/aws-lambda": "8.10.161",
124
124
  "@types/etag": "1.8.4",
125
125
  "@types/geojson": "7946.0.16",
126
126
  "@types/geojson-validation": "1.0.3",
127
127
  "@types/madge": "5.0.3",
128
- "@types/node": "24.12.2",
129
- "@vitest/coverage-v8": "4.1.4",
130
- "aws-cdk-lib": "2.248.0",
128
+ "@types/node": "25.8.0",
129
+ "@vitest/coverage-v8": "4.1.6",
130
+ "aws-cdk-lib": "2.254.0",
131
131
  "change-case": "5.4.4",
132
132
  "constructs": "10.6.0",
133
133
  "date-fns": "4.1.0",
134
- "es-toolkit": "1.45.1",
134
+ "es-toolkit": "1.46.1",
135
135
  "etag": "1.8.1",
136
136
  "geojson-validation": "1.0.2",
137
- "ky": "1.14.3",
138
- "lefthook": "2.1.5",
137
+ "ky": "2.0.2",
138
+ "lefthook": "2.1.6",
139
139
  "madge": "8.0.0",
140
140
  "pg-native": "3.7.0",
141
141
  "pg-promise": "12.6.2",
142
142
  "pg-query-stream": "4.14.0",
143
143
  "rimraf": "6.1.3",
144
144
  "sort-package-json": "3.6.1",
145
- "typescript": "5.9.3",
146
- "velocityjs": "2.1.5",
147
- "vitest": "4.1.4",
148
- "zod": "4.3.6"
145
+ "typescript": "6.0.3",
146
+ "velocityjs": "2.1.6",
147
+ "vitest": "4.1.6",
148
+ "zod": "4.4.3"
149
149
  },
150
150
  "peerDependencies": {
151
- "@aws-sdk/client-api-gateway": "3.1028.0",
152
- "@aws-sdk/client-s3": "3.1028.0",
153
- "@aws-sdk/client-secrets-manager": "3.1028.0",
154
- "@aws-sdk/client-sns": "3.1028.0",
155
- "@aws-sdk/lib-storage": "3.1028.0",
151
+ "@aws-sdk/client-api-gateway": "3.1047.0",
152
+ "@aws-sdk/client-s3": "3.1047.0",
153
+ "@aws-sdk/client-secrets-manager": "3.1047.0",
154
+ "@aws-sdk/client-sns": "3.1047.0",
155
+ "@aws-sdk/lib-storage": "3.1047.0",
156
156
  "@date-fns/tz": "1.4.1",
157
- "@smithy/fetch-http-handler": "5.3.16",
158
- "@smithy/node-http-handler": "4.5.2",
159
- "aws-cdk-lib": "2.248.0",
157
+ "@smithy/fetch-http-handler": "5.4.2",
158
+ "@smithy/node-http-handler": "4.7.2",
159
+ "aws-cdk-lib": "2.254.0",
160
160
  "change-case": "5.4.4",
161
161
  "constructs": "10.6.0",
162
162
  "date-fns": "4.1.0",
163
- "es-toolkit": "1.45.1",
163
+ "es-toolkit": "1.46.1",
164
164
  "geojson-validation": "1.0.2",
165
- "ky": "1.14.3",
165
+ "ky": "2.0.2",
166
166
  "pg-native": "3.7.0",
167
167
  "pg-promise": "12.6.2",
168
- "zod": "4.3.6"
168
+ "zod": "4.4.3"
169
169
  },
170
170
  "engines": {
171
171
  "node": ">=24 <25"