@bool-ts/core 1.2.4 → 1.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.
@@ -1,10 +1,18 @@
1
1
  import type { IService } from "./interfaces";
2
2
 
3
- import { Controller, Delete, Get, Inject, Options, Patch, Post, Put } from "../src";
3
+ import * as Zod from "zod";
4
+
5
+ import { Controller, Delete, Get, Inject, Options, Patch, Post, Put, ZodSchema } from "../src";
4
6
  import { TestService } from "./service";
5
7
  import { Request, Response } from "express";
6
8
 
7
9
 
10
+ const getAbcSchema = Zod.object({
11
+ headers: Zod.object({
12
+ authorization: Zod.string().min(10)
13
+ })
14
+ });
15
+
8
16
  @Controller("test")
9
17
  export class TestController {
10
18
  constructor(
@@ -13,7 +21,7 @@ export class TestController {
13
21
 
14
22
  @Get("abc")
15
23
  private _get(
16
- req: Request,
24
+ @ZodSchema(getAbcSchema) req: Request,
17
25
  res: Response
18
26
  ) {
19
27
  console.log("this.testService", this.testService.exec())
@@ -22,7 +30,7 @@ export class TestController {
22
30
 
23
31
  @Post("abc")
24
32
  private _post(
25
- req: Request,
33
+ @ZodSchema(getAbcSchema) req: Request,
26
34
  res: Response
27
35
  ) {
28
36
  console.log("req.body", req.body);
@@ -31,7 +39,7 @@ export class TestController {
31
39
 
32
40
  @Put()
33
41
  private _put(
34
- req: Request,
42
+ @ZodSchema(getAbcSchema) req: Request,
35
43
  res: Response
36
44
  ) {
37
45
  res.json({ test: "success" }).send();
@@ -39,7 +47,7 @@ export class TestController {
39
47
 
40
48
  @Patch("abc/:id")
41
49
  private _patch(
42
- req: Request,
50
+ @ZodSchema(getAbcSchema) req: Request,
43
51
  res: Response
44
52
  ) {
45
53
  console.log(req.params)
@@ -48,7 +56,7 @@ export class TestController {
48
56
 
49
57
  @Delete()
50
58
  private _delete(
51
- req: Request,
59
+ @ZodSchema(getAbcSchema) req: Request,
52
60
  res: Response
53
61
  ) {
54
62
  res.json({ test: "success" }).send();
@@ -56,7 +64,7 @@ export class TestController {
56
64
 
57
65
  @Options()
58
66
  private _options(
59
- req: Request,
67
+ @ZodSchema(getAbcSchema) req: Request,
60
68
  res: Response
61
69
  ) {
62
70
  res.json({ test: "success" }).send();
package/bun.lockb CHANGED
Binary file
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Options = exports.Delete = exports.Patch = exports.Put = exports.Post = exports.Get = exports.controllerRoutesKey = void 0;
4
+ const http_1 = require("../http");
5
+ const zodSchema_1 = require("./zodSchema");
4
6
  exports.controllerRoutesKey = "__bool:controller.routes__";
5
7
  /**
6
8
  *
@@ -11,6 +13,7 @@ const Get = (path = "/") => (target, methodName, descriptor) => {
11
13
  if (typeof descriptor.value !== "function") {
12
14
  throw Error("Get decorator only use for method.");
13
15
  }
16
+ // Define controller metadata
14
17
  Reflect.defineMetadata(exports.controllerRoutesKey, [
15
18
  ...Reflect.getOwnMetadata(exports.controllerRoutesKey, target.constructor) || [],
16
19
  {
@@ -20,6 +23,24 @@ const Get = (path = "/") => (target, methodName, descriptor) => {
20
23
  descriptor: descriptor
21
24
  }
22
25
  ], target.constructor);
26
+ // Define route parameters zod validation
27
+ const currentMethod = descriptor.value;
28
+ descriptor.value = function () {
29
+ const zodSchemaMetadata = Reflect.getOwnMetadata(zodSchema_1.controllerRouteZodSchemaKey, target.constructor, methodName);
30
+ if (zodSchemaMetadata) {
31
+ for (const zodSchemaProp in zodSchemaMetadata) {
32
+ const tmpZodMetadata = zodSchemaMetadata[zodSchemaProp];
33
+ const validation = tmpZodMetadata.schema.safeParse(arguments[tmpZodMetadata.index]);
34
+ if (!validation.success) {
35
+ throw new http_1.HttpClientError({
36
+ httpCode: 400,
37
+ data: validation.error.issues
38
+ });
39
+ }
40
+ }
41
+ }
42
+ return currentMethod.apply(this, arguments);
43
+ };
23
44
  };
24
45
  exports.Get = Get;
25
46
  /**
@@ -40,6 +61,24 @@ const Post = (path = "/") => (target, methodName, descriptor) => {
40
61
  descriptor: descriptor
41
62
  }
42
63
  ], target.constructor);
64
+ // Define route parameters zod validation
65
+ const currentMethod = descriptor.value;
66
+ descriptor.value = function () {
67
+ const zodSchemaMetadata = Reflect.getOwnMetadata(zodSchema_1.controllerRouteZodSchemaKey, target.constructor, methodName);
68
+ if (zodSchemaMetadata) {
69
+ for (const zodSchemaProp in zodSchemaMetadata) {
70
+ const tmpZodMetadata = zodSchemaMetadata[zodSchemaProp];
71
+ const validation = tmpZodMetadata.schema.safeParse(arguments[tmpZodMetadata.index]);
72
+ if (!validation.success) {
73
+ throw new http_1.HttpClientError({
74
+ httpCode: 400,
75
+ data: validation.error.issues
76
+ });
77
+ }
78
+ }
79
+ }
80
+ return currentMethod.apply(this, arguments);
81
+ };
43
82
  };
44
83
  exports.Post = Post;
45
84
  /**
@@ -60,6 +99,24 @@ const Put = (path = "/") => (target, methodName, descriptor) => {
60
99
  descriptor: descriptor
61
100
  }
62
101
  ], target.constructor);
102
+ // Define route parameters zod validation
103
+ const currentMethod = descriptor.value;
104
+ descriptor.value = function () {
105
+ const zodSchemaMetadata = Reflect.getOwnMetadata(zodSchema_1.controllerRouteZodSchemaKey, target.constructor, methodName);
106
+ if (zodSchemaMetadata) {
107
+ for (const zodSchemaProp in zodSchemaMetadata) {
108
+ const tmpZodMetadata = zodSchemaMetadata[zodSchemaProp];
109
+ const validation = tmpZodMetadata.schema.safeParse(arguments[tmpZodMetadata.index]);
110
+ if (!validation.success) {
111
+ throw new http_1.HttpClientError({
112
+ httpCode: 400,
113
+ data: validation.error.issues
114
+ });
115
+ }
116
+ }
117
+ }
118
+ return currentMethod.apply(this, arguments);
119
+ };
63
120
  };
64
121
  exports.Put = Put;
65
122
  /**
@@ -80,6 +137,24 @@ const Patch = (path = "/") => (target, methodName, descriptor) => {
80
137
  descriptor: descriptor
81
138
  }
82
139
  ], target.constructor);
140
+ // Define route parameters zod validation
141
+ const currentMethod = descriptor.value;
142
+ descriptor.value = function () {
143
+ const zodSchemaMetadata = Reflect.getOwnMetadata(zodSchema_1.controllerRouteZodSchemaKey, target.constructor, methodName);
144
+ if (zodSchemaMetadata) {
145
+ for (const zodSchemaProp in zodSchemaMetadata) {
146
+ const tmpZodMetadata = zodSchemaMetadata[zodSchemaProp];
147
+ const validation = tmpZodMetadata.schema.safeParse(arguments[tmpZodMetadata.index]);
148
+ if (!validation.success) {
149
+ throw new http_1.HttpClientError({
150
+ httpCode: 400,
151
+ data: validation.error.issues
152
+ });
153
+ }
154
+ }
155
+ }
156
+ return currentMethod.apply(this, arguments);
157
+ };
83
158
  };
84
159
  exports.Patch = Patch;
85
160
  /**
@@ -100,6 +175,24 @@ const Delete = (path = "/") => (target, methodName, descriptor) => {
100
175
  descriptor: descriptor
101
176
  }
102
177
  ], target.constructor);
178
+ // Define route parameters zod validation
179
+ const currentMethod = descriptor.value;
180
+ descriptor.value = function () {
181
+ const zodSchemaMetadata = Reflect.getOwnMetadata(zodSchema_1.controllerRouteZodSchemaKey, target.constructor, methodName);
182
+ if (zodSchemaMetadata) {
183
+ for (const zodSchemaProp in zodSchemaMetadata) {
184
+ const tmpZodMetadata = zodSchemaMetadata[zodSchemaProp];
185
+ const validation = tmpZodMetadata.schema.safeParse(arguments[tmpZodMetadata.index]);
186
+ if (!validation.success) {
187
+ throw new http_1.HttpClientError({
188
+ httpCode: 400,
189
+ data: validation.error.issues
190
+ });
191
+ }
192
+ }
193
+ }
194
+ return currentMethod.apply(this, arguments);
195
+ };
103
196
  };
104
197
  exports.Delete = Delete;
105
198
  /**
@@ -120,6 +213,24 @@ const Options = (path = "/") => (target, methodName, descriptor) => {
120
213
  descriptor: descriptor
121
214
  }
122
215
  ], target.constructor);
216
+ // Define route parameters zod validation
217
+ const currentMethod = descriptor.value;
218
+ descriptor.value = function () {
219
+ const zodSchemaMetadata = Reflect.getOwnMetadata(zodSchema_1.controllerRouteZodSchemaKey, target.constructor, methodName);
220
+ if (zodSchemaMetadata) {
221
+ for (const zodSchemaProp in zodSchemaMetadata) {
222
+ const tmpZodMetadata = zodSchemaMetadata[zodSchemaProp];
223
+ const validation = tmpZodMetadata.schema.safeParse(arguments[tmpZodMetadata.index]);
224
+ if (!validation.success) {
225
+ throw new http_1.HttpClientError({
226
+ httpCode: 400,
227
+ data: validation.error.issues
228
+ });
229
+ }
230
+ }
231
+ }
232
+ return currentMethod.apply(this, arguments);
233
+ };
123
234
  };
124
235
  exports.Options = Options;
125
236
  exports.default = {
@@ -3,3 +3,4 @@ export { Inject, injectKey } from "./inject";
3
3
  export { Injectable, injectableKey } from "./injectable";
4
4
  export { Module, moduleKey, type TModuleOptions } from "./module";
5
5
  export { Get, Post, Put, Patch, Delete, Options, controllerRoutesKey, type IControllerRoute } from "./http";
6
+ export { ZodSchema, controllerRouteZodSchemaKey } from "./zodSchema";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.controllerRoutesKey = exports.Options = exports.Delete = exports.Patch = exports.Put = exports.Post = exports.Get = exports.moduleKey = exports.Module = exports.injectableKey = exports.Injectable = exports.injectKey = exports.Inject = exports.controllerKey = exports.Controller = void 0;
3
+ exports.controllerRouteZodSchemaKey = exports.ZodSchema = exports.controllerRoutesKey = exports.Options = exports.Delete = exports.Patch = exports.Put = exports.Post = exports.Get = exports.moduleKey = exports.Module = exports.injectableKey = exports.Injectable = exports.injectKey = exports.Inject = exports.controllerKey = exports.Controller = void 0;
4
4
  var controller_1 = require("./controller");
5
5
  Object.defineProperty(exports, "Controller", { enumerable: true, get: function () { return controller_1.Controller; } });
6
6
  Object.defineProperty(exports, "controllerKey", { enumerable: true, get: function () { return controller_1.controllerKey; } });
@@ -21,3 +21,6 @@ Object.defineProperty(exports, "Patch", { enumerable: true, get: function () { r
21
21
  Object.defineProperty(exports, "Delete", { enumerable: true, get: function () { return http_1.Delete; } });
22
22
  Object.defineProperty(exports, "Options", { enumerable: true, get: function () { return http_1.Options; } });
23
23
  Object.defineProperty(exports, "controllerRoutesKey", { enumerable: true, get: function () { return http_1.controllerRoutesKey; } });
24
+ var zodSchema_1 = require("./zodSchema");
25
+ Object.defineProperty(exports, "ZodSchema", { enumerable: true, get: function () { return zodSchema_1.ZodSchema; } });
26
+ Object.defineProperty(exports, "controllerRouteZodSchemaKey", { enumerable: true, get: function () { return zodSchema_1.controllerRouteZodSchemaKey; } });
@@ -1,5 +1,5 @@
1
1
  export declare const injectKey = "design:paramtypes";
2
2
  export declare const Inject: <T extends Object>(classDefinition: {
3
3
  new (...args: any[]): T;
4
- }) => (target: Object, parameterName: string | Symbol | undefined, parameterIndex: number) => void;
4
+ }) => (target: Object, methodName: string | symbol | undefined, parameterIndex: number) => void;
5
5
  export default Inject;
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Inject = exports.injectKey = void 0;
4
4
  exports.injectKey = "design:paramtypes";
5
5
  const Inject = (classDefinition) => {
6
- return (target, parameterName, parameterIndex) => {
6
+ return (target, methodName, parameterIndex) => {
7
7
  const designParameterTypes = Reflect.getMetadata(exports.injectKey, target) || [];
8
8
  designParameterTypes[parameterIndex] = classDefinition;
9
9
  Reflect.defineMetadata(exports.injectKey, designParameterTypes, target);
@@ -0,0 +1,3 @@
1
+ import * as Zod from "zod";
2
+ export declare const controllerRouteZodSchemaKey = "__bool:controller.route.zodSchema__";
3
+ export declare const ZodSchema: (schema: Zod.Schema) => (target: Object, methodName: string | symbol | undefined, parameterIndex: number) => void;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ZodSchema = exports.controllerRouteZodSchemaKey = void 0;
4
+ exports.controllerRouteZodSchemaKey = "__bool:controller.route.zodSchema__";
5
+ const ZodSchema = (schema) => {
6
+ try {
7
+ schema.safeParse(undefined);
8
+ }
9
+ catch (err) {
10
+ throw Error("Zod schema parameter do not allow async.");
11
+ }
12
+ return (target, methodName, parameterIndex) => {
13
+ if (!methodName) {
14
+ return;
15
+ }
16
+ const zodSchemasMetadata = Reflect.getOwnMetadata(exports.controllerRouteZodSchemaKey, target.constructor, methodName) || {};
17
+ zodSchemasMetadata[`paramterIndexes.${parameterIndex}`] = {
18
+ index: parameterIndex,
19
+ schema: schema
20
+ };
21
+ Reflect.defineMetadata(exports.controllerRouteZodSchemaKey, zodSchemasMetadata, target.constructor, methodName);
22
+ };
23
+ };
24
+ exports.ZodSchema = ZodSchema;
@@ -123,7 +123,19 @@ const BoolFactory = (target, options) => {
123
123
  req.body = Object.freeze({});
124
124
  }
125
125
  next();
126
- });
126
+ },
127
+ // Response time log
128
+ ResponseTime.default((req, res, time) => {
129
+ const requestMethod = req.method.toUpperCase();
130
+ if (!factoryOptions.allowLogsMethods.includes(requestMethod)) {
131
+ return;
132
+ }
133
+ const convertedMethod = `${requestMethod.yellow}`.bgBlue;
134
+ const convertedPID = `${process.pid}`.yellow;
135
+ const convertedReqIp = `${req.headers["x-forwarded-for"] || req.headers["x-real-ip"] || req.ip || "<Unknown>"}`.yellow;
136
+ const convertedTime = `${Math.round((time + Number.EPSILON) * 10 ** 2) / 10 ** 2}ms`.yellow;
137
+ console.info(`PID: ${convertedPID} - Method: ${convertedMethod} - IP: ${convertedReqIp} - ${req.originalUrl.blue} - Time: ${convertedTime}`);
138
+ }));
127
139
  app.use((req, res, next) => {
128
140
  if (!allowOrigins.includes("*")) {
129
141
  if (!allowOrigins.includes(req.headers.origin || "*")) {
@@ -149,6 +161,7 @@ const BoolFactory = (target, options) => {
149
161
  app.use(routers) : app.use(!metadata.prefix.startsWith("/") ?
150
162
  `/${metadata.prefix}` : metadata.prefix, routers);
151
163
  }
164
+ // Register error catcher
152
165
  app.use(
153
166
  // Error catcher
154
167
  (err, req, res, next) => {
@@ -157,19 +170,7 @@ const BoolFactory = (target, options) => {
157
170
  return;
158
171
  }
159
172
  console.error("Headers:", JSON.stringify(req.headers), "\nBody:", JSON.stringify(req.body), "\nError:", JSON.stringify(err));
160
- },
161
- // Response time log
162
- ResponseTime.default((req, res, time) => {
163
- const requestMethod = req.method.toUpperCase();
164
- if (!factoryOptions.allowLogsMethods.includes(requestMethod)) {
165
- return;
166
- }
167
- const convertedMethod = `${requestMethod.yellow}`.bgBlue;
168
- const convertedPID = `${process.pid}`.yellow;
169
- const convertedReqIp = `${req.headers["x-forwarded-for"] || req.headers["x-real-ip"] || req.ip || "<Unknown>"}`.yellow;
170
- const convertedTime = `${Math.round((time + Number.EPSILON) * 10 ** 2) / 10 ** 2}ms`.yellow;
171
- console.info(`PID: ${convertedPID} - Method: ${convertedMethod} - IP: ${convertedReqIp} - ${req.originalUrl.blue} - Time: ${convertedTime}`);
172
- }));
173
+ });
173
174
  return app;
174
175
  };
175
176
  exports.BoolFactory = BoolFactory;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bool-ts/core",
3
- "version": "1.2.4",
3
+ "version": "1.3.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -22,7 +22,8 @@
22
22
  "express": "^5.0.0-beta.3",
23
23
  "qs": "^6.12.1",
24
24
  "reflect-metadata": "^0.2.2",
25
- "response-time": "^2.3.2"
25
+ "response-time": "^2.3.2",
26
+ "zod": "^3.23.8"
26
27
  },
27
28
  "devDependencies": {
28
29
  "@types/express": "^4.17.21",
@@ -1,3 +1,6 @@
1
+ import { HttpClientError } from "../http";
2
+ import { controllerRouteZodSchemaKey } from "./zodSchema";
3
+
1
4
  export interface IControllerRoute {
2
5
  path: string;
3
6
  httpMethod: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS";
@@ -24,6 +27,7 @@ export const Get = (
24
27
  throw Error("Get decorator only use for method.");
25
28
  }
26
29
 
30
+ // Define controller metadata
27
31
  Reflect.defineMetadata(controllerRoutesKey, [
28
32
  ...Reflect.getOwnMetadata(controllerRoutesKey, target.constructor) || [],
29
33
  {
@@ -33,6 +37,30 @@ export const Get = (
33
37
  descriptor: descriptor
34
38
  }
35
39
  ], target.constructor);
40
+
41
+ // Define route parameters zod validation
42
+ const currentMethod = descriptor.value;
43
+
44
+ descriptor.value = function () {
45
+ const zodSchemaMetadata = Reflect.getOwnMetadata(controllerRouteZodSchemaKey, target.constructor, methodName);
46
+
47
+ if (zodSchemaMetadata) {
48
+ for (const zodSchemaProp in zodSchemaMetadata) {
49
+ const tmpZodMetadata = zodSchemaMetadata[zodSchemaProp];
50
+
51
+ const validation = tmpZodMetadata.schema.safeParse(arguments[tmpZodMetadata.index]);
52
+
53
+ if (!validation.success) {
54
+ throw new HttpClientError({
55
+ httpCode: 400,
56
+ data: validation.error.issues
57
+ })
58
+ }
59
+ }
60
+ }
61
+
62
+ return currentMethod.apply(this, arguments);
63
+ }
36
64
  }
37
65
 
38
66
 
@@ -61,6 +89,30 @@ export const Post = (
61
89
  descriptor: descriptor
62
90
  }
63
91
  ], target.constructor);
92
+
93
+ // Define route parameters zod validation
94
+ const currentMethod = descriptor.value;
95
+
96
+ descriptor.value = function () {
97
+ const zodSchemaMetadata = Reflect.getOwnMetadata(controllerRouteZodSchemaKey, target.constructor, methodName);
98
+
99
+ if (zodSchemaMetadata) {
100
+ for (const zodSchemaProp in zodSchemaMetadata) {
101
+ const tmpZodMetadata = zodSchemaMetadata[zodSchemaProp];
102
+
103
+ const validation = tmpZodMetadata.schema.safeParse(arguments[tmpZodMetadata.index]);
104
+
105
+ if (!validation.success) {
106
+ throw new HttpClientError({
107
+ httpCode: 400,
108
+ data: validation.error.issues
109
+ })
110
+ }
111
+ }
112
+ }
113
+
114
+ return currentMethod.apply(this, arguments);
115
+ }
64
116
  }
65
117
 
66
118
 
@@ -89,6 +141,30 @@ export const Put = (
89
141
  descriptor: descriptor
90
142
  }
91
143
  ], target.constructor);
144
+
145
+ // Define route parameters zod validation
146
+ const currentMethod = descriptor.value;
147
+
148
+ descriptor.value = function () {
149
+ const zodSchemaMetadata = Reflect.getOwnMetadata(controllerRouteZodSchemaKey, target.constructor, methodName);
150
+
151
+ if (zodSchemaMetadata) {
152
+ for (const zodSchemaProp in zodSchemaMetadata) {
153
+ const tmpZodMetadata = zodSchemaMetadata[zodSchemaProp];
154
+
155
+ const validation = tmpZodMetadata.schema.safeParse(arguments[tmpZodMetadata.index]);
156
+
157
+ if (!validation.success) {
158
+ throw new HttpClientError({
159
+ httpCode: 400,
160
+ data: validation.error.issues
161
+ })
162
+ }
163
+ }
164
+ }
165
+
166
+ return currentMethod.apply(this, arguments);
167
+ }
92
168
  }
93
169
 
94
170
 
@@ -117,6 +193,30 @@ export const Patch = (
117
193
  descriptor: descriptor
118
194
  }
119
195
  ], target.constructor);
196
+
197
+ // Define route parameters zod validation
198
+ const currentMethod = descriptor.value;
199
+
200
+ descriptor.value = function () {
201
+ const zodSchemaMetadata = Reflect.getOwnMetadata(controllerRouteZodSchemaKey, target.constructor, methodName);
202
+
203
+ if (zodSchemaMetadata) {
204
+ for (const zodSchemaProp in zodSchemaMetadata) {
205
+ const tmpZodMetadata = zodSchemaMetadata[zodSchemaProp];
206
+
207
+ const validation = tmpZodMetadata.schema.safeParse(arguments[tmpZodMetadata.index]);
208
+
209
+ if (!validation.success) {
210
+ throw new HttpClientError({
211
+ httpCode: 400,
212
+ data: validation.error.issues
213
+ })
214
+ }
215
+ }
216
+ }
217
+
218
+ return currentMethod.apply(this, arguments);
219
+ }
120
220
  }
121
221
 
122
222
 
@@ -145,6 +245,30 @@ export const Delete = (
145
245
  descriptor: descriptor
146
246
  }
147
247
  ], target.constructor);
248
+
249
+ // Define route parameters zod validation
250
+ const currentMethod = descriptor.value;
251
+
252
+ descriptor.value = function () {
253
+ const zodSchemaMetadata = Reflect.getOwnMetadata(controllerRouteZodSchemaKey, target.constructor, methodName);
254
+
255
+ if (zodSchemaMetadata) {
256
+ for (const zodSchemaProp in zodSchemaMetadata) {
257
+ const tmpZodMetadata = zodSchemaMetadata[zodSchemaProp];
258
+
259
+ const validation = tmpZodMetadata.schema.safeParse(arguments[tmpZodMetadata.index]);
260
+
261
+ if (!validation.success) {
262
+ throw new HttpClientError({
263
+ httpCode: 400,
264
+ data: validation.error.issues
265
+ })
266
+ }
267
+ }
268
+ }
269
+
270
+ return currentMethod.apply(this, arguments);
271
+ }
148
272
  }
149
273
 
150
274
 
@@ -173,6 +297,30 @@ export const Options = (
173
297
  descriptor: descriptor
174
298
  }
175
299
  ], target.constructor);
300
+
301
+ // Define route parameters zod validation
302
+ const currentMethod = descriptor.value;
303
+
304
+ descriptor.value = function () {
305
+ const zodSchemaMetadata = Reflect.getOwnMetadata(controllerRouteZodSchemaKey, target.constructor, methodName);
306
+
307
+ if (zodSchemaMetadata) {
308
+ for (const zodSchemaProp in zodSchemaMetadata) {
309
+ const tmpZodMetadata = zodSchemaMetadata[zodSchemaProp];
310
+
311
+ const validation = tmpZodMetadata.schema.safeParse(arguments[tmpZodMetadata.index]);
312
+
313
+ if (!validation.success) {
314
+ throw new HttpClientError({
315
+ httpCode: 400,
316
+ data: validation.error.issues
317
+ })
318
+ }
319
+ }
320
+ }
321
+
322
+ return currentMethod.apply(this, arguments);
323
+ }
176
324
  }
177
325
 
178
326
  export default {
@@ -3,3 +3,4 @@ export { Inject, injectKey } from "./inject";
3
3
  export { Injectable, injectableKey } from "./injectable";
4
4
  export { Module, moduleKey, type TModuleOptions } from "./module";
5
5
  export { Get, Post, Put, Patch, Delete, Options, controllerRoutesKey, type IControllerRoute } from "./http";
6
+ export { ZodSchema, controllerRouteZodSchemaKey } from "./zodSchema";
@@ -5,7 +5,7 @@ export const Inject = <T extends Object>(
5
5
  ) => {
6
6
  return (
7
7
  target: Object,
8
- parameterName: string | Symbol | undefined,
8
+ methodName: string | symbol | undefined,
9
9
  parameterIndex: number
10
10
  ) => {
11
11
  const designParameterTypes: any[] = Reflect.getMetadata(injectKey, target) || [];
@@ -0,0 +1,33 @@
1
+ import * as Zod from "zod";
2
+
3
+ export const controllerRouteZodSchemaKey = "__bool:controller.route.zodSchema__";
4
+
5
+ export const ZodSchema = (
6
+ schema: Zod.Schema
7
+ ) => {
8
+ try {
9
+ schema.safeParse(undefined);
10
+ }
11
+ catch (err) {
12
+ throw Error("Zod schema parameter do not allow async.");
13
+ }
14
+
15
+ return (
16
+ target: Object,
17
+ methodName: string | symbol | undefined,
18
+ parameterIndex: number
19
+ ) => {
20
+ if (!methodName) {
21
+ return;
22
+ }
23
+
24
+ const zodSchemasMetadata = Reflect.getOwnMetadata(controllerRouteZodSchemaKey, target.constructor, methodName) || {};
25
+
26
+ zodSchemasMetadata[`paramterIndexes.${parameterIndex}`] = {
27
+ index: parameterIndex,
28
+ schema: schema
29
+ };
30
+
31
+ Reflect.defineMetadata(controllerRouteZodSchemaKey, zodSchemasMetadata, target.constructor, methodName);
32
+ }
33
+ }
@@ -136,7 +136,22 @@ export const BoolFactory = (
136
136
  }
137
137
 
138
138
  next();
139
- }
139
+ },
140
+ // Response time log
141
+ ResponseTime.default((req: Request, res: Response, time: number) => {
142
+ const requestMethod = req.method.toUpperCase();
143
+
144
+ if (!factoryOptions.allowLogsMethods.includes(requestMethod)) {
145
+ return;
146
+ }
147
+
148
+ const convertedMethod = `${requestMethod.yellow}`.bgBlue;
149
+ const convertedPID = `${process.pid}`.yellow;
150
+ const convertedReqIp = `${req.headers["x-forwarded-for"] || req.headers["x-real-ip"] || req.ip || "<Unknown>"}`.yellow;
151
+ const convertedTime = `${Math.round((time + Number.EPSILON) * 10 ** 2) / 10 ** 2}ms`.yellow;
152
+
153
+ console.info(`PID: ${convertedPID} - Method: ${convertedMethod} - IP: ${convertedReqIp} - ${req.originalUrl.blue} - Time: ${convertedTime}`);
154
+ })
140
155
  );
141
156
 
142
157
  app.use((req: Request, res: Response, next: NextFunction) => {
@@ -168,6 +183,7 @@ export const BoolFactory = (
168
183
  `/${metadata.prefix}` : metadata.prefix, routers);
169
184
  }
170
185
 
186
+ // Register error catcher
171
187
  app.use(
172
188
  // Error catcher
173
189
  (err: Errback, req: Request, res: Response, next: NextFunction) => {
@@ -178,22 +194,7 @@ export const BoolFactory = (
178
194
  }
179
195
 
180
196
  console.error("Headers:", JSON.stringify(req.headers), "\nBody:", JSON.stringify(req.body), "\nError:", JSON.stringify(err));
181
- },
182
- // Response time log
183
- ResponseTime.default((req: Request, res: Response, time: number) => {
184
- const requestMethod = req.method.toUpperCase();
185
-
186
- if (!factoryOptions.allowLogsMethods.includes(requestMethod)) {
187
- return;
188
- }
189
-
190
- const convertedMethod = `${requestMethod.yellow}`.bgBlue;
191
- const convertedPID = `${process.pid}`.yellow;
192
- const convertedReqIp = `${req.headers["x-forwarded-for"] || req.headers["x-real-ip"] || req.ip || "<Unknown>"}`.yellow;
193
- const convertedTime = `${Math.round((time + Number.EPSILON) * 10 ** 2) / 10 ** 2}ms`.yellow;
194
-
195
- console.info(`PID: ${convertedPID} - Method: ${convertedMethod} - IP: ${convertedReqIp} - ${req.originalUrl.blue} - Time: ${convertedTime}`);
196
- })
197
+ }
197
198
  );
198
199
 
199
200
  return app;