@mateosuarezdev/brpc 1.0.50 → 1.0.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +701 -0
- package/dist/auth/types.d.ts +1 -0
- package/dist/auth/utils.d.ts +1 -0
- package/dist/cache/index.d.ts +1 -0
- package/dist/cache/types.d.ts +1 -0
- package/dist/context.d.ts +2 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +9 -8
- package/dist/middlewares/cors/index.d.ts +1 -0
- package/dist/middlewares/createMiddleware.d.ts +25 -0
- package/dist/middlewares/index.d.ts +1 -0
- package/dist/procedure.d.ts +4 -3
- package/dist/router/RouteMatcher.d.ts +3 -0
- package/dist/types.d.ts +2 -2
- package/package.json +103 -103
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{z as U}from"zod";class b{middlewares=[];constructor(
|
|
2
|
+
import{z as U}from"zod";class b{middlewares=[];constructor(J=[]){this.middlewares=J}use(J){return new b([...this.middlewares,J])}input(J){return new O(this.middlewares,J)}query(J){return{_input:U.object({}),_output:null,_ctx:null,_type:"query",handler:J,middlewares:this.middlewares}}mutation(J){return{_input:U.object({}),_output:null,_ctx:null,_type:"mutation",handler:J,middlewares:this.middlewares}}formMutation(J){return{_input:U.object({}),_output:null,_ctx:null,_type:"formMutation",handler:J,middlewares:this.middlewares}}subscription(J){return{_input:U.object({}),_output:null,_ctx:null,_type:"subscription",handler:J,middlewares:this.middlewares}}file(J){return{_input:U.object({}),_output:null,_ctx:null,_type:"file",handler:J,middlewares:this.middlewares}}fileStream(J){return{_input:U.object({}),_output:null,_ctx:null,_type:"fileStream",handler:J,middlewares:this.middlewares}}html(J){return{_input:U.object({}),_output:null,_ctx:null,_type:"html",handler:J,middlewares:this.middlewares}}}class O{middlewares;inputSchema;timeoutMs;constructor(J,_,W){this.middlewares=J;this.inputSchema=_;this.timeoutMs=W}timeout(J){return new O(this.middlewares,this.inputSchema,J)}query(J){return{_input:this.inputSchema,_output:null,_ctx:null,_type:"query",_timeout:this.timeoutMs,handler:J,middlewares:this.middlewares}}mutation(J){return{_input:this.inputSchema,_output:null,_ctx:null,_type:"mutation",_timeout:this.timeoutMs,handler:J,middlewares:this.middlewares}}formMutation(J){return{_input:this.inputSchema,_output:null,_ctx:null,_type:"formMutation",_timeout:this.timeoutMs,handler:J,middlewares:this.middlewares}}subscription(J){return{_input:this.inputSchema,_output:null,_ctx:null,_type:"subscription",_timeout:this.timeoutMs,handler:J,middlewares:this.middlewares}}file(J){return{_input:this.inputSchema,_output:null,_ctx:null,_type:"file",_timeout:this.timeoutMs,handler:J,middlewares:this.middlewares}}fileStream(J){return{_input:this.inputSchema,_output:null,_ctx:null,_type:"fileStream",_timeout:this.timeoutMs,handler:J,middlewares:this.middlewares}}html(J){return{_input:U.object({}),_output:null,_ctx:null,_type:"html",_timeout:this.timeoutMs,handler:J,middlewares:this.middlewares}}}function g(J){return new b}import{ZodError as P}from"zod";class I extends Error{code;clientCode;httpStatus;data;cause;static STATUS_MAP={BAD_REQUEST:400,UNAUTHORIZED:401,FORBIDDEN:403,NOT_FOUND:404,METHOD_NOT_SUPPORTED:405,TIMEOUT:408,CONFLICT:409,PRECONDITION_FAILED:412,PAYLOAD_TOO_LARGE:413,UNPROCESSABLE_CONTENT:422,TOO_MANY_REQUESTS:429,CLIENT_CLOSED_REQUEST:499,INTERNAL_SERVER_ERROR:500,NOT_IMPLEMENTED:501,BAD_GATEWAY:502,SERVICE_UNAVAILABLE:503,GATEWAY_TIMEOUT:504};constructor(J){super(J.message);if(this.name="BRPCError",this.code=J.code,this.clientCode=J.clientCode,this.httpStatus=I.STATUS_MAP[J.code],this.data=J.data,this.cause=J.cause,Error.captureStackTrace)Error.captureStackTrace(this,I)}toJSON(){return{name:this.name,code:this.code,clientCode:this.clientCode,message:this.message,data:this.data,httpStatus:this.httpStatus}}static badRequest(J,_,W){return new I({code:"BAD_REQUEST",message:J,clientCode:_,data:W})}static unauthorized(J="Unauthorized",_,W){return new I({code:"UNAUTHORIZED",message:J,clientCode:_,data:W})}static forbidden(J="Forbidden",_,W){return new I({code:"FORBIDDEN",message:J,clientCode:_,data:W})}static notFound(J="Not Found",_,W){return new I({code:"NOT_FOUND",message:J,clientCode:_,data:W})}static preconditionFailed(J="Precondition failed",_,W){return new I({code:"NOT_FOUND",message:J,clientCode:_,data:W})}static conflict(J,_,W){return new I({code:"CONFLICT",message:J,clientCode:_,data:W})}static unprocessableContent(J,_,W){return new I({code:"UNPROCESSABLE_CONTENT",message:J,clientCode:_,data:W})}static tooManyRequests(J="Too many requests",_,W){return new I({code:"TOO_MANY_REQUESTS",message:J,clientCode:_,data:W})}static internalServerError(J="Internal Server Error",_,W){return new I({code:"INTERNAL_SERVER_ERROR",message:J,clientCode:_,data:W})}static timeout(J="Request timeout",_,W){return new I({code:"TIMEOUT",message:J,clientCode:_,data:W})}}class Q{routeTree;routeCache;options;routeStats;constructor(J,_={}){if(this.options={enableCaching:!0,maxCacheSize:1000,debug:!1,..._},this.routeCache=new Map,this.routeStats=this.analyzeRoutes(J),this.routeTree=this.compileRoutes(J),this.options.debug)console.log("[ROUTEMATCHER]","initialized with stats:",this.routeStats)}match(J){if(this.options.enableCaching)return this.matchWithCache(J);return this.matchDirect(J)}matchWithCache(J){let _=J.join("/");if(this.routeCache.has(_)){let X=this.routeCache.get(_);if(this.options.debug&&X)console.log("[ROUTEMATCHER]",`\uD83C\uDFAF Cache hit for route: /${_}`);return X}let W=this.matchDirect(J);if(this.cacheResult(_,W),this.options.debug)console.log("[ROUTEMATCHER]",`\uD83D\uDCBE Cached route: /${_} -> ${W?"found":"not found"}`);return W}matchDirect(J){let _=this.options.debug?performance.now():0,W=this.traverseTree(this.routeTree,J,0,{});if(this.options.debug){let X=performance.now()-_,Y=W?.route._type||"none";console.log("[ROUTEMATCHER]",`\u26A1 Route match: /${J.join("/")} (${Y}) took ${X.toFixed(3)}ms`)}return W}traverseTree(J,_,W,X){if(W>=_.length){if(J.handler)return{params:X,route:J.handler.handler};if(J.index)return{params:X,route:J.index.handler};//! This was the last change I made trying to fix
|
|
3
3
|
//! Wildacrd not matching root (/) when index wasn't defined
|
|
4
|
-
if(F.wildcard&&J.length===0)return{params:{...W,wildcardPath:""},route:F.wildcard.handler};return null}let X=J[_],Y=decodeURIComponent(X),$=F.static.get(Y);if($){let A=this.traverseTree($,J,_+1,W);if(A)return A}if(F.param){let A={...W,[F.param.name]:Y},j=this.traverseTree(F.param.node,J,_+1,A);if(j)return j}if(F.wildcard){let A=J.slice(_).join("/");return{params:{...W,wildcardPath:A},route:F.wildcard.handler}}return null}compileRoutes(F,J=[]){let _={static:new Map};for(let[W,X]of Object.entries(F)){if(W==="index"&&this.isProcedure(X)){_.index={handler:X,paramNames:[...J],hasWildcard:!1};continue}if(W==="*"){if(this.isProcedure(X))_.wildcard={handler:X,paramNames:[...J,"wildcardPath"],hasWildcard:!0,wildcardIndex:J.length};continue}if(this.isProcedure(X)){let Y={handler:X,paramNames:[...J],hasWildcard:!1};if(W.startsWith(":")){let $=W.slice(1),A={static:new Map,handler:Y};_.param={name:$,node:A}}else{let $={static:new Map,handler:Y};_.static.set(W,$)}}else if(typeof X==="object"&&X!==null)if(W.startsWith(":")){let Y=W.slice(1),$=this.compileRoutes(X,[...J,Y]);_.param={name:Y,node:$}}else{let Y=this.compileRoutes(X,J);_.static.set(W,Y)}}return _}isProcedure(F){return F&&typeof F==="object"&&"_type"in F&&"_input"in F}cacheResult(F,J){if(this.routeCache.size>=this.options.maxCacheSize){let _=this.routeCache.keys().next().value;if(_!==void 0){if(this.routeCache.delete(_),this.options.debug)console.log(`\uD83D\uDDD1\uFE0F Evicted oldest cache entry: ${_}`)}}this.routeCache.set(F,J)}analyzeRoutes(F){let J={totalRoutes:0,staticRoutes:0,paramRoutes:0,wildcardRoutes:0,indexRoutes:0,maxDepth:0,procedureTypes:{query:0,mutation:0,subscription:0,file:0,fileStream:0,streamQuery:0,streamMutation:0,formMutation:0,html:0}},_=(W,X=0)=>{J.maxDepth=Math.max(J.maxDepth,X);for(let[Y,$]of Object.entries(W))if(this.isProcedure($)){if(J.totalRoutes++,$._type in J.procedureTypes)J.procedureTypes[$._type]++;if(Y==="index")J.indexRoutes++;else if(Y.startsWith(":"))J.paramRoutes++;else if(Y==="*")J.wildcardRoutes++;else J.staticRoutes++}else if(typeof $==="object"&&$!==null)_($,X+1)};return _(F),J}clearCache(){if(this.routeCache.clear(),this.options.debug)console.log("[ROUTEMATCHER]","\uD83E\uDDF9 Route cache cleared")}getCacheStats(){return{size:this.routeCache.size,maxSize:this.options.maxCacheSize,routeStats:this.routeStats}}getOptimizationSuggestions(){let F=[],{routeStats:J}=this;if(J.paramRoutes>J.staticRoutes*2)F.push("\uD83D\uDE80 Consider grouping routes to reduce parameter route overhead");if(J.maxDepth>6)F.push("\uD83D\uDCCA Deep route nesting detected - consider flattening some routes");if(J.totalRoutes>200)F.push("\u26A1 Large route table - consider route splitting or lazy loading");if(!this.options.enableCaching&&J.totalRoutes>50)F.push("\uD83D\uDCBE Enable caching for better performance with many routes");if(J.procedureTypes.file>20)F.push("\uD83D\uDCC1 Many file routes detected - consider static file serving");if(J.procedureTypes.subscription>10)F.push("\uD83D\uDD04 Many subscription routes - ensure WebSocket optimization");return F}findRoutesByPattern(F){return[]}getRouteInfo(F){let J=F.split("/").filter(Boolean),_=J.join("/"),W=this.routeCache.has(_),X=performance.now(),Y=this.matchDirect(J),$=performance.now()-X;return{found:!!Y,route:Y?.route,params:Y?.params,cached:W,matchTime:$}}benchmark(F,J=1000){let _=F.map((G)=>G.split("/").filter(Boolean)),W=new Map(this.routeCache);this.routeCache.clear();let X=performance.now();for(let G=0;G<J;G++)for(let V of _)this.matchDirect(V);let $=performance.now()-X,A=J*F.length,j=$/A,D=A/$*1000;return this.routeCache=W,{averageTime:j,totalTime:$,routesPerSecond:D}}warmupCache(F){if(!this.options.enableCaching)return;let J=performance.now(),_=0;for(let X of F){let Y=X.split("/").filter(Boolean),$=this.matchDirect(Y);if($)this.cacheResult(Y.join("/"),$),_++}let W=performance.now();if(this.options.debug)console.log("[ROUTEMATCHER]",`\uD83D\uDD25 Cache warmed up: ${_} routes in ${(W-J).toFixed(2)}ms`)}}var R=import.meta.require,C={NO_CACHE:{cacheControl:"no-cache, no-store, must-revalidate",expires:new Date(0).toUTCString()},ONE_YEAR:{cacheControl:"public, max-age=31536000",expires:new Date(Date.now()+31536000000).toUTCString()},IMMUTABLE:{cacheControl:"public, max-age=31536000, immutable",expires:new Date(Date.now()+31536000000).toUTCString()},ONE_MONTH:{cacheControl:"public, max-age=2592000"},ONE_WEEK:{cacheControl:"public, max-age=604800"},ONE_DAY:{cacheControl:"public, max-age=86400, must-revalidate"},ONE_HOUR:{cacheControl:"public, max-age=3600, must-revalidate"},FIVE_MINUTES:{cacheControl:"public, max-age=300"},API:{cacheControl:"public, max-age=300, s-maxage=3600"},STYLESHEET:{cacheControl:"public, max-age=2592000, must-revalidate"},JAVASCRIPT:{cacheControl:"public, max-age=2592000, must-revalidate"},HASHED_ASSET:{cacheControl:"public, max-age=31536000, immutable",expires:new Date(Date.now()+31536000000).toUTCString()},FONT:{cacheControl:"public, max-age=31536000",expires:new Date(Date.now()+31536000000).toUTCString()},IMAGE:{cacheControl:"public, max-age=2592000"},FAVICON:{cacheControl:"public, max-age=31536000",expires:new Date(Date.now()+31536000000).toUTCString()},HTML_PAGE:{cacheControl:"public, max-age=3600, must-revalidate"},API_RESPONSE:{cacheControl:"public, max-age=300, s-maxage=900"},FEED:{cacheControl:"public, max-age=3600"},SITEMAP:{cacheControl:"public, max-age=86400"},MANIFEST:{cacheControl:"public, max-age=86400, must-revalidate"},SERVICE_WORKER:{cacheControl:"no-cache, no-store, must-revalidate",expires:new Date(0).toUTCString()},MEDIA_STREAM:{cacheControl:"no-cache, no-store"},DOCUMENT:{cacheControl:"public, max-age=86400"},ARCHIVE:{cacheControl:"public, max-age=604800"}};function q(F){return C[F]}var v={html:"text/html; charset=utf-8",css:"text/css",javascript:"application/javascript",json:"application/json",xml:"application/xml",text:"text/plain; charset=utf-8",csv:"text/csv",markdown:"text/markdown; charset=utf-8",png:"image/png",jpeg:"image/jpeg",gif:"image/gif",svg:"image/svg+xml",webp:"image/webp",icon:"image/x-icon",bmp:"image/bmp",woff:"font/woff",woff2:"font/woff2",truetype:"font/ttf","embedded-opentype":"application/vnd.ms-fontobject",opentype:"font/otf",mp4:"video/mp4",webm:"video/webm",ogg:"video/ogg",mpeg:"audio/mpeg",wav:"audio/wav",flac:"audio/flac",pdf:"application/pdf",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",zip:"application/zip",tar:"application/x-tar",gzip:"application/gzip","7z":"application/x-7z-compressed",js:"application/javascript",txt:"text/plain; charset=utf-8",jpg:"image/jpeg",ico:"image/x-icon",ttf:"font/ttf",eot:"application/vnd.ms-fontobject",otf:"font/otf",mp3:"audio/mpeg",gz:"application/gzip"};function S(F){return v[F]||"application/octet-stream"}function y(F){if(typeof Bun<"u"&&Bun.hash)return Bun.hash(F).toString(16);try{let J=R("crypto"),_;if(typeof F==="string")_=Buffer.from(F);else if(F instanceof ArrayBuffer)_=Buffer.from(new Uint8Array(F));else _=Buffer.from(F);return J.createHash("md5").update(_).digest("hex")}catch{let J=typeof F==="string"?new TextEncoder().encode(F):F instanceof ArrayBuffer?new Uint8Array(F):F,_=0;for(let W=0;W<J.length;W++)_=(_<<5)-_+J[W],_=_&_;return Math.abs(_).toString(16).padStart(16,"0")}}function I(F,J,_){let W=F.headers.get("Origin"),X=!0;if((_?.allowAll??!0)&&W)return W;if(J.length===0)return W||"*";if(!W)return J[0];if(J.includes(W))return W;return J[0]}class B{headers={};contentType(F){return this.headers["Content-Type"]=S(F),this}filePath(F){let J=F.split(".").pop()?.toLowerCase()||"";return this.headers["Content-Type"]=S(J),this}mimeType(F){return this.headers["Content-Type"]=F,this}cache(F){let{cacheControl:J,expires:_}=q(F);if(this.headers["Cache-Control"]=J,_)this.headers.Expires=_;return this}eTag(F){if(!F)return this;let J;if(typeof F==="string"&&F.startsWith('"'))J=F;else J=`"${y(F)}"`;return this.headers.ETag=J,this}lastModified(F){return this.headers["Last-Modified"]=F.toUTCString(),this}contentLength(F){return this.headers["Content-Length"]=F.toString(),this}redirect(F,J=!1){return this.headers.Location=F,this.headers["X-Redirect-Type"]=J?"permanent":"temporary",this}cors({origin:F="*",methods:J=["GET","POST","PUT","DELETE","OPTIONS"],headers:_=["Content-Type","Authorization"],maxAge:W=86400,credentials:X}={}){let Y=X??F!=="*";if(Y&&F==="*")throw Error('CORS: Cannot use credentials with wildcard origin "*". Specify an exact origin or set credentials to false.');if(this.headers["Access-Control-Allow-Origin"]=F,this.headers["Access-Control-Allow-Methods"]=J.join(", "),this.headers["Access-Control-Allow-Headers"]=_.join(", "),Y)this.headers["Access-Control-Allow-Credentials"]="true";return this.headers["Access-Control-Max-Age"]=W.toString(),this}security(F){let J={hsts:!0,noSniff:!0,frameOptions:"SAMEORIGIN",xssProtection:!0,...F};if(J.csp)this.headers["Content-Security-Policy"]=J.csp;if(J.hsts){let _=typeof J.hsts==="number"?J.hsts:31536000;this.headers["Strict-Transport-Security"]=`max-age=${_}; includeSubDomains`}if(J.noSniff)this.headers["X-Content-Type-Options"]="nosniff";if(J.frameOptions)this.headers["X-Frame-Options"]=J.frameOptions;if(J.xssProtection)this.headers["X-XSS-Protection"]="1; mode=block";return this}custom(F,J){return this.headers[F]=J,this}customHeaders(F){return Object.assign(this.headers,F),this}vary(...F){let J=this.headers.Vary,_=J?`${J}, ${F.join(", ")}`:F.join(", ");return this.headers.Vary=_,this}compress(F){if(F)this.headers["Content-Encoding"]=F;return this}build(F){let J={...this.headers};if(F&&!J["Content-Length"]){let _=typeof F==="string"?new TextEncoder().encode(F).length:F.byteLength;J["Content-Length"]=_.toString()}return J}buildHeaders(F){return new Headers(this.build(F))}}function Z(){return new B}function c(F,J){let _=Z().contentType(F);if(J)_.cache(J);return _.build()}var l={css:(F)=>Z().contentType("css").cache("STYLESHEET").eTag(F),javascript:(F)=>Z().contentType("javascript").cache("JAVASCRIPT").eTag(F),hashedAsset:(F,J)=>Z().filePath(F).cache("HASHED_ASSET").eTag(J),font:(F)=>Z().filePath(F).cache("FONT").cors({origin:"*"}),image:(F)=>Z().filePath(F).cache("IMAGE"),favicon:()=>Z().contentType("icon").cache("FAVICON"),api:()=>Z().contentType("json").cache("API_RESPONSE").cors(),expensiveApi:(F)=>Z().contentType("json").cache("API_RESPONSE").cors().eTag(F),realtime:()=>Z().contentType("json").cache("NO_CACHE").cors(),html:()=>Z().contentType("html").cache("HTML_PAGE").security(),expensiveHtml:(F)=>Z().contentType("html").cache("HTML_PAGE").security().eTag(F),manifest:(F)=>Z().contentType("json").cache("MANIFEST").eTag(F),serviceWorker:()=>Z().contentType("javascript").cache("SERVICE_WORKER"),sitemap:(F)=>Z().contentType("xml").cache("SITEMAP").eTag(F),feed:(F,J="rss")=>Z().contentType("xml").cache("FEED").eTag(F).mimeType(J==="rss"?"application/rss+xml":"application/atom+xml"),video:(F)=>Z().filePath(F).cache("MEDIA_STREAM").custom("Accept-Ranges","bytes"),audio:(F)=>Z().filePath(F).cache("MEDIA_STREAM").custom("Accept-Ranges","bytes"),pdf:(F)=>Z().contentType("pdf").cache("DOCUMENT").custom("Content-Disposition","inline").eTag(F),download:(F,J,_)=>Z().filePath(J).cache("ARCHIVE").custom("Content-Disposition",`attachment; filename="${F}"`).eTag(_),secure:()=>Z().security({csp:"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'",hsts:31536000}).custom("X-Powered-By","Bun"),permanentRedirect:(F)=>Z().redirect(F,!0),temporaryRedirect:(F)=>Z().redirect(F,!1)};async function E(F,J,_,W={}){let{maxChunkSize:X=2097152,cacheMaxAge:Y=3600,acceptedExtensions:$}=W;if(!await F.exists())return new Response("Media file not found",{status:404,headers:Z().contentType("text").cors({origin:I(J,_)}).build()});if($&&$.length>0){let K=F.name?.toLowerCase().split(".").pop();if(!K||!$.includes(K))return new Response("File type not supported",{status:415,headers:Z().contentType("text").cors({origin:I(J,_)}).build()})}let j=F.size,D=J.headers.get("Range");if(!D)return new Response(F,{headers:Z().filePath(F.name||"media").custom("Accept-Ranges","bytes").custom("Cache-Control",`public, max-age=${Y}`).cors({origin:I(J,_)}).build()});let G=D.match(/bytes=(\d*)-(\d*)/);if(!G)return new Response("Invalid Range header",{status:416,headers:Z().contentType("text").cors({origin:I(J,_)}).custom("Content-Range",`bytes */${j}`).build()});let V=G[1]?parseInt(G[1]):0,N=G[2]?parseInt(G[2]):j-1,Q=Math.min(N,V+X-1,j-1);if(V>=j||Q>=j||V>Q)return new Response("Range not satisfiable",{status:416,headers:Z().contentType("text").cors({origin:I(J,_)}).custom("Content-Range",`bytes */${j}`).build()});return new Response(F.slice(V,Q+1),{status:206,headers:Z().filePath(F.name||"media").custom("Accept-Ranges","bytes").custom("Cache-Control",`public, max-age=${Y}`).cors({origin:I(J,_)}).build()})}function z(F,J,_){return{type:"stream",file:F,request:J,options:_}}class H{routes;routeMatcher;contextCreator;prefix;globalMiddlewares;server=null;wsConfig;integrations;development=!0;debug=!1;allowedOrigins=[];onError;activeConnections=new Set;maxConnections=parseInt(process.env.MAX_WS_CONNECTIONS??"1000");connectionTimeout=parseInt(process.env.WS_TIMEOUT??"30000");maxRequestSize=parseInt(process.env.MAX_REQUEST_SIZE??"10485760");requestTimeout=parseInt(process.env.REQUEST_TIMEOUT??"30000");constructor(F){if(this.contextCreator=F.context,this.prefix=F.prefix??"",this.routes=F.routes,this.globalMiddlewares=F.globalMiddlewares??[],this.wsConfig=F.websocket??{},this.integrations=F.integrations,this.debug=!!F.debug&&!0,this.onError=F.onError,this.routeMatcher=new M(F.routes,{enableCaching:!this.development,maxCacheSize:parseInt(process.env.ROUTE_CACHE_SIZE??"1000"),debug:this.debug}),!this.development)setInterval(()=>this.cleanupStaleConnections(),60000);if(this.debug)console.log("Router initialized with route matcher"),console.log("Route cache stats:",this.routeMatcher.getCacheStats())}findRoute(F){return this.routeMatcher.match(F)}async parseInput(F,J,_){let W={},X=new URL(F.url),Y=Object.fromEntries(X.searchParams),$=F.method;if($==="POST"){if(parseInt(F.headers.get("content-length")||"0")>this.maxRequestSize)throw Error("Request payload too large")}if($==="GET"&&["query","streamQuery","file","fileStream","html"].includes(_))W=Y;else if($==="POST"&&["mutation","formMutation","streamMutation"].includes(_)){let A=F.headers.get("content-type");if(A?.includes("application/json"))W=await F.json();else if(A?.includes("multipart/form-data")){let j=await F.formData();W=await this.parseFormData(j)}else throw Error("Unsupported content type")}else throw Error(`Unsupported request method ${$} for procedure type ${_}`);return J.parse(W)}async parseFormData(F){let J={},_={};F.forEach(async(W,X)=>{if(W instanceof File){if(!_[X])_[X]=[];_[X].push(W)}else if(typeof W==="string")try{J[X]=JSON.parse(W)}catch{J[X]=W}});for(let[W,X]of Object.entries(_))J[W]=X;return J}handleError(F,J){if(this.onError)try{this.onError(F,{req:J,route:J.url})}catch(_){console.error("Error logger failed:",_)}if(F?.errors&&Array.isArray(F.errors)&&F.name==="ZodError")return new Response(JSON.stringify({error:{name:"ValidationError",code:"BAD_REQUEST",clientCode:"VALIDATION_ERROR",message:"Input validation failed",data:{validationErrors:F.errors.map((_)=>({path:_.path.join("."),message:_.message,code:_.code,received:_.received}))},httpStatus:400}}),{status:400,headers:Z().contentType("json").cors({origin:I(J,this.allowedOrigins)}).build()});if(F instanceof L)return new Response(JSON.stringify({error:F.toJSON()}),{status:F.httpStatus,headers:Z().contentType("json").cors({origin:I(J,this.allowedOrigins)}).build()});if(F instanceof Error){let _=F.message==="Not Found"?404:F.message==="Unauthorized"?401:F.message==="Forbidden"?403:F.message==="Request payload too large"?413:F.message==="Request timeout"?504:500,W=_===404?"NOT_FOUND":_===401?"UNAUTHORIZED":_===403?"FORBIDDEN":_===413?"PAYLOAD_TOO_LARGE":_===504?"GATEWAY_TIMEOUT":"INTERNAL_SERVER_ERROR",X=_<500?F.message:"Internal Server Error";return new Response(JSON.stringify({error:{code:W,message:X}}),{status:_,headers:Z().contentType("json").cors({origin:I(J,this.allowedOrigins)}).build()})}return new Response(JSON.stringify({error:{code:"INTERNAL_SERVER_ERROR",message:"Internal Server Error"}}),{status:500,headers:Z().contentType("json").cors({origin:I(J,this.allowedOrigins)}).build()})}handleFileCacheControl(F){let J;if(F?.includes("text/html"))J="public, max-age=0, must-revalidate";else if(F?.includes("text/css")||F?.includes("text/javascript")||F?.includes("application/javascript"))J="public, max-age=31536000, immutable";else J="public, max-age=86400, stale-while-revalidate=604800";return J}async handleRequest(F,J){try{if(F.method==="OPTIONS")return new Response(null,{status:204,headers:Z().cors({origin:I(F,this.allowedOrigins)}).build()});let W=new URL(F.url).pathname;if(W=W.startsWith(this.prefix)?W.slice(this.prefix.length):W,W=W.startsWith("/")?W:"/"+W,W==="/ws"&&J){if(this.debug)console.log("\uD83D\uDD0C WebSocket upgrade requested");return this.handleWebSocketUpgrade(F,J)}let X=W==="/"?[]:W.split("/").filter(Boolean),Y=this.findRoute(X);if(!Y)return new Response("Not Found",{status:404,headers:Z().contentType("text").cors({origin:I(F,this.allowedOrigins)}).build()});let{route:$}=Y,A=$._timeout??this.requestTimeout,j=new Promise((D,G)=>{setTimeout(()=>G(Error("Request timeout")),A)});return await Promise.race([this._handleRequest(F,J,Y),j])}catch(_){return this.handleError(_,F)}}async _handleRequest(F,J,_){try{if(!_)return new Response("Not Found",{status:404,headers:Z().contentType("text").cors({origin:I(F,this.allowedOrigins)}).build()});let{params:W,route:X}=_;if(!X.handler)return new Response("Handler not implemented",{status:501,headers:Z().contentType("text").cors({origin:I(F,this.allowedOrigins)}).build()});let Y=new Headers,$=await this.contextCreator(F);Object.assign($,{params:W,publishToProcedure:async(G,V,N)=>{await this.publishToProcedure(G,V,$,N)},headers:Y});for(let G of this.globalMiddlewares)await G($);for(let G of X.middlewares)await G($);let A=await this.parseInput(F,X._input,X._type),j=await X.handler({ctx:$,input:A}),D=Z().cors({origin:I(F,this.allowedOrigins)}).build();return Object.keys(D).forEach((G)=>{Y.set(G,D[G])}),await this.handleProcedureResponse(X._type,j,Y)}catch(W){return this.handleError(W,F)}}async testRequest(F){return this.handleRequest(F)}async handleProcedureResponse(F,J,_){switch(F){case"file":if(J instanceof Response)return J;let W=J.type;return _.append("Content-Type",W),_.append("Cache-Control",this.development?"public, max-age=0, must-revalidate":this.handleFileCacheControl(W)),new Response(J,{headers:_});case"fileStream":if(typeof J==="object"&&J!==null&&"type"in J&&J.type==="stream"){let Y=J;return await E(J.file,J.request,this.allowedOrigins,Y.options)}let X=J.type;return _.append("Content-Type",X),_.append("Cache-Control",this.development?"public, max-age=0, must-revalidate":this.handleFileCacheControl(X)),new Response(J,{headers:_});case"html":if(typeof J==="string")return _.append("Content-Type","text/html"),new Response(J,{headers:_});break;case"query":case"mutation":case"formMutation":case"streamQuery":case"streamMutation":case"subscription":default:return _.append("Content-Type","application/json"),new Response(JSON.stringify({data:J}),{headers:_})}return _.append("Content-Type","application/json"),new Response(JSON.stringify({data:J}),{headers:_})}cleanupStaleConnections(){let F=Date.now();for(let J of this.activeConnections)if(F-J.data.lastActivity>this.connectionTimeout)J.close(),this.activeConnections.delete(J)}async handleWebSocketUpgrade(F,J){if(this.activeConnections.size>=this.maxConnections)return new Response("Too many connections",{status:503});let _=await this.contextCreator(F);for(let X of this.globalMiddlewares)await X(_);if(J.upgrade(F,{data:{ctx:_,topics:new Set,lastActivity:Date.now()}}))return new Response(null,{status:101});return new Response("WebSocket upgrade failed",{status:500})}async handleAuthenticate(F,J,_){try{let W=J.startsWith("Bearer ")?J.substring(7):J;if(F.data.ctx.authToken=W,F.send(JSON.stringify({type:"auth_success",message:"Authentication successful"})),this.debug)console.log("[BRPC]","WebSocket authenticated successfully")}catch(W){if(F.send(JSON.stringify({type:"auth_error",error:W instanceof Error?W.message:"Authentication failed"})),this.debug)console.error("WebSocket authentication error:",W)}}async handleSubscribe(F,J,_){let W=this.findRoute(J.split("/").filter(Boolean));if(!W||W.route._type!=="subscription")throw Error("Invalid subscription route");F.subscribe(J),F.data.topics.add(J)}async handleUnsubscribe(F,J,_){let W=this.findRoute(J.split("/").filter(Boolean));if(!W||W.route._type!=="subscription")throw Error("Invalid subscription route");F.unsubscribe(J),F.data.topics.delete(J)}async handlePublish(F,J,_,W){let X=this.findRoute(J.split("/").filter(Boolean));if(!X)throw Error("Subscription not found");let{params:Y,route:$}=X;if($._type!=="subscription"||!$.handler)throw Error("Invalid subscription route");Object.assign(W,{params:Y});let A=$._input.fields?$._input.parse(_):_,j=await $.handler({ctx:W,input:A}),D={topic:J,data:j,type:"publish"};if(this.debug)console.log(`Server will publish to ${J}`,D);this.server.publish(J,JSON.stringify(D))}async publishToProcedure(F,J,_,W){if(F._type!=="subscription"||!F.handler)throw Error("Can only publish to subscription procedures");let X=this.findRoutePath(this.routes,F);if(!X)throw Error("Subscription route not found");let Y=X.split("/").map((j)=>{if(j.startsWith(":")){let D=j.slice(1),G=W[D];if(!G)throw Error(`Missing parameter: ${D}`);return G}return j}).join("/"),$=await F.handler({ctx:{..._,params:W},input:J}),A={topic:Y,data:$,type:"publish"};if(this.debug)console.log(`Server will publish to ${Y}`,A);return this.server?.publish(Y,JSON.stringify(A)),$}async publish(F,J,_){if(F._type!=="subscription"||!F.handler)throw Error("Can only publish to subscription procedures");let W=this.findRoutePath(this.routes,F);if(!W)throw Error("Subscription route not found");let X=W.split("/").map((A)=>{if(A.startsWith(":")){let j=A.slice(1),D=_?_[j]:null;if(!D)throw Error(`Missing parameter: ${j}`);return D}return A}).join("/"),Y=await F.handler({ctx:{params:_},input:J}),$={topic:X,data:Y,type:"publish"};if(this.debug)console.log(`Server will publish to ${X}`,$);return this.server?.publish(X,JSON.stringify($)),Y}freePublish(F,J){let _={topic:F,data:J,type:"publish"};this.server?.publish(F,JSON.stringify(_))}findRoutePath(F,J,_=""){for(let[W,X]of Object.entries(F)){let Y=_?`${_}/${W}`:W;if(X===J)return Y;if(X&&typeof X==="object"&&!("_type"in X)){let $=this.findRoutePath(X,J,Y);if($)return $}}return null}getIntegrationRoutes(){if(!this.integrations)return;let F={};if(this.integrations.betterAuth){let J=this.integrations.betterAuth.handler;if(!J)throw Error("Please provide a handler for betterAuth integration");F["/api/auth/*"]=async(_)=>{return await J(_)}}if(this.integrations.rawRoutes)Object.keys(this.integrations.rawRoutes).forEach((J)=>{F[J]=this.integrations.rawRoutes[J]});return Object.keys(F).length>0?F:void 0}getRouteStats(){return{cache:this.routeMatcher.getCacheStats(),suggestions:this.routeMatcher.getOptimizationSuggestions()}}clearRouteCache(){if(this.routeMatcher.clearCache(),this.debug)console.log("[ROUTEMATCHER] Route cache cleared")}benchmarkRoutes(F=["/users/123","/posts/456/comments"],J=1000){if(this.debug){let _=this.routeMatcher.benchmark(F,J);return console.log("[ROUTEMATCHER]","Route matching benchmark:",_),_}}updateRoutes(F){if(this.development)this.routes=F,this.routeMatcher=new M(F,{enableCaching:!1,debug:this.debug}),console.log("[HMR]","Server Routes updated");else console.warn("Route updates are only allowed in development mode")}listen(F,J){if(this.server=Bun.serve({port:F,routes:this.getIntegrationRoutes(),fetch:(_,W)=>this.handleRequest(_,W),websocket:{open:(_)=>{if(this.activeConnections.add(_),this.wsConfig?.onOpen)this.wsConfig.onOpen(_,_.data.ctx);if(this.debug)console.log("[BRPC]","WebSocket connection opened",{connections:this.activeConnections.size})},message:async(_,W)=>{try{_.data.lastActivity=Date.now();let{type:X,topic:Y,token:$,data:A}=JSON.parse(W),j=_.data.ctx;if(this.debug)console.log("[BRPC]","WebSocket message received:",{type:X,topic:Y});switch(X){case"authenticate":await this.handleAuthenticate(_,$,j);break;case"subscribe":await this.handleSubscribe(_,Y,j);break;case"unsubscribe":await this.handleUnsubscribe(_,Y,j);break;case"publish":await this.handlePublish(_,Y,A,j);break;default:if(_.send(JSON.stringify({error:"Unknown message type"})),this.debug)console.error("Unknown WebSocket message type:",X)}}catch(X){if(this.debug)console.error("[BRPC]","WebSocket message error:",X);if(X instanceof f)_.send(JSON.stringify({error:"Invalid message format"}));else if(X instanceof Error)_.send(JSON.stringify({error:X.message}))}},close:(_,W,X)=>{if(this.activeConnections.delete(_),_.data.topics.forEach((Y)=>{_.unsubscribe(Y)}),this.debug)console.log("[BRPC]","WebSocket connection closed",{code:W,reason:X,remainingConnections:this.activeConnections.size});if(this.wsConfig?.onClose)this.wsConfig.onClose(_,W,X,_.data.ctx)}}}),J)J()}}function e(F){return new H(F)}function J9(F){return F}import{z as P}from"zod";var w={image:["image/jpeg","image/png","image/gif","image/webp","image/svg+xml"],video:["video/mp4","video/webm","video/ogg"],audio:["audio/mpeg","audio/ogg","audio/wav"],document:["application/pdf","application/msword","application/vnd.openxmlformats-officedocument.wordprocessingml.document","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"]},T=(F,J="MB")=>{switch(J){case"MB":return F*1024*1024;case"KB":return F*1024;case"B":return F}},X9=({acceptedTypes:F,maxSize:J=1/0,minSize:_,messages:W={}}={})=>{let X=J?T(J):1/0,Y=_?T(_):0,$=F?Object.entries(F).flatMap(([j,D])=>{let G=j;if(D==="*")return w[G];if(Array.isArray(D))return D;return[]}):void 0,A=P.instanceof(File,{message:W.required??"File is required"});if(A=A.refine((j)=>j.size<=X,W.maxSize??`File size must be less than ${J}MB`).refine((j)=>j.size>=Y,W.minSize??`File size must be at least ${_}MB`),$?.length)A=A.refine((j)=>$.includes(j.type),W.type??`File must be of type: ${$.join(", ")}`);return A};var $9=(F)=>{let J=F.paths.map((W)=>new RegExp(W)),_="Not Found";return async(W)=>{let Y=new URL(W.req.url).pathname;if(J.some(($)=>$.test(Y)))throw Error("Not Found")}};class x{requests=new Map;lastCleanupTime=Date.now();alertThreshold;config;constructor(F){this.config={windowMs:F.windowMs,maxRequests:F.maxRequests,maxEntries:F.maxEntries??1e4,cleanupIntervalMs:F.cleanupIntervalMs??60000,message:F.message??"Too Many Requests",statusCode:F.statusCode??429,headerPrefix:F.headerPrefix??"X-RateLimit"},this.alertThreshold=this.config.maxEntries*0.8}cleanup(){let F=Date.now(),J=0;for(let[_,W]of this.requests.entries()){let X=F-W.startTime>this.config.windowMs,Y=F-W.lastAccessed>this.config.windowMs*2;if(X||Y)this.requests.delete(_),J++}return this.lastCleanupTime=F,J}handleMaxEntries(F){let J=this.requests.size;if(Date.now()-this.lastCleanupTime>this.config.cleanupIntervalMs)this.cleanup();if(J>=this.alertThreshold)console.warn(`Rate limiter at ${Math.round(J/this.config.maxEntries*100)}% capacity`);if(this.requests.has(F))return!0;return J<this.config.maxEntries}check(F){if(!this.handleMaxEntries(F))return{isLimited:!0,remaining:0,resetTime:Date.now()+this.config.windowMs};let J=Date.now(),_=this.requests.get(F);if(!_||J-_.startTime>=this.config.windowMs)return this.requests.set(F,{count:1,startTime:J,lastAccessed:J}),{isLimited:!1,remaining:this.config.maxRequests-1,resetTime:J+this.config.windowMs};_.lastAccessed=J;let W=_.count>=this.config.maxRequests;if(!W)_.count++;return{isLimited:W,remaining:Math.max(0,this.config.maxRequests-_.count),resetTime:_.startTime+this.config.windowMs}}getConfig(){return this.config}}var Z9=(F)=>{let J=new x(F);return async(_)=>{if(_.req.headers.get("range"))return;let W=_.req.headers.get("x-forwarded-for")?.split(",")[0]||_.req.headers.get("x-real-ip")||"unknown",{isLimited:X,remaining:Y,resetTime:$}=J.check(W),{headerPrefix:A}=J.getConfig();if(_.headers.set(`${A}-Remaining`,Y.toString()),_.headers.set(`${A}-Reset`,$.toString()),X)throw _.headers.set(`${A}-Exceeded`,"true"),Error(J.getConfig().message)}};export{z as streamMedia,c as quickHeaders,y as hashContent,S as getMimeType,I as getCorsOrigin,e as createRouter,Z9 as createRateLimiter,h as createProcedure,$9 as createPathBlocker,X9 as createFileSchema,J9 as createContext,l as commonHeaders,Z as buildHeaders,H as Router,L as BRPCError};
|
|
4
|
+
if(J.wildcard&&_.length===0)return{params:{...X,wildcardPath:""},route:J.wildcard.handler};return null}let Y=_[W],$=decodeURIComponent(Y),F=J.static.get($);if(F){let j=this.traverseTree(F,_,W+1,X);if(j)return j}if(J.param){let j={...X,[J.param.name]:$},Z=this.traverseTree(J.param.node,_,W+1,j);if(Z)return Z}if(J.wildcard){let j=_.slice(W).join("/");return{params:{...X,wildcardPath:j},route:J.wildcard.handler}}return null}compileRoutes(J,_=[]){let W={static:new Map};for(let[X,Y]of Object.entries(J)){if(X==="index"&&this.isProcedure(Y)){W.index={handler:Y,paramNames:[..._],hasWildcard:!1};continue}if(X==="*"){if(this.isProcedure(Y))W.wildcard={handler:Y,paramNames:[..._,"wildcardPath"],hasWildcard:!0,wildcardIndex:_.length};continue}if(this.isProcedure(Y)){let $={handler:Y,paramNames:[..._],hasWildcard:!1};if(X.startsWith(":")){let F=X.slice(1),j={static:new Map,handler:$};W.param={name:F,node:j}}else{let F={static:new Map,handler:$};W.static.set(X,F)}}else if(typeof Y==="object"&&Y!==null)if(X.startsWith(":")){let $=X.slice(1),F=this.compileRoutes(Y,[..._,$]);W.param={name:$,node:F}}else{let $=this.compileRoutes(Y,_);W.static.set(X,$)}}return W}isProcedure(J){return J&&typeof J==="object"&&"_type"in J&&"_input"in J}cacheResult(J,_){if(this.routeCache.size>=this.options.maxCacheSize){let W=this.routeCache.keys().next().value;if(W!==void 0){if(this.routeCache.delete(W),this.options.debug)console.log(`\uD83D\uDDD1\uFE0F Evicted oldest cache entry: ${W}`)}}this.routeCache.set(J,_)}analyzeRoutes(J){let _={totalRoutes:0,staticRoutes:0,paramRoutes:0,wildcardRoutes:0,indexRoutes:0,maxDepth:0,procedureTypes:{query:0,mutation:0,subscription:0,file:0,fileStream:0,streamQuery:0,streamMutation:0,formMutation:0,html:0}},W=(X,Y=0)=>{_.maxDepth=Math.max(_.maxDepth,Y);for(let[$,F]of Object.entries(X))if(this.isProcedure(F)){if(_.totalRoutes++,F._type in _.procedureTypes)_.procedureTypes[F._type]++;if($==="index")_.indexRoutes++;else if($.startsWith(":"))_.paramRoutes++;else if($==="*")_.wildcardRoutes++;else _.staticRoutes++}else if(typeof F==="object"&&F!==null)W(F,Y+1)};return W(J),_}clearCache(){if(this.routeCache.clear(),this.options.debug)console.log("[ROUTEMATCHER]","\uD83E\uDDF9 Route cache cleared")}getCacheStats(){return{size:this.routeCache.size,maxSize:this.options.maxCacheSize,routeStats:this.routeStats}}getOptimizationSuggestions(){let J=[],{routeStats:_}=this;if(_.paramRoutes>_.staticRoutes*2)J.push("\uD83D\uDE80 Consider grouping routes to reduce parameter route overhead");if(_.maxDepth>6)J.push("\uD83D\uDCCA Deep route nesting detected - consider flattening some routes");if(_.totalRoutes>200)J.push("\u26A1 Large route table - consider route splitting or lazy loading");if(!this.options.enableCaching&&_.totalRoutes>50)J.push("\uD83D\uDCBE Enable caching for better performance with many routes");if(_.procedureTypes.file>20)J.push("\uD83D\uDCC1 Many file routes detected - consider static file serving");if(_.procedureTypes.subscription>10)J.push("\uD83D\uDD04 Many subscription routes - ensure WebSocket optimization");return J}findRoutesByPattern(J){return[]}getRouteInfo(J){let _=J.split("/").filter(Boolean),W=_.join("/"),X=this.routeCache.has(W),Y=performance.now(),$=this.matchDirect(_),F=performance.now()-Y;return{found:!!$,route:$?.route,params:$?.params,cached:X,matchTime:F}}benchmark(J,_=1000){let W=J.map((G)=>G.split("/").filter(Boolean)),X=new Map(this.routeCache);this.routeCache.clear();let Y=performance.now();for(let G=0;G<_;G++)for(let D of W)this.matchDirect(D);let F=performance.now()-Y,j=_*J.length,Z=F/j,L=j/F*1000;return this.routeCache=X,{averageTime:Z,totalTime:F,routesPerSecond:L}}warmupCache(J){if(!this.options.enableCaching)return;let _=performance.now(),W=0;for(let Y of J){let $=Y.split("/").filter(Boolean),F=this.matchDirect($);if(F)this.cacheResult($.join("/"),F),W++}let X=performance.now();if(this.options.debug)console.log("[ROUTEMATCHER]",`\uD83D\uDD25 Cache warmed up: ${W} routes in ${(X-_).toFixed(2)}ms`)}}var C=import.meta.require,x={NO_CACHE:{cacheControl:"no-cache, no-store, must-revalidate",expires:new Date(0).toUTCString()},ONE_YEAR:{cacheControl:"public, max-age=31536000",expires:new Date(Date.now()+31536000000).toUTCString()},IMMUTABLE:{cacheControl:"public, max-age=31536000, immutable",expires:new Date(Date.now()+31536000000).toUTCString()},ONE_MONTH:{cacheControl:"public, max-age=2592000"},ONE_WEEK:{cacheControl:"public, max-age=604800"},ONE_DAY:{cacheControl:"public, max-age=86400, must-revalidate"},ONE_HOUR:{cacheControl:"public, max-age=3600, must-revalidate"},FIVE_MINUTES:{cacheControl:"public, max-age=300"},API:{cacheControl:"public, max-age=300, s-maxage=3600"},STYLESHEET:{cacheControl:"public, max-age=2592000, must-revalidate"},JAVASCRIPT:{cacheControl:"public, max-age=2592000, must-revalidate"},HASHED_ASSET:{cacheControl:"public, max-age=31536000, immutable",expires:new Date(Date.now()+31536000000).toUTCString()},FONT:{cacheControl:"public, max-age=31536000",expires:new Date(Date.now()+31536000000).toUTCString()},IMAGE:{cacheControl:"public, max-age=2592000"},FAVICON:{cacheControl:"public, max-age=31536000",expires:new Date(Date.now()+31536000000).toUTCString()},HTML_PAGE:{cacheControl:"public, max-age=3600, must-revalidate"},API_RESPONSE:{cacheControl:"public, max-age=300, s-maxage=900"},FEED:{cacheControl:"public, max-age=3600"},SITEMAP:{cacheControl:"public, max-age=86400"},MANIFEST:{cacheControl:"public, max-age=86400, must-revalidate"},SERVICE_WORKER:{cacheControl:"no-cache, no-store, must-revalidate",expires:new Date(0).toUTCString()},MEDIA_STREAM:{cacheControl:"no-cache, no-store"},DOCUMENT:{cacheControl:"public, max-age=86400"},ARCHIVE:{cacheControl:"public, max-age=604800"}};function q(J){return x[J]}var v={html:"text/html; charset=utf-8",css:"text/css",javascript:"application/javascript",json:"application/json",xml:"application/xml",text:"text/plain; charset=utf-8",csv:"text/csv",markdown:"text/markdown; charset=utf-8",png:"image/png",jpeg:"image/jpeg",gif:"image/gif",svg:"image/svg+xml",webp:"image/webp",icon:"image/x-icon",bmp:"image/bmp",woff:"font/woff",woff2:"font/woff2",truetype:"font/ttf","embedded-opentype":"application/vnd.ms-fontobject",opentype:"font/otf",mp4:"video/mp4",webm:"video/webm",ogg:"video/ogg",mpeg:"audio/mpeg",wav:"audio/wav",flac:"audio/flac",pdf:"application/pdf",doc:"application/msword",docx:"application/vnd.openxmlformats-officedocument.wordprocessingml.document",zip:"application/zip",tar:"application/x-tar",gzip:"application/gzip","7z":"application/x-7z-compressed",js:"application/javascript",txt:"text/plain; charset=utf-8",jpg:"image/jpeg",ico:"image/x-icon",ttf:"font/ttf",eot:"application/vnd.ms-fontobject",otf:"font/otf",mp3:"audio/mpeg",gz:"application/gzip"};function B(J){return v[J]||"application/octet-stream"}function z(J){if(typeof Bun<"u"&&Bun.hash)return Bun.hash(J).toString(16);try{let _=C("crypto"),W;if(typeof J==="string")W=Buffer.from(J);else if(J instanceof ArrayBuffer)W=Buffer.from(new Uint8Array(J));else W=Buffer.from(J);return _.createHash("md5").update(W).digest("hex")}catch{let _=typeof J==="string"?new TextEncoder().encode(J):J instanceof ArrayBuffer?new Uint8Array(J):J,W=0;for(let X=0;X<_.length;X++)W=(W<<5)-W+_[X],W=W&W;return Math.abs(W).toString(16).padStart(16,"0")}}function V(J,_,W){let X=J.headers.get("Origin"),Y=!0;if((W?.allowAll??!0)&&X)return X;if(_.length===0)return X||"*";if(!X)return _[0];if(_.includes(X))return X;return _[0]}class S{headers={};contentType(J){return this.headers["Content-Type"]=B(J),this}filePath(J){let _=J.split(".").pop()?.toLowerCase()||"";return this.headers["Content-Type"]=B(_),this}mimeType(J){return this.headers["Content-Type"]=J,this}cache(J){let{cacheControl:_,expires:W}=q(J);if(this.headers["Cache-Control"]=_,W)this.headers.Expires=W;return this}eTag(J){if(!J)return this;let _;if(typeof J==="string"&&J.startsWith('"'))_=J;else _=`"${z(J)}"`;return this.headers.ETag=_,this}lastModified(J){return this.headers["Last-Modified"]=J.toUTCString(),this}contentLength(J){return this.headers["Content-Length"]=J.toString(),this}redirect(J,_=!1){return this.headers.Location=J,this.headers["X-Redirect-Type"]=_?"permanent":"temporary",this}cors({origin:J="*",methods:_=["GET","POST","PUT","DELETE","OPTIONS"],headers:W=["Content-Type","Authorization"],maxAge:X=86400,credentials:Y}={}){let $=Y??J!=="*";if($&&J==="*")throw Error('CORS: Cannot use credentials with wildcard origin "*". Specify an exact origin or set credentials to false.');if(this.headers["Access-Control-Allow-Origin"]=J,this.headers["Access-Control-Allow-Methods"]=_.join(", "),this.headers["Access-Control-Allow-Headers"]=W.join(", "),$)this.headers["Access-Control-Allow-Credentials"]="true";return this.headers["Access-Control-Max-Age"]=X.toString(),this}security(J){let _={hsts:!0,noSniff:!0,frameOptions:"SAMEORIGIN",xssProtection:!0,...J};if(_.csp)this.headers["Content-Security-Policy"]=_.csp;if(_.hsts){let W=typeof _.hsts==="number"?_.hsts:31536000;this.headers["Strict-Transport-Security"]=`max-age=${W}; includeSubDomains`}if(_.noSniff)this.headers["X-Content-Type-Options"]="nosniff";if(_.frameOptions)this.headers["X-Frame-Options"]=_.frameOptions;if(_.xssProtection)this.headers["X-XSS-Protection"]="1; mode=block";return this}custom(J,_){return this.headers[J]=_,this}customHeaders(J){return Object.assign(this.headers,J),this}vary(...J){let _=this.headers.Vary,W=_?`${_}, ${J.join(", ")}`:J.join(", ");return this.headers.Vary=W,this}compress(J){if(J)this.headers["Content-Encoding"]=J;return this}build(J){let _={...this.headers};if(J&&!_["Content-Length"]){let W=typeof J==="string"?new TextEncoder().encode(J).length:J.byteLength;_["Content-Length"]=W.toString()}return _}buildHeaders(J){return new Headers(this.build(J))}}function A(){return new S}function l(J,_){let W=A().contentType(J);if(_)W.cache(_);return W.build()}var c={css:(J)=>A().contentType("css").cache("STYLESHEET").eTag(J),javascript:(J)=>A().contentType("javascript").cache("JAVASCRIPT").eTag(J),hashedAsset:(J,_)=>A().filePath(J).cache("HASHED_ASSET").eTag(_),font:(J)=>A().filePath(J).cache("FONT").cors({origin:"*"}),image:(J)=>A().filePath(J).cache("IMAGE"),favicon:()=>A().contentType("icon").cache("FAVICON"),api:()=>A().contentType("json").cache("API_RESPONSE").cors(),expensiveApi:(J)=>A().contentType("json").cache("API_RESPONSE").cors().eTag(J),realtime:()=>A().contentType("json").cache("NO_CACHE").cors(),html:()=>A().contentType("html").cache("HTML_PAGE").security(),expensiveHtml:(J)=>A().contentType("html").cache("HTML_PAGE").security().eTag(J),manifest:(J)=>A().contentType("json").cache("MANIFEST").eTag(J),serviceWorker:()=>A().contentType("javascript").cache("SERVICE_WORKER"),sitemap:(J)=>A().contentType("xml").cache("SITEMAP").eTag(J),feed:(J,_="rss")=>A().contentType("xml").cache("FEED").eTag(J).mimeType(_==="rss"?"application/rss+xml":"application/atom+xml"),video:(J)=>A().filePath(J).cache("MEDIA_STREAM").custom("Accept-Ranges","bytes"),audio:(J)=>A().filePath(J).cache("MEDIA_STREAM").custom("Accept-Ranges","bytes"),pdf:(J)=>A().contentType("pdf").cache("DOCUMENT").custom("Content-Disposition","inline").eTag(J),download:(J,_,W)=>A().filePath(_).cache("ARCHIVE").custom("Content-Disposition",`attachment; filename="${J}"`).eTag(W),secure:()=>A().security({csp:"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'",hsts:31536000}).custom("X-Powered-By","Bun"),permanentRedirect:(J)=>A().redirect(J,!0),temporaryRedirect:(J)=>A().redirect(J,!1)};async function E(J,_,W,X={}){let{maxChunkSize:Y=2097152,cacheMaxAge:$=3600,acceptedExtensions:F}=X;if(!await J.exists())return new Response("Media file not found",{status:404,headers:A().contentType("text").cors({origin:V(_,W)}).build()});if(F&&F.length>0){let K=J.name?.toLowerCase().split(".").pop();if(!K||!F.includes(K))return new Response("File type not supported",{status:415,headers:A().contentType("text").cors({origin:V(_,W)}).build()})}let Z=J.size,L=_.headers.get("Range");if(!L)return new Response(J,{headers:A().filePath(J.name||"media").custom("Accept-Ranges","bytes").custom("Cache-Control",`public, max-age=${$}`).cors({origin:V(_,W)}).build()});let G=L.match(/bytes=(\d*)-(\d*)/);if(!G)return new Response("Invalid Range header",{status:416,headers:A().contentType("text").cors({origin:V(_,W)}).custom("Content-Range",`bytes */${Z}`).build()});let D=G[1]?parseInt(G[1]):0,N=G[2]?parseInt(G[2]):Z-1,M=Math.min(N,D+Y-1,Z-1);if(D>=Z||M>=Z||D>M)return new Response("Range not satisfiable",{status:416,headers:A().contentType("text").cors({origin:V(_,W)}).custom("Content-Range",`bytes */${Z}`).build()});return new Response(J.slice(D,M+1),{status:206,headers:A().filePath(J.name||"media").custom("Accept-Ranges","bytes").custom("Cache-Control",`public, max-age=${$}`).cors({origin:V(_,W)}).build()})}function y(J,_,W){return{type:"stream",file:J,request:_,options:W}}class T{routes;routeMatcher;contextCreator;prefix;globalMiddlewares;server=null;wsConfig;integrations;development=!0;debug=!1;allowedOrigins=[];onError;activeConnections=new Set;maxConnections=parseInt(process.env.MAX_WS_CONNECTIONS??"1000");connectionTimeout=parseInt(process.env.WS_TIMEOUT??"30000");maxRequestSize=parseInt(process.env.MAX_REQUEST_SIZE??"10485760");requestTimeout=parseInt(process.env.REQUEST_TIMEOUT??"30000");constructor(J){if(this.contextCreator=J.context,this.prefix=J.prefix??"",this.routes=J.routes,this.globalMiddlewares=J.globalMiddlewares??[],this.wsConfig=J.websocket??{},this.integrations=J.integrations,this.debug=!!J.debug&&!0,this.onError=J.onError,this.routeMatcher=new Q(J.routes,{enableCaching:!this.development,maxCacheSize:parseInt(process.env.ROUTE_CACHE_SIZE??"1000"),debug:this.debug}),!this.development)setInterval(()=>this.cleanupStaleConnections(),60000);if(this.debug)console.log("Router initialized with route matcher"),console.log("Route cache stats:",this.routeMatcher.getCacheStats())}findRoute(J){return this.routeMatcher.match(J)}async parseInput(J,_,W){let X={},Y=new URL(J.url),$=Object.fromEntries(Y.searchParams),F=J.method;if(F==="POST"){if(parseInt(J.headers.get("content-length")||"0")>this.maxRequestSize)throw Error("Request payload too large")}if(F==="GET"&&["query","streamQuery","file","fileStream","html"].includes(W))X=$;else if(F==="POST"&&["mutation","formMutation","streamMutation"].includes(W)){let j=J.headers.get("content-type");if(j?.includes("application/json"))X=await J.json();else if(j?.includes("multipart/form-data")){let Z=await J.formData();X=await this.parseFormData(Z)}else throw Error("Unsupported content type")}else throw Error(`Unsupported request method ${F} for procedure type ${W}`);return _.parse(X)}async parseFormData(J){let _={},W={};J.forEach(async(X,Y)=>{if(X instanceof File){if(!W[Y])W[Y]=[];W[Y].push(X)}else if(typeof X==="string")try{_[Y]=JSON.parse(X)}catch{_[Y]=X}});for(let[X,Y]of Object.entries(W))_[X]=Y;return _}handleError(J,_){if(this.onError)try{this.onError(J,{req:_,route:_.url})}catch(W){console.error("Error logger failed:",W)}if(J?.errors&&Array.isArray(J.errors)&&J.name==="ZodError")return new Response(JSON.stringify({error:{name:"ValidationError",code:"BAD_REQUEST",clientCode:"VALIDATION_ERROR",message:"Input validation failed",data:{validationErrors:J.errors.map((W)=>({path:W.path.join("."),message:W.message,code:W.code,received:W.received}))},httpStatus:400}}),{status:400,headers:A().contentType("json").cors({origin:V(_,this.allowedOrigins)}).build()});if(J instanceof I)return new Response(JSON.stringify({error:J.toJSON()}),{status:J.httpStatus,headers:A().contentType("json").cors({origin:V(_,this.allowedOrigins)}).build()});if(J instanceof Error){let W=J.message==="Not Found"?404:J.message==="Unauthorized"?401:J.message==="Forbidden"?403:J.message==="Request payload too large"?413:J.message==="Request timeout"?504:500,X=W===404?"NOT_FOUND":W===401?"UNAUTHORIZED":W===403?"FORBIDDEN":W===413?"PAYLOAD_TOO_LARGE":W===504?"GATEWAY_TIMEOUT":"INTERNAL_SERVER_ERROR",Y=W<500?J.message:"Internal Server Error";return new Response(JSON.stringify({error:{code:X,message:Y}}),{status:W,headers:A().contentType("json").cors({origin:V(_,this.allowedOrigins)}).build()})}return new Response(JSON.stringify({error:{code:"INTERNAL_SERVER_ERROR",message:"Internal Server Error"}}),{status:500,headers:A().contentType("json").cors({origin:V(_,this.allowedOrigins)}).build()})}handleFileCacheControl(J){let _;if(J?.includes("text/html"))_="public, max-age=0, must-revalidate";else if(J?.includes("text/css")||J?.includes("text/javascript")||J?.includes("application/javascript"))_="public, max-age=31536000, immutable";else _="public, max-age=86400, stale-while-revalidate=604800";return _}async handleRequest(J,_){try{if(J.method==="OPTIONS")return new Response(null,{status:204,headers:A().cors({origin:V(J,this.allowedOrigins)}).build()});let X=new URL(J.url).pathname;if(X=X.startsWith(this.prefix)?X.slice(this.prefix.length):X,X=X.startsWith("/")?X:"/"+X,X==="/ws"&&_){if(this.debug)console.log("\uD83D\uDD0C WebSocket upgrade requested");return this.handleWebSocketUpgrade(J,_)}let Y=X==="/"?[]:X.split("/").filter(Boolean),$=this.findRoute(Y);if(!$)return new Response("Not Found",{status:404,headers:A().contentType("text").cors({origin:V(J,this.allowedOrigins)}).build()});let{route:F}=$,j=F._timeout??this.requestTimeout,Z=new Promise((L,G)=>{setTimeout(()=>G(Error("Request timeout")),j)});return await Promise.race([this._handleRequest(J,_,$),Z])}catch(W){return this.handleError(W,J)}}async _handleRequest(J,_,W){try{if(!W)return new Response("Not Found",{status:404,headers:A().contentType("text").cors({origin:V(J,this.allowedOrigins)}).build()});let{params:X,route:Y}=W;if(!Y.handler)return new Response("Handler not implemented",{status:501,headers:A().contentType("text").cors({origin:V(J,this.allowedOrigins)}).build()});let $=new Headers,F=await this.contextCreator(J);Object.assign(F,{req:J,params:X,publishToProcedure:async(G,D,N)=>{await this.publishToProcedure(G,D,F,N)},headers:$});for(let G of this.globalMiddlewares){let D=await G(F);if(D!==null&&D!==void 0&&typeof D==="object")Object.assign(F,D)}for(let G of Y.middlewares){let D=await G(F);if(D!==null&&D!==void 0&&typeof D==="object")Object.assign(F,D)}let j=await this.parseInput(J,Y._input,Y._type),Z=await Y.handler({ctx:F,input:j}),L=A().cors({origin:V(J,this.allowedOrigins)}).build();return Object.keys(L).forEach((G)=>{$.set(G,L[G])}),await this.handleProcedureResponse(Y._type,Z,$)}catch(X){return this.handleError(X,J)}}async testRequest(J){return this.handleRequest(J)}async handleProcedureResponse(J,_,W){switch(J){case"file":if(_ instanceof Response)return _;let X=_.type;return W.append("Content-Type",X),W.append("Cache-Control",this.development?"public, max-age=0, must-revalidate":this.handleFileCacheControl(X)),new Response(_,{headers:W});case"fileStream":if(typeof _==="object"&&_!==null&&"type"in _&&_.type==="stream"){let $=_;return await E(_.file,_.request,this.allowedOrigins,$.options)}let Y=_.type;return W.append("Content-Type",Y),W.append("Cache-Control",this.development?"public, max-age=0, must-revalidate":this.handleFileCacheControl(Y)),new Response(_,{headers:W});case"html":if(typeof _==="string")return W.append("Content-Type","text/html"),new Response(_,{headers:W});break;case"query":case"mutation":case"formMutation":case"streamQuery":case"streamMutation":case"subscription":default:return W.append("Content-Type","application/json"),new Response(JSON.stringify({data:_}),{headers:W})}return W.append("Content-Type","application/json"),new Response(JSON.stringify({data:_}),{headers:W})}cleanupStaleConnections(){let J=Date.now();for(let _ of this.activeConnections)if(J-_.data.lastActivity>this.connectionTimeout)_.close(),this.activeConnections.delete(_)}async handleWebSocketUpgrade(J,_){if(this.activeConnections.size>=this.maxConnections)return new Response("Too many connections",{status:503});let W=await this.contextCreator(J);Object.assign(W,{req:J});for(let Y of this.globalMiddlewares){let $=await Y(W);if($!==null&&$!==void 0&&typeof $==="object")Object.assign(W,$)}if(_.upgrade(J,{data:{ctx:W,topics:new Set,lastActivity:Date.now()}}))return new Response(null,{status:101});return new Response("WebSocket upgrade failed",{status:500})}async handleAuthenticate(J,_,W){try{let X=_.startsWith("Bearer ")?_.substring(7):_;if(J.data.ctx.authToken=X,J.send(JSON.stringify({type:"auth_success",message:"Authentication successful"})),this.debug)console.log("[BRPC]","WebSocket authenticated successfully")}catch(X){if(J.send(JSON.stringify({type:"auth_error",error:X instanceof Error?X.message:"Authentication failed"})),this.debug)console.error("WebSocket authentication error:",X)}}async handleSubscribe(J,_,W){let X=this.findRoute(_.split("/").filter(Boolean));if(!X||X.route._type!=="subscription")throw Error("Invalid subscription route");J.subscribe(_),J.data.topics.add(_)}async handleUnsubscribe(J,_,W){let X=this.findRoute(_.split("/").filter(Boolean));if(!X||X.route._type!=="subscription")throw Error("Invalid subscription route");J.unsubscribe(_),J.data.topics.delete(_)}async handlePublish(J,_,W,X){let Y=this.findRoute(_.split("/").filter(Boolean));if(!Y)throw Error("Subscription not found");let{params:$,route:F}=Y;if(F._type!=="subscription"||!F.handler)throw Error("Invalid subscription route");Object.assign(X,{params:$});let j=F._input.fields?F._input.parse(W):W,Z=await F.handler({ctx:X,input:j}),L={topic:_,data:Z,type:"publish"};if(this.debug)console.log(`Server will publish to ${_}`,L);this.server.publish(_,JSON.stringify(L))}async publishToProcedure(J,_,W,X){if(J._type!=="subscription"||!J.handler)throw Error("Can only publish to subscription procedures");let Y=this.findRoutePath(this.routes,J);if(!Y)throw Error("Subscription route not found");let $=Y.split("/").map((Z)=>{if(Z.startsWith(":")){let L=Z.slice(1),G=X[L];if(!G)throw Error(`Missing parameter: ${L}`);return G}return Z}).join("/"),F=await J.handler({ctx:{...W,params:X},input:_}),j={topic:$,data:F,type:"publish"};if(this.debug)console.log(`Server will publish to ${$}`,j);return this.server?.publish($,JSON.stringify(j)),F}async publish(J,_,W){if(J._type!=="subscription"||!J.handler)throw Error("Can only publish to subscription procedures");let X=this.findRoutePath(this.routes,J);if(!X)throw Error("Subscription route not found");let Y=X.split("/").map((j)=>{if(j.startsWith(":")){let Z=j.slice(1),L=W?W[Z]:null;if(!L)throw Error(`Missing parameter: ${Z}`);return L}return j}).join("/"),$=await J.handler({ctx:{params:W},input:_}),F={topic:Y,data:$,type:"publish"};if(this.debug)console.log(`Server will publish to ${Y}`,F);return this.server?.publish(Y,JSON.stringify(F)),$}freePublish(J,_){let W={topic:J,data:_,type:"publish"};this.server?.publish(J,JSON.stringify(W))}findRoutePath(J,_,W=""){for(let[X,Y]of Object.entries(J)){let $=W?`${W}/${X}`:X;if(Y===_)return $;if(Y&&typeof Y==="object"&&!("_type"in Y)){let F=this.findRoutePath(Y,_,$);if(F)return F}}return null}getIntegrationRoutes(){if(!this.integrations)return;let J={};if(this.integrations.betterAuth){let _=this.integrations.betterAuth.handler;if(!_)throw Error("Please provide a handler for betterAuth integration");J["/api/auth/*"]=async(W)=>{return await _(W)}}if(this.integrations.rawRoutes)Object.keys(this.integrations.rawRoutes).forEach((_)=>{J[_]=this.integrations.rawRoutes[_]});return Object.keys(J).length>0?J:void 0}getRouteStats(){return{cache:this.routeMatcher.getCacheStats(),suggestions:this.routeMatcher.getOptimizationSuggestions()}}clearRouteCache(){if(this.routeMatcher.clearCache(),this.debug)console.log("[ROUTEMATCHER] Route cache cleared")}benchmarkRoutes(J=["/users/123","/posts/456/comments"],_=1000){if(this.debug){let W=this.routeMatcher.benchmark(J,_);return console.log("[ROUTEMATCHER]","Route matching benchmark:",W),W}}updateRoutes(J){if(this.development)this.routes=J,this.routeMatcher=new Q(J,{enableCaching:!1,debug:this.debug}),console.log("[HMR]","Server Routes updated");else console.warn("Route updates are only allowed in development mode")}listen(J,_){if(this.server=Bun.serve({port:J,routes:this.getIntegrationRoutes(),fetch:(W,X)=>this.handleRequest(W,X),websocket:{open:(W)=>{if(this.activeConnections.add(W),this.wsConfig?.onOpen)this.wsConfig.onOpen(W,W.data.ctx);if(this.debug)console.log("[BRPC]","WebSocket connection opened",{connections:this.activeConnections.size})},message:async(W,X)=>{try{W.data.lastActivity=Date.now();let{type:Y,topic:$,token:F,data:j}=JSON.parse(X),Z=W.data.ctx;if(this.debug)console.log("[BRPC]","WebSocket message received:",{type:Y,topic:$});switch(Y){case"authenticate":await this.handleAuthenticate(W,F,Z);break;case"subscribe":await this.handleSubscribe(W,$,Z);break;case"unsubscribe":await this.handleUnsubscribe(W,$,Z);break;case"publish":await this.handlePublish(W,$,j,Z);break;default:if(W.send(JSON.stringify({error:"Unknown message type"})),this.debug)console.error("Unknown WebSocket message type:",Y)}}catch(Y){if(this.debug)console.error("[BRPC]","WebSocket message error:",Y);if(Y instanceof P)W.send(JSON.stringify({error:"Invalid message format"}));else if(Y instanceof Error)W.send(JSON.stringify({error:Y.message}))}},close:(W,X,Y)=>{if(this.activeConnections.delete(W),W.data.topics.forEach(($)=>{W.unsubscribe($)}),this.debug)console.log("[BRPC]","WebSocket connection closed",{code:X,reason:Y,remainingConnections:this.activeConnections.size});if(this.wsConfig?.onClose)this.wsConfig.onClose(W,X,Y,W.data.ctx)}}}),_)_()}}function e(J){return new T(J)}function _9(J){return J}import{z as f}from"zod";var w={image:["image/jpeg","image/png","image/gif","image/webp","image/svg+xml"],video:["video/mp4","video/webm","video/ogg"],audio:["audio/mpeg","audio/ogg","audio/wav"],document:["application/pdf","application/msword","application/vnd.openxmlformats-officedocument.wordprocessingml.document","application/vnd.ms-excel","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"]},H=(J,_="MB")=>{switch(_){case"MB":return J*1024*1024;case"KB":return J*1024;case"B":return J}},Y9=({acceptedTypes:J,maxSize:_=1/0,minSize:W,messages:X={}}={})=>{let Y=_?H(_):1/0,$=W?H(W):0,F=J?Object.entries(J).flatMap(([Z,L])=>{let G=Z;if(L==="*")return w[G];if(Array.isArray(L))return L;return[]}):void 0,j=f.instanceof(File,{message:X.required??"File is required"});if(j=j.refine((Z)=>Z.size<=Y,X.maxSize??`File size must be less than ${_}MB`).refine((Z)=>Z.size>=$,X.minSize??`File size must be at least ${W}MB`),F?.length)j=j.refine((Z)=>F.includes(Z.type),X.type??`File must be of type: ${F.join(", ")}`);return j};var F9=(J)=>{let _=J.paths.map((X)=>new RegExp(X)),W="Not Found";return async(X)=>{let $=new URL(X.req.url).pathname;if(_.some((F)=>F.test($)))throw Error("Not Found")}};class R{requests=new Map;lastCleanupTime=Date.now();alertThreshold;config;constructor(J){this.config={windowMs:J.windowMs,maxRequests:J.maxRequests,maxEntries:J.maxEntries??1e4,cleanupIntervalMs:J.cleanupIntervalMs??60000,message:J.message??"Too Many Requests",statusCode:J.statusCode??429,headerPrefix:J.headerPrefix??"X-RateLimit"},this.alertThreshold=this.config.maxEntries*0.8}cleanup(){let J=Date.now(),_=0;for(let[W,X]of this.requests.entries()){let Y=J-X.startTime>this.config.windowMs,$=J-X.lastAccessed>this.config.windowMs*2;if(Y||$)this.requests.delete(W),_++}return this.lastCleanupTime=J,_}handleMaxEntries(J){let _=this.requests.size;if(Date.now()-this.lastCleanupTime>this.config.cleanupIntervalMs)this.cleanup();if(_>=this.alertThreshold)console.warn(`Rate limiter at ${Math.round(_/this.config.maxEntries*100)}% capacity`);if(this.requests.has(J))return!0;return _<this.config.maxEntries}check(J){if(!this.handleMaxEntries(J))return{isLimited:!0,remaining:0,resetTime:Date.now()+this.config.windowMs};let _=Date.now(),W=this.requests.get(J);if(!W||_-W.startTime>=this.config.windowMs)return this.requests.set(J,{count:1,startTime:_,lastAccessed:_}),{isLimited:!1,remaining:this.config.maxRequests-1,resetTime:_+this.config.windowMs};W.lastAccessed=_;let X=W.count>=this.config.maxRequests;if(!X)W.count++;return{isLimited:X,remaining:Math.max(0,this.config.maxRequests-W.count),resetTime:W.startTime+this.config.windowMs}}getConfig(){return this.config}}var A9=(J)=>{let _=new R(J);return async(W)=>{if(W.req.headers.get("range"))return;let X=W.req.headers.get("x-forwarded-for")?.split(",")[0]||W.req.headers.get("x-real-ip")||"unknown",{isLimited:Y,remaining:$,resetTime:F}=_.check(X),{headerPrefix:j}=_.getConfig();if(W.headers.set(`${j}-Remaining`,$.toString()),W.headers.set(`${j}-Reset`,F.toString()),Y)throw W.headers.set(`${j}-Exceeded`,"true"),Error(_.getConfig().message)}};function G9(J,_){return _??J}export{y as streamMedia,l as quickHeaders,z as hashContent,B as getMimeType,V as getCorsOrigin,e as createRouter,A9 as createRateLimiter,g as createProcedure,F9 as createPathBlocker,G9 as createMiddleware,Y9 as createFileSchema,_9 as createContext,c as commonHeaders,A as buildHeaders,T as Router,I as BRPCError};
|
|
5
5
|
|
|
6
|
-
//# debugId=
|
|
6
|
+
//# debugId=A0ABAC27AD65C3FD64756E2164756E21
|