@minejs/server 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,10 +8,10 @@
8
8
  </div>
9
9
 
10
10
  <div align="center">
11
- <img src="https://img.shields.io/badge/v-0.0.2-black"/>
11
+ <img src="https://img.shields.io/badge/v-0.0.4-black"/>
12
12
  <img src="https://img.shields.io/badge/🔥-@minejs-black"/>
13
13
  <br>
14
- <img src="https://img.shields.io/badge/coverage-94.71%25-brightgreen" alt="Test Coverage" />
14
+ <img src="https://img.shields.io/badge/coverage-98.88%25-brightgreen" alt="Test Coverage" />
15
15
  <img src="https://img.shields.io/github/issues/minejs-org/server?style=flat" alt="Github Repo Issues" />
16
16
  <img src="https://img.shields.io/github/stars/minejs-org/server?style=social" alt="GitHub Repo stars" />
17
17
  </div>
@@ -367,24 +367,37 @@
367
367
  - ### 11. Internationalization (i18n)
368
368
 
369
369
  ```typescript
370
- import { server, type AppContext } from '@minejs/server'
370
+ import { server, type AppContext, setupAuto, setLanguage } from '@minejs/server'
371
371
 
372
372
  const app = server({
373
373
  port: 3000,
374
374
  i18n: {
375
375
  defaultLanguage: 'en',
376
- supportedLanguages: ['en', 'ar', 'fr'],
377
- staticPath: './src/i18n'
376
+ supportedLanguages: ['en', 'ar', 'fr']
377
+ },
378
+
379
+ onStartup: async () => {
380
+ // Auto-setup: Automatically detects server environment and loads from files
381
+ // On server: Reads from ./translations/en.json
382
+ // On browser: Fetches from http://localhost:3000/translations/en.json
383
+ await setupAuto({
384
+ defaultLanguage: 'en',
385
+ supportedLanguages: ['en', 'ar', 'fr'],
386
+ basePath: './translations/',
387
+ fileExtension: 'json'
388
+ })
378
389
  },
390
+
379
391
  routes: [
380
392
  {
381
393
  method: 'GET',
382
394
  path: '/greeting',
383
395
  handler: (c: AppContext) => {
384
396
  const language = c.lang // Detected from query, cookie, or header
397
+ // Use c.i18n?.t() to translate with context
385
398
  return c.json({
386
399
  language,
387
- greeting: 'Hello'
400
+ greeting: c.i18n?.t('greeting') || 'Hello'
388
401
  })
389
402
  }
390
403
  }
@@ -395,6 +408,27 @@
395
408
  // Language detection priority: ?lang query param > lang cookie > Accept-Language header > default
396
409
  ```
397
410
 
411
+ **Translation file structure:**
412
+ ```
413
+ your-app/
414
+ ├── src/
415
+ │ └── index.ts
416
+ ├── translations/
417
+ │ ├── en.json
418
+ │ ├── ar.json
419
+ │ └── fr.json
420
+ └── package.json
421
+ ```
422
+
423
+ **translations/en.json:**
424
+ ```json
425
+ {
426
+ "greeting": "Hello",
427
+ "farewell": "Goodbye",
428
+ "welcome": "Welcome, {name}!"
429
+ }
430
+ ```
431
+
398
432
  - ### 12. Logging
399
433
 
400
434
  ```typescript
package/dist/index.cjs ADDED
@@ -0,0 +1,3 @@
1
+ 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var le=require('@minejs/db'),ge=require('crypto'),path=require('path'),fs=require('fs'),i18n=require('@minejs/i18n');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var le__namespace=/*#__PURE__*/_interopNamespace(le);var ge__default=/*#__PURE__*/_interopDefault(ge);var B=class{constructor(){this.routes=new Map;this.regexRoutes=[];}match(e,t){let n=`${e}:${t}`;if(this.routes.has(n)){let r=this.routes.get(n);return {handler:r.handler,params:{},metadata:r.metadata}}for(let r of this.regexRoutes)if(r.method===e){let i=t.match(r.pattern);if(i){let a=i.groups||{};return {handler:r.handler,params:a,metadata:r.metadata}}}return null}getAll(){let e=Array.from(this.routes.entries()).map(([n,r])=>{let i=n.indexOf(":"),a=n.substring(0,i),l=n.substring(i+1);return {method:a,path:l,handler:r.handler}}),t=this.regexRoutes.map(n=>{let r=n.key.indexOf(":");return {method:n.method,path:n.key.substring(r+1),handler:n.handler}});return [...e,...t]}clear(){this.routes.clear(),this.regexRoutes=[];}remove(e,t){let n=`${e}:${t}`;if(this.routes.has(n))return this.routes.delete(n),true;let r=this.regexRoutes.findIndex(i=>i.key===n);return r>=0?(this.regexRoutes.splice(r,1),true):false}register(e,t,n,r={}){let i=`${e}:${t}`;if(t.includes(":")||t.includes("*")){let a=this.pathToRegex(t),l=this.regexRoutes.findIndex(b=>b.key===i),m={pattern:a,method:e,handler:n,key:i,metadata:r};l>=0?this.regexRoutes[l]=m:this.regexRoutes.push(m);}else this.routes.set(i,{handler:n,metadata:r});}pathToRegex(e){let t=e.replace(/[.+?^${}()|[\]\\]/g,"\\$&");return t=t.replace(/:(\w+)/g,"(?<$1>[^/]+)"),t=t.replace(/\*/g,".*"),new RegExp(`^${t}$`)}};var V=class{constructor(){this.rateLimitStore=new Map;this.csrfTokens=new Map;this.requestLog=new Map;this.MAX_REQUEST_LOG_SIZE=1e3;}checkRateLimit(e,t,n){let r=Date.now(),i=this.rateLimitStore.get(e);return i?r<i.reset?i.count>=t?false:(i.count++,true):(this.rateLimitStore.set(e,{count:1,reset:r+n}),true):(this.rateLimitStore.set(e,{count:1,reset:r+n}),true)}cleanupRateLimit(){let e=Date.now();for(let[t,n]of this.rateLimitStore.entries())e>n.reset&&this.rateLimitStore.delete(t);}generateCsrfToken(e,t=36e5){let n=ge__default.default.randomBytes(32).toString("hex");return this.csrfTokens.set(n,{sessionId:e,expires:Date.now()+t}),n}validateCsrfToken(e,t){let n=this.csrfTokens.get(e);return n?Date.now()>n.expires?(this.csrfTokens.delete(e),false):n.sessionId===t?(this.csrfTokens.delete(e),true):false:false}cleanupCsrfTokens(){let e=Date.now();for(let[t,n]of this.csrfTokens.entries())e>n.expires&&this.csrfTokens.delete(t);}sanitizeHtml(e){return e?e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;").replace(/\//g,"&#x2F;"):""}sanitizeSql(e){return e?e.replace(/\\/g,"\\\\").replace(/;/g,"").replace(/'/g,"''").replace(/"/g,'\\"').replace(/\u0000/g,""):""}logRequest(e,t,n,r,i,a){if(this.requestLog.set(e,{timestamp:new Date().toISOString(),method:t,path:n,ip:r,status:i,duration:a}),this.requestLog.size>this.MAX_REQUEST_LOG_SIZE){let{value:l}=this.requestLog.keys().next()||{value:null};l&&this.requestLog.delete(l);}}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 J=class o{constructor(e="info",t=false,n=""){this.level=1;this.pretty=false;this.prefix="";this.levels={debug:0,info:1,warn:2,error:3,fatal:4};this.colors={reset:"\x1B[0m",gray:"\x1B[90m",cyan:"\x1B[36m",green:"\x1B[32m",yellow:"\x1B[33m",red:"\x1B[31m",magenta:"\x1B[35m",bold:"\x1B[1m"};this.level=this.levels[e]??1,this.pretty=t,this.prefix=n;}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;}child(e){let t=this.prefix?`${this.prefix}:${e}`:e,n=Object.keys(this.levels).find(r=>this.levels[r]===this.level)||"info";return new o(n,this.pretty,t)}log(e,t,n,r){if(t<this.level)return;let i,a;if(typeof n=="string"?(a=n,i={}):(i=n??{},a=r),this.prefix&&a?a=`[${this.prefix}] ${a}`:this.prefix&&(a=`[${this.prefix}]`),this.pretty)this.prettyLog(e,i,a);else {let m={timestamp:new Date().toISOString(),level:e.toUpperCase(),message:a||"No message",...i},b=JSON.stringify(m);e==="error"||e==="fatal"?console.error(b):e==="warn"?console.warn(b):console.log(b);}}prettyLog(e,t,n){let r=this.colors,i=new Date().toLocaleTimeString("en-US",{hour12:false}),a="method"in t&&"path"in t,l=a&&"status"in t&&"duration"in t,m="name"in t,b="url"in t;if(l){let R=this.colorizeMethod(t.method),u=this.colorizeStatus(t.status),g=t.duration?`${t.duration}ms`:"",y=t.path;console.log(`${r.gray}${i}${r.reset} ${R} ${r.bold}${y}${r.reset} ${u} ${r.gray}${g}${r.reset}`);return}if(n==="Route added"&&a){let R=Array.isArray(t.method)?t.method.join("|"):t.method;console.log(`${r.gray}${i}${r.reset} ${r.cyan}\u2192${r.reset} ${r.bold}${R.padEnd(6)}${r.reset} ${t.path}`);return}if(n==="\u2714 Database connected"&&m){console.log(`${r.gray}${i}${r.reset} ${r.green}\u2713${r.reset} Database connected ${r.gray}(${t.name})${r.reset}`);return}if(n==="Server started"&&b){console.log(`${r.gray}${i}${r.reset} ${r.green}\u2713${r.reset} Server started at ${r.cyan}${t.url}${r.reset}`);return}let v=this.getLevelIcon(e),f=this.getLevelColor(e),D=`${r.gray}${i}${r.reset} ${f}${v}${r.reset} `;n&&(D+=`${n} `);let q=Object.keys(t).filter(R=>!["timestamp","level","message"].includes(R));if(q.length>0){let R=q.map(u=>{let g=t[u];return typeof g=="string"||typeof g=="number"?`${r.gray}${u}:${r.reset}${g}`:null}).filter(Boolean);R.length>0&&(D+=r.gray+R.join(" ")+r.reset);}console.log(D);}colorizeMethod(e){let t=this.colors,n=e.toUpperCase();switch(n){case "GET":return `${t.green}${n}${t.reset}`;case "POST":return `${t.cyan}${n}${t.reset}`;case "PUT":return `${t.yellow}${n}${t.reset}`;case "DELETE":return `${t.red}${n}${t.reset}`;case "PATCH":return `${t.magenta}${n}${t.reset}`;default:return `${t.gray}${n}${t.reset}`}}colorizeStatus(e){if(!e)return "";let t=this.colors,n=e.toString();return e>=200&&e<300?`${t.green}${n}${t.reset}`:e>=300&&e<400?`${t.cyan}${n}${t.reset}`:e>=400&&e<500?`${t.yellow}${n}${t.reset}`:e>=500?`${t.red}${n}${t.reset}`:`${t.gray}${n}${t.reset}`}getLevelIcon(e){switch(e){case "debug":return "\u25CF";case "info":return "\u25CF";case "warn":return "\u26A0";case "error":return "\u2716";case "fatal":return "\u2716";default:return "\u25CF"}}getLevelColor(e){let t=this.colors;switch(e){case "debug":return t.gray;case "info":return t.cyan;case "warn":return t.yellow;case "error":return t.red;case "fatal":return t.red+t.bold;default:return t.reset}}};var P=class extends Error{constructor(t,n=500,r){super(t);this.message=t;this.statusCode=n;this.code=r;this.name="AppError";}},I=class extends P{constructor(t,n){super(t,400,"VALIDATION_ERROR");this.issues=n;this.name="ValidationError";}},se=class extends P{constructor(e){super(e,500,"DATABASE_ERROR"),this.name="DatabaseError";}},X=class extends P{constructor(e="Request timeout"){super(e,408,"TIMEOUT_ERROR"),this.name="TimeoutError";}},oe=class extends P{constructor(e="Too many requests"){super(e,429,"RATE_LIMIT_ERROR"),this.name="RateLimitError";}};var O=class{constructor(e){this.fileCache=new Map;this.CACHE_MAX_SIZE=1e3;if(!fs.existsSync(e.directory))throw new Error(`Static directory does not exist: ${e.directory}`);if(!fs.statSync(e.directory).isDirectory())throw new Error(`Static path is not a directory: ${e.directory}`);this.resolvedDir=path.resolve(e.directory),this.config={path:e.path,directory:e.directory,maxAge:e.maxAge??3600,index:e.index??["index.html"],dotfiles:e.dotfiles??"deny",etag:e.etag??true,lastModified:e.lastModified??true,immutable:e.immutable??false,extensions:e.extensions??[],fallthrough:e.fallthrough??false,setHeaders:e.setHeaders};}handler(){return async e=>{let t=e.request.url,r=new URL(t).pathname;r.startsWith(this.config.path)&&(r=r.slice(this.config.path.length));try{r=decodeURIComponent(r);}catch{return e.json({error:"Invalid URL encoding"},400)}if(r.includes("..")||r.includes("\\"))return e.json({error:"Forbidden"},403);if(this.config.dotfiles!=="allow"&&r.split("/").some(l=>l.startsWith(".")))return this.config.dotfiles==="deny"?e.json({error:"Forbidden"},403):this.handleNotFound(e);let i=this.resolveFilePath(r);if(!i)return this.handleNotFound(e);if(!this.isPathSafe(i))return e.json({error:"Forbidden"},403);if(!fs.existsSync(i))return this.handleNotFound(e);let a=fs.statSync(i);return a.isDirectory()?this.serveDirectory(e,i,r):this.serveFile(e,i,a)}}getPathPattern(){return `${this.config.path}/*`}resolveFilePath(e){e.startsWith("/")&&(e=e.slice(1));let t=path.join(this.resolvedDir,e);if(!fs.existsSync(t)&&this.config.extensions.length>0)for(let n of this.config.extensions){let r=`${t}.${n}`;if(fs.existsSync(r))return r}return t}isPathSafe(e){return !path.relative(this.resolvedDir,path.resolve(e)).startsWith("..")&&!path.resolve(e).startsWith("..")}async serveDirectory(e,t,n){for(let r of this.config.index){let i=path.join(t,r);if(fs.existsSync(i)){let a=fs.statSync(i);if(a.isFile())return this.serveFile(e,i,a)}}return this.handleNotFound(e)}async serveFile(e,t,n){let r=e.request.method.toUpperCase();if(r!=="GET"&&r!=="HEAD")return e.json({error:"Method not allowed"},405);let i=t,a=this.fileCache.get(i);if(a&&a.mtime!==n.mtimeMs&&(a=void 0),!a){if(a={etag:this.generateEtag(n),lastModified:new Date(n.mtime),size:n.size,mtime:n.mtimeMs},this.fileCache.size>=this.CACHE_MAX_SIZE){let f=this.fileCache.keys().next().value;f&&this.fileCache.delete(f);}this.fileCache.set(i,a);}let l=e.request.headers.get("if-none-match"),m=e.request.headers.get("if-modified-since");if(this.config.etag&&l===a.etag)return new Response(null,{status:304,headers:this.buildHeaders(t,a)});if(this.config.lastModified&&m){let f=new Date(m);if(a.lastModified<=f)return new Response(null,{status:304,headers:this.buildHeaders(t,a)})}let b=Bun.file(t),v=this.buildHeaders(t,a);return this.config.setHeaders&&this.config.setHeaders(e,t),r==="HEAD"?new Response(null,{status:200,headers:v}):new Response(b,{status:200,headers:v})}buildHeaders(e,t){let n=new Headers,r=this.getMimeType(e);if(n.set("Content-Type",r),n.set("Content-Length",t.size.toString()),this.config.etag&&n.set("ETag",t.etag),this.config.lastModified&&n.set("Last-Modified",t.lastModified.toUTCString()),this.config.maxAge>0){let i=`public, max-age=${this.config.maxAge}`;this.config.immutable&&(i+=", immutable"),n.set("Cache-Control",i);}else n.set("Cache-Control","no-cache");return n.set("Accept-Ranges","bytes"),n}generateEtag(e){return `"${e.size.toString(16)}-${e.mtimeMs.toString(16)}"`}getMimeType(e){let t=path.extname(e).toLowerCase();return be[t]||"application/octet-stream"}handleNotFound(e){return this.config.fallthrough?e.json({error:"Not Found"},404):e.json({error:"Not Found"},404)}clearCache(){this.fileCache.clear();}getCacheStats(){return {entries:this.fileCache.size,maxSize:this.CACHE_MAX_SIZE}}};function ye(o){return new O(o)}var be={".html":"text/html; charset=utf-8",".htm":"text/html; charset=utf-8",".css":"text/css; charset=utf-8",".txt":"text/plain; charset=utf-8",".xml":"text/xml; charset=utf-8",".csv":"text/csv; charset=utf-8",".md":"text/markdown; charset=utf-8",".js":"application/javascript; charset=utf-8",".mjs":"application/javascript; charset=utf-8",".json":"application/json; charset=utf-8",".jsonld":"application/ld+json",".map":"application/json; charset=utf-8",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".svg":"image/svg+xml",".ico":"image/x-icon",".webp":"image/webp",".avif":"image/avif",".bmp":"image/bmp",".tiff":"image/tiff",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".otf":"font/otf",".eot":"application/vnd.ms-fontobject",".mp3":"audio/mpeg",".wav":"audio/wav",".ogg":"audio/ogg",".m4a":"audio/mp4",".aac":"audio/aac",".flac":"audio/flac",".mp4":"video/mp4",".webm":"video/webm",".ogv":"video/ogg",".mov":"video/quicktime",".avi":"video/x-msvideo",".mkv":"video/x-matroska",".pdf":"application/pdf",".doc":"application/msword",".docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document",".xls":"application/vnd.ms-excel",".xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",".ppt":"application/vnd.ms-powerpoint",".pptx":"application/vnd.openxmlformats-officedocument.presentationml.presentation",".zip":"application/zip",".rar":"application/x-rar-compressed",".7z":"application/x-7z-compressed",".tar":"application/x-tar",".gz":"application/gzip",".wasm":"application/wasm",".manifest":"text/cache-manifest",".webmanifest":"application/manifest+json"};var W=new V,k=new B;function xe(o={}){let e=Number(o.port)||3e3,t=o.hostname||"localhost",n=o.maxRequestSize||10*1024*1024,r=o.requestTimeout||3e4,i=o.gracefulShutdownTimeout||1e4,a=typeof o.logging=="object"?o.logging:{},l=o.logging?new J(a.level||"info",a.pretty):null,m=null;o.i18n&&(m=i18n.getI18n());let b=new Map,v=[],f=new Set,D=[],q=setInterval(()=>{W.cleanupRateLimit(),W.cleanupCsrfTokens();},120*1e3);async function R(s,c){let p=Date.now(),d=crypto.randomUUID(),x=new URL(s.url).pathname,E=s.method.toUpperCase(),$=Ce(s,c);f.add(d);try{let C=s.headers.get("content-length");if(C&&parseInt(C)>n)return l?.warn({requestId:d,size:C,ip:$},"Request too large"),new Response(JSON.stringify({error:"Payload too large"}),{status:413,headers:{"Content-Type":"application/json"}});let j=ve(s,o);if(E==="OPTIONS")return new Response(null,{status:204,headers:j});if(o.security&&typeof o.security=="object"&&o.security.rateLimit){let L=typeof o.security.rateLimit=="object"?o.security.rateLimit:{},H=L.max||100,Z=L.windowMs||6e4,ne=L.keyGenerator?L.keyGenerator({request:s,ip:$}):$;if(!W.checkRateLimit(ne,H,Z))return l?.warn({requestId:d,ip:$,key:ne},"Rate limit exceeded"),new Response(JSON.stringify({error:L.message||"Too many requests"}),{status:429,headers:{"Content-Type":"application/json"}})}let w=null;["POST","PUT","PATCH"].includes(E)&&(w=await Re(s,l,n));let T=b.get("default"),A=Object.fromEntries(new URL(s.url).searchParams),ue=s.headers.get("cookie")||"",de=ce(ue).get("lang"),z=A.lang||de||s.headers.get("Accept-Language")?.split(",")[0]?.split("-")[0]||"en";m&&!m.getSupportedLanguages().includes(z)&&(z=m.getLanguage()),m&&m.setLanguage(z);let N=k.match(E,x);if(!N){let L=ae($,s,{},T,l,d,m,z);if(l?.warn({requestId:d,method:E,path:x,ip:$},"Route not found"),o.onError)try{return await o.onError(404,x,E)}catch(H){l?.error({error:String(H),requestId:d},"Error in onError handler");}return L.json({error:"Not Found",path:x},404)}let G=ae($,s,N.params||{},T,l,d,m,z);G.body=w,G.request=s;let ee=new AbortController,pe=new Promise((L,H)=>{let Z=setTimeout(()=>{ee.abort(),H(new X("Request timeout"));},r);ee.signal.addEventListener("abort",()=>clearTimeout(Z));}),te=N.metadata?.middlewares||[],K;te.length>0?K=u(G,te,N.handler):K=Promise.resolve(N.handler(G));let F=await Promise.race([K,pe]),M=new Headers(F.headers);j.forEach((L,H)=>{M.has(H)||M.set(H,L);}),M.set("X-Request-ID",d),M.set("X-Content-Type-Options","nosniff"),M.set("X-Frame-Options","DENY"),M.set("X-XSS-Protection","1; mode=block"),M.set("Referrer-Policy","strict-origin-when-cross-origin");let re=Date.now()-p;return W.logRequest(d,E,x,$,F.status,re),l?.info({requestId:d,method:E,path:x,status:F.status,duration:re,ip:$},"Request completed"),new Response(F.body,{status:F.status,headers:M})}catch(C){if(C instanceof P){if(l?.warn({error:C.message,requestId:d,ip:$},`App error: ${C.message}`),o.onError)try{return await o.onError(C.statusCode,x,E)}catch(w){l?.error({error:String(w),requestId:d},"Error in onError handler");}return new Response(JSON.stringify({error:C.message,code:C.code,requestId:d}),{status:C.statusCode,headers:{"Content-Type":"application/json"}})}l?.error({error:String(C),requestId:d,ip:$},"Unhandled error");let j=process.env.NODE_ENV==="production"?"Internal Server Error":C.message;if(o.onError)try{return await o.onError(500,x,E)}catch(w){l?.error({error:String(w),requestId:d},"Error in onError handler");}return new Response(JSON.stringify({error:j,requestId:d}),{status:500,headers:{"Content-Type":"application/json"}})}finally{f.delete(d);}}async function u(s,c,p){let d=0,h=null,x=s.json.bind(s),E=s.text.bind(s),$=s.html.bind(s),C=s.redirect.bind(s);s.json=function(w,T){let A=x(w,T);return h=A,A},s.text=function(w,T){let A=E(w,T);return h=A,A},s.html=function(w,T){let A=$(w,T);return h=A,A},s.redirect=function(w,T){let A=C(w,T);return h=A,A};async function j(){if(!h&&d<c.length){let w=c[d];d++,await w(s,j);}}return await j(),s.json=x,s.text=E,s.html=$,s.redirect=C,h||p(s)}let g={method:"GET",path:"/health",handler:s=>s.json({status:"healthy",timestamp:new Date().toISOString(),uptime:process.uptime(),activeRequests:f.size})},y={method:"GET",path:"/readiness",handler:s=>{let c=b.size>0,p=c||b.size===0;return s.json({ready:p,checks:{database:c?"connected":"not configured",activeRequests:f.size},timestamp:new Date().toISOString()},p?200:503)}};if(o.routes&&o.routes.forEach(s=>{v.push(s),(Array.isArray(s.method)?s.method:[s.method]).forEach(p=>{k.register(p,s.path,s.handler,s);});}),o.static){let s=Array.isArray(o.static)?o.static:[o.static];for(let c of s)try{let d=new O(c).handler(),h={method:"GET",path:c.path==="/"?"/*":`${c.path}/*`,handler:d};v.push(h);let x=c.path==="/"?"/":c.path;D.push({prefix:x,handler:d}),c.path==="/"?(k.register("GET","/",d,h),k.register("HEAD","/",d,h),k.register("GET","/*",d,h),k.register("HEAD","/*",d,h)):(k.register("GET",`${c.path}/*`,d,h),k.register("HEAD",`${c.path}/*`,d,h));}catch(p){throw l?.error({error:String(p),path:c.path},"Failed to initialize static file server"),p}}v.push(g,y),k.register("GET","/health",g.handler,g),k.register("GET","/readiness",y.handler,y);let S=null,U={app:null,logger:l,db:b,bunServer:null,async start(){if(m&&await m.init(),o.database){let c=Array.isArray(o.database)?o.database:[o.database];for(let p of c){let d=p.name||"default";try{if(typeof p.connection=="string"){let h=new le__namespace.DB(p.connection);if(p.schema&&typeof p.schema=="object")for(let[,x]of Object.entries(p.schema))x&&typeof x=="object"&&h.defineSchema(x);b.set(d,h),l?.info({name:d,connection:p.connection},"\u2714 Database connected");}else throw new Error(`Database connection must be a string path (got ${typeof p.connection})`)}catch(h){throw l?.error({error:String(h),name:d},"Failed to connect to database"),h}}}S=Bun.serve({port:e,hostname:t,fetch:(c,p)=>R(c,p)}),U.bunServer=S;let s=`http://${t}:${e}`;if(l?.info({url:s},"\u2714 Server started"),o.onStartup)try{await o.onStartup(U);}catch(c){l?.error({error:String(c)},"Error in startup handler");}if(o.onReady)try{await o.onReady(U,b);}catch(c){l?.error({error:String(c)},"Error in ready handler");}},async stop(){if(l?.info("Stopping server..."),f.size>0){l?.info({count:f.size},"Waiting for active requests...");let s=Date.now()+i;for(;f.size>0&&Date.now()<s;)await new Promise(c=>setTimeout(c,100));f.size>0&&l?.warn({count:f.size},"Force closing with active requests");}if(clearInterval(q),o.onShutdown)try{await o.onShutdown();}catch(s){l?.error({error:String(s)},"Error in shutdown handler");}for(let[s,c]of b.entries())try{c&&typeof c.close=="function"&&c.close(),l?.info({name:s},"Database closed");}catch(p){l?.error({error:String(p),name:s},"Error closing database");}S&&typeof S.stop=="function"&&(S.stop(),l?.info("Bun server stopped")),l?.info("Server stopped successfully");},addRoute(s){v.push(s),(Array.isArray(s.method)?s.method:[s.method]).forEach(p=>{k.register(p,s.path,s.handler,s);}),l?.info({method:s.method,path:s.path},"Route added");},addRoutes(s){s.forEach(c=>this.addRoute(c));},getRoutes(){return v}};return U}async function Re(o,e,t){let n=o.headers.get("content-type")||"";try{if(n.includes("application/json")){let r=await o.text();if(r.length>t)throw new I("Payload too large");if(!r.trim())return {};try{return JSON.parse(r)}catch(i){throw e?.warn({error:String(i),bodyPreview:r.substring(0,100)},"Invalid JSON in request body"),new I("Invalid JSON in request body")}}if(n.includes("application/x-www-form-urlencoded")){let r=await o.text();if(r.length>t)throw new I("Payload too large");return Object.fromEntries(new URLSearchParams(r))}if(n.includes("multipart/form-data"))return await o.formData()}catch(r){throw r instanceof I?r:(e?.error({error:String(r)},"Error parsing request body"),new I("Failed to parse request body"))}return {}}function ce(o){let e=new Map;if(!o)return e;let t=o.split(";");for(let n of t){let[r,...i]=n.trim().split("=");if(r){let a=i.join("=");e.set(r,a?decodeURIComponent(a):"");}}return e}function ae(o,e,t,n,r,i,a=null,l="en"){let m=new URL(e.url),b=Object.fromEntries(m.searchParams),v=e.headers,f=200,D=new Map,q=ce(v.get("cookie")||""),R={ip:o,request:e,params:t,query:b,headers:v,db:n,logger:r,i18n:a,lang:l,requestId:i,get statusCode(){return f},set statusCode(u){f=u;},body:null,state:{},json(u,g){return new Response(JSON.stringify(u),{status:g??f,headers:{"Content-Type":"application/json",...this._setCookieHeaders()}})},text(u,g){return new Response(u,{status:g??f,headers:{"Content-Type":"text/plain",...this._setCookieHeaders()}})},html(u,g){return new Response(u,{status:g??f,headers:{"Content-Type":"text/html; charset=utf-8",...this._setCookieHeaders()}})},redirect(u,g=302){return new Response(null,{status:g,headers:{Location:u,...this._setCookieHeaders()}})},file(u,g="application/octet-stream"){let y=Bun.file(u);return new Response(y,{headers:{"Content-Type":g,...this._setCookieHeaders()}})},setCookie(u,g,y={}){let S=`${u}=${encodeURIComponent(g)}`;return y.maxAge!==void 0&&(S+=`; Max-Age=${y.maxAge}`),y.expires&&(S+=`; Expires=${y.expires.toUTCString()}`),y.path&&(S+=`; Path=${y.path}`),y.domain&&(S+=`; Domain=${y.domain}`),y.secure&&(S+="; Secure"),y.httpOnly&&(S+="; HttpOnly"),y.sameSite&&(S+=`; SameSite=${y.sameSite}`),D.set(u,S),R},getCookie(u){return q.get(u)},deleteCookie(u,g={}){return R.setCookie(u,"",{...g,maxAge:0,path:g.path||"/"})},setHeader(u,g){return v.set(u,g),R},getHeader(u){return v.get(u)||void 0},status(u){return f=u,R},_setCookieHeaders(){let u={};return D.size>0&&(u["Set-Cookie"]=Array.from(D.values())),u}};return R}function Ce(o,e){let t=o.headers.get("x-forwarded-for");if(t)return t.split(",").map(i=>i.trim())[0]||"unknown";let n=o.headers.get("x-real-ip");if(n)return n;if(e)try{let i=e.requestIP?.(o);if(i?.address)return i.address}catch{}return "unknown"}function ve(o,e){let t=new Headers;if(!e.security||typeof e.security!="object"||!e.security.cors)return t;let n=typeof e.security.cors=="object"?e.security.cors:{},r=o.headers.get("Origin");if(r){typeof n.origin=="function"?n.origin(r)&&t.set("Access-Control-Allow-Origin",r):Array.isArray(n.origin)?n.origin.includes(r)&&t.set("Access-Control-Allow-Origin",r):typeof n.origin=="string"?t.set("Access-Control-Allow-Origin",n.origin):t.set("Access-Control-Allow-Origin",r);let i=n.methods||["GET","POST","PUT","DELETE","PATCH","OPTIONS"];t.set("Access-Control-Allow-Methods",i.join(", "));let a=n.allowedHeaders||["Content-Type","Authorization","X-Requested-With"];t.set("Access-Control-Allow-Headers",a.join(", ")),n.credentials&&t.set("Access-Control-Allow-Credentials","true"),n.maxAge&&t.set("Access-Control-Max-Age",n.maxAge.toString());}return t}var ze=xe;
2
+ Object.defineProperty(exports,"DB",{enumerable:true,get:function(){return le.DB}});Object.defineProperty(exports,"blob",{enumerable:true,get:function(){return le.blob}});Object.defineProperty(exports,"column",{enumerable:true,get:function(){return le.column}});Object.defineProperty(exports,"defaultValue",{enumerable:true,get:function(){return le.defaultValue}});Object.defineProperty(exports,"index",{enumerable:true,get:function(){return le.index}});Object.defineProperty(exports,"integer",{enumerable:true,get:function(){return le.integer}});Object.defineProperty(exports,"notNull",{enumerable:true,get:function(){return le.notNull}});Object.defineProperty(exports,"numeric",{enumerable:true,get:function(){return le.numeric}});Object.defineProperty(exports,"primaryKey",{enumerable:true,get:function(){return le.primaryKey}});Object.defineProperty(exports,"real",{enumerable:true,get:function(){return le.real}});Object.defineProperty(exports,"references",{enumerable:true,get:function(){return le.references}});Object.defineProperty(exports,"table",{enumerable:true,get:function(){return le.table}});Object.defineProperty(exports,"text",{enumerable:true,get:function(){return le.text}});Object.defineProperty(exports,"unique",{enumerable:true,get:function(){return le.unique}});Object.defineProperty(exports,"I18nManager",{enumerable:true,get:function(){return i18n.I18nManager}});Object.defineProperty(exports,"LazyLoader",{enumerable:true,get:function(){return i18n.LazyLoader}});Object.defineProperty(exports,"fetchTranslations",{enumerable:true,get:function(){return i18n.fetchTranslations}});Object.defineProperty(exports,"getI18n",{enumerable:true,get:function(){return i18n.getI18n}});Object.defineProperty(exports,"getLanguage",{enumerable:true,get:function(){return i18n.getLanguage}});Object.defineProperty(exports,"getSupportedLanguages",{enumerable:true,get:function(){return i18n.getSupportedLanguages}});Object.defineProperty(exports,"loadLanguage",{enumerable:true,get:function(){return i18n.loadLanguage}});Object.defineProperty(exports,"loadTranslations",{enumerable:true,get:function(){return i18n.loadTranslations}});Object.defineProperty(exports,"setLanguage",{enumerable:true,get:function(){return i18n.setLanguage}});Object.defineProperty(exports,"setupAuto",{enumerable:true,get:function(){return i18n.setupAuto}});Object.defineProperty(exports,"setupI18n",{enumerable:true,get:function(){return i18n.setupI18n}});Object.defineProperty(exports,"setupLazy",{enumerable:true,get:function(){return i18n.setupLazy}});Object.defineProperty(exports,"t",{enumerable:true,get:function(){return i18n.t}});Object.defineProperty(exports,"tLang",{enumerable:true,get:function(){return i18n.tLang}});Object.defineProperty(exports,"tParse",{enumerable:true,get:function(){return i18n.tParse}});exports.AppError=P;exports.DatabaseError=se;exports.Logger=J;exports.RateLimitError=oe;exports.Router=B;exports.SecurityManager=V;exports.StaticFileServer=O;exports.TimeoutError=X;exports.ValidationError=I;exports.createStatic=ye;exports.default=ze;exports.server=xe;//# sourceMappingURL=index.cjs.map
3
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/mod/router.ts","../src/mod/security.ts","../src/mod/logger.ts","../src/types.ts","../src/mod/static.ts","../src/index.ts"],"names":["Router","method","path","key","route","match","params","staticRoutes","colonIndex","dynamicRoutes","index","r","handler","metadata","pattern","existingIndex","SecurityManager","max","windowMs","now","record","sessionId","ttl","token","crypto","stored","data","html","input","id","ip","status","duration","first","Logger","_Logger","level","pretty","prefix","msg","childPrefix","levelName","k","levelNum","safeData","safeMsg","output","str","c","time","isDataContainsMethodPath","isDataContainsMethodPathStatusDuration","isDataContainsName","isDataContainsUrl","methods","icon","color","keys","parts","val","m","s","AppError","message","statusCode","code","ValidationError","issues","DatabaseError","TimeoutError","RateLimitError","StaticFileServer","config","existsSync","statSync","resolve","ctx","requestPath","pathname","p","filePath","stats","join","ext","withExt","relative","dirPath","_","indexFile","indexPath","cacheKey","cacheEntry","firstKey","ifNoneMatch","ifModifiedSince","ifModDate","file","headers","cache","mimeType","cacheControl","extname","MIME_TYPES","createStatic","security","router","server","port","hostname","maxReqSize","requestTimeout","gracefulShutdownTimeout","logCfg","logger","i18n","getI18n","dbs","routes","activeRequests","staticHandlers","cleanupInterval","handleRequest","request","startTime","requestId","getClientIp","contentLength","corsHeaders","handleCors","rateLimitCfg","rateLimitKey","body","parseBody","defaultDb","query","cookieHeader","cookieLang","parseCookies","requestLang","routeMatch","createAppContext","e","controller","timeoutPromise","reject","middlewares","handlerPromise","executeMiddlewares","response","resHeaders","value","error","errorMessage","earlyResponse","originalJson","originalText","originalHtml","originalRedirect","url","next","middleware","healthRoute","readinessRoute","dbConnected","ready","staticConfigs","staticCfg","staticRoute","bunServer","instance","dbConfigs","dbCfg","dbName","db","le","tableSchema","deadline","name","maxSize","contentType","text","cookies","pairs","pair","valueParts","i18nMgr","lang","cookieStore","parsedCookies","options","cookie","h","forwarded","realIp","remoteAddress","corsConfig","origin","allowedHeaders","index_default"],"mappings":"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","file":"index.cjs","sourcesContent":["// src/mod/router.ts\r\n//\r\n// Developed with ❀ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import type { AppContext } from '../types';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ TYPE ════════════════════════════════════════╗\r\n\r\n export type RouteHandler = (ctx: AppContext) => Response | Promise<Response>;\r\n export type RegexRoutes = RegexRoute[];\r\n\r\n export interface RegexRoute {\r\n pattern : RegExp;\r\n method : string;\r\n handler : RouteHandler;\r\n key : string;\r\n metadata? : unknown;\r\n }\r\n\r\n export interface RouteMatch {\r\n handler : RouteHandler;\r\n params : Record<string, string>;\r\n metadata? : unknown;\r\n }\r\n\r\n export interface RouteInfo {\r\n method : string;\r\n path : string;\r\n handler : RouteHandler;\r\n }\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 private routes = new Map<string, { handler: RouteHandler; metadata?: unknown }>();\r\n private regexRoutes: RegexRoutes = [];\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── MAIN ──────────────────────────────┐\r\n\r\n match(method: string, path: string): RouteMatch | null {\r\n const key = `${method}:${path}`;\r\n\r\n // Try static route first (faster)\r\n if (this.routes.has(key)) {\r\n const route = this.routes.get(key)!;\r\n return {\r\n handler: route.handler,\r\n params: {},\r\n metadata: route.metadata\r\n };\r\n }\r\n\r\n // Try dynamic routes\r\n for (const route of this.regexRoutes) {\r\n if (route.method === method) {\r\n const match = path.match(route.pattern);\r\n if (match) {\r\n // Extract named groups if they exist\r\n const params = match.groups || {};\r\n return {\r\n handler: route.handler,\r\n params,\r\n metadata: route.metadata\r\n };\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n getAll(): RouteInfo[] {\r\n const staticRoutes = Array.from(this.routes.entries()).map(([key, route]) => {\r\n const colonIndex = key.indexOf(':');\r\n const method = key.substring(0, colonIndex);\r\n const path = key.substring(colonIndex + 1);\r\n return { method, path, handler: route.handler };\r\n });\r\n\r\n const dynamicRoutes = this.regexRoutes.map(route => {\r\n const colonIndex = route.key.indexOf(':');\r\n return {\r\n method: route.method,\r\n path: route.key.substring(colonIndex + 1),\r\n handler: route.handler\r\n };\r\n });\r\n\r\n return [...staticRoutes, ...dynamicRoutes];\r\n }\r\n\r\n clear(): void {\r\n this.routes.clear();\r\n this.regexRoutes = [];\r\n }\r\n\r\n remove(method: string, path: string): boolean {\r\n const key = `${method}:${path}`;\r\n\r\n if (this.routes.has(key)) {\r\n this.routes.delete(key);\r\n return true;\r\n }\r\n\r\n const index = this.regexRoutes.findIndex(r => r.key === key);\r\n if (index >= 0) {\r\n this.regexRoutes.splice(index, 1);\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n register(method: string, path: string, handler: RouteHandler, metadata: unknown = {}): void {\r\n const key = `${method}:${path}`;\r\n\r\n // Check if path needs regex (has :params or wildcards)\r\n if (path.includes(':') || path.includes('*')) {\r\n // Dynamic route with params or wildcards\r\n const pattern = this.pathToRegex(path);\r\n\r\n // Check if route already exists to prevent duplicates\r\n const existingIndex = this.regexRoutes.findIndex(r => r.key === key);\r\n\r\n const route: RegexRoute = {\r\n pattern,\r\n method,\r\n handler,\r\n key,\r\n metadata\r\n };\r\n\r\n if (existingIndex >= 0) {\r\n // Update existing route\r\n this.regexRoutes[existingIndex] = route;\r\n } else {\r\n // Add new route\r\n this.regexRoutes.push(route);\r\n }\r\n } else {\r\n // Static route\r\n this.routes.set(key, { handler, metadata });\r\n }\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── HELP ──────────────────────────────┐\r\n\r\n private pathToRegex(path: string): RegExp {\r\n // Escape special regex characters except ':' and '*'\r\n let pattern = path.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&');\r\n\r\n // Replace :param with named capture groups\r\n pattern = pattern.replace(/:(\\w+)/g, '(?<$1>[^/]+)');\r\n\r\n // Replace * with wildcard pattern (matches everything including slashes)\r\n pattern = pattern.replace(/\\*/g, '.*');\r\n\r\n return new RegExp(`^${pattern}$`);\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝","// src/mod/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// ╔════════════════════════════════════════ TYPE ════════════════════════════════════════╗\r\n\r\n interface RateLimitRecord {\r\n count : number;\r\n reset : number;\r\n }\r\n\r\n interface CsrfTokenData {\r\n sessionId : string;\r\n expires : number;\r\n }\r\n\r\n interface RequestLogEntry {\r\n timestamp : string;\r\n method : string;\r\n path : string;\r\n ip : string;\r\n status : number;\r\n duration : number;\r\n }\r\n\r\n interface SecurityStats {\r\n rateLimitEntries : number;\r\n csrfTokens : number;\r\n requestLogs : number;\r\n }\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 private rateLimitStore = new Map<string, RateLimitRecord>();\r\n private csrfTokens = new Map<string, CsrfTokenData>();\r\n private requestLog = new Map<string, RequestLogEntry>();\r\n\r\n private readonly MAX_REQUEST_LOG_SIZE = 1000;\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── MAIN ──────────────────────────────┐\r\n\r\n // Rate Limiting with proper overflow handling\r\n checkRateLimit(key: string, max: number, windowMs: number): boolean {\r\n const now = Date.now();\r\n const record = this.rateLimitStore.get(key);\r\n\r\n if (record) {\r\n if (now < record.reset) {\r\n // Within the current window\r\n if (record.count >= max) {\r\n return false; // Rate limit exceeded\r\n }\r\n record.count++;\r\n return true;\r\n } else {\r\n // Window expired, reset\r\n this.rateLimitStore.set(key, { count: 1, reset: now + windowMs });\r\n return true;\r\n }\r\n } else {\r\n // First request for this key\r\n this.rateLimitStore.set(key, { count: 1, reset: now + windowMs });\r\n return true;\r\n }\r\n }\r\n\r\n // Cleanup old rate limit records\r\n cleanupRateLimit(): void {\r\n const now = Date.now();\r\n for (const [key, record] of this.rateLimitStore.entries()) {\r\n if (now > record.reset) {\r\n this.rateLimitStore.delete(key);\r\n }\r\n }\r\n }\r\n\r\n // CSRF Token Generation with TTL\r\n generateCsrfToken(sessionId: string, ttl = 3600000): string {\r\n const token = crypto.randomBytes(32).toString('hex');\r\n this.csrfTokens.set(token, {\r\n sessionId,\r\n expires: Date.now() + ttl\r\n });\r\n return token;\r\n }\r\n\r\n // Validate CSRF Token with expiration check\r\n validateCsrfToken(token: string, sessionId: string): boolean {\r\n const stored = this.csrfTokens.get(token);\r\n\r\n if (!stored) {\r\n return false;\r\n }\r\n\r\n // Check if token has expired\r\n if (Date.now() > stored.expires) {\r\n this.csrfTokens.delete(token);\r\n return false;\r\n }\r\n\r\n // Validate session ID\r\n if (stored.sessionId === sessionId) {\r\n this.csrfTokens.delete(token); // One-time use\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n // Cleanup expired CSRF tokens\r\n cleanupCsrfTokens(): void {\r\n const now = Date.now();\r\n for (const [token, data] of this.csrfTokens.entries()) {\r\n if (now > data.expires) {\r\n this.csrfTokens.delete(token);\r\n }\r\n }\r\n }\r\n\r\n // HTML Sanitization - comprehensive\r\n sanitizeHtml(html: string): string {\r\n if (!html) return '';\r\n\r\n return html\r\n .replace(/&/g, '&amp;')\r\n .replace(/</g, '&lt;')\r\n .replace(/>/g, '&gt;')\r\n .replace(/\"/g, '&quot;')\r\n .replace(/'/g, '&#x27;')\r\n .replace(/\\//g, '&#x2F;');\r\n }\r\n\r\n // SQL Injection Prevention\r\n sanitizeSql(input: string): string {\r\n if (!input) return '';\r\n\r\n return input\r\n .replace(/\\\\/g, '\\\\\\\\') // Escape backslashes first\r\n .replace(/;/g, '') // Remove semicolons to prevent multi-statement injection\r\n .replace(/'/g, \"''\") // Escape single quotes (SQL standard)\r\n .replace(/\"/g, '\\\\\"') // Escape double quotes\r\n // eslint-disable-next-line no-control-regex\r\n .replace(/\\u0000/g, ''); // Remove null bytes\r\n }\r\n\r\n // Log request for audit trail with size limit\r\n logRequest(\r\n id: string,\r\n method: string,\r\n path: string,\r\n ip: string,\r\n status: number,\r\n duration: number\r\n ): void {\r\n this.requestLog.set(id, {\r\n timestamp: new Date().toISOString(),\r\n method,\r\n path,\r\n ip,\r\n status,\r\n duration\r\n });\r\n\r\n // Keep only last MAX_REQUEST_LOG_SIZE requests\r\n if (this.requestLog.size > this.MAX_REQUEST_LOG_SIZE) {\r\n const { value: first } = this.requestLog.keys().next() || { value: null };\r\n if (first) {\r\n this.requestLog.delete(first);\r\n }\r\n }\r\n }\r\n\r\n // Get request log by ID\r\n getRequestLog(id: string): RequestLogEntry | undefined {\r\n return this.requestLog.get(id);\r\n }\r\n\r\n // Get all request logs\r\n getAllRequestLogs(): RequestLogEntry[] {\r\n return Array.from(this.requestLog.values());\r\n }\r\n\r\n // Clear all\r\n clearAll(): void {\r\n this.rateLimitStore.clear();\r\n this.csrfTokens.clear();\r\n this.requestLog.clear();\r\n }\r\n\r\n // Get stats\r\n getStats(): SecurityStats {\r\n return {\r\n rateLimitEntries: this.rateLimitStore.size,\r\n csrfTokens: this.csrfTokens.size,\r\n requestLogs: this.requestLog.size\r\n };\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝","// src/mod/logger.ts\r\n//\r\n// Made with ❀ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n export 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 prefix\t: string \t= '';\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\t// ANSI color codes\r\n\t\t\tprivate colors = {\r\n\t\t\t\treset\t: '\\x1b[0m',\r\n\t\t\t\tgray\t: '\\x1b[90m',\r\n\t\t\t\tcyan\t: '\\x1b[36m',\r\n\t\t\t\tgreen\t: '\\x1b[32m',\r\n\t\t\t\tyellow\t: '\\x1b[33m',\r\n\t\t\t\tred\t\t: '\\x1b[31m',\r\n\t\t\t\tmagenta\t: '\\x1b[35m',\r\n\t\t\t\tbold\t: '\\x1b[1m'\r\n\t\t\t};\r\n\r\n\t\t\tconstructor(\r\n\t\t\t\tlevel: 'debug' | 'info' | 'warn' | 'error' = 'info',\r\n\t\t\t\tpretty = false,\r\n\t\t\t\tprefix = ''\r\n\t\t\t) {\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\tthis.prefix = prefix;\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: unknown, 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: unknown, 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: unknown, 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: unknown, 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: unknown, msg?: string) {\r\n\t\t\t\tthis.log('fatal', this.levels.fatal, data, msg);\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\t\t\t// New method to create child logger with prefix\r\n\t\t\tchild(prefix: string): Logger {\r\n\t\t\t\tconst childPrefix = this.prefix ? `${this.prefix}:${prefix}` : prefix;\r\n\t\t\t\tconst levelName = (Object.keys(this.levels).find(\r\n\t\t\t\t\tk => this.levels[k as keyof typeof this.levels] === this.level\r\n\t\t\t\t) || 'info') as 'debug' | 'info' | 'warn' | 'error';\r\n\r\n\t\t\t\treturn new Logger(\r\n\t\t\t\t\tlevelName,\r\n\t\t\t\t\tthis.pretty,\r\n\t\t\t\t\tchildPrefix\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 private log(level: string, levelNum: number, data: unknown, msg?: string) {\r\n if (levelNum < this.level) return;\r\n\r\n // Handle when data is a string message\r\n let safeData: Record<string, unknown>;\r\n let safeMsg: string | undefined;\r\n\r\n if (typeof data === 'string') {\r\n safeMsg = data;\r\n safeData = {};\r\n } else {\r\n safeData = data as Record<string, unknown> ?? {};\r\n safeMsg = msg;\r\n }\r\n\r\n\t\t\t\t// Add prefix to message if exists\r\n\t\t\t\tif (this.prefix && safeMsg) {\r\n\t\t\t\t\tsafeMsg = `[${this.prefix}] ${safeMsg}`;\r\n\t\t\t\t} else if (this.prefix) {\r\n\t\t\t\t\tsafeMsg = `[${this.prefix}]`;\r\n\t\t\t\t}\r\n\r\n if (this.pretty) {\r\n this.prettyLog(level, safeData, safeMsg);\r\n } else {\r\n // JSON format (unchanged for compatibility)\r\n const ts = new Date().toISOString();\r\n const output = {\r\n timestamp\t: ts,\r\n level\t\t: level.toUpperCase(),\r\n message\t\t: safeMsg || 'No message',\r\n ...safeData\r\n };\r\n const str = JSON.stringify(output);\r\n\r\n if (level === 'error' || level === 'fatal') {\r\n console.error(str);\r\n } else if (level === 'warn') {\r\n console.warn(str);\r\n } else {\r\n console.log(str);\r\n }\r\n }\r\n }\r\n\r\n\t\t\tprivate prettyLog(level: string, data: Record<string, unknown>, msg?: string) {\r\n\t\t\t\tconst c = this.colors;\r\n\t\t\t\tconst time = new Date().toLocaleTimeString('en-US', { hour12: false });\r\n\r\n const isDataContainsMethodPath = 'method' in data && 'path' in data;\r\n const isDataContainsMethodPathStatusDuration = isDataContainsMethodPath && 'status' in data && 'duration' in data;\r\n const isDataContainsName = 'name' in data;\r\n const isDataContainsUrl = 'url' in data;\r\n\r\n\r\n\t\t\t\t// Special handling for request logs (Morgan-style)\r\n\t\t\t\tif (isDataContainsMethodPathStatusDuration) {\r\n\t\t\t\t\tconst method = this.colorizeMethod(data.method as string);\r\n\t\t\t\t\tconst status = this.colorizeStatus(data.status as number);\r\n\t\t\t\t\tconst duration = data.duration ? `${data.duration as number}ms` : '';\r\n\t\t\t\t\tconst path = data.path;\r\n\r\n\t\t\t\t\tconsole.log(\r\n\t\t\t\t\t\t`${c.gray}${time}${c.reset} ` +\r\n\t\t\t\t\t\t`${method} ` +\r\n\t\t\t\t\t\t`${c.bold}${path}${c.reset} ` +\r\n\t\t\t\t\t\t`${status} ` +\r\n\t\t\t\t\t\t`${c.gray}${duration}${c.reset}`\r\n\t\t\t\t\t);\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Special handling for route registration\r\n\t\t\t\tif (msg === 'Route added' && isDataContainsMethodPath) {\r\n\t\t\t\t\tconst methods = Array.isArray(data.method) ? data.method.join('|') : data.method as string;\r\n\t\t\t\t\tconsole.log(\r\n\t\t\t\t\t\t`${c.gray}${time}${c.reset} ` +\r\n\t\t\t\t\t\t`${c.cyan}→${c.reset} ` +\r\n\t\t\t\t\t\t`${c.bold}${methods.padEnd(6)}${c.reset} ` +\r\n\t\t\t\t\t\t`${data.path}`\r\n\t\t\t\t\t);\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Special handling for database connection\r\n\t\t\t\tif (msg === '✔ Database connected' && isDataContainsName) {\r\n\t\t\t\t\tconsole.log(\r\n\t\t\t\t\t\t`${c.gray}${time}${c.reset} ` +\r\n\t\t\t\t\t\t`${c.green}✓${c.reset} ` +\r\n\t\t\t\t\t\t`Database connected ${c.gray}(${data.name as string})${c.reset}`\r\n\t\t\t\t\t);\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Special handling for server start\r\n\t\t\t\tif (msg === 'Server started' && isDataContainsUrl) {\r\n\t\t\t\t\tconsole.log(\r\n\t\t\t\t\t\t`${c.gray}${time}${c.reset} ` +\r\n\t\t\t\t\t\t`${c.green}✓${c.reset} ` +\r\n\t\t\t\t\t\t`Server started at ${c.cyan}${data.url}${c.reset}`\r\n\t\t\t\t\t);\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Generic colored output\r\n\t\t\t\tconst icon = this.getLevelIcon(level);\r\n\t\t\t\tconst color = this.getLevelColor(level);\r\n\r\n\t\t\t\tlet output = `${c.gray}${time}${c.reset} ${color}${icon}${c.reset} `;\r\n\r\n\t\t\t\tif (msg) {\r\n\t\t\t\t\toutput += `${msg} `;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Add key data points inline\r\n\t\t\t\tconst keys = Object.keys(data).filter(k =>\r\n\t\t\t\t\t!['timestamp', 'level', 'message'].includes(k)\r\n\t\t\t\t);\r\n\r\n\t\t\t\tif (keys.length > 0) {\r\n\t\t\t\t\tconst parts = keys.map((k) => {\r\n\t\t\t\t\t\tconst val = data[k];\r\n if (typeof val === 'string' || typeof val === 'number') {\r\n return `${c.gray}${k}:${c.reset}${val}`;\r\n }\r\n\t\t\t\t\t\treturn null;\r\n\t\t\t\t\t}).filter(Boolean);\r\n\r\n\t\t\t\t\tif (parts.length > 0) {\r\n\t\t\t\t\t\toutput += c.gray + parts.join(' ') + c.reset;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconsole.log(output);\r\n\t\t\t}\r\n\r\n\t\t\tprivate colorizeMethod(method: string): string {\r\n\t\t\t\tconst c = this.colors;\r\n\t\t\t\tconst m = method.toUpperCase();\r\n\r\n\t\t\t\tswitch (m) {\r\n\t\t\t\t\tcase 'GET':\t\treturn `${c.green}${m}${c.reset}`;\r\n\t\t\t\t\tcase 'POST':\treturn `${c.cyan}${m}${c.reset}`;\r\n\t\t\t\t\tcase 'PUT':\t\treturn `${c.yellow}${m}${c.reset}`;\r\n\t\t\t\t\tcase 'DELETE':\treturn `${c.red}${m}${c.reset}`;\r\n\t\t\t\t\tcase 'PATCH':\treturn `${c.magenta}${m}${c.reset}`;\r\n\t\t\t\t\tdefault:\t\treturn `${c.gray}${m}${c.reset}`;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tprivate colorizeStatus(status: number | undefined): string {\r\n\t\t\t\tif (!status) return '';\r\n\r\n\t\t\t\tconst c = this.colors;\r\n\t\t\t\tconst s = status.toString();\r\n\r\n\t\t\t\tif (status >= 200 && status < 300) {\r\n\t\t\t\t\treturn `${c.green}${s}${c.reset}`;\r\n\t\t\t\t} else if (status >= 300 && status < 400) {\r\n\t\t\t\t\treturn `${c.cyan}${s}${c.reset}`;\r\n\t\t\t\t} else if (status >= 400 && status < 500) {\r\n\t\t\t\t\treturn `${c.yellow}${s}${c.reset}`;\r\n\t\t\t\t} else if (status >= 500) {\r\n\t\t\t\t\treturn `${c.red}${s}${c.reset}`;\r\n\t\t\t\t}\r\n\t\t\t\treturn `${c.gray}${s}${c.reset}`;\r\n\t\t\t}\r\n\r\n\t\t\tprivate getLevelIcon(level: string): string {\r\n\t\t\t\tswitch (level) {\r\n\t\t\t\t\tcase 'debug':\treturn '●';\r\n\t\t\t\t\tcase 'info':\treturn '●';\r\n\t\t\t\t\tcase 'warn':\treturn '⚠';\r\n\t\t\t\t\tcase 'error':\treturn '✖';\r\n\t\t\t\t\tcase 'fatal':\treturn '✖';\r\n\t\t\t\t\tdefault:\t\treturn '●';\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tprivate getLevelColor(level: string): string {\r\n\t\t\t\tconst c = this.colors;\r\n\t\t\t\tswitch (level) {\r\n\t\t\t\t\tcase 'debug':\treturn c.gray;\r\n\t\t\t\t\tcase 'info':\treturn c.cyan;\r\n\t\t\t\t\tcase 'warn':\treturn c.yellow;\r\n\t\t\t\t\tcase 'error':\treturn c.red;\r\n\t\t\t\t\tcase 'fatal':\treturn c.red + c.bold;\r\n\t\t\t\t\tdefault:\t\treturn c.reset;\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\r\n\r\n\r\n// ╔════════════════════════════════════════ ════ ════════════════════════════════════════╗\r\n\r\n export default Logger;\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝","// src/types.ts\r\n//\r\n// Developed with ❀ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import { DB } from '@minejs/db';\r\n import type { I18nManager, I18nConfig } from '@minejs/i18n';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ TYPE ════════════════════════════════════════╗\r\n\r\n\r\n export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS' | 'HEAD';\r\n export type RouteHandler = (c: AppContext) => Response | Promise<Response>;\r\n export type AppMiddleware = (c: AppContext, next: () => Promise<void>) => void | Promise<void>;\r\n\r\n export interface AppContext {\r\n ip : string;\r\n request : Request;\r\n params : Record<string, string>;\r\n query : Record<string, string>;\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n body : any;\r\n headers : Headers;\r\n db : DB | undefined;\r\n logger : Logger | null;\r\n i18n : I18nManager | null;\r\n lang? : string;\r\n user? : unknown;\r\n requestId : string;\r\n\r\n state : Record<string, unknown>;\r\n\r\n // Response methods\r\n json (data: unknown, 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 // Internal helper\r\n _setCookieHeaders(): Record<string, string | string[]>;\r\n }\r\n\r\n export interface StaticConfig {\r\n path : string; // URL path prefix (e.g., '/public' or '/static')\r\n directory : string; // Local directory to serve from\r\n maxAge? : number; // Cache control in seconds (default: 3600)\r\n index? : string[]; // Index files (default: ['index.html'])\r\n dotfiles? : 'allow' | 'deny' | 'ignore'; // How to handle dotfiles (default: 'deny')\r\n etag? : boolean; // Enable ETag headers (default: true)\r\n lastModified? : boolean; // Enable Last-Modified headers (default: true)\r\n immutable? : boolean; // Add immutable to cache-control (default: false)\r\n extensions? : string[]; // Try these extensions if file not found (e.g., ['html', 'htm'])\r\n fallthrough? : boolean; // Continue to next handler if file not found (default: false)\r\n setHeaders? : (ctx: AppContext, path: string) => void; // Custom header setter\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 ValidationSchema {\r\n body?: unknown;\r\n query?: unknown;\r\n params?: unknown;\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? : ValidationSchema;\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 // Database types\r\n export interface DatabaseConfig {\r\n name? : string;\r\n connection : string; // File path or ':memory:'\r\n schema? : Record<string, unknown>;\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 type LogLevel = 'debug' | 'info' | 'warn' | 'error';\r\n\r\n export interface LoggingConfig {\r\n level?: LogLevel;\r\n pretty?: boolean;\r\n }\r\n\r\n export interface ServerConfig {\r\n port? : number | string;\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 | LoggingConfig;\r\n\r\n // Internationalization (i18n)\r\n i18n? : boolean | I18nConfig;\r\n\r\n // Static file serving\r\n static? : StaticConfig | StaticConfig[];\r\n\r\n routes? : RouteDefinition[];\r\n middlewares? : AppMiddleware[];\r\n\r\n errorHandler? : (error: Error, context: AppContext) => void | Promise<void>;\r\n // Error page handler - returns Response for custom error pages\r\n onError? : (statusCode: number, path: string, method: string) => Response | Promise<Response>;\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n onStartup? : (app: any) => void | Promise<void>;\r\n onReady? : (app: ServerInstance, db: Map<string, DB>) => 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 : unknown;\r\n logger : Logger | null;\r\n db : Map<string, unknown>;\r\n bunServer : unknown;\r\n start : () => Promise<void>;\r\n stop : () => Promise<void>;\r\n addRoute : (route: RouteDefinition) => void;\r\n addRoutes : (routes: RouteDefinition[]) => void;\r\n getRoutes : () => RouteDefinition[];\r\n }\r\n\r\n export interface Logger {\r\n debug (data: unknown, msg?: string): void;\r\n info (data: unknown, msg?: string): void;\r\n warn (data: unknown, msg?: string): void;\r\n error (data: unknown, msg?: string): void;\r\n fatal (data: unknown, 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?: unknown) {\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// ╚══════════════════════════════════════════════════════════════════════════════════════╝","// src/mod/static.ts\r\n//\r\n// Static file serving module with security and performance features\r\n// Developed with ❀ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import { join, extname, resolve, relative } from 'path';\r\n import { existsSync, statSync } from 'fs';\r\n import type { AppContext } from '../types';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ TYPE ════════════════════════════════════════╗\r\n\r\n export interface StaticConfig {\r\n path : string; // URL path prefix (e.g., '/public' or '/static')\r\n directory : string; // Local directory to serve from\r\n maxAge? : number; // Cache control in seconds (default: 3600)\r\n index? : string[]; // Index files (default: ['index.html'])\r\n dotfiles? : 'allow' | 'deny' | 'ignore'; // How to handle dotfiles (default: 'deny')\r\n etag? : boolean; // Enable ETag headers (default: true)\r\n lastModified? : boolean; // Enable Last-Modified headers (default: true)\r\n immutable? : boolean; // Add immutable to cache-control (default: false)\r\n extensions? : string[]; // Try these extensions if file not found (e.g., ['html', 'htm'])\r\n fallthrough? : boolean; // Continue to next handler if file not found (default: false)\r\n setHeaders? : (ctx: AppContext, path: string) => void; // Custom header setter\r\n }\r\n\r\n interface CacheEntry {\r\n etag : string;\r\n lastModified : Date;\r\n size : number;\r\n mtime : number;\r\n }\r\n\r\n interface FileStats {\r\n size: number;\r\n mtime: Date;\r\n mtimeMs: number;\r\n isDirectory(): boolean;\r\n isFile(): boolean;\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n export class StaticFileServer {\r\n\r\n // ┌──────────────────────────────── INIT ──────────────────────────────┐\r\n\r\n private config : Required<Omit<StaticConfig, 'setHeaders'>> & Pick<StaticConfig, 'setHeaders'>;\r\n private resolvedDir : string;\r\n private fileCache = new Map<string, CacheEntry>();\r\n private readonly CACHE_MAX_SIZE = 1000;\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── CONS ──────────────────────────────┐\r\n\r\n constructor(config: StaticConfig) {\r\n // Validate directory exists\r\n if (!existsSync(config.directory)) {\r\n throw new Error(`Static directory does not exist: ${config.directory}`);\r\n }\r\n\r\n const stats = statSync(config.directory);\r\n if (!stats.isDirectory()) {\r\n throw new Error(`Static path is not a directory: ${config.directory}`);\r\n }\r\n\r\n // Resolve absolute path to prevent directory traversal\r\n this.resolvedDir = resolve(config.directory);\r\n\r\n // Set defaults\r\n this.config = {\r\n path : config.path,\r\n directory : config.directory,\r\n maxAge : config.maxAge ?? 3600,\r\n index : config.index ?? ['index.html'],\r\n dotfiles : config.dotfiles ?? 'deny',\r\n etag : config.etag ?? true,\r\n lastModified : config.lastModified ?? true,\r\n immutable : config.immutable ?? false,\r\n extensions : config.extensions ?? [],\r\n fallthrough : config.fallthrough ?? false,\r\n setHeaders : config.setHeaders\r\n };\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── MAIN ──────────────────────────────┐\r\n\r\n /**\r\n * Create request handler for static files\r\n */\r\n handler(): (ctx: AppContext) => Promise<Response> {\r\n return async (ctx: AppContext): Promise<Response> => {\r\n const requestPath = ctx.request.url;\r\n const url = new URL(requestPath);\r\n let pathname = url.pathname;\r\n\r\n // Remove prefix from pathname\r\n if (pathname.startsWith(this.config.path)) {\r\n pathname = pathname.slice(this.config.path.length);\r\n }\r\n\r\n // Decode URI component\r\n try {\r\n pathname = decodeURIComponent(pathname);\r\n } catch {\r\n return ctx.json({ error: 'Invalid URL encoding' }, 400);\r\n }\r\n\r\n // Security: Prevent directory traversal\r\n if (pathname.includes('..') || pathname.includes('\\\\')) {\r\n return ctx.json({ error: 'Forbidden' }, 403);\r\n }\r\n\r\n // Handle dotfiles\r\n if (this.config.dotfiles !== 'allow' && pathname.split('/').some(p => p.startsWith('.'))) {\r\n if (this.config.dotfiles === 'deny') {\r\n return ctx.json({ error: 'Forbidden' }, 403);\r\n }\r\n // 'ignore' - treat as not found\r\n return this.handleNotFound(ctx);\r\n }\r\n\r\n // Resolve file path\r\n const filePath = this.resolveFilePath(pathname);\r\n if (!filePath) {\r\n return this.handleNotFound(ctx);\r\n }\r\n\r\n // Check if file exists and is within allowed directory\r\n if (!this.isPathSafe(filePath)) {\r\n return ctx.json({ error: 'Forbidden' }, 403);\r\n }\r\n\r\n if (!existsSync(filePath)) {\r\n return this.handleNotFound(ctx);\r\n }\r\n\r\n const stats = statSync(filePath) as FileStats;\r\n\r\n // If directory, try to serve index file\r\n if (stats.isDirectory()) {\r\n return this.serveDirectory(ctx, filePath, pathname);\r\n }\r\n\r\n // Serve file\r\n return this.serveFile(ctx, filePath, stats);\r\n };\r\n }\r\n\r\n /**\r\n * Get URL path pattern for router\r\n */\r\n getPathPattern(): string {\r\n // Match the prefix and anything after it\r\n return `${this.config.path}/*`;\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── HELP ──────────────────────────────┐\r\n\r\n private resolveFilePath(pathname: string): string | null {\r\n // Remove leading slash\r\n if (pathname.startsWith('/')) {\r\n pathname = pathname.slice(1);\r\n }\r\n\r\n const filePath = join(this.resolvedDir, pathname);\r\n\r\n // Try with extensions if file doesn't exist\r\n if (!existsSync(filePath) && this.config.extensions.length > 0) {\r\n for (const ext of this.config.extensions) {\r\n const withExt = `${filePath}.${ext}`;\r\n if (existsSync(withExt)) {\r\n return withExt;\r\n }\r\n }\r\n }\r\n\r\n return filePath;\r\n }\r\n\r\n private isPathSafe(filePath: string): boolean {\r\n // Ensure the resolved path is within the static directory\r\n const rel = relative(this.resolvedDir, resolve(filePath));\r\n return !rel.startsWith('..') && !resolve(filePath).startsWith('..');\r\n }\r\n\r\n private async serveDirectory(ctx: AppContext, dirPath: string, _: string): Promise<Response> {\r\n // Try index files\r\n for (const indexFile of this.config.index) {\r\n const indexPath = join(dirPath, indexFile);\r\n if (existsSync(indexPath)) {\r\n const stats = statSync(indexPath) as FileStats;\r\n if (stats.isFile()) {\r\n return this.serveFile(ctx, indexPath, stats);\r\n }\r\n }\r\n }\r\n\r\n // No index file found\r\n return this.handleNotFound(ctx);\r\n }\r\n\r\n private async serveFile(ctx: AppContext, filePath: string, stats: FileStats): Promise<Response> {\r\n const method = ctx.request.method.toUpperCase();\r\n\r\n // Only allow GET and HEAD\r\n if (method !== 'GET' && method !== 'HEAD') {\r\n return ctx.json({ error: 'Method not allowed' }, 405);\r\n }\r\n\r\n // Get or create cache entry\r\n const cacheKey = filePath;\r\n let cacheEntry = this.fileCache.get(cacheKey);\r\n\r\n // Check if cache is stale\r\n if (cacheEntry && cacheEntry.mtime !== stats.mtimeMs) {\r\n cacheEntry = undefined;\r\n }\r\n\r\n if (!cacheEntry) {\r\n cacheEntry = {\r\n etag : this.generateEtag(stats),\r\n lastModified : new Date(stats.mtime),\r\n size : stats.size,\r\n mtime : stats.mtimeMs\r\n };\r\n\r\n // Add to cache with size limit\r\n if (this.fileCache.size >= this.CACHE_MAX_SIZE) {\r\n const firstKey = this.fileCache.keys().next().value;\r\n if (firstKey) this.fileCache.delete(firstKey);\r\n }\r\n this.fileCache.set(cacheKey, cacheEntry);\r\n }\r\n\r\n // Check conditional requests\r\n const ifNoneMatch = ctx.request.headers.get('if-none-match');\r\n const ifModifiedSince = ctx.request.headers.get('if-modified-since');\r\n\r\n if (this.config.etag && ifNoneMatch === cacheEntry.etag) {\r\n return new Response(null, {\r\n status: 304,\r\n headers: this.buildHeaders(filePath, cacheEntry)\r\n });\r\n }\r\n\r\n if (this.config.lastModified && ifModifiedSince) {\r\n const ifModDate = new Date(ifModifiedSince);\r\n if (cacheEntry.lastModified <= ifModDate) {\r\n return new Response(null, {\r\n status: 304,\r\n headers: this.buildHeaders(filePath, cacheEntry)\r\n });\r\n }\r\n }\r\n\r\n // Read file using Bun.file\r\n const file = Bun.file(filePath);\r\n const headers = this.buildHeaders(filePath, cacheEntry);\r\n\r\n // Set custom headers if provided\r\n if (this.config.setHeaders) {\r\n this.config.setHeaders(ctx, filePath);\r\n }\r\n\r\n // Return 200 with file content (or just headers for HEAD)\r\n if (method === 'HEAD') {\r\n return new Response(null, {\r\n status: 200,\r\n headers\r\n });\r\n }\r\n\r\n return new Response(file, {\r\n status: 200,\r\n headers\r\n });\r\n }\r\n\r\n private buildHeaders(filePath: string, cache: CacheEntry): Headers {\r\n const headers = new Headers();\r\n\r\n // Content-Type\r\n const mimeType = this.getMimeType(filePath);\r\n headers.set('Content-Type', mimeType);\r\n\r\n // Content-Length\r\n headers.set('Content-Length', cache.size.toString());\r\n\r\n // ETag\r\n if (this.config.etag) {\r\n headers.set('ETag', cache.etag);\r\n }\r\n\r\n // Last-Modified\r\n if (this.config.lastModified) {\r\n headers.set('Last-Modified', cache.lastModified.toUTCString());\r\n }\r\n\r\n // Cache-Control\r\n if (this.config.maxAge > 0) {\r\n let cacheControl = `public, max-age=${this.config.maxAge}`;\r\n if (this.config.immutable) {\r\n cacheControl += ', immutable';\r\n }\r\n headers.set('Cache-Control', cacheControl);\r\n } else {\r\n headers.set('Cache-Control', 'no-cache');\r\n }\r\n\r\n // Accept-Ranges for partial content support\r\n headers.set('Accept-Ranges', 'bytes');\r\n\r\n return headers;\r\n }\r\n\r\n private generateEtag(stats: FileStats): string {\r\n // Simple ETag: size-mtime\r\n return `\"${stats.size.toString(16)}-${stats.mtimeMs.toString(16)}\"`;\r\n }\r\n\r\n private getMimeType(filePath: string): string {\r\n const ext = extname(filePath).toLowerCase();\r\n return MIME_TYPES[ext] || 'application/octet-stream';\r\n }\r\n\r\n private handleNotFound(ctx: AppContext): Response {\r\n if (this.config.fallthrough) {\r\n // Let the next handler deal with it\r\n return ctx.json({ error: 'Not Found' }, 404);\r\n }\r\n return ctx.json({ error: 'Not Found' }, 404);\r\n }\r\n\r\n /**\r\n * Clear file cache\r\n */\r\n clearCache(): void {\r\n this.fileCache.clear();\r\n }\r\n\r\n /**\r\n * Get cache statistics\r\n */\r\n getCacheStats(): { entries: number; maxSize: number } {\r\n return {\r\n entries: this.fileCache.size,\r\n maxSize: this.CACHE_MAX_SIZE\r\n };\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ UTIL ════════════════════════════════════════╗\r\n\r\n /**\r\n * Helper function to create static file server\r\n */\r\n export function createStatic(config: StaticConfig): StaticFileServer {\r\n return new StaticFileServer(config);\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ DATA ════════════════════════════════════════╗\r\n\r\n /**\r\n * Comprehensive MIME type mapping\r\n */\r\n const MIME_TYPES: Record<string, string> = {\r\n // Text\r\n '.html' : 'text/html; charset=utf-8',\r\n '.htm' : 'text/html; charset=utf-8',\r\n '.css' : 'text/css; charset=utf-8',\r\n '.txt' : 'text/plain; charset=utf-8',\r\n '.xml' : 'text/xml; charset=utf-8',\r\n '.csv' : 'text/csv; charset=utf-8',\r\n '.md' : 'text/markdown; charset=utf-8',\r\n\r\n // JavaScript\r\n '.js' : 'application/javascript; charset=utf-8',\r\n '.mjs' : 'application/javascript; charset=utf-8',\r\n '.json' : 'application/json; charset=utf-8',\r\n '.jsonld' : 'application/ld+json',\r\n '.map' : 'application/json; charset=utf-8',\r\n\r\n // Images\r\n '.png' : 'image/png',\r\n '.jpg' : 'image/jpeg',\r\n '.jpeg' : 'image/jpeg',\r\n '.gif' : 'image/gif',\r\n '.svg' : 'image/svg+xml',\r\n '.ico' : 'image/x-icon',\r\n '.webp' : 'image/webp',\r\n '.avif' : 'image/avif',\r\n '.bmp' : 'image/bmp',\r\n '.tiff' : 'image/tiff',\r\n\r\n // Fonts\r\n '.woff' : 'font/woff',\r\n '.woff2' : 'font/woff2',\r\n '.ttf' : 'font/ttf',\r\n '.otf' : 'font/otf',\r\n '.eot' : 'application/vnd.ms-fontobject',\r\n\r\n // Audio\r\n '.mp3' : 'audio/mpeg',\r\n '.wav' : 'audio/wav',\r\n '.ogg' : 'audio/ogg',\r\n '.m4a' : 'audio/mp4',\r\n '.aac' : 'audio/aac',\r\n '.flac' : 'audio/flac',\r\n\r\n // Video\r\n '.mp4' : 'video/mp4',\r\n '.webm' : 'video/webm',\r\n '.ogv' : 'video/ogg',\r\n '.mov' : 'video/quicktime',\r\n '.avi' : 'video/x-msvideo',\r\n '.mkv' : 'video/x-matroska',\r\n\r\n // Documents\r\n '.pdf' : 'application/pdf',\r\n '.doc' : 'application/msword',\r\n '.docx' : 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\r\n '.xls' : 'application/vnd.ms-excel',\r\n '.xlsx' : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\r\n '.ppt' : 'application/vnd.ms-powerpoint',\r\n '.pptx' : 'application/vnd.openxmlformats-officedocument.presentationml.presentation',\r\n\r\n // Archives\r\n '.zip' : 'application/zip',\r\n '.rar' : 'application/x-rar-compressed',\r\n '.7z' : 'application/x-7z-compressed',\r\n '.tar' : 'application/x-tar',\r\n '.gz' : 'application/gzip',\r\n\r\n // Other\r\n '.wasm' : 'application/wasm',\r\n '.manifest' : 'text/cache-manifest',\r\n '.webmanifest' : 'application/manifest+json',\r\n };\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝","// src/index.ts\r\n//\r\n// Developed with ❀ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import * as sdb from '@minejs/db';\r\n import { Router } from './mod/router';\r\n import { SecurityManager } from './mod/security';\r\n import { Logger } \t from './mod/logger';\r\n import * as types from './types';\r\n import { StaticFileServer } from './mod/static';\r\n import { getI18n, I18nManager } from '@minejs/i18n';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ INIT ════════════════════════════════════════╗\r\n\r\n const security = new SecurityManager();\r\n const router = new Router();\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n export function server(config: types.ServerConfig = {}): types.ServerInstance {\r\n\r\n\t\t// ════════ Configuration ════════\r\n\t\tconst port = Number(config.port) || 3000;\r\n\t\tconst hostname = config.hostname || 'localhost';\r\n\t\tconst maxReqSize = config.maxRequestSize || 10 * 1024 * 1024;\r\n\t\tconst requestTimeout = config.requestTimeout || 30000;\r\n\t\tconst gracefulShutdownTimeout = config.gracefulShutdownTimeout || 10000;\r\n\r\n\t\tconst logCfg = typeof config.logging === 'object' ? config.logging : {};\r\n\t\tconst logger = config.logging ? new Logger(logCfg.level || 'info', logCfg.pretty) : null;\r\n\r\n\t\t// ════════ i18n Configuration ════════\r\n\t\tlet i18n: I18nManager | null = null;\r\n\t\tif (config.i18n) {\r\n\t\t\ti18n = getI18n();\r\n\t\t\t// The i18n instance is now available and can be initialized with languages as needed\r\n\t\t}\r\n\r\n\t\tconst dbs = new Map<string, sdb.DB>();\r\n\t\tconst routes: types.RouteDefinition[] = [];\r\n\t\tconst activeRequests = new Set<string>();\r\n\t\tconst staticHandlers: { prefix: string; handler: types.RouteHandler }[] = [];\r\n\r\n\t\t// ════════ Cleanup intervals ════════\r\n const cleanupInterval = setInterval(() => {\r\n security.cleanupRateLimit();\r\n security.cleanupCsrfTokens();\r\n }, 2 * 60 * 1000);\r\n\r\n async function handleRequest(request: Request, server: unknown): Promise<Response> {\r\n const startTime = Date.now();\r\n const requestId = crypto.randomUUID();\r\n const url = new URL(request.url);\r\n const path = url.pathname;\r\n const method = request.method.toUpperCase();\r\n const ip = getClientIp(request, server);\r\n\r\n activeRequests.add(requestId);\r\n\r\n try {\r\n // Check request size from header\r\n const contentLength = request.headers.get('content-length');\r\n if (contentLength && parseInt(contentLength) > maxReqSize) {\r\n logger?.warn({ requestId, size: contentLength, ip }, 'Request too large');\r\n return new Response(JSON.stringify({ error: 'Payload too large' }), {\r\n\t\t\t\t\t\tstatus\t: 413,\r\n\t\t\t\t\t\theaders\t: { 'Content-Type': 'application/json' }\r\n });\r\n }\r\n\r\n // CORS handling\r\n const corsHeaders = handleCors(request, config);\r\n if (method === 'OPTIONS') {\r\n return new Response(null, { status: 204, headers: corsHeaders });\r\n }\r\n\r\n // Rate limiting\r\n if (config.security && typeof config.security === 'object' && config.security.rateLimit) {\r\n const rateLimitCfg = typeof config.security.rateLimit === 'object'\r\n ? config.security.rateLimit\r\n : {};\r\n const max = rateLimitCfg.max || 100;\r\n const windowMs = rateLimitCfg.windowMs || 60000;\r\n const rateLimitKey = rateLimitCfg.keyGenerator\r\n ? rateLimitCfg.keyGenerator({ request, ip } as types.AppContext)\r\n : ip;\r\n\r\n if (!security.checkRateLimit(rateLimitKey, max, windowMs)) {\r\n logger?.warn({ requestId, ip, key: rateLimitKey }, 'Rate limit exceeded');\r\n return new Response(\r\n JSON.stringify({ error: rateLimitCfg.message || 'Too many requests' }),\r\n { status: 429, headers: { 'Content-Type': 'application/json' } }\r\n );\r\n }\r\n }\r\n\r\n // Parse body\r\n let body: unknown = null;\r\n if (['POST', 'PUT', 'PATCH'].includes(method)) {\r\n body = await parseBody(request, logger, maxReqSize);\r\n }\r\n\r\n // Get database\r\n const defaultDb = dbs.get('default');\r\n\r\n // Detect language from request (query param, cookie, header, or default)\r\n const query = Object.fromEntries(new URL(request.url).searchParams);\r\n const cookieHeader = request.headers.get('cookie') || '';\r\n const parsedRequestCookies = parseCookies(cookieHeader);\r\n const cookieLang = parsedRequestCookies.get('lang');\r\n\r\n let requestLang = (query.lang as string) || cookieLang || request.headers.get('Accept-Language')?.split(',')[0]?.split('-')[0] || 'en';\r\n if (i18n && !i18n.getSupportedLanguages().includes(requestLang)) {\r\n requestLang = i18n.getLanguage();\r\n }\r\n if (i18n) {\r\n i18n.setLanguage(requestLang);\r\n }\r\n\r\n // Match route\r\n const routeMatch = router.match(method, path);\r\n if (!routeMatch) {\r\n const ctx = createAppContext(ip, request, {}, defaultDb, logger, requestId, i18n, requestLang);\r\n logger?.warn({ requestId, method, path, ip }, 'Route not found');\r\n\r\n // Call onError handler if provided\r\n if (config.onError) {\r\n try {\r\n const errorResponse = await config.onError(404, path, method);\r\n return errorResponse;\r\n } catch (e) {\r\n logger?.error({ error: String(e), requestId }, 'Error in onError handler');\r\n }\r\n }\r\n\r\n return ctx.json({ error: 'Not Found', path }, 404);\r\n }\r\n\r\n const ctx = createAppContext(ip, request, routeMatch.params || {}, defaultDb, logger, requestId, i18n, requestLang);\r\n ctx.body = body;\r\n ctx.request = request;\r\n\r\n // Execute route handler with timeout\r\n const controller = new AbortController();\r\n const timeoutPromise = new Promise<never>((_, reject) => {\r\n const id = setTimeout(() => {\r\n controller.abort();\r\n reject(new types.TimeoutError('Request timeout'));\r\n }, requestTimeout);\r\n controller.signal.addEventListener('abort', () => clearTimeout(id));\r\n });\r\n\r\n // Get middlewares from route metadata\r\n const routeDefinition = routeMatch.metadata as types.RouteDefinition | undefined;\r\n const middlewares = routeDefinition?.middlewares || [];\r\n\r\n let handlerPromise: Promise<Response>;\r\n if (middlewares.length > 0) {\r\n handlerPromise = executeMiddlewares(ctx, middlewares, routeMatch.handler);\r\n } else {\r\n handlerPromise = Promise.resolve(routeMatch.handler(ctx));\r\n }\r\n\r\n const response = await Promise.race([\r\n handlerPromise,\r\n timeoutPromise\r\n ]) as Response;\r\n\r\n // Merge CORS and security headers\r\n const resHeaders = new Headers(response.headers);\r\n corsHeaders.forEach((value, key) => {\r\n if (!resHeaders.has(key)) resHeaders.set(key, value);\r\n });\r\n\r\n resHeaders.set('X-Request-ID', requestId);\r\n resHeaders.set('X-Content-Type-Options', 'nosniff');\r\n resHeaders.set('X-Frame-Options', 'DENY');\r\n resHeaders.set('X-XSS-Protection', '1; mode=block');\r\n resHeaders.set('Referrer-Policy', 'strict-origin-when-cross-origin');\r\n\r\n // Audit log\r\n const duration = Date.now() - startTime;\r\n security.logRequest(requestId, method, path, ip, response.status, duration);\r\n logger?.info({\r\n requestId,\r\n method,\r\n path,\r\n status: response.status,\r\n duration,\r\n ip\r\n }, 'Request completed');\r\n\r\n return new Response(response.body, {\r\n status: response.status,\r\n headers: resHeaders\r\n });\r\n } catch (error) {\r\n if (error instanceof types.AppError) {\r\n logger?.warn({ error: error.message, requestId, ip }, `App error: ${error.message}`);\r\n\r\n // Call onError handler for AppError if provided\r\n if (config.onError) {\r\n try {\r\n const errorResponse = await config.onError(error.statusCode, path, method);\r\n return errorResponse;\r\n } catch (e) {\r\n logger?.error({ error: String(e), requestId }, 'Error in onError handler');\r\n }\r\n }\r\n\r\n return new Response(\r\n JSON.stringify({\r\n error\t: error.message,\r\n code\t: error.code,\r\n requestId\r\n }),\r\n { status: error.statusCode, headers: { 'Content-Type': 'application/json' } }\r\n );\r\n }\r\n\r\n logger?.error({ error: String(error), requestId, ip }, 'Unhandled error');\r\n\r\n const errorMessage = process.env.NODE_ENV === 'production'\r\n ? 'Internal Server Error'\r\n : (error as Error).message;\r\n\r\n // Call onError handler for unhandled errors if provided\r\n if (config.onError) {\r\n try {\r\n const errorResponse = await config.onError(500, path, method);\r\n return errorResponse;\r\n } catch (e) {\r\n logger?.error({ error: String(e), requestId }, 'Error in onError handler');\r\n }\r\n }\r\n\r\n return new Response(\r\n JSON.stringify({ error: errorMessage, requestId }),\r\n { status: 500, headers: { 'Content-Type': 'application/json' } }\r\n );\r\n } finally {\r\n activeRequests.delete(requestId);\r\n }\r\n }\r\n\r\n async function executeMiddlewares(\r\n ctx: types.AppContext,\r\n middlewares: types.AppMiddleware[],\r\n handler: types.RouteHandler\r\n ): Promise<Response> {\r\n let index = 0;\r\n let earlyResponse: Response | null = null;\r\n\r\n // Override ctx methods to capture early responses\r\n const originalJson = ctx.json.bind(ctx);\r\n const originalText = ctx.text.bind(ctx);\r\n const originalHtml = ctx.html.bind(ctx);\r\n const originalRedirect = ctx.redirect.bind(ctx);\r\n\r\n ctx.json = function(data: unknown, status?: number): Response {\r\n const response = originalJson(data, status);\r\n earlyResponse = response;\r\n return response;\r\n };\r\n\r\n ctx.text = function(data: string, status?: number): Response {\r\n const response = originalText(data, status);\r\n earlyResponse = response;\r\n return response;\r\n };\r\n\r\n ctx.html = function(data: string, status?: number): Response {\r\n const response = originalHtml(data, status);\r\n earlyResponse = response;\r\n return response;\r\n };\r\n\r\n ctx.redirect = function(url: string, status?: number): Response {\r\n const response = originalRedirect(url, status);\r\n earlyResponse = response;\r\n return response;\r\n };\r\n\r\n async function next(): Promise<void> {\r\n // If middleware sent a response, stop\r\n if (earlyResponse) {\r\n return;\r\n }\r\n\r\n if (index < middlewares.length) {\r\n const middleware = middlewares[index];\r\n index++;\r\n await middleware(ctx, next);\r\n }\r\n }\r\n\r\n // Execute all middlewares\r\n await next();\r\n\r\n // Restore original methods\r\n ctx.json = originalJson;\r\n ctx.text = originalText;\r\n ctx.html = originalHtml;\r\n ctx.redirect = originalRedirect;\r\n\r\n // If middleware sent a response early, return it\r\n if (earlyResponse) {\r\n return earlyResponse;\r\n }\r\n\r\n // Otherwise, call the handler\r\n return handler(ctx);\r\n }\r\n\r\n // ════════ Health & Readiness routes ════════\r\n const healthRoute: types.RouteDefinition = {\r\n method : 'GET',\r\n path : '/health',\r\n handler : (c: types.AppContext) => c.json({\r\n status : 'healthy',\r\n timestamp : new Date().toISOString(),\r\n uptime : process.uptime(),\r\n activeRequests : activeRequests.size\r\n })\r\n };\r\n\r\n const readinessRoute: types.RouteDefinition = {\r\n method : 'GET',\r\n path : '/readiness',\r\n handler : (c: types.AppContext) => {\r\n const dbConnected = dbs.size > 0;\r\n const ready = dbConnected || dbs.size === 0;\r\n return c.json({\r\n ready,\r\n checks : {\r\n database : dbConnected ? 'connected' : 'not configured',\r\n activeRequests : activeRequests.size\r\n },\r\n timestamp: new Date().toISOString()\r\n }, ready ? 200 : 503);\r\n }\r\n };\r\n\r\n // ════════ Register routes ════════\r\n if (config.routes) {\r\n config.routes.forEach(route => {\r\n routes.push(route);\r\n const methods = Array.isArray(route.method) ? route.method : [route.method];\r\n methods.forEach(m => {\r\n router.register(m, route.path, route.handler as types.RouteHandler, route);\r\n });\r\n });\r\n }\r\n\r\n // ════════ Static file serving ════════\r\n if (config.static) {\r\n const staticConfigs = Array.isArray(config.static) ? config.static : [config.static];\r\n\r\n for (const staticCfg of staticConfigs) {\r\n try {\r\n const staticServer = new StaticFileServer(staticCfg);\r\n const handler = staticServer.handler();\r\n\r\n const staticRoute: types.RouteDefinition = {\r\n method: 'GET',\r\n path: staticCfg.path === '/' ? '/*' : `${staticCfg.path}/*`,\r\n handler: handler as types.RouteHandler\r\n };\r\n\r\n routes.push(staticRoute);\r\n\r\n // Add to static handlers list for early matching\r\n const prefix = staticCfg.path === '/' ? '/' : staticCfg.path;\r\n staticHandlers.push({\r\n prefix,\r\n handler: handler as types.RouteHandler\r\n });\r\n\r\n if (staticCfg.path === '/') {\r\n router.register('GET', '/', handler as types.RouteHandler, staticRoute);\r\n router.register('HEAD', '/', handler as types.RouteHandler, staticRoute);\r\n router.register('GET', '/*', handler as types.RouteHandler, staticRoute);\r\n router.register('HEAD', '/*', handler as types.RouteHandler, staticRoute);\r\n } else {\r\n router.register('GET', `${staticCfg.path}/*`, handler as types.RouteHandler, staticRoute);\r\n router.register('HEAD', `${staticCfg.path}/*`, handler as types.RouteHandler, staticRoute);\r\n }\r\n } catch (error) {\r\n logger?.error({\r\n error: String(error),\r\n path: staticCfg.path\r\n }, 'Failed to initialize static file server');\r\n throw error;\r\n }\r\n }\r\n }\r\n\r\n routes.push(healthRoute, readinessRoute);\r\n router.register('GET', '/health', healthRoute.handler as types.RouteHandler, healthRoute);\r\n router.register('GET', '/readiness', readinessRoute.handler as types.RouteHandler, readinessRoute);\r\n\r\n let bunServer: unknown = null;\r\n\r\n const instance: types.ServerInstance = {\r\n app : null,\r\n logger,\r\n db : dbs,\r\n bunServer : null,\r\n\r\n async start() {\r\n // Initialize i18n if enabled\r\n if (i18n) {\r\n await i18n.init();\r\n // Use setupAuto in onStartup hook to automatically load translations\r\n // from local files on server or remote URLs on browser\r\n // Example in onStartup:\r\n // const { setupAuto } = await import('@minejs/i18n')\r\n // await setupAuto({ defaultLanguage: 'en', basePath: './translations/' })\r\n }\r\n\r\n if (config.database) {\r\n const dbConfigs = Array.isArray(config.database) ? config.database : [config.database];\r\n for (const dbCfg of dbConfigs) {\r\n const dbName = dbCfg.name || 'default';\r\n\r\n try {\r\n if (typeof dbCfg.connection === 'string') {\r\n const db = new sdb.DB(dbCfg.connection);\r\n\r\n if (dbCfg.schema && typeof dbCfg.schema === 'object') {\r\n for (const [, tableSchema] of Object.entries(dbCfg.schema)) {\r\n if (tableSchema && typeof tableSchema === 'object') {\r\n db.defineSchema(tableSchema as sdb.TableSchema);\r\n }\r\n }\r\n }\r\n\r\n dbs.set(dbName, db);\r\n\r\n logger?.info({\r\n name: dbName,\r\n connection: dbCfg.connection\r\n }, '✔ Database connected');\r\n } else {\r\n throw new Error(`Database connection must be a string path (got ${typeof dbCfg.connection})`);\r\n }\r\n } catch (error) {\r\n logger?.error({\r\n error: String(error),\r\n name: dbName\r\n }, 'Failed to connect to database');\r\n throw error;\r\n }\r\n }\r\n }\r\n\r\n bunServer = Bun.serve({\r\n port,\r\n hostname,\r\n fetch: (request, server) => handleRequest(request, server)\r\n });\r\n instance.bunServer = bunServer;\r\n\r\n const url = `http://${hostname}:${port}`;\r\n logger?.info({ url }, '✔ Server started');\r\n\r\n if (config.onStartup) {\r\n try {\r\n await config.onStartup(instance);\r\n } catch (e) {\r\n logger?.error({ error: String(e) }, 'Error in startup handler');\r\n }\r\n }\r\n\r\n if (config.onReady) {\r\n try {\r\n await config.onReady(instance, dbs);\r\n } catch (e) {\r\n logger?.error({ error: String(e) }, 'Error in ready handler');\r\n }\r\n }\r\n },\r\n\r\n async stop() {\r\n logger?.info('Stopping server...');\r\n\r\n if (activeRequests.size > 0) {\r\n logger?.info({ count: activeRequests.size }, 'Waiting for active requests...');\r\n const deadline = Date.now() + gracefulShutdownTimeout;\r\n\r\n while (activeRequests.size > 0 && Date.now() < deadline) {\r\n await new Promise(resolve => setTimeout(resolve, 100));\r\n }\r\n\r\n if (activeRequests.size > 0) {\r\n logger?.warn({ count: activeRequests.size }, 'Force closing with active requests');\r\n }\r\n }\r\n\r\n clearInterval(cleanupInterval);\r\n\r\n if (config.onShutdown) {\r\n try {\r\n await config.onShutdown();\r\n } catch (e) {\r\n logger?.error({ error: String(e) }, 'Error in shutdown handler');\r\n }\r\n }\r\n\r\n for (const [name, db] of dbs.entries()) {\r\n try {\r\n if (db && typeof db.close === 'function') {\r\n db.close();\r\n }\r\n logger?.info({ name }, 'Database closed');\r\n } catch (e) {\r\n logger?.error({ error: String(e), name }, 'Error closing database');\r\n }\r\n }\r\n\r\n if (bunServer && typeof (bunServer as { stop?: () => void }).stop === 'function') {\r\n (bunServer as { stop: () => void }).stop();\r\n logger?.info('Bun server stopped');\r\n }\r\n\r\n logger?.info('Server stopped successfully');\r\n },\r\n\r\n addRoute(route: types.RouteDefinition) {\r\n routes.push(route);\r\n const methods = Array.isArray(route.method) ? route.method : [route.method];\r\n methods.forEach(m => {\r\n router.register(m, route.path, route.handler as types.RouteHandler, route);\r\n });\r\n logger?.info({ method: route.method, path: route.path }, 'Route added');\r\n },\r\n\r\n addRoutes(routes: types.RouteDefinition[]) {\r\n routes.forEach(route => this.addRoute(route));\r\n },\r\n\r\n getRoutes() {\r\n return routes;\r\n }\r\n };\r\n\r\n return instance;\r\n\t}\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ HELP ════════════════════════════════════════╗\r\n\r\n async function parseBody(\r\n request : Request,\r\n logger : Logger | null,\r\n maxSize : number\r\n ): Promise<unknown> {\r\n const contentType = request.headers.get('content-type') || '';\r\n\r\n try {\r\n if (contentType.includes('application/json')) {\r\n\t\t\t\tconst text = await request.text();\r\n\r\n\t\t\t\tif (text.length > maxSize) {\r\n\t\t\t\t\tthrow new types.ValidationError('Payload too large');\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (!text.trim()) return {};\r\n\r\n\t\t\t\ttry {\r\n\t\t\t\t\treturn JSON.parse(text);\r\n\t\t\t\t} catch (e) {\r\n\t\t\t\t\tlogger?.warn({\r\n\t\t\t\t\t\terror\t\t: String(e),\r\n\t\t\t\t\t\tbodyPreview\t: text.substring(0, 100)\r\n\t\t\t\t\t}, 'Invalid JSON in request body');\r\n\r\n\t\t\t\t\tthrow new types.ValidationError('Invalid JSON in request body');\r\n\t\t\t\t}\r\n }\r\n\r\n if (contentType.includes('application/x-www-form-urlencoded')) {\r\n const text = await request.text();\r\n if (text.length > maxSize) {\r\n throw new types.ValidationError('Payload too large');\r\n }\r\n return Object.fromEntries(new URLSearchParams(text));\r\n }\r\n\r\n if (contentType.includes('multipart/form-data')) {\r\n return await request.formData();\r\n }\r\n } catch (e) {\r\n if (e instanceof types.ValidationError) throw e;\r\n logger?.error({ error: String(e) }, 'Error parsing request body');\r\n throw new types.ValidationError('Failed to parse request body');\r\n }\r\n\r\n return {};\r\n }\r\n\r\n function parseCookies(cookieHeader: string): Map<string, string> {\r\n const cookies = new Map<string, string>();\r\n\r\n if (!cookieHeader) return cookies;\r\n\r\n const pairs = cookieHeader.split(';');\r\n for (const pair of pairs) {\r\n const [key, ...valueParts] = pair.trim().split('=');\r\n if (key) {\r\n const value = valueParts.join('=');\r\n cookies.set(key, value ? decodeURIComponent(value) : '');\r\n }\r\n }\r\n\r\n return cookies;\r\n }\r\n\r\n function createAppContext(\r\n ip : string,\r\n request : Request,\r\n params : Record<string, string>,\r\n db : sdb.DB | undefined,\r\n logger : Logger | null,\r\n requestId : string,\r\n i18nMgr : I18nManager | null = null,\r\n lang : string = 'en'\r\n ): types.AppContext {\r\n const url = new URL(request.url);\r\n const query = Object.fromEntries(url.searchParams);\r\n const headers = request.headers;\r\n let statusCode = 200;\r\n const cookieStore = new Map<string, string>();\r\n const parsedCookies = parseCookies(headers.get('cookie') || '');\r\n\r\n const ctx: types.AppContext = {\r\n ip,\r\n request,\r\n params,\r\n query,\r\n headers,\r\n db,\r\n logger,\r\n i18n: i18nMgr,\r\n lang,\r\n requestId,\r\n get statusCode() { return statusCode; },\r\n set statusCode(code: number) { statusCode = code; },\r\n body: null,\r\n state: {},\r\n\r\n json(data: unknown, status?: number): Response {\r\n return new Response(JSON.stringify(data), {\r\n status : status ?? statusCode,\r\n headers : {\r\n 'Content-Type': 'application/json',\r\n ...this._setCookieHeaders()\r\n }\r\n });\r\n },\r\n\r\n text(data: string, status?: number): Response {\r\n return new Response(data, {\r\n status : status ?? statusCode,\r\n headers : {\r\n 'Content-Type': 'text/plain',\r\n ...this._setCookieHeaders()\r\n }\r\n });\r\n },\r\n\r\n html(data: string, status?: number): Response {\r\n return new Response(data, {\r\n status : status ?? statusCode,\r\n headers : {\r\n 'Content-Type': 'text/html; charset=utf-8',\r\n ...this._setCookieHeaders()\r\n }\r\n });\r\n },\r\n\r\n redirect(url: string, status = 302): Response {\r\n return new Response(null, {\r\n status,\r\n headers : {\r\n Location : url,\r\n ...this._setCookieHeaders()\r\n }\r\n });\r\n },\r\n\r\n file(path: string, contentType = 'application/octet-stream'): Response {\r\n const file = Bun.file(path);\r\n return new Response(file, {\r\n headers: {\r\n 'Content-Type': contentType,\r\n ...this._setCookieHeaders()\r\n }\r\n });\r\n },\r\n\r\n setCookie(name: string, value: string, options: types.CookieOptions = {}): types.AppContext {\r\n let cookie = `${name}=${encodeURIComponent(value)}`;\r\n\r\n if (options.maxAge !== undefined) {\r\n cookie += `; Max-Age=${options.maxAge}`;\r\n }\r\n if (options.expires) {\r\n cookie += `; Expires=${options.expires.toUTCString()}`;\r\n }\r\n if (options.path) {\r\n cookie += `; Path=${options.path}`;\r\n }\r\n if (options.domain) {\r\n cookie += `; Domain=${options.domain}`;\r\n }\r\n if (options.secure) {\r\n cookie += '; Secure';\r\n }\r\n if (options.httpOnly) {\r\n cookie += '; HttpOnly';\r\n }\r\n if (options.sameSite) {\r\n cookie += `; SameSite=${options.sameSite}`;\r\n }\r\n\r\n cookieStore.set(name, cookie);\r\n return ctx;\r\n },\r\n\r\n getCookie(name: string): string | undefined {\r\n return parsedCookies.get(name);\r\n },\r\n\r\n deleteCookie(name: string, options: Partial<types.CookieOptions> = {}): types.AppContext {\r\n return ctx.setCookie(name, '', {\r\n ...options,\r\n maxAge: 0,\r\n path: options.path || '/'\r\n });\r\n },\r\n\r\n setHeader(key: string, value: string): types.AppContext {\r\n headers.set(key, value);\r\n return ctx;\r\n },\r\n\r\n getHeader(key: string): string | undefined {\r\n return headers.get(key) || undefined;\r\n },\r\n\r\n status(code: number): types.AppContext {\r\n statusCode = code;\r\n return ctx;\r\n },\r\n\r\n _setCookieHeaders(): Record<string, string | string[]> {\r\n const h: Record<string, string | string[]> = {};\r\n if (cookieStore.size > 0) {\r\n h['Set-Cookie'] = Array.from(cookieStore.values());\r\n }\r\n return h;\r\n }\r\n };\r\n\r\n return ctx;\r\n }\r\n\r\n function getClientIp(request: Request, server?: unknown): string {\r\n const forwarded = request.headers.get('x-forwarded-for');\r\n if (forwarded) {\r\n const ips = forwarded.split(',').map(ip => ip.trim());\r\n return ips[0] || 'unknown';\r\n }\r\n\r\n const realIp = request.headers.get('x-real-ip');\r\n if (realIp) return realIp;\r\n\r\n if (server) {\r\n try {\r\n const serverWithRequestIP = server as { requestIP?: (req: Request) => { address?: string } | null };\r\n const remoteAddress = serverWithRequestIP.requestIP?.(request);\r\n if (remoteAddress?.address) {\r\n return remoteAddress.address;\r\n }\r\n } catch {\r\n // Fallback if requestIP fails\r\n }\r\n }\r\n\r\n return 'unknown';\r\n }\r\n\r\n function handleCors(request: Request, config: types.ServerConfig): Headers {\r\n const headers = new Headers();\r\n\r\n if (!config.security || typeof config.security !== 'object' || !config.security.cors) {\r\n return headers;\r\n }\r\n\r\n const corsConfig = typeof config.security.cors === 'object' ? config.security.cors : {};\r\n const origin = request.headers.get('Origin');\r\n\r\n if (origin) {\r\n if (typeof corsConfig.origin === 'function') {\r\n if (corsConfig.origin(origin)) {\r\n headers.set('Access-Control-Allow-Origin', origin);\r\n }\r\n } else if (Array.isArray(corsConfig.origin)) {\r\n if (corsConfig.origin.includes(origin)) {\r\n headers.set('Access-Control-Allow-Origin', origin);\r\n }\r\n } else if (typeof corsConfig.origin === 'string') {\r\n headers.set('Access-Control-Allow-Origin', corsConfig.origin);\r\n } else {\r\n headers.set('Access-Control-Allow-Origin', origin);\r\n }\r\n\r\n const methods = corsConfig.methods || ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'];\r\n headers.set('Access-Control-Allow-Methods', methods.join(', '));\r\n\r\n const allowedHeaders = corsConfig.allowedHeaders || ['Content-Type', 'Authorization', 'X-Requested-With'];\r\n headers.set('Access-Control-Allow-Headers', allowedHeaders.join(', '));\r\n\r\n if (corsConfig.credentials) {\r\n headers.set('Access-Control-Allow-Credentials', 'true');\r\n }\r\n\r\n if (corsConfig.maxAge) {\r\n headers.set('Access-Control-Max-Age', corsConfig.maxAge.toString());\r\n }\r\n }\r\n\r\n return headers;\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ ════ ════════════════════════════════════════╗\r\n\r\n export * from './types';\r\n export { Logger };\r\n export { SecurityManager };\r\n export { Router };\r\n export {\r\n DB,\r\n table,\r\n column,\r\n integer,\r\n text,\r\n real,\r\n blob,\r\n numeric,\r\n primaryKey,\r\n notNull,\r\n unique,\r\n defaultValue,\r\n references,\r\n index\r\n } from '@minejs/db';\r\n export type {\r\n ColumnType,\r\n SqlValue,\r\n ColumnDefinition,\r\n TableSchema,\r\n WhereCondition,\r\n QueryBuilder\r\n } from '@minejs/db';\r\n export { StaticFileServer, createStatic } from './mod/static';\r\n export type { StaticConfig } from './mod/static';\r\n export {\r\n getI18n,\r\n t,\r\n tLang,\r\n tParse,\r\n setLanguage,\r\n getLanguage,\r\n getSupportedLanguages,\r\n loadLanguage,\r\n loadTranslations,\r\n setupI18n,\r\n setupLazy,\r\n setupAuto,\r\n fetchTranslations,\r\n I18nManager,\r\n LazyLoader\r\n } from '@minejs/i18n';\r\n export type { I18nConfig, TranslationSet, TranslationToken } from '@minejs/i18n';\r\n\r\n export default server;\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝"]}