@mettlecast/domain-cdk-packer 0.2.0

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 (66) hide show
  1. package/README.md +83 -0
  2. package/dist/DomainStack.d.ts +68 -0
  3. package/dist/DomainStack.js +567 -0
  4. package/dist/__tests__/domain-stack.test.d.ts +1 -0
  5. package/dist/__tests__/domain-stack.test.js +223 -0
  6. package/dist/__tests__/lambda-factory.test.d.ts +1 -0
  7. package/dist/__tests__/lambda-factory.test.js +76 -0
  8. package/dist/__tests__/pack-flows.test.d.ts +1 -0
  9. package/dist/__tests__/pack-flows.test.js +283 -0
  10. package/dist/__tests__/registry.test.d.ts +1 -0
  11. package/dist/__tests__/registry.test.js +34 -0
  12. package/dist/__tests__/step-functions-codegen.test.d.ts +1 -0
  13. package/dist/__tests__/step-functions-codegen.test.js +159 -0
  14. package/dist/aspects/iam-boundaries-aspect.d.ts +11 -0
  15. package/dist/aspects/iam-boundaries-aspect.js +15 -0
  16. package/dist/aspects/index.d.ts +5 -0
  17. package/dist/aspects/index.js +3 -0
  18. package/dist/aspects/log-retention-aspect.d.ts +8 -0
  19. package/dist/aspects/log-retention-aspect.js +24 -0
  20. package/dist/aspects/tagging-aspect.d.ts +13 -0
  21. package/dist/aspects/tagging-aspect.js +17 -0
  22. package/dist/constructs/action-construct.d.ts +35 -0
  23. package/dist/constructs/action-construct.js +35 -0
  24. package/dist/constructs/alarm-construct.d.ts +19 -0
  25. package/dist/constructs/alarm-construct.js +58 -0
  26. package/dist/constructs/alarms-construct.d.ts +17 -0
  27. package/dist/constructs/alarms-construct.js +42 -0
  28. package/dist/constructs/api-construct.d.ts +30 -0
  29. package/dist/constructs/api-construct.js +64 -0
  30. package/dist/constructs/canary-construct.d.ts +13 -0
  31. package/dist/constructs/canary-construct.js +30 -0
  32. package/dist/constructs/cmk-construct.d.ts +9 -0
  33. package/dist/constructs/cmk-construct.js +20 -0
  34. package/dist/constructs/dashboard-construct.d.ts +15 -0
  35. package/dist/constructs/dashboard-construct.js +62 -0
  36. package/dist/constructs/health-construct.d.ts +11 -0
  37. package/dist/constructs/health-construct.js +29 -0
  38. package/dist/constructs/job-construct.d.ts +33 -0
  39. package/dist/constructs/job-construct.js +54 -0
  40. package/dist/constructs/schedule-construct.d.ts +27 -0
  41. package/dist/constructs/schedule-construct.js +54 -0
  42. package/dist/constructs/subscriber-construct.d.ts +30 -0
  43. package/dist/constructs/subscriber-construct.js +63 -0
  44. package/dist/constructs/waf-construct.d.ts +13 -0
  45. package/dist/constructs/waf-construct.js +75 -0
  46. package/dist/constructs/webhook-construct.d.ts +33 -0
  47. package/dist/constructs/webhook-construct.js +50 -0
  48. package/dist/flow-registry.d.ts +81 -0
  49. package/dist/flow-registry.js +2 -0
  50. package/dist/grouped-lambda-factory.d.ts +43 -0
  51. package/dist/grouped-lambda-factory.js +71 -0
  52. package/dist/iam/iam-policy-builder.d.ts +95 -0
  53. package/dist/iam/iam-policy-builder.js +232 -0
  54. package/dist/index.d.ts +36 -0
  55. package/dist/index.js +17 -0
  56. package/dist/lambda-factory.d.ts +46 -0
  57. package/dist/lambda-factory.js +80 -0
  58. package/dist/pack-domain.d.ts +35 -0
  59. package/dist/pack-domain.js +32 -0
  60. package/dist/pack-flows.d.ts +28 -0
  61. package/dist/pack-flows.js +154 -0
  62. package/dist/registry.d.ts +224 -0
  63. package/dist/registry.js +1 -0
  64. package/dist/step-functions-codegen.d.ts +65 -0
  65. package/dist/step-functions-codegen.js +55 -0
  66. package/package.json +36 -0
@@ -0,0 +1,43 @@
1
+ import * as lambda from 'aws-cdk-lib/aws-lambda';
2
+ import * as ec2 from 'aws-cdk-lib/aws-ec2';
3
+ import { Construct } from 'constructs';
4
+ /** Primitive types that can be grouped into a single Lambda. */
5
+ export type PrimitiveType = 'api' | 'subscriber' | 'schedule' | 'job' | 'webhook' | 'action';
6
+ /** A single handler entry within a grouped Lambda. */
7
+ export interface HandlerEntry {
8
+ /** Unique handler ID within the domain + primitive type. */
9
+ id: string;
10
+ /** Path to the handler file relative to the domain's dist directory. */
11
+ handlerFile: string;
12
+ }
13
+ /** Props for creating grouped or dedicated Lambdas for a primitive type. */
14
+ export interface GroupedLambdaProps {
15
+ /** Domain ID this Lambda belongs to. */
16
+ domainId: string;
17
+ /** The primitive type being handled (api, subscriber, etc.). */
18
+ primitiveType: PrimitiveType;
19
+ /** All handler entries for this primitive type within the domain. */
20
+ handlerEntries: HandlerEntry[];
21
+ /** Environment variables injected into the Lambda(s). */
22
+ environment: Record<string, string>;
23
+ /** ARN of the project-scoped EventBridge bus. */
24
+ eventBusArn: string;
25
+ /** VPC to place Lambdas in — required for Aurora connectivity. */
26
+ vpc?: ec2.IVpc;
27
+ /** Security groups to attach to the Lambda(s). */
28
+ securityGroups?: ec2.ISecurityGroup[];
29
+ /** When true, creates one dedicated Lambda per handler instead of a single grouped Lambda. */
30
+ dedicated?: boolean;
31
+ /** Reserved concurrency for all Lambdas in this group. If omitted, no limit. */
32
+ reservedConcurrency?: number;
33
+ /** Log retention in days. Default: 30. */
34
+ logRetentionDays?: number;
35
+ }
36
+ /**
37
+ * Creates either a single grouped Lambda (default) or per-handler dedicated Lambdas.
38
+ *
39
+ * Grouped Lambdas use an internal dispatch router: TIB_HANDLER_MAP lists all handler IDs,
40
+ * and the incoming event/request carries a handler ID to route to the correct function.
41
+ * When dedicated=true (escape hatch for hot/critical handlers), each handler gets its own Lambda.
42
+ */
43
+ export declare function createGroupedLambdas(scope: Construct, props: GroupedLambdaProps): lambda.Function[];
@@ -0,0 +1,71 @@
1
+ import * as lambda from 'aws-cdk-lib/aws-lambda';
2
+ import * as logs from 'aws-cdk-lib/aws-logs';
3
+ import * as cdk from 'aws-cdk-lib';
4
+ /**
5
+ * Creates either a single grouped Lambda (default) or per-handler dedicated Lambdas.
6
+ *
7
+ * Grouped Lambdas use an internal dispatch router: TIB_HANDLER_MAP lists all handler IDs,
8
+ * and the incoming event/request carries a handler ID to route to the correct function.
9
+ * When dedicated=true (escape hatch for hot/critical handlers), each handler gets its own Lambda.
10
+ */
11
+ export function createGroupedLambdas(scope, props) {
12
+ const vpcConfig = props.vpc ? { vpc: props.vpc, securityGroups: props.securityGroups } : {};
13
+ const logRetention = toLogRetention(props.logRetentionDays ?? 30);
14
+ const powertoolsLayerArn = `arn:aws:lambda:${cdk.Stack.of(scope).region}:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:26`;
15
+ if (props.dedicated) {
16
+ return props.handlerEntries.map(entry => {
17
+ const powertoolsLayer = lambda.LayerVersion.fromLayerVersionArn(scope, `PowertoolsLayer${props.domainId}-${props.primitiveType}-${entry.id}`, powertoolsLayerArn);
18
+ return new lambda.Function(scope, `${props.domainId}-${props.primitiveType}-${entry.id}`, {
19
+ runtime: lambda.Runtime.NODEJS_22_X,
20
+ architecture: lambda.Architecture.ARM_64,
21
+ handler: 'index.handler',
22
+ code: lambda.Code.fromAsset(`dist/domains/${props.domainId}/${props.primitiveType}/${entry.id}`),
23
+ layers: [powertoolsLayer],
24
+ environment: {
25
+ ...props.environment,
26
+ POWERTOOLS_SERVICE_NAME: `${props.domainId}-${props.primitiveType}`,
27
+ POWERTOOLS_LOG_LEVEL: 'INFO',
28
+ TIB_HANDLER_ID: entry.id,
29
+ TIB_EVENT_BUS_ARN: props.eventBusArn,
30
+ },
31
+ timeout: cdk.Duration.seconds(30),
32
+ memorySize: 256,
33
+ reservedConcurrentExecutions: props.reservedConcurrency,
34
+ logRetention,
35
+ ...vpcConfig,
36
+ });
37
+ });
38
+ }
39
+ // Single grouped Lambda — all handlers for this primitive type bundled together
40
+ const powertoolsLayer = lambda.LayerVersion.fromLayerVersionArn(scope, `PowertoolsLayer${props.domainId}-${props.primitiveType}`, powertoolsLayerArn);
41
+ return [
42
+ new lambda.Function(scope, `${props.domainId}-${props.primitiveType}`, {
43
+ runtime: lambda.Runtime.NODEJS_22_X,
44
+ architecture: lambda.Architecture.ARM_64,
45
+ handler: 'index.handler',
46
+ code: lambda.Code.fromAsset(`dist/domains/${props.domainId}/${props.primitiveType}`),
47
+ layers: [powertoolsLayer],
48
+ environment: {
49
+ ...props.environment,
50
+ POWERTOOLS_SERVICE_NAME: `${props.domainId}-${props.primitiveType}`,
51
+ POWERTOOLS_LOG_LEVEL: 'INFO',
52
+ TIB_HANDLER_MAP: JSON.stringify(props.handlerEntries.map(e => e.id)),
53
+ TIB_EVENT_BUS_ARN: props.eventBusArn,
54
+ },
55
+ timeout: cdk.Duration.seconds(30),
56
+ memorySize: 256,
57
+ reservedConcurrentExecutions: props.reservedConcurrency,
58
+ logRetention,
59
+ ...vpcConfig,
60
+ }),
61
+ ];
62
+ }
63
+ function toLogRetention(days) {
64
+ const map = {
65
+ 30: logs.RetentionDays.ONE_MONTH,
66
+ 90: logs.RetentionDays.THREE_MONTHS,
67
+ 365: logs.RetentionDays.ONE_YEAR,
68
+ 2557: logs.RetentionDays.SEVEN_YEARS,
69
+ };
70
+ return map[days] ?? logs.RetentionDays.ONE_MONTH;
71
+ }
@@ -0,0 +1,95 @@
1
+ import * as iam from 'aws-cdk-lib/aws-iam';
2
+ import type { RegistryEntryKind } from '../registry.js';
3
+ /**
4
+ * Parameters for webhook IAM policy construction.
5
+ */
6
+ export interface WebhookPolicyParams {
7
+ /** ARN of the DynamoDB deduplication table. */
8
+ dedupeTableArn: string;
9
+ }
10
+ /**
11
+ * Parameters for queue-based IAM policy construction (subscriber and job).
12
+ */
13
+ export interface QueuePolicyParams {
14
+ /** ARN of the SQS queue. */
15
+ queueArn: string;
16
+ /** ARN of the SQS dead-letter queue. */
17
+ dlqArn: string;
18
+ }
19
+ /**
20
+ * Parameters for storage IAM policy construction.
21
+ */
22
+ export interface StoragePolicyParams {
23
+ /** ARN of the DynamoDB table. */
24
+ tableArn: string;
25
+ /** ARN of the S3 bucket. */
26
+ bucketArn: string;
27
+ }
28
+ /**
29
+ * Generates least-privilege IAM policy statements per handler kind.
30
+ * Used by CDK constructs to build policies for Lambda execution roles.
31
+ */
32
+ export declare class IamPolicyBuilder {
33
+ /**
34
+ * Returns IAM policy statements for API handlers.
35
+ * @returns Array of policy statements for Secrets Manager and EventBridge access.
36
+ */
37
+ forApi(): iam.PolicyStatement[];
38
+ /**
39
+ * Returns IAM policy statements for webhook handlers.
40
+ * @param params - Webhook policy parameters including deduplication table ARN.
41
+ * @returns Array of policy statements for Secrets Manager, DynamoDB, and EventBridge access.
42
+ */
43
+ forWebhook(params: WebhookPolicyParams): iam.PolicyStatement[];
44
+ /**
45
+ * Returns IAM policy statements for event subscriber handlers.
46
+ * @param params - Queue policy parameters including queue and dead-letter queue ARNs.
47
+ * @returns Array of policy statements for SQS message receive/delete and DLQ send access.
48
+ */
49
+ forSubscriber(params: QueuePolicyParams): iam.PolicyStatement[];
50
+ /**
51
+ * Returns IAM policy statements for schedule (cron) handlers.
52
+ * @returns Array of policy statements for EventBridge and Secrets Manager access.
53
+ */
54
+ forSchedule(): iam.PolicyStatement[];
55
+ /**
56
+ * Returns IAM policy statements for background job handlers.
57
+ * @param params - Queue policy parameters including queue and dead-letter queue ARNs.
58
+ * @returns Array of policy statements for SQS message receive/delete and DLQ send access.
59
+ */
60
+ forJob(params: QueuePolicyParams): iam.PolicyStatement[];
61
+ /**
62
+ * Returns IAM policy statements for callable action handlers.
63
+ * @param crossDomainActionArns - Optional ARNs of other domain action Lambdas to invoke.
64
+ * @returns Array of policy statements for Secrets Manager and Lambda invoke access.
65
+ */
66
+ forAction(crossDomainActionArns?: string[]): iam.PolicyStatement[];
67
+ /**
68
+ * Returns IAM policy statements for storage (DynamoDB table and S3 bucket).
69
+ * @param params - Storage policy parameters including table and bucket ARNs.
70
+ * @returns Array of policy statements for DynamoDB and S3 access.
71
+ */
72
+ forStorage(params: StoragePolicyParams): iam.PolicyStatement[];
73
+ /**
74
+ * Returns IAM policy statements for the per-domain tenant-scoped role.
75
+ * These statements use ${aws:PrincipalTag/tenantId} conditions to restrict
76
+ * access to the current session's tenant only.
77
+ * @param params - Storage policy parameters including table and bucket ARNs.
78
+ * @returns Array of IAM policy statements with PrincipalTag conditions.
79
+ */
80
+ forTenantScopedStorage(params: StoragePolicyParams): iam.PolicyStatement[];
81
+ /**
82
+ * Returns IAM policy statements for Step Functions flow execution roles.
83
+ * Grants lambda:InvokeFunction on each domain-action Lambda the flow invokes.
84
+ * @param actionArns - Unique list of Lambda ARNs referenced by the flow's domain-action steps.
85
+ * @returns Array of policy statements (empty if no action ARNs).
86
+ */
87
+ forFlow(actionArns: string[]): iam.PolicyStatement[];
88
+ /**
89
+ * Returns IAM policy statements based on handler kind.
90
+ * @param kind - The registry entry kind discriminant.
91
+ * @param params - Optional parameters required for certain kinds (webhook, subscriber, job).
92
+ * @returns Array of policy statements appropriate for the handler kind.
93
+ */
94
+ forKind(kind: RegistryEntryKind, params?: WebhookPolicyParams | QueuePolicyParams): iam.PolicyStatement[];
95
+ }
@@ -0,0 +1,232 @@
1
+ import * as iam from 'aws-cdk-lib/aws-iam';
2
+ /**
3
+ * Generates least-privilege IAM policy statements per handler kind.
4
+ * Used by CDK constructs to build policies for Lambda execution roles.
5
+ */
6
+ export class IamPolicyBuilder {
7
+ /**
8
+ * Returns IAM policy statements for API handlers.
9
+ * @returns Array of policy statements for Secrets Manager and EventBridge access.
10
+ */
11
+ forApi() {
12
+ return [
13
+ new iam.PolicyStatement({
14
+ actions: ['secretsmanager:GetSecretValue'],
15
+ resources: ['*'],
16
+ }),
17
+ new iam.PolicyStatement({
18
+ actions: ['events:PutEvents'],
19
+ resources: ['*'],
20
+ }),
21
+ ];
22
+ }
23
+ /**
24
+ * Returns IAM policy statements for webhook handlers.
25
+ * @param params - Webhook policy parameters including deduplication table ARN.
26
+ * @returns Array of policy statements for Secrets Manager, DynamoDB, and EventBridge access.
27
+ */
28
+ forWebhook(params) {
29
+ return [
30
+ new iam.PolicyStatement({
31
+ actions: ['secretsmanager:GetSecretValue'],
32
+ resources: ['*'],
33
+ }),
34
+ new iam.PolicyStatement({
35
+ actions: ['dynamodb:PutItem', 'dynamodb:GetItem', 'dynamodb:DeleteItem'],
36
+ resources: [params.dedupeTableArn],
37
+ }),
38
+ new iam.PolicyStatement({
39
+ actions: ['events:PutEvents'],
40
+ resources: ['*'],
41
+ }),
42
+ ];
43
+ }
44
+ /**
45
+ * Returns IAM policy statements for event subscriber handlers.
46
+ * @param params - Queue policy parameters including queue and dead-letter queue ARNs.
47
+ * @returns Array of policy statements for SQS message receive/delete and DLQ send access.
48
+ */
49
+ forSubscriber(params) {
50
+ return [
51
+ new iam.PolicyStatement({
52
+ actions: ['sqs:ReceiveMessage', 'sqs:DeleteMessage', 'sqs:GetQueueAttributes'],
53
+ resources: [params.queueArn],
54
+ }),
55
+ new iam.PolicyStatement({
56
+ actions: ['sqs:SendMessage'],
57
+ resources: [params.dlqArn],
58
+ }),
59
+ ];
60
+ }
61
+ /**
62
+ * Returns IAM policy statements for schedule (cron) handlers.
63
+ * @returns Array of policy statements for EventBridge and Secrets Manager access.
64
+ */
65
+ forSchedule() {
66
+ return [
67
+ new iam.PolicyStatement({
68
+ actions: ['events:PutEvents'],
69
+ resources: ['*'],
70
+ }),
71
+ new iam.PolicyStatement({
72
+ actions: ['secretsmanager:GetSecretValue'],
73
+ resources: ['*'],
74
+ }),
75
+ ];
76
+ }
77
+ /**
78
+ * Returns IAM policy statements for background job handlers.
79
+ * @param params - Queue policy parameters including queue and dead-letter queue ARNs.
80
+ * @returns Array of policy statements for SQS message receive/delete and DLQ send access.
81
+ */
82
+ forJob(params) {
83
+ return [
84
+ new iam.PolicyStatement({
85
+ actions: ['sqs:ReceiveMessage', 'sqs:DeleteMessage', 'sqs:GetQueueAttributes'],
86
+ resources: [params.queueArn],
87
+ }),
88
+ new iam.PolicyStatement({
89
+ actions: ['sqs:SendMessage'],
90
+ resources: [params.dlqArn],
91
+ }),
92
+ ];
93
+ }
94
+ /**
95
+ * Returns IAM policy statements for callable action handlers.
96
+ * @param crossDomainActionArns - Optional ARNs of other domain action Lambdas to invoke.
97
+ * @returns Array of policy statements for Secrets Manager and Lambda invoke access.
98
+ */
99
+ forAction(crossDomainActionArns) {
100
+ const statements = [
101
+ new iam.PolicyStatement({
102
+ actions: ['secretsmanager:GetSecretValue'],
103
+ resources: ['*'],
104
+ }),
105
+ ];
106
+ if (crossDomainActionArns && crossDomainActionArns.length > 0) {
107
+ statements.push(new iam.PolicyStatement({
108
+ actions: ['lambda:InvokeFunction'],
109
+ resources: crossDomainActionArns,
110
+ }));
111
+ }
112
+ return statements;
113
+ }
114
+ /**
115
+ * Returns IAM policy statements for storage (DynamoDB table and S3 bucket).
116
+ * @param params - Storage policy parameters including table and bucket ARNs.
117
+ * @returns Array of policy statements for DynamoDB and S3 access.
118
+ */
119
+ forStorage(params) {
120
+ return [
121
+ new iam.PolicyStatement({
122
+ actions: ['dynamodb:GetItem', 'dynamodb:PutItem', 'dynamodb:DeleteItem', 'dynamodb:Query', 'dynamodb:UpdateItem'],
123
+ resources: [params.tableArn, `${params.tableArn}/index/*`],
124
+ }),
125
+ new iam.PolicyStatement({
126
+ actions: ['s3:GetObject', 's3:PutObject', 's3:DeleteObject'],
127
+ resources: [`${params.bucketArn}/*`],
128
+ }),
129
+ new iam.PolicyStatement({
130
+ actions: ['s3:ListBucket'],
131
+ resources: [params.bucketArn],
132
+ }),
133
+ new iam.PolicyStatement({
134
+ actions: ['s3:GetBucketLocation'],
135
+ resources: [params.bucketArn],
136
+ }),
137
+ ];
138
+ }
139
+ /**
140
+ * Returns IAM policy statements for the per-domain tenant-scoped role.
141
+ * These statements use ${aws:PrincipalTag/tenantId} conditions to restrict
142
+ * access to the current session's tenant only.
143
+ * @param params - Storage policy parameters including table and bucket ARNs.
144
+ * @returns Array of IAM policy statements with PrincipalTag conditions.
145
+ */
146
+ forTenantScopedStorage(params) {
147
+ return [
148
+ // DynamoDB item-level operations — restricted to current tenant's PK
149
+ new iam.PolicyStatement({
150
+ effect: iam.Effect.ALLOW,
151
+ actions: [
152
+ 'dynamodb:GetItem',
153
+ 'dynamodb:PutItem',
154
+ 'dynamodb:DeleteItem',
155
+ 'dynamodb:UpdateItem',
156
+ 'dynamodb:Query',
157
+ ],
158
+ resources: [params.tableArn, `${params.tableArn}/index/*`],
159
+ conditions: {
160
+ 'ForAllValues:StringEquals': {
161
+ 'dynamodb:LeadingKeys': ['${aws:PrincipalTag/tenantId}'],
162
+ },
163
+ },
164
+ }),
165
+ // S3 object operations — restricted to current tenant's prefix
166
+ new iam.PolicyStatement({
167
+ effect: iam.Effect.ALLOW,
168
+ actions: ['s3:GetObject', 's3:PutObject', 's3:DeleteObject'],
169
+ resources: [`${params.bucketArn}/\${aws:PrincipalTag/tenantId}/*`],
170
+ }),
171
+ // S3 bucket-level — list restricted to current tenant's prefix
172
+ new iam.PolicyStatement({
173
+ effect: iam.Effect.ALLOW,
174
+ actions: ['s3:ListBucket'],
175
+ resources: [params.bucketArn],
176
+ conditions: {
177
+ StringLike: {
178
+ 's3:prefix': ['${aws:PrincipalTag/tenantId}/*'],
179
+ },
180
+ },
181
+ }),
182
+ // S3 bucket location (no tenant scope needed; metadata-only)
183
+ new iam.PolicyStatement({
184
+ effect: iam.Effect.ALLOW,
185
+ actions: ['s3:GetBucketLocation'],
186
+ resources: [params.bucketArn],
187
+ }),
188
+ ];
189
+ }
190
+ /**
191
+ * Returns IAM policy statements for Step Functions flow execution roles.
192
+ * Grants lambda:InvokeFunction on each domain-action Lambda the flow invokes.
193
+ * @param actionArns - Unique list of Lambda ARNs referenced by the flow's domain-action steps.
194
+ * @returns Array of policy statements (empty if no action ARNs).
195
+ */
196
+ forFlow(actionArns) {
197
+ if (actionArns.length === 0)
198
+ return [];
199
+ return [
200
+ new iam.PolicyStatement({
201
+ actions: ['lambda:InvokeFunction'],
202
+ resources: actionArns,
203
+ }),
204
+ ];
205
+ }
206
+ /**
207
+ * Returns IAM policy statements based on handler kind.
208
+ * @param kind - The registry entry kind discriminant.
209
+ * @param params - Optional parameters required for certain kinds (webhook, subscriber, job).
210
+ * @returns Array of policy statements appropriate for the handler kind.
211
+ */
212
+ forKind(kind, params) {
213
+ switch (kind) {
214
+ case 'integration':
215
+ case 'event':
216
+ case 'domain':
217
+ return [];
218
+ case 'webhook':
219
+ return this.forWebhook(params);
220
+ case 'subscriber':
221
+ return this.forSubscriber(params);
222
+ case 'job':
223
+ return this.forJob(params);
224
+ case 'api':
225
+ return this.forApi();
226
+ case 'schedule':
227
+ return this.forSchedule();
228
+ case 'action':
229
+ return this.forAction();
230
+ }
231
+ }
232
+ }
@@ -0,0 +1,36 @@
1
+ export type { DomainRegistry, RegistryEntry, RegistryEntryKind, BaseRegistryEntry, SerialDeploymentConfig, ApiRegistryEntry, ApiVersionSnapshot, WebhookRegistryEntry, SubscriberRegistryEntry, ScheduleRegistryEntry, JobRegistryEntry, ActionRegistryEntry, IntegrationRegistryEntry, EventRegistryEntry, DomainRegistryEntry, SchemaSnapshot, } from './registry.js';
2
+ export { LambdaFactory } from './lambda-factory.js';
3
+ export type { LambdaFactoryProps } from './lambda-factory.js';
4
+ export { createGroupedLambdas } from './grouped-lambda-factory.js';
5
+ export type { PrimitiveType, HandlerEntry, GroupedLambdaProps } from './grouped-lambda-factory.js';
6
+ export { IamPolicyBuilder } from './iam/iam-policy-builder.js';
7
+ export type { WebhookPolicyParams, QueuePolicyParams } from './iam/iam-policy-builder.js';
8
+ export { ApiConstruct } from './constructs/api-construct.js';
9
+ export type { ApiConstructProps } from './constructs/api-construct.js';
10
+ export { WebhookConstruct } from './constructs/webhook-construct.js';
11
+ export type { WebhookConstructProps } from './constructs/webhook-construct.js';
12
+ export { SubscriberConstruct } from './constructs/subscriber-construct.js';
13
+ export type { SubscriberConstructProps } from './constructs/subscriber-construct.js';
14
+ export { ScheduleConstruct } from './constructs/schedule-construct.js';
15
+ export type { ScheduleConstructProps } from './constructs/schedule-construct.js';
16
+ export { JobConstruct } from './constructs/job-construct.js';
17
+ export type { JobConstructProps } from './constructs/job-construct.js';
18
+ export { ActionConstruct } from './constructs/action-construct.js';
19
+ export type { ActionConstructProps } from './constructs/action-construct.js';
20
+ export { CmkConstruct } from './constructs/cmk-construct.js';
21
+ export type { CmkConstructProps } from './constructs/cmk-construct.js';
22
+ export { WafConstruct } from './constructs/waf-construct.js';
23
+ export type { WafConstructProps } from './constructs/waf-construct.js';
24
+ export { AlarmConstruct } from './constructs/alarm-construct.js';
25
+ export type { AlarmConstructProps } from './constructs/alarm-construct.js';
26
+ export { CanaryConstruct } from './constructs/canary-construct.js';
27
+ export type { CanaryConstructProps } from './constructs/canary-construct.js';
28
+ export { DomainStack } from './DomainStack.js';
29
+ export type { DomainStackProps } from './DomainStack.js';
30
+ export { packDomain } from './pack-domain.js';
31
+ export type { PackDomainOptions } from './pack-domain.js';
32
+ export { StepFunctionsCodegen } from './step-functions-codegen.js';
33
+ export type { DomainActionFlowNode, StepFunctionsTaskState } from './step-functions-codegen.js';
34
+ export type { FlowRegistry, FlowRegistryEntry, SerialFlowStep, SerialDomainActionStep, SerialDomainApiStep, SerialDomainEventStep, SerialFlowControlStep } from './flow-registry.js';
35
+ export { FlowsStack, packFlows } from './pack-flows.js';
36
+ export type { PackFlowsOptions } from './pack-flows.js';
package/dist/index.js ADDED
@@ -0,0 +1,17 @@
1
+ export { LambdaFactory } from './lambda-factory.js';
2
+ export { createGroupedLambdas } from './grouped-lambda-factory.js';
3
+ export { IamPolicyBuilder } from './iam/iam-policy-builder.js';
4
+ export { ApiConstruct } from './constructs/api-construct.js';
5
+ export { WebhookConstruct } from './constructs/webhook-construct.js';
6
+ export { SubscriberConstruct } from './constructs/subscriber-construct.js';
7
+ export { ScheduleConstruct } from './constructs/schedule-construct.js';
8
+ export { JobConstruct } from './constructs/job-construct.js';
9
+ export { ActionConstruct } from './constructs/action-construct.js';
10
+ export { CmkConstruct } from './constructs/cmk-construct.js';
11
+ export { WafConstruct } from './constructs/waf-construct.js';
12
+ export { AlarmConstruct } from './constructs/alarm-construct.js';
13
+ export { CanaryConstruct } from './constructs/canary-construct.js';
14
+ export { DomainStack } from './DomainStack.js';
15
+ export { packDomain } from './pack-domain.js';
16
+ export { StepFunctionsCodegen } from './step-functions-codegen.js';
17
+ export { FlowsStack, packFlows } from './pack-flows.js';
@@ -0,0 +1,46 @@
1
+ import * as lambdaNode from 'aws-cdk-lib/aws-lambda-nodejs';
2
+ import { Construct } from 'constructs';
3
+ import type { BaseRegistryEntry, SerialDeploymentConfig, DomainRegistry } from './registry.js';
4
+ /**
5
+ * Configuration properties for LambdaFactory.
6
+ */
7
+ export interface LambdaFactoryProps {
8
+ /** Parent CDK scope */
9
+ scope: Construct;
10
+ /** Full domain registry */
11
+ registry: DomainRegistry;
12
+ /** Absolute path to domain root (= registry.domainRoot) */
13
+ domainRoot: string;
14
+ /** Extra env vars injected into all Lambdas */
15
+ sharedEnv?: Record<string, string>;
16
+ }
17
+ /**
18
+ * Factory for creating CDK NodejsFunction instances from domain registry entries with consistent defaults.
19
+ */
20
+ export declare class LambdaFactory {
21
+ private scope;
22
+ private registry;
23
+ private domainRoot;
24
+ private sharedEnv?;
25
+ /**
26
+ * Create a new LambdaFactory instance.
27
+ * @param props - Factory configuration
28
+ */
29
+ constructor(props: LambdaFactoryProps);
30
+ /**
31
+ * Convert a kebab-case or snake_case string to PascalCase.
32
+ * @param s - Input string
33
+ * @returns PascalCase string
34
+ */
35
+ private toPascalCase;
36
+ /**
37
+ * Create a NodejsFunction from a registry entry.
38
+ * @param entry - Registry entry with handlerFile property
39
+ * @param overrides - Optional deployment configuration overrides
40
+ * @param extraEnv - Optional extra environment variables
41
+ * @returns Created NodejsFunction
42
+ */
43
+ createFunction(entry: BaseRegistryEntry & {
44
+ handlerFile: string;
45
+ }, overrides?: SerialDeploymentConfig, extraEnv?: Record<string, string>): lambdaNode.NodejsFunction;
46
+ }
@@ -0,0 +1,80 @@
1
+ import * as cdk from 'aws-cdk-lib';
2
+ import * as lambda from 'aws-cdk-lib/aws-lambda';
3
+ import * as lambdaNode from 'aws-cdk-lib/aws-lambda-nodejs';
4
+ import * as logs from 'aws-cdk-lib/aws-logs';
5
+ import path from 'node:path';
6
+ /**
7
+ * Factory for creating CDK NodejsFunction instances from domain registry entries with consistent defaults.
8
+ */
9
+ export class LambdaFactory {
10
+ scope;
11
+ registry;
12
+ domainRoot;
13
+ sharedEnv;
14
+ /**
15
+ * Create a new LambdaFactory instance.
16
+ * @param props - Factory configuration
17
+ */
18
+ constructor(props) {
19
+ this.scope = props.scope;
20
+ this.registry = props.registry;
21
+ this.domainRoot = props.domainRoot;
22
+ this.sharedEnv = props.sharedEnv;
23
+ }
24
+ /**
25
+ * Convert a kebab-case or snake_case string to PascalCase.
26
+ * @param s - Input string
27
+ * @returns PascalCase string
28
+ */
29
+ toPascalCase(s) {
30
+ return s
31
+ .split(/[-_]/)
32
+ .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
33
+ .join('');
34
+ }
35
+ /**
36
+ * Create a NodejsFunction from a registry entry.
37
+ * @param entry - Registry entry with handlerFile property
38
+ * @param overrides - Optional deployment configuration overrides
39
+ * @param extraEnv - Optional extra environment variables
40
+ * @returns Created NodejsFunction
41
+ */
42
+ createFunction(entry, overrides, extraEnv) {
43
+ const merged = { ...this.registry.domain.defaultDeployment, ...overrides };
44
+ const architecture = merged.architecture === 'x86_64'
45
+ ? lambda.Architecture.X86_64
46
+ : lambda.Architecture.ARM_64;
47
+ const environment = {
48
+ DOMAIN_ID: this.registry.domain.id,
49
+ NODE_OPTIONS: '--enable-source-maps',
50
+ POWERTOOLS_SERVICE_NAME: `${this.registry.domain.id}-${entry.id}`,
51
+ POWERTOOLS_LOG_LEVEL: process.env['LOG_LEVEL'] ?? 'INFO',
52
+ ...this.sharedEnv,
53
+ ...extraEnv,
54
+ };
55
+ const fn = new lambdaNode.NodejsFunction(this.scope, `${this.toPascalCase(entry.id)}Fn`, {
56
+ runtime: lambda.Runtime.NODEJS_22_X,
57
+ architecture,
58
+ tracing: lambda.Tracing.ACTIVE,
59
+ logRetention: logs.RetentionDays.ONE_WEEK,
60
+ memorySize: merged.memory ?? 512,
61
+ timeout: cdk.Duration.seconds(merged.timeout ?? 30),
62
+ ...(merged.reservedConcurrency !== undefined
63
+ ? { reservedConcurrentExecutions: merged.reservedConcurrency }
64
+ : {}),
65
+ entry: path.join(this.domainRoot, entry.handlerFile),
66
+ handler: 'handler',
67
+ bundling: {
68
+ minify: true,
69
+ sourceMap: true,
70
+ sourceMapMode: lambdaNode.SourceMapMode.INLINE,
71
+ externalModules: ['@aws-sdk/*'],
72
+ },
73
+ environment,
74
+ });
75
+ const powertoolsLayerArn = `arn:aws:lambda:${cdk.Stack.of(this.scope).region}:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:26`;
76
+ const powertoolsLayer = lambda.LayerVersion.fromLayerVersionArn(this.scope, `PowertoolsLayer${this.toPascalCase(entry.id)}`, powertoolsLayerArn);
77
+ fn.addLayers(powertoolsLayer);
78
+ return fn;
79
+ }
80
+ }
@@ -0,0 +1,35 @@
1
+ import * as cdk from 'aws-cdk-lib';
2
+ import * as ec2 from 'aws-cdk-lib/aws-ec2';
3
+ import { DomainStack } from './DomainStack.js';
4
+ import type { DomainRegistry } from './registry.js';
5
+ /**
6
+ * Options for packDomain function.
7
+ */
8
+ export interface PackDomainOptions {
9
+ /** CDK environment (account + region). */
10
+ env?: cdk.Environment;
11
+ /** VPC to place domain Lambdas in — required for Aurora connectivity. */
12
+ vpc?: ec2.IVpc;
13
+ /** Security group for domain Lambdas. */
14
+ lambdaSg?: ec2.ISecurityGroup;
15
+ /** Cognito User Pool ARN — when provided, HTTP API routes are JWT-protected. */
16
+ userPoolArn?: string;
17
+ /** Cognito User Pool Client ID — required alongside userPoolArn for JWT authorizer. */
18
+ userPoolClientId?: string;
19
+ /** Database connection URL. */
20
+ databaseUrl?: string;
21
+ /** ARN of the RDS secret for DB credentials. */
22
+ dbSecretArn?: string;
23
+ }
24
+ /**
25
+ * Convenience entry-point: constructs a DomainStack from a compiled registry.
26
+ * Intended to be called from a CDK app entrypoint (e.g. bin/app.ts in the project's infra).
27
+ * Supports both old (env as 5th arg) and new (options object) calling conventions.
28
+ * @param registry - The compiled domain registry read from .mc/domain-registry.json.
29
+ * @param app - The CDK App instance.
30
+ * @param stackId - CloudFormation stack logical ID.
31
+ * @param eventBusArn - ARN of the named EventBridge event bus for event subscribers.
32
+ * @param options - Optional configuration including VPC, auth, and DB settings.
33
+ * @returns The constructed DomainStack.
34
+ */
35
+ export declare function packDomain(registry: DomainRegistry, app: cdk.App, stackId: string, eventBusArn: string, options?: PackDomainOptions | cdk.Environment): DomainStack;