@hemia/common 0.0.5 → 0.0.7
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 +97 -2
- package/dist/hemia-common.esm.js +407 -2
- package/dist/hemia-common.js +454 -1
- package/dist/types/decorators/custom/custom.decorator.d.ts +12 -0
- package/dist/types/decorators/custom/index.d.ts +1 -0
- package/dist/types/decorators/http/param.decorators.d.ts +108 -0
- package/dist/types/decorators/index.d.ts +3 -0
- package/dist/types/decorators/metadata.d.ts +4 -0
- package/dist/types/decorators/transform/index.d.ts +1 -0
- package/dist/types/decorators/transform/transform.decorator.d.ts +12 -0
- package/dist/types/decorators/validation/index.d.ts +1 -0
- package/dist/types/decorators/validation/validate.decorator.d.ts +12 -0
- package/dist/types/enums/param-type.enum.d.ts +9 -1
- package/dist/types/errors/index.d.ts +3 -0
- package/dist/types/interfaces/configuration/smtp-configuration.interface.d.ts +7 -0
- package/dist/types/interfaces/index.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
# @hemia/common
|
|
3
2
|
|
|
4
3
|
Sistema de decoradores y utilidades para crear controladores HTTP con TypeScript usando metadata reflection.
|
|
@@ -241,6 +240,103 @@ externalRedirect() {
|
|
|
241
240
|
// Redirige temporalmente
|
|
242
241
|
}
|
|
243
242
|
```
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## 🆕 Decoradores Avanzados
|
|
247
|
+
|
|
248
|
+
### Validación y Transformación
|
|
249
|
+
|
|
250
|
+
#### `@Validate(validatorFn)`
|
|
251
|
+
Valida el parámetro usando una función personalizada.
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
@Post('/')
|
|
255
|
+
create(@Body() data: any, @Validate(validateUser) _: any) { /* ... */ }
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
#### `@Transform(transformFn)`
|
|
259
|
+
Transforma el parámetro usando una función personalizada.
|
|
260
|
+
|
|
261
|
+
```typescript
|
|
262
|
+
@Post('/')
|
|
263
|
+
create(@Body() data: any, @Transform(toUserDto) _: any) { /* ... */ }
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
#### `@Custom(key: string)`
|
|
267
|
+
Extrae datos personalizados del request.
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
@Get('/')
|
|
271
|
+
handler(@Custom('customData') custom: any) { /* ... */ }
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Decoradores de Guardias y Autenticación
|
|
275
|
+
|
|
276
|
+
#### `@ReqUser()`
|
|
277
|
+
Inyecta el usuario autenticado (por ejemplo, desde JWTGuard).
|
|
278
|
+
|
|
279
|
+
```typescript
|
|
280
|
+
@Get('/profile')
|
|
281
|
+
profile(@ReqUser() user: any) { /* ... */ }
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
#### `@ReqPermissions()`
|
|
285
|
+
Inyecta los permisos del usuario.
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
@Get('/admin')
|
|
289
|
+
admin(@ReqPermissions() permissions: string[]) { /* ... */ }
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
#### `@ReqContext()`
|
|
293
|
+
Inyecta el contexto de la solicitud.
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
@Get('/context')
|
|
297
|
+
context(@ReqContext() ctx: any) { /* ... */ }
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
#### `@Cookies(key?: string)`
|
|
301
|
+
Extrae cookies de la petición.
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
@Get('/')
|
|
305
|
+
handler(@Cookies('token') token: string) { /* ... */ }
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
#### `@Files()`
|
|
309
|
+
Extrae todos los archivos enviados en la solicitud.
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
@Post('/upload')
|
|
313
|
+
upload(@Files() files: any[]) { /* ... */ }
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
#### `@File(key?: string)`
|
|
317
|
+
Extrae un archivo específico.
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
@Post('/avatar')
|
|
321
|
+
avatar(@File('avatar') avatar: any) { /* ... */ }
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
#### `@Locale()`
|
|
325
|
+
Extrae el locale del usuario.
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
@Get('/')
|
|
329
|
+
handler(@Locale() locale: string) { /* ... */ }
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
#### `@ReqAuth()`
|
|
333
|
+
Extrae datos de autenticación.
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
@Get('/auth')
|
|
337
|
+
auth(@ReqAuth() auth: any) { /* ... */ }
|
|
338
|
+
```
|
|
339
|
+
|
|
244
340
|
---
|
|
245
341
|
|
|
246
342
|
## 🔍 Metadata Keys
|
|
@@ -288,4 +384,3 @@ ISC
|
|
|
288
384
|
## ✨ Generado con Hemia CLI
|
|
289
385
|
|
|
290
386
|
Este paquete fue generado usando [Hemia CLI](https://www.npmjs.com/package/@hemia/cli).
|
|
291
|
-
|
package/dist/hemia-common.esm.js
CHANGED
|
@@ -6,12 +6,16 @@ const METADATA_KEYS = {
|
|
|
6
6
|
PARAMS: 'params',
|
|
7
7
|
HEADERS: 'headers',
|
|
8
8
|
REDIRECT: 'redirect',
|
|
9
|
+
COOKIES: 'cookies',
|
|
9
10
|
GUARDS: 'hemia:guards',
|
|
10
11
|
INTERCEPTORS: 'hemia:interceptors',
|
|
11
12
|
CUSTOM: 'hemia:custom',
|
|
12
13
|
SERIALIZE: 'hemia:serialize',
|
|
13
14
|
ROLES: 'hemia:roles',
|
|
14
|
-
PERMISSIONS: 'hemia:permissions'
|
|
15
|
+
PERMISSIONS: 'hemia:permissions',
|
|
16
|
+
TRANSFORMERS: 'hemia:transformers',
|
|
17
|
+
VALIDATORS: 'hemia:validators',
|
|
18
|
+
CUSTOMS: 'hemia:customs',
|
|
15
19
|
};
|
|
16
20
|
|
|
17
21
|
const Controller = (basePath = '/') => {
|
|
@@ -43,6 +47,14 @@ var ParamType;
|
|
|
43
47
|
ParamType["SESSION"] = "SESSION";
|
|
44
48
|
ParamType["IP"] = "IP";
|
|
45
49
|
ParamType["HOST"] = "HOST";
|
|
50
|
+
ParamType["COOKIES"] = "COOKIES";
|
|
51
|
+
ParamType["FILES"] = "FILES";
|
|
52
|
+
ParamType["FILE"] = "FILE";
|
|
53
|
+
ParamType["LOCALE"] = "LOCALE";
|
|
54
|
+
ParamType["AUTH"] = "AUTH";
|
|
55
|
+
ParamType["USER"] = "USER";
|
|
56
|
+
ParamType["PERMISSIONS"] = "PERMISSIONS";
|
|
57
|
+
ParamType["CONTEXT"] = "CONTEXT";
|
|
46
58
|
})(ParamType || (ParamType = {}));
|
|
47
59
|
|
|
48
60
|
const createMethodDecorator = (method) => {
|
|
@@ -71,18 +83,126 @@ const createParamDecorator = (type) => {
|
|
|
71
83
|
};
|
|
72
84
|
};
|
|
73
85
|
};
|
|
86
|
+
/**
|
|
87
|
+
* Inyecta el objeto Request completo.
|
|
88
|
+
* @example
|
|
89
|
+
* async handler(@Request() req) {}
|
|
90
|
+
*/
|
|
74
91
|
const Request = createParamDecorator(ParamType.REQUEST);
|
|
92
|
+
/**
|
|
93
|
+
* Alias para Request.
|
|
94
|
+
* @example
|
|
95
|
+
* async handler(@Req() req) {}
|
|
96
|
+
*/
|
|
75
97
|
const Req = createParamDecorator(ParamType.REQUEST);
|
|
98
|
+
/**
|
|
99
|
+
* Inyecta el objeto Response.
|
|
100
|
+
* @example
|
|
101
|
+
* async handler(@Response() res) {}
|
|
102
|
+
*/
|
|
76
103
|
const Response = createParamDecorator(ParamType.RESPONSE);
|
|
104
|
+
/**
|
|
105
|
+
* Alias para Response.
|
|
106
|
+
* @example
|
|
107
|
+
* async handler(@Res() res) {}
|
|
108
|
+
*/
|
|
77
109
|
const Res = createParamDecorator(ParamType.RESPONSE);
|
|
110
|
+
/**
|
|
111
|
+
* Inyecta el objeto Next para middlewares.
|
|
112
|
+
* @example
|
|
113
|
+
* async handler(@Next() next) {}
|
|
114
|
+
*/
|
|
78
115
|
const Next = createParamDecorator(ParamType.NEXT);
|
|
116
|
+
/**
|
|
117
|
+
* Inyecta la sesión del usuario.
|
|
118
|
+
* @example
|
|
119
|
+
* async handler(@Session() session) {}
|
|
120
|
+
*/
|
|
79
121
|
const Session = createParamDecorator(ParamType.SESSION);
|
|
122
|
+
/**
|
|
123
|
+
* Inyecta la IP del cliente.
|
|
124
|
+
* @example
|
|
125
|
+
* async handler(@Ip() ip) {}
|
|
126
|
+
*/
|
|
80
127
|
const Ip = createParamDecorator(ParamType.IP);
|
|
128
|
+
/**
|
|
129
|
+
* Inyecta el host de la solicitud.
|
|
130
|
+
* @example
|
|
131
|
+
* async handler(@Host() host) {}
|
|
132
|
+
*/
|
|
81
133
|
const Host = createParamDecorator(ParamType.HOST);
|
|
134
|
+
/**
|
|
135
|
+
* Inyecta el cuerpo de la solicitud.
|
|
136
|
+
* @example
|
|
137
|
+
* async handler(@Body() body) {}
|
|
138
|
+
*/
|
|
82
139
|
const Body = createParamDecorator(ParamType.BODY);
|
|
140
|
+
/**
|
|
141
|
+
* Inyecta los parámetros de consulta (query).
|
|
142
|
+
* @example
|
|
143
|
+
* async handler(@Query('search') search) {}
|
|
144
|
+
*/
|
|
83
145
|
const Query = createParamDecorator(ParamType.QUERY);
|
|
146
|
+
/**
|
|
147
|
+
* Inyecta los parámetros de la URL.
|
|
148
|
+
* @example
|
|
149
|
+
* async handler(@Param('id') id) {}
|
|
150
|
+
*/
|
|
84
151
|
const Param = createParamDecorator(ParamType.PARAM);
|
|
152
|
+
/**
|
|
153
|
+
* Inyecta los encabezados de la solicitud.
|
|
154
|
+
* @example
|
|
155
|
+
* async handler(@Headers('authorization') auth) {}
|
|
156
|
+
*/
|
|
85
157
|
const Headers = createParamDecorator(ParamType.HEADERS);
|
|
158
|
+
/**
|
|
159
|
+
* Inyecta los cookies de la solicitud.
|
|
160
|
+
* @example
|
|
161
|
+
* async handler(@Cookies('token') token) {}
|
|
162
|
+
*/
|
|
163
|
+
const Cookies = createParamDecorator(ParamType.COOKIES);
|
|
164
|
+
/**
|
|
165
|
+
* Inyecta todos los archivos enviados en la solicitud.
|
|
166
|
+
* @example
|
|
167
|
+
* async handler(@Files() files) {}
|
|
168
|
+
*/
|
|
169
|
+
const Files = createParamDecorator(ParamType.FILES);
|
|
170
|
+
/**
|
|
171
|
+
* Inyecta un archivo específico de la solicitud.
|
|
172
|
+
* @example
|
|
173
|
+
* async handler(@File('avatar') avatar) {}
|
|
174
|
+
*/
|
|
175
|
+
const File = createParamDecorator(ParamType.FILE);
|
|
176
|
+
/**
|
|
177
|
+
* Inyecta el locale del usuario.
|
|
178
|
+
* @example
|
|
179
|
+
* async handler(@Locale() locale) {}
|
|
180
|
+
*/
|
|
181
|
+
const Locale = createParamDecorator(ParamType.LOCALE);
|
|
182
|
+
/**
|
|
183
|
+
* Inyecta datos de autenticación.
|
|
184
|
+
* @example
|
|
185
|
+
* async handler(@ReqAuth() auth) {}
|
|
186
|
+
*/
|
|
187
|
+
const ReqAuth = createParamDecorator(ParamType.AUTH);
|
|
188
|
+
/**
|
|
189
|
+
* Inyecta el usuario autenticado.
|
|
190
|
+
* @example
|
|
191
|
+
* async handler(@ReqUser() user) {}
|
|
192
|
+
*/
|
|
193
|
+
const ReqUser = createParamDecorator(ParamType.USER);
|
|
194
|
+
/**
|
|
195
|
+
* Inyecta los permisos del usuario.
|
|
196
|
+
* @example
|
|
197
|
+
* async handler(@ReqPermissions() permissions) {}
|
|
198
|
+
*/
|
|
199
|
+
const ReqPermissions = createParamDecorator(ParamType.PERMISSIONS);
|
|
200
|
+
/**
|
|
201
|
+
* Inyecta el contexto de la solicitud.
|
|
202
|
+
* @example
|
|
203
|
+
* async handler(@ReqContext() context) {}
|
|
204
|
+
*/
|
|
205
|
+
const ReqContext = createParamDecorator(ParamType.CONTEXT);
|
|
86
206
|
|
|
87
207
|
const Header = (name, value) => {
|
|
88
208
|
return (target, propertyKey, descriptor) => {
|
|
@@ -162,6 +282,60 @@ function Serialize(dto) {
|
|
|
162
282
|
return SetMetadata(METADATA_KEYS.SERIALIZE, dto);
|
|
163
283
|
}
|
|
164
284
|
|
|
285
|
+
/**
|
|
286
|
+
* Decorador para extraer datos personalizados del request.
|
|
287
|
+
*
|
|
288
|
+
* @example
|
|
289
|
+
* // Extrae el valor de 'customData' del request
|
|
290
|
+
* @Custom('customData')
|
|
291
|
+
* async handler(@Custom() customData: any) {}
|
|
292
|
+
*
|
|
293
|
+
* @param key Clave personalizada a extraer del request.
|
|
294
|
+
*/
|
|
295
|
+
function Custom(key) {
|
|
296
|
+
return (target, propertyKey, parameterIndex) => {
|
|
297
|
+
const existingCustoms = Reflect.getMetadata(METADATA_KEYS.CUSTOMS, target, propertyKey || '') || [];
|
|
298
|
+
existingCustoms.push({ index: parameterIndex, key });
|
|
299
|
+
Reflect.defineMetadata(METADATA_KEYS.CUSTOMS, existingCustoms, target, propertyKey || '');
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Decorador para validar datos de entrada en un controlador.
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* // Valida el parámetro 'body' usando la función validateUser
|
|
308
|
+
* @Validate(validateUser)
|
|
309
|
+
* async create(@Body() body: any) {}
|
|
310
|
+
*
|
|
311
|
+
* @param validator Función de validación que recibe el valor y retorna booleano o lanza error.
|
|
312
|
+
*/
|
|
313
|
+
function Validate(validator) {
|
|
314
|
+
return (target, propertyKey, parameterIndex) => {
|
|
315
|
+
const existingValidators = Reflect.getMetadata(METADATA_KEYS.VALIDATORS, target, propertyKey || '') || [];
|
|
316
|
+
existingValidators.push({ index: parameterIndex, validator });
|
|
317
|
+
Reflect.defineMetadata(METADATA_KEYS.VALIDATORS, existingValidators, target, propertyKey || '');
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Decorador para transformar datos de entrada en un controlador.
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* // Transforma el parámetro 'body' usando la función toUserDto
|
|
326
|
+
* @Transform(toUserDto)
|
|
327
|
+
* async create(@Body() body: any) {}
|
|
328
|
+
*
|
|
329
|
+
* @param transformer Función de transformación que recibe el valor y retorna el nuevo valor.
|
|
330
|
+
*/
|
|
331
|
+
function Transform(transformer) {
|
|
332
|
+
return (target, propertyKey, parameterIndex) => {
|
|
333
|
+
const existingTransformers = Reflect.getMetadata(METADATA_KEYS.TRANSFORMERS, target, propertyKey || '') || [];
|
|
334
|
+
existingTransformers.push({ index: parameterIndex, transformer });
|
|
335
|
+
Reflect.defineMetadata(METADATA_KEYS.TRANSFORMERS, existingTransformers, target, propertyKey || '');
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
|
|
165
339
|
class ApiResponse {
|
|
166
340
|
static success(data, message = 'OK', status = 200) {
|
|
167
341
|
return {
|
|
@@ -250,4 +424,235 @@ class HttpErrorWithDetails extends HttpError {
|
|
|
250
424
|
}
|
|
251
425
|
}
|
|
252
426
|
|
|
253
|
-
|
|
427
|
+
class PersistenceError extends Error {
|
|
428
|
+
constructor(message, originalError) {
|
|
429
|
+
super(message);
|
|
430
|
+
this.originalError = originalError;
|
|
431
|
+
this.name = 'PersistenceError';
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
class DataNotFoundError extends PersistenceError {
|
|
435
|
+
constructor(entity, criteria, originalError) {
|
|
436
|
+
super(`${entity} not found with criteria: ${criteria}`, originalError);
|
|
437
|
+
this.name = 'DataNotFoundError';
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
class DataConflictError extends PersistenceError {
|
|
441
|
+
constructor(entity, criteria, originalError) {
|
|
442
|
+
super(`Data conflict for ${entity} with criteria: ${criteria}`, originalError);
|
|
443
|
+
this.name = 'DataConflictError';
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
class DataValidationError extends PersistenceError {
|
|
447
|
+
constructor(message, originalError) {
|
|
448
|
+
super(`Data Validation Error: ${message}`, originalError);
|
|
449
|
+
this.name = 'DataValidationError';
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
class TransactionError extends PersistenceError {
|
|
453
|
+
constructor(message, originalError) {
|
|
454
|
+
super(`Transaction Error: ${message}`, originalError);
|
|
455
|
+
this.name = 'TransactionError';
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
class QueryExecutionError extends PersistenceError {
|
|
459
|
+
constructor(query, originalError) {
|
|
460
|
+
super(`Query Execution Error for query: ${query}`, originalError);
|
|
461
|
+
this.name = 'QueryExecutionError';
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
class ConnectionError extends PersistenceError {
|
|
465
|
+
constructor(databaseType, originalError) {
|
|
466
|
+
super(`Connection Error to ${databaseType} database`, originalError);
|
|
467
|
+
this.name = 'ConnectionError';
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
class SchemaMismatchError extends PersistenceError {
|
|
471
|
+
constructor(expectedSchema, actualSchema, originalError) {
|
|
472
|
+
super(`Schema Mismatch Error: expected ${expectedSchema}, got ${actualSchema}`, originalError);
|
|
473
|
+
this.name = 'SchemaMismatchError';
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
class DataIntegrityError extends PersistenceError {
|
|
477
|
+
constructor(message, originalError) {
|
|
478
|
+
super(`Data Integrity Error: ${message}`, originalError);
|
|
479
|
+
this.name = 'DataIntegrityError';
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
class BackupError extends PersistenceError {
|
|
483
|
+
constructor(message, originalError) {
|
|
484
|
+
super(`Backup Error: ${message}`, originalError);
|
|
485
|
+
this.name = 'BackupError';
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
class RestoreError extends PersistenceError {
|
|
489
|
+
constructor(message, originalError) {
|
|
490
|
+
super(`Restore Error: ${message}`, originalError);
|
|
491
|
+
this.name = 'RestoreError';
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
class IndexingError extends PersistenceError {
|
|
495
|
+
constructor(indexName, originalError) {
|
|
496
|
+
super(`Indexing Error on index: ${indexName}`, originalError);
|
|
497
|
+
this.name = 'IndexingError';
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
class DataMigrationError extends PersistenceError {
|
|
501
|
+
constructor(migrationName, originalError) {
|
|
502
|
+
super(`Data Migration Error during migration: ${migrationName}`, originalError);
|
|
503
|
+
this.name = 'DataMigrationError';
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
class ResourceLimitError extends PersistenceError {
|
|
507
|
+
constructor(resourceType, limit, originalError) {
|
|
508
|
+
super(`Resource Limit Exceeded: ${resourceType} limit of ${limit} has been exceeded`, originalError);
|
|
509
|
+
this.name = 'ResourceLimitError';
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* Errores de lógica de negocio (Business Layer)
|
|
515
|
+
* No conocen HTTP, son agnósticos a la infraestructura
|
|
516
|
+
*/
|
|
517
|
+
class DomainError extends Error {
|
|
518
|
+
constructor(message) {
|
|
519
|
+
super(message);
|
|
520
|
+
this.name = 'DomainError';
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
class EntityNotFoundError extends DomainError {
|
|
524
|
+
constructor(entity, criteria) {
|
|
525
|
+
super(`${entity} not found with criteria: ${criteria}`);
|
|
526
|
+
this.name = 'EntityNotFoundError';
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
class DuplicateEntityError extends DomainError {
|
|
530
|
+
constructor(entity, criteria) {
|
|
531
|
+
super(`Duplicate ${entity} found with criteria: ${criteria}`);
|
|
532
|
+
this.name = 'DuplicateEntityError';
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
class ValidationError extends DomainError {
|
|
536
|
+
constructor(message) {
|
|
537
|
+
super(`Validation Error: ${message}`);
|
|
538
|
+
this.name = 'ValidationError';
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
class BusinessRuleViolationError extends DomainError {
|
|
542
|
+
constructor(message) {
|
|
543
|
+
super(`Business Rule Violation: ${message}`);
|
|
544
|
+
this.name = 'BusinessRuleViolationError';
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
class OperationNotAllowedError extends DomainError {
|
|
548
|
+
constructor(operation) {
|
|
549
|
+
super(`Operation not allowed: ${operation}`);
|
|
550
|
+
this.name = 'OperationNotAllowedError';
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
class DependencyError extends DomainError {
|
|
554
|
+
constructor(dependency, message) {
|
|
555
|
+
super(`Dependency Error in ${dependency}: ${message}`);
|
|
556
|
+
this.name = 'DependencyError';
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
class TimeoutError extends DomainError {
|
|
560
|
+
constructor(operation, timeout) {
|
|
561
|
+
super(`Timeout Error: Operation "${operation}" exceeded time limit of ${timeout}ms`);
|
|
562
|
+
this.name = 'TimeoutError';
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
class ResourceLimitExceededError extends DomainError {
|
|
566
|
+
constructor(resource, limit) {
|
|
567
|
+
super(`Resource Limit Exceeded: ${resource} limit of ${limit} has been exceeded`);
|
|
568
|
+
this.name = 'ResourceLimitExceededError';
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
class ConfigurationError extends DomainError {
|
|
572
|
+
constructor(message) {
|
|
573
|
+
super(`Configuration Error: ${message}`);
|
|
574
|
+
this.name = 'ConfigurationError';
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
class InfrastructureError extends Error {
|
|
579
|
+
constructor(message, originalError) {
|
|
580
|
+
super(message);
|
|
581
|
+
this.originalError = originalError;
|
|
582
|
+
this.name = 'InfrastructureError';
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
class InfraDatabaseConnectionError extends InfrastructureError {
|
|
586
|
+
constructor(dbType, originalError) {
|
|
587
|
+
super(`Failed to connect to the ${dbType} database`, originalError);
|
|
588
|
+
this.name = 'InfraDatabaseConnectionError';
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
class InfraCacheConnectionError extends InfrastructureError {
|
|
592
|
+
constructor(cacheType, originalError) {
|
|
593
|
+
super(`Failed to connect to the ${cacheType} cache`, originalError);
|
|
594
|
+
this.name = 'InfraCacheConnectionError';
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
class InfraMessageQueueError extends InfrastructureError {
|
|
598
|
+
constructor(queueType, originalError) {
|
|
599
|
+
super(`Message Queue Error in ${queueType}`, originalError);
|
|
600
|
+
this.name = 'InfraMessageQueueError';
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
class InfraExternalServiceError extends InfrastructureError {
|
|
604
|
+
constructor(serviceName, originalError) {
|
|
605
|
+
super(`External Service Error: ${serviceName}`, originalError);
|
|
606
|
+
this.name = 'InfraExternalServiceError';
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
class InfraConfigurationError extends InfrastructureError {
|
|
610
|
+
constructor(configItem, originalError) {
|
|
611
|
+
super(`Configuration Error: ${configItem}`, originalError);
|
|
612
|
+
this.name = 'InfraConfigurationError';
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
class InfraNetworkError extends InfrastructureError {
|
|
616
|
+
constructor(message, originalError) {
|
|
617
|
+
super(`Network Error: ${message}`, originalError);
|
|
618
|
+
this.name = 'InfraNetworkError';
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
class InfraTimeoutError extends InfrastructureError {
|
|
622
|
+
constructor(operation, timeout, originalError) {
|
|
623
|
+
super(`Timeout Error: Operation "${operation}" exceeded time limit of ${timeout}ms`, originalError);
|
|
624
|
+
this.name = 'InfraTimeoutError';
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
class InfraAuthenticationError extends InfrastructureError {
|
|
628
|
+
constructor(message, originalError) {
|
|
629
|
+
super(`Authentication Error: ${message}`, originalError);
|
|
630
|
+
this.name = 'InfraAuthenticationError';
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
class InfraAuthorizationError extends InfrastructureError {
|
|
634
|
+
constructor(message, originalError) {
|
|
635
|
+
super(`Authorization Error: ${message}`, originalError);
|
|
636
|
+
this.name = 'InfraAuthorizationError';
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
class InfraServiceUnavailableError extends InfrastructureError {
|
|
640
|
+
constructor(serviceName, originalError) {
|
|
641
|
+
super(`Service Unavailable: ${serviceName}`, originalError);
|
|
642
|
+
this.name = 'InfraServiceUnavailableError';
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
class InfraDataSerializationError extends InfrastructureError {
|
|
646
|
+
constructor(dataType, originalError) {
|
|
647
|
+
super(`Data Serialization Error for type: ${dataType}`, originalError);
|
|
648
|
+
this.name = 'InfraDataSerializationError';
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
class InfraDataDeserializationError extends InfrastructureError {
|
|
652
|
+
constructor(dataType, originalError) {
|
|
653
|
+
super(`Data Deserialization Error for type: ${dataType}`, originalError);
|
|
654
|
+
this.name = 'InfraDataDeserializationError';
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
export { ApiResponse, BackupError, BadRequestError, Body, BusinessRuleViolationError, ConfigurationError, ConflictError, ConnectionError, Controller, Cookies, Custom, CustomHttpError, DataConflictError, DataIntegrityError, DataMigrationError, DataNotFoundError, DataValidationError, Delete, DependencyError, DomainError, DuplicateEntityError, EntityNotFoundError, File, Files, ForbiddenError, GatewayTimeoutError, Get, Head, Header, Headers, Host, HttpError, HttpErrorWithDetails, HttpMethod, IndexingError, InfraAuthenticationError, InfraAuthorizationError, InfraCacheConnectionError, InfraConfigurationError, InfraDataDeserializationError, InfraDataSerializationError, InfraDatabaseConnectionError, InfraExternalServiceError, InfraMessageQueueError, InfraNetworkError, InfraServiceUnavailableError, InfraTimeoutError, InfrastructureError, InternalServerError, Ip, Locale, METADATA_KEYS, Next, NotFoundError, OperationNotAllowedError, Options, Param, ParamType, Patch, PersistenceError, Post, Put, Query, QueryExecutionError, Redirect, Req, ReqAuth, ReqContext, ReqPermissions, ReqUser, Request, Res, ResourceLimitError, ResourceLimitExceededError, Response, RestoreError, SchemaMismatchError, Serialize, ServiceUnavailableError, Session, SetMetadata, TimeoutError, TransactionError, Transform, UnauthorizedError, UnprocessableEntityError, UseGuards, UseInterceptors, Validate, ValidationError, isRedirectResponse };
|
package/dist/hemia-common.js
CHANGED
|
@@ -8,12 +8,16 @@ const METADATA_KEYS = {
|
|
|
8
8
|
PARAMS: 'params',
|
|
9
9
|
HEADERS: 'headers',
|
|
10
10
|
REDIRECT: 'redirect',
|
|
11
|
+
COOKIES: 'cookies',
|
|
11
12
|
GUARDS: 'hemia:guards',
|
|
12
13
|
INTERCEPTORS: 'hemia:interceptors',
|
|
13
14
|
CUSTOM: 'hemia:custom',
|
|
14
15
|
SERIALIZE: 'hemia:serialize',
|
|
15
16
|
ROLES: 'hemia:roles',
|
|
16
|
-
PERMISSIONS: 'hemia:permissions'
|
|
17
|
+
PERMISSIONS: 'hemia:permissions',
|
|
18
|
+
TRANSFORMERS: 'hemia:transformers',
|
|
19
|
+
VALIDATORS: 'hemia:validators',
|
|
20
|
+
CUSTOMS: 'hemia:customs',
|
|
17
21
|
};
|
|
18
22
|
|
|
19
23
|
const Controller = (basePath = '/') => {
|
|
@@ -45,6 +49,14 @@ exports.ParamType = void 0;
|
|
|
45
49
|
ParamType["SESSION"] = "SESSION";
|
|
46
50
|
ParamType["IP"] = "IP";
|
|
47
51
|
ParamType["HOST"] = "HOST";
|
|
52
|
+
ParamType["COOKIES"] = "COOKIES";
|
|
53
|
+
ParamType["FILES"] = "FILES";
|
|
54
|
+
ParamType["FILE"] = "FILE";
|
|
55
|
+
ParamType["LOCALE"] = "LOCALE";
|
|
56
|
+
ParamType["AUTH"] = "AUTH";
|
|
57
|
+
ParamType["USER"] = "USER";
|
|
58
|
+
ParamType["PERMISSIONS"] = "PERMISSIONS";
|
|
59
|
+
ParamType["CONTEXT"] = "CONTEXT";
|
|
48
60
|
})(exports.ParamType || (exports.ParamType = {}));
|
|
49
61
|
|
|
50
62
|
const createMethodDecorator = (method) => {
|
|
@@ -73,18 +85,126 @@ const createParamDecorator = (type) => {
|
|
|
73
85
|
};
|
|
74
86
|
};
|
|
75
87
|
};
|
|
88
|
+
/**
|
|
89
|
+
* Inyecta el objeto Request completo.
|
|
90
|
+
* @example
|
|
91
|
+
* async handler(@Request() req) {}
|
|
92
|
+
*/
|
|
76
93
|
const Request = createParamDecorator(exports.ParamType.REQUEST);
|
|
94
|
+
/**
|
|
95
|
+
* Alias para Request.
|
|
96
|
+
* @example
|
|
97
|
+
* async handler(@Req() req) {}
|
|
98
|
+
*/
|
|
77
99
|
const Req = createParamDecorator(exports.ParamType.REQUEST);
|
|
100
|
+
/**
|
|
101
|
+
* Inyecta el objeto Response.
|
|
102
|
+
* @example
|
|
103
|
+
* async handler(@Response() res) {}
|
|
104
|
+
*/
|
|
78
105
|
const Response = createParamDecorator(exports.ParamType.RESPONSE);
|
|
106
|
+
/**
|
|
107
|
+
* Alias para Response.
|
|
108
|
+
* @example
|
|
109
|
+
* async handler(@Res() res) {}
|
|
110
|
+
*/
|
|
79
111
|
const Res = createParamDecorator(exports.ParamType.RESPONSE);
|
|
112
|
+
/**
|
|
113
|
+
* Inyecta el objeto Next para middlewares.
|
|
114
|
+
* @example
|
|
115
|
+
* async handler(@Next() next) {}
|
|
116
|
+
*/
|
|
80
117
|
const Next = createParamDecorator(exports.ParamType.NEXT);
|
|
118
|
+
/**
|
|
119
|
+
* Inyecta la sesión del usuario.
|
|
120
|
+
* @example
|
|
121
|
+
* async handler(@Session() session) {}
|
|
122
|
+
*/
|
|
81
123
|
const Session = createParamDecorator(exports.ParamType.SESSION);
|
|
124
|
+
/**
|
|
125
|
+
* Inyecta la IP del cliente.
|
|
126
|
+
* @example
|
|
127
|
+
* async handler(@Ip() ip) {}
|
|
128
|
+
*/
|
|
82
129
|
const Ip = createParamDecorator(exports.ParamType.IP);
|
|
130
|
+
/**
|
|
131
|
+
* Inyecta el host de la solicitud.
|
|
132
|
+
* @example
|
|
133
|
+
* async handler(@Host() host) {}
|
|
134
|
+
*/
|
|
83
135
|
const Host = createParamDecorator(exports.ParamType.HOST);
|
|
136
|
+
/**
|
|
137
|
+
* Inyecta el cuerpo de la solicitud.
|
|
138
|
+
* @example
|
|
139
|
+
* async handler(@Body() body) {}
|
|
140
|
+
*/
|
|
84
141
|
const Body = createParamDecorator(exports.ParamType.BODY);
|
|
142
|
+
/**
|
|
143
|
+
* Inyecta los parámetros de consulta (query).
|
|
144
|
+
* @example
|
|
145
|
+
* async handler(@Query('search') search) {}
|
|
146
|
+
*/
|
|
85
147
|
const Query = createParamDecorator(exports.ParamType.QUERY);
|
|
148
|
+
/**
|
|
149
|
+
* Inyecta los parámetros de la URL.
|
|
150
|
+
* @example
|
|
151
|
+
* async handler(@Param('id') id) {}
|
|
152
|
+
*/
|
|
86
153
|
const Param = createParamDecorator(exports.ParamType.PARAM);
|
|
154
|
+
/**
|
|
155
|
+
* Inyecta los encabezados de la solicitud.
|
|
156
|
+
* @example
|
|
157
|
+
* async handler(@Headers('authorization') auth) {}
|
|
158
|
+
*/
|
|
87
159
|
const Headers = createParamDecorator(exports.ParamType.HEADERS);
|
|
160
|
+
/**
|
|
161
|
+
* Inyecta los cookies de la solicitud.
|
|
162
|
+
* @example
|
|
163
|
+
* async handler(@Cookies('token') token) {}
|
|
164
|
+
*/
|
|
165
|
+
const Cookies = createParamDecorator(exports.ParamType.COOKIES);
|
|
166
|
+
/**
|
|
167
|
+
* Inyecta todos los archivos enviados en la solicitud.
|
|
168
|
+
* @example
|
|
169
|
+
* async handler(@Files() files) {}
|
|
170
|
+
*/
|
|
171
|
+
const Files = createParamDecorator(exports.ParamType.FILES);
|
|
172
|
+
/**
|
|
173
|
+
* Inyecta un archivo específico de la solicitud.
|
|
174
|
+
* @example
|
|
175
|
+
* async handler(@File('avatar') avatar) {}
|
|
176
|
+
*/
|
|
177
|
+
const File = createParamDecorator(exports.ParamType.FILE);
|
|
178
|
+
/**
|
|
179
|
+
* Inyecta el locale del usuario.
|
|
180
|
+
* @example
|
|
181
|
+
* async handler(@Locale() locale) {}
|
|
182
|
+
*/
|
|
183
|
+
const Locale = createParamDecorator(exports.ParamType.LOCALE);
|
|
184
|
+
/**
|
|
185
|
+
* Inyecta datos de autenticación.
|
|
186
|
+
* @example
|
|
187
|
+
* async handler(@ReqAuth() auth) {}
|
|
188
|
+
*/
|
|
189
|
+
const ReqAuth = createParamDecorator(exports.ParamType.AUTH);
|
|
190
|
+
/**
|
|
191
|
+
* Inyecta el usuario autenticado.
|
|
192
|
+
* @example
|
|
193
|
+
* async handler(@ReqUser() user) {}
|
|
194
|
+
*/
|
|
195
|
+
const ReqUser = createParamDecorator(exports.ParamType.USER);
|
|
196
|
+
/**
|
|
197
|
+
* Inyecta los permisos del usuario.
|
|
198
|
+
* @example
|
|
199
|
+
* async handler(@ReqPermissions() permissions) {}
|
|
200
|
+
*/
|
|
201
|
+
const ReqPermissions = createParamDecorator(exports.ParamType.PERMISSIONS);
|
|
202
|
+
/**
|
|
203
|
+
* Inyecta el contexto de la solicitud.
|
|
204
|
+
* @example
|
|
205
|
+
* async handler(@ReqContext() context) {}
|
|
206
|
+
*/
|
|
207
|
+
const ReqContext = createParamDecorator(exports.ParamType.CONTEXT);
|
|
88
208
|
|
|
89
209
|
const Header = (name, value) => {
|
|
90
210
|
return (target, propertyKey, descriptor) => {
|
|
@@ -164,6 +284,60 @@ function Serialize(dto) {
|
|
|
164
284
|
return SetMetadata(METADATA_KEYS.SERIALIZE, dto);
|
|
165
285
|
}
|
|
166
286
|
|
|
287
|
+
/**
|
|
288
|
+
* Decorador para extraer datos personalizados del request.
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* // Extrae el valor de 'customData' del request
|
|
292
|
+
* @Custom('customData')
|
|
293
|
+
* async handler(@Custom() customData: any) {}
|
|
294
|
+
*
|
|
295
|
+
* @param key Clave personalizada a extraer del request.
|
|
296
|
+
*/
|
|
297
|
+
function Custom(key) {
|
|
298
|
+
return (target, propertyKey, parameterIndex) => {
|
|
299
|
+
const existingCustoms = Reflect.getMetadata(METADATA_KEYS.CUSTOMS, target, propertyKey || '') || [];
|
|
300
|
+
existingCustoms.push({ index: parameterIndex, key });
|
|
301
|
+
Reflect.defineMetadata(METADATA_KEYS.CUSTOMS, existingCustoms, target, propertyKey || '');
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Decorador para validar datos de entrada en un controlador.
|
|
307
|
+
*
|
|
308
|
+
* @example
|
|
309
|
+
* // Valida el parámetro 'body' usando la función validateUser
|
|
310
|
+
* @Validate(validateUser)
|
|
311
|
+
* async create(@Body() body: any) {}
|
|
312
|
+
*
|
|
313
|
+
* @param validator Función de validación que recibe el valor y retorna booleano o lanza error.
|
|
314
|
+
*/
|
|
315
|
+
function Validate(validator) {
|
|
316
|
+
return (target, propertyKey, parameterIndex) => {
|
|
317
|
+
const existingValidators = Reflect.getMetadata(METADATA_KEYS.VALIDATORS, target, propertyKey || '') || [];
|
|
318
|
+
existingValidators.push({ index: parameterIndex, validator });
|
|
319
|
+
Reflect.defineMetadata(METADATA_KEYS.VALIDATORS, existingValidators, target, propertyKey || '');
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Decorador para transformar datos de entrada en un controlador.
|
|
325
|
+
*
|
|
326
|
+
* @example
|
|
327
|
+
* // Transforma el parámetro 'body' usando la función toUserDto
|
|
328
|
+
* @Transform(toUserDto)
|
|
329
|
+
* async create(@Body() body: any) {}
|
|
330
|
+
*
|
|
331
|
+
* @param transformer Función de transformación que recibe el valor y retorna el nuevo valor.
|
|
332
|
+
*/
|
|
333
|
+
function Transform(transformer) {
|
|
334
|
+
return (target, propertyKey, parameterIndex) => {
|
|
335
|
+
const existingTransformers = Reflect.getMetadata(METADATA_KEYS.TRANSFORMERS, target, propertyKey || '') || [];
|
|
336
|
+
existingTransformers.push({ index: parameterIndex, transformer });
|
|
337
|
+
Reflect.defineMetadata(METADATA_KEYS.TRANSFORMERS, existingTransformers, target, propertyKey || '');
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
|
|
167
341
|
class ApiResponse {
|
|
168
342
|
static success(data, message = 'OK', status = 200) {
|
|
169
343
|
return {
|
|
@@ -252,13 +426,261 @@ class HttpErrorWithDetails extends HttpError {
|
|
|
252
426
|
}
|
|
253
427
|
}
|
|
254
428
|
|
|
429
|
+
class PersistenceError extends Error {
|
|
430
|
+
constructor(message, originalError) {
|
|
431
|
+
super(message);
|
|
432
|
+
this.originalError = originalError;
|
|
433
|
+
this.name = 'PersistenceError';
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
class DataNotFoundError extends PersistenceError {
|
|
437
|
+
constructor(entity, criteria, originalError) {
|
|
438
|
+
super(`${entity} not found with criteria: ${criteria}`, originalError);
|
|
439
|
+
this.name = 'DataNotFoundError';
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
class DataConflictError extends PersistenceError {
|
|
443
|
+
constructor(entity, criteria, originalError) {
|
|
444
|
+
super(`Data conflict for ${entity} with criteria: ${criteria}`, originalError);
|
|
445
|
+
this.name = 'DataConflictError';
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
class DataValidationError extends PersistenceError {
|
|
449
|
+
constructor(message, originalError) {
|
|
450
|
+
super(`Data Validation Error: ${message}`, originalError);
|
|
451
|
+
this.name = 'DataValidationError';
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
class TransactionError extends PersistenceError {
|
|
455
|
+
constructor(message, originalError) {
|
|
456
|
+
super(`Transaction Error: ${message}`, originalError);
|
|
457
|
+
this.name = 'TransactionError';
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
class QueryExecutionError extends PersistenceError {
|
|
461
|
+
constructor(query, originalError) {
|
|
462
|
+
super(`Query Execution Error for query: ${query}`, originalError);
|
|
463
|
+
this.name = 'QueryExecutionError';
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
class ConnectionError extends PersistenceError {
|
|
467
|
+
constructor(databaseType, originalError) {
|
|
468
|
+
super(`Connection Error to ${databaseType} database`, originalError);
|
|
469
|
+
this.name = 'ConnectionError';
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
class SchemaMismatchError extends PersistenceError {
|
|
473
|
+
constructor(expectedSchema, actualSchema, originalError) {
|
|
474
|
+
super(`Schema Mismatch Error: expected ${expectedSchema}, got ${actualSchema}`, originalError);
|
|
475
|
+
this.name = 'SchemaMismatchError';
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
class DataIntegrityError extends PersistenceError {
|
|
479
|
+
constructor(message, originalError) {
|
|
480
|
+
super(`Data Integrity Error: ${message}`, originalError);
|
|
481
|
+
this.name = 'DataIntegrityError';
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
class BackupError extends PersistenceError {
|
|
485
|
+
constructor(message, originalError) {
|
|
486
|
+
super(`Backup Error: ${message}`, originalError);
|
|
487
|
+
this.name = 'BackupError';
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
class RestoreError extends PersistenceError {
|
|
491
|
+
constructor(message, originalError) {
|
|
492
|
+
super(`Restore Error: ${message}`, originalError);
|
|
493
|
+
this.name = 'RestoreError';
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
class IndexingError extends PersistenceError {
|
|
497
|
+
constructor(indexName, originalError) {
|
|
498
|
+
super(`Indexing Error on index: ${indexName}`, originalError);
|
|
499
|
+
this.name = 'IndexingError';
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
class DataMigrationError extends PersistenceError {
|
|
503
|
+
constructor(migrationName, originalError) {
|
|
504
|
+
super(`Data Migration Error during migration: ${migrationName}`, originalError);
|
|
505
|
+
this.name = 'DataMigrationError';
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
class ResourceLimitError extends PersistenceError {
|
|
509
|
+
constructor(resourceType, limit, originalError) {
|
|
510
|
+
super(`Resource Limit Exceeded: ${resourceType} limit of ${limit} has been exceeded`, originalError);
|
|
511
|
+
this.name = 'ResourceLimitError';
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Errores de lógica de negocio (Business Layer)
|
|
517
|
+
* No conocen HTTP, son agnósticos a la infraestructura
|
|
518
|
+
*/
|
|
519
|
+
class DomainError extends Error {
|
|
520
|
+
constructor(message) {
|
|
521
|
+
super(message);
|
|
522
|
+
this.name = 'DomainError';
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
class EntityNotFoundError extends DomainError {
|
|
526
|
+
constructor(entity, criteria) {
|
|
527
|
+
super(`${entity} not found with criteria: ${criteria}`);
|
|
528
|
+
this.name = 'EntityNotFoundError';
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
class DuplicateEntityError extends DomainError {
|
|
532
|
+
constructor(entity, criteria) {
|
|
533
|
+
super(`Duplicate ${entity} found with criteria: ${criteria}`);
|
|
534
|
+
this.name = 'DuplicateEntityError';
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
class ValidationError extends DomainError {
|
|
538
|
+
constructor(message) {
|
|
539
|
+
super(`Validation Error: ${message}`);
|
|
540
|
+
this.name = 'ValidationError';
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
class BusinessRuleViolationError extends DomainError {
|
|
544
|
+
constructor(message) {
|
|
545
|
+
super(`Business Rule Violation: ${message}`);
|
|
546
|
+
this.name = 'BusinessRuleViolationError';
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
class OperationNotAllowedError extends DomainError {
|
|
550
|
+
constructor(operation) {
|
|
551
|
+
super(`Operation not allowed: ${operation}`);
|
|
552
|
+
this.name = 'OperationNotAllowedError';
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
class DependencyError extends DomainError {
|
|
556
|
+
constructor(dependency, message) {
|
|
557
|
+
super(`Dependency Error in ${dependency}: ${message}`);
|
|
558
|
+
this.name = 'DependencyError';
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
class TimeoutError extends DomainError {
|
|
562
|
+
constructor(operation, timeout) {
|
|
563
|
+
super(`Timeout Error: Operation "${operation}" exceeded time limit of ${timeout}ms`);
|
|
564
|
+
this.name = 'TimeoutError';
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
class ResourceLimitExceededError extends DomainError {
|
|
568
|
+
constructor(resource, limit) {
|
|
569
|
+
super(`Resource Limit Exceeded: ${resource} limit of ${limit} has been exceeded`);
|
|
570
|
+
this.name = 'ResourceLimitExceededError';
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
class ConfigurationError extends DomainError {
|
|
574
|
+
constructor(message) {
|
|
575
|
+
super(`Configuration Error: ${message}`);
|
|
576
|
+
this.name = 'ConfigurationError';
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
class InfrastructureError extends Error {
|
|
581
|
+
constructor(message, originalError) {
|
|
582
|
+
super(message);
|
|
583
|
+
this.originalError = originalError;
|
|
584
|
+
this.name = 'InfrastructureError';
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
class InfraDatabaseConnectionError extends InfrastructureError {
|
|
588
|
+
constructor(dbType, originalError) {
|
|
589
|
+
super(`Failed to connect to the ${dbType} database`, originalError);
|
|
590
|
+
this.name = 'InfraDatabaseConnectionError';
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
class InfraCacheConnectionError extends InfrastructureError {
|
|
594
|
+
constructor(cacheType, originalError) {
|
|
595
|
+
super(`Failed to connect to the ${cacheType} cache`, originalError);
|
|
596
|
+
this.name = 'InfraCacheConnectionError';
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
class InfraMessageQueueError extends InfrastructureError {
|
|
600
|
+
constructor(queueType, originalError) {
|
|
601
|
+
super(`Message Queue Error in ${queueType}`, originalError);
|
|
602
|
+
this.name = 'InfraMessageQueueError';
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
class InfraExternalServiceError extends InfrastructureError {
|
|
606
|
+
constructor(serviceName, originalError) {
|
|
607
|
+
super(`External Service Error: ${serviceName}`, originalError);
|
|
608
|
+
this.name = 'InfraExternalServiceError';
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
class InfraConfigurationError extends InfrastructureError {
|
|
612
|
+
constructor(configItem, originalError) {
|
|
613
|
+
super(`Configuration Error: ${configItem}`, originalError);
|
|
614
|
+
this.name = 'InfraConfigurationError';
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
class InfraNetworkError extends InfrastructureError {
|
|
618
|
+
constructor(message, originalError) {
|
|
619
|
+
super(`Network Error: ${message}`, originalError);
|
|
620
|
+
this.name = 'InfraNetworkError';
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
class InfraTimeoutError extends InfrastructureError {
|
|
624
|
+
constructor(operation, timeout, originalError) {
|
|
625
|
+
super(`Timeout Error: Operation "${operation}" exceeded time limit of ${timeout}ms`, originalError);
|
|
626
|
+
this.name = 'InfraTimeoutError';
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
class InfraAuthenticationError extends InfrastructureError {
|
|
630
|
+
constructor(message, originalError) {
|
|
631
|
+
super(`Authentication Error: ${message}`, originalError);
|
|
632
|
+
this.name = 'InfraAuthenticationError';
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
class InfraAuthorizationError extends InfrastructureError {
|
|
636
|
+
constructor(message, originalError) {
|
|
637
|
+
super(`Authorization Error: ${message}`, originalError);
|
|
638
|
+
this.name = 'InfraAuthorizationError';
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
class InfraServiceUnavailableError extends InfrastructureError {
|
|
642
|
+
constructor(serviceName, originalError) {
|
|
643
|
+
super(`Service Unavailable: ${serviceName}`, originalError);
|
|
644
|
+
this.name = 'InfraServiceUnavailableError';
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
class InfraDataSerializationError extends InfrastructureError {
|
|
648
|
+
constructor(dataType, originalError) {
|
|
649
|
+
super(`Data Serialization Error for type: ${dataType}`, originalError);
|
|
650
|
+
this.name = 'InfraDataSerializationError';
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
class InfraDataDeserializationError extends InfrastructureError {
|
|
654
|
+
constructor(dataType, originalError) {
|
|
655
|
+
super(`Data Deserialization Error for type: ${dataType}`, originalError);
|
|
656
|
+
this.name = 'InfraDataDeserializationError';
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
|
|
255
660
|
exports.ApiResponse = ApiResponse;
|
|
661
|
+
exports.BackupError = BackupError;
|
|
256
662
|
exports.BadRequestError = BadRequestError;
|
|
257
663
|
exports.Body = Body;
|
|
664
|
+
exports.BusinessRuleViolationError = BusinessRuleViolationError;
|
|
665
|
+
exports.ConfigurationError = ConfigurationError;
|
|
258
666
|
exports.ConflictError = ConflictError;
|
|
667
|
+
exports.ConnectionError = ConnectionError;
|
|
259
668
|
exports.Controller = Controller;
|
|
669
|
+
exports.Cookies = Cookies;
|
|
670
|
+
exports.Custom = Custom;
|
|
260
671
|
exports.CustomHttpError = CustomHttpError;
|
|
672
|
+
exports.DataConflictError = DataConflictError;
|
|
673
|
+
exports.DataIntegrityError = DataIntegrityError;
|
|
674
|
+
exports.DataMigrationError = DataMigrationError;
|
|
675
|
+
exports.DataNotFoundError = DataNotFoundError;
|
|
676
|
+
exports.DataValidationError = DataValidationError;
|
|
261
677
|
exports.Delete = Delete;
|
|
678
|
+
exports.DependencyError = DependencyError;
|
|
679
|
+
exports.DomainError = DomainError;
|
|
680
|
+
exports.DuplicateEntityError = DuplicateEntityError;
|
|
681
|
+
exports.EntityNotFoundError = EntityNotFoundError;
|
|
682
|
+
exports.File = File;
|
|
683
|
+
exports.Files = Files;
|
|
262
684
|
exports.ForbiddenError = ForbiddenError;
|
|
263
685
|
exports.GatewayTimeoutError = GatewayTimeoutError;
|
|
264
686
|
exports.Get = Get;
|
|
@@ -268,28 +690,59 @@ exports.Headers = Headers;
|
|
|
268
690
|
exports.Host = Host;
|
|
269
691
|
exports.HttpError = HttpError;
|
|
270
692
|
exports.HttpErrorWithDetails = HttpErrorWithDetails;
|
|
693
|
+
exports.IndexingError = IndexingError;
|
|
694
|
+
exports.InfraAuthenticationError = InfraAuthenticationError;
|
|
695
|
+
exports.InfraAuthorizationError = InfraAuthorizationError;
|
|
696
|
+
exports.InfraCacheConnectionError = InfraCacheConnectionError;
|
|
697
|
+
exports.InfraConfigurationError = InfraConfigurationError;
|
|
698
|
+
exports.InfraDataDeserializationError = InfraDataDeserializationError;
|
|
699
|
+
exports.InfraDataSerializationError = InfraDataSerializationError;
|
|
700
|
+
exports.InfraDatabaseConnectionError = InfraDatabaseConnectionError;
|
|
701
|
+
exports.InfraExternalServiceError = InfraExternalServiceError;
|
|
702
|
+
exports.InfraMessageQueueError = InfraMessageQueueError;
|
|
703
|
+
exports.InfraNetworkError = InfraNetworkError;
|
|
704
|
+
exports.InfraServiceUnavailableError = InfraServiceUnavailableError;
|
|
705
|
+
exports.InfraTimeoutError = InfraTimeoutError;
|
|
706
|
+
exports.InfrastructureError = InfrastructureError;
|
|
271
707
|
exports.InternalServerError = InternalServerError;
|
|
272
708
|
exports.Ip = Ip;
|
|
709
|
+
exports.Locale = Locale;
|
|
273
710
|
exports.METADATA_KEYS = METADATA_KEYS;
|
|
274
711
|
exports.Next = Next;
|
|
275
712
|
exports.NotFoundError = NotFoundError;
|
|
713
|
+
exports.OperationNotAllowedError = OperationNotAllowedError;
|
|
276
714
|
exports.Options = Options;
|
|
277
715
|
exports.Param = Param;
|
|
278
716
|
exports.Patch = Patch;
|
|
717
|
+
exports.PersistenceError = PersistenceError;
|
|
279
718
|
exports.Post = Post;
|
|
280
719
|
exports.Put = Put;
|
|
281
720
|
exports.Query = Query;
|
|
721
|
+
exports.QueryExecutionError = QueryExecutionError;
|
|
282
722
|
exports.Redirect = Redirect;
|
|
283
723
|
exports.Req = Req;
|
|
724
|
+
exports.ReqAuth = ReqAuth;
|
|
725
|
+
exports.ReqContext = ReqContext;
|
|
726
|
+
exports.ReqPermissions = ReqPermissions;
|
|
727
|
+
exports.ReqUser = ReqUser;
|
|
284
728
|
exports.Request = Request;
|
|
285
729
|
exports.Res = Res;
|
|
730
|
+
exports.ResourceLimitError = ResourceLimitError;
|
|
731
|
+
exports.ResourceLimitExceededError = ResourceLimitExceededError;
|
|
286
732
|
exports.Response = Response;
|
|
733
|
+
exports.RestoreError = RestoreError;
|
|
734
|
+
exports.SchemaMismatchError = SchemaMismatchError;
|
|
287
735
|
exports.Serialize = Serialize;
|
|
288
736
|
exports.ServiceUnavailableError = ServiceUnavailableError;
|
|
289
737
|
exports.Session = Session;
|
|
290
738
|
exports.SetMetadata = SetMetadata;
|
|
739
|
+
exports.TimeoutError = TimeoutError;
|
|
740
|
+
exports.TransactionError = TransactionError;
|
|
741
|
+
exports.Transform = Transform;
|
|
291
742
|
exports.UnauthorizedError = UnauthorizedError;
|
|
292
743
|
exports.UnprocessableEntityError = UnprocessableEntityError;
|
|
293
744
|
exports.UseGuards = UseGuards;
|
|
294
745
|
exports.UseInterceptors = UseInterceptors;
|
|
746
|
+
exports.Validate = Validate;
|
|
747
|
+
exports.ValidationError = ValidationError;
|
|
295
748
|
exports.isRedirectResponse = isRedirectResponse;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
/**
|
|
3
|
+
* Decorador para extraer datos personalizados del request.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* // Extrae el valor de 'customData' del request
|
|
7
|
+
* @Custom('customData')
|
|
8
|
+
* async handler(@Custom() customData: any) {}
|
|
9
|
+
*
|
|
10
|
+
* @param key Clave personalizada a extraer del request.
|
|
11
|
+
*/
|
|
12
|
+
export declare function Custom(key: string): ParameterDecorator;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './custom.decorator';
|
|
@@ -1,13 +1,121 @@
|
|
|
1
1
|
import 'reflect-metadata';
|
|
2
|
+
/**
|
|
3
|
+
* Inyecta el objeto Request completo.
|
|
4
|
+
* @example
|
|
5
|
+
* async handler(@Request() req) {}
|
|
6
|
+
*/
|
|
2
7
|
export declare const Request: (data?: string) => ParameterDecorator;
|
|
8
|
+
/**
|
|
9
|
+
* Alias para Request.
|
|
10
|
+
* @example
|
|
11
|
+
* async handler(@Req() req) {}
|
|
12
|
+
*/
|
|
3
13
|
export declare const Req: (data?: string) => ParameterDecorator;
|
|
14
|
+
/**
|
|
15
|
+
* Inyecta el objeto Response.
|
|
16
|
+
* @example
|
|
17
|
+
* async handler(@Response() res) {}
|
|
18
|
+
*/
|
|
4
19
|
export declare const Response: (data?: string) => ParameterDecorator;
|
|
20
|
+
/**
|
|
21
|
+
* Alias para Response.
|
|
22
|
+
* @example
|
|
23
|
+
* async handler(@Res() res) {}
|
|
24
|
+
*/
|
|
5
25
|
export declare const Res: (data?: string) => ParameterDecorator;
|
|
26
|
+
/**
|
|
27
|
+
* Inyecta el objeto Next para middlewares.
|
|
28
|
+
* @example
|
|
29
|
+
* async handler(@Next() next) {}
|
|
30
|
+
*/
|
|
6
31
|
export declare const Next: (data?: string) => ParameterDecorator;
|
|
32
|
+
/**
|
|
33
|
+
* Inyecta la sesión del usuario.
|
|
34
|
+
* @example
|
|
35
|
+
* async handler(@Session() session) {}
|
|
36
|
+
*/
|
|
7
37
|
export declare const Session: (data?: string) => ParameterDecorator;
|
|
38
|
+
/**
|
|
39
|
+
* Inyecta la IP del cliente.
|
|
40
|
+
* @example
|
|
41
|
+
* async handler(@Ip() ip) {}
|
|
42
|
+
*/
|
|
8
43
|
export declare const Ip: (data?: string) => ParameterDecorator;
|
|
44
|
+
/**
|
|
45
|
+
* Inyecta el host de la solicitud.
|
|
46
|
+
* @example
|
|
47
|
+
* async handler(@Host() host) {}
|
|
48
|
+
*/
|
|
9
49
|
export declare const Host: (data?: string) => ParameterDecorator;
|
|
50
|
+
/**
|
|
51
|
+
* Inyecta el cuerpo de la solicitud.
|
|
52
|
+
* @example
|
|
53
|
+
* async handler(@Body() body) {}
|
|
54
|
+
*/
|
|
10
55
|
export declare const Body: (data?: string) => ParameterDecorator;
|
|
56
|
+
/**
|
|
57
|
+
* Inyecta los parámetros de consulta (query).
|
|
58
|
+
* @example
|
|
59
|
+
* async handler(@Query('search') search) {}
|
|
60
|
+
*/
|
|
11
61
|
export declare const Query: (data?: string) => ParameterDecorator;
|
|
62
|
+
/**
|
|
63
|
+
* Inyecta los parámetros de la URL.
|
|
64
|
+
* @example
|
|
65
|
+
* async handler(@Param('id') id) {}
|
|
66
|
+
*/
|
|
12
67
|
export declare const Param: (data?: string) => ParameterDecorator;
|
|
68
|
+
/**
|
|
69
|
+
* Inyecta los encabezados de la solicitud.
|
|
70
|
+
* @example
|
|
71
|
+
* async handler(@Headers('authorization') auth) {}
|
|
72
|
+
*/
|
|
13
73
|
export declare const Headers: (data?: string) => ParameterDecorator;
|
|
74
|
+
/**
|
|
75
|
+
* Inyecta los cookies de la solicitud.
|
|
76
|
+
* @example
|
|
77
|
+
* async handler(@Cookies('token') token) {}
|
|
78
|
+
*/
|
|
79
|
+
export declare const Cookies: (data?: string) => ParameterDecorator;
|
|
80
|
+
/**
|
|
81
|
+
* Inyecta todos los archivos enviados en la solicitud.
|
|
82
|
+
* @example
|
|
83
|
+
* async handler(@Files() files) {}
|
|
84
|
+
*/
|
|
85
|
+
export declare const Files: (data?: string) => ParameterDecorator;
|
|
86
|
+
/**
|
|
87
|
+
* Inyecta un archivo específico de la solicitud.
|
|
88
|
+
* @example
|
|
89
|
+
* async handler(@File('avatar') avatar) {}
|
|
90
|
+
*/
|
|
91
|
+
export declare const File: (data?: string) => ParameterDecorator;
|
|
92
|
+
/**
|
|
93
|
+
* Inyecta el locale del usuario.
|
|
94
|
+
* @example
|
|
95
|
+
* async handler(@Locale() locale) {}
|
|
96
|
+
*/
|
|
97
|
+
export declare const Locale: (data?: string) => ParameterDecorator;
|
|
98
|
+
/**
|
|
99
|
+
* Inyecta datos de autenticación.
|
|
100
|
+
* @example
|
|
101
|
+
* async handler(@ReqAuth() auth) {}
|
|
102
|
+
*/
|
|
103
|
+
export declare const ReqAuth: (data?: string) => ParameterDecorator;
|
|
104
|
+
/**
|
|
105
|
+
* Inyecta el usuario autenticado.
|
|
106
|
+
* @example
|
|
107
|
+
* async handler(@ReqUser() user) {}
|
|
108
|
+
*/
|
|
109
|
+
export declare const ReqUser: (data?: string) => ParameterDecorator;
|
|
110
|
+
/**
|
|
111
|
+
* Inyecta los permisos del usuario.
|
|
112
|
+
* @example
|
|
113
|
+
* async handler(@ReqPermissions() permissions) {}
|
|
114
|
+
*/
|
|
115
|
+
export declare const ReqPermissions: (data?: string) => ParameterDecorator;
|
|
116
|
+
/**
|
|
117
|
+
* Inyecta el contexto de la solicitud.
|
|
118
|
+
* @example
|
|
119
|
+
* async handler(@ReqContext() context) {}
|
|
120
|
+
*/
|
|
121
|
+
export declare const ReqContext: (data?: string) => ParameterDecorator;
|
|
@@ -4,10 +4,14 @@ export declare const METADATA_KEYS: {
|
|
|
4
4
|
readonly PARAMS: "params";
|
|
5
5
|
readonly HEADERS: "headers";
|
|
6
6
|
readonly REDIRECT: "redirect";
|
|
7
|
+
readonly COOKIES: "cookies";
|
|
7
8
|
readonly GUARDS: "hemia:guards";
|
|
8
9
|
readonly INTERCEPTORS: "hemia:interceptors";
|
|
9
10
|
readonly CUSTOM: "hemia:custom";
|
|
10
11
|
readonly SERIALIZE: "hemia:serialize";
|
|
11
12
|
readonly ROLES: "hemia:roles";
|
|
12
13
|
readonly PERMISSIONS: "hemia:permissions";
|
|
14
|
+
readonly TRANSFORMERS: "hemia:transformers";
|
|
15
|
+
readonly VALIDATORS: "hemia:validators";
|
|
16
|
+
readonly CUSTOMS: "hemia:customs";
|
|
13
17
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './transform.decorator';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
/**
|
|
3
|
+
* Decorador para transformar datos de entrada en un controlador.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* // Transforma el parámetro 'body' usando la función toUserDto
|
|
7
|
+
* @Transform(toUserDto)
|
|
8
|
+
* async create(@Body() body: any) {}
|
|
9
|
+
*
|
|
10
|
+
* @param transformer Función de transformación que recibe el valor y retorna el nuevo valor.
|
|
11
|
+
*/
|
|
12
|
+
export declare function Transform(transformer: (value: any) => any): ParameterDecorator;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./validate.decorator";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
/**
|
|
3
|
+
* Decorador para validar datos de entrada en un controlador.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* // Valida el parámetro 'body' usando la función validateUser
|
|
7
|
+
* @Validate(validateUser)
|
|
8
|
+
* async create(@Body() body: any) {}
|
|
9
|
+
*
|
|
10
|
+
* @param validator Función de validación que recibe el valor y retorna booleano o lanza error.
|
|
11
|
+
*/
|
|
12
|
+
export declare function Validate(validator: (value: any) => boolean | void): ParameterDecorator;
|
|
@@ -8,5 +8,13 @@ export declare enum ParamType {
|
|
|
8
8
|
HEADERS = "HEADERS",
|
|
9
9
|
SESSION = "SESSION",
|
|
10
10
|
IP = "IP",
|
|
11
|
-
HOST = "HOST"
|
|
11
|
+
HOST = "HOST",
|
|
12
|
+
COOKIES = "COOKIES",
|
|
13
|
+
FILES = "FILES",
|
|
14
|
+
FILE = "FILE",
|
|
15
|
+
LOCALE = "LOCALE",
|
|
16
|
+
AUTH = "AUTH",
|
|
17
|
+
USER = "USER",
|
|
18
|
+
PERMISSIONS = "PERMISSIONS",
|
|
19
|
+
CONTEXT = "CONTEXT"
|
|
12
20
|
}
|
|
@@ -12,3 +12,4 @@ export * from './configuration/mongo-db-configuration.interface';
|
|
|
12
12
|
export * from './configuration/aws-s3-configuration.interface';
|
|
13
13
|
export * from './configuration/drizzle-db-configuration.interface';
|
|
14
14
|
export * from './configuration/olap-db-configuration.interface';
|
|
15
|
+
export * from './configuration/smtp-configuration.interface';
|