@bool-ts/core 1.1.1 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,193 +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
- 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;
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;
@@ -1,2 +1,2 @@
1
- export { BoolFactory } from "./factory";
2
- export { Injector } from "./injector";
1
+ export { BoolFactory } from "./factory";
2
+ export { Injector } from "./injector";
@@ -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;
@@ -1,57 +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
- }
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
+ }