{"id":18217343,"url":"https://github.com/mikaelvesavuori/aws-serverless-utils","last_synced_at":"2026-02-16T21:33:26.838Z","repository":{"id":259758790,"uuid":"879386925","full_name":"mikaelvesavuori/aws-serverless-utils","owner":"mikaelvesavuori","description":"Utility functions for AWS serverless services like Lambda, EventBridge, and DynamoDB.","archived":false,"fork":false,"pushed_at":"2025-01-22T17:33:44.000Z","size":560,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-18T11:33:12.048Z","etag":null,"topics":["aws","dynamodb","eventbridge","lambda","serverless","utilities","utility-functions","utility-library"],"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/mikaelvesavuori.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"mikaelvesavuori"}},"created_at":"2024-10-27T19:07:51.000Z","updated_at":"2025-01-22T17:33:34.000Z","dependencies_parsed_at":"2024-10-27T21:48:24.218Z","dependency_job_id":"c46600f8-1a0e-49a8-b5e1-29daa4c1ec2e","html_url":"https://github.com/mikaelvesavuori/aws-serverless-utils","commit_stats":null,"previous_names":["mikaelvesavuori/aws-serverless-utils"],"tags_count":19,"template":false,"template_full_name":null,"purl":"pkg:github/mikaelvesavuori/aws-serverless-utils","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikaelvesavuori%2Faws-serverless-utils","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikaelvesavuori%2Faws-serverless-utils/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikaelvesavuori%2Faws-serverless-utils/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikaelvesavuori%2Faws-serverless-utils/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mikaelvesavuori","download_url":"https://codeload.github.com/mikaelvesavuori/aws-serverless-utils/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikaelvesavuori%2Faws-serverless-utils/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29519409,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-16T18:37:19.720Z","status":"ssl_error","status_checked_at":"2026-02-16T18:36:46.920Z","response_time":115,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["aws","dynamodb","eventbridge","lambda","serverless","utilities","utility-functions","utility-library"],"created_at":"2024-11-03T17:04:57.214Z","updated_at":"2026-02-16T21:33:26.807Z","avatar_url":"https://github.com/mikaelvesavuori.png","language":"TypeScript","funding_links":["https://github.com/sponsors/mikaelvesavuori"],"categories":[],"sub_categories":[],"readme":"# aws-serverless-utils\n\n**Utility functions for AWS serverless services like Lambda, EventBridge, and DynamoDB.**\n\n![Build Status](https://github.com/mikaelvesavuori/aws-serverless-utils/workflows/main/badge.svg)\n\n[![codecov](https://codecov.io/gh/mikaelvesavuori/aws-serverless-utils/graph/badge.svg?token=FLNTPTAYAS)](https://codecov.io/gh/mikaelvesavuori/aws-serverless-utils)\n\n[![Maintainability](https://api.codeclimate.com/v1/badges/937c2275a4ad46fe265a/maintainability)](https://codeclimate.com/github/mikaelvesavuori/aws-serverless-utils/maintainability)\n\nServerless is awesome but what happens when you have a ton of microservices and small APIs? Well, you replicate the same boring boilerplate everywhere, that's what happens! This packages resolves some of those issues.\n\n- Saves you time when building AWS serverless solutions\n- Sensible helpers for common boring boilerplate stuff\n- Lightweight\n- Zero dependencies, unless you use `end()`, `endWithError()`, or `startLogger()` which use [MikroLog](https://github.com/mikaelvesavuori/mikrolog)\n- Has 100% test coverage\n\n## Usage\n\n### Basic importing and usage\n\nThe basic pattern is to import each function you want to use, respectively, and then use them.\n\n```typescript\n// ES5 format\nconst { end } = require('aws-serverless-utils');\n// ES6 format\nimport { end } from 'aws-serverless-utils';\n\n// One example could be...\nreturn await end(); // Returns a 200 with CORS headers but no message\n```\n\n## Functions\n\n### `end()`\n\nUtility function to create a valid AWS Lambda response object. Note that headers will be completely replaced if you supply custom headers.\n\n```ts\nreturn await end(); // Returns a 200 with default CORS headers but no message\nreturn await end({ statusCode: 204 }); // Returns a 204 with default CORS headers but no message\nreturn await end({ statusCode: 200, message: { timeCreated: '2024-10-27', itemId: 'abc123' }}); // Returns a 200 with an object message\nreturn await end({ statusCode: 200, headers: { 'X-Custom-Header': 'custom-value' }}); // Replaces the headers with a custom set of headers\n\nasync function flushFn() {\n  await sendLogsToService(MikroLog.logBuffer)\n};\n\nreturn await end({ statusCode: 200, flushFn }); // Runs a \"flush\" function before ending\n```\n\n### `endWithError()`\n\nUtility function to create a valid AWS Lambda response object when encountering an error.\n\nMikroLog will be initialized to log the error; because it's static, it will reuse any previous configuration.\n\nThe resulting status code will be the value of `error.cause.statusCode` or it'll use the default value if not found (falling back to status `400`).\n\nAny provided headers will be passed to the `end()` function. Please see the documentation for that function for more information.\n\nThis supports the optional `flushFn` argument as the regular `end()` function does.\n\n### `getAuthContext()`\n\nGet the authorization data coming from the Lambda authorizer.\n\n```ts\nexport async function handler(event, context) {\n  const authData = getAuthContext(event); // Get any data from the Lambda authorizer.\n}\n```\n\n### `getBearerToken()`\n\nExtract the Bearer token from the Authorization header. The value must start with `Bearer`.\n\n```ts\nconst token = getBearerToken({ Authorization: 'Bearer some-very-long-value-123-abc...' }); // Result: 'some-very-long-value-123-abc...'\n```\n\n### `getCleanedDynamoItems()`\n\nClean up and return DynamoDB items in a normalized format. Accepts one or multiple items and returns an array of cleaned objects. Returns a cleaned and parsed array of objects.\n\nThe optional `includePkSk` (set to false by default) will enable getting the `pk` and `sk` keys.\n\n```ts\nconst items = getCleanedDynamoItems(\n  [\n    {\n      pk: { S: 'item#123' },\n      sk: { S: 'meta#456' },\n      name: { S: 'Test Item' },\n      age: { N: '25' },\n      isActive: { BOOL: true },\n      tags: { SS: ['tag1', 'tag2'] },\n      metadata: { M: { key1: { S: 'value1' }, key2: { N: '100' } } },\n      list: { L: [{ S: 'item1' }, { S: 'item2' }] }\n    }\n  ],\n  true // This will return the pk and sk values, else they are omitted\n);\n\n// This is what items will look like\nconst result = {\n  pk: 'item#123',\n  sk: 'meta#456',\n  name: 'Test Item',\n  age: 25,\n  isActive: true,\n  tags: ['tag1', 'tag2'],\n  metadata: { key1: 'value1', key2: 100 },\n  list: ['item1', 'item2']\n};\n```\n\n### `getCorrelationId()`\n\nGet correlation ID from:\n\n1. Environment, via `process.env.CORRELATION_ID`\n2. Event headers (`event.headers.['x-correlation-id']` or `event.headers.['X-Correlation-Id']`)\n3. Event metadata (`event.detail.metadata.correlationId` or `event.detail.metadata.correlation_id`)\n4. Context request ID (`awsRequestId`)\n5. Empty string, if nothing is found\n\n### `getInputBody()`\n\nGet the main input body from EventBridge or API Gateway input, in which case it also handles if the input is stringified JSON.\n\nIf you follow the convention with `data` + `metadata` in EventBridge, then the `data` object will be returned, otherwise the whole `detail` object will be returned. It will also handle Base64-encoded bodies.\n\n```ts\nexport async function handler(event, context) {\n  const body = getInputBody(event);\n  const result = {\n    myThingHere: true // You'll get a ready-to-use JSON object\n  };\n}\n```\n\n### `getMetadata()`\n\nGet the contents of an EventBridge `metadata` object, as per the [data + metadata convention](https://www.boyney.io/blog/2022-02-11-event-payload-patterns).\n\n```ts\nexport async function handler(event, context) {\n  const metadata = getMetadata(event); // EventBridge event\n  const result = {\n    tenantId: 'qwerty' // You'll get the `event.detail.metadata` data here\n  };\n}\n```\n\n### `getPathParameters()`\n\nGet the `pathParameters` object if it exists, else an empty object.\n\n```ts\nexport async function handler(event, context) {\n  const body = getPathParameters(event);\n  const result = {\n    recordId: 'abc123' // You'll get a ready-to-use JSON object\n  };\n}\n```\n\n### `getQueryStringParameters()`\n\nGet query string parameters if they exist, else an empty object.\n\n```ts\nexport async function handler(event, context) {\n  const body = getQueryStringParameters(event);\n  const result = {\n    isSpecialFeature: true // You'll get a ready-to-use JSON object\n  };\n}\n```\n\n### `handleCors()`\n\nReturn a CORS response.\n\n```ts\nexport async function handler(event, context) {\n  if (event?.requestContext?.http?.method === 'OPTIONS') return handleCors();\n}\n```\n\n```json\n{\n    statusCode: 200,\n    headers: {\n      'Content-Type': 'text/plain',\n      'Access-Control-Allow-Origin': '*',\n      'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',\n      'Access-Control-Allow-Headers': 'Content-Type, Authorization',\n      'Access-Control-Allow-Credentials': true\n    },\n    body: JSON.stringify('OK')\n  }\n```\n\n### `isJsonString()`\n\nCheck if input is stringified JSON.\n\n```ts\nisJsonString('asdf'); // false\nisJsonString('{\"abc\": 123}'); // true\n```\n\n### `mapToDynamoAttribute()`\n\nMap out values as DynamoDB attributes. Use this to convert JSON to a shape ready to use with DynamoDB.\n\nSupports mapping to:\n\n- `NULL`\n- `BOOL`\n- `S`\n- `N`\n- `L`\n- `M`\n\n```ts\nmapToDynamoAttribute({\n  title: 'Complex Item',\n  count: 5,\n  isActive: true,\n  tags: ['tag1', 'tag2'],\n  metadata: {\n    createdBy: 'user123',\n    scores: [1, 2, 3],\n    settings: { darkMode: false }\n  }\n});\n\n// You'll get a result like this\nconst result = {\n  M: {\n    title: { S: 'Complex Item' },\n    count: { N: '5' },\n    isActive: { BOOL: true },\n    tags: { L: [{ S: 'tag1' }, { S: 'tag2' }] },\n    metadata: {\n      M: {\n        createdBy: { S: 'user123' },\n        scores: { L: [{ N: '1' }, { N: '2' }, { N: '3' }] },\n        settings: {\n          M: {\n            darkMode: { BOOL: false }\n          }\n        }\n      }\n    }\n  }\n};\n```\n\n### `startLogger()`\n\nStarts an instance of [MikroLog](https://github.com/mikaelvesavuori/mikrolog) with correlation ID already set up and returns it.\n\nSee the documentation for `getCorrelationId()` to understand how the ID is fetched.\n\n## License\n\nMIT. See `LICENSE` file.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikaelvesavuori%2Faws-serverless-utils","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmikaelvesavuori%2Faws-serverless-utils","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikaelvesavuori%2Faws-serverless-utils/lists"}