quantum-flow 1.3.2 → 1.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/app/http/Application.js +8 -6
- package/dist/core/Controller.d.ts +3 -3
- package/dist/core/Controller.js +12 -9
- package/dist/core/utils/extractors.d.ts +2 -2
- package/dist/core/utils/extractors.js +2 -2
- package/dist/examples/controllers/user.js +5 -3
- package/dist/examples/controllers/userMetadata.js +11 -2
- package/dist/examples/server.js +8 -3
- package/dist/types/common.d.ts +11 -2
- package/dist/types/controller.d.ts +1 -0
- package/dist/utils/controller.js +2 -2
- package/dist/utils/endpoint.js +0 -1
- package/package.json +1 -1
- package/dist/validators/Validate.d.ts +0 -3
- package/dist/validators/Validate.js +0 -40
- package/dist/validators/index.d.ts +0 -1
- package/dist/validators/index.js +0 -17
package/README.md
CHANGED
|
@@ -66,7 +66,7 @@ export class User {
|
|
|
66
66
|
@Body(UserDto) body: UserDto,
|
|
67
67
|
@Query() query: any,
|
|
68
68
|
@Headers() headers: any,
|
|
69
|
-
@Params() params: any,
|
|
69
|
+
@Params(ParamDTO, 'param') params: any,
|
|
70
70
|
@Request() req: any,
|
|
71
71
|
@Response() resp: any,
|
|
72
72
|
@InjectWS() ws: IWebSocketService,
|
|
@@ -36,7 +36,7 @@ class HttpServer extends Socket_1.Socket {
|
|
|
36
36
|
║ 🔌 Port: ${this.config.port}
|
|
37
37
|
║ 🔌 Websocket: ${!!this.config.websocket}
|
|
38
38
|
║ 🔧 Global Middlewares: ${this.config.middlewares?.length || 0}
|
|
39
|
-
║ 🔧 Error
|
|
39
|
+
║ 🔧 Error handler: ${!this.config.errorHandler}
|
|
40
40
|
║ 🎯 Global Interceptors: ${!!this.config.interceptor?.length}
|
|
41
41
|
║ 📦 Controllers: ${_constants_1.STATISTIC.controllers}
|
|
42
42
|
║ 📦 Routes: ${_constants_1.STATISTIC.routes}
|
|
@@ -103,13 +103,17 @@ class HttpServer extends Socket_1.Socket {
|
|
|
103
103
|
const request = await this.createRequest(req);
|
|
104
104
|
let appRequest = await this.applyMiddlewares(request, req, res);
|
|
105
105
|
let data = await this.findController(appRequest, req, res);
|
|
106
|
+
const isError = !_constants_1.OK_STATUSES.includes(data.status);
|
|
107
|
+
if (isError) {
|
|
108
|
+
return this.handleError(data, req, res, startTime);
|
|
109
|
+
}
|
|
106
110
|
if (this.config.interceptor) {
|
|
107
111
|
data = await this.config.interceptor(data, req, res);
|
|
108
112
|
}
|
|
109
|
-
|
|
113
|
+
return this.sendResponse(res, data, startTime);
|
|
110
114
|
}
|
|
111
115
|
catch (error) {
|
|
112
|
-
|
|
116
|
+
return this.handleError(error, req, res, startTime);
|
|
113
117
|
}
|
|
114
118
|
}
|
|
115
119
|
async createRequest(req) {
|
|
@@ -141,9 +145,7 @@ class HttpServer extends Socket_1.Socket {
|
|
|
141
145
|
let processed = appRequest;
|
|
142
146
|
for (const middleware of this.config.middlewares?.reverse() || []) {
|
|
143
147
|
const result = await middleware(processed, request, response);
|
|
144
|
-
|
|
145
|
-
processed = result;
|
|
146
|
-
}
|
|
148
|
+
processed = result ?? processed;
|
|
147
149
|
}
|
|
148
150
|
return processed;
|
|
149
151
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AppRequest, ControllerClass, ControllerConfig, ControllerInstance, InterceptorCB, RouteContext } from '../types/index.js';
|
|
1
|
+
import { AppRequest, ControllerClass, ControllerConfig, ControllerInstance, InterceptorCB, MiddlewareCB, RouteContext } from '../types/index.js';
|
|
2
2
|
import { IncomingMessage, ServerResponse } from 'http';
|
|
3
3
|
import 'reflect-metadata';
|
|
4
4
|
/**
|
|
@@ -45,8 +45,8 @@ export declare function Controller(config: string | ControllerConfig, middleware
|
|
|
45
45
|
name: string;
|
|
46
46
|
pathParams: Record<string, string>;
|
|
47
47
|
priority: number;
|
|
48
|
-
methodMiddlewares:
|
|
49
|
-
methodInterceptors:
|
|
48
|
+
methodMiddlewares: MiddlewareCB[];
|
|
49
|
+
methodInterceptors: InterceptorCB[];
|
|
50
50
|
};
|
|
51
51
|
};
|
|
52
52
|
} & T;
|
package/dist/core/Controller.js
CHANGED
|
@@ -92,7 +92,6 @@ function Controller(config, middlewares = []) {
|
|
|
92
92
|
return { status, data: appResponse };
|
|
93
93
|
}
|
|
94
94
|
catch (err) {
|
|
95
|
-
console.error(err);
|
|
96
95
|
throw err;
|
|
97
96
|
}
|
|
98
97
|
}
|
|
@@ -113,6 +112,7 @@ function Controller(config, middlewares = []) {
|
|
|
113
112
|
response,
|
|
114
113
|
middlewareChain: [],
|
|
115
114
|
interceptorChain: [],
|
|
115
|
+
errorHandlerChain: [Reflect.getMetadata(_constants_1.CATCH, proto)],
|
|
116
116
|
subPath: Reflect.getMetadata(_constants_1.ROUTE_PREFIX, proto) || '',
|
|
117
117
|
};
|
|
118
118
|
const result = await this.routeWalker(context);
|
|
@@ -126,7 +126,7 @@ function Controller(config, middlewares = []) {
|
|
|
126
126
|
routePrefix: Reflect.getMetadata(_constants_1.ROUTE_PREFIX, SubController.prototype) || '',
|
|
127
127
|
middlewares: Reflect.getMetadata(_constants_1.MIDDLEWARES, SubController.prototype) || [],
|
|
128
128
|
interceptor: Reflect.getMetadata(_constants_1.INTERCEPTOR, SubController.prototype),
|
|
129
|
-
errorHandler: Reflect.getMetadata(_constants_1.CATCH, SubController
|
|
129
|
+
errorHandler: Reflect.getMetadata(_constants_1.CATCH, SubController),
|
|
130
130
|
subControllers: Reflect.getMetadata(_constants_1.CONTROLLERS, SubController.prototype) || [],
|
|
131
131
|
};
|
|
132
132
|
const fullSubPath = [subPath, subMeta.routePrefix]
|
|
@@ -141,6 +141,7 @@ function Controller(config, middlewares = []) {
|
|
|
141
141
|
controllerMeta: subMeta,
|
|
142
142
|
path,
|
|
143
143
|
middlewareChain: [...context.middlewareChain, ...controllerMeta.middlewares],
|
|
144
|
+
errorHandlerChain: [...context.errorHandlerChain, subMeta.errorHandler].filter((el) => !!el),
|
|
144
145
|
interceptorChain: [...context.interceptorChain, controllerMeta.interceptor].filter((el) => !!el),
|
|
145
146
|
});
|
|
146
147
|
if (subResult && subResult.status !== 404) {
|
|
@@ -159,21 +160,23 @@ function Controller(config, middlewares = []) {
|
|
|
159
160
|
let payload = { ...context.appRequest, params: pathParams };
|
|
160
161
|
for (const mw of allMiddlewares) {
|
|
161
162
|
const mwResult = await mw(payload, context.request, context.response);
|
|
162
|
-
payload =
|
|
163
|
+
payload = mwResult ?? payload;
|
|
163
164
|
}
|
|
164
|
-
|
|
165
|
+
let apiResponse = await this.getResponse({
|
|
165
166
|
interceptors: [...context.interceptorChain, controllerMeta.interceptor].filter((el) => !!el),
|
|
166
167
|
controllerInstance,
|
|
167
168
|
name,
|
|
168
169
|
payload,
|
|
169
170
|
response: context.response,
|
|
170
171
|
request: context.request,
|
|
171
|
-
}).catch((
|
|
172
|
-
|
|
173
|
-
|
|
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);
|
|
174
177
|
}
|
|
175
|
-
|
|
176
|
-
|
|
178
|
+
}
|
|
179
|
+
return apiResponse;
|
|
177
180
|
}
|
|
178
181
|
return null;
|
|
179
182
|
}
|
|
@@ -7,12 +7,12 @@ export declare const Body: (dto?: any) => (target: any, propertyKey: string | sy
|
|
|
7
7
|
* Parameter decorator to extract route parameters.
|
|
8
8
|
* @param name Optional name of the parameter to extract.
|
|
9
9
|
*/
|
|
10
|
-
export declare const Params: (name?: string) => (target: any, propertyKey: string | symbol, parameterIndex: number) => void;
|
|
10
|
+
export declare const Params: (dto?: any, name?: string) => (target: any, propertyKey: string | symbol, parameterIndex: number) => void;
|
|
11
11
|
/**
|
|
12
12
|
* Parameter decorator to extract query parameters.
|
|
13
13
|
* @param name Optional name of the query parameter to extract.
|
|
14
14
|
*/
|
|
15
|
-
export declare const Query: (name?: string) => (target: any, propertyKey: string | symbol, parameterIndex: number) => void;
|
|
15
|
+
export declare const Query: (dto?: any, name?: string) => (target: any, propertyKey: string | symbol, parameterIndex: number) => void;
|
|
16
16
|
/**
|
|
17
17
|
* Parameter decorator to inject the entire request object.
|
|
18
18
|
*/
|
|
@@ -12,13 +12,13 @@ exports.Body = Body;
|
|
|
12
12
|
* Parameter decorator to extract route parameters.
|
|
13
13
|
* @param name Optional name of the parameter to extract.
|
|
14
14
|
*/
|
|
15
|
-
const Params = (name) => (0, _utils_1.createParamDecorator)('params', undefined, name);
|
|
15
|
+
const Params = (dto, name) => (0, _utils_1.createParamDecorator)('params', typeof dto == 'string' ? undefined : dto, typeof dto == 'string' ? dto : name);
|
|
16
16
|
exports.Params = Params;
|
|
17
17
|
/**
|
|
18
18
|
* Parameter decorator to extract query parameters.
|
|
19
19
|
* @param name Optional name of the query parameter to extract.
|
|
20
20
|
*/
|
|
21
|
-
const Query = (name) => (0, _utils_1.createParamDecorator)('query', undefined, name);
|
|
21
|
+
const Query = (dto, name) => (0, _utils_1.createParamDecorator)('query', typeof dto == 'string' ? undefined : dto, typeof dto == 'string' ? dto : name);
|
|
22
22
|
exports.Query = Query;
|
|
23
23
|
/**
|
|
24
24
|
* Parameter decorator to inject the entire request object.
|
|
@@ -59,11 +59,13 @@ exports.User = User = __decorate([
|
|
|
59
59
|
(0, core_1.Controller)({
|
|
60
60
|
prefix: 'user',
|
|
61
61
|
controllers: [userMetadata_1.UserMetadata],
|
|
62
|
+
middlewares: [
|
|
63
|
+
(req) => {
|
|
64
|
+
return req;
|
|
65
|
+
},
|
|
66
|
+
],
|
|
62
67
|
interceptor: (data, req, res) => {
|
|
63
68
|
return { data, intercepted: true };
|
|
64
69
|
},
|
|
65
|
-
}),
|
|
66
|
-
(0, core_1.Catch)((err) => {
|
|
67
|
-
return { status: 401, err };
|
|
68
70
|
})
|
|
69
71
|
], User);
|
|
@@ -13,7 +13,16 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.UserMetadata = void 0;
|
|
16
|
+
const class_validator_1 = require("class-validator");
|
|
16
17
|
const core_1 = require("quantum-flow/core");
|
|
18
|
+
class DTO {
|
|
19
|
+
constructor() { }
|
|
20
|
+
meta;
|
|
21
|
+
}
|
|
22
|
+
__decorate([
|
|
23
|
+
(0, class_validator_1.IsString)(),
|
|
24
|
+
__metadata("design:type", String)
|
|
25
|
+
], DTO.prototype, "meta", void 0);
|
|
17
26
|
let UserMetadata = class UserMetadata {
|
|
18
27
|
async getUserMetadata(params) {
|
|
19
28
|
return params;
|
|
@@ -21,8 +30,8 @@ let UserMetadata = class UserMetadata {
|
|
|
21
30
|
};
|
|
22
31
|
exports.UserMetadata = UserMetadata;
|
|
23
32
|
__decorate([
|
|
24
|
-
(0, core_1.GET)('/:
|
|
25
|
-
__param(0, (0, core_1.Params)()),
|
|
33
|
+
(0, core_1.GET)('/:meta'),
|
|
34
|
+
__param(0, (0, core_1.Params)(DTO, 'meta')),
|
|
26
35
|
__metadata("design:type", Function),
|
|
27
36
|
__metadata("design:paramtypes", [Object]),
|
|
28
37
|
__metadata("design:returntype", Promise)
|
package/dist/examples/server.js
CHANGED
|
@@ -15,18 +15,23 @@ let Root = class Root {
|
|
|
15
15
|
Root = __decorate([
|
|
16
16
|
(0, core_1.Controller)({ prefix: 'api', controllers: [user_1.User] })
|
|
17
17
|
], Root);
|
|
18
|
-
let App =
|
|
18
|
+
let App =
|
|
19
|
+
// @Catch((error) => ({ status: 400, error }))
|
|
20
|
+
class App {
|
|
19
21
|
};
|
|
20
22
|
App = __decorate([
|
|
21
23
|
(0, http_1.Server)({
|
|
22
24
|
controllers: [Root],
|
|
23
25
|
websocket: { enabled: true },
|
|
24
26
|
interceptor: (data) => data,
|
|
27
|
+
errorHandler: (err) => {
|
|
28
|
+
return err;
|
|
29
|
+
},
|
|
25
30
|
}),
|
|
26
31
|
(0, http_1.Port)(3000),
|
|
27
32
|
(0, core_1.Use)((data) => data),
|
|
28
|
-
(0, core_1.Use)((data) => data)
|
|
29
|
-
|
|
33
|
+
(0, core_1.Use)((data) => data)
|
|
34
|
+
// @Catch((error) => ({ status: 400, error }))
|
|
30
35
|
], App);
|
|
31
36
|
const server = new http_1.HttpServer(App);
|
|
32
37
|
server.listen().catch(console.error);
|
package/dist/types/common.d.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { IncomingHttpHeaders, IncomingMessage, ServerResponse } from 'http';
|
|
2
2
|
type P_Q = Record<string, string | undefined> | null | unknown;
|
|
3
|
+
export interface HttpError extends Error {
|
|
4
|
+
statusCode?: number;
|
|
5
|
+
status: number;
|
|
6
|
+
data?: any;
|
|
7
|
+
messages?: string[];
|
|
8
|
+
errors?: Array<{
|
|
9
|
+
message: string;
|
|
10
|
+
}>;
|
|
11
|
+
}
|
|
3
12
|
export type AppRequest<B = unknown, Q extends P_Q = unknown, P extends P_Q = unknown> = {
|
|
4
13
|
method: HTTP_METHODS;
|
|
5
14
|
url: URL;
|
|
@@ -38,9 +47,9 @@ export type AxiosQuery = {
|
|
|
38
47
|
export interface IController {
|
|
39
48
|
handleRequest: Router;
|
|
40
49
|
}
|
|
41
|
-
export type MiddlewareCB = (appRequest: AppRequest, request?: IncomingMessage,
|
|
50
|
+
export type MiddlewareCB = (appRequest: AppRequest, request?: IncomingMessage, response?: ServerResponse) => void | Promise<AppRequest> | AppRequest;
|
|
42
51
|
export type InterceptorCB = (data: any, req?: IncomingMessage, res?: ServerResponse) => Promise<unknown> | unknown;
|
|
43
|
-
export type ErrorCB = (error:
|
|
52
|
+
export type ErrorCB = (error: HttpError, req?: IncomingMessage, res?: ServerResponse) => Promise<ResponseWithStatus> | ResponseWithStatus;
|
|
44
53
|
export type ParamDecoratorType = 'body' | 'params' | 'query' | 'request' | 'headers' | 'cookies' | 'response' | 'multipart' | 'event' | 'context';
|
|
45
54
|
export interface ParamMetadata {
|
|
46
55
|
index: number;
|
package/dist/utils/controller.js
CHANGED
|
@@ -43,10 +43,10 @@ const executeControllerMethod = async (controller, propertyName, payload, reques
|
|
|
43
43
|
}
|
|
44
44
|
const prototype = Object.getPrototypeOf(controller);
|
|
45
45
|
const paramMetadata = Reflect.getMetadata(_constants_1.PARAM_METADATA_KEY, prototype, propertyName) || [];
|
|
46
|
-
const { body, multipart } = getBodyAndMultipart(payload);
|
|
47
46
|
if (paramMetadata.length === 0) {
|
|
48
47
|
return fn.call(controller, payload);
|
|
49
48
|
}
|
|
49
|
+
const { body, multipart } = getBodyAndMultipart(payload);
|
|
50
50
|
const args = [];
|
|
51
51
|
const wsParams = Reflect.getMetadata(_constants_1.WS_SERVICE_KEY, controller, propertyName) || [];
|
|
52
52
|
const totalParams = Math.max(paramMetadata.length ? Math.max(...paramMetadata.map((p) => p.index)) + 1 : 0, wsParams.length ? Math.max(...wsParams.map((p) => p.index)) + 1 : 0);
|
|
@@ -78,7 +78,7 @@ const executeControllerMethod = async (controller, propertyName, payload, reques
|
|
|
78
78
|
value = response;
|
|
79
79
|
}
|
|
80
80
|
if (_constants_1.TO_VALIDATE.includes(param.type)) {
|
|
81
|
-
value = await (0, validate_1.validate)(param.dto, value);
|
|
81
|
+
value = await (0, validate_1.validate)(param.dto, typeof value === 'string' ? { [param.name ?? '']: value } : value);
|
|
82
82
|
}
|
|
83
83
|
args[i] = value;
|
|
84
84
|
}
|
package/dist/utils/endpoint.js
CHANGED
|
@@ -8,6 +8,5 @@ function createParamDecorator(type, dto, name) {
|
|
|
8
8
|
existingParams.push({ index: parameterIndex, type, dto, name });
|
|
9
9
|
existingParams.sort((a, b) => a.index - b.index);
|
|
10
10
|
Reflect.defineMetadata(_constants_1.PARAM_METADATA_KEY, existingParams, target, propertyKey);
|
|
11
|
-
const saved = Reflect.getMetadata(_constants_1.PARAM_METADATA_KEY, target, propertyKey);
|
|
12
11
|
};
|
|
13
12
|
}
|
package/package.json
CHANGED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Validate = Validate;
|
|
4
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
5
|
-
const class_validator_1 = require("class-validator");
|
|
6
|
-
function Validate(param, dtoClass) {
|
|
7
|
-
return function (target, propertyKey, descriptor) {
|
|
8
|
-
// METHOD DECORATOR
|
|
9
|
-
if (descriptor) {
|
|
10
|
-
wrapMethod(descriptor, param, dtoClass);
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
// CLASS DECORATOR
|
|
14
|
-
const prototype = target.prototype;
|
|
15
|
-
Object.getOwnPropertyNames(prototype).forEach((method) => {
|
|
16
|
-
if (method === 'constructor')
|
|
17
|
-
return;
|
|
18
|
-
const desc = Object.getOwnPropertyDescriptor(prototype, method);
|
|
19
|
-
if (!desc || typeof desc.value !== 'function')
|
|
20
|
-
return;
|
|
21
|
-
wrapMethod(desc, param, dtoClass);
|
|
22
|
-
Object.defineProperty(prototype, method, desc);
|
|
23
|
-
});
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
function wrapMethod(descriptor, param, dtoClass) {
|
|
27
|
-
const originalMethod = descriptor.value;
|
|
28
|
-
descriptor.value = async function (...args) {
|
|
29
|
-
const value = args[0][param];
|
|
30
|
-
const instance = new dtoClass();
|
|
31
|
-
Object.entries(value || {}).forEach(([key, val]) => {
|
|
32
|
-
instance[key] = val;
|
|
33
|
-
});
|
|
34
|
-
const errors = await (0, class_validator_1.validate)(instance, { whitelist: true });
|
|
35
|
-
if (errors.length) {
|
|
36
|
-
throw { status: 422, message: 'Validation failed', data: errors };
|
|
37
|
-
}
|
|
38
|
-
return originalMethod.apply(this, args);
|
|
39
|
-
};
|
|
40
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './Validate';
|
package/dist/validators/index.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
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("./Validate"), exports);
|