@lunora/client 1.0.0-alpha.231 → 1.0.0-alpha.233
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/auth/index.d.mts +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/index.d.mts +82 -3
- package/dist/index.d.ts +82 -3
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/LunoraClient-CN4shVl4.mjs +1 -0
- package/dist/packem_shared/OfflineQueue-BLRESpAe.mjs +1 -0
- package/dist/packem_shared/TabCoordinator-DBuR7Dwv.mjs +1 -0
- package/dist/packem_shared/client-tuning-C10B2KCO.mjs +1 -0
- package/dist/packem_shared/connectLiveStream-CXD8k-Sp.mjs +1 -0
- package/dist/packem_shared/{createAsyncStorageQueryCache-f5023fdB.mjs → createAsyncStorageQueryCache-COqH5_SV.mjs} +1 -1
- package/dist/packem_shared/{createInMemoryPersistence-Cz2W6XVj.mjs → createInMemoryPersistence-BfgXApi_.mjs} +1 -1
- package/dist/packem_shared/{createInMemoryQueryCache-D2uNHLfM.mjs → createInMemoryQueryCache-B5wX-gTy.mjs} +1 -1
- package/dist/packem_shared/{createServerClient-BqCdfoE1.mjs → createServerClient-CwEIYb-6.mjs} +1 -1
- package/dist/packem_shared/httpStream-DceAMeMf.mjs +9 -0
- package/dist/packem_shared/idb-utility-BS7xvou1.mjs +1 -0
- package/dist/packem_shared/live-stream-Dil9byXF.mjs +10 -0
- package/dist/packem_shared/{liveTopicSubscription-Bs-ULKfs.mjs → liveTopicSubscription-gOmRbuhH.mjs} +1 -1
- package/dist/packem_shared/{lunora-client.d-dOEEoF4x.d.mts → lunora-client.d-D7gNlYT7.d.mts} +153 -17
- package/dist/packem_shared/{lunora-client.d-DpmxnYmL.d.ts → lunora-client.d-DTJ5zJKH.d.ts} +153 -17
- package/dist/packem_shared/offline-queue-Dt_um8sR.mjs +1 -0
- package/dist/packem_shared/{preload.d-XVLTUaah.d.mts → preload.d-B0FFchsh.d.mts} +1 -1
- package/dist/packem_shared/{preload.d-BkXsKMmU.d.ts → preload.d-d05S6fB-.d.ts} +1 -1
- package/dist/packem_shared/stream-idle-C7CsIT_m.mjs +1 -0
- package/dist/packem_shared/{wire-errors-Bw04a4ZQ.mjs → wire-errors-BTLdHNoh.mjs} +1 -1
- package/dist/query/index.d.mts +2 -2
- package/dist/query/index.d.ts +2 -2
- package/dist/service.mjs +1 -1
- package/dist/ssr/index.d.mts +2 -2
- package/dist/ssr/index.d.ts +2 -2
- package/dist/ssr/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/packem_shared/LunoraClient-D6MyuSWy.mjs +0 -1
- package/dist/packem_shared/OfflineQueue-BWamzR6p.mjs +0 -1
- package/dist/packem_shared/TabCoordinator-CXD7vulJ.mjs +0 -1
- package/dist/packem_shared/connectLiveStream-DCgklEjI.mjs +0 -1
- package/dist/packem_shared/httpStream-DaqP70Ne.mjs +0 -9
- package/dist/packem_shared/idb-utility-C8WS390w.mjs +0 -1
- package/dist/packem_shared/live-stream-ct8j7T75.mjs +0 -10
- package/dist/packem_shared/offline-queue-D_fr-uQ3.mjs +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{LunoraError as y}from"@lunora/errors";import{encodeWire as N,decodeWire as T,stableWireKey as ce}from"@lunora/wire";import{r as Ue,U as Ne,P as xe}from"./delta-merge-Ls3DED4g.mjs";import{w as b,b as re,j as k,d as de,p as he,s as ue}from"./client-urls-BHLUjjcG.mjs";import Be from"./createInMemoryBookmarkStorage-BooZhW0n.mjs";import{s as X,a as De,e as x,r as Qe,b as le,w as We,c as qe,d as fe}from"./wire-errors-Bw04a4ZQ.mjs";import{ClientQueryStore as Ke}from"./createClientQuery-B8Nfj-7o.mjs";import{TabCoordinator as je}from"./TabCoordinator-CXD7vulJ.mjs";import{TransportError as U,getRetryAfterMs as Ge,AUTH_REPLAY_ERROR_CODES as $e,isAuthReplayFailure as K}from"./CONFLICT_ERROR_CODE-B7qNZMMk.mjs";import{httpStream as Ve}from"./httpStream-DaqP70Ne.mjs";import{d as Z,r as P,a as M,b as ze,c as Je,e as Ye,f as Xe}from"./local-store-fqWV2n_Z.mjs";import{O as Ze,n as pe,i as et,r as tt}from"./offline-queue-D_fr-uQ3.mjs";import{resolvePersistenceAdapter as st}from"./createInMemoryPersistence-Cz2W6XVj.mjs";import{resolveQueryCacheAdapter as rt,queryCacheKey as O}from"./createInMemoryQueryCache-D2uNHLfM.mjs";import{createReconnect as me}from"./createReconnect-CjTmjJDH.mjs";import{fanSubscriptionError as A,SubscriptionRegistry as w,wrapSubscriber as j}from"./SubscriptionRegistry-DKIXE7M7.mjs";import it from"./createSnapshotPrecondition-CLkxVeN1.mjs";import{createStream as nt}from"./DEFAULT_MAX_BUFFER-Bd-_iyiV.mjs";const G=500,Ce=(i,e)=>{if(i.size<e)return;const t=i.keys().next().value;t!==void 0&&i.delete(t)},E="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",ot=i=>{let e="",t=0;const s=i.length-2;for(;t<s;t+=3){const n=i[t]<<16|i[t+1]<<8|i[t+2];e+=E.charAt(n>>18&63)+E.charAt(n>>12&63)+E.charAt(n>>6&63)+E.charAt(n&63)}const r=i.length-t;if(r===1){const n=i[t]<<16;e+=E.charAt(n>>18&63)+E.charAt(n>>12&63)}else if(r===2){const n=i[t]<<16|i[t+1]<<8;e+=E.charAt(n>>18&63)+E.charAt(n>>12&63)+E.charAt(n>>6&63)}return e};new TextDecoder;const at=new TextEncoder,ct=i=>ot(at.encode(JSON.stringify(i))),dt="x-lunora-expect-subject",ht=i=>ct({subject:i}),ye=Symbol.for("lunora:session-change"),ut="lunora:session-change",lt="better-auth.message",ft="signout",we=()=>{const i=globalThis;let e=i[ye];return e===void 0&&(e={detach:void 0,listeners:new Set,tab:`${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`},i[ye]=e),e},pt=()=>"document"in globalThis,mt=async()=>{const i=[];for(const e of we().listeners)try{i.push(e())}catch{}await Promise.allSettled(i)},yt=(i,e)=>{if(i!==lt||e===null)return!1;try{const t=JSON.parse(e);return t?.event==="session"&&t.data?.trigger===ft}catch{return!1}},St=i=>{const e=[],t=()=>{mt().catch(()=>{})};let s;try{s=typeof BroadcastChannel=="function"?new BroadcastChannel(ut):void 0}catch{s=void 0}if(s!==void 0){const n=s;n.addEventListener("message",a=>{a.data?.type==="lunora:session-change"&&a.data.tab!==i&&t()}),e.push(()=>{n.close()})}const r=globalThis;if(typeof r.addEventListener=="function"){const n=a=>{yt(a.key,a.newValue)&&t()};r.addEventListener("storage",n),e.push(()=>{r.removeEventListener?.("storage",n)})}return()=>{for(const n of e)n()}},bt=i=>{const e=we();return e.listeners.add(i),e.detach===void 0&&pt()&&(e.detach=St(e.tab)),()=>{e.listeners.delete(i),e.listeners.size===0&&(e.detach?.(),e.detach=void 0)}},gt="/_lunora/rpc",$="/_lunora/rpc-batch",V="/_lunora/ws",vt="/_lunora/admin/shard-traffic",Tt="/_lunora/admin/scheduled",kt="/_lunora/admin/scheduled/status",Ct="/_lunora/admin/scheduled/ws",wt="/_lunora/admin/scheduled/cancel",Se="/_lunora/admin/scheduled/dead",Et="/_lunora/admin/scheduled/dead/retry",At="/_lunora/admin/scheduled/dead/cancel",_t="/_lunora/admin/workflows/instances",It="/_lunora/admin/workflows/instance",Ot="/_lunora/admin/workflows/status",ie="/_lunora/admin/storage",Rt="/_lunora/admin/storage/url",Pt="/_lunora/admin/storage/buckets",Ft="/_lunora/admin/functions",Lt="/_lunora/admin/cron-jobs",Mt="/_lunora/admin/cron-jobs/run",Ht="/_lunora/admin/architecture",Ut="/_lunora/admin/openapi",Nt="/_lunora/admin/openrpc",xt="/_lunora/admin/global/tables",Bt="/_lunora/admin/global/table",Dt="/_lunora/admin/global/facet",Qt="/_lunora/admin/vector/indexes",Wt="/_lunora/admin/vector/query",qt="/_lunora/admin/logs/archive",Kt="/_lunora/admin/kv/namespaces",jt="/_lunora/admin/kv/keys",ne="/_lunora/admin/kv/value",Gt="/_lunora/admin/auth/users",$t="/_lunora/admin/auth/sessions",Vt="/_lunora/admin/auth/users/create",zt="/_lunora/admin/auth/users/role",Jt="/_lunora/admin/auth/users/ban",Yt="/_lunora/admin/auth/users/unban",Xt="/_lunora/admin/auth/users/password",Zt="/_lunora/admin/auth/users/remove",es="/_lunora/admin/auth/users/impersonate",ts="/_lunora/admin/auth/sessions/revoke",ss="/_lunora/admin/auth/sessions/revoke-all",rs="/_lunora/admin/auth/capabilities",is="/_lunora/admin/auth/users/update",ns="/_lunora/admin/auth/accounts",os="/_lunora/admin/auth/accounts/unlink",as="/_lunora/admin/auth/passkeys",cs="/_lunora/admin/auth/passkeys/delete",ds="/_lunora/admin/auth/two-factor/disable",hs="/_lunora/admin/auth/organizations",us="/_lunora/admin/auth/organizations/members",ls="/_lunora/admin/auth/organizations/invitations",fs="/_lunora/admin/auth/organizations/members/remove",ps="/_lunora/admin/auth/organizations/invitations/cancel",ms="/_lunora/admin/auth/config",ys="/_lunora/admin/auth/sign-up-invitations",Ss="/_lunora/admin/auth/sign-up-invitations/create",bs="/_lunora/admin/auth/sign-up-invitations/revoke",gs="/_lunora/admin/auth/organizations/create",vs="/_lunora/admin/auth/organizations/update",Ts="/_lunora/admin/auth/organizations/remove",ks="/_lunora/admin/auth/organizations/members/add",Cs="/_lunora/admin/auth/organizations/members/invite",ws="/_lunora/admin/auth/organizations/members/role",Es="/_lunora/admin/auth/organizations/teams",As="/_lunora/admin/auth/organizations/teams/create",_s="/_lunora/admin/auth/organizations/teams/update",Is="/_lunora/admin/auth/organizations/teams/remove",Os="/_lunora/admin/auth/organizations/teams/members",Rs="/_lunora/admin/auth/organizations/teams/members/add",Ps="/_lunora/admin/auth/organizations/teams/members/remove",Fs="/_lunora/admin/auth/organizations/roles",Ls="/_lunora/admin/auth/organizations/roles/create",Ms="/_lunora/admin/auth/organizations/roles/update",Hs="/_lunora/admin/auth/organizations/roles/remove",Us="/api/auth",Ns="/get-session",xs="lunora-ping",Bs=async i=>(i.assertOpen(),(await i.adminFetch(Ft,"GET")).functions??[]),Ds=async i=>(i.assertOpen(),(await i.adminFetch(Lt,"GET")).jobs??[]),Qs=async(i,e)=>{i.assertOpen();const t=await i.adminFetch(Mt,"POST",{name:e});return{name:t.name??e,ran:t.ran===!0}},Ws=async i=>(i.assertOpen(),await i.adminFetch(Ut,"GET")),qs=async i=>(i.assertOpen(),await i.adminFetch(Ht,"GET")),Ks=async i=>(i.assertOpen(),await i.adminFetch(Nt,"GET")),js=async i=>(i.assertOpen(),await i.adminFetch(xt,"GET")),Gs=async(i,e)=>{i.assertOpen();const t=new URLSearchParams({table:e.table});return e.limit!==void 0&&t.set("limit",String(e.limit)),e.offset!==void 0&&t.set("offset",String(e.offset)),e.filters!==void 0&&e.filters.length>0&&t.set("filters",JSON.stringify(N(e.filters))),T(await i.adminFetch(`${Bt}?${t.toString()}`,"GET"))},$s=async(i,e)=>{i.assertOpen();const t=new URLSearchParams({column:e.column,table:e.table});return e.limit!==void 0&&t.set("limit",String(e.limit)),e.filters!==void 0&&e.filters.length>0&&t.set("filters",JSON.stringify(N(e.filters))),T(await i.adminFetch(`${Dt}?${t.toString()}`,"GET"))},Vs=async i=>(i.assertOpen(),(await i.adminFetch(Kt,"GET")).namespaces??[]),zs=async(i,e)=>{i.assertOpen();const t=b(jt,{cursor:e.cursor,limit:e.limit,namespace:e.namespace,prefix:e.prefix});return await i.adminFetch(t,"GET")},Js=async(i,e)=>{i.assertOpen();const t=b(ne,{key:e.key,namespace:e.namespace});return await i.adminFetch(t,"GET")},Ys=async(i,e)=>{i.assertOpen(),await i.adminFetch(ne,"PUT",e)},Xs=async(i,e)=>{i.assertOpen();const t=b(ne,{key:e.key,namespace:e.namespace});await i.adminFetch(t,"DELETE")},Zs=async(i,e)=>{i.assertOpen();const t=await i.adminFetch(vt,"POST",{table:e});return{failed:t.failed??0,ok:t.ok??0,shards:t.shards??[]}},er=async(i,e={})=>{i.assertOpen();const t=await i.adminFetch(qt,"POST",e);return{nextCursor:t.nextCursor,rows:t.rows??[]}},tr=async i=>{const e=[];let t;for(;;){const s=await i(t);if(e.push(...Array.isArray(s.records)?s.records:[]),s.truncated!==!0||typeof s.cursor!="string"||s.cursor.length===0)return e;if(s.cursor===t)throw new Error("collectPages: the list did not advance its cursor — refusing to page forever");t=s.cursor}},oe=i=>"args"in i?{...i,args:T(i.args)}:i,sr=async i=>(i.assertOpen(),((await i.adminFetch(Tt,"GET")).records??[]).map(t=>oe(t))),rr=async i=>{i.assertOpen();const e=await i.adminFetch(kt,"GET");return{backlog:e.backlog??0,inFlight:e.inFlight??0,pools:e.pools??[]}},ir=async(i,e)=>(i.assertOpen(),{cancelled:(await i.adminFetch(wt,"POST",{id:e})).cancelled===!0}),nr=async i=>(i.assertOpen(),(await tr(async t=>await i.adminFetch(t===void 0?Se:`${Se}?cursor=${encodeURIComponent(t)}`,"GET"))).map(t=>oe(t))),or=async(i,e)=>(i.assertOpen(),{retried:(await i.adminFetch(Et,"POST",{id:e})).retried===!0}),ar=async(i,e)=>(i.assertOpen(),{removed:(await i.adminFetch(At,"POST",{id:e})).removed===!0}),cr=async(i,e)=>{i.assertOpen();const t=new URLSearchParams({name:e.name});e.status!==void 0&&t.set("status",e.status),e.page!==void 0&&t.set("page",String(e.page)),e.perPage!==void 0&&t.set("perPage",String(e.perPage));const s=await i.adminFetch(`${_t}?${t.toString()}`,"GET");return{configured:s.configured,instances:s.instances??[],page:s.page??1,perPage:s.perPage??e.perPage??0,totalCount:s.totalCount}},dr=async(i,e)=>{i.assertOpen();const t=new URLSearchParams({id:e.id,name:e.name}),s=await i.adminFetch(`${It}?${t.toString()}`,"GET");return{createdOn:s.createdOn,endedOn:s.endedOn,error:s.error,id:s.id??e.id,output:s.output,params:s.params,startedOn:s.startedOn,status:s.status??"unknown",steps:s.steps??[]}},hr=async(i,e)=>(i.assertOpen(),{status:(await i.adminFetch(Ot,"POST",{action:e.action,id:e.id,name:e.name})).status??"unknown"}),ur=async(i,e={})=>{i.assertOpen();const t=b(ie,{bucket:e.bucket,cursor:e.cursor,limit:e.limit,prefix:e.prefix}),s=await i.adminFetch(t,"GET");return{cursor:s.cursor,objects:s.objects??[]}},lr=async(i,e,t)=>{i.assertOpen();const s=`${ie}?key=${encodeURIComponent(e)}${re(t?.bucket)}`,r=await i.adminFetch(s,"DELETE");return{deleted:r.deleted===!0,key:r.key??e}},fr=async i=>(i.assertOpen(),(await i.adminFetch(Pt,"GET")).buckets??[]),pr=async(i,e)=>{i.assertOpen();const t=`${ie}?key=${encodeURIComponent(e.key)}${re(e.bucket)}`,s=await i.adminFetch(t,"PUT",e.body,e.contentType);return{etag:s.etag,key:s.key??e.key}},mr=async(i,e,t)=>{i.assertOpen();const s=t?.expiresInSeconds,r=s===void 0?"":`&expiresIn=${encodeURIComponent(s.toString())}`,n=`${Rt}?key=${encodeURIComponent(e)}${r}${re(t?.bucket)}`,a=await i.adminFetch(n,"GET");if(typeof a.url!="string")throw new TypeError("LunoraClient: storage URL endpoint returned no `url`");return a.url},yr=async i=>(i.assertOpen(),(await i.adminFetch(Qt,"GET")).indexes??[]),Sr=async(i,e)=>(i.assertOpen(),(await i.adminFetch(Wt,"POST",e)).matches??[]),C=(i,e)=>{try{return N(i)}catch(t){const s=t instanceof Error?t.message:String(t);throw new TypeError(`LunoraClient: cannot encode ${e} — ${s}`,t instanceof Error?{cause:t}:void 0)}},be=i=>{try{return N(i),!0}catch{return!1}},Ee=i=>i!==null&&typeof i=="object"&&("error"in i||"result"in i),br=(i,e)=>{const t=Array.from({length:e});for(const s of i){if(typeof s.id!="number"||s.id<0||s.id>=e)continue;if(!Ee(s.body)){t[s.id]={error:X({}),ok:!1};continue}const r=s.body;t[s.id]="error"in r?{error:X(r),ok:!1}:{ok:!0,value:T(r.result)}}return t.map(s=>s??{error:new Error("batch call returned no result"),ok:!1})},z=(i,e)=>e!==null?{}:i===null?{expectSubject:null}:i?.startsWith("subj:")===!0?{expectSubject:i.slice(5)}:{},gr=3e4,vr=1e4,Tr=5e3,kr=3,Cr=250,ge=5e3,wr=5e3,Er=64,Ar=3,_r=1e4,Ir=8,J=i=>i==="connected"||i==="polling",l=i=>i??"",v=(i,e)=>{if(!i.socket||i.wsState!=="open")return!1;try{return i.socket.send(JSON.stringify(e)),!0}catch{return!1}},Or=i=>{if(!i.pendingStreams||i.pendingStreams.length===0)return;const e=i.pendingStreams;i.pendingStreams=[];for(const t of e)v(i,t)},Rr=new TextDecoder,Pr=i=>{if(typeof i=="string")return i;if(i instanceof ArrayBuffer)return Rr.decode(i)};class R{listeners=new Set;add(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}emit(...e){const[t]=e;for(const s of this.listeners)try{s(t)}catch{}}clear(){this.listeners.clear()}}const F=i=>{i.heartbeatTimer!==void 0&&(clearInterval(i.heartbeatTimer),i.heartbeatTimer=void 0)},Fr=(i,e,t)=>{F(i),!(e<=0)&&(i.heartbeatTimer=setInterval(()=>{if(!i.socket)return;const{socket:s}=i;if(Date.now()-i.lastFrameAt>e*2.5){try{s.close()}catch{}t();return}try{s.send(xs)}catch{}},e))},ve=(i,e,t,s)=>{const{WebSocketImpl:r,connectTimeoutMs:n,heartbeatIntervalMs:a}=t;if(r===void 0)throw new y("INTERNAL","no WebSocket implementation available");const o=new r(e);i.socket=o;const c=()=>{F(i),i.connectTimer!==void 0&&(clearTimeout(i.connectTimer),i.connectTimer=void 0),i.socket===o&&(i.socket=void 0)},d=h=>{c(),s.onClose(h)};n>0&&(i.connectTimer=setTimeout(()=>{if(i.connectTimer=void 0,i.socket===o){try{o.close()}catch{}d()}},n)),o.addEventListener("open",()=>{if(i.socket===o){i.connectTimer!==void 0&&(clearTimeout(i.connectTimer),i.connectTimer=void 0),i.lastFrameAt=Date.now();try{s.onOpen?.()}catch(h){console.error("[lunora] connection open handler threw",h)}i.socket===o&&Fr(i,a,d)}}),o.addEventListener("message",h=>{if(i.socket===o){i.lastFrameAt=Date.now();try{s.onMessage(h)}catch(u){console.error("[lunora] server frame handler threw",u)}}}),o.addEventListener("close",h=>{i.socket===o&&d(h)}),o.addEventListener("error",()=>{i.socket===o&&d()})},Lr=i=>{const{afterFailedAttempts:e,intervalMs:t,onReachable:s,onStateChange:r,poll:n}=i,a=t>0&&e>0;let o=0,c,d=!1,h=!1;const u=()=>{c!==void 0&&(clearInterval(c),c=void 0,d=!1,r())},m=p=>{if(c!==void 0){if(!p){u();return}d||(d=!0,r()),s()}},f=()=>{h||(h=!0,n().then(m).finally(()=>{h=!1}).catch(()=>{}))};return{isPolling:()=>c!==void 0&&d,noteFailedOpen:()=>{o+=1,!(!a||c!==void 0||o<e)&&(c=setInterval(f,t),r(),f())},noteOpen:()=>{o=0,u()},stop:u}},Mr=1e4,Te=async i=>{const e=new AbortController;let t;const s=new Promise((r,n)=>{t=setTimeout(()=>{e.abort(),n(new TypeError("LunoraClient: poll timed out"))},Mr)});try{return await Promise.race([i(e.signal),s])}catch(r){throw e.signal.aborted?new TypeError("LunoraClient: poll timed out"):r}finally{clearTimeout(t)}},Ae=new Set(["DELIVERY_FENCED","RATE_LIMITED","SHARD_ERROR","SHARD_UNAVAILABLE","TOO_MANY_REQUESTS"]),Hr=i=>{if(i instanceof U)return!0;const e=i?.code;return e===void 0||Ae.has(e)||$e.has(e)},_e=6e4,Ur=1e3,Nr={401:"UNAUTHORIZED",403:"FORBIDDEN",404:"NOT_FOUND",413:"PAYLOAD_TOO_LARGE",429:"TOO_MANY_REQUESTS"},H=(i,e,t)=>{const s=De(t),r=s===void 0?void 0:{retryAfterMs:s},n=`LunoraClient: response carried no error envelope (status ${i.toString()}${e?` ${e}`:""})`;return i<400||i>=500||i===408?new U(n,r):new y(Nr[i]??"BAD_REQUEST",n,{data:r})},ee=(i,e=Math.random)=>{const t=Math.min(Ur*2**Math.max(i-1,0),_e);return Math.round(t*(.5+e()*.5))},xr=i=>i instanceof U||Ae.has(i?.code??""),Br=(i,e,t)=>{const s=Ge(i);return s!==void 0&&s>0?Math.min(s,_e):xr(i)?ee(e,t):void 0},Dr=983040,Qr=i=>typeof TextEncoder>"u"?i.length:new TextEncoder().encode(i).length,Ie=new WeakSet,Oe=i=>{const e=new y("WIRE_DECODE_FAILED",`LunoraClient: the call succeeded but its result could not be decoded (a mutation has still committed) — ${i instanceof Error?i.message:String(i)}`,{cause:i});return Ie.add(e),e},B=i=>i instanceof Error&&Ie.has(i),Wr=i=>{const e=new Map;for(const t of i)typeof t.id=="number"&&Ee(t.body)&&e.set(t.id,t.body);return e},qr=i=>{if(i===void 0)return{kind:"unanswered"};if("error"in i)return{error:X(i),kind:"errored"};try{return{commitCursor:i.commitCursor,kind:"committed",value:T(i.result)}}catch(e){return{commitCursor:i.commitCursor,error:Oe(e),kind:"undecodable"}}},Y=(i,e)=>`${l(i)}\0${e}`,Kr=(i,e)=>{for(const t of e)t.op==="delete"?i.delete(t.key):t.value!==void 0&&i.set(t.key,t.value)};class jr{constructor(e){this.maxBuffers=e}maxBuffers;buffers=new Map;start(e,t){Ce(this.buffers,this.maxBuffers),this.buffers.set(Y(e,t.pokeId),{baseCheckpoint:t.baseCheckpoint,bases:new Map,epoch:t.epoch,lastMutationId:new Map,parts:new Map,resets:new Set,undecodable:new Map})}part(e,t){const s=this.buffers.get(Y(e,t.pokeId));if(!s)return;const r=[];try{for(const o of t.rowsPatch)r.push(o.value===void 0?o:{...o,value:T(o.value)})}catch(o){s.undecodable.set(t.shapeId,o);return}const n=s.parts.get(t.shapeId)??[];for(const o of r)n.push(o);s.parts.set(t.shapeId,n),t.lastMutationId!==void 0&&s.lastMutationId.set(t.shapeId,t.lastMutationId);const a=t.baseCheckpoint??s.baseCheckpoint;a!==void 0&&s.bases.set(t.shapeId,a),t.reset===!0&&s.resets.add(t.shapeId)}end(e,t){const s=Y(e,t),r=this.buffers.get(s);return r&&this.buffers.delete(s),r}clear(){this.buffers.clear()}}const Gr=(i,e,t)=>{const s=e.parts.get(i.id)??[],r=e.resets.has(i.id),n=e.bases.get(i.id),a=e.epoch!==void 0&&i.serverEpoch!==void 0&&e.epoch!==i.serverEpoch,o=n!==void 0&&i.serverCursor!==void 0&&i.serverCursor!==n;if(!r&&(a||o))return i.rows.clear(),i.serverCursor=void 0,i.serverEpoch=void 0,"reseed";r&&i.rows.clear(),Kr(i.rows,s),t.checkpoint!==void 0&&(i.serverCursor=t.checkpoint),t.epoch!==void 0&&(i.serverEpoch=t.epoch);const c=e.lastMutationId.get(i.id);return c!==void 0&&(i.lastMutationId=c),"applied"},ke=i=>{const e=[...i.rows.values()];for(const t of i.callbacks)try{t(e)}catch{}},$r=(i,e)=>{for(const[t,s]of e.undecodable){const r=i.get(t);r&&A(r.errorCallbacks,{code:"WIRE_DECODE_FAILED",message:`could not decode a poke for this shape — ${s instanceof Error?s.message:String(s)}`})}},te=(i,e)=>{i.lastMutationId=Math.max(i.lastMutationId??0,e)},se=(i,e=!1)=>{for(const t of i.checkpointCallbacks)t({checkpoint:i.serverCursor,mutationId:i.lastMutationId,...e&&{rowsFollow:!0}})},Re=(i,e,t)=>{i.serverBase=e,t.cursor!==void 0&&(i.serverCursor=t.cursor),t.epoch!==void 0&&(i.serverEpoch=t.epoch)},D=(i,e)=>i!==void 0&&i!==e,Vr=(i,e)=>e==="connected"&&i!=="connected"||e==="polling"&&i!=="connected"&&i!=="polling",zr=i=>{for(const e of i.activeSubscriptions())i.ensureSocket(e.shardKey),i.queueResubscribe(e);for(const e of i.queuedShardKeys())i.ensureSocket(e);i.broadcastStatus(i.computeStatus(),i.identityFingerprint())},Jr=i=>{i.closeConnections();const e=i.leader;e.status=void 0,e.wasEverConnected=!1},Yr=(i,e,t)=>{if(D(t,i.identityFingerprint()))return;const s=i.leader,r=Vr(s.status,e);s.status=e,e==="connected"&&(s.wasEverConnected=!0),i.emitConnectionStatus(),r&&i.flushOfflineQueues()},Xr=i=>{i.isLeader()&&i.broadcastStatus(i.computeStatus(),i.identityFingerprint())},Zr=(i,e,t,s,r,n)=>{if(D(n,i.identityFingerprint()))return;const a=i.subscription(e);a&&(i.dropCacheSeed(e),Re(a,t,s===void 0?{}:{cursor:s,epoch:r}),s!==void 0&&Z(a,s),P(a,t))},ei=(i,e,t,s)=>{if(D(s,i.identityFingerprint()))return;const r=i.subscription(e);r&&A(r.errorCallbacks,t)},ti=(i,e,t,s,r,n,a)=>{if(D(a,i.identityFingerprint()))return;const o=i.subscription(e);o&&(i.ackAndAdvanceCursor(o,t,s),r!==void 0&&n===i.clientIdentifier()&&te(o,r),se(o))},si=(i,e,t)=>i!==null||e&&t===null,ri=[xe],ii=100,Pe=1e4,ni=async(i,e,t,s)=>{const r=new AbortController,n=setTimeout(()=>{r.abort()},Pe);try{const a=await i(e,{body:t,credentials:"include",headers:s,method:"POST",signal:r.signal});return await a.text(),a.status}finally{clearTimeout(n)}},oi=Promise.resolve();class Fe{static MAX_POKE_BUFFERS=256;static createClientQuery(e,t){return{defaultValue:t,key:e}}url;wsUrl;adminHost={adminFetch:(...e)=>this.adminFetch(...e),assertOpen:()=>{this.assertOpen()}};clientQueryStore;wsToken;wsTokenGeneration=0;authBasePath;fetchImpl;WebSocketImpl;bookmark;reconnectOptions;connectTimeoutMs;heartbeatIntervalMs;managedSocketOptions;pollingFallbackAfterFailedAttempts;pollingFallbackIntervalMs;offlineQueue;outbox;clientId;shardCursors=new Map;defaultShardKey;readyResolved=!1;readyResolve;readyPromise;clientWatermarks=new Map;outboxMutationCounter=0;onPersistenceError;persistence;persistenceVersion;outboxLeaderRelease;queryCache;hydratedQueryCache=new Map;cacheSeededQueries=new Map;pendingCacheWrites=new Map;cacheFlushTimer;subscriptions=new w;tabCoordinator;leader={status:void 0,wasEverConnected:!1};connections=new Map;idleClosedShards=new Set;defaultConnectionContext;connectionContexts=new Map;connectionContextHolders=new Map;authToken=null;authSubject=void 0;subjectToken=null;sessionProbesInFlight=0;sessionProbeGeneration=0;identityQuestions=0;identityAnsweredAt=0;releaseSessionChangeListener;warnedIdentityDisagreement=!1;identityResolutionExpected=!1;identitySettled=!1;queuedIdentities=new Map;queuedOfflineShardKeys=new Set;closed=!1;authTokenListeners=new R;statusListeners=new R;roomFlushes=new Map;roomIdentityResets=new Set;tokenExpiredListeners=new R;identityChangeListeners=new R;retiredIdentities=0;authRefusalNotifiedFor;replayCredentials=new WeakMap;mutationSettledListeners=new R;pendingChangeListeners=new R;whisperHandlers=new Map;liveSocketGrants=new Map;liveControlChain=Promise.resolve();whisperJoins=new Map;nextLiveSocketId=0;lastStatus="idle";nextSubId=0;nextStreamId=0;streams=new Map;adminSocketTeardowns=new Set;supplementaryBounces=new Set;offlineFlushes=new Map;replayRetryState=new Map;replayRetryTimers=new Map;shapeSubscriptions=new Map;pokeAssembler=new jr(Fe.MAX_POKE_BUFFERS);nextShapeId=0;constructor(e){this.url=e.url,this.wsUrl=e.wsUrl??k(de(e.url),V),this.wsToken=e.wsToken;const t=e.authBasePath??Us;this.authBasePath=t.endsWith("/")?t.slice(0,-1):t,this.fetchImpl=e.fetch??(typeof fetch=="function"?fetch.bind(globalThis):void 0),this.WebSocketImpl=e.WebSocket??(typeof WebSocket=="function"?WebSocket:void 0),this.bookmark=e.bookmarkStorage??Be(),this.reconnectOptions=e.reconnect,this.heartbeatIntervalMs=e.heartbeatIntervalMs??gr,this.connectTimeoutMs=e.connectTimeoutMs??vr,this.managedSocketOptions={connectTimeoutMs:this.connectTimeoutMs,heartbeatIntervalMs:this.heartbeatIntervalMs,WebSocketImpl:this.WebSocketImpl},this.pollingFallbackIntervalMs=e.pollingFallback?.intervalMs??Tr,this.pollingFallbackAfterFailedAttempts=e.pollingFallback?.afterFailedAttempts??kr,this.defaultConnectionContext=e.connectionContext,this.persistence=st(e.persistence,e.outbox===void 0),this.persistenceVersion=e.persistenceVersion,this.queryCache=rt(e.queryCache),this.onPersistenceError=e.offlineQueue?.onPersistenceError,this.clientQueryStore=new Ke,e.crossTabSync?(this.tabCoordinator=this.createTabCoordinator(),this.tabCoordinator.start()):this.tabCoordinator=void 0,e.hydrateOnStart&&this.queryCache?this.readyPromise=new Promise(s=>{this.readyResolve=s}):(this.readyResolved=!0,this.readyPromise=oi),this.offlineQueue=new Ze(e.offlineQueue,{onEvict:(s,r)=>{this.emitItemSettled(s,"rejected",r),this.releaseIdleShard(s.shardKey)},onSizeChange:s=>{this.pendingChangeListeners.emit(s)},persistence:this.persistence,version:e.persistenceVersion}),this.outbox=e.outbox,this.clientId=e.clientId??`client-${pe()}`,this.persistence&&queueMicrotask(()=>{this.hydrateAsOutboxLeader()}),this.queryCache&&queueMicrotask(()=>{(async()=>{try{await this.hydrateQueryCache()}catch{}finally{this.readyResolved=!0,this.readyResolve?.()}})().catch(()=>{})}),"document"in globalThis&&(this.releaseSessionChangeListener=bt(async()=>{!this.closed&&this.authToken===null&&await this.getCurrentUser().catch(()=>{})}))}setAuthToken(e,t){const s=this.authToken!==e,r=this.identityFingerprint(),n=this.authSubject===void 0||this.subjectToken===this.authToken,a=this.subjectAwaitingReconfirm(),o=this.isKnownNobody(),c=this.authToken;this.authToken=e,this.applySubject(e,t);const d=this.identityFingerprint();d!==r&&(!s&&e!==null&&n?(this.restampQueuedIdentity(r,d),this.restampWatermarks(r,d),this.restampConnectionIdentity(r,d),this.reseedFromHydratedCache()):!s&&e===null&&r===null&&n&&!o?(this.restampWatermarks(r,d),this.restampConnectionIdentity(r,d),this.reseedFromHydratedCache()):(this.rejectQueuedForIdentityChange(r),this.warnRefreshWithoutSubject(c,e),si(r,o,e)&&this.evictPreviousIdentitySession()),this.restartTabCoordinatorForIdentity()),this.syncReadCacheToCredential(a),s&&this.authTokenListeners.emit(e),(d!==r||s||a)&&this.offlineQueue.size>0&&J(this.computeStatus())&&this.flushAllOfflineQueues()}getAuthToken(){return this.authToken}currentIdentity(){return this.identityFingerprint()}expectIdentityResolution(){this.identityResolutionExpected=!0}currentBaseline(e){return this.baselineCursorFor(e)}replayIdentityVerdict(e){const t=this.identityVerdict(e);if(t!=="match")return{verdict:t};const s=Object.freeze({});return this.replayCredentials.set(s,{authToken:this.authToken,stamp:e}),{credential:s,verdict:t}}clientIdentifier(){return this.clientId}confirmedMutationWatermark(e){return this.clientWatermarks.get(this.identityFingerprint()??"")?.get(e??"")??0}async callMutator(e,t,s){const r=s?.clientSeq;if(r!==void 0&&(!Number.isInteger(r)||r<=0))throw new y("INTERNAL",`callMutator: clientSeq must be a positive integer, got ${String(r)}`);const n=s?.shardKey??"",a=this.identityFingerprint();let o,c,d;try{c=await this.rpc(e,t,s?.shardKey,{captureBookmark:!0,clientId:this.clientId,clientSeq:r,onMutationAck:u=>{o=u}})}catch(u){if(!B(u))throw u;d=u}if(o!==void 0&&o>(this.clientWatermarks.get(a??"")?.get(n)??0)){let u=this.clientWatermarks.get(a??"");u===void 0&&(Ce(this.clientWatermarks,Ir),u=new Map,this.clientWatermarks.set(a??"",u)),u.set(n,o)}if(d!==void 0)throw d;return{applied:o===void 0||o===r,result:c}}onAuthTokenChange(e){return this.authTokenListeners.add(e)}onIdentityChange(e){return this.identityChangeListeners.add(e)}identityEpoch(){return this.retiredIdentities}async getCurrentUser(){if(this.identityResolutionExpected=!0,this.closed||!this.fetchImpl)return this.identitySettled=!0,null;const e={},t=this.authToken;this.authToken&&(e.authorization=`Bearer ${this.authToken}`),this.sessionProbesInFlight+=1,this.identityQuestions+=1,this.sessionProbeGeneration=this.identityQuestions;const s=this.sessionProbeGeneration;try{const r=await this.fetchImpl(k(this.url,`${this.authBasePath}${Ns}`),{credentials:"include",headers:e,method:"GET"});if(!r.ok)return this.identitySettled=!0,r.status===401&&this.adoptResolvedSubject(t,null,s),null;const a=(await r.json())?.user??null;return this.identitySettled=!0,this.adoptResolvedSubject(t,a,s),a}finally{this.releaseSessionProbe()}}setWsToken(e){this.wsToken!==e&&(this.wsToken=e,this.wsTokenGeneration+=1,this.resetRoomSends(),this.bounceShardSockets())}setConnectionContext(e,t={}){this.assertLeaderOwnedSurface("setConnectionContext");const s=l(t.shardKey);e===void 0?this.connectionContexts.delete(s):this.connectionContexts.set(s,e),this.refreshConnectionContext(s),e===void 0&&this.releaseIdleShard(t.shardKey)}acquireConnectionContext(e,t={}){if(this.followsAnotherTab())return()=>{};const s=l(t.shardKey),r={context:e},n=this.connectionContextHolders.get(s);n?n.push(r):this.connectionContextHolders.set(s,[r]),this.refreshConnectionContext(s);let a=!1;return()=>{if(a)return;a=!0;const o=this.connectionContextHolders.get(s);if(!o)return;const c=o.indexOf(r);c!==-1&&o.splice(c,1),o.length===0&&this.connectionContextHolders.delete(s),this.refreshConnectionContext(s),this.releaseIdleShard(t.shardKey)}}whisperSubscribe(e,t,s={}){this.assertLeaderOwnedSurface("whisperSubscribe");const r=l(s.shardKey);let n=this.whisperHandlers.get(r);n||(n=new Map,this.whisperHandlers.set(r,n));let a=n.get(e);const o=a===void 0;if(a||(a=new Set,n.set(e,a)),a.add(t),this.ensureSocket(s.shardKey),o){const c=this.getConnection(s.shardKey);c&&this.sendWhisperJoin(c,r,e)}return()=>{const c=this.whisperHandlers.get(r),d=c?.get(e);if(!d?.delete(t)||d.size>0)return;c?.delete(e),c?.size===0&&this.whisperHandlers.delete(r);const h=this.getConnection(s.shardKey);h&&v(h,{topic:e,type:"whisper_unsubscribe"}),this.releaseWhisperJoin(r,e),this.releaseIdleShard(s.shardKey)}}subscribeLiveTopic(e){const{onError:t,onEvent:s,shardKey:r,stream:n,topic:a}=e;if(a.length===0)throw new y("INTERNAL","LunoraClient: subscribeLiveTopic needs a non-empty topic");this.nextLiveSocketId+=1;const o=`ws-live-${String(this.nextLiveSocketId)}`,c=l(r),d=`/live/${n}/control`;let u=this.whisperSubscribe(a,()=>{},{shardKey:r});const m=()=>{const g=u;u=void 0,g?.()};let f=this.liveSocketGrants.get(c);f===void 0&&(f=new Map,this.liveSocketGrants.set(c,f)),f.set(o,{onError:t,onEvent:s,release:m,stream:n,topic:a});const p=this.getConnection(r)?.connectionId;p!==void 0&&this.grantWhenJoined(r,o,p);let S=!1;return()=>{if(S)return;S=!0;const g=this.liveSocketGrants.get(c),_=g?.delete(o)===!0;g?.size===0&&this.liveSocketGrants.delete(c);const I=this.getConnection(r)?.connectionId;_&&I!==void 0&&this.postLiveControl(d,r,{action:"unsubscribe",connectionId:I,stream:n,subscriptionId:o,topic:a}),m()}}whisper(e,t,s={}){return this.assertLeaderOwnedSurface("whisper"),this.sendEncodedWhisper(e,C(t??null,`whisper data for topic '${e}'`),s)}connectRoom(e,t,s={}){const r=`room:${e.name}`,n=this.whisperSubscribe(r,m=>{t.onMessage(m)},s);let a=!1;const o=[],c=()=>{o.length=0},d=()=>{for(;o.length>0&&this.roomSendsAdmitted(s.shardKey);){if(!this.sendEncodedWhisper(r,o[0],s))return;o.shift()}},h=l(s.shardKey),u=this.roomFlushes.get(h)??new Set;return u.add(d),this.roomFlushes.set(h,u),this.roomIdentityResets.add(c),{close:()=>{a=!0,o.length=0,u.delete(d),u.size===0&&this.roomFlushes.delete(h),this.roomIdentityResets.delete(c),n()},send:m=>{if(a||this.closed||this.WebSocketImpl===void 0)return!1;const f=C(m,`room message for '${r}'`),p=typeof structuredClone=="function"?structuredClone(f):JSON.parse(JSON.stringify(f));return d(),o.length===0&&this.roomSendsAdmitted(s.shardKey)&&this.sendEncodedWhisper(r,p,s)?!0:o.length>=ii?!1:(o.push(p),!0)}}}connectWebSocket(e,t,s={}){if(this.assertLeaderOwnedSurface("connectWebSocket"),this.WebSocketImpl===void 0||this.closed)return{close:()=>{},send:()=>{}};const r=o=>{try{o?.()}catch(c){console.error("[lunora] socket route handler threw",c)}};let n;const a=this.openSupplementarySocket(this.supplementaryUrl(e),{onClose:()=>{clearTimeout(n),r(t.onClose)},onMessage:o=>{let c;try{c=JSON.parse(typeof o.data=="string"?o.data:"")}catch{return}c.type==="message"&&(a.resetBackoff(),r(()=>{t.onMessage(T(c.data))}))},onOpen:()=>{clearTimeout(n);const o=a.socket();n=setTimeout(()=>{a.socket()===o&&a.resetBackoff()},ge),r(t.onOpen)},shardKey:s.shardKey});return{close:()=>{clearTimeout(n),a.close()},send:o=>{const c=JSON.stringify(C(o,`socket message for '${e}'`)),d=a.socket();if(d!==void 0)try{d.send(c)}catch{}}}}onTokenExpired(e){return this.tokenExpiredListeners.add(e)}connectionStatus(){return this.computeStatus()}onConnectionStatus(e){const t=this.statusListeners.add(e);return e(this.computeStatus()),t}pendingCount(){return this.offlineQueue.size}debug(){const e=[],t=this.clientWatermarks.get(this.identityFingerprint()??""),s=new Set([...this.connections.keys(),...t?.keys()??[]]);for(const n of s){const a=this.connections.get(n);e.push({confirmedMutationWatermark:t?.get(n)??0,hasSocket:a?.socket!==void 0,shardKey:n===""?void 0:n,wasEverConnected:a?.wasEverConnected??!1,wsState:a?.wsState??"idle"})}const r=this.subscriptions.all().map(n=>({acked:n.acked,functionPath:n.fn.__lunoraRef,id:n.id,kind:"query",lastMutationId:n.lastMutationId,pendingOptimisticLayers:n.optimisticLayers.length,serverCursor:n.serverCursor,shardKey:n.shardKey,subscriberCount:n.callbacks.size}));for(const n of this.shapeSubscriptions.values())r.push({acked:n.serverCursor!==void 0,functionPath:`shape:${n.name}`,id:n.id,kind:"shape",lastMutationId:n.lastMutationId,pendingOptimisticLayers:0,rowCount:n.rows.size,serverCursor:n.serverCursor,shardKey:n.shardKey,subscriberCount:n.callbacks.size});return{clientId:this.clientId,closed:this.closed,connectionStatus:this.computeStatus(),pendingWrites:this.offlineQueue.size,shards:e.toSorted((n,a)=>(n.shardKey??"").localeCompare(a.shardKey??"")),subscriptions:r.toSorted((n,a)=>n.functionPath.localeCompare(a.functionPath))}}onPendingChange(e){const t=this.pendingChangeListeners.add(e);return e(this.offlineQueue.size),t}onMutationSettled(e){return this.mutationSettledListeners.add(e)}getWebSocketImpl(){return this.WebSocketImpl}getClientQuery(e){return this.clientQueryStore.get(e)}setClientQuery(e,t){this.clientQueryStore.set(e,t)}subscribeClientQuery(e,t){return this.clientQueryStore.subscribe(e,t)}resetClientQuery(e){this.clientQueryStore.reset(e)}snapshotPrecondition(e,t,s){return it(this,e,t,s)}whenReady(){return this.readyPromise}get isReady(){return this.readyResolved}peekHydratedQuery(e,t,s){return this.peekHydratedQueryByKey(e,ce(t),s)}peekHydratedQueryByKey(e,t,s){if(!this.readyResolved)return;const r=O(e,t,s),n=this.hydratedQueryCache.get(r);if(n!==void 0)return this.cachedQueryMatchesIdentity(n)?n.value:void 0}peekActiveQuerySnapshot(e,t,s){const r=w.key(e,t,s),n=this.subscriptions.get(r);return{present:n!==void 0,value:n?.lastValue}}async query(e,t,s={}){return this.assertOpen(),await this.rpc(e.__lunoraRef,t,s.shardKey,{attachBookmark:!0})}async batch(e){return this.sendBatch(e)}async mutation(e,t,s={}){const{value:r}=await this.runMutation(e,t,s);return r}canQueueOffline(e){const{wasEverConnected:t}=this.connectionGateState(e);return this.WebSocketImpl!==void 0&&(t||this.offlineQueue.queueBeforeFirstConnect)}async action(e,t,s={}){return this.assertOpen(),await this.rpc(e.__lunoraRef,t,s.shardKey,{attachBookmark:!0,captureBookmark:!0})}async importRows(e,t,s={}){this.assertOpen();const r=Math.max(1,Math.trunc(s.chunkSize??500)),n=s.toArgs??(h=>({rows:h})),a=t.length;let o=0,c=0,d=0;for(let h=0;h<a;h+=r){const u=t.slice(h,h+r),m=d,{committed:f}=await this.runMutation(e,n(u),{...s.importId===void 0?{}:{mutationId:`${s.importId}:${String(m)}`},shardKey:s.shardKey});d+=1,o+=u.length,f&&(c+=u.length),s.onProgress?.({done:o,total:a})}return{chunks:d,imported:c,queued:o-c}}async shardTraffic(e){return Zs(this.adminHost,e)}async listScheduledJobs(){return sr(this.adminHost)}async schedulerStatus(){return rr(this.adminHost)}async cancelScheduledJob(e){return ir(this.adminHost,e)}async listDeadJobs(){return nr(this.adminHost)}async retryDeadJob(e){return or(this.adminHost,e)}async removeDeadJob(e){return ar(this.adminHost,e)}async listWorkflowInstances(e){return cr(this.adminHost,e)}async getWorkflowInstance(e){return dr(this.adminHost,e)}async setWorkflowInstanceStatus(e){return hr(this.adminHost,e)}subscribeScheduledJobs(e){if(this.assertOpen(),this.WebSocketImpl===void 0)return()=>{};const t=this.openSupplementarySocket(k(de(this.url),Ct),{onMessage:s=>{let r;try{r=JSON.parse(typeof s.data=="string"?s.data:"")}catch{return}r.type==="jobs"&&Array.isArray(r.records)&&(t.resetBackoff(),e(r.records.map(n=>oe(n))))}});return t.close}async listFunctions(){return Bs(this.adminHost)}async getCronJobs(){return Ds(this.adminHost)}async runCronJob(e){return Qs(this.adminHost,e)}async fetchOpenApi(){return Ws(this.adminHost)}async fetchArchitecture(){return qs(this.adminHost)}async fetchOpenRpc(){return Ks(this.adminHost)}async listStorageObjects(e={}){return ur(this.adminHost,e)}async deleteStorageObject(e,t){return lr(this.adminHost,e,t)}async listStorageBuckets(){return fr(this.adminHost)}async uploadStorageObject(e){return pr(this.adminHost,e)}async signedStorageUrl(e,t){return mr(this.adminHost,e,t)}async listGlobalTables(){return js(this.adminHost)}async readGlobalTablePage(e){return Gs(this.adminHost,e)}async facetGlobalColumn(e){return $s(this.adminHost,e)}async listVectorIndexes(){return yr(this.adminHost)}async queryVectorIndex(e){return Sr(this.adminHost,e)}async queryLogArchive(e={}){return er(this.adminHost,e)}async listKvNamespaces(){return Vs(this.adminHost)}async listKvKeys(e){return zs(this.adminHost,e)}async getKvValue(e){return Js(this.adminHost,e)}async putKvValue(e){return Ys(this.adminHost,e)}async deleteKvKey(e){return Xs(this.adminHost,e)}async listAuthUsers(e={}){this.assertOpen();const t=b(Gt,{filterField:e.filterField,filterValue:e.filterValue,limit:e.limit,offset:e.offset,search:e.search,searchField:e.searchField,sortBy:e.sortBy,sortDirection:e.sortDirection});return await this.adminFetch(t,"GET")}async createAuthUser(e){return this.assertOpen(),await this.adminFetch(Vt,"POST",e)}async setAuthUserRole(e){return this.assertOpen(),await this.adminFetch(zt,"POST",e)}async banAuthUser(e){return this.assertOpen(),await this.adminFetch(Jt,"POST",e)}async unbanAuthUser(e){return this.assertOpen(),await this.adminFetch(Yt,"POST",e)}async setAuthUserPassword(e){this.assertOpen(),await this.adminFetch(Xt,"POST",e)}async removeAuthUser(e){this.assertOpen(),await this.adminFetch(Zt,"POST",e)}async impersonateAuthUser(e){return this.assertOpen(),await this.adminFetch(es,"POST",e)}async revokeAuthSession(e){this.assertOpen(),await this.adminFetch(ts,"POST",e)}async revokeAuthUserSessions(e){this.assertOpen(),await this.adminFetch(ss,"POST",e)}async getAuthCapabilities(){return this.assertOpen(),await this.adminFetch(rs,"GET")}async updateAuthUser(e){return this.assertOpen(),await this.adminFetch(is,"POST",e)}async listAuthAccounts(e){return this.assertOpen(),await this.adminFetch(b(ns,{userId:e.userId}),"GET")}async unlinkAuthAccount(e){this.assertOpen(),await this.adminFetch(os,"POST",e)}async listAuthPasskeys(e){return this.assertOpen(),await this.adminFetch(b(as,{userId:e.userId}),"GET")}async deleteAuthPasskey(e){this.assertOpen(),await this.adminFetch(cs,"POST",e)}async disableAuthTwoFactor(e){this.assertOpen(),await this.adminFetch(ds,"POST",e)}async listAuthOrganizations(e={}){return this.assertOpen(),await this.adminFetch(b(hs,{limit:e.limit,offset:e.offset}),"GET")}async listAuthOrgMembers(e){this.assertOpen();const t=b(us,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async listAuthOrgInvitations(e){this.assertOpen();const t=b(ls,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async listAuthSignUpInvitations(e={}){this.assertOpen();const t=b(ys,{limit:e.limit,offset:e.offset});return await this.adminFetch(t,"GET")}async createAuthSignUpInvitation(e){return this.assertOpen(),await this.adminFetch(Ss,"POST",e)}async revokeAuthSignUpInvitation(e){this.assertOpen(),await this.adminFetch(bs,"POST",e)}async removeAuthOrgMember(e){this.assertOpen(),await this.adminFetch(fs,"POST",e)}async cancelAuthOrgInvitation(e){this.assertOpen(),await this.adminFetch(ps,"POST",e)}async getAuthConfig(){return this.assertOpen(),await this.adminFetch(ms,"GET")}async createAuthOrganization(e){return this.assertOpen(),await this.adminFetch(gs,"POST",e)}async updateAuthOrganization(e){return this.assertOpen(),await this.adminFetch(vs,"POST",e)}async deleteAuthOrganization(e){this.assertOpen(),await this.adminFetch(Ts,"POST",e)}async addAuthOrgMember(e){return this.assertOpen(),await this.adminFetch(ks,"POST",e)}async inviteAuthOrgMember(e){return this.assertOpen(),await this.adminFetch(Cs,"POST",e)}async setAuthOrgMemberRole(e){return this.assertOpen(),await this.adminFetch(ws,"POST",e)}async listAuthOrgTeams(e){this.assertOpen();const t=b(Es,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async createAuthOrgTeam(e){return this.assertOpen(),await this.adminFetch(As,"POST",e)}async updateAuthOrgTeam(e){return this.assertOpen(),await this.adminFetch(_s,"POST",e)}async removeAuthOrgTeam(e){this.assertOpen(),await this.adminFetch(Is,"POST",e)}async listAuthOrgTeamMembers(e){this.assertOpen();const t=b(Os,{limit:e.limit,offset:e.offset,teamId:e.teamId});return await this.adminFetch(t,"GET")}async addAuthOrgTeamMember(e){return this.assertOpen(),await this.adminFetch(Rs,"POST",e)}async removeAuthOrgTeamMember(e){this.assertOpen(),await this.adminFetch(Ps,"POST",e)}async listAuthOrgRoles(e){this.assertOpen();const t=b(Fs,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async createAuthOrgRole(e){return this.assertOpen(),await this.adminFetch(Ls,"POST",e)}async updateAuthOrgRole(e){return this.assertOpen(),await this.adminFetch(Ms,"POST",e)}async deleteAuthOrgRole(e){this.assertOpen(),await this.adminFetch(Hs,"POST",e)}async listAuthSessions(e={}){this.assertOpen();const t=b($t,{limit:e.limit,offset:e.offset,userId:e.userId});return await this.adminFetch(t,"GET")}subscribe(e,t,s,r={}){this.assertOpen();const n=t??{},a=w.key(e.__lunoraRef,n,r.shardKey);let o=this.subscriptions.get(a);const c=j(s),d=j(r.onError),h=j(r.onCheckpoint);if(!o){this.nextSubId+=1;const m=`sub_${this.nextSubId.toString()}`,f=ce(n),p=this.takeHydratedCache(e.__lunoraRef,f,r.shardKey);o={acked:!1,args:n,argsKey:f,callbacks:new Set,checkpointCallbacks:new Set,errorCallbacks:new Set,fn:e,id:m,lastValue:p?.value,optimisticLayers:[],serverBase:p?.value,serverCursor:p?.serverCursor,shardKey:r.shardKey,wireArgs:C(n,`args for '${e.__lunoraRef}'`),...p?.serverEpoch===void 0?{}:{serverEpoch:p.serverEpoch}},this.subscriptions.add(o),p!==void 0&&this.cacheSeededQueries.set(a,p)}if(o.callbacks.add(c),d&&o.errorCallbacks.add(d),h&&o.checkpointCallbacks.add(h),o.lastValue!==void 0)try{c(o.lastValue)}catch{}this.ensureSocket(r.shardKey),this.sendSubscribeIfOpen(o);const u=o;return()=>{u.callbacks.delete(c),d&&u.errorCallbacks.delete(d),h&&u.checkpointCallbacks.delete(h),u.callbacks.size===0&&(this.sendOrQueueUnsubscribe(u.shardKey,u.id,"unsubscribe"),this.returnCacheSeed(w.keyOf(u)),this.subscriptions.remove(u),this.releaseIdleShard(u.shardKey))}}subscribeShape(e,t,s={}){if(this.assertOpen(),this.followsAnotherTab()){const{onError:a}=s;return a!==void 0&&queueMicrotask(()=>{a({code:"NOT_IMPLEMENTED",message:"LunoraClient: `subscribeShape` is unavailable on a cross-tab follower tab. The `crossTabSync` channel only carries data from the leader tab outward and shape pokes are not part of that broadcast set, so this subscription could never resolve. Turn off `crossTabSync`, or use a `list`-backed collection, which IS relayed."})}),()=>{}}this.nextShapeId+=1;const r=`shape_${this.nextShapeId.toString()}`,n={args:e.args,callbacks:new Set([t]),errorCallbacks:s.onError?new Set([s.onError]):new Set,id:r,name:e.name,onCheckpoint:s.onCheckpoint,rows:new Map,shardKey:s.shardKey,wireArgs:e.args===void 0?void 0:C(e.args,`shape args for '${e.name}'`)};return this.shapeSubscriptions.set(r,n),this.ensureSocket(s.shardKey),this.sendShapeSubscribeIfOpen(n),()=>{this.shapeSubscriptions.delete(r),this.sendOrQueueUnsubscribe(n.shardKey,r,"shape_unsubscribe"),this.releaseIdleShard(n.shardKey)}}stream(e,t,s={}){if(this.assertOpen(),this.WebSocketImpl===void 0)throw new y("INTERNAL","LunoraClient: streams require a WebSocket implementation");this.nextStreamId+=1;const r=`stream_${this.nextStreamId.toString()}`,{shardKey:n}=s,a=t??{},{handle:o,iterable:c}=nt({maxBuffer:s.maxBuffer,onCancel:()=>{this.cancelStream(r,n)}});this.ensureSocket(n);const d=this.getConnection(n),h={id:r,query:{args:C(a,`stream args for '${e.__lunoraRef}'`),functionPath:e.__lunoraRef,shardKey:n},type:"stream"},u={durable:s.durable===!0,generation:void 0,handle:o,lastSeq:0,message:h,shardKey:n};this.streams.set(r,u);const m=d?.wsState==="open"&&v(d,h);if(!m&&d===void 0)return this.forgetStream(r),o.fail(new y("STREAM_DISCONNECTED","stream unavailable: this tab is not the cross-tab WebSocket leader, so it holds no socket to stream over")),c;if(!m){for(d.pendingStreams=d.pendingStreams??[];d.pendingStreams.length>=Er;){const p=d.pendingStreams.shift()?.id,S=p?this.streams.get(p):void 0;S&&(S.handle.fail(new y("STREAM_QUEUE_OVERFLOW","stream-start frame evicted while socket was unreachable")),this.forgetStream(p))}d.pendingStreams.push(h)}return c}httpStream(e,t,s={}){if(this.closed)throw new y("CLIENT_CLOSED","LunoraClient is closed");if(!this.fetchImpl)throw new y("INTERNAL","LunoraClient: no `fetch` implementation available");const r={...this.authToken?{authorization:`Bearer ${this.authToken}`}:{},...s.headers};return Ve(e,t,{baseUrl:this.url,fetch:this.fetchImpl,headers:r,maxBuffer:s.maxBuffer,signal:s.signal})}close(){this.closed=!0;for(const e of this.whisperJoins.keys())this.dropWhisperJoinWaiters(e);this.releaseSessionChangeListener?.(),this.releaseSessionChangeListener=void 0,this.outboxLeaderRelease?.(),this.outboxLeaderRelease=void 0;for(const e of this.streams.values())e.handle.fail(new y("CLIENT_CLOSED","LunoraClient closed"));this.streams.clear();for(const e of this.connections.values())this.teardownConnection(e);for(const e of this.adminSocketTeardowns)e();this.adminSocketTeardowns.clear(),this.supplementaryBounces.clear();for(const e of this.replayRetryTimers.values())clearTimeout(e);this.replayRetryTimers.clear(),this.replayRetryState.clear(),this.offlineQueue.clear(),this.queuedIdentities.clear(),this.cacheFlushTimer!==void 0&&(clearTimeout(this.cacheFlushTimer),this.cacheFlushTimer=void 0),this.pendingCacheWrites.size>0&&this.flushQueryCacheWrites().catch(()=>{}),this.authTokenListeners.clear(),this.statusListeners.clear(),this.tokenExpiredListeners.clear(),this.identityChangeListeners.clear(),this.mutationSettledListeners.clear(),this.pendingChangeListeners.clear(),this.whisperHandlers.clear(),this.liveSocketGrants.clear(),this.roomFlushes.clear(),this.roomIdentityResets.clear(),this.shapeSubscriptions.clear(),this.pokeAssembler.clear(),this.subscriptions.clear(),this.clientQueryStore.clear(),this.hydratedQueryCache.clear(),this.cacheSeededQueries.clear(),this.tabCoordinator?.stop(),this.tabCoordinator=void 0}assertOpen(){if(this.closed)throw new y("INTERNAL","LunoraClient is closed")}followsAnotherTab(){const e=this.tabCoordinator;if(e===void 0||e.isLeader())return!1;const t=e.leaderTabId;return t!==void 0&&t!==e.id}assertLeaderOwnedSurface(e){if(this.followsAnotherTab())throw new y("NOT_IMPLEMENTED",`LunoraClient: \`${e}\` is unavailable on a cross-tab follower tab. The \`crossTabSync\` channel only carries data from the leader tab outward, so this call could never reach the server. Turn off \`crossTabSync\`, or keep \`${e}\` on the leader tab.`)}clearConnectionTimers(e){clearTimeout(e.reconnectTimer),clearTimeout(e.connectTimer),clearTimeout(e.stableTimer),e.reconnectTimer=void 0,e.connectTimer=void 0,e.stableTimer=void 0}shardInUse(e){const t=s=>l(s)===e;return this.subscriptions.all().some(s=>t(s.shardKey))||[...this.shapeSubscriptions.values()].some(s=>t(s.shardKey))||[...this.streams.values()].some(s=>t(s.shardKey))||this.whisperHandlers.has(e)||this.connectionContexts.has(e)||this.connectionContextHolders.has(e)||this.offlineFlushes.has(e)||this.offlineQueue.hasPending(s=>t(s.shardKey))}releaseIdleShard(e){const t=l(e),s=this.connections.get(t);this.closed||t===""||s===void 0||(clearTimeout(s.idleTimer),s.idleTimer=setTimeout(()=>{s.idleTimer=void 0,!(this.closed||this.connections.get(t)!==s||this.shardInUse(t))&&(s.wasEverConnected&&this.idleClosedShards.add(t),this.teardownConnection(s),this.connections.delete(t),this.emitConnectionStatus())},wr))}forgetStream(e){const t=this.streams.get(e);this.streams.delete(e),t&&this.releaseIdleShard(t.shardKey)}teardownConnection(e){e.polling.stop();const t=l(e.shardKey);for(const[r,n]of this.streams)l(n.shardKey)===t&&(n.handle.fail(new y("STREAM_DISCONNECTED","stream terminated: the connection carrying it was torn down")),this.streams.delete(r));e.pendingStreams=void 0,e.pendingUnsubscribes=[],this.clearResubscribeQueue(e),this.clearConnectionTimers(e),clearTimeout(e.idleTimer),e.idleTimer=void 0,F(e);const{socket:s}=e;if(s){e.socket=void 0;try{s.close()}catch{}}e.wsState="closed"}createTabCoordinator(){const e=`lunora-bridge::${this.url}::${this.identityFingerprint()??"anon"}`,t={activeSubscriptions:()=>this.subscriptions.all(),broadcastStatus:(s,r)=>this.tabCoordinator?.broadcastConnectionStatus(s,r),closeConnections:()=>{for(const[s,r]of this.connections)this.teardownConnection(r),this.connections.delete(s)},computeStatus:()=>this.computeStatus(),emitConnectionStatus:()=>{this.emitConnectionStatus()},ensureSocket:s=>{this.ensureSocket(s)},flushOfflineQueues:()=>{this.flushAllOfflineQueues()},identityFingerprint:()=>this.identityFingerprint(),isLeader:()=>this.tabCoordinator?.isLeader()===!0,leader:this.leader,queueResubscribe:s=>{this.queueResubscribe(s)},queuedShardKeys:()=>this.queuedOfflineShardKeys,clientIdentifier:()=>this.clientId,dropCacheSeed:s=>{this.dropCacheSeed(s)},ackAndAdvanceCursor:(s,r,n)=>{this.ackAndAdvanceCursor(s,r,n)},subscription:s=>this.subscriptions.get(s)};return new je({channelName:e,onBecomeLeader:()=>{zr(t)},onStopBeingLeader:()=>{Jr(t)},onConnectionStatus:(s,r)=>{Yr(t,s,r)},onSubscriptionData:(s,r,n,a,o)=>{Zr(t,s,r,n,a,o)},onLeaderClaimAnswered:()=>{Xr(t)},onSubscriptionError:(s,r,n)=>{ei(t,s,r,n)},onSubscriptionSettled:(s,r,n,a,o,c)=>{ti(t,s,r,n,a,o,c)}})}async sendBatch(e,t){if(this.assertOpen(),!this.fetchImpl)throw new y("INTERNAL","LunoraClient: no `fetch` implementation available");if(e.length===0)return[];const s=await this.fetchImpl(k(this.url,$),{body:JSON.stringify({calls:e.map((o,c)=>({args:C(o.args??{},`args for batch call '${o.fn.__lunoraRef}'`),functionPath:o.fn.__lunoraRef,id:c,shardKey:o.shardKey}))}),headers:this.rpcRequestHeaders({attachBookmark:!0}),method:"POST",signal:t}),r=s.headers.get("x-d1-bookmark");r&&this.bookmark.set(r);let n;try{n=await s.json()}catch{throw new y("INTERNAL",`LunoraClient: batch response was not JSON (status ${s.status.toString()})`)}const a=x(n);if(!s.ok||a!==void 0&&!n.results)throw a!==void 0?Qe(a):new y("INTERNAL",`LunoraClient: batch request failed (status ${s.status.toString()})`);for(const o of n.results??[]){const c=o.body?.commitCursor;typeof o.id=="number"&&typeof c=="number"&&this.recordShardCursor(e[o.id]?.shardKey,c)}return br(n.results??[],e.length)}async runMutation(e,t,s){this.assertOpen();const r=t,n=s.mutationId??pe(),a=this.takeReplayCredential(s.replayCredential),o=s.replayBaseline===void 0?this.baselineCursorFor(s.shardKey):s.replayBaseline??void 0,{confirms:c,rollbacks:d}=this.applyOptimisticUpdates(e.__lunoraRef,r,s.shardKey,s.optimistic);s.optimisticUpdate&&this.applyOptimisticUpdate(s.optimisticUpdate,t,s.shardKey,d,c);const h=this.offlineFlushes.get(l(s.shardKey));h!==void 0&&await h;const{hasSocket:u,idleClosed:m,polling:f,wasEverConnected:p,wsState:S}=this.connectionGateState(s.shardKey),{queueBeforeFirstConnect:g}=this.offlineQueue,_=p||g,I=this.WebSocketImpl!==void 0&&_,Q=f||m,Le=S==="connecting"&&_&&!Q,Me=S!=="open"&&!u&&I&&!Q,He=I&&s.replayBaseline===void 0&&this.hasPendingWriteAhead(s.shardKey),ae=async()=>this.enqueueOfflineMutation(e,r,s.shardKey,o,n,d,c,s.precondition,s.mutationId,a?.stamp);if(Me||Le||He)return ae();let W;try{const L=await this.rpc(e.__lunoraRef,r,s.shardKey,{baselineSeq:o,captureBookmark:!0,...a?.flags,mutationId:n,onCommitCursor:q=>{W=q}});for(const q of c)q(W);return{committed:!0,value:L}}catch(L){if(Q&&I&&L instanceof TypeError&&be(r))return ae();throw this.settleFailedDirectWrite(L,W,c,d,a?.flags.authToken),L}}settleFailedDirectWrite(e,t,s,r,n){if(this.noteIdentityMismatch(e),n!==void 0&&this.noteReplayAuthRefusal(e,n),B(e)){for(const a of s)a(t);return}M(r)}async enqueueOfflineMutation(e,t,s,r,n,a,o,c,d,h){const u=h===void 0?this.identityFingerprint():h;if(this.outbox){this.outboxMutationCounter+=1;const f=this.outboxMutationCounter;try{await this.outbox.enqueue({args:t,baselineSeq:r,clientId:this.clientId,functionPath:e.__lunoraRef,idempotencyKey:d??`${this.clientId}:${String(f)}`,identity:u,mutationId:f,...a.length>0&&{onRejected:()=>{M(a)}},shardKey:s})}catch(p){throw M(a),p instanceof Error?p:new Error(String(p))}for(const p of o)p(void 0);return{committed:!1,value:void 0}}return{committed:!0,value:await new Promise((f,p)=>{const S={args:t,functionPath:e.__lunoraRef,liveAwaiter:!0,baselineSeq:r,id:n,clientId:this.clientId,identity:u,precondition:c,onCommit:g=>{for(const _ of o)_(g)},reject:g=>{this.queuedIdentities.delete(n),B(g)||M(a),p(g instanceof Error?g:new Error(String(g))),this.releaseIdleShard(s)},resolve:f,shardKey:s};this.offlineQueue.enqueue(S),this.queuedOfflineShardKeys.add(s),this.ensureSocket(s),S.id!==void 0&&this.queuedIdentities.set(S.id,u)})}}hasPendingWriteAhead(e){if(this.outbox)return this.outbox.pending?.()??!1;const t=l(e);return this.offlineQueue.hasPending(s=>l(s.shardKey)===t)}async hydratePersistedQueue(){try{const e=await this.offlineQueue.hydrate();for(const t of e)this.queuedOfflineShardKeys.add(t),this.ensureSocket(t)}catch{}}hydrateAsOutboxLeader(){const e=()=>{this.hydratePersistedQueue().catch(()=>{})},t=globalThis.navigator?.locks;if(!t){e();return}t.request(`lunora:outbox-leader:${this.url}`,()=>(this.closed||e(),new Promise(s=>{if(this.closed){s();return}this.outboxLeaderRelease=s}))).catch(e)}async hydrateQueryCache(){if(this.queryCache)try{const e=await this.queryCache.load(),t=new Map;for(const s of this.subscriptions.all())t.set(O(s.fn.__lunoraRef,s.argsKey,s.shardKey),s);for(const{key:s,...r}of e){if(et(this.persistenceVersion,r.version)){this.queryCache.remove(s).catch(()=>{});continue}const n=t.get(s);if(n&&this.cachedQueryMatchesIdentity(r)){this.seedSubscriptionFromCache(n,r);continue}this.hydratedQueryCache.set(s,r)}}catch{}}seedSubscriptionFromCache(e,t){e.serverBase!==void 0||e.lastValue!==void 0||!this.cachedQueryMatchesIdentity(t)||(e.serverBase=t.value,e.serverCursor=t.serverCursor,t.serverEpoch!==void 0&&(e.serverEpoch=t.serverEpoch),this.cacheSeededQueries.set(O(e.fn.__lunoraRef,e.argsKey,e.shardKey),t),P(e,t.value))}syncReadCacheToCredential(e){this.subjectAwaitingReconfirm()?this.revokeCacheSeededValues():e&&this.reseedFromHydratedCache()}dropCacheSeed(e){this.cacheSeededQueries.delete(e),this.hydratedQueryCache.delete(e)}returnCacheSeed(e){const t=this.cacheSeededQueries.get(e);t!==void 0&&(this.cacheSeededQueries.delete(e),this.hydratedQueryCache.set(e,t))}revokeCacheSeededValues(){if(this.cacheSeededQueries.size!==0){for(const[e,t]of this.cacheSeededQueries){const s=this.subscriptions.get(e);s!==void 0&&(s.serverBase=void 0,s.serverCursor=void 0,s.serverEpoch=void 0,P(s,void 0)),this.hydratedQueryCache.set(e,t)}this.cacheSeededQueries.clear()}}takeHydratedCache(e,t,s){const r=O(e,t,s),n=this.hydratedQueryCache.get(r);if(!(n===void 0||!this.cachedQueryMatchesIdentity(n)))return this.hydratedQueryCache.delete(r),n}reseedFromHydratedCache(){if(this.hydratedQueryCache.size!==0)for(const e of this.subscriptions.all()){const t=O(e.fn.__lunoraRef,e.argsKey,e.shardKey),s=this.hydratedQueryCache.get(t);s!==void 0&&this.cachedQueryMatchesIdentity(s)&&(this.hydratedQueryCache.delete(t),this.seedSubscriptionFromCache(e,s))}}persistQueryValue(e){const t=e.serverBase;if(!this.queryCache||t===void 0)return;const s=O(e.fn.__lunoraRef,e.argsKey,e.shardKey),r=this.getConnection(e.shardKey)?.identity,n=r===void 0?this.identityFingerprint():r;n===null&&this.identityUnresolved()||(this.pendingCacheWrites.set(s,{identity:n,serverCursor:e.serverCursor,ts:Date.now(),value:t,...n===this.identityFingerprint()&&!this.subjectAwaitingReconfirm()?this.credentialStamp():{},...e.serverEpoch===void 0?{}:{serverEpoch:e.serverEpoch},...this.persistenceVersion===void 0?{}:{version:this.persistenceVersion}}),this.cacheFlushTimer??=setTimeout(()=>{this.flushQueryCacheWrites().catch(()=>{})},Cr))}async flushQueryCacheWrites(){this.cacheFlushTimer=void 0;const{queryCache:e}=this;if(!e){this.pendingCacheWrites.clear();return}const t=[...this.pendingCacheWrites.entries()];this.pendingCacheWrites.clear(),await Promise.allSettled(t.map(async([s,r])=>e.put(s,r)))}computeStatus(){if(this.tabCoordinator&&!this.tabCoordinator.isLeader())return this.leader.status??"idle";const e=[...this.connections.values()];return e.length===0?"idle":e.some(t=>t.wsState==="open")?"connected":e.some(t=>t.polling.isPolling())?"polling":e.some(t=>t.wsState==="connecting")?"connecting":"offline"}baselineCursorFor(e){const t=l(e);let s;for(const r of this.subscriptions.all())l(r.shardKey)!==t||r.serverCursor===void 0||(s=s===void 0?r.serverCursor:Math.max(s,r.serverCursor));return s}async pollSubscriptions(e){const t=l(e),s=[];for(const o of this.subscriptions.all())l(o.shardKey)===t&&(be(o.args)?s.push(o):A(o.errorCallbacks,{code:"WIRE_ENCODE_FAILED",message:"could not encode this subscription's args for a poll"}));if(s.length===0)return this.probeOrigin();const r=Xe(),n=this.identityFingerprint();let a;try{a=await Te(async o=>this.sendBatch(s.map(c=>({args:c.args,fn:c.fn,shardKey:c.shardKey})),o))}catch(o){return!(o instanceof TypeError)}if(this.identityFingerprint()!==n)return!0;for(const[o,c]of s.entries()){const d=a[o];if(d!==void 0){if(!d.ok){A(c.errorCallbacks,{code:d.error.code,message:d.error.message});continue}this.handleDataMessage({data:N(d.value),id:c.id,type:"data"},r)}}return!0}async probeOrigin(){const{fetchImpl:e}=this;if(!e)return!1;try{return await Te(async t=>e(k(this.url,$),{body:JSON.stringify({calls:[]}),headers:this.rpcRequestHeaders({}),method:"POST",signal:t})),!0}catch{return!1}}emitConnectionStatus(){const e=this.computeStatus();e!==this.lastStatus&&(this.lastStatus=e,this.statusListeners.emit(e),this.tabCoordinator?.isLeader()&&this.tabCoordinator.broadcastConnectionStatus(e,this.identityFingerprint()))}emitItemSettled(e,t,s){this.mutationSettledListeners.emit({args:e.args,code:s===void 0?void 0:s.code,error:s,functionPath:e.functionPath,hadAwaiter:e.liveAwaiter??!1,id:e.id??"",shardKey:e.shardKey,status:t})}applyOptimisticUpdates(e,t,s,r){const n=[],a=[];if(!r)return{confirms:n,rollbacks:a};const o=w.key(e,t,s),c=this.subscriptions.get(o);if(c){const d=ze(c,r);d&&(n.push(d.confirm),a.push(d.rollback))}return{confirms:n,rollbacks:a}}applyOptimisticUpdate(e,t,s,r,n){const{confirms:a,rollbacks:o,store:c}=Je(this.subscriptions,s);try{e(c,t)}catch{M(o);return}r.push(...o),n.push(...a)}getConnection(e){return this.connections.get(l(e))}sendOrQueueUnsubscribe(e,t,s){const r=this.getConnection(e);r&&!v(r,{id:t,type:s})&&r.pendingUnsubscribes.push({id:t,type:s})}connectionGateState(e){if(this.tabCoordinator&&!this.tabCoordinator.isLeader()){let r="idle";return this.leader.status==="connected"?r="open":this.leader.status==="connecting"&&(r="connecting"),{hasSocket:!1,idleClosed:!1,polling:this.leader.status==="polling",wasEverConnected:this.leader.wasEverConnected,wsState:r}}const t=this.getConnection(e),s=t===void 0&&this.idleClosedShards.has(l(e));return{hasSocket:t?.socket!==void 0,idleClosed:s,polling:t?.polling.isPolling()??!1,wasEverConnected:t?.wasEverConnected??s,wsState:t?.wsState??"idle"}}getOrCreateConnection(e){const t=l(e);let s=this.connections.get(t);return s||(s={connectTimer:void 0,heartbeatTimer:void 0,lastFrameAt:0,pendingUnsubscribes:[],polling:Lr({afterFailedAttempts:this.pollingFallbackAfterFailedAttempts,intervalMs:this.pollingFallbackIntervalMs,onReachable:()=>{this.flushOfflineQueue(e).catch(()=>{})},onStateChange:()=>{this.emitConnectionStatus()},poll:async()=>this.pollSubscriptions(e)}),reconnect:me(this.reconnectOptions),reconnectTimer:void 0,resubscribePending:new Map,resubscribeQueue:[],shardKey:e,socket:void 0,stableTimer:void 0,wasEverConnected:this.idleClosedShards.delete(t),wsState:"idle"},this.connections.set(t,s)),s}openSupplementarySocket(e,t){if(this.WebSocketImpl===void 0||this.closed)return{close:()=>{},resetBackoff:()=>{},socket:()=>{}};const s=me(this.reconnectOptions),r={connectTimer:void 0,heartbeatTimer:void 0,lastFrameAt:0,socket:void 0};let n,a=!1;const o=()=>{a||this.closed||(n=setTimeout(h,s.next()))},c=f=>{a||this.WebSocketImpl===void 0||ve(r,this.wsUrlFor(t.shardKey,f,e),this.managedSocketOptions,{onClose:()=>{o(),t.onClose?.()},onMessage:t.onMessage,...t.onOpen===void 0?{}:{onOpen:t.onOpen}})},d=async f=>{const p=this.wsTokenGeneration;let S;try{S=await f()}catch{o();return}if(p!==this.wsTokenGeneration){h();return}c(S)},h=()=>{if(a||this.WebSocketImpl===void 0)return;const{wsToken:f}=this;if(typeof f=="function"){d(f).catch(()=>{});return}c(f)};h();const u=()=>{a=!0,n!==void 0&&(clearTimeout(n),n=void 0),r.connectTimer!==void 0&&(clearTimeout(r.connectTimer),r.connectTimer=void 0),F(r);const{socket:f}=r;r.socket=void 0;try{f?.close()}catch{}};this.adminSocketTeardowns.add(u);const m=()=>{const{socket:f}=r;if(f!==void 0){r.socket=void 0,r.connectTimer!==void 0&&(clearTimeout(r.connectTimer),r.connectTimer=void 0),F(r);try{f.close()}catch{}t.onClose?.(),o()}};return this.supplementaryBounces.add(m),{close:()=>{u(),this.adminSocketTeardowns.delete(u),this.supplementaryBounces.delete(m)},resetBackoff:()=>{s.reset()},socket:()=>r.socket}}supplementaryUrl(e){const t=he(this.wsUrl),s=t.pathname.endsWith(V)?t.pathname.slice(0,-V.length):t.pathname;return t.pathname=k(s,e),ue(t,this.wsUrl)}wsUrlFor(e,t,s=this.wsUrl){if(e===void 0&&t===void 0)return s;const r=he(s),n=new Set([...e===void 0?[]:["shard"],...t===void 0?[]:["token"]]),a=[...r.searchParams].filter(([o])=>!n.has(o)).map(([o,c])=>`${encodeURIComponent(o)}=${encodeURIComponent(c)}`);return e!==void 0&&a.push(`shard=${encodeURIComponent(e)}`),t!==void 0&&a.push(`token=${encodeURIComponent(t)}`),r.search=a.join("&"),ue(r,s)}rpcRequestHeaders(e,t){const s={"content-type":"application/json"};e.expectSubject!==void 0&&(s[dt]=ht(e.expectSubject));const r=this.shardCursors.get(this.cursorKeyFor(t));r!==void 0&&(s["x-lunora-min-seq"]=r.toString());const n=e.authToken===void 0?this.authToken:e.authToken;if(n&&(s.authorization=`Bearer ${n}`),e.mutationId&&(s["x-lunora-mutation-id"]=e.mutationId),(e.clientId!==void 0||e.mutationId!==void 0)&&(s["x-lunora-client-id"]=e.clientId??this.clientId),e.clientSeq!==void 0&&(s["x-lunora-client-seq"]=e.clientSeq.toString()),e.baselineSeq!==void 0&&(s["x-lunora-base-seq"]=e.baselineSeq.toString()),e.attachBookmark){const a=this.bookmark.get();a&&(s["x-d1-bookmark"]=a)}return s}async rpc(e,t,s,r={}){if(!this.fetchImpl)throw new U("LunoraClient: no `fetch` implementation available");const n=this.rpcRequestHeaders(r,s),a=r.authToken===void 0?this.authToken:r.authToken,o=await this.fetchImpl(k(this.url,gt),{body:JSON.stringify({args:C(t,`args for '${e}'`),functionPath:e,shardKey:s}),headers:n,method:"POST"});if(r.captureBookmark){const u=o.headers.get("x-d1-bookmark");u&&this.bookmark.set(u)}let c;try{c=await o.json()}catch{throw H(o.status,o.statusText,o.headers.get("retry-after"))}const d=c;if(typeof d!="object"||d===null||Array.isArray(d))throw H(o.status,o.statusText,o.headers.get("retry-after"));const h=x(c);if(h!==void 0)throw le(h,o.headers.get("retry-after"));if(!o.ok)throw H(o.status,o.statusText,o.headers.get("retry-after"));r.onMutationAck?.(c.lastMutationId),r.onCommitCursor?.(c.commitCursor),this.noteCredentialAccepted(a),this.learnDefaultShardKey(o,s),this.recordShardCursor(s,c.commitCursor);try{return T(c.result)}catch(u){throw Oe(u)}}async adminFetch(e,t,s,r){if(!this.fetchImpl)throw new y("INTERNAL","LunoraClient: no `fetch` implementation available");const n={};this.authToken&&(n.authorization=`Bearer ${this.authToken}`);const a=s instanceof ArrayBuffer||s instanceof Blob;let o;s===void 0?o=void 0:a?(o=s,r!==void 0&&(n["content-type"]=r)):(o=JSON.stringify(s),n["content-type"]="application/json");const c=await this.fetchImpl(k(this.url,e),{body:o,headers:n,method:t});let d;try{d=await c.json()}catch{const u=c.statusText?` ${c.statusText}`:"";throw new y("INTERNAL",`LunoraClient: response was not JSON (status ${c.status.toString()}${u})`)}const h=x(d);if(h!==void 0){const u=new Error(h.message??"admin request failed");throw Object.assign(u,{code:h.code},We(h)),u}if(!c.ok){const u=c.statusText?` ${c.statusText}`:"";throw new y("INTERNAL",`LunoraClient: admin request failed (status ${c.status.toString()}${u})`)}return d}effectiveConnectionContext(e){const t=this.connectionContextHolders.get(e);return t&&t.length>0?t[t.length-1]?.context:this.connectionContexts.get(e)??this.defaultConnectionContext}refreshConnectionContext(e){const t=this.connections.get(e);t?.wsState==="open"&&this.sendConnectEnvelope(t)}sendConnectEnvelope(e){const t=this.effectiveConnectionContext(l(e.shardKey));v(e,{caps:ri,clientId:this.clientId,id:"connect",type:"connect",...t===void 0?{}:{context:t}})}resendShapeSubscriptions(e){for(const t of this.shapeSubscriptions.values())l(t.shardKey)===l(e)&&this.sendShapeSubscribeIfOpen(t)}ensureSocket(e){if(this.closed||this.WebSocketImpl===void 0||this.tabCoordinator&&!this.tabCoordinator.isLeader())return;const t=this.getOrCreateConnection(e);if(!(t.wsState==="open"||t.wsState==="connecting")){if(t.wsState="connecting",this.emitConnectionStatus(),typeof this.wsToken=="function"){this.openSocketWithProvidedToken(t,e,this.wsToken).catch(()=>{});return}this.openSocket(t,e,this.wsToken)}}async openSocketWithProvidedToken(e,t,s){const r=this.wsTokenGeneration;let n;try{n=await s()}catch{this.handleDisconnect(e);return}if(!(this.closed||this.WebSocketImpl===void 0||e.wsState!=="connecting"||e.socket!==void 0)){if(r!==this.wsTokenGeneration){typeof this.wsToken=="function"?await this.openSocketWithProvidedToken(e,t,this.wsToken):this.openSocket(e,t,this.wsToken);return}this.openSocket(e,t,n)}}openSocket(e,t,s){this.WebSocketImpl!==void 0&&(e.identity=this.identityFingerprint(),s===void 0&&this.authToken===null?(this.identityQuestions+=1,e.identityQuestion=this.identityQuestions):e.identityQuestion=void 0,e.retired=!1,ve(e,this.wsUrlFor(t,s),this.managedSocketOptions,{onClose:r=>{r?.code===4001&&this.notifyTokenExpired(),this.handleDisconnect(e)},onMessage:r=>{e.retired!==!0&&this.handleServerMessage(r.data,t)},onOpen:()=>{e.wsState="open",e.wasEverConnected=!0,e.identityConfirmed=!1,e.connectionId=void 0,e.roomsRejoined=!1,e.polling.noteOpen(),clearTimeout(e.stableTimer),e.stableTimer=setTimeout(()=>{e.wsState==="open"&&e.reconnect.reset()},ge),this.emitConnectionStatus(),this.sendConnectEnvelope(e),this.markShardPendingAck(t),this.clearResubscribeQueue(e);for(const a of this.subscriptions.all())l(a.shardKey)===l(t)&&this.queueResubscribe(a);if(this.resendShapeSubscriptions(t),e.pendingUnsubscribes.length>0){const a=e.pendingUnsubscribes;e.pendingUnsubscribes=[];for(const{id:o,type:c}of a)v(e,{id:o,type:c});this.releaseIdleShard(t)}Or(e);const r=l(t),n=this.whisperHandlers.get(r);if(this.dropWhisperJoinWaiters(r),this.whisperJoins.set(r,new Map),n)for(const a of n.keys())this.sendWhisperJoin(e,r,a);e.roomsRejoined=!0,this.releaseRoomSends(t),this.flushOfflineQueue(t).catch(()=>{})}}))}cancelStream(e,t){const s=this.getConnection(t);s&&(s.pendingStreams=s.pendingStreams?.filter(r=>r.id!==e),v(s,{id:e,type:"unsubscribe"})),this.forgetStream(e)}handleDisconnect(e){if(this.closed||e.wsState==="idle"||e.wsState==="closed")return;e.wsState==="connecting"&&e.polling.noteFailedOpen(),F(e),this.clearConnectionTimers(e),e.socket=void 0,e.wsState="idle",e.connectionId=void 0,e.whisperAck=void 0,this.dropWhisperJoinWaiters(l(e.shardKey)),this.emitConnectionStatus(),this.markShardPendingAck(e.shardKey),this.clearResubscribeQueue(e);const t=new Set((e.pendingStreams??[]).map(r=>r.id));for(const[r,n]of this.streams)if(!(l(n.shardKey)!==l(e.shardKey)||t.has(r))){if(n.durable){const a={...n.message,...n.generation===void 0?{}:{generation:n.generation},sinceChunk:n.lastSeq};n.message=a,e.pendingStreams=[...(e.pendingStreams??[]).filter(o=>o.id!==r),a];continue}n.handle.fail(new y("STREAM_DISCONNECTED","stream terminated: WebSocket disconnected")),this.forgetStream(r)}if(this.WebSocketImpl===void 0)return;const s=e.reconnect.next();e.reconnectTimer=setTimeout(()=>{e.reconnectTimer=void 0,this.ensureSocket(e.shardKey)},s)}markShardPendingAck(e){const t=l(e);for(const s of this.subscriptions.all())l(s.shardKey)===t&&(s.acked=!1)}queueResubscribe(e){const t=this.getConnection(e.shardKey);t&&(t.resubscribeQueue.push(e),this.drainResubscribeQueue(t))}drainResubscribeQueue(e){for(;e.resubscribePending.size<Ar;){const t=e.resubscribeQueue.shift();if(!t)return;this.subscriptions.getById(t.id)&&this.sendSubscribeIfOpen(t)&&e.resubscribePending.set(t.id,setTimeout(()=>{this.releaseResubscribeSlot(e,t.id)},_r))}}releaseResubscribeSlot(e,t){const s=e.resubscribePending.get(t);s!==void 0&&(clearTimeout(s),e.resubscribePending.delete(t),this.drainResubscribeQueue(e))}clearResubscribeQueue(e){for(const t of e.resubscribePending.values())clearTimeout(t);e.resubscribePending.clear(),e.resubscribeQueue=[]}sendSubscribeIfOpen(e){const t=this.getConnection(e.shardKey);if(t?.wsState!=="open"||e.acked)return!1;const s=e.serverCursor!==void 0&&e.serverBase!==void 0;return v(t,{id:e.id,query:{args:e.wireArgs,functionPath:e.fn.__lunoraRef,table:e.fn.__lunoraRef,...s?{sinceSeq:e.serverCursor}:{},...s&&e.serverEpoch!==void 0?{sinceEpoch:e.serverEpoch}:{}},type:"subscribe"})}sendShapeSubscribeIfOpen(e){const t=this.getConnection(e.shardKey);t?.wsState==="open"&&v(t,{id:e.id,shape:{name:e.name,...e.wireArgs===void 0?{}:{args:e.wireArgs}},type:"shape_subscribe",...e.serverCursor===void 0?{}:{sinceCheckpoint:e.serverCursor},...e.serverEpoch===void 0?{}:{sinceEpoch:e.serverEpoch}})}handleServerMessage(e,t){const s=Pr(e);if(s===void 0)return;let r;try{r=JSON.parse(s)}catch{return}if(r.type!=="error"&&this.getConnection(t)?.reconnect.reset(),typeof r.id=="string"){const n=this.getConnection(t);n&&this.releaseResubscribeSlot(n,r.id)}switch(r.type){case"ack":{const n=this.subscriptions.getById(r.id);n&&(n.acked=!0);return}case"chunk":{const{data:n,generation:a,id:o,seq:c}=r,d=this.streams.get(o);d&&typeof c=="number"&&(d.lastSeq=c,typeof a=="number"&&(d.generation=a),d.durable=!0),d?.handle.push(T(n));return}case"complete":{this.handleCompleteMessage(r.id);return}case"data":case"delta":{this.handleDataMessage(r);return}case"error":{this.handleErrorMessage(r);break}case"identity":{this.handleIdentityFrame(r,t),this.adoptSocketConnectionId(r,t),this.confirmShardIdentity(t);break}case"live":{this.dispatchLive(r,t);break}case"pokeEnd":{this.handlePokeEnd(r,t);break}case"pokePart":{this.pokeAssembler.part(t,r);break}case"pokeStart":{this.pokeAssembler.start(t,r);break}case"resume":{this.handleResumeMessage(r);break}case"settled":{this.handleSettledMessage(r);break}case"whisper":{this.dispatchWhisper(r,t);break}case"whisper_subscribed":{this.acknowledgeWhisperJoin(l(t),r.topic);break}}}handleErrorMessage(e){const t=e.error?.code;if(t==="TOKEN_EXPIRED"){this.notifyTokenExpired();return}if(t==="STREAM_ID_IN_USE")return;const{id:s}=e,r=s===void 0?void 0:this.streams.get(s);if(r&&s!==void 0){r.handle.fail(qe(e)),this.forgetStream(s);return}const n=s===void 0?void 0:this.subscriptions.getById(s);if(n){const o=fe(e),c=this.identityFingerprint(),d=w.keyOf(n);A(n.errorCallbacks,o),this.tabCoordinator?.isLeader()&&this.tabCoordinator.broadcastSubscriptionError(d,o,c);return}const a=s===void 0?void 0:this.shapeSubscriptions.get(s);a&&A(a.errorCallbacks,fe(e))}handlePokeEnd(e,t){const s=this.pokeAssembler.end(t,e.pokeId);if(s){$r(this.shapeSubscriptions,s);for(const r of s.parts.keys()){const n=this.shapeSubscriptions.get(r);n&&!s.undecodable.has(r)&&this.applyPokePart(n,s,e)}}}applyPokePart(e,t,s){const r=Gr(e,t,s);if(ke(e),r==="reseed"){this.sendShapeSubscribeIfOpen(e);return}e.onCheckpoint?.({checkpoint:e.serverCursor,mutationId:e.lastMutationId})}resnapshotSubscription(e){e.acked=!1,e.serverCursor=void 0,e.serverEpoch=void 0,console.warn("[lunora] could not merge a row delta into the cached result; re-subscribing for a full snapshot"),this.sendSubscribeIfOpen(e)}handleDataMessage(e,t){const{id:s}=e,r=s?this.subscriptions.getById(s):void 0;if(!r)return;let n;try{n=Ue(e,r.serverBase)}catch(a){A(r.errorCallbacks,{code:"WIRE_DECODE_FAILED",message:`could not decode a server frame for this subscription — ${a instanceof Error?a.message:String(a)}`});return}if(n===Ne){this.resnapshotSubscription(r);return}if(this.dropCacheSeed(w.keyOf(r)),Re(r,n,{cursor:e.cursor,epoch:e.epoch}),e.lastMutationId!==void 0&&(te(r,e.lastMutationId),se(r,!0)),this.persistQueryValue(r),Z(r,r.serverCursor),t!==void 0&&Ye(r,t),P(r,n),this.tabCoordinator?.isLeader()){const a=w.keyOf(r);this.tabCoordinator.broadcastSubscriptionData(a,n,r.serverCursor,r.serverEpoch,this.identityFingerprint())}}handleResumeMessage(e){const t=this.subscriptions.getById(e.id);t&&this.ackAndAdvanceCursor(t,e.cursor,e.epoch)}handleSettledMessage(e){const t=this.subscriptions.getById(e.id);if(t&&(this.ackAndAdvanceCursor(t,e.cursor,e.epoch),e.lastMutationId!==void 0&&te(t,e.lastMutationId),se(t),this.tabCoordinator?.isLeader())){const s=w.keyOf(t);this.tabCoordinator.broadcastSubscriptionSettled(s,t.serverCursor,t.serverEpoch,t.lastMutationId,this.clientId,this.identityFingerprint())}}ackAndAdvanceCursor(e,t,s){e.acked=!0,(t!==void 0&&t!==e.serverCursor||s!==void 0&&s!==e.serverEpoch)&&(t!==void 0&&(e.serverCursor=t),s!==void 0&&(e.serverEpoch=s),this.persistQueryValue(e),Z(e,e.serverCursor)&&P(e,e.serverBase))}adoptSocketConnectionId(e,t){const s=this.getConnection(t);if(!(s===void 0||typeof e.connectionId!="string")){s.connectionId=e.connectionId,s.whisperAck=e.whisperAck===!0;for(const r of this.liveSocketGrants.get(l(t))?.keys()??[])this.grantWhenJoined(t,r,e.connectionId)}}grantWhenJoined(e,t,s){const r=l(e),n=this.liveSocketGrants.get(r)?.get(t);if(n===void 0)return;const{stream:a,topic:o}=n,c=()=>{this.liveSocketGrants.get(r)?.get(t)===void 0||this.getConnection(e)?.connectionId!==s||this.postLiveControl(`/live/${a}/control`,e,{action:"subscribe",connectionId:s,stream:a,subscriptionId:t,topic:o},h=>{this.refuseLiveGrant(e,t,h,s)})};this.getConnection(e)?.whisperAck===!0?this.whenWhisperJoined(r,o,c):c()}sendWhisperJoin(e,t,s){const r=this.whisperJoinState(t,s);r.pending+=1,r.joined=!1,v(e,{topic:s,type:"whisper_subscribe"})}acknowledgeWhisperJoin(e,t){const s=this.whisperJoins.get(e)?.get(t);if(s!==void 0&&(s.pending=Math.max(0,s.pending-1),!(s.pending>0))){s.joined=!0;for(const r of s.waiters.splice(0))clearTimeout(r.timer),r.run();this.releaseWhisperJoin(e,t)}}releaseWhisperJoin(e,t){if(this.whisperHandlers.get(e)?.has(t)===!0)return;const s=this.whisperJoins.get(e),r=s?.get(t);if(!(s===void 0||r===void 0||r.pending>0)){for(const n of r.waiters.splice(0))clearTimeout(n.timer);s.delete(t),s.size===0&&this.whisperJoins.delete(e)}}whenWhisperJoined(e,t,s){const r=this.whisperJoinState(e,t);if(r.joined){s();return}const n={run:s,timer:void 0};n.timer=setTimeout(()=>{r.waiters=r.waiters.filter(a=>a!==n),s()},Pe),r.waiters.push(n)}dropWhisperJoinWaiters(e){for(const t of this.whisperJoins.get(e)?.values()??[])for(const s of t.waiters.splice(0))clearTimeout(s.timer)}whisperJoinState(e,t){let s=this.whisperJoins.get(e);s===void 0&&(s=new Map,this.whisperJoins.set(e,s));let r=s.get(t);return r===void 0&&(r={joined:!1,pending:0,waiters:[]},s.set(t,r)),r}refuseLiveGrant(e,t,s,r){const n=l(e),a=this.liveSocketGrants.get(n),o=a?.get(t);a===void 0||o===void 0||this.getConnection(e)?.connectionId!==r||(a.delete(t),a.size===0&&this.liveSocketGrants.delete(n),o.release(),o.onError?.({status:s,topic:o.topic}))}postLiveControl(e,t,s,r){const{fetchImpl:n}=this;if(!n)return;const a=JSON.stringify(t===void 0?s:{...s,shardKey:t}),o=this.rpcRequestHeaders({},t);this.liveControlChain=this.liveControlChain.then(()=>ni(n,k(this.url,e),a,o)).then(c=>{c>=400&&c<500&&c!==404&&c!==401&&r?.(c)}).catch(()=>{})}dispatchLive(e,t){const s=this.liveSocketGrants.get(l(t));if(!s)return;const r=T(e.data);for(const n of s.values())if(!(n.stream!==e.stream||n.topic!==e.topic))try{n.onEvent(r)}catch{}}dispatchWhisper(e,t){const s=this.whisperHandlers.get(l(t))?.get(e.topic);if(!s)return;const r=T(e.data);for(const n of s)try{n(r,e.from)}catch{}}notifyTokenExpired(){this.tokenExpiredListeners.emit()}handleCompleteMessage(e){const t=this.streams.get(e);if(t){t.handle.complete(),this.forgetStream(e);return}const s=this.subscriptions.getById(e);s&&(s.acked=!1,A(s.errorCallbacks,{code:"SUBSCRIPTION_CANCELLED",message:"subscription was cancelled by the server"}))}unpersist(e){e&&this.persistence?.remove(e).catch(t=>{tt(this.onPersistenceError,"remove",t,e)})}identityFingerprint(){if(this.authSubject!==void 0)return this.authSubject===null?null:`subj:${this.authSubject}`;const e=this.authToken;return e===null?null:this.hashToken(e)}hashToken(e){let t=2166136261,s=5381;for(let r=0;r<e.length;r+=1){const n=e.charCodeAt(r);t^=n,t=Math.imul(t,16777619),s=Math.imul(s,33)+n}return`${e.length.toString(36)}:${(t>>>0).toString(36)}:${(s>>>0).toString(36)}`}credentialStamp(){const e=this.authToken;return e===null?{}:{credential:this.hashToken(e)}}cachedQueryMatchesIdentity(e){return this.identityFingerprint()===null&&this.identityUnresolved()?!1:!this.subjectAwaitingReconfirm()&&e.identity===this.identityFingerprint()||this.isSameCredentialUnderTokenHash(e.identity)?!0:e.credential!==void 0&&e.credential===this.credentialStamp().credential}isSameCredentialUnderTokenHash(e){if(e===null||e.startsWith("subj:"))return!1;const t=this.authToken;return t===null?!1:this.hashToken(t)===e}releaseSessionProbe(){this.sessionProbesInFlight-=1,!(this.identityUnresolved()||this.identityFingerprint()!==null)&&!this.closed&&this.offlineQueue.size>0&&J(this.computeStatus())&&this.flushAllOfflineQueues()}identityUnresolved(){return this.sessionProbesInFlight>0?!0:this.identityResolutionExpected&&!this.identitySettled}adoptResolvedSubject(e,t,s){if(!(this.closed||this.authToken!==e||s!==this.sessionProbeGeneration)){if(e===null){this.adoptCookieSubject(t?.id??null,s);return}t!==null&&this.setAuthToken(e,t.id)}}adoptCookieSubject(e,t){return this.closed||this.authToken!==null||t<this.identityAnsweredAt?!1:(this.identityAnsweredAt=t,this.identitySettled=!0,this.setAuthToken(null,e),!0)}sendEncodedWhisper(e,t,s){this.ensureSocket(s.shardKey);const r=this.getConnection(s.shardKey),n=r!==void 0&&v(r,{data:t,topic:e,type:"whisper"});return this.releaseIdleShard(s.shardKey),n}roomSendsAdmitted(e){const t=this.getConnection(e);return t?.wsState==="open"&&t.retired!==!0&&t.identityConfirmed===!0&&t.roomsRejoined===!0}releaseRoomSends(e){if(this.roomSendsAdmitted(e))for(const t of this.roomFlushes.get(l(e))??[])t()}confirmShardIdentity(e){const t=this.getConnection(e);t!==void 0&&(t.identityConfirmed=!0),this.releaseRoomSends(e)}handleIdentityFrame(e,t){const s=this.getConnection(t)?.identityQuestion,{subject:r}=e;s===void 0||r!==null&&typeof r!="string"||this.adoptCookieSubject(r,s)||!this.closed&&this.authToken===null&&(r===null?null:`subj:${r}`)!==this.identityFingerprint()&&this.evictPreviousIdentitySession()}applySubject(e,t){if(t!==void 0){this.authSubject=t,this.subjectToken=e;return}(e===null&&this.authSubject!==null||e!==null&&this.authSubject===null)&&(this.authSubject=void 0,this.subjectToken=null)}isKnownNobody(){return this.authSubject===null&&this.authToken===null}subjectAwaitingReconfirm(){return this.authSubject!==void 0&&this.authSubject!==null&&this.subjectToken!==this.authToken}stampOf(e){const t=e.id===void 0?void 0:this.queuedIdentities.get(e.id);return t===void 0?e.identity:t}warnRefreshWithoutSubject(e,t){e===null||t===null||this.authSubject!==void 0||this.authRefusalNotifiedFor!==this.hashToken(e)||console.warn("[lunora] setAuthToken replaced a token that was just refused for a queued write, with no subject: without one a refresh reads as a user switch, so the held writes were discarded (OFFLINE_IDENTITY_CHANGED). Pass the user id, e.g. setAuthToken(token, user.id), to keep them across a refresh.")}rejectQueuedForIdentityChange(e){const t=this.offlineQueue.drain(),s=[];for(const r of t){if(this.identityVerdict(this.stampOf(r))!=="mismatch"){s.push(r);continue}this.queuedIdentities.delete(r.id??""),this.unpersist(r.id);const n=new Error("offline mutation discarded: auth identity changed before replay");n.code="OFFLINE_IDENTITY_CHANGED",r.reject(n),this.emitItemSettled(r,"rejected",n)}this.offlineQueue.requeue(s),e!==null&&this.clearQueryCacheForIdentityChange()}restampConnectionIdentity(e,t){for(const s of this.connections.values())s.identity===e&&(s.identity=t)}restampQueuedIdentity(e,t){for(const[s,r]of this.queuedIdentities)r===e&&this.queuedIdentities.set(s,t);this.offlineQueue.restampIdentity(e,t)}restampWatermarks(e,t){const s=e??"",r=this.clientWatermarks.get(s);if(r===void 0)return;this.clientWatermarks.delete(s);const n=t??"",a=this.clientWatermarks.get(n);if(a===void 0)this.clientWatermarks.set(n,r);else for(const[o,c]of r)a.set(o,c)}clearQueryCacheForIdentityChange(){this.revokeCacheSeededValues(),this.cacheFlushTimer!==void 0&&(clearTimeout(this.cacheFlushTimer),this.cacheFlushTimer=void 0),this.pendingCacheWrites.clear(),this.hydratedQueryCache.clear(),this.queryCache?.clear().catch(()=>{})}evictPreviousIdentitySession(){this.resetRoomSends(),this.revokeCacheSeededValues();for(const e of this.subscriptions.all())e.serverBase=void 0,e.serverCursor=void 0,e.serverEpoch=void 0,e.acked=!1,P(e,void 0);for(const e of this.shapeSubscriptions.values())e.rows.clear(),e.serverCursor=void 0,e.serverEpoch=void 0,ke(e);this.bounceShardSockets(),this.retiredIdentities+=1,this.identityChangeListeners.emit()}restartTabCoordinatorForIdentity(){if(!this.tabCoordinator)return;const e=this.tabCoordinator.isLeader();this.tabCoordinator.stop(),this.tabCoordinator=this.createTabCoordinator(),this.tabCoordinator.start(),e&&this.tabCoordinator.promoteImmediately()}resetRoomSends(){for(const e of this.roomIdentityResets)e()}bounceShardSockets(){for(const e of this.connections.values())if(e.socket){e.retired=!0;try{e.socket.close()}catch{}}for(const e of this.supplementaryBounces)e()}flushAllOfflineQueues(){for(const e of this.queuedOfflineShardKeys)this.flushOfflineQueue(e).catch(()=>{})}async flushOfflineQueue(e){const t=l(e),s=this.offlineFlushes.get(t);if(s===void 0&&this.offlineQueue.size===0)return;const r=(async()=>{await(s??Promise.resolve());const{authToken:n}=this;try{await this.drainOfflineQueue(e,n)}catch{}!this.closed&&this.authToken!==n&&this.offlineQueue.size>0&&J(this.computeStatus())&&this.flushOfflineQueue(e).catch(()=>{})})();this.offlineFlushes.set(t,r),await r,this.offlineFlushes.get(t)===r&&(this.offlineFlushes.delete(t),this.releaseIdleShard(e))}async drainOfflineQueue(e,t){const s=this.offlineQueue.drainConflict();for(const h of s){this.unpersist(h.id),this.queuedIdentities.delete(h.id??"");const u=new Error("offline mutation skipped: precondition failed before replay");u.code="OFFLINE_PRECONDITION_FAILED",this.emitItemSettled(h,"rejected",u)}const r=l(e),n=this.offlineQueue.drain(h=>l(h.shardKey)===r);if(n.length===0)return;const a=[],o=[];for(const h of n){const u=this.replayGateVerdict(h);u==="send"?a.push(h):u==="hold"&&o.push(h)}if(this.offlineQueue.requeue(o),o.length>0&&this.subjectAwaitingReconfirm()&&(this.getCurrentUser().catch(()=>{}),this.noteHeldRetryDelay(e)),a.length===0){this.scheduleRateLimitedRetry(e);return}const c=this.encodableOrSettleTerminal(a);if(c.length===0){this.scheduleRateLimitedRetry(e);return}if(c.length===1){await this.replaySequential(c,e,t),this.scheduleRateLimitedRetry(e);return}const d=[];for(let h=0;h<c.length;h+=G){const u=c.slice(h,h+G),m=await this.replayBatched(u,e,t);if(d.push(...m.requeue),m.stop){d.push(...c.slice(h+G));break}}d.length>0&&this.offlineQueue.requeue(d),this.scheduleRateLimitedRetry(e)}noteHeldRetryDelay(e){const t=l(e),s=this.replayRetryState.get(t),r=(s?.attempts??0)+1;this.replayRetryState.set(t,{attempts:r,delayMs:Math.max(s?.delayMs??0,ee(r))})}noteReplayRetryDelay(e,t,s){const r=l(e),n=this.replayRetryState.get(r),a=(n?.attempts??0)+1,o=Br(t,a)??(s===null&&K(t)?ee(a):void 0);this.replayRetryState.set(r,{attempts:a,delayMs:o===void 0?n?.delayMs:Math.max(n?.delayMs??0,o)})}scheduleRateLimitedRetry(e){const t=l(e),s=this.replayRetryState.get(t),r=s?.delayMs;if(s===void 0||r===void 0||this.closed||this.offlineQueue.size===0){this.replayRetryState.delete(t);return}s.delayMs=void 0;const n=this.replayRetryTimers.get(t);n!==void 0&&clearTimeout(n),this.replayRetryTimers.set(t,setTimeout(()=>{this.replayRetryTimers.delete(t),this.flushOfflineQueue(e).catch(()=>{})},r))}encodableOrSettleTerminal(e){const t=[];for(const s of e)try{C(s.args,`args for '${s.functionPath}'`),t.push(s)}catch(r){this.settleReplayTerminal(s,r instanceof Error?r:new Error(String(r)))}return t}identityVerdict(e){if(this.subjectAwaitingReconfirm())return"unknown";const t=this.identityFingerprint();return t===null&&this.identityUnresolved()?"unknown":e===t||e!==void 0&&this.isSameCredentialUnderTokenHash(e)?"match":t===null?"unknown":"mismatch"}replayGateVerdict(e){const t=this.stampOf(e);if(t===void 0)return this.queuedIdentities.delete(e.id??""),"send";const s=this.identityVerdict(t);if(s==="unknown")return"hold";if(this.queuedIdentities.delete(e.id??""),s==="match")return"send";this.unpersist(e.id);const r=new Error("offline mutation skipped: auth identity changed before replay");return r.code="OFFLINE_IDENTITY_CHANGED",e.reject(r),this.emitItemSettled(e,"rejected",r),"reject"}settleReplaySuccess(e,t,s){this.unpersist(e.id),this.recordShardCursor(e.shardKey,s),e.onCommit?.(s),e.resolve(t),this.emitItemSettled(e,"committed")}cursorKeyFor(e){return e??this.defaultShardKey??""}learnDefaultShardKey(e,t){const s=e.headers.get("x-lunora-shard-key");if(s===null||t!==void 0||this.defaultShardKey===s)return;this.defaultShardKey=s;const r=this.shardCursors.get("");r!==void 0&&(this.shardCursors.set(s,Math.max(this.shardCursors.get(s)??0,r)),this.shardCursors.delete(""))}recordShardCursor(e,t){if(typeof t!="number")return;const s=this.cursorKeyFor(e);this.shardCursors.set(s,Math.max(this.shardCursors.get(s)??0,t))}shouldRequeueReplayFailure(e,t){return this.noteIdentityMismatch(e)?!0:this.noteReplayAuthRefusal(e,t)||Hr(e)}noteReplayAuthRefusal(e,t){if(!K(e))return!1;const s=this.hashToken(t??"");return t===this.authToken&&this.authRefusalNotifiedFor!==s&&(this.authRefusalNotifiedFor=s,this.notifyTokenExpired()),!0}noteCredentialAccepted(e){this.authRefusalNotifiedFor!==void 0&&this.authRefusalNotifiedFor===this.hashToken(e??"")&&(this.authRefusalNotifiedFor=void 0)}takeReplayCredential(e){if(e===void 0)return;const t=this.replayCredentials.get(e);if(t===void 0)throw new TypeError("LunoraClient: `replayCredential` must come from this client's `replayIdentityVerdict`, and is single use");return this.replayCredentials.delete(e),{flags:{authToken:t.authToken,...z(t.stamp,t.authToken)},stamp:t.stamp}}noteIdentityMismatch(e){if(e?.code!=="IDENTITY_MISMATCH")return!1;const t=this.identityFingerprint();return this.getCurrentUser().then(()=>{!this.warnedIdentityDisagreement&&this.identityFingerprint()===t&&(this.warnedIdentityDisagreement=!0,console.warn('[lunora] a replayed write was refused with IDENTITY_MISMATCH, but `/get-session` still names the same user. The worker\'s `resolveIdentity` must return the same `userId` as the better-auth `user.id`, and RPC requests must carry the session cookie (`credentials: "include"` on a cross-origin fetch).'))}).catch(()=>{}),!0}settleReplayUndecodable(e,t,s){this.unpersist(e.id),this.recordShardCursor(e.shardKey,s),e.onCommit?.(s),e.reject(t),this.emitItemSettled(e,"committed",t)}settleReplayTerminal(e,t){this.unpersist(e.id),e.reject(t),this.emitItemSettled(e,"rejected",t)}async replaySequential(e,t,s){for(let r=0;r<e.length;r+=1){const n=e[r];if(!n)continue;let a;try{const o=await this.rpc(n.functionPath,n.args,n.shardKey,{authToken:s,baselineSeq:n.baselineSeq,captureBookmark:!0,clientId:n.clientId??this.clientId,...z(n.identity,s),mutationId:n.id,onCommitCursor:c=>{a=c}});this.settleReplaySuccess(n,o,a)}catch(o){if(B(o)){this.settleReplayUndecodable(n,o,a);continue}if(!this.shouldRequeueReplayFailure(o,s)){this.settleReplayTerminal(n,o);continue}this.noteReplayRetryDelay(t,o,s),this.offlineQueue.requeue(e.slice(r));return}}}async replayBatched(e,t,s){if(!this.fetchImpl)return{requeue:e,stop:!0};const r=JSON.stringify({calls:e.map((d,h)=>({args:C(d.args,`args for '${d.functionPath}'`),baselineSeq:d.baselineSeq,functionPath:d.functionPath,id:h,clientId:d.clientId??this.clientId,mutationId:d.id,shardKey:d.shardKey}))});if(e.length>1&&Qr(r)>Dr)return await this.replayBatchedHalves(e,t,s);let n;try{n=await this.fetchImpl(k(this.url,$),{body:r,headers:this.rpcRequestHeaders({attachBookmark:!0,authToken:s,...z(e.find(d=>d.identity!==void 0)?.identity,s)}),method:"POST"})}catch{return{requeue:e,stop:!0}}const a=n.headers.get("x-d1-bookmark");if(a&&this.bookmark.set(a),n.status===413&&e.length>1)return await this.replayBatchedHalves(e,t,s);let o;const c=n.headers.get("retry-after");try{o=await n.json()}catch{return this.settleWholeBatchError(e,H(n.status,n.statusText,c),t,s)}if(!o.results){const d=x(o),h=d===void 0?H(n.status,n.statusText,c):le(d,c);return this.settleWholeBatchError(e,h,t,s)}return{requeue:this.settleReplayBatchSlots(e,o.results,t,s),stop:!1}}settleWholeBatchError(e,t,s,r){if(t instanceof U||t.code!==void 0&&this.shouldRequeueReplayFailure(t,r))return this.noteReplayRetryDelay(s,t,r),{requeue:e,stop:!0};for(const n of e)this.settleReplayTerminal(n,t);return{requeue:[],stop:!1}}async replayBatchedHalves(e,t,s){const r=Math.ceil(e.length/2),n=await this.replayBatched(e.slice(0,r),t,s);if(n.stop)return{requeue:[...n.requeue,...e.slice(r)],stop:!0};const a=await this.replayBatched(e.slice(r),t,s);return{requeue:[...n.requeue,...a.requeue],stop:a.stop}}settleReplayBatchSlots(e,t,s,r){const n=Wr(t),a=[];let o=!1,c=!1;for(const[d,h]of e.entries()){const u=qr(n.get(d));switch(u.kind){case"committed":{o=!0,this.settleReplaySuccess(h,u.value,u.commitCursor);break}case"errored":{c||=K(u.error),this.shouldRequeueReplayFailure(u.error,r)?(this.noteReplayRetryDelay(s,u.error,r),a.push(h)):this.settleReplayTerminal(h,u.error);break}case"unanswered":{a.push(h);break}default:o=!0,this.settleReplayUndecodable(h,u.error,u.commitCursor)}}return o&&!c&&this.noteCredentialAccepted(r),a}}export{Fe as LunoraClient};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{O as s,n,r as o}from"./offline-queue-D_fr-uQ3.mjs";export{s as OfflineQueue,n as nextId,o as reportPersistenceError};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
let d=0;const s="lunora-bridge",o=1e3,h=3e3;class l{bc;tabId;heartbeatInterval;leaderTimeout;knownLeader=void 0;leader=!1;running=!1;promotionPending=!1;lastHeartbeat=0;heartbeatTimer=void 0;leaderCheckTimer=void 0;onBecomeLeader;onStopBeingLeader;onConnectionStatus;onSubscriptionData;onLeaderClaimAnswered;onSubscriptionError;onSubscriptionSettled;constructor(t={}){if(d+=1,this.tabId=`tab_${String(d)}_${crypto.randomUUID()}`,this.heartbeatInterval=t.heartbeatInterval??o,this.leaderTimeout=t.leaderTimeout??h,this.onBecomeLeader=t.onBecomeLeader,this.onStopBeingLeader=t.onStopBeingLeader,this.onConnectionStatus=t.onConnectionStatus,this.onSubscriptionData=t.onSubscriptionData,this.onLeaderClaimAnswered=t.onLeaderClaimAnswered,this.onSubscriptionError=t.onSubscriptionError,this.onSubscriptionSettled=t.onSubscriptionSettled,typeof BroadcastChannel>"u"){this.bc=void 0;return}this.bc=new BroadcastChannel(t.channelName??s),this.bc.addEventListener("message",e=>{this.handleMessage(e.data)})}start(){if(!this.running){if(this.running=!0,this.bc===void 0){this.becomeLeader();return}this.broadcast({type:"claim-leadership",tabId:this.tabId,ts:Date.now()}),setTimeout(()=>{this.running&&this.knownLeader===void 0&&this.becomeLeader()},this.leaderTimeout),this.leaderCheckTimer=setInterval(()=>{this.checkLeaderHealth()},this.leaderTimeout),this.heartbeatTimer=setInterval(()=>{this.sendHeartbeat()},this.heartbeatInterval)}}stop(){this.running=!1,this.leader&&(this.broadcast({type:"yield-leadership",tabId:this.tabId}),this.leader=!1,this.knownLeader=void 0,this.onStopBeingLeader?.()),this.heartbeatTimer!==void 0&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=void 0),this.leaderCheckTimer!==void 0&&(clearInterval(this.leaderCheckTimer),this.leaderCheckTimer=void 0),this.bc?.close()}isLeader(){return this.leader}promoteImmediately(){this.running&&this.becomeLeader()}get leaderTabId(){return this.knownLeader}get id(){return this.tabId}get isRunning(){return this.running}broadcastSubscriptionData(t,e,i,a,r){this.leader&&this.broadcast({type:"subscription-data",tabId:this.tabId,key:t,data:e,...i===void 0?{}:{cursor:i},...a===void 0?{}:{epoch:a},...r===void 0?{}:{identity:r}})}broadcastSubscriptionError(t,e,i){this.leader&&this.broadcast({type:"subscription-error",tabId:this.tabId,key:t,error:e,...i===void 0?{}:{identity:i}})}broadcastSubscriptionSettled(t,e,i,a,r,n){this.leader&&this.broadcast({type:"subscription-settled",tabId:this.tabId,key:t,...e===void 0?{}:{cursor:e},...i===void 0?{}:{epoch:i},...a===void 0?{}:{lastMutationId:a},...r===void 0?{}:{clientId:r},...n===void 0?{}:{identity:n}})}broadcastConnectionStatus(t,e){this.leader&&this.broadcast({type:"connection-status",tabId:this.tabId,status:t,...e===void 0?{}:{identity:e}})}broadcast(t){this.bc?.postMessage(t)}handleMessage(t){switch(t.type){case"claim-leadership":{this.handleClaimLeadership(t);break}case"connection-status":{if(this.leader||t.tabId===this.tabId)break;this.onConnectionStatus?.(t.status,t.identity);break}case"heartbeat":{this.handleHeartbeat(t);break}case"subscription-data":{if(this.leader||t.tabId===this.tabId)break;this.onSubscriptionData?.(t.key,t.data,t.cursor,t.epoch,t.identity);break}case"subscription-error":{if(this.leader||t.tabId===this.tabId)break;this.onSubscriptionError?.(t.key,t.error,t.identity);break}case"subscription-settled":{if(this.leader||t.tabId===this.tabId)break;this.onSubscriptionSettled?.(t.key,t.cursor,t.epoch,t.lastMutationId,t.clientId,t.identity);break}case"yield-leadership":{this.knownLeader===t.tabId&&(this.knownLeader=void 0,this.running&&!this.leader&&this.claimAndPromote());break}}}handleClaimLeadership(t){if(t.tabId!==this.tabId){if(this.leader){this.broadcast({type:"heartbeat",tabId:this.tabId,ts:Date.now()}),this.onLeaderClaimAnswered?.();return}this.knownLeader===void 0&&t.tabId<this.tabId&&(this.knownLeader=t.tabId,this.lastHeartbeat=t.ts)}}handleHeartbeat(t){if(t.tabId!==this.tabId){if(this.leader){this.resolveLeaderVsLeaderTieBreak(t);return}this.lastHeartbeat=t.ts,this.knownLeader=t.tabId}}resolveLeaderVsLeaderTieBreak(t){t.tabId<this.tabId?(this.leader=!1,this.knownLeader=t.tabId,this.lastHeartbeat=t.ts,this.onStopBeingLeader?.()):this.broadcast({type:"heartbeat",tabId:this.tabId,ts:Date.now()})}becomeLeader(){this.leader||(this.leader=!0,this.knownLeader=this.tabId,this.lastHeartbeat=Date.now(),this.onBecomeLeader?.(),this.broadcast({type:"heartbeat",tabId:this.tabId,ts:Date.now()}))}sendHeartbeat(){this.leader&&this.broadcast({type:"heartbeat",tabId:this.tabId,ts:Date.now()})}checkLeaderHealth(){if(!this.running||this.leader)return;if(this.knownLeader===void 0){this.claimAndPromote();return}Date.now()-this.lastHeartbeat>this.leaderTimeout&&(this.knownLeader=void 0,this.claimAndPromote())}claimAndPromote(){this.promotionPending||(this.promotionPending=!0,this.broadcast({type:"claim-leadership",tabId:this.tabId,ts:Date.now()}),setTimeout(()=>{this.promotionPending=!1,this.running&&this.knownLeader===void 0&&this.becomeLeader()},this.leaderTimeout))}}export{l as TabCoordinator};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{c as t}from"./live-stream-ct8j7T75.mjs";import"./createReconnect-CjTmjJDH.mjs";export{t as connectLiveStream};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import{LunoraError as u}from"@lunora/errors";import{decodeWire as O}from"@lunora/wire";import{createReconnect as N}from"./createReconnect-CjTmjJDH.mjs";import{createStream as I}from"./DEFAULT_MAX_BUFFER-Bd-_iyiV.mjs";const S=/^ /u,L=/^\d+$/u,C=2147483647,H=10,$=1e3,R=t=>typeof t=="object"&&t!==null?JSON.stringify(t):String(t),x=t=>{let n="",e,a;const o=[];for(const r of t.split(`
|
|
2
|
-
`))if(r.startsWith("event:"))n=r.slice(6).replace(S,"");else if(r.startsWith("data:"))o.push(r.slice(5).replace(S,""));else if(r.startsWith("id:")){const s=r.slice(3).replace(S,"");s.includes("\0")||(e=s)}else if(r.startsWith("retry:")){const s=r.slice(6).replace(S,"");L.test(s)&&Number.isSafeInteger(Number(s))&&(a=Math.min(Number(s),C))}return{data:o.join(`
|
|
3
|
-
`),event:n,id:e,retry:a}},B=(t,n,e)=>{const a=n.params??{},o=t.path.split("/").map(c=>{if(!c.startsWith(":"))return c;const f=c.slice(1),i=a[f];if(i===void 0)throw new u("HTTP_STREAM_MISSING_PARAM",`httpStream: missing path param ":${f}" for route ${t.path}`);return encodeURIComponent(R(i))}).join("/"),r=new URLSearchParams;for(const[c,f]of Object.entries(n.searchParams??{}))f!==void 0&&r.set(c,R(f));const s=r.toString();return`${e.endsWith("/")?e.slice(0,-1):e}${o}${s===""?"":`?${s}`}`},k=(t,n)=>{if(t.event==="complete")return n.complete(),!0;if(t.event==="error"){let e={};try{e=JSON.parse(t.data)}catch{}const a=typeof e.message=="string"?e.message:"stream error",o=typeof e.code=="string"?e.code:"HTTP_STREAM_ERROR",r=new u(o,a);return typeof e.why=="string"&&(r.why=e.why),n.fail(r),!0}if((t.event===""||t.event==="message")&&t.data!=="")try{n.push(O(JSON.parse(t.data)))}catch{return n.fail(new u("HTTP_STREAM_BAD_CHUNK","httpStream: malformed SSE chunk (invalid JSON)")),!0}return!1},F=async(t,n,e)=>{const a=t.getReader(),o=new TextDecoder;let r="",s=!1;const h=i=>{let d=s?`\r${i}`:i;s=d.endsWith("\r"),s&&(d=d.slice(0,-1)),r+=d.replaceAll(`\r
|
|
4
|
-
`,`
|
|
5
|
-
`)},c=()=>{let i=r.indexOf(`
|
|
6
|
-
|
|
7
|
-
`);for(;i!==-1;){const d=x(r.slice(0,i));if(r=r.slice(i+2),e.onFrame?.(),d.id!==void 0&&e.onId?.(d.id),d.retry!==void 0&&e.onRetry?.(d.retry),k(d,n))return!0;i=r.indexOf(`
|
|
8
|
-
|
|
9
|
-
`)}return!1},f=()=>a.cancel().then(()=>{},()=>{});try{for(;;){const{done:i,value:d}=await a.read();if(i)break;if(h(o.decode(d,{stream:!0})),c())return await f(),!0}return h(o.decode()),c()}catch(i){throw await f(),i}},W=async(t,n)=>{n.aborted||await new Promise(e=>{let a;const o=()=>{clearTimeout(a),e()};a=setTimeout(()=>{n.removeEventListener("abort",o),e()},t),n.addEventListener("abort",o,{once:!0})})},j=(t,n)=>{if(typeof t!="object"||t===null)return;const{code:e,error:a,why:o}=t;if(!(typeof e!="string"||typeof a!="string"))return new u("HTTP_STREAM_STATUS",`httpStream: request failed (status ${n.toString()}, ${e}): ${a}`,{status:n,why:typeof o=="string"?o:void 0})},D=async(t,n)=>{let e;const a=new Promise(r=>{e=setTimeout(()=>{r(void 0)},$)}),o=t.json().catch(r=>{if(n.aborted)throw r});try{return await Promise.race([o,a])}finally{clearTimeout(e),await t.body?.cancel().catch(()=>{})}},U=(t,n)=>{const e=Object.entries(t??{}).filter(([a])=>n===void 0||a.toLowerCase()!=="last-event-id");return{accept:"text/event-stream",...Object.fromEntries(e),...n===void 0?{}:{"last-event-id":n}}},_=t=>t instanceof Error&&"code"in t?t:new u("HTTP_STREAM_TRANSPORT",t instanceof Error?t.message:String(t),{cause:t}),X=(t,n,e={})=>{const a=e.fetch??(typeof fetch=="function"?fetch.bind(globalThis):void 0);if(!a)throw new u("INTERNAL","httpStream: no `fetch` implementation available");const o=B(t,n??{},e.baseUrl??""),r=new AbortController;let s;e.signal&&(e.signal.aborted?r.abort():(s=()=>{r.abort()},e.signal.addEventListener("abort",s,{once:!0})));const h=()=>{s&&e.signal?.removeEventListener("abort",s)},{handle:c,iterable:f}=I({maxBuffer:e.maxBuffer,onCancel:()=>{r.abort()},onFail:()=>{r.abort()}}),i=e.reconnect??!1,d=N();let{lastEventId:v}=e,w,T=0;const g=()=>{d.reset(),T=0},y={},b=l=>{try{l()}catch(p){throw y.value={error:p},p}},A={onFrame:g,onId:l=>{b(()=>e.onEventId?.(l)),v=l},onRetry:l=>{b(()=>e.onRetry?.(l)),w=l}},P=async()=>{const l=U(e.headers,v),p=new u("HTTP_STREAM_INTERRUPTED","httpStream: stream ended without a complete frame");try{const m=await a(o,{headers:l,method:t.method,signal:r.signal});if(!m.ok){const M=await D(m,r.signal);c.fail(j(M,m.status)??new u("HTTP_STREAM_STATUS",`httpStream: request failed (status ${m.status.toString()})`,{status:m.status}));return}if(!m.body){c.fail(new u("HTTP_STREAM_NO_BODY","httpStream: response has no body"));return}return{completed:await F(m.body,c,A),error:p}}catch(m){if(r.signal.aborted){c.complete();return}if(y.value){const{error:E}=y.value;c.fail(E instanceof Error?E:new u("HTTP_STREAM_CALLBACK","httpStream: an onEventId/onRetry callback threw"));return}return{completed:!1,error:_(m)}}};return(async()=>{try{for(;;){if(r.signal.aborted){c.complete();return}const l=await P();if(!l)return;if(l.completed||!i||T>=H){l.completed||c.fail(l.error);return}T+=1,await W(w??d.next(),r.signal)}}finally{h()}})().catch(l=>{if(r.signal.aborted){c.complete();return}c.fail(_(l))}),f};export{X as httpStream};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const c=e=>new Promise((n,a)=>{e.addEventListener("success",()=>{n(e.result)}),e.addEventListener("error",()=>{a(e.error??new Error("IndexedDB request failed"))})}),E=(e,n,a,o)=>{let s;return()=>s||(s=new Promise((r,d)=>{const t=e.open(n,a);t.addEventListener("upgradeneeded",()=>{o(t.result)}),t.addEventListener("success",()=>{r(t.result)}),t.addEventListener("error",()=>{d(t.error??new Error("IndexedDB open failed"))})}),s)},u=(e,n)=>async(a,o)=>{const r=(await e()).transaction(n,a),d=await o(r.objectStore(n));return await new Promise((t,i)=>{r.addEventListener("complete",()=>{t()}),r.addEventListener("error",()=>{i(r.error??new Error("IndexedDB transaction failed"))}),r.addEventListener("abort",()=>{i(r.error??new Error("IndexedDB transaction aborted"))})}),d};export{E as a,u as c,c as p};
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import{decodeWire as B}from"@lunora/wire";import{createReconnect as G}from"./createReconnect-CjTmjJDH.mjs";const J="x-lunora-live-connection",q="live",ee=c=>`/live/${c}/connect`,I=c=>c===void 0?void 0:(...s)=>{c(...s)},F=/^ /u,K=1e4,z=c=>{const s=c.indexOf("?"),l=s===-1?c:c.slice(0,s);if(!l.endsWith("/connect"))throw new Error(`connectLiveStream: expected a connect URL ending in "/connect", got "${c}"`);return`${l.slice(0,-8)}/control${s===-1?"":c.slice(s)}`},Q=c=>{let s="message";const l=[];for(const h of c.split(`
|
|
2
|
-
`))h.startsWith("event:")?s=h.slice(6).trim():h.startsWith("data:")&&l.push(h.slice(5).replace(F,""));return l.length===0?void 0:{data:l.join(`
|
|
3
|
-
`),event:s}},te=(c,s={})=>{const l=s.fetch??fetch,h=z(c),D=s.maxDelayMs??3e4,O=G({initialDelayMs:s.retryDelay??1e3,maxDelayMs:D}),M=s.withCredentials===!0?"include":"same-origin",N=new URL(c,"https://lunora.invalid").searchParams.get("shard")??void 0,d=new Map,g=new Set;let f,v,L=!1,P=0;const U=()=>{let e;do P+=1,e=`live-${String(P)}`;while(d.has(e));return e},A=()=>L;let E,S;const R=new Promise((e,t)=>{E=e,S=t});R.catch(()=>{});const _={...s.headers},x=new Map,C=new Set,W=async e=>{const t=new AbortController,r=setTimeout(()=>{t.abort()},K);C.add(t);try{const n=await l(h,{body:JSON.stringify(N===void 0?e:{...e,shardKey:N}),credentials:M,headers:{"content-type":"application/json",..._},method:"POST",signal:t.signal});return await n.text(),n.status}catch{return}finally{clearTimeout(r),C.delete(t)}},T=(e,t)=>{const n=(x.get(e)??Promise.resolve()).then(()=>A()?void 0:W(t)),o=n.then(()=>{},()=>{});return x.set(e,o),o.then(()=>{x.get(e)===o&&x.delete(e)}).catch(()=>{}),n},j=(e,t)=>{for(const r of d.values())if(r.topic===e)for(const n of r.handlers)try{n(t)}catch{}for(const r of g)try{r({payload:t,topic:e})}catch{}},k=e=>{const t=Q(e);if(t?.event===q)try{const r=JSON.parse(t.data);j(r.topic,B(r.data))}catch{}},$=(e,t,r)=>{if(d.get(e)===t){d.delete(e);for(const n of t.errors)try{n({status:r,subscriptionId:e,topic:t.topic})}catch{}}},V=async()=>{const e=await Promise.all([...d].map(async([t,r])=>{const n=await T(t,{action:"subscribe",connectionId:f,subscriptionId:t,topic:r.topic});return{entry:r,id:t,status:n}}));for(const{entry:t,id:r,status:n}of e){if(n===void 0||n>=500||n===404||n===401){v?.abort();return}n>=400&&$(r,t,n)}},H=async e=>{f=e.headers.get(J)??void 0,O.reset();const r=(async()=>{try{await V()}catch{v?.abort();return}E?.(),E=void 0,S=void 0})(),n=e.body?.getReader();if(n===void 0){await r;return}const o=new TextDecoder;let a="",i=!1;for(;;){const{done:u,value:w}=await n.read();if(u)break;const y=o.decode(w,{stream:!0}),m=i?`\r${y}`:y;i=m.endsWith("\r"),a+=(i?m.slice(0,-1):m).replaceAll(`\r
|
|
4
|
-
`,`
|
|
5
|
-
`).replaceAll("\r",`
|
|
6
|
-
`);let b=a.indexOf(`
|
|
7
|
-
|
|
8
|
-
`);for(;b!==-1;)k(a.slice(0,b)),a=a.slice(b+2),b=a.indexOf(`
|
|
9
|
-
|
|
10
|
-
`)}await r};return(async()=>{for(;!A();){v=new AbortController;try{const t=await l(c,{credentials:M,headers:{accept:"text/event-stream",..._},signal:v.signal});if(!t.ok)throw new Error(`live stream connect failed: HTTP ${String(t.status)}`);await H(t)}catch{}if(f=void 0,A())return;const e=O.next();await new Promise(t=>{setTimeout(t,e)})}})().catch(()=>{}),{close:()=>{L=!0,v?.abort();for(const e of C)e.abort();C.clear(),d.clear(),g.clear(),S?.(new Error("connectLiveStream: closed before the first connection")),E=void 0,S=void 0},get connectionId(){return f},onEvent:e=>(g.add(e),()=>g.delete(e)),ready:R,subscribe:({id:e,onError:t,onEvent:r,topic:n})=>{if(L)throw new Error("connectLiveStream: subscribe on a closed stream");const o=e??U(),a=d.get(o);if(a!==void 0&&a.topic!==n)throw new Error(`connectLiveStream: subscription id "${o}" already follows "${a.topic}"; unsubscribe it first`);const i=a??{errors:new Set,handlers:new Set,refs:0,topic:n},u=I(r),w=I(t);if(i.refs+=1,u!==void 0&&i.handlers.add(u),w!==void 0&&i.errors.add(w),a===void 0&&(d.set(o,i),f!==void 0)){const m=f,b=v;T(o,{action:"subscribe",connectionId:m,subscriptionId:o,topic:n}).then(p=>{if(p===void 0||p===401||p===404||p>=500){m===f&&d.get(o)===i&&b?.abort();return}p>=400&&$(o,i,p)}).catch(()=>{})}let y=!1;return()=>{y||(y=!0,u!==void 0&&i.handlers.delete(u),w!==void 0&&i.errors.delete(w),i.refs-=1,!(i.refs>0||d.get(o)!==i)&&(d.delete(o),T(o,{action:"unsubscribe",connectionId:f,subscriptionId:o,topic:n}).catch(()=>{})))}}}};export{te as c,ee as l};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
let h=0;const d=()=>{if(typeof crypto<"u"&&typeof crypto.randomUUID=="function")return crypto.randomUUID();h+=1;const r=typeof crypto<"u"&&typeof crypto.getRandomValues=="function"?Array.from(crypto.getRandomValues(new Uint8Array(8)),t=>t.toString(16).padStart(2,"0")).join(""):Math.random().toString(16).slice(2,12);return`id_${Date.now().toString(36)}_${h.toString(36)}_${r}`},f=(r,t)=>r!==void 0&&t!==r,u=d,o=(r,t,e,i)=>{if(r)try{r({error:e,mutationId:i,operation:t});return}catch{}console.warn(`[lunora] offline-queue persistence ${t} failed`,e)};class l{queueBeforeFirstConnect;maxItems;onPersistenceError;persistence;onEvict;onSizeChange;version;items=[];constructor(t={},e={}){this.maxItems=t.maxItems??1e3,this.queueBeforeFirstConnect=t.queueBeforeFirstConnect??!1,this.onPersistenceError=t.onPersistenceError,this.persistence=e.persistence,this.onEvict=e.onEvict,this.onSizeChange=e.onSizeChange,this.version=e.version}get size(){return this.items.length}enqueue(t){const e=t;e.id??=u(),this.items.push(e),this.persistence?.append({args:e.args,...e.baselineSeq===void 0?{}:{baselineSeq:e.baselineSeq},clientId:e.clientId,functionPath:e.functionPath,id:e.id,identity:e.identity,shardKey:e.shardKey,...this.version===void 0?{}:{version:this.version}}).catch(i=>{o(this.onPersistenceError,"append",i,e.id)}),this.evictOverflow(),this.notifySize()}async hydrate(){if(!this.persistence)return[];let t;try{t=await this.persistence.load()}catch(s){throw o(this.onPersistenceError,"load",s),s}const e=[],i=new Set(this.items.map(s=>s.id));for(const s of t)if(!i.has(s.id)){if(f(this.version,s.version)){this.persistence.remove(s.id).catch(a=>{o(this.onPersistenceError,"remove",a,s.id)});continue}i.add(s.id),e.push({args:s.args,baselineSeq:s.baselineSeq,clientId:s.clientId,functionPath:s.functionPath,id:s.id,identity:s.identity,reject:()=>{},resolve:()=>{},shardKey:s.shardKey})}this.items.unshift(...e),this.evictOverflow(),this.notifySize();const n=new Set(this.items),c=new Set;for(const s of e)n.has(s)&&c.add(s.shardKey);return[...c]}restampIdentity(t,e){for(const i of this.items){if(i.identity!==t)continue;i.identity=e;const{id:n}=i;if(!this.persistence||n===void 0)continue;const c={args:i.args,...i.baselineSeq===void 0?{}:{baselineSeq:i.baselineSeq},clientId:i.clientId,functionPath:i.functionPath,id:n,identity:e,shardKey:i.shardKey,...this.version===void 0?{}:{version:this.version}};this.rewriteStamp(n,c).catch(s=>{o(this.onPersistenceError,"replace",s,n)})}}hasPending(t){return this.items.some(e=>t(e))}drain(t){if(!t){const n=[...this.items];return this.items.length=0,this.notifySize(),n}const e=[],i=[];for(const n of this.items)(t(n)?e:i).push(n);return this.items.length=0,this.items.push(...i),this.notifySize(),e}requeue(t){t.length!==0&&(this.items.unshift(...t),this.notifySize())}drainConflict(){const t=[],e=[];for(const i of this.items)if(i.precondition!==void 0&&!i.precondition()){const n=new Error("offline mutation skipped: precondition failed before replay");n.code="OFFLINE_PRECONDITION_FAILED",i.reject(n),t.push(i)}else e.push(i);return t.length>0&&(this.items.length=0,this.items.push(...e),this.notifySize()),t}clear(){for(const t of this.items){const e=new Error("CLIENT_CLOSED");e.code="CLIENT_CLOSED",t.reject(e)}this.items.length=0,this.notifySize()}async rewriteStamp(t,e){const i=this.persistence;if(i)try{await i.replace(e)}catch(n){o(this.onPersistenceError,"replace",n,t)}}evictOverflow(){for(;this.items.length>this.maxItems;){const t=this.items.shift();if(t){t.id&&this.persistence?.remove(t.id).catch(i=>{o(this.onPersistenceError,"remove",i,t.id)});const e=new Error("offline queue overflow");e.code="OFFLINE_QUEUE_OVERFLOW",t.reject(e),this.onEvict?.(t,e)}}}notifySize(){this.onSizeChange?.(this.items.length)}}export{l as O,f as i,u as n,o as r};
|