@stacksjs/bun-router 0.1.11 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-7s1kcj7w.js +357 -0
- package/dist/{chunk-7g1et0fb.js → chunk-sccx6r6k.js} +16 -16
- package/dist/cli.js +1 -1
- package/dist/container/index.js +1 -1
- package/dist/crypto.d.ts +2 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +29 -29
- package/dist/request/context.d.ts +6 -0
- package/dist/response/compression.d.ts +11 -10
- package/dist/router/handler-resolver.d.ts +1 -1
- package/dist/router/router.d.ts +3 -5
- package/dist/types.d.ts +2 -0
- package/package.json +2 -2
- package/bin/cli.ts +0 -9
- package/dist/chunk-trm3jyqk.js +0 -357
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var Pe=Object.defineProperty;var Te=(t)=>t;function ke(t,i){this[t]=Te.bind(null,i)}var qe=(t,i)=>{for(var o in i)Pe(t,o,{get:i[o],enumerable:!0,configurable:!0,set:ke.bind(i,o)})};var Ie=import.meta.require;import Ae from"process";var me={verbose:!1,routesPath:"routes",apiRoutesPath:"routes/api.ts",webRoutesPath:"routes/web.ts",apiPrefix:"/api",webPrefix:"",defaultMiddleware:{api:["security","helmet","cors","rate_limit","json_body","request_id"],web:["security","helmet","ddos_protection","session","csrf"]},docs:{output:"api-reference.md",groupBy:"path",includeExamples:!0,title:"API Reference",description:"API documentation for the application.",version:"1.0.0",baseUrl:"http://localhost:3000",contact:{name:"API Support",email:"support@example.com",url:"https://example.com/support"},security:{bearer:{type:"http",scheme:"bearer",bearerFormat:"JWT"}}},server:{port:3000,hostname:"localhost",development:Ae.env.NODE_ENV!=="production",cors:{enabled:!0,origin:"*",methods:["GET","POST","PUT","DELETE","PATCH"],allowedHeaders:["Content-Type","Authorization"],exposedHeaders:["X-Request-Id"],credentials:!1,maxAge:86400},rateLimit:{enabled:!0,max:100,timeWindow:60000,message:"Too many requests, please try again later"},compression:{enabled:!0,level:6,threshold:1024},static:{enabled:!0,dir:"public",maxAge:86400},performance:{cache:{enabled:!1,type:"memory",ttl:3600},prefetch:{enabled:!1,paths:[],maxConcurrent:5},optimization:{minify:!1,compress:!1,treeshake:!1,lazyLoad:!1,chunkSize:50000},monitoring:{enabled:!1,metrics:{responseTime:!0,memoryUsage:!0,cpuUsage:!0,errorRate:!0,requestRate:!0,cacheStats:!0},tracing:{enabled:!1,sampleRate:0.1,exporters:["console"],propagation:["w3c"]},logging:{level:"info",format:"json",destination:"console"}}},security:{schemes:{},rateLimit:{enabled:!0,max:100,timeWindow:60000},cors:{enabled:!0,origin:"*",methods:["GET","POST","PUT","DELETE","PATCH"]},csrf:{enabled:!0,secret:"csrf-secret",cookie:{name:"csrf-token",options:{httpOnly:!0,secure:!0,sameSite:"strict"}}},helmet:{enabled:!0,contentSecurityPolicy:{directives:{"default-src":["'self'"],"script-src":["'self'","'unsafe-inline'"],"style-src":["'self'","'unsafe-inline'"],"img-src":["'self'","data:","https:"],"font-src":["'self'"],"connect-src":["'self'"],"media-src":["'self'"],"object-src":["'none'"],"child-src":["'self'"],"worker-src":["'self'"],"frame-ancestors":["'none'"],"form-action":["'self'"],"base-uri":["'self'"],"manifest-src":["'self'"]}},xssFilter:!0,noSniff:!0,frameOptions:"DENY",hidePoweredBy:!0,hsts:{maxAge:31536000,includeSubDomains:!0,preload:!0},referrerPolicy:"strict-origin-when-cross-origin"},ddos:{enabled:!0,maxRequestsPerSecond:10,maxRequestsPerMinute:100,maxRequestsPerHour:1000,burstLimit:20,windowSize:60000,blockDuration:300000,whitelistedIPs:[],blacklistedIPs:[],trustProxy:!0,store:"memory"},inputValidation:{enabled:!0,sanitizeByDefault:!0,strictMode:!1,allowUnknownFields:!0,maxDepth:10},attackPrevention:{enabled:!0,sqlInjection:!0,xss:!0,pathTraversal:!0,commandInjection:!0,ldapInjection:!0,xxe:!0,customPatterns:[]},requestFiltering:{enabled:!0,blockSuspiciousPatterns:!0,maxRequestsPerMinute:1000,blockUserAgents:["sqlmap","nikto","nessus","openvas","nmap","masscan","zap","w3af"],allowedMethods:["GET","POST","PUT","DELETE","PATCH","HEAD","OPTIONS"],requireUserAgent:!1,maxBodySize:10485760,maxUrlLength:2048,maxHeaderSize:8192,allowedContentTypes:["application/json","application/x-www-form-urlencoded","multipart/form-data","text/plain","text/html","application/xml","text/xml"]},ipFiltering:{enabled:!1,whitelist:[],blacklist:[],blockPrivateIPs:!1,blockCloudProviders:!1,geoBlocking:{enabled:!1,allowedCountries:[],blockedCountries:[]}},responseSecurity:{enabled:!0,removeServerHeaders:!0,addSecurityHeaders:!0,sanitizeErrors:!0,preventInfoDisclosure:!0},auth:{jwt:{secret:"jwt-secret",expiresIn:"1h",algorithm:"HS256"},session:{enabled:!1,secret:"session-secret",name:"session",resave:!1,rolling:!0,saveUninitialized:!1,cookie:{maxAge:86400000,secure:!0,httpOnly:!0,sameSite:"strict"}}}},cluster:{enabled:!1,workers:"auto",sticky:!0},gracefulShutdown:{enabled:!0,timeout:30000,signals:["SIGTERM","SIGINT"],forceTimeout:1e4},middleware:{order:[],global:[]},hooks:{}}},ie=null;async function wt(){if(!ie){let{loadConfig:t}=await import("./chunk-9y37n6xs.js");ie=await t({name:"router",defaultConfig:me})}return ie}var e=me;function ge(t){if(!t||!t.startsWith("Basic "))return null;try{let i=t.split(" ")[1],o=atob(i),[a,l]=o.split(":");return{username:a,password:l}}catch(i){return null}}function W(t){if(!t||!t.startsWith("Bearer "))return null;return t.split(" ")[1]}function fe(t,i="header",o="X-API-Key"){switch(i){case"header":return t.headers.get(o)||null;case"query":return new URL(t.url).searchParams.get(o);case"cookie":if(t.cookies){if(typeof t.cookies.get==="function")return t.cookies.get(o)||null;return t.cookies[o]||null}return null;default:return null}}class V{options;constructor(t){this.options={source:"header",key:"Authorization",attachUser:!0,...t}}async handle(t,i){let o=null;if(this.options.credentialsExtractor)o=await this.options.credentialsExtractor(t);else switch(this.options.type){case"basic":{let d=t.headers.get(this.options.key||"Authorization");o=ge(d||"");break}case"bearer":case"jwt":{let d=t.headers.get(this.options.key||"Authorization");o=W(d||"");break}case"api-key":{o=fe(t,this.options.source,this.options.key);break}case"oauth2":{let d=t.headers.get(this.options.key||"Authorization");o=W(d||"");break}}if(!o){let d={};if(this.options.type==="basic"){let p=this.options.realm||"Secure Area";d["WWW-Authenticate"]=`Basic realm="${p}"`}return new Response("Unauthorized",{status:401,headers:d})}if(!await this.options.validator(o,t))return new Response("Unauthorized",{status:401});if(this.options.userExtractor&&this.options.attachUser){let d=await this.options.userExtractor(o,t);t.user=d}return await i()||new Response("Not Found",{status:404})}}function He(t,i={}){return new V({type:"basic",validator:t,...i})}function Be(t,i={}){return new V({type:"bearer",validator:t,...i})}function je(t,i={}){return new V({type:"jwt",validator:t,...i})}function Ue(t,i={}){return new V({type:"api-key",validator:t,...i})}function Le(t,i={}){return new V({type:"oauth2",validator:t,...i})}var oe={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, POST, PUT, DELETE, PATCH, OPTIONS","Access-Control-Allow-Headers":"Content-Type, Authorization, X-Requested-With, Accept, Origin","Access-Control-Max-Age":"86400"};class h{resolveAllowOrigin(t,i,o){if(Array.isArray(t)){if(o&&t.includes(o))return{value:o,vary:!0};return{value:null,vary:!0}}let a=t||"*";if(a==="*"){if(i){if(o)return{value:o,vary:!0};return{value:null,vary:!0}}return{value:"*",vary:!1}}return{value:a,vary:!1}}getCorsHeaders(t){let i=e.server?.cors,o=t.headers.get("origin");if(i&&i.enabled){let a=Boolean(i.credentials),{value:l,vary:d}=this.resolveAllowOrigin(i.origin,a,o),p={"Access-Control-Allow-Methods":Array.isArray(i.methods)?i.methods.join(", "):oe["Access-Control-Allow-Methods"],"Access-Control-Allow-Headers":Array.isArray(i.allowedHeaders)?i.allowedHeaders.join(", "):oe["Access-Control-Allow-Headers"],"Access-Control-Max-Age":String(i.maxAge||86400)};if(l!==null)p["Access-Control-Allow-Origin"]=l;if(a&&l!==null&&l!=="*")p["Access-Control-Allow-Credentials"]="true";if(d)p.Vary="Origin";return p}return{...oe}}async handle(t,i){let o=this.getCorsHeaders(t);if(t.method==="OPTIONS")return new Response(null,{status:204,headers:o});let a=(l)=>{let d=new Headers(l.headers);return Object.entries(o).forEach(([p,x])=>{d.set(p,x)}),new Response(l.body,{status:l.status,statusText:l.statusText,headers:d})};try{let l=await i();if(!l)return new Response(JSON.stringify({error:"Not Found"}),{status:404,headers:{...o,"Content-Type":"application/json"}});return a(l)}catch(l){return console.error("[CORS] Error in middleware chain:",l),new Response(JSON.stringify({error:"Internal Server Error",message:l instanceof Error?l.message:String(l)}),{status:500,headers:{...o,"Content-Type":"application/json"}})}}}var Me;function s(){return Me??=Ie("crypto")}var Ce=1e4,Ee=7200000;class r{static tokens=new Map;async handle(t,i){let o=e.server?.security?.csrf??{},a=t.method.toUpperCase();if(["GET","HEAD","OPTIONS",...o?.ignoreMethods||[]].includes(a)){let M=this.generateToken(o?.secret||"csrf-secret"),C=await i();if(!C)return new Response("Not Found",{status:404});let U=o?.cookie?.name||"csrf-token",L=[];if(L.push(`${U}=${M}`),L.push("Path=/"),o?.cookie?.options?.httpOnly)L.push("HttpOnly");if(o?.cookie?.options?.secure)L.push("Secure");if(o?.cookie?.options?.sameSite)L.push(`SameSite=${o.cookie.options.sameSite}`);let z=new Headers(C.headers);return z.append("Set-Cookie",L.join("; ")),r.storeToken(M),new Response(C.body,{status:C.status,statusText:C.statusText,headers:z})}let d=t.headers.get("authorization")??t.headers.get("Authorization");if(d&&/^Bearer\s+\S/i.test(d))return await i()||new Response("Not Found",{status:404});let p=t.headers.get("X-CSRF-TOKEN")||t.jsonBody?.csrf_token||t.jsonBody?._token||null,x=typeof p==="string"?p:null,T=this.parseCookies(t)[o?.cookie?.name||"csrf-token"];if(!x||!T||!r.safeCompare(x,T)||!r.isTokenValid(x))return new Response(JSON.stringify({error:"CSRF token validation failed"}),{status:403,headers:{"Content-Type":"application/json"}});return await i()||new Response("Not Found",{status:404})}static safeCompare(t,i){let o=Buffer.from(t),a=Buffer.from(i);if(o.length!==a.length)return!1;return s().timingSafeEqual(o,a)}static storeToken(t){if(r.tokens.size>=Ce){let i=r.tokens.keys().next().value;if(i!==void 0)r.tokens.delete(i)}r.tokens.set(t,Date.now())}static isTokenValid(t){let i=r.tokens.get(t);if(i===void 0)return!1;if(Date.now()-i>Ee)return r.tokens.delete(t),!1;return!0}generateToken(t){let{createHash:i,randomBytes:o}=s(),a=o(16).toString("hex");return i("sha256").update(`${a}${t}`).digest("hex")}parseCookies(t){let i=t.headers.get("cookie");if(!i)return{};let o={};for(let a of i.split(";")){let l=a.indexOf("=");if(l===-1)continue;let d=a.slice(0,l).trim();if(!d)continue;o[d]=a.slice(l+1).trim()}return o}}class m{async handle(t,i){let o=t.headers.get("content-type");if(o&&o.includes("application/json"))try{let d=await t.clone().json();Object.defineProperty(t,"jsonBody",{value:d,writable:!0,enumerable:!0,configurable:!0})}catch{return new Response(JSON.stringify({error:"Invalid JSON payload"}),{status:400,headers:{"Content-Type":"application/json"}})}return await i()||new Response("Not Found",{status:404})}}function Ne(t={}){let i=new A(t);return async(a,l)=>i.handle(a,l)}class A{limiterPromise;options;constructor(t={}){let i=e.server?.rateLimit||{},o=e.server?.security?.rateLimit||{};if(this.options={windowMs:t.windowMs||i.timeWindow||o.timeWindow||60000,maxRequests:t.maxRequests||i.max||o.max||100,standardHeaders:t.standardHeaders??!0,legacyHeaders:t.legacyHeaders??!1,skipFailedRequests:t.skipFailedRequests??i.advanced?.skipFailedRequests??o.advanced?.skipFailedRequests??!1,draftMode:t.draftMode??!1,keyGenerator:t.keyGenerator,handler:t.handler||(i.message?(a,l)=>new Response(i.message,{status:429}):void 0),skip:t.skip,algorithm:t.algorithm||"fixed-window",storage:t.storage},!this.options.storage&&i.stores?.type==="redis"&&i.stores.redis){if(this.options.storage="redis",i.stores.redis)this.options.redis={url:i.stores.redis.url,prefix:i.stores.redis.prefix||"ratelimit:"}}if(i.advanced){if(i.advanced.tokensPerInterval&&this.options.algorithm==="token-bucket")this.options.tokenBucket={tokensPerInterval:i.advanced.tokensPerInterval,interval:i.advanced.interval||this.options.windowMs,burst:i.advanced.burst}}}getLimiter(){return this.limiterPromise??=this.initLimiter(),this.limiterPromise}async initLimiter(){let t={...this.options};t.windowMs=this.options.windowMs,t.maxRequests=this.options.maxRequests,t.standardHeaders=this.options.standardHeaders,t.legacyHeaders=this.options.legacyHeaders,t.skipFailedRequests=this.options.skipFailedRequests,t.keyGenerator=this.options.keyGenerator,t.skip=this.options.skip,t.algorithm=this.options.algorithm,t.draftMode=this.options.draftMode,t.handler=this.options.handler?async(a,l)=>this.options.handler?.(a,{remaining:l.remaining,limit:l.limit,resetTime:l.resetTime})||this.defaultHandler(a,l):void 0;let{log:i,warn:o}=console;console.log=()=>{},console.warn=()=>{};try{let{createRateLimiter:a}=await import("ts-rate-limiter");return await a(t)}finally{console.log=i,console.warn=o}}defaultHandler(t,i){let o={};if(this.options.standardHeaders)o["RateLimit-Limit"]=String(i.limit),o["RateLimit-Remaining"]=String(Math.max(0,i.limit-i.current)),o["RateLimit-Reset"]=String(Math.ceil(i.resetTime/1000));if(this.options.legacyHeaders)o["X-RateLimit-Limit"]=String(i.limit),o["X-RateLimit-Remaining"]=String(Math.max(0,i.limit-i.current)),o["X-RateLimit-Reset"]=String(Math.ceil(i.resetTime/1000)),o["Retry-After"]=String(Math.ceil(i.remaining/1000));let a=e.server?.rateLimit?.message||"Too Many Requests";return new Response(a,{status:429,headers:o})}async handle(t,i){if(e.server?.rateLimit?.enabled===!1)return await i()||new Response("Not Found",{status:404});try{let a=await(await this.getLimiter()).check(t);if(!a.allowed)return this.options.handler?await this.options.handler(t,{remaining:a.remaining,limit:a.limit,resetTime:a.resetTime}):this.defaultHandler(t,a);let l=await i();if(!l)return new Response("Not Found",{status:404});let d=new Headers(l.headers);if(this.options.standardHeaders)d.set("RateLimit-Limit",String(a.limit)),d.set("RateLimit-Remaining",String(Math.max(0,a.limit-a.current))),d.set("RateLimit-Reset",String(Math.ceil(a.resetTime/1000)));if(this.options.legacyHeaders)d.set("X-RateLimit-Limit",String(a.limit)),d.set("X-RateLimit-Remaining",String(Math.max(0,a.limit-a.current))),d.set("X-RateLimit-Reset",String(Math.ceil(a.resetTime/1000)));return new Response(l.body,{status:l.status,statusText:l.statusText,headers:d})}catch(o){return console.error("[RateLimit] Error during rate limiting:",o),await i()||new Response("Not Found",{status:404})}}}function G(t={}){return Ne(t)}class g{async handle(t,i){let o=t.headers.get("X-Request-ID")||s().randomUUID();Object.defineProperty(t,"requestId",{value:o,writable:!1,enumerable:!0,configurable:!1});let a=await i();if(!a)return new Response("Not Found",{status:404});let l=new Headers(a.headers);if(!l.has("X-Request-ID"))l.set("X-Request-ID",o);return new Response(a.body,{status:a.status,statusText:a.statusText,headers:l})}}class n extends Error{code;statusCode;constructor(t,i){super(i);this.name="SignatureError",this.code=t,this.statusCode=401}}class ye{nonces=new Map;cleanupInterval=null;constructor(t=60000){this.cleanupInterval=setInterval(()=>this.cleanup(),t),this.cleanupInterval.unref?.()}has(t){let i=this.nonces.get(t);if(i===void 0)return!1;if(Date.now()>i)return this.nonces.delete(t),!1;return!0}set(t,i=300){this.nonces.set(t,Date.now()+i*1000)}cleanup(){let t=Date.now();for(let[i,o]of this.nonces.entries())if(t>o)this.nonces.delete(i)}destroy(){if(this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null;this.nonces.clear()}}class f{options;constructor(t){this.options={secret:t.secret,algorithm:t.algorithm??"sha256",signatureHeader:t.signatureHeader??"X-Signature",timestampHeader:t.timestampHeader??"X-Timestamp",keyIdHeader:t.keyIdHeader??"X-Key-Id",nonceHeader:t.nonceHeader??"X-Nonce",maxAge:t.maxAge??300,requireTimestamp:t.requireTimestamp??!0,requireNonce:t.requireNonce??!1,signedParts:t.signedParts??["method","path","timestamp","body"],signedHeaders:t.signedHeaders??[],encoding:t.encoding??"hex",onError:t.onError,exclude:t.exclude,nonceStore:t.nonceStore,stringToSign:t.stringToSign}}async handle(t,i){if(this.shouldSkip(t))return i();try{return await this.verifySignature(t),i()}catch(o){if(o instanceof n){if(this.options.onError)return this.options.onError(o,t);return this.defaultErrorResponse(o)}throw o}}shouldSkip(t){if(!this.options.exclude)return!1;if(typeof this.options.exclude==="function")return this.options.exclude(t);let i=new URL(t.url);return this.options.exclude.some((o)=>i.pathname===o||i.pathname.startsWith(`${o}/`))}async verifySignature(t){let i=t.headers.get(this.options.signatureHeader);if(!i)throw new n("MISSING_SIGNATURE",`Missing ${this.options.signatureHeader} header`);let o=t.headers.get(this.options.timestampHeader);if(this.options.requireTimestamp){if(!o)throw new n("MISSING_TIMESTAMP",`Missing ${this.options.timestampHeader} header`);this.validateTimestamp(o)}let a=t.headers.get(this.options.nonceHeader);if(this.options.requireNonce){if(!a)throw new n("MISSING_NONCE",`Missing ${this.options.nonceHeader} header`);await this.validateNonce(a)}let l=await this.getSecret(t);if(!l)throw new n("INVALID_KEY","Invalid or missing API key");let d=await this.buildStringToSign(t,o||"",a||void 0),p=await this.calculateSignature(d,l);if(!this.timingSafeEqual(i,p))throw new n("SIGNATURE_MISMATCH","Invalid signature");if(this.options.requireNonce&&a&&this.options.nonceStore)await this.options.nonceStore.set(a,this.options.maxAge)}async getSecret(t){if(typeof this.options.secret==="string")return this.options.secret;let i=t.headers.get(this.options.keyIdHeader);if(!i)throw new n("MISSING_KEY_ID",`Missing ${this.options.keyIdHeader} header`);return this.options.secret(i)}validateTimestamp(t){let i=Number.parseInt(t,10);if(Number.isNaN(i))throw new n("EXPIRED_TIMESTAMP","Invalid timestamp format");let a=Math.floor(Date.now()/1000)-i;if(a>this.options.maxAge)throw new n("EXPIRED_TIMESTAMP",`Request timestamp expired (${a}s old, max ${this.options.maxAge}s)`);if(a<-30)throw new n("FUTURE_TIMESTAMP","Request timestamp is in the future")}async validateNonce(t){if(!this.options.nonceStore)return;if(await this.options.nonceStore.has(t))throw new n("NONCE_REUSED","Nonce has already been used (possible replay attack)")}async buildStringToSign(t,i,o){if(this.options.stringToSign)return this.options.stringToSign(t,i,o);let a=new URL(t.url),l=[];for(let d of this.options.signedParts)switch(d){case"method":l.push(t.method.toUpperCase());break;case"path":l.push(a.pathname);break;case"query":l.push(a.search);break;case"timestamp":l.push(i);break;case"nonce":if(o)l.push(o);break;case"body":if(t.body){let p=await t.clone().text();l.push(p)}break;case"headers":for(let p of this.options.signedHeaders){let x=t.headers.get(p);if(x)l.push(`${p.toLowerCase()}:${x}`)}break}return l.join(`
|
|
3
|
+
`)}async calculateSignature(t,i){let o=new TextEncoder,a=o.encode(i),l=o.encode(t),d={sha256:"SHA-256",sha384:"SHA-384",sha512:"SHA-512"}[this.options.algorithm],p=await crypto.subtle.importKey("raw",a,{name:"HMAC",hash:d},!1,["sign"]),x=await crypto.subtle.sign("HMAC",p,l);if(this.options.encoding==="base64")return btoa(String.fromCharCode(...new Uint8Array(x)));return Array.from(new Uint8Array(x)).map((P)=>P.toString(16).padStart(2,"0")).join("")}timingSafeEqual(t,i){if(t.length!==i.length)return!1;let o=0;for(let a=0;a<t.length;a++)o|=t.charCodeAt(a)^i.charCodeAt(a);return o===0}defaultErrorResponse(t){return new Response(JSON.stringify({error:{code:t.code,message:t.message}}),{status:t.statusCode,headers:{"Content-Type":"application/json","WWW-Authenticate":"HMAC-SHA256"}})}}function _e(t){return new f(t)}async function ze(t,i,o={}){let{algorithm:a="sha256",signedParts:l=["method","path","timestamp","body"],signedHeaders:d=[],signatureHeader:p="X-Signature",timestampHeader:x="X-Timestamp",nonceHeader:P="X-Nonce",keyId:T,keyIdHeader:k="X-Key-Id",encoding:M="hex"}=o,C=Math.floor(Date.now()/1000).toString(),U=crypto.randomUUID(),L=new URL(t.url),z=[];for(let ne of l)switch(ne){case"method":z.push(t.method.toUpperCase());break;case"path":z.push(L.pathname);break;case"query":z.push(L.search);break;case"timestamp":z.push(C);break;case"nonce":z.push(U);break;case"body":if(t.body){let Z=await t.clone().text();z.push(Z)}break;case"headers":for(let Z of d){let pe=t.headers.get(Z);if(pe)z.push(`${Z.toLowerCase()}:${pe}`)}break}let we=z.join(`
|
|
4
|
+
`),de=new TextEncoder,ve=de.encode(i),Se=de.encode(we),xe={sha256:"SHA-256",sha384:"SHA-384",sha512:"SHA-512"}[a],Re=await crypto.subtle.importKey("raw",ve,{name:"HMAC",hash:xe},!1,["sign"]),ue=await crypto.subtle.sign("HMAC",Re,Se),re;if(M==="base64")re=btoa(String.fromCharCode(...new Uint8Array(ue)));else re=Array.from(new Uint8Array(ue)).map((ne)=>ne.toString(16).padStart(2,"0")).join("");let Q=new Headers(t.headers);if(Q.set(p,re),Q.set(x,C),Q.set(P,U),T)Q.set(k,T);return new Request(t.url,{method:t.method,headers:Q,body:t.body,redirect:t.redirect,integrity:t.integrity,signal:t.signal})}async function Ve(t,i,o,a="sha256",l="hex"){let d=new TextEncoder,p=d.encode(o),x=d.encode(t),P={sha256:"SHA-256",sha384:"SHA-384",sha512:"SHA-512"}[a],T=await crypto.subtle.importKey("raw",p,{name:"HMAC",hash:P},!1,["sign"]),k=await crypto.subtle.sign("HMAC",T,x),M;if(l==="base64")M=btoa(String.fromCharCode(...new Uint8Array(k)));else M=Array.from(new Uint8Array(k)).map((U)=>U.toString(16).padStart(2,"0")).join("");if(i.length!==M.length)return!1;let C=0;for(let U=0;U<i.length;U++)C|=i.charCodeAt(U)^M.charCodeAt(U);return C===0}class u{defaultTtl;sessions=new Map;cleanupInterval=null;constructor(t=86400){this.defaultTtl=t;this.cleanupInterval=setInterval(()=>this.cleanup(),300000)}async get(t){let i=this.sessions.get(t);if(!i)return null;if(Date.now()>i.expiresAt)return this.sessions.delete(t),null;return i.data}async set(t,i,o){let a=Date.now()+(o??this.defaultTtl)*1000;this.sessions.set(t,{data:i,expiresAt:a})}async destroy(t){this.sessions.delete(t)}async touch(t,i,o){let a=this.sessions.get(t);if(a)a.expiresAt=Date.now()+(o??this.defaultTtl)*1000,a.data=i}async all(){let t={},i=Date.now();for(let[o,a]of this.sessions)if(i<=a.expiresAt)t[o]=a.data;return t}async length(){return this.sessions.size}async clear(){this.sessions.clear()}cleanup(){let t=Date.now();for(let[i,o]of this.sessions)if(t>o.expiresAt)this.sessions.delete(i)}dispose(){if(this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null;this.sessions.clear()}}import{existsSync as ee,mkdirSync as Fe,readdirSync as te,unlinkSync as se,writeFileSync as he,readFileSync as ae}from"fs";import{join as Y}from"path";import{tmpdir as De}from"os";class O{defaultTtl;dir;cleanupInterval=null;constructor(t=86400,i){this.defaultTtl=t;if(this.dir=i||Y(De(),"bun-router-sessions"),!ee(this.dir))Fe(this.dir,{recursive:!0});this.cleanupInterval=setInterval(()=>this.cleanup(),600000)}filePath(t){let i=t.replace(/[^a-zA-Z0-9_-]/g,"");return Y(this.dir,`${i}.json`)}async get(t){let i=this.filePath(t);if(!ee(i))return null;try{let o=ae(i,"utf-8"),a=JSON.parse(o);if(Date.now()>a.expiresAt)return se(i),null;return a.data}catch{return null}}async set(t,i,o){let a={data:i,expiresAt:Date.now()+(o??this.defaultTtl)*1000};he(this.filePath(t),JSON.stringify(a),"utf-8")}async destroy(t){let i=this.filePath(t);if(ee(i))se(i)}async touch(t,i,o){let a=this.filePath(t);if(!ee(a))return;let l={data:i,expiresAt:Date.now()+(o??this.defaultTtl)*1000};he(a,JSON.stringify(l),"utf-8")}async all(){let t={},i=Date.now();try{let o=te(this.dir).filter((a)=>a.endsWith(".json"));for(let a of o){let l=ae(Y(this.dir,a),"utf-8"),d=JSON.parse(l);if(i<=d.expiresAt){let p=a.replace(".json","");t[p]=d.data}}}catch{}return t}async length(){try{return te(this.dir).filter((t)=>t.endsWith(".json")).length}catch{return 0}}async clear(){try{let t=te(this.dir).filter((i)=>i.endsWith(".json"));for(let i of t)se(Y(this.dir,i))}catch{}}cleanup(){let t=Date.now();try{let i=te(this.dir).filter((o)=>o.endsWith(".json"));for(let o of i){let a=Y(this.dir,o),l=ae(a,"utf-8"),d=JSON.parse(l);if(t>d.expiresAt)se(a)}}catch{}}dispose(){if(this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null}}class I{client;defaultTtl;prefix;constructor(t,i=86400,o="sess:"){this.client=t;this.defaultTtl=i;this.prefix=o}key(t){return`${this.prefix}${t}`}async get(t){let i=await this.client.get(this.key(t));if(!i)return null;try{return JSON.parse(i)}catch{return null}}async set(t,i,o){let a=this.key(t),l=o??this.defaultTtl;await this.client.set(a,JSON.stringify(i),"EX",l)}async destroy(t){await this.client.del(this.key(t))}async touch(t,i,o){let a=this.key(t),l=o??this.defaultTtl;await this.client.set(a,JSON.stringify(i),"EX",l)}async all(){let t=await this.client.keys(`${this.prefix}*`),i={};for(let o of t){let a=await this.client.get(o);if(a)try{let l=o.slice(this.prefix.length);i[l]=JSON.parse(a)}catch{}}return i}async length(){return(await this.client.keys(`${this.prefix}*`)).length}async clear(){let t=await this.client.keys(`${this.prefix}*`);if(t.length>0)await this.client.del(t)}}class F{adapter;defaultTtl;cleanupInterval=null;constructor(t,i=86400){this.adapter=t;this.defaultTtl=i;this.cleanupInterval=setInterval(()=>{let o=Date.now()-this.defaultTtl*1000;this.adapter.deleteExpiredSessions(o)},1800000)}async get(t){let i=await this.adapter.findSession(t);if(!i)return null;let o=Date.now()-this.defaultTtl*1000;if(i.last_activity<o)return await this.adapter.deleteSession(t),null;try{return JSON.parse(i.payload)}catch{return null}}async set(t,i,o){await this.adapter.upsertSession(t,JSON.stringify(i),Date.now())}async destroy(t){await this.adapter.deleteSession(t)}async touch(t,i,o){await this.adapter.upsertSession(t,JSON.stringify(i),Date.now())}async all(){let t=await this.adapter.getAllSessions(),i={},o=Date.now()-this.defaultTtl*1000;for(let a of t)if(a.last_activity>=o)try{i[a.id]=JSON.parse(a.payload)}catch{}return i}async length(){return this.adapter.countSessions()}async clear(){await this.adapter.clearAllSessions()}dispose(){if(this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null}}function bt(t){let i=t.ttl??86400;switch(t.driver){case"memory":return new u(i);case"file":return new O(i,t.file?.dir);case"redis":{if(!t.redis?.client)throw Error("Redis client is required for redis session driver");return new I(t.redis.client,i,t.redis.prefix)}case"database":{if(!t.database?.adapter)throw Error("Database adapter is required for database session driver");return new F(t.database.adapter,i)}default:return new u(i)}}class K{sessionId;data;store;flashedKeys=[];previousFlash={};dirty=!1;constructor(t,i,o){this.sessionId=t,this.data=i,this.store=o,this.previousFlash={...i.flash||{}}}get id(){return this.sessionId}get(t){if(this.data.flash&&t in this.data.flash)return this.data.flash[t];if(this.data.data&&t in this.data.data)return this.data.data[t];return}set(t,i){if(!this.data.data)this.data.data={};this.data.data[t]=i,this.dirty=!0}has(t){return this.data.data&&t in this.data.data||this.data.flash&&t in this.data.flash||!1}forget(t){if(this.data.data)delete this.data.data[t],this.dirty=!0}all(){return{...this.data.data||{},...this.data.flash||{}}}flash(t,i){if(!this.data.flash)this.data.flash={};this.data.flash[t]=i,this.flashedKeys.push(t),this.dirty=!0}getFlash(t){return this.previousFlash[t]}keep(t){for(let i of t)if(i in this.previousFlash)this.flash(i,this.previousFlash[i])}reflash(){for(let[t,i]of Object.entries(this.previousFlash))this.flash(t,i)}async regenerate(){let t=this.sessionId;return this.sessionId=D(),await this.store.set(this.sessionId,this.data),await this.store.destroy(t),this.sessionId}async invalidate(){let t=this.sessionId;return this.sessionId=D(),this.data={id:this.sessionId},await this.store.destroy(t),await this.store.set(this.sessionId,this.data),this.sessionId}async save(){if(this.data.flash){let t={};for(let i of this.flashedKeys)if(this.data.flash[i]!==void 0)t[i]=this.data.flash[i];this.data.flash=Object.keys(t).length>0?t:void 0}await this.store.set(this.sessionId,this.data)}async destroy(){await this.store.destroy(this.sessionId),this.data={}}}function D(){let t=new Uint8Array(32);return crypto.getRandomValues(t),Array.from(t,(i)=>i.toString(16).padStart(2,"0")).join("")}class y{store;constructor(t){this.store=t?.store||new u}async handle(t,i){let o=e.server?.security?.auth?.session,a=o?.name||"session",l=t.cookies?.get(a)||"",d=!1;if(!l)l=D(),d=!0;let p=d?null:await this.store.get(l);if(!p)p={id:l},d=!0;let x=new K(l,p,this.store);t.session=x;let P=await i();await x.save();let T={maxAge:o?.cookie?.maxAge||86400000,path:o?.cookie?.path||"/"};if(o?.cookie?.httpOnly!==!1)T.httpOnly=!0;if(o?.cookie?.secure)T.secure=!0;if(o?.cookie?.sameSite)T.sameSite=o.cookie.sameSite;if(!t._cookiesToSet)t._cookiesToSet=[];return t._cookiesToSet.push({name:a,value:x.id,options:T}),P||new Response("Not Found",{status:404})}}class w{options;nonces=new Map;constructor(t={}){let i=e.server?.security?.helmet?.contentSecurityPolicy,o={"default-src":["'self'"],"script-src":["'self'"],"style-src":["'self'"],"img-src":["'self'","data:","https:"],"font-src":["'self'"],"connect-src":["'self'"],"media-src":["'self'"],"object-src":["'none'"],"child-src":["'self'"],"worker-src":["'self'"],"frame-ancestors":["'none'"],"form-action":["'self'"],"base-uri":["'self'"],"manifest-src":["'self'"]};this.options={directives:t.directives||typeof i==="object"&&i.directives||o,reportOnly:t.reportOnly??(typeof i==="object"&&i.reportOnly)??!1,reportUri:t.reportUri,reportTo:t.reportTo,useNonces:t.useNonces??!1,nonceLength:t.nonceLength??16,upgradeInsecureRequests:t.upgradeInsecureRequests??!0,blockAllMixedContent:t.blockAllMixedContent??!1}}generateNonce(){let i="";for(let o=0;o<(this.options.nonceLength||16);o++)i+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(Math.floor(Math.random()*64));return i}buildCSPHeader(){let t=[],i=this.options.directives||{};for(let[o,a]of Object.entries(i)){if(o==="upgrade-insecure-requests"||o==="block-all-mixed-content"||o==="disown-opener"){if(a===!0)t.push(o.replace(/([A-Z])/g,"-$1").toLowerCase());continue}if(Array.isArray(a)&&a.length>0){let l=o.replace(/([A-Z])/g,"-$1").toLowerCase();t.push(`${l} ${a.join(" ")}`)}}if(this.options.upgradeInsecureRequests)t.push("upgrade-insecure-requests");if(this.options.blockAllMixedContent)t.push("block-all-mixed-content");if(this.options.reportUri)t.push(`report-uri ${this.options.reportUri}`);if(this.options.reportTo)t.push(`report-to ${this.options.reportTo}`);return t.join("; ")}async handle(t,i){if((e.server?.security?.helmet||{}).contentSecurityPolicy===!1)return await i()||new Response("Not Found",{status:404});let a;if(this.options.useNonces){if(a=this.generateNonce(),this.nonces.set(t.url,a),this.options.directives?.["script-src"])this.options.directives["script-src"]=[...this.options.directives["script-src"],`'nonce-${a}'`];if(this.options.directives?.["style-src"])this.options.directives["style-src"]=[...this.options.directives["style-src"],`'nonce-${a}'`]}if(a)t.nonce=a;let l=await i();if(!l)return new Response("Not Found",{status:404});let d=new Headers(l.headers),p=this.buildCSPHeader();if(p){let x=this.options.reportOnly?"Content-Security-Policy-Report-Only":"Content-Security-Policy";d.set(x,p)}if(this.options.reportTo)d.set("Report-To",JSON.stringify({group:this.options.reportTo,max_age:10886400,endpoints:[{url:this.options.reportUri||"/csp-report"}]}));if(a)this.nonces.delete(t.url);return new Response(l.body,{status:l.status,statusText:l.statusText,headers:d})}getNonce(t){return this.nonces.get(t)}}function We(t={}){let i=new w(t);return async(o,a)=>i.handle(o,a)}class b{options;requestStore=new Map;cleanupInterval=null;constructor(t={}){let i=e.server?.security?.ddos||{};if(this.options={enabled:t.enabled??i.enabled??!0,maxRequestsPerSecond:t.maxRequestsPerSecond??i.maxRequestsPerSecond??10,maxRequestsPerMinute:t.maxRequestsPerMinute??i.maxRequestsPerMinute??100,maxRequestsPerHour:t.maxRequestsPerHour??i.maxRequestsPerHour??1000,burstLimit:t.burstLimit??i.burstLimit??20,windowSize:t.windowSize??i.windowSize??60000,blockDuration:t.blockDuration??i.blockDuration??300000,whitelistedIPs:t.whitelistedIPs??i.whitelistedIPs??[],blacklistedIPs:t.blacklistedIPs??i.blacklistedIPs??[],trustProxy:t.trustProxy??i.trustProxy??!0,skipSuccessfulRequests:t.skipSuccessfulRequests??i.skipSuccessfulRequests??!1,skipFailedRequests:t.skipFailedRequests??i.skipFailedRequests??!1,keyGenerator:t.keyGenerator??this.defaultKeyGenerator.bind(this),onLimitReached:t.onLimitReached,store:t.store??i.store??"memory",redis:t.redis??i.redis},this.options.store==="memory")this.startCleanupInterval()}defaultKeyGenerator(t){let i=t.headers.get("x-forwarded-for"),o=t.headers.get("x-real-ip"),a=t.headers.get("cf-connecting-ip");if(this.options.trustProxy&&i)return i.split(",")[0].trim();return o||a||"unknown"}startCleanupInterval(){this.cleanupInterval=setInterval(()=>{let t=Date.now();for(let[i,o]of this.requestStore.entries()){if(t-o.lastRequest>this.options.windowSize*2)this.requestStore.delete(i);if(o.blocked&&o.blockExpires&&t>o.blockExpires)o.blocked=!1,o.blockExpires=void 0}},this.options.windowSize/2),this.cleanupInterval.unref?.()}isWhitelisted(t){return this.options.whitelistedIPs?.includes(t)??!1}isBlacklisted(t){return this.options.blacklistedIPs?.includes(t)??!1}getRateLimitInfo(t,i){let o=this.requestStore.get(t);if(!o){if(this.requestStore.size>=1e5){let a=Math.ceil(this.requestStore.size/10);for(let l of this.requestStore.keys())if(this.requestStore.delete(l),--a<=0)break}o={count:0,firstRequest:i,lastRequest:i,blocked:!1},this.requestStore.set(t,o)}if(i-o.firstRequest>this.options.windowSize)o.count=0,o.firstRequest=i;return o}shouldBlock(t,i){if(t.blocked&&t.blockExpires&&i<t.blockExpires)return!0;let o=1000;if(t.count>this.options.burstLimit)return!0;if(t.count>this.options.maxRequestsPerMinute)return!0;return!1}blockIP(t,i){t.blocked=!0,t.blockExpires=i+this.options.blockDuration}createBlockedResponse(t,i){let o=Math.ceil((i.blockExpires-Date.now())/1000),a={"Retry-After":o.toString(),"X-RateLimit-Limit":this.options.maxRequestsPerMinute.toString(),"X-RateLimit-Remaining":"0","X-RateLimit-Reset":Math.ceil(i.blockExpires/1000).toString()};if(this.options.onLimitReached)return this.options.onLimitReached(t,{...i,retryAfter:o});return new Response(JSON.stringify({error:"Too Many Requests",message:"Rate limit exceeded. Please try again later.",retryAfter:o}),{status:429,headers:{"Content-Type":"application/json",...a}})}async handle(t,i){if(!this.options.enabled)return await i()||new Response("Not Found",{status:404});let o=Date.now(),a=this.options.keyGenerator(t);if(this.isWhitelisted(a))return await i()||new Response("Not Found",{status:404});if(this.isBlacklisted(a))return new Response("Access Denied",{status:403});let l=this.getRateLimitInfo(a,o);if(this.shouldBlock(l,o))return this.blockIP(l,o),this.createBlockedResponse(t,l);l.count++,l.lastRequest=o;let d=await i();if(!d)return new Response("Not Found",{status:404});if(this.options.skipSuccessfulRequests&&d.status<400)l.count--;if(this.options.skipFailedRequests&&d.status>=400)l.count--;let p=new Headers(d.headers);return p.set("X-RateLimit-Limit",this.options.maxRequestsPerMinute.toString()),p.set("X-RateLimit-Remaining",Math.max(0,this.options.maxRequestsPerMinute-l.count).toString()),p.set("X-RateLimit-Reset",Math.ceil((l.firstRequest+this.options.windowSize)/1000).toString()),new Response(d.body,{status:d.status,statusText:d.statusText,headers:p})}destroy(){if(this.cleanupInterval)clearInterval(this.cleanupInterval),this.cleanupInterval=null;this.requestStore.clear()}}function Ge(t={}){let i=new b(t);return async(o,a)=>i.handle(o,a)}class S{config;FILE_SIGNATURES={"image/jpeg":[new Uint8Array([255,216,255])],"image/png":[new Uint8Array([137,80,78,71,13,10,26,10])],"image/gif":[new Uint8Array([71,73,70,56,55,97]),new Uint8Array([71,73,70,56,57,97])],"application/pdf":[new Uint8Array([37,80,68,70])],"application/zip":[new Uint8Array([80,75,3,4]),new Uint8Array([80,75,5,6]),new Uint8Array([80,75,7,8])]};EXECUTABLE_EXTENSIONS=[".exe",".bat",".cmd",".com",".pif",".scr",".vbs",".js",".jar",".app",".deb",".pkg",".dmg",".sh",".ps1",".msi",".dll"];constructor(t={}){this.config={scanForMalware:t.scanForMalware??!1,checkMagicNumbers:t.checkMagicNumbers??!0,sanitizeFilenames:t.sanitizeFilenames??!0,preventExecutableUploads:t.preventExecutableUploads??!0,maxFilenameLength:t.maxFilenameLength??255}}validateFile(t){let i=[];if(t.originalName.length>this.config.maxFilenameLength)i.push(`Filename too long (max ${this.config.maxFilenameLength} characters)`);if(this.config.sanitizeFilenames){let o=this.sanitizeFilename(t.originalName);if(!o||o.length===0)i.push("Filename is invalid or empty after sanitization")}if(this.config.preventExecutableUploads){let o=this.getFileExtension(t.originalName).toLowerCase();if(this.EXECUTABLE_EXTENSIONS.includes(o))i.push("Executable files are not allowed")}if(this.config.checkMagicNumbers){if(!this.validateFileSignature(t))i.push("File signature does not match declared MIME type")}if(this.config.scanForMalware){if(this.basicMalwareScan(t))i.push("Potential malware detected")}return{isValid:i.length===0,errors:i}}validateFileSignature(t){let i=this.FILE_SIGNATURES[t.mimetype];if(!i)return!0;let o=new Uint8Array(t.buffer.slice(0,16));return i.some((a)=>{if(o.length<a.length)return!1;for(let l=0;l<a.length;l++)if(o[l]!==a[l])return!1;return!0})}sanitizeFilename(t){return t.replace(/[<>:"/\\|?*\u0000-\u001F]/u,"_").replace(/^\.+/,"").replace(/\.+$/,"").replace(/\s+/g,"_").substring(0,this.config.maxFilenameLength)}getFileExtension(t){let i=t.lastIndexOf(".");return i===-1?"":t.substring(i)}basicMalwareScan(t){let i=new Uint8Array(t.buffer),o=new TextDecoder("utf-8",{fatal:!1}).decode(i);return[/eval\s*\(/gi,/document\.write/gi,/window\.location/gi,/<script[^>]*>/gi,/javascript:/gi,/vbscript:/gi,/onload\s*=/gi,/onerror\s*=/gi].some((l)=>l.test(o))}getSafeFilename(t){return this.sanitizeFilename(t)}isAllowedFileType(t,i){if(i.length===0)return!0;return i.includes(t)}isWithinSizeLimit(t,i){return t<=i}}import{existsSync as Oe,mkdirSync as $e,writeFileSync as ot}from"fs";import{basename as at,extname as be,join as ct}from"path";class c{config;fileSecurity;constructor(t={}){if(this.config={destination:t.destination||"./uploads",maxFileSize:t.maxFileSize||10485760,maxFiles:t.maxFiles||10,allowedMimeTypes:t.allowedMimeTypes||[],allowedExtensions:t.allowedExtensions||[],preserveOriginalName:t.preserveOriginalName??!1,generateUniqueFilename:t.generateUniqueFilename??!0,createDestination:t.createDestination??!0,scanForMalware:t.scanForMalware??!1,checkMagicNumbers:t.checkMagicNumbers??!0,sanitizeFilenames:t.sanitizeFilenames??!0,preventExecutableUploads:t.preventExecutableUploads??!0,maxFilenameLength:t.maxFilenameLength??255},this.fileSecurity=new S(t),this.config.createDestination&&!Oe(this.config.destination))$e(this.config.destination,{recursive:!0})}async handle(t,i){let o=t.headers.get("content-type");if(!o||!o.includes("multipart/form-data"))return await i()||new Response("Not Found",{status:404});try{let a=await t.formData(),l=[],d={};for(let[x,P]of a.entries())if(P instanceof File){if(l.length>=this.config.maxFiles)return this.createErrorResponse(`Maximum ${this.config.maxFiles} files allowed`,400);if(P.size>this.config.maxFileSize)return this.createErrorResponse(`File ${P.name} exceeds maximum size of ${this.formatBytes(this.config.maxFileSize)}`,413);if(this.config.allowedMimeTypes.length>0){let z=P.type.split(";")[0];if(!this.config.allowedMimeTypes.includes(z))return this.createErrorResponse(`File type ${z} not allowed. Allowed types: ${this.config.allowedMimeTypes.join(", ")}`,415)}let T=be(P.name).toLowerCase();if(this.config.allowedExtensions.length>0&&!this.config.allowedExtensions.includes(T))return this.createErrorResponse(`File extension ${T} not allowed. Allowed extensions: ${this.config.allowedExtensions.join(", ")}`,415);let k=this.generateFilename(P.name),M=ct(this.config.destination,k),C=await P.arrayBuffer(),U={fieldName:x,originalName:P.name,filename:k,path:M,size:P.size,mimetype:P.type,buffer:C},L=this.fileSecurity.validateFile(U);if(!L.isValid)return this.createErrorResponse(`Security validation failed: ${L.errors.join(", ")}`,400);ot(M,new Uint8Array(C)),l.push(U)}else if(d[x])if(Array.isArray(d[x]))d[x].push(P);else d[x]=[d[x],P];else d[x]=P;return Object.defineProperty(t,"files",{value:l,writable:!0,enumerable:!0,configurable:!0}),Object.defineProperty(t,"file",{value:(x)=>l.find((P)=>P.fieldName===x)??null,writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(t,"formBody",{value:d,writable:!0,enumerable:!0,configurable:!0}),await i()||new Response("Not Found",{status:404})}catch(a){return this.createErrorResponse(`File upload failed: ${a instanceof Error?a.message:"Unknown error"}`,500)}}generateFilename(t){let i=this.fileSecurity.getSafeFilename(t);if(this.config.preserveOriginalName&&!this.config.generateUniqueFilename)return i;let o=be(i),a=at(i,o);if(this.config.generateUniqueFilename){let l=s().randomUUID();return this.config.preserveOriginalName?`${a}_${l}${o}`:`${l}${o}`}return i}formatBytes(t){if(t===0)return"0 Bytes";let i=1024,o=["Bytes","KB","MB","GB"],a=Math.floor(Math.log(t)/Math.log(i));return`${Number.parseFloat((t/i**a).toFixed(2))} ${o[a]}`}createErrorResponse(t,i){return new Response(JSON.stringify({error:t}),{status:i,headers:{"Content-Type":"application/json"}})}}function Ke(t={}){return new c(t)}function Je(t,i={}){return new c({...i,maxFiles:1})}function Xe(t=10,i={}){return new c({...i,maxFiles:t})}function Ye(t={}){return new c({...t,allowedMimeTypes:["image/jpeg","image/jpg","image/png","image/gif","image/webp","image/svg+xml"],allowedExtensions:[".jpg",".jpeg",".png",".gif",".webp",".svg"]})}function Qe(t={}){return new c({...t,allowedMimeTypes:["application/pdf","application/msword","application/vnd.openxmlformats-officedocument.wordprocessingml.document","text/plain"],allowedExtensions:[".pdf",".doc",".docx",".txt"]})}class E{options;constructor(t={}){let i=e.server?.security?.helmet||{};this.options={contentSecurityPolicy:t.contentSecurityPolicy??i.contentSecurityPolicy??{directives:{"default-src":["'self'"],"script-src":["'self'","'unsafe-inline'"],"style-src":["'self'","'unsafe-inline'"],"img-src":["'self'","data:","https:"],"font-src":["'self'"],"connect-src":["'self'"],"media-src":["'self'"],"object-src":["'none'"],"child-src":["'self'"],"worker-src":["'self'"],"frame-ancestors":["'none'"],"form-action":["'self'"],"base-uri":["'self'"],"manifest-src":["'self'"]}},crossOriginEmbedderPolicy:t.crossOriginEmbedderPolicy??!0,crossOriginOpenerPolicy:t.crossOriginOpenerPolicy??!0,crossOriginResourcePolicy:t.crossOriginResourcePolicy??!0,dnsPrefetchControl:t.dnsPrefetchControl??!0,expectCt:t.expectCt??i.expectCt??!1,frameguard:t.frameguard??{action:i.frameOptions?.toLowerCase()||"deny"},hidePoweredBy:t.hidePoweredBy??i.hidePoweredBy??!0,hsts:t.hsts??i.hsts??{maxAge:31536000,includeSubDomains:!0,preload:!0},ieNoOpen:t.ieNoOpen??!0,noSniff:t.noSniff??i.noSniff??!0,originAgentCluster:t.originAgentCluster??!0,permittedCrossDomainPolicies:t.permittedCrossDomainPolicies??{permittedPolicies:"none"},referrerPolicy:t.referrerPolicy??i.referrerPolicy??{policy:"strict-origin-when-cross-origin"},xssFilter:t.xssFilter??i.xssFilter??!0}}async handle(t,i){if((e.server?.security?.helmet||{}).enabled===!1)return await i()||new Response("Not Found",{status:404});let a=await i();if(!a)return new Response("Not Found",{status:404});let l=new Headers(a.headers);if(this.options.contentSecurityPolicy){let d=this.options.contentSecurityPolicy;if(typeof d==="object"&&d.directives){let p=Object.entries(d.directives).map(([P,T])=>`${P} ${T.join(" ")}`).join("; "),x=d.reportOnly?"Content-Security-Policy-Report-Only":"Content-Security-Policy";if(l.set(x,p),d.reportUri)l.set("Report-To",JSON.stringify({group:"csp-endpoint",max_age:10886400,endpoints:[{url:d.reportUri}]}))}}if(this.options.crossOriginEmbedderPolicy){let d=this.options.crossOriginEmbedderPolicy,p=typeof d==="object"?d.policy||"require-corp":"require-corp";l.set("Cross-Origin-Embedder-Policy",p)}if(this.options.crossOriginOpenerPolicy){let d=this.options.crossOriginOpenerPolicy,p=typeof d==="object"?d.policy||"same-origin":"same-origin";l.set("Cross-Origin-Opener-Policy",p)}if(this.options.crossOriginResourcePolicy){let d=this.options.crossOriginResourcePolicy,p=typeof d==="object"?d.policy||"same-origin":"same-origin";l.set("Cross-Origin-Resource-Policy",p)}if(this.options.dnsPrefetchControl){let d=this.options.dnsPrefetchControl,p=typeof d==="object"?d.allow:!1;l.set("X-DNS-Prefetch-Control",p?"on":"off")}if(this.options.expectCt){let d=this.options.expectCt;if(typeof d==="object"){let p=[];if(d.enforce)p.push("enforce");if(d.maxAge)p.push(`max-age=${d.maxAge}`);if(d.reportUri)p.push(`report-uri="${d.reportUri}"`);l.set("Expect-CT",p.join(", "))}}if(this.options.frameguard){let d=this.options.frameguard;if(typeof d==="object"){let p=d.action||"deny",x=p==="sameorigin"&&d.domain?`ALLOW-FROM ${d.domain}`:p.toUpperCase();l.set("X-Frame-Options",x)}}if(this.options.hidePoweredBy)l.delete("X-Powered-By");if(this.options.hsts){let d=this.options.hsts;if(typeof d==="object"){let p=[`max-age=${d.maxAge||31536000}`];if(d.includeSubDomains)p.push("includeSubDomains");if(d.preload)p.push("preload");l.set("Strict-Transport-Security",p.join("; "))}}if(this.options.ieNoOpen)l.set("X-Download-Options","noopen");if(this.options.noSniff)l.set("X-Content-Type-Options","nosniff");if(this.options.originAgentCluster)l.set("Origin-Agent-Cluster","?1");if(this.options.permittedCrossDomainPolicies){let d=this.options.permittedCrossDomainPolicies,p=typeof d==="object"?d.permittedPolicies||"none":"none";l.set("X-Permitted-Cross-Domain-Policies",p)}if(this.options.referrerPolicy){let d=this.options.referrerPolicy;if(typeof d==="object"){let p=Array.isArray(d.policy)?d.policy.join(", "):d.policy||"strict-origin-when-cross-origin";l.set("Referrer-Policy",p)}else l.set("Referrer-Policy","strict-origin-when-cross-origin")}if(this.options.xssFilter){let d=this.options.xssFilter,p=typeof d==="object"&&d.setOnOldIE?"1; mode=block":"0";l.set("X-XSS-Protection",p)}return new Response(a.body,{status:a.status,statusText:a.statusText,headers:l})}}var lt=/^[^\s@]+@[^\s@][^\s.@]*\.[^\s@]+$/,dt=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;class R{options;constructor(t={}){let i=e.server?.security?.inputValidation||{};this.options={enabled:t.enabled??i.enabled??!0,schemas:t.schemas??i.schemas??{},sanitizeByDefault:t.sanitizeByDefault??i.sanitizeByDefault??!0,strictMode:t.strictMode??i.strictMode??!1,allowUnknownFields:t.allowUnknownFields??i.allowUnknownFields??!0,maxDepth:t.maxDepth??i.maxDepth??10,onValidationError:t.onValidationError}}validateValue(t,i,o){let a=[];if(i.required&&(t===void 0||t===null||t===""))return a.push({field:o,message:"Field is required",value:t,rule:"required"}),a;if(t===void 0||t===null)return a;switch(i.type){case"string":if(typeof t!=="string")a.push({field:o,message:"Must be a string",value:t,rule:"type"});else{if(i.min!==void 0&&t.length<i.min)a.push({field:o,message:`Must be at least ${i.min} characters`,value:t,rule:"min"});if(i.max!==void 0&&t.length>i.max)a.push({field:o,message:`Must be at most ${i.max} characters`,value:t,rule:"max"})}break;case"number":{let l=Number(t);if(Number.isNaN(l))a.push({field:o,message:"Must be a number",value:t,rule:"type"});else{if(i.min!==void 0&&l<i.min)a.push({field:o,message:`Must be at least ${i.min}`,value:t,rule:"min"});if(i.max!==void 0&&l>i.max)a.push({field:o,message:`Must be at most ${i.max}`,value:t,rule:"max"})}break}case"boolean":if(typeof t!=="boolean"&&t!=="true"&&t!=="false")a.push({field:o,message:"Must be a boolean",value:t,rule:"type"});break;case"email":{if(typeof t==="string"&&!lt.test(t))a.push({field:o,message:"Must be a valid email address",value:t,rule:"format"});break}case"url":try{new URL(t)}catch{a.push({field:o,message:"Must be a valid URL",value:t,rule:"format"})}break;case"uuid":{if(typeof t==="string"&&!dt.test(t))a.push({field:o,message:"Must be a valid UUID",value:t,rule:"format"});break}case"date":{let l=new Date(t);if(Number.isNaN(l.getTime()))a.push({field:o,message:"Must be a valid date",value:t,rule:"format"});break}case"regex":if(i.pattern&&typeof t==="string"&&!i.pattern.test(t))a.push({field:o,message:"Does not match required pattern",value:t,rule:"pattern"});break;case"custom":if(i.custom){let l=i.custom(t);if(l!==!0)a.push({field:o,message:typeof l==="string"?l:"Custom validation failed",value:t,rule:"custom"})}break}if(i.enum&&!i.enum.includes(t))a.push({field:o,message:`Must be one of: ${i.enum.join(", ")}`,value:t,rule:"enum"});if(i.type!=="regex"&&i.pattern&&typeof t==="string"&&!i.pattern.test(t))a.push({field:o,message:"Does not match required pattern",value:t,rule:"pattern"});return a}sanitizeValue(t,i){if(!i.sanitize&&!this.options.sanitizeByDefault)return t;if(typeof t==="string")t=t.replace(/[<>'"&]/g,(o)=>({"<":"<",">":">",'"':""","'":"'","&":"&"})[o]||o).trim();if(i.transform)t=i.transform(t);return t}validateObject(t,i,o="",a=0){let l=[];if(a>this.options.maxDepth)return l.push({field:o,message:"Maximum nesting depth exceeded",value:t,rule:"depth"}),l;if(this.options.strictMode&&!this.options.allowUnknownFields){for(let d in t)if(!(d in i))l.push({field:o?`${o}.${d}`:d,message:"Unknown field",value:t[d],rule:"unknown"})}for(let[d,p]of Object.entries(i)){let x=o?`${o}.${d}`:d,P=t?.[d];if(typeof p==="object"&&!("type"in p)){if(P&&typeof P==="object")l.push(...this.validateObject(P,p,x,a+1))}else{let T=p;if(l.push(...this.validateValue(P,T,x)),t&&(T.sanitize||this.options.sanitizeByDefault))t[d]=this.sanitizeValue(P,T)}}return l}async parseRequestBody(t){let i=t.headers.get("content-type")||"";try{if(i.includes("application/json"))return await t.json();else if(i.includes("application/x-www-form-urlencoded")){let o=await t.formData(),a={};for(let[l,d]of o.entries())a[l]=d;return a}else if(i.includes("multipart/form-data")){let o=await t.formData(),a={};for(let[l,d]of o.entries())a[l]=d;return a}}catch(o){throw console.error(o),Error("Invalid request body format")}return{}}async handle(t,i){if(!this.options.enabled)return await i()||new Response("Not Found",{status:404});let o=[],a=new URL(t.url);try{if(this.options.schemas?.query){let d={};for(let[x,P]of a.searchParams.entries())d[x]=P;let p=this.validateObject(d,this.options.schemas.query);o.push(...p)}if(this.options.schemas?.body&&t.method!=="GET"&&t.method!=="HEAD")try{let d=await this.parseRequestBody(t),p=this.validateObject(d,this.options.schemas.body);o.push(...p),t.validatedBody=d}catch(d){o.push({field:"body",message:d instanceof Error?d.message:"Invalid request body",value:null,rule:"parse"})}if(this.options.schemas?.headers){let d={};for(let[x,P]of t.headers.entries())d[x]=P;let p=this.validateObject(d,this.options.schemas.headers);o.push(...p)}if(this.options.schemas?.params&&t.params){let d=this.validateObject(t.params,this.options.schemas.params);o.push(...d)}if(o.length>0){if(this.options.onValidationError)return this.options.onValidationError(o);return new Response(JSON.stringify({error:"Validation Error",message:"Request validation failed",errors:o}),{status:400,headers:{"Content-Type":"application/json"}})}return await i()||new Response("Not Found",{status:404})}catch(l){return console.error("Input validation error:",l),new Response("Internal Server Error",{status:500})}}}function Ze(t={}){let i=new R(t);return async(o,a)=>i.handle(o,a)}class N{options;rules=new Map;channels=[];notifications=[];lastAlertTimes=new Map;metricsBuffer=[];checkInterval;constructor(t={}){if(this.options={enabled:t.enabled??!0,defaultCooldown:t.defaultCooldown??300000,maxAlerts:t.maxAlerts??1000,autoResolve:t.autoResolve??!0,autoResolveTimeout:t.autoResolveTimeout??600000,...t},t.rules)for(let i of t.rules)this.rules.set(i.id,i);if(this.channels=t.channels||[],this.rules.size===0)this.addDefaultRules();if(this.channels.length===0)this.channels.push({type:"console",enabled:!0,config:{}});if(this.options.enabled)this.startAlertingEngine()}addDefaultRules(){let t=[{id:"high-response-time",name:"High Response Time",description:"Alert when average response time exceeds threshold",enabled:!0,metric:"responseTime",condition:"gt",threshold:1000,duration:60000,severity:"warning"},{id:"critical-response-time",name:"Critical Response Time",description:"Alert when response time is critically high",enabled:!0,metric:"responseTime",condition:"gt",threshold:5000,duration:30000,severity:"critical"},{id:"high-error-rate",name:"High Error Rate",description:"Alert when error rate exceeds threshold",enabled:!0,metric:"errorRate",condition:"gt",threshold:0.05,duration:120000,severity:"warning"},{id:"critical-error-rate",name:"Critical Error Rate",description:"Alert when error rate is critically high",enabled:!0,metric:"errorRate",condition:"gt",threshold:0.1,duration:60000,severity:"critical"},{id:"high-memory-usage",name:"High Memory Usage",description:"Alert when memory usage exceeds threshold",enabled:!0,metric:"memoryUsage",condition:"gt",threshold:536870912,duration:300000,severity:"warning"},{id:"low-request-rate",name:"Low Request Rate",description:"Alert when request rate drops significantly",enabled:!1,metric:"requestRate",condition:"lt",threshold:1,duration:300000,severity:"info"}];for(let i of t)this.rules.set(i.id,i)}startAlertingEngine(){this.checkInterval=setInterval(()=>{this.evaluateRules(),this.cleanupOldNotifications(),this.autoResolveAlerts()},1e4),this.checkInterval.unref?.()}evaluateRules(){let t=Date.now();for(let i of this.rules.values()){if(!i.enabled)continue;let o=this.lastAlertTimes.get(i.id),a=i.cooldown||this.options.defaultCooldown||300000;if(o&&t-o<a)continue;let l=i.duration||60000,d=this.metricsBuffer.filter((P)=>t-P.timestamp<=l);if(d.length===0)continue;let p=!1,x;if(i.metric==="custom"&&i.customEvaluator)p=i.customEvaluator(d),x="custom condition";else{let P=this.extractMetricValues(d,i.metric);if(P.length===0)continue;let T=P.reduce((k,M)=>k+M,0)/P.length;x=T,p=this.evaluateCondition(T,i.condition,i.threshold)}if(p)this.triggerAlert(i,x,d),this.lastAlertTimes.set(i.id,t)}}extractMetricValues(t,i){switch(i){case"responseTime":return t.map((o)=>o.responseTime);case"errorRate":return t.map((o)=>o.statusCode>=400?1:0);case"memoryUsage":return t.map((o)=>o.memoryUsage.heapUsed);case"cpuUsage":return t.map((o)=>o.cpuUsage.user+o.cpuUsage.system);case"requestRate":{if(t.length<2)return[];let o=(t[t.length-1].timestamp-t[0].timestamp)/1000;return[t.length/Math.max(o,1)]}default:return[]}}evaluateCondition(t,i,o){switch(i){case"gt":return t>o;case"gte":return t>=o;case"lt":return t<o;case"lte":return t<=o;case"eq":return Math.abs(t-o)<0.001;default:return!1}}async triggerAlert(t,i,o){let a={id:this.generateId(),ruleId:t.id,ruleName:t.name,severity:t.severity,message:this.formatAlertMessage(t,i,o),timestamp:Date.now(),resolved:!1,metadata:{rule:t,value:i,threshold:t.threshold,condition:t.condition,metricsCount:o.length}};this.notifications.push(a);for(let l of this.channels){if(!l.enabled)continue;if(l.filters?.severities&&!l.filters.severities.includes(t.severity))continue;if(l.filters?.rules&&!l.filters.rules.includes(t.id))continue;try{await this.sendNotification(l,a)}catch(d){console.error(`Failed to send alert to ${l.type}:`,d)}}if(this.notifications.length>(this.options.maxAlerts||1000))this.notifications=this.notifications.slice(-(this.options.maxAlerts||1000))}formatAlertMessage(t,i,o){let a=(p,x)=>{switch(x){case"responseTime":return`${Math.round(p)}ms`;case"errorRate":return`${Math.round(p*100)}%`;case"memoryUsage":return`${Math.round(p/1024/1024)}MB`;case"cpuUsage":return`${Math.round(p)}%`;case"requestRate":return`${Math.round(p)}/s`;default:return String(p)}},l=typeof i==="number"?a(i,t.metric):String(i),d=a(t.threshold,t.metric);return`${t.name}: ${l} ${t.condition} ${d} (${o.length} samples)`}async sendNotification(t,i){switch(t.type){case"console":this.sendConsoleNotification(i);break;case"webhook":await this.sendWebhookNotification(t,i);break;case"slack":await this.sendSlackNotification(t,i);break;case"email":await this.sendEmailNotification(t,i);break;case"custom":if(t.config.customHandler)await t.config.customHandler(i);break}}sendConsoleNotification(t){let i=t.severity==="critical"?"\uD83D\uDEA8":t.severity==="warning"?"\u26A0\uFE0F":"\u2139\uFE0F";console.log(`${i} ALERT [${t.severity.toUpperCase()}]: ${t.message}`),console.log(` Rule: ${t.ruleName} (${t.ruleId})`),console.log(` Time: ${new Date(t.timestamp).toISOString()}`)}async sendWebhookNotification(t,i){if(!t.config.url)return;let o={alert:i,timestamp:new Date(i.timestamp).toISOString(),service:"bun-router"};await fetch(t.config.url,{method:"POST",headers:{"Content-Type":"application/json",...t.config.token&&{Authorization:`Bearer ${t.config.token}`}},body:JSON.stringify(o)})}async sendSlackNotification(t,i){if(!t.config.url)return;let o=i.severity==="critical"?"danger":i.severity==="warning"?"warning":"good",a=i.severity==="critical"?":rotating_light:":i.severity==="warning"?":warning:":":information_source:",l=(()=>({channel:t.config.channel,username:"Performance Monitor",icon_emoji:":chart_with_upwards_trend:",attachments:[{color:o,title:`${a} ${i.ruleName}`,text:i.message,fields:[{title:"Severity",value:i.severity.toUpperCase(),short:!0},{title:"Time",value:new Date(i.timestamp).toISOString(),short:!0}],footer:"bun-router Performance Monitor",ts:Math.floor(i.timestamp/1000)}]}))();await fetch(t.config.url,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)})}async sendEmailNotification(t,i){console.log(`Email notification would be sent to ${t.config.email}:`,i.message)}cleanupOldNotifications(){let i=Date.now()-86400000;this.notifications=this.notifications.filter((o)=>o.timestamp>i)}autoResolveAlerts(){if(!this.options.autoResolve)return;let t=this.options.autoResolveTimeout||600000,i=Date.now()-t;for(let o of this.notifications)if(!o.resolved&&o.timestamp<i)o.resolved=!0,o.resolvedAt=Date.now()}generateId(){return Math.random().toString(36).substring(2,15)+Math.random().toString(36).substring(2,15)}addMetrics(t){this.metricsBuffer.push(t);let i=3600000,o=Date.now()-i;this.metricsBuffer=this.metricsBuffer.filter((a)=>a.timestamp>o)}addRule(t){this.rules.set(t.id,t)}removeRule(t){this.rules.delete(t)}updateRule(t,i){let o=this.rules.get(t);if(o)this.rules.set(t,{...o,...i})}addChannel(t){this.channels.push(t)}removeChannel(t){this.channels.splice(t,1)}getActiveAlerts(){return this.notifications.filter((t)=>!t.resolved)}getAllNotifications(){return[...this.notifications]}resolveAlert(t){let i=this.notifications.find((o)=>o.id===t);if(i&&!i.resolved)i.resolved=!0,i.resolvedAt=Date.now()}async handle(t,i){let o=await i();if(o)return o;return new Response("No response from next middleware",{status:500})}destroy(){if(this.checkInterval)clearInterval(this.checkInterval);this.rules.clear(),this.channels=[],this.notifications=[],this.lastAlertTimes.clear(),this.metricsBuffer=[]}}function et(t={}){return new N(t)}import X from"process";class q{options;metricsHistory=[];alerts=[];startTime=Date.now();constructor(t={}){this.options={enabled:t.enabled??!0,path:t.path??"/performance",title:t.title??"Performance Dashboard",refreshInterval:t.refreshInterval??5000,maxMetrics:t.maxMetrics??1000,authentication:{enabled:!1,...t.authentication},features:{realTimeMetrics:!0,historicalCharts:!0,alertsPanel:!0,tracingView:!0,systemMetrics:!0,...t.features}}}isAuthenticated(t){if(!this.options.authentication?.enabled)return!0;let i=t.headers.get("authorization"),o=t.headers.get("x-api-key");if(this.options.authentication.apiKey&&o===this.options.authentication.apiKey)return!0;if(i&&this.options.authentication.username&&this.options.authentication.password){let[a,l]=i.split(" ");if(a==="Basic"){let d=atob(l),[p,x]=d.split(":");return p===this.options.authentication.username&&x===this.options.authentication.password}}return!1}generateDashboardHTML(t){return`
|
|
5
|
+
<!DOCTYPE html>
|
|
6
|
+
<html lang="en">
|
|
7
|
+
<head>
|
|
8
|
+
<meta charset="UTF-8">
|
|
9
|
+
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
|
|
10
|
+
<title>${this.options.title}</title>
|
|
11
|
+
<style>
|
|
12
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
13
|
+
body {
|
|
14
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
15
|
+
background: #f5f5f5;
|
|
16
|
+
color: #333;
|
|
17
|
+
line-height: 1.6;
|
|
18
|
+
}
|
|
19
|
+
.header {
|
|
20
|
+
background: #2c3e50;
|
|
21
|
+
color: white;
|
|
22
|
+
padding: 1rem 2rem;
|
|
23
|
+
display: flex;
|
|
24
|
+
justify-content: space-between;
|
|
25
|
+
align-items: center;
|
|
26
|
+
}
|
|
27
|
+
.header h1 { font-size: 1.5rem; }
|
|
28
|
+
.status {
|
|
29
|
+
display: flex;
|
|
30
|
+
gap: 1rem;
|
|
31
|
+
align-items: center;
|
|
32
|
+
}
|
|
33
|
+
.status-item {
|
|
34
|
+
display: flex;
|
|
35
|
+
flex-direction: column;
|
|
36
|
+
align-items: center;
|
|
37
|
+
font-size: 0.8rem;
|
|
38
|
+
}
|
|
39
|
+
.status-value {
|
|
40
|
+
font-size: 1.2rem;
|
|
41
|
+
font-weight: bold;
|
|
42
|
+
}
|
|
43
|
+
.container {
|
|
44
|
+
max-width: 1400px;
|
|
45
|
+
margin: 0 auto;
|
|
46
|
+
padding: 2rem;
|
|
47
|
+
display: grid;
|
|
48
|
+
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
49
|
+
gap: 2rem;
|
|
50
|
+
}
|
|
51
|
+
.card {
|
|
52
|
+
background: white;
|
|
53
|
+
border-radius: 8px;
|
|
54
|
+
padding: 1.5rem;
|
|
55
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
56
|
+
}
|
|
57
|
+
.card h2 {
|
|
58
|
+
margin-bottom: 1rem;
|
|
59
|
+
color: #2c3e50;
|
|
60
|
+
font-size: 1.2rem;
|
|
61
|
+
}
|
|
62
|
+
.metric {
|
|
63
|
+
display: flex;
|
|
64
|
+
justify-content: space-between;
|
|
65
|
+
align-items: center;
|
|
66
|
+
padding: 0.5rem 0;
|
|
67
|
+
border-bottom: 1px solid #eee;
|
|
68
|
+
}
|
|
69
|
+
.metric:last-child { border-bottom: none; }
|
|
70
|
+
.metric-label { font-weight: 500; }
|
|
71
|
+
.metric-value {
|
|
72
|
+
font-weight: bold;
|
|
73
|
+
color: #27ae60;
|
|
74
|
+
}
|
|
75
|
+
.metric-value.warning { color: #f39c12; }
|
|
76
|
+
.metric-value.critical { color: #e74c3c; }
|
|
77
|
+
.alert {
|
|
78
|
+
padding: 0.75rem;
|
|
79
|
+
margin: 0.5rem 0;
|
|
80
|
+
border-radius: 4px;
|
|
81
|
+
border-left: 4px solid;
|
|
82
|
+
}
|
|
83
|
+
.alert.warning {
|
|
84
|
+
background: #fff3cd;
|
|
85
|
+
border-color: #f39c12;
|
|
86
|
+
color: #856404;
|
|
87
|
+
}
|
|
88
|
+
.alert.critical {
|
|
89
|
+
background: #f8d7da;
|
|
90
|
+
border-color: #e74c3c;
|
|
91
|
+
color: #721c24;
|
|
92
|
+
}
|
|
93
|
+
.chart-container {
|
|
94
|
+
height: 200px;
|
|
95
|
+
background: #f8f9fa;
|
|
96
|
+
border-radius: 4px;
|
|
97
|
+
display: flex;
|
|
98
|
+
align-items: center;
|
|
99
|
+
justify-content: center;
|
|
100
|
+
color: #666;
|
|
101
|
+
}
|
|
102
|
+
.distribution {
|
|
103
|
+
display: grid;
|
|
104
|
+
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
|
|
105
|
+
gap: 1rem;
|
|
106
|
+
margin-top: 1rem;
|
|
107
|
+
}
|
|
108
|
+
.distribution-item {
|
|
109
|
+
text-align: center;
|
|
110
|
+
padding: 1rem;
|
|
111
|
+
background: #f8f9fa;
|
|
112
|
+
border-radius: 4px;
|
|
113
|
+
}
|
|
114
|
+
.distribution-value {
|
|
115
|
+
font-size: 1.5rem;
|
|
116
|
+
font-weight: bold;
|
|
117
|
+
color: #2c3e50;
|
|
118
|
+
}
|
|
119
|
+
.distribution-label {
|
|
120
|
+
font-size: 0.8rem;
|
|
121
|
+
color: #666;
|
|
122
|
+
margin-top: 0.5rem;
|
|
123
|
+
}
|
|
124
|
+
.trace {
|
|
125
|
+
padding: 0.75rem;
|
|
126
|
+
margin: 0.5rem 0;
|
|
127
|
+
background: #f8f9fa;
|
|
128
|
+
border-radius: 4px;
|
|
129
|
+
border-left: 4px solid #3498db;
|
|
130
|
+
}
|
|
131
|
+
.trace-header {
|
|
132
|
+
display: flex;
|
|
133
|
+
justify-content: space-between;
|
|
134
|
+
align-items: center;
|
|
135
|
+
margin-bottom: 0.5rem;
|
|
136
|
+
}
|
|
137
|
+
.trace-operation {
|
|
138
|
+
font-weight: bold;
|
|
139
|
+
color: #2c3e50;
|
|
140
|
+
}
|
|
141
|
+
.trace-duration {
|
|
142
|
+
color: #666;
|
|
143
|
+
font-size: 0.9rem;
|
|
144
|
+
}
|
|
145
|
+
.trace-details {
|
|
146
|
+
font-size: 0.8rem;
|
|
147
|
+
color: #666;
|
|
148
|
+
}
|
|
149
|
+
.refresh-indicator {
|
|
150
|
+
position: fixed;
|
|
151
|
+
top: 1rem;
|
|
152
|
+
right: 1rem;
|
|
153
|
+
background: #27ae60;
|
|
154
|
+
color: white;
|
|
155
|
+
padding: 0.5rem 1rem;
|
|
156
|
+
border-radius: 4px;
|
|
157
|
+
font-size: 0.8rem;
|
|
158
|
+
opacity: 0;
|
|
159
|
+
transition: opacity 0.3s;
|
|
160
|
+
}
|
|
161
|
+
.refresh-indicator.active { opacity: 1; }
|
|
162
|
+
@media (max-width: 768px) {
|
|
163
|
+
.container {
|
|
164
|
+
grid-template-columns: 1fr;
|
|
165
|
+
padding: 1rem;
|
|
166
|
+
}
|
|
167
|
+
.header {
|
|
168
|
+
padding: 1rem;
|
|
169
|
+
flex-direction: column;
|
|
170
|
+
gap: 1rem;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
</style>
|
|
174
|
+
</head>
|
|
175
|
+
<body>
|
|
176
|
+
<div class='header'>
|
|
177
|
+
<h1>${this.options.title}</h1>
|
|
178
|
+
<div class='status'>
|
|
179
|
+
<div class='status-item'>
|
|
180
|
+
<div class='status-value'>${t.metrics.current.totalRequests}</div>
|
|
181
|
+
<div>Total Requests</div>
|
|
182
|
+
</div>
|
|
183
|
+
<div class='status-item'>
|
|
184
|
+
<div class='status-value'>${Math.round(t.metrics.current.averageResponseTime)}ms</div>
|
|
185
|
+
<div>Avg Response</div>
|
|
186
|
+
</div>
|
|
187
|
+
<div class='status-item'>
|
|
188
|
+
<div class='status-value'>${Math.round(t.metrics.current.errorRate*100)}%</div>
|
|
189
|
+
<div>Error Rate</div>
|
|
190
|
+
</div>
|
|
191
|
+
<div class='status-item'>
|
|
192
|
+
<div class='status-value'>${Math.round(t.metrics.current.requestsPerSecond)}/s</div>
|
|
193
|
+
<div>Requests/sec</div>
|
|
194
|
+
</div>
|
|
195
|
+
</div>
|
|
196
|
+
</div>
|
|
197
|
+
|
|
198
|
+
<div class='container'>
|
|
199
|
+
${this.options.features?.realTimeMetrics?`
|
|
200
|
+
<div class='card'>
|
|
201
|
+
<h2>Real-time Metrics</h2>
|
|
202
|
+
<div class='metric'>
|
|
203
|
+
<span class='metric-label'>Response Time</span>
|
|
204
|
+
<span class='metric-value'>${Math.round(t.metrics.current.averageResponseTime)}ms</span>
|
|
205
|
+
</div>
|
|
206
|
+
<div class='metric'>
|
|
207
|
+
<span class='metric-label'>Memory Usage</span>
|
|
208
|
+
<span class='metric-value'>${Math.round(t.metrics.current.memoryUsage/1024/1024)}MB</span>
|
|
209
|
+
</div>
|
|
210
|
+
<div class='metric'>
|
|
211
|
+
<span class='metric-label'>CPU Usage</span>
|
|
212
|
+
<span class='metric-value'>${Math.round(t.metrics.current.cpuUsage)}%</span>
|
|
213
|
+
</div>
|
|
214
|
+
<div class='metric'>
|
|
215
|
+
<span class='metric-label'>Requests/sec</span>
|
|
216
|
+
<span class='metric-value'>${Math.round(t.metrics.current.requestsPerSecond)}</span>
|
|
217
|
+
</div>
|
|
218
|
+
<div class='metric'>
|
|
219
|
+
<span class='metric-label'>Error Rate</span>
|
|
220
|
+
<span class='metric-value ${t.metrics.current.errorRate>0.1?"critical":t.metrics.current.errorRate>0.05?"warning":""}'>${Math.round(t.metrics.current.errorRate*100)}%</span>
|
|
221
|
+
</div>
|
|
222
|
+
</div>
|
|
223
|
+
`:""}
|
|
224
|
+
|
|
225
|
+
${this.options.features?.historicalCharts?`
|
|
226
|
+
<div class='card'>
|
|
227
|
+
<h2>Historical Performance</h2>
|
|
228
|
+
<div class='chart-container'>
|
|
229
|
+
Response Time Chart (${t.metrics.historical.length} data points)
|
|
230
|
+
</div>
|
|
231
|
+
</div>
|
|
232
|
+
`:""}
|
|
233
|
+
|
|
234
|
+
<div class='card'>
|
|
235
|
+
<h2>Request Distribution</h2>
|
|
236
|
+
<div class='distribution'>
|
|
237
|
+
${Object.entries(t.metrics.distribution.statusCodes).map(([i,o])=>`
|
|
238
|
+
<div class='distribution-item'>
|
|
239
|
+
<div class='distribution-value'>${o}</div>
|
|
240
|
+
<div class='distribution-label'>HTTP ${i}</div>
|
|
241
|
+
</div>
|
|
242
|
+
`).join("")}
|
|
243
|
+
</div>
|
|
244
|
+
</div>
|
|
245
|
+
|
|
246
|
+
<div class='card'>
|
|
247
|
+
<h2>Top Endpoints</h2>
|
|
248
|
+
${Object.entries(t.metrics.distribution.paths).sort(([,i],[,o])=>o-i).slice(0,10).map(([i,o])=>`
|
|
249
|
+
<div class='metric'>
|
|
250
|
+
<span class='metric-label'>${i}</span>
|
|
251
|
+
<span class='metric-value'>${o}</span>
|
|
252
|
+
</div>
|
|
253
|
+
`).join("")}
|
|
254
|
+
</div>
|
|
255
|
+
|
|
256
|
+
${this.options.features?.alertsPanel?`
|
|
257
|
+
<div class='card'>
|
|
258
|
+
<h2>Active Alerts</h2>
|
|
259
|
+
${t.alerts.length===0?"<p>No active alerts</p>":""}
|
|
260
|
+
${t.alerts.filter((i)=>!i.resolved).map((i)=>`
|
|
261
|
+
<div class='${i.type} alert'>
|
|
262
|
+
<strong>${i.type.toUpperCase()}:</strong> ${i.message}
|
|
263
|
+
<br><small>${new Date(i.timestamp).toLocaleString()}</small>
|
|
264
|
+
</div>
|
|
265
|
+
`).join("")}
|
|
266
|
+
</div>
|
|
267
|
+
`:""}
|
|
268
|
+
|
|
269
|
+
${this.options.features?.tracingView?`
|
|
270
|
+
<div class='card'>
|
|
271
|
+
<h2>Recent Traces</h2>
|
|
272
|
+
${t.traces.slice(0,10).map((i)=>`
|
|
273
|
+
<div class='trace'>
|
|
274
|
+
<div class='trace-header'>
|
|
275
|
+
<span class='trace-operation'>${i.operationName}</span>
|
|
276
|
+
<span class='trace-duration'>${Math.round((i.duration||0)*100)/100}ms</span>
|
|
277
|
+
</div>
|
|
278
|
+
<div class='trace-details'>
|
|
279
|
+
Trace ID: ${i.traceId} | Status: ${i.status}
|
|
280
|
+
${i.error?` | Error: ${i.error}`:""}
|
|
281
|
+
</div>
|
|
282
|
+
</div>
|
|
283
|
+
`).join("")}
|
|
284
|
+
</div>
|
|
285
|
+
`:""}
|
|
286
|
+
|
|
287
|
+
${this.options.features?.systemMetrics?`
|
|
288
|
+
<div class='card'>
|
|
289
|
+
<h2>System Information</h2>
|
|
290
|
+
<div class='metric'>
|
|
291
|
+
<span class='metric-label'>Uptime</span>
|
|
292
|
+
<span class='metric-value'>${Math.round(t.system.uptime/1000/60)} minutes</span>
|
|
293
|
+
</div>
|
|
294
|
+
<div class='metric'>
|
|
295
|
+
<span class='metric-label'>Node.js</span>
|
|
296
|
+
<span class='metric-value'>${t.system.nodeVersion}</span>
|
|
297
|
+
</div>
|
|
298
|
+
<div class='metric'>
|
|
299
|
+
<span class='metric-label'>Platform</span>
|
|
300
|
+
<span class='metric-value'>${t.system.platform} ${t.system.arch}</span>
|
|
301
|
+
</div>
|
|
302
|
+
<div class='metric'>
|
|
303
|
+
<span class='metric-label'>Heap Used</span>
|
|
304
|
+
<span class='metric-value'>${Math.round(t.system.memory.heapUsed/1024/1024)}MB</span>
|
|
305
|
+
</div>
|
|
306
|
+
<div class='metric'>
|
|
307
|
+
<span class='metric-label'>RSS</span>
|
|
308
|
+
<span class='metric-value'>${Math.round(t.system.memory.rss/1024/1024)}MB</span>
|
|
309
|
+
</div>
|
|
310
|
+
</div>
|
|
311
|
+
`:""}
|
|
312
|
+
</div>
|
|
313
|
+
|
|
314
|
+
<div class='refresh-indicator' id='refreshIndicator'>Updated</div>
|
|
315
|
+
|
|
316
|
+
<script>
|
|
317
|
+
let refreshInterval;
|
|
318
|
+
|
|
319
|
+
function startAutoRefresh() {
|
|
320
|
+
refreshInterval = setInterval(async () => {
|
|
321
|
+
try {
|
|
322
|
+
const response = await fetch('${this.options.path}/api/data');
|
|
323
|
+
if (response.ok) {
|
|
324
|
+
const indicator = document.getElementById('refreshIndicator');
|
|
325
|
+
indicator.classList.add('active');
|
|
326
|
+
setTimeout(() => indicator.classList.remove('active'), 1000);
|
|
327
|
+
|
|
328
|
+
// In a real implementation, we would update the DOM with new data
|
|
329
|
+
// For now, we'll just refresh the page
|
|
330
|
+
setTimeout(() => window.location.reload(), ${this.options.refreshInterval});
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
catch (error) {
|
|
334
|
+
console.error('Failed to refresh data:', error);
|
|
335
|
+
}
|
|
336
|
+
}, ${this.options.refreshInterval});
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Start auto-refresh
|
|
340
|
+
startAutoRefresh();
|
|
341
|
+
|
|
342
|
+
// Stop refresh when page is hidden
|
|
343
|
+
document.addEventListener('visibilitychange', () => {
|
|
344
|
+
if (document.hidden) {
|
|
345
|
+
clearInterval(refreshInterval);
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
startAutoRefresh();
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
</script>
|
|
352
|
+
</body>
|
|
353
|
+
</html>
|
|
354
|
+
`}async getDashboardData(t,i){let o=Date.now(),a={current:{totalRequests:0,averageResponseTime:0,errorRate:0,requestsPerSecond:0,memoryUsage:0,cpuUsage:0},historical:this.metricsHistory,distribution:{statusCodes:{},paths:{},methods:{},responseTimes:[]}};if(t&&typeof t.getAggregatedMetrics==="function"){let p=t.getAggregatedMetrics(60000);a.current={totalRequests:p.totalRequests,averageResponseTime:p.averageResponseTime,errorRate:p.errorRate,requestsPerSecond:p.requestsPerSecond,memoryUsage:p.averageMemoryUsage,cpuUsage:0},a.distribution.statusCodes=p.statusCodeDistribution,a.distribution.paths=p.pathDistribution}let l=[];if(i&&typeof i.getActiveSpans==="function")l=i.getActiveSpans();let d={uptime:o-this.startTime,nodeVersion:X.version,bunVersion:X.versions.bun||"N/A",platform:X.platform,arch:X.arch,memory:X.memoryUsage(),cpu:X.cpuUsage()};return{metrics:a,alerts:this.alerts,traces:l,system:d}}async handle(t,i){if(!this.options.enabled)return await i()||new Response("Internal Server Error",{status:500});let o=new URL(t.url);if(o.pathname===this.options.path){if(!this.isAuthenticated(t))return new Response("Unauthorized",{status:401,headers:{"WWW-Authenticate":'Basic realm="Performance Dashboard"'}});let a=await this.getDashboardData(),l=this.generateDashboardHTML(a);return new Response(l,{headers:{"Content-Type":"text/html","Cache-Control":"no-cache, no-store, must-revalidate"}})}if(o.pathname===`${this.options.path}/api/data`){if(!this.isAuthenticated(t))return new Response("Unauthorized",{status:401});let a=await this.getDashboardData();return new Response(JSON.stringify(a),{headers:{"Content-Type":"application/json","Cache-Control":"no-cache, no-store, must-revalidate"}})}return await i()}addAlert(t,i){if(this.alerts.push({id:Math.random().toString(36).substring(2,15),type:t,message:i,timestamp:Date.now(),resolved:!1}),this.alerts.length>100)this.alerts=this.alerts.slice(-100)}resolveAlert(t){let i=this.alerts.find((o)=>o.id===t);if(i)i.resolved=!0}updateMetricsHistory(t){this.metricsHistory.push({timestamp:Date.now(),...t});let i=this.options.maxMetrics||1000;if(this.metricsHistory.length>i)this.metricsHistory=this.metricsHistory.slice(-i)}}function tt(t={}){let i=new q(t);return async(o,a)=>i.handle(o,a)}import _ from"process";class H{options;metrics=[];lastAlertTime={};requestsThisSecond=0;lastSecondTimestamp=Date.now();requestContexts=new Map;samplingCounter=0;alertCooldowns=new Map;cleanupInterval;constructor(t={}){let i=e.server?.performance?.monitoring||{};if(this.options={enabled:t.enabled??i.enabled??!0,sampleRate:t.sampleRate??t.sampling?.rate??1,collectMetrics:{responseTime:!0,memoryUsage:!0,cpuUsage:!0,requestDetails:!0,headers:!1,queryParams:!0,...t.collectMetrics},sampling:{rate:t.sampling?.rate??t.sampleRate??1,maxRequestsPerSecond:t.sampling?.maxRequestsPerSecond??1000,...t.sampling},thresholds:{responseTime:{warning:1000,critical:5000},memoryUsage:{warning:536870912,critical:1073741824},errorRate:{warning:0.05,critical:0.1}},profiling:{enabled:!1,sampleInterval:100,maxSamples:10,includeStackTrace:!1,maxStackDepth:10},alerts:{enabled:!1,thresholds:{responseTime:1000,memoryUsage:104857600,errorRate:0.05},cooldown:60000},...t},this.options.storage?.type==="memory")this.startCleanupInterval()}startCleanupInterval(){this.cleanupInterval=setInterval(()=>{this.cleanupOldMetrics()},60000),this.cleanupInterval.unref?.()}cleanupOldMetrics(){let t=Date.now(),i=this.options.storage?.retentionPeriod||86400000;this.metrics=this.metrics.filter((a)=>t-a.timestamp<i);let o=this.options.storage?.maxEntries||1e4;if(this.metrics.length>o)this.metrics=this.metrics.slice(-o)}shouldSample(){let t=this.options.sampling?.rate||this.options.sampleRate||1;return Math.random()<t}generateTraceId(){return Math.random().toString(36).substring(2,15)+Math.random().toString(36).substring(2,15)}generateSpanId(){return Math.random().toString(36).substring(2,10)}getClientIP(t){return t.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||t.headers.get("x-real-ip")||t.headers.get("cf-connecting-ip")||"unknown"}async collectSystemMetrics(){let t=_.memoryUsage(),i=_.cpuUsage();return{memory:t,cpu:i}}takeSample(t){let i=_.memoryUsage(),o=_.cpuUsage(),a=Date.now();if(!t.systemSamples)t.systemSamples=[];if(!t.samples)t.samples=[];t.systemSamples.push({timestamp:a,memory:i,cpu:o}),t.samples.push({timestamp:a,memory:i,cpu:o,stack:this.options.profiling?.includeStackTrace?Error("Profile sample").stack?.slice(0,this.options.profiling.maxStackDepth||10):void 0})}calculateCpuPercent(t,i,o){let a=i.user-t.user,l=i.system-t.system;return{user:a/o*100,system:l/o*100}}async storeMetrics(t){if(this.metrics.push(t),console.warn(`[PerformanceMonitor] Stored metric: ${t.path} ${t.method} ${t.responseTime}ms`),console.warn(`[PerformanceMonitor] Added metric to internal array: ${t.path} ${t.method} ${t.responseTime}ms`),this.options.storage?.type)switch(this.options.storage.type){case"file":if(this.options.storage.filePath){let i=`${JSON.stringify(t)}
|
|
355
|
+
`;await Bun.write(this.options.storage.filePath,i,{createPath:!0})}break;case"custom":if(this.options.storage.customHandler)await this.options.storage.customHandler(t);break;case"memory":default:break}}async checkThresholds(t){let i=typeof this.options.alerts?.customHandler==="function";if(!this.options.alerts?.enabled&&!i)return;let o=this.options.alerts?.thresholds,a=this.options.thresholds;if(console.warn(`[PerformanceMonitor] Checking thresholds for ${t.path}: responseTime=${t.responseTime}ms, threshold=${o?.responseTime||a?.responseTime?.warning||"none"}`),o?.responseTime&&t.responseTime>o.responseTime)await this.sendAlert({type:"responseTime",message:`Response time threshold exceeded: ${t.responseTime}ms > ${o.responseTime}ms`,value:t.responseTime,threshold:o.responseTime,path:t.path,method:t.method,statusCode:t.statusCode,timestamp:t.timestamp,severity:"warning"});else if(a?.responseTime?.warning&&t.responseTime>a.responseTime.warning)await this.sendAlert({type:"responseTime",message:`Response time threshold exceeded: ${t.responseTime}ms > ${a.responseTime.warning}ms`,value:t.responseTime,threshold:a.responseTime.warning,path:t.path,method:t.method,statusCode:t.statusCode,timestamp:t.timestamp,severity:"warning"});let l=t.memoryUsage.heapUsed;if(o?.memoryUsage&&l>o.memoryUsage)await this.sendAlert({type:"memoryUsage",message:`Memory usage threshold exceeded: ${l} bytes > ${o.memoryUsage} bytes`,value:l,threshold:o.memoryUsage,path:t.path,method:t.method,statusCode:t.statusCode,timestamp:t.timestamp,severity:"warning"});else if(a?.memoryUsage?.warning&&l>a.memoryUsage.warning)await this.sendAlert({type:"memoryUsage",message:`Memory usage threshold exceeded: ${l} bytes > ${a.memoryUsage.warning} bytes`,value:l,threshold:a.memoryUsage.warning,path:t.path,method:t.method,statusCode:t.statusCode,timestamp:t.timestamp,severity:"warning"});if((o?.errorRate||a?.errorRate?.warning)&&t.statusCode>=500){let d=this.metrics.filter((k)=>k.timestamp>Date.now()-60000),p=d.length,x=d.filter((k)=>k.statusCode>=500).length,P=p>0?x/p:0,T=o?.errorRate||a?.errorRate?.warning;if(T&&P>T)await this.sendAlert({type:"errorRate",message:`Error rate threshold exceeded: ${P.toFixed(2)} > ${T.toFixed(2)}`,value:P,threshold:T,path:t.path,method:t.method,statusCode:t.statusCode,timestamp:t.timestamp,severity:"critical"})}}async sendAlert(t){let i=typeof this.options.alerts?.customHandler==="function";if(!i){let o=`${t.type}:${t.path}`,a=Date.now(),l=this.alertCooldowns.get(o)||0,d=this.options.alerts?.cooldown||60000;if(a-l<d)return;this.alertCooldowns.set(o,a)}if(i)try{await this.options.alerts.customHandler(t)}catch(o){console.error("Error in custom alert handler:",o)}if(this.options.alerts?.handler)try{await this.options.alerts.handler(t)}catch(o){console.error("Error in alert handler:",o)}console.warn(`[PerformanceMonitor] Alert: ${t.message} (${t.severity})`)}async sendAlerts(t,i){let o=`${i.path}-${t.join(",")}`,a=Date.now(),l=300000,d=this.alertCooldowns.get(o);if(d&&a-d<300000)return;this.alertCooldowns.set(o,a);let p={timestamp:new Date(i.timestamp).toISOString(),requestId:i.requestId,path:i.path,method:i.method,alerts:t,metrics:{responseTime:i.responseTime,memoryUsage:Math.round(i.memoryUsage.heapUsed/1024/1024),statusCode:i.statusCode}};if(this.options.alerts?.webhookUrl)try{await fetch(this.options.alerts.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(p)})}catch(x){console.error("Failed to send webhook alert:",x)}if(this.options.alerts?.slackConfig?.webhookUrl)try{await fetch(this.options.alerts.slackConfig.webhookUrl,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({channel:this.options.alerts.slackConfig.channel,text:`\uD83D\uDEA8 Performance Alert: ${t.join(", ")}`,attachments:[{color:"danger",fields:[{title:"Path",value:i.path,short:!0},{title:"Response Time",value:`${i.responseTime}ms`,short:!0},{title:"Memory Usage",value:`${Math.round(i.memoryUsage.heapUsed/1024/1024)}MB`,short:!0},{title:"Status Code",value:i.statusCode.toString(),short:!0}]}]})})}catch(x){console.error("Failed to send Slack alert:",x)}}async collectMetrics(t){let{req:i,res:o,startTime:a,startMemory:l,startCPU:d,error:p}=t,x=performance.now(),P=_.memoryUsage(),T=_.cpuUsage(d),k=new URL(i.url),M=i.requestId||s().randomUUID(),C={user:T.user,system:T.system},U={requestId:M,timestamp:Date.now(),responseTime:x-a,memoryUsage:{rss:P.rss,heapTotal:P.heapTotal,heapUsed:P.heapUsed,external:P.external,arrayBuffers:P.arrayBuffers},cpuUsage:C,statusCode:o?.status||500,method:i.method,path:k.pathname};if(p)U.error=p.message||String(p);if(i.traceId)U.traceId=i.traceId;if(i.spanId)U.spanId=i.spanId;if(o){let L=o.headers.get("content-length");if(L)U.contentLength=Number.parseInt(L,10)}return console.warn(`[PerformanceMonitor] Collected metrics for ${i.method} ${k.pathname}: responseTime=${U.responseTime}ms, memory=${U.memoryUsage.heapUsed} bytes`),U}async handle(t,i){if(!this.options.enabled)return i();let o=this.options.sampling?.rate??this.options.sampleRate??1,a=Math.random();if(o<=0||a>o)return i();let l=Date.now();if(l-this.lastSecondTimestamp>1000)this.lastSecondTimestamp=l,this.requestsThisSecond=0;if(this.options.maxRequestsPerSecond&&this.requestsThisSecond>=this.options.maxRequestsPerSecond)return i();this.requestsThisSecond++,console.warn(`[PerformanceMonitor] Handling request: ${t.method} ${new URL(t.url).pathname}`);let d=performance.now(),p=_.memoryUsage(),x=_.cpuUsage(),P=[],T;if(this.options.profiling?.enabled){let C=t.requestId||s().randomUUID();if(!t.profiling)t.profiling={requestId:C,samples:[],systemSamples:[]};if(this.takeSample(t.profiling),this.options.profiling.sampleInterval)T=setInterval(()=>{if(t.profiling&&t.profiling.samples.length<(this.options.profiling?.maxSamples||100))this.takeSample(t.profiling)},this.options.profiling.sampleInterval)}let k=null,M;try{k=await i()}catch(C){throw M=C instanceof Error?C:Error(String(C)),M}finally{if(T)clearInterval(T);let C=await this.collectMetrics({req:t,res:k||new Response("Internal Server Error",{status:500}),startTime:d,startMemory:p,startCPU:x,profilingSamples:P,error:M});await this.storeMetrics(C),await this.checkThresholds(C)}if(!k)return new Response("Internal Server Error",{status:500});return k}addMetrics(t){this.metrics.push(t),console.warn(`[PerformanceMonitor] Added metric to internal array: ${t.path} ${t.method} ${t.responseTime}ms`)}async checkThresholdsPublic(t){return this.checkThresholds(t)}getMetrics(t){let i=this.metrics;if(t?.startTime)i=i.filter((o)=>o.timestamp>=t.startTime);if(t?.endTime)i=i.filter((o)=>o.timestamp<=t.endTime);if(t?.path)i=i.filter((o)=>o.path===t.path);if(t?.method)i=i.filter((o)=>o.method===t.method);if(t?.statusCode)i=i.filter((o)=>o.statusCode===t.statusCode);if(t?.limit)i=i.slice(-t.limit);return i}getAggregatedMetrics(t=60000){let o=Date.now()-t,a=this.metrics.filter((T)=>T.timestamp>=o);if(a.length===0)return{totalRequests:0,averageResponseTime:0,medianResponseTime:0,p95ResponseTime:0,p99ResponseTime:0,errorRate:0,averageMemoryUsage:0,requestsPerSecond:0,statusCodeDistribution:{},pathDistribution:{}};let l=a.map((T)=>T.responseTime).sort((T,k)=>T-k),d=a.filter((T)=>T.statusCode>=400).length,p=a.map((T)=>T.memoryUsage.heapUsed),x={},P={};return a.forEach((T)=>{x[T.statusCode]=(x[T.statusCode]||0)+1,P[T.path]=(P[T.path]||0)+1}),{totalRequests:a.length,averageResponseTime:l.reduce((T,k)=>T+k,0)/l.length,medianResponseTime:l[Math.floor(l.length/2)],p95ResponseTime:l[Math.floor(l.length*0.95)],p99ResponseTime:l[Math.floor(l.length*0.99)],errorRate:d/a.length,averageMemoryUsage:p.reduce((T,k)=>T+k,0)/p.length,requestsPerSecond:a.length/(t/1000),statusCodeDistribution:x,pathDistribution:P}}getProfiles(){let t=[],i=_.memoryUsage(),o=_.cpuUsage();t.push({timestamp:Date.now(),memoryUsage:i,cpuUsage:o});for(let a of this.requestContexts.values())if(a.samples&&a.samples.length>0)for(let l of a.samples)t.push({timestamp:l.timestamp,memoryUsage:l.memory,cpuUsage:l.cpu});return t}destroy(){if(this.cleanupInterval)clearInterval(this.cleanupInterval);this.requestContexts.clear(),this.alertCooldowns.clear()}}function rt(t={}){let i=new H(t);return async(o,a)=>i.handle(o,a)}class B{options;spans=new Map;activeSpans=new Map;exportQueue=[];exportInterval;constructor(t={}){let i=e.server?.performance?.monitoring?.tracing||{};if(this.options={enabled:t.enabled??i.enabled??!1,sampleRate:t.sampleRate??i.sampleRate??1,maxSpans:t.maxSpans??1e4,includeHeaders:t.includeHeaders??!1,includeQueryParams:t.includeQueryParams??!0,includeRequestBody:t.includeRequestBody??!1,includeResponseBody:t.includeResponseBody??!1,maxBodySize:t.maxBodySize??1048576,exporters:t.exporters??[{type:"console"}],propagation:{enabled:!0,headers:["x-trace-id","x-span-id","x-parent-span-id"],...t.propagation}},this.options.enabled)this.startExportInterval()}startExportInterval(){this.exportInterval=setInterval(async()=>{try{await this.exportSpans()}catch(t){console.warn("Error exporting spans:",t)}},100),this.exportInterval.unref?.()}shouldSample(){return Math.random()<(this.options.sampleRate||1)}generateId(){return Math.random().toString(36).substring(2,15)+Math.random().toString(36).substring(2,15)}extractPropagationHeaders(t){if(!this.options.propagation?.enabled)return{};let i=this.options.propagation.headers||[],o;for(let l of i){let d=t.headers.get(l);if(d){o=d;break}}let a=t.headers.get("x-parent-span-id")||void 0;return{traceId:o,parentSpanId:a}}async captureRequestBody(t){if(!this.options.includeRequestBody)return;try{let i=t.headers.get("content-type")||"",o=Number.parseInt(t.headers.get("content-length")||"0",10);if(o>(this.options.maxBodySize||1048576))return{truncated:!0,reason:"Body too large",size:o};if(i.includes("application/json"))return await t.clone().json();else if(i.includes("application/x-www-form-urlencoded")){let l=await t.clone().formData(),d={};for(let[p,x]of l.entries())d[p]=x;return d}else if(i.includes("text/"))return await t.clone().text()}catch(i){return{error:"Failed to capture body",message:i instanceof Error?i.message:String(i)}}return}async captureResponseBody(t){if(!this.options.includeResponseBody)return;try{let i=t.headers.get("content-type")||"",o=Number.parseInt(t.headers.get("content-length")||"0",10);if(o>(this.options.maxBodySize||1048576))return{truncated:!0,reason:"Body too large",size:o};if(i.includes("application/json"))return await t.clone().json();else if(i.includes("text/"))return await t.clone().text()}catch(i){return{error:"Failed to capture body",message:i instanceof Error?i.message:String(i)}}return}createSpan(t,i,o,a){return{traceId:t,spanId:i,parentSpanId:a,operationName:o,startTime:performance.now(),tags:{},logs:[],status:"ok"}}addSpanTag(t,i,o){let a=this.spans.get(t);if(a)a.tags[i]=o}addSpanLog(t,i,o,a){let l=this.spans.get(t);if(l)l.logs.push({timestamp:performance.now(),level:i,message:o,fields:a})}finishSpan(t,i="ok",o){let a=this.spans.get(t);if(a){if(a.endTime=performance.now(),a.duration=a.endTime-a.startTime,a.status=i,o){if(a.error=o,this.options.includeHeaders)a.stackTrace=Error("Trace error stack").stack?.split(`
|
|
356
|
+
`)}this.exportQueue.push(a),this.spans.delete(t)}}async exportSpans(){if(this.spans.size>0){let o=performance.now()-60000;for(let[a,l]of this.spans)if(l.endTime===void 0&&l.startTime<o)this.spans.delete(a)}if(this.exportQueue.length===0){let o=Array.from(this.spans.values()).filter((a)=>a.endTime!==void 0);if(o.length>0){this.exportQueue.push(...o);for(let a of o)this.spans.delete(a.spanId)}if(this.exportQueue.length===0)return}let t=[...this.exportQueue];this.exportQueue=[];let i=this.options.exporters||[];if(i.length===0){this.exportToConsole(t);return}for(let o of i)try{switch(o.type){case"console":this.exportToConsole(t);break;case"jaeger":await this.exportToJaeger(t,o);break;case"zipkin":await this.exportToZipkin(t,o);break;case"custom":if(typeof o.customExporter==="function")await o.customExporter(t);break}}catch(a){console.warn(`Failed to export spans to ${o.type}:`,a)}}exportToConsole(t){for(let i of t)console.warn("Trace Span:",{traceId:i.traceId,spanId:i.spanId,operation:i.operationName,duration:`${Math.round((i.duration||0)*100)/100}ms`,status:i.status,tags:i.tags,logs:i.logs.length,error:i.error})}async exportToJaeger(t,i){if(!i.endpoint)return;let o=t.map((a)=>({traceID:a.traceId,spanID:a.spanId,parentSpanID:a.parentSpanId,operationName:a.operationName,startTime:Math.floor(a.startTime*1000),duration:Math.floor((a.duration||0)*1000),tags:Object.entries(a.tags).map(([l,d])=>({key:l,type:typeof d==="string"?"string":"number",value:String(d)})),logs:a.logs.map((l)=>({timestamp:Math.floor(l.timestamp*1000),fields:[{key:"level",value:l.level},{key:"message",value:l.message},...l.fields?Object.entries(l.fields).map(([d,p])=>({key:d,value:String(p)})):[]]})),process:{serviceName:"bun-router",tags:[{key:"hostname",value:Bun.env.HOSTNAME||"localhost"},{key:"pid",value:String(123)}]}}));await fetch(`${i.endpoint}/api/traces`,{method:"POST",headers:{"Content-Type":"application/json",...i.headers},body:JSON.stringify({data:[{spans:o}]})})}async exportToZipkin(t,i){if(!i.endpoint)return;let o=t.map((a)=>({traceId:a.traceId,id:a.spanId,parentId:a.parentSpanId,name:a.operationName,timestamp:Math.floor(a.startTime*1000),duration:Math.floor((a.duration||0)*1000),kind:"SERVER",localEndpoint:{serviceName:"bun-router"},tags:a.tags,annotations:a.logs.map((l)=>({timestamp:Math.floor(l.timestamp*1000),value:`${l.level}: ${l.message}`}))}));await fetch(`${i.endpoint}/api/v2/spans`,{method:"POST",headers:{"Content-Type":"application/json",...i.headers},body:JSON.stringify(o)})}async handle(t,i){if(!this.options.enabled||!this.shouldSample())return await i()||new Response("Internal Server Error",{status:500});let o=t.requestId||this.generateId(),a=this.extractPropagationHeaders(t),l=a.traceId||this.generateId(),d=this.generateId(),p=new URL(t.url);console.warn(`[RequestTracer] Creating span for ${t.method} ${p.pathname}, traceId=${l}, spanId=${d}`);let x=this.createSpan(l,d,`${t.method} ${p.pathname}`,a.parentSpanId);if(this.spans.set(d,x),this.activeSpans.set(o,d),t.traceId=l,t.spanId=d,Object.defineProperties(t,{traceId:{value:l,writable:!0,enumerable:!0,configurable:!0},spanId:{value:d,writable:!0,enumerable:!0,configurable:!0}}),this.addSpanTag(d,"http.method",t.method),this.addSpanTag(d,"http.url",t.url),this.addSpanTag(d,"http.path",p.pathname),this.addSpanTag(d,"user_agent",t.headers.get("user-agent")),this.options.includeHeaders){let k={};for(let[M,C]of t.headers.entries())k[M]=C;this.addSpanTag(d,"http.headers",k)}if(this.options.includeQueryParams&&p.searchParams.size>0){let k={};for(let[M,C]of p.searchParams.entries())k[M]=C;this.addSpanTag(d,"http.query_params",k)}if(this.options.includeRequestBody&&t.method!=="GET"&&t.method!=="HEAD")try{let k=await this.captureRequestBody(t);if(k!==void 0)this.addSpanTag(d,"http.request_body",k)}catch(k){this.addSpanLog(d,"warn","Failed to capture request body",{error:String(k)})}this.addSpanLog(d,"info","Request started");let P,T;try{if(P=await i()||new Response("Internal Server Error",{status:500}),this.addSpanTag(d,"http.status_code",P.status),this.addSpanTag(d,"http.status_text",P.statusText),this.options.includeResponseBody)try{let C=await this.captureResponseBody(P);if(C!==void 0)this.addSpanTag(d,"http.response_body",C)}catch(C){this.addSpanLog(d,"warn","Failed to capture response body",{error:String(C)})}this.addSpanLog(d,"info","Request completed",{status:P.status,statusText:P.statusText});let M=P.status>=400;if(M)this.addSpanTag(d,"error",!0),this.addSpanTag(d,"error.status_code",P.status);this.finishSpan(d,M?"error":"ok",M?`HTTP ${P.status}`:void 0)}catch(k){T=k instanceof Error?k.message:String(k),this.addSpanTag(d,"error",!0),this.addSpanTag(d,"error.message",T),this.addSpanTag(d,"error.type",k instanceof Error?k.constructor.name:"Unknown"),this.addSpanLog(d,"error","Request failed",{error:T}),this.finishSpan(d,"error",T);let M=this.spans.get(d);if(M){if(M.endTime===void 0)M.endTime=performance.now(),M.duration=M.endTime-M.startTime,M.status="error",M.error=T;this.exportQueue.push(M),this.spans.delete(d),this.exportSpans().catch((C)=>{console.warn("Failed to export error span:",C)})}P=new Response("Internal Server Error",{status:500})}if(this.activeSpans.delete(o),this.options.propagation?.enabled)P.headers.set("x-trace-id",l),P.headers.set("x-span-id",d);return P}getActiveSpans(){return Array.from(this.spans.values())}getSpanById(t){return this.spans.get(t)}createChildSpan(t,i){let o=this.spans.get(t);if(!o)return null;let a=this.generateId(),l=this.createSpan(o.traceId,a,i,t);return this.spans.set(a,l),a}addTag(t,i,o){this.addSpanTag(t,i,o)}addLog(t,i,o,a){this.addSpanLog(t,i,o,a)}finish(t,i="ok",o){this.finishSpan(t,i,o)}async flush(){let t=Array.from(this.spans.keys());console.warn(`[RequestTracer] Flushing ${t.length} active spans`);for(let i of t){let o=this.spans.get(i);if(o&&!o.endTime)this.finishSpan(i,"ok")}await this.exportSpans()}destroy(){if(this.exportInterval)clearInterval(this.exportInterval);this.spans.clear(),this.activeSpans.clear(),this.exportQueue=[]}}function nt(t={}){let i=new B(t);return async(o,a)=>i.handle(o,a)}class v{options;suspiciousPatterns=[];sqlInjectionPatterns=[];xssPatterns=[];pathTraversalPatterns=[];commandInjectionPatterns=[];constructor(t={}){let i=e.server?.security||{};this.options={inputValidation:{enabled:!0,maxBodySize:10485760,maxUrlLength:2048,maxHeaderSize:8192,allowedContentTypes:["application/json","application/x-www-form-urlencoded","multipart/form-data","text/plain","text/html","application/xml","text/xml"],sanitizeInput:!0,validateEncoding:!0,...t.inputValidation},requestFiltering:{enabled:!0,blockSuspiciousPatterns:!0,maxRequestsPerMinute:1000,blockUserAgents:["sqlmap","nikto","nessus","openvas","nmap","masscan","zap","w3af"],allowedMethods:["GET","POST","PUT","DELETE","PATCH","HEAD","OPTIONS"],requireUserAgent:!1,...t.requestFiltering},ipFiltering:{enabled:!1,whitelist:[],blacklist:[],blockPrivateIPs:!1,blockCloudProviders:!1,geoBlocking:{enabled:!1,allowedCountries:[],blockedCountries:[]},...t.ipFiltering},attackPrevention:{enabled:!0,sqlInjection:!0,xss:!0,pathTraversal:!0,commandInjection:!0,ldapInjection:!0,xxe:!0,customPatterns:[],...t.attackPrevention},responseSecurity:{enabled:!0,removeServerHeaders:!0,addSecurityHeaders:!0,sanitizeErrors:!0,preventInfoDisclosure:!0,...t.responseSecurity}},this.initializePatterns()}initializePatterns(){this.suspiciousPatterns=[/\.\.\//g,/\.\.\\/g,/%2e%2e%2f/gi,/%2e%2e%5c/gi,/\/etc\/passwd/gi,/\/proc\/self\/environ/gi,/cmd\.exe/gi,/powershell/gi,/<script/gi,/javascript:/gi,/vbscript:/gi,/onload=/gi,/onerror=/gi],this.sqlInjectionPatterns=[/(\bunion\b.+\bselect\b)|(\bselect\b.+\bunion\b)/gi,/\b(select|insert|update|delete|drop|create|alter|exec|execute)\b.+\b(from|into|set|where|table|database|schema)\b/gi,/(\bor\b|\band\b).+['"]\s*=\s*['"]|['"]\s*=\s*['"].+(\bor\b|\band\b)/gi,/\b(sleep|benchmark|waitfor)\s*\(/gi,/\b(information_schema|sys\.databases|sysobjects)\b/gi,/('|(\\')).+(or|and)\s+(?:\S.*|[\t\v\f \xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF])[=><]/gi,/\b(concat|group_concat|load_file|into\s+outfile)\b/gi],this.xssPatterns=[/<script[^>]*>.*?<\/script>/gi,/<iframe[^>]*>.*?<\/iframe>/gi,/<object[^>]*>.*?<\/object>/gi,/<embed[^>]*>/gi,/<link[^>]*>/gi,/<meta[^>]*>/gi,/javascript:/gi,/vbscript:/gi,/on\w+\s*=/gi,/<[^>]*\son\w+\s*=.*?>/gi,/expression\s*\(/gi,/url\s*\(\s*javascript:/gi],this.pathTraversalPatterns=[/\.\.\//g,/\.\.\\/g,/%2e%2e%2f/gi,/%2e%2e%5c/gi,/\.\.%2f/gi,/\.\.%5c/gi,/%252e%252e%252f/gi,/\.\/%2e%2e%2f/gi],this.commandInjectionPatterns=[/[;&|`${}[\]]/g,/\b(cat|ls|pwd|id|whoami|uname|ps|netstat|ifconfig|ping|nslookup|dig|curl|wget)\s/gi,/\b(cmd|powershell|bash|sh|zsh|fish)\s/gi,/\b(exec|system|shell_exec|passthru|eval)\s*\(/gi,/\$\{.*\}/g,/#\{.*\}/g]}getClientIP(t){return t.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||t.headers.get("x-real-ip")||t.headers.get("cf-connecting-ip")||t.headers.get("x-client-ip")||"unknown"}isPrivateIP(t){return[/^10\./,/^172\.(1[6-9]|2\d|3[01])\./,/^192\.168\./,/^127\./,/^169\.254\./,/^::1$/,/^fc00:/,/^fe80:/].some((o)=>o.test(t))}validateInput(t){let i=[];if(!this.options.attackPrevention?.enabled)return{isValid:!0,threats:i};if(this.options.attackPrevention.sqlInjection){for(let o of this.sqlInjectionPatterns)if(o.test(t)){i.push("SQL Injection");break}}if(this.options.attackPrevention.xss){for(let o of this.xssPatterns)if(o.test(t)){i.push("XSS");break}}if(this.options.attackPrevention.pathTraversal){for(let o of this.pathTraversalPatterns)if(o.test(t)){i.push("Path Traversal");break}}if(this.options.attackPrevention.commandInjection){for(let o of this.commandInjectionPatterns)if(o.test(t)){i.push("Command Injection");break}}if(this.options.attackPrevention.customPatterns){for(let o of this.options.attackPrevention.customPatterns)if(o.pattern.test(t))i.push(o.name)}return{isValid:i.length===0,threats:i}}sanitizeInput(t){if(!this.options.inputValidation?.sanitizeInput)return t;return t.replace(/[<>'"&]/g,(i)=>({"<":"<",">":">",'"':""","'":"'","&":"&"})[i]||i).replace(/javascript:/gi,"blocked:").replace(/vbscript:/gi,"blocked:").replace(/on\w+=/gi,"blocked=")}async handle(t,i){let o=this.getClientIP(t),a=t.headers.get("user-agent")||"",l=new URL(t.url);if(this.options.ipFiltering?.enabled){let p=this.options.ipFiltering;if(p.whitelist?.length&&!p.whitelist.includes(o))return new Response("Access Denied",{status:403});if(p.blacklist?.includes(o))return new Response("Access Denied",{status:403});if(p.blockPrivateIPs&&this.isPrivateIP(o))return new Response("Access Denied",{status:403})}if(this.options.requestFiltering?.enabled){let p=this.options.requestFiltering;if(p.allowedMethods&&!p.allowedMethods.includes(t.method))return new Response("Method Not Allowed",{status:405});if(p.requireUserAgent&&!a)return new Response("Bad Request",{status:400});if(p.blockUserAgents){if(p.blockUserAgents.some((P)=>a.toLowerCase().includes(P.toLowerCase())))return new Response("Access Denied",{status:403})}if(p.blockSuspiciousPatterns){let x=l.pathname+l.search;for(let P of this.suspiciousPatterns)if(P.test(x))return new Response("Suspicious Request Blocked",{status:400})}}if(this.options.inputValidation?.enabled){let p=this.options.inputValidation;if(p.maxUrlLength&&t.url.length>p.maxUrlLength)return new Response("URL Too Long",{status:414});let x=t.headers.get("content-type");if(x&&p.allowedContentTypes){if(!p.allowedContentTypes.some((T)=>x.toLowerCase().startsWith(T.toLowerCase())))return new Response("Unsupported Media Type",{status:415})}for(let[P,T]of l.searchParams.entries()){let k=this.validateInput(T);if(!k.isValid)return console.warn(`Security threat detected in query param ${P}:`,k.threats),new Response(`Security threat detected: ${k.threats.join(", ")}`,{status:400})}for(let[P,T]of t.headers.entries()){if(p.maxHeaderSize&&T.length>p.maxHeaderSize)return new Response("Header Too Large",{status:431});let k=this.validateInput(T);if(!k.isValid)return console.warn(`Security threat detected in header ${P}:`,k.threats),new Response(`Security threat detected: ${k.threats.join(", ")}`,{status:400})}}if(t.method!=="GET"&&t.method!=="HEAD"&&t.method!=="OPTIONS")try{let p=t.headers.get("content-length");if(p&&this.options.inputValidation?.maxBodySize){if(Number.parseInt(p,10)>this.options.inputValidation.maxBodySize)return new Response("Payload Too Large",{status:413})}}catch(p){console.error("Error checking content length:",p)}let d=await i();if(!d)return new Response("Not Found",{status:404});if(this.options.responseSecurity?.enabled){let p=new Headers(d.headers),x=this.options.responseSecurity;if(x.removeServerHeaders)p.delete("Server"),p.delete("X-Powered-By"),p.delete("X-AspNet-Version"),p.delete("X-AspNetMvc-Version");if(x.addSecurityHeaders)p.set("X-Content-Type-Options","nosniff"),p.set("X-Frame-Options","DENY"),p.set("X-XSS-Protection","0"),p.set("Referrer-Policy","strict-origin-when-cross-origin");return new Response(d.body,{status:d.status,statusText:d.statusText,headers:p})}return d}}function st(t={}){let i=new v(t);return async(o,a)=>i.handle(o,a)}class j{middlewares=[];constructor(t={}){let i=e.server?.security||{},o=["ddosProtection","security","helmet","contentSecurityPolicy","inputValidation"],a=t.order||o;for(let l of a)switch(l){case"ddosProtection":if(t.ddosProtection!==!1&&i.ddos?.enabled!==!1){let d=typeof t.ddosProtection==="object"?t.ddosProtection:{},p=new b(d);this.middlewares.push((x,P)=>p.handle(x,P))}break;case"security":if(t.security!==!1){let d=typeof t.security==="object"?t.security:{},p=new v(d);this.middlewares.push((x,P)=>p.handle(x,P))}break;case"helmet":if(t.helmet!==!1&&i.helmet?.enabled!==!1){let d=typeof t.helmet==="object"?t.helmet:{},p=new E(d);this.middlewares.push((x,P)=>p.handle(x,P))}break;case"contentSecurityPolicy":if(t.contentSecurityPolicy!==!1&&i.helmet?.contentSecurityPolicy!==!1){let d=typeof t.contentSecurityPolicy==="object"?t.contentSecurityPolicy:{},p=new w(d);this.middlewares.push((x,P)=>p.handle(x,P))}break;case"inputValidation":if(t.inputValidation!==!1&&i.inputValidation?.enabled!==!1){let d=typeof t.inputValidation==="object"?t.inputValidation:{},p=new R(d);this.middlewares.push((x,P)=>p.handle(x,P))}break}}async handle(t,i){let o=0,a=async()=>{if(o>=this.middlewares.length)return await i();let l=this.middlewares[o++];return await l(t,a)};return await a()}}function it(t={}){let i=new j(t);return async(o,a)=>i.handle(o,a)}var Rt=()=>new h,vt=()=>new m,xt=()=>new g,Tt=()=>new y,Ct=()=>new r;function St(){return new V({type:"bearer",validator:()=>!0})}var ce=null;function le(){if(!ce)ce={"Middleware/Cors":new h,"Middleware/JsonBody":new m,"Middleware/RequestId":new g,"Middleware/Session":new y,"Middleware/Csrf":new r,"Middleware/Auth":new V({type:"bearer",validator:()=>!0}),"Middleware/RateLimit":G(),"Middleware/RequestSigning":new f({secret:""})};return ce}var J=new Proxy({},{get(t,i){return le()[i]},ownKeys(){return Object.keys(le())},getOwnPropertyDescriptor(t,i){let o=le()[i];if(o!==void 0)return{configurable:!0,enumerable:!0,value:o};return}});
|
|
357
|
+
export{qe,s,me,wt,e,ge,W,fe,He,Be,je,Ue,Le,h,r,m,A,G,g,n,ye,f,_e,ze,Ve,u,O,I,F,bt,K,D,y,w,We,b,Ge,S,c,Ke,Je,Xe,Ye,Qe,E,R,Ze,N,et,q,tt,H,rt,B,nt,v,st,j,it,Rt,vt,xt,Tt,Ct,St,J};
|