Logo

dev-resources.site

for different kinds of informations.

Enabling Decorators for Lambda Functions with CDK in an Nx Monorepo

Published at
1/9/2025
Categories
cdk
typescript
aws
serverless
Author
jochenf
Categories
4 categories in total
cdk
open
typescript
open
aws
open
serverless
open
Author
7 person written this
jochenf
open
Enabling Decorators for Lambda Functions with CDK in an Nx Monorepo

Working with CDK's Node.js Lambda Function Construct

The AWS CDK provides a convenient construct for Node.js Lambda functions.

What is the NodejsFunction Construct?

According to the documentation:

The NodejsFunction construct creates a Lambda function with automatic transpiling and bundling of TypeScript or JavaScript code. This results in smaller Lambda packages that contain only the code and dependencies needed to run the function.

To perform this transpiling and bundling, it relies on esbuild.


Issue: Esbuild Lacks Support for Decorators

Unfortunately, esbuild does not support the TypeScript compiler options experimentalDecorators and emitDecoratorMetadata. This causes it to ignore decorators, leading to errors when the Lambda function is invoked. A typical error looks like this:

{
  "errorType": "MissingReflectMetadata",
  "errorMessage": "Could not reflect metadata of type design:type, did you forget to enable 'emitDecoratorMetadata' on compiler options?",
  "stack": [
    "MissingReflectMetadata: Could not reflect metadata of type design:type, did you forget to enable 'emitDecoratorMetadata' on compiler options?",
    "    at /var/task/index.js:85333:13",
    "    at __decorateClass (/var/task/index.js:39:24)",
    "    at Object.<anonymous> (/var/task/index.js:85734:1)"
  ]
}
Enter fullscreen mode Exit fullscreen mode

Workaround: Using Pre-Compilation with TypeScript

Thankfully, the CDK provides a workaround for this issue by allowing a pre-compilation step using TypeScript (tsc). To enable this, simply set the preCompilation flag in the bundling options:

new nodejs.NodejsFunction(this, 'my-handler', {
  bundling: {
    preCompilation: true,
  },
});
Enter fullscreen mode Exit fullscreen mode

Challenges in an Nx Monorepo

In an Nx monorepo, projects are organized into apps and libraries that share a common tsconfig.base.json file at the root. This file defines path aliases for libraries, enabling easy imports like this:

import doingX from '@MyComp/MyLibrary'
Enter fullscreen mode Exit fullscreen mode

The relevant section in tsconfig.base.json might look like this:

{
  "compilerOptions": {
    "paths": {
       "@MyComp/MyLibrary": [
                "libs/shared/MyLibrary/src/index.ts"
            ],
    },
}
Enter fullscreen mode Exit fullscreen mode

Unfortunately, the tsc step used in CDK's pre-compilation process does not respect the paths configuration, resulting in errors like:

Cannot find module '@MyComp/MyLibrary' or its corresponding type declarations
Enter fullscreen mode Exit fullscreen mode

Since we don't have control over how the CDK runs the tsc command it's difficult to modify this behavior.

Solution: Custom Build Script

The CDK provides an escape hatch by allowing developers to run a custom-build script as part of the CDK synthesis process.

Here’s an example of such a script using esbuild and the esbuild-plugin-tsc plugin:

import path from 'path';
import esbuild from 'esbuild';
import esbuildPluginTsc from 'esbuild-plugin-tsc';

await esbuild
  .build({
    entryPoints: [path.join(__dirname, 'handler', 'index.ts')],
    outfile: path.join(__dirname, 'build-output', 'index.js'),
    external: ['@aws-sdk/*', 'aws-sdk'],
    format: 'cjs',
    platform: 'node',
    target: 'node18',
    bundle: true,
    minify: true,
    plugins: [esbuildPluginTsc()]],
  })
  .catch((error) => {
    console.log(error);
    process.exit(1)
  });

Enter fullscreen mode Exit fullscreen mode

Why Use esbuild-plugin-tsc?

The esbuild-plugin-tsc plugin integrates with TypeScript’s compiler, ensuring that all TypeScript options -including paths- are respected. This enables the seamless compiling of files with decorators and path aliases while retaining the benefits of esbuild for other files.

Caveats

  1. Performance Impact: Custom build scripts can slow down the bundling process.
  2. Maintenance: By adopting a custom script, you assume responsibility for maintaining it.

When to Use This Solution

Reserve this approach for cases where the default CDK configuration is insufficient. For simpler setups, the built-in preCompilation flag should suffice.

cdk Article's
30 articles in total
Favicon
Invoking Private API Gateway Endpoints From Step Functions
Favicon
Automating Cross-Account CDK Bootstrapping Using AWS Lambda
Favicon
Deploy de NextJS utilizando CDK
Favicon
Config AWS Cloudwatch Application Signals Transaction Search with CDK
Favicon
[Solved] AWS Resource limit exceeded
Favicon
Create a cross-account glue Job using AWS CDK
Favicon
Enabling Decorators for Lambda Functions with CDK in an Nx Monorepo
Favicon
Run vs code on a private AWS ec2 instance without ssh (with AWS CDK examples)
Favicon
Config AWS Cloudwatch Application Signals for NodeJs Lambda with CDK
Favicon
Deploying a Simple Static Website on AWS with CDK and TypeScript
Favicon
AWS Architectural Diagrams on a Commit Base: Using AWS PDK Diagram Plugin with Python
Favicon
AWS CDK Aspects specifications have changed
Favicon
Relative Python imports in a Dockerized lambda function
Favicon
Building Scalable Infrastructure with AWS CDK: A Developer’s Guide to Best Practices
Favicon
API Gateway integration with AWS Services.
Favicon
DevSecOps with AWS- IaC at scale - Building your own platform – Part 3 - Pipeline as a Service
Favicon
AWS Cloud Development Kit (CDK) vs. Terraform
Favicon
Query your EventBridge Scheduled Events in DynamoDB
Favicon
AWS CDK context validation
Favicon
How to combine SQS and SNS to implement multiple Consumers (Part 2)
Favicon
Serverless Code-Signing (EV) with KMS and Fargate
Favicon
How to build an API with Lambdas, API Gateway and deploy with AWS CDK
Favicon
The Journey of CDK.dev: From Static Site to Bluesky
Favicon
Create an Asset Store with a Custom Domain using AWS CDK, Route53, S3 and CloudFront
Favicon
Crafting a Scalable Node.js API: Insights from My RealWorld Project with Express, Knex, and AWS CDK
Favicon
Techniques to Save Costs Using AWS Lambda Functions with CDK
Favicon
Deploy a Docker Image to ECS with Auto Scaling Using AWS CDK in Minutes
Favicon
AWS CDK + Localstack (API Gateway, Lambda, SQS, DynamoDB,TypeScript)
Favicon
Simplifying Cloud Infrastructure with AWS CDK
Favicon
Effortless Debugging: AWS CDK TypeScript Projects in VSCode

Featured ones: