@mettlecast/domain-cdk-packer 0.2.91 → 0.2.93

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.
@@ -9,7 +9,7 @@ import * as iam from 'aws-cdk-lib/aws-iam';
9
9
  import * as scheduler from 'aws-cdk-lib/aws-scheduler';
10
10
  import * as ec2 from 'aws-cdk-lib/aws-ec2';
11
11
  import * as s3 from 'aws-cdk-lib/aws-s3';
12
- import { createGroupedLambdas } from './grouped-lambda-factory.js';
12
+ import { createGroupedLambdas, createGroupedApiActionLambda } from './grouped-lambda-factory.js';
13
13
  import { IamPolicyBuilder } from './iam/iam-policy-builder.js';
14
14
  import { HealthConstruct } from './constructs/health-construct.js';
15
15
  import { DashboardConstruct } from './constructs/dashboard-construct.js';
@@ -124,7 +124,7 @@ export class DomainStack extends cdk.Stack {
124
124
  const resolvedUserPoolId = userPoolId ?? cdk.Fn.select(1, cdk.Fn.split('/', userPoolArn));
125
125
  jwtAuthorizer = new apigwv2.HttpAuthorizer(this, 'CognitoAuthorizer', {
126
126
  httpApi: this.httpApi,
127
- authorizerName: 'CognitoAuthorizer',
127
+ authorizerName: `CognitoAuthorizer-${domainId}`,
128
128
  type: apigwv2.HttpAuthorizerType.JWT,
129
129
  identitySource: ['$request.header.Authorization'],
130
130
  jwtAudience: [userPoolClientId],
@@ -207,17 +207,77 @@ export class DomainStack extends cdk.Stack {
207
207
  const lambdas = [];
208
208
  const byId = new Map();
209
209
  for (const group of splitByOutboundAccess(entries)) {
210
- // Force dedicated mode for action groups that contain any API-exposed
211
- // action the per-entry adapter override only takes effect in
212
- // dedicated mode (grouped mode uses a single TIB_HANDLER_MAP dispatcher
213
- // which assumes a uniform adapter across all entries). We detect
214
- // api-exposed actions by their `adapter` override (set by the caller
215
- // in the action block below), since the entry shape is intentionally
216
- // primitive-agnostic.
217
- const hasApiExposedAction = primitiveType === 'action'
218
- && group.entries.some(e => e.adapter === 'createExposedActionApiHandler');
219
- const dedicated = group.entries.some(entry => entry.deployment?.isolation === 'dedicated')
220
- || hasApiExposedAction;
210
+ if (primitiveType === 'action') {
211
+ // Split API-exposed actions from internal actions so they can be
212
+ // grouped into a single Lambda each (instead of one Lambda per action).
213
+ const apiExposed = group.entries.filter(e => e.adapter === 'createExposedActionApiHandler' && e.apiMethod && e.apiRoutePath);
214
+ const internal = group.entries.filter(e => !(e.adapter === 'createExposedActionApiHandler' && e.apiMethod && e.apiRoutePath));
215
+ // API-exposed actions ONE grouped Lambda with route-key dispatch
216
+ if (apiExposed.length > 0) {
217
+ const apiEntries = apiExposed.map(e => ({
218
+ id: e.id,
219
+ handlerFile: e.handlerFile,
220
+ method: e.apiMethod,
221
+ routePath: e.apiRoutePath,
222
+ }));
223
+ const apiLambda = createGroupedApiActionLambda(this, {
224
+ domainId,
225
+ domainRoot: registry.domainRoot,
226
+ apiEntries,
227
+ environment,
228
+ eventBusArn,
229
+ reservedConcurrency,
230
+ logRetentionDays: logRetentionDays ?? 30,
231
+ lambdaGroupId: group.outboundAccess,
232
+ ...(vpc ? {
233
+ vpc,
234
+ securityGroups: lambdaSg ? [lambdaSg] : undefined,
235
+ subnetSelection: resolveSubnetSelection(group.outboundAccess),
236
+ } : {}),
237
+ });
238
+ lambdas.push(apiLambda);
239
+ apiExposed.forEach(entry => byId.set(entry.id, apiLambda));
240
+ }
241
+ // Internal actions → existing grouped mode (one Lambda for all)
242
+ if (internal.length > 0) {
243
+ const internalDedicated = internal.some(entry => entry.deployment?.isolation === 'dedicated');
244
+ const internalLambdas = createGroupedLambdas(this, {
245
+ domainId,
246
+ domainRoot: registry.domainRoot,
247
+ primitiveType,
248
+ handlerEntries: internal.map(entry => {
249
+ const handlerEntry = {
250
+ id: entry.id,
251
+ handlerFile: entry.handlerFile,
252
+ };
253
+ if (entry.adapter)
254
+ handlerEntry.adapter = entry.adapter;
255
+ return handlerEntry;
256
+ }),
257
+ environment,
258
+ eventBusArn,
259
+ dedicated: internalDedicated,
260
+ reservedConcurrency,
261
+ logRetentionDays: logRetentionDays ?? 30,
262
+ lambdaGroupId: group.outboundAccess,
263
+ ...(vpc ? {
264
+ vpc,
265
+ securityGroups: lambdaSg ? [lambdaSg] : undefined,
266
+ subnetSelection: resolveSubnetSelection(group.outboundAccess),
267
+ } : {}),
268
+ });
269
+ lambdas.push(...internalLambdas);
270
+ if (internalDedicated) {
271
+ internal.forEach((entry, index) => byId.set(entry.id, internalLambdas[index]));
272
+ }
273
+ else {
274
+ internal.forEach(entry => byId.set(entry.id, internalLambdas[0]));
275
+ }
276
+ }
277
+ continue;
278
+ }
279
+ // Non-action primitives: existing logic
280
+ const dedicated = group.entries.some(entry => entry.deployment?.isolation === 'dedicated');
221
281
  const groupLambdas = createGroupedLambdas(this, {
222
282
  domainId,
223
283
  domainRoot: registry.domainRoot,
@@ -495,6 +555,8 @@ export class DomainStack extends cdk.Stack {
495
555
  entry.deployment = action.deployment;
496
556
  if (action.exposure?.type === 'api') {
497
557
  entry.adapter = 'createExposedActionApiHandler';
558
+ entry.apiMethod = action.exposure.method;
559
+ entry.apiRoutePath = `/${domainId}${action.exposure.path}`;
498
560
  }
499
561
  return entry;
500
562
  });
@@ -69,17 +69,17 @@ describe('DomainStack', () => {
69
69
  const eventBusArn = 'arn:aws:events:eu-north-1:123456789012:event-bus/tib-event-bus';
70
70
  it('synthesises without error for minimal registry', () => {
71
71
  const app = new cdk.App();
72
- expect(() => new DomainStack(app, 'TestDomainStack', { registry: minimalRegistry, eventBusArn })).not.toThrow();
72
+ expect(() => new DomainStack(app, 'TestDomainStack', { registry: minimalRegistry, eventBusArn, projectId: 'Test', envCode: 'Dev' })).not.toThrow();
73
73
  });
74
74
  it('template contains HttpApi', () => {
75
75
  const app = new cdk.App();
76
- const stack = new DomainStack(app, 'TestDomainStack2', { registry: minimalRegistry, eventBusArn });
76
+ const stack = new DomainStack(app, 'TestDomainStack2', { registry: minimalRegistry, eventBusArn, projectId: 'Test', envCode: 'Dev' });
77
77
  const template = Template.fromStack(stack);
78
78
  template.resourceCountIs('AWS::ApiGatewayV2::Api', 1);
79
79
  });
80
80
  it('template contains one Lambda function for the api entry', () => {
81
81
  const app = new cdk.App();
82
- const stack = new DomainStack(app, 'TestDomainStack3', { registry: minimalRegistry, eventBusArn });
82
+ const stack = new DomainStack(app, 'TestDomainStack3', { registry: minimalRegistry, eventBusArn, projectId: 'Test', envCode: 'Dev' });
83
83
  const template = Template.fromStack(stack);
84
84
  template.resourceCountIs('AWS::Lambda::Function', 4);
85
85
  });
@@ -90,6 +90,8 @@ describe('DomainStack', () => {
90
90
  const stack = new DomainStack(app, 'TestDomainStackJwt', {
91
91
  registry: minimalRegistry,
92
92
  eventBusArn,
93
+ projectId: 'Test',
94
+ envCode: 'Dev',
93
95
  userPoolArn,
94
96
  userPoolClientId,
95
97
  });
@@ -98,6 +100,21 @@ describe('DomainStack', () => {
98
100
  AuthorizerType: 'JWT',
99
101
  });
100
102
  });
103
+ it('authorizer name is unique per-domain (includes domainId)', () => {
104
+ const app = new cdk.App();
105
+ const stack = new DomainStack(app, 'TestDomainStackName', {
106
+ registry: minimalRegistry,
107
+ eventBusArn,
108
+ projectId: 'Test',
109
+ envCode: 'Dev',
110
+ userPoolId: 'eu-north-1_test',
111
+ userPoolClientId: 'client-id',
112
+ });
113
+ const template = Template.fromStack(stack);
114
+ template.hasResourceProperties('AWS::ApiGatewayV2::Authorizer', {
115
+ Name: 'CognitoAuthorizer-test-domain',
116
+ });
117
+ });
101
118
  it('no authorizer attached when no JWT-protected actions are declared', () => {
102
119
  const app = new cdk.App();
103
120
  const registryNoAuth = {
@@ -120,6 +137,8 @@ describe('DomainStack', () => {
120
137
  const stack = new DomainStack(app, 'TestDomainStackNoAuth', {
121
138
  registry: registryNoAuth,
122
139
  eventBusArn,
140
+ projectId: 'Test',
141
+ envCode: 'Dev',
123
142
  });
124
143
  const template = Template.fromStack(stack);
125
144
  template.resourceCountIs('AWS::ApiGatewayV2::Authorizer', 0);
@@ -130,6 +149,8 @@ describe('DomainStack', () => {
130
149
  const stack = new DomainStack(app, 'TestDomainStackDbSecret', {
131
150
  registry: minimalRegistry,
132
151
  eventBusArn,
152
+ projectId: 'Test',
153
+ envCode: 'Dev',
133
154
  dbSecretArn,
134
155
  });
135
156
  const template = Template.fromStack(stack);
@@ -143,6 +164,8 @@ describe('DomainStack', () => {
143
164
  const stack = new DomainStack(app, 'TestDomainStackSecretGrant', {
144
165
  registry: minimalRegistry,
145
166
  eventBusArn,
167
+ projectId: 'Test',
168
+ envCode: 'Dev',
146
169
  dbSecretArn,
147
170
  });
148
171
  const template = Template.fromStack(stack);
@@ -152,7 +175,7 @@ describe('DomainStack', () => {
152
175
  });
153
176
  describe('domain S3 bucket', () => {
154
177
  const app = new cdk.App();
155
- const stack = new DomainStack(app, 'TestDomainStackS3', { registry: minimalRegistry, eventBusArn });
178
+ const stack = new DomainStack(app, 'TestDomainStackS3', { registry: minimalRegistry, eventBusArn, projectId: 'Test', envCode: 'Dev' });
156
179
  const template = Template.fromStack(stack);
157
180
  it('creates exactly one S3 bucket', () => {
158
181
  template.resourceCountIs('AWS::S3::Bucket', 1);
@@ -170,7 +193,7 @@ describe('DomainStack', () => {
170
193
  });
171
194
  describe('tenant-scoped IAM role (defence in depth)', () => {
172
195
  const app = new cdk.App();
173
- const stack = new DomainStack(app, 'TestDomainStackTenant', { registry: minimalRegistry, eventBusArn });
196
+ const stack = new DomainStack(app, 'TestDomainStackTenant', { registry: minimalRegistry, eventBusArn, projectId: 'Test', envCode: 'Dev' });
174
197
  const template = Template.fromStack(stack);
175
198
  it('creates a tenant-scoped IAM role', () => {
176
199
  template.hasResourceProperties('AWS::IAM::Role', {
@@ -280,6 +303,8 @@ describe('DomainStack', () => {
280
303
  const stack = new DomainStack(app, 'TestDomainStackMethods', {
281
304
  registry: multiMethodRegistry,
282
305
  eventBusArn,
306
+ projectId: 'Test',
307
+ envCode: 'Dev',
283
308
  userPoolArn,
284
309
  userPoolClientId,
285
310
  });
@@ -302,6 +327,8 @@ describe('DomainStack', () => {
302
327
  const stack = new DomainStack(app, 'TestDomainStackRouteAuth', {
303
328
  registry: multiMethodRegistry,
304
329
  eventBusArn,
330
+ projectId: 'Test',
331
+ envCode: 'Dev',
305
332
  userPoolArn,
306
333
  userPoolClientId,
307
334
  });
@@ -325,6 +352,8 @@ describe('DomainStack', () => {
325
352
  const stack = new DomainStack(app, 'TestDomainStackUnauthRoute', {
326
353
  registry: multiMethodRegistry,
327
354
  eventBusArn,
355
+ projectId: 'Test',
356
+ envCode: 'Dev',
328
357
  userPoolArn,
329
358
  userPoolClientId,
330
359
  });
@@ -340,6 +369,8 @@ describe('DomainStack', () => {
340
369
  const stack = new DomainStack(app, 'TestDomainStackMissingPool', {
341
370
  registry: multiMethodRegistry,
342
371
  eventBusArn,
372
+ projectId: 'Test',
373
+ envCode: 'Dev',
343
374
  // No userPoolArn / userPoolId / userPoolClientId provided
344
375
  });
345
376
  // `Annotations.of(stack).errors` is not exposed; read the construct's
@@ -372,6 +403,8 @@ describe('DomainStack', () => {
372
403
  const stack = new DomainStack(app, 'TestDomainStackNoJwtNeeded', {
373
404
  registry: noJwtRegistry,
374
405
  eventBusArn,
406
+ projectId: 'Test',
407
+ envCode: 'Dev',
375
408
  });
376
409
  const metadata = stack.node.metadata;
377
410
  const errorMessages = metadata
@@ -445,6 +478,8 @@ describe('DomainStack', () => {
445
478
  const stack = new DomainStack(app, 'TestDomainStackActionRoutes', {
446
479
  registry: registryWithActions,
447
480
  eventBusArn,
481
+ projectId: 'Test',
482
+ envCode: 'Dev',
448
483
  userPoolArn: 'arn:aws:cognito-idp:eu-north-1:123456789012:userpool/eu-north-1_abc123xyz',
449
484
  userPoolClientId: 'test-client-id',
450
485
  });
@@ -459,6 +494,8 @@ describe('DomainStack', () => {
459
494
  const stack = new DomainStack(app, 'TestDomainStackInternalOnly', {
460
495
  registry: registryWithActions,
461
496
  eventBusArn,
497
+ projectId: 'Test',
498
+ envCode: 'Dev',
462
499
  userPoolArn: 'arn:aws:cognito-idp:eu-north-1:123456789012:userpool/eu-north-1_abc123xyz',
463
500
  userPoolClientId: 'test-client-id',
464
501
  });
@@ -472,6 +509,8 @@ describe('DomainStack', () => {
472
509
  const stack = new DomainStack(app, 'TestDomainStackActionJwt', {
473
510
  registry: registryWithActions,
474
511
  eventBusArn,
512
+ projectId: 'Test',
513
+ envCode: 'Dev',
475
514
  userPoolArn: 'arn:aws:cognito-idp:eu-north-1:123456789012:userpool/eu-north-1_abc123xyz',
476
515
  userPoolClientId: 'test-client-id',
477
516
  });
@@ -1,5 +1,5 @@
1
1
  import { describe, it, expect } from 'vitest';
2
- import { buildDedicatedEntryContent, ADAPTER_BY_PRIMITIVE, EXPOSED_ACTION_ADAPTER, } from '../grouped-lambda-factory.js';
2
+ import { buildDedicatedEntryContent, buildGroupedApiActionEntryContent, ADAPTER_BY_PRIMITIVE, EXPOSED_ACTION_ADAPTER, } from '../grouped-lambda-factory.js';
3
3
  /**
4
4
  * Wave 7 Task 7.3 (#4619) — narrow, pure tests for the dedicated-mode
5
5
  * Lambda entry-content generator.
@@ -143,4 +143,25 @@ describe('buildDedicatedEntryContent (Wave 7 Task 7.3, #4619)', () => {
143
143
  expect(EXPOSED_ACTION_ADAPTER).toBe('createExposedActionApiHandler');
144
144
  });
145
145
  });
146
+ describe('buildGroupedApiActionEntryContent', () => {
147
+ it('generates a single entry that imports all API actions and dispatches by routeKey', () => {
148
+ const entries = [
149
+ { id: 'whoami', handlerFile: 'actions/whoami.ts', method: 'GET', routePath: '/auth/v1/auth/whoami' },
150
+ { id: 'register-sys-admin', handlerFile: 'actions/register-sys-admin.ts', method: 'POST', routePath: '/auth/v1/auth/register-sys-admin' },
151
+ ];
152
+ const content = buildGroupedApiActionEntryContent('auth', entries, '/tmp/entry', '/repo/domains/auth');
153
+ // Imports createExposedActionApiHandler from the runtime
154
+ expect(content).toContain("import { createExposedActionApiHandler } from '@mettlecast/domain-runtime'");
155
+ // Imports each action
156
+ expect(content).toContain('import { whoami } from');
157
+ expect(content).toContain('import { registerSysAdmin } from');
158
+ // Route handlers keyed by routeKey
159
+ expect(content).toContain('"GET /auth/v1/auth/whoami"');
160
+ expect(content).toContain('"POST /auth/v1/auth/register-sys-admin"');
161
+ // Dispatcher reads routeKey from event
162
+ expect(content).toContain('event.requestContext?.routeKey');
163
+ // 404 fallback
164
+ expect(content).toContain('statusCode: 404');
165
+ });
166
+ });
146
167
  });
@@ -1,4 +1,5 @@
1
1
  import * as lambda from 'aws-cdk-lib/aws-lambda';
2
+ import * as lambdaNode from 'aws-cdk-lib/aws-lambda-nodejs';
2
3
  import * as ec2 from 'aws-cdk-lib/aws-ec2';
3
4
  import { Construct } from 'constructs';
4
5
  /** Primitive types that can be grouped into a single Lambda. */
@@ -115,3 +116,32 @@ export declare function buildDedicatedEntryContent(handlerImportPath: string, en
115
116
  * Grouped mode retains Code.fromAsset for backward compatibility.
116
117
  */
117
118
  export declare function createGroupedLambdas(scope: Construct, props: GroupedLambdaProps): lambda.Function[];
119
+ /** Entry for a single API-exposed action within a grouped Lambda. */
120
+ export interface ApiActionRouteEntry {
121
+ id: string;
122
+ handlerFile: string;
123
+ method: string;
124
+ /** Full HTTP route path including the domain prefix (e.g. /auth/v1/auth/whoami). */
125
+ routePath: string;
126
+ }
127
+ /**
128
+ * Pure entry-content generator for the grouped API-action Lambda.
129
+ *
130
+ * Generates a single TypeScript entry that imports all API-exposed actions,
131
+ * pre-creates per-action HTTP handlers via `createExposedActionApiHandler`,
132
+ * and dispatches by `event.requestContext.routeKey`.
133
+ *
134
+ * Exported so unit tests can assert on the generated content without
135
+ * instantiating CDK or esbuild.
136
+ */
137
+ export declare function buildGroupedApiActionEntryContent(domainId: string, entries: ApiActionRouteEntry[], entryDir: string, domainRoot: string): string;
138
+ /**
139
+ * Creates a single grouped Lambda for all API-exposed actions in a domain.
140
+ *
141
+ * Uses NodejsFunction (esbuild on-the-fly) with a generated multi-action entry
142
+ * that dispatches by `event.requestContext.routeKey`. All HTTP API routes for
143
+ * the domain's API actions point to this one Lambda.
144
+ */
145
+ export declare function createGroupedApiActionLambda(scope: Construct, props: Omit<GroupedLambdaProps, 'handlerEntries' | 'primitiveType' | 'dedicated'> & {
146
+ apiEntries: ApiActionRouteEntry[];
147
+ }): lambdaNode.NodejsFunction;
@@ -226,3 +226,96 @@ function toLogRetention(days) {
226
226
  };
227
227
  return map[days] ?? logs.RetentionDays.ONE_MONTH;
228
228
  }
229
+ /**
230
+ * Pure entry-content generator for the grouped API-action Lambda.
231
+ *
232
+ * Generates a single TypeScript entry that imports all API-exposed actions,
233
+ * pre-creates per-action HTTP handlers via `createExposedActionApiHandler`,
234
+ * and dispatches by `event.requestContext.routeKey`.
235
+ *
236
+ * Exported so unit tests can assert on the generated content without
237
+ * instantiating CDK or esbuild.
238
+ */
239
+ export function buildGroupedApiActionEntryContent(domainId, entries, entryDir, domainRoot) {
240
+ const lines = [
241
+ `import { createExposedActionApiHandler } from '@mettlecast/domain-runtime';`,
242
+ ];
243
+ // Import each action handler
244
+ for (const entry of entries) {
245
+ const exportName = camelCase(entry.id);
246
+ const absPath = join(domainRoot, entry.handlerFile);
247
+ let rel = relative(entryDir, absPath).replace(/\\/g, '/');
248
+ if (!rel.startsWith('.'))
249
+ rel = `./${rel}`;
250
+ lines.push(`import { ${exportName} } from '${rel}';`);
251
+ }
252
+ lines.push('');
253
+ // Build the action registry (for ctx.actions cross-domain calls)
254
+ const registryEntries = entries
255
+ .map(e => `${JSON.stringify(e.id)}: ${camelCase(e.id)}`)
256
+ .join(', ');
257
+ lines.push(`const domainId = ${JSON.stringify(domainId)};`);
258
+ lines.push(`const actionRegistry = { [domainId]: { ${registryEntries} } };`);
259
+ lines.push('');
260
+ // Pre-create per-route handlers
261
+ lines.push('const routeHandlers: Record<string, (event: any) => Promise<any>> = {');
262
+ for (const entry of entries) {
263
+ const exportName = camelCase(entry.id);
264
+ const routeKey = `${entry.method} ${entry.routePath}`;
265
+ lines.push(` ${JSON.stringify(routeKey)}: createExposedActionApiHandler(${exportName}, { definingDomain: domainId, domainId, actionRegistry, callerDomainId: domainId }),`);
266
+ }
267
+ lines.push('};');
268
+ lines.push('');
269
+ // Dispatcher
270
+ lines.push('export const handler = async (event: any) => {', ' const routeKey = event.requestContext?.routeKey;', ' const matched = routeHandlers[routeKey];', ' if (!matched) {', ' return { statusCode: 404, headers: { "Content-Type": "application/json" }, body: JSON.stringify({ message: "Not Found" }) };', ' }', ' return matched(event);', '};');
271
+ return lines.join('\n');
272
+ }
273
+ /**
274
+ * Creates a single grouped Lambda for all API-exposed actions in a domain.
275
+ *
276
+ * Uses NodejsFunction (esbuild on-the-fly) with a generated multi-action entry
277
+ * that dispatches by `event.requestContext.routeKey`. All HTTP API routes for
278
+ * the domain's API actions point to this one Lambda.
279
+ */
280
+ export function createGroupedApiActionLambda(scope, props) {
281
+ if (!props.domainRoot)
282
+ throw new Error('domainRoot is required for createGroupedApiActionLambda');
283
+ const vpcConfig = props.vpc
284
+ ? {
285
+ vpc: props.vpc,
286
+ securityGroups: props.securityGroups,
287
+ ...(props.subnetSelection ? { vpcSubnets: props.subnetSelection } : {}),
288
+ }
289
+ : {};
290
+ const logRetention = toLogRetention(props.logRetentionDays ?? 30);
291
+ const powertoolsLayerArn = `arn:aws:lambda:${cdk.Stack.of(scope).region}:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:26`;
292
+ const serviceName = `${props.domainId}-action-api`;
293
+ const entryDir = createTempEntryDir();
294
+ const entryPath = join(entryDir, 'entry.ts');
295
+ const entryContent = buildGroupedApiActionEntryContent(props.domainId, props.apiEntries, entryDir, props.domainRoot);
296
+ writeFileSync(entryPath, entryContent, 'utf8');
297
+ const powertoolsLayer = lambda.LayerVersion.fromLayerVersionArn(scope, `PowertoolsLayer${props.domainId}-action-api`, powertoolsLayerArn);
298
+ return new lambdaNode.NodejsFunction(scope, `${props.domainId}-action-api`, {
299
+ runtime: lambda.Runtime.NODEJS_22_X,
300
+ architecture: lambda.Architecture.ARM_64,
301
+ entry: entryPath,
302
+ handler: 'handler',
303
+ layers: [powertoolsLayer],
304
+ bundling: {
305
+ minify: true,
306
+ sourceMap: true,
307
+ externalModules: ['@aws-sdk/*'],
308
+ },
309
+ environment: {
310
+ ...props.environment,
311
+ POWERTOOLS_SERVICE_NAME: serviceName,
312
+ POWERTOOLS_LOG_LEVEL: 'INFO',
313
+ TIB_EVENT_BUS_ARN: props.eventBusArn,
314
+ },
315
+ timeout: cdk.Duration.seconds(30),
316
+ memorySize: 256,
317
+ reservedConcurrentExecutions: props.reservedConcurrency,
318
+ logRetention,
319
+ ...vpcConfig,
320
+ });
321
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mettlecast/domain-cdk-packer",
3
- "version": "0.2.91",
3
+ "version": "0.2.93",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org",