@celerity-sdk/serverless-aws 0.3.0 → 0.4.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/dist/entry.cjs CHANGED
@@ -34,12 +34,13 @@ __export(entry_exports, {
34
34
  handler: () => handler
35
35
  });
36
36
  module.exports = __toCommonJS(entry_exports);
37
- var import_node_path = require("path");
38
- var import_debug2 = __toESM(require("debug"), 1);
39
- var import_core = require("@celerity-sdk/core");
37
+ var import_debug4 = __toESM(require("debug"), 1);
38
+ var import_core2 = require("@celerity-sdk/core");
40
39
 
41
40
  // src/event-mapper.ts
42
41
  var import_debug = __toESM(require("debug"), 1);
42
+ var import_util_dynamodb = require("@aws-sdk/util-dynamodb");
43
+ var import_common = require("@celerity-sdk/common");
43
44
  var debug = (0, import_debug.default)("celerity:serverless-aws");
44
45
  function parseBody(event) {
45
46
  if (!event.body) return {
@@ -137,74 +138,497 @@ function mapHttpResponseToResult(response) {
137
138
  return result;
138
139
  }
139
140
  __name(mapHttpResponseToResult, "mapHttpResponseToResult");
141
+ var VALID_HANDLER_TYPES = /* @__PURE__ */ new Set([
142
+ "http",
143
+ "websocket",
144
+ "consumer",
145
+ "schedule",
146
+ "custom"
147
+ ]);
148
+ function hasNested(obj, key, nested) {
149
+ const child = obj[key];
150
+ return child !== null && typeof child === "object" && nested in child;
151
+ }
152
+ __name(hasNested, "hasNested");
153
+ function detectEventType(event) {
154
+ const envType = process.env.CELERITY_HANDLER_TYPE;
155
+ if (envType && VALID_HANDLER_TYPES.has(envType)) {
156
+ debug("detectEventType: using env var CELERITY_HANDLER_TYPE=%s", envType);
157
+ return envType;
158
+ }
159
+ if (!event || typeof event !== "object") return "custom";
160
+ const e = event;
161
+ if (hasNested(e, "requestContext", "http")) return "http";
162
+ if (hasNested(e, "requestContext", "connectionId") && hasNested(e, "requestContext", "eventType")) return "websocket";
163
+ if (Array.isArray(e.Records) && e.Records.length > 0 && e.Records[0]?.eventSource === "aws:sqs") return "consumer";
164
+ if ("source" in e && "detail-type" in e) return "schedule";
165
+ return "custom";
166
+ }
167
+ __name(detectEventType, "detectEventType");
168
+ var WS_EVENT_TYPE_MAP = {
169
+ CONNECT: "connect",
170
+ MESSAGE: "message",
171
+ DISCONNECT: "disconnect"
172
+ };
173
+ function mapApiGatewayWebSocketEvent(event) {
174
+ const rc = event.requestContext;
175
+ const eventType = WS_EVENT_TYPE_MAP[rc.eventType] ?? "message";
176
+ let jsonBody;
177
+ let binaryBody;
178
+ if (event.body) {
179
+ if (event.isBase64Encoded) {
180
+ binaryBody = Buffer.from(event.body, "base64");
181
+ } else {
182
+ try {
183
+ jsonBody = JSON.parse(event.body);
184
+ } catch {
185
+ jsonBody = event.body;
186
+ }
187
+ }
188
+ }
189
+ const message = {
190
+ messageType: binaryBody ? "binary" : "json",
191
+ eventType,
192
+ connectionId: rc.connectionId,
193
+ messageId: rc.requestId,
194
+ jsonBody,
195
+ binaryBody,
196
+ requestContext: {
197
+ requestId: rc.requestId,
198
+ requestTime: rc.requestTimeEpoch,
199
+ path: `/${rc.stage}`,
200
+ protocolVersion: "websocket",
201
+ headers: {},
202
+ clientIp: "",
203
+ query: {},
204
+ cookies: {}
205
+ },
206
+ traceContext: null
207
+ };
208
+ const routeKey = rc.routeKey;
209
+ const endpoint = `https://${rc.domainName}/${rc.stage}`;
210
+ debug("mapWebSocketEvent: %s connectionId=%s routeKey=%s", eventType, rc.connectionId, routeKey);
211
+ return {
212
+ message,
213
+ routeKey,
214
+ endpoint
215
+ };
216
+ }
217
+ __name(mapApiGatewayWebSocketEvent, "mapApiGatewayWebSocketEvent");
218
+ function tryParseJson(body) {
219
+ try {
220
+ return JSON.parse(body);
221
+ } catch {
222
+ return void 0;
223
+ }
224
+ }
225
+ __name(tryParseJson, "tryParseJson");
226
+ function isS3Notification(parsed) {
227
+ if (!parsed || typeof parsed !== "object") return false;
228
+ const obj = parsed;
229
+ if (!Array.isArray(obj.Records) || obj.Records.length === 0) return false;
230
+ const first = obj.Records[0];
231
+ return first.eventSource === "aws:s3";
232
+ }
233
+ __name(isS3Notification, "isS3Notification");
234
+ function isDynamoDBStreamRecord(parsed) {
235
+ if (!parsed || typeof parsed !== "object") return false;
236
+ return parsed.eventSource === "aws:dynamodb";
237
+ }
238
+ __name(isDynamoDBStreamRecord, "isDynamoDBStreamRecord");
239
+ function extractTableName(eventSourceARN) {
240
+ if (!eventSourceARN) return void 0;
241
+ const match = eventSourceARN.match(/table\/([^/]+)/);
242
+ return match?.[1];
243
+ }
244
+ __name(extractTableName, "extractTableName");
245
+ function transformS3Body(record) {
246
+ return JSON.stringify({
247
+ key: record.s3.object.key,
248
+ ...record.s3.object.size !== void 0 && {
249
+ size: record.s3.object.size
250
+ },
251
+ ...record.s3.object.eTag !== void 0 && {
252
+ eTag: record.s3.object.eTag
253
+ }
254
+ });
255
+ }
256
+ __name(transformS3Body, "transformS3Body");
257
+ function unmarshallRecord(attrs) {
258
+ if (!attrs) return void 0;
259
+ return (0, import_util_dynamodb.unmarshall)(attrs);
260
+ }
261
+ __name(unmarshallRecord, "unmarshallRecord");
262
+ function transformDynamoDBBody(record) {
263
+ const db = record.dynamodb;
264
+ return JSON.stringify({
265
+ keys: unmarshallRecord(db?.Keys) ?? {},
266
+ ...db?.NewImage !== void 0 && {
267
+ newItem: unmarshallRecord(db.NewImage)
268
+ },
269
+ ...db?.OldImage !== void 0 && {
270
+ oldItem: unmarshallRecord(db.OldImage)
271
+ }
272
+ });
273
+ }
274
+ __name(transformDynamoDBBody, "transformDynamoDBBody");
275
+ function mapSqsRecord(record) {
276
+ const sqsVendor = {
277
+ receiptHandle: record.receiptHandle,
278
+ attributes: record.attributes,
279
+ md5OfBody: record.md5OfBody,
280
+ eventSource: record.eventSource,
281
+ awsRegion: record.awsRegion
282
+ };
283
+ const parsed = tryParseJson(record.body);
284
+ if (isS3Notification(parsed)) {
285
+ const s3Record = parsed.Records[0];
286
+ return {
287
+ messageId: record.messageId,
288
+ body: transformS3Body(s3Record),
289
+ source: record.eventSourceARN,
290
+ sourceType: "bucket",
291
+ sourceName: s3Record.s3.bucket.name,
292
+ eventType: (0, import_common.mapBucketEventType)(s3Record.eventName),
293
+ messageAttributes: record.messageAttributes,
294
+ vendor: {
295
+ ...sqsVendor,
296
+ originalBody: parsed
297
+ }
298
+ };
299
+ }
300
+ if (isDynamoDBStreamRecord(parsed)) {
301
+ return {
302
+ messageId: record.messageId,
303
+ body: transformDynamoDBBody(parsed),
304
+ source: record.eventSourceARN,
305
+ sourceType: "datastore",
306
+ sourceName: extractTableName(parsed.eventSourceARN),
307
+ eventType: (0, import_common.mapDatastoreEventType)(parsed.eventName),
308
+ messageAttributes: record.messageAttributes,
309
+ vendor: {
310
+ ...sqsVendor,
311
+ originalBody: parsed
312
+ }
313
+ };
314
+ }
315
+ return {
316
+ messageId: record.messageId,
317
+ body: record.body,
318
+ source: record.eventSourceARN,
319
+ messageAttributes: record.messageAttributes,
320
+ vendor: sqsVendor
321
+ };
322
+ }
323
+ __name(mapSqsRecord, "mapSqsRecord");
324
+ function mapSqsEvent(event, handlerTag) {
325
+ const messages = event.Records.map(mapSqsRecord);
326
+ const firstTraceHeader = event.Records[0]?.attributes?.AWSTraceHeader;
327
+ const traceContext = firstTraceHeader ? {
328
+ "x-amzn-trace-id": firstTraceHeader
329
+ } : null;
330
+ debug("mapSqsEvent: %d records, handlerTag=%s", messages.length, handlerTag);
331
+ return {
332
+ handlerTag,
333
+ messages,
334
+ vendor: {
335
+ eventSource: "aws:sqs"
336
+ },
337
+ traceContext
338
+ };
339
+ }
340
+ __name(mapSqsEvent, "mapSqsEvent");
341
+ function mapConsumerResultToSqsBatchResponse(failures) {
342
+ const batchItemFailures = (failures ?? []).map((f) => ({
343
+ itemIdentifier: f.messageId
344
+ }));
345
+ return {
346
+ batchItemFailures
347
+ };
348
+ }
349
+ __name(mapConsumerResultToSqsBatchResponse, "mapConsumerResultToSqsBatchResponse");
350
+ function mapEventBridgeEvent(event, handlerTag) {
351
+ debug("mapEventBridgeEvent: id=%s handlerTag=%s", event.id, handlerTag);
352
+ return {
353
+ handlerTag,
354
+ scheduleId: event.id,
355
+ messageId: event.id,
356
+ schedule: "",
357
+ input: event.detail,
358
+ vendor: {
359
+ source: event.source,
360
+ detailType: event["detail-type"],
361
+ account: event.account,
362
+ region: event.region
363
+ },
364
+ traceContext: null
365
+ };
366
+ }
367
+ __name(mapEventBridgeEvent, "mapEventBridgeEvent");
140
368
 
141
- // src/entry.ts
369
+ // src/adapter.ts
370
+ var import_node_path = require("path");
371
+ var import_debug3 = __toESM(require("debug"), 1);
372
+ var import_core = require("@celerity-sdk/core");
373
+ var import_types = require("@celerity-sdk/types");
374
+
375
+ // src/websocket-sender.ts
376
+ var import_debug2 = __toESM(require("debug"), 1);
142
377
  var debug2 = (0, import_debug2.default)("celerity:serverless-aws");
143
- var cached = null;
378
+ var API_GW_MGMT_PKG = "@aws-sdk/client-apigatewaymanagementapi";
379
+ var ApiGatewayWebSocketSender = class {
380
+ static {
381
+ __name(this, "ApiGatewayWebSocketSender");
382
+ }
383
+ endpoint;
384
+ client = null;
385
+ constructor(endpoint) {
386
+ this.endpoint = endpoint;
387
+ debug2("ApiGatewayWebSocketSender: created with endpoint=%s", endpoint);
388
+ }
389
+ async sendMessage(connectionId, data, _options) {
390
+ const client = await this.getClient();
391
+ const payload = typeof data === "string" ? data : JSON.stringify(data);
392
+ const { PostToConnectionCommand } = await import(API_GW_MGMT_PKG);
393
+ await client.send(new PostToConnectionCommand({
394
+ ConnectionId: connectionId,
395
+ Data: new TextEncoder().encode(payload)
396
+ }));
397
+ debug2("ApiGatewayWebSocketSender: sent message to connectionId=%s", connectionId);
398
+ }
399
+ async getClient() {
400
+ if (!this.client) {
401
+ const { ApiGatewayManagementApiClient } = await import(API_GW_MGMT_PKG);
402
+ this.client = new ApiGatewayManagementApiClient({
403
+ endpoint: this.endpoint
404
+ });
405
+ debug2("ApiGatewayWebSocketSender: client initialized for endpoint=%s", this.endpoint);
406
+ }
407
+ return this.client;
408
+ }
409
+ };
410
+
411
+ // src/adapter.ts
412
+ var debug3 = (0, import_debug3.default)("celerity:serverless-aws");
413
+ var AwsLambdaAdapter = class {
414
+ static {
415
+ __name(this, "AwsLambdaAdapter");
416
+ }
417
+ config;
418
+ wsSenderRegistered = false;
419
+ constructor() {
420
+ this.config = captureAwsLambdaConfig();
421
+ }
422
+ createHttpHandler(registry, options) {
423
+ let cachedHandler2 = null;
424
+ return async (event, _context) => {
425
+ const apiEvent = event;
426
+ const httpRequest = mapApiGatewayV2Event(apiEvent);
427
+ if (!cachedHandler2) {
428
+ debug3("adapter: cache miss, looking up handler for %s %s", httpRequest.method, httpRequest.path);
429
+ cachedHandler2 = (this.config.handlerId ? registry.getHandlerById("http", this.config.handlerId) : void 0) ?? null;
430
+ if (!cachedHandler2 && this.config.handlerId) {
431
+ cachedHandler2 = await (0, import_core.resolveHandlerByModuleRef)(this.config.handlerId, "http", registry, this.config.moduleDir);
432
+ }
433
+ if (!cachedHandler2) {
434
+ cachedHandler2 = registry.getHandler("http", `${httpRequest.method} ${httpRequest.path}`) ?? null;
435
+ }
436
+ } else {
437
+ debug3("adapter: using cached handler for %s %s", httpRequest.method, httpRequest.path);
438
+ }
439
+ if (!cachedHandler2) {
440
+ debug3("adapter: no handler found \u2192 404");
441
+ return {
442
+ statusCode: 404,
443
+ headers: {
444
+ "content-type": "application/json"
445
+ },
446
+ body: JSON.stringify({
447
+ message: `No handler for ${httpRequest.method} ${httpRequest.path}`
448
+ })
449
+ };
450
+ }
451
+ const httpResponse = await (0, import_core.executeHttpPipeline)(cachedHandler2, httpRequest, options);
452
+ return mapHttpResponseToResult(httpResponse);
453
+ };
454
+ }
455
+ createWebSocketHandler(registry, options) {
456
+ let cachedHandler2 = null;
457
+ return async (event, _context) => {
458
+ const wsEvent = event;
459
+ const { message, routeKey, endpoint } = mapApiGatewayWebSocketEvent(wsEvent);
460
+ if (!this.wsSenderRegistered) {
461
+ const sender = new ApiGatewayWebSocketSender(endpoint);
462
+ options.container.register(import_types.WebSocketSender, {
463
+ useValue: sender
464
+ });
465
+ this.wsSenderRegistered = true;
466
+ debug3("adapter: registered ApiGatewayWebSocketSender for endpoint=%s", endpoint);
467
+ }
468
+ if (!cachedHandler2) {
469
+ debug3("adapter: cache miss, looking up WebSocket handler for routeKey=%s", routeKey);
470
+ cachedHandler2 = (this.config.handlerId ? registry.getHandlerById("websocket", this.config.handlerId) : void 0) ?? null;
471
+ if (!cachedHandler2 && this.config.handlerId) {
472
+ cachedHandler2 = await (0, import_core.resolveHandlerByModuleRef)(this.config.handlerId, "websocket", registry, this.config.moduleDir);
473
+ }
474
+ if (!cachedHandler2) {
475
+ cachedHandler2 = registry.getHandler("websocket", routeKey) ?? null;
476
+ }
477
+ } else {
478
+ debug3("adapter: using cached WebSocket handler");
479
+ }
480
+ if (!cachedHandler2) {
481
+ debug3("adapter: no WebSocket handler found \u2192 404");
482
+ return {
483
+ statusCode: 404
484
+ };
485
+ }
486
+ await (0, import_core.executeWebSocketPipeline)(cachedHandler2, message, options);
487
+ return {
488
+ statusCode: 200
489
+ };
490
+ };
491
+ }
492
+ createConsumerHandler(registry, options) {
493
+ let cachedHandler2 = null;
494
+ return async (event, _context) => {
495
+ const sqsEvent = event;
496
+ const handlerTag = this.config.handlerTag ?? sqsEvent.Records[0]?.eventSourceARN ?? "unknown";
497
+ const consumerEvent = mapSqsEvent(sqsEvent, handlerTag);
498
+ if (!cachedHandler2) {
499
+ debug3("adapter: cache miss, looking up Consumer handler for tag=%s", handlerTag);
500
+ cachedHandler2 = (this.config.handlerId ? registry.getHandlerById("consumer", this.config.handlerId) : void 0) ?? null;
501
+ if (!cachedHandler2 && this.config.handlerId) {
502
+ cachedHandler2 = await (0, import_core.resolveHandlerByModuleRef)(this.config.handlerId, "consumer", registry, this.config.moduleDir);
503
+ }
504
+ if (!cachedHandler2) {
505
+ cachedHandler2 = registry.getHandler("consumer", handlerTag) ?? null;
506
+ }
507
+ } else {
508
+ debug3("adapter: using cached Consumer handler");
509
+ }
510
+ if (!cachedHandler2) {
511
+ debug3("adapter: no Consumer handler found \u2192 empty response");
512
+ return {
513
+ batchItemFailures: []
514
+ };
515
+ }
516
+ const result = await (0, import_core.executeConsumerPipeline)(cachedHandler2, consumerEvent, options);
517
+ return mapConsumerResultToSqsBatchResponse(result.failures);
518
+ };
519
+ }
520
+ createScheduleHandler(registry, options) {
521
+ let cachedHandler2 = null;
522
+ return async (event, _context) => {
523
+ const ebEvent = event;
524
+ const handlerTag = this.config.handlerTag ?? ebEvent.resources?.[0] ?? "unknown";
525
+ const scheduleEvent = mapEventBridgeEvent(ebEvent, handlerTag);
526
+ if (!cachedHandler2) {
527
+ debug3("adapter: cache miss, looking up Schedule handler for tag=%s", handlerTag);
528
+ cachedHandler2 = (this.config.handlerId ? registry.getHandlerById("schedule", this.config.handlerId) : void 0) ?? null;
529
+ if (!cachedHandler2 && this.config.handlerId) {
530
+ cachedHandler2 = await (0, import_core.resolveHandlerByModuleRef)(this.config.handlerId, "schedule", registry, this.config.moduleDir);
531
+ }
532
+ if (!cachedHandler2) {
533
+ cachedHandler2 = registry.getHandler("schedule", handlerTag) ?? null;
534
+ }
535
+ } else {
536
+ debug3("adapter: using cached Schedule handler");
537
+ }
538
+ if (!cachedHandler2) {
539
+ debug3("adapter: no Schedule handler found");
540
+ return {
541
+ success: false,
542
+ errorMessage: `No handler for schedule tag: ${handlerTag}`
543
+ };
544
+ }
545
+ return (0, import_core.executeSchedulePipeline)(cachedHandler2, scheduleEvent, options);
546
+ };
547
+ }
548
+ createCustomHandler(registry, options) {
549
+ let cachedHandler2 = null;
550
+ return async (event, _context) => {
551
+ let handlerName = this.config.handlerId;
552
+ let payload = event;
553
+ if (!handlerName && event && typeof event === "object") {
554
+ const e = event;
555
+ if (typeof e.handlerName === "string") {
556
+ handlerName = e.handlerName;
557
+ payload = e.payload ?? {};
558
+ }
559
+ }
560
+ if (!cachedHandler2) {
561
+ debug3("adapter: cache miss, looking up Custom handler for name=%s", handlerName);
562
+ cachedHandler2 = (handlerName ? registry.getHandlerById("custom", handlerName) : void 0) ?? null;
563
+ if (!cachedHandler2 && handlerName) {
564
+ cachedHandler2 = await (0, import_core.resolveHandlerByModuleRef)(handlerName, "custom", registry, this.config.moduleDir);
565
+ }
566
+ if (!cachedHandler2 && handlerName) {
567
+ cachedHandler2 = registry.getHandler("custom", handlerName) ?? null;
568
+ }
569
+ if (!cachedHandler2) {
570
+ const allCustom = registry.getHandlersByType("custom");
571
+ if (allCustom.length === 1) cachedHandler2 = allCustom[0];
572
+ }
573
+ } else {
574
+ debug3("adapter: using cached Custom handler");
575
+ }
576
+ if (!cachedHandler2) {
577
+ debug3("adapter: no Custom handler found");
578
+ return {
579
+ error: `No handler found for custom invoke: ${handlerName ?? "unknown"}`
580
+ };
581
+ }
582
+ return (0, import_core.executeCustomPipeline)(cachedHandler2, payload, options);
583
+ };
584
+ }
585
+ };
586
+ function captureAwsLambdaConfig() {
587
+ const modulePath = process.env.CELERITY_MODULE_PATH;
588
+ return {
589
+ handlerId: process.env.CELERITY_HANDLER_ID,
590
+ handlerTag: process.env.CELERITY_HANDLER_TAG,
591
+ moduleDir: modulePath ? (0, import_node_path.dirname)((0, import_node_path.resolve)(modulePath)) : process.cwd()
592
+ };
593
+ }
594
+ __name(captureAwsLambdaConfig, "captureAwsLambdaConfig");
595
+
596
+ // src/entry.ts
597
+ var debug4 = (0, import_debug4.default)("celerity:serverless-aws");
598
+ var app = null;
599
+ var cachedHandler = null;
144
600
  var shutdownRegistered = false;
145
- function registerShutdownHandler(options) {
601
+ async function ensureBootstrapped() {
602
+ if (!app) {
603
+ debug4("entry: cold start, bootstrapping via CelerityFactory");
604
+ const rootModule = await (0, import_core2.discoverModule)();
605
+ app = await import_core2.CelerityFactory.create(rootModule, {
606
+ adapter: new AwsLambdaAdapter()
607
+ });
608
+ debug4("entry: bootstrap complete");
609
+ }
610
+ return app;
611
+ }
612
+ __name(ensureBootstrapped, "ensureBootstrapped");
613
+ function registerShutdownHandler(application) {
146
614
  if (shutdownRegistered) return;
147
615
  shutdownRegistered = true;
148
- debug2("entry: SIGTERM shutdown handler registered");
616
+ debug4("entry: SIGTERM shutdown handler registered");
149
617
  process.on("SIGTERM", async () => {
150
- await options.container.closeAll();
151
- await (0, import_core.disposeLayers)([
152
- ...options.systemLayers ?? [],
153
- ...options.appLayers ?? []
154
- ]);
618
+ await application.close();
155
619
  process.exit(0);
156
620
  });
157
621
  }
158
622
  __name(registerShutdownHandler, "registerShutdownHandler");
159
- async function ensureBootstrapped() {
160
- if (!cached) {
161
- debug2("entry: cold start, bootstrapping");
162
- const systemLayers = await (0, import_core.createDefaultSystemLayers)();
163
- debug2("entry: %d system layers created", systemLayers.length);
164
- const rootModule = await (0, import_core.discoverModule)();
165
- const result = await (0, import_core.bootstrap)(rootModule);
166
- const modulePath = process.env.CELERITY_MODULE_PATH;
167
- cached = {
168
- registry: result.registry,
169
- options: {
170
- container: result.container,
171
- systemLayers
172
- },
173
- moduleDir: modulePath ? (0, import_node_path.dirname)((0, import_node_path.resolve)(modulePath)) : process.cwd()
174
- };
175
- debug2("entry: bootstrap complete");
176
- }
177
- return cached;
178
- }
179
- __name(ensureBootstrapped, "ensureBootstrapped");
180
- async function handler(event, _context) {
181
- const { registry, options, moduleDir } = await ensureBootstrapped();
182
- registerShutdownHandler(options);
183
- const apiEvent = event;
184
- const httpRequest = mapApiGatewayV2Event(apiEvent);
185
- debug2("entry: %s %s", httpRequest.method, httpRequest.path);
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
- }
194
- if (!resolved) {
195
- return {
196
- statusCode: 404,
197
- headers: {
198
- "content-type": "application/json"
199
- },
200
- body: JSON.stringify({
201
- statusCode: 404,
202
- message: `No handler for ${httpRequest.method} ${httpRequest.path}`
203
- })
204
- };
623
+ async function handler(event, context) {
624
+ const application = await ensureBootstrapped();
625
+ registerShutdownHandler(application);
626
+ if (!cachedHandler) {
627
+ const eventType = detectEventType(event);
628
+ debug4("entry: creating handler for type=%s", eventType);
629
+ cachedHandler = application.createHandler(eventType);
205
630
  }
206
- const httpResponse = await (0, import_core.executeHandlerPipeline)(resolved, httpRequest, options);
207
- return mapHttpResponseToResult(httpResponse);
631
+ return cachedHandler(event, context);
208
632
  }
209
633
  __name(handler, "handler");
210
634
  // Annotate the CommonJS export names for ESM import in node: