@bool-ts/core 1.2.5 → 1.3.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.
@@ -1,10 +1,25 @@
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
+
16
+ const stringSchema = Zod.object({}).refine(async (val) => {
17
+ const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
18
+ await delay(10000);
19
+
20
+ return val;
21
+ });
22
+
8
23
  @Controller("test")
9
24
  export class TestController {
10
25
  constructor(
@@ -13,7 +28,7 @@ export class TestController {
13
28
 
14
29
  @Get("abc")
15
30
  private _get(
16
- req: Request,
31
+ @ZodSchema(getAbcSchema) req: Request,
17
32
  res: Response
18
33
  ) {
19
34
  console.log("this.testService", this.testService.exec())
@@ -22,7 +37,7 @@ export class TestController {
22
37
 
23
38
  @Post("abc")
24
39
  private _post(
25
- req: Request,
40
+ @ZodSchema(getAbcSchema) req: Request,
26
41
  res: Response
27
42
  ) {
28
43
  console.log("req.body", req.body);
@@ -31,7 +46,7 @@ export class TestController {
31
46
 
32
47
  @Put()
33
48
  private _put(
34
- req: Request,
49
+ @ZodSchema(getAbcSchema) req: Request,
35
50
  res: Response
36
51
  ) {
37
52
  res.json({ test: "success" }).send();
@@ -39,7 +54,7 @@ export class TestController {
39
54
 
40
55
  @Patch("abc/:id")
41
56
  private _patch(
42
- req: Request,
57
+ @ZodSchema(getAbcSchema) req: Request,
43
58
  res: Response
44
59
  ) {
45
60
  console.log(req.params)
@@ -49,14 +64,14 @@ export class TestController {
49
64
  @Delete()
50
65
  private _delete(
51
66
  req: Request,
52
- res: Response
67
+ @ZodSchema(stringSchema) res: Response
53
68
  ) {
54
69
  res.json({ test: "success" }).send();
55
70
  }
56
71
 
57
72
  @Options()
58
73
  private _options(
59
- req: Request,
74
+ @ZodSchema(getAbcSchema) req: Request,
60
75
  res: Response
61
76
  ) {
62
77
  res.json({ test: "success" }).send();
package/bun.lockb CHANGED
Binary file
@@ -1,126 +1,139 @@
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 ultils_1 = require("../ultils");
6
+ const zodSchema_1 = require("./zodSchema");
4
7
  exports.controllerRoutesKey = "__bool:controller.routes__";
5
- /**
6
- *
7
- * @param path
8
- * @returns
9
- */
10
- const Get = (path = "/") => (target, methodName, descriptor) => {
11
- if (typeof descriptor.value !== "function") {
12
- throw Error("Get decorator only use for method.");
8
+ const defaultDecorator = (path, method) => (target, methodName, descriptor) => {
9
+ if (!(descriptor.value instanceof Function)) {
10
+ throw Error(`${method} decorator only use for method.`);
13
11
  }
12
+ // Define controller metadata
14
13
  Reflect.defineMetadata(exports.controllerRoutesKey, [
15
14
  ...Reflect.getOwnMetadata(exports.controllerRoutesKey, target.constructor) || [],
16
15
  {
17
16
  path: !path.startsWith("/") ? `/${path}` : path,
18
- httpMethod: "GET",
17
+ httpMethod: method.toUpperCase(),
19
18
  methodName: methodName,
20
19
  descriptor: descriptor
21
20
  }
22
21
  ], target.constructor);
22
+ // Define route parameters zod validation
23
+ const currentMethod = descriptor.value;
24
+ const isAsync = descriptor.value instanceof ultils_1.AsyncFunction;
25
+ if (!isAsync) {
26
+ descriptor.value = function () {
27
+ const zodSchemaMetadata = Reflect.getOwnMetadata(zodSchema_1.controllerRouteZodSchemaKey, target.constructor, methodName);
28
+ if (zodSchemaMetadata) {
29
+ for (const zodSchemaProp in zodSchemaMetadata) {
30
+ const tmpZodMetadata = zodSchemaMetadata[zodSchemaProp];
31
+ try {
32
+ const validation = tmpZodMetadata.schema.safeParse(arguments[tmpZodMetadata.index]);
33
+ if (!validation.success) {
34
+ throw new http_1.HttpClientError({
35
+ httpCode: 400,
36
+ message: `Validation at the [${methodName}] method fails at positional argument [${tmpZodMetadata.index}].`,
37
+ data: validation.error.issues
38
+ });
39
+ }
40
+ }
41
+ catch (error) {
42
+ if (error instanceof http_1.HttpClientError) {
43
+ throw error;
44
+ }
45
+ throw new http_1.HttpServerError({
46
+ httpCode: 500,
47
+ message: `Validation at the [${methodName}] method error at positional argument [${tmpZodMetadata.index}].`,
48
+ data: !(error instanceof Error) ? error : [{
49
+ message: error.message,
50
+ code: error.name,
51
+ cause: error.cause
52
+ }]
53
+ });
54
+ }
55
+ }
56
+ }
57
+ return currentMethod.apply(this, arguments);
58
+ };
59
+ }
60
+ else {
61
+ descriptor.value = async function () {
62
+ const zodSchemaMetadata = Reflect.getOwnMetadata(zodSchema_1.controllerRouteZodSchemaKey, target.constructor, methodName);
63
+ if (zodSchemaMetadata) {
64
+ for (const zodSchemaProp in zodSchemaMetadata) {
65
+ const tmpZodMetadata = zodSchemaMetadata[zodSchemaProp];
66
+ try {
67
+ const validation = await tmpZodMetadata.schema.safeParseAsync(arguments[tmpZodMetadata.index]);
68
+ if (!validation.success) {
69
+ throw new http_1.HttpClientError({
70
+ httpCode: 400,
71
+ message: `Validation at the [${methodName}] method fails at positional argument [${tmpZodMetadata.index}].`,
72
+ data: validation.error.issues
73
+ });
74
+ }
75
+ }
76
+ catch (error) {
77
+ if (error instanceof http_1.HttpClientError) {
78
+ throw error;
79
+ }
80
+ throw new http_1.HttpServerError({
81
+ httpCode: 500,
82
+ message: `Validation at the [${methodName}] method error at positional argument [${tmpZodMetadata.index}].`,
83
+ data: !(error instanceof Error) ? error : [{
84
+ message: error.message,
85
+ code: error.name,
86
+ cause: error.cause
87
+ }]
88
+ });
89
+ }
90
+ }
91
+ }
92
+ return currentMethod.apply(this, arguments);
93
+ };
94
+ }
23
95
  };
96
+ /**
97
+ *
98
+ * @param path
99
+ * @returns
100
+ */
101
+ const Get = (path = "/") => defaultDecorator(path, "Get");
24
102
  exports.Get = Get;
25
103
  /**
26
104
  *
27
105
  * @param path
28
106
  * @returns
29
107
  */
30
- const Post = (path = "/") => (target, methodName, descriptor) => {
31
- if (typeof descriptor.value !== "function") {
32
- throw Error("Post decorator only use for method.");
33
- }
34
- Reflect.defineMetadata(exports.controllerRoutesKey, [
35
- ...Reflect.getOwnMetadata(exports.controllerRoutesKey, target.constructor) || [],
36
- {
37
- path: !path.startsWith("/") ? `/${path}` : path,
38
- httpMethod: "POST",
39
- methodName: methodName,
40
- descriptor: descriptor
41
- }
42
- ], target.constructor);
43
- };
108
+ const Post = (path = "/") => defaultDecorator(path, "Post");
44
109
  exports.Post = Post;
45
110
  /**
46
111
  *
47
112
  * @param path
48
113
  * @returns
49
114
  */
50
- const Put = (path = "/") => (target, methodName, descriptor) => {
51
- if (typeof descriptor.value !== "function") {
52
- throw Error("Put decorator only use for method.");
53
- }
54
- Reflect.defineMetadata(exports.controllerRoutesKey, [
55
- ...Reflect.getOwnMetadata(exports.controllerRoutesKey, target.constructor) || [],
56
- {
57
- path: !path.startsWith("/") ? `/${path}` : path,
58
- httpMethod: "PUT",
59
- methodName: methodName,
60
- descriptor: descriptor
61
- }
62
- ], target.constructor);
63
- };
115
+ const Put = (path = "/") => defaultDecorator(path, "Put");
64
116
  exports.Put = Put;
65
117
  /**
66
118
  *
67
119
  * @param path
68
120
  * @returns
69
121
  */
70
- const Patch = (path = "/") => (target, methodName, descriptor) => {
71
- if (typeof descriptor.value !== "function") {
72
- throw Error("Patch decorator only use for method.");
73
- }
74
- Reflect.defineMetadata(exports.controllerRoutesKey, [
75
- ...Reflect.getOwnMetadata(exports.controllerRoutesKey, target.constructor) || [],
76
- {
77
- path: !path.startsWith("/") ? `/${path}` : path,
78
- httpMethod: "PATCH",
79
- methodName: methodName,
80
- descriptor: descriptor
81
- }
82
- ], target.constructor);
83
- };
122
+ const Patch = (path = "/") => defaultDecorator(path, "Patch");
84
123
  exports.Patch = Patch;
85
124
  /**
86
125
  *
87
126
  * @param path
88
127
  * @returns
89
128
  */
90
- const Delete = (path = "/") => (target, methodName, descriptor) => {
91
- if (typeof descriptor.value !== "function") {
92
- throw Error("Delete decorator only use for method.");
93
- }
94
- Reflect.defineMetadata(exports.controllerRoutesKey, [
95
- ...Reflect.getOwnMetadata(exports.controllerRoutesKey, target.constructor) || [],
96
- {
97
- path: !path.startsWith("/") ? `/${path}` : path,
98
- httpMethod: "DELETE",
99
- methodName: methodName,
100
- descriptor: descriptor
101
- }
102
- ], target.constructor);
103
- };
129
+ const Delete = (path = "/") => defaultDecorator(path, "Delete");
104
130
  exports.Delete = Delete;
105
131
  /**
106
132
  *
107
133
  * @param path
108
134
  * @returns
109
135
  */
110
- const Options = (path = "/") => (target, methodName, descriptor) => {
111
- if (typeof descriptor.value !== "function") {
112
- throw Error("Options decorator only use for method.");
113
- }
114
- Reflect.defineMetadata(exports.controllerRoutesKey, [
115
- ...Reflect.getOwnMetadata(exports.controllerRoutesKey, target.constructor) || [],
116
- {
117
- path: !path.startsWith("/") ? `/${path}` : path,
118
- httpMethod: "OPTIONS",
119
- methodName: methodName,
120
- descriptor: descriptor
121
- }
122
- ], target.constructor);
123
- };
136
+ const Options = (path = "/") => defaultDecorator(path, "Options");
124
137
  exports.Options = Options;
125
138
  exports.default = {
126
139
  Get: exports.Get,
@@ -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,18 @@
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
+ return (target, methodName, parameterIndex) => {
7
+ if (!methodName) {
8
+ return;
9
+ }
10
+ const zodSchemasMetadata = Reflect.getOwnMetadata(exports.controllerRouteZodSchemaKey, target.constructor, methodName) || {};
11
+ zodSchemasMetadata[`paramterIndexes.${parameterIndex}`] = {
12
+ index: parameterIndex,
13
+ schema: schema
14
+ };
15
+ Reflect.defineMetadata(exports.controllerRouteZodSchemaKey, zodSchemasMetadata, target.constructor, methodName);
16
+ };
17
+ };
18
+ exports.ZodSchema = ZodSchema;
@@ -169,7 +169,9 @@ const BoolFactory = (target, options) => {
169
169
  if (!options?.debug) {
170
170
  return;
171
171
  }
172
- console.error("Headers:", JSON.stringify(req.headers), "\nBody:", JSON.stringify(req.body), "\nError:", JSON.stringify(err));
172
+ console.info("Headers:", JSON.stringify(req.headers, null, 4), "\nBody:", JSON.stringify(req.body, null, 4));
173
+ console.error("Error:");
174
+ console.error(err);
173
175
  });
174
176
  return app;
175
177
  };
@@ -31,10 +31,11 @@ export declare const httpClientErrors: Readonly<{
31
31
  }>;
32
32
  export declare class HttpClientError<T extends keyof typeof httpClientErrors = keyof typeof httpClientErrors, K = any> extends Error {
33
33
  readonly httpCode: T;
34
- readonly message: typeof httpClientErrors[T];
34
+ readonly message: typeof httpClientErrors[T] | string;
35
35
  readonly data: K;
36
- constructor({ httpCode, data }: {
37
- ["httpCode"]: T;
38
- ["data"]: K;
36
+ constructor({ httpCode, data, message }: {
37
+ httpCode: T;
38
+ data: K;
39
+ message?: string;
39
40
  });
40
41
  }
@@ -36,10 +36,10 @@ class HttpClientError extends Error {
36
36
  httpCode;
37
37
  message;
38
38
  data;
39
- constructor({ httpCode, data }) {
39
+ constructor({ httpCode, data, message }) {
40
40
  super();
41
41
  this.httpCode = httpCode;
42
- this.message = exports.httpClientErrors[httpCode];
42
+ this.message = !message?.trim() ? exports.httpClientErrors[httpCode] : message.trim();
43
43
  this.data = data;
44
44
  }
45
45
  }
@@ -34,7 +34,11 @@ const errorInfer = (res, data) => {
34
34
  res.status(500).json({
35
35
  httpCode: 500,
36
36
  message: "INTERNAL SERVER ERROR",
37
- data: data
37
+ data: !(data instanceof Error) ? data : {
38
+ message: data.message,
39
+ code: data.name,
40
+ cause: data.cause
41
+ }
38
42
  });
39
43
  return;
40
44
  }
@@ -13,10 +13,11 @@ export declare const httpServerErrors: Readonly<{
13
13
  }>;
14
14
  export declare class HttpServerError<T extends keyof typeof httpServerErrors = keyof typeof httpServerErrors, K = any> extends Error {
15
15
  readonly httpCode: T;
16
- readonly message: typeof httpServerErrors[T];
16
+ readonly message: typeof httpServerErrors[T] | string;
17
17
  readonly data: K;
18
- constructor({ httpCode, data }: {
19
- ["httpCode"]: T;
20
- ["data"]: K;
18
+ constructor({ httpCode, data, message }: {
19
+ httpCode: T;
20
+ data: K;
21
+ message?: string;
21
22
  });
22
23
  }
@@ -18,10 +18,10 @@ class HttpServerError extends Error {
18
18
  httpCode;
19
19
  message;
20
20
  data;
21
- constructor({ httpCode, data }) {
21
+ constructor({ httpCode, data, message }) {
22
22
  super();
23
23
  this.httpCode = httpCode;
24
- this.message = exports.httpServerErrors[httpCode];
24
+ this.message = !message?.trim() ? exports.httpServerErrors[httpCode] : message.trim();
25
25
  this.data = data;
26
26
  }
27
27
  }
@@ -0,0 +1 @@
1
+ export declare const AsyncFunction: Function;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AsyncFunction = void 0;
4
+ exports.AsyncFunction = async function () { }.constructor;
@@ -0,0 +1 @@
1
+ export * from "./asyncFunction";
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./asyncFunction"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bool-ts/core",
3
- "version": "1.2.5",
3
+ "version": "1.3.1",
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,7 @@
1
+ import { HttpClientError, HttpServerError } from "../http";
2
+ import { AsyncFunction } from "../ultils";
3
+ import { controllerRouteZodSchemaKey } from "./zodSchema";
4
+
1
5
  export interface IControllerRoute {
2
6
  path: string;
3
7
  httpMethod: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS";
@@ -8,33 +12,125 @@ export interface IControllerRoute {
8
12
 
9
13
  export const controllerRoutesKey = "__bool:controller.routes__";
10
14
 
11
- /**
12
- *
13
- * @param path
14
- * @returns
15
- */
16
- export const Get = (
17
- path = "/"
15
+
16
+ const defaultDecorator = (
17
+ path: string,
18
+ method: "Get" | "Post" | "Put" | "Patch" | "Delete" | "Options"
18
19
  ) => (
19
20
  target: Object,
20
21
  methodName: string,
21
22
  descriptor: PropertyDescriptor
22
23
  ) => {
23
- if (typeof descriptor.value !== "function") {
24
- throw Error("Get decorator only use for method.");
24
+ if (!(descriptor.value instanceof Function)) {
25
+ throw Error(`${method} decorator only use for method.`);
25
26
  }
26
27
 
28
+ // Define controller metadata
27
29
  Reflect.defineMetadata(controllerRoutesKey, [
28
30
  ...Reflect.getOwnMetadata(controllerRoutesKey, target.constructor) || [],
29
31
  {
30
32
  path: !path.startsWith("/") ? `/${path}` : path,
31
- httpMethod: "GET",
33
+ httpMethod: method.toUpperCase(),
32
34
  methodName: methodName,
33
35
  descriptor: descriptor
34
36
  }
35
37
  ], target.constructor);
38
+
39
+ // Define route parameters zod validation
40
+ const currentMethod = descriptor.value;
41
+ const isAsync = descriptor.value instanceof AsyncFunction;
42
+
43
+ if (!isAsync) {
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
+ try {
52
+ const validation = tmpZodMetadata.schema.safeParse(arguments[tmpZodMetadata.index]);
53
+
54
+ if (!validation.success) {
55
+ throw new HttpClientError({
56
+ httpCode: 400,
57
+ message: `Validation at the [${methodName}] method fails at positional argument [${tmpZodMetadata.index}].`,
58
+ data: validation.error.issues
59
+ });
60
+ }
61
+ }
62
+ catch (error) {
63
+ if (error instanceof HttpClientError) {
64
+ throw error;
65
+ }
66
+
67
+ throw new HttpServerError({
68
+ httpCode: 500,
69
+ message: `Validation at the [${methodName}] method error at positional argument [${tmpZodMetadata.index}].`,
70
+ data: !(error instanceof Error) ? error : [{
71
+ message: error.message,
72
+ code: error.name,
73
+ cause: error.cause
74
+ }]
75
+ });
76
+ }
77
+ }
78
+ }
79
+
80
+ return currentMethod.apply(this, arguments);
81
+ }
82
+ }
83
+ else {
84
+ descriptor.value = async function () {
85
+ const zodSchemaMetadata = Reflect.getOwnMetadata(controllerRouteZodSchemaKey, target.constructor, methodName);
86
+
87
+ if (zodSchemaMetadata) {
88
+ for (const zodSchemaProp in zodSchemaMetadata) {
89
+ const tmpZodMetadata = zodSchemaMetadata[zodSchemaProp];
90
+
91
+ try {
92
+ const validation = await tmpZodMetadata.schema.safeParseAsync(arguments[tmpZodMetadata.index]);
93
+
94
+ if (!validation.success) {
95
+ throw new HttpClientError({
96
+ httpCode: 400,
97
+ message: `Validation at the [${methodName}] method fails at positional argument [${tmpZodMetadata.index}].`,
98
+ data: validation.error.issues
99
+ });
100
+ }
101
+ }
102
+ catch (error) {
103
+ if (error instanceof HttpClientError) {
104
+ throw error;
105
+ }
106
+
107
+ throw new HttpServerError({
108
+ httpCode: 500,
109
+ message: `Validation at the [${methodName}] method error at positional argument [${tmpZodMetadata.index}].`,
110
+ data: !(error instanceof Error) ? error : [{
111
+ message: error.message,
112
+ code: error.name,
113
+ cause: error.cause
114
+ }]
115
+ });
116
+ }
117
+ }
118
+ }
119
+
120
+ return currentMethod.apply(this, arguments);
121
+ }
122
+ }
36
123
  }
37
124
 
125
+ /**
126
+ *
127
+ * @param path
128
+ * @returns
129
+ */
130
+ export const Get = (
131
+ path = "/"
132
+ ) => defaultDecorator(path, "Get");
133
+
38
134
 
39
135
  /**
40
136
  *
@@ -43,25 +139,7 @@ export const Get = (
43
139
  */
44
140
  export const Post = (
45
141
  path = "/"
46
- ) => (
47
- target: Object,
48
- methodName: string,
49
- descriptor: PropertyDescriptor
50
- ) => {
51
- if (typeof descriptor.value !== "function") {
52
- throw Error("Post decorator only use for method.");
53
- }
54
-
55
- Reflect.defineMetadata(controllerRoutesKey, [
56
- ...Reflect.getOwnMetadata(controllerRoutesKey, target.constructor) || [],
57
- {
58
- path: !path.startsWith("/") ? `/${path}` : path,
59
- httpMethod: "POST",
60
- methodName: methodName,
61
- descriptor: descriptor
62
- }
63
- ], target.constructor);
64
- }
142
+ ) => defaultDecorator(path, "Post");
65
143
 
66
144
 
67
145
  /**
@@ -71,25 +149,7 @@ export const Post = (
71
149
  */
72
150
  export const Put = (
73
151
  path = "/"
74
- ) => (
75
- target: Object,
76
- methodName: string,
77
- descriptor: PropertyDescriptor
78
- ) => {
79
- if (typeof descriptor.value !== "function") {
80
- throw Error("Put decorator only use for method.");
81
- }
82
-
83
- Reflect.defineMetadata(controllerRoutesKey, [
84
- ...Reflect.getOwnMetadata(controllerRoutesKey, target.constructor) || [],
85
- {
86
- path: !path.startsWith("/") ? `/${path}` : path,
87
- httpMethod: "PUT",
88
- methodName: methodName,
89
- descriptor: descriptor
90
- }
91
- ], target.constructor);
92
- }
152
+ ) => defaultDecorator(path, "Put");
93
153
 
94
154
 
95
155
  /**
@@ -99,25 +159,7 @@ export const Put = (
99
159
  */
100
160
  export const Patch = (
101
161
  path = "/"
102
- ) => (
103
- target: Object,
104
- methodName: string,
105
- descriptor: PropertyDescriptor
106
- ) => {
107
- if (typeof descriptor.value !== "function") {
108
- throw Error("Patch decorator only use for method.");
109
- }
110
-
111
- Reflect.defineMetadata(controllerRoutesKey, [
112
- ...Reflect.getOwnMetadata(controllerRoutesKey, target.constructor) || [],
113
- {
114
- path: !path.startsWith("/") ? `/${path}` : path,
115
- httpMethod: "PATCH",
116
- methodName: methodName,
117
- descriptor: descriptor
118
- }
119
- ], target.constructor);
120
- }
162
+ ) => defaultDecorator(path, "Patch");
121
163
 
122
164
 
123
165
  /**
@@ -127,25 +169,7 @@ export const Patch = (
127
169
  */
128
170
  export const Delete = (
129
171
  path = "/"
130
- ) => (
131
- target: Object,
132
- methodName: string,
133
- descriptor: PropertyDescriptor
134
- ) => {
135
- if (typeof descriptor.value !== "function") {
136
- throw Error("Delete decorator only use for method.");
137
- }
138
-
139
- Reflect.defineMetadata(controllerRoutesKey, [
140
- ...Reflect.getOwnMetadata(controllerRoutesKey, target.constructor) || [],
141
- {
142
- path: !path.startsWith("/") ? `/${path}` : path,
143
- httpMethod: "DELETE",
144
- methodName: methodName,
145
- descriptor: descriptor
146
- }
147
- ], target.constructor);
148
- }
172
+ ) => defaultDecorator(path, "Delete");
149
173
 
150
174
 
151
175
  /**
@@ -155,25 +179,7 @@ export const Delete = (
155
179
  */
156
180
  export const Options = (
157
181
  path = "/"
158
- ) => (
159
- target: Object,
160
- methodName: string,
161
- descriptor: PropertyDescriptor
162
- ) => {
163
- if (typeof descriptor.value !== "function") {
164
- throw Error("Options decorator only use for method.");
165
- }
166
-
167
- Reflect.defineMetadata(controllerRoutesKey, [
168
- ...Reflect.getOwnMetadata(controllerRoutesKey, target.constructor) || [],
169
- {
170
- path: !path.startsWith("/") ? `/${path}` : path,
171
- httpMethod: "OPTIONS",
172
- methodName: methodName,
173
- descriptor: descriptor
174
- }
175
- ], target.constructor);
176
- }
182
+ ) => defaultDecorator(path, "Options");
177
183
 
178
184
  export default {
179
185
  Get,
@@ -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,27 @@
1
+ import * as Zod from "zod";
2
+
3
+ export const controllerRouteZodSchemaKey = "__bool:controller.route.zodSchema__";
4
+
5
+
6
+ export const ZodSchema = (
7
+ schema: Zod.Schema
8
+ ) => {
9
+ return (
10
+ target: Object,
11
+ methodName: string | symbol | undefined,
12
+ parameterIndex: number
13
+ ) => {
14
+ if (!methodName) {
15
+ return;
16
+ }
17
+
18
+ const zodSchemasMetadata = Reflect.getOwnMetadata(controllerRouteZodSchemaKey, target.constructor, methodName) || {};
19
+
20
+ zodSchemasMetadata[`paramterIndexes.${parameterIndex}`] = {
21
+ index: parameterIndex,
22
+ schema: schema
23
+ };
24
+
25
+ Reflect.defineMetadata(controllerRouteZodSchemaKey, zodSchemasMetadata, target.constructor, methodName);
26
+ }
27
+ }
@@ -193,7 +193,9 @@ export const BoolFactory = (
193
193
  return;
194
194
  }
195
195
 
196
- console.error("Headers:", JSON.stringify(req.headers), "\nBody:", JSON.stringify(req.body), "\nError:", JSON.stringify(err));
196
+ console.info("Headers:", JSON.stringify(req.headers, null, 4), "\nBody:", JSON.stringify(req.body, null, 4));
197
+ console.error("Error:");
198
+ console.error(err);
197
199
  }
198
200
  );
199
201
 
@@ -1,6 +1,3 @@
1
- import * as ExpressJS from "express";
2
-
3
-
4
1
  export const httpClientErrors = Object.freeze({
5
2
  400: "BAD_REQUEST",
6
3
  401: "UNAUTHORIZED",
@@ -38,20 +35,22 @@ export class HttpClientError<
38
35
  K = any
39
36
  > extends Error {
40
37
  public readonly httpCode: T;
41
- public readonly message: typeof httpClientErrors[T];
38
+ public readonly message: typeof httpClientErrors[T] | string;
42
39
  public readonly data: K;
43
40
 
44
41
  constructor({
45
42
  httpCode,
46
- data
43
+ data,
44
+ message
47
45
  }: {
48
- ["httpCode"]: T;
49
- ["data"]: K;
46
+ httpCode: T;
47
+ data: K;
48
+ message?: string;
50
49
  }) {
51
50
  super();
52
51
 
53
52
  this.httpCode = httpCode;
54
- this.message = httpClientErrors[httpCode];
53
+ this.message = !message?.trim() ? httpClientErrors[httpCode] : message.trim();
55
54
  this.data = data;
56
55
  }
57
56
  }
package/src/http/index.ts CHANGED
@@ -23,7 +23,11 @@ export const errorInfer = (res: Response, data: any) => {
23
23
  res.status(500).json({
24
24
  httpCode: 500,
25
25
  message: "INTERNAL SERVER ERROR",
26
- data: data
26
+ data: !(data instanceof Error) ? data : {
27
+ message: data.message,
28
+ code: data.name,
29
+ cause: data.cause
30
+ }
27
31
  });
28
32
  return;
29
33
  }
@@ -1,6 +1,3 @@
1
- import * as ExpressJS from "express";
2
-
3
-
4
1
  export const httpServerErrors = Object.freeze({
5
2
  500: "INTERNAL_SERVER_ERROR",
6
3
  501: "NOT_IMPLEMENTED",
@@ -20,20 +17,22 @@ export class HttpServerError<
20
17
  K = any
21
18
  > extends Error {
22
19
  public readonly httpCode: T;
23
- public readonly message: typeof httpServerErrors[T];
20
+ public readonly message: typeof httpServerErrors[T] | string;
24
21
  public readonly data: K;
25
22
 
26
23
  constructor({
27
24
  httpCode,
28
- data
25
+ data,
26
+ message
29
27
  }: {
30
- ["httpCode"]: T;
31
- ["data"]: K;
28
+ httpCode: T;
29
+ data: K;
30
+ message?: string;
32
31
  }) {
33
32
  super();
34
33
 
35
34
  this.httpCode = httpCode;
36
- this.message = httpServerErrors[httpCode];
35
+ this.message = !message?.trim() ? httpServerErrors[httpCode] : message.trim();
37
36
  this.data = data;
38
37
  }
39
38
  }
@@ -0,0 +1 @@
1
+ export const AsyncFunction = async function () { }.constructor;
@@ -0,0 +1 @@
1
+ export * from "./asyncFunction";