framework-do-dede 3.4.0 → 4.0.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.
- package/README.md +77 -14
- package/dist/application/controller.d.ts +6 -2
- package/dist/application/controller.js +10 -18
- package/dist/application/index.d.ts +1 -1
- package/dist/application/index.js +1 -1
- package/dist/application/services.d.ts +2 -1
- package/dist/application/services.js +3 -3
- package/dist/dede.d.ts +10 -1
- package/dist/dede.js +30 -9
- package/dist/domain/entity.d.ts +4 -0
- package/dist/domain/entity.js +25 -0
- package/dist/domain/errors/app-error.d.ts +12 -0
- package/dist/domain/errors/app-error.js +14 -0
- package/dist/domain/errors/http-errors.d.ts +42 -0
- package/dist/domain/errors/http-errors.js +40 -0
- package/dist/domain/index.d.ts +2 -0
- package/dist/domain/index.js +2 -0
- package/dist/http/controller.handler.d.ts +4 -5
- package/dist/http/controller.handler.js +27 -119
- package/dist/http/errors/server.d.ts +2 -28
- package/dist/http/errors/server.js +2 -49
- package/dist/http/http-server.d.ts +2 -0
- package/dist/http/http-server.js +1 -1
- package/dist/http/index.d.ts +2 -2
- package/dist/http/index.js +2 -2
- package/dist/index.d.ts +4 -3
- package/dist/index.js +4 -3
- package/dist/infra/di/registry.d.ts +4 -6
- package/dist/infra/di/registry.js +8 -10
- package/dist/{application → infra/serialization}/entity.d.ts +3 -1
- package/dist/{application → infra/serialization}/entity.js +7 -25
- package/dist/interface/errors/http-error-mapper.d.ts +10 -0
- package/dist/interface/errors/http-error-mapper.js +31 -0
- package/dist/interface/http/middleware-executor.d.ts +10 -0
- package/dist/interface/http/middleware-executor.js +33 -0
- package/dist/interface/http/request-mapper.d.ts +21 -0
- package/dist/interface/http/request-mapper.js +55 -0
- package/dist/interface/validation/class-validator.d.ts +6 -0
- package/dist/interface/validation/class-validator.js +28 -0
- package/dist/interface/validation/validator.d.ts +5 -0
- package/dist/interface/validation/validator.js +1 -0
- package/dist/protocols/repository.d.ts +1 -1
- package/package.json +5 -2
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import { InternalServerError, ServerError } from "../http";
|
|
2
|
-
import { flushControllers, getControllers } from "../application/controller";
|
|
3
1
|
import { FrameworkError } from "../http/errors/framework";
|
|
4
|
-
import {
|
|
2
|
+
import { HttpRequestMapper } from "../interface/http/request-mapper";
|
|
3
|
+
import { MiddlewareExecutor } from "../interface/http/middleware-executor";
|
|
4
|
+
import { HttpErrorMapper } from "../interface/errors/http-error-mapper";
|
|
5
|
+
import { validateWithClassValidator } from "../interface/validation/class-validator";
|
|
5
6
|
export default class ControllerHandler {
|
|
6
|
-
constructor(httpServer,
|
|
7
|
-
|
|
7
|
+
constructor(httpServer, controllers = []) {
|
|
8
|
+
this.requestMapper = new HttpRequestMapper();
|
|
9
|
+
this.middlewareExecutor = new MiddlewareExecutor();
|
|
10
|
+
this.errorMapper = new HttpErrorMapper();
|
|
11
|
+
for (const { handler, middlewares, validator, method, route, statusCode, params, query, headers, body, bodyFilter, responseType } of this.registryControllers(controllers)) {
|
|
8
12
|
httpServer.register({
|
|
9
13
|
method,
|
|
10
14
|
route,
|
|
@@ -14,6 +18,7 @@ export default class ControllerHandler {
|
|
|
14
18
|
query,
|
|
15
19
|
headers,
|
|
16
20
|
middlewares,
|
|
21
|
+
validator,
|
|
17
22
|
responseType
|
|
18
23
|
}, async (input) => {
|
|
19
24
|
let requestedAt = new Date();
|
|
@@ -25,23 +30,26 @@ export default class ControllerHandler {
|
|
|
25
30
|
let middlewaresExecuted = [];
|
|
26
31
|
try {
|
|
27
32
|
startTime = performance.now();
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
request = this.requestMapper.map(input, { params, query, headers, body, bodyFilter });
|
|
34
|
+
if (validator) {
|
|
35
|
+
if (typeof validator === 'function') {
|
|
36
|
+
await validateWithClassValidator(validator, request.data);
|
|
37
|
+
}
|
|
38
|
+
else if (typeof validator.validate === 'function') {
|
|
39
|
+
await validator.validate(request.data);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
throw new FrameworkError('Validator must be a class or implement validate()');
|
|
43
|
+
}
|
|
35
44
|
}
|
|
36
|
-
mergedParams =
|
|
37
|
-
|
|
38
|
-
middlewaresExecuted = await this.executeMiddlewares(middlewares, request);
|
|
45
|
+
mergedParams = request.data;
|
|
46
|
+
middlewaresExecuted = await this.middlewareExecutor.execute(middlewares, request);
|
|
39
47
|
const response = await handler.instance[handler.methodName](request);
|
|
40
48
|
endTime = performance.now();
|
|
41
49
|
return response;
|
|
42
50
|
}
|
|
43
51
|
catch (error) {
|
|
44
|
-
capturedError = this.
|
|
52
|
+
capturedError = this.errorMapper.map(error, httpServer);
|
|
45
53
|
input.setStatus(capturedError.statusCode);
|
|
46
54
|
endTime = performance.now();
|
|
47
55
|
if (capturedError?.custom) {
|
|
@@ -70,42 +78,10 @@ export default class ControllerHandler {
|
|
|
70
78
|
}
|
|
71
79
|
});
|
|
72
80
|
}
|
|
73
|
-
httpServer.listen(port);
|
|
74
81
|
}
|
|
75
|
-
|
|
76
|
-
const executed = [];
|
|
77
|
-
if (middlewares && middlewares.length > 0) {
|
|
78
|
-
for (const middleware of middlewares) {
|
|
79
|
-
let startTime = 0;
|
|
80
|
-
let endTime = 0;
|
|
81
|
-
let elapsedTime;
|
|
82
|
-
try {
|
|
83
|
-
startTime = performance.now();
|
|
84
|
-
const middlewareResult = await middleware.execute(request);
|
|
85
|
-
request.context = Object.assign(request.context, middlewareResult);
|
|
86
|
-
endTime = performance.now();
|
|
87
|
-
elapsedTime = `${(endTime - startTime).toFixed(2)} ms`;
|
|
88
|
-
executed.push({
|
|
89
|
-
elapsedTime,
|
|
90
|
-
middleware: middleware.constructor.name
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
catch (error) {
|
|
94
|
-
elapsedTime = `${(endTime - startTime).toFixed(2)} ms`;
|
|
95
|
-
executed.push({
|
|
96
|
-
elapsedTime,
|
|
97
|
-
middleware: middleware.constructor.name,
|
|
98
|
-
error
|
|
99
|
-
});
|
|
100
|
-
throw error;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
return executed;
|
|
105
|
-
}
|
|
106
|
-
registryControllers() {
|
|
82
|
+
registryControllers(controllersList) {
|
|
107
83
|
const controllers = [];
|
|
108
|
-
for (const controller of
|
|
84
|
+
for (const controller of controllersList) {
|
|
109
85
|
const basePath = Reflect.getMetadata('basePath', controller);
|
|
110
86
|
const methodNames = Object.getOwnPropertyNames(controller.prototype).filter(method => method !== 'constructor');
|
|
111
87
|
let tracer = Reflect.getMetadata('tracer', controller) || null;
|
|
@@ -124,6 +100,7 @@ export default class ControllerHandler {
|
|
|
124
100
|
body: routeConfig.body,
|
|
125
101
|
bodyFilter: routeConfig.bodyFilter,
|
|
126
102
|
statusCode: routeConfig.statusCode,
|
|
103
|
+
validator: routeConfig.validator,
|
|
127
104
|
handler: {
|
|
128
105
|
instance,
|
|
129
106
|
methodName,
|
|
@@ -134,7 +111,6 @@ export default class ControllerHandler {
|
|
|
134
111
|
});
|
|
135
112
|
}
|
|
136
113
|
}
|
|
137
|
-
flushControllers();
|
|
138
114
|
return controllers;
|
|
139
115
|
}
|
|
140
116
|
resolveMiddleware(middleware) {
|
|
@@ -158,72 +134,4 @@ export default class ControllerHandler {
|
|
|
158
134
|
}
|
|
159
135
|
return middleware;
|
|
160
136
|
}
|
|
161
|
-
filter(params, filterParams) {
|
|
162
|
-
const filter = {};
|
|
163
|
-
for (const paramName of filterParams || []) {
|
|
164
|
-
const [paramNameFiltered, type] = paramName.split('|');
|
|
165
|
-
let value = params[paramName] || params[paramNameFiltered];
|
|
166
|
-
if (!value)
|
|
167
|
-
continue;
|
|
168
|
-
if (type === 'boolean')
|
|
169
|
-
value = value === 'true';
|
|
170
|
-
if (type === 'integer') {
|
|
171
|
-
value = value.replace(/[^0-9]/g, '');
|
|
172
|
-
value = value ? parseInt(value) : 0;
|
|
173
|
-
}
|
|
174
|
-
if (type === 'string')
|
|
175
|
-
value = value.toString();
|
|
176
|
-
if (type === 'number')
|
|
177
|
-
value = parseFloat(value);
|
|
178
|
-
filter[paramNameFiltered] = value;
|
|
179
|
-
}
|
|
180
|
-
return filter;
|
|
181
|
-
}
|
|
182
|
-
extractError(error, httpServer) {
|
|
183
|
-
if (error instanceof ServerError) {
|
|
184
|
-
return {
|
|
185
|
-
message: error.message,
|
|
186
|
-
statusCode: error.getStatusCode()
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
if (error instanceof CustomServerError) {
|
|
190
|
-
return {
|
|
191
|
-
...error.getCustom(),
|
|
192
|
-
statusCode: error.getStatusCode(),
|
|
193
|
-
custom: true
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
const debugError = {
|
|
197
|
-
sourceUrl: error.sourceURL,
|
|
198
|
-
line: error.line,
|
|
199
|
-
column: error.column,
|
|
200
|
-
};
|
|
201
|
-
error = new InternalServerError(error.message, httpServer.getDefaultMessageError());
|
|
202
|
-
return {
|
|
203
|
-
message: error.message,
|
|
204
|
-
statusCode: error.getStatusCode(),
|
|
205
|
-
unexpectedError: error instanceof InternalServerError ? error.getUnexpectedError() : undefined,
|
|
206
|
-
...debugError
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
normalizeBracketNotation(data) {
|
|
210
|
-
if (!data || typeof data !== "object")
|
|
211
|
-
return data;
|
|
212
|
-
const normalized = {};
|
|
213
|
-
for (const [rawKey, value] of Object.entries(data)) {
|
|
214
|
-
const key = String(rawKey);
|
|
215
|
-
const match = key.match(/^([^\[\]]+)\[([^\[\]]+)\]$/);
|
|
216
|
-
if (match) {
|
|
217
|
-
const parent = match[1];
|
|
218
|
-
const child = match[2];
|
|
219
|
-
if (!normalized[parent] || typeof normalized[parent] !== "object") {
|
|
220
|
-
normalized[parent] = {};
|
|
221
|
-
}
|
|
222
|
-
normalized[parent][child] = value;
|
|
223
|
-
continue;
|
|
224
|
-
}
|
|
225
|
-
normalized[key] = value;
|
|
226
|
-
}
|
|
227
|
-
return normalized;
|
|
228
|
-
}
|
|
229
137
|
}
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
constructor(message: string, statusCode: number);
|
|
4
|
-
getStatusCode(): number;
|
|
5
|
-
}
|
|
1
|
+
export { AppError as ServerError } from "../../domain/errors/app-error";
|
|
2
|
+
export { BadRequest, NotFound, Forbidden, Conflict, Unauthorized, UnprocessableEntity, InternalServerError } from "../../domain/errors/http-errors";
|
|
6
3
|
export declare class CustomServerError extends Error {
|
|
7
4
|
private statusCode;
|
|
8
5
|
private custom;
|
|
@@ -10,26 +7,3 @@ export declare class CustomServerError extends Error {
|
|
|
10
7
|
getStatusCode(): number;
|
|
11
8
|
getCustom(): any;
|
|
12
9
|
}
|
|
13
|
-
export declare class NotFound extends ServerError {
|
|
14
|
-
constructor(message: string);
|
|
15
|
-
}
|
|
16
|
-
export declare class Forbidden extends ServerError {
|
|
17
|
-
constructor(message: string);
|
|
18
|
-
}
|
|
19
|
-
export declare class UnprocessableEntity extends ServerError {
|
|
20
|
-
constructor(message: string);
|
|
21
|
-
}
|
|
22
|
-
export declare class Conflict extends ServerError {
|
|
23
|
-
constructor(message: string);
|
|
24
|
-
}
|
|
25
|
-
export declare class Unauthorized extends ServerError {
|
|
26
|
-
constructor(message: string);
|
|
27
|
-
}
|
|
28
|
-
export declare class BadRequest extends ServerError {
|
|
29
|
-
constructor(message: string);
|
|
30
|
-
}
|
|
31
|
-
export declare class InternalServerError extends ServerError {
|
|
32
|
-
private unexpectedError;
|
|
33
|
-
constructor(unexpectedError: string, defaultMessage?: string);
|
|
34
|
-
getUnexpectedError(): string;
|
|
35
|
-
}
|
|
@@ -1,13 +1,5 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
super(message);
|
|
4
|
-
this.name = this.constructor.name;
|
|
5
|
-
this.statusCode = statusCode;
|
|
6
|
-
}
|
|
7
|
-
getStatusCode() {
|
|
8
|
-
return this.statusCode;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
1
|
+
export { AppError as ServerError } from "../../domain/errors/app-error";
|
|
2
|
+
export { BadRequest, NotFound, Forbidden, Conflict, Unauthorized, UnprocessableEntity, InternalServerError } from "../../domain/errors/http-errors";
|
|
11
3
|
export class CustomServerError extends Error {
|
|
12
4
|
constructor(custom, statusCode, nameError = '') {
|
|
13
5
|
super();
|
|
@@ -22,42 +14,3 @@ export class CustomServerError extends Error {
|
|
|
22
14
|
return this.custom;
|
|
23
15
|
}
|
|
24
16
|
}
|
|
25
|
-
export class NotFound extends ServerError {
|
|
26
|
-
constructor(message) {
|
|
27
|
-
super(message, 404);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
export class Forbidden extends ServerError {
|
|
31
|
-
constructor(message) {
|
|
32
|
-
super(message, 403);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
export class UnprocessableEntity extends ServerError {
|
|
36
|
-
constructor(message) {
|
|
37
|
-
super(message, 422);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
export class Conflict extends ServerError {
|
|
41
|
-
constructor(message) {
|
|
42
|
-
super(message, 409);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
export class Unauthorized extends ServerError {
|
|
46
|
-
constructor(message) {
|
|
47
|
-
super(message, 401);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
export class BadRequest extends ServerError {
|
|
51
|
-
constructor(message) {
|
|
52
|
-
super(message, 400);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
export class InternalServerError extends ServerError {
|
|
56
|
-
constructor(unexpectedError, defaultMessage = 'Ops, An unexpected error occurred') {
|
|
57
|
-
super(defaultMessage, 500);
|
|
58
|
-
this.unexpectedError = unexpectedError;
|
|
59
|
-
}
|
|
60
|
-
getUnexpectedError() {
|
|
61
|
-
return this.unexpectedError;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Middleware, Tracer } from "../application/controller";
|
|
2
|
+
import type { ValidatorLike } from "../interface/validation/validator";
|
|
2
3
|
export type Request = {
|
|
3
4
|
data: any;
|
|
4
5
|
context: any;
|
|
@@ -15,6 +16,7 @@ export type HttpServerParams = {
|
|
|
15
16
|
};
|
|
16
17
|
responseType: 'json' | 'text' | 'html';
|
|
17
18
|
middlewares?: Middleware[];
|
|
19
|
+
validator?: ValidatorLike;
|
|
18
20
|
statusCode?: number;
|
|
19
21
|
params?: string[];
|
|
20
22
|
query?: string[];
|
package/dist/http/http-server.js
CHANGED
|
@@ -53,7 +53,7 @@ export default class HttpServer {
|
|
|
53
53
|
express(httpServerParams, route, handler) {
|
|
54
54
|
const method = httpServerParams.method;
|
|
55
55
|
this.framework[method](route, async (request, res) => {
|
|
56
|
-
request.headers['ip'] = request.ip
|
|
56
|
+
request.headers['ip'] = request.ip;
|
|
57
57
|
res.status(httpServerParams.statusCode ?? 200);
|
|
58
58
|
const output = await handler({
|
|
59
59
|
setStatus: (statusCode) => res.status(statusCode),
|
package/dist/http/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import HttpServer from "./http-server";
|
|
2
|
-
import { ServerError, NotFound, Forbidden, Conflict, Unauthorized, UnprocessableEntity, BadRequest, InternalServerError } from "./errors/server";
|
|
3
|
-
export { ServerError, BadRequest, NotFound, Forbidden, Conflict, Unauthorized, UnprocessableEntity, HttpServer, InternalServerError };
|
|
2
|
+
import { ServerError, NotFound, Forbidden, Conflict, Unauthorized, UnprocessableEntity, BadRequest, InternalServerError, CustomServerError } from "./errors/server";
|
|
3
|
+
export { ServerError, BadRequest, NotFound, Forbidden, Conflict, Unauthorized, UnprocessableEntity, HttpServer, InternalServerError, CustomServerError };
|
package/dist/http/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import HttpServer from "./http-server";
|
|
2
|
-
import { ServerError, NotFound, Forbidden, Conflict, Unauthorized, UnprocessableEntity, BadRequest, InternalServerError } from "./errors/server";
|
|
3
|
-
export { ServerError, BadRequest, NotFound, Forbidden, Conflict, Unauthorized, UnprocessableEntity, HttpServer, InternalServerError };
|
|
2
|
+
import { ServerError, NotFound, Forbidden, Conflict, Unauthorized, UnprocessableEntity, BadRequest, InternalServerError, CustomServerError } from "./errors/server";
|
|
3
|
+
export { ServerError, BadRequest, NotFound, Forbidden, Conflict, Unauthorized, UnprocessableEntity, HttpServer, InternalServerError, CustomServerError };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Post, Get, Put, Delete, Patch, Controller, Input, Middleware, UseMiddleware, UseMiddlewares, Tracer, Tracing, TracerData, Entity, Restrict, VirtualProperty, GetterPrefix, Serialize, UseCase, DecorateUseCase, Storage, StorageGateway } from "./application";
|
|
2
|
-
import { Inject } from './infra/di/registry';
|
|
2
|
+
import { Container, DefaultContainer, Inject, setDefaultContainer } from './infra/di/registry';
|
|
3
3
|
import { Dede, type Options, Register } from './dede';
|
|
4
|
-
import { ServerError, NotFound, Forbidden, Conflict, Unauthorized, UnprocessableEntity, BadRequest, InternalServerError } from './http/errors/server';
|
|
4
|
+
import { ServerError, NotFound, Forbidden, Conflict, Unauthorized, UnprocessableEntity, BadRequest, InternalServerError, CustomServerError } from './http/errors/server';
|
|
5
|
+
import { AppError } from './domain/errors/app-error';
|
|
5
6
|
import type { RepositoryCreate, RepositoryUpdate, RepositoryRemove, RepositoryRemoveBy, RepositoryExistsBy, RepositoryRestore, RepositoryRestoreBy, RepositoryNotExistsBy, RepositoryPagination } from './protocols/repository';
|
|
6
|
-
export { Controller, Post, Get, Put, Delete, Patch, Input, Middleware, UseMiddleware, UseMiddlewares, Tracer, Tracing, TracerData, Entity, Restrict, VirtualProperty, GetterPrefix, Serialize, UseCase, DecorateUseCase, Storage, StorageGateway, Inject, Dede, Options, Register, ServerError, NotFound, Forbidden, Conflict, Unauthorized, UnprocessableEntity, BadRequest, InternalServerError, RepositoryCreate, RepositoryUpdate, RepositoryRemove, RepositoryRemoveBy, RepositoryRestore, RepositoryExistsBy, RepositoryRestoreBy, RepositoryNotExistsBy, RepositoryPagination };
|
|
7
|
+
export { Controller, Post, Get, Put, Delete, Patch, Input, Middleware, UseMiddleware, UseMiddlewares, Tracer, Tracing, TracerData, Entity, Restrict, VirtualProperty, GetterPrefix, Serialize, UseCase, DecorateUseCase, Storage, StorageGateway, Inject, Container, DefaultContainer, setDefaultContainer, Dede, Options, Register, ServerError, NotFound, Forbidden, Conflict, Unauthorized, UnprocessableEntity, BadRequest, InternalServerError, CustomServerError, AppError, RepositoryCreate, RepositoryUpdate, RepositoryRemove, RepositoryRemoveBy, RepositoryRestore, RepositoryExistsBy, RepositoryRestoreBy, RepositoryNotExistsBy, RepositoryPagination };
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,8 @@ UseCase, DecorateUseCase,
|
|
|
10
10
|
// usecase
|
|
11
11
|
// storage
|
|
12
12
|
Storage } from "./application";
|
|
13
|
-
import { Inject } from './infra/di/registry';
|
|
13
|
+
import { Container, DefaultContainer, Inject, setDefaultContainer } from './infra/di/registry';
|
|
14
14
|
import { Dede } from './dede';
|
|
15
|
-
import { ServerError, NotFound, Forbidden, Conflict, Unauthorized, UnprocessableEntity, BadRequest, InternalServerError } from './http/errors/server';
|
|
16
|
-
|
|
15
|
+
import { ServerError, NotFound, Forbidden, Conflict, Unauthorized, UnprocessableEntity, BadRequest, InternalServerError, CustomServerError } from './http/errors/server';
|
|
16
|
+
import { AppError } from './domain/errors/app-error';
|
|
17
|
+
export { Controller, Post, Get, Put, Delete, Patch, UseMiddleware, UseMiddlewares, Tracing, Entity, Restrict, VirtualProperty, GetterPrefix, Serialize, UseCase, DecorateUseCase, Storage, Inject, Container, DefaultContainer, setDefaultContainer, Dede, ServerError, NotFound, Forbidden, Conflict, Unauthorized, UnprocessableEntity, BadRequest, InternalServerError, CustomServerError, AppError };
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
declare class
|
|
2
|
-
private static instance;
|
|
1
|
+
export declare class Container {
|
|
3
2
|
private dependencies;
|
|
4
|
-
static getInstance(): ComponentRegistry;
|
|
5
3
|
load(name: string, dependency: any): void;
|
|
6
4
|
inject(name: string): any;
|
|
7
5
|
remove(name: string): void;
|
|
8
6
|
}
|
|
9
|
-
export declare
|
|
10
|
-
export declare function
|
|
11
|
-
export
|
|
7
|
+
export declare let DefaultContainer: Container;
|
|
8
|
+
export declare function setDefaultContainer(container: Container): void;
|
|
9
|
+
export declare function Inject(name: string, container?: Container): (target: any, propertyKey: string) => void;
|
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
class
|
|
1
|
+
export class Container {
|
|
2
2
|
constructor() {
|
|
3
3
|
this.dependencies = new Map();
|
|
4
4
|
}
|
|
5
|
-
static getInstance() {
|
|
6
|
-
if (!this.instance) {
|
|
7
|
-
this.instance = new ComponentRegistry();
|
|
8
|
-
}
|
|
9
|
-
return this.instance;
|
|
10
|
-
}
|
|
11
5
|
load(name, dependency) {
|
|
12
6
|
this.dependencies.set(name, dependency);
|
|
13
7
|
}
|
|
@@ -20,12 +14,16 @@ class ComponentRegistry {
|
|
|
20
14
|
this.dependencies.delete(name);
|
|
21
15
|
}
|
|
22
16
|
}
|
|
23
|
-
export
|
|
24
|
-
export function
|
|
17
|
+
export let DefaultContainer = new Container();
|
|
18
|
+
export function setDefaultContainer(container) {
|
|
19
|
+
DefaultContainer = container;
|
|
20
|
+
}
|
|
21
|
+
export function Inject(name, container) {
|
|
25
22
|
return function (target, propertyKey) {
|
|
26
23
|
target[propertyKey] = new Proxy({}, {
|
|
27
24
|
get(_, propertyKey) {
|
|
28
|
-
const
|
|
25
|
+
const resolvedContainer = container ?? DefaultContainer;
|
|
26
|
+
const dependency = resolvedContainer.inject(name);
|
|
29
27
|
return dependency[propertyKey];
|
|
30
28
|
}
|
|
31
29
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { Entity as DomainEntity } from "../../domain/entity";
|
|
2
|
+
export declare abstract class SerializableEntity extends DomainEntity {
|
|
2
3
|
[x: string]: any;
|
|
3
4
|
private buildRawEntityObject;
|
|
4
5
|
private getEntityHooks;
|
|
@@ -17,5 +18,6 @@ export declare function Restrict(): (target: any, propertyKey: string) => void;
|
|
|
17
18
|
export declare function VirtualProperty(propertyName: string): (target: any, methodName: string) => void;
|
|
18
19
|
export declare function Serialize(callback: (value: any) => any): PropertyDecorator;
|
|
19
20
|
export declare function GetterPrefix(prefix: string): (target: any, propertyKey: string) => void;
|
|
21
|
+
export { SerializableEntity as Entity };
|
|
20
22
|
export declare function BeforeToEntity(): MethodDecorator;
|
|
21
23
|
export declare function AfterToEntity(): MethodDecorator;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { Entity as DomainEntity } from "../../domain/entity";
|
|
2
|
+
export class SerializableEntity extends DomainEntity {
|
|
2
3
|
buildRawEntityObject() {
|
|
3
4
|
const result = {};
|
|
4
5
|
for (const [propName] of Object.entries(this)) {
|
|
@@ -14,7 +15,7 @@ export class Entity {
|
|
|
14
15
|
getEntityHooks(hookKey) {
|
|
15
16
|
const hooks = [];
|
|
16
17
|
let current = this.constructor;
|
|
17
|
-
while (current && current !==
|
|
18
|
+
while (current && current !== SerializableEntity) {
|
|
18
19
|
const currentHooks = current[hookKey];
|
|
19
20
|
if (currentHooks && currentHooks.length) {
|
|
20
21
|
hooks.unshift(...currentHooks);
|
|
@@ -103,7 +104,7 @@ export class Entity {
|
|
|
103
104
|
if (value === undefined)
|
|
104
105
|
continue;
|
|
105
106
|
// @ts-ignore
|
|
106
|
-
if (propertiesConfigs && propertiesConfigs[propName]?.serialize && (value ||
|
|
107
|
+
if (propertiesConfigs && propertiesConfigs[propName]?.serialize && (value || value === 0)) {
|
|
107
108
|
const serializedValue = await propertiesConfigs[propName].serialize(value);
|
|
108
109
|
if (serializedValue && typeof serializedValue === 'object' && !Array.isArray(serializedValue)) {
|
|
109
110
|
const entries = Object.entries(serializedValue);
|
|
@@ -181,27 +182,7 @@ export class Entity {
|
|
|
181
182
|
return result;
|
|
182
183
|
}
|
|
183
184
|
generateGetters() {
|
|
184
|
-
|
|
185
|
-
if (typeof this[property] === 'function')
|
|
186
|
-
continue;
|
|
187
|
-
let prefixName = null;
|
|
188
|
-
// @ts-ignore
|
|
189
|
-
if (this.constructor.propertiesConfigs && this.constructor.propertiesConfigs[property] && this.constructor.propertiesConfigs[property].prefix) {
|
|
190
|
-
// @ts-ignore
|
|
191
|
-
prefixName = this.constructor.propertiesConfigs[property].prefix;
|
|
192
|
-
}
|
|
193
|
-
else {
|
|
194
|
-
const isBoolean = this[property] ? typeof this[property] === 'boolean' : false;
|
|
195
|
-
prefixName = isBoolean ? 'is' : 'get';
|
|
196
|
-
}
|
|
197
|
-
let getterName = null;
|
|
198
|
-
if (property[0]) {
|
|
199
|
-
getterName = `${prefixName}${property[0].toUpperCase()}${property.slice(1)}`;
|
|
200
|
-
if (this[getterName])
|
|
201
|
-
continue;
|
|
202
|
-
this[getterName] = () => this[property];
|
|
203
|
-
}
|
|
204
|
-
}
|
|
185
|
+
super.generateGetters();
|
|
205
186
|
}
|
|
206
187
|
}
|
|
207
188
|
export function Restrict() {
|
|
@@ -240,10 +221,11 @@ const loadPropertiesConfig = (target, propertyKey) => {
|
|
|
240
221
|
const BEFORE_TO_ENTITY = Symbol('beforeToEntity');
|
|
241
222
|
const AFTER_TO_ENTITY = Symbol('afterToEntity');
|
|
242
223
|
const assertEntityDecoratorTarget = (target, decoratorName) => {
|
|
243
|
-
if (!
|
|
224
|
+
if (!SerializableEntity.prototype.isPrototypeOf(target)) {
|
|
244
225
|
throw new Error(`${decoratorName} can only be used on Entity classes`);
|
|
245
226
|
}
|
|
246
227
|
};
|
|
228
|
+
export { SerializableEntity as Entity };
|
|
247
229
|
export function BeforeToEntity() {
|
|
248
230
|
return function (target, propertyKey) {
|
|
249
231
|
assertEntityDecoratorTarget(target, 'BeforeToEntity');
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type HttpServer from '../../http/http-server';
|
|
2
|
+
export type MappedError = {
|
|
3
|
+
message: string;
|
|
4
|
+
statusCode: number;
|
|
5
|
+
custom?: boolean;
|
|
6
|
+
unexpectedError?: string;
|
|
7
|
+
};
|
|
8
|
+
export declare class HttpErrorMapper {
|
|
9
|
+
map(error: any, httpServer: HttpServer): MappedError;
|
|
10
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { AppError } from '../../domain/errors/app-error';
|
|
2
|
+
import { InternalServerError } from '../../domain/errors/http-errors';
|
|
3
|
+
export class HttpErrorMapper {
|
|
4
|
+
map(error, httpServer) {
|
|
5
|
+
if (error instanceof AppError) {
|
|
6
|
+
return {
|
|
7
|
+
message: error.message,
|
|
8
|
+
statusCode: error.getStatusCode()
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
if (error && typeof error.getStatusCode === 'function' && typeof error.getCustom === 'function') {
|
|
12
|
+
return {
|
|
13
|
+
...error.getCustom(),
|
|
14
|
+
statusCode: error.getStatusCode(),
|
|
15
|
+
custom: true
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
const debugError = {
|
|
19
|
+
sourceUrl: error?.sourceURL,
|
|
20
|
+
line: error?.line,
|
|
21
|
+
column: error?.column,
|
|
22
|
+
};
|
|
23
|
+
const internal = new InternalServerError(error?.message || 'Unexpected error', httpServer.getDefaultMessageError());
|
|
24
|
+
return {
|
|
25
|
+
message: internal.message,
|
|
26
|
+
statusCode: internal.getStatusCode(),
|
|
27
|
+
unexpectedError: internal.getUnexpectedError(),
|
|
28
|
+
...debugError
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Request } from "../../http/http-server";
|
|
2
|
+
import type { Middleware } from "../../application/controller";
|
|
3
|
+
export type ExecutedMiddleware = {
|
|
4
|
+
elapsedTime: string;
|
|
5
|
+
middleware: string;
|
|
6
|
+
error?: any;
|
|
7
|
+
};
|
|
8
|
+
export declare class MiddlewareExecutor {
|
|
9
|
+
execute(middlewares: Middleware[] | undefined, request: Request): Promise<ExecutedMiddleware[]>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export class MiddlewareExecutor {
|
|
2
|
+
async execute(middlewares = [], request) {
|
|
3
|
+
const executed = [];
|
|
4
|
+
if (middlewares && middlewares.length > 0) {
|
|
5
|
+
for (const middleware of middlewares) {
|
|
6
|
+
let startTime = 0;
|
|
7
|
+
let endTime = 0;
|
|
8
|
+
let elapsedTime;
|
|
9
|
+
try {
|
|
10
|
+
startTime = performance.now();
|
|
11
|
+
const middlewareResult = await middleware.execute(request);
|
|
12
|
+
request.context = Object.assign(request.context, middlewareResult);
|
|
13
|
+
endTime = performance.now();
|
|
14
|
+
elapsedTime = `${(endTime - startTime).toFixed(2)} ms`;
|
|
15
|
+
executed.push({
|
|
16
|
+
elapsedTime,
|
|
17
|
+
middleware: middleware.constructor.name,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
elapsedTime = `${(endTime - startTime).toFixed(2)} ms`;
|
|
22
|
+
executed.push({
|
|
23
|
+
elapsedTime,
|
|
24
|
+
middleware: middleware.constructor.name,
|
|
25
|
+
error,
|
|
26
|
+
});
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return executed;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Request } from "../../http/http-server";
|
|
2
|
+
type BodyFilter = 'none' | 'restrict';
|
|
3
|
+
type RouteInputConfig = {
|
|
4
|
+
params?: string[];
|
|
5
|
+
query?: string[];
|
|
6
|
+
headers?: string[];
|
|
7
|
+
body?: string[];
|
|
8
|
+
bodyFilter?: BodyFilter;
|
|
9
|
+
};
|
|
10
|
+
type HttpInput = {
|
|
11
|
+
headers: any;
|
|
12
|
+
body: any;
|
|
13
|
+
params: any;
|
|
14
|
+
query: any;
|
|
15
|
+
};
|
|
16
|
+
export declare class HttpRequestMapper {
|
|
17
|
+
map(input: HttpInput, config: RouteInputConfig): Request;
|
|
18
|
+
private filter;
|
|
19
|
+
private normalizeBracketNotation;
|
|
20
|
+
}
|
|
21
|
+
export {};
|