@zenofolio/hyper-decor 1.0.61 → 1.0.63

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 (72) hide show
  1. package/dist/__internals/constants.d.ts +1 -0
  2. package/dist/__internals/constants.js +1 -0
  3. package/dist/__internals/decorator-base.js +46 -10
  4. package/dist/__internals/helpers/imports.helper.d.ts +2 -2
  5. package/dist/__internals/helpers/imports.helper.js +68 -21
  6. package/dist/__internals/helpers/lifecycle.helper.d.ts +3 -0
  7. package/dist/__internals/helpers/lifecycle.helper.js +25 -0
  8. package/dist/__internals/helpers/merge-metadata.js +16 -20
  9. package/dist/__internals/helpers/prepare.helper.js +85 -52
  10. package/dist/__internals/helpers/tree.helper.d.ts +32 -0
  11. package/dist/__internals/helpers/tree.helper.js +48 -0
  12. package/dist/__internals/transform/middleware.transform.js +0 -2
  13. package/dist/__internals/transform/role.transform.js +5 -5
  14. package/dist/__internals/transform/scope.transfrom.js +2 -3
  15. package/dist/common/bootstrap.js +4 -0
  16. package/dist/common/helpers/role.js +1 -4
  17. package/dist/common/message-bus.d.ts +11 -0
  18. package/dist/common/message-bus.js +51 -0
  19. package/dist/common/transport.d.ts +9 -0
  20. package/dist/common/transport.js +46 -0
  21. package/dist/decorators/HyperApp.js +3 -1
  22. package/dist/decorators/HyperService.d.ts +2 -1
  23. package/dist/decorators/HyperService.js +6 -4
  24. package/dist/decorators/Messaging.d.ts +10 -0
  25. package/dist/decorators/Messaging.js +22 -0
  26. package/dist/decorators/Middleware.d.ts +1 -1
  27. package/dist/decorators/Middleware.js +14 -2
  28. package/dist/decorators/index.d.ts +1 -0
  29. package/dist/decorators/index.js +1 -0
  30. package/dist/decorators/types.d.ts +21 -4
  31. package/dist/index.d.ts +3 -0
  32. package/dist/index.js +3 -0
  33. package/dist/type.d.ts +5 -2
  34. package/dist/vitest.config.d.ts +2 -0
  35. package/dist/vitest.config.js +34 -0
  36. package/package.json +66 -59
  37. package/scripts/clean.js +56 -0
  38. package/vitest.config.mjs +30 -0
  39. package/vitest.json +0 -0
  40. package/.mocharc.js +0 -5
  41. package/dist/__internals/store.d.ts +0 -29
  42. package/dist/__internals/store.js +0 -17
  43. package/dist/__internals/stores/index.d.ts +0 -15
  44. package/dist/__internals/stores/index.js +0 -37
  45. package/dist/__internals/stores/middleware.store.d.ts +0 -7
  46. package/dist/__internals/stores/middleware.store.js +0 -19
  47. package/dist/__internals/stores/params.store.d.ts +0 -21
  48. package/dist/__internals/stores/params.store.js +0 -65
  49. package/dist/__internals/stores/routes.store.d.ts +0 -17
  50. package/dist/__internals/stores/routes.store.js +0 -43
  51. package/dist/__internals/stores/store.interface.d.ts +0 -8
  52. package/dist/__internals/stores/store.interface.js +0 -2
  53. package/dist/__internals/transform/method.transform.d.ts +0 -2
  54. package/dist/__internals/transform/method.transform.js +0 -20
  55. package/dist/__internals/transform/pass.transfrom.d.ts +0 -1
  56. package/dist/__internals/transform/pass.transfrom.js +0 -2
  57. package/dist/__internals/utils/mixin.utils.d.ts +0 -11
  58. package/dist/__internals/utils/mixin.utils.js +0 -34
  59. package/dist/__internals/utils/router.d.ts +0 -1
  60. package/dist/__internals/utils/router.js +0 -2
  61. package/dist/collectors/index.d.ts +0 -1
  62. package/dist/collectors/index.js +0 -17
  63. package/dist/collectors/scope.collector.d.ts +0 -14
  64. package/dist/collectors/scope.collector.js +0 -29
  65. package/dist/common/openapi/collect-class-data.d.ts +0 -21
  66. package/dist/common/openapi/collect-class-data.js +0 -45
  67. package/dist/common/openapi/collect-function-data.d.ts +0 -32
  68. package/dist/common/openapi/collect-function-data.js +0 -70
  69. package/dist/common/openapi/index.d.ts +0 -2
  70. package/dist/common/openapi/index.js +0 -18
  71. package/dist/decorators/Service.d.ts +0 -5
  72. package/dist/decorators/Service.js +0 -16
@@ -41,6 +41,7 @@ export declare const METADATA_KEYS: {
41
41
  SCOPES: string;
42
42
  SCOPED: string;
43
43
  MIDDLEWARES: string;
44
+ ON_MESSAGE: string;
44
45
  };
45
46
  export declare const METADATA_STORE_KEYS: {
46
47
  PARAMS: string;
@@ -52,6 +52,7 @@ exports.METADATA_KEYS = {
52
52
  SCOPES: "hyper:scopes",
53
53
  SCOPED: "hyper:scoped",
54
54
  MIDDLEWARES: "hyper:middleware",
55
+ ON_MESSAGE: "hyper:on_message",
55
56
  };
56
57
  exports.METADATA_STORE_KEYS = {
57
58
  PARAMS: "hyper:store:params",
@@ -48,12 +48,17 @@ function DecoratorHelper({ key, type, options, targetResolver, onDefineData }, .
48
48
  else {
49
49
  (0, exports.defineDecorData)(key, Object.assign({ type }, options), Target);
50
50
  value = Reflect.decorate(transforms, Target);
51
+ // If the class was wrapped/replaced, apply metadata to the new class too
52
+ if (value && value !== Target) {
53
+ (0, exports.defineDecorData)(key, Object.assign({ type }, options), value);
54
+ }
51
55
  }
52
56
  }
53
57
  (0, tsyringe_1.injectable)()((0, object_util_1.$constructor)(target));
54
58
  return value;
55
59
  };
56
60
  }
61
+ const METADATA_CACHE = new WeakMap();
57
62
  const defineDecorData = (key, options, target, property, descriptor) => {
58
63
  let value = options;
59
64
  if (typeof options === "function") {
@@ -66,21 +71,52 @@ const defineDecorData = (key, options, target, property, descriptor) => {
66
71
  else {
67
72
  Reflect.defineMetadata(key, value, target);
68
73
  }
74
+ // Update Cache
75
+ let targetCache = METADATA_CACHE.get(target);
76
+ if (!targetCache) {
77
+ targetCache = new Map();
78
+ METADATA_CACHE.set(target, targetCache);
79
+ }
80
+ targetCache.set(property ? `${key}:${property}` : key, value);
69
81
  };
70
82
  exports.defineDecorData = defineDecorData;
71
- const getDecorData = (key, target, property) => property
72
- ? Reflect.getMetadata(key, target, property)
73
- : Reflect.getMetadata(key, target);
83
+ const getDecorData = (key, target, property) => {
84
+ const cacheKey = property ? `${key}:${property}` : key;
85
+ const targetCache = METADATA_CACHE.get(target);
86
+ if (targetCache && targetCache.has(cacheKey)) {
87
+ return targetCache.get(cacheKey);
88
+ }
89
+ const value = property
90
+ ? Reflect.getMetadata(key, target, property)
91
+ : Reflect.getMetadata(key, target);
92
+ if (value !== undefined) {
93
+ let tc = METADATA_CACHE.get(target);
94
+ if (!tc) {
95
+ tc = new Map();
96
+ METADATA_CACHE.set(target, tc);
97
+ }
98
+ tc.set(cacheKey, value);
99
+ }
100
+ return value;
101
+ };
74
102
  exports.getDecorData = getDecorData;
75
- const hasDecorData = (key, target, property) => property
76
- ? Reflect.hasMetadata(key, target, property)
77
- : Reflect.hasMetadata(key, target);
103
+ const hasDecorData = (key, target, property) => {
104
+ const cacheKey = property ? `${key}:${property}` : key;
105
+ const targetCache = METADATA_CACHE.get(target);
106
+ if (targetCache && targetCache.has(cacheKey))
107
+ return true;
108
+ return property
109
+ ? Reflect.hasMetadata(key, target, property)
110
+ : Reflect.hasMetadata(key, target);
111
+ };
78
112
  exports.hasDecorData = hasDecorData;
79
113
  const extractDecorData = (target) => {
80
114
  const keys = Reflect.getMetadataKeys(target);
81
- return keys.reduce((acc, key) => {
82
- acc[key] = Reflect.getMetadata(key, target);
83
- return acc;
84
- }, {});
115
+ const result = {};
116
+ for (let i = 0; i < keys.length; i++) {
117
+ const key = keys[i];
118
+ result[key] = (0, exports.getDecorData)(key, target);
119
+ }
120
+ return result;
85
121
  };
86
122
  exports.extractDecorData = extractDecorData;
@@ -1,8 +1,8 @@
1
- import { ImportType } from "../../decorators/types";
1
+ import { IHyperHooks, ImportType } from "../../decorators/types";
2
2
  /**
3
3
  * Prepare imports for the target class.
4
4
  *
5
5
  * @param target
6
6
  * @param imports
7
7
  */
8
- export declare function prepareImports(target: any, imports: ImportType[]): Promise<void>;
8
+ export declare function prepareImports(_target: any, imports: ImportType[], hooks?: IHyperHooks, context?: any): Promise<void>;
@@ -11,35 +11,82 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.prepareImports = prepareImports;
13
13
  const tsyringe_1 = require("tsyringe");
14
+ const lifecycle_helper_1 = require("./lifecycle.helper");
15
+ const decorator_base_1 = require("../decorator-base");
16
+ const constants_1 = require("../constants");
17
+ const message_bus_1 = require("../../common/message-bus");
14
18
  /**
15
19
  * Prepare imports for the target class.
16
20
  *
17
21
  * @param target
18
22
  * @param imports
19
23
  */
20
- function prepareImports(target, imports) {
24
+ function prepareImports(_target, imports, hooks, context) {
21
25
  return __awaiter(this, void 0, void 0, function* () {
22
- var _a;
23
- for (const service of imports) {
24
- const _class = tsyringe_1.container.resolve(service);
25
- if (!_class)
26
- continue;
27
- const isSingleton = ((_a = _class.isSingleton) === null || _a === void 0 ? void 0 : _a.call(_class)) === true;
28
- if (isSingleton) {
29
- if (isInitialized(_class))
30
- continue;
31
- tsyringe_1.container.registerInstance(service, _class);
26
+ const bus = tsyringe_1.container.resolve(message_bus_1.MessageBus);
27
+ yield Promise.all(imports.map((item) => __awaiter(this, void 0, void 0, function* () {
28
+ let token;
29
+ if (typeof item === "function" || typeof item === "string" || typeof item === "symbol") {
30
+ token = item;
32
31
  }
33
- if (typeof _class.onInit === "function") {
34
- yield _class.onInit();
35
- if (isSingleton)
36
- setInitialized(_class);
32
+ else if (item && typeof item === "object" && "token" in item) {
33
+ token = item.token;
34
+ if (item.useClass) {
35
+ tsyringe_1.container.register(token, { useClass: item.useClass }, item.options);
36
+ }
37
+ else if ("useValue" in item) {
38
+ tsyringe_1.container.registerInstance(token, item.useValue);
39
+ return;
40
+ }
41
+ else if (item.useFactory) {
42
+ tsyringe_1.container.register(token, { useFactory: item.useFactory }, item.options);
43
+ return;
44
+ }
45
+ else if (item.useToken) {
46
+ tsyringe_1.container.register(token, { useToken: item.useToken }, item.options);
47
+ return;
48
+ }
37
49
  }
38
- }
50
+ if (!token)
51
+ return;
52
+ try {
53
+ const instance = tsyringe_1.container.resolve(token);
54
+ if (!instance)
55
+ return;
56
+ // Skip if already initialized to avoid double work/double subscription
57
+ const alreadyDone = (0, lifecycle_helper_1.isInitialized)(instance);
58
+ if (!alreadyDone) {
59
+ if (hooks === null || hooks === void 0 ? void 0 : hooks.onBeforeInit) {
60
+ yield hooks.onBeforeInit(instance, token, context);
61
+ }
62
+ }
63
+ yield (0, lifecycle_helper_1.initializeInstance)(instance);
64
+ if (!alreadyDone) {
65
+ if (hooks === null || hooks === void 0 ? void 0 : hooks.onAfterInit) {
66
+ yield hooks.onAfterInit(instance, token, context);
67
+ }
68
+ // Handle singleton registration if it's a constructor and not registered
69
+ if (typeof token === "function" && !tsyringe_1.container.isRegistered(token)) {
70
+ const isSingleton = typeof instance.isSingleton === "function" ? instance.isSingleton() : true;
71
+ if (isSingleton) {
72
+ tsyringe_1.container.registerInstance(token, instance);
73
+ }
74
+ }
75
+ // Discovery: Messaging (only on first init)
76
+ const messaging = (0, decorator_base_1.getDecorData)(constants_1.METADATA_KEYS.ON_MESSAGE, typeof token === "function" ? token : instance.constructor);
77
+ if (messaging === null || messaging === void 0 ? void 0 : messaging.length) {
78
+ messaging.forEach((msg) => {
79
+ bus.listen(msg.topic, instance[msg.propertyKey].bind(instance));
80
+ });
81
+ }
82
+ }
83
+ }
84
+ catch (e) {
85
+ // Skip dependencies that cannot be resolved automatically
86
+ // Log a warning to prevent silent failures in production
87
+ const name = typeof token === "function" ? token.name : String(token);
88
+ console.warn(`[HyperDecor] Warn: Could not resolve dependency for token "${name}". It might be missing injectable() or not exported correctly.`);
89
+ }
90
+ })));
39
91
  });
40
92
  }
41
- ////////////////////////
42
- /// Utils
43
- ////////////////////////
44
- const isInitialized = (target) => Reflect.get(target, "____initialized") === true;
45
- const setInitialized = (target) => Reflect.set(target, "____initialized", true);
@@ -0,0 +1,3 @@
1
+ export declare const isInitialized: (target: any) => boolean;
2
+ export declare const setInitialized: (target: any) => boolean;
3
+ export declare function initializeInstance(instance: any): Promise<void>;
@@ -0,0 +1,25 @@
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.setInitialized = exports.isInitialized = void 0;
13
+ exports.initializeInstance = initializeInstance;
14
+ const isInitialized = (target) => Reflect.get(target, "____initialized") === true;
15
+ exports.isInitialized = isInitialized;
16
+ const setInitialized = (target) => Reflect.set(target, "____initialized", true);
17
+ exports.setInitialized = setInitialized;
18
+ function initializeInstance(instance) {
19
+ return __awaiter(this, void 0, void 0, function* () {
20
+ if (instance && typeof instance.onInit === "function" && !(0, exports.isInitialized)(instance)) {
21
+ yield instance.onInit();
22
+ (0, exports.setInitialized)(instance);
23
+ }
24
+ });
25
+ }
@@ -10,35 +10,31 @@ require("reflect-metadata");
10
10
  * @param options Merge options (e.g., array handling).
11
11
  */
12
12
  function mergeMetadata(target, source, keys, options = {}) {
13
- for (const key of keys) {
13
+ for (let i = 0; i < keys.length; i++) {
14
+ const key = keys[i];
14
15
  const sourceMeta = Reflect.getMetadata(key, source);
15
- const targetMeta = Reflect.getMetadata(key, target);
16
16
  if (sourceMeta === undefined)
17
17
  continue;
18
- let mergedMeta = sourceMeta;
19
- if (typeof sourceMeta === "object" && typeof targetMeta === "object") {
20
- mergedMeta = deepMerge(targetMeta, sourceMeta, options);
21
- }
22
- Reflect.defineMetadata(key, mergedMeta, target);
18
+ const targetMeta = Reflect.getMetadata(key, target);
19
+ Reflect.defineMetadata(key, targetMeta === undefined ? sourceMeta : deepMerge(targetMeta, sourceMeta, options), target);
23
20
  }
24
21
  }
25
- /**
26
- * Performs a deep merge of two objects.
27
- * @param target Target object.
28
- * @param source Source object.
29
- * @param options Merge options.
30
- * @returns Merged object.
31
- */
32
22
  function deepMerge(target, source, options) {
33
23
  if (Array.isArray(target) && Array.isArray(source)) {
34
- return (options.overwriteArrays ? source : Array.from(new Set([...target, ...source])));
24
+ if (options.overwriteArrays)
25
+ return source;
26
+ // Faster deduplication for primitive arrays
27
+ const combined = target.concat(source);
28
+ return Array.from(new Set(combined));
35
29
  }
36
- if (typeof target === "object" && target !== null && typeof source === "object" && source !== null) {
37
- const merged = Object.assign({}, target);
38
- for (const key of Object.keys(source)) {
39
- merged[key] = deepMerge(target[key], source[key], options);
30
+ if (source && typeof source === "object" && target && typeof target === "object") {
31
+ const result = Object.assign({}, target);
32
+ const sourceKeys = Object.keys(source);
33
+ for (let i = 0; i < sourceKeys.length; i++) {
34
+ const k = sourceKeys[i];
35
+ result[k] = deepMerge(result[k], source[k], options);
40
36
  }
41
- return merged;
37
+ return result;
42
38
  }
43
39
  return source;
44
40
  }
@@ -24,7 +24,8 @@ 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 service_store_1 = require("../stores/service.store");
27
+ const message_bus_1 = require("../../common/message-bus");
28
+ const transport_1 = require("../../common/transport");
28
29
  const if_router = (current) => {
29
30
  if (!current || !((current === null || current === void 0 ? void 0 : current.prototype) instanceof hyper_express_1.Router))
30
31
  return new hyper_express_1.Router();
@@ -71,12 +72,29 @@ function getData(target) {
71
72
  */
72
73
  function prepareApplication(options, Target, app, log) {
73
74
  return __awaiter(this, void 0, void 0, function* () {
74
- var _a, _b;
75
+ var _a, _b, _c;
75
76
  const data = getData(Target);
76
77
  const prefix = (_a = options.prefix) !== null && _a !== void 0 ? _a : "/";
77
78
  const imports = (_b = options.imports) !== null && _b !== void 0 ? _b : [];
78
- yield prepareServices(service_store_1.serviceStore);
79
- yield (0, imports_helper_1.prepareImports)(Target, imports);
79
+ // Register transports if provided, otherwise fallback to internal
80
+ const bus = tsyringe_1.container.resolve(message_bus_1.MessageBus);
81
+ if ((_c = options === null || options === void 0 ? void 0 : options.transports) === null || _c === void 0 ? void 0 : _c.length) {
82
+ options.transports.forEach((t) => bus.registerTransport(t));
83
+ }
84
+ else {
85
+ bus.registerTransport(new transport_1.InternalTransport());
86
+ }
87
+ let hooks = options.hooks;
88
+ if (typeof hooks === "function" && !(hooks instanceof hyper_express_1.Router)) {
89
+ if (hooks && "constructor" in hooks) {
90
+ if (tsyringe_1.container.isRegistered(hooks)) {
91
+ tsyringe_1.container.register(hooks, hooks);
92
+ }
93
+ }
94
+ hooks = tsyringe_1.container.resolve(hooks);
95
+ }
96
+ const context = { target: Target, metadata: options, type: "app" };
97
+ yield (0, imports_helper_1.prepareImports)(Target, imports, hooks, context);
80
98
  if (data.middlewares.length) {
81
99
  app.use(...data.middlewares);
82
100
  log("middleware", `${Target.name} with middlewares: ${data.middlewares
@@ -92,11 +110,11 @@ function prepareApplication(options, Target, app, log) {
92
110
  app.use(middleware);
93
111
  log("middleware", `${Target.name} with roles: ${data.roles.join(", ")}`);
94
112
  });
95
- const routers = yield Promise.all(options.modules.map((module) => __awaiter(this, void 0, void 0, function* () {
96
- var _a, _b, _c, _d;
113
+ const routers = (yield Promise.all(options.modules.map((module) => __awaiter(this, void 0, void 0, function* () {
114
+ var _a, _b, _c;
97
115
  const data = getData(module);
98
- const path = (_b = (_a = data.module) === null || _a === void 0 ? void 0 : _a.path) !== null && _b !== void 0 ? _b : "/";
99
- const imports = (_d = (_c = data.module) === null || _c === void 0 ? void 0 : _c.imports) !== null && _d !== void 0 ? _d : [];
116
+ const path = (_a = data.module) === null || _a === void 0 ? void 0 : _a.path;
117
+ const imports = (_c = (_b = data.module) === null || _b === void 0 ? void 0 : _b.imports) !== null && _c !== void 0 ? _c : [];
100
118
  return prepareTarget({
101
119
  target: module,
102
120
  router: if_router(module),
@@ -105,10 +123,11 @@ function prepareApplication(options, Target, app, log) {
105
123
  prefix: path,
106
124
  imports: imports,
107
125
  log,
126
+ hooks: hooks,
108
127
  });
109
- })));
128
+ })))).filter((r) => r.router);
110
129
  routers.forEach(({ router, path }) => {
111
- app.use((0, path_util_1.join)(prefix, path), router);
130
+ app.use((0, path_util_1.join)(prefix, path || "/"), router);
112
131
  });
113
132
  });
114
133
  }
@@ -120,29 +139,43 @@ function prepareApplication(options, Target, app, log) {
120
139
  * @returns
121
140
  */
122
141
  function prepareTarget(_a) {
123
- return __awaiter(this, arguments, void 0, function* ({ target, router, prefix = "/", namespace = "", instance, imports = [], log, }) {
142
+ return __awaiter(this, arguments, void 0, function* ({ target, router, prefix, namespace = "", instance, imports = [], log, hooks, }) {
124
143
  var _b, _c, _d, _e, _f, _g, _h, _j;
125
- const _router = router !== null && router !== void 0 ? router : if_router(target);
126
144
  const data = getData(target);
145
+ if (data.module) {
146
+ log("modules", `${namespace} { ${prefix || "/"} }`);
147
+ }
148
+ else if (data.controller) {
149
+ log("controllers", `${namespace} { ${prefix || "/"} }`);
150
+ }
127
151
  const modules = (_c = (_b = data.module) === null || _b === void 0 ? void 0 : _b.modules) !== null && _c !== void 0 ? _c : [];
128
152
  const controllers = (_e = (_d = data.module) === null || _d === void 0 ? void 0 : _d.controllers) !== null && _e !== void 0 ? _e : [];
129
- const routes = (_f = data.routes) !== null && _f !== void 0 ? _f : [];
153
+ const routes = (_f = data.routes) !== null && _f !== void 0 ? _f : { routes: [] };
130
154
  const middlewares = (_g = data.middlewares) !== null && _g !== void 0 ? _g : [];
131
155
  const scopes = (_h = data.scopes) !== null && _h !== void 0 ? _h : [];
132
156
  const roles = (_j = data.roles) !== null && _j !== void 0 ? _j : [];
157
+ const needsRouter = controllers.length > 0 ||
158
+ routes.routes.size > 0 ||
159
+ middlewares.length > 0 ||
160
+ scopes.length > 0 ||
161
+ roles.length > 0;
162
+ const _router = router !== null && router !== void 0 ? router : (needsRouter ? if_router(target) : undefined);
133
163
  ////////////////////////////////
134
164
  /// Prepare Imports
135
165
  ////////////////////////////////
136
- yield (0, imports_helper_1.prepareImports)(target, imports);
166
+ const context = { target: target, metadata: data, type: "target" };
167
+ yield (0, imports_helper_1.prepareImports)(target, imports, hooks, context);
137
168
  ////////////////////////////////
138
- /// Attach Middlewares
169
+ /// Attach Middlewares & Security
139
170
  ////////////////////////////////
140
- _router.use(...middlewares);
141
- (0, scope_transfrom_1.default)(scopes, (middleware, scopes) => {
142
- stores_1.ScopeStore.addAll(scopes);
143
- _router.use(middleware);
144
- });
145
- (0, role_transform_1.default)(roles, (middleware) => _router.use(middleware));
171
+ if (_router) {
172
+ _router.use(...middlewares);
173
+ (0, scope_transfrom_1.default)(scopes, (middleware, scopes) => {
174
+ stores_1.ScopeStore.addAll(scopes);
175
+ _router.use(middleware);
176
+ });
177
+ (0, role_transform_1.default)(roles, (middleware) => _router.use(middleware));
178
+ }
146
179
  ////////////////////////////////
147
180
  /// Prepare Modules
148
181
  ////////////////////////////////
@@ -150,15 +183,18 @@ function prepareTarget(_a) {
150
183
  const moduleData = getData(module);
151
184
  if (!moduleData.module)
152
185
  return;
153
- const router = yield prepareTarget({
186
+ const res = yield prepareTarget({
154
187
  target: module,
155
188
  imports: moduleData.module.imports,
156
189
  namespace: `${namespace}/${module.name}`,
157
190
  prefix: moduleData.module.path,
158
191
  instance: tsyringe_1.container.resolve(module),
159
192
  log,
193
+ hooks,
160
194
  });
161
- _router.use(router.path, router.router);
195
+ if (res.router && _router) {
196
+ _router.use(res.path || "/", res.router);
197
+ }
162
198
  }));
163
199
  // ////////////////////////////////
164
200
  // /// Prepare Controllers
@@ -168,32 +204,37 @@ function prepareTarget(_a) {
168
204
  const controllerData = data.controller;
169
205
  if (!controllerData)
170
206
  return;
171
- const router = yield prepareTarget({
207
+ const res = yield prepareTarget({
172
208
  target: controller,
173
209
  namespace: `${namespace}/${controller.name}`,
174
210
  prefix: controllerData.path,
175
211
  imports: controllerData.imports,
176
212
  instance: tsyringe_1.container.resolve(controller),
177
213
  log,
214
+ hooks,
178
215
  });
179
- _router.use(router.path, router.router);
216
+ if (res.router && _router) {
217
+ _router.use(res.path || "/", res.router);
218
+ }
180
219
  }));
181
220
  ////////////////////////////////
182
221
  /// Prepare Routes
183
222
  ////////////////////////////////
184
- yield (0, object_util_1.$each)(Array.from(routes.routes), (route) => __awaiter(this, void 0, void 0, function* () {
185
- if (typeof route !== "object")
186
- return;
187
- yield prepareRoutes({
188
- target: target,
189
- router: _router,
190
- route,
191
- namespace,
192
- instance,
193
- prefix,
194
- log,
195
- });
196
- }));
223
+ if (_router) {
224
+ yield (0, object_util_1.$each)(Array.from(routes.routes), (route) => __awaiter(this, void 0, void 0, function* () {
225
+ if (typeof route !== "object")
226
+ return;
227
+ yield prepareRoutes({
228
+ target: target,
229
+ router: _router,
230
+ route,
231
+ namespace,
232
+ instance,
233
+ prefix: prefix || "/",
234
+ log,
235
+ });
236
+ }));
237
+ }
197
238
  return {
198
239
  router: _router,
199
240
  path: prefix,
@@ -232,21 +273,13 @@ function prepareRoutes(_a) {
232
273
  }
233
274
  else {
234
275
  $fn.call(router, path, ...middlewares, (req, res) => __awaiter(this, void 0, void 0, function* () {
235
- const args = yield Promise.all(params.map((param) => __awaiter(this, void 0, void 0, function* () {
236
- const { resolver, key } = param;
237
- return yield resolver(req, res);
238
- })));
239
- return handler.bind(instance)(...args, req, res);
276
+ const len = params.length;
277
+ const args = new Array(len);
278
+ for (let i = 0; i < len; i++) {
279
+ args[i] = yield params[i].resolver(req, res);
280
+ }
281
+ return handler.apply(instance, args);
240
282
  }));
241
283
  }
242
284
  });
243
285
  }
244
- function prepareServices(list) {
245
- return __awaiter(this, void 0, void 0, function* () {
246
- yield Promise.all(Array.from(list).map((service) => __awaiter(this, void 0, void 0, function* () {
247
- const instance = tsyringe_1.container.resolve(service);
248
- if (instance.onInit)
249
- yield instance.onInit();
250
- })));
251
- });
252
- }
@@ -0,0 +1,32 @@
1
+ import { HyperAppMetadata, HyperModuleMetadata, HyperControllerMetadata, RouteMetadata } from "../../decorators/types";
2
+ export interface AppTree {
3
+ app: HyperAppMetadata & {
4
+ target: any;
5
+ fullPath: string;
6
+ };
7
+ modules: ModuleNode[];
8
+ }
9
+ export interface ModuleNode {
10
+ metadata: HyperModuleMetadata;
11
+ target: any;
12
+ fullPath: string;
13
+ modules: ModuleNode[];
14
+ controllers: ControllerNode[];
15
+ services: any[];
16
+ }
17
+ export interface ControllerNode {
18
+ metadata: HyperControllerMetadata;
19
+ target: any;
20
+ fullPath: string;
21
+ routes: RouteNode[];
22
+ services: any[];
23
+ }
24
+ export interface RouteNode extends RouteMetadata {
25
+ fullPath: string;
26
+ params: any[];
27
+ }
28
+ /**
29
+ * Extracts the complete application metadata tree.
30
+ * This is useful for generating Swagger/OpenAPI documentation or graphing the app structure.
31
+ */
32
+ export declare function getAppTree(Target: any): AppTree;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getAppTree = getAppTree;
4
+ const decorator_base_1 = require("../decorator-base");
5
+ const constants_1 = require("../constants");
6
+ const path_util_1 = require("../utils/path.util");
7
+ /**
8
+ * Extracts the complete application metadata tree.
9
+ * This is useful for generating Swagger/OpenAPI documentation or graphing the app structure.
10
+ */
11
+ function getAppTree(Target) {
12
+ const appMetadata = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_APP, Target);
13
+ const prefix = (appMetadata === null || appMetadata === void 0 ? void 0 : appMetadata.prefix) || "/";
14
+ return {
15
+ 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
+ };
18
+ }
19
+ function getModuleNode(Target, parentPath = "") {
20
+ const metadata = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_MODULE, Target);
21
+ const currentPath = (0, path_util_1.join)(parentPath, (metadata === null || metadata === void 0 ? void 0 : metadata.path) || "");
22
+ return {
23
+ metadata,
24
+ target: Target,
25
+ 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) || [])
29
+ };
30
+ }
31
+ function getControllerNode(Target, parentPath = "") {
32
+ const metadata = (0, decorator_base_1.getDecorData)(constants_1.KEY_TYPE_CONTROLLER, Target);
33
+ 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);
35
+ const currentPath = (0, path_util_1.join)(parentPath, (metadata === null || metadata === void 0 ? void 0 : metadata.path) || "");
36
+ 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 });
40
+ });
41
+ return {
42
+ metadata,
43
+ target: Target,
44
+ fullPath: currentPath,
45
+ routes,
46
+ services: (metadata === null || metadata === void 0 ? void 0 : metadata.imports) || []
47
+ };
48
+ }
@@ -3,8 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.default = middlewareTransformer;
4
4
  const tsyringe_1 = require("tsyringe");
5
5
  function middlewareTransformer(list) {
6
- if (!(list === null || list === void 0 ? void 0 : list.length))
7
- return [];
8
6
  return list
9
7
  .map((middleware) => {
10
8
  if (isClass(middleware)) {
@@ -10,16 +10,16 @@ function roleTransform(list, callback) {
10
10
  var _a;
11
11
  if (isEmtpy)
12
12
  return next();
13
- const requestRoles = new Set((_a = (0, helpers_1.getRoles)(req)) !== null && _a !== void 0 ? _a : []);
14
- if (requestRoles.size === 0 && isEmtpy)
13
+ const requestRoles = (_a = (0, helpers_1.getRoles)(req)) !== null && _a !== void 0 ? _a : [];
14
+ if (requestRoles.length === 0 && isEmtpy)
15
15
  return next();
16
- if (requestRoles.has(constants_1.FULL_ACCESS))
16
+ if (requestRoles.includes(constants_1.FULL_ACCESS))
17
17
  return next();
18
- const role = roles.some((scope) => requestRoles.has(scope.role));
18
+ const role = roles.some((scope) => requestRoles.includes(scope.role));
19
19
  if (role) {
20
20
  return next();
21
21
  }
22
- return next(new exeptions_1.NotRoleException(`Only ${Array.from(names).join(", ")} can access this resource`, Array.from(requestRoles), Array.from(names)));
22
+ return next(new exeptions_1.NotRoleException(`Only ${Array.from(names).join(", ")} can access this resource`, requestRoles, Array.from(names)));
23
23
  };
24
24
  if (names.size > 0 && callback) {
25
25
  callback(middleware, roles, names);