@hemia/common 0.0.1 → 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.
Files changed (25) hide show
  1. package/dist/hemia-common.esm.js +127 -2
  2. package/dist/hemia-common.js +141 -1
  3. package/dist/types/decorators/core/index.d.ts +2 -0
  4. package/dist/types/decorators/core/use-guards.decorator.d.ts +7 -0
  5. package/dist/types/decorators/core/use-interceptors.decorator.d.ts +7 -0
  6. package/dist/types/decorators/index.d.ts +2 -1
  7. package/dist/types/decorators/metadata.d.ts +3 -0
  8. package/dist/types/decorators/utils/extend-metadata.util.d.ts +2 -0
  9. package/dist/types/errors/http.error.d.ts +40 -0
  10. package/dist/types/errors/index.d.ts +1 -0
  11. package/dist/types/index.d.ts +1 -0
  12. package/dist/types/interfaces/activate.interface.d.ts +4 -0
  13. package/dist/types/interfaces/api-response.interface.d.ts +13 -0
  14. package/dist/types/interfaces/features/arguments-host.interface.d.ts +18 -0
  15. package/dist/types/interfaces/features/execution-context.interface.d.ts +14 -0
  16. package/dist/types/interfaces/handler.interface.d.ts +3 -0
  17. package/dist/types/interfaces/index.d.ts +7 -0
  18. package/dist/types/interfaces/interceptor.interface.d.ts +5 -0
  19. package/dist/types/interfaces/type.interface.d.ts +1 -0
  20. package/package.json +1 -1
  21. /package/dist/types/decorators/{controllers → http}/controller.decorator.d.ts +0 -0
  22. /package/dist/types/decorators/{controllers → http}/index.d.ts +0 -0
  23. /package/dist/types/decorators/{controllers → http}/method.decorators.d.ts +0 -0
  24. /package/dist/types/decorators/{controllers → http}/param.decorators.d.ts +0 -0
  25. /package/dist/types/decorators/{controllers → http}/response.decorators.d.ts +0 -0
@@ -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,8 +97,130 @@ 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
  }
100
160
 
101
- export { Body, Controller, Delete, Get, Head, Header, Headers, Host, HttpMethod, Ip, METADATA_KEYS, Next, Options, Param, ParamType, Patch, Post, Put, Query, Redirect, Req, Request, Res, Response, Session, isRedirectResponse };
161
+ class HttpError extends Error {
162
+ constructor(message, statusCode, error) {
163
+ super(message);
164
+ this.message = message;
165
+ this.statusCode = statusCode;
166
+ this.error = error;
167
+ }
168
+ }
169
+ class NotFoundError extends HttpError {
170
+ constructor(message = 'Resource not found', error) {
171
+ super(message, 404, error);
172
+ }
173
+ }
174
+ class BadRequestError extends HttpError {
175
+ constructor(message = 'Invalid data', error) {
176
+ super(message, 400, error);
177
+ }
178
+ }
179
+ class UnauthorizedError extends HttpError {
180
+ constructor(message = 'Unauthorized', error) {
181
+ super(message, 401, error);
182
+ }
183
+ }
184
+ class ForbiddenError extends HttpError {
185
+ constructor(message = 'Forbidden', error) {
186
+ super(message, 403, error);
187
+ }
188
+ }
189
+ class InternalServerError extends HttpError {
190
+ constructor(message = 'Internal server error', error) {
191
+ super(message, 500, error);
192
+ }
193
+ }
194
+ class ConflictError extends HttpError {
195
+ constructor(message = 'Conflict', error) {
196
+ super(message, 409, error);
197
+ }
198
+ }
199
+ class UnprocessableEntityError extends HttpError {
200
+ constructor(message = 'Unprocessable Entity', error) {
201
+ super(message, 422, error);
202
+ }
203
+ }
204
+ class ServiceUnavailableError extends HttpError {
205
+ constructor(message = 'Service Unavailable', error) {
206
+ super(message, 503, error);
207
+ }
208
+ }
209
+ class GatewayTimeoutError extends HttpError {
210
+ constructor(message = 'Gateway Timeout', error) {
211
+ super(message, 504, error);
212
+ }
213
+ }
214
+ class CustomHttpError extends HttpError {
215
+ constructor(message, statusCode, error) {
216
+ super(message, statusCode, error);
217
+ }
218
+ }
219
+ class HttpErrorWithDetails extends HttpError {
220
+ constructor(message, statusCode, details, error) {
221
+ super(message, statusCode, error);
222
+ this.details = details;
223
+ }
224
+ }
225
+
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,21 +99,153 @@ 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
  }
102
162
 
163
+ class HttpError extends Error {
164
+ constructor(message, statusCode, error) {
165
+ super(message);
166
+ this.message = message;
167
+ this.statusCode = statusCode;
168
+ this.error = error;
169
+ }
170
+ }
171
+ class NotFoundError extends HttpError {
172
+ constructor(message = 'Resource not found', error) {
173
+ super(message, 404, error);
174
+ }
175
+ }
176
+ class BadRequestError extends HttpError {
177
+ constructor(message = 'Invalid data', error) {
178
+ super(message, 400, error);
179
+ }
180
+ }
181
+ class UnauthorizedError extends HttpError {
182
+ constructor(message = 'Unauthorized', error) {
183
+ super(message, 401, error);
184
+ }
185
+ }
186
+ class ForbiddenError extends HttpError {
187
+ constructor(message = 'Forbidden', error) {
188
+ super(message, 403, error);
189
+ }
190
+ }
191
+ class InternalServerError extends HttpError {
192
+ constructor(message = 'Internal server error', error) {
193
+ super(message, 500, error);
194
+ }
195
+ }
196
+ class ConflictError extends HttpError {
197
+ constructor(message = 'Conflict', error) {
198
+ super(message, 409, error);
199
+ }
200
+ }
201
+ class UnprocessableEntityError extends HttpError {
202
+ constructor(message = 'Unprocessable Entity', error) {
203
+ super(message, 422, error);
204
+ }
205
+ }
206
+ class ServiceUnavailableError extends HttpError {
207
+ constructor(message = 'Service Unavailable', error) {
208
+ super(message, 503, error);
209
+ }
210
+ }
211
+ class GatewayTimeoutError extends HttpError {
212
+ constructor(message = 'Gateway Timeout', error) {
213
+ super(message, 504, error);
214
+ }
215
+ }
216
+ class CustomHttpError extends HttpError {
217
+ constructor(message, statusCode, error) {
218
+ super(message, statusCode, error);
219
+ }
220
+ }
221
+ class HttpErrorWithDetails extends HttpError {
222
+ constructor(message, statusCode, details, error) {
223
+ super(message, statusCode, error);
224
+ this.details = details;
225
+ }
226
+ }
227
+
228
+ exports.ApiResponse = ApiResponse;
229
+ exports.BadRequestError = BadRequestError;
103
230
  exports.Body = Body;
231
+ exports.ConflictError = ConflictError;
104
232
  exports.Controller = Controller;
233
+ exports.CustomHttpError = CustomHttpError;
105
234
  exports.Delete = Delete;
235
+ exports.ForbiddenError = ForbiddenError;
236
+ exports.GatewayTimeoutError = GatewayTimeoutError;
106
237
  exports.Get = Get;
107
238
  exports.Head = Head;
108
239
  exports.Header = Header;
109
240
  exports.Headers = Headers;
110
241
  exports.Host = Host;
242
+ exports.HttpError = HttpError;
243
+ exports.HttpErrorWithDetails = HttpErrorWithDetails;
244
+ exports.InternalServerError = InternalServerError;
111
245
  exports.Ip = Ip;
112
246
  exports.METADATA_KEYS = METADATA_KEYS;
113
247
  exports.Next = Next;
248
+ exports.NotFoundError = NotFoundError;
114
249
  exports.Options = Options;
115
250
  exports.Param = Param;
116
251
  exports.Patch = Patch;
@@ -122,5 +257,10 @@ exports.Req = Req;
122
257
  exports.Request = Request;
123
258
  exports.Res = Res;
124
259
  exports.Response = Response;
260
+ exports.ServiceUnavailableError = ServiceUnavailableError;
125
261
  exports.Session = Session;
262
+ exports.UnauthorizedError = UnauthorizedError;
263
+ exports.UnprocessableEntityError = UnprocessableEntityError;
264
+ exports.UseGuards = UseGuards;
265
+ exports.UseInterceptors = UseInterceptors;
126
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,40 @@
1
+ export declare class HttpError extends Error {
2
+ message: string;
3
+ statusCode: number;
4
+ error?: string | undefined;
5
+ constructor(message: string, statusCode: number, error?: string | undefined);
6
+ }
7
+ export declare class NotFoundError extends HttpError {
8
+ constructor(message?: string, error?: string);
9
+ }
10
+ export declare class BadRequestError extends HttpError {
11
+ constructor(message?: string, error?: string);
12
+ }
13
+ export declare class UnauthorizedError extends HttpError {
14
+ constructor(message?: string, error?: string);
15
+ }
16
+ export declare class ForbiddenError extends HttpError {
17
+ constructor(message?: string, error?: string);
18
+ }
19
+ export declare class InternalServerError extends HttpError {
20
+ constructor(message?: string, error?: string);
21
+ }
22
+ export declare class ConflictError extends HttpError {
23
+ constructor(message?: string, error?: string);
24
+ }
25
+ export declare class UnprocessableEntityError extends HttpError {
26
+ constructor(message?: string, error?: string);
27
+ }
28
+ export declare class ServiceUnavailableError extends HttpError {
29
+ constructor(message?: string, error?: string);
30
+ }
31
+ export declare class GatewayTimeoutError extends HttpError {
32
+ constructor(message?: string, error?: string);
33
+ }
34
+ export declare class CustomHttpError extends HttpError {
35
+ constructor(message: string, statusCode: number, error?: string);
36
+ }
37
+ export declare class HttpErrorWithDetails extends HttpError {
38
+ details: any;
39
+ constructor(message: string, statusCode: number, details: any, error?: string);
40
+ }
@@ -0,0 +1 @@
1
+ export * from "./http.error";
@@ -4,3 +4,4 @@ export * from "./enums";
4
4
  export * from "./interfaces";
5
5
  export * from "./types";
6
6
  export * from "./utils";
7
+ export * from "./errors";
@@ -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.1",
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",