node-honest 0.0.7 → 0.1.0

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 (163) hide show
  1. package/dist/index.cjs +2185 -0
  2. package/dist/index.d.cts +1539 -0
  3. package/dist/index.d.ts +1539 -16
  4. package/dist/index.js +2116 -15
  5. package/package.json +12 -9
  6. package/dist/application/plugin-entries.d.ts +0 -13
  7. package/dist/application/plugin-entries.js +0 -38
  8. package/dist/application/startup-guide.d.ts +0 -4
  9. package/dist/application/startup-guide.js +0 -53
  10. package/dist/application-context.d.ts +0 -13
  11. package/dist/application-context.js +0 -22
  12. package/dist/application.d.ts +0 -34
  13. package/dist/application.js +0 -224
  14. package/dist/components/index.d.ts +0 -1
  15. package/dist/components/index.js +0 -1
  16. package/dist/components/layout.component.d.ts +0 -31
  17. package/dist/components/layout.component.js +0 -94
  18. package/dist/constants/index.d.ts +0 -2
  19. package/dist/constants/index.js +0 -2
  20. package/dist/constants/pipeline.constants.d.ts +0 -6
  21. package/dist/constants/pipeline.constants.js +0 -6
  22. package/dist/constants/version.constants.d.ts +0 -5
  23. package/dist/constants/version.constants.js +0 -5
  24. package/dist/decorators/controller.decorator.d.ts +0 -9
  25. package/dist/decorators/controller.decorator.js +0 -16
  26. package/dist/decorators/http-method.decorator.d.ts +0 -43
  27. package/dist/decorators/http-method.decorator.js +0 -44
  28. package/dist/decorators/index.d.ts +0 -11
  29. package/dist/decorators/index.js +0 -11
  30. package/dist/decorators/module.decorator.d.ts +0 -8
  31. package/dist/decorators/module.decorator.js +0 -12
  32. package/dist/decorators/mvc.decorator.d.ts +0 -26
  33. package/dist/decorators/mvc.decorator.js +0 -36
  34. package/dist/decorators/parameter.decorator.d.ts +0 -41
  35. package/dist/decorators/parameter.decorator.js +0 -59
  36. package/dist/decorators/service.decorator.d.ts +0 -6
  37. package/dist/decorators/service.decorator.js +0 -11
  38. package/dist/decorators/use-component.decorator.d.ts +0 -10
  39. package/dist/decorators/use-component.decorator.js +0 -19
  40. package/dist/decorators/use-filters.decorator.d.ts +0 -8
  41. package/dist/decorators/use-filters.decorator.js +0 -17
  42. package/dist/decorators/use-guards.decorator.d.ts +0 -9
  43. package/dist/decorators/use-guards.decorator.js +0 -18
  44. package/dist/decorators/use-middleware.decorator.d.ts +0 -9
  45. package/dist/decorators/use-middleware.decorator.js +0 -18
  46. package/dist/decorators/use-pipes.decorator.d.ts +0 -9
  47. package/dist/decorators/use-pipes.decorator.js +0 -18
  48. package/dist/di/container.d.ts +0 -34
  49. package/dist/di/container.js +0 -114
  50. package/dist/di/index.d.ts +0 -1
  51. package/dist/di/index.js +0 -1
  52. package/dist/errors/framework.error.d.ts +0 -19
  53. package/dist/errors/framework.error.js +0 -23
  54. package/dist/errors/index.d.ts +0 -1
  55. package/dist/errors/index.js +0 -1
  56. package/dist/handlers/error.handler.d.ts +0 -28
  57. package/dist/handlers/error.handler.js +0 -17
  58. package/dist/handlers/index.d.ts +0 -2
  59. package/dist/handlers/index.js +0 -2
  60. package/dist/handlers/not-found.handler.d.ts +0 -14
  61. package/dist/handlers/not-found.handler.js +0 -17
  62. package/dist/helpers/create-error-response.helper.d.ts +0 -25
  63. package/dist/helpers/create-error-response.helper.js +0 -90
  64. package/dist/helpers/create-http-method-decorator.helper.d.ts +0 -16
  65. package/dist/helpers/create-http-method-decorator.helper.js +0 -30
  66. package/dist/helpers/create-param-decorator.helper.d.ts +0 -16
  67. package/dist/helpers/create-param-decorator.helper.js +0 -60
  68. package/dist/helpers/index.d.ts +0 -3
  69. package/dist/helpers/index.js +0 -3
  70. package/dist/interfaces/application-context.interface.d.ts +0 -35
  71. package/dist/interfaces/application-context.interface.js +0 -1
  72. package/dist/interfaces/controller-options.interface.d.ts +0 -17
  73. package/dist/interfaces/controller-options.interface.js +0 -1
  74. package/dist/interfaces/di-container.interface.d.ts +0 -35
  75. package/dist/interfaces/di-container.interface.js +0 -1
  76. package/dist/interfaces/error-response.interface.d.ts +0 -13
  77. package/dist/interfaces/error-response.interface.js +0 -1
  78. package/dist/interfaces/filter.interface.d.ts +0 -20
  79. package/dist/interfaces/filter.interface.js +0 -1
  80. package/dist/interfaces/guard.interface.d.ts +0 -21
  81. package/dist/interfaces/guard.interface.js +0 -1
  82. package/dist/interfaces/handler-invocation.interface.d.ts +0 -10
  83. package/dist/interfaces/handler-invocation.interface.js +0 -1
  84. package/dist/interfaces/honest-options.interface.d.ts +0 -121
  85. package/dist/interfaces/honest-options.interface.js +0 -1
  86. package/dist/interfaces/http-method-options.interface.d.ts +0 -38
  87. package/dist/interfaces/http-method-options.interface.js +0 -1
  88. package/dist/interfaces/index.d.ts +0 -21
  89. package/dist/interfaces/index.js +0 -21
  90. package/dist/interfaces/logger.interface.d.ts +0 -23
  91. package/dist/interfaces/logger.interface.js +0 -1
  92. package/dist/interfaces/metadata-repository.interface.d.ts +0 -30
  93. package/dist/interfaces/metadata-repository.interface.js +0 -1
  94. package/dist/interfaces/middleware.interface.d.ts +0 -22
  95. package/dist/interfaces/middleware.interface.js +0 -1
  96. package/dist/interfaces/module-options.interface.d.ts +0 -18
  97. package/dist/interfaces/module-options.interface.js +0 -1
  98. package/dist/interfaces/parameter-metadata.interface.d.ts +0 -27
  99. package/dist/interfaces/parameter-metadata.interface.js +0 -1
  100. package/dist/interfaces/parameter-resolution.interface.d.ts +0 -14
  101. package/dist/interfaces/parameter-resolution.interface.js +0 -1
  102. package/dist/interfaces/pipe.interface.d.ts +0 -37
  103. package/dist/interfaces/pipe.interface.js +0 -1
  104. package/dist/interfaces/pipeline-context.interface.d.ts +0 -9
  105. package/dist/interfaces/pipeline-context.interface.js +0 -1
  106. package/dist/interfaces/plugin.interface.d.ts +0 -74
  107. package/dist/interfaces/plugin.interface.js +0 -1
  108. package/dist/interfaces/route-definition.interface.d.ts +0 -51
  109. package/dist/interfaces/route-definition.interface.js +0 -1
  110. package/dist/interfaces/route-info.interface.d.ts +0 -42
  111. package/dist/interfaces/route-info.interface.js +0 -1
  112. package/dist/interfaces/service-registry.interface.d.ts +0 -7
  113. package/dist/interfaces/service-registry.interface.js +0 -1
  114. package/dist/loggers/console.logger.d.ts +0 -7
  115. package/dist/loggers/console.logger.js +0 -21
  116. package/dist/loggers/index.d.ts +0 -2
  117. package/dist/loggers/index.js +0 -2
  118. package/dist/loggers/noop.logger.d.ts +0 -7
  119. package/dist/loggers/noop.logger.js +0 -8
  120. package/dist/managers/component.manager.d.ts +0 -48
  121. package/dist/managers/component.manager.js +0 -209
  122. package/dist/managers/handler.invoker.d.ts +0 -7
  123. package/dist/managers/handler.invoker.js +0 -37
  124. package/dist/managers/index.d.ts +0 -5
  125. package/dist/managers/index.js +0 -5
  126. package/dist/managers/parameter.resolver.d.ts +0 -13
  127. package/dist/managers/parameter.resolver.js +0 -57
  128. package/dist/managers/pipeline.executor.d.ts +0 -28
  129. package/dist/managers/pipeline.executor.js +0 -68
  130. package/dist/managers/route.manager.d.ts +0 -36
  131. package/dist/managers/route.manager.js +0 -147
  132. package/dist/registries/index.d.ts +0 -4
  133. package/dist/registries/index.js +0 -4
  134. package/dist/registries/metadata.registry.d.ts +0 -163
  135. package/dist/registries/metadata.registry.js +0 -250
  136. package/dist/registries/metadata.repository.d.ts +0 -30
  137. package/dist/registries/metadata.repository.js +0 -151
  138. package/dist/registries/route.registry.d.ts +0 -16
  139. package/dist/registries/route.registry.js +0 -46
  140. package/dist/registries/service.registry.d.ts +0 -8
  141. package/dist/registries/service.registry.js +0 -9
  142. package/dist/testing/create-controller-test-application.d.ts +0 -5
  143. package/dist/testing/create-controller-test-application.js +0 -11
  144. package/dist/testing/create-service-test-container.d.ts +0 -5
  145. package/dist/testing/create-service-test-container.js +0 -31
  146. package/dist/testing/create-test-application.d.ts +0 -5
  147. package/dist/testing/create-test-application.js +0 -20
  148. package/dist/testing/create-testing-module.d.ts +0 -6
  149. package/dist/testing/create-testing-module.js +0 -13
  150. package/dist/testing/fixtures/application-test-fixtures.d.ts +0 -17
  151. package/dist/testing/fixtures/application-test-fixtures.js +0 -230
  152. package/dist/testing/index.d.ts +0 -5
  153. package/dist/testing/index.js +0 -5
  154. package/dist/testing/testing.interface.d.ts +0 -96
  155. package/dist/testing/testing.interface.js +0 -1
  156. package/dist/types/constructor.type.d.ts +0 -12
  157. package/dist/types/constructor.type.js +0 -1
  158. package/dist/types/index.d.ts +0 -1
  159. package/dist/types/index.js +0 -1
  160. package/dist/utils/common.util.d.ts +0 -117
  161. package/dist/utils/common.util.js +0 -140
  162. package/dist/utils/index.d.ts +0 -1
  163. package/dist/utils/index.js +0 -1
package/dist/index.cjs ADDED
@@ -0,0 +1,2185 @@
1
+ 'use strict';
2
+
3
+ require('reflect-metadata');
4
+ var hono = require('hono');
5
+ var httpException = require('hono/http-exception');
6
+ var html = require('hono/html');
7
+
8
+ var __defProp = Object.defineProperty;
9
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
10
+
11
+ // src/application/startup-guide.ts
12
+ function createStartupGuideHints(errorMessage) {
13
+ const hints = /* @__PURE__ */ new Set();
14
+ hints.add("Check module wiring: root module imports, controllers, and services should be registered correctly.");
15
+ if (errorMessage.includes("not decorated with @Controller()")) {
16
+ hints.add("Add @Controller() to the class or remove it from module.controllers.");
17
+ }
18
+ if (errorMessage.includes("has no route handlers")) {
19
+ hints.add("Add at least one HTTP method decorator such as @Get() or @Post() in the controller.");
20
+ }
21
+ if (errorMessage.includes("not decorated with @Service()")) {
22
+ hints.add("Add @Service() to injectable classes used in constructor dependencies.");
23
+ }
24
+ if (errorMessage.includes("constructor metadata is missing") || errorMessage.includes("reflect-metadata")) {
25
+ hints.add("Import 'reflect-metadata' in your entry file and enable 'emitDecoratorMetadata' in tsconfig.");
26
+ }
27
+ if (errorMessage.includes("Strict mode: no routes were registered")) {
28
+ hints.add("Disable strict.requireRoutes for empty modules, or add a controller with at least one route.");
29
+ }
30
+ return [
31
+ ...hints
32
+ ];
33
+ }
34
+ __name(createStartupGuideHints, "createStartupGuideHints");
35
+ function emitStartupGuide(logger, startupGuide, error, rootModule) {
36
+ if (!startupGuide) {
37
+ return;
38
+ }
39
+ const verbose = typeof startupGuide === "object" && Boolean(startupGuide.verbose);
40
+ const errorMessage = error instanceof Error ? error.message : String(error);
41
+ const hints = createStartupGuideHints(errorMessage);
42
+ logger.emit({
43
+ level: "warn",
44
+ category: "startup",
45
+ message: "Startup guide",
46
+ details: {
47
+ rootModule: rootModule.name,
48
+ errorMessage,
49
+ hints,
50
+ verbose
51
+ }
52
+ });
53
+ if (verbose) {
54
+ logger.emit({
55
+ level: "warn",
56
+ category: "startup",
57
+ message: "Startup guide (verbose)",
58
+ details: {
59
+ steps: [
60
+ "Verify decorators are present for controllers/services used by DI and routing.",
61
+ "Ensure 'reflect-metadata' is imported once at entry and 'emitDecoratorMetadata' is enabled.",
62
+ "Enable debug.startup for extra startup diagnostics and timing details."
63
+ ]
64
+ }
65
+ });
66
+ }
67
+ }
68
+ __name(emitStartupGuide, "emitStartupGuide");
69
+
70
+ // src/utils/common.util.ts
71
+ var isUndefined = /* @__PURE__ */ __name((obj) => typeof obj === "undefined", "isUndefined");
72
+ var isNil = /* @__PURE__ */ __name((val) => val === null || typeof val === "undefined", "isNil");
73
+ var isObject = /* @__PURE__ */ __name((val) => val !== null && typeof val === "object", "isObject");
74
+ var isPlainObject = /* @__PURE__ */ __name((val) => {
75
+ if (!isObject(val)) {
76
+ return false;
77
+ }
78
+ const proto = Object.getPrototypeOf(val);
79
+ if (proto === null) {
80
+ return true;
81
+ }
82
+ const ctor = Object.prototype.hasOwnProperty.call(proto, "constructor") && proto.constructor;
83
+ return typeof ctor === "function" && ctor instanceof ctor && Function.prototype.toString.call(ctor) === Function.prototype.toString.call(Object);
84
+ }, "isPlainObject");
85
+ var isFunction = /* @__PURE__ */ __name((val) => typeof val === "function", "isFunction");
86
+ var isString = /* @__PURE__ */ __name((val) => typeof val === "string", "isString");
87
+ var isNumber = /* @__PURE__ */ __name((val) => typeof val === "number", "isNumber");
88
+ var isEmpty = /* @__PURE__ */ __name((array) => array.length === 0, "isEmpty");
89
+ var isSymbol = /* @__PURE__ */ __name((val) => typeof val === "symbol", "isSymbol");
90
+ var addLeadingSlash = /* @__PURE__ */ __name((path) => typeof path === "string" ? path.charAt(0) !== "/" ? "/" + path : path : "", "addLeadingSlash");
91
+ var normalizePath = /* @__PURE__ */ __name((path) => path ? path.startsWith("/") ? ("/" + path.replace(/\/+$/, "")).replace(/\/+/g, "/") : "/" + path.replace(/\/+$/, "") : "/", "normalizePath");
92
+ var stripEndSlash = /* @__PURE__ */ __name((path) => path.endsWith("/") ? path.slice(0, -1) : path, "stripEndSlash");
93
+ var isConstructor = /* @__PURE__ */ __name((val) => {
94
+ return isFunction(val) && !isNil(val.prototype) && !isFunction(val.prototype) && Object.getOwnPropertyNames(val.prototype).length >= 1;
95
+ }, "isConstructor");
96
+
97
+ // src/application/plugin-entries.ts
98
+ var DEFAULT_PLUGIN_NAME = "AnonymousPlugin";
99
+ function resolvePlugin(pluginType) {
100
+ if (isConstructor(pluginType)) {
101
+ return new pluginType();
102
+ }
103
+ return pluginType;
104
+ }
105
+ __name(resolvePlugin, "resolvePlugin");
106
+ function resolvePluginName(plugin, index, override) {
107
+ const resolved = override || plugin.meta?.name || plugin.constructor?.name;
108
+ if (!resolved || resolved === DEFAULT_PLUGIN_NAME) {
109
+ return `${DEFAULT_PLUGIN_NAME}#${index + 1}`;
110
+ }
111
+ return resolved;
112
+ }
113
+ __name(resolvePluginName, "resolvePluginName");
114
+ function normalizePluginEntry(entry, index) {
115
+ if (entry && typeof entry === "object" && "plugin" in entry) {
116
+ const obj = entry;
117
+ const plugin2 = resolvePlugin(obj.plugin);
118
+ const name = resolvePluginName(plugin2, index, obj.name);
119
+ return {
120
+ plugin: plugin2,
121
+ name,
122
+ preProcessors: obj.preProcessors ?? [],
123
+ postProcessors: obj.postProcessors ?? []
124
+ };
125
+ }
126
+ const plugin = resolvePlugin(entry);
127
+ return {
128
+ plugin,
129
+ name: resolvePluginName(plugin, index),
130
+ preProcessors: [],
131
+ postProcessors: []
132
+ };
133
+ }
134
+ __name(normalizePluginEntry, "normalizePluginEntry");
135
+ function normalizePluginEntries(plugins) {
136
+ return (plugins ?? []).map((entry, index) => normalizePluginEntry(entry, index));
137
+ }
138
+ __name(normalizePluginEntries, "normalizePluginEntries");
139
+
140
+ // src/application-context.ts
141
+ var ApplicationContext = class {
142
+ static {
143
+ __name(this, "ApplicationContext");
144
+ }
145
+ store = /* @__PURE__ */ new Map();
146
+ get(key) {
147
+ return this.store.get(key);
148
+ }
149
+ set(key, value) {
150
+ this.store.set(key, value);
151
+ }
152
+ has(key) {
153
+ return this.store.has(key);
154
+ }
155
+ delete(key) {
156
+ return this.store.delete(key);
157
+ }
158
+ keys() {
159
+ return this.store.keys();
160
+ }
161
+ };
162
+
163
+ // src/loggers/console.logger.ts
164
+ var ConsoleLogger = class {
165
+ static {
166
+ __name(this, "ConsoleLogger");
167
+ }
168
+ emit(event) {
169
+ const prefix = `[HonestJS:${event.category}]`;
170
+ const payload = event.details ? [
171
+ prefix,
172
+ event.message,
173
+ event.details
174
+ ] : [
175
+ prefix,
176
+ event.message
177
+ ];
178
+ switch (event.level) {
179
+ case "debug":
180
+ case "info":
181
+ console.info(...payload);
182
+ break;
183
+ case "warn":
184
+ console.warn(...payload);
185
+ break;
186
+ case "error":
187
+ console.error(...payload);
188
+ break;
189
+ }
190
+ }
191
+ };
192
+
193
+ // src/loggers/noop.logger.ts
194
+ var NoopLogger = class {
195
+ static {
196
+ __name(this, "NoopLogger");
197
+ }
198
+ emit(_event) {
199
+ }
200
+ };
201
+
202
+ // src/registries/metadata.registry.ts
203
+ var MetadataRegistry = class {
204
+ static {
205
+ __name(this, "MetadataRegistry");
206
+ }
207
+ /**
208
+ * Stores route definitions for each controller
209
+ * Maps controller classes to their route configurations
210
+ */
211
+ static routes = /* @__PURE__ */ new Map();
212
+ /**
213
+ * Stores base paths for controllers
214
+ * Maps controller classes to their route prefixes
215
+ */
216
+ static controllers = /* @__PURE__ */ new Map();
217
+ /**
218
+ * Stores configuration options for controllers
219
+ * Includes settings like versioning and prefix options
220
+ */
221
+ static controllerOptions = /* @__PURE__ */ new Map();
222
+ /**
223
+ * Registry of service classes
224
+ * Used for dependency injection and lifecycle management
225
+ */
226
+ static services = /* @__PURE__ */ new Set();
227
+ /**
228
+ * Stores configuration options for modules
229
+ * Includes imports, exports, providers, and controllers
230
+ */
231
+ static modules = /* @__PURE__ */ new Map();
232
+ /**
233
+ * Stores parameter metadata for controller methods
234
+ * Used for parameter transformation and validation
235
+ */
236
+ static parameters = /* @__PURE__ */ new Map();
237
+ /**
238
+ * Stores indices of context parameters in controller methods
239
+ * Used for optimizing context injection
240
+ */
241
+ static contextIndices = /* @__PURE__ */ new Map();
242
+ /**
243
+ * Registry for controller-level components
244
+ * Components registered here apply to all routes in a specific controller
245
+ */
246
+ static controller = /* @__PURE__ */ new Map([
247
+ [
248
+ "middleware",
249
+ /* @__PURE__ */ new Map()
250
+ ],
251
+ [
252
+ "guard",
253
+ /* @__PURE__ */ new Map()
254
+ ],
255
+ [
256
+ "pipe",
257
+ /* @__PURE__ */ new Map()
258
+ ],
259
+ [
260
+ "filter",
261
+ /* @__PURE__ */ new Map()
262
+ ]
263
+ ]);
264
+ /**
265
+ * Registry for handler-level components
266
+ * Components registered here apply to specific route handlers
267
+ * Keyed by controller constructor then handler name for collision-safe lookups
268
+ */
269
+ static handler = /* @__PURE__ */ new Map([
270
+ [
271
+ "middleware",
272
+ /* @__PURE__ */ new Map()
273
+ ],
274
+ [
275
+ "guard",
276
+ /* @__PURE__ */ new Map()
277
+ ],
278
+ [
279
+ "pipe",
280
+ /* @__PURE__ */ new Map()
281
+ ],
282
+ [
283
+ "filter",
284
+ /* @__PURE__ */ new Map()
285
+ ]
286
+ ]);
287
+ /**
288
+ * Gets all route definitions for a controller
289
+ * @param controller - The controller class to get routes for
290
+ * @returns Array of route definitions for the controller
291
+ */
292
+ static getRoutes(controller) {
293
+ return this.routes.get(controller) || [];
294
+ }
295
+ /**
296
+ * Set routes for a controller
297
+ */
298
+ static setRoutes(controller, routes) {
299
+ this.routes.set(controller, routes);
300
+ }
301
+ /**
302
+ * Add a route to a controller
303
+ */
304
+ static addRoute(controller, route) {
305
+ if (!this.routes.has(controller)) {
306
+ this.routes.set(controller, []);
307
+ }
308
+ this.routes.get(controller).push(route);
309
+ }
310
+ /**
311
+ * Get controller path
312
+ */
313
+ static getControllerPath(controller) {
314
+ return this.controllers.get(controller) || "";
315
+ }
316
+ /**
317
+ * Check if a class is registered as a controller.
318
+ */
319
+ static hasController(controller) {
320
+ return this.controllers.has(controller);
321
+ }
322
+ /**
323
+ * Set controller path
324
+ */
325
+ static setControllerPath(controller, path) {
326
+ this.controllers.set(controller, path);
327
+ }
328
+ /**
329
+ * Get controller options
330
+ */
331
+ static getControllerOptions(controller) {
332
+ return this.controllerOptions.get(controller) || {};
333
+ }
334
+ /**
335
+ * Set controller options
336
+ */
337
+ static setControllerOptions(controller, options) {
338
+ this.controllerOptions.set(controller, options);
339
+ }
340
+ /**
341
+ * Check if class is a service
342
+ */
343
+ static isService(service) {
344
+ return this.services.has(service);
345
+ }
346
+ /**
347
+ * Add a service
348
+ */
349
+ static addService(service) {
350
+ this.services.add(service);
351
+ }
352
+ /**
353
+ * Get all services
354
+ */
355
+ static getAllServices() {
356
+ return this.services;
357
+ }
358
+ /**
359
+ * Get module options
360
+ */
361
+ static getModuleOptions(module) {
362
+ return this.modules.get(module);
363
+ }
364
+ /**
365
+ * Set module options
366
+ */
367
+ static setModuleOptions(module, options) {
368
+ this.modules.set(module, options);
369
+ }
370
+ /**
371
+ * Get parameter metadata
372
+ */
373
+ static getParameters(controller) {
374
+ return this.parameters.get(controller) || /* @__PURE__ */ new Map();
375
+ }
376
+ /**
377
+ * Set parameter metadata
378
+ */
379
+ static setParameterMap(controller, params) {
380
+ this.parameters.set(controller, params);
381
+ }
382
+ /**
383
+ * Get context indices
384
+ */
385
+ static getContextIndices(controller) {
386
+ return this.contextIndices.get(controller) || /* @__PURE__ */ new Map();
387
+ }
388
+ /**
389
+ * Set context indices
390
+ */
391
+ static setContextIndices(controller, indices) {
392
+ this.contextIndices.set(controller, indices);
393
+ }
394
+ /**
395
+ * Register a component at the controller level
396
+ */
397
+ static registerController(type, controller, component) {
398
+ const typeMap = this.controller.get(type);
399
+ if (!typeMap.has(controller)) {
400
+ typeMap.set(controller, []);
401
+ }
402
+ typeMap.get(controller).push(component);
403
+ }
404
+ /**
405
+ * Get all controller-level components of a specific type for a controller
406
+ */
407
+ static getController(type, controller) {
408
+ const typeMap = this.controller.get(type);
409
+ return typeMap.get(controller) || [];
410
+ }
411
+ /**
412
+ * Register a component at the handler level
413
+ */
414
+ static registerHandler(type, controller, handlerName, component) {
415
+ const typeMap = this.handler.get(type);
416
+ if (!typeMap.has(controller)) {
417
+ typeMap.set(controller, /* @__PURE__ */ new Map());
418
+ }
419
+ const controllerMap = typeMap.get(controller);
420
+ if (!controllerMap.has(handlerName)) {
421
+ controllerMap.set(handlerName, []);
422
+ }
423
+ controllerMap.get(handlerName).push(component);
424
+ }
425
+ /**
426
+ * Get all handler-level components of a specific type for a handler
427
+ */
428
+ static getHandler(type, controller, handlerName) {
429
+ const typeMap = this.handler.get(type);
430
+ const controllerMap = typeMap.get(controller);
431
+ if (!controllerMap) {
432
+ return [];
433
+ }
434
+ return controllerMap.get(handlerName) || [];
435
+ }
436
+ /**
437
+ * Clears handler-level component registrations created via {@link registerHandler}.
438
+ * Does not remove decorator-defined routes, controllers, or modules.
439
+ */
440
+ static clearHandlerComponents() {
441
+ for (const typeMap of this.handler.values()) {
442
+ for (const controllerMap of typeMap.values()) {
443
+ controllerMap.clear();
444
+ }
445
+ typeMap.clear();
446
+ }
447
+ }
448
+ /**
449
+ * Clears all registered decorator metadata.
450
+ * Primarily used for testing. Warning: clearing after importing decorated classes
451
+ * (e.g. shared fixtures) removes their metadata until those modules are re-evaluated.
452
+ */
453
+ static clear() {
454
+ this.routes.clear();
455
+ this.controllers.clear();
456
+ this.controllerOptions.clear();
457
+ this.services.clear();
458
+ this.modules.clear();
459
+ this.parameters.clear();
460
+ this.contextIndices.clear();
461
+ for (const map of this.controller.values()) {
462
+ map.clear();
463
+ }
464
+ for (const typeMap of this.handler.values()) {
465
+ for (const controllerMap of typeMap.values()) {
466
+ controllerMap.clear();
467
+ }
468
+ typeMap.clear();
469
+ }
470
+ }
471
+ };
472
+
473
+ // src/registries/metadata.repository.ts
474
+ var MetadataRepository = class _MetadataRepository {
475
+ static {
476
+ __name(this, "MetadataRepository");
477
+ }
478
+ controllerPaths = /* @__PURE__ */ new Map();
479
+ controllerOptions = /* @__PURE__ */ new Map();
480
+ routes = /* @__PURE__ */ new Map();
481
+ parameters = /* @__PURE__ */ new Map();
482
+ contextIndices = /* @__PURE__ */ new Map();
483
+ modules = /* @__PURE__ */ new Map();
484
+ controllerComponents = /* @__PURE__ */ new Map([
485
+ [
486
+ "middleware",
487
+ /* @__PURE__ */ new Map()
488
+ ],
489
+ [
490
+ "guard",
491
+ /* @__PURE__ */ new Map()
492
+ ],
493
+ [
494
+ "pipe",
495
+ /* @__PURE__ */ new Map()
496
+ ],
497
+ [
498
+ "filter",
499
+ /* @__PURE__ */ new Map()
500
+ ]
501
+ ]);
502
+ handlerComponents = /* @__PURE__ */ new Map([
503
+ [
504
+ "middleware",
505
+ /* @__PURE__ */ new Map()
506
+ ],
507
+ [
508
+ "guard",
509
+ /* @__PURE__ */ new Map()
510
+ ],
511
+ [
512
+ "pipe",
513
+ /* @__PURE__ */ new Map()
514
+ ],
515
+ [
516
+ "filter",
517
+ /* @__PURE__ */ new Map()
518
+ ]
519
+ ]);
520
+ static fromRootModule(rootModule) {
521
+ const snapshot = new _MetadataRepository();
522
+ snapshot.captureModuleGraph(rootModule);
523
+ return snapshot;
524
+ }
525
+ hasController(controller) {
526
+ return this.controllerPaths.has(controller);
527
+ }
528
+ getControllerPath(controller) {
529
+ return this.controllerPaths.get(controller) || "";
530
+ }
531
+ getControllerOptions(controller) {
532
+ const options = this.controllerOptions.get(controller);
533
+ return options ? {
534
+ ...options
535
+ } : {};
536
+ }
537
+ getRoutes(controller) {
538
+ return (this.routes.get(controller) || []).map((route) => this.cloneRouteDefinition(route));
539
+ }
540
+ getParameters(controller) {
541
+ const parameters = this.parameters.get(controller);
542
+ if (!parameters) {
543
+ return /* @__PURE__ */ new Map();
544
+ }
545
+ const cloned = /* @__PURE__ */ new Map();
546
+ for (const [handlerName, entries] of parameters.entries()) {
547
+ cloned.set(handlerName, entries.map((entry) => ({
548
+ ...entry
549
+ })));
550
+ }
551
+ return cloned;
552
+ }
553
+ getContextIndices(controller) {
554
+ return new Map(this.contextIndices.get(controller) || /* @__PURE__ */ new Map());
555
+ }
556
+ getModuleOptions(module) {
557
+ const options = this.modules.get(module);
558
+ if (!options) {
559
+ return void 0;
560
+ }
561
+ return {
562
+ controllers: options.controllers ? [
563
+ ...options.controllers
564
+ ] : void 0,
565
+ services: options.services ? [
566
+ ...options.services
567
+ ] : void 0,
568
+ imports: options.imports ? [
569
+ ...options.imports
570
+ ] : void 0
571
+ };
572
+ }
573
+ getControllerComponents(type, controller) {
574
+ const map = this.controllerComponents.get(type);
575
+ const components = map.get(controller) || [];
576
+ return [
577
+ ...components
578
+ ];
579
+ }
580
+ getHandlerComponents(type, controller, handlerName) {
581
+ const typeMap = this.handlerComponents.get(type);
582
+ const controllerMap = typeMap.get(controller);
583
+ if (!controllerMap) {
584
+ return [];
585
+ }
586
+ const components = controllerMap.get(handlerName) || [];
587
+ return [
588
+ ...components
589
+ ];
590
+ }
591
+ captureModuleGraph(rootModule) {
592
+ const visitedModules = /* @__PURE__ */ new Set();
593
+ const controllers = /* @__PURE__ */ new Set();
594
+ const visitModule = /* @__PURE__ */ __name((moduleClass) => {
595
+ if (visitedModules.has(moduleClass)) {
596
+ return;
597
+ }
598
+ visitedModules.add(moduleClass);
599
+ const moduleOptions = MetadataRegistry.getModuleOptions(moduleClass);
600
+ if (!moduleOptions) {
601
+ return;
602
+ }
603
+ const moduleSnapshot = {
604
+ controllers: moduleOptions.controllers ? [
605
+ ...moduleOptions.controllers
606
+ ] : void 0,
607
+ services: moduleOptions.services ? [
608
+ ...moduleOptions.services
609
+ ] : void 0,
610
+ imports: moduleOptions.imports ? [
611
+ ...moduleOptions.imports
612
+ ] : void 0
613
+ };
614
+ this.modules.set(moduleClass, moduleSnapshot);
615
+ for (const controller of moduleSnapshot.controllers || []) {
616
+ controllers.add(controller);
617
+ }
618
+ for (const importedModule of moduleSnapshot.imports || []) {
619
+ visitModule(importedModule);
620
+ }
621
+ }, "visitModule");
622
+ visitModule(rootModule);
623
+ for (const controller of controllers) {
624
+ this.captureController(controller);
625
+ }
626
+ }
627
+ captureController(controller) {
628
+ if (!MetadataRegistry.hasController(controller)) {
629
+ return;
630
+ }
631
+ this.controllerPaths.set(controller, MetadataRegistry.getControllerPath(controller) || "");
632
+ this.controllerOptions.set(controller, {
633
+ ...MetadataRegistry.getControllerOptions(controller)
634
+ });
635
+ const routes = (MetadataRegistry.getRoutes(controller) || []).map((route) => this.cloneRouteDefinition(route));
636
+ this.routes.set(controller, routes);
637
+ const parameters = MetadataRegistry.getParameters(controller);
638
+ const parameterSnapshot = /* @__PURE__ */ new Map();
639
+ for (const [handlerName, entries] of parameters.entries()) {
640
+ parameterSnapshot.set(handlerName, (entries || []).map((entry) => ({
641
+ ...entry
642
+ })));
643
+ }
644
+ this.parameters.set(controller, parameterSnapshot);
645
+ this.contextIndices.set(controller, new Map(MetadataRegistry.getContextIndices(controller) || /* @__PURE__ */ new Map()));
646
+ for (const type of [
647
+ "middleware",
648
+ "guard",
649
+ "pipe",
650
+ "filter"
651
+ ]) {
652
+ const controllerMap = this.controllerComponents.get(type);
653
+ controllerMap.set(controller, [
654
+ ...MetadataRegistry.getController(type, controller) || []
655
+ ]);
656
+ }
657
+ for (const route of routes) {
658
+ for (const type of [
659
+ "middleware",
660
+ "guard",
661
+ "pipe",
662
+ "filter"
663
+ ]) {
664
+ const typeMap = this.handlerComponents.get(type);
665
+ if (!typeMap.has(controller)) {
666
+ typeMap.set(controller, /* @__PURE__ */ new Map());
667
+ }
668
+ const controllerHandlers = typeMap.get(controller);
669
+ controllerHandlers.set(route.handlerName, [
670
+ ...MetadataRegistry.getHandler(type, controller, route.handlerName)
671
+ ]);
672
+ }
673
+ }
674
+ }
675
+ cloneRouteDefinition(route) {
676
+ return {
677
+ ...route,
678
+ version: Array.isArray(route.version) ? [
679
+ ...route.version
680
+ ] : route.version
681
+ };
682
+ }
683
+ };
684
+
685
+ // src/registries/route.registry.ts
686
+ var RouteRegistry = class {
687
+ static {
688
+ __name(this, "RouteRegistry");
689
+ }
690
+ routes = [];
691
+ registerRoute(routeInfo) {
692
+ if (!routeInfo) {
693
+ throw new Error("Route info is required");
694
+ }
695
+ if (!routeInfo.controller) {
696
+ throw new Error("Route controller is required");
697
+ }
698
+ if (!routeInfo.handler) {
699
+ throw new Error("Route handler is required");
700
+ }
701
+ if (!routeInfo.method) {
702
+ throw new Error("Route method is required");
703
+ }
704
+ if (!routeInfo.fullPath) {
705
+ throw new Error("Route fullPath is required");
706
+ }
707
+ const isDuplicate = this.routes.some((route) => route.fullPath === routeInfo.fullPath && route.method.toUpperCase() === routeInfo.method.toUpperCase());
708
+ if (isDuplicate) {
709
+ throw new Error(`Duplicate route detected: ${routeInfo.method.toUpperCase()} ${routeInfo.fullPath} (${String(routeInfo.controller)}.${String(routeInfo.handler)})`);
710
+ }
711
+ this.routes.push(routeInfo);
712
+ }
713
+ getRoutes() {
714
+ return this.routes;
715
+ }
716
+ getRoutesByController(controllerName) {
717
+ return this.routes.filter((route) => route.controller === controllerName);
718
+ }
719
+ getRoutesByMethod(method) {
720
+ return this.routes.filter((route) => route.method.toUpperCase() === method.toUpperCase());
721
+ }
722
+ getRoutesByPath(pattern) {
723
+ return this.routes.filter((route) => pattern.test(route.fullPath));
724
+ }
725
+ clear() {
726
+ this.routes.length = 0;
727
+ }
728
+ };
729
+
730
+ // src/registries/service.registry.ts
731
+ var StaticServiceRegistry = class {
732
+ static {
733
+ __name(this, "StaticServiceRegistry");
734
+ }
735
+ isService(service) {
736
+ return MetadataRegistry.isService(service);
737
+ }
738
+ };
739
+
740
+ // src/di/container.ts
741
+ var Container = class {
742
+ static {
743
+ __name(this, "Container");
744
+ }
745
+ serviceRegistry;
746
+ logger;
747
+ debugDi;
748
+ constructor(serviceRegistry = new StaticServiceRegistry(), logger = new NoopLogger(), debugDi = false) {
749
+ this.serviceRegistry = serviceRegistry;
750
+ this.logger = logger;
751
+ this.debugDi = debugDi;
752
+ }
753
+ /**
754
+ * Map of class constructors to their instances
755
+ */
756
+ instances = /* @__PURE__ */ new Map();
757
+ emitLog(event) {
758
+ if (!this.debugDi) {
759
+ return;
760
+ }
761
+ this.logger.emit(event);
762
+ }
763
+ /**
764
+ * Resolves a class instance, creating it if necessary and injecting its dependencies
765
+ * @param target - The class constructor to resolve
766
+ * @returns An instance of the target class
767
+ */
768
+ resolve(target) {
769
+ return this.resolveWithTracking(target, /* @__PURE__ */ new Set());
770
+ }
771
+ /**
772
+ * Internal recursive resolver with circular dependency tracking
773
+ */
774
+ resolveWithTracking(target, resolving) {
775
+ if (this.instances.has(target)) {
776
+ this.emitLog({
777
+ level: "debug",
778
+ category: "di",
779
+ message: `Resolved ${target.name} from DI cache`
780
+ });
781
+ return this.instances.get(target);
782
+ }
783
+ if (resolving.has(target)) {
784
+ const cycle = [
785
+ ...resolving.keys(),
786
+ target
787
+ ].map((t) => t.name).join(" -> ");
788
+ this.emitLog({
789
+ level: "error",
790
+ category: "di",
791
+ message: `Circular dependency detected while resolving ${target.name}`,
792
+ details: {
793
+ cycle
794
+ }
795
+ });
796
+ throw new Error(`Circular dependency detected: ${cycle}`);
797
+ }
798
+ resolving.add(target);
799
+ this.emitLog({
800
+ level: "debug",
801
+ category: "di",
802
+ message: `Resolving ${target.name}`,
803
+ details: {
804
+ resolving: [
805
+ ...resolving
806
+ ].map((constructor) => constructor.name)
807
+ }
808
+ });
809
+ const paramTypes = Reflect.getMetadata("design:paramtypes", target) || [];
810
+ if (target.length > 0 && paramTypes.length === 0) {
811
+ if (!this.serviceRegistry.isService(target)) {
812
+ this.emitLog({
813
+ level: "error",
814
+ category: "di",
815
+ message: `Cannot resolve ${target.name}: missing @Service() decorator`
816
+ });
817
+ throw new Error(`Cannot resolve ${target.name}: it is not decorated with @Service(). Did you forget to add @Service() to the class?`);
818
+ }
819
+ this.emitLog({
820
+ level: "error",
821
+ category: "di",
822
+ message: `Cannot resolve ${target.name}: missing constructor metadata`
823
+ });
824
+ throw new Error(`Cannot resolve dependencies for ${target.name}: constructor metadata is missing. Ensure 'reflect-metadata' is imported and 'emitDecoratorMetadata' is enabled.`);
825
+ }
826
+ const dependencies = paramTypes.map((paramType, index) => {
827
+ if (!paramType || paramType === Object || paramType === Array || paramType === Function) {
828
+ this.emitLog({
829
+ level: "error",
830
+ category: "di",
831
+ message: `Cannot resolve dependency at index ${index} of ${target.name}`
832
+ });
833
+ throw new Error(`Cannot resolve dependency at index ${index} of ${target.name}. Use concrete class types for constructor dependencies.`);
834
+ }
835
+ return this.resolveWithTracking(paramType, new Set(resolving));
836
+ });
837
+ const instance = new target(...dependencies);
838
+ this.instances.set(target, instance);
839
+ this.emitLog({
840
+ level: "debug",
841
+ category: "di",
842
+ message: `Created ${target.name} instance`,
843
+ details: {
844
+ dependencyCount: dependencies.length
845
+ }
846
+ });
847
+ return instance;
848
+ }
849
+ /**
850
+ * Registers a pre-created instance for a class
851
+ * @param target - The class constructor to register
852
+ * @param instance - The instance to register
853
+ */
854
+ register(target, instance) {
855
+ this.instances.set(target, instance);
856
+ }
857
+ has(target) {
858
+ return this.instances.has(target);
859
+ }
860
+ clear() {
861
+ this.instances.clear();
862
+ }
863
+ };
864
+
865
+ // src/errors/framework.error.ts
866
+ var FrameworkError = class extends Error {
867
+ static {
868
+ __name(this, "FrameworkError");
869
+ }
870
+ status;
871
+ code;
872
+ category;
873
+ remediation;
874
+ details;
875
+ constructor(message, options) {
876
+ super(message);
877
+ this.name = "FrameworkError";
878
+ this.status = options.status;
879
+ this.code = options.code;
880
+ this.category = options.category;
881
+ this.remediation = options.remediation;
882
+ this.details = options.details;
883
+ if (options.cause !== void 0) {
884
+ this.cause = options.cause;
885
+ }
886
+ }
887
+ };
888
+
889
+ // src/helpers/create-error-response.helper.ts
890
+ function createErrorResponse(exception, context, options) {
891
+ const normalizedException = exception instanceof Error ? exception : new Error(String(exception));
892
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
893
+ const requestId = context.get("requestId");
894
+ const path = context.req.path;
895
+ if (normalizedException instanceof httpException.HTTPException) {
896
+ const response2 = {
897
+ status: options?.status || normalizedException.status,
898
+ message: options?.title || normalizedException.message,
899
+ timestamp,
900
+ path,
901
+ requestId,
902
+ code: options?.code,
903
+ details: options?.additionalDetails,
904
+ ...options?.detail && {
905
+ detail: options.detail
906
+ }
907
+ };
908
+ return {
909
+ response: response2,
910
+ status: options?.status || normalizedException.status
911
+ };
912
+ }
913
+ if (normalizedException instanceof FrameworkError) {
914
+ const status2 = options?.status || normalizedException.status || 500;
915
+ const response2 = {
916
+ status: status2,
917
+ message: options?.title || normalizedException.message,
918
+ timestamp,
919
+ path,
920
+ requestId,
921
+ code: options?.code || normalizedException.code,
922
+ details: {
923
+ category: normalizedException.category,
924
+ remediation: normalizedException.remediation,
925
+ ...normalizedException.details,
926
+ ...options?.additionalDetails
927
+ },
928
+ ...options?.detail && {
929
+ detail: options.detail
930
+ }
931
+ };
932
+ return {
933
+ response: response2,
934
+ status: status2
935
+ };
936
+ }
937
+ if (normalizedException.statusCode || normalizedException.status) {
938
+ const defaultStatus = normalizedException.statusCode || normalizedException.status || 500;
939
+ const status2 = options?.status || defaultStatus;
940
+ const response2 = {
941
+ status: status2,
942
+ message: options?.title || normalizedException.message,
943
+ timestamp,
944
+ path,
945
+ requestId,
946
+ code: options?.code || normalizedException.name,
947
+ details: options?.additionalDetails,
948
+ ...options?.detail && {
949
+ detail: options.detail
950
+ }
951
+ };
952
+ return {
953
+ response: response2,
954
+ status: status2
955
+ };
956
+ }
957
+ const status = options?.status || 500;
958
+ const response = {
959
+ status,
960
+ message: options?.title || (process.env.NODE_ENV === "production" ? "Internal Server Error" : normalizedException.message),
961
+ timestamp,
962
+ path,
963
+ requestId,
964
+ code: options?.code || normalizedException.name,
965
+ details: options?.additionalDetails || (process.env.NODE_ENV === "development" ? {
966
+ stack: normalizedException.stack
967
+ } : void 0),
968
+ ...options?.detail && {
969
+ detail: options.detail
970
+ }
971
+ };
972
+ return {
973
+ response,
974
+ status
975
+ };
976
+ }
977
+ __name(createErrorResponse, "createErrorResponse");
978
+
979
+ // src/helpers/create-http-method-decorator.helper.ts
980
+ function createHttpMethodDecorator(method) {
981
+ return (path = "", options = {}) => {
982
+ return (target, propertyKey, descriptor) => {
983
+ const controllerClass = target.constructor;
984
+ MetadataRegistry.addRoute(controllerClass, {
985
+ path,
986
+ method,
987
+ handlerName: propertyKey,
988
+ version: options.version,
989
+ prefix: options.prefix
990
+ });
991
+ };
992
+ };
993
+ }
994
+ __name(createHttpMethodDecorator, "createHttpMethodDecorator");
995
+
996
+ // src/helpers/create-param-decorator.helper.ts
997
+ function createParamDecorator(type, factory) {
998
+ const fallbackFactory = /* @__PURE__ */ __name((data, ctx) => {
999
+ if (data === void 0) {
1000
+ return ctx;
1001
+ }
1002
+ return ctx.get(String(data));
1003
+ }, "fallbackFactory");
1004
+ return (data) => {
1005
+ return (target, propertyKey, parameterIndex) => {
1006
+ const controllerClass = target.constructor;
1007
+ if (!MetadataRegistry.getParameters(controllerClass).size) {
1008
+ MetadataRegistry.setParameterMap(controllerClass, /* @__PURE__ */ new Map());
1009
+ }
1010
+ const parametersMap = MetadataRegistry.getParameters(controllerClass);
1011
+ if (!parametersMap.has(propertyKey)) {
1012
+ parametersMap.set(propertyKey, []);
1013
+ }
1014
+ const paramTypes = Reflect.getMetadata("design:paramtypes", target, propertyKey);
1015
+ const metatype = paramTypes?.[parameterIndex];
1016
+ const parameters = parametersMap.get(propertyKey);
1017
+ parameters.push({
1018
+ index: parameterIndex,
1019
+ name: type,
1020
+ data,
1021
+ factory: factory || fallbackFactory,
1022
+ metatype
1023
+ });
1024
+ if (type === "context") {
1025
+ if (!MetadataRegistry.getContextIndices(controllerClass).size) {
1026
+ MetadataRegistry.setContextIndices(controllerClass, /* @__PURE__ */ new Map());
1027
+ }
1028
+ const contextIndices = MetadataRegistry.getContextIndices(controllerClass);
1029
+ contextIndices.set(propertyKey, parameterIndex);
1030
+ }
1031
+ };
1032
+ };
1033
+ }
1034
+ __name(createParamDecorator, "createParamDecorator");
1035
+
1036
+ // src/handlers/error.handler.ts
1037
+ var ErrorHandler = class {
1038
+ static {
1039
+ __name(this, "ErrorHandler");
1040
+ }
1041
+ /**
1042
+ * Creates a middleware function that handles error responses
1043
+ * @returns A middleware function that formats and returns error responses using createErrorResponse
1044
+ */
1045
+ static handle() {
1046
+ return async (err, c) => {
1047
+ const { response, status } = createErrorResponse(err, c);
1048
+ return c.json(response, status);
1049
+ };
1050
+ }
1051
+ };
1052
+
1053
+ // src/handlers/not-found.handler.ts
1054
+ var NotFoundHandler = class {
1055
+ static {
1056
+ __name(this, "NotFoundHandler");
1057
+ }
1058
+ /**
1059
+ * Creates a middleware function that handles 404 Not Found responses
1060
+ * @returns A middleware function that returns a JSON response with a 404 status
1061
+ */
1062
+ static handle() {
1063
+ return async (c) => {
1064
+ return c.json({
1065
+ message: `Not Found - ${c.req.path}`
1066
+ }, 404);
1067
+ };
1068
+ }
1069
+ };
1070
+
1071
+ // src/constants/version.constants.ts
1072
+ var VERSION_NEUTRAL = /* @__PURE__ */ Symbol("VERSION_NEUTRAL");
1073
+
1074
+ // src/constants/pipeline.constants.ts
1075
+ var HONEST_PIPELINE_CONTROLLER_KEY = "__honest_controllerClass";
1076
+ var HONEST_PIPELINE_HANDLER_KEY = "__honest_handlerName";
1077
+ var HONEST_PIPELINE_BODY_CACHE_KEY = "__honest.body.cache";
1078
+
1079
+ // src/managers/component.manager.ts
1080
+ var ComponentManager = class {
1081
+ static {
1082
+ __name(this, "ComponentManager");
1083
+ }
1084
+ container;
1085
+ metadataRepository;
1086
+ logger;
1087
+ globalComponents = /* @__PURE__ */ new Map([
1088
+ [
1089
+ "middleware",
1090
+ /* @__PURE__ */ new Set()
1091
+ ],
1092
+ [
1093
+ "guard",
1094
+ /* @__PURE__ */ new Set()
1095
+ ],
1096
+ [
1097
+ "pipe",
1098
+ /* @__PURE__ */ new Set()
1099
+ ],
1100
+ [
1101
+ "filter",
1102
+ /* @__PURE__ */ new Set()
1103
+ ]
1104
+ ]);
1105
+ constructor(container, metadataRepository, logger = new NoopLogger()) {
1106
+ this.container = container;
1107
+ this.metadataRepository = metadataRepository;
1108
+ this.logger = logger;
1109
+ }
1110
+ /**
1111
+ * Configures global components from application options.
1112
+ */
1113
+ setupGlobalComponents(options) {
1114
+ const components = options.components || {};
1115
+ if (components.middleware) {
1116
+ this.registerGlobal("middleware", ...components.middleware);
1117
+ }
1118
+ if (components.guards) {
1119
+ this.registerGlobal("guard", ...components.guards);
1120
+ }
1121
+ if (components.pipes) {
1122
+ this.registerGlobal("pipe", ...components.pipes);
1123
+ }
1124
+ if (components.filters) {
1125
+ this.registerGlobal("filter", ...components.filters);
1126
+ }
1127
+ }
1128
+ registerGlobal(type, ...components) {
1129
+ components.forEach((component) => {
1130
+ this.globalComponents.get(type).add(component);
1131
+ });
1132
+ }
1133
+ getGlobal(type) {
1134
+ return this.globalComponents.get(type);
1135
+ }
1136
+ /**
1137
+ * Gets all components of a specific type for a handler.
1138
+ * Merges: instance global → static controller → static handler.
1139
+ */
1140
+ getComponents(type, controller, handlerName) {
1141
+ const handlerComponents = this.metadataRepository.getHandlerComponents(type, controller, handlerName);
1142
+ const controllerComponents = this.metadataRepository.getControllerComponents(type, controller);
1143
+ const globalComponents = Array.from(this.globalComponents.get(type) || []);
1144
+ return [
1145
+ ...globalComponents,
1146
+ ...controllerComponents,
1147
+ ...handlerComponents
1148
+ ];
1149
+ }
1150
+ // -- Middleware --
1151
+ resolveMiddleware(middlewareItems) {
1152
+ return middlewareItems.map((middlewareItem) => {
1153
+ if (isObject(middlewareItem) && "use" in middlewareItem) {
1154
+ return middlewareItem.use.bind(middlewareItem);
1155
+ }
1156
+ const middleware = this.container.resolve(middlewareItem);
1157
+ return middleware.use.bind(middleware);
1158
+ });
1159
+ }
1160
+ getHandlerMiddleware(controller, handlerName) {
1161
+ const controllerMiddleware = this.metadataRepository.getControllerComponents("middleware", controller);
1162
+ const handlerMiddleware = this.metadataRepository.getHandlerComponents("middleware", controller, handlerName);
1163
+ return this.resolveMiddleware([
1164
+ ...controllerMiddleware,
1165
+ ...handlerMiddleware
1166
+ ]);
1167
+ }
1168
+ getGlobalMiddleware() {
1169
+ const globalMiddleware = Array.from(this.globalComponents.get("middleware") || []);
1170
+ return this.resolveMiddleware(globalMiddleware);
1171
+ }
1172
+ // -- Guards --
1173
+ resolveGuards(guardItems) {
1174
+ return guardItems.map((guardItem) => {
1175
+ if (isObject(guardItem) && "canActivate" in guardItem) {
1176
+ return guardItem;
1177
+ }
1178
+ return this.container.resolve(guardItem);
1179
+ });
1180
+ }
1181
+ getHandlerGuards(controller, handlerName) {
1182
+ const guardItems = this.getComponents("guard", controller, handlerName);
1183
+ return this.resolveGuards(guardItems);
1184
+ }
1185
+ // -- Pipes --
1186
+ resolvePipes(pipeItems) {
1187
+ return pipeItems.map((pipeItem) => {
1188
+ if (isObject(pipeItem) && "transform" in pipeItem) {
1189
+ return pipeItem;
1190
+ }
1191
+ return this.container.resolve(pipeItem);
1192
+ });
1193
+ }
1194
+ getHandlerPipes(controller, handlerName) {
1195
+ const pipeItems = this.getComponents("pipe", controller, handlerName);
1196
+ return this.resolvePipes(pipeItems);
1197
+ }
1198
+ async executePipes(value, metadata, pipes) {
1199
+ let transformedValue = value;
1200
+ for (const pipe of pipes) {
1201
+ transformedValue = await pipe.transform(transformedValue, metadata);
1202
+ }
1203
+ return transformedValue;
1204
+ }
1205
+ // -- Filters --
1206
+ async handleException(exception, context) {
1207
+ const normalizedException = exception instanceof Error ? exception : new Error(String(exception));
1208
+ const controller = context.get(HONEST_PIPELINE_CONTROLLER_KEY);
1209
+ const handlerName = context.get(HONEST_PIPELINE_HANDLER_KEY);
1210
+ if (controller && handlerName) {
1211
+ const handlerFilters = this.metadataRepository.getHandlerComponents("filter", controller, handlerName);
1212
+ if (handlerFilters.length > 0) {
1213
+ const response2 = await this.executeFilters(handlerFilters, normalizedException, context);
1214
+ if (response2) return response2;
1215
+ }
1216
+ }
1217
+ if (controller) {
1218
+ const controllerFilters = this.metadataRepository.getControllerComponents("filter", controller);
1219
+ if (controllerFilters.length > 0) {
1220
+ const response2 = await this.executeFilters(controllerFilters, normalizedException, context);
1221
+ if (response2) return response2;
1222
+ }
1223
+ }
1224
+ const globalFilters = Array.from(this.globalComponents.get("filter") || []);
1225
+ if (globalFilters.length > 0) {
1226
+ const response2 = await this.executeFilters(globalFilters, normalizedException, context);
1227
+ if (response2) return response2;
1228
+ }
1229
+ const { response, status } = createErrorResponse(normalizedException, context);
1230
+ return context.json(response, status);
1231
+ }
1232
+ async executeFilters(filterItems, exception, context) {
1233
+ for (const filterItem of filterItems) {
1234
+ let filter;
1235
+ if (isObject(filterItem) && "catch" in filterItem) {
1236
+ filter = filterItem;
1237
+ } else {
1238
+ filter = this.container.resolve(filterItem);
1239
+ }
1240
+ try {
1241
+ const result = await filter.catch(exception, context);
1242
+ if (result !== void 0) {
1243
+ return result;
1244
+ }
1245
+ } catch (filterError) {
1246
+ const filterName = filter.constructor?.name || "UnknownFilter";
1247
+ this.logger.emit({
1248
+ level: "error",
1249
+ category: "errors",
1250
+ message: `Error in exception filter ${filterName}`,
1251
+ details: {
1252
+ error: filterError instanceof Error ? filterError.message : String(filterError)
1253
+ }
1254
+ });
1255
+ const { response, status } = createErrorResponse(filterError, context);
1256
+ return context.json(response, status);
1257
+ }
1258
+ }
1259
+ return void 0;
1260
+ }
1261
+ // -- Module registration --
1262
+ async registerModule(moduleClass, registered = /* @__PURE__ */ new Set()) {
1263
+ if (registered.has(moduleClass)) {
1264
+ return [];
1265
+ }
1266
+ registered.add(moduleClass);
1267
+ const moduleOptions = this.metadataRepository.getModuleOptions(moduleClass);
1268
+ if (!moduleOptions) {
1269
+ this.logger.emit({
1270
+ level: "error",
1271
+ category: "startup",
1272
+ message: `Module ${moduleClass.name} is not properly decorated with @Module()`
1273
+ });
1274
+ throw new Error(`Module ${moduleClass.name} is not properly decorated with @Module()`);
1275
+ }
1276
+ const controllers = [];
1277
+ if (moduleOptions.imports && moduleOptions.imports.length > 0) {
1278
+ for (const importedModule of moduleOptions.imports) {
1279
+ const importedControllers = await this.registerModule(importedModule, registered);
1280
+ controllers.push(...importedControllers);
1281
+ }
1282
+ }
1283
+ if (moduleOptions.services && moduleOptions.services.length > 0) {
1284
+ for (const serviceClass of moduleOptions.services) {
1285
+ this.container.resolve(serviceClass);
1286
+ }
1287
+ }
1288
+ if (moduleOptions.controllers && moduleOptions.controllers.length > 0) {
1289
+ controllers.push(...moduleOptions.controllers);
1290
+ }
1291
+ return controllers;
1292
+ }
1293
+ };
1294
+
1295
+ // src/managers/handler.invoker.ts
1296
+ var HandlerInvoker = class {
1297
+ static {
1298
+ __name(this, "HandlerInvoker");
1299
+ }
1300
+ async invoke({ handler, args, context, contextIndex }) {
1301
+ const result = await handler(...args);
1302
+ if (contextIndex !== void 0) {
1303
+ return result;
1304
+ }
1305
+ if (result instanceof Response) {
1306
+ return result;
1307
+ }
1308
+ if (isNil(result)) {
1309
+ return context.json(null);
1310
+ }
1311
+ if (isString(result)) {
1312
+ return context.text(result);
1313
+ }
1314
+ try {
1315
+ return context.json(result);
1316
+ } catch (error) {
1317
+ throw new FrameworkError("Handler return value could not be serialized as JSON.", {
1318
+ status: 500,
1319
+ code: "RESPONSE_SERIALIZATION_FAILED",
1320
+ category: "pipeline",
1321
+ remediation: "Return JSON-serializable values from handlers or map custom values in a filter before returning.",
1322
+ details: {
1323
+ handlerResultType: typeof result
1324
+ },
1325
+ cause: error
1326
+ });
1327
+ }
1328
+ }
1329
+ };
1330
+
1331
+ // src/managers/parameter.resolver.ts
1332
+ var ParameterResolver = class {
1333
+ static {
1334
+ __name(this, "ParameterResolver");
1335
+ }
1336
+ componentManager;
1337
+ logger;
1338
+ debugPipeline;
1339
+ constructor(componentManager, logger = new NoopLogger(), debugPipeline = false) {
1340
+ this.componentManager = componentManager;
1341
+ this.logger = logger;
1342
+ this.debugPipeline = debugPipeline;
1343
+ }
1344
+ async resolveArguments(input) {
1345
+ const { controllerName, handlerName, handlerArity, handlerParams, handlerPipes, context } = input;
1346
+ const maxDecoratorIndex = handlerParams.length > 0 ? Math.max(...handlerParams.map((parameter) => parameter.index)) : -1;
1347
+ const args = new Array(Math.max(handlerArity, maxDecoratorIndex + 1));
1348
+ const decoratedIndices = new Set(handlerParams.map((parameter) => parameter.index));
1349
+ if (this.debugPipeline && maxDecoratorIndex >= 0) {
1350
+ const sparseIndices = [];
1351
+ for (let i = 0; i <= maxDecoratorIndex; i++) {
1352
+ if (!decoratedIndices.has(i)) {
1353
+ sparseIndices.push(i);
1354
+ }
1355
+ }
1356
+ const hasOutOfRangeDecoratorIndex = maxDecoratorIndex >= handlerArity;
1357
+ if (sparseIndices.length > 0 || hasOutOfRangeDecoratorIndex) {
1358
+ this.logger.emit({
1359
+ level: "warn",
1360
+ category: "pipeline",
1361
+ message: `Potential parameter binding mismatch at ${controllerName}.${String(handlerName)}`,
1362
+ details: {
1363
+ handlerArity,
1364
+ maxDecoratorIndex,
1365
+ sparseIndices,
1366
+ handlerParamCount: handlerParams.length
1367
+ }
1368
+ });
1369
+ }
1370
+ }
1371
+ for (const parameter of handlerParams) {
1372
+ if (typeof parameter.factory !== "function") {
1373
+ throw new Error(`Invalid parameter decorator metadata for ${controllerName}.${String(handlerName)}`);
1374
+ }
1375
+ const rawValue = await parameter.factory(parameter.data, context);
1376
+ const transformedValue = await this.componentManager.executePipes(rawValue, {
1377
+ type: parameter.name,
1378
+ metatype: parameter.metatype,
1379
+ data: typeof parameter.data === "string" || typeof parameter.data === "undefined" ? parameter.data : String(parameter.data)
1380
+ }, handlerPipes);
1381
+ args[parameter.index] = transformedValue;
1382
+ }
1383
+ return args;
1384
+ }
1385
+ };
1386
+ var PipelineExecutor = class {
1387
+ static {
1388
+ __name(this, "PipelineExecutor");
1389
+ }
1390
+ componentManager;
1391
+ parameterResolver;
1392
+ handlerInvoker;
1393
+ logger;
1394
+ debugPipeline;
1395
+ constructor(componentManager, parameterResolver, handlerInvoker, logger = new NoopLogger(), debugPipeline = false) {
1396
+ this.componentManager = componentManager;
1397
+ this.parameterResolver = parameterResolver;
1398
+ this.handlerInvoker = handlerInvoker;
1399
+ this.logger = logger;
1400
+ this.debugPipeline = debugPipeline;
1401
+ }
1402
+ async execute(input) {
1403
+ const { controllerClass, handlerName, handler, handlerParams, handlerPipes, contextIndex, context } = input;
1404
+ context.set(HONEST_PIPELINE_CONTROLLER_KEY, controllerClass);
1405
+ context.set(HONEST_PIPELINE_HANDLER_KEY, String(handlerName));
1406
+ const guards = this.componentManager.getHandlerGuards(controllerClass, handlerName);
1407
+ for (const guard of guards) {
1408
+ const canActivate = await guard.canActivate(context);
1409
+ if (!canActivate) {
1410
+ if (this.debugPipeline) {
1411
+ this.logger.emit({
1412
+ level: "warn",
1413
+ category: "pipeline",
1414
+ message: `Guard rejected request at ${controllerClass.name}.${String(handlerName)}`,
1415
+ details: {
1416
+ guard: guard.constructor?.name || "UnknownGuard"
1417
+ }
1418
+ });
1419
+ }
1420
+ throw new httpException.HTTPException(403, {
1421
+ message: `Forbidden by ${guard.constructor?.name || "UnknownGuard"} at ${controllerClass.name}.${String(handlerName)}`
1422
+ });
1423
+ }
1424
+ }
1425
+ const args = await this.parameterResolver.resolveArguments({
1426
+ controllerName: controllerClass.name,
1427
+ handlerName,
1428
+ handlerArity: handler.length,
1429
+ handlerParams,
1430
+ handlerPipes,
1431
+ context
1432
+ });
1433
+ if (this.debugPipeline) {
1434
+ this.logger.emit({
1435
+ level: "debug",
1436
+ category: "pipeline",
1437
+ message: `Resolved handler arguments for ${controllerClass.name}.${String(handlerName)}`,
1438
+ details: {
1439
+ guardCount: guards.length,
1440
+ parameterCount: handlerParams.length,
1441
+ pipeCount: handlerPipes.length
1442
+ }
1443
+ });
1444
+ }
1445
+ return this.handlerInvoker.invoke({
1446
+ handler,
1447
+ args,
1448
+ context,
1449
+ contextIndex
1450
+ });
1451
+ }
1452
+ };
1453
+
1454
+ // src/managers/route.manager.ts
1455
+ var RouteManager = class {
1456
+ static {
1457
+ __name(this, "RouteManager");
1458
+ }
1459
+ hono;
1460
+ container;
1461
+ routeRegistry;
1462
+ componentManager;
1463
+ parameterResolver;
1464
+ pipelineExecutor;
1465
+ metadataRepository;
1466
+ logger;
1467
+ globalPrefix;
1468
+ globalVersion;
1469
+ constructor(hono, container, routeRegistry, componentManager, metadataRepository, logger = new NoopLogger(), options = {}) {
1470
+ this.hono = hono;
1471
+ this.container = container;
1472
+ this.routeRegistry = routeRegistry;
1473
+ this.componentManager = componentManager;
1474
+ this.logger = logger;
1475
+ this.parameterResolver = new ParameterResolver(this.componentManager, this.logger, Boolean(options.debugPipeline));
1476
+ this.pipelineExecutor = new PipelineExecutor(this.componentManager, this.parameterResolver, new HandlerInvoker(), this.logger, Boolean(options.debugPipeline));
1477
+ this.metadataRepository = metadataRepository;
1478
+ this.globalPrefix = options.prefix !== void 0 ? this.normalizePath(options.prefix) : void 0;
1479
+ this.globalVersion = options.version;
1480
+ this.applyGlobalMiddleware();
1481
+ }
1482
+ applyGlobalMiddleware() {
1483
+ const globalMiddleware = this.componentManager.getGlobalMiddleware();
1484
+ for (const middleware of globalMiddleware) {
1485
+ this.hono.use("*", middleware);
1486
+ }
1487
+ }
1488
+ normalizePath(path) {
1489
+ if (!isString(path)) {
1490
+ throw new Error(`Invalid path: expected a string but received ${typeof path}. Check your @Controller() and route decorator arguments.`);
1491
+ }
1492
+ return normalizePath(path);
1493
+ }
1494
+ registerRouteHandler(method, path, handlerMiddleware, wrapperHandler) {
1495
+ if (handlerMiddleware.length > 0) {
1496
+ this.hono.on(method.toUpperCase(), [
1497
+ path
1498
+ ], ...handlerMiddleware, wrapperHandler);
1499
+ } else {
1500
+ this.hono.on(method.toUpperCase(), [
1501
+ path
1502
+ ], wrapperHandler);
1503
+ }
1504
+ }
1505
+ buildRoutePath(prefix, version, controllerPath, methodPath) {
1506
+ return normalizePath(`${prefix}${version}${controllerPath}${methodPath}`);
1507
+ }
1508
+ formatVersionSegment(version) {
1509
+ if (isNil(version)) {
1510
+ return "";
1511
+ }
1512
+ return version === VERSION_NEUTRAL ? "" : `/v${String(version)}`;
1513
+ }
1514
+ async registerController(controllerClass) {
1515
+ if (!this.metadataRepository.hasController(controllerClass)) {
1516
+ throw new Error(`Controller ${controllerClass.name} is not decorated with @Controller()`);
1517
+ }
1518
+ const controllerPath = this.metadataRepository.getControllerPath(controllerClass) || "";
1519
+ const controllerOptions = this.metadataRepository.getControllerOptions(controllerClass) || {};
1520
+ const routes = this.metadataRepository.getRoutes(controllerClass) || [];
1521
+ const parameterMetadata = this.metadataRepository.getParameters(controllerClass) || /* @__PURE__ */ new Map();
1522
+ const contextIndices = this.metadataRepository.getContextIndices(controllerClass) || /* @__PURE__ */ new Map();
1523
+ const controllerSegment = this.normalizePath(controllerPath);
1524
+ const controllerInstance = this.container.resolve(controllerClass);
1525
+ const effectiveControllerPrefix = controllerOptions.prefix !== void 0 ? controllerOptions.prefix : this.globalPrefix;
1526
+ const effectiveControllerVersion = controllerOptions.version !== void 0 ? controllerOptions.version : this.globalVersion;
1527
+ if (routes.length === 0) {
1528
+ throw new Error(`Controller ${controllerClass.name} has no route handlers. Add HTTP method decorators like @Get()`);
1529
+ }
1530
+ for (const route of routes) {
1531
+ const { path, method, version: routeVersion, prefix: routePrefix } = route;
1532
+ const effectivePrefix = routePrefix !== void 0 ? routePrefix : effectiveControllerPrefix;
1533
+ const prefixSegment = !isNil(effectivePrefix) ? this.normalizePath(effectivePrefix) : "";
1534
+ const effectiveVersion = routeVersion !== void 0 ? routeVersion : effectiveControllerVersion;
1535
+ const methodSegment = this.normalizePath(path);
1536
+ if (isNil(effectiveVersion)) {
1537
+ this.registerRoute(controllerInstance, route, parameterMetadata, contextIndices, controllerClass, prefixSegment, "", controllerSegment, methodSegment, method);
1538
+ continue;
1539
+ }
1540
+ if (effectiveVersion === VERSION_NEUTRAL) {
1541
+ this.registerRoute(controllerInstance, route, parameterMetadata, contextIndices, controllerClass, prefixSegment, "", controllerSegment, methodSegment, method);
1542
+ this.registerRoute(controllerInstance, route, parameterMetadata, contextIndices, controllerClass, prefixSegment, "/:version{v[0-9]+}", controllerSegment, methodSegment, method);
1543
+ continue;
1544
+ }
1545
+ if (Array.isArray(effectiveVersion)) {
1546
+ for (const version of effectiveVersion) {
1547
+ const versionSegment2 = this.formatVersionSegment(version);
1548
+ this.registerRoute(controllerInstance, route, parameterMetadata, contextIndices, controllerClass, prefixSegment, versionSegment2, controllerSegment, methodSegment, method);
1549
+ }
1550
+ continue;
1551
+ }
1552
+ const versionSegment = this.formatVersionSegment(effectiveVersion);
1553
+ this.registerRoute(controllerInstance, route, parameterMetadata, contextIndices, controllerClass, prefixSegment, versionSegment, controllerSegment, methodSegment, method);
1554
+ }
1555
+ }
1556
+ registerRoute(controllerInstance, route, parameterMetadata, contextIndices, controllerClass, prefixSegment, versionSegment, controllerSegment, methodSegment, method) {
1557
+ const { handlerName } = route;
1558
+ const fullPath = this.buildRoutePath(prefixSegment, versionSegment, controllerSegment, methodSegment);
1559
+ const handler = controllerInstance[handlerName].bind(controllerInstance);
1560
+ const handlerParams = parameterMetadata.get(handlerName) || [];
1561
+ const contextIndex = contextIndices.get(handlerName);
1562
+ const handlerMiddleware = this.componentManager.getHandlerMiddleware(controllerClass, handlerName);
1563
+ const handlerPipes = this.componentManager.getHandlerPipes(controllerClass, handlerName);
1564
+ this.routeRegistry.registerRoute({
1565
+ controller: controllerClass.name,
1566
+ handler: handlerName,
1567
+ method,
1568
+ prefix: prefixSegment,
1569
+ version: versionSegment,
1570
+ route: controllerSegment,
1571
+ path: methodSegment,
1572
+ fullPath,
1573
+ parameters: handlerParams
1574
+ });
1575
+ const componentManager = this.componentManager;
1576
+ const pipelineExecutor = this.pipelineExecutor;
1577
+ const wrapperHandler = /* @__PURE__ */ __name(async (c) => {
1578
+ try {
1579
+ return await pipelineExecutor.execute({
1580
+ controllerClass,
1581
+ handlerName,
1582
+ handler,
1583
+ handlerParams,
1584
+ handlerPipes,
1585
+ contextIndex,
1586
+ context: c
1587
+ });
1588
+ } catch (error) {
1589
+ return componentManager.handleException(error, c);
1590
+ }
1591
+ }, "wrapperHandler");
1592
+ this.registerRouteHandler(method, fullPath, handlerMiddleware, wrapperHandler);
1593
+ }
1594
+ };
1595
+
1596
+ // src/application.ts
1597
+ var Application = class _Application {
1598
+ static {
1599
+ __name(this, "Application");
1600
+ }
1601
+ hono;
1602
+ container;
1603
+ context;
1604
+ routeRegistry;
1605
+ metadataRepository;
1606
+ componentManager;
1607
+ routeManager;
1608
+ logger;
1609
+ options;
1610
+ constructor(options = {}, metadataRepository) {
1611
+ this.options = isObject(options) ? options : {};
1612
+ const debugPipeline = this.options.debug === true || typeof this.options.debug === "object" && Boolean(this.options.debug.pipeline);
1613
+ const debugDi = this.options.debug === true || typeof this.options.debug === "object" && Boolean(this.options.debug.di);
1614
+ this.hono = new hono.Hono(this.options.hono);
1615
+ this.logger = this.options.logger || new ConsoleLogger();
1616
+ this.container = this.options.container || new Container(void 0, this.logger, debugDi);
1617
+ this.context = new ApplicationContext();
1618
+ this.routeRegistry = new RouteRegistry();
1619
+ this.metadataRepository = metadataRepository;
1620
+ this.componentManager = new ComponentManager(this.container, this.metadataRepository, this.logger);
1621
+ this.componentManager.setupGlobalComponents(this.options);
1622
+ this.setupErrorHandlers();
1623
+ this.routeManager = new RouteManager(this.hono, this.container, this.routeRegistry, this.componentManager, this.metadataRepository, this.logger, {
1624
+ prefix: this.options.routing?.prefix,
1625
+ version: this.options.routing?.version,
1626
+ debugPipeline
1627
+ });
1628
+ if (this.options.deprecations?.printPreV1Warning) {
1629
+ this.logger.emit({
1630
+ level: "warn",
1631
+ category: "deprecations",
1632
+ message: "Pre-v1 warning: APIs may change before 1.0.0."
1633
+ });
1634
+ }
1635
+ }
1636
+ setupErrorHandlers() {
1637
+ this.hono.notFound(this.options.notFound || NotFoundHandler.handle());
1638
+ this.hono.onError(this.options.onError || ErrorHandler.handle());
1639
+ }
1640
+ shouldEmitRouteDiagnostics() {
1641
+ const debug = this.options.debug;
1642
+ return debug === true || typeof debug === "object" && Boolean(debug.routes);
1643
+ }
1644
+ emitStartupGuide(error, rootModule) {
1645
+ emitStartupGuide(this.logger, this.options.startupGuide, error, rootModule);
1646
+ }
1647
+ async register(moduleClass) {
1648
+ const controllers = await this.componentManager.registerModule(moduleClass);
1649
+ const debugRoutes = this.shouldEmitRouteDiagnostics();
1650
+ for (const controller of controllers) {
1651
+ const controllerStartedAt = Date.now();
1652
+ const routeCountBefore = this.routeRegistry.getRoutes().length;
1653
+ try {
1654
+ await this.routeManager.registerController(controller);
1655
+ if (debugRoutes) {
1656
+ this.logger.emit({
1657
+ level: "info",
1658
+ category: "routes",
1659
+ message: "Registered controller routes",
1660
+ details: {
1661
+ controller: controller.name,
1662
+ routeCountAdded: this.routeRegistry.getRoutes().length - routeCountBefore,
1663
+ registrationDurationMs: Date.now() - controllerStartedAt
1664
+ }
1665
+ });
1666
+ }
1667
+ } catch (error) {
1668
+ if (debugRoutes) {
1669
+ this.logger.emit({
1670
+ level: "error",
1671
+ category: "routes",
1672
+ message: "Failed to register controller routes",
1673
+ details: {
1674
+ controller: controller.name,
1675
+ registrationDurationMs: Date.now() - controllerStartedAt,
1676
+ errorMessage: error instanceof Error ? error.message : String(error)
1677
+ }
1678
+ });
1679
+ }
1680
+ throw error;
1681
+ }
1682
+ }
1683
+ return this;
1684
+ }
1685
+ static async create(rootModule, options = {}) {
1686
+ const startupStartedAt = Date.now();
1687
+ const metadataSnapshot = MetadataRepository.fromRootModule(rootModule);
1688
+ const app = new _Application(options, metadataSnapshot);
1689
+ const entries = normalizePluginEntries(options.plugins);
1690
+ const ctx = app.getContext();
1691
+ const debug = options.debug;
1692
+ const debugPlugins = debug === true || typeof debug === "object" && debug.plugins;
1693
+ const debugRoutes = debug === true || typeof debug === "object" && debug.routes;
1694
+ const debugStartup = debug === true || typeof debug === "object" && (debug.startup || debugRoutes);
1695
+ let strictNoRoutesFailureEmitted = false;
1696
+ try {
1697
+ if (debugPlugins && entries.length > 0) {
1698
+ app.logger.emit({
1699
+ level: "info",
1700
+ category: "plugins",
1701
+ message: `Plugin order: ${entries.map(({ name }) => name).join(" -> ")}`
1702
+ });
1703
+ }
1704
+ for (const { plugin, preProcessors } of entries) {
1705
+ plugin.logger = app.logger;
1706
+ for (const fn of preProcessors) {
1707
+ await fn(app, app.hono, ctx);
1708
+ }
1709
+ if (plugin.beforeModulesRegistered) {
1710
+ await plugin.beforeModulesRegistered(app, app.hono);
1711
+ }
1712
+ }
1713
+ await app.register(rootModule);
1714
+ const routes = app.getRoutes();
1715
+ if (debugStartup) {
1716
+ app.logger.emit({
1717
+ level: "info",
1718
+ category: "startup",
1719
+ message: `Application registered ${routes.length} route(s)`,
1720
+ details: {
1721
+ routeCount: routes.length,
1722
+ rootModule: rootModule.name
1723
+ }
1724
+ });
1725
+ }
1726
+ if (options.strict?.requireRoutes && routes.length === 0) {
1727
+ strictNoRoutesFailureEmitted = true;
1728
+ app.logger.emit({
1729
+ level: "error",
1730
+ category: "startup",
1731
+ message: "Strict mode failed: no routes were registered",
1732
+ details: {
1733
+ rootModule: rootModule.name,
1734
+ requireRoutes: true,
1735
+ startupDurationMs: Date.now() - startupStartedAt
1736
+ }
1737
+ });
1738
+ const strictError = new Error("Strict mode: no routes were registered. Check your module/controller decorators.");
1739
+ app.emitStartupGuide(strictError, rootModule);
1740
+ throw strictError;
1741
+ }
1742
+ if (debugRoutes) {
1743
+ app.logger.emit({
1744
+ level: "info",
1745
+ category: "routes",
1746
+ message: "Registered routes",
1747
+ details: {
1748
+ routes: routes.map((route) => `${route.method.toUpperCase()} ${route.fullPath}`)
1749
+ }
1750
+ });
1751
+ }
1752
+ for (const { plugin, postProcessors } of entries) {
1753
+ if (plugin.afterModulesRegistered) {
1754
+ await plugin.afterModulesRegistered(app, app.hono);
1755
+ }
1756
+ for (const fn of postProcessors) {
1757
+ await fn(app, app.hono, ctx);
1758
+ }
1759
+ }
1760
+ if (debugStartup) {
1761
+ app.logger.emit({
1762
+ level: "info",
1763
+ category: "startup",
1764
+ message: "Application startup completed",
1765
+ details: {
1766
+ rootModule: rootModule.name,
1767
+ pluginCount: entries.length,
1768
+ routeCount: routes.length,
1769
+ startupDurationMs: Date.now() - startupStartedAt
1770
+ }
1771
+ });
1772
+ }
1773
+ return {
1774
+ app,
1775
+ hono: app.getApp()
1776
+ };
1777
+ } catch (error) {
1778
+ app.emitStartupGuide(error, rootModule);
1779
+ if (debugStartup && !strictNoRoutesFailureEmitted) {
1780
+ app.logger.emit({
1781
+ level: "error",
1782
+ category: "startup",
1783
+ message: "Application startup failed",
1784
+ details: {
1785
+ rootModule: rootModule.name,
1786
+ startupDurationMs: Date.now() - startupStartedAt,
1787
+ errorMessage: error instanceof Error ? error.message : String(error)
1788
+ }
1789
+ });
1790
+ }
1791
+ throw error;
1792
+ }
1793
+ }
1794
+ getApp() {
1795
+ return this.hono;
1796
+ }
1797
+ getContainer() {
1798
+ return this.container;
1799
+ }
1800
+ getContext() {
1801
+ return this.context;
1802
+ }
1803
+ getRoutes() {
1804
+ return this.routeRegistry.getRoutes();
1805
+ }
1806
+ };
1807
+ var defaultSiteData = {
1808
+ type: "website",
1809
+ locale: "en_US"
1810
+ };
1811
+ var attrsToString = /* @__PURE__ */ __name((attrs) => {
1812
+ if (!attrs) {
1813
+ return "";
1814
+ }
1815
+ return Object.entries(attrs).map(([key, value]) => {
1816
+ if (typeof value === "boolean") {
1817
+ return value ? key : "";
1818
+ }
1819
+ const escapedValue = String(value).replace(/"/g, "&quot;");
1820
+ return `${key}="${escapedValue}"`;
1821
+ }).filter(Boolean).join(" ");
1822
+ }, "attrsToString");
1823
+ var Layout = /* @__PURE__ */ __name((props) => {
1824
+ const data = {
1825
+ ...defaultSiteData,
1826
+ ...props
1827
+ };
1828
+ return html.html`
1829
+ <!DOCTYPE html>
1830
+ <html lang="${data.locale?.split("_")[0] || "en"}" ${html.raw(attrsToString(data.htmlAttributes))}>
1831
+ <head ${html.raw(attrsToString(data.headAttributes))}>
1832
+ <meta charset="UTF-8" />
1833
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
1834
+ ${data.csp ? html.html`<meta http-equiv="Content-Security-Policy" content="${data.csp}" />` : ""}
1835
+ <title>${data.title}</title>
1836
+ ${data.description ? html.html`<meta name="description" content="${data.description}" />` : ""}
1837
+
1838
+ <!-- Open Graph / Facebook -->
1839
+ <meta prefix="og: http://ogp.me/ns#" />
1840
+ <meta property="og:title" content="${data.title}" />
1841
+ ${data.description ? html.html`<meta property="og:description" content="${data.description}" />` : ""}
1842
+ ${data.image ? html.html`<meta property="og:image" content="${data.image}" />` : ""}
1843
+ ${data.url ? html.html`<meta property="og:url" content="${data.url}" />` : ""}
1844
+ ${data.locale ? html.html`<meta property="og:locale" content="${data.locale}" />` : ""}
1845
+ ${data.type ? html.html`<meta property="og:type" content="${data.type}" />` : ""}
1846
+ ${data.siteName ? html.html`<meta property="og:site_name" content="${data.siteName}" />` : ""}
1847
+
1848
+ <!-- Twitter -->
1849
+ <meta
1850
+ name="twitter:card"
1851
+ content="${data.twitterCard || (data.image ? "summary_large_image" : "summary")}"
1852
+ />
1853
+ <meta name="twitter:title" content="${data.title}" />
1854
+ ${data.description ? html.html`<meta name="twitter:description" content="${data.description}" />` : ""}
1855
+ ${data.image ? html.html`<meta name="twitter:image" content="${data.image}" />` : ""}
1856
+
1857
+ <!-- Custom Meta Tags -->
1858
+ ${data.customMeta ? data.customMeta.map((meta) => {
1859
+ const nameAttr = meta.name ? `name="${meta.name}"` : "";
1860
+ const propertyAttr = meta.property ? `property="${meta.property}"` : "";
1861
+ return html.html`<meta ${nameAttr} ${propertyAttr} content="${meta.content}" />`;
1862
+ }) : ""}
1863
+
1864
+ <!-- Favicon -->
1865
+ ${data.favicon ? html.html`<link rel="icon" href="${data.favicon}" />` : ""}
1866
+
1867
+ <!-- Stylesheets -->
1868
+ ${data.stylesheets ? data.stylesheets.map((href) => html.html`<link rel="stylesheet" href="${href}" />`) : ""}
1869
+
1870
+ <!-- Scripts -->
1871
+ ${data.scripts ? data.scripts.map((script) => {
1872
+ if (typeof script === "string") {
1873
+ return html.html`<script src="${script}"></script>`;
1874
+ }
1875
+ const { src, async, defer } = script;
1876
+ if (async && defer) {
1877
+ return html.html`<script src="${src}" async defer></script>`;
1878
+ }
1879
+ if (async) {
1880
+ return html.html`<script src="${src}" async></script>`;
1881
+ }
1882
+ if (defer) {
1883
+ return html.html`<script src="${src}" defer></script>`;
1884
+ }
1885
+ return html.html`<script src="${src}"></script>`;
1886
+ }) : ""}
1887
+ </head>
1888
+ <body ${html.raw(attrsToString(data.bodyAttributes))}>
1889
+ ${data.children}
1890
+ </body>
1891
+ </html>
1892
+ `;
1893
+ }, "Layout");
1894
+
1895
+ // src/decorators/controller.decorator.ts
1896
+ function Controller(route = "", options = {}) {
1897
+ return (target) => {
1898
+ MetadataRegistry.setControllerPath(target, route);
1899
+ MetadataRegistry.setControllerOptions(target, options);
1900
+ };
1901
+ }
1902
+ __name(Controller, "Controller");
1903
+
1904
+ // src/decorators/http-method.decorator.ts
1905
+ var Get = createHttpMethodDecorator("get");
1906
+ var Post = createHttpMethodDecorator("post");
1907
+ var Put = createHttpMethodDecorator("put");
1908
+ var Delete = createHttpMethodDecorator("delete");
1909
+ var Patch = createHttpMethodDecorator("patch");
1910
+ var Options = createHttpMethodDecorator("options");
1911
+ var All = createHttpMethodDecorator("all");
1912
+
1913
+ // src/decorators/module.decorator.ts
1914
+ function Module(options = {}) {
1915
+ return (target) => {
1916
+ MetadataRegistry.setModuleOptions(target, options);
1917
+ };
1918
+ }
1919
+ __name(Module, "Module");
1920
+
1921
+ // src/decorators/mvc.decorator.ts
1922
+ function View(route = "", options = {
1923
+ prefix: null,
1924
+ version: null
1925
+ }) {
1926
+ return Controller(route, options);
1927
+ }
1928
+ __name(View, "View");
1929
+ var Page = Get;
1930
+ function MvcModule(options = {}) {
1931
+ return Module({
1932
+ imports: options.imports,
1933
+ services: options.services,
1934
+ controllers: (options.views || []).concat(options.controllers || [])
1935
+ });
1936
+ }
1937
+ __name(MvcModule, "MvcModule");
1938
+
1939
+ // src/decorators/parameter.decorator.ts
1940
+ var Body = createParamDecorator("body", async (data, ctx) => {
1941
+ let body = ctx.get(HONEST_PIPELINE_BODY_CACHE_KEY);
1942
+ if (body === void 0) {
1943
+ body = await ctx.req.json();
1944
+ ctx.set(HONEST_PIPELINE_BODY_CACHE_KEY, body);
1945
+ }
1946
+ if (data && body && typeof body === "object") {
1947
+ return body[String(data)];
1948
+ }
1949
+ return body;
1950
+ });
1951
+ var Param = createParamDecorator("param", (data, ctx) => {
1952
+ return data ? ctx.req.param(String(data)) : ctx.req.param();
1953
+ });
1954
+ var Query = createParamDecorator("query", (data, ctx) => {
1955
+ return data ? ctx.req.query(String(data)) : ctx.req.query();
1956
+ });
1957
+ var Header = createParamDecorator("header", (data, ctx) => {
1958
+ return data ? ctx.req.header(String(data)) : ctx.req.header();
1959
+ });
1960
+ var Req = createParamDecorator("request", (_, ctx) => ctx.req);
1961
+ var Request = createParamDecorator("request", (_, ctx) => ctx.req);
1962
+ var Res = createParamDecorator("response", (_, ctx) => ctx.res);
1963
+ var Response2 = createParamDecorator("response", (_, ctx) => ctx.res);
1964
+ var Ctx = createParamDecorator("context", (_, ctx) => ctx);
1965
+ var Context = createParamDecorator("context", (_, ctx) => ctx);
1966
+ var Var = createParamDecorator("variable", (data, ctx) => data === void 0 ? void 0 : ctx.get(String(data)));
1967
+ var Variable = createParamDecorator("variable", (data, ctx) => data === void 0 ? void 0 : ctx.get(String(data)));
1968
+
1969
+ // src/decorators/service.decorator.ts
1970
+ function Service() {
1971
+ return (target) => {
1972
+ MetadataRegistry.addService(target);
1973
+ };
1974
+ }
1975
+ __name(Service, "Service");
1976
+
1977
+ // src/decorators/use-component.decorator.ts
1978
+ function UseComponent(type, ...components) {
1979
+ return (target, propertyKey) => {
1980
+ if (propertyKey) {
1981
+ const controllerClass = target.constructor;
1982
+ components.forEach((component) => MetadataRegistry.registerHandler(type, controllerClass, propertyKey, component));
1983
+ } else {
1984
+ components.forEach((component) => MetadataRegistry.registerController(type, target, component));
1985
+ }
1986
+ };
1987
+ }
1988
+ __name(UseComponent, "UseComponent");
1989
+
1990
+ // src/decorators/use-filters.decorator.ts
1991
+ function UseFilters(...filters) {
1992
+ return (target, propertyKey) => {
1993
+ if (propertyKey) {
1994
+ const controllerClass = target.constructor;
1995
+ filters.forEach((filter) => MetadataRegistry.registerHandler("filter", controllerClass, propertyKey, filter));
1996
+ } else {
1997
+ filters.forEach((filter) => MetadataRegistry.registerController("filter", target, filter));
1998
+ }
1999
+ };
2000
+ }
2001
+ __name(UseFilters, "UseFilters");
2002
+
2003
+ // src/decorators/use-guards.decorator.ts
2004
+ function UseGuards(...guards) {
2005
+ return (target, propertyKey) => {
2006
+ if (propertyKey) {
2007
+ const controllerClass = target.constructor;
2008
+ guards.forEach((guard) => MetadataRegistry.registerHandler("guard", controllerClass, propertyKey, guard));
2009
+ } else {
2010
+ guards.forEach((guard) => MetadataRegistry.registerController("guard", target, guard));
2011
+ }
2012
+ };
2013
+ }
2014
+ __name(UseGuards, "UseGuards");
2015
+
2016
+ // src/decorators/use-middleware.decorator.ts
2017
+ function UseMiddleware(...middleware) {
2018
+ return (target, propertyKey) => {
2019
+ if (propertyKey) {
2020
+ const controllerClass = target.constructor;
2021
+ middleware.forEach((mw) => MetadataRegistry.registerHandler("middleware", controllerClass, propertyKey, mw));
2022
+ } else {
2023
+ middleware.forEach((mw) => MetadataRegistry.registerController("middleware", target, mw));
2024
+ }
2025
+ };
2026
+ }
2027
+ __name(UseMiddleware, "UseMiddleware");
2028
+
2029
+ // src/decorators/use-pipes.decorator.ts
2030
+ function UsePipes(...pipes) {
2031
+ return (target, propertyKey) => {
2032
+ if (propertyKey) {
2033
+ const controllerClass = target.constructor;
2034
+ pipes.forEach((pipe) => MetadataRegistry.registerHandler("pipe", controllerClass, propertyKey, pipe));
2035
+ } else {
2036
+ pipes.forEach((pipe) => MetadataRegistry.registerController("pipe", target, pipe));
2037
+ }
2038
+ };
2039
+ }
2040
+ __name(UsePipes, "UsePipes");
2041
+
2042
+ // src/testing/create-testing-module.ts
2043
+ function createTestingModule(options = {}) {
2044
+ const { controllers, services, imports, name = "TestModule" } = options;
2045
+ const dynamicModule = {
2046
+ [name]: class {
2047
+ }
2048
+ }[name];
2049
+ Module({
2050
+ controllers,
2051
+ services,
2052
+ imports
2053
+ })(dynamicModule);
2054
+ return dynamicModule;
2055
+ }
2056
+ __name(createTestingModule, "createTestingModule");
2057
+
2058
+ // src/testing/create-test-application.ts
2059
+ async function createTestApplication(options = {}) {
2060
+ const { module, appOptions, ...moduleOptions } = options;
2061
+ const rootModule = module ?? createTestingModule(moduleOptions);
2062
+ const { app, hono } = await Application.create(rootModule, appOptions);
2063
+ const request = /* @__PURE__ */ __name((input, init) => {
2064
+ if (typeof input === "string") {
2065
+ const normalizedInput = input.startsWith("http://") || input.startsWith("https://") ? input : `http://localhost${input.startsWith("/") ? input : `/${input}`}`;
2066
+ return Promise.resolve(hono.request(normalizedInput, init));
2067
+ }
2068
+ return Promise.resolve(hono.request(input));
2069
+ }, "request");
2070
+ return {
2071
+ app,
2072
+ hono,
2073
+ request
2074
+ };
2075
+ }
2076
+ __name(createTestApplication, "createTestApplication");
2077
+
2078
+ // src/testing/create-controller-test-application.ts
2079
+ async function createControllerTestApplication(options) {
2080
+ const { controller, ...rest } = options;
2081
+ return createTestApplication({
2082
+ ...rest,
2083
+ controllers: [
2084
+ controller
2085
+ ]
2086
+ });
2087
+ }
2088
+ __name(createControllerTestApplication, "createControllerTestApplication");
2089
+
2090
+ // src/testing/create-service-test-container.ts
2091
+ function createServiceTestContainer(options = {}) {
2092
+ const logger = options.logger ?? new NoopLogger();
2093
+ const container = new Container(void 0, logger, Boolean(options.debugDi));
2094
+ for (const override of options.overrides ?? []) {
2095
+ const typedOverride = override;
2096
+ container.register(typedOverride.provide, typedOverride.useValue);
2097
+ }
2098
+ for (const service of options.preload ?? []) {
2099
+ container.resolve(service);
2100
+ }
2101
+ return {
2102
+ container,
2103
+ get(target) {
2104
+ return container.resolve(target);
2105
+ },
2106
+ register(target, instance) {
2107
+ container.register(target, instance);
2108
+ },
2109
+ has(target) {
2110
+ return container.has(target);
2111
+ },
2112
+ clear() {
2113
+ container.clear();
2114
+ }
2115
+ };
2116
+ }
2117
+ __name(createServiceTestContainer, "createServiceTestContainer");
2118
+
2119
+ exports.All = All;
2120
+ exports.Application = Application;
2121
+ exports.ApplicationContext = ApplicationContext;
2122
+ exports.Body = Body;
2123
+ exports.ConsoleLogger = ConsoleLogger;
2124
+ exports.Container = Container;
2125
+ exports.Context = Context;
2126
+ exports.Controller = Controller;
2127
+ exports.Ctx = Ctx;
2128
+ exports.Delete = Delete;
2129
+ exports.ErrorHandler = ErrorHandler;
2130
+ exports.FrameworkError = FrameworkError;
2131
+ exports.Get = Get;
2132
+ exports.HONEST_PIPELINE_BODY_CACHE_KEY = HONEST_PIPELINE_BODY_CACHE_KEY;
2133
+ exports.HONEST_PIPELINE_CONTROLLER_KEY = HONEST_PIPELINE_CONTROLLER_KEY;
2134
+ exports.HONEST_PIPELINE_HANDLER_KEY = HONEST_PIPELINE_HANDLER_KEY;
2135
+ exports.Header = Header;
2136
+ exports.Layout = Layout;
2137
+ exports.MetadataRegistry = MetadataRegistry;
2138
+ exports.MetadataRepository = MetadataRepository;
2139
+ exports.Module = Module;
2140
+ exports.MvcModule = MvcModule;
2141
+ exports.NoopLogger = NoopLogger;
2142
+ exports.NotFoundHandler = NotFoundHandler;
2143
+ exports.Options = Options;
2144
+ exports.Page = Page;
2145
+ exports.Param = Param;
2146
+ exports.Patch = Patch;
2147
+ exports.Post = Post;
2148
+ exports.Put = Put;
2149
+ exports.Query = Query;
2150
+ exports.Req = Req;
2151
+ exports.Request = Request;
2152
+ exports.Res = Res;
2153
+ exports.Response = Response2;
2154
+ exports.RouteRegistry = RouteRegistry;
2155
+ exports.Service = Service;
2156
+ exports.StaticServiceRegistry = StaticServiceRegistry;
2157
+ exports.UseComponent = UseComponent;
2158
+ exports.UseFilters = UseFilters;
2159
+ exports.UseGuards = UseGuards;
2160
+ exports.UseMiddleware = UseMiddleware;
2161
+ exports.UsePipes = UsePipes;
2162
+ exports.VERSION_NEUTRAL = VERSION_NEUTRAL;
2163
+ exports.Var = Var;
2164
+ exports.Variable = Variable;
2165
+ exports.View = View;
2166
+ exports.addLeadingSlash = addLeadingSlash;
2167
+ exports.createControllerTestApplication = createControllerTestApplication;
2168
+ exports.createErrorResponse = createErrorResponse;
2169
+ exports.createHttpMethodDecorator = createHttpMethodDecorator;
2170
+ exports.createParamDecorator = createParamDecorator;
2171
+ exports.createServiceTestContainer = createServiceTestContainer;
2172
+ exports.createTestApplication = createTestApplication;
2173
+ exports.createTestingModule = createTestingModule;
2174
+ exports.isConstructor = isConstructor;
2175
+ exports.isEmpty = isEmpty;
2176
+ exports.isFunction = isFunction;
2177
+ exports.isNil = isNil;
2178
+ exports.isNumber = isNumber;
2179
+ exports.isObject = isObject;
2180
+ exports.isPlainObject = isPlainObject;
2181
+ exports.isString = isString;
2182
+ exports.isSymbol = isSymbol;
2183
+ exports.isUndefined = isUndefined;
2184
+ exports.normalizePath = normalizePath;
2185
+ exports.stripEndSlash = stripEndSlash;