@lunora/client 1.0.0-alpha.137 → 1.0.0-alpha.138
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 +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/LunoraClient-Cj6Z6KeC.mjs +1 -0
- package/dist/packem_shared/createLocalStore-BmKEBUWU.mjs +1 -0
- package/dist/packem_shared/{createServerClient-CzDIXbC4.mjs → createServerClient-C0jOZaix.mjs} +1 -1
- package/dist/packem_shared/httpStream-BWdNJzId.mjs +9 -0
- package/dist/packem_shared/local-store-CWeFEk6w.mjs +1 -0
- package/dist/packem_shared/{lunora-client.d-Cqp1YHAJ.d.mts → lunora-client.d-DWo4CzIH.d.mts} +88 -16
- package/dist/packem_shared/{lunora-client.d-BiwicHKh.d.ts → lunora-client.d-WFeiiO0Z.d.ts} +88 -16
- package/dist/packem_shared/{preload.d-91KD5ae3.d.mts → preload.d-6E3-9j1g.d.mts} +1 -1
- package/dist/packem_shared/{preload.d-DE--vVCE.d.ts → preload.d-CVB-TzK6.d.ts} +1 -1
- package/dist/query/index.d.mts +2 -2
- package/dist/query/index.d.ts +2 -2
- 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 +2 -2
- package/dist/packem_shared/LunoraClient-BbpyxE38.mjs +0 -1
- package/dist/packem_shared/createLocalStore-BFdXRTFz.mjs +0 -1
- package/dist/packem_shared/httpStream-CPdblK2G.mjs +0 -11
- package/dist/packem_shared/local-store-BjenEm3t.mjs +0 -1
package/dist/auth/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-
|
|
1
|
+
import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-DWo4CzIH.mjs";
|
|
2
2
|
import '@lunora/errors';
|
|
3
3
|
import "../packem_shared/function-reference.d-Br_hsKje.mjs";
|
|
4
4
|
import '@lunora/runtime';
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-
|
|
1
|
+
import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-WFeiiO0Z.js";
|
|
2
2
|
import '@lunora/errors';
|
|
3
3
|
import "../packem_shared/function-reference.d-Br_hsKje.js";
|
|
4
4
|
import '@lunora/runtime';
|
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { c as PersistenceAdapter, Q as QueryCacheAdapter, B as BookmarkStorage, C as ConnectionStatus, S as SubscriptionError, H as HttpStreamRef, d as HttpStreamArgsOf, e as HttpStreamChunkOf, f as StreamIterable, O as OfflineQueueOptions, R as ReconnectOptions, L as LunoraClient } from "./packem_shared/lunora-client.d-
|
|
2
|
-
export { type A as ActionCallOptions, type g as BatchSlot, type h as CachedQuery, type i as ClientDebugShard, type j as ClientDebugSnapshot, type k as ClientDebugSubscription, type l as ClientMessage, type m as ClientQueryRef, type n as ClientShapeSubscribeMessage, type o as ClientShapeUnsubscribeMessage, D as DEFAULT_MAX_BUFFER, type F as FunctionArgumentDescriptor, type p as FunctionDescriptor, type G as GlobalFacetResult, type q as GlobalFacetValue, type r as GlobalFilterClause, type s as GlobalTableInfo, type t as GlobalTablePage, type u as HttpStreamCallArgs, type v as LunoraClientError, type w as LunoraClientOptions, type M as MutationCallOptions, type x as MutationSettledEvent, type y as OptimisticLocalStore, type z as OptimisticUpdate, type E as OutboxMutation, type I as OutboxSink, type J as PersistedMutation, type P as Preloaded, type K as RowOp, type N as RpcEnvelope, type T as RpcResponseBody, type V as ScheduleRecord, type W as ScheduleRetryPolicy, type X as SchedulerPoolStatus, type Y as SchedulerStatus, type Z as ServerMessage, type _ as ServerPokeEndMessage, type $ as ServerPokePartMessage, type a0 as ServerPokeStartMessage, type a1 as ShardTrafficEntry, type a2 as ShardTrafficResult, type a3 as StorageListPage, type a4 as StorageObject, type a5 as StoredQuery, type a6 as StreamHandle, type a7 as SubscriptionCallback, type b as SubscriptionErrorCallback, a8 as SubscriptionRegistry, type a9 as SubscriptionState, type aa as SyncWatermark, type a as Unsubscribe, type U as User, type ab as WorkflowInstanceAction, type ac as WorkflowInstanceDetail, type ad as WorkflowInstancePage, type ae as WorkflowInstanceStatus, type af as WorkflowInstanceSummary, type ag as WorkflowStepDetail, type ah as WsTokenProvider, ai as createClientQuery, aj as createLocalStore, ak as createStream } from "./packem_shared/lunora-client.d-
|
|
1
|
+
import { c as PersistenceAdapter, Q as QueryCacheAdapter, B as BookmarkStorage, C as ConnectionStatus, S as SubscriptionError, H as HttpStreamRef, d as HttpStreamArgsOf, e as HttpStreamChunkOf, f as StreamIterable, O as OfflineQueueOptions, R as ReconnectOptions, L as LunoraClient } from "./packem_shared/lunora-client.d-DWo4CzIH.mjs";
|
|
2
|
+
export { type A as ActionCallOptions, type g as BatchSlot, type h as CachedQuery, type i as ClientDebugShard, type j as ClientDebugSnapshot, type k as ClientDebugSubscription, type l as ClientMessage, type m as ClientQueryRef, type n as ClientShapeSubscribeMessage, type o as ClientShapeUnsubscribeMessage, D as DEFAULT_MAX_BUFFER, type F as FunctionArgumentDescriptor, type p as FunctionDescriptor, type G as GlobalFacetResult, type q as GlobalFacetValue, type r as GlobalFilterClause, type s as GlobalTableInfo, type t as GlobalTablePage, type u as HttpStreamCallArgs, type v as LunoraClientError, type w as LunoraClientOptions, type M as MutationCallOptions, type x as MutationSettledEvent, type y as OptimisticLocalStore, type z as OptimisticUpdate, type E as OutboxMutation, type I as OutboxSink, type J as PersistedMutation, type P as Preloaded, type K as RowOp, type N as RpcEnvelope, type T as RpcResponseBody, type V as ScheduleRecord, type W as ScheduleRetryPolicy, type X as SchedulerPoolStatus, type Y as SchedulerStatus, type Z as ServerMessage, type _ as ServerPokeEndMessage, type $ as ServerPokePartMessage, type a0 as ServerPokeStartMessage, type a1 as ShardTrafficEntry, type a2 as ShardTrafficResult, type a3 as StorageListPage, type a4 as StorageObject, type a5 as StoredQuery, type a6 as StreamHandle, type a7 as SubscriptionCallback, type b as SubscriptionErrorCallback, a8 as SubscriptionRegistry, type a9 as SubscriptionState, type aa as SyncWatermark, type a as Unsubscribe, type U as User, type ab as WorkflowInstanceAction, type ac as WorkflowInstanceDetail, type ad as WorkflowInstancePage, type ae as WorkflowInstanceStatus, type af as WorkflowInstanceSummary, type ag as WorkflowStepDetail, type ah as WsTokenProvider, ai as createClientQuery, aj as createLocalStore, ak as createStream } from "./packem_shared/lunora-client.d-DWo4CzIH.mjs";
|
|
3
3
|
import { LunoraError, LunoraErrorCode } from '@lunora/errors';
|
|
4
4
|
export type { LunoraErrorCode } from '@lunora/errors';
|
|
5
|
-
export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-
|
|
5
|
+
export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-6E3-9j1g.mjs";
|
|
6
6
|
import { F as FunctionReference } from "./packem_shared/function-reference.d-Br_hsKje.mjs";
|
|
7
7
|
export type { A as ArgsOf, R as ReturnOf } from "./packem_shared/function-reference.d-Br_hsKje.mjs";
|
|
8
8
|
export type { AuthCapabilities, AuthConfigInfo, AuthImpersonation, AuthPage, AuthSession, AuthUser, AuthUserFieldSpec, CronJobInfo, KvKeyEntry, KvKeyListResult, KvNamespaceSummary, KvValueResult, PipelineLogColumnMap, PipelineLogCursor, PipelineLogField, PipelineLogPage, PipelineLogQuery, PipelineLogRow, VectorIndexSummary, VectorQueryMatch } from '@lunora/runtime';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { c as PersistenceAdapter, Q as QueryCacheAdapter, B as BookmarkStorage, C as ConnectionStatus, S as SubscriptionError, H as HttpStreamRef, d as HttpStreamArgsOf, e as HttpStreamChunkOf, f as StreamIterable, O as OfflineQueueOptions, R as ReconnectOptions, L as LunoraClient } from "./packem_shared/lunora-client.d-
|
|
2
|
-
export { type A as ActionCallOptions, type g as BatchSlot, type h as CachedQuery, type i as ClientDebugShard, type j as ClientDebugSnapshot, type k as ClientDebugSubscription, type l as ClientMessage, type m as ClientQueryRef, type n as ClientShapeSubscribeMessage, type o as ClientShapeUnsubscribeMessage, D as DEFAULT_MAX_BUFFER, type F as FunctionArgumentDescriptor, type p as FunctionDescriptor, type G as GlobalFacetResult, type q as GlobalFacetValue, type r as GlobalFilterClause, type s as GlobalTableInfo, type t as GlobalTablePage, type u as HttpStreamCallArgs, type v as LunoraClientError, type w as LunoraClientOptions, type M as MutationCallOptions, type x as MutationSettledEvent, type y as OptimisticLocalStore, type z as OptimisticUpdate, type E as OutboxMutation, type I as OutboxSink, type J as PersistedMutation, type P as Preloaded, type K as RowOp, type N as RpcEnvelope, type T as RpcResponseBody, type V as ScheduleRecord, type W as ScheduleRetryPolicy, type X as SchedulerPoolStatus, type Y as SchedulerStatus, type Z as ServerMessage, type _ as ServerPokeEndMessage, type $ as ServerPokePartMessage, type a0 as ServerPokeStartMessage, type a1 as ShardTrafficEntry, type a2 as ShardTrafficResult, type a3 as StorageListPage, type a4 as StorageObject, type a5 as StoredQuery, type a6 as StreamHandle, type a7 as SubscriptionCallback, type b as SubscriptionErrorCallback, a8 as SubscriptionRegistry, type a9 as SubscriptionState, type aa as SyncWatermark, type a as Unsubscribe, type U as User, type ab as WorkflowInstanceAction, type ac as WorkflowInstanceDetail, type ad as WorkflowInstancePage, type ae as WorkflowInstanceStatus, type af as WorkflowInstanceSummary, type ag as WorkflowStepDetail, type ah as WsTokenProvider, ai as createClientQuery, aj as createLocalStore, ak as createStream } from "./packem_shared/lunora-client.d-
|
|
1
|
+
import { c as PersistenceAdapter, Q as QueryCacheAdapter, B as BookmarkStorage, C as ConnectionStatus, S as SubscriptionError, H as HttpStreamRef, d as HttpStreamArgsOf, e as HttpStreamChunkOf, f as StreamIterable, O as OfflineQueueOptions, R as ReconnectOptions, L as LunoraClient } from "./packem_shared/lunora-client.d-WFeiiO0Z.js";
|
|
2
|
+
export { type A as ActionCallOptions, type g as BatchSlot, type h as CachedQuery, type i as ClientDebugShard, type j as ClientDebugSnapshot, type k as ClientDebugSubscription, type l as ClientMessage, type m as ClientQueryRef, type n as ClientShapeSubscribeMessage, type o as ClientShapeUnsubscribeMessage, D as DEFAULT_MAX_BUFFER, type F as FunctionArgumentDescriptor, type p as FunctionDescriptor, type G as GlobalFacetResult, type q as GlobalFacetValue, type r as GlobalFilterClause, type s as GlobalTableInfo, type t as GlobalTablePage, type u as HttpStreamCallArgs, type v as LunoraClientError, type w as LunoraClientOptions, type M as MutationCallOptions, type x as MutationSettledEvent, type y as OptimisticLocalStore, type z as OptimisticUpdate, type E as OutboxMutation, type I as OutboxSink, type J as PersistedMutation, type P as Preloaded, type K as RowOp, type N as RpcEnvelope, type T as RpcResponseBody, type V as ScheduleRecord, type W as ScheduleRetryPolicy, type X as SchedulerPoolStatus, type Y as SchedulerStatus, type Z as ServerMessage, type _ as ServerPokeEndMessage, type $ as ServerPokePartMessage, type a0 as ServerPokeStartMessage, type a1 as ShardTrafficEntry, type a2 as ShardTrafficResult, type a3 as StorageListPage, type a4 as StorageObject, type a5 as StoredQuery, type a6 as StreamHandle, type a7 as SubscriptionCallback, type b as SubscriptionErrorCallback, a8 as SubscriptionRegistry, type a9 as SubscriptionState, type aa as SyncWatermark, type a as Unsubscribe, type U as User, type ab as WorkflowInstanceAction, type ac as WorkflowInstanceDetail, type ad as WorkflowInstancePage, type ae as WorkflowInstanceStatus, type af as WorkflowInstanceSummary, type ag as WorkflowStepDetail, type ah as WsTokenProvider, ai as createClientQuery, aj as createLocalStore, ak as createStream } from "./packem_shared/lunora-client.d-WFeiiO0Z.js";
|
|
3
3
|
import { LunoraError, LunoraErrorCode } from '@lunora/errors';
|
|
4
4
|
export type { LunoraErrorCode } from '@lunora/errors';
|
|
5
|
-
export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-
|
|
5
|
+
export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-CVB-TzK6.js";
|
|
6
6
|
import { F as FunctionReference } from "./packem_shared/function-reference.d-Br_hsKje.js";
|
|
7
7
|
export type { A as ArgsOf, R as ReturnOf } from "./packem_shared/function-reference.d-Br_hsKje.js";
|
|
8
8
|
export type { AuthCapabilities, AuthConfigInfo, AuthImpersonation, AuthPage, AuthSession, AuthUser, AuthUserFieldSpec, CronJobInfo, KvKeyEntry, KvKeyListResult, KvNamespaceSummary, KvValueResult, PipelineLogColumnMap, PipelineLogCursor, PipelineLogField, PipelineLogPage, PipelineLogQuery, PipelineLogRow, VectorIndexSummary, VectorQueryMatch } from '@lunora/runtime';
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{anyApi as o}from"./packem_shared/anyApi-CBOws2ZA.mjs";import{RETIRE_AFTER_DURABLE_SEQ_ADVANCE as a,maxSeq as c,reconcileOptimistic as p}from"./packem_shared/RETIRE_AFTER_DURABLE_SEQ_ADVANCE-DoEHtuR8.mjs";import{createAsyncStoragePersistence as m}from"./packem_shared/createAsyncStoragePersistence-CeUW9NTj.mjs";import{createAsyncStorageQueryCache as f}from"./packem_shared/createAsyncStorageQueryCache-BfZkthAE.mjs";import{default as x}from"./packem_shared/createInMemoryBookmarkStorage-BooZhW0n.mjs";import{createCallRunner as l}from"./packem_shared/createCallRunner-Bwcrfh76.mjs";import{createClientQuery as d}from"./packem_shared/createClientQuery-B8Nfj-7o.mjs";import{TabCoordinator as R}from"./packem_shared/TabCoordinator-CXD7vulJ.mjs";import{a as S,i as A}from"./packem_shared/delta-merge-vxvH3PvF.mjs";import{CONFLICT_ERROR_CODE as Q,TransportError as _,getErrorCode as h,getRetryAfterMs as I,isConflictError as M,isForbiddenError as T,isRateLimitedError as g,isUnauthorizedError as F}from"./packem_shared/CONFLICT_ERROR_CODE-BOeeP_Wl.mjs";import{httpStream as O}from"./packem_shared/httpStream-
|
|
1
|
+
import{anyApi as o}from"./packem_shared/anyApi-CBOws2ZA.mjs";import{RETIRE_AFTER_DURABLE_SEQ_ADVANCE as a,maxSeq as c,reconcileOptimistic as p}from"./packem_shared/RETIRE_AFTER_DURABLE_SEQ_ADVANCE-DoEHtuR8.mjs";import{createAsyncStoragePersistence as m}from"./packem_shared/createAsyncStoragePersistence-CeUW9NTj.mjs";import{createAsyncStorageQueryCache as f}from"./packem_shared/createAsyncStorageQueryCache-BfZkthAE.mjs";import{default as x}from"./packem_shared/createInMemoryBookmarkStorage-BooZhW0n.mjs";import{createCallRunner as l}from"./packem_shared/createCallRunner-Bwcrfh76.mjs";import{createClientQuery as d}from"./packem_shared/createClientQuery-B8Nfj-7o.mjs";import{TabCoordinator as R}from"./packem_shared/TabCoordinator-CXD7vulJ.mjs";import{a as S,i as A}from"./packem_shared/delta-merge-vxvH3PvF.mjs";import{CONFLICT_ERROR_CODE as Q,TransportError as _,getErrorCode as h,getRetryAfterMs as I,isConflictError as M,isForbiddenError as T,isRateLimitedError as g,isUnauthorizedError as F}from"./packem_shared/CONFLICT_ERROR_CODE-BOeeP_Wl.mjs";import{httpStream as O}from"./packem_shared/httpStream-BWdNJzId.mjs";import{c as P}from"./packem_shared/local-store-CWeFEk6w.mjs";import{LunoraClient as k}from"./packem_shared/LunoraClient-Cj6Z6KeC.mjs";import{createMutatorRunner as q}from"./packem_shared/createMutatorRunner-CuMRJpUx.mjs";import{O as v}from"./packem_shared/offline-queue-D_fr-uQ3.mjs";import{createInMemoryPersistence as z,createIndexedDbPersistence as K}from"./packem_shared/createInMemoryPersistence-Cz2W6XVj.mjs";import{preloadQuery as W,preloadedQueryResult as X}from"./packem_shared/preloadQuery-uFy24PCR.mjs";import{createInMemoryQueryCache as G,createIndexedDbQueryCache as H,queryCacheKey as J}from"./packem_shared/createInMemoryQueryCache-D2uNHLfM.mjs";import{createReconnect as Z}from"./packem_shared/createReconnect-CjTmjJDH.mjs";import{default as ee}from"./packem_shared/createSnapshotPrecondition-GRVKxPsh.mjs";import{DEFAULT_MAX_BUFFER as oe,createStream as te}from"./packem_shared/DEFAULT_MAX_BUFFER-D3QH2iaq.mjs";import{SubscriptionRegistry as ce}from"./packem_shared/SubscriptionRegistry-CS-AFUI9.mjs";import{ClientServiceWorker as ne}from"./packem_shared/ClientServiceWorker-DXnBXeWK.mjs";import{createReply as ie,sendToSw as fe}from"./packem_shared/createReply-CwFABEJs.mjs";export{Q as CONFLICT_ERROR_CODE,ne as ClientServiceWorker,oe as DEFAULT_MAX_BUFFER,k as LunoraClient,v as OfflineQueue,a as RETIRE_AFTER_DURABLE_SEQ_ADVANCE,ce as SubscriptionRegistry,R as TabCoordinator,_ as TransportError,o as anyApi,S as applyDelta,m as createAsyncStoragePersistence,f as createAsyncStorageQueryCache,l as createCallRunner,d as createClientQuery,x as createInMemoryBookmarkStorage,z as createInMemoryPersistence,G as createInMemoryQueryCache,K as createIndexedDbPersistence,H as createIndexedDbQueryCache,P as createLocalStore,q as createMutatorRunner,Z as createReconnect,ie as createReply,ee as createSnapshotPrecondition,te as createStream,h as getErrorCode,I as getRetryAfterMs,O as httpStream,M as isConflictError,T as isForbiddenError,A as isMutationDelta,g as isRateLimitedError,F as isUnauthorizedError,c as maxSeq,W as preloadQuery,X as preloadedQueryResult,J as queryCacheKey,p as reconcileOptimistic,fe as sendToSw};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as y}from"@lunora/errors";import{i as le,a as fe,P as pe}from"./delta-merge-vxvH3PvF.mjs";import{e as M,d as g}from"./wire-codec-Sw1rAu-Z.mjs";import{s as G}from"./wire-key-HsUDTlQ7.mjs";import me from"./createInMemoryBookmarkStorage-BooZhW0n.mjs";import{ClientQueryStore as ye}from"./createClientQuery-B8Nfj-7o.mjs";import{TabCoordinator as be}from"./TabCoordinator-CXD7vulJ.mjs";import{TransportError as j}from"./CONFLICT_ERROR_CODE-BOeeP_Wl.mjs";import{httpStream as Se}from"./httpStream-BWdNJzId.mjs";import{d as U,n as _,f as A,a as ve,c as ge,b as Te,e as ke}from"./local-store-CWeFEk6w.mjs";import{O as Ce,n as z,i as we,r as Ee}from"./offline-queue-D_fr-uQ3.mjs";import{resolvePersistenceAdapter as _e}from"./createInMemoryPersistence-Cz2W6XVj.mjs";import{resolveQueryCacheAdapter as Ae,queryCacheKey as I}from"./createInMemoryQueryCache-D2uNHLfM.mjs";import{createReconnect as V}from"./createReconnect-CjTmjJDH.mjs";import{e as F,u as L,d as Ie,r as Oe,i as Re,a as Pe,b as Fe,M as Me,c as Le,f as He}from"./replay-DYdPvn3o.mjs";import Ue from"./createSnapshotPrecondition-GRVKxPsh.mjs";import{createStream as xe}from"./DEFAULT_MAX_BUFFER-D3QH2iaq.mjs";import{SubscriptionRegistry as T}from"./SubscriptionRegistry-CS-AFUI9.mjs";const x=500,Ne=async h=>{const e=[];let t;for(;;){const s=await h(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}},J=(h,e)=>{if(h.size<e)return;const t=h.keys().next().value;t!==void 0&&h.delete(t)};class O{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 Be=h=>{const{afterFailedAttempts:e,intervalMs:t,onReachable:s,onStateChange:r,poll:i}=h,n=t>0&&e>0;let a=0,o,c=!1,d=!1;const u=()=>{o!==void 0&&(clearInterval(o),o=void 0,c=!1,r())},f=m=>{if(o!==void 0){if(!m){u();return}c||(c=!0,r()),s()}},p=()=>{d||(d=!0,i().then(f).finally(()=>{d=!1}).catch(()=>{}))};return{isPolling:()=>o!==void 0&&c,noteFailedOpen:()=>{a+=1,!(!n||o!==void 0||a<e)&&(o=setInterval(p,t),r(),p())},noteOpen:()=>{a=0,u()},stop:u}},Qe="/_lunora/rpc",N="/_lunora/rpc-batch",qe="/_lunora/ws",B=h=>h===void 0||h===""?"":`&bucket=${encodeURIComponent(h)}`,P=h=>{for(let e=h.length-1;e>=0;e-=1)h[e]?.()},Y=Symbol("lunora.unmergeableDelta"),De=(h,e)=>{for(const t of e)t.op==="delete"?h.delete(t.key):t.value!==void 0&&h.set(t.key,t.value)},Ke="lunora-ping",We=3e4,$e=1e4,Ge=5e3,je=3,ze=250,Ve=5e3,Je=64,Ye=3,Xe=1e4,Ze=8,et="/_lunora/admin/shard-traffic",tt="/_lunora/admin/scheduled",st="/_lunora/admin/scheduled/status",rt="/_lunora/admin/scheduled/ws",it="/_lunora/admin/scheduled/cancel",X="/_lunora/admin/scheduled/dead",nt="/_lunora/admin/scheduled/dead/retry",at="/_lunora/admin/scheduled/dead/cancel",ot="/_lunora/admin/workflows/instances",ct="/_lunora/admin/workflows/instance",ht="/_lunora/admin/workflows/status",Q="/_lunora/admin/storage",dt="/_lunora/admin/storage/url",ut="/_lunora/admin/storage/buckets",lt="/_lunora/admin/functions",ft="/_lunora/admin/cron-jobs",pt="/_lunora/admin/cron-jobs/run",mt="/_lunora/admin/openapi",yt="/_lunora/admin/openrpc",bt="/_lunora/admin/global/tables",St="/_lunora/admin/global/table",vt="/_lunora/admin/global/facet",gt="/_lunora/admin/vector/indexes",Tt="/_lunora/admin/vector/query",kt="/_lunora/admin/logs/archive",Ct="/_lunora/admin/kv/namespaces",wt="/_lunora/admin/kv/keys",q="/_lunora/admin/kv/value",Et="/_lunora/admin/auth/users",_t="/_lunora/admin/auth/sessions",At="/_lunora/admin/auth/users/create",It="/_lunora/admin/auth/users/role",Ot="/_lunora/admin/auth/users/ban",Rt="/_lunora/admin/auth/users/unban",Pt="/_lunora/admin/auth/users/password",Ft="/_lunora/admin/auth/users/remove",Mt="/_lunora/admin/auth/users/impersonate",Lt="/_lunora/admin/auth/sessions/revoke",Ht="/_lunora/admin/auth/sessions/revoke-all",Ut="/_lunora/admin/auth/capabilities",xt="/_lunora/admin/auth/users/update",Nt="/_lunora/admin/auth/accounts",Bt="/_lunora/admin/auth/accounts/unlink",Qt="/_lunora/admin/auth/passkeys",qt="/_lunora/admin/auth/passkeys/delete",Dt="/_lunora/admin/auth/two-factor/disable",Kt="/_lunora/admin/auth/organizations",Wt="/_lunora/admin/auth/organizations/members",$t="/_lunora/admin/auth/organizations/invitations",Gt="/_lunora/admin/auth/organizations/members/remove",jt="/_lunora/admin/auth/organizations/invitations/cancel",zt="/_lunora/admin/auth/config",Vt="/_lunora/admin/auth/sign-up-invitations",Jt="/_lunora/admin/auth/sign-up-invitations/create",Yt="/_lunora/admin/auth/sign-up-invitations/revoke",Xt="/_lunora/admin/auth/organizations/create",Zt="/_lunora/admin/auth/organizations/update",es="/_lunora/admin/auth/organizations/remove",ts="/_lunora/admin/auth/organizations/members/add",ss="/_lunora/admin/auth/organizations/members/invite",rs="/_lunora/admin/auth/organizations/members/role",is="/_lunora/admin/auth/organizations/teams",ns="/_lunora/admin/auth/organizations/teams/create",as="/_lunora/admin/auth/organizations/teams/update",os="/_lunora/admin/auth/organizations/teams/remove",cs="/_lunora/admin/auth/organizations/teams/members",hs="/_lunora/admin/auth/organizations/teams/members/add",ds="/_lunora/admin/auth/organizations/teams/members/remove",us="/_lunora/admin/auth/organizations/roles",ls="/_lunora/admin/auth/organizations/roles/create",fs="/_lunora/admin/auth/organizations/roles/update",ps="/_lunora/admin/auth/organizations/roles/remove",ms="/api/auth",ys="/get-session",Z=h=>h==="connected"||h==="polling",ee=h=>h.startsWith("https://")?`wss://${h.slice(8)}`:h.startsWith("http://")?`ws://${h.slice(7)}`:h,k=(h,e)=>`${h.endsWith("/")?h.slice(0,-1):h}${e}`,S=(h,e)=>{const t=new URLSearchParams;for(const[r,i]of Object.entries(e))i!==void 0&&i!==""&&t.set(r,String(i));const s=t.toString();return s===""?h:`${h}?${s}`},bs=[pe],l=h=>h??"",ne=(h,e)=>{const t=h.error,s=typeof t?.code=="string"?t.code:void 0,r=typeof t?.message=="string"?t.message:void 0;return{code:s,messageText:(typeof h.message=="string"?h.message:void 0)??r??e}},Ss=h=>{const{code:e,messageText:t}=ne(h,"stream error");return e===void 0?new Error(t):new y(e,t)},te=h=>{const{code:e,messageText:t}=ne(h,"subscription error");return{message:t,...e===void 0?{}:{code:e}}};function D(h){if(h!==void 0)return e=>{h(e)}}const E=(h,e)=>{for(const t of h)try{t(e)}catch{}},vs=new TextDecoder,gs=h=>{if(typeof h=="string")return h;if(h instanceof ArrayBuffer)return vs.decode(h)},v=(h,e)=>{if(!h.socket||h.wsState!=="open")return!1;try{return h.socket.send(JSON.stringify(e)),!0}catch{return!1}},W=h=>{const e=new Error(h.message??"request failed");return e.code=h.code,h.data!==void 0&&(e.data=g(h.data)),h.hint!==void 0&&(e.hint=h.hint),h.docsUrl!==void 0&&(e.docsUrl=h.docsUrl),e},se=(h,e)=>{const t=W(h),s=Le(t,e);return s!==void 0&&(t.data=s),t},C=(h,e)=>{try{return M(h)}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)}},Ts=1e4,re=async h=>{const e=new AbortController;let t;const s=new Promise((r,i)=>{t=setTimeout(()=>{e.abort(),i(new TypeError("LunoraClient: poll timed out"))},Ts)});try{return await Promise.race([h(e.signal),s])}catch(r){throw e.signal.aborted?new TypeError("LunoraClient: poll timed out"):r}finally{clearTimeout(t)}},ie=h=>{try{return M(h),!0}catch{return!1}},K=h=>"args"in h?{...h,args:g(h.args)}:h,ae=h=>{const e=F(h);return e===void 0?He():W(e)},ks=(h,e)=>{const t=Array.from({length:e});for(const s of h){if(typeof s.id!="number"||s.id<0||s.id>=e)continue;const r=s.body;t[s.id]=r!==void 0&&"error"in r?{error:ae(r),ok:!1}:{ok:!0,value:g(r?.result)}}return t.map(s=>s??{error:new Error("batch call returned no result"),ok:!1})},Cs=Promise.resolve();class oe{static MAX_POKE_BUFFERS=256;static createClientQuery(e,t){return{defaultValue:t,key:e}}url;wsUrl;clientQueryStore;wsToken;authBasePath;fetchImpl;WebSocketImpl;bookmark;reconnectOptions;connectTimeoutMs;heartbeatIntervalMs;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 T;tabCoordinator;leaderStatus;leaderWasEverConnected=!1;connections=new Map;defaultConnectionContext;connectionContexts=new Map;connectionContextHolders=new Map;authToken=null;authSubject=void 0;subjectToken=null;sessionProbesInFlight=0;sessionProbeGeneration=0;identityResolutionExpected=!1;identitySettled=!1;queuedIdentities=new Map;queuedOfflineShardKeys=new Set;closed=!1;authTokenListeners=new O;statusListeners=new O;tokenExpiredListeners=new O;identityChangeListeners=new O;authRefusalNotifiedFor;mutationSettledListeners=new O;pendingChangeListeners=new O;whisperHandlers=new Map;lastStatus="idle";nextSubId=0;nextStreamId=0;streams=new Map;adminSocketTeardowns=new Set;offlineFlushes=new Map;replayRetryState=new Map;replayRetryTimers=new Map;shapeSubscriptions=new Map;pokeBuffers=new Map;nextShapeId=0;constructor(e){this.url=e.url,this.wsUrl=e.wsUrl??k(ee(e.url),qe),this.wsToken=e.wsToken;const t=e.authBasePath??ms;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??me(),this.reconnectOptions=e.reconnect,this.heartbeatIntervalMs=e.heartbeatIntervalMs??We,this.connectTimeoutMs=e.connectTimeoutMs??$e,this.pollingFallbackIntervalMs=e.pollingFallback?.intervalMs??Ge,this.pollingFallbackAfterFailedAttempts=e.pollingFallback?.afterFailedAttempts??je,this.defaultConnectionContext=e.connectionContext,this.persistence=_e(e.persistence,e.outbox===void 0),this.persistenceVersion=e.persistenceVersion,this.queryCache=Ae(e.queryCache),this.onPersistenceError=e.offlineQueue?.onPersistenceError,this.clientQueryStore=new ye,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=Cs),this.offlineQueue=new Ce(e.offlineQueue,{onEvict:(s,r)=>{this.emitItemSettled(s,"rejected",r)},onSizeChange:s=>{this.pendingChangeListeners.emit(s)},persistence:this.persistence,version:e.persistenceVersion}),this.outbox=e.outbox,this.clientId=e.clientId??`client-${z()}`,this.persistence&&queueMicrotask(()=>{this.hydrateAsOutboxLeader()}),this.queryCache&&queueMicrotask(()=>{(async()=>{try{await this.hydrateQueryCache()}catch{}finally{this.readyResolved=!0,this.readyResolve?.()}})().catch(()=>{})})}setAuthToken(e,t){const s=this.authToken!==e,r=this.identityFingerprint(),i=this.authSubject===void 0||this.subjectToken===this.authToken,n=this.subjectAwaitingReconfirm();this.authToken=e,t!==void 0?(this.authSubject=t,this.subjectToken=e):e===null&&(this.authSubject=void 0,this.subjectToken=null);const a=this.identityFingerprint();a!==r&&(!s&&e!==null&&i?(this.restampQueuedIdentity(r,a),this.restampWatermarks(r,a),this.restampConnectionIdentity(r,a),this.reseedFromHydratedCache()):!s&&e===null&&r===null&&i?(this.restampWatermarks(r,a),this.restampConnectionIdentity(r,a),this.reseedFromHydratedCache()):(this.rejectQueuedForIdentityChange(r),r!==null&&this.evictPreviousIdentitySession()),this.restartTabCoordinatorForIdentity()),this.syncReadCacheToCredential(n),s&&this.authTokenListeners.emit(e),this.offlineQueue.size>0&&Z(this.computeStatus())&&this.flushAllOfflineQueues()}getAuthToken(){return this.authToken}currentIdentity(){return this.identityFingerprint()}expectIdentityResolution(){this.identityResolutionExpected=!0}currentBaseline(e){return this.baselineCursorFor(e)}replayIdentityVerdict(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"}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 i=s?.shardKey??"",n=this.identityFingerprint();let a;const o=await this.rpc(e,t,s?.shardKey,{captureBookmark:!0,clientId:this.clientId,clientSeq:r,onMutationAck:d=>{a=d}});if(a!==void 0&&a>(this.clientWatermarks.get(n??"")?.get(i)??0)){let d=this.clientWatermarks.get(n??"");d===void 0&&(J(this.clientWatermarks,Ze),d=new Map,this.clientWatermarks.set(n??"",d)),d.set(i,a)}return{applied:a===void 0||a===r,result:o}}onAuthTokenChange(e){return this.authTokenListeners.add(e)}onIdentityChange(e){return this.identityChangeListeners.add(e)}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.sessionProbeGeneration+=1;const s=this.sessionProbeGeneration;try{const r=await this.fetchImpl(k(this.url,`${this.authBasePath}${ys}`),{credentials:"include",headers:e,method:"GET"});if(!r.ok)return this.identitySettled=!0,null;const n=(await r.json())?.user??null;return this.identitySettled=!0,this.adoptResolvedSubject(t,n,s),n}finally{this.releaseSessionProbe()}}setWsToken(e){this.wsToken!==e&&(this.wsToken=e,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)}acquireConnectionContext(e,t={}){if(this.followsAnotherTab())return()=>{};const s=l(t.shardKey),r={context:e},i=this.connectionContextHolders.get(s);i?i.push(r):this.connectionContextHolders.set(s,[r]),this.refreshConnectionContext(s);let n=!1;return()=>{if(n)return;n=!0;const a=this.connectionContextHolders.get(s);if(!a)return;const o=a.indexOf(r);o!==-1&&a.splice(o,1),a.length===0&&this.connectionContextHolders.delete(s),this.refreshConnectionContext(s)}}whisperSubscribe(e,t,s={}){this.assertLeaderOwnedSurface("whisperSubscribe");const r=l(s.shardKey);let i=this.whisperHandlers.get(r);i||(i=new Map,this.whisperHandlers.set(r,i));let n=i.get(e);const a=n===void 0;if(n||(n=new Set,i.set(e,n)),n.add(t),this.ensureSocket(s.shardKey),a){const o=this.getConnection(s.shardKey);o&&v(o,{topic:e,type:"whisper_subscribe"})}return()=>{const o=this.whisperHandlers.get(r),c=o?.get(e);if(!c?.delete(t)||c.size>0)return;o?.delete(e),o?.size===0&&this.whisperHandlers.delete(r);const d=this.getConnection(s.shardKey);d&&v(d,{topic:e,type:"whisper_unsubscribe"})}}whisper(e,t,s={}){this.assertLeaderOwnedSurface("whisper"),this.ensureSocket(s.shardKey);const r=this.getConnection(s.shardKey);r&&v(r,{data:C(t??null,`whisper data for topic '${e}'`),topic:e,type:"whisper"})}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 i of s){const n=this.connections.get(i);e.push({confirmedMutationWatermark:t?.get(i)??0,hasSocket:n?.socket!==void 0,shardKey:i===""?void 0:i,wasEverConnected:n?.wasEverConnected??!1,wsState:n?.wsState??"idle"})}const r=this.subscriptions.all().map(i=>({acked:i.acked,functionPath:i.fn.__lunoraRef,id:i.id,kind:"query",lastMutationId:i.lastMutationId,pendingOptimisticLayers:i.optimisticLayers.length,serverCursor:i.serverCursor,shardKey:i.shardKey,subscriberCount:i.callbacks.size}));for(const i of this.shapeSubscriptions.values())r.push({acked:i.serverCursor!==void 0,functionPath:`shape:${i.name}`,id:i.id,kind:"shape",lastMutationId:i.lastMutationId,pendingOptimisticLayers:0,rowCount:i.rows.size,serverCursor:i.serverCursor,shardKey:i.shardKey,subscriberCount:i.callbacks.size});return{clientId:this.clientId,closed:this.closed,connectionStatus:this.computeStatus(),pendingWrites:this.offlineQueue.size,shards:e.toSorted((i,n)=>(i.shardKey??"").localeCompare(n.shardKey??"")),subscriptions:r.toSorted((i,n)=>i.functionPath.localeCompare(n.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 Ue(this,e,t,s)}whenReady(){return this.readyPromise}get isReady(){return this.readyResolved}peekHydratedQuery(e,t,s){if(!this.readyResolved)return;const r=G(t),i=I(e,r,s),n=this.hydratedQueryCache.get(i);if(n!==void 0)return this.cachedQueryMatchesIdentity(n)?n.value:void 0}peekActiveQuerySnapshot(e,t,s){const r=T.key(e,t,s),i=this.subscriptions.get(r);return{present:i!==void 0,value:i?.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)),i=s.toArgs??(d=>({rows:d})),n=t.length;let a=0,o=0,c=0;for(let d=0;d<n;d+=r){const u=t.slice(d,d+r),f=c,{committed:p}=await this.runMutation(e,i(u),{...s.importId===void 0?{}:{mutationId:`${s.importId}:${String(f)}`},shardKey:s.shardKey});c+=1,a+=u.length,p&&(o+=u.length),s.onProgress?.({done:a,total:n})}return{chunks:c,imported:o,queued:a-o}}async shardTraffic(e){this.assertOpen();const t=await this.adminFetch(et,"POST",{table:e});return{failed:t.failed??0,ok:t.ok??0,shards:t.shards??[]}}async listScheduledJobs(){return this.assertOpen(),((await this.adminFetch(tt,"GET")).records??[]).map(t=>K(t))}async schedulerStatus(){this.assertOpen();const e=await this.adminFetch(st,"GET");return{backlog:e.backlog??0,inFlight:e.inFlight??0,pools:e.pools??[]}}async cancelScheduledJob(e){return this.assertOpen(),{cancelled:(await this.adminFetch(it,"POST",{id:e})).cancelled===!0}}async listDeadJobs(){return this.assertOpen(),(await Ne(async t=>await this.adminFetch(t===void 0?X:`${X}?cursor=${encodeURIComponent(t)}`,"GET"))).map(t=>K(t))}async retryDeadJob(e){return this.assertOpen(),{retried:(await this.adminFetch(nt,"POST",{id:e})).retried===!0}}async removeDeadJob(e){return this.assertOpen(),{removed:(await this.adminFetch(at,"POST",{id:e})).removed===!0}}async listWorkflowInstances(e){this.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 this.adminFetch(`${ot}?${t.toString()}`,"GET");return{configured:s.configured,instances:s.instances??[],page:s.page??1,perPage:s.perPage??e.perPage??0,totalCount:s.totalCount}}async getWorkflowInstance(e){this.assertOpen();const t=new URLSearchParams({id:e.id,name:e.name}),s=await this.adminFetch(`${ct}?${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??[]}}async setWorkflowInstanceStatus(e){return this.assertOpen(),{status:(await this.adminFetch(ht,"POST",{action:e.action,id:e.id,name:e.name})).status??"unknown"}}subscribeScheduledJobs(e){if(this.assertOpen(),this.WebSocketImpl===void 0)return()=>{};const t=k(ee(this.url),rt),s=V(this.reconnectOptions),r={connectTimer:void 0,heartbeatTimer:void 0,lastFrameAt:0,socket:void 0};let i,n=!1;const a=()=>{n||this.closed||(i=setTimeout(d,s.next()))},o=f=>{if(n||this.WebSocketImpl===void 0)return;const p=f===void 0?t:`${t}?token=${encodeURIComponent(f)}`;this.openManagedSocket(r,p,this.connectTimeoutMs,{onClose:()=>{a()},onMessage:m=>{let b;try{b=JSON.parse(typeof m.data=="string"?m.data:"")}catch{return}b.type==="jobs"&&Array.isArray(b.records)&&(s.reset(),e(b.records.map(w=>K(w))))}})},c=async f=>{let p;try{p=await f()}catch{a();return}o(p)},d=()=>{if(n||this.WebSocketImpl===void 0)return;const{wsToken:f}=this;if(typeof f=="function"){c(f).catch(()=>{});return}o(f)};d();const u=()=>{n=!0,i!==void 0&&(clearTimeout(i),i=void 0),r.connectTimer!==void 0&&(clearTimeout(r.connectTimer),r.connectTimer=void 0),this.stopHeartbeat(r),r.socket?.close(),r.socket=void 0};return this.adminSocketTeardowns.add(u),()=>{this.adminSocketTeardowns.delete(u),u()}}async listFunctions(){return this.assertOpen(),(await this.adminFetch(lt,"GET")).functions??[]}async getCronJobs(){return this.assertOpen(),(await this.adminFetch(ft,"GET")).jobs??[]}async runCronJob(e){this.assertOpen();const t=await this.adminFetch(pt,"POST",{name:e});return{name:t.name??e,ran:t.ran===!0}}async fetchOpenApi(){return this.assertOpen(),await this.adminFetch(mt,"GET")}async fetchOpenRpc(){return this.assertOpen(),await this.adminFetch(yt,"GET")}async listStorageObjects(e={}){this.assertOpen();const t=S(Q,{bucket:e.bucket,cursor:e.cursor,limit:e.limit,prefix:e.prefix}),s=await this.adminFetch(t,"GET");return{cursor:s.cursor,objects:s.objects??[]}}async deleteStorageObject(e,t){this.assertOpen();const s=`${Q}?key=${encodeURIComponent(e)}${B(t?.bucket)}`,r=await this.adminFetch(s,"DELETE");return{deleted:r.deleted===!0,key:r.key??e}}async listStorageBuckets(){return this.assertOpen(),(await this.adminFetch(ut,"GET")).buckets??[]}async uploadStorageObject(e){this.assertOpen();const t=`${Q}?key=${encodeURIComponent(e.key)}${B(e.bucket)}`,s=await this.adminFetch(t,"PUT",e.body,e.contentType);return{etag:s.etag,key:s.key??e.key}}async signedStorageUrl(e,t){this.assertOpen();const s=t?.expiresInSeconds,r=s===void 0?"":`&expiresIn=${encodeURIComponent(s.toString())}`,i=`${dt}?key=${encodeURIComponent(e)}${r}${B(t?.bucket)}`,n=await this.adminFetch(i,"GET");if(typeof n.url!="string")throw new TypeError("LunoraClient: storage URL endpoint returned no `url`");return n.url}async listGlobalTables(){return this.assertOpen(),await this.adminFetch(bt,"GET")}async readGlobalTablePage(e){this.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(M(e.filters))),g(await this.adminFetch(`${St}?${t.toString()}`,"GET"))}async facetGlobalColumn(e){this.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(M(e.filters))),g(await this.adminFetch(`${vt}?${t.toString()}`,"GET"))}async listVectorIndexes(){return this.assertOpen(),(await this.adminFetch(gt,"GET")).indexes??[]}async queryVectorIndex(e){return this.assertOpen(),(await this.adminFetch(Tt,"POST",e)).matches??[]}async queryLogArchive(e={}){this.assertOpen();const t=await this.adminFetch(kt,"POST",e);return{nextCursor:t.nextCursor,rows:t.rows??[]}}async listKvNamespaces(){return this.assertOpen(),(await this.adminFetch(Ct,"GET")).namespaces??[]}async listKvKeys(e){this.assertOpen();const t=S(wt,{cursor:e.cursor,limit:e.limit,namespace:e.namespace,prefix:e.prefix});return await this.adminFetch(t,"GET")}async getKvValue(e){this.assertOpen();const t=S(q,{key:e.key,namespace:e.namespace});return await this.adminFetch(t,"GET")}async putKvValue(e){this.assertOpen(),await this.adminFetch(q,"PUT",e)}async deleteKvKey(e){this.assertOpen();const t=S(q,{key:e.key,namespace:e.namespace});await this.adminFetch(t,"DELETE")}async listAuthUsers(e={}){this.assertOpen();const t=S(Et,{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 await this.adminFetch(At,"POST",e)}async setAuthUserRole(e){return await this.adminFetch(It,"POST",e)}async banAuthUser(e){return await this.adminFetch(Ot,"POST",e)}async unbanAuthUser(e){return await this.adminFetch(Rt,"POST",e)}async setAuthUserPassword(e){await this.adminFetch(Pt,"POST",e)}async removeAuthUser(e){await this.adminFetch(Ft,"POST",e)}async impersonateAuthUser(e){return await this.adminFetch(Mt,"POST",e)}async revokeAuthSession(e){await this.adminFetch(Lt,"POST",e)}async revokeAuthUserSessions(e){await this.adminFetch(Ht,"POST",e)}async getAuthCapabilities(){return await this.adminFetch(Ut,"GET")}async updateAuthUser(e){return await this.adminFetch(xt,"POST",e)}async listAuthAccounts(e){return await this.adminFetch(S(Nt,{userId:e.userId}),"GET")}async unlinkAuthAccount(e){await this.adminFetch(Bt,"POST",e)}async listAuthPasskeys(e){return await this.adminFetch(S(Qt,{userId:e.userId}),"GET")}async deleteAuthPasskey(e){await this.adminFetch(qt,"POST",e)}async disableAuthTwoFactor(e){await this.adminFetch(Dt,"POST",e)}async listAuthOrganizations(e={}){return await this.adminFetch(S(Kt,{limit:e.limit,offset:e.offset}),"GET")}async listAuthOrgMembers(e){const t=S(Wt,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async listAuthOrgInvitations(e){const t=S($t,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async listAuthSignUpInvitations(e={}){const t=S(Vt,{limit:e.limit,offset:e.offset});return await this.adminFetch(t,"GET")}async createAuthSignUpInvitation(e){return await this.adminFetch(Jt,"POST",e)}async revokeAuthSignUpInvitation(e){await this.adminFetch(Yt,"POST",e)}async removeAuthOrgMember(e){await this.adminFetch(Gt,"POST",e)}async cancelAuthOrgInvitation(e){await this.adminFetch(jt,"POST",e)}async getAuthConfig(){return await this.adminFetch(zt,"GET")}async createAuthOrganization(e){return await this.adminFetch(Xt,"POST",e)}async updateAuthOrganization(e){return await this.adminFetch(Zt,"POST",e)}async deleteAuthOrganization(e){await this.adminFetch(es,"POST",e)}async addAuthOrgMember(e){return await this.adminFetch(ts,"POST",e)}async inviteAuthOrgMember(e){return await this.adminFetch(ss,"POST",e)}async setAuthOrgMemberRole(e){return await this.adminFetch(rs,"POST",e)}async listAuthOrgTeams(e){const t=S(is,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async createAuthOrgTeam(e){return await this.adminFetch(ns,"POST",e)}async updateAuthOrgTeam(e){return await this.adminFetch(as,"POST",e)}async removeAuthOrgTeam(e){await this.adminFetch(os,"POST",e)}async listAuthOrgTeamMembers(e){const t=S(cs,{limit:e.limit,offset:e.offset,teamId:e.teamId});return await this.adminFetch(t,"GET")}async addAuthOrgTeamMember(e){return await this.adminFetch(hs,"POST",e)}async removeAuthOrgTeamMember(e){await this.adminFetch(ds,"POST",e)}async listAuthOrgRoles(e){const t=S(us,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async createAuthOrgRole(e){return await this.adminFetch(ls,"POST",e)}async updateAuthOrgRole(e){return await this.adminFetch(fs,"POST",e)}async deleteAuthOrgRole(e){await this.adminFetch(ps,"POST",e)}async listAuthSessions(e={}){this.assertOpen();const t=S(_t,{limit:e.limit,offset:e.offset,userId:e.userId});return await this.adminFetch(t,"GET")}subscribe(e,t,s,r={}){this.assertOpen();const i=t??{},n=T.key(e.__lunoraRef,i,r.shardKey);let a=this.subscriptions.get(n);const o=D(s),c=D(r.onError),d=D(r.onCheckpoint);if(!a){this.nextSubId+=1;const f=`sub_${this.nextSubId.toString()}`,p=G(i),m=this.takeHydratedCache(e.__lunoraRef,p,r.shardKey);a={acked:!1,args:i,argsKey:p,callbacks:new Set,checkpointCallbacks:new Set,errorCallbacks:new Set,fn:e,id:f,lastValue:m?.value,optimisticLayers:[],serverBase:m?.value,serverCursor:m?.serverCursor,shardKey:r.shardKey,wireArgs:C(i,`args for '${e.__lunoraRef}'`),...m?.serverEpoch===void 0?{}:{serverEpoch:m.serverEpoch}},this.subscriptions.add(a),m!==void 0&&this.cacheSeededQueries.set(n,m)}if(a.callbacks.add(o),c&&a.errorCallbacks.add(c),d&&a.checkpointCallbacks.add(d),a.lastValue!==void 0)try{o(a.lastValue)}catch{}this.ensureSocket(r.shardKey),this.sendSubscribeIfOpen(a);const u=a;return()=>{u.callbacks.delete(o),c&&u.errorCallbacks.delete(c),d&&u.checkpointCallbacks.delete(d),u.callbacks.size===0&&(this.sendOrQueueUnsubscribe(u.shardKey,u.id,"unsubscribe"),this.returnCacheSeed(T.keyOf(u)),this.subscriptions.remove(u))}}subscribeShape(e,t,s={}){if(this.assertOpen(),this.followsAnotherTab()){const{onError:n}=s;return n!==void 0&&queueMicrotask(()=>{n({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()}`,i={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,i),this.ensureSocket(s.shardKey),this.sendShapeSubscribeIfOpen(i),()=>{this.shapeSubscriptions.delete(r),this.sendOrQueueUnsubscribe(i.shardKey,r,"shape_unsubscribe")}}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:i}=s,n=t??{},{handle:a,iterable:o}=xe({maxBuffer:s.maxBuffer,onCancel:()=>{this.cancelStream(r,i)}});this.ensureSocket(i);const c=this.getConnection(i),d={id:r,query:{args:C(n,`stream args for '${e.__lunoraRef}'`),functionPath:e.__lunoraRef,shardKey:i},type:"stream"},u={durable:s.durable===!0,generation:void 0,handle:a,lastSeq:0,message:d,shardKey:i,started:!1};this.streams.set(r,u);const f=c?.wsState==="open"&&v(c,d);if(u.started=f,!f&&c===void 0)return this.streams.delete(r),a.fail(new y("STREAM_DISCONNECTED","stream unavailable: this tab is not the cross-tab WebSocket leader, so it holds no socket to stream over")),o;if(!f){for(c.pendingStreams=c.pendingStreams??[];c.pendingStreams.length>=Je;){const m=c.pendingStreams.shift()?.id,b=m?this.streams.get(m):void 0;b&&(b.handle.fail(new y("STREAM_QUEUE_OVERFLOW","stream-start frame evicted while socket was unreachable")),this.streams.delete(m))}c.pendingStreams.push(d)}return o}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 Se(e,t,{baseUrl:this.url,fetch:this.fetchImpl,headers:r,maxBuffer:s.maxBuffer,signal:s.signal})}close(){this.closed=!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();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.shapeSubscriptions.clear(),this.pokeBuffers.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}teardownConnection(e){e.polling.stop();const t=l(e.shardKey);for(const[s,r]of this.streams)l(r.shardKey)===t&&(r.handle.fail(new y("STREAM_DISCONNECTED","stream terminated: the connection carrying it was torn down")),this.streams.delete(s));if(e.pendingStreams=void 0,e.pendingUnsubscribes=[],this.clearResubscribeQueue(e),this.clearConnectionTimers(e),this.stopHeartbeat(e),e.socket){try{e.socket.close()}catch{}e.socket=void 0}e.wsState="closed"}createTabCoordinator(){const e=`lunora-bridge::${this.url}::${this.identityFingerprint()??"anon"}`;return new be({channelName:e,onBecomeLeader:()=>{for(const t of this.subscriptions.all())this.ensureSocket(t.shardKey),this.queueResubscribe(t);for(const t of this.queuedOfflineShardKeys)this.ensureSocket(t);this.tabCoordinator?.broadcastConnectionStatus(this.computeStatus(),this.identityFingerprint())},onStopBeingLeader:()=>{for(const[t,s]of this.connections)this.teardownConnection(s),this.connections.delete(t);this.leaderStatus=void 0,this.leaderWasEverConnected=!1},onConnectionStatus:(t,s)=>{if(s!==void 0&&s!==this.identityFingerprint())return;const r=t==="connected"&&this.leaderStatus!=="connected"||t==="polling"&&this.leaderStatus!=="connected"&&this.leaderStatus!=="polling";this.leaderStatus=t,t==="connected"&&(this.leaderWasEverConnected=!0),this.emitConnectionStatus(),r&&this.flushAllOfflineQueues()},onSubscriptionData:(t,s,r,i,n)=>{if(n!==void 0&&n!==this.identityFingerprint())return;const a=this.subscriptions.get(t);a&&(a.serverBase=s,this.dropCacheSeed(t),r!==void 0&&(a.serverCursor=r,i!==void 0&&(a.serverEpoch=i),U(a,r)),_(a,A(s,a.optimisticLayers)))},onLeaderClaimAnswered:()=>{this.tabCoordinator?.isLeader()&&this.tabCoordinator.broadcastConnectionStatus(this.computeStatus(),this.identityFingerprint())},onSubscriptionError:(t,s,r)=>{if(r!==void 0&&r!==this.identityFingerprint())return;const i=this.subscriptions.get(t);i&&E(i.errorCallbacks,s)},onSubscriptionSettled:(t,s,r,i,n,a)=>{if(a!==void 0&&a!==this.identityFingerprint())return;const o=this.subscriptions.get(t);if(o){this.ackAndAdvanceCursor(o,s,r),i!==void 0&&n===this.clientId&&(o.lastMutationId=Math.max(o.lastMutationId??0,i));for(const c of o.checkpointCallbacks)c({checkpoint:o.serverCursor,mutationId:o.lastMutationId})}}})}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,N),{body:JSON.stringify({calls:e.map((a,o)=>({args:C(a.args??{},`args for batch call '${a.fn.__lunoraRef}'`),functionPath:a.fn.__lunoraRef,id:o,shardKey:a.shardKey}))}),headers:this.rpcRequestHeaders({attachBookmark:!0}),method:"POST",signal:t}),r=s.headers.get("x-d1-bookmark");r&&this.bookmark.set(r);let i;try{i=await s.json()}catch{throw new y("INTERNAL",`LunoraClient: batch response was not JSON (status ${s.status.toString()})`)}const n=F(i);if(!s.ok||n!==void 0&&!i.results)throw n!==void 0?W(n):new y("INTERNAL",`LunoraClient: batch request failed (status ${s.status.toString()})`);for(const a of i.results??[]){const o=a.body?.commitCursor;typeof a.id=="number"&&typeof o=="number"&&this.recordShardCursor(e[a.id]?.shardKey,o)}return ks(i.results??[],e.length)}async runMutation(e,t,s){this.assertOpen();const r=t,i=s.mutationId??z(),n=s.replayBaseline===void 0?this.baselineCursorFor(s.shardKey):s.replayBaseline??void 0,{confirms:a,rollbacks:o}=this.applyOptimisticUpdates(e.__lunoraRef,r,s.shardKey,s.optimistic);s.optimisticUpdate&&this.applyOptimisticUpdate(s.optimisticUpdate,t,s.shardKey,o,a);const c=this.offlineFlushes.get(l(s.shardKey));c!==void 0&&await c;const{hasSocket:d,polling:u,wasEverConnected:f,wsState:p}=this.connectionGateState(s.shardKey),{queueBeforeFirstConnect:m}=this.offlineQueue,b=f||m,w=this.WebSocketImpl!==void 0&&b,ce=p==="connecting"&&b&&!u,he=p!=="open"&&!d&&w&&!u,de=w&&s.replayBaseline===void 0&&this.hasPendingWriteAhead(s.shardKey),$=async()=>this.enqueueOfflineMutation(e,r,s.shardKey,n,i,o,a,s.precondition,s.mutationId);if(he||ce||de)return $();try{let R;const ue=await this.rpc(e.__lunoraRef,r,s.shardKey,{baselineSeq:n,captureBookmark:!0,mutationId:i,onCommitCursor:H=>{R=H}});for(const H of a)H(R);return{committed:!0,value:ue}}catch(R){if(u&&w&&R instanceof TypeError&&ie(r))return $();throw P(o),R}}async enqueueOfflineMutation(e,t,s,r,i,n,a,o,c){const d=this.identityFingerprint();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:c??`${this.clientId}:${String(f)}`,identity:d,mutationId:f,...n.length>0&&{onRejected:()=>{P(n)}},shardKey:s})}catch(p){throw P(n),p instanceof Error?p:new Error(String(p))}for(const p of a)p(void 0);return{committed:!1,value:void 0}}return{committed:!0,value:await new Promise((f,p)=>{const m={args:t,functionPath:e.__lunoraRef,liveAwaiter:!0,baselineSeq:r,id:i,clientId:this.clientId,identity:d,precondition:o,onCommit:b=>{for(const w of a)w(b)},reject:b=>{this.queuedIdentities.delete(i),P(n),p(b instanceof Error?b:new Error(String(b)))},resolve:f,shardKey:s};this.offlineQueue.enqueue(m),this.queuedOfflineShardKeys.add(s),m.id!==void 0&&this.queuedIdentities.set(m.id,d)})}}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(I(s.fn.__lunoraRef,s.argsKey,s.shardKey),s);for(const{key:s,...r}of e){if(we(this.persistenceVersion,r.version)){this.queryCache.remove(s).catch(()=>{});continue}const i=t.get(s);if(i&&this.cachedQueryMatchesIdentity(r)){this.seedSubscriptionFromCache(i,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(I(e.fn.__lunoraRef,e.argsKey,e.shardKey),t),_(e,A(t.value,e.optimisticLayers)))}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,_(s,A(void 0,s.optimisticLayers))),this.hydratedQueryCache.set(e,t)}this.cacheSeededQueries.clear()}}takeHydratedCache(e,t,s){const r=I(e,t,s),i=this.hydratedQueryCache.get(r);if(!(i===void 0||!this.cachedQueryMatchesIdentity(i)))return this.hydratedQueryCache.delete(r),i}reseedFromHydratedCache(){if(this.hydratedQueryCache.size!==0)for(const e of this.subscriptions.all()){const t=I(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=I(e.fn.__lunoraRef,e.argsKey,e.shardKey),r=this.getConnection(e.shardKey)?.identity,i=r===void 0?this.identityFingerprint():r;i===null&&this.identityUnresolved()||(this.pendingCacheWrites.set(s,{identity:i,serverCursor:e.serverCursor,ts:Date.now(),value:t,...i===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(()=>{})},ze))}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.leaderStatus??"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 a of this.subscriptions.all())l(a.shardKey)===t&&(ie(a.args)?s.push(a):E(a.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=ke(),i=this.identityFingerprint();let n;try{n=await re(async a=>this.sendBatch(s.map(o=>({args:o.args,fn:o.fn,shardKey:o.shardKey})),a))}catch(a){return!(a instanceof TypeError)}if(this.identityFingerprint()!==i)return!0;for(const[a,o]of s.entries()){const c=n[a];if(c!==void 0){if(!c.ok){E(o.errorCallbacks,{code:c.error.code,message:c.error.message});continue}this.handleDataMessage({data:M(c.value),id:o.id,type:"data"},r)}}return!0}async probeOrigin(){const{fetchImpl:e}=this;if(!e)return!1;try{return await re(async t=>e(k(this.url,N),{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 i=[],n=[];if(!r)return{confirms:i,rollbacks:n};const a=T.key(e,t,s),o=this.subscriptions.get(a);if(o){const c=ve(o,r);c&&(i.push(c.confirm),n.push(c.rollback))}return{confirms:i,rollbacks:n}}applyOptimisticUpdate(e,t,s,r,i){const{confirms:n,rollbacks:a,store:o}=ge(this.subscriptions,s);try{e(o,t)}catch{P(a);return}r.push(...a),i.push(...n)}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 s="idle";return this.leaderStatus==="connected"?s="open":this.leaderStatus==="connecting"&&(s="connecting"),{hasSocket:!1,polling:this.leaderStatus==="polling",wasEverConnected:this.leaderWasEverConnected,wsState:s}}const t=this.getConnection(e);return{hasSocket:t?.socket!==void 0,polling:t?.polling.isPolling()??!1,wasEverConnected:t?.wasEverConnected??!1,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:Be({afterFailedAttempts:this.pollingFallbackAfterFailedAttempts,intervalMs:this.pollingFallbackIntervalMs,onReachable:()=>{this.flushOfflineQueue(e).catch(()=>{})},onStateChange:()=>{this.emitConnectionStatus()},poll:async()=>this.pollSubscriptions(e)}),reconnect:V(this.reconnectOptions),reconnectTimer:void 0,resubscribePending:new Map,resubscribeQueue:[],shardKey:e,socket:void 0,stableTimer:void 0,wasEverConnected:!1,wsState:"idle"},this.connections.set(t,s)),s}wsUrlFor(e,t){const s=[];if(e!==void 0&&s.push(`shard=${encodeURIComponent(e)}`),t!==void 0&&s.push(`token=${encodeURIComponent(t)}`),s.length===0)return this.wsUrl;const r=this.wsUrl.includes("?")?"&":"?";return`${this.wsUrl}${r}${s.join("&")}`}rpcRequestHeaders(e,t){const s={"content-type":"application/json"},r=this.shardCursors.get(this.cursorKeyFor(t));if(r!==void 0&&(s["x-lunora-min-seq"]=r.toString()),this.authToken&&(s.authorization=`Bearer ${this.authToken}`),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 i=this.bookmark.get();i&&(s["x-d1-bookmark"]=i)}return s}async rpc(e,t,s,r={}){if(!this.fetchImpl)throw new j("LunoraClient: no `fetch` implementation available");const i=this.rpcRequestHeaders(r,s),n=await this.fetchImpl(k(this.url,Qe),{body:JSON.stringify({args:C(t,`args for '${e}'`),functionPath:e,shardKey:s}),headers:i,method:"POST"});if(r.captureBookmark){const c=n.headers.get("x-d1-bookmark");c&&this.bookmark.set(c)}let a;try{a=await n.json()}catch{throw L(n.status,n.statusText,n.headers.get("retry-after"))}const o=F(a);if(o!==void 0)throw se(o,n.headers.get("retry-after"));if(!n.ok)throw L(n.status,n.statusText,n.headers.get("retry-after"));return r.onMutationAck?.(a.lastMutationId),r.onCommitCursor?.(a.commitCursor),this.learnDefaultShardKey(n,s),this.recordShardCursor(s,a.commitCursor),g(a.result)}async adminFetch(e,t,s,r){if(!this.fetchImpl)throw new y("INTERNAL","LunoraClient: no `fetch` implementation available");const i={};this.authToken&&(i.authorization=`Bearer ${this.authToken}`);const n=s instanceof ArrayBuffer||s instanceof Blob;let a;s===void 0?a=void 0:n?(a=s,r!==void 0&&(i["content-type"]=r)):(a=JSON.stringify(s),i["content-type"]="application/json");const o=await this.fetchImpl(k(this.url,e),{body:a,headers:i,method:t});let c;try{c=await o.json()}catch{const u=o.statusText?` ${o.statusText}`:"";throw new y("INTERNAL",`LunoraClient: response was not JSON (status ${o.status.toString()}${u})`)}const d=F(c);if(d!==void 0){const u=new Error(d.message??"admin request failed");throw u.code=d.code,u}if(!o.ok){const u=o.statusText?` ${o.statusText}`:"";throw new y("INTERNAL",`LunoraClient: admin request failed (status ${o.status.toString()}${u})`)}return c}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:bs,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){let r;try{r=await s()}catch{this.handleDisconnect(e);return}this.closed||this.WebSocketImpl===void 0||e.wsState!=="connecting"||e.socket!==void 0||this.openSocket(e,t,r)}openManagedSocket(e,t,s,r){const{WebSocketImpl:i}=this;if(i===void 0)throw new y("INTERNAL","no WebSocket implementation available");const n=new i(t);e.socket=n;const a=()=>{this.stopHeartbeat(e),e.connectTimer!==void 0&&(clearTimeout(e.connectTimer),e.connectTimer=void 0),e.socket===n&&(e.socket=void 0)},o=c=>{a(),r.onClose(c)};s>0&&(e.connectTimer=setTimeout(()=>{if(e.connectTimer=void 0,e.socket===n){try{n.close()}catch{}o()}},s)),n.addEventListener("open",()=>{if(e.socket===n){e.connectTimer!==void 0&&(clearTimeout(e.connectTimer),e.connectTimer=void 0),e.lastFrameAt=Date.now();try{r.onOpen?.()}catch(c){console.error("[lunora] connection open handler threw",c)}this.startHeartbeat(e,o)}}),n.addEventListener("message",c=>{if(e.socket===n){e.lastFrameAt=Date.now();try{r.onMessage(c)}catch(d){console.error("[lunora] server frame handler threw",d)}}}),n.addEventListener("close",c=>{e.socket===n&&o(c)}),n.addEventListener("error",()=>{e.socket===n&&o()})}openSocket(e,t,s){this.WebSocketImpl!==void 0&&(e.identity=this.identityFingerprint(),e.retired=!1,this.openManagedSocket(e,this.wsUrlFor(t,s),this.connectTimeoutMs,{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.polling.noteOpen(),clearTimeout(e.stableTimer),e.stableTimer=setTimeout(()=>{e.wsState==="open"&&e.reconnect.reset()},Ve),this.emitConnectionStatus(),this.sendConnectEnvelope(e),this.markShardPendingAck(t),this.clearResubscribeQueue(e);for(const i of this.subscriptions.all())l(i.shardKey)===l(t)&&this.queueResubscribe(i);if(this.resendShapeSubscriptions(t),e.pendingUnsubscribes.length>0){const i=e.pendingUnsubscribes;e.pendingUnsubscribes=[];for(const{id:n,type:a}of i)v(e,{id:n,type:a})}this.flushPendingStreams(e);const r=this.whisperHandlers.get(l(t));if(r)for(const i of r.keys())v(e,{topic:i,type:"whisper_subscribe"});this.flushOfflineQueue(t).catch(()=>{})}}))}flushPendingStreams(e){if(!e.pendingStreams||e.pendingStreams.length===0)return;const t=e.pendingStreams;e.pendingStreams=[];for(const s of t){const r=v(e,s)?this.streams.get(String(s.id)):void 0;r&&(r.started=!0)}}cancelStream(e,t){const s=this.getConnection(t),r=this.streams.get(e);s&&(s.pendingStreams=s.pendingStreams?.filter(i=>i.id!==e),!v(s,{id:e,type:"unsubscribe"})&&r?.durable===!0&&r.started&&s.pendingUnsubscribes.push({id:e,type:"unsubscribe"})),this.streams.delete(e)}handleDisconnect(e){if(this.closed||e.wsState==="idle"||e.wsState==="closed")return;e.wsState==="connecting"&&e.polling.noteFailedOpen(),this.stopHeartbeat(e),this.clearConnectionTimers(e),e.socket=void 0,e.wsState="idle",this.emitConnectionStatus(),this.markShardPendingAck(e.shardKey),this.clearResubscribeQueue(e);const t=new Set((e.pendingStreams??[]).map(r=>r.id));for(const[r,i]of this.streams)if(!(l(i.shardKey)!==l(e.shardKey)||t.has(r))){if(i.durable){const n={...i.message,...i.generation===void 0?{}:{generation:i.generation},sinceChunk:i.lastSeq};i.message=n,e.pendingStreams=[...(e.pendingStreams??[]).filter(a=>a.id!==r),n];continue}i.handle.fail(new y("STREAM_DISCONNECTED","stream terminated: WebSocket disconnected")),this.streams.delete(r)}if(this.WebSocketImpl===void 0)return;const s=e.reconnect.next();e.reconnectTimer=setTimeout(()=>{e.reconnectTimer=void 0,this.ensureSocket(e.shardKey)},s)}startHeartbeat(e,t){this.stopHeartbeat(e),!(this.heartbeatIntervalMs<=0)&&(e.heartbeatTimer=setInterval(()=>{if(!e.socket)return;const{socket:s}=e;if(Date.now()-e.lastFrameAt>this.heartbeatIntervalMs*2.5){try{s.close()}catch{}t();return}try{s.send(Ke)}catch{}},this.heartbeatIntervalMs))}stopHeartbeat(e){e.heartbeatTimer!==void 0&&(clearInterval(e.heartbeatTimer),e.heartbeatTimer=void 0)}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<Ye;){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)},Xe))}}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=gs(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 i=this.getConnection(t);i&&this.releaseResubscribeSlot(i,r.id)}switch(r.type){case"ack":{const i=this.subscriptions.getById(r.id);i&&(i.acked=!0);return}case"chunk":{const{data:i,generation:n,id:a,seq:o}=r,c=this.streams.get(a);c&&typeof o=="number"&&(c.lastSeq=o,typeof n=="number"&&(c.generation=n),c.durable=!0),c?.handle.push(g(i));return}case"complete":{this.handleCompleteMessage(r.id);return}case"data":case"delta":{this.handleDataMessage(r);return}case"error":{this.handleErrorMessage(r);break}case"pokeEnd":{this.handlePokeEnd(r,t);break}case"pokePart":{this.handlePokePart(r,t);break}case"pokeStart":{this.handlePokeStart(r,t);break}case"resume":{this.handleResumeMessage(r);break}case"settled":{this.handleSettledMessage(r);break}case"whisper":{this.dispatchWhisper(r,t);break}}}handleErrorMessage(e){if(e.error?.code==="TOKEN_EXPIRED"){this.notifyTokenExpired();return}const{id:s}=e,r=s===void 0?void 0:this.streams.get(s);if(r&&s!==void 0){r.handle.fail(Ss(e)),this.streams.delete(s);return}const i=s===void 0?void 0:this.subscriptions.getById(s);if(i){const a=te(e),o=this.identityFingerprint(),c=T.keyOf(i);E(i.errorCallbacks,a),this.tabCoordinator?.isLeader()&&this.tabCoordinator.broadcastSubscriptionError(c,a,o);return}const n=s===void 0?void 0:this.shapeSubscriptions.get(s);n&&E(n.errorCallbacks,te(e))}pokeBufferKey(e,t){return`${l(e)}\0${t}`}handlePokeStart(e,t){J(this.pokeBuffers,oe.MAX_POKE_BUFFERS),this.pokeBuffers.set(this.pokeBufferKey(t,e.pokeId),{baseCheckpoint:e.baseCheckpoint,bases:new Map,epoch:e.epoch,lastMutationId:new Map,parts:new Map,resets:new Set})}handlePokePart(e,t){const s=this.pokeBuffers.get(this.pokeBufferKey(t,e.pokeId));if(!s)return;const r=s.parts.get(e.shapeId)??[];for(const n of e.rowsPatch)r.push(n.value===void 0?n:{...n,value:g(n.value)});s.parts.set(e.shapeId,r),e.lastMutationId!==void 0&&s.lastMutationId.set(e.shapeId,e.lastMutationId);const i=e.baseCheckpoint??s.baseCheckpoint;i!==void 0&&s.bases.set(e.shapeId,i),e.reset===!0&&s.resets.add(e.shapeId)}handlePokeEnd(e,t){const s=this.pokeBufferKey(t,e.pokeId),r=this.pokeBuffers.get(s);if(r){this.pokeBuffers.delete(s);for(const i of r.parts.keys()){const n=this.shapeSubscriptions.get(i);n&&this.applyPokePart(n,r,e)}}}applyPokePart(e,t,s){const r=t.parts.get(e.id)??[],i=t.resets.has(e.id),n=t.bases.get(e.id),a=t.epoch!==void 0&&e.serverEpoch!==void 0&&t.epoch!==e.serverEpoch,o=n!==void 0&&e.serverCursor!==void 0&&e.serverCursor!==n;if(!i&&(a||o)){e.rows.clear(),e.serverCursor=void 0,e.serverEpoch=void 0,this.emitShapeRows(e),this.sendShapeSubscribeIfOpen(e);return}i&&e.rows.clear(),De(e.rows,r),s.checkpoint!==void 0&&(e.serverCursor=s.checkpoint),s.epoch!==void 0&&(e.serverEpoch=s.epoch);const c=t.lastMutationId.get(e.id);c!==void 0&&(e.lastMutationId=c),this.emitShapeRows(e),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)}emitShapeRows(e){const t=[...e.rows.values()];for(const s of e.callbacks)try{s(t)}catch{}}handleDataMessage(e,t){const{id:s}=e,r=s?this.subscriptions.getById(s):void 0;if(!r)return;let i;try{i=this.resolveDataPayload(e,r)}catch(n){E(r.errorCallbacks,{code:"WIRE_DECODE_FAILED",message:`could not decode a server frame for this subscription — ${n instanceof Error?n.message:String(n)}`});return}if(i===Y){this.resnapshotSubscription(r);return}if(r.serverBase=i,this.dropCacheSeed(T.keyOf(r)),e.cursor!==void 0&&(r.serverCursor=e.cursor),e.epoch!==void 0&&(r.serverEpoch=e.epoch),e.lastMutationId!==void 0){r.lastMutationId=Math.max(r.lastMutationId??0,e.lastMutationId);for(const n of r.checkpointCallbacks)n({checkpoint:r.serverCursor,mutationId:r.lastMutationId,rowsFollow:!0})}if(this.persistQueryValue(r),U(r,r.serverCursor),t!==void 0&&Te(r,t),_(r,A(i,r.optimisticLayers)),this.tabCoordinator?.isLeader()){const n=T.keyOf(r);this.tabCoordinator.broadcastSubscriptionData(n,i,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&&(t.lastMutationId=Math.max(t.lastMutationId??0,e.lastMutationId));for(const s of t.checkpointCallbacks)s({checkpoint:t.serverCursor,mutationId:t.lastMutationId});if(this.tabCoordinator?.isLeader()){const s=T.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),U(e,e.serverCursor)&&_(e,A(e.serverBase,e.optimisticLayers)))}resolveDataPayload(e,t){if("data"in e&&e.data!==void 0)return g(e.data);const s=g(e.delta);return le(s)?t.serverBase===void 0?s:fe(t.serverBase,s)??Y:s}dispatchWhisper(e,t){const s=this.whisperHandlers.get(l(t))?.get(e.topic);if(!s)return;const r=g(e.data);for(const i of s)try{i(r,e.from)}catch{}}notifyTokenExpired(){this.tokenExpiredListeners.emit()}handleCompleteMessage(e){const t=this.streams.get(e);if(t){t.handle.complete(),this.streams.delete(e);return}const s=this.subscriptions.getById(e);s&&(s.acked=!1,E(s.errorCallbacks,{code:"SUBSCRIPTION_CANCELLED",message:"subscription was cancelled by the server"}))}unpersist(e){e&&this.persistence?.remove(e).catch(t=>{Ee(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 i=e.charCodeAt(r);t^=i,t=Math.imul(t,16777619),s=Math.imul(s,33)+i}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&&Z(this.computeStatus())&&this.flushAllOfflineQueues()}identityUnresolved(){return this.sessionProbesInFlight>0?!0:this.identityResolutionExpected&&!this.identitySettled}adoptResolvedSubject(e,t,s){this.closed||t===null||this.authToken!==e||s!==this.sessionProbeGeneration||this.setAuthToken(e,t.id)}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}rejectQueuedForIdentityChange(e){const t=this.offlineQueue.drain(),s=[];for(const r of t){if(this.replayIdentityVerdict(this.stampOf(r))!=="mismatch"){s.push(r);continue}this.queuedIdentities.delete(r.id??""),this.unpersist(r.id);const i=new Error("offline mutation discarded: auth identity changed before replay");i.code="OFFLINE_IDENTITY_CHANGED",r.reject(i),this.emitItemSettled(r,"rejected",i)}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 i=t??"",n=this.clientWatermarks.get(i);if(n===void 0)this.clientWatermarks.set(i,r);else for(const[a,o]of r)n.set(a,o)}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.revokeCacheSeededValues();for(const e of this.subscriptions.all())e.serverBase=void 0,e.serverCursor=void 0,e.serverEpoch=void 0,e.acked=!1,_(e,A(void 0,e.optimisticLayers));for(const e of this.shapeSubscriptions.values())e.rows.clear(),e.serverCursor=void 0,e.serverEpoch=void 0,this.emitShapeRows(e);this.bounceShardSockets(),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()}bounceShardSockets(){for(const e of this.connections.values())if(e.socket){e.retired=!0;try{e.socket.close()}catch{}}}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());try{await this.drainOfflineQueue(e)}catch{}})();this.offlineFlushes.set(t,r),await r,this.offlineFlushes.get(t)===r&&this.offlineFlushes.delete(t)}async drainOfflineQueue(e){const t=this.offlineQueue.drainConflict();for(const c of t){this.unpersist(c.id),this.queuedIdentities.delete(c.id??"");const d=new Error("offline mutation skipped: precondition failed before replay");d.code="OFFLINE_PRECONDITION_FAILED",this.emitItemSettled(c,"rejected",d)}const s=l(e),r=this.offlineQueue.drain(c=>l(c.shardKey)===s);if(r.length===0)return;const i=[],n=[];for(const c of r){const d=this.replayGateVerdict(c);d==="send"?i.push(c):d==="hold"&&n.push(c)}if(this.offlineQueue.requeue(n),n.length>0&&this.subjectAwaitingReconfirm()&&(this.getCurrentUser().catch(()=>{}),this.noteHeldRetryDelay(e)),i.length===0){this.scheduleRateLimitedRetry(e);return}const a=this.encodableOrSettleTerminal(i);if(a.length===0){this.scheduleRateLimitedRetry(e);return}if(a.length===1){await this.replaySequential(a,e),this.scheduleRateLimitedRetry(e);return}const o=[];for(let c=0;c<a.length;c+=x){const d=a.slice(c,c+x),u=await this.replayBatched(d,e);if(o.push(...u.requeue),u.stop){o.push(...a.slice(c+x));break}}o.length>0&&this.offlineQueue.requeue(o),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,Ie(r))})}noteReplayRetryDelay(e,t){const s=l(e),r=this.replayRetryState.get(s),i=(r?.attempts??0)+1,n=Oe(t,i);this.replayRetryState.set(s,{attempts:i,delayMs:n===void 0?r?.delayMs:Math.max(r?.delayMs??0,n)})}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 i=this.replayRetryTimers.get(t);i!==void 0&&clearTimeout(i),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}replayGateVerdict(e){const t=this.stampOf(e);if(t===void 0)return this.queuedIdentities.delete(e.id??""),"send";const s=this.replayIdentityVerdict(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){if(Re(e)){const t=this.hashToken(this.authToken??"");return this.authRefusalNotifiedFor!==t&&(this.authRefusalNotifiedFor=t,this.notifyTokenExpired()),!0}return Pe(e)}settleReplayTerminal(e,t){this.unpersist(e.id),e.reject(t),this.emitItemSettled(e,"rejected",t)}async replaySequential(e,t){for(let s=0;s<e.length;s+=1){const r=e[s];if(r)try{let i;const n=await this.rpc(r.functionPath,r.args,r.shardKey,{baselineSeq:r.baselineSeq,captureBookmark:!0,clientId:r.clientId??this.clientId,mutationId:r.id,onCommitCursor:a=>{i=a}});this.settleReplaySuccess(r,n,i)}catch(i){if(!this.shouldRequeueReplayFailure(i)){this.settleReplayTerminal(r,i);continue}this.noteReplayRetryDelay(t,i),this.offlineQueue.requeue(e.slice(s));return}}}async replayBatched(e,t){if(!this.fetchImpl)return{requeue:e,stop:!0};const s=JSON.stringify({calls:e.map((o,c)=>({args:C(o.args,`args for '${o.functionPath}'`),baselineSeq:o.baselineSeq,functionPath:o.functionPath,id:c,clientId:o.clientId??this.clientId,mutationId:o.id,shardKey:o.shardKey}))});if(e.length>1&&Fe(s)>Me)return await this.replayBatchedHalves(e,t);let r;try{r=await this.fetchImpl(k(this.url,N),{body:s,headers:this.rpcRequestHeaders({attachBookmark:!0}),method:"POST"})}catch{return{requeue:e,stop:!0}}const i=r.headers.get("x-d1-bookmark");if(i&&this.bookmark.set(i),r.status===413&&e.length>1)return await this.replayBatchedHalves(e,t);let n;const a=r.headers.get("retry-after");try{n=await r.json()}catch{return this.settleWholeBatchError(e,L(r.status,r.statusText,a),t)}if(!n.results){const o=F(n),c=o===void 0?L(r.status,r.statusText,a):se(o,a);return this.settleWholeBatchError(e,c,t)}return{requeue:this.settleReplayBatchSlots(e,n.results,t),stop:!1}}settleWholeBatchError(e,t,s){if(t instanceof j||t.code!==void 0&&this.shouldRequeueReplayFailure(t))return this.noteReplayRetryDelay(s,t),{requeue:e,stop:!0};for(const r of e)this.settleReplayTerminal(r,t);return{requeue:[],stop:!1}}async replayBatchedHalves(e,t){const s=Math.ceil(e.length/2),r=await this.replayBatched(e.slice(0,s),t);if(r.stop)return{requeue:[...r.requeue,...e.slice(s)],stop:!0};const i=await this.replayBatched(e.slice(s),t);return{requeue:[...r.requeue,...i.requeue],stop:i.stop}}settleReplayBatchSlots(e,t,s){const r=new Map;for(const n of t)typeof n.id=="number"&&n.body!==void 0&&r.set(n.id,n.body);const i=[];for(const[n,a]of e.entries()){const o=r.get(n);if(o===void 0)i.push(a);else if("error"in o){const c=ae(o);this.shouldRequeueReplayFailure(c)?(this.noteReplayRetryDelay(s,c),i.push(a)):this.settleReplayTerminal(a,c)}else this.settleReplaySuccess(a,g(o.result),o.commitCursor)}return i}}export{oe as LunoraClient};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{c as t}from"./local-store-CWeFEk6w.mjs";import"./SubscriptionRegistry-CS-AFUI9.mjs";export{t as createLocalStore};
|
package/dist/packem_shared/{createServerClient-CzDIXbC4.mjs → createServerClient-C0jOZaix.mjs}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{LunoraClient as r}from"./LunoraClient-
|
|
1
|
+
import{LunoraClient as r}from"./LunoraClient-Cj6Z6KeC.mjs";const c=e=>{const t=new r({fetch:e.fetch,url:e.url});return e.token!==void 0&&t.setAuthToken(e.token),t};export{c as createServerClient};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import{LunoraError as f}from"@lunora/errors";import{d as p}from"./wire-codec-Sw1rAu-Z.mjs";import{createStream as u}from"./DEFAULT_MAX_BUFFER-D3QH2iaq.mjs";const m=/^ /u,h=t=>typeof t=="object"&&t!==null?JSON.stringify(t):String(t),S=t=>{let s="";const e=[];for(const o of t.split(`
|
|
2
|
+
`))o.startsWith("event:")?s=o.slice(6).replace(m,""):o.startsWith("data:")&&e.push(o.slice(5).replace(m,""));return{data:e.join(`
|
|
3
|
+
`),event:s}},T=(t,s,e)=>{const o=s.params??{},c=t.path.split("/").map(a=>{if(!a.startsWith(":"))return a;const n=a.slice(1),r=o[n];if(r===void 0)throw new f("HTTP_STREAM_MISSING_PARAM",`httpStream: missing path param ":${n}" for route ${t.path}`);return encodeURIComponent(h(r))}).join("/"),i=new URLSearchParams;for(const[a,n]of Object.entries(s.searchParams??{}))n!==void 0&&i.set(a,h(n));const l=i.toString();return`${e.endsWith("/")?e.slice(0,-1):e}${c}${l===""?"":`?${l}`}`},E=(t,s)=>{if(t.event==="complete")return s.complete(),!0;if(t.event==="error"){let e={};try{e=JSON.parse(t.data)}catch{}const o=typeof e.message=="string"?e.message:"stream error",c=typeof e.code=="string"?e.code:"HTTP_STREAM_ERROR";return s.fail(new f(c,o)),!0}if((t.event===""||t.event==="message")&&t.data!=="")try{s.push(p(JSON.parse(t.data)))}catch{return s.fail(new f("HTTP_STREAM_BAD_CHUNK","httpStream: malformed SSE chunk (invalid JSON)")),!0}return!1},b=async(t,s)=>{const e=t.getReader(),o=new TextDecoder;let c="",i=!1;const l=a=>{let n=i?`\r${a}`:a;i=n.endsWith("\r"),i&&(n=n.slice(0,-1)),c+=n.replaceAll(`\r
|
|
4
|
+
`,`
|
|
5
|
+
`)},d=()=>{let a=c.indexOf(`
|
|
6
|
+
|
|
7
|
+
`);for(;a!==-1;){const n=S(c.slice(0,a));if(c=c.slice(a+2),E(n,s))return!0;a=c.indexOf(`
|
|
8
|
+
|
|
9
|
+
`)}return!1};for(;;){const{done:a,value:n}=await e.read();if(a)break;if(l(o.decode(n,{stream:!0})),d()){await e.cancel().catch(()=>{});return}}l(o.decode()),d()||s.fail(new f("HTTP_STREAM_INTERRUPTED","httpStream: stream ended without a complete frame"))},_=(t,s,e={})=>{const o=e.fetch??(typeof fetch=="function"?fetch.bind(globalThis):void 0);if(!o)throw new f("INTERNAL","httpStream: no `fetch` implementation available");const c=T(t,s??{},e.baseUrl??""),i=new AbortController;let l;e.signal&&(e.signal.aborted?i.abort():(l=()=>{i.abort()},e.signal.addEventListener("abort",l,{once:!0})));const d=()=>{l&&e.signal?.removeEventListener("abort",l)},{handle:a,iterable:n}=u({maxBuffer:e.maxBuffer,onCancel:()=>{i.abort()}});return(async()=>{try{const r=await o(c,{headers:{accept:"text/event-stream",...e.headers},method:t.method,signal:i.signal});if(!r.ok){await r.body?.cancel().catch(()=>{}),a.fail(new f("HTTP_STREAM_STATUS",`httpStream: request failed (status ${r.status.toString()})`,{status:r.status}));return}if(!r.body){a.fail(new f("HTTP_STREAM_NO_BODY","httpStream: response has no body"));return}await b(r.body,a)}finally{d()}})().catch(r=>{if(i.signal.aborted){a.complete();return}if(r instanceof Error&&"code"in r){a.fail(r);return}a.fail(new f("HTTP_STREAM_TRANSPORT",r instanceof Error?r.message:String(r),{cause:r}))}),n};export{_ as httpStream};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{SubscriptionRegistry as m}from"./SubscriptionRegistry-CS-AFUI9.mjs";let f=0;const L=()=>f,p=(r,e)=>{let t=r;for(const i of e)try{t=i.transform(t)}catch{}return t},d=(r,e)=>{if(e!==r.lastValue){r.lastValue=e;for(const t of r.callbacks)try{t(e)}catch{}}},y=(r,e)=>{let t;try{t=e(r.lastValue)}catch{return}const i={id:Symbol("optimistic"),transform:e};let c=!1;r.optimisticLayers.push(i),d(r,t);const a=()=>{const o=r.optimisticLayers.findIndex(n=>n.id===i.id);return o===-1?!1:(r.optimisticLayers.splice(o,1),!0)},s=()=>{d(r,p(r.serverBase,r.optimisticLayers))};return{confirm:o=>{if(o===void 0){a();return}i.commitCursor=o,f+=1,i.acknowledgedAt=f,r.serverCursor!==void 0&&r.serverCursor>=o&&a()&&s()},rollback:()=>{c||(c=!0,a(),s())}}},k=(r,e)=>{if(e===void 0||r.optimisticLayers.length===0)return!1;const t=r.optimisticLayers.length;return r.optimisticLayers=r.optimisticLayers.filter(i=>i.commitCursor===void 0||i.commitCursor>e),r.optimisticLayers.length!==t},h=(r,e)=>{r.optimisticLayers.length!==0&&(r.optimisticLayers=r.optimisticLayers.filter(t=>t.acknowledgedAt===void 0||t.acknowledgedAt>e))},v=(r,e)=>{const t=[],i=[],c=(s,o)=>r.get(m.key(s,o,e));return{confirms:t,rollbacks:i,store:{getAllQueries:s=>{const o=[];for(const n of r.all())n.fn.__lunoraRef===s.__lunoraRef&&(n.shardKey??"")===(e??"")&&o.push({args:n.args,value:n.lastValue});return o},getQuery:(s,o)=>c(s.__lunoraRef,o??{})?.lastValue,setQuery:(s,o,n)=>{const u=c(s.__lunoraRef,o??{});if(!u)return;const l=y(u,()=>n);l&&(t.push(l.confirm),i.push(l.rollback))}}}};export{y as a,h as b,v as c,k as d,L as e,p as f,d as n};
|
package/dist/packem_shared/{lunora-client.d-Cqp1YHAJ.d.mts → lunora-client.d-DWo4CzIH.d.mts}
RENAMED
|
@@ -252,7 +252,11 @@ interface OutboxMutation {
|
|
|
252
252
|
/** Stable per-client id; pairs with {@link OutboxMutation.mutationId} as `idempotencyKey`. */
|
|
253
253
|
clientId: string;
|
|
254
254
|
functionPath: string;
|
|
255
|
-
/**
|
|
255
|
+
/**
|
|
256
|
+
* `${clientId}:${mutationId}`, or the caller's own `mutationId` when it passed
|
|
257
|
+
* one (an `importRows` chunk) — sent as `x-lunora-mutation-id` so a replay is
|
|
258
|
+
* server-idempotent.
|
|
259
|
+
*/
|
|
256
260
|
idempotencyKey: string;
|
|
257
261
|
/** Issuing identity fingerprint (`null` = signed out); drives the sink's identity guard. */
|
|
258
262
|
identity: string | null;
|
|
@@ -1255,6 +1259,12 @@ type SubscriptionErrorCallback = (error: SubscriptionError) => void;
|
|
|
1255
1259
|
* in-flight (so the overlay survives unrelated deltas until confirmed).
|
|
1256
1260
|
*/
|
|
1257
1261
|
interface OptimisticLayer {
|
|
1262
|
+
/**
|
|
1263
|
+
* Where this write's RPC resolved in the process-wide acknowledgement order
|
|
1264
|
+
* (see `acknowledgementMark`); `undefined` until confirmed. A polled snapshot
|
|
1265
|
+
* carries no cursor, so this is what lets it drop the layer instead.
|
|
1266
|
+
*/
|
|
1267
|
+
acknowledgedAt?: number;
|
|
1258
1268
|
/** The committed CDC cursor (from the mutation response); `undefined` until confirmed. */
|
|
1259
1269
|
commitCursor?: number;
|
|
1260
1270
|
readonly id: symbol;
|
|
@@ -1473,8 +1483,9 @@ type WSState = "idle" | "connecting" | "open" | "closed";
|
|
|
1473
1483
|
* is (re)connecting and none is open; `connected` = at least one socket is open;
|
|
1474
1484
|
* `polling` = no socket would open, so live queries are being refreshed over HTTP
|
|
1475
1485
|
* instead (see {@link file://./polling-fallback.ts} — live but slower, and shapes
|
|
1476
|
-
* / streams / whispers are dark
|
|
1477
|
-
* (between reconnect
|
|
1486
|
+
* / streams / whispers are dark; mutations go over HTTP as they do while
|
|
1487
|
+
* connected); `offline` = sockets exist but all are down (between reconnect
|
|
1488
|
+
* attempts), and a poll could not reach the origin either.
|
|
1478
1489
|
*
|
|
1479
1490
|
* `polling` outranks `connecting`: while the fallback is running a reconnect is
|
|
1480
1491
|
* still armed in the background, and reporting that attempt would flicker the
|
|
@@ -1952,6 +1963,8 @@ declare class LunoraClient {
|
|
|
1952
1963
|
private readonly statusListeners;
|
|
1953
1964
|
/** Subscribers notified when the server drops a socket for an expired token (see `onTokenExpired`). */
|
|
1954
1965
|
private readonly tokenExpiredListeners;
|
|
1966
|
+
/** Subscribers notified when the previous identity's session is retired (see `onIdentityChange`). */
|
|
1967
|
+
private readonly identityChangeListeners;
|
|
1955
1968
|
/** Token hash the last durable-replay auth refusal fired `onTokenExpired` for — see `shouldRequeueReplayFailure`. */
|
|
1956
1969
|
private authRefusalNotifiedFor;
|
|
1957
1970
|
/** Subscribers to offline-queued mutation verdicts (see `onMutationSettled`). */
|
|
@@ -2189,6 +2202,19 @@ declare class LunoraClient {
|
|
|
2189
2202
|
* the current value.
|
|
2190
2203
|
*/
|
|
2191
2204
|
onAuthTokenChange(listener: (token: string | null) => void): Unsubscribe;
|
|
2205
|
+
/**
|
|
2206
|
+
* Subscribe to a user switch or sign-out: fired after {@link setAuthToken}
|
|
2207
|
+
* retires the previous identity's session, i.e. every live subscription has
|
|
2208
|
+
* just been blanked to `undefined` and its socket closed. Not fired when an
|
|
2209
|
+
* identity is first established from signed-out (nothing is retired), nor
|
|
2210
|
+
* when a subject is attached to the same credential.
|
|
2211
|
+
*
|
|
2212
|
+
* For caches layered on top of the client. A subscriber only hears the
|
|
2213
|
+
* blank for queries it still subscribes to, so a cache that keeps values for
|
|
2214
|
+
* unmounted queries must drop them here, or the next user can read the
|
|
2215
|
+
* previous user's rows from it.
|
|
2216
|
+
*/
|
|
2217
|
+
onIdentityChange(listener: () => void): Unsubscribe;
|
|
2192
2218
|
/**
|
|
2193
2219
|
* Fetch the currently authenticated user from better-auth's `get-session`
|
|
2194
2220
|
* endpoint, returning the `user` record or `null` when signed out. Sends
|
|
@@ -2533,16 +2559,24 @@ declare class LunoraClient {
|
|
|
2533
2559
|
* {@link LunoraClient.importRows} documents the same caveat for its counts.
|
|
2534
2560
|
*/
|
|
2535
2561
|
mutation<F extends FunctionReference>(function_: F, args: ArgsOf<F>, options?: MutationCallOptions<unknown, unknown, ArgsOf<F>>): Promise<ReturnOf<F>>;
|
|
2562
|
+
/**
|
|
2563
|
+
* Whether a {@link mutation} on `shardKey` would be queued (offline queue or
|
|
2564
|
+
* durable outbox) rather than fail when the network is down. `false` before
|
|
2565
|
+
* the shard's first connect (unless `queueBeforeFirstConnect` is set) and on
|
|
2566
|
+
* a client with no WebSocket. A caller that wants to hold a write until the
|
|
2567
|
+
* network returns must do so itself when this is `false`.
|
|
2568
|
+
*/
|
|
2569
|
+
canQueueOffline(shardKey?: string): boolean;
|
|
2536
2570
|
action<F extends FunctionReference>(function_: F, args: ArgsOf<F>, options?: ActionCallOptions): Promise<ReturnOf<F>>;
|
|
2537
2571
|
/**
|
|
2538
2572
|
* Bulk-import `rows` through a mutation that accepts a batch, chunked so a large
|
|
2539
2573
|
* dataset lands in a bounded number of round-trips.
|
|
2540
2574
|
*
|
|
2541
|
-
* **
|
|
2542
|
-
*
|
|
2543
|
-
*
|
|
2544
|
-
*
|
|
2545
|
-
*
|
|
2575
|
+
* **Queued chunks:** `imported` counts only rows the server committed. A chunk a
|
|
2576
|
+
* durable outbox took instead (offline, or behind older queued writes) is counted
|
|
2577
|
+
* in `queued`; the outbox replays it later under the same key. The built-in
|
|
2578
|
+
* offline queue holds the call until each chunk commits, so its rows land in
|
|
2579
|
+
* `imported`. Report "migration complete" only when `queued` is `0`.
|
|
2546
2580
|
*
|
|
2547
2581
|
* This is the one-shot migration / seed path: "I have 20k rows client-side and a
|
|
2548
2582
|
* server mutation that inserts many at once". Doing it by hand goes wrong in two
|
|
@@ -2550,7 +2584,8 @@ declare class LunoraClient {
|
|
|
2550
2584
|
* wait per row (a 200-row import becomes 200 sequential hops), while a single
|
|
2551
2585
|
* giant call blows the DO's batch limit. So: chunk, send sequentially, and give
|
|
2552
2586
|
* each chunk a stable idempotency key derived from `importId` + its index, so a
|
|
2553
|
-
* resumed or retried import doesn't double-insert the chunks that already landed
|
|
2587
|
+
* resumed or retried import doesn't double-insert the chunks that already landed
|
|
2588
|
+
* (for an anonymous caller only while the `clientId` is the same; see `importId`).
|
|
2554
2589
|
*
|
|
2555
2590
|
* The server mutation is yours (Lunora can't guess the table or the row shape);
|
|
2556
2591
|
* back it with `ctx.db.insertMany(...)`, or `insertManyUnsafe(...)` for data you
|
|
@@ -2581,15 +2616,18 @@ declare class LunoraClient {
|
|
|
2581
2616
|
* SILENTLY DROPS those rows. Keep `chunkSize` (and the row order) identical
|
|
2582
2617
|
* across resumes of the same `importId`. Omit `importId` only for a
|
|
2583
2618
|
* throwaway import where double-insertion is acceptable.
|
|
2619
|
+
*
|
|
2620
|
+
* CAVEAT — anonymous callers: the server scopes the key to the signed-in
|
|
2621
|
+
* user, or to the client's `clientId` when nobody is signed in. A
|
|
2622
|
+
* `LunoraClient` mints a fresh `clientId` on every construction, so an
|
|
2623
|
+
* anonymous import resumed after a reload is not deduped and inserts the
|
|
2624
|
+
* landed chunks again. Pass a persisted `clientId` to the constructor to
|
|
2625
|
+
* resume anonymously, or run the import signed in.
|
|
2584
2626
|
*/
|
|
2585
2627
|
importId?: string;
|
|
2586
2628
|
/**
|
|
2587
|
-
* Called after each chunk is accepted — for a progress bar.
|
|
2588
|
-
*
|
|
2589
|
-
* "Accepted" is not always "committed": while offline (or mid-reconnect) a
|
|
2590
|
-
* `mutation` resolves as soon as the write is durably **queued**, so a fully
|
|
2591
|
-
* offline import reports completion with nothing yet applied server-side.
|
|
2592
|
-
* Gate a migration's "done" state on connectivity, not just on this.
|
|
2629
|
+
* Called after each chunk is accepted — for a progress bar. `done` counts
|
|
2630
|
+
* committed and queued rows alike; the result separates them.
|
|
2593
2631
|
*/
|
|
2594
2632
|
onProgress?: (progress: {
|
|
2595
2633
|
done: number;
|
|
@@ -2602,6 +2640,7 @@ declare class LunoraClient {
|
|
|
2602
2640
|
}): Promise<{
|
|
2603
2641
|
chunks: number;
|
|
2604
2642
|
imported: number;
|
|
2643
|
+
queued: number;
|
|
2605
2644
|
}>;
|
|
2606
2645
|
/**
|
|
2607
2646
|
* Read the cross-shard request distribution for a `.shardBy(...)` table —
|
|
@@ -3372,6 +3411,14 @@ declare class LunoraClient {
|
|
|
3372
3411
|
* stamp elsewhere in this file) — moved verbatim, not reflowed.
|
|
3373
3412
|
*/
|
|
3374
3413
|
private createTabCoordinator;
|
|
3414
|
+
/** The body of {@link batch}, optionally abortable (the polling fallback's timeout). */
|
|
3415
|
+
private sendBatch;
|
|
3416
|
+
/**
|
|
3417
|
+
* The body of {@link mutation}, also saying whether the write committed. `committed` is
|
|
3418
|
+
* `false` only when a durable outbox took the write, which resolves at once
|
|
3419
|
+
* with no server result.
|
|
3420
|
+
*/
|
|
3421
|
+
private runMutation;
|
|
3375
3422
|
/**
|
|
3376
3423
|
* Persist a mutation that can't go out on the wire right now (offline, or
|
|
3377
3424
|
* mid-reconnect after a prior connect). The optimistic update has already
|
|
@@ -3574,8 +3621,24 @@ declare class LunoraClient {
|
|
|
3574
3621
|
* than being swallowed: the whole point of the fallback is that the app keeps
|
|
3575
3622
|
* working, and a query that is now failing (a permission change, a bad arg)
|
|
3576
3623
|
* has to be visible.
|
|
3624
|
+
*
|
|
3625
|
+
* Resolves `false` when the request never reached the origin (`fetch` itself
|
|
3626
|
+
* rejected), which is how the fallback tells a device with no network from a
|
|
3627
|
+
* network that only refuses the upgrade. Any answer, an error envelope
|
|
3628
|
+
* included, resolves `true`.
|
|
3629
|
+
*
|
|
3630
|
+
* Optimistic layers need the same care without a cursor. The snapshot is taken
|
|
3631
|
+
* after the request is sent, so every write whose RPC had resolved before that
|
|
3632
|
+
* moment is already in it. Those layers are dropped against the acknowledgement
|
|
3633
|
+
* mark sampled before the send. A write acknowledged after the send may be
|
|
3634
|
+
* missing from the snapshot, so its layer stays.
|
|
3577
3635
|
*/
|
|
3578
3636
|
private pollSubscriptions;
|
|
3637
|
+
/**
|
|
3638
|
+
* Whether a request reaches the origin at all: an empty batch, whose answer
|
|
3639
|
+
* (even a refusal) is the proof. `false` only when `fetch` itself rejects.
|
|
3640
|
+
*/
|
|
3641
|
+
private probeOrigin;
|
|
3579
3642
|
/** Recompute the aggregate status and notify listeners if it changed. */
|
|
3580
3643
|
private emitConnectionStatus;
|
|
3581
3644
|
/**
|
|
@@ -3619,7 +3682,7 @@ declare class LunoraClient {
|
|
|
3619
3682
|
*/
|
|
3620
3683
|
private sendOrQueueUnsubscribe;
|
|
3621
3684
|
/**
|
|
3622
|
-
* The `(wsState, hasSocket, wasEverConnected)`
|
|
3685
|
+
* The `(wsState, hasSocket, wasEverConnected, polling)` state `mutation()`'s
|
|
3623
3686
|
* offline-queue gate reads. On the leader/single-tab path this is exactly
|
|
3624
3687
|
* the real `ShardConnection`'s state (byte-identical to the pre-cross-tab
|
|
3625
3688
|
* behavior). A follower has no `ShardConnection` of its own (see
|
|
@@ -3629,6 +3692,11 @@ declare class LunoraClient {
|
|
|
3629
3692
|
* `"connecting"` (the mid-reconnect queue branch), anything else is
|
|
3630
3693
|
* `"idle"`. `hasSocket` is always `false` for a follower — it never has
|
|
3631
3694
|
* one.
|
|
3695
|
+
*
|
|
3696
|
+
* `polling` is `true` while the HTTP polling fallback is reaching the origin
|
|
3697
|
+
* (the leader's mirrored `"polling"` on a follower). Writes then go straight
|
|
3698
|
+
* over HTTP, as they do while connected, instead of queueing for a socket
|
|
3699
|
+
* that may never open.
|
|
3632
3700
|
*/
|
|
3633
3701
|
private connectionGateState;
|
|
3634
3702
|
private getOrCreateConnection;
|
|
@@ -3806,6 +3874,10 @@ declare class LunoraClient {
|
|
|
3806
3874
|
private resnapshotSubscription;
|
|
3807
3875
|
/** Materialize a shape's keyed view to an array and invoke its callbacks. */
|
|
3808
3876
|
private emitShapeRows;
|
|
3877
|
+
/**
|
|
3878
|
+
* Apply one `data` frame. `snapshotMark` is set only for a frame synthesized
|
|
3879
|
+
* by a poll, which carries no cursor: see {@link pollSubscriptions}.
|
|
3880
|
+
*/
|
|
3809
3881
|
private handleDataMessage;
|
|
3810
3882
|
/**
|
|
3811
3883
|
* Handle a `resume` frame (Pillar 1b): the server proved nothing the
|
|
@@ -252,7 +252,11 @@ interface OutboxMutation {
|
|
|
252
252
|
/** Stable per-client id; pairs with {@link OutboxMutation.mutationId} as `idempotencyKey`. */
|
|
253
253
|
clientId: string;
|
|
254
254
|
functionPath: string;
|
|
255
|
-
/**
|
|
255
|
+
/**
|
|
256
|
+
* `${clientId}:${mutationId}`, or the caller's own `mutationId` when it passed
|
|
257
|
+
* one (an `importRows` chunk) — sent as `x-lunora-mutation-id` so a replay is
|
|
258
|
+
* server-idempotent.
|
|
259
|
+
*/
|
|
256
260
|
idempotencyKey: string;
|
|
257
261
|
/** Issuing identity fingerprint (`null` = signed out); drives the sink's identity guard. */
|
|
258
262
|
identity: string | null;
|
|
@@ -1255,6 +1259,12 @@ type SubscriptionErrorCallback = (error: SubscriptionError) => void;
|
|
|
1255
1259
|
* in-flight (so the overlay survives unrelated deltas until confirmed).
|
|
1256
1260
|
*/
|
|
1257
1261
|
interface OptimisticLayer {
|
|
1262
|
+
/**
|
|
1263
|
+
* Where this write's RPC resolved in the process-wide acknowledgement order
|
|
1264
|
+
* (see `acknowledgementMark`); `undefined` until confirmed. A polled snapshot
|
|
1265
|
+
* carries no cursor, so this is what lets it drop the layer instead.
|
|
1266
|
+
*/
|
|
1267
|
+
acknowledgedAt?: number;
|
|
1258
1268
|
/** The committed CDC cursor (from the mutation response); `undefined` until confirmed. */
|
|
1259
1269
|
commitCursor?: number;
|
|
1260
1270
|
readonly id: symbol;
|
|
@@ -1473,8 +1483,9 @@ type WSState = "idle" | "connecting" | "open" | "closed";
|
|
|
1473
1483
|
* is (re)connecting and none is open; `connected` = at least one socket is open;
|
|
1474
1484
|
* `polling` = no socket would open, so live queries are being refreshed over HTTP
|
|
1475
1485
|
* instead (see {@link file://./polling-fallback.ts} — live but slower, and shapes
|
|
1476
|
-
* / streams / whispers are dark
|
|
1477
|
-
* (between reconnect
|
|
1486
|
+
* / streams / whispers are dark; mutations go over HTTP as they do while
|
|
1487
|
+
* connected); `offline` = sockets exist but all are down (between reconnect
|
|
1488
|
+
* attempts), and a poll could not reach the origin either.
|
|
1478
1489
|
*
|
|
1479
1490
|
* `polling` outranks `connecting`: while the fallback is running a reconnect is
|
|
1480
1491
|
* still armed in the background, and reporting that attempt would flicker the
|
|
@@ -1952,6 +1963,8 @@ declare class LunoraClient {
|
|
|
1952
1963
|
private readonly statusListeners;
|
|
1953
1964
|
/** Subscribers notified when the server drops a socket for an expired token (see `onTokenExpired`). */
|
|
1954
1965
|
private readonly tokenExpiredListeners;
|
|
1966
|
+
/** Subscribers notified when the previous identity's session is retired (see `onIdentityChange`). */
|
|
1967
|
+
private readonly identityChangeListeners;
|
|
1955
1968
|
/** Token hash the last durable-replay auth refusal fired `onTokenExpired` for — see `shouldRequeueReplayFailure`. */
|
|
1956
1969
|
private authRefusalNotifiedFor;
|
|
1957
1970
|
/** Subscribers to offline-queued mutation verdicts (see `onMutationSettled`). */
|
|
@@ -2189,6 +2202,19 @@ declare class LunoraClient {
|
|
|
2189
2202
|
* the current value.
|
|
2190
2203
|
*/
|
|
2191
2204
|
onAuthTokenChange(listener: (token: string | null) => void): Unsubscribe;
|
|
2205
|
+
/**
|
|
2206
|
+
* Subscribe to a user switch or sign-out: fired after {@link setAuthToken}
|
|
2207
|
+
* retires the previous identity's session, i.e. every live subscription has
|
|
2208
|
+
* just been blanked to `undefined` and its socket closed. Not fired when an
|
|
2209
|
+
* identity is first established from signed-out (nothing is retired), nor
|
|
2210
|
+
* when a subject is attached to the same credential.
|
|
2211
|
+
*
|
|
2212
|
+
* For caches layered on top of the client. A subscriber only hears the
|
|
2213
|
+
* blank for queries it still subscribes to, so a cache that keeps values for
|
|
2214
|
+
* unmounted queries must drop them here, or the next user can read the
|
|
2215
|
+
* previous user's rows from it.
|
|
2216
|
+
*/
|
|
2217
|
+
onIdentityChange(listener: () => void): Unsubscribe;
|
|
2192
2218
|
/**
|
|
2193
2219
|
* Fetch the currently authenticated user from better-auth's `get-session`
|
|
2194
2220
|
* endpoint, returning the `user` record or `null` when signed out. Sends
|
|
@@ -2533,16 +2559,24 @@ declare class LunoraClient {
|
|
|
2533
2559
|
* {@link LunoraClient.importRows} documents the same caveat for its counts.
|
|
2534
2560
|
*/
|
|
2535
2561
|
mutation<F extends FunctionReference>(function_: F, args: ArgsOf<F>, options?: MutationCallOptions<unknown, unknown, ArgsOf<F>>): Promise<ReturnOf<F>>;
|
|
2562
|
+
/**
|
|
2563
|
+
* Whether a {@link mutation} on `shardKey` would be queued (offline queue or
|
|
2564
|
+
* durable outbox) rather than fail when the network is down. `false` before
|
|
2565
|
+
* the shard's first connect (unless `queueBeforeFirstConnect` is set) and on
|
|
2566
|
+
* a client with no WebSocket. A caller that wants to hold a write until the
|
|
2567
|
+
* network returns must do so itself when this is `false`.
|
|
2568
|
+
*/
|
|
2569
|
+
canQueueOffline(shardKey?: string): boolean;
|
|
2536
2570
|
action<F extends FunctionReference>(function_: F, args: ArgsOf<F>, options?: ActionCallOptions): Promise<ReturnOf<F>>;
|
|
2537
2571
|
/**
|
|
2538
2572
|
* Bulk-import `rows` through a mutation that accepts a batch, chunked so a large
|
|
2539
2573
|
* dataset lands in a bounded number of round-trips.
|
|
2540
2574
|
*
|
|
2541
|
-
* **
|
|
2542
|
-
*
|
|
2543
|
-
*
|
|
2544
|
-
*
|
|
2545
|
-
*
|
|
2575
|
+
* **Queued chunks:** `imported` counts only rows the server committed. A chunk a
|
|
2576
|
+
* durable outbox took instead (offline, or behind older queued writes) is counted
|
|
2577
|
+
* in `queued`; the outbox replays it later under the same key. The built-in
|
|
2578
|
+
* offline queue holds the call until each chunk commits, so its rows land in
|
|
2579
|
+
* `imported`. Report "migration complete" only when `queued` is `0`.
|
|
2546
2580
|
*
|
|
2547
2581
|
* This is the one-shot migration / seed path: "I have 20k rows client-side and a
|
|
2548
2582
|
* server mutation that inserts many at once". Doing it by hand goes wrong in two
|
|
@@ -2550,7 +2584,8 @@ declare class LunoraClient {
|
|
|
2550
2584
|
* wait per row (a 200-row import becomes 200 sequential hops), while a single
|
|
2551
2585
|
* giant call blows the DO's batch limit. So: chunk, send sequentially, and give
|
|
2552
2586
|
* each chunk a stable idempotency key derived from `importId` + its index, so a
|
|
2553
|
-
* resumed or retried import doesn't double-insert the chunks that already landed
|
|
2587
|
+
* resumed or retried import doesn't double-insert the chunks that already landed
|
|
2588
|
+
* (for an anonymous caller only while the `clientId` is the same; see `importId`).
|
|
2554
2589
|
*
|
|
2555
2590
|
* The server mutation is yours (Lunora can't guess the table or the row shape);
|
|
2556
2591
|
* back it with `ctx.db.insertMany(...)`, or `insertManyUnsafe(...)` for data you
|
|
@@ -2581,15 +2616,18 @@ declare class LunoraClient {
|
|
|
2581
2616
|
* SILENTLY DROPS those rows. Keep `chunkSize` (and the row order) identical
|
|
2582
2617
|
* across resumes of the same `importId`. Omit `importId` only for a
|
|
2583
2618
|
* throwaway import where double-insertion is acceptable.
|
|
2619
|
+
*
|
|
2620
|
+
* CAVEAT — anonymous callers: the server scopes the key to the signed-in
|
|
2621
|
+
* user, or to the client's `clientId` when nobody is signed in. A
|
|
2622
|
+
* `LunoraClient` mints a fresh `clientId` on every construction, so an
|
|
2623
|
+
* anonymous import resumed after a reload is not deduped and inserts the
|
|
2624
|
+
* landed chunks again. Pass a persisted `clientId` to the constructor to
|
|
2625
|
+
* resume anonymously, or run the import signed in.
|
|
2584
2626
|
*/
|
|
2585
2627
|
importId?: string;
|
|
2586
2628
|
/**
|
|
2587
|
-
* Called after each chunk is accepted — for a progress bar.
|
|
2588
|
-
*
|
|
2589
|
-
* "Accepted" is not always "committed": while offline (or mid-reconnect) a
|
|
2590
|
-
* `mutation` resolves as soon as the write is durably **queued**, so a fully
|
|
2591
|
-
* offline import reports completion with nothing yet applied server-side.
|
|
2592
|
-
* Gate a migration's "done" state on connectivity, not just on this.
|
|
2629
|
+
* Called after each chunk is accepted — for a progress bar. `done` counts
|
|
2630
|
+
* committed and queued rows alike; the result separates them.
|
|
2593
2631
|
*/
|
|
2594
2632
|
onProgress?: (progress: {
|
|
2595
2633
|
done: number;
|
|
@@ -2602,6 +2640,7 @@ declare class LunoraClient {
|
|
|
2602
2640
|
}): Promise<{
|
|
2603
2641
|
chunks: number;
|
|
2604
2642
|
imported: number;
|
|
2643
|
+
queued: number;
|
|
2605
2644
|
}>;
|
|
2606
2645
|
/**
|
|
2607
2646
|
* Read the cross-shard request distribution for a `.shardBy(...)` table —
|
|
@@ -3372,6 +3411,14 @@ declare class LunoraClient {
|
|
|
3372
3411
|
* stamp elsewhere in this file) — moved verbatim, not reflowed.
|
|
3373
3412
|
*/
|
|
3374
3413
|
private createTabCoordinator;
|
|
3414
|
+
/** The body of {@link batch}, optionally abortable (the polling fallback's timeout). */
|
|
3415
|
+
private sendBatch;
|
|
3416
|
+
/**
|
|
3417
|
+
* The body of {@link mutation}, also saying whether the write committed. `committed` is
|
|
3418
|
+
* `false` only when a durable outbox took the write, which resolves at once
|
|
3419
|
+
* with no server result.
|
|
3420
|
+
*/
|
|
3421
|
+
private runMutation;
|
|
3375
3422
|
/**
|
|
3376
3423
|
* Persist a mutation that can't go out on the wire right now (offline, or
|
|
3377
3424
|
* mid-reconnect after a prior connect). The optimistic update has already
|
|
@@ -3574,8 +3621,24 @@ declare class LunoraClient {
|
|
|
3574
3621
|
* than being swallowed: the whole point of the fallback is that the app keeps
|
|
3575
3622
|
* working, and a query that is now failing (a permission change, a bad arg)
|
|
3576
3623
|
* has to be visible.
|
|
3624
|
+
*
|
|
3625
|
+
* Resolves `false` when the request never reached the origin (`fetch` itself
|
|
3626
|
+
* rejected), which is how the fallback tells a device with no network from a
|
|
3627
|
+
* network that only refuses the upgrade. Any answer, an error envelope
|
|
3628
|
+
* included, resolves `true`.
|
|
3629
|
+
*
|
|
3630
|
+
* Optimistic layers need the same care without a cursor. The snapshot is taken
|
|
3631
|
+
* after the request is sent, so every write whose RPC had resolved before that
|
|
3632
|
+
* moment is already in it. Those layers are dropped against the acknowledgement
|
|
3633
|
+
* mark sampled before the send. A write acknowledged after the send may be
|
|
3634
|
+
* missing from the snapshot, so its layer stays.
|
|
3577
3635
|
*/
|
|
3578
3636
|
private pollSubscriptions;
|
|
3637
|
+
/**
|
|
3638
|
+
* Whether a request reaches the origin at all: an empty batch, whose answer
|
|
3639
|
+
* (even a refusal) is the proof. `false` only when `fetch` itself rejects.
|
|
3640
|
+
*/
|
|
3641
|
+
private probeOrigin;
|
|
3579
3642
|
/** Recompute the aggregate status and notify listeners if it changed. */
|
|
3580
3643
|
private emitConnectionStatus;
|
|
3581
3644
|
/**
|
|
@@ -3619,7 +3682,7 @@ declare class LunoraClient {
|
|
|
3619
3682
|
*/
|
|
3620
3683
|
private sendOrQueueUnsubscribe;
|
|
3621
3684
|
/**
|
|
3622
|
-
* The `(wsState, hasSocket, wasEverConnected)`
|
|
3685
|
+
* The `(wsState, hasSocket, wasEverConnected, polling)` state `mutation()`'s
|
|
3623
3686
|
* offline-queue gate reads. On the leader/single-tab path this is exactly
|
|
3624
3687
|
* the real `ShardConnection`'s state (byte-identical to the pre-cross-tab
|
|
3625
3688
|
* behavior). A follower has no `ShardConnection` of its own (see
|
|
@@ -3629,6 +3692,11 @@ declare class LunoraClient {
|
|
|
3629
3692
|
* `"connecting"` (the mid-reconnect queue branch), anything else is
|
|
3630
3693
|
* `"idle"`. `hasSocket` is always `false` for a follower — it never has
|
|
3631
3694
|
* one.
|
|
3695
|
+
*
|
|
3696
|
+
* `polling` is `true` while the HTTP polling fallback is reaching the origin
|
|
3697
|
+
* (the leader's mirrored `"polling"` on a follower). Writes then go straight
|
|
3698
|
+
* over HTTP, as they do while connected, instead of queueing for a socket
|
|
3699
|
+
* that may never open.
|
|
3632
3700
|
*/
|
|
3633
3701
|
private connectionGateState;
|
|
3634
3702
|
private getOrCreateConnection;
|
|
@@ -3806,6 +3874,10 @@ declare class LunoraClient {
|
|
|
3806
3874
|
private resnapshotSubscription;
|
|
3807
3875
|
/** Materialize a shape's keyed view to an array and invoke its callbacks. */
|
|
3808
3876
|
private emitShapeRows;
|
|
3877
|
+
/**
|
|
3878
|
+
* Apply one `data` frame. `snapshotMark` is set only for a frame synthesized
|
|
3879
|
+
* by a poll, which carries no cursor: see {@link pollSubscriptions}.
|
|
3880
|
+
*/
|
|
3809
3881
|
private handleDataMessage;
|
|
3810
3882
|
/**
|
|
3811
3883
|
* Handle a `resume` frame (Pillar 1b): the server proved nothing the
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { L as LunoraClient, P as Preloaded } from "./lunora-client.d-
|
|
1
|
+
import { L as LunoraClient, P as Preloaded } from "./lunora-client.d-DWo4CzIH.mjs";
|
|
2
2
|
import { F as FunctionReference, A as ArgsOf, R as ReturnOf } from "./function-reference.d-Br_hsKje.mjs";
|
|
3
3
|
/**
|
|
4
4
|
* Run a query once on the server (during SSR) and capture its result in a
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { L as LunoraClient, P as Preloaded } from "./lunora-client.d-
|
|
1
|
+
import { L as LunoraClient, P as Preloaded } from "./lunora-client.d-WFeiiO0Z.js";
|
|
2
2
|
import { F as FunctionReference, A as ArgsOf, R as ReturnOf } from "./function-reference.d-Br_hsKje.js";
|
|
3
3
|
/**
|
|
4
4
|
* Run a query once on the server (during SSR) and capture its result in a
|
package/dist/query/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as SubscriptionError, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-
|
|
1
|
+
import { S as SubscriptionError, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-DWo4CzIH.mjs";
|
|
2
2
|
export type {
|
|
3
3
|
/**
|
|
4
4
|
* `@lunora/client/query` — the framework-neutral live-query state machine shared
|
|
@@ -10,7 +10,7 @@ export type {
|
|
|
10
10
|
* framework — each adapter supplies thin sinks that write into its own ref /
|
|
11
11
|
* store / signal / cache.
|
|
12
12
|
*/
|
|
13
|
-
b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-
|
|
13
|
+
b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-DWo4CzIH.mjs";
|
|
14
14
|
import { F as FunctionReference, A as ArgsOf, R as ReturnOf } from "../packem_shared/function-reference.d-Br_hsKje.mjs";
|
|
15
15
|
import '@lunora/errors';
|
|
16
16
|
import '@lunora/runtime';
|
package/dist/query/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { S as SubscriptionError, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-
|
|
1
|
+
import { S as SubscriptionError, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-WFeiiO0Z.js";
|
|
2
2
|
export type {
|
|
3
3
|
/**
|
|
4
4
|
* `@lunora/client/query` — the framework-neutral live-query state machine shared
|
|
@@ -10,7 +10,7 @@ export type {
|
|
|
10
10
|
* framework — each adapter supplies thin sinks that write into its own ref /
|
|
11
11
|
* store / signal / cache.
|
|
12
12
|
*/
|
|
13
|
-
b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-
|
|
13
|
+
b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-WFeiiO0Z.js";
|
|
14
14
|
import { F as FunctionReference, A as ArgsOf, R as ReturnOf } from "../packem_shared/function-reference.d-Br_hsKje.js";
|
|
15
15
|
import '@lunora/errors';
|
|
16
16
|
import '@lunora/runtime';
|
package/dist/ssr/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-
|
|
1
|
+
import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-DWo4CzIH.mjs";
|
|
2
2
|
export type { A as ArgsOf, F as FunctionReference, R as ReturnOf } from "../packem_shared/function-reference.d-Br_hsKje.mjs";
|
|
3
3
|
export {
|
|
4
4
|
/**
|
|
@@ -20,7 +20,7 @@ p as preloadQuery,
|
|
|
20
20
|
* WebSocket or touches a UI framework, so it is safe to import from any SSR
|
|
21
21
|
* loader.
|
|
22
22
|
*/
|
|
23
|
-
a as preloadedQueryResult } from "../packem_shared/preload.d-
|
|
23
|
+
a as preloadedQueryResult } from "../packem_shared/preload.d-6E3-9j1g.mjs";
|
|
24
24
|
import '@lunora/errors';
|
|
25
25
|
import '@lunora/runtime';
|
|
26
26
|
/**
|
package/dist/ssr/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-
|
|
1
|
+
import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-WFeiiO0Z.js";
|
|
2
2
|
export type { A as ArgsOf, F as FunctionReference, R as ReturnOf } from "../packem_shared/function-reference.d-Br_hsKje.js";
|
|
3
3
|
export {
|
|
4
4
|
/**
|
|
@@ -20,7 +20,7 @@ p as preloadQuery,
|
|
|
20
20
|
* WebSocket or touches a UI framework, so it is safe to import from any SSR
|
|
21
21
|
* loader.
|
|
22
22
|
*/
|
|
23
|
-
a as preloadedQueryResult } from "../packem_shared/preload.d-
|
|
23
|
+
a as preloadedQueryResult } from "../packem_shared/preload.d-CVB-TzK6.js";
|
|
24
24
|
import '@lunora/errors';
|
|
25
25
|
import '@lunora/runtime';
|
|
26
26
|
/**
|
package/dist/ssr/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getServerSession as o}from"../packem_shared/getServerSession-BaOoo1p6.mjs";import{deserializePreloaded as l,serializePreloaded as t}from"../packem_shared/deserializePreloaded-C6NTQdFa.mjs";import{createServerClient as i}from"../packem_shared/createServerClient-
|
|
1
|
+
import{getServerSession as o}from"../packem_shared/getServerSession-BaOoo1p6.mjs";import{deserializePreloaded as l,serializePreloaded as t}from"../packem_shared/deserializePreloaded-C6NTQdFa.mjs";import{createServerClient as i}from"../packem_shared/createServerClient-C0jOZaix.mjs";import{preloadQuery as s,preloadedQueryResult as f}from"../packem_shared/preloadQuery-uFy24PCR.mjs";export{i as createServerClient,l as deserializePreloaded,o as getServerSession,s as preloadQuery,f as preloadedQueryResult,t as serializePreloaded};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/client",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.138",
|
|
4
4
|
"description": "Lunora browser SDK: WebSocket transport, optimistic updates, and an offline mutation queue",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"access": "public"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"@lunora/errors": "1.0.0-alpha.
|
|
73
|
+
"@lunora/errors": "1.0.0-alpha.42",
|
|
74
74
|
"@visulima/storage-client": "1.0.3"
|
|
75
75
|
},
|
|
76
76
|
"peerDependencies": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{LunoraError as m}from"@lunora/errors";import{i as ae,a as oe,P as ce}from"./delta-merge-vxvH3PvF.mjs";import{e as M,d as v}from"./wire-codec-Sw1rAu-Z.mjs";import{s as W}from"./wire-key-HsUDTlQ7.mjs";import he from"./createInMemoryBookmarkStorage-BooZhW0n.mjs";import{ClientQueryStore as de}from"./createClientQuery-B8Nfj-7o.mjs";import{TabCoordinator as ue}from"./TabCoordinator-CXD7vulJ.mjs";import{TransportError as $}from"./CONFLICT_ERROR_CODE-BOeeP_Wl.mjs";import{httpStream as le}from"./httpStream-CPdblK2G.mjs";import{d as U,n as w,f as E,a as fe,c as pe}from"./local-store-BjenEm3t.mjs";import{O as me,n as G,i as ye,r as be}from"./offline-queue-D_fr-uQ3.mjs";import{resolvePersistenceAdapter as Se}from"./createInMemoryPersistence-Cz2W6XVj.mjs";import{resolveQueryCacheAdapter as ve,queryCacheKey as A}from"./createInMemoryQueryCache-D2uNHLfM.mjs";import{createReconnect as j}from"./createReconnect-CjTmjJDH.mjs";import{e as R,u as F,d as Te,r as ge,i as ke,a as Ce,b as we,M as Ee,c as Ae,f as _e}from"./replay-DYdPvn3o.mjs";import Ie from"./createSnapshotPrecondition-GRVKxPsh.mjs";import{createStream as Oe}from"./DEFAULT_MAX_BUFFER-D3QH2iaq.mjs";import{SubscriptionRegistry as g}from"./SubscriptionRegistry-CS-AFUI9.mjs";const x=500,Re=async h=>{const e=[];let t;for(;;){const s=await h(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}},z=(h,e)=>{if(h.size<e)return;const t=h.keys().next().value;t!==void 0&&h.delete(t)};class I{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 Pe=h=>{const{afterFailedAttempts:e,intervalMs:t,onStateChange:s,poll:r}=h,i=t>0&&e>0;let n=0,a,o=!1;const c=()=>{o||(o=!0,r().finally(()=>{o=!1}).catch(()=>{}))},d=()=>{a!==void 0&&(clearInterval(a),a=void 0,s())};return{isPolling:()=>a!==void 0,noteFailedOpen:()=>{n+=1,!(!i||a!==void 0||n<e)&&(a=setInterval(c,t),s(),c())},noteOpen:()=>{n=0,d()},stop:d}},Fe="/_lunora/rpc",V="/_lunora/rpc-batch",Me="/_lunora/ws",N=h=>h===void 0||h===""?"":`&bucket=${encodeURIComponent(h)}`,O=h=>{for(let e=h.length-1;e>=0;e-=1)h[e]?.()},J=Symbol("lunora.unmergeableDelta"),He=(h,e)=>{for(const t of e)t.op==="delete"?h.delete(t.key):t.value!==void 0&&h.set(t.key,t.value)},Le="lunora-ping",Ue=3e4,xe=1e4,Ne=5e3,Be=3,Qe=250,qe=5e3,Ke=64,De=3,We=1e4,$e=8,Ge="/_lunora/admin/shard-traffic",je="/_lunora/admin/scheduled",ze="/_lunora/admin/scheduled/status",Ve="/_lunora/admin/scheduled/ws",Je="/_lunora/admin/scheduled/cancel",Y="/_lunora/admin/scheduled/dead",Ye="/_lunora/admin/scheduled/dead/retry",Xe="/_lunora/admin/scheduled/dead/cancel",Ze="/_lunora/admin/workflows/instances",et="/_lunora/admin/workflows/instance",tt="/_lunora/admin/workflows/status",B="/_lunora/admin/storage",st="/_lunora/admin/storage/url",rt="/_lunora/admin/storage/buckets",it="/_lunora/admin/functions",nt="/_lunora/admin/cron-jobs",at="/_lunora/admin/cron-jobs/run",ot="/_lunora/admin/openapi",ct="/_lunora/admin/openrpc",ht="/_lunora/admin/global/tables",dt="/_lunora/admin/global/table",ut="/_lunora/admin/global/facet",lt="/_lunora/admin/vector/indexes",ft="/_lunora/admin/vector/query",pt="/_lunora/admin/logs/archive",mt="/_lunora/admin/kv/namespaces",yt="/_lunora/admin/kv/keys",Q="/_lunora/admin/kv/value",bt="/_lunora/admin/auth/users",St="/_lunora/admin/auth/sessions",vt="/_lunora/admin/auth/users/create",Tt="/_lunora/admin/auth/users/role",gt="/_lunora/admin/auth/users/ban",kt="/_lunora/admin/auth/users/unban",Ct="/_lunora/admin/auth/users/password",wt="/_lunora/admin/auth/users/remove",Et="/_lunora/admin/auth/users/impersonate",At="/_lunora/admin/auth/sessions/revoke",_t="/_lunora/admin/auth/sessions/revoke-all",It="/_lunora/admin/auth/capabilities",Ot="/_lunora/admin/auth/users/update",Rt="/_lunora/admin/auth/accounts",Pt="/_lunora/admin/auth/accounts/unlink",Ft="/_lunora/admin/auth/passkeys",Mt="/_lunora/admin/auth/passkeys/delete",Ht="/_lunora/admin/auth/two-factor/disable",Lt="/_lunora/admin/auth/organizations",Ut="/_lunora/admin/auth/organizations/members",xt="/_lunora/admin/auth/organizations/invitations",Nt="/_lunora/admin/auth/organizations/members/remove",Bt="/_lunora/admin/auth/organizations/invitations/cancel",Qt="/_lunora/admin/auth/config",qt="/_lunora/admin/auth/sign-up-invitations",Kt="/_lunora/admin/auth/sign-up-invitations/create",Dt="/_lunora/admin/auth/sign-up-invitations/revoke",Wt="/_lunora/admin/auth/organizations/create",$t="/_lunora/admin/auth/organizations/update",Gt="/_lunora/admin/auth/organizations/remove",jt="/_lunora/admin/auth/organizations/members/add",zt="/_lunora/admin/auth/organizations/members/invite",Vt="/_lunora/admin/auth/organizations/members/role",Jt="/_lunora/admin/auth/organizations/teams",Yt="/_lunora/admin/auth/organizations/teams/create",Xt="/_lunora/admin/auth/organizations/teams/update",Zt="/_lunora/admin/auth/organizations/teams/remove",es="/_lunora/admin/auth/organizations/teams/members",ts="/_lunora/admin/auth/organizations/teams/members/add",ss="/_lunora/admin/auth/organizations/teams/members/remove",rs="/_lunora/admin/auth/organizations/roles",is="/_lunora/admin/auth/organizations/roles/create",ns="/_lunora/admin/auth/organizations/roles/update",as="/_lunora/admin/auth/organizations/roles/remove",os="/api/auth",cs="/get-session",X=h=>h.startsWith("https://")?`wss://${h.slice(8)}`:h.startsWith("http://")?`ws://${h.slice(7)}`:h,C=(h,e)=>`${h.endsWith("/")?h.slice(0,-1):h}${e}`,b=(h,e)=>{const t=new URLSearchParams;for(const[r,i]of Object.entries(e))i!==void 0&&i!==""&&t.set(r,String(i));const s=t.toString();return s===""?h:`${h}?${s}`},hs=[ce],l=h=>h??"",te=(h,e)=>{const t=h.error,s=typeof t?.code=="string"?t.code:void 0,r=typeof t?.message=="string"?t.message:void 0;return{code:s,messageText:(typeof h.message=="string"?h.message:void 0)??r??e}},ds=h=>{const{code:e,messageText:t}=te(h,"stream error");return e===void 0?new Error(t):new m(e,t)},Z=h=>{const{code:e,messageText:t}=te(h,"subscription error");return{message:t,...e===void 0?{}:{code:e}}};function q(h){if(h!==void 0)return e=>{h(e)}}const _=(h,e)=>{for(const t of h)try{t(e)}catch{}},us=new TextDecoder,ls=h=>{if(typeof h=="string")return h;if(h instanceof ArrayBuffer)return us.decode(h)},S=(h,e)=>{if(!h.socket||h.wsState!=="open")return!1;try{return h.socket.send(JSON.stringify(e)),!0}catch{return!1}},D=h=>{const e=new Error(h.message??"request failed");return e.code=h.code,h.data!==void 0&&(e.data=v(h.data)),h.hint!==void 0&&(e.hint=h.hint),h.docsUrl!==void 0&&(e.docsUrl=h.docsUrl),e},ee=(h,e)=>{const t=D(h),s=Ae(t,e);return s!==void 0&&(t.data=s),t},k=(h,e)=>{try{return M(h)}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)}},K=h=>"args"in h?{...h,args:v(h.args)}:h,se=h=>{const e=R(h);return e===void 0?_e():D(e)},fs=(h,e)=>{const t=Array.from({length:e});for(const s of h){if(typeof s.id!="number"||s.id<0||s.id>=e)continue;const r=s.body;t[s.id]=r!==void 0&&"error"in r?{error:se(r),ok:!1}:{ok:!0,value:v(r?.result)}}return t.map(s=>s??{error:new Error("batch call returned no result"),ok:!1})},ps=Promise.resolve();class re{static MAX_POKE_BUFFERS=256;static createClientQuery(e,t){return{defaultValue:t,key:e}}url;wsUrl;clientQueryStore;wsToken;authBasePath;fetchImpl;WebSocketImpl;bookmark;reconnectOptions;connectTimeoutMs;heartbeatIntervalMs;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 g;tabCoordinator;leaderStatus;leaderWasEverConnected=!1;connections=new Map;defaultConnectionContext;connectionContexts=new Map;connectionContextHolders=new Map;authToken=null;authSubject=void 0;subjectToken=null;sessionProbesInFlight=0;sessionProbeGeneration=0;identityResolutionExpected=!1;identitySettled=!1;queuedIdentities=new Map;queuedOfflineShardKeys=new Set;closed=!1;authTokenListeners=new I;statusListeners=new I;tokenExpiredListeners=new I;authRefusalNotifiedFor;mutationSettledListeners=new I;pendingChangeListeners=new I;whisperHandlers=new Map;lastStatus="idle";nextSubId=0;nextStreamId=0;streams=new Map;adminSocketTeardowns=new Set;offlineFlushes=new Map;replayRetryState=new Map;replayRetryTimers=new Map;shapeSubscriptions=new Map;pokeBuffers=new Map;nextShapeId=0;constructor(e){this.url=e.url,this.wsUrl=e.wsUrl??C(X(e.url),Me),this.wsToken=e.wsToken;const t=e.authBasePath??os;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??he(),this.reconnectOptions=e.reconnect,this.heartbeatIntervalMs=e.heartbeatIntervalMs??Ue,this.connectTimeoutMs=e.connectTimeoutMs??xe,this.pollingFallbackIntervalMs=e.pollingFallback?.intervalMs??Ne,this.pollingFallbackAfterFailedAttempts=e.pollingFallback?.afterFailedAttempts??Be,this.defaultConnectionContext=e.connectionContext,this.persistence=Se(e.persistence,e.outbox===void 0),this.persistenceVersion=e.persistenceVersion,this.queryCache=ve(e.queryCache),this.onPersistenceError=e.offlineQueue?.onPersistenceError,this.clientQueryStore=new de,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=ps),this.offlineQueue=new me(e.offlineQueue,{onEvict:(s,r)=>{this.emitItemSettled(s,"rejected",r)},onSizeChange:s=>{this.pendingChangeListeners.emit(s)},persistence:this.persistence,version:e.persistenceVersion}),this.outbox=e.outbox,this.clientId=e.clientId??`client-${G()}`,this.persistence&&queueMicrotask(()=>{this.hydrateAsOutboxLeader()}),this.queryCache&&queueMicrotask(()=>{(async()=>{try{await this.hydrateQueryCache()}catch{}finally{this.readyResolved=!0,this.readyResolve?.()}})().catch(()=>{})})}setAuthToken(e,t){const s=this.authToken!==e,r=this.identityFingerprint(),i=this.authSubject===void 0||this.subjectToken===this.authToken,n=this.subjectAwaitingReconfirm();this.authToken=e,t!==void 0?(this.authSubject=t,this.subjectToken=e):e===null&&(this.authSubject=void 0,this.subjectToken=null);const a=this.identityFingerprint();a!==r&&(!s&&e!==null&&i?(this.restampQueuedIdentity(r,a),this.restampWatermarks(r,a),this.restampConnectionIdentity(r,a),this.reseedFromHydratedCache()):!s&&e===null&&r===null&&i?(this.restampWatermarks(r,a),this.restampConnectionIdentity(r,a),this.reseedFromHydratedCache()):(this.rejectQueuedForIdentityChange(r),r!==null&&this.evictPreviousIdentitySession()),this.restartTabCoordinatorForIdentity()),this.syncReadCacheToCredential(n),s&&this.authTokenListeners.emit(e),this.offlineQueue.size>0&&this.computeStatus()==="connected"&&this.flushAllOfflineQueues()}getAuthToken(){return this.authToken}currentIdentity(){return this.identityFingerprint()}expectIdentityResolution(){this.identityResolutionExpected=!0}currentBaseline(e){return this.baselineCursorFor(e)}replayIdentityVerdict(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"}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 m("INTERNAL",`callMutator: clientSeq must be a positive integer, got ${String(r)}`);const i=s?.shardKey??"",n=this.identityFingerprint();let a;const o=await this.rpc(e,t,s?.shardKey,{captureBookmark:!0,clientId:this.clientId,clientSeq:r,onMutationAck:d=>{a=d}});if(a!==void 0&&a>(this.clientWatermarks.get(n??"")?.get(i)??0)){let d=this.clientWatermarks.get(n??"");d===void 0&&(z(this.clientWatermarks,$e),d=new Map,this.clientWatermarks.set(n??"",d)),d.set(i,a)}return{applied:a===void 0||a===r,result:o}}onAuthTokenChange(e){return this.authTokenListeners.add(e)}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.sessionProbeGeneration+=1;const s=this.sessionProbeGeneration;try{const r=await this.fetchImpl(C(this.url,`${this.authBasePath}${cs}`),{credentials:"include",headers:e,method:"GET"});if(!r.ok)return this.identitySettled=!0,null;const n=(await r.json())?.user??null;return this.identitySettled=!0,this.adoptResolvedSubject(t,n,s),n}finally{this.releaseSessionProbe()}}setWsToken(e){this.wsToken!==e&&(this.wsToken=e,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)}acquireConnectionContext(e,t={}){if(this.followsAnotherTab())return()=>{};const s=l(t.shardKey),r={context:e},i=this.connectionContextHolders.get(s);i?i.push(r):this.connectionContextHolders.set(s,[r]),this.refreshConnectionContext(s);let n=!1;return()=>{if(n)return;n=!0;const a=this.connectionContextHolders.get(s);if(!a)return;const o=a.indexOf(r);o!==-1&&a.splice(o,1),a.length===0&&this.connectionContextHolders.delete(s),this.refreshConnectionContext(s)}}whisperSubscribe(e,t,s={}){this.assertLeaderOwnedSurface("whisperSubscribe");const r=l(s.shardKey);let i=this.whisperHandlers.get(r);i||(i=new Map,this.whisperHandlers.set(r,i));let n=i.get(e);const a=n===void 0;if(n||(n=new Set,i.set(e,n)),n.add(t),this.ensureSocket(s.shardKey),a){const o=this.getConnection(s.shardKey);o&&S(o,{topic:e,type:"whisper_subscribe"})}return()=>{const o=this.whisperHandlers.get(r),c=o?.get(e);if(!c?.delete(t)||c.size>0)return;o?.delete(e),o?.size===0&&this.whisperHandlers.delete(r);const d=this.getConnection(s.shardKey);d&&S(d,{topic:e,type:"whisper_unsubscribe"})}}whisper(e,t,s={}){this.assertLeaderOwnedSurface("whisper"),this.ensureSocket(s.shardKey);const r=this.getConnection(s.shardKey);r&&S(r,{data:k(t??null,`whisper data for topic '${e}'`),topic:e,type:"whisper"})}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 i of s){const n=this.connections.get(i);e.push({confirmedMutationWatermark:t?.get(i)??0,hasSocket:n?.socket!==void 0,shardKey:i===""?void 0:i,wasEverConnected:n?.wasEverConnected??!1,wsState:n?.wsState??"idle"})}const r=this.subscriptions.all().map(i=>({acked:i.acked,functionPath:i.fn.__lunoraRef,id:i.id,kind:"query",lastMutationId:i.lastMutationId,pendingOptimisticLayers:i.optimisticLayers.length,serverCursor:i.serverCursor,shardKey:i.shardKey,subscriberCount:i.callbacks.size}));for(const i of this.shapeSubscriptions.values())r.push({acked:i.serverCursor!==void 0,functionPath:`shape:${i.name}`,id:i.id,kind:"shape",lastMutationId:i.lastMutationId,pendingOptimisticLayers:0,rowCount:i.rows.size,serverCursor:i.serverCursor,shardKey:i.shardKey,subscriberCount:i.callbacks.size});return{clientId:this.clientId,closed:this.closed,connectionStatus:this.computeStatus(),pendingWrites:this.offlineQueue.size,shards:e.toSorted((i,n)=>(i.shardKey??"").localeCompare(n.shardKey??"")),subscriptions:r.toSorted((i,n)=>i.functionPath.localeCompare(n.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 Ie(this,e,t,s)}whenReady(){return this.readyPromise}get isReady(){return this.readyResolved}peekHydratedQuery(e,t,s){if(!this.readyResolved)return;const r=W(t),i=A(e,r,s),n=this.hydratedQueryCache.get(i);if(n!==void 0)return this.cachedQueryMatchesIdentity(n)?n.value:void 0}peekActiveQuerySnapshot(e,t,s){const r=g.key(e,t,s),i=this.subscriptions.get(r);return{present:i!==void 0,value:i?.lastValue}}async query(e,t,s={}){return this.assertOpen(),await this.rpc(e.__lunoraRef,t,s.shardKey,{attachBookmark:!0})}async batch(e){if(this.assertOpen(),!this.fetchImpl)throw new m("INTERNAL","LunoraClient: no `fetch` implementation available");if(e.length===0)return[];const t=await this.fetchImpl(C(this.url,V),{body:JSON.stringify({calls:e.map((n,a)=>({args:k(n.args??{},`args for batch call '${n.fn.__lunoraRef}'`),functionPath:n.fn.__lunoraRef,id:a,shardKey:n.shardKey}))}),headers:this.rpcRequestHeaders({attachBookmark:!0}),method:"POST"}),s=t.headers.get("x-d1-bookmark");s&&this.bookmark.set(s);let r;try{r=await t.json()}catch{throw new m("INTERNAL",`LunoraClient: batch response was not JSON (status ${t.status.toString()})`)}const i=R(r);if(!t.ok||i!==void 0&&!r.results)throw i!==void 0?D(i):new m("INTERNAL",`LunoraClient: batch request failed (status ${t.status.toString()})`);for(const n of r.results??[]){const a=n.body?.commitCursor;typeof n.id=="number"&&typeof a=="number"&&this.recordShardCursor(e[n.id]?.shardKey,a)}return fs(r.results??[],e.length)}async mutation(e,t,s={}){this.assertOpen();const r=t,i=s.mutationId??G(),n=s.replayBaseline===void 0?this.baselineCursorFor(s.shardKey):s.replayBaseline??void 0,{confirms:a,rollbacks:o}=this.applyOptimisticUpdates(e.__lunoraRef,r,s.shardKey,s.optimistic);s.optimisticUpdate&&this.applyOptimisticUpdate(s.optimisticUpdate,t,s.shardKey,o,a);const c=this.offlineFlushes.get(l(s.shardKey));c!==void 0&&await c;const{hasSocket:d,wasEverConnected:u,wsState:f}=this.connectionGateState(s.shardKey),{queueBeforeFirstConnect:y}=this.offlineQueue,p=u||y,T=this.WebSocketImpl!==void 0&&p,H=f==="connecting"&&p,ie=T&&s.mutationId===void 0&&this.hasPendingWriteAhead(s.shardKey);if(f!=="open"&&!d&&T||H||ie)return this.enqueueOfflineMutation(e,r,s.shardKey,n,i,o,a,s.precondition);try{let P;const ne=await this.rpc(e.__lunoraRef,r,s.shardKey,{baselineSeq:n,captureBookmark:!0,mutationId:i,onCommitCursor:L=>{P=L}});for(const L of a)L(P);return ne}catch(P){throw O(o),P}}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)),i=s.toArgs??(c=>({rows:c})),n=t.length;let a=0,o=0;for(let c=0;c<n;c+=r){const d=t.slice(c,c+r),u=o;await this.mutation(e,i(d),{...s.importId===void 0?{}:{mutationId:`${s.importId}:${String(u)}`},shardKey:s.shardKey}),o+=1,a+=d.length,s.onProgress?.({done:a,total:n})}return{chunks:o,imported:a}}async shardTraffic(e){this.assertOpen();const t=await this.adminFetch(Ge,"POST",{table:e});return{failed:t.failed??0,ok:t.ok??0,shards:t.shards??[]}}async listScheduledJobs(){return this.assertOpen(),((await this.adminFetch(je,"GET")).records??[]).map(t=>K(t))}async schedulerStatus(){this.assertOpen();const e=await this.adminFetch(ze,"GET");return{backlog:e.backlog??0,inFlight:e.inFlight??0,pools:e.pools??[]}}async cancelScheduledJob(e){return this.assertOpen(),{cancelled:(await this.adminFetch(Je,"POST",{id:e})).cancelled===!0}}async listDeadJobs(){return this.assertOpen(),(await Re(async t=>await this.adminFetch(t===void 0?Y:`${Y}?cursor=${encodeURIComponent(t)}`,"GET"))).map(t=>K(t))}async retryDeadJob(e){return this.assertOpen(),{retried:(await this.adminFetch(Ye,"POST",{id:e})).retried===!0}}async removeDeadJob(e){return this.assertOpen(),{removed:(await this.adminFetch(Xe,"POST",{id:e})).removed===!0}}async listWorkflowInstances(e){this.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 this.adminFetch(`${Ze}?${t.toString()}`,"GET");return{configured:s.configured,instances:s.instances??[],page:s.page??1,perPage:s.perPage??e.perPage??0,totalCount:s.totalCount}}async getWorkflowInstance(e){this.assertOpen();const t=new URLSearchParams({id:e.id,name:e.name}),s=await this.adminFetch(`${et}?${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??[]}}async setWorkflowInstanceStatus(e){return this.assertOpen(),{status:(await this.adminFetch(tt,"POST",{action:e.action,id:e.id,name:e.name})).status??"unknown"}}subscribeScheduledJobs(e){if(this.assertOpen(),this.WebSocketImpl===void 0)return()=>{};const t=C(X(this.url),Ve),s=j(this.reconnectOptions),r={connectTimer:void 0,heartbeatTimer:void 0,lastFrameAt:0,socket:void 0};let i,n=!1;const a=()=>{n||this.closed||(i=setTimeout(d,s.next()))},o=f=>{if(n||this.WebSocketImpl===void 0)return;const y=f===void 0?t:`${t}?token=${encodeURIComponent(f)}`;this.openManagedSocket(r,y,this.connectTimeoutMs,{onClose:()=>{a()},onMessage:p=>{let T;try{T=JSON.parse(typeof p.data=="string"?p.data:"")}catch{return}T.type==="jobs"&&Array.isArray(T.records)&&(s.reset(),e(T.records.map(H=>K(H))))}})},c=async f=>{let y;try{y=await f()}catch{a();return}o(y)},d=()=>{if(n||this.WebSocketImpl===void 0)return;const{wsToken:f}=this;if(typeof f=="function"){c(f).catch(()=>{});return}o(f)};d();const u=()=>{n=!0,i!==void 0&&(clearTimeout(i),i=void 0),r.connectTimer!==void 0&&(clearTimeout(r.connectTimer),r.connectTimer=void 0),this.stopHeartbeat(r),r.socket?.close(),r.socket=void 0};return this.adminSocketTeardowns.add(u),()=>{this.adminSocketTeardowns.delete(u),u()}}async listFunctions(){return this.assertOpen(),(await this.adminFetch(it,"GET")).functions??[]}async getCronJobs(){return this.assertOpen(),(await this.adminFetch(nt,"GET")).jobs??[]}async runCronJob(e){this.assertOpen();const t=await this.adminFetch(at,"POST",{name:e});return{name:t.name??e,ran:t.ran===!0}}async fetchOpenApi(){return this.assertOpen(),await this.adminFetch(ot,"GET")}async fetchOpenRpc(){return this.assertOpen(),await this.adminFetch(ct,"GET")}async listStorageObjects(e={}){this.assertOpen();const t=b(B,{bucket:e.bucket,cursor:e.cursor,limit:e.limit,prefix:e.prefix}),s=await this.adminFetch(t,"GET");return{cursor:s.cursor,objects:s.objects??[]}}async deleteStorageObject(e,t){this.assertOpen();const s=`${B}?key=${encodeURIComponent(e)}${N(t?.bucket)}`,r=await this.adminFetch(s,"DELETE");return{deleted:r.deleted===!0,key:r.key??e}}async listStorageBuckets(){return this.assertOpen(),(await this.adminFetch(rt,"GET")).buckets??[]}async uploadStorageObject(e){this.assertOpen();const t=`${B}?key=${encodeURIComponent(e.key)}${N(e.bucket)}`,s=await this.adminFetch(t,"PUT",e.body,e.contentType);return{etag:s.etag,key:s.key??e.key}}async signedStorageUrl(e,t){this.assertOpen();const s=t?.expiresInSeconds,r=s===void 0?"":`&expiresIn=${encodeURIComponent(s.toString())}`,i=`${st}?key=${encodeURIComponent(e)}${r}${N(t?.bucket)}`,n=await this.adminFetch(i,"GET");if(typeof n.url!="string")throw new TypeError("LunoraClient: storage URL endpoint returned no `url`");return n.url}async listGlobalTables(){return this.assertOpen(),await this.adminFetch(ht,"GET")}async readGlobalTablePage(e){this.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(M(e.filters))),v(await this.adminFetch(`${dt}?${t.toString()}`,"GET"))}async facetGlobalColumn(e){this.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(M(e.filters))),v(await this.adminFetch(`${ut}?${t.toString()}`,"GET"))}async listVectorIndexes(){return this.assertOpen(),(await this.adminFetch(lt,"GET")).indexes??[]}async queryVectorIndex(e){return this.assertOpen(),(await this.adminFetch(ft,"POST",e)).matches??[]}async queryLogArchive(e={}){this.assertOpen();const t=await this.adminFetch(pt,"POST",e);return{nextCursor:t.nextCursor,rows:t.rows??[]}}async listKvNamespaces(){return this.assertOpen(),(await this.adminFetch(mt,"GET")).namespaces??[]}async listKvKeys(e){this.assertOpen();const t=b(yt,{cursor:e.cursor,limit:e.limit,namespace:e.namespace,prefix:e.prefix});return await this.adminFetch(t,"GET")}async getKvValue(e){this.assertOpen();const t=b(Q,{key:e.key,namespace:e.namespace});return await this.adminFetch(t,"GET")}async putKvValue(e){this.assertOpen(),await this.adminFetch(Q,"PUT",e)}async deleteKvKey(e){this.assertOpen();const t=b(Q,{key:e.key,namespace:e.namespace});await this.adminFetch(t,"DELETE")}async listAuthUsers(e={}){this.assertOpen();const t=b(bt,{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 await this.adminFetch(vt,"POST",e)}async setAuthUserRole(e){return await this.adminFetch(Tt,"POST",e)}async banAuthUser(e){return await this.adminFetch(gt,"POST",e)}async unbanAuthUser(e){return await this.adminFetch(kt,"POST",e)}async setAuthUserPassword(e){await this.adminFetch(Ct,"POST",e)}async removeAuthUser(e){await this.adminFetch(wt,"POST",e)}async impersonateAuthUser(e){return await this.adminFetch(Et,"POST",e)}async revokeAuthSession(e){await this.adminFetch(At,"POST",e)}async revokeAuthUserSessions(e){await this.adminFetch(_t,"POST",e)}async getAuthCapabilities(){return await this.adminFetch(It,"GET")}async updateAuthUser(e){return await this.adminFetch(Ot,"POST",e)}async listAuthAccounts(e){return await this.adminFetch(b(Rt,{userId:e.userId}),"GET")}async unlinkAuthAccount(e){await this.adminFetch(Pt,"POST",e)}async listAuthPasskeys(e){return await this.adminFetch(b(Ft,{userId:e.userId}),"GET")}async deleteAuthPasskey(e){await this.adminFetch(Mt,"POST",e)}async disableAuthTwoFactor(e){await this.adminFetch(Ht,"POST",e)}async listAuthOrganizations(e={}){return await this.adminFetch(b(Lt,{limit:e.limit,offset:e.offset}),"GET")}async listAuthOrgMembers(e){const t=b(Ut,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async listAuthOrgInvitations(e){const t=b(xt,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async listAuthSignUpInvitations(e={}){const t=b(qt,{limit:e.limit,offset:e.offset});return await this.adminFetch(t,"GET")}async createAuthSignUpInvitation(e){return await this.adminFetch(Kt,"POST",e)}async revokeAuthSignUpInvitation(e){await this.adminFetch(Dt,"POST",e)}async removeAuthOrgMember(e){await this.adminFetch(Nt,"POST",e)}async cancelAuthOrgInvitation(e){await this.adminFetch(Bt,"POST",e)}async getAuthConfig(){return await this.adminFetch(Qt,"GET")}async createAuthOrganization(e){return await this.adminFetch(Wt,"POST",e)}async updateAuthOrganization(e){return await this.adminFetch($t,"POST",e)}async deleteAuthOrganization(e){await this.adminFetch(Gt,"POST",e)}async addAuthOrgMember(e){return await this.adminFetch(jt,"POST",e)}async inviteAuthOrgMember(e){return await this.adminFetch(zt,"POST",e)}async setAuthOrgMemberRole(e){return await this.adminFetch(Vt,"POST",e)}async listAuthOrgTeams(e){const t=b(Jt,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async createAuthOrgTeam(e){return await this.adminFetch(Yt,"POST",e)}async updateAuthOrgTeam(e){return await this.adminFetch(Xt,"POST",e)}async removeAuthOrgTeam(e){await this.adminFetch(Zt,"POST",e)}async listAuthOrgTeamMembers(e){const t=b(es,{limit:e.limit,offset:e.offset,teamId:e.teamId});return await this.adminFetch(t,"GET")}async addAuthOrgTeamMember(e){return await this.adminFetch(ts,"POST",e)}async removeAuthOrgTeamMember(e){await this.adminFetch(ss,"POST",e)}async listAuthOrgRoles(e){const t=b(rs,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async createAuthOrgRole(e){return await this.adminFetch(is,"POST",e)}async updateAuthOrgRole(e){return await this.adminFetch(ns,"POST",e)}async deleteAuthOrgRole(e){await this.adminFetch(as,"POST",e)}async listAuthSessions(e={}){this.assertOpen();const t=b(St,{limit:e.limit,offset:e.offset,userId:e.userId});return await this.adminFetch(t,"GET")}subscribe(e,t,s,r={}){this.assertOpen();const i=t??{},n=g.key(e.__lunoraRef,i,r.shardKey);let a=this.subscriptions.get(n);const o=q(s),c=q(r.onError),d=q(r.onCheckpoint);if(!a){this.nextSubId+=1;const f=`sub_${this.nextSubId.toString()}`,y=W(i),p=this.takeHydratedCache(e.__lunoraRef,y,r.shardKey);a={acked:!1,args:i,argsKey:y,callbacks:new Set,checkpointCallbacks:new Set,errorCallbacks:new Set,fn:e,id:f,lastValue:p?.value,optimisticLayers:[],serverBase:p?.value,serverCursor:p?.serverCursor,shardKey:r.shardKey,wireArgs:k(i,`args for '${e.__lunoraRef}'`),...p?.serverEpoch===void 0?{}:{serverEpoch:p.serverEpoch}},this.subscriptions.add(a),p!==void 0&&this.cacheSeededQueries.set(n,p)}if(a.callbacks.add(o),c&&a.errorCallbacks.add(c),d&&a.checkpointCallbacks.add(d),a.lastValue!==void 0)try{o(a.lastValue)}catch{}this.ensureSocket(r.shardKey),this.sendSubscribeIfOpen(a);const u=a;return()=>{u.callbacks.delete(o),c&&u.errorCallbacks.delete(c),d&&u.checkpointCallbacks.delete(d),u.callbacks.size===0&&(this.sendOrQueueUnsubscribe(u.shardKey,u.id,"unsubscribe"),this.returnCacheSeed(g.keyOf(u)),this.subscriptions.remove(u))}}subscribeShape(e,t,s={}){if(this.assertOpen(),this.followsAnotherTab()){const{onError:n}=s;return n!==void 0&&queueMicrotask(()=>{n({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()}`,i={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:k(e.args,`shape args for '${e.name}'`)};return this.shapeSubscriptions.set(r,i),this.ensureSocket(s.shardKey),this.sendShapeSubscribeIfOpen(i),()=>{this.shapeSubscriptions.delete(r),this.sendOrQueueUnsubscribe(i.shardKey,r,"shape_unsubscribe")}}stream(e,t,s={}){if(this.assertOpen(),this.WebSocketImpl===void 0)throw new m("INTERNAL","LunoraClient: streams require a WebSocket implementation");this.nextStreamId+=1;const r=`stream_${this.nextStreamId.toString()}`,{shardKey:i}=s,n=t??{},{handle:a,iterable:o}=Oe({maxBuffer:s.maxBuffer,onCancel:()=>{this.cancelStream(r,i)}});this.ensureSocket(i);const c=this.getConnection(i),d={id:r,query:{args:k(n,`stream args for '${e.__lunoraRef}'`),functionPath:e.__lunoraRef,shardKey:i},type:"stream"},u={durable:s.durable===!0,generation:void 0,handle:a,lastSeq:0,message:d,shardKey:i,started:!1};this.streams.set(r,u);const f=c?.wsState==="open"&&S(c,d);if(u.started=f,!f&&c===void 0)return this.streams.delete(r),a.fail(new m("STREAM_DISCONNECTED","stream unavailable: this tab is not the cross-tab WebSocket leader, so it holds no socket to stream over")),o;if(!f){for(c.pendingStreams=c.pendingStreams??[];c.pendingStreams.length>=Ke;){const p=c.pendingStreams.shift()?.id,T=p?this.streams.get(p):void 0;T&&(T.handle.fail(new m("STREAM_QUEUE_OVERFLOW","stream-start frame evicted while socket was unreachable")),this.streams.delete(p))}c.pendingStreams.push(d)}return o}httpStream(e,t,s={}){if(this.closed)throw new m("CLIENT_CLOSED","LunoraClient is closed");if(!this.fetchImpl)throw new m("INTERNAL","LunoraClient: no `fetch` implementation available");const r={...this.authToken?{authorization:`Bearer ${this.authToken}`}:{},...s.headers};return le(e,t,{baseUrl:this.url,fetch:this.fetchImpl,headers:r,maxBuffer:s.maxBuffer,signal:s.signal})}close(){this.closed=!0,this.outboxLeaderRelease?.(),this.outboxLeaderRelease=void 0;for(const e of this.streams.values())e.handle.fail(new m("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();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.mutationSettledListeners.clear(),this.pendingChangeListeners.clear(),this.whisperHandlers.clear(),this.shapeSubscriptions.clear(),this.pokeBuffers.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 m("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 m("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}teardownConnection(e){e.polling.stop();const t=l(e.shardKey);for(const[s,r]of this.streams)l(r.shardKey)===t&&(r.handle.fail(new m("STREAM_DISCONNECTED","stream terminated: the connection carrying it was torn down")),this.streams.delete(s));if(e.pendingStreams=void 0,e.pendingUnsubscribes=[],this.clearResubscribeQueue(e),this.clearConnectionTimers(e),this.stopHeartbeat(e),e.socket){try{e.socket.close()}catch{}e.socket=void 0}e.wsState="closed"}createTabCoordinator(){const e=`lunora-bridge::${this.url}::${this.identityFingerprint()??"anon"}`;return new ue({channelName:e,onBecomeLeader:()=>{for(const t of this.subscriptions.all())this.ensureSocket(t.shardKey),this.queueResubscribe(t);for(const t of this.queuedOfflineShardKeys)this.ensureSocket(t);this.tabCoordinator?.broadcastConnectionStatus(this.computeStatus(),this.identityFingerprint())},onStopBeingLeader:()=>{for(const[t,s]of this.connections)this.teardownConnection(s),this.connections.delete(t);this.leaderStatus=void 0,this.leaderWasEverConnected=!1},onConnectionStatus:(t,s)=>{if(s!==void 0&&s!==this.identityFingerprint())return;const r=t==="connected"&&this.leaderStatus!=="connected";this.leaderStatus=t,t==="connected"&&(this.leaderWasEverConnected=!0),this.emitConnectionStatus(),r&&this.flushAllOfflineQueues()},onSubscriptionData:(t,s,r,i,n)=>{if(n!==void 0&&n!==this.identityFingerprint())return;const a=this.subscriptions.get(t);a&&(a.serverBase=s,this.dropCacheSeed(t),r!==void 0&&(a.serverCursor=r,i!==void 0&&(a.serverEpoch=i),U(a,r)),w(a,E(s,a.optimisticLayers)))},onLeaderClaimAnswered:()=>{this.tabCoordinator?.isLeader()&&this.tabCoordinator.broadcastConnectionStatus(this.computeStatus(),this.identityFingerprint())},onSubscriptionError:(t,s,r)=>{if(r!==void 0&&r!==this.identityFingerprint())return;const i=this.subscriptions.get(t);i&&_(i.errorCallbacks,s)},onSubscriptionSettled:(t,s,r,i,n,a)=>{if(a!==void 0&&a!==this.identityFingerprint())return;const o=this.subscriptions.get(t);if(o){this.ackAndAdvanceCursor(o,s,r),i!==void 0&&n===this.clientId&&(o.lastMutationId=Math.max(o.lastMutationId??0,i));for(const c of o.checkpointCallbacks)c({checkpoint:o.serverCursor,mutationId:o.lastMutationId})}}})}async enqueueOfflineMutation(e,t,s,r,i,n,a,o){const c=this.identityFingerprint();if(this.outbox){this.outboxMutationCounter+=1;const d=this.outboxMutationCounter;try{await this.outbox.enqueue({args:t,baselineSeq:r,clientId:this.clientId,functionPath:e.__lunoraRef,idempotencyKey:`${this.clientId}:${String(d)}`,identity:c,mutationId:d,...n.length>0&&{onRejected:()=>{O(n)}},shardKey:s})}catch(u){throw O(n),u instanceof Error?u:new Error(String(u))}for(const u of a)u(void 0);return}return new Promise((d,u)=>{const f={args:t,functionPath:e.__lunoraRef,liveAwaiter:!0,baselineSeq:r,id:i,clientId:this.clientId,identity:c,precondition:o,onCommit:y=>{for(const p of a)p(y)},reject:y=>{this.queuedIdentities.delete(i),O(n),u(y instanceof Error?y:new Error(String(y)))},resolve:d,shardKey:s};this.offlineQueue.enqueue(f),this.queuedOfflineShardKeys.add(s),f.id!==void 0&&this.queuedIdentities.set(f.id,c)})}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(A(s.fn.__lunoraRef,s.argsKey,s.shardKey),s);for(const{key:s,...r}of e){if(ye(this.persistenceVersion,r.version)){this.queryCache.remove(s).catch(()=>{});continue}const i=t.get(s);if(i&&this.cachedQueryMatchesIdentity(r)){this.seedSubscriptionFromCache(i,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(A(e.fn.__lunoraRef,e.argsKey,e.shardKey),t),w(e,E(t.value,e.optimisticLayers)))}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,w(s,E(void 0,s.optimisticLayers))),this.hydratedQueryCache.set(e,t)}this.cacheSeededQueries.clear()}}takeHydratedCache(e,t,s){const r=A(e,t,s),i=this.hydratedQueryCache.get(r);if(!(i===void 0||!this.cachedQueryMatchesIdentity(i)))return this.hydratedQueryCache.delete(r),i}reseedFromHydratedCache(){if(this.hydratedQueryCache.size!==0)for(const e of this.subscriptions.all()){const t=A(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=A(e.fn.__lunoraRef,e.argsKey,e.shardKey),r=this.getConnection(e.shardKey)?.identity,i=r===void 0?this.identityFingerprint():r;i===null&&this.identityUnresolved()||(this.pendingCacheWrites.set(s,{identity:i,serverCursor:e.serverCursor,ts:Date.now(),value:t,...i===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(()=>{})},Qe))}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.leaderStatus??"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=this.subscriptions.all().filter(i=>l(i.shardKey)===t);if(s.length===0)return;const r=await this.batch(s.map(i=>({args:i.args,fn:i.fn,shardKey:i.shardKey})));for(const[i,n]of s.entries()){const a=r[i];if(a!==void 0){if(!a.ok){_(n.errorCallbacks,{code:a.error.code,message:a.error.message});continue}this.handleDataMessage({data:M(a.value),id:n.id,type:"data"})}}}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 i=[],n=[];if(!r)return{confirms:i,rollbacks:n};const a=g.key(e,t,s),o=this.subscriptions.get(a);if(o){const c=fe(o,r);c&&(i.push(c.confirm),n.push(c.rollback))}return{confirms:i,rollbacks:n}}applyOptimisticUpdate(e,t,s,r,i){const{confirms:n,rollbacks:a,store:o}=pe(this.subscriptions,s);try{e(o,t)}catch{O(a);return}r.push(...a),i.push(...n)}getConnection(e){return this.connections.get(l(e))}sendOrQueueUnsubscribe(e,t,s){const r=this.getConnection(e);r&&!S(r,{id:t,type:s})&&r.pendingUnsubscribes.push({id:t,type:s})}connectionGateState(e){if(this.tabCoordinator&&!this.tabCoordinator.isLeader()){let s="idle";return this.leaderStatus==="connected"?s="open":this.leaderStatus==="connecting"&&(s="connecting"),{hasSocket:!1,wasEverConnected:this.leaderWasEverConnected,wsState:s}}const t=this.getConnection(e);return{hasSocket:t?.socket!==void 0,wasEverConnected:t?.wasEverConnected??!1,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:Pe({afterFailedAttempts:this.pollingFallbackAfterFailedAttempts,intervalMs:this.pollingFallbackIntervalMs,onStateChange:()=>{this.emitConnectionStatus()},poll:async()=>{await this.pollSubscriptions(e)}}),reconnect:j(this.reconnectOptions),reconnectTimer:void 0,resubscribePending:new Map,resubscribeQueue:[],shardKey:e,socket:void 0,stableTimer:void 0,wasEverConnected:!1,wsState:"idle"},this.connections.set(t,s)),s}wsUrlFor(e,t){const s=[];if(e!==void 0&&s.push(`shard=${encodeURIComponent(e)}`),t!==void 0&&s.push(`token=${encodeURIComponent(t)}`),s.length===0)return this.wsUrl;const r=this.wsUrl.includes("?")?"&":"?";return`${this.wsUrl}${r}${s.join("&")}`}rpcRequestHeaders(e,t){const s={"content-type":"application/json"},r=this.shardCursors.get(this.cursorKeyFor(t));if(r!==void 0&&(s["x-lunora-min-seq"]=r.toString()),this.authToken&&(s.authorization=`Bearer ${this.authToken}`),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 i=this.bookmark.get();i&&(s["x-d1-bookmark"]=i)}return s}async rpc(e,t,s,r={}){if(!this.fetchImpl)throw new $("LunoraClient: no `fetch` implementation available");const i=this.rpcRequestHeaders(r,s),n=await this.fetchImpl(C(this.url,Fe),{body:JSON.stringify({args:k(t,`args for '${e}'`),functionPath:e,shardKey:s}),headers:i,method:"POST"});if(r.captureBookmark){const c=n.headers.get("x-d1-bookmark");c&&this.bookmark.set(c)}let a;try{a=await n.json()}catch{throw F(n.status,n.statusText,n.headers.get("retry-after"))}const o=R(a);if(o!==void 0)throw ee(o,n.headers.get("retry-after"));if(!n.ok)throw F(n.status,n.statusText,n.headers.get("retry-after"));return r.onMutationAck?.(a.lastMutationId),r.onCommitCursor?.(a.commitCursor),this.learnDefaultShardKey(n,s),this.recordShardCursor(s,a.commitCursor),v(a.result)}async adminFetch(e,t,s,r){if(!this.fetchImpl)throw new m("INTERNAL","LunoraClient: no `fetch` implementation available");const i={};this.authToken&&(i.authorization=`Bearer ${this.authToken}`);const n=s instanceof ArrayBuffer||s instanceof Blob;let a;s===void 0?a=void 0:n?(a=s,r!==void 0&&(i["content-type"]=r)):(a=JSON.stringify(s),i["content-type"]="application/json");const o=await this.fetchImpl(C(this.url,e),{body:a,headers:i,method:t});let c;try{c=await o.json()}catch{const u=o.statusText?` ${o.statusText}`:"";throw new m("INTERNAL",`LunoraClient: response was not JSON (status ${o.status.toString()}${u})`)}const d=R(c);if(d!==void 0){const u=new Error(d.message??"admin request failed");throw u.code=d.code,u}if(!o.ok){const u=o.statusText?` ${o.statusText}`:"";throw new m("INTERNAL",`LunoraClient: admin request failed (status ${o.status.toString()}${u})`)}return c}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));S(e,{caps:hs,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){let r;try{r=await s()}catch{this.handleDisconnect(e);return}this.closed||this.WebSocketImpl===void 0||e.wsState!=="connecting"||e.socket!==void 0||this.openSocket(e,t,r)}openManagedSocket(e,t,s,r){const{WebSocketImpl:i}=this;if(i===void 0)throw new m("INTERNAL","no WebSocket implementation available");const n=new i(t);e.socket=n;const a=()=>{this.stopHeartbeat(e),e.connectTimer!==void 0&&(clearTimeout(e.connectTimer),e.connectTimer=void 0),e.socket===n&&(e.socket=void 0)},o=c=>{a(),r.onClose(c)};s>0&&(e.connectTimer=setTimeout(()=>{if(e.connectTimer=void 0,e.socket===n){try{n.close()}catch{}o()}},s)),n.addEventListener("open",()=>{if(e.socket===n){e.connectTimer!==void 0&&(clearTimeout(e.connectTimer),e.connectTimer=void 0),e.lastFrameAt=Date.now();try{r.onOpen?.()}catch(c){console.error("[lunora] connection open handler threw",c)}this.startHeartbeat(e,o)}}),n.addEventListener("message",c=>{if(e.socket===n){e.lastFrameAt=Date.now();try{r.onMessage(c)}catch(d){console.error("[lunora] server frame handler threw",d)}}}),n.addEventListener("close",c=>{e.socket===n&&o(c)}),n.addEventListener("error",()=>{e.socket===n&&o()})}openSocket(e,t,s){this.WebSocketImpl!==void 0&&(e.identity=this.identityFingerprint(),e.retired=!1,this.openManagedSocket(e,this.wsUrlFor(t,s),this.connectTimeoutMs,{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.polling.noteOpen(),clearTimeout(e.stableTimer),e.stableTimer=setTimeout(()=>{e.wsState==="open"&&e.reconnect.reset()},qe),this.emitConnectionStatus(),this.sendConnectEnvelope(e),this.markShardPendingAck(t),this.clearResubscribeQueue(e);for(const i of this.subscriptions.all())l(i.shardKey)===l(t)&&this.queueResubscribe(i);if(this.resendShapeSubscriptions(t),e.pendingUnsubscribes.length>0){const i=e.pendingUnsubscribes;e.pendingUnsubscribes=[];for(const{id:n,type:a}of i)S(e,{id:n,type:a})}this.flushPendingStreams(e);const r=this.whisperHandlers.get(l(t));if(r)for(const i of r.keys())S(e,{topic:i,type:"whisper_subscribe"});this.flushOfflineQueue(t).catch(()=>{})}}))}flushPendingStreams(e){if(!e.pendingStreams||e.pendingStreams.length===0)return;const t=e.pendingStreams;e.pendingStreams=[];for(const s of t){const r=S(e,s)?this.streams.get(String(s.id)):void 0;r&&(r.started=!0)}}cancelStream(e,t){const s=this.getConnection(t),r=this.streams.get(e);s&&(s.pendingStreams=s.pendingStreams?.filter(i=>i.id!==e),!S(s,{id:e,type:"unsubscribe"})&&r?.durable===!0&&r.started&&s.pendingUnsubscribes.push({id:e,type:"unsubscribe"})),this.streams.delete(e)}handleDisconnect(e){if(this.closed||e.wsState==="idle"||e.wsState==="closed")return;e.wsState==="connecting"&&e.polling.noteFailedOpen(),this.stopHeartbeat(e),this.clearConnectionTimers(e),e.socket=void 0,e.wsState="idle",this.emitConnectionStatus(),this.markShardPendingAck(e.shardKey),this.clearResubscribeQueue(e);const t=new Set((e.pendingStreams??[]).map(r=>r.id));for(const[r,i]of this.streams)if(!(l(i.shardKey)!==l(e.shardKey)||t.has(r))){if(i.durable){const n={...i.message,...i.generation===void 0?{}:{generation:i.generation},sinceChunk:i.lastSeq};i.message=n,e.pendingStreams=[...(e.pendingStreams??[]).filter(a=>a.id!==r),n];continue}i.handle.fail(new m("STREAM_DISCONNECTED","stream terminated: WebSocket disconnected")),this.streams.delete(r)}if(this.WebSocketImpl===void 0)return;const s=e.reconnect.next();e.reconnectTimer=setTimeout(()=>{e.reconnectTimer=void 0,this.ensureSocket(e.shardKey)},s)}startHeartbeat(e,t){this.stopHeartbeat(e),!(this.heartbeatIntervalMs<=0)&&(e.heartbeatTimer=setInterval(()=>{if(!e.socket)return;const{socket:s}=e;if(Date.now()-e.lastFrameAt>this.heartbeatIntervalMs*2.5){try{s.close()}catch{}t();return}try{s.send(Le)}catch{}},this.heartbeatIntervalMs))}stopHeartbeat(e){e.heartbeatTimer!==void 0&&(clearInterval(e.heartbeatTimer),e.heartbeatTimer=void 0)}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<De;){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)},We))}}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 S(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"&&S(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=ls(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 i=this.getConnection(t);i&&this.releaseResubscribeSlot(i,r.id)}switch(r.type){case"ack":{const i=this.subscriptions.getById(r.id);i&&(i.acked=!0);return}case"chunk":{const{data:i,generation:n,id:a,seq:o}=r,c=this.streams.get(a);c&&typeof o=="number"&&(c.lastSeq=o,typeof n=="number"&&(c.generation=n),c.durable=!0),c?.handle.push(v(i));return}case"complete":{this.handleCompleteMessage(r.id);return}case"data":case"delta":{this.handleDataMessage(r);return}case"error":{this.handleErrorMessage(r);break}case"pokeEnd":{this.handlePokeEnd(r,t);break}case"pokePart":{this.handlePokePart(r,t);break}case"pokeStart":{this.handlePokeStart(r,t);break}case"resume":{this.handleResumeMessage(r);break}case"settled":{this.handleSettledMessage(r);break}case"whisper":{this.dispatchWhisper(r,t);break}}}handleErrorMessage(e){if(e.error?.code==="TOKEN_EXPIRED"){this.notifyTokenExpired();return}const{id:s}=e,r=s===void 0?void 0:this.streams.get(s);if(r&&s!==void 0){r.handle.fail(ds(e)),this.streams.delete(s);return}const i=s===void 0?void 0:this.subscriptions.getById(s);if(i){const a=Z(e),o=this.identityFingerprint(),c=g.keyOf(i);_(i.errorCallbacks,a),this.tabCoordinator?.isLeader()&&this.tabCoordinator.broadcastSubscriptionError(c,a,o);return}const n=s===void 0?void 0:this.shapeSubscriptions.get(s);n&&_(n.errorCallbacks,Z(e))}pokeBufferKey(e,t){return`${l(e)}\0${t}`}handlePokeStart(e,t){z(this.pokeBuffers,re.MAX_POKE_BUFFERS),this.pokeBuffers.set(this.pokeBufferKey(t,e.pokeId),{baseCheckpoint:e.baseCheckpoint,bases:new Map,epoch:e.epoch,lastMutationId:new Map,parts:new Map,resets:new Set})}handlePokePart(e,t){const s=this.pokeBuffers.get(this.pokeBufferKey(t,e.pokeId));if(!s)return;const r=s.parts.get(e.shapeId)??[];for(const n of e.rowsPatch)r.push(n.value===void 0?n:{...n,value:v(n.value)});s.parts.set(e.shapeId,r),e.lastMutationId!==void 0&&s.lastMutationId.set(e.shapeId,e.lastMutationId);const i=e.baseCheckpoint??s.baseCheckpoint;i!==void 0&&s.bases.set(e.shapeId,i),e.reset===!0&&s.resets.add(e.shapeId)}handlePokeEnd(e,t){const s=this.pokeBufferKey(t,e.pokeId),r=this.pokeBuffers.get(s);if(r){this.pokeBuffers.delete(s);for(const i of r.parts.keys()){const n=this.shapeSubscriptions.get(i);n&&this.applyPokePart(n,r,e)}}}applyPokePart(e,t,s){const r=t.parts.get(e.id)??[],i=t.resets.has(e.id),n=t.bases.get(e.id),a=t.epoch!==void 0&&e.serverEpoch!==void 0&&t.epoch!==e.serverEpoch,o=n!==void 0&&e.serverCursor!==void 0&&e.serverCursor!==n;if(!i&&(a||o)){e.rows.clear(),e.serverCursor=void 0,e.serverEpoch=void 0,this.emitShapeRows(e),this.sendShapeSubscribeIfOpen(e);return}i&&e.rows.clear(),He(e.rows,r),s.checkpoint!==void 0&&(e.serverCursor=s.checkpoint),s.epoch!==void 0&&(e.serverEpoch=s.epoch);const c=t.lastMutationId.get(e.id);c!==void 0&&(e.lastMutationId=c),this.emitShapeRows(e),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)}emitShapeRows(e){const t=[...e.rows.values()];for(const s of e.callbacks)try{s(t)}catch{}}handleDataMessage(e){const{id:t}=e,s=t?this.subscriptions.getById(t):void 0;if(!s)return;let r;try{r=this.resolveDataPayload(e,s)}catch(i){_(s.errorCallbacks,{code:"WIRE_DECODE_FAILED",message:`could not decode a server frame for this subscription — ${i instanceof Error?i.message:String(i)}`});return}if(r===J){this.resnapshotSubscription(s);return}if(s.serverBase=r,this.dropCacheSeed(g.keyOf(s)),e.cursor!==void 0&&(s.serverCursor=e.cursor),e.epoch!==void 0&&(s.serverEpoch=e.epoch),e.lastMutationId!==void 0){s.lastMutationId=Math.max(s.lastMutationId??0,e.lastMutationId);for(const i of s.checkpointCallbacks)i({checkpoint:s.serverCursor,mutationId:s.lastMutationId,rowsFollow:!0})}if(this.persistQueryValue(s),U(s,s.serverCursor),w(s,E(r,s.optimisticLayers)),this.tabCoordinator?.isLeader()){const i=g.keyOf(s);this.tabCoordinator.broadcastSubscriptionData(i,r,s.serverCursor,s.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&&(t.lastMutationId=Math.max(t.lastMutationId??0,e.lastMutationId));for(const s of t.checkpointCallbacks)s({checkpoint:t.serverCursor,mutationId:t.lastMutationId});if(this.tabCoordinator?.isLeader()){const s=g.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),U(e,e.serverCursor)&&w(e,E(e.serverBase,e.optimisticLayers)))}resolveDataPayload(e,t){if("data"in e&&e.data!==void 0)return v(e.data);const s=v(e.delta);return ae(s)?t.serverBase===void 0?s:oe(t.serverBase,s)??J:s}dispatchWhisper(e,t){const s=this.whisperHandlers.get(l(t))?.get(e.topic);if(!s)return;const r=v(e.data);for(const i of s)try{i(r,e.from)}catch{}}notifyTokenExpired(){this.tokenExpiredListeners.emit()}handleCompleteMessage(e){const t=this.streams.get(e);if(t){t.handle.complete(),this.streams.delete(e);return}const s=this.subscriptions.getById(e);s&&(s.acked=!1,_(s.errorCallbacks,{code:"SUBSCRIPTION_CANCELLED",message:"subscription was cancelled by the server"}))}unpersist(e){e&&this.persistence?.remove(e).catch(t=>{be(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 i=e.charCodeAt(r);t^=i,t=Math.imul(t,16777619),s=Math.imul(s,33)+i}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&&this.computeStatus()==="connected"&&this.flushAllOfflineQueues()}identityUnresolved(){return this.sessionProbesInFlight>0?!0:this.identityResolutionExpected&&!this.identitySettled}adoptResolvedSubject(e,t,s){this.closed||t===null||this.authToken!==e||s!==this.sessionProbeGeneration||this.setAuthToken(e,t.id)}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}rejectQueuedForIdentityChange(e){const t=this.offlineQueue.drain(),s=[];for(const r of t){if(this.replayIdentityVerdict(this.stampOf(r))!=="mismatch"){s.push(r);continue}this.queuedIdentities.delete(r.id??""),this.unpersist(r.id);const i=new Error("offline mutation discarded: auth identity changed before replay");i.code="OFFLINE_IDENTITY_CHANGED",r.reject(i),this.emitItemSettled(r,"rejected",i)}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 i=t??"",n=this.clientWatermarks.get(i);if(n===void 0)this.clientWatermarks.set(i,r);else for(const[a,o]of r)n.set(a,o)}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.revokeCacheSeededValues();for(const e of this.subscriptions.all())e.serverBase=void 0,e.serverCursor=void 0,e.serverEpoch=void 0,e.acked=!1,w(e,E(void 0,e.optimisticLayers));for(const e of this.shapeSubscriptions.values())e.rows.clear(),e.serverCursor=void 0,e.serverEpoch=void 0,this.emitShapeRows(e);this.bounceShardSockets()}restartTabCoordinatorForIdentity(){if(!this.tabCoordinator)return;const e=this.tabCoordinator.isLeader();this.tabCoordinator.stop(),this.tabCoordinator=this.createTabCoordinator(),this.tabCoordinator.start(),e&&this.tabCoordinator.promoteImmediately()}bounceShardSockets(){for(const e of this.connections.values())if(e.socket){e.retired=!0;try{e.socket.close()}catch{}}}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());try{await this.drainOfflineQueue(e)}catch{}})();this.offlineFlushes.set(t,r),await r,this.offlineFlushes.get(t)===r&&this.offlineFlushes.delete(t)}async drainOfflineQueue(e){const t=this.offlineQueue.drainConflict();for(const c of t){this.unpersist(c.id),this.queuedIdentities.delete(c.id??"");const d=new Error("offline mutation skipped: precondition failed before replay");d.code="OFFLINE_PRECONDITION_FAILED",this.emitItemSettled(c,"rejected",d)}const s=l(e),r=this.offlineQueue.drain(c=>l(c.shardKey)===s);if(r.length===0)return;const i=[],n=[];for(const c of r){const d=this.replayGateVerdict(c);d==="send"?i.push(c):d==="hold"&&n.push(c)}if(this.offlineQueue.requeue(n),n.length>0&&this.subjectAwaitingReconfirm()&&(this.getCurrentUser().catch(()=>{}),this.noteHeldRetryDelay(e)),i.length===0){this.scheduleRateLimitedRetry(e);return}const a=this.encodableOrSettleTerminal(i);if(a.length===0){this.scheduleRateLimitedRetry(e);return}if(a.length===1){await this.replaySequential(a,e),this.scheduleRateLimitedRetry(e);return}const o=[];for(let c=0;c<a.length;c+=x){const d=a.slice(c,c+x),u=await this.replayBatched(d,e);if(o.push(...u.requeue),u.stop){o.push(...a.slice(c+x));break}}o.length>0&&this.offlineQueue.requeue(o),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,Te(r))})}noteReplayRetryDelay(e,t){const s=l(e),r=this.replayRetryState.get(s),i=(r?.attempts??0)+1,n=ge(t,i);this.replayRetryState.set(s,{attempts:i,delayMs:n===void 0?r?.delayMs:Math.max(r?.delayMs??0,n)})}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 i=this.replayRetryTimers.get(t);i!==void 0&&clearTimeout(i),this.replayRetryTimers.set(t,setTimeout(()=>{this.replayRetryTimers.delete(t),this.flushOfflineQueue(e).catch(()=>{})},r))}encodableOrSettleTerminal(e){const t=[];for(const s of e)try{k(s.args,`args for '${s.functionPath}'`),t.push(s)}catch(r){this.settleReplayTerminal(s,r instanceof Error?r:new Error(String(r)))}return t}replayGateVerdict(e){const t=this.stampOf(e);if(t===void 0)return this.queuedIdentities.delete(e.id??""),"send";const s=this.replayIdentityVerdict(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){if(ke(e)){const t=this.hashToken(this.authToken??"");return this.authRefusalNotifiedFor!==t&&(this.authRefusalNotifiedFor=t,this.notifyTokenExpired()),!0}return Ce(e)}settleReplayTerminal(e,t){this.unpersist(e.id),e.reject(t),this.emitItemSettled(e,"rejected",t)}async replaySequential(e,t){for(let s=0;s<e.length;s+=1){const r=e[s];if(r)try{let i;const n=await this.rpc(r.functionPath,r.args,r.shardKey,{baselineSeq:r.baselineSeq,captureBookmark:!0,clientId:r.clientId??this.clientId,mutationId:r.id,onCommitCursor:a=>{i=a}});this.settleReplaySuccess(r,n,i)}catch(i){if(!this.shouldRequeueReplayFailure(i)){this.settleReplayTerminal(r,i);continue}this.noteReplayRetryDelay(t,i),this.offlineQueue.requeue(e.slice(s));return}}}async replayBatched(e,t){if(!this.fetchImpl)return{requeue:e,stop:!0};const s=JSON.stringify({calls:e.map((o,c)=>({args:k(o.args,`args for '${o.functionPath}'`),baselineSeq:o.baselineSeq,functionPath:o.functionPath,id:c,clientId:o.clientId??this.clientId,mutationId:o.id,shardKey:o.shardKey}))});if(e.length>1&&we(s)>Ee)return await this.replayBatchedHalves(e,t);let r;try{r=await this.fetchImpl(C(this.url,V),{body:s,headers:this.rpcRequestHeaders({attachBookmark:!0}),method:"POST"})}catch{return{requeue:e,stop:!0}}const i=r.headers.get("x-d1-bookmark");if(i&&this.bookmark.set(i),r.status===413&&e.length>1)return await this.replayBatchedHalves(e,t);let n;const a=r.headers.get("retry-after");try{n=await r.json()}catch{return this.settleWholeBatchError(e,F(r.status,r.statusText,a),t)}if(!n.results){const o=R(n),c=o===void 0?F(r.status,r.statusText,a):ee(o,a);return this.settleWholeBatchError(e,c,t)}return{requeue:this.settleReplayBatchSlots(e,n.results,t),stop:!1}}settleWholeBatchError(e,t,s){if(t instanceof $||t.code!==void 0&&this.shouldRequeueReplayFailure(t))return this.noteReplayRetryDelay(s,t),{requeue:e,stop:!0};for(const r of e)this.settleReplayTerminal(r,t);return{requeue:[],stop:!1}}async replayBatchedHalves(e,t){const s=Math.ceil(e.length/2),r=await this.replayBatched(e.slice(0,s),t);if(r.stop)return{requeue:[...r.requeue,...e.slice(s)],stop:!0};const i=await this.replayBatched(e.slice(s),t);return{requeue:[...r.requeue,...i.requeue],stop:i.stop}}settleReplayBatchSlots(e,t,s){const r=new Map;for(const n of t)typeof n.id=="number"&&n.body!==void 0&&r.set(n.id,n.body);const i=[];for(const[n,a]of e.entries()){const o=r.get(n);if(o===void 0)i.push(a);else if("error"in o){const c=se(o);this.shouldRequeueReplayFailure(c)?(this.noteReplayRetryDelay(s,c),i.push(a)):this.settleReplayTerminal(a,c)}else this.settleReplaySuccess(a,v(o.result),o.commitCursor)}return i}}export{re as LunoraClient};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{c as t}from"./local-store-BjenEm3t.mjs";import"./SubscriptionRegistry-CS-AFUI9.mjs";export{t as createLocalStore};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import{LunoraError as l}from"@lunora/errors";import{d as h}from"./wire-codec-Sw1rAu-Z.mjs";import{createStream as u}from"./DEFAULT_MAX_BUFFER-D3QH2iaq.mjs";const m=/^ /u,p=t=>typeof t=="object"&&t!==null?JSON.stringify(t):String(t),S=t=>{let r="";const e=[];for(const n of t.split(`
|
|
2
|
-
`))n.startsWith("event:")?r=n.slice(6).replace(m,""):n.startsWith("data:")&&e.push(n.slice(5).replace(m,""));return{data:e.join(`
|
|
3
|
-
`),event:r}},T=(t,r,e)=>{const n=r.params??{},o=t.path.split("/").map(c=>{if(!c.startsWith(":"))return c;const f=c.slice(1),a=n[f];if(a===void 0)throw new l("HTTP_STREAM_MISSING_PARAM",`httpStream: missing path param ":${f}" for route ${t.path}`);return encodeURIComponent(p(a))}).join("/"),i=new URLSearchParams;for(const[c,f]of Object.entries(r.searchParams??{}))f!==void 0&&i.set(c,p(f));const s=i.toString();return`${e.endsWith("/")?e.slice(0,-1):e}${o}${s===""?"":`?${s}`}`},E=(t,r)=>{if(t.event==="complete")return r.complete(),!0;if(t.event==="error"){let e={};try{e=JSON.parse(t.data)}catch{}const n=typeof e.message=="string"?e.message:"stream error",o=typeof e.code=="string"?e.code:"HTTP_STREAM_ERROR";return r.fail(new l(o,n)),!0}if((t.event===""||t.event==="message")&&t.data!=="")try{r.push(h(JSON.parse(t.data)))}catch{return r.fail(new l("HTTP_STREAM_BAD_CHUNK","httpStream: malformed SSE chunk (invalid JSON)")),!0}return!1},b=async(t,r)=>{const e=t.getReader(),n=new TextDecoder;let o="";const i=()=>{let s=o.indexOf(`
|
|
4
|
-
|
|
5
|
-
`);for(;s!==-1;){const d=S(o.slice(0,s));if(o=o.slice(s+2),E(d,r))return!0;s=o.indexOf(`
|
|
6
|
-
|
|
7
|
-
`)}return!1};for(;;){const{done:s,value:d}=await e.read();if(s)break;if(o+=n.decode(d,{stream:!0}).replaceAll(`\r
|
|
8
|
-
`,`
|
|
9
|
-
`),i()){await e.cancel().catch(()=>{});return}}o+=n.decode().replaceAll(`\r
|
|
10
|
-
`,`
|
|
11
|
-
`),i()||r.fail(new l("HTTP_STREAM_INTERRUPTED","httpStream: stream ended without a complete frame"))},_=(t,r,e={})=>{const n=e.fetch??(typeof fetch=="function"?fetch.bind(globalThis):void 0);if(!n)throw new l("INTERNAL","httpStream: no `fetch` implementation available");const o=T(t,r??{},e.baseUrl??""),i=new AbortController;let s;e.signal&&(e.signal.aborted?i.abort():(s=()=>{i.abort()},e.signal.addEventListener("abort",s,{once:!0})));const d=()=>{s&&e.signal?.removeEventListener("abort",s)},{handle:c,iterable:f}=u({maxBuffer:e.maxBuffer,onCancel:()=>{i.abort()}});return(async()=>{try{const a=await n(o,{headers:{accept:"text/event-stream",...e.headers},method:t.method,signal:i.signal});if(!a.ok){await a.body?.cancel().catch(()=>{}),c.fail(new l("HTTP_STREAM_STATUS",`httpStream: request failed (status ${a.status.toString()})`,{status:a.status}));return}if(!a.body){c.fail(new l("HTTP_STREAM_NO_BODY","httpStream: response has no body"));return}await b(a.body,c)}finally{d()}})().catch(a=>{if(i.signal.aborted){c.complete();return}if(a instanceof Error&&"code"in a){c.fail(a);return}c.fail(new l("HTTP_STREAM_TRANSPORT",a instanceof Error?a.message:String(a),{cause:a}))}),f};export{_ as httpStream};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{SubscriptionRegistry as m}from"./SubscriptionRegistry-CS-AFUI9.mjs";const p=(r,e)=>{let o=r;for(const s of e)try{o=s.transform(o)}catch{}return o},u=(r,e)=>{if(e!==r.lastValue){r.lastValue=e;for(const o of r.callbacks)try{o(e)}catch{}}},y=(r,e)=>{let o;try{o=e(r.lastValue)}catch{return}const s={id:Symbol("optimistic"),transform:e};let c=!1;r.optimisticLayers.push(s),u(r,o);const l=()=>{const t=r.optimisticLayers.findIndex(n=>n.id===s.id);return t===-1?!1:(r.optimisticLayers.splice(t,1),!0)},i=()=>{u(r,p(r.serverBase,r.optimisticLayers))};return{confirm:t=>{if(t===void 0){l();return}s.commitCursor=t,r.serverCursor!==void 0&&r.serverCursor>=t&&l()&&i()},rollback:()=>{c||(c=!0,l(),i())}}},h=(r,e)=>{if(e===void 0||r.optimisticLayers.length===0)return!1;const o=r.optimisticLayers.length;return r.optimisticLayers=r.optimisticLayers.filter(s=>s.commitCursor===void 0||s.commitCursor>e),r.optimisticLayers.length!==o},L=(r,e)=>{const o=[],s=[],c=(i,t)=>r.get(m.key(i,t,e));return{confirms:o,rollbacks:s,store:{getAllQueries:i=>{const t=[];for(const n of r.all())n.fn.__lunoraRef===i.__lunoraRef&&(n.shardKey??"")===(e??"")&&t.push({args:n.args,value:n.lastValue});return t},getQuery:(i,t)=>c(i.__lunoraRef,t??{})?.lastValue,setQuery:(i,t,n)=>{const f=c(i.__lunoraRef,t??{});if(!f)return;const a=y(f,()=>n);a&&(o.push(a.confirm),s.push(a.rollback))}}}};export{y as a,L as c,h as d,p as f,u as n};
|