@zenofolio/hyper-decor 1.0.60 → 1.0.62

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 (69) hide show
  1. package/debug.txt +1 -0
  2. package/dist/__internals/constants.d.ts +1 -0
  3. package/dist/__internals/constants.js +1 -0
  4. package/dist/__internals/decorator-base.js +46 -10
  5. package/dist/__internals/helpers/imports.helper.d.ts +2 -2
  6. package/dist/__internals/helpers/imports.helper.js +68 -21
  7. package/dist/__internals/helpers/lifecycle.helper.d.ts +3 -0
  8. package/dist/__internals/helpers/lifecycle.helper.js +25 -0
  9. package/dist/__internals/helpers/merge-metadata.js +16 -20
  10. package/dist/__internals/helpers/prepare.helper.js +79 -52
  11. package/dist/__internals/helpers/tree.helper.d.ts +32 -0
  12. package/dist/__internals/helpers/tree.helper.js +48 -0
  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/message-bus.d.ts +11 -0
  17. package/dist/common/message-bus.js +51 -0
  18. package/dist/common/transport.d.ts +9 -0
  19. package/dist/common/transport.js +46 -0
  20. package/dist/decorators/HyperApp.js +2 -0
  21. package/dist/decorators/HyperService.d.ts +2 -1
  22. package/dist/decorators/HyperService.js +6 -4
  23. package/dist/decorators/Messaging.d.ts +10 -0
  24. package/dist/decorators/Messaging.js +22 -0
  25. package/dist/decorators/index.d.ts +1 -0
  26. package/dist/decorators/index.js +1 -0
  27. package/dist/decorators/types.d.ts +19 -3
  28. package/dist/index.d.ts +7 -0
  29. package/dist/index.js +9 -0
  30. package/dist/type.d.ts +5 -2
  31. package/dist/vitest.config.d.ts +2 -0
  32. package/dist/vitest.config.js +34 -0
  33. package/package.json +66 -59
  34. package/scripts/clean.js +56 -0
  35. package/vitest.config.mjs +30 -0
  36. package/vitest.json +0 -0
  37. package/.mocharc.js +0 -5
  38. package/dist/__internals/store.d.ts +0 -29
  39. package/dist/__internals/store.js +0 -17
  40. package/dist/__internals/stores/index.d.ts +0 -15
  41. package/dist/__internals/stores/index.js +0 -37
  42. package/dist/__internals/stores/middleware.store.d.ts +0 -7
  43. package/dist/__internals/stores/middleware.store.js +0 -19
  44. package/dist/__internals/stores/params.store.d.ts +0 -21
  45. package/dist/__internals/stores/params.store.js +0 -65
  46. package/dist/__internals/stores/routes.store.d.ts +0 -17
  47. package/dist/__internals/stores/routes.store.js +0 -43
  48. package/dist/__internals/stores/store.interface.d.ts +0 -8
  49. package/dist/__internals/stores/store.interface.js +0 -2
  50. package/dist/__internals/transform/method.transform.d.ts +0 -2
  51. package/dist/__internals/transform/method.transform.js +0 -20
  52. package/dist/__internals/transform/pass.transfrom.d.ts +0 -1
  53. package/dist/__internals/transform/pass.transfrom.js +0 -2
  54. package/dist/__internals/utils/mixin.utils.d.ts +0 -11
  55. package/dist/__internals/utils/mixin.utils.js +0 -34
  56. package/dist/__internals/utils/router.d.ts +0 -1
  57. package/dist/__internals/utils/router.js +0 -2
  58. package/dist/collectors/index.d.ts +0 -1
  59. package/dist/collectors/index.js +0 -17
  60. package/dist/collectors/scope.collector.d.ts +0 -14
  61. package/dist/collectors/scope.collector.js +0 -29
  62. package/dist/common/openapi/collect-class-data.d.ts +0 -21
  63. package/dist/common/openapi/collect-class-data.js +0 -45
  64. package/dist/common/openapi/collect-function-data.d.ts +0 -32
  65. package/dist/common/openapi/collect-function-data.js +0 -70
  66. package/dist/common/openapi/index.d.ts +0 -2
  67. package/dist/common/openapi/index.js +0 -18
  68. package/dist/decorators/Service.d.ts +0 -5
  69. package/dist/decorators/Service.js +0 -16
package/debug.txt ADDED
@@ -0,0 +1 @@
1
+ State: class-before-dep-ok
@@ -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,37 @@ 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);
127
145
  const modules = (_c = (_b = data.module) === null || _b === void 0 ? void 0 : _b.modules) !== null && _c !== void 0 ? _c : [];
128
146
  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 : [];
147
+ const routes = (_f = data.routes) !== null && _f !== void 0 ? _f : { routes: [] };
130
148
  const middlewares = (_g = data.middlewares) !== null && _g !== void 0 ? _g : [];
131
149
  const scopes = (_h = data.scopes) !== null && _h !== void 0 ? _h : [];
132
150
  const roles = (_j = data.roles) !== null && _j !== void 0 ? _j : [];
151
+ const needsRouter = controllers.length > 0 ||
152
+ routes.routes.size > 0 ||
153
+ middlewares.length > 0 ||
154
+ scopes.length > 0 ||
155
+ roles.length > 0;
156
+ const _router = router !== null && router !== void 0 ? router : (needsRouter ? if_router(target) : undefined);
133
157
  ////////////////////////////////
134
158
  /// Prepare Imports
135
159
  ////////////////////////////////
136
- yield (0, imports_helper_1.prepareImports)(target, imports);
160
+ const context = { target: target, metadata: data, type: "target" };
161
+ yield (0, imports_helper_1.prepareImports)(target, imports, hooks, context);
137
162
  ////////////////////////////////
138
- /// Attach Middlewares
163
+ /// Attach Middlewares & Security
139
164
  ////////////////////////////////
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));
165
+ if (_router) {
166
+ _router.use(...middlewares);
167
+ (0, scope_transfrom_1.default)(scopes, (middleware, scopes) => {
168
+ stores_1.ScopeStore.addAll(scopes);
169
+ _router.use(middleware);
170
+ });
171
+ (0, role_transform_1.default)(roles, (middleware) => _router.use(middleware));
172
+ }
146
173
  ////////////////////////////////
147
174
  /// Prepare Modules
148
175
  ////////////////////////////////
@@ -150,15 +177,18 @@ function prepareTarget(_a) {
150
177
  const moduleData = getData(module);
151
178
  if (!moduleData.module)
152
179
  return;
153
- const router = yield prepareTarget({
180
+ const res = yield prepareTarget({
154
181
  target: module,
155
182
  imports: moduleData.module.imports,
156
183
  namespace: `${namespace}/${module.name}`,
157
184
  prefix: moduleData.module.path,
158
185
  instance: tsyringe_1.container.resolve(module),
159
186
  log,
187
+ hooks,
160
188
  });
161
- _router.use(router.path, router.router);
189
+ if (res.router && _router) {
190
+ _router.use(res.path || "/", res.router);
191
+ }
162
192
  }));
163
193
  // ////////////////////////////////
164
194
  // /// Prepare Controllers
@@ -168,32 +198,37 @@ function prepareTarget(_a) {
168
198
  const controllerData = data.controller;
169
199
  if (!controllerData)
170
200
  return;
171
- const router = yield prepareTarget({
201
+ const res = yield prepareTarget({
172
202
  target: controller,
173
203
  namespace: `${namespace}/${controller.name}`,
174
204
  prefix: controllerData.path,
175
205
  imports: controllerData.imports,
176
206
  instance: tsyringe_1.container.resolve(controller),
177
207
  log,
208
+ hooks,
178
209
  });
179
- _router.use(router.path, router.router);
210
+ if (res.router && _router) {
211
+ _router.use(res.path || "/", res.router);
212
+ }
180
213
  }));
181
214
  ////////////////////////////////
182
215
  /// Prepare Routes
183
216
  ////////////////////////////////
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
- }));
217
+ if (_router) {
218
+ yield (0, object_util_1.$each)(Array.from(routes.routes), (route) => __awaiter(this, void 0, void 0, function* () {
219
+ if (typeof route !== "object")
220
+ return;
221
+ yield prepareRoutes({
222
+ target: target,
223
+ router: _router,
224
+ route,
225
+ namespace,
226
+ instance,
227
+ prefix: prefix || "/",
228
+ log,
229
+ });
230
+ }));
231
+ }
197
232
  return {
198
233
  router: _router,
199
234
  path: prefix,
@@ -232,21 +267,13 @@ function prepareRoutes(_a) {
232
267
  }
233
268
  else {
234
269
  $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);
270
+ const len = params.length;
271
+ const args = new Array(len);
272
+ for (let i = 0; i < len; i++) {
273
+ args[i] = yield params[i].resolver(req, res);
274
+ }
275
+ return handler.apply(instance, args);
240
276
  }));
241
277
  }
242
278
  });
243
279
  }
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
+ }
@@ -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);
@@ -14,11 +14,10 @@ function scopeTransfrom(listScopes, ...callback) {
14
14
  if (!userScopesRaw || userScopesRaw.length === 0) {
15
15
  return next(new exeptions_1.NotScopeException(`FORBIDDEN`, [], Array.from(scopeNames)));
16
16
  }
17
- const userScopes = new Set(userScopesRaw);
18
- if (userScopes.has(constants_1.FULL_ACCESS))
17
+ if (userScopesRaw.includes(constants_1.FULL_ACCESS))
19
18
  return next();
20
19
  for (const scope of scopes) {
21
- if (!userScopes.has(scope.scope)) {
20
+ if (!userScopesRaw.includes(scope.scope)) {
22
21
  return next(new exeptions_1.NotScopeException((_a = scope.message) !== null && _a !== void 0 ? _a : `FORBIDDEN`, userScopesRaw, Array.from(scopeNames)));
23
22
  }
24
23
  }