@bool-ts/core 1.9.1 → 1.9.3

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