@zenofolio/hyper-decor 1.0.67 → 1.0.69

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 (56) hide show
  1. package/dist/__internals/constants.d.ts +2 -1
  2. package/dist/__internals/constants.js +2 -1
  3. package/dist/__internals/helpers/prepare.helper.js +33 -0
  4. package/dist/__internals/helpers/tree.helper.d.ts +8 -4
  5. package/dist/__internals/helpers/tree.helper.js +47 -14
  6. package/dist/__internals/transform/transform.registry.d.ts +33 -0
  7. package/dist/__internals/transform/transform.registry.js +59 -0
  8. package/dist/common/helpers/index.d.ts +1 -0
  9. package/dist/common/helpers/index.js +1 -0
  10. package/dist/common/helpers/state.d.ts +17 -0
  11. package/dist/common/helpers/state.js +44 -0
  12. package/dist/decorators/Http.js +1 -1
  13. package/dist/decorators/HyperApp.d.ts +0 -4
  14. package/dist/decorators/HyperApp.js +9 -6
  15. package/dist/decorators/Transform.d.ts +14 -0
  16. package/dist/decorators/Transform.js +18 -0
  17. package/dist/decorators/index.d.ts +1 -0
  18. package/dist/decorators/index.js +1 -0
  19. package/dist/extension.js +6 -0
  20. package/dist/lib/openapi/collectors/class.collector.js +24 -10
  21. package/dist/lib/openapi/collectors/index.d.ts +1 -0
  22. package/dist/lib/openapi/collectors/index.js +1 -0
  23. package/dist/lib/openapi/collectors/method.collector.d.ts +0 -1
  24. package/dist/lib/openapi/collectors/method.collector.js +21 -2
  25. package/dist/lib/openapi/collectors/schema.collector.d.ts +11 -0
  26. package/dist/lib/openapi/collectors/schema.collector.js +37 -0
  27. package/dist/lib/openapi/decorators/api-bearer-auth.decorator.d.ts +2 -0
  28. package/dist/lib/openapi/decorators/api-bearer-auth.decorator.js +10 -0
  29. package/dist/lib/openapi/decorators/api-method.decorator.d.ts +1 -1
  30. package/dist/lib/openapi/decorators/api-parameter.decorator.d.ts +1 -1
  31. package/dist/lib/openapi/decorators/api-request-body.decorator.d.ts +1 -1
  32. package/dist/lib/openapi/decorators/{api-response.decodator.d.ts → api-response.decorator.d.ts} +1 -1
  33. package/dist/lib/openapi/decorators/{api-response.decodator.js → api-response.decorator.js} +1 -1
  34. package/dist/lib/openapi/decorators/api-security.decorator.d.ts +1 -1
  35. package/dist/lib/openapi/decorators/api-security.decorator.js +2 -2
  36. package/dist/lib/openapi/decorators/index.d.ts +2 -1
  37. package/dist/lib/openapi/decorators/index.js +2 -1
  38. package/dist/lib/openapi/helpers/index.d.ts +1 -0
  39. package/dist/lib/openapi/helpers/index.js +1 -0
  40. package/dist/lib/openapi/helpers/openapi.helper.d.ts +7 -0
  41. package/dist/lib/openapi/helpers/openapi.helper.js +51 -0
  42. package/dist/lib/openapi/helpers/security.helper.d.ts +1 -1
  43. package/dist/lib/openapi/helpers/security.helper.js +10 -3
  44. package/dist/lib/openapi/index.d.ts +5 -0
  45. package/dist/lib/openapi/index.js +5 -0
  46. package/dist/lib/openapi/metadata.registry.d.ts +29 -0
  47. package/dist/lib/openapi/metadata.registry.js +41 -0
  48. package/dist/type.d.ts +8 -0
  49. package/package.json +9 -6
  50. package/tsconfig.json +18 -13
  51. package/dist/run-bench.d.ts +0 -1
  52. package/dist/run-bench.js +0 -190
  53. package/dist/scripts/test-server.d.ts +0 -1
  54. package/dist/scripts/test-server.js +0 -110
  55. package/dist/vitest.config.d.ts +0 -2
  56. package/dist/vitest.config.js +0 -34
@@ -14,7 +14,8 @@ export declare const KEY_PARAMS_MIDDLEWARES = "hyper:type:middlewares";
14
14
  export declare const KEY_PARAMS_SCOPE = "hyper:type:scope";
15
15
  export declare const KEY_PARAMS_ROLE = "hyper:type:role";
16
16
  export declare const KEY_PARAMS_PASS = "hyper:type:pass";
17
- export type KeyParams = typeof KEY_PARAMS_APP | typeof KEY_PARAMS_CONTROLLER | typeof KEY_PARAMS_MODULE | typeof KEY_PARAMS_ROUTE | typeof KEY_PARAMS_PARAM | typeof KEY_PARAMS_MIDDLEWARES | typeof KEY_PARAMS_SCOPE | typeof KEY_PARAMS_ROLE | typeof KEY_PARAMS_PASS;
17
+ export declare const KEY_PARAMS_TRANSFORM = "hyper:type:transform";
18
+ export type KeyParams = typeof KEY_PARAMS_APP | typeof KEY_PARAMS_CONTROLLER | typeof KEY_PARAMS_MODULE | typeof KEY_PARAMS_ROUTE | typeof KEY_PARAMS_PARAM | typeof KEY_PARAMS_MIDDLEWARES | typeof KEY_PARAMS_SCOPE | typeof KEY_PARAMS_ROLE | typeof KEY_PARAMS_PASS | typeof KEY_PARAMS_TRANSFORM;
18
19
  export declare const KEY_STATE_UPDATED = "hyper:state:updated";
19
20
  export declare const KEY_STATE_CREATED = "hyper:state:created";
20
21
  export declare const KEY_STATE_PREPARED = "hyper:state:prepared";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FULL_ACCESS = exports.METADATA_STATE_KEYS = exports.METADATA_PARAMS_KEYS = exports.METADATA_METHOD_KEYS = exports.METADATA_STORE_KEYS = exports.METADATA_KEYS = exports.METADATA_HYPER_TYPE = exports.DESIGN_TYPE = exports.DESIGN_RETURNTYPE = exports.DESIGN_PARAMTYPES = exports.KEY_STATE_BY_PASS = exports.KEY_STATE_PREPARED = exports.KEY_STATE_CREATED = exports.KEY_STATE_UPDATED = exports.KEY_PARAMS_PASS = exports.KEY_PARAMS_ROLE = exports.KEY_PARAMS_SCOPE = exports.KEY_PARAMS_MIDDLEWARES = exports.KEY_PARAMS_PARAM = exports.KEY_PARAMS_ROUTE = exports.KEY_PARAMS_MODULE = exports.KEY_PARAMS_CONTROLLER = exports.KEY_PARAMS_APP = exports.KEY_TYPE_GUARD = exports.KEY_TYPE_SERVICE = exports.KEY_TYPE_ROUTE = exports.KEY_TYPE_MODULE = exports.KEY_TYPE_CONTROLLER = exports.KEY_TYPE_APP = void 0;
3
+ exports.FULL_ACCESS = exports.METADATA_STATE_KEYS = exports.METADATA_PARAMS_KEYS = exports.METADATA_METHOD_KEYS = exports.METADATA_STORE_KEYS = exports.METADATA_KEYS = exports.METADATA_HYPER_TYPE = exports.DESIGN_TYPE = exports.DESIGN_RETURNTYPE = exports.DESIGN_PARAMTYPES = exports.KEY_STATE_BY_PASS = exports.KEY_STATE_PREPARED = exports.KEY_STATE_CREATED = exports.KEY_STATE_UPDATED = exports.KEY_PARAMS_TRANSFORM = exports.KEY_PARAMS_PASS = exports.KEY_PARAMS_ROLE = exports.KEY_PARAMS_SCOPE = exports.KEY_PARAMS_MIDDLEWARES = exports.KEY_PARAMS_PARAM = exports.KEY_PARAMS_ROUTE = exports.KEY_PARAMS_MODULE = exports.KEY_PARAMS_CONTROLLER = exports.KEY_PARAMS_APP = exports.KEY_TYPE_GUARD = exports.KEY_TYPE_SERVICE = exports.KEY_TYPE_ROUTE = exports.KEY_TYPE_MODULE = exports.KEY_TYPE_CONTROLLER = exports.KEY_TYPE_APP = void 0;
4
4
  //////////////////////////////
5
5
  /// Types constants
6
6
  //////////////////////////////
@@ -22,6 +22,7 @@ exports.KEY_PARAMS_MIDDLEWARES = "hyper:type:middlewares";
22
22
  exports.KEY_PARAMS_SCOPE = "hyper:type:scope";
23
23
  exports.KEY_PARAMS_ROLE = "hyper:type:role";
24
24
  exports.KEY_PARAMS_PASS = "hyper:type:pass";
25
+ exports.KEY_PARAMS_TRANSFORM = "hyper:type:transform";
25
26
  //////////////////////////////
26
27
  /// State constants
27
28
  //////////////////////////////
@@ -24,8 +24,10 @@ const middleware_transform_1 = __importDefault(require("../transform/middleware.
24
24
  const tsyringe_1 = require("tsyringe");
25
25
  const path_util_1 = require("../utils/path.util");
26
26
  const imports_helper_1 = require("./imports.helper");
27
+ const constants_2 = require("../constants");
27
28
  const message_bus_1 = require("../../common/message-bus");
28
29
  const transport_1 = require("../../common/transport");
30
+ const transform_registry_1 = require("../transform/transform.registry");
29
31
  const if_router = (current) => {
30
32
  if (!current || !((current === null || current === void 0 ? void 0 : current.prototype) instanceof hyper_express_1.Router))
31
33
  return new hyper_express_1.Router();
@@ -258,6 +260,37 @@ function prepareRoutes(_a) {
258
260
  if (!$fn)
259
261
  return;
260
262
  const middlewares = [...metadata.middlewares];
263
+ // Agnostic Transform Integration
264
+ const transform = (0, decorator_base_1.getDecorData)(constants_2.KEY_PARAMS_TRANSFORM, target.prototype || target, propertyKey);
265
+ if (transform) {
266
+ middlewares.push((req, res, next) => __awaiter(this, void 0, void 0, function* () {
267
+ try {
268
+ const from = transform.options.from || "body";
269
+ let data;
270
+ if (from === "body") {
271
+ data = req.body !== undefined ? req.body : yield req.json();
272
+ }
273
+ else {
274
+ data = req[from];
275
+ }
276
+ // Resolve through the chain of responsibility
277
+ const transformed = yield transform_registry_1.transformRegistry.resolve({
278
+ data,
279
+ schema: transform.schema,
280
+ options: transform.options,
281
+ req,
282
+ res,
283
+ from
284
+ });
285
+ // Update the request object
286
+ req[from] = transformed;
287
+ next();
288
+ }
289
+ catch (err) {
290
+ next(err);
291
+ }
292
+ }));
293
+ }
261
294
  (0, role_transform_1.default)(metadata.roles, (middleware) => middlewares.push(middleware));
262
295
  (0, scope_transfrom_1.default)(metadata.scopes, (middleware, scopes) => {
263
296
  middlewares.push(middleware);
@@ -4,15 +4,18 @@ export interface AppTree {
4
4
  target: any;
5
5
  fullPath: string;
6
6
  };
7
- modules: ModuleNode[];
7
+ modules: Record<string, ModuleNode>;
8
+ paths: Record<string, RouteNode[]>;
9
+ openapi?: any;
8
10
  }
9
11
  export interface ModuleNode {
10
12
  metadata: HyperModuleMetadata;
11
13
  target: any;
12
14
  fullPath: string;
13
- modules: ModuleNode[];
14
- controllers: ControllerNode[];
15
+ modules: Record<string, ModuleNode>;
16
+ controllers: Record<string, ControllerNode>;
15
17
  services: any[];
18
+ openapi?: any;
16
19
  }
17
20
  export interface ControllerNode {
18
21
  metadata: HyperControllerMetadata;
@@ -20,13 +23,14 @@ export interface ControllerNode {
20
23
  fullPath: string;
21
24
  routes: RouteNode[];
22
25
  services: any[];
26
+ openapi?: any;
23
27
  }
24
28
  export interface RouteNode extends RouteMetadata {
25
29
  fullPath: string;
26
30
  params: any[];
31
+ openapi?: any;
27
32
  }
28
33
  /**
29
34
  * Extracts the complete application metadata tree.
30
- * This is useful for generating Swagger/OpenAPI documentation or graphing the app structure.
31
35
  */
32
36
  export declare function getAppTree(Target: any): AppTree;
@@ -4,45 +4,78 @@ exports.getAppTree = getAppTree;
4
4
  const decorator_base_1 = require("../decorator-base");
5
5
  const constants_1 = require("../constants");
6
6
  const path_util_1 = require("../utils/path.util");
7
+ const class_collector_1 = require("../../lib/openapi/collectors/class.collector");
8
+ const metadata_registry_1 = require("../../lib/openapi/metadata.registry");
7
9
  /**
8
10
  * Extracts the complete application metadata tree.
9
- * This is useful for generating Swagger/OpenAPI documentation or graphing the app structure.
10
11
  */
11
12
  function getAppTree(Target) {
12
13
  const appMetadata = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_APP, Target);
13
14
  const prefix = (appMetadata === null || appMetadata === void 0 ? void 0 : appMetadata.prefix) || "/";
14
- return {
15
+ const tree = {
15
16
  app: Object.assign(Object.assign({}, appMetadata), { target: Target, fullPath: prefix }),
16
- modules: ((appMetadata === null || appMetadata === void 0 ? void 0 : appMetadata.modules) || []).map(m => getModuleNode(m, prefix))
17
+ modules: {},
18
+ paths: {}
17
19
  };
20
+ ((appMetadata === null || appMetadata === void 0 ? void 0 : appMetadata.modules) || []).forEach(m => {
21
+ const node = getModuleNode(m, prefix, tree.paths);
22
+ tree.modules[m.name] = node;
23
+ });
24
+ // Apply tree processors
25
+ metadata_registry_1.openApiRegistry.getProcessors().forEach(processor => processor(tree));
26
+ return tree;
18
27
  }
19
- function getModuleNode(Target, parentPath = "") {
28
+ function getModuleNode(Target, parentPath = "", globalPaths = {}) {
20
29
  const metadata = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_MODULE, Target);
21
30
  const currentPath = (0, path_util_1.join)(parentPath, (metadata === null || metadata === void 0 ? void 0 : metadata.path) || "");
22
- return {
31
+ const openapi = (0, class_collector_1.collectClassMetadata)(Target);
32
+ const node = {
23
33
  metadata,
24
34
  target: Target,
25
35
  fullPath: currentPath,
26
- modules: ((metadata === null || metadata === void 0 ? void 0 : metadata.modules) || []).map(m => getModuleNode(m, currentPath)),
27
- controllers: ((metadata === null || metadata === void 0 ? void 0 : metadata.controllers) || []).map(c => getControllerNode(c, currentPath)),
28
- services: ((metadata === null || metadata === void 0 ? void 0 : metadata.imports) || [])
36
+ modules: {},
37
+ controllers: {},
38
+ services: ((metadata === null || metadata === void 0 ? void 0 : metadata.imports) || []),
39
+ openapi
29
40
  };
41
+ ((metadata === null || metadata === void 0 ? void 0 : metadata.modules) || []).forEach(m => {
42
+ node.modules[m.name] = getModuleNode(m, currentPath, globalPaths);
43
+ });
44
+ ((metadata === null || metadata === void 0 ? void 0 : metadata.controllers) || []).forEach(c => {
45
+ node.controllers[c.name] = getControllerNode(c, currentPath, globalPaths);
46
+ });
47
+ return node;
30
48
  }
31
- function getControllerNode(Target, parentPath = "") {
49
+ function getControllerNode(Target, parentPath = "", globalPaths = {}) {
50
+ var _a;
32
51
  const metadata = (0, decorator_base_1.getDecorData)(constants_1.KEY_TYPE_CONTROLLER, Target);
33
52
  const routeList = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_ROUTE, Target);
34
- const paramMetadata = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_PARAM, Target);
53
+ // Param metadata can be on the constructor or the prototype
54
+ const paramMetadata = (_a = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_PARAM, Target)) !== null && _a !== void 0 ? _a : (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_PARAM, Target.prototype);
35
55
  const currentPath = (0, path_util_1.join)(parentPath, (metadata === null || metadata === void 0 ? void 0 : metadata.path) || "");
56
+ const openapi = (0, class_collector_1.collectClassMetadata)(Target);
36
57
  const routes = Array.from((routeList === null || routeList === void 0 ? void 0 : routeList.routes) || []).map((route) => {
37
- var _a;
38
- const params = ((_a = paramMetadata === null || paramMetadata === void 0 ? void 0 : paramMetadata.params) === null || _a === void 0 ? void 0 : _a[route.propertyKey]) || [];
39
- return Object.assign(Object.assign({}, route), { fullPath: (0, path_util_1.join)(currentPath, route.path), params });
58
+ var _a, _b, _c, _d, _e, _f;
59
+ // Also try to get params from the handler itself if not in aggregated metadata
60
+ const params = (_e = (_b = (_a = paramMetadata === null || paramMetadata === void 0 ? void 0 : paramMetadata.params) === null || _a === void 0 ? void 0 : _a[route.propertyKey]) !== null && _b !== void 0 ? _b : (_d = (_c = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_PARAM, route.handler)) === null || _c === void 0 ? void 0 : _c.params) === null || _d === void 0 ? void 0 : _d[route.propertyKey]) !== null && _e !== void 0 ? _e : [];
61
+ const fullPath = (0, path_util_1.join)(currentPath, route.path);
62
+ // Get OpenAPI metadata for the method
63
+ const methodOpenApi = ((_f = openapi.methods) === null || _f === void 0 ? void 0 : _f[route.propertyKey]) || {};
64
+ const routeNode = Object.assign(Object.assign({}, route), { fullPath,
65
+ params, openapi: methodOpenApi });
66
+ // Add to global paths map
67
+ if (!globalPaths[fullPath]) {
68
+ globalPaths[fullPath] = [];
69
+ }
70
+ globalPaths[fullPath].push(routeNode);
71
+ return routeNode;
40
72
  });
41
73
  return {
42
74
  metadata,
43
75
  target: Target,
44
76
  fullPath: currentPath,
45
77
  routes,
46
- services: (metadata === null || metadata === void 0 ? void 0 : metadata.imports) || []
78
+ services: (metadata === null || metadata === void 0 ? void 0 : metadata.imports) || [],
79
+ openapi
47
80
  };
48
81
  }
@@ -0,0 +1,33 @@
1
+ import { Request, Response } from "hyper-express";
2
+ export interface TransformContext<T = any, S = any> {
3
+ data: T;
4
+ schema: S;
5
+ options: any;
6
+ req: Request;
7
+ res: Response;
8
+ from: string;
9
+ }
10
+ export type TransformHandler<T = any, S = any> = (ctx: TransformContext<T, S>) => any | Promise<any>;
11
+ export interface ITransformer<T = any, S = any> {
12
+ transform: TransformHandler<T, S>;
13
+ getOpenApiSchema?: (schema: S) => any;
14
+ }
15
+ export type TransformerInput = TransformHandler | ITransformer;
16
+ declare class TransformRegistry {
17
+ private transformers;
18
+ /**
19
+ * Register a transformer (function or object with transform method).
20
+ */
21
+ register(input: TransformerInput): void;
22
+ /**
23
+ * Iterates through registered transformers to process the data.
24
+ * Returns the transformed data or the original data if no transformer matched.
25
+ */
26
+ resolve(ctx: TransformContext): Promise<any>;
27
+ /**
28
+ * Queries transformers to get an OpenAPI schema representation.
29
+ */
30
+ getOpenApiSchema(schema: any): any | undefined;
31
+ }
32
+ export declare const transformRegistry: TransformRegistry;
33
+ export {};
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.transformRegistry = void 0;
13
+ class TransformRegistry {
14
+ constructor() {
15
+ this.transformers = [];
16
+ }
17
+ /**
18
+ * Register a transformer (function or object with transform method).
19
+ */
20
+ register(input) {
21
+ if (typeof input === 'function') {
22
+ this.transformers.push({ transform: input });
23
+ }
24
+ else {
25
+ this.transformers.push(input);
26
+ }
27
+ }
28
+ /**
29
+ * Iterates through registered transformers to process the data.
30
+ * Returns the transformed data or the original data if no transformer matched.
31
+ */
32
+ resolve(ctx) {
33
+ return __awaiter(this, void 0, void 0, function* () {
34
+ let currentData = ctx.data;
35
+ for (const transformer of this.transformers) {
36
+ const result = yield transformer.transform(Object.assign(Object.assign({}, ctx), { data: currentData }));
37
+ // If transformer returns non-undefined, we assume it's the new data (or unchanged but recognized)
38
+ if (result !== undefined) {
39
+ currentData = result;
40
+ }
41
+ }
42
+ return currentData;
43
+ });
44
+ }
45
+ /**
46
+ * Queries transformers to get an OpenAPI schema representation.
47
+ */
48
+ getOpenApiSchema(schema) {
49
+ for (const transformer of this.transformers) {
50
+ if (transformer.getOpenApiSchema) {
51
+ const result = transformer.getOpenApiSchema(schema);
52
+ if (result !== undefined)
53
+ return result;
54
+ }
55
+ }
56
+ return undefined;
57
+ }
58
+ }
59
+ exports.transformRegistry = new TransformRegistry();
@@ -1,2 +1,3 @@
1
1
  export * from "./role";
2
2
  export * from "./scopes";
3
+ export * from "./state";
@@ -16,3 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./role"), exports);
18
18
  __exportStar(require("./scopes"), exports);
19
+ __exportStar(require("./state"), exports);
@@ -0,0 +1,17 @@
1
+ import type { Request } from "hyper-express";
2
+ /**
3
+ * Save a custom value against the request directly via an internal Map
4
+ *
5
+ * @param {Request} request
6
+ * @param {string} key
7
+ * @param {any} value
8
+ */
9
+ export declare const setValue: (request: Request, key: string, value: any) => void;
10
+ /**
11
+ * Get a custom value from the request object directly via an internal Map
12
+ *
13
+ * @param {Request} request
14
+ * @param {string} key
15
+ * @param {any} defaultValue
16
+ */
17
+ export declare const getValue: <T>(request: Request, key: string, defaultValue?: T) => T | any;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getValue = exports.setValue = void 0;
4
+ const STATE_SYMBOL = Symbol("HYPER_DECOR_REQUEST_STATE");
5
+ /**
6
+ * Get or create the internal state map for the request
7
+ * @param request
8
+ * @returns
9
+ */
10
+ function getStore(request) {
11
+ if (!request[STATE_SYMBOL]) {
12
+ request[STATE_SYMBOL] = new Map();
13
+ }
14
+ return request[STATE_SYMBOL];
15
+ }
16
+ /**
17
+ * Save a custom value against the request directly via an internal Map
18
+ *
19
+ * @param {Request} request
20
+ * @param {string} key
21
+ * @param {any} value
22
+ */
23
+ const setValue = (request, key, value) => {
24
+ const store = getStore(request);
25
+ if (value === undefined) {
26
+ store.delete(key);
27
+ return;
28
+ }
29
+ store.set(key, value);
30
+ };
31
+ exports.setValue = setValue;
32
+ /**
33
+ * Get a custom value from the request object directly via an internal Map
34
+ *
35
+ * @param {Request} request
36
+ * @param {string} key
37
+ * @param {any} defaultValue
38
+ */
39
+ const getValue = (request, key, defaultValue) => {
40
+ const store = getStore(request);
41
+ const value = store.get(key);
42
+ return value !== undefined ? value : defaultValue;
43
+ };
44
+ exports.getValue = getValue;
@@ -35,7 +35,7 @@ exports.Query = Query;
35
35
  * @returns
36
36
  */
37
37
  const Body = (resolver) => (0, request_creator_1.default)("req", "BODY", (request) => __awaiter(void 0, void 0, void 0, function* () {
38
- const value = yield request.json();
38
+ const value = request.body !== undefined ? request.body : yield request.json();
39
39
  return resolver ? resolver(value) : value;
40
40
  }));
41
41
  exports.Body = Body;
@@ -1,7 +1,3 @@
1
1
  import "reflect-metadata";
2
2
  import { HyperAppDecorator } from "./types";
3
- /**
4
- * Decorator to define the main application class with assigned modules.
5
- * @param modules - List of modules to be used in the application.
6
- */
7
3
  export declare const HyperApp: HyperAppDecorator;
@@ -16,11 +16,8 @@ const tsyringe_1 = require("tsyringe");
16
16
  const constants_1 = require("../__internals/constants");
17
17
  const decorator_base_1 = require("../__internals/decorator-base");
18
18
  const merge_metadata_1 = require("../__internals/helpers/merge-metadata");
19
+ const transform_registry_1 = require("../__internals/transform/transform.registry");
19
20
  const prepare_helper_1 = require("../__internals/helpers/prepare.helper");
20
- /**
21
- * Decorator to define the main application class with assigned modules.
22
- * @param modules - List of modules to be used in the application.
23
- */
24
21
  const HyperApp = (options) => (0, decorator_base_1.DecoratorHelper)({
25
22
  type: constants_1.KEY_TYPE_APP,
26
23
  key: constants_1.KEY_PARAMS_APP,
@@ -33,6 +30,11 @@ const HyperApp = (options) => (0, decorator_base_1.DecoratorHelper)({
33
30
  this.storeLogs = {};
34
31
  this.listArguments = args;
35
32
  }
33
+ /** Registers an agnostic transformer (Zod, Joi, etc.) */
34
+ useTransform(transformer) {
35
+ transform_registry_1.transformRegistry.register(transformer);
36
+ return this;
37
+ }
36
38
  prepare() {
37
39
  return __awaiter(this, void 0, void 0, function* () {
38
40
  tsyringe_1.container.registerInstance(hyper_express_1.Server, this);
@@ -52,10 +54,11 @@ const HyperApp = (options) => (0, decorator_base_1.DecoratorHelper)({
52
54
  /** Aplica las opciones y prepara la instancia del Target */
53
55
  applyOptions(Target) {
54
56
  return __awaiter(this, void 0, void 0, function* () {
55
- var _a;
56
57
  yield (0, prepare_helper_1.prepareApplication)(options, Target, this, this.log.bind(this));
57
58
  const target = Reflect.construct(Target, this.listArguments);
58
- (_a = target === null || target === void 0 ? void 0 : target.onPrepare) === null || _a === void 0 ? void 0 : _a.call(target);
59
+ if (target && typeof target === 'object' && 'onPrepare' in target) {
60
+ target.onPrepare();
61
+ }
59
62
  this.showLogs();
60
63
  });
61
64
  }
@@ -0,0 +1,14 @@
1
+ import "reflect-metadata";
2
+ export interface TransformOptions {
3
+ /**
4
+ * Where to extract the data from. Defaults to 'body'.
5
+ */
6
+ from?: 'body' | 'query' | 'params' | 'headers';
7
+ }
8
+ /**
9
+ * Agnostic decorator to transform/validate request data using a registered transformer.
10
+ *
11
+ * @param schema The schema or object to be used by the registered transformer.
12
+ * @param options Transformation options.
13
+ */
14
+ export declare function Transform(schema: any, options?: TransformOptions): (target: any, propertyKey: any) => void;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Transform = Transform;
4
+ require("reflect-metadata");
5
+ const constants_1 = require("../__internals/constants");
6
+ const decorator_base_1 = require("../__internals/decorator-base");
7
+ /**
8
+ * Agnostic decorator to transform/validate request data using a registered transformer.
9
+ *
10
+ * @param schema The schema or object to be used by the registered transformer.
11
+ * @param options Transformation options.
12
+ */
13
+ function Transform(schema, options = {}) {
14
+ return (target, propertyKey) => {
15
+ const data = { schema, options };
16
+ (0, decorator_base_1.defineDecorData)(constants_1.KEY_PARAMS_TRANSFORM, data, target, propertyKey);
17
+ };
18
+ }
@@ -11,3 +11,4 @@ export * from "./Http";
11
11
  export * from "./Pass";
12
12
  export * from "./File";
13
13
  export * from "./Messaging";
14
+ export * from "./Transform";
@@ -27,3 +27,4 @@ __exportStar(require("./Http"), exports);
27
27
  __exportStar(require("./Pass"), exports);
28
28
  __exportStar(require("./File"), exports);
29
29
  __exportStar(require("./Messaging"), exports);
30
+ __exportStar(require("./Transform"), exports);
package/dist/extension.js CHANGED
@@ -31,6 +31,12 @@ const requestMethods = {
31
31
  (0, helpers_1.setRole)(this, role);
32
32
  (0, helpers_1.setScopes)(this, scopes);
33
33
  },
34
+ setValue(key, value) {
35
+ (0, helpers_1.setValue)(this, key, value);
36
+ },
37
+ getValue(key, defaultValue) {
38
+ return (0, helpers_1.getValue)(this, key, defaultValue);
39
+ },
34
40
  };
35
41
  /////////////////////////////
36
42
  /// Agregar métodos al prototipo
@@ -3,44 +3,58 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.collectClassMetadata = collectClassMetadata;
4
4
  require("reflect-metadata");
5
5
  const constants_1 = require("../constants");
6
- const method_collector_1 = require("./method.collector"); // Importamos el colector de métodos
6
+ const method_collector_1 = require("./method.collector");
7
7
  const function_util_1 = require("../../../__internals/utils/function.util");
8
+ const metadata_registry_1 = require("../metadata.registry");
8
9
  function collectClassMetadata(target) {
9
10
  var _a;
10
11
  const prototype = Reflect.getPrototypeOf(target);
11
12
  const constructor = prototype === null || prototype === void 0 ? void 0 : prototype.constructor;
12
13
  const name = target.name || (constructor === null || constructor === void 0 ? void 0 : constructor.name) || ((_a = target === null || target === void 0 ? void 0 : target.constructor) === null || _a === void 0 ? void 0 : _a.name);
13
14
  // Extraemos las metadata de la clase
14
- const tags = Reflect.getMetadata(constants_1.TAGS, target) || [];
15
- const security = Reflect.getMetadata(constants_1.SECURITY, target) || [];
15
+ let tags = Reflect.getMetadata(constants_1.TAGS, target) || [];
16
+ let security = Reflect.getMetadata(constants_1.SECURITY, target) || [];
17
+ // Invoke custom class collectors
18
+ metadata_registry_1.openApiRegistry.getCollectors("class").forEach(collector => {
19
+ const data = collector(target);
20
+ if (data === null || data === void 0 ? void 0 : data.tags)
21
+ tags = [...tags, ...data.tags];
22
+ if (data === null || data === void 0 ? void 0 : data.security)
23
+ security = [...security, ...data.security];
24
+ });
16
25
  // Si no tenemos tags, intentamos inferirlos
17
26
  if (tags.length === 0) {
18
- tags.push({ name }); // El nombre de la clase podría ser un tag
27
+ tags.push({ name });
19
28
  }
20
29
  // Si no tenemos seguridad, intentamos asignar un valor predeterminado
21
30
  if (security.length === 0) {
22
- security.push({ bearerAuth: [] }); // Se puede ajustar según la seguridad predeterminada de la clase
31
+ security.push({ bearerAuth: [] });
23
32
  }
24
33
  // Obtenemos todos los métodos de la clase
25
- const methodNames = Object.getOwnPropertyNames(target.prototype).filter((method) => method !== "constructor");
34
+ const methodNames = Object.getOwnPropertyNames(target.prototype || {}).filter((method) => method !== "constructor");
26
35
  // Creamos una lista con la metadata de cada uno de los métodos
27
36
  const methods = {};
28
37
  methodNames.forEach((methodName) => {
29
38
  let methodMetadata = (0, method_collector_1.collectMethodMetadata)(target.prototype, methodName);
39
+ // Invoke custom method collectors
40
+ metadata_registry_1.openApiRegistry.getCollectors("method").forEach(collector => {
41
+ const data = collector(target.prototype, methodName);
42
+ methodMetadata = Object.assign(Object.assign({}, methodMetadata), data);
43
+ });
30
44
  // Si el método no tiene parámetros definidos, intentamos inferirlos
31
45
  if (!methodMetadata.parameters || methodMetadata.parameters.length === 0) {
32
46
  const methodParams = (0, function_util_1.extractArgsNames)(target.prototype[methodName]);
33
47
  methodParams === null || methodParams === void 0 ? void 0 : methodParams.forEach((paramName, index) => {
34
- var _a;
35
48
  const inferredParam = {
36
49
  name: paramName || `param${index}`,
37
- in: "query", // Asignamos por defecto 'query', esto puede mejorarse según el contexto
50
+ in: "query",
38
51
  required: true,
39
52
  schema: {
40
- type: "string", // Asignamos 'string' por defecto, también mejorable
53
+ type: "string",
41
54
  },
42
55
  };
43
- (_a = methodMetadata.parameters) === null || _a === void 0 ? void 0 : _a.push(inferredParam);
56
+ methodMetadata.parameters || (methodMetadata.parameters = []);
57
+ methodMetadata.parameters.push(inferredParam);
44
58
  });
45
59
  }
46
60
  methods[methodName] = methodMetadata;
@@ -1,3 +1,4 @@
1
1
  export * from "./class.collector";
2
2
  export * from "./method.collector";
3
3
  export * from "./param.collector";
4
+ export * from "./schema.collector";
@@ -17,3 +17,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./class.collector"), exports);
18
18
  __exportStar(require("./method.collector"), exports);
19
19
  __exportStar(require("./param.collector"), exports);
20
+ __exportStar(require("./schema.collector"), exports);
@@ -1,3 +1,2 @@
1
- import 'reflect-metadata';
2
1
  import { Operation } from '../types';
3
2
  export declare function collectMethodMetadata(target: any, methodName: string): Operation;
@@ -1,15 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.collectMethodMetadata = collectMethodMetadata;
4
- require("reflect-metadata");
5
4
  const constants_1 = require("../constants");
6
- const param_collector_1 = require("./param.collector"); // Importamos el colector de parámetros
5
+ const param_collector_1 = require("./param.collector");
6
+ const constants_2 = require("../../../__internals/constants");
7
+ const decorator_base_1 = require("../../../__internals/decorator-base");
8
+ const transform_registry_1 = require("../../../__internals/transform/transform.registry");
7
9
  function collectMethodMetadata(target, methodName) {
8
10
  const methodMetadata = {};
9
11
  // Extraemos la metadata del método
10
12
  const summary = Reflect.getMetadata(constants_1.METHOD_SUMMARY, target, methodName);
11
13
  const operationId = Reflect.getMetadata(constants_1.METHOD_OPERATION_ID, target, methodName);
12
14
  const tags = Reflect.getMetadata(constants_1.METHOD_TAGS, target, methodName);
15
+ const security = Reflect.getMetadata(constants_1.SECURITY, target, methodName);
13
16
  // Extraemos las respuestas del método
14
17
  const responses = Reflect.getMetadata(constants_1.RESPONSES, target, methodName) || {};
15
18
  // Extraemos los parámetros del método
@@ -19,6 +22,20 @@ function collectMethodMetadata(target, methodName) {
19
22
  description: Reflect.getMetadata(constants_1.REQUEST_BODY_DESCRIPTION, target, methodName),
20
23
  content: Reflect.getMetadata(constants_1.REQUEST_BODY_CONTENT, target, methodName),
21
24
  };
25
+ // Bridging @Transform to OpenAPI
26
+ const transform = (0, decorator_base_1.getDecorData)(constants_2.KEY_PARAMS_TRANSFORM, target, methodName);
27
+ if (transform) {
28
+ const openApiSchema = transform_registry_1.transformRegistry.getOpenApiSchema(transform.schema);
29
+ if (openApiSchema) {
30
+ const from = transform.options.from || 'body';
31
+ if (from === 'body') {
32
+ requestBody.content = requestBody.content || {};
33
+ requestBody.content['application/json'] = {
34
+ schema: openApiSchema
35
+ };
36
+ }
37
+ }
38
+ }
22
39
  // Asignamos las propiedades al objeto de metadata solo si existen
23
40
  if (summary)
24
41
  methodMetadata.summary = summary;
@@ -26,6 +43,8 @@ function collectMethodMetadata(target, methodName) {
26
43
  methodMetadata.operationId = operationId;
27
44
  if (tags)
28
45
  methodMetadata.tags = tags;
46
+ if (security)
47
+ methodMetadata.security = security;
29
48
  if (responses && Object.keys(responses).length > 0)
30
49
  methodMetadata.responses = responses;
31
50
  if (parameters.length > 0)