UNPKG

honestjs

Version:

HonestJS - a modern web framework built on top of Hono

47 lines (40 loc) 16.6 kB
import"reflect-metadata";import{Hono as t}from"hono";class M{instances=new Map;resolve($,_=new Set){if(this.instances.has($))return this.instances.get($);if(_.has($))throw new 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 R($,_,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 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(_)||[]}}class T{static routes=[];static registerRoute($){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}=R($,_);return _.json(W,Y)}}}class I{static handle(){return async($)=>{return $.json({message:`Not Found - ${$.req.path}`},404)}}}var K=($)=>$!==null&&typeof $==="object";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 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}console.log("No filter handled the exception, creating default response");let{response:Q,status:J}=R($,_);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 new 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 C=Symbol("VERSION_NEUTRAL");var K$=($)=>typeof $==="undefined",H=($)=>$===null||typeof $==="undefined",v=($)=>$!==null&&typeof $==="object",f$=($)=>{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)},c=($)=>typeof $==="function",y=($)=>typeof $==="string",M$=($)=>typeof $==="number",x$=($)=>$.length===0,I$=($)=>typeof $==="symbol",C$=($)=>typeof $==="string"?$.charAt(0)!=="/"?"/"+$:$:"",u=($)=>$?$.startsWith("/")?("/"+$.replace(/\/+$/,"")).replace(/\/+/g,"/"):"/"+$.replace(/\/+$/,""):"/",v$=($)=>$.endsWith("/")?$.slice(0,-1):$,i=($)=>{return c($)&&!H($.prototype)&&!c($.prototype)&&Object.getOwnPropertyNames($.prototype).length>1};class g{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(y($))return u($);return $?`/${$}`:""}registerRouteHandler($,_,W,Y){if(W.length>0)this.hono.on($.toUpperCase(),_,...W,Y);else this.hono.on($.toUpperCase(),_,Y)}buildRoutePath($,_,W,Y){return u(`${$}${_}${W}${Y}`)}formatVersionSegment($){if(H($))return"";return $===C?"":`/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:O,method:E,handlerName:f,version:S,prefix:N}=U,w=N!==void 0?N:z,V=!H(w)?this.normalizePath(w):"",L=S!==void 0?S:G,F=this.normalizePath(O);if(H(L)){this.registerRoute(A,U,q,Q,$,V,"",J,F,E);continue}if(L===C){this.registerRoute(A,U,q,Q,$,V,"",J,F,E),this.registerRoute(A,U,q,Q,$,V,"/:version{v[0-9]+}",J,F,E);continue}if(Array.isArray(L)){for(let D of L){let j=this.formatVersionSegment(D);this.registerRoute(A,U,q,Q,$,V,j,J,F,E)}continue}let P=this.formatVersionSegment(L);this.registerRoute(A,U,q,Q,$,V,P,J,F,E)}}registerRoute($,_,W,Y,q,Q,J,A,z,G){let{handlerName:U}=_,O=this.buildRoutePath(Q,J,A,z),E=$[U].bind($),f=W.get(U)||[],S=Y.get(U),N=Z.getHandlerMiddleware(q,U),w=Z.getHandlerPipes(q,U);T.registerRoute({controller:q.name,handler:U,method:G,prefix:Q,version:J,route:A,path:z,fullPath:O,parameters:f});let V=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 o(403,{message:"Forbidden"});let P=new Array(E.length);for(let j of f){let d=j.factory(j.data,L),a=await Z.executePipes(d,{type:j.type,metatype:j.metatype,data:j.data},w);P[j.index]=a}let D=await E(...P);if(S!==void 0)return D;if(H(D))return L.json(null);if(y(D))return L.text(D);return L.json(D)}catch(F){return Z.handleException(F,L)}};this.registerRouteHandler(G,O,N,V)}}class p{hono;container;routeManager;options;constructor($={}){this.options=v($)?$:{},this.hono=new t(this.options.hono),this.container=this.options.container||new M,this.setupComponents(),this.setupErrorHandlers(),this.routeManager=new g(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||x.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}getRoutes(){return T.getRoutes()}}import{html as B,raw as h}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(" ")},Y_=($)=>{let _={...e,...$};return B` <!DOCTYPE html> <html lang="${_.locale?.split("_")[0]||"en"}" ${h(m(_.htmlAttributes))}> <head ${h(m(_.headAttributes))}> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> ${_.csp?B`<meta http-equiv="Content-Security-Policy" content="${_.csp}" />`:""} <title>${_.title}</title> ${_.description?B`<meta name="description" content="${_.description}" />`:""} <!-- Open Graph / Facebook --> <meta prefix="og: http://ogp.me/ns#" /> <meta property="og:title" content="${_.title}" /> ${_.description?B`<meta property="og:description" content="${_.description}" />`:""} ${_.image?B`<meta property="og:image" content="${_.image}" />`:""} ${_.url?B`<meta property="og:url" content="${_.url}" />`:""} ${_.locale?B`<meta property="og:locale" content="${_.locale}" />`:""} ${_.type?B`<meta property="og:type" content="${_.type}" />`:""} ${_.siteName?B`<meta property="og:site_name" content="${_.siteName}" />`:""} <!-- Twitter --> <meta name="twitter:card" content="${_.twitterCard||(_.image?"summary_large_image":"summary")}" /> <meta name="twitter:title" content="${_.title}" /> ${_.description?B`<meta name="twitter:description" content="${_.description}" />`:""} ${_.image?B`<meta name="twitter:image" content="${_.image}" />`:""} <!-- Custom Meta Tags --> ${_.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}" />`}):""} <!-- Favicon --> ${_.favicon?B`<link rel="icon" href="${_.favicon}" />`:""} <!-- Stylesheets --> ${_.stylesheets?_.stylesheets.map((W)=>B`<link rel="stylesheet" href="${W}" />`):""} <!-- Scripts --> ${_.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>`}):""} </head> <body ${h(m(_.bodyAttributes))}> ${_.children} </body> </html> `};function s($="",_={}){return(W)=>{X.setControllerPath(W,$),X.setControllerOptions(W,_)}}var l=b("get"),B_=b("post"),U_=b("put"),z_=b("delete"),L_=b("patch"),k_=b("options"),j_=b("all");function n($={}){return(_)=>{X.setModuleOptions(_,$)}}function H_($="",_={prefix:null,version:null}){return s($,_)}var O_=l;function T_($={}){return n({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),I_=k("response",($,_)=>_.res),C_=k("context",($,_)=>_),v_=k("context",($,_)=>_),y_=k("variable",($,_)=>_.get($)),u_=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{v$ as stripEndSlash,u as normalizePath,K$ as isUndefined,I$ as isSymbol,y as isString,f$ as isPlainObject,v as isObject,M$ as isNumber,H as isNil,c as isFunction,x$ as isEmpty,i as isConstructor,k as createParamDecorator,b as createHttpMethodDecorator,R as createErrorResponse,C$ as addLeadingSlash,H_ as View,u_ as Variable,y_ as Var,C as VERSION_NEUTRAL,WW as UsePipes,e_ as UseMiddleware,r_ as UseGuards,l_ as UseFilters,i_ as UseComponent,m_ as Service,T as RouteRegistry,g as RouteManager,I_ 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,I as NotFoundHandler,T_ as MvcModule,n as Module,X as MetadataRegistry,Y_ as Layout,K_ as Header,l as Get,x as ErrorHandler,z_ as Delete,C_ as Ctx,s as Controller,v_ as Context,M as Container,Z as ComponentManager,w_ as Body,p as Application,j_ as All};