aws / aws-sam-cli

CLI tool to build, test, debug, and deploy Serverless applications using AWS SAM

Home Page:https://aws.amazon.com/serverless/sam/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Bug: CDK typescript project fails with "Runtime.ImportModuleError" when running sam local

yiluhe-fpd opened this issue · comments

commented

Created cdk project using "cdk init app --language typescript", added lambda and api gateway which works if I simple replies to GET / POST calls with dummy data.

Added the following code to use jsonwebtoken.
import * as jwt from 'jsonwebtoken'; export const parseJwtToken = (event: APIGatewayProxyEvent): JwtToken => { const authToken = event.headers['Authorization'] || event.headers['authorization']; const token = authToken.split(' ')[1]; const decoded = jwt.verify(token, process.env.JWT_SECRET!) as jwt.JwtPayload; if (!decoded.sub) { return { subject: null } } };

The packages are installed and shown in the package.json file
"dependencies": { "@types/jsonwebtoken": "^9.0.6", "aws-cdk-lib": "2.138.0", "constructs": "^10.0.0", "jsonwebtoken": "^9.0.2", "source-map-support": "^0.5.21" }

Run the following step to build/start SAM

  1. npm run build
  2. cdk synth --no-staging
  3. sam build -t ./cdk.out/EmployerApiStack.template.json
  4. sam local start-api -t ./cdk.out/EmployerApiStack.template.json

When hitting the api with using postman, I got the error noted above.

Observed result:

sam local start-api --debug -t ./cdk.out/EmployerApiStack.template.json
2024-04-29 23:52:10,278 | Using SAM Template at D:_FPD\payapp\employer-api\cdk.out\EmployerApiStack.template.json
2024-04-29 23:52:10,281 | No config file found in this directory.
2024-04-29 23:52:10,283 | OSError occurred while reading TOML file: [Errno 2] No such file or directory: 'D:\_FPD\payapp\employer-api\cdk.out\samconfig.toml'
2024-04-29 23:52:10,284 | Config file location: D:_FPD\payapp\employer-api\cdk.out\samconfig.toml
2024-04-29 23:52:10,285 | Config file 'D:_FPD\payapp\employer-api\cdk.out\samconfig.toml' does not exist
2024-04-29 23:52:10,302 | OSError occurred while reading TOML file: [Errno 2] No such file or directory: 'D:\_FPD\payapp\employer-api\cdk.out\samconfig.toml'
2024-04-29 23:52:10,304 | Using config file: samconfig.toml, config environment: default
2024-04-29 23:52:10,304 | Expand command line arguments to:
2024-04-29 23:52:10,305 | --template_file=D:_FPD\payapp\employer-api\cdk.out\EmployerApiStack.template.json --host=127.0.0.1 --port=3000 --static_dir=public
--layer_cache_basedir=C:\Users\kokot\AppData\Roaming\AWS SAM\layers-pkg --container_host=localhost --container_host_interface=127.0.0.1
2024-04-29 23:52:10,395 | local start-api command is called
2024-04-29 23:52:10,396 | Collected default values for parameters: {'BootstrapVersion': '/cdk-bootstrap/hnb659fds/version'}
2024-04-29 23:52:10,416 | CDK Path for resource EmployerLambdaServiceRole00D1C4FB is ['EmployerApiStack', 'EmployerLambda', 'ServiceRole', 'Resource']
2024-04-29 23:52:10,417 | CDK Path for resource EmployerLambdaServiceRoleDefaultPolicy7FC77184 is ['EmployerApiStack', 'EmployerLambda', 'ServiceRole', 'DefaultPolicy', 'Resource']
2024-04-29 23:52:10,419 | CDK Path for resource EmployerLambdaBF758BBE is ['EmployerApiStack', 'EmployerLambda', 'Resource']
2024-04-29 23:52:10,421 | CDK Path for resource EmployerTableC63ED560 is ['EmployerApiStack', 'EmployerTable', 'Resource']
2024-04-29 23:52:10,422 | CDK Path for resource EmployerApi75F260C4 is ['EmployerApiStack', 'EmployerApi', 'Resource']
2024-04-29 23:52:10,423 | CDK Path for resource EmployerApiDeployment0BDE00401d48bfbc2c2b86101337151fb9abd9f4 is ['EmployerApiStack', 'EmployerApi', 'Deployment', 'Resource']
2024-04-29 23:52:10,425 | CDK Path for resource EmployerApiDeploymentStageprodC4CFBAC0 is ['EmployerApiStack', 'EmployerApi', 'DeploymentStage.prod', 'Resource']
2024-04-29 23:52:10,425 | CDK Path for resource EmployerApiemployers39D0344D is ['EmployerApiStack', 'EmployerApi', 'Default', 'employers', 'Resource']
2024-04-29 23:52:10,427 | CDK Path for resource EmployerApiemployersGETApiPermissionEmployerApiStackEmployerApi16A32E8DGETemployers997DB134 is ['EmployerApiStack', 'EmployerApi', 'Default', 'employers', 'GET',
'ApiPermission.EmployerApiStackEmployerApi16A32E8D.GET..employers']
2024-04-29 23:52:10,428 | CDK Path for resource EmployerApiemployersGETApiPermissionTestEmployerApiStackEmployerApi16A32E8DGETemployers8B296932 is ['EmployerApiStack', 'EmployerApi', 'Default', 'employers',
'GET', 'ApiPermission.Test.EmployerApiStackEmployerApi16A32E8D.GET..employers']
2024-04-29 23:52:10,429 | CDK Path for resource EmployerApiemployersGET436B0A2F is ['EmployerApiStack', 'EmployerApi', 'Default', 'employers', 'GET', 'Resource']
2024-04-29 23:52:10,430 | CDK Path for resource EmployerApiemployersPOSTApiPermissionEmployerApiStackEmployerApi16A32E8DPOSTemployers8EF3A42A is ['EmployerApiStack', 'EmployerApi', 'Default', 'employers',
'POST', 'ApiPermission.EmployerApiStackEmployerApi16A32E8D.POST..employers']
2024-04-29 23:52:10,432 | CDK Path for resource EmployerApiemployersPOSTApiPermissionTestEmployerApiStackEmployerApi16A32E8DPOSTemployersC742DEDA is ['EmployerApiStack', 'EmployerApi', 'Default', 'employers',
'POST', 'ApiPermission.Test.EmployerApiStackEmployerApi16A32E8D.POST..employers']
2024-04-29 23:52:10,433 | CDK Path for resource EmployerApiemployersPOST6EE88D13 is ['EmployerApiStack', 'EmployerApi', 'Default', 'employers', 'POST', 'Resource']
2024-04-29 23:52:10,434 | CDK Path for resource CDKMetadata is ['EmployerApiStack', 'CDKMetadata', 'Default']
2024-04-29 23:52:10,436 | 0 stacks found in the template
2024-04-29 23:52:10,437 | Collected default values for parameters: {'BootstrapVersion': '/cdk-bootstrap/hnb659fds/version'}
2024-04-29 23:52:10,453 | CDK Path for resource EmployerLambdaServiceRole00D1C4FB is ['EmployerApiStack', 'EmployerLambda', 'ServiceRole', 'Resource']
2024-04-29 23:52:10,454 | CDK Path for resource EmployerLambdaServiceRoleDefaultPolicy7FC77184 is ['EmployerApiStack', 'EmployerLambda', 'ServiceRole', 'DefaultPolicy', 'Resource']
2024-04-29 23:52:10,456 | CDK Path for resource EmployerLambdaBF758BBE is ['EmployerApiStack', 'EmployerLambda', 'Resource']
2024-04-29 23:52:10,457 | CDK Path for resource EmployerTableC63ED560 is ['EmployerApiStack', 'EmployerTable', 'Resource']
2024-04-29 23:52:10,458 | CDK Path for resource EmployerApi75F260C4 is ['EmployerApiStack', 'EmployerApi', 'Resource']
2024-04-29 23:52:10,459 | CDK Path for resource EmployerApiDeployment0BDE00401d48bfbc2c2b86101337151fb9abd9f4 is ['EmployerApiStack', 'EmployerApi', 'Deployment', 'Resource']
2024-04-29 23:52:10,460 | CDK Path for resource EmployerApiDeploymentStageprodC4CFBAC0 is ['EmployerApiStack', 'EmployerApi', 'DeploymentStage.prod', 'Resource']
2024-04-29 23:52:10,461 | CDK Path for resource EmployerApiemployers39D0344D is ['EmployerApiStack', 'EmployerApi', 'Default', 'employers', 'Resource']
2024-04-29 23:52:10,461 | CDK Path for resource EmployerApiemployersGETApiPermissionEmployerApiStackEmployerApi16A32E8DGETemployers997DB134 is ['EmployerApiStack', 'EmployerApi', 'Default', 'employers', 'GET',
'ApiPermission.EmployerApiStackEmployerApi16A32E8D.GET..employers']
2024-04-29 23:52:10,462 | CDK Path for resource EmployerApiemployersGETApiPermissionTestEmployerApiStackEmployerApi16A32E8DGETemployers8B296932 is ['EmployerApiStack', 'EmployerApi', 'Default', 'employers',
'GET', 'ApiPermission.Test.EmployerApiStackEmployerApi16A32E8D.GET..employers']
2024-04-29 23:52:10,463 | CDK Path for resource EmployerApiemployersGET436B0A2F is ['EmployerApiStack', 'EmployerApi', 'Default', 'employers', 'GET', 'Resource']
2024-04-29 23:52:10,464 | CDK Path for resource EmployerApiemployersPOSTApiPermissionEmployerApiStackEmployerApi16A32E8DPOSTemployers8EF3A42A is ['EmployerApiStack', 'EmployerApi', 'Default', 'employers',
'POST', 'ApiPermission.EmployerApiStackEmployerApi16A32E8D.POST..employers']
2024-04-29 23:52:10,465 | CDK Path for resource EmployerApiemployersPOSTApiPermissionTestEmployerApiStackEmployerApi16A32E8DPOSTemployersC742DEDA is ['EmployerApiStack', 'EmployerApi', 'Default', 'employers',
'POST', 'ApiPermission.Test.EmployerApiStackEmployerApi16A32E8D.POST..employers']
2024-04-29 23:52:10,466 | CDK Path for resource EmployerApiemployersPOST6EE88D13 is ['EmployerApiStack', 'EmployerApi', 'Default', 'employers', 'POST', 'Resource']
2024-04-29 23:52:10,466 | CDK Path for resource CDKMetadata is ['EmployerApiStack', 'CDKMetadata', 'Default']
2024-04-29 23:52:10,470 | 15 resources found in the stack
2024-04-29 23:52:10,470 | Found Lambda function with name='EmployerLambdaBF758BBE' and CodeUri='D:_FPD\payapp\employer-api\src'
2024-04-29 23:52:10,471 | --base-dir is not presented, adjusting uri D:_FPD\payapp\employer-api\src relative to D:_FPD\payapp\employer-api\cdk.out\EmployerApiStack.template.json
2024-04-29 23:52:10,477 | Skipping resource 'EmployerApi75F260C4'. Swagger document not found in Body and BodyS3Location
2024-04-29 23:52:10,478 | Extracted Function ARN: arn:aws:lambda:us-east-1:123456789012:function:EmployerLambdaBF758BBE
2024-04-29 23:52:10,479 | Extracted Function ARN: arn:aws:lambda:us-east-1:123456789012:function:EmployerLambdaBF758BBE
2024-04-29 23:52:10,480 | 1 APIs found in the template
2024-04-29 23:52:10,485 | Mounting EmployerLambdaBF758BBE at http://127.0.0.1:3000/employers [GET, POST]
2024-04-29 23:52:10,486 | You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected
instantly/automatically. If you used sam build before running local commands, you will need to re-run sam build for the changes to be picked up. You only need to restart SAM CLI if you update your AWS SAM
template
2024-04-29 23:52:10,488 | Localhost server is starting up. Multi-threading = True
2024-04-29 23:52:10,488 | Setting SIGTERM interrupt handler
2024-04-29 23:52:10 WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.

2024-04-29 23:53:45,627 | Constructed Event 1.0 to invoke Lambda. Event: {'httpMethod': 'GET', 'body': None, 'resource': '/employers', 'requestContext': {'resourceId': '123456', 'apiId': '1234567890',
'resourcePath': '/employers', 'httpMethod': 'GET', 'requestId': '0164a0ce-48bf-4fd3-8613-bad5dff26b9f', 'accountId': '123456789012', 'stage': 'prod', 'identity': {'apiKey': None, 'userArn': None,
'cognitoAuthenticationType': None, 'caller': None, 'userAgent': 'Custom User Agent String', 'user': None, 'cognitoIdentityPoolId': None, 'cognitoAuthenticationProvider': None, 'sourceIp': '127.0.0.1',
'accountId': None}, 'extendedRequestId': None, 'path': '/employers', 'protocol': 'HTTP/1.1', 'domainName': '127.0.0.1:3000', 'requestTimeEpoch': 1714449130, 'requestTime': '30/Apr/2024:03:52:10 +0000'},
'queryStringParameters': None, 'multiValueQueryStringParameters': None, 'headers': {'User-Agent': 'PostmanRuntime/7.37.3', 'Accept': '/', 'Postman-Token': 'cc86ea4d-a3ef-41f3-8137-da7b19f53bbe', 'Host':
'127.0.0.1:3000', 'Accept-Encoding': 'gzip, deflate, br', 'Connection': 'keep-alive', 'X-Forwarded-Proto': 'http', 'X-Forwarded-Port': '3000'}, 'multiValueHeaders': {'User-Agent': ['PostmanRuntime/7.37.3'],
'Accept': ['/'], 'Postman-Token': ['cc86ea4d-a3ef-41f3-8137-da7b19f53bbe'], 'Host': ['127.0.0.1:3000'], 'Accept-Encoding': ['gzip, deflate, br'], 'Connection': ['keep-alive'], 'X-Forwarded-Proto': ['http'],
'X-Forwarded-Port': ['3000']}, 'pathParameters': None, 'stageVariables': None, 'path': '/employers', 'isBase64Encoded': False}
2024-04-29 23:53:45,634 | Found one Lambda function with name 'EmployerLambdaBF758BBE'
2024-04-29 23:53:45,635 | Invoking index.handler (nodejs20.x)
2024-04-29 23:53:45,636 | No environment variables found for function 'EmployerLambdaBF758BBE'
2024-04-29 23:53:45,637 | Loading AWS credentials from session with profile 'None'
2024-04-29 23:53:47,660 | Resolving code path. Cwd=D:_FPD\payapp\employer-api\cdk.out, CodeUri=D:_FPD\payapp\employer-api\src
2024-04-29 23:53:47,664 | Resolved absolute path to code is D:_FPD\payapp\employer-api\src
2024-04-29 23:53:47,666 | Resolving code path. Cwd=D:_FPD\payapp\employer-api\cdk.out, CodeUri=D:_FPD\payapp\employer-api\src
2024-04-29 23:53:47,670 | Resolved real code path to D:_FPD\payapp\employer-api\src
2024-04-29 23:53:47,672 | Code D:_FPD\payapp\employer-api\src is not a zip/jar file
2024-04-29 23:53:48,356 | Local image is up-to-date
2024-04-29 23:53:48,362 | Checking free port on 127.0.0.1:5433
2024-04-29 23:53:48,366 | Using local image: public.ecr.aws/lambda/nodejs:20-rapid-x86_64.

2024-04-29 23:53:48,368 | Mounting D:_FPD\payapp\employer-api\src as /var/task:ro,delegated, inside runtime container
2024-04-29 23:53:49,455 | Starting a timer for 3 seconds for function 'EmployerLambda'
2024-04-29 23:53:49,456 | Getting lock for the key localhost-5433
2024-04-29 23:53:49,457 | Waiting to retrieve the lock (localhost-5433) to start invocation
START RequestId: 39770929-bf87-484c-90a9-b91b762ffc11 Version: $LATEST
2024-04-30T03:53:50.652Z undefined ERROR Uncaught Exception {"errorType":"Runtime.ImportModuleError","errorMessage":"Error: Cannot find module 'jsonwebtoken'\nRequire stack:\n- /var/task/common.js\n- /var/task/index.js\n- /var/runtime/index.mjs","stack":["Runtime.ImportModuleError: Error: Cannot find module 'jsonwebtoken'","Require stack:","- /var/task/common.js","- /var/task/index.js","- /var/runtime/index.mjs"," at _loadUserApp (file:///var/runtime/index.mjs:1087:17)"," at async UserFunction.js.module.exports.load (file:///var/runtime/index.mjs:1119:21)"," at async start (file:///var/runtime/index.mjs:1282:23)"," at async file:///var/runtime/index.mjs:1288:1"]}
30 Apr 2024 03:53:50,665 [ERROR] (rapid) Init failed error=Runtime exited with error: exit status 129 InvokeID=
30 Apr 2024 03:53:50,666 [ERROR] (rapid) Invoke failed error=Runtime exited with error: exit status 129 InvokeID=d2e58fc2-0e34-4c17-8dc3-c121d015505a
30 Apr 2024 03:53:50,666 [ERROR] (rapid) Invoke DONE failed: Sandbox.Failure

2024-04-29 23:53:51,692 | [Container state] OOMKilled False
2024-04-29 23:53:52,014 | Cleaning all decompressed code dirs
2024-04-29 23:53:52,016 | Unable to find Click Context for getting session_id.
2024-04-29 23:53:52 127.0.0.1 - - [29/Apr/2024 23:53:52] "GET /employers HTTP/1.1" 500 -

Expected result:

Additional environment details (Ex: Windows, Mac, Amazon Linux etc)

  1. OS: Windows
  2. sam --version: 1.115.0
  3. AWS region: NA, local
# Paste the output of `sam --info` here
{
  "version": "1.115.0",
  "system": {
    "python": "3.11.8",
    "os": "Windows-10-10.0.22621-SP0"
  },
  "additional_dependencies": {
    "docker_engine": "25.0.3",
    "aws_cdk": "Not available",
    "terraform": "Not available"
  },
  "available_beta_feature_env_vars": [
    "SAM_CLI_BETA_FEATURES",
    "SAM_CLI_BETA_BUILD_PERFORMANCE",
    "SAM_CLI_BETA_TERRAFORM_SUPPORT",
    "SAM_CLI_BETA_RUST_CARGO_LAMBDA"
  ]
}

Add --debug flag to command you are running

Hey @yiluhe-fpd, can I see some more of your configuration? I was able to get it to work on my end. My setup looks like

CDK Lambda function config

new nodejs.NodejsFunction(this, "MyFunction", {
      entry: path.join(__dirname, "../functions/app.ts"),
      handler: "parseJwtToken",
      runtime: Runtime.NODEJS_20_X,
      timeout: Duration.minutes(15),
      bundling: {
        minify: true,
      },
});

Lambda function code

export const parseJwtToken = (event: APIGatewayProxyEvent): LambdaResponse => {
  const authToken =
    event.headers["Authorization"] || event.headers["authorization"];

  if (!authToken) {
    return { statusCode: 500, body: JSON.stringify({ something: "failed" }) };
  }

  const token = authToken.split(" ")[1];
  const decoded = jwt.verify(token, process.env.JWT_SECRET!) as jwt.JwtPayload;
  if (!decoded.sub) {
    return { statusCode: 500, body: JSON.stringify({ something: "failed" }) };
  }

  return { statusCode: 200, body: JSON.stringify({ something: "succeeded" }) };
};

Also to note, with this setup you shouldn't be running sam build. The cdk synth should take care of building the function code and generating required assets in the construct.

commented

Hello and thank you for the response. My CDK code for Lambda definition is the following. It is using the FunctionProps as mentioned here: https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda.FunctionProps.html. It is not the same as your approach and I would like to understand the difference, and if there is way to fix my approach.

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
// import * as sqs from 'aws-cdk-lib/aws-sqs';

export class EmployerApiStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);

// Define the Lambda function
const myLambda = new lambda.Function(this, 'EmployerLambda', {
  runtime: lambda.Runtime.NODEJS_20_X,
  handler: 'index.handler',
  code: lambda.Code.fromAsset('./src'),
});

}
}

Can you try using the L2 NodejsFunction construct and see if that fixes the issue for you?

commented

Great! Using NodejsFunction works! Can you tell me what's difference between the 2 approach? I see the following output when running CDK Synth with NodejsFunction, which didn't happen with lambda.Function. Is it a bug related to lambda.Function?

[+] Building 52.5s (14/14) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 1.30kB 0.0s
=> [internal] load metadata for public.ecr.aws/sam/build-nodejs20.x:latest 0.8s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [ 1/10] FROM public.ecr.aws/sam/build-nodejs20.x:latest@sha256:a69eaec5c26548c5acc107db8f99ece8d394a4c60b9ff 30.1s
=> => resolve public.ecr.aws/sam/build-nodejs20.x:latest@sha256:a69eaec5c26548c5acc107db8f99ece8d394a4c60b9ffe44 0.0s
=> => sha256:acf38c9ddfa51c5d4d868ce924400c553daa359362aaeaf0f14e0d9285101970 253.59MB / 253.59MB 12.5s
=> => sha256:8c011a14df013d37d34b5382e934324551678c42cef64eea45f9bb98a5f36726 57.99MB / 57.99MB 4.2s
=> => sha256:a69eaec5c26548c5acc107db8f99ece8d394a4c60b9ffe4462c3a873059c445c 743B / 743B 0.0s
=> => sha256:406ad47f0c3370d5a13adba666f0cd74333b90ca400b8585c9c97c211c06394b 3.69kB / 3.69kB 0.0s
=> => sha256:56cc389a078d6a55ad2a6a8db2978027c1def36eaadaae3b7624784b10825c70 86.08MB / 86.08MB 5.9s
=> => sha256:d0e8c276e2e874072a3a0d2540a04040aad55193dabbc773bc51e5803eabf5ff 9.35kB / 9.35kB 0.0s
=> => sha256:7859e0802c2afa770bff9ea17043d2f8c0a7b5236caacf1e4db221a206763e2e 72.68MB / 72.68MB 8.8s
=> => sha256:2bdf27323307fb3153840f0c2bfa565404833ff5d29d8c179409cbc8dda72bd2 4.81kB / 4.81kB 6.0s
=> => extracting sha256:56cc389a078d6a55ad2a6a8db2978027c1def36eaadaae3b7624784b10825c70 5.7s
=> => sha256:cd75de67102ad6e440afb2797d14932629fd220fd899bb7d8eb0664c6b0cbf8e 2.11MB / 2.11MB 6.3s
=> => sha256:f9d26094117c5d3d2a50e920fde0269971984c5081977094e10d46d3e8cbe603 8.82MB / 8.82MB 7.1s
=> => sha256:76647c7d243e0f180441b262646e68cb45d29e9eac1a1d973c653499d2ae62e9 178.00kB / 178.00kB 7.2s
=> => sha256:9491ad7ecb21731181b9824803748618455cc27f97631fdf3f313baaee03f47e 233.90kB / 233.90kB 7.3s
=> => sha256:c15ec4da029bb9554c9392259cc84995ea304d466c1d991c623b7f7aeb6a672a 122.19kB / 122.19kB 7.4s
=> => extracting sha256:acf38c9ddfa51c5d4d868ce924400c553daa359362aaeaf0f14e0d9285101970 8.8s
=> => extracting sha256:8c011a14df013d37d34b5382e934324551678c42cef64eea45f9bb98a5f36726 3.2s
=> => extracting sha256:7859e0802c2afa770bff9ea17043d2f8c0a7b5236caacf1e4db221a206763e2e 2.2s
=> => extracting sha256:2bdf27323307fb3153840f0c2bfa565404833ff5d29d8c179409cbc8dda72bd2 0.0s
=> => extracting sha256:cd75de67102ad6e440afb2797d14932629fd220fd899bb7d8eb0664c6b0cbf8e 0.0s
=> => extracting sha256:f9d26094117c5d3d2a50e920fde0269971984c5081977094e10d46d3e8cbe603 0.7s
=> => extracting sha256:76647c7d243e0f180441b262646e68cb45d29e9eac1a1d973c653499d2ae62e9 0.0s
=> => extracting sha256:9491ad7ecb21731181b9824803748618455cc27f97631fdf3f313baaee03f47e 0.0s
=> => extracting sha256:c15ec4da029bb9554c9392259cc84995ea304d466c1d991c623b7f7aeb6a672a 0.0s
=> [ 2/10] RUN npm install --global yarn@1.22.5 8.2s
=> [ 3/10] RUN npm install --global pnpm@7.30.5 2.1s
=> [ 4/10] RUN npm install --global typescript 1.8s
=> [ 5/10] RUN npm install --global --unsafe-perm=true esbuild@0 2.8s
=> [ 6/10] RUN mkdir /tmp/npm-cache && chmod -R 777 /tmp/npm-cache && npm config --global set cache /tmp 1.2s
=> [ 7/10] RUN mkdir /tmp/yarn-cache && chmod -R 777 /tmp/yarn-cache && yarn config set cache-folder /tm 1.2s
=> [ 8/10] RUN mkdir /tmp/pnpm-cache && chmod -R 777 /tmp/pnpm-cache && pnpm config --global set store-d 1.7s
=> [ 9/10] RUN npm config --global set update-notifier false 1.2s
=> [10/10] RUN /sbin/useradd -u 1000 user && chmod 711 / 0.6s
=> exporting to image 0.3s
=> => exporting layers 0.3s
=> => writing image sha256:3c4fc5438b5454e0445ef524ede74b48ee111ca5a01ced8cbc0c8cd8b2baac14 0.0s
=> => naming to docker.io/library/cdk-3c33a81cedb01f8fc7ad2fa7b736f3a13e329372ea7acda82779dec137eb24a6 0.0s

This isn't a bug in the construct, it's just that the NodejsFunction construct provides a layer of abstraction around the base Function construct that also "builds" the function code. In SAM CLI, to build TS functions you need to specify the BuildMethod: esbuild in the function metadata. Since the produced CloudFormation configuration for the Function construct doesn't do this, SAM CLI doesn't know how to build the TS.

I recommend using the NodejsFunction construct since it addresses the issue. If you really want to test with the L1 construct, you can always add that BuildMethod property to the produced CFN template, run a sam build and then a sam local .. against the generated .aws-sam/build assets (though this is a hacky workaround that I don't recommend).

To understand more about these various constructs and how they interact with SAM CLI, you can look through these links:
https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-cdk-building.html
https://docs.aws.amazon.com/cdk/v2/guide/constructs.html

Please let us know if you have anymore questions, otherwise I will mark this issue as resolved.

commented

Thank you very much for the help and explanation. Closing the issue.

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see.
If you need more assistance, please either tag a team member or open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.