honestjs 0.1.7 → 0.1.8

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 CHANGED
@@ -61,7 +61,7 @@ ultra-fast performance of Hono, giving you the best of both worlds.
61
61
 
62
62
  > ⚠️ **Documentation is not yet complete** ⚠️
63
63
  >
64
- > If you find any issues or have suggestions for improvements, please open an issue or submit a pull request.
64
+ > If you find any issues or have suggestions for improvements, please open an issue or submit a pull request. See [CONTRIBUTING.md](CONTRIBUTING.md) for how to contribute and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for community guidelines.
65
65
 
66
66
  ## Features
67
67
 
@@ -0,0 +1,13 @@
1
+ import type { IApplicationContext } from './interfaces';
2
+ /**
3
+ * Map-backed implementation of the app-level registry.
4
+ * Used by Application so the app (bootstrap, services, any code with `app`) can share pipeline data by key.
5
+ */
6
+ export declare class ApplicationContext implements IApplicationContext {
7
+ private readonly store;
8
+ get<T>(key: string): T | undefined;
9
+ set<T>(key: string, value: T): void;
10
+ has(key: string): boolean;
11
+ delete(key: string): boolean;
12
+ keys(): IterableIterator<string>;
13
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,5 +1,5 @@
1
1
  import { Hono } from 'hono';
2
- import type { HonestOptions, RouteInfo } from './interfaces';
2
+ import type { HonestOptions, IApplicationContext, RouteInfo } from './interfaces';
3
3
  import type { Constructor } from './types';
4
4
  /**
5
5
  * Main application class for the Honest framework
@@ -23,6 +23,7 @@ import type { Constructor } from './types';
23
23
  export declare class Application {
24
24
  private readonly hono;
25
25
  private readonly container;
26
+ private readonly context;
26
27
  private readonly routeManager;
27
28
  private readonly options;
28
29
  /**
@@ -109,6 +110,18 @@ export declare class Application {
109
110
  * ```
110
111
  */
111
112
  getApp(): Hono;
113
+ /**
114
+ * Gets the app-level registry (context) where your app can publish and read pipeline data by key.
115
+ * Use namespaced keys (e.g. 'app.config', 'openapi.spec') and document contracts in your app.
116
+ *
117
+ * @returns The application context instance
118
+ * @example
119
+ * ```ts
120
+ * app.getContext().set('app.config', { env: process.env.NODE_ENV })
121
+ * const config = app.getContext().get<{ env: string }>('app.config')
122
+ * ```
123
+ */
124
+ getContext(): IApplicationContext;
112
125
  /**
113
126
  * Gets information about all registered routes in the application
114
127
  * Useful for documentation and debugging purposes
@@ -0,0 +1 @@
1
+ import 'reflect-metadata';
@@ -0,0 +1 @@
1
+ import 'reflect-metadata';
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import 'reflect-metadata';
2
2
  export * from './application';
3
+ export * from './application-context';
3
4
  export * from './components';
4
5
  export * from './constants';
5
6
  export * from './decorators';
package/dist/index.js CHANGED
@@ -1,22 +1,22 @@
1
- import"reflect-metadata";import{Hono as o}from"hono";class M{instances=new Map;resolve($,_=new Set){if(this.instances.has($))return this.instances.get($);if(_.has($))throw Error(`Circular dependency detected: ${[..._.keys(),$].map((Q)=>Q.name).join(" -> ")}`);_.add($);let Y=(Reflect.getMetadata("design:paramtypes",$)||[]).map((Q)=>{return this.resolve(Q,new Set(_))}),q=new $(...Y);return this.instances.set($,q),q}register($,_){this.instances.set($,_)}}import{HTTPException as a}from"hono/http-exception";function K($,_,W){let Y=new Date().toISOString(),q=_.get("requestId"),Q=_.req.path;if($ instanceof a)return{response:{status:W?.status||$.status,message:W?.title||$.message,timestamp:Y,path:Q,requestId:q,code:W?.code,details:W?.additionalDetails,...W?.detail&&{detail:W.detail}},status:W?.status||$.status};if($.statusCode||$.status){let z=$.statusCode||$.status,G=W?.status||z;return{response:{status:G,message:W?.title||$.message,timestamp:Y,path:Q,requestId:q,code:W?.code||$.name,details:W?.additionalDetails,...W?.detail&&{detail:W.detail}},status:G}}let J=W?.status||500;return{response:{status:J,message:W?.title||$.message,timestamp:Y,path:Q,requestId:q,code:W?.code||$.name,details:W?.additionalDetails||{stack:$.stack},...W?.detail&&{detail:W.detail}},status:J}}class X{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 global=new Map([["middleware",new Set],["guard",new Set],["pipe",new Set],["filter",new Set]]);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 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 registerGlobal($,_){this.global.get($).add(_)}static getGlobal($){return this.global.get($)}static registerController($,_,W){let Y=this.controller.get($);if(!Y.has(_))Y.set(_,[]);Y.get(_).push(W)}static getController($,_){return this.controller.get($).get(_)||[]}static registerHandler($,_,W){let Y=this.handler.get($);if(!Y.has(_))Y.set(_,[]);Y.get(_).push(W)}static getHandler($,_){return this.handler.get($).get(_)||[]}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.global.values())$.clear();for(let $ of this.controller.values())$.clear();for(let $ of this.handler.values())$.clear()}}class S{static routes=[];static 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");this.routes.push($)}static getRoutes(){return this.routes}static getRoutesByController($){return this.routes.filter((_)=>_.controller===$)}static getRoutesByMethod($){return this.routes.filter((_)=>_.method.toUpperCase()===$.toUpperCase())}static getRoutesByPath($){return this.routes.filter((_)=>$.test(_.fullPath))}static clear(){this.routes.length=0}}function b($){return(_="",W={})=>{return(Y,q,Q)=>{let J=Y.constructor;X.addRoute(J,{path:_,method:$,handlerName:q,parameterMetadata:[],version:W.version,prefix:W.prefix})}}}function k($,_){return(W)=>{return(Y,q,Q)=>{let J=Y.constructor;if(!X.getParameters(J).size)X.setParameterMap(J,new Map);let A=X.getParameters(J);if(!A.has(q))A.set(q,[]);let G=Reflect.getMetadata("design:paramtypes",Y,q)?.[Q];if(A.get(q).push({index:Q,name:$,data:W,factory:_,metatype:G}),$==="context"){if(!X.getContextIndices(J).size)X.setContextIndices(J,new Map);X.getContextIndices(J).set(q,Q)}}}}class x{static handle(){return async($,_)=>{let{response:W,status:Y}=K($,_);return _.json(W,Y)}}}class C{static handle(){return async($)=>{return $.json({message:`Not Found - ${$.req.path}`},404)}}}var O$=($)=>typeof $>"u",O=($)=>$===null||typeof $>"u",V=($)=>$!==null&&typeof $==="object",T$=($)=>{if(!V($))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)},d=($)=>typeof $==="function",I=($)=>typeof $==="string",S$=($)=>typeof $==="number",N$=($)=>$.length===0,w$=($)=>typeof $==="symbol",P$=($)=>typeof $==="string"?$.charAt(0)!=="/"?"/"+$:$:"",v=($)=>$?$.startsWith("/")?("/"+$.replace(/\/+$/,"")).replace(/\/+/g,"/"):"/"+$.replace(/\/+$/,""):"/",R$=($)=>$.endsWith("/")?$.slice(0,-1):$,c=($)=>{return d($)&&!O($.prototype)&&!d($.prototype)&&Object.getOwnPropertyNames($.prototype).length>1};class Z{static container;static init($){this.container=$}static 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)}static registerGlobal($,..._){_.forEach((W)=>{X.registerGlobal($,W)})}static registerController($,_,...W){W.forEach((Y)=>{X.registerController($,_,Y)})}static registerHandler($,_,W,...Y){let q=`${_.name}:${String(W)}`;Y.forEach((Q)=>{X.registerHandler($,q,Q)})}static getComponents($,_,W){let Y=`${_.name}:${String(W)}`,q=X.getHandler($,Y),Q=X.getController($,_);return[...Array.from(X.getGlobal($)),...Q,...q]}static resolveMiddleware($){return $.map((_)=>{if(V(_)&&"use"in _)return _.use.bind(_);let W=this.container.resolve(_);return W.use.bind(W)})}static getHandlerMiddleware($,_){let W=this.getComponents("middleware",$,_);return this.resolveMiddleware(W)}static getGlobalMiddleware(){let $=Array.from(X.getGlobal("middleware"));return this.resolveMiddleware($)}static resolveGuards($){return $.map((_)=>{if(V(_)&&"canActivate"in _)return _;return this.container.resolve(_)})}static getHandlerGuards($,_){let W=this.getComponents("guard",$,_);return this.resolveGuards(W)}static resolvePipes($){return $.map((_)=>{if(V(_)&&"transform"in _)return _;return this.container.resolve(_)})}static getHandlerPipes($,_){let W=this.getComponents("pipe",$,_);return this.resolvePipes(W)}static async executePipes($,_,W){let Y=$;for(let q of W)Y=await q.transform(Y,_);return Y}static async handleException($,_){let W=_.get("controllerClass"),Y=_.get("handlerName");if(W&&Y){let A=X.getHandler("filter",`${W.name}:${Y}`);if(A.length>0){let z=await this.executeFilters(A,$,_);if(z)return z}}if(W){let A=X.getController("filter",W);if(A.length>0){let z=await this.executeFilters(A,$,_);if(z)return z}}let q=Array.from(X.getGlobal("filter"));if(q.length>0){let A=await this.executeFilters(q,$,_);if(A)return A}let{response:Q,status:J}=K($,_);return _.json(Q,J)}static async executeFilters($,_,W){for(let Y of $){let q;if(V(Y)&&"catch"in Y)q=Y;else q=this.container.resolve(Y);try{let Q=await q.catch(_,W);if(Q!==void 0)return Q}catch(Q){console.error("Error in exception filter:",Q)}}return}static async registerModule($,_){let W=X.getModuleOptions($);if(!W)throw Error(`Module ${$.name} is not properly decorated with @Module()`);let Y=[];if(W.imports&&W.imports.length>0)for(let q of W.imports){let Q=await this.registerModule(q,_);Y.push(...Q)}if(W.services&&W.services.length>0)for(let q of W.services)_.resolve(q);if(W.controllers&&W.controllers.length>0)Y.push(...W.controllers);return Y}}import{HTTPException as r}from"hono/http-exception";var y=Symbol("VERSION_NEUTRAL");class h{hono;container;globalPrefix;globalVersion;constructor($,_,W={}){this.hono=$,this.container=_,this.globalPrefix=W.prefix!==void 0?this.normalizePath(W.prefix):void 0,this.globalVersion=W.version,this.applyGlobalMiddleware()}applyGlobalMiddleware(){let $=Z.getGlobalMiddleware();for(let _ of $)this.hono.use("*",_)}normalizePath($){if(I($))return v($);return $?`/${$}`:""}registerRouteHandler($,_,W,Y){if(W.length>0)this.hono.on($.toUpperCase(),_,...W,Y);else this.hono.on($.toUpperCase(),_,Y)}buildRoutePath($,_,W,Y){return v(`${$}${_}${W}${Y}`)}formatVersionSegment($){if(O($))return"";return $===y?"":`/v${String($)}`}async registerController($){let _=X.getControllerPath($)||"",W=X.getControllerOptions($)||{},Y=X.getRoutes($)||[],q=X.getParameters($)||new Map,Q=X.getContextIndices($)||new Map,J=this.normalizePath(_),A=this.container.resolve($),z=W.prefix!==void 0?W.prefix:this.globalPrefix,G=W.version!==void 0?W.version:this.globalVersion;for(let U of Y){let{path:T,method:E,handlerName:f,version:N,prefix:w}=U,P=w!==void 0?w:z,D=!O(P)?this.normalizePath(P):"",L=N!==void 0?N:G,F=this.normalizePath(T);if(O(L)){this.registerRoute(A,U,q,Q,$,D,"",J,F,E);continue}if(L===y){this.registerRoute(A,U,q,Q,$,D,"",J,F,E),this.registerRoute(A,U,q,Q,$,D,"/:version{v[0-9]+}",J,F,E);continue}if(Array.isArray(L)){for(let H of L){let j=this.formatVersionSegment(H);this.registerRoute(A,U,q,Q,$,D,j,J,F,E)}continue}let R=this.formatVersionSegment(L);this.registerRoute(A,U,q,Q,$,D,R,J,F,E)}}registerRoute($,_,W,Y,q,Q,J,A,z,G){let{handlerName:U}=_,T=this.buildRoutePath(Q,J,A,z),E=$[U].bind($),f=W.get(U)||[],N=Y.get(U),w=Z.getHandlerMiddleware(q,U),P=Z.getHandlerPipes(q,U);S.registerRoute({controller:q.name,handler:U,method:G,prefix:Q,version:J,route:A,path:z,fullPath:T,parameters:f});let D=async(L)=>{try{L.set("controllerClass",q),L.set("handlerName",String(U));let F=Z.getHandlerGuards(q,U);for(let j of F)if(!await j.canActivate(L))throw new r(403,{message:"Forbidden"});let R=Array(E.length);for(let j of f){let m=j.factory(j.data,L),n=await Z.executePipes(m,{type:j.name,metatype:j.metatype,data:j.data},P);R[j.index]=n}let H=await E(...R);if(N!==void 0)return H;if(O(H))return L.json(null);if(I(H))return L.text(H);return L.json(H)}catch(F){return Z.handleException(F,L)}};this.registerRouteHandler(G,T,w,D)}}class i{hono;container;routeManager;options;constructor($={}){this.options=V($)?$:{},this.hono=new o(this.options.hono),this.container=this.options.container||new M,this.setupComponents(),this.setupErrorHandlers(),this.routeManager=new h(this.hono,this.container,{prefix:this.options.routing?.prefix,version:this.options.routing?.version})}setupComponents(){Z.init(this.container),Z.setupGlobalComponents(this.options)}setupErrorHandlers(){this.hono.notFound(this.options.notFound||C.handle()),this.hono.onError(this.options.onError||x.handle())}resolvePlugin($){if(c($))return new $;return $}async register($){let _=await Z.registerModule($,this.container);for(let W of _)await this.routeManager.registerController(W);return this}static async create($,_={}){let W=new i(_),Y=(_.plugins||[]).map((q)=>W.resolvePlugin(q));for(let q of Y)if(q.beforeModulesRegistered)await q.beforeModulesRegistered(W,W.hono);await W.register($);for(let q of Y)if(q.afterModulesRegistered)await q.afterModulesRegistered(W,W.hono);return{app:W,hono:W.getApp()}}getApp(){return this.hono}getRoutes(){return S.getRoutes()}}import{html as B,raw as g}from"hono/html";var t={type:"website",locale:"en_US"},u=($)=>{if(!$)return"";return Object.entries($).map(([_,W])=>{if(typeof W==="boolean")return W?_:"";let Y=String(W).replace(/"/g,"&quot;");return`${_}="${Y}"`}).filter(Boolean).join(" ")},Y_=($)=>{let _={...t,...$};return B`
1
+ import"reflect-metadata";import{Hono as t}from"hono";class M{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 x{instances=new Map;resolve($,_=new Set){if(this.instances.has($))return this.instances.get($);if(_.has($))throw Error(`Circular dependency detected: ${[..._.keys(),$].map((Q)=>Q.name).join(" -> ")}`);_.add($);let Y=(Reflect.getMetadata("design:paramtypes",$)||[]).map((Q)=>{return this.resolve(Q,new Set(_))}),q=new $(...Y);return this.instances.set($,q),q}register($,_){this.instances.set($,_)}}import{HTTPException as r}from"hono/http-exception";function K($,_,W){let Y=new Date().toISOString(),q=_.get("requestId"),Q=_.req.path;if($ instanceof r)return{response:{status:W?.status||$.status,message:W?.title||$.message,timestamp:Y,path:Q,requestId:q,code:W?.code,details:W?.additionalDetails,...W?.detail&&{detail:W.detail}},status:W?.status||$.status};if($.statusCode||$.status){let A=$.statusCode||$.status,F=W?.status||A;return{response:{status:F,message:W?.title||$.message,timestamp:Y,path:Q,requestId:q,code:W?.code||$.name,details:W?.additionalDetails,...W?.detail&&{detail:W.detail}},status:F}}let J=W?.status||500;return{response:{status:J,message:W?.title||$.message,timestamp:Y,path:Q,requestId:q,code:W?.code||$.name,details:W?.additionalDetails||{stack:$.stack},...W?.detail&&{detail:W.detail}},status:J}}class X{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 global=new Map([["middleware",new Set],["guard",new Set],["pipe",new Set],["filter",new Set]]);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 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 registerGlobal($,_){this.global.get($).add(_)}static getGlobal($){return this.global.get($)}static registerController($,_,W){let Y=this.controller.get($);if(!Y.has(_))Y.set(_,[]);Y.get(_).push(W)}static getController($,_){return this.controller.get($).get(_)||[]}static registerHandler($,_,W){let Y=this.handler.get($);if(!Y.has(_))Y.set(_,[]);Y.get(_).push(W)}static getHandler($,_){return this.handler.get($).get(_)||[]}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.global.values())$.clear();for(let $ of this.controller.values())$.clear();for(let $ of this.handler.values())$.clear()}}class S{static routes=[];static 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");this.routes.push($)}static getRoutes(){return this.routes}static getRoutesByController($){return this.routes.filter((_)=>_.controller===$)}static getRoutesByMethod($){return this.routes.filter((_)=>_.method.toUpperCase()===$.toUpperCase())}static getRoutesByPath($){return this.routes.filter((_)=>$.test(_.fullPath))}static clear(){this.routes.length=0}}function b($){return(_="",W={})=>{return(Y,q,Q)=>{let J=Y.constructor;X.addRoute(J,{path:_,method:$,handlerName:q,parameterMetadata:[],version:W.version,prefix:W.prefix})}}}function j($,_){return(W)=>{return(Y,q,Q)=>{let J=Y.constructor;if(!X.getParameters(J).size)X.setParameterMap(J,new Map);let B=X.getParameters(J);if(!B.has(q))B.set(q,[]);let F=Reflect.getMetadata("design:paramtypes",Y,q)?.[Q];if(B.get(q).push({index:Q,name:$,data:W,factory:_,metatype:F}),$==="context"){if(!X.getContextIndices(J).size)X.setContextIndices(J,new Map);X.getContextIndices(J).set(q,Q)}}}}class C{static handle(){return async($,_)=>{let{response:W,status:Y}=K($,_);return _.json(W,Y)}}}class I{static handle(){return async($)=>{return $.json({message:`Not Found - ${$.req.path}`},404)}}}var S$=($)=>typeof $>"u",O=($)=>$===null||typeof $>"u",k=($)=>$!==null&&typeof $==="object",N$=($)=>{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)},c=($)=>typeof $==="function",v=($)=>typeof $==="string",P$=($)=>typeof $==="number",w$=($)=>$.length===0,R$=($)=>typeof $==="symbol",K$=($)=>typeof $==="string"?$.charAt(0)!=="/"?"/"+$:$:"",y=($)=>$?$.startsWith("/")?("/"+$.replace(/\/+$/,"")).replace(/\/+/g,"/"):"/"+$.replace(/\/+$/,""):"/",f$=($)=>$.endsWith("/")?$.slice(0,-1):$,i=($)=>{return c($)&&!O($.prototype)&&!c($.prototype)&&Object.getOwnPropertyNames($.prototype).length>=1};class Z{static container;static init($){this.container=$}static 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)}static registerGlobal($,..._){_.forEach((W)=>{X.registerGlobal($,W)})}static registerController($,_,...W){W.forEach((Y)=>{X.registerController($,_,Y)})}static registerHandler($,_,W,...Y){let q=`${_.name}:${String(W)}`;Y.forEach((Q)=>{X.registerHandler($,q,Q)})}static getComponents($,_,W){let Y=`${_.name}:${String(W)}`,q=X.getHandler($,Y),Q=X.getController($,_);return[...Array.from(X.getGlobal($)),...Q,...q]}static resolveMiddleware($){return $.map((_)=>{if(k(_)&&"use"in _)return _.use.bind(_);let W=this.container.resolve(_);return W.use.bind(W)})}static getHandlerMiddleware($,_){let W=this.getComponents("middleware",$,_);return this.resolveMiddleware(W)}static getGlobalMiddleware(){let $=Array.from(X.getGlobal("middleware"));return this.resolveMiddleware($)}static resolveGuards($){return $.map((_)=>{if(k(_)&&"canActivate"in _)return _;return this.container.resolve(_)})}static getHandlerGuards($,_){let W=this.getComponents("guard",$,_);return this.resolveGuards(W)}static resolvePipes($){return $.map((_)=>{if(k(_)&&"transform"in _)return _;return this.container.resolve(_)})}static getHandlerPipes($,_){let W=this.getComponents("pipe",$,_);return this.resolvePipes(W)}static async executePipes($,_,W){let Y=$;for(let q of W)Y=await q.transform(Y,_);return Y}static async handleException($,_){let W=_.get("controllerClass"),Y=_.get("handlerName");if(W&&Y){let B=X.getHandler("filter",`${W.name}:${Y}`);if(B.length>0){let A=await this.executeFilters(B,$,_);if(A)return A}}if(W){let B=X.getController("filter",W);if(B.length>0){let A=await this.executeFilters(B,$,_);if(A)return A}}let q=Array.from(X.getGlobal("filter"));if(q.length>0){let B=await this.executeFilters(q,$,_);if(B)return B}let{response:Q,status:J}=K($,_);return _.json(Q,J)}static async executeFilters($,_,W){for(let Y of $){let q;if(k(Y)&&"catch"in Y)q=Y;else q=this.container.resolve(Y);try{let Q=await q.catch(_,W);if(Q!==void 0)return Q}catch(Q){console.error("Error in exception filter:",Q)}}return}static async registerModule($,_){let W=X.getModuleOptions($);if(!W)throw Error(`Module ${$.name} is not properly decorated with @Module()`);let Y=[];if(W.imports&&W.imports.length>0)for(let q of W.imports){let Q=await this.registerModule(q,_);Y.push(...Q)}if(W.services&&W.services.length>0)for(let q of W.services)_.resolve(q);if(W.controllers&&W.controllers.length>0)Y.push(...W.controllers);return Y}}import{HTTPException as o}from"hono/http-exception";var g=Symbol("VERSION_NEUTRAL");class h{hono;container;globalPrefix;globalVersion;constructor($,_,W={}){this.hono=$,this.container=_,this.globalPrefix=W.prefix!==void 0?this.normalizePath(W.prefix):void 0,this.globalVersion=W.version,this.applyGlobalMiddleware()}applyGlobalMiddleware(){let $=Z.getGlobalMiddleware();for(let _ of $)this.hono.use("*",_)}normalizePath($){if(v($))return y($);return $?`/${$}`:""}registerRouteHandler($,_,W,Y){if(W.length>0)this.hono.on($.toUpperCase(),_,...W,Y);else this.hono.on($.toUpperCase(),_,Y)}buildRoutePath($,_,W,Y){return y(`${$}${_}${W}${Y}`)}formatVersionSegment($){if(O($))return"";return $===g?"":`/v${String($)}`}async registerController($){let _=X.getControllerPath($)||"",W=X.getControllerOptions($)||{},Y=X.getRoutes($)||[],q=X.getParameters($)||new Map,Q=X.getContextIndices($)||new Map,J=this.normalizePath(_),B=this.container.resolve($),A=W.prefix!==void 0?W.prefix:this.globalPrefix,F=W.version!==void 0?W.version:this.globalVersion;for(let z of Y){let{path:T,method:V,handlerName:f,version:N,prefix:P}=z,w=P!==void 0?P:A,D=!O(w)?this.normalizePath(w):"",L=N!==void 0?N:F,E=this.normalizePath(T);if(O(L)){this.registerRoute(B,z,q,Q,$,D,"",J,E,V);continue}if(L===g){this.registerRoute(B,z,q,Q,$,D,"",J,E,V),this.registerRoute(B,z,q,Q,$,D,"/:version{v[0-9]+}",J,E,V);continue}if(Array.isArray(L)){for(let H of L){let G=this.formatVersionSegment(H);this.registerRoute(B,z,q,Q,$,D,G,J,E,V)}continue}let R=this.formatVersionSegment(L);this.registerRoute(B,z,q,Q,$,D,R,J,E,V)}}registerRoute($,_,W,Y,q,Q,J,B,A,F){let{handlerName:z}=_,T=this.buildRoutePath(Q,J,B,A),V=$[z].bind($),f=W.get(z)||[],N=Y.get(z),P=Z.getHandlerMiddleware(q,z),w=Z.getHandlerPipes(q,z);S.registerRoute({controller:q.name,handler:z,method:F,prefix:Q,version:J,route:B,path:A,fullPath:T,parameters:f});let D=async(L)=>{try{L.set("controllerClass",q),L.set("handlerName",String(z));let E=Z.getHandlerGuards(q,z);for(let G of E)if(!await G.canActivate(L))throw new o(403,{message:"Forbidden"});let R=Array(V.length);for(let G of f){let d=G.factory(G.data,L),a=await Z.executePipes(d,{type:G.name,metatype:G.metatype,data:G.data},w);R[G.index]=a}let H=await V(...R);if(N!==void 0)return H;if(O(H))return L.json(null);if(v(H))return L.text(H);return L.json(H)}catch(E){return Z.handleException(E,L)}};this.registerRouteHandler(F,T,P,D)}}class p{hono;container;context;routeManager;options;constructor($={}){this.options=k($)?$:{},this.hono=new t(this.options.hono),this.container=this.options.container||new x,this.context=new M,this.setupComponents(),this.setupErrorHandlers(),this.routeManager=new h(this.hono,this.container,{prefix:this.options.routing?.prefix,version:this.options.routing?.version})}setupComponents(){Z.init(this.container),Z.setupGlobalComponents(this.options)}setupErrorHandlers(){this.hono.notFound(this.options.notFound||I.handle()),this.hono.onError(this.options.onError||C.handle())}resolvePlugin($){if(i($))return new $;return $}async register($){let _=await Z.registerModule($,this.container);for(let W of _)await this.routeManager.registerController(W);return this}static async create($,_={}){let W=new p(_),Y=(_.plugins||[]).map((q)=>W.resolvePlugin(q));for(let q of Y)if(q.beforeModulesRegistered)await q.beforeModulesRegistered(W,W.hono);await W.register($);for(let q of Y)if(q.afterModulesRegistered)await q.afterModulesRegistered(W,W.hono);return{app:W,hono:W.getApp()}}getApp(){return this.hono}getContext(){return this.context}getRoutes(){return S.getRoutes()}}import{html as U,raw as u}from"hono/html";var e={type:"website",locale:"en_US"},m=($)=>{if(!$)return"";return Object.entries($).map(([_,W])=>{if(typeof W==="boolean")return W?_:"";let Y=String(W).replace(/"/g,"&quot;");return`${_}="${Y}"`}).filter(Boolean).join(" ")},X_=($)=>{let _={...e,...$};return U`
2
2
  <!DOCTYPE html>
3
- <html lang="${_.locale?.split("_")[0]||"en"}" ${g(u(_.htmlAttributes))}>
4
- <head ${g(u(_.headAttributes))}>
3
+ <html lang="${_.locale?.split("_")[0]||"en"}" ${u(m(_.htmlAttributes))}>
4
+ <head ${u(m(_.headAttributes))}>
5
5
  <meta charset="UTF-8" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
- ${_.csp?B`<meta http-equiv="Content-Security-Policy" content="${_.csp}" />`:""}
7
+ ${_.csp?U`<meta http-equiv="Content-Security-Policy" content="${_.csp}" />`:""}
8
8
  <title>${_.title}</title>
9
- ${_.description?B`<meta name="description" content="${_.description}" />`:""}
9
+ ${_.description?U`<meta name="description" content="${_.description}" />`:""}
10
10
 
11
11
  <!-- Open Graph / Facebook -->
12
12
  <meta prefix="og: http://ogp.me/ns#" />
13
13
  <meta property="og:title" content="${_.title}" />
14
- ${_.description?B`<meta property="og:description" content="${_.description}" />`:""}
15
- ${_.image?B`<meta property="og:image" content="${_.image}" />`:""}
16
- ${_.url?B`<meta property="og:url" content="${_.url}" />`:""}
17
- ${_.locale?B`<meta property="og:locale" content="${_.locale}" />`:""}
18
- ${_.type?B`<meta property="og:type" content="${_.type}" />`:""}
19
- ${_.siteName?B`<meta property="og:site_name" content="${_.siteName}" />`:""}
14
+ ${_.description?U`<meta property="og:description" content="${_.description}" />`:""}
15
+ ${_.image?U`<meta property="og:image" content="${_.image}" />`:""}
16
+ ${_.url?U`<meta property="og:url" content="${_.url}" />`:""}
17
+ ${_.locale?U`<meta property="og:locale" content="${_.locale}" />`:""}
18
+ ${_.type?U`<meta property="og:type" content="${_.type}" />`:""}
19
+ ${_.siteName?U`<meta property="og:site_name" content="${_.siteName}" />`:""}
20
20
 
21
21
  <!-- Twitter -->
22
22
  <meta
@@ -24,23 +24,23 @@ import"reflect-metadata";import{Hono as o}from"hono";class M{instances=new Map;r
24
24
  content="${_.twitterCard||(_.image?"summary_large_image":"summary")}"
25
25
  />
26
26
  <meta name="twitter:title" content="${_.title}" />
27
- ${_.description?B`<meta name="twitter:description" content="${_.description}" />`:""}
28
- ${_.image?B`<meta name="twitter:image" content="${_.image}" />`:""}
27
+ ${_.description?U`<meta name="twitter:description" content="${_.description}" />`:""}
28
+ ${_.image?U`<meta name="twitter:image" content="${_.image}" />`:""}
29
29
 
30
30
  <!-- Custom Meta Tags -->
31
- ${_.customMeta?_.customMeta.map((W)=>{let Y=W.name?`name="${W.name}"`:"",q=W.property?`property="${W.property}"`:"";return B`<meta ${Y} ${q} content="${W.content}" />`}):""}
31
+ ${_.customMeta?_.customMeta.map((W)=>{let Y=W.name?`name="${W.name}"`:"",q=W.property?`property="${W.property}"`:"";return U`<meta ${Y} ${q} content="${W.content}" />`}):""}
32
32
 
33
33
  <!-- Favicon -->
34
- ${_.favicon?B`<link rel="icon" href="${_.favicon}" />`:""}
34
+ ${_.favicon?U`<link rel="icon" href="${_.favicon}" />`:""}
35
35
 
36
36
  <!-- Stylesheets -->
37
- ${_.stylesheets?_.stylesheets.map((W)=>B`<link rel="stylesheet" href="${W}" />`):""}
37
+ ${_.stylesheets?_.stylesheets.map((W)=>U`<link rel="stylesheet" href="${W}" />`):""}
38
38
 
39
39
  <!-- Scripts -->
40
- ${_.scripts?_.scripts.map((W)=>{if(typeof W==="string")return B`<script src="${W}"></script>`;let{src:Y,async:q,defer:Q}=W;if(q&&Q)return B`<script src="${Y}" async defer></script>`;if(q)return B`<script src="${Y}" async></script>`;if(Q)return B`<script src="${Y}" defer></script>`;return B`<script src="${Y}"></script>`}):""}
40
+ ${_.scripts?_.scripts.map((W)=>{if(typeof W==="string")return U`<script src="${W}"></script>`;let{src:Y,async:q,defer:Q}=W;if(q&&Q)return U`<script src="${Y}" async defer></script>`;if(q)return U`<script src="${Y}" async></script>`;if(Q)return U`<script src="${Y}" defer></script>`;return U`<script src="${Y}"></script>`}):""}
41
41
  </head>
42
- <body ${g(u(_.bodyAttributes))}>
42
+ <body ${u(m(_.bodyAttributes))}>
43
43
  ${_.children}
44
44
  </body>
45
45
  </html>
46
- `};function p($="",_={}){return(W)=>{X.setControllerPath(W,$),X.setControllerOptions(W,_)}}var s=b("get"),B_=b("post"),U_=b("put"),z_=b("delete"),L_=b("patch"),k_=b("options"),j_=b("all");function l($={}){return(_)=>{X.setModuleOptions(_,$)}}function H_($="",_={prefix:null,version:null}){return p($,_)}var O_=s;function T_($={}){return l({imports:$.imports,services:$.services,controllers:($.views||[]).concat($.controllers||[])})}var w_=k("body",async($,_)=>{let W=await _.req.json();return $?W[$]:W}),P_=k("param",($,_)=>{return $?_.req.param($):_.req.param()}),R_=k("query",($,_)=>{return $?_.req.query($):_.req.query()}),K_=k("header",($,_)=>{return $?_.req.header($):_.req.header()}),f_=k("request",($,_)=>_.req),M_=k("request",($,_)=>_.req),x_=k("response",($,_)=>_.res),C_=k("response",($,_)=>_.res),I_=k("context",($,_)=>_),v_=k("context",($,_)=>_),y_=k("variable",($,_)=>_.get($)),h_=k("variable",($,_)=>_.get($));function m_(){return($)=>{X.addService($)}}function i_($,..._){return(W,Y)=>{if(Y){let q=W.constructor;Z.registerHandler($,q,Y,..._)}else Z.registerController($,W,..._)}}function l_(...$){return(_,W)=>{if(W){let Y=_.constructor;Z.registerHandler("filter",Y,W,...$)}else Z.registerController("filter",_,...$)}}function r_(...$){return(_,W)=>{if(W){let Y=_.constructor;Z.registerHandler("guard",Y,W,...$)}else Z.registerController("guard",_,...$)}}function e_(...$){return(_,W)=>{if(W){let Y=_.constructor;Z.registerHandler("middleware",Y,W,...$)}else Z.registerController("middleware",_,...$)}}function WW(...$){return(_,W)=>{if(W){let Y=_.constructor;Z.registerHandler("pipe",Y,W,...$)}else Z.registerController("pipe",_,...$)}}export{R$ as stripEndSlash,v as normalizePath,O$ as isUndefined,w$ as isSymbol,I as isString,T$ as isPlainObject,V as isObject,S$ as isNumber,O as isNil,d as isFunction,N$ as isEmpty,c as isConstructor,k as createParamDecorator,b as createHttpMethodDecorator,K as createErrorResponse,P$ as addLeadingSlash,H_ as View,h_ as Variable,y_ as Var,y as VERSION_NEUTRAL,WW as UsePipes,e_ as UseMiddleware,r_ as UseGuards,l_ as UseFilters,i_ as UseComponent,m_ as Service,S as RouteRegistry,h as RouteManager,C_ as Response,x_ as Res,M_ as Request,f_ as Req,R_ as Query,U_ as Put,B_ as Post,L_ as Patch,P_ as Param,O_ as Page,k_ as Options,C as NotFoundHandler,T_ as MvcModule,l as Module,X as MetadataRegistry,Y_ as Layout,K_ as Header,s as Get,x as ErrorHandler,z_ as Delete,I_ as Ctx,p as Controller,v_ as Context,M as Container,Z as ComponentManager,w_ as Body,i as Application,j_ as All};
46
+ `};function s($="",_={}){return(W)=>{X.setControllerPath(W,$),X.setControllerOptions(W,_)}}var l=b("get"),L_=b("post"),j_=b("put"),G_=b("delete"),F_=b("patch"),E_=b("options"),V_=b("all");function n($={}){return(_)=>{X.setModuleOptions(_,$)}}function S_($="",_={prefix:null,version:null}){return s($,_)}var N_=l;function P_($={}){return n({imports:$.imports,services:$.services,controllers:($.views||[]).concat($.controllers||[])})}var K_=j("body",async($,_)=>{let W=await _.req.json();return $?W[$]:W}),f_=j("param",($,_)=>{return $?_.req.param($):_.req.param()}),M_=j("query",($,_)=>{return $?_.req.query($):_.req.query()}),x_=j("header",($,_)=>{return $?_.req.header($):_.req.header()}),C_=j("request",($,_)=>_.req),I_=j("request",($,_)=>_.req),v_=j("response",($,_)=>_.res),y_=j("response",($,_)=>_.res),g_=j("context",($,_)=>_),h_=j("context",($,_)=>_),u_=j("variable",($,_)=>_.get($)),m_=j("variable",($,_)=>_.get($));function i_(){return($)=>{X.addService($)}}function l_($,..._){return(W,Y)=>{if(Y){let q=W.constructor;Z.registerHandler($,q,Y,..._)}else Z.registerController($,W,..._)}}function r_(...$){return(_,W)=>{if(W){let Y=_.constructor;Z.registerHandler("filter",Y,W,...$)}else Z.registerController("filter",_,...$)}}function e_(...$){return(_,W)=>{if(W){let Y=_.constructor;Z.registerHandler("guard",Y,W,...$)}else Z.registerController("guard",_,...$)}}function WW(...$){return(_,W)=>{if(W){let Y=_.constructor;Z.registerHandler("middleware",Y,W,...$)}else Z.registerController("middleware",_,...$)}}function QW(...$){return(_,W)=>{if(W){let Y=_.constructor;Z.registerHandler("pipe",Y,W,...$)}else Z.registerController("pipe",_,...$)}}export{f$ as stripEndSlash,y as normalizePath,S$ as isUndefined,R$ as isSymbol,v as isString,N$ as isPlainObject,k as isObject,P$ as isNumber,O as isNil,c as isFunction,w$ as isEmpty,i as isConstructor,j as createParamDecorator,b as createHttpMethodDecorator,K as createErrorResponse,K$ as addLeadingSlash,S_ as View,m_ as Variable,u_ as Var,g as VERSION_NEUTRAL,QW as UsePipes,WW as UseMiddleware,e_ as UseGuards,r_ as UseFilters,l_ as UseComponent,i_ as Service,S as RouteRegistry,h as RouteManager,y_ as Response,v_ as Res,I_ as Request,C_ as Req,M_ as Query,j_ as Put,L_ as Post,F_ as Patch,f_ as Param,N_ as Page,E_ as Options,I as NotFoundHandler,P_ as MvcModule,n as Module,X as MetadataRegistry,X_ as Layout,x_ as Header,l as Get,C as ErrorHandler,G_ as Delete,g_ as Ctx,s as Controller,h_ as Context,x as Container,Z as ComponentManager,K_ as Body,M as ApplicationContext,p as Application,V_ as All};
@@ -0,0 +1,35 @@
1
+ /**
2
+ * App-level registry where your application can publish and read pipeline data by key.
3
+ * Available to bootstrap code, services, and any code with access to `app`.
4
+ * Enables composition without hard coupling: producers and consumers use namespaced keys.
5
+ */
6
+ export interface IApplicationContext {
7
+ /**
8
+ * Get a value by key. Caller provides type for type safety.
9
+ * @param key - Namespaced registry key (e.g. 'app.config', 'openapi.spec')
10
+ * @returns The value or undefined if not set
11
+ */
12
+ get<T>(key: string): T | undefined;
13
+ /**
14
+ * Set a value by key.
15
+ * @param key - Namespaced registry key
16
+ * @param value - Value to store
17
+ */
18
+ set<T>(key: string, value: T): void;
19
+ /**
20
+ * Check if a key is present.
21
+ * @param key - Registry key
22
+ * @returns true if the key exists
23
+ */
24
+ has(key: string): boolean;
25
+ /**
26
+ * Remove a key and its value.
27
+ * @param key - Registry key
28
+ * @returns true if the key existed and was removed
29
+ */
30
+ delete(key: string): boolean;
31
+ /**
32
+ * Iterate over all registered keys.
33
+ */
34
+ keys(): IterableIterator<string>;
35
+ }
@@ -1,3 +1,4 @@
1
+ export * from './application-context.interface';
1
2
  export * from './controller-options.interface';
2
3
  export * from './di-container.interface';
3
4
  export * from './error-response.interface';
@@ -0,0 +1 @@
1
+ export {};
@@ -98,11 +98,12 @@ export declare const normalizePath: (path?: string) => string;
98
98
  */
99
99
  export declare const stripEndSlash: (path: string) => string;
100
100
  /**
101
- * Checks if a value is a constructor function
101
+ * Checks if a value is a constructor function (callable with `new`).
102
102
  * A constructor function must:
103
103
  * - Be a function
104
- * - Have a prototype
105
- * - Have prototype properties beyond the default ones
104
+ * - Have a non-null prototype (excludes arrow functions, which have no prototype)
105
+ * - Have a prototype that is not a function (excludes rare edge cases)
106
+ * - Have at least the built-in 'constructor' on prototype (so empty classes are constructors)
106
107
  *
107
108
  * @param val - The value to check
108
109
  * @returns True if the value is a constructor function, false otherwise
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "honestjs",
3
3
  "description": "HonestJS - a modern web framework built on top of Hono",
4
- "version": "0.1.7",
4
+ "version": "0.1.8",
5
5
  "author": "Orkhan Karimov <karimovok1@gmail.com> (https://github.com/kerimovok)",
6
6
  "repository": {
7
7
  "type": "git",
@@ -51,6 +51,8 @@
51
51
  "scripts": {
52
52
  "clean": "rm -rf dist",
53
53
  "prepare": "husky",
54
+ "test": "bun test",
55
+ "test:watch": "bun test --watch",
54
56
  "build": "bun run clean && bun build ./src/index.ts --outdir=dist --target=node --minify --external hono --external reflect-metadata && bun run build:types",
55
57
  "build:types": "tsc --emitDeclarationOnly --declaration --outDir dist",
56
58
  "lint": "eslint .",