node-honest 0.0.7 → 0.1.1

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