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