@lunora/client 1.0.0-alpha.100 → 1.0.0-alpha.102

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -63,8 +63,21 @@ const client = new LunoraClient({ url: "https://app.acme.test" });
63
63
  // One-shot query (HTTP, carries the D1 bookmark for read-your-writes).
64
64
  const messages = await client.query(api.messages.list, { room: "general" });
65
65
 
66
- // Mutation with an optimistic update applied to matching subscribers.
67
- await client.mutation(api.messages.send, { body: "hi" }, { optimistic: (current = []) => [...current, { body: "hi", pending: true }] });
66
+ // Mutation with an optimistic update. `optimisticUpdate` names the query it
67
+ // patches a write and the queries it affects are different functions, and only
68
+ // you know which. (The per-call `optimistic` shortcut patches the subscription
69
+ // registered under the mutation's OWN reference and args, nothing else.)
70
+ await client.mutation(
71
+ api.messages.send,
72
+ { room: "general", body: "hi" },
73
+ {
74
+ optimisticUpdate: (store, args) => {
75
+ const current = store.getQuery(api.messages.list, { room: args.room }) ?? [];
76
+
77
+ store.setQuery(api.messages.list, { room: args.room }, [...current, { body: args.body, pending: true }]);
78
+ },
79
+ },
80
+ );
68
81
 
69
82
  // Live subscription over WS — returns an unsubscribe function.
70
83
  const unsubscribe = client.subscribe(api.messages.list, { room: "general" }, (next) => {
@@ -1,13 +1,35 @@
1
- import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-C5tvkz8x.mjs";
1
+ import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-zO8sL_gk.mjs";
2
2
  import '@lunora/errors';
3
3
  import "../packem_shared/function-reference.d-Br_hsKje.mjs";
4
4
  import '@lunora/runtime';
5
+ /**
6
+ * Resolved authentication state. See the contract table in this module's header
7
+ * — the states are not interchangeable, and `unreachable` is the one that exists
8
+ * only so "the server said no session" and "we could not ask" stop colliding.
9
+ */
10
+ type AuthStatus = "authenticated" | "loading" | "unauthenticated" | "unreachable";
11
+ /**
12
+ * Whether a gate should render its authenticated branch.
13
+ *
14
+ * Both `authenticated` and `unreachable` qualify: the credential is held in
15
+ * either case, and only the identity round-trip differs.
16
+ */
17
+ declare const isAuthenticatedStatus: (status: AuthStatus) => boolean;
18
+ /** Whether a gate should render its loading branch — the first resolve only. */
19
+ declare const isLoadingStatus: (status: AuthStatus) => boolean;
5
20
  interface IdentityStore {
6
- /** Read the current resolved user, or `null` when signed out / not yet resolved. */
21
+ /** The current {@link AuthStatus} what a gate branches on. */
22
+ getStatus: () => AuthStatus;
23
+ /**
24
+ * The last resolved user, or `null`. `null` does NOT mean signed out on its
25
+ * own: read `getStatus` for that. A user resolved before the endpoint
26
+ * went unreachable is retained, so the UI keeps rendering the identity it
27
+ * last knew instead of blanking.
28
+ */
7
29
  getUser: () => User | null;
8
30
  /**
9
31
  * Subscribe to identity changes. `onChange` is called whenever the user or
10
- * token changes. Returns an unsubscribe handle.
32
+ * the status changes. Returns an unsubscribe handle.
11
33
  */
12
34
  subscribe: (onChange: () => void) => () => void;
13
35
  }
@@ -19,4 +41,4 @@ interface IdentityStore {
19
41
  * returns the same store, keeping the single-fetch / fan-out invariant.
20
42
  */
21
43
  declare const getIdentityStore: (client: LunoraClient) => IdentityStore;
22
- export { type IdentityStore, getIdentityStore };
44
+ export { type AuthStatus, type IdentityStore, getIdentityStore, isAuthenticatedStatus, isLoadingStatus };
@@ -1,13 +1,35 @@
1
- import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-CK3FxGNH.js";
1
+ import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-Do8Jp8Ow.js";
2
2
  import '@lunora/errors';
3
3
  import "../packem_shared/function-reference.d-Br_hsKje.js";
4
4
  import '@lunora/runtime';
5
+ /**
6
+ * Resolved authentication state. See the contract table in this module's header
7
+ * — the states are not interchangeable, and `unreachable` is the one that exists
8
+ * only so "the server said no session" and "we could not ask" stop colliding.
9
+ */
10
+ type AuthStatus = "authenticated" | "loading" | "unauthenticated" | "unreachable";
11
+ /**
12
+ * Whether a gate should render its authenticated branch.
13
+ *
14
+ * Both `authenticated` and `unreachable` qualify: the credential is held in
15
+ * either case, and only the identity round-trip differs.
16
+ */
17
+ declare const isAuthenticatedStatus: (status: AuthStatus) => boolean;
18
+ /** Whether a gate should render its loading branch — the first resolve only. */
19
+ declare const isLoadingStatus: (status: AuthStatus) => boolean;
5
20
  interface IdentityStore {
6
- /** Read the current resolved user, or `null` when signed out / not yet resolved. */
21
+ /** The current {@link AuthStatus} what a gate branches on. */
22
+ getStatus: () => AuthStatus;
23
+ /**
24
+ * The last resolved user, or `null`. `null` does NOT mean signed out on its
25
+ * own: read `getStatus` for that. A user resolved before the endpoint
26
+ * went unreachable is retained, so the UI keeps rendering the identity it
27
+ * last knew instead of blanking.
28
+ */
7
29
  getUser: () => User | null;
8
30
  /**
9
31
  * Subscribe to identity changes. `onChange` is called whenever the user or
10
- * token changes. Returns an unsubscribe handle.
32
+ * the status changes. Returns an unsubscribe handle.
11
33
  */
12
34
  subscribe: (onChange: () => void) => () => void;
13
35
  }
@@ -19,4 +41,4 @@ interface IdentityStore {
19
41
  * returns the same store, keeping the single-fetch / fan-out invariant.
20
42
  */
21
43
  declare const getIdentityStore: (client: LunoraClient) => IdentityStore;
22
- export { type IdentityStore, getIdentityStore };
44
+ export { type AuthStatus, type IdentityStore, getIdentityStore, isAuthenticatedStatus, isLoadingStatus };
@@ -1 +1 @@
1
- const f=new WeakMap,a=r=>{const t=new Set;let s=null,u=!1;const c=()=>{for(const e of t)e()};let n=0;const o=e=>{s!==e&&(s=e,c())},l=()=>{n+=1;const e=n;if(r.getAuthToken()===null){o(null);return}r.getCurrentUser().then(i=>{e===n&&o(i)}).catch(()=>{e===n&&o(null)})};return r.onAuthTokenChange(l),{getUser:()=>s,subscribe:e=>(t.add(e),u||(u=!0,l()),()=>{t.delete(e)})}},d=r=>{let t=f.get(r);return t||(t=a(r),f.set(r,t)),t};export{d as getIdentityStore};
1
+ const f=t=>t==="authenticated"||t==="unreachable",g=t=>t==="loading",l=new WeakMap,h=t=>{const n=new Set;let a=null,r=t.getAuthToken()===null?"unauthenticated":"loading",i=!1;const d=()=>{for(const e of n)e()};let o=0;const s=(e,u)=>{(r!==e||a!==u)&&(r=e,a=u,d())},c=()=>{o+=1;const e=o;if(t.getAuthToken()===null){s("unauthenticated",null);return}s(a===null?"loading":"authenticated",a),t.getCurrentUser().then(u=>{e===o&&s(u===null?"unauthenticated":"authenticated",u)}).catch(()=>{e===o&&s("unreachable",a)})};return t.onAuthTokenChange(c),t.onConnectionStatus(e=>{e==="connected"&&r==="unreachable"&&c()}),{getStatus:()=>r,getUser:()=>a,subscribe:e=>(n.add(e),i||(i=!0,c()),()=>{n.delete(e)})}},S=t=>{let n=l.get(t);return n||(n=h(t),l.set(t,n)),n};export{S as getIdentityStore,f as isAuthenticatedStatus,g as isLoadingStatus};
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-C5tvkz8x.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-C5tvkz8x.mjs";
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-zO8sL_gk.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-zO8sL_gk.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-CAXl1Y8Y.mjs";
5
+ export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-CV5OAa01.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';
@@ -143,7 +143,7 @@ declare const maxSeq: (messages: ReadonlyArray<{
143
143
  * persists only the user row (+1). Those non-(+2) turns are retired by the PRIMARY
144
144
  * seq-based content match below (which sees the user row land at a greater `seq`),
145
145
  * never by this count-based fallback. The fully robust fix is a server-echoed
146
- * correlation id on each persisted user row (deferred see plan 188).
146
+ * correlation id on each persisted user row (deferred; no plan filed).
147
147
  *
148
148
  * KNOWN LIMITATION (inherent to a client-only heuristic): on an ownerless /
149
149
  * `instanceId`-less thread a FOREIGN writer that advances `seq` by >= 2 between this
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-CK3FxGNH.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-CK3FxGNH.js";
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-Do8Jp8Ow.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-Do8Jp8Ow.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-Csjxr5HM.js";
5
+ export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-fzoWay0Y.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';
@@ -143,7 +143,7 @@ declare const maxSeq: (messages: ReadonlyArray<{
143
143
  * persists only the user row (+1). Those non-(+2) turns are retired by the PRIMARY
144
144
  * seq-based content match below (which sees the user row land at a greater `seq`),
145
145
  * never by this count-based fallback. The fully robust fix is a server-echoed
146
- * correlation id on each persisted user row (deferred see plan 188).
146
+ * correlation id on each persisted user row (deferred; no plan filed).
147
147
  *
148
148
  * KNOWN LIMITATION (inherent to a client-only heuristic): on an ownerless /
149
149
  * `instanceId`-less thread a FOREIGN writer that advances `seq` by >= 2 between this
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-CPdblK2G.mjs";import{c as P}from"./packem_shared/local-store-CVfQDdXy.mjs";import{LunoraClient as k}from"./packem_shared/LunoraClient-DArMFG67.mjs";import{createMutatorRunner as q}from"./packem_shared/createMutatorRunner-CuMRJpUx.mjs";import{O as v}from"./packem_shared/offline-queue-xntsWiKt.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};
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-CPdblK2G.mjs";import{c as P}from"./packem_shared/local-store-BjenEm3t.mjs";import{LunoraClient as k}from"./packem_shared/LunoraClient-C5AvZOeg.mjs";import{createMutatorRunner as q}from"./packem_shared/createMutatorRunner-CuMRJpUx.mjs";import{O as v}from"./packem_shared/offline-queue-xntsWiKt.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 m}from"@lunora/errors";import{i as oe,a as ce,P as he}from"./delta-merge-vxvH3PvF.mjs";import{e as K,d as T}from"./wire-codec-Sw1rAu-Z.mjs";import{s as q}from"./wire-key-HsUDTlQ7.mjs";import de from"./createInMemoryBookmarkStorage-BooZhW0n.mjs";import{ClientQueryStore as ue}from"./createClientQuery-B8Nfj-7o.mjs";import{TabCoordinator as le}from"./TabCoordinator-CXD7vulJ.mjs";import{TransportError as P,getRetryAfterMs as Z}from"./CONFLICT_ERROR_CODE-BOeeP_Wl.mjs";import{httpStream as fe}from"./httpStream-CPdblK2G.mjs";import{d as L,n as _,f as A,a as me,c as pe}from"./local-store-BjenEm3t.mjs";import{O as ye,n as W,i as Se,r as be}from"./offline-queue-xntsWiKt.mjs";import{resolvePersistenceAdapter as Te}from"./createInMemoryPersistence-Cz2W6XVj.mjs";import{resolveQueryCacheAdapter as ve,queryCacheKey as E}from"./createInMemoryQueryCache-D2uNHLfM.mjs";import{createReconnect as $}from"./createReconnect-CjTmjJDH.mjs";import ge from"./createSnapshotPrecondition-GRVKxPsh.mjs";import{createStream as ke}from"./DEFAULT_MAX_BUFFER-D3QH2iaq.mjs";import{SubscriptionRegistry as v}from"./SubscriptionRegistry-CS-AFUI9.mjs";const U=500,Ce=async o=>{const e=[];let t;for(;;){const s=await o(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}},G=(o,e)=>{if(o.size<e)return;const t=o.keys().next().value;t!==void 0&&o.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 ee=new Set(["RATE_LIMITED","SHARD_ERROR","SHARD_UNAVAILABLE","TOO_MANY_REQUESTS"]),te=new Set(["TOKEN_EXPIRED","UNAUTHENTICATED","UNAUTHORIZED"]),we=o=>te.has(o?.code??""),Ee=o=>{if(o instanceof P)return!0;const e=o?.code;return e===void 0||ee.has(e)||te.has(e)},se=6e4,_e=1e3,re=o=>{if(o===null)return;const e=Number(o);if(Number.isFinite(e))return e>0?e*1e3:void 0;const t=Date.parse(o);if(Number.isNaN(t))return;const s=t-Date.now();return s>0?s:void 0},Ae={401:"UNAUTHORIZED",403:"FORBIDDEN",404:"NOT_FOUND",413:"PAYLOAD_TOO_LARGE",429:"TOO_MANY_REQUESTS"},M=(o,e,t)=>{const s=re(t),r=s===void 0?void 0:{retryAfterMs:s},i=`LunoraClient: response carried no error envelope (status ${o.toString()}${e?` ${e}`:""})`;return o<400||o>=500||o===408?new P(i,r):new m(Ae[o]??"BAD_REQUEST",i,{data:r})},Ie=(o,e)=>{const t=re(e);if(!(t===void 0||Z(o)!==void 0))return o.data===void 0?{retryAfterMs:t}:typeof o.data=="object"&&o.data!==null&&!Array.isArray(o.data)?{...o.data,retryAfterMs:t}:void 0},Oe=(o,e=Math.random)=>{const t=Math.min(_e*2**Math.max(o-1,0),se);return Math.round(t*(.5+e()*.5))},Re=o=>o instanceof P||ee.has(o?.code??""),Pe=(o,e,t)=>{const s=Z(o);return s!==void 0&&s>0?Math.min(s,se):Re(o)?Oe(e,t):void 0},Me=983040,Fe=o=>typeof TextEncoder>"u"?o.length:new TextEncoder().encode(o).length,He="/_lunora/rpc",j="/_lunora/rpc-batch",Le="/_lunora/ws",N=o=>o===void 0||o===""?"":`&bucket=${encodeURIComponent(o)}`,O=o=>{for(let e=o.length-1;e>=0;e-=1)o[e]?.()},V=Symbol("lunora.unmergeableDelta"),Ue=(o,e)=>{for(const t of e)t.op==="delete"?o.delete(t.key):t.value!==void 0&&o.set(t.key,t.value)},Ne="lunora-ping",xe=3e4,De=1e4,Be=250,Qe=5e3,Ke=64,qe=8,We="/_lunora/admin/shard-traffic",$e="/_lunora/admin/scheduled",Ge="/_lunora/admin/scheduled/status",je="/_lunora/admin/scheduled/ws",Ve="/_lunora/admin/scheduled/cancel",z="/_lunora/admin/scheduled/dead",ze="/_lunora/admin/scheduled/dead/retry",Ye="/_lunora/admin/scheduled/dead/cancel",Je="/_lunora/admin/workflows/instances",Xe="/_lunora/admin/workflows/instance",Ze="/_lunora/admin/workflows/status",x="/_lunora/admin/storage",et="/_lunora/admin/storage/url",tt="/_lunora/admin/storage/buckets",st="/_lunora/admin/functions",rt="/_lunora/admin/cron-jobs",it="/_lunora/admin/cron-jobs/run",nt="/_lunora/admin/openapi",at="/_lunora/admin/openrpc",ot="/_lunora/admin/global/tables",ct="/_lunora/admin/global/table",ht="/_lunora/admin/global/facet",dt="/_lunora/admin/vector/indexes",ut="/_lunora/admin/vector/query",lt="/_lunora/admin/logs/archive",ft="/_lunora/admin/kv/namespaces",mt="/_lunora/admin/kv/keys",D="/_lunora/admin/kv/value",pt="/_lunora/admin/auth/users",yt="/_lunora/admin/auth/sessions",St="/_lunora/admin/auth/users/create",bt="/_lunora/admin/auth/users/role",Tt="/_lunora/admin/auth/users/ban",vt="/_lunora/admin/auth/users/unban",gt="/_lunora/admin/auth/users/password",kt="/_lunora/admin/auth/users/remove",Ct="/_lunora/admin/auth/users/impersonate",wt="/_lunora/admin/auth/sessions/revoke",Et="/_lunora/admin/auth/sessions/revoke-all",_t="/_lunora/admin/auth/capabilities",At="/_lunora/admin/auth/users/update",It="/_lunora/admin/auth/accounts",Ot="/_lunora/admin/auth/accounts/unlink",Rt="/_lunora/admin/auth/passkeys",Pt="/_lunora/admin/auth/passkeys/delete",Mt="/_lunora/admin/auth/two-factor/disable",Ft="/_lunora/admin/auth/organizations",Ht="/_lunora/admin/auth/organizations/members",Lt="/_lunora/admin/auth/organizations/invitations",Ut="/_lunora/admin/auth/organizations/members/remove",Nt="/_lunora/admin/auth/organizations/invitations/cancel",xt="/_lunora/admin/auth/config",Dt="/_lunora/admin/auth/sign-up-invitations",Bt="/_lunora/admin/auth/sign-up-invitations/create",Qt="/_lunora/admin/auth/sign-up-invitations/revoke",Kt="/_lunora/admin/auth/organizations/create",qt="/_lunora/admin/auth/organizations/update",Wt="/_lunora/admin/auth/organizations/remove",$t="/_lunora/admin/auth/organizations/members/add",Gt="/_lunora/admin/auth/organizations/members/invite",jt="/_lunora/admin/auth/organizations/members/role",Vt="/_lunora/admin/auth/organizations/teams",zt="/_lunora/admin/auth/organizations/teams/create",Yt="/_lunora/admin/auth/organizations/teams/update",Jt="/_lunora/admin/auth/organizations/teams/remove",Xt="/_lunora/admin/auth/organizations/teams/members",Zt="/_lunora/admin/auth/organizations/teams/members/add",es="/_lunora/admin/auth/organizations/teams/members/remove",ts="/_lunora/admin/auth/organizations/roles",ss="/_lunora/admin/auth/organizations/roles/create",rs="/_lunora/admin/auth/organizations/roles/update",is="/_lunora/admin/auth/organizations/roles/remove",ns="/api/auth",as="/get-session",Y=o=>o.startsWith("https://")?`wss://${o.slice(8)}`:o.startsWith("http://")?`ws://${o.slice(7)}`:o,C=(o,e)=>`${o.endsWith("/")?o.slice(0,-1):o}${e}`,y=(o,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===""?o:`${o}?${s}`},os=[he],l=o=>o??"",ie=(o,e)=>{const t=o.error,s=typeof t?.code=="string"?t.code:void 0,r=typeof t?.message=="string"?t.message:void 0;return{code:s,messageText:(typeof o.message=="string"?o.message:void 0)??r??e}},cs=o=>{const{code:e,messageText:t}=ie(o,"stream error");return e===void 0?new Error(t):new m(e,t)},J=o=>{const{code:e,messageText:t}=ie(o,"subscription error");return{message:t,...e===void 0?{}:{code:e}}};function B(o){if(o!==void 0)return e=>{o(e)}}const R=(o,e)=>{for(const t of o)try{t(e)}catch{}},hs=new TextDecoder,ds=o=>{if(typeof o=="string")return o;if(o instanceof ArrayBuffer)return hs.decode(o)},b=(o,e)=>{if(!o.socket||o.wsState!=="open")return!1;try{return o.socket.send(JSON.stringify(e)),!0}catch{return!1}},F=o=>{const e=new Error(o.message??"request failed");return e.code=o.code,o.data!==void 0&&(e.data=T(o.data)),o.hint!==void 0&&(e.hint=o.hint),o.docsUrl!==void 0&&(e.docsUrl=o.docsUrl),e},X=(o,e)=>{const t=F(o),s=Ie(t,e);return s!==void 0&&(t.data=s),t},k=(o,e)=>{try{return K(o)}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)}},Q=o=>"args"in o?{...o,args:T(o.args)}:o,us=(o,e)=>{const t=Array.from({length:e});for(const s of o){if(typeof s.id!="number"||s.id<0||s.id>=e)continue;const r=s.body;t[s.id]=r&&"error"in r&&r.error?{error:F(r.error),ok:!1}:{ok:!0,value:T(r?.result)}}return t.map(s=>s??{error:new Error("batch call returned no result"),ok:!1})},ls=Promise.resolve();class ne{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;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 v;tabCoordinator;leaderStatus;leaderWasEverConnected=!1;connections=new Map;defaultConnectionContext;connectionContexts=new Map;connectionContextHolders=new Map;authToken=null;authSubject=void 0;subjectToken=null;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(Y(e.url),Le),this.wsToken=e.wsToken;const t=e.authBasePath??ns;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??de(),this.reconnectOptions=e.reconnect,this.heartbeatIntervalMs=e.heartbeatIntervalMs??xe,this.connectTimeoutMs=e.connectTimeoutMs??De,this.defaultConnectionContext=e.connectionContext,this.persistence=Te(e.persistence,e.outbox===void 0),this.persistenceVersion=e.persistenceVersion,this.queryCache=ve(e.queryCache),this.onPersistenceError=e.offlineQueue?.onPersistenceError,this.clientQueryStore=new ue,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=ls),this.offlineQueue=new ye(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-${W()}`,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();if(a!==r&&(!s&&i?(this.restampQueuedIdentity(r,a),this.restampWatermarks(r,a),this.restampConnectionIdentity(r,a),this.reseedFromHydratedCache()):this.rejectQueuedForIdentityChange(r),this.tabCoordinator)){const c=this.tabCoordinator.isLeader();this.tabCoordinator.stop(),this.tabCoordinator=this.createTabCoordinator(),this.tabCoordinator.start(),c&&this.tabCoordinator.promoteImmediately()}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()}replayIdentityVerdict(e){if(this.subjectAwaitingReconfirm())return"unknown";const t=this.identityFingerprint();return 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 c=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&&(G(this.clientWatermarks,qe),d=new Map,this.clientWatermarks.set(n??"",d)),d.set(i,a)}return{applied:a===void 0||a===r,result:c}}onAuthTokenChange(e){return this.authTokenListeners.add(e)}async getCurrentUser(){if(this.closed||!this.fetchImpl)return null;const e={},t=this.authToken;this.authToken&&(e.authorization=`Bearer ${this.authToken}`);const s=await this.fetchImpl(C(this.url,`${this.authBasePath}${as}`),{credentials:"include",headers:e,method:"GET"});if(!s.ok)return null;const i=(await s.json())?.user??null;return this.adoptResolvedSubject(t,i),i}setWsToken(e){if(this.wsToken!==e){this.wsToken=e;for(const t of this.connections.values())if(t.socket)try{t.socket.close()}catch{}}}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 c=a.indexOf(r);c!==-1&&a.splice(c,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 c=this.getConnection(s.shardKey);c&&b(c,{topic:e,type:"whisper_subscribe"})}return()=>{const c=this.whisperHandlers.get(r),h=c?.get(e);if(!h?.delete(t)||h.size>0)return;c?.delete(e),c?.size===0&&this.whisperHandlers.delete(r);const d=this.getConnection(s.shardKey);d&&b(d,{topic:e,type:"whisper_unsubscribe"})}}whisper(e,t,s={}){this.assertLeaderOwnedSurface("whisper"),this.ensureSocket(s.shardKey);const r=this.getConnection(s.shardKey);r&&b(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 ge(this,e,t,s)}whenReady(){return this.readyPromise}get isReady(){return this.readyResolved}peekHydratedQuery(e,t,s){if(!this.readyResolved)return;const r=q(t),i=E(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=v.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,j),{body:JSON.stringify({calls:e.map((i,n)=>({args:k(i.args??{},`args for batch call '${i.fn.__lunoraRef}'`),functionPath:i.fn.__lunoraRef,id:n,shardKey:i.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()})`)}if(!t.ok||r.error&&!r.results)throw r.error?F(r.error):new m("INTERNAL",`LunoraClient: batch request failed (status ${t.status.toString()})`);for(const i of r.results??[]){const n=i.body?.commitCursor;typeof i.id=="number"&&typeof n=="number"&&this.recordShardCursor(e[i.id]?.shardKey,n)}return us(r.results??[],e.length)}async mutation(e,t,s={}){this.assertOpen();const r=t,i=s.mutationId??W(),{confirms:n,rollbacks:a}=this.applyOptimisticUpdates(e.__lunoraRef,r,s.shardKey,s.optimistic);s.optimisticUpdate&&this.applyOptimisticUpdate(s.optimisticUpdate,t,s.shardKey,a,n);const c=this.offlineFlushes.get(l(s.shardKey));c!==void 0&&await c;const{hasSocket:h,wasEverConnected:d,wsState:u}=this.connectionGateState(s.shardKey),{queueBeforeFirstConnect:f}=this.offlineQueue,S=d||f,p=this.WebSocketImpl!==void 0&&S;if(u!=="open"&&!h&&p||u==="connecting"&&S)return this.enqueueOfflineMutation(e,r,s.shardKey,i,a,n,s.precondition);try{let w;const ae=await this.rpc(e.__lunoraRef,r,s.shardKey,{captureBookmark:!0,mutationId:i,onCommitCursor:H=>{w=H}});for(const H of n)H(w);return ae}catch(w){throw O(a),w}}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??(h=>({rows:h})),n=t.length;let a=0,c=0;for(let h=0;h<n;h+=r){const d=t.slice(h,h+r),u=c;await this.mutation(e,i(d),{...s.importId===void 0?{}:{mutationId:`${s.importId}:${String(u)}`},shardKey:s.shardKey}),c+=1,a+=d.length,s.onProgress?.({done:a,total:n})}return{chunks:c,imported:a}}async shardTraffic(e){this.assertOpen();const t=await this.adminFetch(We,"POST",{table:e});return{failed:t.failed??0,ok:t.ok??0,shards:t.shards??[]}}async listScheduledJobs(){return this.assertOpen(),((await this.adminFetch($e,"GET")).records??[]).map(t=>Q(t))}async schedulerStatus(){this.assertOpen();const e=await this.adminFetch(Ge,"GET");return{backlog:e.backlog??0,inFlight:e.inFlight??0,pools:e.pools??[]}}async cancelScheduledJob(e){return this.assertOpen(),{cancelled:(await this.adminFetch(Ve,"POST",{id:e})).cancelled===!0}}async listDeadJobs(){return this.assertOpen(),(await Ce(async t=>await this.adminFetch(t===void 0?z:`${z}?cursor=${encodeURIComponent(t)}`,"GET"))).map(t=>Q(t))}async retryDeadJob(e){return this.assertOpen(),{retried:(await this.adminFetch(ze,"POST",{id:e})).retried===!0}}async removeDeadJob(e){return this.assertOpen(),{removed:(await this.adminFetch(Ye,"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(`${Je}?${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(`${Xe}?${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(Ze,"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(Y(this.url),je),s=$(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()))},c=f=>{if(n||this.WebSocketImpl===void 0)return;const S=f===void 0?t:`${t}?token=${encodeURIComponent(f)}`;this.openManagedSocket(r,S,this.connectTimeoutMs,{onClose:()=>{a()},onMessage:p=>{let g;try{g=JSON.parse(typeof p.data=="string"?p.data:"")}catch{return}g.type==="jobs"&&Array.isArray(g.records)&&(s.reset(),e(g.records.map(w=>Q(w))))}})},h=async f=>{let S;try{S=await f()}catch{a();return}c(S)},d=()=>{if(n||this.WebSocketImpl===void 0)return;const{wsToken:f}=this;if(typeof f=="function"){h(f).catch(()=>{});return}c(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(st,"GET")).functions??[]}async getCronJobs(){return this.assertOpen(),(await this.adminFetch(rt,"GET")).jobs??[]}async runCronJob(e){this.assertOpen();const t=await this.adminFetch(it,"POST",{name:e});return{name:t.name??e,ran:t.ran===!0}}async fetchOpenApi(){return this.assertOpen(),await this.adminFetch(nt,"GET")}async fetchOpenRpc(){return this.assertOpen(),await this.adminFetch(at,"GET")}async listStorageObjects(e={}){this.assertOpen();const t=y(x,{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=`${x}?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(tt,"GET")).buckets??[]}async uploadStorageObject(e){this.assertOpen();const t=`${x}?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=`${et}?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(ot,"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(K(e.filters))),T(await this.adminFetch(`${ct}?${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(K(e.filters))),T(await this.adminFetch(`${ht}?${t.toString()}`,"GET"))}async listVectorIndexes(){return this.assertOpen(),(await this.adminFetch(dt,"GET")).indexes??[]}async queryVectorIndex(e){return this.assertOpen(),(await this.adminFetch(ut,"POST",e)).matches??[]}async queryLogArchive(e={}){this.assertOpen();const t=await this.adminFetch(lt,"POST",e);return{nextCursor:t.nextCursor,rows:t.rows??[]}}async listKvNamespaces(){return this.assertOpen(),(await this.adminFetch(ft,"GET")).namespaces??[]}async listKvKeys(e){this.assertOpen();const t=y(mt,{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=y(D,{key:e.key,namespace:e.namespace});return await this.adminFetch(t,"GET")}async putKvValue(e){this.assertOpen(),await this.adminFetch(D,"PUT",e)}async deleteKvKey(e){this.assertOpen();const t=y(D,{key:e.key,namespace:e.namespace});await this.adminFetch(t,"DELETE")}async listAuthUsers(e={}){this.assertOpen();const t=y(pt,{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(St,"POST",e)}async setAuthUserRole(e){return await this.adminFetch(bt,"POST",e)}async banAuthUser(e){return await this.adminFetch(Tt,"POST",e)}async unbanAuthUser(e){return await this.adminFetch(vt,"POST",e)}async setAuthUserPassword(e){await this.adminFetch(gt,"POST",e)}async removeAuthUser(e){await this.adminFetch(kt,"POST",e)}async impersonateAuthUser(e){return await this.adminFetch(Ct,"POST",e)}async revokeAuthSession(e){await this.adminFetch(wt,"POST",e)}async revokeAuthUserSessions(e){await this.adminFetch(Et,"POST",e)}async getAuthCapabilities(){return await this.adminFetch(_t,"GET")}async updateAuthUser(e){return await this.adminFetch(At,"POST",e)}async listAuthAccounts(e){return await this.adminFetch(y(It,{userId:e.userId}),"GET")}async unlinkAuthAccount(e){await this.adminFetch(Ot,"POST",e)}async listAuthPasskeys(e){return await this.adminFetch(y(Rt,{userId:e.userId}),"GET")}async deleteAuthPasskey(e){await this.adminFetch(Pt,"POST",e)}async disableAuthTwoFactor(e){await this.adminFetch(Mt,"POST",e)}async listAuthOrganizations(e={}){return await this.adminFetch(y(Ft,{limit:e.limit,offset:e.offset}),"GET")}async listAuthOrgMembers(e){const t=y(Ht,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async listAuthOrgInvitations(e){const t=y(Lt,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async listAuthSignUpInvitations(e={}){const t=y(Dt,{limit:e.limit,offset:e.offset});return await this.adminFetch(t,"GET")}async createAuthSignUpInvitation(e){return await this.adminFetch(Bt,"POST",e)}async revokeAuthSignUpInvitation(e){await this.adminFetch(Qt,"POST",e)}async removeAuthOrgMember(e){await this.adminFetch(Ut,"POST",e)}async cancelAuthOrgInvitation(e){await this.adminFetch(Nt,"POST",e)}async getAuthConfig(){return await this.adminFetch(xt,"GET")}async createAuthOrganization(e){return await this.adminFetch(Kt,"POST",e)}async updateAuthOrganization(e){return await this.adminFetch(qt,"POST",e)}async deleteAuthOrganization(e){await this.adminFetch(Wt,"POST",e)}async addAuthOrgMember(e){return await this.adminFetch($t,"POST",e)}async inviteAuthOrgMember(e){return await this.adminFetch(Gt,"POST",e)}async setAuthOrgMemberRole(e){return await this.adminFetch(jt,"POST",e)}async listAuthOrgTeams(e){const t=y(Vt,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async createAuthOrgTeam(e){return await this.adminFetch(zt,"POST",e)}async updateAuthOrgTeam(e){return await this.adminFetch(Yt,"POST",e)}async removeAuthOrgTeam(e){await this.adminFetch(Jt,"POST",e)}async listAuthOrgTeamMembers(e){const t=y(Xt,{limit:e.limit,offset:e.offset,teamId:e.teamId});return await this.adminFetch(t,"GET")}async addAuthOrgTeamMember(e){return await this.adminFetch(Zt,"POST",e)}async removeAuthOrgTeamMember(e){await this.adminFetch(es,"POST",e)}async listAuthOrgRoles(e){const t=y(ts,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async createAuthOrgRole(e){return await this.adminFetch(ss,"POST",e)}async updateAuthOrgRole(e){return await this.adminFetch(rs,"POST",e)}async deleteAuthOrgRole(e){await this.adminFetch(is,"POST",e)}async listAuthSessions(e={}){this.assertOpen();const t=y(yt,{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=v.key(e.__lunoraRef,i,r.shardKey);let a=this.subscriptions.get(n);const c=B(s),h=B(r.onError),d=B(r.onCheckpoint);if(!a){this.nextSubId+=1;const f=`sub_${this.nextSubId.toString()}`,S=q(i),p=this.takeHydratedCache(e.__lunoraRef,S,r.shardKey);a={acked:!1,args:i,argsKey:S,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(c),h&&a.errorCallbacks.add(h),d&&a.checkpointCallbacks.add(d),a.lastValue!==void 0)try{c(a.lastValue)}catch{}this.ensureSocket(r.shardKey),this.sendSubscribeIfOpen(a);const u=a;return()=>{u.callbacks.delete(c),h&&u.errorCallbacks.delete(h),d&&u.checkpointCallbacks.delete(d),u.callbacks.size===0&&(this.sendOrQueueUnsubscribe(u.shardKey,u.id,"unsubscribe"),this.returnCacheSeed(v.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:c}=ke({maxBuffer:s.maxBuffer,onCancel:()=>{this.cancelStream(r,i)}});this.ensureSocket(i);const h=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=h?.wsState==="open"&&b(h,d);if(u.started=f,!f&&h===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")),c;if(!f){for(h.pendingStreams=h.pendingStreams??[];h.pendingStreams.length>=Ke;){const p=h.pendingStreams.shift()?.id,g=p?this.streams.get(p):void 0;g&&(g.handle.fail(new m("STREAM_QUEUE_OVERFLOW","stream-start frame evicted while socket was unreachable")),this.streams.delete(p))}h.pendingStreams.push(d)}return c}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 fe(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){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.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 le({channelName:e,onBecomeLeader:()=>{for(const t of this.subscriptions.all())this.ensureSocket(t.shardKey),this.sendSubscribeIfOpen(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),L(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&&R(i.errorCallbacks,s)},onSubscriptionSettled:(t,s,r,i,n,a)=>{if(a!==void 0&&a!==this.identityFingerprint())return;const c=this.subscriptions.get(t);if(c){this.ackAndAdvanceCursor(c,s,r),i!==void 0&&n===this.clientId&&(c.lastMutationId=Math.max(c.lastMutationId??0,i));for(const h of c.checkpointCallbacks)h({checkpoint:c.serverCursor,mutationId:c.lastMutationId})}}})}async enqueueOfflineMutation(e,t,s,r,i,n,a){const c=this.identityFingerprint();if(this.outbox){this.outboxMutationCounter+=1;const h=this.outboxMutationCounter;try{await this.outbox.enqueue({args:t,clientId:this.clientId,functionPath:e.__lunoraRef,idempotencyKey:`${this.clientId}:${String(h)}`,identity:c,mutationId:h,...i.length>0&&{onRejected:()=>{O(i)}},shardKey:s})}catch(d){throw O(i),d instanceof Error?d:new Error(String(d))}for(const d of n)d(void 0);return}return new Promise((h,d)=>{const u={args:t,functionPath:e.__lunoraRef,liveAwaiter:!0,id:r,clientId:this.clientId,identity:c,precondition:a,onCommit:f=>{for(const S of n)S(f)},reject:f=>{this.queuedIdentities.delete(r),O(i),d(f instanceof Error?f:new Error(String(f)))},resolve:h,shardKey:s};this.offlineQueue.enqueue(u),this.queuedOfflineShardKeys.add(s),u.id!==void 0&&this.queuedIdentities.set(u.id,c)})}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(E(s.fn.__lunoraRef,s.argsKey,s.shardKey),s);for(const{key:s,...r}of e){if(Se(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(E(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=E(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=E(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=E(e.fn.__lunoraRef,e.argsKey,e.shardKey),r=this.getConnection(e.shardKey)?.identity,i=r===void 0?this.identityFingerprint():r;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(()=>{})},Be)}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.wsState==="connecting")?"connecting":"offline"}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=v.key(e,t,s),c=this.subscriptions.get(a);if(c){const h=me(c,r);h&&(i.push(h.confirm),n.push(h.rollback))}return{confirms:i,rollbacks:n}}applyOptimisticUpdate(e,t,s,r,i){const{confirms:n,rollbacks:a,store:c}=pe(this.subscriptions,s);try{e(c,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&&!b(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:[],reconnect:$(this.reconnectOptions),reconnectTimer:void 0,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.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 P("LunoraClient: no `fetch` implementation available");const i=this.rpcRequestHeaders(r,s),n=await this.fetchImpl(C(this.url,He),{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 M(n.status,n.statusText,n.headers.get("retry-after"))}if("error"in a)throw X(a.error,n.headers.get("retry-after"));if(!n.ok)throw M(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),T(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 c=await this.fetchImpl(C(this.url,e),{body:a,headers:i,method:t});let h;try{h=await c.json()}catch{const d=c.statusText?` ${c.statusText}`:"";throw new m("INTERNAL",`LunoraClient: response was not JSON (status ${c.status.toString()}${d})`)}if(typeof h=="object"&&h!==null&&"error"in h){const d=h.error,u=new Error(d.message??"admin request failed");throw u.code=d.code,u}if(!c.ok){const d=c.statusText?` ${c.statusText}`:"";throw new m("INTERNAL",`LunoraClient: admin request failed (status ${c.status.toString()}${d})`)}return h}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));b(e,{caps:os,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)},c=h=>{a(),r.onClose(h)};s>0&&(e.connectTimer=setTimeout(()=>{if(e.connectTimer=void 0,e.socket===n){try{n.close()}catch{}c()}},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(h){console.error("[lunora] connection open handler threw",h)}this.startHeartbeat(e,c)}}),n.addEventListener("message",h=>{if(e.socket===n){e.lastFrameAt=Date.now();try{r.onMessage(h)}catch(d){console.error("[lunora] server frame handler threw",d)}}}),n.addEventListener("close",h=>{e.socket===n&&c(h)}),n.addEventListener("error",()=>{e.socket===n&&c()})}openSocket(e,t,s){this.WebSocketImpl!==void 0&&(e.identity=this.identityFingerprint(),this.openManagedSocket(e,this.wsUrlFor(t,s),this.connectTimeoutMs,{onClose:r=>{r?.code===4001&&this.notifyTokenExpired(),this.handleDisconnect(e)},onMessage:r=>{this.handleServerMessage(r.data,t)},onOpen:()=>{e.wsState="open",e.wasEverConnected=!0,clearTimeout(e.stableTimer),e.stableTimer=setTimeout(()=>{e.wsState==="open"&&e.reconnect.reset()},Qe),this.emitConnectionStatus(),this.sendConnectEnvelope(e),this.markShardPendingAck(t);for(const i of this.subscriptions.all())l(i.shardKey)===l(t)&&this.sendSubscribeIfOpen(i);if(this.resendShapeSubscriptions(t),e.pendingUnsubscribes.length>0){const i=e.pendingUnsubscribes;e.pendingUnsubscribes=[];for(const{id:n,type:a}of i)b(e,{id:n,type:a})}this.flushPendingStreams(e);const r=this.whisperHandlers.get(l(t));if(r)for(const i of r.keys())b(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=b(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),!b(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;this.stopHeartbeat(e),this.clearConnectionTimers(e),e.socket=void 0,e.wsState="idle",this.emitConnectionStatus(),this.markShardPendingAck(e.shardKey);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(Ne)}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)}sendSubscribeIfOpen(e){const t=this.getConnection(e.shardKey);if(t?.wsState!=="open"||e.acked)return;const s=e.fn.__lunoraTable??e.fn.__lunoraRef,r=e.serverCursor!==void 0&&e.serverBase!==void 0;b(t,{id:e.id,query:{args:e.wireArgs,functionPath:e.fn.__lunoraRef,table:s,...r?{sinceSeq:e.serverCursor}:{},...r&&e.serverEpoch!==void 0?{sinceEpoch:e.serverEpoch}:{}},type:"subscribe"})}sendShapeSubscribeIfOpen(e){const t=this.getConnection(e.shardKey);t?.wsState==="open"&&b(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=ds(e);if(s===void 0)return;let r;try{r=JSON.parse(s)}catch{return}switch(r.type!=="error"&&this.getConnection(t)?.reconnect.reset(),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:c}=r,h=this.streams.get(a);h&&typeof c=="number"&&(h.lastSeq=c,typeof n=="number"&&(h.generation=n),h.durable=!0),h?.handle.push(T(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(cs(e)),this.streams.delete(s);return}const i=s===void 0?void 0:this.subscriptions.getById(s);if(i){const a=J(e),c=this.identityFingerprint(),h=v.keyOf(i);R(i.errorCallbacks,a),this.tabCoordinator?.isLeader()&&this.tabCoordinator.broadcastSubscriptionError(h,a,c);return}const n=s===void 0?void 0:this.shapeSubscriptions.get(s);n&&R(n.errorCallbacks,J(e))}pokeBufferKey(e,t){return`${l(e)}\0${t}`}handlePokeStart(e,t){G(this.pokeBuffers,ne.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:T(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,c=n!==void 0&&e.serverCursor!==void 0&&e.serverCursor!==n;if(!i&&(a||c)){e.rows.clear(),e.serverCursor=void 0,e.serverEpoch=void 0,this.emitShapeRows(e),this.sendShapeSubscribeIfOpen(e);return}i&&e.rows.clear(),Ue(e.rows,r),s.checkpoint!==void 0&&(e.serverCursor=s.checkpoint),s.epoch!==void 0&&(e.serverEpoch=s.epoch);const h=t.lastMutationId.get(e.id);h!==void 0&&(e.lastMutationId=h),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){R(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===V){this.resnapshotSubscription(s);return}if(s.serverBase=r,this.dropCacheSeed(v.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),L(s,s.serverCursor),_(s,A(r,s.optimisticLayers)),this.tabCoordinator?.isLeader()){const i=v.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=v.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),L(e,e.serverCursor)&&_(e,A(e.serverBase,e.optimisticLayers)))}resolveDataPayload(e,t){if("data"in e&&e.data!==void 0)return T(e.data);const s=T(e.delta);return oe(s)?t.serverBase===void 0?s:ce(t.serverBase,s)??V:s}dispatchWhisper(e,t){const s=this.whisperHandlers.get(l(t))?.get(e.topic);if(!s)return;const r=T(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,R(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.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}adoptResolvedSubject(e,t){this.closed||t===null||this.authToken!==e||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,c]of r)n.set(a,c)}clearQueryCacheForIdentityChange(){this.revokeCacheSeededValues(),this.cacheFlushTimer!==void 0&&(clearTimeout(this.cacheFlushTimer),this.cacheFlushTimer=void 0),this.pendingCacheWrites.clear(),this.hydratedQueryCache.clear(),this.queryCache?.clear().catch(()=>{})}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 h of t){this.unpersist(h.id),this.queuedIdentities.delete(h.id??"");const d=new Error("offline mutation skipped: precondition failed before replay");d.code="OFFLINE_PRECONDITION_FAILED",this.emitItemSettled(h,"rejected",d)}const s=l(e),r=this.offlineQueue.drain(h=>l(h.shardKey)===s);if(r.length===0)return;const i=[],n=[];for(const h of r){const d=this.replayGateVerdict(h);d==="send"?i.push(h):d==="hold"&&n.push(h)}if(this.offlineQueue.requeue(n),n.length>0&&this.subjectAwaitingReconfirm()&&this.getCurrentUser().catch(()=>{}),i.length===0)return;const a=this.encodableOrSettleTerminal(i);if(a.length===0)return;if(a.length===1){await this.replaySequential(a,e),this.scheduleRateLimitedRetry(e);return}const c=[];for(let h=0;h<a.length;h+=U){const d=a.slice(h,h+U),u=await this.replayBatched(d,e);if(c.push(...u.requeue),u.stop){c.push(...a.slice(h+U));break}}c.length>0&&this.offlineQueue.requeue(c),this.scheduleRateLimitedRetry(e)}noteReplayRetryDelay(e,t){const s=l(e),r=this.replayRetryState.get(s),i=(r?.attempts??0)+1,n=Pe(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(we(e)){const t=this.hashToken(this.authToken??"");return this.authRefusalNotifiedFor!==t&&(this.authRefusalNotifiedFor=t,this.notifyTokenExpired()),!0}return Ee(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,{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((c,h)=>({args:k(c.args,`args for '${c.functionPath}'`),functionPath:c.functionPath,id:h,clientId:c.clientId??this.clientId,mutationId:c.id,shardKey:c.shardKey}))});if(e.length>1&&Fe(s)>Me)return await this.replayBatchedHalves(e,t);let r;try{r=await this.fetchImpl(C(this.url,j),{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,M(r.status,r.statusText,a),t)}if(!n.results){const c=n.error===void 0?M(r.status,r.statusText,a):X(n.error,a);return this.settleWholeBatchError(e,c,t)}return{requeue:this.settleReplayBatchSlots(e,n.results,t),stop:!1}}settleWholeBatchError(e,t,s){if(t instanceof P||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 c=r.get(n);if(c===void 0)i.push(a);else if("error"in c){const h=F(c.error);this.shouldRequeueReplayFailure(h)?(this.noteReplayRetryDelay(s,h),i.push(a)):this.settleReplayTerminal(a,h)}else this.settleReplaySuccess(a,T(c.result),c.commitCursor)}return i}}export{ne as LunoraClient};
@@ -0,0 +1 @@
1
+ import{c as t}from"./local-store-BjenEm3t.mjs";import"./SubscriptionRegistry-CS-AFUI9.mjs";export{t as createLocalStore};
@@ -1 +1 @@
1
- import{LunoraClient as r}from"./LunoraClient-DArMFG67.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};
1
+ import{LunoraClient as r}from"./LunoraClient-C5AvZOeg.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 @@
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};
@@ -228,6 +228,18 @@ interface OutboxMutation {
228
228
  identity: string | null;
229
229
  /** Monotonic per-client mutation id, backing the server `__client_watermark`. */
230
230
  mutationId: number;
231
+ /**
232
+ * Roll this write's optimistic patch back. The sink's owner invokes it when
233
+ * the replay reaches a PERMANENT verdict (a coded rejection, an identity
234
+ * drop) — never on a transient failure it will retry, and never on success.
235
+ *
236
+ * Without it a rejected replay leaves its predicted value on screen until an
237
+ * unrelated frame or a reload: the client drops the layer when it hands the
238
+ * write over (it cannot cursor-confirm through this path) and has no other
239
+ * signal that the write died. Absent when the write carried no optimistic
240
+ * update, and safe to ignore — a sink that never calls it behaves as before.
241
+ */
242
+ onRejected?: () => void;
231
243
  shardKey?: string;
232
244
  }
233
245
  /**
@@ -1504,6 +1516,22 @@ interface MutationCallOptions<TCurrent = unknown, TValue = unknown, TArgs = unkn
1504
1516
  * each then gets a fresh key.
1505
1517
  */
1506
1518
  mutationId?: string;
1519
+ /**
1520
+ * Single-query shortcut: the transform is layered onto the subscription
1521
+ * registered under **this write's own** `(functionPath, args, shardKey)`, and
1522
+ * nothing else. A client cannot know which queries a write affects, so the
1523
+ * targeting rule is "same reference, same args" — which makes this the
1524
+ * shorthand for a query and a mutation that share a path (a counter, a
1525
+ * document by id), and a silent no-op for anything else.
1526
+ *
1527
+ * **The general case — a `messages:send` mutation patching a `messages:list`
1528
+ * query — is {@link MutationCallOptions.optimisticUpdate}**, whose store names
1529
+ * its targets. Reach for that whenever the mutation and the query are
1530
+ * different functions, which is nearly always.
1531
+ *
1532
+ * The transform must be pure: it re-runs on every server frame while the write
1533
+ * is pending, so derive from `current` rather than closing over a value.
1534
+ */
1507
1535
  optimistic?: (current: TCurrent | undefined) => TValue;
1508
1536
  /**
1509
1537
  * Convex-parity multi-query optimistic update. Receives an
@@ -1969,9 +1997,16 @@ declare class LunoraClient {
1969
1997
  * Fetch the currently authenticated user from better-auth's `get-session`
1970
1998
  * endpoint, returning the `user` record or `null` when signed out. Sends
1971
1999
  * the stored bearer token (if any) and `credentials: "include"` so a
1972
- * cookie-session is also honoured. A network/parse failure or a non-OK
1973
- * response resolves to `null` rather than throwing — callers treat "couldn't
1974
- * resolve identity" as "signed out".
2000
+ * cookie-session is also honoured.
2001
+ *
2002
+ * `null` means the **server answered** that there is no session — an empty
2003
+ * body, no `user` field, or a non-OK status such as 401. A network or parse
2004
+ * failure **rejects** instead, because "the endpoint was unreachable" is not
2005
+ * the same answer as "you are signed out": collapsing the two made an
2006
+ * offline reload with a valid stored token read as a sign-out in every
2007
+ * adapter's auth gate. Callers that cannot act on the difference can still
2008
+ * `.catch(() => null)`; `@lunora/client/auth`'s identity store maps the
2009
+ * rejection to the `"unreachable"` status instead.
1975
2010
  *
1976
2011
  * Framework-agnostic: pair it with {@link onAuthTokenChange} to refetch when
1977
2012
  * the token changes (that's what `@lunora/react`'s `useAuth` does).
@@ -3206,6 +3241,26 @@ declare class LunoraClient {
3206
3241
  * a later `subscribe()` of the same key to replay a stale session over.
3207
3242
  */
3208
3243
  private dropCacheSeed;
3244
+ /**
3245
+ * Hand a cache-seeded entry back to {@link hydratedQueryCache} when its last
3246
+ * subscriber detaches, so the NEXT `subscribe()` of the same key can seed
3247
+ * from it again.
3248
+ *
3249
+ * Without this the hydrated cache was one-shot per key: {@link takeHydratedCache}
3250
+ * consumes the entry, the final unsubscribe drops the state that held its
3251
+ * value, and nothing re-seeds. Navigating away from a route and back while
3252
+ * offline therefore rendered `undefined` for the rest of the offline
3253
+ * session even though the durable store still held the rows. React hid it
3254
+ * behind TanStack's `gcTime`; every other adapter showed it immediately.
3255
+ *
3256
+ * Only a seed still listed in {@link cacheSeededQueries} moves — a server
3257
+ * frame calls {@link dropCacheSeed}, which clears both maps, so an entry
3258
+ * that is still here has not been superseded and is the freshest value this
3259
+ * client has for the key. That is the same map-to-map move
3260
+ * {@link revokeCacheSeededValues} makes, and it keeps the two maps disjoint:
3261
+ * an entry is either on display or waiting, never both.
3262
+ */
3263
+ private returnCacheSeed;
3209
3264
  /**
3210
3265
  * Take every value the durable read cache is currently displaying back off
3211
3266
  * screen, and return its entry to {@link hydratedQueryCache} so the identity
@@ -3571,6 +3626,18 @@ declare class LunoraClient {
3571
3626
  * `/get-session` round trip later — which offline never completes at all.
3572
3627
  * Without it the durable read cache never seeded for a bearer-token app.
3573
3628
  *
3629
+ * All three want a credential this client actually HOLDS, which is why a
3630
+ * **cookie session seeds nothing on an offline cold start** — a documented
3631
+ * limitation, not a gap. The cookie is `HttpOnly`: the client can neither
3632
+ * read it nor prove it still has it, and offline the `/get-session` that
3633
+ * would resolve the subject never answers, so such entries (stamped
3634
+ * `subj:<id>`, no credential) have nothing to match. Seeding them on the
3635
+ * remembered subject LABEL would hand the rows to whoever opens the browser
3636
+ * profile with nothing evidencing they are that subject, and revoking on a
3637
+ * later mismatch does not repair it: that check can only run once
3638
+ * connectivity returns, which is exactly the state where the offline seed
3639
+ * was not needed. Offline-first reads require a bearer token.
3640
+ *
3574
3641
  * Case 1 is suspended while the subject awaits re-confirmation
3575
3642
  * ({@link subjectAwaitingReconfirm}): the fingerprint then labels a
3576
3643
  * credential nothing has checked it against, which is precisely the
@@ -3659,7 +3726,7 @@ declare class LunoraClient {
3659
3726
  * instead of the flush guard discarding them as a mismatch.
3660
3727
  *
3661
3728
  * That map alone was not enough: it is consumed and DELETED on the first
3662
- * flush attempt (`passesReplayIdentityGate`), while the queue entry and its
3729
+ * flush attempt (`replayIdentityVerdict`), while the queue entry and its
3663
3730
  * persisted record keep the original stamp. So a reload, or a requeue after a
3664
3731
  * transient failure, fell back to the old token hash — and once the token had
3665
3732
  * been refreshed, `isSameCredentialUnderTokenHash` no longer recognised it
@@ -3695,11 +3762,11 @@ declare class LunoraClient {
3695
3762
  * (see `queuedOfflineShardKeys`). Used on a FOLLOWER tab when the
3696
3763
  * mirrored leader status transitions to `"connected"` — a follower has no
3697
3764
  * per-shard `ShardConnection` reconnect event to hang the usual
3698
- * single-shard `flushOfflineQueue(shardKey)` call off of (see the
3699
- * `handleConnect` call site), so this walks every shard that might have
3700
- * something queued instead. Flushing an already-empty shard is a cheap
3701
- * no-op (`flushOfflineQueue` returns immediately once `drain` yields
3702
- * nothing), so over-inclusion here is harmless.
3765
+ * single-shard `flushOfflineQueue(shardKey)` call off of (see the `onOpen`
3766
+ * callback that calls `flushOfflineQueue(shardKey)`), so this walks every
3767
+ * shard that might have something queued instead. Flushing an already-empty
3768
+ * shard is a cheap no-op (`flushOfflineQueue` returns immediately once
3769
+ * `drain` yields nothing), so over-inclusion here is harmless.
3703
3770
  */
3704
3771
  private flushAllOfflineQueues;
3705
3772
  /**
@@ -228,6 +228,18 @@ interface OutboxMutation {
228
228
  identity: string | null;
229
229
  /** Monotonic per-client mutation id, backing the server `__client_watermark`. */
230
230
  mutationId: number;
231
+ /**
232
+ * Roll this write's optimistic patch back. The sink's owner invokes it when
233
+ * the replay reaches a PERMANENT verdict (a coded rejection, an identity
234
+ * drop) — never on a transient failure it will retry, and never on success.
235
+ *
236
+ * Without it a rejected replay leaves its predicted value on screen until an
237
+ * unrelated frame or a reload: the client drops the layer when it hands the
238
+ * write over (it cannot cursor-confirm through this path) and has no other
239
+ * signal that the write died. Absent when the write carried no optimistic
240
+ * update, and safe to ignore — a sink that never calls it behaves as before.
241
+ */
242
+ onRejected?: () => void;
231
243
  shardKey?: string;
232
244
  }
233
245
  /**
@@ -1504,6 +1516,22 @@ interface MutationCallOptions<TCurrent = unknown, TValue = unknown, TArgs = unkn
1504
1516
  * each then gets a fresh key.
1505
1517
  */
1506
1518
  mutationId?: string;
1519
+ /**
1520
+ * Single-query shortcut: the transform is layered onto the subscription
1521
+ * registered under **this write's own** `(functionPath, args, shardKey)`, and
1522
+ * nothing else. A client cannot know which queries a write affects, so the
1523
+ * targeting rule is "same reference, same args" — which makes this the
1524
+ * shorthand for a query and a mutation that share a path (a counter, a
1525
+ * document by id), and a silent no-op for anything else.
1526
+ *
1527
+ * **The general case — a `messages:send` mutation patching a `messages:list`
1528
+ * query — is {@link MutationCallOptions.optimisticUpdate}**, whose store names
1529
+ * its targets. Reach for that whenever the mutation and the query are
1530
+ * different functions, which is nearly always.
1531
+ *
1532
+ * The transform must be pure: it re-runs on every server frame while the write
1533
+ * is pending, so derive from `current` rather than closing over a value.
1534
+ */
1507
1535
  optimistic?: (current: TCurrent | undefined) => TValue;
1508
1536
  /**
1509
1537
  * Convex-parity multi-query optimistic update. Receives an
@@ -1969,9 +1997,16 @@ declare class LunoraClient {
1969
1997
  * Fetch the currently authenticated user from better-auth's `get-session`
1970
1998
  * endpoint, returning the `user` record or `null` when signed out. Sends
1971
1999
  * the stored bearer token (if any) and `credentials: "include"` so a
1972
- * cookie-session is also honoured. A network/parse failure or a non-OK
1973
- * response resolves to `null` rather than throwing — callers treat "couldn't
1974
- * resolve identity" as "signed out".
2000
+ * cookie-session is also honoured.
2001
+ *
2002
+ * `null` means the **server answered** that there is no session — an empty
2003
+ * body, no `user` field, or a non-OK status such as 401. A network or parse
2004
+ * failure **rejects** instead, because "the endpoint was unreachable" is not
2005
+ * the same answer as "you are signed out": collapsing the two made an
2006
+ * offline reload with a valid stored token read as a sign-out in every
2007
+ * adapter's auth gate. Callers that cannot act on the difference can still
2008
+ * `.catch(() => null)`; `@lunora/client/auth`'s identity store maps the
2009
+ * rejection to the `"unreachable"` status instead.
1975
2010
  *
1976
2011
  * Framework-agnostic: pair it with {@link onAuthTokenChange} to refetch when
1977
2012
  * the token changes (that's what `@lunora/react`'s `useAuth` does).
@@ -3206,6 +3241,26 @@ declare class LunoraClient {
3206
3241
  * a later `subscribe()` of the same key to replay a stale session over.
3207
3242
  */
3208
3243
  private dropCacheSeed;
3244
+ /**
3245
+ * Hand a cache-seeded entry back to {@link hydratedQueryCache} when its last
3246
+ * subscriber detaches, so the NEXT `subscribe()` of the same key can seed
3247
+ * from it again.
3248
+ *
3249
+ * Without this the hydrated cache was one-shot per key: {@link takeHydratedCache}
3250
+ * consumes the entry, the final unsubscribe drops the state that held its
3251
+ * value, and nothing re-seeds. Navigating away from a route and back while
3252
+ * offline therefore rendered `undefined` for the rest of the offline
3253
+ * session even though the durable store still held the rows. React hid it
3254
+ * behind TanStack's `gcTime`; every other adapter showed it immediately.
3255
+ *
3256
+ * Only a seed still listed in {@link cacheSeededQueries} moves — a server
3257
+ * frame calls {@link dropCacheSeed}, which clears both maps, so an entry
3258
+ * that is still here has not been superseded and is the freshest value this
3259
+ * client has for the key. That is the same map-to-map move
3260
+ * {@link revokeCacheSeededValues} makes, and it keeps the two maps disjoint:
3261
+ * an entry is either on display or waiting, never both.
3262
+ */
3263
+ private returnCacheSeed;
3209
3264
  /**
3210
3265
  * Take every value the durable read cache is currently displaying back off
3211
3266
  * screen, and return its entry to {@link hydratedQueryCache} so the identity
@@ -3571,6 +3626,18 @@ declare class LunoraClient {
3571
3626
  * `/get-session` round trip later — which offline never completes at all.
3572
3627
  * Without it the durable read cache never seeded for a bearer-token app.
3573
3628
  *
3629
+ * All three want a credential this client actually HOLDS, which is why a
3630
+ * **cookie session seeds nothing on an offline cold start** — a documented
3631
+ * limitation, not a gap. The cookie is `HttpOnly`: the client can neither
3632
+ * read it nor prove it still has it, and offline the `/get-session` that
3633
+ * would resolve the subject never answers, so such entries (stamped
3634
+ * `subj:<id>`, no credential) have nothing to match. Seeding them on the
3635
+ * remembered subject LABEL would hand the rows to whoever opens the browser
3636
+ * profile with nothing evidencing they are that subject, and revoking on a
3637
+ * later mismatch does not repair it: that check can only run once
3638
+ * connectivity returns, which is exactly the state where the offline seed
3639
+ * was not needed. Offline-first reads require a bearer token.
3640
+ *
3574
3641
  * Case 1 is suspended while the subject awaits re-confirmation
3575
3642
  * ({@link subjectAwaitingReconfirm}): the fingerprint then labels a
3576
3643
  * credential nothing has checked it against, which is precisely the
@@ -3659,7 +3726,7 @@ declare class LunoraClient {
3659
3726
  * instead of the flush guard discarding them as a mismatch.
3660
3727
  *
3661
3728
  * That map alone was not enough: it is consumed and DELETED on the first
3662
- * flush attempt (`passesReplayIdentityGate`), while the queue entry and its
3729
+ * flush attempt (`replayIdentityVerdict`), while the queue entry and its
3663
3730
  * persisted record keep the original stamp. So a reload, or a requeue after a
3664
3731
  * transient failure, fell back to the old token hash — and once the token had
3665
3732
  * been refreshed, `isSameCredentialUnderTokenHash` no longer recognised it
@@ -3695,11 +3762,11 @@ declare class LunoraClient {
3695
3762
  * (see `queuedOfflineShardKeys`). Used on a FOLLOWER tab when the
3696
3763
  * mirrored leader status transitions to `"connected"` — a follower has no
3697
3764
  * per-shard `ShardConnection` reconnect event to hang the usual
3698
- * single-shard `flushOfflineQueue(shardKey)` call off of (see the
3699
- * `handleConnect` call site), so this walks every shard that might have
3700
- * something queued instead. Flushing an already-empty shard is a cheap
3701
- * no-op (`flushOfflineQueue` returns immediately once `drain` yields
3702
- * nothing), so over-inclusion here is harmless.
3765
+ * single-shard `flushOfflineQueue(shardKey)` call off of (see the `onOpen`
3766
+ * callback that calls `flushOfflineQueue(shardKey)`), so this walks every
3767
+ * shard that might have something queued instead. Flushing an already-empty
3768
+ * shard is a cheap no-op (`flushOfflineQueue` returns immediately once
3769
+ * `drain` yields nothing), so over-inclusion here is harmless.
3703
3770
  */
3704
3771
  private flushAllOfflineQueues;
3705
3772
  /**
@@ -1,4 +1,4 @@
1
- import { L as LunoraClient, P as Preloaded } from "./lunora-client.d-C5tvkz8x.mjs";
1
+ import { L as LunoraClient, P as Preloaded } from "./lunora-client.d-zO8sL_gk.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-CK3FxGNH.js";
1
+ import { L as LunoraClient, P as Preloaded } from "./lunora-client.d-Do8Jp8Ow.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
@@ -1,4 +1,4 @@
1
- import { S as SubscriptionError, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-C5tvkz8x.mjs";
1
+ import { S as SubscriptionError, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-zO8sL_gk.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-C5tvkz8x.mjs";
13
+ b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-zO8sL_gk.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';
@@ -1,4 +1,4 @@
1
- import { S as SubscriptionError, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-CK3FxGNH.js";
1
+ import { S as SubscriptionError, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-Do8Jp8Ow.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-CK3FxGNH.js";
13
+ b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-Do8Jp8Ow.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';
@@ -1,4 +1,4 @@
1
- import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-C5tvkz8x.mjs";
1
+ import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-zO8sL_gk.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-CAXl1Y8Y.mjs";
23
+ a as preloadedQueryResult } from "../packem_shared/preload.d-CV5OAa01.mjs";
24
24
  import '@lunora/errors';
25
25
  import '@lunora/runtime';
26
26
  /**
@@ -1,4 +1,4 @@
1
- import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-CK3FxGNH.js";
1
+ import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-Do8Jp8Ow.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-Csjxr5HM.js";
23
+ a as preloadedQueryResult } from "../packem_shared/preload.d-fzoWay0Y.js";
24
24
  import '@lunora/errors';
25
25
  import '@lunora/runtime';
26
26
  /**
@@ -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-BrNyme3I.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};
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-MBTVrXgX.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.100",
3
+ "version": "1.0.0-alpha.102",
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.35",
73
+ "@lunora/errors": "1.0.0-alpha.36",
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 oe,a as ce,P as he}from"./delta-merge-vxvH3PvF.mjs";import{e as K,d as T}from"./wire-codec-Sw1rAu-Z.mjs";import{s as q}from"./wire-key-HsUDTlQ7.mjs";import de from"./createInMemoryBookmarkStorage-BooZhW0n.mjs";import{ClientQueryStore as ue}from"./createClientQuery-B8Nfj-7o.mjs";import{TabCoordinator as le}from"./TabCoordinator-CXD7vulJ.mjs";import{TransportError as R,getRetryAfterMs as Z}from"./CONFLICT_ERROR_CODE-BOeeP_Wl.mjs";import{httpStream as fe}from"./httpStream-CPdblK2G.mjs";import{d as L,n as _,f as A,a as me,c as pe}from"./local-store-CVfQDdXy.mjs";import{O as ye,n as W,i as Se,r as be}from"./offline-queue-xntsWiKt.mjs";import{resolvePersistenceAdapter as Te}from"./createInMemoryPersistence-Cz2W6XVj.mjs";import{resolveQueryCacheAdapter as ve,queryCacheKey as E}from"./createInMemoryQueryCache-D2uNHLfM.mjs";import{createReconnect as $}from"./createReconnect-CjTmjJDH.mjs";import ge from"./createSnapshotPrecondition-GRVKxPsh.mjs";import{createStream as ke}from"./DEFAULT_MAX_BUFFER-D3QH2iaq.mjs";import{SubscriptionRegistry as g}from"./SubscriptionRegistry-CS-AFUI9.mjs";const U=500,Ce=async o=>{const e=[];let t;for(;;){const s=await o(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}},G=(o,e)=>{if(o.size<e)return;const t=o.keys().next().value;t!==void 0&&o.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 ee=new Set(["RATE_LIMITED","SHARD_ERROR","SHARD_UNAVAILABLE","TOO_MANY_REQUESTS"]),te=new Set(["TOKEN_EXPIRED","UNAUTHENTICATED","UNAUTHORIZED"]),we=o=>te.has(o?.code??""),Ee=o=>{if(o instanceof R)return!0;const e=o?.code;return e===void 0||ee.has(e)||te.has(e)},se=6e4,_e=1e3,re=o=>{if(o===null)return;const e=Number(o);if(Number.isFinite(e))return e>0?e*1e3:void 0;const t=Date.parse(o);if(Number.isNaN(t))return;const s=t-Date.now();return s>0?s:void 0},Ae={401:"UNAUTHORIZED",403:"FORBIDDEN",404:"NOT_FOUND",413:"PAYLOAD_TOO_LARGE",429:"TOO_MANY_REQUESTS"},P=(o,e,t)=>{const s=re(t),r=s===void 0?void 0:{retryAfterMs:s},i=`LunoraClient: response carried no error envelope (status ${o.toString()}${e?` ${e}`:""})`;return o<400||o>=500||o===408?new R(i,r):new m(Ae[o]??"BAD_REQUEST",i,{data:r})},Ie=(o,e)=>{const t=re(e);if(!(t===void 0||Z(o)!==void 0))return o.data===void 0?{retryAfterMs:t}:typeof o.data=="object"&&o.data!==null&&!Array.isArray(o.data)?{...o.data,retryAfterMs:t}:void 0},Oe=(o,e=Math.random)=>{const t=Math.min(_e*2**Math.max(o-1,0),se);return Math.round(t*(.5+e()*.5))},Re=o=>o instanceof R||ee.has(o?.code??""),Pe=(o,e,t)=>{const s=Z(o);return s!==void 0&&s>0?Math.min(s,se):Re(o)?Oe(e,t):void 0},Me=983040,Fe=o=>typeof TextEncoder>"u"?o.length:new TextEncoder().encode(o).length,He="/_lunora/rpc",j="/_lunora/rpc-batch",Le="/_lunora/ws",N=o=>o===void 0||o===""?"":`&bucket=${encodeURIComponent(o)}`,M=o=>{for(let e=o.length-1;e>=0;e-=1)o[e]?.()},V=Symbol("lunora.unmergeableDelta"),Ue=(o,e)=>{for(const t of e)t.op==="delete"?o.delete(t.key):t.value!==void 0&&o.set(t.key,t.value)},Ne="lunora-ping",xe=3e4,De=1e4,Be=250,Qe=5e3,Ke=64,qe=8,We="/_lunora/admin/shard-traffic",$e="/_lunora/admin/scheduled",Ge="/_lunora/admin/scheduled/status",je="/_lunora/admin/scheduled/ws",Ve="/_lunora/admin/scheduled/cancel",z="/_lunora/admin/scheduled/dead",ze="/_lunora/admin/scheduled/dead/retry",Ye="/_lunora/admin/scheduled/dead/cancel",Je="/_lunora/admin/workflows/instances",Xe="/_lunora/admin/workflows/instance",Ze="/_lunora/admin/workflows/status",x="/_lunora/admin/storage",et="/_lunora/admin/storage/url",tt="/_lunora/admin/storage/buckets",st="/_lunora/admin/functions",rt="/_lunora/admin/cron-jobs",it="/_lunora/admin/cron-jobs/run",nt="/_lunora/admin/openapi",at="/_lunora/admin/openrpc",ot="/_lunora/admin/global/tables",ct="/_lunora/admin/global/table",ht="/_lunora/admin/global/facet",dt="/_lunora/admin/vector/indexes",ut="/_lunora/admin/vector/query",lt="/_lunora/admin/logs/archive",ft="/_lunora/admin/kv/namespaces",mt="/_lunora/admin/kv/keys",D="/_lunora/admin/kv/value",pt="/_lunora/admin/auth/users",yt="/_lunora/admin/auth/sessions",St="/_lunora/admin/auth/users/create",bt="/_lunora/admin/auth/users/role",Tt="/_lunora/admin/auth/users/ban",vt="/_lunora/admin/auth/users/unban",gt="/_lunora/admin/auth/users/password",kt="/_lunora/admin/auth/users/remove",Ct="/_lunora/admin/auth/users/impersonate",wt="/_lunora/admin/auth/sessions/revoke",Et="/_lunora/admin/auth/sessions/revoke-all",_t="/_lunora/admin/auth/capabilities",At="/_lunora/admin/auth/users/update",It="/_lunora/admin/auth/accounts",Ot="/_lunora/admin/auth/accounts/unlink",Rt="/_lunora/admin/auth/passkeys",Pt="/_lunora/admin/auth/passkeys/delete",Mt="/_lunora/admin/auth/two-factor/disable",Ft="/_lunora/admin/auth/organizations",Ht="/_lunora/admin/auth/organizations/members",Lt="/_lunora/admin/auth/organizations/invitations",Ut="/_lunora/admin/auth/organizations/members/remove",Nt="/_lunora/admin/auth/organizations/invitations/cancel",xt="/_lunora/admin/auth/config",Dt="/_lunora/admin/auth/sign-up-invitations",Bt="/_lunora/admin/auth/sign-up-invitations/create",Qt="/_lunora/admin/auth/sign-up-invitations/revoke",Kt="/_lunora/admin/auth/organizations/create",qt="/_lunora/admin/auth/organizations/update",Wt="/_lunora/admin/auth/organizations/remove",$t="/_lunora/admin/auth/organizations/members/add",Gt="/_lunora/admin/auth/organizations/members/invite",jt="/_lunora/admin/auth/organizations/members/role",Vt="/_lunora/admin/auth/organizations/teams",zt="/_lunora/admin/auth/organizations/teams/create",Yt="/_lunora/admin/auth/organizations/teams/update",Jt="/_lunora/admin/auth/organizations/teams/remove",Xt="/_lunora/admin/auth/organizations/teams/members",Zt="/_lunora/admin/auth/organizations/teams/members/add",es="/_lunora/admin/auth/organizations/teams/members/remove",ts="/_lunora/admin/auth/organizations/roles",ss="/_lunora/admin/auth/organizations/roles/create",rs="/_lunora/admin/auth/organizations/roles/update",is="/_lunora/admin/auth/organizations/roles/remove",ns="/api/auth",as="/get-session",Y=o=>o.startsWith("https://")?`wss://${o.slice(8)}`:o.startsWith("http://")?`ws://${o.slice(7)}`:o,C=(o,e)=>`${o.endsWith("/")?o.slice(0,-1):o}${e}`,y=(o,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===""?o:`${o}?${s}`},os=[he],l=o=>o??"",ie=(o,e)=>{const t=o.error,s=typeof t?.code=="string"?t.code:void 0,r=typeof t?.message=="string"?t.message:void 0;return{code:s,messageText:(typeof o.message=="string"?o.message:void 0)??r??e}},cs=o=>{const{code:e,messageText:t}=ie(o,"stream error");return e===void 0?new Error(t):new m(e,t)},J=o=>{const{code:e,messageText:t}=ie(o,"subscription error");return{message:t,...e===void 0?{}:{code:e}}};function B(o){if(o!==void 0)return e=>{o(e)}}const O=(o,e)=>{for(const t of o)try{t(e)}catch{}},hs=new TextDecoder,ds=o=>{if(typeof o=="string")return o;if(o instanceof ArrayBuffer)return hs.decode(o)},b=(o,e)=>{if(!o.socket||o.wsState!=="open")return!1;try{return o.socket.send(JSON.stringify(e)),!0}catch{return!1}},F=o=>{const e=new Error(o.message??"request failed");return e.code=o.code,o.data!==void 0&&(e.data=T(o.data)),o.hint!==void 0&&(e.hint=o.hint),o.docsUrl!==void 0&&(e.docsUrl=o.docsUrl),e},X=(o,e)=>{const t=F(o),s=Ie(t,e);return s!==void 0&&(t.data=s),t},k=(o,e)=>{try{return K(o)}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)}},Q=o=>"args"in o?{...o,args:T(o.args)}:o,us=(o,e)=>{const t=Array.from({length:e});for(const s of o){if(typeof s.id!="number"||s.id<0||s.id>=e)continue;const r=s.body;t[s.id]=r&&"error"in r&&r.error?{error:F(r.error),ok:!1}:{ok:!0,value:T(r?.result)}}return t.map(s=>s??{error:new Error("batch call returned no result"),ok:!1})},ls=Promise.resolve();class ne{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;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;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(Y(e.url),Le),this.wsToken=e.wsToken;const t=e.authBasePath??ns;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??de(),this.reconnectOptions=e.reconnect,this.heartbeatIntervalMs=e.heartbeatIntervalMs??xe,this.connectTimeoutMs=e.connectTimeoutMs??De,this.defaultConnectionContext=e.connectionContext,this.persistence=Te(e.persistence,e.outbox===void 0),this.persistenceVersion=e.persistenceVersion,this.queryCache=ve(e.queryCache),this.onPersistenceError=e.offlineQueue?.onPersistenceError,this.clientQueryStore=new ue,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=ls),this.offlineQueue=new ye(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-${W()}`,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();if(a!==r&&(!s&&i?(this.restampQueuedIdentity(r,a),this.restampWatermarks(r,a),this.restampConnectionIdentity(r,a),this.reseedFromHydratedCache()):this.rejectQueuedForIdentityChange(r),this.tabCoordinator)){const c=this.tabCoordinator.isLeader();this.tabCoordinator.stop(),this.tabCoordinator=this.createTabCoordinator(),this.tabCoordinator.start(),c&&this.tabCoordinator.promoteImmediately()}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()}replayIdentityVerdict(e){if(this.subjectAwaitingReconfirm())return"unknown";const t=this.identityFingerprint();return 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 c=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&&(G(this.clientWatermarks,qe),d=new Map,this.clientWatermarks.set(n??"",d)),d.set(i,a)}return{applied:a===void 0||a===r,result:c}}onAuthTokenChange(e){return this.authTokenListeners.add(e)}async getCurrentUser(){if(this.closed||!this.fetchImpl)return null;const e={},t=this.authToken;this.authToken&&(e.authorization=`Bearer ${this.authToken}`);try{const s=await this.fetchImpl(C(this.url,`${this.authBasePath}${as}`),{credentials:"include",headers:e,method:"GET"});if(!s.ok)return null;const i=(await s.json())?.user??null;return this.adoptResolvedSubject(t,i),i}catch{return null}}setWsToken(e){if(this.wsToken!==e){this.wsToken=e;for(const t of this.connections.values())if(t.socket)try{t.socket.close()}catch{}}}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 c=a.indexOf(r);c!==-1&&a.splice(c,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 c=this.getConnection(s.shardKey);c&&b(c,{topic:e,type:"whisper_subscribe"})}return()=>{const c=this.whisperHandlers.get(r),h=c?.get(e);if(!h?.delete(t)||h.size>0)return;c?.delete(e),c?.size===0&&this.whisperHandlers.delete(r);const d=this.getConnection(s.shardKey);d&&b(d,{topic:e,type:"whisper_unsubscribe"})}}whisper(e,t,s={}){this.assertLeaderOwnedSurface("whisper"),this.ensureSocket(s.shardKey);const r=this.getConnection(s.shardKey);r&&b(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 ge(this,e,t,s)}whenReady(){return this.readyPromise}get isReady(){return this.readyResolved}peekHydratedQuery(e,t,s){if(!this.readyResolved)return;const r=q(t),i=E(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,j),{body:JSON.stringify({calls:e.map((i,n)=>({args:k(i.args??{},`args for batch call '${i.fn.__lunoraRef}'`),functionPath:i.fn.__lunoraRef,id:n,shardKey:i.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()})`)}if(!t.ok||r.error&&!r.results)throw r.error?F(r.error):new m("INTERNAL",`LunoraClient: batch request failed (status ${t.status.toString()})`);for(const i of r.results??[]){const n=i.body?.commitCursor;typeof i.id=="number"&&typeof n=="number"&&this.recordShardCursor(e[i.id]?.shardKey,n)}return us(r.results??[],e.length)}async mutation(e,t,s={}){this.assertOpen();const r=t,i=s.mutationId??W(),{confirms:n,rollbacks:a}=this.applyOptimisticUpdates(e.__lunoraRef,r,s.shardKey,s.optimistic);s.optimisticUpdate&&this.applyOptimisticUpdate(s.optimisticUpdate,t,s.shardKey,a,n);const c=this.offlineFlushes.get(l(s.shardKey));c!==void 0&&await c;const{hasSocket:h,wasEverConnected:d,wsState:u}=this.connectionGateState(s.shardKey),{queueBeforeFirstConnect:f}=this.offlineQueue,S=d||f,p=this.WebSocketImpl!==void 0&&S;if(u!=="open"&&!h&&p||u==="connecting"&&S)return this.enqueueOfflineMutation(e,r,s.shardKey,i,a,n,s.precondition);try{let w;const ae=await this.rpc(e.__lunoraRef,r,s.shardKey,{captureBookmark:!0,mutationId:i,onCommitCursor:H=>{w=H}});for(const H of n)H(w);return ae}catch(w){throw M(a),w}}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??(h=>({rows:h})),n=t.length;let a=0,c=0;for(let h=0;h<n;h+=r){const d=t.slice(h,h+r),u=c;await this.mutation(e,i(d),{...s.importId===void 0?{}:{mutationId:`${s.importId}:${String(u)}`},shardKey:s.shardKey}),c+=1,a+=d.length,s.onProgress?.({done:a,total:n})}return{chunks:c,imported:a}}async shardTraffic(e){this.assertOpen();const t=await this.adminFetch(We,"POST",{table:e});return{failed:t.failed??0,ok:t.ok??0,shards:t.shards??[]}}async listScheduledJobs(){return this.assertOpen(),((await this.adminFetch($e,"GET")).records??[]).map(t=>Q(t))}async schedulerStatus(){this.assertOpen();const e=await this.adminFetch(Ge,"GET");return{backlog:e.backlog??0,inFlight:e.inFlight??0,pools:e.pools??[]}}async cancelScheduledJob(e){return this.assertOpen(),{cancelled:(await this.adminFetch(Ve,"POST",{id:e})).cancelled===!0}}async listDeadJobs(){return this.assertOpen(),(await Ce(async t=>await this.adminFetch(t===void 0?z:`${z}?cursor=${encodeURIComponent(t)}`,"GET"))).map(t=>Q(t))}async retryDeadJob(e){return this.assertOpen(),{retried:(await this.adminFetch(ze,"POST",{id:e})).retried===!0}}async removeDeadJob(e){return this.assertOpen(),{removed:(await this.adminFetch(Ye,"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(`${Je}?${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(`${Xe}?${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(Ze,"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(Y(this.url),je),s=$(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()))},c=f=>{if(n||this.WebSocketImpl===void 0)return;const S=f===void 0?t:`${t}?token=${encodeURIComponent(f)}`;this.openManagedSocket(r,S,this.connectTimeoutMs,{onClose:()=>{a()},onMessage:p=>{let v;try{v=JSON.parse(typeof p.data=="string"?p.data:"")}catch{return}v.type==="jobs"&&Array.isArray(v.records)&&(s.reset(),e(v.records.map(w=>Q(w))))}})},h=async f=>{let S;try{S=await f()}catch{a();return}c(S)},d=()=>{if(n||this.WebSocketImpl===void 0)return;const{wsToken:f}=this;if(typeof f=="function"){h(f).catch(()=>{});return}c(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(st,"GET")).functions??[]}async getCronJobs(){return this.assertOpen(),(await this.adminFetch(rt,"GET")).jobs??[]}async runCronJob(e){this.assertOpen();const t=await this.adminFetch(it,"POST",{name:e});return{name:t.name??e,ran:t.ran===!0}}async fetchOpenApi(){return this.assertOpen(),await this.adminFetch(nt,"GET")}async fetchOpenRpc(){return this.assertOpen(),await this.adminFetch(at,"GET")}async listStorageObjects(e={}){this.assertOpen();const t=y(x,{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=`${x}?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(tt,"GET")).buckets??[]}async uploadStorageObject(e){this.assertOpen();const t=`${x}?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=`${et}?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(ot,"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(K(e.filters))),T(await this.adminFetch(`${ct}?${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(K(e.filters))),T(await this.adminFetch(`${ht}?${t.toString()}`,"GET"))}async listVectorIndexes(){return this.assertOpen(),(await this.adminFetch(dt,"GET")).indexes??[]}async queryVectorIndex(e){return this.assertOpen(),(await this.adminFetch(ut,"POST",e)).matches??[]}async queryLogArchive(e={}){this.assertOpen();const t=await this.adminFetch(lt,"POST",e);return{nextCursor:t.nextCursor,rows:t.rows??[]}}async listKvNamespaces(){return this.assertOpen(),(await this.adminFetch(ft,"GET")).namespaces??[]}async listKvKeys(e){this.assertOpen();const t=y(mt,{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=y(D,{key:e.key,namespace:e.namespace});return await this.adminFetch(t,"GET")}async putKvValue(e){this.assertOpen(),await this.adminFetch(D,"PUT",e)}async deleteKvKey(e){this.assertOpen();const t=y(D,{key:e.key,namespace:e.namespace});await this.adminFetch(t,"DELETE")}async listAuthUsers(e={}){this.assertOpen();const t=y(pt,{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(St,"POST",e)}async setAuthUserRole(e){return await this.adminFetch(bt,"POST",e)}async banAuthUser(e){return await this.adminFetch(Tt,"POST",e)}async unbanAuthUser(e){return await this.adminFetch(vt,"POST",e)}async setAuthUserPassword(e){await this.adminFetch(gt,"POST",e)}async removeAuthUser(e){await this.adminFetch(kt,"POST",e)}async impersonateAuthUser(e){return await this.adminFetch(Ct,"POST",e)}async revokeAuthSession(e){await this.adminFetch(wt,"POST",e)}async revokeAuthUserSessions(e){await this.adminFetch(Et,"POST",e)}async getAuthCapabilities(){return await this.adminFetch(_t,"GET")}async updateAuthUser(e){return await this.adminFetch(At,"POST",e)}async listAuthAccounts(e){return await this.adminFetch(y(It,{userId:e.userId}),"GET")}async unlinkAuthAccount(e){await this.adminFetch(Ot,"POST",e)}async listAuthPasskeys(e){return await this.adminFetch(y(Rt,{userId:e.userId}),"GET")}async deleteAuthPasskey(e){await this.adminFetch(Pt,"POST",e)}async disableAuthTwoFactor(e){await this.adminFetch(Mt,"POST",e)}async listAuthOrganizations(e={}){return await this.adminFetch(y(Ft,{limit:e.limit,offset:e.offset}),"GET")}async listAuthOrgMembers(e){const t=y(Ht,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async listAuthOrgInvitations(e){const t=y(Lt,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async listAuthSignUpInvitations(e={}){const t=y(Dt,{limit:e.limit,offset:e.offset});return await this.adminFetch(t,"GET")}async createAuthSignUpInvitation(e){return await this.adminFetch(Bt,"POST",e)}async revokeAuthSignUpInvitation(e){await this.adminFetch(Qt,"POST",e)}async removeAuthOrgMember(e){await this.adminFetch(Ut,"POST",e)}async cancelAuthOrgInvitation(e){await this.adminFetch(Nt,"POST",e)}async getAuthConfig(){return await this.adminFetch(xt,"GET")}async createAuthOrganization(e){return await this.adminFetch(Kt,"POST",e)}async updateAuthOrganization(e){return await this.adminFetch(qt,"POST",e)}async deleteAuthOrganization(e){await this.adminFetch(Wt,"POST",e)}async addAuthOrgMember(e){return await this.adminFetch($t,"POST",e)}async inviteAuthOrgMember(e){return await this.adminFetch(Gt,"POST",e)}async setAuthOrgMemberRole(e){return await this.adminFetch(jt,"POST",e)}async listAuthOrgTeams(e){const t=y(Vt,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async createAuthOrgTeam(e){return await this.adminFetch(zt,"POST",e)}async updateAuthOrgTeam(e){return await this.adminFetch(Yt,"POST",e)}async removeAuthOrgTeam(e){await this.adminFetch(Jt,"POST",e)}async listAuthOrgTeamMembers(e){const t=y(Xt,{limit:e.limit,offset:e.offset,teamId:e.teamId});return await this.adminFetch(t,"GET")}async addAuthOrgTeamMember(e){return await this.adminFetch(Zt,"POST",e)}async removeAuthOrgTeamMember(e){await this.adminFetch(es,"POST",e)}async listAuthOrgRoles(e){const t=y(ts,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async createAuthOrgRole(e){return await this.adminFetch(ss,"POST",e)}async updateAuthOrgRole(e){return await this.adminFetch(rs,"POST",e)}async deleteAuthOrgRole(e){await this.adminFetch(is,"POST",e)}async listAuthSessions(e={}){this.assertOpen();const t=y(yt,{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 c=B(s),h=B(r.onError),d=B(r.onCheckpoint);if(!a){this.nextSubId+=1;const f=`sub_${this.nextSubId.toString()}`,S=q(i),p=this.takeHydratedCache(e.__lunoraRef,S,r.shardKey);a={acked:!1,args:i,argsKey:S,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(c),h&&a.errorCallbacks.add(h),d&&a.checkpointCallbacks.add(d),a.lastValue!==void 0)try{c(a.lastValue)}catch{}this.ensureSocket(r.shardKey),this.sendSubscribeIfOpen(a);const u=a;return()=>{u.callbacks.delete(c),h&&u.errorCallbacks.delete(h),d&&u.checkpointCallbacks.delete(d),u.callbacks.size===0&&(this.sendOrQueueUnsubscribe(u.shardKey,u.id,"unsubscribe"),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:c}=ke({maxBuffer:s.maxBuffer,onCancel:()=>{this.cancelStream(r,i)}});this.ensureSocket(i);const h=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=h?.wsState==="open"&&b(h,d);if(u.started=f,!f&&h===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")),c;if(!f){for(h.pendingStreams=h.pendingStreams??[];h.pendingStreams.length>=Ke;){const p=h.pendingStreams.shift()?.id,v=p?this.streams.get(p):void 0;v&&(v.handle.fail(new m("STREAM_QUEUE_OVERFLOW","stream-start frame evicted while socket was unreachable")),this.streams.delete(p))}h.pendingStreams.push(d)}return c}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 fe(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){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.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 le({channelName:e,onBecomeLeader:()=>{for(const t of this.subscriptions.all())this.ensureSocket(t.shardKey),this.sendSubscribeIfOpen(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),L(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&&O(i.errorCallbacks,s)},onSubscriptionSettled:(t,s,r,i,n,a)=>{if(a!==void 0&&a!==this.identityFingerprint())return;const c=this.subscriptions.get(t);if(c){this.ackAndAdvanceCursor(c,s,r),i!==void 0&&n===this.clientId&&(c.lastMutationId=Math.max(c.lastMutationId??0,i));for(const h of c.checkpointCallbacks)h({checkpoint:c.serverCursor,mutationId:c.lastMutationId})}}})}async enqueueOfflineMutation(e,t,s,r,i,n,a){const c=this.identityFingerprint();if(this.outbox){this.outboxMutationCounter+=1;const h=this.outboxMutationCounter;try{await this.outbox.enqueue({args:t,clientId:this.clientId,functionPath:e.__lunoraRef,idempotencyKey:`${this.clientId}:${String(h)}`,identity:c,mutationId:h,shardKey:s})}catch(d){throw M(i),d instanceof Error?d:new Error(String(d))}for(const d of n)d(void 0);return}return new Promise((h,d)=>{const u={args:t,functionPath:e.__lunoraRef,liveAwaiter:!0,id:r,clientId:this.clientId,identity:c,precondition:a,onCommit:f=>{for(const S of n)S(f)},reject:f=>{this.queuedIdentities.delete(r),M(i),d(f instanceof Error?f:new Error(String(f)))},resolve:h,shardKey:s};this.offlineQueue.enqueue(u),this.queuedOfflineShardKeys.add(s),u.id!==void 0&&this.queuedIdentities.set(u.id,c)})}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(E(s.fn.__lunoraRef,s.argsKey,s.shardKey),s);for(const{key:s,...r}of e){if(Se(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(E(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)}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=E(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=E(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=E(e.fn.__lunoraRef,e.argsKey,e.shardKey),r=this.getConnection(e.shardKey)?.identity,i=r===void 0?this.identityFingerprint():r;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(()=>{})},Be)}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.wsState==="connecting")?"connecting":"offline"}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),c=this.subscriptions.get(a);if(c){const h=me(c,r);h&&(i.push(h.confirm),n.push(h.rollback))}return{confirms:i,rollbacks:n}}applyOptimisticUpdate(e,t,s,r,i){const{confirms:n,rollbacks:a,store:c}=pe(this.subscriptions,s);try{e(c,t)}catch{M(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&&!b(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:[],reconnect:$(this.reconnectOptions),reconnectTimer:void 0,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.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 R("LunoraClient: no `fetch` implementation available");const i=this.rpcRequestHeaders(r,s),n=await this.fetchImpl(C(this.url,He),{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 P(n.status,n.statusText,n.headers.get("retry-after"))}if("error"in a)throw X(a.error,n.headers.get("retry-after"));if(!n.ok)throw P(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),T(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 c=await this.fetchImpl(C(this.url,e),{body:a,headers:i,method:t});let h;try{h=await c.json()}catch{const d=c.statusText?` ${c.statusText}`:"";throw new m("INTERNAL",`LunoraClient: response was not JSON (status ${c.status.toString()}${d})`)}if(typeof h=="object"&&h!==null&&"error"in h){const d=h.error,u=new Error(d.message??"admin request failed");throw u.code=d.code,u}if(!c.ok){const d=c.statusText?` ${c.statusText}`:"";throw new m("INTERNAL",`LunoraClient: admin request failed (status ${c.status.toString()}${d})`)}return h}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));b(e,{caps:os,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)},c=h=>{a(),r.onClose(h)};s>0&&(e.connectTimer=setTimeout(()=>{if(e.connectTimer=void 0,e.socket===n){try{n.close()}catch{}c()}},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(h){console.error("[lunora] connection open handler threw",h)}this.startHeartbeat(e,c)}}),n.addEventListener("message",h=>{if(e.socket===n){e.lastFrameAt=Date.now();try{r.onMessage(h)}catch(d){console.error("[lunora] server frame handler threw",d)}}}),n.addEventListener("close",h=>{e.socket===n&&c(h)}),n.addEventListener("error",()=>{e.socket===n&&c()})}openSocket(e,t,s){this.WebSocketImpl!==void 0&&(e.identity=this.identityFingerprint(),this.openManagedSocket(e,this.wsUrlFor(t,s),this.connectTimeoutMs,{onClose:r=>{r?.code===4001&&this.notifyTokenExpired(),this.handleDisconnect(e)},onMessage:r=>{this.handleServerMessage(r.data,t)},onOpen:()=>{e.wsState="open",e.wasEverConnected=!0,clearTimeout(e.stableTimer),e.stableTimer=setTimeout(()=>{e.wsState==="open"&&e.reconnect.reset()},Qe),this.emitConnectionStatus(),this.sendConnectEnvelope(e),this.markShardPendingAck(t);for(const i of this.subscriptions.all())l(i.shardKey)===l(t)&&this.sendSubscribeIfOpen(i);if(this.resendShapeSubscriptions(t),e.pendingUnsubscribes.length>0){const i=e.pendingUnsubscribes;e.pendingUnsubscribes=[];for(const{id:n,type:a}of i)b(e,{id:n,type:a})}this.flushPendingStreams(e);const r=this.whisperHandlers.get(l(t));if(r)for(const i of r.keys())b(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=b(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),!b(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;this.stopHeartbeat(e),this.clearConnectionTimers(e),e.socket=void 0,e.wsState="idle",this.emitConnectionStatus(),this.markShardPendingAck(e.shardKey);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(Ne)}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)}sendSubscribeIfOpen(e){const t=this.getConnection(e.shardKey);if(t?.wsState!=="open"||e.acked)return;const s=e.fn.__lunoraTable??e.fn.__lunoraRef,r=e.serverCursor!==void 0&&e.serverBase!==void 0;b(t,{id:e.id,query:{args:e.wireArgs,functionPath:e.fn.__lunoraRef,table:s,...r?{sinceSeq:e.serverCursor}:{},...r&&e.serverEpoch!==void 0?{sinceEpoch:e.serverEpoch}:{}},type:"subscribe"})}sendShapeSubscribeIfOpen(e){const t=this.getConnection(e.shardKey);t?.wsState==="open"&&b(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=ds(e);if(s===void 0)return;let r;try{r=JSON.parse(s)}catch{return}switch(r.type!=="error"&&this.getConnection(t)?.reconnect.reset(),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:c}=r,h=this.streams.get(a);h&&typeof c=="number"&&(h.lastSeq=c,typeof n=="number"&&(h.generation=n),h.durable=!0),h?.handle.push(T(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(cs(e)),this.streams.delete(s);return}const i=s===void 0?void 0:this.subscriptions.getById(s);if(i){const a=J(e),c=this.identityFingerprint(),h=g.keyOf(i);O(i.errorCallbacks,a),this.tabCoordinator?.isLeader()&&this.tabCoordinator.broadcastSubscriptionError(h,a,c);return}const n=s===void 0?void 0:this.shapeSubscriptions.get(s);n&&O(n.errorCallbacks,J(e))}pokeBufferKey(e,t){return`${l(e)}\0${t}`}handlePokeStart(e,t){G(this.pokeBuffers,ne.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:T(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,c=n!==void 0&&e.serverCursor!==void 0&&e.serverCursor!==n;if(!i&&(a||c)){e.rows.clear(),e.serverCursor=void 0,e.serverEpoch=void 0,this.emitShapeRows(e),this.sendShapeSubscribeIfOpen(e);return}i&&e.rows.clear(),Ue(e.rows,r),s.checkpoint!==void 0&&(e.serverCursor=s.checkpoint),s.epoch!==void 0&&(e.serverEpoch=s.epoch);const h=t.lastMutationId.get(e.id);h!==void 0&&(e.lastMutationId=h),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){O(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===V){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),L(s,s.serverCursor),_(s,A(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),L(e,e.serverCursor)&&_(e,A(e.serverBase,e.optimisticLayers)))}resolveDataPayload(e,t){if("data"in e&&e.data!==void 0)return T(e.data);const s=T(e.delta);return oe(s)?t.serverBase===void 0?s:ce(t.serverBase,s)??V:s}dispatchWhisper(e,t){const s=this.whisperHandlers.get(l(t))?.get(e.topic);if(!s)return;const r=T(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,O(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.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}adoptResolvedSubject(e,t){this.closed||t===null||this.authToken!==e||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,c]of r)n.set(a,c)}clearQueryCacheForIdentityChange(){this.revokeCacheSeededValues(),this.cacheFlushTimer!==void 0&&(clearTimeout(this.cacheFlushTimer),this.cacheFlushTimer=void 0),this.pendingCacheWrites.clear(),this.hydratedQueryCache.clear(),this.queryCache?.clear().catch(()=>{})}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 h of t){this.unpersist(h.id),this.queuedIdentities.delete(h.id??"");const d=new Error("offline mutation skipped: precondition failed before replay");d.code="OFFLINE_PRECONDITION_FAILED",this.emitItemSettled(h,"rejected",d)}const s=l(e),r=this.offlineQueue.drain(h=>l(h.shardKey)===s);if(r.length===0)return;const i=[],n=[];for(const h of r){const d=this.replayGateVerdict(h);d==="send"?i.push(h):d==="hold"&&n.push(h)}if(this.offlineQueue.requeue(n),n.length>0&&this.subjectAwaitingReconfirm()&&this.getCurrentUser().catch(()=>{}),i.length===0)return;const a=this.encodableOrSettleTerminal(i);if(a.length===0)return;if(a.length===1){await this.replaySequential(a,e),this.scheduleRateLimitedRetry(e);return}const c=[];for(let h=0;h<a.length;h+=U){const d=a.slice(h,h+U),u=await this.replayBatched(d,e);if(c.push(...u.requeue),u.stop){c.push(...a.slice(h+U));break}}c.length>0&&this.offlineQueue.requeue(c),this.scheduleRateLimitedRetry(e)}noteReplayRetryDelay(e,t){const s=l(e),r=this.replayRetryState.get(s),i=(r?.attempts??0)+1,n=Pe(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(we(e)){const t=this.hashToken(this.authToken??"");return this.authRefusalNotifiedFor!==t&&(this.authRefusalNotifiedFor=t,this.notifyTokenExpired()),!0}return Ee(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,{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((c,h)=>({args:k(c.args,`args for '${c.functionPath}'`),functionPath:c.functionPath,id:h,clientId:c.clientId??this.clientId,mutationId:c.id,shardKey:c.shardKey}))});if(e.length>1&&Fe(s)>Me)return await this.replayBatchedHalves(e,t);let r;try{r=await this.fetchImpl(C(this.url,j),{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,P(r.status,r.statusText,a),t)}if(!n.results){const c=n.error===void 0?P(r.status,r.statusText,a):X(n.error,a);return this.settleWholeBatchError(e,c,t)}return{requeue:this.settleReplayBatchSlots(e,n.results,t),stop:!1}}settleWholeBatchError(e,t,s){if(t instanceof R||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 c=r.get(n);if(c===void 0)i.push(a);else if("error"in c){const h=F(c.error);this.shouldRequeueReplayFailure(h)?(this.noteReplayRetryDelay(s,h),i.push(a)):this.settleReplayTerminal(a,h)}else this.settleReplaySuccess(a,T(c.result),c.commitCursor)}return i}}export{ne as LunoraClient};
@@ -1 +0,0 @@
1
- import{c as t}from"./local-store-CVfQDdXy.mjs";import"./SubscriptionRegistry-CS-AFUI9.mjs";export{t as createLocalStore};
@@ -1 +0,0 @@
1
- import{SubscriptionRegistry as m}from"./SubscriptionRegistry-CS-AFUI9.mjs";const p=(r,o)=>{let e=r;for(const i of o)try{e=i.transform(e)}catch{}return e},u=(r,o)=>{if(o!==r.lastValue){r.lastValue=o;for(const e of r.callbacks)try{e(o)}catch{}}},y=(r,o)=>{let e;try{e=o(r.lastValue)}catch{return}const i={id:Symbol("optimistic"),transform:o};r.optimisticLayers.push(i),u(r,e);const c=()=>{const t=r.optimisticLayers.findIndex(s=>s.id===i.id);return t===-1?!1:(r.optimisticLayers.splice(t,1),!0)},a=()=>{u(r,p(r.serverBase,r.optimisticLayers))};return{confirm:t=>{if(t===void 0){c();return}i.commitCursor=t,r.serverCursor!==void 0&&r.serverCursor>=t&&c()&&a()},rollback:()=>{c()&&a()}}},h=(r,o)=>{if(o===void 0||r.optimisticLayers.length===0)return!1;const e=r.optimisticLayers.length;return r.optimisticLayers=r.optimisticLayers.filter(i=>i.commitCursor===void 0||i.commitCursor>o),r.optimisticLayers.length!==e},L=(r,o)=>{const e=[],i=[],c=(t,s)=>r.get(m.key(t,s,o));return{confirms:e,rollbacks:i,store:{getAllQueries:t=>{const s=[];for(const n of r.all())n.fn.__lunoraRef===t.__lunoraRef&&(n.shardKey??"")===(o??"")&&s.push({args:n.args,value:n.lastValue});return s},getQuery:(t,s)=>c(t.__lunoraRef,s??{})?.lastValue,setQuery:(t,s,n)=>{const f=c(t.__lunoraRef,s??{});if(!f)return;const l=y(f,()=>n);l&&(e.push(l.confirm),i.push(l.rollback))}}}};export{y as a,L as c,h as d,p as f,u as n};