@aligent/nx-cdk 0.0.1 → 0.1.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 (42) hide show
  1. package/README.md +4 -4
  2. package/generators.json +1 -1
  3. package/package.json +1 -1
  4. package/src/generators/helpers/configs/nxJson.js +7 -17
  5. package/src/generators/helpers/configs/packageJson.d.ts +27 -5
  6. package/src/generators/helpers/configs/packageJson.js +22 -5
  7. package/src/generators/helpers/configs/tsConfigs.js +3 -3
  8. package/src/generators/helpers/utilities.d.ts +24 -3
  9. package/src/generators/helpers/utilities.js +7 -4
  10. package/src/generators/preset/files/.github/workflows/pull-request.yml.template +11 -0
  11. package/src/generators/preset/files/.github/workflows/release.yml.template +17 -0
  12. package/src/generators/preset/files/.github/workflows/stg-deployment.yml.template +17 -0
  13. package/src/generators/preset/files/.gitignore.template +5 -1
  14. package/src/generators/preset/files/README.md.template +17 -2
  15. package/src/generators/preset/files/application/README.md.template +0 -17
  16. package/src/generators/preset/files/application/_internal/log-group-defaults-aspect.ts.template +83 -0
  17. package/src/generators/preset/files/application/_internal/nodejs-function-defaults-aspect.ts.template +72 -0
  18. package/src/generators/preset/files/application/_internal/step-function-defaults-aspect.ts.template +83 -0
  19. package/src/generators/preset/files/application/bin/main.ts.template +34 -38
  20. package/src/generators/preset/files/application/cdk.json.template +1 -1
  21. package/src/generators/preset/files/application/lib/service-stacks.ts.template +3 -0
  22. package/src/generators/preset/files/application/package.json.template +0 -6
  23. package/src/generators/preset/files/eslint.config.mjs.template +1 -2
  24. package/src/generators/preset/files/libs/infra/README.md.template +61 -0
  25. package/src/generators/preset/files/libs/infra/eslint.config.mjs.template +20 -0
  26. package/src/generators/preset/files/libs/infra/package.json.template +19 -0
  27. package/src/generators/preset/files/libs/infra/src/index.ts.template +44 -0
  28. package/src/generators/preset/files/libs/infra/tsconfig.json.template +6 -0
  29. package/src/generators/preset/files/parameters/dev.csv.template +2 -0
  30. package/src/generators/preset/files/tsconfig.json.template +1 -1
  31. package/src/generators/preset/preset.js +2 -4
  32. package/src/generators/service/files/README.md.template +2 -2
  33. package/src/generators/service/files/package.json.template +3 -2
  34. package/src/generators/service/files/src/index.ts.template +2 -1
  35. package/src/generators/service/files/vitest.config.mjs.template +1 -1
  36. package/src/generators/preset/files/.github/workflows/ci-cd.yml.template +0 -27
  37. package/src/generators/preset/files/application/_internal/log-group-defaults-injector.ts.template +0 -100
  38. package/src/generators/preset/files/application/_internal/microservice-checks.ts.template +0 -58
  39. package/src/generators/preset/files/application/_internal/nodejs-function-defaults-injector.ts.template +0 -110
  40. package/src/generators/preset/files/application/_internal/step-function-defaults-injector.ts.template +0 -126
  41. package/src/generators/preset/files/application/_internal/version-functions-aspect.ts.template +0 -74
  42. package/src/generators/preset/files/cdk-config.yml.template +0 -16
@@ -0,0 +1,83 @@
1
+ import { type IAspect } from 'aws-cdk-lib';
2
+ import { CfnLogGroup, LogGroup } from 'aws-cdk-lib/aws-logs';
3
+ import {
4
+ CfnStateMachine,
5
+ LogLevel,
6
+ StateMachine,
7
+ StateMachineType,
8
+ } from 'aws-cdk-lib/aws-stepfunctions';
9
+ import { IConstruct } from 'constructs';
10
+
11
+ /**
12
+ * Aspect that automatically applies tracing and logging settings to Step Functions
13
+ *
14
+ * Visits all constructs in the scope and automatically applies X-Ray tracing to all
15
+ * state machines. For EXPRESS state machines, automatically creates log groups and
16
+ * configures comprehensive logging for enhanced observability.
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * // Apply configuration-specific defaults to all Step Functions
21
+ * Aspects.of(app).add(new StepFunctionDefaultsAspect());
22
+ *
23
+ * // Step Functions automatically inherit defaults
24
+ * new StateMachine(stack, 'MyWorkflow', {
25
+ * stateMachineType: StateMachineType.EXPRESS,
26
+ * definitionBody: DefinitionBody.fromFile('workflow.asl.yaml'),
27
+ * // tracing enabled and logging configured automatically for EXPRESS
28
+ * });
29
+ * ```
30
+ *
31
+ * @see https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_stepfunctions.StateMachine.html
32
+ */
33
+ export class StepFunctionDefaultsAspect implements IAspect {
34
+ /**
35
+ * Visits a construct and applies tracing and logging settings if it's a StateMachine
36
+ *
37
+ * Enables X-Ray tracing for all state machines. For EXPRESS state machines that don't
38
+ * already have logging configured, automatically creates log groups and configures
39
+ * comprehensive logging with full execution data capture.
40
+ *
41
+ * @param node - The construct to potentially modify
42
+ */
43
+ visit(node: IConstruct): void {
44
+ if (node instanceof StateMachine) {
45
+ const cfnStateMachine = node.node.defaultChild as CfnStateMachine;
46
+
47
+ if (cfnStateMachine) {
48
+ // Apply tracing if not already set
49
+ if (cfnStateMachine.tracingConfiguration === undefined) {
50
+ cfnStateMachine.tracingConfiguration = {
51
+ enabled: true,
52
+ };
53
+ }
54
+
55
+ // For EXPRESS state machines, configure logging if not already set
56
+ if (
57
+ cfnStateMachine.stateMachineType === StateMachineType.EXPRESS &&
58
+ cfnStateMachine.loggingConfiguration === undefined
59
+ ) {
60
+ // Create a log group for the state machine
61
+ const logGroup = new LogGroup(node, 'LogGroup', {
62
+ logGroupName: `/aws/vendedlogs/states/${node.node.id}`,
63
+ });
64
+
65
+ // Get the underlying CFN log group to access its ARN
66
+ const cfnLogGroup = logGroup.node.defaultChild as CfnLogGroup;
67
+
68
+ cfnStateMachine.loggingConfiguration = {
69
+ destinations: [
70
+ {
71
+ cloudWatchLogsLogGroup: {
72
+ logGroupArn: cfnLogGroup.attrArn,
73
+ },
74
+ },
75
+ ],
76
+ level: LogLevel.ALL,
77
+ includeExecutionData: true,
78
+ };
79
+ }
80
+ }
81
+ }
82
+ }
83
+ }
@@ -1,30 +1,32 @@
1
1
  #!/usr/bin/env node
2
+ import { MicroserviceChecks, VersionFunctionsAspect } from '@aligent/cdk-aspects';
2
3
  import { App, Aspects, Tags } from 'aws-cdk-lib';
3
4
  import { Runtime } from 'aws-cdk-lib/aws-lambda';
4
5
  import { ApplicationStage } from '../lib/service-stacks.js';
5
6
 
6
- // TODO [MI-277] Pull this out to constructs repo so we can import and use later
7
- import { LogGroupDefaultsInjector } from '../_internal/log-group-defaults-injector.js';
8
- import { MicroserviceChecks } from '../_internal/microservice-checks.js';
9
- import { NodeJsFunctionDefaultsInjector } from '../_internal/nodejs-function-defaults-injector.js';
10
- import { StepFunctionDefaultsInjector } from '../_internal/step-function-defaults-injector.ts';
11
- import { VersionFunctionsAspect } from '../_internal/version-functions-aspect.js';
7
+ // TODO: [MI-277] Move these aspects to @aligent/cdk-aspects package for reuse across projects
8
+ import { LogGroupDefaultsAspect } from '../_internal/log-group-defaults-aspect.js';
9
+ import { NodeJsFunctionDefaultsAspect } from '../_internal/nodejs-function-defaults-aspect.js';
10
+ import { StepFunctionDefaultsAspect } from '../_internal/step-function-defaults-aspect.js';
12
11
 
13
- const APPLICATION_CONTEXT = { APPLICATION_OWNER: 'aligent' } as const;
12
+ const APPLICATION_CONTEXT = { NAME: '<%= name %>-int', OWNER: 'aligent' } as const;
13
+ const STAGE_NAMES = { DEV: 'dev', STG: 'stg', PRD: 'prd' } as const;
14
14
 
15
- const app = new App({
16
- context: APPLICATION_CONTEXT,
17
- propertyInjectors: [
18
- new NodeJsFunctionDefaultsInjector({ runtime: <%= nodeRuntime %> }),
19
- new StepFunctionDefaultsInjector(),
20
- ],
21
- });
22
- Tags.of(app).add('OWNER', APPLICATION_CONTEXT.APPLICATION_OWNER);
15
+ const app = new App({ context: APPLICATION_CONTEXT });
16
+ Tags.of(app).add('OWNER', APPLICATION_CONTEXT.OWNER);
17
+
18
+ /**
19
+ * Apply Application-Level Aspects
20
+ * These aspects are applied to all resources across all stages
21
+ */
22
+ Aspects.of(app).add(new NodeJsFunctionDefaultsAspect({ runtime: Runtime.NODEJS_<%= nodeRuntime %> }));
23
+ Aspects.of(app).add(new StepFunctionDefaultsAspect());
24
+ Aspects.of(app).add(new MicroserviceChecks());
23
25
 
24
26
  /**
25
27
  * Static Stage Creation Approach
26
28
  *
27
- * We use static stage creation (explicitly defining development, staging, production) for several reasons:
29
+ * We use static stage creation (explicitly defining dev, stg, prd) for several reasons:
28
30
  *
29
31
  * 1. **Predictability**: All stages are known at synthesis time, making the CDK app
30
32
  * behavior deterministic and easier to reason about.
@@ -33,8 +35,8 @@ Tags.of(app).add('OWNER', APPLICATION_CONTEXT.APPLICATION_OWNER);
33
35
  * and compile-time type checking for stage-specific configurations.
34
36
  *
35
37
  * 3. **Explicit Configuration**: Each stage's unique settings (e.g., log retention
36
- * durations, aspects, property injectors) are clearly visible in the code without
37
- * needing to trace through dynamic logic.
38
+ * durations, aspects) are clearly visible in the code without needing to trace
39
+ * through dynamic logic.
38
40
  *
39
41
  * 4. **Simpler Deployment**: CDK can synthesize all stages in a single pass without
40
42
  * requiring runtime context lookups or conditional logic.
@@ -44,29 +46,23 @@ Tags.of(app).add('OWNER', APPLICATION_CONTEXT.APPLICATION_OWNER);
44
46
  *
45
47
  * @see {@link https://dev.to/aws-heroes/how-to-use-aws-cdk-stage-and-when-to-choose-static-vs-dynamic-stack-creation-35h|Static vs Dynamic Stack Creation}
46
48
  *
47
- * @remarks Property Injector Behavior
48
- * Property injectors are applied based on their class type and will only execute once per
49
- * construct tree. When the same injector type is defined at both app and stage levels, the
50
- * stage-level injector takes precedence and overrides the app-level configuration.
49
+ * @remarks
50
+ * Aspects visit all constructs in the tree after synthesis and can modify them
51
+ * (e.g., applying log retention policies, enabling tracing).
51
52
  */
52
- const development = new ApplicationStage(app, 'development', {
53
- propertyInjectors: [new LogGroupDefaultsInjector({ duration: 'SHORT' })],
54
- });
55
- Aspects.of(development).add(new MicroserviceChecks());
56
53
 
57
- const staging = new ApplicationStage(app, 'staging', {
58
- propertyInjectors: [new LogGroupDefaultsInjector({ duration: 'MEDIUM' })],
59
- });
60
- Aspects.of(staging).add(new MicroserviceChecks());
54
+ const dev = new ApplicationStage(app, STAGE_NAMES.DEV);
55
+ Aspects.of(dev).add(new LogGroupDefaultsAspect({ duration: 'SHORT' }));
61
56
 
62
- const production = new ApplicationStage(app, 'production', {
63
- propertyInjectors: [new LogGroupDefaultsInjector({ duration: 'LONG' })],
64
- });
65
- Aspects.of(production).add(new MicroserviceChecks());
57
+ const stg = new ApplicationStage(app, STAGE_NAMES.STG);
58
+ Aspects.of(stg).add(new LogGroupDefaultsAspect({ duration: 'MEDIUM' }));
66
59
 
67
60
  /**
68
- * This aspect ensures all Lambda functions and Step Functions in production
69
- * are automatically versioned and have a stable 'live' alias pointing to the
70
- * current version, enabling zero-downtime deployments.
61
+ * Production Stage
62
+ * - Long log retention (2 years) for compliance and debugging
63
+ * - Resources retained on stack deletion
64
+ * - Lambda functions and Step Functions are automatically versioned, enabled for zero-downtime deployments
71
65
  */
72
- Aspects.of(production).add(new VersionFunctionsAspect());
66
+ const prd = new ApplicationStage(app, STAGE_NAMES.PRD);
67
+ Aspects.of(prd).add(new LogGroupDefaultsAspect({ duration: 'LONG' }));
68
+ Aspects.of(prd).add(new VersionFunctionsAspect());
@@ -1,5 +1,5 @@
1
1
  {
2
- "app": "npx tsx bin/main.ts",
2
+ "app": "yarn tsx bin/main.ts",
3
3
  "watch": {
4
4
  "include": ["**"],
5
5
  "exclude": [
@@ -1,3 +1,4 @@
1
+ import { SharedInfraStack } from '@libs/infra';
1
2
  import { Stage, Tags, type StageProps } from 'aws-cdk-lib';
2
3
  import type { Construct } from 'constructs';
3
4
 
@@ -16,6 +17,8 @@ export class ApplicationStage extends Stage {
16
17
  super(scope, id, props);
17
18
  Tags.of(this).add('STAGE', id);
18
19
 
20
+ const sharedInfra = new SharedInfraStack(this, 'shared-infra', props);
21
+
19
22
  // Service stacks initialization
20
23
  }
21
24
  }
@@ -15,12 +15,6 @@
15
15
  "command": "cdk",
16
16
  "cwd": "{projectRoot}"
17
17
  }
18
- },
19
- "parameters": {
20
- "executor": "nx:run-commands",
21
- "options": {
22
- "path": "/application/dev"
23
- }
24
18
  }
25
19
  }
26
20
  }
@@ -13,8 +13,7 @@ const eslintBaseConfig = [
13
13
  '**/cdk.out',
14
14
  '**/dist',
15
15
  '**/out-tsc',
16
- '**/vite.config.*.timestamp*',
17
- '**/vitest.config.*.timestamp*',
16
+ '**/*.config.*.timestamp*',
18
17
  ],
19
18
  },
20
19
  {
@@ -0,0 +1,61 @@
1
+ # @libs/infra
2
+
3
+ Shared infrastructure library for CDK stacks providing common resources used across multiple services.
4
+
5
+ ## Architecture
6
+
7
+ This library exports a `SharedInfraStack` that manages shared infrastructure resources, preventing duplication and ensuring consistency across service stacks.
8
+
9
+ ### Shared Resources
10
+
11
+ This `SharedInfraStack` provides:
12
+
13
+ <!-- List your shared resources here. For example:
14
+ - **eCommerce Base URL**: Retrieved from SSM Parameter Store (`/{applicationName}/e-commerce/base-url`)
15
+ - **eCommerce Credentials**: Managed secret for API authentication (`{applicationName}/e-commerce-credentials`)
16
+ -->
17
+
18
+ ### Usage
19
+
20
+ - Import and instantiate the `SharedInfraStack` in your application stage, then pass the shared resources to service stacks:
21
+
22
+ ```typescript
23
+ import { SharedInfraStack } from '@libs/infra';
24
+
25
+ const sharedInfra = new SharedInfraStack(this, 'shared-infra', props);
26
+
27
+ new MyServiceStack(this, 'service-name', {
28
+ ...props,
29
+ ...sharedInfra.getProps(),
30
+ description: 'service description',
31
+ });
32
+ ```
33
+
34
+ - Import and extend your service stack props:
35
+
36
+ ```typescript
37
+ import { SharedInfraProps } from '@libs/infra';
38
+
39
+ interface Props extends StackProps, SharedInfraProps {
40
+ description: string;
41
+ }
42
+ ```
43
+
44
+ ## Technical Decisions
45
+
46
+ ### Single Shared Stack Pattern
47
+
48
+ Resources that are used by multiple services are created once in the shared infrastructure stack and passed to service stacks via constructor props. This approach:
49
+
50
+ - Prevents resource duplication
51
+ - Ensures consistent configuration across services
52
+ - Simplifies resource management and updates
53
+ - Reduces AWS costs by sharing resources
54
+
55
+ ### Stage Requirement
56
+
57
+ The `SharedInfraStack` must be instantiated within a CDK Stage to properly resolve the stage name for resource naming and tagging.
58
+
59
+ ### Application Context
60
+
61
+ Requires the `NAME` context variable to be set for proper resource naming conventions.
@@ -0,0 +1,20 @@
1
+ import eslintPluginImport from 'eslint-plugin-import';
2
+ import baseConfig from '../../eslint.config.mjs';
3
+
4
+ export default [
5
+ ...baseConfig,
6
+ {
7
+ files: ['**/*.ts'],
8
+ plugins: { import: eslintPluginImport },
9
+ rules: {
10
+ 'import/no-extraneous-dependencies': [
11
+ 'warn',
12
+ {
13
+ optionalDependencies: false,
14
+ peerDependencies: false,
15
+ packageDir: ['.', '..', '../..'],
16
+ },
17
+ ],
18
+ },
19
+ },
20
+ ];
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@libs/infra",
3
+ "type": "module",
4
+ "main": "./src/index.ts",
5
+ "types": "./src/index.ts",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./src/index.ts",
9
+ "import": "./src/index.ts",
10
+ "default": "./src/index.ts"
11
+ },
12
+ "./package.json": "./package.json"
13
+ },
14
+ "nx": {
15
+ "tags": [
16
+ "scope:libs"
17
+ ]
18
+ }
19
+ }
@@ -0,0 +1,44 @@
1
+ import { Stack, Stage, type StackProps } from 'aws-cdk-lib';
2
+ import { Secret } from 'aws-cdk-lib/aws-secretsmanager';
3
+ import { StringParameter } from 'aws-cdk-lib/aws-ssm';
4
+ import type { Construct } from 'constructs';
5
+
6
+ export interface SharedInfraProps {
7
+ eCommerceBaseUrl: string;
8
+ eCommerceCredentials: Secret;
9
+ }
10
+
11
+ export class SharedInfraStack extends Stack {
12
+ readonly eCommerceBaseUrl: string;
13
+ readonly eCommerceCredentials: Secret;
14
+
15
+ constructor(scope: Construct, id: string, props?: StackProps) {
16
+ super(scope, id, props);
17
+
18
+ const STAGE = Stage.of(this)?.stageName;
19
+ if (!STAGE) {
20
+ throw new Error('This construct must be used within a CDK Stage');
21
+ }
22
+
23
+ const applicationName = this.node.tryGetContext('NAME');
24
+
25
+ this.eCommerceBaseUrl = StringParameter.fromStringParameterName(
26
+ this,
27
+ 'ECommerceBaseUrl',
28
+ `/${applicationName}/e-commerce/base-url`
29
+ ).stringValue;
30
+
31
+ // Create secrets once in the shared stack
32
+ this.eCommerceCredentials = new Secret(this, 'ECommerceCredentials', {
33
+ secretName: `${applicationName}/e-commerce-credentials`,
34
+ description: 'E-Commerce API credentials shared across services',
35
+ });
36
+ }
37
+
38
+ getProps(): SharedInfraProps {
39
+ return {
40
+ eCommerceBaseUrl: this.eCommerceBaseUrl,
41
+ eCommerceCredentials: this.eCommerceCredentials,
42
+ };
43
+ }
44
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "extends": "@aligent/ts-code-standards/tsconfigs-extend",
3
+ "files": [],
4
+ "include": [],
5
+ "references": []
6
+ }
@@ -0,0 +1,2 @@
1
+ Note|Name|Type|Value
2
+ Collect from eCommerce|/<%= name %>-int/e-commerce/base-url|String|https://e-commerce.com/dev/api
@@ -2,5 +2,5 @@
2
2
  "extends": "@aligent/ts-code-standards/tsconfigs-extend",
3
3
  "compileOnSave": false,
4
4
  "files": [],
5
- "references": [{"path": "./application"}]
5
+ "references": [{"path": "./application"}, {"path": "./libs/infra"}]
6
6
  }
@@ -14,7 +14,7 @@ async function presetGenerator(tree, options) {
14
14
  ...options,
15
15
  projectName,
16
16
  folderName: destination || name,
17
- nodeRuntime: `Runtime.NODEJS_${nodeVersionMajor}_X`,
17
+ nodeRuntime: `${nodeVersionMajor}_X`,
18
18
  template: '',
19
19
  });
20
20
  (0, devkit_1.updateNxJson)(tree, { ...nxJson_1.NX_JSON });
@@ -26,10 +26,8 @@ async function presetGenerator(tree, options) {
26
26
  });
27
27
  (0, devkit_1.writeJson)(tree, 'package.json', packageJson);
28
28
  // Generate application's tsconfigs
29
- const { tsConfig, tsConfigLib, tsConfigSpec } = (0, utilities_1.constructProjectTsConfigFiles)('application');
29
+ const { tsConfig } = (0, utilities_1.constructProjectTsConfigFiles)('application');
30
30
  (0, devkit_1.writeJson)(tree, 'application/tsconfig.json', tsConfig);
31
- (0, devkit_1.writeJson)(tree, 'application/tsconfig.lib.json', tsConfigLib);
32
- (0, devkit_1.writeJson)(tree, 'application/tsconfig.spec.json', tsConfigSpec);
33
31
  await (0, devkit_1.formatFiles)(tree);
34
32
  }
35
33
  exports.default = presetGenerator;
@@ -15,13 +15,13 @@ This is a CDK service generated using `@aligent/nx-cdk` for Nx.
15
15
  ### Type Checking
16
16
 
17
17
  ```bash
18
- npx nx check-types <%= name %>
18
+ yarn nx check-types <%= name %>
19
19
  ```
20
20
 
21
21
  ### Testing
22
22
 
23
23
  ```bash
24
- npx nx test <%= name %>
24
+ yarn nx test <%= name %>
25
25
  ```
26
26
 
27
27
  ## Deployment
@@ -1,5 +1,5 @@
1
1
  {
2
- "name": "<%= name %>",
2
+ "name": "@services/<%= name %>",
3
3
  "type": "module",
4
4
  "main": "./src/index.ts",
5
5
  "types": "./src/index.ts",
@@ -12,7 +12,8 @@
12
12
  "./package.json": "./package.json"
13
13
  },
14
14
  "bundleDependencies": [
15
- "clients"
15
+ "clients",
16
+ "@libs/infra"
16
17
  ],
17
18
  "nx": {
18
19
  "targets": {
@@ -1,3 +1,4 @@
1
+ import { SharedInfraProps } from '@libs/infra';
1
2
  import { Stack, StackProps, Stage, Tags } from 'aws-cdk-lib';
2
3
  import { Code } from 'aws-cdk-lib/aws-lambda';
3
4
  import { Construct } from 'constructs';
@@ -14,7 +15,7 @@ export const <%= constant %> = {
14
15
  } as const;
15
16
 
16
17
  type Id = typeof <%= constant %>.NAME | (string & {});
17
- interface Props extends StackProps {
18
+ interface Props extends StackProps, SharedInfraProps {
18
19
  description: string;
19
20
  }
20
21
 
@@ -5,7 +5,7 @@ export default defineConfig(configEnv => {
5
5
  return mergeConfig(
6
6
  vitestBaseConfig(configEnv),
7
7
  defineConfig({
8
- cacheDir: '../../node_modules/.vite/<%= name %>',
8
+ cacheDir: '../../node_modules/.vitest/<%= name %>',
9
9
  test: {
10
10
  env: {
11
11
  NODE_ENV: 'test',
@@ -1,27 +0,0 @@
1
- name: CI/CD Pipeline
2
-
3
- on:
4
- pull_request:
5
- branches:
6
- - '**'
7
- push:
8
- branches:
9
- - staging
10
- - production
11
-
12
- jobs:
13
- code-quality:
14
- name: 🕵️‍♀️ Code Quality Check
15
- uses: aligent/workflows/.github/workflows/node-pr.yml@main
16
- with:
17
- skip-format: false
18
-
19
- deploy:
20
- name: Deploy to AWS
21
- uses: aligent/workflows/.github/workflows/aws-cdk-deploy.yml@main
22
- with:
23
- cdk-stack-name: ${{ vars.STACK_NAME }}
24
- aws-access-key-id: ${{ vars.AWS_ACCESS_KEY_ID }}
25
- deploy: true
26
- secrets:
27
- aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
@@ -1,100 +0,0 @@
1
- import { RemovalPolicy, type IPropertyInjector } from 'aws-cdk-lib';
2
- import { LogGroup, RetentionDays, type LogGroupProps } from 'aws-cdk-lib/aws-logs';
3
-
4
- interface Config {
5
- duration: 'SHORT' | 'MEDIUM' | 'LONG';
6
- }
7
-
8
- /**
9
- * Property injector for CloudWatch Log Groups with configuration-aware defaults
10
- *
11
- * Applies configuration-specific retention policies and removal settings to log groups.
12
- * Different configurations balance between cost optimization and data retention needs.
13
- *
14
- * @example
15
- * ```typescript
16
- * // Apply configuration-specific defaults
17
- * PropertyInjectors.of(scope).add(
18
- * new LogGroupDefaultsInjector({ duration: 'SHORT' }).withProps({
19
- * logGroupName: '/custom/log/group',
20
- * })
21
- * );
22
- *
23
- * // Log groups automatically inherit configuration defaults
24
- * new LogGroup(stack, 'MyLogGroup', {
25
- * // retention and removal policy applied automatically
26
- * });
27
- * ```
28
- *
29
- * @see https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_logs.LogGroup.html
30
- */
31
- export class LogGroupDefaultsInjector implements IPropertyInjector {
32
- readonly constructUniqueId = LogGroup.PROPERTY_INJECTION_ID;
33
- private readonly config: Config;
34
- private defaultProps: LogGroupProps;
35
-
36
- /**
37
- * Creates a new LogGroupDefaultsInjector
38
- *
39
- * @param config - Configuration identifier used to select appropriate defaults.
40
- */
41
- constructor(config: Config) {
42
- const props = retentionProperties(config.duration);
43
- this.config = { ...config };
44
- this.defaultProps = { ...props };
45
- }
46
-
47
- /**
48
- * Creates a new injector instance with additional properties
49
- *
50
- * Returns a new injector that inherits the current configuration but includes
51
- * additional properties that override the configuration defaults.
52
- *
53
- * @param props - Additional properties to merge with configuration defaults
54
- * @returns A new injector instance with merged properties
55
- *
56
- * @example
57
- * ```typescript
58
- * const customInjector = new LogGroupDefaultsInjector({ duration: 'SHORT' })
59
- * .withProps({
60
- * logGroupName: '/aws/lambda/custom',
61
- * retention: RetentionDays.ONE_MONTH,
62
- * });
63
- * ```
64
- */
65
- public withProps(props: LogGroupProps) {
66
- const modifiedInjector = new LogGroupDefaultsInjector(this.config);
67
- modifiedInjector.defaultProps = { ...this.defaultProps, ...props };
68
- return modifiedInjector;
69
- }
70
-
71
- /**
72
- * Injects configuration-appropriate defaults into log group properties
73
- *
74
- * Merges configuration-specific retention and removal policies with user-provided properties.
75
- *
76
- * @param originalProps - Properties provided when creating the log group
77
- * @param context - CDK injection context containing construct information
78
- * @returns Merged properties with injected defaults
79
- */
80
- public inject(originalProps: LogGroupProps) {
81
- return { ...this.defaultProps, ...originalProps };
82
- }
83
- }
84
-
85
- /**
86
- * Get duration-specific log group properties
87
- *
88
- * @param duration - The duration to get the log group properties for
89
- * @returns The log group properties for the duration
90
- */
91
- function retentionProperties(duration: 'SHORT' | 'MEDIUM' | 'LONG') {
92
- switch (duration) {
93
- case 'SHORT':
94
- return { retention: RetentionDays.ONE_WEEK, removalPolicy: RemovalPolicy.DESTROY };
95
- case 'MEDIUM':
96
- return { retention: RetentionDays.SIX_MONTHS, removalPolicy: RemovalPolicy.DESTROY };
97
- default:
98
- return { retention: RetentionDays.TWO_YEARS, removalPolicy: RemovalPolicy.RETAIN };
99
- }
100
- }