@celerity-sdk/core 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1885 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+
4
+ // src/index.ts
5
+ import "reflect-metadata";
6
+
7
+ // src/decorators/controller.ts
8
+ import "reflect-metadata";
9
+
10
+ // src/metadata/constants.ts
11
+ var CONTROLLER_METADATA = /* @__PURE__ */ Symbol("celerity:controller");
12
+ var HTTP_METHOD_METADATA = /* @__PURE__ */ Symbol("celerity:http-method");
13
+ var ROUTE_PATH_METADATA = /* @__PURE__ */ Symbol("celerity:route-path");
14
+ var PARAM_METADATA = /* @__PURE__ */ Symbol("celerity:param");
15
+ var GUARD_PROTECTEDBY_METADATA = /* @__PURE__ */ Symbol("celerity:guard:protectedBy");
16
+ var GUARD_CUSTOM_METADATA = /* @__PURE__ */ Symbol("celerity:guard:custom");
17
+ var LAYER_METADATA = /* @__PURE__ */ Symbol("celerity:layer");
18
+ var MODULE_METADATA = /* @__PURE__ */ Symbol("celerity:module");
19
+ var INJECTABLE_METADATA = /* @__PURE__ */ Symbol("celerity:injectable");
20
+ var INJECT_METADATA = /* @__PURE__ */ Symbol("celerity:inject");
21
+ var PUBLIC_METADATA = /* @__PURE__ */ Symbol("celerity:public");
22
+ var CUSTOM_METADATA = /* @__PURE__ */ Symbol("celerity:custom-metadata");
23
+
24
+ // src/decorators/controller.ts
25
+ function Controller(prefix) {
26
+ return (target) => {
27
+ const metadata = {};
28
+ if (prefix !== void 0) {
29
+ metadata.prefix = prefix;
30
+ }
31
+ Reflect.defineMetadata(CONTROLLER_METADATA, metadata, target);
32
+ Reflect.defineMetadata(INJECTABLE_METADATA, true, target);
33
+ };
34
+ }
35
+ __name(Controller, "Controller");
36
+
37
+ // src/decorators/http.ts
38
+ import "reflect-metadata";
39
+ function createMethodDecorator(method, path = "/") {
40
+ return (target, propertyKey, descriptor) => {
41
+ Reflect.defineMetadata(HTTP_METHOD_METADATA, method, target, propertyKey);
42
+ Reflect.defineMetadata(ROUTE_PATH_METADATA, path, target, propertyKey);
43
+ return descriptor;
44
+ };
45
+ }
46
+ __name(createMethodDecorator, "createMethodDecorator");
47
+ function Get(path) {
48
+ return createMethodDecorator("GET", path);
49
+ }
50
+ __name(Get, "Get");
51
+ function Post(path) {
52
+ return createMethodDecorator("POST", path);
53
+ }
54
+ __name(Post, "Post");
55
+ function Put(path) {
56
+ return createMethodDecorator("PUT", path);
57
+ }
58
+ __name(Put, "Put");
59
+ function Patch(path) {
60
+ return createMethodDecorator("PATCH", path);
61
+ }
62
+ __name(Patch, "Patch");
63
+ function Delete(path) {
64
+ return createMethodDecorator("DELETE", path);
65
+ }
66
+ __name(Delete, "Delete");
67
+ function Head(path) {
68
+ return createMethodDecorator("HEAD", path);
69
+ }
70
+ __name(Head, "Head");
71
+ function Options(path) {
72
+ return createMethodDecorator("OPTIONS", path);
73
+ }
74
+ __name(Options, "Options");
75
+
76
+ // src/decorators/params.ts
77
+ import "reflect-metadata";
78
+ function createParamDecorator(type, keyOrSchema, schema) {
79
+ return (target, propertyKey, parameterIndex) => {
80
+ if (!propertyKey) return;
81
+ const existing = Reflect.getOwnMetadata(PARAM_METADATA, target, propertyKey) ?? [];
82
+ const meta = {
83
+ index: parameterIndex,
84
+ type
85
+ };
86
+ if (typeof keyOrSchema === "string") {
87
+ meta.key = keyOrSchema;
88
+ if (schema) meta.schema = schema;
89
+ } else if (keyOrSchema && typeof keyOrSchema === "object") {
90
+ meta.schema = keyOrSchema;
91
+ }
92
+ existing.push(meta);
93
+ Reflect.defineMetadata(PARAM_METADATA, existing, target, propertyKey);
94
+ };
95
+ }
96
+ __name(createParamDecorator, "createParamDecorator");
97
+ function Body(schema) {
98
+ return createParamDecorator("body", schema);
99
+ }
100
+ __name(Body, "Body");
101
+ function Query(keyOrSchema, schema) {
102
+ return createParamDecorator("query", keyOrSchema, schema);
103
+ }
104
+ __name(Query, "Query");
105
+ function Param(keyOrSchema, schema) {
106
+ return createParamDecorator("param", keyOrSchema, schema);
107
+ }
108
+ __name(Param, "Param");
109
+ function Headers(keyOrSchema, schema) {
110
+ return createParamDecorator("headers", keyOrSchema, schema);
111
+ }
112
+ __name(Headers, "Headers");
113
+ function Auth() {
114
+ return createParamDecorator("auth");
115
+ }
116
+ __name(Auth, "Auth");
117
+ function Req() {
118
+ return createParamDecorator("request");
119
+ }
120
+ __name(Req, "Req");
121
+ function Cookies(key) {
122
+ return createParamDecorator("cookies", key);
123
+ }
124
+ __name(Cookies, "Cookies");
125
+ function RequestId() {
126
+ return createParamDecorator("requestId");
127
+ }
128
+ __name(RequestId, "RequestId");
129
+ function extractParam(type, key, request) {
130
+ switch (type) {
131
+ case "body":
132
+ return request.textBody ? JSON.parse(request.textBody) : null;
133
+ case "query":
134
+ return key ? request.query[key] : request.query;
135
+ case "param":
136
+ return key ? request.pathParams[key] : request.pathParams;
137
+ case "headers":
138
+ return key ? request.headers[key] : request.headers;
139
+ case "auth":
140
+ return request.auth;
141
+ case "request":
142
+ return request;
143
+ case "cookies":
144
+ return key ? request.cookies[key] : request.cookies;
145
+ case "requestId":
146
+ return request.requestId;
147
+ }
148
+ }
149
+ __name(extractParam, "extractParam");
150
+
151
+ // src/decorators/guards.ts
152
+ import "reflect-metadata";
153
+ function Guard(name) {
154
+ return (target) => {
155
+ Reflect.defineMetadata(GUARD_CUSTOM_METADATA, name, target);
156
+ };
157
+ }
158
+ __name(Guard, "Guard");
159
+ function ProtectedBy(name) {
160
+ return (target, propertyKey, _descriptor) => {
161
+ if (propertyKey) {
162
+ const existing = Reflect.getOwnMetadata(GUARD_PROTECTEDBY_METADATA, target, propertyKey) ?? [];
163
+ Reflect.defineMetadata(GUARD_PROTECTEDBY_METADATA, [
164
+ name,
165
+ ...existing
166
+ ], target, propertyKey);
167
+ } else {
168
+ const existing = Reflect.getOwnMetadata(GUARD_PROTECTEDBY_METADATA, target) ?? [];
169
+ Reflect.defineMetadata(GUARD_PROTECTEDBY_METADATA, [
170
+ name,
171
+ ...existing
172
+ ], target);
173
+ }
174
+ };
175
+ }
176
+ __name(ProtectedBy, "ProtectedBy");
177
+ function Public() {
178
+ return (target, propertyKey, descriptor) => {
179
+ Reflect.defineMetadata(PUBLIC_METADATA, true, target, propertyKey);
180
+ return descriptor;
181
+ };
182
+ }
183
+ __name(Public, "Public");
184
+
185
+ // src/decorators/layer.ts
186
+ import "reflect-metadata";
187
+ function UseLayer(...layers) {
188
+ return (target, propertyKey, _descriptor) => {
189
+ if (propertyKey) {
190
+ const existing = Reflect.getOwnMetadata(LAYER_METADATA, target, propertyKey) ?? [];
191
+ Reflect.defineMetadata(LAYER_METADATA, [
192
+ ...layers,
193
+ ...existing
194
+ ], target, propertyKey);
195
+ } else {
196
+ const existing = Reflect.getOwnMetadata(LAYER_METADATA, target) ?? [];
197
+ Reflect.defineMetadata(LAYER_METADATA, [
198
+ ...layers,
199
+ ...existing
200
+ ], target);
201
+ }
202
+ };
203
+ }
204
+ __name(UseLayer, "UseLayer");
205
+ function UseLayers(layers) {
206
+ return UseLayer(...layers);
207
+ }
208
+ __name(UseLayers, "UseLayers");
209
+
210
+ // src/decorators/metadata.ts
211
+ import "reflect-metadata";
212
+ function SetMetadata(key, value) {
213
+ return (target, propertyKey, _descriptor) => {
214
+ if (propertyKey) {
215
+ const existing = Reflect.getOwnMetadata(CUSTOM_METADATA, target, propertyKey) ?? {};
216
+ Reflect.defineMetadata(CUSTOM_METADATA, {
217
+ ...existing,
218
+ [key]: value
219
+ }, target, propertyKey);
220
+ } else {
221
+ const existing = Reflect.getOwnMetadata(CUSTOM_METADATA, target) ?? {};
222
+ Reflect.defineMetadata(CUSTOM_METADATA, {
223
+ ...existing,
224
+ [key]: value
225
+ }, target);
226
+ }
227
+ };
228
+ }
229
+ __name(SetMetadata, "SetMetadata");
230
+ function Action(value) {
231
+ return SetMetadata("action", value);
232
+ }
233
+ __name(Action, "Action");
234
+
235
+ // src/decorators/injectable.ts
236
+ import "reflect-metadata";
237
+ function Injectable() {
238
+ return (target) => {
239
+ Reflect.defineMetadata(INJECTABLE_METADATA, true, target);
240
+ };
241
+ }
242
+ __name(Injectable, "Injectable");
243
+ function Inject(token) {
244
+ return (target, _propertyKey, parameterIndex) => {
245
+ const existing = Reflect.getOwnMetadata(INJECT_METADATA, target) ?? /* @__PURE__ */ new Map();
246
+ existing.set(parameterIndex, token);
247
+ Reflect.defineMetadata(INJECT_METADATA, existing, target);
248
+ };
249
+ }
250
+ __name(Inject, "Inject");
251
+
252
+ // src/decorators/module.ts
253
+ import "reflect-metadata";
254
+ function Module(metadata) {
255
+ return (target) => {
256
+ Reflect.defineMetadata(MODULE_METADATA, metadata, target);
257
+ };
258
+ }
259
+ __name(Module, "Module");
260
+
261
+ // src/errors/http-exception.ts
262
+ var HttpException = class extends Error {
263
+ static {
264
+ __name(this, "HttpException");
265
+ }
266
+ statusCode;
267
+ details;
268
+ constructor(statusCode, message, details) {
269
+ super(message), this.statusCode = statusCode, this.details = details;
270
+ this.name = "HttpException";
271
+ }
272
+ };
273
+ var BadRequestException = class extends HttpException {
274
+ static {
275
+ __name(this, "BadRequestException");
276
+ }
277
+ constructor(message = "Bad Request", details) {
278
+ super(400, message, details);
279
+ this.name = "BadRequestException";
280
+ }
281
+ };
282
+ var UnauthorizedException = class extends HttpException {
283
+ static {
284
+ __name(this, "UnauthorizedException");
285
+ }
286
+ constructor(message = "Unauthorized", details) {
287
+ super(401, message, details);
288
+ this.name = "UnauthorizedException";
289
+ }
290
+ };
291
+ var ForbiddenException = class extends HttpException {
292
+ static {
293
+ __name(this, "ForbiddenException");
294
+ }
295
+ constructor(message = "Forbidden", details) {
296
+ super(403, message, details);
297
+ this.name = "ForbiddenException";
298
+ }
299
+ };
300
+ var NotFoundException = class extends HttpException {
301
+ static {
302
+ __name(this, "NotFoundException");
303
+ }
304
+ constructor(message = "Not Found", details) {
305
+ super(404, message, details);
306
+ this.name = "NotFoundException";
307
+ }
308
+ };
309
+ var MethodNotAllowedException = class extends HttpException {
310
+ static {
311
+ __name(this, "MethodNotAllowedException");
312
+ }
313
+ constructor(message = "Method Not Allowed", details) {
314
+ super(405, message, details);
315
+ this.name = "MethodNotAllowedException";
316
+ }
317
+ };
318
+ var NotAcceptableException = class extends HttpException {
319
+ static {
320
+ __name(this, "NotAcceptableException");
321
+ }
322
+ constructor(message = "Not Acceptable", details) {
323
+ super(406, message, details);
324
+ this.name = "NotAcceptableException";
325
+ }
326
+ };
327
+ var ConflictException = class extends HttpException {
328
+ static {
329
+ __name(this, "ConflictException");
330
+ }
331
+ constructor(message = "Conflict", details) {
332
+ super(409, message, details);
333
+ this.name = "ConflictException";
334
+ }
335
+ };
336
+ var GoneException = class extends HttpException {
337
+ static {
338
+ __name(this, "GoneException");
339
+ }
340
+ constructor(message = "Gone", details) {
341
+ super(410, message, details);
342
+ this.name = "GoneException";
343
+ }
344
+ };
345
+ var UnprocessableEntityException = class extends HttpException {
346
+ static {
347
+ __name(this, "UnprocessableEntityException");
348
+ }
349
+ constructor(message = "Unprocessable Entity", details) {
350
+ super(422, message, details);
351
+ this.name = "UnprocessableEntityException";
352
+ }
353
+ };
354
+ var TooManyRequestsException = class extends HttpException {
355
+ static {
356
+ __name(this, "TooManyRequestsException");
357
+ }
358
+ constructor(message = "Too Many Requests", details) {
359
+ super(429, message, details);
360
+ this.name = "TooManyRequestsException";
361
+ }
362
+ };
363
+ var InternalServerErrorException = class extends HttpException {
364
+ static {
365
+ __name(this, "InternalServerErrorException");
366
+ }
367
+ constructor(message = "Internal Server Error", details) {
368
+ super(500, message, details);
369
+ this.name = "InternalServerErrorException";
370
+ }
371
+ };
372
+ var NotImplementedException = class extends HttpException {
373
+ static {
374
+ __name(this, "NotImplementedException");
375
+ }
376
+ constructor(message = "Not Implemented", details) {
377
+ super(501, message, details);
378
+ this.name = "NotImplementedException";
379
+ }
380
+ };
381
+ var BadGatewayException = class extends HttpException {
382
+ static {
383
+ __name(this, "BadGatewayException");
384
+ }
385
+ constructor(message = "Bad Gateway", details) {
386
+ super(502, message, details);
387
+ this.name = "BadGatewayException";
388
+ }
389
+ };
390
+ var ServiceUnavailableException = class extends HttpException {
391
+ static {
392
+ __name(this, "ServiceUnavailableException");
393
+ }
394
+ constructor(message = "Service Unavailable", details) {
395
+ super(503, message, details);
396
+ this.name = "ServiceUnavailableException";
397
+ }
398
+ };
399
+ var GatewayTimeoutException = class extends HttpException {
400
+ static {
401
+ __name(this, "GatewayTimeoutException");
402
+ }
403
+ constructor(message = "Gateway Timeout", details) {
404
+ super(504, message, details);
405
+ this.name = "GatewayTimeoutException";
406
+ }
407
+ };
408
+
409
+ // src/layers/validate.ts
410
+ var ValidationLayer = class ValidationLayer2 {
411
+ static {
412
+ __name(this, "ValidationLayer");
413
+ }
414
+ schemas;
415
+ constructor(schemas) {
416
+ this.schemas = schemas;
417
+ }
418
+ async handle(context, next) {
419
+ const { request } = context;
420
+ if (this.schemas.body && request.textBody) {
421
+ try {
422
+ const raw = JSON.parse(request.textBody);
423
+ context.metadata.set("validatedBody", this.schemas.body.parse(raw));
424
+ } catch (error) {
425
+ throw new BadRequestException("Body validation failed", formatError(error));
426
+ }
427
+ }
428
+ if (this.schemas.params) {
429
+ try {
430
+ context.metadata.set("validatedParams", this.schemas.params.parse(request.pathParams));
431
+ } catch (error) {
432
+ throw new BadRequestException("Path params validation failed", formatError(error));
433
+ }
434
+ }
435
+ if (this.schemas.query) {
436
+ try {
437
+ context.metadata.set("validatedQuery", this.schemas.query.parse(request.query));
438
+ } catch (error) {
439
+ throw new BadRequestException("Query validation failed", formatError(error));
440
+ }
441
+ }
442
+ if (this.schemas.headers) {
443
+ try {
444
+ context.metadata.set("validatedHeaders", this.schemas.headers.parse(request.headers));
445
+ } catch (error) {
446
+ throw new BadRequestException("Headers validation failed", formatError(error));
447
+ }
448
+ }
449
+ return next();
450
+ }
451
+ };
452
+ function formatError(error) {
453
+ if (error instanceof Error && "issues" in error) {
454
+ return error.issues;
455
+ }
456
+ if (error instanceof Error) {
457
+ return error.message;
458
+ }
459
+ return error;
460
+ }
461
+ __name(formatError, "formatError");
462
+ function validate(schemas) {
463
+ return new ValidationLayer(schemas);
464
+ }
465
+ __name(validate, "validate");
466
+
467
+ // src/layers/pipeline.ts
468
+ import createDebug from "debug";
469
+ 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);
473
+ let index = -1;
474
+ function dispatch(i) {
475
+ if (i <= index) {
476
+ return Promise.reject(new Error("next() called multiple times"));
477
+ }
478
+ index = i;
479
+ if (i >= resolved.length) {
480
+ return handler();
481
+ }
482
+ const current = resolved[i];
483
+ debug("layer[%d] %s", i, current.constructor.name);
484
+ return current.handle(context, () => dispatch(i + 1));
485
+ }
486
+ __name(dispatch, "dispatch");
487
+ return dispatch(0);
488
+ }
489
+ __name(runLayerPipeline, "runLayerPipeline");
490
+
491
+ // src/layers/system.ts
492
+ import { ConfigLayer } from "@celerity-sdk/config";
493
+ async function createDefaultSystemLayers() {
494
+ const layers = [];
495
+ try {
496
+ const pkg = "@celerity-sdk/telemetry";
497
+ const mod = await import(pkg);
498
+ const TelemetryLayerClass = mod.TelemetryLayer;
499
+ layers.push(new TelemetryLayerClass());
500
+ } catch {
501
+ }
502
+ layers.push(new ConfigLayer());
503
+ return layers;
504
+ }
505
+ __name(createDefaultSystemLayers, "createDefaultSystemLayers");
506
+
507
+ // src/layers/dispose.ts
508
+ async function disposeLayers(layers) {
509
+ for (const layer of [
510
+ ...layers
511
+ ].reverse()) {
512
+ if (typeof layer === "object" && "dispose" in layer) {
513
+ try {
514
+ await layer.dispose?.();
515
+ } catch {
516
+ }
517
+ }
518
+ }
519
+ }
520
+ __name(disposeLayers, "disposeLayers");
521
+
522
+ // src/metadata/handler-metadata.ts
523
+ var HandlerMetadataStore = class {
524
+ static {
525
+ __name(this, "HandlerMetadataStore");
526
+ }
527
+ decoratorData;
528
+ requestData = /* @__PURE__ */ new Map();
529
+ constructor(decoratorMetadata) {
530
+ this.decoratorData = new Map(Object.entries(decoratorMetadata));
531
+ }
532
+ get(key) {
533
+ if (this.requestData.has(key)) return this.requestData.get(key);
534
+ return this.decoratorData.get(key);
535
+ }
536
+ set(key, value) {
537
+ this.requestData.set(key, value);
538
+ }
539
+ has(key) {
540
+ return this.requestData.has(key) || this.decoratorData.has(key);
541
+ }
542
+ };
543
+
544
+ // src/di/container.ts
545
+ import "reflect-metadata";
546
+ import createDebug2 from "debug";
547
+
548
+ // src/di/dependency-tokens.ts
549
+ import "reflect-metadata";
550
+ function isClassProvider(p) {
551
+ return "useClass" in p;
552
+ }
553
+ __name(isClassProvider, "isClassProvider");
554
+ function isFactoryProvider(p) {
555
+ return "useFactory" in p;
556
+ }
557
+ __name(isFactoryProvider, "isFactoryProvider");
558
+ function getClassDependencyTokens(target) {
559
+ const paramTypes = Reflect.getMetadata("design:paramtypes", target) ?? [];
560
+ const injectOverrides = Reflect.getMetadata(INJECT_METADATA, target) ?? /* @__PURE__ */ new Map();
561
+ return paramTypes.map((paramType, index) => injectOverrides.get(index) ?? paramType);
562
+ }
563
+ __name(getClassDependencyTokens, "getClassDependencyTokens");
564
+ function getProviderDependencyTokens(provider) {
565
+ if (isClassProvider(provider)) {
566
+ return getClassDependencyTokens(provider.useClass);
567
+ }
568
+ if (isFactoryProvider(provider) && provider.inject) {
569
+ return [
570
+ ...provider.inject
571
+ ];
572
+ }
573
+ return [];
574
+ }
575
+ __name(getProviderDependencyTokens, "getProviderDependencyTokens");
576
+
577
+ // src/di/container.ts
578
+ var debug2 = createDebug2("celerity:core:di");
579
+ var CLOSE_METHODS = [
580
+ "close",
581
+ "end",
582
+ "quit",
583
+ "disconnect",
584
+ "$disconnect",
585
+ "destroy"
586
+ ];
587
+ function isClassProvider2(p) {
588
+ return "useClass" in p;
589
+ }
590
+ __name(isClassProvider2, "isClassProvider");
591
+ function isFactoryProvider2(p) {
592
+ return "useFactory" in p;
593
+ }
594
+ __name(isFactoryProvider2, "isFactoryProvider");
595
+ function isValueProvider(p) {
596
+ return "useValue" in p;
597
+ }
598
+ __name(isValueProvider, "isValueProvider");
599
+ function tokenToString(token) {
600
+ if (typeof token === "function") return token.name;
601
+ return String(token);
602
+ }
603
+ __name(tokenToString, "tokenToString");
604
+ function detectCloseMethod(value) {
605
+ if (typeof value !== "object" || value === null) return null;
606
+ const obj = value;
607
+ for (const method of CLOSE_METHODS) {
608
+ if (typeof obj[method] === "function") {
609
+ return () => obj[method]();
610
+ }
611
+ }
612
+ return null;
613
+ }
614
+ __name(detectCloseMethod, "detectCloseMethod");
615
+ var Container = class {
616
+ static {
617
+ __name(this, "Container");
618
+ }
619
+ providers = /* @__PURE__ */ new Map();
620
+ instances = /* @__PURE__ */ new Map();
621
+ resolving = /* @__PURE__ */ new Set();
622
+ edges = /* @__PURE__ */ new Map();
623
+ closeStack = [];
624
+ trackedTokens = /* @__PURE__ */ new Set();
625
+ register(token, provider) {
626
+ const type = isClassProvider2(provider) ? "class" : isFactoryProvider2(provider) ? "factory" : "value";
627
+ debug2("register %s (%s)", tokenToString(token), type);
628
+ this.providers.set(token, provider);
629
+ if (isValueProvider(provider)) {
630
+ this.trackCloseable(token, provider.useValue, provider.onClose);
631
+ }
632
+ }
633
+ registerClass(target) {
634
+ debug2("register %s (class)", target.name);
635
+ this.providers.set(target, {
636
+ useClass: target
637
+ });
638
+ }
639
+ registerValue(token, value) {
640
+ debug2("registerValue %s", tokenToString(token));
641
+ this.instances.set(token, value);
642
+ this.trackCloseable(token, value);
643
+ }
644
+ async resolve(token) {
645
+ const name = tokenToString(token);
646
+ if (this.instances.has(token)) {
647
+ debug2("resolve %s \u2192 cached", name);
648
+ return this.instances.get(token);
649
+ }
650
+ if (this.resolving.has(token)) {
651
+ const path = [
652
+ ...this.resolving,
653
+ token
654
+ ].map(tokenToString).join(" \u2192 ");
655
+ throw new Error(`Circular dependency detected: ${path}`);
656
+ }
657
+ debug2("resolve %s \u2192 constructing", name);
658
+ this.resolving.add(token);
659
+ try {
660
+ const provider = this.providers.get(token);
661
+ if (!provider) {
662
+ if (typeof token === "function") {
663
+ return this.constructClass(token);
664
+ }
665
+ throw new Error(`No provider registered for ${tokenToString(token)}.
666
+ Ensure the module providing it is included in your module's "imports" array,
667
+ or register a provider for it directly.`);
668
+ }
669
+ if (isFactoryProvider2(provider) && provider.inject) {
670
+ this.recordEdges(token, provider.inject);
671
+ }
672
+ const instance = await this.createFromProvider(provider);
673
+ this.instances.set(token, instance);
674
+ if (!isValueProvider(provider)) {
675
+ this.trackCloseable(token, instance, provider.onClose);
676
+ }
677
+ return instance;
678
+ } finally {
679
+ this.resolving.delete(token);
680
+ }
681
+ }
682
+ async resolveClass(target) {
683
+ if (this.instances.has(target)) {
684
+ return this.instances.get(target);
685
+ }
686
+ if (this.resolving.has(target)) {
687
+ const path = [
688
+ ...this.resolving,
689
+ target
690
+ ].map(tokenToString).join(" \u2192 ");
691
+ throw new Error(`Circular dependency detected: ${path}`);
692
+ }
693
+ this.resolving.add(target);
694
+ try {
695
+ return this.constructClass(target);
696
+ } finally {
697
+ this.resolving.delete(target);
698
+ }
699
+ }
700
+ has(token) {
701
+ return this.instances.has(token) || this.providers.has(token);
702
+ }
703
+ getDependencies(token) {
704
+ return this.edges.get(token) ?? /* @__PURE__ */ new Set();
705
+ }
706
+ async closeAll() {
707
+ debug2("closeAll: %d resources", this.closeStack.length);
708
+ const entries = [
709
+ ...this.closeStack
710
+ ].reverse();
711
+ for (const entry of entries) {
712
+ try {
713
+ debug2("closing %s", tokenToString(entry.token));
714
+ await entry.close();
715
+ } catch {
716
+ }
717
+ }
718
+ this.closeStack = [];
719
+ this.trackedTokens.clear();
720
+ }
721
+ /**
722
+ * Validates that all registered providers have resolvable dependencies.
723
+ * Call after all module providers are registered but before resolution.
724
+ * Throws a descriptive error listing ALL missing dependencies at once.
725
+ */
726
+ validateDependencies() {
727
+ const missing = [];
728
+ const visited = /* @__PURE__ */ new Set();
729
+ const walk = /* @__PURE__ */ __name((token) => {
730
+ if (visited.has(token)) return;
731
+ visited.add(token);
732
+ let depTokens;
733
+ const provider = this.providers.get(token);
734
+ if (provider) {
735
+ depTokens = this.getProviderDependencyTokens(provider);
736
+ } else if (typeof token === "function") {
737
+ depTokens = this.getClassDependencyTokens(token);
738
+ } else {
739
+ return;
740
+ }
741
+ for (const dep of depTokens) {
742
+ if (this.providers.has(dep) || this.instances.has(dep)) {
743
+ walk(dep);
744
+ } else if (typeof dep === "function") {
745
+ walk(dep);
746
+ } else {
747
+ missing.push({
748
+ consumer: tokenToString(token),
749
+ dependency: tokenToString(dep)
750
+ });
751
+ }
752
+ }
753
+ }, "walk");
754
+ for (const token of this.providers.keys()) {
755
+ walk(token);
756
+ }
757
+ if (missing.length > 0) {
758
+ const details = missing.map(({ consumer, dependency }) => ` ${consumer} requires ${dependency} \u2014 no provider registered`).join("\n");
759
+ throw new Error(`Unresolvable dependencies detected during bootstrap:
760
+
761
+ ${details}
762
+
763
+ For each unresolved dependency, check that the module providing it is included
764
+ in your root module's "imports" array, or register a provider for it directly.`);
765
+ }
766
+ }
767
+ getClassDependencyTokens(target) {
768
+ return getClassDependencyTokens(target);
769
+ }
770
+ getProviderDependencyTokens(provider) {
771
+ return getProviderDependencyTokens(provider);
772
+ }
773
+ /**
774
+ * Constructs a class by resolving constructor dependencies via design:paramtypes.
775
+ * Does NOT manage the resolving set — callers (resolve/resolveClass) own cycle detection.
776
+ */
777
+ async constructClass(target) {
778
+ if (this.instances.has(target)) {
779
+ return this.instances.get(target);
780
+ }
781
+ const isInjectable = Reflect.getOwnMetadata(INJECTABLE_METADATA, target) === true;
782
+ if (!isInjectable && target.length > 0) {
783
+ throw new Error(`Class ${target.name} has constructor parameters but is not decorated with @Injectable(). Add @Injectable() to enable dependency injection, or use a factory provider.`);
784
+ }
785
+ const depTokens = this.getClassDependencyTokens(target);
786
+ debug2("construct %s deps=[%s]", target.name, depTokens.map(tokenToString).join(", "));
787
+ this.recordEdges(target, depTokens);
788
+ const deps = [];
789
+ for (const t of depTokens) {
790
+ deps.push(await this.resolve(t));
791
+ }
792
+ const instance = new target(...deps);
793
+ this.instances.set(target, instance);
794
+ this.trackCloseable(target, instance);
795
+ return instance;
796
+ }
797
+ recordEdges(from, to) {
798
+ let set = this.edges.get(from);
799
+ if (!set) {
800
+ set = /* @__PURE__ */ new Set();
801
+ this.edges.set(from, set);
802
+ }
803
+ for (const dep of to) {
804
+ set.add(dep);
805
+ }
806
+ }
807
+ trackCloseable(token, value, onClose) {
808
+ if (this.trackedTokens.has(token)) return;
809
+ if (onClose) {
810
+ this.closeStack.push({
811
+ token,
812
+ close: /* @__PURE__ */ __name(() => onClose(value), "close")
813
+ });
814
+ this.trackedTokens.add(token);
815
+ return;
816
+ }
817
+ const closeFn = detectCloseMethod(value);
818
+ if (closeFn) {
819
+ this.closeStack.push({
820
+ token,
821
+ close: closeFn
822
+ });
823
+ this.trackedTokens.add(token);
824
+ }
825
+ }
826
+ async createFromProvider(provider) {
827
+ if (isValueProvider(provider)) {
828
+ return provider.useValue;
829
+ }
830
+ if (isClassProvider2(provider)) {
831
+ return this.constructClass(provider.useClass);
832
+ }
833
+ if (isFactoryProvider2(provider)) {
834
+ const deps = provider.inject ? await Promise.all(provider.inject.map((t) => this.resolve(t))) : [];
835
+ return provider.useFactory(...deps);
836
+ }
837
+ throw new Error("Invalid provider configuration");
838
+ }
839
+ };
840
+
841
+ // src/di/tokens.ts
842
+ var APP_CONFIG = /* @__PURE__ */ Symbol("celerity:app-config");
843
+ var RUNTIME_APP = /* @__PURE__ */ Symbol("celerity:runtime-app");
844
+
845
+ // src/application/factory.ts
846
+ import createDebug8 from "debug";
847
+
848
+ // src/bootstrap/bootstrap.ts
849
+ import "reflect-metadata";
850
+ import createDebug5 from "debug";
851
+
852
+ // src/handlers/registry.ts
853
+ import "reflect-metadata";
854
+ import createDebug4 from "debug";
855
+ import { joinHandlerPath } from "@celerity-sdk/common";
856
+
857
+ // src/bootstrap/module-graph.ts
858
+ import "reflect-metadata";
859
+ import createDebug3 from "debug";
860
+ var debug3 = createDebug3("celerity:core:bootstrap");
861
+ function buildModuleGraph(rootModule) {
862
+ const graph = /* @__PURE__ */ new Map();
863
+ const resolving = /* @__PURE__ */ new Set();
864
+ function walk(moduleClass, importChain) {
865
+ if (graph.has(moduleClass)) {
866
+ debug3("walk %s \u2192 already visited", moduleClass.name);
867
+ return;
868
+ }
869
+ if (resolving.has(moduleClass)) {
870
+ const cyclePath = [
871
+ ...importChain,
872
+ moduleClass
873
+ ].map((m) => m.name).join(" \u2192 ");
874
+ throw new Error(`Circular module import detected: ${cyclePath}`);
875
+ }
876
+ resolving.add(moduleClass);
877
+ const metadata = Reflect.getOwnMetadata(MODULE_METADATA, moduleClass);
878
+ if (!metadata) {
879
+ resolving.delete(moduleClass);
880
+ graph.set(moduleClass, {
881
+ moduleClass,
882
+ ownTokens: /* @__PURE__ */ new Set(),
883
+ exports: /* @__PURE__ */ new Set(),
884
+ imports: [],
885
+ controllers: [],
886
+ functionHandlers: [],
887
+ providers: []
888
+ });
889
+ return;
890
+ }
891
+ const imports = metadata.imports ?? [];
892
+ for (const imported of imports) {
893
+ walk(imported, [
894
+ ...importChain,
895
+ moduleClass
896
+ ]);
897
+ }
898
+ const ownTokens = /* @__PURE__ */ new Set();
899
+ const providers = metadata.providers ?? [];
900
+ for (const provider of providers) {
901
+ if (typeof provider === "function") {
902
+ ownTokens.add(provider);
903
+ } else {
904
+ const typed = provider;
905
+ ownTokens.add(typed.provide);
906
+ }
907
+ }
908
+ const controllers = metadata.controllers ?? [];
909
+ for (const controller of controllers) {
910
+ ownTokens.add(controller);
911
+ }
912
+ const exportTokens = new Set(metadata.exports ?? []);
913
+ resolving.delete(moduleClass);
914
+ debug3("walk %s: %d providers, %d controllers, %d imports", moduleClass.name, providers.length, controllers.length, imports.length);
915
+ graph.set(moduleClass, {
916
+ moduleClass,
917
+ ownTokens,
918
+ exports: exportTokens,
919
+ imports,
920
+ controllers,
921
+ functionHandlers: metadata.functionHandlers ?? [],
922
+ providers
923
+ });
924
+ }
925
+ __name(walk, "walk");
926
+ walk(rootModule, []);
927
+ return graph;
928
+ }
929
+ __name(buildModuleGraph, "buildModuleGraph");
930
+ function registerModuleGraph(graph, container) {
931
+ for (const [, node] of graph) {
932
+ for (const provider of node.providers) {
933
+ if (typeof provider === "function") {
934
+ container.registerClass(provider);
935
+ } else {
936
+ const typed = provider;
937
+ container.register(typed.provide, typed);
938
+ }
939
+ }
940
+ for (const controller of node.controllers) {
941
+ if (!container.has(controller)) {
942
+ container.registerClass(controller);
943
+ }
944
+ }
945
+ }
946
+ }
947
+ __name(registerModuleGraph, "registerModuleGraph");
948
+ function walkModuleGraph(rootModule, container) {
949
+ const graph = buildModuleGraph(rootModule);
950
+ registerModuleGraph(graph, container);
951
+ return graph;
952
+ }
953
+ __name(walkModuleGraph, "walkModuleGraph");
954
+ function validateModuleGraph(graph, container) {
955
+ const diagnostics = [];
956
+ for (const [, node] of graph) {
957
+ for (const exportToken of node.exports) {
958
+ if (!node.ownTokens.has(exportToken)) {
959
+ diagnostics.push({
960
+ type: "invalid_export",
961
+ message: `${node.moduleClass.name} exports ${tokenToString(exportToken)}, but that token is not provided by this module.`
962
+ });
963
+ }
964
+ }
965
+ const visibleTokens = new Set(node.ownTokens);
966
+ for (const importedModule of node.imports) {
967
+ const importedNode = graph.get(importedModule);
968
+ if (importedNode) {
969
+ for (const exportedToken of importedNode.exports) {
970
+ visibleTokens.add(exportedToken);
971
+ }
972
+ }
973
+ }
974
+ for (const provider of node.providers) {
975
+ let depTokens;
976
+ let consumerToken;
977
+ if (typeof provider === "function") {
978
+ consumerToken = provider;
979
+ depTokens = getClassDependencyTokens(provider);
980
+ } else {
981
+ const typed = provider;
982
+ consumerToken = typed.provide;
983
+ depTokens = getProviderDependencyTokens(typed);
984
+ }
985
+ checkDependencies(consumerToken, depTokens, visibleTokens, node.moduleClass, graph, container, diagnostics);
986
+ }
987
+ for (const controller of node.controllers) {
988
+ const depTokens = getClassDependencyTokens(controller);
989
+ checkDependencies(controller, depTokens, visibleTokens, node.moduleClass, graph, container, diagnostics);
990
+ }
991
+ }
992
+ debug3("validateModuleGraph: %d modules, %d diagnostics", graph.size, diagnostics.length);
993
+ if (diagnostics.length > 0) {
994
+ const details = diagnostics.map((d) => ` ${d.message}`).join("\n");
995
+ throw new Error(`Module validation errors:
996
+
997
+ ${details}`);
998
+ }
999
+ }
1000
+ __name(validateModuleGraph, "validateModuleGraph");
1001
+ function checkDependencies(consumer, depTokens, visibleTokens, moduleClass, graph, container, diagnostics) {
1002
+ for (const dep of depTokens) {
1003
+ if (visibleTokens.has(dep)) continue;
1004
+ const ownerModule = findTokenOwner(dep, graph);
1005
+ if (ownerModule) {
1006
+ const ownerNode = graph.get(ownerModule);
1007
+ if (ownerNode.exports.has(dep)) {
1008
+ diagnostics.push({
1009
+ type: "export_violation",
1010
+ message: `${tokenToString(consumer)} in ${moduleClass.name} depends on ${tokenToString(dep)}, which is exported from ${ownerModule.name} but ${moduleClass.name} does not import ${ownerModule.name}. Add ${ownerModule.name} to ${moduleClass.name}'s "imports" array.`
1011
+ });
1012
+ } else {
1013
+ diagnostics.push({
1014
+ type: "export_violation",
1015
+ message: `${tokenToString(consumer)} in ${moduleClass.name} depends on ${tokenToString(dep)}, but ${tokenToString(dep)} is not exported from ${ownerModule.name}. Add ${tokenToString(dep)} to ${ownerModule.name}'s "exports" array.`
1016
+ });
1017
+ }
1018
+ continue;
1019
+ }
1020
+ if (typeof dep === "function") {
1021
+ if (!container.has(dep)) {
1022
+ container.registerClass(dep);
1023
+ }
1024
+ visibleTokens.add(dep);
1025
+ const adoptedDeps = getClassDependencyTokens(dep);
1026
+ checkDependencies(dep, adoptedDeps, visibleTokens, moduleClass, graph, container, diagnostics);
1027
+ continue;
1028
+ }
1029
+ diagnostics.push({
1030
+ type: "missing_dependency",
1031
+ message: `${tokenToString(consumer)} in ${moduleClass.name} requires ${tokenToString(dep)} \u2014 no provider registered. Ensure the module providing it is included in your module's "imports" array, or register a provider for it directly.`
1032
+ });
1033
+ }
1034
+ }
1035
+ __name(checkDependencies, "checkDependencies");
1036
+ function findTokenOwner(token, graph) {
1037
+ for (const [, node] of graph) {
1038
+ if (node.ownTokens.has(token)) {
1039
+ return node.moduleClass;
1040
+ }
1041
+ }
1042
+ return null;
1043
+ }
1044
+ __name(findTokenOwner, "findTokenOwner");
1045
+
1046
+ // src/handlers/registry.ts
1047
+ var debug4 = createDebug4("celerity:core:registry");
1048
+ var HandlerRegistry = class {
1049
+ static {
1050
+ __name(this, "HandlerRegistry");
1051
+ }
1052
+ handlers = [];
1053
+ getHandler(path, method) {
1054
+ const found = this.handlers.find((h) => h.path !== void 0 && h.method !== void 0 && matchRoute(h.path, path) && h.method === method);
1055
+ debug4("getHandler %s %s \u2192 %s", method, path, found ? "matched" : "not found");
1056
+ return found;
1057
+ }
1058
+ getAllHandlers() {
1059
+ return [
1060
+ ...this.handlers
1061
+ ];
1062
+ }
1063
+ async populateFromGraph(graph, container) {
1064
+ for (const [, node] of graph) {
1065
+ for (const controllerClass of node.controllers) {
1066
+ await this.registerClassHandler(controllerClass, container);
1067
+ }
1068
+ for (const fnHandler of node.functionHandlers) {
1069
+ this.registerFunctionHandler(fnHandler);
1070
+ }
1071
+ }
1072
+ }
1073
+ async scanModule(moduleClass, container) {
1074
+ const graph = buildModuleGraph(moduleClass);
1075
+ registerModuleGraph(graph, container);
1076
+ await this.populateFromGraph(graph, container);
1077
+ }
1078
+ async registerClassHandler(controllerClass, container) {
1079
+ const controllerMeta = Reflect.getOwnMetadata(CONTROLLER_METADATA, controllerClass);
1080
+ if (!controllerMeta) return;
1081
+ const instance = await container.resolve(controllerClass);
1082
+ const prototype = Object.getPrototypeOf(instance);
1083
+ const methods = Object.getOwnPropertyNames(prototype).filter((name) => name !== "constructor");
1084
+ const classProtectedBy = Reflect.getOwnMetadata(GUARD_PROTECTEDBY_METADATA, controllerClass) ?? [];
1085
+ const classLayers = Reflect.getOwnMetadata(LAYER_METADATA, controllerClass) ?? [];
1086
+ const classCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, controllerClass) ?? {};
1087
+ for (const methodName of methods) {
1088
+ const method = Reflect.getOwnMetadata(HTTP_METHOD_METADATA, prototype, methodName);
1089
+ if (!method) continue;
1090
+ const routePath = Reflect.getOwnMetadata(ROUTE_PATH_METADATA, prototype, methodName) ?? "/";
1091
+ const fullPath = joinHandlerPath(controllerMeta.prefix ?? "", routePath);
1092
+ const methodProtectedBy = Reflect.getOwnMetadata(GUARD_PROTECTEDBY_METADATA, prototype, methodName) ?? [];
1093
+ const methodLayers = Reflect.getOwnMetadata(LAYER_METADATA, prototype, methodName) ?? [];
1094
+ const paramMetadata = Reflect.getOwnMetadata(PARAM_METADATA, prototype, methodName) ?? [];
1095
+ const isPublic = Reflect.getOwnMetadata(PUBLIC_METADATA, prototype, methodName) === true;
1096
+ const methodCustomMetadata = Reflect.getOwnMetadata(CUSTOM_METADATA, prototype, methodName) ?? {};
1097
+ const descriptor = Object.getOwnPropertyDescriptor(prototype, methodName);
1098
+ if (!descriptor?.value || typeof descriptor.value !== "function") continue;
1099
+ const layers = [
1100
+ ...classLayers,
1101
+ ...methodLayers
1102
+ ];
1103
+ const validationSchemas = buildValidationSchemasFromParams(paramMetadata);
1104
+ if (validationSchemas) {
1105
+ layers.unshift(validate(validationSchemas));
1106
+ }
1107
+ debug4("registerClassHandler: %s %s (%s.%s)", method, fullPath, controllerClass.name, methodName);
1108
+ this.handlers.push({
1109
+ path: fullPath,
1110
+ method,
1111
+ protectedBy: [
1112
+ ...classProtectedBy,
1113
+ ...methodProtectedBy
1114
+ ],
1115
+ layers,
1116
+ isPublic,
1117
+ paramMetadata,
1118
+ customMetadata: {
1119
+ ...classCustomMetadata,
1120
+ ...methodCustomMetadata
1121
+ },
1122
+ handlerFn: descriptor.value,
1123
+ handlerInstance: instance
1124
+ });
1125
+ }
1126
+ }
1127
+ registerFunctionHandler(definition) {
1128
+ if (definition.type !== "http") return;
1129
+ const meta = definition.metadata;
1130
+ const layers = [
1131
+ ...meta.layers ?? []
1132
+ ];
1133
+ if (meta.schema) {
1134
+ const schemas = {};
1135
+ if (meta.schema.body) schemas.body = meta.schema.body;
1136
+ if (meta.schema.query) schemas.query = meta.schema.query;
1137
+ if (meta.schema.params) schemas.params = meta.schema.params;
1138
+ if (meta.schema.headers) schemas.headers = meta.schema.headers;
1139
+ if (Object.keys(schemas).length > 0) {
1140
+ layers.unshift(validate(schemas));
1141
+ }
1142
+ }
1143
+ debug4("registerFunctionHandler: %s", meta.method && meta.path ? `${meta.method} ${meta.path}` : "(no route)");
1144
+ this.handlers.push({
1145
+ path: meta.path,
1146
+ method: meta.method,
1147
+ protectedBy: [],
1148
+ layers,
1149
+ isPublic: false,
1150
+ paramMetadata: [],
1151
+ customMetadata: meta.customMetadata ?? {},
1152
+ handlerFn: definition.handler,
1153
+ isFunctionHandler: true,
1154
+ injectTokens: meta.inject ?? []
1155
+ });
1156
+ }
1157
+ };
1158
+ function matchRoute(pattern, actual) {
1159
+ const patternParts = pattern.split("/").filter(Boolean);
1160
+ const actualParts = actual.split("/").filter(Boolean);
1161
+ if (patternParts.length !== actualParts.length) return false;
1162
+ return patternParts.every((part, i) => part.startsWith("{") || part === actualParts[i]);
1163
+ }
1164
+ __name(matchRoute, "matchRoute");
1165
+ var PARAM_TYPE_TO_SCHEMA_KEY = {
1166
+ body: "body",
1167
+ query: "query",
1168
+ param: "params",
1169
+ headers: "headers"
1170
+ };
1171
+ function buildValidationSchemasFromParams(paramMetadata) {
1172
+ const wholeObjectSchemas = /* @__PURE__ */ new Map();
1173
+ const perKeySchemas = /* @__PURE__ */ new Map();
1174
+ for (const meta of paramMetadata) {
1175
+ if (!meta.schema) continue;
1176
+ const schemaKey = PARAM_TYPE_TO_SCHEMA_KEY[meta.type];
1177
+ if (!schemaKey) continue;
1178
+ if (meta.key) {
1179
+ let keyMap = perKeySchemas.get(schemaKey);
1180
+ if (!keyMap) {
1181
+ keyMap = /* @__PURE__ */ new Map();
1182
+ perKeySchemas.set(schemaKey, keyMap);
1183
+ }
1184
+ keyMap.set(meta.key, meta.schema);
1185
+ } else {
1186
+ wholeObjectSchemas.set(schemaKey, meta.schema);
1187
+ }
1188
+ }
1189
+ const schemas = {};
1190
+ let hasSchemas = false;
1191
+ for (const key of [
1192
+ "body",
1193
+ "query",
1194
+ "params",
1195
+ "headers"
1196
+ ]) {
1197
+ if (wholeObjectSchemas.has(key)) {
1198
+ schemas[key] = wholeObjectSchemas.get(key);
1199
+ hasSchemas = true;
1200
+ } else if (perKeySchemas.has(key)) {
1201
+ schemas[key] = composeKeySchemas(perKeySchemas.get(key));
1202
+ hasSchemas = true;
1203
+ }
1204
+ }
1205
+ return hasSchemas ? schemas : null;
1206
+ }
1207
+ __name(buildValidationSchemasFromParams, "buildValidationSchemasFromParams");
1208
+ function composeKeySchemas(keySchemas) {
1209
+ return {
1210
+ parse(data) {
1211
+ const record = data;
1212
+ const result = {
1213
+ ...record
1214
+ };
1215
+ for (const [key, schema] of keySchemas) {
1216
+ if (key in result) {
1217
+ result[key] = schema.parse(result[key]);
1218
+ }
1219
+ }
1220
+ return result;
1221
+ }
1222
+ };
1223
+ }
1224
+ __name(composeKeySchemas, "composeKeySchemas");
1225
+
1226
+ // src/bootstrap/bootstrap.ts
1227
+ var debug5 = createDebug5("celerity:core:bootstrap");
1228
+ async function bootstrap(rootModule) {
1229
+ debug5("bootstrap: starting from %s", rootModule.name);
1230
+ const container = new Container();
1231
+ const registry = new HandlerRegistry();
1232
+ const graph = walkModuleGraph(rootModule, container);
1233
+ validateModuleGraph(graph, container);
1234
+ await registry.populateFromGraph(graph, container);
1235
+ debug5("bootstrap: complete \u2014 %d modules, %d handlers", graph.size, registry.getAllHandlers().length);
1236
+ return {
1237
+ container,
1238
+ registry
1239
+ };
1240
+ }
1241
+ __name(bootstrap, "bootstrap");
1242
+
1243
+ // src/application/application.ts
1244
+ import createDebug6 from "debug";
1245
+ var debug6 = createDebug6("celerity:core:factory");
1246
+ var CelerityApplication = class {
1247
+ static {
1248
+ __name(this, "CelerityApplication");
1249
+ }
1250
+ registry;
1251
+ container;
1252
+ systemLayers;
1253
+ appLayers;
1254
+ runtimeApp;
1255
+ constructor(registry, container, systemLayers = [], appLayers = [], runtimeApp) {
1256
+ this.registry = registry;
1257
+ this.container = container;
1258
+ this.systemLayers = systemLayers;
1259
+ this.appLayers = appLayers;
1260
+ this.runtimeApp = runtimeApp;
1261
+ }
1262
+ async start() {
1263
+ if (this.runtimeApp && typeof this.runtimeApp === "object") {
1264
+ const app = this.runtimeApp;
1265
+ await app.run(false);
1266
+ }
1267
+ }
1268
+ async close() {
1269
+ debug6("close: shutting down application");
1270
+ if (this.runtimeApp && typeof this.runtimeApp === "object") {
1271
+ const app = this.runtimeApp;
1272
+ await app.shutdown();
1273
+ }
1274
+ await this.container.closeAll();
1275
+ await disposeLayers([
1276
+ ...this.systemLayers,
1277
+ ...this.appLayers
1278
+ ]);
1279
+ }
1280
+ getContainer() {
1281
+ return this.container;
1282
+ }
1283
+ getRegistry() {
1284
+ return this.registry;
1285
+ }
1286
+ getSystemLayers() {
1287
+ return this.systemLayers;
1288
+ }
1289
+ getAppLayers() {
1290
+ return this.appLayers;
1291
+ }
1292
+ };
1293
+
1294
+ // src/application/serverless.ts
1295
+ var ServerlessApplication = class {
1296
+ static {
1297
+ __name(this, "ServerlessApplication");
1298
+ }
1299
+ registry;
1300
+ container;
1301
+ adapter;
1302
+ systemLayers;
1303
+ appLayers;
1304
+ handler = null;
1305
+ constructor(registry, container, adapter, systemLayers = [], appLayers = []) {
1306
+ this.registry = registry;
1307
+ this.container = container;
1308
+ this.adapter = adapter;
1309
+ this.systemLayers = systemLayers;
1310
+ this.appLayers = appLayers;
1311
+ }
1312
+ async start() {
1313
+ this.handler = this.adapter.createHandler(this.registry, {
1314
+ container: this.container,
1315
+ systemLayers: this.systemLayers,
1316
+ appLayers: this.appLayers
1317
+ });
1318
+ return this.handler;
1319
+ }
1320
+ async close() {
1321
+ await this.container.closeAll();
1322
+ await disposeLayers([
1323
+ ...this.systemLayers,
1324
+ ...this.appLayers
1325
+ ]);
1326
+ }
1327
+ getHandler() {
1328
+ if (!this.handler) {
1329
+ throw new Error("ServerlessApplication.start() must be called before getHandler()");
1330
+ }
1331
+ return this.handler;
1332
+ }
1333
+ getContainer() {
1334
+ return this.container;
1335
+ }
1336
+ getRegistry() {
1337
+ return this.registry;
1338
+ }
1339
+ };
1340
+
1341
+ // src/handlers/pipeline.ts
1342
+ import createDebug7 from "debug";
1343
+
1344
+ // src/functions/context.ts
1345
+ function buildHttpRequest(request, metadata) {
1346
+ const validatedBody = metadata.get("validatedBody");
1347
+ let body;
1348
+ if (validatedBody !== void 0) {
1349
+ body = validatedBody;
1350
+ } else if (request.binaryBody) {
1351
+ body = request.binaryBody;
1352
+ } else if (request.textBody) {
1353
+ body = JSON.parse(request.textBody);
1354
+ } else {
1355
+ body = null;
1356
+ }
1357
+ return {
1358
+ method: request.method,
1359
+ path: request.path,
1360
+ params: metadata.get("validatedParams") ?? request.pathParams,
1361
+ query: metadata.get("validatedQuery") ?? request.query,
1362
+ body,
1363
+ headers: metadata.get("validatedHeaders") ?? request.headers,
1364
+ cookies: request.cookies,
1365
+ auth: request.auth,
1366
+ clientIp: request.clientIp,
1367
+ userAgent: request.userAgent,
1368
+ contentType: request.contentType
1369
+ };
1370
+ }
1371
+ __name(buildHttpRequest, "buildHttpRequest");
1372
+ function buildHttpContext(request, metadata, container, logger) {
1373
+ return {
1374
+ requestId: request.requestId,
1375
+ requestTime: request.requestTime,
1376
+ metadata,
1377
+ container,
1378
+ logger,
1379
+ raw: request
1380
+ };
1381
+ }
1382
+ __name(buildHttpContext, "buildHttpContext");
1383
+
1384
+ // src/handlers/pipeline.ts
1385
+ var debug7 = createDebug7("celerity:core:pipeline");
1386
+ async function executeHandlerPipeline(handler, request, options) {
1387
+ const context = {
1388
+ request,
1389
+ metadata: new HandlerMetadataStore(handler.customMetadata ?? {}),
1390
+ container: options.container
1391
+ };
1392
+ const allLayers = [
1393
+ ...options.systemLayers ?? [],
1394
+ ...options.appLayers ?? [],
1395
+ ...handler.layers
1396
+ ];
1397
+ debug7("%s %s \u2014 %d layers", request.method, request.path, allLayers.length);
1398
+ try {
1399
+ const response = await runLayerPipeline(allLayers, context, async () => {
1400
+ const handlerType = handler.isFunctionHandler ? "function" : "class";
1401
+ debug7("invoking %s handler", handlerType);
1402
+ const result = handler.isFunctionHandler ? await invokeFunctionHandler(handler, context) : await invokeClassHandler(handler, context);
1403
+ return normalizeResponse(result);
1404
+ });
1405
+ debug7("response %d", response.status);
1406
+ return response;
1407
+ } catch (error) {
1408
+ if (error instanceof HttpException) {
1409
+ debug7("HttpException %d: %s", error.statusCode, error.message);
1410
+ return {
1411
+ status: error.statusCode,
1412
+ headers: {
1413
+ "content-type": "application/json"
1414
+ },
1415
+ body: JSON.stringify({
1416
+ message: error.message,
1417
+ ...error.details ? {
1418
+ details: error.details
1419
+ } : {}
1420
+ })
1421
+ };
1422
+ }
1423
+ const message = error instanceof Error ? error.message : String(error);
1424
+ if (context.logger) {
1425
+ context.logger.error("Unhandled error in handler pipeline", {
1426
+ error: message,
1427
+ ...error instanceof Error && error.stack ? {
1428
+ stack: error.stack
1429
+ } : {}
1430
+ });
1431
+ } else {
1432
+ console.error("Unhandled error in handler pipeline:", error);
1433
+ }
1434
+ return {
1435
+ status: 500,
1436
+ headers: {
1437
+ "content-type": "application/json"
1438
+ },
1439
+ body: JSON.stringify({
1440
+ message: "Internal Server Error"
1441
+ })
1442
+ };
1443
+ }
1444
+ }
1445
+ __name(executeHandlerPipeline, "executeHandlerPipeline");
1446
+ async function invokeClassHandler(handler, context) {
1447
+ const args = [];
1448
+ const sorted = [
1449
+ ...handler.paramMetadata
1450
+ ].sort((a, b) => a.index - b.index);
1451
+ for (const meta of sorted) {
1452
+ args[meta.index] = extractValidatedParam(meta.type, meta.key, context.request, context.metadata);
1453
+ }
1454
+ return handler.handlerFn.apply(handler.handlerInstance, args);
1455
+ }
1456
+ __name(invokeClassHandler, "invokeClassHandler");
1457
+ var VALIDATED_METADATA_KEYS = {
1458
+ body: "validatedBody",
1459
+ query: "validatedQuery",
1460
+ param: "validatedParams",
1461
+ headers: "validatedHeaders"
1462
+ };
1463
+ function extractValidatedParam(type, key, request, metadata) {
1464
+ const metaKey = VALIDATED_METADATA_KEYS[type];
1465
+ if (metaKey) {
1466
+ const validated = metadata.get(metaKey);
1467
+ if (validated !== void 0) {
1468
+ if (key && typeof validated === "object" && validated !== null) {
1469
+ return validated[key];
1470
+ }
1471
+ return validated;
1472
+ }
1473
+ }
1474
+ return extractParam(type, key, request);
1475
+ }
1476
+ __name(extractValidatedParam, "extractValidatedParam");
1477
+ async function invokeFunctionHandler(handler, context) {
1478
+ const req = buildHttpRequest(context.request, context.metadata);
1479
+ const ctx = buildHttpContext(context.request, context.metadata, context.container, context.logger);
1480
+ if (handler.injectTokens && handler.injectTokens.length > 0) {
1481
+ const deps = [];
1482
+ for (const token of handler.injectTokens) {
1483
+ deps.push(await context.container.resolve(token));
1484
+ }
1485
+ return handler.handlerFn(req, ctx, ...deps);
1486
+ }
1487
+ return handler.handlerFn(req, ctx);
1488
+ }
1489
+ __name(invokeFunctionHandler, "invokeFunctionHandler");
1490
+ function normalizeResponse(result) {
1491
+ if (isHttpResponse(result)) {
1492
+ return result;
1493
+ }
1494
+ if (result === void 0 || result === null) {
1495
+ return {
1496
+ status: 204
1497
+ };
1498
+ }
1499
+ const body = typeof result === "string" ? result : JSON.stringify(result);
1500
+ return {
1501
+ status: 200,
1502
+ headers: {
1503
+ "content-type": "application/json"
1504
+ },
1505
+ body
1506
+ };
1507
+ }
1508
+ __name(normalizeResponse, "normalizeResponse");
1509
+ function isHttpResponse(value) {
1510
+ return typeof value === "object" && value !== null && "status" in value && typeof value.status === "number";
1511
+ }
1512
+ __name(isHttpResponse, "isHttpResponse");
1513
+
1514
+ // src/testing/test-app.ts
1515
+ var TestingApplication = class {
1516
+ static {
1517
+ __name(this, "TestingApplication");
1518
+ }
1519
+ registry;
1520
+ container;
1521
+ systemLayers;
1522
+ appLayers;
1523
+ constructor(registry, container, systemLayers = [], appLayers = []) {
1524
+ this.registry = registry;
1525
+ this.container = container;
1526
+ this.systemLayers = systemLayers;
1527
+ this.appLayers = appLayers;
1528
+ }
1529
+ async inject(request) {
1530
+ const handler = this.registry.getHandler(request.path, request.method);
1531
+ if (!handler) {
1532
+ throw new NotFoundException(`No handler found for ${request.method} ${request.path}`);
1533
+ }
1534
+ return executeHandlerPipeline(handler, request, {
1535
+ container: this.container,
1536
+ systemLayers: this.systemLayers,
1537
+ appLayers: this.appLayers
1538
+ });
1539
+ }
1540
+ getContainer() {
1541
+ return this.container;
1542
+ }
1543
+ getRegistry() {
1544
+ return this.registry;
1545
+ }
1546
+ };
1547
+ function mockRequest(method, path, options = {}) {
1548
+ return {
1549
+ method,
1550
+ path,
1551
+ pathParams: options.pathParams ?? {},
1552
+ query: options.query ?? {},
1553
+ headers: options.headers ?? {},
1554
+ cookies: options.cookies ?? {},
1555
+ textBody: options.body !== void 0 ? JSON.stringify(options.body) : null,
1556
+ binaryBody: null,
1557
+ contentType: options.body !== void 0 ? "application/json" : null,
1558
+ requestId: options.requestId ?? "test-request-id",
1559
+ requestTime: (/* @__PURE__ */ new Date()).toISOString(),
1560
+ auth: options.auth ?? null,
1561
+ clientIp: options.clientIp ?? "127.0.0.1",
1562
+ traceContext: null,
1563
+ userAgent: "celerity-testing",
1564
+ matchedRoute: null
1565
+ };
1566
+ }
1567
+ __name(mockRequest, "mockRequest");
1568
+
1569
+ // src/application/factory.ts
1570
+ var debug8 = createDebug8("celerity:core:factory");
1571
+ var CelerityFactory = class {
1572
+ static {
1573
+ __name(this, "CelerityFactory");
1574
+ }
1575
+ static async create(rootModule, options) {
1576
+ debug8("create: bootstrapping %s", rootModule.name);
1577
+ const systemLayers = options?.systemLayers ?? await createDefaultSystemLayers();
1578
+ const appLayers = options?.layers ?? [];
1579
+ debug8("create: %d system layers, %d app layers", systemLayers.length, appLayers.length);
1580
+ const { container, registry } = await bootstrap(rootModule);
1581
+ if (options?.adapter) {
1582
+ debug8("create: using adapter \u2192 ServerlessApplication");
1583
+ return new ServerlessApplication(registry, container, options.adapter, systemLayers, appLayers);
1584
+ }
1585
+ debug8("create: \u2192 CelerityApplication");
1586
+ return new CelerityApplication(registry, container, systemLayers, appLayers);
1587
+ }
1588
+ static async createTestingApp(rootModule, options) {
1589
+ debug8("createTestingApp: bootstrapping %s", rootModule.name);
1590
+ const { container, registry } = await bootstrap(rootModule);
1591
+ const systemLayers = options?.systemLayers ?? [];
1592
+ const appLayers = options?.layers ?? [];
1593
+ return new TestingApplication(registry, container, systemLayers, appLayers);
1594
+ }
1595
+ };
1596
+
1597
+ // src/functions/create-handler.ts
1598
+ function createHttpHandler(config, handler) {
1599
+ const metadata = {
1600
+ schema: config.schema,
1601
+ layers: config.layers ?? [],
1602
+ inject: config.inject ?? [],
1603
+ customMetadata: config.metadata ?? {}
1604
+ };
1605
+ if (config.path !== void 0) metadata.path = config.path;
1606
+ if (config.method !== void 0) metadata.method = config.method;
1607
+ return {
1608
+ __celerity_handler: true,
1609
+ type: "http",
1610
+ metadata,
1611
+ handler
1612
+ };
1613
+ }
1614
+ __name(createHttpHandler, "createHttpHandler");
1615
+ function httpGet(path, handlerOrOptions, maybeHandler) {
1616
+ if (typeof handlerOrOptions === "function") {
1617
+ return createHttpHandler({
1618
+ path,
1619
+ method: "GET"
1620
+ }, handlerOrOptions);
1621
+ }
1622
+ return createHttpHandler({
1623
+ path,
1624
+ method: "GET",
1625
+ ...handlerOrOptions
1626
+ }, maybeHandler);
1627
+ }
1628
+ __name(httpGet, "httpGet");
1629
+ function httpPost(path, handlerOrOptions, maybeHandler) {
1630
+ if (typeof handlerOrOptions === "function") {
1631
+ return createHttpHandler({
1632
+ path,
1633
+ method: "POST"
1634
+ }, handlerOrOptions);
1635
+ }
1636
+ return createHttpHandler({
1637
+ path,
1638
+ method: "POST",
1639
+ ...handlerOrOptions
1640
+ }, maybeHandler);
1641
+ }
1642
+ __name(httpPost, "httpPost");
1643
+ function httpPut(path, handlerOrOptions, maybeHandler) {
1644
+ if (typeof handlerOrOptions === "function") {
1645
+ return createHttpHandler({
1646
+ path,
1647
+ method: "PUT"
1648
+ }, handlerOrOptions);
1649
+ }
1650
+ return createHttpHandler({
1651
+ path,
1652
+ method: "PUT",
1653
+ ...handlerOrOptions
1654
+ }, maybeHandler);
1655
+ }
1656
+ __name(httpPut, "httpPut");
1657
+ function httpPatch(path, handlerOrOptions, maybeHandler) {
1658
+ if (typeof handlerOrOptions === "function") {
1659
+ return createHttpHandler({
1660
+ path,
1661
+ method: "PATCH"
1662
+ }, handlerOrOptions);
1663
+ }
1664
+ return createHttpHandler({
1665
+ path,
1666
+ method: "PATCH",
1667
+ ...handlerOrOptions
1668
+ }, maybeHandler);
1669
+ }
1670
+ __name(httpPatch, "httpPatch");
1671
+ function httpDelete(path, handlerOrOptions, maybeHandler) {
1672
+ if (typeof handlerOrOptions === "function") {
1673
+ return createHttpHandler({
1674
+ path,
1675
+ method: "DELETE"
1676
+ }, handlerOrOptions);
1677
+ }
1678
+ return createHttpHandler({
1679
+ path,
1680
+ method: "DELETE",
1681
+ ...handlerOrOptions
1682
+ }, maybeHandler);
1683
+ }
1684
+ __name(httpDelete, "httpDelete");
1685
+
1686
+ // src/bootstrap/discovery.ts
1687
+ import { resolve } from "path";
1688
+ import createDebug9 from "debug";
1689
+ var debug9 = createDebug9("celerity:core:bootstrap");
1690
+ async function discoverModule(modulePath) {
1691
+ const resolved = modulePath ?? process.env.CELERITY_MODULE_PATH;
1692
+ if (!resolved) {
1693
+ throw new Error("Cannot discover module: set CELERITY_MODULE_PATH environment variable or pass modulePath");
1694
+ }
1695
+ const absolutePath = resolve(resolved);
1696
+ debug9("discoverModule: importing %s", absolutePath);
1697
+ const imported = await import(absolutePath);
1698
+ const rootModule = imported.default ?? findModuleExport(imported);
1699
+ if (!rootModule || typeof rootModule !== "function") {
1700
+ throw new Error(`No module class found in "${resolved}"`);
1701
+ }
1702
+ debug9("discoverModule: found %s", rootModule.name);
1703
+ return rootModule;
1704
+ }
1705
+ __name(discoverModule, "discoverModule");
1706
+ function findModuleExport(imported) {
1707
+ for (const key of Object.keys(imported)) {
1708
+ if (key === "default") continue;
1709
+ if (typeof imported[key] === "function") {
1710
+ return imported[key];
1711
+ }
1712
+ }
1713
+ return void 0;
1714
+ }
1715
+ __name(findModuleExport, "findModuleExport");
1716
+
1717
+ // src/bootstrap/runtime-mapper.ts
1718
+ function flattenMultiValueRecord(record) {
1719
+ const result = {};
1720
+ for (const [key, values] of Object.entries(record)) {
1721
+ result[key] = values.length === 1 ? values[0] : values;
1722
+ }
1723
+ return result;
1724
+ }
1725
+ __name(flattenMultiValueRecord, "flattenMultiValueRecord");
1726
+ function mapRuntimeRequest(request) {
1727
+ return {
1728
+ method: request.method.toUpperCase(),
1729
+ path: request.path,
1730
+ pathParams: request.pathParams,
1731
+ query: flattenMultiValueRecord(request.query),
1732
+ headers: flattenMultiValueRecord(request.headers),
1733
+ cookies: request.cookies,
1734
+ textBody: request.textBody,
1735
+ binaryBody: request.binaryBody,
1736
+ contentType: request.contentType || null,
1737
+ requestId: request.requestId,
1738
+ requestTime: request.requestTime,
1739
+ auth: request.auth ?? null,
1740
+ clientIp: request.clientIp || null,
1741
+ traceContext: request.traceContext ?? null,
1742
+ userAgent: request.userAgent || null,
1743
+ matchedRoute: request.matchedRoute
1744
+ };
1745
+ }
1746
+ __name(mapRuntimeRequest, "mapRuntimeRequest");
1747
+ function mapToRuntimeResponse(response) {
1748
+ return {
1749
+ status: response.status,
1750
+ headers: response.headers,
1751
+ body: response.body,
1752
+ binaryBody: response.binaryBody
1753
+ };
1754
+ }
1755
+ __name(mapToRuntimeResponse, "mapToRuntimeResponse");
1756
+
1757
+ // src/bootstrap/runtime-entry.ts
1758
+ async function bootstrapForRuntime(modulePath, systemLayers) {
1759
+ const layers = systemLayers ?? await createDefaultSystemLayers();
1760
+ const rootModule = await discoverModule(modulePath);
1761
+ const { container, registry } = await bootstrap(rootModule);
1762
+ return {
1763
+ registry,
1764
+ container,
1765
+ createRouteCallback(path, method) {
1766
+ const handler = registry.getHandler(path, method);
1767
+ if (!handler) return null;
1768
+ return async (_err, request) => {
1769
+ const httpRequest = mapRuntimeRequest(request);
1770
+ const httpResponse = await executeHandlerPipeline(handler, httpRequest, {
1771
+ container,
1772
+ systemLayers: layers
1773
+ });
1774
+ return mapToRuntimeResponse(httpResponse);
1775
+ };
1776
+ }
1777
+ };
1778
+ }
1779
+ __name(bootstrapForRuntime, "bootstrapForRuntime");
1780
+
1781
+ // src/bootstrap/runtime-orchestrator.ts
1782
+ async function startRuntime(options) {
1783
+ const pkg = "@celerity-sdk/runtime";
1784
+ const runtimeModule = await import(pkg);
1785
+ const config = runtimeModule.runtimeConfigFromEnv();
1786
+ const app = new runtimeModule.CoreRuntimeApplication(config);
1787
+ const appConfig = app.setup();
1788
+ const result = await bootstrapForRuntime();
1789
+ for (const def of appConfig.api?.http?.handlers ?? []) {
1790
+ const callback = result.createRouteCallback(def.path, def.method);
1791
+ if (callback) {
1792
+ app.registerHttpHandler(def.path, def.method, def.timeout, callback);
1793
+ }
1794
+ }
1795
+ await app.run(options?.block ?? true);
1796
+ }
1797
+ __name(startRuntime, "startRuntime");
1798
+ export {
1799
+ APP_CONFIG,
1800
+ Action,
1801
+ Auth,
1802
+ BadGatewayException,
1803
+ BadRequestException,
1804
+ Body,
1805
+ CONTROLLER_METADATA,
1806
+ CUSTOM_METADATA,
1807
+ CelerityApplication,
1808
+ CelerityFactory,
1809
+ ConflictException,
1810
+ Container,
1811
+ Controller,
1812
+ Cookies,
1813
+ Delete,
1814
+ ForbiddenException,
1815
+ GUARD_CUSTOM_METADATA,
1816
+ GUARD_PROTECTEDBY_METADATA,
1817
+ GatewayTimeoutException,
1818
+ Get,
1819
+ GoneException,
1820
+ Guard,
1821
+ HTTP_METHOD_METADATA,
1822
+ HandlerMetadataStore,
1823
+ HandlerRegistry,
1824
+ Head,
1825
+ Headers,
1826
+ HttpException,
1827
+ INJECT_METADATA,
1828
+ Inject,
1829
+ Injectable,
1830
+ InternalServerErrorException,
1831
+ LAYER_METADATA,
1832
+ MODULE_METADATA,
1833
+ MethodNotAllowedException,
1834
+ Module,
1835
+ NotAcceptableException,
1836
+ NotFoundException,
1837
+ NotImplementedException,
1838
+ Options,
1839
+ PUBLIC_METADATA,
1840
+ Param,
1841
+ Patch,
1842
+ Post,
1843
+ ProtectedBy,
1844
+ Public,
1845
+ Put,
1846
+ Query,
1847
+ ROUTE_PATH_METADATA,
1848
+ RUNTIME_APP,
1849
+ Req,
1850
+ RequestId,
1851
+ ServerlessApplication,
1852
+ ServiceUnavailableException,
1853
+ SetMetadata,
1854
+ TestingApplication,
1855
+ TooManyRequestsException,
1856
+ UnauthorizedException,
1857
+ UnprocessableEntityException,
1858
+ UseLayer,
1859
+ UseLayers,
1860
+ bootstrap,
1861
+ bootstrapForRuntime,
1862
+ buildModuleGraph,
1863
+ createDefaultSystemLayers,
1864
+ createHttpHandler,
1865
+ discoverModule,
1866
+ disposeLayers,
1867
+ executeHandlerPipeline,
1868
+ flattenMultiValueRecord,
1869
+ getClassDependencyTokens,
1870
+ getProviderDependencyTokens,
1871
+ httpDelete,
1872
+ httpGet,
1873
+ httpPatch,
1874
+ httpPost,
1875
+ httpPut,
1876
+ mapRuntimeRequest,
1877
+ mapToRuntimeResponse,
1878
+ mockRequest,
1879
+ registerModuleGraph,
1880
+ runLayerPipeline,
1881
+ startRuntime,
1882
+ tokenToString,
1883
+ validate
1884
+ };
1885
+ //# sourceMappingURL=index.js.map