@bool-ts/core 1.7.16 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierrc +1 -1
- package/__test/controller.ts +1 -1
- package/__test/index.ts +4 -1
- package/__test/module.ts +3 -1
- package/__test/tsconfig.json +109 -0
- package/__test/webSocket.ts +37 -0
- package/__test/webSocketClient.ts +23 -0
- package/dist/decorators/controller.d.ts +3 -3
- package/dist/decorators/controller.js +1 -2
- package/dist/decorators/dispatcher.d.ts +1 -1
- package/dist/decorators/http.d.ts +12 -12
- package/dist/decorators/http.js +1 -1
- package/dist/decorators/index.d.ts +5 -0
- package/dist/decorators/index.js +3 -0
- package/dist/decorators/module.d.ts +3 -1
- package/dist/decorators/module.js +9 -2
- package/dist/decorators/webSocket.d.ts +25 -0
- package/dist/decorators/webSocket.js +40 -0
- package/dist/decorators/webSocketArguments.d.ts +22 -0
- package/dist/decorators/webSocketArguments.js +49 -0
- package/dist/decorators/webSocketEvent.d.ts +15 -0
- package/dist/decorators/webSocketEvent.js +24 -0
- package/dist/decorators/zodSchema.js +3 -3
- package/dist/entities/{route.d.ts → httpRoute.d.ts} +12 -12
- package/dist/entities/{route.js → httpRoute.js} +27 -25
- package/dist/entities/httpRouter.d.ts +10 -0
- package/dist/entities/{router.js → httpRouter.js} +7 -5
- package/dist/entities/{routerGroup.d.ts → httpRouterGroup.d.ts} +4 -4
- package/dist/entities/{routerGroup.js → httpRouterGroup.js} +1 -1
- package/dist/entities/index.d.ts +7 -4
- package/dist/entities/index.js +6 -3
- package/dist/entities/webSocketRoute.d.ts +10 -0
- package/dist/entities/webSocketRoute.js +15 -0
- package/dist/entities/webSocketRouter.d.ts +31 -0
- package/dist/entities/webSocketRouter.js +54 -0
- package/dist/entities/webSocketRouterGroup.d.ts +25 -0
- package/dist/entities/webSocketRouterGroup.js +51 -0
- package/dist/hooks/factory.d.ts +1 -39
- package/dist/hooks/factory.js +450 -76
- package/dist/hooks/injector.js +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/interfaces/index.d.ts +1 -0
- package/dist/interfaces/webSocket.d.ts +2 -0
- package/dist/interfaces/webSocket.js +1 -0
- package/dist/keys/index.d.ts +10 -1
- package/dist/keys/index.js +21 -12
- package/dist/ultils/colors.d.ts +30 -0
- package/dist/ultils/colors.js +41 -0
- package/dist/ultils/index.d.ts +2 -0
- package/dist/ultils/index.js +2 -0
- package/dist/ultils/socket.d.ts +1 -0
- package/dist/ultils/socket.js +7 -0
- package/package.json +8 -7
- package/src/decorators/controller.ts +5 -4
- package/src/decorators/dispatcher.ts +2 -1
- package/src/decorators/guard.ts +1 -0
- package/src/decorators/http.ts +3 -3
- package/src/decorators/index.ts +10 -0
- package/src/decorators/middleware.ts +1 -0
- package/src/decorators/module.ts +14 -3
- package/src/decorators/webSocket.ts +81 -0
- package/src/decorators/webSocketArguments.ts +144 -0
- package/src/decorators/webSocketEvent.ts +56 -0
- package/src/decorators/zodSchema.ts +5 -3
- package/src/entities/{route.ts → httpRoute.ts} +71 -57
- package/src/entities/{router.ts → httpRouter.ts} +8 -6
- package/src/entities/{routerGroup.ts → httpRouterGroup.ts} +4 -4
- package/src/entities/index.ts +7 -4
- package/src/entities/webSocketRoute.ts +27 -0
- package/src/entities/webSocketRouter.ts +64 -0
- package/src/entities/webSocketRouterGroup.ts +64 -0
- package/src/hooks/factory.ts +704 -112
- package/src/hooks/injector.ts +2 -2
- package/src/index.ts +1 -1
- package/src/interfaces/index.ts +1 -0
- package/src/interfaces/webSocket.ts +1 -0
- package/src/keys/index.ts +22 -12
- package/src/ultils/colors.ts +56 -0
- package/src/ultils/index.ts +3 -1
- package/src/ultils/socket.ts +9 -0
- package/test.ts +0 -0
- package/tsconfig.json +3 -2
- package/bun.lockb +0 -0
- package/dist/entities/router.d.ts +0 -10
package/src/hooks/factory.ts
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
TArgumentsMetadata,
|
|
3
|
+
TControllerMetadata,
|
|
4
|
+
THttpMetadata,
|
|
5
|
+
TModuleMetadata,
|
|
6
|
+
TWebSocketEventHandlerMetadata,
|
|
7
|
+
TWebSocketMetadata
|
|
8
|
+
} from "../decorators";
|
|
9
|
+
import type { TWebSocketUpgradeData } from "../decorators/webSocket";
|
|
2
10
|
import type { IContext, IGuard, IMiddleware } from "../interfaces";
|
|
3
11
|
import type { IDispatcher } from "../interfaces/dispatcher";
|
|
4
12
|
|
|
5
|
-
import "colors";
|
|
6
13
|
import "reflect-metadata";
|
|
7
14
|
|
|
8
15
|
import Qs from "qs";
|
|
9
16
|
import * as Zod from "zod";
|
|
10
17
|
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
18
|
+
import { ETimeUnit, add as TimeAdd } from "@bool-ts/date-time";
|
|
19
|
+
import type { BunFile, Server } from "bun";
|
|
20
|
+
import {
|
|
21
|
+
HttpRouter,
|
|
22
|
+
HttpRouterGroup,
|
|
23
|
+
WebSocketRoute,
|
|
24
|
+
WebSocketRouter,
|
|
25
|
+
WebSocketRouterGroup
|
|
26
|
+
} from "../entities";
|
|
13
27
|
import { HttpClientError, HttpServerError, jsonErrorInfer, type THttpMethods } from "../http";
|
|
14
28
|
import {
|
|
15
29
|
argumentsKey,
|
|
@@ -27,8 +41,15 @@ import {
|
|
|
27
41
|
requestHeadersArgsKey,
|
|
28
42
|
responseBodyArgsKey,
|
|
29
43
|
responseHeadersArgsKey,
|
|
30
|
-
routeModelArgsKey
|
|
44
|
+
routeModelArgsKey,
|
|
45
|
+
webSocketCloseCodeArgsKey,
|
|
46
|
+
webSocketCloseReasonArgsKey,
|
|
47
|
+
webSocketConnectionArgsKey,
|
|
48
|
+
webSocketKey,
|
|
49
|
+
webSocketMessageArgsKey,
|
|
50
|
+
webSocketServerArgsKey
|
|
31
51
|
} from "../keys";
|
|
52
|
+
import { ansiText, isWebSocketUpgrade } from "../ultils";
|
|
32
53
|
import { Injector } from "./injector";
|
|
33
54
|
|
|
34
55
|
export type TGroupElementModel<
|
|
@@ -57,6 +78,7 @@ export type TBoolFactoryOptions = Required<{
|
|
|
57
78
|
}> &
|
|
58
79
|
Partial<{
|
|
59
80
|
headers: Record<string, string>;
|
|
81
|
+
cacheTimeInSeconds: number;
|
|
60
82
|
}>;
|
|
61
83
|
cors: Partial<{
|
|
62
84
|
credentials: boolean;
|
|
@@ -66,18 +88,25 @@ export type TBoolFactoryOptions = Required<{
|
|
|
66
88
|
}>;
|
|
67
89
|
}>;
|
|
68
90
|
|
|
69
|
-
|
|
91
|
+
const DEFAULT_STATIC_CACHE_TIME_IN_SECONDS = 900;
|
|
92
|
+
|
|
93
|
+
const responseConverter = (response: Response) => {
|
|
70
94
|
response.headers.set("X-Powered-By", "Bool Typescript");
|
|
71
95
|
|
|
72
96
|
return response;
|
|
73
97
|
};
|
|
74
98
|
|
|
75
|
-
|
|
76
|
-
controllerConstructor
|
|
77
|
-
|
|
78
|
-
injector
|
|
79
|
-
prefix
|
|
80
|
-
|
|
99
|
+
const controllerCreator = ({
|
|
100
|
+
controllerConstructor,
|
|
101
|
+
httpRouterGroup,
|
|
102
|
+
injector,
|
|
103
|
+
prefix
|
|
104
|
+
}: Readonly<{
|
|
105
|
+
controllerConstructor: new (...args: any[]) => unknown;
|
|
106
|
+
httpRouterGroup: HttpRouterGroup;
|
|
107
|
+
injector: Injector;
|
|
108
|
+
prefix?: string;
|
|
109
|
+
}>) => {
|
|
81
110
|
if (!Reflect.getOwnMetadataKeys(controllerConstructor).includes(controllerKey)) {
|
|
82
111
|
throw Error(`${controllerConstructor.name} is not a controller.`);
|
|
83
112
|
}
|
|
@@ -88,12 +117,16 @@ export const controllerCreator = (
|
|
|
88
117
|
throw Error("Can not initialize controller.");
|
|
89
118
|
}
|
|
90
119
|
|
|
91
|
-
const controllerMetadata: TControllerMetadata = Reflect.getOwnMetadata(
|
|
120
|
+
const controllerMetadata: TControllerMetadata = Reflect.getOwnMetadata(
|
|
121
|
+
controllerKey,
|
|
122
|
+
controllerConstructor
|
|
123
|
+
) || {
|
|
92
124
|
prefix: "/",
|
|
93
125
|
httpMetadata: []
|
|
94
126
|
};
|
|
95
|
-
const routesMetadata = (Reflect.getOwnMetadata(controllerHttpKey, controllerConstructor) ||
|
|
96
|
-
|
|
127
|
+
const routesMetadata = (Reflect.getOwnMetadata(controllerHttpKey, controllerConstructor) ||
|
|
128
|
+
[]) as THttpMetadata;
|
|
129
|
+
const router = new HttpRouter(`/${prefix || ""}/${controllerMetadata.prefix}`);
|
|
97
130
|
|
|
98
131
|
routesMetadata.forEach((routeMetadata) => {
|
|
99
132
|
if (typeof routeMetadata.descriptor.value !== "function") {
|
|
@@ -124,10 +157,98 @@ export const controllerCreator = (
|
|
|
124
157
|
}
|
|
125
158
|
});
|
|
126
159
|
|
|
127
|
-
return
|
|
160
|
+
return httpRouterGroup.add(router);
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const webSocketCreator = ({
|
|
164
|
+
injector,
|
|
165
|
+
httpRouterGroup,
|
|
166
|
+
prefix,
|
|
167
|
+
webSocketRouterGroup,
|
|
168
|
+
webSocketConstructor
|
|
169
|
+
}: Readonly<{
|
|
170
|
+
webSocketConstructor: new (...args: any[]) => unknown;
|
|
171
|
+
httpRouterGroup: HttpRouterGroup;
|
|
172
|
+
webSocketRouterGroup: WebSocketRouterGroup;
|
|
173
|
+
injector: Injector;
|
|
174
|
+
prefix?: string;
|
|
175
|
+
}>): Readonly<{
|
|
176
|
+
httpRouterGroup: HttpRouterGroup;
|
|
177
|
+
webSocketRouterGroup: WebSocketRouterGroup;
|
|
178
|
+
}> => {
|
|
179
|
+
if (!Reflect.getOwnMetadataKeys(webSocketConstructor).includes(webSocketKey)) {
|
|
180
|
+
throw Error(`${webSocketConstructor.name} is not a controller.`);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const webSocket = injector.get(webSocketConstructor);
|
|
184
|
+
|
|
185
|
+
if (!webSocket) {
|
|
186
|
+
throw Error("Can not initialize webSocket.");
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const webSocketMetadata: TWebSocketMetadata = Reflect.getOwnMetadata(
|
|
190
|
+
webSocketKey,
|
|
191
|
+
webSocketConstructor
|
|
192
|
+
) || {
|
|
193
|
+
prefix: "/",
|
|
194
|
+
events: [],
|
|
195
|
+
http: []
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const fullPrefix = `/${prefix || ""}/${webSocketMetadata.prefix}`;
|
|
199
|
+
|
|
200
|
+
//#region [HTTP ROUTER]
|
|
201
|
+
const router = new HttpRouter(fullPrefix);
|
|
202
|
+
|
|
203
|
+
for (const [_key, httpMetadata] of Object.entries(webSocketMetadata.http)) {
|
|
204
|
+
if (typeof httpMetadata.descriptor?.value !== "function") {
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const route = router.route(httpMetadata.path);
|
|
209
|
+
const handler = httpMetadata.descriptor.value.bind(webSocket);
|
|
210
|
+
const routeArgument = Object.freeze({
|
|
211
|
+
class: webSocketConstructor,
|
|
212
|
+
funcName: httpMetadata.methodName,
|
|
213
|
+
func: handler
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
switch (httpMetadata.httpMethod) {
|
|
217
|
+
case "GET":
|
|
218
|
+
route.get(routeArgument);
|
|
219
|
+
break;
|
|
220
|
+
case "POST":
|
|
221
|
+
route.post(routeArgument);
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
httpRouterGroup.add(router);
|
|
227
|
+
//#endregion
|
|
228
|
+
|
|
229
|
+
//#region [WEBSOCKET ROUTER]
|
|
230
|
+
const webSocketRouter = new WebSocketRouter(fullPrefix);
|
|
231
|
+
|
|
232
|
+
for (const [key, event] of Object.entries(webSocketMetadata.events)) {
|
|
233
|
+
const webSocketRoute = new WebSocketRoute({
|
|
234
|
+
eventName: key,
|
|
235
|
+
metadata: event
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
webSocketRouter.addRoutes(webSocketRoute);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
webSocketRouter.bind(webSocket);
|
|
242
|
+
webSocketRouterGroup.addRouters(webSocketRouter);
|
|
243
|
+
//#endregion
|
|
244
|
+
|
|
245
|
+
return Object.freeze({
|
|
246
|
+
httpRouterGroup: httpRouterGroup,
|
|
247
|
+
webSocketRouterGroup: webSocketRouterGroup
|
|
248
|
+
});
|
|
128
249
|
};
|
|
129
250
|
|
|
130
|
-
|
|
251
|
+
const argumentsResolution = async (
|
|
131
252
|
data: unknown,
|
|
132
253
|
zodSchema: Zod.Schema,
|
|
133
254
|
argumentIndex: number,
|
|
@@ -166,7 +287,10 @@ export const argumentsResolution = async (
|
|
|
166
287
|
}
|
|
167
288
|
};
|
|
168
289
|
|
|
169
|
-
|
|
290
|
+
const moduleResolution = async (
|
|
291
|
+
module: new (...args: any[]) => unknown,
|
|
292
|
+
options: TBoolFactoryOptions
|
|
293
|
+
) => {
|
|
170
294
|
if (!Reflect.getOwnMetadataKeys(module).includes(moduleKey)) {
|
|
171
295
|
throw Error(`${module.name} is not a module.`);
|
|
172
296
|
}
|
|
@@ -185,11 +309,14 @@ export const moduleResolution = async (module: new (...args: any[]) => unknown,
|
|
|
185
309
|
dispatchers,
|
|
186
310
|
controllers,
|
|
187
311
|
dependencies,
|
|
312
|
+
webSockets,
|
|
188
313
|
prefix: modulePrefix,
|
|
189
314
|
config: moduleConfig
|
|
190
315
|
} = moduleMetadata;
|
|
191
316
|
|
|
192
|
-
|
|
317
|
+
const fullPrefix = `${options.prefix || ""}/${modulePrefix || ""}`;
|
|
318
|
+
|
|
319
|
+
//#region [Configuration(s)]
|
|
193
320
|
const { config } = Object.freeze({
|
|
194
321
|
config: {
|
|
195
322
|
...(typeof options.config !== "function" ? options.config : await options.config()),
|
|
@@ -200,10 +327,13 @@ export const moduleResolution = async (module: new (...args: any[]) => unknown,
|
|
|
200
327
|
: await moduleConfig())
|
|
201
328
|
}
|
|
202
329
|
});
|
|
330
|
+
//#endregion
|
|
203
331
|
|
|
204
|
-
|
|
332
|
+
//#region [Register config like an injection]
|
|
205
333
|
injector.set(configKey, config);
|
|
334
|
+
//#endregion
|
|
206
335
|
|
|
336
|
+
//#region [Run loader(s)]
|
|
207
337
|
if (loaders) {
|
|
208
338
|
const loaderFunctions = [];
|
|
209
339
|
|
|
@@ -211,10 +341,24 @@ export const moduleResolution = async (module: new (...args: any[]) => unknown,
|
|
|
211
341
|
loaderFunctions.push(async () => {
|
|
212
342
|
try {
|
|
213
343
|
const result = await func({ config });
|
|
214
|
-
|
|
344
|
+
|
|
345
|
+
console.info(
|
|
346
|
+
`${ansiText(" INFO ", {
|
|
347
|
+
color: "white",
|
|
348
|
+
backgroundColor: "blue",
|
|
349
|
+
bold: true
|
|
350
|
+
})} Loader [${key}] initialized successfully.`
|
|
351
|
+
);
|
|
352
|
+
|
|
215
353
|
return result;
|
|
216
354
|
} catch (error) {
|
|
217
|
-
console.error(
|
|
355
|
+
console.error(
|
|
356
|
+
`${ansiText(" WARN ", {
|
|
357
|
+
color: "yellow",
|
|
358
|
+
backgroundColor: "red",
|
|
359
|
+
bold: true
|
|
360
|
+
})} Loader [${key}] initialization failed.`
|
|
361
|
+
);
|
|
218
362
|
options.debug && console.error(error);
|
|
219
363
|
throw error;
|
|
220
364
|
}
|
|
@@ -228,22 +372,28 @@ export const moduleResolution = async (module: new (...args: any[]) => unknown,
|
|
|
228
372
|
injector.set(key, value);
|
|
229
373
|
}
|
|
230
374
|
}
|
|
375
|
+
//#endregion
|
|
231
376
|
|
|
232
|
-
|
|
377
|
+
//#region [Dependencies]
|
|
233
378
|
!dependencies || dependencies.map((dependency) => injector.get(dependency));
|
|
379
|
+
//#endregion
|
|
234
380
|
|
|
235
|
-
|
|
236
|
-
const startMiddlewareGroup: Array<
|
|
237
|
-
|
|
381
|
+
//#region [Middleware(s)]
|
|
382
|
+
const startMiddlewareGroup: Array<
|
|
383
|
+
TGroupElementModel<"start", IMiddleware, NonNullable<IMiddleware["start"]>>
|
|
384
|
+
> = [];
|
|
385
|
+
const endMiddlewareGroup: Array<
|
|
386
|
+
TGroupElementModel<"end", IMiddleware, NonNullable<IMiddleware["end"]>>
|
|
387
|
+
> = [];
|
|
238
388
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
const instance = injector.get<IMiddleware>(
|
|
389
|
+
middlewares &&
|
|
390
|
+
middlewares.forEach((middleware) => {
|
|
391
|
+
const instance = injector.get<IMiddleware>(middleware);
|
|
242
392
|
|
|
243
393
|
if (instance.start && typeof instance.start === "function") {
|
|
244
394
|
startMiddlewareGroup.push(
|
|
245
395
|
Object.freeze({
|
|
246
|
-
class:
|
|
396
|
+
class: middleware as IMiddleware,
|
|
247
397
|
funcName: "start",
|
|
248
398
|
func: instance.start.bind(instance)
|
|
249
399
|
})
|
|
@@ -253,16 +403,16 @@ export const moduleResolution = async (module: new (...args: any[]) => unknown,
|
|
|
253
403
|
if (instance.end && typeof instance.end === "function") {
|
|
254
404
|
endMiddlewareGroup.push(
|
|
255
405
|
Object.freeze({
|
|
256
|
-
class:
|
|
406
|
+
class: middleware as IMiddleware,
|
|
257
407
|
funcName: "end",
|
|
258
408
|
func: instance.end.bind(instance)
|
|
259
409
|
})
|
|
260
410
|
);
|
|
261
411
|
}
|
|
262
|
-
}
|
|
263
|
-
|
|
412
|
+
});
|
|
413
|
+
//#endregion
|
|
264
414
|
|
|
265
|
-
|
|
415
|
+
//#region [Guard(s)]
|
|
266
416
|
const guardGroup = !guards
|
|
267
417
|
? []
|
|
268
418
|
: guards.map((guard) => {
|
|
@@ -274,19 +424,24 @@ export const moduleResolution = async (module: new (...args: any[]) => unknown,
|
|
|
274
424
|
func: guardInstance.enforce.bind(guardInstance)
|
|
275
425
|
});
|
|
276
426
|
});
|
|
427
|
+
//#endregion
|
|
277
428
|
|
|
278
|
-
|
|
279
|
-
const openDispatcherGroup: Array<
|
|
280
|
-
|
|
429
|
+
//#region [Before dispatcher(s)]
|
|
430
|
+
const openDispatcherGroup: Array<
|
|
431
|
+
TGroupElementModel<"open", IDispatcher, NonNullable<IDispatcher["open"]>>
|
|
432
|
+
> = [];
|
|
433
|
+
const closeDispatcherGroup: Array<
|
|
434
|
+
TGroupElementModel<"close", IDispatcher, NonNullable<IDispatcher["close"]>>
|
|
435
|
+
> = [];
|
|
281
436
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
const instance = injector.get<IDispatcher>(
|
|
437
|
+
dispatchers &&
|
|
438
|
+
dispatchers.forEach((dispatcher) => {
|
|
439
|
+
const instance = injector.get<IDispatcher>(dispatcher);
|
|
285
440
|
|
|
286
441
|
if (instance.open && typeof instance.open === "function") {
|
|
287
442
|
openDispatcherGroup.push(
|
|
288
443
|
Object.freeze({
|
|
289
|
-
class:
|
|
444
|
+
class: dispatcher as IDispatcher,
|
|
290
445
|
funcName: "open",
|
|
291
446
|
func: instance.open.bind(instance)
|
|
292
447
|
})
|
|
@@ -296,22 +451,44 @@ export const moduleResolution = async (module: new (...args: any[]) => unknown,
|
|
|
296
451
|
if (instance.close && typeof instance.close === "function") {
|
|
297
452
|
closeDispatcherGroup.push(
|
|
298
453
|
Object.freeze({
|
|
299
|
-
class:
|
|
454
|
+
class: dispatcher as IDispatcher,
|
|
300
455
|
funcName: "close",
|
|
301
456
|
func: instance.close.bind(instance)
|
|
302
457
|
})
|
|
303
458
|
);
|
|
304
459
|
}
|
|
305
|
-
}
|
|
306
|
-
|
|
460
|
+
});
|
|
461
|
+
//#endregion
|
|
307
462
|
|
|
308
|
-
|
|
309
|
-
const
|
|
463
|
+
//#region [Controller(s)]
|
|
464
|
+
const controllerRouterGroup = new HttpRouterGroup();
|
|
310
465
|
|
|
311
466
|
controllers &&
|
|
312
|
-
controllers.
|
|
313
|
-
controllerCreator(
|
|
467
|
+
controllers.forEach((controllerConstructor) =>
|
|
468
|
+
controllerCreator({
|
|
469
|
+
controllerConstructor,
|
|
470
|
+
httpRouterGroup: controllerRouterGroup,
|
|
471
|
+
injector: injector,
|
|
472
|
+
prefix: fullPrefix
|
|
473
|
+
})
|
|
474
|
+
);
|
|
475
|
+
//#endregion
|
|
476
|
+
|
|
477
|
+
//#region [WebSocket(s)]
|
|
478
|
+
const webSocketHttpRouterGroup = new HttpRouterGroup();
|
|
479
|
+
const webSocketRouterGroup = new WebSocketRouterGroup();
|
|
480
|
+
|
|
481
|
+
webSockets &&
|
|
482
|
+
webSockets.forEach((webSocket) =>
|
|
483
|
+
webSocketCreator({
|
|
484
|
+
webSocketConstructor: webSocket,
|
|
485
|
+
httpRouterGroup: webSocketHttpRouterGroup,
|
|
486
|
+
webSocketRouterGroup: webSocketRouterGroup,
|
|
487
|
+
injector,
|
|
488
|
+
prefix: fullPrefix
|
|
489
|
+
})
|
|
314
490
|
);
|
|
491
|
+
//#endregion
|
|
315
492
|
|
|
316
493
|
return Object.freeze({
|
|
317
494
|
prefix: moduleMetadata.prefix,
|
|
@@ -321,11 +498,13 @@ export const moduleResolution = async (module: new (...args: any[]) => unknown,
|
|
|
321
498
|
guardGroup,
|
|
322
499
|
openDispatcherGroup,
|
|
323
500
|
closeDispatcherGroup,
|
|
324
|
-
|
|
501
|
+
controllerRouterGroup,
|
|
502
|
+
webSocketHttpRouterGroup,
|
|
503
|
+
webSocketRouterGroup
|
|
325
504
|
});
|
|
326
505
|
};
|
|
327
506
|
|
|
328
|
-
const
|
|
507
|
+
const webSocketFetcher = async (
|
|
329
508
|
bun: Required<{
|
|
330
509
|
request: Request;
|
|
331
510
|
server: Server;
|
|
@@ -333,17 +512,82 @@ const fetcher = async (
|
|
|
333
512
|
bool: Required<{
|
|
334
513
|
responseHeaders: Headers;
|
|
335
514
|
query: Record<string, unknown>;
|
|
336
|
-
route: NonNullable<ReturnType<
|
|
515
|
+
route: NonNullable<ReturnType<HttpRouterGroup["find"]>>;
|
|
337
516
|
moduleResolution: NonNullable<Awaited<ReturnType<typeof moduleResolution>>>;
|
|
338
517
|
}>
|
|
339
518
|
) => {
|
|
519
|
+
const { request, server } = bun;
|
|
340
520
|
const {
|
|
341
521
|
query,
|
|
342
522
|
responseHeaders,
|
|
343
|
-
route: {
|
|
344
|
-
moduleResolution: { startMiddlewareGroup, endMiddlewareGroup, guardGroup, openDispatcherGroup, closeDispatcherGroup }
|
|
523
|
+
route: { model }
|
|
345
524
|
} = bool;
|
|
525
|
+
|
|
526
|
+
// Execute controller action
|
|
527
|
+
const isUpgrade = await model.func(...[server, request, query]);
|
|
528
|
+
|
|
529
|
+
if (typeof isUpgrade !== "boolean") {
|
|
530
|
+
return responseConverter(
|
|
531
|
+
new Response(
|
|
532
|
+
JSON.stringify({
|
|
533
|
+
httpCode: 500,
|
|
534
|
+
message: "Can not detect webSocket upgrade result.",
|
|
535
|
+
data: undefined
|
|
536
|
+
}),
|
|
537
|
+
{
|
|
538
|
+
status: 500,
|
|
539
|
+
statusText: "Internal server error.",
|
|
540
|
+
headers: responseHeaders
|
|
541
|
+
}
|
|
542
|
+
)
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
if (!isUpgrade) {
|
|
547
|
+
return responseConverter(
|
|
548
|
+
new Response(
|
|
549
|
+
JSON.stringify({
|
|
550
|
+
httpCode: 500,
|
|
551
|
+
message: "Can not upgrade.",
|
|
552
|
+
data: undefined
|
|
553
|
+
}),
|
|
554
|
+
{
|
|
555
|
+
status: 500,
|
|
556
|
+
statusText: "Internal server error.",
|
|
557
|
+
headers: responseHeaders
|
|
558
|
+
}
|
|
559
|
+
)
|
|
560
|
+
);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
return isUpgrade;
|
|
564
|
+
};
|
|
565
|
+
|
|
566
|
+
const httpFetcher = async (
|
|
567
|
+
bun: Required<{
|
|
568
|
+
request: Request;
|
|
569
|
+
server: Server;
|
|
570
|
+
}>,
|
|
571
|
+
bool: Required<{
|
|
572
|
+
responseHeaders: Headers;
|
|
573
|
+
query: Record<string, unknown>;
|
|
574
|
+
route: NonNullable<ReturnType<HttpRouterGroup["find"]>>;
|
|
575
|
+
moduleResolution: NonNullable<Awaited<ReturnType<typeof moduleResolution>>>;
|
|
576
|
+
}>
|
|
577
|
+
) => {
|
|
346
578
|
const { request, server: _server } = bun;
|
|
579
|
+
const {
|
|
580
|
+
query,
|
|
581
|
+
responseHeaders,
|
|
582
|
+
route: { parameters, model },
|
|
583
|
+
moduleResolution: {
|
|
584
|
+
startMiddlewareGroup,
|
|
585
|
+
endMiddlewareGroup,
|
|
586
|
+
guardGroup,
|
|
587
|
+
openDispatcherGroup,
|
|
588
|
+
closeDispatcherGroup
|
|
589
|
+
}
|
|
590
|
+
} = bool;
|
|
347
591
|
|
|
348
592
|
const context: Record<symbol, any> = {
|
|
349
593
|
[requestHeadersArgsKey]: request.headers,
|
|
@@ -397,7 +641,9 @@ const fetcher = async (
|
|
|
397
641
|
);
|
|
398
642
|
break;
|
|
399
643
|
case contextArgsKey:
|
|
400
|
-
args[argsMetadata.index] = !argsMetadata.key
|
|
644
|
+
args[argsMetadata.index] = !argsMetadata.key
|
|
645
|
+
? contextHook
|
|
646
|
+
: contextHook.get(argsMetadata.key);
|
|
401
647
|
break;
|
|
402
648
|
case requestHeadersArgsKey:
|
|
403
649
|
args[argsMetadata.index] = !argsMetadata.zodSchema
|
|
@@ -441,7 +687,9 @@ const fetcher = async (
|
|
|
441
687
|
? undefined
|
|
442
688
|
: context[argsMetadata.type]
|
|
443
689
|
: await argumentsResolution(
|
|
444
|
-
!(argsMetadata.type in context)
|
|
690
|
+
!(argsMetadata.type in context)
|
|
691
|
+
? undefined
|
|
692
|
+
: context[argsMetadata.type],
|
|
445
693
|
argsMetadata.zodSchema,
|
|
446
694
|
argsMetadata.index,
|
|
447
695
|
collection.funcName
|
|
@@ -489,7 +737,9 @@ const fetcher = async (
|
|
|
489
737
|
);
|
|
490
738
|
break;
|
|
491
739
|
case contextArgsKey:
|
|
492
|
-
args[argsMetadata.index] = !argsMetadata.key
|
|
740
|
+
args[argsMetadata.index] = !argsMetadata.key
|
|
741
|
+
? contextHook
|
|
742
|
+
: contextHook.get(argsMetadata.key);
|
|
493
743
|
break;
|
|
494
744
|
case requestHeadersArgsKey:
|
|
495
745
|
args[argsMetadata.index] = !argsMetadata.zodSchema
|
|
@@ -583,7 +833,9 @@ const fetcher = async (
|
|
|
583
833
|
);
|
|
584
834
|
break;
|
|
585
835
|
case contextArgsKey:
|
|
586
|
-
args[argsMetadata.index] = !argsMetadata.key
|
|
836
|
+
args[argsMetadata.index] = !argsMetadata.key
|
|
837
|
+
? contextHook
|
|
838
|
+
: contextHook.get(argsMetadata.key);
|
|
587
839
|
break;
|
|
588
840
|
case requestHeadersArgsKey:
|
|
589
841
|
args[argsMetadata.index] = !argsMetadata.zodSchema
|
|
@@ -642,7 +894,11 @@ const fetcher = async (
|
|
|
642
894
|
const controllerActionArguments: any[] = [];
|
|
643
895
|
const controllerActionCollection = model;
|
|
644
896
|
const controllerActionMetadata: Record<string, TArgumentsMetadata> =
|
|
645
|
-
Reflect.getOwnMetadata(
|
|
897
|
+
Reflect.getOwnMetadata(
|
|
898
|
+
argumentsKey,
|
|
899
|
+
controllerActionCollection.class,
|
|
900
|
+
controllerActionCollection.funcName
|
|
901
|
+
) || {};
|
|
646
902
|
|
|
647
903
|
if (controllerActionMetadata) {
|
|
648
904
|
for (const [_key, argsMetadata] of Object.entries(controllerActionMetadata)) {
|
|
@@ -722,7 +978,9 @@ const fetcher = async (
|
|
|
722
978
|
}
|
|
723
979
|
}
|
|
724
980
|
|
|
725
|
-
context[responseBodyArgsKey] = await controllerActionCollection.func(
|
|
981
|
+
context[responseBodyArgsKey] = await controllerActionCollection.func(
|
|
982
|
+
...controllerActionArguments
|
|
983
|
+
);
|
|
726
984
|
|
|
727
985
|
// Execute close dispatcher(s)
|
|
728
986
|
for (let i = 0; i < closeDispatcherGroup.length; i++) {
|
|
@@ -755,7 +1013,9 @@ const fetcher = async (
|
|
|
755
1013
|
);
|
|
756
1014
|
break;
|
|
757
1015
|
case contextArgsKey:
|
|
758
|
-
args[argsMetadata.index] = !argsMetadata.key
|
|
1016
|
+
args[argsMetadata.index] = !argsMetadata.key
|
|
1017
|
+
? contextHook
|
|
1018
|
+
: contextHook.get(argsMetadata.key);
|
|
759
1019
|
break;
|
|
760
1020
|
case requestHeadersArgsKey:
|
|
761
1021
|
args[argsMetadata.index] = !argsMetadata.zodSchema
|
|
@@ -845,7 +1105,9 @@ const fetcher = async (
|
|
|
845
1105
|
);
|
|
846
1106
|
break;
|
|
847
1107
|
case contextArgsKey:
|
|
848
|
-
args[argsMetadata.index] = !argsMetadata.key
|
|
1108
|
+
args[argsMetadata.index] = !argsMetadata.key
|
|
1109
|
+
? contextHook
|
|
1110
|
+
: contextHook.get(argsMetadata.key);
|
|
849
1111
|
break;
|
|
850
1112
|
case requestHeadersArgsKey:
|
|
851
1113
|
args[argsMetadata.index] = !argsMetadata.zodSchema
|
|
@@ -889,7 +1151,9 @@ const fetcher = async (
|
|
|
889
1151
|
? undefined
|
|
890
1152
|
: context[argsMetadata.type]
|
|
891
1153
|
: await argumentsResolution(
|
|
892
|
-
!(argsMetadata.type in context)
|
|
1154
|
+
!(argsMetadata.type in context)
|
|
1155
|
+
? undefined
|
|
1156
|
+
: context[argsMetadata.type],
|
|
893
1157
|
argsMetadata.zodSchema,
|
|
894
1158
|
argsMetadata.index,
|
|
895
1159
|
collection.funcName
|
|
@@ -924,10 +1188,29 @@ const fetcher = async (
|
|
|
924
1188
|
);
|
|
925
1189
|
};
|
|
926
1190
|
|
|
927
|
-
export const BoolFactory = async (
|
|
1191
|
+
export const BoolFactory = async (
|
|
1192
|
+
modules: Object | Array<Object>,
|
|
1193
|
+
options: TBoolFactoryOptions
|
|
1194
|
+
) => {
|
|
928
1195
|
try {
|
|
1196
|
+
const staticMap: Map<
|
|
1197
|
+
string,
|
|
1198
|
+
Readonly<{
|
|
1199
|
+
expiredAt: Date;
|
|
1200
|
+
file: BunFile;
|
|
1201
|
+
}>
|
|
1202
|
+
> = new Map();
|
|
1203
|
+
|
|
929
1204
|
const modulesConverted = !Array.isArray(modules) ? [modules] : modules;
|
|
930
|
-
|
|
1205
|
+
|
|
1206
|
+
const {
|
|
1207
|
+
allowLogsMethods,
|
|
1208
|
+
staticOption,
|
|
1209
|
+
allowOrigins,
|
|
1210
|
+
allowMethods,
|
|
1211
|
+
allowCredentials,
|
|
1212
|
+
allowHeaders
|
|
1213
|
+
} = Object.freeze({
|
|
931
1214
|
allowLogsMethods: options?.log?.methods,
|
|
932
1215
|
staticOption: options.static,
|
|
933
1216
|
allowOrigins: !options.cors?.origins
|
|
@@ -937,9 +1220,19 @@ export const BoolFactory = async (modules: Object | Array<Object>, options: TBoo
|
|
|
937
1220
|
? ["*"]
|
|
938
1221
|
: options.cors.origins
|
|
939
1222
|
: [options.cors.origins !== "*" ? options.cors.origins : "*"],
|
|
940
|
-
allowMethods: options.cors?.methods || [
|
|
1223
|
+
allowMethods: options.cors?.methods || [
|
|
1224
|
+
"GET",
|
|
1225
|
+
"POST",
|
|
1226
|
+
"PUT",
|
|
1227
|
+
"PATCH",
|
|
1228
|
+
"DELETE",
|
|
1229
|
+
"OPTIONS"
|
|
1230
|
+
],
|
|
941
1231
|
allowCredentials: !options.cors?.credentials ? false : true,
|
|
942
|
-
allowHeaders:
|
|
1232
|
+
allowHeaders:
|
|
1233
|
+
!options.cors?.headers || options.cors.headers.includes("*")
|
|
1234
|
+
? ["*"]
|
|
1235
|
+
: options.cors.headers
|
|
943
1236
|
});
|
|
944
1237
|
|
|
945
1238
|
const moduleResolutions = await Promise.all(
|
|
@@ -951,14 +1244,28 @@ export const BoolFactory = async (modules: Object | Array<Object>, options: TBoo
|
|
|
951
1244
|
);
|
|
952
1245
|
|
|
953
1246
|
const prefixs = [
|
|
954
|
-
...new Set(
|
|
1247
|
+
...new Set(
|
|
1248
|
+
availableModuleResolutions.map(
|
|
1249
|
+
(availableModuleResolution) => availableModuleResolution.prefix
|
|
1250
|
+
)
|
|
1251
|
+
)
|
|
955
1252
|
];
|
|
956
1253
|
|
|
957
1254
|
if (prefixs.length !== availableModuleResolutions.length) {
|
|
958
|
-
throw Error(
|
|
1255
|
+
throw Error("Module prefix should be unique.");
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
const webSocketsMap = new Map<string, TWebSocketEventHandlerMetadata>();
|
|
1259
|
+
|
|
1260
|
+
for (const availableModuleResolution of availableModuleResolutions) {
|
|
1261
|
+
const webSocketMap = availableModuleResolution.webSocketRouterGroup.execute();
|
|
1262
|
+
|
|
1263
|
+
for (const [key, metadata] of webSocketMap.entries()) {
|
|
1264
|
+
webSocketsMap.set(key, metadata);
|
|
1265
|
+
}
|
|
959
1266
|
}
|
|
960
1267
|
|
|
961
|
-
Bun.serve({
|
|
1268
|
+
const server = Bun.serve<TWebSocketUpgradeData>({
|
|
962
1269
|
port: options.port,
|
|
963
1270
|
fetch: async (request, server) => {
|
|
964
1271
|
const start = performance.now();
|
|
@@ -969,13 +1276,77 @@ export const BoolFactory = async (modules: Object | Array<Object>, options: TBoo
|
|
|
969
1276
|
const responseHeaders = new Headers();
|
|
970
1277
|
|
|
971
1278
|
try {
|
|
972
|
-
|
|
1279
|
+
const isUpgradable = isWebSocketUpgrade(request);
|
|
1280
|
+
|
|
1281
|
+
let collection:
|
|
1282
|
+
| undefined
|
|
1283
|
+
| Required<{
|
|
1284
|
+
route: NonNullable<ReturnType<HttpRouterGroup["find"]>>;
|
|
1285
|
+
resolution: NonNullable<Awaited<ReturnType<typeof moduleResolution>>>;
|
|
1286
|
+
}>;
|
|
1287
|
+
|
|
1288
|
+
if (isUpgradable) {
|
|
1289
|
+
for (const availableModuleResolution of availableModuleResolutions) {
|
|
1290
|
+
const routeResult =
|
|
1291
|
+
availableModuleResolution.webSocketHttpRouterGroup.find(
|
|
1292
|
+
url.pathname,
|
|
1293
|
+
request.method as keyof THttpMethods
|
|
1294
|
+
);
|
|
1295
|
+
|
|
1296
|
+
if (routeResult) {
|
|
1297
|
+
collection = Object.freeze({
|
|
1298
|
+
route: routeResult,
|
|
1299
|
+
resolution: availableModuleResolution
|
|
1300
|
+
});
|
|
1301
|
+
break;
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
if (!collection) {
|
|
1306
|
+
return responseConverter(
|
|
1307
|
+
new Response(
|
|
1308
|
+
JSON.stringify({
|
|
1309
|
+
httpCode: 404,
|
|
1310
|
+
message: "Route not found",
|
|
1311
|
+
data: undefined
|
|
1312
|
+
}),
|
|
1313
|
+
{
|
|
1314
|
+
status: 404,
|
|
1315
|
+
statusText: "Not found.",
|
|
1316
|
+
headers: responseHeaders
|
|
1317
|
+
}
|
|
1318
|
+
)
|
|
1319
|
+
);
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
const upgradeResult = await webSocketFetcher(
|
|
1323
|
+
{
|
|
1324
|
+
request,
|
|
1325
|
+
server
|
|
1326
|
+
},
|
|
1327
|
+
{
|
|
1328
|
+
query: query,
|
|
1329
|
+
responseHeaders: responseHeaders,
|
|
1330
|
+
route: collection.route,
|
|
1331
|
+
moduleResolution: collection.resolution
|
|
1332
|
+
}
|
|
1333
|
+
);
|
|
1334
|
+
|
|
1335
|
+
return upgradeResult instanceof Response ? upgradeResult : undefined;
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
allowCredentials &&
|
|
1339
|
+
responseHeaders.set("Access-Control-Allow-Credentials", "true");
|
|
973
1340
|
|
|
974
1341
|
responseHeaders.set("Access-Control-Allow-Methods", allowMethods.join(", "));
|
|
975
1342
|
responseHeaders.set("Access-Control-Allow-Headers", allowHeaders.join(", "));
|
|
976
1343
|
responseHeaders.set(
|
|
977
1344
|
"Access-Control-Allow-Origin",
|
|
978
|
-
allowOrigins.includes("*")
|
|
1345
|
+
allowOrigins.includes("*")
|
|
1346
|
+
? "*"
|
|
1347
|
+
: !allowOrigins.includes(origin)
|
|
1348
|
+
? allowOrigins[0]
|
|
1349
|
+
: origin
|
|
979
1350
|
);
|
|
980
1351
|
|
|
981
1352
|
if (!allowMethods.includes(method)) {
|
|
@@ -1005,37 +1376,77 @@ export const BoolFactory = async (modules: Object | Array<Object>, options: TBoo
|
|
|
1005
1376
|
}
|
|
1006
1377
|
|
|
1007
1378
|
if (staticOption) {
|
|
1008
|
-
const
|
|
1009
|
-
const
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1379
|
+
const { path, headers, cacheTimeInSeconds } = staticOption;
|
|
1380
|
+
const pathname = `${path}/${url.pathname}`;
|
|
1381
|
+
const cachedFile = staticMap.get(pathname);
|
|
1382
|
+
|
|
1383
|
+
if (!cachedFile) {
|
|
1384
|
+
const file = Bun.file(pathname);
|
|
1385
|
+
const isFileExists = await file.exists();
|
|
1386
|
+
|
|
1387
|
+
if (isFileExists) {
|
|
1388
|
+
if (headers) {
|
|
1389
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
1390
|
+
responseHeaders.set(key, value);
|
|
1391
|
+
}
|
|
1015
1392
|
}
|
|
1393
|
+
|
|
1394
|
+
responseHeaders.set("Content-Type", file.type);
|
|
1395
|
+
|
|
1396
|
+
return responseConverter(
|
|
1397
|
+
new Response(await file.arrayBuffer(), {
|
|
1398
|
+
status: 200,
|
|
1399
|
+
statusText: "SUCCESS",
|
|
1400
|
+
headers: responseHeaders
|
|
1401
|
+
})
|
|
1402
|
+
);
|
|
1016
1403
|
}
|
|
1404
|
+
} else {
|
|
1405
|
+
const isExpired = new Date() > cachedFile.expiredAt;
|
|
1017
1406
|
|
|
1018
|
-
|
|
1407
|
+
if (isExpired) {
|
|
1408
|
+
staticMap.delete(pathname);
|
|
1409
|
+
}
|
|
1019
1410
|
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1411
|
+
const file = !isExpired ? cachedFile.file : Bun.file(pathname);
|
|
1412
|
+
const isFileExists = await file.exists();
|
|
1413
|
+
|
|
1414
|
+
if (isFileExists) {
|
|
1415
|
+
staticMap.set(
|
|
1416
|
+
pathname,
|
|
1417
|
+
Object.freeze({
|
|
1418
|
+
expiredAt: TimeAdd(
|
|
1419
|
+
new Date(),
|
|
1420
|
+
typeof cacheTimeInSeconds !== "number"
|
|
1421
|
+
? DEFAULT_STATIC_CACHE_TIME_IN_SECONDS
|
|
1422
|
+
: cacheTimeInSeconds,
|
|
1423
|
+
ETimeUnit.seconds
|
|
1424
|
+
),
|
|
1425
|
+
file: file
|
|
1426
|
+
})
|
|
1427
|
+
);
|
|
1428
|
+
|
|
1429
|
+
if (headers) {
|
|
1430
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
1431
|
+
responseHeaders.set(key, value);
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
responseHeaders.set("Content-Type", file.type);
|
|
1436
|
+
|
|
1437
|
+
return responseConverter(
|
|
1438
|
+
new Response(await file.arrayBuffer(), {
|
|
1439
|
+
status: 200,
|
|
1440
|
+
statusText: "SUCCESS",
|
|
1441
|
+
headers: responseHeaders
|
|
1442
|
+
})
|
|
1443
|
+
);
|
|
1444
|
+
}
|
|
1027
1445
|
}
|
|
1028
1446
|
}
|
|
1029
1447
|
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
| Required<{
|
|
1033
|
-
route: NonNullable<ReturnType<RouterGroup["find"]>>;
|
|
1034
|
-
resolution: NonNullable<Awaited<ReturnType<typeof moduleResolution>>>;
|
|
1035
|
-
}>;
|
|
1036
|
-
|
|
1037
|
-
for (let i = 0; i < availableModuleResolutions.length; i++) {
|
|
1038
|
-
const routeResult = availableModuleResolutions[i].routerGroup.find(
|
|
1448
|
+
for (const availableModuleResolution of availableModuleResolutions) {
|
|
1449
|
+
const routeResult = availableModuleResolution.controllerRouterGroup.find(
|
|
1039
1450
|
url.pathname,
|
|
1040
1451
|
request.method as keyof THttpMethods
|
|
1041
1452
|
);
|
|
@@ -1043,7 +1454,7 @@ export const BoolFactory = async (modules: Object | Array<Object>, options: TBoo
|
|
|
1043
1454
|
if (routeResult) {
|
|
1044
1455
|
collection = Object.freeze({
|
|
1045
1456
|
route: routeResult,
|
|
1046
|
-
resolution:
|
|
1457
|
+
resolution: availableModuleResolution
|
|
1047
1458
|
});
|
|
1048
1459
|
break;
|
|
1049
1460
|
}
|
|
@@ -1056,12 +1467,17 @@ export const BoolFactory = async (modules: Object | Array<Object>, options: TBoo
|
|
|
1056
1467
|
httpCode: 404,
|
|
1057
1468
|
message: "Route not found",
|
|
1058
1469
|
data: undefined
|
|
1059
|
-
})
|
|
1470
|
+
}),
|
|
1471
|
+
{
|
|
1472
|
+
status: 404,
|
|
1473
|
+
statusText: "Not found.",
|
|
1474
|
+
headers: responseHeaders
|
|
1475
|
+
}
|
|
1060
1476
|
)
|
|
1061
1477
|
);
|
|
1062
1478
|
}
|
|
1063
1479
|
|
|
1064
|
-
return await
|
|
1480
|
+
return await httpFetcher(
|
|
1065
1481
|
{
|
|
1066
1482
|
request,
|
|
1067
1483
|
server
|
|
@@ -1080,24 +1496,200 @@ export const BoolFactory = async (modules: Object | Array<Object>, options: TBoo
|
|
|
1080
1496
|
} finally {
|
|
1081
1497
|
if (allowLogsMethods) {
|
|
1082
1498
|
const end = performance.now();
|
|
1083
|
-
const
|
|
1084
|
-
const
|
|
1085
|
-
const
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1499
|
+
const pathname = ansiText(url.pathname, { color: "blue" });
|
|
1500
|
+
const convertedPID = `${Bun.color("yellow", "ansi")}${process.pid}`;
|
|
1501
|
+
const convertedMethod = ansiText(request.method, {
|
|
1502
|
+
color: "yellow",
|
|
1503
|
+
backgroundColor: "blue"
|
|
1504
|
+
});
|
|
1505
|
+
const convertedReqIp = ansiText(
|
|
1506
|
+
`${
|
|
1507
|
+
request.headers.get("x-forwarded-for") ||
|
|
1508
|
+
request.headers.get("x-real-ip") ||
|
|
1509
|
+
server.requestIP(request)?.address ||
|
|
1510
|
+
"<Unknown>"
|
|
1511
|
+
}`,
|
|
1512
|
+
{
|
|
1513
|
+
color: "yellow"
|
|
1514
|
+
}
|
|
1515
|
+
);
|
|
1516
|
+
const convertedTime = ansiText(
|
|
1517
|
+
`${Math.round((end - start + Number.EPSILON) * 10 ** 2) / 10 ** 2}ms`,
|
|
1518
|
+
{
|
|
1519
|
+
color: "yellow",
|
|
1520
|
+
backgroundColor: "blue"
|
|
1521
|
+
}
|
|
1522
|
+
);
|
|
1523
|
+
|
|
1524
|
+
allowLogsMethods.includes(
|
|
1525
|
+
request.method.toUpperCase() as (typeof allowLogsMethods)[number]
|
|
1526
|
+
) &&
|
|
1094
1527
|
console.info(
|
|
1095
|
-
`PID: ${convertedPID} - Method: ${convertedMethod} - IP: ${convertedReqIp} - ${
|
|
1096
|
-
new URL(request.url).pathname.blue
|
|
1097
|
-
} - Time: ${convertedTime}`
|
|
1528
|
+
`PID: ${convertedPID} - Method: ${convertedMethod} - IP: ${convertedReqIp} - ${pathname} - Time: ${convertedTime}`
|
|
1098
1529
|
);
|
|
1099
1530
|
}
|
|
1100
1531
|
}
|
|
1532
|
+
},
|
|
1533
|
+
websocket: {
|
|
1534
|
+
open: (connection) => {
|
|
1535
|
+
const pathnameKey = `${connection.data.pathname}:::open`;
|
|
1536
|
+
const handlerMetadata = webSocketsMap.get(pathnameKey);
|
|
1537
|
+
|
|
1538
|
+
if (!handlerMetadata) {
|
|
1539
|
+
return;
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
const argumentsMetadata = handlerMetadata.arguments || {};
|
|
1543
|
+
const args: Array<unknown> = [];
|
|
1544
|
+
|
|
1545
|
+
for (const [_key, argumentMetadata] of Object.entries(argumentsMetadata)) {
|
|
1546
|
+
switch (argumentMetadata.type) {
|
|
1547
|
+
case webSocketConnectionArgsKey:
|
|
1548
|
+
args[argumentMetadata.index] = connection;
|
|
1549
|
+
break;
|
|
1550
|
+
case webSocketServerArgsKey:
|
|
1551
|
+
args[argumentMetadata.index] = server;
|
|
1552
|
+
break;
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
handlerMetadata.descriptor.value(...args);
|
|
1557
|
+
},
|
|
1558
|
+
close: (connection, code: number, reason: string) => {
|
|
1559
|
+
const pathnameKey = `${connection.data.pathname}:::close`;
|
|
1560
|
+
const handlerMetadata = webSocketsMap.get(pathnameKey);
|
|
1561
|
+
|
|
1562
|
+
if (!handlerMetadata) {
|
|
1563
|
+
return;
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
const argumentsMetadata = handlerMetadata.arguments || {};
|
|
1567
|
+
const args: Array<unknown> = [];
|
|
1568
|
+
|
|
1569
|
+
for (const [_key, argumentMetadata] of Object.entries(argumentsMetadata)) {
|
|
1570
|
+
switch (argumentMetadata.type) {
|
|
1571
|
+
case webSocketConnectionArgsKey:
|
|
1572
|
+
args[argumentMetadata.index] = connection;
|
|
1573
|
+
break;
|
|
1574
|
+
case webSocketServerArgsKey:
|
|
1575
|
+
args[argumentMetadata.index] = server;
|
|
1576
|
+
break;
|
|
1577
|
+
case webSocketCloseCodeArgsKey:
|
|
1578
|
+
args[argumentMetadata.index] = code;
|
|
1579
|
+
break;
|
|
1580
|
+
case webSocketCloseReasonArgsKey:
|
|
1581
|
+
args[argumentMetadata.index] = reason;
|
|
1582
|
+
break;
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
handlerMetadata.descriptor.value(...args);
|
|
1587
|
+
},
|
|
1588
|
+
message: (connection, message) => {
|
|
1589
|
+
const pathnameKey = `${connection.data.pathname}:::message`;
|
|
1590
|
+
const handlerMetadata = webSocketsMap.get(pathnameKey);
|
|
1591
|
+
|
|
1592
|
+
if (!handlerMetadata) {
|
|
1593
|
+
return;
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
const argumentsMetadata = handlerMetadata.arguments || {};
|
|
1597
|
+
const args: Array<unknown> = [];
|
|
1598
|
+
|
|
1599
|
+
for (const [_key, argumentMetadata] of Object.entries(argumentsMetadata)) {
|
|
1600
|
+
switch (argumentMetadata.type) {
|
|
1601
|
+
case webSocketConnectionArgsKey:
|
|
1602
|
+
args[argumentMetadata.index] = connection;
|
|
1603
|
+
break;
|
|
1604
|
+
case webSocketMessageArgsKey:
|
|
1605
|
+
args[argumentMetadata.index] = message;
|
|
1606
|
+
break;
|
|
1607
|
+
case webSocketServerArgsKey:
|
|
1608
|
+
args[argumentMetadata.index] = server;
|
|
1609
|
+
break;
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
handlerMetadata.descriptor.value(...args);
|
|
1614
|
+
},
|
|
1615
|
+
drain: (connection) => {
|
|
1616
|
+
const pathnameKey = `${connection.data.pathname}:::drain`;
|
|
1617
|
+
const handlerMetadata = webSocketsMap.get(pathnameKey);
|
|
1618
|
+
|
|
1619
|
+
if (!handlerMetadata) {
|
|
1620
|
+
return;
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
const argumentsMetadata = handlerMetadata.arguments || {};
|
|
1624
|
+
const args: Array<unknown> = [];
|
|
1625
|
+
|
|
1626
|
+
for (const [_key, argumentMetadata] of Object.entries(argumentsMetadata)) {
|
|
1627
|
+
switch (argumentMetadata.type) {
|
|
1628
|
+
case webSocketConnectionArgsKey:
|
|
1629
|
+
args[argumentMetadata.index] = connection;
|
|
1630
|
+
break;
|
|
1631
|
+
case webSocketServerArgsKey:
|
|
1632
|
+
args[argumentMetadata.index] = server;
|
|
1633
|
+
break;
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
handlerMetadata.descriptor.value(...args);
|
|
1638
|
+
},
|
|
1639
|
+
ping: (connection, data) => {
|
|
1640
|
+
const pathnameKey = `${connection.data.pathname}:::ping`;
|
|
1641
|
+
const handlerMetadata = webSocketsMap.get(pathnameKey);
|
|
1642
|
+
|
|
1643
|
+
if (!handlerMetadata) {
|
|
1644
|
+
return;
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
const argumentsMetadata = handlerMetadata.arguments || {};
|
|
1648
|
+
const args: Array<unknown> = [];
|
|
1649
|
+
|
|
1650
|
+
for (const [_key, argumentMetadata] of Object.entries(argumentsMetadata)) {
|
|
1651
|
+
switch (argumentMetadata.type) {
|
|
1652
|
+
case webSocketConnectionArgsKey:
|
|
1653
|
+
args[argumentMetadata.index] = connection;
|
|
1654
|
+
break;
|
|
1655
|
+
case webSocketServerArgsKey:
|
|
1656
|
+
args[argumentMetadata.index] = server;
|
|
1657
|
+
break;
|
|
1658
|
+
case webSocketMessageArgsKey:
|
|
1659
|
+
args[argumentMetadata.index] = data;
|
|
1660
|
+
break;
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
handlerMetadata.descriptor.value(...args);
|
|
1665
|
+
},
|
|
1666
|
+
pong: (connection, data) => {
|
|
1667
|
+
const pathnameKey = `${connection.data.pathname}:::pong`;
|
|
1668
|
+
const handlerMetadata = webSocketsMap.get(pathnameKey);
|
|
1669
|
+
|
|
1670
|
+
if (!handlerMetadata) {
|
|
1671
|
+
return;
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1674
|
+
const argumentsMetadata = handlerMetadata.arguments || {};
|
|
1675
|
+
const args: Array<unknown> = [];
|
|
1676
|
+
|
|
1677
|
+
for (const [_key, argumentMetadata] of Object.entries(argumentsMetadata)) {
|
|
1678
|
+
switch (argumentMetadata.type) {
|
|
1679
|
+
case webSocketConnectionArgsKey:
|
|
1680
|
+
args[argumentMetadata.index] = connection;
|
|
1681
|
+
break;
|
|
1682
|
+
case webSocketServerArgsKey:
|
|
1683
|
+
args[argumentMetadata.index] = server;
|
|
1684
|
+
break;
|
|
1685
|
+
case webSocketMessageArgsKey:
|
|
1686
|
+
args[argumentMetadata.index] = data;
|
|
1687
|
+
break;
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
handlerMetadata.descriptor.value(...args);
|
|
1692
|
+
}
|
|
1101
1693
|
}
|
|
1102
1694
|
});
|
|
1103
1695
|
} catch (error) {
|