{"id":26351638,"url":"https://github.com/inqnuam/serverless-aws-lambda","last_synced_at":"2025-03-16T10:33:36.701Z","repository":{"id":57750666,"uuid":"525927990","full_name":"Inqnuam/serverless-aws-lambda","owner":"Inqnuam","description":"AWS Lambda dev tool for Serverless. Supports packaging, local invoking and local ALB and APG lambda server mocking.","archived":false,"fork":false,"pushed_at":"2025-02-07T14:45:37.000Z","size":1249,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-10T20:47:17.050Z","etag":null,"topics":["alb","apg","aws","aws-lambda","express","lambda","local","offline","serverless"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Inqnuam.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-08-17T19:29:06.000Z","updated_at":"2025-02-07T14:45:40.000Z","dependencies_parsed_at":"2024-04-28T17:44:27.808Z","dependency_job_id":"3c9d7da0-ab3b-4560-aa0d-adef8c8ad857","html_url":"https://github.com/Inqnuam/serverless-aws-lambda","commit_stats":{"total_commits":113,"total_committers":2,"mean_commits":56.5,"dds":0.04424778761061943,"last_synced_commit":"392c3e02db2e9f67f32400b5c46898ffc2b1e2a9"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Inqnuam%2Fserverless-aws-lambda","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Inqnuam%2Fserverless-aws-lambda/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Inqnuam%2Fserverless-aws-lambda/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Inqnuam%2Fserverless-aws-lambda/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Inqnuam","download_url":"https://codeload.github.com/Inqnuam/serverless-aws-lambda/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243858894,"owners_count":20359258,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alb","apg","aws","aws-lambda","express","lambda","local","offline","serverless"],"created_at":"2025-03-16T10:33:36.595Z","updated_at":"2025-03-16T10:33:36.663Z","avatar_url":"https://github.com/Inqnuam.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# serverless-aws-lambda\n\n[![NPM](https://nodei.co/npm/serverless-aws-lambda.png?compact=true)](https://nodei.co/npm/serverless-aws-lambda/)\n\n### Description\n\n\u003e AWS Lambda dev tool for Serverless. Supports packaging, local invoking with Application Load Balancer and API Gateway, S3, SQS, SNS, DynamoStream server mocking.\n\n- Plug \u0026 Play (easy to install, configure and use)\n- Highly customizable\n- Functions are bundled by [esbuild](https://github.com/evanw/esbuild)\n- Local server uses NodeJS `http` module\n- Packaging is made by [node-archiver](https://github.com/archiverjs/node-archiver)\n\n### Supported Runtimes\n\n- NodeJS\n- Python\n- Ruby\n\n### Minimum requirements\n\n- Node v18.20.4+\n- Serverless 2.0.0+ \u003c 4.0\n\n---\n\n## Table of Contents\n\n- [Installation](#installation)\n  - [Quick start](#quick-start)\n  - [Manual installation](#manual-installation)\n- [Usage](#usage)\n- [Invoke](#invoke)\n  - [Lifecycle](#lambda-execution-lifecycles)\n  - [Events](#events)\n  - [AWS Test button](#aws-console-test-button)\n  - [Function URL](#function-url)\n  - [Serverless Invoke local](#serverless-invoke-local)\n  - [AWS SDK Lambda Client](#aws-sdk)\n  - [Stream Response](#aws-lambda-response-stream)\n- [Environment variables](#environment-variables)\n- [Package](#package)\n  - [assets](#assets)\n  - [preserveDir](#preservedir)\n  - [files](#files)\n- [Deploy](#deploy)\n\n- [Advanced configuration](#advanced-configuration)\n- [Plugins](#plugins)\n- [Benchmarks](#benchmarks)\n\n### **Installation**\n\n#### **Quick start**\n\n```bash\nnpx degit github:inqnuam/serverless-aws-lambda/templates/simple my-project\ncd my-project \u0026\u0026 yarn install\nyarn start\n```\n\n#### **Manual installation**\n\nUsual node module installation...\n\n```bash\nyarn add -D serverless-aws-lambda\n# or\nnpm install -D serverless-aws-lambda\n```\n\nThen add the plugin to your serverless plugins list\n\n```yaml\nservice: myapp\n\nframeworkVersion: \"3\"\nconfigValidationMode: error\n\nplugins:\n  - serverless-aws-lambda\n```\n\n---\n\n### **Usage**\n\nStart the local server\n\n```bash\nSLS_DEBUG=\"*\" sls aws-lambda -s dev\n```\n\nDuring development the env variable `SLS_DEBUG=\"*\"` is strongly recommanded as it will print a bunch of useful information.  \nIt is also possible to set server port from the CLI with `--port` or `-p`.\n\nThis will overwrite serverless.yml custom \u003e serverless-aws-lambda \u003e port value if it is set.  \nFor more options see [advanced configuration](#advanced-configuration).\n\n---\n\n### **Invoke**\n\n#### **Lambda execution lifecycles.**\n\nSuccefull execution:\n![lambda success](https://github.com/Inqnuam/serverless-aws-lambda/blob/main/resources/invokeSuccess.png)\nFailed execution:\n![lambda error](https://github.com/Inqnuam/serverless-aws-lambda/blob/main/resources/invokeError.png)\n\n#### **Events**\n\nLocal server supports Application Load Balancer, API Gateway and Function URL endpoints out of box.\nSee [plugins](#plugins) for more triggers (SNS, SQS, etc.).  \nAppropriate `event` object is sent to the handler based on your lambda declaration.\n\n```yaml\nfunctions:\n  myAwsomeLambda:\n    handler: src/handlers/awsomeLambda.default\n    events:\n      - alb:\n          listenerArn: arn:aws:elasticloadbalancing:eu-west-3:170838072631:listener/app/myAlb/bf88e6ec8f3d91df/e653b73728d04626\n          priority: 939\n          conditions:\n            path: \"/paradise\"\n            method: GET\n```\n\nAll available local endpoints will be printed to the console when `SLS_DEBUG=\"*\"` is set.\n\n`myAwsomeLambda` is available at `http://localhost:PORT/paradise`\n\nHowever if your declare both `alb` and `http` or `httpApi` inside a single lambda `events` with the same `path` you have to specify desired server by setting `alb` or `apg` inside your request's:\n\n- header with `X-Mock-Type`.\n- or in query string with `x_mock_type`.\n\nPlease note that invoking a lambda from sls CLI (`sls invoke local -f myFunction`) will not trigger the local server. But will still make your handler ready to be invoked.\n\n#### **AWS Console `Test` button**\n\nTo invoke your Lambda like with AWS Console's `Test` button, prefix your Lambda name by `@invoke/`.  \nExample:\n\n```\nhttp://localhost:3000/@invoke/myAwsomeLambda\n```\n\n#### **Function URL**\n\nFunction URL is available with `@url/` prefix. (must be enabled inside lambda declaration).  \nExample:\n\n```yaml\nfunctions:\n  myAwsomeLambda:\n    handler: src/handlers/awsomeLambda.default\n    url: true\n```\n\n```\nhttp://localhost:3000/@url/myAwsomeLambda\n```\n\n#### **Serverless Invoke local**\n\nWorks out of box.  \n[see options](https://www.serverless.com/framework/docs/providers/aws/cli-reference/invoke-local)  \nExample:\n\n`serverless invoke local -f myAwsomeLambda`\n\n#### **AWS SDK**\n\nInvoking with `aws-sdk` Lambda Client requires to set client endpoint to local server host.\n\nExample:\n\n```js\nimport { LambdaClient, InvokeCommand } from \"@aws-sdk/client-lambda\";\n\nconst client = new LambdaClient({ region: \"us-east-1\", endpoint: \"http://localhost:3000\" });\nconst DryRun = \"DryRun\";\nconst Event = \"Event\";\nconst RequestResponse = \"RequestResponse\";\n\nconst cmd = new InvokeCommand({\n  FunctionName: \"myAwsomeLambda\",\n  InvocationType: RequestResponse,\n  Payload: Buffer.from(JSON.stringify({ foo: \"bar\" })),\n});\n\nclient\n  .send(cmd)\n  .then((data) =\u003e {\n    data.Payload = new TextDecoder(\"utf-8\").decode(data.Payload);\n    console.log(data);\n  })\n  .catch((error) =\u003e {\n    // 🥲\n    console.log(\"error\", error);\n  });\n```\n\n### **AWS Lambda Response Stream**\n\nStream responses are supported out of box through Function URL invoke or AWS SDK invoke.  \nSee example:\n\n```yaml\nfunctions:\n  myAwsomeLambda:\n    handler: src/handlers/awsomeLambda.default\n    url: # required only for Function URL invoke\n      invokeMode: RESPONSE_STREAM\n```\n\n```ts\n// awsomeLambda.ts\nimport stream from \"stream\";\nimport { promisify } from \"util\";\nconst pipeline = promisify(stream.pipeline);\nimport { createReadStream } from \"fs\";\n\nexport const handler = awslambda.streamifyResponse(async (event, responseStream, context) =\u003e {\n  responseStream.setContentType(\"image/png\");\n  // https://svs.gsfc.nasa.gov/vis/a030000/a030800/a030877/frames/5760x3240_16x9_01p/BlackMarble_2016_928m_europe_labeled.png\n  const streamImage = createReadStream(\"BlackMarble_2016_928m_europe_labeled.png\");\n\n  await pipeline(streamImage, responseStream);\n});\n```\n\nExample with AWS SDK:\n\n```ts\nimport { LambdaClient, InvokeWithResponseStreamCommand } from \"@aws-sdk/client-lambda\";\n\nconst client = new LambdaClient({\n  region: \"eu-west-3\",\n  endpoint: \"http://localhost:3000\",\n});\n\nconst cmd = new InvokeWithResponseStreamCommand({\n  FunctionName: \"myAwsomeLambda\",\n  InvocationType: \"RequestResponse\",\n  Payload: Buffer.from(JSON.stringify({ hello: \"world\" })),\n  ClientContext: Buffer.from(JSON.stringify({ anything: \"some value\" })).toString(\"base64\"),\n});\n\nconst data = await client.send(cmd);\n\nfor await (const x of data.EventStream) {\n  if (x.PayloadChunk) {\n    console.log(x.PayloadChunk.Payload);\n  }\n}\n```\n\n---\n\n### Environment variables\n\nLambdas are executed in worker threads. \\*Only variables declared in your `serverless.yml` are injected into `process.env`.\n\n\\*In local mode following env variables are set for `sls invoke`, serverless-offline and AWS SAM compatibility.\n\n- IS_LOCAL\n- IS_OFFLINE\n- AWS_SAM_LOCAL\n\nIf `NODE_ENV` is present it will be injected in both local mode, while deploying also during bundle process for optimized output.\n\n---\n\n### **Package**\n\nserverless-aws-lambda bundles every (nodejs) handler separetly (with esbuild) and creates the artifact zip archive.  \nArchive will include bundeled handler and sourcemap (if enabled in esbuild).\n\n#### - `assets`\n\nBy default bundle produced assets (css, png, svg etc.) are excluded.  \nTo include all assets set `assets` to true.  \nFor all functions set it at top-level `package`:\n\n```yaml\npackage:\n  individually: true\n  assets: true # default false\n\nfunctions:\n  myAwsomeLambda:\n    description: inherits assets from top-level package\n    handler: src/handlers/awsomeLambda.default\n```\n\nor by function:\n\n```yaml\nfunctions:\n  myAwsomeLambda:\n    package:\n      assets: false\n    description: don't includes assets\n    handler: src/handlers/awsomeLambda.default\n```\n\ninclude assets by file extension:\n\n```yaml\nfunctions:\n  myAwsomeLambda:\n    package:\n      assets: .css\n    description: include only css files\n    handler: src/handlers/awsomeLambda.default\n```\n\n```yaml\nfunctions:\n  myAwsomeLambda:\n    package:\n      assets:\n        - .css\n        - .svg\n    description: include only css and svg files\n    handler: src/handlers/awsomeLambda.default\n```\n\n#### - `preserveDir` :\n\nTo preserve your project directories structure inside the archive set `preserveDir` globally or at function level.\n\n```yaml\npackage:\n  individually: true\n  preserveDir: true # default true\n\nfunctions:\n  myAwsomeLambda:\n    description: directories preserved\n    handler: src/handlers/awsomeLambda.default\n\n  dummyLambda:\n    package:\n      preserveDir: false\n    description: directories NOT preserved\n    handler: src/handlers/dummyLambda.default\n```\n\n#### - `files`\n\ninclude additional files or directories into the package.\n\n```yaml\nfunctions:\n  myAwsomeLambda:\n    handler: src/handlers/awsomeLambda.default\n    package:\n      files:\n        - ./resources/some/file.png\n        - ./resources/anotherFile.pdf\n        - ./images\n```\n\nBy default `files` are inherited from top level `package`'s `files`.  \nThis can be disabled with `inheritFiles` at function level.\n\n```yaml\nfunctions:\n  myAwsomeLambda:\n    handler: src/handlers/awsomeLambda.default\n    package:\n      inheritFiles: false\n      files:\n        - ./resources/some/file.png\n        - ./node_modules/my-module\n```\n\nfiles may be added to the archive with custom path:\n\n```yaml\nfunctions:\n  myAwsomeLambda:\n    handler: src/handlers/awsomeLambda.default\n    package:\n      files:\n        - { at: \"./resources/some/file.png\", as: \"./documents/important.png\" }\n```\n\nAdding files with a filter:\n\n```yaml\nfunctions:\n  myAwsomeLambda:\n    handler: src/handlers/awsomeLambda.default\n    package:\n      files:\n        - { pattern: \"./resources/some/*.png\" }\n```\n\nIf you need to preserve `pattern`'s directories structure inside the archive but search for files in another directory set `dir` value.  \nThis will search for all .png files inside `./resources/images` but only `images` directory will be created inside the archive.\n\n```yaml\nfunctions:\n  myAwsomeLambda:\n    handler: src/handlers/awsomeLambda.default\n    package:\n      files:\n        - { pattern: \"images/*.png\", dir: \"./resources\" }\n```\n\nAdding inline files:\n\n```yaml\nfunctions:\n  myAwsomeLambda:\n    handler: src/handlers/awsomeLambda.default\n    package:\n      files:\n        - { text: \"Hello world\", dir: \"./documents/hello.txt\" }\n```\n\n---\n\n### **Deploy**\n\nAdding the param `online: false` will omit the deployement of your Lambda.\n\n```yaml\nfunctions:\n  myAwsomeLambda:\n    handler: src/handlers/awsomeLambda.default\n    online: false\n```\n\nTo deploy a lambda by stage(s) set `online`'s value to target stage(s)\n\n```yaml\nfunctions:\n  lambdaOnlyInDev:\n    handler: src/handlers/awsomeLambda.default\n    online: dev\n```\n\n```yaml\nfunctions:\n  lambdaOnlyInDevAndTest:\n    handler: src/handlers/awsomeLambda.default\n    online:\n      - dev\n      - test\n```\n\n### Extended properties\n\n- `virtualEnvs`  \n  a key-value object which will only be available inside [defineConfig](resources/defineConfig.md).  \n  by default virtualEnvs are inherited from custom \u003e virtualEnvs if exists.\n\n---\n\n### Advanced configuration:\n\nTo have more control over the plugin you can passe a config file via `configPath` param in plugin options:\n\n```yaml\ncustom:\n  serverless-aws-lambda:\n    configPath: ./config.default\n```\n\nSee [defineConfig](resources/defineConfig.md) for advanced configuration.\n\n---\n\n### Plugins:\n\n- [AWS Local S3](resources/s3.md)\n- [AWS Local SNS](resources/sns.md)\n- [AWS Local SQS](resources/sqs.md)\n- [DocumentDB Local Streams](https://github.com/Inqnuam/serverless-aws-lambda-documentdb-streams)\n- [DynamoDB Local Streams](https://github.com/Inqnuam/serverless-aws-lambda-ddb-streams)\n- [Jest](https://github.com/Inqnuam/serverless-aws-lambda-jest)\n- [Vitest](https://github.com/Inqnuam/serverless-aws-lambda-vitest)\n\n---\n\n### **Benchmarks**\n\nHardware and software:\n\n- iMac Pro 2017 (10 cors, 32Gb RAM)\n- macOS Ventura (13.2.1)\n- NodeJS v18.16.0\n- Serverless 3.32.2\n- serverless-aws-lambda 4.5.9\n- serverless-offline 12.0.4\n- serverless-esbuild 1.45.1\n\nHandler:\n\n```js\n// src/handlers/visitor.js\nlet count = 0;\nexport const handler = async () =\u003e {\n  count++;\n\n  return {\n    statusCode: 200,\n    body: `Visit count ${count}`,\n  };\n};\n```\n\n```yaml\nfunctions:\n  visitor:\n    handler: src/handlers/visitor.handler\n    events:\n      - http: ANY /visitor\n```\n\n| 200 + 200 executions                                                                    | Time (in seconds)                        | Memory used (mb)          | CPU (core) usage           | last invoke response | note                                |\n| --------------------------------------------------------------------------------------- | ---------------------------------------- | ------------------------- | -------------------------- | -------------------- | ----------------------------------- |\n| serverless-aws-lambda \u003cbr/\u003e cmd: `serverless aws-lambda`                                | sequential: 0.644\u003cbr/\u003e concurrent: 0.414 | idle: 125\u003cbr/\u003e peak: 169  | idle: 0,1%\u003cbr/\u003e peak: 15%  | Visit count 400      |                                     |\n| serverless-offline + serverless-esbuild \u003cbr/\u003e cmd: `serverless offline --reloadHandler` | sequential: 10.4\u003cbr/\u003e concurrent: 2.8    | idle: 110\u003cbr/\u003e peak: 3960 | idle: 0,1%\u003cbr/\u003e peak: 537% | Visit count 1        | most of concurrent invocations fail |\n\n---\n\n### Use [Express](https://expressjs.com) syntax with your lambdas:\n\n[See docs.](resources/express.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finqnuam%2Fserverless-aws-lambda","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finqnuam%2Fserverless-aws-lambda","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finqnuam%2Fserverless-aws-lambda/lists"}