@hono-di/core 0.0.9 → 0.0.15

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.
package/dist/index.cjs CHANGED
@@ -407,14 +407,13 @@ var Container = class {
407
407
  };
408
408
 
409
409
  // src/injector/context-id.ts
410
- var ContextId = class _ContextId {
410
+ var ContextId = class {
411
411
  static {
412
412
  __name(this, "ContextId");
413
413
  }
414
- static idCounter = 0;
415
414
  id;
416
415
  constructor() {
417
- this.id = _ContextId.idCounter++;
416
+ this.id = crypto.randomUUID();
418
417
  }
419
418
  };
420
419
  new ContextId();
@@ -459,6 +458,13 @@ var ModuleRefImpl = class extends ModuleRef {
459
458
  }
460
459
  return this.injector.loadInstance(wrapper, contextId || new ContextId());
461
460
  }
461
+ async create(type, contextId) {
462
+ const instance = await this.injector.resolveConstructorParams({
463
+ metatype: type
464
+ }, this.moduleRef, Reflect.getMetadata("design:paramtypes", type) || [], () => {
465
+ }, contextId || new ContextId());
466
+ return new type(...instance);
467
+ }
462
468
  };
463
469
 
464
470
  // src/injector/injector.ts
@@ -471,8 +477,12 @@ var Injector = class {
471
477
  this.container = container;
472
478
  }
473
479
  async resolveConstructorParams(wrapper, module, inject, callback, contextId = new ContextId(), inquire = [], parentInquire = []) {
474
- if (inquire.some((item) => item === wrapper) && wrapper.scope === Scope.DEFAULT) {
475
- throw new Error(`Circular dependency detected: ${wrapper.name}`);
480
+ if (inquire.some((item) => item === wrapper)) {
481
+ const chain = [
482
+ ...inquire,
483
+ wrapper
484
+ ].map((w) => w.name || "Unknown").join(" -> ");
485
+ throw new Error(`Circular dependency detected: ${chain}`);
476
486
  }
477
487
  const args = [];
478
488
  for (const [index, token] of inject.entries()) {
@@ -513,13 +523,13 @@ var Injector = class {
513
523
  return this.loadInstance(wrapper, contextId, inquire);
514
524
  }
515
525
  lookupProvider(token, module) {
516
- if (module.hasProvider(token)) {
517
- return module.getProvider(token);
518
- }
526
+ let wrapper = module.getProvider(token);
527
+ if (wrapper) return wrapper;
519
528
  for (const importedModule of module.imports) {
520
529
  if (importedModule.exports.has(token)) {
521
- if (importedModule.hasProvider(token)) {
522
- return importedModule.getProvider(token);
530
+ wrapper = importedModule.getProvider(token);
531
+ if (wrapper) {
532
+ return wrapper;
523
533
  }
524
534
  const nestedWrapper = this.lookupProvider(token, importedModule);
525
535
  if (nestedWrapper) return nestedWrapper;
@@ -529,8 +539,9 @@ var Injector = class {
529
539
  for (const globalModule of this.container.getGlobalModules()) {
530
540
  if (globalModule === module) continue;
531
541
  if (globalModule.exports.has(token)) {
532
- if (globalModule.hasProvider(token)) {
533
- return globalModule.getProvider(token);
542
+ wrapper = globalModule.getProvider(token);
543
+ if (wrapper) {
544
+ return wrapper;
534
545
  }
535
546
  const nestedWrapper = this.lookupProvider(token, globalModule);
536
547
  if (nestedWrapper) return nestedWrapper;
@@ -585,7 +596,15 @@ var Injector = class {
585
596
  }, contextId, inquire);
586
597
  const instance = new metatype(...constructorArgs);
587
598
  if (wrapper.properties) {
599
+ const UNSAFE_KEYS = [
600
+ "__proto__",
601
+ "constructor",
602
+ "prototype"
603
+ ];
588
604
  for (const prop of wrapper.properties) {
605
+ if (typeof prop.key === "string" && UNSAFE_KEYS.includes(prop.key)) {
606
+ throw new Error(`Unsafe property injection detected: ${prop.key}`);
607
+ }
589
608
  const propInstance = await this.resolveSingleParam(prop.token, wrapper.host, contextId, inquire, prop.isOptional);
590
609
  if (propInstance !== void 0) {
591
610
  instance[prop.key] = propInstance;
@@ -637,6 +656,7 @@ var InstanceWrapper = class {
637
656
  this.useExisting = metadata.useExisting;
638
657
  this.isAlias = !!metadata.useExisting;
639
658
  this.isOptional = metadata.isOptional;
659
+ this.properties = metadata.properties;
640
660
  this.id = Math.random().toString(36).substring(7);
641
661
  }
642
662
  getInstanceByContextId(contextId) {
@@ -661,6 +681,13 @@ var InstanceWrapper = class {
661
681
  }
662
682
  this.inject[index] = token;
663
683
  }
684
+ cleanup(contextId) {
685
+ if (contextId) {
686
+ this.instancesPerContext.delete(contextId);
687
+ } else {
688
+ this.instancesPerContext.clear();
689
+ }
690
+ }
664
691
  };
665
692
 
666
693
  // src/services/logger.service.ts
@@ -714,7 +741,14 @@ var Logger = class _Logger {
714
741
  const timestamp = date.toLocaleString();
715
742
  const pid = process.pid;
716
743
  const contextMessage = context ? `[${context}] ` : "";
717
- const output = message instanceof Object ? JSON.stringify(message, null, 2) : message;
744
+ let output;
745
+ if (typeof message === "symbol") {
746
+ output = message.toString();
747
+ } else if (message instanceof Object) {
748
+ output = JSON.stringify(message, null, 2);
749
+ } else {
750
+ output = String(message);
751
+ }
718
752
  const currentTimestamp = Date.now();
719
753
  const timeDiff = _Logger.updateAndGetTimestampDiff(currentTimestamp);
720
754
  const C = {
@@ -761,15 +795,15 @@ var Logger = class _Logger {
761
795
  };
762
796
 
763
797
  // src/scanner.ts
764
- var HonoDiScanner = class {
798
+ var Scanner = class {
765
799
  static {
766
- __name(this, "HonoDiScanner");
800
+ __name(this, "Scanner");
767
801
  }
768
802
  container;
769
803
  constructor(container) {
770
804
  this.container = container;
771
805
  }
772
- logger = new Logger("HonoDiScanner");
806
+ logger = new Logger("Scanner");
773
807
  async scan(module) {
774
808
  await this.scanModule(module);
775
809
  }
@@ -858,12 +892,13 @@ var HonoDiScanner = class {
858
892
  const isPlainObject = provider && typeof provider === "object" && "provide" in provider;
859
893
  if (!isPlainObject) {
860
894
  const token2 = provider;
895
+ const providerScope = Reflect.getMetadata(METADATA_KEYS.SCOPE, provider) ?? Scope.DEFAULT;
861
896
  const wrapper2 = new InstanceWrapper({
862
897
  token: token2,
863
898
  name: token2.name,
864
899
  metatype: provider,
865
900
  host: moduleRef,
866
- scope: Scope.DEFAULT
901
+ scope: providerScope
867
902
  });
868
903
  this.scanDependencies(wrapper2);
869
904
  moduleRef.addProvider(wrapper2);
@@ -892,12 +927,13 @@ var HonoDiScanner = class {
892
927
  }
893
928
  insertController(controller, moduleRef) {
894
929
  const token = controller;
930
+ const controllerScope = Reflect.getMetadata(METADATA_KEYS.SCOPE, controller) ?? Scope.DEFAULT;
895
931
  const wrapper = new InstanceWrapper({
896
932
  token,
897
933
  name: token.name,
898
934
  metatype: controller,
899
935
  host: moduleRef,
900
- scope: Scope.DEFAULT
936
+ scope: controllerScope
901
937
  });
902
938
  this.scanDependencies(wrapper);
903
939
  moduleRef.addController(wrapper);
@@ -1011,6 +1047,172 @@ var MiddlewareConfigProxyImpl = class MiddlewareConfigProxyImpl2 {
1011
1047
  }
1012
1048
  };
1013
1049
 
1050
+ // src/application/context-manager.ts
1051
+ var ContextManager = class {
1052
+ static {
1053
+ __name(this, "ContextManager");
1054
+ }
1055
+ activeContexts = /* @__PURE__ */ new Set();
1056
+ /**
1057
+ * Registers a new context as active
1058
+ */
1059
+ addContext(contextId) {
1060
+ this.activeContexts.add(contextId);
1061
+ }
1062
+ /**
1063
+ * Removes a context and allows cleanup
1064
+ */
1065
+ removeContext(contextId) {
1066
+ this.activeContexts.delete(contextId);
1067
+ }
1068
+ /**
1069
+ * Gets all currently active contexts
1070
+ */
1071
+ getActiveContexts() {
1072
+ return this.activeContexts;
1073
+ }
1074
+ /**
1075
+ * Clears all tracked contexts
1076
+ */
1077
+ clearAll() {
1078
+ this.activeContexts.clear();
1079
+ }
1080
+ };
1081
+
1082
+ // src/application/lifecycle-manager.ts
1083
+ var LifecycleManager = class {
1084
+ static {
1085
+ __name(this, "LifecycleManager");
1086
+ }
1087
+ logger = new Logger("LifecycleManager");
1088
+ /**
1089
+ * Calls a lifecycle hook on all providers/controllers in all modules
1090
+ *
1091
+ * @param hookName - Name of the lifecycle method to call
1092
+ * @param container - DI container with all modules
1093
+ */
1094
+ async callHook(hookName, container) {
1095
+ const modules = container.getModules();
1096
+ for (const module of modules.values()) {
1097
+ for (const wrapper of module.providers.values()) {
1098
+ const instance = wrapper.instance;
1099
+ if (instance && typeof instance[hookName] === "function") {
1100
+ await instance[hookName]();
1101
+ }
1102
+ }
1103
+ for (const wrapper of module.controllers.values()) {
1104
+ const instance = wrapper.instance;
1105
+ if (instance && typeof instance[hookName] === "function") {
1106
+ await instance[hookName]();
1107
+ }
1108
+ }
1109
+ }
1110
+ }
1111
+ /**
1112
+ * Calls OnModuleInit on all modules
1113
+ */
1114
+ async onModuleInit(container) {
1115
+ this.logger.log("Calling OnModuleInit...");
1116
+ await this.callHook("onModuleInit", container);
1117
+ }
1118
+ /**
1119
+ * Calls OnApplicationBootstrap on all modules
1120
+ */
1121
+ async onApplicationBootstrap(container) {
1122
+ this.logger.log("Calling OnApplicationBootstrap...");
1123
+ await this.callHook("onApplicationBootstrap", container);
1124
+ }
1125
+ /**
1126
+ * Calls shutdown hooks on all modules
1127
+ */
1128
+ async onApplicationShutdown(container) {
1129
+ this.logger.log("Calling shutdown hooks...");
1130
+ await this.callHook("beforeApplicationShutdown", container);
1131
+ await this.callHook("onApplicationShutdown", container);
1132
+ }
1133
+ };
1134
+
1135
+ // src/application/argument-resolver.ts
1136
+ var ArgumentResolver = class {
1137
+ static {
1138
+ __name(this, "ArgumentResolver");
1139
+ }
1140
+ /**
1141
+ * Resolves arguments from request context based on metadata
1142
+ *
1143
+ * @param c - Hono context
1144
+ * @param argsMetadata - Pre-parsed argument metadata
1145
+ * @param pipes - Pipes to apply to arguments
1146
+ * @param executionContext - Execution context for guards/interceptors
1147
+ * @param moduleRef - Module reference for DI
1148
+ * @param contextId - Request context ID
1149
+ * @returns Array of resolved arguments
1150
+ */
1151
+ async resolveArgs(c, argsMetadata, pipes, executionContext, moduleRef, contextId) {
1152
+ const args = [];
1153
+ for (const metadata of argsMetadata) {
1154
+ let value;
1155
+ switch (metadata.paramtype) {
1156
+ case RouteParamtypes.BODY:
1157
+ value = await c.req.json().catch(() => ({}));
1158
+ if (metadata.data) {
1159
+ value = value[metadata.data];
1160
+ }
1161
+ break;
1162
+ case RouteParamtypes.QUERY:
1163
+ if (metadata.data) {
1164
+ value = c.req.query(metadata.data);
1165
+ } else {
1166
+ value = c.req.query();
1167
+ }
1168
+ break;
1169
+ case RouteParamtypes.PARAM:
1170
+ if (metadata.data) {
1171
+ value = c.req.param(metadata.data);
1172
+ } else {
1173
+ value = c.req.param();
1174
+ }
1175
+ break;
1176
+ case RouteParamtypes.HEADERS:
1177
+ if (metadata.data) {
1178
+ value = c.req.header(metadata.data);
1179
+ } else {
1180
+ const headers = {};
1181
+ c.req.raw.headers.forEach((val, key) => {
1182
+ headers[key] = val;
1183
+ });
1184
+ value = headers;
1185
+ }
1186
+ break;
1187
+ case RouteParamtypes.CONTEXT:
1188
+ value = c;
1189
+ break;
1190
+ case RouteParamtypes.REQUEST:
1191
+ value = c.req;
1192
+ break;
1193
+ case RouteParamtypes.RESPONSE:
1194
+ value = c.res;
1195
+ break;
1196
+ default:
1197
+ value = void 0;
1198
+ }
1199
+ const allPipes = [
1200
+ ...metadata.pipes,
1201
+ ...pipes
1202
+ ];
1203
+ for (const pipe of allPipes) {
1204
+ value = await pipe.transform(value, {
1205
+ type: metadata.paramtype,
1206
+ data: metadata.data,
1207
+ metatype: void 0
1208
+ });
1209
+ }
1210
+ args[metadata.index] = value;
1211
+ }
1212
+ return args;
1213
+ }
1214
+ };
1215
+
1014
1216
  // src/common/exceptions/http.exception.ts
1015
1217
  var HttpException = class extends Error {
1016
1218
  static {
@@ -1173,10 +1375,191 @@ var GatewayTimeoutException = class extends HttpException {
1173
1375
  }
1174
1376
  };
1175
1377
 
1176
- // src/application.ts
1177
- var HonoDiApplication = class {
1378
+ // src/application/exception-handler.ts
1379
+ var ExceptionHandler = class {
1380
+ static {
1381
+ __name(this, "ExceptionHandler");
1382
+ }
1383
+ logger = new Logger("ExceptionHandler");
1384
+ /**
1385
+ * Handles an exception through the filter chain
1386
+ *
1387
+ * @param exception - The exception to handle
1388
+ * @param c - Hono context
1389
+ * @param controllerClass - Controller class
1390
+ * @param methodName - Handler method name
1391
+ * @param moduleRef - Module reference
1392
+ * @param contextId - Context ID
1393
+ * @param globalFilters - Global exception filters
1394
+ * @param resolveFilters - Function to resolve filters
1395
+ * @returns Response from filter or default error response
1396
+ */
1397
+ async handle(exception, c, controllerClass, methodName, moduleRef, contextId, globalFilters, resolveFilters) {
1398
+ const filters = await resolveFilters([
1399
+ ...Reflect.getMetadata(METADATA_KEYS.USE_FILTERS, moduleRef.controllers.get(controllerClass)?.instance?.[methodName]) || [],
1400
+ ...Reflect.getMetadata(METADATA_KEYS.USE_FILTERS, controllerClass) || [],
1401
+ ...globalFilters
1402
+ ], moduleRef, contextId);
1403
+ for (const filter of filters) {
1404
+ const catchExceptions = Reflect.getMetadata(METADATA_KEYS.FILTER_CATCH, filter.constructor) || [];
1405
+ if (catchExceptions.length === 0 || catchExceptions.some((e) => exception instanceof e)) {
1406
+ const host = new ExecutionContextHost([
1407
+ c
1408
+ ], controllerClass, moduleRef.controllers.get(controllerClass)?.instance?.[methodName]);
1409
+ return await filter.catch(exception, host);
1410
+ }
1411
+ }
1412
+ return this.handleDefault(exception, c);
1413
+ }
1414
+ /**
1415
+ * Default exception handling when no filter matches
1416
+ */
1417
+ async handleDefault(exception, c) {
1418
+ this.logger.error(exception);
1419
+ if (exception instanceof HttpException) {
1420
+ const status = exception.getStatus();
1421
+ const response = exception.getResponse();
1422
+ c.status(status);
1423
+ return c.json(response);
1424
+ }
1425
+ if (exception instanceof Error) {
1426
+ c.status(500);
1427
+ return c.json({
1428
+ statusCode: 500,
1429
+ message: "Internal Server Error",
1430
+ cause: exception.message
1431
+ });
1432
+ }
1433
+ c.status(500);
1434
+ return c.json({
1435
+ statusCode: 500,
1436
+ message: "Internal Server Error",
1437
+ error: String(exception)
1438
+ });
1439
+ }
1440
+ };
1441
+
1442
+ // src/application/middleware-handler.ts
1443
+ var MiddlewareHandler = class {
1444
+ static {
1445
+ __name(this, "MiddlewareHandler");
1446
+ }
1447
+ logger = new Logger("MiddlewareHandler");
1448
+ /**
1449
+ * Registers all middleware to the Hono app
1450
+ *
1451
+ * @param app - Hono instance
1452
+ * @param middlewareConfigs - Middleware configurations from modules
1453
+ * @param container - DI container
1454
+ * @param injector - Injector for resolving middleware instances
1455
+ */
1456
+ async registerMiddleware(app, middlewareConfigs, container, injector) {
1457
+ const resolvedConfigs = [];
1458
+ for (const config of middlewareConfigs) {
1459
+ const instances = [];
1460
+ for (const middleware of config.middlewares) {
1461
+ if (typeof middleware === "function") {
1462
+ const modules = container.getModules();
1463
+ let wrapper;
1464
+ for (const module of modules.values()) {
1465
+ wrapper = module.getProvider(middleware);
1466
+ if (wrapper) break;
1467
+ }
1468
+ if (!wrapper) {
1469
+ wrapper = new InstanceWrapper({
1470
+ token: middleware,
1471
+ name: middleware.name,
1472
+ metatype: middleware,
1473
+ host: Array.from(modules.values())[0]
1474
+ });
1475
+ }
1476
+ const instance = wrapper.instance || await injector.loadInstance(wrapper, new ContextId());
1477
+ instances.push(instance);
1478
+ } else {
1479
+ instances.push(middleware);
1480
+ }
1481
+ }
1482
+ resolvedConfigs.push({
1483
+ ...config,
1484
+ instances
1485
+ });
1486
+ }
1487
+ app.use("*", async (c, next) => {
1488
+ const path = c.req.path;
1489
+ const method = c.req.method;
1490
+ const matchingMiddleware = [];
1491
+ for (const config of resolvedConfigs) {
1492
+ if (this.isRouteExcluded(config.excludes, path, method)) continue;
1493
+ if (this.isRouteMatch(config.routes, path, method)) {
1494
+ matchingMiddleware.push(...config.instances);
1495
+ }
1496
+ }
1497
+ if (matchingMiddleware.length === 0) {
1498
+ return await next();
1499
+ }
1500
+ const executeChain = /* @__PURE__ */ __name(async (index, finalNext) => {
1501
+ if (index >= matchingMiddleware.length) {
1502
+ return await finalNext();
1503
+ }
1504
+ const middleware = matchingMiddleware[index];
1505
+ return new Promise((resolve, reject) => {
1506
+ let nextCalled = false;
1507
+ const nextFn = /* @__PURE__ */ __name(async () => {
1508
+ nextCalled = true;
1509
+ try {
1510
+ await executeChain(index + 1, finalNext);
1511
+ resolve();
1512
+ } catch (e) {
1513
+ reject(e);
1514
+ }
1515
+ }, "nextFn");
1516
+ try {
1517
+ const useFn = middleware.use ? middleware.use.bind(middleware) : middleware;
1518
+ const result = useFn(c, nextFn);
1519
+ if (result instanceof Promise) {
1520
+ result.then(() => {
1521
+ if (!nextCalled) resolve();
1522
+ }).catch(reject);
1523
+ } else {
1524
+ if (!nextCalled) resolve();
1525
+ }
1526
+ } catch (e) {
1527
+ reject(e);
1528
+ }
1529
+ });
1530
+ }, "executeChain");
1531
+ await executeChain(0, next);
1532
+ });
1533
+ }
1534
+ isRouteMatch(routes, path, method) {
1535
+ for (const route of routes) {
1536
+ if (typeof route === "string") {
1537
+ const normalizedRoute = route === "*" ? "*" : route.startsWith("/") ? route : `/${route}`;
1538
+ if (normalizedRoute === "*" || path.startsWith(normalizedRoute)) return true;
1539
+ if (path === normalizedRoute) return true;
1540
+ } else if (route instanceof RegExp) {
1541
+ if (route.test(path)) return true;
1542
+ }
1543
+ }
1544
+ return false;
1545
+ }
1546
+ isRouteExcluded(excludes, path, method) {
1547
+ for (const exclude of excludes) {
1548
+ if (typeof exclude === "string") {
1549
+ const normalizedExclude = exclude.startsWith("/") ? exclude : `/${exclude}`;
1550
+ if (path.startsWith(normalizedExclude)) return true;
1551
+ } else if (exclude instanceof RegExp) {
1552
+ if (exclude.test(path)) return true;
1553
+ }
1554
+ }
1555
+ return false;
1556
+ }
1557
+ };
1558
+
1559
+ // src/application/index.ts
1560
+ var Application = class {
1178
1561
  static {
1179
- __name(this, "HonoDiApplication");
1562
+ __name(this, "Application");
1180
1563
  }
1181
1564
  app;
1182
1565
  container;
@@ -1185,28 +1568,114 @@ var HonoDiApplication = class {
1185
1568
  globalPipes = [];
1186
1569
  globalGuards = [];
1187
1570
  globalInterceptors = [];
1571
+ scanner;
1572
+ // Delegate to managers
1573
+ contextManager = new ContextManager();
1574
+ lifecycleManager = new LifecycleManager();
1575
+ argumentResolver = new ArgumentResolver();
1576
+ exceptionHandler = new ExceptionHandler();
1577
+ middlewareHandler = new MiddlewareHandler();
1578
+ // Security: Dangerous property names that should not be injected
1579
+ UNSAFE_PROPERTIES = /* @__PURE__ */ new Set([
1580
+ "__proto__",
1581
+ "constructor",
1582
+ "prototype"
1583
+ ]);
1584
+ // Performance: Route metadata cache
1585
+ routeCache = /* @__PURE__ */ new Map();
1188
1586
  constructor(app, container, injector) {
1189
1587
  this.app = app;
1190
1588
  this.container = container;
1191
1589
  this.injector = injector;
1192
- }
1590
+ this.scanner = new Scanner(container);
1591
+ }
1592
+ /**
1593
+ * Registers global exception filters
1594
+ *
1595
+ * @param filters - Exception filter instances or classes
1596
+ * @returns This application instance for chaining
1597
+ *
1598
+ * @example
1599
+ * ```typescript
1600
+ * app.useGlobalFilters(new HttpExceptionFilter());
1601
+ * ```
1602
+ *
1603
+ * @public
1604
+ */
1193
1605
  useGlobalFilters(...filters) {
1194
1606
  this.globalFilters.push(...filters);
1195
1607
  return this;
1196
1608
  }
1609
+ /**
1610
+ * Registers global pipes for request transformation/validation
1611
+ *
1612
+ * @param pipes - Pipe instances or classes
1613
+ * @returns This application instance for chaining
1614
+ *
1615
+ * @example
1616
+ * ```typescript
1617
+ * app.useGlobalPipes(new ValidationPipe());
1618
+ * ```
1619
+ *
1620
+ * @public
1621
+ */
1197
1622
  useGlobalPipes(...pipes) {
1198
1623
  this.globalPipes.push(...pipes);
1199
1624
  return this;
1200
1625
  }
1626
+ /**
1627
+ * Registers global interceptors for request/response manipulation
1628
+ *
1629
+ * @param interceptors - Interceptor instances or classes
1630
+ * @returns This application instance for chaining
1631
+ *
1632
+ * @example
1633
+ * ```typescript
1634
+ * app.useGlobalInterceptors(new LoggingInterceptor());
1635
+ * ```
1636
+ *
1637
+ * @public
1638
+ */
1201
1639
  useGlobalInterceptors(...interceptors) {
1202
1640
  this.globalInterceptors.push(...interceptors);
1203
1641
  return this;
1204
1642
  }
1643
+ /**
1644
+ * Registers global guards for route protection
1645
+ *
1646
+ * @param guards - Guard instances or classes
1647
+ * @returns This application instance for chaining
1648
+ *
1649
+ * @example
1650
+ * ```typescript
1651
+ * app.useGlobalGuards(new AuthGuard());
1652
+ * ```
1653
+ *
1654
+ * @public
1655
+ */
1205
1656
  useGlobalGuards(...guards) {
1206
1657
  this.globalGuards.push(...guards);
1207
1658
  return this;
1208
1659
  }
1209
1660
  globalPrefix = "";
1661
+ /**
1662
+ * Sets a global prefix for all routes
1663
+ *
1664
+ * @param prefix - URL prefix (e.g., 'api' or 'api/v1')
1665
+ * @returns This application instance for chaining
1666
+ *
1667
+ * @remarks
1668
+ * Must be called before init() if using autoInit: true.
1669
+ * Use autoInit: false in HonoDiFactory.create() to set prefix before initialization.
1670
+ *
1671
+ * @example
1672
+ * ```typescript
1673
+ * app.setGlobalPrefix('api/v1');
1674
+ * // All routes will be prefixed with /api/v1
1675
+ * ```
1676
+ *
1677
+ * @public
1678
+ */
1210
1679
  setGlobalPrefix(prefix) {
1211
1680
  if (this.isInitialized) {
1212
1681
  this.logger.warn("Setting global prefix after initialization will not affect existing routes. Use { autoInit: false } in HonoDiFactory.create() if you need to set a prefix.");
@@ -1217,8 +1686,22 @@ var HonoDiApplication = class {
1217
1686
  getGlobalPrefix() {
1218
1687
  return this.globalPrefix;
1219
1688
  }
1220
- logger = new Logger("HonoDiApplication");
1689
+ logger = new Logger("Application");
1221
1690
  isInitialized = false;
1691
+ /**
1692
+ * Initializes the application by registering all routes and middleware
1693
+ *
1694
+ * @returns Promise resolving to this application instance
1695
+ *
1696
+ * @remarks
1697
+ * Called automatically unless autoInit: false is specified in HonoDiFactory.create().
1698
+ * Handles:
1699
+ * - Middleware registration
1700
+ * - Controller and route registration
1701
+ * - Lifecycle hook execution (OnApplicationBootstrap)
1702
+ *
1703
+ * @public
1704
+ */
1222
1705
  async init() {
1223
1706
  if (this.isInitialized) return this;
1224
1707
  this.logger.log("Initializing middleware...");
@@ -1269,26 +1752,63 @@ var HonoDiApplication = class {
1269
1752
  const { prefix } = Reflect.getMetadata(METADATA_KEYS.CONTROLLER, controllerClass);
1270
1753
  const routes = Reflect.getMetadata(METADATA_KEYS.ROUTES, controllerClass);
1271
1754
  if (!routes) return;
1755
+ const controllerGuards = Reflect.getMetadata(METADATA_KEYS.USE_GUARDS, controllerClass) || [];
1756
+ const controllerInterceptors = Reflect.getMetadata(METADATA_KEYS.USE_INTERCEPTORS, controllerClass) || [];
1757
+ const controllerPipes = Reflect.getMetadata(METADATA_KEYS.USE_PIPES, controllerClass) || [];
1272
1758
  routes.forEach((route) => {
1273
1759
  const globalPrefix = this.getGlobalPrefix();
1274
1760
  const fullPath = this.combinePaths(globalPrefix, this.combinePaths(prefix, route.path));
1761
+ const cacheKey = `${controllerClass.name}.${route.methodName}`;
1762
+ const handler = controllerClass.prototype[route.methodName];
1763
+ const methodGuards = Reflect.getMetadata(METADATA_KEYS.USE_GUARDS, handler) || [];
1764
+ const methodInterceptors = Reflect.getMetadata(METADATA_KEYS.USE_INTERCEPTORS, handler) || [];
1765
+ const methodPipes = Reflect.getMetadata(METADATA_KEYS.USE_PIPES, handler) || [];
1766
+ const allGuards = [
1767
+ ...this.globalGuards,
1768
+ ...controllerGuards,
1769
+ ...methodGuards
1770
+ ];
1771
+ const allInterceptors = [
1772
+ ...this.globalInterceptors,
1773
+ ...controllerInterceptors,
1774
+ ...methodInterceptors
1775
+ ];
1776
+ const allPipes = [
1777
+ ...this.globalPipes,
1778
+ ...controllerPipes,
1779
+ ...methodPipes
1780
+ ];
1781
+ const argsMetadata = Reflect.getMetadata(METADATA_KEYS.ROUTE_ARGS_METADATA, controllerClass, route.methodName) || {};
1782
+ const parsedArgs = Object.values(argsMetadata).sort((a, b) => a.index - b.index).map((arg) => ({
1783
+ index: arg.index,
1784
+ data: arg.data,
1785
+ paramtype: arg.paramtype,
1786
+ pipes: arg.pipes || []
1787
+ }));
1788
+ const wrapper = moduleRef.controllers.get(controllerClass);
1789
+ this.routeCache.set(cacheKey, {
1790
+ wrapper,
1791
+ handler,
1792
+ guards: allGuards,
1793
+ interceptors: allInterceptors,
1794
+ pipes: allPipes,
1795
+ argsMetadata: parsedArgs,
1796
+ httpCode: Reflect.getMetadata(METADATA_KEYS.HTTP_CODE, handler),
1797
+ headers: Reflect.getMetadata(METADATA_KEYS.HEADERS, handler),
1798
+ redirect: Reflect.getMetadata(METADATA_KEYS.REDIRECT, handler)
1799
+ });
1275
1800
  app[route.requestMethod](fullPath, async (c) => {
1276
1801
  const contextId = new ContextId();
1802
+ this.contextManager.addContext(contextId);
1803
+ const cacheKey2 = `${controllerClass.name}.${route.methodName}`;
1804
+ const cache = this.routeCache.get(cacheKey2);
1277
1805
  const executionContext = new ExecutionContextHost([
1278
1806
  c
1279
- ], controllerClass, controllerClass.prototype[route.methodName]);
1807
+ ], controllerClass, cache.handler);
1280
1808
  try {
1281
- const wrapper = moduleRef.getProvider(controllerClass) || moduleRef.controllers.get(controllerClass);
1282
- if (!wrapper) {
1283
- throw new Error(`Controller ${controllerClass.name} not found in module ${moduleRef.metatype.name}`);
1284
- }
1285
- const controllerInstance = await this.injector.loadInstance(wrapper, contextId);
1286
- const handler = controllerInstance[route.methodName].bind(controllerInstance);
1287
- const guards = await this.resolveContextItems([
1288
- ...this.globalGuards,
1289
- ...Reflect.getMetadata(METADATA_KEYS.USE_GUARDS, controllerClass) || [],
1290
- ...Reflect.getMetadata(METADATA_KEYS.USE_GUARDS, controllerInstance[route.methodName]) || []
1291
- ], moduleRef, contextId);
1809
+ const controllerInstance = await this.injector.loadInstance(cache.wrapper, contextId);
1810
+ const handler2 = controllerInstance[route.methodName].bind(controllerInstance);
1811
+ const guards = await this.resolveContextItems(cache.guards, moduleRef, contextId);
1292
1812
  if (!await this.runGuards(guards, executionContext)) {
1293
1813
  c.status(403);
1294
1814
  return c.json({
@@ -1296,25 +1816,16 @@ var HonoDiApplication = class {
1296
1816
  message: "Forbidden resource"
1297
1817
  });
1298
1818
  }
1299
- const interceptors = await this.resolveContextItems([
1300
- ...this.globalInterceptors,
1301
- ...Reflect.getMetadata(METADATA_KEYS.USE_INTERCEPTORS, controllerClass) || [],
1302
- ...Reflect.getMetadata(METADATA_KEYS.USE_INTERCEPTORS, controllerInstance[route.methodName]) || []
1303
- ], moduleRef, contextId);
1304
- const pipes = await this.resolveContextItems([
1305
- ...this.globalPipes,
1306
- ...Reflect.getMetadata(METADATA_KEYS.USE_PIPES, controllerClass) || [],
1307
- ...Reflect.getMetadata(METADATA_KEYS.USE_PIPES, controllerInstance[route.methodName]) || []
1308
- ], moduleRef, contextId);
1309
- const args = await this.resolveArgs(contextId, executionContext, controllerClass, route.methodName, moduleRef, pipes);
1310
- if (args.length === 0 && !Reflect.hasMetadata(METADATA_KEYS.ROUTE_ARGS_METADATA, controllerClass, route.methodName)) {
1311
- args.push(c);
1312
- }
1819
+ const interceptors = await this.resolveContextItems(cache.interceptors, moduleRef, contextId);
1820
+ const pipes = await this.resolveContextItems(cache.pipes, moduleRef, contextId);
1821
+ const args = cache.argsMetadata.length > 0 ? await this.resolveArgsFromCache(c, cache.argsMetadata, pipes, executionContext, moduleRef, contextId) : [
1822
+ c
1823
+ ];
1313
1824
  const interceptorChain = /* @__PURE__ */ __name(async (index) => {
1314
1825
  if (index >= interceptors.length) {
1315
1826
  return new rxjs.Observable((subscriber) => {
1316
1827
  try {
1317
- const result2 = handler(...args);
1828
+ const result2 = handler2(...args);
1318
1829
  if (result2 instanceof Promise) {
1319
1830
  result2.then((data) => {
1320
1831
  subscriber.next(data);
@@ -1335,20 +1846,17 @@ var HonoDiApplication = class {
1335
1846
  }, "interceptorChain");
1336
1847
  const obs = await interceptorChain(0);
1337
1848
  const result = await rxjs.lastValueFrom(obs);
1338
- const httpCode = Reflect.getMetadata(METADATA_KEYS.HTTP_CODE, controllerInstance[route.methodName]);
1339
- if (httpCode) {
1340
- c.status(httpCode);
1849
+ if (cache.httpCode) {
1850
+ c.status(cache.httpCode);
1341
1851
  }
1342
- const headers = Reflect.getMetadata(METADATA_KEYS.HEADERS, controllerInstance[route.methodName]);
1343
- if (headers) {
1344
- headers.forEach((h) => c.header(h.name, h.value));
1852
+ if (cache.headers) {
1853
+ cache.headers.forEach((h) => c.header(h.name, h.value));
1345
1854
  }
1346
- const redirect = Reflect.getMetadata(METADATA_KEYS.REDIRECT, controllerInstance[route.methodName]);
1347
- if (redirect) {
1855
+ if (cache.redirect) {
1348
1856
  if (result && typeof result === "object" && result.url) {
1349
- return c.redirect(result.url, result.statusCode || redirect.statusCode);
1857
+ return c.redirect(result.url, result.statusCode || cache.redirect.statusCode);
1350
1858
  }
1351
- return c.redirect(redirect.url, redirect.statusCode);
1859
+ return c.redirect(cache.redirect.url, cache.redirect.statusCode);
1352
1860
  }
1353
1861
  if (result instanceof Response) {
1354
1862
  return result;
@@ -1358,46 +1866,16 @@ var HonoDiApplication = class {
1358
1866
  }
1359
1867
  return c.json(result);
1360
1868
  } catch (exception) {
1361
- return await this.handleException(exception, c, controllerClass, route.methodName, moduleRef, contextId);
1869
+ return await this.exceptionHandler.handle(exception, c, controllerClass, route.methodName, moduleRef, contextId, this.globalFilters, this.resolveContextItems.bind(this));
1870
+ } finally {
1871
+ this.cleanupContext(contextId);
1362
1872
  }
1363
1873
  });
1364
1874
  this.logger.log(`[Route] Mapped {${fullPath}, ${route.requestMethod.toUpperCase()}}`);
1365
1875
  });
1366
1876
  }
1367
- async handleException(exception, c, controllerClass, methodName, moduleRef, contextId) {
1368
- const filters = await this.resolveContextItems([
1369
- ...Reflect.getMetadata(METADATA_KEYS.USE_FILTERS, moduleRef.controllers.get(controllerClass)?.instance?.[methodName]) || [],
1370
- ...Reflect.getMetadata(METADATA_KEYS.USE_FILTERS, controllerClass) || [],
1371
- ...this.globalFilters
1372
- ], moduleRef, contextId);
1373
- for (const filter of filters) {
1374
- const catchExceptions = Reflect.getMetadata(METADATA_KEYS.FILTER_CATCH, filter.constructor) || [];
1375
- if (catchExceptions.length === 0 || catchExceptions.some((e) => exception instanceof e)) {
1376
- const host = new ExecutionContextHost([
1377
- c
1378
- ], controllerClass, moduleRef.controllers.get(controllerClass)?.instance?.[methodName]);
1379
- return await filter.catch(exception, host);
1380
- }
1381
- }
1382
- this.logger.error(exception);
1383
- if (exception instanceof HttpException) {
1384
- const status = exception.getStatus();
1385
- const response = exception.getResponse();
1386
- c.status(status);
1387
- return c.json(response);
1388
- }
1389
- if (exception instanceof Error) {
1390
- c.status(500);
1391
- return c.json({
1392
- statusCode: 500,
1393
- message: "Internal Server Error",
1394
- cause: exception.message
1395
- });
1396
- }
1397
- }
1398
1877
  async resolveContextItems(items, moduleRef, contextId) {
1399
1878
  const instances = [];
1400
- const scanner = new HonoDiScanner(this.container);
1401
1879
  for (const item of items) {
1402
1880
  if (typeof item === "function") {
1403
1881
  let wrapper = moduleRef.getProvider(item);
@@ -1409,7 +1887,7 @@ var HonoDiApplication = class {
1409
1887
  host: moduleRef,
1410
1888
  scope: Scope.TRANSIENT
1411
1889
  });
1412
- scanner.scanDependencies(wrapper);
1890
+ this.scanner.scanDependencies(wrapper);
1413
1891
  }
1414
1892
  const instance = await this.injector.loadInstance(wrapper, contextId);
1415
1893
  instances.push(instance);
@@ -1497,6 +1975,66 @@ var HonoDiApplication = class {
1497
1975
  }
1498
1976
  return true;
1499
1977
  }
1978
+ // Performance: Optimized args resolution using pre-parsed metadata
1979
+ async resolveArgsFromCache(c, parsedArgs, methodPipes, context, moduleRef, contextId) {
1980
+ const args = [];
1981
+ for (const arg of parsedArgs) {
1982
+ let value;
1983
+ switch (arg.paramtype) {
1984
+ case RouteParamtypes.REQUEST:
1985
+ value = c.req;
1986
+ break;
1987
+ case RouteParamtypes.RESPONSE:
1988
+ value = c;
1989
+ break;
1990
+ case RouteParamtypes.CONTEXT:
1991
+ value = c;
1992
+ break;
1993
+ case RouteParamtypes.BODY:
1994
+ try {
1995
+ const body = await c.req.json();
1996
+ value = arg.data ? body[arg.data] : body;
1997
+ } catch (e) {
1998
+ value = null;
1999
+ }
2000
+ break;
2001
+ case RouteParamtypes.QUERY:
2002
+ value = arg.data ? c.req.query(arg.data) : c.req.query();
2003
+ break;
2004
+ case RouteParamtypes.PARAM:
2005
+ value = arg.data ? c.req.param(arg.data) : c.req.param();
2006
+ break;
2007
+ case RouteParamtypes.HEADERS:
2008
+ value = arg.data ? c.req.header(arg.data) : c.req.header();
2009
+ break;
2010
+ case RouteParamtypes.IP:
2011
+ value = c.req.header("x-forwarded-for") || "127.0.0.1";
2012
+ break;
2013
+ case RouteParamtypes.CUSTOM:
2014
+ const factory = arg.pipes[0];
2015
+ if (typeof factory === "function") {
2016
+ value = factory(arg.data, context);
2017
+ }
2018
+ break;
2019
+ default:
2020
+ value = null;
2021
+ }
2022
+ const paramPipes = await this.resolveContextItems(arg.pipes, moduleRef, contextId);
2023
+ const allPipes = [
2024
+ ...methodPipes,
2025
+ ...paramPipes
2026
+ ];
2027
+ for (const pipe of allPipes) {
2028
+ value = await pipe.transform(value, {
2029
+ type: "custom",
2030
+ metatype: null,
2031
+ data: arg.data
2032
+ });
2033
+ }
2034
+ args[arg.index] = value;
2035
+ }
2036
+ return args;
2037
+ }
1500
2038
  async initializeMiddleware() {
1501
2039
  const configs = [];
1502
2040
  const modules = this.container.getModules();
@@ -1524,7 +2062,7 @@ var HonoDiApplication = class {
1524
2062
  metatype: m,
1525
2063
  scope: Scope.TRANSIENT
1526
2064
  });
1527
- const scanner = new HonoDiScanner(this.container);
2065
+ const scanner = new Scanner(this.container);
1528
2066
  scanner.scanDependencies(wrapper);
1529
2067
  const hostModule = config.module || modules.values().next().value;
1530
2068
  wrapper.host = hostModule;
@@ -1627,6 +2165,41 @@ var HonoDiApplication = class {
1627
2165
  throw new Error(`Provider ${String(typeOrToken)} not found`);
1628
2166
  }
1629
2167
  async close() {
2168
+ await this.callLifecycleHook("beforeApplicationShutdown");
2169
+ for (const contextId of this.contextManager.getActiveContexts()) {
2170
+ this.cleanupContext(contextId);
2171
+ }
2172
+ this.contextManager.clearAll();
2173
+ const modules = this.container.getModules();
2174
+ for (const module of modules.values()) {
2175
+ for (const wrapper of module.providers.values()) {
2176
+ if (wrapper.scope !== Scope.DEFAULT) {
2177
+ wrapper.cleanup();
2178
+ }
2179
+ }
2180
+ for (const wrapper of module.controllers.values()) {
2181
+ if (wrapper.scope !== Scope.DEFAULT) {
2182
+ wrapper.cleanup();
2183
+ }
2184
+ }
2185
+ }
2186
+ await this.callLifecycleHook("onApplicationShutdown");
2187
+ }
2188
+ cleanupContext(contextId) {
2189
+ this.contextManager.removeContext(contextId);
2190
+ const modules = this.container.getModules();
2191
+ for (const module of modules.values()) {
2192
+ for (const wrapper of module.providers.values()) {
2193
+ if (wrapper.scope === Scope.REQUEST) {
2194
+ wrapper.cleanup(contextId);
2195
+ }
2196
+ }
2197
+ for (const wrapper of module.controllers.values()) {
2198
+ if (wrapper.scope === Scope.REQUEST) {
2199
+ wrapper.cleanup(contextId);
2200
+ }
2201
+ }
2202
+ }
1630
2203
  }
1631
2204
  // Getters for global items (internal use)
1632
2205
  getGlobalFilters() {
@@ -1651,7 +2224,31 @@ var HonoDiFactory = class {
1651
2224
  static {
1652
2225
  __name(this, "HonoDiFactory");
1653
2226
  }
1654
- static logger = new Logger("HonoDiFactory");
2227
+ static logger = new Logger("Factory");
2228
+ /**
2229
+ * Creates and bootstraps a Hono DI application
2230
+ *
2231
+ * @param rootModule - The root module class decorated with @Module
2232
+ * @param appOrOptions - Optional Hono instance or configuration options
2233
+ * @param appOrOptions.app - Custom Hono instance to use
2234
+ * @param appOrOptions.autoInit - Whether to automatically initialize the app (default: true)
2235
+ *
2236
+ * @returns Promise resolving to the initialized application instance
2237
+ *
2238
+ * @throws {Error} If module scanning fails
2239
+ * @throws {Error} If circular dependencies are detected
2240
+ * @throws {Error} If required dependencies cannot be resolved
2241
+ *
2242
+ * @remarks
2243
+ * The creation process includes:
2244
+ * 1. Module scanning and dependency graph building
2245
+ * 2. Scope bubbling optimization (REQUEST-scoped propagation)
2246
+ * 3. Singleton provider instantiation
2247
+ * 4. Lifecycle hook execution (OnModuleInit, OnApplicationBootstrap)
2248
+ * 5. Route registration and middleware setup
2249
+ *
2250
+ * @public
2251
+ */
1655
2252
  static async create(rootModule, appOrOptions) {
1656
2253
  let app;
1657
2254
  let autoInit = true;
@@ -1665,12 +2262,13 @@ var HonoDiFactory = class {
1665
2262
  }
1666
2263
  }
1667
2264
  const container = new Container();
1668
- const scanner = new HonoDiScanner(container);
2265
+ const scanner = new Scanner(container);
1669
2266
  const injector = new Injector(container);
1670
2267
  const honoApp = app || new hono.Hono();
1671
- const bunApp = new HonoDiApplication(honoApp, container, injector);
2268
+ const bunApp = new Application(honoApp, container, injector);
1672
2269
  this.logger.log("Scanning modules...");
1673
2270
  await scanner.scan(rootModule);
2271
+ this.applyScopeBubbling(container);
1674
2272
  this.logger.log("Instantiating providers...");
1675
2273
  await this.instantiateProviders(container, injector);
1676
2274
  this.logger.log("Calling OnModuleInit...");
@@ -1680,6 +2278,61 @@ var HonoDiFactory = class {
1680
2278
  }
1681
2279
  return bunApp;
1682
2280
  }
2281
+ static applyScopeBubbling(container) {
2282
+ const modules = container.getModules();
2283
+ const tokenMap = /* @__PURE__ */ new Map();
2284
+ for (const module of modules.values()) {
2285
+ for (const wrapper of module.providers.values()) {
2286
+ tokenMap.set(wrapper.token, wrapper);
2287
+ }
2288
+ for (const wrapper of module.controllers.values()) {
2289
+ tokenMap.set(wrapper.token, wrapper);
2290
+ }
2291
+ }
2292
+ const hasRequestScopedDeps = /* @__PURE__ */ __name((wrapper, visited = /* @__PURE__ */ new Set()) => {
2293
+ if (visited.has(wrapper)) return false;
2294
+ visited.add(wrapper);
2295
+ if (wrapper.inject) {
2296
+ for (const token of wrapper.inject) {
2297
+ const depWrapper = tokenMap.get(token);
2298
+ if (depWrapper) {
2299
+ if (depWrapper.scope === Scope.REQUEST) {
2300
+ return true;
2301
+ }
2302
+ if (hasRequestScopedDeps(depWrapper, visited)) {
2303
+ return true;
2304
+ }
2305
+ }
2306
+ }
2307
+ }
2308
+ if (wrapper.properties) {
2309
+ for (const prop of wrapper.properties) {
2310
+ const depWrapper = tokenMap.get(prop.token);
2311
+ if (depWrapper) {
2312
+ if (depWrapper.scope === Scope.REQUEST) {
2313
+ return true;
2314
+ }
2315
+ if (hasRequestScopedDeps(depWrapper, visited)) {
2316
+ return true;
2317
+ }
2318
+ }
2319
+ }
2320
+ }
2321
+ return false;
2322
+ }, "hasRequestScopedDeps");
2323
+ for (const module of modules.values()) {
2324
+ for (const wrapper of module.providers.values()) {
2325
+ if (wrapper.scope === Scope.DEFAULT && hasRequestScopedDeps(wrapper)) {
2326
+ wrapper.scope = Scope.REQUEST;
2327
+ }
2328
+ }
2329
+ for (const wrapper of module.controllers.values()) {
2330
+ if (wrapper.scope === Scope.DEFAULT && hasRequestScopedDeps(wrapper)) {
2331
+ wrapper.scope = Scope.REQUEST;
2332
+ }
2333
+ }
2334
+ }
2335
+ }
1683
2336
  static async instantiateProviders(container, injector) {
1684
2337
  const modules = container.getModules();
1685
2338
  const globalContextId = new ContextId();
@@ -1940,11 +2593,31 @@ exports.BaseExceptionFilter = class BaseExceptionFilter {
1940
2593
  honoCtx.status(status);
1941
2594
  return honoCtx.json(res);
1942
2595
  }
2596
+ if (exception instanceof Error) {
2597
+ console.error(exception);
2598
+ honoCtx.status(500);
2599
+ return honoCtx.json({
2600
+ statusCode: 500,
2601
+ message: "Internal Server Error",
2602
+ cause: exception.message
2603
+ });
2604
+ }
1943
2605
  console.error(exception);
1944
2606
  honoCtx.status(500);
2607
+ let errorMessage;
2608
+ if (typeof exception === "symbol") {
2609
+ errorMessage = exception.toString();
2610
+ } else if (exception === null || exception === void 0) {
2611
+ errorMessage = String(exception);
2612
+ } else if (typeof exception === "object") {
2613
+ errorMessage = JSON.stringify(exception);
2614
+ } else {
2615
+ errorMessage = String(exception);
2616
+ }
1945
2617
  return honoCtx.json({
1946
2618
  statusCode: 500,
1947
- message: "Internal Server Error"
2619
+ message: "Internal Server Error",
2620
+ error: errorMessage
1948
2621
  });
1949
2622
  }
1950
2623
  };
@@ -1957,6 +2630,7 @@ var HonoDi = HonoDiFactory;
1957
2630
 
1958
2631
  exports.All = All;
1959
2632
  exports.AppError = AppError;
2633
+ exports.Application = Application;
1960
2634
  exports.BadGatewayException = BadGatewayException;
1961
2635
  exports.BadRequestError = BadRequestError;
1962
2636
  exports.BadRequestException = BadRequestException;
@@ -1981,9 +2655,7 @@ exports.Head = Head;
1981
2655
  exports.Header = Header;
1982
2656
  exports.Headers = Headers;
1983
2657
  exports.HonoDi = HonoDi;
1984
- exports.HonoDiApplication = HonoDiApplication;
1985
2658
  exports.HonoDiFactory = HonoDiFactory;
1986
- exports.HonoDiScanner = HonoDiScanner;
1987
2659
  exports.HostParam = HostParam;
1988
2660
  exports.HttpCode = HttpCode;
1989
2661
  exports.HttpException = HttpException;
@@ -2016,6 +2688,7 @@ exports.RequestMethod = RequestMethod;
2016
2688
  exports.RequestTimeoutException = RequestTimeoutException;
2017
2689
  exports.Response = Response2;
2018
2690
  exports.RouteParamtypes = RouteParamtypes;
2691
+ exports.Scanner = Scanner;
2019
2692
  exports.Scope = Scope;
2020
2693
  exports.ServiceUnavailableException = ServiceUnavailableException;
2021
2694
  exports.Session = Session;