@celerity-sdk/serverless-aws 0.2.0 → 0.3.0

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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @celerity-sdk/serverless-aws
2
2
 
3
- AWS Lambda adapter for the Celerity Node SDK maps API Gateway v2 events to SDK types and routes them through the handler pipeline.
3
+ AWS Lambda adapter for the Celerity Node SDK. Maps API Gateway v2 events to SDK types and routes them through the handler pipeline.
4
4
 
5
5
  ## Installation
6
6
 
@@ -14,10 +14,20 @@ The `AwsLambdaAdapter` implements the `ServerlessAdapter` interface from `@celer
14
14
 
15
15
  1. Receives an API Gateway v2 proxy event
16
16
  2. Maps it to an `HttpRequest` via `mapApiGatewayV2Event`
17
- 3. Resolves the matching handler from the registry
17
+ 3. Resolves the matching handler using the three-tier resolution chain (see below)
18
18
  4. Executes the full handler pipeline (system layers, app layers, handler layers, handler)
19
19
  5. Maps the `HttpResponse` back to an `APIGatewayProxyResultV2`
20
20
 
21
+ ### Handler Resolution
22
+
23
+ When `CELERITY_HANDLER_ID` is set (typical for serverless deployments where each Lambda maps to a single handler), the adapter resolves the handler using a three-tier chain:
24
+
25
+ 1. **Direct registry lookup** - `registry.getHandlerById(CELERITY_HANDLER_ID)` for handlers with an explicit ID
26
+ 2. **Module resolution fallback** - dynamically imports the handler module and matches the exported function against the registry by reference. Supports formats like `"handlers.hello"` (named export) and `"handlers"` (default export). Dotted module names like `"app.module"` are handled by trying the named export split first, then falling back to the full string as a module with a default export.
27
+ 3. **Path/method routing** - falls back to matching the incoming request's HTTP method and path
28
+
29
+ Resolution is cached: once a handler is matched on cold start, subsequent warm invocations use the cached handler directly without repeating the lookup.
30
+
21
31
  ### Event Mapping
22
32
 
23
33
  `mapApiGatewayV2Event` extracts from the API Gateway v2 event:
@@ -33,7 +43,7 @@ The `AwsLambdaAdapter` implements the `ServerlessAdapter` interface from `@celer
33
43
  The `./handler` export provides a pre-configured Lambda handler that bootstraps the application module, initialises system layers, and caches the handler for warm invocations. It also registers a SIGTERM handler for graceful shutdown (container close + layer disposal).
34
44
 
35
45
  ```typescript
36
- // handler.ts used as the Lambda entry point
46
+ // handler.ts - used as the Lambda entry point
37
47
  export { handler } from "@celerity-sdk/serverless-aws/handler";
38
48
  ```
39
49
 
package/dist/entry.cjs CHANGED
@@ -34,6 +34,7 @@ __export(entry_exports, {
34
34
  handler: () => handler
35
35
  });
36
36
  module.exports = __toCommonJS(entry_exports);
37
+ var import_node_path = require("path");
37
38
  var import_debug2 = __toESM(require("debug"), 1);
38
39
  var import_core = require("@celerity-sdk/core");
39
40
 
@@ -162,12 +163,14 @@ async function ensureBootstrapped() {
162
163
  debug2("entry: %d system layers created", systemLayers.length);
163
164
  const rootModule = await (0, import_core.discoverModule)();
164
165
  const result = await (0, import_core.bootstrap)(rootModule);
166
+ const modulePath = process.env.CELERITY_MODULE_PATH;
165
167
  cached = {
166
168
  registry: result.registry,
167
169
  options: {
168
170
  container: result.container,
169
171
  systemLayers
170
- }
172
+ },
173
+ moduleDir: modulePath ? (0, import_node_path.dirname)((0, import_node_path.resolve)(modulePath)) : process.cwd()
171
174
  };
172
175
  debug2("entry: bootstrap complete");
173
176
  }
@@ -175,12 +178,19 @@ async function ensureBootstrapped() {
175
178
  }
176
179
  __name(ensureBootstrapped, "ensureBootstrapped");
177
180
  async function handler(event, _context) {
178
- const { registry, options } = await ensureBootstrapped();
181
+ const { registry, options, moduleDir } = await ensureBootstrapped();
179
182
  registerShutdownHandler(options);
180
183
  const apiEvent = event;
181
184
  const httpRequest = mapApiGatewayV2Event(apiEvent);
182
185
  debug2("entry: %s %s", httpRequest.method, httpRequest.path);
183
- const resolved = registry.getHandler(httpRequest.path, httpRequest.method);
186
+ const handlerId = process.env.CELERITY_HANDLER_ID;
187
+ let resolved = handlerId ? registry.getHandlerById(handlerId) : void 0;
188
+ if (!resolved && handlerId) {
189
+ resolved = await (0, import_core.resolveHandlerByModuleRef)(handlerId, registry, moduleDir) ?? void 0;
190
+ }
191
+ if (!resolved) {
192
+ resolved = registry.getHandler(httpRequest.path, httpRequest.method);
193
+ }
184
194
  if (!resolved) {
185
195
  return {
186
196
  statusCode: 404,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/entry.ts","../src/event-mapper.ts"],"sourcesContent":["import createDebug from \"debug\";\nimport type { APIGatewayProxyEventV2, APIGatewayProxyResultV2 } from \"aws-lambda\";\nimport type { PipelineOptions } from \"@celerity-sdk/core\";\nimport {\n discoverModule,\n bootstrap,\n executeHandlerPipeline,\n createDefaultSystemLayers,\n disposeLayers,\n} from \"@celerity-sdk/core\";\nimport type { HandlerRegistry } from \"@celerity-sdk/core\";\nimport { mapApiGatewayV2Event, mapHttpResponseToResult } from \"./event-mapper\";\n\nconst debug = createDebug(\"celerity:serverless-aws\");\n\nlet cached: { registry: HandlerRegistry; options: PipelineOptions } | null = null;\nlet shutdownRegistered = false;\n\nfunction registerShutdownHandler(options: PipelineOptions): void {\n if (shutdownRegistered) return;\n shutdownRegistered = true;\n debug(\"entry: SIGTERM shutdown handler registered\");\n\n process.on(\"SIGTERM\", async () => {\n await options.container.closeAll();\n await disposeLayers([...(options.systemLayers ?? []), ...(options.appLayers ?? [])]);\n process.exit(0);\n });\n}\n\nasync function ensureBootstrapped(): Promise<{\n registry: HandlerRegistry;\n options: PipelineOptions;\n}> {\n if (!cached) {\n debug(\"entry: cold start, bootstrapping\");\n const systemLayers = await createDefaultSystemLayers();\n debug(\"entry: %d system layers created\", systemLayers.length);\n const rootModule = await discoverModule();\n const result = await bootstrap(rootModule);\n cached = {\n registry: result.registry,\n options: {\n container: result.container,\n systemLayers,\n },\n };\n debug(\"entry: bootstrap complete\");\n }\n return cached;\n}\n\nexport async function handler(event: unknown, _context: unknown): Promise<APIGatewayProxyResultV2> {\n const { registry, options } = await ensureBootstrapped();\n registerShutdownHandler(options);\n const apiEvent = event as APIGatewayProxyEventV2;\n const httpRequest = mapApiGatewayV2Event(apiEvent);\n debug(\"entry: %s %s\", httpRequest.method, httpRequest.path);\n\n const resolved = registry.getHandler(httpRequest.path, httpRequest.method);\n if (!resolved) {\n return {\n statusCode: 404,\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n statusCode: 404,\n message: `No handler for ${httpRequest.method} ${httpRequest.path}`,\n }),\n };\n }\n\n const httpResponse = await executeHandlerPipeline(resolved, httpRequest, options);\n return mapHttpResponseToResult(httpResponse);\n}\n","import createDebug from \"debug\";\nimport type { HttpMethod, HttpRequest, HttpResponse } from \"@celerity-sdk/types\";\nimport type { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2 } from \"aws-lambda\";\n\nconst debug = createDebug(\"celerity:serverless-aws\");\n\nfunction parseBody(event: APIGatewayProxyEventV2): {\n textBody: string | null;\n binaryBody: Buffer | null;\n} {\n if (!event.body) return { textBody: null, binaryBody: null };\n if (event.isBase64Encoded)\n return { textBody: null, binaryBody: Buffer.from(event.body, \"base64\") };\n return { textBody: event.body, binaryBody: null };\n}\n\nfunction parseHeaders(event: APIGatewayProxyEventV2): Record<string, string | string[]> {\n const headers: Record<string, string | string[]> = {};\n if (!event.headers) return headers;\n\n for (const [key, value] of Object.entries(event.headers)) {\n if (value !== undefined) {\n headers[key.toLowerCase()] = value;\n }\n }\n return headers;\n}\n\nfunction parseCookies(event: APIGatewayProxyEventV2): Record<string, string> {\n const cookies: Record<string, string> = {};\n if (!event.cookies) return cookies;\n\n for (const cookie of event.cookies) {\n const eqIndex = cookie.indexOf(\"=\");\n if (eqIndex > 0) {\n cookies[cookie.slice(0, eqIndex).trim()] = cookie.slice(eqIndex + 1).trim();\n }\n }\n return cookies;\n}\n\nfunction parsePathParams(event: APIGatewayProxyEventV2): Record<string, string> {\n const params: Record<string, string> = {};\n if (!event.pathParameters) return params;\n\n for (const [key, value] of Object.entries(event.pathParameters)) {\n if (value !== undefined) {\n params[key] = value;\n }\n }\n return params;\n}\n\nexport function mapApiGatewayV2Event(event: APIGatewayProxyEventV2): HttpRequest {\n const method = event.requestContext.http.method.toUpperCase() as HttpMethod;\n const headers = parseHeaders(event);\n const { textBody, binaryBody } = parseBody(event);\n\n const authorizer = (\n event.requestContext as unknown as {\n authorizer?: { jwt?: { claims?: Record<string, unknown> } };\n }\n ).authorizer;\n\n const contentType = (headers[\"content-type\"] as string | undefined) ?? null;\n const xrayHeader = (headers[\"x-amzn-trace-id\"] as string | undefined) ?? null;\n\n const request: HttpRequest = {\n method,\n path: event.rawPath,\n pathParams: parsePathParams(event),\n query: (event.queryStringParameters ?? {}) as Record<string, string | string[]>,\n headers,\n cookies: parseCookies(event),\n textBody,\n binaryBody,\n contentType,\n requestId: event.requestContext.requestId,\n requestTime: event.requestContext.time ?? new Date().toISOString(),\n auth: authorizer?.jwt?.claims ?? null,\n clientIp: event.requestContext.http.sourceIp,\n traceContext: xrayHeader ? { \"x-amzn-trace-id\": xrayHeader } : null,\n userAgent: event.requestContext.http.userAgent ?? null,\n matchedRoute: event.routeKey ?? null,\n };\n\n debug(\n \"mapEvent: %s %s (auth=%s, traceContext=%s)\",\n method,\n event.rawPath,\n !!authorizer?.jwt?.claims,\n !!xrayHeader,\n );\n\n return request;\n}\n\nexport function mapHttpResponseToResult(response: HttpResponse): APIGatewayProxyStructuredResultV2 {\n const result: APIGatewayProxyStructuredResultV2 = {\n statusCode: response.status,\n };\n\n if (response.headers) {\n result.headers = response.headers;\n }\n\n if (response.binaryBody) {\n result.body = response.binaryBody.toString(\"base64\");\n result.isBase64Encoded = true;\n } else if (response.body) {\n result.body = response.body;\n }\n\n return result;\n}\n"],"mappings":"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","names":["import_debug","debug","createDebug","parseBody","event","body","textBody","binaryBody","isBase64Encoded","Buffer","from","parseHeaders","headers","key","value","Object","entries","undefined","toLowerCase","parseCookies","cookies","cookie","eqIndex","indexOf","slice","trim","parsePathParams","params","pathParameters","mapApiGatewayV2Event","method","requestContext","http","toUpperCase","authorizer","contentType","xrayHeader","request","path","rawPath","pathParams","query","queryStringParameters","requestId","requestTime","time","Date","toISOString","auth","jwt","claims","clientIp","sourceIp","traceContext","userAgent","matchedRoute","routeKey","mapHttpResponseToResult","response","result","statusCode","status","toString","debug","createDebug","cached","shutdownRegistered","registerShutdownHandler","options","process","on","container","closeAll","disposeLayers","systemLayers","appLayers","exit","ensureBootstrapped","createDefaultSystemLayers","length","rootModule","discoverModule","result","bootstrap","registry","handler","event","_context","apiEvent","httpRequest","mapApiGatewayV2Event","method","path","resolved","getHandler","statusCode","headers","body","JSON","stringify","message","httpResponse","executeHandlerPipeline","mapHttpResponseToResult"]}
1
+ {"version":3,"sources":["../src/entry.ts","../src/event-mapper.ts"],"sourcesContent":["import { dirname, resolve } from \"node:path\";\nimport createDebug from \"debug\";\nimport type { APIGatewayProxyEventV2, APIGatewayProxyResultV2 } from \"aws-lambda\";\nimport type { PipelineOptions } from \"@celerity-sdk/core\";\nimport {\n discoverModule,\n bootstrap,\n executeHandlerPipeline,\n createDefaultSystemLayers,\n disposeLayers,\n resolveHandlerByModuleRef,\n} from \"@celerity-sdk/core\";\nimport type { HandlerRegistry } from \"@celerity-sdk/core\";\nimport { mapApiGatewayV2Event, mapHttpResponseToResult } from \"./event-mapper\";\n\nconst debug = createDebug(\"celerity:serverless-aws\");\n\nlet cached: {\n registry: HandlerRegistry;\n options: PipelineOptions;\n moduleDir: string;\n} | null = null;\nlet shutdownRegistered = false;\n\nfunction registerShutdownHandler(options: PipelineOptions): void {\n if (shutdownRegistered) return;\n shutdownRegistered = true;\n debug(\"entry: SIGTERM shutdown handler registered\");\n\n process.on(\"SIGTERM\", async () => {\n await options.container.closeAll();\n await disposeLayers([...(options.systemLayers ?? []), ...(options.appLayers ?? [])]);\n process.exit(0);\n });\n}\n\nasync function ensureBootstrapped(): Promise<{\n registry: HandlerRegistry;\n options: PipelineOptions;\n moduleDir: string;\n}> {\n if (!cached) {\n debug(\"entry: cold start, bootstrapping\");\n const systemLayers = await createDefaultSystemLayers();\n debug(\"entry: %d system layers created\", systemLayers.length);\n const rootModule = await discoverModule();\n const result = await bootstrap(rootModule);\n const modulePath = process.env.CELERITY_MODULE_PATH;\n cached = {\n registry: result.registry,\n options: {\n container: result.container,\n systemLayers,\n },\n moduleDir: modulePath ? dirname(resolve(modulePath)) : process.cwd(),\n };\n debug(\"entry: bootstrap complete\");\n }\n return cached;\n}\n\nexport async function handler(event: unknown, _context: unknown): Promise<APIGatewayProxyResultV2> {\n const { registry, options, moduleDir } = await ensureBootstrapped();\n registerShutdownHandler(options);\n const apiEvent = event as APIGatewayProxyEventV2;\n const httpRequest = mapApiGatewayV2Event(apiEvent);\n debug(\"entry: %s %s\", httpRequest.method, httpRequest.path);\n\n const handlerId = process.env.CELERITY_HANDLER_ID;\n\n let resolved = handlerId ? registry.getHandlerById(handlerId) : undefined;\n\n if (!resolved && handlerId) {\n resolved = (await resolveHandlerByModuleRef(handlerId, registry, moduleDir)) ?? undefined;\n }\n\n if (!resolved) {\n resolved = registry.getHandler(httpRequest.path, httpRequest.method);\n }\n\n if (!resolved) {\n return {\n statusCode: 404,\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n statusCode: 404,\n message: `No handler for ${httpRequest.method} ${httpRequest.path}`,\n }),\n };\n }\n\n const httpResponse = await executeHandlerPipeline(resolved, httpRequest, options);\n return mapHttpResponseToResult(httpResponse);\n}\n","import createDebug from \"debug\";\nimport type { HttpMethod, HttpRequest, HttpResponse } from \"@celerity-sdk/types\";\nimport type { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2 } from \"aws-lambda\";\n\nconst debug = createDebug(\"celerity:serverless-aws\");\n\nfunction parseBody(event: APIGatewayProxyEventV2): {\n textBody: string | null;\n binaryBody: Buffer | null;\n} {\n if (!event.body) return { textBody: null, binaryBody: null };\n if (event.isBase64Encoded)\n return { textBody: null, binaryBody: Buffer.from(event.body, \"base64\") };\n return { textBody: event.body, binaryBody: null };\n}\n\nfunction parseHeaders(event: APIGatewayProxyEventV2): Record<string, string | string[]> {\n const headers: Record<string, string | string[]> = {};\n if (!event.headers) return headers;\n\n for (const [key, value] of Object.entries(event.headers)) {\n if (value !== undefined) {\n headers[key.toLowerCase()] = value;\n }\n }\n return headers;\n}\n\nfunction parseCookies(event: APIGatewayProxyEventV2): Record<string, string> {\n const cookies: Record<string, string> = {};\n if (!event.cookies) return cookies;\n\n for (const cookie of event.cookies) {\n const eqIndex = cookie.indexOf(\"=\");\n if (eqIndex > 0) {\n cookies[cookie.slice(0, eqIndex).trim()] = cookie.slice(eqIndex + 1).trim();\n }\n }\n return cookies;\n}\n\nfunction parsePathParams(event: APIGatewayProxyEventV2): Record<string, string> {\n const params: Record<string, string> = {};\n if (!event.pathParameters) return params;\n\n for (const [key, value] of Object.entries(event.pathParameters)) {\n if (value !== undefined) {\n params[key] = value;\n }\n }\n return params;\n}\n\nexport function mapApiGatewayV2Event(event: APIGatewayProxyEventV2): HttpRequest {\n const method = event.requestContext.http.method.toUpperCase() as HttpMethod;\n const headers = parseHeaders(event);\n const { textBody, binaryBody } = parseBody(event);\n\n const authorizer = (\n event.requestContext as unknown as {\n authorizer?: { jwt?: { claims?: Record<string, unknown> } };\n }\n ).authorizer;\n\n const contentType = (headers[\"content-type\"] as string | undefined) ?? null;\n const xrayHeader = (headers[\"x-amzn-trace-id\"] as string | undefined) ?? null;\n\n const request: HttpRequest = {\n method,\n path: event.rawPath,\n pathParams: parsePathParams(event),\n query: (event.queryStringParameters ?? {}) as Record<string, string | string[]>,\n headers,\n cookies: parseCookies(event),\n textBody,\n binaryBody,\n contentType,\n requestId: event.requestContext.requestId,\n requestTime: event.requestContext.time ?? new Date().toISOString(),\n auth: authorizer?.jwt?.claims ?? null,\n clientIp: event.requestContext.http.sourceIp,\n traceContext: xrayHeader ? { \"x-amzn-trace-id\": xrayHeader } : null,\n userAgent: event.requestContext.http.userAgent ?? null,\n matchedRoute: event.routeKey ?? null,\n };\n\n debug(\n \"mapEvent: %s %s (auth=%s, traceContext=%s)\",\n method,\n event.rawPath,\n !!authorizer?.jwt?.claims,\n !!xrayHeader,\n );\n\n return request;\n}\n\nexport function mapHttpResponseToResult(response: HttpResponse): APIGatewayProxyStructuredResultV2 {\n const result: APIGatewayProxyStructuredResultV2 = {\n statusCode: response.status,\n };\n\n if (response.headers) {\n result.headers = response.headers;\n }\n\n if (response.binaryBody) {\n result.body = response.binaryBody.toString(\"base64\");\n result.isBase64Encoded = true;\n } else if (response.body) {\n result.body = response.body;\n }\n\n return result;\n}\n"],"mappings":"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","names":["import_debug","debug","createDebug","parseBody","event","body","textBody","binaryBody","isBase64Encoded","Buffer","from","parseHeaders","headers","key","value","Object","entries","undefined","toLowerCase","parseCookies","cookies","cookie","eqIndex","indexOf","slice","trim","parsePathParams","params","pathParameters","mapApiGatewayV2Event","method","requestContext","http","toUpperCase","authorizer","contentType","xrayHeader","request","path","rawPath","pathParams","query","queryStringParameters","requestId","requestTime","time","Date","toISOString","auth","jwt","claims","clientIp","sourceIp","traceContext","userAgent","matchedRoute","routeKey","mapHttpResponseToResult","response","result","statusCode","status","toString","debug","createDebug","cached","shutdownRegistered","registerShutdownHandler","options","process","on","container","closeAll","disposeLayers","systemLayers","appLayers","exit","ensureBootstrapped","createDefaultSystemLayers","length","rootModule","discoverModule","result","bootstrap","modulePath","env","CELERITY_MODULE_PATH","registry","moduleDir","dirname","resolve","cwd","handler","event","_context","apiEvent","httpRequest","mapApiGatewayV2Event","method","path","handlerId","CELERITY_HANDLER_ID","resolved","getHandlerById","undefined","resolveHandlerByModuleRef","getHandler","statusCode","headers","body","JSON","stringify","message","httpResponse","executeHandlerPipeline","mapHttpResponseToResult"]}
package/dist/entry.js CHANGED
@@ -2,8 +2,9 @@ var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
 
4
4
  // src/entry.ts
5
+ import { dirname, resolve } from "path";
5
6
  import createDebug2 from "debug";
6
- import { discoverModule, bootstrap, executeHandlerPipeline, createDefaultSystemLayers, disposeLayers } from "@celerity-sdk/core";
7
+ import { discoverModule, bootstrap, executeHandlerPipeline, createDefaultSystemLayers, disposeLayers, resolveHandlerByModuleRef } from "@celerity-sdk/core";
7
8
 
8
9
  // src/event-mapper.ts
9
10
  import createDebug from "debug";
@@ -130,12 +131,14 @@ async function ensureBootstrapped() {
130
131
  debug2("entry: %d system layers created", systemLayers.length);
131
132
  const rootModule = await discoverModule();
132
133
  const result = await bootstrap(rootModule);
134
+ const modulePath = process.env.CELERITY_MODULE_PATH;
133
135
  cached = {
134
136
  registry: result.registry,
135
137
  options: {
136
138
  container: result.container,
137
139
  systemLayers
138
- }
140
+ },
141
+ moduleDir: modulePath ? dirname(resolve(modulePath)) : process.cwd()
139
142
  };
140
143
  debug2("entry: bootstrap complete");
141
144
  }
@@ -143,12 +146,19 @@ async function ensureBootstrapped() {
143
146
  }
144
147
  __name(ensureBootstrapped, "ensureBootstrapped");
145
148
  async function handler(event, _context) {
146
- const { registry, options } = await ensureBootstrapped();
149
+ const { registry, options, moduleDir } = await ensureBootstrapped();
147
150
  registerShutdownHandler(options);
148
151
  const apiEvent = event;
149
152
  const httpRequest = mapApiGatewayV2Event(apiEvent);
150
153
  debug2("entry: %s %s", httpRequest.method, httpRequest.path);
151
- const resolved = registry.getHandler(httpRequest.path, httpRequest.method);
154
+ const handlerId = process.env.CELERITY_HANDLER_ID;
155
+ let resolved = handlerId ? registry.getHandlerById(handlerId) : void 0;
156
+ if (!resolved && handlerId) {
157
+ resolved = await resolveHandlerByModuleRef(handlerId, registry, moduleDir) ?? void 0;
158
+ }
159
+ if (!resolved) {
160
+ resolved = registry.getHandler(httpRequest.path, httpRequest.method);
161
+ }
152
162
  if (!resolved) {
153
163
  return {
154
164
  statusCode: 404,
package/dist/entry.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/entry.ts","../src/event-mapper.ts"],"sourcesContent":["import createDebug from \"debug\";\nimport type { APIGatewayProxyEventV2, APIGatewayProxyResultV2 } from \"aws-lambda\";\nimport type { PipelineOptions } from \"@celerity-sdk/core\";\nimport {\n discoverModule,\n bootstrap,\n executeHandlerPipeline,\n createDefaultSystemLayers,\n disposeLayers,\n} from \"@celerity-sdk/core\";\nimport type { HandlerRegistry } from \"@celerity-sdk/core\";\nimport { mapApiGatewayV2Event, mapHttpResponseToResult } from \"./event-mapper\";\n\nconst debug = createDebug(\"celerity:serverless-aws\");\n\nlet cached: { registry: HandlerRegistry; options: PipelineOptions } | null = null;\nlet shutdownRegistered = false;\n\nfunction registerShutdownHandler(options: PipelineOptions): void {\n if (shutdownRegistered) return;\n shutdownRegistered = true;\n debug(\"entry: SIGTERM shutdown handler registered\");\n\n process.on(\"SIGTERM\", async () => {\n await options.container.closeAll();\n await disposeLayers([...(options.systemLayers ?? []), ...(options.appLayers ?? [])]);\n process.exit(0);\n });\n}\n\nasync function ensureBootstrapped(): Promise<{\n registry: HandlerRegistry;\n options: PipelineOptions;\n}> {\n if (!cached) {\n debug(\"entry: cold start, bootstrapping\");\n const systemLayers = await createDefaultSystemLayers();\n debug(\"entry: %d system layers created\", systemLayers.length);\n const rootModule = await discoverModule();\n const result = await bootstrap(rootModule);\n cached = {\n registry: result.registry,\n options: {\n container: result.container,\n systemLayers,\n },\n };\n debug(\"entry: bootstrap complete\");\n }\n return cached;\n}\n\nexport async function handler(event: unknown, _context: unknown): Promise<APIGatewayProxyResultV2> {\n const { registry, options } = await ensureBootstrapped();\n registerShutdownHandler(options);\n const apiEvent = event as APIGatewayProxyEventV2;\n const httpRequest = mapApiGatewayV2Event(apiEvent);\n debug(\"entry: %s %s\", httpRequest.method, httpRequest.path);\n\n const resolved = registry.getHandler(httpRequest.path, httpRequest.method);\n if (!resolved) {\n return {\n statusCode: 404,\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n statusCode: 404,\n message: `No handler for ${httpRequest.method} ${httpRequest.path}`,\n }),\n };\n }\n\n const httpResponse = await executeHandlerPipeline(resolved, httpRequest, options);\n return mapHttpResponseToResult(httpResponse);\n}\n","import createDebug from \"debug\";\nimport type { HttpMethod, HttpRequest, HttpResponse } from \"@celerity-sdk/types\";\nimport type { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2 } from \"aws-lambda\";\n\nconst debug = createDebug(\"celerity:serverless-aws\");\n\nfunction parseBody(event: APIGatewayProxyEventV2): {\n textBody: string | null;\n binaryBody: Buffer | null;\n} {\n if (!event.body) return { textBody: null, binaryBody: null };\n if (event.isBase64Encoded)\n return { textBody: null, binaryBody: Buffer.from(event.body, \"base64\") };\n return { textBody: event.body, binaryBody: null };\n}\n\nfunction parseHeaders(event: APIGatewayProxyEventV2): Record<string, string | string[]> {\n const headers: Record<string, string | string[]> = {};\n if (!event.headers) return headers;\n\n for (const [key, value] of Object.entries(event.headers)) {\n if (value !== undefined) {\n headers[key.toLowerCase()] = value;\n }\n }\n return headers;\n}\n\nfunction parseCookies(event: APIGatewayProxyEventV2): Record<string, string> {\n const cookies: Record<string, string> = {};\n if (!event.cookies) return cookies;\n\n for (const cookie of event.cookies) {\n const eqIndex = cookie.indexOf(\"=\");\n if (eqIndex > 0) {\n cookies[cookie.slice(0, eqIndex).trim()] = cookie.slice(eqIndex + 1).trim();\n }\n }\n return cookies;\n}\n\nfunction parsePathParams(event: APIGatewayProxyEventV2): Record<string, string> {\n const params: Record<string, string> = {};\n if (!event.pathParameters) return params;\n\n for (const [key, value] of Object.entries(event.pathParameters)) {\n if (value !== undefined) {\n params[key] = value;\n }\n }\n return params;\n}\n\nexport function mapApiGatewayV2Event(event: APIGatewayProxyEventV2): HttpRequest {\n const method = event.requestContext.http.method.toUpperCase() as HttpMethod;\n const headers = parseHeaders(event);\n const { textBody, binaryBody } = parseBody(event);\n\n const authorizer = (\n event.requestContext as unknown as {\n authorizer?: { jwt?: { claims?: Record<string, unknown> } };\n }\n ).authorizer;\n\n const contentType = (headers[\"content-type\"] as string | undefined) ?? null;\n const xrayHeader = (headers[\"x-amzn-trace-id\"] as string | undefined) ?? null;\n\n const request: HttpRequest = {\n method,\n path: event.rawPath,\n pathParams: parsePathParams(event),\n query: (event.queryStringParameters ?? {}) as Record<string, string | string[]>,\n headers,\n cookies: parseCookies(event),\n textBody,\n binaryBody,\n contentType,\n requestId: event.requestContext.requestId,\n requestTime: event.requestContext.time ?? new Date().toISOString(),\n auth: authorizer?.jwt?.claims ?? null,\n clientIp: event.requestContext.http.sourceIp,\n traceContext: xrayHeader ? { \"x-amzn-trace-id\": xrayHeader } : null,\n userAgent: event.requestContext.http.userAgent ?? null,\n matchedRoute: event.routeKey ?? null,\n };\n\n debug(\n \"mapEvent: %s %s (auth=%s, traceContext=%s)\",\n method,\n event.rawPath,\n !!authorizer?.jwt?.claims,\n !!xrayHeader,\n );\n\n return request;\n}\n\nexport function mapHttpResponseToResult(response: HttpResponse): APIGatewayProxyStructuredResultV2 {\n const result: APIGatewayProxyStructuredResultV2 = {\n statusCode: response.status,\n };\n\n if (response.headers) {\n result.headers = response.headers;\n }\n\n if (response.binaryBody) {\n result.body = response.binaryBody.toString(\"base64\");\n result.isBase64Encoded = true;\n } else if (response.body) {\n result.body = response.body;\n }\n\n return result;\n}\n"],"mappings":"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","names":["createDebug","discoverModule","bootstrap","executeHandlerPipeline","createDefaultSystemLayers","disposeLayers","createDebug","debug","createDebug","parseBody","event","body","textBody","binaryBody","isBase64Encoded","Buffer","from","parseHeaders","headers","key","value","Object","entries","undefined","toLowerCase","parseCookies","cookies","cookie","eqIndex","indexOf","slice","trim","parsePathParams","params","pathParameters","mapApiGatewayV2Event","method","requestContext","http","toUpperCase","authorizer","contentType","xrayHeader","request","path","rawPath","pathParams","query","queryStringParameters","requestId","requestTime","time","Date","toISOString","auth","jwt","claims","clientIp","sourceIp","traceContext","userAgent","matchedRoute","routeKey","mapHttpResponseToResult","response","result","statusCode","status","toString","debug","createDebug","cached","shutdownRegistered","registerShutdownHandler","options","process","on","container","closeAll","disposeLayers","systemLayers","appLayers","exit","ensureBootstrapped","createDefaultSystemLayers","length","rootModule","discoverModule","result","bootstrap","registry","handler","event","_context","apiEvent","httpRequest","mapApiGatewayV2Event","method","path","resolved","getHandler","statusCode","headers","body","JSON","stringify","message","httpResponse","executeHandlerPipeline","mapHttpResponseToResult"]}
1
+ {"version":3,"sources":["../src/entry.ts","../src/event-mapper.ts"],"sourcesContent":["import { dirname, resolve } from \"node:path\";\nimport createDebug from \"debug\";\nimport type { APIGatewayProxyEventV2, APIGatewayProxyResultV2 } from \"aws-lambda\";\nimport type { PipelineOptions } from \"@celerity-sdk/core\";\nimport {\n discoverModule,\n bootstrap,\n executeHandlerPipeline,\n createDefaultSystemLayers,\n disposeLayers,\n resolveHandlerByModuleRef,\n} from \"@celerity-sdk/core\";\nimport type { HandlerRegistry } from \"@celerity-sdk/core\";\nimport { mapApiGatewayV2Event, mapHttpResponseToResult } from \"./event-mapper\";\n\nconst debug = createDebug(\"celerity:serverless-aws\");\n\nlet cached: {\n registry: HandlerRegistry;\n options: PipelineOptions;\n moduleDir: string;\n} | null = null;\nlet shutdownRegistered = false;\n\nfunction registerShutdownHandler(options: PipelineOptions): void {\n if (shutdownRegistered) return;\n shutdownRegistered = true;\n debug(\"entry: SIGTERM shutdown handler registered\");\n\n process.on(\"SIGTERM\", async () => {\n await options.container.closeAll();\n await disposeLayers([...(options.systemLayers ?? []), ...(options.appLayers ?? [])]);\n process.exit(0);\n });\n}\n\nasync function ensureBootstrapped(): Promise<{\n registry: HandlerRegistry;\n options: PipelineOptions;\n moduleDir: string;\n}> {\n if (!cached) {\n debug(\"entry: cold start, bootstrapping\");\n const systemLayers = await createDefaultSystemLayers();\n debug(\"entry: %d system layers created\", systemLayers.length);\n const rootModule = await discoverModule();\n const result = await bootstrap(rootModule);\n const modulePath = process.env.CELERITY_MODULE_PATH;\n cached = {\n registry: result.registry,\n options: {\n container: result.container,\n systemLayers,\n },\n moduleDir: modulePath ? dirname(resolve(modulePath)) : process.cwd(),\n };\n debug(\"entry: bootstrap complete\");\n }\n return cached;\n}\n\nexport async function handler(event: unknown, _context: unknown): Promise<APIGatewayProxyResultV2> {\n const { registry, options, moduleDir } = await ensureBootstrapped();\n registerShutdownHandler(options);\n const apiEvent = event as APIGatewayProxyEventV2;\n const httpRequest = mapApiGatewayV2Event(apiEvent);\n debug(\"entry: %s %s\", httpRequest.method, httpRequest.path);\n\n const handlerId = process.env.CELERITY_HANDLER_ID;\n\n let resolved = handlerId ? registry.getHandlerById(handlerId) : undefined;\n\n if (!resolved && handlerId) {\n resolved = (await resolveHandlerByModuleRef(handlerId, registry, moduleDir)) ?? undefined;\n }\n\n if (!resolved) {\n resolved = registry.getHandler(httpRequest.path, httpRequest.method);\n }\n\n if (!resolved) {\n return {\n statusCode: 404,\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n statusCode: 404,\n message: `No handler for ${httpRequest.method} ${httpRequest.path}`,\n }),\n };\n }\n\n const httpResponse = await executeHandlerPipeline(resolved, httpRequest, options);\n return mapHttpResponseToResult(httpResponse);\n}\n","import createDebug from \"debug\";\nimport type { HttpMethod, HttpRequest, HttpResponse } from \"@celerity-sdk/types\";\nimport type { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2 } from \"aws-lambda\";\n\nconst debug = createDebug(\"celerity:serverless-aws\");\n\nfunction parseBody(event: APIGatewayProxyEventV2): {\n textBody: string | null;\n binaryBody: Buffer | null;\n} {\n if (!event.body) return { textBody: null, binaryBody: null };\n if (event.isBase64Encoded)\n return { textBody: null, binaryBody: Buffer.from(event.body, \"base64\") };\n return { textBody: event.body, binaryBody: null };\n}\n\nfunction parseHeaders(event: APIGatewayProxyEventV2): Record<string, string | string[]> {\n const headers: Record<string, string | string[]> = {};\n if (!event.headers) return headers;\n\n for (const [key, value] of Object.entries(event.headers)) {\n if (value !== undefined) {\n headers[key.toLowerCase()] = value;\n }\n }\n return headers;\n}\n\nfunction parseCookies(event: APIGatewayProxyEventV2): Record<string, string> {\n const cookies: Record<string, string> = {};\n if (!event.cookies) return cookies;\n\n for (const cookie of event.cookies) {\n const eqIndex = cookie.indexOf(\"=\");\n if (eqIndex > 0) {\n cookies[cookie.slice(0, eqIndex).trim()] = cookie.slice(eqIndex + 1).trim();\n }\n }\n return cookies;\n}\n\nfunction parsePathParams(event: APIGatewayProxyEventV2): Record<string, string> {\n const params: Record<string, string> = {};\n if (!event.pathParameters) return params;\n\n for (const [key, value] of Object.entries(event.pathParameters)) {\n if (value !== undefined) {\n params[key] = value;\n }\n }\n return params;\n}\n\nexport function mapApiGatewayV2Event(event: APIGatewayProxyEventV2): HttpRequest {\n const method = event.requestContext.http.method.toUpperCase() as HttpMethod;\n const headers = parseHeaders(event);\n const { textBody, binaryBody } = parseBody(event);\n\n const authorizer = (\n event.requestContext as unknown as {\n authorizer?: { jwt?: { claims?: Record<string, unknown> } };\n }\n ).authorizer;\n\n const contentType = (headers[\"content-type\"] as string | undefined) ?? null;\n const xrayHeader = (headers[\"x-amzn-trace-id\"] as string | undefined) ?? null;\n\n const request: HttpRequest = {\n method,\n path: event.rawPath,\n pathParams: parsePathParams(event),\n query: (event.queryStringParameters ?? {}) as Record<string, string | string[]>,\n headers,\n cookies: parseCookies(event),\n textBody,\n binaryBody,\n contentType,\n requestId: event.requestContext.requestId,\n requestTime: event.requestContext.time ?? new Date().toISOString(),\n auth: authorizer?.jwt?.claims ?? null,\n clientIp: event.requestContext.http.sourceIp,\n traceContext: xrayHeader ? { \"x-amzn-trace-id\": xrayHeader } : null,\n userAgent: event.requestContext.http.userAgent ?? null,\n matchedRoute: event.routeKey ?? null,\n };\n\n debug(\n \"mapEvent: %s %s (auth=%s, traceContext=%s)\",\n method,\n event.rawPath,\n !!authorizer?.jwt?.claims,\n !!xrayHeader,\n );\n\n return request;\n}\n\nexport function mapHttpResponseToResult(response: HttpResponse): APIGatewayProxyStructuredResultV2 {\n const result: APIGatewayProxyStructuredResultV2 = {\n statusCode: response.status,\n };\n\n if (response.headers) {\n result.headers = response.headers;\n }\n\n if (response.binaryBody) {\n result.body = response.binaryBody.toString(\"base64\");\n result.isBase64Encoded = true;\n } else if (response.body) {\n result.body = response.body;\n }\n\n return result;\n}\n"],"mappings":"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","names":["dirname","resolve","createDebug","discoverModule","bootstrap","executeHandlerPipeline","createDefaultSystemLayers","disposeLayers","resolveHandlerByModuleRef","createDebug","debug","createDebug","parseBody","event","body","textBody","binaryBody","isBase64Encoded","Buffer","from","parseHeaders","headers","key","value","Object","entries","undefined","toLowerCase","parseCookies","cookies","cookie","eqIndex","indexOf","slice","trim","parsePathParams","params","pathParameters","mapApiGatewayV2Event","method","requestContext","http","toUpperCase","authorizer","contentType","xrayHeader","request","path","rawPath","pathParams","query","queryStringParameters","requestId","requestTime","time","Date","toISOString","auth","jwt","claims","clientIp","sourceIp","traceContext","userAgent","matchedRoute","routeKey","mapHttpResponseToResult","response","result","statusCode","status","toString","debug","createDebug","cached","shutdownRegistered","registerShutdownHandler","options","process","on","container","closeAll","disposeLayers","systemLayers","appLayers","exit","ensureBootstrapped","createDefaultSystemLayers","length","rootModule","discoverModule","result","bootstrap","modulePath","env","CELERITY_MODULE_PATH","registry","moduleDir","dirname","resolve","cwd","handler","event","_context","apiEvent","httpRequest","mapApiGatewayV2Event","method","path","handlerId","CELERITY_HANDLER_ID","resolved","getHandlerById","undefined","resolveHandlerByModuleRef","getHandler","statusCode","headers","body","JSON","stringify","message","httpResponse","executeHandlerPipeline","mapHttpResponseToResult"]}
package/dist/index.cjs CHANGED
@@ -39,6 +39,7 @@ __export(index_exports, {
39
39
  module.exports = __toCommonJS(index_exports);
40
40
 
41
41
  // src/adapter.ts
42
+ var import_node_path = require("path");
42
43
  var import_debug2 = __toESM(require("debug"), 1);
43
44
  var import_core = require("@celerity-sdk/core");
44
45
 
@@ -148,6 +149,10 @@ var AwsLambdaAdapter = class {
148
149
  static {
149
150
  __name(this, "AwsLambdaAdapter");
150
151
  }
152
+ config;
153
+ constructor() {
154
+ this.config = captureAwsLambdaConfig();
155
+ }
151
156
  createHandler(registry, options) {
152
157
  let cachedHandler = null;
153
158
  return async (event, _context) => {
@@ -155,7 +160,13 @@ var AwsLambdaAdapter = class {
155
160
  const httpRequest = mapApiGatewayV2Event(apiEvent);
156
161
  if (!cachedHandler) {
157
162
  debug2("adapter: cache miss, looking up handler for %s %s", httpRequest.method, httpRequest.path);
158
- cachedHandler = registry.getHandler(httpRequest.path, httpRequest.method) ?? null;
163
+ cachedHandler = (this.config.handlerId ? registry.getHandlerById(this.config.handlerId) : void 0) ?? null;
164
+ if (!cachedHandler && this.config.handlerId) {
165
+ cachedHandler = await (0, import_core.resolveHandlerByModuleRef)(this.config.handlerId, registry, this.config.moduleDir);
166
+ }
167
+ if (!cachedHandler) {
168
+ cachedHandler = registry.getHandler(httpRequest.path, httpRequest.method) ?? null;
169
+ }
159
170
  } else {
160
171
  debug2("adapter: using cached handler for %s %s", httpRequest.method, httpRequest.path);
161
172
  }
@@ -176,8 +187,17 @@ var AwsLambdaAdapter = class {
176
187
  };
177
188
  }
178
189
  };
190
+ function captureAwsLambdaConfig() {
191
+ const modulePath = process.env.CELERITY_MODULE_PATH;
192
+ return {
193
+ handlerId: process.env.CELERITY_HANDLER_ID,
194
+ moduleDir: modulePath ? (0, import_node_path.dirname)((0, import_node_path.resolve)(modulePath)) : process.cwd()
195
+ };
196
+ }
197
+ __name(captureAwsLambdaConfig, "captureAwsLambdaConfig");
179
198
 
180
199
  // src/entry.ts
200
+ var import_node_path2 = require("path");
181
201
  var import_debug3 = __toESM(require("debug"), 1);
182
202
  var import_core2 = require("@celerity-sdk/core");
183
203
  var debug3 = (0, import_debug3.default)("celerity:serverless-aws");
@@ -204,12 +224,14 @@ async function ensureBootstrapped() {
204
224
  debug3("entry: %d system layers created", systemLayers.length);
205
225
  const rootModule = await (0, import_core2.discoverModule)();
206
226
  const result = await (0, import_core2.bootstrap)(rootModule);
227
+ const modulePath = process.env.CELERITY_MODULE_PATH;
207
228
  cached = {
208
229
  registry: result.registry,
209
230
  options: {
210
231
  container: result.container,
211
232
  systemLayers
212
- }
233
+ },
234
+ moduleDir: modulePath ? (0, import_node_path2.dirname)((0, import_node_path2.resolve)(modulePath)) : process.cwd()
213
235
  };
214
236
  debug3("entry: bootstrap complete");
215
237
  }
@@ -217,12 +239,19 @@ async function ensureBootstrapped() {
217
239
  }
218
240
  __name(ensureBootstrapped, "ensureBootstrapped");
219
241
  async function handler(event, _context) {
220
- const { registry, options } = await ensureBootstrapped();
242
+ const { registry, options, moduleDir } = await ensureBootstrapped();
221
243
  registerShutdownHandler(options);
222
244
  const apiEvent = event;
223
245
  const httpRequest = mapApiGatewayV2Event(apiEvent);
224
246
  debug3("entry: %s %s", httpRequest.method, httpRequest.path);
225
- const resolved = registry.getHandler(httpRequest.path, httpRequest.method);
247
+ const handlerId = process.env.CELERITY_HANDLER_ID;
248
+ let resolved = handlerId ? registry.getHandlerById(handlerId) : void 0;
249
+ if (!resolved && handlerId) {
250
+ resolved = await (0, import_core2.resolveHandlerByModuleRef)(handlerId, registry, moduleDir) ?? void 0;
251
+ }
252
+ if (!resolved) {
253
+ resolved = registry.getHandler(httpRequest.path, httpRequest.method);
254
+ }
226
255
  if (!resolved) {
227
256
  return {
228
257
  statusCode: 404,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/adapter.ts","../src/event-mapper.ts","../src/entry.ts"],"sourcesContent":["export { AwsLambdaAdapter } from \"./adapter\";\nexport { mapApiGatewayV2Event, mapHttpResponseToResult } from \"./event-mapper\";\nexport { handler } from \"./entry\";\n","import createDebug from \"debug\";\nimport type { APIGatewayProxyEventV2, APIGatewayProxyResultV2 } from \"aws-lambda\";\nimport type {\n HandlerRegistry,\n ServerlessAdapter,\n ResolvedHandler,\n PipelineOptions,\n} from \"@celerity-sdk/core\";\nimport { executeHandlerPipeline } from \"@celerity-sdk/core\";\nimport { mapApiGatewayV2Event, mapHttpResponseToResult } from \"./event-mapper\";\n\nconst debug = createDebug(\"celerity:serverless-aws\");\n\nexport class AwsLambdaAdapter implements ServerlessAdapter {\n createHandler(\n registry: HandlerRegistry,\n options: PipelineOptions,\n ): (event: unknown, context: unknown) => Promise<unknown> {\n let cachedHandler: ResolvedHandler | null = null;\n\n return async (event: unknown, _context: unknown): Promise<APIGatewayProxyResultV2> => {\n const apiEvent = event as APIGatewayProxyEventV2;\n const httpRequest = mapApiGatewayV2Event(apiEvent);\n\n if (!cachedHandler) {\n debug(\n \"adapter: cache miss, looking up handler for %s %s\",\n httpRequest.method,\n httpRequest.path,\n );\n cachedHandler = registry.getHandler(httpRequest.path, httpRequest.method) ?? null;\n } else {\n debug(\"adapter: using cached handler for %s %s\", httpRequest.method, httpRequest.path);\n }\n\n if (!cachedHandler) {\n debug(\"adapter: no handler found → 404\");\n return {\n statusCode: 404,\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n message: `No handler for ${httpRequest.method} ${httpRequest.path}`,\n }),\n };\n }\n\n const httpResponse = await executeHandlerPipeline(cachedHandler, httpRequest, options);\n return mapHttpResponseToResult(httpResponse);\n };\n }\n}\n","import createDebug from \"debug\";\nimport type { HttpMethod, HttpRequest, HttpResponse } from \"@celerity-sdk/types\";\nimport type { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2 } from \"aws-lambda\";\n\nconst debug = createDebug(\"celerity:serverless-aws\");\n\nfunction parseBody(event: APIGatewayProxyEventV2): {\n textBody: string | null;\n binaryBody: Buffer | null;\n} {\n if (!event.body) return { textBody: null, binaryBody: null };\n if (event.isBase64Encoded)\n return { textBody: null, binaryBody: Buffer.from(event.body, \"base64\") };\n return { textBody: event.body, binaryBody: null };\n}\n\nfunction parseHeaders(event: APIGatewayProxyEventV2): Record<string, string | string[]> {\n const headers: Record<string, string | string[]> = {};\n if (!event.headers) return headers;\n\n for (const [key, value] of Object.entries(event.headers)) {\n if (value !== undefined) {\n headers[key.toLowerCase()] = value;\n }\n }\n return headers;\n}\n\nfunction parseCookies(event: APIGatewayProxyEventV2): Record<string, string> {\n const cookies: Record<string, string> = {};\n if (!event.cookies) return cookies;\n\n for (const cookie of event.cookies) {\n const eqIndex = cookie.indexOf(\"=\");\n if (eqIndex > 0) {\n cookies[cookie.slice(0, eqIndex).trim()] = cookie.slice(eqIndex + 1).trim();\n }\n }\n return cookies;\n}\n\nfunction parsePathParams(event: APIGatewayProxyEventV2): Record<string, string> {\n const params: Record<string, string> = {};\n if (!event.pathParameters) return params;\n\n for (const [key, value] of Object.entries(event.pathParameters)) {\n if (value !== undefined) {\n params[key] = value;\n }\n }\n return params;\n}\n\nexport function mapApiGatewayV2Event(event: APIGatewayProxyEventV2): HttpRequest {\n const method = event.requestContext.http.method.toUpperCase() as HttpMethod;\n const headers = parseHeaders(event);\n const { textBody, binaryBody } = parseBody(event);\n\n const authorizer = (\n event.requestContext as unknown as {\n authorizer?: { jwt?: { claims?: Record<string, unknown> } };\n }\n ).authorizer;\n\n const contentType = (headers[\"content-type\"] as string | undefined) ?? null;\n const xrayHeader = (headers[\"x-amzn-trace-id\"] as string | undefined) ?? null;\n\n const request: HttpRequest = {\n method,\n path: event.rawPath,\n pathParams: parsePathParams(event),\n query: (event.queryStringParameters ?? {}) as Record<string, string | string[]>,\n headers,\n cookies: parseCookies(event),\n textBody,\n binaryBody,\n contentType,\n requestId: event.requestContext.requestId,\n requestTime: event.requestContext.time ?? new Date().toISOString(),\n auth: authorizer?.jwt?.claims ?? null,\n clientIp: event.requestContext.http.sourceIp,\n traceContext: xrayHeader ? { \"x-amzn-trace-id\": xrayHeader } : null,\n userAgent: event.requestContext.http.userAgent ?? null,\n matchedRoute: event.routeKey ?? null,\n };\n\n debug(\n \"mapEvent: %s %s (auth=%s, traceContext=%s)\",\n method,\n event.rawPath,\n !!authorizer?.jwt?.claims,\n !!xrayHeader,\n );\n\n return request;\n}\n\nexport function mapHttpResponseToResult(response: HttpResponse): APIGatewayProxyStructuredResultV2 {\n const result: APIGatewayProxyStructuredResultV2 = {\n statusCode: response.status,\n };\n\n if (response.headers) {\n result.headers = response.headers;\n }\n\n if (response.binaryBody) {\n result.body = response.binaryBody.toString(\"base64\");\n result.isBase64Encoded = true;\n } else if (response.body) {\n result.body = response.body;\n }\n\n return result;\n}\n","import createDebug from \"debug\";\nimport type { APIGatewayProxyEventV2, APIGatewayProxyResultV2 } from \"aws-lambda\";\nimport type { PipelineOptions } from \"@celerity-sdk/core\";\nimport {\n discoverModule,\n bootstrap,\n executeHandlerPipeline,\n createDefaultSystemLayers,\n disposeLayers,\n} from \"@celerity-sdk/core\";\nimport type { HandlerRegistry } from \"@celerity-sdk/core\";\nimport { mapApiGatewayV2Event, mapHttpResponseToResult } from \"./event-mapper\";\n\nconst debug = createDebug(\"celerity:serverless-aws\");\n\nlet cached: { registry: HandlerRegistry; options: PipelineOptions } | null = null;\nlet shutdownRegistered = false;\n\nfunction registerShutdownHandler(options: PipelineOptions): void {\n if (shutdownRegistered) return;\n shutdownRegistered = true;\n debug(\"entry: SIGTERM shutdown handler registered\");\n\n process.on(\"SIGTERM\", async () => {\n await options.container.closeAll();\n await disposeLayers([...(options.systemLayers ?? []), ...(options.appLayers ?? [])]);\n process.exit(0);\n });\n}\n\nasync function ensureBootstrapped(): Promise<{\n registry: HandlerRegistry;\n options: PipelineOptions;\n}> {\n if (!cached) {\n debug(\"entry: cold start, bootstrapping\");\n const systemLayers = await createDefaultSystemLayers();\n debug(\"entry: %d system layers created\", systemLayers.length);\n const rootModule = await discoverModule();\n const result = await bootstrap(rootModule);\n cached = {\n registry: result.registry,\n options: {\n container: result.container,\n systemLayers,\n },\n };\n debug(\"entry: bootstrap complete\");\n }\n return cached;\n}\n\nexport async function handler(event: unknown, _context: unknown): Promise<APIGatewayProxyResultV2> {\n const { registry, options } = await ensureBootstrapped();\n registerShutdownHandler(options);\n const apiEvent = event as APIGatewayProxyEventV2;\n const httpRequest = mapApiGatewayV2Event(apiEvent);\n debug(\"entry: %s %s\", httpRequest.method, httpRequest.path);\n\n const resolved = registry.getHandler(httpRequest.path, httpRequest.method);\n if (!resolved) {\n return {\n statusCode: 404,\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n statusCode: 404,\n message: `No handler for ${httpRequest.method} ${httpRequest.path}`,\n }),\n };\n }\n\n const httpResponse = await executeHandlerPipeline(resolved, httpRequest, options);\n return mapHttpResponseToResult(httpResponse);\n}\n"],"mappings":"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","names":["import_debug","debug","createDebug","parseBody","event","body","textBody","binaryBody","isBase64Encoded","Buffer","from","parseHeaders","headers","key","value","Object","entries","undefined","toLowerCase","parseCookies","cookies","cookie","eqIndex","indexOf","slice","trim","parsePathParams","params","pathParameters","mapApiGatewayV2Event","method","requestContext","http","toUpperCase","authorizer","contentType","xrayHeader","request","path","rawPath","pathParams","query","queryStringParameters","requestId","requestTime","time","Date","toISOString","auth","jwt","claims","clientIp","sourceIp","traceContext","userAgent","matchedRoute","routeKey","mapHttpResponseToResult","response","result","statusCode","status","toString","debug","createDebug","AwsLambdaAdapter","createHandler","registry","options","cachedHandler","event","_context","apiEvent","httpRequest","mapApiGatewayV2Event","method","path","getHandler","statusCode","headers","body","JSON","stringify","message","httpResponse","executeHandlerPipeline","mapHttpResponseToResult","import_debug","import_core","debug","createDebug","cached","shutdownRegistered","registerShutdownHandler","options","process","on","container","closeAll","disposeLayers","systemLayers","appLayers","exit","ensureBootstrapped","createDefaultSystemLayers","length","rootModule","discoverModule","result","bootstrap","registry","handler","event","_context","apiEvent","httpRequest","mapApiGatewayV2Event","method","path","resolved","getHandler","statusCode","headers","body","JSON","stringify","message","httpResponse","executeHandlerPipeline","mapHttpResponseToResult"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/adapter.ts","../src/event-mapper.ts","../src/entry.ts"],"sourcesContent":["export { AwsLambdaAdapter } from \"./adapter\";\nexport { mapApiGatewayV2Event, mapHttpResponseToResult } from \"./event-mapper\";\nexport { handler } from \"./entry\";\n","import { dirname, resolve } from \"node:path\";\nimport createDebug from \"debug\";\nimport type { APIGatewayProxyEventV2, APIGatewayProxyResultV2 } from \"aws-lambda\";\nimport type {\n HandlerRegistry,\n ServerlessAdapter,\n ResolvedHandler,\n PipelineOptions,\n} from \"@celerity-sdk/core\";\nimport { executeHandlerPipeline, resolveHandlerByModuleRef } from \"@celerity-sdk/core\";\nimport { mapApiGatewayV2Event, mapHttpResponseToResult } from \"./event-mapper\";\n\nconst debug = createDebug(\"celerity:serverless-aws\");\n\ntype AwsLambdaAdapterConfig = {\n handlerId?: string;\n moduleDir: string;\n};\n\nexport class AwsLambdaAdapter implements ServerlessAdapter {\n config: AwsLambdaAdapterConfig;\n\n constructor() {\n // Capture config from environment variables on construction\n // to take a snapshot at the initialisation phase similarly to\n // how layers capture config.\n this.config = captureAwsLambdaConfig();\n }\n\n createHandler(\n registry: HandlerRegistry,\n options: PipelineOptions,\n ): (event: unknown, context: unknown) => Promise<unknown> {\n let cachedHandler: ResolvedHandler | null = null;\n\n return async (event: unknown, _context: unknown): Promise<APIGatewayProxyResultV2> => {\n const apiEvent = event as APIGatewayProxyEventV2;\n const httpRequest = mapApiGatewayV2Event(apiEvent);\n\n if (!cachedHandler) {\n debug(\n \"adapter: cache miss, looking up handler for %s %s\",\n httpRequest.method,\n httpRequest.path,\n );\n\n cachedHandler =\n (this.config.handlerId ? registry.getHandlerById(this.config.handlerId) : undefined) ??\n null;\n\n if (!cachedHandler && this.config.handlerId) {\n cachedHandler = await resolveHandlerByModuleRef(\n this.config.handlerId,\n registry,\n this.config.moduleDir,\n );\n }\n\n if (!cachedHandler) {\n cachedHandler = registry.getHandler(httpRequest.path, httpRequest.method) ?? null;\n }\n } else {\n debug(\"adapter: using cached handler for %s %s\", httpRequest.method, httpRequest.path);\n }\n\n if (!cachedHandler) {\n debug(\"adapter: no handler found → 404\");\n return {\n statusCode: 404,\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n message: `No handler for ${httpRequest.method} ${httpRequest.path}`,\n }),\n };\n }\n\n const httpResponse = await executeHandlerPipeline(cachedHandler, httpRequest, options);\n return mapHttpResponseToResult(httpResponse);\n };\n }\n}\n\nfunction captureAwsLambdaConfig(): AwsLambdaAdapterConfig {\n const modulePath = process.env.CELERITY_MODULE_PATH;\n return {\n handlerId: process.env.CELERITY_HANDLER_ID,\n moduleDir: modulePath ? dirname(resolve(modulePath)) : process.cwd(),\n };\n}\n","import createDebug from \"debug\";\nimport type { HttpMethod, HttpRequest, HttpResponse } from \"@celerity-sdk/types\";\nimport type { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2 } from \"aws-lambda\";\n\nconst debug = createDebug(\"celerity:serverless-aws\");\n\nfunction parseBody(event: APIGatewayProxyEventV2): {\n textBody: string | null;\n binaryBody: Buffer | null;\n} {\n if (!event.body) return { textBody: null, binaryBody: null };\n if (event.isBase64Encoded)\n return { textBody: null, binaryBody: Buffer.from(event.body, \"base64\") };\n return { textBody: event.body, binaryBody: null };\n}\n\nfunction parseHeaders(event: APIGatewayProxyEventV2): Record<string, string | string[]> {\n const headers: Record<string, string | string[]> = {};\n if (!event.headers) return headers;\n\n for (const [key, value] of Object.entries(event.headers)) {\n if (value !== undefined) {\n headers[key.toLowerCase()] = value;\n }\n }\n return headers;\n}\n\nfunction parseCookies(event: APIGatewayProxyEventV2): Record<string, string> {\n const cookies: Record<string, string> = {};\n if (!event.cookies) return cookies;\n\n for (const cookie of event.cookies) {\n const eqIndex = cookie.indexOf(\"=\");\n if (eqIndex > 0) {\n cookies[cookie.slice(0, eqIndex).trim()] = cookie.slice(eqIndex + 1).trim();\n }\n }\n return cookies;\n}\n\nfunction parsePathParams(event: APIGatewayProxyEventV2): Record<string, string> {\n const params: Record<string, string> = {};\n if (!event.pathParameters) return params;\n\n for (const [key, value] of Object.entries(event.pathParameters)) {\n if (value !== undefined) {\n params[key] = value;\n }\n }\n return params;\n}\n\nexport function mapApiGatewayV2Event(event: APIGatewayProxyEventV2): HttpRequest {\n const method = event.requestContext.http.method.toUpperCase() as HttpMethod;\n const headers = parseHeaders(event);\n const { textBody, binaryBody } = parseBody(event);\n\n const authorizer = (\n event.requestContext as unknown as {\n authorizer?: { jwt?: { claims?: Record<string, unknown> } };\n }\n ).authorizer;\n\n const contentType = (headers[\"content-type\"] as string | undefined) ?? null;\n const xrayHeader = (headers[\"x-amzn-trace-id\"] as string | undefined) ?? null;\n\n const request: HttpRequest = {\n method,\n path: event.rawPath,\n pathParams: parsePathParams(event),\n query: (event.queryStringParameters ?? {}) as Record<string, string | string[]>,\n headers,\n cookies: parseCookies(event),\n textBody,\n binaryBody,\n contentType,\n requestId: event.requestContext.requestId,\n requestTime: event.requestContext.time ?? new Date().toISOString(),\n auth: authorizer?.jwt?.claims ?? null,\n clientIp: event.requestContext.http.sourceIp,\n traceContext: xrayHeader ? { \"x-amzn-trace-id\": xrayHeader } : null,\n userAgent: event.requestContext.http.userAgent ?? null,\n matchedRoute: event.routeKey ?? null,\n };\n\n debug(\n \"mapEvent: %s %s (auth=%s, traceContext=%s)\",\n method,\n event.rawPath,\n !!authorizer?.jwt?.claims,\n !!xrayHeader,\n );\n\n return request;\n}\n\nexport function mapHttpResponseToResult(response: HttpResponse): APIGatewayProxyStructuredResultV2 {\n const result: APIGatewayProxyStructuredResultV2 = {\n statusCode: response.status,\n };\n\n if (response.headers) {\n result.headers = response.headers;\n }\n\n if (response.binaryBody) {\n result.body = response.binaryBody.toString(\"base64\");\n result.isBase64Encoded = true;\n } else if (response.body) {\n result.body = response.body;\n }\n\n return result;\n}\n","import { dirname, resolve } from \"node:path\";\nimport createDebug from \"debug\";\nimport type { APIGatewayProxyEventV2, APIGatewayProxyResultV2 } from \"aws-lambda\";\nimport type { PipelineOptions } from \"@celerity-sdk/core\";\nimport {\n discoverModule,\n bootstrap,\n executeHandlerPipeline,\n createDefaultSystemLayers,\n disposeLayers,\n resolveHandlerByModuleRef,\n} from \"@celerity-sdk/core\";\nimport type { HandlerRegistry } from \"@celerity-sdk/core\";\nimport { mapApiGatewayV2Event, mapHttpResponseToResult } from \"./event-mapper\";\n\nconst debug = createDebug(\"celerity:serverless-aws\");\n\nlet cached: {\n registry: HandlerRegistry;\n options: PipelineOptions;\n moduleDir: string;\n} | null = null;\nlet shutdownRegistered = false;\n\nfunction registerShutdownHandler(options: PipelineOptions): void {\n if (shutdownRegistered) return;\n shutdownRegistered = true;\n debug(\"entry: SIGTERM shutdown handler registered\");\n\n process.on(\"SIGTERM\", async () => {\n await options.container.closeAll();\n await disposeLayers([...(options.systemLayers ?? []), ...(options.appLayers ?? [])]);\n process.exit(0);\n });\n}\n\nasync function ensureBootstrapped(): Promise<{\n registry: HandlerRegistry;\n options: PipelineOptions;\n moduleDir: string;\n}> {\n if (!cached) {\n debug(\"entry: cold start, bootstrapping\");\n const systemLayers = await createDefaultSystemLayers();\n debug(\"entry: %d system layers created\", systemLayers.length);\n const rootModule = await discoverModule();\n const result = await bootstrap(rootModule);\n const modulePath = process.env.CELERITY_MODULE_PATH;\n cached = {\n registry: result.registry,\n options: {\n container: result.container,\n systemLayers,\n },\n moduleDir: modulePath ? dirname(resolve(modulePath)) : process.cwd(),\n };\n debug(\"entry: bootstrap complete\");\n }\n return cached;\n}\n\nexport async function handler(event: unknown, _context: unknown): Promise<APIGatewayProxyResultV2> {\n const { registry, options, moduleDir } = await ensureBootstrapped();\n registerShutdownHandler(options);\n const apiEvent = event as APIGatewayProxyEventV2;\n const httpRequest = mapApiGatewayV2Event(apiEvent);\n debug(\"entry: %s %s\", httpRequest.method, httpRequest.path);\n\n const handlerId = process.env.CELERITY_HANDLER_ID;\n\n let resolved = handlerId ? registry.getHandlerById(handlerId) : undefined;\n\n if (!resolved && handlerId) {\n resolved = (await resolveHandlerByModuleRef(handlerId, registry, moduleDir)) ?? undefined;\n }\n\n if (!resolved) {\n resolved = registry.getHandler(httpRequest.path, httpRequest.method);\n }\n\n if (!resolved) {\n return {\n statusCode: 404,\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n statusCode: 404,\n message: `No handler for ${httpRequest.method} ${httpRequest.path}`,\n }),\n };\n }\n\n const httpResponse = await executeHandlerPipeline(resolved, httpRequest, options);\n return mapHttpResponseToResult(httpResponse);\n}\n"],"mappings":"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","names":["import_debug","debug","createDebug","parseBody","event","body","textBody","binaryBody","isBase64Encoded","Buffer","from","parseHeaders","headers","key","value","Object","entries","undefined","toLowerCase","parseCookies","cookies","cookie","eqIndex","indexOf","slice","trim","parsePathParams","params","pathParameters","mapApiGatewayV2Event","method","requestContext","http","toUpperCase","authorizer","contentType","xrayHeader","request","path","rawPath","pathParams","query","queryStringParameters","requestId","requestTime","time","Date","toISOString","auth","jwt","claims","clientIp","sourceIp","traceContext","userAgent","matchedRoute","routeKey","mapHttpResponseToResult","response","result","statusCode","status","toString","debug","createDebug","AwsLambdaAdapter","config","captureAwsLambdaConfig","createHandler","registry","options","cachedHandler","event","_context","apiEvent","httpRequest","mapApiGatewayV2Event","method","path","handlerId","getHandlerById","undefined","resolveHandlerByModuleRef","moduleDir","getHandler","statusCode","headers","body","JSON","stringify","message","httpResponse","executeHandlerPipeline","mapHttpResponseToResult","modulePath","process","env","CELERITY_MODULE_PATH","CELERITY_HANDLER_ID","dirname","resolve","cwd","import_node_path","import_debug","import_core","debug","createDebug","cached","shutdownRegistered","registerShutdownHandler","options","process","on","container","closeAll","disposeLayers","systemLayers","appLayers","exit","ensureBootstrapped","createDefaultSystemLayers","length","rootModule","discoverModule","result","bootstrap","modulePath","env","CELERITY_MODULE_PATH","registry","moduleDir","dirname","resolve","cwd","handler","event","_context","apiEvent","httpRequest","mapApiGatewayV2Event","method","path","handlerId","CELERITY_HANDLER_ID","resolved","getHandlerById","undefined","resolveHandlerByModuleRef","getHandler","statusCode","headers","body","JSON","stringify","message","httpResponse","executeHandlerPipeline","mapHttpResponseToResult"]}
package/dist/index.d.cts CHANGED
@@ -3,7 +3,13 @@ import { HttpRequest, HttpResponse } from '@celerity-sdk/types';
3
3
  import { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2 } from 'aws-lambda';
4
4
  export { handler } from './entry.cjs';
5
5
 
6
+ type AwsLambdaAdapterConfig = {
7
+ handlerId?: string;
8
+ moduleDir: string;
9
+ };
6
10
  declare class AwsLambdaAdapter implements ServerlessAdapter {
11
+ config: AwsLambdaAdapterConfig;
12
+ constructor();
7
13
  createHandler(registry: HandlerRegistry, options: PipelineOptions): (event: unknown, context: unknown) => Promise<unknown>;
8
14
  }
9
15
 
package/dist/index.d.ts CHANGED
@@ -3,7 +3,13 @@ import { HttpRequest, HttpResponse } from '@celerity-sdk/types';
3
3
  import { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2 } from 'aws-lambda';
4
4
  export { handler } from './entry.js';
5
5
 
6
+ type AwsLambdaAdapterConfig = {
7
+ handlerId?: string;
8
+ moduleDir: string;
9
+ };
6
10
  declare class AwsLambdaAdapter implements ServerlessAdapter {
11
+ config: AwsLambdaAdapterConfig;
12
+ constructor();
7
13
  createHandler(registry: HandlerRegistry, options: PipelineOptions): (event: unknown, context: unknown) => Promise<unknown>;
8
14
  }
9
15
 
package/dist/index.js CHANGED
@@ -2,8 +2,9 @@ var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
 
4
4
  // src/adapter.ts
5
+ import { dirname, resolve } from "path";
5
6
  import createDebug2 from "debug";
6
- import { executeHandlerPipeline } from "@celerity-sdk/core";
7
+ import { executeHandlerPipeline, resolveHandlerByModuleRef } from "@celerity-sdk/core";
7
8
 
8
9
  // src/event-mapper.ts
9
10
  import createDebug from "debug";
@@ -111,6 +112,10 @@ var AwsLambdaAdapter = class {
111
112
  static {
112
113
  __name(this, "AwsLambdaAdapter");
113
114
  }
115
+ config;
116
+ constructor() {
117
+ this.config = captureAwsLambdaConfig();
118
+ }
114
119
  createHandler(registry, options) {
115
120
  let cachedHandler = null;
116
121
  return async (event, _context) => {
@@ -118,7 +123,13 @@ var AwsLambdaAdapter = class {
118
123
  const httpRequest = mapApiGatewayV2Event(apiEvent);
119
124
  if (!cachedHandler) {
120
125
  debug2("adapter: cache miss, looking up handler for %s %s", httpRequest.method, httpRequest.path);
121
- cachedHandler = registry.getHandler(httpRequest.path, httpRequest.method) ?? null;
126
+ cachedHandler = (this.config.handlerId ? registry.getHandlerById(this.config.handlerId) : void 0) ?? null;
127
+ if (!cachedHandler && this.config.handlerId) {
128
+ cachedHandler = await resolveHandlerByModuleRef(this.config.handlerId, registry, this.config.moduleDir);
129
+ }
130
+ if (!cachedHandler) {
131
+ cachedHandler = registry.getHandler(httpRequest.path, httpRequest.method) ?? null;
132
+ }
122
133
  } else {
123
134
  debug2("adapter: using cached handler for %s %s", httpRequest.method, httpRequest.path);
124
135
  }
@@ -139,10 +150,19 @@ var AwsLambdaAdapter = class {
139
150
  };
140
151
  }
141
152
  };
153
+ function captureAwsLambdaConfig() {
154
+ const modulePath = process.env.CELERITY_MODULE_PATH;
155
+ return {
156
+ handlerId: process.env.CELERITY_HANDLER_ID,
157
+ moduleDir: modulePath ? dirname(resolve(modulePath)) : process.cwd()
158
+ };
159
+ }
160
+ __name(captureAwsLambdaConfig, "captureAwsLambdaConfig");
142
161
 
143
162
  // src/entry.ts
163
+ import { dirname as dirname2, resolve as resolve2 } from "path";
144
164
  import createDebug3 from "debug";
145
- import { discoverModule, bootstrap, executeHandlerPipeline as executeHandlerPipeline2, createDefaultSystemLayers, disposeLayers } from "@celerity-sdk/core";
165
+ import { discoverModule, bootstrap, executeHandlerPipeline as executeHandlerPipeline2, createDefaultSystemLayers, disposeLayers, resolveHandlerByModuleRef as resolveHandlerByModuleRef2 } from "@celerity-sdk/core";
146
166
  var debug3 = createDebug3("celerity:serverless-aws");
147
167
  var cached = null;
148
168
  var shutdownRegistered = false;
@@ -167,12 +187,14 @@ async function ensureBootstrapped() {
167
187
  debug3("entry: %d system layers created", systemLayers.length);
168
188
  const rootModule = await discoverModule();
169
189
  const result = await bootstrap(rootModule);
190
+ const modulePath = process.env.CELERITY_MODULE_PATH;
170
191
  cached = {
171
192
  registry: result.registry,
172
193
  options: {
173
194
  container: result.container,
174
195
  systemLayers
175
- }
196
+ },
197
+ moduleDir: modulePath ? dirname2(resolve2(modulePath)) : process.cwd()
176
198
  };
177
199
  debug3("entry: bootstrap complete");
178
200
  }
@@ -180,12 +202,19 @@ async function ensureBootstrapped() {
180
202
  }
181
203
  __name(ensureBootstrapped, "ensureBootstrapped");
182
204
  async function handler(event, _context) {
183
- const { registry, options } = await ensureBootstrapped();
205
+ const { registry, options, moduleDir } = await ensureBootstrapped();
184
206
  registerShutdownHandler(options);
185
207
  const apiEvent = event;
186
208
  const httpRequest = mapApiGatewayV2Event(apiEvent);
187
209
  debug3("entry: %s %s", httpRequest.method, httpRequest.path);
188
- const resolved = registry.getHandler(httpRequest.path, httpRequest.method);
210
+ const handlerId = process.env.CELERITY_HANDLER_ID;
211
+ let resolved = handlerId ? registry.getHandlerById(handlerId) : void 0;
212
+ if (!resolved && handlerId) {
213
+ resolved = await resolveHandlerByModuleRef2(handlerId, registry, moduleDir) ?? void 0;
214
+ }
215
+ if (!resolved) {
216
+ resolved = registry.getHandler(httpRequest.path, httpRequest.method);
217
+ }
189
218
  if (!resolved) {
190
219
  return {
191
220
  statusCode: 404,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/adapter.ts","../src/event-mapper.ts","../src/entry.ts"],"sourcesContent":["import createDebug from \"debug\";\nimport type { APIGatewayProxyEventV2, APIGatewayProxyResultV2 } from \"aws-lambda\";\nimport type {\n HandlerRegistry,\n ServerlessAdapter,\n ResolvedHandler,\n PipelineOptions,\n} from \"@celerity-sdk/core\";\nimport { executeHandlerPipeline } from \"@celerity-sdk/core\";\nimport { mapApiGatewayV2Event, mapHttpResponseToResult } from \"./event-mapper\";\n\nconst debug = createDebug(\"celerity:serverless-aws\");\n\nexport class AwsLambdaAdapter implements ServerlessAdapter {\n createHandler(\n registry: HandlerRegistry,\n options: PipelineOptions,\n ): (event: unknown, context: unknown) => Promise<unknown> {\n let cachedHandler: ResolvedHandler | null = null;\n\n return async (event: unknown, _context: unknown): Promise<APIGatewayProxyResultV2> => {\n const apiEvent = event as APIGatewayProxyEventV2;\n const httpRequest = mapApiGatewayV2Event(apiEvent);\n\n if (!cachedHandler) {\n debug(\n \"adapter: cache miss, looking up handler for %s %s\",\n httpRequest.method,\n httpRequest.path,\n );\n cachedHandler = registry.getHandler(httpRequest.path, httpRequest.method) ?? null;\n } else {\n debug(\"adapter: using cached handler for %s %s\", httpRequest.method, httpRequest.path);\n }\n\n if (!cachedHandler) {\n debug(\"adapter: no handler found → 404\");\n return {\n statusCode: 404,\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n message: `No handler for ${httpRequest.method} ${httpRequest.path}`,\n }),\n };\n }\n\n const httpResponse = await executeHandlerPipeline(cachedHandler, httpRequest, options);\n return mapHttpResponseToResult(httpResponse);\n };\n }\n}\n","import createDebug from \"debug\";\nimport type { HttpMethod, HttpRequest, HttpResponse } from \"@celerity-sdk/types\";\nimport type { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2 } from \"aws-lambda\";\n\nconst debug = createDebug(\"celerity:serverless-aws\");\n\nfunction parseBody(event: APIGatewayProxyEventV2): {\n textBody: string | null;\n binaryBody: Buffer | null;\n} {\n if (!event.body) return { textBody: null, binaryBody: null };\n if (event.isBase64Encoded)\n return { textBody: null, binaryBody: Buffer.from(event.body, \"base64\") };\n return { textBody: event.body, binaryBody: null };\n}\n\nfunction parseHeaders(event: APIGatewayProxyEventV2): Record<string, string | string[]> {\n const headers: Record<string, string | string[]> = {};\n if (!event.headers) return headers;\n\n for (const [key, value] of Object.entries(event.headers)) {\n if (value !== undefined) {\n headers[key.toLowerCase()] = value;\n }\n }\n return headers;\n}\n\nfunction parseCookies(event: APIGatewayProxyEventV2): Record<string, string> {\n const cookies: Record<string, string> = {};\n if (!event.cookies) return cookies;\n\n for (const cookie of event.cookies) {\n const eqIndex = cookie.indexOf(\"=\");\n if (eqIndex > 0) {\n cookies[cookie.slice(0, eqIndex).trim()] = cookie.slice(eqIndex + 1).trim();\n }\n }\n return cookies;\n}\n\nfunction parsePathParams(event: APIGatewayProxyEventV2): Record<string, string> {\n const params: Record<string, string> = {};\n if (!event.pathParameters) return params;\n\n for (const [key, value] of Object.entries(event.pathParameters)) {\n if (value !== undefined) {\n params[key] = value;\n }\n }\n return params;\n}\n\nexport function mapApiGatewayV2Event(event: APIGatewayProxyEventV2): HttpRequest {\n const method = event.requestContext.http.method.toUpperCase() as HttpMethod;\n const headers = parseHeaders(event);\n const { textBody, binaryBody } = parseBody(event);\n\n const authorizer = (\n event.requestContext as unknown as {\n authorizer?: { jwt?: { claims?: Record<string, unknown> } };\n }\n ).authorizer;\n\n const contentType = (headers[\"content-type\"] as string | undefined) ?? null;\n const xrayHeader = (headers[\"x-amzn-trace-id\"] as string | undefined) ?? null;\n\n const request: HttpRequest = {\n method,\n path: event.rawPath,\n pathParams: parsePathParams(event),\n query: (event.queryStringParameters ?? {}) as Record<string, string | string[]>,\n headers,\n cookies: parseCookies(event),\n textBody,\n binaryBody,\n contentType,\n requestId: event.requestContext.requestId,\n requestTime: event.requestContext.time ?? new Date().toISOString(),\n auth: authorizer?.jwt?.claims ?? null,\n clientIp: event.requestContext.http.sourceIp,\n traceContext: xrayHeader ? { \"x-amzn-trace-id\": xrayHeader } : null,\n userAgent: event.requestContext.http.userAgent ?? null,\n matchedRoute: event.routeKey ?? null,\n };\n\n debug(\n \"mapEvent: %s %s (auth=%s, traceContext=%s)\",\n method,\n event.rawPath,\n !!authorizer?.jwt?.claims,\n !!xrayHeader,\n );\n\n return request;\n}\n\nexport function mapHttpResponseToResult(response: HttpResponse): APIGatewayProxyStructuredResultV2 {\n const result: APIGatewayProxyStructuredResultV2 = {\n statusCode: response.status,\n };\n\n if (response.headers) {\n result.headers = response.headers;\n }\n\n if (response.binaryBody) {\n result.body = response.binaryBody.toString(\"base64\");\n result.isBase64Encoded = true;\n } else if (response.body) {\n result.body = response.body;\n }\n\n return result;\n}\n","import createDebug from \"debug\";\nimport type { APIGatewayProxyEventV2, APIGatewayProxyResultV2 } from \"aws-lambda\";\nimport type { PipelineOptions } from \"@celerity-sdk/core\";\nimport {\n discoverModule,\n bootstrap,\n executeHandlerPipeline,\n createDefaultSystemLayers,\n disposeLayers,\n} from \"@celerity-sdk/core\";\nimport type { HandlerRegistry } from \"@celerity-sdk/core\";\nimport { mapApiGatewayV2Event, mapHttpResponseToResult } from \"./event-mapper\";\n\nconst debug = createDebug(\"celerity:serverless-aws\");\n\nlet cached: { registry: HandlerRegistry; options: PipelineOptions } | null = null;\nlet shutdownRegistered = false;\n\nfunction registerShutdownHandler(options: PipelineOptions): void {\n if (shutdownRegistered) return;\n shutdownRegistered = true;\n debug(\"entry: SIGTERM shutdown handler registered\");\n\n process.on(\"SIGTERM\", async () => {\n await options.container.closeAll();\n await disposeLayers([...(options.systemLayers ?? []), ...(options.appLayers ?? [])]);\n process.exit(0);\n });\n}\n\nasync function ensureBootstrapped(): Promise<{\n registry: HandlerRegistry;\n options: PipelineOptions;\n}> {\n if (!cached) {\n debug(\"entry: cold start, bootstrapping\");\n const systemLayers = await createDefaultSystemLayers();\n debug(\"entry: %d system layers created\", systemLayers.length);\n const rootModule = await discoverModule();\n const result = await bootstrap(rootModule);\n cached = {\n registry: result.registry,\n options: {\n container: result.container,\n systemLayers,\n },\n };\n debug(\"entry: bootstrap complete\");\n }\n return cached;\n}\n\nexport async function handler(event: unknown, _context: unknown): Promise<APIGatewayProxyResultV2> {\n const { registry, options } = await ensureBootstrapped();\n registerShutdownHandler(options);\n const apiEvent = event as APIGatewayProxyEventV2;\n const httpRequest = mapApiGatewayV2Event(apiEvent);\n debug(\"entry: %s %s\", httpRequest.method, httpRequest.path);\n\n const resolved = registry.getHandler(httpRequest.path, httpRequest.method);\n if (!resolved) {\n return {\n statusCode: 404,\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n statusCode: 404,\n message: `No handler for ${httpRequest.method} ${httpRequest.path}`,\n }),\n };\n }\n\n const httpResponse = await executeHandlerPipeline(resolved, httpRequest, options);\n return mapHttpResponseToResult(httpResponse);\n}\n"],"mappings":"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","names":["createDebug","executeHandlerPipeline","createDebug","debug","createDebug","parseBody","event","body","textBody","binaryBody","isBase64Encoded","Buffer","from","parseHeaders","headers","key","value","Object","entries","undefined","toLowerCase","parseCookies","cookies","cookie","eqIndex","indexOf","slice","trim","parsePathParams","params","pathParameters","mapApiGatewayV2Event","method","requestContext","http","toUpperCase","authorizer","contentType","xrayHeader","request","path","rawPath","pathParams","query","queryStringParameters","requestId","requestTime","time","Date","toISOString","auth","jwt","claims","clientIp","sourceIp","traceContext","userAgent","matchedRoute","routeKey","mapHttpResponseToResult","response","result","statusCode","status","toString","debug","createDebug","AwsLambdaAdapter","createHandler","registry","options","cachedHandler","event","_context","apiEvent","httpRequest","mapApiGatewayV2Event","method","path","getHandler","statusCode","headers","body","JSON","stringify","message","httpResponse","executeHandlerPipeline","mapHttpResponseToResult","createDebug","discoverModule","bootstrap","executeHandlerPipeline","createDefaultSystemLayers","disposeLayers","debug","createDebug","cached","shutdownRegistered","registerShutdownHandler","options","process","on","container","closeAll","disposeLayers","systemLayers","appLayers","exit","ensureBootstrapped","createDefaultSystemLayers","length","rootModule","discoverModule","result","bootstrap","registry","handler","event","_context","apiEvent","httpRequest","mapApiGatewayV2Event","method","path","resolved","getHandler","statusCode","headers","body","JSON","stringify","message","httpResponse","executeHandlerPipeline","mapHttpResponseToResult"]}
1
+ {"version":3,"sources":["../src/adapter.ts","../src/event-mapper.ts","../src/entry.ts"],"sourcesContent":["import { dirname, resolve } from \"node:path\";\nimport createDebug from \"debug\";\nimport type { APIGatewayProxyEventV2, APIGatewayProxyResultV2 } from \"aws-lambda\";\nimport type {\n HandlerRegistry,\n ServerlessAdapter,\n ResolvedHandler,\n PipelineOptions,\n} from \"@celerity-sdk/core\";\nimport { executeHandlerPipeline, resolveHandlerByModuleRef } from \"@celerity-sdk/core\";\nimport { mapApiGatewayV2Event, mapHttpResponseToResult } from \"./event-mapper\";\n\nconst debug = createDebug(\"celerity:serverless-aws\");\n\ntype AwsLambdaAdapterConfig = {\n handlerId?: string;\n moduleDir: string;\n};\n\nexport class AwsLambdaAdapter implements ServerlessAdapter {\n config: AwsLambdaAdapterConfig;\n\n constructor() {\n // Capture config from environment variables on construction\n // to take a snapshot at the initialisation phase similarly to\n // how layers capture config.\n this.config = captureAwsLambdaConfig();\n }\n\n createHandler(\n registry: HandlerRegistry,\n options: PipelineOptions,\n ): (event: unknown, context: unknown) => Promise<unknown> {\n let cachedHandler: ResolvedHandler | null = null;\n\n return async (event: unknown, _context: unknown): Promise<APIGatewayProxyResultV2> => {\n const apiEvent = event as APIGatewayProxyEventV2;\n const httpRequest = mapApiGatewayV2Event(apiEvent);\n\n if (!cachedHandler) {\n debug(\n \"adapter: cache miss, looking up handler for %s %s\",\n httpRequest.method,\n httpRequest.path,\n );\n\n cachedHandler =\n (this.config.handlerId ? registry.getHandlerById(this.config.handlerId) : undefined) ??\n null;\n\n if (!cachedHandler && this.config.handlerId) {\n cachedHandler = await resolveHandlerByModuleRef(\n this.config.handlerId,\n registry,\n this.config.moduleDir,\n );\n }\n\n if (!cachedHandler) {\n cachedHandler = registry.getHandler(httpRequest.path, httpRequest.method) ?? null;\n }\n } else {\n debug(\"adapter: using cached handler for %s %s\", httpRequest.method, httpRequest.path);\n }\n\n if (!cachedHandler) {\n debug(\"adapter: no handler found → 404\");\n return {\n statusCode: 404,\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n message: `No handler for ${httpRequest.method} ${httpRequest.path}`,\n }),\n };\n }\n\n const httpResponse = await executeHandlerPipeline(cachedHandler, httpRequest, options);\n return mapHttpResponseToResult(httpResponse);\n };\n }\n}\n\nfunction captureAwsLambdaConfig(): AwsLambdaAdapterConfig {\n const modulePath = process.env.CELERITY_MODULE_PATH;\n return {\n handlerId: process.env.CELERITY_HANDLER_ID,\n moduleDir: modulePath ? dirname(resolve(modulePath)) : process.cwd(),\n };\n}\n","import createDebug from \"debug\";\nimport type { HttpMethod, HttpRequest, HttpResponse } from \"@celerity-sdk/types\";\nimport type { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2 } from \"aws-lambda\";\n\nconst debug = createDebug(\"celerity:serverless-aws\");\n\nfunction parseBody(event: APIGatewayProxyEventV2): {\n textBody: string | null;\n binaryBody: Buffer | null;\n} {\n if (!event.body) return { textBody: null, binaryBody: null };\n if (event.isBase64Encoded)\n return { textBody: null, binaryBody: Buffer.from(event.body, \"base64\") };\n return { textBody: event.body, binaryBody: null };\n}\n\nfunction parseHeaders(event: APIGatewayProxyEventV2): Record<string, string | string[]> {\n const headers: Record<string, string | string[]> = {};\n if (!event.headers) return headers;\n\n for (const [key, value] of Object.entries(event.headers)) {\n if (value !== undefined) {\n headers[key.toLowerCase()] = value;\n }\n }\n return headers;\n}\n\nfunction parseCookies(event: APIGatewayProxyEventV2): Record<string, string> {\n const cookies: Record<string, string> = {};\n if (!event.cookies) return cookies;\n\n for (const cookie of event.cookies) {\n const eqIndex = cookie.indexOf(\"=\");\n if (eqIndex > 0) {\n cookies[cookie.slice(0, eqIndex).trim()] = cookie.slice(eqIndex + 1).trim();\n }\n }\n return cookies;\n}\n\nfunction parsePathParams(event: APIGatewayProxyEventV2): Record<string, string> {\n const params: Record<string, string> = {};\n if (!event.pathParameters) return params;\n\n for (const [key, value] of Object.entries(event.pathParameters)) {\n if (value !== undefined) {\n params[key] = value;\n }\n }\n return params;\n}\n\nexport function mapApiGatewayV2Event(event: APIGatewayProxyEventV2): HttpRequest {\n const method = event.requestContext.http.method.toUpperCase() as HttpMethod;\n const headers = parseHeaders(event);\n const { textBody, binaryBody } = parseBody(event);\n\n const authorizer = (\n event.requestContext as unknown as {\n authorizer?: { jwt?: { claims?: Record<string, unknown> } };\n }\n ).authorizer;\n\n const contentType = (headers[\"content-type\"] as string | undefined) ?? null;\n const xrayHeader = (headers[\"x-amzn-trace-id\"] as string | undefined) ?? null;\n\n const request: HttpRequest = {\n method,\n path: event.rawPath,\n pathParams: parsePathParams(event),\n query: (event.queryStringParameters ?? {}) as Record<string, string | string[]>,\n headers,\n cookies: parseCookies(event),\n textBody,\n binaryBody,\n contentType,\n requestId: event.requestContext.requestId,\n requestTime: event.requestContext.time ?? new Date().toISOString(),\n auth: authorizer?.jwt?.claims ?? null,\n clientIp: event.requestContext.http.sourceIp,\n traceContext: xrayHeader ? { \"x-amzn-trace-id\": xrayHeader } : null,\n userAgent: event.requestContext.http.userAgent ?? null,\n matchedRoute: event.routeKey ?? null,\n };\n\n debug(\n \"mapEvent: %s %s (auth=%s, traceContext=%s)\",\n method,\n event.rawPath,\n !!authorizer?.jwt?.claims,\n !!xrayHeader,\n );\n\n return request;\n}\n\nexport function mapHttpResponseToResult(response: HttpResponse): APIGatewayProxyStructuredResultV2 {\n const result: APIGatewayProxyStructuredResultV2 = {\n statusCode: response.status,\n };\n\n if (response.headers) {\n result.headers = response.headers;\n }\n\n if (response.binaryBody) {\n result.body = response.binaryBody.toString(\"base64\");\n result.isBase64Encoded = true;\n } else if (response.body) {\n result.body = response.body;\n }\n\n return result;\n}\n","import { dirname, resolve } from \"node:path\";\nimport createDebug from \"debug\";\nimport type { APIGatewayProxyEventV2, APIGatewayProxyResultV2 } from \"aws-lambda\";\nimport type { PipelineOptions } from \"@celerity-sdk/core\";\nimport {\n discoverModule,\n bootstrap,\n executeHandlerPipeline,\n createDefaultSystemLayers,\n disposeLayers,\n resolveHandlerByModuleRef,\n} from \"@celerity-sdk/core\";\nimport type { HandlerRegistry } from \"@celerity-sdk/core\";\nimport { mapApiGatewayV2Event, mapHttpResponseToResult } from \"./event-mapper\";\n\nconst debug = createDebug(\"celerity:serverless-aws\");\n\nlet cached: {\n registry: HandlerRegistry;\n options: PipelineOptions;\n moduleDir: string;\n} | null = null;\nlet shutdownRegistered = false;\n\nfunction registerShutdownHandler(options: PipelineOptions): void {\n if (shutdownRegistered) return;\n shutdownRegistered = true;\n debug(\"entry: SIGTERM shutdown handler registered\");\n\n process.on(\"SIGTERM\", async () => {\n await options.container.closeAll();\n await disposeLayers([...(options.systemLayers ?? []), ...(options.appLayers ?? [])]);\n process.exit(0);\n });\n}\n\nasync function ensureBootstrapped(): Promise<{\n registry: HandlerRegistry;\n options: PipelineOptions;\n moduleDir: string;\n}> {\n if (!cached) {\n debug(\"entry: cold start, bootstrapping\");\n const systemLayers = await createDefaultSystemLayers();\n debug(\"entry: %d system layers created\", systemLayers.length);\n const rootModule = await discoverModule();\n const result = await bootstrap(rootModule);\n const modulePath = process.env.CELERITY_MODULE_PATH;\n cached = {\n registry: result.registry,\n options: {\n container: result.container,\n systemLayers,\n },\n moduleDir: modulePath ? dirname(resolve(modulePath)) : process.cwd(),\n };\n debug(\"entry: bootstrap complete\");\n }\n return cached;\n}\n\nexport async function handler(event: unknown, _context: unknown): Promise<APIGatewayProxyResultV2> {\n const { registry, options, moduleDir } = await ensureBootstrapped();\n registerShutdownHandler(options);\n const apiEvent = event as APIGatewayProxyEventV2;\n const httpRequest = mapApiGatewayV2Event(apiEvent);\n debug(\"entry: %s %s\", httpRequest.method, httpRequest.path);\n\n const handlerId = process.env.CELERITY_HANDLER_ID;\n\n let resolved = handlerId ? registry.getHandlerById(handlerId) : undefined;\n\n if (!resolved && handlerId) {\n resolved = (await resolveHandlerByModuleRef(handlerId, registry, moduleDir)) ?? undefined;\n }\n\n if (!resolved) {\n resolved = registry.getHandler(httpRequest.path, httpRequest.method);\n }\n\n if (!resolved) {\n return {\n statusCode: 404,\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n statusCode: 404,\n message: `No handler for ${httpRequest.method} ${httpRequest.path}`,\n }),\n };\n }\n\n const httpResponse = await executeHandlerPipeline(resolved, httpRequest, options);\n return mapHttpResponseToResult(httpResponse);\n}\n"],"mappings":"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","names":["dirname","resolve","createDebug","executeHandlerPipeline","resolveHandlerByModuleRef","createDebug","debug","createDebug","parseBody","event","body","textBody","binaryBody","isBase64Encoded","Buffer","from","parseHeaders","headers","key","value","Object","entries","undefined","toLowerCase","parseCookies","cookies","cookie","eqIndex","indexOf","slice","trim","parsePathParams","params","pathParameters","mapApiGatewayV2Event","method","requestContext","http","toUpperCase","authorizer","contentType","xrayHeader","request","path","rawPath","pathParams","query","queryStringParameters","requestId","requestTime","time","Date","toISOString","auth","jwt","claims","clientIp","sourceIp","traceContext","userAgent","matchedRoute","routeKey","mapHttpResponseToResult","response","result","statusCode","status","toString","debug","createDebug","AwsLambdaAdapter","config","captureAwsLambdaConfig","createHandler","registry","options","cachedHandler","event","_context","apiEvent","httpRequest","mapApiGatewayV2Event","method","path","handlerId","getHandlerById","undefined","resolveHandlerByModuleRef","moduleDir","getHandler","statusCode","headers","body","JSON","stringify","message","httpResponse","executeHandlerPipeline","mapHttpResponseToResult","modulePath","process","env","CELERITY_MODULE_PATH","CELERITY_HANDLER_ID","dirname","resolve","cwd","dirname","resolve","createDebug","discoverModule","bootstrap","executeHandlerPipeline","createDefaultSystemLayers","disposeLayers","resolveHandlerByModuleRef","debug","createDebug","cached","shutdownRegistered","registerShutdownHandler","options","process","on","container","closeAll","disposeLayers","systemLayers","appLayers","exit","ensureBootstrapped","createDefaultSystemLayers","length","rootModule","discoverModule","result","bootstrap","modulePath","env","CELERITY_MODULE_PATH","registry","moduleDir","dirname","resolve","cwd","handler","event","_context","apiEvent","httpRequest","mapApiGatewayV2Event","method","path","handlerId","CELERITY_HANDLER_ID","resolved","getHandlerById","undefined","resolveHandlerByModuleRef","getHandler","statusCode","headers","body","JSON","stringify","message","httpResponse","executeHandlerPipeline","mapHttpResponseToResult"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@celerity-sdk/serverless-aws",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "AWS Lambda adapter for the Celerity Node SDK — converts API Gateway events to SDK types",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -42,8 +42,8 @@
42
42
  },
43
43
  "dependencies": {
44
44
  "debug": "^4.4.0",
45
- "@celerity-sdk/types": "^0.2.0",
46
- "@celerity-sdk/core": "^0.2.0"
45
+ "@celerity-sdk/core": "^0.3.0",
46
+ "@celerity-sdk/types": "^0.3.0"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/aws-lambda": "^8.10.160"