@bool-ts/core 1.0.11 → 1.1.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/LICENSE +21 -21
- package/__test/controller.ts +63 -63
- package/__test/index.ts +11 -11
- package/__test/interfaces.ts +7 -7
- package/__test/module.ts +17 -17
- package/__test/repository.ts +16 -16
- package/__test/service.ts +20 -20
- package/bun.lockb +0 -0
- package/dist/hooks/factory.d.ts +11 -1
- package/dist/hooks/factory.js +12 -14
- package/dist/http/clientError.d.ts +40 -0
- package/dist/http/clientError.js +42 -0
- package/dist/http/index.d.ts +4 -0
- package/dist/http/index.js +58 -0
- package/dist/http/serverError.d.ts +22 -0
- package/dist/http/serverError.js +24 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +2 -2
- package/src/decorators/controller.ts +18 -18
- package/src/decorators/http.ts +185 -185
- package/src/decorators/index.ts +5 -5
- package/src/decorators/inject.ts +19 -19
- package/src/decorators/injectable.ts +12 -12
- package/src/decorators/module.ts +21 -21
- package/src/hooks/factory.ts +193 -181
- package/src/hooks/index.ts +2 -2
- package/src/hooks/injector.ts +43 -43
- package/src/http/clientError.ts +57 -0
- package/src/http/index.ts +68 -0
- package/src/http/serverError.ts +39 -0
- package/src/index.ts +6 -5
- package/src/interfaces/index.ts +3 -3
- package/test.http +28 -28
- package/tsconfig.json +108 -108
package/src/hooks/factory.ts
CHANGED
|
@@ -1,181 +1,193 @@
|
|
|
1
|
-
import "reflect-metadata";
|
|
2
|
-
import "colors";
|
|
3
|
-
|
|
4
|
-
import * as Qs from "qs";
|
|
5
|
-
import * as ResponseTime from "response-time";
|
|
6
|
-
|
|
7
|
-
import { type IControllerRoute, type TModuleOptions, controllerKey, controllerRoutesKey, moduleKey } from "../decorators";
|
|
8
|
-
import { default as ExpressApp, Router, json, urlencoded, Request, Response, NextFunction, Errback } from "express";
|
|
9
|
-
import { Injector } from "./injector";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
type: "application/
|
|
110
|
-
verify: undefined
|
|
111
|
-
}),
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
},
|
|
120
|
-
//
|
|
121
|
-
(req: Request, res: Response, next: NextFunction) => {
|
|
122
|
-
|
|
123
|
-
req.
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
next();
|
|
127
|
-
},
|
|
128
|
-
//
|
|
129
|
-
(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
1
|
+
import "reflect-metadata";
|
|
2
|
+
import "colors";
|
|
3
|
+
|
|
4
|
+
import * as Qs from "qs";
|
|
5
|
+
import * as ResponseTime from "response-time";
|
|
6
|
+
|
|
7
|
+
import { type IControllerRoute, type TModuleOptions, controllerKey, controllerRoutesKey, moduleKey } from "../decorators";
|
|
8
|
+
import { default as ExpressApp, Router, json, urlencoded, Request, Response, NextFunction, Errback } from "express";
|
|
9
|
+
import { Injector } from "./injector";
|
|
10
|
+
import { errorInfer } from "../http";
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
export type TBoolFactoryOptions = Partial<{
|
|
14
|
+
debug: boolean;
|
|
15
|
+
log: Partial<{
|
|
16
|
+
methods: Array<"GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS">;
|
|
17
|
+
}>;
|
|
18
|
+
queryParser: Partial<{
|
|
19
|
+
depth: 10,
|
|
20
|
+
arrayLimit: 50
|
|
21
|
+
}>;
|
|
22
|
+
}>;
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
*
|
|
27
|
+
* @param target
|
|
28
|
+
* @param router
|
|
29
|
+
*/
|
|
30
|
+
const controllerCreator = (
|
|
31
|
+
target: new (...args: any[]) => unknown,
|
|
32
|
+
router = Router()
|
|
33
|
+
) => {
|
|
34
|
+
if (!Reflect.getOwnMetadataKeys(target).includes(controllerKey)) {
|
|
35
|
+
throw Error(`${target.name} is not a controller.`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const controller = Injector.get(target);
|
|
39
|
+
|
|
40
|
+
if (!controller) {
|
|
41
|
+
throw Error("Can not initialize controller.");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const controllerMetadata = Reflect.getOwnMetadata(controllerKey, target) || "/";
|
|
45
|
+
const routesMetadata = (Reflect.getOwnMetadata(controllerRoutesKey, target) || []) as Array<IControllerRoute>;
|
|
46
|
+
const innerRouter = router.route(controllerMetadata);
|
|
47
|
+
|
|
48
|
+
routesMetadata.forEach(route => {
|
|
49
|
+
if (typeof route.descriptor.value !== "function") {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
switch (route.httpMethod) {
|
|
54
|
+
case "GET":
|
|
55
|
+
return innerRouter.get(route.descriptor.value.bind(controller));
|
|
56
|
+
case "POST":
|
|
57
|
+
return innerRouter.post(route.descriptor.value.bind(controller));
|
|
58
|
+
case "PUT":
|
|
59
|
+
return innerRouter.put(route.descriptor.value.bind(controller));
|
|
60
|
+
case "PATCH":
|
|
61
|
+
return innerRouter.patch(route.descriptor.value.bind(controller));
|
|
62
|
+
case "DELETE":
|
|
63
|
+
return innerRouter.delete(route.descriptor.value.bind(controller));
|
|
64
|
+
case "OPTIONS":
|
|
65
|
+
return innerRouter.options(route.descriptor.value.bind(controller));
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
return router;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
*
|
|
75
|
+
* @param target
|
|
76
|
+
*/
|
|
77
|
+
export const BoolFactory = (
|
|
78
|
+
target: new (...args: any[]) => unknown,
|
|
79
|
+
options?: TBoolFactoryOptions
|
|
80
|
+
) => {
|
|
81
|
+
if (!Reflect.getOwnMetadataKeys(target).includes(moduleKey)) {
|
|
82
|
+
throw Error(`${target.name} is not a module.`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const metadata = Reflect.getOwnMetadata(moduleKey, target) as TModuleOptions;
|
|
86
|
+
const routers = !metadata?.controllers ? [] : metadata.controllers.map(controllerConstructor => controllerCreator(controllerConstructor));
|
|
87
|
+
const allowOrigins = !metadata?.allowOrigins ?
|
|
88
|
+
["*"] : typeof metadata.allowOrigins !== "string" ?
|
|
89
|
+
metadata.allowOrigins : [metadata.allowOrigins];
|
|
90
|
+
const allowMethods = !metadata?.allowMethods ?
|
|
91
|
+
["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"] : metadata.allowMethods;
|
|
92
|
+
const app = ExpressApp();
|
|
93
|
+
const factoryOptions = Object.freeze({
|
|
94
|
+
allowLogsMethods: !options?.log?.methods ? ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"] : options.log.methods
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
app.set("etag", "strong");
|
|
98
|
+
app.set("query parser", (query: string) => Qs.parse(query, {
|
|
99
|
+
depth: !options?.queryParser?.depth || options.queryParser.depth < 0 ? 10 : options.queryParser.depth,
|
|
100
|
+
arrayLimit: !options?.queryParser?.arrayLimit || options.queryParser.arrayLimit < 0 ? 50 : options.queryParser.arrayLimit
|
|
101
|
+
}));
|
|
102
|
+
|
|
103
|
+
app.use(
|
|
104
|
+
urlencoded({
|
|
105
|
+
extended: true,
|
|
106
|
+
inflate: true,
|
|
107
|
+
limit: "1mb",
|
|
108
|
+
parameterLimit: 20,
|
|
109
|
+
type: "application/x-www-form-urlencoded",
|
|
110
|
+
verify: undefined
|
|
111
|
+
}),
|
|
112
|
+
json({
|
|
113
|
+
inflate: true,
|
|
114
|
+
limit: "5mb",
|
|
115
|
+
reviver: undefined,
|
|
116
|
+
strict: true,
|
|
117
|
+
type: "application/json",
|
|
118
|
+
verify: undefined
|
|
119
|
+
}),
|
|
120
|
+
// Headers parser
|
|
121
|
+
(req: Request, res: Response, next: NextFunction) => {
|
|
122
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
123
|
+
req.headers[key] = typeof value !== "string" ? value : decodeURI(value)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
next();
|
|
127
|
+
},
|
|
128
|
+
// Body parser
|
|
129
|
+
(req: Request, res: Response, next: NextFunction) => {
|
|
130
|
+
if (typeof req.body !== "object" || !req.body) {
|
|
131
|
+
req.body = Object.freeze({});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
next();
|
|
135
|
+
},
|
|
136
|
+
// Error catcher
|
|
137
|
+
(err: Errback, req: Request, res: Response, next: NextFunction) => {
|
|
138
|
+
errorInfer(res, err);
|
|
139
|
+
|
|
140
|
+
if (!options?.debug) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
console.error("Headers:", JSON.stringify(req.headers), "\nBody:", JSON.stringify(req.body), "\nError:", JSON.stringify(err));
|
|
145
|
+
},
|
|
146
|
+
// Response time log
|
|
147
|
+
ResponseTime.default((req: Request, res: Response, time: number) => {
|
|
148
|
+
const requestMethod = req.method.toUpperCase();
|
|
149
|
+
|
|
150
|
+
if (!factoryOptions.allowLogsMethods.includes(requestMethod)) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const convertedMethod = `${requestMethod.yellow}`.bgBlue;
|
|
155
|
+
const convertedPID = `${process.pid}`.yellow;
|
|
156
|
+
const convertedReqIp = `${req.headers["x-forwarded-for"] || req.headers["x-real-ip"] || req.ip || "<Unknown>"}`.yellow;
|
|
157
|
+
const convertedTime = `${Math.round((time + Number.EPSILON) * 10 ** 2) / 10 ** 2}ms`.yellow;
|
|
158
|
+
|
|
159
|
+
console.info(`PID: ${convertedPID} - Method: ${convertedMethod} - IP: ${convertedReqIp} - ${req.originalUrl.blue} - Time: ${convertedTime}`);
|
|
160
|
+
})
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
app.use((req: Request, res: Response, next: NextFunction) => {
|
|
164
|
+
if (!allowOrigins.includes("*")) {
|
|
165
|
+
if (!allowOrigins.includes(req.headers.origin || "*")) {
|
|
166
|
+
return res.status(403).json({
|
|
167
|
+
httpCode: 403,
|
|
168
|
+
data: {
|
|
169
|
+
origin: {
|
|
170
|
+
code: "origin:invalid:0x00001",
|
|
171
|
+
message: "Invalid origin."
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
res.header("Access-Control-Allow-Origin", req.headers.origin || "*");
|
|
179
|
+
res.header("Access-Control-Allow-Headers", "*");
|
|
180
|
+
res.header("Access-Control-Allow-Credentials", "true");
|
|
181
|
+
res.header("Access-Control-Allow-Methods", allowMethods.join(", "));
|
|
182
|
+
|
|
183
|
+
next();
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
if (routers.length > 0) {
|
|
187
|
+
app.use(routers);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return app;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export default BoolFactory;
|
package/src/hooks/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { BoolFactory } from "./factory";
|
|
2
|
-
export { Injector } from "./injector";
|
|
1
|
+
export { BoolFactory } from "./factory";
|
|
2
|
+
export { Injector } from "./injector";
|
package/src/hooks/injector.ts
CHANGED
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
import "reflect-metadata";
|
|
2
|
-
|
|
3
|
-
import { injectableKey, injectKey } from "../decorators";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
interface IInjector {
|
|
7
|
-
get<T>(classDefinition: { new(...args: any[]): T }): T
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const Injector: IInjector = new class {
|
|
11
|
-
|
|
12
|
-
private readonly _mapper: Map<Function, any> = new Map();
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
*
|
|
16
|
-
* @param constructor
|
|
17
|
-
*/
|
|
18
|
-
get<T>(
|
|
19
|
-
classDefinition: { new(...args: any[]): T }
|
|
20
|
-
) {
|
|
21
|
-
if (this._mapper.has(classDefinition)) {
|
|
22
|
-
return this._mapper.get(classDefinition) as T;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const ownMetadataKeys = Reflect.getMetadataKeys(classDefinition);
|
|
26
|
-
|
|
27
|
-
if (!ownMetadataKeys.includes(injectableKey)) {
|
|
28
|
-
throw Error("Missing dependency declaration, please check @Injectable() used on dependency(ies).");
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Initialize dependencies injection
|
|
32
|
-
const dependencies: any[] = Reflect.getOwnMetadata(injectKey, classDefinition) || [];
|
|
33
|
-
const injections: any[] = dependencies.map(dependency => Injector.get(dependency));
|
|
34
|
-
const instance = new classDefinition(...injections);
|
|
35
|
-
|
|
36
|
-
this._mapper.set(classDefinition, instance);
|
|
37
|
-
|
|
38
|
-
return instance;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export default Injector;
|
|
1
|
+
import "reflect-metadata";
|
|
2
|
+
|
|
3
|
+
import { injectableKey, injectKey } from "../decorators";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
interface IInjector {
|
|
7
|
+
get<T>(classDefinition: { new(...args: any[]): T }): T
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const Injector: IInjector = new class {
|
|
11
|
+
|
|
12
|
+
private readonly _mapper: Map<Function, any> = new Map();
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @param constructor
|
|
17
|
+
*/
|
|
18
|
+
get<T>(
|
|
19
|
+
classDefinition: { new(...args: any[]): T }
|
|
20
|
+
) {
|
|
21
|
+
if (this._mapper.has(classDefinition)) {
|
|
22
|
+
return this._mapper.get(classDefinition) as T;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const ownMetadataKeys = Reflect.getMetadataKeys(classDefinition);
|
|
26
|
+
|
|
27
|
+
if (!ownMetadataKeys.includes(injectableKey)) {
|
|
28
|
+
throw Error("Missing dependency declaration, please check @Injectable() used on dependency(ies).");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Initialize dependencies injection
|
|
32
|
+
const dependencies: any[] = Reflect.getOwnMetadata(injectKey, classDefinition) || [];
|
|
33
|
+
const injections: any[] = dependencies.map(dependency => Injector.get(dependency));
|
|
34
|
+
const instance = new classDefinition(...injections);
|
|
35
|
+
|
|
36
|
+
this._mapper.set(classDefinition, instance);
|
|
37
|
+
|
|
38
|
+
return instance;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export default Injector;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import * as ExpressJS from "express";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export const httpClientErrors = Object.freeze({
|
|
5
|
+
400: "BAD_REQUEST",
|
|
6
|
+
401: "UNAUTHORIZED",
|
|
7
|
+
402: "PAYMENT_REQUIRED",
|
|
8
|
+
403: "FORBIDDEN",
|
|
9
|
+
404: "NOT_FOUND",
|
|
10
|
+
405: "METHOD_NOT_ALLOWED",
|
|
11
|
+
406: "NOT_ACCEPTABLE",
|
|
12
|
+
407: "PROXY_AUTHENCATION_REQUIRED",
|
|
13
|
+
408: "REQUEST_TIMEOUT",
|
|
14
|
+
409: "CONFLICT",
|
|
15
|
+
410: "GONE",
|
|
16
|
+
411: "LENGTH_REQUIRED",
|
|
17
|
+
412: "PRECONDITION_FAILED",
|
|
18
|
+
413: "PAYLOAD_TOO_LARGE",
|
|
19
|
+
414: "URI_TOO_LONG",
|
|
20
|
+
415: "UNSUPPORTED_MEDIA_TYPE",
|
|
21
|
+
416: "RANGE_NOT_SATISFIABLE",
|
|
22
|
+
417: "EXPECTATION_FAILED",
|
|
23
|
+
418: "IM_A_TEAPOT",
|
|
24
|
+
421: "MISDIRECTED_REQUEST",
|
|
25
|
+
422: "UNPROCESSABLE_ENTITY",
|
|
26
|
+
423: "LOCKED",
|
|
27
|
+
424: "FAILED_DEPENDENCY",
|
|
28
|
+
425: "TOO_EARLY_",
|
|
29
|
+
426: "UPGRAGE_REQUIRED",
|
|
30
|
+
428: "PRECONDITION_REQUIRED",
|
|
31
|
+
429: "TOO_MANY_REQUESTS",
|
|
32
|
+
431: "REQUEST_HEADER_FIELDS_TOO_LARGE",
|
|
33
|
+
451: "UNAVAILABLE_FOR_LEGAL_REASONS"
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export class HttpClientError<
|
|
37
|
+
T extends keyof typeof httpClientErrors = keyof typeof httpClientErrors,
|
|
38
|
+
K = any
|
|
39
|
+
> extends Error {
|
|
40
|
+
public readonly httpCode: T;
|
|
41
|
+
public readonly message: typeof httpClientErrors[T];
|
|
42
|
+
public readonly data: K;
|
|
43
|
+
|
|
44
|
+
constructor({
|
|
45
|
+
httpCode,
|
|
46
|
+
data
|
|
47
|
+
}: {
|
|
48
|
+
["httpCode"]: T;
|
|
49
|
+
["data"]: K;
|
|
50
|
+
}) {
|
|
51
|
+
super();
|
|
52
|
+
|
|
53
|
+
this.httpCode = httpCode;
|
|
54
|
+
this.message = httpClientErrors[httpCode];
|
|
55
|
+
this.data = data;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Response } from "express";
|
|
2
|
+
import { HttpClientError } from "./clientError";
|
|
3
|
+
import { HttpServerError } from "./serverError";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export const errorInfer = (res: Response, data: any) => {
|
|
7
|
+
if (res.headersSent) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
try {
|
|
12
|
+
if (data instanceof HttpClientError) {
|
|
13
|
+
res.status(data.httpCode).json(data);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (data instanceof HttpServerError) {
|
|
18
|
+
res.status(data.httpCode).json(data);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (typeof data === "object") {
|
|
23
|
+
res.status(500).json({
|
|
24
|
+
httpCode: 500,
|
|
25
|
+
message: "INTERNAL SERVER ERROR",
|
|
26
|
+
data: data
|
|
27
|
+
});
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
switch (typeof data) {
|
|
32
|
+
case "string":
|
|
33
|
+
res.status(500).json({
|
|
34
|
+
httpCode: 500,
|
|
35
|
+
message: "INTERNAL SERVER ERROR",
|
|
36
|
+
data: {
|
|
37
|
+
message: data
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
return;
|
|
41
|
+
|
|
42
|
+
case "number":
|
|
43
|
+
res.status(500).json({
|
|
44
|
+
httpCode: 500,
|
|
45
|
+
message: "INTERNAL SERVER ERROR",
|
|
46
|
+
data: {
|
|
47
|
+
code: data
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
return;
|
|
51
|
+
|
|
52
|
+
default:
|
|
53
|
+
res.status(500).json({
|
|
54
|
+
httpCode: 500,
|
|
55
|
+
message: "INTERNAL SERVER ERROR",
|
|
56
|
+
data: undefined
|
|
57
|
+
});
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
console.error(error);
|
|
63
|
+
res.end();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export * from "./clientError";
|
|
68
|
+
export * from "./serverError";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as ExpressJS from "express";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export const httpServerErrors = Object.freeze({
|
|
5
|
+
500: "INTERNAL_SERVER_ERROR",
|
|
6
|
+
501: "NOT_IMPLEMENTED",
|
|
7
|
+
502: "BAD_GATEWAY",
|
|
8
|
+
503: "SERVICE_UNAVAILABLE",
|
|
9
|
+
504: "GATEWAY_TIMEOUT",
|
|
10
|
+
505: "HTTP_VERSION_NOT_SUPPORTED",
|
|
11
|
+
506: "VARIANT_ALSO_NEGOTIATES",
|
|
12
|
+
507: "INSUFFICIENT_STORAGE",
|
|
13
|
+
508: "LOOP_DETECTED",
|
|
14
|
+
510: "NOT_EXTENDED",
|
|
15
|
+
511: "NETWORK_AUTHENTICATION_REQUIRED"
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export class HttpServerError<
|
|
19
|
+
T extends keyof typeof httpServerErrors = keyof typeof httpServerErrors,
|
|
20
|
+
K = any
|
|
21
|
+
> extends Error {
|
|
22
|
+
public readonly httpCode: T;
|
|
23
|
+
public readonly message: typeof httpServerErrors[T];
|
|
24
|
+
public readonly data: K;
|
|
25
|
+
|
|
26
|
+
constructor({
|
|
27
|
+
httpCode,
|
|
28
|
+
data
|
|
29
|
+
}: {
|
|
30
|
+
["httpCode"]: T;
|
|
31
|
+
["data"]: K;
|
|
32
|
+
}) {
|
|
33
|
+
super();
|
|
34
|
+
|
|
35
|
+
this.httpCode = httpCode;
|
|
36
|
+
this.message = httpServerErrors[httpCode];
|
|
37
|
+
this.data = data;
|
|
38
|
+
}
|
|
39
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import "reflect-metadata";
|
|
2
|
-
|
|
3
|
-
export * from "./interfaces";
|
|
4
|
-
export * from "./hooks";
|
|
5
|
-
export * from "./decorators";
|
|
1
|
+
import "reflect-metadata";
|
|
2
|
+
|
|
3
|
+
export * from "./interfaces";
|
|
4
|
+
export * from "./hooks";
|
|
5
|
+
export * from "./decorators";
|
|
6
|
+
export * from "./http";
|
package/src/interfaces/index.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export default {};
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
export default {};
|