@incloodsolutions/devkit 0.0.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.
package/dist/index.cjs ADDED
@@ -0,0 +1,881 @@
1
+ 'use strict';
2
+
3
+ var constructs = require('constructs');
4
+ var awsCdkLib = require('aws-cdk-lib');
5
+ var awsApigateway = require('aws-cdk-lib/aws-apigateway');
6
+ var toolkit = require('@incloodsolutions/toolkit');
7
+ var awsApigatewayv2Integrations = require('aws-cdk-lib/aws-apigatewayv2-integrations');
8
+ var awsApigatewayv2 = require('aws-cdk-lib/aws-apigatewayv2');
9
+ var awsCloudfront = require('aws-cdk-lib/aws-cloudfront');
10
+ var awsLogs = require('aws-cdk-lib/aws-logs');
11
+ var awsDynamodb = require('aws-cdk-lib/aws-dynamodb');
12
+ var awsEvents = require('aws-cdk-lib/aws-events');
13
+ var awsEventsTargets = require('aws-cdk-lib/aws-events-targets');
14
+ var awsApigatewayv2Authorizers = require('aws-cdk-lib/aws-apigatewayv2-authorizers');
15
+ var awsLambda = require('aws-cdk-lib/aws-lambda');
16
+ var awsIam = require('aws-cdk-lib/aws-iam');
17
+ var awsS3 = require('aws-cdk-lib/aws-s3');
18
+ var awsCloudfrontOrigins = require('aws-cdk-lib/aws-cloudfront-origins');
19
+ var awsS3Deployment = require('aws-cdk-lib/aws-s3-deployment');
20
+ var awsSns = require('aws-cdk-lib/aws-sns');
21
+ var awsSnsSubscriptions = require('aws-cdk-lib/aws-sns-subscriptions');
22
+ var awsSqs = require('aws-cdk-lib/aws-sqs');
23
+ var awsEc2 = require('aws-cdk-lib/aws-ec2');
24
+
25
+ var __defProp = Object.defineProperty;
26
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
27
+ var BaseApiGatewayConstruct = class _BaseApiGatewayConstruct extends constructs.Construct {
28
+ static {
29
+ __name(this, "BaseApiGatewayConstruct");
30
+ }
31
+ /** The created REST API instance */
32
+ api;
33
+ /** Enables debug logging for route creation */
34
+ enableDebug = false;
35
+ /**
36
+ * @param scope Parent construct
37
+ * @param id Unique construct identifier
38
+ * @param props Configuration for API, routes, and Lambda handler
39
+ */
40
+ constructor(scope, id, props) {
41
+ super(scope, id);
42
+ this.enableDebug = props.enableDebug;
43
+ this.api = new awsApigateway.RestApi(this, id, {
44
+ ...props?.options?.gatewayOptions,
45
+ /** Default API description if not provided */
46
+ description: props?.options?.gatewayOptions?.description || "This is a REST API using CDK",
47
+ /**
48
+ * CORS configuration
49
+ * Falls back to allowing all origins, methods, and standard headers
50
+ */
51
+ defaultCorsPreflightOptions: {
52
+ ...props?.options?.gatewayOptions?.defaultCorsPreflightOptions,
53
+ /** Allow all origins by default */
54
+ allowOrigins: props?.options?.gatewayOptions?.defaultCorsPreflightOptions?.allowOrigins || awsApigateway.Cors.ALL_ORIGINS,
55
+ /** Allow all HTTP methods by default */
56
+ allowMethods: props?.options?.gatewayOptions?.defaultCorsPreflightOptions?.allowMethods || awsApigateway.Cors.ALL_METHODS,
57
+ /** Merge default headers with user-defined headers */
58
+ allowHeaders: [
59
+ ...props.options?.gatewayOptions?.defaultCorsPreflightOptions?.allowHeaders,
60
+ "Content-Type",
61
+ "Accept",
62
+ "X-Amz-Date",
63
+ "Authorization",
64
+ "X-Api-Key",
65
+ "X-Amz-Security-Token",
66
+ "X-Amz-User-Agent"
67
+ ]
68
+ },
69
+ /** Minimum payload size (in bytes) before compression is applied */
70
+ minCompressionSize: props?.options?.gatewayOptions?.minCompressionSize || awsCdkLib.Size.bytes(1)
71
+ });
72
+ if (props?.options?.routeOptions?.length && props?.handlerFunction) {
73
+ const integration = new awsApigateway.LambdaIntegration(props.handlerFunction);
74
+ this.addRoutes(this.api.root, props.options.routeOptions, integration);
75
+ }
76
+ this.api.applyRemovalPolicy(awsCdkLib.RemovalPolicy.DESTROY);
77
+ new awsCdkLib.CfnOutput(this, "ApiGateway", {
78
+ value: this.api.url
79
+ });
80
+ }
81
+ /**
82
+ * Recursively attaches routes to the API Gateway
83
+ *
84
+ * Behaviour:
85
+ * - Creates a resource for each route segment
86
+ * - Attaches method + Lambda integration
87
+ * - Traverses child routes for nested paths
88
+ *
89
+ * @param parent Parent API resource
90
+ * @param routes Route definitions
91
+ * @param integration Lambda integration applied to each route
92
+ * @param previousPath Accumulated path (used for debug logging)
93
+ * @private
94
+ */
95
+ addRoutes(parent, routes, integration, previousPath) {
96
+ routes.forEach((route) => {
97
+ const currentPath = `${previousPath || ""}/${route.name}`;
98
+ const resource = parent.addResource(route.name);
99
+ resource.addMethod(route.method, integration);
100
+ if (route?.children.length) {
101
+ this.addRoutes(resource, route.children, integration, currentPath);
102
+ }
103
+ if (this.enableDebug) {
104
+ toolkit.printLog(_BaseApiGatewayConstruct.name, `Route created: ${route.method} ${currentPath}`);
105
+ }
106
+ });
107
+ }
108
+ };
109
+ var BaseApiGatewayV2Construct = class extends constructs.Construct {
110
+ static {
111
+ __name(this, "BaseApiGatewayV2Construct");
112
+ }
113
+ /** The created HTTP API instance */
114
+ api;
115
+ /** Enables debug logging (if used externally) */
116
+ enableDebug = false;
117
+ /**
118
+ * @param scope Parent construct
119
+ * @param id Unique construct identifier
120
+ * @param props Configuration for API, routes, and handlers
121
+ */
122
+ constructor(scope, id, props) {
123
+ super(scope, id);
124
+ this.enableDebug = props.enableDebug;
125
+ this.api = new awsApigatewayv2.HttpApi(this, id, {
126
+ ...props?.options?.gatewayOptions,
127
+ /** Default API description if not provided */
128
+ description: props?.options?.gatewayOptions?.description || "This is an Http API using CDK",
129
+ /**
130
+ * CORS configuration
131
+ * Falls back to allowing all methods and standard headers if not explicitly defined
132
+ */
133
+ corsPreflight: {
134
+ ...props.options?.gatewayOptions?.corsPreflight,
135
+ /** Allow all HTTP methods by default */
136
+ allowMethods: props.options?.gatewayOptions?.corsPreflight?.allowMethods || Object.values(awsApigatewayv2.CorsHttpMethod),
137
+ /** Merge default headers with user-defined headers */
138
+ allowHeaders: [
139
+ "Content-Type",
140
+ "Accept",
141
+ "X-Amz-Date",
142
+ "Authorization",
143
+ "X-Api-Key",
144
+ "X-Amz-Security-Token",
145
+ "X-Amz-User-Agent",
146
+ ...props.options?.gatewayOptions?.corsPreflight?.allowHeaders || []
147
+ ]
148
+ }
149
+ });
150
+ if (!props?.handlerFunctions?.length) {
151
+ throw new toolkit.CustomException("Construct requires atleast one function");
152
+ }
153
+ if (props?.options?.routeOptions?.length) {
154
+ props.handlerFunctions.forEach((handlerFunc) => {
155
+ props?.options?.routeOptions.forEach((route) => {
156
+ this.api.addRoutes({
157
+ ...route,
158
+ /**
159
+ * Lambda integration for each route
160
+ */
161
+ integration: new awsApigatewayv2Integrations.HttpLambdaIntegration("routes", handlerFunc)
162
+ });
163
+ });
164
+ });
165
+ }
166
+ this.api.applyRemovalPolicy(awsCdkLib.RemovalPolicy.DESTROY);
167
+ new awsCdkLib.CfnOutput(this, "ApiGatewayV2", {
168
+ value: this.api.url
169
+ });
170
+ }
171
+ };
172
+ var BaseApiGatewayWebSocketConstruct = class extends constructs.Construct {
173
+ static {
174
+ __name(this, "BaseApiGatewayWebSocketConstruct");
175
+ }
176
+ /** The created WebSocket API instance */
177
+ socketApi;
178
+ /**
179
+ * @param scope Parent construct
180
+ * @param id Unique construct identifier
181
+ * @param props Configuration for API, stage, and route handlers
182
+ */
183
+ constructor(scope, id, props) {
184
+ super(scope, id);
185
+ this.socketApi = new awsApigatewayv2.WebSocketApi(this, id, {
186
+ ...props.options.webSocketApiOptions,
187
+ /**
188
+ * Route for connection establishment ($connect)
189
+ */
190
+ connectRouteOptions: {
191
+ ...props.handlers.connect?.option,
192
+ integration: new awsApigatewayv2Integrations.WebSocketLambdaIntegration("connectIntegration", props.handlers.connect.function)
193
+ },
194
+ /**
195
+ * Route for disconnection events ($disconnect)
196
+ */
197
+ disconnectRouteOptions: {
198
+ ...props.handlers.disconnect?.option,
199
+ integration: new awsApigatewayv2Integrations.WebSocketLambdaIntegration("disconnectIntegration", props.handlers.disconnect.function)
200
+ },
201
+ /**
202
+ * Default route for unmatched messages ($default)
203
+ */
204
+ defaultRouteOptions: {
205
+ ...props.handlers.default?.option,
206
+ integration: new awsApigatewayv2Integrations.WebSocketLambdaIntegration("defaultIntegration", props.handlers.default.function)
207
+ }
208
+ });
209
+ this.socketApi.addRoute("notifications", {
210
+ ...props.handlers.message?.option,
211
+ /** Lambda integration for message handling */
212
+ integration: new awsApigatewayv2Integrations.WebSocketLambdaIntegration("routes", props.handlers.message.function)
213
+ });
214
+ const webSocketStage = new awsApigatewayv2.WebSocketStage(this, `${id}_stage`, {
215
+ ...props.options?.webSocketStageOptions,
216
+ webSocketApi: this.socketApi,
217
+ autoDeploy: true
218
+ });
219
+ new awsCdkLib.CfnOutput(this, "WebSocketURL", {
220
+ value: webSocketStage.url
221
+ });
222
+ }
223
+ };
224
+ var BaseCloudfrontConstruct = class extends constructs.Construct {
225
+ static {
226
+ __name(this, "BaseCloudfrontConstruct");
227
+ }
228
+ /** The created CloudFront distribution instance */
229
+ distribution;
230
+ /**
231
+ * @param scope Parent construct
232
+ * @param id Unique construct identifier
233
+ * @param props Configuration for CloudFront distribution
234
+ */
235
+ constructor(scope, id, props) {
236
+ super(scope, id);
237
+ this.distribution = new awsCloudfront.Distribution(this, id, {
238
+ ...props.options?.cloudfrontOptions,
239
+ /**
240
+ * Default behaviour configuration
241
+ * Enforces HTTPS if not explicitly defined
242
+ */
243
+ defaultBehavior: {
244
+ ...props.options?.cloudfrontOptions?.defaultBehavior,
245
+ viewerProtocolPolicy: props.options?.cloudfrontOptions?.defaultBehavior?.viewerProtocolPolicy || awsCloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS
246
+ },
247
+ /**
248
+ * Error response configuration
249
+ *
250
+ * Adds SPA-friendly fallbacks:
251
+ * - 400, 403, 404 responses are redirected to index.html
252
+ */
253
+ errorResponses: [
254
+ ...props.options?.cloudfrontOptions?.errorResponses || [],
255
+ /** Handle 400 errors */
256
+ {
257
+ httpStatus: 400,
258
+ responseHttpStatus: 200,
259
+ responsePagePath: "/index.html",
260
+ ttl: awsCdkLib.Duration.days(1)
261
+ },
262
+ /** Handle 403 errors */
263
+ {
264
+ httpStatus: 403,
265
+ responseHttpStatus: 200,
266
+ responsePagePath: "/index.html",
267
+ ttl: awsCdkLib.Duration.days(1)
268
+ },
269
+ /** Handle 404 errors */
270
+ {
271
+ httpStatus: 404,
272
+ responseHttpStatus: 200,
273
+ responsePagePath: "/index.html",
274
+ ttl: awsCdkLib.Duration.days(1)
275
+ }
276
+ ]
277
+ });
278
+ }
279
+ };
280
+ var BaseCloudwatchLogGroupConstruct = class extends constructs.Construct {
281
+ static {
282
+ __name(this, "BaseCloudwatchLogGroupConstruct");
283
+ }
284
+ /** The created CloudWatch Log Group instance */
285
+ logGroup;
286
+ /**
287
+ * @param scope Parent construct
288
+ * @param id Unique construct identifier
289
+ * @param props Configuration for the log group
290
+ */
291
+ constructor(scope, id, props) {
292
+ super(scope, id);
293
+ this.logGroup = new awsLogs.LogGroup(this, id, {
294
+ ...props.options?.logGroupOptions,
295
+ /**
296
+ * Removal policy applied to the log group
297
+ * Defaults to DESTROY when not explicitly defined
298
+ */
299
+ removalPolicy: props?.options?.logGroupOptions?.removalPolicy || awsCdkLib.RemovalPolicy.DESTROY,
300
+ /**
301
+ * Log retention period
302
+ * Defaults to INFINITE when not explicitly defined
303
+ */
304
+ retention: props?.options?.logGroupOptions?.retention || awsLogs.RetentionDays.INFINITE
305
+ });
306
+ new awsCdkLib.CfnOutput(this, "CloudwatchArn", {
307
+ value: this.logGroup.logGroupArn
308
+ });
309
+ }
310
+ };
311
+ var BaseDynamoDBConstruct = class _BaseDynamoDBConstruct extends constructs.Construct {
312
+ static {
313
+ __name(this, "BaseDynamoDBConstruct");
314
+ }
315
+ /** Newly created DynamoDB table (null if importing existing table) */
316
+ table;
317
+ /** Imported DynamoDB table reference (null if creating new table) */
318
+ existingTable;
319
+ /** Enables debug logging */
320
+ enableDebug = false;
321
+ /**
322
+ * @param scope Parent construct
323
+ * @param id Unique construct identifier
324
+ * @param props Configuration for table creation or import
325
+ */
326
+ constructor(scope, id, props) {
327
+ super(scope, id);
328
+ this.enableDebug = props?.enableDebug;
329
+ if (props.options?.fromExistingTableName) {
330
+ this.table = null;
331
+ this.existingTable = awsDynamodb.Table.fromTableName(
332
+ this,
333
+ `${id}-RefName`,
334
+ props.options.fromExistingTableName
335
+ );
336
+ if (this.enableDebug) {
337
+ toolkit.printLog(
338
+ _BaseDynamoDBConstruct.name,
339
+ `Created Dynamo-DB table from existing using name ${props.options?.fromExistingTableName}`
340
+ );
341
+ }
342
+ } else if (props.options?.fromExistingTableArn) {
343
+ this.table = null;
344
+ this.existingTable = awsDynamodb.Table.fromTableArn(
345
+ this,
346
+ `${id}-RefArn`,
347
+ props.options.fromExistingTableArn
348
+ );
349
+ if (this.enableDebug) {
350
+ toolkit.printLog(
351
+ _BaseDynamoDBConstruct.name,
352
+ `Created Dynamo-DB table from existing using ARN`
353
+ );
354
+ }
355
+ } else if (props.options?.fromExistingTableAttributes) {
356
+ this.table = null;
357
+ this.existingTable = awsDynamodb.Table.fromTableAttributes(
358
+ this,
359
+ `${id}-RefAttributes`,
360
+ props.options.fromExistingTableAttributes
361
+ );
362
+ if (this.enableDebug) {
363
+ toolkit.printLog(
364
+ _BaseDynamoDBConstruct.name,
365
+ `Created Dynamo-DB table from existing attributes`
366
+ );
367
+ }
368
+ } else {
369
+ this.existingTable = null;
370
+ this.table = new awsDynamodb.Table(this, id, {
371
+ ...props.options?.tableOptions,
372
+ /**
373
+ * Billing mode defaults to PAY_PER_REQUEST if not provided
374
+ */
375
+ billingMode: props.options?.tableOptions?.billingMode || awsDynamodb.BillingMode.PAY_PER_REQUEST,
376
+ /**
377
+ * Deletion protection:
378
+ * - Uses explicit value if provided
379
+ * - Defaults to true in production stage
380
+ */
381
+ deletionProtection: props.options?.tableOptions?.deletionProtection === true || props.options?.tableOptions?.deletionProtection === false ? props.options.tableOptions.deletionProtection : props.stage === "production"
382
+ });
383
+ if (props.options?.globalSecondaryIndexes?.length) {
384
+ props.options.globalSecondaryIndexes.forEach((globalIndex) => {
385
+ this.table.addGlobalSecondaryIndex(globalIndex);
386
+ if (this.enableDebug) {
387
+ toolkit.printLog(
388
+ _BaseDynamoDBConstruct.name,
389
+ `Added GSI: ${globalIndex.indexName}`
390
+ );
391
+ }
392
+ });
393
+ }
394
+ if (props.options?.localSecondaryIndexes?.length) {
395
+ props.options.localSecondaryIndexes.forEach((localIndex) => {
396
+ this.table.addLocalSecondaryIndex(localIndex);
397
+ if (this.enableDebug) {
398
+ toolkit.printLog(
399
+ _BaseDynamoDBConstruct.name,
400
+ `Added LSI: ${localIndex.indexName}`
401
+ );
402
+ }
403
+ });
404
+ }
405
+ }
406
+ new awsCdkLib.CfnOutput(this, "DynamoDbArn", {
407
+ value: props.options?.fromExistingTableName || props.options?.fromExistingTableArn ? this.existingTable.tableArn : this.table.tableArn
408
+ });
409
+ }
410
+ };
411
+ var BaseEventBridgeConstruct = class extends constructs.Construct {
412
+ static {
413
+ __name(this, "BaseEventBridgeConstruct");
414
+ }
415
+ /** The created EventBridge rule instance */
416
+ eventSchedule;
417
+ /**
418
+ * @param scope Parent construct
419
+ * @param id Unique construct identifier
420
+ * @param props Configuration for rule and target functions
421
+ */
422
+ constructor(scope, id, props) {
423
+ super(scope, id);
424
+ this.eventSchedule = new awsEvents.Rule(this, id, {
425
+ ...props.options?.eventBridgeOptions,
426
+ /** Default description if not explicitly provided */
427
+ description: props?.options?.eventBridgeOptions?.description || "An Event-bridge rule"
428
+ });
429
+ if (props.options?.targetFunctions?.length) {
430
+ props.options.targetFunctions.forEach((targetFunction) => {
431
+ this.eventSchedule.addTarget(
432
+ /**
433
+ * Lambda target integration
434
+ */
435
+ new awsEventsTargets.LambdaFunction(targetFunction)
436
+ );
437
+ });
438
+ }
439
+ this.eventSchedule.applyRemovalPolicy(awsCdkLib.RemovalPolicy.DESTROY);
440
+ new awsCdkLib.CfnOutput(this, "EventBridgeArn", {
441
+ value: this.eventSchedule.ruleArn
442
+ });
443
+ }
444
+ };
445
+ var BaseLambdaAuthoriserConstruct = class extends constructs.Construct {
446
+ static {
447
+ __name(this, "BaseLambdaAuthoriserConstruct");
448
+ }
449
+ /** The created Token Authorizer instance */
450
+ authoriser;
451
+ /**
452
+ * @param scope Parent construct
453
+ * @param id Unique construct identifier
454
+ * @param props Configuration for authorizer and handler function
455
+ */
456
+ constructor(scope, id, props) {
457
+ super(scope, id);
458
+ this.authoriser = new awsApigateway.TokenAuthorizer(this, id, {
459
+ ...props.options?.authorizerOptions,
460
+ /**
461
+ * Lambda handler responsible for request authorization
462
+ */
463
+ handler: props.handlerFunction
464
+ });
465
+ new awsCdkLib.CfnOutput(this, "LambdaAuthorizerArn", {
466
+ value: this.authoriser.authorizerArn
467
+ });
468
+ }
469
+ };
470
+ var BaseLambdaAuthoriserV2Construct = class extends constructs.Construct {
471
+ static {
472
+ __name(this, "BaseLambdaAuthoriserV2Construct");
473
+ }
474
+ /** The created HTTP Lambda Authorizer instance */
475
+ authoriser;
476
+ /**
477
+ * @param scope Parent construct
478
+ * @param id Unique construct identifier
479
+ * @param props Configuration for authorizer and handler function
480
+ */
481
+ constructor(scope, id, props) {
482
+ super(scope, id);
483
+ this.authoriser = new awsApigatewayv2Authorizers.HttpLambdaAuthorizer(id, props.handlerFunction, {
484
+ ...props?.options?.authorizerOptions,
485
+ /**
486
+ * Identity sources used to extract credentials from incoming requests
487
+ * Defaults to Cookie and Authorization headers
488
+ */
489
+ identitySource: [
490
+ "$request.header.Cookie",
491
+ "$request.header.Authorization",
492
+ ...props?.options?.authorizerOptions?.identitySource
493
+ ],
494
+ /**
495
+ * Supported response types for the authorizer
496
+ * Defaults to IAM and SIMPLE responses
497
+ */
498
+ responseTypes: props?.options?.authorizerOptions?.responseTypes || [awsApigatewayv2Authorizers.HttpLambdaResponseType.IAM, awsApigatewayv2Authorizers.HttpLambdaResponseType.SIMPLE]
499
+ });
500
+ new awsCdkLib.CfnOutput(this, "LambdaAuthorizerV2_ID", {
501
+ value: this.authoriser.authorizerId
502
+ });
503
+ }
504
+ };
505
+ var BaseLambdaConstruct = class extends constructs.Construct {
506
+ static {
507
+ __name(this, "BaseLambdaConstruct");
508
+ }
509
+ /** The created Lambda function instance */
510
+ function;
511
+ /**
512
+ * @param scope Parent construct
513
+ * @param id Unique construct identifier
514
+ * @param props Configuration for Lambda function
515
+ */
516
+ constructor(scope, id, props) {
517
+ super(scope, id);
518
+ const environment = {
519
+ ...props.options?.lambdaOptions?.environment,
520
+ NODE_ENV: props.stage,
521
+ NODE_OPTIONS: "--enable-source-maps",
522
+ AWS_NODEJS_CONNECTION_REUSE_ENABLED: "1"
523
+ };
524
+ toolkit.detectDuplicateProperties({ data: environment });
525
+ this.function = new awsLambda.Function(this, id, {
526
+ ...props?.options?.lambdaOptions,
527
+ /**
528
+ * Lambda function name
529
+ * Defaults to "<stackName>-handler" if not provided
530
+ */
531
+ functionName: `${props?.options?.lambdaOptions?.functionName || props?.stackName}-handler`,
532
+ /**
533
+ * Function description
534
+ */
535
+ description: props?.options?.lambdaOptions?.description || "A lambda function",
536
+ /**
537
+ * Entry handler for the Lambda function
538
+ */
539
+ handler: props?.options?.lambdaOptions?.handler || "lambda.handler",
540
+ /**
541
+ * Runtime environment
542
+ */
543
+ runtime: props?.options?.lambdaOptions?.runtime || awsLambda.Runtime.NODEJS_24_X,
544
+ /**
545
+ * Execution timeout
546
+ * - 30 seconds in production
547
+ * - 15 seconds otherwise
548
+ */
549
+ timeout: props?.options?.lambdaOptions?.timeout || awsCdkLib.Duration.seconds(
550
+ props.stage === toolkit.AppEnvironmentEnum.PRODUCTION ? 30 : 15
551
+ ),
552
+ /**
553
+ * Memory allocation (in MB)
554
+ */
555
+ memorySize: props?.options?.lambdaOptions?.memorySize || 1024,
556
+ /**
557
+ * CPU architecture
558
+ */
559
+ architecture: props?.options?.lambdaOptions?.architecture || awsLambda.Architecture.ARM_64,
560
+ /**
561
+ * Lambda deployment package source
562
+ */
563
+ code: props?.options?.lambdaOptions?.code || awsLambda.Code.fromAsset("dist"),
564
+ /**
565
+ * Final merged environment variables
566
+ */
567
+ environment
568
+ });
569
+ new awsCdkLib.CfnOutput(this, "LambdaFunctionArn", {
570
+ value: this.function.functionArn
571
+ });
572
+ }
573
+ };
574
+ var BaseLambdaLayerConstruct = class extends constructs.Construct {
575
+ static {
576
+ __name(this, "BaseLambdaLayerConstruct");
577
+ }
578
+ /** Newly created Lambda Layer (null if importing existing layer) */
579
+ layer;
580
+ /** Imported Lambda Layer reference (null if creating new layer) */
581
+ existingLayer;
582
+ /**
583
+ * @param scope Parent construct
584
+ * @param id Unique construct identifier
585
+ * @param props Configuration for layer creation or import
586
+ */
587
+ constructor(scope, id, props) {
588
+ super(scope, id);
589
+ if (props?.options?.fromExistingLayerArn) {
590
+ this.existingLayer = awsLambda.LayerVersion.fromLayerVersionArn(
591
+ this,
592
+ `${id}-Arn`,
593
+ props?.options?.fromExistingLayerArn
594
+ );
595
+ } else if (props?.options?.fromExistingLayerAttribute) {
596
+ this.existingLayer = awsLambda.LayerVersion.fromLayerVersionAttributes(
597
+ this,
598
+ `${id}-Attribute`,
599
+ props?.options?.fromExistingLayerAttribute
600
+ );
601
+ } else {
602
+ this.layer = new awsLambda.LayerVersion(this, id, {
603
+ ...props.options?.layerOptions,
604
+ /**
605
+ * Default layer code asset
606
+ */
607
+ code: props?.options?.layerOptions?.code || awsLambda.Code.fromAsset("./dist-layer"),
608
+ /**
609
+ * Layer description
610
+ */
611
+ description: props?.options?.layerOptions?.description || "Lambda Layer written in NodeJS, NestJS, NodeJS-express, serverless-express",
612
+ /**
613
+ * Supported CPU architectures
614
+ */
615
+ compatibleArchitectures: [
616
+ awsLambda.Architecture.ARM_64,
617
+ awsLambda.Architecture.X86_64
618
+ ],
619
+ /**
620
+ * Supported runtimes
621
+ */
622
+ compatibleRuntimes: [
623
+ awsLambda.Runtime.NODEJS_22_X,
624
+ awsLambda.Runtime.NODEJS_24_X,
625
+ awsLambda.Runtime.NODEJS_LATEST
626
+ ]
627
+ });
628
+ }
629
+ new awsCdkLib.CfnOutput(this, "LambdaLayerArn", {
630
+ value: props.options?.fromExistingLayerArn || props.options?.fromExistingLayerAttribute ? this.existingLayer.layerVersionArn : this.layer.layerVersionArn
631
+ });
632
+ }
633
+ };
634
+ var BaseRolePolicyConstruct = class extends constructs.Construct {
635
+ static {
636
+ __name(this, "BaseRolePolicyConstruct");
637
+ }
638
+ /** The created IAM Role instance */
639
+ role;
640
+ /**
641
+ * @param scope Parent construct
642
+ * @param id Unique construct identifier
643
+ * @param props Configuration for role and policies
644
+ */
645
+ constructor(scope, id, props) {
646
+ super(scope, id);
647
+ this.role = new awsIam.Role(this, id, {
648
+ ...props.options?.roleOptions,
649
+ /**
650
+ * Managed policies attached to the role
651
+ * Defaults to AWSLambdaBasicExecutionRole if not provided
652
+ */
653
+ managedPolicies: props.options?.roleOptions?.managedPolicies ? props.options.roleOptions.managedPolicies : [
654
+ awsIam.ManagedPolicy.fromAwsManagedPolicyName(
655
+ "service-role/AWSLambdaBasicExecutionRole"
656
+ )
657
+ ]
658
+ });
659
+ if (props?.policies?.length) {
660
+ props.policies.forEach((policy) => {
661
+ this.role.addToPolicy(
662
+ /**
663
+ * Inline policy statement
664
+ */
665
+ new awsIam.PolicyStatement(policy)
666
+ );
667
+ });
668
+ }
669
+ this.role.applyRemovalPolicy(awsCdkLib.RemovalPolicy.DESTROY);
670
+ new awsCdkLib.CfnOutput(this, "RolePolicyArn", {
671
+ value: this.role.roleArn
672
+ });
673
+ }
674
+ };
675
+ var BaseS3Construct = class extends constructs.Construct {
676
+ static {
677
+ __name(this, "BaseS3Construct");
678
+ }
679
+ /** The created S3 bucket instance */
680
+ bucket;
681
+ /**
682
+ * @param scope Parent construct
683
+ * @param id Unique construct identifier
684
+ * @param props Configuration for S3 bucket
685
+ */
686
+ constructor(scope, id, props) {
687
+ super(scope, id);
688
+ this.bucket = new awsS3.Bucket(this, id, {
689
+ ...props.options?.bucketOptions,
690
+ /**
691
+ * Removal policy applied to the bucket
692
+ * Defaults to DESTROY if not explicitly defined
693
+ */
694
+ removalPolicy: props.options?.bucketOptions?.removalPolicy || awsCdkLib.RemovalPolicy.DESTROY
695
+ });
696
+ new awsCdkLib.CfnOutput(this, "S3BucketArn", {
697
+ value: this.bucket.bucketArn
698
+ });
699
+ }
700
+ };
701
+ var BaseS3DeploymentConstruct = class extends constructs.Construct {
702
+ static {
703
+ __name(this, "BaseS3DeploymentConstruct");
704
+ }
705
+ /** The created or provided S3 bucket */
706
+ bucket;
707
+ /** The created CloudFront distribution */
708
+ distribution;
709
+ /** S3 bucket deployment instance */
710
+ bucketDeployment;
711
+ /**
712
+ * @param scope Parent construct
713
+ * @param id Unique construct identifier
714
+ * @param props Configuration for bucket, distribution, and deployment
715
+ */
716
+ constructor(scope, id, props) {
717
+ super(scope, id);
718
+ if (!props.options?.cloudfrontOptions?.defaultBehavior?.origin && !props?.withS3Bucket && props.withCloudfront) {
719
+ throw new toolkit.CustomException("Cloudfront distribution S3_Bucket origins must be defined!");
720
+ }
721
+ if (!props.options?.bucketDeploymentOptions?.destinationBucket && !props?.withS3Bucket) {
722
+ throw new toolkit.CustomException("Deployment S3_Bucket destination must be defined!");
723
+ }
724
+ if (props?.withS3Bucket) {
725
+ this.bucket = new BaseS3Construct(this, "bucket", {
726
+ enableDebug: props.enableDebug,
727
+ options: { bucketOptions: props.options?.bucketOptions }
728
+ }).bucket;
729
+ }
730
+ if (props?.withCloudfront) {
731
+ const s3Origin = props.options?.cloudfrontOptions?.defaultBehavior?.origin || awsCloudfrontOrigins.S3BucketOrigin.withOriginAccessControl(this.bucket);
732
+ this.distribution = new BaseCloudfrontConstruct(this, "distribution", {
733
+ enableDebug: props.enableDebug,
734
+ options: {
735
+ cloudfrontOptions: {
736
+ ...props.options?.cloudfrontOptions,
737
+ /**
738
+ * Map additional behaviors and ensure origin is assigned
739
+ */
740
+ additionalBehaviors: Object.entries(props.options?.cloudfrontOptions?.additionalBehaviors || {}).reduce((behavior, [pattern, behaviorOptions]) => {
741
+ behavior[pattern] = {
742
+ ...behaviorOptions,
743
+ origin: behaviorOptions.origin || s3Origin
744
+ };
745
+ return behavior;
746
+ }, {}),
747
+ /**
748
+ * Default behavior configuration
749
+ */
750
+ defaultBehavior: {
751
+ ...props.options?.cloudfrontOptions?.defaultBehavior,
752
+ origin: s3Origin
753
+ }
754
+ }
755
+ }
756
+ }).distribution;
757
+ }
758
+ this.bucketDeployment = new awsS3Deployment.BucketDeployment(this, "deployment", {
759
+ ...props.options?.bucketDeploymentOptions,
760
+ /** Target distribution for cache invalidation */
761
+ distribution: props.options?.bucketDeploymentOptions?.distribution || this.distribution,
762
+ /** Paths to invalidate after deployment */
763
+ distributionPaths: props.options?.bucketDeploymentOptions?.distributionPaths || ["/*"],
764
+ /** Destination S3 bucket */
765
+ destinationBucket: props.options?.bucketDeploymentOptions?.destinationBucket || this.bucket
766
+ });
767
+ }
768
+ };
769
+ var BaseSnsConstruct = class extends constructs.Construct {
770
+ static {
771
+ __name(this, "BaseSnsConstruct");
772
+ }
773
+ /** The created SNS topic instance */
774
+ topic;
775
+ /**
776
+ * @param scope Parent construct
777
+ * @param id Unique construct identifier
778
+ * @param props Configuration for topic and subscriptions
779
+ */
780
+ constructor(scope, id, props) {
781
+ super(scope, id);
782
+ this.topic = new awsSns.Topic(this, id, props.options?.topicOptions);
783
+ if (props.options?.targetFunctions?.length) {
784
+ props.options.targetFunctions.forEach((targetFunction) => {
785
+ this.topic.addSubscription(
786
+ /**
787
+ * Lambda subscription target
788
+ */
789
+ new awsSnsSubscriptions.LambdaSubscription(targetFunction)
790
+ );
791
+ });
792
+ }
793
+ this.topic.applyRemovalPolicy(awsCdkLib.RemovalPolicy.DESTROY);
794
+ new awsCdkLib.CfnOutput(this, "SnsTopicArn", {
795
+ value: this.topic.topicArn
796
+ });
797
+ }
798
+ };
799
+ var BaseSqsConstruct = class extends constructs.Construct {
800
+ static {
801
+ __name(this, "BaseSqsConstruct");
802
+ }
803
+ /** The created SQS queue instance */
804
+ queue;
805
+ /**
806
+ * @param scope Parent construct
807
+ * @param id Unique construct identifier
808
+ * @param props Configuration for queue and Lambda consumers
809
+ */
810
+ constructor(scope, id, props) {
811
+ super(scope, id);
812
+ this.queue = new awsSqs.Queue(this, id, {
813
+ ...props?.options?.queueOptions,
814
+ /**
815
+ * Removal policy applied to the queue
816
+ * Defaults to DESTROY if not explicitly defined
817
+ */
818
+ removalPolicy: props?.options?.queueOptions?.removalPolicy || awsCdkLib.RemovalPolicy.DESTROY
819
+ });
820
+ if (props?.targetFunctions?.length) {
821
+ props.targetFunctions.forEach((targetFunction, index) => {
822
+ new awsLambda.EventSourceMapping(this, `${id}-eventSourceMap${index + 1}`, {
823
+ ...props?.options?.eventSourceMappingOptions,
824
+ /** Target Lambda function */
825
+ target: targetFunction,
826
+ /** Source SQS queue ARN */
827
+ eventSourceArn: this.queue.queueArn,
828
+ /**
829
+ * Retry attempts for failed batch processing
830
+ * Defaults to 3 if not explicitly defined
831
+ */
832
+ retryAttempts: props?.options?.eventSourceMappingOptions?.retryAttempts || 3
833
+ });
834
+ });
835
+ }
836
+ new awsCdkLib.CfnOutput(this, "SqsQueueArn", {
837
+ value: this.queue.queueArn
838
+ });
839
+ }
840
+ };
841
+ var BaseVpcConstruct = class extends constructs.Construct {
842
+ static {
843
+ __name(this, "BaseVpcConstruct");
844
+ }
845
+ /** The created VPC instance */
846
+ vpc;
847
+ /**
848
+ * @param scope Parent construct
849
+ * @param id Unique construct identifier
850
+ * @param props Configuration for VPC
851
+ */
852
+ constructor(scope, id, props) {
853
+ super(scope, id);
854
+ this.vpc = new awsEc2.Vpc(this, id, {
855
+ ...props.options.vpcOptions
856
+ });
857
+ new awsCdkLib.CfnOutput(this, "VpcArn", {
858
+ value: this.vpc.vpcArn
859
+ });
860
+ }
861
+ };
862
+
863
+ exports.BaseApiGatewayConstruct = BaseApiGatewayConstruct;
864
+ exports.BaseApiGatewayV2Construct = BaseApiGatewayV2Construct;
865
+ exports.BaseApiGatewayWebSocketConstruct = BaseApiGatewayWebSocketConstruct;
866
+ exports.BaseCloudfrontConstruct = BaseCloudfrontConstruct;
867
+ exports.BaseCloudwatchLogGroupConstruct = BaseCloudwatchLogGroupConstruct;
868
+ exports.BaseDynamoDBConstruct = BaseDynamoDBConstruct;
869
+ exports.BaseEventBridgeConstruct = BaseEventBridgeConstruct;
870
+ exports.BaseLambdaAuthoriserConstruct = BaseLambdaAuthoriserConstruct;
871
+ exports.BaseLambdaAuthoriserV2Construct = BaseLambdaAuthoriserV2Construct;
872
+ exports.BaseLambdaConstruct = BaseLambdaConstruct;
873
+ exports.BaseLambdaLayerConstruct = BaseLambdaLayerConstruct;
874
+ exports.BaseRolePolicyConstruct = BaseRolePolicyConstruct;
875
+ exports.BaseS3Construct = BaseS3Construct;
876
+ exports.BaseS3DeploymentConstruct = BaseS3DeploymentConstruct;
877
+ exports.BaseSnsConstruct = BaseSnsConstruct;
878
+ exports.BaseSqsConstruct = BaseSqsConstruct;
879
+ exports.BaseVpcConstruct = BaseVpcConstruct;
880
+ //# sourceMappingURL=index.cjs.map
881
+ //# sourceMappingURL=index.cjs.map