@je-es/server 0.0.1
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/LICENSE +21 -0
- package/README.md +802 -0
- package/dist/main.cjs +11 -0
- package/dist/main.cjs.map +1 -0
- package/dist/main.d.cts +262 -0
- package/dist/main.d.ts +262 -0
- package/dist/main.js +11 -0
- package/dist/main.js.map +1 -0
- package/package.json +59 -0
package/dist/main.cjs
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use strict';Object.defineProperty(exports,'__esModule',{value:true});var bunSql=require('drizzle-orm/bun-sql'),W=require('crypto'),sqliteCore=require('drizzle-orm/sqlite-core'),drizzleOrm=require('drizzle-orm');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var W__default=/*#__PURE__*/_interopDefault(W);var D=class{constructor(){this.routes=new Map;this.regexRoutes=[];}match(e,t){let r=`${e}:${t}`;if(this.routes.has(r))return {handler:this.routes.get(r),params:{}};for(let n of this.regexRoutes)if(n.method===e){let c=t.match(n.pattern);if(c?.groups)return {handler:n.handler,params:c.groups}}return null}getAll(){let e=Array.from(this.routes.entries()).map(([r,n])=>{let c=r.indexOf(":"),d=r.substring(0,c),a=r.substring(c+1);return {method:d,path:a,handler:n}}),t=this.regexRoutes.map(r=>{let n=r.key.indexOf(":");return {method:r.method,path:r.key.substring(n+1),handler:r.handler}});return [...e,...t]}clear(){this.routes.clear(),this.regexRoutes=[];}remove(e,t){let r=`${e}:${t}`;if(this.routes.has(r))return this.routes.delete(r),true;let n=this.regexRoutes.findIndex(c=>c.key===r);return n>=0?(this.regexRoutes.splice(n,1),true):false}register(e,t,r,n={}){let c=`${e}:${t}`;if(t.includes(":")){let d=this.pathToRegex(t),a=this.regexRoutes.findIndex(b=>b.key===c),l={pattern:d,method:e,handler:r,key:c};a>=0?this.regexRoutes[a]=l:this.regexRoutes.push(l);}else this.routes.set(c,r);}pathToRegex(e){let r=e.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/:(\w+)/g,"(?<$1>[^/]+)");return new RegExp(`^${r}$`)}};var I=class{constructor(){this.rateLimitStore=new Map;this.csrfTokens=new Map;this.requestLog=new Map;this.MAX_REQUEST_LOG_SIZE=1e3;}checkRateLimit(e,t,r){let n=Date.now(),c=this.rateLimitStore.get(e);return c?n<c.reset?c.count>=t?false:(c.count++,true):(this.rateLimitStore.set(e,{count:1,reset:n+r}),true):(this.rateLimitStore.set(e,{count:1,reset:n+r}),true)}cleanupRateLimit(){let e=Date.now();for(let[t,r]of this.rateLimitStore.entries())e>r.reset&&this.rateLimitStore.delete(t);}generateCsrfToken(e,t=36e5){let r=W__default.default.randomBytes(32).toString("hex");return this.csrfTokens.set(r,{sessionId:e,expires:Date.now()+t}),r}validateCsrfToken(e,t){let r=this.csrfTokens.get(e);return r?Date.now()>r.expires?(this.csrfTokens.delete(e),false):r.sessionId===t?(this.csrfTokens.delete(e),true):false:false}cleanupCsrfTokens(){let e=Date.now();for(let[t,r]of this.csrfTokens.entries())e>r.expires&&this.csrfTokens.delete(t);}sanitizeHtml(e){return e?e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/"):""}sanitizeSql(e){return e?e.replace(/\\/g,"\\\\").replace(/;/g,"").replace(/'/g,"''").replace(/"/g,'\\"').replace(/\x00/g,""):""}logRequest(e,t,r,n,c,d){if(this.requestLog.set(e,{timestamp:new Date().toISOString(),method:t,path:r,ip:n,status:c,duration:d}),this.requestLog.size>this.MAX_REQUEST_LOG_SIZE){let{value:a}=this.requestLog.keys().next()||{value:null};a&&this.requestLog.delete(a);}}getRequestLog(e){return this.requestLog.get(e)}getAllRequestLogs(){return Array.from(this.requestLog.values())}clearAll(){this.rateLimitStore.clear(),this.csrfTokens.clear(),this.requestLog.clear();}getStats(){return {rateLimitEntries:this.rateLimitStore.size,csrfTokens:this.csrfTokens.size,requestLogs:this.requestLog.size}}};var P=class{constructor(e="info",t=false){this.level=1;this.pretty=false;this.levels={debug:0,info:1,warn:2,error:3,fatal:4};this.level=this.levels[e]??1,this.pretty=t;}debug(e,t){this.log("debug",this.levels.debug,e,t);}info(e,t){this.log("info",this.levels.info,e,t);}warn(e,t){this.log("warn",this.levels.warn,e,t);}error(e,t){this.log("error",this.levels.error,e,t);}fatal(e,t){this.log("fatal",this.levels.fatal,e,t),process.env.NODE_ENV;}log(e,t,r,n){if(t<this.level)return;let c=new Date().toISOString(),d=r??{},a={timestamp:c,level:e.toUpperCase(),message:n||"No message",...d},l=this.pretty?`[${c}] ${e.toUpperCase()} ${n||"No message"}
|
|
2
|
+
${JSON.stringify(d,null,2)}`:JSON.stringify(a);e==="error"||e==="fatal"?console.error(l):e==="warn"?console.warn(l):console.log(l);}};var v=class extends Error{constructor(t,r=500,n){super(t);this.message=t;this.statusCode=r;this.code=n;this.name="AppError";}},A=class extends v{constructor(t,r){super(t,400,"VALIDATION_ERROR");this.issues=r;this.name="ValidationError";}},Q=class extends v{constructor(e){super(e,500,"DATABASE_ERROR"),this.name="DatabaseError";}},$=class extends v{constructor(e="Request timeout"){super(e,408,"TIMEOUT_ERROR"),this.name="TimeoutError";}},X=class extends v{constructor(e="Too many requests"){super(e,429,"RATE_LIMIT_ERROR"),this.name="RateLimitError";}};var H=new I,O=new D;function Y(s={}){let e=s.port||3e3,t=s.hostname||"localhost",r=s.maxRequestSize||10*1024*1024,n=s.requestTimeout||3e4,c=s.gracefulShutdownTimeout||1e4,d=typeof s.logging=="object"?s.logging:{},a=s.logging?new P(d.level||"info",d.pretty):null,l=new Map,b=[],x=new Set,T=setInterval(()=>{H.cleanupRateLimit(),H.cleanupCsrfTokens();},120*1e3);async function u(o){let h=Date.now(),i=crypto.randomUUID(),m=new URL(o.url).pathname,E=o.method.toUpperCase(),R=re(o);x.add(i);try{let y=o.headers.get("content-length");if(y&&parseInt(y)>r)return a?.warn({requestId:i,size:y,ip:R},"Request too large"),new Response(JSON.stringify({error:"Payload too large"}),{status:413,headers:{"Content-Type":"application/json"}});let q=ne(o,s);if(E==="OPTIONS")return new Response(null,{status:204,headers:q});if(s.security&&typeof s.security=="object"&&s.security.rateLimit){let w=typeof s.security.rateLimit=="object"?s.security.rateLimit:{},L=w.max||100,z=w.windowMs||6e4,V=w.keyGenerator?w.keyGenerator({request:o,ip:R}):R;if(!H.checkRateLimit(V,L,z))return a?.warn({requestId:i,ip:R,key:V},"Rate limit exceeded"),new Response(JSON.stringify({error:w.message||"Too many requests"}),{status:429,headers:{"Content-Type":"application/json"}})}let U=null;["POST","PUT","PATCH"].includes(E)&&(U=await ee(o,a,r));let B=l.get("default"),N=O.match(E,m);if(!N){let w=F(o,{},B,a,i);return a?.warn({requestId:i,method:E,path:m,ip:R},"Route not found"),w.json({error:"Not Found",path:m},404)}let M=F(o,N.params||{},B,a,i);M.body=U,M.request=o;let G=new AbortController,K=new Promise((w,L)=>{let z=setTimeout(()=>{G.abort(),L(new $("Request timeout"));},n);G.signal.addEventListener("abort",()=>clearTimeout(z));}),k=await Promise.race([N.handler(M),K]),S=new Headers(k.headers);q.forEach((w,L)=>{S.has(L)||S.set(L,w);}),S.set("X-Request-ID",i),S.set("X-Content-Type-Options","nosniff"),S.set("X-Frame-Options","DENY"),S.set("X-XSS-Protection","1; mode=block"),S.set("Referrer-Policy","strict-origin-when-cross-origin");let J=Date.now()-h;return H.logRequest(i,E,m,R,k.status,J),a?.info({requestId:i,method:E,path:m,status:k.status,duration:J,ip:R},"Request completed"),new Response(k.body,{status:k.status,headers:S})}catch(y){if(y instanceof v)return a?.warn({error:y.message,requestId:i,ip:R},`App error: ${y.message}`),new Response(JSON.stringify({error:y.message,code:y.code,requestId:i}),{status:y.statusCode,headers:{"Content-Type":"application/json"}});a?.error({error:String(y),requestId:i,ip:R},"Unhandled error");let q=process.env.NODE_ENV==="production"?"Internal Server Error":y.message;return new Response(JSON.stringify({error:q,requestId:i}),{status:500,headers:{"Content-Type":"application/json"}})}finally{x.delete(i);}}let p={method:"GET",path:"/health",handler:o=>o.json({status:"healthy",timestamp:new Date().toISOString(),uptime:process.uptime(),activeRequests:x.size})},g={method:"GET",path:"/readiness",handler:o=>{let h=l.size>0,i=h||l.size===0;return o.json({ready:i,checks:{database:h?"connected":"not configured",activeRequests:x.size},timestamp:new Date().toISOString()},i?200:503)}};s.routes&&s.routes.forEach(o=>{b.push(o),(Array.isArray(o.method)?o.method:[o.method]).forEach(i=>{O.register(i,o.path,o.handler,o);});}),b.push(p,g),O.register("GET","/health",p.handler,p),O.register("GET","/readiness",g.handler,g);let f=null,_={app:null,logger:a,db:l,bunServer:null,async start(){if(s.database){let h=Array.isArray(s.database)?s.database:[s.database];for(let i of h){let C=i.name||"default";try{if(i.type||(i.type="bun-sql"),i.type==="bun-sql")if(typeof i.connection=="string"){let m=bunSql.drizzle(i.connection,{schema:i.schema});l.set(C,m),a?.info({name:C,connection:"string"},"\u2705 Bun SQL connected");}else if(typeof i.connection=="function"){let m=bunSql.drizzle({client:i.connection,schema:i.schema});l.set(C,m),a?.info({name:C,connection:"function"},"\u2705 Bun SQL connected");}else if(i.connection!==null&&i.connection!==void 0&&typeof i.connection=="object"){let m=bunSql.drizzle({client:i.connection,schema:i.schema});l.set(C,m),a?.info({name:C,connection:"object"},"\u2705 Bun SQL connected");}else {let m=typeof i.connection;throw new Error(`Bun SQL connection must be a connection string, SQL function, or SQL instance (got ${m})`)}else throw new Error(`Unsupported database type: ${i.type}`)}catch(m){throw a?.error({error:String(m),name:C,type:i.type},"Failed to connect to database"),m}}}f=Bun.serve({port:e,hostname:t,fetch:u}),_.bunServer=f;let o=`http://${t}:${e}`;console.log(`\u2192 URL: ${o}
|
|
3
|
+
\u2192 Environment: ${process.env.NODE_ENV||"development"}
|
|
4
|
+
\u2192 Routes: ${b.length.toString()}
|
|
5
|
+
\u2192 Database: ${l.size>0?"\u2705 Connected":"\u274C None"}
|
|
6
|
+
\u2192 Security: ${s.security?"\u2705 ENABLED":"\u274C Disabled"}
|
|
7
|
+
|
|
8
|
+
\u{1F50D} Health: ${o}/health
|
|
9
|
+
\u{1F50D} Ready: ${o}/readiness
|
|
10
|
+
`),a?.info({url:o},"Server started");},async stop(){if(a?.info("Stopping server..."),x.size>0){a?.info({count:x.size},"Waiting for active requests...");let o=Date.now()+c;for(;x.size>0&&Date.now()<o;)await new Promise(h=>setTimeout(h,100));x.size>0&&a?.warn({count:x.size},"Force closing with active requests");}if(clearInterval(T),s.onShutdown)try{await s.onShutdown();}catch(o){a?.error({error:String(o)},"Error in shutdown handler");}for(let[o,h]of l.entries())try{h?.$client?.close&&h.$client.close(),a?.info({name:o},"Database closed");}catch(i){a?.error({error:String(i),name:o},"Error closing database");}f&&(f.stop(),a?.info("Bun server stopped")),a?.info("Server stopped successfully");},addRoute(o){b.push(o),(Array.isArray(o.method)?o.method:[o.method]).forEach(i=>{O.register(i,o.path,o.handler,o);}),a?.info({method:o.method,path:o.path},"Route added");},getRoutes(){return b}};return _}async function ee(s,e,t){let r=s.headers.get("content-type")||"";try{if(r.includes("application/json")){let n=await s.text();if(n.length>t)throw new A("Payload too large");if(!n.trim())return {};try{return JSON.parse(n)}catch(c){throw e?.warn({error:String(c),bodyPreview:n.substring(0,100)},"Invalid JSON in request body"),new A("Invalid JSON in request body")}}if(r.includes("application/x-www-form-urlencoded")){let n=await s.text();if(n.length>t)throw new A("Payload too large");return Object.fromEntries(new URLSearchParams(n))}if(r.includes("multipart/form-data"))return await s.formData()}catch(n){throw n instanceof A?n:(e?.error({error:String(n)},"Error parsing request body"),new A("Failed to parse request body"))}return {}}function te(s){let e=new Map;if(!s)return e;let t=s.split(";");for(let r of t){let[n,...c]=r.trim().split("=");if(n){let d=c.join("=");e.set(n,d?decodeURIComponent(d):"");}}return e}function F(s,e,t,r,n){let c=new URL(s.url),d=Object.fromEntries(c.searchParams),a=s.headers,l=200,b=new Map,x=te(a.get("cookie")||""),T={request:s,params:e,query:d,headers:a,db:t,logger:r,requestId:n,get statusCode(){return l},set statusCode(u){l=u;},body:null,json(u,p){return new Response(JSON.stringify(u),{status:p??l,headers:{"Content-Type":"application/json",...this._setCookieHeaders()}})},text(u,p){return new Response(u,{status:p??l,headers:{"Content-Type":"text/plain",...this._setCookieHeaders()}})},html(u,p){return new Response(u,{status:p??l,headers:{"Content-Type":"text/html; charset=utf-8",...this._setCookieHeaders()}})},redirect(u,p=302){return new Response(null,{status:p,headers:{Location:u,...this._setCookieHeaders()}})},file(u,p="application/octet-stream"){let g=Bun.file(u);return new Response(g,{headers:{"Content-Type":p,...this._setCookieHeaders()}})},setCookie(u,p,g={}){let f=`${u}=${encodeURIComponent(p)}`;return g.maxAge!==void 0&&(f+=`; Max-Age=${g.maxAge}`),g.expires&&(f+=`; Expires=${g.expires.toUTCString()}`),g.path&&(f+=`; Path=${g.path}`),g.domain&&(f+=`; Domain=${g.domain}`),g.secure&&(f+="; Secure"),g.httpOnly&&(f+="; HttpOnly"),g.sameSite&&(f+=`; SameSite=${g.sameSite}`),b.set(u,f),T},getCookie(u){return x.get(u)},deleteCookie(u,p={}){return T.setCookie(u,"",{...p,maxAge:0,path:p.path||"/"})},setHeader(u,p){return a.set(u,p),T},getHeader(u){return a.get(u)||void 0},status(u){return l=u,T},_setCookieHeaders(){let u={};return b.size>0&&(u["Set-Cookie"]=Array.from(b.values())),u}};return T}function re(s){let e=s.headers.get("x-forwarded-for");if(e)return e.split(",").map(n=>n.trim())[0]||"unknown";let t=s.headers.get("x-real-ip");return t||"unknown"}function ne(s,e){let t=new Headers;if(!e.security||typeof e.security!="object"||!e.security.cors)return t;let r=typeof e.security.cors=="object"?e.security.cors:{},n=s.headers.get("Origin");if(n){typeof r.origin=="function"?r.origin(n)&&t.set("Access-Control-Allow-Origin",n):Array.isArray(r.origin)?r.origin.includes(n)&&t.set("Access-Control-Allow-Origin",n):typeof r.origin=="string"?t.set("Access-Control-Allow-Origin",r.origin):t.set("Access-Control-Allow-Origin",n);let c=r.methods||["GET","POST","PUT","DELETE","PATCH","OPTIONS"];t.set("Access-Control-Allow-Methods",c.join(", "));let d=r.allowedHeaders||["Content-Type","Authorization","X-Requested-With"];t.set("Access-Control-Allow-Headers",d.join(", ")),r.credentials&&t.set("Access-Control-Allow-Credentials","true"),r.maxAge&&t.set("Access-Control-Max-Age",r.maxAge.toString());}return t}var de=Y;Object.defineProperty(exports,"blob",{enumerable:true,get:function(){return sqliteCore.blob}});Object.defineProperty(exports,"check",{enumerable:true,get:function(){return sqliteCore.check}});Object.defineProperty(exports,"foreignKey",{enumerable:true,get:function(){return sqliteCore.foreignKey}});Object.defineProperty(exports,"index",{enumerable:true,get:function(){return sqliteCore.index}});Object.defineProperty(exports,"integer",{enumerable:true,get:function(){return sqliteCore.integer}});Object.defineProperty(exports,"numeric",{enumerable:true,get:function(){return sqliteCore.numeric}});Object.defineProperty(exports,"primaryKey",{enumerable:true,get:function(){return sqliteCore.primaryKey}});Object.defineProperty(exports,"real",{enumerable:true,get:function(){return sqliteCore.real}});Object.defineProperty(exports,"sqliteTable",{enumerable:true,get:function(){return sqliteCore.sqliteTable}});Object.defineProperty(exports,"text",{enumerable:true,get:function(){return sqliteCore.text}});Object.defineProperty(exports,"uniqueIndex",{enumerable:true,get:function(){return sqliteCore.uniqueIndex}});Object.defineProperty(exports,"Many",{enumerable:true,get:function(){return drizzleOrm.Many}});Object.defineProperty(exports,"One",{enumerable:true,get:function(){return drizzleOrm.One}});Object.defineProperty(exports,"and",{enumerable:true,get:function(){return drizzleOrm.and}});Object.defineProperty(exports,"asc",{enumerable:true,get:function(){return drizzleOrm.asc}});Object.defineProperty(exports,"between",{enumerable:true,get:function(){return drizzleOrm.between}});Object.defineProperty(exports,"desc",{enumerable:true,get:function(){return drizzleOrm.desc}});Object.defineProperty(exports,"eq",{enumerable:true,get:function(){return drizzleOrm.eq}});Object.defineProperty(exports,"exists",{enumerable:true,get:function(){return drizzleOrm.exists}});Object.defineProperty(exports,"gt",{enumerable:true,get:function(){return drizzleOrm.gt}});Object.defineProperty(exports,"gte",{enumerable:true,get:function(){return drizzleOrm.gte}});Object.defineProperty(exports,"ilike",{enumerable:true,get:function(){return drizzleOrm.ilike}});Object.defineProperty(exports,"inArray",{enumerable:true,get:function(){return drizzleOrm.inArray}});Object.defineProperty(exports,"isNotNull",{enumerable:true,get:function(){return drizzleOrm.isNotNull}});Object.defineProperty(exports,"isNull",{enumerable:true,get:function(){return drizzleOrm.isNull}});Object.defineProperty(exports,"like",{enumerable:true,get:function(){return drizzleOrm.like}});Object.defineProperty(exports,"lt",{enumerable:true,get:function(){return drizzleOrm.lt}});Object.defineProperty(exports,"lte",{enumerable:true,get:function(){return drizzleOrm.lte}});Object.defineProperty(exports,"ne",{enumerable:true,get:function(){return drizzleOrm.ne}});Object.defineProperty(exports,"not",{enumerable:true,get:function(){return drizzleOrm.not}});Object.defineProperty(exports,"notBetween",{enumerable:true,get:function(){return drizzleOrm.notBetween}});Object.defineProperty(exports,"notExists",{enumerable:true,get:function(){return drizzleOrm.notExists}});Object.defineProperty(exports,"notInArray",{enumerable:true,get:function(){return drizzleOrm.notInArray}});Object.defineProperty(exports,"or",{enumerable:true,get:function(){return drizzleOrm.or}});Object.defineProperty(exports,"relations",{enumerable:true,get:function(){return drizzleOrm.relations}});Object.defineProperty(exports,"sql",{enumerable:true,get:function(){return drizzleOrm.sql}});exports.AppError=v;exports.DatabaseError=Q;exports.Logger=P;exports.RateLimitError=X;exports.Router=D;exports.SecurityManager=I;exports.TimeoutError=$;exports.ValidationError=A;exports.default=de;exports.server=Y;//# sourceMappingURL=main.cjs.map
|
|
11
|
+
//# sourceMappingURL=main.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mod/router.ts","../src/mod/security.ts","../src/mod/logger.ts","../src/types.d.ts","../src/main.ts"],"names":["Router","method","path","key","route","match","staticRoutes","handler","colonIndex","dynamicRoutes","index","r","config","pattern","existingIndex","SecurityManager","max","windowMs","now","record","sessionId","ttl","token","crypto","stored","data","html","input","id","ip","status","duration","first","Logger","level","pretty","msg","levelNum","ts","safeData","output","str","AppError","message","statusCode","code","ValidationError","issues","DatabaseError","TimeoutError","RateLimitError","security","router","server","port","hostname","maxReqSize","requestTimeout","gracefulShutdownTimeout","logCfg","logger","dbs","routes","activeRequests","cleanupInterval","handleRequest","request","startTime","requestId","getClientIp","contentLength","corsHeaders","handleCors","rateLimitCfg","rateLimitKey","body","parseBody","defaultDb","routeMatch","ctx","createAppContext","controller","timeoutPromise","_","reject","response","resHeaders","value","error","errorMessage","healthRoute","c","readinessRoute","dbConnected","ready","m","bunServer","instance","dbConfigs","dbCfg","dbName","db","drizzle","actualType","url","deadline","resolve","e","name","maxSize","contentType","text","parseCookies","cookieHeader","cookies","pairs","pair","valueParts","params","query","headers","cookieStore","parsedCookies","file","options","cookie","h","forwarded","realIp","corsConfig","origin","methods","allowedHeaders","main_default"],"mappings":"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","file":"main.cjs","sourcesContent":["// lib/router.ts\r\n//\r\n// Developed with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ TYPE ════════════════════════════════════════╗\r\n\r\n\texport interface RegexRoute {\r\n\t\tpattern\t\t: RegExp\r\n\t\tmethod\t\t: string\r\n\t\thandler\t\t: any\r\n\t\tkey\t\t\t: string\r\n\t}\r\n\r\n\texport type RegexRoutes = Array<RegexRoute>\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n export class Router {\r\n\r\n // ┌──────────────────────────────── INIT ──────────────────────────────┐\r\n\r\n\t\t\tprivate routes \t\t\t= new Map<string, any>()\r\n\t\t\tprivate regexRoutes\t\t: RegexRoutes = []\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── MAIN ──────────────────────────────┐\r\n\r\n\t\t\tmatch(method: string, path: string): { handler: any; params: Record<string, string> } | null {\r\n\t\t\t\tconst key = `${method}:${path}`\r\n\r\n\t\t\t\t// Try static route first (faster)\r\n\t\t\t\tif (this.routes.has(key)) {\r\n\t\t\t\treturn { handler: this.routes.get(key), params: {} }\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Try dynamic routes\r\n\t\t\t\tfor (const route of this.regexRoutes) {\r\n\t\t\t\tif (route.method === method) {\r\n\t\t\t\t\tconst match = path.match(route.pattern)\r\n\t\t\t\t\tif (match?.groups) {\r\n\t\t\t\t\treturn { handler: route.handler, params: match.groups }\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn null\r\n\t\t\t}\r\n\r\n\t\t\tgetAll() {\r\n\t\t\t\tconst staticRoutes = Array.from(this.routes.entries()).map(([key, handler]) => {\r\n\t\t\t\tconst colonIndex = key.indexOf(':')\r\n\t\t\t\tconst method = key.substring(0, colonIndex)\r\n\t\t\t\tconst path = key.substring(colonIndex + 1)\r\n\t\t\t\treturn { method, path, handler }\r\n\t\t\t\t})\r\n\r\n\t\t\t\tconst dynamicRoutes = this.regexRoutes.map(route => {\r\n\t\t\t\tconst colonIndex = route.key.indexOf(':')\r\n\t\t\t\treturn {\r\n\t\t\t\t\tmethod: route.method,\r\n\t\t\t\t\tpath: route.key.substring(colonIndex + 1),\r\n\t\t\t\t\thandler: route.handler\r\n\t\t\t\t}\r\n\t\t\t\t})\r\n\r\n\t\t\t\treturn [...staticRoutes, ...dynamicRoutes]\r\n\t\t\t}\r\n\r\n\t\t\tclear() {\r\n\t\t\t\tthis.routes.clear()\r\n\t\t\t\tthis.regexRoutes = []\r\n\t\t\t}\r\n\r\n\t\t\tremove(method: string, path: string): boolean {\r\n\t\t\t\tconst key = `${method}:${path}`\r\n\r\n\t\t\t\tif (this.routes.has(key)) {\r\n\t\t\t\tthis.routes.delete(key)\r\n\t\t\t\treturn true\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst index = this.regexRoutes.findIndex(r => r.key === key)\r\n\t\t\t\tif (index >= 0) {\r\n\t\t\t\tthis.regexRoutes.splice(index, 1)\r\n\t\t\t\treturn true\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn false\r\n\t\t\t}\r\n\r\n\t\t\tregister(method: string, path: string, handler: any, config: any = {}) {\r\n\t\t\t\tconst key = `${method}:${path}`\r\n\r\n\t\t\t\tif (path.includes(':')) {\r\n\t\t\t\t// Dynamic route with params\r\n\t\t\t\tconst pattern = this.pathToRegex(path)\r\n\r\n\t\t\t\t// Check if route already exists to prevent duplicates\r\n\t\t\t\tconst existingIndex = this.regexRoutes.findIndex(r => r.key === key)\r\n\r\n\t\t\t\tconst route = {\r\n\t\t\t\t\tpattern,\r\n\t\t\t\t\tmethod,\r\n\t\t\t\t\thandler,\r\n\t\t\t\t\tkey\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (existingIndex >= 0) {\r\n\t\t\t\t\t// Update existing route\r\n\t\t\t\t\tthis.regexRoutes[existingIndex] = route\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// Add new route\r\n\t\t\t\t\tthis.regexRoutes.push(route)\r\n\t\t\t\t}\r\n\t\t\t\t} else {\r\n\t\t\t\t// Static route\r\n\t\t\t\tthis.routes.set(key, handler)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── HELP ──────────────────────────────┐\r\n\r\n\t\t\tprivate pathToRegex(path: string): RegExp {\r\n\t\t\t\t// Escape special regex characters except ':'\r\n\t\t\t\tconst escaped = path.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&')\r\n\t\t\t\t// Replace :param with named capture groups\r\n\t\t\t\tconst pattern = escaped.replace(/:(\\w+)/g, '(?<$1>[^/]+)')\r\n\t\t\t\treturn new RegExp(`^${pattern}$`)\r\n\t\t\t}\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n","// lib/security.ts\r\n//\r\n// Developed with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import crypto from 'crypto'\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n export class SecurityManager {\r\n\r\n // ┌──────────────────────────────── INIT ──────────────────────────────┐\r\n\r\n\t\t\tprivate rateLimitStore \t= new Map<string, { count: number; reset: number }>()\r\n\t\t\tprivate csrfTokens \t\t= new Map<string, { sessionId: string; expires: number }>()\r\n\t\t\tprivate requestLog\t\t= new Map<string, any>()\r\n\r\n\t\t\tprivate readonly MAX_REQUEST_LOG_SIZE = 1000\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── MAIN ──────────────────────────────┐\r\n\r\n\t\t\t// Rate Limiting with proper overflow handling\r\n\t\t\tcheckRateLimit(key: string, max: number, windowMs: number): boolean {\r\n\t\t\tconst now = Date.now()\r\n\t\t\tconst record = this.rateLimitStore.get(key)\r\n\r\n\t\t\tif (record) {\r\n\t\t\t\tif (now < record.reset) {\r\n\t\t\t\t// Within the current window\r\n\t\t\t\tif (record.count >= max) {\r\n\t\t\t\t\treturn false // Rate limit exceeded\r\n\t\t\t\t}\r\n\t\t\t\trecord.count++\r\n\t\t\t\treturn true\r\n\t\t\t\t} else {\r\n\t\t\t\t// Window expired, reset\r\n\t\t\t\tthis.rateLimitStore.set(key, { count: 1, reset: now + windowMs })\r\n\t\t\t\treturn true\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\t// First request for this key\r\n\t\t\t\tthis.rateLimitStore.set(key, { count: 1, reset: now + windowMs })\r\n\t\t\t\treturn true\r\n\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Cleanup old rate limit records\r\n\t\t\tcleanupRateLimit() {\r\n\t\t\tconst now = Date.now()\r\n\t\t\tfor (const [key, record] of this.rateLimitStore.entries()) {\r\n\t\t\t\tif (now > record.reset) {\r\n\t\t\t\tthis.rateLimitStore.delete(key)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// CSRF Token Generation with TTL\r\n\t\t\tgenerateCsrfToken(sessionId: string, ttl = 3600000): string {\r\n\t\t\tconst token = crypto.randomBytes(32).toString('hex')\r\n\t\t\tthis.csrfTokens.set(token, {\r\n\t\t\t\tsessionId,\r\n\t\t\t\texpires: Date.now() + ttl\r\n\t\t\t})\r\n\t\t\treturn token\r\n\t\t\t}\r\n\r\n\t\t\t// Validate CSRF Token with expiration check\r\n\t\t\tvalidateCsrfToken(token: string, sessionId: string): boolean {\r\n\t\t\tconst stored = this.csrfTokens.get(token)\r\n\r\n\t\t\tif (!stored) {\r\n\t\t\t\treturn false\r\n\t\t\t}\r\n\r\n\t\t\t// Check if token has expired\r\n\t\t\tif (Date.now() > stored.expires) {\r\n\t\t\t\tthis.csrfTokens.delete(token)\r\n\t\t\t\treturn false\r\n\t\t\t}\r\n\r\n\t\t\t// Validate session ID\r\n\t\t\tif (stored.sessionId === sessionId) {\r\n\t\t\t\tthis.csrfTokens.delete(token) // One-time use\r\n\t\t\t\treturn true\r\n\t\t\t}\r\n\r\n\t\t\treturn false\r\n\t\t\t}\r\n\r\n\t\t\t// Cleanup expired CSRF tokens\r\n\t\t\tcleanupCsrfTokens() {\r\n\t\t\tconst now = Date.now()\r\n\t\t\tfor (const [token, data] of this.csrfTokens.entries()) {\r\n\t\t\t\tif (now > data.expires) {\r\n\t\t\t\tthis.csrfTokens.delete(token)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// HTML Sanitization - comprehensive\r\n\t\t\tsanitizeHtml(html: string): string {\r\n\t\t\tif (!html) return ''\r\n\r\n\t\t\treturn html\r\n\t\t\t\t.replace(/&/g, '&')\r\n\t\t\t\t.replace(/</g, '<')\r\n\t\t\t\t.replace(/>/g, '>')\r\n\t\t\t\t.replace(/\"/g, '"')\r\n\t\t\t\t.replace(/'/g, ''')\r\n\t\t\t\t.replace(/\\//g, '/')\r\n\t\t\t}\r\n\r\n\t\t\t// SQL Injection Prevention\r\n\t\t\tsanitizeSql(input: string): string {\r\n\t\t\tif (!input) return ''\r\n\r\n\t\t\treturn input\r\n\t\t\t\t.replace(/\\\\/g, '\\\\\\\\') // Escape backslashes first\r\n\t\t\t\t.replace(/;/g, '') // Remove semicolons to prevent multi-statement injection\r\n\t\t\t\t.replace(/'/g, \"''\") // Escape single quotes (SQL standard)\r\n\t\t\t\t.replace(/\"/g, '\\\\\"') // Escape double quotes\r\n\t\t\t\t.replace(/\\x00/g, '') // Remove null bytes\r\n\t\t\t}\r\n\r\n\t\t\t// Log request for audit trail with size limit\r\n\t\t\tlogRequest(\r\n\t\t\tid: string,\r\n\t\t\tmethod: string,\r\n\t\t\tpath: string,\r\n\t\t\tip: string,\r\n\t\t\tstatus: number,\r\n\t\t\tduration: number\r\n\t\t\t) {\r\n\t\t\tthis.requestLog.set(id, {\r\n\t\t\t\ttimestamp: new Date().toISOString(),\r\n\t\t\t\tmethod,\r\n\t\t\t\tpath,\r\n\t\t\t\tip,\r\n\t\t\t\tstatus,\r\n\t\t\t\tduration\r\n\t\t\t})\r\n\r\n\t\t\t// Keep only last MAX_REQUEST_LOG_SIZE requests\r\n\t\t\tif (this.requestLog.size > this.MAX_REQUEST_LOG_SIZE) {\r\n\t\t\t\tconst { value: first } = this.requestLog.keys().next() || { value: null }\r\n\t\t\t\tif (first) {\r\n\t\t\t\tthis.requestLog.delete(first)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// Get request log by ID\r\n\t\t\tgetRequestLog(id: string) {\r\n\t\t\treturn this.requestLog.get(id)\r\n\t\t\t}\r\n\r\n\t\t\t// Get all request logs\r\n\t\t\tgetAllRequestLogs() {\r\n\t\t\treturn Array.from(this.requestLog.values())\r\n\t\t\t}\r\n\r\n\t\t\t// Clear all\r\n\t\t\tclearAll() {\r\n\t\t\tthis.rateLimitStore.clear()\r\n\t\t\tthis.csrfTokens.clear()\r\n\t\t\tthis.requestLog.clear()\r\n\t\t\t}\r\n\r\n\t\t\t// Get stats\r\n\t\t\tgetStats() {\r\n\t\t\t\treturn {\r\n\t\t\t\t\trateLimitEntries: this.rateLimitStore.size,\r\n\t\t\t\t\tcsrfTokens: this.csrfTokens.size,\r\n\t\t\t\t\trequestLogs: this.requestLog.size\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── HELP ──────────────────────────────┐\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n","// lib/logger.ts\r\n//\r\n// Developed with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n\texport class Logger {\r\n\r\n // ┌──────────────────────────────── INIT ──────────────────────────────┐\r\n\r\n\t\t\tprivate level\t: number \t= 1\r\n\t\t\tprivate pretty\t: boolean \t= false\r\n\t\t\tprivate levels\t\t\t\t= { debug: 0, info: 1, warn: 2, error: 3, fatal: 4 }\r\n\r\n\t\t\tconstructor(level: 'debug' | 'info' | 'warn' | 'error' = 'info', pretty = false) {\r\n\t\t\t\tthis.level \t= this.levels[level] ?? 1\r\n\t\t\t\tthis.pretty = pretty\r\n\t\t\t}\r\n\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── MAIN ──────────────────────────────┐\r\n\r\n\t\t\tdebug(data: any, msg?: string) {\r\n\t\t\t\tthis.log('debug', this.levels.debug, data, msg)\r\n\t\t\t}\r\n\r\n\t\t\tinfo(data: any, msg?: string) {\r\n\t\t\t\tthis.log('info', this.levels.info, data, msg)\r\n\t\t\t}\r\n\r\n\t\t\twarn(data: any, msg?: string) {\r\n\t\t\t\tthis.log('warn', this.levels.warn, data, msg)\r\n\t\t\t}\r\n\r\n\t\t\terror(data: any, msg?: string) {\r\n\t\t\t\tthis.log('error', this.levels.error, data, msg)\r\n\t\t\t}\r\n\r\n\t\t\tfatal(data: any, msg?: string) {\r\n\t\t\t\tthis.log('fatal', this.levels.fatal, data, msg)\r\n\t\t\t\t// Fatal errors might need additional handling in production\r\n\t\t\t\tif (process.env.NODE_ENV === 'production') {\r\n\t\t\t\t\t// Could send to external logging service here\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── HELP ──────────────────────────────┐\r\n\r\n\t\t\tprivate log(level: string, levelNum: number, data: any, msg?: string) {\r\n\t\t\t\tif (levelNum < this.level) return\r\n\r\n\t\t\t\tconst ts = new Date().toISOString()\r\n\r\n\t\t\t\t// Handle null/undefined data gracefully\r\n\t\t\t\tconst safeData = data ?? {}\r\n\r\n\t\t\t\tconst output = {\r\n\t\t\t\t\ttimestamp\t: ts,\r\n\t\t\t\t\tlevel\t\t: level.toUpperCase(),\r\n\t\t\t\t\tmessage\t\t: msg || 'No message',\r\n\t\t\t\t\t...safeData\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst str = this.pretty\r\n\t\t\t\t? `[${ts}] ${level.toUpperCase()} ${msg || 'No message'}\\n${JSON.stringify(safeData, null, 2)}`\r\n\t\t\t\t: JSON.stringify(output)\r\n\r\n\t\t\t\tif (level === 'error' || level === 'fatal') {\r\n\t\t\t\t\tconsole.error(str)\r\n\t\t\t\t} else if (level === 'warn') {\r\n\t\t\t\t\tconsole.warn(str)\r\n\t\t\t\t} else {\r\n\t\t\t\t\tconsole.log(str)\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\t}\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n","// src/types.d.ts\r\n//\r\n// Developed with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ TYPE ════════════════════════════════════════╗\r\n\r\n export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS' | 'HEAD'\r\n export type RouteHandler = (c: AppContext) => any | Promise<any>\r\n export type AppMiddleware = (c: AppContext, next: () => Promise<void>) => void | Promise<void>\r\n\r\n export interface AppContext {\r\n request : Request\r\n params : Record<string, string>\r\n query : Record<string, any>\r\n body : any\r\n headers : Headers\r\n db : any\r\n logger : Logger | null\r\n user? : any\r\n requestId : string\r\n\r\n // Response methods\r\n json (data: any, status?: number): Response\r\n text (data: string, status?: number): Response\r\n html (data: string, status?: number): Response\r\n redirect (url: string, status?: number): Response\r\n file (path: string, contentType?: string): Response\r\n\r\n // Cookie methods\r\n setCookie (name: string, value: string, options?: CookieOptions): AppContext\r\n getCookie (name: string): string | undefined\r\n deleteCookie (name: string, options?: Partial<CookieOptions>): AppContext\r\n\r\n // Header methods\r\n setHeader(key: string, value: string): AppContext\r\n getHeader(key: string): string | undefined\r\n\r\n // Status code\r\n status(code: number): AppContext\r\n statusCode: number\r\n }\r\n\r\n export interface CookieOptions {\r\n maxAge? : number\r\n expires? : Date\r\n path? : string\r\n domain? : string\r\n secure? : boolean\r\n httpOnly? : boolean\r\n sameSite? : 'Strict' | 'Lax' | 'None'\r\n }\r\n\r\n export interface RouteDefinition {\r\n method : HttpMethod | HttpMethod[]\r\n path : string\r\n handler : RouteHandler\r\n validate? : { body?: any, query?: any, params?: any }\r\n middlewares? : AppMiddleware[]\r\n timeout? : number\r\n rateLimit? : { max: number; windowMs: number }\r\n cache? : number\r\n tags? : string[]\r\n }\r\n\r\n export interface DatabaseConfig {\r\n type? : 'bun-sql' // default\r\n name? : string\r\n connection : string | any\r\n schema? : any\r\n poolSize? : number\r\n timeout? : number\r\n }\r\n\r\n export interface SecurityConfig {\r\n cors? : boolean | CorsConfig\r\n rateLimit? : boolean | RateLimitConfig\r\n csrf? : boolean | CsrfConfig\r\n helmet? : boolean | HelmetConfig\r\n auth? : boolean | AuthConfig\r\n validation? : boolean\r\n sanitize? : boolean\r\n }\r\n\r\n export interface CorsConfig {\r\n origin? : string | string[] | ((origin: string) => boolean)\r\n methods? : HttpMethod[]\r\n allowedHeaders? : string[]\r\n credentials? : boolean\r\n maxAge? : number\r\n }\r\n\r\n export interface RateLimitConfig {\r\n windowMs? : number\r\n max? : number\r\n keyGenerator? : (c: AppContext) => string\r\n message? : string\r\n }\r\n\r\n export interface CsrfConfig {\r\n secret? : string\r\n headerName? : string\r\n tokenTTL? : number\r\n }\r\n\r\n export interface HelmetConfig {\r\n contentSecurityPolicy? : Record<string, string[]> | boolean\r\n hsts? : boolean | { maxAge?: number; includeSubDomains?: boolean; preload?: boolean }\r\n frameguard? : boolean | { action: 'deny' | 'sameorigin' }\r\n noSniff? : boolean\r\n xssFilter? : boolean\r\n referrerPolicy? : string | boolean\r\n }\r\n\r\n export interface AuthConfig {\r\n jwt? : boolean | { secret: string; expiresIn?: string }\r\n apiKey? : boolean | { header?: string }\r\n bearer? : boolean\r\n }\r\n\r\n export interface ServerConfig {\r\n port? : number\r\n hostname? : string\r\n requestTimeout? : number\r\n maxRequestSize? : number\r\n maxJsonSize? : number\r\n\r\n database? : DatabaseConfig | DatabaseConfig[]\r\n\r\n security? : boolean | SecurityConfig\r\n\r\n compression? : boolean | { threshold?: number }\r\n\r\n logging? : boolean | { level?: 'debug' | 'info' | 'warn' | 'error'; pretty?: boolean }\r\n\r\n routes? : RouteDefinition[]\r\n middlewares? : AppMiddleware[]\r\n\r\n errorHandler? : (error: Error, context: AppContext) => void | Promise<void>\r\n onShutdown? : () => void | Promise<void>\r\n\r\n apiPrefix? : string\r\n apiVersion? : string\r\n\r\n gracefulShutdownTimeout?: number\r\n }\r\n\r\n export interface ServerInstance {\r\n app : any\r\n logger : Logger | null\r\n db : Map<string, any>\r\n bunServer : any\r\n start : () => Promise<void>\r\n stop : () => Promise<void>\r\n addRoute : (route: RouteDefinition) => void\r\n getRoutes : () => RouteDefinition[]\r\n }\r\n\r\n export interface Logger {\r\n debug (data: any, msg?: string): void\r\n info (data: any, msg?: string): void\r\n warn (data: any, msg?: string): void\r\n error (data: any, msg?: string): void\r\n fatal (data: any, msg?: string): void\r\n }\r\n\r\n export class AppError extends Error {\r\n constructor(public message: string, public statusCode: number = 500, public code?: string) {\r\n super(message)\r\n this.name = 'AppError'\r\n }\r\n }\r\n\r\n export class ValidationError extends AppError {\r\n constructor(message: string, public issues?: any) {\r\n super(message, 400, 'VALIDATION_ERROR')\r\n this.name = 'ValidationError'\r\n }\r\n }\r\n\r\n export class DatabaseError extends AppError {\r\n constructor(message: string) {\r\n super(message, 500, 'DATABASE_ERROR')\r\n this.name = 'DatabaseError'\r\n }\r\n }\r\n\r\n export class TimeoutError extends AppError {\r\n constructor(message = 'Request timeout') {\r\n super(message, 408, 'TIMEOUT_ERROR')\r\n this.name = 'TimeoutError'\r\n }\r\n }\r\n\r\n export class RateLimitError extends AppError {\r\n constructor(message = 'Too many requests') {\r\n super(message, 429, 'RATE_LIMIT_ERROR')\r\n this.name = 'RateLimitError'\r\n }\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝","// main.ts\n//\n// Developed with ❤️ by Maysara.\n\n\n\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\n\n import { drizzle } from 'drizzle-orm/bun-sql'\n import { Router } from './mod/router'\n import { SecurityManager } from './mod/security'\n import { Logger } \tfrom './mod/logger'\n import * as types from './types.d'\n\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\n\n\n\n// ╔════════════════════════════════════════ INIT ════════════════════════════════════════╗\n\n const security = new SecurityManager()\n const router = new Router()\n\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\n\n\n\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\n\n export function server(config: types.ServerConfig = {}): types.ServerInstance {\n\n\t\t// ════════ Configuration ════════\n\t\tconst port = config.port || 3000\n\t\tconst hostname = config.hostname || 'localhost'\n\t\tconst maxReqSize = config.maxRequestSize || 10 * 1024 * 1024\n\t\tconst requestTimeout = config.requestTimeout || 30000\n\t\tconst gracefulShutdownTimeout = config.gracefulShutdownTimeout || 10000\n\n\t\tconst logCfg = typeof config.logging === 'object' ? config.logging : {}\n\t\tconst logger = config.logging ? new Logger(logCfg.level || 'info', logCfg.pretty) : null\n\n\t\tconst dbs = new Map<string, any>()\n\t\tconst routes: types.RouteDefinition[] = []\n\t\tconst activeRequests = new Set<string>()\n\n\t\t// ════════ Cleanup intervals ════════\n const cleanupInterval = setInterval(() => {\n security.cleanupRateLimit()\n security.cleanupCsrfTokens()\n }, 2 * 60 * 1000)\n\n async function handleRequest(request: Request): Promise<Response> {\n const startTime = Date.now()\n const requestId = crypto.randomUUID()\n const url = new URL(request.url)\n const path = url.pathname\n const method = request.method.toUpperCase()\n const ip = getClientIp(request)\n\n activeRequests.add(requestId)\n\n try {\n // Check request size from header\n const contentLength = request.headers.get('content-length')\n if (contentLength && parseInt(contentLength) > maxReqSize) {\n\n logger?.warn({ requestId, size: contentLength, ip }, 'Request too large')\n\n return new Response(JSON.stringify({ error: 'Payload too large' }), {\n\t\t\t\t\t\tstatus\t: 413,\n\t\t\t\t\t\theaders\t: { 'Content-Type': 'application/json' }\n })\n }\n\n // CORS handling\n const corsHeaders = handleCors(request, config)\n if (method === 'OPTIONS') {\n return new Response(null, { status: 204, headers: corsHeaders })\n }\n\n // Rate limiting\n if (config.security && typeof config.security === 'object' && config.security.rateLimit) {\n const rateLimitCfg = typeof config.security.rateLimit === 'object'\n ? config.security.rateLimit\n : {}\n const max = rateLimitCfg.max || 100\n const windowMs = rateLimitCfg.windowMs || 60000\n const rateLimitKey = rateLimitCfg.keyGenerator\n ? rateLimitCfg.keyGenerator({ request, ip } as any)\n : ip\n\n if (!security.checkRateLimit(rateLimitKey, max, windowMs)) {\n logger?.warn({ requestId, ip, key: rateLimitKey }, 'Rate limit exceeded')\n return new Response(\n JSON.stringify({ error: rateLimitCfg.message || 'Too many requests' }),\n { status: 429, headers: { 'Content-Type': 'application/json' } }\n )\n }\n }\n\n // Parse body\n let body: any = null\n if (['POST', 'PUT', 'PATCH'].includes(method)) {\n body = await parseBody(request, logger, maxReqSize)\n }\n\n // Get database\n const defaultDb = dbs.get('default')\n\n // Match route\n const routeMatch = router.match(method, path)\n if (!routeMatch) {\n const ctx = createAppContext(request, {}, defaultDb, logger, requestId)\n logger?.warn({ requestId, method, path, ip }, 'Route not found')\n return ctx.json({ error: 'Not Found', path }, 404)\n }\n\n const ctx = createAppContext(request, routeMatch.params || {}, defaultDb, logger, requestId)\n ctx.body = body\n ctx.request = request\n\n // Execute route handler with timeout\n const controller = new AbortController()\n const timeoutPromise = new Promise<never>((_, reject) => {\n const id = setTimeout(() => {\n controller.abort()\n reject(new types.TimeoutError('Request timeout'))\n }, requestTimeout)\n controller.signal.addEventListener('abort', () => clearTimeout(id))\n })\n\n const response = await Promise.race([\n routeMatch.handler(ctx),\n timeoutPromise\n ]) as Response\n\n // Merge CORS and security headers\n const resHeaders = new Headers(response.headers)\n corsHeaders.forEach((value, key) => {\n if (!resHeaders.has(key)) resHeaders.set(key, value)\n })\n\n resHeaders.set('X-Request-ID', requestId)\n resHeaders.set('X-Content-Type-Options', 'nosniff')\n resHeaders.set('X-Frame-Options', 'DENY')\n resHeaders.set('X-XSS-Protection', '1; mode=block')\n resHeaders.set('Referrer-Policy', 'strict-origin-when-cross-origin')\n\n // Audit log\n const duration = Date.now() - startTime\n security.logRequest(requestId, method, path, ip, response.status, duration)\n logger?.info({\n requestId,\n method,\n path,\n status: response.status,\n duration,\n ip\n }, 'Request completed')\n\n return new Response(response.body, {\n status: response.status,\n headers: resHeaders\n })\n } catch (error) {\n if (error instanceof types.AppError) {\n logger?.warn({ error: error.message, requestId, ip }, `App error: ${error.message}`)\n return new Response(\n JSON.stringify({\n error\t: error.message,\n code\t: error.code,\n requestId\n }),\n { status: error.statusCode, headers: { 'Content-Type': 'application/json' } }\n )\n }\n\n logger?.error({ error: String(error), requestId, ip }, 'Unhandled error')\n\n const errorMessage = process.env.NODE_ENV === 'production'\n ? 'Internal Server Error'\n : (error as Error).message\n\n return new Response(\n JSON.stringify({ error: errorMessage, requestId }),\n { status: 500, headers: { 'Content-Type': 'application/json' } }\n )\n } finally {\n activeRequests.delete(requestId)\n }\n }\n\n // ════════ Health & Readiness routes ════════\n const healthRoute: types.RouteDefinition = {\n method : 'GET',\n path : '/health',\n handler : (c: types.AppContext) => c.json({\n status : 'healthy',\n timestamp : new Date().toISOString(),\n uptime : process.uptime(),\n activeRequests : activeRequests.size\n })\n }\n\n const readinessRoute: types.RouteDefinition = {\n method : 'GET',\n path : '/readiness',\n handler : (c: types.AppContext) => {\n const dbConnected = dbs.size > 0\n const ready = dbConnected || dbs.size === 0\n return c.json({\n ready,\n checks : {\n database : dbConnected ? 'connected' : 'not configured',\n activeRequests : activeRequests.size\n },\n timestamp: new Date().toISOString()\n }, ready ? 200 : 503)\n }\n }\n\n // ════════ Register routes ════════\n if (config.routes) {\n config.routes.forEach(route => {\n routes.push(route)\n const methods = Array.isArray(route.method) ? route.method : [route.method]\n methods.forEach(m => {\n router.register(m, route.path, route.handler, route)\n })\n })\n }\n\n routes.push(healthRoute, readinessRoute)\n router.register('GET', '/health', healthRoute.handler, healthRoute)\n router.register('GET', '/readiness', readinessRoute.handler, readinessRoute)\n\n let bunServer: any = null\n\n const instance: types.ServerInstance = {\n app : null,\n logger,\n db : dbs,\n bunServer : null,\n\n async start() {\n // Initialize databases with Bun SQL support\n if (config.database) {\n const dbConfigs = Array.isArray(config.database) ? config.database : [config.database]\n for (const dbCfg of dbConfigs) {\n const dbName = dbCfg.name || 'default'\n\n try {\n // fallback to bun-sql\n if(!dbCfg.type) { dbCfg.type = 'bun-sql' }\n\n if (dbCfg.type === 'bun-sql') {\n // Bun's native SQL database\n if (typeof dbCfg.connection === 'string') {\n // Create Drizzle instance directly with connection string\n const db = drizzle(dbCfg.connection, { schema: dbCfg.schema })\n dbs.set(dbName, db)\n\n logger?.info({\n name: dbName,\n connection: 'string'\n }, '✅ Bun SQL connected')\n } else if (typeof dbCfg.connection === 'function') {\n // SQL is actually a function in Bun, not a class\n // Pass the SQL function directly to Drizzle\n const db = drizzle({\n client: dbCfg.connection,\n schema: dbCfg.schema\n })\n dbs.set(dbName, db)\n\n logger?.info({\n name: dbName,\n connection: 'function'\n }, '✅ Bun SQL connected')\n } else if (dbCfg.connection !== null && dbCfg.connection !== undefined && typeof dbCfg.connection === 'object') {\n // Also support object connections\n const db = drizzle({\n client: dbCfg.connection,\n schema: dbCfg.schema\n })\n dbs.set(dbName, db)\n\n logger?.info({\n name: dbName,\n connection: 'object'\n }, '✅ Bun SQL connected')\n } else {\n // Better error message with actual type\n const actualType = typeof dbCfg.connection\n throw new Error(`Bun SQL connection must be a connection string, SQL function, or SQL instance (got ${actualType})`)\n }\n } else {\n throw new Error(`Unsupported database type: ${dbCfg.type}`)\n }\n } catch (error) {\n logger?.error({\n error: String(error),\n name: dbName,\n type: dbCfg.type\n }, 'Failed to connect to database')\n throw error\n }\n }\n }\n\n bunServer = Bun.serve({ port, hostname, fetch: handleRequest })\n instance.bunServer = bunServer\n\n const url = `http://${hostname}:${port}`\n console.log(\n `→ URL: ${url}` + `\\n` +\n `→ Environment: ${(process.env.NODE_ENV || 'development')}` + `\\n` +\n `→ Routes: ${routes.length.toString()}` + `\\n` +\n `→ Database: ${(dbs.size > 0 ? '✅ Connected' : '❌ None')}` + `\\n` +\n `→ Security: ${(config.security ? '✅ ENABLED' : '❌ Disabled')}` + `\\n` +\n `\\n` +\n `🔍 Health: ${url}/health` + `\\n` +\n `🔍 Ready: ${url}/readiness`+ `\\n`\n )\n\n logger?.info({ url }, 'Server started')\n },\n\n async stop() {\n logger?.info('Stopping server...')\n\n // Wait for active requests to complete\n if (activeRequests.size > 0) {\n logger?.info({ count: activeRequests.size }, 'Waiting for active requests...')\n const deadline = Date.now() + gracefulShutdownTimeout\n\n while (activeRequests.size > 0 && Date.now() < deadline) {\n await new Promise(resolve => setTimeout(resolve, 100))\n }\n\n if (activeRequests.size > 0) {\n logger?.warn({ count: activeRequests.size }, 'Force closing with active requests')\n }\n }\n\n clearInterval(cleanupInterval)\n\n if (config.onShutdown) {\n try {\n await config.onShutdown()\n } catch (e) {\n logger?.error({ error: String(e) }, 'Error in shutdown handler')\n }\n }\n\n // Close database connections\n for (const [name, db] of dbs.entries()) {\n try {\n if (db?.$client?.close) {\n db.$client.close()\n }\n logger?.info({ name }, 'Database closed')\n } catch (e) {\n logger?.error({ error: String(e), name }, 'Error closing database')\n }\n }\n\n if (bunServer) {\n bunServer.stop()\n logger?.info('Bun server stopped')\n }\n\n logger?.info('Server stopped successfully')\n },\n\n addRoute(route: types.RouteDefinition) {\n routes.push(route)\n const methods = Array.isArray(route.method) ? route.method : [route.method]\n methods.forEach(m => {\n router.register(m, route.path, route.handler, route)\n })\n logger?.info({ method: route.method, path: route.path }, 'Route added')\n },\n\n getRoutes() {\n return routes\n }\n }\n\n return instance\n\t}\n\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\n\n\n\n// ╔════════════════════════════════════════ HELP ════════════════════════════════════════╗\n\n // Better body parsing with size validation\n async function parseBody(\n request : Request,\n logger : Logger | null,\n maxSize : number\n ): Promise<any> {\n const contentType = request.headers.get('content-type') || ''\n\n try {\n if (contentType.includes('application/json')) {\n\t\t\t\tconst text = await request.text()\n\n\t\t\t\t// Validate size after reading\n\t\t\t\tif (text.length > maxSize) {\n\t\t\t\t\tthrow new types.ValidationError('Payload too large')\n\t\t\t\t}\n\n\t\t\t\tif (!text.trim()) return {}\n\n\t\t\t\ttry {\n\t\t\t\t\treturn JSON.parse(text)\n\t\t\t\t} catch (e) {\n\t\t\t\t\tlogger?.warn({\n\t\t\t\t\t\terror\t\t: String(e),\n\t\t\t\t\t\tbodyPreview\t: text.substring(0, 100)\n\t\t\t\t\t}, 'Invalid JSON in request body')\n\n\t\t\t\t\tthrow new types.ValidationError('Invalid JSON in request body')\n\t\t\t\t}\n }\n\n if (contentType.includes('application/x-www-form-urlencoded')) {\n const text = await request.text()\n if (text.length > maxSize) {\n throw new types.ValidationError('Payload too large')\n }\n\n return Object.fromEntries(new URLSearchParams(text))\n }\n\n if (contentType.includes('multipart/form-data')) {\n // Note: FormData size can't be validated before parsing\n return await request.formData()\n }\n\n } catch (e) {\n if (e instanceof types.ValidationError) throw e\n logger?.error({ error: String(e) }, 'Error parsing request body')\n throw new types.ValidationError('Failed to parse request body')\n }\n\n return {}\n }\n\n // Better cookie parsing\n function parseCookies(cookieHeader: string): Map<string, string> {\n const cookies = new Map<string, string>()\n\n if (!cookieHeader) return cookies\n\n const pairs = cookieHeader.split(';')\n for (const pair of pairs) {\n const [key, ...valueParts] = pair.trim().split('=')\n if (key) {\n const value = valueParts.join('=') // Handle '=' in value\n cookies.set(key, value ? decodeURIComponent(value) : '')\n }\n }\n\n return cookies\n }\n\n // Create app context with request ID\n function createAppContext(\n request : Request,\n params : Record<string, string>,\n db : any,\n logger : Logger | null,\n requestId : string\n ): types.AppContext {\n const url = new URL(request.url)\n const query = Object.fromEntries(url.searchParams)\n const headers = request.headers\n let statusCode = 200\n const cookieStore = new Map<string, string>()\n const parsedCookies = parseCookies(headers.get('cookie') || '')\n\n const ctx: any = {\n request,\n params,\n query,\n headers,\n db,\n logger,\n requestId,\n get statusCode() { return statusCode },\n set statusCode(code: number) { statusCode = code },\n body: null,\n\n json(data: any, status?: number): Response {\n return new Response(JSON.stringify(data), {\n status : status ?? statusCode,\n headers : {\n 'Content-Type': 'application/json',\n ...this._setCookieHeaders()\n }\n })\n },\n\n text(data: string, status?: number): Response {\n return new Response(data, {\n status : status ?? statusCode,\n headers : {\n 'Content-Type': 'text/plain',\n ...this._setCookieHeaders()\n }\n })\n },\n\n html(data: string, status?: number): Response {\n return new Response(data, {\n status : status ?? statusCode,\n headers : {\n 'Content-Type': 'text/html; charset=utf-8',\n ...this._setCookieHeaders()\n }\n })\n },\n\n redirect(url: string, status = 302): Response {\n return new Response(null, {\n status,\n headers : {\n Location : url,\n ...this._setCookieHeaders()\n }\n })\n },\n\n file(path: string, contentType = 'application/octet-stream'): Response {\n const file = Bun.file(path)\n return new Response(file, {\n headers: {\n 'Content-Type': contentType,\n ...this._setCookieHeaders()\n }\n })\n },\n\n setCookie(name: string, value: string, options: types.CookieOptions = {}): types.AppContext {\n let cookie = `${name}=${encodeURIComponent(value)}`\n\n if (options.maxAge !== undefined) {\n cookie += `; Max-Age=${options.maxAge}`\n }\n if (options.expires) {\n cookie += `; Expires=${options.expires.toUTCString()}`\n }\n if (options.path) {\n cookie += `; Path=${options.path}`\n }\n if (options.domain) {\n cookie += `; Domain=${options.domain}`\n }\n if (options.secure) {\n cookie += '; Secure'\n }\n if (options.httpOnly) {\n cookie += '; HttpOnly'\n }\n if (options.sameSite) {\n cookie += `; SameSite=${options.sameSite}`\n }\n\n cookieStore.set(name, cookie)\n return ctx\n },\n\n getCookie(name: string): string | undefined {\n return parsedCookies.get(name)\n },\n\n deleteCookie(name: string, options: Partial<types.CookieOptions> = {}): types.AppContext {\n return ctx.setCookie(name, '', {\n ...options,\n maxAge: 0,\n path: options.path || '/'\n })\n },\n\n setHeader(key: string, value: string): types.AppContext {\n headers.set(key, value)\n return ctx\n },\n\n getHeader(key: string): string | undefined {\n return headers.get(key) || undefined\n },\n\n status(code: number): types.AppContext {\n statusCode = code\n return ctx\n },\n\n _setCookieHeaders(): Record<string, string | string[]> {\n const h: any = {}\n if (cookieStore.size > 0) {\n h['Set-Cookie'] = Array.from(cookieStore.values())\n }\n return h\n }\n }\n\n return ctx\n }\n\n // Better IP extraction\n function getClientIp(request: Request): string {\n const forwarded = request.headers.get('x-forwarded-for')\n\n if (forwarded) {\n const ips = forwarded.split(',').map(ip => ip.trim())\n return ips[0] || 'unknown'\n }\n\n const realIp = request.headers.get('x-real-ip')\n if (realIp) return realIp\n return 'unknown'\n }\n\n // CORS helper with proper configuration\n function handleCors(request: Request, config: types.ServerConfig): Headers {\n const headers = new Headers()\n\n if (!config.security || typeof config.security !== 'object' || !config.security.cors) {\n return headers\n }\n\n const corsConfig = typeof config.security.cors === 'object' ? config.security.cors : {}\n const origin = request.headers.get('Origin')\n\n if (origin) {\n if (typeof corsConfig.origin === 'function') {\n if (corsConfig.origin(origin)) {\n headers.set('Access-Control-Allow-Origin', origin)\n }\n } else if (Array.isArray(corsConfig.origin)) {\n if (corsConfig.origin.includes(origin)) {\n headers.set('Access-Control-Allow-Origin', origin)\n }\n } else if (typeof corsConfig.origin === 'string') {\n headers.set('Access-Control-Allow-Origin', corsConfig.origin)\n } else {\n headers.set('Access-Control-Allow-Origin', origin)\n }\n\n const methods = corsConfig.methods || ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS']\n headers.set('Access-Control-Allow-Methods', methods.join(', '))\n\n const allowedHeaders = corsConfig.allowedHeaders || ['Content-Type', 'Authorization', 'X-Requested-With']\n headers.set('Access-Control-Allow-Headers', allowedHeaders.join(', '))\n\n if (corsConfig.credentials) {\n headers.set('Access-Control-Allow-Credentials', 'true')\n }\n\n if (corsConfig.maxAge) {\n headers.set('Access-Control-Max-Age', corsConfig.maxAge.toString())\n }\n }\n\n return headers\n }\n\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\n\n\n\n// ╔════════════════════════════════════════ ════ ════════════════════════════════════════╗\n\n // Export all types\n export * from './types.d';\n\n // Export Logger\n export { Logger };\n\n // Export SecurityManager for advanced use cases\n export { SecurityManager };\n\n // Export Router for advanced use cases\n export { Router };\n\n // Default export\n export default server;\n\n // ════════════════════ Drizzle ORM - Bun SQL (SQLite) ════════════════════\n // Re-export Drizzle ORM types for Bun SQL (SQLite)\n export {\n sqliteTable,\n integer,\n text,\n real,\n blob,\n numeric,\n primaryKey,\n uniqueIndex,\n index,\n foreignKey,\n check\n } from 'drizzle-orm/sqlite-core';\n\n // ════════════════════ Drizzle ORM - Common Operators ════════════════════\n // Re-export common Drizzle operators and utilities\n export {\n eq, // Equal\n ne, // Not equal\n and, // AND condition\n or, // OR condition\n not, // NOT condition\n gt, // Greater than\n gte, // Greater than or equal\n lt, // Less than\n lte, // Less than or equal\n like, // LIKE pattern matching\n ilike, // Case-insensitive LIKE\n inArray, // IN array\n notInArray, // NOT IN array\n isNull, // IS NULL\n isNotNull, // IS NOT NULL\n exists, // EXISTS subquery\n notExists, // NOT EXISTS subquery\n between, // BETWEEN range\n notBetween, // NOT BETWEEN range\n sql, // Raw SQL\n asc, // Ascending order\n desc // Descending order\n } from 'drizzle-orm';\n\n // ════════════════════ Drizzle ORM - Relations ════════════════════\n // Re-export relations helpers\n export {\n relations,\n One,\n Many\n } from 'drizzle-orm';\n\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝"]}
|
package/dist/main.d.cts
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
export { blob, check, foreignKey, index, integer, numeric, primaryKey, real, sqliteTable, text, uniqueIndex } from 'drizzle-orm/sqlite-core';
|
|
2
|
+
export { Many, One, and, asc, between, desc, eq, exists, gt, gte, ilike, inArray, isNotNull, isNull, like, lt, lte, ne, not, notBetween, notExists, notInArray, or, relations, sql } from 'drizzle-orm';
|
|
3
|
+
|
|
4
|
+
declare class Router {
|
|
5
|
+
private routes;
|
|
6
|
+
private regexRoutes;
|
|
7
|
+
match(method: string, path: string): {
|
|
8
|
+
handler: any;
|
|
9
|
+
params: Record<string, string>;
|
|
10
|
+
} | null;
|
|
11
|
+
getAll(): {
|
|
12
|
+
method: string;
|
|
13
|
+
path: string;
|
|
14
|
+
handler: any;
|
|
15
|
+
}[];
|
|
16
|
+
clear(): void;
|
|
17
|
+
remove(method: string, path: string): boolean;
|
|
18
|
+
register(method: string, path: string, handler: any, config?: any): void;
|
|
19
|
+
private pathToRegex;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
declare class SecurityManager {
|
|
23
|
+
private rateLimitStore;
|
|
24
|
+
private csrfTokens;
|
|
25
|
+
private requestLog;
|
|
26
|
+
private readonly MAX_REQUEST_LOG_SIZE;
|
|
27
|
+
checkRateLimit(key: string, max: number, windowMs: number): boolean;
|
|
28
|
+
cleanupRateLimit(): void;
|
|
29
|
+
generateCsrfToken(sessionId: string, ttl?: number): string;
|
|
30
|
+
validateCsrfToken(token: string, sessionId: string): boolean;
|
|
31
|
+
cleanupCsrfTokens(): void;
|
|
32
|
+
sanitizeHtml(html: string): string;
|
|
33
|
+
sanitizeSql(input: string): string;
|
|
34
|
+
logRequest(id: string, method: string, path: string, ip: string, status: number, duration: number): void;
|
|
35
|
+
getRequestLog(id: string): any;
|
|
36
|
+
getAllRequestLogs(): any[];
|
|
37
|
+
clearAll(): void;
|
|
38
|
+
getStats(): {
|
|
39
|
+
rateLimitEntries: number;
|
|
40
|
+
csrfTokens: number;
|
|
41
|
+
requestLogs: number;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
declare class Logger$1 {
|
|
46
|
+
private level;
|
|
47
|
+
private pretty;
|
|
48
|
+
private levels;
|
|
49
|
+
constructor(level?: 'debug' | 'info' | 'warn' | 'error', pretty?: boolean);
|
|
50
|
+
debug(data: any, msg?: string): void;
|
|
51
|
+
info(data: any, msg?: string): void;
|
|
52
|
+
warn(data: any, msg?: string): void;
|
|
53
|
+
error(data: any, msg?: string): void;
|
|
54
|
+
fatal(data: any, msg?: string): void;
|
|
55
|
+
private log;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/types.d.ts
|
|
59
|
+
//
|
|
60
|
+
// Developed with ❤️ by Maysara.
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
// ╔════════════════════════════════════════ TYPE ════════════════════════════════════════╗
|
|
65
|
+
|
|
66
|
+
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS' | 'HEAD'
|
|
67
|
+
type RouteHandler = (c: AppContext) => any | Promise<any>
|
|
68
|
+
type AppMiddleware = (c: AppContext, next: () => Promise<void>) => void | Promise<void>
|
|
69
|
+
|
|
70
|
+
interface AppContext {
|
|
71
|
+
request : Request
|
|
72
|
+
params : Record<string, string>
|
|
73
|
+
query : Record<string, any>
|
|
74
|
+
body : any
|
|
75
|
+
headers : Headers
|
|
76
|
+
db : any
|
|
77
|
+
logger : Logger | null
|
|
78
|
+
user? : any
|
|
79
|
+
requestId : string
|
|
80
|
+
|
|
81
|
+
// Response methods
|
|
82
|
+
json (data: any, status?: number): Response
|
|
83
|
+
text (data: string, status?: number): Response
|
|
84
|
+
html (data: string, status?: number): Response
|
|
85
|
+
redirect (url: string, status?: number): Response
|
|
86
|
+
file (path: string, contentType?: string): Response
|
|
87
|
+
|
|
88
|
+
// Cookie methods
|
|
89
|
+
setCookie (name: string, value: string, options?: CookieOptions): AppContext
|
|
90
|
+
getCookie (name: string): string | undefined
|
|
91
|
+
deleteCookie (name: string, options?: Partial<CookieOptions>): AppContext
|
|
92
|
+
|
|
93
|
+
// Header methods
|
|
94
|
+
setHeader(key: string, value: string): AppContext
|
|
95
|
+
getHeader(key: string): string | undefined
|
|
96
|
+
|
|
97
|
+
// Status code
|
|
98
|
+
status(code: number): AppContext
|
|
99
|
+
statusCode: number
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
interface CookieOptions {
|
|
103
|
+
maxAge? : number
|
|
104
|
+
expires? : Date
|
|
105
|
+
path? : string
|
|
106
|
+
domain? : string
|
|
107
|
+
secure? : boolean
|
|
108
|
+
httpOnly? : boolean
|
|
109
|
+
sameSite? : 'Strict' | 'Lax' | 'None'
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
interface RouteDefinition {
|
|
113
|
+
method : HttpMethod | HttpMethod[]
|
|
114
|
+
path : string
|
|
115
|
+
handler : RouteHandler
|
|
116
|
+
validate? : { body?: any, query?: any, params?: any }
|
|
117
|
+
middlewares? : AppMiddleware[]
|
|
118
|
+
timeout? : number
|
|
119
|
+
rateLimit? : { max: number; windowMs: number }
|
|
120
|
+
cache? : number
|
|
121
|
+
tags? : string[]
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
interface DatabaseConfig {
|
|
125
|
+
type? : 'bun-sql' // default
|
|
126
|
+
name? : string
|
|
127
|
+
connection : string | any
|
|
128
|
+
schema? : any
|
|
129
|
+
poolSize? : number
|
|
130
|
+
timeout? : number
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
interface SecurityConfig {
|
|
134
|
+
cors? : boolean | CorsConfig
|
|
135
|
+
rateLimit? : boolean | RateLimitConfig
|
|
136
|
+
csrf? : boolean | CsrfConfig
|
|
137
|
+
helmet? : boolean | HelmetConfig
|
|
138
|
+
auth? : boolean | AuthConfig
|
|
139
|
+
validation? : boolean
|
|
140
|
+
sanitize? : boolean
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
interface CorsConfig {
|
|
144
|
+
origin? : string | string[] | ((origin: string) => boolean)
|
|
145
|
+
methods? : HttpMethod[]
|
|
146
|
+
allowedHeaders? : string[]
|
|
147
|
+
credentials? : boolean
|
|
148
|
+
maxAge? : number
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
interface RateLimitConfig {
|
|
152
|
+
windowMs? : number
|
|
153
|
+
max? : number
|
|
154
|
+
keyGenerator? : (c: AppContext) => string
|
|
155
|
+
message? : string
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
interface CsrfConfig {
|
|
159
|
+
secret? : string
|
|
160
|
+
headerName? : string
|
|
161
|
+
tokenTTL? : number
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
interface HelmetConfig {
|
|
165
|
+
contentSecurityPolicy? : Record<string, string[]> | boolean
|
|
166
|
+
hsts? : boolean | { maxAge?: number; includeSubDomains?: boolean; preload?: boolean }
|
|
167
|
+
frameguard? : boolean | { action: 'deny' | 'sameorigin' }
|
|
168
|
+
noSniff? : boolean
|
|
169
|
+
xssFilter? : boolean
|
|
170
|
+
referrerPolicy? : string | boolean
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
interface AuthConfig {
|
|
174
|
+
jwt? : boolean | { secret: string; expiresIn?: string }
|
|
175
|
+
apiKey? : boolean | { header?: string }
|
|
176
|
+
bearer? : boolean
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
interface ServerConfig {
|
|
180
|
+
port? : number
|
|
181
|
+
hostname? : string
|
|
182
|
+
requestTimeout? : number
|
|
183
|
+
maxRequestSize? : number
|
|
184
|
+
maxJsonSize? : number
|
|
185
|
+
|
|
186
|
+
database? : DatabaseConfig | DatabaseConfig[]
|
|
187
|
+
|
|
188
|
+
security? : boolean | SecurityConfig
|
|
189
|
+
|
|
190
|
+
compression? : boolean | { threshold?: number }
|
|
191
|
+
|
|
192
|
+
logging? : boolean | { level?: 'debug' | 'info' | 'warn' | 'error'; pretty?: boolean }
|
|
193
|
+
|
|
194
|
+
routes? : RouteDefinition[]
|
|
195
|
+
middlewares? : AppMiddleware[]
|
|
196
|
+
|
|
197
|
+
errorHandler? : (error: Error, context: AppContext) => void | Promise<void>
|
|
198
|
+
onShutdown? : () => void | Promise<void>
|
|
199
|
+
|
|
200
|
+
apiPrefix? : string
|
|
201
|
+
apiVersion? : string
|
|
202
|
+
|
|
203
|
+
gracefulShutdownTimeout?: number
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
interface ServerInstance {
|
|
207
|
+
app : any
|
|
208
|
+
logger : Logger | null
|
|
209
|
+
db : Map<string, any>
|
|
210
|
+
bunServer : any
|
|
211
|
+
start : () => Promise<void>
|
|
212
|
+
stop : () => Promise<void>
|
|
213
|
+
addRoute : (route: RouteDefinition) => void
|
|
214
|
+
getRoutes : () => RouteDefinition[]
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
interface Logger {
|
|
218
|
+
debug (data: any, msg?: string): void
|
|
219
|
+
info (data: any, msg?: string): void
|
|
220
|
+
warn (data: any, msg?: string): void
|
|
221
|
+
error (data: any, msg?: string): void
|
|
222
|
+
fatal (data: any, msg?: string): void
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
declare class AppError extends Error {
|
|
226
|
+
constructor(public message: string, public statusCode: number = 500, public code?: string) {
|
|
227
|
+
super(message)
|
|
228
|
+
this.name = 'AppError'
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
declare class ValidationError extends AppError {
|
|
233
|
+
constructor(message: string, public issues?: any) {
|
|
234
|
+
super(message, 400, 'VALIDATION_ERROR')
|
|
235
|
+
this.name = 'ValidationError'
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
declare class DatabaseError extends AppError {
|
|
240
|
+
constructor(message: string) {
|
|
241
|
+
super(message, 500, 'DATABASE_ERROR')
|
|
242
|
+
this.name = 'DatabaseError'
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
declare class TimeoutError extends AppError {
|
|
247
|
+
constructor(message = 'Request timeout') {
|
|
248
|
+
super(message, 408, 'TIMEOUT_ERROR')
|
|
249
|
+
this.name = 'TimeoutError'
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
declare class RateLimitError extends AppError {
|
|
254
|
+
constructor(message = 'Too many requests') {
|
|
255
|
+
super(message, 429, 'RATE_LIMIT_ERROR')
|
|
256
|
+
this.name = 'RateLimitError'
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
declare function server(config?: ServerConfig): ServerInstance;
|
|
261
|
+
|
|
262
|
+
export { type AppContext, AppError, type AppMiddleware, type AuthConfig, type CookieOptions, type CorsConfig, type CsrfConfig, type DatabaseConfig, DatabaseError, type HelmetConfig, type HttpMethod, Logger$1 as Logger, type RateLimitConfig, RateLimitError, type RouteDefinition, type RouteHandler, Router, type SecurityConfig, SecurityManager, type ServerConfig, type ServerInstance, TimeoutError, ValidationError, server as default, server };
|