@hemia/common 0.0.6 → 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 {
@@ -481,4 +655,4 @@ class InfraDataDeserializationError extends InfrastructureError {
481
655
  }
482
656
  }
483
657
 
484
- export { ApiResponse, BackupError, BadRequestError, Body, BusinessRuleViolationError, ConfigurationError, ConflictError, ConnectionError, Controller, CustomHttpError, DataConflictError, DataIntegrityError, DataMigrationError, DataNotFoundError, DataValidationError, Delete, DependencyError, DomainError, DuplicateEntityError, EntityNotFoundError, 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, METADATA_KEYS, Next, NotFoundError, OperationNotAllowedError, Options, Param, ParamType, Patch, PersistenceError, Post, Put, Query, QueryExecutionError, Redirect, Req, Request, Res, ResourceLimitError, ResourceLimitExceededError, Response, RestoreError, SchemaMismatchError, Serialize, ServiceUnavailableError, Session, SetMetadata, TimeoutError, TransactionError, UnauthorizedError, UnprocessableEntityError, UseGuards, UseInterceptors, ValidationError, isRedirectResponse };
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 {
@@ -492,6 +666,8 @@ exports.ConfigurationError = ConfigurationError;
492
666
  exports.ConflictError = ConflictError;
493
667
  exports.ConnectionError = ConnectionError;
494
668
  exports.Controller = Controller;
669
+ exports.Cookies = Cookies;
670
+ exports.Custom = Custom;
495
671
  exports.CustomHttpError = CustomHttpError;
496
672
  exports.DataConflictError = DataConflictError;
497
673
  exports.DataIntegrityError = DataIntegrityError;
@@ -503,6 +679,8 @@ exports.DependencyError = DependencyError;
503
679
  exports.DomainError = DomainError;
504
680
  exports.DuplicateEntityError = DuplicateEntityError;
505
681
  exports.EntityNotFoundError = EntityNotFoundError;
682
+ exports.File = File;
683
+ exports.Files = Files;
506
684
  exports.ForbiddenError = ForbiddenError;
507
685
  exports.GatewayTimeoutError = GatewayTimeoutError;
508
686
  exports.Get = Get;
@@ -528,6 +706,7 @@ exports.InfraTimeoutError = InfraTimeoutError;
528
706
  exports.InfrastructureError = InfrastructureError;
529
707
  exports.InternalServerError = InternalServerError;
530
708
  exports.Ip = Ip;
709
+ exports.Locale = Locale;
531
710
  exports.METADATA_KEYS = METADATA_KEYS;
532
711
  exports.Next = Next;
533
712
  exports.NotFoundError = NotFoundError;
@@ -542,6 +721,10 @@ exports.Query = Query;
542
721
  exports.QueryExecutionError = QueryExecutionError;
543
722
  exports.Redirect = Redirect;
544
723
  exports.Req = Req;
724
+ exports.ReqAuth = ReqAuth;
725
+ exports.ReqContext = ReqContext;
726
+ exports.ReqPermissions = ReqPermissions;
727
+ exports.ReqUser = ReqUser;
545
728
  exports.Request = Request;
546
729
  exports.Res = Res;
547
730
  exports.ResourceLimitError = ResourceLimitError;
@@ -555,9 +738,11 @@ exports.Session = Session;
555
738
  exports.SetMetadata = SetMetadata;
556
739
  exports.TimeoutError = TimeoutError;
557
740
  exports.TransactionError = TransactionError;
741
+ exports.Transform = Transform;
558
742
  exports.UnauthorizedError = UnauthorizedError;
559
743
  exports.UnprocessableEntityError = UnprocessableEntityError;
560
744
  exports.UseGuards = UseGuards;
561
745
  exports.UseInterceptors = UseInterceptors;
746
+ exports.Validate = Validate;
562
747
  exports.ValidationError = ValidationError;
563
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hemia/common",
3
- "version": "0.0.6",
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",