honestjs 0.1.21 → 0.1.22
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/README.md +8 -4
- package/dist/application.d.ts +1 -1
- package/dist/index.js +5 -5
- package/dist/interfaces/honest-options.interface.d.ts +1 -1
- package/dist/interfaces/metadata-repository.interface.d.ts +1 -1
- package/dist/managers/component.manager.d.ts +2 -2
- package/dist/managers/parameter.resolver.d.ts +4 -1
- package/dist/managers/route.manager.d.ts +1 -1
- package/dist/registries/metadata.registry.d.ts +3 -2
- package/dist/registries/metadata.repository.d.ts +6 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -94,13 +94,17 @@ See [honestjs/skills](https://github.com/honestjs/skills) for details.
|
|
|
94
94
|
|
|
95
95
|
```bash
|
|
96
96
|
bun add -g @honestjs/cli
|
|
97
|
-
honestjs new my-project
|
|
97
|
+
honestjs new my-project # alias: honest, hnjs; interactive template picker
|
|
98
98
|
cd my-project
|
|
99
99
|
bun dev
|
|
100
100
|
```
|
|
101
101
|
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
Templates: **blank** (minimal), **barebone** (modules + services — best for APIs), **mvc** (full-stack with Hono JSX
|
|
103
|
+
views). Use `-t barebone -y` to skip prompts.
|
|
104
|
+
|
|
105
|
+
See **[Getting Started](https://honestjs.dev/docs/getting-started)** on [honestjs.dev](https://honestjs.dev) for the
|
|
106
|
+
full tutorial, and **[FAQ](https://honestjs.dev/docs/faq)** /
|
|
107
|
+
**[Troubleshooting](https://honestjs.dev/docs/troubleshooting)** for common questions and edge cases.
|
|
104
108
|
|
|
105
109
|
## Features
|
|
106
110
|
|
|
@@ -198,7 +202,7 @@ export default hono
|
|
|
198
202
|
```
|
|
199
203
|
|
|
200
204
|
Controllers, services, and modules are wired by decorators; use **guards** for auth, **pipes** for validation, and
|
|
201
|
-
**filters** for error handling. See the [documentation](https://
|
|
205
|
+
**filters** for error handling. See the [documentation](https://honestjs.dev/docs/overview) for details.
|
|
202
206
|
|
|
203
207
|
## Runtime Metadata Isolation
|
|
204
208
|
|
package/dist/application.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export declare class Application {
|
|
|
18
18
|
private readonly routeManager;
|
|
19
19
|
private readonly logger;
|
|
20
20
|
private readonly options;
|
|
21
|
-
constructor(options
|
|
21
|
+
constructor(options: HonestOptions | undefined, metadataRepository: IMetadataRepository);
|
|
22
22
|
private setupErrorHandlers;
|
|
23
23
|
private shouldEmitRouteDiagnostics;
|
|
24
24
|
private emitStartupGuide;
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import"reflect-metadata";import{Hono as P$}from"hono";function G$($){let _=new Set;if(_.add("Check module wiring: root module imports, controllers, and services should be registered correctly."),$.includes("not decorated with @Controller()"))_.add("Add @Controller() to the class or remove it from module.controllers.");if($.includes("has no route handlers"))_.add("Add at least one HTTP method decorator such as @Get() or @Post() in the controller.");if($.includes("not decorated with @Service()"))_.add("Add @Service() to injectable classes used in constructor dependencies.");if($.includes("constructor metadata is missing")||$.includes("reflect-metadata"))_.add("Import 'reflect-metadata' in your entry file and enable 'emitDecoratorMetadata' in tsconfig.");if($.includes("Strict mode: no routes were registered"))_.add("Disable strict.requireRoutes for empty modules, or add a controller with at least one route.");return[..._]}function _$($,_,W,Q){if(!_)return;let U=typeof _==="object"&&Boolean(_.verbose),X=W instanceof Error?W.message:String(W),Z=G$(X);if($.emit({level:"warn",category:"startup",message:"Startup guide",details:{rootModule:Q.name,errorMessage:X,hints:Z,verbose:U}}),U)$.emit({level:"warn",category:"startup",message:"Startup guide (verbose)",details:{steps:["Verify decorators are present for controllers/services used by DI and routing.","Ensure 'reflect-metadata' is imported once at entry and 'emitDecoratorMetadata' is enabled.","Enable debug.startup for extra startup diagnostics and timing details."]}})}var D$=($)=>typeof $>"u",N=($)=>$===null||typeof $>"u",H=($)=>$!==null&&typeof $==="object",H$=($)=>{if(!H($))return!1;let _=Object.getPrototypeOf($);if(_===null)return!0;let W=Object.prototype.hasOwnProperty.call(_,"constructor")&&_.constructor;return typeof W==="function"&&W instanceof W&&Function.prototype.toString.call(W)===Function.prototype.toString.call(Object)},W$=($)=>typeof $==="function",R=($)=>typeof $==="string",k$=($)=>typeof $==="number",O$=($)=>$.length===0,T$=($)=>typeof $==="symbol",E$=($)=>typeof $==="string"?$.charAt(0)!=="/"?"/"+$:$:"",g=($)=>$?$.startsWith("/")?("/"+$.replace(/\/+$/,"")).replace(/\/+/g,"/"):"/"+$.replace(/\/+$/,""):"/",b$=($)=>$.endsWith("/")?$.slice(0,-1):$,Q$=($)=>{return W$($)&&!N($.prototype)&&!W$($.prototype)&&Object.getOwnPropertyNames($.prototype).length>=1};var U$="AnonymousPlugin";function X$($){if(Q$($))return new $;return $}function Z$($,_,W){let Q=W||$.meta?.name||$.constructor?.name;if(!Q||Q===U$)return`${U$}#${_+1}`;return Q}function V$($,_){if($&&typeof $==="object"&&"plugin"in $){let Q=$,U=X$(Q.plugin),X=Z$(U,_,Q.name);return{plugin:U,name:X,preProcessors:Q.preProcessors??[],postProcessors:Q.postProcessors??[]}}let W=X$($);return{plugin:W,name:Z$(W,_),preProcessors:[],postProcessors:[]}}function J$($){return($??[]).map((_,W)=>V$(_,W))}class h{store=new Map;get($){return this.store.get($)}set($,_){this.store.set($,_)}has($){return this.store.has($)}delete($){return this.store.delete($)}keys(){return this.store.keys()}}class m{emit($){let _=`[HonestJS:${$.category}]`,W=$.details?[_,$.message,$.details]:[_,$.message];switch($.level){case"debug":case"info":console.info(...W);break;case"warn":console.warn(...W);break;case"error":console.error(...W);break}}}class A{emit($){}}class B{static routes=new Map;static controllers=new Map;static controllerOptions=new Map;static services=new Set;static modules=new Map;static parameters=new Map;static contextIndices=new Map;static controller=new Map([["middleware",new Map],["guard",new Map],["pipe",new Map],["filter",new Map]]);static handler=new Map([["middleware",new Map],["guard",new Map],["pipe",new Map],["filter",new Map]]);static getRoutes($){return this.routes.get($)||[]}static setRoutes($,_){this.routes.set($,_)}static addRoute($,_){if(!this.routes.has($))this.routes.set($,[]);this.routes.get($).push(_)}static getControllerPath($){return this.controllers.get($)||""}static hasController($){return this.controllers.has($)}static setControllerPath($,_){this.controllers.set($,_)}static getControllerOptions($){return this.controllerOptions.get($)||{}}static setControllerOptions($,_){this.controllerOptions.set($,_)}static isService($){return this.services.has($)}static addService($){this.services.add($)}static getAllServices(){return this.services}static getModuleOptions($){return this.modules.get($)}static setModuleOptions($,_){this.modules.set($,_)}static getParameters($){return this.parameters.get($)||new Map}static setParameterMap($,_){this.parameters.set($,_)}static getContextIndices($){return this.contextIndices.get($)||new Map}static setContextIndices($,_){this.contextIndices.set($,_)}static registerController($,_,W){let Q=this.controller.get($);if(!Q.has(_))Q.set(_,[]);Q.get(_).push(W)}static getController($,_){return this.controller.get($).get(_)||[]}static registerHandler($,_,W){let Q=this.handler.get($);if(!Q.has(_))Q.set(_,[]);Q.get(_).push(W)}static getHandler($,_){return this.handler.get($).get(_)||[]}static clearHandlerComponents(){for(let $ of this.handler.values())$.clear()}static clear(){this.routes.clear(),this.controllers.clear(),this.controllerOptions.clear(),this.services.clear(),this.modules.clear(),this.parameters.clear(),this.contextIndices.clear();for(let $ of this.controller.values())$.clear();for(let $ of this.handler.values())$.clear()}}class k{hasController($){return B.hasController($)}getControllerPath($){return B.getControllerPath($)}getControllerOptions($){return B.getControllerOptions($)}getRoutes($){return B.getRoutes($)}getParameters($){return B.getParameters($)}getContextIndices($){return B.getContextIndices($)}getModuleOptions($){return B.getModuleOptions($)}getControllerComponents($,_){return B.getController($,_)}getHandlerComponents($,_){return B.getHandler($,_)}}class C{controllerPaths=new Map;controllerOptions=new Map;routes=new Map;parameters=new Map;contextIndices=new Map;modules=new Map;controllerComponents=new Map([["middleware",new Map],["guard",new Map],["pipe",new Map],["filter",new Map]]);handlerComponents=new Map([["middleware",new Map],["guard",new Map],["pipe",new Map],["filter",new Map]]);static fromRootModule($,_=new k){let W=new C;return W.captureModuleGraph($,_),W}hasController($){return this.controllerPaths.has($)}getControllerPath($){return this.controllerPaths.get($)||""}getControllerOptions($){let _=this.controllerOptions.get($);return _?{..._}:{}}getRoutes($){return(this.routes.get($)||[]).map((_)=>this.cloneRouteDefinition(_))}getParameters($){let _=this.parameters.get($);if(!_)return new Map;let W=new Map;for(let[Q,U]of _.entries())W.set(Q,U.map((X)=>({...X})));return W}getContextIndices($){return new Map(this.contextIndices.get($)||new Map)}getModuleOptions($){let _=this.modules.get($);if(!_)return;return{controllers:_.controllers?[..._.controllers]:void 0,services:_.services?[..._.services]:void 0,imports:_.imports?[..._.imports]:void 0}}getControllerComponents($,_){return[...this.controllerComponents.get($).get(_)||[]]}getHandlerComponents($,_){return[...this.handlerComponents.get($).get(_)||[]]}captureModuleGraph($,_){let W=new Set,Q=new Set,U=(X)=>{if(W.has(X))return;W.add(X);let Z=_.getModuleOptions(X);if(!Z)return;let J={controllers:Z.controllers?[...Z.controllers]:void 0,services:Z.services?[...Z.services]:void 0,imports:Z.imports?[...Z.imports]:void 0};this.modules.set(X,J);for(let Y of J.controllers||[])Q.add(Y);for(let Y of J.imports||[])U(Y)};U($);for(let X of Q)this.captureController(X,_)}captureController($,_){if(!_.hasController($))return;this.controllerPaths.set($,_.getControllerPath($)||""),this.controllerOptions.set($,{..._.getControllerOptions($)});let W=(_.getRoutes($)||[]).map((X)=>this.cloneRouteDefinition(X));this.routes.set($,W);let Q=_.getParameters($),U=new Map;for(let[X,Z]of Q.entries())U.set(X,(Z||[]).map((J)=>({...J})));this.parameters.set($,U),this.contextIndices.set($,new Map(_.getContextIndices($)||new Map));for(let X of["middleware","guard","pipe","filter"])this.controllerComponents.get(X).set($,[..._.getControllerComponents(X,$)||[]]);for(let X of W){let Z=`${$.name}:${String(X.handlerName)}`;for(let J of["middleware","guard","pipe","filter"])this.handlerComponents.get(J).set(Z,[..._.getHandlerComponents(J,Z)||[]])}}cloneRouteDefinition($){return{...$,version:Array.isArray($.version)?[...$.version]:$.version}}}class u{routes=[];registerRoute($){if(!$)throw Error("Route info is required");if(!$.controller)throw Error("Route controller is required");if(!$.handler)throw Error("Route handler is required");if(!$.method)throw Error("Route method is required");if(!$.fullPath)throw Error("Route fullPath is required");if(this.routes.some((W)=>W.fullPath===$.fullPath&&W.method.toUpperCase()===$.method.toUpperCase()))throw Error(`Duplicate route detected: ${$.method.toUpperCase()} ${$.fullPath} (${String($.controller)}.${String($.handler)})`);this.routes.push($)}getRoutes(){return this.routes}getRoutesByController($){return this.routes.filter((_)=>_.controller===$)}getRoutesByMethod($){return this.routes.filter((_)=>_.method.toUpperCase()===$.toUpperCase())}getRoutesByPath($){return this.routes.filter((_)=>$.test(_.fullPath))}clear(){this.routes.length=0}}class d{isService($){return B.isService($)}}class S{serviceRegistry;logger;debugDi;constructor($=new d,_=new A,W=!1){this.serviceRegistry=$;this.logger=_;this.debugDi=W}instances=new Map;emitLog($){if(!this.debugDi)return;this.logger.emit($)}resolve($){return this.resolveWithTracking($,new Set)}resolveWithTracking($,_){if(this.instances.has($))return this.emitLog({level:"debug",category:"di",message:`Resolved ${$.name} from DI cache`}),this.instances.get($);if(_.has($)){let X=[..._.keys(),$].map((Z)=>Z.name).join(" -> ");throw this.emitLog({level:"error",category:"di",message:`Circular dependency detected while resolving ${$.name}`,details:{cycle:X}}),Error(`Circular dependency detected: ${X}`)}_.add($),this.emitLog({level:"debug",category:"di",message:`Resolving ${$.name}`,details:{resolving:[..._].map((X)=>X.name)}});let W=Reflect.getMetadata("design:paramtypes",$)||[];if($.length>0&&W.length===0){if(!this.serviceRegistry.isService($))throw this.emitLog({level:"error",category:"di",message:`Cannot resolve ${$.name}: missing @Service() decorator`}),Error(`Cannot resolve ${$.name}: it is not decorated with @Service(). Did you forget to add @Service() to the class?`);throw this.emitLog({level:"error",category:"di",message:`Cannot resolve ${$.name}: missing constructor metadata`}),Error(`Cannot resolve dependencies for ${$.name}: constructor metadata is missing. Ensure 'reflect-metadata' is imported and 'emitDecoratorMetadata' is enabled.`)}let Q=W.map((X,Z)=>{if(!X||X===Object||X===Array||X===Function)throw this.emitLog({level:"error",category:"di",message:`Cannot resolve dependency at index ${Z} of ${$.name}`}),Error(`Cannot resolve dependency at index ${Z} of ${$.name}. Use concrete class types for constructor dependencies.`);return this.resolveWithTracking(X,new Set(_))}),U=new $(...Q);return this.instances.set($,U),this.emitLog({level:"debug",category:"di",message:`Created ${$.name} instance`,details:{dependencyCount:Q.length}}),U}register($,_){this.instances.set($,_)}has($){return this.instances.has($)}clear(){this.instances.clear()}}import{HTTPException as F$}from"hono/http-exception";class c extends Error{status;code;category;remediation;details;constructor($,_){super($);if(this.name="FrameworkError",this.status=_.status,this.code=_.code,this.category=_.category,this.remediation=_.remediation,this.details=_.details,_.cause!==void 0)this.cause=_.cause}}function w($,_,W){let Q=$ instanceof Error?$:Error(String($)),U=new Date().toISOString(),X=_.get("requestId"),Z=_.req.path;if(Q instanceof F$)return{response:{status:W?.status||Q.status,message:W?.title||Q.message,timestamp:U,path:Z,requestId:X,code:W?.code,details:W?.additionalDetails,...W?.detail&&{detail:W.detail}},status:W?.status||Q.status};if(Q instanceof c){let q=W?.status||Q.status||500;return{response:{status:q,message:W?.title||Q.message,timestamp:U,path:Z,requestId:X,code:W?.code||Q.code,details:{category:Q.category,remediation:Q.remediation,...Q.details,...W?.additionalDetails},...W?.detail&&{detail:W.detail}},status:q}}if(Q.statusCode||Q.status){let q=Q.statusCode||Q.status||500,j=W?.status||q;return{response:{status:j,message:W?.title||Q.message,timestamp:U,path:Z,requestId:X,code:W?.code||Q.name,details:W?.additionalDetails,...W?.detail&&{detail:W.detail}},status:j}}let J=W?.status||500;return{response:{status:J,message:W?.title||Q.message,timestamp:U,path:Z,requestId:X,code:W?.code||Q.name,details:W?.additionalDetails||{stack:Q.stack},...W?.detail&&{detail:W.detail}},status:J}}function O($){return(_="",W={})=>{return(Q,U,X)=>{let Z=Q.constructor;B.addRoute(Z,{path:_,method:$,handlerName:U,version:W.version,prefix:W.prefix})}}}function L($,_){let W=(Q,U)=>{if(Q===void 0)return U;return U.get(String(Q))};return(Q)=>{return(U,X,Z)=>{let J=U.constructor;if(!B.getParameters(J).size)B.setParameterMap(J,new Map);let Y=B.getParameters(J);if(!Y.has(X))Y.set(X,[]);let j=Reflect.getMetadata("design:paramtypes",U,X)?.[Z];if(Y.get(X).push({index:Z,name:$,data:Q,factory:_||W,metatype:j}),$==="context"){if(!B.getContextIndices(J).size)B.setContextIndices(J,new Map);B.getContextIndices(J).set(X,Z)}}}}class i{static handle(){return async($,_)=>{let{response:W,status:Q}=w($,_);return _.json(W,Q)}}}class p{static handle(){return async($)=>{return $.json({message:`Not Found - ${$.req.path}`},404)}}}var s=Symbol("VERSION_NEUTRAL");var f="__honest_controllerClass",I="__honest_handlerName",l="__honest.body.cache";class n{container;metadataRepository;logger;globalComponents=new Map([["middleware",new Set],["guard",new Set],["pipe",new Set],["filter",new Set]]);constructor($,_=new k,W=new A){this.container=$;this.metadataRepository=_;this.logger=W}setupGlobalComponents($){let _=$.components||{};if(_.middleware)this.registerGlobal("middleware",..._.middleware);if(_.guards)this.registerGlobal("guard",..._.guards);if(_.pipes)this.registerGlobal("pipe",..._.pipes);if(_.filters)this.registerGlobal("filter",..._.filters)}registerGlobal($,..._){_.forEach((W)=>{this.globalComponents.get($).add(W)})}getGlobal($){return this.globalComponents.get($)}getComponents($,_,W){let Q=`${_.name}:${String(W)}`,U=this.metadataRepository.getHandlerComponents($,Q),X=this.metadataRepository.getControllerComponents($,_);return[...Array.from(this.globalComponents.get($)||[]),...X,...U]}resolveMiddleware($){return $.map((_)=>{if(H(_)&&"use"in _)return _.use.bind(_);let W=this.container.resolve(_);return W.use.bind(W)})}getHandlerMiddleware($,_){let W=`${$.name}:${String(_)}`,Q=this.metadataRepository.getControllerComponents("middleware",$),U=this.metadataRepository.getHandlerComponents("middleware",W);return this.resolveMiddleware([...Q,...U])}getGlobalMiddleware(){let $=Array.from(this.globalComponents.get("middleware")||[]);return this.resolveMiddleware($)}resolveGuards($){return $.map((_)=>{if(H(_)&&"canActivate"in _)return _;return this.container.resolve(_)})}getHandlerGuards($,_){let W=this.getComponents("guard",$,_);return this.resolveGuards(W)}resolvePipes($){return $.map((_)=>{if(H(_)&&"transform"in _)return _;return this.container.resolve(_)})}getHandlerPipes($,_){let W=this.getComponents("pipe",$,_);return this.resolvePipes(W)}async executePipes($,_,W){let Q=$;for(let U of W)Q=await U.transform(Q,_);return Q}async handleException($,_){let W=_.get(f),Q=_.get(I);if(W&&Q){let J=this.metadataRepository.getHandlerComponents("filter",`${W.name}:${Q}`);if(J.length>0){let Y=await this.executeFilters(J,$,_);if(Y)return Y}}if(W){let J=this.metadataRepository.getControllerComponents("filter",W);if(J.length>0){let Y=await this.executeFilters(J,$,_);if(Y)return Y}}let U=Array.from(this.globalComponents.get("filter")||[]);if(U.length>0){let J=await this.executeFilters(U,$,_);if(J)return J}let{response:X,status:Z}=w($,_);return _.json(X,Z)}async executeFilters($,_,W){for(let Q of $){let U;if(H(Q)&&"catch"in Q)U=Q;else U=this.container.resolve(Q);try{let X=await U.catch(_,W);if(X!==void 0)return X}catch(X){let Z=U.constructor?.name||"UnknownFilter";this.logger.emit({level:"error",category:"errors",message:`Error in exception filter ${Z}`,details:{error:X instanceof Error?X.message:String(X)}});let{response:J,status:Y}=w(X,W);return W.json(J,Y)}}return}async registerModule($,_=new Set){if(_.has($))return[];_.add($);let W=this.metadataRepository.getModuleOptions($);if(!W)throw this.logger.emit({level:"error",category:"startup",message:`Module ${$.name} is not properly decorated with @Module()`}),Error(`Module ${$.name} is not properly decorated with @Module()`);let Q=[];if(W.imports&&W.imports.length>0)for(let U of W.imports){let X=await this.registerModule(U,_);Q.push(...X)}if(W.services&&W.services.length>0)for(let U of W.services)this.container.resolve(U);if(W.controllers&&W.controllers.length>0)Q.push(...W.controllers);return Q}}class a{async invoke({handler:$,args:_,context:W,contextIndex:Q}){let U=await $(..._);if(Q!==void 0)return U;if(U instanceof Response)return U;if(N(U))return W.json(null);if(R(U))return W.text(U);return W.json(U)}}class r{componentManager;constructor($){this.componentManager=$}async resolveArguments($){let{controllerName:_,handlerName:W,handlerArity:Q,handlerParams:U,handlerPipes:X,context:Z}=$,J=U.length>0?Math.max(...U.map((q)=>q.index)):-1,Y=Array(Math.max(Q,J+1));for(let q of U){if(typeof q.factory!=="function")throw Error(`Invalid parameter decorator metadata for ${_}.${String(W)}`);let j=await q.factory(q.data,Z),P=await this.componentManager.executePipes(j,{type:q.name,metatype:q.metatype,data:typeof q.data==="string"||typeof q.data>"u"?q.data:String(q.data)},X);Y[q.index]=P}return Y}}import{HTTPException as L$}from"hono/http-exception";class o{componentManager;parameterResolver;handlerInvoker;logger;debugPipeline;constructor($,_,W,Q=new A,U=!1){this.componentManager=$;this.parameterResolver=_;this.handlerInvoker=W;this.logger=Q;this.debugPipeline=U}async execute($){let{controllerClass:_,handlerName:W,handler:Q,handlerParams:U,handlerPipes:X,contextIndex:Z,context:J}=$;J.set(f,_),J.set(I,String(W));let Y=this.componentManager.getHandlerGuards(_,W);for(let j of Y)if(!await j.canActivate(J)){if(this.debugPipeline)this.logger.emit({level:"warn",category:"pipeline",message:`Guard rejected request at ${_.name}.${String(W)}`,details:{guard:j.constructor?.name||"UnknownGuard"}});throw new L$(403,{message:`Forbidden by ${j.constructor?.name||"UnknownGuard"} at ${_.name}.${String(W)}`})}let q=await this.parameterResolver.resolveArguments({controllerName:_.name,handlerName:W,handlerArity:Q.length,handlerParams:U,handlerPipes:X,context:J});if(this.debugPipeline)this.logger.emit({level:"debug",category:"pipeline",message:`Resolved handler arguments for ${_.name}.${String(W)}`,details:{guardCount:Y.length,parameterCount:U.length,pipeCount:X.length}});return this.handlerInvoker.invoke({handler:Q,args:q,context:J,contextIndex:Z})}}class t{hono;container;routeRegistry;componentManager;parameterResolver;pipelineExecutor;metadataRepository;logger;globalPrefix;globalVersion;constructor($,_,W,Q,U=new k,X=new A,Z={}){this.hono=$,this.container=_,this.routeRegistry=W,this.componentManager=Q,this.parameterResolver=new r(this.componentManager),this.logger=X,this.pipelineExecutor=new o(this.componentManager,this.parameterResolver,new a,this.logger,Boolean(Z.debugPipeline)),this.metadataRepository=U,this.globalPrefix=Z.prefix!==void 0?this.normalizePath(Z.prefix):void 0,this.globalVersion=Z.version,this.applyGlobalMiddleware()}applyGlobalMiddleware(){let $=this.componentManager.getGlobalMiddleware();for(let _ of $)this.hono.use("*",_)}normalizePath($){if(!R($))throw Error(`Invalid path: expected a string but received ${typeof $}. Check your @Controller() and route decorator arguments.`);return g($)}registerRouteHandler($,_,W,Q){if(W.length>0)this.hono.on($.toUpperCase(),[_],...W,Q);else this.hono.on($.toUpperCase(),[_],Q)}buildRoutePath($,_,W,Q){return g(`${$}${_}${W}${Q}`)}formatVersionSegment($){if(N($))return"";return $===s?"":`/v${String($)}`}async registerController($){if(!this.metadataRepository.hasController($))throw Error(`Controller ${$.name} is not decorated with @Controller()`);let _=this.metadataRepository.getControllerPath($)||"",W=this.metadataRepository.getControllerOptions($)||{},Q=this.metadataRepository.getRoutes($)||[],U=this.metadataRepository.getParameters($)||new Map,X=this.metadataRepository.getContextIndices($)||new Map,Z=this.normalizePath(_),J=this.container.resolve($),Y=W.prefix!==void 0?W.prefix:this.globalPrefix,q=W.version!==void 0?W.version:this.globalVersion;if(Q.length===0)throw Error(`Controller ${$.name} has no route handlers. Add HTTP method decorators like @Get()`);for(let j of Q){let{path:P,method:G,version:V,prefix:z}=j,D=z!==void 0?z:Y,T=!N(D)?this.normalizePath(D):"",E=V!==void 0?V:q,b=this.normalizePath(P);if(N(E)){this.registerRoute(J,j,U,X,$,T,"",Z,b,G);continue}if(E===s){this.registerRoute(J,j,U,X,$,T,"",Z,b,G),this.registerRoute(J,j,U,X,$,T,"/:version{v[0-9]+}",Z,b,G);continue}if(Array.isArray(E)){for(let K of E){let y=this.formatVersionSegment(K);this.registerRoute(J,j,U,X,$,T,y,Z,b,G)}continue}let v=this.formatVersionSegment(E);this.registerRoute(J,j,U,X,$,T,v,Z,b,G)}}registerRoute($,_,W,Q,U,X,Z,J,Y,q){let{handlerName:j}=_,P=this.buildRoutePath(X,Z,J,Y),G=$[j].bind($),V=W.get(j)||[],z=Q.get(j),D=this.componentManager.getHandlerMiddleware(U,j),T=this.componentManager.getHandlerPipes(U,j);this.routeRegistry.registerRoute({controller:U.name,handler:j,method:q,prefix:X,version:Z,route:J,path:Y,fullPath:P,parameters:V});let E=this.componentManager,b=this.pipelineExecutor,v=async(K)=>{try{return await b.execute({controllerClass:U,handlerName:j,handler:G,handlerParams:V,handlerPipes:T,contextIndex:z,context:K})}catch(y){return E.handleException(y,K)}};this.registerRouteHandler(q,P,D,v)}}class M{hono;container;context;routeRegistry;metadataRepository;componentManager;routeManager;logger;options;constructor($={},_=new k){this.options=H($)?$:{};let W=this.options.debug===!0||typeof this.options.debug==="object"&&Boolean(this.options.debug.pipeline),Q=this.options.debug===!0||typeof this.options.debug==="object"&&Boolean(this.options.debug.di);if(this.hono=new P$(this.options.hono),this.logger=this.options.logger||new m,this.container=this.options.container||new S(void 0,this.logger,Q),this.context=new h,this.routeRegistry=new u,this.metadataRepository=_,this.componentManager=new n(this.container,this.metadataRepository,this.logger),this.componentManager.setupGlobalComponents(this.options),this.setupErrorHandlers(),this.routeManager=new t(this.hono,this.container,this.routeRegistry,this.componentManager,this.metadataRepository,this.logger,{prefix:this.options.routing?.prefix,version:this.options.routing?.version,debugPipeline:W}),this.options.deprecations?.printPreV1Warning)this.logger.emit({level:"warn",category:"deprecations",message:"Pre-v1 warning: APIs may change before 1.0.0."})}setupErrorHandlers(){this.hono.notFound(this.options.notFound||p.handle()),this.hono.onError(this.options.onError||i.handle())}shouldEmitRouteDiagnostics(){let $=this.options.debug;return $===!0||typeof $==="object"&&Boolean($.routes)}emitStartupGuide($,_){_$(this.logger,this.options.startupGuide,$,_)}async register($){let _=await this.componentManager.registerModule($),W=this.shouldEmitRouteDiagnostics();for(let Q of _){let U=Date.now(),X=this.routeRegistry.getRoutes().length;try{if(await this.routeManager.registerController(Q),W)this.logger.emit({level:"info",category:"routes",message:"Registered controller routes",details:{controller:Q.name,routeCountAdded:this.routeRegistry.getRoutes().length-X,registrationDurationMs:Date.now()-U}})}catch(Z){if(W)this.logger.emit({level:"error",category:"routes",message:"Failed to register controller routes",details:{controller:Q.name,registrationDurationMs:Date.now()-U,errorMessage:Z instanceof Error?Z.message:String(Z)}});throw Z}}return this}static async create($,_={}){let W=Date.now(),Q=C.fromRootModule($),U=new M(_,Q),X=J$(_.plugins),Z=U.getContext(),J=_.debug,Y=J===!0||typeof J==="object"&&J.plugins,q=J===!0||typeof J==="object"&&J.routes,j=J===!0||typeof J==="object"&&(J.startup||q),P=!1;try{if(Y&&X.length>0)U.logger.emit({level:"info",category:"plugins",message:`Plugin order: ${X.map(({name:V})=>V).join(" -> ")}`});for(let{plugin:V,preProcessors:z}of X){V.logger=U.logger;for(let D of z)await D(U,U.hono,Z);if(V.beforeModulesRegistered)await V.beforeModulesRegistered(U,U.hono)}await U.register($);let G=U.getRoutes();if(j)U.logger.emit({level:"info",category:"startup",message:`Application registered ${G.length} route(s)`,details:{routeCount:G.length,rootModule:$.name}});if(_.strict?.requireRoutes&&G.length===0){P=!0,U.logger.emit({level:"error",category:"startup",message:"Strict mode failed: no routes were registered",details:{rootModule:$.name,requireRoutes:!0,startupDurationMs:Date.now()-W}});let V=Error("Strict mode: no routes were registered. Check your module/controller decorators.");throw U.emitStartupGuide(V,$),V}if(q)U.logger.emit({level:"info",category:"routes",message:"Registered routes",details:{routes:G.map((V)=>`${V.method.toUpperCase()} ${V.fullPath}`)}});for(let{plugin:V,postProcessors:z}of X){if(V.afterModulesRegistered)await V.afterModulesRegistered(U,U.hono);for(let D of z)await D(U,U.hono,Z)}if(j)U.logger.emit({level:"info",category:"startup",message:"Application startup completed",details:{rootModule:$.name,pluginCount:X.length,routeCount:G.length,startupDurationMs:Date.now()-W}});return{app:U,hono:U.getApp()}}catch(G){if(U.emitStartupGuide(G,$),j&&!P)U.logger.emit({level:"error",category:"startup",message:"Application startup failed",details:{rootModule:$.name,startupDurationMs:Date.now()-W,errorMessage:G instanceof Error?G.message:String(G)}});throw G}}getApp(){return this.hono}getContainer(){return this.container}getContext(){return this.context}getRoutes(){return this.routeRegistry.getRoutes()}}import{html as F,raw as e}from"hono/html";var A$={type:"website",locale:"en_US"},$$=($)=>{if(!$)return"";return Object.entries($).map(([_,W])=>{if(typeof W==="boolean")return W?_:"";let Q=String(W).replace(/"/g,""");return`${_}="${Q}"`}).filter(Boolean).join(" ")},YW=($)=>{let _={...A$,...$};return F`
|
|
1
|
+
import"reflect-metadata";import{Hono as L$}from"hono";function q$($){let _=new Set;if(_.add("Check module wiring: root module imports, controllers, and services should be registered correctly."),$.includes("not decorated with @Controller()"))_.add("Add @Controller() to the class or remove it from module.controllers.");if($.includes("has no route handlers"))_.add("Add at least one HTTP method decorator such as @Get() or @Post() in the controller.");if($.includes("not decorated with @Service()"))_.add("Add @Service() to injectable classes used in constructor dependencies.");if($.includes("constructor metadata is missing")||$.includes("reflect-metadata"))_.add("Import 'reflect-metadata' in your entry file and enable 'emitDecoratorMetadata' in tsconfig.");if($.includes("Strict mode: no routes were registered"))_.add("Disable strict.requireRoutes for empty modules, or add a controller with at least one route.");return[..._]}function $$($,_,W,Q){if(!_)return;let U=typeof _==="object"&&Boolean(_.verbose),X=W instanceof Error?W.message:String(W),Z=q$(X);if($.emit({level:"warn",category:"startup",message:"Startup guide",details:{rootModule:Q.name,errorMessage:X,hints:Z,verbose:U}}),U)$.emit({level:"warn",category:"startup",message:"Startup guide (verbose)",details:{steps:["Verify decorators are present for controllers/services used by DI and routing.","Ensure 'reflect-metadata' is imported once at entry and 'emitDecoratorMetadata' is enabled.","Enable debug.startup for extra startup diagnostics and timing details."]}})}var z$=($)=>typeof $>"u",S=($)=>$===null||typeof $>"u",k=($)=>$!==null&&typeof $==="object",H$=($)=>{if(!k($))return!1;let _=Object.getPrototypeOf($);if(_===null)return!0;let W=Object.prototype.hasOwnProperty.call(_,"constructor")&&_.constructor;return typeof W==="function"&&W instanceof W&&Function.prototype.toString.call(W)===Function.prototype.toString.call(Object)},_$=($)=>typeof $==="function",R=($)=>typeof $==="string",k$=($)=>typeof $==="number",D$=($)=>$.length===0,K$=($)=>typeof $==="symbol",T$=($)=>typeof $==="string"?$.charAt(0)!=="/"?"/"+$:$:"",g=($)=>$?$.startsWith("/")?("/"+$.replace(/\/+$/,"")).replace(/\/+/g,"/"):"/"+$.replace(/\/+$/,""):"/",O$=($)=>$.endsWith("/")?$.slice(0,-1):$,W$=($)=>{return _$($)&&!S($.prototype)&&!_$($.prototype)&&Object.getOwnPropertyNames($.prototype).length>=1};var Q$="AnonymousPlugin";function U$($){if(W$($))return new $;return $}function X$($,_,W){let Q=W||$.meta?.name||$.constructor?.name;if(!Q||Q===Q$)return`${Q$}#${_+1}`;return Q}function G$($,_){if($&&typeof $==="object"&&"plugin"in $){let Q=$,U=U$(Q.plugin),X=X$(U,_,Q.name);return{plugin:U,name:X,preProcessors:Q.preProcessors??[],postProcessors:Q.postProcessors??[]}}let W=U$($);return{plugin:W,name:X$(W,_),preProcessors:[],postProcessors:[]}}function Z$($){return($??[]).map((_,W)=>G$(_,W))}class h{store=new Map;get($){return this.store.get($)}set($,_){this.store.set($,_)}has($){return this.store.has($)}delete($){return this.store.delete($)}keys(){return this.store.keys()}}class u{emit($){let _=`[HonestJS:${$.category}]`,W=$.details?[_,$.message,$.details]:[_,$.message];switch($.level){case"debug":case"info":console.info(...W);break;case"warn":console.warn(...W);break;case"error":console.error(...W);break}}}class P{emit($){}}class Y{static routes=new Map;static controllers=new Map;static controllerOptions=new Map;static services=new Set;static modules=new Map;static parameters=new Map;static contextIndices=new Map;static controller=new Map([["middleware",new Map],["guard",new Map],["pipe",new Map],["filter",new Map]]);static handler=new Map([["middleware",new Map],["guard",new Map],["pipe",new Map],["filter",new Map]]);static getRoutes($){return this.routes.get($)||[]}static setRoutes($,_){this.routes.set($,_)}static addRoute($,_){if(!this.routes.has($))this.routes.set($,[]);this.routes.get($).push(_)}static getControllerPath($){return this.controllers.get($)||""}static hasController($){return this.controllers.has($)}static setControllerPath($,_){this.controllers.set($,_)}static getControllerOptions($){return this.controllerOptions.get($)||{}}static setControllerOptions($,_){this.controllerOptions.set($,_)}static isService($){return this.services.has($)}static addService($){this.services.add($)}static getAllServices(){return this.services}static getModuleOptions($){return this.modules.get($)}static setModuleOptions($,_){this.modules.set($,_)}static getParameters($){return this.parameters.get($)||new Map}static setParameterMap($,_){this.parameters.set($,_)}static getContextIndices($){return this.contextIndices.get($)||new Map}static setContextIndices($,_){this.contextIndices.set($,_)}static registerController($,_,W){let Q=this.controller.get($);if(!Q.has(_))Q.set(_,[]);Q.get(_).push(W)}static getController($,_){return this.controller.get($).get(_)||[]}static registerHandler($,_,W,Q){let U=this.handler.get($);if(!U.has(_))U.set(_,new Map);let X=U.get(_);if(!X.has(W))X.set(W,[]);X.get(W).push(Q)}static getHandler($,_,W){let U=this.handler.get($).get(_);if(!U)return[];return U.get(W)||[]}static clearHandlerComponents(){for(let $ of this.handler.values()){for(let _ of $.values())_.clear();$.clear()}}static clear(){this.routes.clear(),this.controllers.clear(),this.controllerOptions.clear(),this.services.clear(),this.modules.clear(),this.parameters.clear(),this.contextIndices.clear();for(let $ of this.controller.values())$.clear();for(let $ of this.handler.values()){for(let _ of $.values())_.clear();$.clear()}}}class C{controllerPaths=new Map;controllerOptions=new Map;routes=new Map;parameters=new Map;contextIndices=new Map;modules=new Map;controllerComponents=new Map([["middleware",new Map],["guard",new Map],["pipe",new Map],["filter",new Map]]);handlerComponents=new Map([["middleware",new Map],["guard",new Map],["pipe",new Map],["filter",new Map]]);static fromRootModule($){let _=new C;return _.captureModuleGraph($),_}hasController($){return this.controllerPaths.has($)}getControllerPath($){return this.controllerPaths.get($)||""}getControllerOptions($){let _=this.controllerOptions.get($);return _?{..._}:{}}getRoutes($){return(this.routes.get($)||[]).map((_)=>this.cloneRouteDefinition(_))}getParameters($){let _=this.parameters.get($);if(!_)return new Map;let W=new Map;for(let[Q,U]of _.entries())W.set(Q,U.map((X)=>({...X})));return W}getContextIndices($){return new Map(this.contextIndices.get($)||new Map)}getModuleOptions($){let _=this.modules.get($);if(!_)return;return{controllers:_.controllers?[..._.controllers]:void 0,services:_.services?[..._.services]:void 0,imports:_.imports?[..._.imports]:void 0}}getControllerComponents($,_){return[...this.controllerComponents.get($).get(_)||[]]}getHandlerComponents($,_,W){let U=this.handlerComponents.get($).get(_);if(!U)return[];return[...U.get(W)||[]]}captureModuleGraph($){let _=new Set,W=new Set,Q=(U)=>{if(_.has(U))return;_.add(U);let X=Y.getModuleOptions(U);if(!X)return;let Z={controllers:X.controllers?[...X.controllers]:void 0,services:X.services?[...X.services]:void 0,imports:X.imports?[...X.imports]:void 0};this.modules.set(U,Z);for(let J of Z.controllers||[])W.add(J);for(let J of Z.imports||[])Q(J)};Q($);for(let U of W)this.captureController(U)}captureController($){if(!Y.hasController($))return;this.controllerPaths.set($,Y.getControllerPath($)||""),this.controllerOptions.set($,{...Y.getControllerOptions($)});let _=(Y.getRoutes($)||[]).map((U)=>this.cloneRouteDefinition(U));this.routes.set($,_);let W=Y.getParameters($),Q=new Map;for(let[U,X]of W.entries())Q.set(U,(X||[]).map((Z)=>({...Z})));this.parameters.set($,Q),this.contextIndices.set($,new Map(Y.getContextIndices($)||new Map));for(let U of["middleware","guard","pipe","filter"])this.controllerComponents.get(U).set($,[...Y.getController(U,$)||[]]);for(let U of _)for(let X of["middleware","guard","pipe","filter"]){let Z=this.handlerComponents.get(X);if(!Z.has($))Z.set($,new Map);Z.get($).set(U.handlerName,[...Y.getHandler(X,$,U.handlerName)])}}cloneRouteDefinition($){return{...$,version:Array.isArray($.version)?[...$.version]:$.version}}}class m{routes=[];registerRoute($){if(!$)throw Error("Route info is required");if(!$.controller)throw Error("Route controller is required");if(!$.handler)throw Error("Route handler is required");if(!$.method)throw Error("Route method is required");if(!$.fullPath)throw Error("Route fullPath is required");if(this.routes.some((W)=>W.fullPath===$.fullPath&&W.method.toUpperCase()===$.method.toUpperCase()))throw Error(`Duplicate route detected: ${$.method.toUpperCase()} ${$.fullPath} (${String($.controller)}.${String($.handler)})`);this.routes.push($)}getRoutes(){return this.routes}getRoutesByController($){return this.routes.filter((_)=>_.controller===$)}getRoutesByMethod($){return this.routes.filter((_)=>_.method.toUpperCase()===$.toUpperCase())}getRoutesByPath($){return this.routes.filter((_)=>$.test(_.fullPath))}clear(){this.routes.length=0}}class d{isService($){return Y.isService($)}}class b{serviceRegistry;logger;debugDi;constructor($=new d,_=new P,W=!1){this.serviceRegistry=$;this.logger=_;this.debugDi=W}instances=new Map;emitLog($){if(!this.debugDi)return;this.logger.emit($)}resolve($){return this.resolveWithTracking($,new Set)}resolveWithTracking($,_){if(this.instances.has($))return this.emitLog({level:"debug",category:"di",message:`Resolved ${$.name} from DI cache`}),this.instances.get($);if(_.has($)){let X=[..._.keys(),$].map((Z)=>Z.name).join(" -> ");throw this.emitLog({level:"error",category:"di",message:`Circular dependency detected while resolving ${$.name}`,details:{cycle:X}}),Error(`Circular dependency detected: ${X}`)}_.add($),this.emitLog({level:"debug",category:"di",message:`Resolving ${$.name}`,details:{resolving:[..._].map((X)=>X.name)}});let W=Reflect.getMetadata("design:paramtypes",$)||[];if($.length>0&&W.length===0){if(!this.serviceRegistry.isService($))throw this.emitLog({level:"error",category:"di",message:`Cannot resolve ${$.name}: missing @Service() decorator`}),Error(`Cannot resolve ${$.name}: it is not decorated with @Service(). Did you forget to add @Service() to the class?`);throw this.emitLog({level:"error",category:"di",message:`Cannot resolve ${$.name}: missing constructor metadata`}),Error(`Cannot resolve dependencies for ${$.name}: constructor metadata is missing. Ensure 'reflect-metadata' is imported and 'emitDecoratorMetadata' is enabled.`)}let Q=W.map((X,Z)=>{if(!X||X===Object||X===Array||X===Function)throw this.emitLog({level:"error",category:"di",message:`Cannot resolve dependency at index ${Z} of ${$.name}`}),Error(`Cannot resolve dependency at index ${Z} of ${$.name}. Use concrete class types for constructor dependencies.`);return this.resolveWithTracking(X,new Set(_))}),U=new $(...Q);return this.instances.set($,U),this.emitLog({level:"debug",category:"di",message:`Created ${$.name} instance`,details:{dependencyCount:Q.length}}),U}register($,_){this.instances.set($,_)}has($){return this.instances.has($)}clear(){this.instances.clear()}}import{HTTPException as V$}from"hono/http-exception";class E extends Error{status;code;category;remediation;details;constructor($,_){super($);if(this.name="FrameworkError",this.status=_.status,this.code=_.code,this.category=_.category,this.remediation=_.remediation,this.details=_.details,_.cause!==void 0)this.cause=_.cause}}function w($,_,W){let Q=$ instanceof Error?$:Error(String($)),U=new Date().toISOString(),X=_.get("requestId"),Z=_.req.path;if(Q instanceof V$)return{response:{status:W?.status||Q.status,message:W?.title||Q.message,timestamp:U,path:Z,requestId:X,code:W?.code,details:W?.additionalDetails,...W?.detail&&{detail:W.detail}},status:W?.status||Q.status};if(Q instanceof E){let G=W?.status||Q.status||500;return{response:{status:G,message:W?.title||Q.message,timestamp:U,path:Z,requestId:X,code:W?.code||Q.code,details:{category:Q.category,remediation:Q.remediation,...Q.details,...W?.additionalDetails},...W?.detail&&{detail:W.detail}},status:G}}if(Q.statusCode||Q.status){let G=Q.statusCode||Q.status||500,B=W?.status||G;return{response:{status:B,message:W?.title||Q.message,timestamp:U,path:Z,requestId:X,code:W?.code||Q.name,details:W?.additionalDetails,...W?.detail&&{detail:W.detail}},status:B}}let J=W?.status||500;return{response:{status:J,message:W?.title||Q.message,timestamp:U,path:Z,requestId:X,code:W?.code||Q.name,details:W?.additionalDetails||{stack:Q.stack},...W?.detail&&{detail:W.detail}},status:J}}function D($){return(_="",W={})=>{return(Q,U,X)=>{let Z=Q.constructor;Y.addRoute(Z,{path:_,method:$,handlerName:U,version:W.version,prefix:W.prefix})}}}function A($,_){let W=(Q,U)=>{if(Q===void 0)return U;return U.get(String(Q))};return(Q)=>{return(U,X,Z)=>{let J=U.constructor;if(!Y.getParameters(J).size)Y.setParameterMap(J,new Map);let j=Y.getParameters(J);if(!j.has(X))j.set(X,[]);let B=Reflect.getMetadata("design:paramtypes",U,X)?.[Z];if(j.get(X).push({index:Z,name:$,data:Q,factory:_||W,metatype:B}),$==="context"){if(!Y.getContextIndices(J).size)Y.setContextIndices(J,new Map);Y.getContextIndices(J).set(X,Z)}}}}class c{static handle(){return async($,_)=>{let{response:W,status:Q}=w($,_);return _.json(W,Q)}}}class i{static handle(){return async($)=>{return $.json({message:`Not Found - ${$.req.path}`},404)}}}var p=Symbol("VERSION_NEUTRAL");var f="__honest_controllerClass",I="__honest_handlerName",s="__honest.body.cache";class l{container;metadataRepository;logger;globalComponents=new Map([["middleware",new Set],["guard",new Set],["pipe",new Set],["filter",new Set]]);constructor($,_,W=new P){this.container=$;this.metadataRepository=_;this.logger=W}setupGlobalComponents($){let _=$.components||{};if(_.middleware)this.registerGlobal("middleware",..._.middleware);if(_.guards)this.registerGlobal("guard",..._.guards);if(_.pipes)this.registerGlobal("pipe",..._.pipes);if(_.filters)this.registerGlobal("filter",..._.filters)}registerGlobal($,..._){_.forEach((W)=>{this.globalComponents.get($).add(W)})}getGlobal($){return this.globalComponents.get($)}getComponents($,_,W){let Q=this.metadataRepository.getHandlerComponents($,_,W),U=this.metadataRepository.getControllerComponents($,_);return[...Array.from(this.globalComponents.get($)||[]),...U,...Q]}resolveMiddleware($){return $.map((_)=>{if(k(_)&&"use"in _)return _.use.bind(_);let W=this.container.resolve(_);return W.use.bind(W)})}getHandlerMiddleware($,_){let W=this.metadataRepository.getControllerComponents("middleware",$),Q=this.metadataRepository.getHandlerComponents("middleware",$,_);return this.resolveMiddleware([...W,...Q])}getGlobalMiddleware(){let $=Array.from(this.globalComponents.get("middleware")||[]);return this.resolveMiddleware($)}resolveGuards($){return $.map((_)=>{if(k(_)&&"canActivate"in _)return _;return this.container.resolve(_)})}getHandlerGuards($,_){let W=this.getComponents("guard",$,_);return this.resolveGuards(W)}resolvePipes($){return $.map((_)=>{if(k(_)&&"transform"in _)return _;return this.container.resolve(_)})}getHandlerPipes($,_){let W=this.getComponents("pipe",$,_);return this.resolvePipes(W)}async executePipes($,_,W){let Q=$;for(let U of W)Q=await U.transform(Q,_);return Q}async handleException($,_){let W=$ instanceof Error?$:Error(String($)),Q=_.get(f),U=_.get(I);if(Q&&U){let j=this.metadataRepository.getHandlerComponents("filter",Q,U);if(j.length>0){let G=await this.executeFilters(j,W,_);if(G)return G}}if(Q){let j=this.metadataRepository.getControllerComponents("filter",Q);if(j.length>0){let G=await this.executeFilters(j,W,_);if(G)return G}}let X=Array.from(this.globalComponents.get("filter")||[]);if(X.length>0){let j=await this.executeFilters(X,W,_);if(j)return j}let{response:Z,status:J}=w(W,_);return _.json(Z,J)}async executeFilters($,_,W){for(let Q of $){let U;if(k(Q)&&"catch"in Q)U=Q;else U=this.container.resolve(Q);try{let X=await U.catch(_,W);if(X!==void 0)return X}catch(X){let Z=U.constructor?.name||"UnknownFilter";this.logger.emit({level:"error",category:"errors",message:`Error in exception filter ${Z}`,details:{error:X instanceof Error?X.message:String(X)}});let{response:J,status:j}=w(X,W);return W.json(J,j)}}return}async registerModule($,_=new Set){if(_.has($))return[];_.add($);let W=this.metadataRepository.getModuleOptions($);if(!W)throw this.logger.emit({level:"error",category:"startup",message:`Module ${$.name} is not properly decorated with @Module()`}),Error(`Module ${$.name} is not properly decorated with @Module()`);let Q=[];if(W.imports&&W.imports.length>0)for(let U of W.imports){let X=await this.registerModule(U,_);Q.push(...X)}if(W.services&&W.services.length>0)for(let U of W.services)this.container.resolve(U);if(W.controllers&&W.controllers.length>0)Q.push(...W.controllers);return Q}}class n{async invoke({handler:$,args:_,context:W,contextIndex:Q}){let U=await $(..._);if(Q!==void 0)return U;if(U instanceof Response)return U;if(S(U))return W.json(null);if(R(U))return W.text(U);try{return W.json(U)}catch(X){throw new E("Handler return value could not be serialized as JSON.",{status:500,code:"RESPONSE_SERIALIZATION_FAILED",category:"pipeline",remediation:"Return JSON-serializable values from handlers or map custom values in a filter before returning.",details:{handlerResultType:typeof U},cause:X})}}}class a{componentManager;logger;debugPipeline;constructor($,_=new P,W=!1){this.componentManager=$;this.logger=_;this.debugPipeline=W}async resolveArguments($){let{controllerName:_,handlerName:W,handlerArity:Q,handlerParams:U,handlerPipes:X,context:Z}=$,J=U.length>0?Math.max(...U.map((B)=>B.index)):-1,j=Array(Math.max(Q,J+1)),G=new Set(U.map((B)=>B.index));if(this.debugPipeline&&J>=0){let B=[];for(let q=0;q<=J;q++)if(!G.has(q))B.push(q);let L=J>=Q;if(B.length>0||L)this.logger.emit({level:"warn",category:"pipeline",message:`Potential parameter binding mismatch at ${_}.${String(W)}`,details:{handlerArity:Q,maxDecoratorIndex:J,sparseIndices:B,handlerParamCount:U.length}})}for(let B of U){if(typeof B.factory!=="function")throw Error(`Invalid parameter decorator metadata for ${_}.${String(W)}`);let L=await B.factory(B.data,Z),q=await this.componentManager.executePipes(L,{type:B.name,metatype:B.metatype,data:typeof B.data==="string"||typeof B.data>"u"?B.data:String(B.data)},X);j[B.index]=q}return j}}import{HTTPException as F$}from"hono/http-exception";class r{componentManager;parameterResolver;handlerInvoker;logger;debugPipeline;constructor($,_,W,Q=new P,U=!1){this.componentManager=$;this.parameterResolver=_;this.handlerInvoker=W;this.logger=Q;this.debugPipeline=U}async execute($){let{controllerClass:_,handlerName:W,handler:Q,handlerParams:U,handlerPipes:X,contextIndex:Z,context:J}=$;J.set(f,_),J.set(I,String(W));let j=this.componentManager.getHandlerGuards(_,W);for(let B of j)if(!await B.canActivate(J)){if(this.debugPipeline)this.logger.emit({level:"warn",category:"pipeline",message:`Guard rejected request at ${_.name}.${String(W)}`,details:{guard:B.constructor?.name||"UnknownGuard"}});throw new F$(403,{message:`Forbidden by ${B.constructor?.name||"UnknownGuard"} at ${_.name}.${String(W)}`})}let G=await this.parameterResolver.resolveArguments({controllerName:_.name,handlerName:W,handlerArity:Q.length,handlerParams:U,handlerPipes:X,context:J});if(this.debugPipeline)this.logger.emit({level:"debug",category:"pipeline",message:`Resolved handler arguments for ${_.name}.${String(W)}`,details:{guardCount:j.length,parameterCount:U.length,pipeCount:X.length}});return this.handlerInvoker.invoke({handler:Q,args:G,context:J,contextIndex:Z})}}class o{hono;container;routeRegistry;componentManager;parameterResolver;pipelineExecutor;metadataRepository;logger;globalPrefix;globalVersion;constructor($,_,W,Q,U,X=new P,Z={}){this.hono=$,this.container=_,this.routeRegistry=W,this.componentManager=Q,this.logger=X,this.parameterResolver=new a(this.componentManager,this.logger,Boolean(Z.debugPipeline)),this.pipelineExecutor=new r(this.componentManager,this.parameterResolver,new n,this.logger,Boolean(Z.debugPipeline)),this.metadataRepository=U,this.globalPrefix=Z.prefix!==void 0?this.normalizePath(Z.prefix):void 0,this.globalVersion=Z.version,this.applyGlobalMiddleware()}applyGlobalMiddleware(){let $=this.componentManager.getGlobalMiddleware();for(let _ of $)this.hono.use("*",_)}normalizePath($){if(!R($))throw Error(`Invalid path: expected a string but received ${typeof $}. Check your @Controller() and route decorator arguments.`);return g($)}registerRouteHandler($,_,W,Q){if(W.length>0)this.hono.on($.toUpperCase(),[_],...W,Q);else this.hono.on($.toUpperCase(),[_],Q)}buildRoutePath($,_,W,Q){return g(`${$}${_}${W}${Q}`)}formatVersionSegment($){if(S($))return"";return $===p?"":`/v${String($)}`}async registerController($){if(!this.metadataRepository.hasController($))throw Error(`Controller ${$.name} is not decorated with @Controller()`);let _=this.metadataRepository.getControllerPath($)||"",W=this.metadataRepository.getControllerOptions($)||{},Q=this.metadataRepository.getRoutes($)||[],U=this.metadataRepository.getParameters($)||new Map,X=this.metadataRepository.getContextIndices($)||new Map,Z=this.normalizePath(_),J=this.container.resolve($),j=W.prefix!==void 0?W.prefix:this.globalPrefix,G=W.version!==void 0?W.version:this.globalVersion;if(Q.length===0)throw Error(`Controller ${$.name} has no route handlers. Add HTTP method decorators like @Get()`);for(let B of Q){let{path:L,method:q,version:V,prefix:z}=B,H=z!==void 0?z:j,K=!S(H)?this.normalizePath(H):"",T=V!==void 0?V:G,O=this.normalizePath(L);if(S(T)){this.registerRoute(J,B,U,X,$,K,"",Z,O,q);continue}if(T===p){this.registerRoute(J,B,U,X,$,K,"",Z,O,q),this.registerRoute(J,B,U,X,$,K,"/:version{v[0-9]+}",Z,O,q);continue}if(Array.isArray(T)){for(let N of T){let y=this.formatVersionSegment(N);this.registerRoute(J,B,U,X,$,K,y,Z,O,q)}continue}let v=this.formatVersionSegment(T);this.registerRoute(J,B,U,X,$,K,v,Z,O,q)}}registerRoute($,_,W,Q,U,X,Z,J,j,G){let{handlerName:B}=_,L=this.buildRoutePath(X,Z,J,j),q=$[B].bind($),V=W.get(B)||[],z=Q.get(B),H=this.componentManager.getHandlerMiddleware(U,B),K=this.componentManager.getHandlerPipes(U,B);this.routeRegistry.registerRoute({controller:U.name,handler:B,method:G,prefix:X,version:Z,route:J,path:j,fullPath:L,parameters:V});let T=this.componentManager,O=this.pipelineExecutor,v=async(N)=>{try{return await O.execute({controllerClass:U,handlerName:B,handler:q,handlerParams:V,handlerPipes:K,contextIndex:z,context:N})}catch(y){return T.handleException(y,N)}};this.registerRouteHandler(G,L,H,v)}}class M{hono;container;context;routeRegistry;metadataRepository;componentManager;routeManager;logger;options;constructor($={},_){this.options=k($)?$:{};let W=this.options.debug===!0||typeof this.options.debug==="object"&&Boolean(this.options.debug.pipeline),Q=this.options.debug===!0||typeof this.options.debug==="object"&&Boolean(this.options.debug.di);if(this.hono=new L$(this.options.hono),this.logger=this.options.logger||new u,this.container=this.options.container||new b(void 0,this.logger,Q),this.context=new h,this.routeRegistry=new m,this.metadataRepository=_,this.componentManager=new l(this.container,this.metadataRepository,this.logger),this.componentManager.setupGlobalComponents(this.options),this.setupErrorHandlers(),this.routeManager=new o(this.hono,this.container,this.routeRegistry,this.componentManager,this.metadataRepository,this.logger,{prefix:this.options.routing?.prefix,version:this.options.routing?.version,debugPipeline:W}),this.options.deprecations?.printPreV1Warning)this.logger.emit({level:"warn",category:"deprecations",message:"Pre-v1 warning: APIs may change before 1.0.0."})}setupErrorHandlers(){this.hono.notFound(this.options.notFound||i.handle()),this.hono.onError(this.options.onError||c.handle())}shouldEmitRouteDiagnostics(){let $=this.options.debug;return $===!0||typeof $==="object"&&Boolean($.routes)}emitStartupGuide($,_){$$(this.logger,this.options.startupGuide,$,_)}async register($){let _=await this.componentManager.registerModule($),W=this.shouldEmitRouteDiagnostics();for(let Q of _){let U=Date.now(),X=this.routeRegistry.getRoutes().length;try{if(await this.routeManager.registerController(Q),W)this.logger.emit({level:"info",category:"routes",message:"Registered controller routes",details:{controller:Q.name,routeCountAdded:this.routeRegistry.getRoutes().length-X,registrationDurationMs:Date.now()-U}})}catch(Z){if(W)this.logger.emit({level:"error",category:"routes",message:"Failed to register controller routes",details:{controller:Q.name,registrationDurationMs:Date.now()-U,errorMessage:Z instanceof Error?Z.message:String(Z)}});throw Z}}return this}static async create($,_={}){let W=Date.now(),Q=C.fromRootModule($),U=new M(_,Q),X=Z$(_.plugins),Z=U.getContext(),J=_.debug,j=J===!0||typeof J==="object"&&J.plugins,G=J===!0||typeof J==="object"&&J.routes,B=J===!0||typeof J==="object"&&(J.startup||G),L=!1;try{if(j&&X.length>0)U.logger.emit({level:"info",category:"plugins",message:`Plugin order: ${X.map(({name:V})=>V).join(" -> ")}`});for(let{plugin:V,preProcessors:z}of X){V.logger=U.logger;for(let H of z)await H(U,U.hono,Z);if(V.beforeModulesRegistered)await V.beforeModulesRegistered(U,U.hono)}await U.register($);let q=U.getRoutes();if(B)U.logger.emit({level:"info",category:"startup",message:`Application registered ${q.length} route(s)`,details:{routeCount:q.length,rootModule:$.name}});if(_.strict?.requireRoutes&&q.length===0){L=!0,U.logger.emit({level:"error",category:"startup",message:"Strict mode failed: no routes were registered",details:{rootModule:$.name,requireRoutes:!0,startupDurationMs:Date.now()-W}});let V=Error("Strict mode: no routes were registered. Check your module/controller decorators.");throw U.emitStartupGuide(V,$),V}if(G)U.logger.emit({level:"info",category:"routes",message:"Registered routes",details:{routes:q.map((V)=>`${V.method.toUpperCase()} ${V.fullPath}`)}});for(let{plugin:V,postProcessors:z}of X){if(V.afterModulesRegistered)await V.afterModulesRegistered(U,U.hono);for(let H of z)await H(U,U.hono,Z)}if(B)U.logger.emit({level:"info",category:"startup",message:"Application startup completed",details:{rootModule:$.name,pluginCount:X.length,routeCount:q.length,startupDurationMs:Date.now()-W}});return{app:U,hono:U.getApp()}}catch(q){if(U.emitStartupGuide(q,$),B&&!L)U.logger.emit({level:"error",category:"startup",message:"Application startup failed",details:{rootModule:$.name,startupDurationMs:Date.now()-W,errorMessage:q instanceof Error?q.message:String(q)}});throw q}}getApp(){return this.hono}getContainer(){return this.container}getContext(){return this.context}getRoutes(){return this.routeRegistry.getRoutes()}}import{html as F,raw as t}from"hono/html";var P$={type:"website",locale:"en_US"},e=($)=>{if(!$)return"";return Object.entries($).map(([_,W])=>{if(typeof W==="boolean")return W?_:"";let Q=String(W).replace(/"/g,""");return`${_}="${Q}"`}).filter(Boolean).join(" ")},BW=($)=>{let _={...P$,...$};return F`
|
|
2
2
|
<!DOCTYPE html>
|
|
3
|
-
<html lang="${_.locale?.split("_")[0]||"en"}" ${e(
|
|
4
|
-
<head ${e(
|
|
3
|
+
<html lang="${_.locale?.split("_")[0]||"en"}" ${t(e(_.htmlAttributes))}>
|
|
4
|
+
<head ${t(e(_.headAttributes))}>
|
|
5
5
|
<meta charset="UTF-8" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
${_.csp?F`<meta http-equiv="Content-Security-Policy" content="${_.csp}" />`:""}
|
|
@@ -39,8 +39,8 @@ import"reflect-metadata";import{Hono as P$}from"hono";function G$($){let _=new S
|
|
|
39
39
|
<!-- Scripts -->
|
|
40
40
|
${_.scripts?_.scripts.map((W)=>{if(typeof W==="string")return F`<script src="${W}"></script>`;let{src:Q,async:U,defer:X}=W;if(U&&X)return F`<script src="${Q}" async defer></script>`;if(U)return F`<script src="${Q}" async></script>`;if(X)return F`<script src="${Q}" defer></script>`;return F`<script src="${Q}"></script>`}):""}
|
|
41
41
|
</head>
|
|
42
|
-
<body ${e(
|
|
42
|
+
<body ${t(e(_.bodyAttributes))}>
|
|
43
43
|
${_.children}
|
|
44
44
|
</body>
|
|
45
45
|
</html>
|
|
46
|
-
`};function
|
|
46
|
+
`};function J$($="",_={}){return(W)=>{Y.setControllerPath(W,$),Y.setControllerOptions(W,_)}}var B$=D("get"),LW=D("post"),PW=D("put"),AW=D("delete"),zW=D("patch"),HW=D("options"),kW=D("all");function x($={}){return(_)=>{Y.setModuleOptions(_,$)}}function EW($="",_={prefix:null,version:null}){return J$($,_)}var wW=B$;function NW($={}){return x({imports:$.imports,services:$.services,controllers:($.views||[]).concat($.controllers||[])})}var IW=A("body",async($,_)=>{let W=_.get(s);if(W===void 0)W=await _.req.json(),_.set(s,W);if($&&W&&typeof W==="object")return W[String($)];return W}),MW=A("param",($,_)=>{return $?_.req.param(String($)):_.req.param()}),xW=A("query",($,_)=>{return $?_.req.query(String($)):_.req.query()}),vW=A("header",($,_)=>{return $?_.req.header(String($)):_.req.header()}),yW=A("request",($,_)=>_.req),gW=A("request",($,_)=>_.req),hW=A("response",($,_)=>_.res),uW=A("response",($,_)=>_.res),mW=A("context",($,_)=>_),dW=A("context",($,_)=>_),cW=A("variable",($,_)=>$===void 0?void 0:_.get(String($))),iW=A("variable",($,_)=>$===void 0?void 0:_.get(String($)));function lW(){return($)=>{Y.addService($)}}function rW($,..._){return(W,Q)=>{if(Q){let U=W.constructor;_.forEach((X)=>Y.registerHandler($,U,Q,X))}else _.forEach((U)=>Y.registerController($,W,U))}}function eW(...$){return(_,W)=>{if(W){let Q=_.constructor;$.forEach((U)=>Y.registerHandler("filter",Q,W,U))}else $.forEach((Q)=>Y.registerController("filter",_,Q))}}function W8(...$){return(_,W)=>{if(W){let Q=_.constructor;$.forEach((U)=>Y.registerHandler("guard",Q,W,U))}else $.forEach((Q)=>Y.registerController("guard",_,Q))}}function X8(...$){return(_,W)=>{if(W){let Q=_.constructor;$.forEach((U)=>Y.registerHandler("middleware",Q,W,U))}else $.forEach((Q)=>Y.registerController("middleware",_,Q))}}function B8(...$){return(_,W)=>{if(W){let Q=_.constructor;$.forEach((U)=>Y.registerHandler("pipe",Q,W,U))}else $.forEach((Q)=>Y.registerController("pipe",_,Q))}}function Y$($={}){let{controllers:_,services:W,imports:Q,name:U="TestModule"}=$,X={[U]:class{}}[U];return x({controllers:_,services:W,imports:Q})(X),X}async function j$($={}){let{module:_,appOptions:W,...Q}=$,U=_??Y$(Q),{app:X,hono:Z}=await M.create(U,W);return{app:X,hono:Z,request:(j,G)=>{if(typeof j==="string"){let B=j.startsWith("http://")||j.startsWith("https://")?j:`http://localhost${j.startsWith("/")?j:`/${j}`}`;return Promise.resolve(Z.request(B,G))}return Promise.resolve(Z.request(j))}}}async function r8($){let{controller:_,...W}=$;return j$({...W,controllers:[_]})}function $Q($={}){let _=$.logger??new P,W=new b(void 0,_,Boolean($.debugDi));for(let Q of $.overrides??[]){let U=Q;W.register(U.provide,U.useValue)}for(let Q of $.preload??[])W.resolve(Q);return{container:W,get(Q){return W.resolve(Q)},register(Q,U){W.register(Q,U)},has(Q){return W.has(Q)},clear(){W.clear()}}}export{O$ as stripEndSlash,g as normalizePath,z$ as isUndefined,K$ as isSymbol,R as isString,H$ as isPlainObject,k as isObject,k$ as isNumber,S as isNil,_$ as isFunction,D$ as isEmpty,W$ as isConstructor,Y$ as createTestingModule,j$ as createTestApplication,$Q as createServiceTestContainer,A as createParamDecorator,D as createHttpMethodDecorator,w as createErrorResponse,r8 as createControllerTestApplication,T$ as addLeadingSlash,EW as View,iW as Variable,cW as Var,p as VERSION_NEUTRAL,B8 as UsePipes,X8 as UseMiddleware,W8 as UseGuards,eW as UseFilters,rW as UseComponent,d as StaticServiceRegistry,lW as Service,m as RouteRegistry,uW as Response,hW as Res,gW as Request,yW as Req,xW as Query,PW as Put,LW as Post,zW as Patch,MW as Param,wW as Page,HW as Options,i as NotFoundHandler,P as NoopLogger,NW as MvcModule,x as Module,C as MetadataRepository,Y as MetadataRegistry,BW as Layout,vW as Header,I as HONEST_PIPELINE_HANDLER_KEY,f as HONEST_PIPELINE_CONTROLLER_KEY,s as HONEST_PIPELINE_BODY_CACHE_KEY,B$ as Get,E as FrameworkError,c as ErrorHandler,AW as Delete,mW as Ctx,J$ as Controller,dW as Context,b as Container,u as ConsoleLogger,IW as Body,h as ApplicationContext,M as Application,kW as All};
|
|
@@ -113,7 +113,7 @@ export interface HonestOptions {
|
|
|
113
113
|
/**
|
|
114
114
|
* Default exception handler to use when no filter matches
|
|
115
115
|
*/
|
|
116
|
-
onError?: (error:
|
|
116
|
+
onError?: (error: unknown, context: Context) => Response | Promise<Response>;
|
|
117
117
|
/**
|
|
118
118
|
* Default not found handler for routes that don't match any pattern
|
|
119
119
|
*/
|
|
@@ -26,5 +26,5 @@ export interface IMetadataRepository {
|
|
|
26
26
|
getContextIndices(controller: Constructor): Map<string | symbol, number>;
|
|
27
27
|
getModuleOptions(module: Constructor): ModuleOptions | undefined;
|
|
28
28
|
getControllerComponents<T extends MetadataComponentType>(type: T, controller: Constructor): MetadataComponentTypeMap[T][];
|
|
29
|
-
getHandlerComponents<T extends MetadataComponentType>(type: T,
|
|
29
|
+
getHandlerComponents<T extends MetadataComponentType>(type: T, controller: Constructor, handlerName: string | symbol): MetadataComponentTypeMap[T][];
|
|
30
30
|
}
|
|
@@ -15,7 +15,7 @@ export declare class ComponentManager {
|
|
|
15
15
|
private readonly metadataRepository;
|
|
16
16
|
private readonly logger;
|
|
17
17
|
private readonly globalComponents;
|
|
18
|
-
constructor(container: DiContainer, metadataRepository
|
|
18
|
+
constructor(container: DiContainer, metadataRepository: IMetadataRepository, logger?: ILogger);
|
|
19
19
|
/**
|
|
20
20
|
* Configures global components from application options.
|
|
21
21
|
*/
|
|
@@ -42,7 +42,7 @@ export declare class ComponentManager {
|
|
|
42
42
|
resolvePipes(pipeItems: PipeType[]): IPipe[];
|
|
43
43
|
getHandlerPipes(controller: Constructor, handlerName: string | symbol): IPipe[];
|
|
44
44
|
executePipes(value: unknown, metadata: ArgumentMetadata, pipes: ReadonlyArray<IPipe>): Promise<unknown>;
|
|
45
|
-
handleException(exception:
|
|
45
|
+
handleException(exception: unknown, context: Context): Promise<Response | undefined>;
|
|
46
46
|
private executeFilters;
|
|
47
47
|
registerModule(moduleClass: Constructor, registered?: Set<Constructor>): Promise<Constructor[]>;
|
|
48
48
|
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import type { ParameterResolutionInput } from '../interfaces';
|
|
2
|
+
import type { ILogger } from '../interfaces';
|
|
2
3
|
import { ComponentManager } from './component.manager';
|
|
3
4
|
/**
|
|
4
5
|
* Resolves route handler arguments from parameter decorator metadata.
|
|
5
6
|
*/
|
|
6
7
|
export declare class ParameterResolver {
|
|
7
8
|
private readonly componentManager;
|
|
8
|
-
|
|
9
|
+
private readonly logger;
|
|
10
|
+
private readonly debugPipeline;
|
|
11
|
+
constructor(componentManager: ComponentManager, logger?: ILogger, debugPipeline?: boolean);
|
|
9
12
|
resolveArguments(input: ParameterResolutionInput): Promise<unknown[]>;
|
|
10
13
|
}
|
|
@@ -21,7 +21,7 @@ export declare class RouteManager {
|
|
|
21
21
|
private logger;
|
|
22
22
|
private globalPrefix?;
|
|
23
23
|
private globalVersion?;
|
|
24
|
-
constructor(hono: Hono, container: DiContainer, routeRegistry: RouteRegistry, componentManager: ComponentManager, metadataRepository
|
|
24
|
+
constructor(hono: Hono, container: DiContainer, routeRegistry: RouteRegistry, componentManager: ComponentManager, metadataRepository: IMetadataRepository, logger?: ILogger, options?: {
|
|
25
25
|
prefix?: string;
|
|
26
26
|
version?: number | typeof VERSION_NEUTRAL | number[];
|
|
27
27
|
debugPipeline?: boolean;
|
|
@@ -60,6 +60,7 @@ export declare class MetadataRegistry {
|
|
|
60
60
|
/**
|
|
61
61
|
* Registry for handler-level components
|
|
62
62
|
* Components registered here apply to specific route handlers
|
|
63
|
+
* Keyed by controller constructor then handler name for collision-safe lookups
|
|
63
64
|
*/
|
|
64
65
|
private static readonly handler;
|
|
65
66
|
/**
|
|
@@ -143,11 +144,11 @@ export declare class MetadataRegistry {
|
|
|
143
144
|
/**
|
|
144
145
|
* Register a component at the handler level
|
|
145
146
|
*/
|
|
146
|
-
static registerHandler<T extends ComponentType>(type: T,
|
|
147
|
+
static registerHandler<T extends ComponentType>(type: T, controller: Constructor, handlerName: string | symbol, component: ComponentTypeMap[T]): void;
|
|
147
148
|
/**
|
|
148
149
|
* Get all handler-level components of a specific type for a handler
|
|
149
150
|
*/
|
|
150
|
-
static getHandler<T extends ComponentType>(type: T,
|
|
151
|
+
static getHandler<T extends ComponentType>(type: T, controller: Constructor, handlerName: string | symbol): ComponentTypeMap[T][];
|
|
151
152
|
/**
|
|
152
153
|
* Clears handler-level component registrations created via {@link registerHandler}.
|
|
153
154
|
* Does not remove decorator-defined routes, controllers, or modules.
|
|
@@ -1,23 +1,11 @@
|
|
|
1
1
|
import type { ControllerOptions, IMetadataRepository, MetadataComponentType, MetadataComponentTypeMap, ModuleOptions, ParameterMetadata, RouteDefinition } from '../interfaces';
|
|
2
2
|
import type { Constructor } from '../types';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Immutable metadata repository for a single Application instance.
|
|
5
|
+
* Captures a deep copy of all metadata reachable from a root module at creation time,
|
|
6
|
+
* isolating the application from later mutations to the static MetadataRegistry.
|
|
5
7
|
*/
|
|
6
|
-
export declare class
|
|
7
|
-
hasController(controller: Constructor): boolean;
|
|
8
|
-
getControllerPath(controller: Constructor): string;
|
|
9
|
-
getControllerOptions(controller: Constructor): ControllerOptions;
|
|
10
|
-
getRoutes(controller: Constructor): RouteDefinition[];
|
|
11
|
-
getParameters(controller: Constructor): Map<string | symbol, ParameterMetadata[]>;
|
|
12
|
-
getContextIndices(controller: Constructor): Map<string | symbol, number>;
|
|
13
|
-
getModuleOptions(module: Constructor): ModuleOptions | undefined;
|
|
14
|
-
getControllerComponents<T extends MetadataComponentType>(type: T, controller: Constructor): MetadataComponentTypeMap[T][];
|
|
15
|
-
getHandlerComponents<T extends MetadataComponentType>(type: T, handlerKey: string): MetadataComponentTypeMap[T][];
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Immutable metadata repository snapshot for a single Application instance.
|
|
19
|
-
*/
|
|
20
|
-
export declare class SnapshotMetadataRepository implements IMetadataRepository {
|
|
8
|
+
export declare class MetadataRepository implements IMetadataRepository {
|
|
21
9
|
private readonly controllerPaths;
|
|
22
10
|
private readonly controllerOptions;
|
|
23
11
|
private readonly routes;
|
|
@@ -26,7 +14,7 @@ export declare class SnapshotMetadataRepository implements IMetadataRepository {
|
|
|
26
14
|
private readonly modules;
|
|
27
15
|
private readonly controllerComponents;
|
|
28
16
|
private readonly handlerComponents;
|
|
29
|
-
static fromRootModule(rootModule: Constructor
|
|
17
|
+
static fromRootModule(rootModule: Constructor): MetadataRepository;
|
|
30
18
|
hasController(controller: Constructor): boolean;
|
|
31
19
|
getControllerPath(controller: Constructor): string;
|
|
32
20
|
getControllerOptions(controller: Constructor): ControllerOptions;
|
|
@@ -35,7 +23,7 @@ export declare class SnapshotMetadataRepository implements IMetadataRepository {
|
|
|
35
23
|
getContextIndices(controller: Constructor): Map<string | symbol, number>;
|
|
36
24
|
getModuleOptions(module: Constructor): ModuleOptions | undefined;
|
|
37
25
|
getControllerComponents<T extends MetadataComponentType>(type: T, controller: Constructor): MetadataComponentTypeMap[T][];
|
|
38
|
-
getHandlerComponents<T extends MetadataComponentType>(type: T,
|
|
26
|
+
getHandlerComponents<T extends MetadataComponentType>(type: T, controller: Constructor, handlerName: string | symbol): MetadataComponentTypeMap[T][];
|
|
39
27
|
private captureModuleGraph;
|
|
40
28
|
private captureController;
|
|
41
29
|
private cloneRouteDefinition;
|
package/package.json
CHANGED