tezx 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,5 +1,2503 @@
1
- "use strict";var P=Object.create;var O=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var L=Object.getOwnPropertyNames;var H=Object.getPrototypeOf,z=Object.prototype.hasOwnProperty;var d=(l,e)=>O(l,"name",{value:e,configurable:!0});var I=(l,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of L(e))!z.call(l,n)&&n!==t&&O(l,n,{get:()=>e[n],enumerable:!(s=k(e,n))||s.enumerable});return l};var R=(l,e,t)=>(t=l!=null?P(H(l)):{},I(e||!l||!l.__esModule?O(t,"default",{value:l,enumerable:!0}):t,l));class B{static{d(this,"HeadersParser")}headers=new Map;constructor(e){e&&this.add(e)}add(e){if(Array.isArray(e))for(const[t,s]of e)this.set(t,s);else if(typeof Headers<"u"&&e instanceof Headers)for(const[t,s]of e.entries())this.set(t,s);else if(typeof e=="object")for(const t in e)Object.prototype.hasOwnProperty.call(e,t)&&this.set(t,e[t]);return this}set(e,t){return this.headers.set(e.toLowerCase(),Array.isArray(t)?t:[t]),this}get(e){const t=this.headers.get(e.toLowerCase());return t?t[0]:void 0}getAll(e){return this.headers.get(e.toLowerCase())||[]}has(e){return this.headers.has(e.toLowerCase())}delete(e){return this.headers.delete(e.toLowerCase())}append(e,t){const s=e.toLowerCase();return this.headers.has(s)?this.headers.get(s).push(t):this.headers.set(s,[t]),this}entries(){return this.headers.entries()}keys(){return this.headers.keys()}values(){return this.headers.values()}forEach(e){for(const[t,s]of this.headers)e(s,t)}toObject(){const e={};for(const[t,s]of this.headers.entries())e[t]=s.length>1?s:s[0];return e}}Object.defineProperty(B,"name",{value:"Headers"});class x{static{d(this,"EnvironmentDetector")}static get getEnvironment(){return typeof Bun<"u"?"bun":typeof Deno<"u"?"deno":typeof process<"u"&&process.versions?.node?"node":"unknown"}static detectProtocol(e){try{return this.getEnvironment==="node"?e?.socket?.encrypted?"https":"http":"unknown"}catch{throw new Error("Failed to detect protocol.")}}static getHost(e){try{return e?.get("host")||"unknown"}catch{throw new Error("Failed to get host.")}}}async function F(l){const e=x.getEnvironment;if(e==="node")return new Promise((t,s)=>{let n="";l.on("data",r=>{n+=r.toString()}),l.on("end",()=>{try{t(JSON.parse(n))}catch{s(new Error("Invalid JSON format"))}})});if(e==="deno"||e==="bun")return await l.json();throw new Error("Unsupported environment for multipart parsing")}d(F,"parseJsonBody");async function q(l){const e=x.getEnvironment;if(e==="node")return new Promise((t,s)=>{let n="";l.on("data",r=>{n+=r.toString()}),l.on("end",()=>{try{t(n)}catch{s(new Error("Invalid JSON format"))}})});if(e==="deno"||e==="bun")return await l.text();throw new Error("Unsupported environment for multipart parsing")}d(q,"parseTextBody");async function U(l){const e=x.getEnvironment;if(e==="node")return new Promise((t,s)=>{let n="";l.on("data",r=>{n+=r.toString("binary")}),l.on("end",()=>{try{const r=n.split("&"),i={};r.forEach(o=>{const[a,c]=o.split("=");i[decodeURIComponent(a)]=decodeURIComponent(c||"")}),t(i)}catch{s(new Error("Invalid x-www-form-urlencoded format"))}})});if(e==="deno"||e==="bun"){const t=await l.formData(),s={};for(const[n,r]of t.entries())s[n]=r;return s}else throw new Error("Unsupported environment for multipart parsing")}d(U,"parseUrlEncodedBody");async function W(l,e,t){const s=x.getEnvironment;if(t?.sanitized,s==="node")return new Promise((n,r)=>{let i="";l.on("data",o=>{i+=o.toString("binary")}),l.on("end",()=>{try{const o={};i.split("----------------------------").forEach(h=>{const u=h.match(/name="(.*)"\r\n\r\n(.*)\r\n/);if(u&&u.length===3){const f=u[1],p=u[2];o[f]=p}});const c=i.split(`--${e}`);for(const h of c)if(h.includes("filename")){const u=h.match(/filename="([^"]+)"/),f=h.match(/name="([^"]+)"/),p=h.match(/Content-Type: ([^\r\n]+)/);if(u&&f&&p){let m=u[1];const y=f[1],g=p[1];t?.sanitized&&(m=`${Date.now()}-${m.replace(/\s+/g,"")?.replace(/[^a-zA-Z0-9.-]/g,"-")}`?.toLowerCase()),Array.isArray(t?.allowedTypes)&&!t.allowedTypes?.includes(g)&&r(`Invalid file type: "${g}". Allowed types: ${t.allowedTypes.join(", ")}`);const j=h.indexOf(`\r
2
- \r
3
- `)+4,v=Buffer.from(h.substring(j),"binary"),A=v.buffer.slice(v.byteOffset,v.byteOffset+v.byteLength);typeof t?.maxSize<"u"&&v.byteLength>t.maxSize&&r(`File size exceeds the limit: ${v.byteLength} bytes (Max: ${t.maxSize} bytes)`);const T=new File([A],m,{type:g});o[y]?Array.isArray(o[y])?o[y].push(T):o[y]=[o[y],T]:o[y]=T}}n(o)}catch{}})});if(s==="deno"||s==="bun"){const n=await l.formData(),r={};for(const[i,o]of n.entries()){let a=o;if(a instanceof File&&typeof t=="object"){let c=a.name;if(t?.sanitized&&(c=`${Date.now()}-${c.replace(/\s+/g,"")?.replace(/[^a-zA-Z0-9.-]/g,"-")}`?.toLowerCase()),Array.isArray(t?.allowedTypes)&&!t.allowedTypes?.includes(a.type))throw new Error(`Invalid file type: "${a.type}". Allowed types: ${t.allowedTypes.join(", ")}`);if(typeof t?.maxSize<"u"&&a.size>t.maxSize)throw new Error(`File size exceeds the limit: ${a.size} bytes (Max: ${t.maxSize} bytes)`);a=new File([await a.arrayBuffer()],c,{type:a.type})}r[i]?Array.isArray(r[i])?r[i].push(a):r[i]=[r[i],a]:r[i]=a}return r}else throw new Error("Unsupported environment for multipart parsing")}d(W,"parseMultipartBody");function J(l){const e=/^(?:(\w+):\/\/)?(?:([^:@]+)?(?::([^@]+))?@)?([^:/?#]+)?(?::(\d+))?(\/[^?#]*)?(?:\?([^#]*))?(?:#(.*))?$/;let t=l.match(e);const[s,n,r,i,o,a,c,h,u]=t;let f=o;n&&(f=n+"://"+o),a&&(f=f+":"+a);let p=c;p?.endsWith("/")&&p.slice(0,-1);function m(){return h?(decodeURIComponent(h).split("&")?.map(v=>{const[A,T]=v.split("=");return{[A]:T}})).reduce(function(v,A){return{...v,...A}},{}):{}}return d(m,"query"),{pathname:p,hash:u,protocol:n,origin:f,username:r,password:i,hostname:o,href:l,port:a,query:m()}}d(J,"urlParse");class V{static{d(this,"Request")}headers=new B;url;method;urlRef={hash:void 0,protocol:void 0,origin:void 0,username:void 0,password:void 0,hostname:void 0,port:void 0,href:void 0,query:{},pathname:"/"};query;#e;params={};constructor(e,t){if(this.headers=new B(e?.headers),this.method=e?.method?.toUpperCase(),this.params=t,this.#e=e,x.getEnvironment=="node"){const s=x.detectProtocol(e),n=x.getHost(this.headers);this.url=`${s}://${n}${e.url}`}else this.url=e.url;this.urlRef=J(this.url),this.query=this.urlRef.query}async text(){return await q(this.#e)}async json(){return(this.headers.get("content-type")||"").includes("application/json")?await F(this.#e):{}}async formData(e){const t=this.headers.get("content-type")||"";if(!t)throw Error("Invalid Content-Type");if(t.includes("application/json"))return await F(this.#e);if(t.includes("application/x-www-form-urlencoded"))return U(this.#e);if(t.includes("multipart/form-data")){const s=t?.split("; ")?.[1]?.split("=")?.[1];if(!s)throw Error("Boundary not found");return await W(this.#e,s,e)}else return{}}}class M{static{d(this,"JetResponse")}static json(e,...t){let s=200,n={"Content-Type":"application/json; charset=utf-8"};return typeof t[0]=="number"?(s=t[0],typeof t[1]=="object"&&(n={...n,...t[1]})):typeof t[0]=="object"&&(n={...n,...t[0]}),new Response(JSON.stringify(e),{status:s,headers:n})}static html(e,...t){let s=200,n={"Content-Type":"text/html; charset=utf-8"};return typeof t[0]=="number"?(s=t[0],typeof t[1]=="object"&&(n={...n,...t[1]})):typeof t[0]=="object"&&(n={...n,...t[0]}),new Response(e,{status:s,headers:n})}static text(e,...t){let s=200,n={"Content-Type":"text/plain; charset=utf-8"};return typeof t[0]=="number"?(s=t[0],typeof t[1]=="object"&&(n={...n,...t[1]})):typeof t[0]=="object"&&(n={...n,...t[0]}),new Response(e,{status:s,headers:n})}static xml(e,...t){let s=200,n={"Content-Type":"application/xml; charset=utf-8"};return typeof t[0]=="number"?(s=t[0],typeof t[1]=="object"&&(n={...n,...t[1]})):typeof t[0]=="object"&&(n={...n,...t[0]}),new Response(e,{status:s,headers:n})}static send(e,...t){let s=200,n={};return typeof t[0]=="number"?(s=t[0],typeof t[1]=="object"&&(n=t[1])):typeof t[0]=="object"&&(n=t[0]),n["Content-Type"]||(typeof e=="string"?n["Content-Type"]="text/plain;":typeof e=="object"&&e!==null?(n["Content-Type"]="application/json;",e=JSON.stringify(e)):n["Content-Type"]="application/octet-stream"),new Response(e,{status:s,headers:n})}static redirect(e,t=302,s){return new Response(null,{status:t,headers:{Location:e}})}static async download(e,t){try{let s=!1;const n=x.getEnvironment;if(n==="node"){const{existsSync:i}=await import("fs");s=i(e)}else if(n==="bun")s=Bun.file(e).exists();else if(n==="deno")try{await Deno.stat(e),s=!0}catch{s=!1}if(!s)throw Error("File not found");let r;if(n==="node"){const{readFileSync:i}=await import("fs");r=await i(e)}else n==="bun"?r=await Bun.file(e).arrayBuffer().then(i=>new Uint8Array(i)):n==="deno"&&(r=await Deno.readFile(e));return new Response(r,{status:200,headers:{"Content-Disposition":`attachment; filename="${t}"`,"Content-Type":"application/octet-stream","Content-Length":r.byteLength.toString()}})}catch(s){throw Error("Internal Server Error"+s?.message)}}static async sendFile(e,...t){try{const s=x.getEnvironment,n=e;let r=!1;if(s==="node"){const{existsSync:p}=await import("fs");r=p(n)}else if(s==="bun")r=Bun.file(n).exists();else if(s==="deno")try{await Deno.stat(n),r=!0}catch{r=!1}if(!r)throw Error("File not found");let i=0;if(s==="node"){const{statSync:p}=await import("fs");i=p(n).size}else s==="bun"?i=(await Bun.file(n).arrayBuffer()).byteLength:s==="deno"&&(i=(await Deno.stat(n)).size);const o={html:"text/html",htm:"text/html",css:"text/css",js:"application/javascript",json:"application/json",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",svg:"image/svg+xml",ico:"image/x-icon",pdf:"application/pdf",txt:"text/plain",xml:"application/xml",mp4:"video/mp4",webm:"video/webm",ogg:"audio/ogg",mp3:"audio/mpeg",wav:"audio/wav",zip:"application/zip",gz:"application/gzip",tar:"application/x-tar"},a=e.split(".").pop()?.toLowerCase()||"",c=o[a]||"application/octet-stream";let h;if(s==="node"){const{createReadStream:p}=await import("fs");h=p(n)}else s==="bun"?h=Bun.file(n).stream():s==="deno"&&(h=(await Deno.open(n,{read:!0})).readable);let u={"Content-Type":c,"Content-Length":i.toString()},f="";return typeof t[0]=="string"?(f=t[0],typeof t[1]=="object"&&(u={...u,...t[1]})):typeof t[0]=="object"&&(u={...u,...t[0]}),f&&(u["Content-Disposition"]=`attachment; filename="${f}"`),new Response(h,{status:200,headers:u})}catch(s){throw Error("Internal Server Error"+s?.message)}}}class G{static{d(this,"State")}state;constructor(){this.state=new Map}set(e,t){this.state.set(e,t)}get(e){return this.state.get(e)}delete(e){return this.state.delete(e)}has(e){return this.state.has(e)}keys(){return Array.from(this.state.keys())}values(){return Array.from(this.state.values())}entries(){return Array.from(this.state.entries())}clear(){this.state.clear()}}const N={100:"Continue",101:"Switching Protocols",102:"Processing",103:"Early Hints",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",207:"Multi-Status",208:"Already Reported",226:"IM Used",300:"Multiple Choices",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",306:"Switch Proxy",307:"Temporary Redirect",308:"Permanent Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Payload Too Large",414:"URI Too Long",415:"Unsupported Media Type",416:"Range Not Satisfiable",417:"Expectation Failed",418:"I'm a Teapot",421:"Misdirected Request",422:"Unprocessable Entity",423:"Locked",424:"Failed Dependency",425:"Too Early",426:"Upgrade Required",428:"Precondition Required",429:"Too Many Requests",431:"Request Header Fields Too Large",451:"Unavailable For Legal Reasons",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported",506:"Variant Also Negotiates",507:"Insufficient Storage",508:"Loop Detected",510:"Not Extended",511:"Network Authentication Required"};class Z{static{d(this,"Context")}#e;env={};headers=new B;res=new Response;pathname;url;method;#t=200;state=new G;#n={};#r;finalized=!1;#s;#o;#i;#a;#l=!0;#c;#d;#f;#u;#h;constructor(e){this.#e=e,this.method=e?.method?.toUpperCase(),this.pathname=this.req.urlRef.pathname,this.url=this.req.url}get cookies(){const e=this.headers.getAll("cookie");let t={};if(Array.isArray(e)&&e.length!=0){const s=e.join("; ").split(";");for(const n of s){const[r,i]=n?.trim()?.split("=");t[r]=decodeURIComponent(i)}}else if(typeof e=="string"){const s=e.split(";");for(const n of s){const[r,i]=n?.trim()?.split("=");t[r]=decodeURIComponent(i)}}return{get:d(s=>t?.[s],"get"),all:d(()=>t,"all"),delete:d((s,n)=>{const r="",i={...n,expires:new Date(0)},o=`${s}=${r};${D(i)}`;this.headers.set("Set-Cookie",o)},"delete"),set:d((s,n,r)=>{const i=`${s}=${n};${D(r||{})}`;this.headers.set("Set-Cookie",i)},"set")}}json(e,...t){let s=this.#t,n={"Content-Type":"application/json; charset=utf-8"};return typeof t[0]=="number"?(s=t[0],typeof t[1]=="object"&&(n={...n,...t[1]})):typeof t[0]=="object"&&(n={...n,...t[0]}),new Response(JSON.stringify(e),{status:s,headers:n})}send(e,...t){let s=this.#t,n={};return typeof t[0]=="number"?(s=t[0],typeof t[1]=="object"&&(n=t[1])):typeof t[0]=="object"&&(n=t[0]),n["Content-Type"]||(typeof e=="string"?n["Content-Type"]="text/plain;":typeof e=="object"&&e!==null?(n["Content-Type"]="application/json;",e=JSON.stringify(e)):n["Content-Type"]="application/octet-stream"),new Response(e,{status:s,headers:n})}html(e,...t){let s=this.#t,n={"Content-Type":"text/html; charset=utf-8"};return typeof t[0]=="number"?(s=t[0],typeof t[1]=="object"&&(n={...n,...t[1]})):typeof t[0]=="object"&&(n={...n,...t[0]}),new Response(e,{status:s,headers:n})}text(e,...t){let s=this.#t,n={"Content-Type":"text/plain; charset=utf-8"};return typeof t[0]=="number"?(s=t[0],typeof t[1]=="object"&&(n={...n,...t[1]})):typeof t[0]=="object"&&(n={...n,...t[0]}),new Response(e,{status:s,headers:n})}xml(e,...t){let s=this.#t,n={"Content-Type":"application/xml; charset=utf-8"};return typeof t[0]=="number"?(s=t[0],typeof t[1]=="object"&&(n={...n,...t[1]})):typeof t[0]=="object"&&(n={...n,...t[0]}),new Response(e,{status:s,headers:n})}status=d(e=>(this.#t=e,this),"status");redirect(e,t=302,s){return M.redirect(e,t,s)}async download(e,t){return await M.download(e,t)}async sendFile(e,...t){return await M.sendFile(e,...t)}get req(){return new V(this.#e,this.params)}set params(e){this.#n=e}get params(){return this.#n}}function D(l){const e=[];return l.maxAge&&e.push(`Max-Age=${l.maxAge}`),l.expires&&e.push(`Expires=${l.expires.toUTCString()}`),l.path&&e.push(`Path=${l.path}`),l.domain&&e.push(`Domain=${l.domain}`),l.secure&&e.push("Secure"),l.httpOnly&&e.push("HttpOnly"),l.sameSite&&e.push(`SameSite=${l.sameSite}`),e.join("; ")}d(D,"serializeOptions");let b=class{static{d(this,"GlobalConfig")}static middlewareRule="ignore";static env;static notFound=d(l=>{const{method:e,urlRef:{pathname:t}}=l.req;return new Response(`${e}: '${t}' could not find
4
- `,{headers:{"Content-Type":"text/plain"},status:404})},"notFound");static onError=d((l,e)=>{throw Error(l)},"onError");static loggerFn=d(()=>({}),"loggerFn")};function _(l){async function e(s,n){console.log(n.addr);const r=await l.serve(s);return r instanceof Response?r:new Response(r.body,{status:r.status,statusText:r.statusText||N[r?.status],headers:new Headers(r.headers)})}d(e,"handleRequest");function t(s,n){const r=typeof Deno<"u";try{const i=r?Deno.serve({port:s},e):null;if(!i)throw new Error("Deno is not find");const a=`\x1B[1m\u{1F680} Deno Accelero Server running at \x1B[1;34mhttp\x1B[0m://localhost:${s}/\x1B[0m`;if(typeof n=="function")n(a);else{const c=b.loggerFn();c.success&&c.success(a)}return i}catch(i){throw new Error(i?.message)}}return d(t,"listen"),{listen:t}}d(_,"denoAdapter");function K(l){function e(t,s){const n=typeof Bun<"u"?Bun.serve:null;try{if(!n)throw new Error("Bun is not find");const r=n({port:t,async fetch(a){console.log(r.requestIP(a));const c=await l.serve(a);return c instanceof Response?c:new Response(c.body,{status:c.status,statusText:c.statusText||N[c?.status],headers:new Headers(c.headers)})}}),o=`\x1B[1m Bun \u{1F680}Accelero Server running at \x1B[1;34mhttp\x1B[0m://localhost:${t}/\x1B[0m`;if(typeof s=="function")s(o);else{const a=b.loggerFn();a.success&&a.success(o)}return r}catch(r){throw new Error(r?.message)}}return d(e,"listen"),{listen:e}}d(K,"bunAdapter");function Q(l){function e(t,s){import("http").then(n=>{let r=n.createServer(async(i,o)=>{const a=await l.serve(i);console.log(i.socket.remoteAddress);const c=a?.statusText;if(!(a instanceof Response))throw new Error("Invalid response from Accelero.serve");const h=Object.fromEntries(await a.headers.entries());c&&(o.statusMessage=c),o.writeHead(a.status,h);const{Readable:u}=await import("stream");if(a.body instanceof u)a.body.pipe(o);else{const f=await a.arrayBuffer();o.end(Buffer.from(f))}});r.listen(t,()=>{const o=`\x1B[1m NodeJS \u{1F680}Accelero Server running at \x1B[1;34mhttp\x1B[0m://localhost:${t}/\x1B[0m`;if(typeof s=="function")s(o);else{const a=b.loggerFn();a.success&&a.success(o)}return r})}).catch(n=>{throw Error(n.message)})}return d(e,"listen"),{listen:e}}d(Q,"nodeAdapter");class X{static{d(this,"CommonHandler")}notFound(e){return b.notFound=e,this}onError(e){return b.onError=e,this}}class ${static{d(this,"TriMiddleware")}children=new Map;middlewares=[];groupMiddlewares=new Map;isOptional=!1;pathname;constructor(e="/"){this.pathname=e}}class Y extends X{static{d(this,"MiddlewareConfigure")}triMiddlewares=new $;basePath;constructor(e="/"){super(),this.basePath=e}addMiddleware(e,t){const s=`${this.basePath}/${e}`?.split("/").filter(Boolean);let n=this.triMiddlewares;for(const r of s)if(r.startsWith("*"))n.children.has("*")||n.children.set("*",new $),n=n.children.get("*");else if(r.startsWith(":")){const i=r?.endsWith("?");if(i){n.isOptional=i;continue}n.children.has(":")||n.children.set(":",new $),n=n.children.get(":")}else n.children.has(r)||n.children.set(r,new $),n=n.children.get(r);n.middlewares.push(...t)}}class S{static{d(this,"TrieRouter")}children=new Map;handlers=new Map;pathname;paramName;isParam=!1;constructor(e="/"){this.children=new Map,this.pathname=e}}class E extends Y{static{d(this,"Router")}routers=new Map;rootNode;constructor({basePath:e="/",env:t={}}={}){super(e),this.basePath=e,b.env={...b.env,...t},this.rootNode=new S(e),this.get.bind(this),this.post.bind(this),this.put.bind(this),this.delete.bind(this),this.all.bind(this),this.#s.bind(this),this.addRouter.bind(this),this.group.bind(this)}get(e,...t){return this.#e("GET",e,...t),this}post(e,...t){return this.#e("POST",e,...t),this}put(e,...t){return this.#e("PUT",e,...t),this}patch(e,...t){return this.#e("PATCH",e,...t),this}delete(e,...t){return this.#e("DELETE",e,...t),this}options(e,...t){return this.#e("OPTIONS",e,...t),this}head(e,...t){return this.#e("HEAD",e,...t),this}all(e,...t){return this.#e("ALL",e,...t),this}addRoute(e,t,...s){return this.#e(e,t,...s),this}addRouter(e,t){return this.#s(e,t)}group(e,t){const s=new E({basePath:e,env:b.env});return t(s),this.#s("/",s),this}use(...e){let t="/",s=[],n;return typeof e[0]=="string"?(t=e[0],Array.isArray(e[1])?(s=e[1],n=e[2]):typeof e[1]=="function"?(s=[e[1]],n=e[2]):n=e[1]):typeof e[0]=="function"?e.length===1?s=[e[0]]:(s=[e[0]],n=e[1]):Array.isArray(e[0])?(s=e[0],n=e[1]):e[0]instanceof E&&(n=e[0]),this.#n(t,s),n&&n instanceof E&&this.addRouter(t,n),this}#e(e,t,...s){if(s.length===0)throw new Error("At least one handler is required.");let n=[],r;if(s.length>1?(Array.isArray(s[0])?n=s[0]:typeof s[0]=="function"&&(n=[s[0]]),r=s[s.length-1]):r=s[0],typeof r!="function")throw new Error("Route callback function is missing or invalid.");if(!n.every(i=>typeof i=="function"))throw new Error("Middleware must be a function or an array of functions.");this.#t(e,t,r,n)}#t(e,t,s,n){const r=`${this.basePath}/${t}`.replace(/\\/g,"")?.split("/").filter(Boolean);let i=r.join("/");if(/(\/\*|\?)/.test(i)){let a=this.routers.get(i);return a?a.set(e,{callback:s,middlewares:n}):(a=new Map,a.set(e,{callback:s,middlewares:n}),this.routers.set(i,a))}let o=this.rootNode;for(const a of r)a.startsWith(":")?(o.children.has(":")||o.children.set(":",new S),o=o.children.get(":"),o.isParam=!0,o.paramName||(o.paramName=a.slice(1))):(o.children.has(a)||o.children.set(a,new S),o=o.children.get(a));o.handlers.set(e,{callback:s,middlewares:n}),o.pathname=t}#n(e,t){this.addMiddleware(e,t)}#r(){return`HNDLR-${Date.now().toString(16)}-${Math.random().toString(16).slice(2)}`}#s(e,t){const s=`${this.basePath}/${e}`.replace(/\\/g,"")?.split("/").filter(Boolean);let n;if(b.middlewareRule=="ignore"&&(n=this.#r()),t.routers.size)for(const[o,a]of t.routers){let c=o;if(s.length!==0&&(c=s?.join("/")+"/"+o),this.routers.has(c)){const h=this.routers.get(c);for(const[u,f]of a)f.handlerID=n,h.set(u,f);continue}if(n)for(const[h,u]of a)u.handlerID=n;this.routers.set(c,a)}let r=this.rootNode,i=this.triMiddlewares;if(s.length==0)this.#o(r,i,t,n);else{for(const o of s)o.startsWith(":")?(r.children.has(":")||r.children.set(":",new S),r=r.children.get(":"),r.isParam=!0,r.paramName||(r.paramName=o.slice(1))):(r.children.has(o)||r.children.set(o,new S),r=r.children.get(o));for(const o of s)if(o.startsWith("*"))i.children.has("*")||i.children.set("*",new $),i=i.children.get("*");else if(o.startsWith(":")){const a=o?.endsWith("?");if(a){i.isOptional=a;continue}i.children.has(":")||i.children.set(":",new $),i=i.children.get(":")}else i.children.has(o)||i.children.set(o,new $),i=i.children.get(o);this.#o(r,i,t,n)}}#o(e,t,s,n){function r(c,h){let u=h;for(const f of c)if(u.children.has(f[0])){let p=u.children.get(f[0]);for(const[m,y]of f[1].handlers){let g={...y,handlerID:n};p.handlers.set(m,g)}f[1].children.size&&r(f[1].children,p)}else{if(n){let p=d(function(m){for(const[y,g]of m.handlers)g.handlerID=n;for(const[y,g]of m.children)p(g)},"assignHandlerIDs2");p(f[1])}u.children.set(f[0],f[1])}}d(r,"addSubRouter");function i(c,h){let u=h;for(const[f,p]of c)if(u.children.has(f)){let m=u.children.get(f);if(n){let y=[...p.middlewares];m.groupMiddlewares.set(n,y)}else m.middlewares.push(...p.middlewares);p.children.size&&i(p.children,m)}else{if(n){let m=d(function(y){let g=[...y.middlewares];y.groupMiddlewares.set(n,g);for(const[,j]of y.children)m(j)},"assignHandlerIDs2");m(p)}u.children.set(f,p)}}d(i,"addMiddleware");let o=s.rootNode;const a=s.triMiddlewares;for(const[c,h]of o.handlers){let u={...h,handlerID:n};e.handlers.set(c,u)}o.children.size>0&&r(o.children,e),n?t.groupMiddlewares.set(n,[...a.middlewares]):t.middlewares.push(...a.middlewares),a.children.size>0&&i(a.children,t)}}function ee({path:l,urlPattern:e}){let t={};l=l.replace(/^\/+|\/+$/g,""),e=e.replace(/^\/+|\/+$/g,"");const s=l?l.split("/"):[],n=e?e.split("/"):[],r=s.length,i=n.length;if(r>i&&!e.includes("*"))return{success:!1,params:{}};let o=0;for(let a=0;a<i;a++){const c=n[a];if(c?.startsWith("*")){const u=n.slice(a+1);let f=c.length==1?"*":c?.slice(1);if(u.length>0){const p=u.join("/"),m=s.slice(r-u.length).join("/"),y=s.slice(o,r-u.length).join("/");return p!==m||!y?{success:!1,params:{}}:(t[f]=y,{success:!0,params:t})}else{const p=s.slice(o).join("/");return p?(t[f]=p,{success:!0,params:t}):{success:!1,params:{}}}}if(c.startsWith(":")&&c.endsWith("?")){const u=c.slice(1,-1),f=n[a+1];if(f&&!f.startsWith(":")&&f!=="*"&&o<r&&s[o]===f){t[u]=null;continue}const m=n.slice(a+1).filter(g=>!(g.startsWith(":")&&g.endsWith("?"))).length;r-o===m?t[u]=null:o<r?(t[u]=s[o],o++):t[u]=null;continue}if(c.startsWith(":")){const u=c.slice(1);if(!/^[a-zA-Z0-9_]+$/.test(u))return{success:!1,params:{}};if(o<r)t[u]=s[o],o++;else return{success:!1,params:{}};continue}const h=s[o];if(c!==h)return{success:!1,params:{}};o++}return o<r?{success:!1,params:{}}:{success:!0,params:t}}d(ee,"useParams");class te extends E{static{d(this,"Accelero")}constructor({basePath:e="/",middlewareRule:t="follow",env:s={},logger:n=void 0}={}){super({basePath:e,env:s}),b.middlewareRule=t,n&&(b.loggerFn=n),this.serve=this.serve.bind(this)}#e(e,t){const s=this.routers;for(let n of this.routers.keys()){const{success:r,params:i}=ee({path:t,urlPattern:n}),o=s.get(n)?.get(e)||s.get(n)?.get("ALL");if(r&&o)return{handlerID:o.handlerID,callback:o.callback,middlewares:o.middlewares,params:i}}return null}#t(e,t){const s=t.split("/").filter(Boolean),n={};let r=this.rootNode;for(let i of s)if(r.children.has(i))r=r.children.get(i);else if(r.children.has(":"))r=r.children.get(":"),r.paramName&&(n[r.paramName]=i);else return null;if(r?.handlers?.size&&r?.pathname){const i=r.handlers.get(e)||r.handlers.get("ALL");return i?{handlerID:i?.handlerID,middlewares:i.middlewares,callback:i.callback,params:n}:null}return null}findRoute(e,t){return this.#t(e,t)||this.#e(e,t)}#n(e,t){return async s=>{let n=0;const r=d(async()=>n<e.length?e[n++](s,r):await t(s),"next");return await r()}}#r(e,t){const s=e.split("/").filter(Boolean);let n=[],r=this.triMiddlewares;for(let i of s){if(r.children.has(i))r=r.children.get(i);else if(r.children.has("*"))r=r.children.get("*");else if(r.children.has(":"))r=r.children.get(":");else break;t?n.push(...r.groupMiddlewares.get(t)||[]):n.push(...r.middlewares)}return n}async#s(e){let t=new Z(e);const s=t.req.urlRef,{pathname:n}=s;let r=this.#r(n);t.env=b.env;const i=b.loggerFn();i.request&&i.request(t.method,t.pathname);try{return await this.#n([...this.triMiddlewares.middlewares,...r],async o=>{const a=this.findRoute(o.req.method,n);if(a?.callback){o.params=a.params;const c=a.callback,h=a.handlerID;let u=[...a.middlewares];h&&u.push(...this.#r(n,h));const f=await this.#n(u,c)(o);f?.headers&&o.headers.add(f.headers);const p=f?.statusText||N[f?.status]||"",m=f.status||200;let y=o.headers.toObject();return i.response&&i.response(o.method,o.pathname,m),f instanceof Response?new Response(f.body,{status:m,statusText:p,headers:y}):new Response(f.body,{status:m,statusText:p,headers:y})}else return i.response&&i.response(o.method,o.pathname,404),b.notFound(o)})(t)}catch(o){let a=o;return o instanceof Error&&(a=o.message),i.error&&i.error(`${N[500]}: ${a} `),b.onError(a,t)}}async serve(e){return this.#s(e)}}function ne(l,e){try{let t=!1,s=x.getEnvironment;if(s==="node"||s==="bun"){const{existsSync:i}=require("fs");t=i(l)}else if(s==="deno")try{Deno.statSync(l),t=!0}catch{t=!1}if(!t)return;let n="";if(s==="node"||s==="bun"){const{readFileSync:i}=require("fs");n=i(l,"utf8")}else s==="deno"&&(n=new TextDecoder("utf-8").decode(Deno.readFileSync(l)));const r=n.split(`
5
- `);for(const i of r){const o=i.trim();if(!o||o.startsWith("#"))continue;const[a,c]=o.split("=",2).map(h=>h.trim());if(a&&c){const h=c.replace(/^"(.*)"$/,"$1").replace(/^'(.*)'$/,"$1");e[a]=h,s==="node"||s==="bun"?process.env[a]=h:s==="deno"&&Deno.env.set(a,h)}}}catch(t){console.error(`[dotenv] Error parsing file: ${l}`,t)}}d(ne,"parseEnvFile");function se(l="./"){const e={},t=[".env",".env.local",`.env.${process?.env?.NODE_ENV||"development"}`,`.env.${process?.env?.NODE_ENV||"development"}.local`];for(const s of t)ne(`${l}${s}`,e);return e}d(se,"loadEnv");const w={reset:"\x1B[0m",bold:"\x1B[1m",gray:"\x1B[90m",red:"\x1B[31m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",magenta:"\x1B[35m",cyan:"\x1B[36m",bgBlue:"\x1B[44m",bgMagenta:"\x1B[45m"},C=d((l,e,...t)=>{const s=new Date().toISOString(),n={info:w.blue,warn:w.yellow,error:w.red,debug:w.cyan,success:w.green},r=`${w.gray}[${s}]${w.reset}`,i=`${n[l]}[${l.toUpperCase()}]${w.reset}`;console.log(`${r} ${i} ${e}`,...t?.flat())},"loggerOutput");function re(){const l=performance.now();return{request:d((e,t)=>{console.log(`${w.bold}<-- ${w.reset}${w.bgMagenta} ${e} ${w.reset} ${t}`)},"request"),response:d((e,t,s)=>{const n=performance.now()-l;console.log(`${w.bold}--> ${w.reset}${w.bgBlue} ${e} ${w.reset} ${t} ${w.yellow}${s}${w.reset} ${w.magenta}${n.toFixed(2)}ms${w.reset}`)},"response"),info:d((e,...t)=>C("info",e,...t),"info"),warn:d((e,...t)=>C("warn",e,...t),"warn"),error:d((e,...t)=>C("error",e,...t),"error"),debug:d((e,...t)=>C("debug",e,...t),"debug"),success:d((e,...t)=>C("success",e,...t),"success")}}d(re,"logger");function oe(l={}){const{methods:e,allowedHeaders:t,credentials:s,exposedHeaders:n,maxAge:r,origin:i}=l;return async(o,a)=>{const c=o.req.headers.get("origin")||"";let h="*";return typeof i=="string"?h=i:i instanceof RegExp?h=i.test(c)?c:"":Array.isArray(i)?h=i.some(f=>{if(typeof f=="string")return f===c;if(f instanceof RegExp)return f.test(c)})?c:"":typeof i=="function"&&(h=i(c)?c:""),o.headers.set("Access-Control-Allow-Origin",h),o.headers.set("Access-Control-Allow-Methods",(e||["GET","POST","PUT","DELETE"]).join(", ")),o.headers.set("Access-Control-Allow-Headers",(t||["Content-Type","Authorization"]).join(", ")),n&&o.headers.set("Access-Control-Expose-Headers",n.join(", ")),s&&o.headers.set("Access-Control-Allow-Credentials","true"),r&&o.headers.set("Access-Control-Max-Age",r.toString()),o.req.method==="OPTIONS"?new Response(null,{status:204,headers:o.headers.toObject()}):await a()}}d(oe,"cors"),exports.Accelero=te,exports.JetResponse=M,exports.Router=E,exports.bunAdapter=K,exports.cors=oe,exports.denoAdapter=_,exports.loadEnv=se,exports.logger=re,exports.nodeAdapter=Q;
1
+ 'use strict';
2
+
3
+ let GlobalConfig = class {
4
+ static notFound = (ctx2) => {
5
+ const {
6
+ method,
7
+ urlRef: { pathname }
8
+ } = ctx2.req;
9
+ return ctx2.text(`${method}: '${pathname}' could not find
10
+ `, 404);
11
+ };
12
+ static onError = (err, ctx2) => {
13
+ return ctx2.text(err, 500);
14
+ };
15
+ static allowDuplicateMw = false;
16
+ static overwriteMethod = true;
17
+ static enableLogger = false;
18
+ static loggerFn = () => {
19
+ return {};
20
+ };
21
+ };
22
+
23
+ function denoAdapter(TezX2) {
24
+ async function handleRequest(req, x) {
25
+ const response = await TezX2.serve(req);
26
+ if (response instanceof Response) {
27
+ return response;
28
+ } else {
29
+ return new Response(response.body, {
30
+ status: response.status,
31
+ statusText: response.statusText || "",
32
+ headers: new Headers(response.headers)
33
+ });
34
+ }
35
+ }
36
+ function listen(port, callback) {
37
+ const isDeno = typeof Deno !== "undefined";
38
+ try {
39
+ const server = isDeno ? Deno.serve({ port }, handleRequest) : null;
40
+ if (!server) {
41
+ throw new Error("Deno is not find");
42
+ }
43
+ const protocol = "\x1B[1;34mhttp\x1B[0m";
44
+ const message = `\x1B[1m\u{1F680} Deno TezX Server running at ${protocol}://localhost:${port}/\x1B[0m`;
45
+ if (typeof callback === "function") {
46
+ callback(message);
47
+ } else {
48
+ const logger = GlobalConfig.loggerFn();
49
+ if (logger.success) {
50
+ logger.success(message);
51
+ }
52
+ }
53
+ return server;
54
+ } catch (err) {
55
+ throw new Error(err?.message);
56
+ }
57
+ }
58
+ return {
59
+ listen
60
+ };
61
+ }
62
+ function bunAdapter(TezX2) {
63
+ function listen(port, callback) {
64
+ const serve = typeof Bun !== "undefined" ? Bun.serve : null;
65
+ try {
66
+ if (!serve) {
67
+ throw new Error("Bun is not find");
68
+ }
69
+ const server = serve({
70
+ port,
71
+ async fetch(req) {
72
+ const response = await TezX2.serve(req);
73
+ if (response instanceof Response) {
74
+ return response;
75
+ } else {
76
+ return new Response(response.body, {
77
+ status: response.status,
78
+ statusText: response.statusText || "",
79
+ headers: new Headers(response.headers)
80
+ });
81
+ }
82
+ }
83
+ });
84
+ const protocol = "\x1B[1;34mhttp\x1B[0m";
85
+ const message = `\x1B[1m Bun TezX Server running at ${protocol}://localhost:${port}/\x1B[0m`;
86
+ if (typeof callback == "function") {
87
+ callback(message);
88
+ } else {
89
+ const logger = GlobalConfig.loggerFn();
90
+ if (logger.success) {
91
+ logger.success(message);
92
+ }
93
+ }
94
+ return server;
95
+ } catch (err) {
96
+ throw new Error(err?.message);
97
+ }
98
+ }
99
+ return {
100
+ listen
101
+ };
102
+ }
103
+ function nodeAdapter(TezX2) {
104
+ function listen(port, callback) {
105
+ import('http').then((r) => {
106
+ let server = r.createServer(async (req, res) => {
107
+ const response = await TezX2.serve(req);
108
+ const statusText = response?.statusText;
109
+ if (!(response instanceof Response)) {
110
+ throw new Error("Invalid response from TezX.serve");
111
+ }
112
+ const headers = Object.fromEntries(await response.headers.entries());
113
+ if (statusText) {
114
+ res.statusMessage = statusText;
115
+ }
116
+ res.writeHead(response.status, headers);
117
+ const { Readable } = await import('stream');
118
+ if (response.body instanceof Readable) {
119
+ response.body.pipe(res);
120
+ } else {
121
+ const body = await response.arrayBuffer();
122
+ res.end(Buffer.from(body));
123
+ }
124
+ });
125
+ server.listen(port, () => {
126
+ const protocol = "\x1B[1;34mhttp\x1B[0m";
127
+ const message = `\x1B[1m NodeJS TezX Server running at ${protocol}://localhost:${port}/\x1B[0m`;
128
+ if (typeof callback == "function") {
129
+ callback(message);
130
+ } else {
131
+ const logger = GlobalConfig.loggerFn();
132
+ if (logger.success) {
133
+ logger.success(message);
134
+ }
135
+ }
136
+ return server;
137
+ });
138
+ }).catch((r) => {
139
+ throw Error(r.message);
140
+ });
141
+ }
142
+ return {
143
+ listen
144
+ };
145
+ }
146
+
147
+ class EnvironmentDetector {
148
+ static get getEnvironment() {
149
+ if (typeof Bun !== "undefined") return "bun";
150
+ if (typeof Deno !== "undefined") return "deno";
151
+ if (typeof process !== "undefined" && process.versions?.node) return "node";
152
+ return "unknown";
153
+ }
154
+ static detectProtocol(req) {
155
+ try {
156
+ if (this.getEnvironment === "node") {
157
+ return req?.socket?.encrypted ? "https" : "http";
158
+ }
159
+ return "unknown";
160
+ } catch (error) {
161
+ throw new Error("Failed to detect protocol.");
162
+ }
163
+ }
164
+ static getHost(headers) {
165
+ try {
166
+ return headers?.get("host") || "unknown";
167
+ } catch (error) {
168
+ throw new Error("Failed to get host.");
169
+ }
170
+ }
171
+ }
172
+
173
+ const mimeTypes = {
174
+ // Text/Web Formats
175
+ html: "text/html",
176
+ htm: "text/html",
177
+ css: "text/css",
178
+ js: "text/javascript",
179
+ mjs: "text/javascript",
180
+ json: "application/json",
181
+ xml: "application/xml",
182
+ txt: "text/plain",
183
+ md: "text/markdown",
184
+ csv: "text/csv",
185
+ tsv: "text/tab-separated-values",
186
+ rtf: "application/rtf",
187
+ markdown: "text/markdown",
188
+ // Image Formats
189
+ png: "image/png",
190
+ jpg: "image/jpeg",
191
+ jpeg: "image/jpeg",
192
+ gif: "image/gif",
193
+ svg: "image/svg+xml",
194
+ webp: "image/webp",
195
+ ico: "image/x-icon",
196
+ bmp: "image/bmp",
197
+ tiff: "image/tiff",
198
+ psd: "image/vnd.adobe.photoshop",
199
+ // Video Formats
200
+ mp4: "video/mp4",
201
+ webm: "video/webm",
202
+ ogg: "video/ogg",
203
+ mov: "video/quicktime",
204
+ avi: "video/x-msvideo",
205
+ wmv: "video/x-ms-wmv",
206
+ flv: "video/x-flv",
207
+ "3gp": "video/3gpp",
208
+ // Audio Formats
209
+ mp3: "audio/mpeg",
210
+ wav: "audio/wav",
211
+ aac: "audio/aac",
212
+ flac: "audio/flac",
213
+ m4a: "audio/mp4",
214
+ mid: "audio/midi",
215
+ midi: "audio/midi",
216
+ // Font Formats
217
+ woff: "font/woff",
218
+ woff2: "font/woff2",
219
+ ttf: "font/ttf",
220
+ otf: "font/otf",
221
+ eot: "application/vnd.ms-fontobject",
222
+ // Application/Document Formats
223
+ pdf: "application/pdf",
224
+ odp: "application/vnd.oasis.opendocument.presentation",
225
+ zip: "application/zip",
226
+ gz: "application/gzip",
227
+ tar: "application/x-tar",
228
+ rar: "application/x-rar-compressed",
229
+ _7z: "application/x-7z-compressed",
230
+ bz2: "application/x-bzip2",
231
+ "7z": "application/x-7z-compressed",
232
+ doc: "application/msword",
233
+ docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
234
+ xls: "application/vnd.ms-excel",
235
+ xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
236
+ ppt: "application/vnd.ms-powerpoint",
237
+ pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
238
+ odt: "application/vnd.oasis.opendocument.text",
239
+ ods: "application/vnd.oasis.opendocument.spreadsheet",
240
+ // Programming/Data Formats
241
+ wasm: "application/wasm",
242
+ map: "application/json",
243
+ // Source maps
244
+ yaml: "application/yaml",
245
+ yml: "application/yaml",
246
+ proto: "text/plain",
247
+ graphql: "application/graphql",
248
+ // Security/Config Formats
249
+ pem: "application/x-pem-file",
250
+ cer: "application/pkix-cert",
251
+ crt: "application/x-x509-ca-cert",
252
+ key: "application/x-pem-file",
253
+ pfx: "application/x-pkcs12",
254
+ // 3D/Model Formats
255
+ glb: "model/gltf-binary",
256
+ gltf: "model/gltf+json",
257
+ obj: "model/obj",
258
+ stl: "model/stl",
259
+ // Virtual/Mixed Reality
260
+ usdz: "model/vnd.usdz+zip",
261
+ // System Formats
262
+ exe: "application/x-msdownload",
263
+ dmg: "application/x-apple-diskimage",
264
+ deb: "application/x-debian-package",
265
+ rpm: "application/x-redhat-package-manager",
266
+ apk: "application/vnd.android.package-archive",
267
+ // Special Web Formats
268
+ webmanifest: "application/manifest+json",
269
+ ics: "text/calendar",
270
+ vcf: "text/vcard",
271
+ warc: "application/warc",
272
+ atom: "application/atom+xml",
273
+ rss: "application/rss+xml",
274
+ // Executables and scripts
275
+ dll: "application/x-msdownload",
276
+ sh: "application/x-sh",
277
+ py: "text/x-python",
278
+ rb: "text/x-ruby",
279
+ pl: "text/x-perl",
280
+ php: "application/x-httpd-php",
281
+ // Miscellaneous
282
+ torrent: "application/x-bittorrent",
283
+ ipa: "application/vnd.iphone",
284
+ eps: "application/postscript",
285
+ ps: "application/postscript",
286
+ ai: "application/postscript",
287
+ swf: "application/x-shockwave-flash",
288
+ jar: "application/java-archive",
289
+ gcode: "text/x.gcode"
290
+ };
291
+ const defaultMimeType = "application/octet-stream";
292
+ async function getFiles(dir, basePath = "/", ref, option) {
293
+ const files = [];
294
+ const runtime = EnvironmentDetector.getEnvironment;
295
+ if (runtime == "deno") {
296
+ for await (const entry of Deno.readDir(dir)) {
297
+ const path = `${dir}/${entry.name}`;
298
+ if (entry.isDirectory) {
299
+ files.push(
300
+ ...await getFiles(path, `${basePath}/${entry.name}`, ref, option)
301
+ );
302
+ } else {
303
+ const x = `${basePath}/${entry.name}`;
304
+ files.push({
305
+ file: path,
306
+ path: x.replace(/\\/g, "/")
307
+ });
308
+ }
309
+ }
310
+ } else {
311
+ const fs = await import('fs/promises');
312
+ const path = await import('path');
313
+ const entries = await fs.readdir(dir, { withFileTypes: true });
314
+ for (const entry of entries) {
315
+ const fullPath = path.join(dir, entry.name);
316
+ if (entry.isDirectory()) {
317
+ files.push(
318
+ ...await getFiles(
319
+ fullPath,
320
+ `${basePath}/${entry.name}`,
321
+ ref,
322
+ option
323
+ )
324
+ );
325
+ } else {
326
+ const path2 = `${basePath}/${entry.name}`;
327
+ files.push({
328
+ file: fullPath,
329
+ path: path2.replace(/\\/g, "/")
330
+ });
331
+ }
332
+ }
333
+ }
334
+ files.forEach((r) => {
335
+ ref.get(r.path, (ctx2) => {
336
+ if (option.cacheControl) {
337
+ ctx2.headers.set("Cache-Control", option.cacheControl);
338
+ }
339
+ if (option.headers) {
340
+ ctx2.headers.add(option.headers);
341
+ }
342
+ return ctx2.sendFile(r.file);
343
+ });
344
+ });
345
+ return files;
346
+ }
347
+
348
+ class TezResponse {
349
+ static json(body, ...args) {
350
+ let status = 200;
351
+ let headers = {
352
+ "Content-Type": "application/json; charset=utf-8"
353
+ };
354
+ if (typeof args[0] === "number") {
355
+ status = args[0];
356
+ if (typeof args[1] === "object") {
357
+ headers = { ...headers, ...args[1] };
358
+ }
359
+ } else if (typeof args[0] === "object") {
360
+ headers = { ...headers, ...args[0] };
361
+ }
362
+ return new Response(JSON.stringify(body), {
363
+ status,
364
+ headers
365
+ });
366
+ }
367
+ static html(data, ...args) {
368
+ let status = 200;
369
+ let headers = {
370
+ "Content-Type": "text/html; charset=utf-8"
371
+ };
372
+ if (typeof args[0] === "number") {
373
+ status = args[0];
374
+ if (typeof args[1] === "object") {
375
+ headers = { ...headers, ...args[1] };
376
+ }
377
+ } else if (typeof args[0] === "object") {
378
+ headers = { ...headers, ...args[0] };
379
+ }
380
+ return new Response(data, {
381
+ status,
382
+ headers
383
+ });
384
+ }
385
+ static text(data, ...args) {
386
+ let status = 200;
387
+ let headers = {
388
+ "Content-Type": "text/plain; charset=utf-8"
389
+ };
390
+ if (typeof args[0] === "number") {
391
+ status = args[0];
392
+ if (typeof args[1] === "object") {
393
+ headers = { ...headers, ...args[1] };
394
+ }
395
+ } else if (typeof args[0] === "object") {
396
+ headers = { ...headers, ...args[0] };
397
+ }
398
+ return new Response(data, {
399
+ status,
400
+ headers
401
+ });
402
+ }
403
+ static xml(data, ...args) {
404
+ let status = 200;
405
+ let headers = {
406
+ "Content-Type": "application/xml; charset=utf-8"
407
+ };
408
+ if (typeof args[0] === "number") {
409
+ status = args[0];
410
+ if (typeof args[1] === "object") {
411
+ headers = { ...headers, ...args[1] };
412
+ }
413
+ } else if (typeof args[0] === "object") {
414
+ headers = { ...headers, ...args[0] };
415
+ }
416
+ return new Response(data, {
417
+ status,
418
+ headers
419
+ });
420
+ }
421
+ static send(body, ...args) {
422
+ let status = 200;
423
+ let headers = {};
424
+ if (typeof args[0] === "number") {
425
+ status = args[0];
426
+ if (typeof args[1] === "object") {
427
+ headers = args[1];
428
+ }
429
+ } else if (typeof args[0] === "object") {
430
+ headers = args[0];
431
+ }
432
+ if (!headers["Content-Type"]) {
433
+ if (typeof body === "string") {
434
+ headers["Content-Type"] = "text/plain;";
435
+ } else if (typeof body === "object" && body !== null) {
436
+ headers["Content-Type"] = "application/json;";
437
+ body = JSON.stringify(body);
438
+ } else {
439
+ headers["Content-Type"] = "application/octet-stream";
440
+ }
441
+ }
442
+ return new Response(body, {
443
+ status,
444
+ headers
445
+ });
446
+ }
447
+ /**
448
+ * Redirects to a given URL.
449
+ * @param url - The target URL.
450
+ * @param status - (Optional) HTTP status code (default: 302).
451
+ * @param headers - (Optional) Additional headers.
452
+ * @returns Response object with redirect.
453
+ */
454
+ static redirect(url, status = 302, headers) {
455
+ return new Response(null, {
456
+ status,
457
+ headers: { Location: url }
458
+ });
459
+ }
460
+ /**
461
+ * Handles file downloads.
462
+ * @param filePath - The path to the file.
463
+ * @param fileName - The name of the downloaded file.
464
+ * @returns Response object for file download.
465
+ */
466
+ static async download(filePath, fileName) {
467
+ try {
468
+ let fileExists = false;
469
+ const runtime = EnvironmentDetector.getEnvironment;
470
+ if (runtime === "node") {
471
+ const { existsSync } = await import('fs');
472
+ fileExists = existsSync(filePath);
473
+ } else if (runtime === "bun") {
474
+ fileExists = Bun.file(filePath).exists();
475
+ } else if (runtime === "deno") {
476
+ try {
477
+ await Deno.stat(filePath);
478
+ fileExists = true;
479
+ } catch {
480
+ fileExists = false;
481
+ }
482
+ }
483
+ if (!fileExists) {
484
+ throw Error("File not found");
485
+ }
486
+ let fileBuffer;
487
+ if (runtime === "node") {
488
+ const { readFileSync } = await import('fs');
489
+ fileBuffer = await readFileSync(filePath);
490
+ } else if (runtime === "bun") {
491
+ fileBuffer = await Bun.file(filePath).arrayBuffer().then((buf) => new Uint8Array(buf));
492
+ } else if (runtime === "deno") {
493
+ fileBuffer = await Deno.readFile(filePath);
494
+ }
495
+ return new Response(fileBuffer, {
496
+ status: 200,
497
+ headers: {
498
+ "Content-Disposition": `attachment; filename="${fileName}"`,
499
+ "Content-Type": "application/octet-stream",
500
+ "Content-Length": fileBuffer.byteLength.toString()
501
+ }
502
+ });
503
+ } catch (error) {
504
+ throw Error("Internal Server Error" + error?.message);
505
+ }
506
+ }
507
+ static async sendFile(filePath, ...args) {
508
+ try {
509
+ const runtime = EnvironmentDetector.getEnvironment;
510
+ const resolvedPath = filePath;
511
+ let fileExists = false;
512
+ if (runtime === "node") {
513
+ const { existsSync } = await import('fs');
514
+ fileExists = existsSync(resolvedPath);
515
+ } else if (runtime === "bun") {
516
+ fileExists = Bun.file(resolvedPath).exists();
517
+ } else if (runtime === "deno") {
518
+ try {
519
+ await Deno.stat(resolvedPath);
520
+ fileExists = true;
521
+ } catch {
522
+ fileExists = false;
523
+ }
524
+ }
525
+ if (!fileExists) {
526
+ throw Error("File not found");
527
+ }
528
+ let fileSize = 0;
529
+ if (runtime === "node") {
530
+ const { statSync } = await import('fs');
531
+ fileSize = statSync(resolvedPath).size;
532
+ } else if (runtime === "bun") {
533
+ fileSize = (await Bun.file(resolvedPath).arrayBuffer()).byteLength;
534
+ } else if (runtime === "deno") {
535
+ const fileInfo = await Deno.stat(resolvedPath);
536
+ fileSize = fileInfo.size;
537
+ }
538
+ const ext = filePath.split(".").pop()?.toLowerCase() || "";
539
+ const mimeType = mimeTypes[ext] || defaultMimeType;
540
+ let fileStream;
541
+ if (runtime === "node") {
542
+ const { createReadStream } = await import('fs');
543
+ fileStream = createReadStream(resolvedPath);
544
+ } else if (runtime === "bun") {
545
+ fileStream = Bun.file(resolvedPath).stream();
546
+ } else if (runtime === "deno") {
547
+ const file = await Deno.open(resolvedPath, { read: true });
548
+ fileStream = file.readable;
549
+ }
550
+ let headers = {
551
+ "Content-Type": mimeType,
552
+ "Content-Length": fileSize.toString()
553
+ };
554
+ let fileName = "";
555
+ if (typeof args[0] === "string") {
556
+ fileName = args[0];
557
+ if (typeof args[1] === "object") {
558
+ headers = { ...headers, ...args[1] };
559
+ }
560
+ } else if (typeof args[0] === "object") {
561
+ headers = { ...headers, ...args[0] };
562
+ }
563
+ if (fileName) {
564
+ headers["Content-Disposition"] = `attachment; filename="${fileName}"`;
565
+ }
566
+ return new Response(fileStream, {
567
+ status: 200,
568
+ headers
569
+ });
570
+ } catch (error) {
571
+ throw Error("Internal Server Error" + error?.message);
572
+ }
573
+ }
574
+ }
575
+
576
+ class CommonHandler {
577
+ /**
578
+ * Register a custom 404 handler for missing routes
579
+ * @param {Callback} callback - Handler function to execute when no route matches
580
+ * @returns {this} - Returns current instance for chaining
581
+ *
582
+ * @example
583
+ * // Register a custom not-found handler
584
+ * app.notFound((ctx) => {
585
+ * ctx.status(404).text('Custom not found message');
586
+ * });
587
+ */
588
+ notFound(callback) {
589
+ GlobalConfig.notFound = callback;
590
+ return this;
591
+ }
592
+ onError(callback) {
593
+ GlobalConfig.onError = callback;
594
+ return this;
595
+ }
596
+ }
597
+
598
+ function sanitizePathSplit(basePath, path) {
599
+ const parts = `${basePath}/${path}`.replace(/\\/g, "")?.split("/").filter(Boolean);
600
+ return parts;
601
+ }
602
+ function urlParse(url) {
603
+ const urlPattern = /^(?:(\w+):\/\/)?(?:([^:@]+)?(?::([^@]+))?@)?([^:/?#]+)?(?::(\d+))?(\/[^?#]*)?(?:\?([^#]*))?(?:#(.*))?$/;
604
+ let matches = url.match(urlPattern);
605
+ const [
606
+ _,
607
+ protocol,
608
+ username,
609
+ password,
610
+ hostname,
611
+ port,
612
+ path,
613
+ queryString,
614
+ hash
615
+ ] = matches;
616
+ let origin = hostname;
617
+ if (protocol) {
618
+ origin = protocol + "://" + hostname;
619
+ }
620
+ if (port) {
621
+ origin = origin + ":" + port;
622
+ }
623
+ let p = path;
624
+ if (p?.endsWith("/")) p.slice(0, -1);
625
+ function query() {
626
+ if (queryString) {
627
+ const queryPart = decodeURIComponent(queryString);
628
+ const keyValuePairs = queryPart.split("&");
629
+ const paramsObj = keyValuePairs?.map(
630
+ (keyValue) => {
631
+ const [key, value] = keyValue.split("=");
632
+ return {
633
+ [key]: value
634
+ };
635
+ }
636
+ );
637
+ return paramsObj.reduce(function(total, value) {
638
+ return { ...total, ...value };
639
+ }, {});
640
+ } else {
641
+ return {};
642
+ }
643
+ }
644
+ return {
645
+ pathname: p,
646
+ hash,
647
+ protocol,
648
+ origin,
649
+ username,
650
+ password,
651
+ hostname,
652
+ href: url,
653
+ port,
654
+ query: query()
655
+ };
656
+ }
657
+
658
+ class TriMiddleware {
659
+ children = /* @__PURE__ */ new Map();
660
+ middlewares = /* @__PURE__ */ new Set();
661
+ isOptional = false;
662
+ pathname;
663
+ constructor(pathname = "/") {
664
+ this.pathname = pathname;
665
+ if (GlobalConfig.allowDuplicateMw) {
666
+ this.middlewares = [];
667
+ } else {
668
+ this.middlewares = /* @__PURE__ */ new Set();
669
+ }
670
+ }
671
+ }
672
+ class MiddlewareConfigure extends CommonHandler {
673
+ triMiddlewares = new TriMiddleware();
674
+ basePath;
675
+ constructor(basePath = "/") {
676
+ super();
677
+ this.basePath = basePath;
678
+ }
679
+ addMiddleware(pathname, middlewares) {
680
+ const parts = sanitizePathSplit(this.basePath, pathname);
681
+ let node = this.triMiddlewares;
682
+ for (const part of parts) {
683
+ if (part.startsWith("*")) {
684
+ if (!node.children.has("*")) {
685
+ node.children.set("*", new TriMiddleware());
686
+ }
687
+ node = node.children.get("*");
688
+ } else if (part.startsWith(":")) {
689
+ const isOptional = part?.endsWith("?");
690
+ if (isOptional) {
691
+ node.isOptional = isOptional;
692
+ continue;
693
+ }
694
+ if (!node.children.has(":")) {
695
+ node.children.set(":", new TriMiddleware());
696
+ }
697
+ node = node.children.get(":");
698
+ } else {
699
+ if (!node.children.has(part)) {
700
+ node.children.set(part, new TriMiddleware());
701
+ }
702
+ node = node.children.get(part);
703
+ }
704
+ }
705
+ if (GlobalConfig.allowDuplicateMw) {
706
+ node.middlewares.push(...middlewares);
707
+ } else {
708
+ for (const middleware of middlewares) {
709
+ node.middlewares.add(middleware);
710
+ }
711
+ }
712
+ }
713
+ }
714
+
715
+ class TrieRouter {
716
+ children = /* @__PURE__ */ new Map();
717
+ // handlers: Map<HTTPMethod, Callback<any>> = new Map();
718
+ handlers = /* @__PURE__ */ new Map();
719
+ pathname;
720
+ // isWildcard: boolean = false;
721
+ paramName;
722
+ isParam = false;
723
+ constructor(pathname = "/") {
724
+ this.children = /* @__PURE__ */ new Map();
725
+ this.pathname = pathname;
726
+ }
727
+ }
728
+ class Router extends MiddlewareConfigure {
729
+ routers = /* @__PURE__ */ new Map();
730
+ env = {};
731
+ triRouter;
732
+ constructor({ basePath = "/", env = {} } = {}) {
733
+ super(basePath);
734
+ this.basePath = basePath;
735
+ this.env = { ...env };
736
+ this.triRouter = new TrieRouter(basePath);
737
+ this.get.bind(this);
738
+ this.post.bind(this);
739
+ this.put.bind(this);
740
+ this.delete.bind(this);
741
+ this.all.bind(this);
742
+ this.#routeAddTriNode.bind(this);
743
+ this.addRouter.bind(this);
744
+ this.group.bind(this);
745
+ }
746
+ static(...args) {
747
+ let route = "";
748
+ let dir;
749
+ let options = {};
750
+ switch (args.length) {
751
+ case 3:
752
+ [route, dir, options] = args;
753
+ break;
754
+ case 2:
755
+ if (typeof args[1] === "object") {
756
+ [dir, options] = args;
757
+ } else {
758
+ [route, dir] = args;
759
+ }
760
+ break;
761
+ case 1:
762
+ [dir] = args;
763
+ break;
764
+ default:
765
+ throw new Error(
766
+ `\x1B[1;31m404 Not Found\x1B[0m \x1B[1;32mInvalid arguments\x1B[0m`
767
+ );
768
+ }
769
+ getFiles(dir, route, this, options);
770
+ return this;
771
+ }
772
+ get(path, ...args) {
773
+ this.#registerRoute("GET", path, ...args);
774
+ return this;
775
+ }
776
+ post(path, ...args) {
777
+ this.#registerRoute("POST", path, ...args);
778
+ return this;
779
+ }
780
+ put(path, ...args) {
781
+ this.#registerRoute("PUT", path, ...args);
782
+ return this;
783
+ }
784
+ patch(path, ...args) {
785
+ this.#registerRoute("PATCH", path, ...args);
786
+ return this;
787
+ }
788
+ delete(path, ...args) {
789
+ this.#registerRoute("DELETE", path, ...args);
790
+ return this;
791
+ }
792
+ options(path, ...args) {
793
+ this.#registerRoute("OPTIONS", path, ...args);
794
+ return this;
795
+ }
796
+ head(path, ...args) {
797
+ this.#registerRoute("HEAD", path, ...args);
798
+ return this;
799
+ }
800
+ all(path, ...args) {
801
+ this.#registerRoute("ALL", path, ...args);
802
+ return this;
803
+ }
804
+ addRoute(method, path, ...args) {
805
+ this.#registerRoute(method, path, ...args);
806
+ return this;
807
+ }
808
+ /**
809
+ * Mount a sub-router at specific path prefix
810
+ * @param path - Base path for the sub-router
811
+ * @param router - Router instance to mount
812
+ * @returns Current instance for chaining
813
+ *
814
+ * @example
815
+ * const apiRouter = new Router();
816
+ * apiRouter.get('/users', () => { ... });
817
+ * server.addRouter('/api', apiRouter);
818
+ */
819
+ addRouter(path, router) {
820
+ return this.#routeAddTriNode(path, router);
821
+ }
822
+ /**
823
+ * Create route group with shared path prefix
824
+ * @param prefix - Path prefix for the group
825
+ * @param callback - Function that receives group-specific router
826
+ * @returns Current router instance for chaining
827
+ *
828
+ * @example
829
+ * app.group('/v1', (group) => {
830
+ * group.get('/users', v1UserHandler);
831
+ * });
832
+ */
833
+ group(prefix, callback) {
834
+ const router = new Router({
835
+ basePath: prefix
836
+ // env: this.env
837
+ });
838
+ callback(router);
839
+ this.#routeAddTriNode("/", router);
840
+ return this;
841
+ }
842
+ use(...args) {
843
+ let path = "/";
844
+ let middlewares = [];
845
+ let router;
846
+ if (typeof args[0] === "string") {
847
+ path = args[0];
848
+ if (Array.isArray(args[1])) {
849
+ middlewares = args[1];
850
+ router = args[2];
851
+ } else if (typeof args[1] === "function") {
852
+ middlewares = [args[1]];
853
+ router = args[2];
854
+ } else {
855
+ router = args[1];
856
+ }
857
+ } else if (typeof args[0] === "function") {
858
+ if (args.length === 1) {
859
+ middlewares = [args[0]];
860
+ } else {
861
+ middlewares = [args[0]];
862
+ router = args[1];
863
+ }
864
+ } else if (Array.isArray(args[0])) {
865
+ middlewares = args[0];
866
+ router = args[1];
867
+ } else if (args[0] instanceof Router) {
868
+ router = args[0];
869
+ }
870
+ this.#addRouteMiddleware(path, middlewares);
871
+ if (router && router instanceof Router) {
872
+ this.addRouter(path, router);
873
+ }
874
+ return this;
875
+ }
876
+ // Other HTTP methods (PUT, DELETE, etc.) can be added similarly
877
+ #registerRoute(method, path, ...args) {
878
+ if (args.length === 0) {
879
+ throw new Error("At least one handler is required.");
880
+ }
881
+ let middlewares = [];
882
+ let callback;
883
+ if (args.length > 1) {
884
+ if (Array.isArray(args[0])) {
885
+ middlewares = args[0];
886
+ } else if (typeof args[0] === "function") {
887
+ middlewares = [args[0]];
888
+ }
889
+ callback = args[args.length - 1];
890
+ } else {
891
+ callback = args[0];
892
+ }
893
+ if (typeof callback !== "function") {
894
+ throw new Error("Route callback function is missing or invalid.");
895
+ }
896
+ if (!middlewares.every((middleware) => typeof middleware === "function")) {
897
+ throw new Error(
898
+ "Middleware must be a function or an array of functions."
899
+ );
900
+ }
901
+ this.#addRoute(method, path, callback, middlewares);
902
+ }
903
+ #addRoute(method, path, callback, middlewares) {
904
+ const parts = sanitizePathSplit(this.basePath, path);
905
+ let finalMiddleware = middlewares;
906
+ if (!GlobalConfig.allowDuplicateMw) {
907
+ finalMiddleware = new Set(middlewares);
908
+ }
909
+ let p = parts.join("/");
910
+ if (/(\/\*|\?)/.test(p)) {
911
+ let handler = this.routers.get(p);
912
+ if (!handler) {
913
+ handler = /* @__PURE__ */ new Map();
914
+ handler.set(method, {
915
+ callback,
916
+ middlewares: finalMiddleware
917
+ });
918
+ return this.routers.set(p, handler);
919
+ }
920
+ if (!GlobalConfig.overwriteMethod && handler.has(method)) return;
921
+ return handler.set(method, { callback, middlewares: finalMiddleware });
922
+ }
923
+ let node = this.triRouter;
924
+ for (const part of parts) {
925
+ if (part.startsWith(":")) {
926
+ if (!node.children.has(":")) {
927
+ node.children.set(":", new TrieRouter());
928
+ }
929
+ node = node.children.get(":");
930
+ node.isParam = true;
931
+ if (!node.paramName) {
932
+ node.paramName = part.slice(1);
933
+ }
934
+ } else {
935
+ if (!node.children.has(part)) {
936
+ node.children.set(part, new TrieRouter());
937
+ }
938
+ node = node.children.get(part);
939
+ }
940
+ }
941
+ if (!GlobalConfig.overwriteMethod && node.handlers.has(method)) return;
942
+ node.handlers.set(method, {
943
+ callback,
944
+ middlewares: finalMiddleware
945
+ });
946
+ node.pathname = path;
947
+ }
948
+ #addRouteMiddleware(path, middlewareFunctions) {
949
+ this.addMiddleware(path, middlewareFunctions);
950
+ }
951
+ #routeAddTriNode(path, router) {
952
+ this.env = { ...this.env, ...router.env };
953
+ if (!(router instanceof Router)) {
954
+ throw new Error("Router instance is required.");
955
+ }
956
+ const parts = sanitizePathSplit(this.basePath, path);
957
+ if (router.routers.size) {
958
+ for (const [segment, handlers] of router.routers) {
959
+ let path2 = parts.length ? parts.join("/") + "/" + segment : segment;
960
+ if (this.routers.has(path2)) {
961
+ const baseRouter = this.routers.get(path2);
962
+ for (const [method, handler] of handlers) {
963
+ if (!GlobalConfig.overwriteMethod && baseRouter.has(method)) return;
964
+ baseRouter.set(method, handler);
965
+ }
966
+ } else {
967
+ this.routers.set(path2, new Map(handlers));
968
+ }
969
+ }
970
+ }
971
+ let rootNode = this.triRouter;
972
+ let rootMiddlewares = this.triMiddlewares;
973
+ if (parts.length == 0) {
974
+ this.#addMiddlewareHandlerIDsTriNode(rootNode, rootMiddlewares, router);
975
+ } else {
976
+ for (const part of parts) {
977
+ if (part.startsWith(":")) {
978
+ if (!rootNode.children.has(":")) {
979
+ rootNode.children.set(":", new TrieRouter());
980
+ }
981
+ rootNode = rootNode.children.get(":");
982
+ rootNode.isParam = true;
983
+ if (!rootNode.paramName) {
984
+ rootNode.paramName = part.slice(1);
985
+ }
986
+ } else {
987
+ if (!rootNode.children.has(part)) {
988
+ rootNode.children.set(part, new TrieRouter());
989
+ }
990
+ rootNode = rootNode.children.get(part);
991
+ }
992
+ }
993
+ for (const part of parts) {
994
+ if (part.startsWith("*")) {
995
+ if (!rootMiddlewares.children.has("*")) {
996
+ rootMiddlewares.children.set("*", new TriMiddleware());
997
+ }
998
+ rootMiddlewares = rootMiddlewares.children.get("*");
999
+ } else if (part.startsWith(":")) {
1000
+ const isOptional = part?.endsWith("?");
1001
+ if (isOptional) {
1002
+ rootMiddlewares.isOptional = isOptional;
1003
+ continue;
1004
+ }
1005
+ if (!rootMiddlewares.children.has(":")) {
1006
+ rootMiddlewares.children.set(":", new TriMiddleware());
1007
+ }
1008
+ rootMiddlewares = rootMiddlewares.children.get(":");
1009
+ } else {
1010
+ if (!rootMiddlewares.children.has(part)) {
1011
+ rootMiddlewares.children.set(part, new TriMiddleware());
1012
+ }
1013
+ rootMiddlewares = rootMiddlewares.children.get(part);
1014
+ }
1015
+ }
1016
+ this.#addMiddlewareHandlerIDsTriNode(rootNode, rootMiddlewares, router);
1017
+ }
1018
+ }
1019
+ #addMiddlewareHandlerIDsTriNode(rootNode, rootMiddlewares, router) {
1020
+ function addSubRouter(children, node) {
1021
+ let rtN = node;
1022
+ for (const element of children) {
1023
+ const pathSegment = element[0];
1024
+ const subRouter = element[1];
1025
+ if (rtN.children.has(pathSegment)) {
1026
+ let findNode = rtN.children.get(pathSegment);
1027
+ for (const [method, handlers] of subRouter.handlers) {
1028
+ if (!GlobalConfig.overwriteMethod && node.handlers.has(method))
1029
+ return;
1030
+ findNode.handlers.set(method, handlers);
1031
+ }
1032
+ if (subRouter.children.size) {
1033
+ addSubRouter(subRouter.children, findNode);
1034
+ }
1035
+ } else {
1036
+ rtN.children.set(pathSegment, subRouter);
1037
+ }
1038
+ }
1039
+ }
1040
+ let routerNode = router.triRouter;
1041
+ const routerMiddlewares = router.triMiddlewares;
1042
+ for (const [method, handlers] of routerNode.handlers) {
1043
+ if (!GlobalConfig.overwriteMethod) {
1044
+ rootNode.handlers.set(method, handlers);
1045
+ continue;
1046
+ }
1047
+ if (!rootNode.handlers.has(method)) {
1048
+ rootNode.handlers.set(method, handlers);
1049
+ }
1050
+ }
1051
+ if (routerNode.children.size > 0) {
1052
+ addSubRouter(routerNode.children, rootNode);
1053
+ }
1054
+ function addMiddleware(children, node) {
1055
+ let n = node;
1056
+ for (const [path, middlewareNode] of children) {
1057
+ if (n.children.has(path)) {
1058
+ let findNode = n.children.get(path);
1059
+ if (GlobalConfig.allowDuplicateMw) {
1060
+ findNode.middlewares.push(
1061
+ ...middlewareNode.middlewares
1062
+ );
1063
+ } else {
1064
+ for (const mw of middlewareNode.middlewares) {
1065
+ if (findNode.middlewares.has(mw)) {
1066
+ middlewareNode.middlewares.delete(mw);
1067
+ }
1068
+ findNode.middlewares.add(mw);
1069
+ }
1070
+ }
1071
+ if (middlewareNode.children.size) {
1072
+ addMiddleware(middlewareNode.children, findNode);
1073
+ }
1074
+ } else {
1075
+ n.children.set(path, middlewareNode);
1076
+ }
1077
+ }
1078
+ }
1079
+ if (GlobalConfig.allowDuplicateMw) {
1080
+ rootMiddlewares.middlewares.push(
1081
+ ...routerMiddlewares.middlewares
1082
+ );
1083
+ } else {
1084
+ for (const mw of routerMiddlewares.middlewares) {
1085
+ if (rootMiddlewares.middlewares.has(mw)) {
1086
+ routerMiddlewares.middlewares.delete(mw);
1087
+ }
1088
+ rootMiddlewares.middlewares.add(mw);
1089
+ }
1090
+ }
1091
+ if (routerMiddlewares.children.size > 0) {
1092
+ addMiddleware(routerMiddlewares.children, rootMiddlewares);
1093
+ }
1094
+ }
1095
+ }
1096
+
1097
+ class HeadersParser {
1098
+ headers = /* @__PURE__ */ new Map();
1099
+ // Lowercase keys for case-insensitivity
1100
+ constructor(init) {
1101
+ if (init) {
1102
+ this.add(init);
1103
+ }
1104
+ }
1105
+ /**
1106
+ * Adds multiple headers to the parser.
1107
+ * @param headers - Headers as an array of tuples or a record object.
1108
+ */
1109
+ add(headers) {
1110
+ if (Array.isArray(headers)) {
1111
+ for (const [key, value] of headers) {
1112
+ this.set(key, value);
1113
+ }
1114
+ } else if (typeof Headers !== "undefined" && headers instanceof Headers) {
1115
+ for (const [key, value] of headers.entries()) {
1116
+ this.set(key, value);
1117
+ }
1118
+ } else if (typeof headers === "object") {
1119
+ for (const key in headers) {
1120
+ if (Object.prototype.hasOwnProperty.call(headers, key)) {
1121
+ this.set(key, headers[key]);
1122
+ }
1123
+ }
1124
+ }
1125
+ return this;
1126
+ }
1127
+ /**
1128
+ * Sets a header value.
1129
+ * @param key - Header name.
1130
+ * @param value - Header value(s).
1131
+ */
1132
+ set(key, value) {
1133
+ this.headers.set(key.toLowerCase(), Array.isArray(value) ? value : [value]);
1134
+ return this;
1135
+ }
1136
+ /**
1137
+ * Retrieves the first value of a header.
1138
+ * @param key - Header name.
1139
+ * @returns The first header value or undefined if not found.
1140
+ */
1141
+ get(key) {
1142
+ const values = this.headers.get(key.toLowerCase());
1143
+ return values ? values[0] : void 0;
1144
+ }
1145
+ /**
1146
+ * Retrieves all values of a header.
1147
+ * @param key - Header name.
1148
+ * @returns An array of header values.
1149
+ */
1150
+ getAll(key) {
1151
+ return this.headers.get(key.toLowerCase()) || [];
1152
+ }
1153
+ /**
1154
+ * Checks if a header exists.
1155
+ * @param key - Header name.
1156
+ * @returns True if the header exists, false otherwise.
1157
+ */
1158
+ has(key) {
1159
+ return this.headers.has(key.toLowerCase());
1160
+ }
1161
+ /**
1162
+ * Deletes a header.
1163
+ * @param key - Header name.
1164
+ * @returns True if deleted successfully, false otherwise.
1165
+ */
1166
+ delete(key) {
1167
+ return this.headers.delete(key.toLowerCase());
1168
+ }
1169
+ /**
1170
+ * Appends a value to an existing header or creates a new one.
1171
+ * @param key - Header name.
1172
+ * @param value - Value to append.
1173
+ */
1174
+ append(key, value) {
1175
+ const lowerKey = key.toLowerCase();
1176
+ if (this.headers.has(lowerKey)) {
1177
+ this.headers.get(lowerKey).push(value);
1178
+ } else {
1179
+ this.headers.set(lowerKey, [value]);
1180
+ }
1181
+ return this;
1182
+ }
1183
+ /**
1184
+ * Returns an iterator over header entries.
1185
+ * @returns IterableIterator of header key-value pairs.
1186
+ */
1187
+ entries() {
1188
+ return this.headers.entries();
1189
+ }
1190
+ /**
1191
+ * Returns an iterator over header keys.
1192
+ * @returns IterableIterator of header names.
1193
+ */
1194
+ keys() {
1195
+ return this.headers.keys();
1196
+ }
1197
+ /**
1198
+ * Returns an iterator over header values.
1199
+ * @returns IterableIterator of header values arrays.
1200
+ */
1201
+ values() {
1202
+ return this.headers.values();
1203
+ }
1204
+ /**
1205
+ * Iterates over headers and executes a callback function.
1206
+ * @param callback - Function to execute for each header.
1207
+ */
1208
+ forEach(callback) {
1209
+ for (const [key, value] of this.headers) {
1210
+ callback(value, key);
1211
+ }
1212
+ }
1213
+ /**
1214
+ * Converts headers into a plain object.
1215
+ * @returns A record of headers where single-value headers are returned as a string.
1216
+ */
1217
+ toObject() {
1218
+ const obj = {};
1219
+ for (const [key, value] of this.headers.entries()) {
1220
+ obj[key] = value.length > 1 ? value : value[0];
1221
+ }
1222
+ return obj;
1223
+ }
1224
+ }
1225
+ Object.defineProperty(HeadersParser, "name", { value: "Headers" });
1226
+
1227
+ async function parseJsonBody(req) {
1228
+ const runtime = EnvironmentDetector.getEnvironment;
1229
+ if (runtime === "node") {
1230
+ return new Promise((resolve, reject) => {
1231
+ let body = "";
1232
+ req.on("data", (chunk) => {
1233
+ body += chunk.toString();
1234
+ });
1235
+ req.on("end", () => {
1236
+ try {
1237
+ resolve(JSON.parse(body));
1238
+ } catch (error) {
1239
+ reject(new Error("Invalid JSON format"));
1240
+ }
1241
+ });
1242
+ });
1243
+ } else if (runtime === "deno" || runtime === "bun") {
1244
+ return await req.json();
1245
+ } else {
1246
+ throw new Error("Unsupported environment for multipart parsing");
1247
+ }
1248
+ }
1249
+ async function parseTextBody(req) {
1250
+ const runtime = EnvironmentDetector.getEnvironment;
1251
+ if (runtime === "node") {
1252
+ return new Promise((resolve, reject) => {
1253
+ let body = "";
1254
+ req.on("data", (chunk) => {
1255
+ body += chunk.toString();
1256
+ });
1257
+ req.on("end", () => {
1258
+ try {
1259
+ resolve(body);
1260
+ } catch (error) {
1261
+ reject(new Error("Invalid JSON format"));
1262
+ }
1263
+ });
1264
+ });
1265
+ } else if (runtime === "deno" || runtime === "bun") {
1266
+ return await req.text();
1267
+ } else {
1268
+ throw new Error("Unsupported environment for multipart parsing");
1269
+ }
1270
+ }
1271
+ async function parseUrlEncodedBody(req) {
1272
+ const runtime = EnvironmentDetector.getEnvironment;
1273
+ if (runtime === "node") {
1274
+ return new Promise((resolve, reject) => {
1275
+ let body = "";
1276
+ req.on("data", (chunk) => {
1277
+ body += chunk.toString("binary");
1278
+ });
1279
+ req.on("end", () => {
1280
+ try {
1281
+ const pairs = body.split("&");
1282
+ const formData = {};
1283
+ pairs.forEach((pair) => {
1284
+ const [key, value] = pair.split("=");
1285
+ formData[decodeURIComponent(key)] = decodeURIComponent(value || "");
1286
+ });
1287
+ resolve(formData);
1288
+ } catch {
1289
+ reject(new Error("Invalid x-www-form-urlencoded format"));
1290
+ }
1291
+ });
1292
+ });
1293
+ } else if (runtime === "deno" || runtime === "bun") {
1294
+ const formData = await req.formData();
1295
+ const result = {};
1296
+ for (const [key, value] of formData.entries()) {
1297
+ result[key] = value;
1298
+ }
1299
+ return result;
1300
+ } else {
1301
+ throw new Error("Unsupported environment for multipart parsing");
1302
+ }
1303
+ }
1304
+ async function parseMultipartBody(req, boundary, options) {
1305
+ const runtime = EnvironmentDetector.getEnvironment;
1306
+ options?.sanitized;
1307
+ if (runtime === "node") {
1308
+ return new Promise((resolve, reject) => {
1309
+ let body = "";
1310
+ req.on("data", (chunk) => {
1311
+ body += chunk.toString("binary");
1312
+ });
1313
+ req.on("end", () => {
1314
+ try {
1315
+ const formDataField = {};
1316
+ const formDataFieldParts = body.split("----------------------------");
1317
+ formDataFieldParts.forEach((part) => {
1318
+ const match = part.match(/name="(.*)"\r\n\r\n(.*)\r\n/);
1319
+ if (match && match.length === 3) {
1320
+ const name = match[1];
1321
+ const value = match[2];
1322
+ formDataField[name] = value;
1323
+ }
1324
+ });
1325
+ const parts = body.split(`--${boundary}`);
1326
+ for (const part of parts) {
1327
+ if (part.includes("filename")) {
1328
+ const filenameMatch = part.match(/filename="([^"]+)"/);
1329
+ const fieldNameMatch = part.match(/name="([^"]+)"/);
1330
+ const contentTypeMatch = part.match(/Content-Type: ([^\r\n]+)/);
1331
+ if (filenameMatch && fieldNameMatch && contentTypeMatch) {
1332
+ let filename = filenameMatch[1];
1333
+ const fieldName = fieldNameMatch[1];
1334
+ const contentType = contentTypeMatch[1];
1335
+ if (options?.sanitized) {
1336
+ filename = `${Date.now()}-${filename.replace(/\s+/g, "")?.replace(/[^a-zA-Z0-9.-]/g, "-")}`?.toLowerCase();
1337
+ }
1338
+ if (Array.isArray(options?.allowedTypes) && !options.allowedTypes?.includes(contentType)) {
1339
+ reject(
1340
+ `Invalid file type: "${contentType}". Allowed types: ${options.allowedTypes.join(", ")}`
1341
+ );
1342
+ }
1343
+ const fileContentStartIndex = part.indexOf("\r\n\r\n") + 4;
1344
+ const fileContent = Buffer.from(
1345
+ part.substring(fileContentStartIndex),
1346
+ "binary"
1347
+ );
1348
+ const arrayBuffer = fileContent.buffer.slice(
1349
+ fileContent.byteOffset,
1350
+ fileContent.byteOffset + fileContent.byteLength
1351
+ );
1352
+ if (typeof options?.maxSize !== "undefined" && fileContent.byteLength > options.maxSize) {
1353
+ reject(
1354
+ `File size exceeds the limit: ${fileContent.byteLength} bytes (Max: ${options.maxSize} bytes)`
1355
+ );
1356
+ }
1357
+ const file = new File([arrayBuffer], filename, {
1358
+ type: contentType
1359
+ });
1360
+ if (typeof options?.maxFiles != "undefined" && options.maxFiles == 0) {
1361
+ reject(
1362
+ `Field "${fieldName}" exceeds the maximum allowed file count of ${options.maxFiles}.`
1363
+ );
1364
+ }
1365
+ if (formDataField[fieldName]) {
1366
+ if (Array.isArray(formDataField[fieldName])) {
1367
+ if (typeof options?.maxFiles != "undefined" && formDataField[fieldName]?.length >= options.maxFiles) {
1368
+ reject(
1369
+ `Field "${fieldName}" exceeds the maximum allowed file count of ${options.maxFiles}.`
1370
+ );
1371
+ }
1372
+ formDataField[fieldName].push(file);
1373
+ } else {
1374
+ formDataField[fieldName] = [formDataField[fieldName], file];
1375
+ }
1376
+ } else {
1377
+ formDataField[fieldName] = file;
1378
+ }
1379
+ }
1380
+ }
1381
+ }
1382
+ resolve(formDataField);
1383
+ } catch {
1384
+ }
1385
+ });
1386
+ });
1387
+ } else if (runtime === "deno" || runtime === "bun") {
1388
+ const formData = await req.formData();
1389
+ const result = {};
1390
+ for (const [key, value] of formData.entries()) {
1391
+ let val = value;
1392
+ if (val instanceof File && typeof options == "object") {
1393
+ let filename = val.name;
1394
+ if (options?.sanitized) {
1395
+ filename = `${Date.now()}-${filename.replace(/\s+/g, "")?.replace(/[^a-zA-Z0-9.-]/g, "-")}`?.toLowerCase();
1396
+ }
1397
+ if (Array.isArray(options?.allowedTypes) && !options.allowedTypes?.includes(val.type)) {
1398
+ throw new Error(
1399
+ `Invalid file type: "${val.type}". Allowed types: ${options.allowedTypes.join(", ")}`
1400
+ );
1401
+ }
1402
+ if (typeof options?.maxSize !== "undefined" && val.size > options.maxSize) {
1403
+ throw new Error(
1404
+ `File size exceeds the limit: ${val.size} bytes (Max: ${options.maxSize} bytes)`
1405
+ );
1406
+ }
1407
+ if (typeof options?.maxFiles != "undefined" && options.maxFiles == 0) {
1408
+ throw new Error(
1409
+ `Field "${key}" exceeds the maximum allowed file count of ${options.maxFiles}.`
1410
+ );
1411
+ }
1412
+ val = new File([await val.arrayBuffer()], filename, {
1413
+ type: val.type
1414
+ });
1415
+ }
1416
+ if (result[key]) {
1417
+ if (Array.isArray(result[key])) {
1418
+ if (val instanceof File && typeof options?.maxFiles != "undefined" && result[key]?.length >= options.maxFiles) {
1419
+ throw new Error(
1420
+ `Field "${key}" exceeds the maximum allowed file count of ${options.maxFiles}.`
1421
+ );
1422
+ }
1423
+ result[key].push(val);
1424
+ } else {
1425
+ result[key] = [result[key], val];
1426
+ }
1427
+ } else {
1428
+ result[key] = val;
1429
+ }
1430
+ }
1431
+ return result;
1432
+ } else {
1433
+ throw new Error("Unsupported environment for multipart parsing");
1434
+ }
1435
+ }
1436
+
1437
+ class Request {
1438
+ headers = new HeadersParser();
1439
+ /**
1440
+ * Full request URL including protocol and query string
1441
+ * @type {string}
1442
+ */
1443
+ url;
1444
+ /**
1445
+ * HTTP request method (GET, POST, PUT, DELETE, etc.)
1446
+ * @type {HTTPMethod}
1447
+ */
1448
+ method;
1449
+ /** Parsed URL reference containing components like query parameters, pathname, etc. */
1450
+ urlRef = {
1451
+ hash: void 0,
1452
+ protocol: void 0,
1453
+ origin: void 0,
1454
+ username: void 0,
1455
+ password: void 0,
1456
+ hostname: void 0,
1457
+ port: void 0,
1458
+ href: void 0,
1459
+ query: {},
1460
+ pathname: "/"
1461
+ };
1462
+ /** Query parameters extracted from the URL */
1463
+ query;
1464
+ #request;
1465
+ /**
1466
+ * Retrieve a parameter by name.
1467
+ * @param name - The parameter name.
1468
+ * @returns The parameter value if found, or undefined.
1469
+ */
1470
+ params = {};
1471
+ // static statusText: string;
1472
+ // static bodyUsed: boolean;
1473
+ constructor(req, params) {
1474
+ this.headers = new HeadersParser(req?.headers);
1475
+ this.method = req?.method?.toUpperCase();
1476
+ this.params = params;
1477
+ this.#request = req;
1478
+ if (EnvironmentDetector.getEnvironment == "node") {
1479
+ const protocol = EnvironmentDetector.detectProtocol(req);
1480
+ const host = EnvironmentDetector.getHost(this.headers);
1481
+ this.url = `${protocol}://${host}${req.url}`;
1482
+ } else {
1483
+ this.url = req.url;
1484
+ }
1485
+ this.urlRef = urlParse(this.url);
1486
+ this.query = this.urlRef.query;
1487
+ }
1488
+ /**
1489
+ * Parses the request body as plain text.
1490
+ * @returns {Promise<string>} The text content of the request body.
1491
+ */
1492
+ async text() {
1493
+ return await parseTextBody(this.#request);
1494
+ }
1495
+ /**
1496
+ * Parses the request body as JSON.
1497
+ * @returns {Promise<Record<string, any>>} The parsed JSON object.
1498
+ * If the Content-Type is not 'application/json', it returns an empty object.
1499
+ */
1500
+ async json() {
1501
+ const contentType = this.headers.get("content-type") || "";
1502
+ if (contentType.includes("application/json")) {
1503
+ return await parseJsonBody(this.#request);
1504
+ } else {
1505
+ return {};
1506
+ }
1507
+ }
1508
+ /**
1509
+ * Parses the request body based on Content-Type.
1510
+ * Supports:
1511
+ * - application/json → JSON parsing
1512
+ * - application/x-www-form-urlencoded → URL-encoded form parsing
1513
+ * - multipart/form-data → Multipart form-data parsing (for file uploads)
1514
+ * @returns {Promise<Record<string, any>>} The parsed form data as an object.
1515
+ * @throws {Error} If the Content-Type is missing or invalid.
1516
+ */
1517
+ async formData(options) {
1518
+ const contentType = this.headers.get("content-type") || "";
1519
+ if (!contentType) {
1520
+ throw Error("Invalid Content-Type");
1521
+ }
1522
+ if (contentType.includes("application/json")) {
1523
+ return await parseJsonBody(this.#request);
1524
+ } else if (contentType.includes("application/x-www-form-urlencoded")) {
1525
+ return parseUrlEncodedBody(this.#request);
1526
+ } else if (contentType.includes("multipart/form-data")) {
1527
+ const boundary = contentType?.split("; ")?.[1]?.split("=")?.[1];
1528
+ if (!boundary) {
1529
+ throw Error("Boundary not found");
1530
+ }
1531
+ return await parseMultipartBody(this.#request, boundary, options);
1532
+ } else {
1533
+ return {};
1534
+ }
1535
+ }
1536
+ }
1537
+
1538
+ class State {
1539
+ state;
1540
+ constructor() {
1541
+ this.state = /* @__PURE__ */ new Map();
1542
+ }
1543
+ /**
1544
+ * Store a value with a specific key.
1545
+ * @param key - The key for the value.
1546
+ * @param value - The value to be stored.
1547
+ */
1548
+ set(key, value) {
1549
+ this.state.set(key, value);
1550
+ }
1551
+ /**
1552
+ * Retrieve a value by key.
1553
+ * @param key - The key of the value to retrieve.
1554
+ * @returns The stored value or undefined if not found.
1555
+ */
1556
+ get(key) {
1557
+ return this.state.get(key);
1558
+ }
1559
+ /**
1560
+ * Delete a key from storage.
1561
+ * @param key - The key to remove.
1562
+ * @returns True if the key was deleted, false otherwise.
1563
+ */
1564
+ delete(key) {
1565
+ return this.state.delete(key);
1566
+ }
1567
+ /**
1568
+ * Check if a key exists in the storage.
1569
+ * @param key - The key to check.
1570
+ * @returns True if the key exists, false otherwise.
1571
+ */
1572
+ has(key) {
1573
+ return this.state.has(key);
1574
+ }
1575
+ /**
1576
+ * Get an array of all stored keys.
1577
+ * @returns An array of keys.
1578
+ */
1579
+ keys() {
1580
+ return Array.from(this.state.keys());
1581
+ }
1582
+ /**
1583
+ * Get an array of all stored values.
1584
+ * @returns An array of values.
1585
+ */
1586
+ values() {
1587
+ return Array.from(this.state.values());
1588
+ }
1589
+ /**
1590
+ * Get an array of all key-value pairs.
1591
+ * @returns An array of [key, value] tuples.
1592
+ */
1593
+ entries() {
1594
+ return Array.from(this.state.entries());
1595
+ }
1596
+ /**
1597
+ * Remove all entries from storage.
1598
+ */
1599
+ clear() {
1600
+ this.state.clear();
1601
+ }
1602
+ }
1603
+
1604
+ const httpStatusMap = {
1605
+ 100: "Continue",
1606
+ 101: "Switching Protocols",
1607
+ 102: "Processing",
1608
+ 103: "Early Hints",
1609
+ 200: "OK",
1610
+ 201: "Created",
1611
+ 202: "Accepted",
1612
+ 203: "Non-Authoritative Information",
1613
+ 204: "No Content",
1614
+ 205: "Reset Content",
1615
+ 206: "Partial Content",
1616
+ 207: "Multi-Status",
1617
+ 208: "Already Reported",
1618
+ 226: "IM Used",
1619
+ 300: "Multiple Choices",
1620
+ 301: "Moved Permanently",
1621
+ 302: "Found",
1622
+ 303: "See Other",
1623
+ 304: "Not Modified",
1624
+ 305: "Use Proxy",
1625
+ 306: "Switch Proxy",
1626
+ 307: "Temporary Redirect",
1627
+ 308: "Permanent Redirect",
1628
+ 400: "Bad Request",
1629
+ 401: "Unauthorized",
1630
+ 402: "Payment Required",
1631
+ 403: "Forbidden",
1632
+ 404: "Not Found",
1633
+ 405: "Method Not Allowed",
1634
+ 406: "Not Acceptable",
1635
+ 407: "Proxy Authentication Required",
1636
+ 408: "Request Timeout",
1637
+ 409: "Conflict",
1638
+ 410: "Gone",
1639
+ 411: "Length Required",
1640
+ 412: "Precondition Failed",
1641
+ 413: "Payload Too Large",
1642
+ 414: "URI Too Long",
1643
+ 415: "Unsupported Media Type",
1644
+ 416: "Range Not Satisfiable",
1645
+ 417: "Expectation Failed",
1646
+ 418: "I'm a Teapot",
1647
+ 421: "Misdirected Request",
1648
+ 422: "Unprocessable Entity",
1649
+ 423: "Locked",
1650
+ 424: "Failed Dependency",
1651
+ 425: "Too Early",
1652
+ 426: "Upgrade Required",
1653
+ 428: "Precondition Required",
1654
+ 429: "Too Many Requests",
1655
+ 431: "Request Header Fields Too Large",
1656
+ 451: "Unavailable For Legal Reasons",
1657
+ 500: "Internal Server Error",
1658
+ 501: "Not Implemented",
1659
+ 502: "Bad Gateway",
1660
+ 503: "Service Unavailable",
1661
+ 504: "Gateway Timeout",
1662
+ 505: "HTTP Version Not Supported",
1663
+ 506: "Variant Also Negotiates",
1664
+ 507: "Insufficient Storage",
1665
+ 508: "Loop Detected",
1666
+ 510: "Not Extended",
1667
+ 511: "Network Authentication Required"
1668
+ };
1669
+ class Context {
1670
+ #rawRequest;
1671
+ /**
1672
+ * Environment variables and configuration
1673
+ * @type {object}
1674
+ */
1675
+ env = {};
1676
+ /**
1677
+ * Parser for handling and manipulating HTTP headers
1678
+ * @type {HeadersParser}
1679
+ */
1680
+ headers = new HeadersParser();
1681
+ // /**
1682
+ // * Parser for handling and manipulating HTTP response(Read Only)
1683
+ // * @type {Response}
1684
+ // */
1685
+ // public readonly res: Response = new Response();
1686
+ /**
1687
+ * Request path without query parameters
1688
+ * @type {string}
1689
+ */
1690
+ pathname;
1691
+ /**
1692
+ * Full request URL including protocol and query string
1693
+ * @type {string}
1694
+ */
1695
+ url;
1696
+ /**
1697
+ * HTTP request method (GET, POST, PUT, DELETE, etc.)
1698
+ * @type {HTTPMethod}
1699
+ */
1700
+ method;
1701
+ #status = 200;
1702
+ /**
1703
+ * Public state container for application data
1704
+ * state storage for middleware and plugins
1705
+ * @type {State}
1706
+ */
1707
+ state = new State();
1708
+ /**
1709
+ * URL parameters extracted from route
1710
+ * @private
1711
+ * @type {Record<string, any>}
1712
+ */
1713
+ #params = {};
1714
+ // /**
1715
+ // * WebSocket connection instance (null until upgraded)
1716
+ // * @type {WebSocket | null}
1717
+ // */
1718
+ // ws: WebSocket | null = null;
1719
+ /**
1720
+ * Generic variable storage for internal framework use
1721
+ * @private
1722
+ * @type {any}
1723
+ */
1724
+ #var;
1725
+ /**
1726
+ * Flag indicating if the request processing is complete
1727
+ * @type {boolean}
1728
+ */
1729
+ finalized = false;
1730
+ /**
1731
+ * HTTP response status code
1732
+ * @private
1733
+ * @type {number}
1734
+ */
1735
+ /**
1736
+ * Execution context reference
1737
+ * @private
1738
+ * @type {any}
1739
+ */
1740
+ #executionCtx;
1741
+ /**
1742
+ * Internal headers storage
1743
+ * @private
1744
+ * @type {any}
1745
+ */
1746
+ #headers;
1747
+ /**
1748
+ * Processed headers ready for sending
1749
+ * @private
1750
+ * @type {any}
1751
+ */
1752
+ #preparedHeaders;
1753
+ /**
1754
+ * Native response object reference
1755
+ * @private
1756
+ * @type {any}
1757
+ */
1758
+ #res;
1759
+ /**
1760
+ * Flag indicating if the response is fresh/unmodified
1761
+ * @private
1762
+ * @type {boolean}
1763
+ */
1764
+ #isFresh = true;
1765
+ /**
1766
+ * Active layout template reference
1767
+ * @private
1768
+ * @type {any}
1769
+ */
1770
+ #layout;
1771
+ /**
1772
+ * Template renderer instance
1773
+ * @private
1774
+ * @type {any}
1775
+ */
1776
+ #renderer;
1777
+ /**
1778
+ * Custom 404 handler reference
1779
+ * @private
1780
+ * @type {any}
1781
+ */
1782
+ #notFoundHandler;
1783
+ /**
1784
+ * Route matching results
1785
+ * @private
1786
+ * @type {any}
1787
+ */
1788
+ #matchResult;
1789
+ /**
1790
+ * Processed path information
1791
+ * @private
1792
+ * @type {any}
1793
+ */
1794
+ #path;
1795
+ constructor(req) {
1796
+ this.#rawRequest = req;
1797
+ this.method = req?.method?.toUpperCase();
1798
+ this.pathname = this.req.urlRef.pathname;
1799
+ this.url = this.req.url;
1800
+ }
1801
+ /**
1802
+ * Cookie handling utility with get/set/delete operations
1803
+ * @returns {{
1804
+ * get: (name: string) => string | undefined,
1805
+ * all: () => Record<string, string>,
1806
+ * delete: (name: string, options?: CookieOptions) => void,
1807
+ * set: (name: string, value: string, options?: CookieOptions) => void
1808
+ * }} Cookie handling interface
1809
+ */
1810
+ get cookies() {
1811
+ const c = this.headers.getAll("cookie");
1812
+ let cookies = {};
1813
+ if (Array.isArray(c) && c.length != 0) {
1814
+ const cookieHeader = c.join("; ").split(";");
1815
+ for (const pair of cookieHeader) {
1816
+ const [key, value] = pair?.trim()?.split("=");
1817
+ cookies[key] = decodeURIComponent(value);
1818
+ }
1819
+ } else if (typeof c == "string") {
1820
+ const cookieHeader = c.split(";");
1821
+ for (const pair of cookieHeader) {
1822
+ const [key, value] = pair?.trim()?.split("=");
1823
+ cookies[key] = decodeURIComponent(value);
1824
+ }
1825
+ }
1826
+ return {
1827
+ /**
1828
+ * Get a specific cookie by name.
1829
+ * @param {string} cookie - The name of the cookie to retrieve.
1830
+ * @returns {string | undefined} - The cookie value or undefined if not found.
1831
+ */
1832
+ get: (cookie) => {
1833
+ return cookies?.[cookie];
1834
+ },
1835
+ /**
1836
+ * Get all cookies as an object.
1837
+ * @returns {Record<string, string>} - An object containing all cookies.
1838
+ */
1839
+ all: () => {
1840
+ return cookies;
1841
+ },
1842
+ /**
1843
+ * Delete a cookie by setting its expiration to the past.
1844
+ * @param {string} name - The name of the cookie to delete.
1845
+ * @param {CookieOptions} [options] - Additional cookie options.
1846
+ */
1847
+ delete: (name, options) => {
1848
+ const value = "";
1849
+ const cookieOptions = {
1850
+ ...options,
1851
+ expires: /* @__PURE__ */ new Date(0)
1852
+ // Set expiration time to the past
1853
+ };
1854
+ const cookieHeader = `${name}=${value};${serializeOptions(cookieOptions)}`;
1855
+ this.headers.set("Set-Cookie", cookieHeader);
1856
+ },
1857
+ /**
1858
+ * Set a new cookie with the given name, value, and options.
1859
+ * @param {string} name - The name of the cookie.
1860
+ * @param {string} value - The value of the cookie.
1861
+ * @param {CookieOptions} [options] - Additional options like expiration.
1862
+ */
1863
+ set: (name, value, options) => {
1864
+ const cookieHeader = `${name}=${value};${serializeOptions(options || {})}`;
1865
+ this.headers.set("Set-Cookie", cookieHeader);
1866
+ }
1867
+ };
1868
+ }
1869
+ json(body, ...args) {
1870
+ let status = this.#status;
1871
+ let headers = {
1872
+ "Content-Type": "application/json; charset=utf-8"
1873
+ };
1874
+ if (typeof args[0] === "number") {
1875
+ status = args[0];
1876
+ if (typeof args[1] === "object") {
1877
+ headers = { ...headers, ...args[1] };
1878
+ }
1879
+ } else if (typeof args[0] === "object") {
1880
+ headers = { ...headers, ...args[0] };
1881
+ }
1882
+ return new Response(JSON.stringify(body), {
1883
+ status,
1884
+ headers
1885
+ });
1886
+ }
1887
+ send(body, ...args) {
1888
+ let status = this.#status;
1889
+ let headers = {};
1890
+ if (typeof args[0] === "number") {
1891
+ status = args[0];
1892
+ if (typeof args[1] === "object") {
1893
+ headers = args[1];
1894
+ }
1895
+ } else if (typeof args[0] === "object") {
1896
+ headers = args[0];
1897
+ }
1898
+ if (!headers["Content-Type"]) {
1899
+ if (typeof body === "string") {
1900
+ headers["Content-Type"] = "text/plain;";
1901
+ } else if (typeof body === "object" && body !== null) {
1902
+ headers["Content-Type"] = "application/json;";
1903
+ body = JSON.stringify(body);
1904
+ } else {
1905
+ headers["Content-Type"] = "application/octet-stream";
1906
+ }
1907
+ }
1908
+ return new Response(body, {
1909
+ status,
1910
+ headers
1911
+ });
1912
+ }
1913
+ html(data, ...args) {
1914
+ let status = this.#status;
1915
+ let headers = {
1916
+ "Content-Type": "text/html; charset=utf-8"
1917
+ };
1918
+ if (typeof args[0] === "number") {
1919
+ status = args[0];
1920
+ if (typeof args[1] === "object") {
1921
+ headers = { ...headers, ...args[1] };
1922
+ }
1923
+ } else if (typeof args[0] === "object") {
1924
+ headers = { ...headers, ...args[0] };
1925
+ }
1926
+ return new Response(data, {
1927
+ status,
1928
+ headers
1929
+ });
1930
+ }
1931
+ text(data, ...args) {
1932
+ let status = this.#status;
1933
+ let headers = {
1934
+ "Content-Type": "text/plain; charset=utf-8"
1935
+ };
1936
+ if (typeof args[0] === "number") {
1937
+ status = args[0];
1938
+ if (typeof args[1] === "object") {
1939
+ headers = { ...headers, ...args[1] };
1940
+ }
1941
+ } else if (typeof args[0] === "object") {
1942
+ headers = { ...headers, ...args[0] };
1943
+ }
1944
+ return new Response(data, {
1945
+ status,
1946
+ headers
1947
+ });
1948
+ }
1949
+ xml(data, ...args) {
1950
+ let status = this.#status;
1951
+ let headers = {
1952
+ "Content-Type": "application/xml; charset=utf-8"
1953
+ };
1954
+ if (typeof args[0] === "number") {
1955
+ status = args[0];
1956
+ if (typeof args[1] === "object") {
1957
+ headers = { ...headers, ...args[1] };
1958
+ }
1959
+ } else if (typeof args[0] === "object") {
1960
+ headers = { ...headers, ...args[0] };
1961
+ }
1962
+ return new Response(data, {
1963
+ status,
1964
+ headers
1965
+ });
1966
+ }
1967
+ /**
1968
+ * HTTP status code..
1969
+ * @param status - number.
1970
+ * @returns Response object with context all method.
1971
+ */
1972
+ status = (status) => {
1973
+ this.#status = status;
1974
+ return this;
1975
+ };
1976
+ /**
1977
+ * Redirects to a given URL.
1978
+ * @param url - The target URL.
1979
+ * @param status - (Optional) HTTP status code (default: 302).
1980
+ * @param headers - (Optional) Additional headers.
1981
+ * @returns Response object with redirect.
1982
+ */
1983
+ redirect(url, status = 302, headers) {
1984
+ return TezResponse.redirect(url, status, headers);
1985
+ }
1986
+ /**
1987
+ * Handles file downloads.
1988
+ * @param filePath - The path to the file.
1989
+ * @param fileName - The name of the downloaded file.
1990
+ * @returns Response object for file download.
1991
+ */
1992
+ async download(filePath, fileName) {
1993
+ return await TezResponse.download(filePath, fileName);
1994
+ }
1995
+ async sendFile(filePath, ...args) {
1996
+ return await TezResponse.sendFile(filePath, ...args);
1997
+ }
1998
+ /**
1999
+ * Getter that creates a standardized Request object from internal state
2000
+ * @returns {Request} - Normalized request object combining:
2001
+ * - Raw platform-specific request
2002
+ * - Parsed headers
2003
+ * - Route parameters
2004
+ *
2005
+ * @example
2006
+ * // Get standardized request
2007
+ * const request = ctx.req;
2008
+ * // Access route params
2009
+ * const id = request.params.get('id');
2010
+ */
2011
+ get req() {
2012
+ return new Request(this.#rawRequest, this.params);
2013
+ }
2014
+ // attachWebSocket(ws) {
2015
+ // this.ws = ws;
2016
+ // }
2017
+ set params(params) {
2018
+ this.#params = params;
2019
+ }
2020
+ get params() {
2021
+ return this.#params;
2022
+ }
2023
+ }
2024
+ function serializeOptions(options) {
2025
+ const parts = [];
2026
+ if (options.maxAge) {
2027
+ parts.push(`Max-Age=${options.maxAge}`);
2028
+ }
2029
+ if (options.expires) {
2030
+ parts.push(`Expires=${options.expires.toUTCString()}`);
2031
+ }
2032
+ if (options.path) {
2033
+ parts.push(`Path=${options.path}`);
2034
+ }
2035
+ if (options.domain) {
2036
+ parts.push(`Domain=${options.domain}`);
2037
+ }
2038
+ if (options.secure) {
2039
+ parts.push(`Secure`);
2040
+ }
2041
+ if (options.httpOnly) {
2042
+ parts.push(`HttpOnly`);
2043
+ }
2044
+ if (options.sameSite) {
2045
+ parts.push(`SameSite=${options.sameSite}`);
2046
+ }
2047
+ return parts.join("; ");
2048
+ }
2049
+
2050
+ function useParams({
2051
+ path,
2052
+ urlPattern
2053
+ }) {
2054
+ let params = {};
2055
+ path = path.replace(/^\/+|\/+$/g, "");
2056
+ urlPattern = urlPattern.replace(/^\/+|\/+$/g, "");
2057
+ const pathSegments = path ? path.split("/") : [];
2058
+ const patternSegments = urlPattern ? urlPattern.split("/") : [];
2059
+ const pathLength = pathSegments.length;
2060
+ const patternLength = patternSegments.length;
2061
+ if (pathLength > patternLength && !urlPattern.includes("*")) {
2062
+ return { success: false, params: {} };
2063
+ }
2064
+ let pathIndex = 0;
2065
+ for (let i = 0; i < patternLength; i++) {
2066
+ const patternSegment = patternSegments[i];
2067
+ if (patternSegment?.startsWith("*")) {
2068
+ const trailingPatterns = patternSegments.slice(i + 1);
2069
+ let paramName = patternSegment.length == 1 ? "*" : patternSegment?.slice(1);
2070
+ if (trailingPatterns.length > 0) {
2071
+ const expectedTrailing = trailingPatterns.join("/");
2072
+ const actualTrailing = pathSegments.slice(pathLength - trailingPatterns.length).join("/");
2073
+ const wildcardPath = pathSegments.slice(pathIndex, pathLength - trailingPatterns.length).join("/");
2074
+ if (expectedTrailing !== actualTrailing || !wildcardPath) {
2075
+ return { success: false, params: {} };
2076
+ }
2077
+ params[paramName] = wildcardPath;
2078
+ return { success: true, params };
2079
+ } else {
2080
+ const wildcardPath = pathSegments.slice(pathIndex).join("/");
2081
+ if (!wildcardPath) {
2082
+ return { success: false, params: {} };
2083
+ }
2084
+ params[paramName] = wildcardPath;
2085
+ return { success: true, params };
2086
+ }
2087
+ }
2088
+ if (patternSegment.startsWith(":") && patternSegment.endsWith("?")) {
2089
+ const paramName = patternSegment.slice(1, -1);
2090
+ const nextPattern = patternSegments[i + 1];
2091
+ if (nextPattern && !nextPattern.startsWith(":") && nextPattern !== "*" && pathIndex < pathLength && // !/test == /:user?/test
2092
+ // বর্তমান পথ যদি পরবর্তী প্যাটার্ন মানে স্ট্যাটিক পথ এর সাথে মাইল তাহলে
2093
+ pathSegments[pathIndex] === nextPattern) {
2094
+ params[paramName] = null;
2095
+ continue;
2096
+ }
2097
+ const remainingPatterns = patternSegments.slice(i + 1);
2098
+ const requiredCount = remainingPatterns.filter(
2099
+ (seg) => !(seg.startsWith(":") && seg.endsWith("?"))
2100
+ ).length;
2101
+ const remainingPath = pathLength - pathIndex;
2102
+ if (remainingPath === requiredCount) {
2103
+ params[paramName] = null;
2104
+ } else if (pathIndex < pathLength) {
2105
+ params[paramName] = pathSegments[pathIndex];
2106
+ pathIndex++;
2107
+ } else {
2108
+ params[paramName] = null;
2109
+ }
2110
+ continue;
2111
+ }
2112
+ if (patternSegment.startsWith(":")) {
2113
+ const paramName = patternSegment.slice(1);
2114
+ if (!/^[a-zA-Z0-9_]+$/.test(paramName)) {
2115
+ return { success: false, params: {} };
2116
+ }
2117
+ if (pathIndex < pathLength) {
2118
+ params[paramName] = pathSegments[pathIndex];
2119
+ pathIndex++;
2120
+ } else {
2121
+ return { success: false, params: {} };
2122
+ }
2123
+ continue;
2124
+ }
2125
+ const pathSegment = pathSegments[pathIndex];
2126
+ if (patternSegment !== pathSegment) {
2127
+ return { success: false, params: {} };
2128
+ }
2129
+ pathIndex++;
2130
+ }
2131
+ if (pathIndex < pathLength) {
2132
+ return { success: false, params: {} };
2133
+ }
2134
+ return { success: true, params };
2135
+ }
2136
+
2137
+ class TezX extends Router {
2138
+ constructor({
2139
+ basePath = "/",
2140
+ env = {},
2141
+ logger = void 0,
2142
+ allowDuplicateMw = false,
2143
+ overwriteMethod = true
2144
+ } = {}) {
2145
+ GlobalConfig.allowDuplicateMw = allowDuplicateMw;
2146
+ GlobalConfig.overwriteMethod = overwriteMethod;
2147
+ if (logger) {
2148
+ GlobalConfig.loggerFn = logger;
2149
+ GlobalConfig.enableLogger = true;
2150
+ }
2151
+ super({ basePath, env });
2152
+ this.serve = this.serve.bind(this);
2153
+ }
2154
+ #hashRouter(method, pathname) {
2155
+ const routers = this.routers;
2156
+ for (let pattern of this.routers.keys()) {
2157
+ const { success, params } = useParams({
2158
+ path: pathname,
2159
+ urlPattern: pattern
2160
+ });
2161
+ const handlers = routers.get(pattern)?.get(method) || routers.get(pattern)?.get("ALL");
2162
+ if (success && handlers) {
2163
+ return {
2164
+ callback: handlers.callback,
2165
+ middlewares: handlers.middlewares,
2166
+ params
2167
+ };
2168
+ }
2169
+ }
2170
+ return null;
2171
+ }
2172
+ #triRouter(method, pathname) {
2173
+ const parts = pathname.split("/").filter(Boolean);
2174
+ const params = {};
2175
+ let node = this.triRouter;
2176
+ for (let part of parts) {
2177
+ if (node.children.has(part)) {
2178
+ node = node.children.get(part);
2179
+ } else if (node.children.has(":")) {
2180
+ node = node.children.get(":");
2181
+ if (node.paramName) params[node.paramName] = part;
2182
+ } else {
2183
+ return null;
2184
+ }
2185
+ }
2186
+ if (node?.handlers?.size && node?.pathname) {
2187
+ const handlers = node.handlers.get(method) || node.handlers.get("ALL");
2188
+ if (handlers) {
2189
+ return {
2190
+ middlewares: handlers.middlewares,
2191
+ callback: handlers.callback,
2192
+ params
2193
+ };
2194
+ }
2195
+ return null;
2196
+ }
2197
+ return null;
2198
+ }
2199
+ findRoute(method, pathname) {
2200
+ const route = this.#triRouter(method, pathname) || this.#hashRouter(method, pathname);
2201
+ if (route) {
2202
+ return {
2203
+ ...route,
2204
+ middlewares: [...route.middlewares]
2205
+ };
2206
+ }
2207
+ return null;
2208
+ }
2209
+ #createHandler(middlewares, finalCallback) {
2210
+ return async (ctx) => {
2211
+ let index = 0;
2212
+ const next = async () => {
2213
+ if (index < middlewares.length) {
2214
+ return middlewares[index++](ctx, next);
2215
+ } else {
2216
+ const response = await finalCallback(ctx);
2217
+ return response;
2218
+ }
2219
+ };
2220
+ return await next();
2221
+ };
2222
+ }
2223
+ #findMiddleware(pathname) {
2224
+ const parts = pathname.split("/").filter(Boolean);
2225
+ let middlewares = [];
2226
+ let node = this.triMiddlewares;
2227
+ for (let part of parts) {
2228
+ if (node.children.has(part)) {
2229
+ node = node.children.get(part);
2230
+ } else if (node.children.has("*")) {
2231
+ node = node.children.get("*");
2232
+ } else if (node.children.has(":")) {
2233
+ node = node.children.get(":");
2234
+ } else {
2235
+ break;
2236
+ }
2237
+ middlewares.push(...node.middlewares);
2238
+ }
2239
+ return middlewares;
2240
+ }
2241
+ async #handleRequest(req) {
2242
+ let ctx = new Context(req);
2243
+ const urlRef = ctx.req.urlRef;
2244
+ const { pathname } = urlRef;
2245
+ let middlewares = this.#findMiddleware(pathname);
2246
+ ctx.env = this.env;
2247
+ const logger = GlobalConfig.loggerFn();
2248
+ if (logger.request) {
2249
+ logger.request(ctx.method, ctx.pathname);
2250
+ }
2251
+ try {
2252
+ return await this.#createHandler(
2253
+ [...this.triMiddlewares.middlewares, ...middlewares],
2254
+ async (ctx2) => {
2255
+ const find = this.findRoute(ctx2.req.method, pathname);
2256
+ if (find?.callback) {
2257
+ ctx2.params = find.params;
2258
+ const callback = find.callback;
2259
+ let middlewares2 = find.middlewares;
2260
+ const response = await this.#createHandler(
2261
+ middlewares2,
2262
+ callback
2263
+ )(ctx2);
2264
+ if (response?.headers) {
2265
+ ctx2.headers.add(response.headers);
2266
+ }
2267
+ const statusText = response?.statusText || httpStatusMap[response?.status] || "";
2268
+ const status = response.status || 200;
2269
+ let headers = ctx2.headers.toObject();
2270
+ if (logger.response) {
2271
+ logger.response(ctx2.method, ctx2.pathname, status);
2272
+ }
2273
+ if (response instanceof Response) {
2274
+ return new Response(response.body, {
2275
+ status,
2276
+ statusText,
2277
+ headers
2278
+ });
2279
+ }
2280
+ return new Response(response.body, {
2281
+ status,
2282
+ statusText,
2283
+ headers
2284
+ });
2285
+ } else {
2286
+ if (logger.response) {
2287
+ logger.response(ctx2.method, ctx2.pathname, 404);
2288
+ }
2289
+ return GlobalConfig.notFound(ctx2);
2290
+ }
2291
+ }
2292
+ )(ctx);
2293
+ } catch (err) {
2294
+ let error = err;
2295
+ if (err instanceof Error) {
2296
+ error = err.stack;
2297
+ }
2298
+ if (logger.error) {
2299
+ logger.error(`${httpStatusMap[500]}: ${error} `);
2300
+ }
2301
+ return GlobalConfig.onError(error, ctx);
2302
+ }
2303
+ }
2304
+ async serve(req) {
2305
+ return this.#handleRequest(req);
2306
+ }
2307
+ }
2308
+
2309
+ function parseEnvFile(filePath, result) {
2310
+ try {
2311
+ let fileExists = false;
2312
+ let runtime = EnvironmentDetector.getEnvironment;
2313
+ if (runtime === "node" || runtime === "bun") {
2314
+ const { existsSync } = require("fs");
2315
+ fileExists = existsSync(filePath);
2316
+ } else if (runtime === "deno") {
2317
+ try {
2318
+ Deno.statSync(filePath);
2319
+ fileExists = true;
2320
+ } catch {
2321
+ fileExists = false;
2322
+ }
2323
+ }
2324
+ if (!fileExists) {
2325
+ return;
2326
+ }
2327
+ let fileContent = "";
2328
+ if (runtime === "node" || runtime === "bun") {
2329
+ const { readFileSync } = require("fs");
2330
+ fileContent = readFileSync(filePath, "utf8");
2331
+ } else if (runtime === "deno") {
2332
+ fileContent = new TextDecoder("utf-8").decode(
2333
+ Deno.readFileSync(filePath)
2334
+ );
2335
+ }
2336
+ const lines = fileContent.split("\n");
2337
+ for (const line of lines) {
2338
+ const trimmedLine = line.trim();
2339
+ if (!trimmedLine || trimmedLine.startsWith("#")) continue;
2340
+ const [key, value] = trimmedLine.split("=", 2).map((part) => part.trim());
2341
+ if (key && value) {
2342
+ const parsedValue = value.replace(/^"(.*)"$/, "$1").replace(/^'(.*)'$/, "$1");
2343
+ result[key] = parsedValue;
2344
+ if (runtime === "node" || runtime === "bun") {
2345
+ process.env[key] = parsedValue;
2346
+ } else if (runtime === "deno") {
2347
+ Deno.env.set(key, parsedValue);
2348
+ }
2349
+ }
2350
+ }
2351
+ } catch (error) {
2352
+ console.error(`[dotenv] Error parsing file: ${filePath}`, error);
2353
+ }
2354
+ }
2355
+ function loadEnv(basePath = "./") {
2356
+ const result = {};
2357
+ const envFiles = [
2358
+ ".env",
2359
+ ".env.local",
2360
+ `.env.${process?.env?.NODE_ENV || "development"}`,
2361
+ // Supports NODE_ENV (e.g., .env.development, .env.production)
2362
+ `.env.${process?.env?.NODE_ENV || "development"}.local`
2363
+ ];
2364
+ for (const envFile of envFiles) {
2365
+ parseEnvFile(`${basePath}${envFile}`, result);
2366
+ }
2367
+ return result;
2368
+ }
2369
+
2370
+ const COLORS = {
2371
+ reset: "\x1B[0m",
2372
+ bold: "\x1B[1m",
2373
+ gray: "\x1B[90m",
2374
+ red: "\x1B[31m",
2375
+ green: "\x1B[32m",
2376
+ yellow: "\x1B[33m",
2377
+ blue: "\x1B[34m",
2378
+ magenta: "\x1B[35m",
2379
+ cyan: "\x1B[36m",
2380
+ bgBlue: "\x1B[44m",
2381
+ bgMagenta: "\x1B[45m"};
2382
+ const loggerOutput = (level, message, ...args) => {
2383
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
2384
+ const LEVEL_COLORS = {
2385
+ info: COLORS.blue,
2386
+ warn: COLORS.yellow,
2387
+ error: COLORS.red,
2388
+ debug: COLORS.cyan,
2389
+ success: COLORS.green
2390
+ };
2391
+ const prefix = `${COLORS.gray}[${timestamp}]${COLORS.reset}`;
2392
+ const levelText = `${LEVEL_COLORS[level]}[${level.toUpperCase()}]${COLORS.reset}`;
2393
+ console.log(`${prefix} ${levelText} ${message}`, ...args?.flat());
2394
+ };
2395
+ function logger() {
2396
+ const startTime = performance.now();
2397
+ if (GlobalConfig.enableLogger) {
2398
+ return {
2399
+ request: (method, pathname) => {
2400
+ console.log(
2401
+ `${COLORS.bold}<-- ${COLORS.reset}${COLORS.bgMagenta} ${method} ${COLORS.reset} ${pathname}`
2402
+ );
2403
+ },
2404
+ response: (method, pathname, status) => {
2405
+ const elapsed = performance.now() - startTime;
2406
+ console.log(
2407
+ `${COLORS.bold}--> ${COLORS.reset}${COLORS.bgBlue} ${method} ${COLORS.reset} ${pathname} ${COLORS.yellow}${status}${COLORS.reset} ${COLORS.magenta}${elapsed.toFixed(2)}ms${COLORS.reset}`
2408
+ );
2409
+ },
2410
+ info: (msg, ...args) => loggerOutput("info", msg, ...args),
2411
+ warn: (msg, ...args) => loggerOutput("warn", msg, ...args),
2412
+ error: (msg, ...args) => loggerOutput("error", msg, ...args),
2413
+ debug: (msg, ...args) => loggerOutput("debug", msg, ...args),
2414
+ success: (msg, ...args) => loggerOutput("success", msg, ...args)
2415
+ };
2416
+ }
2417
+ return {
2418
+ request: (method, pathname) => {
2419
+ },
2420
+ response: (method, pathname, status) => {
2421
+ },
2422
+ info: (msg, ...args) => {
2423
+ },
2424
+ warn: (msg, ...args) => {
2425
+ },
2426
+ error: (msg, ...args) => {
2427
+ },
2428
+ debug: (msg, ...args) => {
2429
+ },
2430
+ success: (msg, ...args) => {
2431
+ }
2432
+ };
2433
+ }
2434
+
2435
+ function cors(option = {}) {
2436
+ const {
2437
+ methods,
2438
+ allowedHeaders,
2439
+ credentials,
2440
+ exposedHeaders,
2441
+ maxAge,
2442
+ origin
2443
+ } = option;
2444
+ return async (ctx, next) => {
2445
+ const reqOrigin = ctx.req.headers.get("origin") || "";
2446
+ let allowOrigin = "*";
2447
+ if (typeof origin === "string") {
2448
+ allowOrigin = origin;
2449
+ } else if (origin instanceof RegExp) {
2450
+ allowOrigin = origin.test(reqOrigin) ? reqOrigin : "";
2451
+ } else if (Array.isArray(origin)) {
2452
+ const isAllowed = origin.some((item) => {
2453
+ if (typeof item === "string") {
2454
+ return item === reqOrigin;
2455
+ } else if (item instanceof RegExp) {
2456
+ return item.test(reqOrigin);
2457
+ }
2458
+ });
2459
+ allowOrigin = isAllowed ? reqOrigin : "";
2460
+ } else if (typeof origin === "function") {
2461
+ allowOrigin = origin(reqOrigin) ? reqOrigin : "";
2462
+ }
2463
+ ctx.headers.set("Access-Control-Allow-Origin", allowOrigin);
2464
+ ctx.headers.set(
2465
+ "Access-Control-Allow-Methods",
2466
+ (methods || ["GET", "POST", "PUT", "DELETE"]).join(", ")
2467
+ );
2468
+ ctx.headers.set(
2469
+ "Access-Control-Allow-Headers",
2470
+ (allowedHeaders || ["Content-Type", "Authorization"]).join(", ")
2471
+ );
2472
+ if (exposedHeaders) {
2473
+ ctx.headers.set(
2474
+ "Access-Control-Expose-Headers",
2475
+ exposedHeaders.join(", ")
2476
+ );
2477
+ }
2478
+ if (credentials) {
2479
+ ctx.headers.set("Access-Control-Allow-Credentials", "true");
2480
+ }
2481
+ if (maxAge) {
2482
+ ctx.headers.set("Access-Control-Max-Age", maxAge.toString());
2483
+ }
2484
+ if (ctx.req.method === "OPTIONS") {
2485
+ return new Response(null, {
2486
+ status: 204,
2487
+ headers: ctx.headers.toObject()
2488
+ });
2489
+ }
2490
+ return await next();
2491
+ };
2492
+ }
2493
+
2494
+ exports.Router = Router;
2495
+ exports.TezResponse = TezResponse;
2496
+ exports.TezX = TezX;
2497
+ exports.bunAdapter = bunAdapter;
2498
+ exports.cors = cors;
2499
+ exports.denoAdapter = denoAdapter;
2500
+ exports.loadEnv = loadEnv;
2501
+ exports.logger = logger;
2502
+ exports.nodeAdapter = nodeAdapter;
2503
+ exports.useParams = useParams;