@aligent/nx-cdk 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.
Files changed (61) hide show
  1. package/README.md +130 -0
  2. package/generators.json +15 -0
  3. package/package.json +20 -0
  4. package/src/generators/helpers/configs/nxJson.d.ts +4 -0
  5. package/src/generators/helpers/configs/nxJson.js +52 -0
  6. package/src/generators/helpers/configs/packageJson.d.ts +61 -0
  7. package/src/generators/helpers/configs/packageJson.js +65 -0
  8. package/src/generators/helpers/configs/tsConfigs.d.ts +12 -0
  9. package/src/generators/helpers/configs/tsConfigs.js +40 -0
  10. package/src/generators/helpers/utilities.d.ts +82 -0
  11. package/src/generators/helpers/utilities.js +100 -0
  12. package/src/generators/preset/files/.editorconfig.template +18 -0
  13. package/src/generators/preset/files/.git-hooks/pre-push.template +68 -0
  14. package/src/generators/preset/files/.github/CODEOWNERS.template +3 -0
  15. package/src/generators/preset/files/.github/dependabot.yml.template +7 -0
  16. package/src/generators/preset/files/.github/workflows/ci-cd.yml.template +27 -0
  17. package/src/generators/preset/files/.gitignore.template +62 -0
  18. package/src/generators/preset/files/.nvmrc.template +1 -0
  19. package/src/generators/preset/files/.prettierignore.template +10 -0
  20. package/src/generators/preset/files/.yarnrc.yml.template +6 -0
  21. package/src/generators/preset/files/LICENSE.template +21 -0
  22. package/src/generators/preset/files/README.md.template +77 -0
  23. package/src/generators/preset/files/application/README.md.template +61 -0
  24. package/src/generators/preset/files/application/_internal/log-group-defaults-injector.ts.template +100 -0
  25. package/src/generators/preset/files/application/_internal/microservice-checks.ts.template +58 -0
  26. package/src/generators/preset/files/application/_internal/nodejs-function-defaults-injector.ts.template +110 -0
  27. package/src/generators/preset/files/application/_internal/step-function-defaults-injector.ts.template +126 -0
  28. package/src/generators/preset/files/application/_internal/version-functions-aspect.ts.template +74 -0
  29. package/src/generators/preset/files/application/bin/main.ts.template +72 -0
  30. package/src/generators/preset/files/application/cdk.context.json.template +4 -0
  31. package/src/generators/preset/files/application/cdk.json.template +92 -0
  32. package/src/generators/preset/files/application/eslint.config.mjs.template +3 -0
  33. package/src/generators/preset/files/application/lib/service-stacks.ts.template +21 -0
  34. package/src/generators/preset/files/application/package.json.template +27 -0
  35. package/src/generators/preset/files/cdk-config.yml.template +16 -0
  36. package/src/generators/preset/files/eslint.config.mjs.template +54 -0
  37. package/src/generators/preset/files/prettier.config.mjs.template +3 -0
  38. package/src/generators/preset/files/rolldown.config.base.mjs.template +46 -0
  39. package/src/generators/preset/files/tsconfig.json.template +6 -0
  40. package/src/generators/preset/files/vitest.config.base.mjs.template +39 -0
  41. package/src/generators/preset/files/vitest.global.setup.mjs.template +109 -0
  42. package/src/generators/preset/preset.d.ts +4 -0
  43. package/src/generators/preset/preset.js +35 -0
  44. package/src/generators/preset/schema.d.ts +7 -0
  45. package/src/generators/preset/schema.json +32 -0
  46. package/src/generators/service/files/README.md.template +29 -0
  47. package/src/generators/service/files/eslint.config.mjs.template +20 -0
  48. package/src/generators/service/files/package.json.template +32 -0
  49. package/src/generators/service/files/rolldown.config.mjs.template +3 -0
  50. package/src/generators/service/files/src/index.ts.template +75 -0
  51. package/src/generators/service/files/src/infra/.gitkeep.template +0 -0
  52. package/src/generators/service/files/src/runtime/handlers/.gitkeep.template +0 -0
  53. package/src/generators/service/files/src/runtime/lib/utils/.gitkeep.template +0 -0
  54. package/src/generators/service/files/tests/__data__/.gitkeep.template +0 -0
  55. package/src/generators/service/files/vitest.config.mjs.template +18 -0
  56. package/src/generators/service/generator.d.ts +4 -0
  57. package/src/generators/service/generator.js +43 -0
  58. package/src/generators/service/schema.d.ts +4 -0
  59. package/src/generators/service/schema.json +20 -0
  60. package/src/index.d.ts +2 -0
  61. package/src/index.js +19 -0
@@ -0,0 +1,68 @@
1
+ #!/bin/bash
2
+ # Script adapted from https://github.com/kaczor6418/git-hooks-example/blob/master/git-hooks/pre-commit
3
+
4
+ # Support using VSCode to commit
5
+ # This loads nvm.sh and sets the correct PATH before running hook
6
+ export NVM_DIR="$HOME/.nvm"
7
+ [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
8
+
9
+ # Define colours for nicer CLI output
10
+ RED="\033[1;31m"
11
+ GREEN="\033[1;32m"
12
+ NO_COLOUR="\033[0m"
13
+
14
+ echo -e "${GREEN}Executing git hook $0 $@${NO_COLOUR}"
15
+
16
+ # Use the current Node version explicitly
17
+ nvm use
18
+
19
+ # Get the list of staged changes
20
+ STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
21
+
22
+ # Exclude files that shouldn't trigger pre-commit checks
23
+ # This is done here because `nx affected` doesn't look at task inputs
24
+ # when determining if a project is affected
25
+ EXCLUDED_FILES_REGEX='.*\.md$' # Ignore markdown files
26
+ EXCLUDED_FILES_REGEX+='|.*\/step-functions\/.*\.(yml|yaml)$' # Ignore step function yaml files
27
+ EXCLUDED_FILES_REGEX+='|^\/?([^\/]*)$' # Ignore all root-level files
28
+ AFFECTED_FILES=$(echo "$STAGED_FILES" | \
29
+ grep -vE "$EXCLUDED_FILES_REGEX" | \
30
+ paste -sd,)
31
+
32
+ echo -e "${GREEN}\nAffected files: $AFFECTED_FILES\n${NO_COLOUR}"
33
+
34
+ # Exit early if there are no affected files
35
+ if [ -z "$AFFECTED_FILES" ]; then
36
+ echo -e "${GREEN}No affected files found. Exiting pre-commit hook.${NO_COLOUR}"
37
+ exit 0
38
+ fi
39
+
40
+ # Prepare the affected commands for static analysis targets
41
+ AFFECTED_COMMAND="yarn nx affected --files=$AFFECTED_FILES --nxBail --tui=false"
42
+ commands=("$AFFECTED_COMMAND -t lint typecheck --parallel=3", "$AFFECTED_COMMAND -t test --configuration coverage")
43
+ failures=()
44
+
45
+ # Loop over commands, execute and push failure message if we see one
46
+ for cmd in "${commands[@]}"; do
47
+ $cmd
48
+ exit_code=$?
49
+
50
+ if [ "$exit_code" -eq 1 ]; then
51
+ failures+=("✖ Command ${RED}'${cmd}'${NO_COLOUR} failed with exit code ${exit_code} - see CLI output for errors")
52
+ elif [ "$exit_code" -eq 127 ]; then
53
+ failures+=("✖ Command ${RED}'${cmd}'${NO_COLOUR} failed with exit code ${exit_code} - check that the script exists in package.json")
54
+ elif [ "$exit_code" -ne 0 ]; then
55
+ failures+=("✖ Command ${RED}'${cmd}'${NO_COLOUR} failed with unexpected exit code ${exit_code}")
56
+ fi
57
+ done
58
+
59
+ # Report overall success or failure
60
+ if [ ${#failures[@]} -ne 0 ]; then
61
+ echo -e "\n🚩${RED} Couldn't commit changes dues to the following errors: ${NO_COLOUR}"
62
+
63
+ for report in "${failures[@]}"; do
64
+ echo -e $report;
65
+ done
66
+
67
+ exit 1
68
+ fi
@@ -0,0 +1,3 @@
1
+ # Both Microservice and DevOps teams own everything in this repo
2
+ # We'll review this in few months time and adjust when needed
3
+ * @aligent/microservices @aligent/devops
@@ -0,0 +1,7 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: 'npm'
4
+ directory: '/'
5
+ schedule:
6
+ interval: 'monthly'
7
+ open-pull-requests-limit: 10
@@ -0,0 +1,27 @@
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 }}
@@ -0,0 +1,62 @@
1
+ # See http://help.github.com/ignore-files/ for more about ignoring files.
2
+ # Ignore everything by default
3
+ *
4
+
5
+ # Project standard configurations
6
+ !**/*.md
7
+ !.git-hooks
8
+ !.git-hooks/*
9
+ !.github
10
+ !.github/*
11
+ !.github/**/*
12
+ !.editorconfig
13
+ !.gitignore
14
+ !.nvmrc
15
+ !.prettierignore
16
+ !cdk-config.yml
17
+ !eslint.config.mjs
18
+ !LICENSE
19
+ !nx.json
20
+ !package.json
21
+ !prettier.config.mjs
22
+ !rolldown.config.base.mjs
23
+ !tsconfig.json
24
+ !vitest.global.setup.mjs
25
+ !vitest.config.base.mjs
26
+
27
+ # Package manager
28
+ !.yarn
29
+ !.yarn/patches
30
+ !.yarn/plugins
31
+ !.yarn/plugins/*
32
+ !.yarn/plugins/**/*
33
+ !.yarn/releases
34
+ !.yarn/sdks
35
+ !.yarn/versions
36
+ !.yarnrc.yml
37
+ !yarn.lock
38
+
39
+ # Application
40
+ !application
41
+ !application/*
42
+ !application/**/*
43
+ !collection
44
+ !collection/*
45
+ !collection/**/*
46
+ !docs
47
+ !docs/*
48
+ !docs/**/*
49
+ !libs
50
+ !libs/*
51
+ !libs/**/*
52
+ !services
53
+ !services/*
54
+ !services/**/*
55
+
56
+ # Test and bundle artifacts
57
+ **/cdk.out
58
+ **/dist
59
+ **/coverage
60
+
61
+ # Environment files
62
+ *.env
@@ -0,0 +1 @@
1
+ v<%= nodeVersion %>
@@ -0,0 +1,10 @@
1
+ # Add files here to ignore them from prettier formatting
2
+
3
+ # Build and test artifacts
4
+ **/dist
5
+ **/coverage
6
+
7
+ # Tools, misc and autogenerated files
8
+ .nx
9
+ **/tsconfig.*
10
+ yarn.lock
@@ -0,0 +1,6 @@
1
+ nodeLinker: node-modules
2
+
3
+ plugins:
4
+ - checksum: e5e6e2885ab0e6521b70b0af7c6d8ca2c75dcae2403706fc4600a783b339a6530a476dafb9450c9436ca4050eb6bdee9b62e6e2cebfecf1e81dd709a2480dc07
5
+ path: .yarn/plugins/@yarnpkg/plugin-engines.cjs
6
+ spec: 'https://raw.githubusercontent.com/devoto13/yarn-plugin-engines/main/bundles/%40yarnpkg/plugin-engines.js'
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Aligent
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,77 @@
1
+ # <%= projectName %> Integrations
2
+
3
+ A monorepo containing integration services that support the <%= projectName %> project. This repository manages the deployment of microservices and their shared infrastructure using AWS CDK.
4
+
5
+ ## Overview
6
+
7
+ <!-- Add an overview of the whole system -->
8
+
9
+ ## Services
10
+
11
+ Services deployment are managed by the main [CDK Application](./application/README.md)
12
+
13
+ <!-- List services here with link to the service read me file -->
14
+ <!-- Eg: [User Management](../services/user-management/README.md) -->
15
+
16
+ ## Project Structure
17
+
18
+ ```
19
+ <%= folderName %>/
20
+ ├── application/ # CDK Application & orchestration
21
+ │ ├── bin/main.ts # CDK App entry point (development/staging/production stages)
22
+ │ ├── lib/ # Service stack composition
23
+ │ └── cdk.json # CDK configuration
24
+
25
+ ├── services/ # Microservices workspace
26
+
27
+ ├── nx.json # Nx monorepo configuration
28
+ ├── rolldown.config.base.mjs # Base Lambda bundling config
29
+ ├── vitest.config.base.mjs # Base test configuration
30
+ └── eslint.config.mjs # ESLint configuration
31
+ ```
32
+
33
+ ## Getting Started
34
+
35
+ ### Prerequisites
36
+
37
+ - Node.js <%= nodeVersion %> (see [.nvmrc](.nvmrc))
38
+ - Yarn 4.12.0+
39
+ - AWS CLI configured with appropriate credentials
40
+
41
+ ### Installation
42
+
43
+ ```bash
44
+ # Use correct Node version
45
+ nvm use
46
+
47
+ # Install dependencies
48
+ yarn install
49
+ ```
50
+
51
+ ## Contributing
52
+
53
+ We follow [trunk-based development framework](https://trunkbaseddevelopment.com/) as a start and will evolve depending on our need.
54
+
55
+ 1. Create new branch from `main`
56
+ 2. Make your changes following code standards
57
+ 3. Ensure your changes pass linting, type checks and testes
58
+ 4. Submit a pull request back to `main`
59
+ 5. For deployment, submit a pull request from `main` to `staging` or `production`
60
+
61
+ ## Adding New Services
62
+
63
+ To add a new service to the monorepo:
64
+
65
+ 1. Use the Aligent CDK generator `@aligent/nx-cdk`
66
+ 2. Add service infrastructure in
67
+ - `services/{service-name}/src/index.ts`
68
+ - `services/{service-name}/src/infra/`
69
+ 3. Add Lambda handlers in `services/{service-name}/src/runtime/handlers/`
70
+
71
+ ## License
72
+
73
+ MIT
74
+
75
+ ## Support
76
+
77
+ For questions or issues, please contact the Aligent Microservices guild.
@@ -0,0 +1,61 @@
1
+ # Application
2
+
3
+ This application manages the deployment of microservices and their shared infrastructure.
4
+
5
+ ## Configuration
6
+
7
+ ### Environment Parameters
8
+
9
+ Parameters are managed through the `parameters/.env.csv` file by default
10
+
11
+ ```bash
12
+ # Pull down parameters from the playground environment to .env.csv
13
+ yarn nx run application:parameters
14
+
15
+ # Update parameters from .env.csv
16
+ yarn nx run application:parameters:import
17
+
18
+ # Custom filename and parameter path can be passed in as arguments
19
+ yarn nx run application:parameters --file .env.dev.csv --path /my/dev/path
20
+ ```
21
+
22
+ ## Deployment
23
+
24
+ ### Using yarn script from workspace root (Recommended)
25
+
26
+ ```bash
27
+ # Synthesize templates
28
+ yarn pg:synth
29
+
30
+ # Deploy to playground
31
+ yarn pg:deploy
32
+ ```
33
+
34
+ ### Direct Nx Commands
35
+
36
+ ```bash
37
+ yarn nx run application:cdk <command> <args>
38
+ ```
39
+
40
+ ## Testing
41
+
42
+ ### Mock Services
43
+
44
+ The application may include mock services for testing integrations without external dependencies.
45
+
46
+ <!-- list mock services here -->
47
+
48
+ Change the value of the `/application/dev/url` SSM Parameter to switch between real and mock endpoints
49
+
50
+ ### Local Development
51
+
52
+ ```bash
53
+ # Type checking
54
+ yarn typecheck
55
+
56
+ # Testing
57
+ yarn test
58
+
59
+ # Linting
60
+ yarn lint
61
+ ```
@@ -0,0 +1,100 @@
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
+ }
@@ -0,0 +1,58 @@
1
+ import { CfnResource } from 'aws-cdk-lib';
2
+ import { NagMessageLevel, NagPack, rules, type NagPackProps } from 'cdk-nag';
3
+ import type { IConstruct } from 'constructs';
4
+
5
+ /**
6
+ * Microservice Checks are a compilation of rules to validate infrastructure-as-code template
7
+ * against recommended practices using the cdk-nag library.
8
+ *
9
+ * @see https://github.com/cdk-patterns/cdk-nag/
10
+ *
11
+ * @example
12
+ * const app = new App();
13
+ * const stack = new Stack(app, 'MyStack');
14
+ * Aspects.of(stack).add(new MicroservicesChecks());
15
+ */
16
+ export class MicroserviceChecks extends NagPack {
17
+ constructor(props?: NagPackProps) {
18
+ super(props);
19
+ this.packName = 'Microservices';
20
+ }
21
+
22
+ public visit(node: IConstruct) {
23
+ if (node instanceof CfnResource) {
24
+ this.applyRule({
25
+ info: 'The Lambda function does not have an explicit memory value configured.',
26
+ explanation:
27
+ "Lambda allocates CPU power in proportion to the amount of memory configured. By default, your functions have 128 MB of memory allocated. You can increase that value up to 10 GB. With more CPU resources, your Lambda function's duration might decrease. You can use tools such as AWS Lambda Power Tuning to test your function at different memory settings to find the one that matches your cost and performance requirements the best.",
28
+ level: NagMessageLevel.ERROR,
29
+ rule: rules.lambda.LambdaDefaultMemorySize,
30
+ node: node,
31
+ });
32
+ this.applyRule({
33
+ info: 'The Lambda function does not have an explicitly defined timeout value.',
34
+ explanation:
35
+ 'Lambda functions have a default timeout of 3 seconds. If your timeout value is too short, Lambda might terminate invocations prematurely. On the other side, setting the timeout much higher than the average execution may cause functions to execute for longer upon code malfunction, resulting in higher costs and possibly reaching concurrency limits depending on how such functions are invoked. You can also use AWS Lambda Power Tuning to test your function at different timeout settings to find the one that matches your cost and performance requirements the best.',
36
+ level: NagMessageLevel.ERROR,
37
+ rule: rules.lambda.LambdaDefaultTimeout,
38
+ node: node,
39
+ });
40
+ this.applyRule({
41
+ info: 'The Lambda function does not have tracing set to Tracing.ACTIVE.',
42
+ explanation:
43
+ 'When a Lambda function has ACTIVE tracing, Lambda automatically samples invocation requests, based on the sampling algorithm specified by X-Ray.',
44
+ level: NagMessageLevel.ERROR,
45
+ rule: rules.lambda.LambdaTracing,
46
+ node: node,
47
+ });
48
+ this.applyRule({
49
+ info: 'The CloudWatch Log Group does not have an explicit retention policy defined.',
50
+ explanation:
51
+ 'By default, logs are kept indefinitely and never expire. You can adjust the retention policy for each log group, keeping the indefinite retention, or choosing a retention period between one day and 10 years. For Lambda functions, this applies to their automatically created CloudWatch Log Groups.',
52
+ level: NagMessageLevel.ERROR,
53
+ rule: rules.cloudwatch.CloudWatchLogGroupRetentionPeriod,
54
+ node: node,
55
+ });
56
+ }
57
+ }
58
+ }
@@ -0,0 +1,110 @@
1
+ import { type IPropertyInjector } from 'aws-cdk-lib';
2
+ import { Runtime, Tracing } from 'aws-cdk-lib/aws-lambda';
3
+ import { NodejsFunction, type NodejsFunctionProps } from 'aws-cdk-lib/aws-lambda-nodejs';
4
+
5
+ interface Config {
6
+ runtime: Runtime;
7
+ sourceMap?: boolean;
8
+ }
9
+
10
+ /**
11
+ * Property injector for Node.js Lambda functions with configuration-aware defaults
12
+ *
13
+ * Applies configuration-specific bundling and runtime settings to Lambda functions.
14
+ * Different configurations can optimize for different priorities such as build speed,
15
+ * bundle size, or debugging capabilities.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * // Apply configuration-specific defaults
20
+ * PropertyInjectors.of(scope).add(
21
+ * new NodeJsFunctionDefaultsInjector({
22
+ * sourceMaps: true,
23
+ * esm: true,
24
+ * minify: true,
25
+ * }).withProps({
26
+ * timeout: Duration.seconds(30),
27
+ * memorySize: 256,
28
+ * })
29
+ * );
30
+ *
31
+ * // Functions automatically inherit configuration defaults
32
+ * new Function(stack, 'MyFunction', {
33
+ * code: Code.fromAsset('src/lambda'),
34
+ * handler: 'index.handler',
35
+ * // bundling and runtime config applied automatically
36
+ * });
37
+ * ```
38
+ *
39
+ * @see https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs.NodejsFunction.html
40
+ */
41
+ export class NodeJsFunctionDefaultsInjector implements IPropertyInjector {
42
+ public readonly constructUniqueId = NodejsFunction.PROPERTY_INJECTION_ID;
43
+ private readonly config: Required<Config>;
44
+ private defaultProps: NodejsFunctionProps;
45
+
46
+ /**
47
+ * Creates a new NodeJsFunctionDefaultsInjector
48
+ *
49
+ * @param config - Configuration identifier used to select appropriate defaults. Uses production defaults if not specified.
50
+ */
51
+ constructor(config: Config) {
52
+ this.config = { ...config, sourceMap: config.sourceMap || true };
53
+ this.defaultProps = { runtime: config.runtime, tracing: Tracing.ACTIVE };
54
+ }
55
+
56
+ /**
57
+ * Creates a new injector instance with additional properties
58
+ *
59
+ * Returns a new injector that inherits the current configuration but includes
60
+ * additional properties that override the configuration defaults.
61
+ *
62
+ * @param props - Additional properties to merge with configuration defaults
63
+ * @returns A new injector instance with merged properties
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * const customInjector = new NodeJsFunctionDefaultsInjector({
68
+ * sourceMaps: false,
69
+ * })
70
+ * .withProps({
71
+ * timeout: Duration.minutes(5),
72
+ * memorySize: 1024,
73
+ * });
74
+ * ```
75
+ *
76
+ * TODO: Provide a nice way to inherit global properties from previous injectors
77
+ */
78
+ public withProps(props: NodejsFunctionProps) {
79
+ const modifiedInjector = new NodeJsFunctionDefaultsInjector(this.config);
80
+ modifiedInjector.defaultProps = { ...this.defaultProps, ...props };
81
+ return modifiedInjector;
82
+ }
83
+
84
+ /**
85
+ * Injects configuration-appropriate defaults into Lambda function properties
86
+ *
87
+ * Merges configuration-specific defaults with user-provided properties,
88
+ * automatically configuring bundling options and runtime settings.
89
+ *
90
+ * @param originalProps - Properties provided when creating the function
91
+ * @returns Merged properties with injected defaults
92
+ */
93
+ public inject(originalProps: NodejsFunctionProps) {
94
+ // The NodeJsFunction constructor pre-sets runtime to 16.x or LATEST depending on feature flags
95
+ // We assume that using this injector means you want to standardise the runtime across all lambdas
96
+ const props = {
97
+ ...this.defaultProps,
98
+ ...originalProps,
99
+ runtime: this.defaultProps.runtime,
100
+ };
101
+
102
+ // If source maps are enabled in our bundling, add the required NODE_OPTIONS flag to the environment
103
+ const environment = {
104
+ ...props.environment,
105
+ ...(this.config.sourceMap ? { NODE_OPTIONS: '--enable-source-maps' } : {}),
106
+ };
107
+
108
+ return { ...props, environment };
109
+ }
110
+ }