@bool-ts/core 2.1.3 → 2.2.1
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/README.md +1 -1
- package/dist/entities/application.d.ts +5 -4
- package/dist/entities/httpRoute.d.ts +46 -29
- package/dist/entities/httpRouter.d.ts +3 -1
- package/dist/entities/httpRouterGroup.d.ts +9 -5
- package/dist/http/clientError.d.ts +3 -3
- package/dist/http/index.d.ts +3 -11
- package/dist/http/serverError.d.ts +2 -2
- package/dist/index.js +6 -6
- package/dist/index.js.map +10 -10
- package/package.json +1 -1
- package/src/entities/application.ts +125 -84
- package/src/entities/httpRoute.ts +73 -166
- package/src/entities/httpRouter.ts +2 -4
- package/src/entities/httpRouterGroup.ts +16 -6
- package/src/http/clientError.ts +6 -3
- package/src/http/index.ts +26 -11
- package/src/http/serverError.ts +6 -3
package/package.json
CHANGED
|
@@ -7,13 +7,20 @@ import type {
|
|
|
7
7
|
TWebSocketEventHandlerMetadata,
|
|
8
8
|
TWebSocketMetadata
|
|
9
9
|
} from "../decorators";
|
|
10
|
-
import {
|
|
10
|
+
import type { THttpMethods } from "../http";
|
|
11
11
|
import type { IGuard, IInterceptor, IMiddleware } from "../interfaces";
|
|
12
|
+
import type { ICustomValidator } from "../interfaces/customValidator";
|
|
12
13
|
import type { TConstructor } from "../ultils";
|
|
13
14
|
|
|
14
15
|
import { ETimeUnit, add as TimeAdd } from "@bool-ts/date-time";
|
|
15
16
|
import { parse as QsParse } from "qs";
|
|
16
|
-
import
|
|
17
|
+
import {
|
|
18
|
+
HttpClientError,
|
|
19
|
+
httpMethods,
|
|
20
|
+
httpMethodsStandardization,
|
|
21
|
+
HttpServerError,
|
|
22
|
+
jsonErrorInfer
|
|
23
|
+
} from "../http";
|
|
17
24
|
import {
|
|
18
25
|
argumentsKey,
|
|
19
26
|
configKey,
|
|
@@ -46,38 +53,39 @@ import { Context } from "./context";
|
|
|
46
53
|
import { HttpRouter } from "./httpRouter";
|
|
47
54
|
import { HttpRouterGroup } from "./httpRouterGroup";
|
|
48
55
|
import { Injector } from "./injector";
|
|
49
|
-
import ValidationFailed from "./validationFailed";
|
|
56
|
+
import { ValidationFailed } from "./validationFailed";
|
|
50
57
|
import { WebSocketRoute } from "./webSocketRoute";
|
|
51
58
|
import { WebSocketRouter } from "./webSocketRouter";
|
|
52
59
|
import { WebSocketRouterGroup } from "./webSocketRouterGroup";
|
|
53
60
|
|
|
54
61
|
type TParamsType = Record<string, string>;
|
|
55
62
|
|
|
56
|
-
type TApplicationOptions =
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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>;
|
|
73
87
|
}>;
|
|
74
|
-
cors: Partial<{
|
|
75
|
-
credentials: boolean;
|
|
76
|
-
origins: string | Array<string>;
|
|
77
|
-
methods: Array<"GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS">;
|
|
78
|
-
headers: Array<string>;
|
|
79
88
|
}>;
|
|
80
|
-
}>;
|
|
81
89
|
|
|
82
90
|
type TGroupElementModel<
|
|
83
91
|
TFuncName extends keyof TClass,
|
|
@@ -99,10 +107,10 @@ type TStaticMap = Map<
|
|
|
99
107
|
>;
|
|
100
108
|
|
|
101
109
|
type TResolutedOptions = Readonly<{
|
|
102
|
-
allowLogsMethods:
|
|
103
|
-
allowOrigins: string
|
|
104
|
-
allowMethods:
|
|
105
|
-
allowHeaders: string
|
|
110
|
+
allowLogsMethods: Array<THttpMethods>;
|
|
111
|
+
allowOrigins: Array<string>;
|
|
112
|
+
allowMethods: Array<THttpMethods>;
|
|
113
|
+
allowHeaders: Array<string>;
|
|
106
114
|
allowCredentials: boolean;
|
|
107
115
|
staticOption?: Required<{
|
|
108
116
|
path: string;
|
|
@@ -133,7 +141,7 @@ type TValidator = undefined | ICustomValidator;
|
|
|
133
141
|
|
|
134
142
|
export class Application<TRootClass extends Object = Object> {
|
|
135
143
|
#preLaunchData: TPreLaunch;
|
|
136
|
-
#inputedConstructorKeys: any
|
|
144
|
+
#inputedConstructorKeys: Array<any>;
|
|
137
145
|
#injector = new Injector();
|
|
138
146
|
#staticMap: TStaticMap = new Map();
|
|
139
147
|
#resolutedOptions: TResolutedOptions;
|
|
@@ -170,14 +178,7 @@ export class Application<TRootClass extends Object = Object> {
|
|
|
170
178
|
? ["*"]
|
|
171
179
|
: this.options.cors.origins
|
|
172
180
|
: [this.options.cors.origins !== "*" ? this.options.cors.origins : "*"],
|
|
173
|
-
allowMethods: this.options.cors?.methods ||
|
|
174
|
-
"GET",
|
|
175
|
-
"POST",
|
|
176
|
-
"PUT",
|
|
177
|
-
"PATCH",
|
|
178
|
-
"DELETE",
|
|
179
|
-
"OPTIONS"
|
|
180
|
-
],
|
|
181
|
+
allowMethods: this.options.cors?.methods || httpMethods,
|
|
181
182
|
allowCredentials: !this.options.cors?.credentials ? false : true,
|
|
182
183
|
allowHeaders:
|
|
183
184
|
!this.options.cors?.headers || this.options.cors.headers.includes("*")
|
|
@@ -299,6 +300,25 @@ export class Application<TRootClass extends Object = Object> {
|
|
|
299
300
|
.set(queryArgsKey, query);
|
|
300
301
|
|
|
301
302
|
try {
|
|
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
|
+
}
|
|
321
|
+
|
|
302
322
|
const isUpgradable = isWebSocketUpgrade(request);
|
|
303
323
|
|
|
304
324
|
let collection:
|
|
@@ -313,10 +333,10 @@ export class Application<TRootClass extends Object = Object> {
|
|
|
313
333
|
if (isUpgradable) {
|
|
314
334
|
for (const availableModuleResolution of resolutedModules) {
|
|
315
335
|
const routeResult =
|
|
316
|
-
availableModuleResolution.webSocketHttpRouterGroup.find(
|
|
317
|
-
url.pathname,
|
|
318
|
-
|
|
319
|
-
);
|
|
336
|
+
availableModuleResolution.webSocketHttpRouterGroup.find({
|
|
337
|
+
pathname: url.pathname,
|
|
338
|
+
method: method
|
|
339
|
+
});
|
|
320
340
|
|
|
321
341
|
if (routeResult) {
|
|
322
342
|
collection = Object.freeze({
|
|
@@ -475,9 +495,25 @@ export class Application<TRootClass extends Object = Object> {
|
|
|
475
495
|
}
|
|
476
496
|
}
|
|
477
497
|
|
|
498
|
+
for (const availableModuleResolution of resolutedModules) {
|
|
499
|
+
const routeResult = availableModuleResolution.controllerRouterGroup.find({
|
|
500
|
+
pathname: url.pathname,
|
|
501
|
+
method: method
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
if (routeResult) {
|
|
505
|
+
collection = Object.freeze({
|
|
506
|
+
route: routeResult,
|
|
507
|
+
resolution: availableModuleResolution
|
|
508
|
+
});
|
|
509
|
+
break;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
478
513
|
if (resolutedContainer) {
|
|
479
514
|
const { context: newContext } = await this.httpFetcher({
|
|
480
515
|
context: context,
|
|
516
|
+
route: collection?.route,
|
|
481
517
|
resolutedMap: {
|
|
482
518
|
injector: resolutedContainer.injector,
|
|
483
519
|
startMiddlewareGroup: resolutedContainer.startMiddlewareGroup,
|
|
@@ -491,21 +527,6 @@ export class Application<TRootClass extends Object = Object> {
|
|
|
491
527
|
context = newContext;
|
|
492
528
|
}
|
|
493
529
|
|
|
494
|
-
for (const availableModuleResolution of resolutedModules) {
|
|
495
|
-
const routeResult = availableModuleResolution.controllerRouterGroup.find(
|
|
496
|
-
url.pathname,
|
|
497
|
-
method as keyof THttpMethods
|
|
498
|
-
);
|
|
499
|
-
|
|
500
|
-
if (routeResult) {
|
|
501
|
-
collection = Object.freeze({
|
|
502
|
-
route: routeResult,
|
|
503
|
-
resolution: availableModuleResolution
|
|
504
|
-
});
|
|
505
|
-
break;
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
|
|
509
530
|
if (!collection) {
|
|
510
531
|
context
|
|
511
532
|
.setOptions({ isStatic: false })
|
|
@@ -554,14 +575,16 @@ export class Application<TRootClass extends Object = Object> {
|
|
|
554
575
|
latestResponseStatus = context.get<unknown>(responseStatusArgsKey, {
|
|
555
576
|
isStatic: false
|
|
556
577
|
}),
|
|
557
|
-
latestResponseStatusText = context.get<unknown>(
|
|
578
|
+
latestResponseStatusText = context.get<unknown>(responseStatusTextArgsKey, {
|
|
558
579
|
isStatic: false
|
|
559
580
|
});
|
|
560
581
|
|
|
561
582
|
return this.serializeResponse({
|
|
562
583
|
status:
|
|
563
584
|
typeof latestResponseStatus !== "number"
|
|
564
|
-
?
|
|
585
|
+
? method === "POST"
|
|
586
|
+
? 201
|
|
587
|
+
: undefined
|
|
565
588
|
: latestResponseStatus,
|
|
566
589
|
statusText:
|
|
567
590
|
typeof latestResponseStatusText !== "string"
|
|
@@ -1304,7 +1327,9 @@ export class Application<TRootClass extends Object = Object> {
|
|
|
1304
1327
|
httpMetadata: []
|
|
1305
1328
|
};
|
|
1306
1329
|
|
|
1307
|
-
const router = new HttpRouter(
|
|
1330
|
+
const router = new HttpRouter({
|
|
1331
|
+
alias: `/${prefix || ""}/${controllerMetadata.prefix}`
|
|
1332
|
+
});
|
|
1308
1333
|
|
|
1309
1334
|
controllerMetadata.httpMetadata.forEach((routeMetadata) => {
|
|
1310
1335
|
if (typeof routeMetadata.descriptor.value !== "function") {
|
|
@@ -1313,7 +1338,7 @@ export class Application<TRootClass extends Object = Object> {
|
|
|
1313
1338
|
|
|
1314
1339
|
const route = router.route(routeMetadata.path);
|
|
1315
1340
|
const handler = routeMetadata.descriptor.value.bind(controller);
|
|
1316
|
-
const
|
|
1341
|
+
const httpRouteModel = Object.freeze({
|
|
1317
1342
|
class: controllerConstructor,
|
|
1318
1343
|
funcName: routeMetadata.methodName,
|
|
1319
1344
|
func: handler,
|
|
@@ -1322,17 +1347,17 @@ export class Application<TRootClass extends Object = Object> {
|
|
|
1322
1347
|
|
|
1323
1348
|
switch (routeMetadata.httpMethod) {
|
|
1324
1349
|
case "GET":
|
|
1325
|
-
return route.get(
|
|
1350
|
+
return route.get({ model: httpRouteModel });
|
|
1326
1351
|
case "POST":
|
|
1327
|
-
return route.post(
|
|
1352
|
+
return route.post({ model: httpRouteModel });
|
|
1328
1353
|
case "PUT":
|
|
1329
|
-
return route.put(
|
|
1354
|
+
return route.put({ model: httpRouteModel });
|
|
1330
1355
|
case "PATCH":
|
|
1331
|
-
return route.patch(
|
|
1356
|
+
return route.patch({ model: httpRouteModel });
|
|
1332
1357
|
case "DELETE":
|
|
1333
|
-
return route.delete(
|
|
1358
|
+
return route.delete({ model: httpRouteModel });
|
|
1334
1359
|
case "OPTIONS":
|
|
1335
|
-
return route.options(
|
|
1360
|
+
return route.options({ model: httpRouteModel });
|
|
1336
1361
|
}
|
|
1337
1362
|
});
|
|
1338
1363
|
|
|
@@ -1382,7 +1407,9 @@ export class Application<TRootClass extends Object = Object> {
|
|
|
1382
1407
|
const fullPrefix = `/${prefix || ""}/${webSocketMetadata.prefix}`;
|
|
1383
1408
|
|
|
1384
1409
|
//#region [HTTP ROUTER]
|
|
1385
|
-
const router = new HttpRouter(
|
|
1410
|
+
const router = new HttpRouter({
|
|
1411
|
+
alias: fullPrefix
|
|
1412
|
+
});
|
|
1386
1413
|
|
|
1387
1414
|
for (const [_key, httpMetadata] of Object.entries(webSocketMetadata.http)) {
|
|
1388
1415
|
if (typeof httpMetadata.descriptor?.value !== "function") {
|
|
@@ -1391,7 +1418,7 @@ export class Application<TRootClass extends Object = Object> {
|
|
|
1391
1418
|
|
|
1392
1419
|
const route = router.route(httpMetadata.path);
|
|
1393
1420
|
const handler = httpMetadata.descriptor.value.bind(webSocket);
|
|
1394
|
-
const
|
|
1421
|
+
const httpRouteModel = Object.freeze({
|
|
1395
1422
|
class: webSocketConstructor,
|
|
1396
1423
|
funcName: httpMetadata.methodName,
|
|
1397
1424
|
func: handler,
|
|
@@ -1400,10 +1427,10 @@ export class Application<TRootClass extends Object = Object> {
|
|
|
1400
1427
|
|
|
1401
1428
|
switch (httpMetadata.httpMethod) {
|
|
1402
1429
|
case "GET":
|
|
1403
|
-
route.get(
|
|
1430
|
+
route.get({ model: httpRouteModel });
|
|
1404
1431
|
break;
|
|
1405
1432
|
case "POST":
|
|
1406
|
-
route.post(
|
|
1433
|
+
route.post({ model: httpRouteModel });
|
|
1407
1434
|
break;
|
|
1408
1435
|
}
|
|
1409
1436
|
}
|
|
@@ -1453,21 +1480,31 @@ export class Application<TRootClass extends Object = Object> {
|
|
|
1453
1480
|
|
|
1454
1481
|
if (contentType.includes("application/json")) {
|
|
1455
1482
|
return this.finalizeResponse(
|
|
1456
|
-
new Response(
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
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
|
+
)
|
|
1461
1495
|
);
|
|
1462
1496
|
}
|
|
1463
1497
|
|
|
1464
1498
|
if (contentType.includes("text/plain") || contentType.includes("text/html")) {
|
|
1465
1499
|
return this.finalizeResponse(
|
|
1466
|
-
new Response(
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1500
|
+
new Response(
|
|
1501
|
+
!data ? undefined : data instanceof ReadableStream ? data : String(data),
|
|
1502
|
+
{
|
|
1503
|
+
status: !data ? 204 : status,
|
|
1504
|
+
statusText: statusText,
|
|
1505
|
+
headers: headers
|
|
1506
|
+
}
|
|
1507
|
+
)
|
|
1471
1508
|
);
|
|
1472
1509
|
}
|
|
1473
1510
|
|
|
@@ -1501,7 +1538,11 @@ export class Application<TRootClass extends Object = Object> {
|
|
|
1501
1538
|
}
|
|
1502
1539
|
|
|
1503
1540
|
return this.finalizeResponse(
|
|
1504
|
-
new Response(
|
|
1541
|
+
new Response(!data ? undefined : String(data), {
|
|
1542
|
+
status: !data ? 204 : status,
|
|
1543
|
+
statusText: statusText,
|
|
1544
|
+
headers: headers
|
|
1545
|
+
})
|
|
1505
1546
|
);
|
|
1506
1547
|
}
|
|
1507
1548
|
|
|
@@ -1541,7 +1582,7 @@ export class Application<TRootClass extends Object = Object> {
|
|
|
1541
1582
|
}>;
|
|
1542
1583
|
}>) {
|
|
1543
1584
|
const contextOptions = { isStatic: true };
|
|
1544
|
-
const context = (!outerContext ?
|
|
1585
|
+
const context = new Context(...(!outerContext ? [] : [outerContext])).setOptions(
|
|
1545
1586
|
contextOptions
|
|
1546
1587
|
);
|
|
1547
1588
|
|