@celerity-sdk/core 0.3.1 → 0.5.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/index.js CHANGED
@@ -8,18 +8,24 @@ import "reflect-metadata";
8
8
  import "reflect-metadata";
9
9
 
10
10
  // src/metadata/constants.ts
11
- var CONTROLLER_METADATA = /* @__PURE__ */ Symbol("celerity:controller");
12
- var HTTP_METHOD_METADATA = /* @__PURE__ */ Symbol("celerity:http-method");
13
- var ROUTE_PATH_METADATA = /* @__PURE__ */ Symbol("celerity:route-path");
14
- var PARAM_METADATA = /* @__PURE__ */ Symbol("celerity:param");
15
- var GUARD_PROTECTEDBY_METADATA = /* @__PURE__ */ Symbol("celerity:guard:protectedBy");
16
- var GUARD_CUSTOM_METADATA = /* @__PURE__ */ Symbol("celerity:guard:custom");
17
- var LAYER_METADATA = /* @__PURE__ */ Symbol("celerity:layer");
18
- var MODULE_METADATA = /* @__PURE__ */ Symbol("celerity:module");
19
- var INJECTABLE_METADATA = /* @__PURE__ */ Symbol("celerity:injectable");
20
- var INJECT_METADATA = /* @__PURE__ */ Symbol("celerity:inject");
21
- var PUBLIC_METADATA = /* @__PURE__ */ Symbol("celerity:public");
22
- var CUSTOM_METADATA = /* @__PURE__ */ Symbol("celerity:custom-metadata");
11
+ import { INJECT_METADATA, USE_RESOURCE_METADATA } from "@celerity-sdk/common";
12
+ var CONTROLLER_METADATA = /* @__PURE__ */ Symbol.for("celerity:controller");
13
+ var HTTP_METHOD_METADATA = /* @__PURE__ */ Symbol.for("celerity:http-method");
14
+ var ROUTE_PATH_METADATA = /* @__PURE__ */ Symbol.for("celerity:route-path");
15
+ var PARAM_METADATA = /* @__PURE__ */ Symbol.for("celerity:param");
16
+ var GUARD_PROTECTEDBY_METADATA = /* @__PURE__ */ Symbol.for("celerity:guard:protectedBy");
17
+ var GUARD_CUSTOM_METADATA = /* @__PURE__ */ Symbol.for("celerity:guard:custom");
18
+ var LAYER_METADATA = /* @__PURE__ */ Symbol.for("celerity:layer");
19
+ var MODULE_METADATA = /* @__PURE__ */ Symbol.for("celerity:module");
20
+ var INJECTABLE_METADATA = /* @__PURE__ */ Symbol.for("celerity:injectable");
21
+ var PUBLIC_METADATA = /* @__PURE__ */ Symbol.for("celerity:public");
22
+ var CUSTOM_METADATA = /* @__PURE__ */ Symbol.for("celerity:custom-metadata");
23
+ var WEBSOCKET_CONTROLLER_METADATA = /* @__PURE__ */ Symbol.for("celerity:websocket-controller");
24
+ var WEBSOCKET_EVENT_METADATA = /* @__PURE__ */ Symbol.for("celerity:websocket-event");
25
+ var CONSUMER_METADATA = /* @__PURE__ */ Symbol.for("celerity:consumer");
26
+ var CONSUMER_HANDLER_METADATA = /* @__PURE__ */ Symbol.for("celerity:consumer-handler");
27
+ var SCHEDULE_HANDLER_METADATA = /* @__PURE__ */ Symbol.for("celerity:schedule-handler");
28
+ var INVOKE_METADATA = /* @__PURE__ */ Symbol.for("celerity:invoke");
23
29
 
24
30
  // src/decorators/controller.ts
25
31
  function Controller(prefix) {
@@ -114,6 +120,10 @@ function Auth() {
114
120
  return createParamDecorator("auth");
115
121
  }
116
122
  __name(Auth, "Auth");
123
+ function Token() {
124
+ return createParamDecorator("token");
125
+ }
126
+ __name(Token, "Token");
117
127
  function Req() {
118
128
  return createParamDecorator("request");
119
129
  }
@@ -153,6 +163,9 @@ import "reflect-metadata";
153
163
  function Guard(name) {
154
164
  return (target) => {
155
165
  Reflect.defineMetadata(GUARD_CUSTOM_METADATA, name, target);
166
+ if (!Reflect.hasOwnMetadata(INJECTABLE_METADATA, target)) {
167
+ Reflect.defineMetadata(INJECTABLE_METADATA, true, target);
168
+ }
156
169
  };
157
170
  }
158
171
  __name(Guard, "Guard");
@@ -207,6 +220,31 @@ function UseLayers(layers) {
207
220
  }
208
221
  __name(UseLayers, "UseLayers");
209
222
 
223
+ // src/decorators/resource.ts
224
+ import "reflect-metadata";
225
+ function UseResource(...resourceNames) {
226
+ return (target, propertyKey, _descriptor) => {
227
+ if (propertyKey) {
228
+ const existing = Reflect.getOwnMetadata(USE_RESOURCE_METADATA, target, propertyKey) ?? [];
229
+ Reflect.defineMetadata(USE_RESOURCE_METADATA, [
230
+ ...resourceNames,
231
+ ...existing
232
+ ], target, propertyKey);
233
+ } else {
234
+ const existing = Reflect.getOwnMetadata(USE_RESOURCE_METADATA, target) ?? [];
235
+ Reflect.defineMetadata(USE_RESOURCE_METADATA, [
236
+ ...resourceNames,
237
+ ...existing
238
+ ], target);
239
+ }
240
+ };
241
+ }
242
+ __name(UseResource, "UseResource");
243
+ function UseResources(resourceNames) {
244
+ return UseResource(...resourceNames);
245
+ }
246
+ __name(UseResources, "UseResources");
247
+
210
248
  // src/decorators/metadata.ts
211
249
  import "reflect-metadata";
212
250
  function SetMetadata(key, value) {
@@ -258,6 +296,237 @@ function Module(metadata) {
258
296
  }
259
297
  __name(Module, "Module");
260
298
 
299
+ // src/decorators/websocket.ts
300
+ import "reflect-metadata";
301
+ function WebSocketController() {
302
+ return (target) => {
303
+ Reflect.defineMetadata(WEBSOCKET_CONTROLLER_METADATA, true, target);
304
+ Reflect.defineMetadata(INJECTABLE_METADATA, true, target);
305
+ };
306
+ }
307
+ __name(WebSocketController, "WebSocketController");
308
+ function OnConnect() {
309
+ return (target, propertyKey, descriptor) => {
310
+ const meta = {
311
+ eventType: "connect",
312
+ route: "$connect"
313
+ };
314
+ Reflect.defineMetadata(WEBSOCKET_EVENT_METADATA, meta, target, propertyKey);
315
+ return descriptor;
316
+ };
317
+ }
318
+ __name(OnConnect, "OnConnect");
319
+ function OnMessage(route) {
320
+ return (target, propertyKey, descriptor) => {
321
+ const meta = {
322
+ eventType: "message",
323
+ route: route ?? "$default"
324
+ };
325
+ Reflect.defineMetadata(WEBSOCKET_EVENT_METADATA, meta, target, propertyKey);
326
+ return descriptor;
327
+ };
328
+ }
329
+ __name(OnMessage, "OnMessage");
330
+ function OnDisconnect() {
331
+ return (target, propertyKey, descriptor) => {
332
+ const meta = {
333
+ eventType: "disconnect",
334
+ route: "$disconnect"
335
+ };
336
+ Reflect.defineMetadata(WEBSOCKET_EVENT_METADATA, meta, target, propertyKey);
337
+ return descriptor;
338
+ };
339
+ }
340
+ __name(OnDisconnect, "OnDisconnect");
341
+
342
+ // src/decorators/websocket-params.ts
343
+ import "reflect-metadata";
344
+ function createWsParamDecorator(type, schema) {
345
+ return (target, propertyKey, parameterIndex) => {
346
+ if (!propertyKey) return;
347
+ const existing = Reflect.getOwnMetadata(PARAM_METADATA, target, propertyKey) ?? [];
348
+ const meta = {
349
+ index: parameterIndex,
350
+ type
351
+ };
352
+ if (schema) meta.schema = schema;
353
+ existing.push(meta);
354
+ Reflect.defineMetadata(PARAM_METADATA, existing, target, propertyKey);
355
+ };
356
+ }
357
+ __name(createWsParamDecorator, "createWsParamDecorator");
358
+ function ConnectionId() {
359
+ return createWsParamDecorator("connectionId");
360
+ }
361
+ __name(ConnectionId, "ConnectionId");
362
+ function MessageBody(schema) {
363
+ return createWsParamDecorator("messageBody", schema);
364
+ }
365
+ __name(MessageBody, "MessageBody");
366
+ function MessageId() {
367
+ return createWsParamDecorator("messageId");
368
+ }
369
+ __name(MessageId, "MessageId");
370
+ function RequestContext() {
371
+ return createWsParamDecorator("requestContext");
372
+ }
373
+ __name(RequestContext, "RequestContext");
374
+ function EventType() {
375
+ return createWsParamDecorator("eventType");
376
+ }
377
+ __name(EventType, "EventType");
378
+
379
+ // src/decorators/consumer.ts
380
+ import "reflect-metadata";
381
+ function Consumer(source) {
382
+ return (target) => {
383
+ const meta = {};
384
+ if (source !== void 0) meta.source = source;
385
+ Reflect.defineMetadata(CONSUMER_METADATA, meta, target);
386
+ Reflect.defineMetadata(INJECTABLE_METADATA, true, target);
387
+ };
388
+ }
389
+ __name(Consumer, "Consumer");
390
+ function MessageHandler(route) {
391
+ return (target, propertyKey) => {
392
+ const meta = {};
393
+ if (route !== void 0) meta.route = route;
394
+ Reflect.defineMetadata(CONSUMER_HANDLER_METADATA, meta, target, propertyKey);
395
+ };
396
+ }
397
+ __name(MessageHandler, "MessageHandler");
398
+
399
+ // src/decorators/consumer-params.ts
400
+ import "reflect-metadata";
401
+ function createConsumerParamDecorator(type, schema) {
402
+ return (target, propertyKey, parameterIndex) => {
403
+ if (!propertyKey) return;
404
+ const existing = Reflect.getOwnMetadata(PARAM_METADATA, target, propertyKey) ?? [];
405
+ const meta = {
406
+ index: parameterIndex,
407
+ type
408
+ };
409
+ if (schema) meta.schema = schema;
410
+ existing.push(meta);
411
+ Reflect.defineMetadata(PARAM_METADATA, existing, target, propertyKey);
412
+ };
413
+ }
414
+ __name(createConsumerParamDecorator, "createConsumerParamDecorator");
415
+ function Messages(schema) {
416
+ return createConsumerParamDecorator("messages", schema);
417
+ }
418
+ __name(Messages, "Messages");
419
+ function EventInput() {
420
+ return createConsumerParamDecorator("consumerEvent");
421
+ }
422
+ __name(EventInput, "EventInput");
423
+ function Vendor() {
424
+ return createConsumerParamDecorator("consumerVendor");
425
+ }
426
+ __name(Vendor, "Vendor");
427
+ function ConsumerTraceContext() {
428
+ return createConsumerParamDecorator("consumerTraceContext");
429
+ }
430
+ __name(ConsumerTraceContext, "ConsumerTraceContext");
431
+
432
+ // src/decorators/schedule.ts
433
+ import "reflect-metadata";
434
+ function isScheduleExpression(value) {
435
+ return value.startsWith("rate(") || value.startsWith("cron(");
436
+ }
437
+ __name(isScheduleExpression, "isScheduleExpression");
438
+ function parseScheduleArg(arg) {
439
+ if (typeof arg === "string") {
440
+ return isScheduleExpression(arg) ? {
441
+ schedule: arg
442
+ } : {
443
+ source: arg
444
+ };
445
+ }
446
+ const meta = {};
447
+ if (arg.source !== void 0) meta.source = arg.source;
448
+ if (arg.schedule !== void 0) meta.schedule = arg.schedule;
449
+ return meta;
450
+ }
451
+ __name(parseScheduleArg, "parseScheduleArg");
452
+ function ScheduleHandler(arg) {
453
+ return (target, propertyKey) => {
454
+ const meta = arg ? parseScheduleArg(arg) : {};
455
+ Reflect.defineMetadata(SCHEDULE_HANDLER_METADATA, meta, target, propertyKey);
456
+ };
457
+ }
458
+ __name(ScheduleHandler, "ScheduleHandler");
459
+
460
+ // src/decorators/schedule-params.ts
461
+ import "reflect-metadata";
462
+ function createScheduleParamDecorator(type, schema) {
463
+ return (target, propertyKey, parameterIndex) => {
464
+ if (!propertyKey) return;
465
+ const existing = Reflect.getOwnMetadata(PARAM_METADATA, target, propertyKey) ?? [];
466
+ const meta = {
467
+ index: parameterIndex,
468
+ type
469
+ };
470
+ if (schema) meta.schema = schema;
471
+ existing.push(meta);
472
+ Reflect.defineMetadata(PARAM_METADATA, existing, target, propertyKey);
473
+ };
474
+ }
475
+ __name(createScheduleParamDecorator, "createScheduleParamDecorator");
476
+ function ScheduleInput(schema) {
477
+ return createScheduleParamDecorator("scheduleInput", schema);
478
+ }
479
+ __name(ScheduleInput, "ScheduleInput");
480
+ function ScheduleId() {
481
+ return createScheduleParamDecorator("scheduleId");
482
+ }
483
+ __name(ScheduleId, "ScheduleId");
484
+ function ScheduleExpression() {
485
+ return createScheduleParamDecorator("scheduleExpression");
486
+ }
487
+ __name(ScheduleExpression, "ScheduleExpression");
488
+ function ScheduleEventInput() {
489
+ return createScheduleParamDecorator("scheduleEvent");
490
+ }
491
+ __name(ScheduleEventInput, "ScheduleEventInput");
492
+
493
+ // src/decorators/invoke.ts
494
+ import "reflect-metadata";
495
+ function Invoke(name) {
496
+ return (target, propertyKey) => {
497
+ const meta = {
498
+ name
499
+ };
500
+ Reflect.defineMetadata(INVOKE_METADATA, meta, target, propertyKey);
501
+ };
502
+ }
503
+ __name(Invoke, "Invoke");
504
+
505
+ // src/decorators/invoke-params.ts
506
+ import "reflect-metadata";
507
+ function createInvokeParamDecorator(type, schema) {
508
+ return (target, propertyKey, parameterIndex) => {
509
+ if (!propertyKey) return;
510
+ const existing = Reflect.getOwnMetadata(PARAM_METADATA, target, propertyKey) ?? [];
511
+ const meta = {
512
+ index: parameterIndex,
513
+ type
514
+ };
515
+ if (schema) meta.schema = schema;
516
+ existing.push(meta);
517
+ Reflect.defineMetadata(PARAM_METADATA, existing, target, propertyKey);
518
+ };
519
+ }
520
+ __name(createInvokeParamDecorator, "createInvokeParamDecorator");
521
+ function Payload(schema) {
522
+ return createInvokeParamDecorator("payload", schema);
523
+ }
524
+ __name(Payload, "Payload");
525
+ function InvokeContext() {
526
+ return createInvokeParamDecorator("invokeContext");
527
+ }
528
+ __name(InvokeContext, "InvokeContext");
529
+
261
530
  // src/errors/http-exception.ts
262
531
  var HttpException = class extends Error {
263
532
  static {
@@ -407,15 +676,48 @@ var GatewayTimeoutException = class extends HttpException {
407
676
  };
408
677
 
409
678
  // src/layers/validate.ts
679
+ function inferMode(schemas) {
680
+ if (schemas.consumerMessage) return "consumer";
681
+ if (schemas.scheduleInput) return "schedule";
682
+ if (schemas.customPayload) return "custom";
683
+ if (schemas.wsMessageBody) return "websocket";
684
+ return "http";
685
+ }
686
+ __name(inferMode, "inferMode");
410
687
  var ValidationLayer = class ValidationLayer2 {
411
688
  static {
412
689
  __name(this, "ValidationLayer");
413
690
  }
414
691
  schemas;
692
+ mode;
415
693
  constructor(schemas) {
416
694
  this.schemas = schemas;
695
+ this.mode = inferMode(schemas);
696
+ }
697
+ supports(handlerType) {
698
+ return handlerType === this.mode;
417
699
  }
418
700
  async handle(context, next) {
701
+ switch (this.mode) {
702
+ case "http":
703
+ this.validateHttp(context);
704
+ break;
705
+ case "websocket":
706
+ this.validateWebSocket(context);
707
+ break;
708
+ case "consumer":
709
+ this.validateConsumer(context);
710
+ break;
711
+ case "schedule":
712
+ this.validateSchedule(context);
713
+ break;
714
+ case "custom":
715
+ this.validateCustom(context);
716
+ break;
717
+ }
718
+ return next();
719
+ }
720
+ validateHttp(context) {
419
721
  const { request } = context;
420
722
  if (this.schemas.body && request.textBody) {
421
723
  try {
@@ -446,7 +748,49 @@ var ValidationLayer = class ValidationLayer2 {
446
748
  throw new BadRequestException("Headers validation failed", formatError(error));
447
749
  }
448
750
  }
449
- return next();
751
+ }
752
+ validateWebSocket(context) {
753
+ const schema = this.schemas.wsMessageBody;
754
+ if (!schema) return;
755
+ const body = context.message.jsonBody;
756
+ if (body === void 0) return;
757
+ context.metadata.set("validatedMessageBody", schema.parse(body));
758
+ }
759
+ validateConsumer(context) {
760
+ const schema = this.schemas.consumerMessage;
761
+ if (!schema) return;
762
+ const validated = [];
763
+ const failures = [];
764
+ for (const msg of context.event.messages) {
765
+ try {
766
+ const parsed = JSON.parse(msg.body);
767
+ const result = schema.parse(parsed);
768
+ validated.push({
769
+ ...msg,
770
+ parsedBody: result
771
+ });
772
+ } catch (err) {
773
+ failures.push({
774
+ messageId: msg.messageId,
775
+ errorMessage: err instanceof Error ? err.message : String(err)
776
+ });
777
+ }
778
+ }
779
+ context.metadata.set("validatedMessages", validated);
780
+ if (failures.length > 0) {
781
+ context.metadata.set("validationFailures", failures);
782
+ }
783
+ }
784
+ validateSchedule(context) {
785
+ const schema = this.schemas.scheduleInput;
786
+ if (!schema) return;
787
+ context.metadata.set("validatedInput", schema.parse(context.event.input));
788
+ }
789
+ validateCustom(context) {
790
+ const schema = this.schemas.customPayload;
791
+ if (!schema) return;
792
+ const raw = context.metadata.get("rawPayload");
793
+ context.metadata.set("validatedPayload", schema.parse(raw));
450
794
  }
451
795
  };
452
796
  function formatError(error) {
@@ -467,9 +811,9 @@ __name(validate, "validate");
467
811
  // src/layers/pipeline.ts
468
812
  import createDebug from "debug";
469
813
  var debug = createDebug("celerity:core:layers");
470
- function runLayerPipeline(layers, context, handler) {
471
- const resolved = layers.map((layer) => typeof layer === "function" ? new layer() : layer);
472
- debug("runLayerPipeline: %d layers", resolved.length);
814
+ function runLayerPipeline(layers, context, handler, handlerType) {
815
+ const resolved = layers.map((layer) => typeof layer === "function" ? new layer() : layer).filter((layer) => !handlerType || !layer.supports || layer.supports(handlerType));
816
+ debug("runLayerPipeline: %d layers (handlerType=%s)", resolved.length, handlerType ?? "all");
473
817
  let index = -1;
474
818
  function dispatch(i) {
475
819
  if (i <= index) {
@@ -489,7 +833,33 @@ function runLayerPipeline(layers, context, handler) {
489
833
  __name(runLayerPipeline, "runLayerPipeline");
490
834
 
491
835
  // src/layers/system.ts
492
- import { ConfigLayer } from "@celerity-sdk/config";
836
+ import { ConfigLayer, captureResourceLinks, getResourceTypes } from "@celerity-sdk/config";
837
+ var RESOURCE_LAYER_MAP = {
838
+ datastore: {
839
+ pkg: "@celerity-sdk/datastore",
840
+ className: "DatastoreLayer"
841
+ },
842
+ bucket: {
843
+ pkg: "@celerity-sdk/bucket",
844
+ className: "ObjectStorageLayer"
845
+ },
846
+ queue: {
847
+ pkg: "@celerity-sdk/queue",
848
+ className: "QueueLayer"
849
+ },
850
+ topic: {
851
+ pkg: "@celerity-sdk/topic",
852
+ className: "TopicLayer"
853
+ },
854
+ cache: {
855
+ pkg: "@celerity-sdk/cache",
856
+ className: "CacheLayer"
857
+ },
858
+ sqlDatabase: {
859
+ pkg: "@celerity-sdk/sql-database",
860
+ className: "SqlDatabaseLayer"
861
+ }
862
+ };
493
863
  async function createDefaultSystemLayers() {
494
864
  const layers = [];
495
865
  try {
@@ -500,6 +870,19 @@ async function createDefaultSystemLayers() {
500
870
  } catch {
501
871
  }
502
872
  layers.push(new ConfigLayer());
873
+ const links = captureResourceLinks();
874
+ const resourceTypes = getResourceTypes(links);
875
+ for (const type of resourceTypes) {
876
+ const entry = RESOURCE_LAYER_MAP[type];
877
+ if (!entry) continue;
878
+ try {
879
+ const pkg = entry.pkg;
880
+ const mod = await import(pkg);
881
+ const LayerClass = mod[entry.className];
882
+ layers.push(new LayerClass());
883
+ } catch {
884
+ }
885
+ }
503
886
  return layers;
504
887
  }
505
888
  __name(createDefaultSystemLayers, "createDefaultSystemLayers");
@@ -843,27 +1226,123 @@ var APP_CONFIG = /* @__PURE__ */ Symbol("celerity:app-config");
843
1226
  var RUNTIME_APP = /* @__PURE__ */ Symbol("celerity:runtime-app");
844
1227
 
845
1228
  // src/application/factory.ts
846
- import createDebug8 from "debug";
1229
+ import createDebug17 from "debug";
847
1230
 
848
1231
  // src/bootstrap/bootstrap.ts
849
1232
  import "reflect-metadata";
850
- import createDebug5 from "debug";
1233
+ import createDebug10 from "debug";
851
1234
 
852
1235
  // src/handlers/registry.ts
853
- import "reflect-metadata";
854
- import createDebug4 from "debug";
855
- import { joinHandlerPath } from "@celerity-sdk/common";
1236
+ import createDebug3 from "debug";
1237
+
1238
+ // src/handlers/routing.ts
1239
+ function routingKeyOf(handler) {
1240
+ switch (handler.type) {
1241
+ case "http":
1242
+ return `${handler.method} ${handler.path}`;
1243
+ case "websocket":
1244
+ return handler.route;
1245
+ case "consumer":
1246
+ return handler.handlerTag;
1247
+ case "schedule":
1248
+ return handler.handlerTag;
1249
+ case "custom":
1250
+ return handler.name;
1251
+ }
1252
+ }
1253
+ __name(routingKeyOf, "routingKeyOf");
1254
+
1255
+ // src/handlers/registry.ts
1256
+ var debug3 = createDebug3("celerity:core:registry");
1257
+ var HandlerRegistry = class {
1258
+ static {
1259
+ __name(this, "HandlerRegistry");
1260
+ }
1261
+ byType = /* @__PURE__ */ new Map();
1262
+ exactLookup = /* @__PURE__ */ new Map();
1263
+ byId = /* @__PURE__ */ new Map();
1264
+ guards = /* @__PURE__ */ new Map();
1265
+ register(handler) {
1266
+ const list = this.byType.get(handler.type) ?? [];
1267
+ list.push(handler);
1268
+ this.byType.set(handler.type, list);
1269
+ if (handler.type !== "http") {
1270
+ this.exactLookup.set(`${handler.type}::${routingKeyOf(handler)}`, handler);
1271
+ }
1272
+ if (handler.id) {
1273
+ this.byId.set(handler.id, handler);
1274
+ }
1275
+ }
1276
+ getHandler(type, routingKey) {
1277
+ if (type === "http") return this.findHttpHandler(routingKey);
1278
+ const found = this.exactLookup.get(`${type}::${routingKey}`);
1279
+ debug3("getHandler %s %s \u2192 %s", type, routingKey, found ? "matched" : "not found");
1280
+ return found;
1281
+ }
1282
+ getHandlerById(type, id) {
1283
+ const handler = this.byId.get(id);
1284
+ if (handler && handler.type === type) {
1285
+ return handler;
1286
+ }
1287
+ debug3("getHandlerById %s %s \u2192 not found", type, id);
1288
+ return void 0;
1289
+ }
1290
+ getHandlersByType(type) {
1291
+ return this.byType.get(type) ?? [];
1292
+ }
1293
+ getAllHandlers() {
1294
+ const result = [];
1295
+ for (const list of this.byType.values()) result.push(...list);
1296
+ return result;
1297
+ }
1298
+ registerGuard(guard) {
1299
+ debug3("registerGuard: %s", guard.name);
1300
+ this.guards.set(guard.name, guard);
1301
+ }
1302
+ getGuard(name) {
1303
+ const found = this.guards.get(name);
1304
+ debug3("getGuard %s \u2192 %s", name, found ? "matched" : "not found");
1305
+ return found;
1306
+ }
1307
+ getAllGuards() {
1308
+ return [
1309
+ ...this.guards.values()
1310
+ ];
1311
+ }
1312
+ /**
1313
+ * HTTP routing uses path-pattern matching: `"GET /items/{id}"` matches `"GET /items/42"`.
1314
+ * The routing key format is `"METHOD path"` (e.g., `"GET /items/{id}"`).
1315
+ */
1316
+ findHttpHandler(routingKey) {
1317
+ const spaceIdx = routingKey.indexOf(" ");
1318
+ if (spaceIdx < 0) return void 0;
1319
+ const method = routingKey.slice(0, spaceIdx);
1320
+ const path = routingKey.slice(spaceIdx + 1);
1321
+ const httpHandlers = this.byType.get("http") ?? [];
1322
+ const found = httpHandlers.find((h) => h.path !== void 0 && h.method !== void 0 && h.method === method && matchRoute(h.path, path));
1323
+ debug3("getHandler http %s \u2192 %s", routingKey, found ? "matched" : "not found");
1324
+ return found;
1325
+ }
1326
+ };
1327
+ function matchRoute(pattern, actual) {
1328
+ const patternParts = pattern.split("/").filter(Boolean);
1329
+ const actualParts = actual.split("/").filter(Boolean);
1330
+ if (patternParts.length !== actualParts.length) return false;
1331
+ return patternParts.every((part, i) => part.startsWith("{") || part === actualParts[i]);
1332
+ }
1333
+ __name(matchRoute, "matchRoute");
856
1334
 
857
1335
  // src/bootstrap/module-graph.ts
858
1336
  import "reflect-metadata";
859
- import createDebug3 from "debug";
860
- var debug3 = createDebug3("celerity:core:bootstrap");
1337
+ import createDebug4 from "debug";
1338
+ import { isResourceLayerToken } from "@celerity-sdk/common";
1339
+ var debug4 = createDebug4("celerity:core:bootstrap");
861
1340
  function buildModuleGraph(rootModule) {
862
1341
  const graph = /* @__PURE__ */ new Map();
863
1342
  const resolving = /* @__PURE__ */ new Set();
864
1343
  function walk(moduleClass, importChain) {
865
1344
  if (graph.has(moduleClass)) {
866
- debug3("walk %s \u2192 already visited", moduleClass.name);
1345
+ debug4("walk %s \u2192 already visited", moduleClass.name);
867
1346
  return;
868
1347
  }
869
1348
  if (resolving.has(moduleClass)) {
@@ -884,6 +1363,7 @@ function buildModuleGraph(rootModule) {
884
1363
  imports: [],
885
1364
  controllers: [],
886
1365
  functionHandlers: [],
1366
+ guards: [],
887
1367
  providers: []
888
1368
  });
889
1369
  return;
@@ -909,9 +1389,15 @@ function buildModuleGraph(rootModule) {
909
1389
  for (const controller of controllers) {
910
1390
  ownTokens.add(controller);
911
1391
  }
1392
+ const guards = metadata.guards ?? [];
1393
+ for (const guard of guards) {
1394
+ if (typeof guard === "function") {
1395
+ ownTokens.add(guard);
1396
+ }
1397
+ }
912
1398
  const exportTokens = new Set(metadata.exports ?? []);
913
1399
  resolving.delete(moduleClass);
914
- debug3("walk %s: %d providers, %d controllers, %d imports", moduleClass.name, providers.length, controllers.length, imports.length);
1400
+ debug4("walk %s: %d providers, %d controllers, %d guards, %d imports", moduleClass.name, providers.length, controllers.length, guards.length, imports.length);
915
1401
  graph.set(moduleClass, {
916
1402
  moduleClass,
917
1403
  ownTokens,
@@ -919,6 +1405,7 @@ function buildModuleGraph(rootModule) {
919
1405
  imports,
920
1406
  controllers,
921
1407
  functionHandlers: metadata.functionHandlers ?? [],
1408
+ guards,
922
1409
  providers
923
1410
  });
924
1411
  }
@@ -942,6 +1429,11 @@ function registerModuleGraph(graph, container) {
942
1429
  container.registerClass(controller);
943
1430
  }
944
1431
  }
1432
+ for (const guard of node.guards) {
1433
+ if (typeof guard === "function" && !container.has(guard)) {
1434
+ container.registerClass(guard);
1435
+ }
1436
+ }
945
1437
  }
946
1438
  }
947
1439
  __name(registerModuleGraph, "registerModuleGraph");
@@ -988,8 +1480,14 @@ function validateModuleGraph(graph, container) {
988
1480
  const depTokens = getClassDependencyTokens(controller);
989
1481
  checkDependencies(controller, depTokens, visibleTokens, node.moduleClass, graph, container, diagnostics);
990
1482
  }
1483
+ for (const guard of node.guards) {
1484
+ if (typeof guard === "function") {
1485
+ const depTokens = getClassDependencyTokens(guard);
1486
+ checkDependencies(guard, depTokens, visibleTokens, node.moduleClass, graph, container, diagnostics);
1487
+ }
1488
+ }
991
1489
  }
992
- debug3("validateModuleGraph: %d modules, %d diagnostics", graph.size, diagnostics.length);
1490
+ debug4("validateModuleGraph: %d modules, %d diagnostics", graph.size, diagnostics.length);
993
1491
  if (diagnostics.length > 0) {
994
1492
  const details = diagnostics.map((d) => ` ${d.message}`).join("\n");
995
1493
  throw new Error(`Module validation errors:
@@ -1026,6 +1524,7 @@ function checkDependencies(consumer, depTokens, visibleTokens, moduleClass, grap
1026
1524
  checkDependencies(dep, adoptedDeps, visibleTokens, moduleClass, graph, container, diagnostics);
1027
1525
  continue;
1028
1526
  }
1527
+ if (isResourceLayerToken(dep)) continue;
1029
1528
  diagnostics.push({
1030
1529
  type: "missing_dependency",
1031
1530
  message: `${tokenToString(consumer)} in ${moduleClass.name} requires ${tokenToString(dep)} \u2014 no provider registered. Ensure the module providing it is included in your module's "imports" array, or register a provider for it directly.`
@@ -1043,131 +1542,163 @@ function findTokenOwner(token, graph) {
1043
1542
  }
1044
1543
  __name(findTokenOwner, "findTokenOwner");
1045
1544
 
1046
- // src/handlers/registry.ts
1047
- var debug4 = createDebug4("celerity:core:registry");
1048
- var HandlerRegistry = class {
1049
- static {
1050
- __name(this, "HandlerRegistry");
1051
- }
1052
- handlers = [];
1053
- getHandler(path, method) {
1054
- const found = this.handlers.find((h) => h.path !== void 0 && h.method !== void 0 && matchRoute(h.path, path) && h.method === method);
1055
- debug4("getHandler %s %s \u2192 %s", method, path, found ? "matched" : "not found");
1056
- return found;
1057
- }
1058
- getHandlerById(id) {
1059
- const found = this.handlers.find((h) => h.id !== void 0 && h.id === id);
1060
- debug4("getHandlerById %s \u2192 %s", id, found ? "matched" : "not found");
1061
- return found;
1062
- }
1063
- getAllHandlers() {
1064
- return [
1065
- ...this.handlers
1066
- ];
1067
- }
1068
- async populateFromGraph(graph, container) {
1069
- for (const [, node] of graph) {
1070
- for (const controllerClass of node.controllers) {
1071
- await this.registerClassHandler(controllerClass, container);
1072
- }
1073
- for (const fnHandler of node.functionHandlers) {
1074
- this.registerFunctionHandler(fnHandler);
1075
- }
1545
+ // src/handlers/scanners/http.ts
1546
+ import "reflect-metadata";
1547
+ import createDebug5 from "debug";
1548
+ import { joinHandlerPath } from "@celerity-sdk/common";
1549
+ var debug5 = createDebug5("celerity:core:scanner:http");
1550
+ async function scanHttpHandlers(graph, container, registry) {
1551
+ for (const [, node] of graph) {
1552
+ for (const controllerClass of node.controllers) {
1553
+ await scanClassHandler(controllerClass, container, registry);
1554
+ }
1555
+ for (const fnHandler of node.functionHandlers) {
1556
+ scanFunctionHandler(fnHandler, registry);
1076
1557
  }
1077
1558
  }
1078
- async scanModule(moduleClass, container) {
1079
- const graph = buildModuleGraph(moduleClass);
1080
- registerModuleGraph(graph, container);
1081
- await this.populateFromGraph(graph, container);
1082
- }
1083
- async registerClassHandler(controllerClass, container) {
1084
- const controllerMeta = Reflect.getOwnMetadata(CONTROLLER_METADATA, controllerClass);
1085
- if (!controllerMeta) return;
1086
- const instance = await container.resolve(controllerClass);
1087
- const prototype = Object.getPrototypeOf(instance);
1088
- const methods = Object.getOwnPropertyNames(prototype).filter((name) => name !== "constructor");
1089
- const classProtectedBy = Reflect.getOwnMetadata(GUARD_PROTECTEDBY_METADATA, controllerClass) ?? [];
1090
- const classLayers = Reflect.getOwnMetadata(LAYER_METADATA, controllerClass) ?? [];
1091
- const classCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, controllerClass) ?? {};
1092
- for (const methodName of methods) {
1093
- const method = Reflect.getOwnMetadata(HTTP_METHOD_METADATA, prototype, methodName);
1094
- if (!method) continue;
1095
- const routePath = Reflect.getOwnMetadata(ROUTE_PATH_METADATA, prototype, methodName) ?? "/";
1096
- const fullPath = joinHandlerPath(controllerMeta.prefix ?? "", routePath);
1097
- const methodProtectedBy = Reflect.getOwnMetadata(GUARD_PROTECTEDBY_METADATA, prototype, methodName) ?? [];
1098
- const methodLayers = Reflect.getOwnMetadata(LAYER_METADATA, prototype, methodName) ?? [];
1099
- const paramMetadata = Reflect.getOwnMetadata(PARAM_METADATA, prototype, methodName) ?? [];
1100
- const isPublic = Reflect.getOwnMetadata(PUBLIC_METADATA, prototype, methodName) === true;
1101
- const methodCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, prototype, methodName) ?? {};
1102
- const descriptor = Object.getOwnPropertyDescriptor(prototype, methodName);
1103
- if (!descriptor?.value || typeof descriptor.value !== "function") continue;
1104
- const layers = [
1105
- ...classLayers,
1106
- ...methodLayers
1107
- ];
1108
- const validationSchemas = buildValidationSchemasFromParams(paramMetadata);
1109
- if (validationSchemas) {
1110
- layers.unshift(validate(validationSchemas));
1559
+ }
1560
+ __name(scanHttpHandlers, "scanHttpHandlers");
1561
+ async function scanHttpGuards(graph, container, registry) {
1562
+ for (const [, node] of graph) {
1563
+ for (const guard of node.guards) {
1564
+ if (typeof guard === "function") {
1565
+ await scanClassGuard(guard, container, registry);
1566
+ } else {
1567
+ scanFunctionGuard(guard, registry);
1111
1568
  }
1112
- debug4("registerClassHandler: %s %s (%s.%s)", method, fullPath, controllerClass.name, methodName);
1113
- this.handlers.push({
1114
- path: fullPath,
1115
- method,
1116
- protectedBy: [
1117
- ...classProtectedBy,
1118
- ...methodProtectedBy
1119
- ],
1120
- layers,
1121
- isPublic,
1122
- paramMetadata,
1123
- customMetadata: {
1124
- ...classCustomMetadata,
1125
- ...methodCustomMetadata
1126
- },
1127
- handlerFn: descriptor.value,
1128
- handlerInstance: instance
1129
- });
1130
1569
  }
1131
1570
  }
1132
- registerFunctionHandler(definition) {
1133
- if (definition.type !== "http") return;
1134
- const meta = definition.metadata;
1571
+ }
1572
+ __name(scanHttpGuards, "scanHttpGuards");
1573
+ async function scanModule(moduleClass, container, registry) {
1574
+ const graph = buildModuleGraph(moduleClass);
1575
+ registerModuleGraph(graph, container);
1576
+ await scanHttpHandlers(graph, container, registry);
1577
+ await scanHttpGuards(graph, container, registry);
1578
+ }
1579
+ __name(scanModule, "scanModule");
1580
+ async function scanClassHandler(controllerClass, container, registry) {
1581
+ const controllerMeta = Reflect.getOwnMetadata(CONTROLLER_METADATA, controllerClass);
1582
+ if (!controllerMeta) return;
1583
+ const prototype = controllerClass.prototype;
1584
+ const methods = Object.getOwnPropertyNames(prototype).filter((name) => name !== "constructor");
1585
+ const classProtectedBy = Reflect.getOwnMetadata(GUARD_PROTECTEDBY_METADATA, controllerClass) ?? [];
1586
+ const classLayers = Reflect.getOwnMetadata(LAYER_METADATA, controllerClass) ?? [];
1587
+ const classCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, controllerClass) ?? {};
1588
+ for (const methodName of methods) {
1589
+ const method = Reflect.getOwnMetadata(HTTP_METHOD_METADATA, prototype, methodName);
1590
+ if (!method) continue;
1591
+ const routePath = Reflect.getOwnMetadata(ROUTE_PATH_METADATA, prototype, methodName) ?? "/";
1592
+ const fullPath = joinHandlerPath(controllerMeta.prefix ?? "", routePath);
1593
+ const methodProtectedBy = Reflect.getOwnMetadata(GUARD_PROTECTEDBY_METADATA, prototype, methodName) ?? [];
1594
+ const methodLayers = Reflect.getOwnMetadata(LAYER_METADATA, prototype, methodName) ?? [];
1595
+ const paramMetadata = Reflect.getOwnMetadata(PARAM_METADATA, prototype, methodName) ?? [];
1596
+ const isPublic = Reflect.getOwnMetadata(PUBLIC_METADATA, prototype, methodName) === true;
1597
+ const methodCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, prototype, methodName) ?? {};
1598
+ const descriptor = Object.getOwnPropertyDescriptor(prototype, methodName);
1599
+ if (!descriptor?.value || typeof descriptor.value !== "function") continue;
1135
1600
  const layers = [
1136
- ...meta.layers ?? []
1601
+ ...classLayers,
1602
+ ...methodLayers
1137
1603
  ];
1138
- if (meta.schema) {
1139
- const schemas = {};
1140
- if (meta.schema.body) schemas.body = meta.schema.body;
1141
- if (meta.schema.query) schemas.query = meta.schema.query;
1142
- if (meta.schema.params) schemas.params = meta.schema.params;
1143
- if (meta.schema.headers) schemas.headers = meta.schema.headers;
1144
- if (Object.keys(schemas).length > 0) {
1145
- layers.unshift(validate(schemas));
1146
- }
1147
- }
1148
- debug4("registerFunctionHandler: %s", definition.id ?? (meta.method && meta.path ? `${meta.method} ${meta.path}` : "(no route)"));
1149
- this.handlers.push({
1150
- id: definition.id,
1151
- path: meta.path,
1152
- method: meta.method,
1153
- protectedBy: [],
1604
+ const validationSchemas = buildValidationSchemasFromParams(paramMetadata);
1605
+ if (validationSchemas) {
1606
+ layers.unshift(validate(validationSchemas));
1607
+ }
1608
+ debug5("scanClassHandler: %s %s (%s.%s)", method, fullPath, controllerClass.name, methodName);
1609
+ registry.register({
1610
+ type: "http",
1611
+ path: fullPath,
1612
+ method,
1613
+ protectedBy: [
1614
+ ...classProtectedBy,
1615
+ ...methodProtectedBy
1616
+ ],
1154
1617
  layers,
1155
- isPublic: false,
1156
- paramMetadata: [],
1157
- customMetadata: meta.customMetadata ?? {},
1158
- handlerFn: definition.handler,
1159
- isFunctionHandler: true,
1160
- injectTokens: meta.inject ?? []
1618
+ isPublic,
1619
+ paramMetadata,
1620
+ customMetadata: {
1621
+ ...classCustomMetadata,
1622
+ ...methodCustomMetadata
1623
+ },
1624
+ handlerFn: descriptor.value,
1625
+ controllerClass
1161
1626
  });
1162
1627
  }
1163
- };
1164
- function matchRoute(pattern, actual) {
1165
- const patternParts = pattern.split("/").filter(Boolean);
1166
- const actualParts = actual.split("/").filter(Boolean);
1167
- if (patternParts.length !== actualParts.length) return false;
1168
- return patternParts.every((part, i) => part.startsWith("{") || part === actualParts[i]);
1169
1628
  }
1170
- __name(matchRoute, "matchRoute");
1629
+ __name(scanClassHandler, "scanClassHandler");
1630
+ function scanFunctionHandler(definition, registry) {
1631
+ if (definition.type !== "http") return;
1632
+ const meta = definition.metadata;
1633
+ const layers = [
1634
+ ...meta.layers ?? []
1635
+ ];
1636
+ if (meta.schema) {
1637
+ const schemas = {};
1638
+ if (meta.schema.body) schemas.body = meta.schema.body;
1639
+ if (meta.schema.query) schemas.query = meta.schema.query;
1640
+ if (meta.schema.params) schemas.params = meta.schema.params;
1641
+ if (meta.schema.headers) schemas.headers = meta.schema.headers;
1642
+ if (Object.keys(schemas).length > 0) {
1643
+ layers.unshift(validate(schemas));
1644
+ }
1645
+ }
1646
+ debug5("scanFunctionHandler: %s", definition.id ?? (meta.method && meta.path ? `${meta.method} ${meta.path}` : "(no route)"));
1647
+ registry.register({
1648
+ type: "http",
1649
+ id: definition.id,
1650
+ path: meta.path,
1651
+ method: meta.method,
1652
+ protectedBy: [],
1653
+ layers,
1654
+ isPublic: false,
1655
+ paramMetadata: [],
1656
+ customMetadata: meta.customMetadata ?? {},
1657
+ handlerFn: definition.handler,
1658
+ isFunctionHandler: true,
1659
+ injectTokens: meta.inject ?? []
1660
+ });
1661
+ }
1662
+ __name(scanFunctionHandler, "scanFunctionHandler");
1663
+ async function scanClassGuard(guardClass, container, registry) {
1664
+ const guardName = Reflect.getOwnMetadata(GUARD_CUSTOM_METADATA, guardClass);
1665
+ if (!guardName) return;
1666
+ const prototype = guardClass.prototype;
1667
+ const descriptor = Object.getOwnPropertyDescriptor(prototype, "check");
1668
+ if (!descriptor?.value || typeof descriptor.value !== "function") {
1669
+ debug5("scanClassGuard: %s has no check() method, skipping", guardClass.name);
1670
+ return;
1671
+ }
1672
+ const paramMetadata = Reflect.getOwnMetadata(PARAM_METADATA, prototype, "check") ?? [];
1673
+ const customMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, guardClass) ?? {};
1674
+ debug5("scanClassGuard: %s (name=%s)", guardClass.name, guardName);
1675
+ registry.registerGuard({
1676
+ name: guardName,
1677
+ handlerFn: descriptor.value,
1678
+ guardClass,
1679
+ paramMetadata,
1680
+ customMetadata
1681
+ });
1682
+ }
1683
+ __name(scanClassGuard, "scanClassGuard");
1684
+ function scanFunctionGuard(definition, registry) {
1685
+ const name = definition.name;
1686
+ if (!name) {
1687
+ debug5("scanFunctionGuard: no name, skipping");
1688
+ return;
1689
+ }
1690
+ const meta = definition.metadata ?? {};
1691
+ debug5("scanFunctionGuard: %s", name);
1692
+ registry.registerGuard({
1693
+ name,
1694
+ handlerFn: definition.handler,
1695
+ customMetadata: meta.customMetadata ?? {},
1696
+ paramMetadata: [],
1697
+ isFunctionGuard: true,
1698
+ injectTokens: meta.inject ?? []
1699
+ });
1700
+ }
1701
+ __name(scanFunctionGuard, "scanFunctionGuard");
1171
1702
  var PARAM_TYPE_TO_SCHEMA_KEY = {
1172
1703
  body: "body",
1173
1704
  query: "query",
@@ -1229,26 +1760,377 @@ function composeKeySchemas(keySchemas) {
1229
1760
  }
1230
1761
  __name(composeKeySchemas, "composeKeySchemas");
1231
1762
 
1232
- // src/bootstrap/bootstrap.ts
1233
- var debug5 = createDebug5("celerity:core:bootstrap");
1234
- async function bootstrap(rootModule) {
1235
- debug5("bootstrap: starting from %s", rootModule.name);
1236
- const container = new Container();
1237
- const registry = new HandlerRegistry();
1238
- const graph = walkModuleGraph(rootModule, container);
1239
- validateModuleGraph(graph, container);
1240
- await registry.populateFromGraph(graph, container);
1241
- debug5("bootstrap: complete \u2014 %d modules, %d handlers", graph.size, registry.getAllHandlers().length);
1242
- return {
1243
- container,
1244
- registry
1245
- };
1246
- }
1247
- __name(bootstrap, "bootstrap");
1248
-
1249
- // src/application/application.ts
1763
+ // src/handlers/scanners/websocket.ts
1764
+ import "reflect-metadata";
1250
1765
  import createDebug6 from "debug";
1251
- var debug6 = createDebug6("celerity:core:factory");
1766
+ var debug6 = createDebug6("celerity:core:scanner:websocket");
1767
+ async function scanWebSocketHandlers(graph, container, registry) {
1768
+ for (const [, node] of graph) {
1769
+ for (const controllerClass of node.controllers) {
1770
+ await scanClassHandler2(controllerClass, container, registry);
1771
+ }
1772
+ for (const fnHandler of node.functionHandlers) {
1773
+ scanFunctionHandler2(fnHandler, registry);
1774
+ }
1775
+ }
1776
+ }
1777
+ __name(scanWebSocketHandlers, "scanWebSocketHandlers");
1778
+ async function scanClassHandler2(controllerClass, container, registry) {
1779
+ const isWsController = Reflect.getOwnMetadata(WEBSOCKET_CONTROLLER_METADATA, controllerClass);
1780
+ if (!isWsController) return;
1781
+ const prototype = controllerClass.prototype;
1782
+ const methods = Object.getOwnPropertyNames(prototype).filter((name) => name !== "constructor");
1783
+ const classProtectedBy = Reflect.getOwnMetadata(GUARD_PROTECTEDBY_METADATA, controllerClass) ?? [];
1784
+ const classLayers = Reflect.getOwnMetadata(LAYER_METADATA, controllerClass) ?? [];
1785
+ const classCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, controllerClass) ?? {};
1786
+ const classIsPublic = Reflect.getOwnMetadata(PUBLIC_METADATA, controllerClass) === true;
1787
+ for (const methodName of methods) {
1788
+ const eventMeta = Reflect.getOwnMetadata(WEBSOCKET_EVENT_METADATA, prototype, methodName);
1789
+ if (!eventMeta) continue;
1790
+ const methodLayers = Reflect.getOwnMetadata(LAYER_METADATA, prototype, methodName) ?? [];
1791
+ const paramMetadata = Reflect.getOwnMetadata(PARAM_METADATA, prototype, methodName) ?? [];
1792
+ const methodCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, prototype, methodName) ?? {};
1793
+ const descriptor = Object.getOwnPropertyDescriptor(prototype, methodName);
1794
+ if (!descriptor?.value || typeof descriptor.value !== "function") continue;
1795
+ debug6("scanClassHandler: %s %s (%s.%s)", eventMeta.eventType, eventMeta.route, controllerClass.name, methodName);
1796
+ const layers = [
1797
+ ...classLayers,
1798
+ ...methodLayers
1799
+ ];
1800
+ const msgBodyParam = paramMetadata.find((p) => p.type === "messageBody");
1801
+ if (msgBodyParam?.schema) {
1802
+ layers.unshift(validate({
1803
+ wsMessageBody: msgBodyParam.schema
1804
+ }));
1805
+ }
1806
+ registry.register({
1807
+ type: "websocket",
1808
+ route: eventMeta.route,
1809
+ protectedBy: classProtectedBy,
1810
+ layers,
1811
+ isPublic: classIsPublic,
1812
+ paramMetadata,
1813
+ customMetadata: {
1814
+ ...classCustomMetadata,
1815
+ ...methodCustomMetadata
1816
+ },
1817
+ handlerFn: descriptor.value,
1818
+ controllerClass
1819
+ });
1820
+ }
1821
+ }
1822
+ __name(scanClassHandler2, "scanClassHandler");
1823
+ function scanFunctionHandler2(definition, registry) {
1824
+ if (definition.type !== "websocket") return;
1825
+ const meta = definition.metadata;
1826
+ const layers = [
1827
+ ...meta.layers ?? []
1828
+ ];
1829
+ if (meta.schema) {
1830
+ layers.unshift(validate({
1831
+ wsMessageBody: meta.schema
1832
+ }));
1833
+ }
1834
+ debug6("scanFunctionHandler: %s", definition.id ?? meta.route ?? "(no route)");
1835
+ registry.register({
1836
+ type: "websocket",
1837
+ id: definition.id,
1838
+ route: meta.route ?? "$default",
1839
+ protectedBy: meta.protectedBy ?? [],
1840
+ layers,
1841
+ isPublic: false,
1842
+ paramMetadata: [],
1843
+ customMetadata: meta.customMetadata ?? {},
1844
+ handlerFn: definition.handler,
1845
+ isFunctionHandler: true,
1846
+ injectTokens: meta.inject ?? []
1847
+ });
1848
+ }
1849
+ __name(scanFunctionHandler2, "scanFunctionHandler");
1850
+
1851
+ // src/handlers/scanners/consumer.ts
1852
+ import "reflect-metadata";
1853
+ import createDebug7 from "debug";
1854
+ var debug7 = createDebug7("celerity:core:scanner:consumer");
1855
+ async function scanConsumerHandlers(graph, container, registry) {
1856
+ for (const [, node] of graph) {
1857
+ for (const controllerClass of node.controllers) {
1858
+ await scanClassHandler3(controllerClass, container, registry);
1859
+ }
1860
+ for (const fnHandler of node.functionHandlers) {
1861
+ scanFunctionHandler3(fnHandler, registry);
1862
+ }
1863
+ }
1864
+ }
1865
+ __name(scanConsumerHandlers, "scanConsumerHandlers");
1866
+ async function scanClassHandler3(controllerClass, container, registry) {
1867
+ const consumerMeta = Reflect.getOwnMetadata(CONSUMER_METADATA, controllerClass);
1868
+ if (!consumerMeta) return;
1869
+ const prototype = controllerClass.prototype;
1870
+ const methods = Object.getOwnPropertyNames(prototype).filter((name) => name !== "constructor");
1871
+ const classLayers = Reflect.getOwnMetadata(LAYER_METADATA, controllerClass) ?? [];
1872
+ const classCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, controllerClass) ?? {};
1873
+ for (const methodName of methods) {
1874
+ const handlerMeta = Reflect.getOwnMetadata(CONSUMER_HANDLER_METADATA, prototype, methodName);
1875
+ if (!handlerMeta) continue;
1876
+ const methodLayers = Reflect.getOwnMetadata(LAYER_METADATA, prototype, methodName) ?? [];
1877
+ const paramMetadata = Reflect.getOwnMetadata(PARAM_METADATA, prototype, methodName) ?? [];
1878
+ const methodCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, prototype, methodName) ?? {};
1879
+ const descriptor = Object.getOwnPropertyDescriptor(prototype, methodName);
1880
+ if (!descriptor?.value || typeof descriptor.value !== "function") continue;
1881
+ const handlerTag = consumerMeta.source ? `${consumerMeta.source}::${methodName}` : methodName;
1882
+ const layers = [
1883
+ ...classLayers,
1884
+ ...methodLayers
1885
+ ];
1886
+ const messageParam = paramMetadata.find((p) => p.type === "messages");
1887
+ if (messageParam?.schema) {
1888
+ layers.unshift(validate({
1889
+ consumerMessage: messageParam.schema
1890
+ }));
1891
+ }
1892
+ debug7("scanClassHandler: tag=%s (%s.%s)", handlerTag, controllerClass.name, methodName);
1893
+ registry.register({
1894
+ type: "consumer",
1895
+ handlerTag,
1896
+ layers,
1897
+ paramMetadata,
1898
+ customMetadata: {
1899
+ ...classCustomMetadata,
1900
+ ...methodCustomMetadata
1901
+ },
1902
+ handlerFn: descriptor.value,
1903
+ controllerClass
1904
+ });
1905
+ }
1906
+ }
1907
+ __name(scanClassHandler3, "scanClassHandler");
1908
+ function scanFunctionHandler3(definition, registry) {
1909
+ if (definition.type !== "consumer") return;
1910
+ const meta = definition.metadata;
1911
+ const handlerTag = definition.id ?? "default";
1912
+ const layers = [
1913
+ ...meta.layers ?? []
1914
+ ];
1915
+ if (meta.messageSchema) {
1916
+ layers.unshift(validate({
1917
+ consumerMessage: meta.messageSchema
1918
+ }));
1919
+ }
1920
+ debug7("scanFunctionHandler: tag=%s", handlerTag);
1921
+ registry.register({
1922
+ type: "consumer",
1923
+ id: definition.id,
1924
+ handlerTag,
1925
+ layers,
1926
+ paramMetadata: [],
1927
+ customMetadata: meta.customMetadata ?? {},
1928
+ handlerFn: definition.handler,
1929
+ isFunctionHandler: true,
1930
+ injectTokens: meta.inject ?? []
1931
+ });
1932
+ }
1933
+ __name(scanFunctionHandler3, "scanFunctionHandler");
1934
+
1935
+ // src/handlers/scanners/schedule.ts
1936
+ import "reflect-metadata";
1937
+ import createDebug8 from "debug";
1938
+ var debug8 = createDebug8("celerity:core:scanner:schedule");
1939
+ async function scanScheduleHandlers(graph, container, registry) {
1940
+ for (const [, node] of graph) {
1941
+ for (const controllerClass of node.controllers) {
1942
+ await scanClassHandler4(controllerClass, container, registry);
1943
+ }
1944
+ for (const fnHandler of node.functionHandlers) {
1945
+ scanFunctionHandler4(fnHandler, registry);
1946
+ }
1947
+ }
1948
+ }
1949
+ __name(scanScheduleHandlers, "scanScheduleHandlers");
1950
+ async function scanClassHandler4(controllerClass, container, registry) {
1951
+ const prototype = controllerClass.prototype;
1952
+ const methods = Object.getOwnPropertyNames(prototype).filter((name) => name !== "constructor");
1953
+ const classLayers = Reflect.getOwnMetadata(LAYER_METADATA, controllerClass) ?? [];
1954
+ const classCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, controllerClass) ?? {};
1955
+ for (const methodName of methods) {
1956
+ const handlerMeta = Reflect.getOwnMetadata(SCHEDULE_HANDLER_METADATA, prototype, methodName);
1957
+ if (!handlerMeta) continue;
1958
+ const methodLayers = Reflect.getOwnMetadata(LAYER_METADATA, prototype, methodName) ?? [];
1959
+ const paramMetadata = Reflect.getOwnMetadata(PARAM_METADATA, prototype, methodName) ?? [];
1960
+ const methodCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, prototype, methodName) ?? {};
1961
+ const descriptor = Object.getOwnPropertyDescriptor(prototype, methodName);
1962
+ if (!descriptor?.value || typeof descriptor.value !== "function") continue;
1963
+ const handlerTag = handlerMeta.source ? `${handlerMeta.source}::${methodName}` : methodName;
1964
+ const layers = [
1965
+ ...classLayers,
1966
+ ...methodLayers
1967
+ ];
1968
+ const inputParam = paramMetadata.find((p) => p.type === "scheduleInput");
1969
+ if (inputParam?.schema) {
1970
+ layers.unshift(validate({
1971
+ scheduleInput: inputParam.schema
1972
+ }));
1973
+ }
1974
+ debug8("scanClassHandler: tag=%s (%s.%s)", handlerTag, controllerClass.name, methodName);
1975
+ registry.register({
1976
+ type: "schedule",
1977
+ handlerTag,
1978
+ layers,
1979
+ paramMetadata,
1980
+ customMetadata: {
1981
+ ...classCustomMetadata,
1982
+ ...methodCustomMetadata,
1983
+ ...handlerMeta.schedule ? {
1984
+ schedule: handlerMeta.schedule
1985
+ } : {},
1986
+ ...handlerMeta.source ? {
1987
+ source: handlerMeta.source
1988
+ } : {}
1989
+ },
1990
+ handlerFn: descriptor.value,
1991
+ controllerClass
1992
+ });
1993
+ }
1994
+ }
1995
+ __name(scanClassHandler4, "scanClassHandler");
1996
+ function scanFunctionHandler4(definition, registry) {
1997
+ if (definition.type !== "schedule") return;
1998
+ const meta = definition.metadata;
1999
+ const handlerTag = meta.source ?? definition.id ?? "default";
2000
+ const layers = [
2001
+ ...meta.layers ?? []
2002
+ ];
2003
+ if (meta.schema) {
2004
+ layers.unshift(validate({
2005
+ scheduleInput: meta.schema
2006
+ }));
2007
+ }
2008
+ const customMetadata = {
2009
+ ...meta.customMetadata ?? {}
2010
+ };
2011
+ if (meta.schedule) customMetadata.schedule = meta.schedule;
2012
+ if (meta.source) customMetadata.source = meta.source;
2013
+ debug8("scanFunctionHandler: tag=%s", handlerTag);
2014
+ registry.register({
2015
+ type: "schedule",
2016
+ id: definition.id,
2017
+ handlerTag,
2018
+ layers,
2019
+ paramMetadata: [],
2020
+ customMetadata,
2021
+ handlerFn: definition.handler,
2022
+ isFunctionHandler: true,
2023
+ injectTokens: meta.inject ?? []
2024
+ });
2025
+ }
2026
+ __name(scanFunctionHandler4, "scanFunctionHandler");
2027
+
2028
+ // src/handlers/scanners/custom.ts
2029
+ import "reflect-metadata";
2030
+ import createDebug9 from "debug";
2031
+ var debug9 = createDebug9("celerity:core:scanner:custom");
2032
+ async function scanCustomHandlers(graph, container, registry) {
2033
+ for (const [, node] of graph) {
2034
+ for (const controllerClass of node.controllers) {
2035
+ await scanClassHandler5(controllerClass, container, registry);
2036
+ }
2037
+ for (const fnHandler of node.functionHandlers) {
2038
+ scanFunctionHandler5(fnHandler, registry);
2039
+ }
2040
+ }
2041
+ }
2042
+ __name(scanCustomHandlers, "scanCustomHandlers");
2043
+ async function scanClassHandler5(controllerClass, container, registry) {
2044
+ const prototype = controllerClass.prototype;
2045
+ const methods = Object.getOwnPropertyNames(prototype).filter((name) => name !== "constructor");
2046
+ const classLayers = Reflect.getOwnMetadata(LAYER_METADATA, controllerClass) ?? [];
2047
+ const classCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, controllerClass) ?? {};
2048
+ for (const methodName of methods) {
2049
+ const invokeMeta = Reflect.getOwnMetadata(INVOKE_METADATA, prototype, methodName);
2050
+ if (!invokeMeta) continue;
2051
+ const methodLayers = Reflect.getOwnMetadata(LAYER_METADATA, prototype, methodName) ?? [];
2052
+ const paramMetadata = Reflect.getOwnMetadata(PARAM_METADATA, prototype, methodName) ?? [];
2053
+ const methodCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, prototype, methodName) ?? {};
2054
+ const descriptor = Object.getOwnPropertyDescriptor(prototype, methodName);
2055
+ if (!descriptor?.value || typeof descriptor.value !== "function") continue;
2056
+ const layers = [
2057
+ ...classLayers,
2058
+ ...methodLayers
2059
+ ];
2060
+ const payloadParam = paramMetadata.find((p) => p.type === "payload");
2061
+ if (payloadParam?.schema) {
2062
+ layers.unshift(validate({
2063
+ customPayload: payloadParam.schema
2064
+ }));
2065
+ }
2066
+ debug9("scanClassHandler: name=%s (%s.%s)", invokeMeta.name, controllerClass.name, methodName);
2067
+ registry.register({
2068
+ type: "custom",
2069
+ name: invokeMeta.name,
2070
+ layers,
2071
+ paramMetadata,
2072
+ customMetadata: {
2073
+ ...classCustomMetadata,
2074
+ ...methodCustomMetadata
2075
+ },
2076
+ handlerFn: descriptor.value,
2077
+ controllerClass
2078
+ });
2079
+ }
2080
+ }
2081
+ __name(scanClassHandler5, "scanClassHandler");
2082
+ function scanFunctionHandler5(definition, registry) {
2083
+ if (definition.type !== "custom") return;
2084
+ const meta = definition.metadata;
2085
+ const name = meta.name ?? definition.id ?? "default";
2086
+ const layers = [
2087
+ ...meta.layers ?? []
2088
+ ];
2089
+ if (meta.schema) {
2090
+ layers.unshift(validate({
2091
+ customPayload: meta.schema
2092
+ }));
2093
+ }
2094
+ debug9("scanFunctionHandler: name=%s", name);
2095
+ registry.register({
2096
+ type: "custom",
2097
+ id: definition.id,
2098
+ name,
2099
+ layers,
2100
+ paramMetadata: [],
2101
+ customMetadata: meta.customMetadata ?? {},
2102
+ handlerFn: definition.handler,
2103
+ isFunctionHandler: true,
2104
+ injectTokens: meta.inject ?? []
2105
+ });
2106
+ }
2107
+ __name(scanFunctionHandler5, "scanFunctionHandler");
2108
+
2109
+ // src/bootstrap/bootstrap.ts
2110
+ var debug10 = createDebug10("celerity:core:bootstrap");
2111
+ async function bootstrap(rootModule) {
2112
+ debug10("bootstrap: starting from %s", rootModule.name);
2113
+ const container = new Container();
2114
+ const registry = new HandlerRegistry();
2115
+ const graph = walkModuleGraph(rootModule, container);
2116
+ validateModuleGraph(graph, container);
2117
+ await scanHttpHandlers(graph, container, registry);
2118
+ await scanHttpGuards(graph, container, registry);
2119
+ await scanWebSocketHandlers(graph, container, registry);
2120
+ await scanConsumerHandlers(graph, container, registry);
2121
+ await scanScheduleHandlers(graph, container, registry);
2122
+ await scanCustomHandlers(graph, container, registry);
2123
+ debug10("bootstrap: complete \u2014 %d modules, %d handlers", graph.size, registry.getAllHandlers().length);
2124
+ return {
2125
+ container,
2126
+ registry
2127
+ };
2128
+ }
2129
+ __name(bootstrap, "bootstrap");
2130
+
2131
+ // src/application/application.ts
2132
+ import createDebug11 from "debug";
2133
+ var debug11 = createDebug11("celerity:core:factory");
1252
2134
  var CelerityApplication = class {
1253
2135
  static {
1254
2136
  __name(this, "CelerityApplication");
@@ -1272,7 +2154,7 @@ var CelerityApplication = class {
1272
2154
  }
1273
2155
  }
1274
2156
  async close() {
1275
- debug6("close: shutting down application");
2157
+ debug11("close: shutting down application");
1276
2158
  if (this.runtimeApp && typeof this.runtimeApp === "object") {
1277
2159
  const app = this.runtimeApp;
1278
2160
  await app.shutdown();
@@ -1298,6 +2180,13 @@ var CelerityApplication = class {
1298
2180
  };
1299
2181
 
1300
2182
  // src/application/serverless.ts
2183
+ var HANDLER_CREATORS = {
2184
+ http: /* @__PURE__ */ __name((adapter, registry, options) => adapter.createHttpHandler(registry, options), "http"),
2185
+ websocket: /* @__PURE__ */ __name((adapter, registry, options) => adapter.createWebSocketHandler(registry, options), "websocket"),
2186
+ consumer: /* @__PURE__ */ __name((adapter, registry, options) => adapter.createConsumerHandler(registry, options), "consumer"),
2187
+ schedule: /* @__PURE__ */ __name((adapter, registry, options) => adapter.createScheduleHandler(registry, options), "schedule"),
2188
+ custom: /* @__PURE__ */ __name((adapter, registry, options) => adapter.createCustomHandler(registry, options), "custom")
2189
+ };
1301
2190
  var ServerlessApplication = class {
1302
2191
  static {
1303
2192
  __name(this, "ServerlessApplication");
@@ -1315,12 +2204,16 @@ var ServerlessApplication = class {
1315
2204
  this.systemLayers = systemLayers;
1316
2205
  this.appLayers = appLayers;
1317
2206
  }
1318
- async start() {
1319
- this.handler = this.adapter.createHandler(this.registry, {
2207
+ createHandler(type) {
2208
+ const options = {
1320
2209
  container: this.container,
1321
2210
  systemLayers: this.systemLayers,
1322
2211
  appLayers: this.appLayers
1323
- });
2212
+ };
2213
+ return HANDLER_CREATORS[type](this.adapter, this.registry, options);
2214
+ }
2215
+ async start(type = "http") {
2216
+ this.handler = this.createHandler(type);
1324
2217
  return this.handler;
1325
2218
  }
1326
2219
  async close() {
@@ -1344,8 +2237,8 @@ var ServerlessApplication = class {
1344
2237
  }
1345
2238
  };
1346
2239
 
1347
- // src/handlers/pipeline.ts
1348
- import createDebug7 from "debug";
2240
+ // src/handlers/http-pipeline.ts
2241
+ import createDebug12 from "debug";
1349
2242
 
1350
2243
  // src/functions/context.ts
1351
2244
  function buildHttpRequest(request, metadata) {
@@ -1387,12 +2280,39 @@ function buildHttpContext(request, metadata, container, logger) {
1387
2280
  }
1388
2281
  __name(buildHttpContext, "buildHttpContext");
1389
2282
 
1390
- // src/handlers/pipeline.ts
1391
- var debug7 = createDebug7("celerity:core:pipeline");
1392
- async function executeHandlerPipeline(handler, request, options) {
2283
+ // src/handlers/types.ts
2284
+ async function resolveHandlerInstance(handler, container) {
2285
+ if (handler.handlerInstance) return handler.handlerInstance;
2286
+ if (!handler.controllerClass) {
2287
+ throw new Error("Handler has no controllerClass for deferred resolution");
2288
+ }
2289
+ const instance = await container.resolve(handler.controllerClass);
2290
+ handler.handlerInstance = instance;
2291
+ return instance;
2292
+ }
2293
+ __name(resolveHandlerInstance, "resolveHandlerInstance");
2294
+ async function resolveGuardInstance(guard, container) {
2295
+ if (guard.handlerInstance) return guard.handlerInstance;
2296
+ if (!guard.guardClass) {
2297
+ throw new Error("Guard has no guardClass for deferred resolution");
2298
+ }
2299
+ const instance = await container.resolve(guard.guardClass);
2300
+ guard.handlerInstance = instance;
2301
+ return instance;
2302
+ }
2303
+ __name(resolveGuardInstance, "resolveGuardInstance");
2304
+
2305
+ // src/handlers/http-pipeline.ts
2306
+ var debug12 = createDebug12("celerity:core:pipeline");
2307
+ async function executeHttpPipeline(handler, request, options) {
1393
2308
  const context = {
1394
2309
  request,
1395
- metadata: new HandlerMetadataStore(handler.customMetadata ?? {}),
2310
+ metadata: new HandlerMetadataStore({
2311
+ ...handler.customMetadata ?? {},
2312
+ ...options.handlerName ? {
2313
+ handlerName: options.handlerName
2314
+ } : {}
2315
+ }),
1396
2316
  container: options.container
1397
2317
  };
1398
2318
  const allLayers = [
@@ -1400,19 +2320,19 @@ async function executeHandlerPipeline(handler, request, options) {
1400
2320
  ...options.appLayers ?? [],
1401
2321
  ...handler.layers
1402
2322
  ];
1403
- debug7("%s %s \u2014 %d layers", request.method, request.path, allLayers.length);
2323
+ debug12("%s %s \u2014 %d layers", request.method, request.path, allLayers.length);
1404
2324
  try {
1405
2325
  const response = await runLayerPipeline(allLayers, context, async () => {
1406
- const handlerType = handler.isFunctionHandler ? "function" : "class";
1407
- debug7("invoking %s handler", handlerType);
2326
+ const style = handler.isFunctionHandler ? "function" : "class";
2327
+ debug12("invoking %s handler", style);
1408
2328
  const result = handler.isFunctionHandler ? await invokeFunctionHandler(handler, context) : await invokeClassHandler(handler, context);
1409
2329
  return normalizeResponse(result);
1410
- });
1411
- debug7("response %d", response.status);
2330
+ }, "http");
2331
+ debug12("response %d", response.status);
1412
2332
  return response;
1413
2333
  } catch (error) {
1414
2334
  if (error instanceof HttpException) {
1415
- debug7("HttpException %d: %s", error.statusCode, error.message);
2335
+ debug12("HttpException %d: %s", error.statusCode, error.message);
1416
2336
  return {
1417
2337
  status: error.statusCode,
1418
2338
  headers: {
@@ -1432,6 +2352,9 @@ async function executeHandlerPipeline(handler, request, options) {
1432
2352
  error: message,
1433
2353
  ...error instanceof Error && error.stack ? {
1434
2354
  stack: error.stack
2355
+ } : {},
2356
+ ...error instanceof Error && error.cause ? {
2357
+ cause: String(error.cause)
1435
2358
  } : {}
1436
2359
  });
1437
2360
  } else {
@@ -1448,7 +2371,7 @@ async function executeHandlerPipeline(handler, request, options) {
1448
2371
  };
1449
2372
  }
1450
2373
  }
1451
- __name(executeHandlerPipeline, "executeHandlerPipeline");
2374
+ __name(executeHttpPipeline, "executeHttpPipeline");
1452
2375
  async function invokeClassHandler(handler, context) {
1453
2376
  const args = [];
1454
2377
  const sorted = [
@@ -1457,7 +2380,8 @@ async function invokeClassHandler(handler, context) {
1457
2380
  for (const meta of sorted) {
1458
2381
  args[meta.index] = extractValidatedParam(meta.type, meta.key, context.request, context.metadata);
1459
2382
  }
1460
- return handler.handlerFn.apply(handler.handlerInstance, args);
2383
+ const instance = await resolveHandlerInstance(handler, context.container);
2384
+ return handler.handlerFn.apply(instance, args);
1461
2385
  }
1462
2386
  __name(invokeClassHandler, "invokeClassHandler");
1463
2387
  var VALIDATED_METADATA_KEYS = {
@@ -1517,6 +2441,383 @@ function isHttpResponse(value) {
1517
2441
  }
1518
2442
  __name(isHttpResponse, "isHttpResponse");
1519
2443
 
2444
+ // src/handlers/websocket-pipeline.ts
2445
+ import createDebug13 from "debug";
2446
+ var debug13 = createDebug13("celerity:core:ws-pipeline");
2447
+ async function executeWebSocketPipeline(handler, message, options) {
2448
+ const context = {
2449
+ message,
2450
+ metadata: new HandlerMetadataStore({
2451
+ ...handler.customMetadata ?? {},
2452
+ ...options.handlerName ? {
2453
+ handlerName: options.handlerName
2454
+ } : {}
2455
+ }),
2456
+ container: options.container
2457
+ };
2458
+ const allLayers = [
2459
+ ...options.systemLayers ?? [],
2460
+ ...options.appLayers ?? [],
2461
+ ...handler.layers
2462
+ ];
2463
+ debug13("%s %s \u2014 %d layers", message.eventType, message.connectionId, allLayers.length);
2464
+ try {
2465
+ await runLayerPipeline(allLayers, context, async () => {
2466
+ const style = handler.isFunctionHandler ? "function" : "class";
2467
+ debug13("invoking %s handler", style);
2468
+ if (handler.isFunctionHandler) {
2469
+ await invokeFunctionHandler2(handler, context);
2470
+ } else {
2471
+ await invokeClassHandler2(handler, context);
2472
+ }
2473
+ }, "websocket");
2474
+ } catch (error) {
2475
+ const errorMessage = error instanceof Error ? error.message : String(error);
2476
+ if (context.logger) {
2477
+ context.logger.error("Unhandled error in WebSocket handler pipeline", {
2478
+ error: errorMessage,
2479
+ connectionId: message.connectionId,
2480
+ eventType: message.eventType,
2481
+ ...error instanceof Error && error.stack ? {
2482
+ stack: error.stack
2483
+ } : {},
2484
+ ...error instanceof Error && error.cause ? {
2485
+ cause: String(error.cause)
2486
+ } : {}
2487
+ });
2488
+ } else {
2489
+ console.error("Unhandled error in WebSocket handler pipeline:", error);
2490
+ }
2491
+ }
2492
+ }
2493
+ __name(executeWebSocketPipeline, "executeWebSocketPipeline");
2494
+ async function invokeClassHandler2(handler, context) {
2495
+ const args = [];
2496
+ const sorted = [
2497
+ ...handler.paramMetadata
2498
+ ].sort((a, b) => a.index - b.index);
2499
+ for (const meta of sorted) {
2500
+ args[meta.index] = extractWebSocketParam(meta, context);
2501
+ }
2502
+ const instance = await resolveHandlerInstance(handler, context.container);
2503
+ await handler.handlerFn.apply(instance, args);
2504
+ }
2505
+ __name(invokeClassHandler2, "invokeClassHandler");
2506
+ async function invokeFunctionHandler2(handler, context) {
2507
+ const validatedBody = context.metadata.get("validatedMessageBody");
2508
+ const message = validatedBody !== void 0 ? {
2509
+ ...context.message,
2510
+ jsonBody: validatedBody
2511
+ } : context.message;
2512
+ if (handler.injectTokens && handler.injectTokens.length > 0) {
2513
+ const deps = [];
2514
+ for (const token of handler.injectTokens) {
2515
+ deps.push(await context.container.resolve(token));
2516
+ }
2517
+ await handler.handlerFn(message, context, ...deps);
2518
+ } else {
2519
+ await handler.handlerFn(message, context);
2520
+ }
2521
+ }
2522
+ __name(invokeFunctionHandler2, "invokeFunctionHandler");
2523
+ function extractWebSocketParam(meta, context) {
2524
+ const { message } = context;
2525
+ switch (meta.type) {
2526
+ case "connectionId":
2527
+ return message.connectionId;
2528
+ case "messageBody": {
2529
+ const validated = context.metadata.get("validatedMessageBody");
2530
+ if (validated !== void 0) return validated;
2531
+ return message.jsonBody;
2532
+ }
2533
+ case "messageId":
2534
+ return message.messageId;
2535
+ case "requestContext":
2536
+ return message.requestContext;
2537
+ case "eventType":
2538
+ return message.eventType;
2539
+ default:
2540
+ return void 0;
2541
+ }
2542
+ }
2543
+ __name(extractWebSocketParam, "extractWebSocketParam");
2544
+
2545
+ // src/handlers/consumer-pipeline.ts
2546
+ import createDebug14 from "debug";
2547
+ var debug14 = createDebug14("celerity:core:consumer-pipeline");
2548
+ async function executeConsumerPipeline(handler, event, options) {
2549
+ const context = {
2550
+ event,
2551
+ metadata: new HandlerMetadataStore({
2552
+ ...handler.customMetadata ?? {},
2553
+ ...options.handlerName ? {
2554
+ handlerName: options.handlerName
2555
+ } : {}
2556
+ }),
2557
+ container: options.container
2558
+ };
2559
+ const allLayers = [
2560
+ ...options.systemLayers ?? [],
2561
+ ...options.appLayers ?? [],
2562
+ ...handler.layers
2563
+ ];
2564
+ debug14("tag=%s \u2014 %d messages, %d layers", event.handlerTag, event.messages.length, allLayers.length);
2565
+ let result = {
2566
+ success: true
2567
+ };
2568
+ try {
2569
+ await runLayerPipeline(allLayers, context, async () => {
2570
+ const style = handler.isFunctionHandler ? "function" : "class";
2571
+ debug14("invoking %s handler", style);
2572
+ const validatedMessages = context.metadata.get("validatedMessages");
2573
+ const validationFailures = context.metadata.get("validationFailures") ?? [];
2574
+ const rawMessages = validatedMessages ? void 0 : event.messages;
2575
+ if (handler.isFunctionHandler) {
2576
+ result = await invokeFunctionHandler3(handler, context, validatedMessages, rawMessages);
2577
+ } else {
2578
+ result = await invokeClassHandler3(handler, context, validatedMessages, rawMessages);
2579
+ }
2580
+ if (validationFailures.length > 0) {
2581
+ const existing = result.failures ?? [];
2582
+ result = {
2583
+ ...result,
2584
+ success: result.success && validationFailures.length === 0,
2585
+ failures: [
2586
+ ...validationFailures,
2587
+ ...existing
2588
+ ]
2589
+ };
2590
+ }
2591
+ }, "consumer");
2592
+ } catch (error) {
2593
+ const errorMessage = error instanceof Error ? error.message : String(error);
2594
+ if (context.logger) {
2595
+ context.logger.error("Unhandled error in consumer handler pipeline", {
2596
+ error: errorMessage,
2597
+ handlerTag: event.handlerTag,
2598
+ messageCount: event.messages.length,
2599
+ ...error instanceof Error && error.stack ? {
2600
+ stack: error.stack
2601
+ } : {},
2602
+ ...error instanceof Error && error.cause ? {
2603
+ cause: String(error.cause)
2604
+ } : {}
2605
+ });
2606
+ } else {
2607
+ console.error("Unhandled error in consumer handler pipeline:", error);
2608
+ }
2609
+ return {
2610
+ success: false,
2611
+ errorMessage
2612
+ };
2613
+ }
2614
+ return result;
2615
+ }
2616
+ __name(executeConsumerPipeline, "executeConsumerPipeline");
2617
+ async function invokeClassHandler3(handler, context, validatedMessages, rawMessages) {
2618
+ const args = [];
2619
+ const sorted = [
2620
+ ...handler.paramMetadata
2621
+ ].sort((a, b) => a.index - b.index);
2622
+ for (const meta of sorted) {
2623
+ args[meta.index] = extractConsumerParam(meta, context, validatedMessages, rawMessages);
2624
+ }
2625
+ const instance = await resolveHandlerInstance(handler, context.container);
2626
+ return await handler.handlerFn.apply(instance, args);
2627
+ }
2628
+ __name(invokeClassHandler3, "invokeClassHandler");
2629
+ async function invokeFunctionHandler3(handler, context, validatedMessages, _rawMessages) {
2630
+ const deps = [];
2631
+ if (handler.injectTokens && handler.injectTokens.length > 0) {
2632
+ for (const token of handler.injectTokens) {
2633
+ deps.push(await context.container.resolve(token));
2634
+ }
2635
+ }
2636
+ const firstArg = validatedMessages ?? context.event;
2637
+ return await handler.handlerFn(firstArg, context, ...deps);
2638
+ }
2639
+ __name(invokeFunctionHandler3, "invokeFunctionHandler");
2640
+ function extractConsumerParam(meta, context, validatedMessages, rawMessages) {
2641
+ switch (meta.type) {
2642
+ case "messages":
2643
+ return validatedMessages ?? rawMessages ?? context.event.messages;
2644
+ case "consumerEvent":
2645
+ return context.event;
2646
+ case "consumerVendor":
2647
+ return context.event.vendor;
2648
+ case "consumerTraceContext":
2649
+ return context.event.traceContext ?? null;
2650
+ default:
2651
+ return void 0;
2652
+ }
2653
+ }
2654
+ __name(extractConsumerParam, "extractConsumerParam");
2655
+
2656
+ // src/handlers/schedule-pipeline.ts
2657
+ import createDebug15 from "debug";
2658
+ var debug15 = createDebug15("celerity:core:schedule-pipeline");
2659
+ async function executeSchedulePipeline(handler, event, options) {
2660
+ const context = {
2661
+ event,
2662
+ metadata: new HandlerMetadataStore({
2663
+ ...handler.customMetadata ?? {},
2664
+ ...options.handlerName ? {
2665
+ handlerName: options.handlerName
2666
+ } : {}
2667
+ }),
2668
+ container: options.container
2669
+ };
2670
+ const allLayers = [
2671
+ ...options.systemLayers ?? [],
2672
+ ...options.appLayers ?? [],
2673
+ ...handler.layers
2674
+ ];
2675
+ debug15("tag=%s \u2014 %d layers", event.handlerTag, allLayers.length);
2676
+ let result = {
2677
+ success: true
2678
+ };
2679
+ try {
2680
+ await runLayerPipeline(allLayers, context, async () => {
2681
+ const style = handler.isFunctionHandler ? "function" : "class";
2682
+ debug15("invoking %s handler", style);
2683
+ const validatedInput = context.metadata.get("validatedInput") ?? event.input;
2684
+ if (handler.isFunctionHandler) {
2685
+ result = await invokeFunctionHandler4(handler, context, validatedInput);
2686
+ } else {
2687
+ result = await invokeClassHandler4(handler, context, validatedInput);
2688
+ }
2689
+ }, "schedule");
2690
+ } catch (error) {
2691
+ const errorMessage = error instanceof Error ? error.message : String(error);
2692
+ if (context.logger) {
2693
+ context.logger.error("Unhandled error in schedule handler pipeline", {
2694
+ error: errorMessage,
2695
+ handlerTag: event.handlerTag,
2696
+ scheduleId: event.scheduleId,
2697
+ ...error instanceof Error && error.stack ? {
2698
+ stack: error.stack
2699
+ } : {},
2700
+ ...error instanceof Error && error.cause ? {
2701
+ cause: String(error.cause)
2702
+ } : {}
2703
+ });
2704
+ } else {
2705
+ console.error("Unhandled error in schedule handler pipeline:", error);
2706
+ }
2707
+ return {
2708
+ success: false,
2709
+ errorMessage
2710
+ };
2711
+ }
2712
+ return result;
2713
+ }
2714
+ __name(executeSchedulePipeline, "executeSchedulePipeline");
2715
+ async function invokeClassHandler4(handler, context, validatedInput) {
2716
+ const args = [];
2717
+ const sorted = [
2718
+ ...handler.paramMetadata
2719
+ ].sort((a, b) => a.index - b.index);
2720
+ for (const meta of sorted) {
2721
+ args[meta.index] = extractScheduleParam(meta, context, validatedInput);
2722
+ }
2723
+ const instance = await resolveHandlerInstance(handler, context.container);
2724
+ return await handler.handlerFn.apply(instance, args);
2725
+ }
2726
+ __name(invokeClassHandler4, "invokeClassHandler");
2727
+ async function invokeFunctionHandler4(handler, context, _validatedInput) {
2728
+ const deps = [];
2729
+ if (handler.injectTokens && handler.injectTokens.length > 0) {
2730
+ for (const token of handler.injectTokens) {
2731
+ deps.push(await context.container.resolve(token));
2732
+ }
2733
+ }
2734
+ return await handler.handlerFn(context.event, context, ...deps);
2735
+ }
2736
+ __name(invokeFunctionHandler4, "invokeFunctionHandler");
2737
+ function extractScheduleParam(meta, context, validatedInput) {
2738
+ switch (meta.type) {
2739
+ case "scheduleInput":
2740
+ return validatedInput;
2741
+ case "scheduleId":
2742
+ return context.event.scheduleId;
2743
+ case "scheduleExpression":
2744
+ return context.event.schedule;
2745
+ case "scheduleEvent":
2746
+ return context.event;
2747
+ default:
2748
+ return void 0;
2749
+ }
2750
+ }
2751
+ __name(extractScheduleParam, "extractScheduleParam");
2752
+
2753
+ // src/handlers/custom-pipeline.ts
2754
+ import createDebug16 from "debug";
2755
+ var debug16 = createDebug16("celerity:core:custom-pipeline");
2756
+ async function executeCustomPipeline(handler, payload, options) {
2757
+ const context = {
2758
+ metadata: new HandlerMetadataStore({
2759
+ ...handler.customMetadata ?? {},
2760
+ ...options.handlerName ? {
2761
+ handlerName: options.handlerName
2762
+ } : {},
2763
+ rawPayload: payload
2764
+ }),
2765
+ container: options.container
2766
+ };
2767
+ const allLayers = [
2768
+ ...options.systemLayers ?? [],
2769
+ ...options.appLayers ?? [],
2770
+ ...handler.layers
2771
+ ];
2772
+ debug16("name=%s \u2014 %d layers", options.handlerName ?? "unknown", allLayers.length);
2773
+ let result;
2774
+ await runLayerPipeline(allLayers, context, async () => {
2775
+ const style = handler.isFunctionHandler ? "function" : "class";
2776
+ debug16("invoking %s handler", style);
2777
+ const validatedPayload = context.metadata.get("validatedPayload") ?? payload;
2778
+ if (handler.isFunctionHandler) {
2779
+ result = await invokeFunctionHandler5(handler, context, validatedPayload);
2780
+ } else {
2781
+ result = await invokeClassHandler5(handler, context, validatedPayload);
2782
+ }
2783
+ }, "custom");
2784
+ return result;
2785
+ }
2786
+ __name(executeCustomPipeline, "executeCustomPipeline");
2787
+ async function invokeClassHandler5(handler, context, validatedPayload) {
2788
+ const args = [];
2789
+ const sorted = [
2790
+ ...handler.paramMetadata
2791
+ ].sort((a, b) => a.index - b.index);
2792
+ for (const meta of sorted) {
2793
+ args[meta.index] = extractCustomParam(meta, context, validatedPayload);
2794
+ }
2795
+ const instance = await resolveHandlerInstance(handler, context.container);
2796
+ return handler.handlerFn.apply(instance, args);
2797
+ }
2798
+ __name(invokeClassHandler5, "invokeClassHandler");
2799
+ async function invokeFunctionHandler5(handler, context, validatedPayload) {
2800
+ const deps = [];
2801
+ if (handler.injectTokens && handler.injectTokens.length > 0) {
2802
+ for (const token of handler.injectTokens) {
2803
+ deps.push(await context.container.resolve(token));
2804
+ }
2805
+ }
2806
+ return handler.handlerFn(validatedPayload, context, ...deps);
2807
+ }
2808
+ __name(invokeFunctionHandler5, "invokeFunctionHandler");
2809
+ function extractCustomParam(meta, context, validatedPayload) {
2810
+ switch (meta.type) {
2811
+ case "payload":
2812
+ return validatedPayload;
2813
+ case "invokeContext":
2814
+ return context;
2815
+ default:
2816
+ return void 0;
2817
+ }
2818
+ }
2819
+ __name(extractCustomParam, "extractCustomParam");
2820
+
1520
2821
  // src/testing/test-app.ts
1521
2822
  var TestingApplication = class {
1522
2823
  static {
@@ -1532,12 +2833,56 @@ var TestingApplication = class {
1532
2833
  this.systemLayers = systemLayers;
1533
2834
  this.appLayers = appLayers;
1534
2835
  }
1535
- async inject(request) {
1536
- const handler = this.registry.getHandler(request.path, request.method);
2836
+ async injectHttp(request) {
2837
+ const handler = this.registry.getHandler("http", `${request.method} ${request.path}`);
1537
2838
  if (!handler) {
1538
2839
  throw new NotFoundException(`No handler found for ${request.method} ${request.path}`);
1539
2840
  }
1540
- return executeHandlerPipeline(handler, request, {
2841
+ return executeHttpPipeline(handler, request, {
2842
+ container: this.container,
2843
+ systemLayers: this.systemLayers,
2844
+ appLayers: this.appLayers
2845
+ });
2846
+ }
2847
+ async injectWebSocket(route, message) {
2848
+ const handler = this.registry.getHandler("websocket", route);
2849
+ if (!handler) {
2850
+ throw new NotFoundException(`No WebSocket handler found for route: ${route}`);
2851
+ }
2852
+ await executeWebSocketPipeline(handler, message, {
2853
+ container: this.container,
2854
+ systemLayers: this.systemLayers,
2855
+ appLayers: this.appLayers
2856
+ });
2857
+ }
2858
+ async injectConsumer(handlerTag, event) {
2859
+ const handler = this.registry.getHandler("consumer", handlerTag);
2860
+ if (!handler) {
2861
+ throw new NotFoundException(`No consumer handler found for tag: ${handlerTag}`);
2862
+ }
2863
+ return executeConsumerPipeline(handler, event, {
2864
+ container: this.container,
2865
+ systemLayers: this.systemLayers,
2866
+ appLayers: this.appLayers
2867
+ });
2868
+ }
2869
+ async injectSchedule(handlerTag, event) {
2870
+ const handler = this.registry.getHandler("schedule", handlerTag);
2871
+ if (!handler) {
2872
+ throw new NotFoundException(`No schedule handler found for tag: ${handlerTag}`);
2873
+ }
2874
+ return executeSchedulePipeline(handler, event, {
2875
+ container: this.container,
2876
+ systemLayers: this.systemLayers,
2877
+ appLayers: this.appLayers
2878
+ });
2879
+ }
2880
+ async injectCustom(name, payload) {
2881
+ const handler = this.registry.getHandler("custom", name);
2882
+ if (!handler) {
2883
+ throw new NotFoundException(`No custom handler found for name: ${name}`);
2884
+ }
2885
+ return executeCustomPipeline(handler, payload ?? null, {
1541
2886
  container: this.container,
1542
2887
  systemLayers: this.systemLayers,
1543
2888
  appLayers: this.appLayers
@@ -1571,28 +2916,77 @@ function mockRequest(method, path, options = {}) {
1571
2916
  };
1572
2917
  }
1573
2918
  __name(mockRequest, "mockRequest");
2919
+ function mockWebSocketMessage(options = {}) {
2920
+ return {
2921
+ messageType: options.messageType ?? "json",
2922
+ eventType: options.eventType ?? "message",
2923
+ connectionId: options.connectionId ?? "test-conn-id",
2924
+ messageId: options.messageId ?? "test-msg-id",
2925
+ jsonBody: options.jsonBody ?? null,
2926
+ binaryBody: options.binaryBody,
2927
+ traceContext: options.traceContext ?? null
2928
+ };
2929
+ }
2930
+ __name(mockWebSocketMessage, "mockWebSocketMessage");
2931
+ function mockConsumerEvent(handlerTag, messages, options = {}) {
2932
+ const builtMessages = messages.map((msg, index) => ({
2933
+ messageId: msg.messageId ?? `msg-${index}`,
2934
+ body: msg.body,
2935
+ source: msg.source ?? "test",
2936
+ ...msg.sourceType !== void 0 && {
2937
+ sourceType: msg.sourceType
2938
+ },
2939
+ ...msg.sourceName !== void 0 && {
2940
+ sourceName: msg.sourceName
2941
+ },
2942
+ ...msg.eventType !== void 0 && {
2943
+ eventType: msg.eventType
2944
+ },
2945
+ messageAttributes: msg.messageAttributes ?? {},
2946
+ vendor: {}
2947
+ }));
2948
+ return {
2949
+ handlerTag,
2950
+ messages: builtMessages,
2951
+ vendor: options.vendor ?? {},
2952
+ traceContext: options.traceContext ?? null
2953
+ };
2954
+ }
2955
+ __name(mockConsumerEvent, "mockConsumerEvent");
2956
+ function mockScheduleEvent(handlerTag, options = {}) {
2957
+ return {
2958
+ handlerTag,
2959
+ scheduleId: options.scheduleId ?? handlerTag,
2960
+ messageId: options.messageId ?? "test-schedule-msg-id",
2961
+ schedule: options.schedule ?? "rate(1 day)",
2962
+ input: options.input,
2963
+ vendor: options.vendor ?? {},
2964
+ traceContext: options.traceContext ?? null
2965
+ };
2966
+ }
2967
+ __name(mockScheduleEvent, "mockScheduleEvent");
1574
2968
 
1575
2969
  // src/application/factory.ts
1576
- var debug8 = createDebug8("celerity:core:factory");
2970
+ var debug17 = createDebug17("celerity:core:factory");
1577
2971
  var CelerityFactory = class {
1578
2972
  static {
1579
2973
  __name(this, "CelerityFactory");
1580
2974
  }
1581
2975
  static async create(rootModule, options) {
1582
- debug8("create: bootstrapping %s", rootModule.name);
2976
+ debug17("create: bootstrapping %s", rootModule.name);
1583
2977
  const systemLayers = options?.systemLayers ?? await createDefaultSystemLayers();
1584
2978
  const appLayers = options?.layers ?? [];
1585
- debug8("create: %d system layers, %d app layers", systemLayers.length, appLayers.length);
2979
+ debug17("create: %d system layers, %d app layers", systemLayers.length, appLayers.length);
1586
2980
  const { container, registry } = await bootstrap(rootModule);
1587
2981
  if (options?.adapter) {
1588
- debug8("create: using adapter \u2192 ServerlessApplication");
2982
+ debug17("create: using adapter \u2192 ServerlessApplication");
1589
2983
  return new ServerlessApplication(registry, container, options.adapter, systemLayers, appLayers);
1590
2984
  }
1591
- debug8("create: \u2192 CelerityApplication");
2985
+ debug17("create: \u2192 CelerityApplication");
1592
2986
  return new CelerityApplication(registry, container, systemLayers, appLayers);
1593
2987
  }
1594
2988
  static async createTestingApp(rootModule, options) {
1595
- debug8("createTestingApp: bootstrapping %s", rootModule.name);
2989
+ debug17("createTestingApp: bootstrapping %s", rootModule.name);
1596
2990
  const { container, registry } = await bootstrap(rootModule);
1597
2991
  const systemLayers = options?.systemLayers ?? [];
1598
2992
  const appLayers = options?.layers ?? [];
@@ -1689,22 +3083,130 @@ function httpDelete(path, handlerOrOptions, maybeHandler) {
1689
3083
  }
1690
3084
  __name(httpDelete, "httpDelete");
1691
3085
 
3086
+ // src/functions/create-guard.ts
3087
+ function createGuard(config, handler) {
3088
+ return {
3089
+ __celerity_guard: true,
3090
+ name: config.name,
3091
+ handler,
3092
+ metadata: {
3093
+ inject: config.inject ?? [],
3094
+ customMetadata: config.metadata ?? {}
3095
+ }
3096
+ };
3097
+ }
3098
+ __name(createGuard, "createGuard");
3099
+
3100
+ // src/functions/create-websocket-handler.ts
3101
+ function createWebSocketHandler(config, handler) {
3102
+ const metadata = {
3103
+ layers: config.layers ?? [],
3104
+ inject: config.inject ?? [],
3105
+ customMetadata: config.metadata ?? {}
3106
+ };
3107
+ if (config.route !== void 0) metadata.route = config.route;
3108
+ if (config.protectedBy !== void 0) metadata.protectedBy = config.protectedBy;
3109
+ if (config.schema !== void 0) metadata.schema = config.schema;
3110
+ return {
3111
+ __celerity_handler: true,
3112
+ type: "websocket",
3113
+ metadata,
3114
+ handler
3115
+ };
3116
+ }
3117
+ __name(createWebSocketHandler, "createWebSocketHandler");
3118
+
3119
+ // src/functions/create-consumer-handler.ts
3120
+ function createConsumerHandler(config, handler) {
3121
+ const metadata = {
3122
+ layers: config.layers ?? [],
3123
+ inject: config.inject ?? [],
3124
+ customMetadata: config.metadata ?? {}
3125
+ };
3126
+ if (config.route !== void 0) metadata.route = config.route;
3127
+ if (config.messageSchema !== void 0) metadata.messageSchema = config.messageSchema;
3128
+ return {
3129
+ __celerity_handler: true,
3130
+ type: "consumer",
3131
+ metadata,
3132
+ handler
3133
+ };
3134
+ }
3135
+ __name(createConsumerHandler, "createConsumerHandler");
3136
+
3137
+ // src/functions/create-schedule-handler.ts
3138
+ function isScheduleExpression2(value) {
3139
+ return value.startsWith("rate(") || value.startsWith("cron(");
3140
+ }
3141
+ __name(isScheduleExpression2, "isScheduleExpression");
3142
+ function createScheduleHandler(configOrString, configOrHandler, maybeHandler) {
3143
+ let config;
3144
+ let handler;
3145
+ if (typeof configOrString === "string") {
3146
+ config = {
3147
+ ...configOrHandler
3148
+ };
3149
+ handler = maybeHandler;
3150
+ if (isScheduleExpression2(configOrString)) {
3151
+ config.schedule = configOrString;
3152
+ } else {
3153
+ config.source = configOrString;
3154
+ }
3155
+ } else {
3156
+ config = configOrString;
3157
+ handler = configOrHandler;
3158
+ }
3159
+ const metadata = {
3160
+ layers: config.layers ?? [],
3161
+ inject: config.inject ?? [],
3162
+ customMetadata: config.metadata ?? {}
3163
+ };
3164
+ if (config.source !== void 0) metadata.source = config.source;
3165
+ if (config.schedule !== void 0) metadata.schedule = config.schedule;
3166
+ if (config.schema !== void 0) metadata.schema = config.schema;
3167
+ return {
3168
+ __celerity_handler: true,
3169
+ type: "schedule",
3170
+ metadata,
3171
+ handler
3172
+ };
3173
+ }
3174
+ __name(createScheduleHandler, "createScheduleHandler");
3175
+
3176
+ // src/functions/create-custom-handler.ts
3177
+ function createCustomHandler(config, handler) {
3178
+ const metadata = {
3179
+ layers: config.layers ?? [],
3180
+ inject: config.inject ?? [],
3181
+ customMetadata: config.metadata ?? {}
3182
+ };
3183
+ if (config.name !== void 0) metadata.name = config.name;
3184
+ if (config.schema !== void 0) metadata.schema = config.schema;
3185
+ return {
3186
+ __celerity_handler: true,
3187
+ type: "custom",
3188
+ metadata,
3189
+ handler
3190
+ };
3191
+ }
3192
+ __name(createCustomHandler, "createCustomHandler");
3193
+
1692
3194
  // src/handlers/module-resolver.ts
1693
3195
  import { resolve } from "path";
1694
- import createDebug9 from "debug";
1695
- var debug9 = createDebug9("celerity:core:module-resolver");
1696
- async function resolveHandlerByModuleRef(handlerId, registry, baseDir) {
3196
+ import createDebug18 from "debug";
3197
+ var debug18 = createDebug18("celerity:core:module-resolver");
3198
+ async function resolveHandlerByModuleRef(handlerId, handlerType, registry, baseDir) {
1697
3199
  const lastDot = handlerId.lastIndexOf(".");
1698
3200
  if (lastDot > 0) {
1699
3201
  const moduleName = handlerId.slice(0, lastDot);
1700
3202
  const exportName = handlerId.slice(lastDot + 1);
1701
- const result = await tryResolveExport(baseDir, moduleName, exportName, handlerId, registry);
3203
+ const result = await tryResolveExport(baseDir, moduleName, exportName, handlerId, handlerType, registry);
1702
3204
  if (result) return result;
1703
3205
  }
1704
- return tryResolveExport(baseDir, handlerId, "default", handlerId, registry);
3206
+ return tryResolveExport(baseDir, handlerId, "default", handlerId, handlerType, registry);
1705
3207
  }
1706
3208
  __name(resolveHandlerByModuleRef, "resolveHandlerByModuleRef");
1707
- async function tryResolveExport(baseDir, moduleName, exportName, handlerId, registry) {
3209
+ async function tryResolveExport(baseDir, moduleName, exportName, handlerId, handlerType, registry) {
1708
3210
  const handlerModulePath = resolve(baseDir, moduleName);
1709
3211
  let mod;
1710
3212
  try {
@@ -1719,66 +3221,236 @@ async function tryResolveExport(baseDir, moduleName, exportName, handlerId, regi
1719
3221
  const exported = mod[exportName];
1720
3222
  if (!exported) return null;
1721
3223
  const isFnDef = typeof exported === "object" && exported !== null && exported.__celerity_handler;
3224
+ if (isFnDef && exported.type !== handlerType) {
3225
+ return null;
3226
+ }
1722
3227
  const handlerFn = isFnDef ? exported.handler : exported;
1723
3228
  if (typeof handlerFn !== "function") return null;
1724
- const match = registry.getAllHandlers().find((h) => h.handlerFn === handlerFn);
3229
+ const handlers = registry.getHandlersByType(handlerType);
3230
+ const match = handlers.find((h) => h.handlerFn === handlerFn);
1725
3231
  if (match) {
1726
3232
  match.id = handlerId;
1727
- debug9("matched '%s' to registry handler", handlerId);
3233
+ debug18("matched '%s' to registry handler", handlerId);
1728
3234
  return match;
1729
3235
  }
1730
- debug9("'%s' not in registry, wrapping directly", handlerId);
1731
- return buildResolvedFromExport(handlerId, handlerFn, isFnDef ? exported : null);
3236
+ debug18("'%s' not in registry, wrapping directly", handlerId);
3237
+ return buildResolvedFromExport(handlerId, handlerType, handlerFn, isFnDef ? exported : null);
1732
3238
  }
1733
3239
  __name(tryResolveExport, "tryResolveExport");
1734
- function buildResolvedFromExport(handlerId, handlerFn, fnDef) {
1735
- if (fnDef) {
1736
- const meta = fnDef.metadata;
1737
- return {
1738
- id: handlerId,
1739
- protectedBy: [],
1740
- layers: [
1741
- ...meta.layers ?? []
1742
- ],
1743
- isPublic: false,
1744
- paramMetadata: [],
1745
- customMetadata: meta.customMetadata ?? {},
1746
- handlerFn,
1747
- isFunctionHandler: true,
1748
- injectTokens: meta.inject ?? []
1749
- };
1750
- }
1751
- return {
3240
+ function buildResolvedFromExport(handlerId, handlerType, handlerFn, fnDef) {
3241
+ const meta = fnDef ? fnDef.metadata : null;
3242
+ const base = {
1752
3243
  id: handlerId,
1753
- protectedBy: [],
1754
- layers: [],
1755
- isPublic: false,
3244
+ layers: [
3245
+ ...meta?.layers ?? []
3246
+ ],
1756
3247
  paramMetadata: [],
1757
- customMetadata: {},
3248
+ customMetadata: meta?.customMetadata ?? {},
1758
3249
  handlerFn,
1759
3250
  isFunctionHandler: true,
1760
- injectTokens: []
3251
+ injectTokens: meta?.inject ?? []
3252
+ };
3253
+ const guardFields = {
3254
+ protectedBy: [],
3255
+ isPublic: false
1761
3256
  };
3257
+ switch (handlerType) {
3258
+ case "http":
3259
+ return {
3260
+ ...base,
3261
+ ...guardFields,
3262
+ type: "http",
3263
+ ...meta?.path !== void 0 ? {
3264
+ path: meta.path
3265
+ } : {},
3266
+ ...meta?.method !== void 0 ? {
3267
+ method: meta.method
3268
+ } : {}
3269
+ };
3270
+ case "websocket":
3271
+ return {
3272
+ ...base,
3273
+ ...guardFields,
3274
+ type: "websocket",
3275
+ route: meta?.route ?? handlerId
3276
+ };
3277
+ case "consumer":
3278
+ return {
3279
+ ...base,
3280
+ type: "consumer",
3281
+ handlerTag: meta?.route ?? handlerId
3282
+ };
3283
+ case "schedule":
3284
+ return {
3285
+ ...base,
3286
+ type: "schedule",
3287
+ handlerTag: meta?.source ?? handlerId
3288
+ };
3289
+ case "custom":
3290
+ return {
3291
+ ...base,
3292
+ type: "custom",
3293
+ name: meta?.name ?? handlerId
3294
+ };
3295
+ }
1762
3296
  }
1763
3297
  __name(buildResolvedFromExport, "buildResolvedFromExport");
1764
3298
 
3299
+ // src/handlers/websocket-sender.ts
3300
+ var RuntimeWebSocketSender = class {
3301
+ static {
3302
+ __name(this, "RuntimeWebSocketSender");
3303
+ }
3304
+ registry;
3305
+ constructor(registry) {
3306
+ this.registry = registry;
3307
+ }
3308
+ async sendMessage(connectionId, data, options) {
3309
+ const messageId = options?.messageId ?? crypto.randomUUID();
3310
+ const messageType = options?.messageType === "binary" ? "binary" : "json";
3311
+ const payload = typeof data === "string" ? data : JSON.stringify(data);
3312
+ await this.registry.sendMessage(connectionId, messageId, messageType, payload);
3313
+ }
3314
+ };
3315
+
3316
+ // src/handlers/guard-pipeline.ts
3317
+ import createDebug19 from "debug";
3318
+ var debug19 = createDebug19("celerity:core:guard-pipeline");
3319
+ async function executeGuardPipeline(guard, input, options) {
3320
+ const metadata = new HandlerMetadataStore({
3321
+ ...guard.customMetadata ?? {},
3322
+ ...options.handlerMetadata ?? {}
3323
+ });
3324
+ const logger = await createGuardLogger(guard.name, input, options.container);
3325
+ try {
3326
+ const result = guard.isFunctionGuard ? await invokeFunctionGuard(guard, input, metadata, options, logger) : await invokeClassGuard(guard, input, metadata, options, logger);
3327
+ debug19("guard %s \u2014 allowed", guard.name);
3328
+ return {
3329
+ allowed: true,
3330
+ auth: result ?? {}
3331
+ };
3332
+ } catch (error) {
3333
+ if (error instanceof HttpException) {
3334
+ debug19("guard %s \u2014 rejected %d: %s", guard.name, error.statusCode, error.message);
3335
+ return {
3336
+ allowed: false,
3337
+ statusCode: error.statusCode,
3338
+ message: error.message,
3339
+ details: error.details
3340
+ };
3341
+ }
3342
+ const message = error instanceof Error ? error.message : String(error);
3343
+ debug19("guard %s \u2014 unexpected error: %s", guard.name, message);
3344
+ return {
3345
+ allowed: false,
3346
+ statusCode: 401,
3347
+ message: "Unauthorized"
3348
+ };
3349
+ }
3350
+ }
3351
+ __name(executeGuardPipeline, "executeGuardPipeline");
3352
+ async function createGuardLogger(guardName, input, container) {
3353
+ const attrs = {
3354
+ guard: guardName,
3355
+ requestId: input.requestId,
3356
+ method: input.method,
3357
+ path: input.path,
3358
+ clientIp: input.clientIp,
3359
+ ...input.handlerName ? {
3360
+ handlerName: input.handlerName
3361
+ } : {}
3362
+ };
3363
+ if (container.has("CelerityLogger")) {
3364
+ const root = await container.resolve("CelerityLogger");
3365
+ return root.child("guard", attrs);
3366
+ }
3367
+ const pkg = "@celerity-sdk/telemetry";
3368
+ const { createLogger, readTelemetryEnv } = await import(pkg);
3369
+ const rootLogger = await createLogger(readTelemetryEnv());
3370
+ return rootLogger.child("guard", attrs);
3371
+ }
3372
+ __name(createGuardLogger, "createGuardLogger");
3373
+ async function invokeClassGuard(guard, input, metadata, options, logger) {
3374
+ const guardContext = {
3375
+ token: input.token,
3376
+ auth: input.auth,
3377
+ request: {
3378
+ method: input.method,
3379
+ path: input.path,
3380
+ headers: input.headers,
3381
+ query: input.query,
3382
+ cookies: input.cookies,
3383
+ body: input.body,
3384
+ requestId: input.requestId,
3385
+ clientIp: input.clientIp
3386
+ },
3387
+ metadata,
3388
+ container: options.container,
3389
+ logger
3390
+ };
3391
+ const paramCount = guard.handlerFn.length;
3392
+ const args = new Array(paramCount);
3393
+ const decorated = new Set(guard.paramMetadata.map((m) => m.index));
3394
+ for (const meta of guard.paramMetadata) {
3395
+ if (meta.type === "token") {
3396
+ args[meta.index] = guardContext.token;
3397
+ } else if (meta.type === "auth") {
3398
+ args[meta.index] = guardContext.auth;
3399
+ }
3400
+ }
3401
+ for (let i = 0; i < paramCount; i++) {
3402
+ if (!decorated.has(i)) {
3403
+ args[i] = guardContext;
3404
+ }
3405
+ }
3406
+ const instance = await resolveGuardInstance(guard, options.container);
3407
+ return guard.handlerFn.apply(instance, args);
3408
+ }
3409
+ __name(invokeClassGuard, "invokeClassGuard");
3410
+ async function invokeFunctionGuard(guard, input, metadata, options, logger) {
3411
+ const req = {
3412
+ token: input.token,
3413
+ headers: input.headers,
3414
+ query: input.query,
3415
+ cookies: input.cookies,
3416
+ body: input.body,
3417
+ requestId: input.requestId,
3418
+ clientIp: input.clientIp
3419
+ };
3420
+ const ctx = {
3421
+ metadata,
3422
+ container: options.container,
3423
+ auth: input.auth,
3424
+ logger
3425
+ };
3426
+ if (guard.injectTokens && guard.injectTokens.length > 0) {
3427
+ const deps = [];
3428
+ for (const token of guard.injectTokens) {
3429
+ deps.push(await options.container.resolve(token));
3430
+ }
3431
+ return guard.handlerFn(req, ctx, ...deps);
3432
+ }
3433
+ return guard.handlerFn(req, ctx);
3434
+ }
3435
+ __name(invokeFunctionGuard, "invokeFunctionGuard");
3436
+
1765
3437
  // src/bootstrap/discovery.ts
1766
3438
  import { resolve as resolve2 } from "path";
1767
- import createDebug10 from "debug";
1768
- var debug10 = createDebug10("celerity:core:bootstrap");
3439
+ import createDebug20 from "debug";
3440
+ var debug20 = createDebug20("celerity:core:bootstrap");
1769
3441
  async function discoverModule(modulePath) {
1770
3442
  const resolved = modulePath ?? process.env.CELERITY_MODULE_PATH;
1771
3443
  if (!resolved) {
1772
3444
  throw new Error("Cannot discover module: set CELERITY_MODULE_PATH environment variable or pass modulePath");
1773
3445
  }
1774
3446
  const absolutePath = resolve2(resolved);
1775
- debug10("discoverModule: importing %s", absolutePath);
3447
+ debug20("discoverModule: importing %s", absolutePath);
1776
3448
  const imported = await import(absolutePath);
1777
3449
  const rootModule = imported.default ?? findModuleExport(imported);
1778
3450
  if (!rootModule || typeof rootModule !== "function") {
1779
3451
  throw new Error(`No module class found in "${resolved}"`);
1780
3452
  }
1781
- debug10("discoverModule: found %s", rootModule.name);
3453
+ debug20("discoverModule: found %s", rootModule.name);
1782
3454
  return rootModule;
1783
3455
  }
1784
3456
  __name(discoverModule, "discoverModule");
@@ -1832,61 +3504,366 @@ function mapToRuntimeResponse(response) {
1832
3504
  };
1833
3505
  }
1834
3506
  __name(mapToRuntimeResponse, "mapToRuntimeResponse");
3507
+ function mapWebSocketMessage(info) {
3508
+ const requestContext = info.requestContext ? {
3509
+ requestId: info.requestContext.requestId,
3510
+ requestTime: info.requestContext.requestTime,
3511
+ path: info.requestContext.path,
3512
+ protocolVersion: info.requestContext.protocolVersion,
3513
+ headers: flattenMultiValueRecord(info.requestContext.headers),
3514
+ userAgent: info.requestContext.userAgent,
3515
+ clientIp: info.requestContext.clientIp,
3516
+ query: flattenMultiValueRecord(info.requestContext.query),
3517
+ cookies: info.requestContext.cookies,
3518
+ auth: info.requestContext.auth,
3519
+ traceContext: info.requestContext.traceContext
3520
+ } : void 0;
3521
+ return {
3522
+ messageType: info.messageType,
3523
+ eventType: info.eventType,
3524
+ connectionId: info.connectionId,
3525
+ messageId: info.messageId,
3526
+ jsonBody: info.jsonBody,
3527
+ binaryBody: info.binaryBody,
3528
+ requestContext,
3529
+ traceContext: info.traceContext ?? null
3530
+ };
3531
+ }
3532
+ __name(mapWebSocketMessage, "mapWebSocketMessage");
3533
+ function mapConsumerEventInput(input) {
3534
+ return {
3535
+ handlerTag: input.handlerTag,
3536
+ messages: input.messages.map((msg) => {
3537
+ const m = msg;
3538
+ return {
3539
+ messageId: msg.messageId,
3540
+ body: msg.body,
3541
+ source: msg.source,
3542
+ ...m.sourceType !== void 0 && {
3543
+ sourceType: m.sourceType
3544
+ },
3545
+ ...m.sourceName !== void 0 && {
3546
+ sourceName: m.sourceName
3547
+ },
3548
+ ...m.eventType !== void 0 && {
3549
+ eventType: m.eventType
3550
+ },
3551
+ messageAttributes: msg.messageAttributes,
3552
+ vendor: msg.vendor
3553
+ };
3554
+ }),
3555
+ vendor: input.vendor,
3556
+ traceContext: input.traceContext ?? null
3557
+ };
3558
+ }
3559
+ __name(mapConsumerEventInput, "mapConsumerEventInput");
3560
+ function mapScheduleEventInput(input) {
3561
+ return {
3562
+ handlerTag: input.handlerTag,
3563
+ scheduleId: input.scheduleId,
3564
+ messageId: input.messageId,
3565
+ schedule: input.schedule,
3566
+ input: input.input,
3567
+ vendor: input.vendor,
3568
+ traceContext: input.traceContext ?? null
3569
+ };
3570
+ }
3571
+ __name(mapScheduleEventInput, "mapScheduleEventInput");
3572
+ function mapToNapiEventResult(result) {
3573
+ return {
3574
+ success: result.success,
3575
+ failures: result.failures?.map((f) => ({
3576
+ messageId: f.messageId,
3577
+ errorMessage: f.errorMessage
3578
+ })),
3579
+ errorMessage: result.errorMessage
3580
+ };
3581
+ }
3582
+ __name(mapToNapiEventResult, "mapToNapiEventResult");
1835
3583
 
1836
3584
  // src/bootstrap/runtime-entry.ts
1837
3585
  import { resolve as resolve3, dirname } from "path";
3586
+ import createDebug21 from "debug";
3587
+ var debug21 = createDebug21("celerity:core:runtime-entry");
1838
3588
  async function bootstrapForRuntime(modulePath, systemLayers) {
1839
3589
  const layers = systemLayers ?? await createDefaultSystemLayers();
1840
3590
  const resolvedModulePath = modulePath ?? process.env.CELERITY_MODULE_PATH;
1841
3591
  const moduleDir = resolvedModulePath ? dirname(resolve3(resolvedModulePath)) : process.cwd();
1842
3592
  const rootModule = await discoverModule(modulePath);
1843
3593
  const { container, registry } = await bootstrap(rootModule);
1844
- function buildCallback(handler) {
3594
+ function buildHttpCallback(handler, handlerName) {
1845
3595
  if (!handler) return null;
1846
3596
  return async (_err, request) => {
1847
3597
  const httpRequest = mapRuntimeRequest(request);
1848
- const httpResponse = await executeHandlerPipeline(handler, httpRequest, {
3598
+ const httpResponse = await executeHttpPipeline(handler, httpRequest, {
1849
3599
  container,
1850
- systemLayers: layers
3600
+ systemLayers: layers,
3601
+ handlerName
1851
3602
  });
1852
3603
  return mapToRuntimeResponse(httpResponse);
1853
3604
  };
1854
3605
  }
1855
- __name(buildCallback, "buildCallback");
3606
+ __name(buildHttpCallback, "buildHttpCallback");
3607
+ function buildWebSocketCallback(handler, handlerName) {
3608
+ if (!handler) return null;
3609
+ return async (_err, info) => {
3610
+ const message = mapWebSocketMessage(info);
3611
+ await executeWebSocketPipeline(handler, message, {
3612
+ container,
3613
+ systemLayers: layers,
3614
+ handlerName
3615
+ });
3616
+ };
3617
+ }
3618
+ __name(buildWebSocketCallback, "buildWebSocketCallback");
3619
+ function buildConsumerCallback(handler, handlerName) {
3620
+ if (!handler) return null;
3621
+ return async (_err, input) => {
3622
+ const event = mapConsumerEventInput(input);
3623
+ const result = await executeConsumerPipeline(handler, event, {
3624
+ container,
3625
+ systemLayers: layers,
3626
+ handlerName
3627
+ });
3628
+ return mapToNapiEventResult(result);
3629
+ };
3630
+ }
3631
+ __name(buildConsumerCallback, "buildConsumerCallback");
3632
+ function buildScheduleCallback(handler, handlerName) {
3633
+ if (!handler) return null;
3634
+ return async (_err, input) => {
3635
+ const event = mapScheduleEventInput(input);
3636
+ const result = await executeSchedulePipeline(handler, event, {
3637
+ container,
3638
+ systemLayers: layers,
3639
+ handlerName
3640
+ });
3641
+ return mapToNapiEventResult(result);
3642
+ };
3643
+ }
3644
+ __name(buildScheduleCallback, "buildScheduleCallback");
3645
+ function buildCustomCallback(handler, handlerName) {
3646
+ if (!handler) return null;
3647
+ return async (_err, payload) => {
3648
+ return executeCustomPipeline(handler, payload, {
3649
+ container,
3650
+ systemLayers: layers,
3651
+ handlerName
3652
+ });
3653
+ };
3654
+ }
3655
+ __name(buildCustomCallback, "buildCustomCallback");
1856
3656
  return {
1857
3657
  registry,
1858
3658
  container,
1859
- createRouteCallback(path, method) {
1860
- return buildCallback(registry.getHandler(path, method));
3659
+ createRouteCallback(method, path, handlerName) {
3660
+ return buildHttpCallback(registry.getHandler("http", `${method} ${path}`), handlerName);
3661
+ },
3662
+ async createRouteCallbackById(handlerId, codeLocation, handlerName) {
3663
+ const fromRegistry = registry.getHandlerById("http", handlerId);
3664
+ if (fromRegistry) return buildHttpCallback(fromRegistry, handlerName);
3665
+ const baseDir = codeLocation ? resolve3(codeLocation) : moduleDir;
3666
+ const resolved = await resolveHandlerByModuleRef(handlerId, "http", registry, baseDir);
3667
+ return resolved ? buildHttpCallback(resolved, handlerName) : null;
3668
+ },
3669
+ createGuardCallback(guardName) {
3670
+ const guard = registry.getGuard(guardName);
3671
+ if (!guard) return null;
3672
+ return async (input) => {
3673
+ debug21("guard %s \u2014 input method=%s path=%s", guardName, input.method, input.path);
3674
+ const handler = registry.getHandler("http", `${input.method} ${input.path}`);
3675
+ debug21("guard %s \u2014 handler %s, customMetadata=%o", guardName, handler ? "found" : "not found", handler?.customMetadata);
3676
+ return executeGuardPipeline(guard, input, {
3677
+ container,
3678
+ handlerMetadata: handler?.customMetadata
3679
+ });
3680
+ };
3681
+ },
3682
+ createWebSocketCallback(route, handlerName) {
3683
+ return buildWebSocketCallback(registry.getHandler("websocket", route), handlerName);
3684
+ },
3685
+ async createWebSocketCallbackById(handlerId, codeLocation, handlerName) {
3686
+ const fromRegistry = registry.getHandlerById("websocket", handlerId);
3687
+ if (fromRegistry) return buildWebSocketCallback(fromRegistry, handlerName);
3688
+ const baseDir = codeLocation ? resolve3(codeLocation) : moduleDir;
3689
+ const resolved = await resolveHandlerByModuleRef(handlerId, "websocket", registry, baseDir);
3690
+ return resolved ? buildWebSocketCallback(resolved, handlerName) : null;
3691
+ },
3692
+ createConsumerCallback(handlerTag, handlerName) {
3693
+ return buildConsumerCallback(registry.getHandler("consumer", handlerTag), handlerName);
3694
+ },
3695
+ async createConsumerCallbackById(handlerId, codeLocation, handlerName) {
3696
+ const fromRegistry = registry.getHandlerById("consumer", handlerId);
3697
+ if (fromRegistry) return buildConsumerCallback(fromRegistry, handlerName);
3698
+ const baseDir = codeLocation ? resolve3(codeLocation) : moduleDir;
3699
+ const resolved = await resolveHandlerByModuleRef(handlerId, "consumer", registry, baseDir);
3700
+ return resolved ? buildConsumerCallback(resolved, handlerName) : null;
3701
+ },
3702
+ createScheduleCallback(handlerTag, handlerName) {
3703
+ return buildScheduleCallback(registry.getHandler("schedule", handlerTag), handlerName);
3704
+ },
3705
+ async createScheduleCallbackById(handlerId, codeLocation, handlerName) {
3706
+ const fromRegistry = registry.getHandlerById("schedule", handlerId);
3707
+ if (fromRegistry) return buildScheduleCallback(fromRegistry, handlerName);
3708
+ const baseDir = codeLocation ? resolve3(codeLocation) : moduleDir;
3709
+ const resolved = await resolveHandlerByModuleRef(handlerId, "schedule", registry, baseDir);
3710
+ return resolved ? buildScheduleCallback(resolved, handlerName) : null;
3711
+ },
3712
+ createCustomCallback(handlerName) {
3713
+ return buildCustomCallback(registry.getHandler("custom", handlerName), handlerName);
1861
3714
  },
1862
- async createRouteCallbackById(handlerId, codeLocation) {
1863
- const fromRegistry = registry.getHandlerById(handlerId);
1864
- if (fromRegistry) return buildCallback(fromRegistry);
3715
+ async createCustomCallbackById(handlerId, codeLocation, handlerName) {
3716
+ const fromRegistry = registry.getHandlerById("custom", handlerId);
3717
+ if (fromRegistry) return buildCustomCallback(fromRegistry, handlerName);
1865
3718
  const baseDir = codeLocation ? resolve3(codeLocation) : moduleDir;
1866
- const resolved = await resolveHandlerByModuleRef(handlerId, registry, baseDir);
1867
- return resolved ? buildCallback(resolved) : null;
3719
+ const resolved = await resolveHandlerByModuleRef(handlerId, "custom", registry, baseDir);
3720
+ return resolved ? buildCustomCallback(resolved, handlerName) : null;
1868
3721
  }
1869
3722
  };
1870
3723
  }
1871
3724
  __name(bootstrapForRuntime, "bootstrapForRuntime");
1872
3725
 
1873
3726
  // src/bootstrap/runtime-orchestrator.ts
1874
- async function startRuntime(options) {
3727
+ import { WebSocketSender } from "@celerity-sdk/types";
3728
+ async function loadRuntime() {
1875
3729
  const pkg = "@celerity-sdk/runtime";
1876
3730
  const runtimeModule = await import(pkg);
1877
3731
  const config = runtimeModule.runtimeConfigFromEnv();
1878
3732
  const app = new runtimeModule.CoreRuntimeApplication(config);
1879
3733
  const appConfig = app.setup();
1880
- const result = await bootstrapForRuntime();
1881
- for (const def of appConfig.api?.http?.handlers ?? []) {
1882
- const callback = result.createRouteCallback(def.path, def.method) ?? await result.createRouteCallbackById(def.handler, def.location);
3734
+ return {
3735
+ app,
3736
+ appConfig
3737
+ };
3738
+ }
3739
+ __name(loadRuntime, "loadRuntime");
3740
+ function mapGuardResult(result) {
3741
+ if (result.allowed) {
3742
+ return {
3743
+ status: "allowed",
3744
+ auth: result.auth
3745
+ };
3746
+ }
3747
+ const status = result.statusCode === 403 ? "forbidden" : "unauthorised";
3748
+ return {
3749
+ status,
3750
+ message: result.message
3751
+ };
3752
+ }
3753
+ __name(mapGuardResult, "mapGuardResult");
3754
+ async function registerHttpHandlers(app, handlers, result) {
3755
+ for (const def of handlers?.http?.handlers ?? []) {
3756
+ const callback = result.createRouteCallback(def.method, def.path, def.name) ?? await result.createRouteCallbackById(def.handler, def.location, def.name);
1883
3757
  if (callback) {
1884
3758
  app.registerHttpHandler(def.path, def.method, def.timeout, callback);
1885
3759
  }
1886
3760
  }
3761
+ }
3762
+ __name(registerHttpHandlers, "registerHttpHandlers");
3763
+ async function registerGuardHandlers(app, guards, result) {
3764
+ for (const guardDef of guards?.handlers ?? []) {
3765
+ const coreCallback = result.createGuardCallback(guardDef.name);
3766
+ if (coreCallback) {
3767
+ await app.registerGuardHandler(guardDef.name, async (_err, input) => {
3768
+ const coreResult = await coreCallback({
3769
+ token: input.token,
3770
+ method: input.request.method,
3771
+ path: input.request.path,
3772
+ headers: input.request.headers,
3773
+ query: input.request.query,
3774
+ cookies: input.request.cookies,
3775
+ body: input.request.body ?? null,
3776
+ requestId: input.request.requestId,
3777
+ clientIp: input.request.clientIp,
3778
+ auth: input.auth ?? {},
3779
+ handlerName: input.handlerName
3780
+ });
3781
+ return mapGuardResult(coreResult);
3782
+ });
3783
+ }
3784
+ }
3785
+ }
3786
+ __name(registerGuardHandlers, "registerGuardHandlers");
3787
+ async function registerWebSocketHandlers(app, websocket, result) {
3788
+ for (const def of websocket?.handlers ?? []) {
3789
+ const callback = result.createWebSocketCallback(def.route, def.name) ?? await result.createWebSocketCallbackById(def.handler, def.location, def.name);
3790
+ if (callback) {
3791
+ app.registerWebsocketHandler(def.route, callback);
3792
+ }
3793
+ }
3794
+ }
3795
+ __name(registerWebSocketHandlers, "registerWebSocketHandlers");
3796
+ async function registerConsumerHandlers(app, consumers, result) {
3797
+ for (const consumer of consumers?.consumers ?? []) {
3798
+ for (const def of consumer.handlers) {
3799
+ const methodName = def.handler.split(".").pop() ?? def.name;
3800
+ const lookupKey = `${consumer.consumerName}::${methodName}`;
3801
+ const callback = result.createConsumerCallback(lookupKey, def.name) ?? await result.createConsumerCallbackById(def.handler, def.location, def.name);
3802
+ if (callback) {
3803
+ app.registerConsumerHandler(def.name, def.timeout, callback);
3804
+ }
3805
+ }
3806
+ }
3807
+ }
3808
+ __name(registerConsumerHandlers, "registerConsumerHandlers");
3809
+ async function registerEventHandlers(app, events, result) {
3810
+ for (const event of events?.events ?? []) {
3811
+ for (const def of event.handlers) {
3812
+ const methodName = def.handler.split(".").pop() ?? def.name;
3813
+ const lookupKey = `${event.consumerName}::${methodName}`;
3814
+ const callback = result.createConsumerCallback(lookupKey, def.name) ?? await result.createConsumerCallbackById(def.handler, def.location, def.name);
3815
+ if (callback) {
3816
+ app.registerConsumerHandler(def.name, def.timeout, callback);
3817
+ }
3818
+ }
3819
+ }
3820
+ }
3821
+ __name(registerEventHandlers, "registerEventHandlers");
3822
+ async function registerScheduleHandlers(app, schedules, result) {
3823
+ for (const schedule of schedules?.schedules ?? []) {
3824
+ for (const def of schedule.handlers) {
3825
+ const methodName = def.handler.split(".").pop() ?? def.name;
3826
+ const lookupKey = `${schedule.scheduleId}::${methodName}`;
3827
+ const callback = result.createScheduleCallback(lookupKey, def.name) ?? await result.createScheduleCallbackById(def.handler, def.location, def.name);
3828
+ if (callback) {
3829
+ app.registerScheduleHandler(def.name, def.timeout, callback);
3830
+ }
3831
+ }
3832
+ }
3833
+ }
3834
+ __name(registerScheduleHandlers, "registerScheduleHandlers");
3835
+ async function registerCustomHandlers(app, customHandlers, result) {
3836
+ for (const def of customHandlers?.handlers ?? []) {
3837
+ const callback = result.createCustomCallback(def.name) ?? await result.createCustomCallbackById(def.handler, def.location, def.name);
3838
+ if (callback) {
3839
+ app.registerCustomHandler(def.name, def.timeout, callback);
3840
+ }
3841
+ }
3842
+ }
3843
+ __name(registerCustomHandlers, "registerCustomHandlers");
3844
+ async function startRuntime(options) {
3845
+ const { app, appConfig } = await loadRuntime();
3846
+ const result = await bootstrapForRuntime();
3847
+ await registerHttpHandlers(app, appConfig.api, result);
3848
+ await registerGuardHandlers(app, appConfig.api?.guards, result);
3849
+ await registerWebSocketHandlers(app, appConfig.api?.websocket, result);
3850
+ await registerConsumerHandlers(app, appConfig.consumers, result);
3851
+ await registerEventHandlers(app, appConfig.events, result);
3852
+ await registerScheduleHandlers(app, appConfig.schedules, result);
3853
+ await registerCustomHandlers(app, appConfig.customHandlers, result);
3854
+ if (appConfig.api?.websocket) {
3855
+ const sender = new RuntimeWebSocketSender(app.websocketRegistry());
3856
+ result.container.register(WebSocketSender, {
3857
+ useValue: sender
3858
+ });
3859
+ }
1887
3860
  await app.run(options?.block ?? true);
1888
3861
  }
1889
3862
  __name(startRuntime, "startRuntime");
3863
+
3864
+ // src/index.ts
3865
+ import { WebSocketSender as WebSocketSender2 } from "@celerity-sdk/types";
3866
+ import { SourceType, BucketEventType, DatastoreEventType } from "@celerity-sdk/types";
1890
3867
  export {
1891
3868
  APP_CONFIG,
1892
3869
  Action,
@@ -1894,15 +3871,24 @@ export {
1894
3871
  BadGatewayException,
1895
3872
  BadRequestException,
1896
3873
  Body,
3874
+ BucketEventType,
3875
+ CONSUMER_HANDLER_METADATA,
3876
+ CONSUMER_METADATA,
1897
3877
  CONTROLLER_METADATA,
1898
3878
  CUSTOM_METADATA,
1899
3879
  CelerityApplication,
1900
3880
  CelerityFactory,
1901
3881
  ConflictException,
3882
+ ConnectionId,
3883
+ Consumer,
3884
+ ConsumerTraceContext,
1902
3885
  Container,
1903
3886
  Controller,
1904
3887
  Cookies,
3888
+ DatastoreEventType,
1905
3889
  Delete,
3890
+ EventInput,
3891
+ EventType,
1906
3892
  ForbiddenException,
1907
3893
  GUARD_CUSTOM_METADATA,
1908
3894
  GUARD_PROTECTEDBY_METADATA,
@@ -1917,20 +3903,31 @@ export {
1917
3903
  Headers,
1918
3904
  HttpException,
1919
3905
  INJECT_METADATA,
3906
+ INVOKE_METADATA,
1920
3907
  Inject,
1921
3908
  Injectable,
1922
3909
  InternalServerErrorException,
3910
+ Invoke,
3911
+ InvokeContext,
1923
3912
  LAYER_METADATA,
1924
3913
  MODULE_METADATA,
3914
+ MessageBody,
3915
+ MessageHandler,
3916
+ MessageId,
3917
+ Messages,
1925
3918
  MethodNotAllowedException,
1926
3919
  Module,
1927
3920
  NotAcceptableException,
1928
3921
  NotFoundException,
1929
3922
  NotImplementedException,
3923
+ OnConnect,
3924
+ OnDisconnect,
3925
+ OnMessage,
1930
3926
  Options,
1931
3927
  PUBLIC_METADATA,
1932
3928
  Param,
1933
3929
  Patch,
3930
+ Payload,
1934
3931
  Post,
1935
3932
  ProtectedBy,
1936
3933
  Public,
@@ -1939,24 +3936,52 @@ export {
1939
3936
  ROUTE_PATH_METADATA,
1940
3937
  RUNTIME_APP,
1941
3938
  Req,
3939
+ RequestContext,
1942
3940
  RequestId,
3941
+ RuntimeWebSocketSender,
3942
+ SCHEDULE_HANDLER_METADATA,
3943
+ ScheduleEventInput as ScheduleEventInputParam,
3944
+ ScheduleExpression,
3945
+ ScheduleHandler,
3946
+ ScheduleId,
3947
+ ScheduleInput,
1943
3948
  ServerlessApplication,
1944
3949
  ServiceUnavailableException,
1945
3950
  SetMetadata,
3951
+ SourceType,
1946
3952
  TestingApplication,
3953
+ Token,
1947
3954
  TooManyRequestsException,
3955
+ USE_RESOURCE_METADATA,
1948
3956
  UnauthorizedException,
1949
3957
  UnprocessableEntityException,
1950
3958
  UseLayer,
1951
3959
  UseLayers,
3960
+ UseResource,
3961
+ UseResources,
3962
+ Vendor,
3963
+ WEBSOCKET_CONTROLLER_METADATA,
3964
+ WEBSOCKET_EVENT_METADATA,
3965
+ WebSocketController,
3966
+ WebSocketSender2 as WebSocketSender,
1952
3967
  bootstrap,
1953
3968
  bootstrapForRuntime,
1954
3969
  buildModuleGraph,
3970
+ createConsumerHandler,
3971
+ createCustomHandler,
1955
3972
  createDefaultSystemLayers,
3973
+ createGuard,
1956
3974
  createHttpHandler,
3975
+ createScheduleHandler,
3976
+ createWebSocketHandler,
1957
3977
  discoverModule,
1958
3978
  disposeLayers,
1959
- executeHandlerPipeline,
3979
+ executeConsumerPipeline,
3980
+ executeCustomPipeline,
3981
+ executeGuardPipeline,
3982
+ executeHttpPipeline,
3983
+ executeSchedulePipeline,
3984
+ executeWebSocketPipeline,
1960
3985
  flattenMultiValueRecord,
1961
3986
  getClassDependencyTokens,
1962
3987
  getProviderDependencyTokens,
@@ -1965,12 +3990,27 @@ export {
1965
3990
  httpPatch,
1966
3991
  httpPost,
1967
3992
  httpPut,
3993
+ mapConsumerEventInput,
1968
3994
  mapRuntimeRequest,
3995
+ mapScheduleEventInput,
3996
+ mapToNapiEventResult,
1969
3997
  mapToRuntimeResponse,
3998
+ mapWebSocketMessage,
3999
+ mockConsumerEvent,
1970
4000
  mockRequest,
4001
+ mockScheduleEvent,
4002
+ mockWebSocketMessage,
1971
4003
  registerModuleGraph,
1972
4004
  resolveHandlerByModuleRef,
4005
+ routingKeyOf,
1973
4006
  runLayerPipeline,
4007
+ scanConsumerHandlers,
4008
+ scanCustomHandlers,
4009
+ scanHttpGuards,
4010
+ scanHttpHandlers,
4011
+ scanModule,
4012
+ scanScheduleHandlers,
4013
+ scanWebSocketHandlers,
1974
4014
  startRuntime,
1975
4015
  tokenToString,
1976
4016
  validate