@bool-ts/core 1.9.1 → 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.
- package/__test/_constants.ts +1 -0
- package/__test/container.ts +28 -0
- package/__test/controller.ts +1 -1
- package/__test/{module.ts → firstModule.ts} +4 -6
- package/__test/index.ts +2 -4
- package/__test/secondModule.ts +29 -0
- package/__test/tsconfig.json +1 -1
- package/dist/decorators/arguments.d.ts +5 -1
- package/dist/decorators/container.d.ts +10 -10
- package/dist/decorators/index.d.ts +4 -2
- package/dist/decorators/module.d.ts +6 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5 -5
- package/dist/interfaces/context.d.ts +8 -2
- package/dist/interfaces/index.d.ts +1 -1
- package/dist/keys/index.d.ts +2 -0
- package/dist/producers/context.d.ts +13 -0
- package/dist/{hooks → producers}/factory.d.ts +3 -2
- package/dist/{hooks → producers}/injector.d.ts +7 -1
- package/package.json +3 -3
- package/src/decorators/arguments.ts +27 -0
- package/src/decorators/container.ts +45 -30
- package/src/decorators/index.ts +4 -1
- package/src/decorators/module.ts +16 -2
- package/src/index.ts +1 -1
- package/src/interfaces/context.ts +9 -2
- package/src/interfaces/index.ts +1 -1
- package/src/keys/index.ts +2 -0
- package/src/producers/context.ts +63 -0
- package/src/producers/factory.ts +2013 -0
- package/src/{hooks → producers}/injector.ts +41 -6
- package/src/hooks/factory.ts +0 -1703
- /package/dist/{hooks → producers}/index.d.ts +0 -0
- /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;
|