@mateosuarezdev/brpc 1.0.52 → 1.0.53
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/cache/index.d.ts +117 -0
- package/dist/client/index.js +2 -2
- package/dist/client/index.js.map +6 -6
- package/dist/client/storage.d.ts +1 -1
- package/dist/client/types.d.ts +12 -0
- package/dist/client/ws-manager.d.ts +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -3
- package/dist/index.js.map +5 -4
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/measure.d.ts +1 -0
- package/package.json +1 -1
- package/dist/cache/types.d.ts +0 -1
package/dist/cache/index.d.ts
CHANGED
|
@@ -1 +1,118 @@
|
|
|
1
|
+
type CacheOptions = {
|
|
2
|
+
ttl?: number;
|
|
3
|
+
maxSize?: number;
|
|
4
|
+
cleanupInterval?: number;
|
|
5
|
+
};
|
|
6
|
+
export declare class CacheService {
|
|
7
|
+
private entries;
|
|
8
|
+
private accessOrder;
|
|
9
|
+
private readonly maxSize;
|
|
10
|
+
private readonly defaultTTL;
|
|
11
|
+
private cleanupTimer;
|
|
12
|
+
private accessCounter;
|
|
13
|
+
constructor(options?: CacheOptions);
|
|
14
|
+
/**
|
|
15
|
+
* Set a value in cache with optional TTL
|
|
16
|
+
*/
|
|
17
|
+
set(key: string, value: any, ttl?: number): void;
|
|
18
|
+
/**
|
|
19
|
+
* Get a value from cache (returns null if expired or not found)
|
|
20
|
+
*/
|
|
21
|
+
get<T = any>(key: string): T | null;
|
|
22
|
+
/**
|
|
23
|
+
* Check if key exists and is not expired
|
|
24
|
+
*/
|
|
25
|
+
has(key: string): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Delete a specific key
|
|
28
|
+
*/
|
|
29
|
+
delete(key: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Clear all cache entries
|
|
32
|
+
*/
|
|
33
|
+
clear(): void;
|
|
34
|
+
/**
|
|
35
|
+
* Get all keys (including expired ones)
|
|
36
|
+
*/
|
|
37
|
+
keys(): string[];
|
|
38
|
+
/**
|
|
39
|
+
* Get all valid (non-expired) keys
|
|
40
|
+
*/
|
|
41
|
+
validKeys(): string[];
|
|
42
|
+
/**
|
|
43
|
+
* Get cache size
|
|
44
|
+
*/
|
|
45
|
+
size(): number;
|
|
46
|
+
/**
|
|
47
|
+
* Get or set pattern (lazy evaluation)
|
|
48
|
+
*/
|
|
49
|
+
getOrSet<T = any>(key: string, factory: () => T | Promise<T>, ttl?: number): Promise<T>;
|
|
50
|
+
/**
|
|
51
|
+
* Set value with expiration timestamp (instead of TTL)
|
|
52
|
+
*/
|
|
53
|
+
setWithExpiry(key: string, value: any, expiresAt: number): void;
|
|
54
|
+
/**
|
|
55
|
+
* Get remaining TTL for a key (in milliseconds)
|
|
56
|
+
*/
|
|
57
|
+
ttl(key: string): number | null;
|
|
58
|
+
/**
|
|
59
|
+
* Update TTL for existing key
|
|
60
|
+
*/
|
|
61
|
+
expire(key: string, ttl: number): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Remove expiration from key
|
|
64
|
+
*/
|
|
65
|
+
persist(key: string): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Delete keys matching a pattern (simple wildcard support)
|
|
68
|
+
*/
|
|
69
|
+
deletePattern(pattern: string): number;
|
|
70
|
+
/**
|
|
71
|
+
* Get multiple keys at once
|
|
72
|
+
*/
|
|
73
|
+
mget<T = any>(keys: string[]): (T | null)[];
|
|
74
|
+
/**
|
|
75
|
+
* Set multiple keys at once
|
|
76
|
+
*/
|
|
77
|
+
mset(entries: Record<string, any>, ttl?: number): void;
|
|
78
|
+
/**
|
|
79
|
+
* Increment a numeric value (creates if doesn't exist)
|
|
80
|
+
*/
|
|
81
|
+
incr(key: string, amount?: number): number;
|
|
82
|
+
/**
|
|
83
|
+
* Decrement a numeric value
|
|
84
|
+
*/
|
|
85
|
+
decr(key: string, amount?: number): number;
|
|
86
|
+
/**
|
|
87
|
+
* Get cache statistics
|
|
88
|
+
*/
|
|
89
|
+
stats(): {
|
|
90
|
+
size: number;
|
|
91
|
+
valid: number;
|
|
92
|
+
expired: number;
|
|
93
|
+
maxSize: number;
|
|
94
|
+
defaultTTL: number | null;
|
|
95
|
+
entries: {
|
|
96
|
+
key: string;
|
|
97
|
+
expiresIn: number | null;
|
|
98
|
+
age: number;
|
|
99
|
+
}[];
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Clean up expired entries
|
|
103
|
+
*/
|
|
104
|
+
cleanup(): number;
|
|
105
|
+
/**
|
|
106
|
+
* Track access for LRU
|
|
107
|
+
*/
|
|
108
|
+
private trackAccess;
|
|
109
|
+
/**
|
|
110
|
+
* Evict least recently used entry
|
|
111
|
+
*/
|
|
112
|
+
private evictLRU;
|
|
113
|
+
/**
|
|
114
|
+
* Destroy cache and cleanup timers
|
|
115
|
+
*/
|
|
116
|
+
destroy(): void;
|
|
117
|
+
}
|
|
1
118
|
export {};
|
package/dist/client/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
function v(q,G={placeholder:void 0,throwOnInvalid:!0}){if(!q)return G?.placeholder??"PLACEHOLDER";if(q.url)return q.url;if(q.key)if(q.isPrivate||q.provider==="local")return`/storage/${q.key}`;else return`${import.meta.env.VITE_S3_CDN_ENDPOINT}/${q.key}`;if(G.throwOnInvalid)throw Error("Invalid storage object");else return G?.placeholder??"PLACEHOLDER"}class T extends Error{status;code;clientCode;data;constructor(q,G,L,N,E){super(q);this.name="BrpcClientError",this.status=G,this.code=L,this.clientCode=N,this.data=E}isClientError(q){return this.clientCode===q}isUnauthorized(){return this.status===401}isForbidden(){return this.status===403}isNotFound(){return this.status===404}isValidationError(){return this.status===400||this.code==="BAD_REQUEST"}}function H(q){if(!q)return null;return q.replace(/\//g,"")}function b(q){let G=q&&q.length>0?q:window.location.origin;return G=G.endsWith("/")?G.slice(0,-1):G,G}function y(q,G){let L=G?`/${G}/ws`:"/ws";return`${q.replace(/^http/,"ws")}${L}`}function k(q,G){if(q&&G)return`/${q}/${G}`;else if(q&&!G)return`/${q}`;else if(!q&&G)return`/${G}`;else return""}class U{baseUrl;ws=null;subscriptions=new Map;messageQueue=[];isConnected=!1;reconnectTimeout=null;WebSocketImpl;getHeaders;authToken=null;debug;pendingAuth=!1;authActions=[];constructor(q,G,L,N=!1){this.baseUrl=q;this.WebSocketImpl=G,this.debug=N&&import.meta.env.VITE_NODE_ENV==="development",this.getHeaders=async()=>{if(typeof L==="function")return await L();return L??{}},this.connect()}async connect(){try{let q=await this.getHeaders();this.authToken=q.Authorization||null;let G=this.baseUrl;if(this.debug)console.log(`Connecting to WebSocket: ${G}`);this.ws=new this.WebSocketImpl(G),this.ws.onopen=async()=>{if(this.debug)console.log("WebSocket connection established");if(this.isConnected=!0,this.authActions=[],this.authToken){if(this.pendingAuth=!0,this.send({type:"authenticate",token:this.authToken}),this.debug)console.log("Sent authentication token, waiting for response");this.authActions.push(()=>{for(let L of this.subscriptions.keys())if(this.send({type:"subscribe",topic:L}),this.debug)console.log(`Resubscribed to topic: ${L}`);if(this.messageQueue.length>0&&this.debug)console.log(`Sending ${this.messageQueue.length} queued messages`);this.messageQueue.forEach((L)=>this.send(L)),this.messageQueue=[]})}else{for(let L of this.subscriptions.keys())if(this.send({type:"subscribe",topic:L}),this.debug)console.log(`Resubscribed to topic: ${L}`);if(this.messageQueue.length>0&&this.debug)console.log(`Sending ${this.messageQueue.length} queued messages`);this.messageQueue.forEach((L)=>this.send(L)),this.messageQueue=[]}},this.ws.onmessage=(L)=>{try{if(this.debug)console.log("WebSocket message received:",L.data);let N=JSON.parse(L.data);if(N.type==="auth_success"){let E=N.authenticated!==!1;if(this.debug)console.log(`WebSocket ${E?"authentication":"deauthentication"} successful`);if(this.pendingAuth=!1,E)this.authActions.forEach((O)=>O());this.authActions=[];return}if(N.type==="auth_error"){console.error("WebSocket authentication failed:",N.error),this.pendingAuth=!1,this.authActions=[];return}if(this.debug)console.log("Got new message",N);if(N.topic&&this.subscriptions.has(N.topic)){let E=this.subscriptions.get(N.topic);if(this.debug)console.log("Calling subscription callbacks");E?.forEach((O)=>O(N.data))}else if(N.error)console.error("WebSocket error:",N.error);else console.warn("Unhandled WebSocket message format:",N)}catch(N){if(this.debug)console.error("Error processing WebSocket message:",N),console.error("Raw message:",L.data)}},this.ws.onclose=(L)=>{if(this.isConnected=!1,this.pendingAuth=!1,this.debug)console.log(`WebSocket connection closed. Code: ${L.code}, Reason: ${L.reason}`);this.reconnectTimeout=setTimeout(()=>this.connect(),2000)},this.ws.onerror=(L)=>{if(this.debug)console.log("WebSocket error:",L)}}catch(q){if(this.debug)console.log("Failed to create WebSocket connection:",q);this.pendingAuth=!1,this.reconnectTimeout=setTimeout(()=>this.connect(),2000)}}disconnect(){if(this.reconnectTimeout)clearTimeout(this.reconnectTimeout),this.reconnectTimeout=null;if(this.ws)this.ws.close(),this.ws=null;this.isConnected=!1,this.pendingAuth=!1,this.authActions=[],this.subscriptions.clear()}send(q){if(this.isConnected&&this.ws?.readyState===this.WebSocketImpl.OPEN){if(this.pendingAuth&&q.type!=="authenticate"){if(this.messageQueue.push(q),this.debug)console.log("Message queued until authentication completes:",q);return}let G=JSON.stringify(q);if(this.ws.send(G),this.debug)console.log("WebSocket message sent:",G)}else if(this.messageQueue.push(q),this.debug)console.log("WebSocket message queued (not connected):",q)}subscribe(q,G){if(!this.subscriptions.has(q)){if(this.subscriptions.set(q,new Set),this.isConnected){if(this.pendingAuth)this.authActions.push(()=>{if(this.send({type:"subscribe",topic:q}),this.debug)console.log(`Subscribed to topic after auth: ${q}`)});else if(this.send({type:"subscribe",topic:q}),this.debug)console.log(`Subscribed to topic: ${q}`)}}return this.subscriptions.get(q).add(G),{unsubscribe:()=>this.unsubscribe(q,G),publish:(L)=>this.publish(q,L)}}unsubscribe(q,G){let L=this.subscriptions.get(q);if(L){if(L.delete(G),L.size===0){if(this.subscriptions.delete(q),this.send({type:"unsubscribe",topic:q}),this.debug)console.log(`Unsubscribed from topic: ${q}`)}}}publish(q,G){if(this.send({type:"publish",topic:q,data:G}),this.debug)console.log(`Published to topic: ${q}`,G)}async updateAuth(){let G=(await this.getHeaders()).Authorization||"",L=G.startsWith("Bearer ")?G.substring(7).trim():G.trim(),N=L.length>0,E=this.authToken!==null&&this.authToken.trim().length>0;if((N!==E||L!==this.authToken)&&this.isConnected){if(this.authToken=L,this.pendingAuth=N,this.send({type:"authenticate",token:G}),this.debug)if(N)console.log("Updated authentication token, waiting for confirmation");else console.log("Sent empty token for deauthentication"),this.pendingAuth=!1,this.authActions=[]}}}function e(q,G={}){let L=G.fetch||fetch,N=G.WebSocket??(typeof WebSocket<"u"?WebSocket:null),E=G.prefix??"",O=G.apiPrefix??"",R=G.debug??!1;if(!N)throw Error("WebSocket is not available in this environment");let W=G.headers??{},m=async()=>{if(typeof W==="function")return await W();return W},D=b(q),x=H(G.prefix),g=H(G.apiPrefix),S=k(x,g),P=y(D,x),C=new U(P,N,W,R),K=async(Q=!0)=>{let M={};if(Q)M["Content-Type"]="application/json";let J=await m();return{...M,...J}},c=async(Q)=>{if(!Q.ok){let J;try{J=await Q.json()}catch{try{J={error:await Q.text()}}catch{J={error:"Failed to parse error response"}}}if(J?.error&&typeof J.error==="object"){let V=J.error;throw new T(V.message||Q.statusText,Q.status,V.code,V.clientCode,V.data)}let z=J?.error||J?.message||Q.statusText;throw new T(z,Q.status,void 0,void 0,J)}let M=Q.headers.get("Content-Type")||"";try{if(M.includes("application/json"))return(await Q.json()).data;else if(M.includes("text/"))return Q.text();else return Q.blob()}catch(J){throw new T(`Failed to parse response: ${J instanceof Error?J.message:"Unknown error"}`,Q.status,"PARSE_ERROR")}},B=async(Q,M)=>{try{let J=await L(Q,M);return await c(J)}catch(J){if(J instanceof T)throw J;throw new T(J instanceof Error?J.message:"Network request failed",0,"NETWORK_ERROR")}},h=(Q=[])=>{return new Proxy({},{get(M,J){if(typeof J==="symbol")return;if(J==="query"||J==="mutation"||J==="formMutation"||J==="subscription"||J==="getStringKey"||J==="getArrayKey"||J==="getNoInputsArrayKey"){let z=Q.join("/"),V=`${D}${S}/${z}`;if(R)console.log(`BRPC ${J} procedure path: ${z}`),console.log(`BRPC ${J} full URL: ${V}`);if(J==="query")return async(X)=>{let _=await K(!0);if(R)console.log(`BRPC query request to ${z}`,{input:X,headers:_});let $=new URL(V);if(X&&typeof X==="object")Object.entries(X).forEach(([F,Y])=>{if(Y!==void 0)$.searchParams.append(F,String(Y))});let I=await B($.toString(),{method:"GET",headers:_,credentials:"include"});if(R)console.log(`BRPC query response from ${z}:`,I);return I};else if(J==="mutation")return async(X)=>{let _=await K(!0);if(R)console.log(`BRPC mutation request to ${z}`,{input:X,headers:_});let $=JSON.stringify(X),I=await B(V,{method:"POST",headers:_,body:$,credentials:"include"});if(R)console.log(`BRPC mutation response from ${z}:`,I);return I};else if(J==="formMutation")return async(X)=>{let _=await K(!1);if(R)console.log(`BRPC formMutation request to ${z}`,{input:X,headers:_});let $=new FormData,I=(Y,Z,f)=>{let w=f?`${f}[${Y}]`:Y;if(Z===null||Z===void 0)return;else if(Z instanceof File||Z instanceof Blob)$.append(w,Z);else if(Array.isArray(Z))Z.forEach((A,j)=>{if(A instanceof File||A instanceof Blob)$.append(w,A);else if(typeof A==="object"&&A!==null)Object.entries(A).forEach(([u,l])=>{I(u,l,`${w}[${j}]`)});else $.append(`${w}[${j}]`,String(A))});else if(typeof Z==="object"&&Z!==null)Object.entries(Z).forEach(([A,j])=>{I(A,j,w)});else $.append(w,String(Z))};Object.entries(X).forEach(([Y,Z])=>{I(Y,Z)});let F=await B(V,{method:"POST",headers:_,body:$,credentials:"include"});if(R)console.log(`BRPC formMutation response from ${z}:`,F);return F};else if(J==="subscription")return(X)=>{if(R)console.log(`BRPC subscription to ${z}`);let _=S?`${S.slice(1)}/${z}`:z;return C.updateAuth(),C.subscribe(_,X)};else if(J==="getStringKey")return(X)=>{let _=z;if(!X||Object.keys(X).length===0)return _;let $=Object.keys(X).sort().reduce((F,Y)=>{let Z=X[Y];if(Z!==void 0&&Z!==null)F[Y]=Z;return F},{});if(Object.keys($).length===0)return _;let I=JSON.stringify($);return`${_}?${I}`};else if(J==="getArrayKey")return(X)=>{let _=z;if(!X||Object.keys(X).length===0)return[_];let $=[];if(Object.keys(X).sort().forEach((F)=>{let Y=X[F];if(Y!==void 0&&Y!==null){let Z=Y;if(typeof Y==="boolean"||typeof Y==="number")Z=String(Y);else if(typeof Y==="object")Z=JSON.stringify(Y);$.push([F,Z])}}),$.length===0)return[_];let I=$.flatMap(([F,Y])=>[F,Y]);return[_,...I]};else if(J==="getNoInputsArrayKey")return()=>{return[z]}}return h([...Q,J])}})},d=h();if(R)console.log("BRPC client created",{baseUrl:D,prefix:S,wsUrl:P});return{routes:d,storage:{getObjectUrl:v},utils:{updateWsAuth:async()=>await C.updateAuth(),setHeader:async(Q,M)=>{if(typeof W==="function"){console.warn("Cannot use setHeader with function-based headers resolver");return}W={...W,[Q]:M},await C.updateAuth()},setHeaders:async(Q)=>{if(typeof W==="function"){console.warn("Cannot use setHeaders with function-based headers resolver");return}W={...W,...Q},await C.updateAuth()}}}}export{v as getObjectUrl,e as createBrpcClient,T as BrpcClientError};
|
|
2
|
+
function v(q,G={placeholder:void 0,throwOnInvalid:!0},L){if(!q)return G?.placeholder??"PLACEHOLDER";if(q.url)return q.url;if(q.key)if(q.isPrivate||q.provider==="local")return`/storage/${q.key}`;else return`${L??import.meta.env.VITE_S3_CDN_ENDPOINT}/${q.key}`;if(G.throwOnInvalid)throw Error("Invalid storage object");else return G?.placeholder??"PLACEHOLDER"}class w extends Error{status;code;clientCode;data;constructor(q,G,L,N,W){super(q);this.name="BrpcClientError",this.status=G,this.code=L,this.clientCode=N,this.data=W}isClientError(q){return this.clientCode===q}isUnauthorized(){return this.status===401}isForbidden(){return this.status===403}isNotFound(){return this.status===404}isValidationError(){return this.status===400||this.code==="BAD_REQUEST"}}function H(q){if(!q)return null;return q.replace(/\//g,"")}function b(q){let G=q&&q.length>0?q:typeof window<"u"?window.location.origin:"";return G=G.endsWith("/")?G.slice(0,-1):G,G}function y(q,G){let L=G?`/${G}/ws`:"/ws";return`${q.replace(/^http/,"ws")}${L}`}function k(q,G){if(q&&G)return`/${q}/${G}`;else if(q&&!G)return`/${q}`;else if(!q&&G)return`/${G}`;else return""}class U{baseUrl;ws=null;subscriptions=new Map;messageQueue=[];isConnected=!1;reconnectTimeout=null;WebSocketImpl;getHeaders;authToken=null;debug;pendingAuth=!1;authActions=[];constructor(q,G,L,N=!1,W){this.baseUrl=q;this.WebSocketImpl=G,this.debug=N&&(W??import.meta.env.VITE_NODE_ENV)==="development",this.getHeaders=async()=>{if(typeof L==="function")return await L();return L??{}},this.connect()}async connect(){try{let q=await this.getHeaders();this.authToken=q.Authorization||null;let G=this.baseUrl;if(this.debug)console.log(`Connecting to WebSocket: ${G}`);this.ws=new this.WebSocketImpl(G),this.ws.onopen=async()=>{if(this.debug)console.log("WebSocket connection established");if(this.isConnected=!0,this.authActions=[],this.authToken){if(this.pendingAuth=!0,this.send({type:"authenticate",token:this.authToken}),this.debug)console.log("Sent authentication token, waiting for response");this.authActions.push(()=>{for(let L of this.subscriptions.keys())if(this.send({type:"subscribe",topic:L}),this.debug)console.log(`Resubscribed to topic: ${L}`);if(this.messageQueue.length>0&&this.debug)console.log(`Sending ${this.messageQueue.length} queued messages`);this.messageQueue.forEach((L)=>this.send(L)),this.messageQueue=[]})}else{for(let L of this.subscriptions.keys())if(this.send({type:"subscribe",topic:L}),this.debug)console.log(`Resubscribed to topic: ${L}`);if(this.messageQueue.length>0&&this.debug)console.log(`Sending ${this.messageQueue.length} queued messages`);this.messageQueue.forEach((L)=>this.send(L)),this.messageQueue=[]}},this.ws.onmessage=(L)=>{try{if(this.debug)console.log("WebSocket message received:",L.data);let N=JSON.parse(L.data);if(N.type==="auth_success"){let W=N.authenticated!==!1;if(this.debug)console.log(`WebSocket ${W?"authentication":"deauthentication"} successful`);if(this.pendingAuth=!1,W)this.authActions.forEach((D)=>D());this.authActions=[];return}if(N.type==="auth_error"){console.error("WebSocket authentication failed:",N.error),this.pendingAuth=!1,this.authActions=[];return}if(this.debug)console.log("Got new message",N);if(N.topic&&this.subscriptions.has(N.topic)){let W=this.subscriptions.get(N.topic);if(this.debug)console.log("Calling subscription callbacks");W?.forEach((D)=>D(N.data))}else if(N.error)console.error("WebSocket error:",N.error);else console.warn("Unhandled WebSocket message format:",N)}catch(N){if(this.debug)console.error("Error processing WebSocket message:",N),console.error("Raw message:",L.data)}},this.ws.onclose=(L)=>{if(this.isConnected=!1,this.pendingAuth=!1,this.debug)console.log(`WebSocket connection closed. Code: ${L.code}, Reason: ${L.reason}`);this.reconnectTimeout=setTimeout(()=>this.connect(),2000)},this.ws.onerror=(L)=>{if(this.debug)console.log("WebSocket error:",L)}}catch(q){if(this.debug)console.log("Failed to create WebSocket connection:",q);this.pendingAuth=!1,this.reconnectTimeout=setTimeout(()=>this.connect(),2000)}}disconnect(){if(this.reconnectTimeout)clearTimeout(this.reconnectTimeout),this.reconnectTimeout=null;if(this.ws)this.ws.close(),this.ws=null;this.isConnected=!1,this.pendingAuth=!1,this.authActions=[],this.subscriptions.clear()}send(q){if(this.isConnected&&this.ws?.readyState===this.WebSocketImpl.OPEN){if(this.pendingAuth&&q.type!=="authenticate"){if(this.messageQueue.push(q),this.debug)console.log("Message queued until authentication completes:",q);return}let G=JSON.stringify(q);if(this.ws.send(G),this.debug)console.log("WebSocket message sent:",G)}else if(this.messageQueue.push(q),this.debug)console.log("WebSocket message queued (not connected):",q)}subscribe(q,G){if(!this.subscriptions.has(q)){if(this.subscriptions.set(q,new Set),this.isConnected){if(this.pendingAuth)this.authActions.push(()=>{if(this.send({type:"subscribe",topic:q}),this.debug)console.log(`Subscribed to topic after auth: ${q}`)});else if(this.send({type:"subscribe",topic:q}),this.debug)console.log(`Subscribed to topic: ${q}`)}}return this.subscriptions.get(q).add(G),{unsubscribe:()=>this.unsubscribe(q,G),publish:(L)=>this.publish(q,L)}}unsubscribe(q,G){let L=this.subscriptions.get(q);if(L){if(L.delete(G),L.size===0){if(this.subscriptions.delete(q),this.send({type:"unsubscribe",topic:q}),this.debug)console.log(`Unsubscribed from topic: ${q}`)}}}publish(q,G){if(this.send({type:"publish",topic:q,data:G}),this.debug)console.log(`Published to topic: ${q}`,G)}async updateAuth(){let G=(await this.getHeaders()).Authorization||"",L=G.startsWith("Bearer ")?G.substring(7).trim():G.trim(),N=L.length>0,W=this.authToken!==null&&this.authToken.trim().length>0;if((N!==W||L!==this.authToken)&&this.isConnected){if(this.authToken=L,this.pendingAuth=N,this.send({type:"authenticate",token:G}),this.debug)if(N)console.log("Updated authentication token, waiting for confirmation");else console.log("Sent empty token for deauthentication"),this.pendingAuth=!1,this.authActions=[]}}}function Gq(q,G={}){let L=G.fetch||fetch,N=G.WebSocket??(typeof WebSocket<"u"?WebSocket:null),W=G.prefix??"",D=G.apiPrefix??"",M=G.debug??!1,m=G.s3Endpoint,g=G.nodeEnv;if(!N)throw Error("WebSocket is not available in this environment");let V=G.headers??{},c=async()=>{if(typeof V==="function")return await V();return V},B=b(q),x=H(G.prefix),d=H(G.apiPrefix),E=k(x,d),P=y(B,x),S=new U(P,N,V,M,g),O=async(Q=!0)=>{let F={};if(Q)F["Content-Type"]="application/json";let J=await c();return{...F,...J}},u=async(Q)=>{if(!Q.ok){let J;try{J=await Q.json()}catch{try{J={error:await Q.text()}}catch{J={error:"Failed to parse error response"}}}if(J?.error&&typeof J.error==="object"){let A=J.error;throw new w(A.message||Q.statusText,Q.status,A.code,A.clientCode,A.data)}let z=J?.error||J?.message||Q.statusText;throw new w(z,Q.status,void 0,void 0,J)}let F=Q.headers.get("Content-Type")||"";try{if(F.includes("application/json"))return(await Q.json()).data;else if(F.includes("text/"))return Q.text();else return Q.blob()}catch(J){throw new w(`Failed to parse response: ${J instanceof Error?J.message:"Unknown error"}`,Q.status,"PARSE_ERROR")}},j=async(Q,F)=>{try{let J=await L(Q,F);return await u(J)}catch(J){if(J instanceof w)throw J;throw new w(J instanceof Error?J.message:"Network request failed",0,"NETWORK_ERROR")}},h=(Q=[])=>{return new Proxy({},{get(F,J){if(typeof J==="symbol")return;if(J==="query"||J==="mutation"||J==="formMutation"||J==="subscription"||J==="getStringKey"||J==="getArrayKey"||J==="getNoInputsArrayKey"){let z=Q.join("/"),A=`${B}${E}/${z}`;if(M)console.log(`BRPC ${J} procedure path: ${z}`),console.log(`BRPC ${J} full URL: ${A}`);if(J==="query")return async(X)=>{let _=await O(!0);if(M)console.log(`BRPC query request to ${z}`,{input:X,headers:_});let $=new URL(A);if(X&&typeof X==="object")Object.entries(X).forEach(([R,Y])=>{if(Y!==void 0)$.searchParams.append(R,String(Y))});let I=await j($.toString(),{method:"GET",headers:_,credentials:"include"});if(M)console.log(`BRPC query response from ${z}:`,I);return I};else if(J==="mutation")return async(X)=>{let _=await O(!0);if(M)console.log(`BRPC mutation request to ${z}`,{input:X,headers:_});let $=JSON.stringify(X),I=await j(A,{method:"POST",headers:_,body:$,credentials:"include"});if(M)console.log(`BRPC mutation response from ${z}:`,I);return I};else if(J==="formMutation")return async(X)=>{let _=await O(!1);if(M)console.log(`BRPC formMutation request to ${z}`,{input:X,headers:_});let $=new FormData,I=(Y,Z,f)=>{let C=f?`${f}[${Y}]`:Y;if(Z===null||Z===void 0)return;else if(Z instanceof File||Z instanceof Blob)$.append(C,Z);else if(Array.isArray(Z))Z.forEach((T,K)=>{if(T instanceof File||T instanceof Blob)$.append(C,T);else if(typeof T==="object"&&T!==null)Object.entries(T).forEach(([n,i])=>{I(n,i,`${C}[${K}]`)});else $.append(`${C}[${K}]`,String(T))});else if(typeof Z==="object"&&Z!==null)Object.entries(Z).forEach(([T,K])=>{I(T,K,C)});else $.append(C,String(Z))};Object.entries(X).forEach(([Y,Z])=>{I(Y,Z)});let R=await j(A,{method:"POST",headers:_,body:$,credentials:"include"});if(M)console.log(`BRPC formMutation response from ${z}:`,R);return R};else if(J==="subscription")return(X)=>{if(M)console.log(`BRPC subscription to ${z}`);let _=E?`${E.slice(1)}/${z}`:z;return S.updateAuth(),S.subscribe(_,X)};else if(J==="getStringKey")return(X)=>{let _=z;if(!X||Object.keys(X).length===0)return _;let $=Object.keys(X).sort().reduce((R,Y)=>{let Z=X[Y];if(Z!==void 0&&Z!==null)R[Y]=Z;return R},{});if(Object.keys($).length===0)return _;let I=JSON.stringify($);return`${_}?${I}`};else if(J==="getArrayKey")return(X)=>{let _=z;if(!X||Object.keys(X).length===0)return[_];let $=[];if(Object.keys(X).sort().forEach((R)=>{let Y=X[R];if(Y!==void 0&&Y!==null){let Z=Y;if(typeof Y==="boolean"||typeof Y==="number")Z=String(Y);else if(typeof Y==="object")Z=JSON.stringify(Y);$.push([R,Z])}}),$.length===0)return[_];let I=$.flatMap(([R,Y])=>[R,Y]);return[_,...I]};else if(J==="getNoInputsArrayKey")return()=>{return[z]}}return h([...Q,J])}})},l=h();if(M)console.log("BRPC client created",{baseUrl:B,prefix:E,wsUrl:P});return{routes:l,storage:{getObjectUrl:(Q,F)=>v(Q,F,m)},utils:{updateWsAuth:async()=>await S.updateAuth(),setHeader:async(Q,F)=>{if(typeof V==="function"){console.warn("Cannot use setHeader with function-based headers resolver");return}V={...V,[Q]:F},await S.updateAuth()},setHeaders:async(Q)=>{if(typeof V==="function"){console.warn("Cannot use setHeaders with function-based headers resolver");return}V={...V,...Q},await S.updateAuth()}}}}export{v as getObjectUrl,Gq as createBrpcClient,w as BrpcClientError};
|
|
3
3
|
|
|
4
|
-
//# debugId=
|
|
4
|
+
//# debugId=5C8464CC76330D1564756E2164756E21
|
package/dist/client/index.js.map
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["..\\src\\client\\storage.ts", "..\\src\\client\\brpc-client-error.ts", "..\\src\\client\\utils.ts", "..\\src\\client\\ws-manager.ts", "..\\src\\client\\service.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type { StorageObject } from \"../storage\";\r\n\r\nexport type GetObjectUrl = (\r\n storageObject: StorageObject | null | undefined,\r\n options: { placeholder?: string; throwOnInvalid?: boolean }\r\n) => string;\r\n\r\n/**\r\n * @returns url of the file\r\n */\r\nexport function getObjectUrl(\r\n storageObject: StorageObject | null | undefined,\r\n options: { placeholder?: string; throwOnInvalid?: boolean } = {\r\n placeholder: undefined,\r\n throwOnInvalid: true,\r\n }\r\n): string {\r\n if (!storageObject) return options?.placeholder ?? \"PLACEHOLDER\";\r\n\r\n // External file\r\n if (storageObject.url) {\r\n return storageObject.url;\r\n }\r\n\r\n // Internal file\r\n if (storageObject.key) {\r\n if (storageObject.isPrivate || storageObject.provider === \"local\") {\r\n // if private or local proxy/serve through/from server\r\n return `/storage/${storageObject.key}`;\r\n } else {\r\n // if public serve from s3\r\n return `${import.meta.env.VITE_S3_CDN_ENDPOINT}/${storageObject.key}`;\r\n }\r\n }\r\n\r\n if (options.throwOnInvalid) {\r\n throw new Error(\"Invalid storage object\");\r\n } else {\r\n return options?.placeholder ?? \"PLACEHOLDER\";\r\n }\r\n}\r\n",
|
|
5
|
+
"import type { StorageObject } from \"../storage\";\r\n\r\nexport type GetObjectUrl = (\r\n storageObject: StorageObject | null | undefined,\r\n options: { placeholder?: string; throwOnInvalid?: boolean }\r\n) => string;\r\n\r\n/**\r\n * @returns url of the file\r\n */\r\nexport function getObjectUrl(\r\n storageObject: StorageObject | null | undefined,\r\n options: { placeholder?: string; throwOnInvalid?: boolean } = {\r\n placeholder: undefined,\r\n throwOnInvalid: true,\r\n },\r\n s3Endpoint?: string\r\n): string {\r\n if (!storageObject) return options?.placeholder ?? \"PLACEHOLDER\";\r\n\r\n // External file\r\n if (storageObject.url) {\r\n return storageObject.url;\r\n }\r\n\r\n // Internal file\r\n if (storageObject.key) {\r\n if (storageObject.isPrivate || storageObject.provider === \"local\") {\r\n // if private or local proxy/serve through/from server\r\n return `/storage/${storageObject.key}`;\r\n } else {\r\n // if public serve from s3\r\n return `${s3Endpoint ?? import.meta.env.VITE_S3_CDN_ENDPOINT}/${storageObject.key}`;\r\n }\r\n }\r\n\r\n if (options.throwOnInvalid) {\r\n throw new Error(\"Invalid storage object\");\r\n } else {\r\n return options?.placeholder ?? \"PLACEHOLDER\";\r\n }\r\n}\r\n",
|
|
6
6
|
"class BrpcClientError extends Error {\r\n readonly status: number;\r\n readonly code?: string;\r\n readonly clientCode?: string;\r\n readonly data?: any;\r\n\r\n constructor(\r\n message: string,\r\n status: number,\r\n code?: string,\r\n clientCode?: string,\r\n data?: any\r\n ) {\r\n super(message);\r\n this.name = \"BrpcClientError\";\r\n this.status = status;\r\n this.code = code;\r\n this.clientCode = clientCode;\r\n this.data = data;\r\n }\r\n\r\n // Helper method to check if this is a specific client error\r\n isClientError(clientCode: string): boolean {\r\n return this.clientCode === clientCode;\r\n }\r\n\r\n // Helper methods for common error types\r\n isUnauthorized(): boolean {\r\n return this.status === 401;\r\n }\r\n\r\n isForbidden(): boolean {\r\n return this.status === 403;\r\n }\r\n\r\n isNotFound(): boolean {\r\n return this.status === 404;\r\n }\r\n\r\n isValidationError(): boolean {\r\n return this.status === 400 || this.code === \"BAD_REQUEST\";\r\n }\r\n}\r\n\r\nexport { BrpcClientError };\r\n",
|
|
7
|
-
"/**\r\n * Removes any slashes (/) from prefixes\r\n */\r\nexport function parsePrefix(prefix?: string) {\r\n if (!prefix) return null;\r\n return prefix.replace(/\\//g, \"\");\r\n}\r\n\r\n/**\r\n * Returns base url without trailing slash\r\n */\r\nexport function getFormattedBaseUrl(baseUrl?: string) {\r\n let formattedBaseUrl =\r\n baseUrl && baseUrl.length > 0
|
|
8
|
-
"import type { HeadersResolver } from \"./types\";\r\n\r\n// WebSocket Manager with improved authentication handling\r\nclass WebSocketManager {\r\n private ws: WebSocket | null = null;\r\n private subscriptions: Map<string, Set<(data: any) => void>> = new Map();\r\n private messageQueue: any[] = [];\r\n private isConnected: boolean = false;\r\n private reconnectTimeout: any = null;\r\n private WebSocketImpl: typeof WebSocket;\r\n private getHeaders: () => Promise<Record<string, string>>;\r\n private authToken: string | null = null;\r\n private debug: boolean;\r\n private pendingAuth: boolean = false; // Track if we're waiting for auth response\r\n private authActions: (() => void)[] = []; // Actions to perform after successful auth\r\n\r\n constructor(\r\n private baseUrl: string,\r\n WebSocketImpl: typeof WebSocket,\r\n headersResolver: HeadersResolver,\r\n debug: boolean = false\r\n ) {\r\n this.WebSocketImpl = WebSocketImpl;\r\n this.debug = debug && import.meta.env.VITE_NODE_ENV === \"development\";\r\n\r\n // Create headers resolver function\r\n this.getHeaders = async () => {\r\n if (typeof headersResolver === \"function\") {\r\n return await headersResolver();\r\n }\r\n return headersResolver ?? {};\r\n };\r\n\r\n this.connect();\r\n }\r\n\r\n private async connect() {\r\n try {\r\n // Get latest headers for authentication\r\n const headers = await this.getHeaders();\r\n this.authToken = headers[\"Authorization\"] || null;\r\n\r\n const wsUrl = this.baseUrl;\r\n\r\n if (this.debug) {\r\n console.log(`Connecting to WebSocket: ${wsUrl}`);\r\n }\r\n\r\n this.ws = new this.WebSocketImpl(wsUrl);\r\n\r\n this.ws.onopen = async () => {\r\n if (this.debug) {\r\n console.log(\"WebSocket connection established\");\r\n }\r\n\r\n this.isConnected = true;\r\n\r\n // Clear any pending auth actions from previous connection attempts\r\n this.authActions = [];\r\n\r\n // If we have auth token, send it first and mark auth as pending\r\n if (this.authToken) {\r\n this.pendingAuth = true;\r\n this.send({ type: \"authenticate\", token: this.authToken });\r\n if (this.debug) {\r\n console.log(\"Sent authentication token, waiting for response\");\r\n }\r\n\r\n // Queue resubscriptions to happen after authentication\r\n this.authActions.push(() => {\r\n // Resubscribe to all topics\r\n for (const topic of this.subscriptions.keys()) {\r\n this.send({ type: \"subscribe\", topic });\r\n if (this.debug) {\r\n console.log(`Resubscribed to topic: ${topic}`);\r\n }\r\n }\r\n\r\n // Send any queued messages\r\n if (this.messageQueue.length > 0 && this.debug) {\r\n console.log(\r\n `Sending ${this.messageQueue.length} queued messages`\r\n );\r\n }\r\n\r\n this.messageQueue.forEach((msg) => this.send(msg));\r\n this.messageQueue = [];\r\n });\r\n } else {\r\n // No auth needed, proceed with subscriptions immediately\r\n for (const topic of this.subscriptions.keys()) {\r\n this.send({ type: \"subscribe\", topic });\r\n if (this.debug) {\r\n console.log(`Resubscribed to topic: ${topic}`);\r\n }\r\n }\r\n\r\n // Send any queued messages\r\n if (this.messageQueue.length > 0 && this.debug) {\r\n console.log(`Sending ${this.messageQueue.length} queued messages`);\r\n }\r\n\r\n this.messageQueue.forEach((msg) => this.send(msg));\r\n this.messageQueue = [];\r\n }\r\n };\r\n\r\n this.ws.onmessage = (event) => {\r\n try {\r\n if (this.debug) {\r\n // console.log(\"Active subscriptions\", this.subscriptions);\r\n console.log(\"WebSocket message received:\", event.data);\r\n }\r\n\r\n const message = JSON.parse(event.data);\r\n\r\n // Handle auth-specific messages\r\n if (message.type === \"auth_success\") {\r\n // Check if authentication was successful or if it was a logout confirmation\r\n const isAuthenticated = message.authenticated !== false;\r\n\r\n if (this.debug) {\r\n console.log(\r\n `WebSocket ${\r\n isAuthenticated ? \"authentication\" : \"deauthentication\"\r\n } successful`\r\n );\r\n }\r\n\r\n // Clear pending auth state\r\n this.pendingAuth = false;\r\n\r\n // Only execute queued actions for successful authentication\r\n if (isAuthenticated) {\r\n // Execute all queued actions that were waiting for authentication\r\n this.authActions.forEach((action) => action());\r\n }\r\n\r\n // Clear action queue\r\n this.authActions = [];\r\n\r\n return;\r\n }\r\n\r\n if (message.type === \"auth_error\") {\r\n console.error(\"WebSocket authentication failed:\", message.error);\r\n\r\n // Clear pending auth state but don't process queued actions\r\n this.pendingAuth = false;\r\n this.authActions = [];\r\n\r\n return;\r\n }\r\n\r\n if (this.debug) {\r\n console.log(\"Got new message\", message);\r\n }\r\n\r\n if (message.topic && this.subscriptions.has(message.topic)) {\r\n const callbacks = this.subscriptions.get(message.topic);\r\n if (this.debug) {\r\n console.log(\"Calling subscription callbacks\");\r\n }\r\n callbacks?.forEach((callback) => callback(message.data));\r\n } else if (message.error) {\r\n console.error(\"WebSocket error:\", message.error);\r\n } else {\r\n // Log unknown message formats to help debug\r\n console.warn(\"Unhandled WebSocket message format:\", message);\r\n }\r\n } catch (error) {\r\n if (this.debug) {\r\n console.error(\"Error processing WebSocket message:\", error);\r\n console.error(\"Raw message:\", event.data);\r\n }\r\n }\r\n };\r\n\r\n this.ws.onclose = (event) => {\r\n this.isConnected = false;\r\n this.pendingAuth = false; // Reset auth state\r\n\r\n if (this.debug) {\r\n console.log(\r\n `WebSocket connection closed. Code: ${event.code}, Reason: ${event.reason}`\r\n );\r\n }\r\n\r\n // Try to reconnect after a delay\r\n this.reconnectTimeout = setTimeout(() => this.connect(), 2000);\r\n };\r\n\r\n this.ws.onerror = (error) => {\r\n if (this.debug) {\r\n console.log(\"WebSocket error:\", error);\r\n }\r\n };\r\n } catch (error) {\r\n if (this.debug) {\r\n console.log(\"Failed to create WebSocket connection:\", error);\r\n }\r\n this.pendingAuth = false;\r\n // Try to reconnect after a delay\r\n this.reconnectTimeout = setTimeout(() => this.connect(), 2000);\r\n }\r\n }\r\n\r\n public disconnect() {\r\n if (this.reconnectTimeout) {\r\n clearTimeout(this.reconnectTimeout);\r\n this.reconnectTimeout = null;\r\n }\r\n\r\n if (this.ws) {\r\n this.ws.close();\r\n this.ws = null;\r\n }\r\n\r\n this.isConnected = false;\r\n this.pendingAuth = false;\r\n this.authActions = [];\r\n this.subscriptions.clear();\r\n }\r\n\r\n public send(message: any) {\r\n if (this.isConnected && this.ws?.readyState === this.WebSocketImpl.OPEN) {\r\n // If authentication is pending and this isn't an auth message, queue it\r\n if (this.pendingAuth && message.type !== \"authenticate\") {\r\n this.messageQueue.push(message);\r\n if (this.debug) {\r\n console.log(\r\n \"Message queued until authentication completes:\",\r\n message\r\n );\r\n }\r\n return;\r\n }\r\n\r\n const messageStr = JSON.stringify(message);\r\n this.ws.send(messageStr);\r\n\r\n if (this.debug) {\r\n console.log(\"WebSocket message sent:\", messageStr);\r\n }\r\n } else {\r\n this.messageQueue.push(message);\r\n\r\n if (this.debug) {\r\n console.log(\"WebSocket message queued (not connected):\", message);\r\n }\r\n }\r\n }\r\n\r\n public subscribe(topic: string, callback: (data: any) => void) {\r\n if (!this.subscriptions.has(topic)) {\r\n this.subscriptions.set(topic, new Set());\r\n\r\n // If we're connected, send the subscription (with auth awareness)\r\n if (this.isConnected) {\r\n if (this.pendingAuth) {\r\n // Queue the subscription for after auth\r\n this.authActions.push(() => {\r\n this.send({ type: \"subscribe\", topic });\r\n if (this.debug) {\r\n console.log(`Subscribed to topic after auth: ${topic}`);\r\n }\r\n });\r\n } else {\r\n // Send immediately\r\n this.send({ type: \"subscribe\", topic });\r\n if (this.debug) {\r\n console.log(`Subscribed to topic: ${topic}`);\r\n }\r\n }\r\n }\r\n }\r\n\r\n this.subscriptions.get(topic)!.add(callback);\r\n\r\n return {\r\n unsubscribe: () => this.unsubscribe(topic, callback),\r\n publish: (data: any) => this.publish(topic, data),\r\n };\r\n }\r\n\r\n private unsubscribe(topic: string, callback: (data: any) => void) {\r\n const callbacks = this.subscriptions.get(topic);\r\n if (callbacks) {\r\n callbacks.delete(callback);\r\n if (callbacks.size === 0) {\r\n this.subscriptions.delete(topic);\r\n this.send({ type: \"unsubscribe\", topic });\r\n\r\n if (this.debug) {\r\n console.log(`Unsubscribed from topic: ${topic}`);\r\n }\r\n }\r\n }\r\n }\r\n\r\n public publish(topic: string, data: any) {\r\n this.send({ type: \"publish\", topic, data });\r\n\r\n if (this.debug) {\r\n console.log(`Published to topic: ${topic}`, data);\r\n }\r\n }\r\n\r\n // Method to update auth token when it changes\r\n public async updateAuth() {\r\n const headers = await this.getHeaders();\r\n const authHeader = headers[\"Authorization\"] || \"\";\r\n\r\n // Extract token from header - may be empty (\"Bearer \")\r\n const newToken = authHeader.startsWith(\"Bearer \")\r\n ? authHeader.substring(7).trim()\r\n : authHeader.trim();\r\n\r\n const hasValidToken = newToken.length > 0;\r\n const hadValidToken =\r\n this.authToken !== null && this.authToken.trim().length > 0;\r\n\r\n // If token status changed and we're connected, handle the change\r\n if (\r\n (hasValidToken !== hadValidToken || newToken !== this.authToken) &&\r\n this.isConnected\r\n ) {\r\n // Update stored token\r\n this.authToken = newToken;\r\n\r\n // Always send authenticate message, but with empty token when logging out\r\n this.pendingAuth = hasValidToken;\r\n this.send({ type: \"authenticate\", token: authHeader });\r\n\r\n if (this.debug) {\r\n if (hasValidToken) {\r\n console.log(\"Updated authentication token, waiting for confirmation\");\r\n } else {\r\n console.log(\"Sent empty token for deauthentication\");\r\n // Since we're not expecting auth confirmation for logout, clear pending state\r\n this.pendingAuth = false;\r\n this.authActions = [];\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\nexport { WebSocketManager };\r\n",
|
|
9
|
-
"import { BrpcClientError } from \"./brpc-client-error\";\r\nimport { getObjectUrl } from \"./storage\";\r\nimport type {\r\n HeadersResolver,\r\n BrpcClient,\r\n InferClientRoutes,\r\n BrpcClientOptions,\r\n} from \"./types\";\r\nimport {\r\n getFormattedBaseUrl,\r\n getProceduresPrefixPath,\r\n getWsUrl,\r\n parsePrefix,\r\n} from \"./utils\";\r\nimport { WebSocketManager } from \"./ws-manager\";\r\n\r\n/**\r\n * Creates a type-safe client for the BRPC API\r\n * @param baseUrl The base URL of the BRPC server\r\n * @param options Client configuration options\r\n * @returns A client object that mirrors the server routes\r\n */\r\nexport function createBrpcClient<TRoutesStructure>(\r\n baseUrl: string,\r\n options: BrpcClientOptions = {}\r\n): BrpcClient<TRoutesStructure> {\r\n const fetchImpl = options.fetch || fetch;\r\n const WebSocketImpl =\r\n options.WebSocket ?? (typeof WebSocket !== \"undefined\" ? WebSocket : null);\r\n const prefix = options.prefix ?? \"\";\r\n const apiPrefix = options.apiPrefix ?? \"\";\r\n const debug = options.debug ?? false;\r\n\r\n if (!WebSocketImpl) {\r\n throw new Error(\"WebSocket is not available in this environment\");\r\n }\r\n\r\n let currentHeaders: HeadersResolver = options.headers ?? {};\r\n\r\n const headersResolver: HeadersResolver = async () => {\r\n if (typeof currentHeaders === \"function\") {\r\n return await currentHeaders();\r\n }\r\n return currentHeaders;\r\n };\r\n\r\n // Properly format the base URL\r\n const formattedBaseUrl = getFormattedBaseUrl(baseUrl);\r\n\r\n // Format prefixes (returns clean word, like api, without\r\n // initial and trailing slahes)\r\n const parsedPrefix = parsePrefix(options.prefix);\r\n const parsedApiPrefix = parsePrefix(options.apiPrefix);\r\n\r\n const proceduresPrefixedPath = getProceduresPrefixPath(\r\n parsedPrefix,\r\n parsedApiPrefix\r\n );\r\n\r\n // Create WebSocket URL with proper path joining\r\n const wsUrl = getWsUrl(formattedBaseUrl, parsedPrefix);\r\n\r\n // Create WebSocket manager with headers resolver\r\n const wsManager = new WebSocketManager(\r\n wsUrl,\r\n WebSocketImpl,\r\n currentHeaders,\r\n debug\r\n );\r\n\r\n // Helper to resolve headers before each request\r\n const resolveHeaders = async (\r\n defaultContentType = true\r\n ): Promise<Record<string, string>> => {\r\n const baseHeaders: Record<string, string> = {};\r\n\r\n if (defaultContentType) {\r\n baseHeaders[\"Content-Type\"] = \"application/json\";\r\n }\r\n\r\n // Use the same headersResolver as WebSocket\r\n const dynamicHeaders = await headersResolver();\r\n return { ...baseHeaders, ...dynamicHeaders };\r\n };\r\n\r\n // Helper to handle HTTP responses\r\n const handleResponse = async (response: Response) => {\r\n if (!response.ok) {\r\n let errorData;\r\n try {\r\n errorData = await response.json();\r\n } catch {\r\n try {\r\n errorData = { error: await response.text() };\r\n } catch {\r\n errorData = { error: \"Failed to parse error response\" };\r\n }\r\n }\r\n\r\n // Handle the new BRPCError format from server\r\n if (errorData?.error && typeof errorData.error === \"object\") {\r\n const serverError = errorData.error;\r\n\r\n throw new BrpcClientError(\r\n serverError.message || response.statusText,\r\n response.status,\r\n serverError.code,\r\n serverError.clientCode,\r\n serverError.data\r\n );\r\n }\r\n\r\n // Handle legacy error format or simple string errors\r\n const errorMessage =\r\n errorData?.error || errorData?.message || response.statusText;\r\n\r\n throw new BrpcClientError(\r\n errorMessage,\r\n response.status,\r\n undefined,\r\n undefined,\r\n errorData\r\n );\r\n }\r\n\r\n // Check content type to determine how to handle the response\r\n const contentType = response.headers.get(\"Content-Type\") || \"\";\r\n\r\n try {\r\n if (contentType.includes(\"application/json\")) {\r\n const result = await response.json();\r\n return result.data;\r\n } else if (contentType.includes(\"text/\")) {\r\n return response.text();\r\n } else {\r\n return response.blob();\r\n }\r\n } catch (error) {\r\n // Wrap JSON parsing errors\r\n throw new BrpcClientError(\r\n `Failed to parse response: ${\r\n error instanceof Error ? error.message : \"Unknown error\"\r\n }`,\r\n response.status,\r\n \"PARSE_ERROR\"\r\n );\r\n }\r\n };\r\n\r\n // Wrap fetch AND response handling to always return BrpcClientError\r\n const safeFetch = async (url: string | URL, init?: RequestInit) => {\r\n try {\r\n const response = await fetchImpl(url, init);\r\n return await handleResponse(response); // This throws BrpcClientError if not ok\r\n } catch (error) {\r\n // If already a BrpcClientError (from handleResponse), re-throw as-is\r\n if (error instanceof BrpcClientError) {\r\n throw error;\r\n }\r\n\r\n // Network errors - wrap them\r\n throw new BrpcClientError(\r\n error instanceof Error ? error.message : \"Network request failed\",\r\n 0,\r\n \"NETWORK_ERROR\"\r\n );\r\n }\r\n };\r\n\r\n // Create a proxy for a specific path\r\n const createProxy = (pathSegments: string[] = []): any => {\r\n return new Proxy(\r\n {},\r\n {\r\n get(_, key: string | symbol) {\r\n if (typeof key === \"symbol\") return undefined;\r\n\r\n // Special methods for procedures\r\n if (\r\n key === \"query\" ||\r\n key === \"mutation\" ||\r\n key === \"formMutation\" ||\r\n key === \"subscription\" ||\r\n key === \"getStringKey\" ||\r\n key === \"getArrayKey\" ||\r\n key === \"getNoInputsArrayKey\"\r\n ) {\r\n // The path up to this point is the procedure path\r\n const procedurePath = pathSegments.join(\"/\");\r\n const fullUrl = `${formattedBaseUrl}${proceduresPrefixedPath}/${procedurePath}`;\r\n\r\n if (debug) {\r\n console.log(`BRPC ${key} procedure path: ${procedurePath}`);\r\n console.log(`BRPC ${key} full URL: ${fullUrl}`);\r\n }\r\n\r\n if (key === \"query\") {\r\n return async (input: any) => {\r\n // Get fresh headers for this request\r\n const headers = await resolveHeaders(true);\r\n\r\n if (debug) {\r\n console.log(`BRPC query request to ${procedurePath}`, {\r\n input,\r\n headers,\r\n });\r\n }\r\n\r\n const url = new URL(fullUrl);\r\n\r\n // Add input parameters to URL for GET request\r\n if (input && typeof input === \"object\") {\r\n Object.entries(input).forEach(([k, v]) => {\r\n if (v !== undefined) {\r\n url.searchParams.append(k, String(v));\r\n }\r\n });\r\n }\r\n\r\n const result = await safeFetch(url.toString(), {\r\n method: \"GET\",\r\n headers,\r\n credentials: \"include\", //always include credentials\r\n });\r\n\r\n if (debug) {\r\n console.log(\r\n `BRPC query response from ${procedurePath}:`,\r\n result\r\n );\r\n }\r\n\r\n return result;\r\n };\r\n } else if (key === \"mutation\") {\r\n return async (input: any) => {\r\n // Get fresh headers for this request\r\n const headers = await resolveHeaders(true);\r\n\r\n if (debug) {\r\n console.log(`BRPC mutation request to ${procedurePath}`, {\r\n input,\r\n headers,\r\n });\r\n }\r\n\r\n const body = JSON.stringify(input);\r\n\r\n const result = await safeFetch(fullUrl, {\r\n method: \"POST\",\r\n headers,\r\n body,\r\n credentials: \"include\",\r\n });\r\n\r\n if (debug) {\r\n console.log(\r\n `BRPC mutation response from ${procedurePath}:`,\r\n result\r\n );\r\n }\r\n\r\n return result;\r\n };\r\n } else if (key === \"formMutation\") {\r\n return async (input: Record<string, any>) => {\r\n // Get fresh headers for this request (no Content-Type for FormData)\r\n const headers = await resolveHeaders(false);\r\n\r\n if (debug) {\r\n console.log(`BRPC formMutation request to ${procedurePath}`, {\r\n input,\r\n headers,\r\n });\r\n }\r\n\r\n // Convert object input to FormData\r\n const formData = new FormData();\r\n\r\n // Helper function to append values to FormData\r\n const appendToFormData = (\r\n key: string,\r\n value: any,\r\n parentKey?: string\r\n ) => {\r\n const fullKey = parentKey ? `${parentKey}[${key}]` : key;\r\n\r\n if (value === null || value === undefined) {\r\n // Skip null/undefined values\r\n return;\r\n } else if (value instanceof File || value instanceof Blob) {\r\n // Handle files directly\r\n formData.append(fullKey, value);\r\n } else if (Array.isArray(value)) {\r\n // Handle arrays\r\n value.forEach((item, index) => {\r\n if (item instanceof File || item instanceof Blob) {\r\n // ✅ Append files with the same key (not indexed)\r\n formData.append(fullKey, item);\r\n } else if (typeof item === \"object\" && item !== null) {\r\n Object.entries(item).forEach(([subKey, subValue]) => {\r\n appendToFormData(\r\n subKey,\r\n subValue,\r\n `${fullKey}[${index}]`\r\n );\r\n });\r\n } else {\r\n formData.append(`${fullKey}[${index}]`, String(item));\r\n }\r\n });\r\n } else if (typeof value === \"object\" && value !== null) {\r\n // Handle nested objects\r\n Object.entries(value).forEach(([subKey, subValue]) => {\r\n appendToFormData(subKey, subValue, fullKey);\r\n });\r\n } else {\r\n // Handle primitive values\r\n formData.append(fullKey, String(value));\r\n }\r\n };\r\n\r\n // Convert input object to FormData\r\n Object.entries(input).forEach(([key, value]) => {\r\n appendToFormData(key, value);\r\n });\r\n\r\n const result = await safeFetch(fullUrl, {\r\n method: \"POST\",\r\n headers,\r\n body: formData,\r\n credentials: \"include\",\r\n });\r\n\r\n if (debug) {\r\n console.log(\r\n `BRPC formMutation response from ${procedurePath}:`,\r\n result\r\n );\r\n }\r\n\r\n return result;\r\n };\r\n } else if (key === \"subscription\") {\r\n return (callback: (data: any) => void) => {\r\n if (debug) {\r\n console.log(`BRPC subscription to ${procedurePath}`);\r\n }\r\n\r\n // Use the same pattern as fullUrl for consistency\r\n const topicPath = proceduresPrefixedPath\r\n ? `${proceduresPrefixedPath.slice(1)}/${procedurePath}` // Remove leading /\r\n : procedurePath;\r\n\r\n // Update WebSocket auth if needed before subscribing\r\n wsManager.updateAuth();\r\n\r\n // Return an object with unsubscribe and publish methods\r\n return wsManager.subscribe(topicPath, callback);\r\n };\r\n } else if (key === \"getStringKey\") {\r\n return (input?: any) => {\r\n // Create a deterministic key based on procedure path and input\r\n const baseKey = procedurePath;\r\n\r\n if (!input || Object.keys(input).length === 0) {\r\n return baseKey;\r\n }\r\n\r\n // Sort input keys for deterministic key generation\r\n const sortedInput = Object.keys(input)\r\n .sort()\r\n .reduce((result, key) => {\r\n const value = input[key];\r\n if (value !== undefined && value !== null) {\r\n result[key] = value;\r\n }\r\n return result;\r\n }, {} as Record<string, any>);\r\n\r\n // Only add input hash if there are actual values\r\n if (Object.keys(sortedInput).length === 0) {\r\n return baseKey;\r\n }\r\n\r\n // Create a simple hash from the sorted input\r\n const inputString = JSON.stringify(sortedInput);\r\n return `${baseKey}?${inputString}`;\r\n };\r\n } else if (key === \"getArrayKey\") {\r\n return (input?: any) => {\r\n // Use the full procedure path as the first segment for easier invalidation\r\n const basePath = procedurePath;\r\n\r\n if (!input || Object.keys(input).length === 0) {\r\n return [basePath];\r\n }\r\n\r\n // Normalize and sort input keys for deterministic key generation\r\n const normalizedPairs: Array<[string, any]> = [];\r\n\r\n Object.keys(input)\r\n .sort()\r\n .forEach((key) => {\r\n const value = input[key];\r\n if (value !== undefined && value !== null) {\r\n // Normalize values for consistent comparison\r\n let normalizedValue = value;\r\n\r\n // Convert primitives to strings for consistency\r\n if (\r\n typeof value === \"boolean\" ||\r\n typeof value === \"number\"\r\n ) {\r\n normalizedValue = String(value);\r\n } else if (typeof value === \"object\") {\r\n // For objects/arrays, use JSON representation\r\n normalizedValue = JSON.stringify(value);\r\n }\r\n\r\n normalizedPairs.push([key, normalizedValue]);\r\n }\r\n });\r\n\r\n // Only add input segments if there are actual values\r\n if (normalizedPairs.length === 0) {\r\n return [basePath];\r\n }\r\n\r\n // Create individual segments for each input pair\r\n // This allows for better pattern matching\r\n const inputSegments = normalizedPairs.flatMap(\r\n ([key, value]) => [key, value]\r\n );\r\n\r\n return [basePath, ...inputSegments];\r\n };\r\n } else if (key === \"getNoInputsArrayKey\") {\r\n return () => {\r\n // Always return just the procedure path, ignoring any inputs\r\n // Perfect for invalidating all variants of a procedure\r\n return [procedurePath];\r\n };\r\n }\r\n }\r\n\r\n // Continue traversing the path for nested routes\r\n return createProxy([...pathSegments, key]);\r\n },\r\n }\r\n );\r\n };\r\n\r\n // Create the base proxy\r\n const clientProxy = createProxy() as InferClientRoutes<TRoutesStructure>;\r\n\r\n if (debug) {\r\n console.log(\"BRPC client created\", {\r\n baseUrl: formattedBaseUrl,\r\n prefix: proceduresPrefixedPath,\r\n wsUrl: wsUrl,\r\n });\r\n }\r\n\r\n return {\r\n routes: clientProxy,\r\n\r\n storage: { getObjectUrl },\r\n\r\n utils: {\r\n updateWsAuth: async () => await wsManager.updateAuth(),\r\n\r\n setHeader: async (key: string, value: string) => {\r\n if (typeof currentHeaders === \"function\") {\r\n console.warn(\r\n \"Cannot use setHeader with function-based headers resolver\"\r\n );\r\n return;\r\n }\r\n currentHeaders = { ...currentHeaders, [key]: value };\r\n await wsManager.updateAuth();\r\n },\r\n\r\n setHeaders: async (headers: Record<string, string>) => {\r\n if (typeof currentHeaders === \"function\") {\r\n console.warn(\r\n \"Cannot use setHeaders with function-based headers resolver\"\r\n );\r\n return;\r\n }\r\n currentHeaders = { ...currentHeaders, ...headers };\r\n await wsManager.updateAuth();\r\n },\r\n },\r\n };\r\n}\r\n"
|
|
7
|
+
"/**\r\n * Removes any slashes (/) from prefixes\r\n */\r\nexport function parsePrefix(prefix?: string) {\r\n if (!prefix) return null;\r\n return prefix.replace(/\\//g, \"\");\r\n}\r\n\r\n/**\r\n * Returns base url without trailing slash\r\n */\r\nexport function getFormattedBaseUrl(baseUrl?: string) {\r\n let formattedBaseUrl =\r\n baseUrl && baseUrl.length > 0\r\n ? baseUrl\r\n : typeof window !== \"undefined\"\r\n ? window.location.origin\r\n : \"\";\r\n\r\n // Remove trailing slash if present\r\n formattedBaseUrl = formattedBaseUrl.endsWith(\"/\")\r\n ? formattedBaseUrl.slice(0, -1)\r\n : formattedBaseUrl;\r\n\r\n return formattedBaseUrl;\r\n}\r\n\r\nexport function getWsUrl(\r\n formattedBaseUrl: string,\r\n parsedPrefix: string | null\r\n) {\r\n const wsPath = parsedPrefix ? `/${parsedPrefix}/ws` : `/ws`;\r\n return `${formattedBaseUrl.replace(/^http/, \"ws\")}${wsPath}`;\r\n}\r\n\r\nexport function getProceduresPrefixPath(\r\n parsedPrefix: string | null,\r\n parsedApiPrefix: string | null\r\n) {\r\n if (parsedPrefix && parsedApiPrefix) {\r\n return `/${parsedPrefix}/${parsedApiPrefix}`;\r\n } else if (parsedPrefix && !parsedApiPrefix) {\r\n return `/${parsedPrefix}`;\r\n } else if (!parsedPrefix && parsedApiPrefix) {\r\n return `/${parsedApiPrefix}`;\r\n } else {\r\n return \"\";\r\n }\r\n}\r\n",
|
|
8
|
+
"import type { HeadersResolver } from \"./types\";\r\n\r\n// WebSocket Manager with improved authentication handling\r\nclass WebSocketManager {\r\n private ws: WebSocket | null = null;\r\n private subscriptions: Map<string, Set<(data: any) => void>> = new Map();\r\n private messageQueue: any[] = [];\r\n private isConnected: boolean = false;\r\n private reconnectTimeout: any = null;\r\n private WebSocketImpl: typeof WebSocket;\r\n private getHeaders: () => Promise<Record<string, string>>;\r\n private authToken: string | null = null;\r\n private debug: boolean;\r\n private pendingAuth: boolean = false; // Track if we're waiting for auth response\r\n private authActions: (() => void)[] = []; // Actions to perform after successful auth\r\n\r\n constructor(\r\n private baseUrl: string,\r\n WebSocketImpl: typeof WebSocket,\r\n headersResolver: HeadersResolver,\r\n debug: boolean = false,\r\n nodeEnv?: string\r\n ) {\r\n this.WebSocketImpl = WebSocketImpl;\r\n this.debug =\r\n debug &&\r\n (nodeEnv ?? import.meta.env.VITE_NODE_ENV) === \"development\";\r\n\r\n // Create headers resolver function\r\n this.getHeaders = async () => {\r\n if (typeof headersResolver === \"function\") {\r\n return await headersResolver();\r\n }\r\n return headersResolver ?? {};\r\n };\r\n\r\n this.connect();\r\n }\r\n\r\n private async connect() {\r\n try {\r\n // Get latest headers for authentication\r\n const headers = await this.getHeaders();\r\n this.authToken = headers[\"Authorization\"] || null;\r\n\r\n const wsUrl = this.baseUrl;\r\n\r\n if (this.debug) {\r\n console.log(`Connecting to WebSocket: ${wsUrl}`);\r\n }\r\n\r\n this.ws = new this.WebSocketImpl(wsUrl);\r\n\r\n this.ws.onopen = async () => {\r\n if (this.debug) {\r\n console.log(\"WebSocket connection established\");\r\n }\r\n\r\n this.isConnected = true;\r\n\r\n // Clear any pending auth actions from previous connection attempts\r\n this.authActions = [];\r\n\r\n // If we have auth token, send it first and mark auth as pending\r\n if (this.authToken) {\r\n this.pendingAuth = true;\r\n this.send({ type: \"authenticate\", token: this.authToken });\r\n if (this.debug) {\r\n console.log(\"Sent authentication token, waiting for response\");\r\n }\r\n\r\n // Queue resubscriptions to happen after authentication\r\n this.authActions.push(() => {\r\n // Resubscribe to all topics\r\n for (const topic of this.subscriptions.keys()) {\r\n this.send({ type: \"subscribe\", topic });\r\n if (this.debug) {\r\n console.log(`Resubscribed to topic: ${topic}`);\r\n }\r\n }\r\n\r\n // Send any queued messages\r\n if (this.messageQueue.length > 0 && this.debug) {\r\n console.log(\r\n `Sending ${this.messageQueue.length} queued messages`\r\n );\r\n }\r\n\r\n this.messageQueue.forEach((msg) => this.send(msg));\r\n this.messageQueue = [];\r\n });\r\n } else {\r\n // No auth needed, proceed with subscriptions immediately\r\n for (const topic of this.subscriptions.keys()) {\r\n this.send({ type: \"subscribe\", topic });\r\n if (this.debug) {\r\n console.log(`Resubscribed to topic: ${topic}`);\r\n }\r\n }\r\n\r\n // Send any queued messages\r\n if (this.messageQueue.length > 0 && this.debug) {\r\n console.log(`Sending ${this.messageQueue.length} queued messages`);\r\n }\r\n\r\n this.messageQueue.forEach((msg) => this.send(msg));\r\n this.messageQueue = [];\r\n }\r\n };\r\n\r\n this.ws.onmessage = (event) => {\r\n try {\r\n if (this.debug) {\r\n // console.log(\"Active subscriptions\", this.subscriptions);\r\n console.log(\"WebSocket message received:\", event.data);\r\n }\r\n\r\n const message = JSON.parse(event.data);\r\n\r\n // Handle auth-specific messages\r\n if (message.type === \"auth_success\") {\r\n // Check if authentication was successful or if it was a logout confirmation\r\n const isAuthenticated = message.authenticated !== false;\r\n\r\n if (this.debug) {\r\n console.log(\r\n `WebSocket ${\r\n isAuthenticated ? \"authentication\" : \"deauthentication\"\r\n } successful`\r\n );\r\n }\r\n\r\n // Clear pending auth state\r\n this.pendingAuth = false;\r\n\r\n // Only execute queued actions for successful authentication\r\n if (isAuthenticated) {\r\n // Execute all queued actions that were waiting for authentication\r\n this.authActions.forEach((action) => action());\r\n }\r\n\r\n // Clear action queue\r\n this.authActions = [];\r\n\r\n return;\r\n }\r\n\r\n if (message.type === \"auth_error\") {\r\n console.error(\"WebSocket authentication failed:\", message.error);\r\n\r\n // Clear pending auth state but don't process queued actions\r\n this.pendingAuth = false;\r\n this.authActions = [];\r\n\r\n return;\r\n }\r\n\r\n if (this.debug) {\r\n console.log(\"Got new message\", message);\r\n }\r\n\r\n if (message.topic && this.subscriptions.has(message.topic)) {\r\n const callbacks = this.subscriptions.get(message.topic);\r\n if (this.debug) {\r\n console.log(\"Calling subscription callbacks\");\r\n }\r\n callbacks?.forEach((callback) => callback(message.data));\r\n } else if (message.error) {\r\n console.error(\"WebSocket error:\", message.error);\r\n } else {\r\n // Log unknown message formats to help debug\r\n console.warn(\"Unhandled WebSocket message format:\", message);\r\n }\r\n } catch (error) {\r\n if (this.debug) {\r\n console.error(\"Error processing WebSocket message:\", error);\r\n console.error(\"Raw message:\", event.data);\r\n }\r\n }\r\n };\r\n\r\n this.ws.onclose = (event) => {\r\n this.isConnected = false;\r\n this.pendingAuth = false; // Reset auth state\r\n\r\n if (this.debug) {\r\n console.log(\r\n `WebSocket connection closed. Code: ${event.code}, Reason: ${event.reason}`\r\n );\r\n }\r\n\r\n // Try to reconnect after a delay\r\n this.reconnectTimeout = setTimeout(() => this.connect(), 2000);\r\n };\r\n\r\n this.ws.onerror = (error) => {\r\n if (this.debug) {\r\n console.log(\"WebSocket error:\", error);\r\n }\r\n };\r\n } catch (error) {\r\n if (this.debug) {\r\n console.log(\"Failed to create WebSocket connection:\", error);\r\n }\r\n this.pendingAuth = false;\r\n // Try to reconnect after a delay\r\n this.reconnectTimeout = setTimeout(() => this.connect(), 2000);\r\n }\r\n }\r\n\r\n public disconnect() {\r\n if (this.reconnectTimeout) {\r\n clearTimeout(this.reconnectTimeout);\r\n this.reconnectTimeout = null;\r\n }\r\n\r\n if (this.ws) {\r\n this.ws.close();\r\n this.ws = null;\r\n }\r\n\r\n this.isConnected = false;\r\n this.pendingAuth = false;\r\n this.authActions = [];\r\n this.subscriptions.clear();\r\n }\r\n\r\n public send(message: any) {\r\n if (this.isConnected && this.ws?.readyState === this.WebSocketImpl.OPEN) {\r\n // If authentication is pending and this isn't an auth message, queue it\r\n if (this.pendingAuth && message.type !== \"authenticate\") {\r\n this.messageQueue.push(message);\r\n if (this.debug) {\r\n console.log(\r\n \"Message queued until authentication completes:\",\r\n message\r\n );\r\n }\r\n return;\r\n }\r\n\r\n const messageStr = JSON.stringify(message);\r\n this.ws.send(messageStr);\r\n\r\n if (this.debug) {\r\n console.log(\"WebSocket message sent:\", messageStr);\r\n }\r\n } else {\r\n this.messageQueue.push(message);\r\n\r\n if (this.debug) {\r\n console.log(\"WebSocket message queued (not connected):\", message);\r\n }\r\n }\r\n }\r\n\r\n public subscribe(topic: string, callback: (data: any) => void) {\r\n if (!this.subscriptions.has(topic)) {\r\n this.subscriptions.set(topic, new Set());\r\n\r\n // If we're connected, send the subscription (with auth awareness)\r\n if (this.isConnected) {\r\n if (this.pendingAuth) {\r\n // Queue the subscription for after auth\r\n this.authActions.push(() => {\r\n this.send({ type: \"subscribe\", topic });\r\n if (this.debug) {\r\n console.log(`Subscribed to topic after auth: ${topic}`);\r\n }\r\n });\r\n } else {\r\n // Send immediately\r\n this.send({ type: \"subscribe\", topic });\r\n if (this.debug) {\r\n console.log(`Subscribed to topic: ${topic}`);\r\n }\r\n }\r\n }\r\n }\r\n\r\n this.subscriptions.get(topic)!.add(callback);\r\n\r\n return {\r\n unsubscribe: () => this.unsubscribe(topic, callback),\r\n publish: (data: any) => this.publish(topic, data),\r\n };\r\n }\r\n\r\n private unsubscribe(topic: string, callback: (data: any) => void) {\r\n const callbacks = this.subscriptions.get(topic);\r\n if (callbacks) {\r\n callbacks.delete(callback);\r\n if (callbacks.size === 0) {\r\n this.subscriptions.delete(topic);\r\n this.send({ type: \"unsubscribe\", topic });\r\n\r\n if (this.debug) {\r\n console.log(`Unsubscribed from topic: ${topic}`);\r\n }\r\n }\r\n }\r\n }\r\n\r\n public publish(topic: string, data: any) {\r\n this.send({ type: \"publish\", topic, data });\r\n\r\n if (this.debug) {\r\n console.log(`Published to topic: ${topic}`, data);\r\n }\r\n }\r\n\r\n // Method to update auth token when it changes\r\n public async updateAuth() {\r\n const headers = await this.getHeaders();\r\n const authHeader = headers[\"Authorization\"] || \"\";\r\n\r\n // Extract token from header - may be empty (\"Bearer \")\r\n const newToken = authHeader.startsWith(\"Bearer \")\r\n ? authHeader.substring(7).trim()\r\n : authHeader.trim();\r\n\r\n const hasValidToken = newToken.length > 0;\r\n const hadValidToken =\r\n this.authToken !== null && this.authToken.trim().length > 0;\r\n\r\n // If token status changed and we're connected, handle the change\r\n if (\r\n (hasValidToken !== hadValidToken || newToken !== this.authToken) &&\r\n this.isConnected\r\n ) {\r\n // Update stored token\r\n this.authToken = newToken;\r\n\r\n // Always send authenticate message, but with empty token when logging out\r\n this.pendingAuth = hasValidToken;\r\n this.send({ type: \"authenticate\", token: authHeader });\r\n\r\n if (this.debug) {\r\n if (hasValidToken) {\r\n console.log(\"Updated authentication token, waiting for confirmation\");\r\n } else {\r\n console.log(\"Sent empty token for deauthentication\");\r\n // Since we're not expecting auth confirmation for logout, clear pending state\r\n this.pendingAuth = false;\r\n this.authActions = [];\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\nexport { WebSocketManager };\r\n",
|
|
9
|
+
"import { BrpcClientError } from \"./brpc-client-error\";\r\nimport { getObjectUrl } from \"./storage\";\r\nimport type {\r\n HeadersResolver,\r\n BrpcClient,\r\n InferClientRoutes,\r\n BrpcClientOptions,\r\n} from \"./types\";\r\nimport {\r\n getFormattedBaseUrl,\r\n getProceduresPrefixPath,\r\n getWsUrl,\r\n parsePrefix,\r\n} from \"./utils\";\r\nimport { WebSocketManager } from \"./ws-manager\";\r\n\r\n/**\r\n * Creates a type-safe client for the BRPC API\r\n * @param baseUrl The base URL of the BRPC server\r\n * @param options Client configuration options\r\n * @returns A client object that mirrors the server routes\r\n */\r\nexport function createBrpcClient<TRoutesStructure>(\r\n baseUrl: string,\r\n options: BrpcClientOptions = {}\r\n): BrpcClient<TRoutesStructure> {\r\n const fetchImpl = options.fetch || fetch;\r\n const WebSocketImpl =\r\n options.WebSocket ?? (typeof WebSocket !== \"undefined\" ? WebSocket : null);\r\n const prefix = options.prefix ?? \"\";\r\n const apiPrefix = options.apiPrefix ?? \"\";\r\n const debug = options.debug ?? false;\r\n const s3Endpoint = options.s3Endpoint;\r\n const nodeEnv = options.nodeEnv;\r\n\r\n if (!WebSocketImpl) {\r\n throw new Error(\"WebSocket is not available in this environment\");\r\n }\r\n\r\n let currentHeaders: HeadersResolver = options.headers ?? {};\r\n\r\n const headersResolver: HeadersResolver = async () => {\r\n if (typeof currentHeaders === \"function\") {\r\n return await currentHeaders();\r\n }\r\n return currentHeaders;\r\n };\r\n\r\n // Properly format the base URL\r\n const formattedBaseUrl = getFormattedBaseUrl(baseUrl);\r\n\r\n // Format prefixes (returns clean word, like api, without\r\n // initial and trailing slahes)\r\n const parsedPrefix = parsePrefix(options.prefix);\r\n const parsedApiPrefix = parsePrefix(options.apiPrefix);\r\n\r\n const proceduresPrefixedPath = getProceduresPrefixPath(\r\n parsedPrefix,\r\n parsedApiPrefix\r\n );\r\n\r\n // Create WebSocket URL with proper path joining\r\n const wsUrl = getWsUrl(formattedBaseUrl, parsedPrefix);\r\n\r\n // Create WebSocket manager with headers resolver\r\n const wsManager = new WebSocketManager(\r\n wsUrl,\r\n WebSocketImpl,\r\n currentHeaders,\r\n debug,\r\n nodeEnv\r\n );\r\n\r\n // Helper to resolve headers before each request\r\n const resolveHeaders = async (\r\n defaultContentType = true\r\n ): Promise<Record<string, string>> => {\r\n const baseHeaders: Record<string, string> = {};\r\n\r\n if (defaultContentType) {\r\n baseHeaders[\"Content-Type\"] = \"application/json\";\r\n }\r\n\r\n // Use the same headersResolver as WebSocket\r\n const dynamicHeaders = await headersResolver();\r\n return { ...baseHeaders, ...dynamicHeaders };\r\n };\r\n\r\n // Helper to handle HTTP responses\r\n const handleResponse = async (response: Response) => {\r\n if (!response.ok) {\r\n let errorData;\r\n try {\r\n errorData = await response.json();\r\n } catch {\r\n try {\r\n errorData = { error: await response.text() };\r\n } catch {\r\n errorData = { error: \"Failed to parse error response\" };\r\n }\r\n }\r\n\r\n // Handle the new BRPCError format from server\r\n if (errorData?.error && typeof errorData.error === \"object\") {\r\n const serverError = errorData.error;\r\n\r\n throw new BrpcClientError(\r\n serverError.message || response.statusText,\r\n response.status,\r\n serverError.code,\r\n serverError.clientCode,\r\n serverError.data\r\n );\r\n }\r\n\r\n // Handle legacy error format or simple string errors\r\n const errorMessage =\r\n errorData?.error || errorData?.message || response.statusText;\r\n\r\n throw new BrpcClientError(\r\n errorMessage,\r\n response.status,\r\n undefined,\r\n undefined,\r\n errorData\r\n );\r\n }\r\n\r\n // Check content type to determine how to handle the response\r\n const contentType = response.headers.get(\"Content-Type\") || \"\";\r\n\r\n try {\r\n if (contentType.includes(\"application/json\")) {\r\n const result = await response.json();\r\n return result.data;\r\n } else if (contentType.includes(\"text/\")) {\r\n return response.text();\r\n } else {\r\n return response.blob();\r\n }\r\n } catch (error) {\r\n // Wrap JSON parsing errors\r\n throw new BrpcClientError(\r\n `Failed to parse response: ${\r\n error instanceof Error ? error.message : \"Unknown error\"\r\n }`,\r\n response.status,\r\n \"PARSE_ERROR\"\r\n );\r\n }\r\n };\r\n\r\n // Wrap fetch AND response handling to always return BrpcClientError\r\n const safeFetch = async (url: string | URL, init?: RequestInit) => {\r\n try {\r\n const response = await fetchImpl(url, init);\r\n return await handleResponse(response); // This throws BrpcClientError if not ok\r\n } catch (error) {\r\n // If already a BrpcClientError (from handleResponse), re-throw as-is\r\n if (error instanceof BrpcClientError) {\r\n throw error;\r\n }\r\n\r\n // Network errors - wrap them\r\n throw new BrpcClientError(\r\n error instanceof Error ? error.message : \"Network request failed\",\r\n 0,\r\n \"NETWORK_ERROR\"\r\n );\r\n }\r\n };\r\n\r\n // Create a proxy for a specific path\r\n const createProxy = (pathSegments: string[] = []): any => {\r\n return new Proxy(\r\n {},\r\n {\r\n get(_, key: string | symbol) {\r\n if (typeof key === \"symbol\") return undefined;\r\n\r\n // Special methods for procedures\r\n if (\r\n key === \"query\" ||\r\n key === \"mutation\" ||\r\n key === \"formMutation\" ||\r\n key === \"subscription\" ||\r\n key === \"getStringKey\" ||\r\n key === \"getArrayKey\" ||\r\n key === \"getNoInputsArrayKey\"\r\n ) {\r\n // The path up to this point is the procedure path\r\n const procedurePath = pathSegments.join(\"/\");\r\n const fullUrl = `${formattedBaseUrl}${proceduresPrefixedPath}/${procedurePath}`;\r\n\r\n if (debug) {\r\n console.log(`BRPC ${key} procedure path: ${procedurePath}`);\r\n console.log(`BRPC ${key} full URL: ${fullUrl}`);\r\n }\r\n\r\n if (key === \"query\") {\r\n return async (input: any) => {\r\n // Get fresh headers for this request\r\n const headers = await resolveHeaders(true);\r\n\r\n if (debug) {\r\n console.log(`BRPC query request to ${procedurePath}`, {\r\n input,\r\n headers,\r\n });\r\n }\r\n\r\n const url = new URL(fullUrl);\r\n\r\n // Add input parameters to URL for GET request\r\n if (input && typeof input === \"object\") {\r\n Object.entries(input).forEach(([k, v]) => {\r\n if (v !== undefined) {\r\n url.searchParams.append(k, String(v));\r\n }\r\n });\r\n }\r\n\r\n const result = await safeFetch(url.toString(), {\r\n method: \"GET\",\r\n headers,\r\n credentials: \"include\", //always include credentials\r\n });\r\n\r\n if (debug) {\r\n console.log(\r\n `BRPC query response from ${procedurePath}:`,\r\n result\r\n );\r\n }\r\n\r\n return result;\r\n };\r\n } else if (key === \"mutation\") {\r\n return async (input: any) => {\r\n // Get fresh headers for this request\r\n const headers = await resolveHeaders(true);\r\n\r\n if (debug) {\r\n console.log(`BRPC mutation request to ${procedurePath}`, {\r\n input,\r\n headers,\r\n });\r\n }\r\n\r\n const body = JSON.stringify(input);\r\n\r\n const result = await safeFetch(fullUrl, {\r\n method: \"POST\",\r\n headers,\r\n body,\r\n credentials: \"include\",\r\n });\r\n\r\n if (debug) {\r\n console.log(\r\n `BRPC mutation response from ${procedurePath}:`,\r\n result\r\n );\r\n }\r\n\r\n return result;\r\n };\r\n } else if (key === \"formMutation\") {\r\n return async (input: Record<string, any>) => {\r\n // Get fresh headers for this request (no Content-Type for FormData)\r\n const headers = await resolveHeaders(false);\r\n\r\n if (debug) {\r\n console.log(`BRPC formMutation request to ${procedurePath}`, {\r\n input,\r\n headers,\r\n });\r\n }\r\n\r\n // Convert object input to FormData\r\n const formData = new FormData();\r\n\r\n // Helper function to append values to FormData\r\n const appendToFormData = (\r\n key: string,\r\n value: any,\r\n parentKey?: string\r\n ) => {\r\n const fullKey = parentKey ? `${parentKey}[${key}]` : key;\r\n\r\n if (value === null || value === undefined) {\r\n // Skip null/undefined values\r\n return;\r\n } else if (value instanceof File || value instanceof Blob) {\r\n // Handle files directly\r\n formData.append(fullKey, value);\r\n } else if (Array.isArray(value)) {\r\n // Handle arrays\r\n value.forEach((item, index) => {\r\n if (item instanceof File || item instanceof Blob) {\r\n // ✅ Append files with the same key (not indexed)\r\n formData.append(fullKey, item);\r\n } else if (typeof item === \"object\" && item !== null) {\r\n Object.entries(item).forEach(([subKey, subValue]) => {\r\n appendToFormData(\r\n subKey,\r\n subValue,\r\n `${fullKey}[${index}]`\r\n );\r\n });\r\n } else {\r\n formData.append(`${fullKey}[${index}]`, String(item));\r\n }\r\n });\r\n } else if (typeof value === \"object\" && value !== null) {\r\n // Handle nested objects\r\n Object.entries(value).forEach(([subKey, subValue]) => {\r\n appendToFormData(subKey, subValue, fullKey);\r\n });\r\n } else {\r\n // Handle primitive values\r\n formData.append(fullKey, String(value));\r\n }\r\n };\r\n\r\n // Convert input object to FormData\r\n Object.entries(input).forEach(([key, value]) => {\r\n appendToFormData(key, value);\r\n });\r\n\r\n const result = await safeFetch(fullUrl, {\r\n method: \"POST\",\r\n headers,\r\n body: formData,\r\n credentials: \"include\",\r\n });\r\n\r\n if (debug) {\r\n console.log(\r\n `BRPC formMutation response from ${procedurePath}:`,\r\n result\r\n );\r\n }\r\n\r\n return result;\r\n };\r\n } else if (key === \"subscription\") {\r\n return (callback: (data: any) => void) => {\r\n if (debug) {\r\n console.log(`BRPC subscription to ${procedurePath}`);\r\n }\r\n\r\n // Use the same pattern as fullUrl for consistency\r\n const topicPath = proceduresPrefixedPath\r\n ? `${proceduresPrefixedPath.slice(1)}/${procedurePath}` // Remove leading /\r\n : procedurePath;\r\n\r\n // Update WebSocket auth if needed before subscribing\r\n wsManager.updateAuth();\r\n\r\n // Return an object with unsubscribe and publish methods\r\n return wsManager.subscribe(topicPath, callback);\r\n };\r\n } else if (key === \"getStringKey\") {\r\n return (input?: any) => {\r\n // Create a deterministic key based on procedure path and input\r\n const baseKey = procedurePath;\r\n\r\n if (!input || Object.keys(input).length === 0) {\r\n return baseKey;\r\n }\r\n\r\n // Sort input keys for deterministic key generation\r\n const sortedInput = Object.keys(input)\r\n .sort()\r\n .reduce((result, key) => {\r\n const value = input[key];\r\n if (value !== undefined && value !== null) {\r\n result[key] = value;\r\n }\r\n return result;\r\n }, {} as Record<string, any>);\r\n\r\n // Only add input hash if there are actual values\r\n if (Object.keys(sortedInput).length === 0) {\r\n return baseKey;\r\n }\r\n\r\n // Create a simple hash from the sorted input\r\n const inputString = JSON.stringify(sortedInput);\r\n return `${baseKey}?${inputString}`;\r\n };\r\n } else if (key === \"getArrayKey\") {\r\n return (input?: any) => {\r\n // Use the full procedure path as the first segment for easier invalidation\r\n const basePath = procedurePath;\r\n\r\n if (!input || Object.keys(input).length === 0) {\r\n return [basePath];\r\n }\r\n\r\n // Normalize and sort input keys for deterministic key generation\r\n const normalizedPairs: Array<[string, any]> = [];\r\n\r\n Object.keys(input)\r\n .sort()\r\n .forEach((key) => {\r\n const value = input[key];\r\n if (value !== undefined && value !== null) {\r\n // Normalize values for consistent comparison\r\n let normalizedValue = value;\r\n\r\n // Convert primitives to strings for consistency\r\n if (\r\n typeof value === \"boolean\" ||\r\n typeof value === \"number\"\r\n ) {\r\n normalizedValue = String(value);\r\n } else if (typeof value === \"object\") {\r\n // For objects/arrays, use JSON representation\r\n normalizedValue = JSON.stringify(value);\r\n }\r\n\r\n normalizedPairs.push([key, normalizedValue]);\r\n }\r\n });\r\n\r\n // Only add input segments if there are actual values\r\n if (normalizedPairs.length === 0) {\r\n return [basePath];\r\n }\r\n\r\n // Create individual segments for each input pair\r\n // This allows for better pattern matching\r\n const inputSegments = normalizedPairs.flatMap(\r\n ([key, value]) => [key, value]\r\n );\r\n\r\n return [basePath, ...inputSegments];\r\n };\r\n } else if (key === \"getNoInputsArrayKey\") {\r\n return () => {\r\n // Always return just the procedure path, ignoring any inputs\r\n // Perfect for invalidating all variants of a procedure\r\n return [procedurePath];\r\n };\r\n }\r\n }\r\n\r\n // Continue traversing the path for nested routes\r\n return createProxy([...pathSegments, key]);\r\n },\r\n }\r\n );\r\n };\r\n\r\n // Create the base proxy\r\n const clientProxy = createProxy() as InferClientRoutes<TRoutesStructure>;\r\n\r\n if (debug) {\r\n console.log(\"BRPC client created\", {\r\n baseUrl: formattedBaseUrl,\r\n prefix: proceduresPrefixedPath,\r\n wsUrl: wsUrl,\r\n });\r\n }\r\n\r\n return {\r\n routes: clientProxy,\r\n\r\n storage: {\r\n getObjectUrl: (storageObject, opts) =>\r\n getObjectUrl(storageObject, opts, s3Endpoint),\r\n },\r\n\r\n utils: {\r\n updateWsAuth: async () => await wsManager.updateAuth(),\r\n\r\n setHeader: async (key: string, value: string) => {\r\n if (typeof currentHeaders === \"function\") {\r\n console.warn(\r\n \"Cannot use setHeader with function-based headers resolver\"\r\n );\r\n return;\r\n }\r\n currentHeaders = { ...currentHeaders, [key]: value };\r\n await wsManager.updateAuth();\r\n },\r\n\r\n setHeaders: async (headers: Record<string, string>) => {\r\n if (typeof currentHeaders === \"function\") {\r\n console.warn(\r\n \"Cannot use setHeaders with function-based headers resolver\"\r\n );\r\n return;\r\n }\r\n currentHeaders = { ...currentHeaders, ...headers };\r\n await wsManager.updateAuth();\r\n },\r\n },\r\n };\r\n}\r\n"
|
|
10
10
|
],
|
|
11
|
-
"mappings": "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",
|
|
12
|
-
"debugId": "
|
|
11
|
+
"mappings": "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",
|
|
12
|
+
"debugId": "5C8464CC76330D1564756E2164756E21",
|
|
13
13
|
"names": []
|
|
14
14
|
}
|
package/dist/client/storage.d.ts
CHANGED
|
@@ -9,4 +9,4 @@ export type GetObjectUrl = (storageObject: StorageObject | null | undefined, opt
|
|
|
9
9
|
export declare function getObjectUrl(storageObject: StorageObject | null | undefined, options?: {
|
|
10
10
|
placeholder?: string;
|
|
11
11
|
throwOnInvalid?: boolean;
|
|
12
|
-
}): string;
|
|
12
|
+
}, s3Endpoint?: string): string;
|
package/dist/client/types.d.ts
CHANGED
|
@@ -83,6 +83,18 @@ export interface BrpcClientOptions {
|
|
|
83
83
|
* Enable debug logging for requests, responses, and WebSocket communication.
|
|
84
84
|
*/
|
|
85
85
|
debug?: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* S3 CDN endpoint for resolving public storage object URLs.
|
|
88
|
+
* Falls back to VITE_S3_CDN_ENDPOINT in Vite environments.
|
|
89
|
+
* Required in React Native (no import.meta.env available).
|
|
90
|
+
*/
|
|
91
|
+
s3Endpoint?: string;
|
|
92
|
+
/**
|
|
93
|
+
* Current environment (e.g. "development", "production").
|
|
94
|
+
* Falls back to VITE_NODE_ENV in Vite environments.
|
|
95
|
+
* Required in React Native to enable debug WebSocket logging.
|
|
96
|
+
*/
|
|
97
|
+
nodeEnv?: string;
|
|
86
98
|
}
|
|
87
99
|
/**
|
|
88
100
|
* Creates a type-safe client for the BRPC API
|
|
@@ -12,7 +12,7 @@ declare class WebSocketManager {
|
|
|
12
12
|
private debug;
|
|
13
13
|
private pendingAuth;
|
|
14
14
|
private authActions;
|
|
15
|
-
constructor(baseUrl: string, WebSocketImpl: typeof WebSocket, headersResolver: HeadersResolver, debug?: boolean);
|
|
15
|
+
constructor(baseUrl: string, WebSocketImpl: typeof WebSocket, headersResolver: HeadersResolver, debug?: boolean, nodeEnv?: string);
|
|
16
16
|
private connect;
|
|
17
17
|
disconnect(): void;
|
|
18
18
|
send(message: any): void;
|
package/dist/index.d.ts
CHANGED
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($=[]){this.middlewares=$}use($){return new b([...this.middlewares,$])}input($){return new O(this.middlewares,$)}query($){return{_input:U.object({}),_output:null,_ctx:null,_type:"query",handler:$,middlewares:this.middlewares}}mutation($){return{_input:U.object({}),_output:null,_ctx:null,_type:"mutation",handler:$,middlewares:this.middlewares}}formMutation($){return{_input:U.object({}),_output:null,_ctx:null,_type:"formMutation",handler:$,middlewares:this.middlewares}}subscription($){return{_input:U.object({}),_output:null,_ctx:null,_type:"subscription",handler:$,middlewares:this.middlewares}}file($){return{_input:U.object({}),_output:null,_ctx:null,_type:"file",handler:$,middlewares:this.middlewares}}fileStream($){return{_input:U.object({}),_output:null,_ctx:null,_type:"fileStream",handler:$,middlewares:this.middlewares}}html($){return{_input:U.object({}),_output:null,_ctx:null,_type:"html",handler:$,middlewares:this.middlewares}}}class O{middlewares;inputSchema;timeoutMs;constructor($,F,J){this.middlewares=$;this.inputSchema=F;this.timeoutMs=J}timeout($){return new O(this.middlewares,this.inputSchema,$)}query($){return{_input:this.inputSchema,_output:null,_ctx:null,_type:"query",_timeout:this.timeoutMs,handler:$,middlewares:this.middlewares}}mutation($){return{_input:this.inputSchema,_output:null,_ctx:null,_type:"mutation",_timeout:this.timeoutMs,handler:$,middlewares:this.middlewares}}formMutation($){return{_input:this.inputSchema,_output:null,_ctx:null,_type:"formMutation",_timeout:this.timeoutMs,handler:$,middlewares:this.middlewares}}subscription($){return{_input:this.inputSchema,_output:null,_ctx:null,_type:"subscription",_timeout:this.timeoutMs,handler:$,middlewares:this.middlewares}}file($){return{_input:this.inputSchema,_output:null,_ctx:null,_type:"file",_timeout:this.timeoutMs,handler:$,middlewares:this.middlewares}}fileStream($){return{_input:this.inputSchema,_output:null,_ctx:null,_type:"fileStream",_timeout:this.timeoutMs,handler:$,middlewares:this.middlewares}}html($){return{_input:U.object({}),_output:null,_ctx:null,_type:"html",_timeout:this.timeoutMs,handler:$,middlewares:this.middlewares}}}function g($){return new b}import{ZodError as y}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($){super($.message);if(this.name="BRPCError",this.code=$.code,this.clientCode=$.clientCode,this.httpStatus=I.STATUS_MAP[$.code],this.data=$.data,this.cause=$.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($,F,J){return new I({code:"BAD_REQUEST",message:$,clientCode:F,data:J})}static unauthorized($="Unauthorized",F,J){return new I({code:"UNAUTHORIZED",message:$,clientCode:F,data:J})}static forbidden($="Forbidden",F,J){return new I({code:"FORBIDDEN",message:$,clientCode:F,data:J})}static notFound($="Not Found",F,J){return new I({code:"NOT_FOUND",message:$,clientCode:F,data:J})}static preconditionFailed($="Precondition failed",F,J){return new I({code:"NOT_FOUND",message:$,clientCode:F,data:J})}static conflict($,F,J){return new I({code:"CONFLICT",message:$,clientCode:F,data:J})}static unprocessableContent($,F,J){return new I({code:"UNPROCESSABLE_CONTENT",message:$,clientCode:F,data:J})}static tooManyRequests($="Too many requests",F,J){return new I({code:"TOO_MANY_REQUESTS",message:$,clientCode:F,data:J})}static internalServerError($="Internal Server Error",F,J){return new I({code:"INTERNAL_SERVER_ERROR",message:$,clientCode:F,data:J})}static timeout($="Request timeout",F,J){return new I({code:"TIMEOUT",message:$,clientCode:F,data:J})}}class Q{routeTree;routeCache;options;routeStats;constructor($,F={}){if(this.options={enableCaching:!0,maxCacheSize:1000,debug:!1,...F},this.routeCache=new Map,this.routeStats=this.analyzeRoutes($),this.routeTree=this.compileRoutes($),this.options.debug)console.log("[ROUTEMATCHER]","initialized with stats:",this.routeStats)}match($){if(this.options.enableCaching)return this.matchWithCache($);return this.matchDirect($)}matchWithCache($){let F=$.join("/");if(this.routeCache.has(F)){let _=this.routeCache.get(F);if(this.options.debug&&_)console.log("[ROUTEMATCHER]",`\uD83C\uDFAF Cache hit for route: /${F}`);return _}let J=this.matchDirect($);if(this.cacheResult(F,J),this.options.debug)console.log("[ROUTEMATCHER]",`\uD83D\uDCBE Cached route: /${F} -> ${J?"found":"not found"}`);return J}matchDirect($){let F=this.options.debug?performance.now():0,J=this.traverseTree(this.routeTree,$,0,{});if(this.options.debug){let _=performance.now()-F,W=J?.route._type||"none";console.log("[ROUTEMATCHER]",`\u26A1 Route match: /${$.join("/")} (${W}) took ${_.toFixed(3)}ms`)}return J}traverseTree($,F,J,_){if(J>=F.length){if($.handler)return{params:_,route:$.handler.handler};if($.index)return{params:_,route:$.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(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};
|
|
4
|
+
if($.wildcard&&F.length===0)return{params:{..._,wildcardPath:""},route:$.wildcard.handler};return null}let W=F[J],X=decodeURIComponent(W),Y=$.static.get(X);if(Y){let j=this.traverseTree(Y,F,J+1,_);if(j)return j}if($.param){let j={..._,[$.param.name]:X},Z=this.traverseTree($.param.node,F,J+1,j);if(Z)return Z}if($.wildcard){let j=F.slice(J).join("/");return{params:{..._,wildcardPath:j},route:$.wildcard.handler}}return null}compileRoutes($,F=[]){let J={static:new Map};for(let[_,W]of Object.entries($)){if(_==="index"&&this.isProcedure(W)){J.index={handler:W,paramNames:[...F],hasWildcard:!1};continue}if(_==="*"){if(this.isProcedure(W))J.wildcard={handler:W,paramNames:[...F,"wildcardPath"],hasWildcard:!0,wildcardIndex:F.length};continue}if(this.isProcedure(W)){let X={handler:W,paramNames:[...F],hasWildcard:!1};if(_.startsWith(":")){let Y=_.slice(1),j={static:new Map,handler:X};J.param={name:Y,node:j}}else{let Y={static:new Map,handler:X};J.static.set(_,Y)}}else if(typeof W==="object"&&W!==null)if(_.startsWith(":")){let X=_.slice(1),Y=this.compileRoutes(W,[...F,X]);J.param={name:X,node:Y}}else{let X=this.compileRoutes(W,F);J.static.set(_,X)}}return J}isProcedure($){return $&&typeof $==="object"&&"_type"in $&&"_input"in $}cacheResult($,F){if(this.routeCache.size>=this.options.maxCacheSize){let J=this.routeCache.keys().next().value;if(J!==void 0){if(this.routeCache.delete(J),this.options.debug)console.log(`\uD83D\uDDD1\uFE0F Evicted oldest cache entry: ${J}`)}}this.routeCache.set($,F)}analyzeRoutes($){let F={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}},J=(_,W=0)=>{F.maxDepth=Math.max(F.maxDepth,W);for(let[X,Y]of Object.entries(_))if(this.isProcedure(Y)){if(F.totalRoutes++,Y._type in F.procedureTypes)F.procedureTypes[Y._type]++;if(X==="index")F.indexRoutes++;else if(X.startsWith(":"))F.paramRoutes++;else if(X==="*")F.wildcardRoutes++;else F.staticRoutes++}else if(typeof Y==="object"&&Y!==null)J(Y,W+1)};return J($),F}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 $=[],{routeStats:F}=this;if(F.paramRoutes>F.staticRoutes*2)$.push("\uD83D\uDE80 Consider grouping routes to reduce parameter route overhead");if(F.maxDepth>6)$.push("\uD83D\uDCCA Deep route nesting detected - consider flattening some routes");if(F.totalRoutes>200)$.push("\u26A1 Large route table - consider route splitting or lazy loading");if(!this.options.enableCaching&&F.totalRoutes>50)$.push("\uD83D\uDCBE Enable caching for better performance with many routes");if(F.procedureTypes.file>20)$.push("\uD83D\uDCC1 Many file routes detected - consider static file serving");if(F.procedureTypes.subscription>10)$.push("\uD83D\uDD04 Many subscription routes - ensure WebSocket optimization");return $}findRoutesByPattern($){return[]}getRouteInfo($){let F=$.split("/").filter(Boolean),J=F.join("/"),_=this.routeCache.has(J),W=performance.now(),X=this.matchDirect(F),Y=performance.now()-W;return{found:!!X,route:X?.route,params:X?.params,cached:_,matchTime:Y}}benchmark($,F=1000){let J=$.map((G)=>G.split("/").filter(Boolean)),_=new Map(this.routeCache);this.routeCache.clear();let W=performance.now();for(let G=0;G<F;G++)for(let D of J)this.matchDirect(D);let Y=performance.now()-W,j=F*$.length,Z=Y/j,L=j/Y*1000;return this.routeCache=_,{averageTime:Z,totalTime:Y,routesPerSecond:L}}warmupCache($){if(!this.options.enableCaching)return;let F=performance.now(),J=0;for(let W of $){let X=W.split("/").filter(Boolean),Y=this.matchDirect(X);if(Y)this.cacheResult(X.join("/"),Y),J++}let _=performance.now();if(this.options.debug)console.log("[ROUTEMATCHER]",`\uD83D\uDD25 Cache warmed up: ${J} routes in ${(_-F).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($){return x[$]}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($){return v[$]||"application/octet-stream"}function f($){if(typeof Bun<"u"&&Bun.hash)return Bun.hash($).toString(16);try{let F=C("crypto"),J;if(typeof $==="string")J=Buffer.from($);else if($ instanceof ArrayBuffer)J=Buffer.from(new Uint8Array($));else J=Buffer.from($);return F.createHash("md5").update(J).digest("hex")}catch{let F=typeof $==="string"?new TextEncoder().encode($):$ instanceof ArrayBuffer?new Uint8Array($):$,J=0;for(let _=0;_<F.length;_++)J=(J<<5)-J+F[_],J=J&J;return Math.abs(J).toString(16).padStart(16,"0")}}function V($,F,J){let _=$.headers.get("Origin"),W=!0;if((J?.allowAll??!0)&&_)return _;if(F.length===0)return _||"*";if(!_)return F[0];if(F.includes(_))return _;return F[0]}class B{headers={};contentType($){return this.headers["Content-Type"]=S($),this}filePath($){let F=$.split(".").pop()?.toLowerCase()||"";return this.headers["Content-Type"]=S(F),this}mimeType($){return this.headers["Content-Type"]=$,this}cache($){let{cacheControl:F,expires:J}=q($);if(this.headers["Cache-Control"]=F,J)this.headers.Expires=J;return this}eTag($){if(!$)return this;let F;if(typeof $==="string"&&$.startsWith('"'))F=$;else F=`"${f($)}"`;return this.headers.ETag=F,this}lastModified($){return this.headers["Last-Modified"]=$.toUTCString(),this}contentLength($){return this.headers["Content-Length"]=$.toString(),this}redirect($,F=!1){return this.headers.Location=$,this.headers["X-Redirect-Type"]=F?"permanent":"temporary",this}cors({origin:$="*",methods:F=["GET","POST","PUT","DELETE","OPTIONS"],headers:J=["Content-Type","Authorization"],maxAge:_=86400,credentials:W}={}){let X=W??$!=="*";if(X&&$==="*")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"]=$,this.headers["Access-Control-Allow-Methods"]=F.join(", "),this.headers["Access-Control-Allow-Headers"]=J.join(", "),X)this.headers["Access-Control-Allow-Credentials"]="true";return this.headers["Access-Control-Max-Age"]=_.toString(),this}security($){let F={hsts:!0,noSniff:!0,frameOptions:"SAMEORIGIN",xssProtection:!0,...$};if(F.csp)this.headers["Content-Security-Policy"]=F.csp;if(F.hsts){let J=typeof F.hsts==="number"?F.hsts:31536000;this.headers["Strict-Transport-Security"]=`max-age=${J}; includeSubDomains`}if(F.noSniff)this.headers["X-Content-Type-Options"]="nosniff";if(F.frameOptions)this.headers["X-Frame-Options"]=F.frameOptions;if(F.xssProtection)this.headers["X-XSS-Protection"]="1; mode=block";return this}custom($,F){return this.headers[$]=F,this}customHeaders($){return Object.assign(this.headers,$),this}vary(...$){let F=this.headers.Vary,J=F?`${F}, ${$.join(", ")}`:$.join(", ");return this.headers.Vary=J,this}compress($){if($)this.headers["Content-Encoding"]=$;return this}build($){let F={...this.headers};if($&&!F["Content-Length"]){let J=typeof $==="string"?new TextEncoder().encode($).length:$.byteLength;F["Content-Length"]=J.toString()}return F}buildHeaders($){return new Headers(this.build($))}}function A(){return new B}function l($,F){let J=A().contentType($);if(F)J.cache(F);return J.build()}var c={css:($)=>A().contentType("css").cache("STYLESHEET").eTag($),javascript:($)=>A().contentType("javascript").cache("JAVASCRIPT").eTag($),hashedAsset:($,F)=>A().filePath($).cache("HASHED_ASSET").eTag(F),font:($)=>A().filePath($).cache("FONT").cors({origin:"*"}),image:($)=>A().filePath($).cache("IMAGE"),favicon:()=>A().contentType("icon").cache("FAVICON"),api:()=>A().contentType("json").cache("API_RESPONSE").cors(),expensiveApi:($)=>A().contentType("json").cache("API_RESPONSE").cors().eTag($),realtime:()=>A().contentType("json").cache("NO_CACHE").cors(),html:()=>A().contentType("html").cache("HTML_PAGE").security(),expensiveHtml:($)=>A().contentType("html").cache("HTML_PAGE").security().eTag($),manifest:($)=>A().contentType("json").cache("MANIFEST").eTag($),serviceWorker:()=>A().contentType("javascript").cache("SERVICE_WORKER"),sitemap:($)=>A().contentType("xml").cache("SITEMAP").eTag($),feed:($,F="rss")=>A().contentType("xml").cache("FEED").eTag($).mimeType(F==="rss"?"application/rss+xml":"application/atom+xml"),video:($)=>A().filePath($).cache("MEDIA_STREAM").custom("Accept-Ranges","bytes"),audio:($)=>A().filePath($).cache("MEDIA_STREAM").custom("Accept-Ranges","bytes"),pdf:($)=>A().contentType("pdf").cache("DOCUMENT").custom("Content-Disposition","inline").eTag($),download:($,F,J)=>A().filePath(F).cache("ARCHIVE").custom("Content-Disposition",`attachment; filename="${$}"`).eTag(J),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:($)=>A().redirect($,!0),temporaryRedirect:($)=>A().redirect($,!1)};async function T($,F,J,_={}){let{maxChunkSize:W=2097152,cacheMaxAge:X=3600,acceptedExtensions:Y}=_;if(!await $.exists())return new Response("Media file not found",{status:404,headers:A().contentType("text").cors({origin:V(F,J)}).build()});if(Y&&Y.length>0){let K=$.name?.toLowerCase().split(".").pop();if(!K||!Y.includes(K))return new Response("File type not supported",{status:415,headers:A().contentType("text").cors({origin:V(F,J)}).build()})}let Z=$.size,L=F.headers.get("Range");if(!L)return new Response($,{headers:A().filePath($.name||"media").custom("Accept-Ranges","bytes").custom("Cache-Control",`public, max-age=${X}`).cors({origin:V(F,J)}).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(F,J)}).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+W-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(F,J)}).custom("Content-Range",`bytes */${Z}`).build()});return new Response($.slice(D,M+1),{status:206,headers:A().filePath($.name||"media").custom("Accept-Ranges","bytes").custom("Cache-Control",`public, max-age=${X}`).cors({origin:V(F,J)}).build()})}function z($,F,J){return{type:"stream",file:$,request:F,options:J}}class E{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($){if(this.contextCreator=$.context,this.prefix=$.prefix??"",this.routes=$.routes,this.globalMiddlewares=$.globalMiddlewares??[],this.wsConfig=$.websocket??{},this.integrations=$.integrations,this.debug=!!$.debug&&!0,this.onError=$.onError,this.routeMatcher=new Q($.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($){return this.routeMatcher.match($)}async parseInput($,F,J){let _={},W=new URL($.url),X=Object.fromEntries(W.searchParams),Y=$.method;if(Y==="POST"){if(parseInt($.headers.get("content-length")||"0")>this.maxRequestSize)throw Error("Request payload too large")}if(Y==="GET"&&["query","streamQuery","file","fileStream","html"].includes(J))_=X;else if(Y==="POST"&&["mutation","formMutation","streamMutation"].includes(J)){let j=$.headers.get("content-type");if(j?.includes("application/json"))_=await $.json();else if(j?.includes("multipart/form-data")){let Z=await $.formData();_=await this.parseFormData(Z)}else throw Error("Unsupported content type")}else throw Error(`Unsupported request method ${Y} for procedure type ${J}`);return F.parse(_)}async parseFormData($){let F={},J={};$.forEach(async(_,W)=>{if(_ instanceof File){if(!J[W])J[W]=[];J[W].push(_)}else if(typeof _==="string")try{F[W]=JSON.parse(_)}catch{F[W]=_}});for(let[_,W]of Object.entries(J))F[_]=W;return F}handleError($,F){if(this.onError)try{this.onError($,{req:F,route:F.url})}catch(J){console.error("Error logger failed:",J)}if($?.errors&&Array.isArray($.errors)&&$.name==="ZodError")return new Response(JSON.stringify({error:{name:"ValidationError",code:"BAD_REQUEST",clientCode:"VALIDATION_ERROR",message:"Input validation failed",data:{validationErrors:$.errors.map((J)=>({path:J.path.join("."),message:J.message,code:J.code,received:J.received}))},httpStatus:400}}),{status:400,headers:A().contentType("json").cors({origin:V(F,this.allowedOrigins)}).build()});if($ instanceof I)return new Response(JSON.stringify({error:$.toJSON()}),{status:$.httpStatus,headers:A().contentType("json").cors({origin:V(F,this.allowedOrigins)}).build()});if($ instanceof Error){let J=$.message==="Not Found"?404:$.message==="Unauthorized"?401:$.message==="Forbidden"?403:$.message==="Request payload too large"?413:$.message==="Request timeout"?504:500,_=J===404?"NOT_FOUND":J===401?"UNAUTHORIZED":J===403?"FORBIDDEN":J===413?"PAYLOAD_TOO_LARGE":J===504?"GATEWAY_TIMEOUT":"INTERNAL_SERVER_ERROR",W=J<500?$.message:"Internal Server Error";return new Response(JSON.stringify({error:{code:_,message:W}}),{status:J,headers:A().contentType("json").cors({origin:V(F,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(F,this.allowedOrigins)}).build()})}handleFileCacheControl($){let F;if($?.includes("text/html"))F="public, max-age=0, must-revalidate";else if($?.includes("text/css")||$?.includes("text/javascript")||$?.includes("application/javascript"))F="public, max-age=31536000, immutable";else F="public, max-age=86400, stale-while-revalidate=604800";return F}async handleRequest($,F){try{if($.method==="OPTIONS")return new Response(null,{status:204,headers:A().cors({origin:V($,this.allowedOrigins)}).build()});let _=new URL($.url).pathname;if(_=_.startsWith(this.prefix)?_.slice(this.prefix.length):_,_=_.startsWith("/")?_:"/"+_,_==="/ws"&&F){if(this.debug)console.log("\uD83D\uDD0C WebSocket upgrade requested");return this.handleWebSocketUpgrade($,F)}let W=_==="/"?[]:_.split("/").filter(Boolean),X=this.findRoute(W);if(!X)return new Response("Not Found",{status:404,headers:A().contentType("text").cors({origin:V($,this.allowedOrigins)}).build()});let{route:Y}=X,j=Y._timeout??this.requestTimeout,Z=new Promise((L,G)=>{setTimeout(()=>G(Error("Request timeout")),j)});return await Promise.race([this._handleRequest($,F,X),Z])}catch(J){return this.handleError(J,$)}}async _handleRequest($,F,J){try{if(!J)return new Response("Not Found",{status:404,headers:A().contentType("text").cors({origin:V($,this.allowedOrigins)}).build()});let{params:_,route:W}=J;if(!W.handler)return new Response("Handler not implemented",{status:501,headers:A().contentType("text").cors({origin:V($,this.allowedOrigins)}).build()});let X=new Headers,Y=await this.contextCreator($);Object.assign(Y,{req:$,params:_,publishToProcedure:async(G,D,N)=>{await this.publishToProcedure(G,D,Y,N)},headers:X});for(let G of this.globalMiddlewares){let D=await G(Y);if(D!==null&&D!==void 0&&typeof D==="object")Object.assign(Y,D)}for(let G of W.middlewares){let D=await G(Y);if(D!==null&&D!==void 0&&typeof D==="object")Object.assign(Y,D)}let j=await this.parseInput($,W._input,W._type),Z=await W.handler({ctx:Y,input:j}),L=A().cors({origin:V($,this.allowedOrigins)}).build();return Object.keys(L).forEach((G)=>{X.set(G,L[G])}),await this.handleProcedureResponse(W._type,Z,X)}catch(_){return this.handleError(_,$)}}async testRequest($){return this.handleRequest($)}async handleProcedureResponse($,F,J){switch($){case"file":if(F instanceof Response)return F;let _=F.type;return J.append("Content-Type",_),J.append("Cache-Control",this.development?"public, max-age=0, must-revalidate":this.handleFileCacheControl(_)),new Response(F,{headers:J});case"fileStream":if(typeof F==="object"&&F!==null&&"type"in F&&F.type==="stream"){let X=F;return await T(F.file,F.request,this.allowedOrigins,X.options)}let W=F.type;return J.append("Content-Type",W),J.append("Cache-Control",this.development?"public, max-age=0, must-revalidate":this.handleFileCacheControl(W)),new Response(F,{headers:J});case"html":if(typeof F==="string")return J.append("Content-Type","text/html"),new Response(F,{headers:J});break;case"query":case"mutation":case"formMutation":case"streamQuery":case"streamMutation":case"subscription":default:return J.append("Content-Type","application/json"),new Response(JSON.stringify({data:F}),{headers:J})}return J.append("Content-Type","application/json"),new Response(JSON.stringify({data:F}),{headers:J})}cleanupStaleConnections(){let $=Date.now();for(let F of this.activeConnections)if($-F.data.lastActivity>this.connectionTimeout)F.close(),this.activeConnections.delete(F)}async handleWebSocketUpgrade($,F){if(this.activeConnections.size>=this.maxConnections)return new Response("Too many connections",{status:503});let J=await this.contextCreator($);Object.assign(J,{req:$});for(let W of this.globalMiddlewares){let X=await W(J);if(X!==null&&X!==void 0&&typeof X==="object")Object.assign(J,X)}if(F.upgrade($,{data:{ctx:J,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 _=F.startsWith("Bearer ")?F.substring(7):F;if($.data.ctx.authToken=_,$.send(JSON.stringify({type:"auth_success",message:"Authentication successful"})),this.debug)console.log("[BRPC]","WebSocket authenticated successfully")}catch(_){if($.send(JSON.stringify({type:"auth_error",error:_ instanceof Error?_.message:"Authentication failed"})),this.debug)console.error("WebSocket authentication error:",_)}}async handleSubscribe($,F,J){let _=this.findRoute(F.split("/").filter(Boolean));if(!_||_.route._type!=="subscription")throw Error("Invalid subscription route");$.subscribe(F),$.data.topics.add(F)}async handleUnsubscribe($,F,J){let _=this.findRoute(F.split("/").filter(Boolean));if(!_||_.route._type!=="subscription")throw Error("Invalid subscription route");$.unsubscribe(F),$.data.topics.delete(F)}async handlePublish($,F,J,_){let W=this.findRoute(F.split("/").filter(Boolean));if(!W)throw Error("Subscription not found");let{params:X,route:Y}=W;if(Y._type!=="subscription"||!Y.handler)throw Error("Invalid subscription route");Object.assign(_,{params:X});let j=Y._input.fields?Y._input.parse(J):J,Z=await Y.handler({ctx:_,input:j}),L={topic:F,data:Z,type:"publish"};if(this.debug)console.log(`Server will publish to ${F}`,L);this.server.publish(F,JSON.stringify(L))}async publishToProcedure($,F,J,_){if($._type!=="subscription"||!$.handler)throw Error("Can only publish to subscription procedures");let W=this.findRoutePath(this.routes,$);if(!W)throw Error("Subscription route not found");let X=W.split("/").map((Z)=>{if(Z.startsWith(":")){let L=Z.slice(1),G=_[L];if(!G)throw Error(`Missing parameter: ${L}`);return G}return Z}).join("/"),Y=await $.handler({ctx:{...J,params:_},input:F}),j={topic:X,data:Y,type:"publish"};if(this.debug)console.log(`Server will publish to ${X}`,j);return this.server?.publish(X,JSON.stringify(j)),Y}async publish($,F,J){if($._type!=="subscription"||!$.handler)throw Error("Can only publish to subscription procedures");let _=this.findRoutePath(this.routes,$);if(!_)throw Error("Subscription route not found");let W=_.split("/").map((j)=>{if(j.startsWith(":")){let Z=j.slice(1),L=J?J[Z]:null;if(!L)throw Error(`Missing parameter: ${Z}`);return L}return j}).join("/"),X=await $.handler({ctx:{params:J},input:F}),Y={topic:W,data:X,type:"publish"};if(this.debug)console.log(`Server will publish to ${W}`,Y);return this.server?.publish(W,JSON.stringify(Y)),X}freePublish($,F){let J={topic:$,data:F,type:"publish"};this.server?.publish($,JSON.stringify(J))}findRoutePath($,F,J=""){for(let[_,W]of Object.entries($)){let X=J?`${J}/${_}`:_;if(W===F)return X;if(W&&typeof W==="object"&&!("_type"in W)){let Y=this.findRoutePath(W,F,X);if(Y)return Y}}return null}getIntegrationRoutes(){if(!this.integrations)return;let $={};if(this.integrations.betterAuth){let F=this.integrations.betterAuth.handler;if(!F)throw Error("Please provide a handler for betterAuth integration");$["/api/auth/*"]=async(J)=>{return await F(J)}}if(this.integrations.rawRoutes)Object.keys(this.integrations.rawRoutes).forEach((F)=>{$[F]=this.integrations.rawRoutes[F]});return Object.keys($).length>0?$: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($=["/users/123","/posts/456/comments"],F=1000){if(this.debug){let J=this.routeMatcher.benchmark($,F);return console.log("[ROUTEMATCHER]","Route matching benchmark:",J),J}}updateRoutes($){if(this.development)this.routes=$,this.routeMatcher=new Q($,{enableCaching:!1,debug:this.debug}),console.log("[HMR]","Server Routes updated");else console.warn("Route updates are only allowed in development mode")}listen($,F){if(this.server=Bun.serve({port:$,routes:this.getIntegrationRoutes(),fetch:(J,_)=>this.handleRequest(J,_),websocket:{open:(J)=>{if(this.activeConnections.add(J),this.wsConfig?.onOpen)this.wsConfig.onOpen(J,J.data.ctx);if(this.debug)console.log("[BRPC]","WebSocket connection opened",{connections:this.activeConnections.size})},message:async(J,_)=>{try{J.data.lastActivity=Date.now();let{type:W,topic:X,token:Y,data:j}=JSON.parse(_),Z=J.data.ctx;if(this.debug)console.log("[BRPC]","WebSocket message received:",{type:W,topic:X});switch(W){case"authenticate":await this.handleAuthenticate(J,Y,Z);break;case"subscribe":await this.handleSubscribe(J,X,Z);break;case"unsubscribe":await this.handleUnsubscribe(J,X,Z);break;case"publish":await this.handlePublish(J,X,j,Z);break;default:if(J.send(JSON.stringify({error:"Unknown message type"})),this.debug)console.error("Unknown WebSocket message type:",W)}}catch(W){if(this.debug)console.error("[BRPC]","WebSocket message error:",W);if(W instanceof y)J.send(JSON.stringify({error:"Invalid message format"}));else if(W instanceof Error)J.send(JSON.stringify({error:W.message}))}},close:(J,_,W)=>{if(this.activeConnections.delete(J),J.data.topics.forEach((X)=>{J.unsubscribe(X)}),this.debug)console.log("[BRPC]","WebSocket connection closed",{code:_,reason:W,remainingConnections:this.activeConnections.size});if(this.wsConfig?.onClose)this.wsConfig.onClose(J,_,W,J.data.ctx)}}}),F)F()}}function e($){return new E($)}function F$($){return $}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"]},H=($,F="MB")=>{switch(F){case"MB":return $*1024*1024;case"KB":return $*1024;case"B":return $}},W$=({acceptedTypes:$,maxSize:F=1/0,minSize:J,messages:_={}}={})=>{let W=F?H(F):1/0,X=J?H(J):0,Y=$?Object.entries($).flatMap(([Z,L])=>{let G=Z;if(L==="*")return w[G];if(Array.isArray(L))return L;return[]}):void 0,j=P.instanceof(File,{message:_.required??"File is required"});if(j=j.refine((Z)=>Z.size<=W,_.maxSize??`File size must be less than ${F}MB`).refine((Z)=>Z.size>=X,_.minSize??`File size must be at least ${J}MB`),Y?.length)j=j.refine((Z)=>Y.includes(Z.type),_.type??`File must be of type: ${Y.join(", ")}`);return j};var Y$=($)=>{let F=$.paths.map((_)=>new RegExp(_)),J="Not Found";return async(_)=>{let X=new URL(_.req.url).pathname;if(F.some((Y)=>Y.test(X)))throw Error("Not Found")}};class R{requests=new Map;lastCleanupTime=Date.now();alertThreshold;config;constructor($){this.config={windowMs:$.windowMs,maxRequests:$.maxRequests,maxEntries:$.maxEntries??1e4,cleanupIntervalMs:$.cleanupIntervalMs??60000,message:$.message??"Too Many Requests",statusCode:$.statusCode??429,headerPrefix:$.headerPrefix??"X-RateLimit"},this.alertThreshold=this.config.maxEntries*0.8}cleanup(){let $=Date.now(),F=0;for(let[J,_]of this.requests.entries()){let W=$-_.startTime>this.config.windowMs,X=$-_.lastAccessed>this.config.windowMs*2;if(W||X)this.requests.delete(J),F++}return this.lastCleanupTime=$,F}handleMaxEntries($){let F=this.requests.size;if(Date.now()-this.lastCleanupTime>this.config.cleanupIntervalMs)this.cleanup();if(F>=this.alertThreshold)console.warn(`Rate limiter at ${Math.round(F/this.config.maxEntries*100)}% capacity`);if(this.requests.has($))return!0;return F<this.config.maxEntries}check($){if(!this.handleMaxEntries($))return{isLimited:!0,remaining:0,resetTime:Date.now()+this.config.windowMs};let F=Date.now(),J=this.requests.get($);if(!J||F-J.startTime>=this.config.windowMs)return this.requests.set($,{count:1,startTime:F,lastAccessed:F}),{isLimited:!1,remaining:this.config.maxRequests-1,resetTime:F+this.config.windowMs};J.lastAccessed=F;let _=J.count>=this.config.maxRequests;if(!_)J.count++;return{isLimited:_,remaining:Math.max(0,this.config.maxRequests-J.count),resetTime:J.startTime+this.config.windowMs}}getConfig(){return this.config}}var A$=($)=>{let F=new R($);return async(J)=>{if(J.req.headers.get("range"))return;let _=J.req.headers.get("x-forwarded-for")?.split(",")[0]||J.req.headers.get("x-real-ip")||"unknown",{isLimited:W,remaining:X,resetTime:Y}=F.check(_),{headerPrefix:j}=F.getConfig();if(J.headers.set(`${j}-Remaining`,X.toString()),J.headers.set(`${j}-Reset`,Y.toString()),W)throw J.headers.set(`${j}-Exceeded`,"true"),Error(F.getConfig().message)}};function G$($,F){return F??$}async function I$($,F){let J=performance.now();try{return await F()}catch(_){let W=performance.now();throw console.log(`[PERF] ${$} failed after ${(W-J).toFixed(4)} ms`),_}finally{let _=performance.now();console.log(`[PERF] ${$}: ${(_-J).toFixed(4)} ms`)}}export{z as streamMedia,l as quickHeaders,I$ as measure,f as hashContent,S as getMimeType,V as getCorsOrigin,e as createRouter,A$ as createRateLimiter,g as createProcedure,Y$ as createPathBlocker,G$ as createMiddleware,W$ as createFileSchema,F$ as createContext,c as commonHeaders,A as buildHeaders,E as Router,C$ as CacheService,I as BRPCError};
|
|
5
5
|
|
|
6
|
-
//# debugId=
|
|
6
|
+
//# debugId=F612D0D8B6F80A0564756E2164756E21
|
package/dist/index.js.map
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["..\\src\\procedure.ts", "..\\src\\router\\router.ts", "..\\src\\errors\\BRPCError.ts", "..\\src\\router\\RouteMatcher.ts", "..\\..\\..\\node_modules\\@mateosuarezdev\\headers-builder\\dist\\index.js", "..\\src\\stream\\media.ts", "..\\src\\context.ts", "..\\src\\schemas.ts", "..\\src\\middlewares\\pathblocker\\index.ts", "..\\src\\middlewares\\ratelimiter\\index.ts", "..\\src\\middlewares\\createMiddleware.ts"],
|
|
3
|
+
"sources": ["..\\src\\procedure.ts", "..\\src\\router\\router.ts", "..\\src\\errors\\BRPCError.ts", "..\\src\\router\\RouteMatcher.ts", "..\\..\\..\\node_modules\\@mateosuarezdev\\headers-builder\\dist\\index.js", "..\\src\\stream\\media.ts", "..\\src\\context.ts", "..\\src\\schemas.ts", "..\\src\\middlewares\\pathblocker\\index.ts", "..\\src\\middlewares\\ratelimiter\\index.ts", "..\\src\\middlewares\\createMiddleware.ts", "..\\src\\utils\\measure.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"import { z } from \"zod\";\r\nimport type {\r\n BaseContext,\r\n Handler,\r\n InferInput,\r\n Procedure,\r\n StreamableResponse,\r\n} from \"./types\";\r\nimport type { BunFile } from \"bun\";\r\n\r\nclass ProcedureBuilder<C extends BaseContext> {\r\n private middlewares: ((ctx: any) => Promise<Record<string, any> | void>)[] = [];\r\n\r\n constructor(middlewares: ((ctx: any) => Promise<Record<string, any> | void>)[] = []) {\r\n this.middlewares = middlewares;\r\n }\r\n\r\n use<M extends (ctx: C) => Promise<Record<string, any> | void>>(\r\n middleware: M\r\n ): ProcedureBuilder<\r\n Awaited<ReturnType<M>> extends Record<string, any>\r\n ? C & Awaited<ReturnType<M>>\r\n : C\r\n > {\r\n return new ProcedureBuilder<any>([...this.middlewares, middleware]);\r\n }\r\n\r\n input<I extends z.ZodType>(schema: I) {\r\n return new InputProcedureBuilder<C, I>(this.middlewares, schema);\r\n }\r\n\r\n query<O>(\r\n handler: Handler<C, {}, O>\r\n ): Procedure<C, z.ZodObject<{}>, O, \"query\"> {\r\n return {\r\n _input: z.object({}),\r\n _output: null as unknown as O,\r\n _ctx: null as unknown as C,\r\n _type: \"query\",\r\n handler,\r\n middlewares: this.middlewares,\r\n };\r\n }\r\n\r\n mutation<O>(\r\n handler: Handler<C, {}, O>\r\n ): Procedure<C, z.ZodObject<{}>, O, \"mutation\"> {\r\n return {\r\n _input: z.object({}),\r\n _output: null as unknown as O,\r\n _ctx: null as unknown as C,\r\n _type: \"mutation\",\r\n handler,\r\n middlewares: this.middlewares,\r\n };\r\n }\r\n\r\n formMutation<O>(\r\n handler: Handler<C, {}, O>\r\n ): Procedure<C, z.ZodObject<{}>, O, \"formMutation\"> {\r\n return {\r\n _input: z.object({}),\r\n _output: null as unknown as O,\r\n _ctx: null as unknown as C,\r\n _type: \"formMutation\",\r\n handler,\r\n middlewares: this.middlewares,\r\n };\r\n }\r\n\r\n //TODO\r\n // formMutation\r\n // streamMutation\r\n // streamQuery? Is even possible?\r\n\r\n subscription<O>(\r\n handler: Handler<C, {}, O>\r\n ): Procedure<C, z.ZodObject<{}>, O, \"subscription\"> {\r\n return {\r\n _input: z.object({}),\r\n _output: null as unknown as O,\r\n _ctx: null as unknown as C,\r\n _type: \"subscription\",\r\n handler,\r\n middlewares: this.middlewares,\r\n };\r\n }\r\n\r\n file(\r\n handler: Handler<C, {}, BunFile | Response>\r\n ): Procedure<C, z.ZodObject<{}>, BunFile | Response, \"file\"> {\r\n return {\r\n _input: z.object({}),\r\n _output: null as unknown as BunFile | Response,\r\n _ctx: null as unknown as C,\r\n _type: \"file\",\r\n handler,\r\n middlewares: this.middlewares,\r\n };\r\n }\r\n\r\n // NEW: Video streaming file handler using existing Handler type\r\n fileStream(\r\n handler: Handler<C, {}, Blob | string>\r\n ): Procedure<\r\n C,\r\n z.ZodObject<{}>,\r\n StreamableResponse | Blob | string,\r\n \"fileStream\"\r\n > {\r\n return {\r\n _input: z.object({}),\r\n _output: null as unknown as StreamableResponse | Blob | string,\r\n _ctx: null as unknown as C,\r\n _type: \"fileStream\",\r\n handler,\r\n middlewares: this.middlewares,\r\n };\r\n }\r\n\r\n html(\r\n handler: Handler<C, {}, string>\r\n ): Procedure<C, z.ZodObject<{}>, string, \"html\"> {\r\n return {\r\n _input: z.object({}),\r\n _output: null as unknown as string,\r\n _ctx: null as unknown as C,\r\n _type: \"html\",\r\n handler,\r\n middlewares: this.middlewares,\r\n };\r\n }\r\n}\r\n\r\nclass InputProcedureBuilder<C extends BaseContext, I extends z.ZodType> {\r\n constructor(\r\n private middlewares: ((ctx: any) => Promise<Record<string, any> | void>)[],\r\n private inputSchema: I,\r\n private timeoutMs?: number\r\n ) {}\r\n\r\n /**\r\n * Set a custom timeout for this procedure (in milliseconds).\r\n * Overrides the default router timeout.\r\n */\r\n timeout(ms: number) {\r\n return new InputProcedureBuilder<C, I>(\r\n this.middlewares,\r\n this.inputSchema,\r\n ms\r\n );\r\n }\r\n\r\n query<O>(handler: Handler<C, InferInput<I>, O>): Procedure<C, I, O, \"query\"> {\r\n return {\r\n _input: this.inputSchema,\r\n _output: null as unknown as O,\r\n _ctx: null as unknown as C,\r\n _type: \"query\",\r\n _timeout: this.timeoutMs,\r\n handler,\r\n middlewares: this.middlewares,\r\n };\r\n }\r\n\r\n mutation<O>(\r\n handler: Handler<C, InferInput<I>, O>\r\n ): Procedure<C, I, O, \"mutation\"> {\r\n return {\r\n _input: this.inputSchema,\r\n _output: null as unknown as O,\r\n _ctx: null as unknown as C,\r\n _type: \"mutation\",\r\n _timeout: this.timeoutMs,\r\n handler,\r\n middlewares: this.middlewares,\r\n };\r\n }\r\n\r\n formMutation<O>(\r\n handler: Handler<C, InferInput<I>, O>\r\n ): Procedure<C, I, O, \"formMutation\"> {\r\n return {\r\n _input: this.inputSchema,\r\n _output: null as unknown as O,\r\n _ctx: null as unknown as C,\r\n _type: \"formMutation\",\r\n _timeout: this.timeoutMs,\r\n handler,\r\n middlewares: this.middlewares,\r\n };\r\n }\r\n\r\n subscription<O>(\r\n handler: Handler<C, InferInput<I>, O>\r\n ): Procedure<C, I, O, \"subscription\"> {\r\n return {\r\n _input: this.inputSchema,\r\n _output: null as unknown as O,\r\n _ctx: null as unknown as C,\r\n _type: \"subscription\",\r\n _timeout: this.timeoutMs,\r\n handler,\r\n middlewares: this.middlewares,\r\n };\r\n }\r\n\r\n file(\r\n handler: Handler<C, InferInput<I>, BunFile | Response>\r\n ): Procedure<C, I, BunFile | Response, \"file\"> {\r\n return {\r\n _input: this.inputSchema,\r\n _output: null as unknown as BunFile | Response,\r\n _ctx: null as unknown as C,\r\n _type: \"file\",\r\n _timeout: this.timeoutMs,\r\n handler,\r\n middlewares: this.middlewares,\r\n };\r\n }\r\n\r\n // NEW: Video streaming file handler using existing Handler type\r\n fileStream(\r\n handler: Handler<C, InferInput<I>, StreamableResponse | Blob | string>\r\n ): Procedure<C, I, StreamableResponse | Blob | string, \"fileStream\"> {\r\n return {\r\n _input: this.inputSchema,\r\n _output: null as unknown as StreamableResponse | Blob | string,\r\n _ctx: null as unknown as C,\r\n _type: \"fileStream\",\r\n _timeout: this.timeoutMs,\r\n handler,\r\n middlewares: this.middlewares,\r\n };\r\n }\r\n\r\n html(\r\n handler: Handler<C, {}, string>\r\n ): Procedure<C, z.ZodObject<{}>, string, \"html\"> {\r\n return {\r\n _input: z.object({}),\r\n _output: null as unknown as string,\r\n _ctx: null as unknown as C,\r\n _type: \"html\",\r\n _timeout: this.timeoutMs,\r\n handler,\r\n middlewares: this.middlewares,\r\n };\r\n }\r\n}\r\n\r\nexport function createProcedure<C extends BaseContext>(\r\n _context: (req: Request) => Promise<C>\r\n): ProcedureBuilder<C>;\r\nexport function createProcedure<C extends BaseContext>(): ProcedureBuilder<C>;\r\nexport function createProcedure<C extends BaseContext>(_context?: any): ProcedureBuilder<C> {\r\n return new ProcedureBuilder<C>();\r\n}\r\n",
|
|
6
6
|
"import type { BunFile, Server, ServerWebSocket, BunRequest } from \"bun\";\r\nimport type {\r\n BaseContext,\r\n InferInput,\r\n Procedure,\r\n ProcedureType,\r\n RouterConfig,\r\n Routes,\r\n} from \"../types\";\r\nimport { ZodError, z } from \"zod\";\r\nimport { BRPCError } from \"../errors/BRPCError\";\r\nimport { type RouteMatch, RouteMatcher } from \"./RouteMatcher\";\r\nimport { buildHeaders, getCorsOrigin } from \"@mateosuarezdev/headers-builder\";\r\nimport {\r\n streamMediaInternal,\r\n type StreamableMediaResponse,\r\n} from \"../stream/media\";\r\n\r\ninterface WebSocketData {\r\n ctx: any;\r\n topics: Set<string>;\r\n lastActivity: number;\r\n}\r\n\r\n//====================\r\n// #region Class\r\n//====================\r\nexport class Router<C extends BaseContext> {\r\n private routes: Routes;\r\n private routeMatcher: RouteMatcher;\r\n private contextCreator: (req: Request) => Promise<C>;\r\n private prefix: string;\r\n private globalMiddlewares: ((ctx: C) => Promise<Record<string, any> | void>)[];\r\n private server: Server | null = null;\r\n private wsConfig: RouterConfig<C>[\"websocket\"];\r\n private integrations: RouterConfig<C>[\"integrations\"];\r\n private development = process.env.NODE_ENV !== \"production\";\r\n private debug = false;\r\n private allowedOrigins = [];\r\n private onError?: (\r\n error: Error,\r\n { req, route }: { req: Request; route: string },\r\n ) => void;\r\n\r\n // Connection management fields...\r\n private activeConnections: Set<ServerWebSocket<WebSocketData>> = new Set();\r\n private readonly maxConnections: number = parseInt(\r\n process.env.MAX_WS_CONNECTIONS ?? \"1000\",\r\n );\r\n private readonly connectionTimeout: number = parseInt(\r\n process.env.WS_TIMEOUT ?? \"30000\",\r\n );\r\n private readonly maxRequestSize: number = parseInt(\r\n process.env.MAX_REQUEST_SIZE ?? \"10485760\",\r\n );\r\n private readonly requestTimeout: number = parseInt(\r\n process.env.REQUEST_TIMEOUT ?? \"30000\",\r\n );\r\n\r\n constructor(config: RouterConfig<C>) {\r\n this.contextCreator = config.context;\r\n this.prefix = config.prefix ?? \"\";\r\n this.routes = config.routes;\r\n this.globalMiddlewares = config.globalMiddlewares ?? [];\r\n this.wsConfig = config.websocket ?? {};\r\n this.integrations = config.integrations;\r\n this.debug = !!config.debug && process.env.NODE_ENV === \"development\";\r\n this.onError = config.onError;\r\n\r\n // Initialize the route matcher\r\n this.routeMatcher = new RouteMatcher(config.routes, {\r\n enableCaching: !this.development, // Disable cache in dev for hot reloading\r\n maxCacheSize: parseInt(process.env.ROUTE_CACHE_SIZE ?? \"1000\"),\r\n debug: this.debug,\r\n });\r\n\r\n // Start periodic cleanup\r\n if (!this.development) {\r\n setInterval(() => this.cleanupStaleConnections(), 60000);\r\n }\r\n\r\n if (this.debug) {\r\n console.log(\"Router initialized with route matcher\");\r\n console.log(\"Route cache stats:\", this.routeMatcher.getCacheStats());\r\n }\r\n }\r\n\r\n /**\r\n * Simplified route finding using RouteMatcher\r\n */\r\n private findRoute(pathParts: string[]): RouteMatch | null {\r\n return this.routeMatcher.match(pathParts);\r\n }\r\n\r\n /**\r\n * Parses and validates the request input\r\n */\r\n private async parseInput(\r\n req: Request,\r\n schema: z.ZodType,\r\n routeType: ProcedureType,\r\n ): Promise<any> {\r\n let input: any = {};\r\n const url = new URL(req.url);\r\n const queryParams = Object.fromEntries(url.searchParams);\r\n const method = req.method;\r\n\r\n // Check request size for POST requests\r\n if (method === \"POST\") {\r\n const contentLength = parseInt(req.headers.get(\"content-length\") || \"0\");\r\n if (contentLength > this.maxRequestSize) {\r\n throw new Error(\"Request payload too large\");\r\n }\r\n }\r\n\r\n // Handle different procedure types and HTTP methods\r\n if (\r\n method === \"GET\" &&\r\n [\"query\", \"streamQuery\", \"file\", \"fileStream\", \"html\"].includes(routeType)\r\n ) {\r\n input = queryParams;\r\n } else if (\r\n method === \"POST\" &&\r\n [\"mutation\", \"formMutation\", \"streamMutation\"].includes(routeType)\r\n ) {\r\n const contentType = req.headers.get(\"content-type\");\r\n if (contentType?.includes(\"application/json\")) {\r\n input = await req.json();\r\n } else if (contentType?.includes(\"multipart/form-data\")) {\r\n const formData = await req.formData();\r\n //todo investigate about this deprecation\r\n //@ts-ignore\r\n input = await this.parseFormData(formData);\r\n } else {\r\n throw new Error(\"Unsupported content type\");\r\n }\r\n } else {\r\n throw new Error(\r\n `Unsupported request method ${method} for procedure type ${routeType}`,\r\n );\r\n }\r\n\r\n return schema.parse(input);\r\n }\r\n\r\n /**\r\n * Helper method to parse form data\r\n */\r\n private async parseFormData(\r\n formData: FormData,\r\n ): Promise<Record<string, any>> {\r\n const result: Record<string, any> = {};\r\n const fileGroups: Record<string, any[]> = {};\r\n\r\n formData.forEach(async (value, key) => {\r\n if (value instanceof File) {\r\n // Initialize array for this file key if it doesn't exist\r\n if (!fileGroups[key]) {\r\n fileGroups[key] = [];\r\n }\r\n fileGroups[key].push(value);\r\n } else if (typeof value === \"string\") {\r\n // Try to parse JSON strings\r\n try {\r\n result[key] = JSON.parse(value);\r\n } catch {\r\n // If not JSON, keep as string\r\n result[key] = value;\r\n }\r\n }\r\n });\r\n\r\n // Process file groups - ALWAYS return as array\r\n for (const [key, files] of Object.entries(fileGroups)) {\r\n result[key] = files; // ✅ Always an array, even if single file\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * handleError\r\n * @description global error handling for\r\n * each incoming request\r\n */\r\n private handleError(error: any, req: Request): Response {\r\n // Fire error logging with the REAL error (before any mapping)\r\n if (this.onError) {\r\n try {\r\n this.onError(error, { req, route: req.url });\r\n } catch (logError) {\r\n console.error(\"Error logger failed:\", logError);\r\n }\r\n }\r\n\r\n // Handle Zod validation errors\r\n if (\r\n error?.errors &&\r\n Array.isArray(error.errors) &&\r\n error.name === \"ZodError\"\r\n ) {\r\n return new Response(\r\n JSON.stringify({\r\n error: {\r\n name: \"ValidationError\",\r\n code: \"BAD_REQUEST\",\r\n clientCode: \"VALIDATION_ERROR\",\r\n message: \"Input validation failed\",\r\n data: {\r\n validationErrors: error.errors.map((err: any) => ({\r\n path: err.path.join(\".\"),\r\n message: err.message,\r\n code: err.code,\r\n received: err.received,\r\n })),\r\n },\r\n httpStatus: 400,\r\n },\r\n }),\r\n {\r\n status: 400,\r\n headers: buildHeaders()\r\n .contentType(\"json\")\r\n .cors({ origin: getCorsOrigin(req, this.allowedOrigins) })\r\n .build(),\r\n },\r\n );\r\n }\r\n\r\n // Handle BRPCError\r\n if (error instanceof BRPCError) {\r\n return new Response(JSON.stringify({ error: error.toJSON() }), {\r\n status: error.httpStatus,\r\n headers: buildHeaders()\r\n .contentType(\"json\")\r\n .cors({ origin: getCorsOrigin(req, this.allowedOrigins) })\r\n .build(),\r\n });\r\n }\r\n\r\n // Handle generic Error instances with special messages (backward compatibility)\r\n if (error instanceof Error) {\r\n const status =\r\n error.message === \"Not Found\"\r\n ? 404\r\n : error.message === \"Unauthorized\"\r\n ? 401\r\n : error.message === \"Forbidden\"\r\n ? 403\r\n : error.message === \"Request payload too large\"\r\n ? 413\r\n : error.message === \"Request timeout\"\r\n ? 504 // Use 504 Gateway Timeout instead of 408 to prevent browser auto-retry\r\n : 500;\r\n\r\n const errorCode =\r\n status === 404\r\n ? \"NOT_FOUND\"\r\n : status === 401\r\n ? \"UNAUTHORIZED\"\r\n : status === 403\r\n ? \"FORBIDDEN\"\r\n : status === 413\r\n ? \"PAYLOAD_TOO_LARGE\"\r\n : status === 504\r\n ? \"GATEWAY_TIMEOUT\"\r\n : \"INTERNAL_SERVER_ERROR\";\r\n\r\n // ✅ Safe message for client (never expose internal errors)\r\n const clientMessage =\r\n status < 500\r\n ? error.message // 4xx errors are safe (client's fault)\r\n : \"Internal Server Error\"; // 5xx errors hide details\r\n\r\n return new Response(\r\n JSON.stringify({\r\n error: {\r\n code: errorCode,\r\n message: clientMessage,\r\n },\r\n }),\r\n {\r\n status,\r\n headers: buildHeaders()\r\n .contentType(\"json\")\r\n .cors({ origin: getCorsOrigin(req, this.allowedOrigins) })\r\n .build(),\r\n },\r\n );\r\n }\r\n\r\n // Fallback for unknown errors\r\n return new Response(\r\n JSON.stringify({\r\n error: {\r\n code: \"INTERNAL_SERVER_ERROR\",\r\n message: \"Internal Server Error\", // Generic safe message\r\n },\r\n }),\r\n {\r\n status: 500,\r\n headers: buildHeaders()\r\n .contentType(\"json\")\r\n .cors({ origin: getCorsOrigin(req, this.allowedOrigins) })\r\n .build(),\r\n },\r\n );\r\n }\r\n\r\n /**\r\n * handles the default cache control headers for file routes\r\n */\r\n private handleFileCacheControl(contentType: string) {\r\n let cacheControl: string;\r\n if (contentType?.includes(\"text/html\")) {\r\n cacheControl = \"public, max-age=0, must-revalidate\";\r\n } else if (\r\n contentType?.includes(\"text/css\") ||\r\n contentType?.includes(\"text/javascript\") ||\r\n contentType?.includes(\"application/javascript\")\r\n ) {\r\n cacheControl = \"public, max-age=31536000, immutable\";\r\n } else {\r\n cacheControl = \"public, max-age=86400, stale-while-revalidate=604800\";\r\n }\r\n return cacheControl;\r\n }\r\n\r\n /**\r\n * Handles the behavior of each request\r\n */\r\n private async handleRequest(\r\n req: Request,\r\n server?: Server,\r\n ): Promise<Response> {\r\n try {\r\n // Handle OPTIONS preflight requests without timeout\r\n if (req.method === \"OPTIONS\") {\r\n return new Response(null, {\r\n status: 204,\r\n headers: buildHeaders()\r\n .cors({ origin: getCorsOrigin(req, this.allowedOrigins) })\r\n .build(),\r\n });\r\n }\r\n\r\n const url = new URL(req.url);\r\n let path = url.pathname;\r\n path = path.startsWith(this.prefix)\r\n ? path.slice(this.prefix.length)\r\n : path;\r\n path = path.startsWith(\"/\") ? path : \"/\" + path;\r\n\r\n // Handle WebSocket upgrade without timeout\r\n if (path === \"/ws\" && server) {\r\n if (this.debug) {\r\n console.log(\"🔌 WebSocket upgrade requested\");\r\n }\r\n return this.handleWebSocketUpgrade(req, server);\r\n }\r\n\r\n // Handle root path specially, not returning two parts [\"\",\"\"]\r\n const pathParts = path === \"/\" ? [] : path.split(\"/\").filter(Boolean);\r\n\r\n // Use the optimized route matcher\r\n const routeResult = this.findRoute(pathParts);\r\n\r\n if (!routeResult) {\r\n return new Response(\"Not Found\", {\r\n status: 404,\r\n headers: buildHeaders()\r\n .contentType(\"text\")\r\n .cors({ origin: getCorsOrigin(req, this.allowedOrigins) })\r\n .build(),\r\n });\r\n }\r\n\r\n const { route } = routeResult;\r\n\r\n // Determine timeout: use procedure-specific timeout or fall back to default\r\n const timeout = route._timeout ?? this.requestTimeout;\r\n\r\n const timeoutPromise = new Promise<Response>((_, reject) => {\r\n setTimeout(() => reject(new Error(\"Request timeout\")), timeout);\r\n });\r\n\r\n return await Promise.race([\r\n this._handleRequest(req, server, routeResult),\r\n timeoutPromise,\r\n ]);\r\n } catch (error) {\r\n return this.handleError(error, req);\r\n }\r\n }\r\n\r\n private async _handleRequest(\r\n req: Request,\r\n server?: Server,\r\n routeResult?: RouteMatch | null,\r\n ): Promise<Response> {\r\n try {\r\n // routeResult is now passed in from handleRequest\r\n if (!routeResult) {\r\n return new Response(\"Not Found\", {\r\n status: 404,\r\n headers: buildHeaders()\r\n .contentType(\"text\")\r\n .cors({ origin: getCorsOrigin(req, this.allowedOrigins) })\r\n .build(),\r\n });\r\n }\r\n\r\n const { params, route } = routeResult;\r\n\r\n if (!route.handler) {\r\n return new Response(\"Handler not implemented\", {\r\n status: 501,\r\n headers: buildHeaders()\r\n .contentType(\"text\")\r\n .cors({ origin: getCorsOrigin(req, this.allowedOrigins) })\r\n .build(),\r\n });\r\n }\r\n\r\n // Simple headers storage\r\n const customHeaders: Headers = new Headers();\r\n\r\n // Create context with all the properties from BaseContext\r\n const ctx = await this.contextCreator(req);\r\n Object.assign(ctx, {\r\n req,\r\n params,\r\n publishToProcedure: async <\r\n P extends Procedure<any, any, any, \"subscription\">,\r\n >(\r\n procedure: P,\r\n input: InferInput<P[\"_input\"]>,\r\n params: Record<string, string>,\r\n ) => {\r\n await this.publishToProcedure(procedure, input, ctx, params);\r\n },\r\n headers: customHeaders,\r\n });\r\n\r\n // Run global middlewares\r\n for (const middleware of this.globalMiddlewares) {\r\n const ext = await middleware(ctx);\r\n if (ext !== null && ext !== undefined && typeof ext === \"object\") {\r\n Object.assign(ctx, ext);\r\n }\r\n }\r\n\r\n // Run procedure-specific middlewares\r\n for (const middleware of route.middlewares) {\r\n const ext = await middleware(ctx);\r\n if (ext !== null && ext !== undefined && typeof ext === \"object\") {\r\n Object.assign(ctx, ext);\r\n }\r\n }\r\n\r\n // Parse input based on procedure type\r\n const input = await this.parseInput(req, route._input, route._type);\r\n const result = await route.handler({ ctx, input });\r\n\r\n const corsHeaders = buildHeaders()\r\n .cors({ origin: getCorsOrigin(req, this.allowedOrigins) })\r\n .build();\r\n\r\n Object.keys(corsHeaders).forEach((key) => {\r\n customHeaders.set(key, corsHeaders[key]);\r\n });\r\n\r\n // Handle different response types based on procedure type\r\n return await this.handleProcedureResponse(\r\n route._type,\r\n result,\r\n customHeaders,\r\n );\r\n } catch (error) {\r\n return this.handleError(error, req);\r\n }\r\n }\r\n\r\n /**\r\n * @description Entry point for testing router behavior without starting a server.\r\n * This method processes a request through the full routing pipeline including\r\n * middlewares, validation, and handlers.\r\n *\r\n * @example\r\n * ```typescript\r\n * const request = new Request(\"http://localhost/api/users\", {\r\n * method: \"POST\",\r\n * body: JSON.stringify({ name: \"John\" })\r\n * });\r\n * const response = await router.testRequest(request);\r\n * expect(response.status).toBe(200);\r\n * ```\r\n */\r\n public async testRequest(req: Request): Promise<Response> {\r\n return this.handleRequest(req);\r\n }\r\n\r\n /**\r\n * Handle responses based on procedure type\r\n */\r\n private async handleProcedureResponse(\r\n procedureType: ProcedureType,\r\n result: any,\r\n customHeaders: Headers,\r\n // corsHeaders: Record<string, string>,\r\n ): Promise<Response> {\r\n switch (procedureType) {\r\n case \"file\":\r\n if (result instanceof Response) {\r\n return result;\r\n }\r\n const contentType = (result as BunFile).type;\r\n customHeaders.append(\"Content-Type\", contentType);\r\n customHeaders.append(\r\n \"Cache-Control\",\r\n this.development\r\n ? \"public, max-age=0, must-revalidate\"\r\n : this.handleFileCacheControl(contentType),\r\n );\r\n return new Response(result, {\r\n headers: customHeaders,\r\n });\r\n\r\n case \"fileStream\":\r\n if (\r\n typeof result === \"object\" &&\r\n result !== null &&\r\n \"type\" in result &&\r\n result.type === \"stream\"\r\n ) {\r\n const mediaStreamResult = result as StreamableMediaResponse;\r\n return await streamMediaInternal(\r\n result.file,\r\n result.request,\r\n this.allowedOrigins,\r\n mediaStreamResult.options,\r\n );\r\n }\r\n // Fallback to regular file response\r\n const streamContentType = (result as Blob).type;\r\n customHeaders.append(\"Content-Type\", streamContentType);\r\n customHeaders.append(\r\n \"Cache-Control\",\r\n this.development\r\n ? \"public, max-age=0, must-revalidate\"\r\n : this.handleFileCacheControl(streamContentType),\r\n );\r\n return new Response(result, {\r\n headers: customHeaders,\r\n });\r\n\r\n case \"html\":\r\n // Handle HTML rendering\r\n if (typeof result === \"string\") {\r\n customHeaders.append(\"Content-Type\", \"text/html\");\r\n return new Response(result, {\r\n headers: customHeaders,\r\n });\r\n }\r\n break;\r\n\r\n case \"query\":\r\n case \"mutation\":\r\n case \"formMutation\":\r\n case \"streamQuery\":\r\n case \"streamMutation\":\r\n case \"subscription\":\r\n default:\r\n // Standard JSON response\r\n customHeaders.append(\"Content-Type\", \"application/json\");\r\n return new Response(JSON.stringify({ data: result }), {\r\n headers: customHeaders,\r\n });\r\n }\r\n\r\n // Fallback\r\n customHeaders.append(\"Content-Type\", \"application/json\");\r\n return new Response(JSON.stringify({ data: result }), {\r\n headers: customHeaders,\r\n });\r\n }\r\n\r\n //====================\r\n // #region Websockets\r\n //====================\r\n private cleanupStaleConnections() {\r\n const now = Date.now();\r\n for (const ws of this.activeConnections) {\r\n if (now - ws.data.lastActivity > this.connectionTimeout) {\r\n ws.close();\r\n this.activeConnections.delete(ws);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * handleWebSocketUpgrade\r\n * @description upgrades the incoming request to\r\n * a websocket connection\r\n */\r\n private async handleWebSocketUpgrade(\r\n req: Request,\r\n server: Server,\r\n ): Promise<Response> {\r\n if (this.activeConnections.size >= this.maxConnections) {\r\n return new Response(\"Too many connections\", { status: 503 });\r\n }\r\n\r\n const ctx = await this.contextCreator(req);\r\n Object.assign(ctx, { req });\r\n for (const middleware of this.globalMiddlewares) {\r\n const ext = await middleware(ctx);\r\n if (ext !== null && ext !== undefined && typeof ext === \"object\") {\r\n Object.assign(ctx, ext);\r\n }\r\n }\r\n\r\n const success = server.upgrade<WebSocketData>(req, {\r\n data: {\r\n ctx,\r\n topics: new Set<string>(),\r\n lastActivity: Date.now(),\r\n },\r\n });\r\n\r\n if (success) {\r\n return new Response(null, { status: 101 }); // Switching Protocols\r\n }\r\n\r\n return new Response(\"WebSocket upgrade failed\", { status: 500 });\r\n }\r\n\r\n /**\r\n * Handles WebSocket authentication\r\n */\r\n private async handleAuthenticate(\r\n ws: ServerWebSocket<WebSocketData>,\r\n token: string,\r\n _ctx: C,\r\n ) {\r\n try {\r\n // Extract token from \"Bearer xxx\" format if needed\r\n const finalToken = token.startsWith(\"Bearer \")\r\n ? token.substring(7)\r\n : token;\r\n\r\n // Store the token in the WebSocket context\r\n ws.data.ctx.authToken = finalToken;\r\n\r\n // Additionally, we can verify the token and update the session\r\n // For example, with Supabase:\r\n // const { data, error } = await supabase.auth.getUser(finalToken);\r\n // if (error) throw new Error(error.message);\r\n // ws.data.ctx.session = { user: data.user };\r\n\r\n // Send success response\r\n ws.send(\r\n JSON.stringify({\r\n type: \"auth_success\",\r\n message: \"Authentication successful\",\r\n }),\r\n );\r\n\r\n if (this.debug) {\r\n console.log(\"[BRPC]\", \"WebSocket authenticated successfully\");\r\n }\r\n } catch (error) {\r\n ws.send(\r\n JSON.stringify({\r\n type: \"auth_error\",\r\n error:\r\n error instanceof Error ? error.message : \"Authentication failed\",\r\n }),\r\n );\r\n\r\n if (this.debug) {\r\n console.error(\"WebSocket authentication error:\", error);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * handles the ws client topic subscription\r\n */\r\n private async handleSubscribe(\r\n ws: ServerWebSocket<WebSocketData>,\r\n topic: string,\r\n _ctx: C,\r\n ) {\r\n // Find route first to validate subscription\r\n const routeResult = this.findRoute(topic.split(\"/\").filter(Boolean));\r\n\r\n if (!routeResult || routeResult.route._type !== \"subscription\") {\r\n throw new Error(\"Invalid subscription route\");\r\n }\r\n\r\n ws.subscribe(topic);\r\n ws.data.topics.add(topic);\r\n }\r\n\r\n /**\r\n * handles the ws client topic unsubscription\r\n */\r\n private async handleUnsubscribe(\r\n ws: ServerWebSocket<WebSocketData>,\r\n topic: string,\r\n _ctx: C,\r\n ) {\r\n const routeResult = this.findRoute(topic.split(\"/\").filter(Boolean));\r\n\r\n if (!routeResult || routeResult.route._type !== \"subscription\") {\r\n throw new Error(\"Invalid subscription route\");\r\n }\r\n\r\n ws.unsubscribe(topic);\r\n ws.data.topics.delete(topic);\r\n }\r\n\r\n /**\r\n * handles the message publication of a certain ws client\r\n */\r\n private async handlePublish(\r\n _ws: ServerWebSocket<WebSocketData>,\r\n topic: string,\r\n message: any,\r\n ctx: C,\r\n ) {\r\n const routeResult = this.findRoute(topic.split(\"/\").filter(Boolean));\r\n\r\n if (!routeResult) {\r\n throw new Error(\"Subscription not found\");\r\n }\r\n\r\n const { params, route } = routeResult;\r\n\r\n if (route._type !== \"subscription\" || !route.handler) {\r\n throw new Error(\"Invalid subscription route\");\r\n }\r\n\r\n Object.assign(ctx, { params });\r\n\r\n // Only validate if the procedure has defined input\r\n const validatedMessage = route._input.fields\r\n ? route._input.parse(message)\r\n : message;\r\n\r\n const publishMessage = await route.handler({\r\n ctx,\r\n input: validatedMessage,\r\n });\r\n\r\n const converted = {\r\n topic: topic,\r\n data: publishMessage,\r\n type: \"publish\",\r\n };\r\n\r\n if (this.debug) {\r\n console.log(`Server will publish to ${topic}`, converted);\r\n }\r\n\r\n // this.server!.publish(topic, JSON.stringify(publishMessage));\r\n this.server!.publish(topic, JSON.stringify(converted));\r\n }\r\n\r\n private async publishToProcedure<\r\n P extends Procedure<any, any, any, \"subscription\">,\r\n >(\r\n procedure: P,\r\n input: InferInput<P[\"_input\"]>,\r\n ctx: C,\r\n params: Record<string, string>,\r\n ) {\r\n if (procedure._type !== \"subscription\" || !procedure.handler) {\r\n throw new Error(\"Can only publish to subscription procedures\");\r\n }\r\n\r\n const routePath = this.findRoutePath(this.routes, procedure);\r\n\r\n if (!routePath) {\r\n throw new Error(\"Subscription route not found\");\r\n }\r\n\r\n // Replace params in the path\r\n const finalPath = routePath\r\n .split(\"/\")\r\n .map((part) => {\r\n if (part.startsWith(\":\")) {\r\n const paramName = part.slice(1);\r\n const paramValue = params[paramName];\r\n if (!paramValue) {\r\n throw new Error(`Missing parameter: ${paramName}`);\r\n }\r\n return paramValue;\r\n }\r\n return part;\r\n })\r\n .join(\"/\");\r\n\r\n const result = await procedure.handler({\r\n ctx: { ...ctx, params },\r\n input,\r\n });\r\n\r\n const converted = { topic: finalPath, data: result, type: \"publish\" };\r\n\r\n if (this.debug) {\r\n console.log(`Server will publish to ${finalPath}`, converted);\r\n }\r\n\r\n // this.server?.publish(finalPath, JSON.stringify(result));\r\n this.server?.publish(finalPath, JSON.stringify(converted));\r\n return result;\r\n }\r\n\r\n async publish<P extends Procedure<any, any, any, \"subscription\">>(\r\n procedure: P,\r\n input: InferInput<P[\"_input\"]>,\r\n params?: Record<string, string>,\r\n ) {\r\n if (procedure._type !== \"subscription\" || !procedure.handler) {\r\n throw new Error(\"Can only publish to subscription procedures\");\r\n }\r\n\r\n const routePath = this.findRoutePath(this.routes, procedure);\r\n\r\n if (!routePath) {\r\n throw new Error(\"Subscription route not found\");\r\n }\r\n\r\n // Replace params in the path\r\n const finalPath = routePath\r\n .split(\"/\")\r\n .map((part) => {\r\n if (part.startsWith(\":\")) {\r\n const paramName = part.slice(1);\r\n const paramValue = params ? params[paramName] : null;\r\n if (!paramValue) {\r\n throw new Error(`Missing parameter: ${paramName}`);\r\n }\r\n return paramValue;\r\n }\r\n return part;\r\n })\r\n .join(\"/\");\r\n\r\n const result = await procedure.handler({\r\n ctx: { params },\r\n input,\r\n });\r\n\r\n const converted = { topic: finalPath, data: result, type: \"publish\" };\r\n\r\n if (this.debug) {\r\n console.log(`Server will publish to ${finalPath}`, converted);\r\n }\r\n\r\n // this.server?.publish(finalPath, JSON.stringify(result));\r\n this.server?.publish(finalPath, JSON.stringify(converted));\r\n return result;\r\n }\r\n\r\n /**\r\n * publish\r\n * @description publish a message to a topic from\r\n * the server itself\r\n */\r\n // private publish(topic: string, message: string | Uint8Array) {\r\n // if (this.server) {\r\n // this.server.publish(topic, message);\r\n // } else {\r\n // //?debug\r\n // //console.warn(\"Server not initialized. Cannot publish message.\");\r\n // }\r\n // }\r\n public freePublish<T>(topic: string, message: T) {\r\n const converted = { topic: topic, data: message, type: \"publish\" };\r\n this.server?.publish(topic, JSON.stringify(converted));\r\n }\r\n //====================\r\n // #endregion\r\n //====================\r\n\r\n //====================\r\n // #region Helpers\r\n //====================\r\n /**\r\n * findRoutePath\r\n * @description finds the full path to a procedure in the routes tree\r\n */\r\n private findRoutePath(\r\n routes: Routes,\r\n targetProcedure: Procedure<any, any, any, any>,\r\n prefix: string = \"\",\r\n ): string | null {\r\n for (const [key, value] of Object.entries(routes)) {\r\n const currentPath = prefix ? `${prefix}/${key}` : key;\r\n\r\n if (value === targetProcedure) {\r\n return currentPath;\r\n }\r\n\r\n if (value && typeof value === \"object\" && !(\"_type\" in value)) {\r\n const found = this.findRoutePath(\r\n value as Routes,\r\n targetProcedure,\r\n currentPath,\r\n );\r\n if (found) return found;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n private getIntegrationRoutes() {\r\n if (!this.integrations) return undefined;\r\n\r\n let routes: any = {}; // Initialize the routes object\r\n\r\n if (this.integrations.betterAuth) {\r\n const handler = this.integrations.betterAuth.handler;\r\n if (!handler) {\r\n throw new Error(\"Please provide a handler for betterAuth integration\");\r\n }\r\n routes[\"/api/auth/*\"] = async (req: BunRequest<\"auth\">) => {\r\n return await handler(req);\r\n };\r\n }\r\n\r\n if (this.integrations.rawRoutes) {\r\n Object.keys(this.integrations.rawRoutes).forEach((val) => {\r\n routes[val] = this.integrations!.rawRoutes![val];\r\n });\r\n }\r\n\r\n return Object.keys(routes).length > 0 ? routes : undefined;\r\n }\r\n\r\n /**\r\n * New utility methods for route management\r\n */\r\n public getRouteStats() {\r\n return {\r\n cache: this.routeMatcher.getCacheStats(),\r\n suggestions: this.routeMatcher.getOptimizationSuggestions(),\r\n };\r\n }\r\n\r\n public clearRouteCache() {\r\n this.routeMatcher.clearCache();\r\n if (this.debug) {\r\n console.log(\"[ROUTEMATCHER] Route cache cleared\");\r\n }\r\n }\r\n\r\n public benchmarkRoutes(\r\n testPaths: string[] = [\"/users/123\", \"/posts/456/comments\"],\r\n iterations = 1000,\r\n ) {\r\n if (this.debug) {\r\n const results = this.routeMatcher.benchmark(testPaths, iterations);\r\n console.log(\"[ROUTEMATCHER]\", \"Route matching benchmark:\", results);\r\n return results;\r\n }\r\n }\r\n\r\n /**\r\n * Hot reload support for development\r\n */\r\n public updateRoutes(newRoutes: Routes) {\r\n if (this.development) {\r\n this.routes = newRoutes;\r\n this.routeMatcher = new RouteMatcher(newRoutes, {\r\n enableCaching: false, // No caching in dev\r\n debug: this.debug,\r\n });\r\n console.log(\"[HMR]\", \"Server Routes updated\");\r\n } else {\r\n console.warn(\"Route updates are only allowed in development mode\");\r\n }\r\n }\r\n //====================\r\n // #endregion\r\n //====================\r\n\r\n //====================\r\n // #region Server\r\n //====================\r\n /**\r\n * Listen\r\n * @description starts up the Bun http server\r\n */\r\n listen(port: number, callback?: () => void) {\r\n this.server = Bun.serve({\r\n port,\r\n routes: this.getIntegrationRoutes(),\r\n fetch: (req, server) => this.handleRequest(req, server),\r\n websocket: {\r\n open: (ws: ServerWebSocket<WebSocketData>) => {\r\n this.activeConnections.add(ws);\r\n if (this.wsConfig?.onOpen) {\r\n this.wsConfig.onOpen(ws, ws.data.ctx);\r\n }\r\n\r\n if (this.debug) {\r\n console.log(\"[BRPC]\", \"WebSocket connection opened\", {\r\n connections: this.activeConnections.size,\r\n });\r\n }\r\n },\r\n message: async (ws: ServerWebSocket<WebSocketData>, message: any) => {\r\n try {\r\n ws.data.lastActivity = Date.now();\r\n const { type, topic, token, data } = JSON.parse(message as string);\r\n // console.log(type, token);\r\n const ctx = ws.data.ctx;\r\n\r\n if (this.debug) {\r\n console.log(\"[BRPC]\", \"WebSocket message received:\", {\r\n type,\r\n topic,\r\n });\r\n }\r\n\r\n switch (type) {\r\n case \"authenticate\":\r\n await this.handleAuthenticate(ws, token, ctx);\r\n break;\r\n case \"subscribe\":\r\n await this.handleSubscribe(ws, topic, ctx);\r\n break;\r\n case \"unsubscribe\":\r\n await this.handleUnsubscribe(ws, topic, ctx);\r\n break;\r\n case \"publish\":\r\n await this.handlePublish(ws, topic, data, ctx);\r\n break;\r\n default:\r\n ws.send(JSON.stringify({ error: \"Unknown message type\" }));\r\n if (this.debug) {\r\n console.error(\"Unknown WebSocket message type:\", type);\r\n }\r\n }\r\n } catch (error) {\r\n if (this.debug) {\r\n console.error(\"[BRPC]\", \"WebSocket message error:\", error);\r\n }\r\n\r\n if (error instanceof ZodError) {\r\n ws.send(JSON.stringify({ error: \"Invalid message format\" }));\r\n } else if (error instanceof Error) {\r\n ws.send(JSON.stringify({ error: error.message }));\r\n }\r\n }\r\n },\r\n close: (\r\n ws: ServerWebSocket<WebSocketData>,\r\n code: number,\r\n reason: string,\r\n ) => {\r\n this.activeConnections.delete(ws);\r\n ws.data.topics.forEach((topic) => {\r\n ws.unsubscribe(topic);\r\n });\r\n\r\n if (this.debug) {\r\n console.log(\"[BRPC]\", \"WebSocket connection closed\", {\r\n code,\r\n reason,\r\n remainingConnections: this.activeConnections.size,\r\n });\r\n }\r\n\r\n if (this.wsConfig?.onClose) {\r\n this.wsConfig.onClose(ws, code, reason, ws.data.ctx);\r\n }\r\n },\r\n },\r\n });\r\n\r\n if (callback) callback();\r\n }\r\n //====================\r\n // #endregion\r\n //====================\r\n}\r\n//====================\r\n// #endregion Class\r\n//====================\r\n\r\n//====================\r\n// #region Exports\r\n//====================\r\n/**\r\n * createRouter\r\n * @description helper function to create a\r\n * Router instance\r\n */\r\nexport function createRouter<C extends BaseContext>(config: RouterConfig<C>) {\r\n return new Router(config);\r\n}\r\n\r\nexport type CreateRouter = ReturnType<typeof createRouter>;\r\n//====================\r\n// #endregion\r\n//====================\r\n",
|
|
@@ -12,9 +12,10 @@
|
|
|
12
12
|
"import { z } from \"zod\";\r\n\r\n// Common MIME type groups\r\nconst MIME_TYPES = {\r\n image: [\r\n \"image/jpeg\",\r\n \"image/png\",\r\n \"image/gif\",\r\n \"image/webp\",\r\n \"image/svg+xml\",\r\n ],\r\n video: [\"video/mp4\", \"video/webm\", \"video/ogg\"],\r\n audio: [\"audio/mpeg\", \"audio/ogg\", \"audio/wav\"],\r\n document: [\r\n \"application/pdf\",\r\n \"application/msword\",\r\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\r\n \"application/vnd.ms-excel\",\r\n \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\r\n ],\r\n} as const;\r\n\r\ntype MimeTypeGroup = keyof typeof MIME_TYPES;\r\ntype MimeTypeValues<T extends MimeTypeGroup> = (typeof MIME_TYPES)[T][number];\r\n\r\n// Type for accepting either specific types or wildcard per group\r\ntype MimeTypeConfig = {\r\n [K in MimeTypeGroup]?: \"*\" | MimeTypeValues<K>[];\r\n};\r\n\r\n/** Options for creating a file validation schema */\r\ntype FileSchemaOptions = {\r\n /** Accepted MIME types configuration. Use \"*\" for all types in a category or specify an array of types\r\n * @example\r\n * {\r\n * image: \"*\", // All image types\r\n * audio: [\"audio/mpeg\"], // Only MP3s\r\n * document: [\"application/pdf\", \"application/msword\"] // PDFs and DOCs\r\n * }\r\n */\r\n acceptedTypes?: MimeTypeConfig;\r\n /** Maximum file size in megabytes */\r\n maxSize?: number;\r\n /** Minimum file size in megabytes */\r\n minSize?: number;\r\n /** Whether the file field is required */\r\n // required?: boolean;\r\n /** Custom error messages */\r\n messages?: {\r\n /** Custom message for type validation failure */\r\n type?: string;\r\n /** Custom message for maximum size validation failure */\r\n maxSize?: string;\r\n /** Custom message for minimum size validation failure */\r\n minSize?: string;\r\n /** Custom message for required field validation failure */\r\n required?: string;\r\n };\r\n};\r\n\r\nconst convertToBytes = (\r\n size: number,\r\n unit: \"MB\" | \"KB\" | \"B\" = \"MB\"\r\n): number => {\r\n switch (unit) {\r\n case \"MB\":\r\n return size * 1024 * 1024;\r\n case \"KB\":\r\n return size * 1024;\r\n case \"B\":\r\n return size;\r\n }\r\n};\r\n\r\n/**\r\n * Creates a Zod schema for file validation with support for MIME types and size constraints\r\n * you can extend it as any other zod schema after calling it\r\n * @param {Object} options - The configuration options for the file schema\r\n * @returns Zod schema for file validation\r\n */\r\nexport const createFileSchema = ({\r\n acceptedTypes,\r\n maxSize = Infinity,\r\n minSize,\r\n // required = true,\r\n messages = {},\r\n}: FileSchemaOptions = {}) => {\r\n // Convert MB to bytes\r\n const maxBytes = maxSize ? convertToBytes(maxSize) : Infinity;\r\n const minBytes = minSize ? convertToBytes(minSize) : 0;\r\n\r\n // Process accepted types\r\n const validMimeTypes = acceptedTypes\r\n ? Object.entries(acceptedTypes).flatMap(([category, types]) => {\r\n const cat = category as MimeTypeGroup;\r\n\r\n // Handle wildcard\r\n if (types === \"*\") {\r\n return MIME_TYPES[cat];\r\n }\r\n\r\n // Handle array of specific types\r\n if (Array.isArray(types)) {\r\n return types;\r\n }\r\n\r\n return [];\r\n })\r\n : undefined;\r\n\r\n // Base schema\r\n let schema = z.instanceof(File, {\r\n message: messages.required ?? \"File is required\",\r\n });\r\n\r\n // Add size refinement\r\n schema = schema\r\n .refine(\r\n (file) => file.size <= maxBytes,\r\n messages.maxSize ?? `File size must be less than ${maxSize}MB`\r\n )\r\n .refine(\r\n (file) => file.size >= minBytes,\r\n messages.minSize ?? `File size must be at least ${minSize}MB`\r\n );\r\n\r\n // Add type refinement if acceptedTypes is provided\r\n if (validMimeTypes?.length) {\r\n schema = schema.refine(\r\n (file) =>\r\n validMimeTypes.includes(file.type as MimeTypeValues<MimeTypeGroup>),\r\n messages.type ?? `File must be of type: ${validMimeTypes.join(\", \")}`\r\n );\r\n }\r\n\r\n return schema;\r\n};\r\n",
|
|
13
13
|
"import type { BaseContext } from \"../..\";\r\n\r\n// blockPaths.ts\r\nexport type PathBlockerConfig = {\r\n paths: string[]; // Array of paths/patterns to block\r\n};\r\n\r\nexport const createPathBlocker = (config: PathBlockerConfig) => {\r\n const patterns = config.paths.map((path) => new RegExp(path));\r\n const message = \"Not Found\";\r\n\r\n return async <C extends BaseContext>(ctx: C): Promise<void> => {\r\n const url = new URL(ctx.req.url);\r\n const path = url.pathname;\r\n\r\n // Check if the path matches any blocked pattern\r\n if (patterns.some((pattern) => pattern.test(path))) {\r\n throw new Error(message);\r\n }\r\n };\r\n};\r\n",
|
|
14
14
|
"import type { BaseContext } from \"../../types\";\r\n\r\nexport interface RateLimitConfig {\r\n windowMs: number;\r\n maxRequests: number;\r\n maxEntries?: number;\r\n cleanupIntervalMs?: number;\r\n message?: string;\r\n statusCode?: number;\r\n headerPrefix?: string;\r\n}\r\n\r\ninterface RequestWindow {\r\n count: number;\r\n startTime: number;\r\n lastAccessed: number;\r\n}\r\n\r\ninterface RateLimitResult {\r\n isLimited: boolean;\r\n remaining: number;\r\n resetTime: number;\r\n}\r\n\r\nclass RateLimiter {\r\n private requests: Map<string, RequestWindow> = new Map();\r\n private lastCleanupTime: number = Date.now();\r\n private readonly alertThreshold: number;\r\n private config: Required<RateLimitConfig>;\r\n\r\n constructor(config: RateLimitConfig) {\r\n this.config = {\r\n windowMs: config.windowMs,\r\n maxRequests: config.maxRequests,\r\n maxEntries: config.maxEntries ?? 10000,\r\n cleanupIntervalMs: config.cleanupIntervalMs ?? 60000,\r\n message: config.message ?? \"Too Many Requests\",\r\n statusCode: config.statusCode ?? 429,\r\n headerPrefix: config.headerPrefix ?? \"X-RateLimit\",\r\n };\r\n this.alertThreshold = this.config.maxEntries * 0.8;\r\n\r\n // Start periodic cleanup\r\n if (process.env.NODE_ENV !== \"development\") {\r\n setInterval(() => this.cleanup(), this.config.cleanupIntervalMs);\r\n }\r\n }\r\n\r\n private cleanup(): number {\r\n const now = Date.now();\r\n let deletedCount = 0;\r\n\r\n for (const [ip, window] of this.requests.entries()) {\r\n const windowExpired = now - window.startTime > this.config.windowMs;\r\n const inactive = now - window.lastAccessed > this.config.windowMs * 2;\r\n\r\n if (windowExpired || inactive) {\r\n this.requests.delete(ip);\r\n deletedCount++;\r\n }\r\n }\r\n\r\n this.lastCleanupTime = now;\r\n return deletedCount;\r\n }\r\n\r\n private handleMaxEntries(ip: string): boolean {\r\n const currentSize = this.requests.size;\r\n\r\n // Regular cleanup if interval passed\r\n if (Date.now() - this.lastCleanupTime > this.config.cleanupIntervalMs) {\r\n this.cleanup();\r\n }\r\n\r\n // Alert if nearing capacity\r\n if (currentSize >= this.alertThreshold) {\r\n console.warn(\r\n `Rate limiter at ${Math.round(\r\n (currentSize / this.config.maxEntries) * 100,\r\n )}% capacity`,\r\n );\r\n }\r\n\r\n // If IP is already tracked, allow it\r\n if (this.requests.has(ip)) {\r\n return true;\r\n }\r\n\r\n // Reject if at max capacity\r\n return currentSize < this.config.maxEntries;\r\n }\r\n\r\n check(ip: string): RateLimitResult {\r\n // Check system capacity first\r\n if (!this.handleMaxEntries(ip)) {\r\n return {\r\n isLimited: true,\r\n remaining: 0,\r\n resetTime: Date.now() + this.config.windowMs,\r\n };\r\n }\r\n\r\n const now = Date.now();\r\n const window = this.requests.get(ip);\r\n\r\n // Create new window if none exists or current one expired\r\n if (!window || now - window.startTime >= this.config.windowMs) {\r\n this.requests.set(ip, {\r\n count: 1,\r\n startTime: now,\r\n lastAccessed: now,\r\n });\r\n\r\n return {\r\n isLimited: false,\r\n remaining: this.config.maxRequests - 1,\r\n resetTime: now + this.config.windowMs,\r\n };\r\n }\r\n\r\n // Update existing window\r\n window.lastAccessed = now;\r\n const isLimited = window.count >= this.config.maxRequests;\r\n\r\n if (!isLimited) {\r\n window.count++;\r\n }\r\n\r\n return {\r\n isLimited,\r\n remaining: Math.max(0, this.config.maxRequests - window.count),\r\n resetTime: window.startTime + this.config.windowMs,\r\n };\r\n }\r\n\r\n getConfig() {\r\n return this.config;\r\n }\r\n}\r\n\r\n// Middleware factory\r\nexport const createRateLimiter = (config: RateLimitConfig) => {\r\n const limiter = new RateLimiter(config);\r\n\r\n return async <C extends BaseContext>(ctx: C): Promise<void> => {\r\n // Skip rate limiting for video range requests\r\n if (ctx.req.headers.get(\"range\")) {\r\n return; // Don't apply rate limiting to video chunks\r\n }\r\n\r\n const ip =\r\n ctx.req.headers.get(\"x-forwarded-for\")?.split(\",\")[0] || // Get first IP if multiple\r\n ctx.req.headers.get(\"x-real-ip\") ||\r\n \"unknown\";\r\n\r\n const { isLimited, remaining, resetTime } = limiter.check(ip);\r\n\r\n const { headerPrefix } = limiter.getConfig();\r\n ctx.headers.set(`${headerPrefix}-Remaining`, remaining.toString());\r\n ctx.headers.set(`${headerPrefix}-Reset`, resetTime.toString());\r\n\r\n if (isLimited) {\r\n ctx.headers.set(`${headerPrefix}-Exceeded`, \"true\");\r\n throw new Error(limiter.getConfig().message);\r\n }\r\n };\r\n};\r\n\r\n//example usage with more options\r\n// const rateLimiter = createRateLimiter({\r\n// windowMs: 60 * 1000, // 1 minute\r\n// maxRequests: 100, // 100 requests per minute\r\n// maxEntries: 10000, // Maximum number of IPs to track\r\n// cleanupIntervalMs: 30000, // Cleanup every 30 seconds\r\n// message: 'Rate limit exceeded. Please try again later.',\r\n// headerPrefix: 'X-RateLimit'\r\n// });\r\n\r\n// const router = createRouter({\r\n// context: createContext,\r\n// routes: appRoutes,\r\n// globalMiddlewares: [rateLimiter],\r\n// // ... other config\r\n// });\r\n",
|
|
15
|
-
"import type { BaseContext } from \"../types\";\r\n\r\n/**\r\n * Helper to define a reusable, typed middleware outside of a procedure chain.\r\n *\r\n * @example\r\n * ```ts\r\n * // Infer context type from your context creator\r\n * const authMiddleware = createMiddleware(context, async (ctx) => {\r\n * const session = await getSession(ctx.req);\r\n * if (!session) throw new BRPCError({ code: \"UNAUTHORIZED\" });\r\n * return { session };\r\n * });\r\n *\r\n * // Or with an explicit generic (no context reference needed)\r\n * const authMiddleware = createMiddleware<MyContext>(async (ctx) => {\r\n * return { session: await getSession(ctx.req) };\r\n * });\r\n *\r\n * createProcedure(context)\r\n * .use(authMiddleware) // ctx.session is typed in the handler ✅\r\n * .query(async ({ ctx }) => ctx.session.user);\r\n * ```\r\n */\r\nexport function createMiddleware<C extends BaseContext, TReturn extends Record<string, any> | void = void>(\r\n _context: (req: Request) => Promise<C>,\r\n fn: (ctx: C) => Promise<TReturn>\r\n): (ctx: C) => Promise<TReturn>;\r\nexport function createMiddleware<C extends BaseContext, TReturn extends Record<string, any> | void = void>(\r\n fn: (ctx: C) => Promise<TReturn>\r\n): (ctx: C) => Promise<TReturn>;\r\nexport function createMiddleware<C extends BaseContext, TReturn extends Record<string, any> | void = void>(\r\n contextOrFn: ((req: Request) => Promise<C>) | ((ctx: C) => Promise<TReturn>),\r\n fn?: (ctx: C) => Promise<TReturn>\r\n): (ctx: C) => Promise<TReturn> {\r\n return fn ?? (contextOrFn as (ctx: C) => Promise<TReturn>);\r\n}\r\n"
|
|
15
|
+
"import type { BaseContext } from \"../types\";\r\n\r\n/**\r\n * Helper to define a reusable, typed middleware outside of a procedure chain.\r\n *\r\n * @example\r\n * ```ts\r\n * // Infer context type from your context creator\r\n * const authMiddleware = createMiddleware(context, async (ctx) => {\r\n * const session = await getSession(ctx.req);\r\n * if (!session) throw new BRPCError({ code: \"UNAUTHORIZED\" });\r\n * return { session };\r\n * });\r\n *\r\n * // Or with an explicit generic (no context reference needed)\r\n * const authMiddleware = createMiddleware<MyContext>(async (ctx) => {\r\n * return { session: await getSession(ctx.req) };\r\n * });\r\n *\r\n * createProcedure(context)\r\n * .use(authMiddleware) // ctx.session is typed in the handler ✅\r\n * .query(async ({ ctx }) => ctx.session.user);\r\n * ```\r\n */\r\nexport function createMiddleware<C extends BaseContext, TReturn extends Record<string, any> | void = void>(\r\n _context: (req: Request) => Promise<C>,\r\n fn: (ctx: C) => Promise<TReturn>\r\n): (ctx: C) => Promise<TReturn>;\r\nexport function createMiddleware<C extends BaseContext, TReturn extends Record<string, any> | void = void>(\r\n fn: (ctx: C) => Promise<TReturn>\r\n): (ctx: C) => Promise<TReturn>;\r\nexport function createMiddleware<C extends BaseContext, TReturn extends Record<string, any> | void = void>(\r\n contextOrFn: ((req: Request) => Promise<C>) | ((ctx: C) => Promise<TReturn>),\r\n fn?: (ctx: C) => Promise<TReturn>\r\n): (ctx: C) => Promise<TReturn> {\r\n return fn ?? (contextOrFn as (ctx: C) => Promise<TReturn>);\r\n}\r\n",
|
|
16
|
+
"export async function measure<T>(\r\n label: string,\r\n fn: () => Promise<T>,\r\n): Promise<T> {\r\n const start = performance.now();\r\n try {\r\n return await fn();\r\n } catch (err) {\r\n const end = performance.now();\r\n console.log(`[PERF] ${label} failed after ${(end - start).toFixed(4)} ms`);\r\n throw err;\r\n } finally {\r\n const end = performance.now();\r\n console.log(`[PERF] ${label}: ${(end - start).toFixed(4)} ms`);\r\n }\r\n}\r\n"
|
|
16
17
|
],
|
|
17
|
-
"mappings": "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",
|
|
18
|
-
"debugId": "
|
|
18
|
+
"mappings": "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",
|
|
19
|
+
"debugId": "F612D0D8B6F80A0564756E2164756E21",
|
|
19
20
|
"names": []
|
|
20
21
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./measure";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function measure<T>(label: string, fn: () => Promise<T>): Promise<T>;
|
package/package.json
CHANGED
package/dist/cache/types.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|