@gradientedge/cdk-utils-aws 2.3.0 → 2.4.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.
Files changed (49) hide show
  1. package/dist/src/common/construct.d.ts +38 -0
  2. package/dist/src/common/construct.js +38 -0
  3. package/dist/src/common/resource-name-formatter.d.ts +12 -1
  4. package/dist/src/common/resource-name-formatter.js +12 -1
  5. package/dist/src/common/stack.d.ts +9 -0
  6. package/dist/src/common/stack.js +9 -0
  7. package/dist/src/common/types.d.ts +22 -0
  8. package/dist/src/construct/api-to-any-target/main.d.ts +19 -0
  9. package/dist/src/construct/api-to-any-target/main.js +19 -0
  10. package/dist/src/construct/api-to-eventbridge-target/main.d.ts +6 -0
  11. package/dist/src/construct/api-to-eventbridge-target/main.js +6 -0
  12. package/dist/src/construct/api-to-eventbridge-target-with-sns/main.d.ts +3 -0
  13. package/dist/src/construct/api-to-eventbridge-target-with-sns/main.js +3 -0
  14. package/dist/src/construct/api-to-lambda-target/main.d.ts +9 -0
  15. package/dist/src/construct/api-to-lambda-target/main.js +9 -0
  16. package/dist/src/construct/application-configuration/main.d.ts +27 -0
  17. package/dist/src/construct/application-configuration/main.js +27 -0
  18. package/dist/src/construct/event-handler/main.d.ts +3 -0
  19. package/dist/src/construct/event-handler/main.js +12 -1
  20. package/dist/src/construct/lambda-with-iam-access/main.d.ts +15 -0
  21. package/dist/src/construct/lambda-with-iam-access/main.js +22 -0
  22. package/dist/src/construct/piped-event-handler/main.d.ts +3 -0
  23. package/dist/src/construct/piped-event-handler/main.js +3 -0
  24. package/dist/src/construct/rest-api-lambda/main.js +3 -0
  25. package/dist/src/construct/rest-api-lambda-with-cache/main.d.ts +3 -0
  26. package/dist/src/construct/rest-api-lambda-with-cache/main.js +3 -0
  27. package/dist/src/construct/site-with-ecs-backend/main.d.ts +27 -0
  28. package/dist/src/construct/site-with-ecs-backend/main.js +31 -1
  29. package/dist/src/construct/site-with-lambda-backend/main.d.ts +54 -0
  30. package/dist/src/construct/site-with-lambda-backend/main.js +61 -0
  31. package/dist/src/construct/static-asset-deployment/main.js +4 -0
  32. package/dist/src/services/api-gateway/main.js +6 -0
  33. package/dist/src/services/certificate-manager/main.js +3 -0
  34. package/dist/src/services/cloudfront/main.d.ts +11 -0
  35. package/dist/src/services/cloudfront/main.js +11 -0
  36. package/dist/src/services/cloudtrail/main.js +4 -0
  37. package/dist/src/services/cloudwatch/main.js +9 -0
  38. package/dist/src/services/codebuild/main.d.ts +10 -10
  39. package/dist/src/services/codebuild/main.js +10 -10
  40. package/dist/src/services/elastic-file-system/main.js +3 -0
  41. package/dist/src/services/identity-access-management/main.js +5 -0
  42. package/dist/src/services/lambda/main.d.ts +5 -0
  43. package/dist/src/services/lambda/main.js +12 -0
  44. package/dist/src/services/simple-queue-service/main.js +1 -0
  45. package/dist/src/services/simple-storage-service/main.js +4 -0
  46. package/dist/src/services/step-function/main.js +5 -0
  47. package/dist/src/services/systems-manager/main.d.ts +1 -1
  48. package/dist/src/services/systems-manager/main.js +1 -1
  49. package/package.json +5 -5
@@ -32,6 +32,12 @@ import { createCfnOutput } from '../../utils/index.js';
32
32
  * @category Service
33
33
  */
34
34
  export class CloudFrontManager {
35
+ /**
36
+ * @summary Method to create a CloudFront Origin Access Identity
37
+ * @param id scoped id of the resource
38
+ * @param scope scope in which this resource is defined
39
+ * @param accessBucket optional S3 bucket to grant read access to the OAI
40
+ */
35
41
  createOriginAccessIdentity(id, scope, accessBucket) {
36
42
  const oai = new OriginAccessIdentity(scope, `${id}`, {
37
43
  comment: `${id} - ${scope.props.stage} stage`,
@@ -228,6 +234,11 @@ export class CloudFrontManager {
228
234
  createCfnOutput(`${id}-functionName`, scope, cloudfrontFunction.functionName);
229
235
  return cloudfrontFunction;
230
236
  }
237
+ /**
238
+ * @summary Method to resolve an existing CloudFront distribution by its attributes
239
+ * @param scope scope in which this resource is defined
240
+ * @param props the distribution attributes to look up
241
+ */
231
242
  resolveDistribution(scope, props) {
232
243
  return Distribution.fromDistributionAttributes(scope, `${scope.node.id}-sa-distribution`, props);
233
244
  }
@@ -45,6 +45,8 @@ export class CloudTrailManager {
45
45
  ...props,
46
46
  cloudWatchLogsLogGroupArn: logGroup.attrArn,
47
47
  cloudWatchLogsRoleArn: role.attrArn,
48
+ /* Track only S3 data write events (not management events) to reduce
49
+ noise and cost — reads are excluded to focus on mutation auditing */
48
50
  eventSelectors: [
49
51
  {
50
52
  dataResources: [
@@ -62,6 +64,8 @@ export class CloudTrailManager {
62
64
  tags: [{ key: 'service', value: scope.props.name }],
63
65
  trailName: scope.resourceNameFormatter.format(props.trailName, scope.props.resourceNameOptions?.cloudtrail),
64
66
  });
67
+ /* CloudTrail requires the bucket policy (write permissions), log group,
68
+ and IAM role to exist before the trail can be created */
65
69
  cloudTrail.addDependency(logBucketPolicy);
66
70
  cloudTrail.addDependency(logGroup);
67
71
  cloudTrail.addDependency(role);
@@ -44,6 +44,8 @@ export class CloudWatchManager {
44
44
  throw new Error(`Could not find expression for Alarm props for id:${id}`);
45
45
  if (!props.metricProps)
46
46
  throw new Error(`Could not find metricProps for Alarm props for id:${id}`);
47
+ /* Build a keyed map of metrics (m0, m1, m2, ...) that aligns with the
48
+ metric references used in the MathExpression string (e.g. "m0 + m1") */
47
49
  const metrics = {};
48
50
  _.map(this.determineMetrics(scope, props.metricProps), (metric, index) => {
49
51
  metrics[`m${index}`] = metric;
@@ -427,6 +429,10 @@ export class CloudWatchManager {
427
429
  const metrics = [];
428
430
  if (metricProps) {
429
431
  metricProps.forEach((metricProp) => {
432
+ /* Start with any custom dimensions provided, then override based on
433
+ which service-specific fields are set. Note: these blocks are not
434
+ mutually exclusive — if multiple fields match, the last matching
435
+ block wins, since each reassigns metricDimensions entirely. */
430
436
  let metricDimensions = metricProp.dimensionsMap || {};
431
437
  if (metricProp.functionName) {
432
438
  metricDimensions = {
@@ -466,6 +472,7 @@ export class CloudWatchManager {
466
472
  };
467
473
  }
468
474
  if (metricProp.distributionId) {
475
+ /* CloudFront metrics are always reported as Region: Global */
469
476
  metricDimensions = {
470
477
  ...metricProp.dimensionsMap,
471
478
  DistributionId: `${metricProp.distributionId}`,
@@ -503,6 +510,8 @@ export class CloudWatchManager {
503
510
  RuleName: `${metricProp.ruleName}`,
504
511
  };
505
512
  }
513
+ /* When stageSuffix is enabled, append the stage to both metric name
514
+ and namespace to isolate metrics per deployment stage */
506
515
  const metric = new watch.Metric({
507
516
  dimensionsMap: metricDimensions,
508
517
  metricName: metricProp.stageSuffix ? `${metricProp.metricName}-${scope.props.stage}` : metricProp.metricName,
@@ -19,19 +19,19 @@ import { CommonConstruct } from '../../common/index.js';
19
19
  */
20
20
  export declare class CodeBuildManager {
21
21
  /**
22
- *
23
- * @param id
24
- * @param scope
25
- * @param dockerfilePath
22
+ * @summary Method to create a Docker image used for CloudFront cache invalidation
23
+ * @param id scoped id of the resource
24
+ * @param scope scope in which this resource is defined
25
+ * @param dockerfilePath the path to the Dockerfile
26
26
  */
27
27
  createImageForCloudfrontInvalidation(id: string, scope: CommonConstruct, dockerfilePath: string): import("aws-cdk-lib/aws-ecr-assets").DockerImageAsset;
28
28
  /**
29
- *
30
- * @param id
31
- * @param scope
32
- * @param dockerFilepath
33
- * @param distributionId
34
- * @param paths
29
+ * @summary Method to create a CodeBuild project for invalidating a CloudFront distribution cache
30
+ * @param id scoped id of the resource
31
+ * @param scope scope in which this resource is defined
32
+ * @param dockerFilepath the path to the Dockerfile for the build image
33
+ * @param distributionId the CloudFront distribution ID to invalidate
34
+ * @param paths optional invalidation paths (defaults to /*)
35
35
  */
36
36
  createProjectForCloudfrontInvalidation(id: string, scope: CommonConstruct, dockerFilepath: string, distributionId: string, paths?: string): Project;
37
37
  }
@@ -19,21 +19,21 @@ import { BuildSpec, ComputeType, LinuxBuildImage, Project } from 'aws-cdk-lib/aw
19
19
  */
20
20
  export class CodeBuildManager {
21
21
  /**
22
- *
23
- * @param id
24
- * @param scope
25
- * @param dockerfilePath
22
+ * @summary Method to create a Docker image used for CloudFront cache invalidation
23
+ * @param id scoped id of the resource
24
+ * @param scope scope in which this resource is defined
25
+ * @param dockerfilePath the path to the Dockerfile
26
26
  */
27
27
  createImageForCloudfrontInvalidation(id, scope, dockerfilePath) {
28
28
  return scope.ecrManager.createDockerImage(`${id}-build-image`, scope, dockerfilePath);
29
29
  }
30
30
  /**
31
- *
32
- * @param id
33
- * @param scope
34
- * @param dockerFilepath
35
- * @param distributionId
36
- * @param paths
31
+ * @summary Method to create a CodeBuild project for invalidating a CloudFront distribution cache
32
+ * @param id scoped id of the resource
33
+ * @param scope scope in which this resource is defined
34
+ * @param dockerFilepath the path to the Dockerfile for the build image
35
+ * @param distributionId the CloudFront distribution ID to invalidate
36
+ * @param paths optional invalidation paths (defaults to /*)
37
37
  */
38
38
  createProjectForCloudfrontInvalidation(id, scope, dockerFilepath, distributionId, paths) {
39
39
  const invalidationPaths = paths ?? '/*';
@@ -46,6 +46,8 @@ export class EfsManager {
46
46
  throw new Error(`EFS props undefined for ${id}`);
47
47
  if (!props.fileSystemName)
48
48
  throw new Error(`EFS fileSystemName undefined for ${id}`);
49
+ /* Appending a timestamp to the logical ID forces CDK to replace the file system
50
+ on each deployment — used when a fresh EFS volume is required per deploy */
49
51
  const fileSystemId = props.provisionNewOnDeployment ? `${id}-${new Date().getMilliseconds()}` : `${id}`;
50
52
  const fileSystem = new FileSystem(scope, `${fileSystemId}`, {
51
53
  ...props,
@@ -65,6 +67,7 @@ export class EfsManager {
65
67
  for (const [index, accessPointOption] of accessPointOptions.entries()) {
66
68
  if (!accessPointOption.path)
67
69
  throw new Error(`Undefined access point path for option: [${accessPointOption}], id: [${id}]`);
70
+ /* Defaults use UID/GID 1000 (standard non-root Linux user) with 755 permissions */
68
71
  const accessPoint = fileSystem.addAccessPoint(`${id}-ap-${index}`, {
69
72
  createAcl: accessPointOption.createAcl ?? DEFAULT_CREATE_ACL,
70
73
  path: accessPointOption.path,
@@ -276,6 +276,9 @@ export class IamManager {
276
276
  return new PolicyStatement({
277
277
  actions: ['logs:CreateLogStream'],
278
278
  effect: Effect.ALLOW,
279
+ /* Note: the log stream name pattern follows CloudTrail's convention:
280
+ {accountId}_CloudTrail_{region}. The eu-west-1 suffix is hard-coded
281
+ to match the expected trail region for this deployment. */
279
282
  resources: [
280
283
  `arn:aws:logs:${Stack.of(scope).region}:${Stack.of(scope).account}:log-group:${logGroup.logGroupName}:log-stream:${Stack.of(scope).account}_CloudTrail_eu-west-1*`,
281
284
  ],
@@ -302,6 +305,8 @@ export class IamManager {
302
305
  return new PolicyStatement({
303
306
  actions: ['logs:PutLogEvents'],
304
307
  effect: Effect.ALLOW,
308
+ /* Note: log stream name follows CloudTrail convention — eu-west-1 is
309
+ hard-coded to match the expected trail region for this deployment */
305
310
  resources: [
306
311
  `arn:aws:logs:${Stack.of(scope).region}:${Stack.of(scope).account}:log-group:${logGroup.logGroupName}:log-stream:${Stack.of(scope).account}_CloudTrail_eu-west-1*`,
307
312
  ],
@@ -31,6 +31,11 @@ export declare class LambdaManager {
31
31
  * @param architectures
32
32
  */
33
33
  createLambdaLayer(id: string, scope: CommonConstruct, code: AssetCode, architectures?: Architecture[]): LayerVersion;
34
+ /**
35
+ * @summary Method to create Lambda Web Adapter layers for both x86_64 and ARM64 architectures
36
+ * @param id scoped id of the resource
37
+ * @param scope scope in which this resource is defined
38
+ */
34
39
  createWebAdapterLayer(id: string, scope: CommonConstruct): ILayerVersion[];
35
40
  /**
36
41
  * @summary Method to create a lambda function (nodejs)
@@ -42,6 +42,11 @@ export class LambdaManager {
42
42
  createCfnOutput(`${id}-lambdaLayerArn`, scope, lambdaLayer.layerVersionArn);
43
43
  return lambdaLayer;
44
44
  }
45
+ /**
46
+ * @summary Method to create Lambda Web Adapter layers for both x86_64 and ARM64 architectures
47
+ * @param id scoped id of the resource
48
+ * @param scope scope in which this resource is defined
49
+ */
45
50
  createWebAdapterLayer(id, scope) {
46
51
  return [
47
52
  LayerVersion.fromLayerVersionArn(scope, `${id}-${Architecture.X86_64}`, `arn:aws:lambda:${scope.props.region}:753240598075:layer:LambdaAdapterLayerX86:17`),
@@ -77,6 +82,7 @@ export class LambdaManager {
77
82
  }
78
83
  const lambdaFunction = new Function(scope, `${id}`, {
79
84
  ...props,
85
+ /* When a VPC is provided, allow placement in public subnets (e.g. for NAT access) */
80
86
  allowPublicSubnet: !!vpc,
81
87
  architecture: props.architecture ?? Architecture.ARM_64,
82
88
  code,
@@ -96,7 +102,9 @@ export class LambdaManager {
96
102
  removalPolicy: RemovalPolicy.DESTROY,
97
103
  retention: scope.props.logRetention ?? props.logRetentionInDays,
98
104
  }),
105
+ /* Per-function concurrency takes precedence over the stack-wide default */
99
106
  reservedConcurrentExecutions: props.reservedConcurrentExecutions ?? scope.props.defaultReservedLambdaConcurrentExecutions,
107
+ /* Only L2 Role is accepted here — CfnRole (L1) is not compatible with the Function construct */
100
108
  role: role instanceof Role ? role : undefined,
101
109
  runtime: props.runtime ?? scope.props.nodejsRuntime ?? CommonStack.NODEJS_RUNTIME,
102
110
  securityGroups,
@@ -105,12 +113,16 @@ export class LambdaManager {
105
113
  vpc,
106
114
  vpcSubnets,
107
115
  });
116
+ /* When DLQ retries are enabled, wire the DLQ back as an SQS event source
117
+ so failed messages are automatically reprocessed by the same function */
108
118
  if (lambdaFunction.deadLetterQueue && props.dlq?.retriesEnabled) {
109
119
  lambdaFunction.addEventSource(new SqsEventSource(lambdaFunction.deadLetterQueue, {
110
120
  batchSize: props.dlq.retryBatchSize ?? 1,
111
121
  reportBatchItemFailures: true,
112
122
  }));
113
123
  }
124
+ /* Create aliases and optionally attach provisioned concurrency auto-scaling.
125
+ Provisioned concurrency requires an alias — it cannot be set on $LATEST. */
114
126
  if (props.lambdaAliases && !_.isEmpty(props.lambdaAliases)) {
115
127
  props.lambdaAliases.forEach(alias => {
116
128
  const aliasId = alias.id ?? `${id}-${alias.aliasName}`;
@@ -33,6 +33,7 @@ export class SqsManager {
33
33
  if (!props.queueName)
34
34
  throw new Error(`Queue queueName undefined for ${id}`);
35
35
  let queueName = scope.resourceNameFormatter.format(props.queueName, scope.props.resourceNameOptions?.sqs);
36
+ /* AWS SQS requires FIFO queue names to end with the .fifo suffix */
36
37
  if (props.fifo)
37
38
  queueName += '.fifo';
38
39
  const queue = new Queue(scope, id, {
@@ -65,6 +65,10 @@ export class S3Manager {
65
65
  * @param bucketName the bucket name
66
66
  */
67
67
  static determineBucketName(scope, props, bucketName) {
68
+ /* Naming strategy priority (note: flags use negative naming — "exclude" means "don't use"):
69
+ 1. Domain-based naming (default) — includes the domain name for global uniqueness
70
+ 2. Account-based naming — falls back to account+region when domain is excluded
71
+ 3. Formatter-only — plain prefix/suffix when both domain and account are excluded */
68
72
  if (!scope.props.excludeDomainNameForBuckets) {
69
73
  return S3Manager.determineBucketNameByDomainName(scope, bucketName);
70
74
  }
@@ -4,6 +4,9 @@ import { CallApiGatewayRestApiEndpoint, DynamoDeleteItem, DynamoGetItem, DynamoP
4
4
  import _ from 'lodash';
5
5
  import { v4 as uuidv4 } from 'uuid';
6
6
  import { createCfnOutput } from '../../utils/index.js';
7
+ /* Default retry configuration applied to all step function steps when no
8
+ explicit retries are provided: exponential backoff (2x) starting at 30s,
9
+ up to 6 attempts, catching all error types */
7
10
  const DEFAULT_RETRY_CONFIG = [
8
11
  {
9
12
  backoffRate: 2,
@@ -267,6 +270,8 @@ export class SfnManager {
267
270
  createSkippableLambdaStep(id, scope, props, lambdaFunction, skipExecution) {
268
271
  if (!props)
269
272
  throw new Error(`Step props undefined for ${id}`);
273
+ /* When skipExecution is true, substitute a no-op Pass step instead of the Lambda
274
+ invocation — useful for conditionally disabling steps without changing the workflow topology */
270
275
  if (skipExecution)
271
276
  return this.createPassStep(id, scope, { comment: props.comment, name: props.name });
272
277
  const step = new LambdaInvoke(scope, `${props.name}`, {
@@ -51,7 +51,7 @@ export declare class SsmManager {
51
51
  export declare class SSMParameterReader extends AwsCustomResource {
52
52
  constructor(scope: CommonConstruct, name: string, props: SSMParameterReaderProps);
53
53
  /**
54
- *
54
+ * @summary Method to retrieve the SSM parameter value from the custom resource response
55
55
  */
56
56
  getParameterValue(): string;
57
57
  }
@@ -91,7 +91,7 @@ export class SSMParameterReader extends AwsCustomResource {
91
91
  });
92
92
  }
93
93
  /**
94
- *
94
+ * @summary Method to retrieve the SSM parameter value from the custom resource response
95
95
  */
96
96
  getParameterValue() {
97
97
  return this.getResponseField('Parameter.Value');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gradientedge/cdk-utils-aws",
3
- "version": "2.3.0",
3
+ "version": "2.4.1",
4
4
  "description": "AWS CDK utilities for @gradientedge/cdk-utils",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",
@@ -14,17 +14,17 @@
14
14
  "dist/src/"
15
15
  ],
16
16
  "dependencies": {
17
- "@aws-sdk/client-secrets-manager": "3.1034.0",
18
- "@aws-sdk/credential-providers": "3.1034.0",
17
+ "@aws-sdk/client-secrets-manager": "3.1040.0",
18
+ "@aws-sdk/credential-providers": "3.1040.0",
19
19
  "@aws-sdk/types": "3.973.8",
20
20
  "@types/lodash": "4.17.24",
21
21
  "app-root-path": "3.1.0",
22
- "aws-cdk-lib": "2.250.0",
22
+ "aws-cdk-lib": "2.252.0",
23
23
  "lodash": "4.18.1",
24
24
  "constructs": "10.6.0",
25
25
  "moment": "2.30.1",
26
26
  "uuid": "14.0.0",
27
- "@gradientedge/cdk-utils-common": "2.1.0"
27
+ "@gradientedge/cdk-utils-common": "2.2.1"
28
28
  },
29
29
  "keywords": [
30
30
  "gradientedge",