@zenofolio/hyper-decor 1.0.72 → 1.0.73

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 (118) hide show
  1. package/.agent/rules/philosophy.md +103 -0
  2. package/.agent/rules/writing.md +32 -0
  3. package/README.md +125 -136
  4. package/dist/__internals/constants.d.ts +1 -62
  5. package/dist/__internals/constants.js +3 -69
  6. package/dist/__internals/helpers/merge-metadata.d.ts +2 -3
  7. package/dist/__internals/helpers/merge-metadata.js +31 -7
  8. package/dist/__internals/helpers/prepare.helper.d.ts +4 -10
  9. package/dist/__internals/helpers/prepare.helper.js +316 -271
  10. package/dist/__internals/stores/hyper.store.d.ts +5 -0
  11. package/dist/__internals/stores/hyper.store.js +5 -0
  12. package/dist/__internals/stores/index.d.ts +4 -0
  13. package/dist/__internals/stores/index.js +20 -0
  14. package/dist/__internals/stores/meta.store.d.ts +34 -0
  15. package/dist/__internals/stores/meta.store.js +107 -0
  16. package/dist/__internals/stores/scope.store.d.ts +14 -0
  17. package/dist/__internals/stores/scope.store.js +29 -0
  18. package/dist/__internals/stores/serivces.store.d.ts +1 -0
  19. package/dist/__internals/stores/serivces.store.js +4 -0
  20. package/dist/__internals/transform/middleware.transform.d.ts +1 -1
  21. package/dist/__internals/transform/middleware.transform.js +1 -1
  22. package/dist/__internals/transform/role.transform.d.ts +1 -1
  23. package/dist/__internals/transform/role.transform.js +4 -4
  24. package/dist/__internals/transform/scope.transfrom.d.ts +1 -1
  25. package/dist/__internals/transform/scope.transfrom.js +2 -2
  26. package/dist/__internals/types.d.ts +53 -4
  27. package/dist/common/bootstrap.d.ts +6 -2
  28. package/dist/common/bootstrap.js +44 -10
  29. package/dist/common/transport.d.ts +1 -0
  30. package/dist/common/transport.js +27 -14
  31. package/dist/constants.d.ts +1 -0
  32. package/dist/constants.js +2 -1
  33. package/dist/decorators.d.ts +1 -0
  34. package/dist/decorators.js +17 -0
  35. package/dist/index.d.ts +6 -5
  36. package/dist/index.js +6 -5
  37. package/dist/lib/event/meta.store.d.ts +4 -0
  38. package/dist/lib/event/meta.store.js +5 -0
  39. package/dist/lib/openapi/collectors/class.collector.d.ts +5 -9
  40. package/dist/lib/openapi/collectors/class.collector.js +6 -63
  41. package/dist/lib/openapi/collectors/index.d.ts +3 -4
  42. package/dist/lib/openapi/collectors/index.js +0 -1
  43. package/dist/lib/openapi/collectors/method.collector.d.ts +6 -1
  44. package/dist/lib/openapi/collectors/method.collector.js +92 -59
  45. package/dist/lib/openapi/collectors/schema.collector.d.ts +3 -8
  46. package/dist/lib/openapi/collectors/schema.collector.js +17 -25
  47. package/dist/lib/openapi/constants.d.ts +1 -0
  48. package/dist/lib/openapi/constants.js +2 -2
  49. package/dist/lib/openapi/decorators.d.ts +16 -0
  50. package/dist/lib/openapi/decorators.js +93 -0
  51. package/dist/lib/openapi/index.d.ts +29 -5
  52. package/dist/lib/openapi/index.js +119 -5
  53. package/dist/lib/openapi/metadata.d.ts +7 -0
  54. package/dist/lib/openapi/metadata.js +8 -0
  55. package/dist/lib/openapi/metadata.registry.d.ts +1 -1
  56. package/dist/lib/server/decorators/File.d.ts +37 -0
  57. package/dist/lib/server/decorators/File.js +167 -0
  58. package/dist/lib/server/decorators/Http.d.ts +12 -0
  59. package/dist/lib/server/decorators/Http.js +56 -0
  60. package/dist/lib/server/decorators/HyperApp.d.ts +7 -0
  61. package/dist/lib/server/decorators/HyperApp.js +14 -0
  62. package/dist/lib/server/decorators/HyperController.d.ts +6 -0
  63. package/dist/lib/server/decorators/HyperController.js +27 -0
  64. package/dist/lib/server/decorators/HyperModule.d.ts +6 -0
  65. package/dist/lib/server/decorators/HyperModule.js +13 -0
  66. package/dist/lib/server/decorators/HyperService.d.ts +11 -0
  67. package/dist/lib/server/decorators/HyperService.js +30 -0
  68. package/dist/lib/server/decorators/Messaging.d.ts +8 -0
  69. package/dist/lib/server/decorators/Messaging.js +19 -0
  70. package/dist/lib/server/decorators/Middleware.d.ts +18 -0
  71. package/dist/lib/server/decorators/Middleware.js +52 -0
  72. package/dist/lib/server/decorators/Output.d.ts +6 -0
  73. package/dist/lib/server/decorators/Output.js +14 -0
  74. package/dist/lib/server/decorators/Pass.d.ts +10 -0
  75. package/dist/lib/server/decorators/Pass.js +13 -0
  76. package/dist/lib/server/decorators/Role.d.ts +7 -0
  77. package/dist/lib/server/decorators/Role.js +14 -0
  78. package/dist/lib/server/decorators/Routes.d.ts +14 -0
  79. package/dist/lib/server/decorators/Routes.js +39 -0
  80. package/dist/lib/server/decorators/Scope.d.ts +7 -0
  81. package/dist/lib/server/decorators/Scope.js +14 -0
  82. package/dist/lib/server/decorators/index.d.ts +16 -0
  83. package/dist/lib/server/decorators/index.js +32 -0
  84. package/dist/lib/server/decorators/metadata.d.ts +1 -0
  85. package/dist/lib/server/decorators/metadata.js +5 -0
  86. package/dist/lib/server/decorators/types.d.ts +125 -0
  87. package/dist/lib/server/decorators/types.js +6 -0
  88. package/dist/lib/server/exeptions/DuplicateControllerPathException.d.ts +14 -0
  89. package/dist/lib/server/exeptions/DuplicateControllerPathException.js +12 -0
  90. package/dist/lib/server/exeptions/DuplicatedException.d.ts +8 -0
  91. package/dist/lib/server/exeptions/DuplicatedException.js +12 -0
  92. package/dist/lib/server/exeptions/DuplicatedHandlerException.d.ts +4 -0
  93. package/dist/lib/server/exeptions/DuplicatedHandlerException.js +12 -0
  94. package/dist/lib/server/exeptions/HyperException.d.ts +8 -0
  95. package/dist/lib/server/exeptions/HyperException.js +14 -0
  96. package/dist/lib/server/exeptions/HyperFileException.d.ts +4 -0
  97. package/dist/lib/server/exeptions/HyperFileException.js +12 -0
  98. package/dist/lib/server/exeptions/MethodNotFountException.d.ts +4 -0
  99. package/dist/lib/server/exeptions/MethodNotFountException.js +12 -0
  100. package/dist/lib/server/exeptions/NotPropertyException.d.ts +6 -0
  101. package/dist/lib/server/exeptions/NotPropertyException.js +16 -0
  102. package/dist/lib/server/exeptions/NotRoleException.d.ts +6 -0
  103. package/dist/lib/server/exeptions/NotRoleException.js +17 -0
  104. package/dist/lib/server/exeptions/NotScopeException.d.ts +7 -0
  105. package/dist/lib/server/exeptions/NotScopeException.js +18 -0
  106. package/dist/lib/server/exeptions/WrongPlaceException.d.ts +8 -0
  107. package/dist/lib/server/exeptions/WrongPlaceException.js +21 -0
  108. package/dist/lib/server/exeptions/index.d.ts +8 -0
  109. package/dist/lib/server/exeptions/index.js +18 -0
  110. package/dist/lib/server/exeptions/types.d.ts +1 -0
  111. package/dist/lib/server/exeptions/types.js +2 -0
  112. package/dist/lib/tree/tree.d.ts +36 -0
  113. package/dist/lib/tree/tree.js +106 -0
  114. package/package.json +1 -1
  115. package/scripts/clean.js +55 -55
  116. package/scripts/test-server.ts +85 -85
  117. package/vitest.config.mjs +33 -30
  118. package/vitest.json +0 -0
@@ -12,259 +12,149 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.registerInstanceHandlers = registerInstanceHandlers;
15
16
  exports.prepareApplication = prepareApplication;
17
+ require("reflect-metadata");
16
18
  const hyper_express_1 = require("hyper-express");
17
- const stores_1 = require("../../stores");
19
+ const tsyringe_1 = require("tsyringe");
20
+ const stores_1 = require("../stores");
21
+ const meta_store_1 = require("../stores/meta.store");
18
22
  const role_transform_1 = __importDefault(require("../transform/role.transform"));
19
23
  const scope_transfrom_1 = __importDefault(require("../transform/scope.transfrom"));
20
- const object_util_1 = require("../utils/object.util");
21
- const decorator_base_1 = require("../decorator-base");
22
- const constants_1 = require("../constants");
23
24
  const middleware_transform_1 = __importDefault(require("../transform/middleware.transform"));
24
- const tsyringe_1 = require("tsyringe");
25
25
  const path_util_1 = require("../utils/path.util");
26
- const imports_helper_1 = require("./imports.helper");
26
+ const transform_registry_1 = require("../transform/transform.registry");
27
27
  const message_bus_1 = require("../../common/message-bus");
28
28
  const transport_1 = require("../../common/transport");
29
- const transform_registry_1 = require("../transform/transform.registry");
30
- const if_router = (current) => {
31
- if (!current || !((current === null || current === void 0 ? void 0 : current.prototype) instanceof hyper_express_1.Router))
29
+ /* -------------------------------------------------------------------------- */
30
+ /* Helpers */
31
+ /* -------------------------------------------------------------------------- */
32
+ function createRouter(target) {
33
+ if (!target || !(target.prototype instanceof hyper_express_1.Router)) {
32
34
  return new hyper_express_1.Router();
33
- return new current();
34
- };
35
- /**
36
- * Extract the data from the target class.
37
- *
38
- * @param target
39
- * @returns
40
- */
41
- function getData(target) {
42
- var _a, _b, _c, _d, _e;
43
- const app = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_APP, target);
44
- const module = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_MODULE, target);
45
- const controller = (0, decorator_base_1.getDecorData)(constants_1.KEY_TYPE_CONTROLLER, target);
46
- const middlewares = (0, middleware_transform_1.default)((_a = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_MIDDLEWARES, target)) !== null && _a !== void 0 ? _a : []);
47
- const scopes = (_b = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_SCOPE, target)) !== null && _b !== void 0 ? _b : [];
48
- const roles = (_c = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_ROLE, target)) !== null && _c !== void 0 ? _c : [];
49
- const routes = (_d = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_ROUTE, target)) !== null && _d !== void 0 ? _d : {
50
- routes: [],
35
+ }
36
+ return new target();
37
+ }
38
+ function getServerMetadata(target) {
39
+ const root = meta_store_1.Metadata.get(target);
40
+ return root.server || {
41
+ common: { type: "controller" },
42
+ methods: {},
51
43
  };
52
- const params = (_e = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_PARAM, target)) !== null && _e !== void 0 ? _e : {};
53
- const pass = (0, decorator_base_1.getDecorData)(constants_1.KEY_PARAMS_PASS, target);
44
+ }
45
+ function getCommonMetadata(target) {
46
+ const server = getServerMetadata(target);
47
+ return server.common || { type: "controller" };
48
+ }
49
+ function getMethodMetadataMap(target) {
50
+ const server = getServerMetadata(target);
51
+ return (server.methods || {});
52
+ }
53
+ function getData(target) {
54
+ var _a, _b, _c;
55
+ const common = getCommonMetadata(target);
54
56
  return {
55
- app,
56
- module,
57
- controller,
58
- middlewares,
59
- scopes,
60
- roles,
61
- routes,
62
- params,
63
- pass,
57
+ type: common.type,
58
+ metadata: common,
59
+ middlewares: (0, middleware_transform_1.default)((_a = common.middlewares) !== null && _a !== void 0 ? _a : []),
60
+ scopes: (_b = common.scopes) !== null && _b !== void 0 ? _b : [],
61
+ roles: (_c = common.roles) !== null && _c !== void 0 ? _c : [],
62
+ methods: getMethodMetadataMap(target),
63
+ pass: !!common.pass,
64
64
  };
65
65
  }
66
- /**
67
- * Prepare the application with the given options.
68
- *
69
- * @param options
70
- * @param Target
71
- * @param app
72
- * @param log
73
- */
74
- function prepareApplication(options, Target, app, log) {
66
+ function logTargetType(type, namespace, prefix, log) {
67
+ if (type === "module") {
68
+ log("modules", `${namespace} { ${prefix} }`);
69
+ }
70
+ else if (type === "controller") {
71
+ log("controllers", `${namespace} { ${prefix} }`);
72
+ }
73
+ }
74
+ function registerInstanceHandlers(instance, target, namespace, log) {
75
75
  return __awaiter(this, void 0, void 0, function* () {
76
- var _a, _b, _c;
77
- const data = getData(Target);
78
- const prefix = (_a = options.prefix) !== null && _a !== void 0 ? _a : "/";
79
- const imports = (_b = options.imports) !== null && _b !== void 0 ? _b : [];
80
- // Register transports if provided, otherwise fallback to internal
76
+ const methods = getMethodMetadataMap(target);
81
77
  const bus = tsyringe_1.container.resolve(message_bus_1.MessageBus);
82
- if ((_c = options === null || options === void 0 ? void 0 : options.transports) === null || _c === void 0 ? void 0 : _c.length) {
83
- options.transports.forEach((t) => bus.registerTransport(t));
84
- }
85
- else {
86
- bus.registerTransport(new transport_1.InternalTransport());
87
- }
88
- let hooks = options.hooks;
89
- if (typeof hooks === "function" && !(hooks instanceof hyper_express_1.Router)) {
90
- if (hooks && "constructor" in hooks) {
91
- if (tsyringe_1.container.isRegistered(hooks)) {
92
- tsyringe_1.container.register(hooks, hooks);
93
- }
78
+ for (const propertyKey of Object.keys(methods)) {
79
+ const methodMeta = methods[propertyKey];
80
+ if (methodMeta.onMessage) {
81
+ yield bus.listen(methodMeta.onMessage.topic, (data) => __awaiter(this, void 0, void 0, function* () {
82
+ return yield instance[propertyKey].call(instance, data);
83
+ }));
84
+ log("messaging", `${namespace}/${propertyKey} -> ${methodMeta.onMessage.topic}`);
94
85
  }
95
- hooks = tsyringe_1.container.resolve(hooks);
96
- }
97
- const context = { target: Target, metadata: options, type: "app" };
98
- yield (0, imports_helper_1.prepareImports)(Target, imports, hooks, context);
99
- if (data.middlewares.length) {
100
- app.use(...data.middlewares);
101
- log("middleware", `${Target.name} with middlewares: ${data.middlewares
102
- .map((e) => e.name)
103
- .join(", ")}`);
104
86
  }
105
- (0, scope_transfrom_1.default)(data.scopes, (middleware, scopes) => {
106
- stores_1.ScopeStore.addAll(scopes);
107
- app.use(middleware);
108
- log("middleware", `${Target.name} with scopes: ${data.scopes.join(", ")}`);
87
+ });
88
+ }
89
+ function applyCommonPipeline(targetName, carrier, data, log) {
90
+ if (data.middlewares.length) {
91
+ carrier.use(...data.middlewares);
92
+ log === null || log === void 0 ? void 0 : log("middleware", `${targetName} with middlewares: ${data.middlewares.map(m => m.name).join(", ")}`);
93
+ }
94
+ if (data.scopes.length) {
95
+ (0, scope_transfrom_1.default)(data.scopes, (middleware, resolvedScopes) => {
96
+ stores_1.ScopeStore.addAll(resolvedScopes);
97
+ carrier.use(middleware);
98
+ log === null || log === void 0 ? void 0 : log("middleware", `${targetName} with scopes: ${data.scopes.join(", ")}`);
109
99
  });
100
+ }
101
+ if (data.roles.length) {
110
102
  (0, role_transform_1.default)(data.roles, (middleware) => {
111
- app.use(middleware);
112
- log("middleware", `${Target.name} with roles: ${data.roles.join(", ")}`);
113
- });
114
- const routers = (yield Promise.all(options.modules.map((module) => __awaiter(this, void 0, void 0, function* () {
115
- var _a, _b, _c;
116
- const data = getData(module);
117
- const path = (_a = data.module) === null || _a === void 0 ? void 0 : _a.path;
118
- const imports = (_c = (_b = data.module) === null || _b === void 0 ? void 0 : _b.imports) !== null && _c !== void 0 ? _c : [];
119
- return prepareTarget({
120
- target: module,
121
- router: if_router(module),
122
- namespace: `${Target.name}/${module.name}`,
123
- instance: app,
124
- prefix: path,
125
- imports: imports,
126
- log,
127
- hooks: hooks,
128
- });
129
- })))).filter((r) => r.router);
130
- routers.forEach(({ router, path }) => {
131
- app.use((0, path_util_1.join)(prefix, path || "/"), router);
103
+ carrier.use(middleware);
104
+ log === null || log === void 0 ? void 0 : log("middleware", `${targetName} with roles: ${data.roles.join(", ")}`);
132
105
  });
133
- });
106
+ }
134
107
  }
135
- /**
136
- * Prepare the target class
137
- * HyperModule or HyperController can be used as target.
138
- *
139
- * @param param0
140
- * @returns
141
- */
142
- function prepareTarget(_a) {
143
- return __awaiter(this, arguments, void 0, function* ({ target, router, prefix, namespace = "", instance, imports = [], log, hooks, }) {
144
- var _b, _c, _d, _e, _f, _g, _h, _j;
145
- const data = getData(target);
146
- if (data.module) {
147
- log("modules", `${namespace} { ${prefix || "/"} }`);
148
- }
149
- else if (data.controller) {
150
- log("controllers", `${namespace} { ${prefix || "/"} }`);
151
- }
152
- const modules = (_c = (_b = data.module) === null || _b === void 0 ? void 0 : _b.modules) !== null && _c !== void 0 ? _c : [];
153
- const controllers = (_e = (_d = data.module) === null || _d === void 0 ? void 0 : _d.controllers) !== null && _e !== void 0 ? _e : [];
154
- const routes = (_f = data.routes) !== null && _f !== void 0 ? _f : { routes: [] };
155
- const middlewares = (_g = data.middlewares) !== null && _g !== void 0 ? _g : [];
156
- const scopes = (_h = data.scopes) !== null && _h !== void 0 ? _h : [];
157
- const roles = (_j = data.roles) !== null && _j !== void 0 ? _j : [];
158
- const needsRouter = controllers.length > 0 ||
159
- routes.routes.size > 0 ||
160
- middlewares.length > 0 ||
161
- scopes.length > 0 ||
162
- roles.length > 0;
163
- const _router = router !== null && router !== void 0 ? router : (needsRouter ? if_router(target) : undefined);
164
- ////////////////////////////////
165
- /// Prepare Imports
166
- ////////////////////////////////
167
- const context = { target: target, metadata: data, type: "target" };
168
- yield (0, imports_helper_1.prepareImports)(target, imports, hooks, context);
169
- ////////////////////////////////
170
- /// Attach Middlewares & Security
171
- ////////////////////////////////
172
- if (_router) {
173
- _router.use(...middlewares);
174
- (0, scope_transfrom_1.default)(scopes, (middleware, scopes) => {
175
- stores_1.ScopeStore.addAll(scopes);
176
- _router.use(middleware);
177
- });
178
- (0, role_transform_1.default)(roles, (middleware) => _router.use(middleware));
179
- }
180
- ////////////////////////////////
181
- /// Prepare Modules
182
- ////////////////////////////////
183
- yield (0, object_util_1.$each)(modules, (module) => __awaiter(this, void 0, void 0, function* () {
184
- const moduleData = getData(module);
185
- if (!moduleData.module)
186
- return;
187
- const res = yield prepareTarget({
188
- target: module,
189
- imports: moduleData.module.imports,
190
- namespace: `${namespace}/${module.name}`,
191
- prefix: moduleData.module.path,
192
- instance: tsyringe_1.container.resolve(module),
193
- log,
194
- hooks,
195
- });
196
- if (res.router && _router) {
197
- _router.use(res.path || "/", res.router);
198
- }
199
- }));
200
- // ////////////////////////////////
201
- // /// Prepare Controllers
202
- // ////////////////////////////////
203
- yield (0, object_util_1.$each)(controllers, (controller) => __awaiter(this, void 0, void 0, function* () {
204
- const data = getData(controller);
205
- const controllerData = data.controller;
206
- if (!controllerData)
207
- return;
208
- const res = yield prepareTarget({
209
- target: controller,
210
- namespace: `${namespace}/${controller.name}`,
211
- prefix: controllerData.path,
212
- imports: controllerData.imports,
213
- instance: tsyringe_1.container.resolve(controller),
214
- log,
215
- hooks,
108
+ /* -------------------------------------------------------------------------- */
109
+ /* Route/Handler construction */
110
+ /* -------------------------------------------------------------------------- */
111
+ function buildArgumentsResolver(paramsMeta) {
112
+ const sorted = [...paramsMeta].sort((a, b) => a.index - b.index);
113
+ const hasBody = sorted.some((p) => p.source === "body");
114
+ // Pre-calculate per-parameter resolution logic
115
+ const resolvers = sorted.map((meta) => {
116
+ if (meta.resolver)
117
+ return meta.resolver;
118
+ const sourceKey = meta.source;
119
+ if (!sourceKey)
120
+ return () => null;
121
+ const isWhole = meta.isWholeSource;
122
+ const picker = meta.picker;
123
+ const schema = meta.schema;
124
+ return (req, res, body) => __awaiter(this, void 0, void 0, function* () {
125
+ if (sourceKey === "req")
126
+ return req;
127
+ if (sourceKey === "res")
128
+ return res;
129
+ let source = sourceKey === "body" ? body : req[sourceKey];
130
+ if (!source)
131
+ return null;
132
+ const rawValue = isWhole ? source : picker ? source[picker] : source;
133
+ if (!schema)
134
+ return rawValue;
135
+ return yield transform_registry_1.transformRegistry.resolve({
136
+ data: rawValue,
137
+ schema,
138
+ options: {},
139
+ req,
140
+ res,
141
+ from: sourceKey,
216
142
  });
217
- if (res.router && _router) {
218
- _router.use(res.path || "/", res.router);
219
- }
220
- }));
221
- ////////////////////////////////
222
- /// Prepare Routes
223
- ////////////////////////////////
224
- if (_router) {
225
- yield (0, object_util_1.$each)(Array.from(routes.routes), (route) => __awaiter(this, void 0, void 0, function* () {
226
- if (typeof route !== "object")
227
- return;
228
- yield prepareRoutes({
229
- target: target,
230
- router: _router,
231
- route,
232
- namespace,
233
- instance,
234
- prefix: prefix || "/",
235
- log,
236
- });
237
- }));
238
- }
239
- return {
240
- router: _router,
241
- path: prefix,
242
- };
143
+ });
243
144
  });
244
- }
245
- /**
246
- * Resolves method parameters and applies adaptive transformations.
247
- * Optimized: Metadata is resolved once and passed here.
248
- */
249
- function resolveMethodParams(req, res, params) {
250
- return __awaiter(this, void 0, void 0, function* () {
251
- const len = params.length;
252
- const args = new Array(len);
253
- for (let i = 0; i < len; i++) {
254
- args[i] = yield params[i].resolver(req, res);
255
- }
256
- return args;
145
+ return (req, res) => __awaiter(this, void 0, void 0, function* () {
146
+ if (resolvers.length === 0)
147
+ return [req, res];
148
+ const body = hasBody && typeof req.json === "function" ? yield req.json() : undefined;
149
+ return yield Promise.all(resolvers.map((r) => r(req, res, body)));
257
150
  });
258
151
  }
259
- /**
260
- * Handles output transformation and sends the response.
261
- * Optimized: outputSchema is pre-resolved outside the request hotpath.
262
- */
263
- function handleResponse(req, res, result, outputSchema) {
264
- return __awaiter(this, void 0, void 0, function* () {
152
+ function buildResponseSender(outputSchema) {
153
+ const needsTransform = outputSchema && outputSchema !== Object && outputSchema !== Promise;
154
+ return (res, result, req) => __awaiter(this, void 0, void 0, function* () {
265
155
  if (result === undefined || res.completed)
266
156
  return;
267
- if (outputSchema && outputSchema !== Object && outputSchema !== Promise) {
157
+ if (needsTransform) {
268
158
  const transformed = yield transform_registry_1.transformRegistry.resolve({
269
159
  data: result,
270
160
  schema: outputSchema,
@@ -278,61 +168,216 @@ function handleResponse(req, res, result, outputSchema) {
278
168
  return;
279
169
  }
280
170
  }
281
- if (!res.completed) {
282
- if (typeof result === "object" && result !== null) {
283
- res.json(result);
284
- }
285
- else {
286
- res.send(result);
287
- }
171
+ if (res.completed)
172
+ return;
173
+ if (typeof result === "object" && result !== null) {
174
+ res.json(result);
175
+ }
176
+ else {
177
+ res.send(result);
288
178
  }
289
179
  });
290
180
  }
291
- /**
292
- * Prepare the routes for the target class.
293
- */
294
- function prepareRoutes(_a) {
295
- return __awaiter(this, arguments, void 0, function* ({ target, router, route, instance, namespace, log, }) {
296
- var _b, _c, _d;
297
- const { method, path, handler, propertyKey, options } = route;
298
- const metadata = getData(handler);
299
- const params = (_d = (_c = (_b = metadata.params) === null || _b === void 0 ? void 0 : _b.params) === null || _c === void 0 ? void 0 : _c[propertyKey]) !== null && _d !== void 0 ? _d : [];
300
- const $fn = Reflect.get(router, method);
301
- if (!$fn)
302
- return;
303
- const middlewares = [...metadata.middlewares];
304
- const proto = target.prototype || target;
305
- // Pre-resolve Output-Metadata
306
- const outputSchema = Reflect.getMetadata(constants_1.KEY_OUTPUT_SCHEMA, proto, propertyKey) ||
307
- Reflect.getMetadata(constants_1.DESIGN_RETURNTYPE, proto, propertyKey);
308
- (0, role_transform_1.default)(metadata.roles, (middleware) => middlewares.push(middleware));
309
- (0, scope_transfrom_1.default)(metadata.scopes, (middleware, scopes) => {
310
- middlewares.push(middleware);
311
- stores_1.ScopeStore.addAll(scopes);
181
+ function prepareRoute(target, router, route, instance, namespace, log) {
182
+ return __awaiter(this, void 0, void 0, function* () {
183
+ var _a, _b, _c, _d, _e, _f, _g;
184
+ const { method, path, propertyKey, options } = route;
185
+ const methodMeta = getMethodMetadataMap(target)[propertyKey] || {};
186
+ const ctrlMeta = getCommonMetadata(target);
187
+ const roles = [...((_a = ctrlMeta.roles) !== null && _a !== void 0 ? _a : []), ...((_b = methodMeta.roles) !== null && _b !== void 0 ? _b : [])];
188
+ const scopes = [...((_c = ctrlMeta.scopes) !== null && _c !== void 0 ? _c : []), ...((_d = methodMeta.scopes) !== null && _d !== void 0 ? _d : [])];
189
+ const middlewares = (0, middleware_transform_1.default)((_e = methodMeta.middlewares) !== null && _e !== void 0 ? _e : []);
190
+ (0, role_transform_1.default)(roles, m => middlewares.push(m));
191
+ (0, scope_transfrom_1.default)(scopes, (m, s) => {
192
+ middlewares.push(m);
193
+ stores_1.ScopeStore.addAll(s);
312
194
  });
313
- log("routes", `${namespace}/${propertyKey.toString()} ${method.toUpperCase()} { ${path} }`);
314
- const routeHandler = (req, res) => __awaiter(this, void 0, void 0, function* () {
195
+ log("routes", `${namespace}/${propertyKey} ${method.toUpperCase()} { ${path} }`);
196
+ if (method === "ws" && options) {
197
+ router.ws(path, options, instance[propertyKey].bind(instance));
198
+ return;
199
+ }
200
+ const argumentResolver = buildArgumentsResolver(((_f = methodMeta.params) === null || _f === void 0 ? void 0 : _f.params) || []);
201
+ const responseSender = buildResponseSender(methodMeta.output || ((_g = methodMeta.reflection) === null || _g === void 0 ? void 0 : _g.output));
202
+ const handlerMethod = instance[propertyKey];
203
+ const handler = (req, res) => __awaiter(this, void 0, void 0, function* () {
315
204
  try {
316
- const args = params.length > 0
317
- ? yield resolveMethodParams(req, res, params)
318
- : [req, res];
319
- const result = yield handler.apply(instance, args);
320
- yield handleResponse(req, res, result, outputSchema);
205
+ const args = yield argumentResolver(req, res);
206
+ const result = yield handlerMethod.apply(instance, args);
207
+ yield responseSender(res, result, req);
321
208
  }
322
209
  catch (err) {
323
- if (!res.completed) {
324
- const error = err;
325
- res.status(error.status || 500).json({
326
- error: error.message || "Internal Server Error",
327
- code: error.code,
328
- });
210
+ if (res.completed)
211
+ return;
212
+ const error = err;
213
+ res.status(error.status || 500).json({
214
+ error: error.message || "Internal Server Error",
215
+ code: error.code,
216
+ });
217
+ }
218
+ });
219
+ const fn = Reflect.get(router, method);
220
+ if (fn)
221
+ fn.call(router, path, ...middlewares, handler);
222
+ });
223
+ }
224
+ /* -------------------------------------------------------------------------- */
225
+ /* Preparation Logic */
226
+ /* -------------------------------------------------------------------------- */
227
+ function prepareImportsInternal(imports, context, log) {
228
+ return __awaiter(this, void 0, void 0, function* () {
229
+ yield Promise.all(imports.map((item) => __awaiter(this, void 0, void 0, function* () {
230
+ var _a, _b;
231
+ let token;
232
+ if (typeof item === "function") {
233
+ token = item;
234
+ if (!tsyringe_1.container.isRegistered(token))
235
+ tsyringe_1.container.register(token, token);
236
+ }
237
+ else if (typeof item === "object" && item !== null) {
238
+ const obj = item;
239
+ token = obj.token;
240
+ if (obj.useClass)
241
+ tsyringe_1.container.register(token, { useClass: obj.useClass });
242
+ else if (obj.useValue)
243
+ tsyringe_1.container.register(token, { useValue: obj.useValue });
244
+ else if (obj.useFactory)
245
+ tsyringe_1.container.register(token, { useFactory: obj.useFactory });
246
+ else if (obj.useToken)
247
+ tsyringe_1.container.register(token, { useToken: obj.useToken });
248
+ }
249
+ else {
250
+ token = item;
251
+ }
252
+ const instance = tsyringe_1.container.resolve(token);
253
+ if (instance) {
254
+ const itemContext = Object.assign(Object.assign({}, context), { type: "service", target: token });
255
+ if ((_a = context.hooks) === null || _a === void 0 ? void 0 : _a.onBeforeInit)
256
+ yield context.hooks.onBeforeInit(instance, token, itemContext);
257
+ if (typeof token === "function" && token.name) {
258
+ yield registerInstanceHandlers(instance, token, `imports/${token.name}`, log);
329
259
  }
260
+ if (typeof instance.onInit === "function")
261
+ yield instance.onInit();
262
+ if ((_b = context.hooks) === null || _b === void 0 ? void 0 : _b.onAfterInit)
263
+ yield context.hooks.onAfterInit(instance, token, itemContext);
330
264
  }
265
+ })));
266
+ });
267
+ }
268
+ /**
269
+ * Ensures a class is resolvable by tsyringe even without @injectable()
270
+ */
271
+ function ensureResolvable(target) {
272
+ if (!tsyringe_1.container.isRegistered(target)) {
273
+ // We apply injectable() at runtime to ensure metadata is picked up if not already done
274
+ (0, tsyringe_1.injectable)()(target);
275
+ tsyringe_1.container.register(target, target);
276
+ }
277
+ }
278
+ function prepareController(descriptor, context, log) {
279
+ return __awaiter(this, void 0, void 0, function* () {
280
+ var _a;
281
+ const { target, instance, metadata } = descriptor;
282
+ const data = getData(target);
283
+ const router = new hyper_express_1.Router();
284
+ logTargetType("controller", context.namespace, context.prefix, log);
285
+ yield prepareImportsInternal((_a = metadata.imports) !== null && _a !== void 0 ? _a : [], context, log);
286
+ yield registerInstanceHandlers(instance, target, context.namespace, log);
287
+ applyCommonPipeline(target.name, { use: (...args) => router.use(...args) }, data, log);
288
+ const methods = getMethodMetadataMap(target);
289
+ for (const key of Object.keys(methods)) {
290
+ const route = methods[key].route;
291
+ if (route)
292
+ yield prepareRoute(target, router, route, instance, context.namespace, log);
293
+ }
294
+ context.parentRouter.use(context.prefix, router);
295
+ });
296
+ }
297
+ function prepareModule(descriptor, context, log) {
298
+ return __awaiter(this, void 0, void 0, function* () {
299
+ var _a, _b, _c;
300
+ const { target, instance, metadata } = descriptor;
301
+ const data = getData(target);
302
+ const router = new hyper_express_1.Router();
303
+ logTargetType("module", context.namespace, context.prefix, log);
304
+ yield prepareImportsInternal((_a = metadata.imports) !== null && _a !== void 0 ? _a : [], context, log);
305
+ yield registerInstanceHandlers(instance, target, context.namespace, log);
306
+ applyCommonPipeline(target.name, { use: (...args) => router.use(...args) }, data, log);
307
+ // Recurse modules
308
+ if ((_b = metadata.modules) === null || _b === void 0 ? void 0 : _b.length) {
309
+ for (const m of metadata.modules) {
310
+ const mData = getData(m).metadata;
311
+ ensureResolvable(m);
312
+ yield prepareModule({ target: m, instance: tsyringe_1.container.resolve(m), metadata: mData }, {
313
+ parentRouter: router,
314
+ namespace: `${context.namespace}/${m.name}`,
315
+ prefix: mData.path || "/",
316
+ hooks: context.hooks,
317
+ type: "module",
318
+ target: m
319
+ }, log);
320
+ }
321
+ }
322
+ // Controllers
323
+ if ((_c = metadata.controllers) === null || _c === void 0 ? void 0 : _c.length) {
324
+ for (const c of metadata.controllers) {
325
+ const cData = getData(c).metadata;
326
+ ensureResolvable(c);
327
+ yield prepareController({ target: c, instance: tsyringe_1.container.resolve(c), metadata: cData }, {
328
+ parentRouter: router,
329
+ namespace: `${context.namespace}/${c.name}`,
330
+ prefix: cData.path || "/",
331
+ hooks: context.hooks,
332
+ type: "controller",
333
+ target: c
334
+ }, log);
335
+ }
336
+ }
337
+ context.parentRouter.use(context.prefix, router);
338
+ });
339
+ }
340
+ function prepareApplication(options, Target, log) {
341
+ return __awaiter(this, void 0, void 0, function* () {
342
+ var _a, _b, _c;
343
+ const appServer = new hyper_express_1.Server(options.uwsOptions || options.options);
344
+ // Register global error handler to properly handle status codes from exceptions
345
+ appServer.set_error_handler((req, res, error) => {
346
+ const status = error.status || 500;
347
+ res.status(status).json(Object.assign({ error: error.message || "Internal Server Error", code: error.code || "InternalServerError" }, (error instanceof Error ? { stack: error.stack } : {})));
331
348
  });
332
- if (method === "ws" && options) {
333
- router.ws(path, options, handler.bind(instance));
334
- return;
349
+ ensureResolvable(Target);
350
+ const appInstance = tsyringe_1.container.resolve(Target);
351
+ const data = getData(Target);
352
+ const bus = tsyringe_1.container.resolve(message_bus_1.MessageBus);
353
+ const transports = options.transports && options.transports.length > 0 ? options.transports : [transport_1.InternalTransport];
354
+ transports.forEach(t => bus.registerTransport(typeof t === "function" ? tsyringe_1.container.resolve(t) : t));
355
+ const hooks = (options.hooks ? (typeof options.hooks === "function" ? tsyringe_1.container.resolve(options.hooks) : options.hooks) : undefined);
356
+ const context = {
357
+ parentRouter: appServer,
358
+ namespace: Target.name,
359
+ prefix: (_a = options.prefix) !== null && _a !== void 0 ? _a : "/",
360
+ hooks,
361
+ type: "app",
362
+ target: Target
363
+ };
364
+ yield prepareImportsInternal((_b = options.imports) !== null && _b !== void 0 ? _b : [], context, log);
365
+ yield registerInstanceHandlers(appInstance, Target, context.namespace, log);
366
+ applyCommonPipeline(Target.name, { use: (...args) => appServer.use(...args) }, data, log);
367
+ if ((_c = options.modules) === null || _c === void 0 ? void 0 : _c.length) {
368
+ for (const m of options.modules) {
369
+ const mData = getData(m).metadata;
370
+ ensureResolvable(m);
371
+ yield prepareModule({ target: m, instance: tsyringe_1.container.resolve(m), metadata: mData }, {
372
+ parentRouter: appServer,
373
+ namespace: `${Target.name}/${m.name}`,
374
+ prefix: (0, path_util_1.join)(context.prefix, mData.path || "/"),
375
+ hooks,
376
+ type: "module",
377
+ target: m
378
+ }, log);
379
+ }
335
380
  }
336
- $fn.call(router, path, ...middlewares, routeHandler);
381
+ return appServer;
337
382
  });
338
383
  }
@@ -0,0 +1,5 @@
1
+ import { HyperCommonMetadata, HyperMethodMetadata } from "../types";
2
+ export declare const HyperMeta: {
3
+ set: (target: object, propertyKey: any, data: Partial<HyperCommonMetadata> | Partial<HyperMethodMetadata>) => void;
4
+ get: (target: object, propertyKey?: any) => Partial<HyperCommonMetadata> | Partial<HyperMethodMetadata>;
5
+ };