|
2
|
-
var O=import.meta.require;export*from"ts-broadcasting";var _=null;function D(G){_=G}function L(){return _}async function w(G){let V=new(await import("ts-broadcasting")).BroadcastServer(G);return await V.start(),D(V),V}async function b(){if(_)await _.stop(),_=null}function F(G,J,Q,V){let Y=L();if(!Y){console.warn("[realtime] Server not initialized, cannot emit event");return}let Z=G;if(V?.presence){if(!G.startsWith("presence-"))Z=`presence-${G}`}else if(V?.private){if(!G.startsWith("private-"))Z=`private-${G}`}let W=V?.exclude?Array.isArray(V.exclude)?V.exclude[0]:V.exclude:void 0;Y.broadcast(Z,J,Q,W)}function M(G,J,Q,V){F(`private-user.${G}`,J,Q,{...V,private:!0})}function y(G,J,Q,V){for(let Y of G)M(Y,J,Q,V)}var f=["private-","presence-"];function T(G){for(let J of f)if(G.startsWith(J))return G.slice(J.length);return G}class E{channelName;constructor(G){this.channelName=G}async private(G,J){let Q=L();if(!Q)throw Error("Broadcast server not initialized");await Q.broadcast(`private-${T(this.channelName)}`,G,J)}async public(G,J){let Q=L();if(!Q)throw Error("Broadcast server not initialized");await Q.broadcast(T(this.channelName),G,J)}async presence(G,J){let Q=L();if(!Q)throw Error("Broadcast server not initialized");await Q.broadcast(`presence-${T(this.channelName)}`,G,J)}async broadcast(G,J,Q="public"){switch(Q){case"private":return this.private(G,J);case"presence":return this.presence(G,J);default:return this.public(G,J)}}}function P(G){return new E(G)}import{log as U}from"@stacksjs/logging";var $=null;function u(G){if(!G){$=null;return}$={channels:G.channels??[],maxPerChannel:G.maxPerChannel??100,ttlMs:G.ttlMs??300000,state:new Map}}function m(){return $}function p(G){if(!$||$.channels.length===0)return!1;for(let J of $.channels){if(J==="*")return!0;if(J===G)return!0;if(J.endsWith(".*")&&G.startsWith(J.slice(0,-1)))return!0}return!1}function A(G,J,Q){if(!$||!p(G))return null;let V=$.state.get(G);if(!V)V={messages:[],nextSeq:1},$.state.set(G,V);let Y={seq:V.nextSeq++,ts:Date.now(),event:J,data:Q};if(V.messages.push(Y),V.messages.length>$.maxPerChannel)V.messages.splice(0,V.messages.length-$.maxPerChannel);return Y.seq}function d(G,J){if(!$)return[];let Q=$.state.get(G);if(!Q)return[];let V=Date.now(),Y=$.ttlMs;while(Q.messages.length>0&&V-Q.messages[0].ts>Y)Q.messages.shift();if(Q.messages.length===0)return[];return Q.messages.filter((Z)=>Z.seq>J)}function g(){if(!$)return;let G=Date.now(),J=$.ttlMs;for(let Q of $.state.values())while(Q.messages.length>0&&G-Q.messages[0].ts>J)Q.messages.shift()}function h(){let G={};if(!$)return G;for(let[J,Q]of $.state)G[J]={count:Q.messages.length,firstSeq:Q.messages[0]?.seq??null,lastSeq:Q.messages[Q.messages.length-1]?.seq??null};return G}var j=null;function v(G){if(!G){j=null;return}j={maxPerSocketBytes:G.maxPerSocketBytes??1048576,onSlow:G.onSlow??((J)=>{U.warn(`[realtime] slow consumer on '${J.channelName}': ${J.backpressure} bytes buffered`)})}}function i(){return j}function l(G,J){if(!j)return;try{let Q=G.channels??G.clients,V=Q&&typeof Q.get==="function"?Q.get(J):null;if(!V||typeof V[Symbol.iterator]!=="function")return;let{maxPerSocketBytes:Y,onSlow:Z}=j;for(let W of V){let R=W&&typeof W==="object"&&"ws"in W?W.ws:W,z=R&&typeof R==="object"&&"backpressure"in R?R.backpressure:null;if(typeof z==="number"&&z>Y)Z({channelName:J,backpressure:z,socket:R})}}catch{}}function o(G,J){try{if(typeof G.hasSubscribers==="function")return Boolean(G.hasSubscribers(J));if(typeof G.subscriberCount==="function")return G.subscriberCount(J)>0;let Q=G.channels??G.clients;if(Q&&typeof Q.get==="function"){let V=Q.get(J),Y=(V&&(V.size??V.length))??null;if(typeof Y==="number")return Y>0}}catch{}return!0}class q{async connect(){}async disconnect(){}subscribe(G,J){U.warn("Broadcast.subscribe() is a client-side operation. Use BroadcastClient instead.")}unsubscribe(G){U.warn("Broadcast.unsubscribe() is a client-side operation. Use BroadcastClient instead.")}broadcast(G,J,Q,V="public"){let Y=L();if(!Y){U.warn("Broadcast server not initialized");return}let Z=G;if(V==="private"&&!G.startsWith("private-"))Z=`private-${G}`;else if(V==="presence"&&!G.startsWith("presence-"))Z=`presence-${G}`;if(!o(Y,Z)){U.debug(`[Broadcast] Skipping '${J}' on '${Z}' \u2014 no subscribers`);return}l(Y,Z),A(Z,J,Q);try{Y.broadcast(Z,J,Q)}catch(W){U.error(`[Broadcast] Failed to broadcast event '${J}' to channel '${Z}':`,W)}}isConnected(){return L()!==null}}async function B(G,J){let{appPath:Q}=await import("@stacksjs/path"),V=awaitPromise.resolve(globalThis.Bun),Y;try{Y=V.globSync([Q("Broadcasts/**/*.ts")],{absolute:!0})}catch(X){throw Error(`Failed to scan broadcast files: ${X instanceof Error?X.message:String(X)}`)}let Z=Y.find((X)=>X.endsWith(`${G}.ts`));if(!Z)throw Error(`Broadcast ${G} not found`);let W;try{W=await import(Z)}catch(X){throw Error(`Failed to import broadcast '${G}': ${X instanceof Error?X.message:String(X)}`)}let R=W.default;if(R.handle){await R.handle(J);return}let z=L();if(!z)throw Error("Broadcast server not initialized");let I=R.broadcastOn?.()||R.channel?.()||[],S=R.broadcastAs?.()||R.event?.()||G,k=R.broadcastWith?.()||R.data?.()||J,N={shouldBroadcast:()=>!0,broadcastOn:()=>I,broadcastAs:()=>S,broadcastWith:()=>k};await z.broadcaster.broadcast(N)}async function c(G,J){if(typeof G!=="string"||G.trim().length===0)throw Error("[realtime] broadcast() requires a non-empty event name");await B(G,J)}import{log as C}from"@stacksjs/logging";var K=null;function s(G){if(K?.timer)clearInterval(K.timer),K.timer=null;if(!G){K=null;return}let J=G.intervalMs??30000,Q=G.maxMissedPongs??2,V=G.onDead??t;K={intervalMs:J,maxMissedPongs:Q,onDead:V,missed:new WeakMap,timer:null},K.timer=setInterval(()=>{if(!K)return;x()},J),K.timer.unref?.()}function r(){return K}function x(){if(!K)return;let G=L();if(!G)return;let J=a(G);for(let Q of J){let V=Q,Y=K.missed.get(Q)??0;if(Y>=K.maxMissedPongs){C.warn(`[realtime] socket missed ${Y} pongs \u2014 declaring dead`);try{K.onDead(Q)}catch(Z){C.warn(`[realtime] heartbeat onDead handler threw: ${Z instanceof Error?Z.message:String(Z)}`)}K.missed.delete(Q);continue}K.missed.set(Q,Y+1);try{if(typeof V.ping==="function")V.ping();else if(typeof V.send==="function")V.send("__stacks_ping__")}catch{}}}function n(G){if(!K)return;K.missed.delete(G)}function a(G){let J=new Set;try{let Q=G.channels??G.clients;if(Q&&typeof Q.values==="function"){for(let V of Q.values())if(V&&typeof V[Symbol.iterator]==="function")for(let Y of V){let Z=Y&&typeof Y==="object"&&"ws"in Y?Y.ws:Y;if(Z&&typeof Z==="object")J.add(Z)}}}catch{}return[...J]}function t(G){let J=G;if(typeof J.close==="function")J.close(1011,"heartbeat timeout")}function e(G){if(G)D(G)}async function GG(G,J,Q){}var H=null;function JG(G){H=G}function QG(){return H}async function VG(G,J){if(!L())return new Response("WebSocket server not initialized",{status:500});if(H)try{let Y=await H(G);if(!Y.ok)return new Response(Y.message??"Unauthorized",{status:Y.status??401});if(J.upgrade(G,Y.data?{data:Y.data}:void 0))return;return new Response("WebSocket upgrade failed",{status:400})}catch(Y){return console.error("[realtime] WebSocket authenticator threw:",Y),new Response("WebSocket auth error",{status:500})}if(J.upgrade(G))return;return new Response("WebSocket upgrade failed",{status:400})}export{GG as storeWebSocketEvent,b as stopServer,JG as setWsAuthenticator,D as setServer,u as setReplayBuffer,s as setHeartbeatConfig,e as setBunSocket,v as setBackpressureGuard,x as runOneTick,B as runBroadcast,d as replaySince,A as recordBroadcast,g as pruneExpired,n as markPong,VG as handleWebSocketRequest,QG as getWsAuthenticator,L as getServer,m as getReplayBuffer,r as getHeartbeatConfig,i as getBackpressureGuard,y as emitToUsers,M as emitToUser,F as emit,c as dispatchBroadcast,h as debugSnapshot,w as createServer,P as createChannel,P as channel,E as StacksChannel,q as LegacyBroadcast};
|
|
2
|
+
export*from"ts-broadcasting";export{l as storeWebSocketEvent,C as stopServer,p as setWsAuthenticator,A as setServer,m as setReplayBuffer,W as setHeartbeatConfig,f as setBunSocket,Q as setBackpressureGuard,V as runOneTick,N as runBroadcast,k as replaySince,$ as recordBroadcast,_ as pruneExpired,U as markPong,g as handleWebSocketRequest,w as getWsAuthenticator,z as getServer,Z as getReplayBuffer,T as getHeartbeatConfig,R as getBackpressureGuard,G as emitToUsers,F as emitToUser,E as emit,M as dispatchBroadcast,Y as debugSnapshot,B as createServer,J as createChannel,I as channel,K as StacksChannel,O as LegacyBroadcast};
|