@bool-ts/core 1.9.0 → 1.9.2

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.
Files changed (42) hide show
  1. package/__test/_constants.ts +1 -0
  2. package/__test/container.ts +28 -0
  3. package/__test/controller.ts +1 -1
  4. package/__test/{module.ts → firstModule.ts} +4 -6
  5. package/__test/index.ts +2 -4
  6. package/__test/secondModule.ts +29 -0
  7. package/__test/tsconfig.json +1 -1
  8. package/__test/webSocket.ts +1 -1
  9. package/dist/decorators/arguments.d.ts +6 -1
  10. package/dist/decorators/container.d.ts +29 -0
  11. package/dist/decorators/http.d.ts +2 -0
  12. package/dist/decorators/index.d.ts +4 -2
  13. package/dist/decorators/module.d.ts +6 -2
  14. package/dist/decorators/webSocket.d.ts +2 -0
  15. package/dist/entities/httpRoute.d.ts +6 -0
  16. package/dist/index.d.ts +1 -1
  17. package/dist/index.js +5 -5
  18. package/dist/interfaces/context.d.ts +8 -2
  19. package/dist/interfaces/index.d.ts +1 -1
  20. package/dist/keys/index.d.ts +3 -0
  21. package/dist/producers/context.d.ts +13 -0
  22. package/dist/{hooks → producers}/factory.d.ts +5 -2
  23. package/dist/{hooks → producers}/injector.d.ts +7 -1
  24. package/package.json +3 -3
  25. package/src/decorators/arguments.ts +126 -77
  26. package/src/decorators/container.ts +94 -0
  27. package/src/decorators/controller.ts +1 -1
  28. package/src/decorators/http.ts +9 -2
  29. package/src/decorators/index.ts +4 -1
  30. package/src/decorators/module.ts +27 -4
  31. package/src/decorators/webSocket.ts +6 -2
  32. package/src/entities/httpRoute.ts +2 -0
  33. package/src/index.ts +1 -1
  34. package/src/interfaces/context.ts +9 -2
  35. package/src/interfaces/index.ts +1 -1
  36. package/src/keys/index.ts +3 -0
  37. package/src/producers/context.ts +63 -0
  38. package/src/producers/factory.ts +2013 -0
  39. package/src/{hooks → producers}/injector.ts +41 -6
  40. package/src/hooks/factory.ts +0 -1701
  41. /package/dist/{hooks → producers}/index.d.ts +0 -0
  42. /package/src/{hooks → producers}/index.ts +0 -0
@@ -0,0 +1,2013 @@
1
+ import type { BunFile, Server } from "bun";
2
+ import type {
3
+ TContainerMetadata,
4
+ TControllerMetadata,
5
+ TModuleMetadata,
6
+ TWebSocketEventHandlerMetadata,
7
+ TWebSocketMetadata
8
+ } from "../decorators";
9
+ import type { TArgumentsMetadataCollection } from "../decorators/arguments";
10
+ import type { TWebSocketUpgradeData } from "../decorators/webSocket";
11
+ import type { IGuard, IMiddleware } from "../interfaces";
12
+ import type { IDispatcher } from "../interfaces/dispatcher";
13
+
14
+ import "reflect-metadata";
15
+
16
+ import Qs from "qs";
17
+ import * as Zod from "zod";
18
+
19
+ import { ETimeUnit, add as TimeAdd } from "@bool-ts/date-time";
20
+ import {
21
+ HttpRouter,
22
+ HttpRouterGroup,
23
+ WebSocketRoute,
24
+ WebSocketRouter,
25
+ WebSocketRouterGroup
26
+ } from "../entities";
27
+ import { HttpClientError, HttpServerError, jsonErrorInfer, type THttpMethods } from "../http";
28
+ import {
29
+ argumentsKey,
30
+ configKey,
31
+ containerKey,
32
+ contextArgsKey,
33
+ controllerKey,
34
+ httpServerArgsKey,
35
+ moduleKey,
36
+ paramArgsKey,
37
+ paramsArgsKey,
38
+ queryArgsKey,
39
+ requestArgsKey,
40
+ requestBodyArgsKey,
41
+ requestHeaderArgsKey,
42
+ requestHeadersArgsKey,
43
+ responseBodyArgsKey,
44
+ responseHeadersArgsKey,
45
+ responseStatusArgsKey,
46
+ responseStatusTextArgsKey,
47
+ routeModelArgsKey,
48
+ webSocketCloseCodeArgsKey,
49
+ webSocketCloseReasonArgsKey,
50
+ webSocketConnectionArgsKey,
51
+ webSocketKey,
52
+ webSocketMessageArgsKey,
53
+ webSocketServerArgsKey
54
+ } from "../keys";
55
+ import { ansiText, isWebSocketUpgrade } from "../ultils";
56
+ import { Context } from "./context";
57
+ import { Injector } from "./injector";
58
+
59
+ export type TParamsType = Record<string, string>;
60
+
61
+ export type TGroupElementModel<
62
+ TFuncName extends keyof TClass,
63
+ TClass extends Object = Object,
64
+ TFunc = TClass[TFuncName]
65
+ > = Readonly<{
66
+ class: TClass;
67
+ func: TFunc;
68
+ funcName: TFuncName;
69
+ argumentsMetadata: TArgumentsMetadataCollection;
70
+ }>;
71
+
72
+ export type TBoolFactoryOptions = Required<{
73
+ port: number;
74
+ }> &
75
+ Partial<{
76
+ config: Record<string | symbol, any> | (() => Record<string | symbol, any>);
77
+ prefix: string;
78
+ debug: boolean;
79
+ log: Partial<{
80
+ methods: Array<"GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS">;
81
+ }>;
82
+ queryParser: Parameters<typeof Qs.parse>[1];
83
+ static: Required<{
84
+ path: string;
85
+ }> &
86
+ Partial<{
87
+ headers: TParamsType;
88
+ cacheTimeInSeconds: number;
89
+ }>;
90
+ cors: Partial<{
91
+ credentials: boolean;
92
+ origins: string | Array<string>;
93
+ methods: Array<"GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS">;
94
+ headers: Array<string>;
95
+ }>;
96
+ }>;
97
+
98
+ const DEFAULT_STATIC_CACHE_TIME_IN_SECONDS = 900;
99
+
100
+ const responseConverter = (response: Response) => {
101
+ response.headers.set("X-Powered-By", "Bool Typescript");
102
+
103
+ return response;
104
+ };
105
+
106
+ const controllerCreator = ({
107
+ controllerConstructor,
108
+ httpRouterGroup,
109
+ injector,
110
+ prefix
111
+ }: Readonly<{
112
+ controllerConstructor: new (...args: any[]) => unknown;
113
+ httpRouterGroup: HttpRouterGroup;
114
+ injector: Injector;
115
+ prefix?: string;
116
+ }>) => {
117
+ if (!Reflect.getOwnMetadataKeys(controllerConstructor).includes(controllerKey)) {
118
+ throw Error(`${controllerConstructor.name} is not a controller.`);
119
+ }
120
+
121
+ const controller = injector.get(controllerConstructor);
122
+
123
+ if (!controller) {
124
+ throw Error("Can not initialize controller.");
125
+ }
126
+
127
+ const controllerMetadata: TControllerMetadata = Reflect.getOwnMetadata(
128
+ controllerKey,
129
+ controllerConstructor
130
+ ) || {
131
+ prefix: "/",
132
+ httpMetadata: []
133
+ };
134
+
135
+ const router = new HttpRouter(`/${prefix || ""}/${controllerMetadata.prefix}`);
136
+
137
+ controllerMetadata.httpMetadata.forEach((routeMetadata) => {
138
+ if (typeof routeMetadata.descriptor.value !== "function") {
139
+ return;
140
+ }
141
+
142
+ const route = router.route(routeMetadata.path);
143
+ const handler = routeMetadata.descriptor.value.bind(controller);
144
+ const routeArgument = Object.freeze({
145
+ class: controllerConstructor,
146
+ funcName: routeMetadata.methodName,
147
+ func: handler,
148
+ argumentsMetadata: routeMetadata.argumentsMetadata
149
+ });
150
+
151
+ switch (routeMetadata.httpMethod) {
152
+ case "GET":
153
+ return route.get(routeArgument);
154
+ case "POST":
155
+ return route.post(routeArgument);
156
+ case "PUT":
157
+ return route.put(routeArgument);
158
+ case "PATCH":
159
+ return route.patch(routeArgument);
160
+ case "DELETE":
161
+ return route.delete(routeArgument);
162
+ case "OPTIONS":
163
+ return route.options(routeArgument);
164
+ }
165
+ });
166
+
167
+ return httpRouterGroup.add(router);
168
+ };
169
+
170
+ const webSocketCreator = ({
171
+ injector,
172
+ httpRouterGroup,
173
+ prefix,
174
+ webSocketRouterGroup,
175
+ webSocketConstructor
176
+ }: Readonly<{
177
+ webSocketConstructor: new (...args: any[]) => unknown;
178
+ httpRouterGroup: HttpRouterGroup;
179
+ webSocketRouterGroup: WebSocketRouterGroup;
180
+ injector: Injector;
181
+ prefix?: string;
182
+ }>): Readonly<{
183
+ httpRouterGroup: HttpRouterGroup;
184
+ webSocketRouterGroup: WebSocketRouterGroup;
185
+ }> => {
186
+ if (!Reflect.getOwnMetadataKeys(webSocketConstructor).includes(webSocketKey)) {
187
+ throw Error(`${webSocketConstructor.name} is not a websocket route.`);
188
+ }
189
+
190
+ const webSocket = injector.get(webSocketConstructor);
191
+
192
+ if (!webSocket) {
193
+ throw Error("Can not initialize webSocket.");
194
+ }
195
+
196
+ const webSocketMetadata: TWebSocketMetadata = Reflect.getOwnMetadata(
197
+ webSocketKey,
198
+ webSocketConstructor
199
+ ) || {
200
+ prefix: "/",
201
+ events: [],
202
+ http: []
203
+ };
204
+
205
+ const fullPrefix = `/${prefix || ""}/${webSocketMetadata.prefix}`;
206
+
207
+ //#region [HTTP ROUTER]
208
+ const router = new HttpRouter(fullPrefix);
209
+
210
+ for (const [_key, httpMetadata] of Object.entries(webSocketMetadata.http)) {
211
+ if (typeof httpMetadata.descriptor?.value !== "function") {
212
+ continue;
213
+ }
214
+
215
+ const route = router.route(httpMetadata.path);
216
+ const handler = httpMetadata.descriptor.value.bind(webSocket);
217
+ const routeArgument = Object.freeze({
218
+ class: webSocketConstructor,
219
+ funcName: httpMetadata.methodName,
220
+ func: handler,
221
+ argumentsMetadata: httpMetadata.argumentsMetadata
222
+ });
223
+
224
+ switch (httpMetadata.httpMethod) {
225
+ case "GET":
226
+ route.get(routeArgument);
227
+ break;
228
+ case "POST":
229
+ route.post(routeArgument);
230
+ break;
231
+ }
232
+ }
233
+
234
+ httpRouterGroup.add(router);
235
+ //#endregion
236
+
237
+ //#region [WEBSOCKET ROUTER]
238
+ const webSocketRouter = new WebSocketRouter(fullPrefix);
239
+
240
+ for (const [key, event] of Object.entries(webSocketMetadata.events)) {
241
+ const webSocketRoute = new WebSocketRoute({
242
+ eventName: key,
243
+ metadata: event
244
+ });
245
+
246
+ webSocketRouter.addRoutes(webSocketRoute);
247
+ }
248
+
249
+ webSocketRouter.bind(webSocket);
250
+ webSocketRouterGroup.addRouters(webSocketRouter);
251
+ //#endregion
252
+
253
+ return Object.freeze({
254
+ httpRouterGroup: httpRouterGroup,
255
+ webSocketRouterGroup: webSocketRouterGroup
256
+ });
257
+ };
258
+
259
+ const argumentsResolution = async (
260
+ data: unknown,
261
+ zodSchema: Zod.Schema,
262
+ argumentIndex: number,
263
+ funcName: string | symbol
264
+ ) => {
265
+ try {
266
+ const validation = await zodSchema.safeParseAsync(data);
267
+
268
+ if (!validation.success) {
269
+ throw new HttpClientError({
270
+ httpCode: 400,
271
+ message: `Validation at the [${funcName.toString()}] method fails at positional argument [${argumentIndex}].`,
272
+ data: validation.error.issues
273
+ });
274
+ }
275
+
276
+ return validation.data;
277
+ } catch (error) {
278
+ if (error instanceof HttpClientError) {
279
+ throw error;
280
+ }
281
+
282
+ throw new HttpServerError({
283
+ httpCode: 500,
284
+ message: `Validation at the [${funcName.toString()}] method error at positional argument [${argumentIndex}].`,
285
+ data: !(error instanceof Error)
286
+ ? error
287
+ : [
288
+ {
289
+ message: error.message,
290
+ code: error.name,
291
+ cause: error.cause
292
+ }
293
+ ]
294
+ });
295
+ }
296
+ };
297
+
298
+ const containerResolution = async ({
299
+ containerClass,
300
+ options,
301
+ extendInjector
302
+ }: {
303
+ containerClass: new (...args: any[]) => unknown;
304
+ options: TBoolFactoryOptions;
305
+ extendInjector: Injector;
306
+ }) => {
307
+ if (!Reflect.getOwnMetadataKeys(containerClass).includes(containerKey)) {
308
+ throw Error(`${containerClass.name} is not a container.`);
309
+ }
310
+
311
+ const injector = new Injector(extendInjector);
312
+ const containerMetadata: TContainerMetadata = Reflect.getOwnMetadata(
313
+ containerKey,
314
+ containerClass
315
+ );
316
+
317
+ const {
318
+ loaders,
319
+ middlewares,
320
+ guards,
321
+ dependencies,
322
+ config: containerConfig
323
+ } = containerMetadata || {};
324
+
325
+ //#region [Configuration(s)]
326
+ const { config } = Object.freeze({
327
+ config: {
328
+ ...(typeof options.config !== "function" ? options.config : await options.config()),
329
+ ...(typeof containerConfig !== "function"
330
+ ? typeof containerConfig !== "object"
331
+ ? undefined
332
+ : "key" in containerConfig &&
333
+ "value" in containerConfig &&
334
+ typeof containerConfig.key === "symbol"
335
+ ? typeof containerConfig.value !== "function"
336
+ ? containerConfig.value
337
+ : await containerConfig.value()
338
+ : containerConfig
339
+ : await containerConfig())
340
+ }
341
+ });
342
+ //#endregion
343
+
344
+ //#region [Register config like an injection]
345
+ injector.set(
346
+ containerConfig &&
347
+ "key" in containerConfig &&
348
+ "value" in containerConfig &&
349
+ typeof containerConfig.key === "symbol"
350
+ ? containerConfig.key
351
+ : configKey,
352
+ config
353
+ );
354
+ //#endregion
355
+
356
+ //#region [Run loader(s)]
357
+ if (loaders) {
358
+ const loaderFunctions = [];
359
+
360
+ for (const [key, func] of Object.entries(loaders)) {
361
+ loaderFunctions.push(async () => {
362
+ try {
363
+ const result = await func({ config });
364
+
365
+ console.info(
366
+ `${ansiText(" INFO ", {
367
+ color: "white",
368
+ backgroundColor: "blue",
369
+ bold: true
370
+ })} Loader [${key}] initialized successfully.`
371
+ );
372
+
373
+ return result;
374
+ } catch (error) {
375
+ console.error(
376
+ `${ansiText(" WARN ", {
377
+ color: "yellow",
378
+ backgroundColor: "red",
379
+ bold: true
380
+ })} Loader [${key}] initialization failed.`
381
+ );
382
+ options.debug && console.error(error);
383
+ throw error;
384
+ }
385
+ });
386
+ }
387
+
388
+ const results = await Promise.all(loaderFunctions.map((func) => func()));
389
+
390
+ for (let i = 0; i < results.length; i++) {
391
+ const [key, value] = results[i];
392
+ injector.set(key, value);
393
+ }
394
+ }
395
+ //#endregion
396
+
397
+ //#region [Dependencies]
398
+ !dependencies || dependencies.map((dependency) => injector.get(dependency));
399
+ //#endregion
400
+
401
+ //#region [Middleware(s)]
402
+ const startMiddlewareGroup: Array<
403
+ TGroupElementModel<"start", IMiddleware, NonNullable<IMiddleware["start"]>>
404
+ > = [];
405
+ const endMiddlewareGroup: Array<
406
+ TGroupElementModel<"end", IMiddleware, NonNullable<IMiddleware["end"]>>
407
+ > = [];
408
+
409
+ !middlewares ||
410
+ middlewares.forEach((middleware) => {
411
+ const instance = injector.get<IMiddleware>(middleware);
412
+
413
+ if (instance.start && typeof instance.start === "function") {
414
+ const argumentsMetadata: TArgumentsMetadataCollection =
415
+ Reflect.getOwnMetadata(argumentsKey, middleware, "start") || {};
416
+
417
+ startMiddlewareGroup.push(
418
+ Object.freeze({
419
+ class: middleware as IMiddleware,
420
+ funcName: "start",
421
+ func: instance.start.bind(instance),
422
+ argumentsMetadata: argumentsMetadata
423
+ })
424
+ );
425
+ }
426
+
427
+ if (instance.end && typeof instance.end === "function") {
428
+ const argumentsMetadata: TArgumentsMetadataCollection =
429
+ Reflect.getOwnMetadata(argumentsKey, middleware, "start") || {};
430
+
431
+ endMiddlewareGroup.push(
432
+ Object.freeze({
433
+ class: middleware as IMiddleware,
434
+ funcName: "end",
435
+ func: instance.end.bind(instance),
436
+ argumentsMetadata: argumentsMetadata
437
+ })
438
+ );
439
+ }
440
+ });
441
+ //#endregion
442
+
443
+ //#region [Guard(s)]
444
+ const guardGroup: Array<TGroupElementModel<"enforce", IGuard, NonNullable<IGuard["enforce"]>>> =
445
+ !guards
446
+ ? []
447
+ : guards.map((guard) => {
448
+ const guardInstance = injector.get<IGuard>(guard);
449
+ const argumentsMetadata: TArgumentsMetadataCollection =
450
+ Reflect.getOwnMetadata(argumentsKey, guard, "enforce") || {};
451
+
452
+ return Object.freeze({
453
+ class: guard as unknown as IGuard,
454
+ funcName: "enforce",
455
+ func: guardInstance.enforce.bind(guardInstance),
456
+ argumentsMetadata: argumentsMetadata
457
+ });
458
+ });
459
+ //#endregion
460
+
461
+ return Object.freeze({
462
+ injector,
463
+ startMiddlewareGroup,
464
+ endMiddlewareGroup,
465
+ guardGroup
466
+ });
467
+ };
468
+
469
+ const moduleResolution = async ({
470
+ moduleClass,
471
+ options,
472
+ extendInjector
473
+ }: {
474
+ moduleClass: new (...args: any[]) => unknown;
475
+ options: TBoolFactoryOptions;
476
+ extendInjector: Injector;
477
+ }) => {
478
+ if (!Reflect.getOwnMetadataKeys(moduleClass).includes(moduleKey)) {
479
+ throw Error(`${moduleClass.name} is not a module.`);
480
+ }
481
+
482
+ const injector = new Injector(extendInjector);
483
+ const moduleMetadata: TModuleMetadata = Reflect.getOwnMetadata(moduleKey, moduleClass);
484
+
485
+ const {
486
+ loaders,
487
+ middlewares,
488
+ guards,
489
+ dispatchers,
490
+ controllers,
491
+ dependencies,
492
+ webSockets,
493
+ prefix: modulePrefix,
494
+ config: moduleConfig
495
+ } = moduleMetadata || {};
496
+
497
+ const fullPrefix = `${options.prefix || ""}/${modulePrefix || ""}`;
498
+
499
+ //#region [Configuration(s)]
500
+ const { config } = Object.freeze({
501
+ config: {
502
+ ...(typeof options.config !== "function" ? options.config : await options.config()),
503
+ ...(typeof moduleConfig !== "function"
504
+ ? typeof moduleConfig !== "object"
505
+ ? undefined
506
+ : "key" in moduleConfig &&
507
+ "value" in moduleConfig &&
508
+ typeof moduleConfig.key === "symbol"
509
+ ? typeof moduleConfig.value !== "function"
510
+ ? moduleConfig.value
511
+ : await moduleConfig.value()
512
+ : moduleConfig
513
+ : await moduleConfig())
514
+ }
515
+ });
516
+ //#endregion
517
+
518
+ //#region [Register config like an injection]
519
+ injector.set(
520
+ moduleConfig &&
521
+ "key" in moduleConfig &&
522
+ "value" in moduleConfig &&
523
+ typeof moduleConfig.key === "symbol"
524
+ ? moduleConfig.key
525
+ : configKey,
526
+ config
527
+ );
528
+ //#endregion
529
+
530
+ //#region [Run loader(s)]
531
+ if (loaders) {
532
+ const loaderFunctions = [];
533
+
534
+ for (const [key, func] of Object.entries(loaders)) {
535
+ loaderFunctions.push(async () => {
536
+ try {
537
+ const result = await func({ config });
538
+
539
+ console.info(
540
+ `${ansiText(" INFO ", {
541
+ color: "white",
542
+ backgroundColor: "blue",
543
+ bold: true
544
+ })} Loader [${key}] initialized successfully.`
545
+ );
546
+
547
+ return result;
548
+ } catch (error) {
549
+ console.error(
550
+ `${ansiText(" WARN ", {
551
+ color: "yellow",
552
+ backgroundColor: "red",
553
+ bold: true
554
+ })} Loader [${key}] initialization failed.`
555
+ );
556
+ options.debug && console.error(error);
557
+ throw error;
558
+ }
559
+ });
560
+ }
561
+
562
+ const results = await Promise.all(loaderFunctions.map((func) => func()));
563
+
564
+ for (let i = 0; i < results.length; i++) {
565
+ const [key, value] = results[i];
566
+ injector.set(key, value);
567
+ }
568
+ }
569
+ //#endregion
570
+
571
+ //#region [Dependencies]
572
+ !dependencies || dependencies.map((dependency) => injector.get(dependency));
573
+ //#endregion
574
+
575
+ //#region [Middleware(s)]
576
+ const startMiddlewareGroup: Array<
577
+ TGroupElementModel<"start", IMiddleware, NonNullable<IMiddleware["start"]>>
578
+ > = [];
579
+ const endMiddlewareGroup: Array<
580
+ TGroupElementModel<"end", IMiddleware, NonNullable<IMiddleware["end"]>>
581
+ > = [];
582
+
583
+ !middlewares ||
584
+ middlewares.forEach((middleware) => {
585
+ const instance = injector.get<IMiddleware>(middleware);
586
+
587
+ if (instance.start && typeof instance.start === "function") {
588
+ const argumentsMetadata: TArgumentsMetadataCollection =
589
+ Reflect.getOwnMetadata(argumentsKey, middleware, "start") || {};
590
+
591
+ startMiddlewareGroup.push(
592
+ Object.freeze({
593
+ class: middleware as IMiddleware,
594
+ funcName: "start",
595
+ func: instance.start.bind(instance),
596
+ argumentsMetadata: argumentsMetadata
597
+ })
598
+ );
599
+ }
600
+
601
+ if (instance.end && typeof instance.end === "function") {
602
+ const argumentsMetadata: TArgumentsMetadataCollection =
603
+ Reflect.getOwnMetadata(argumentsKey, middleware, "start") || {};
604
+
605
+ endMiddlewareGroup.push(
606
+ Object.freeze({
607
+ class: middleware as IMiddleware,
608
+ funcName: "end",
609
+ func: instance.end.bind(instance),
610
+ argumentsMetadata: argumentsMetadata
611
+ })
612
+ );
613
+ }
614
+ });
615
+ //#endregion
616
+
617
+ //#region [Guard(s)]
618
+ const guardGroup: Array<TGroupElementModel<"enforce", IGuard, NonNullable<IGuard["enforce"]>>> =
619
+ !guards
620
+ ? []
621
+ : guards.map((guard) => {
622
+ const guardInstance = injector.get<IGuard>(guard);
623
+ const argumentsMetadata: TArgumentsMetadataCollection =
624
+ Reflect.getOwnMetadata(argumentsKey, guard, "enforce") || {};
625
+
626
+ return Object.freeze({
627
+ class: guard as unknown as IGuard,
628
+ funcName: "enforce",
629
+ func: guardInstance.enforce.bind(guardInstance),
630
+ argumentsMetadata: argumentsMetadata
631
+ });
632
+ });
633
+ //#endregion
634
+
635
+ //#region [Before dispatcher(s)]
636
+ const openDispatcherGroup: Array<
637
+ TGroupElementModel<"open", IDispatcher, NonNullable<IDispatcher["open"]>>
638
+ > = [];
639
+ const closeDispatcherGroup: Array<
640
+ TGroupElementModel<"close", IDispatcher, NonNullable<IDispatcher["close"]>>
641
+ > = [];
642
+
643
+ !dispatchers ||
644
+ dispatchers.forEach((dispatcher) => {
645
+ const instance = injector.get<IDispatcher>(dispatcher);
646
+
647
+ if (instance.open && typeof instance.open === "function") {
648
+ const argumentsMetadata: TArgumentsMetadataCollection =
649
+ Reflect.getOwnMetadata(argumentsKey, dispatcher, "open") || {};
650
+
651
+ openDispatcherGroup.push(
652
+ Object.freeze({
653
+ class: dispatcher as IDispatcher,
654
+ funcName: "open",
655
+ func: instance.open.bind(instance),
656
+ argumentsMetadata: argumentsMetadata
657
+ })
658
+ );
659
+ }
660
+
661
+ if (instance.close && typeof instance.close === "function") {
662
+ const argumentsMetadata: TArgumentsMetadataCollection =
663
+ Reflect.getOwnMetadata(argumentsKey, dispatcher, "close") || {};
664
+
665
+ closeDispatcherGroup.push(
666
+ Object.freeze({
667
+ class: dispatcher as IDispatcher,
668
+ funcName: "close",
669
+ func: instance.close.bind(instance),
670
+ argumentsMetadata: argumentsMetadata
671
+ })
672
+ );
673
+ }
674
+ });
675
+ //#endregion
676
+
677
+ //#region [Controller(s)]
678
+ const controllerRouterGroup = new HttpRouterGroup();
679
+
680
+ !controllers ||
681
+ controllers.forEach((controllerConstructor) =>
682
+ controllerCreator({
683
+ controllerConstructor,
684
+ httpRouterGroup: controllerRouterGroup,
685
+ injector: injector,
686
+ prefix: fullPrefix
687
+ })
688
+ );
689
+ //#endregion
690
+
691
+ //#region [WebSocket(s)]
692
+ const webSocketHttpRouterGroup = new HttpRouterGroup();
693
+ const webSocketRouterGroup = new WebSocketRouterGroup();
694
+
695
+ webSockets &&
696
+ webSockets.forEach((webSocket) =>
697
+ webSocketCreator({
698
+ webSocketConstructor: webSocket,
699
+ httpRouterGroup: webSocketHttpRouterGroup,
700
+ webSocketRouterGroup: webSocketRouterGroup,
701
+ injector: injector,
702
+ prefix: fullPrefix
703
+ })
704
+ );
705
+ //#endregion
706
+
707
+ return Object.freeze({
708
+ prefix: modulePrefix || "",
709
+ injector: injector,
710
+ startMiddlewareGroup: startMiddlewareGroup,
711
+ endMiddlewareGroup: endMiddlewareGroup,
712
+ guardGroup: guardGroup,
713
+ openDispatcherGroup: openDispatcherGroup,
714
+ closeDispatcherGroup: closeDispatcherGroup,
715
+ controllerRouterGroup: controllerRouterGroup,
716
+ webSocketHttpRouterGroup: webSocketHttpRouterGroup,
717
+ webSocketRouterGroup: webSocketRouterGroup
718
+ });
719
+ };
720
+
721
+ const webSocketFetcher = async (
722
+ bun: Required<{
723
+ request: Request;
724
+ server: Server;
725
+ }>,
726
+ bool: Required<{
727
+ responseHeaders: Headers;
728
+ query: Record<string, unknown>;
729
+ route: NonNullable<ReturnType<HttpRouterGroup["find"]>>;
730
+ moduleResolution: NonNullable<Awaited<ReturnType<typeof moduleResolution>>>;
731
+ }>
732
+ ) => {
733
+ const { request, server } = bun;
734
+ const {
735
+ query,
736
+ responseHeaders,
737
+ route: { model }
738
+ } = bool;
739
+
740
+ // Execute controller action
741
+ const isUpgrade = await model.func(...[server, request, query]);
742
+
743
+ if (typeof isUpgrade !== "boolean") {
744
+ return responseConverter(
745
+ new Response(
746
+ JSON.stringify({
747
+ httpCode: 500,
748
+ message: "Can not detect webSocket upgrade result.",
749
+ data: undefined
750
+ }),
751
+ {
752
+ status: 500,
753
+ statusText: "Internal server error.",
754
+ headers: responseHeaders
755
+ }
756
+ )
757
+ );
758
+ }
759
+
760
+ if (!isUpgrade) {
761
+ return responseConverter(
762
+ new Response(
763
+ JSON.stringify({
764
+ httpCode: 500,
765
+ message: "Can not upgrade.",
766
+ data: undefined
767
+ }),
768
+ {
769
+ status: 500,
770
+ statusText: "Internal server error.",
771
+ headers: responseHeaders
772
+ }
773
+ )
774
+ );
775
+ }
776
+
777
+ return isUpgrade;
778
+ };
779
+
780
+ const httpFetcher = async (
781
+ bool: Required<{}> &
782
+ Partial<{
783
+ route: NonNullable<ReturnType<HttpRouterGroup["find"]>>;
784
+ resolutedMap:
785
+ | Partial<NonNullable<Awaited<ReturnType<typeof containerResolution>>>>
786
+ | Partial<NonNullable<Awaited<ReturnType<typeof moduleResolution>>>>;
787
+ context: Context;
788
+ }>
789
+ ) => {
790
+ const { context: outerContext, route, resolutedMap } = bool;
791
+
792
+ const context = (!outerContext ? new Context() : new Context(outerContext)).setOptions({
793
+ isStatic: true
794
+ });
795
+
796
+ if (route) {
797
+ context.set(paramsArgsKey, route.parameters).set(routeModelArgsKey, route.model);
798
+ }
799
+
800
+ const httpServer = context.get<Server | null | undefined>(httpServerArgsKey) || undefined,
801
+ request = context.get<Request | null | undefined>(requestArgsKey) || undefined,
802
+ requestHeaders = context.get<Headers | null | undefined>(requestHeaderArgsKey) || undefined,
803
+ responseHeaders =
804
+ context.get<Headers | null | undefined>(responseHeadersArgsKey) || undefined,
805
+ parameters = context.get<TParamsType | null | undefined>(paramsArgsKey) || undefined,
806
+ routeModel =
807
+ context.get<
808
+ NonNullable<ReturnType<HttpRouterGroup["find"]>>["model"] | null | undefined
809
+ >(routeModelArgsKey) || undefined;
810
+
811
+ if (resolutedMap) {
812
+ const { startMiddlewareGroup, guardGroup } = resolutedMap;
813
+
814
+ // Execute start middleware(s)
815
+ if (startMiddlewareGroup) {
816
+ for (let i = 0; i < startMiddlewareGroup.length; i++) {
817
+ const args = [];
818
+ const {
819
+ func: handler,
820
+ funcName: functionName,
821
+ argumentsMetadata
822
+ } = startMiddlewareGroup[i];
823
+
824
+ for (const [_key, argMetadata] of Object.entries(argumentsMetadata)) {
825
+ switch (argMetadata.type) {
826
+ case contextArgsKey:
827
+ args[argMetadata.index] = !argMetadata.key
828
+ ? context
829
+ : context.get(argMetadata.key);
830
+ break;
831
+ case requestArgsKey:
832
+ args[argMetadata.index] = !argMetadata.zodSchema
833
+ ? request
834
+ : await argumentsResolution(
835
+ request,
836
+ argMetadata.zodSchema,
837
+ argMetadata.index,
838
+ functionName
839
+ );
840
+ break;
841
+ case requestBodyArgsKey:
842
+ args[argMetadata.index] = !argMetadata.zodSchema
843
+ ? await request?.[argMetadata.parser || "json"]()
844
+ : await argumentsResolution(
845
+ await request?.[argMetadata.parser || "json"](),
846
+ argMetadata.zodSchema,
847
+ argMetadata.index,
848
+ functionName
849
+ );
850
+ break;
851
+ case requestHeadersArgsKey:
852
+ args[argMetadata.index] = !argMetadata.zodSchema
853
+ ? requestHeaders
854
+ : await argumentsResolution(
855
+ requestHeaders?.toJSON(),
856
+ argMetadata.zodSchema,
857
+ argMetadata.index,
858
+ functionName
859
+ );
860
+ break;
861
+ case requestHeaderArgsKey:
862
+ args[argMetadata.index] = !argMetadata.zodSchema
863
+ ? requestHeaders?.get(argMetadata.key) || undefined
864
+ : await argumentsResolution(
865
+ requestHeaders?.get(argMetadata.key) || undefined,
866
+ argMetadata.zodSchema,
867
+ argMetadata.index,
868
+ functionName
869
+ );
870
+ break;
871
+ case paramArgsKey:
872
+ args[argMetadata.index] = !argMetadata.zodSchema
873
+ ? parameters?.[argMetadata.key] || undefined
874
+ : await argumentsResolution(
875
+ parameters?.[argMetadata.key] || undefined,
876
+ argMetadata.zodSchema,
877
+ argMetadata.index,
878
+ functionName
879
+ );
880
+ break;
881
+ case routeModelArgsKey:
882
+ args[argMetadata.index] = routeModel;
883
+ break;
884
+ case responseHeadersArgsKey:
885
+ args[argMetadata.index] = responseHeaders;
886
+ break;
887
+ case httpServerArgsKey:
888
+ args[argMetadata.index] = httpServer;
889
+ break;
890
+ default:
891
+ args[argMetadata.index] = !argMetadata.zodSchema
892
+ ? !context.has(argMetadata.type)
893
+ ? undefined
894
+ : context.get(argMetadata.type)
895
+ : await argumentsResolution(
896
+ !(argMetadata.type in context)
897
+ ? undefined
898
+ : context.get(argMetadata.type),
899
+ argMetadata.zodSchema,
900
+ argMetadata.index,
901
+ functionName
902
+ );
903
+ break;
904
+ }
905
+ }
906
+
907
+ await handler(...args);
908
+ }
909
+ }
910
+
911
+ // Execute guard(s)
912
+ if (guardGroup) {
913
+ for (let i = 0; i < guardGroup.length; i++) {
914
+ const args = [];
915
+ const { func: handler, funcName: functionName, argumentsMetadata } = guardGroup[i];
916
+
917
+ for (const [_key, argMetadata] of Object.entries(argumentsMetadata)) {
918
+ switch (argMetadata.type) {
919
+ case requestArgsKey:
920
+ args[argMetadata.index] = !argMetadata.zodSchema
921
+ ? request
922
+ : await argumentsResolution(
923
+ request,
924
+ argMetadata.zodSchema,
925
+ argMetadata.index,
926
+ functionName
927
+ );
928
+ break;
929
+ case requestBodyArgsKey:
930
+ args[argMetadata.index] = !argMetadata.zodSchema
931
+ ? await request?.[argMetadata.parser || "json"]()
932
+ : await argumentsResolution(
933
+ await request?.[argMetadata.parser || "json"](),
934
+ argMetadata.zodSchema,
935
+ argMetadata.index,
936
+ functionName
937
+ );
938
+ break;
939
+ case contextArgsKey:
940
+ args[argMetadata.index] = !argMetadata.key
941
+ ? context
942
+ : context.get(argMetadata.key);
943
+ break;
944
+ case requestHeadersArgsKey:
945
+ args[argMetadata.index] = !argMetadata.zodSchema
946
+ ? requestHeaders
947
+ : await argumentsResolution(
948
+ requestHeaders?.toJSON(),
949
+ argMetadata.zodSchema,
950
+ argMetadata.index,
951
+ functionName
952
+ );
953
+ break;
954
+ case responseHeadersArgsKey:
955
+ args[argMetadata.index] = responseHeaders;
956
+ break;
957
+ case requestHeaderArgsKey:
958
+ args[argMetadata.index] = !argMetadata.zodSchema
959
+ ? requestHeaders?.get(argMetadata.key) || undefined
960
+ : await argumentsResolution(
961
+ requestHeaders?.get(argMetadata.key) || undefined,
962
+ argMetadata.zodSchema,
963
+ argMetadata.index,
964
+ functionName
965
+ );
966
+ break;
967
+ case paramArgsKey:
968
+ args[argMetadata.index] = !argMetadata.zodSchema
969
+ ? parameters?.[argMetadata.key] || undefined
970
+ : await argumentsResolution(
971
+ parameters?.[argMetadata.key],
972
+ argMetadata.zodSchema,
973
+ argMetadata.index,
974
+ functionName
975
+ );
976
+ break;
977
+ case routeModelArgsKey:
978
+ args[argMetadata.index] = routeModel;
979
+ break;
980
+ case httpServerArgsKey:
981
+ args[argMetadata.index] = httpServer;
982
+ break;
983
+ default:
984
+ args[argMetadata.index] = !argMetadata.zodSchema
985
+ ? !context.has(argMetadata.type)
986
+ ? undefined
987
+ : context.get(argMetadata.type)
988
+ : await argumentsResolution(
989
+ context.get(argMetadata.type),
990
+ argMetadata.zodSchema,
991
+ argMetadata.index,
992
+ functionName
993
+ );
994
+ break;
995
+ }
996
+ }
997
+
998
+ const guardResult = await handler(...args);
999
+
1000
+ if (typeof guardResult !== "boolean" || !guardResult) {
1001
+ throw new HttpClientError({
1002
+ httpCode: 401,
1003
+ message: "Unauthorization.",
1004
+ data: undefined
1005
+ });
1006
+ }
1007
+ }
1008
+ }
1009
+ }
1010
+
1011
+ if (routeModel) {
1012
+ if (
1013
+ resolutedMap &&
1014
+ "openDispatcherGroup" in resolutedMap &&
1015
+ resolutedMap.openDispatcherGroup
1016
+ ) {
1017
+ const { openDispatcherGroup } = resolutedMap;
1018
+
1019
+ // Execute open dispatcher(s)
1020
+ for (let i = 0; i < openDispatcherGroup.length; i++) {
1021
+ const args = [];
1022
+ const {
1023
+ func: handler,
1024
+ funcName: functionName,
1025
+ argumentsMetadata
1026
+ } = openDispatcherGroup[i];
1027
+
1028
+ for (const [_key, argMetadata] of Object.entries(argumentsMetadata)) {
1029
+ switch (argMetadata.type) {
1030
+ case requestArgsKey:
1031
+ args[argMetadata.index] = !argMetadata.zodSchema
1032
+ ? request
1033
+ : await argumentsResolution(
1034
+ request,
1035
+ argMetadata.zodSchema,
1036
+ argMetadata.index,
1037
+ functionName
1038
+ );
1039
+ break;
1040
+ case requestBodyArgsKey:
1041
+ args[argMetadata.index] = !argMetadata.zodSchema
1042
+ ? await request?.[argMetadata.parser || "json"]()
1043
+ : await argumentsResolution(
1044
+ await request?.[argMetadata.parser || "json"](),
1045
+ argMetadata.zodSchema,
1046
+ argMetadata.index,
1047
+ functionName
1048
+ );
1049
+ break;
1050
+ case contextArgsKey:
1051
+ args[argMetadata.index] = !argMetadata.key
1052
+ ? context
1053
+ : context.get(argMetadata.key);
1054
+ break;
1055
+ case requestHeadersArgsKey:
1056
+ args[argMetadata.index] = !argMetadata.zodSchema
1057
+ ? requestHeaders
1058
+ : await argumentsResolution(
1059
+ requestHeaders?.toJSON(),
1060
+ argMetadata.zodSchema,
1061
+ argMetadata.index,
1062
+ functionName
1063
+ );
1064
+ break;
1065
+ case requestHeaderArgsKey:
1066
+ args[argMetadata.index] = !argMetadata.zodSchema
1067
+ ? requestHeaders?.get(argMetadata.key) || undefined
1068
+ : await argumentsResolution(
1069
+ requestHeaders?.get(argMetadata.key) || undefined,
1070
+ argMetadata.zodSchema,
1071
+ argMetadata.index,
1072
+ functionName
1073
+ );
1074
+ break;
1075
+ case responseHeadersArgsKey:
1076
+ args[argMetadata.index] = responseHeaders;
1077
+ break;
1078
+ case paramArgsKey:
1079
+ args[argMetadata.index] = !argMetadata.zodSchema
1080
+ ? parameters?.[argMetadata.key] || undefined
1081
+ : await argumentsResolution(
1082
+ parameters?.[argMetadata.key] || undefined,
1083
+ argMetadata.zodSchema,
1084
+ argMetadata.index,
1085
+ functionName
1086
+ );
1087
+ break;
1088
+ case routeModelArgsKey:
1089
+ args[argMetadata.index] = routeModel;
1090
+ break;
1091
+ case httpServerArgsKey:
1092
+ args[argMetadata.index] = httpServer;
1093
+ break;
1094
+ default:
1095
+ args[argMetadata.index] = !argMetadata.zodSchema
1096
+ ? !context.has(argMetadata.type)
1097
+ ? undefined
1098
+ : context.get(argMetadata.type)
1099
+ : await argumentsResolution(
1100
+ context.get(argMetadata.type),
1101
+ argMetadata.zodSchema,
1102
+ argMetadata.index,
1103
+ functionName
1104
+ );
1105
+ break;
1106
+ }
1107
+ }
1108
+
1109
+ await handler(...args);
1110
+ }
1111
+ }
1112
+
1113
+ // Execute controller action
1114
+ const controllerActionArguments: any[] = [];
1115
+ const {
1116
+ func: controllerAction,
1117
+ funcName: controllerActionName,
1118
+ argumentsMetadata: controllerActionArgumentsMetadata
1119
+ } = routeModel;
1120
+
1121
+ for (const [_key, argMetadata] of Object.entries(controllerActionArgumentsMetadata)) {
1122
+ switch (argMetadata.type) {
1123
+ case requestArgsKey:
1124
+ controllerActionArguments[argMetadata.index] = !argMetadata.zodSchema
1125
+ ? request
1126
+ : await argumentsResolution(
1127
+ request,
1128
+ argMetadata.zodSchema,
1129
+ argMetadata.index,
1130
+ controllerActionName
1131
+ );
1132
+ break;
1133
+ case requestBodyArgsKey:
1134
+ controllerActionArguments[argMetadata.index] = !argMetadata.zodSchema
1135
+ ? await request?.[argMetadata.parser || "json"]()
1136
+ : await argumentsResolution(
1137
+ await request?.[argMetadata.parser || "json"](),
1138
+ argMetadata.zodSchema,
1139
+ argMetadata.index,
1140
+ controllerActionName
1141
+ );
1142
+ break;
1143
+ case contextArgsKey:
1144
+ controllerActionArguments[argMetadata.index] = !argMetadata.key
1145
+ ? context
1146
+ : context.get(argMetadata.key);
1147
+ break;
1148
+ case requestHeadersArgsKey:
1149
+ controllerActionArguments[argMetadata.index] = !argMetadata.zodSchema
1150
+ ? requestHeaders
1151
+ : await argumentsResolution(
1152
+ requestHeaders?.toJSON(),
1153
+ argMetadata.zodSchema,
1154
+ argMetadata.index,
1155
+ controllerActionName
1156
+ );
1157
+ break;
1158
+ case requestHeaderArgsKey:
1159
+ controllerActionArguments[argMetadata.index] = !argMetadata.zodSchema
1160
+ ? requestHeaders?.get(argMetadata.key) || undefined
1161
+ : await argumentsResolution(
1162
+ requestHeaders?.get(argMetadata.key) || undefined,
1163
+ argMetadata.zodSchema,
1164
+ argMetadata.index,
1165
+ controllerActionName
1166
+ );
1167
+ break;
1168
+ case responseHeadersArgsKey:
1169
+ controllerActionArguments[argMetadata.index] = responseHeaders;
1170
+ break;
1171
+ case paramArgsKey:
1172
+ controllerActionArguments[argMetadata.index] = !argMetadata.zodSchema
1173
+ ? parameters?.[argMetadata.key] || undefined
1174
+ : await argumentsResolution(
1175
+ parameters?.[argMetadata.key] || undefined,
1176
+ argMetadata.zodSchema,
1177
+ argMetadata.index,
1178
+ controllerActionName
1179
+ );
1180
+ break;
1181
+ case routeModelArgsKey:
1182
+ controllerActionArguments[argMetadata.index] = routeModel;
1183
+ break;
1184
+ case httpServerArgsKey:
1185
+ controllerActionArguments[argMetadata.index] = httpServer;
1186
+ break;
1187
+ default:
1188
+ controllerActionArguments[argMetadata.index] = !argMetadata.zodSchema
1189
+ ? !context.has(argMetadata.type)
1190
+ ? undefined
1191
+ : context.get(argMetadata.type)
1192
+ : await argumentsResolution(
1193
+ context.get(argMetadata.type),
1194
+ argMetadata.zodSchema,
1195
+ argMetadata.index,
1196
+ controllerActionName
1197
+ );
1198
+ break;
1199
+ }
1200
+ }
1201
+
1202
+ context.set(responseBodyArgsKey, await controllerAction(...controllerActionArguments), {
1203
+ isStatic: false
1204
+ });
1205
+
1206
+ if (
1207
+ resolutedMap &&
1208
+ "closeDispatcherGroup" in resolutedMap &&
1209
+ resolutedMap.closeDispatcherGroup
1210
+ ) {
1211
+ const { closeDispatcherGroup } = resolutedMap;
1212
+
1213
+ // Execute close dispatcher(s)
1214
+ for (let i = 0; i < closeDispatcherGroup.length; i++) {
1215
+ const args = [];
1216
+ const {
1217
+ func: handler,
1218
+ funcName: functionName,
1219
+ argumentsMetadata
1220
+ } = closeDispatcherGroup[i];
1221
+
1222
+ for (const [_key, argMetadata] of Object.entries(argumentsMetadata)) {
1223
+ switch (argMetadata.type) {
1224
+ case requestArgsKey:
1225
+ args[argMetadata.index] = !argMetadata.zodSchema
1226
+ ? request
1227
+ : await argumentsResolution(
1228
+ request,
1229
+ argMetadata.zodSchema,
1230
+ argMetadata.index,
1231
+ functionName
1232
+ );
1233
+ break;
1234
+ case requestBodyArgsKey:
1235
+ args[argMetadata.index] = !argMetadata.zodSchema
1236
+ ? await request?.[argMetadata.parser || "json"]()
1237
+ : await argumentsResolution(
1238
+ await request?.[argMetadata.parser || "json"](),
1239
+ argMetadata.zodSchema,
1240
+ argMetadata.index,
1241
+ functionName
1242
+ );
1243
+ break;
1244
+ case contextArgsKey:
1245
+ args[argMetadata.index] = !argMetadata.key
1246
+ ? context
1247
+ : context.get(argMetadata.key);
1248
+ break;
1249
+ case requestHeadersArgsKey:
1250
+ args[argMetadata.index] = !argMetadata.zodSchema
1251
+ ? requestHeaders
1252
+ : await argumentsResolution(
1253
+ requestHeaders?.toJSON(),
1254
+ argMetadata.zodSchema,
1255
+ argMetadata.index,
1256
+ functionName
1257
+ );
1258
+ break;
1259
+ case responseHeadersArgsKey:
1260
+ args[argMetadata.index] = context.get(argMetadata.type);
1261
+ break;
1262
+ case requestHeaderArgsKey:
1263
+ args[argMetadata.index] = !argMetadata.zodSchema
1264
+ ? requestHeaders?.get(argMetadata.key) || undefined
1265
+ : await argumentsResolution(
1266
+ requestHeaders?.get(argMetadata.key) || undefined,
1267
+ argMetadata.zodSchema,
1268
+ argMetadata.index,
1269
+ functionName
1270
+ );
1271
+ break;
1272
+ case paramArgsKey:
1273
+ args[argMetadata.index] = !argMetadata.zodSchema
1274
+ ? parameters?.[argMetadata.key] || undefined
1275
+ : await argumentsResolution(
1276
+ parameters?.[argMetadata.key] || undefined,
1277
+ argMetadata.zodSchema,
1278
+ argMetadata.index,
1279
+ functionName
1280
+ );
1281
+ break;
1282
+ case routeModelArgsKey:
1283
+ args[argMetadata.index] = routeModel;
1284
+ break;
1285
+ case httpServerArgsKey:
1286
+ args[argMetadata.index] = httpServer;
1287
+ break;
1288
+ default:
1289
+ args[argMetadata.index] = !argMetadata.zodSchema
1290
+ ? !context.has(argMetadata.type)
1291
+ ? undefined
1292
+ : context.get(argMetadata.type)
1293
+ : await argumentsResolution(
1294
+ context.get(argMetadata.type),
1295
+ argMetadata.zodSchema,
1296
+ argMetadata.index,
1297
+ functionName
1298
+ );
1299
+ break;
1300
+ }
1301
+ }
1302
+
1303
+ await handler(...args);
1304
+ }
1305
+ }
1306
+ }
1307
+
1308
+ if (resolutedMap) {
1309
+ const { endMiddlewareGroup } = resolutedMap;
1310
+
1311
+ // Execute end middleware(s)
1312
+ if (endMiddlewareGroup) {
1313
+ for (let i = 0; i < endMiddlewareGroup.length; i++) {
1314
+ const args = [];
1315
+ const {
1316
+ func: handler,
1317
+ funcName: functionName,
1318
+ argumentsMetadata
1319
+ } = endMiddlewareGroup[i];
1320
+
1321
+ for (const [_key, argMetadata] of Object.entries(argumentsMetadata)) {
1322
+ switch (argMetadata.type) {
1323
+ case requestArgsKey:
1324
+ args[argMetadata.index] = !argMetadata.zodSchema
1325
+ ? request
1326
+ : await argumentsResolution(
1327
+ request,
1328
+ argMetadata.zodSchema,
1329
+ argMetadata.index,
1330
+ functionName
1331
+ );
1332
+ break;
1333
+ case requestBodyArgsKey:
1334
+ args[argMetadata.index] = !argMetadata.zodSchema
1335
+ ? await request?.[argMetadata.parser || "json"]()
1336
+ : await argumentsResolution(
1337
+ await request?.[argMetadata.parser || "json"](),
1338
+ argMetadata.zodSchema,
1339
+ argMetadata.index,
1340
+ functionName
1341
+ );
1342
+ break;
1343
+ case contextArgsKey:
1344
+ args[argMetadata.index] = !argMetadata.key
1345
+ ? context
1346
+ : context.get(argMetadata.key);
1347
+ break;
1348
+ case requestHeadersArgsKey:
1349
+ args[argMetadata.index] = !argMetadata.zodSchema
1350
+ ? requestHeaders
1351
+ : await argumentsResolution(
1352
+ requestHeaders?.toJSON(),
1353
+ argMetadata.zodSchema,
1354
+ argMetadata.index,
1355
+ functionName
1356
+ );
1357
+ break;
1358
+ case responseHeadersArgsKey:
1359
+ args[argMetadata.index] = context.get(argMetadata.type);
1360
+ break;
1361
+ case requestHeaderArgsKey:
1362
+ args[argMetadata.index] = !argMetadata.zodSchema
1363
+ ? requestHeaders?.get(argMetadata.key) || undefined
1364
+ : await argumentsResolution(
1365
+ requestHeaders?.get(argMetadata.key) || undefined,
1366
+ argMetadata.zodSchema,
1367
+ argMetadata.index,
1368
+ functionName
1369
+ );
1370
+ break;
1371
+ case paramArgsKey:
1372
+ args[argMetadata.index] = !argMetadata.zodSchema
1373
+ ? parameters?.[argMetadata.key] || undefined
1374
+ : await argumentsResolution(
1375
+ parameters?.[argMetadata.key] || undefined,
1376
+ argMetadata.zodSchema,
1377
+ argMetadata.index,
1378
+ functionName
1379
+ );
1380
+ break;
1381
+ case routeModelArgsKey:
1382
+ args[argMetadata.index] = routeModel;
1383
+ break;
1384
+ case httpServerArgsKey:
1385
+ args[argMetadata.index] = httpServer;
1386
+ break;
1387
+ default:
1388
+ args[argMetadata.index] = !argMetadata.zodSchema
1389
+ ? !context.has(argMetadata.type)
1390
+ ? undefined
1391
+ : context.get(argMetadata.type)
1392
+ : await argumentsResolution(
1393
+ !(argMetadata.type in context)
1394
+ ? undefined
1395
+ : context.get(argMetadata.type),
1396
+ argMetadata.zodSchema,
1397
+ argMetadata.index,
1398
+ functionName
1399
+ );
1400
+ break;
1401
+ }
1402
+ }
1403
+
1404
+ await handler(...args);
1405
+ }
1406
+ }
1407
+ }
1408
+
1409
+ return Object.freeze({
1410
+ context: context
1411
+ });
1412
+ };
1413
+
1414
+ export const BoolFactory = async (
1415
+ classConstructor: new (...args: any[]) => unknown,
1416
+ options: TBoolFactoryOptions
1417
+ ) => {
1418
+ try {
1419
+ const staticMap: Map<
1420
+ string,
1421
+ Readonly<{
1422
+ expiredAt: Date;
1423
+ file: BunFile;
1424
+ }>
1425
+ > = new Map();
1426
+
1427
+ const {
1428
+ allowLogsMethods,
1429
+ staticOption,
1430
+ allowOrigins,
1431
+ allowMethods,
1432
+ allowCredentials,
1433
+ allowHeaders
1434
+ } = Object.freeze({
1435
+ allowLogsMethods: options?.log?.methods,
1436
+ staticOption: options.static,
1437
+ allowOrigins: !options.cors?.origins
1438
+ ? ["*"]
1439
+ : typeof options.cors.origins !== "string"
1440
+ ? options.cors.origins.includes("*") || options.cors.origins.length < 1
1441
+ ? ["*"]
1442
+ : options.cors.origins
1443
+ : [options.cors.origins !== "*" ? options.cors.origins : "*"],
1444
+ allowMethods: options.cors?.methods || [
1445
+ "GET",
1446
+ "POST",
1447
+ "PUT",
1448
+ "PATCH",
1449
+ "DELETE",
1450
+ "OPTIONS"
1451
+ ],
1452
+ allowCredentials: !options.cors?.credentials ? false : true,
1453
+ allowHeaders:
1454
+ !options.cors?.headers || options.cors.headers.includes("*")
1455
+ ? ["*"]
1456
+ : options.cors.headers
1457
+ });
1458
+
1459
+ const inputedConstructorKeys = Reflect.getOwnMetadataKeys(classConstructor);
1460
+
1461
+ if (
1462
+ !inputedConstructorKeys.includes(containerKey) &&
1463
+ !inputedConstructorKeys.includes(moduleKey)
1464
+ ) {
1465
+ throw Error(
1466
+ `Can not detect! ${classConstructor.name} class is not a container or module.`
1467
+ );
1468
+ }
1469
+
1470
+ const injector = new Injector();
1471
+
1472
+ const containerMetadata: TContainerMetadata = !inputedConstructorKeys.includes(containerKey)
1473
+ ? undefined
1474
+ : Reflect.getOwnMetadata(containerKey, classConstructor);
1475
+
1476
+ const modulesConverted = !inputedConstructorKeys.includes(containerKey)
1477
+ ? [classConstructor]
1478
+ : containerMetadata?.modules || [];
1479
+
1480
+ const resolutedContainer = !containerMetadata
1481
+ ? undefined
1482
+ : await containerResolution({
1483
+ containerClass: classConstructor,
1484
+ options: options,
1485
+ extendInjector: injector
1486
+ });
1487
+
1488
+ const resolutedModules = await Promise.all(
1489
+ modulesConverted.map((moduleConverted) =>
1490
+ moduleResolution({
1491
+ moduleClass: moduleConverted,
1492
+ options: options,
1493
+ extendInjector: !resolutedContainer ? injector : resolutedContainer.injector
1494
+ })
1495
+ )
1496
+ );
1497
+
1498
+ const availableModuleResolutions = resolutedModules.filter(
1499
+ (resolutedModule) => typeof resolutedModule !== "undefined"
1500
+ );
1501
+
1502
+ const prefixs = [
1503
+ ...new Set(
1504
+ availableModuleResolutions.map(
1505
+ (availableModuleResolution) => availableModuleResolution.prefix
1506
+ )
1507
+ )
1508
+ ];
1509
+
1510
+ if (prefixs.length !== availableModuleResolutions.length) {
1511
+ throw Error("Module prefix should be unique.");
1512
+ }
1513
+
1514
+ const webSocketsMap = new Map<string, TWebSocketEventHandlerMetadata>();
1515
+
1516
+ for (const availableModuleResolution of availableModuleResolutions) {
1517
+ const webSocketMap = availableModuleResolution.webSocketRouterGroup.execute();
1518
+
1519
+ for (const [key, metadata] of webSocketMap.entries()) {
1520
+ webSocketsMap.set(key, metadata);
1521
+ }
1522
+ }
1523
+
1524
+ const server = Bun.serve<TWebSocketUpgradeData, {}>({
1525
+ port: options.port,
1526
+ fetch: async (request, server) => {
1527
+ const start = performance.now(),
1528
+ url = new URL(request.url),
1529
+ query = Qs.parse(url.searchParams.toString(), options.queryParser),
1530
+ origin = request.headers.get("origin") || "*",
1531
+ method = request.method.toUpperCase(),
1532
+ responseHeaders = new Headers();
1533
+
1534
+ let context = new Context()
1535
+ .setOptions({ isStatic: true })
1536
+ .set(httpServerArgsKey, server)
1537
+ .set(requestHeaderArgsKey, request.headers)
1538
+ .set(responseHeadersArgsKey, responseHeaders)
1539
+ .set(queryArgsKey, query);
1540
+
1541
+ try {
1542
+ const isUpgradable = isWebSocketUpgrade(request);
1543
+
1544
+ let collection:
1545
+ | undefined
1546
+ | Required<{
1547
+ route: NonNullable<ReturnType<HttpRouterGroup["find"]>>;
1548
+ resolution: NonNullable<Awaited<ReturnType<typeof moduleResolution>>>;
1549
+ }>;
1550
+
1551
+ if (isUpgradable) {
1552
+ for (const availableModuleResolution of availableModuleResolutions) {
1553
+ const routeResult =
1554
+ availableModuleResolution.webSocketHttpRouterGroup.find(
1555
+ url.pathname,
1556
+ request.method as keyof THttpMethods
1557
+ );
1558
+
1559
+ if (routeResult) {
1560
+ collection = Object.freeze({
1561
+ route: routeResult,
1562
+ resolution: availableModuleResolution
1563
+ });
1564
+ break;
1565
+ }
1566
+ }
1567
+
1568
+ if (!collection) {
1569
+ return responseConverter(
1570
+ new Response(
1571
+ JSON.stringify({
1572
+ httpCode: 404,
1573
+ message: "Route not found",
1574
+ data: undefined
1575
+ }),
1576
+ {
1577
+ status: 404,
1578
+ statusText: "Not found.",
1579
+ headers: responseHeaders
1580
+ }
1581
+ )
1582
+ );
1583
+ }
1584
+
1585
+ const upgradeResult = await webSocketFetcher(
1586
+ {
1587
+ request,
1588
+ server
1589
+ },
1590
+ {
1591
+ query: query,
1592
+ responseHeaders: responseHeaders,
1593
+ route: collection.route,
1594
+ moduleResolution: collection.resolution
1595
+ }
1596
+ );
1597
+
1598
+ return upgradeResult instanceof Response ? upgradeResult : undefined;
1599
+ }
1600
+
1601
+ [
1602
+ ...(!allowCredentials
1603
+ ? []
1604
+ : [
1605
+ {
1606
+ key: "Access-Control-Allow-Credentials",
1607
+ value: "true"
1608
+ }
1609
+ ]),
1610
+ {
1611
+ key: "Access-Control-Allow-Origin",
1612
+ value: allowOrigins.includes("*")
1613
+ ? "*"
1614
+ : !allowOrigins.includes(origin)
1615
+ ? allowOrigins[0]
1616
+ : origin
1617
+ },
1618
+ { key: "Access-Control-Allow-Methods", value: allowMethods.join(", ") },
1619
+ { key: "Access-Control-Allow-Headers", value: allowHeaders.join(", ") }
1620
+ ].forEach(({ key, value }) => responseHeaders.set(key, value));
1621
+
1622
+ if (!allowMethods.includes(method)) {
1623
+ return responseConverter(
1624
+ new Response(undefined, {
1625
+ status: 405,
1626
+ statusText: "Method Not Allowed.",
1627
+ headers: responseHeaders
1628
+ })
1629
+ );
1630
+ }
1631
+
1632
+ if (request.method.toUpperCase() === "OPTIONS") {
1633
+ return responseConverter(
1634
+ allowOrigins.includes("*") || allowOrigins.includes(origin)
1635
+ ? new Response(undefined, {
1636
+ status: 204,
1637
+ statusText: "No Content.",
1638
+ headers: responseHeaders
1639
+ })
1640
+ : new Response(undefined, {
1641
+ status: 417,
1642
+ statusText: "Expectation Failed.",
1643
+ headers: responseHeaders
1644
+ })
1645
+ );
1646
+ }
1647
+
1648
+ if (staticOption) {
1649
+ const { path, headers, cacheTimeInSeconds } = staticOption;
1650
+ const pathname = `${path}/${url.pathname}`;
1651
+ const cachedFile = staticMap.get(pathname);
1652
+
1653
+ if (!cachedFile) {
1654
+ const file = Bun.file(pathname);
1655
+ const isFileExists = await file.exists();
1656
+
1657
+ if (isFileExists) {
1658
+ if (headers) {
1659
+ for (const [key, value] of Object.entries(headers)) {
1660
+ responseHeaders.set(key, value);
1661
+ }
1662
+ }
1663
+
1664
+ responseHeaders.set("Content-Type", file.type);
1665
+
1666
+ return responseConverter(
1667
+ new Response(await file.arrayBuffer(), {
1668
+ status: 200,
1669
+ statusText: "SUCCESS",
1670
+ headers: responseHeaders
1671
+ })
1672
+ );
1673
+ }
1674
+ } else {
1675
+ const isExpired = new Date() > cachedFile.expiredAt;
1676
+
1677
+ if (isExpired) {
1678
+ staticMap.delete(pathname);
1679
+ }
1680
+
1681
+ const file = !isExpired ? cachedFile.file : Bun.file(pathname);
1682
+ const isFileExists = await file.exists();
1683
+
1684
+ if (isFileExists) {
1685
+ staticMap.set(
1686
+ pathname,
1687
+ Object.freeze({
1688
+ expiredAt: TimeAdd(
1689
+ new Date(),
1690
+ typeof cacheTimeInSeconds !== "number"
1691
+ ? DEFAULT_STATIC_CACHE_TIME_IN_SECONDS
1692
+ : cacheTimeInSeconds,
1693
+ ETimeUnit.seconds
1694
+ ),
1695
+ file: file
1696
+ })
1697
+ );
1698
+
1699
+ if (headers) {
1700
+ for (const [key, value] of Object.entries(headers)) {
1701
+ responseHeaders.set(key, value);
1702
+ }
1703
+ }
1704
+
1705
+ responseHeaders.set("Content-Type", file.type);
1706
+
1707
+ return responseConverter(
1708
+ new Response(await file.arrayBuffer(), {
1709
+ status: 200,
1710
+ statusText: "SUCCESS",
1711
+ headers: responseHeaders
1712
+ })
1713
+ );
1714
+ }
1715
+ }
1716
+ }
1717
+
1718
+ if (resolutedContainer) {
1719
+ const { context: newContext } = await httpFetcher({
1720
+ context: context,
1721
+ resolutedMap: {
1722
+ injector: resolutedContainer.injector,
1723
+ startMiddlewareGroup: resolutedContainer.startMiddlewareGroup,
1724
+ guardGroup: resolutedContainer.guardGroup
1725
+ }
1726
+ });
1727
+
1728
+ context = newContext;
1729
+ }
1730
+
1731
+ for (const availableModuleResolution of availableModuleResolutions) {
1732
+ const routeResult = availableModuleResolution.controllerRouterGroup.find(
1733
+ url.pathname,
1734
+ method as keyof THttpMethods
1735
+ );
1736
+
1737
+ if (routeResult) {
1738
+ collection = Object.freeze({
1739
+ route: routeResult,
1740
+ resolution: availableModuleResolution
1741
+ });
1742
+ break;
1743
+ }
1744
+ }
1745
+
1746
+ if (!collection) {
1747
+ context
1748
+ .setOptions({ isStatic: false })
1749
+ .set(responseStatusArgsKey, 404)
1750
+ .set(responseStatusTextArgsKey, "Not found.")
1751
+ .set(
1752
+ responseBodyArgsKey,
1753
+ JSON.stringify({
1754
+ httpCode: 404,
1755
+ message: "Route not found",
1756
+ data: undefined
1757
+ })
1758
+ );
1759
+ } else {
1760
+ const { context: newContext } = await httpFetcher({
1761
+ context: context,
1762
+ route: collection.route,
1763
+ resolutedMap: collection.resolution
1764
+ });
1765
+
1766
+ context = newContext;
1767
+ }
1768
+
1769
+ if (resolutedContainer) {
1770
+ const { context: newContext } = await httpFetcher({
1771
+ context: context,
1772
+ resolutedMap: {
1773
+ injector: resolutedContainer.injector,
1774
+ endMiddlewareGroup: resolutedContainer.endMiddlewareGroup
1775
+ }
1776
+ });
1777
+
1778
+ context = newContext;
1779
+ }
1780
+
1781
+ context.setOptions({ isStatic: false });
1782
+
1783
+ const latestResponseHeaders =
1784
+ context.get<Headers | null | undefined>(responseHeadersArgsKey) ||
1785
+ new Headers(),
1786
+ latestResponseBody = context.get<BodyInit>(responseBodyArgsKey) || null,
1787
+ latestResponseStatus = context.get<unknown>(responseStatusArgsKey) || 200,
1788
+ latestResponseStatusText =
1789
+ context.get<unknown>(responseStatusArgsKey) || 200;
1790
+
1791
+ return responseConverter(
1792
+ new Response(latestResponseBody, {
1793
+ status:
1794
+ typeof latestResponseStatus !== "number"
1795
+ ? 200
1796
+ : latestResponseStatus,
1797
+ statusText:
1798
+ typeof latestResponseStatusText !== "string"
1799
+ ? undefined
1800
+ : latestResponseStatusText,
1801
+ headers: latestResponseHeaders
1802
+ })
1803
+ );
1804
+ } catch (error) {
1805
+ options.debug && console.error(error);
1806
+
1807
+ return responseConverter(jsonErrorInfer(error, responseHeaders));
1808
+ } finally {
1809
+ if (allowLogsMethods) {
1810
+ const end = performance.now();
1811
+ const pathname = ansiText(url.pathname, { color: "blue" });
1812
+ const convertedPID = `${Bun.color("yellow", "ansi")}${process.pid}`;
1813
+ const convertedMethod = ansiText(request.method, {
1814
+ color: "yellow",
1815
+ backgroundColor: "blue"
1816
+ });
1817
+ const convertedReqIp = ansiText(
1818
+ `${
1819
+ request.headers.get("x-forwarded-for") ||
1820
+ request.headers.get("x-real-ip") ||
1821
+ server.requestIP(request)?.address ||
1822
+ "<Unknown>"
1823
+ }`,
1824
+ {
1825
+ color: "yellow"
1826
+ }
1827
+ );
1828
+ const convertedTime = ansiText(
1829
+ `${Math.round((end - start + Number.EPSILON) * 10 ** 2) / 10 ** 2}ms`,
1830
+ {
1831
+ color: "yellow",
1832
+ backgroundColor: "blue"
1833
+ }
1834
+ );
1835
+
1836
+ allowLogsMethods.includes(
1837
+ request.method.toUpperCase() as (typeof allowLogsMethods)[number]
1838
+ ) &&
1839
+ console.info(
1840
+ `PID: ${convertedPID} - Method: ${convertedMethod} - IP: ${convertedReqIp} - ${pathname} - Time: ${convertedTime}`
1841
+ );
1842
+ }
1843
+ }
1844
+ },
1845
+ websocket: {
1846
+ open: (connection) => {
1847
+ const pathnameKey = `${connection.data.pathname}:::open`;
1848
+ const handlerMetadata = webSocketsMap.get(pathnameKey);
1849
+
1850
+ if (!handlerMetadata) {
1851
+ return;
1852
+ }
1853
+
1854
+ const argumentsMetadata = handlerMetadata.arguments || {};
1855
+ const args: Array<unknown> = [];
1856
+
1857
+ for (const [_key, argumentMetadata] of Object.entries(argumentsMetadata)) {
1858
+ switch (argumentMetadata.type) {
1859
+ case webSocketConnectionArgsKey:
1860
+ args[argumentMetadata.index] = connection;
1861
+ break;
1862
+ case webSocketServerArgsKey:
1863
+ args[argumentMetadata.index] = server;
1864
+ break;
1865
+ }
1866
+ }
1867
+
1868
+ handlerMetadata.descriptor.value(...args);
1869
+ },
1870
+ close: (connection, code: number, reason: string) => {
1871
+ const pathnameKey = `${connection.data.pathname}:::close`;
1872
+ const handlerMetadata = webSocketsMap.get(pathnameKey);
1873
+
1874
+ if (!handlerMetadata) {
1875
+ return;
1876
+ }
1877
+
1878
+ const argumentsMetadata = handlerMetadata.arguments || {};
1879
+ const args: Array<unknown> = [];
1880
+
1881
+ for (const [_key, argumentMetadata] of Object.entries(argumentsMetadata)) {
1882
+ switch (argumentMetadata.type) {
1883
+ case webSocketConnectionArgsKey:
1884
+ args[argumentMetadata.index] = connection;
1885
+ break;
1886
+ case webSocketServerArgsKey:
1887
+ args[argumentMetadata.index] = server;
1888
+ break;
1889
+ case webSocketCloseCodeArgsKey:
1890
+ args[argumentMetadata.index] = code;
1891
+ break;
1892
+ case webSocketCloseReasonArgsKey:
1893
+ args[argumentMetadata.index] = reason;
1894
+ break;
1895
+ }
1896
+ }
1897
+
1898
+ handlerMetadata.descriptor.value(...args);
1899
+ },
1900
+ message: (connection, message) => {
1901
+ const pathnameKey = `${connection.data.pathname}:::message`;
1902
+ const handlerMetadata = webSocketsMap.get(pathnameKey);
1903
+
1904
+ if (!handlerMetadata) {
1905
+ return;
1906
+ }
1907
+
1908
+ const argumentsMetadata = handlerMetadata.arguments || {};
1909
+ const args: Array<unknown> = [];
1910
+
1911
+ for (const [_key, argumentMetadata] of Object.entries(argumentsMetadata)) {
1912
+ switch (argumentMetadata.type) {
1913
+ case webSocketConnectionArgsKey:
1914
+ args[argumentMetadata.index] = connection;
1915
+ break;
1916
+ case webSocketMessageArgsKey:
1917
+ args[argumentMetadata.index] = message;
1918
+ break;
1919
+ case webSocketServerArgsKey:
1920
+ args[argumentMetadata.index] = server;
1921
+ break;
1922
+ }
1923
+ }
1924
+
1925
+ handlerMetadata.descriptor.value(...args);
1926
+ },
1927
+ drain: (connection) => {
1928
+ const pathnameKey = `${connection.data.pathname}:::drain`;
1929
+ const handlerMetadata = webSocketsMap.get(pathnameKey);
1930
+
1931
+ if (!handlerMetadata) {
1932
+ return;
1933
+ }
1934
+
1935
+ const argumentsMetadata = handlerMetadata.arguments || {};
1936
+ const args: Array<unknown> = [];
1937
+
1938
+ for (const [_key, argumentMetadata] of Object.entries(argumentsMetadata)) {
1939
+ switch (argumentMetadata.type) {
1940
+ case webSocketConnectionArgsKey:
1941
+ args[argumentMetadata.index] = connection;
1942
+ break;
1943
+ case webSocketServerArgsKey:
1944
+ args[argumentMetadata.index] = server;
1945
+ break;
1946
+ }
1947
+ }
1948
+
1949
+ handlerMetadata.descriptor.value(...args);
1950
+ },
1951
+ ping: (connection, data) => {
1952
+ const pathnameKey = `${connection.data.pathname}:::ping`;
1953
+ const handlerMetadata = webSocketsMap.get(pathnameKey);
1954
+
1955
+ if (!handlerMetadata) {
1956
+ return;
1957
+ }
1958
+
1959
+ const argumentsMetadata = handlerMetadata.arguments || {};
1960
+ const args: Array<unknown> = [];
1961
+
1962
+ for (const [_key, argumentMetadata] of Object.entries(argumentsMetadata)) {
1963
+ switch (argumentMetadata.type) {
1964
+ case webSocketConnectionArgsKey:
1965
+ args[argumentMetadata.index] = connection;
1966
+ break;
1967
+ case webSocketServerArgsKey:
1968
+ args[argumentMetadata.index] = server;
1969
+ break;
1970
+ case webSocketMessageArgsKey:
1971
+ args[argumentMetadata.index] = data;
1972
+ break;
1973
+ }
1974
+ }
1975
+
1976
+ handlerMetadata.descriptor.value(...args);
1977
+ },
1978
+ pong: (connection, data) => {
1979
+ const pathnameKey = `${connection.data.pathname}:::pong`;
1980
+ const handlerMetadata = webSocketsMap.get(pathnameKey);
1981
+
1982
+ if (!handlerMetadata) {
1983
+ return;
1984
+ }
1985
+
1986
+ const argumentsMetadata = handlerMetadata.arguments || {};
1987
+ const args: Array<unknown> = [];
1988
+
1989
+ for (const [_key, argumentMetadata] of Object.entries(argumentsMetadata)) {
1990
+ switch (argumentMetadata.type) {
1991
+ case webSocketConnectionArgsKey:
1992
+ args[argumentMetadata.index] = connection;
1993
+ break;
1994
+ case webSocketServerArgsKey:
1995
+ args[argumentMetadata.index] = server;
1996
+ break;
1997
+ case webSocketMessageArgsKey:
1998
+ args[argumentMetadata.index] = data;
1999
+ break;
2000
+ }
2001
+ }
2002
+
2003
+ handlerMetadata.descriptor.value(...args);
2004
+ }
2005
+ }
2006
+ });
2007
+ } catch (error) {
2008
+ options.debug && console.error(error);
2009
+ throw error;
2010
+ }
2011
+ };
2012
+
2013
+ export default BoolFactory;