@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 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
-
@@ -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
- export { ApiResponse, BadRequestError, Body, ConflictError, Controller, CustomHttpError, Delete, ForbiddenError, GatewayTimeoutError, Get, Head, Header, Headers, Host, HttpError, HttpErrorWithDetails, HttpMethod, InternalServerError, Ip, METADATA_KEYS, Next, NotFoundError, Options, Param, ParamType, Patch, Post, Put, Query, Redirect, Req, Request, Res, Response, Serialize, ServiceUnavailableError, Session, SetMetadata, UnauthorizedError, UnprocessableEntityError, UseGuards, UseInterceptors, isRedirectResponse };
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 };
@@ -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;
@@ -1,3 +1,6 @@
1
1
  export * from "./http";
2
2
  export * from "./metadata";
3
3
  export * from "./core";
4
+ export * from "./custom";
5
+ export * from "./validation";
6
+ export * from "./transform";
@@ -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
  }
@@ -1 +1,4 @@
1
1
  export * from "./http.error";
2
+ export * from "./persistence.error";
3
+ export * from "./domain.error";
4
+ export * from "./infrastructure.error";
@@ -0,0 +1,7 @@
1
+ export interface SmtpConfiguration {
2
+ SMTP_HOST: string;
3
+ SMTP_PORT: number;
4
+ SMTP_USER: string;
5
+ SMTP_PASSWORD: string;
6
+ SMTP_SECURE: boolean;
7
+ }
@@ -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';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hemia/common",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "Paquete común para proyectos de Hemia",
5
5
  "main": "dist/hemia-common.js",
6
6
  "module": "dist/hemia-common.esm.js",