quantum-flow 1.3.10 → 1.5.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.
Files changed (67) hide show
  1. package/README.md +22 -15
  2. package/dist/app/aws/lambda.d.ts +0 -3
  3. package/dist/app/aws/lambda.js +25 -112
  4. package/dist/app/aws/utils/helpers.d.ts +4 -0
  5. package/dist/app/aws/utils/helpers.js +83 -0
  6. package/dist/app/aws/utils/index.d.ts +3 -0
  7. package/dist/app/aws/utils/index.js +19 -0
  8. package/dist/app/aws/utils/request.d.ts +23 -0
  9. package/dist/app/aws/utils/request.js +96 -0
  10. package/dist/app/aws/utils/response.d.ts +14 -0
  11. package/dist/app/aws/utils/response.js +37 -0
  12. package/dist/app/http/Application.d.ts +1 -1
  13. package/dist/app/http/Application.js +36 -21
  14. package/dist/app/http/decorators.js +1 -0
  15. package/dist/constants.d.ts +2 -0
  16. package/dist/constants.js +3 -1
  17. package/dist/core/Controller.d.ts +6 -25
  18. package/dist/core/Controller.js +84 -118
  19. package/dist/core/Endpoint.js +1 -2
  20. package/dist/core/index.d.ts +1 -1
  21. package/dist/core/utils/index.d.ts +0 -2
  22. package/dist/core/utils/index.js +0 -2
  23. package/dist/examples/app.d.ts +0 -1
  24. package/dist/examples/app.js +70 -5
  25. package/dist/examples/controllers/user.js +44 -8
  26. package/dist/examples/controllers/userMetadata.d.ts +1 -1
  27. package/dist/examples/controllers/userMetadata.js +59 -9
  28. package/dist/middlewares/catch.d.ts +2 -0
  29. package/dist/middlewares/catch.js +10 -0
  30. package/dist/middlewares/cors.d.ts +2 -0
  31. package/dist/middlewares/cors.js +21 -0
  32. package/dist/middlewares/index.d.ts +5 -0
  33. package/dist/middlewares/index.js +21 -0
  34. package/dist/middlewares/sanitize.d.ts +2 -0
  35. package/dist/middlewares/sanitize.js +15 -0
  36. package/dist/{core/utils/helpers.js → middlewares/status.js} +1 -1
  37. package/dist/middlewares/use.d.ts +2 -0
  38. package/dist/middlewares/use.js +11 -0
  39. package/dist/types/common.d.ts +15 -32
  40. package/dist/types/controller.d.ts +7 -5
  41. package/dist/types/cors.d.ts +10 -0
  42. package/dist/types/cors.js +2 -0
  43. package/dist/types/http.d.ts +4 -0
  44. package/dist/types/index.d.ts +3 -0
  45. package/dist/types/index.js +3 -0
  46. package/dist/types/lambda.d.ts +7 -17
  47. package/dist/types/multipart.d.ts +8 -0
  48. package/dist/types/multipart.js +2 -0
  49. package/dist/types/sanitize.d.ts +8 -0
  50. package/dist/types/sanitize.js +2 -0
  51. package/dist/utils/controller.d.ts +27 -3
  52. package/dist/utils/controller.js +122 -23
  53. package/dist/utils/cors.d.ts +8 -0
  54. package/dist/utils/cors.js +127 -0
  55. package/dist/utils/headers.d.ts +2 -0
  56. package/dist/utils/headers.js +9 -0
  57. package/dist/utils/index.d.ts +3 -0
  58. package/dist/utils/index.js +3 -0
  59. package/dist/utils/multipart.d.ts +2 -8
  60. package/dist/utils/multipart.js +98 -2
  61. package/dist/utils/sanitize.d.ts +30 -0
  62. package/dist/utils/sanitize.js +134 -0
  63. package/dist/utils/server.js +5 -0
  64. package/package.json +9 -2
  65. package/dist/core/utils/middlewares.d.ts +0 -3
  66. package/dist/core/utils/middlewares.js +0 -22
  67. /package/dist/{core/utils/helpers.d.ts → middlewares/status.d.ts} +0 -0
@@ -85,7 +85,6 @@ class HttpServer extends Socket_1.Socket {
85
85
  }
86
86
  else {
87
87
  this.isRunning = false;
88
- console.log(_constants_1.STOPPED);
89
88
  resolve();
90
89
  }
91
90
  });
@@ -97,23 +96,39 @@ class HttpServer extends Socket_1.Socket {
97
96
  config: this.config,
98
97
  };
99
98
  }
100
- async requestHandler(req, res) {
99
+ async requestHandler(req, response) {
101
100
  const startTime = Date.now();
101
+ let request;
102
102
  try {
103
- const request = await this.createRequest(req);
104
- let appRequest = await this.applyMiddlewares(request, req, res);
105
- let data = await this.findController(appRequest, req, res);
103
+ request = await this.createRequest(req);
104
+ }
105
+ catch (err) {
106
+ return this.sendResponse(response, { status: 500, message: err.message }, startTime);
107
+ }
108
+ try {
109
+ let handledCors = { permitted: true, continue: true };
110
+ if (this.config.cors) {
111
+ handledCors = (0, _utils_1.handleCORS)(request, response, this.config.cors);
112
+ }
113
+ if (!handledCors.permitted) {
114
+ return this.sendResponse(response, { status: 403, message: 'CORS: Origin not allowed' }, startTime);
115
+ }
116
+ if (!handledCors.continue && handledCors.permitted) {
117
+ return this.sendResponse(response, { status: 204 }, startTime);
118
+ }
119
+ await this.beforeRequest(request, response);
120
+ let data = await this.findController(request, response);
106
121
  const isError = !_constants_1.OK_STATUSES.includes(data.status);
107
122
  if (isError) {
108
- return this.handleError(data, req, res, startTime);
123
+ return this.handleError(data, request, response, startTime);
109
124
  }
110
125
  if (this.config.interceptor) {
111
- data = await this.config.interceptor(data, req, res);
126
+ data = await this.config.interceptor(data, request, response);
112
127
  }
113
- return this.sendResponse(res, data, startTime);
128
+ return this.sendResponse(response, data, startTime);
114
129
  }
115
130
  catch (error) {
116
- return this.handleError(error, req, res, startTime);
131
+ return this.handleError(error, request, response, startTime);
117
132
  }
118
133
  }
119
134
  async createRequest(req) {
@@ -127,33 +142,33 @@ class HttpServer extends Socket_1.Socket {
127
142
  const protocol = req.headers['x-forwarded-proto'] || 'http';
128
143
  const host = req.headers.host || 'localhost';
129
144
  const fullUrl = `${protocol}://${host}${req.url}`;
130
- const whatwgUrl = new URL(fullUrl);
131
- return {
145
+ const requestUrl = new URL(fullUrl);
146
+ const parsedRequest = {
132
147
  method: req.method?.toUpperCase(),
133
- url: whatwgUrl,
148
+ requestUrl,
134
149
  headers: req.headers,
135
150
  body: parsedBody,
136
151
  rawBody: rawBody,
137
- query: (0, _utils_1.ParseQuery)(whatwgUrl),
152
+ query: (0, _utils_1.ParseQuery)(requestUrl),
138
153
  params: {},
139
154
  cookies: (0, _utils_1.ParseCookies)(req),
140
155
  isBase64Encoded: false,
141
156
  _startTime: Date.now(),
142
157
  };
158
+ Object.assign(req, parsedRequest);
159
+ return req;
143
160
  }
144
- async applyMiddlewares(appRequest, request, response) {
145
- let processed = appRequest;
161
+ async beforeRequest(request, response) {
162
+ (0, _utils_1.sanitizeRequest)(request, this.config.sanitizers ?? []);
146
163
  for (const middleware of this.config.middlewares?.reverse() || []) {
147
- const result = await middleware(processed, request, response);
148
- processed = result ?? processed;
164
+ await middleware(request, response, _utils_1.NextFN);
149
165
  }
150
- return processed;
151
166
  }
152
- async findController(appRequest, request, response) {
167
+ async findController(request, response) {
153
168
  for (const ControllerClass of this.config.controllers || []) {
154
169
  const instance = new ControllerClass();
155
170
  if (typeof instance.handleRequest === 'function') {
156
- const data = await instance.handleRequest(appRequest, request, response);
171
+ const data = await instance.handleRequest(request, response);
157
172
  if (data && data.status !== 404) {
158
173
  return data;
159
174
  }
@@ -161,7 +176,7 @@ class HttpServer extends Socket_1.Socket {
161
176
  }
162
177
  return {
163
178
  status: 404,
164
- data: { message: `Route ${appRequest.method} ${appRequest.url.pathname} not found` },
179
+ data: { message: `Route ${request.method} ${request.requestUrl.pathname} not found` },
165
180
  };
166
181
  }
167
182
  async sendResponse(res, data, startTime) {
@@ -12,6 +12,7 @@ function Server(config = {}) {
12
12
  ...config,
13
13
  controllers: [...(existingConfig.controllers || []), ...(config.controllers || [])],
14
14
  middlewares: [...(existingConfig.middlewares ?? []), ...(config.middlewares ?? [])],
15
+ cors: config.cors,
15
16
  interceptors: existingConfig.interceptor ?? config.interceptor,
16
17
  };
17
18
  Reflect.defineMetadata(_constants_1.SERVER_CONFIG_KEY, mergedConfig, target);
@@ -15,8 +15,10 @@ export declare const WS_TOPIC_KEY = "websocket:topic";
15
15
  export declare const WS_SERVICE_KEY = "websocket:service";
16
16
  export declare const INTECEPT = "server:intercept";
17
17
  export declare const CATCH = "server:catch";
18
+ export declare const SANITIZE = "action:sanitize";
18
19
  export declare const STOPPED = "\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n\u2551 \uD83D\uDC4B Server stopped \u2551\n\u2551 \uD83D\uDCCA Status: STOPPED \u2551\n\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n ";
19
20
  export declare const OK_STATUSES: number[];
20
21
  export declare const TO_VALIDATE: string[];
21
22
  export declare const STATISTIC: Record<'controllers' | 'routes', number>;
22
23
  export declare const INCREMENT_STATISTIC: (prop: "controllers" | "routes") => void;
24
+ export declare const CORS_METADATA = "cors:config";
package/dist/constants.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.INCREMENT_STATISTIC = exports.STATISTIC = exports.TO_VALIDATE = exports.OK_STATUSES = exports.STOPPED = exports.CATCH = exports.INTECEPT = exports.WS_SERVICE_KEY = exports.WS_TOPIC_KEY = exports.WS_METADATA_KEY = exports.USE_MIDDLEWARE = exports.SERVER_MODULES_KEY = exports.SERVER_CONFIG_KEY = exports.OK_METADATA_KEY = exports.ENDPOINT = exports.INTERCEPTOR = exports.CONTROLLERS = exports.MIDDLEWARES = exports.ROUTE_MIDDLEWARES = exports.ROUTE_PREFIX = exports.APP_METADATA_KEY = exports.PARAM_METADATA_KEY = void 0;
3
+ exports.CORS_METADATA = exports.INCREMENT_STATISTIC = exports.STATISTIC = exports.TO_VALIDATE = exports.OK_STATUSES = exports.STOPPED = exports.SANITIZE = exports.CATCH = exports.INTECEPT = exports.WS_SERVICE_KEY = exports.WS_TOPIC_KEY = exports.WS_METADATA_KEY = exports.USE_MIDDLEWARE = exports.SERVER_MODULES_KEY = exports.SERVER_CONFIG_KEY = exports.OK_METADATA_KEY = exports.ENDPOINT = exports.INTERCEPTOR = exports.CONTROLLERS = exports.MIDDLEWARES = exports.ROUTE_MIDDLEWARES = exports.ROUTE_PREFIX = exports.APP_METADATA_KEY = exports.PARAM_METADATA_KEY = void 0;
4
4
  exports.PARAM_METADATA_KEY = 'design:parameters';
5
5
  exports.APP_METADATA_KEY = 'app:configuration';
6
6
  exports.ROUTE_PREFIX = 'route:prefix';
@@ -18,6 +18,7 @@ exports.WS_TOPIC_KEY = 'websocket:topic';
18
18
  exports.WS_SERVICE_KEY = 'websocket:service';
19
19
  exports.INTECEPT = 'server:intercept';
20
20
  exports.CATCH = 'server:catch';
21
+ exports.SANITIZE = 'action:sanitize';
21
22
  exports.STOPPED = `
22
23
  ╔════════════════════════════════════════╗
23
24
  ║ 👋 Server stopped ║
@@ -34,3 +35,4 @@ const INCREMENT_STATISTIC = (prop) => {
34
35
  exports.STATISTIC[prop] = exports.STATISTIC[prop] + 1;
35
36
  };
36
37
  exports.INCREMENT_STATISTIC = INCREMENT_STATISTIC;
38
+ exports.CORS_METADATA = 'cors:config';
@@ -1,5 +1,5 @@
1
- import { AppRequest, ControllerClass, ControllerConfig, ControllerInstance, InterceptorCB, MiddlewareCB, RouteContext } from '../types/index.js';
2
- import { IncomingMessage, ServerResponse } from 'http';
1
+ import { AppRequest, ControllerClass, ControllerConfig, InterceptorCB, RouteContext } from '../types/index.js';
2
+ import { ServerResponse } from 'http';
3
3
  import 'reflect-metadata';
4
4
  /**
5
5
  * Class decorator to define a controller with optional configuration.
@@ -25,28 +25,9 @@ import 'reflect-metadata';
25
25
  export declare function Controller(config: string | ControllerConfig, middlewares?: Array<InterceptorCB>): <T extends ControllerClass>(constructor: T) => {
26
26
  new (...args: any[]): {
27
27
  [x: string]: any;
28
- executeControllerMethod: (controller: ControllerInstance, propertyName: string, payload: any, request?: IncomingMessage, response?: ServerResponse) => Promise<any>;
29
- getControllerMethods: (controller: ControllerInstance) => import("../types/index.js").ControllerMethods;
30
- getResponse(data: {
31
- controllerInstance: ControllerInstance;
32
- name: string;
33
- payload: any;
34
- interceptors: InterceptorCB[];
35
- request?: IncomingMessage;
36
- response?: ServerResponse;
37
- }): Promise<{
38
- status: any;
39
- data: any;
40
- }>;
41
- handleRequest: (appRequest: AppRequest, request?: IncomingMessage, response?: ServerResponse) => Promise<any>;
42
- routeWalker(context: RouteContext): Promise<any>;
43
- getAllMethods(obj: any): string[];
44
- findRouteInController(instance: any, path: string, route: string, method: string): {
45
- name: string;
46
- pathParams: Record<string, string>;
47
- priority: number;
48
- methodMiddlewares: MiddlewareCB[];
49
- methodInterceptors: InterceptorCB[];
50
- };
28
+ executeControllerMethod: (controller: import("../types/index.js").ControllerInstance, propertyName: string, request: AppRequest, response: ServerResponse) => Promise<any>;
29
+ getControllerMethods: (controller: import("../types/index.js").ControllerInstance) => import("../types/index.js").ControllerMethods;
30
+ handleRequest: (request: AppRequest, response: ServerResponse) => Promise<any>;
31
+ routeWalker(context: RouteContext, request: AppRequest, response: ServerResponse): Promise<any>;
51
32
  };
52
33
  } & T;
@@ -69,170 +69,136 @@ function Controller(config, middlewares = []) {
69
69
  constructor(...args) {
70
70
  super(...args);
71
71
  }
72
- async getResponse(data) {
73
- try {
74
- let appResponse = await this.executeControllerMethod(data.controllerInstance, data.name, data.payload, data.request, data.response);
75
- let status = appResponse.status ?? 200;
76
- const isError = !_constants_1.OK_STATUSES.includes(status);
77
- const interceptors = data.interceptors.reverse();
78
- for (let index = 0; index < interceptors?.length && !isError; index++) {
79
- const interceptor = interceptors[index];
80
- appResponse = await interceptor(appResponse, data.request, data.response);
81
- }
82
- const propertyName = data.name;
83
- const prototype = Object.getPrototypeOf(data.controllerInstance);
84
- const methodOkStatus = Reflect.getMetadata(_constants_1.OK_METADATA_KEY, data.controllerInstance, propertyName);
85
- if (methodOkStatus) {
86
- !isError && (status = methodOkStatus);
87
- }
88
- else {
89
- const classOkStatus = Reflect.getMetadata(_constants_1.OK_METADATA_KEY, prototype);
90
- !isError && classOkStatus && (status = classOkStatus);
91
- }
92
- return { status, data: appResponse };
93
- }
94
- catch (err) {
95
- throw err;
96
- }
97
- }
98
- handleRequest = async (appRequest, request, response) => {
72
+ handleRequest = async (request, response) => {
73
+ const middlewares = []
74
+ .concat(Reflect.getMetadata(_constants_1.MIDDLEWARES, proto))
75
+ .concat(Reflect.getMetadata(_constants_1.USE_MIDDLEWARE, constructor))
76
+ .filter((el) => !!el);
99
77
  const context = {
100
78
  controllerInstance: this,
101
79
  controllerMeta: {
102
80
  routePrefix: Reflect.getMetadata(_constants_1.ROUTE_PREFIX, proto) || '',
103
- middlewares: Reflect.getMetadata(_constants_1.MIDDLEWARES, proto) || [],
81
+ middlewares,
104
82
  interceptor: Reflect.getMetadata(_constants_1.INTERCEPTOR, proto),
105
83
  subControllers: Reflect.getMetadata(_constants_1.CONTROLLERS, proto) || [],
106
- errorHandler: Reflect.getMetadata(_constants_1.CATCH, proto),
84
+ errorHandler: Reflect.getMetadata(_constants_1.CATCH, constructor),
85
+ cors: Reflect.getMetadata(_constants_1.CORS_METADATA, proto),
86
+ sanitizers: Reflect.getMetadata(_constants_1.SANITIZE, proto) || [],
107
87
  },
108
- path: (appRequest.url.pathname ?? '').replace(/^\/+/g, ''),
109
- method: appRequest.method.toUpperCase(),
110
- appRequest,
111
- request,
112
- response,
88
+ path: (request.requestUrl.pathname ?? '').replace(/^\/+/g, ''),
89
+ method: request.method.toUpperCase(),
113
90
  middlewareChain: [],
114
91
  interceptorChain: [],
92
+ sanitizersChain: [],
93
+ corsChain: [Reflect.getMetadata(_constants_1.CORS_METADATA, proto)],
115
94
  errorHandlerChain: [Reflect.getMetadata(_constants_1.CATCH, proto)],
116
95
  subPath: Reflect.getMetadata(_constants_1.ROUTE_PREFIX, proto) || '',
117
96
  };
118
- const result = await this.routeWalker(context);
97
+ const result = await this.routeWalker(context, request, response);
119
98
  return result || { status: 404, message: 'Method Not Found' };
120
99
  };
121
- async routeWalker(context) {
100
+ async routeWalker(context, request, response) {
122
101
  const { controllerInstance, controllerMeta, path, method, subPath } = context;
123
102
  for (const SubController of controllerMeta.subControllers) {
124
103
  const subInstance = new SubController();
104
+ const middlewares = []
105
+ .concat(Reflect.getMetadata(_constants_1.MIDDLEWARES, SubController.prototype))
106
+ .concat(Reflect.getMetadata(_constants_1.USE_MIDDLEWARE, SubController))
107
+ .filter((el) => !!el);
108
+ const sanitizers = []
109
+ .concat(Reflect.getMetadata(_constants_1.SANITIZE, SubController.prototype))
110
+ .concat(Reflect.getMetadata(_constants_1.SANITIZE, SubController))
111
+ .filter((el) => !!el);
125
112
  const subMeta = {
126
113
  routePrefix: Reflect.getMetadata(_constants_1.ROUTE_PREFIX, SubController.prototype) || '',
127
- middlewares: Reflect.getMetadata(_constants_1.MIDDLEWARES, SubController.prototype) || [],
114
+ middlewares,
128
115
  interceptor: Reflect.getMetadata(_constants_1.INTERCEPTOR, SubController.prototype),
129
116
  errorHandler: Reflect.getMetadata(_constants_1.CATCH, SubController),
130
117
  subControllers: Reflect.getMetadata(_constants_1.CONTROLLERS, SubController.prototype) || [],
118
+ cors: Reflect.getMetadata(_constants_1.CORS_METADATA, SubController.prototype) || [],
119
+ sanitizers,
131
120
  };
132
121
  const fullSubPath = [subPath, subMeta.routePrefix]
133
122
  .filter(Boolean)
134
123
  .join('/')
135
124
  .replace(/\/+/g, '/');
136
125
  if (path.startsWith(fullSubPath)) {
137
- const subResult = await this.routeWalker({
126
+ const walkerData = {
138
127
  ...context,
139
128
  subPath: fullSubPath,
140
129
  controllerInstance: subInstance,
141
130
  controllerMeta: subMeta,
142
131
  path,
143
132
  middlewareChain: [...context.middlewareChain, ...controllerMeta.middlewares],
133
+ sanitizersChain: [...context.sanitizersChain, ...controllerMeta.sanitizers],
144
134
  errorHandlerChain: [...context.errorHandlerChain, subMeta.errorHandler].filter((el) => !!el),
145
135
  interceptorChain: [...context.interceptorChain, controllerMeta.interceptor].filter((el) => !!el),
146
- });
136
+ corsChain: [...context.corsChain, subMeta.cors].filter((el) => !!el),
137
+ };
138
+ const subResult = await this.routeWalker(walkerData, request, response);
147
139
  if (subResult && subResult.status !== 404) {
148
140
  return subResult;
149
141
  }
150
142
  }
151
143
  }
152
- const routeMatch = this.findRouteInController(controllerInstance, subPath, path, method);
153
- if (routeMatch) {
154
- const { name, pathParams, methodMiddlewares, methodInterceptors } = routeMatch;
155
- const allMiddlewares = [
156
- ...context.middlewareChain,
157
- ...controllerMeta.middlewares,
158
- ...methodMiddlewares,
159
- ];
160
- let payload = { ...context.appRequest, params: pathParams };
161
- for (const mw of allMiddlewares) {
162
- const mwResult = await mw(payload, context.request, context.response);
163
- payload = mwResult ?? payload;
164
- }
165
- let apiResponse = await this.getResponse({
166
- interceptors: [...context.interceptorChain, controllerMeta.interceptor].filter((el) => !!el),
167
- controllerInstance,
168
- name,
169
- payload,
170
- response: context.response,
171
- request: context.request,
172
- }).catch((err) => err);
173
- const isError = !_constants_1.OK_STATUSES.includes(apiResponse.status);
174
- if (isError) {
175
- for (const handler of context.errorHandlerChain?.reverse() || []) {
176
- apiResponse = handler(apiResponse);
144
+ const routeMatch = (0, _utils_1.findRouteInController)(controllerInstance, subPath, path, method);
145
+ try {
146
+ if (routeMatch) {
147
+ const { name, pathParams, middlewares, cors, sanitizers } = routeMatch;
148
+ Object.assign(request, { params: pathParams });
149
+ const handledCors = context.corsChain
150
+ .concat(cors ?? [])
151
+ .flat()
152
+ .reduce((acc, conf) => {
153
+ const cors = (0, _utils_1.handleCORS)(request, response, conf);
154
+ return {
155
+ permitted: acc.permitted && cors.permitted,
156
+ continue: acc.continue && cors.continue,
157
+ };
158
+ }, { permitted: true, continue: true });
159
+ if (!handledCors.permitted) {
160
+ return { status: 403, message: 'Cors: Origin not allowed' };
177
161
  }
178
- }
179
- return apiResponse;
180
- }
181
- return null;
182
- }
183
- getAllMethods(obj) {
184
- let methods = new Set();
185
- let current = Object.getPrototypeOf(obj);
186
- while (current && current !== Object.prototype) {
187
- Object.getOwnPropertyNames(current).forEach((name) => {
188
- if (name !== 'constructor' && typeof current[name] === 'function') {
189
- methods.add(name);
162
+ if (!handledCors.continue && handledCors.permitted) {
163
+ return { status: 204 };
190
164
  }
191
- });
192
- current = Object.getPrototypeOf(current);
193
- }
194
- return Array.from(methods);
195
- }
196
- findRouteInController(instance, path, route, method) {
197
- const prototype = Object.getPrototypeOf(instance);
198
- const propertyNames = this.getAllMethods(instance);
199
- const matches = [];
200
- for (const name of propertyNames) {
201
- if ([
202
- 'constructor',
203
- 'getResponse',
204
- 'routeWalker',
205
- 'getAllMethods',
206
- 'findRouteInController',
207
- ].includes(name))
208
- continue;
209
- const endpointMeta = Reflect.getMetadata(_constants_1.ENDPOINT, prototype, name) || [];
210
- if (endpointMeta.length === 0)
211
- continue;
212
- const [httpMethod, routePattern] = endpointMeta;
213
- if (httpMethod !== method && httpMethod !== 'USE') {
214
- continue;
215
- }
216
- if (httpMethod === 'USE') {
217
- let useRoute = route.split('/');
218
- useRoute.pop();
219
- route = useRoute.join('/');
220
- }
221
- const current = [path, routePattern].join('/').replace(/\/+/g, '/');
222
- const pathParams = (0, _utils_1.matchRoute)(current, route);
223
- if (pathParams) {
224
- const priority = httpMethod === 'USE' ? 0 : Object.keys(pathParams).length > 0 ? 1 : 2;
225
- matches.push({
226
- name,
227
- pathParams,
228
- priority,
229
- methodMiddlewares: Reflect.getMetadata(_constants_1.MIDDLEWARES, prototype, name) || [],
230
- methodInterceptors: Reflect.getMetadata(_constants_1.INTERCEPTOR, prototype, name) || [],
165
+ const controllerMiddlewares = [
166
+ ...context.middlewareChain,
167
+ ...controllerMeta.middlewares,
168
+ ];
169
+ const controllerSanitizers = [
170
+ ...context.sanitizersChain,
171
+ ...controllerMeta.sanitizers,
172
+ ].filter((el) => !!el);
173
+ await (0, _utils_1.applyMiddlewaresVsSanitizers)(request, response, {
174
+ sanitizers: [controllerSanitizers, sanitizers],
175
+ middlewares: [controllerMiddlewares, middlewares],
231
176
  });
177
+ let apiResponse = await (0, _utils_1.getResponse)({
178
+ interceptors: [...context.interceptorChain, controllerMeta.interceptor].filter((el) => !!el),
179
+ controllerInstance,
180
+ name,
181
+ response: response,
182
+ request: request,
183
+ }).catch((err) => err);
184
+ const isError = !_constants_1.OK_STATUSES.includes(apiResponse.status);
185
+ if (isError) {
186
+ for (const handler of context.errorHandlerChain?.reverse() || []) {
187
+ apiResponse = handler(apiResponse, request, response);
188
+ }
189
+ }
190
+ return apiResponse;
232
191
  }
233
192
  }
234
- matches.sort((a, b) => b.priority - a.priority);
235
- return matches[0] || null;
193
+ catch (errror) {
194
+ let data = { status: 500, ...errror };
195
+ for (const handler of context.errorHandlerChain?.reverse() || []) {
196
+ const res = await handler(errror, request, response);
197
+ Object.assign(data, res);
198
+ }
199
+ return data;
200
+ }
201
+ return null;
236
202
  }
237
203
  };
238
204
  };
@@ -27,8 +27,7 @@ function Endpoint(method, pathPattern, middlewares) {
27
27
  return descriptor;
28
28
  }
29
29
  if (method && pathPattern) {
30
- Reflect.defineMetadata(_constants_1.ENDPOINT, [method, pathPattern], target, propertyKey);
31
- Reflect.defineMetadata('middlewares', middlewares || [], target, propertyKey);
30
+ Reflect.defineMetadata(_constants_1.ENDPOINT, [method, pathPattern, middlewares], target, propertyKey);
32
31
  }
33
32
  (0, _constants_1.INCREMENT_STATISTIC)('routes');
34
33
  return descriptor;
@@ -4,7 +4,7 @@
4
4
  * This module provides centralized exports for controller and endpoint decorators,
5
5
  * as well as related types and utility functions used throughout the core framework.
6
6
  */
7
- export { AppRequest, EndpointResponse, ErrorCB, HttpError, IController, InterceptorCB, IWebSocketService, MiddlewareCB, ResponseWithStatus, Router, WebSocketClient, WebSocketEvent, WebSocketMessage, } from '../types/index.js';
7
+ export { AppRequest, CORSConfig, EndpointResponse, ErrorCB, HttpError, IController, InterceptorCB, IWebSocketService, MiddlewareCB, MultipartFile, ResponseWithStatus, WebSocketClient, WebSocketEvent, WebSocketMessage, } from '../types/index.js';
8
8
  export * from './Controller';
9
9
  export * from './Endpoint';
10
10
  export * from './utils';
@@ -1,4 +1,2 @@
1
1
  export * from './extractors';
2
- export * from './helpers';
3
- export * from './middlewares';
4
2
  export * from './websocket';
@@ -15,6 +15,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./extractors"), exports);
18
- __exportStar(require("./helpers"), exports);
19
- __exportStar(require("./middlewares"), exports);
20
18
  __exportStar(require("./websocket"), exports);
@@ -1,4 +1,3 @@
1
- import 'reflect-metadata';
2
1
  export declare class Root {
3
2
  }
4
3
  export declare class App {
@@ -1,21 +1,75 @@
1
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
2
18
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
19
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
20
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
21
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
22
  return c > 3 && r && Object.defineProperty(target, key, r), r;
7
23
  };
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
8
41
  Object.defineProperty(exports, "__esModule", { value: true });
9
42
  exports.App = exports.Root = void 0;
43
+ const Joi = __importStar(require("joi"));
10
44
  const core_1 = require("quantum-flow/core");
11
45
  const http_1 = require("quantum-flow/http");
12
- require("reflect-metadata");
46
+ const middlewares_1 = require("quantum-flow/middlewares");
13
47
  const user_1 = require("./controllers/user");
14
48
  let Root = class Root {
15
49
  };
16
50
  exports.Root = Root;
17
51
  exports.Root = Root = __decorate([
18
- (0, core_1.Controller)({ prefix: 'api', controllers: [user_1.User] })
52
+ (0, core_1.Controller)({
53
+ prefix: 'api',
54
+ controllers: [user_1.User],
55
+ middlewares: [function Global(req, res, next) { }],
56
+ }),
57
+ (0, middlewares_1.Cors)({ origin: '*' }),
58
+ (0, middlewares_1.Use)(function Global1(req, res, next) {
59
+ return next();
60
+ }),
61
+ (0, middlewares_1.Catch)(function GLOBALCATCH(err) {
62
+ return { status: 400 };
63
+ }),
64
+ (0, middlewares_1.Sanitize)({
65
+ schema: Joi.object({
66
+ name: Joi.string().trim().min(2).max(50).required(),
67
+ }),
68
+ action: 'both',
69
+ options: { abortEarly: false },
70
+ stripUnknown: true,
71
+ type: 'body',
72
+ })
19
73
  ], Root);
20
74
  let App = class App {
21
75
  };
@@ -26,9 +80,20 @@ exports.App = App = __decorate([
26
80
  websocket: { enabled: true },
27
81
  interceptor: (data) => data,
28
82
  errorHandler: (err) => err,
83
+ cors: { origin: '*' },
84
+ middlewares: [() => { }, () => { }],
29
85
  }),
30
86
  (0, http_1.Port)(3000),
31
- (0, core_1.Use)((data) => data),
32
- (0, core_1.Use)((data) => data),
33
- (0, core_1.Catch)((err) => err)
87
+ (0, middlewares_1.Use)(() => { }),
88
+ (0, middlewares_1.Use)([() => { }, () => { }]),
89
+ (0, middlewares_1.Catch)((err) => err),
90
+ (0, middlewares_1.Sanitize)({
91
+ schema: Joi.object({
92
+ name: Joi.string().trim().min(2).max(50).required(),
93
+ }),
94
+ action: 'both',
95
+ options: { abortEarly: false },
96
+ stripUnknown: true,
97
+ type: 'headers',
98
+ })
34
99
  ], App);