@lunora/client 1.0.0-alpha.231 → 1.0.0-alpha.233

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/auth/index.d.mts +1 -1
  2. package/dist/auth/index.d.ts +1 -1
  3. package/dist/index.d.mts +82 -3
  4. package/dist/index.d.ts +82 -3
  5. package/dist/index.mjs +1 -1
  6. package/dist/packem_shared/LunoraClient-CN4shVl4.mjs +1 -0
  7. package/dist/packem_shared/OfflineQueue-BLRESpAe.mjs +1 -0
  8. package/dist/packem_shared/TabCoordinator-DBuR7Dwv.mjs +1 -0
  9. package/dist/packem_shared/client-tuning-C10B2KCO.mjs +1 -0
  10. package/dist/packem_shared/connectLiveStream-CXD8k-Sp.mjs +1 -0
  11. package/dist/packem_shared/{createAsyncStorageQueryCache-f5023fdB.mjs → createAsyncStorageQueryCache-COqH5_SV.mjs} +1 -1
  12. package/dist/packem_shared/{createInMemoryPersistence-Cz2W6XVj.mjs → createInMemoryPersistence-BfgXApi_.mjs} +1 -1
  13. package/dist/packem_shared/{createInMemoryQueryCache-D2uNHLfM.mjs → createInMemoryQueryCache-B5wX-gTy.mjs} +1 -1
  14. package/dist/packem_shared/{createServerClient-BqCdfoE1.mjs → createServerClient-CwEIYb-6.mjs} +1 -1
  15. package/dist/packem_shared/httpStream-DceAMeMf.mjs +9 -0
  16. package/dist/packem_shared/idb-utility-BS7xvou1.mjs +1 -0
  17. package/dist/packem_shared/live-stream-Dil9byXF.mjs +10 -0
  18. package/dist/packem_shared/{liveTopicSubscription-Bs-ULKfs.mjs → liveTopicSubscription-gOmRbuhH.mjs} +1 -1
  19. package/dist/packem_shared/{lunora-client.d-dOEEoF4x.d.mts → lunora-client.d-D7gNlYT7.d.mts} +153 -17
  20. package/dist/packem_shared/{lunora-client.d-DpmxnYmL.d.ts → lunora-client.d-DTJ5zJKH.d.ts} +153 -17
  21. package/dist/packem_shared/offline-queue-Dt_um8sR.mjs +1 -0
  22. package/dist/packem_shared/{preload.d-XVLTUaah.d.mts → preload.d-B0FFchsh.d.mts} +1 -1
  23. package/dist/packem_shared/{preload.d-BkXsKMmU.d.ts → preload.d-d05S6fB-.d.ts} +1 -1
  24. package/dist/packem_shared/stream-idle-C7CsIT_m.mjs +1 -0
  25. package/dist/packem_shared/{wire-errors-Bw04a4ZQ.mjs → wire-errors-BTLdHNoh.mjs} +1 -1
  26. package/dist/query/index.d.mts +2 -2
  27. package/dist/query/index.d.ts +2 -2
  28. package/dist/service.mjs +1 -1
  29. package/dist/ssr/index.d.mts +2 -2
  30. package/dist/ssr/index.d.ts +2 -2
  31. package/dist/ssr/index.mjs +1 -1
  32. package/package.json +1 -1
  33. package/dist/packem_shared/LunoraClient-D6MyuSWy.mjs +0 -1
  34. package/dist/packem_shared/OfflineQueue-BWamzR6p.mjs +0 -1
  35. package/dist/packem_shared/TabCoordinator-CXD7vulJ.mjs +0 -1
  36. package/dist/packem_shared/connectLiveStream-DCgklEjI.mjs +0 -1
  37. package/dist/packem_shared/httpStream-DaqP70Ne.mjs +0 -9
  38. package/dist/packem_shared/idb-utility-C8WS390w.mjs +0 -1
  39. package/dist/packem_shared/live-stream-ct8j7T75.mjs +0 -10
  40. package/dist/packem_shared/offline-queue-D_fr-uQ3.mjs +0 -1
@@ -1,4 +1,4 @@
1
- import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-dOEEoF4x.mjs";
1
+ import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-D7gNlYT7.mjs";
2
2
  import '@lunora/errors';
3
3
  import "../packem_shared/function-reference.d-Br_hsKje.mjs";
4
4
  import '@lunora/runtime';
@@ -1,4 +1,4 @@
1
- import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-DpmxnYmL.js";
1
+ import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-DTJ5zJKH.js";
2
2
  import '@lunora/errors';
3
3
  import "../packem_shared/function-reference.d-Br_hsKje.js";
4
4
  import '@lunora/runtime';
package/dist/index.d.mts CHANGED
@@ -1,8 +1,8 @@
1
- import { R as ReconnectOptions, 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, L as LunoraClient } from "./packem_shared/lunora-client.d-dOEEoF4x.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 ReplayCredential, type N as ReplayIdentityVerdict, type T as RoomRef, type V as RowOp, type W as RpcEnvelope, type X as RpcResponseBody, type Y as ScheduleRecord, type Z as ScheduleRetryPolicy, type _ as SchedulerPoolStatus, type $ as SchedulerStatus, type a0 as ServerMessage, type a1 as ServerPokeEndMessage, type a2 as ServerPokePartMessage, type a3 as ServerPokeStartMessage, type a4 as ShardTrafficEntry, type a5 as ShardTrafficResult, type a6 as StorageListPage, type a7 as StorageObject, type a8 as StoredQuery, type a9 as StreamHandle, type aa as SubscriptionCallback, type b as SubscriptionErrorCallback, ab as SubscriptionRegistry, type ac as SubscriptionState, type ad as SyncWatermark, type a as Unsubscribe, type U as User, type ae as WorkflowInstanceAction, type af as WorkflowInstanceDetail, type ag as WorkflowInstancePage, type ah as WorkflowInstanceStatus, type ai as WorkflowInstanceSummary, type aj as WorkflowStepDetail, type ak as WsTokenProvider, al as createClientQuery, am as createLocalStore, an as createStream } from "./packem_shared/lunora-client.d-dOEEoF4x.mjs";
1
+ import { R as ReconnectOptions, 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, L as LunoraClient } from "./packem_shared/lunora-client.d-D7gNlYT7.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 ReplayCredential, type N as ReplayIdentityVerdict, type T as RoomRef, type V as RowOp, type W as RpcEnvelope, type X as RpcResponseBody, type Y as ScheduleRecord, type Z as ScheduleRetryPolicy, type _ as SchedulerPoolStatus, type $ as SchedulerStatus, type a0 as ServerMessage, type a1 as ServerPokeEndMessage, type a2 as ServerPokePartMessage, type a3 as ServerPokeStartMessage, type a4 as ShardTrafficEntry, type a5 as ShardTrafficResult, type a6 as StorageListPage, type a7 as StorageObject, type a8 as StoredQuery, type a9 as StreamHandle, type aa as SubscriptionCallback, type b as SubscriptionErrorCallback, ab as SubscriptionRegistry, type ac as SubscriptionState, type ad as SyncStatus, type ae as SyncWatermark, type a as Unsubscribe, type U as User, type af as WorkflowInstanceAction, type ag as WorkflowInstanceDetail, type ah as WorkflowInstancePage, type ai as WorkflowInstanceStatus, type aj as WorkflowInstanceSummary, type ak as WorkflowStepDetail, type al as WsTokenProvider, am as createClientQuery, an as createLocalStore, ao as createStream } from "./packem_shared/lunora-client.d-D7gNlYT7.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-XVLTUaah.mjs";
5
+ export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-B0FFchsh.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';
@@ -395,6 +395,13 @@ declare class TabCoordinator {
395
395
  private promotionPending;
396
396
  /** Timestamp of the most recent leader heartbeat. */
397
397
  private lastHeartbeat;
398
+ /**
399
+ * Snapshots waiting for the end of the current tick, latest per key. A
400
+ * `subscription-data` frame is a full snapshot, so a burst for one key within
401
+ * a tick only needs its last frame posted — each post structured-clones the
402
+ * whole value for every tab on the channel.
403
+ */
404
+ private readonly pendingData;
398
405
  private heartbeatTimer;
399
406
  private leaderCheckTimer;
400
407
  /** Callbacks set via constructor options. */
@@ -488,6 +495,8 @@ declare class TabCoordinator {
488
495
  */
489
496
  broadcastConnectionStatus(status: ConnectionStatus, identity?: string | null): void;
490
497
  private broadcast;
498
+ /** Post the snapshots queued this tick — unless leadership was lost meanwhile, when the new leader's own snapshots supersede them. */
499
+ private flushPendingData;
491
500
  private handleMessage;
492
501
  private handleClaimLeadership;
493
502
  private handleHeartbeat;
@@ -565,6 +574,15 @@ interface HttpStreamOptions {
565
574
  fetch?: typeof fetch;
566
575
  /** Extra request headers (e.g. `authorization`). `accept: text/event-stream` is always sent. */
567
576
  headers?: Record<string, string>;
577
+ /**
578
+ * Treat a connection that delivers nothing — no chunk, no keepalive comment —
579
+ * for this many milliseconds as dead: it is cancelled, then reconnected with
580
+ * {@link HttpStreamOptions.reconnect} or failed with `STREAM_IDLE`. Off by
581
+ * default, because a route may be silent for as long as its handler works
582
+ * (a model thinking); set it to a few multiples of the route's keepalive
583
+ * interval when the route sends one.
584
+ */
585
+ idleTimeoutMs?: number;
568
586
  /**
569
587
  * Seed the first request's `Last-Event-ID` header, resuming a stream from a
570
588
  * position a previous consumer persisted. Once frames arrive this is
@@ -611,6 +629,14 @@ interface ConnectLiveStreamOptions {
611
629
  fetch?: typeof fetch;
612
630
  /** Extra headers sent on both the stream and the control requests. */
613
631
  headers?: Record<string, string>;
632
+ /**
633
+ * Treat a connection that delivers nothing — not even a keepalive — for this many milliseconds as
634
+ * dead, and reconnect. Every target that serves live streams (Cloudflare Workers, the Node host
635
+ * and celld) runs the same `ShardDO` live handlers, and they write a `:ka` comment every 25s
636
+ * while a stream is open, so the default is `75000`. Set `0` to disable the bound when a proxy
637
+ * or a server of your own in front of the shard does not forward comment frames.
638
+ */
639
+ idleTimeoutMs?: number;
614
640
  /** Ceiling for the reconnect backoff, in ms. Defaults to `30000`. */
615
641
  maxDelayMs?: number;
616
642
  /** Base reconnect delay in ms. Defaults to `1000`. */
@@ -775,6 +801,13 @@ declare const createMutatorRunner: <TArgs>(handle: MutatorHandle<TArgs>, sinks:
775
801
  reset: () => void;
776
802
  };
777
803
  interface QueuedMutation<T = unknown> {
804
+ /**
805
+ * Set on a write that was queued because its direct send failed in a way that
806
+ * says nothing about its fate (see `LunoraClient.mutation`). Its caller is still
807
+ * waiting and was never told it failed, so the replay counts its transient
808
+ * failures and rejects it after a few, rather than retrying for ever.
809
+ */
810
+ readonly ambiguousSend?: boolean;
778
811
  readonly args: Record<string, unknown>;
779
812
  /**
780
813
  * CDC cursor this write was composed against (see
@@ -803,6 +836,13 @@ interface QueuedMutation<T = unknown> {
803
836
  * a reload and a requeue.
804
837
  */
805
838
  identity?: string | null;
839
+ /**
840
+ * Position in the order this session ISSUED its writes, taken before the first send. A write whose
841
+ * direct send failed ambiguously is queued only once that send gives up, behind writes issued (and
842
+ * queued) while it was in flight; this puts it back ahead of them. Absent on hydrated records,
843
+ * which are older than anything issued this session.
844
+ */
845
+ readonly issueSeq?: number;
806
846
  /**
807
847
  * `true` when a live caller is still awaiting this write's `mutation()`
808
848
  * Promise; `false`/absent for a write restored from durable storage after a
@@ -852,6 +892,8 @@ type EvictHandler = (entry: QueuedMutation, error: Error & {
852
892
  interface OfflineQueueDeps {
853
893
  /** Invoked when an entry is discarded on capacity overflow (carries `OFFLINE_QUEUE_OVERFLOW`). */
854
894
  onEvict?: EvictHandler;
895
+ /** Invoked when a write that was out for replay settles, which `onSizeChange` does not cover: the queue was already shorter. */
896
+ onReplayingChange?: () => void;
855
897
  /** Invoked with the new depth after any size change (drives the client's pending-sync count). */
856
898
  onSizeChange?: (size: number) => void;
857
899
  /** Durable store; when present, writes are mirrored and restored across reloads. */
@@ -879,12 +921,44 @@ declare class OfflineQueue {
879
921
  private readonly persistence;
880
922
  private readonly onEvict;
881
923
  private readonly onSizeChange;
924
+ private readonly onReplayingChange;
882
925
  /** App/schema version stamped on persisted writes; mismatched records are purged on hydrate. */
883
926
  private readonly version;
884
927
  private readonly items;
928
+ /** Ids of writes a flush has {@link OfflineQueue.drain}ed and neither requeued nor discarded yet, which are on the wire or about to be. */
929
+ private readonly replayingIds;
930
+ /** Appends still in flight, by write id, each resolving to whether the record landed. Anything that touches a record durably waits on its append first. */
931
+ private readonly appending;
932
+ /**
933
+ * Writes enqueued this session and not yet settled (see {@link OfflineQueue.discard}). Unlike `items`
934
+ * this survives a replay temporarily draining the queue, so a failed append is tracked for as long as
935
+ * the write is unsettled, and a retry derives its record from the entry as it is NOW.
936
+ */
937
+ private readonly unsettled;
938
+ /** Ids whose append was rejected (a quota error, a closed connection), kept to be tried again — see {@link OfflineQueue.flushUnpersisted}. */
939
+ private readonly unpersisted;
885
940
  constructor(options?: OfflineQueueOptions, deps?: OfflineQueueDeps);
886
941
  get size(): number;
942
+ /** Writes drained for replay and not yet settled or requeued: out of {@link OfflineQueue.size}, but still unsettled. */
943
+ get replaying(): number;
887
944
  enqueue<T>(entry: QueuedMutation<T>): void;
945
+ /**
946
+ * Remove a settled write's durable record — after its append, if that is
947
+ * still in flight. A write that replays quickly can settle before its append
948
+ * has landed; a `remove` that overtook it found nothing, and the record then
949
+ * landed behind it and replayed in the next session.
950
+ */
951
+ discard(id: string): void;
952
+ /**
953
+ * Try again to persist every write whose append was rejected. Called when the
954
+ * page is being hidden: the last chance to get a still-queued write into
955
+ * durable storage before a reload or a discard of the tab loses it.
956
+ *
957
+ * A write whose append is still in flight is skipped: `visibilitychange` and `pagehide` fire
958
+ * back to back, and a second append for the same id would hit a unique-id constraint (or store
959
+ * the record twice) and leave the write wrongly tracked as unpersisted.
960
+ */
961
+ flushUnpersisted(): void;
888
962
  /**
889
963
  * Restore mutations persisted in a prior session and re-queue them in FIFO
890
964
  * order. Restored entries already live in durable storage, so they are not
@@ -956,6 +1030,10 @@ declare class OfflineQueue {
956
1030
  */
957
1031
  drainConflict(): QueuedMutation[];
958
1032
  clear(): void;
1033
+ /** The durable form of a queued write. */
1034
+ private recordOf;
1035
+ /** Append `record`, remembering it as unpersisted if the append is rejected. */
1036
+ private persist;
959
1037
  /**
960
1038
  * The durable half of {@link OfflineQueue.restampIdentity}: rewrite the
961
1039
  * persisted record under the new identity stamp.
@@ -986,6 +1064,7 @@ declare class OfflineQueue {
986
1064
  * always drops the same way regardless of which caller triggered it.
987
1065
  */
988
1066
  private evictOverflow;
1067
+ private markReplaying;
989
1068
  /** Notify the size observer (the client's pending-sync count) after any change. */
990
1069
  private notifySize;
991
1070
  }
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { R as ReconnectOptions, 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, L as LunoraClient } from "./packem_shared/lunora-client.d-DpmxnYmL.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 ReplayCredential, type N as ReplayIdentityVerdict, type T as RoomRef, type V as RowOp, type W as RpcEnvelope, type X as RpcResponseBody, type Y as ScheduleRecord, type Z as ScheduleRetryPolicy, type _ as SchedulerPoolStatus, type $ as SchedulerStatus, type a0 as ServerMessage, type a1 as ServerPokeEndMessage, type a2 as ServerPokePartMessage, type a3 as ServerPokeStartMessage, type a4 as ShardTrafficEntry, type a5 as ShardTrafficResult, type a6 as StorageListPage, type a7 as StorageObject, type a8 as StoredQuery, type a9 as StreamHandle, type aa as SubscriptionCallback, type b as SubscriptionErrorCallback, ab as SubscriptionRegistry, type ac as SubscriptionState, type ad as SyncWatermark, type a as Unsubscribe, type U as User, type ae as WorkflowInstanceAction, type af as WorkflowInstanceDetail, type ag as WorkflowInstancePage, type ah as WorkflowInstanceStatus, type ai as WorkflowInstanceSummary, type aj as WorkflowStepDetail, type ak as WsTokenProvider, al as createClientQuery, am as createLocalStore, an as createStream } from "./packem_shared/lunora-client.d-DpmxnYmL.js";
1
+ import { R as ReconnectOptions, 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, L as LunoraClient } from "./packem_shared/lunora-client.d-DTJ5zJKH.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 ReplayCredential, type N as ReplayIdentityVerdict, type T as RoomRef, type V as RowOp, type W as RpcEnvelope, type X as RpcResponseBody, type Y as ScheduleRecord, type Z as ScheduleRetryPolicy, type _ as SchedulerPoolStatus, type $ as SchedulerStatus, type a0 as ServerMessage, type a1 as ServerPokeEndMessage, type a2 as ServerPokePartMessage, type a3 as ServerPokeStartMessage, type a4 as ShardTrafficEntry, type a5 as ShardTrafficResult, type a6 as StorageListPage, type a7 as StorageObject, type a8 as StoredQuery, type a9 as StreamHandle, type aa as SubscriptionCallback, type b as SubscriptionErrorCallback, ab as SubscriptionRegistry, type ac as SubscriptionState, type ad as SyncStatus, type ae as SyncWatermark, type a as Unsubscribe, type U as User, type af as WorkflowInstanceAction, type ag as WorkflowInstanceDetail, type ah as WorkflowInstancePage, type ai as WorkflowInstanceStatus, type aj as WorkflowInstanceSummary, type ak as WorkflowStepDetail, type al as WsTokenProvider, am as createClientQuery, an as createLocalStore, ao as createStream } from "./packem_shared/lunora-client.d-DTJ5zJKH.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-BkXsKMmU.js";
5
+ export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-d05S6fB-.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';
@@ -395,6 +395,13 @@ declare class TabCoordinator {
395
395
  private promotionPending;
396
396
  /** Timestamp of the most recent leader heartbeat. */
397
397
  private lastHeartbeat;
398
+ /**
399
+ * Snapshots waiting for the end of the current tick, latest per key. A
400
+ * `subscription-data` frame is a full snapshot, so a burst for one key within
401
+ * a tick only needs its last frame posted — each post structured-clones the
402
+ * whole value for every tab on the channel.
403
+ */
404
+ private readonly pendingData;
398
405
  private heartbeatTimer;
399
406
  private leaderCheckTimer;
400
407
  /** Callbacks set via constructor options. */
@@ -488,6 +495,8 @@ declare class TabCoordinator {
488
495
  */
489
496
  broadcastConnectionStatus(status: ConnectionStatus, identity?: string | null): void;
490
497
  private broadcast;
498
+ /** Post the snapshots queued this tick — unless leadership was lost meanwhile, when the new leader's own snapshots supersede them. */
499
+ private flushPendingData;
491
500
  private handleMessage;
492
501
  private handleClaimLeadership;
493
502
  private handleHeartbeat;
@@ -565,6 +574,15 @@ interface HttpStreamOptions {
565
574
  fetch?: typeof fetch;
566
575
  /** Extra request headers (e.g. `authorization`). `accept: text/event-stream` is always sent. */
567
576
  headers?: Record<string, string>;
577
+ /**
578
+ * Treat a connection that delivers nothing — no chunk, no keepalive comment —
579
+ * for this many milliseconds as dead: it is cancelled, then reconnected with
580
+ * {@link HttpStreamOptions.reconnect} or failed with `STREAM_IDLE`. Off by
581
+ * default, because a route may be silent for as long as its handler works
582
+ * (a model thinking); set it to a few multiples of the route's keepalive
583
+ * interval when the route sends one.
584
+ */
585
+ idleTimeoutMs?: number;
568
586
  /**
569
587
  * Seed the first request's `Last-Event-ID` header, resuming a stream from a
570
588
  * position a previous consumer persisted. Once frames arrive this is
@@ -611,6 +629,14 @@ interface ConnectLiveStreamOptions {
611
629
  fetch?: typeof fetch;
612
630
  /** Extra headers sent on both the stream and the control requests. */
613
631
  headers?: Record<string, string>;
632
+ /**
633
+ * Treat a connection that delivers nothing — not even a keepalive — for this many milliseconds as
634
+ * dead, and reconnect. Every target that serves live streams (Cloudflare Workers, the Node host
635
+ * and celld) runs the same `ShardDO` live handlers, and they write a `:ka` comment every 25s
636
+ * while a stream is open, so the default is `75000`. Set `0` to disable the bound when a proxy
637
+ * or a server of your own in front of the shard does not forward comment frames.
638
+ */
639
+ idleTimeoutMs?: number;
614
640
  /** Ceiling for the reconnect backoff, in ms. Defaults to `30000`. */
615
641
  maxDelayMs?: number;
616
642
  /** Base reconnect delay in ms. Defaults to `1000`. */
@@ -775,6 +801,13 @@ declare const createMutatorRunner: <TArgs>(handle: MutatorHandle<TArgs>, sinks:
775
801
  reset: () => void;
776
802
  };
777
803
  interface QueuedMutation<T = unknown> {
804
+ /**
805
+ * Set on a write that was queued because its direct send failed in a way that
806
+ * says nothing about its fate (see `LunoraClient.mutation`). Its caller is still
807
+ * waiting and was never told it failed, so the replay counts its transient
808
+ * failures and rejects it after a few, rather than retrying for ever.
809
+ */
810
+ readonly ambiguousSend?: boolean;
778
811
  readonly args: Record<string, unknown>;
779
812
  /**
780
813
  * CDC cursor this write was composed against (see
@@ -803,6 +836,13 @@ interface QueuedMutation<T = unknown> {
803
836
  * a reload and a requeue.
804
837
  */
805
838
  identity?: string | null;
839
+ /**
840
+ * Position in the order this session ISSUED its writes, taken before the first send. A write whose
841
+ * direct send failed ambiguously is queued only once that send gives up, behind writes issued (and
842
+ * queued) while it was in flight; this puts it back ahead of them. Absent on hydrated records,
843
+ * which are older than anything issued this session.
844
+ */
845
+ readonly issueSeq?: number;
806
846
  /**
807
847
  * `true` when a live caller is still awaiting this write's `mutation()`
808
848
  * Promise; `false`/absent for a write restored from durable storage after a
@@ -852,6 +892,8 @@ type EvictHandler = (entry: QueuedMutation, error: Error & {
852
892
  interface OfflineQueueDeps {
853
893
  /** Invoked when an entry is discarded on capacity overflow (carries `OFFLINE_QUEUE_OVERFLOW`). */
854
894
  onEvict?: EvictHandler;
895
+ /** Invoked when a write that was out for replay settles, which `onSizeChange` does not cover: the queue was already shorter. */
896
+ onReplayingChange?: () => void;
855
897
  /** Invoked with the new depth after any size change (drives the client's pending-sync count). */
856
898
  onSizeChange?: (size: number) => void;
857
899
  /** Durable store; when present, writes are mirrored and restored across reloads. */
@@ -879,12 +921,44 @@ declare class OfflineQueue {
879
921
  private readonly persistence;
880
922
  private readonly onEvict;
881
923
  private readonly onSizeChange;
924
+ private readonly onReplayingChange;
882
925
  /** App/schema version stamped on persisted writes; mismatched records are purged on hydrate. */
883
926
  private readonly version;
884
927
  private readonly items;
928
+ /** Ids of writes a flush has {@link OfflineQueue.drain}ed and neither requeued nor discarded yet, which are on the wire or about to be. */
929
+ private readonly replayingIds;
930
+ /** Appends still in flight, by write id, each resolving to whether the record landed. Anything that touches a record durably waits on its append first. */
931
+ private readonly appending;
932
+ /**
933
+ * Writes enqueued this session and not yet settled (see {@link OfflineQueue.discard}). Unlike `items`
934
+ * this survives a replay temporarily draining the queue, so a failed append is tracked for as long as
935
+ * the write is unsettled, and a retry derives its record from the entry as it is NOW.
936
+ */
937
+ private readonly unsettled;
938
+ /** Ids whose append was rejected (a quota error, a closed connection), kept to be tried again — see {@link OfflineQueue.flushUnpersisted}. */
939
+ private readonly unpersisted;
885
940
  constructor(options?: OfflineQueueOptions, deps?: OfflineQueueDeps);
886
941
  get size(): number;
942
+ /** Writes drained for replay and not yet settled or requeued: out of {@link OfflineQueue.size}, but still unsettled. */
943
+ get replaying(): number;
887
944
  enqueue<T>(entry: QueuedMutation<T>): void;
945
+ /**
946
+ * Remove a settled write's durable record — after its append, if that is
947
+ * still in flight. A write that replays quickly can settle before its append
948
+ * has landed; a `remove` that overtook it found nothing, and the record then
949
+ * landed behind it and replayed in the next session.
950
+ */
951
+ discard(id: string): void;
952
+ /**
953
+ * Try again to persist every write whose append was rejected. Called when the
954
+ * page is being hidden: the last chance to get a still-queued write into
955
+ * durable storage before a reload or a discard of the tab loses it.
956
+ *
957
+ * A write whose append is still in flight is skipped: `visibilitychange` and `pagehide` fire
958
+ * back to back, and a second append for the same id would hit a unique-id constraint (or store
959
+ * the record twice) and leave the write wrongly tracked as unpersisted.
960
+ */
961
+ flushUnpersisted(): void;
888
962
  /**
889
963
  * Restore mutations persisted in a prior session and re-queue them in FIFO
890
964
  * order. Restored entries already live in durable storage, so they are not
@@ -956,6 +1030,10 @@ declare class OfflineQueue {
956
1030
  */
957
1031
  drainConflict(): QueuedMutation[];
958
1032
  clear(): void;
1033
+ /** The durable form of a queued write. */
1034
+ private recordOf;
1035
+ /** Append `record`, remembering it as unpersisted if the append is rejected. */
1036
+ private persist;
959
1037
  /**
960
1038
  * The durable half of {@link OfflineQueue.restampIdentity}: rewrite the
961
1039
  * persisted record under the new identity stamp.
@@ -986,6 +1064,7 @@ declare class OfflineQueue {
986
1064
  * always drops the same way regardless of which caller triggered it.
987
1065
  */
988
1066
  private evictOverflow;
1067
+ private markReplaying;
989
1068
  /** Notify the size observer (the client's pending-sync count) after any change. */
990
1069
  private notifySize;
991
1070
  }
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{RETIRE_AFTER_DURABLE_SEQ_ADVANCE as o,maxSeq as t,reconcileOptimistic as a}from"./packem_shared/RETIRE_AFTER_DURABLE_SEQ_ADVANCE-DoEHtuR8.mjs";import{createAsyncStoragePersistence as i}from"./packem_shared/createAsyncStoragePersistence-6FCvqc6C.mjs";import{createAsyncStorageQueryCache as n}from"./packem_shared/createAsyncStorageQueryCache-f5023fdB.mjs";import{default as s}from"./packem_shared/createInMemoryBookmarkStorage-BooZhW0n.mjs";import{createCallRunner as x}from"./packem_shared/createCallRunner-Bwcrfh76.mjs";import{createClientQuery as l}from"./packem_shared/createClientQuery-B8Nfj-7o.mjs";import{TabCoordinator as d}from"./packem_shared/TabCoordinator-CXD7vulJ.mjs";import{a as R,i as C}from"./packem_shared/delta-merge-Ls3DED4g.mjs";import{CONFLICT_ERROR_CODE as A,TransportError as b,getErrorCode as h,getRetryAfterMs as D,isAuthReplayFailure as L,isConflictError as Q,isForbiddenError as T,isRateLimitedError as _,isUnauthorizedError as F}from"./packem_shared/CONFLICT_ERROR_CODE-B7qNZMMk.mjs";import{httpStream as M}from"./packem_shared/httpStream-DaqP70Ne.mjs";import{c as O}from"./packem_shared/live-stream-ct8j7T75.mjs";import{liveTopicSubscription as U,subscribeLiveTopic as v}from"./packem_shared/liveTopicSubscription-Bs-ULKfs.mjs";import{c as k}from"./packem_shared/local-store-fqWV2n_Z.mjs";import{LunoraClient as N}from"./packem_shared/LunoraClient-D6MyuSWy.mjs";import{createMutatorRunner as K}from"./packem_shared/createMutatorRunner-CuMRJpUx.mjs";import{O as X}from"./packem_shared/offline-queue-D_fr-uQ3.mjs";import{createInMemoryPersistence as w,createIndexedDbPersistence as G}from"./packem_shared/createInMemoryPersistence-Cz2W6XVj.mjs";import{preloadQuery as J,preloadedQueryResult as W}from"./packem_shared/preloadQuery-uFy24PCR.mjs";import{createInMemoryQueryCache as Z,createIndexedDbQueryCache as $,queryCacheKey as ee}from"./packem_shared/createInMemoryQueryCache-D2uNHLfM.mjs";import{createReconnect as oe}from"./packem_shared/createReconnect-CjTmjJDH.mjs";import{default as ae}from"./packem_shared/createSnapshotPrecondition-CLkxVeN1.mjs";import{DEFAULT_MAX_BUFFER as ie,createStream as pe}from"./packem_shared/DEFAULT_MAX_BUFFER-Bd-_iyiV.mjs";import{SubscriptionRegistry as me}from"./packem_shared/SubscriptionRegistry-DKIXE7M7.mjs";export{A as CONFLICT_ERROR_CODE,ie as DEFAULT_MAX_BUFFER,N as LunoraClient,X as OfflineQueue,o as RETIRE_AFTER_DURABLE_SEQ_ADVANCE,me as SubscriptionRegistry,d as TabCoordinator,b as TransportError,R as applyDelta,O as connectLiveStream,i as createAsyncStoragePersistence,n as createAsyncStorageQueryCache,x as createCallRunner,l as createClientQuery,s as createInMemoryBookmarkStorage,w as createInMemoryPersistence,Z as createInMemoryQueryCache,G as createIndexedDbPersistence,$ as createIndexedDbQueryCache,k as createLocalStore,K as createMutatorRunner,oe as createReconnect,ae as createSnapshotPrecondition,pe as createStream,h as getErrorCode,D as getRetryAfterMs,M as httpStream,L as isAuthReplayFailure,Q as isConflictError,T as isForbiddenError,C as isMutationDelta,_ as isRateLimitedError,F as isUnauthorizedError,U as liveTopicSubscription,t as maxSeq,J as preloadQuery,W as preloadedQueryResult,ee as queryCacheKey,a as reconcileOptimistic,v as subscribeLiveTopic};
1
+ import{RETIRE_AFTER_DURABLE_SEQ_ADVANCE as o,maxSeq as t,reconcileOptimistic as a}from"./packem_shared/RETIRE_AFTER_DURABLE_SEQ_ADVANCE-DoEHtuR8.mjs";import{createAsyncStoragePersistence as i}from"./packem_shared/createAsyncStoragePersistence-6FCvqc6C.mjs";import{createAsyncStorageQueryCache as n}from"./packem_shared/createAsyncStorageQueryCache-COqH5_SV.mjs";import{default as s}from"./packem_shared/createInMemoryBookmarkStorage-BooZhW0n.mjs";import{createCallRunner as x}from"./packem_shared/createCallRunner-Bwcrfh76.mjs";import{createClientQuery as l}from"./packem_shared/createClientQuery-B8Nfj-7o.mjs";import{TabCoordinator as d}from"./packem_shared/TabCoordinator-DBuR7Dwv.mjs";import{a as R,i as C}from"./packem_shared/delta-merge-Ls3DED4g.mjs";import{CONFLICT_ERROR_CODE as A,TransportError as b,getErrorCode as h,getRetryAfterMs as D,isAuthReplayFailure as L,isConflictError as Q,isForbiddenError as T,isRateLimitedError as _,isUnauthorizedError as F}from"./packem_shared/CONFLICT_ERROR_CODE-B7qNZMMk.mjs";import{httpStream as M}from"./packem_shared/httpStream-DceAMeMf.mjs";import{c as O}from"./packem_shared/live-stream-Dil9byXF.mjs";import{liveTopicSubscription as U,subscribeLiveTopic as v}from"./packem_shared/liveTopicSubscription-gOmRbuhH.mjs";import{c as k}from"./packem_shared/local-store-fqWV2n_Z.mjs";import{LunoraClient as N}from"./packem_shared/LunoraClient-CN4shVl4.mjs";import{createMutatorRunner as K}from"./packem_shared/createMutatorRunner-CuMRJpUx.mjs";import{O as X}from"./packem_shared/offline-queue-Dt_um8sR.mjs";import{createInMemoryPersistence as w,createIndexedDbPersistence as G}from"./packem_shared/createInMemoryPersistence-BfgXApi_.mjs";import{preloadQuery as J,preloadedQueryResult as W}from"./packem_shared/preloadQuery-uFy24PCR.mjs";import{createInMemoryQueryCache as Z,createIndexedDbQueryCache as $,queryCacheKey as ee}from"./packem_shared/createInMemoryQueryCache-B5wX-gTy.mjs";import{createReconnect as oe}from"./packem_shared/createReconnect-CjTmjJDH.mjs";import{default as ae}from"./packem_shared/createSnapshotPrecondition-CLkxVeN1.mjs";import{DEFAULT_MAX_BUFFER as ie,createStream as pe}from"./packem_shared/DEFAULT_MAX_BUFFER-Bd-_iyiV.mjs";import{SubscriptionRegistry as me}from"./packem_shared/SubscriptionRegistry-DKIXE7M7.mjs";export{A as CONFLICT_ERROR_CODE,ie as DEFAULT_MAX_BUFFER,N as LunoraClient,X as OfflineQueue,o as RETIRE_AFTER_DURABLE_SEQ_ADVANCE,me as SubscriptionRegistry,d as TabCoordinator,b as TransportError,R as applyDelta,O as connectLiveStream,i as createAsyncStoragePersistence,n as createAsyncStorageQueryCache,x as createCallRunner,l as createClientQuery,s as createInMemoryBookmarkStorage,w as createInMemoryPersistence,Z as createInMemoryQueryCache,G as createIndexedDbPersistence,$ as createIndexedDbQueryCache,k as createLocalStore,K as createMutatorRunner,oe as createReconnect,ae as createSnapshotPrecondition,pe as createStream,h as getErrorCode,D as getRetryAfterMs,M as httpStream,L as isAuthReplayFailure,Q as isConflictError,T as isForbiddenError,C as isMutationDelta,_ as isRateLimitedError,F as isUnauthorizedError,U as liveTopicSubscription,t as maxSeq,J as preloadQuery,W as preloadedQueryResult,ee as queryCacheKey,a as reconcileOptimistic,v as subscribeLiveTopic};
@@ -0,0 +1 @@
1
+ import{LunoraError as S}from"@lunora/errors";import{encodeWire as B,decodeWire as k,stableWireKey as he}from"@lunora/wire";import{r as Be,U as De,P as Qe}from"./delta-merge-Ls3DED4g.mjs";import{w as v,b as re,j as C,d as ue,p as le,s as fe}from"./client-urls-BHLUjjcG.mjs";import qe from"./createInMemoryBookmarkStorage-BooZhW0n.mjs";import{s as Z,a as Ke,e as D,r as je,b as pe,w as Ge,c as $e,d as me,u as Ve}from"./wire-errors-BTLdHNoh.mjs";import{ClientQueryStore as ze}from"./createClientQuery-B8Nfj-7o.mjs";import{D as Je,a as Ye,b as Xe,c as Ze,d as et,S as ye,M as tt,I as st,Q as it,R as rt,e as nt,f as ot,g as at}from"./client-tuning-C10B2KCO.mjs";import{TabCoordinator as ct}from"./TabCoordinator-DBuR7Dwv.mjs";import{TransportError as M,getRetryAfterMs as dt,AUTH_REPLAY_ERROR_CODES as ht,isAuthReplayFailure as Q}from"./CONFLICT_ERROR_CODE-B7qNZMMk.mjs";import{httpStream as ut}from"./httpStream-DceAMeMf.mjs";import{d as ee,r as F,a as N,b as lt,c as ft,e as pt,f as mt}from"./local-store-fqWV2n_Z.mjs";import{O as yt,n as Se,i as St}from"./offline-queue-Dt_um8sR.mjs";import{resolvePersistenceAdapter as bt}from"./createInMemoryPersistence-BfgXApi_.mjs";import{w as W,a as be,b as vt}from"./stream-idle-C7CsIT_m.mjs";import{resolveQueryCacheAdapter as gt,queryCacheKey as P}from"./createInMemoryQueryCache-B5wX-gTy.mjs";import{createReconnect as ve}from"./createReconnect-CjTmjJDH.mjs";import{fanSubscriptionError as I,SubscriptionRegistry as E,wrapSubscriber as $}from"./SubscriptionRegistry-DKIXE7M7.mjs";import Tt from"./createSnapshotPrecondition-CLkxVeN1.mjs";import{createStream as kt}from"./DEFAULT_MAX_BUFFER-Bd-_iyiV.mjs";const V=500,_e=(r,e)=>{if(r.size<e)return;const t=r.keys().next().value;t!==void 0&&r.delete(t)},_="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",Ct=r=>{let e="",t=0;const s=r.length-2;for(;t<s;t+=3){const n=r[t]<<16|r[t+1]<<8|r[t+2];e+=_.charAt(n>>18&63)+_.charAt(n>>12&63)+_.charAt(n>>6&63)+_.charAt(n&63)}const i=r.length-t;if(i===1){const n=r[t]<<16;e+=_.charAt(n>>18&63)+_.charAt(n>>12&63)}else if(i===2){const n=r[t]<<16|r[t+1]<<8;e+=_.charAt(n>>18&63)+_.charAt(n>>12&63)+_.charAt(n>>6&63)}return e};new TextDecoder;const wt=new TextEncoder,At=r=>Ct(wt.encode(JSON.stringify(r))),Et="x-lunora-expect-subject",_t=r=>At({subject:r}),ge=Symbol.for("lunora:session-change"),It="lunora:session-change",Ot="better-auth.message",Rt="signout",Ie=()=>{const r=globalThis;let e=r[ge];return e===void 0&&(e={detach:void 0,listeners:new Set,tab:`${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`},r[ge]=e),e},Pt=()=>"document"in globalThis,Ft=async()=>{const r=[];for(const e of Ie().listeners)try{r.push(e())}catch{}await Promise.allSettled(r)},Lt=(r,e)=>{if(r!==Ot||e===null)return!1;try{const t=JSON.parse(e);return t?.event==="session"&&t.data?.trigger===Rt}catch{return!1}},Mt=r=>{const e=[],t=()=>{Ft().catch(()=>{})};let s;try{s=typeof BroadcastChannel=="function"?new BroadcastChannel(It):void 0}catch{s=void 0}if(s!==void 0){const n=s;n.addEventListener("message",a=>{a.data?.type==="lunora:session-change"&&a.data.tab!==r&&t()}),e.push(()=>{n.close()})}const i=globalThis;if(typeof i.addEventListener=="function"){const n=a=>{Lt(a.key,a.newValue)&&t()};i.addEventListener("storage",n),e.push(()=>{i.removeEventListener?.("storage",n)})}return()=>{for(const n of e)n()}},Ht=r=>{const e=Ie();return e.listeners.add(r),e.detach===void 0&&Pt()&&(e.detach=Mt(e.tab)),()=>{e.listeners.delete(r),e.listeners.size===0&&(e.detach?.(),e.detach=void 0)}},Ut="/_lunora/rpc",z="/_lunora/rpc-batch",J="/_lunora/ws",Nt="/_lunora/admin/shard-traffic",xt="/_lunora/admin/scheduled",Wt="/_lunora/admin/scheduled/status",Bt="/_lunora/admin/scheduled/ws",Dt="/_lunora/admin/scheduled/cancel",Te="/_lunora/admin/scheduled/dead",Qt="/_lunora/admin/scheduled/dead/retry",qt="/_lunora/admin/scheduled/dead/cancel",Kt="/_lunora/admin/workflows/instances",jt="/_lunora/admin/workflows/instance",Gt="/_lunora/admin/workflows/status",ne="/_lunora/admin/storage",$t="/_lunora/admin/storage/url",Vt="/_lunora/admin/storage/buckets",zt="/_lunora/admin/functions",Jt="/_lunora/admin/cron-jobs",Yt="/_lunora/admin/cron-jobs/run",Xt="/_lunora/admin/architecture",Zt="/_lunora/admin/openapi",es="/_lunora/admin/openrpc",ts="/_lunora/admin/global/tables",ss="/_lunora/admin/global/table",is="/_lunora/admin/global/facet",rs="/_lunora/admin/vector/indexes",ns="/_lunora/admin/vector/query",os="/_lunora/admin/logs/archive",as="/_lunora/admin/kv/namespaces",cs="/_lunora/admin/kv/keys",oe="/_lunora/admin/kv/value",ds="/_lunora/admin/auth/users",hs="/_lunora/admin/auth/sessions",us="/_lunora/admin/auth/users/create",ls="/_lunora/admin/auth/users/role",fs="/_lunora/admin/auth/users/ban",ps="/_lunora/admin/auth/users/unban",ms="/_lunora/admin/auth/users/password",ys="/_lunora/admin/auth/users/remove",Ss="/_lunora/admin/auth/users/impersonate",bs="/_lunora/admin/auth/sessions/revoke",vs="/_lunora/admin/auth/sessions/revoke-all",gs="/_lunora/admin/auth/capabilities",Ts="/_lunora/admin/auth/users/update",ks="/_lunora/admin/auth/accounts",Cs="/_lunora/admin/auth/accounts/unlink",ws="/_lunora/admin/auth/passkeys",As="/_lunora/admin/auth/passkeys/delete",Es="/_lunora/admin/auth/two-factor/disable",_s="/_lunora/admin/auth/organizations",Is="/_lunora/admin/auth/organizations/members",Os="/_lunora/admin/auth/organizations/invitations",Rs="/_lunora/admin/auth/organizations/members/remove",Ps="/_lunora/admin/auth/organizations/invitations/cancel",Fs="/_lunora/admin/auth/config",Ls="/_lunora/admin/auth/sign-up-invitations",Ms="/_lunora/admin/auth/sign-up-invitations/create",Hs="/_lunora/admin/auth/sign-up-invitations/revoke",Us="/_lunora/admin/auth/organizations/create",Ns="/_lunora/admin/auth/organizations/update",xs="/_lunora/admin/auth/organizations/remove",Ws="/_lunora/admin/auth/organizations/members/add",Bs="/_lunora/admin/auth/organizations/members/invite",Ds="/_lunora/admin/auth/organizations/members/role",Qs="/_lunora/admin/auth/organizations/teams",qs="/_lunora/admin/auth/organizations/teams/create",Ks="/_lunora/admin/auth/organizations/teams/update",js="/_lunora/admin/auth/organizations/teams/remove",Gs="/_lunora/admin/auth/organizations/teams/members",$s="/_lunora/admin/auth/organizations/teams/members/add",Vs="/_lunora/admin/auth/organizations/teams/members/remove",zs="/_lunora/admin/auth/organizations/roles",Js="/_lunora/admin/auth/organizations/roles/create",Ys="/_lunora/admin/auth/organizations/roles/update",Xs="/_lunora/admin/auth/organizations/roles/remove",Zs="/api/auth",ei="/get-session",ti="lunora-ping",si=async r=>(r.assertOpen(),(await r.adminFetch(zt,"GET")).functions??[]),ii=async r=>(r.assertOpen(),(await r.adminFetch(Jt,"GET")).jobs??[]),ri=async(r,e)=>{r.assertOpen();const t=await r.adminFetch(Yt,"POST",{name:e});return{name:t.name??e,ran:t.ran===!0}},ni=async r=>(r.assertOpen(),await r.adminFetch(Zt,"GET")),oi=async r=>(r.assertOpen(),await r.adminFetch(Xt,"GET")),ai=async r=>(r.assertOpen(),await r.adminFetch(es,"GET")),ci=async r=>(r.assertOpen(),await r.adminFetch(ts,"GET")),di=async(r,e)=>{r.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(B(e.filters))),k(await r.adminFetch(`${ss}?${t.toString()}`,"GET"))},hi=async(r,e)=>{r.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(B(e.filters))),k(await r.adminFetch(`${is}?${t.toString()}`,"GET"))},ui=async r=>(r.assertOpen(),(await r.adminFetch(as,"GET")).namespaces??[]),li=async(r,e)=>{r.assertOpen();const t=v(cs,{cursor:e.cursor,limit:e.limit,namespace:e.namespace,prefix:e.prefix});return await r.adminFetch(t,"GET")},fi=async(r,e)=>{r.assertOpen();const t=v(oe,{key:e.key,namespace:e.namespace});return await r.adminFetch(t,"GET")},pi=async(r,e)=>{r.assertOpen(),await r.adminFetch(oe,"PUT",e)},mi=async(r,e)=>{r.assertOpen();const t=v(oe,{key:e.key,namespace:e.namespace});await r.adminFetch(t,"DELETE")},yi=async(r,e)=>{r.assertOpen();const t=await r.adminFetch(Nt,"POST",{table:e});return{failed:t.failed??0,ok:t.ok??0,shards:t.shards??[]}},Si=async(r,e={})=>{r.assertOpen();const t=await r.adminFetch(os,"POST",e);return{nextCursor:t.nextCursor,rows:t.rows??[]}},bi=async r=>{const e=[];let t;for(;;){const s=await r(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}},ae=r=>"args"in r?{...r,args:k(r.args)}:r,vi=async r=>(r.assertOpen(),((await r.adminFetch(xt,"GET")).records??[]).map(t=>ae(t))),gi=async r=>{r.assertOpen();const e=await r.adminFetch(Wt,"GET");return{backlog:e.backlog??0,inFlight:e.inFlight??0,pools:e.pools??[]}},Ti=async(r,e)=>(r.assertOpen(),{cancelled:(await r.adminFetch(Dt,"POST",{id:e})).cancelled===!0}),ki=async r=>(r.assertOpen(),(await bi(async t=>await r.adminFetch(t===void 0?Te:`${Te}?cursor=${encodeURIComponent(t)}`,"GET"))).map(t=>ae(t))),Ci=async(r,e)=>(r.assertOpen(),{retried:(await r.adminFetch(Qt,"POST",{id:e})).retried===!0}),wi=async(r,e)=>(r.assertOpen(),{removed:(await r.adminFetch(qt,"POST",{id:e})).removed===!0}),Ai=async(r,e)=>{r.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 r.adminFetch(`${Kt}?${t.toString()}`,"GET");return{configured:s.configured,instances:s.instances??[],page:s.page??1,perPage:s.perPage??e.perPage??0,totalCount:s.totalCount}},Ei=async(r,e)=>{r.assertOpen();const t=new URLSearchParams({id:e.id,name:e.name}),s=await r.adminFetch(`${jt}?${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??[]}},_i=async(r,e)=>(r.assertOpen(),{status:(await r.adminFetch(Gt,"POST",{action:e.action,id:e.id,name:e.name})).status??"unknown"}),Ii=async(r,e={})=>{r.assertOpen();const t=v(ne,{bucket:e.bucket,cursor:e.cursor,limit:e.limit,prefix:e.prefix}),s=await r.adminFetch(t,"GET");return{cursor:s.cursor,objects:s.objects??[]}},Oi=async(r,e,t)=>{r.assertOpen();const s=`${ne}?key=${encodeURIComponent(e)}${re(t?.bucket)}`,i=await r.adminFetch(s,"DELETE");return{deleted:i.deleted===!0,key:i.key??e}},Ri=async r=>(r.assertOpen(),(await r.adminFetch(Vt,"GET")).buckets??[]),Pi=async(r,e)=>{r.assertOpen();const t=`${ne}?key=${encodeURIComponent(e.key)}${re(e.bucket)}`,s=await r.adminFetch(t,"PUT",e.body,e.contentType);return{etag:s.etag,key:s.key??e.key}},Fi=async(r,e,t)=>{r.assertOpen();const s=t?.expiresInSeconds,i=s===void 0?"":`&expiresIn=${encodeURIComponent(s.toString())}`,n=`${$t}?key=${encodeURIComponent(e)}${i}${re(t?.bucket)}`,a=await r.adminFetch(n,"GET");if(typeof a.url!="string")throw new TypeError("LunoraClient: storage URL endpoint returned no `url`");return a.url},Li=async r=>(r.assertOpen(),(await r.adminFetch(rs,"GET")).indexes??[]),Mi=async(r,e)=>(r.assertOpen(),(await r.adminFetch(ns,"POST",e)).matches??[]),w=(r,e)=>{try{return B(r)}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)}},ke=r=>{try{return B(r),!0}catch{return!1}},Oe=r=>r!==null&&typeof r=="object"&&("error"in r||"result"in r),Hi=(r,e)=>{const t=Array.from({length:e});for(const s of r){if(typeof s.id!="number"||s.id<0||s.id>=e)continue;if(!Oe(s.body)){t[s.id]={error:Z({}),ok:!1};continue}const i=s.body;t[s.id]="error"in i?{error:Z(i),ok:!1}:{ok:!0,value:k(i.result)}}return t.map(s=>s??{error:new Error("batch call returned no result"),ok:!1})},Y=(r,e)=>e!==null?{}:r===null?{expectSubject:null}:r?.startsWith("subj:")===!0?{expectSubject:r.slice(5)}:{},q=r=>r==="connected"||r==="polling",l=r=>r??"",T=(r,e)=>{if(!r.socket||r.wsState!=="open")return!1;try{return r.socket.send(JSON.stringify(e)),!0}catch{return!1}},Ui=r=>{if(!r.pendingStreams||r.pendingStreams.length===0)return;const e=r.pendingStreams;r.pendingStreams=[];for(const t of e)T(r,t)},Ni=new TextDecoder,xi=r=>{if(typeof r=="string")return r;if(r instanceof ArrayBuffer)return Ni.decode(r)};class R{listeners=new Set;get size(){return this.listeners.size}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 L=r=>{r.heartbeatTimer!==void 0&&(clearInterval(r.heartbeatTimer),r.heartbeatTimer=void 0)},Wi=(r,e,t)=>{L(r),!(e<=0)&&(r.heartbeatTimer=setInterval(()=>{if(!r.socket)return;const{socket:s}=r;if(Date.now()-r.lastFrameAt>e*2.5){try{s.close()}catch{}t();return}try{s.send(ti)}catch{}},e))},Ce=(r,e,t,s)=>{const{WebSocketImpl:i,connectTimeoutMs:n,heartbeatIntervalMs:a}=t;if(i===void 0)throw new S("INTERNAL","no WebSocket implementation available");const o=new i(e);r.socket=o;const c=()=>{L(r),r.connectTimer!==void 0&&(clearTimeout(r.connectTimer),r.connectTimer=void 0),r.socket===o&&(r.socket=void 0)},h=d=>{c(),s.onClose(d)};n>0&&(r.connectTimer=setTimeout(()=>{if(r.connectTimer=void 0,r.socket===o){try{o.close()}catch{}h()}},n)),o.addEventListener("open",()=>{if(r.socket===o){r.connectTimer!==void 0&&(clearTimeout(r.connectTimer),r.connectTimer=void 0),r.lastFrameAt=Date.now();try{s.onOpen?.()}catch(d){console.error("[lunora] connection open handler threw",d)}r.socket===o&&Wi(r,a,h)}}),o.addEventListener("message",d=>{if(r.socket===o){r.lastFrameAt=Date.now();try{s.onMessage(d)}catch(u){console.error("[lunora] server frame handler threw",u)}}}),o.addEventListener("close",d=>{r.socket===o&&h(d)}),o.addEventListener("error",()=>{r.socket===o&&h()})},Bi=r=>{const{afterFailedAttempts:e,intervalMs:t,onReachable:s,onStateChange:i,poll:n}=r,a=t>0&&e>0;let o=0,c,h=!1,d=!1;const u=()=>{c!==void 0&&(clearInterval(c),c=void 0,h=!1,i())},p=m=>{if(c!==void 0){if(!m){u();return}h||(h=!0,i()),s()}},f=()=>{d||(d=!0,n().then(p).finally(()=>{d=!1}).catch(()=>{}))};return{isPolling:()=>c!==void 0&&h,noteFailedOpen:()=>{o+=1,!(!a||c!==void 0||o<e)&&(c=setInterval(f,t),i(),f())},noteOpen:()=>{o=0,u()},stop:u}},Di=1e4,we=async r=>W(Di,void 0,r,()=>new TypeError("LunoraClient: poll timed out")),Re=new Set(["DELIVERY_FENCED","RATE_LIMITED","SHARD_ERROR","SHARD_UNAVAILABLE","TOO_MANY_REQUESTS"]),Ae=r=>{if(r instanceof M)return!0;const e=r?.code;return e===void 0||Re.has(e)||ht.has(e)},Qi=1e3,Pe=6e4,qi={401:"UNAUTHORIZED",403:"FORBIDDEN",404:"NOT_FOUND",413:"PAYLOAD_TOO_LARGE",429:"TOO_MANY_REQUESTS"},x=(r,e,t)=>{const s=Ke(t),i=s===void 0?void 0:{retryAfterMs:s},n=`LunoraClient: response carried no error envelope (status ${r.toString()}${e?` ${e}`:""})`;return r<400||r>=500||r===408?new M(n,i):new S(qi[r]??"BAD_REQUEST",n,{data:i})},te=(r,e=Math.random)=>{const t=Math.min(Qi*2**Math.max(r-1,0),Pe);return Math.round(t*(.5+e()*.5))},Ki=r=>{const e=r?.code;return r instanceof M||e===void 0||Re.has(e)},ji=(r,e,t)=>{const s=dt(r);return s!==void 0&&s>0?Math.min(s,Pe):Ki(r)?te(e,t):void 0},Gi=983040,$i=r=>typeof TextEncoder>"u"?r.length:new TextEncoder().encode(r).length,Fe=new WeakSet,Le=r=>{const e=new S("WIRE_DECODE_FAILED",`LunoraClient: the call succeeded but its result could not be decoded (a mutation has still committed) — ${r instanceof Error?r.message:String(r)}`,{cause:r});return Fe.add(e),e},K=r=>r instanceof Error&&Fe.has(r),Vi=r=>{const e=new Map;for(const t of r)typeof t.id=="number"&&Oe(t.body)&&e.set(t.id,t.body);return e},zi=r=>{if(r===void 0)return{kind:"unanswered"};if("error"in r)return{error:Z(r),kind:"errored"};try{return{commitCursor:r.commitCursor,kind:"committed",value:k(r.result)}}catch(e){return{commitCursor:r.commitCursor,error:Le(e),kind:"undecodable"}}},X=(r,e)=>`${l(r)}\0${e}`,Ji=(r,e)=>{for(const t of e)t.op==="delete"?r.delete(t.key):t.value!==void 0&&r.set(t.key,t.value)};class Yi{constructor(e){this.maxBuffers=e}maxBuffers;buffers=new Map;start(e,t){_e(this.buffers,this.maxBuffers),this.buffers.set(X(e,t.pokeId),{baseCheckpoint:t.baseCheckpoint,bases:new Map,epoch:t.epoch,lastMutationId:new Map,parts:new Map,resets:new Set,undecodable:new Map})}part(e,t){const s=this.buffers.get(X(e,t.pokeId));if(!s)return;const i=[];try{for(const o of t.rowsPatch)i.push(o.value===void 0?o:{...o,value:k(o.value)})}catch(o){s.undecodable.set(t.shapeId,o);return}const n=s.parts.get(t.shapeId)??[];for(const o of i)n.push(o);s.parts.set(t.shapeId,n),t.lastMutationId!==void 0&&s.lastMutationId.set(t.shapeId,t.lastMutationId);const a=t.baseCheckpoint??s.baseCheckpoint;a!==void 0&&s.bases.set(t.shapeId,a),t.reset===!0&&s.resets.add(t.shapeId)}end(e,t){const s=X(e,t),i=this.buffers.get(s);return i&&this.buffers.delete(s),i}clear(){this.buffers.clear()}}const Xi=(r,e,t)=>{const s=e.parts.get(r.id)??[],i=e.resets.has(r.id),n=e.bases.get(r.id),a=e.epoch!==void 0&&r.serverEpoch!==void 0&&e.epoch!==r.serverEpoch,o=n!==void 0&&r.serverCursor!==void 0&&r.serverCursor!==n;if(!i&&(a||o))return r.rows.clear(),r.serverCursor=void 0,r.serverEpoch=void 0,r.answered=!1,"reseed";i&&r.rows.clear(),Ji(r.rows,s),r.answered=!0,t.checkpoint!==void 0&&(r.serverCursor=t.checkpoint),t.epoch!==void 0&&(r.serverEpoch=t.epoch);const c=e.lastMutationId.get(r.id);return c!==void 0&&(r.lastMutationId=c),"applied"},Ee=r=>{const e=[...r.rows.values()];for(const t of r.callbacks)try{t(e)}catch{}},Zi=(r,e)=>{for(const[t,s]of e.undecodable){const i=r.get(t);i&&I(i.errorCallbacks,{code:"WIRE_DECODE_FAILED",message:`could not decode a poke for this shape — ${s instanceof Error?s.message:String(s)}`})}},se=(r,e)=>{r.lastMutationId=Math.max(r.lastMutationId??0,e)},ie=(r,e=!1)=>{for(const t of r.checkpointCallbacks)t({checkpoint:r.serverCursor,mutationId:r.lastMutationId,...e&&{rowsFollow:!0}})},Me=(r,e,t)=>{r.serverBase=e,t.cursor!==void 0&&(r.serverCursor=t.cursor),t.epoch!==void 0&&(r.serverEpoch=t.epoch)},er=(r,e)=>e.cursor!==void 0&&r.serverCursor!==void 0&&r.serverBase!==void 0&&e.epoch!==void 0&&e.epoch===r.serverEpoch&&e.cursor<r.serverCursor,j=(r,e)=>r!==void 0&&r!==e,tr=(r,e)=>e==="connected"&&r!=="connected"||e==="polling"&&r!=="connected"&&r!=="polling",sr=r=>{for(const e of r.activeSubscriptions())e.valueReceived=!1,r.ensureSocket(e.shardKey),r.queueResubscribe(e);for(const e of r.activeShapes())e.answered=!1,r.ensureSocket(e.shardKey);for(const e of r.queuedShardKeys())r.ensureSocket(e);r.broadcastStatus(r.computeStatus(),r.identityFingerprint()),r.emitConnectionStatus()},ir=r=>{r.closeConnections();const e=r.leader;e.status=void 0,e.wasEverConnected=!1;for(const t of r.activeSubscriptions())t.acked=!1,t.valueReceived=!1;for(const t of r.activeShapes())t.answered=!1;r.emitConnectionStatus()},rr=(r,e,t)=>{if(j(t,r.identityFingerprint()))return;const s=r.leader,i=tr(s.status,e);s.status=e,e==="connected"&&(s.wasEverConnected=!0),r.emitConnectionStatus(),i&&r.flushOfflineQueues()},nr=r=>{r.isLeader()&&r.broadcastStatus(r.computeStatus(),r.identityFingerprint())},or=(r,e,t,s,i,n)=>{if(j(n,r.identityFingerprint()))return;const a=r.subscription(e);if(!a)return;r.dropCacheSeed(e);const o=!a.valueReceived;a.valueReceived=!0,Me(a,t,s===void 0?{}:{cursor:s,epoch:i}),s!==void 0&&ee(a,s),F(a,t),o&&r.emitConnectionStatus()},ar=(r,e,t,s)=>{if(j(s,r.identityFingerprint()))return;const i=r.subscription(e);if(i){const n=!i.valueReceived;i.valueReceived=!0,I(i.errorCallbacks,t),n&&r.emitConnectionStatus()}},cr=(r,e,t,s,i,n,a)=>{if(j(a,r.identityFingerprint()))return;const o=r.subscription(e);o&&(r.ackAndAdvanceCursor(o,t,s),i!==void 0&&n===r.clientIdentifier()&&se(o,i),ie(o))},dr=(r,e,t)=>r!==null||e&&t===null,hr=[Qe],ur=100,He=1e4,lr=async(r,e,t,s)=>{const i=new AbortController,n=setTimeout(()=>{i.abort()},He);try{const a=await r(e,{body:t,credentials:"include",headers:s,method:"POST",signal:i.signal});return await a.text(),a.status}finally{clearTimeout(n)}},fr=Promise.resolve();class Ue{static MAX_POKE_BUFFERS=256;static createClientQuery(e,t){return{defaultValue:t,key:e}}url;wsUrl;adminHost={adminFetch:(...e)=>this.adminFetch(...e),assertOpen:()=>{this.assertOpen()}};clientQueryStore;wsToken;wsTokenGeneration=0;authBasePath;fetchImpl;WebSocketImpl;bookmark;reconnectOptions;connectTimeoutMs;heartbeatIntervalMs;rpcTimeoutMs;managedSocketOptions;pollingFallbackAfterFailedAttempts;pollingFallbackIntervalMs;offlineQueue;outbox;clientId;shardCursors=new Map;defaultShardKey;readyResolved=!1;readyResolve;readyPromise;clientWatermarks=new Map;outboxMutationCounter=0;mutationIssueCounter=0;persistence;persistenceVersion;releasePageHideFlush;outboxLeaderRelease;queryCache;hydratedQueryCache=new Map;cacheSeededQueries=new Map;pendingCacheWrites=new Map;cacheFlushTimer;subscriptions=new E;tabCoordinator;leader={status:void 0,wasEverConnected:!1};connections=new Map;idleClosedShards=new Set;defaultConnectionContext;connectionContexts=new Map;connectionContextHolders=new Map;authToken=null;authSubject=void 0;subjectToken=null;sessionProbesInFlight=0;sessionProbeGeneration=0;identityQuestions=0;identityAnsweredAt=0;releaseSessionChangeListener;warnedIdentityDisagreement=!1;identityResolutionExpected=!1;identitySettled=!1;queuedIdentities=new Map;queuedOfflineShardKeys=new Set;closed=!1;authTokenListeners=new R;statusListeners=new R;roomFlushes=new Map;roomIdentityResets=new Set;tokenExpiredListeners=new R;identityChangeListeners=new R;retiredIdentities=0;authRefusalNotifiedFor;replayCredentials=new WeakMap;mutationSettledListeners=new R;pendingChangeListeners=new R;syncStatusListeners=new R;lastSyncStatus;whisperHandlers=new Map;liveSocketGrants=new Map;liveControlChain=Promise.resolve();whisperJoins=new Map;nextLiveSocketId=0;lastStatus="idle";nextSubId=0;nextStreamId=0;streams=new Map;adminSocketTeardowns=new Set;supplementaryBounces=new Set;offlineFlushes=new Map;replayRetryState=new Map;replayAttempts=new Map;replayRetryTimers=new Map;shapeSubscriptions=new Map;pokeAssembler=new Yi(Ue.MAX_POKE_BUFFERS);nextShapeId=0;constructor(e){this.url=e.url,this.wsUrl=e.wsUrl??C(ue(e.url),J),this.wsToken=e.wsToken;const t=e.authBasePath??Zs;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??qe(),this.reconnectOptions=e.reconnect,this.heartbeatIntervalMs=e.heartbeatIntervalMs??Je,this.connectTimeoutMs=e.connectTimeoutMs??Ye,this.rpcTimeoutMs=e.rpcTimeoutMs??Xe,this.managedSocketOptions={connectTimeoutMs:this.connectTimeoutMs,heartbeatIntervalMs:this.heartbeatIntervalMs,WebSocketImpl:this.WebSocketImpl},this.pollingFallbackIntervalMs=e.pollingFallback?.intervalMs??Ze,this.pollingFallbackAfterFailedAttempts=e.pollingFallback?.afterFailedAttempts??et,this.defaultConnectionContext=e.connectionContext,this.persistence=bt(e.persistence,e.outbox===void 0),this.persistenceVersion=e.persistenceVersion,this.queryCache=gt(e.queryCache),this.clientQueryStore=new ze,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=fr),this.offlineQueue=new yt(e.offlineQueue,{onEvict:(s,i)=>{this.emitItemSettled(s,"rejected",i),this.releaseIdleShard(s.shardKey)},onReplayingChange:()=>{this.emitSyncStatus()},onSizeChange:s=>{this.pendingChangeListeners.emit(s),this.emitSyncStatus()},persistence:this.persistence,version:e.persistenceVersion}),this.outbox=e.outbox,this.clientId=e.clientId??`client-${Se()}`,this.persistence&&queueMicrotask(()=>{this.hydrateAsOutboxLeader()}),this.installPageHideFlush(),this.queryCache&&queueMicrotask(()=>{(async()=>{try{await this.hydrateQueryCache()}catch{}finally{this.readyResolved=!0,this.readyResolve?.()}})().catch(()=>{})}),"document"in globalThis&&(this.releaseSessionChangeListener=Ht(async()=>{!this.closed&&this.authToken===null&&await this.getCurrentUser().catch(()=>{})}))}setAuthToken(e,t){const s=this.authToken!==e,i=this.identityFingerprint(),n=this.authSubject===void 0||this.subjectToken===this.authToken,a=this.subjectAwaitingReconfirm(),o=this.isKnownNobody(),c=this.authToken;this.authToken=e,this.applySubject(e,t);const h=this.identityFingerprint();h!==i&&(!s&&e!==null&&n?(this.restampQueuedIdentity(i,h),this.restampWatermarks(i,h),this.restampConnectionIdentity(i,h),this.reseedFromHydratedCache()):!s&&e===null&&i===null&&n&&!o?(this.restampWatermarks(i,h),this.restampConnectionIdentity(i,h),this.reseedFromHydratedCache()):(this.rejectQueuedForIdentityChange(i),this.warnRefreshWithoutSubject(c,e),dr(i,o,e)&&this.evictPreviousIdentitySession()),this.restartTabCoordinatorForIdentity()),this.syncReadCacheToCredential(a),s&&this.authTokenListeners.emit(e),(h!==i||s||a)&&this.offlineQueue.size>0&&q(this.computeStatus())&&this.flushAllOfflineQueues()}getAuthToken(){return this.authToken}currentIdentity(){return this.identityFingerprint()}expectIdentityResolution(){this.identityResolutionExpected=!0}currentBaseline(e){return this.baselineCursorFor(e)}replayIdentityVerdict(e){const t=this.identityVerdict(e);if(t!=="match")return{verdict:t};const s=Object.freeze({});return this.replayCredentials.set(s,{authToken:this.authToken,stamp:e}),{credential:s,verdict:t}}clientIdentifier(){return this.clientId}confirmedMutationWatermark(e){return this.clientWatermarks.get(this.identityFingerprint()??"")?.get(e??"")??0}async callMutator(e,t,s){const i=s?.clientSeq;if(i!==void 0&&(!Number.isInteger(i)||i<=0))throw new S("INTERNAL",`callMutator: clientSeq must be a positive integer, got ${String(i)}`);const n=s?.shardKey??"",a=this.identityFingerprint();let o,c,h;try{c=await this.rpc(e,t,s?.shardKey,{captureBookmark:!0,clientId:this.clientId,clientSeq:i,onMutationAck:u=>{o=u}})}catch(u){if(!K(u))throw u;h=u}if(o!==void 0&&o>(this.clientWatermarks.get(a??"")?.get(n)??0)){let u=this.clientWatermarks.get(a??"");u===void 0&&(_e(this.clientWatermarks,at),u=new Map,this.clientWatermarks.set(a??"",u)),u.set(n,o)}if(h!==void 0)throw h;return{applied:o===void 0||o===i,result:c}}onAuthTokenChange(e){return this.authTokenListeners.add(e)}onIdentityChange(e){return this.identityChangeListeners.add(e)}identityEpoch(){return this.retiredIdentities}async getCurrentUser(){if(this.identityResolutionExpected=!0,this.closed||!this.fetchImpl)return this.identitySettled=!0,null;const e={},t=this.authToken;this.authToken&&(e.authorization=`Bearer ${this.authToken}`),this.sessionProbesInFlight+=1,this.identityQuestions+=1,this.sessionProbeGeneration=this.identityQuestions;const s=this.sessionProbeGeneration;try{const i=await this.fetchImpl(C(this.url,`${this.authBasePath}${ei}`),{credentials:"include",headers:e,method:"GET"});if(!i.ok)return this.identitySettled=!0,i.status===401&&this.adoptResolvedSubject(t,null,s),null;const a=(await i.json())?.user??null;return this.identitySettled=!0,this.adoptResolvedSubject(t,a,s),a}finally{this.releaseSessionProbe()}}setWsToken(e){this.wsToken!==e&&(this.wsToken=e,this.wsTokenGeneration+=1,this.resetRoomSends(),this.bounceShardSockets())}setConnectionContext(e,t={}){this.assertLeaderOwnedSurface("setConnectionContext");const s=l(t.shardKey);e===void 0?this.connectionContexts.delete(s):this.connectionContexts.set(s,e),this.refreshConnectionContext(s),e===void 0&&this.releaseIdleShard(t.shardKey)}acquireConnectionContext(e,t={}){if(this.followsAnotherTab())return()=>{};const s=l(t.shardKey),i={context:e},n=this.connectionContextHolders.get(s);n?n.push(i):this.connectionContextHolders.set(s,[i]),this.refreshConnectionContext(s);let a=!1;return()=>{if(a)return;a=!0;const o=this.connectionContextHolders.get(s);if(!o)return;const c=o.indexOf(i);c!==-1&&o.splice(c,1),o.length===0&&this.connectionContextHolders.delete(s),this.refreshConnectionContext(s),this.releaseIdleShard(t.shardKey)}}whisperSubscribe(e,t,s={}){this.assertLeaderOwnedSurface("whisperSubscribe");const i=l(s.shardKey);let n=this.whisperHandlers.get(i);n||(n=new Map,this.whisperHandlers.set(i,n));let a=n.get(e);const o=a===void 0;if(a||(a=new Set,n.set(e,a)),a.add(t),this.ensureSocket(s.shardKey),o){const c=this.getConnection(s.shardKey);c&&this.sendWhisperJoin(c,i,e)}return()=>{const c=this.whisperHandlers.get(i),h=c?.get(e);if(!h?.delete(t)||h.size>0)return;c?.delete(e),c?.size===0&&this.whisperHandlers.delete(i);const d=this.getConnection(s.shardKey);d&&T(d,{topic:e,type:"whisper_unsubscribe"}),this.releaseWhisperJoin(i,e),this.releaseIdleShard(s.shardKey)}}subscribeLiveTopic(e){const{onError:t,onEvent:s,shardKey:i,stream:n,topic:a}=e;if(a.length===0)throw new S("INTERNAL","LunoraClient: subscribeLiveTopic needs a non-empty topic");this.nextLiveSocketId+=1;const o=`ws-live-${String(this.nextLiveSocketId)}`,c=l(i),h=`/live/${n}/control`;let u=this.whisperSubscribe(a,()=>{},{shardKey:i});const p=()=>{const y=u;u=void 0,y?.()};let f=this.liveSocketGrants.get(c);f===void 0&&(f=new Map,this.liveSocketGrants.set(c,f)),f.set(o,{onError:t,onEvent:s,release:p,stream:n,topic:a});const m=this.getConnection(i)?.connectionId;m!==void 0&&this.grantWhenJoined(i,o,m);let b=!1;return()=>{if(b)return;b=!0;const y=this.liveSocketGrants.get(c),O=y?.delete(o)===!0;y?.size===0&&this.liveSocketGrants.delete(c);const g=this.getConnection(i)?.connectionId;O&&g!==void 0&&this.postLiveControl(h,i,{action:"unsubscribe",connectionId:g,stream:n,subscriptionId:o,topic:a}),p()}}whisper(e,t,s={}){return this.assertLeaderOwnedSurface("whisper"),this.sendEncodedWhisper(e,w(t??null,`whisper data for topic '${e}'`),s)}connectRoom(e,t,s={}){const i=`room:${e.name}`,n=this.whisperSubscribe(i,p=>{t.onMessage(p)},s);let a=!1;const o=[],c=()=>{o.length=0},h=()=>{for(;o.length>0&&this.roomSendsAdmitted(s.shardKey);){if(!this.sendEncodedWhisper(i,o[0],s))return;o.shift()}},d=l(s.shardKey),u=this.roomFlushes.get(d)??new Set;return u.add(h),this.roomFlushes.set(d,u),this.roomIdentityResets.add(c),{close:()=>{a=!0,o.length=0,u.delete(h),u.size===0&&this.roomFlushes.delete(d),this.roomIdentityResets.delete(c),n()},send:p=>{if(a||this.closed||this.WebSocketImpl===void 0)return!1;const f=w(p,`room message for '${i}'`),m=typeof structuredClone=="function"?structuredClone(f):JSON.parse(JSON.stringify(f));return h(),o.length===0&&this.roomSendsAdmitted(s.shardKey)&&this.sendEncodedWhisper(i,m,s)?!0:o.length>=ur?!1:(o.push(m),!0)}}}connectWebSocket(e,t,s={}){if(this.assertLeaderOwnedSurface("connectWebSocket"),this.WebSocketImpl===void 0||this.closed)return{close:()=>{},send:()=>{}};const i=o=>{try{o?.()}catch(c){console.error("[lunora] socket route handler threw",c)}};let n;const a=this.openSupplementarySocket(this.supplementaryUrl(e),{onClose:()=>{clearTimeout(n),i(t.onClose)},onMessage:o=>{let c;try{c=JSON.parse(typeof o.data=="string"?o.data:"")}catch{return}c.type==="message"&&(a.resetBackoff(),i(()=>{t.onMessage(k(c.data))}))},onOpen:()=>{clearTimeout(n);const o=a.socket();n=setTimeout(()=>{a.socket()===o&&a.resetBackoff()},ye),i(t.onOpen)},shardKey:s.shardKey});return{close:()=>{clearTimeout(n),a.close()},send:o=>{const c=JSON.stringify(w(o,`socket message for '${e}'`)),h=a.socket();if(h!==void 0)try{h.send(c)}catch{}}}}onTokenExpired(e){return this.tokenExpiredListeners.add(e)}connectionStatus(){return this.computeStatus()}onConnectionStatus(e){const t=this.statusListeners.add(e);return e(this.computeStatus()),t}syncStatus(){const e=this.computeStatus(),t=this.tabCoordinator!==void 0&&!this.tabCoordinator.isLeader();let s=0;for(const n of this.subscriptions.all())(t||this.connectionGateState(n.shardKey).polling?n.valueReceived:n.acked)||(s+=1);for(const n of this.shapeSubscriptions.values())n.answered||(s+=1);const i=this.offlineQueue.size+this.offlineQueue.replaying;return{connection:e,pendingSubscriptions:s,pendingWrites:i,synced:q(e)&&s===0&&i===0}}onSyncStatus(e){const t=this.syncStatusListeners.add(e),s=this.syncStatus();return this.lastSyncStatus=s,e(s),t}pendingCount(){return this.offlineQueue.size}debug(){const e=[],t=this.clientWatermarks.get(this.identityFingerprint()??""),s=new Set([...this.connections.keys(),...t?.keys()??[]]);for(const n of s){const a=this.connections.get(n);e.push({confirmedMutationWatermark:t?.get(n)??0,hasSocket:a?.socket!==void 0,shardKey:n===""?void 0:n,wasEverConnected:a?.wasEverConnected??!1,wsState:a?.wsState??"idle"})}const i=this.subscriptions.all().map(n=>({acked:n.acked,functionPath:n.fn.__lunoraRef,id:n.id,kind:"query",lastMutationId:n.lastMutationId,pendingOptimisticLayers:n.optimisticLayers.length,serverCursor:n.serverCursor,shardKey:n.shardKey,subscriberCount:n.callbacks.size}));for(const n of this.shapeSubscriptions.values())i.push({acked:n.answered,functionPath:`shape:${n.name}`,id:n.id,kind:"shape",lastMutationId:n.lastMutationId,pendingOptimisticLayers:0,rowCount:n.rows.size,serverCursor:n.serverCursor,shardKey:n.shardKey,subscriberCount:n.callbacks.size});return{clientId:this.clientId,closed:this.closed,connectionStatus:this.computeStatus(),pendingWrites:this.offlineQueue.size,shards:e.toSorted((n,a)=>(n.shardKey??"").localeCompare(a.shardKey??"")),subscriptions:i.toSorted((n,a)=>n.functionPath.localeCompare(a.functionPath))}}onPendingChange(e){const t=this.pendingChangeListeners.add(e);return e(this.offlineQueue.size),t}onMutationSettled(e){return this.mutationSettledListeners.add(e)}getWebSocketImpl(){return this.WebSocketImpl}getClientQuery(e){return this.clientQueryStore.get(e)}setClientQuery(e,t){this.clientQueryStore.set(e,t)}subscribeClientQuery(e,t){return this.clientQueryStore.subscribe(e,t)}resetClientQuery(e){this.clientQueryStore.reset(e)}snapshotPrecondition(e,t,s){return Tt(this,e,t,s)}whenReady(e={}){return e.signal===void 0?this.readyPromise:be(this.readyPromise,e.signal)}get isReady(){return this.readyResolved}peekHydratedQuery(e,t,s){return this.peekHydratedQueryByKey(e,he(t),s)}peekHydratedQueryByKey(e,t,s){if(!this.readyResolved)return;const i=P(e,t,s),n=this.hydratedQueryCache.get(i);if(n!==void 0)return this.cachedQueryMatchesIdentity(n)?n.value:void 0}peekActiveQuerySnapshot(e,t,s){const i=E.key(e,t,s),n=this.subscriptions.get(i);return{present:n!==void 0,value:n?.lastValue}}async query(e,t,s={}){return this.assertOpen(),await this.rpc(e.__lunoraRef,t,s.shardKey,{attachBookmark:!0,signal:s.signal})}async batch(e){return W(this.rpcTimeoutMs,void 0,async t=>this.sendBatch(e,t))}async mutation(e,t,s={}){if(s.signal?.aborted)throw vt(s.signal);const{value:i}=await be(this.runMutation(e,t,s),s.signal);return i}canQueueOffline(e){const{wasEverConnected:t}=this.connectionGateState(e);return this.WebSocketImpl!==void 0&&(t||this.offlineQueue.queueBeforeFirstConnect)}async action(e,t,s={}){return this.assertOpen(),await this.rpc(e.__lunoraRef,t,s.shardKey,{attachBookmark:!0,captureBookmark:!0,signal:s.signal,unbounded:!0})}async importRows(e,t,s={}){this.assertOpen();const i=Math.max(1,Math.trunc(s.chunkSize??500)),n=s.toArgs??(d=>({rows:d})),a=t.length;let o=0,c=0,h=0;for(let d=0;d<a;d+=i){const u=t.slice(d,d+i),p=h,{committed:f}=await this.runMutation(e,n(u),{...s.importId===void 0?{}:{mutationId:`${s.importId}:${String(p)}`},shardKey:s.shardKey});h+=1,o+=u.length,f&&(c+=u.length),s.onProgress?.({done:o,total:a})}return{chunks:h,imported:c,queued:o-c}}async shardTraffic(e){return yi(this.adminHost,e)}async listScheduledJobs(){return vi(this.adminHost)}async schedulerStatus(){return gi(this.adminHost)}async cancelScheduledJob(e){return Ti(this.adminHost,e)}async listDeadJobs(){return ki(this.adminHost)}async retryDeadJob(e){return Ci(this.adminHost,e)}async removeDeadJob(e){return wi(this.adminHost,e)}async listWorkflowInstances(e){return Ai(this.adminHost,e)}async getWorkflowInstance(e){return Ei(this.adminHost,e)}async setWorkflowInstanceStatus(e){return _i(this.adminHost,e)}subscribeScheduledJobs(e){if(this.assertOpen(),this.WebSocketImpl===void 0)return()=>{};const t=this.openSupplementarySocket(C(ue(this.url),Bt),{onMessage:s=>{let i;try{i=JSON.parse(typeof s.data=="string"?s.data:"")}catch{return}i.type==="jobs"&&Array.isArray(i.records)&&(t.resetBackoff(),e(i.records.map(n=>ae(n))))}});return t.close}async listFunctions(){return si(this.adminHost)}async getCronJobs(){return ii(this.adminHost)}async runCronJob(e){return ri(this.adminHost,e)}async fetchOpenApi(){return ni(this.adminHost)}async fetchArchitecture(){return oi(this.adminHost)}async fetchOpenRpc(){return ai(this.adminHost)}async listStorageObjects(e={}){return Ii(this.adminHost,e)}async deleteStorageObject(e,t){return Oi(this.adminHost,e,t)}async listStorageBuckets(){return Ri(this.adminHost)}async uploadStorageObject(e){return Pi(this.adminHost,e)}async signedStorageUrl(e,t){return Fi(this.adminHost,e,t)}async listGlobalTables(){return ci(this.adminHost)}async readGlobalTablePage(e){return di(this.adminHost,e)}async facetGlobalColumn(e){return hi(this.adminHost,e)}async listVectorIndexes(){return Li(this.adminHost)}async queryVectorIndex(e){return Mi(this.adminHost,e)}async queryLogArchive(e={}){return Si(this.adminHost,e)}async listKvNamespaces(){return ui(this.adminHost)}async listKvKeys(e){return li(this.adminHost,e)}async getKvValue(e){return fi(this.adminHost,e)}async putKvValue(e){return pi(this.adminHost,e)}async deleteKvKey(e){return mi(this.adminHost,e)}async listAuthUsers(e={}){this.assertOpen();const t=v(ds,{filterField:e.filterField,filterValue:e.filterValue,limit:e.limit,offset:e.offset,search:e.search,searchField:e.searchField,sortBy:e.sortBy,sortDirection:e.sortDirection});return await this.adminFetch(t,"GET")}async createAuthUser(e){return this.assertOpen(),await this.adminFetch(us,"POST",e)}async setAuthUserRole(e){return this.assertOpen(),await this.adminFetch(ls,"POST",e)}async banAuthUser(e){return this.assertOpen(),await this.adminFetch(fs,"POST",e)}async unbanAuthUser(e){return this.assertOpen(),await this.adminFetch(ps,"POST",e)}async setAuthUserPassword(e){this.assertOpen(),await this.adminFetch(ms,"POST",e)}async removeAuthUser(e){this.assertOpen(),await this.adminFetch(ys,"POST",e)}async impersonateAuthUser(e){return this.assertOpen(),await this.adminFetch(Ss,"POST",e)}async revokeAuthSession(e){this.assertOpen(),await this.adminFetch(bs,"POST",e)}async revokeAuthUserSessions(e){this.assertOpen(),await this.adminFetch(vs,"POST",e)}async getAuthCapabilities(){return this.assertOpen(),await this.adminFetch(gs,"GET")}async updateAuthUser(e){return this.assertOpen(),await this.adminFetch(Ts,"POST",e)}async listAuthAccounts(e){return this.assertOpen(),await this.adminFetch(v(ks,{userId:e.userId}),"GET")}async unlinkAuthAccount(e){this.assertOpen(),await this.adminFetch(Cs,"POST",e)}async listAuthPasskeys(e){return this.assertOpen(),await this.adminFetch(v(ws,{userId:e.userId}),"GET")}async deleteAuthPasskey(e){this.assertOpen(),await this.adminFetch(As,"POST",e)}async disableAuthTwoFactor(e){this.assertOpen(),await this.adminFetch(Es,"POST",e)}async listAuthOrganizations(e={}){return this.assertOpen(),await this.adminFetch(v(_s,{limit:e.limit,offset:e.offset}),"GET")}async listAuthOrgMembers(e){this.assertOpen();const t=v(Is,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async listAuthOrgInvitations(e){this.assertOpen();const t=v(Os,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async listAuthSignUpInvitations(e={}){this.assertOpen();const t=v(Ls,{limit:e.limit,offset:e.offset});return await this.adminFetch(t,"GET")}async createAuthSignUpInvitation(e){return this.assertOpen(),await this.adminFetch(Ms,"POST",e)}async revokeAuthSignUpInvitation(e){this.assertOpen(),await this.adminFetch(Hs,"POST",e)}async removeAuthOrgMember(e){this.assertOpen(),await this.adminFetch(Rs,"POST",e)}async cancelAuthOrgInvitation(e){this.assertOpen(),await this.adminFetch(Ps,"POST",e)}async getAuthConfig(){return this.assertOpen(),await this.adminFetch(Fs,"GET")}async createAuthOrganization(e){return this.assertOpen(),await this.adminFetch(Us,"POST",e)}async updateAuthOrganization(e){return this.assertOpen(),await this.adminFetch(Ns,"POST",e)}async deleteAuthOrganization(e){this.assertOpen(),await this.adminFetch(xs,"POST",e)}async addAuthOrgMember(e){return this.assertOpen(),await this.adminFetch(Ws,"POST",e)}async inviteAuthOrgMember(e){return this.assertOpen(),await this.adminFetch(Bs,"POST",e)}async setAuthOrgMemberRole(e){return this.assertOpen(),await this.adminFetch(Ds,"POST",e)}async listAuthOrgTeams(e){this.assertOpen();const t=v(Qs,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async createAuthOrgTeam(e){return this.assertOpen(),await this.adminFetch(qs,"POST",e)}async updateAuthOrgTeam(e){return this.assertOpen(),await this.adminFetch(Ks,"POST",e)}async removeAuthOrgTeam(e){this.assertOpen(),await this.adminFetch(js,"POST",e)}async listAuthOrgTeamMembers(e){this.assertOpen();const t=v(Gs,{limit:e.limit,offset:e.offset,teamId:e.teamId});return await this.adminFetch(t,"GET")}async addAuthOrgTeamMember(e){return this.assertOpen(),await this.adminFetch($s,"POST",e)}async removeAuthOrgTeamMember(e){this.assertOpen(),await this.adminFetch(Vs,"POST",e)}async listAuthOrgRoles(e){this.assertOpen();const t=v(zs,{limit:e.limit,offset:e.offset,organizationId:e.organizationId});return await this.adminFetch(t,"GET")}async createAuthOrgRole(e){return this.assertOpen(),await this.adminFetch(Js,"POST",e)}async updateAuthOrgRole(e){return this.assertOpen(),await this.adminFetch(Ys,"POST",e)}async deleteAuthOrgRole(e){this.assertOpen(),await this.adminFetch(Xs,"POST",e)}async listAuthSessions(e={}){this.assertOpen();const t=v(hs,{limit:e.limit,offset:e.offset,userId:e.userId});return await this.adminFetch(t,"GET")}subscribe(e,t,s,i={}){if(this.assertOpen(),i.signal?.aborted)return()=>{};const n=t??{},a=E.key(e.__lunoraRef,n,i.shardKey);let o=this.subscriptions.get(a);const c=$(s),h=$(i.onError),d=$(i.onCheckpoint);if(!o){this.nextSubId+=1;const m=`sub_${this.nextSubId.toString()}`,b=he(n),y=this.takeHydratedCache(e.__lunoraRef,b,i.shardKey);o={acked:!1,args:n,argsKey:b,callbacks:new Set,checkpointCallbacks:new Set,errorCallbacks:new Set,fn:e,id:m,lastValue:y?.value,optimisticLayers:[],serverBase:y?.value,serverCursor:y?.serverCursor,shardKey:i.shardKey,valueReceived:!1,wireArgs:w(n,`args for '${e.__lunoraRef}'`),...y?.serverEpoch===void 0?{}:{serverEpoch:y.serverEpoch}},this.subscriptions.add(o),this.emitSyncStatus(),y!==void 0&&this.cacheSeededQueries.set(a,y)}if(o.callbacks.add(c),h&&o.errorCallbacks.add(h),d&&o.checkpointCallbacks.add(d),o.lastValue!==void 0)try{c(o.lastValue)}catch{}this.ensureSocket(i.shardKey),this.sendSubscribeIfOpen(o);const u=o;let p=!1;const f=()=>{if(!p&&(p=!0,i.signal?.removeEventListener("abort",f),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(E.keyOf(u)),this.subscriptions.remove(u);const m=this.getConnection(u.shardKey);m&&this.settleSubscribeWatchdog(m,u.id),this.releaseIdleShard(u.shardKey),this.emitSyncStatus()}};return i.signal?.addEventListener("abort",f,{once:!0}),i.signal?.aborted&&f(),f}subscribeShape(e,t,s={}){if(this.assertOpen(),this.followsAnotherTab()){const{onError:a}=s;return a!==void 0&&queueMicrotask(()=>{a({code:"NOT_IMPLEMENTED",message:"LunoraClient: `subscribeShape` is unavailable on a cross-tab follower tab. The `crossTabSync` channel only carries data from the leader tab outward and shape pokes are not part of that broadcast set, so this subscription could never resolve. Turn off `crossTabSync`, or use a `list`-backed collection, which IS relayed."})}),()=>{}}this.nextShapeId+=1;const i=`shape_${this.nextShapeId.toString()}`,n={answered:!1,args:e.args,callbacks:new Set([t]),errorCallbacks:s.onError?new Set([s.onError]):new Set,id:i,name:e.name,onCheckpoint:s.onCheckpoint,rows:new Map,shardKey:s.shardKey,wireArgs:e.args===void 0?void 0:w(e.args,`shape args for '${e.name}'`)};return this.shapeSubscriptions.set(i,n),this.emitSyncStatus(),this.ensureSocket(s.shardKey),this.sendShapeSubscribeIfOpen(n),()=>{this.shapeSubscriptions.delete(i),this.sendOrQueueUnsubscribe(n.shardKey,i,"shape_unsubscribe"),this.releaseIdleShard(n.shardKey),this.emitSyncStatus()}}stream(e,t,s={}){if(this.assertOpen(),this.WebSocketImpl===void 0)throw new S("INTERNAL","LunoraClient: streams require a WebSocket implementation");this.nextStreamId+=1;const i=`stream_${this.nextStreamId.toString()}`,{shardKey:n}=s,a=t??{},{handle:o,iterable:c}=kt({maxBuffer:s.maxBuffer,onCancel:()=>{this.cancelStream(i,n)}});this.ensureSocket(n);const h=this.getConnection(n),d={id:i,query:{args:w(a,`stream args for '${e.__lunoraRef}'`),functionPath:e.__lunoraRef,shardKey:n},type:"stream"},u={durable:s.durable===!0,generation:void 0,handle:o,lastSeq:0,message:d,shardKey:n};this.streams.set(i,u);const p=h?.wsState==="open"&&T(h,d);if(!p&&h===void 0)return this.forgetStream(i),o.fail(new S("STREAM_DISCONNECTED","stream unavailable: this tab is not the cross-tab WebSocket leader, so it holds no socket to stream over")),c;if(!p){for(h.pendingStreams=h.pendingStreams??[];h.pendingStreams.length>=tt;){const m=h.pendingStreams.shift()?.id,b=m?this.streams.get(m):void 0;b&&(b.handle.fail(new S("STREAM_QUEUE_OVERFLOW","stream-start frame evicted while socket was unreachable")),this.forgetStream(m))}h.pendingStreams.push(d)}return c}httpStream(e,t,s={}){if(this.closed)throw new S("CLIENT_CLOSED","LunoraClient is closed");if(!this.fetchImpl)throw new S("INTERNAL","LunoraClient: no `fetch` implementation available");const i={...this.authToken?{authorization:`Bearer ${this.authToken}`}:{},...s.headers};return ut(e,t,{baseUrl:this.url,fetch:this.fetchImpl,headers:i,maxBuffer:s.maxBuffer,signal:s.signal})}close(){this.closed=!0;for(const e of this.whisperJoins.keys())this.dropWhisperJoinWaiters(e);this.releaseSessionChangeListener?.(),this.releaseSessionChangeListener=void 0,this.releasePageHideFlush?.(),this.releasePageHideFlush=void 0,this.outboxLeaderRelease?.(),this.outboxLeaderRelease=void 0;for(const e of this.streams.values())e.handle.fail(new S("CLIENT_CLOSED","LunoraClient closed"));this.streams.clear();for(const e of this.connections.values())this.teardownConnection(e);for(const e of this.adminSocketTeardowns)e();this.adminSocketTeardowns.clear(),this.supplementaryBounces.clear();for(const e of this.replayRetryTimers.values())clearTimeout(e);this.replayRetryTimers.clear(),this.replayRetryState.clear(),this.offlineQueue.clear(),this.queuedIdentities.clear(),this.cacheFlushTimer!==void 0&&(clearTimeout(this.cacheFlushTimer),this.cacheFlushTimer=void 0),this.pendingCacheWrites.size>0&&this.flushQueryCacheWrites().catch(()=>{}),this.authTokenListeners.clear(),this.statusListeners.clear(),this.tokenExpiredListeners.clear(),this.identityChangeListeners.clear(),this.mutationSettledListeners.clear(),this.pendingChangeListeners.clear(),this.syncStatusListeners.clear(),this.whisperHandlers.clear(),this.liveSocketGrants.clear(),this.roomFlushes.clear(),this.roomIdentityResets.clear(),this.shapeSubscriptions.clear(),this.pokeAssembler.clear(),this.subscriptions.clear(),this.clientQueryStore.clear(),this.hydratedQueryCache.clear(),this.cacheSeededQueries.clear(),this.tabCoordinator?.stop(),this.tabCoordinator=void 0}assertOpen(){if(this.closed)throw new S("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 S("NOT_IMPLEMENTED",`LunoraClient: \`${e}\` is unavailable on a cross-tab follower tab. The \`crossTabSync\` channel only carries data from the leader tab outward, so this call could never reach the server. Turn off \`crossTabSync\`, or keep \`${e}\` on the leader tab.`)}clearConnectionTimers(e){clearTimeout(e.reconnectTimer),clearTimeout(e.connectTimer),clearTimeout(e.stableTimer),e.reconnectTimer=void 0,e.connectTimer=void 0,e.stableTimer=void 0}shardInUse(e){const t=s=>l(s)===e;return this.subscriptions.all().some(s=>t(s.shardKey))||[...this.shapeSubscriptions.values()].some(s=>t(s.shardKey))||[...this.streams.values()].some(s=>t(s.shardKey))||this.whisperHandlers.has(e)||this.connectionContexts.has(e)||this.connectionContextHolders.has(e)||this.offlineFlushes.has(e)||this.offlineQueue.hasPending(s=>t(s.shardKey))}releaseIdleShard(e){const t=l(e),s=this.connections.get(t);this.closed||t===""||s===void 0||(clearTimeout(s.idleTimer),s.idleTimer=setTimeout(()=>{s.idleTimer=void 0,!(this.closed||this.connections.get(t)!==s||this.shardInUse(t))&&(s.wasEverConnected&&this.idleClosedShards.add(t),this.teardownConnection(s),this.connections.delete(t),this.emitConnectionStatus())},st))}forgetStream(e){const t=this.streams.get(e);this.streams.delete(e),t&&this.releaseIdleShard(t.shardKey)}teardownConnection(e){e.polling.stop();const t=l(e.shardKey);for(const[i,n]of this.streams)l(n.shardKey)===t&&(n.handle.fail(new S("STREAM_DISCONNECTED","stream terminated: the connection carrying it was torn down")),this.streams.delete(i));e.pendingStreams=void 0,e.pendingUnsubscribes=[],this.clearResubscribeQueue(e),this.clearConnectionTimers(e),clearTimeout(e.idleTimer),e.idleTimer=void 0,L(e);const{socket:s}=e;if(s){e.socket=void 0;try{s.close()}catch{}}e.wsState="closed"}createTabCoordinator(){const e=`lunora-bridge::${this.url}::${this.identityFingerprint()??"anon"}`,t={activeShapes:()=>[...this.shapeSubscriptions.values()],activeSubscriptions:()=>this.subscriptions.all(),broadcastStatus:(s,i)=>this.tabCoordinator?.broadcastConnectionStatus(s,i),closeConnections:()=>{for(const[s,i]of this.connections)this.teardownConnection(i),this.connections.delete(s)},computeStatus:()=>this.computeStatus(),emitConnectionStatus:()=>{this.emitConnectionStatus()},ensureSocket:s=>{this.ensureSocket(s)},flushOfflineQueues:()=>{this.flushAllOfflineQueues()},identityFingerprint:()=>this.identityFingerprint(),isLeader:()=>this.tabCoordinator?.isLeader()===!0,leader:this.leader,queueResubscribe:s=>{this.queueResubscribe(s)},queuedShardKeys:()=>this.queuedOfflineShardKeys,clientIdentifier:()=>this.clientId,dropCacheSeed:s=>{this.dropCacheSeed(s)},ackAndAdvanceCursor:(s,i,n)=>{this.ackAndAdvanceCursor(s,i,n)},subscription:s=>this.subscriptions.get(s)};return new ct({channelName:e,onBecomeLeader:()=>{sr(t)},onStopBeingLeader:()=>{ir(t)},onConnectionStatus:(s,i)=>{rr(t,s,i)},onSubscriptionData:(s,i,n,a,o)=>{or(t,s,i,n,a,o)},onLeaderClaimAnswered:()=>{nr(t)},onSubscriptionError:(s,i,n)=>{ar(t,s,i,n)},onSubscriptionSettled:(s,i,n,a,o,c)=>{cr(t,s,i,n,a,o,c)}})}async sendBatch(e,t){if(this.assertOpen(),!this.fetchImpl)throw new S("INTERNAL","LunoraClient: no `fetch` implementation available");if(e.length===0)return[];const s=await this.fetchImpl(C(this.url,z),{body:JSON.stringify({calls:e.map((o,c)=>({args:w(o.args??{},`args for batch call '${o.fn.__lunoraRef}'`),functionPath:o.fn.__lunoraRef,id:c,shardKey:o.shardKey}))}),headers:this.rpcRequestHeaders({attachBookmark:!0}),method:"POST",signal:t}),i=s.headers.get("x-d1-bookmark");i&&this.bookmark.set(i);let n;try{n=await s.json()}catch{throw new S("INTERNAL",`LunoraClient: batch response was not JSON (status ${s.status.toString()})`)}const a=D(n);if(!s.ok||a!==void 0&&!n.results)throw a!==void 0?je(a):new S("INTERNAL",`LunoraClient: batch request failed (status ${s.status.toString()})`);for(const o of n.results??[]){const c=o.body?.commitCursor;typeof o.id=="number"&&typeof c=="number"&&this.recordShardCursor(e[o.id]?.shardKey,c)}return Hi(n.results??[],e.length)}async runMutation(e,t,s){this.assertOpen();const i=t,n=s.mutationId??Se();this.mutationIssueCounter+=1;const a=this.mutationIssueCounter,o=this.takeReplayCredential(s.replayCredential),c=s.replayBaseline===void 0?this.baselineCursorFor(s.shardKey):s.replayBaseline??void 0,{confirms:h,rollbacks:d}=this.applyOptimisticUpdates(e.__lunoraRef,i,s.shardKey,s.optimistic);s.optimisticUpdate&&this.applyOptimisticUpdate(s.optimisticUpdate,t,s.shardKey,d,h);const u=this.offlineFlushes.get(l(s.shardKey));u!==void 0&&await u;const{hasSocket:p,idleClosed:f,polling:m,wasEverConnected:b,wsState:y}=this.connectionGateState(s.shardKey),{queueBeforeFirstConnect:O}=this.offlineQueue,g=b||O,H=this.WebSocketImpl!==void 0&&g,ce=m||f,Ne=y==="connecting"&&g&&!ce,xe=y!=="open"&&!p&&H&&!ce,We=H&&s.replayBaseline===void 0&&this.hasPendingWriteAhead(s.shardKey),de=async(A=!1)=>this.enqueueOfflineMutation(e,i,s.shardKey,c,n,d,h,A?void 0:s.precondition,s.mutationId,o?.stamp,A,a);if(xe||Ne||We)return de();let G;try{const A=await this.rpc(e.__lunoraRef,i,s.shardKey,{baselineSeq:c,captureBookmark:!0,...o?.flags,mutationId:n,onCommitCursor:U=>{G=U}});for(const U of h)U(G);return{committed:!0,value:A}}catch(A){if(H&&this.fetchImpl!==void 0&&!this.outbox&&s.replayBaseline===void 0&&(A instanceof TypeError||A instanceof M)&&ke(i)){const U=de(!0);return this.noteHeldRetryDelay(s.shardKey),this.scheduleRateLimitedRetry(s.shardKey),U}throw this.settleFailedDirectWrite(A,G,h,d,o?.flags.authToken),A}}settleFailedDirectWrite(e,t,s,i,n){if(this.noteIdentityMismatch(e),n!==void 0&&this.noteReplayAuthRefusal(e,n),K(e)){for(const a of s)a(t);return}N(i)}async enqueueOfflineMutation(e,t,s,i,n,a,o,c,h,d,u,p){const f=d===void 0?this.identityFingerprint():d;if(this.outbox){this.outboxMutationCounter+=1;const b=this.outboxMutationCounter;try{await this.outbox.enqueue({args:t,baselineSeq:i,clientId:this.clientId,functionPath:e.__lunoraRef,idempotencyKey:h??`${this.clientId}:${String(b)}`,identity:f,mutationId:b,...a.length>0&&{onRejected:()=>{N(a)}},shardKey:s})}catch(y){throw N(a),y instanceof Error?y:new Error(String(y))}for(const y of o)y(void 0);return{committed:!1,value:void 0}}return{committed:!0,value:await new Promise((b,y)=>{const O={ambiguousSend:u,args:t,functionPath:e.__lunoraRef,liveAwaiter:!0,baselineSeq:i,id:n,issueSeq:p,clientId:this.clientId,identity:f,precondition:c,onCommit:g=>{for(const H of o)H(g)},reject:g=>{this.queuedIdentities.delete(n),K(g)||N(a),y(g instanceof Error?g:new Error(String(g))),this.releaseIdleShard(s)},resolve:b,shardKey:s};this.offlineQueue.enqueue(O),this.queuedOfflineShardKeys.add(s),this.ensureSocket(s),O.id!==void 0&&this.queuedIdentities.set(O.id,f)})}}hasPendingWriteAhead(e){if(this.outbox)return this.outbox.pending?.()??!1;const t=l(e);return this.offlineQueue.hasPending(s=>l(s.shardKey)===t)}async hydratePersistedQueue(){try{const e=await this.offlineQueue.hydrate();for(const t of e)this.queuedOfflineShardKeys.add(t),this.ensureSocket(t)}catch{}}hydrateAsOutboxLeader(){const e=()=>{this.hydratePersistedQueue().catch(()=>{})},t=globalThis.navigator?.locks;if(!t){e();return}t.request(`lunora:outbox-leader:${this.url}`,()=>(this.closed||e(),new Promise(s=>{if(this.closed){s();return}this.outboxLeaderRelease=s}))).catch(e)}async hydrateQueryCache(){if(this.queryCache)try{const e=await this.queryCache.load(),t=new Map;for(const s of this.subscriptions.all())t.set(P(s.fn.__lunoraRef,s.argsKey,s.shardKey),s);for(const{key:s,...i}of e){if(St(this.persistenceVersion,i.version)){this.queryCache.remove(s).catch(()=>{});continue}const n=t.get(s);if(n&&this.cachedQueryMatchesIdentity(i)){this.seedSubscriptionFromCache(n,i);continue}this.hydratedQueryCache.set(s,i)}}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(P(e.fn.__lunoraRef,e.argsKey,e.shardKey),t),F(e,t.value))}syncReadCacheToCredential(e){this.subjectAwaitingReconfirm()?this.revokeCacheSeededValues():e&&this.reseedFromHydratedCache()}dropCacheSeed(e){this.cacheSeededQueries.delete(e),this.hydratedQueryCache.delete(e)}returnCacheSeed(e){const t=this.cacheSeededQueries.get(e);t!==void 0&&(this.cacheSeededQueries.delete(e),this.hydratedQueryCache.set(e,t))}revokeCacheSeededValues(){if(this.cacheSeededQueries.size!==0){for(const[e,t]of this.cacheSeededQueries){const s=this.subscriptions.get(e);s!==void 0&&(s.serverBase=void 0,s.serverCursor=void 0,s.serverEpoch=void 0,F(s,void 0)),this.hydratedQueryCache.set(e,t)}this.cacheSeededQueries.clear()}}takeHydratedCache(e,t,s){const i=P(e,t,s),n=this.hydratedQueryCache.get(i);if(!(n===void 0||!this.cachedQueryMatchesIdentity(n)))return this.hydratedQueryCache.delete(i),n}reseedFromHydratedCache(){if(this.hydratedQueryCache.size!==0)for(const e of this.subscriptions.all()){const t=P(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=P(e.fn.__lunoraRef,e.argsKey,e.shardKey),i=this.getConnection(e.shardKey)?.identity,n=i===void 0?this.identityFingerprint():i;n===null&&this.identityUnresolved()||(this.pendingCacheWrites.set(s,{identity:n,serverCursor:e.serverCursor,ts:Date.now(),value:t,...n===this.identityFingerprint()&&!this.subjectAwaitingReconfirm()?this.credentialStamp():{},...e.serverEpoch===void 0?{}:{serverEpoch:e.serverEpoch},...this.persistenceVersion===void 0?{}:{version:this.persistenceVersion}}),this.cacheFlushTimer??=setTimeout(()=>{this.flushQueryCacheWrites().catch(()=>{})},it))}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,i])=>e.put(s,i)))}installPageHideFlush(){const e=globalThis;if(!this.persistence&&!this.queryCache||!("document"in globalThis)||typeof e.addEventListener!="function")return;const t=()=>{this.offlineQueue.flushUnpersisted(),this.cacheFlushTimer!==void 0&&(clearTimeout(this.cacheFlushTimer),this.flushQueryCacheWrites().catch(()=>{}))},s=()=>{e.document?.visibilityState==="hidden"&&t()};e.addEventListener("pagehide",t),e.document?.addEventListener("visibilitychange",s),this.releasePageHideFlush=()=>{e.removeEventListener?.("pagehide",t),e.document?.removeEventListener("visibilitychange",s)}}computeStatus(){if(this.tabCoordinator&&!this.tabCoordinator.isLeader())return this.leader.status??"idle";const e=[...this.connections.values()];return e.length===0?"idle":e.some(t=>t.wsState==="open")?"connected":e.some(t=>t.polling.isPolling())?"polling":e.some(t=>t.wsState==="connecting")?"connecting":"offline"}baselineCursorFor(e){const t=l(e);let s;for(const i of this.subscriptions.all())l(i.shardKey)!==t||i.serverCursor===void 0||(s=s===void 0?i.serverCursor:Math.max(s,i.serverCursor));return s}async pollSubscriptions(e){const t=l(e),s=[];for(const o of this.subscriptions.all())l(o.shardKey)===t&&(ke(o.args)?s.push(o):(this.markQueryRejected(o,!0),I(o.errorCallbacks,{code:"WIRE_ENCODE_FAILED",message:"could not encode this subscription's args for a poll"})));if(s.length===0)return this.probeOrigin();const i=mt(),n=this.identityFingerprint();let a;try{a=await we(async o=>this.sendBatch(s.map(c=>({args:c.args,fn:c.fn,shardKey:c.shardKey})),o))}catch(o){return!(o instanceof TypeError)}if(this.identityFingerprint()!==n)return!0;for(const[o,c]of s.entries()){const h=a[o];if(h!==void 0){if(!h.ok){this.markQueryRejected(c,!0),I(c.errorCallbacks,{code:h.error.code,message:h.error.message});continue}this.handleDataMessage({data:B(h.value),id:c.id,type:"data"},i)}}return!0}async probeOrigin(){const{fetchImpl:e}=this;if(!e)return!1;try{return await we(async t=>e(C(this.url,z),{body:JSON.stringify({calls:[]}),headers:this.rpcRequestHeaders({}),method:"POST",signal:t})),!0}catch{return!1}}emitSyncStatus(){if(this.syncStatusListeners.size===0)return;const e=this.syncStatus(),t=this.lastSyncStatus;t?.connection===e.connection&&t.pendingSubscriptions===e.pendingSubscriptions&&t.pendingWrites===e.pendingWrites&&t.synced===e.synced||(this.lastSyncStatus=e,this.syncStatusListeners.emit(e))}emitConnectionStatus(){const e=this.computeStatus();this.emitSyncStatus(),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,i){const n=[],a=[];if(!i)return{confirms:n,rollbacks:a};const o=E.key(e,t,s),c=this.subscriptions.get(o);if(c){const h=lt(c,i);h&&(n.push(h.confirm),a.push(h.rollback))}return{confirms:n,rollbacks:a}}applyOptimisticUpdate(e,t,s,i,n){const{confirms:a,rollbacks:o,store:c}=ft(this.subscriptions,s);try{e(c,t)}catch{N(o);return}i.push(...o),n.push(...a)}getConnection(e){return this.connections.get(l(e))}sendOrQueueUnsubscribe(e,t,s){const i=this.getConnection(e);i&&!T(i,{id:t,type:s})&&i.pendingUnsubscribes.push({id:t,type:s})}connectionGateState(e){if(this.tabCoordinator&&!this.tabCoordinator.isLeader()){let i="idle";return this.leader.status==="connected"?i="open":this.leader.status==="connecting"&&(i="connecting"),{hasSocket:!1,idleClosed:!1,polling:this.leader.status==="polling",wasEverConnected:this.leader.wasEverConnected,wsState:i}}const t=this.getConnection(e),s=t===void 0&&this.idleClosedShards.has(l(e));return{hasSocket:t?.socket!==void 0,idleClosed:s,polling:t?.polling.isPolling()??!1,wasEverConnected:t?.wasEverConnected??s,wsState:t?.wsState??"idle"}}getOrCreateConnection(e){const t=l(e);let s=this.connections.get(t);return s||(s={connectTimer:void 0,heartbeatTimer:void 0,lastFrameAt:0,pendingUnsubscribes:[],polling:Bi({afterFailedAttempts:this.pollingFallbackAfterFailedAttempts,intervalMs:this.pollingFallbackIntervalMs,onReachable:()=>{this.flushOfflineQueue(e).catch(()=>{})},onStateChange:()=>{this.emitConnectionStatus()},poll:async()=>this.pollSubscriptions(e)}),reconnect:ve(this.reconnectOptions),reconnectTimer:void 0,resubscribeQueue:[],resubscribeSlots:new Set,shardKey:e,socket:void 0,stableTimer:void 0,unackedWatchdogs:new Map,wasEverConnected:this.idleClosedShards.delete(t),wsState:"idle"},this.connections.set(t,s)),s}openSupplementarySocket(e,t){if(this.WebSocketImpl===void 0||this.closed)return{close:()=>{},resetBackoff:()=>{},socket:()=>{}};const s=ve(this.reconnectOptions),i={connectTimer:void 0,heartbeatTimer:void 0,lastFrameAt:0,socket:void 0};let n,a=!1;const o=()=>{a||this.closed||(n=setTimeout(d,s.next()))},c=f=>{a||this.WebSocketImpl===void 0||Ce(i,this.wsUrlFor(t.shardKey,f,e),this.managedSocketOptions,{onClose:()=>{o(),t.onClose?.()},onMessage:t.onMessage,...t.onOpen===void 0?{}:{onOpen:t.onOpen}})},h=async f=>{const m=this.wsTokenGeneration;let b;try{b=await f()}catch{o();return}if(m!==this.wsTokenGeneration){d();return}c(b)},d=()=>{if(a||this.WebSocketImpl===void 0)return;const{wsToken:f}=this;if(typeof f=="function"){h(f).catch(()=>{});return}c(f)};d();const u=()=>{a=!0,n!==void 0&&(clearTimeout(n),n=void 0),i.connectTimer!==void 0&&(clearTimeout(i.connectTimer),i.connectTimer=void 0),L(i);const{socket:f}=i;i.socket=void 0;try{f?.close()}catch{}};this.adminSocketTeardowns.add(u);const p=()=>{const{socket:f}=i;if(f!==void 0){i.socket=void 0,i.connectTimer!==void 0&&(clearTimeout(i.connectTimer),i.connectTimer=void 0),L(i);try{f.close()}catch{}t.onClose?.(),o()}};return this.supplementaryBounces.add(p),{close:()=>{u(),this.adminSocketTeardowns.delete(u),this.supplementaryBounces.delete(p)},resetBackoff:()=>{s.reset()},socket:()=>i.socket}}supplementaryUrl(e){const t=le(this.wsUrl),s=t.pathname.endsWith(J)?t.pathname.slice(0,-J.length):t.pathname;return t.pathname=C(s,e),fe(t,this.wsUrl)}wsUrlFor(e,t,s=this.wsUrl){if(e===void 0&&t===void 0)return s;const i=le(s),n=new Set([...e===void 0?[]:["shard"],...t===void 0?[]:["token"]]),a=[...i.searchParams].filter(([o])=>!n.has(o)).map(([o,c])=>`${encodeURIComponent(o)}=${encodeURIComponent(c)}`);return e!==void 0&&a.push(`shard=${encodeURIComponent(e)}`),t!==void 0&&a.push(`token=${encodeURIComponent(t)}`),i.search=a.join("&"),fe(i,s)}rpcRequestHeaders(e,t){const s={"content-type":"application/json"};e.expectSubject!==void 0&&(s[Et]=_t(e.expectSubject));const i=this.shardCursors.get(this.cursorKeyFor(t));i!==void 0&&(s["x-lunora-min-seq"]=i.toString());const n=e.authToken===void 0?this.authToken:e.authToken;if(n&&(s.authorization=`Bearer ${n}`),e.mutationId&&(s["x-lunora-mutation-id"]=e.mutationId),(e.clientId!==void 0||e.mutationId!==void 0)&&(s["x-lunora-client-id"]=e.clientId??this.clientId),e.clientSeq!==void 0&&(s["x-lunora-client-seq"]=e.clientSeq.toString()),e.baselineSeq!==void 0&&(s["x-lunora-base-seq"]=e.baselineSeq.toString()),e.attachBookmark){const a=this.bookmark.get();a&&(s["x-d1-bookmark"]=a)}return s}async rpc(e,t,s,i={}){const{fetchImpl:n}=this;if(!n)throw new M("LunoraClient: no `fetch` implementation available");const a=this.rpcRequestHeaders(i,s),o=i.authToken===void 0?this.authToken:i.authToken,c=JSON.stringify({args:w(t,`args for '${e}'`),functionPath:e,shardKey:s}),{body:h,response:d}=await W(i.unbounded?0:this.rpcTimeoutMs,i.signal,async f=>{const m=await n(C(this.url,Ut),{body:c,headers:a,method:"POST",signal:f});try{return{body:await m.json(),response:m}}catch{return{body:void 0,response:m}}});if(i.captureBookmark){const f=d.headers.get("x-d1-bookmark");f&&this.bookmark.set(f)}if(h===void 0)throw x(d.status,d.statusText,d.headers.get("retry-after"));const u=h;if(typeof u!="object"||u===null||Array.isArray(u))throw x(d.status,d.statusText,d.headers.get("retry-after"));const p=D(h);if(p!==void 0)throw pe(p,d.headers.get("retry-after"));if(!d.ok)throw x(d.status,d.statusText,d.headers.get("retry-after"));i.onMutationAck?.(h.lastMutationId),i.onCommitCursor?.(h.commitCursor),this.noteCredentialAccepted(o),this.learnDefaultShardKey(d,s),this.recordShardCursor(s,h.commitCursor);try{return k(h.result)}catch(f){throw Le(f)}}async adminFetch(e,t,s,i){if(!this.fetchImpl)throw new S("INTERNAL","LunoraClient: no `fetch` implementation available");const n={};this.authToken&&(n.authorization=`Bearer ${this.authToken}`);const a=s instanceof ArrayBuffer||s instanceof Blob;let o;s===void 0?o=void 0:a?(o=s,i!==void 0&&(n["content-type"]=i)):(o=JSON.stringify(s),n["content-type"]="application/json");const c=await this.fetchImpl(C(this.url,e),{body:o,headers:n,method:t});let h;try{h=await c.json()}catch{const u=c.statusText?` ${c.statusText}`:"";throw new S("INTERNAL",`LunoraClient: response was not JSON (status ${c.status.toString()}${u})`)}const d=D(h);if(d!==void 0){const u=new Error(d.message??"admin request failed");throw Object.assign(u,{code:d.code},Ge(d)),u}if(!c.ok){const u=c.statusText?` ${c.statusText}`:"";throw new S("INTERNAL",`LunoraClient: admin request failed (status ${c.status.toString()}${u})`)}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));T(e,{caps:hr,clientId:this.clientId,id:"connect",type:"connect",...t===void 0?{}:{context:t}})}resendShapeSubscriptions(e){for(const t of this.shapeSubscriptions.values())l(t.shardKey)===l(e)&&this.sendShapeSubscribeIfOpen(t)}ensureSocket(e){if(this.closed||this.WebSocketImpl===void 0||this.tabCoordinator&&!this.tabCoordinator.isLeader())return;const t=this.getOrCreateConnection(e);if(!(t.wsState==="open"||t.wsState==="connecting")){if(t.wsState="connecting",this.emitConnectionStatus(),typeof this.wsToken=="function"){this.openSocketWithProvidedToken(t,e,this.wsToken).catch(()=>{});return}this.openSocket(t,e,this.wsToken)}}async openSocketWithProvidedToken(e,t,s){const i=this.wsTokenGeneration,n=Symbol("ws-token-attempt");let a;e.providerAttempt=n;try{a=await W(this.connectTimeoutMs,void 0,async()=>s(),()=>new Error("LunoraClient: wsToken provider timed out"))}catch{e.providerAttempt===n&&(e.providerAttempt=void 0,this.handleDisconnect(e));return}if(e.providerAttempt===n&&(e.providerAttempt=void 0,!(this.closed||this.WebSocketImpl===void 0||e.wsState!=="connecting"||e.socket!==void 0))){if(i!==this.wsTokenGeneration){typeof this.wsToken=="function"?await this.openSocketWithProvidedToken(e,t,this.wsToken):this.openSocket(e,t,this.wsToken);return}this.openSocket(e,t,a)}}openSocket(e,t,s){this.WebSocketImpl!==void 0&&(e.identity=this.identityFingerprint(),s===void 0&&this.authToken===null?(this.identityQuestions+=1,e.identityQuestion=this.identityQuestions):e.identityQuestion=void 0,e.retired=!1,Ce(e,this.wsUrlFor(t,s),this.managedSocketOptions,{onClose:i=>{i?.code===4001&&this.notifyTokenExpired(),this.handleDisconnect(e)},onMessage:i=>{e.retired!==!0&&this.handleServerMessage(i.data,t)},onOpen:()=>{e.wsState="open",e.wasEverConnected=!0,e.identityConfirmed=!1,e.connectionId=void 0,e.roomsRejoined=!1,e.polling.noteOpen(),clearTimeout(e.stableTimer),e.stableTimer=setTimeout(()=>{e.wsState==="open"&&e.reconnect.reset()},ye),this.markShardPendingAck(t,!0),this.emitConnectionStatus(),this.sendConnectEnvelope(e),this.clearResubscribeQueue(e);for(const a of this.subscriptions.all())l(a.shardKey)===l(t)&&this.queueResubscribe(a);if(this.resendShapeSubscriptions(t),e.pendingUnsubscribes.length>0){const a=e.pendingUnsubscribes;e.pendingUnsubscribes=[];for(const{id:o,type:c}of a)T(e,{id:o,type:c});this.releaseIdleShard(t)}Ui(e);const i=l(t),n=this.whisperHandlers.get(i);if(this.dropWhisperJoinWaiters(i),this.whisperJoins.set(i,new Map),n)for(const a of n.keys())this.sendWhisperJoin(e,i,a);e.roomsRejoined=!0,this.releaseRoomSends(t),this.flushOfflineQueue(t).catch(()=>{})}}))}cancelStream(e,t){const s=this.getConnection(t);s&&(s.pendingStreams=s.pendingStreams?.filter(i=>i.id!==e),T(s,{id:e,type:"unsubscribe"})),this.forgetStream(e)}handleDisconnect(e){if(this.closed||e.wsState==="idle"||e.wsState==="closed")return;e.wsState==="connecting"&&e.polling.noteFailedOpen(),L(e),this.clearConnectionTimers(e),e.socket=void 0,e.wsState="idle",e.connectionId=void 0,e.whisperAck=void 0,this.dropWhisperJoinWaiters(l(e.shardKey)),this.markShardPendingAck(e.shardKey),this.emitConnectionStatus(),this.clearResubscribeQueue(e);const t=new Set((e.pendingStreams??[]).map(i=>i.id));for(const[i,n]of this.streams)if(!(l(n.shardKey)!==l(e.shardKey)||t.has(i))){if(n.durable){const a={...n.message,...n.generation===void 0?{}:{generation:n.generation},sinceChunk:n.lastSeq};n.message=a,e.pendingStreams=[...(e.pendingStreams??[]).filter(o=>o.id!==i),a];continue}n.handle.fail(new S("STREAM_DISCONNECTED","stream terminated: WebSocket disconnected")),this.forgetStream(i)}if(this.WebSocketImpl===void 0)return;const s=e.reconnect.next();e.reconnectTimer=setTimeout(()=>{e.reconnectTimer=void 0,this.ensureSocket(e.shardKey)},s)}markShardPendingAck(e,t=!1){const s=l(e);for(const i of this.subscriptions.all())l(i.shardKey)===s&&(i.acked=!1,t&&(i.valueReceived=!1));for(const i of this.shapeSubscriptions.values())l(i.shardKey)===s&&(i.answered=!1)}queueResubscribe(e){const t=this.getConnection(e.shardKey);t&&(t.resubscribeQueue.push(e),this.drainResubscribeQueue(t))}drainResubscribeQueue(e){for(;e.resubscribeSlots.size<rt;){const t=e.resubscribeQueue.shift();if(!t)return;this.subscriptions.getById(t.id)&&this.sendSubscribeIfOpen(t)&&e.resubscribeSlots.add(t.id)}}settleSubscribeWatchdog(e,t){clearTimeout(e.unackedWatchdogs.get(t)),e.unackedWatchdogs.delete(t),e.resubscribeSlots.delete(t)&&this.drainResubscribeQueue(e)}clearResubscribeQueue(e){for(const t of e.unackedWatchdogs.values())clearTimeout(t);e.unackedWatchdogs.clear(),e.resubscribeSlots.clear(),e.resubscribeQueue=[]}sendSubscribeIfOpen(e,t=!1){const s=this.getConnection(e.shardKey);if(s?.wsState!=="open"||e.acked)return!1;const i=e.serverCursor!==void 0&&e.serverBase!==void 0,n=T(s,{id:e.id,query:{args:e.wireArgs,functionPath:e.fn.__lunoraRef,table:e.fn.__lunoraRef,...i?{sinceSeq:e.serverCursor}:{},...i&&e.serverEpoch!==void 0?{sinceEpoch:e.serverEpoch}:{}},type:"subscribe"});return n&&!t&&this.armUnackedWatchdog(s,e),n}armUnackedWatchdog(e,t){clearTimeout(e.unackedWatchdogs.get(t.id)),e.unackedWatchdogs.set(t.id,setTimeout(()=>{!t.acked&&this.subscriptions.getById(t.id)===t&&this.sendSubscribeIfOpen(t,!0),this.settleSubscribeWatchdog(e,t.id)},nt))}sendShapeSubscribeIfOpen(e){const t=this.getConnection(e.shardKey);t?.wsState==="open"&&T(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=xi(e);if(s===void 0)return;let i;try{i=JSON.parse(s)}catch{return}if(i.type!=="error"&&this.getConnection(t)?.reconnect.reset(),typeof i.id=="string"){const n=this.getConnection(t);if(n){const{id:a}=i;this.settleSubscribeWatchdog(n,a)}}switch(i.type){case"ack":{const n=this.subscriptions.getById(i.id);n&&this.ackAndAdvanceCursor(n,void 0,void 0);return}case"chunk":{const{data:n,generation:a,id:o,seq:c}=i,h=this.streams.get(o);h&&typeof c=="number"&&(h.lastSeq=c,typeof a=="number"&&(h.generation=a),h.durable=!0),h?.handle.push(k(n));return}case"complete":{this.handleCompleteMessage(i.id);return}case"data":case"delta":{this.handleDataMessage(i);return}case"error":{this.handleErrorMessage(i);break}case"identity":{this.handleIdentityFrame(i,t),this.adoptSocketConnectionId(i,t),this.confirmShardIdentity(t);break}case"live":{this.dispatchLive(i,t);break}case"pokeEnd":{this.handlePokeEnd(i,t);break}case"pokePart":{this.pokeAssembler.part(t,i);break}case"pokeStart":{this.pokeAssembler.start(t,i);break}case"resume":{this.handleResumeMessage(i);break}case"settled":{this.handleSettledMessage(i);break}case"whisper":{this.dispatchWhisper(i,t);break}case"whisper_subscribed":{this.acknowledgeWhisperJoin(l(t),i.topic);break}}}handleErrorMessage(e){const t=e.error?.code;if(t==="TOKEN_EXPIRED"){this.notifyTokenExpired();return}if(t==="STREAM_ID_IN_USE")return;const{id:s}=e,i=s===void 0?void 0:this.streams.get(s);if(i&&s!==void 0){i.handle.fail($e(e)),this.forgetStream(s);return}const n=s===void 0?void 0:this.subscriptions.getById(s);if(n){const o=me(e),c=this.identityFingerprint(),h=E.keyOf(n);this.markQueryRejected(n),I(n.errorCallbacks,o),this.tabCoordinator?.isLeader()&&this.tabCoordinator.broadcastSubscriptionError(h,o,c);return}const a=s===void 0?void 0:this.shapeSubscriptions.get(s);a&&(a.answered||(a.answered=!0,this.emitSyncStatus()),I(a.errorCallbacks,me(e)))}markQueryRejected(e,t=this.tabCoordinator!==void 0&&!this.tabCoordinator.isLeader()||this.connectionGateState(e.shardKey).polling){const s=t?"valueReceived":"acked";e[s]||(e[s]=!0,this.emitSyncStatus())}handlePokeEnd(e,t){const s=this.pokeAssembler.end(t,e.pokeId);if(s){Zi(this.shapeSubscriptions,s);for(const i of s.parts.keys()){const n=this.shapeSubscriptions.get(i);n&&!s.undecodable.has(i)&&this.applyPokePart(n,s,e)}}}applyPokePart(e,t,s){const i=e.answered,n=Xi(e,t,s);if(e.answered!==i&&this.emitSyncStatus(),Ee(e),n==="reseed"){this.sendShapeSubscribeIfOpen(e);return}e.onCheckpoint?.({checkpoint:e.serverCursor,mutationId:e.lastMutationId})}resnapshotSubscription(e){e.acked=!1,e.serverCursor=void 0,e.serverEpoch=void 0,this.emitSyncStatus(),console.warn("[lunora] could not merge a row delta into the cached result; re-subscribing for a full snapshot"),this.sendSubscribeIfOpen(e)}handleDataMessage(e,t){const{id:s}=e,i=s?this.subscriptions.getById(s):void 0;if(!i||e.type==="data"&&er(i,e))return;let n;try{n=Be(e,i.serverBase)}catch(o){I(i.errorCallbacks,{code:"WIRE_DECODE_FAILED",message:`could not decode a server frame for this subscription — ${o instanceof Error?o.message:String(o)}`});return}if(n===De){this.resnapshotSubscription(i);return}this.dropCacheSeed(E.keyOf(i));const a=t!==void 0&&!i.valueReceived;if(Me(i,n,{cursor:e.cursor,epoch:e.epoch}),a&&(i.valueReceived=!0,this.emitSyncStatus()),e.lastMutationId!==void 0&&(se(i,e.lastMutationId),ie(i,!0)),this.persistQueryValue(i),ee(i,i.serverCursor),t!==void 0&&pt(i,t),F(i,n),this.tabCoordinator?.isLeader()){const o=E.keyOf(i);this.tabCoordinator.broadcastSubscriptionData(o,n,i.serverCursor,i.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&&se(t,e.lastMutationId),ie(t),this.tabCoordinator?.isLeader())){const s=E.keyOf(t);this.tabCoordinator.broadcastSubscriptionSettled(s,t.serverCursor,t.serverEpoch,t.lastMutationId,this.clientId,this.identityFingerprint())}}ackAndAdvanceCursor(e,t,s){const i=!e.acked;e.acked=!0,i&&this.emitSyncStatus(),(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),ee(e,e.serverCursor)&&F(e,e.serverBase))}adoptSocketConnectionId(e,t){const s=this.getConnection(t);if(!(s===void 0||typeof e.connectionId!="string")){s.connectionId=e.connectionId,s.whisperAck=e.whisperAck===!0;for(const i of this.liveSocketGrants.get(l(t))?.keys()??[])this.grantWhenJoined(t,i,e.connectionId)}}grantWhenJoined(e,t,s){const i=l(e),n=this.liveSocketGrants.get(i)?.get(t);if(n===void 0)return;const{stream:a,topic:o}=n,c=()=>{this.liveSocketGrants.get(i)?.get(t)===void 0||this.getConnection(e)?.connectionId!==s||this.postLiveControl(`/live/${a}/control`,e,{action:"subscribe",connectionId:s,stream:a,subscriptionId:t,topic:o},d=>{this.refuseLiveGrant(e,t,d,s)})};this.getConnection(e)?.whisperAck===!0?this.whenWhisperJoined(i,o,c):c()}sendWhisperJoin(e,t,s){const i=this.whisperJoinState(t,s);i.pending+=1,i.joined=!1,T(e,{topic:s,type:"whisper_subscribe"})}acknowledgeWhisperJoin(e,t){const s=this.whisperJoins.get(e)?.get(t);if(s!==void 0&&(s.pending=Math.max(0,s.pending-1),!(s.pending>0))){s.joined=!0;for(const i of s.waiters.splice(0))clearTimeout(i.timer),i.run();this.releaseWhisperJoin(e,t)}}releaseWhisperJoin(e,t){if(this.whisperHandlers.get(e)?.has(t)===!0)return;const s=this.whisperJoins.get(e),i=s?.get(t);if(!(s===void 0||i===void 0||i.pending>0)){for(const n of i.waiters.splice(0))clearTimeout(n.timer);s.delete(t),s.size===0&&this.whisperJoins.delete(e)}}whenWhisperJoined(e,t,s){const i=this.whisperJoinState(e,t);if(i.joined){s();return}const n={run:s,timer:void 0};n.timer=setTimeout(()=>{i.waiters=i.waiters.filter(a=>a!==n),s()},He),i.waiters.push(n)}dropWhisperJoinWaiters(e){for(const t of this.whisperJoins.get(e)?.values()??[])for(const s of t.waiters.splice(0))clearTimeout(s.timer)}whisperJoinState(e,t){let s=this.whisperJoins.get(e);s===void 0&&(s=new Map,this.whisperJoins.set(e,s));let i=s.get(t);return i===void 0&&(i={joined:!1,pending:0,waiters:[]},s.set(t,i)),i}refuseLiveGrant(e,t,s,i){const n=l(e),a=this.liveSocketGrants.get(n),o=a?.get(t);a===void 0||o===void 0||this.getConnection(e)?.connectionId!==i||(a.delete(t),a.size===0&&this.liveSocketGrants.delete(n),o.release(),o.onError?.({status:s,topic:o.topic}))}postLiveControl(e,t,s,i){const{fetchImpl:n}=this;if(!n)return;const a=JSON.stringify(t===void 0?s:{...s,shardKey:t}),o=this.rpcRequestHeaders({},t);this.liveControlChain=this.liveControlChain.then(()=>lr(n,C(this.url,e),a,o)).then(c=>{c>=400&&c<500&&c!==404&&c!==401&&i?.(c)}).catch(()=>{})}dispatchLive(e,t){const s=this.liveSocketGrants.get(l(t));if(!s)return;const i=k(e.data);for(const n of s.values())if(!(n.stream!==e.stream||n.topic!==e.topic))try{n.onEvent(i)}catch{}}dispatchWhisper(e,t){const s=this.whisperHandlers.get(l(t))?.get(e.topic);if(!s)return;const i=k(e.data);for(const n of s)try{n(i,e.from)}catch{}}notifyTokenExpired(){this.tokenExpiredListeners.emit()}handleCompleteMessage(e){const t=this.streams.get(e);if(t){t.handle.complete(),this.forgetStream(e);return}const s=this.subscriptions.getById(e);s&&(s.acked=!1,this.emitSyncStatus(),I(s.errorCallbacks,{code:"SUBSCRIPTION_CANCELLED",message:"subscription was cancelled by the server"}))}unpersist(e){e&&(this.replayAttempts.delete(e),this.offlineQueue.discard(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 i=0;i<e.length;i+=1){const n=e.charCodeAt(i);t^=n,t=Math.imul(t,16777619),s=Math.imul(s,33)+n}return`${e.length.toString(36)}:${(t>>>0).toString(36)}:${(s>>>0).toString(36)}`}credentialStamp(){const e=this.authToken;return e===null?{}:{credential:this.hashToken(e)}}cachedQueryMatchesIdentity(e){return this.identityFingerprint()===null&&this.identityUnresolved()?!1:!this.subjectAwaitingReconfirm()&&e.identity===this.identityFingerprint()||this.isSameCredentialUnderTokenHash(e.identity)?!0:e.credential!==void 0&&e.credential===this.credentialStamp().credential}isSameCredentialUnderTokenHash(e){if(e===null||e.startsWith("subj:"))return!1;const t=this.authToken;return t===null?!1:this.hashToken(t)===e}releaseSessionProbe(){this.sessionProbesInFlight-=1,!(this.identityUnresolved()||this.identityFingerprint()!==null)&&!this.closed&&this.offlineQueue.size>0&&q(this.computeStatus())&&this.flushAllOfflineQueues()}identityUnresolved(){return this.sessionProbesInFlight>0?!0:this.identityResolutionExpected&&!this.identitySettled}adoptResolvedSubject(e,t,s){if(!(this.closed||this.authToken!==e||s!==this.sessionProbeGeneration)){if(e===null){this.adoptCookieSubject(t?.id??null,s);return}t!==null&&this.setAuthToken(e,t.id)}}adoptCookieSubject(e,t){return this.closed||this.authToken!==null||t<this.identityAnsweredAt?!1:(this.identityAnsweredAt=t,this.identitySettled=!0,this.setAuthToken(null,e),!0)}sendEncodedWhisper(e,t,s){this.ensureSocket(s.shardKey);const i=this.getConnection(s.shardKey),n=i!==void 0&&T(i,{data:t,topic:e,type:"whisper"});return this.releaseIdleShard(s.shardKey),n}roomSendsAdmitted(e){const t=this.getConnection(e);return t?.wsState==="open"&&t.retired!==!0&&t.identityConfirmed===!0&&t.roomsRejoined===!0}releaseRoomSends(e){if(this.roomSendsAdmitted(e))for(const t of this.roomFlushes.get(l(e))??[])t()}confirmShardIdentity(e){const t=this.getConnection(e);t!==void 0&&(t.identityConfirmed=!0),this.releaseRoomSends(e)}handleIdentityFrame(e,t){const s=this.getConnection(t)?.identityQuestion,{subject:i}=e;s===void 0||i!==null&&typeof i!="string"||this.adoptCookieSubject(i,s)||!this.closed&&this.authToken===null&&(i===null?null:`subj:${i}`)!==this.identityFingerprint()&&this.evictPreviousIdentitySession()}applySubject(e,t){if(t!==void 0){this.authSubject=t,this.subjectToken=e;return}(e===null&&this.authSubject!==null||e!==null&&this.authSubject===null)&&(this.authSubject=void 0,this.subjectToken=null)}isKnownNobody(){return this.authSubject===null&&this.authToken===null}subjectAwaitingReconfirm(){return this.authSubject!==void 0&&this.authSubject!==null&&this.subjectToken!==this.authToken}stampOf(e){const t=e.id===void 0?void 0:this.queuedIdentities.get(e.id);return t===void 0?e.identity:t}warnRefreshWithoutSubject(e,t){e===null||t===null||this.authSubject!==void 0||this.authRefusalNotifiedFor!==this.hashToken(e)||console.warn("[lunora] setAuthToken replaced a token that was just refused for a queued write, with no subject: without one a refresh reads as a user switch, so the held writes were discarded (OFFLINE_IDENTITY_CHANGED). Pass the user id, e.g. setAuthToken(token, user.id), to keep them across a refresh.")}rejectQueuedForIdentityChange(e){const t=this.offlineQueue.drain(),s=[];for(const i of t){if(this.identityVerdict(this.stampOf(i))!=="mismatch"){s.push(i);continue}this.queuedIdentities.delete(i.id??""),this.unpersist(i.id);const n=new Error("offline mutation discarded: auth identity changed before replay");n.code="OFFLINE_IDENTITY_CHANGED",i.reject(n),this.emitItemSettled(i,"rejected",n)}this.offlineQueue.requeue(s),e!==null&&this.clearQueryCacheForIdentityChange()}restampConnectionIdentity(e,t){for(const s of this.connections.values())s.identity===e&&(s.identity=t)}restampQueuedIdentity(e,t){for(const[s,i]of this.queuedIdentities)i===e&&this.queuedIdentities.set(s,t);this.offlineQueue.restampIdentity(e,t)}restampWatermarks(e,t){const s=e??"",i=this.clientWatermarks.get(s);if(i===void 0)return;this.clientWatermarks.delete(s);const n=t??"",a=this.clientWatermarks.get(n);if(a===void 0)this.clientWatermarks.set(n,i);else for(const[o,c]of i)a.set(o,c)}clearQueryCacheForIdentityChange(){this.revokeCacheSeededValues(),this.cacheFlushTimer!==void 0&&(clearTimeout(this.cacheFlushTimer),this.cacheFlushTimer=void 0),this.pendingCacheWrites.clear(),this.hydratedQueryCache.clear(),this.queryCache?.clear().catch(()=>{})}evictPreviousIdentitySession(){this.resetRoomSends(),this.revokeCacheSeededValues();for(const e of this.subscriptions.all())e.serverBase=void 0,e.serverCursor=void 0,e.serverEpoch=void 0,e.acked=!1,e.valueReceived=!1,F(e,void 0);for(const e of this.shapeSubscriptions.values())e.rows.clear(),e.serverCursor=void 0,e.serverEpoch=void 0,e.answered=!1,Ee(e);this.emitSyncStatus(),this.bounceShardSockets(),this.retiredIdentities+=1,this.identityChangeListeners.emit()}restartTabCoordinatorForIdentity(){if(!this.tabCoordinator)return;const e=this.tabCoordinator.isLeader();this.tabCoordinator.stop(),this.tabCoordinator=this.createTabCoordinator(),this.tabCoordinator.start(),e&&this.tabCoordinator.promoteImmediately()}resetRoomSends(){for(const e of this.roomIdentityResets)e()}bounceShardSockets(){for(const e of this.connections.values())if(e.socket){e.retired=!0;try{e.socket.close()}catch{}}for(const e of this.supplementaryBounces)e()}flushAllOfflineQueues(){for(const e of this.queuedOfflineShardKeys)this.flushOfflineQueue(e).catch(()=>{})}async flushOfflineQueue(e){const t=l(e),s=this.offlineFlushes.get(t);if(s===void 0&&this.offlineQueue.size===0)return;const i=(async()=>{await(s??Promise.resolve());const{authToken:n}=this;try{await this.drainOfflineQueue(e,n)}catch{}!this.closed&&this.authToken!==n&&this.offlineQueue.size>0&&q(this.computeStatus())&&this.flushOfflineQueue(e).catch(()=>{})})();this.offlineFlushes.set(t,i),await i,this.offlineFlushes.get(t)===i&&(this.offlineFlushes.delete(t),this.releaseIdleShard(e))}async drainOfflineQueue(e,t){const s=this.offlineQueue.drainConflict();for(const d of s){this.unpersist(d.id),this.queuedIdentities.delete(d.id??"");const u=new Error("offline mutation skipped: precondition failed before replay");u.code="OFFLINE_PRECONDITION_FAILED",this.emitItemSettled(d,"rejected",u)}const i=l(e),n=this.offlineQueue.drain(d=>l(d.shardKey)===i);if(n.length===0)return;const a=[],o=[];for(const d of n){const u=this.replayGateVerdict(d);u==="send"?a.push(d):u==="hold"&&o.push(d)}if(this.offlineQueue.requeue(o),o.length>0&&this.subjectAwaitingReconfirm()&&(this.getCurrentUser().catch(()=>{}),this.noteHeldRetryDelay(e)),a.length===0){this.scheduleRateLimitedRetry(e);return}const c=this.encodableOrSettleTerminal(a);if(c.length===0){this.scheduleRateLimitedRetry(e);return}if(c.length===1){await this.replaySequential(c,e,t),this.scheduleRateLimitedRetry(e);return}const h=[];for(let d=0;d<c.length;d+=V){const u=c.slice(d,d+V),p=await this.replayBatched(u,e,t);if(h.push(...p.requeue),p.stop||p.requeue.length>0){h.push(...c.slice(d+V));break}}h.length>0&&this.offlineQueue.requeue(h),this.scheduleRateLimitedRetry(e)}noteHeldRetryDelay(e){const t=l(e),s=this.replayRetryState.get(t),i=(s?.attempts??0)+1;this.replayRetryState.set(t,{attempts:i,delayMs:Math.max(s?.delayMs??0,te(i))})}noteReplayRetryDelay(e,t,s){const i=l(e),n=this.replayRetryState.get(i),a=(n?.attempts??0)+1,o=ji(t,a)??(s===null&&Q(t)?te(a):void 0);this.replayRetryState.set(i,{attempts:a,delayMs:o===void 0?n?.delayMs:Math.max(n?.delayMs??0,o)})}scheduleRateLimitedRetry(e){const t=l(e),s=this.replayRetryState.get(t),i=s?.delayMs;if(s===void 0||i===void 0||this.closed||this.offlineQueue.size===0){this.replayRetryState.delete(t);return}s.delayMs=void 0;const n=this.replayRetryTimers.get(t);n!==void 0&&clearTimeout(n),this.replayRetryTimers.set(t,setTimeout(()=>{this.replayRetryTimers.delete(t),this.flushOfflineQueue(e).catch(()=>{})},i))}encodableOrSettleTerminal(e){const t=[];for(const s of e)try{w(s.args,`args for '${s.functionPath}'`),t.push(s)}catch(i){this.settleReplayTerminal(s,i instanceof Error?i:new Error(String(i)))}return t}identityVerdict(e){if(this.subjectAwaitingReconfirm())return"unknown";const t=this.identityFingerprint();return t===null&&this.identityUnresolved()?"unknown":e===t||e!==void 0&&this.isSameCredentialUnderTokenHash(e)?"match":t===null?"unknown":"mismatch"}replayGateVerdict(e){const t=this.stampOf(e);if(t===void 0)return this.queuedIdentities.delete(e.id??""),"send";const s=this.identityVerdict(t);if(s==="unknown")return"hold";if(this.queuedIdentities.delete(e.id??""),s==="match")return"send";this.unpersist(e.id);const i=new Error("offline mutation skipped: auth identity changed before replay");return i.code="OFFLINE_IDENTITY_CHANGED",e.reject(i),this.emitItemSettled(e,"rejected",i),"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 i=this.shardCursors.get("");i!==void 0&&(this.shardCursors.set(s,Math.max(this.shardCursors.get(s)??0,i)),this.shardCursors.delete(""))}recordShardCursor(e,t){if(typeof t!="number")return;const s=this.cursorKeyFor(e);this.shardCursors.set(s,Math.max(this.shardCursors.get(s)??0,t))}shouldRequeueReplayFailure(e,t){return this.noteIdentityMismatch(e)?!0:this.noteReplayAuthRefusal(e,t)||Ae(e)}noteReplayAuthRefusal(e,t){if(!Q(e))return!1;const s=this.hashToken(t??"");return t===this.authToken&&this.authRefusalNotifiedFor!==s&&(this.authRefusalNotifiedFor=s,this.notifyTokenExpired()),!0}noteCredentialAccepted(e){this.authRefusalNotifiedFor!==void 0&&this.authRefusalNotifiedFor===this.hashToken(e??"")&&(this.authRefusalNotifiedFor=void 0)}takeReplayCredential(e){if(e===void 0)return;const t=this.replayCredentials.get(e);if(t===void 0)throw new TypeError("LunoraClient: `replayCredential` must come from this client's `replayIdentityVerdict`, and is single use");return this.replayCredentials.delete(e),{flags:{authToken:t.authToken,...Y(t.stamp,t.authToken)},stamp:t.stamp}}noteIdentityMismatch(e){if(e?.code!=="IDENTITY_MISMATCH")return!1;const t=this.identityFingerprint();return this.getCurrentUser().then(()=>{!this.warnedIdentityDisagreement&&this.identityFingerprint()===t&&(this.warnedIdentityDisagreement=!0,console.warn('[lunora] a replayed write was refused with IDENTITY_MISMATCH, but `/get-session` still names the same user. The worker\'s `resolveIdentity` must return the same `userId` as the better-auth `user.id`, and RPC requests must carry the session cookie (`credentials: "include"` on a cross-origin fetch).'))}).catch(()=>{}),!0}settleReplayUndecodable(e,t,s){this.unpersist(e.id),this.recordShardCursor(e.shardKey,s),e.onCommit?.(s),e.reject(t),this.emitItemSettled(e,"committed",t)}spendsLastReplayAttempt(e,t){if(e.id===void 0)return!1;const s=t?.code;if(e.ambiguousSend!==!0||Q(t)||s==="RATE_LIMITED"||s==="TOO_MANY_REQUESTS"||!Ae(t))return!1;const i=(this.replayAttempts.get(e.id)??0)+1;return this.replayAttempts.set(e.id,i),i>=ot}keepUnexhaustedAmbiguousWrites(e,t){return e.filter(s=>s.ambiguousSend===!0&&this.spendsLastReplayAttempt(s,t)?(this.settleReplayTerminal(s,t),!1):!0)}settleReplayTerminal(e,t){this.unpersist(e.id),e.reject(t),this.emitItemSettled(e,"rejected",t)}async replaySequential(e,t,s){for(let i=0;i<e.length;i+=1){const n=e[i];if(!n)continue;let a;try{const o=await this.rpc(n.functionPath,n.args,n.shardKey,{authToken:s,baselineSeq:n.baselineSeq,captureBookmark:!0,clientId:n.clientId??this.clientId,...Y(n.identity,s),mutationId:n.id,onCommitCursor:c=>{a=c}});this.settleReplaySuccess(n,o,a)}catch(o){if(K(o)){this.settleReplayUndecodable(n,o,a);continue}if(!this.shouldRequeueReplayFailure(o,s)||this.spendsLastReplayAttempt(n,o)){this.settleReplayTerminal(n,o);continue}this.noteReplayRetryDelay(t,o,s),this.offlineQueue.requeue(e.slice(i));return}}}async replayBatched(e,t,s){if(!this.fetchImpl)return{requeue:e,stop:!0};const i=JSON.stringify({calls:e.map((d,u)=>({args:w(d.args,`args for '${d.functionPath}'`),baselineSeq:d.baselineSeq,functionPath:d.functionPath,id:u,clientId:d.clientId??this.clientId,mutationId:d.id,shardKey:d.shardKey}))});if(e.length>1&&$i(i)>Gi)return await this.replayBatchedHalves(e,t,s);const{fetchImpl:n}=this;let a,o;try{({payload:o,response:a}=await W(this.rpcTimeoutMs,void 0,async d=>{const u=await n(C(this.url,z),{body:i,headers:this.rpcRequestHeaders({attachBookmark:!0,authToken:s,...Y(e.find(p=>p.identity!==void 0)?.identity,s)}),method:"POST",signal:d});if(u.status===413&&e.length>1)return{payload:void 0,response:u};try{return{payload:await u.json(),response:u}}catch{return{payload:void 0,response:u}}}))}catch(d){return this.noteReplayRetryDelay(t,d,s),{requeue:this.keepUnexhaustedAmbiguousWrites(e,d),stop:!0}}const c=a.headers.get("x-d1-bookmark");if(c&&this.bookmark.set(c),a.status===413&&e.length>1)return await this.replayBatchedHalves(e,t,s);const h=a.headers.get("retry-after");if(!o)return this.settleWholeBatchError(e,x(a.status,a.statusText,h),t,s);if(!Array.isArray(o.results)){const d=D(o),u=d===void 0?x(a.status,a.statusText,h):pe(d,h);return this.settleWholeBatchError(e,u,t,s)}return{requeue:this.settleReplayBatchSlots(e,o.results,t,s),stop:!1}}settleWholeBatchError(e,t,s,i){if(t instanceof M||t.code!==void 0&&this.shouldRequeueReplayFailure(t,i))return this.noteReplayRetryDelay(s,t,i),{requeue:this.keepUnexhaustedAmbiguousWrites(e,t),stop:!0};for(const n of e)this.settleReplayTerminal(n,t);return{requeue:[],stop:!1}}async replayBatchedHalves(e,t,s){const i=Math.ceil(e.length/2),n=await this.replayBatched(e.slice(0,i),t,s);if(n.stop||n.requeue.length>0)return{requeue:[...n.requeue,...e.slice(i)],stop:!0};const a=await this.replayBatched(e.slice(i),t,s);return{requeue:[...n.requeue,...a.requeue],stop:a.stop}}settleReplayBatchSlots(e,t,s,i){const n=Vi(t),a=[];let o=!1,c=!1;for(const[h,d]of e.entries()){const u=zi(n.get(h));switch(u.kind){case"committed":{o=!0,this.settleReplaySuccess(d,u.value,u.commitCursor);break}case"errored":{c||=Q(u.error),this.shouldRequeueReplayFailure(u.error,i)&&!this.spendsLastReplayAttempt(d,u.error)?(this.noteReplayRetryDelay(s,u.error,i),a.push(d)):this.settleReplayTerminal(d,u.error);break}case"unanswered":{const p=Ve();if(this.spendsLastReplayAttempt(d,p)){this.settleReplayTerminal(d,p);break}this.noteReplayRetryDelay(s,p,i),a.push(d);break}default:o=!0,this.settleReplayUndecodable(d,u.error,u.commitCursor)}}return o&&!c&&this.noteCredentialAccepted(i),a}}export{Ue as LunoraClient};