@celerity-sdk/core 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2354 -315
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1046 -76
- package/dist/index.d.ts +1046 -76
- package/dist/index.js +2215 -239
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
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
|
-
|
|
12
|
-
var
|
|
13
|
-
var
|
|
14
|
-
var
|
|
15
|
-
var
|
|
16
|
-
var
|
|
17
|
-
var
|
|
18
|
-
var
|
|
19
|
-
var
|
|
20
|
-
var
|
|
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(sourceId) {
|
|
382
|
+
return (target) => {
|
|
383
|
+
const meta = {};
|
|
384
|
+
if (sourceId !== void 0) meta.sourceId = sourceId;
|
|
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
|
+
scheduleId: arg
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
const meta = {};
|
|
447
|
+
if (arg.scheduleId !== void 0) meta.scheduleId = arg.scheduleId;
|
|
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
|
-
|
|
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,21 @@ 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
|
+
bucket: {
|
|
839
|
+
pkg: "@celerity-sdk/bucket",
|
|
840
|
+
className: "ObjectStorageLayer"
|
|
841
|
+
},
|
|
842
|
+
queue: {
|
|
843
|
+
pkg: "@celerity-sdk/queue",
|
|
844
|
+
className: "QueueLayer"
|
|
845
|
+
},
|
|
846
|
+
cache: {
|
|
847
|
+
pkg: "@celerity-sdk/cache",
|
|
848
|
+
className: "CacheLayer"
|
|
849
|
+
}
|
|
850
|
+
};
|
|
493
851
|
async function createDefaultSystemLayers() {
|
|
494
852
|
const layers = [];
|
|
495
853
|
try {
|
|
@@ -500,6 +858,19 @@ async function createDefaultSystemLayers() {
|
|
|
500
858
|
} catch {
|
|
501
859
|
}
|
|
502
860
|
layers.push(new ConfigLayer());
|
|
861
|
+
const links = captureResourceLinks();
|
|
862
|
+
const resourceTypes = getResourceTypes(links);
|
|
863
|
+
for (const type of resourceTypes) {
|
|
864
|
+
const entry = RESOURCE_LAYER_MAP[type];
|
|
865
|
+
if (!entry) continue;
|
|
866
|
+
try {
|
|
867
|
+
const pkg = entry.pkg;
|
|
868
|
+
const mod = await import(pkg);
|
|
869
|
+
const LayerClass = mod[entry.className];
|
|
870
|
+
layers.push(new LayerClass());
|
|
871
|
+
} catch {
|
|
872
|
+
}
|
|
873
|
+
}
|
|
503
874
|
return layers;
|
|
504
875
|
}
|
|
505
876
|
__name(createDefaultSystemLayers, "createDefaultSystemLayers");
|
|
@@ -843,27 +1214,122 @@ var APP_CONFIG = /* @__PURE__ */ Symbol("celerity:app-config");
|
|
|
843
1214
|
var RUNTIME_APP = /* @__PURE__ */ Symbol("celerity:runtime-app");
|
|
844
1215
|
|
|
845
1216
|
// src/application/factory.ts
|
|
846
|
-
import
|
|
1217
|
+
import createDebug17 from "debug";
|
|
847
1218
|
|
|
848
1219
|
// src/bootstrap/bootstrap.ts
|
|
849
1220
|
import "reflect-metadata";
|
|
850
|
-
import
|
|
1221
|
+
import createDebug10 from "debug";
|
|
851
1222
|
|
|
852
1223
|
// src/handlers/registry.ts
|
|
853
|
-
import "
|
|
854
|
-
|
|
855
|
-
|
|
1224
|
+
import createDebug3 from "debug";
|
|
1225
|
+
|
|
1226
|
+
// src/handlers/routing.ts
|
|
1227
|
+
function routingKeyOf(handler) {
|
|
1228
|
+
switch (handler.type) {
|
|
1229
|
+
case "http":
|
|
1230
|
+
return `${handler.method} ${handler.path}`;
|
|
1231
|
+
case "websocket":
|
|
1232
|
+
return handler.route;
|
|
1233
|
+
case "consumer":
|
|
1234
|
+
return handler.handlerTag;
|
|
1235
|
+
case "schedule":
|
|
1236
|
+
return handler.handlerTag;
|
|
1237
|
+
case "custom":
|
|
1238
|
+
return handler.name;
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
__name(routingKeyOf, "routingKeyOf");
|
|
1242
|
+
|
|
1243
|
+
// src/handlers/registry.ts
|
|
1244
|
+
var debug3 = createDebug3("celerity:core:registry");
|
|
1245
|
+
var HandlerRegistry = class {
|
|
1246
|
+
static {
|
|
1247
|
+
__name(this, "HandlerRegistry");
|
|
1248
|
+
}
|
|
1249
|
+
byType = /* @__PURE__ */ new Map();
|
|
1250
|
+
exactLookup = /* @__PURE__ */ new Map();
|
|
1251
|
+
byId = /* @__PURE__ */ new Map();
|
|
1252
|
+
guards = /* @__PURE__ */ new Map();
|
|
1253
|
+
register(handler) {
|
|
1254
|
+
const list = this.byType.get(handler.type) ?? [];
|
|
1255
|
+
list.push(handler);
|
|
1256
|
+
this.byType.set(handler.type, list);
|
|
1257
|
+
if (handler.type !== "http") {
|
|
1258
|
+
this.exactLookup.set(`${handler.type}::${routingKeyOf(handler)}`, handler);
|
|
1259
|
+
}
|
|
1260
|
+
if (handler.id) {
|
|
1261
|
+
this.byId.set(handler.id, handler);
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
getHandler(type, routingKey) {
|
|
1265
|
+
if (type === "http") return this.findHttpHandler(routingKey);
|
|
1266
|
+
const found = this.exactLookup.get(`${type}::${routingKey}`);
|
|
1267
|
+
debug3("getHandler %s %s \u2192 %s", type, routingKey, found ? "matched" : "not found");
|
|
1268
|
+
return found;
|
|
1269
|
+
}
|
|
1270
|
+
getHandlerById(type, id) {
|
|
1271
|
+
const handler = this.byId.get(id);
|
|
1272
|
+
if (handler && handler.type === type) {
|
|
1273
|
+
return handler;
|
|
1274
|
+
}
|
|
1275
|
+
debug3("getHandlerById %s %s \u2192 not found", type, id);
|
|
1276
|
+
return void 0;
|
|
1277
|
+
}
|
|
1278
|
+
getHandlersByType(type) {
|
|
1279
|
+
return this.byType.get(type) ?? [];
|
|
1280
|
+
}
|
|
1281
|
+
getAllHandlers() {
|
|
1282
|
+
const result = [];
|
|
1283
|
+
for (const list of this.byType.values()) result.push(...list);
|
|
1284
|
+
return result;
|
|
1285
|
+
}
|
|
1286
|
+
registerGuard(guard) {
|
|
1287
|
+
debug3("registerGuard: %s", guard.name);
|
|
1288
|
+
this.guards.set(guard.name, guard);
|
|
1289
|
+
}
|
|
1290
|
+
getGuard(name) {
|
|
1291
|
+
const found = this.guards.get(name);
|
|
1292
|
+
debug3("getGuard %s \u2192 %s", name, found ? "matched" : "not found");
|
|
1293
|
+
return found;
|
|
1294
|
+
}
|
|
1295
|
+
getAllGuards() {
|
|
1296
|
+
return [
|
|
1297
|
+
...this.guards.values()
|
|
1298
|
+
];
|
|
1299
|
+
}
|
|
1300
|
+
/**
|
|
1301
|
+
* HTTP routing uses path-pattern matching: `"GET /items/{id}"` matches `"GET /items/42"`.
|
|
1302
|
+
* The routing key format is `"METHOD path"` (e.g., `"GET /items/{id}"`).
|
|
1303
|
+
*/
|
|
1304
|
+
findHttpHandler(routingKey) {
|
|
1305
|
+
const spaceIdx = routingKey.indexOf(" ");
|
|
1306
|
+
if (spaceIdx < 0) return void 0;
|
|
1307
|
+
const method = routingKey.slice(0, spaceIdx);
|
|
1308
|
+
const path = routingKey.slice(spaceIdx + 1);
|
|
1309
|
+
const httpHandlers = this.byType.get("http") ?? [];
|
|
1310
|
+
const found = httpHandlers.find((h) => h.path !== void 0 && h.method !== void 0 && h.method === method && matchRoute(h.path, path));
|
|
1311
|
+
debug3("getHandler http %s \u2192 %s", routingKey, found ? "matched" : "not found");
|
|
1312
|
+
return found;
|
|
1313
|
+
}
|
|
1314
|
+
};
|
|
1315
|
+
function matchRoute(pattern, actual) {
|
|
1316
|
+
const patternParts = pattern.split("/").filter(Boolean);
|
|
1317
|
+
const actualParts = actual.split("/").filter(Boolean);
|
|
1318
|
+
if (patternParts.length !== actualParts.length) return false;
|
|
1319
|
+
return patternParts.every((part, i) => part.startsWith("{") || part === actualParts[i]);
|
|
1320
|
+
}
|
|
1321
|
+
__name(matchRoute, "matchRoute");
|
|
856
1322
|
|
|
857
1323
|
// src/bootstrap/module-graph.ts
|
|
858
1324
|
import "reflect-metadata";
|
|
859
|
-
import
|
|
860
|
-
var
|
|
1325
|
+
import createDebug4 from "debug";
|
|
1326
|
+
var debug4 = createDebug4("celerity:core:bootstrap");
|
|
861
1327
|
function buildModuleGraph(rootModule) {
|
|
862
1328
|
const graph = /* @__PURE__ */ new Map();
|
|
863
1329
|
const resolving = /* @__PURE__ */ new Set();
|
|
864
1330
|
function walk(moduleClass, importChain) {
|
|
865
1331
|
if (graph.has(moduleClass)) {
|
|
866
|
-
|
|
1332
|
+
debug4("walk %s \u2192 already visited", moduleClass.name);
|
|
867
1333
|
return;
|
|
868
1334
|
}
|
|
869
1335
|
if (resolving.has(moduleClass)) {
|
|
@@ -884,6 +1350,7 @@ function buildModuleGraph(rootModule) {
|
|
|
884
1350
|
imports: [],
|
|
885
1351
|
controllers: [],
|
|
886
1352
|
functionHandlers: [],
|
|
1353
|
+
guards: [],
|
|
887
1354
|
providers: []
|
|
888
1355
|
});
|
|
889
1356
|
return;
|
|
@@ -909,9 +1376,15 @@ function buildModuleGraph(rootModule) {
|
|
|
909
1376
|
for (const controller of controllers) {
|
|
910
1377
|
ownTokens.add(controller);
|
|
911
1378
|
}
|
|
1379
|
+
const guards = metadata.guards ?? [];
|
|
1380
|
+
for (const guard of guards) {
|
|
1381
|
+
if (typeof guard === "function") {
|
|
1382
|
+
ownTokens.add(guard);
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
912
1385
|
const exportTokens = new Set(metadata.exports ?? []);
|
|
913
1386
|
resolving.delete(moduleClass);
|
|
914
|
-
|
|
1387
|
+
debug4("walk %s: %d providers, %d controllers, %d guards, %d imports", moduleClass.name, providers.length, controllers.length, guards.length, imports.length);
|
|
915
1388
|
graph.set(moduleClass, {
|
|
916
1389
|
moduleClass,
|
|
917
1390
|
ownTokens,
|
|
@@ -919,6 +1392,7 @@ function buildModuleGraph(rootModule) {
|
|
|
919
1392
|
imports,
|
|
920
1393
|
controllers,
|
|
921
1394
|
functionHandlers: metadata.functionHandlers ?? [],
|
|
1395
|
+
guards,
|
|
922
1396
|
providers
|
|
923
1397
|
});
|
|
924
1398
|
}
|
|
@@ -942,6 +1416,11 @@ function registerModuleGraph(graph, container) {
|
|
|
942
1416
|
container.registerClass(controller);
|
|
943
1417
|
}
|
|
944
1418
|
}
|
|
1419
|
+
for (const guard of node.guards) {
|
|
1420
|
+
if (typeof guard === "function" && !container.has(guard)) {
|
|
1421
|
+
container.registerClass(guard);
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
945
1424
|
}
|
|
946
1425
|
}
|
|
947
1426
|
__name(registerModuleGraph, "registerModuleGraph");
|
|
@@ -988,8 +1467,14 @@ function validateModuleGraph(graph, container) {
|
|
|
988
1467
|
const depTokens = getClassDependencyTokens(controller);
|
|
989
1468
|
checkDependencies(controller, depTokens, visibleTokens, node.moduleClass, graph, container, diagnostics);
|
|
990
1469
|
}
|
|
1470
|
+
for (const guard of node.guards) {
|
|
1471
|
+
if (typeof guard === "function") {
|
|
1472
|
+
const depTokens = getClassDependencyTokens(guard);
|
|
1473
|
+
checkDependencies(guard, depTokens, visibleTokens, node.moduleClass, graph, container, diagnostics);
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
991
1476
|
}
|
|
992
|
-
|
|
1477
|
+
debug4("validateModuleGraph: %d modules, %d diagnostics", graph.size, diagnostics.length);
|
|
993
1478
|
if (diagnostics.length > 0) {
|
|
994
1479
|
const details = diagnostics.map((d) => ` ${d.message}`).join("\n");
|
|
995
1480
|
throw new Error(`Module validation errors:
|
|
@@ -1043,131 +1528,165 @@ function findTokenOwner(token, graph) {
|
|
|
1043
1528
|
}
|
|
1044
1529
|
__name(findTokenOwner, "findTokenOwner");
|
|
1045
1530
|
|
|
1046
|
-
// src/handlers/
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
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
|
-
}
|
|
1531
|
+
// src/handlers/scanners/http.ts
|
|
1532
|
+
import "reflect-metadata";
|
|
1533
|
+
import createDebug5 from "debug";
|
|
1534
|
+
import { joinHandlerPath } from "@celerity-sdk/common";
|
|
1535
|
+
var debug5 = createDebug5("celerity:core:scanner:http");
|
|
1536
|
+
async function scanHttpHandlers(graph, container, registry) {
|
|
1537
|
+
for (const [, node] of graph) {
|
|
1538
|
+
for (const controllerClass of node.controllers) {
|
|
1539
|
+
await scanClassHandler(controllerClass, container, registry);
|
|
1540
|
+
}
|
|
1541
|
+
for (const fnHandler of node.functionHandlers) {
|
|
1542
|
+
scanFunctionHandler(fnHandler, registry);
|
|
1076
1543
|
}
|
|
1077
1544
|
}
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
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));
|
|
1545
|
+
}
|
|
1546
|
+
__name(scanHttpHandlers, "scanHttpHandlers");
|
|
1547
|
+
async function scanHttpGuards(graph, container, registry) {
|
|
1548
|
+
for (const [, node] of graph) {
|
|
1549
|
+
for (const guard of node.guards) {
|
|
1550
|
+
if (typeof guard === "function") {
|
|
1551
|
+
await scanClassGuard(guard, container, registry);
|
|
1552
|
+
} else {
|
|
1553
|
+
scanFunctionGuard(guard, registry);
|
|
1111
1554
|
}
|
|
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
1555
|
}
|
|
1131
1556
|
}
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1557
|
+
}
|
|
1558
|
+
__name(scanHttpGuards, "scanHttpGuards");
|
|
1559
|
+
async function scanModule(moduleClass, container, registry) {
|
|
1560
|
+
const graph = buildModuleGraph(moduleClass);
|
|
1561
|
+
registerModuleGraph(graph, container);
|
|
1562
|
+
await scanHttpHandlers(graph, container, registry);
|
|
1563
|
+
await scanHttpGuards(graph, container, registry);
|
|
1564
|
+
}
|
|
1565
|
+
__name(scanModule, "scanModule");
|
|
1566
|
+
async function scanClassHandler(controllerClass, container, registry) {
|
|
1567
|
+
const controllerMeta = Reflect.getOwnMetadata(CONTROLLER_METADATA, controllerClass);
|
|
1568
|
+
if (!controllerMeta) return;
|
|
1569
|
+
const instance = await container.resolve(controllerClass);
|
|
1570
|
+
const prototype = Object.getPrototypeOf(instance);
|
|
1571
|
+
const methods = Object.getOwnPropertyNames(prototype).filter((name) => name !== "constructor");
|
|
1572
|
+
const classProtectedBy = Reflect.getOwnMetadata(GUARD_PROTECTEDBY_METADATA, controllerClass) ?? [];
|
|
1573
|
+
const classLayers = Reflect.getOwnMetadata(LAYER_METADATA, controllerClass) ?? [];
|
|
1574
|
+
const classCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, controllerClass) ?? {};
|
|
1575
|
+
for (const methodName of methods) {
|
|
1576
|
+
const method = Reflect.getOwnMetadata(HTTP_METHOD_METADATA, prototype, methodName);
|
|
1577
|
+
if (!method) continue;
|
|
1578
|
+
const routePath = Reflect.getOwnMetadata(ROUTE_PATH_METADATA, prototype, methodName) ?? "/";
|
|
1579
|
+
const fullPath = joinHandlerPath(controllerMeta.prefix ?? "", routePath);
|
|
1580
|
+
const methodProtectedBy = Reflect.getOwnMetadata(GUARD_PROTECTEDBY_METADATA, prototype, methodName) ?? [];
|
|
1581
|
+
const methodLayers = Reflect.getOwnMetadata(LAYER_METADATA, prototype, methodName) ?? [];
|
|
1582
|
+
const paramMetadata = Reflect.getOwnMetadata(PARAM_METADATA, prototype, methodName) ?? [];
|
|
1583
|
+
const isPublic = Reflect.getOwnMetadata(PUBLIC_METADATA, prototype, methodName) === true;
|
|
1584
|
+
const methodCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, prototype, methodName) ?? {};
|
|
1585
|
+
const descriptor = Object.getOwnPropertyDescriptor(prototype, methodName);
|
|
1586
|
+
if (!descriptor?.value || typeof descriptor.value !== "function") continue;
|
|
1135
1587
|
const layers = [
|
|
1136
|
-
...
|
|
1588
|
+
...classLayers,
|
|
1589
|
+
...methodLayers
|
|
1137
1590
|
];
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
path: meta.path,
|
|
1152
|
-
method: meta.method,
|
|
1153
|
-
protectedBy: [],
|
|
1591
|
+
const validationSchemas = buildValidationSchemasFromParams(paramMetadata);
|
|
1592
|
+
if (validationSchemas) {
|
|
1593
|
+
layers.unshift(validate(validationSchemas));
|
|
1594
|
+
}
|
|
1595
|
+
debug5("scanClassHandler: %s %s (%s.%s)", method, fullPath, controllerClass.name, methodName);
|
|
1596
|
+
registry.register({
|
|
1597
|
+
type: "http",
|
|
1598
|
+
path: fullPath,
|
|
1599
|
+
method,
|
|
1600
|
+
protectedBy: [
|
|
1601
|
+
...classProtectedBy,
|
|
1602
|
+
...methodProtectedBy
|
|
1603
|
+
],
|
|
1154
1604
|
layers,
|
|
1155
|
-
isPublic
|
|
1156
|
-
paramMetadata
|
|
1157
|
-
customMetadata:
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1605
|
+
isPublic,
|
|
1606
|
+
paramMetadata,
|
|
1607
|
+
customMetadata: {
|
|
1608
|
+
...classCustomMetadata,
|
|
1609
|
+
...methodCustomMetadata
|
|
1610
|
+
},
|
|
1611
|
+
handlerFn: descriptor.value,
|
|
1612
|
+
handlerInstance: instance
|
|
1161
1613
|
});
|
|
1162
1614
|
}
|
|
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
1615
|
}
|
|
1170
|
-
__name(
|
|
1616
|
+
__name(scanClassHandler, "scanClassHandler");
|
|
1617
|
+
function scanFunctionHandler(definition, registry) {
|
|
1618
|
+
if (definition.type !== "http") return;
|
|
1619
|
+
const meta = definition.metadata;
|
|
1620
|
+
const layers = [
|
|
1621
|
+
...meta.layers ?? []
|
|
1622
|
+
];
|
|
1623
|
+
if (meta.schema) {
|
|
1624
|
+
const schemas = {};
|
|
1625
|
+
if (meta.schema.body) schemas.body = meta.schema.body;
|
|
1626
|
+
if (meta.schema.query) schemas.query = meta.schema.query;
|
|
1627
|
+
if (meta.schema.params) schemas.params = meta.schema.params;
|
|
1628
|
+
if (meta.schema.headers) schemas.headers = meta.schema.headers;
|
|
1629
|
+
if (Object.keys(schemas).length > 0) {
|
|
1630
|
+
layers.unshift(validate(schemas));
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
debug5("scanFunctionHandler: %s", definition.id ?? (meta.method && meta.path ? `${meta.method} ${meta.path}` : "(no route)"));
|
|
1634
|
+
registry.register({
|
|
1635
|
+
type: "http",
|
|
1636
|
+
id: definition.id,
|
|
1637
|
+
path: meta.path,
|
|
1638
|
+
method: meta.method,
|
|
1639
|
+
protectedBy: [],
|
|
1640
|
+
layers,
|
|
1641
|
+
isPublic: false,
|
|
1642
|
+
paramMetadata: [],
|
|
1643
|
+
customMetadata: meta.customMetadata ?? {},
|
|
1644
|
+
handlerFn: definition.handler,
|
|
1645
|
+
isFunctionHandler: true,
|
|
1646
|
+
injectTokens: meta.inject ?? []
|
|
1647
|
+
});
|
|
1648
|
+
}
|
|
1649
|
+
__name(scanFunctionHandler, "scanFunctionHandler");
|
|
1650
|
+
async function scanClassGuard(guardClass, container, registry) {
|
|
1651
|
+
const guardName = Reflect.getOwnMetadata(GUARD_CUSTOM_METADATA, guardClass);
|
|
1652
|
+
if (!guardName) return;
|
|
1653
|
+
const instance = await container.resolve(guardClass);
|
|
1654
|
+
const prototype = Object.getPrototypeOf(instance);
|
|
1655
|
+
const descriptor = Object.getOwnPropertyDescriptor(prototype, "check");
|
|
1656
|
+
if (!descriptor?.value || typeof descriptor.value !== "function") {
|
|
1657
|
+
debug5("scanClassGuard: %s has no check() method, skipping", guardClass.name);
|
|
1658
|
+
return;
|
|
1659
|
+
}
|
|
1660
|
+
const paramMetadata = Reflect.getOwnMetadata(PARAM_METADATA, prototype, "check") ?? [];
|
|
1661
|
+
const customMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, guardClass) ?? {};
|
|
1662
|
+
debug5("scanClassGuard: %s (name=%s)", guardClass.name, guardName);
|
|
1663
|
+
registry.registerGuard({
|
|
1664
|
+
name: guardName,
|
|
1665
|
+
handlerFn: descriptor.value,
|
|
1666
|
+
handlerInstance: instance,
|
|
1667
|
+
paramMetadata,
|
|
1668
|
+
customMetadata
|
|
1669
|
+
});
|
|
1670
|
+
}
|
|
1671
|
+
__name(scanClassGuard, "scanClassGuard");
|
|
1672
|
+
function scanFunctionGuard(definition, registry) {
|
|
1673
|
+
const name = definition.name;
|
|
1674
|
+
if (!name) {
|
|
1675
|
+
debug5("scanFunctionGuard: no name, skipping");
|
|
1676
|
+
return;
|
|
1677
|
+
}
|
|
1678
|
+
const meta = definition.metadata ?? {};
|
|
1679
|
+
debug5("scanFunctionGuard: %s", name);
|
|
1680
|
+
registry.registerGuard({
|
|
1681
|
+
name,
|
|
1682
|
+
handlerFn: definition.handler,
|
|
1683
|
+
customMetadata: meta.customMetadata ?? {},
|
|
1684
|
+
paramMetadata: [],
|
|
1685
|
+
isFunctionGuard: true,
|
|
1686
|
+
injectTokens: meta.inject ?? []
|
|
1687
|
+
});
|
|
1688
|
+
}
|
|
1689
|
+
__name(scanFunctionGuard, "scanFunctionGuard");
|
|
1171
1690
|
var PARAM_TYPE_TO_SCHEMA_KEY = {
|
|
1172
1691
|
body: "body",
|
|
1173
1692
|
query: "query",
|
|
@@ -1229,26 +1748,381 @@ function composeKeySchemas(keySchemas) {
|
|
|
1229
1748
|
}
|
|
1230
1749
|
__name(composeKeySchemas, "composeKeySchemas");
|
|
1231
1750
|
|
|
1232
|
-
// src/
|
|
1233
|
-
|
|
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
|
|
1751
|
+
// src/handlers/scanners/websocket.ts
|
|
1752
|
+
import "reflect-metadata";
|
|
1250
1753
|
import createDebug6 from "debug";
|
|
1251
|
-
var debug6 = createDebug6("celerity:core:
|
|
1754
|
+
var debug6 = createDebug6("celerity:core:scanner:websocket");
|
|
1755
|
+
async function scanWebSocketHandlers(graph, container, registry) {
|
|
1756
|
+
for (const [, node] of graph) {
|
|
1757
|
+
for (const controllerClass of node.controllers) {
|
|
1758
|
+
await scanClassHandler2(controllerClass, container, registry);
|
|
1759
|
+
}
|
|
1760
|
+
for (const fnHandler of node.functionHandlers) {
|
|
1761
|
+
scanFunctionHandler2(fnHandler, registry);
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
__name(scanWebSocketHandlers, "scanWebSocketHandlers");
|
|
1766
|
+
async function scanClassHandler2(controllerClass, container, registry) {
|
|
1767
|
+
const isWsController = Reflect.getOwnMetadata(WEBSOCKET_CONTROLLER_METADATA, controllerClass);
|
|
1768
|
+
if (!isWsController) return;
|
|
1769
|
+
const instance = await container.resolve(controllerClass);
|
|
1770
|
+
const prototype = Object.getPrototypeOf(instance);
|
|
1771
|
+
const methods = Object.getOwnPropertyNames(prototype).filter((name) => name !== "constructor");
|
|
1772
|
+
const classProtectedBy = Reflect.getOwnMetadata(GUARD_PROTECTEDBY_METADATA, controllerClass) ?? [];
|
|
1773
|
+
const classLayers = Reflect.getOwnMetadata(LAYER_METADATA, controllerClass) ?? [];
|
|
1774
|
+
const classCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, controllerClass) ?? {};
|
|
1775
|
+
const classIsPublic = Reflect.getOwnMetadata(PUBLIC_METADATA, controllerClass) === true;
|
|
1776
|
+
for (const methodName of methods) {
|
|
1777
|
+
const eventMeta = Reflect.getOwnMetadata(WEBSOCKET_EVENT_METADATA, prototype, methodName);
|
|
1778
|
+
if (!eventMeta) continue;
|
|
1779
|
+
const methodLayers = Reflect.getOwnMetadata(LAYER_METADATA, prototype, methodName) ?? [];
|
|
1780
|
+
const paramMetadata = Reflect.getOwnMetadata(PARAM_METADATA, prototype, methodName) ?? [];
|
|
1781
|
+
const methodCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, prototype, methodName) ?? {};
|
|
1782
|
+
const descriptor = Object.getOwnPropertyDescriptor(prototype, methodName);
|
|
1783
|
+
if (!descriptor?.value || typeof descriptor.value !== "function") continue;
|
|
1784
|
+
debug6("scanClassHandler: %s %s (%s.%s)", eventMeta.eventType, eventMeta.route, controllerClass.name, methodName);
|
|
1785
|
+
const layers = [
|
|
1786
|
+
...classLayers,
|
|
1787
|
+
...methodLayers
|
|
1788
|
+
];
|
|
1789
|
+
const msgBodyParam = paramMetadata.find((p) => p.type === "messageBody");
|
|
1790
|
+
if (msgBodyParam?.schema) {
|
|
1791
|
+
layers.unshift(validate({
|
|
1792
|
+
wsMessageBody: msgBodyParam.schema
|
|
1793
|
+
}));
|
|
1794
|
+
}
|
|
1795
|
+
registry.register({
|
|
1796
|
+
type: "websocket",
|
|
1797
|
+
route: eventMeta.route,
|
|
1798
|
+
protectedBy: classProtectedBy,
|
|
1799
|
+
layers,
|
|
1800
|
+
isPublic: classIsPublic,
|
|
1801
|
+
paramMetadata,
|
|
1802
|
+
customMetadata: {
|
|
1803
|
+
...classCustomMetadata,
|
|
1804
|
+
...methodCustomMetadata
|
|
1805
|
+
},
|
|
1806
|
+
handlerFn: descriptor.value,
|
|
1807
|
+
handlerInstance: instance
|
|
1808
|
+
});
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
__name(scanClassHandler2, "scanClassHandler");
|
|
1812
|
+
function scanFunctionHandler2(definition, registry) {
|
|
1813
|
+
if (definition.type !== "websocket") return;
|
|
1814
|
+
const meta = definition.metadata;
|
|
1815
|
+
const layers = [
|
|
1816
|
+
...meta.layers ?? []
|
|
1817
|
+
];
|
|
1818
|
+
if (meta.schema) {
|
|
1819
|
+
layers.unshift(validate({
|
|
1820
|
+
wsMessageBody: meta.schema
|
|
1821
|
+
}));
|
|
1822
|
+
}
|
|
1823
|
+
debug6("scanFunctionHandler: %s", definition.id ?? meta.route ?? "(no route)");
|
|
1824
|
+
registry.register({
|
|
1825
|
+
type: "websocket",
|
|
1826
|
+
id: definition.id,
|
|
1827
|
+
route: meta.route ?? "$default",
|
|
1828
|
+
protectedBy: meta.protectedBy ?? [],
|
|
1829
|
+
layers,
|
|
1830
|
+
isPublic: false,
|
|
1831
|
+
paramMetadata: [],
|
|
1832
|
+
customMetadata: meta.customMetadata ?? {},
|
|
1833
|
+
handlerFn: definition.handler,
|
|
1834
|
+
isFunctionHandler: true,
|
|
1835
|
+
injectTokens: meta.inject ?? []
|
|
1836
|
+
});
|
|
1837
|
+
}
|
|
1838
|
+
__name(scanFunctionHandler2, "scanFunctionHandler");
|
|
1839
|
+
|
|
1840
|
+
// src/handlers/scanners/consumer.ts
|
|
1841
|
+
import "reflect-metadata";
|
|
1842
|
+
import createDebug7 from "debug";
|
|
1843
|
+
var debug7 = createDebug7("celerity:core:scanner:consumer");
|
|
1844
|
+
async function scanConsumerHandlers(graph, container, registry) {
|
|
1845
|
+
for (const [, node] of graph) {
|
|
1846
|
+
for (const controllerClass of node.controllers) {
|
|
1847
|
+
await scanClassHandler3(controllerClass, container, registry);
|
|
1848
|
+
}
|
|
1849
|
+
for (const fnHandler of node.functionHandlers) {
|
|
1850
|
+
scanFunctionHandler3(fnHandler, registry);
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
__name(scanConsumerHandlers, "scanConsumerHandlers");
|
|
1855
|
+
async function scanClassHandler3(controllerClass, container, registry) {
|
|
1856
|
+
const consumerMeta = Reflect.getOwnMetadata(CONSUMER_METADATA, controllerClass);
|
|
1857
|
+
if (!consumerMeta) return;
|
|
1858
|
+
const instance = await container.resolve(controllerClass);
|
|
1859
|
+
const prototype = Object.getPrototypeOf(instance);
|
|
1860
|
+
const methods = Object.getOwnPropertyNames(prototype).filter((name) => name !== "constructor");
|
|
1861
|
+
const classLayers = Reflect.getOwnMetadata(LAYER_METADATA, controllerClass) ?? [];
|
|
1862
|
+
const classCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, controllerClass) ?? {};
|
|
1863
|
+
for (const methodName of methods) {
|
|
1864
|
+
const handlerMeta = Reflect.getOwnMetadata(CONSUMER_HANDLER_METADATA, prototype, methodName);
|
|
1865
|
+
if (!handlerMeta) continue;
|
|
1866
|
+
const methodLayers = Reflect.getOwnMetadata(LAYER_METADATA, prototype, methodName) ?? [];
|
|
1867
|
+
const paramMetadata = Reflect.getOwnMetadata(PARAM_METADATA, prototype, methodName) ?? [];
|
|
1868
|
+
const methodCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, prototype, methodName) ?? {};
|
|
1869
|
+
const descriptor = Object.getOwnPropertyDescriptor(prototype, methodName);
|
|
1870
|
+
if (!descriptor?.value || typeof descriptor.value !== "function") continue;
|
|
1871
|
+
const handlerTag = handlerMeta.route ?? methodName;
|
|
1872
|
+
const layers = [
|
|
1873
|
+
...classLayers,
|
|
1874
|
+
...methodLayers
|
|
1875
|
+
];
|
|
1876
|
+
const messageParam = paramMetadata.find((p) => p.type === "messages");
|
|
1877
|
+
if (messageParam?.schema) {
|
|
1878
|
+
layers.unshift(validate({
|
|
1879
|
+
consumerMessage: messageParam.schema
|
|
1880
|
+
}));
|
|
1881
|
+
}
|
|
1882
|
+
debug7("scanClassHandler: tag=%s (%s.%s)", handlerTag, controllerClass.name, methodName);
|
|
1883
|
+
registry.register({
|
|
1884
|
+
type: "consumer",
|
|
1885
|
+
handlerTag,
|
|
1886
|
+
layers,
|
|
1887
|
+
paramMetadata,
|
|
1888
|
+
customMetadata: {
|
|
1889
|
+
...classCustomMetadata,
|
|
1890
|
+
...methodCustomMetadata
|
|
1891
|
+
},
|
|
1892
|
+
handlerFn: descriptor.value,
|
|
1893
|
+
handlerInstance: instance
|
|
1894
|
+
});
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
__name(scanClassHandler3, "scanClassHandler");
|
|
1898
|
+
function scanFunctionHandler3(definition, registry) {
|
|
1899
|
+
if (definition.type !== "consumer") return;
|
|
1900
|
+
const meta = definition.metadata;
|
|
1901
|
+
const handlerTag = meta.route ?? definition.id ?? "default";
|
|
1902
|
+
const layers = [
|
|
1903
|
+
...meta.layers ?? []
|
|
1904
|
+
];
|
|
1905
|
+
if (meta.messageSchema) {
|
|
1906
|
+
layers.unshift(validate({
|
|
1907
|
+
consumerMessage: meta.messageSchema
|
|
1908
|
+
}));
|
|
1909
|
+
}
|
|
1910
|
+
debug7("scanFunctionHandler: tag=%s", handlerTag);
|
|
1911
|
+
registry.register({
|
|
1912
|
+
type: "consumer",
|
|
1913
|
+
id: definition.id,
|
|
1914
|
+
handlerTag,
|
|
1915
|
+
layers,
|
|
1916
|
+
paramMetadata: [],
|
|
1917
|
+
customMetadata: meta.customMetadata ?? {},
|
|
1918
|
+
handlerFn: definition.handler,
|
|
1919
|
+
isFunctionHandler: true,
|
|
1920
|
+
injectTokens: meta.inject ?? []
|
|
1921
|
+
});
|
|
1922
|
+
}
|
|
1923
|
+
__name(scanFunctionHandler3, "scanFunctionHandler");
|
|
1924
|
+
|
|
1925
|
+
// src/handlers/scanners/schedule.ts
|
|
1926
|
+
import "reflect-metadata";
|
|
1927
|
+
import createDebug8 from "debug";
|
|
1928
|
+
var debug8 = createDebug8("celerity:core:scanner:schedule");
|
|
1929
|
+
async function scanScheduleHandlers(graph, container, registry) {
|
|
1930
|
+
for (const [, node] of graph) {
|
|
1931
|
+
for (const controllerClass of node.controllers) {
|
|
1932
|
+
await scanClassHandler4(controllerClass, container, registry);
|
|
1933
|
+
}
|
|
1934
|
+
for (const fnHandler of node.functionHandlers) {
|
|
1935
|
+
scanFunctionHandler4(fnHandler, registry);
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
__name(scanScheduleHandlers, "scanScheduleHandlers");
|
|
1940
|
+
async function scanClassHandler4(controllerClass, container, registry) {
|
|
1941
|
+
const instance = await container.resolve(controllerClass);
|
|
1942
|
+
const prototype = Object.getPrototypeOf(instance);
|
|
1943
|
+
const methods = Object.getOwnPropertyNames(prototype).filter((name) => name !== "constructor");
|
|
1944
|
+
const classLayers = Reflect.getOwnMetadata(LAYER_METADATA, controllerClass) ?? [];
|
|
1945
|
+
const classCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, controllerClass) ?? {};
|
|
1946
|
+
for (const methodName of methods) {
|
|
1947
|
+
const handlerMeta = Reflect.getOwnMetadata(SCHEDULE_HANDLER_METADATA, prototype, methodName);
|
|
1948
|
+
if (!handlerMeta) continue;
|
|
1949
|
+
const methodLayers = Reflect.getOwnMetadata(LAYER_METADATA, prototype, methodName) ?? [];
|
|
1950
|
+
const paramMetadata = Reflect.getOwnMetadata(PARAM_METADATA, prototype, methodName) ?? [];
|
|
1951
|
+
const methodCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, prototype, methodName) ?? {};
|
|
1952
|
+
const descriptor = Object.getOwnPropertyDescriptor(prototype, methodName);
|
|
1953
|
+
if (!descriptor?.value || typeof descriptor.value !== "function") continue;
|
|
1954
|
+
const handlerTag = handlerMeta.scheduleId ?? methodName;
|
|
1955
|
+
const layers = [
|
|
1956
|
+
...classLayers,
|
|
1957
|
+
...methodLayers
|
|
1958
|
+
];
|
|
1959
|
+
const inputParam = paramMetadata.find((p) => p.type === "scheduleInput");
|
|
1960
|
+
if (inputParam?.schema) {
|
|
1961
|
+
layers.unshift(validate({
|
|
1962
|
+
scheduleInput: inputParam.schema
|
|
1963
|
+
}));
|
|
1964
|
+
}
|
|
1965
|
+
debug8("scanClassHandler: tag=%s (%s.%s)", handlerTag, controllerClass.name, methodName);
|
|
1966
|
+
registry.register({
|
|
1967
|
+
type: "schedule",
|
|
1968
|
+
handlerTag,
|
|
1969
|
+
layers,
|
|
1970
|
+
paramMetadata,
|
|
1971
|
+
customMetadata: {
|
|
1972
|
+
...classCustomMetadata,
|
|
1973
|
+
...methodCustomMetadata,
|
|
1974
|
+
...handlerMeta.schedule ? {
|
|
1975
|
+
schedule: handlerMeta.schedule
|
|
1976
|
+
} : {},
|
|
1977
|
+
...handlerMeta.scheduleId ? {
|
|
1978
|
+
scheduleId: handlerMeta.scheduleId
|
|
1979
|
+
} : {}
|
|
1980
|
+
},
|
|
1981
|
+
handlerFn: descriptor.value,
|
|
1982
|
+
handlerInstance: instance
|
|
1983
|
+
});
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
__name(scanClassHandler4, "scanClassHandler");
|
|
1987
|
+
function scanFunctionHandler4(definition, registry) {
|
|
1988
|
+
if (definition.type !== "schedule") return;
|
|
1989
|
+
const meta = definition.metadata;
|
|
1990
|
+
const handlerTag = meta.scheduleId ?? definition.id ?? "default";
|
|
1991
|
+
const layers = [
|
|
1992
|
+
...meta.layers ?? []
|
|
1993
|
+
];
|
|
1994
|
+
if (meta.schema) {
|
|
1995
|
+
layers.unshift(validate({
|
|
1996
|
+
scheduleInput: meta.schema
|
|
1997
|
+
}));
|
|
1998
|
+
}
|
|
1999
|
+
const customMetadata = {
|
|
2000
|
+
...meta.customMetadata ?? {}
|
|
2001
|
+
};
|
|
2002
|
+
if (meta.schedule) customMetadata.schedule = meta.schedule;
|
|
2003
|
+
if (meta.scheduleId) customMetadata.scheduleId = meta.scheduleId;
|
|
2004
|
+
debug8("scanFunctionHandler: tag=%s", handlerTag);
|
|
2005
|
+
registry.register({
|
|
2006
|
+
type: "schedule",
|
|
2007
|
+
id: definition.id,
|
|
2008
|
+
handlerTag,
|
|
2009
|
+
layers,
|
|
2010
|
+
paramMetadata: [],
|
|
2011
|
+
customMetadata,
|
|
2012
|
+
handlerFn: definition.handler,
|
|
2013
|
+
isFunctionHandler: true,
|
|
2014
|
+
injectTokens: meta.inject ?? []
|
|
2015
|
+
});
|
|
2016
|
+
}
|
|
2017
|
+
__name(scanFunctionHandler4, "scanFunctionHandler");
|
|
2018
|
+
|
|
2019
|
+
// src/handlers/scanners/custom.ts
|
|
2020
|
+
import "reflect-metadata";
|
|
2021
|
+
import createDebug9 from "debug";
|
|
2022
|
+
var debug9 = createDebug9("celerity:core:scanner:custom");
|
|
2023
|
+
async function scanCustomHandlers(graph, container, registry) {
|
|
2024
|
+
for (const [, node] of graph) {
|
|
2025
|
+
for (const controllerClass of node.controllers) {
|
|
2026
|
+
await scanClassHandler5(controllerClass, container, registry);
|
|
2027
|
+
}
|
|
2028
|
+
for (const fnHandler of node.functionHandlers) {
|
|
2029
|
+
scanFunctionHandler5(fnHandler, registry);
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
2033
|
+
__name(scanCustomHandlers, "scanCustomHandlers");
|
|
2034
|
+
async function scanClassHandler5(controllerClass, container, registry) {
|
|
2035
|
+
const instance = await container.resolve(controllerClass);
|
|
2036
|
+
const prototype = Object.getPrototypeOf(instance);
|
|
2037
|
+
const methods = Object.getOwnPropertyNames(prototype).filter((name) => name !== "constructor");
|
|
2038
|
+
const classLayers = Reflect.getOwnMetadata(LAYER_METADATA, controllerClass) ?? [];
|
|
2039
|
+
const classCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, controllerClass) ?? {};
|
|
2040
|
+
for (const methodName of methods) {
|
|
2041
|
+
const invokeMeta = Reflect.getOwnMetadata(INVOKE_METADATA, prototype, methodName);
|
|
2042
|
+
if (!invokeMeta) continue;
|
|
2043
|
+
const methodLayers = Reflect.getOwnMetadata(LAYER_METADATA, prototype, methodName) ?? [];
|
|
2044
|
+
const paramMetadata = Reflect.getOwnMetadata(PARAM_METADATA, prototype, methodName) ?? [];
|
|
2045
|
+
const methodCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, prototype, methodName) ?? {};
|
|
2046
|
+
const descriptor = Object.getOwnPropertyDescriptor(prototype, methodName);
|
|
2047
|
+
if (!descriptor?.value || typeof descriptor.value !== "function") continue;
|
|
2048
|
+
const layers = [
|
|
2049
|
+
...classLayers,
|
|
2050
|
+
...methodLayers
|
|
2051
|
+
];
|
|
2052
|
+
const payloadParam = paramMetadata.find((p) => p.type === "payload");
|
|
2053
|
+
if (payloadParam?.schema) {
|
|
2054
|
+
layers.unshift(validate({
|
|
2055
|
+
customPayload: payloadParam.schema
|
|
2056
|
+
}));
|
|
2057
|
+
}
|
|
2058
|
+
debug9("scanClassHandler: name=%s (%s.%s)", invokeMeta.name, controllerClass.name, methodName);
|
|
2059
|
+
registry.register({
|
|
2060
|
+
type: "custom",
|
|
2061
|
+
name: invokeMeta.name,
|
|
2062
|
+
layers,
|
|
2063
|
+
paramMetadata,
|
|
2064
|
+
customMetadata: {
|
|
2065
|
+
...classCustomMetadata,
|
|
2066
|
+
...methodCustomMetadata
|
|
2067
|
+
},
|
|
2068
|
+
handlerFn: descriptor.value,
|
|
2069
|
+
handlerInstance: instance
|
|
2070
|
+
});
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
__name(scanClassHandler5, "scanClassHandler");
|
|
2074
|
+
function scanFunctionHandler5(definition, registry) {
|
|
2075
|
+
if (definition.type !== "custom") return;
|
|
2076
|
+
const meta = definition.metadata;
|
|
2077
|
+
const name = meta.name ?? definition.id ?? "default";
|
|
2078
|
+
const layers = [
|
|
2079
|
+
...meta.layers ?? []
|
|
2080
|
+
];
|
|
2081
|
+
if (meta.schema) {
|
|
2082
|
+
layers.unshift(validate({
|
|
2083
|
+
customPayload: meta.schema
|
|
2084
|
+
}));
|
|
2085
|
+
}
|
|
2086
|
+
debug9("scanFunctionHandler: name=%s", name);
|
|
2087
|
+
registry.register({
|
|
2088
|
+
type: "custom",
|
|
2089
|
+
id: definition.id,
|
|
2090
|
+
name,
|
|
2091
|
+
layers,
|
|
2092
|
+
paramMetadata: [],
|
|
2093
|
+
customMetadata: meta.customMetadata ?? {},
|
|
2094
|
+
handlerFn: definition.handler,
|
|
2095
|
+
isFunctionHandler: true,
|
|
2096
|
+
injectTokens: meta.inject ?? []
|
|
2097
|
+
});
|
|
2098
|
+
}
|
|
2099
|
+
__name(scanFunctionHandler5, "scanFunctionHandler");
|
|
2100
|
+
|
|
2101
|
+
// src/bootstrap/bootstrap.ts
|
|
2102
|
+
var debug10 = createDebug10("celerity:core:bootstrap");
|
|
2103
|
+
async function bootstrap(rootModule) {
|
|
2104
|
+
debug10("bootstrap: starting from %s", rootModule.name);
|
|
2105
|
+
const container = new Container();
|
|
2106
|
+
const registry = new HandlerRegistry();
|
|
2107
|
+
const graph = walkModuleGraph(rootModule, container);
|
|
2108
|
+
validateModuleGraph(graph, container);
|
|
2109
|
+
await scanHttpHandlers(graph, container, registry);
|
|
2110
|
+
await scanHttpGuards(graph, container, registry);
|
|
2111
|
+
await scanWebSocketHandlers(graph, container, registry);
|
|
2112
|
+
await scanConsumerHandlers(graph, container, registry);
|
|
2113
|
+
await scanScheduleHandlers(graph, container, registry);
|
|
2114
|
+
await scanCustomHandlers(graph, container, registry);
|
|
2115
|
+
debug10("bootstrap: complete \u2014 %d modules, %d handlers", graph.size, registry.getAllHandlers().length);
|
|
2116
|
+
return {
|
|
2117
|
+
container,
|
|
2118
|
+
registry
|
|
2119
|
+
};
|
|
2120
|
+
}
|
|
2121
|
+
__name(bootstrap, "bootstrap");
|
|
2122
|
+
|
|
2123
|
+
// src/application/application.ts
|
|
2124
|
+
import createDebug11 from "debug";
|
|
2125
|
+
var debug11 = createDebug11("celerity:core:factory");
|
|
1252
2126
|
var CelerityApplication = class {
|
|
1253
2127
|
static {
|
|
1254
2128
|
__name(this, "CelerityApplication");
|
|
@@ -1272,7 +2146,7 @@ var CelerityApplication = class {
|
|
|
1272
2146
|
}
|
|
1273
2147
|
}
|
|
1274
2148
|
async close() {
|
|
1275
|
-
|
|
2149
|
+
debug11("close: shutting down application");
|
|
1276
2150
|
if (this.runtimeApp && typeof this.runtimeApp === "object") {
|
|
1277
2151
|
const app = this.runtimeApp;
|
|
1278
2152
|
await app.shutdown();
|
|
@@ -1298,6 +2172,13 @@ var CelerityApplication = class {
|
|
|
1298
2172
|
};
|
|
1299
2173
|
|
|
1300
2174
|
// src/application/serverless.ts
|
|
2175
|
+
var HANDLER_CREATORS = {
|
|
2176
|
+
http: /* @__PURE__ */ __name((adapter, registry, options) => adapter.createHttpHandler(registry, options), "http"),
|
|
2177
|
+
websocket: /* @__PURE__ */ __name((adapter, registry, options) => adapter.createWebSocketHandler(registry, options), "websocket"),
|
|
2178
|
+
consumer: /* @__PURE__ */ __name((adapter, registry, options) => adapter.createConsumerHandler(registry, options), "consumer"),
|
|
2179
|
+
schedule: /* @__PURE__ */ __name((adapter, registry, options) => adapter.createScheduleHandler(registry, options), "schedule"),
|
|
2180
|
+
custom: /* @__PURE__ */ __name((adapter, registry, options) => adapter.createCustomHandler(registry, options), "custom")
|
|
2181
|
+
};
|
|
1301
2182
|
var ServerlessApplication = class {
|
|
1302
2183
|
static {
|
|
1303
2184
|
__name(this, "ServerlessApplication");
|
|
@@ -1315,12 +2196,16 @@ var ServerlessApplication = class {
|
|
|
1315
2196
|
this.systemLayers = systemLayers;
|
|
1316
2197
|
this.appLayers = appLayers;
|
|
1317
2198
|
}
|
|
1318
|
-
|
|
1319
|
-
|
|
2199
|
+
createHandler(type) {
|
|
2200
|
+
const options = {
|
|
1320
2201
|
container: this.container,
|
|
1321
2202
|
systemLayers: this.systemLayers,
|
|
1322
2203
|
appLayers: this.appLayers
|
|
1323
|
-
}
|
|
2204
|
+
};
|
|
2205
|
+
return HANDLER_CREATORS[type](this.adapter, this.registry, options);
|
|
2206
|
+
}
|
|
2207
|
+
async start(type = "http") {
|
|
2208
|
+
this.handler = this.createHandler(type);
|
|
1324
2209
|
return this.handler;
|
|
1325
2210
|
}
|
|
1326
2211
|
async close() {
|
|
@@ -1344,8 +2229,8 @@ var ServerlessApplication = class {
|
|
|
1344
2229
|
}
|
|
1345
2230
|
};
|
|
1346
2231
|
|
|
1347
|
-
// src/handlers/pipeline.ts
|
|
1348
|
-
import
|
|
2232
|
+
// src/handlers/http-pipeline.ts
|
|
2233
|
+
import createDebug12 from "debug";
|
|
1349
2234
|
|
|
1350
2235
|
// src/functions/context.ts
|
|
1351
2236
|
function buildHttpRequest(request, metadata) {
|
|
@@ -1387,12 +2272,17 @@ function buildHttpContext(request, metadata, container, logger) {
|
|
|
1387
2272
|
}
|
|
1388
2273
|
__name(buildHttpContext, "buildHttpContext");
|
|
1389
2274
|
|
|
1390
|
-
// src/handlers/pipeline.ts
|
|
1391
|
-
var
|
|
1392
|
-
async function
|
|
2275
|
+
// src/handlers/http-pipeline.ts
|
|
2276
|
+
var debug12 = createDebug12("celerity:core:pipeline");
|
|
2277
|
+
async function executeHttpPipeline(handler, request, options) {
|
|
1393
2278
|
const context = {
|
|
1394
2279
|
request,
|
|
1395
|
-
metadata: new HandlerMetadataStore(
|
|
2280
|
+
metadata: new HandlerMetadataStore({
|
|
2281
|
+
...handler.customMetadata ?? {},
|
|
2282
|
+
...options.handlerName ? {
|
|
2283
|
+
handlerName: options.handlerName
|
|
2284
|
+
} : {}
|
|
2285
|
+
}),
|
|
1396
2286
|
container: options.container
|
|
1397
2287
|
};
|
|
1398
2288
|
const allLayers = [
|
|
@@ -1400,19 +2290,19 @@ async function executeHandlerPipeline(handler, request, options) {
|
|
|
1400
2290
|
...options.appLayers ?? [],
|
|
1401
2291
|
...handler.layers
|
|
1402
2292
|
];
|
|
1403
|
-
|
|
2293
|
+
debug12("%s %s \u2014 %d layers", request.method, request.path, allLayers.length);
|
|
1404
2294
|
try {
|
|
1405
2295
|
const response = await runLayerPipeline(allLayers, context, async () => {
|
|
1406
|
-
const
|
|
1407
|
-
|
|
2296
|
+
const style = handler.isFunctionHandler ? "function" : "class";
|
|
2297
|
+
debug12("invoking %s handler", style);
|
|
1408
2298
|
const result = handler.isFunctionHandler ? await invokeFunctionHandler(handler, context) : await invokeClassHandler(handler, context);
|
|
1409
2299
|
return normalizeResponse(result);
|
|
1410
|
-
});
|
|
1411
|
-
|
|
2300
|
+
}, "http");
|
|
2301
|
+
debug12("response %d", response.status);
|
|
1412
2302
|
return response;
|
|
1413
2303
|
} catch (error) {
|
|
1414
2304
|
if (error instanceof HttpException) {
|
|
1415
|
-
|
|
2305
|
+
debug12("HttpException %d: %s", error.statusCode, error.message);
|
|
1416
2306
|
return {
|
|
1417
2307
|
status: error.statusCode,
|
|
1418
2308
|
headers: {
|
|
@@ -1448,7 +2338,7 @@ async function executeHandlerPipeline(handler, request, options) {
|
|
|
1448
2338
|
};
|
|
1449
2339
|
}
|
|
1450
2340
|
}
|
|
1451
|
-
__name(
|
|
2341
|
+
__name(executeHttpPipeline, "executeHttpPipeline");
|
|
1452
2342
|
async function invokeClassHandler(handler, context) {
|
|
1453
2343
|
const args = [];
|
|
1454
2344
|
const sorted = [
|
|
@@ -1517,6 +2407,370 @@ function isHttpResponse(value) {
|
|
|
1517
2407
|
}
|
|
1518
2408
|
__name(isHttpResponse, "isHttpResponse");
|
|
1519
2409
|
|
|
2410
|
+
// src/handlers/websocket-pipeline.ts
|
|
2411
|
+
import createDebug13 from "debug";
|
|
2412
|
+
var debug13 = createDebug13("celerity:core:ws-pipeline");
|
|
2413
|
+
async function executeWebSocketPipeline(handler, message, options) {
|
|
2414
|
+
const context = {
|
|
2415
|
+
message,
|
|
2416
|
+
metadata: new HandlerMetadataStore({
|
|
2417
|
+
...handler.customMetadata ?? {},
|
|
2418
|
+
...options.handlerName ? {
|
|
2419
|
+
handlerName: options.handlerName
|
|
2420
|
+
} : {}
|
|
2421
|
+
}),
|
|
2422
|
+
container: options.container
|
|
2423
|
+
};
|
|
2424
|
+
const allLayers = [
|
|
2425
|
+
...options.systemLayers ?? [],
|
|
2426
|
+
...options.appLayers ?? [],
|
|
2427
|
+
...handler.layers
|
|
2428
|
+
];
|
|
2429
|
+
debug13("%s %s \u2014 %d layers", message.eventType, message.connectionId, allLayers.length);
|
|
2430
|
+
try {
|
|
2431
|
+
await runLayerPipeline(allLayers, context, async () => {
|
|
2432
|
+
const style = handler.isFunctionHandler ? "function" : "class";
|
|
2433
|
+
debug13("invoking %s handler", style);
|
|
2434
|
+
if (handler.isFunctionHandler) {
|
|
2435
|
+
await invokeFunctionHandler2(handler, context);
|
|
2436
|
+
} else {
|
|
2437
|
+
await invokeClassHandler2(handler, context);
|
|
2438
|
+
}
|
|
2439
|
+
}, "websocket");
|
|
2440
|
+
} catch (error) {
|
|
2441
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2442
|
+
if (context.logger) {
|
|
2443
|
+
context.logger.error("Unhandled error in WebSocket handler pipeline", {
|
|
2444
|
+
error: errorMessage,
|
|
2445
|
+
connectionId: message.connectionId,
|
|
2446
|
+
eventType: message.eventType,
|
|
2447
|
+
...error instanceof Error && error.stack ? {
|
|
2448
|
+
stack: error.stack
|
|
2449
|
+
} : {}
|
|
2450
|
+
});
|
|
2451
|
+
} else {
|
|
2452
|
+
console.error("Unhandled error in WebSocket handler pipeline:", error);
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
}
|
|
2456
|
+
__name(executeWebSocketPipeline, "executeWebSocketPipeline");
|
|
2457
|
+
async function invokeClassHandler2(handler, context) {
|
|
2458
|
+
const args = [];
|
|
2459
|
+
const sorted = [
|
|
2460
|
+
...handler.paramMetadata
|
|
2461
|
+
].sort((a, b) => a.index - b.index);
|
|
2462
|
+
for (const meta of sorted) {
|
|
2463
|
+
args[meta.index] = extractWebSocketParam(meta, context);
|
|
2464
|
+
}
|
|
2465
|
+
await handler.handlerFn.apply(handler.handlerInstance, args);
|
|
2466
|
+
}
|
|
2467
|
+
__name(invokeClassHandler2, "invokeClassHandler");
|
|
2468
|
+
async function invokeFunctionHandler2(handler, context) {
|
|
2469
|
+
const validatedBody = context.metadata.get("validatedMessageBody");
|
|
2470
|
+
const message = validatedBody !== void 0 ? {
|
|
2471
|
+
...context.message,
|
|
2472
|
+
jsonBody: validatedBody
|
|
2473
|
+
} : context.message;
|
|
2474
|
+
if (handler.injectTokens && handler.injectTokens.length > 0) {
|
|
2475
|
+
const deps = [];
|
|
2476
|
+
for (const token of handler.injectTokens) {
|
|
2477
|
+
deps.push(await context.container.resolve(token));
|
|
2478
|
+
}
|
|
2479
|
+
await handler.handlerFn(message, context, ...deps);
|
|
2480
|
+
} else {
|
|
2481
|
+
await handler.handlerFn(message, context);
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
__name(invokeFunctionHandler2, "invokeFunctionHandler");
|
|
2485
|
+
function extractWebSocketParam(meta, context) {
|
|
2486
|
+
const { message } = context;
|
|
2487
|
+
switch (meta.type) {
|
|
2488
|
+
case "connectionId":
|
|
2489
|
+
return message.connectionId;
|
|
2490
|
+
case "messageBody": {
|
|
2491
|
+
const validated = context.metadata.get("validatedMessageBody");
|
|
2492
|
+
if (validated !== void 0) return validated;
|
|
2493
|
+
return message.jsonBody;
|
|
2494
|
+
}
|
|
2495
|
+
case "messageId":
|
|
2496
|
+
return message.messageId;
|
|
2497
|
+
case "requestContext":
|
|
2498
|
+
return message.requestContext;
|
|
2499
|
+
case "eventType":
|
|
2500
|
+
return message.eventType;
|
|
2501
|
+
default:
|
|
2502
|
+
return void 0;
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
2505
|
+
__name(extractWebSocketParam, "extractWebSocketParam");
|
|
2506
|
+
|
|
2507
|
+
// src/handlers/consumer-pipeline.ts
|
|
2508
|
+
import createDebug14 from "debug";
|
|
2509
|
+
var debug14 = createDebug14("celerity:core:consumer-pipeline");
|
|
2510
|
+
async function executeConsumerPipeline(handler, event, options) {
|
|
2511
|
+
const context = {
|
|
2512
|
+
event,
|
|
2513
|
+
metadata: new HandlerMetadataStore({
|
|
2514
|
+
...handler.customMetadata ?? {},
|
|
2515
|
+
...options.handlerName ? {
|
|
2516
|
+
handlerName: options.handlerName
|
|
2517
|
+
} : {}
|
|
2518
|
+
}),
|
|
2519
|
+
container: options.container
|
|
2520
|
+
};
|
|
2521
|
+
const allLayers = [
|
|
2522
|
+
...options.systemLayers ?? [],
|
|
2523
|
+
...options.appLayers ?? [],
|
|
2524
|
+
...handler.layers
|
|
2525
|
+
];
|
|
2526
|
+
debug14("tag=%s \u2014 %d messages, %d layers", event.handlerTag, event.messages.length, allLayers.length);
|
|
2527
|
+
let result = {
|
|
2528
|
+
success: true
|
|
2529
|
+
};
|
|
2530
|
+
try {
|
|
2531
|
+
await runLayerPipeline(allLayers, context, async () => {
|
|
2532
|
+
const style = handler.isFunctionHandler ? "function" : "class";
|
|
2533
|
+
debug14("invoking %s handler", style);
|
|
2534
|
+
const validatedMessages = context.metadata.get("validatedMessages");
|
|
2535
|
+
const validationFailures = context.metadata.get("validationFailures") ?? [];
|
|
2536
|
+
const rawMessages = validatedMessages ? void 0 : event.messages;
|
|
2537
|
+
if (handler.isFunctionHandler) {
|
|
2538
|
+
result = await invokeFunctionHandler3(handler, context, validatedMessages, rawMessages);
|
|
2539
|
+
} else {
|
|
2540
|
+
result = await invokeClassHandler3(handler, context, validatedMessages, rawMessages);
|
|
2541
|
+
}
|
|
2542
|
+
if (validationFailures.length > 0) {
|
|
2543
|
+
const existing = result.failures ?? [];
|
|
2544
|
+
result = {
|
|
2545
|
+
...result,
|
|
2546
|
+
success: result.success && validationFailures.length === 0,
|
|
2547
|
+
failures: [
|
|
2548
|
+
...validationFailures,
|
|
2549
|
+
...existing
|
|
2550
|
+
]
|
|
2551
|
+
};
|
|
2552
|
+
}
|
|
2553
|
+
}, "consumer");
|
|
2554
|
+
} catch (error) {
|
|
2555
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2556
|
+
if (context.logger) {
|
|
2557
|
+
context.logger.error("Unhandled error in consumer handler pipeline", {
|
|
2558
|
+
error: errorMessage,
|
|
2559
|
+
handlerTag: event.handlerTag,
|
|
2560
|
+
messageCount: event.messages.length,
|
|
2561
|
+
...error instanceof Error && error.stack ? {
|
|
2562
|
+
stack: error.stack
|
|
2563
|
+
} : {}
|
|
2564
|
+
});
|
|
2565
|
+
} else {
|
|
2566
|
+
console.error("Unhandled error in consumer handler pipeline:", error);
|
|
2567
|
+
}
|
|
2568
|
+
return {
|
|
2569
|
+
success: false,
|
|
2570
|
+
errorMessage
|
|
2571
|
+
};
|
|
2572
|
+
}
|
|
2573
|
+
return result;
|
|
2574
|
+
}
|
|
2575
|
+
__name(executeConsumerPipeline, "executeConsumerPipeline");
|
|
2576
|
+
async function invokeClassHandler3(handler, context, validatedMessages, rawMessages) {
|
|
2577
|
+
const args = [];
|
|
2578
|
+
const sorted = [
|
|
2579
|
+
...handler.paramMetadata
|
|
2580
|
+
].sort((a, b) => a.index - b.index);
|
|
2581
|
+
for (const meta of sorted) {
|
|
2582
|
+
args[meta.index] = extractConsumerParam(meta, context, validatedMessages, rawMessages);
|
|
2583
|
+
}
|
|
2584
|
+
return await handler.handlerFn.apply(handler.handlerInstance, args);
|
|
2585
|
+
}
|
|
2586
|
+
__name(invokeClassHandler3, "invokeClassHandler");
|
|
2587
|
+
async function invokeFunctionHandler3(handler, context, validatedMessages, _rawMessages) {
|
|
2588
|
+
const deps = [];
|
|
2589
|
+
if (handler.injectTokens && handler.injectTokens.length > 0) {
|
|
2590
|
+
for (const token of handler.injectTokens) {
|
|
2591
|
+
deps.push(await context.container.resolve(token));
|
|
2592
|
+
}
|
|
2593
|
+
}
|
|
2594
|
+
const firstArg = validatedMessages ?? context.event;
|
|
2595
|
+
return await handler.handlerFn(firstArg, context, ...deps);
|
|
2596
|
+
}
|
|
2597
|
+
__name(invokeFunctionHandler3, "invokeFunctionHandler");
|
|
2598
|
+
function extractConsumerParam(meta, context, validatedMessages, rawMessages) {
|
|
2599
|
+
switch (meta.type) {
|
|
2600
|
+
case "messages":
|
|
2601
|
+
return validatedMessages ?? rawMessages ?? context.event.messages;
|
|
2602
|
+
case "consumerEvent":
|
|
2603
|
+
return context.event;
|
|
2604
|
+
case "consumerVendor":
|
|
2605
|
+
return context.event.vendor;
|
|
2606
|
+
case "consumerTraceContext":
|
|
2607
|
+
return context.event.traceContext ?? null;
|
|
2608
|
+
default:
|
|
2609
|
+
return void 0;
|
|
2610
|
+
}
|
|
2611
|
+
}
|
|
2612
|
+
__name(extractConsumerParam, "extractConsumerParam");
|
|
2613
|
+
|
|
2614
|
+
// src/handlers/schedule-pipeline.ts
|
|
2615
|
+
import createDebug15 from "debug";
|
|
2616
|
+
var debug15 = createDebug15("celerity:core:schedule-pipeline");
|
|
2617
|
+
async function executeSchedulePipeline(handler, event, options) {
|
|
2618
|
+
const context = {
|
|
2619
|
+
event,
|
|
2620
|
+
metadata: new HandlerMetadataStore({
|
|
2621
|
+
...handler.customMetadata ?? {},
|
|
2622
|
+
...options.handlerName ? {
|
|
2623
|
+
handlerName: options.handlerName
|
|
2624
|
+
} : {}
|
|
2625
|
+
}),
|
|
2626
|
+
container: options.container
|
|
2627
|
+
};
|
|
2628
|
+
const allLayers = [
|
|
2629
|
+
...options.systemLayers ?? [],
|
|
2630
|
+
...options.appLayers ?? [],
|
|
2631
|
+
...handler.layers
|
|
2632
|
+
];
|
|
2633
|
+
debug15("tag=%s \u2014 %d layers", event.handlerTag, allLayers.length);
|
|
2634
|
+
let result = {
|
|
2635
|
+
success: true
|
|
2636
|
+
};
|
|
2637
|
+
try {
|
|
2638
|
+
await runLayerPipeline(allLayers, context, async () => {
|
|
2639
|
+
const style = handler.isFunctionHandler ? "function" : "class";
|
|
2640
|
+
debug15("invoking %s handler", style);
|
|
2641
|
+
const validatedInput = context.metadata.get("validatedInput") ?? event.input;
|
|
2642
|
+
if (handler.isFunctionHandler) {
|
|
2643
|
+
result = await invokeFunctionHandler4(handler, context, validatedInput);
|
|
2644
|
+
} else {
|
|
2645
|
+
result = await invokeClassHandler4(handler, context, validatedInput);
|
|
2646
|
+
}
|
|
2647
|
+
}, "schedule");
|
|
2648
|
+
} catch (error) {
|
|
2649
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2650
|
+
if (context.logger) {
|
|
2651
|
+
context.logger.error("Unhandled error in schedule handler pipeline", {
|
|
2652
|
+
error: errorMessage,
|
|
2653
|
+
handlerTag: event.handlerTag,
|
|
2654
|
+
scheduleId: event.scheduleId,
|
|
2655
|
+
...error instanceof Error && error.stack ? {
|
|
2656
|
+
stack: error.stack
|
|
2657
|
+
} : {}
|
|
2658
|
+
});
|
|
2659
|
+
} else {
|
|
2660
|
+
console.error("Unhandled error in schedule handler pipeline:", error);
|
|
2661
|
+
}
|
|
2662
|
+
return {
|
|
2663
|
+
success: false,
|
|
2664
|
+
errorMessage
|
|
2665
|
+
};
|
|
2666
|
+
}
|
|
2667
|
+
return result;
|
|
2668
|
+
}
|
|
2669
|
+
__name(executeSchedulePipeline, "executeSchedulePipeline");
|
|
2670
|
+
async function invokeClassHandler4(handler, context, validatedInput) {
|
|
2671
|
+
const args = [];
|
|
2672
|
+
const sorted = [
|
|
2673
|
+
...handler.paramMetadata
|
|
2674
|
+
].sort((a, b) => a.index - b.index);
|
|
2675
|
+
for (const meta of sorted) {
|
|
2676
|
+
args[meta.index] = extractScheduleParam(meta, context, validatedInput);
|
|
2677
|
+
}
|
|
2678
|
+
return await handler.handlerFn.apply(handler.handlerInstance, args);
|
|
2679
|
+
}
|
|
2680
|
+
__name(invokeClassHandler4, "invokeClassHandler");
|
|
2681
|
+
async function invokeFunctionHandler4(handler, context, _validatedInput) {
|
|
2682
|
+
const deps = [];
|
|
2683
|
+
if (handler.injectTokens && handler.injectTokens.length > 0) {
|
|
2684
|
+
for (const token of handler.injectTokens) {
|
|
2685
|
+
deps.push(await context.container.resolve(token));
|
|
2686
|
+
}
|
|
2687
|
+
}
|
|
2688
|
+
return await handler.handlerFn(context.event, context, ...deps);
|
|
2689
|
+
}
|
|
2690
|
+
__name(invokeFunctionHandler4, "invokeFunctionHandler");
|
|
2691
|
+
function extractScheduleParam(meta, context, validatedInput) {
|
|
2692
|
+
switch (meta.type) {
|
|
2693
|
+
case "scheduleInput":
|
|
2694
|
+
return validatedInput;
|
|
2695
|
+
case "scheduleId":
|
|
2696
|
+
return context.event.scheduleId;
|
|
2697
|
+
case "scheduleExpression":
|
|
2698
|
+
return context.event.schedule;
|
|
2699
|
+
case "scheduleEvent":
|
|
2700
|
+
return context.event;
|
|
2701
|
+
default:
|
|
2702
|
+
return void 0;
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
__name(extractScheduleParam, "extractScheduleParam");
|
|
2706
|
+
|
|
2707
|
+
// src/handlers/custom-pipeline.ts
|
|
2708
|
+
import createDebug16 from "debug";
|
|
2709
|
+
var debug16 = createDebug16("celerity:core:custom-pipeline");
|
|
2710
|
+
async function executeCustomPipeline(handler, payload, options) {
|
|
2711
|
+
const context = {
|
|
2712
|
+
metadata: new HandlerMetadataStore({
|
|
2713
|
+
...handler.customMetadata ?? {},
|
|
2714
|
+
...options.handlerName ? {
|
|
2715
|
+
handlerName: options.handlerName
|
|
2716
|
+
} : {},
|
|
2717
|
+
rawPayload: payload
|
|
2718
|
+
}),
|
|
2719
|
+
container: options.container
|
|
2720
|
+
};
|
|
2721
|
+
const allLayers = [
|
|
2722
|
+
...options.systemLayers ?? [],
|
|
2723
|
+
...options.appLayers ?? [],
|
|
2724
|
+
...handler.layers
|
|
2725
|
+
];
|
|
2726
|
+
debug16("name=%s \u2014 %d layers", options.handlerName ?? "unknown", allLayers.length);
|
|
2727
|
+
let result;
|
|
2728
|
+
await runLayerPipeline(allLayers, context, async () => {
|
|
2729
|
+
const style = handler.isFunctionHandler ? "function" : "class";
|
|
2730
|
+
debug16("invoking %s handler", style);
|
|
2731
|
+
const validatedPayload = context.metadata.get("validatedPayload") ?? payload;
|
|
2732
|
+
if (handler.isFunctionHandler) {
|
|
2733
|
+
result = await invokeFunctionHandler5(handler, context, validatedPayload);
|
|
2734
|
+
} else {
|
|
2735
|
+
result = await invokeClassHandler5(handler, context, validatedPayload);
|
|
2736
|
+
}
|
|
2737
|
+
}, "custom");
|
|
2738
|
+
return result;
|
|
2739
|
+
}
|
|
2740
|
+
__name(executeCustomPipeline, "executeCustomPipeline");
|
|
2741
|
+
async function invokeClassHandler5(handler, context, validatedPayload) {
|
|
2742
|
+
const args = [];
|
|
2743
|
+
const sorted = [
|
|
2744
|
+
...handler.paramMetadata
|
|
2745
|
+
].sort((a, b) => a.index - b.index);
|
|
2746
|
+
for (const meta of sorted) {
|
|
2747
|
+
args[meta.index] = extractCustomParam(meta, context, validatedPayload);
|
|
2748
|
+
}
|
|
2749
|
+
return handler.handlerFn.apply(handler.handlerInstance, args);
|
|
2750
|
+
}
|
|
2751
|
+
__name(invokeClassHandler5, "invokeClassHandler");
|
|
2752
|
+
async function invokeFunctionHandler5(handler, context, validatedPayload) {
|
|
2753
|
+
const deps = [];
|
|
2754
|
+
if (handler.injectTokens && handler.injectTokens.length > 0) {
|
|
2755
|
+
for (const token of handler.injectTokens) {
|
|
2756
|
+
deps.push(await context.container.resolve(token));
|
|
2757
|
+
}
|
|
2758
|
+
}
|
|
2759
|
+
return handler.handlerFn(validatedPayload, context, ...deps);
|
|
2760
|
+
}
|
|
2761
|
+
__name(invokeFunctionHandler5, "invokeFunctionHandler");
|
|
2762
|
+
function extractCustomParam(meta, context, validatedPayload) {
|
|
2763
|
+
switch (meta.type) {
|
|
2764
|
+
case "payload":
|
|
2765
|
+
return validatedPayload;
|
|
2766
|
+
case "invokeContext":
|
|
2767
|
+
return context;
|
|
2768
|
+
default:
|
|
2769
|
+
return void 0;
|
|
2770
|
+
}
|
|
2771
|
+
}
|
|
2772
|
+
__name(extractCustomParam, "extractCustomParam");
|
|
2773
|
+
|
|
1520
2774
|
// src/testing/test-app.ts
|
|
1521
2775
|
var TestingApplication = class {
|
|
1522
2776
|
static {
|
|
@@ -1532,12 +2786,56 @@ var TestingApplication = class {
|
|
|
1532
2786
|
this.systemLayers = systemLayers;
|
|
1533
2787
|
this.appLayers = appLayers;
|
|
1534
2788
|
}
|
|
1535
|
-
async
|
|
1536
|
-
const handler = this.registry.getHandler(request.
|
|
2789
|
+
async injectHttp(request) {
|
|
2790
|
+
const handler = this.registry.getHandler("http", `${request.method} ${request.path}`);
|
|
1537
2791
|
if (!handler) {
|
|
1538
2792
|
throw new NotFoundException(`No handler found for ${request.method} ${request.path}`);
|
|
1539
2793
|
}
|
|
1540
|
-
return
|
|
2794
|
+
return executeHttpPipeline(handler, request, {
|
|
2795
|
+
container: this.container,
|
|
2796
|
+
systemLayers: this.systemLayers,
|
|
2797
|
+
appLayers: this.appLayers
|
|
2798
|
+
});
|
|
2799
|
+
}
|
|
2800
|
+
async injectWebSocket(route, message) {
|
|
2801
|
+
const handler = this.registry.getHandler("websocket", route);
|
|
2802
|
+
if (!handler) {
|
|
2803
|
+
throw new NotFoundException(`No WebSocket handler found for route: ${route}`);
|
|
2804
|
+
}
|
|
2805
|
+
await executeWebSocketPipeline(handler, message, {
|
|
2806
|
+
container: this.container,
|
|
2807
|
+
systemLayers: this.systemLayers,
|
|
2808
|
+
appLayers: this.appLayers
|
|
2809
|
+
});
|
|
2810
|
+
}
|
|
2811
|
+
async injectConsumer(handlerTag, event) {
|
|
2812
|
+
const handler = this.registry.getHandler("consumer", handlerTag);
|
|
2813
|
+
if (!handler) {
|
|
2814
|
+
throw new NotFoundException(`No consumer handler found for tag: ${handlerTag}`);
|
|
2815
|
+
}
|
|
2816
|
+
return executeConsumerPipeline(handler, event, {
|
|
2817
|
+
container: this.container,
|
|
2818
|
+
systemLayers: this.systemLayers,
|
|
2819
|
+
appLayers: this.appLayers
|
|
2820
|
+
});
|
|
2821
|
+
}
|
|
2822
|
+
async injectSchedule(handlerTag, event) {
|
|
2823
|
+
const handler = this.registry.getHandler("schedule", handlerTag);
|
|
2824
|
+
if (!handler) {
|
|
2825
|
+
throw new NotFoundException(`No schedule handler found for tag: ${handlerTag}`);
|
|
2826
|
+
}
|
|
2827
|
+
return executeSchedulePipeline(handler, event, {
|
|
2828
|
+
container: this.container,
|
|
2829
|
+
systemLayers: this.systemLayers,
|
|
2830
|
+
appLayers: this.appLayers
|
|
2831
|
+
});
|
|
2832
|
+
}
|
|
2833
|
+
async injectCustom(name, payload) {
|
|
2834
|
+
const handler = this.registry.getHandler("custom", name);
|
|
2835
|
+
if (!handler) {
|
|
2836
|
+
throw new NotFoundException(`No custom handler found for name: ${name}`);
|
|
2837
|
+
}
|
|
2838
|
+
return executeCustomPipeline(handler, payload ?? null, {
|
|
1541
2839
|
container: this.container,
|
|
1542
2840
|
systemLayers: this.systemLayers,
|
|
1543
2841
|
appLayers: this.appLayers
|
|
@@ -1571,28 +2869,77 @@ function mockRequest(method, path, options = {}) {
|
|
|
1571
2869
|
};
|
|
1572
2870
|
}
|
|
1573
2871
|
__name(mockRequest, "mockRequest");
|
|
2872
|
+
function mockWebSocketMessage(options = {}) {
|
|
2873
|
+
return {
|
|
2874
|
+
messageType: options.messageType ?? "json",
|
|
2875
|
+
eventType: options.eventType ?? "message",
|
|
2876
|
+
connectionId: options.connectionId ?? "test-conn-id",
|
|
2877
|
+
messageId: options.messageId ?? "test-msg-id",
|
|
2878
|
+
jsonBody: options.jsonBody ?? null,
|
|
2879
|
+
binaryBody: options.binaryBody,
|
|
2880
|
+
traceContext: options.traceContext ?? null
|
|
2881
|
+
};
|
|
2882
|
+
}
|
|
2883
|
+
__name(mockWebSocketMessage, "mockWebSocketMessage");
|
|
2884
|
+
function mockConsumerEvent(handlerTag, messages, options = {}) {
|
|
2885
|
+
const builtMessages = messages.map((msg, index) => ({
|
|
2886
|
+
messageId: msg.messageId ?? `msg-${index}`,
|
|
2887
|
+
body: msg.body,
|
|
2888
|
+
source: msg.source ?? "test",
|
|
2889
|
+
...msg.sourceType !== void 0 && {
|
|
2890
|
+
sourceType: msg.sourceType
|
|
2891
|
+
},
|
|
2892
|
+
...msg.sourceName !== void 0 && {
|
|
2893
|
+
sourceName: msg.sourceName
|
|
2894
|
+
},
|
|
2895
|
+
...msg.eventType !== void 0 && {
|
|
2896
|
+
eventType: msg.eventType
|
|
2897
|
+
},
|
|
2898
|
+
messageAttributes: msg.messageAttributes ?? {},
|
|
2899
|
+
vendor: {}
|
|
2900
|
+
}));
|
|
2901
|
+
return {
|
|
2902
|
+
handlerTag,
|
|
2903
|
+
messages: builtMessages,
|
|
2904
|
+
vendor: options.vendor ?? {},
|
|
2905
|
+
traceContext: options.traceContext ?? null
|
|
2906
|
+
};
|
|
2907
|
+
}
|
|
2908
|
+
__name(mockConsumerEvent, "mockConsumerEvent");
|
|
2909
|
+
function mockScheduleEvent(handlerTag, options = {}) {
|
|
2910
|
+
return {
|
|
2911
|
+
handlerTag,
|
|
2912
|
+
scheduleId: options.scheduleId ?? handlerTag,
|
|
2913
|
+
messageId: options.messageId ?? "test-schedule-msg-id",
|
|
2914
|
+
schedule: options.schedule ?? "rate(1 day)",
|
|
2915
|
+
input: options.input,
|
|
2916
|
+
vendor: options.vendor ?? {},
|
|
2917
|
+
traceContext: options.traceContext ?? null
|
|
2918
|
+
};
|
|
2919
|
+
}
|
|
2920
|
+
__name(mockScheduleEvent, "mockScheduleEvent");
|
|
1574
2921
|
|
|
1575
2922
|
// src/application/factory.ts
|
|
1576
|
-
var
|
|
2923
|
+
var debug17 = createDebug17("celerity:core:factory");
|
|
1577
2924
|
var CelerityFactory = class {
|
|
1578
2925
|
static {
|
|
1579
2926
|
__name(this, "CelerityFactory");
|
|
1580
2927
|
}
|
|
1581
2928
|
static async create(rootModule, options) {
|
|
1582
|
-
|
|
2929
|
+
debug17("create: bootstrapping %s", rootModule.name);
|
|
1583
2930
|
const systemLayers = options?.systemLayers ?? await createDefaultSystemLayers();
|
|
1584
2931
|
const appLayers = options?.layers ?? [];
|
|
1585
|
-
|
|
2932
|
+
debug17("create: %d system layers, %d app layers", systemLayers.length, appLayers.length);
|
|
1586
2933
|
const { container, registry } = await bootstrap(rootModule);
|
|
1587
2934
|
if (options?.adapter) {
|
|
1588
|
-
|
|
2935
|
+
debug17("create: using adapter \u2192 ServerlessApplication");
|
|
1589
2936
|
return new ServerlessApplication(registry, container, options.adapter, systemLayers, appLayers);
|
|
1590
2937
|
}
|
|
1591
|
-
|
|
2938
|
+
debug17("create: \u2192 CelerityApplication");
|
|
1592
2939
|
return new CelerityApplication(registry, container, systemLayers, appLayers);
|
|
1593
2940
|
}
|
|
1594
2941
|
static async createTestingApp(rootModule, options) {
|
|
1595
|
-
|
|
2942
|
+
debug17("createTestingApp: bootstrapping %s", rootModule.name);
|
|
1596
2943
|
const { container, registry } = await bootstrap(rootModule);
|
|
1597
2944
|
const systemLayers = options?.systemLayers ?? [];
|
|
1598
2945
|
const appLayers = options?.layers ?? [];
|
|
@@ -1689,22 +3036,130 @@ function httpDelete(path, handlerOrOptions, maybeHandler) {
|
|
|
1689
3036
|
}
|
|
1690
3037
|
__name(httpDelete, "httpDelete");
|
|
1691
3038
|
|
|
3039
|
+
// src/functions/create-guard.ts
|
|
3040
|
+
function createGuard(config, handler) {
|
|
3041
|
+
return {
|
|
3042
|
+
__celerity_guard: true,
|
|
3043
|
+
name: config.name,
|
|
3044
|
+
handler,
|
|
3045
|
+
metadata: {
|
|
3046
|
+
inject: config.inject ?? [],
|
|
3047
|
+
customMetadata: config.metadata ?? {}
|
|
3048
|
+
}
|
|
3049
|
+
};
|
|
3050
|
+
}
|
|
3051
|
+
__name(createGuard, "createGuard");
|
|
3052
|
+
|
|
3053
|
+
// src/functions/create-websocket-handler.ts
|
|
3054
|
+
function createWebSocketHandler(config, handler) {
|
|
3055
|
+
const metadata = {
|
|
3056
|
+
layers: config.layers ?? [],
|
|
3057
|
+
inject: config.inject ?? [],
|
|
3058
|
+
customMetadata: config.metadata ?? {}
|
|
3059
|
+
};
|
|
3060
|
+
if (config.route !== void 0) metadata.route = config.route;
|
|
3061
|
+
if (config.protectedBy !== void 0) metadata.protectedBy = config.protectedBy;
|
|
3062
|
+
if (config.schema !== void 0) metadata.schema = config.schema;
|
|
3063
|
+
return {
|
|
3064
|
+
__celerity_handler: true,
|
|
3065
|
+
type: "websocket",
|
|
3066
|
+
metadata,
|
|
3067
|
+
handler
|
|
3068
|
+
};
|
|
3069
|
+
}
|
|
3070
|
+
__name(createWebSocketHandler, "createWebSocketHandler");
|
|
3071
|
+
|
|
3072
|
+
// src/functions/create-consumer-handler.ts
|
|
3073
|
+
function createConsumerHandler(config, handler) {
|
|
3074
|
+
const metadata = {
|
|
3075
|
+
layers: config.layers ?? [],
|
|
3076
|
+
inject: config.inject ?? [],
|
|
3077
|
+
customMetadata: config.metadata ?? {}
|
|
3078
|
+
};
|
|
3079
|
+
if (config.route !== void 0) metadata.route = config.route;
|
|
3080
|
+
if (config.messageSchema !== void 0) metadata.messageSchema = config.messageSchema;
|
|
3081
|
+
return {
|
|
3082
|
+
__celerity_handler: true,
|
|
3083
|
+
type: "consumer",
|
|
3084
|
+
metadata,
|
|
3085
|
+
handler
|
|
3086
|
+
};
|
|
3087
|
+
}
|
|
3088
|
+
__name(createConsumerHandler, "createConsumerHandler");
|
|
3089
|
+
|
|
3090
|
+
// src/functions/create-schedule-handler.ts
|
|
3091
|
+
function isScheduleExpression2(value) {
|
|
3092
|
+
return value.startsWith("rate(") || value.startsWith("cron(");
|
|
3093
|
+
}
|
|
3094
|
+
__name(isScheduleExpression2, "isScheduleExpression");
|
|
3095
|
+
function createScheduleHandler(configOrString, configOrHandler, maybeHandler) {
|
|
3096
|
+
let config;
|
|
3097
|
+
let handler;
|
|
3098
|
+
if (typeof configOrString === "string") {
|
|
3099
|
+
config = {
|
|
3100
|
+
...configOrHandler
|
|
3101
|
+
};
|
|
3102
|
+
handler = maybeHandler;
|
|
3103
|
+
if (isScheduleExpression2(configOrString)) {
|
|
3104
|
+
config.schedule = configOrString;
|
|
3105
|
+
} else {
|
|
3106
|
+
config.scheduleId = configOrString;
|
|
3107
|
+
}
|
|
3108
|
+
} else {
|
|
3109
|
+
config = configOrString;
|
|
3110
|
+
handler = configOrHandler;
|
|
3111
|
+
}
|
|
3112
|
+
const metadata = {
|
|
3113
|
+
layers: config.layers ?? [],
|
|
3114
|
+
inject: config.inject ?? [],
|
|
3115
|
+
customMetadata: config.metadata ?? {}
|
|
3116
|
+
};
|
|
3117
|
+
if (config.scheduleId !== void 0) metadata.scheduleId = config.scheduleId;
|
|
3118
|
+
if (config.schedule !== void 0) metadata.schedule = config.schedule;
|
|
3119
|
+
if (config.schema !== void 0) metadata.schema = config.schema;
|
|
3120
|
+
return {
|
|
3121
|
+
__celerity_handler: true,
|
|
3122
|
+
type: "schedule",
|
|
3123
|
+
metadata,
|
|
3124
|
+
handler
|
|
3125
|
+
};
|
|
3126
|
+
}
|
|
3127
|
+
__name(createScheduleHandler, "createScheduleHandler");
|
|
3128
|
+
|
|
3129
|
+
// src/functions/create-custom-handler.ts
|
|
3130
|
+
function createCustomHandler(config, handler) {
|
|
3131
|
+
const metadata = {
|
|
3132
|
+
layers: config.layers ?? [],
|
|
3133
|
+
inject: config.inject ?? [],
|
|
3134
|
+
customMetadata: config.metadata ?? {}
|
|
3135
|
+
};
|
|
3136
|
+
if (config.name !== void 0) metadata.name = config.name;
|
|
3137
|
+
if (config.schema !== void 0) metadata.schema = config.schema;
|
|
3138
|
+
return {
|
|
3139
|
+
__celerity_handler: true,
|
|
3140
|
+
type: "custom",
|
|
3141
|
+
metadata,
|
|
3142
|
+
handler
|
|
3143
|
+
};
|
|
3144
|
+
}
|
|
3145
|
+
__name(createCustomHandler, "createCustomHandler");
|
|
3146
|
+
|
|
1692
3147
|
// src/handlers/module-resolver.ts
|
|
1693
3148
|
import { resolve } from "path";
|
|
1694
|
-
import
|
|
1695
|
-
var
|
|
1696
|
-
async function resolveHandlerByModuleRef(handlerId, registry, baseDir) {
|
|
3149
|
+
import createDebug18 from "debug";
|
|
3150
|
+
var debug18 = createDebug18("celerity:core:module-resolver");
|
|
3151
|
+
async function resolveHandlerByModuleRef(handlerId, handlerType, registry, baseDir) {
|
|
1697
3152
|
const lastDot = handlerId.lastIndexOf(".");
|
|
1698
3153
|
if (lastDot > 0) {
|
|
1699
3154
|
const moduleName = handlerId.slice(0, lastDot);
|
|
1700
3155
|
const exportName = handlerId.slice(lastDot + 1);
|
|
1701
|
-
const result = await tryResolveExport(baseDir, moduleName, exportName, handlerId, registry);
|
|
3156
|
+
const result = await tryResolveExport(baseDir, moduleName, exportName, handlerId, handlerType, registry);
|
|
1702
3157
|
if (result) return result;
|
|
1703
3158
|
}
|
|
1704
|
-
return tryResolveExport(baseDir, handlerId, "default", handlerId, registry);
|
|
3159
|
+
return tryResolveExport(baseDir, handlerId, "default", handlerId, handlerType, registry);
|
|
1705
3160
|
}
|
|
1706
3161
|
__name(resolveHandlerByModuleRef, "resolveHandlerByModuleRef");
|
|
1707
|
-
async function tryResolveExport(baseDir, moduleName, exportName, handlerId, registry) {
|
|
3162
|
+
async function tryResolveExport(baseDir, moduleName, exportName, handlerId, handlerType, registry) {
|
|
1708
3163
|
const handlerModulePath = resolve(baseDir, moduleName);
|
|
1709
3164
|
let mod;
|
|
1710
3165
|
try {
|
|
@@ -1719,66 +3174,235 @@ async function tryResolveExport(baseDir, moduleName, exportName, handlerId, regi
|
|
|
1719
3174
|
const exported = mod[exportName];
|
|
1720
3175
|
if (!exported) return null;
|
|
1721
3176
|
const isFnDef = typeof exported === "object" && exported !== null && exported.__celerity_handler;
|
|
3177
|
+
if (isFnDef && exported.type !== handlerType) {
|
|
3178
|
+
return null;
|
|
3179
|
+
}
|
|
1722
3180
|
const handlerFn = isFnDef ? exported.handler : exported;
|
|
1723
3181
|
if (typeof handlerFn !== "function") return null;
|
|
1724
|
-
const
|
|
3182
|
+
const handlers = registry.getHandlersByType(handlerType);
|
|
3183
|
+
const match = handlers.find((h) => h.handlerFn === handlerFn);
|
|
1725
3184
|
if (match) {
|
|
1726
3185
|
match.id = handlerId;
|
|
1727
|
-
|
|
3186
|
+
debug18("matched '%s' to registry handler", handlerId);
|
|
1728
3187
|
return match;
|
|
1729
3188
|
}
|
|
1730
|
-
|
|
1731
|
-
return buildResolvedFromExport(handlerId, handlerFn, isFnDef ? exported : null);
|
|
3189
|
+
debug18("'%s' not in registry, wrapping directly", handlerId);
|
|
3190
|
+
return buildResolvedFromExport(handlerId, handlerType, handlerFn, isFnDef ? exported : null);
|
|
1732
3191
|
}
|
|
1733
3192
|
__name(tryResolveExport, "tryResolveExport");
|
|
1734
|
-
function buildResolvedFromExport(handlerId, handlerFn, fnDef) {
|
|
1735
|
-
|
|
1736
|
-
|
|
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 {
|
|
3193
|
+
function buildResolvedFromExport(handlerId, handlerType, handlerFn, fnDef) {
|
|
3194
|
+
const meta = fnDef ? fnDef.metadata : null;
|
|
3195
|
+
const base = {
|
|
1752
3196
|
id: handlerId,
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
3197
|
+
layers: [
|
|
3198
|
+
...meta?.layers ?? []
|
|
3199
|
+
],
|
|
1756
3200
|
paramMetadata: [],
|
|
1757
|
-
customMetadata: {},
|
|
3201
|
+
customMetadata: meta?.customMetadata ?? {},
|
|
1758
3202
|
handlerFn,
|
|
1759
3203
|
isFunctionHandler: true,
|
|
1760
|
-
injectTokens: []
|
|
3204
|
+
injectTokens: meta?.inject ?? []
|
|
3205
|
+
};
|
|
3206
|
+
const guardFields = {
|
|
3207
|
+
protectedBy: [],
|
|
3208
|
+
isPublic: false
|
|
1761
3209
|
};
|
|
3210
|
+
switch (handlerType) {
|
|
3211
|
+
case "http":
|
|
3212
|
+
return {
|
|
3213
|
+
...base,
|
|
3214
|
+
...guardFields,
|
|
3215
|
+
type: "http",
|
|
3216
|
+
...meta?.path !== void 0 ? {
|
|
3217
|
+
path: meta.path
|
|
3218
|
+
} : {},
|
|
3219
|
+
...meta?.method !== void 0 ? {
|
|
3220
|
+
method: meta.method
|
|
3221
|
+
} : {}
|
|
3222
|
+
};
|
|
3223
|
+
case "websocket":
|
|
3224
|
+
return {
|
|
3225
|
+
...base,
|
|
3226
|
+
...guardFields,
|
|
3227
|
+
type: "websocket",
|
|
3228
|
+
route: meta?.route ?? handlerId
|
|
3229
|
+
};
|
|
3230
|
+
case "consumer":
|
|
3231
|
+
return {
|
|
3232
|
+
...base,
|
|
3233
|
+
type: "consumer",
|
|
3234
|
+
handlerTag: meta?.route ?? handlerId
|
|
3235
|
+
};
|
|
3236
|
+
case "schedule":
|
|
3237
|
+
return {
|
|
3238
|
+
...base,
|
|
3239
|
+
type: "schedule",
|
|
3240
|
+
handlerTag: meta?.scheduleId ?? handlerId
|
|
3241
|
+
};
|
|
3242
|
+
case "custom":
|
|
3243
|
+
return {
|
|
3244
|
+
...base,
|
|
3245
|
+
type: "custom",
|
|
3246
|
+
name: meta?.name ?? handlerId
|
|
3247
|
+
};
|
|
3248
|
+
}
|
|
1762
3249
|
}
|
|
1763
3250
|
__name(buildResolvedFromExport, "buildResolvedFromExport");
|
|
1764
3251
|
|
|
3252
|
+
// src/handlers/websocket-sender.ts
|
|
3253
|
+
var RuntimeWebSocketSender = class {
|
|
3254
|
+
static {
|
|
3255
|
+
__name(this, "RuntimeWebSocketSender");
|
|
3256
|
+
}
|
|
3257
|
+
registry;
|
|
3258
|
+
constructor(registry) {
|
|
3259
|
+
this.registry = registry;
|
|
3260
|
+
}
|
|
3261
|
+
async sendMessage(connectionId, data, options) {
|
|
3262
|
+
const messageId = options?.messageId ?? crypto.randomUUID();
|
|
3263
|
+
const messageType = options?.messageType === "binary" ? "binary" : "json";
|
|
3264
|
+
const payload = typeof data === "string" ? data : JSON.stringify(data);
|
|
3265
|
+
await this.registry.sendMessage(connectionId, messageId, messageType, payload);
|
|
3266
|
+
}
|
|
3267
|
+
};
|
|
3268
|
+
|
|
3269
|
+
// src/handlers/guard-pipeline.ts
|
|
3270
|
+
import createDebug19 from "debug";
|
|
3271
|
+
var debug19 = createDebug19("celerity:core:guard-pipeline");
|
|
3272
|
+
async function executeGuardPipeline(guard, input, options) {
|
|
3273
|
+
const metadata = new HandlerMetadataStore({
|
|
3274
|
+
...guard.customMetadata ?? {},
|
|
3275
|
+
...options.handlerMetadata ?? {}
|
|
3276
|
+
});
|
|
3277
|
+
const logger = await createGuardLogger(guard.name, input, options.container);
|
|
3278
|
+
try {
|
|
3279
|
+
const result = guard.isFunctionGuard ? await invokeFunctionGuard(guard, input, metadata, options, logger) : await invokeClassGuard(guard, input, metadata, options, logger);
|
|
3280
|
+
debug19("guard %s \u2014 allowed", guard.name);
|
|
3281
|
+
return {
|
|
3282
|
+
allowed: true,
|
|
3283
|
+
auth: result ?? {}
|
|
3284
|
+
};
|
|
3285
|
+
} catch (error) {
|
|
3286
|
+
if (error instanceof HttpException) {
|
|
3287
|
+
debug19("guard %s \u2014 rejected %d: %s", guard.name, error.statusCode, error.message);
|
|
3288
|
+
return {
|
|
3289
|
+
allowed: false,
|
|
3290
|
+
statusCode: error.statusCode,
|
|
3291
|
+
message: error.message,
|
|
3292
|
+
details: error.details
|
|
3293
|
+
};
|
|
3294
|
+
}
|
|
3295
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3296
|
+
debug19("guard %s \u2014 unexpected error: %s", guard.name, message);
|
|
3297
|
+
return {
|
|
3298
|
+
allowed: false,
|
|
3299
|
+
statusCode: 401,
|
|
3300
|
+
message: "Unauthorized"
|
|
3301
|
+
};
|
|
3302
|
+
}
|
|
3303
|
+
}
|
|
3304
|
+
__name(executeGuardPipeline, "executeGuardPipeline");
|
|
3305
|
+
async function createGuardLogger(guardName, input, container) {
|
|
3306
|
+
const attrs = {
|
|
3307
|
+
guard: guardName,
|
|
3308
|
+
requestId: input.requestId,
|
|
3309
|
+
method: input.method,
|
|
3310
|
+
path: input.path,
|
|
3311
|
+
clientIp: input.clientIp,
|
|
3312
|
+
...input.handlerName ? {
|
|
3313
|
+
handlerName: input.handlerName
|
|
3314
|
+
} : {}
|
|
3315
|
+
};
|
|
3316
|
+
if (container.has("CelerityLogger")) {
|
|
3317
|
+
const root = await container.resolve("CelerityLogger");
|
|
3318
|
+
return root.child("guard", attrs);
|
|
3319
|
+
}
|
|
3320
|
+
const pkg = "@celerity-sdk/telemetry";
|
|
3321
|
+
const { createLogger, readTelemetryEnv } = await import(pkg);
|
|
3322
|
+
const rootLogger = await createLogger(readTelemetryEnv());
|
|
3323
|
+
return rootLogger.child("guard", attrs);
|
|
3324
|
+
}
|
|
3325
|
+
__name(createGuardLogger, "createGuardLogger");
|
|
3326
|
+
async function invokeClassGuard(guard, input, metadata, options, logger) {
|
|
3327
|
+
const guardContext = {
|
|
3328
|
+
token: input.token,
|
|
3329
|
+
auth: input.auth,
|
|
3330
|
+
request: {
|
|
3331
|
+
method: input.method,
|
|
3332
|
+
path: input.path,
|
|
3333
|
+
headers: input.headers,
|
|
3334
|
+
query: input.query,
|
|
3335
|
+
cookies: input.cookies,
|
|
3336
|
+
body: input.body,
|
|
3337
|
+
requestId: input.requestId,
|
|
3338
|
+
clientIp: input.clientIp
|
|
3339
|
+
},
|
|
3340
|
+
metadata,
|
|
3341
|
+
container: options.container,
|
|
3342
|
+
logger
|
|
3343
|
+
};
|
|
3344
|
+
const paramCount = guard.handlerFn.length;
|
|
3345
|
+
const args = new Array(paramCount);
|
|
3346
|
+
const decorated = new Set(guard.paramMetadata.map((m) => m.index));
|
|
3347
|
+
for (const meta of guard.paramMetadata) {
|
|
3348
|
+
if (meta.type === "token") {
|
|
3349
|
+
args[meta.index] = guardContext.token;
|
|
3350
|
+
} else if (meta.type === "auth") {
|
|
3351
|
+
args[meta.index] = guardContext.auth;
|
|
3352
|
+
}
|
|
3353
|
+
}
|
|
3354
|
+
for (let i = 0; i < paramCount; i++) {
|
|
3355
|
+
if (!decorated.has(i)) {
|
|
3356
|
+
args[i] = guardContext;
|
|
3357
|
+
}
|
|
3358
|
+
}
|
|
3359
|
+
return guard.handlerFn.apply(guard.handlerInstance, args);
|
|
3360
|
+
}
|
|
3361
|
+
__name(invokeClassGuard, "invokeClassGuard");
|
|
3362
|
+
async function invokeFunctionGuard(guard, input, metadata, options, logger) {
|
|
3363
|
+
const req = {
|
|
3364
|
+
token: input.token,
|
|
3365
|
+
headers: input.headers,
|
|
3366
|
+
query: input.query,
|
|
3367
|
+
cookies: input.cookies,
|
|
3368
|
+
body: input.body,
|
|
3369
|
+
requestId: input.requestId,
|
|
3370
|
+
clientIp: input.clientIp
|
|
3371
|
+
};
|
|
3372
|
+
const ctx = {
|
|
3373
|
+
metadata,
|
|
3374
|
+
container: options.container,
|
|
3375
|
+
auth: input.auth,
|
|
3376
|
+
logger
|
|
3377
|
+
};
|
|
3378
|
+
if (guard.injectTokens && guard.injectTokens.length > 0) {
|
|
3379
|
+
const deps = [];
|
|
3380
|
+
for (const token of guard.injectTokens) {
|
|
3381
|
+
deps.push(await options.container.resolve(token));
|
|
3382
|
+
}
|
|
3383
|
+
return guard.handlerFn(req, ctx, ...deps);
|
|
3384
|
+
}
|
|
3385
|
+
return guard.handlerFn(req, ctx);
|
|
3386
|
+
}
|
|
3387
|
+
__name(invokeFunctionGuard, "invokeFunctionGuard");
|
|
3388
|
+
|
|
1765
3389
|
// src/bootstrap/discovery.ts
|
|
1766
3390
|
import { resolve as resolve2 } from "path";
|
|
1767
|
-
import
|
|
1768
|
-
var
|
|
3391
|
+
import createDebug20 from "debug";
|
|
3392
|
+
var debug20 = createDebug20("celerity:core:bootstrap");
|
|
1769
3393
|
async function discoverModule(modulePath) {
|
|
1770
3394
|
const resolved = modulePath ?? process.env.CELERITY_MODULE_PATH;
|
|
1771
3395
|
if (!resolved) {
|
|
1772
3396
|
throw new Error("Cannot discover module: set CELERITY_MODULE_PATH environment variable or pass modulePath");
|
|
1773
3397
|
}
|
|
1774
3398
|
const absolutePath = resolve2(resolved);
|
|
1775
|
-
|
|
3399
|
+
debug20("discoverModule: importing %s", absolutePath);
|
|
1776
3400
|
const imported = await import(absolutePath);
|
|
1777
3401
|
const rootModule = imported.default ?? findModuleExport(imported);
|
|
1778
3402
|
if (!rootModule || typeof rootModule !== "function") {
|
|
1779
3403
|
throw new Error(`No module class found in "${resolved}"`);
|
|
1780
3404
|
}
|
|
1781
|
-
|
|
3405
|
+
debug20("discoverModule: found %s", rootModule.name);
|
|
1782
3406
|
return rootModule;
|
|
1783
3407
|
}
|
|
1784
3408
|
__name(discoverModule, "discoverModule");
|
|
@@ -1832,61 +3456,350 @@ function mapToRuntimeResponse(response) {
|
|
|
1832
3456
|
};
|
|
1833
3457
|
}
|
|
1834
3458
|
__name(mapToRuntimeResponse, "mapToRuntimeResponse");
|
|
3459
|
+
function mapWebSocketMessage(info) {
|
|
3460
|
+
const requestContext = info.requestContext ? {
|
|
3461
|
+
requestId: info.requestContext.requestId,
|
|
3462
|
+
requestTime: info.requestContext.requestTime,
|
|
3463
|
+
path: info.requestContext.path,
|
|
3464
|
+
protocolVersion: info.requestContext.protocolVersion,
|
|
3465
|
+
headers: flattenMultiValueRecord(info.requestContext.headers),
|
|
3466
|
+
userAgent: info.requestContext.userAgent,
|
|
3467
|
+
clientIp: info.requestContext.clientIp,
|
|
3468
|
+
query: flattenMultiValueRecord(info.requestContext.query),
|
|
3469
|
+
cookies: info.requestContext.cookies,
|
|
3470
|
+
auth: info.requestContext.auth,
|
|
3471
|
+
traceContext: info.requestContext.traceContext
|
|
3472
|
+
} : void 0;
|
|
3473
|
+
return {
|
|
3474
|
+
messageType: info.messageType,
|
|
3475
|
+
eventType: info.eventType,
|
|
3476
|
+
connectionId: info.connectionId,
|
|
3477
|
+
messageId: info.messageId,
|
|
3478
|
+
jsonBody: info.jsonBody,
|
|
3479
|
+
binaryBody: info.binaryBody,
|
|
3480
|
+
requestContext,
|
|
3481
|
+
traceContext: info.traceContext ?? null
|
|
3482
|
+
};
|
|
3483
|
+
}
|
|
3484
|
+
__name(mapWebSocketMessage, "mapWebSocketMessage");
|
|
3485
|
+
function mapConsumerEventInput(input) {
|
|
3486
|
+
return {
|
|
3487
|
+
handlerTag: input.handlerTag,
|
|
3488
|
+
messages: input.messages.map((msg) => {
|
|
3489
|
+
const m = msg;
|
|
3490
|
+
return {
|
|
3491
|
+
messageId: msg.messageId,
|
|
3492
|
+
body: msg.body,
|
|
3493
|
+
source: msg.source,
|
|
3494
|
+
...m.sourceType !== void 0 && {
|
|
3495
|
+
sourceType: m.sourceType
|
|
3496
|
+
},
|
|
3497
|
+
...m.sourceName !== void 0 && {
|
|
3498
|
+
sourceName: m.sourceName
|
|
3499
|
+
},
|
|
3500
|
+
...m.eventType !== void 0 && {
|
|
3501
|
+
eventType: m.eventType
|
|
3502
|
+
},
|
|
3503
|
+
messageAttributes: msg.messageAttributes,
|
|
3504
|
+
vendor: msg.vendor
|
|
3505
|
+
};
|
|
3506
|
+
}),
|
|
3507
|
+
vendor: input.vendor,
|
|
3508
|
+
traceContext: input.traceContext ?? null
|
|
3509
|
+
};
|
|
3510
|
+
}
|
|
3511
|
+
__name(mapConsumerEventInput, "mapConsumerEventInput");
|
|
3512
|
+
function mapScheduleEventInput(input) {
|
|
3513
|
+
return {
|
|
3514
|
+
handlerTag: input.handlerTag,
|
|
3515
|
+
scheduleId: input.scheduleId,
|
|
3516
|
+
messageId: input.messageId,
|
|
3517
|
+
schedule: input.schedule,
|
|
3518
|
+
input: input.input,
|
|
3519
|
+
vendor: input.vendor,
|
|
3520
|
+
traceContext: input.traceContext ?? null
|
|
3521
|
+
};
|
|
3522
|
+
}
|
|
3523
|
+
__name(mapScheduleEventInput, "mapScheduleEventInput");
|
|
3524
|
+
function mapToNapiEventResult(result) {
|
|
3525
|
+
return {
|
|
3526
|
+
success: result.success,
|
|
3527
|
+
failures: result.failures?.map((f) => ({
|
|
3528
|
+
messageId: f.messageId,
|
|
3529
|
+
errorMessage: f.errorMessage
|
|
3530
|
+
})),
|
|
3531
|
+
errorMessage: result.errorMessage
|
|
3532
|
+
};
|
|
3533
|
+
}
|
|
3534
|
+
__name(mapToNapiEventResult, "mapToNapiEventResult");
|
|
1835
3535
|
|
|
1836
3536
|
// src/bootstrap/runtime-entry.ts
|
|
1837
3537
|
import { resolve as resolve3, dirname } from "path";
|
|
3538
|
+
import createDebug21 from "debug";
|
|
3539
|
+
var debug21 = createDebug21("celerity:core:runtime-entry");
|
|
1838
3540
|
async function bootstrapForRuntime(modulePath, systemLayers) {
|
|
1839
3541
|
const layers = systemLayers ?? await createDefaultSystemLayers();
|
|
1840
3542
|
const resolvedModulePath = modulePath ?? process.env.CELERITY_MODULE_PATH;
|
|
1841
3543
|
const moduleDir = resolvedModulePath ? dirname(resolve3(resolvedModulePath)) : process.cwd();
|
|
1842
3544
|
const rootModule = await discoverModule(modulePath);
|
|
1843
3545
|
const { container, registry } = await bootstrap(rootModule);
|
|
1844
|
-
function
|
|
3546
|
+
function buildHttpCallback(handler, handlerName) {
|
|
1845
3547
|
if (!handler) return null;
|
|
1846
3548
|
return async (_err, request) => {
|
|
1847
3549
|
const httpRequest = mapRuntimeRequest(request);
|
|
1848
|
-
const httpResponse = await
|
|
3550
|
+
const httpResponse = await executeHttpPipeline(handler, httpRequest, {
|
|
1849
3551
|
container,
|
|
1850
|
-
systemLayers: layers
|
|
3552
|
+
systemLayers: layers,
|
|
3553
|
+
handlerName
|
|
1851
3554
|
});
|
|
1852
3555
|
return mapToRuntimeResponse(httpResponse);
|
|
1853
3556
|
};
|
|
1854
3557
|
}
|
|
1855
|
-
__name(
|
|
3558
|
+
__name(buildHttpCallback, "buildHttpCallback");
|
|
3559
|
+
function buildWebSocketCallback(handler, handlerName) {
|
|
3560
|
+
if (!handler) return null;
|
|
3561
|
+
return async (_err, info) => {
|
|
3562
|
+
const message = mapWebSocketMessage(info);
|
|
3563
|
+
await executeWebSocketPipeline(handler, message, {
|
|
3564
|
+
container,
|
|
3565
|
+
systemLayers: layers,
|
|
3566
|
+
handlerName
|
|
3567
|
+
});
|
|
3568
|
+
};
|
|
3569
|
+
}
|
|
3570
|
+
__name(buildWebSocketCallback, "buildWebSocketCallback");
|
|
3571
|
+
function buildConsumerCallback(handler, handlerName) {
|
|
3572
|
+
if (!handler) return null;
|
|
3573
|
+
return async (_err, input) => {
|
|
3574
|
+
const event = mapConsumerEventInput(input);
|
|
3575
|
+
const result = await executeConsumerPipeline(handler, event, {
|
|
3576
|
+
container,
|
|
3577
|
+
systemLayers: layers,
|
|
3578
|
+
handlerName
|
|
3579
|
+
});
|
|
3580
|
+
return mapToNapiEventResult(result);
|
|
3581
|
+
};
|
|
3582
|
+
}
|
|
3583
|
+
__name(buildConsumerCallback, "buildConsumerCallback");
|
|
3584
|
+
function buildScheduleCallback(handler, handlerName) {
|
|
3585
|
+
if (!handler) return null;
|
|
3586
|
+
return async (_err, input) => {
|
|
3587
|
+
const event = mapScheduleEventInput(input);
|
|
3588
|
+
const result = await executeSchedulePipeline(handler, event, {
|
|
3589
|
+
container,
|
|
3590
|
+
systemLayers: layers,
|
|
3591
|
+
handlerName
|
|
3592
|
+
});
|
|
3593
|
+
return mapToNapiEventResult(result);
|
|
3594
|
+
};
|
|
3595
|
+
}
|
|
3596
|
+
__name(buildScheduleCallback, "buildScheduleCallback");
|
|
3597
|
+
function buildCustomCallback(handler, handlerName) {
|
|
3598
|
+
if (!handler) return null;
|
|
3599
|
+
return async (_err, payload) => {
|
|
3600
|
+
return executeCustomPipeline(handler, payload, {
|
|
3601
|
+
container,
|
|
3602
|
+
systemLayers: layers,
|
|
3603
|
+
handlerName
|
|
3604
|
+
});
|
|
3605
|
+
};
|
|
3606
|
+
}
|
|
3607
|
+
__name(buildCustomCallback, "buildCustomCallback");
|
|
1856
3608
|
return {
|
|
1857
3609
|
registry,
|
|
1858
3610
|
container,
|
|
1859
|
-
createRouteCallback(path,
|
|
1860
|
-
return
|
|
3611
|
+
createRouteCallback(method, path, handlerName) {
|
|
3612
|
+
return buildHttpCallback(registry.getHandler("http", `${method} ${path}`), handlerName);
|
|
3613
|
+
},
|
|
3614
|
+
async createRouteCallbackById(handlerId, codeLocation, handlerName) {
|
|
3615
|
+
const fromRegistry = registry.getHandlerById("http", handlerId);
|
|
3616
|
+
if (fromRegistry) return buildHttpCallback(fromRegistry, handlerName);
|
|
3617
|
+
const baseDir = codeLocation ? resolve3(codeLocation) : moduleDir;
|
|
3618
|
+
const resolved = await resolveHandlerByModuleRef(handlerId, "http", registry, baseDir);
|
|
3619
|
+
return resolved ? buildHttpCallback(resolved, handlerName) : null;
|
|
3620
|
+
},
|
|
3621
|
+
createGuardCallback(guardName) {
|
|
3622
|
+
const guard = registry.getGuard(guardName);
|
|
3623
|
+
if (!guard) return null;
|
|
3624
|
+
return async (input) => {
|
|
3625
|
+
debug21("guard %s \u2014 input method=%s path=%s", guardName, input.method, input.path);
|
|
3626
|
+
const handler = registry.getHandler("http", `${input.method} ${input.path}`);
|
|
3627
|
+
debug21("guard %s \u2014 handler %s, customMetadata=%o", guardName, handler ? "found" : "not found", handler?.customMetadata);
|
|
3628
|
+
return executeGuardPipeline(guard, input, {
|
|
3629
|
+
container,
|
|
3630
|
+
handlerMetadata: handler?.customMetadata
|
|
3631
|
+
});
|
|
3632
|
+
};
|
|
3633
|
+
},
|
|
3634
|
+
createWebSocketCallback(route, handlerName) {
|
|
3635
|
+
return buildWebSocketCallback(registry.getHandler("websocket", route), handlerName);
|
|
3636
|
+
},
|
|
3637
|
+
async createWebSocketCallbackById(handlerId, codeLocation, handlerName) {
|
|
3638
|
+
const fromRegistry = registry.getHandlerById("websocket", handlerId);
|
|
3639
|
+
if (fromRegistry) return buildWebSocketCallback(fromRegistry, handlerName);
|
|
3640
|
+
const baseDir = codeLocation ? resolve3(codeLocation) : moduleDir;
|
|
3641
|
+
const resolved = await resolveHandlerByModuleRef(handlerId, "websocket", registry, baseDir);
|
|
3642
|
+
return resolved ? buildWebSocketCallback(resolved, handlerName) : null;
|
|
3643
|
+
},
|
|
3644
|
+
createConsumerCallback(handlerTag, handlerName) {
|
|
3645
|
+
return buildConsumerCallback(registry.getHandler("consumer", handlerTag), handlerName);
|
|
3646
|
+
},
|
|
3647
|
+
async createConsumerCallbackById(handlerId, codeLocation, handlerName) {
|
|
3648
|
+
const fromRegistry = registry.getHandlerById("consumer", handlerId);
|
|
3649
|
+
if (fromRegistry) return buildConsumerCallback(fromRegistry, handlerName);
|
|
3650
|
+
const baseDir = codeLocation ? resolve3(codeLocation) : moduleDir;
|
|
3651
|
+
const resolved = await resolveHandlerByModuleRef(handlerId, "consumer", registry, baseDir);
|
|
3652
|
+
return resolved ? buildConsumerCallback(resolved, handlerName) : null;
|
|
3653
|
+
},
|
|
3654
|
+
createScheduleCallback(handlerTag, handlerName) {
|
|
3655
|
+
return buildScheduleCallback(registry.getHandler("schedule", handlerTag), handlerName);
|
|
3656
|
+
},
|
|
3657
|
+
async createScheduleCallbackById(handlerId, codeLocation, handlerName) {
|
|
3658
|
+
const fromRegistry = registry.getHandlerById("schedule", handlerId);
|
|
3659
|
+
if (fromRegistry) return buildScheduleCallback(fromRegistry, handlerName);
|
|
3660
|
+
const baseDir = codeLocation ? resolve3(codeLocation) : moduleDir;
|
|
3661
|
+
const resolved = await resolveHandlerByModuleRef(handlerId, "schedule", registry, baseDir);
|
|
3662
|
+
return resolved ? buildScheduleCallback(resolved, handlerName) : null;
|
|
1861
3663
|
},
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
3664
|
+
createCustomCallback(handlerName) {
|
|
3665
|
+
return buildCustomCallback(registry.getHandler("custom", handlerName), handlerName);
|
|
3666
|
+
},
|
|
3667
|
+
async createCustomCallbackById(handlerId, codeLocation, handlerName) {
|
|
3668
|
+
const fromRegistry = registry.getHandlerById("custom", handlerId);
|
|
3669
|
+
if (fromRegistry) return buildCustomCallback(fromRegistry, handlerName);
|
|
1865
3670
|
const baseDir = codeLocation ? resolve3(codeLocation) : moduleDir;
|
|
1866
|
-
const resolved = await resolveHandlerByModuleRef(handlerId, registry, baseDir);
|
|
1867
|
-
return resolved ?
|
|
3671
|
+
const resolved = await resolveHandlerByModuleRef(handlerId, "custom", registry, baseDir);
|
|
3672
|
+
return resolved ? buildCustomCallback(resolved, handlerName) : null;
|
|
1868
3673
|
}
|
|
1869
3674
|
};
|
|
1870
3675
|
}
|
|
1871
3676
|
__name(bootstrapForRuntime, "bootstrapForRuntime");
|
|
1872
3677
|
|
|
1873
3678
|
// src/bootstrap/runtime-orchestrator.ts
|
|
1874
|
-
|
|
3679
|
+
import { WebSocketSender } from "@celerity-sdk/types";
|
|
3680
|
+
async function loadRuntime() {
|
|
1875
3681
|
const pkg = "@celerity-sdk/runtime";
|
|
1876
3682
|
const runtimeModule = await import(pkg);
|
|
1877
3683
|
const config = runtimeModule.runtimeConfigFromEnv();
|
|
1878
3684
|
const app = new runtimeModule.CoreRuntimeApplication(config);
|
|
1879
3685
|
const appConfig = app.setup();
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
3686
|
+
return {
|
|
3687
|
+
app,
|
|
3688
|
+
appConfig
|
|
3689
|
+
};
|
|
3690
|
+
}
|
|
3691
|
+
__name(loadRuntime, "loadRuntime");
|
|
3692
|
+
function mapGuardResult(result) {
|
|
3693
|
+
if (result.allowed) {
|
|
3694
|
+
return {
|
|
3695
|
+
status: "allowed",
|
|
3696
|
+
auth: result.auth
|
|
3697
|
+
};
|
|
3698
|
+
}
|
|
3699
|
+
const status = result.statusCode === 403 ? "forbidden" : "unauthorised";
|
|
3700
|
+
return {
|
|
3701
|
+
status,
|
|
3702
|
+
message: result.message
|
|
3703
|
+
};
|
|
3704
|
+
}
|
|
3705
|
+
__name(mapGuardResult, "mapGuardResult");
|
|
3706
|
+
async function registerHttpHandlers(app, handlers, result) {
|
|
3707
|
+
for (const def of handlers?.http?.handlers ?? []) {
|
|
3708
|
+
const callback = result.createRouteCallback(def.method, def.path, def.name) ?? await result.createRouteCallbackById(def.handler, def.location, def.name);
|
|
1883
3709
|
if (callback) {
|
|
1884
3710
|
app.registerHttpHandler(def.path, def.method, def.timeout, callback);
|
|
1885
3711
|
}
|
|
1886
3712
|
}
|
|
3713
|
+
}
|
|
3714
|
+
__name(registerHttpHandlers, "registerHttpHandlers");
|
|
3715
|
+
async function registerGuardHandlers(app, guards, result) {
|
|
3716
|
+
for (const guardDef of guards?.handlers ?? []) {
|
|
3717
|
+
const coreCallback = result.createGuardCallback(guardDef.name);
|
|
3718
|
+
if (coreCallback) {
|
|
3719
|
+
await app.registerGuardHandler(guardDef.name, async (_err, input) => {
|
|
3720
|
+
const coreResult = await coreCallback({
|
|
3721
|
+
token: input.token,
|
|
3722
|
+
method: input.request.method,
|
|
3723
|
+
path: input.request.path,
|
|
3724
|
+
headers: input.request.headers,
|
|
3725
|
+
query: input.request.query,
|
|
3726
|
+
cookies: input.request.cookies,
|
|
3727
|
+
body: input.request.body ?? null,
|
|
3728
|
+
requestId: input.request.requestId,
|
|
3729
|
+
clientIp: input.request.clientIp,
|
|
3730
|
+
auth: input.auth ?? {},
|
|
3731
|
+
handlerName: input.handlerName
|
|
3732
|
+
});
|
|
3733
|
+
return mapGuardResult(coreResult);
|
|
3734
|
+
});
|
|
3735
|
+
}
|
|
3736
|
+
}
|
|
3737
|
+
}
|
|
3738
|
+
__name(registerGuardHandlers, "registerGuardHandlers");
|
|
3739
|
+
async function registerWebSocketHandlers(app, websocket, result) {
|
|
3740
|
+
for (const def of websocket?.handlers ?? []) {
|
|
3741
|
+
const callback = result.createWebSocketCallback(def.route, def.name) ?? await result.createWebSocketCallbackById(def.handler, def.location, def.name);
|
|
3742
|
+
if (callback) {
|
|
3743
|
+
app.registerWebsocketHandler(def.route, callback);
|
|
3744
|
+
}
|
|
3745
|
+
}
|
|
3746
|
+
}
|
|
3747
|
+
__name(registerWebSocketHandlers, "registerWebSocketHandlers");
|
|
3748
|
+
async function registerConsumerHandlers(app, consumers, result) {
|
|
3749
|
+
for (const consumer of consumers?.consumers ?? []) {
|
|
3750
|
+
for (const def of consumer.handlers) {
|
|
3751
|
+
const tag = `source::${consumer.sourceId}::${def.name}`;
|
|
3752
|
+
const callback = result.createConsumerCallback(tag, def.name) ?? await result.createConsumerCallbackById(def.handler, def.location, def.name);
|
|
3753
|
+
if (callback) {
|
|
3754
|
+
app.registerConsumerHandler(tag, def.timeout, callback);
|
|
3755
|
+
}
|
|
3756
|
+
}
|
|
3757
|
+
}
|
|
3758
|
+
}
|
|
3759
|
+
__name(registerConsumerHandlers, "registerConsumerHandlers");
|
|
3760
|
+
async function registerScheduleHandlers(app, schedules, result) {
|
|
3761
|
+
for (const schedule of schedules?.schedules ?? []) {
|
|
3762
|
+
for (const def of schedule.handlers) {
|
|
3763
|
+
const tag = `source::${schedule.scheduleId}::${def.name}`;
|
|
3764
|
+
const callback = result.createScheduleCallback(tag, def.name) ?? await result.createScheduleCallbackById(def.handler, def.location, def.name);
|
|
3765
|
+
if (callback) {
|
|
3766
|
+
app.registerScheduleHandler(tag, def.timeout, callback);
|
|
3767
|
+
}
|
|
3768
|
+
}
|
|
3769
|
+
}
|
|
3770
|
+
}
|
|
3771
|
+
__name(registerScheduleHandlers, "registerScheduleHandlers");
|
|
3772
|
+
async function registerCustomHandlers(app, customHandlers, result) {
|
|
3773
|
+
for (const def of customHandlers?.handlers ?? []) {
|
|
3774
|
+
const callback = result.createCustomCallback(def.name) ?? await result.createCustomCallbackById(def.handler, def.location, def.name);
|
|
3775
|
+
if (callback) {
|
|
3776
|
+
app.registerCustomHandler(def.name, def.timeout, callback);
|
|
3777
|
+
}
|
|
3778
|
+
}
|
|
3779
|
+
}
|
|
3780
|
+
__name(registerCustomHandlers, "registerCustomHandlers");
|
|
3781
|
+
async function startRuntime(options) {
|
|
3782
|
+
const { app, appConfig } = await loadRuntime();
|
|
3783
|
+
const result = await bootstrapForRuntime();
|
|
3784
|
+
await registerHttpHandlers(app, appConfig.api, result);
|
|
3785
|
+
await registerGuardHandlers(app, appConfig.api?.guards, result);
|
|
3786
|
+
await registerWebSocketHandlers(app, appConfig.api?.websocket, result);
|
|
3787
|
+
await registerConsumerHandlers(app, appConfig.consumers, result);
|
|
3788
|
+
await registerScheduleHandlers(app, appConfig.schedules, result);
|
|
3789
|
+
await registerCustomHandlers(app, appConfig.customHandlers, result);
|
|
3790
|
+
if (appConfig.api?.websocket) {
|
|
3791
|
+
const sender = new RuntimeWebSocketSender(app.websocketRegistry());
|
|
3792
|
+
result.container.register(WebSocketSender, {
|
|
3793
|
+
useValue: sender
|
|
3794
|
+
});
|
|
3795
|
+
}
|
|
1887
3796
|
await app.run(options?.block ?? true);
|
|
1888
3797
|
}
|
|
1889
3798
|
__name(startRuntime, "startRuntime");
|
|
3799
|
+
|
|
3800
|
+
// src/index.ts
|
|
3801
|
+
import { WebSocketSender as WebSocketSender2 } from "@celerity-sdk/types";
|
|
3802
|
+
import { SourceType, BucketEventType, DatastoreEventType } from "@celerity-sdk/types";
|
|
1890
3803
|
export {
|
|
1891
3804
|
APP_CONFIG,
|
|
1892
3805
|
Action,
|
|
@@ -1894,15 +3807,24 @@ export {
|
|
|
1894
3807
|
BadGatewayException,
|
|
1895
3808
|
BadRequestException,
|
|
1896
3809
|
Body,
|
|
3810
|
+
BucketEventType,
|
|
3811
|
+
CONSUMER_HANDLER_METADATA,
|
|
3812
|
+
CONSUMER_METADATA,
|
|
1897
3813
|
CONTROLLER_METADATA,
|
|
1898
3814
|
CUSTOM_METADATA,
|
|
1899
3815
|
CelerityApplication,
|
|
1900
3816
|
CelerityFactory,
|
|
1901
3817
|
ConflictException,
|
|
3818
|
+
ConnectionId,
|
|
3819
|
+
Consumer,
|
|
3820
|
+
ConsumerTraceContext,
|
|
1902
3821
|
Container,
|
|
1903
3822
|
Controller,
|
|
1904
3823
|
Cookies,
|
|
3824
|
+
DatastoreEventType,
|
|
1905
3825
|
Delete,
|
|
3826
|
+
EventInput,
|
|
3827
|
+
EventType,
|
|
1906
3828
|
ForbiddenException,
|
|
1907
3829
|
GUARD_CUSTOM_METADATA,
|
|
1908
3830
|
GUARD_PROTECTEDBY_METADATA,
|
|
@@ -1917,20 +3839,31 @@ export {
|
|
|
1917
3839
|
Headers,
|
|
1918
3840
|
HttpException,
|
|
1919
3841
|
INJECT_METADATA,
|
|
3842
|
+
INVOKE_METADATA,
|
|
1920
3843
|
Inject,
|
|
1921
3844
|
Injectable,
|
|
1922
3845
|
InternalServerErrorException,
|
|
3846
|
+
Invoke,
|
|
3847
|
+
InvokeContext,
|
|
1923
3848
|
LAYER_METADATA,
|
|
1924
3849
|
MODULE_METADATA,
|
|
3850
|
+
MessageBody,
|
|
3851
|
+
MessageHandler,
|
|
3852
|
+
MessageId,
|
|
3853
|
+
Messages,
|
|
1925
3854
|
MethodNotAllowedException,
|
|
1926
3855
|
Module,
|
|
1927
3856
|
NotAcceptableException,
|
|
1928
3857
|
NotFoundException,
|
|
1929
3858
|
NotImplementedException,
|
|
3859
|
+
OnConnect,
|
|
3860
|
+
OnDisconnect,
|
|
3861
|
+
OnMessage,
|
|
1930
3862
|
Options,
|
|
1931
3863
|
PUBLIC_METADATA,
|
|
1932
3864
|
Param,
|
|
1933
3865
|
Patch,
|
|
3866
|
+
Payload,
|
|
1934
3867
|
Post,
|
|
1935
3868
|
ProtectedBy,
|
|
1936
3869
|
Public,
|
|
@@ -1939,24 +3872,52 @@ export {
|
|
|
1939
3872
|
ROUTE_PATH_METADATA,
|
|
1940
3873
|
RUNTIME_APP,
|
|
1941
3874
|
Req,
|
|
3875
|
+
RequestContext,
|
|
1942
3876
|
RequestId,
|
|
3877
|
+
RuntimeWebSocketSender,
|
|
3878
|
+
SCHEDULE_HANDLER_METADATA,
|
|
3879
|
+
ScheduleEventInput as ScheduleEventInputParam,
|
|
3880
|
+
ScheduleExpression,
|
|
3881
|
+
ScheduleHandler,
|
|
3882
|
+
ScheduleId,
|
|
3883
|
+
ScheduleInput,
|
|
1943
3884
|
ServerlessApplication,
|
|
1944
3885
|
ServiceUnavailableException,
|
|
1945
3886
|
SetMetadata,
|
|
3887
|
+
SourceType,
|
|
1946
3888
|
TestingApplication,
|
|
3889
|
+
Token,
|
|
1947
3890
|
TooManyRequestsException,
|
|
3891
|
+
USE_RESOURCE_METADATA,
|
|
1948
3892
|
UnauthorizedException,
|
|
1949
3893
|
UnprocessableEntityException,
|
|
1950
3894
|
UseLayer,
|
|
1951
3895
|
UseLayers,
|
|
3896
|
+
UseResource,
|
|
3897
|
+
UseResources,
|
|
3898
|
+
Vendor,
|
|
3899
|
+
WEBSOCKET_CONTROLLER_METADATA,
|
|
3900
|
+
WEBSOCKET_EVENT_METADATA,
|
|
3901
|
+
WebSocketController,
|
|
3902
|
+
WebSocketSender2 as WebSocketSender,
|
|
1952
3903
|
bootstrap,
|
|
1953
3904
|
bootstrapForRuntime,
|
|
1954
3905
|
buildModuleGraph,
|
|
3906
|
+
createConsumerHandler,
|
|
3907
|
+
createCustomHandler,
|
|
1955
3908
|
createDefaultSystemLayers,
|
|
3909
|
+
createGuard,
|
|
1956
3910
|
createHttpHandler,
|
|
3911
|
+
createScheduleHandler,
|
|
3912
|
+
createWebSocketHandler,
|
|
1957
3913
|
discoverModule,
|
|
1958
3914
|
disposeLayers,
|
|
1959
|
-
|
|
3915
|
+
executeConsumerPipeline,
|
|
3916
|
+
executeCustomPipeline,
|
|
3917
|
+
executeGuardPipeline,
|
|
3918
|
+
executeHttpPipeline,
|
|
3919
|
+
executeSchedulePipeline,
|
|
3920
|
+
executeWebSocketPipeline,
|
|
1960
3921
|
flattenMultiValueRecord,
|
|
1961
3922
|
getClassDependencyTokens,
|
|
1962
3923
|
getProviderDependencyTokens,
|
|
@@ -1965,12 +3926,27 @@ export {
|
|
|
1965
3926
|
httpPatch,
|
|
1966
3927
|
httpPost,
|
|
1967
3928
|
httpPut,
|
|
3929
|
+
mapConsumerEventInput,
|
|
1968
3930
|
mapRuntimeRequest,
|
|
3931
|
+
mapScheduleEventInput,
|
|
3932
|
+
mapToNapiEventResult,
|
|
1969
3933
|
mapToRuntimeResponse,
|
|
3934
|
+
mapWebSocketMessage,
|
|
3935
|
+
mockConsumerEvent,
|
|
1970
3936
|
mockRequest,
|
|
3937
|
+
mockScheduleEvent,
|
|
3938
|
+
mockWebSocketMessage,
|
|
1971
3939
|
registerModuleGraph,
|
|
1972
3940
|
resolveHandlerByModuleRef,
|
|
3941
|
+
routingKeyOf,
|
|
1973
3942
|
runLayerPipeline,
|
|
3943
|
+
scanConsumerHandlers,
|
|
3944
|
+
scanCustomHandlers,
|
|
3945
|
+
scanHttpGuards,
|
|
3946
|
+
scanHttpHandlers,
|
|
3947
|
+
scanModule,
|
|
3948
|
+
scanScheduleHandlers,
|
|
3949
|
+
scanWebSocketHandlers,
|
|
1974
3950
|
startRuntime,
|
|
1975
3951
|
tokenToString,
|
|
1976
3952
|
validate
|