@hemia/common 0.0.2 → 0.0.3

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.
@@ -5,7 +5,10 @@ const METADATA_KEYS = {
5
5
  ROUTES: 'routes',
6
6
  PARAMS: 'params',
7
7
  HEADERS: 'headers',
8
- REDIRECT: 'redirect'
8
+ REDIRECT: 'redirect',
9
+ GUARDS: 'hemia:guards',
10
+ INTERCEPTORS: 'hemia:interceptors',
11
+ CUSTOM: 'hemia:custom'
9
12
  };
10
13
 
11
14
  const Controller = (basePath = '/') => {
@@ -94,6 +97,63 @@ const Redirect = (url, statusCode = 302) => {
94
97
  };
95
98
  };
96
99
 
100
+ function extendArrayMetadata(key, metadata, target) {
101
+ const previousValue = Reflect.getMetadata(key, target) || [];
102
+ const value = [...previousValue, ...metadata];
103
+ Reflect.defineMetadata(key, value, target);
104
+ }
105
+
106
+ /**
107
+ * Decorador que vincula Guards al controlador o método.
108
+ * @param guards Una lista de clases Guard o instancias de Guard.
109
+ */
110
+ function UseGuards(...guards) {
111
+ return (target, key, descriptor) => {
112
+ guards.filter(guard => guard && (typeof guard === 'function' || typeof guard === 'object'));
113
+ if (descriptor) {
114
+ extendArrayMetadata(METADATA_KEYS.GUARDS, guards, descriptor.value);
115
+ return descriptor;
116
+ }
117
+ extendArrayMetadata(METADATA_KEYS.GUARDS, guards, target);
118
+ return target;
119
+ };
120
+ }
121
+
122
+ /**
123
+ * Decorador que vincula Interceptores al controlador o método.
124
+ * @param interceptors Una lista de clases Interceptor o instancias.
125
+ */
126
+ function UseInterceptors(...interceptors) {
127
+ return (target, key, descriptor) => {
128
+ const validInterceptors = interceptors.filter(i => i && (typeof i === 'function' || typeof i === 'object'));
129
+ if (descriptor) {
130
+ extendArrayMetadata(METADATA_KEYS.INTERCEPTORS, validInterceptors, descriptor.value);
131
+ return descriptor;
132
+ }
133
+ extendArrayMetadata(METADATA_KEYS.INTERCEPTORS, validInterceptors, target);
134
+ return target;
135
+ };
136
+ }
137
+
138
+ class ApiResponse {
139
+ static success(data, message = 'OK', status = 200) {
140
+ return {
141
+ success: true,
142
+ message,
143
+ data,
144
+ status,
145
+ };
146
+ }
147
+ static error(message, error = null, status = 500) {
148
+ return {
149
+ success: false,
150
+ message,
151
+ error,
152
+ status,
153
+ };
154
+ }
155
+ }
156
+
97
157
  function isRedirectResponse(value) {
98
158
  return value && typeof value === 'object' && typeof value.url === 'string';
99
159
  }
@@ -163,4 +223,4 @@ class HttpErrorWithDetails extends HttpError {
163
223
  }
164
224
  }
165
225
 
166
- export { 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, ServiceUnavailableError, Session, UnauthorizedError, UnprocessableEntityError, isRedirectResponse };
226
+ 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, ServiceUnavailableError, Session, UnauthorizedError, UnprocessableEntityError, UseGuards, UseInterceptors, isRedirectResponse };
@@ -7,7 +7,10 @@ const METADATA_KEYS = {
7
7
  ROUTES: 'routes',
8
8
  PARAMS: 'params',
9
9
  HEADERS: 'headers',
10
- REDIRECT: 'redirect'
10
+ REDIRECT: 'redirect',
11
+ GUARDS: 'hemia:guards',
12
+ INTERCEPTORS: 'hemia:interceptors',
13
+ CUSTOM: 'hemia:custom'
11
14
  };
12
15
 
13
16
  const Controller = (basePath = '/') => {
@@ -96,6 +99,63 @@ const Redirect = (url, statusCode = 302) => {
96
99
  };
97
100
  };
98
101
 
102
+ function extendArrayMetadata(key, metadata, target) {
103
+ const previousValue = Reflect.getMetadata(key, target) || [];
104
+ const value = [...previousValue, ...metadata];
105
+ Reflect.defineMetadata(key, value, target);
106
+ }
107
+
108
+ /**
109
+ * Decorador que vincula Guards al controlador o método.
110
+ * @param guards Una lista de clases Guard o instancias de Guard.
111
+ */
112
+ function UseGuards(...guards) {
113
+ return (target, key, descriptor) => {
114
+ guards.filter(guard => guard && (typeof guard === 'function' || typeof guard === 'object'));
115
+ if (descriptor) {
116
+ extendArrayMetadata(METADATA_KEYS.GUARDS, guards, descriptor.value);
117
+ return descriptor;
118
+ }
119
+ extendArrayMetadata(METADATA_KEYS.GUARDS, guards, target);
120
+ return target;
121
+ };
122
+ }
123
+
124
+ /**
125
+ * Decorador que vincula Interceptores al controlador o método.
126
+ * @param interceptors Una lista de clases Interceptor o instancias.
127
+ */
128
+ function UseInterceptors(...interceptors) {
129
+ return (target, key, descriptor) => {
130
+ const validInterceptors = interceptors.filter(i => i && (typeof i === 'function' || typeof i === 'object'));
131
+ if (descriptor) {
132
+ extendArrayMetadata(METADATA_KEYS.INTERCEPTORS, validInterceptors, descriptor.value);
133
+ return descriptor;
134
+ }
135
+ extendArrayMetadata(METADATA_KEYS.INTERCEPTORS, validInterceptors, target);
136
+ return target;
137
+ };
138
+ }
139
+
140
+ class ApiResponse {
141
+ static success(data, message = 'OK', status = 200) {
142
+ return {
143
+ success: true,
144
+ message,
145
+ data,
146
+ status,
147
+ };
148
+ }
149
+ static error(message, error = null, status = 500) {
150
+ return {
151
+ success: false,
152
+ message,
153
+ error,
154
+ status,
155
+ };
156
+ }
157
+ }
158
+
99
159
  function isRedirectResponse(value) {
100
160
  return value && typeof value === 'object' && typeof value.url === 'string';
101
161
  }
@@ -165,6 +225,7 @@ class HttpErrorWithDetails extends HttpError {
165
225
  }
166
226
  }
167
227
 
228
+ exports.ApiResponse = ApiResponse;
168
229
  exports.BadRequestError = BadRequestError;
169
230
  exports.Body = Body;
170
231
  exports.ConflictError = ConflictError;
@@ -200,4 +261,6 @@ exports.ServiceUnavailableError = ServiceUnavailableError;
200
261
  exports.Session = Session;
201
262
  exports.UnauthorizedError = UnauthorizedError;
202
263
  exports.UnprocessableEntityError = UnprocessableEntityError;
264
+ exports.UseGuards = UseGuards;
265
+ exports.UseInterceptors = UseInterceptors;
203
266
  exports.isRedirectResponse = isRedirectResponse;
@@ -0,0 +1,2 @@
1
+ export * from "./use-guards.decorator";
2
+ export * from "./use-interceptors.decorator";
@@ -0,0 +1,7 @@
1
+ import 'reflect-metadata';
2
+ import { CanActivate, Type } from '../../interfaces';
3
+ /**
4
+ * Decorador que vincula Guards al controlador o método.
5
+ * @param guards Una lista de clases Guard o instancias de Guard.
6
+ */
7
+ export declare function UseGuards(...guards: (Type<CanActivate> | CanActivate | Function)[]): (target: object | Function, key?: string | symbol, descriptor?: PropertyDescriptor) => object;
@@ -0,0 +1,7 @@
1
+ import 'reflect-metadata';
2
+ import { HemiaInterceptor, Type } from '../../interfaces';
3
+ /**
4
+ * Decorador que vincula Interceptores al controlador o método.
5
+ * @param interceptors Una lista de clases Interceptor o instancias.
6
+ */
7
+ export declare function UseInterceptors(...interceptors: (Type<HemiaInterceptor> | HemiaInterceptor | Function)[]): (target: object | Function, key?: string | symbol, descriptor?: PropertyDescriptor) => object;
@@ -1,2 +1,3 @@
1
- export * from "./controllers";
1
+ export * from "./http";
2
2
  export * from "./metadata";
3
+ export * from "./core";
@@ -4,4 +4,7 @@ export declare const METADATA_KEYS: {
4
4
  readonly PARAMS: "params";
5
5
  readonly HEADERS: "headers";
6
6
  readonly REDIRECT: "redirect";
7
+ readonly GUARDS: "hemia:guards";
8
+ readonly INTERCEPTORS: "hemia:interceptors";
9
+ readonly CUSTOM: "hemia:custom";
7
10
  };
@@ -0,0 +1,2 @@
1
+ import 'reflect-metadata';
2
+ export declare function extendArrayMetadata<T>(key: string, metadata: T[], target: object | Function): void;
@@ -0,0 +1,4 @@
1
+ import { ExecutionContext } from "./features/execution-context.interface";
2
+ export interface CanActivate {
3
+ canActivate(context: ExecutionContext): boolean | Promise<boolean>;
4
+ }
@@ -0,0 +1,13 @@
1
+ export interface IResponseData<T> {
2
+ success: boolean;
3
+ data?: T;
4
+ message: string;
5
+ error?: any;
6
+ }
7
+ export interface IApiResponse<T> extends IResponseData<T> {
8
+ status: number;
9
+ }
10
+ export declare class ApiResponse {
11
+ static success<T>(data: T, message?: string, status?: number): IApiResponse<T>;
12
+ static error(message: string, error?: any, status?: number): IApiResponse<null>;
13
+ }
@@ -0,0 +1,18 @@
1
+ export interface HttpArgumentsHost {
2
+ /** Retorna el objeto Request nativo (Express) */
3
+ getRequest<T = any>(): T;
4
+ /** Retorna el objeto Response nativo (Express) */
5
+ getResponse<T = any>(): T;
6
+ /** Retorna la función Next nativa (Express) */
7
+ getNext<T = any>(): T;
8
+ }
9
+ export interface ArgumentsHost {
10
+ /** Retorna el array de argumentos original [req, res, next] */
11
+ getArgs<T extends Array<any> = any[]>(): T;
12
+ /** Retorna un argumento específico por índice */
13
+ getArgByIndex<T = any>(index: number): T;
14
+ /** Cambia el contexto a HTTP para obtener métodos tipados */
15
+ switchToHttp(): HttpArgumentsHost;
16
+ /** Retorna el tipo de contexto actual (ej: 'http') */
17
+ getType<TContext extends string = string>(): TContext;
18
+ }
@@ -0,0 +1,14 @@
1
+ import { Type } from "../type.interface";
2
+ import { ArgumentsHost } from "./arguments-host.interface";
3
+ export interface ExecutionContext extends ArgumentsHost {
4
+ /**
5
+ * Retorna la CLASE (Constructor) del controlador que se está ejecutando.
6
+ * Útil para leer metadata a nivel de clase (ej. @Roles('admin') sobre la clase)
7
+ */
8
+ getClass<T = any>(): Type<T>;
9
+ /**
10
+ * Retorna la FUNCIÓN (Método) del handler que se está ejecutando.
11
+ * Útil para leer metadata a nivel de método (ej. @Public() sobre el método)
12
+ */
13
+ getHandler(): Function;
14
+ }
@@ -0,0 +1,3 @@
1
+ export interface CallHandler<T = any> {
2
+ handle(): Promise<T>;
3
+ }
@@ -1,2 +1,9 @@
1
1
  export * from './param.interface';
2
2
  export * from './route.interface';
3
+ export * from './api-response.interface';
4
+ export * from './activate.interface';
5
+ export * from './features/execution-context.interface';
6
+ export * from "./features/arguments-host.interface";
7
+ export * from './type.interface';
8
+ export * from './handler.interface';
9
+ export * from './interceptor.interface';
@@ -0,0 +1,5 @@
1
+ import { ExecutionContext } from "./features/execution-context.interface";
2
+ import { CallHandler } from "./handler.interface";
3
+ export interface HemiaInterceptor<T = any, R = any> {
4
+ intercept(context: ExecutionContext, next: CallHandler<T>): Promise<R>;
5
+ }
@@ -0,0 +1 @@
1
+ export type Type<T = any> = new (...args: any[]) => T;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hemia/common",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
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",