@lunora/client 1.0.0-alpha.30 → 1.0.0-alpha.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/index.d.mts +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/index.d.mts +92 -4
- package/dist/index.d.ts +92 -4
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/{LunoraClient-DDEoZdgP.mjs → LunoraClient-DRo2LNe9.mjs} +1 -1
- package/dist/packem_shared/OfflineQueue-l0_y9TmK.mjs +1 -0
- package/dist/packem_shared/RETIRE_AFTER_DURABLE_SEQ_ADVANCE-D96iRJDY.mjs +1 -0
- package/dist/packem_shared/{createServerClient-B7KqO8tv.mjs → createServerClient-DX7Dk2w2.mjs} +1 -1
- package/dist/packem_shared/{lunora-client.d-Bt65hm_E.d.ts → lunora-client.d-DLcz4GRz.d.mts} +11 -3
- package/dist/packem_shared/{lunora-client.d-Bt65hm_E.d.mts → lunora-client.d-DLcz4GRz.d.ts} +11 -3
- package/dist/packem_shared/offline-queue-b-v6bWWd.mjs +1 -0
- package/dist/packem_shared/{preload.d-BmztUzzG.d.mts → preload.d-C1M_N5mE.d.mts} +1 -1
- package/dist/packem_shared/{preload.d-DGGRMWB5.d.ts → preload.d-hkFC0Uno.d.ts} +1 -1
- package/dist/query/index.d.mts +2 -2
- package/dist/query/index.d.ts +2 -2
- package/dist/ssr/index.d.mts +3 -3
- package/dist/ssr/index.d.ts +3 -3
- package/dist/ssr/index.mjs +1 -1
- package/package.json +2 -2
- package/dist/packem_shared/OfflineQueue-B603_q8m.mjs +0 -1
- package/dist/packem_shared/offline-queue-D73Dq95V.mjs +0 -1
package/dist/auth/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-
|
|
1
|
+
import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-DLcz4GRz.mjs";
|
|
2
2
|
import '@lunora/runtime';
|
|
3
3
|
interface IdentityStore {
|
|
4
4
|
/** Read the current resolved user, or `null` when signed out / not yet resolved. */
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-
|
|
1
|
+
import { U as User, L as LunoraClient } from "../packem_shared/lunora-client.d-DLcz4GRz.js";
|
|
2
2
|
import '@lunora/runtime';
|
|
3
3
|
interface IdentityStore {
|
|
4
4
|
/** Read the current resolved user, or `null` when signed out / not yet resolved. */
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,95 @@
|
|
|
1
|
-
import { c as PersistenceAdapter, B as BookmarkStorage, S as SubscriptionError, H as HttpStreamRef, d as HttpStreamArgsOf, e as HttpStreamChunkOf, f as StreamIterable, F as FunctionReference, A as ArgsOf, M as MutationCallOptions, R as ReturnOf, O as OfflineQueueOptions, Q as QueryCacheAdapter, g as ReconnectOptions, L as LunoraClient } from "./packem_shared/lunora-client.d-
|
|
2
|
-
export { type h as BatchSlot, C as CONFLICT_ERROR_CODE, type i as CachedQuery, type j as ClientDebugShard, type k as ClientDebugSnapshot, type l as ClientDebugSubscription, type m as ClientMessage, type n as ClientQueryRef, type o as ClientShapeSubscribeMessage, type p as ClientShapeUnsubscribeMessage, type q as ConnectionStatus, D as DEFAULT_MAX_BUFFER, type r as FunctionArgumentDescriptor, type s as FunctionDescriptor, type G as GlobalFacetResult, type t as GlobalFacetValue, type u as GlobalFilterClause, type v as GlobalTableInfo, type w as GlobalTablePage, type x as HttpStreamCallArgs, type y as LunoraClientError, type z as LunoraClientOptions, type E as LunoraErrorCode, type I as MutationSettledEvent, type J as OptimisticLocalStore, type K as OptimisticUpdate, type N as OutboxMutation, type T as OutboxSink, type V as PersistedMutation, type P as Preloaded, type W as RowOp, type X as RpcEnvelope, type Y as RpcResponseBody, type Z as ScheduleRecord, 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 StreamHandle, type a9 as SubscriptionCallback, type b as SubscriptionErrorCallback, aa as SubscriptionRegistry, type ab as SubscriptionState, type ac as SyncWatermark, type a as Unsubscribe, type U as User, type ad as WorkflowInstanceAction, type ae as WorkflowInstanceDetail, type af as WorkflowInstancePage, type ag as WorkflowInstanceStatus, type ah as WorkflowInstanceSummary, type ai as WorkflowStepDetail, type aj as WsTokenProvider, ak as createClientQuery, al as createLocalStore, am as createStream, an as getErrorCode, ao as getRetryAfterMs, ap as isConflictError, aq as isForbiddenError, ar as isRateLimitedError, as as isUnauthorizedError } from "./packem_shared/lunora-client.d-
|
|
3
|
-
export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-
|
|
1
|
+
import { c as PersistenceAdapter, B as BookmarkStorage, S as SubscriptionError, H as HttpStreamRef, d as HttpStreamArgsOf, e as HttpStreamChunkOf, f as StreamIterable, F as FunctionReference, A as ArgsOf, M as MutationCallOptions, R as ReturnOf, O as OfflineQueueOptions, Q as QueryCacheAdapter, g as ReconnectOptions, L as LunoraClient } from "./packem_shared/lunora-client.d-DLcz4GRz.mjs";
|
|
2
|
+
export { type h as BatchSlot, C as CONFLICT_ERROR_CODE, type i as CachedQuery, type j as ClientDebugShard, type k as ClientDebugSnapshot, type l as ClientDebugSubscription, type m as ClientMessage, type n as ClientQueryRef, type o as ClientShapeSubscribeMessage, type p as ClientShapeUnsubscribeMessage, type q as ConnectionStatus, D as DEFAULT_MAX_BUFFER, type r as FunctionArgumentDescriptor, type s as FunctionDescriptor, type G as GlobalFacetResult, type t as GlobalFacetValue, type u as GlobalFilterClause, type v as GlobalTableInfo, type w as GlobalTablePage, type x as HttpStreamCallArgs, type y as LunoraClientError, type z as LunoraClientOptions, type E as LunoraErrorCode, type I as MutationSettledEvent, type J as OptimisticLocalStore, type K as OptimisticUpdate, type N as OutboxMutation, type T as OutboxSink, type V as PersistedMutation, type P as Preloaded, type W as RowOp, type X as RpcEnvelope, type Y as RpcResponseBody, type Z as ScheduleRecord, 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 StreamHandle, type a9 as SubscriptionCallback, type b as SubscriptionErrorCallback, aa as SubscriptionRegistry, type ab as SubscriptionState, type ac as SyncWatermark, type a as Unsubscribe, type U as User, type ad as WorkflowInstanceAction, type ae as WorkflowInstanceDetail, type af as WorkflowInstancePage, type ag as WorkflowInstanceStatus, type ah as WorkflowInstanceSummary, type ai as WorkflowStepDetail, type aj as WsTokenProvider, ak as createClientQuery, al as createLocalStore, am as createStream, an as getErrorCode, ao as getRetryAfterMs, ap as isConflictError, aq as isForbiddenError, ar as isRateLimitedError, as as isUnauthorizedError } from "./packem_shared/lunora-client.d-DLcz4GRz.mjs";
|
|
3
|
+
export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-C1M_N5mE.mjs";
|
|
4
4
|
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';
|
|
5
|
+
/**
|
|
6
|
+
* Optimistic-reconcile logic shared by every `@lunora/*` framework adapter's
|
|
7
|
+
* agent-chat surface (`@lunora/react` `useAgentChat`, plus the `@lunora/vue`,
|
|
8
|
+
* `@lunora/solid`, `@lunora/svelte`, and `@lunora/angular` counterparts). The
|
|
9
|
+
* adapters keep only their framework-specific state plumbing
|
|
10
|
+
* (`useState` / `.value` / `.set()` / a store) and delegate the pure merge decision
|
|
11
|
+
* here, so the heuristic lives — and is tested — in exactly one place.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* The durable-message shape the reconcile reads: a structural subset of each
|
|
15
|
+
* adapter's `AgentChatMessage` (itself a client-safe mirror of `@lunora/agent`'s
|
|
16
|
+
* `AgentMessageRow`). Only `content`, `role`, and the globally-monotonic `seq` are
|
|
17
|
+
* consulted; adapters pass their fuller row type, which is assignable to this.
|
|
18
|
+
*/
|
|
19
|
+
interface ReconcileDurableMessage {
|
|
20
|
+
content: string;
|
|
21
|
+
role: "assistant" | "system" | "tool" | "user";
|
|
22
|
+
seq: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A local optimistic user turn awaiting server acknowledgement. `id` is a
|
|
26
|
+
* client-generated handle the adapter uses to roll the row back on a failed send;
|
|
27
|
+
* the reconcile itself reads only `content` and `maxDurableSeqAtSend`.
|
|
28
|
+
*/
|
|
29
|
+
interface OptimisticMessage {
|
|
30
|
+
content: string;
|
|
31
|
+
id: number;
|
|
32
|
+
/**
|
|
33
|
+
* The highest durable `seq` present when this row was sent. The reconcile
|
|
34
|
+
* retires the row when a durable `user` row with matching `content` lands at a
|
|
35
|
+
* STRICTLY GREATER `seq` (i.e. after the send) — window-independent because
|
|
36
|
+
* `seq` is globally monotonic, not a positional count. Also the age baseline for
|
|
37
|
+
* the {@link RETIRE_AFTER_DURABLE_SEQ_ADVANCE} fallback.
|
|
38
|
+
*/
|
|
39
|
+
maxDurableSeqAtSend: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The highest `seq` across `messages`, or `-1` when empty. Used both to capture an
|
|
43
|
+
* optimistic row's `maxDurableSeqAtSend` at send time and to base the synthetic
|
|
44
|
+
* seqs of rendered optimistic rows above the highest real durable seq (not just
|
|
45
|
+
* `messages.length`, which under-counts when durable rows have gaps), so a
|
|
46
|
+
* placeholder seq never collides with a real one.
|
|
47
|
+
*/
|
|
48
|
+
declare const maxSeq: (messages: ReadonlyArray<{
|
|
49
|
+
seq: number;
|
|
50
|
+
}>) => number;
|
|
51
|
+
/**
|
|
52
|
+
* Secondary, windowed fallback: retire a pending optimistic row once the durable
|
|
53
|
+
* history's highest `seq` has advanced at least this far past the value seen at
|
|
54
|
+
* send, even though no matching-content user row is currently visible to claim it.
|
|
55
|
+
* This covers the pathological "identical content already present at send time"
|
|
56
|
+
* case, where no user row with a STRICTLY GREATER `seq` than the send-time max will
|
|
57
|
+
* ever appear for the primary content match to consume (e.g. the acknowledging row
|
|
58
|
+
* was evicted by a bounded `limit` before reconcile could see it). `seq` is globally
|
|
59
|
+
* monotonic, so it keeps climbing even when the visible user-row COUNT does not.
|
|
60
|
+
*
|
|
61
|
+
* The `2` is a heuristic threshold, NOT an invariant about turn shape. It is
|
|
62
|
+
* tempting to read it as "one turn == a user row and an assistant row (+2)", but
|
|
63
|
+
* `@lunora/agent`'s tool-loop turns can persist MANY rows, and an ERRORED turn
|
|
64
|
+
* persists only the user row (+1). Those non-(+2) turns are retired by the PRIMARY
|
|
65
|
+
* seq-based content match below (which sees the user row land at a greater `seq`),
|
|
66
|
+
* never by this count-based fallback. The fully robust fix is a server-echoed
|
|
67
|
+
* correlation id on each persisted user row (deferred — see plan 188).
|
|
68
|
+
*
|
|
69
|
+
* KNOWN LIMITATION (inherent to a client-only heuristic): on an ownerless /
|
|
70
|
+
* `instanceId`-less thread a FOREIGN writer that advances `seq` by >= 2 between this
|
|
71
|
+
* row's send and its own acknowledgement can trip this fallback and retire the row a
|
|
72
|
+
* beat early. The correlation id closes that gap; until then it is the accepted
|
|
73
|
+
* residual edge.
|
|
74
|
+
*/
|
|
75
|
+
declare const RETIRE_AFTER_DURABLE_SEQ_ADVANCE = 2;
|
|
76
|
+
/**
|
|
77
|
+
* Drop the optimistic user turns the durable history has now caught up on. Pure —
|
|
78
|
+
* it reads only the two arrays plus values captured on each pending row at send
|
|
79
|
+
* time (no clock, no state mutation), so it is safe to run in render.
|
|
80
|
+
*
|
|
81
|
+
* The primary retire condition: a durable `user` row with the same `content` exists
|
|
82
|
+
* whose `seq` is STRICTLY GREATER than the row's `maxDurableSeqAtSend` — i.e. a user
|
|
83
|
+
* row that landed AFTER the send. This is window-independent (it matches on monotonic
|
|
84
|
+
* `seq`, not a positional count), so it retires the normal turn AND an errored
|
|
85
|
+
* single-row (+1) turn even under a saturated, sliding `limit`. Each durable row is
|
|
86
|
+
* consumed at most once (the `consumed` set), so repeated identical prompts sent
|
|
87
|
+
* back-to-back each wait for their OWN durable row instead of collapsing onto one.
|
|
88
|
+
*
|
|
89
|
+
* Failing that, the {@link RETIRE_AFTER_DURABLE_SEQ_ADVANCE} windowed fallback fires
|
|
90
|
+
* (see its doc) for the "identical content already present" pathological case.
|
|
91
|
+
*/
|
|
92
|
+
declare const reconcileOptimistic: (optimistic: ReadonlyArray<OptimisticMessage>, durable: ReadonlyArray<ReconcileDurableMessage>) => OptimisticMessage[];
|
|
5
93
|
/**
|
|
6
94
|
* The slice of React Native's `AsyncStorage` (or any async key/value store —
|
|
7
95
|
* Expo `SecureStore`, a wrapped `localForage`, an in-memory map in tests) this
|
|
@@ -630,4 +718,4 @@ declare const sendToSw: (sw: ServiceWorker | null, message: ClientToSwMessage, e
|
|
|
630
718
|
* Create a reply for a client message (call from inside the SW).
|
|
631
719
|
*/
|
|
632
720
|
declare const createReply: (original: ClientToSwMessage, payload?: unknown) => SwToClientMessage;
|
|
633
|
-
export { type ArgsOf, type AsyncStorageLike, type AsyncStoragePersistenceOptions, type BookmarkStorage, ClientServiceWorker, type ClientSwOptions, type ClientToSwMessage, type FunctionReference, type HttpStreamArgsOf, type HttpStreamChunkOf, type HttpStreamOptions, type HttpStreamRef, type IndexedDbPersistenceOptions, type IndexedDbQueryCacheOptions, LunoraClient, type MutationCallOptions, type MutationDelta, type MutationRunnerSinks, type MutatorHandle, type MutatorRunnerSinks, type MutatorTransaction, OfflineQueue, type OfflineQueueOptions, type PersistenceAdapter, type QueryCacheAdapter, type QueuedMutation, type ReconnectCalculator, type ReconnectOptions, type ReturnOf, type ServiceWorkerStatus, type StreamIterable, type SubscriptionError, type SwToClientMessage, TabCoordinator, applyDelta, createAsyncStoragePersistence, createInMemoryBookmarkStorage, createInMemoryPersistence, createInMemoryQueryCache, createIndexedDbPersistence, createIndexedDbQueryCache, createMutationRunner, createMutatorRunner, createReconnect, createReply, createSnapshotPrecondition, httpStream, isMutationDelta, queryCacheKey, sendToSw };
|
|
721
|
+
export { type ArgsOf, type AsyncStorageLike, type AsyncStoragePersistenceOptions, type BookmarkStorage, ClientServiceWorker, type ClientSwOptions, type ClientToSwMessage, type FunctionReference, type HttpStreamArgsOf, type HttpStreamChunkOf, type HttpStreamOptions, type HttpStreamRef, type IndexedDbPersistenceOptions, type IndexedDbQueryCacheOptions, LunoraClient, type MutationCallOptions, type MutationDelta, type MutationRunnerSinks, type MutatorHandle, type MutatorRunnerSinks, type MutatorTransaction, OfflineQueue, type OfflineQueueOptions, type OptimisticMessage, type PersistenceAdapter, type QueryCacheAdapter, type QueuedMutation, RETIRE_AFTER_DURABLE_SEQ_ADVANCE, type ReconcileDurableMessage, type ReconnectCalculator, type ReconnectOptions, type ReturnOf, type ServiceWorkerStatus, type StreamIterable, type SubscriptionError, type SwToClientMessage, TabCoordinator, applyDelta, createAsyncStoragePersistence, createInMemoryBookmarkStorage, createInMemoryPersistence, createInMemoryQueryCache, createIndexedDbPersistence, createIndexedDbQueryCache, createMutationRunner, createMutatorRunner, createReconnect, createReply, createSnapshotPrecondition, httpStream, isMutationDelta, maxSeq, queryCacheKey, reconcileOptimistic, sendToSw };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,95 @@
|
|
|
1
|
-
import { c as PersistenceAdapter, B as BookmarkStorage, S as SubscriptionError, H as HttpStreamRef, d as HttpStreamArgsOf, e as HttpStreamChunkOf, f as StreamIterable, F as FunctionReference, A as ArgsOf, M as MutationCallOptions, R as ReturnOf, O as OfflineQueueOptions, Q as QueryCacheAdapter, g as ReconnectOptions, L as LunoraClient } from "./packem_shared/lunora-client.d-
|
|
2
|
-
export { type h as BatchSlot, C as CONFLICT_ERROR_CODE, type i as CachedQuery, type j as ClientDebugShard, type k as ClientDebugSnapshot, type l as ClientDebugSubscription, type m as ClientMessage, type n as ClientQueryRef, type o as ClientShapeSubscribeMessage, type p as ClientShapeUnsubscribeMessage, type q as ConnectionStatus, D as DEFAULT_MAX_BUFFER, type r as FunctionArgumentDescriptor, type s as FunctionDescriptor, type G as GlobalFacetResult, type t as GlobalFacetValue, type u as GlobalFilterClause, type v as GlobalTableInfo, type w as GlobalTablePage, type x as HttpStreamCallArgs, type y as LunoraClientError, type z as LunoraClientOptions, type E as LunoraErrorCode, type I as MutationSettledEvent, type J as OptimisticLocalStore, type K as OptimisticUpdate, type N as OutboxMutation, type T as OutboxSink, type V as PersistedMutation, type P as Preloaded, type W as RowOp, type X as RpcEnvelope, type Y as RpcResponseBody, type Z as ScheduleRecord, 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 StreamHandle, type a9 as SubscriptionCallback, type b as SubscriptionErrorCallback, aa as SubscriptionRegistry, type ab as SubscriptionState, type ac as SyncWatermark, type a as Unsubscribe, type U as User, type ad as WorkflowInstanceAction, type ae as WorkflowInstanceDetail, type af as WorkflowInstancePage, type ag as WorkflowInstanceStatus, type ah as WorkflowInstanceSummary, type ai as WorkflowStepDetail, type aj as WsTokenProvider, ak as createClientQuery, al as createLocalStore, am as createStream, an as getErrorCode, ao as getRetryAfterMs, ap as isConflictError, aq as isForbiddenError, ar as isRateLimitedError, as as isUnauthorizedError } from "./packem_shared/lunora-client.d-
|
|
3
|
-
export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-
|
|
1
|
+
import { c as PersistenceAdapter, B as BookmarkStorage, S as SubscriptionError, H as HttpStreamRef, d as HttpStreamArgsOf, e as HttpStreamChunkOf, f as StreamIterable, F as FunctionReference, A as ArgsOf, M as MutationCallOptions, R as ReturnOf, O as OfflineQueueOptions, Q as QueryCacheAdapter, g as ReconnectOptions, L as LunoraClient } from "./packem_shared/lunora-client.d-DLcz4GRz.js";
|
|
2
|
+
export { type h as BatchSlot, C as CONFLICT_ERROR_CODE, type i as CachedQuery, type j as ClientDebugShard, type k as ClientDebugSnapshot, type l as ClientDebugSubscription, type m as ClientMessage, type n as ClientQueryRef, type o as ClientShapeSubscribeMessage, type p as ClientShapeUnsubscribeMessage, type q as ConnectionStatus, D as DEFAULT_MAX_BUFFER, type r as FunctionArgumentDescriptor, type s as FunctionDescriptor, type G as GlobalFacetResult, type t as GlobalFacetValue, type u as GlobalFilterClause, type v as GlobalTableInfo, type w as GlobalTablePage, type x as HttpStreamCallArgs, type y as LunoraClientError, type z as LunoraClientOptions, type E as LunoraErrorCode, type I as MutationSettledEvent, type J as OptimisticLocalStore, type K as OptimisticUpdate, type N as OutboxMutation, type T as OutboxSink, type V as PersistedMutation, type P as Preloaded, type W as RowOp, type X as RpcEnvelope, type Y as RpcResponseBody, type Z as ScheduleRecord, 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 StreamHandle, type a9 as SubscriptionCallback, type b as SubscriptionErrorCallback, aa as SubscriptionRegistry, type ab as SubscriptionState, type ac as SyncWatermark, type a as Unsubscribe, type U as User, type ad as WorkflowInstanceAction, type ae as WorkflowInstanceDetail, type af as WorkflowInstancePage, type ag as WorkflowInstanceStatus, type ah as WorkflowInstanceSummary, type ai as WorkflowStepDetail, type aj as WsTokenProvider, ak as createClientQuery, al as createLocalStore, am as createStream, an as getErrorCode, ao as getRetryAfterMs, ap as isConflictError, aq as isForbiddenError, ar as isRateLimitedError, as as isUnauthorizedError } from "./packem_shared/lunora-client.d-DLcz4GRz.js";
|
|
3
|
+
export { p as preloadQuery, a as preloadedQueryResult } from "./packem_shared/preload.d-hkFC0Uno.js";
|
|
4
4
|
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';
|
|
5
|
+
/**
|
|
6
|
+
* Optimistic-reconcile logic shared by every `@lunora/*` framework adapter's
|
|
7
|
+
* agent-chat surface (`@lunora/react` `useAgentChat`, plus the `@lunora/vue`,
|
|
8
|
+
* `@lunora/solid`, `@lunora/svelte`, and `@lunora/angular` counterparts). The
|
|
9
|
+
* adapters keep only their framework-specific state plumbing
|
|
10
|
+
* (`useState` / `.value` / `.set()` / a store) and delegate the pure merge decision
|
|
11
|
+
* here, so the heuristic lives — and is tested — in exactly one place.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* The durable-message shape the reconcile reads: a structural subset of each
|
|
15
|
+
* adapter's `AgentChatMessage` (itself a client-safe mirror of `@lunora/agent`'s
|
|
16
|
+
* `AgentMessageRow`). Only `content`, `role`, and the globally-monotonic `seq` are
|
|
17
|
+
* consulted; adapters pass their fuller row type, which is assignable to this.
|
|
18
|
+
*/
|
|
19
|
+
interface ReconcileDurableMessage {
|
|
20
|
+
content: string;
|
|
21
|
+
role: "assistant" | "system" | "tool" | "user";
|
|
22
|
+
seq: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A local optimistic user turn awaiting server acknowledgement. `id` is a
|
|
26
|
+
* client-generated handle the adapter uses to roll the row back on a failed send;
|
|
27
|
+
* the reconcile itself reads only `content` and `maxDurableSeqAtSend`.
|
|
28
|
+
*/
|
|
29
|
+
interface OptimisticMessage {
|
|
30
|
+
content: string;
|
|
31
|
+
id: number;
|
|
32
|
+
/**
|
|
33
|
+
* The highest durable `seq` present when this row was sent. The reconcile
|
|
34
|
+
* retires the row when a durable `user` row with matching `content` lands at a
|
|
35
|
+
* STRICTLY GREATER `seq` (i.e. after the send) — window-independent because
|
|
36
|
+
* `seq` is globally monotonic, not a positional count. Also the age baseline for
|
|
37
|
+
* the {@link RETIRE_AFTER_DURABLE_SEQ_ADVANCE} fallback.
|
|
38
|
+
*/
|
|
39
|
+
maxDurableSeqAtSend: number;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The highest `seq` across `messages`, or `-1` when empty. Used both to capture an
|
|
43
|
+
* optimistic row's `maxDurableSeqAtSend` at send time and to base the synthetic
|
|
44
|
+
* seqs of rendered optimistic rows above the highest real durable seq (not just
|
|
45
|
+
* `messages.length`, which under-counts when durable rows have gaps), so a
|
|
46
|
+
* placeholder seq never collides with a real one.
|
|
47
|
+
*/
|
|
48
|
+
declare const maxSeq: (messages: ReadonlyArray<{
|
|
49
|
+
seq: number;
|
|
50
|
+
}>) => number;
|
|
51
|
+
/**
|
|
52
|
+
* Secondary, windowed fallback: retire a pending optimistic row once the durable
|
|
53
|
+
* history's highest `seq` has advanced at least this far past the value seen at
|
|
54
|
+
* send, even though no matching-content user row is currently visible to claim it.
|
|
55
|
+
* This covers the pathological "identical content already present at send time"
|
|
56
|
+
* case, where no user row with a STRICTLY GREATER `seq` than the send-time max will
|
|
57
|
+
* ever appear for the primary content match to consume (e.g. the acknowledging row
|
|
58
|
+
* was evicted by a bounded `limit` before reconcile could see it). `seq` is globally
|
|
59
|
+
* monotonic, so it keeps climbing even when the visible user-row COUNT does not.
|
|
60
|
+
*
|
|
61
|
+
* The `2` is a heuristic threshold, NOT an invariant about turn shape. It is
|
|
62
|
+
* tempting to read it as "one turn == a user row and an assistant row (+2)", but
|
|
63
|
+
* `@lunora/agent`'s tool-loop turns can persist MANY rows, and an ERRORED turn
|
|
64
|
+
* persists only the user row (+1). Those non-(+2) turns are retired by the PRIMARY
|
|
65
|
+
* seq-based content match below (which sees the user row land at a greater `seq`),
|
|
66
|
+
* never by this count-based fallback. The fully robust fix is a server-echoed
|
|
67
|
+
* correlation id on each persisted user row (deferred — see plan 188).
|
|
68
|
+
*
|
|
69
|
+
* KNOWN LIMITATION (inherent to a client-only heuristic): on an ownerless /
|
|
70
|
+
* `instanceId`-less thread a FOREIGN writer that advances `seq` by >= 2 between this
|
|
71
|
+
* row's send and its own acknowledgement can trip this fallback and retire the row a
|
|
72
|
+
* beat early. The correlation id closes that gap; until then it is the accepted
|
|
73
|
+
* residual edge.
|
|
74
|
+
*/
|
|
75
|
+
declare const RETIRE_AFTER_DURABLE_SEQ_ADVANCE = 2;
|
|
76
|
+
/**
|
|
77
|
+
* Drop the optimistic user turns the durable history has now caught up on. Pure —
|
|
78
|
+
* it reads only the two arrays plus values captured on each pending row at send
|
|
79
|
+
* time (no clock, no state mutation), so it is safe to run in render.
|
|
80
|
+
*
|
|
81
|
+
* The primary retire condition: a durable `user` row with the same `content` exists
|
|
82
|
+
* whose `seq` is STRICTLY GREATER than the row's `maxDurableSeqAtSend` — i.e. a user
|
|
83
|
+
* row that landed AFTER the send. This is window-independent (it matches on monotonic
|
|
84
|
+
* `seq`, not a positional count), so it retires the normal turn AND an errored
|
|
85
|
+
* single-row (+1) turn even under a saturated, sliding `limit`. Each durable row is
|
|
86
|
+
* consumed at most once (the `consumed` set), so repeated identical prompts sent
|
|
87
|
+
* back-to-back each wait for their OWN durable row instead of collapsing onto one.
|
|
88
|
+
*
|
|
89
|
+
* Failing that, the {@link RETIRE_AFTER_DURABLE_SEQ_ADVANCE} windowed fallback fires
|
|
90
|
+
* (see its doc) for the "identical content already present" pathological case.
|
|
91
|
+
*/
|
|
92
|
+
declare const reconcileOptimistic: (optimistic: ReadonlyArray<OptimisticMessage>, durable: ReadonlyArray<ReconcileDurableMessage>) => OptimisticMessage[];
|
|
5
93
|
/**
|
|
6
94
|
* The slice of React Native's `AsyncStorage` (or any async key/value store —
|
|
7
95
|
* Expo `SecureStore`, a wrapped `localForage`, an in-memory map in tests) this
|
|
@@ -630,4 +718,4 @@ declare const sendToSw: (sw: ServiceWorker | null, message: ClientToSwMessage, e
|
|
|
630
718
|
* Create a reply for a client message (call from inside the SW).
|
|
631
719
|
*/
|
|
632
720
|
declare const createReply: (original: ClientToSwMessage, payload?: unknown) => SwToClientMessage;
|
|
633
|
-
export { type ArgsOf, type AsyncStorageLike, type AsyncStoragePersistenceOptions, type BookmarkStorage, ClientServiceWorker, type ClientSwOptions, type ClientToSwMessage, type FunctionReference, type HttpStreamArgsOf, type HttpStreamChunkOf, type HttpStreamOptions, type HttpStreamRef, type IndexedDbPersistenceOptions, type IndexedDbQueryCacheOptions, LunoraClient, type MutationCallOptions, type MutationDelta, type MutationRunnerSinks, type MutatorHandle, type MutatorRunnerSinks, type MutatorTransaction, OfflineQueue, type OfflineQueueOptions, type PersistenceAdapter, type QueryCacheAdapter, type QueuedMutation, type ReconnectCalculator, type ReconnectOptions, type ReturnOf, type ServiceWorkerStatus, type StreamIterable, type SubscriptionError, type SwToClientMessage, TabCoordinator, applyDelta, createAsyncStoragePersistence, createInMemoryBookmarkStorage, createInMemoryPersistence, createInMemoryQueryCache, createIndexedDbPersistence, createIndexedDbQueryCache, createMutationRunner, createMutatorRunner, createReconnect, createReply, createSnapshotPrecondition, httpStream, isMutationDelta, queryCacheKey, sendToSw };
|
|
721
|
+
export { type ArgsOf, type AsyncStorageLike, type AsyncStoragePersistenceOptions, type BookmarkStorage, ClientServiceWorker, type ClientSwOptions, type ClientToSwMessage, type FunctionReference, type HttpStreamArgsOf, type HttpStreamChunkOf, type HttpStreamOptions, type HttpStreamRef, type IndexedDbPersistenceOptions, type IndexedDbQueryCacheOptions, LunoraClient, type MutationCallOptions, type MutationDelta, type MutationRunnerSinks, type MutatorHandle, type MutatorRunnerSinks, type MutatorTransaction, OfflineQueue, type OfflineQueueOptions, type OptimisticMessage, type PersistenceAdapter, type QueryCacheAdapter, type QueuedMutation, RETIRE_AFTER_DURABLE_SEQ_ADVANCE, type ReconcileDurableMessage, type ReconnectCalculator, type ReconnectOptions, type ReturnOf, type ServiceWorkerStatus, type StreamIterable, type SubscriptionError, type SwToClientMessage, TabCoordinator, applyDelta, createAsyncStoragePersistence, createInMemoryBookmarkStorage, createInMemoryPersistence, createInMemoryQueryCache, createIndexedDbPersistence, createIndexedDbQueryCache, createMutationRunner, createMutatorRunner, createReconnect, createReply, createSnapshotPrecondition, httpStream, isMutationDelta, maxSeq, queryCacheKey, reconcileOptimistic, sendToSw };
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{RETIRE_AFTER_DURABLE_SEQ_ADVANCE as o,maxSeq as t,reconcileOptimistic as a}from"./packem_shared/RETIRE_AFTER_DURABLE_SEQ_ADVANCE-D96iRJDY.mjs";import{createAsyncStoragePersistence as n}from"./packem_shared/createAsyncStoragePersistence-BRLqeXsC.mjs";import{default as p}from"./packem_shared/createInMemoryBookmarkStorage-DCd5Ej-t.mjs";import{createClientQuery as f}from"./packem_shared/createClientQuery-CrdRoicO.mjs";import{TabCoordinator as s}from"./packem_shared/TabCoordinator-ijLic02x.mjs";import{applyDelta as d,isMutationDelta as l}from"./packem_shared/applyDelta-DXqQORbM.mjs";import{CONFLICT_ERROR_CODE as y,getErrorCode as E,getRetryAfterMs as C,isConflictError as S,isForbiddenError as A,isRateLimitedError as D,isUnauthorizedError as M}from"./packem_shared/CONFLICT_ERROR_CODE-B2SU0CaJ.mjs";import{httpStream as I}from"./packem_shared/httpStream-Cz4_QyjV.mjs";import{c as h}from"./packem_shared/local-store-C53xDvEr.mjs";import{LunoraClient as L}from"./packem_shared/LunoraClient-DRo2LNe9.mjs";import{createMutationRunner as b}from"./packem_shared/createMutationRunner-lQXH8Amk.mjs";import{createMutatorRunner as O}from"./packem_shared/createMutatorRunner-BVzo0FBZ.mjs";import{c as U}from"./packem_shared/offline-queue-b-v6bWWd.mjs";import{createInMemoryPersistence as B,createIndexedDbPersistence as q}from"./packem_shared/createInMemoryPersistence-CQYXy8UP.mjs";import{preloadQuery as v,preloadedQueryResult as w}from"./packem_shared/preloadQuery-DjwSjFwt.mjs";import{createInMemoryQueryCache as K,createIndexedDbQueryCache as V,queryCacheKey as W}from"./packem_shared/createInMemoryQueryCache-DjCKrLjk.mjs";import{createReconnect as j}from"./packem_shared/createReconnect-CFT7YRSR.mjs";import{default as H}from"./packem_shared/createSnapshotPrecondition-DOKRAJ4b.mjs";import{DEFAULT_MAX_BUFFER as Y,createStream as Z}from"./packem_shared/DEFAULT_MAX_BUFFER-TBn2s7Rz.mjs";import{SubscriptionRegistry as ee}from"./packem_shared/SubscriptionRegistry-CdrOD7sZ.mjs";import{ClientServiceWorker as oe}from"./packem_shared/ClientServiceWorker-CRQ5yl7-.mjs";import{createReply as ae,sendToSw as ce}from"./packem_shared/createReply-DF0jRsv-.mjs";export{y as CONFLICT_ERROR_CODE,oe as ClientServiceWorker,Y as DEFAULT_MAX_BUFFER,L as LunoraClient,U as OfflineQueue,o as RETIRE_AFTER_DURABLE_SEQ_ADVANCE,ee as SubscriptionRegistry,s as TabCoordinator,d as applyDelta,n as createAsyncStoragePersistence,f as createClientQuery,p as createInMemoryBookmarkStorage,B as createInMemoryPersistence,K as createInMemoryQueryCache,q as createIndexedDbPersistence,V as createIndexedDbQueryCache,h as createLocalStore,b as createMutationRunner,O as createMutatorRunner,j as createReconnect,ae as createReply,H as createSnapshotPrecondition,Z as createStream,E as getErrorCode,C as getRetryAfterMs,I as httpStream,S as isConflictError,A as isForbiddenError,l as isMutationDelta,D as isRateLimitedError,M as isUnauthorizedError,t as maxSeq,v as preloadQuery,w as preloadedQueryResult,W as queryCacheKey,a as reconcileOptimistic,ce as sendToSw};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{LunoraError as u}from"@lunora/errors";import{t as I,c as g,f as W}from"./wire-key-D_zOxXK4.mjs";import D from"./createInMemoryBookmarkStorage-DCd5Ej-t.mjs";import{ClientQueryStore as H}from"./createClientQuery-CrdRoicO.mjs";import{TabCoordinator as V}from"./TabCoordinator-ijLic02x.mjs";import{isMutationDelta as J,applyDelta as X}from"./applyDelta-DXqQORbM.mjs";import{httpStream as Y}from"./httpStream-Cz4_QyjV.mjs";import{f as A,a as Z,d as F,n as x,c as tt}from"./local-store-C53xDvEr.mjs";import{c as et,u as $,d as st,s as it}from"./offline-queue-D73Dq95V.mjs";import{resolvePersistenceAdapter as nt}from"./createInMemoryPersistence-CQYXy8UP.mjs";import{resolveQueryCacheAdapter as rt,queryCacheKey as R}from"./createInMemoryQueryCache-DjCKrLjk.mjs";import{createReconnect as M}from"./createReconnect-CFT7YRSR.mjs";import{createStream as ot}from"./DEFAULT_MAX_BUFFER-TBn2s7Rz.mjs";import{SubscriptionRegistry as k}from"./SubscriptionRegistry-CdrOD7sZ.mjs";const _=500,at=(h,t)=>{if(h.size<t)return;const e=h.keys().next().value;e!==void 0&&h.delete(e)};class S{listeners=new Set;add(t){return this.listeners.add(t),()=>{this.listeners.delete(t)}}emit(...t){const[e]=t;for(const s of this.listeners)try{s(e)}catch{}}clear(){this.listeners.clear()}}const ct="/_lunora/rpc",K="/_lunora/rpc-batch",ht="/_lunora/ws",N=h=>h===void 0||h===""?"":`&bucket=${encodeURIComponent(h)}`,O=h=>{for(let t=h.length-1;t>=0;t-=1)h[t]?.()},ut=(h,t)=>{for(const e of t)e.op==="delete"?h.delete(e.key):e.value!==void 0&&h.set(e.key,e.value)},dt="lunora-ping",lt=3e4,mt=1e4,pt=250,ft=64,yt="/_lunora/admin/shard-traffic",wt="/_lunora/admin/scheduled",gt="/_lunora/admin/scheduled/status",bt="/_lunora/admin/scheduled/ws",vt="/_lunora/admin/scheduled/cancel",kt="/_lunora/admin/scheduled/dead",St="/_lunora/admin/scheduled/dead/retry",Ct="/_lunora/admin/scheduled/dead/cancel",Tt="/_lunora/admin/workflows/instances",It="/_lunora/admin/workflows/instance",Et="/_lunora/admin/workflows/status",E="/_lunora/admin/storage",Lt="/_lunora/admin/storage/url",At="/_lunora/admin/storage/buckets",Rt="/_lunora/admin/functions",_t="/_lunora/admin/cron-jobs",Nt="/_lunora/admin/cron-jobs/run",Ot="/_lunora/admin/openapi",Pt="/_lunora/admin/openrpc",Ft="/_lunora/admin/global/tables",xt="/_lunora/admin/global/table",$t="/_lunora/admin/global/facet",Mt="/_lunora/admin/vector/indexes",Kt="/_lunora/admin/vector/query",qt="/_lunora/admin/logs/archive",Ut="/_lunora/admin/kv/namespaces",Qt="/_lunora/admin/kv/keys",P="/_lunora/admin/kv/value",Bt="/_lunora/admin/auth/users",q="/_lunora/admin/auth/sessions",Wt="/_lunora/admin/auth/users/create",zt="/_lunora/admin/auth/users/role",Gt="/_lunora/admin/auth/users/ban",jt="/_lunora/admin/auth/users/unban",Dt="/_lunora/admin/auth/users/password",Ht="/_lunora/admin/auth/users/remove",Vt="/_lunora/admin/auth/users/impersonate",Jt="/_lunora/admin/auth/sessions/revoke",Xt="/_lunora/admin/auth/sessions/revoke-all",Yt="/_lunora/admin/auth/capabilities",Zt="/_lunora/admin/auth/users/update",te="/_lunora/admin/auth/accounts",ee="/_lunora/admin/auth/accounts/unlink",se="/_lunora/admin/auth/passkeys",ie="/_lunora/admin/auth/passkeys/delete",ne="/_lunora/admin/auth/two-factor/disable",re="/_lunora/admin/auth/organizations",oe="/_lunora/admin/auth/organizations/members",ae="/_lunora/admin/auth/organizations/invitations",ce="/_lunora/admin/auth/organizations/members/remove",he="/_lunora/admin/auth/organizations/invitations/cancel",ue="/_lunora/admin/auth/config",de="/_lunora/admin/auth/organizations/create",le="/_lunora/admin/auth/organizations/update",me="/_lunora/admin/auth/organizations/remove",pe="/_lunora/admin/auth/organizations/members/add",fe="/_lunora/admin/auth/organizations/members/invite",ye="/_lunora/admin/auth/organizations/members/role",we="/_lunora/admin/auth/organizations/teams",ge="/_lunora/admin/auth/organizations/teams/create",be="/_lunora/admin/auth/organizations/teams/update",ve="/_lunora/admin/auth/organizations/teams/remove",ke="/_lunora/admin/auth/organizations/teams/members",Se="/_lunora/admin/auth/organizations/teams/members/add",Ce="/_lunora/admin/auth/organizations/teams/members/remove",Te="/_lunora/admin/auth/organizations/roles",Ie="/_lunora/admin/auth/organizations/roles/create",Ee="/_lunora/admin/auth/organizations/roles/update",Le="/_lunora/admin/auth/organizations/roles/remove",Ae="/api/auth",Re="/get-session",U=h=>h.startsWith("https://")?`wss://${h.slice(8)}`:h.startsWith("http://")?`ws://${h.slice(7)}`:h,b=(h,t)=>`${h.endsWith("/")?h.slice(0,-1):h}${t}`,w=(h,t)=>{const e=new URLSearchParams;for(const[i,n]of Object.entries(t))n!==void 0&&n!==""&&e.set(i,String(n));const s=e.toString();return s===""?h:`${h}?${s}`},m=h=>h??"",_e=h=>{const t=h.error,e=typeof t?.code=="string"?t.code:void 0,s=typeof t?.message=="string"?t.message:void 0,i=(typeof h.message=="string"?h.message:void 0)??s??"stream error";return e===void 0?new Error(i):new u(e,i)},Q=h=>{const t=h.error,e=typeof t?.code=="string"?t.code:void 0,s=typeof t?.message=="string"?t.message:void 0;return{message:(typeof h.message=="string"?h.message:void 0)??s??"subscription error",...e===void 0?{}:{code:e}}},B=(h,t)=>{for(const e of h)try{e(t)}catch{}},Ne=new TextDecoder,Oe=h=>{if(typeof h=="string")return h;if(h instanceof ArrayBuffer)return Ne.decode(h)},y=(h,t)=>{if(!h.socket||h.wsState!=="open")return!1;try{return h.socket.send(JSON.stringify(t)),!0}catch{return!1}},C=h=>{const t=new Error(h.message??"request failed");return t.code=h.code,h.data!==void 0&&(t.data=g(h.data)),h.hint!==void 0&&(t.hint=h.hint),h.docsUrl!==void 0&&(t.docsUrl=h.docsUrl),t},v=(h,t)=>{try{return W(h)}catch(e){const s=e instanceof Error?e.message:String(e);throw new TypeError(`LunoraClient: cannot encode ${t} — ${s}`,e instanceof Error?{cause:e}:void 0)}},Pe=(h,t)=>{const e=Array.from({length:t});for(const s of h){if(typeof s.id!="number"||s.id<0||s.id>=t)continue;const i=s.body;e[s.id]=i&&"error"in i&&i.error?{error:C(i.error),ok:!1}:{ok:!0,value:g(i?.result)}}return e.map(s=>s??{error:new Error("batch call returned no result"),ok:!1})},Fe=new Set(["SHARD_ERROR","SHARD_UNAVAILABLE"]),xe=Promise.resolve();class z{static MAX_POKE_BUFFERS=256;static createClientQuery(t,e){return{defaultValue:e,key:t}}url;wsUrl;clientQueryStore;wsToken;authBasePath;fetchImpl;WebSocketImpl;bookmark;reconnectOptions;connectTimeoutMs;heartbeatIntervalMs;offlineQueue;outbox;clientId;readyResolved=!1;readyResolve;readyPromise;clientWatermarks=new Map;outboxMutationCounter=0;onPersistenceError;persistence;persistenceVersion;outboxLeaderRelease;queryCache;hydratedQueryCache=new Map;pendingCacheWrites=new Map;cacheFlushTimer;subscriptions=new k;tabCoordinator;connections=new Map;defaultConnectionContext;connectionContexts=new Map;connectionContextHolders=new Map;authToken=null;authSubject=void 0;queuedIdentities=new Map;closed=!1;authTokenListeners=new S;statusListeners=new S;tokenExpiredListeners=new S;mutationSettledListeners=new S;pendingChangeListeners=new S;whisperHandlers=new Map;lastStatus="idle";nextSubId=0;nextStreamId=0;streams=new Map;shapeSubscriptions=new Map;pokeBuffers=new Map;nextShapeId=0;constructor(t){this.url=t.url,this.wsUrl=t.wsUrl??b(U(t.url),ht),this.wsToken=t.wsToken;const e=t.authBasePath??Ae;this.authBasePath=e.endsWith("/")?e.slice(0,-1):e,this.fetchImpl=t.fetch??(typeof fetch=="function"?fetch.bind(globalThis):void 0),this.WebSocketImpl=t.WebSocket??(typeof WebSocket=="function"?WebSocket:void 0),this.bookmark=t.bookmarkStorage??D(),this.reconnectOptions=t.reconnect,this.heartbeatIntervalMs=t.heartbeatIntervalMs??lt,this.connectTimeoutMs=t.connectTimeoutMs??mt,this.defaultConnectionContext=t.connectionContext,this.persistence=nt(t.persistence,t.outbox===void 0),this.persistenceVersion=t.persistenceVersion,this.queryCache=rt(t.queryCache),this.onPersistenceError=t.offlineQueue?.onPersistenceError,this.clientQueryStore=new H,t.crossTabSync?(this.tabCoordinator=new V({onBecomeLeader:()=>{for(const s of this.subscriptions.all())this.ensureSocket(s.shardKey),this.sendSubscribeIfOpen(s)},onStopBeingLeader:()=>{for(const[s,i]of this.connections)i.socket?.close(),this.connections.delete(s)},onSubscriptionData:(s,i)=>{const n=this.subscriptions.get(s);if(n){n.serverBase=i;const r=n.optimisticLayers.length===0?i:A(i,n.optimisticLayers);n.lastValue=r;for(const o of n.callbacks)try{o(r)}catch{}}},onSubscriptionError:(s,i)=>{const n=this.subscriptions.get(s);if(n)for(const r of n.errorCallbacks)try{r(i)}catch{}}}),this.tabCoordinator.start()):this.tabCoordinator=void 0,t.hydrateOnStart&&this.queryCache?this.readyPromise=new Promise(s=>{this.readyResolve=s}):(this.readyResolved=!0,this.readyPromise=xe),this.offlineQueue=new et(t.offlineQueue,{onEvict:(s,i)=>{this.emitItemSettled(s,"rejected",i)},onSizeChange:s=>{this.pendingChangeListeners.emit(s)},persistence:this.persistence,version:t.persistenceVersion}),this.outbox=t.outbox,this.clientId=t.clientId??`client-${$()}`,this.persistence&&queueMicrotask(()=>{this.hydrateAsOutboxLeader()}),this.queryCache&&queueMicrotask(()=>{(async()=>{try{await this.hydrateQueryCache()}catch{}finally{this.readyResolved=!0,this.readyResolve?.()}})().catch(()=>{})})}setAuthToken(t,e){const s=this.authToken!==t,i=this.identityFingerprint();this.authToken=t,e!==void 0&&(this.authSubject=e);const n=this.identityFingerprint();n!==i&&(s?this.rejectQueuedForIdentityChange():this.restampQueuedIdentity(i,n)),s&&this.authTokenListeners.emit(t)}getAuthToken(){return this.authToken}currentIdentity(){return this.identityFingerprint()}clientIdentifier(){return this.clientId}confirmedMutationWatermark(t){return this.clientWatermarks.get(t??"")??0}async callMutator(t,e,s){const i=s?.clientSeq;if(i!==void 0&&(!Number.isInteger(i)||i<=0))throw new u("INTERNAL",`callMutator: clientSeq must be a positive integer, got ${String(i)}`);const n=s?.shardKey??"";let r;const o=await this.rpc(t,e,s?.shardKey,{captureBookmark:!0,clientId:this.clientId,clientSeq:i,onMutationAck:c=>{r=c}});return r!==void 0&&r>(this.clientWatermarks.get(n)??0)&&this.clientWatermarks.set(n,r),{applied:r===void 0||r===i,result:o}}onAuthTokenChange(t){return this.authTokenListeners.add(t)}async getCurrentUser(){if(this.closed||!this.fetchImpl)return null;const t={};this.authToken&&(t.authorization=`Bearer ${this.authToken}`);try{const e=await this.fetchImpl(b(this.url,`${this.authBasePath}${Re}`),{credentials:"include",headers:t,method:"GET"});return e.ok?(await e.json())?.user??null:null}catch{return null}}setWsToken(t){if(this.wsToken!==t){this.wsToken=t;for(const e of this.connections.values())if(e.socket)try{e.socket.close()}catch{}}}setConnectionContext(t,e={}){const s=m(e.shardKey);t===void 0?this.connectionContexts.delete(s):this.connectionContexts.set(s,t),this.refreshConnectionContext(s)}acquireConnectionContext(t,e={}){const s=m(e.shardKey),i={context:t},n=this.connectionContextHolders.get(s);n?n.push(i):this.connectionContextHolders.set(s,[i]),this.refreshConnectionContext(s);let r=!1;return()=>{if(r)return;r=!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)}}whisperSubscribe(t,e,s={}){const i=m(s.shardKey);let n=this.whisperHandlers.get(i);n||(n=new Map,this.whisperHandlers.set(i,n));let r=n.get(t);const o=r===void 0;if(r||(r=new Set,n.set(t,r)),r.add(e),this.ensureSocket(s.shardKey),o){const c=this.getConnection(s.shardKey);c&&y(c,{topic:t,type:"whisper_subscribe"})}return()=>{const c=this.whisperHandlers.get(i),a=c?.get(t);if(!a?.delete(e)||a.size>0)return;c?.delete(t),c?.size===0&&this.whisperHandlers.delete(i);const d=this.getConnection(s.shardKey);d&&y(d,{topic:t,type:"whisper_unsubscribe"})}}whisper(t,e,s={}){this.ensureSocket(s.shardKey);const i=this.getConnection(s.shardKey);i&&y(i,{data:v(e??null,`whisper data for topic '${t}'`),topic:t,type:"whisper"})}onTokenExpired(t){return this.tokenExpiredListeners.add(t)}connectionStatus(){return this.computeStatus()}onConnectionStatus(t){const e=this.statusListeners.add(t);return t(this.computeStatus()),e}pendingCount(){return this.offlineQueue.size}debug(){const t=[],e=new Set([...this.connections.keys(),...this.clientWatermarks.keys()]);for(const i of e){const n=this.connections.get(i);t.push({confirmedMutationWatermark:this.clientWatermarks.get(i)??0,hasSocket:n?.socket!==void 0,shardKey:i===""?void 0:i,wasEverConnected:n?.wasEverConnected??!1,wsState:n?.wsState??"idle"})}const s=this.subscriptions.all().map(i=>({acked:i.acked,functionPath:i.fn.__lunoraRef,id:i.id,kind:"query",lastMutationId:i.lastMutationId,pendingOptimisticLayers:i.optimisticLayers.length,serverCursor:i.serverCursor,shardKey:i.shardKey,subscriberCount:i.callbacks.size}));for(const i of this.shapeSubscriptions.values())s.push({acked:i.serverCursor!==void 0,functionPath:`shape:${i.name}`,id:i.id,kind:"shape",lastMutationId:i.lastMutationId,pendingOptimisticLayers:0,rowCount:i.rows.size,serverCursor:i.serverCursor,shardKey:i.shardKey,subscriberCount:i.callbacks.size});return{clientId:this.clientId,closed:this.closed,connectionStatus:this.computeStatus(),pendingWrites:this.offlineQueue.size,shards:t.toSorted((i,n)=>(i.shardKey??"").localeCompare(n.shardKey??"")),subscriptions:s.toSorted((i,n)=>i.functionPath.localeCompare(n.functionPath))}}onPendingChange(t){const e=this.pendingChangeListeners.add(t);return t(this.offlineQueue.size),e}onMutationSettled(t){return this.mutationSettledListeners.add(t)}getWebSocketImpl(){return this.WebSocketImpl}getClientQuery(t){return this.clientQueryStore.get(t)}setClientQuery(t,e){this.clientQueryStore.set(t,e)}subscribeClientQuery(t,e){return this.clientQueryStore.subscribe(t,e)}resetClientQuery(t){this.clientQueryStore.reset(t)}snapshotPrecondition(t,e,s){const i=this.peekActiveQueryValue(t.__lunoraRef,e,s),n=i===void 0?void 0:I(i);return()=>{const r=this.peekActiveQueryValue(t.__lunoraRef,e,s);return n===void 0&&r===void 0?!0:n===void 0||r===void 0?!1:I(r)===n}}whenReady(){return this.readyPromise}get isReady(){return this.readyResolved}peekHydratedQuery(t,e,s){if(!this.readyResolved)return;const i=I(e),n=R(t,i,s),r=this.hydratedQueryCache.get(n);if(r!==void 0)return r.identity===this.identityFingerprint()?r.value:void 0}peekActiveQueryValue(t,e,s){const i=k.key(t,e,s);return this.subscriptions.get(i)?.lastValue}async query(t,e,s={}){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return await this.rpc(t.__lunoraRef,e,s.shardKey,{attachBookmark:!0})}async batch(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");if(!this.fetchImpl)throw new u("INTERNAL","LunoraClient: no `fetch` implementation available");if(t.length===0)return[];const e=await this.fetchImpl(b(this.url,K),{body:JSON.stringify({calls:t.map((n,r)=>({args:v(n.args??{},`args for batch call '${n.fn.__lunoraRef}'`),functionPath:n.fn.__lunoraRef,id:r,shardKey:n.shardKey}))}),headers:this.rpcRequestHeaders({attachBookmark:!0}),method:"POST"}),s=e.headers.get("x-d1-bookmark");s&&this.bookmark.set(s);let i;try{i=await e.json()}catch{throw new u("INTERNAL",`LunoraClient: batch response was not JSON (status ${e.status.toString()})`)}if(!e.ok||i.error&&!i.results)throw i.error?C(i.error):new u("INTERNAL",`LunoraClient: batch request failed (status ${e.status.toString()})`);return Pe(i.results??[],t.length)}async mutation(t,e,s={}){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const i=e,n=s.mutationId??$(),{confirms:r,rollbacks:o}=this.applyOptimisticUpdates(t.__lunoraRef,i,s.shardKey,s.optimistic);s.optimisticUpdate&&this.applyOptimisticUpdate(s.optimisticUpdate,e,s.shardKey,o,r);const c=this.getConnection(s.shardKey),a=c?.wsState??"idle",d=c?.socket!==void 0,l=c?.wasEverConnected??!1,{queueBeforeFirstConnect:p}=this.offlineQueue,f=l||p,G=this.WebSocketImpl!==void 0&&f;if(a!=="open"&&!d&&G||a==="connecting"&&f)return this.enqueueOfflineMutation(t,i,s.shardKey,n,o,r,s.precondition);try{let T;const j=await this.rpc(t.__lunoraRef,i,s.shardKey,{captureBookmark:!0,mutationId:n,onCommitCursor:L=>{T=L}});for(const L of r)L(T);return j}catch(T){throw O(o),T}}async action(t,e,s={}){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return await this.rpc(t.__lunoraRef,e,s.shardKey)}async importRows(t,e,s={}){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const i=Math.max(1,Math.trunc(s.chunkSize??500)),n=s.toArgs??(a=>({rows:a})),r=e.length;let o=0,c=0;for(let a=0;a<r;a+=i){const d=e.slice(a,a+i),l=c;await this.mutation(t,n(d),{...s.importId===void 0?{}:{mutationId:`${s.importId}:${String(l)}`},shardKey:s.shardKey}),c+=1,o+=d.length,s.onProgress?.({done:o,total:r})}return{chunks:c,imported:o}}async shardTraffic(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=await this.adminFetch(yt,"POST",{table:t});return{failed:e.failed??0,ok:e.ok??0,shards:e.shards??[]}}async listScheduledJobs(){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return(await this.adminFetch(wt,"GET")).records??[]}async schedulerStatus(){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const t=await this.adminFetch(gt,"GET");return{backlog:t.backlog??0,inFlight:t.inFlight??0,pools:t.pools??[]}}async cancelScheduledJob(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return{cancelled:(await this.adminFetch(vt,"POST",{id:t})).cancelled===!0}}async listDeadJobs(){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return(await this.adminFetch(kt,"GET")).records??[]}async retryDeadJob(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return{retried:(await this.adminFetch(St,"POST",{id:t})).retried===!0}}async removeDeadJob(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return{removed:(await this.adminFetch(Ct,"POST",{id:t})).removed===!0}}async listWorkflowInstances(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=new URLSearchParams({name:t.name});t.status!==void 0&&e.set("status",t.status),t.page!==void 0&&e.set("page",String(t.page)),t.perPage!==void 0&&e.set("perPage",String(t.perPage));const s=await this.adminFetch(`${Tt}?${e.toString()}`,"GET");return{configured:s.configured,instances:s.instances??[],page:s.page??1,perPage:s.perPage??t.perPage??0,totalCount:s.totalCount}}async getWorkflowInstance(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=new URLSearchParams({id:t.id,name:t.name}),s=await this.adminFetch(`${It}?${e.toString()}`,"GET");return{createdOn:s.createdOn,endedOn:s.endedOn,error:s.error,id:s.id??t.id,output:s.output,params:s.params,startedOn:s.startedOn,status:s.status??"unknown",steps:s.steps??[]}}async setWorkflowInstanceStatus(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return{status:(await this.adminFetch(Et,"POST",{action:t.action,id:t.id,name:t.name})).status??"unknown"}}subscribeScheduledJobs(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");if(this.WebSocketImpl===void 0)return()=>{};const e=b(U(this.url),bt),s=M(this.reconnectOptions);let i,n,r=!1;const o=d=>{if(r||this.WebSocketImpl===void 0)return;const l=d===void 0?e:`${e}?token=${encodeURIComponent(d)}`;i=new this.WebSocketImpl(l),i.addEventListener("open",()=>{s.reset()}),i.addEventListener("message",p=>{try{const f=JSON.parse(typeof p.data=="string"?p.data:"");f.type==="jobs"&&Array.isArray(f.records)&&t(f.records)}catch{}}),i.addEventListener("close",()=>{i=void 0,r||(n=setTimeout(a,s.next()))}),i.addEventListener("error",()=>{})},c=async d=>{let l;try{l=await d()}catch{r||(n=setTimeout(a,s.next()));return}o(l)},a=()=>{if(r||this.WebSocketImpl===void 0)return;const{wsToken:d}=this;if(typeof d=="function"){c(d).catch(()=>{});return}o(d)};return a(),()=>{r=!0,n!==void 0&&clearTimeout(n),i?.close()}}async listFunctions(){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return(await this.adminFetch(Rt,"GET")).functions??[]}async getCronJobs(){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return(await this.adminFetch(_t,"GET")).jobs??[]}async runCronJob(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=await this.adminFetch(Nt,"POST",{name:t});return{name:e.name??t,ran:e.ran===!0}}async fetchOpenApi(){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return await this.adminFetch(Ot,"GET")}async fetchOpenRpc(){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return await this.adminFetch(Pt,"GET")}async listStorageObjects(t={}){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=new URLSearchParams;t.prefix!==void 0&&t.prefix!==""&&e.set("prefix",t.prefix),t.cursor!==void 0&&t.cursor!==""&&e.set("cursor",t.cursor),t.limit!==void 0&&e.set("limit",String(t.limit)),t.bucket!==void 0&&t.bucket!==""&&e.set("bucket",t.bucket);const s=e.toString(),i=s===""?E:`${E}?${s}`,n=await this.adminFetch(i,"GET");return{cursor:n.cursor,objects:n.objects??[]}}async deleteStorageObject(t,e){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const s=`${E}?key=${encodeURIComponent(t)}${N(e?.bucket)}`,i=await this.adminFetch(s,"DELETE");return{deleted:i.deleted??!0,key:i.key??t}}async listStorageBuckets(){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return(await this.adminFetch(At,"GET")).buckets??[]}async uploadStorageObject(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=`${E}?key=${encodeURIComponent(t.key)}${N(t.bucket)}`,s=await this.adminFetch(e,"PUT",t.body,t.contentType);return{etag:s.etag,key:s.key??t.key}}async signedStorageUrl(t,e){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const s=e?.expiresInSeconds,i=s===void 0?"":`&expiresIn=${encodeURIComponent(s.toString())}`,n=`${Lt}?key=${encodeURIComponent(t)}${i}${N(e?.bucket)}`,r=await this.adminFetch(n,"GET");if(typeof r.url!="string")throw new TypeError("LunoraClient: storage URL endpoint returned no `url`");return r.url}async listGlobalTables(){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return await this.adminFetch(Ft,"GET")}async readGlobalTablePage(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=new URLSearchParams({table:t.table});return t.limit!==void 0&&e.set("limit",String(t.limit)),t.offset!==void 0&&e.set("offset",String(t.offset)),t.filters!==void 0&&t.filters.length>0&&e.set("filters",JSON.stringify(t.filters)),await this.adminFetch(`${xt}?${e.toString()}`,"GET")}async facetGlobalColumn(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=new URLSearchParams({column:t.column,table:t.table});return t.limit!==void 0&&e.set("limit",String(t.limit)),t.filters!==void 0&&t.filters.length>0&&e.set("filters",JSON.stringify(t.filters)),await this.adminFetch(`${$t}?${e.toString()}`,"GET")}async listVectorIndexes(){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return(await this.adminFetch(Mt,"GET")).indexes??[]}async queryVectorIndex(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return(await this.adminFetch(Kt,"POST",t)).matches??[]}async queryLogArchive(t={}){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=await this.adminFetch(qt,"POST",t);return{nextCursor:e.nextCursor,rows:e.rows??[]}}async listKvNamespaces(){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");return(await this.adminFetch(Ut,"GET")).namespaces??[]}async listKvKeys(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=w(Qt,{cursor:t.cursor,limit:t.limit,namespace:t.namespace,prefix:t.prefix});return await this.adminFetch(e,"GET")}async getKvValue(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=w(P,{key:t.key,namespace:t.namespace});return await this.adminFetch(e,"GET")}async putKvValue(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");await this.adminFetch(P,"PUT",t)}async deleteKvKey(t){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=w(P,{key:t.key,namespace:t.namespace});await this.adminFetch(e,"DELETE")}async listAuthUsers(t={}){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=w(Bt,{filterField:t.filterField,filterValue:t.filterValue,limit:t.limit,offset:t.offset,search:t.search,searchField:t.searchField,sortBy:t.sortBy,sortDirection:t.sortDirection});return await this.adminFetch(e,"GET")}async createAuthUser(t){return await this.adminFetch(Wt,"POST",t)}async setAuthUserRole(t){return await this.adminFetch(zt,"POST",t)}async banAuthUser(t){return await this.adminFetch(Gt,"POST",t)}async unbanAuthUser(t){return await this.adminFetch(jt,"POST",t)}async setAuthUserPassword(t){await this.adminFetch(Dt,"POST",t)}async removeAuthUser(t){await this.adminFetch(Ht,"POST",t)}async impersonateAuthUser(t){return await this.adminFetch(Vt,"POST",t)}async revokeAuthSession(t){await this.adminFetch(Jt,"POST",t)}async revokeAuthUserSessions(t){await this.adminFetch(Xt,"POST",t)}async getAuthCapabilities(){return await this.adminFetch(Yt,"GET")}async updateAuthUser(t){return await this.adminFetch(Zt,"POST",t)}async listAuthAccounts(t){return await this.adminFetch(w(te,{userId:t.userId}),"GET")}async unlinkAuthAccount(t){await this.adminFetch(ee,"POST",t)}async listAuthPasskeys(t){return await this.adminFetch(w(se,{userId:t.userId}),"GET")}async deleteAuthPasskey(t){await this.adminFetch(ie,"POST",t)}async disableAuthTwoFactor(t){await this.adminFetch(ne,"POST",t)}async listAuthOrganizations(t={}){return await this.adminFetch(w(re,{limit:t.limit,offset:t.offset}),"GET")}async listAuthOrgMembers(t){const e=w(oe,{limit:t.limit,offset:t.offset,organizationId:t.organizationId});return await this.adminFetch(e,"GET")}async listAuthOrgInvitations(t){const e=w(ae,{limit:t.limit,offset:t.offset,organizationId:t.organizationId});return await this.adminFetch(e,"GET")}async removeAuthOrgMember(t){await this.adminFetch(ce,"POST",t)}async cancelAuthOrgInvitation(t){await this.adminFetch(he,"POST",t)}async getAuthConfig(){return await this.adminFetch(ue,"GET")}async createAuthOrganization(t){return await this.adminFetch(de,"POST",t)}async updateAuthOrganization(t){return await this.adminFetch(le,"POST",t)}async deleteAuthOrganization(t){await this.adminFetch(me,"POST",t)}async addAuthOrgMember(t){return await this.adminFetch(pe,"POST",t)}async inviteAuthOrgMember(t){return await this.adminFetch(fe,"POST",t)}async setAuthOrgMemberRole(t){return await this.adminFetch(ye,"POST",t)}async listAuthOrgTeams(t){const e=w(we,{limit:t.limit,offset:t.offset,organizationId:t.organizationId});return await this.adminFetch(e,"GET")}async createAuthOrgTeam(t){return await this.adminFetch(ge,"POST",t)}async updateAuthOrgTeam(t){return await this.adminFetch(be,"POST",t)}async removeAuthOrgTeam(t){await this.adminFetch(ve,"POST",t)}async listAuthOrgTeamMembers(t){const e=w(ke,{limit:t.limit,offset:t.offset,teamId:t.teamId});return await this.adminFetch(e,"GET")}async addAuthOrgTeamMember(t){return await this.adminFetch(Se,"POST",t)}async removeAuthOrgTeamMember(t){await this.adminFetch(Ce,"POST",t)}async listAuthOrgRoles(t){const e=w(Te,{limit:t.limit,offset:t.offset,organizationId:t.organizationId});return await this.adminFetch(e,"GET")}async createAuthOrgRole(t){return await this.adminFetch(Ie,"POST",t)}async updateAuthOrgRole(t){return await this.adminFetch(Ee,"POST",t)}async deleteAuthOrgRole(t){await this.adminFetch(Le,"POST",t)}async listAuthSessions(t={}){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const e=new URLSearchParams;t.userId!==void 0&&t.userId!==""&&e.set("userId",t.userId),t.limit!==void 0&&e.set("limit",String(t.limit)),t.offset!==void 0&&e.set("offset",String(t.offset));const s=e.toString();return await this.adminFetch(s===""?q:`${q}?${s}`,"GET")}subscribe(t,e,s,i={}){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");const n=e??{},r=k.key(t.__lunoraRef,n,i.shardKey);let o=this.subscriptions.get(r);const c=s,a=i.onError;if(!o){this.nextSubId+=1;const l=`sub_${this.nextSubId.toString()}`,p=I(n),f=this.takeHydratedCache(t.__lunoraRef,p,i.shardKey);o={acked:!1,args:n,argsKey:p,callbacks:new Set,checkpointCallbacks:new Set,errorCallbacks:new Set,fn:t,id:l,lastValue:f?.value,optimisticLayers:[],serverBase:f?.value,serverCursor:f?.serverCursor,shardKey:i.shardKey,...f?.serverEpoch===void 0?{}:{serverEpoch:f.serverEpoch}},this.subscriptions.add(o)}if(o.callbacks.add(c),a&&o.errorCallbacks.add(a),i.onCheckpoint&&o.checkpointCallbacks.add(i.onCheckpoint),o.lastValue!==void 0)try{c(o.lastValue)}catch{}this.ensureSocket(i.shardKey),this.sendSubscribeIfOpen(o);const d=o;return()=>{if(d.callbacks.delete(c),a&&d.errorCallbacks.delete(a),i.onCheckpoint&&d.checkpointCallbacks.delete(i.onCheckpoint),d.callbacks.size===0){const l=this.getConnection(d.shardKey);!(l&&y(l,{id:d.id,type:"unsubscribe"}))&&l&&l.pendingUnsubscribes.push({id:d.id,type:"unsubscribe"}),this.subscriptions.remove(d)}}}subscribeShape(t,e,s={}){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");this.nextShapeId+=1;const i=`shape_${this.nextShapeId.toString()}`,n={args:t.args,callbacks:new Set([e]),errorCallbacks:s.onError?new Set([s.onError]):new Set,id:i,name:t.name,onCheckpoint:s.onCheckpoint,rows:new Map,shardKey:s.shardKey,wireArgs:t.args===void 0?void 0:v(t.args,`shape args for '${t.name}'`)};return this.shapeSubscriptions.set(i,n),this.ensureSocket(s.shardKey),this.sendShapeSubscribeIfOpen(n),()=>{this.shapeSubscriptions.delete(i);const r=this.getConnection(n.shardKey);!(r&&y(r,{id:i,type:"shape_unsubscribe"}))&&r&&r.pendingUnsubscribes.push({id:i,type:"shape_unsubscribe"})}}stream(t,e,s={}){if(this.closed)throw new u("INTERNAL","LunoraClient is closed");if(this.WebSocketImpl===void 0)throw new u("INTERNAL","LunoraClient: streams require a WebSocket implementation");this.nextStreamId+=1;const i=`stream_${this.nextStreamId.toString()}`,{shardKey:n}=s,r=e??{},{handle:o,iterable:c}=ot({maxBuffer:s.maxBuffer,onCancel:()=>{const l=this.getConnection(n);l&&y(l,{id:i,type:"unsubscribe"}),this.streams.delete(i)}});this.streams.set(i,{handle:o,shardKey:n}),this.ensureSocket(n);const a=this.getConnection(n),d={id:i,query:{args:v(r,`stream args for '${t.__lunoraRef}'`),functionPath:t.__lunoraRef,shardKey:n},type:"stream"};if(!(a?.wsState==="open"&&y(a,d))&&a){for(a.pendingStreams=a.pendingStreams??[];a.pendingStreams.length>=ft;){const l=a.pendingStreams.shift()?.id,p=l?this.streams.get(l):void 0;p&&(p.handle.fail(new u("STREAM_QUEUE_OVERFLOW","stream-start frame evicted while socket was unreachable")),this.streams.delete(l))}a.pendingStreams.push(d)}return c}httpStream(t,e,s={}){if(this.closed)throw new u("CLIENT_CLOSED","LunoraClient is closed");if(!this.fetchImpl)throw new u("INTERNAL","LunoraClient: no `fetch` implementation available");const i={...this.authToken?{authorization:`Bearer ${this.authToken}`}:{},...s.headers};return Y(t,e,{baseUrl:this.url,fetch:this.fetchImpl,headers:i,maxBuffer:s.maxBuffer,signal:s.signal})}close(){this.closed=!0,this.outboxLeaderRelease?.(),this.outboxLeaderRelease=void 0;for(const t of this.streams.values())t.handle.fail(new u("CLIENT_CLOSED","LunoraClient closed"));this.streams.clear();for(const t of this.connections.values()){if(t.reconnectTimer!==void 0&&(clearTimeout(t.reconnectTimer),t.reconnectTimer=void 0),t.connectTimer!==void 0&&(clearTimeout(t.connectTimer),t.connectTimer=void 0),this.stopHeartbeat(t),t.socket){try{t.socket.close()}catch{}t.socket=void 0}t.wsState="closed"}this.offlineQueue.clear(),this.queuedIdentities.clear(),this.cacheFlushTimer!==void 0&&(clearTimeout(this.cacheFlushTimer),this.cacheFlushTimer=void 0),this.pendingCacheWrites.size>0&&this.flushQueryCacheWrites().catch(()=>{}),this.authTokenListeners.clear(),this.statusListeners.clear(),this.tokenExpiredListeners.clear(),this.mutationSettledListeners.clear(),this.pendingChangeListeners.clear(),this.whisperHandlers.clear(),this.shapeSubscriptions.clear(),this.pokeBuffers.clear(),this.tabCoordinator?.stop(),this.tabCoordinator=void 0}async enqueueOfflineMutation(t,e,s,i,n,r,o){const c=this.identityFingerprint();if(this.outbox){this.outboxMutationCounter+=1;const a=this.outboxMutationCounter;try{await this.outbox.enqueue({args:e,clientId:this.clientId,functionPath:t.__lunoraRef,idempotencyKey:`${this.clientId}:${String(a)}`,identity:c,mutationId:a,shardKey:s})}catch(d){throw O(n),d instanceof Error?d:new Error(String(d))}for(const d of r)d(void 0);return}return new Promise((a,d)=>{const l={args:e,functionPath:t.__lunoraRef,liveAwaiter:!0,id:i,identity:c,precondition:o,onCommit:p=>{for(const f of r)f(p)},reject:p=>{this.queuedIdentities.delete(i),O(n),d(p instanceof Error?p:new Error(String(p)))},resolve:a,shardKey:s};this.offlineQueue.enqueue(l),l.id!==void 0&&this.queuedIdentities.set(l.id,c)})}async hydratePersistedQueue(){try{const t=await this.offlineQueue.hydrate();for(const e of t)this.ensureSocket(e)}catch{}}hydrateAsOutboxLeader(){const t=()=>{this.hydratePersistedQueue().catch(()=>{})},e=globalThis.navigator?.locks;if(!e){t();return}e.request(`lunora:outbox-leader:${this.url}`,()=>(this.closed||t(),new Promise(s=>{if(this.closed){s();return}this.outboxLeaderRelease=s}))).catch(t)}async hydrateQueryCache(){if(this.queryCache)try{const t=await this.queryCache.load();for(const{key:e,...s}of t){if(st(this.persistenceVersion,s.version)){this.queryCache.remove(e).catch(()=>{});continue}this.hydratedQueryCache.set(e,s)}}catch{}}takeHydratedCache(t,e,s){const i=R(t,e,s),n=this.hydratedQueryCache.get(i);if(n!==void 0)return this.hydratedQueryCache.delete(i),n.identity===this.identityFingerprint()?n:void 0}persistQueryValue(t){const e=t.serverBase;if(!this.queryCache||e===void 0)return;const s=R(t.fn.__lunoraRef,t.argsKey,t.shardKey);this.pendingCacheWrites.set(s,{identity:this.identityFingerprint(),serverCursor:t.serverCursor,ts:Date.now(),value:e,...t.serverEpoch===void 0?{}:{serverEpoch:t.serverEpoch},...this.persistenceVersion===void 0?{}:{version:this.persistenceVersion}}),this.cacheFlushTimer??=setTimeout(()=>{this.flushQueryCacheWrites().catch(()=>{})},pt)}async flushQueryCacheWrites(){this.cacheFlushTimer=void 0;const{queryCache:t}=this;if(!t){this.pendingCacheWrites.clear();return}const e=[...this.pendingCacheWrites.entries()];this.pendingCacheWrites.clear(),await Promise.allSettled(e.map(([s,i])=>t.put(s,i)))}computeStatus(){const t=[...this.connections.values()];return t.length===0?"idle":t.some(e=>e.wsState==="open")?"connected":t.some(e=>e.wsState==="connecting")?"connecting":"offline"}emitConnectionStatus(){const t=this.computeStatus();t!==this.lastStatus&&(this.lastStatus=t,this.statusListeners.emit(t))}emitItemSettled(t,e,s){this.mutationSettledListeners.emit({args:t.args,code:s===void 0?void 0:s.code,error:s,functionPath:t.functionPath,hadAwaiter:t.liveAwaiter??!1,id:t.id??"",shardKey:t.shardKey,status:e})}applyOptimisticUpdates(t,e,s,i){const n=[],r=[];if(!i)return{confirms:n,rollbacks:r};const o=k.key(t,e,s),c=this.subscriptions.get(o);if(c){const a=Z(c,i);a&&(n.push(a.confirm),r.push(a.rollback))}return{confirms:n,rollbacks:r}}applyOptimisticUpdate(t,e,s,i,n){const{confirms:r,rollbacks:o,store:c}=tt(this.subscriptions,s);try{t(c,e)}catch{for(let a=o.length-1;a>=0;a-=1)o[a]?.();return}i.push(...o),n.push(...r)}getConnection(t){return this.connections.get(m(t))}getOrCreateConnection(t){const e=m(t);let s=this.connections.get(e);return s||(s={connectTimer:void 0,heartbeatTimer:void 0,pendingUnsubscribes:[],reconnect:M(this.reconnectOptions),reconnectTimer:void 0,shardKey:t,socket:void 0,wasEverConnected:!1,wsState:"idle"},this.connections.set(e,s)),s}wsUrlFor(t,e){const s=[];if(t!==void 0&&s.push(`shard=${encodeURIComponent(t)}`),e!==void 0&&s.push(`token=${encodeURIComponent(e)}`),s.length===0)return this.wsUrl;const i=this.wsUrl.includes("?")?"&":"?";return`${this.wsUrl}${i}${s.join("&")}`}rpcRequestHeaders(t){const e={"content-type":"application/json"};if(this.authToken&&(e.authorization=`Bearer ${this.authToken}`),t.mutationId&&(e["x-lunora-mutation-id"]=t.mutationId),t.clientId!==void 0&&(e["x-lunora-client-id"]=t.clientId),t.clientSeq!==void 0&&(e["x-lunora-client-seq"]=t.clientSeq.toString()),t.attachBookmark){const s=this.bookmark.get();s&&(e["x-d1-bookmark"]=s)}return e}async rpc(t,e,s,i={}){if(!this.fetchImpl)throw new u("INTERNAL","LunoraClient: no `fetch` implementation available");const n=this.rpcRequestHeaders(i),r=await this.fetchImpl(b(this.url,ct),{body:JSON.stringify({args:v(e,`args for '${t}'`),functionPath:t,shardKey:s}),headers:n,method:"POST"});if(i.captureBookmark){const c=r.headers.get("x-d1-bookmark");c&&this.bookmark.set(c)}let o;try{o=await r.json()}catch{const c=r.statusText?` ${r.statusText}`:"";throw new u("INTERNAL",`LunoraClient: response was not JSON (status ${r.status.toString()}${c})`)}if("error"in o)throw C(o.error);if(!r.ok){const c=r.statusText?` ${r.statusText}`:"";throw new u("INTERNAL",`LunoraClient: request failed (status ${r.status.toString()}${c})`)}return i.onMutationAck?.(o.lastMutationId),i.onCommitCursor?.(o.commitCursor),g(o.result)}async adminFetch(t,e,s,i){if(!this.fetchImpl)throw new u("INTERNAL","LunoraClient: no `fetch` implementation available");const n={};this.authToken&&(n.authorization=`Bearer ${this.authToken}`);const r=s instanceof ArrayBuffer||s instanceof Blob;let o;s===void 0?o=void 0:r?(o=s,i!==void 0&&(n["content-type"]=i)):(o=JSON.stringify(s),n["content-type"]="application/json");const c=await this.fetchImpl(b(this.url,t),{body:o,headers:n,method:e});let a;try{a=await c.json()}catch{const d=c.statusText?` ${c.statusText}`:"";throw new u("INTERNAL",`LunoraClient: response was not JSON (status ${c.status.toString()}${d})`)}if(typeof a=="object"&&a!==null&&"error"in a){const d=a.error,l=new Error(d.message??"admin request failed");throw l.code=d.code,l}if(!c.ok){const d=c.statusText?` ${c.statusText}`:"";throw new u("INTERNAL",`LunoraClient: admin request failed (status ${c.status.toString()}${d})`)}return a}effectiveConnectionContext(t){const e=this.connectionContextHolders.get(t);return e&&e.length>0?e[e.length-1]?.context:this.connectionContexts.get(t)??this.defaultConnectionContext}refreshConnectionContext(t){const e=this.connections.get(t);e?.wsState==="open"&&this.sendConnectEnvelope(e)}sendConnectEnvelope(t){const e=this.effectiveConnectionContext(m(t.shardKey));y(t,{clientId:this.clientId,id:"connect",type:"connect",...e===void 0?{}:{context:e}})}resendShapeSubscriptions(t){for(const e of this.shapeSubscriptions.values())m(e.shardKey)===m(t)&&this.sendShapeSubscribeIfOpen(e)}ensureSocket(t){if(this.closed||this.WebSocketImpl===void 0||this.tabCoordinator&&!this.tabCoordinator.isLeader())return;const e=this.getOrCreateConnection(t);if(!(e.wsState==="open"||e.wsState==="connecting")){if(e.wsState="connecting",this.emitConnectionStatus(),typeof this.wsToken=="function"){this.openSocketWithProvidedToken(e,t,this.wsToken).catch(()=>{});return}this.openSocket(e,t,this.wsToken)}}async openSocketWithProvidedToken(t,e,s){let i;try{i=await s()}catch{this.handleDisconnect(t);return}this.closed||this.WebSocketImpl===void 0||t.wsState!=="connecting"||t.socket!==void 0||this.openSocket(t,e,i)}openSocket(t,e,s){if(this.WebSocketImpl===void 0)return;const i=new this.WebSocketImpl(this.wsUrlFor(e,s));t.socket=i,this.connectTimeoutMs>0&&(t.connectTimer=setTimeout(()=>{if(t.connectTimer=void 0,!(t.socket!==i||t.wsState!=="connecting")){try{i.close()}catch{}this.handleDisconnect(t)}},this.connectTimeoutMs)),i.addEventListener("open",()=>{if(t.socket!==i)return;t.connectTimer!==void 0&&(clearTimeout(t.connectTimer),t.connectTimer=void 0),t.wsState="open",t.wasEverConnected=!0,t.reconnect.reset(),this.emitConnectionStatus(),this.sendConnectEnvelope(t),this.markShardPendingAck(e);for(const r of this.subscriptions.all())m(r.shardKey)===m(e)&&this.sendSubscribeIfOpen(r);if(this.resendShapeSubscriptions(e),t.pendingUnsubscribes.length>0){const r=t.pendingUnsubscribes;t.pendingUnsubscribes=[];for(const{id:o,type:c}of r)y(t,{id:o,type:c})}if(t.pendingStreams&&t.pendingStreams.length>0){const r=t.pendingStreams;t.pendingStreams=[];for(const o of r)y(t,o)}const n=this.whisperHandlers.get(m(e));if(n)for(const r of n.keys())y(t,{topic:r,type:"whisper_subscribe"});this.flushOfflineQueue(e).catch(()=>{}),this.startHeartbeat(t)}),i.addEventListener("message",n=>{this.handleServerMessage(n.data,e)}),i.addEventListener("close",n=>{t.socket===i&&(n?.code===4001&&this.notifyTokenExpired(),this.handleDisconnect(t))}),i.addEventListener("error",()=>{t.socket===i&&(t.wsState==="connecting"||t.wsState==="open")&&this.handleDisconnect(t)})}handleDisconnect(t){if(this.closed||t.wsState==="idle"||t.wsState==="closed")return;this.stopHeartbeat(t),t.connectTimer!==void 0&&(clearTimeout(t.connectTimer),t.connectTimer=void 0),t.socket=void 0,t.wsState="idle",this.emitConnectionStatus(),this.markShardPendingAck(t.shardKey);const e=new Set((t.pendingStreams??[]).map(i=>i.id));for(const[i,n]of this.streams)m(n.shardKey)===m(t.shardKey)&&!e.has(i)&&(n.handle.fail(new u("STREAM_DISCONNECTED","stream terminated: WebSocket disconnected")),this.streams.delete(i));if(this.WebSocketImpl===void 0)return;const s=t.reconnect.next();t.reconnectTimer=setTimeout(()=>{t.reconnectTimer=void 0,this.ensureSocket(t.shardKey)},s)}startHeartbeat(t){this.stopHeartbeat(t),!(this.heartbeatIntervalMs<=0)&&(t.heartbeatTimer=setInterval(()=>{if(!(t.wsState!=="open"||!t.socket))try{t.socket.send(dt)}catch{}},this.heartbeatIntervalMs))}stopHeartbeat(t){t.heartbeatTimer!==void 0&&(clearInterval(t.heartbeatTimer),t.heartbeatTimer=void 0)}markShardPendingAck(t){const e=m(t);for(const s of this.subscriptions.all())m(s.shardKey)===e&&(s.acked=!1)}sendSubscribeIfOpen(t){const e=this.getConnection(t.shardKey);if(e?.wsState!=="open"||t.acked)return;const s=t.fn.__lunoraTable??t.fn.__lunoraRef;y(e,{id:t.id,query:{args:W(t.args),functionPath:t.fn.__lunoraRef,table:s,...t.serverCursor===void 0?{}:{sinceSeq:t.serverCursor},...t.serverEpoch===void 0?{}:{sinceEpoch:t.serverEpoch}},type:"subscribe"})}sendShapeSubscribeIfOpen(t){const e=this.getConnection(t.shardKey);e?.wsState==="open"&&y(e,{id:t.id,shape:{name:t.name,...t.wireArgs===void 0?{}:{args:t.wireArgs}},type:"shape_subscribe",...t.serverCursor===void 0?{}:{sinceCheckpoint:t.serverCursor},...t.serverEpoch===void 0?{}:{sinceEpoch:t.serverEpoch}})}handleServerMessage(t,e){const s=Oe(t);if(s===void 0)return;let i;try{i=JSON.parse(s)}catch{return}switch(i.type){case"ack":{const n=this.subscriptions.getById(i.id);n&&(n.acked=!0);return}case"chunk":{const{data:n,id:r}=i;this.streams.get(r)?.handle.push(g(n));return}case"complete":{this.handleCompleteMessage(i.id);return}case"data":case"delta":{this.handleDataMessage(i);return}case"error":{this.handleErrorMessage(i);break}case"pokeEnd":{this.handlePokeEnd(i);break}case"pokePart":{this.handlePokePart(i);break}case"pokeStart":{this.handlePokeStart(i);break}case"resume":{this.handleResumeMessage(i);break}case"settled":{this.handleSettledMessage(i);break}case"whisper":{this.dispatchWhisper(i,e);break}}}handleErrorMessage(t){if(t.error?.code==="TOKEN_EXPIRED"){this.notifyTokenExpired();return}const{id:e}=t,s=e===void 0?void 0:this.streams.get(e);if(s&&e!==void 0){s.handle.fail(_e(t)),this.streams.delete(e);return}const i=e===void 0?void 0:this.subscriptions.getById(e);if(i){B(i.errorCallbacks,Q(t));return}const n=e===void 0?void 0:this.shapeSubscriptions.get(e);n&&B(n.errorCallbacks,Q(t))}handlePokeStart(t){at(this.pokeBuffers,z.MAX_POKE_BUFFERS),this.pokeBuffers.set(t.pokeId,{baseCheckpoint:t.baseCheckpoint,epoch:t.epoch,lastMutationId:new Map,parts:new Map})}handlePokePart(t){const e=this.pokeBuffers.get(t.pokeId);if(!e)return;const s=e.parts.get(t.shapeId)??[];for(const i of t.rowsPatch)s.push(i.value===void 0?i:{...i,value:g(i.value)});e.parts.set(t.shapeId,s),t.lastMutationId!==void 0&&e.lastMutationId.set(t.shapeId,t.lastMutationId)}handlePokeEnd(t){const e=this.pokeBuffers.get(t.pokeId);if(e){this.pokeBuffers.delete(t.pokeId);for(const[s,i]of e.parts){const n=this.shapeSubscriptions.get(s);if(!n)continue;const r=e.epoch!==void 0&&n.serverEpoch!==void 0&&e.epoch!==n.serverEpoch,o=e.baseCheckpoint!==void 0&&n.serverCursor!==void 0&&n.serverCursor!==e.baseCheckpoint;if(r||o){n.rows.clear(),n.serverCursor=void 0,n.serverEpoch=void 0,this.emitShapeRows(n),this.sendShapeSubscribeIfOpen(n);continue}ut(n.rows,i),t.checkpoint!==void 0&&(n.serverCursor=t.checkpoint),t.epoch!==void 0&&(n.serverEpoch=t.epoch);const c=e.lastMutationId.get(s);c!==void 0&&(n.lastMutationId=c),this.emitShapeRows(n),n.onCheckpoint?.({checkpoint:n.serverCursor,mutationId:n.lastMutationId})}}}emitShapeRows(t){const e=[...t.rows.values()];for(const s of t.callbacks)try{s(e)}catch{}}handleDataMessage(t){const{id:e}=t,s=e?this.subscriptions.getById(e):void 0;if(!s)return;const i=this.resolveDataPayload(t,s);if(s.serverBase=i,t.cursor!==void 0&&(s.serverCursor=t.cursor),t.epoch!==void 0&&(s.serverEpoch=t.epoch),this.persistQueryValue(s),F(s,s.serverCursor),x(s,s.optimisticLayers.length===0?i:A(i,s.optimisticLayers)),this.tabCoordinator?.isLeader()){const n=k.key(s.fn.__lunoraRef,s.args,s.shardKey);this.tabCoordinator.broadcastSubscriptionData(n,i)}}handleResumeMessage(t){const e=this.subscriptions.getById(t.id);e&&this.ackAndAdvanceCursor(e,t.cursor,t.epoch)}handleSettledMessage(t){const e=this.subscriptions.getById(t.id);if(e){this.ackAndAdvanceCursor(e,t.cursor,t.epoch),t.lastMutationId!==void 0&&(e.lastMutationId=t.lastMutationId);for(const s of e.checkpointCallbacks)s({checkpoint:e.serverCursor,mutationId:e.lastMutationId})}}ackAndAdvanceCursor(t,e,s){t.acked=!0,(e!==void 0&&e!==t.serverCursor||s!==void 0&&s!==t.serverEpoch)&&(e!==void 0&&(t.serverCursor=e),s!==void 0&&(t.serverEpoch=s),this.persistQueryValue(t),F(t,t.serverCursor)&&x(t,A(t.serverBase,t.optimisticLayers)))}resolveDataPayload(t,e){if("data"in t&&t.data!==void 0)return g(t.data);const s=g(t.delta);if(J(s)&&e.serverBase!==void 0){const i=X(e.serverBase,s);if(i!==void 0)return i}return s}dispatchWhisper(t,e){const s=this.whisperHandlers.get(m(e))?.get(t.topic);if(!s)return;const i=g(t.data);for(const n of s)try{n(i,t.from)}catch{}}notifyTokenExpired(){this.tokenExpiredListeners.emit()}handleCompleteMessage(t){const e=this.streams.get(t);if(e){e.handle.complete(),this.streams.delete(t);return}const s=this.subscriptions.getById(t);s&&this.subscriptions.remove(s)}unpersist(t){t&&this.persistence?.remove(t).catch(e=>{it(this.onPersistenceError,"remove",e,t)})}identityFingerprint(){if(this.authSubject!==void 0)return this.authSubject===null?null:`subj:${this.authSubject}`;const t=this.authToken;return t===null?null:this.hashToken(t)}hashToken(t){let e=2166136261,s=5381;for(let i=0;i<t.length;i+=1){const n=t.charCodeAt(i);e^=n,e=Math.imul(e,16777619),s=Math.imul(s,33)+n}return`${t.length.toString(36)}:${(e>>>0).toString(36)}:${(s>>>0).toString(36)}`}isSameCredentialUnderTokenHash(t){if(t===null||t.startsWith("subj:"))return!1;const e=this.authToken;return e===null?!1:this.hashToken(e)===t}rejectQueuedForIdentityChange(){const t=this.offlineQueue.drain();for(const e of t){this.queuedIdentities.delete(e.id??""),this.unpersist(e.id);const s=new Error("offline mutation discarded: auth identity changed before replay");s.code="OFFLINE_IDENTITY_CHANGED",e.reject(s),this.emitItemSettled(e,"rejected",s)}this.clearQueryCacheForIdentityChange()}restampQueuedIdentity(t,e){for(const[s,i]of this.queuedIdentities)i===t&&this.queuedIdentities.set(s,e)}clearQueryCacheForIdentityChange(){this.cacheFlushTimer!==void 0&&(clearTimeout(this.cacheFlushTimer),this.cacheFlushTimer=void 0),this.pendingCacheWrites.clear(),this.hydratedQueryCache.clear(),this.queryCache?.clear().catch(()=>{})}async flushOfflineQueue(t){const e=this.offlineQueue.drainConflict();for(const a of e){this.unpersist(a.id),this.queuedIdentities.delete(a.id??"");const d=new Error("offline mutation skipped: precondition failed before replay");d.code="OFFLINE_PRECONDITION_FAILED",this.emitItemSettled(a,"rejected",d)}const s=m(t),i=this.offlineQueue.drain(a=>m(a.shardKey)===s);if(i.length===0)return;const n=this.identityFingerprint(),r=[];for(const a of i)this.passesReplayIdentityGate(a,n)&&r.push(a);if(r.length===0)return;const o=this.encodableOrSettleTerminal(r);if(o.length===0)return;if(o.length===1){await this.replaySequential(o);return}const c=[];for(let a=0;a<o.length;a+=_){const d=o.slice(a,a+_),l=await this.replayBatched(d);if(c.push(...l.requeue),l.stop){c.push(...o.slice(a+_));break}}c.length>0&&this.offlineQueue.requeue(c)}encodableOrSettleTerminal(t){const e=[];for(const s of t)try{v(s.args,`args for '${s.functionPath}'`),e.push(s)}catch(i){this.settleReplayTerminal(s,i instanceof Error?i:new Error(String(i)))}return e}passesReplayIdentityGate(t,e){const s=t.id===void 0?void 0:this.queuedIdentities.get(t.id),i=s===void 0?t.identity:s;if(i!==void 0&&i!==e&&!this.isSameCredentialUnderTokenHash(i)){this.queuedIdentities.delete(t.id??""),this.unpersist(t.id);const n=new Error("offline mutation skipped: auth identity changed before replay");return n.code="OFFLINE_IDENTITY_CHANGED",t.reject(n),this.emitItemSettled(t,"rejected",n),!1}return this.queuedIdentities.delete(t.id??""),!0}settleReplaySuccess(t,e,s){this.unpersist(t.id),t.onCommit?.(s),t.resolve(e),this.emitItemSettled(t,"committed")}settleReplayTerminal(t,e){this.unpersist(t.id),t.reject(e),this.emitItemSettled(t,"rejected",e)}async replaySequential(t){for(let e=0;e<t.length;e+=1){const s=t[e];if(s)try{let i;const n=await this.rpc(s.functionPath,s.args,s.shardKey,{captureBookmark:!0,mutationId:s.id,onCommitCursor:r=>{i=r}});this.settleReplaySuccess(s,n,i)}catch(i){if(i.code!==void 0){this.settleReplayTerminal(s,i);continue}this.offlineQueue.requeue(t.slice(e));return}}}async replayBatched(t){if(!this.fetchImpl)return{requeue:t,stop:!0};let e;try{e=await this.fetchImpl(b(this.url,K),{body:JSON.stringify({calls:t.map((n,r)=>({args:v(n.args,`args for '${n.functionPath}'`),functionPath:n.functionPath,id:r,mutationId:n.id,shardKey:n.shardKey}))}),headers:this.rpcRequestHeaders({attachBookmark:!0}),method:"POST"})}catch{return{requeue:t,stop:!0}}const s=e.headers.get("x-d1-bookmark");s&&this.bookmark.set(s);let i;try{i=await e.json()}catch{return{requeue:t,stop:!0}}if(!i.results){if(i.error){const n=C(i.error);for(const r of t)this.settleReplayTerminal(r,n);return{requeue:[],stop:!1}}return{requeue:t,stop:!0}}return{requeue:this.settleReplayBatchSlots(t,i.results),stop:!1}}settleReplayBatchSlots(t,e){const s=new Map;for(const n of e)typeof n.id=="number"&&n.body!==void 0&&s.set(n.id,n.body);const i=[];for(const[n,r]of t.entries()){const o=s.get(n);o===void 0?i.push(r):"error"in o?Fe.has(o.error.code)?i.push(r):this.settleReplayTerminal(r,C(o.error)):this.settleReplaySuccess(r,g(o.result),o.commitCursor)}return i}}export{z as LunoraClient};
|
|
1
|
+
import{LunoraError as d}from"@lunora/errors";import{t as I,c as g,f as W}from"./wire-key-D_zOxXK4.mjs";import D from"./createInMemoryBookmarkStorage-DCd5Ej-t.mjs";import{ClientQueryStore as H}from"./createClientQuery-CrdRoicO.mjs";import{TabCoordinator as V}from"./TabCoordinator-ijLic02x.mjs";import{isMutationDelta as J,applyDelta as X}from"./applyDelta-DXqQORbM.mjs";import{httpStream as Y}from"./httpStream-Cz4_QyjV.mjs";import{f as A,a as Z,d as F,n as x,c as tt}from"./local-store-C53xDvEr.mjs";import{c as et,d as $,a as st,o as it}from"./offline-queue-b-v6bWWd.mjs";import{resolvePersistenceAdapter as nt}from"./createInMemoryPersistence-CQYXy8UP.mjs";import{resolveQueryCacheAdapter as rt,queryCacheKey as R}from"./createInMemoryQueryCache-DjCKrLjk.mjs";import{createReconnect as M}from"./createReconnect-CFT7YRSR.mjs";import{createStream as ot}from"./DEFAULT_MAX_BUFFER-TBn2s7Rz.mjs";import{SubscriptionRegistry as k}from"./SubscriptionRegistry-CdrOD7sZ.mjs";const _=500,at=(h,t)=>{if(h.size<t)return;const e=h.keys().next().value;e!==void 0&&h.delete(e)};class S{listeners=new Set;add(t){return this.listeners.add(t),()=>{this.listeners.delete(t)}}emit(...t){const[e]=t;for(const s of this.listeners)try{s(e)}catch{}}clear(){this.listeners.clear()}}const ct="/_lunora/rpc",K="/_lunora/rpc-batch",ht="/_lunora/ws",N=h=>h===void 0||h===""?"":`&bucket=${encodeURIComponent(h)}`,O=h=>{for(let t=h.length-1;t>=0;t-=1)h[t]?.()},dt=(h,t)=>{for(const e of t)e.op==="delete"?h.delete(e.key):e.value!==void 0&&h.set(e.key,e.value)},ut="lunora-ping",lt=3e4,mt=1e4,pt=250,ft=64,yt="/_lunora/admin/shard-traffic",wt="/_lunora/admin/scheduled",gt="/_lunora/admin/scheduled/status",bt="/_lunora/admin/scheduled/ws",vt="/_lunora/admin/scheduled/cancel",kt="/_lunora/admin/scheduled/dead",St="/_lunora/admin/scheduled/dead/retry",Ct="/_lunora/admin/scheduled/dead/cancel",Tt="/_lunora/admin/workflows/instances",It="/_lunora/admin/workflows/instance",Et="/_lunora/admin/workflows/status",E="/_lunora/admin/storage",Lt="/_lunora/admin/storage/url",At="/_lunora/admin/storage/buckets",Rt="/_lunora/admin/functions",_t="/_lunora/admin/cron-jobs",Nt="/_lunora/admin/cron-jobs/run",Ot="/_lunora/admin/openapi",Pt="/_lunora/admin/openrpc",Ft="/_lunora/admin/global/tables",xt="/_lunora/admin/global/table",$t="/_lunora/admin/global/facet",Mt="/_lunora/admin/vector/indexes",Kt="/_lunora/admin/vector/query",qt="/_lunora/admin/logs/archive",Ut="/_lunora/admin/kv/namespaces",Qt="/_lunora/admin/kv/keys",P="/_lunora/admin/kv/value",Bt="/_lunora/admin/auth/users",q="/_lunora/admin/auth/sessions",Wt="/_lunora/admin/auth/users/create",zt="/_lunora/admin/auth/users/role",Gt="/_lunora/admin/auth/users/ban",jt="/_lunora/admin/auth/users/unban",Dt="/_lunora/admin/auth/users/password",Ht="/_lunora/admin/auth/users/remove",Vt="/_lunora/admin/auth/users/impersonate",Jt="/_lunora/admin/auth/sessions/revoke",Xt="/_lunora/admin/auth/sessions/revoke-all",Yt="/_lunora/admin/auth/capabilities",Zt="/_lunora/admin/auth/users/update",te="/_lunora/admin/auth/accounts",ee="/_lunora/admin/auth/accounts/unlink",se="/_lunora/admin/auth/passkeys",ie="/_lunora/admin/auth/passkeys/delete",ne="/_lunora/admin/auth/two-factor/disable",re="/_lunora/admin/auth/organizations",oe="/_lunora/admin/auth/organizations/members",ae="/_lunora/admin/auth/organizations/invitations",ce="/_lunora/admin/auth/organizations/members/remove",he="/_lunora/admin/auth/organizations/invitations/cancel",de="/_lunora/admin/auth/config",ue="/_lunora/admin/auth/organizations/create",le="/_lunora/admin/auth/organizations/update",me="/_lunora/admin/auth/organizations/remove",pe="/_lunora/admin/auth/organizations/members/add",fe="/_lunora/admin/auth/organizations/members/invite",ye="/_lunora/admin/auth/organizations/members/role",we="/_lunora/admin/auth/organizations/teams",ge="/_lunora/admin/auth/organizations/teams/create",be="/_lunora/admin/auth/organizations/teams/update",ve="/_lunora/admin/auth/organizations/teams/remove",ke="/_lunora/admin/auth/organizations/teams/members",Se="/_lunora/admin/auth/organizations/teams/members/add",Ce="/_lunora/admin/auth/organizations/teams/members/remove",Te="/_lunora/admin/auth/organizations/roles",Ie="/_lunora/admin/auth/organizations/roles/create",Ee="/_lunora/admin/auth/organizations/roles/update",Le="/_lunora/admin/auth/organizations/roles/remove",Ae="/api/auth",Re="/get-session",U=h=>h.startsWith("https://")?`wss://${h.slice(8)}`:h.startsWith("http://")?`ws://${h.slice(7)}`:h,b=(h,t)=>`${h.endsWith("/")?h.slice(0,-1):h}${t}`,w=(h,t)=>{const e=new URLSearchParams;for(const[i,n]of Object.entries(t))n!==void 0&&n!==""&&e.set(i,String(n));const s=e.toString();return s===""?h:`${h}?${s}`},m=h=>h??"",_e=h=>{const t=h.error,e=typeof t?.code=="string"?t.code:void 0,s=typeof t?.message=="string"?t.message:void 0,i=(typeof h.message=="string"?h.message:void 0)??s??"stream error";return e===void 0?new Error(i):new d(e,i)},Q=h=>{const t=h.error,e=typeof t?.code=="string"?t.code:void 0,s=typeof t?.message=="string"?t.message:void 0;return{message:(typeof h.message=="string"?h.message:void 0)??s??"subscription error",...e===void 0?{}:{code:e}}},B=(h,t)=>{for(const e of h)try{e(t)}catch{}},Ne=new TextDecoder,Oe=h=>{if(typeof h=="string")return h;if(h instanceof ArrayBuffer)return Ne.decode(h)},y=(h,t)=>{if(!h.socket||h.wsState!=="open")return!1;try{return h.socket.send(JSON.stringify(t)),!0}catch{return!1}},C=h=>{const t=new Error(h.message??"request failed");return t.code=h.code,h.data!==void 0&&(t.data=g(h.data)),h.hint!==void 0&&(t.hint=h.hint),h.docsUrl!==void 0&&(t.docsUrl=h.docsUrl),t},v=(h,t)=>{try{return W(h)}catch(e){const s=e instanceof Error?e.message:String(e);throw new TypeError(`LunoraClient: cannot encode ${t} — ${s}`,e instanceof Error?{cause:e}:void 0)}},Pe=(h,t)=>{const e=Array.from({length:t});for(const s of h){if(typeof s.id!="number"||s.id<0||s.id>=t)continue;const i=s.body;e[s.id]=i&&"error"in i&&i.error?{error:C(i.error),ok:!1}:{ok:!0,value:g(i?.result)}}return e.map(s=>s??{error:new Error("batch call returned no result"),ok:!1})},Fe=new Set(["SHARD_ERROR","SHARD_UNAVAILABLE"]),xe=Promise.resolve();class z{static MAX_POKE_BUFFERS=256;static createClientQuery(t,e){return{defaultValue:e,key:t}}url;wsUrl;clientQueryStore;wsToken;authBasePath;fetchImpl;WebSocketImpl;bookmark;reconnectOptions;connectTimeoutMs;heartbeatIntervalMs;offlineQueue;outbox;clientId;readyResolved=!1;readyResolve;readyPromise;clientWatermarks=new Map;outboxMutationCounter=0;onPersistenceError;persistence;persistenceVersion;outboxLeaderRelease;queryCache;hydratedQueryCache=new Map;pendingCacheWrites=new Map;cacheFlushTimer;subscriptions=new k;tabCoordinator;connections=new Map;defaultConnectionContext;connectionContexts=new Map;connectionContextHolders=new Map;authToken=null;authSubject=void 0;queuedIdentities=new Map;closed=!1;authTokenListeners=new S;statusListeners=new S;tokenExpiredListeners=new S;mutationSettledListeners=new S;pendingChangeListeners=new S;whisperHandlers=new Map;lastStatus="idle";nextSubId=0;nextStreamId=0;streams=new Map;shapeSubscriptions=new Map;pokeBuffers=new Map;nextShapeId=0;constructor(t){this.url=t.url,this.wsUrl=t.wsUrl??b(U(t.url),ht),this.wsToken=t.wsToken;const e=t.authBasePath??Ae;this.authBasePath=e.endsWith("/")?e.slice(0,-1):e,this.fetchImpl=t.fetch??(typeof fetch=="function"?fetch.bind(globalThis):void 0),this.WebSocketImpl=t.WebSocket??(typeof WebSocket=="function"?WebSocket:void 0),this.bookmark=t.bookmarkStorage??D(),this.reconnectOptions=t.reconnect,this.heartbeatIntervalMs=t.heartbeatIntervalMs??lt,this.connectTimeoutMs=t.connectTimeoutMs??mt,this.defaultConnectionContext=t.connectionContext,this.persistence=nt(t.persistence,t.outbox===void 0),this.persistenceVersion=t.persistenceVersion,this.queryCache=rt(t.queryCache),this.onPersistenceError=t.offlineQueue?.onPersistenceError,this.clientQueryStore=new H,t.crossTabSync?(this.tabCoordinator=new V({onBecomeLeader:()=>{for(const s of this.subscriptions.all())this.ensureSocket(s.shardKey),this.sendSubscribeIfOpen(s)},onStopBeingLeader:()=>{for(const[s,i]of this.connections)i.socket?.close(),this.connections.delete(s)},onSubscriptionData:(s,i)=>{const n=this.subscriptions.get(s);if(n){n.serverBase=i;const r=n.optimisticLayers.length===0?i:A(i,n.optimisticLayers);n.lastValue=r;for(const o of n.callbacks)try{o(r)}catch{}}},onSubscriptionError:(s,i)=>{const n=this.subscriptions.get(s);if(n)for(const r of n.errorCallbacks)try{r(i)}catch{}}}),this.tabCoordinator.start()):this.tabCoordinator=void 0,t.hydrateOnStart&&this.queryCache?this.readyPromise=new Promise(s=>{this.readyResolve=s}):(this.readyResolved=!0,this.readyPromise=xe),this.offlineQueue=new et(t.offlineQueue,{onEvict:(s,i)=>{this.emitItemSettled(s,"rejected",i)},onSizeChange:s=>{this.pendingChangeListeners.emit(s)},persistence:this.persistence,version:t.persistenceVersion}),this.outbox=t.outbox,this.clientId=t.clientId??`client-${$()}`,this.persistence&&queueMicrotask(()=>{this.hydrateAsOutboxLeader()}),this.queryCache&&queueMicrotask(()=>{(async()=>{try{await this.hydrateQueryCache()}catch{}finally{this.readyResolved=!0,this.readyResolve?.()}})().catch(()=>{})})}setAuthToken(t,e){const s=this.authToken!==t,i=this.identityFingerprint();this.authToken=t,e!==void 0&&(this.authSubject=e);const n=this.identityFingerprint();n!==i&&(s?this.rejectQueuedForIdentityChange():this.restampQueuedIdentity(i,n)),s&&this.authTokenListeners.emit(t)}getAuthToken(){return this.authToken}currentIdentity(){return this.identityFingerprint()}clientIdentifier(){return this.clientId}confirmedMutationWatermark(t){return this.clientWatermarks.get(t??"")??0}async callMutator(t,e,s){const i=s?.clientSeq;if(i!==void 0&&(!Number.isInteger(i)||i<=0))throw new d("INTERNAL",`callMutator: clientSeq must be a positive integer, got ${String(i)}`);const n=s?.shardKey??"";let r;const o=await this.rpc(t,e,s?.shardKey,{captureBookmark:!0,clientId:this.clientId,clientSeq:i,onMutationAck:c=>{r=c}});return r!==void 0&&r>(this.clientWatermarks.get(n)??0)&&this.clientWatermarks.set(n,r),{applied:r===void 0||r===i,result:o}}onAuthTokenChange(t){return this.authTokenListeners.add(t)}async getCurrentUser(){if(this.closed||!this.fetchImpl)return null;const t={};this.authToken&&(t.authorization=`Bearer ${this.authToken}`);try{const e=await this.fetchImpl(b(this.url,`${this.authBasePath}${Re}`),{credentials:"include",headers:t,method:"GET"});return e.ok?(await e.json())?.user??null:null}catch{return null}}setWsToken(t){if(this.wsToken!==t){this.wsToken=t;for(const e of this.connections.values())if(e.socket)try{e.socket.close()}catch{}}}setConnectionContext(t,e={}){const s=m(e.shardKey);t===void 0?this.connectionContexts.delete(s):this.connectionContexts.set(s,t),this.refreshConnectionContext(s)}acquireConnectionContext(t,e={}){const s=m(e.shardKey),i={context:t},n=this.connectionContextHolders.get(s);n?n.push(i):this.connectionContextHolders.set(s,[i]),this.refreshConnectionContext(s);let r=!1;return()=>{if(r)return;r=!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)}}whisperSubscribe(t,e,s={}){const i=m(s.shardKey);let n=this.whisperHandlers.get(i);n||(n=new Map,this.whisperHandlers.set(i,n));let r=n.get(t);const o=r===void 0;if(r||(r=new Set,n.set(t,r)),r.add(e),this.ensureSocket(s.shardKey),o){const c=this.getConnection(s.shardKey);c&&y(c,{topic:t,type:"whisper_subscribe"})}return()=>{const c=this.whisperHandlers.get(i),a=c?.get(t);if(!a?.delete(e)||a.size>0)return;c?.delete(t),c?.size===0&&this.whisperHandlers.delete(i);const u=this.getConnection(s.shardKey);u&&y(u,{topic:t,type:"whisper_unsubscribe"})}}whisper(t,e,s={}){this.ensureSocket(s.shardKey);const i=this.getConnection(s.shardKey);i&&y(i,{data:v(e??null,`whisper data for topic '${t}'`),topic:t,type:"whisper"})}onTokenExpired(t){return this.tokenExpiredListeners.add(t)}connectionStatus(){return this.computeStatus()}onConnectionStatus(t){const e=this.statusListeners.add(t);return t(this.computeStatus()),e}pendingCount(){return this.offlineQueue.size}debug(){const t=[],e=new Set([...this.connections.keys(),...this.clientWatermarks.keys()]);for(const i of e){const n=this.connections.get(i);t.push({confirmedMutationWatermark:this.clientWatermarks.get(i)??0,hasSocket:n?.socket!==void 0,shardKey:i===""?void 0:i,wasEverConnected:n?.wasEverConnected??!1,wsState:n?.wsState??"idle"})}const s=this.subscriptions.all().map(i=>({acked:i.acked,functionPath:i.fn.__lunoraRef,id:i.id,kind:"query",lastMutationId:i.lastMutationId,pendingOptimisticLayers:i.optimisticLayers.length,serverCursor:i.serverCursor,shardKey:i.shardKey,subscriberCount:i.callbacks.size}));for(const i of this.shapeSubscriptions.values())s.push({acked:i.serverCursor!==void 0,functionPath:`shape:${i.name}`,id:i.id,kind:"shape",lastMutationId:i.lastMutationId,pendingOptimisticLayers:0,rowCount:i.rows.size,serverCursor:i.serverCursor,shardKey:i.shardKey,subscriberCount:i.callbacks.size});return{clientId:this.clientId,closed:this.closed,connectionStatus:this.computeStatus(),pendingWrites:this.offlineQueue.size,shards:t.toSorted((i,n)=>(i.shardKey??"").localeCompare(n.shardKey??"")),subscriptions:s.toSorted((i,n)=>i.functionPath.localeCompare(n.functionPath))}}onPendingChange(t){const e=this.pendingChangeListeners.add(t);return t(this.offlineQueue.size),e}onMutationSettled(t){return this.mutationSettledListeners.add(t)}getWebSocketImpl(){return this.WebSocketImpl}getClientQuery(t){return this.clientQueryStore.get(t)}setClientQuery(t,e){this.clientQueryStore.set(t,e)}subscribeClientQuery(t,e){return this.clientQueryStore.subscribe(t,e)}resetClientQuery(t){this.clientQueryStore.reset(t)}snapshotPrecondition(t,e,s){const i=this.peekActiveQueryValue(t.__lunoraRef,e,s),n=i===void 0?void 0:I(i);return()=>{const r=this.peekActiveQueryValue(t.__lunoraRef,e,s);return n===void 0&&r===void 0?!0:n===void 0||r===void 0?!1:I(r)===n}}whenReady(){return this.readyPromise}get isReady(){return this.readyResolved}peekHydratedQuery(t,e,s){if(!this.readyResolved)return;const i=I(e),n=R(t,i,s),r=this.hydratedQueryCache.get(n);if(r!==void 0)return r.identity===this.identityFingerprint()?r.value:void 0}peekActiveQueryValue(t,e,s){const i=k.key(t,e,s);return this.subscriptions.get(i)?.lastValue}async query(t,e,s={}){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");return await this.rpc(t.__lunoraRef,e,s.shardKey,{attachBookmark:!0})}async batch(t){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");if(!this.fetchImpl)throw new d("INTERNAL","LunoraClient: no `fetch` implementation available");if(t.length===0)return[];const e=await this.fetchImpl(b(this.url,K),{body:JSON.stringify({calls:t.map((n,r)=>({args:v(n.args??{},`args for batch call '${n.fn.__lunoraRef}'`),functionPath:n.fn.__lunoraRef,id:r,shardKey:n.shardKey}))}),headers:this.rpcRequestHeaders({attachBookmark:!0}),method:"POST"}),s=e.headers.get("x-d1-bookmark");s&&this.bookmark.set(s);let i;try{i=await e.json()}catch{throw new d("INTERNAL",`LunoraClient: batch response was not JSON (status ${e.status.toString()})`)}if(!e.ok||i.error&&!i.results)throw i.error?C(i.error):new d("INTERNAL",`LunoraClient: batch request failed (status ${e.status.toString()})`);return Pe(i.results??[],t.length)}async mutation(t,e,s={}){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");const i=e,n=s.mutationId??$(),{confirms:r,rollbacks:o}=this.applyOptimisticUpdates(t.__lunoraRef,i,s.shardKey,s.optimistic);s.optimisticUpdate&&this.applyOptimisticUpdate(s.optimisticUpdate,e,s.shardKey,o,r);const c=this.getConnection(s.shardKey),a=c?.wsState??"idle",u=c?.socket!==void 0,l=c?.wasEverConnected??!1,{queueBeforeFirstConnect:p}=this.offlineQueue,f=l||p,G=this.WebSocketImpl!==void 0&&f;if(a!=="open"&&!u&&G||a==="connecting"&&f)return this.enqueueOfflineMutation(t,i,s.shardKey,n,o,r,s.precondition);try{let T;const j=await this.rpc(t.__lunoraRef,i,s.shardKey,{captureBookmark:!0,mutationId:n,onCommitCursor:L=>{T=L}});for(const L of r)L(T);return j}catch(T){throw O(o),T}}async action(t,e,s={}){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");return await this.rpc(t.__lunoraRef,e,s.shardKey)}async importRows(t,e,s={}){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");const i=Math.max(1,Math.trunc(s.chunkSize??500)),n=s.toArgs??(a=>({rows:a})),r=e.length;let o=0,c=0;for(let a=0;a<r;a+=i){const u=e.slice(a,a+i),l=c;await this.mutation(t,n(u),{...s.importId===void 0?{}:{mutationId:`${s.importId}:${String(l)}`},shardKey:s.shardKey}),c+=1,o+=u.length,s.onProgress?.({done:o,total:r})}return{chunks:c,imported:o}}async shardTraffic(t){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");const e=await this.adminFetch(yt,"POST",{table:t});return{failed:e.failed??0,ok:e.ok??0,shards:e.shards??[]}}async listScheduledJobs(){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");return(await this.adminFetch(wt,"GET")).records??[]}async schedulerStatus(){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");const t=await this.adminFetch(gt,"GET");return{backlog:t.backlog??0,inFlight:t.inFlight??0,pools:t.pools??[]}}async cancelScheduledJob(t){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");return{cancelled:(await this.adminFetch(vt,"POST",{id:t})).cancelled===!0}}async listDeadJobs(){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");return(await this.adminFetch(kt,"GET")).records??[]}async retryDeadJob(t){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");return{retried:(await this.adminFetch(St,"POST",{id:t})).retried===!0}}async removeDeadJob(t){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");return{removed:(await this.adminFetch(Ct,"POST",{id:t})).removed===!0}}async listWorkflowInstances(t){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");const e=new URLSearchParams({name:t.name});t.status!==void 0&&e.set("status",t.status),t.page!==void 0&&e.set("page",String(t.page)),t.perPage!==void 0&&e.set("perPage",String(t.perPage));const s=await this.adminFetch(`${Tt}?${e.toString()}`,"GET");return{configured:s.configured,instances:s.instances??[],page:s.page??1,perPage:s.perPage??t.perPage??0,totalCount:s.totalCount}}async getWorkflowInstance(t){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");const e=new URLSearchParams({id:t.id,name:t.name}),s=await this.adminFetch(`${It}?${e.toString()}`,"GET");return{createdOn:s.createdOn,endedOn:s.endedOn,error:s.error,id:s.id??t.id,output:s.output,params:s.params,startedOn:s.startedOn,status:s.status??"unknown",steps:s.steps??[]}}async setWorkflowInstanceStatus(t){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");return{status:(await this.adminFetch(Et,"POST",{action:t.action,id:t.id,name:t.name})).status??"unknown"}}subscribeScheduledJobs(t){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");if(this.WebSocketImpl===void 0)return()=>{};const e=b(U(this.url),bt),s=M(this.reconnectOptions);let i,n,r=!1;const o=u=>{if(r||this.WebSocketImpl===void 0)return;const l=u===void 0?e:`${e}?token=${encodeURIComponent(u)}`;i=new this.WebSocketImpl(l),i.addEventListener("open",()=>{s.reset()}),i.addEventListener("message",p=>{try{const f=JSON.parse(typeof p.data=="string"?p.data:"");f.type==="jobs"&&Array.isArray(f.records)&&t(f.records)}catch{}}),i.addEventListener("close",()=>{i=void 0,r||(n=setTimeout(a,s.next()))}),i.addEventListener("error",()=>{})},c=async u=>{let l;try{l=await u()}catch{r||(n=setTimeout(a,s.next()));return}o(l)},a=()=>{if(r||this.WebSocketImpl===void 0)return;const{wsToken:u}=this;if(typeof u=="function"){c(u).catch(()=>{});return}o(u)};return a(),()=>{r=!0,n!==void 0&&clearTimeout(n),i?.close()}}async listFunctions(){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");return(await this.adminFetch(Rt,"GET")).functions??[]}async getCronJobs(){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");return(await this.adminFetch(_t,"GET")).jobs??[]}async runCronJob(t){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");const e=await this.adminFetch(Nt,"POST",{name:t});return{name:e.name??t,ran:e.ran===!0}}async fetchOpenApi(){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");return await this.adminFetch(Ot,"GET")}async fetchOpenRpc(){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");return await this.adminFetch(Pt,"GET")}async listStorageObjects(t={}){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");const e=new URLSearchParams;t.prefix!==void 0&&t.prefix!==""&&e.set("prefix",t.prefix),t.cursor!==void 0&&t.cursor!==""&&e.set("cursor",t.cursor),t.limit!==void 0&&e.set("limit",String(t.limit)),t.bucket!==void 0&&t.bucket!==""&&e.set("bucket",t.bucket);const s=e.toString(),i=s===""?E:`${E}?${s}`,n=await this.adminFetch(i,"GET");return{cursor:n.cursor,objects:n.objects??[]}}async deleteStorageObject(t,e){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");const s=`${E}?key=${encodeURIComponent(t)}${N(e?.bucket)}`,i=await this.adminFetch(s,"DELETE");return{deleted:i.deleted??!0,key:i.key??t}}async listStorageBuckets(){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");return(await this.adminFetch(At,"GET")).buckets??[]}async uploadStorageObject(t){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");const e=`${E}?key=${encodeURIComponent(t.key)}${N(t.bucket)}`,s=await this.adminFetch(e,"PUT",t.body,t.contentType);return{etag:s.etag,key:s.key??t.key}}async signedStorageUrl(t,e){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");const s=e?.expiresInSeconds,i=s===void 0?"":`&expiresIn=${encodeURIComponent(s.toString())}`,n=`${Lt}?key=${encodeURIComponent(t)}${i}${N(e?.bucket)}`,r=await this.adminFetch(n,"GET");if(typeof r.url!="string")throw new TypeError("LunoraClient: storage URL endpoint returned no `url`");return r.url}async listGlobalTables(){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");return await this.adminFetch(Ft,"GET")}async readGlobalTablePage(t){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");const e=new URLSearchParams({table:t.table});return t.limit!==void 0&&e.set("limit",String(t.limit)),t.offset!==void 0&&e.set("offset",String(t.offset)),t.filters!==void 0&&t.filters.length>0&&e.set("filters",JSON.stringify(t.filters)),await this.adminFetch(`${xt}?${e.toString()}`,"GET")}async facetGlobalColumn(t){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");const e=new URLSearchParams({column:t.column,table:t.table});return t.limit!==void 0&&e.set("limit",String(t.limit)),t.filters!==void 0&&t.filters.length>0&&e.set("filters",JSON.stringify(t.filters)),await this.adminFetch(`${$t}?${e.toString()}`,"GET")}async listVectorIndexes(){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");return(await this.adminFetch(Mt,"GET")).indexes??[]}async queryVectorIndex(t){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");return(await this.adminFetch(Kt,"POST",t)).matches??[]}async queryLogArchive(t={}){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");const e=await this.adminFetch(qt,"POST",t);return{nextCursor:e.nextCursor,rows:e.rows??[]}}async listKvNamespaces(){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");return(await this.adminFetch(Ut,"GET")).namespaces??[]}async listKvKeys(t){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");const e=w(Qt,{cursor:t.cursor,limit:t.limit,namespace:t.namespace,prefix:t.prefix});return await this.adminFetch(e,"GET")}async getKvValue(t){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");const e=w(P,{key:t.key,namespace:t.namespace});return await this.adminFetch(e,"GET")}async putKvValue(t){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");await this.adminFetch(P,"PUT",t)}async deleteKvKey(t){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");const e=w(P,{key:t.key,namespace:t.namespace});await this.adminFetch(e,"DELETE")}async listAuthUsers(t={}){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");const e=w(Bt,{filterField:t.filterField,filterValue:t.filterValue,limit:t.limit,offset:t.offset,search:t.search,searchField:t.searchField,sortBy:t.sortBy,sortDirection:t.sortDirection});return await this.adminFetch(e,"GET")}async createAuthUser(t){return await this.adminFetch(Wt,"POST",t)}async setAuthUserRole(t){return await this.adminFetch(zt,"POST",t)}async banAuthUser(t){return await this.adminFetch(Gt,"POST",t)}async unbanAuthUser(t){return await this.adminFetch(jt,"POST",t)}async setAuthUserPassword(t){await this.adminFetch(Dt,"POST",t)}async removeAuthUser(t){await this.adminFetch(Ht,"POST",t)}async impersonateAuthUser(t){return await this.adminFetch(Vt,"POST",t)}async revokeAuthSession(t){await this.adminFetch(Jt,"POST",t)}async revokeAuthUserSessions(t){await this.adminFetch(Xt,"POST",t)}async getAuthCapabilities(){return await this.adminFetch(Yt,"GET")}async updateAuthUser(t){return await this.adminFetch(Zt,"POST",t)}async listAuthAccounts(t){return await this.adminFetch(w(te,{userId:t.userId}),"GET")}async unlinkAuthAccount(t){await this.adminFetch(ee,"POST",t)}async listAuthPasskeys(t){return await this.adminFetch(w(se,{userId:t.userId}),"GET")}async deleteAuthPasskey(t){await this.adminFetch(ie,"POST",t)}async disableAuthTwoFactor(t){await this.adminFetch(ne,"POST",t)}async listAuthOrganizations(t={}){return await this.adminFetch(w(re,{limit:t.limit,offset:t.offset}),"GET")}async listAuthOrgMembers(t){const e=w(oe,{limit:t.limit,offset:t.offset,organizationId:t.organizationId});return await this.adminFetch(e,"GET")}async listAuthOrgInvitations(t){const e=w(ae,{limit:t.limit,offset:t.offset,organizationId:t.organizationId});return await this.adminFetch(e,"GET")}async removeAuthOrgMember(t){await this.adminFetch(ce,"POST",t)}async cancelAuthOrgInvitation(t){await this.adminFetch(he,"POST",t)}async getAuthConfig(){return await this.adminFetch(de,"GET")}async createAuthOrganization(t){return await this.adminFetch(ue,"POST",t)}async updateAuthOrganization(t){return await this.adminFetch(le,"POST",t)}async deleteAuthOrganization(t){await this.adminFetch(me,"POST",t)}async addAuthOrgMember(t){return await this.adminFetch(pe,"POST",t)}async inviteAuthOrgMember(t){return await this.adminFetch(fe,"POST",t)}async setAuthOrgMemberRole(t){return await this.adminFetch(ye,"POST",t)}async listAuthOrgTeams(t){const e=w(we,{limit:t.limit,offset:t.offset,organizationId:t.organizationId});return await this.adminFetch(e,"GET")}async createAuthOrgTeam(t){return await this.adminFetch(ge,"POST",t)}async updateAuthOrgTeam(t){return await this.adminFetch(be,"POST",t)}async removeAuthOrgTeam(t){await this.adminFetch(ve,"POST",t)}async listAuthOrgTeamMembers(t){const e=w(ke,{limit:t.limit,offset:t.offset,teamId:t.teamId});return await this.adminFetch(e,"GET")}async addAuthOrgTeamMember(t){return await this.adminFetch(Se,"POST",t)}async removeAuthOrgTeamMember(t){await this.adminFetch(Ce,"POST",t)}async listAuthOrgRoles(t){const e=w(Te,{limit:t.limit,offset:t.offset,organizationId:t.organizationId});return await this.adminFetch(e,"GET")}async createAuthOrgRole(t){return await this.adminFetch(Ie,"POST",t)}async updateAuthOrgRole(t){return await this.adminFetch(Ee,"POST",t)}async deleteAuthOrgRole(t){await this.adminFetch(Le,"POST",t)}async listAuthSessions(t={}){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");const e=new URLSearchParams;t.userId!==void 0&&t.userId!==""&&e.set("userId",t.userId),t.limit!==void 0&&e.set("limit",String(t.limit)),t.offset!==void 0&&e.set("offset",String(t.offset));const s=e.toString();return await this.adminFetch(s===""?q:`${q}?${s}`,"GET")}subscribe(t,e,s,i={}){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");const n=e??{},r=k.key(t.__lunoraRef,n,i.shardKey);let o=this.subscriptions.get(r);const c=s,a=i.onError;if(!o){this.nextSubId+=1;const l=`sub_${this.nextSubId.toString()}`,p=I(n),f=this.takeHydratedCache(t.__lunoraRef,p,i.shardKey);o={acked:!1,args:n,argsKey:p,callbacks:new Set,checkpointCallbacks:new Set,errorCallbacks:new Set,fn:t,id:l,lastValue:f?.value,optimisticLayers:[],serverBase:f?.value,serverCursor:f?.serverCursor,shardKey:i.shardKey,...f?.serverEpoch===void 0?{}:{serverEpoch:f.serverEpoch}},this.subscriptions.add(o)}if(o.callbacks.add(c),a&&o.errorCallbacks.add(a),i.onCheckpoint&&o.checkpointCallbacks.add(i.onCheckpoint),o.lastValue!==void 0)try{c(o.lastValue)}catch{}this.ensureSocket(i.shardKey),this.sendSubscribeIfOpen(o);const u=o;return()=>{if(u.callbacks.delete(c),a&&u.errorCallbacks.delete(a),i.onCheckpoint&&u.checkpointCallbacks.delete(i.onCheckpoint),u.callbacks.size===0){const l=this.getConnection(u.shardKey);!(l&&y(l,{id:u.id,type:"unsubscribe"}))&&l&&l.pendingUnsubscribes.push({id:u.id,type:"unsubscribe"}),this.subscriptions.remove(u)}}}subscribeShape(t,e,s={}){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");this.nextShapeId+=1;const i=`shape_${this.nextShapeId.toString()}`,n={args:t.args,callbacks:new Set([e]),errorCallbacks:s.onError?new Set([s.onError]):new Set,id:i,name:t.name,onCheckpoint:s.onCheckpoint,rows:new Map,shardKey:s.shardKey,wireArgs:t.args===void 0?void 0:v(t.args,`shape args for '${t.name}'`)};return this.shapeSubscriptions.set(i,n),this.ensureSocket(s.shardKey),this.sendShapeSubscribeIfOpen(n),()=>{this.shapeSubscriptions.delete(i);const r=this.getConnection(n.shardKey);!(r&&y(r,{id:i,type:"shape_unsubscribe"}))&&r&&r.pendingUnsubscribes.push({id:i,type:"shape_unsubscribe"})}}stream(t,e,s={}){if(this.closed)throw new d("INTERNAL","LunoraClient is closed");if(this.WebSocketImpl===void 0)throw new d("INTERNAL","LunoraClient: streams require a WebSocket implementation");this.nextStreamId+=1;const i=`stream_${this.nextStreamId.toString()}`,{shardKey:n}=s,r=e??{},{handle:o,iterable:c}=ot({maxBuffer:s.maxBuffer,onCancel:()=>{const l=this.getConnection(n);l&&y(l,{id:i,type:"unsubscribe"}),this.streams.delete(i)}});this.streams.set(i,{handle:o,shardKey:n}),this.ensureSocket(n);const a=this.getConnection(n),u={id:i,query:{args:v(r,`stream args for '${t.__lunoraRef}'`),functionPath:t.__lunoraRef,shardKey:n},type:"stream"};if(!(a?.wsState==="open"&&y(a,u))&&a){for(a.pendingStreams=a.pendingStreams??[];a.pendingStreams.length>=ft;){const l=a.pendingStreams.shift()?.id,p=l?this.streams.get(l):void 0;p&&(p.handle.fail(new d("STREAM_QUEUE_OVERFLOW","stream-start frame evicted while socket was unreachable")),this.streams.delete(l))}a.pendingStreams.push(u)}return c}httpStream(t,e,s={}){if(this.closed)throw new d("CLIENT_CLOSED","LunoraClient is closed");if(!this.fetchImpl)throw new d("INTERNAL","LunoraClient: no `fetch` implementation available");const i={...this.authToken?{authorization:`Bearer ${this.authToken}`}:{},...s.headers};return Y(t,e,{baseUrl:this.url,fetch:this.fetchImpl,headers:i,maxBuffer:s.maxBuffer,signal:s.signal})}close(){this.closed=!0,this.outboxLeaderRelease?.(),this.outboxLeaderRelease=void 0;for(const t of this.streams.values())t.handle.fail(new d("CLIENT_CLOSED","LunoraClient closed"));this.streams.clear();for(const t of this.connections.values()){if(t.reconnectTimer!==void 0&&(clearTimeout(t.reconnectTimer),t.reconnectTimer=void 0),t.connectTimer!==void 0&&(clearTimeout(t.connectTimer),t.connectTimer=void 0),this.stopHeartbeat(t),t.socket){try{t.socket.close()}catch{}t.socket=void 0}t.wsState="closed"}this.offlineQueue.clear(),this.queuedIdentities.clear(),this.cacheFlushTimer!==void 0&&(clearTimeout(this.cacheFlushTimer),this.cacheFlushTimer=void 0),this.pendingCacheWrites.size>0&&this.flushQueryCacheWrites().catch(()=>{}),this.authTokenListeners.clear(),this.statusListeners.clear(),this.tokenExpiredListeners.clear(),this.mutationSettledListeners.clear(),this.pendingChangeListeners.clear(),this.whisperHandlers.clear(),this.shapeSubscriptions.clear(),this.pokeBuffers.clear(),this.tabCoordinator?.stop(),this.tabCoordinator=void 0}async enqueueOfflineMutation(t,e,s,i,n,r,o){const c=this.identityFingerprint();if(this.outbox){this.outboxMutationCounter+=1;const a=this.outboxMutationCounter;try{await this.outbox.enqueue({args:e,clientId:this.clientId,functionPath:t.__lunoraRef,idempotencyKey:`${this.clientId}:${String(a)}`,identity:c,mutationId:a,shardKey:s})}catch(u){throw O(n),u instanceof Error?u:new Error(String(u))}for(const u of r)u(void 0);return}return new Promise((a,u)=>{const l={args:e,functionPath:t.__lunoraRef,liveAwaiter:!0,id:i,identity:c,precondition:o,onCommit:p=>{for(const f of r)f(p)},reject:p=>{this.queuedIdentities.delete(i),O(n),u(p instanceof Error?p:new Error(String(p)))},resolve:a,shardKey:s};this.offlineQueue.enqueue(l),l.id!==void 0&&this.queuedIdentities.set(l.id,c)})}async hydratePersistedQueue(){try{const t=await this.offlineQueue.hydrate();for(const e of t)this.ensureSocket(e)}catch{}}hydrateAsOutboxLeader(){const t=()=>{this.hydratePersistedQueue().catch(()=>{})},e=globalThis.navigator?.locks;if(!e){t();return}e.request(`lunora:outbox-leader:${this.url}`,()=>(this.closed||t(),new Promise(s=>{if(this.closed){s();return}this.outboxLeaderRelease=s}))).catch(t)}async hydrateQueryCache(){if(this.queryCache)try{const t=await this.queryCache.load();for(const{key:e,...s}of t){if(st(this.persistenceVersion,s.version)){this.queryCache.remove(e).catch(()=>{});continue}this.hydratedQueryCache.set(e,s)}}catch{}}takeHydratedCache(t,e,s){const i=R(t,e,s),n=this.hydratedQueryCache.get(i);if(n!==void 0)return this.hydratedQueryCache.delete(i),n.identity===this.identityFingerprint()?n:void 0}persistQueryValue(t){const e=t.serverBase;if(!this.queryCache||e===void 0)return;const s=R(t.fn.__lunoraRef,t.argsKey,t.shardKey);this.pendingCacheWrites.set(s,{identity:this.identityFingerprint(),serverCursor:t.serverCursor,ts:Date.now(),value:e,...t.serverEpoch===void 0?{}:{serverEpoch:t.serverEpoch},...this.persistenceVersion===void 0?{}:{version:this.persistenceVersion}}),this.cacheFlushTimer??=setTimeout(()=>{this.flushQueryCacheWrites().catch(()=>{})},pt)}async flushQueryCacheWrites(){this.cacheFlushTimer=void 0;const{queryCache:t}=this;if(!t){this.pendingCacheWrites.clear();return}const e=[...this.pendingCacheWrites.entries()];this.pendingCacheWrites.clear(),await Promise.allSettled(e.map(([s,i])=>t.put(s,i)))}computeStatus(){const t=[...this.connections.values()];return t.length===0?"idle":t.some(e=>e.wsState==="open")?"connected":t.some(e=>e.wsState==="connecting")?"connecting":"offline"}emitConnectionStatus(){const t=this.computeStatus();t!==this.lastStatus&&(this.lastStatus=t,this.statusListeners.emit(t))}emitItemSettled(t,e,s){this.mutationSettledListeners.emit({args:t.args,code:s===void 0?void 0:s.code,error:s,functionPath:t.functionPath,hadAwaiter:t.liveAwaiter??!1,id:t.id??"",shardKey:t.shardKey,status:e})}applyOptimisticUpdates(t,e,s,i){const n=[],r=[];if(!i)return{confirms:n,rollbacks:r};const o=k.key(t,e,s),c=this.subscriptions.get(o);if(c){const a=Z(c,i);a&&(n.push(a.confirm),r.push(a.rollback))}return{confirms:n,rollbacks:r}}applyOptimisticUpdate(t,e,s,i,n){const{confirms:r,rollbacks:o,store:c}=tt(this.subscriptions,s);try{t(c,e)}catch{for(let a=o.length-1;a>=0;a-=1)o[a]?.();return}i.push(...o),n.push(...r)}getConnection(t){return this.connections.get(m(t))}getOrCreateConnection(t){const e=m(t);let s=this.connections.get(e);return s||(s={connectTimer:void 0,heartbeatTimer:void 0,pendingUnsubscribes:[],reconnect:M(this.reconnectOptions),reconnectTimer:void 0,shardKey:t,socket:void 0,wasEverConnected:!1,wsState:"idle"},this.connections.set(e,s)),s}wsUrlFor(t,e){const s=[];if(t!==void 0&&s.push(`shard=${encodeURIComponent(t)}`),e!==void 0&&s.push(`token=${encodeURIComponent(e)}`),s.length===0)return this.wsUrl;const i=this.wsUrl.includes("?")?"&":"?";return`${this.wsUrl}${i}${s.join("&")}`}rpcRequestHeaders(t){const e={"content-type":"application/json"};if(this.authToken&&(e.authorization=`Bearer ${this.authToken}`),t.mutationId&&(e["x-lunora-mutation-id"]=t.mutationId),t.clientId!==void 0&&(e["x-lunora-client-id"]=t.clientId),t.clientSeq!==void 0&&(e["x-lunora-client-seq"]=t.clientSeq.toString()),t.attachBookmark){const s=this.bookmark.get();s&&(e["x-d1-bookmark"]=s)}return e}async rpc(t,e,s,i={}){if(!this.fetchImpl)throw new d("INTERNAL","LunoraClient: no `fetch` implementation available");const n=this.rpcRequestHeaders(i),r=await this.fetchImpl(b(this.url,ct),{body:JSON.stringify({args:v(e,`args for '${t}'`),functionPath:t,shardKey:s}),headers:n,method:"POST"});if(i.captureBookmark){const c=r.headers.get("x-d1-bookmark");c&&this.bookmark.set(c)}let o;try{o=await r.json()}catch{const c=r.statusText?` ${r.statusText}`:"";throw new d("INTERNAL",`LunoraClient: response was not JSON (status ${r.status.toString()}${c})`)}if("error"in o)throw C(o.error);if(!r.ok){const c=r.statusText?` ${r.statusText}`:"";throw new d("INTERNAL",`LunoraClient: request failed (status ${r.status.toString()}${c})`)}return i.onMutationAck?.(o.lastMutationId),i.onCommitCursor?.(o.commitCursor),g(o.result)}async adminFetch(t,e,s,i){if(!this.fetchImpl)throw new d("INTERNAL","LunoraClient: no `fetch` implementation available");const n={};this.authToken&&(n.authorization=`Bearer ${this.authToken}`);const r=s instanceof ArrayBuffer||s instanceof Blob;let o;s===void 0?o=void 0:r?(o=s,i!==void 0&&(n["content-type"]=i)):(o=JSON.stringify(s),n["content-type"]="application/json");const c=await this.fetchImpl(b(this.url,t),{body:o,headers:n,method:e});let a;try{a=await c.json()}catch{const u=c.statusText?` ${c.statusText}`:"";throw new d("INTERNAL",`LunoraClient: response was not JSON (status ${c.status.toString()}${u})`)}if(typeof a=="object"&&a!==null&&"error"in a){const u=a.error,l=new Error(u.message??"admin request failed");throw l.code=u.code,l}if(!c.ok){const u=c.statusText?` ${c.statusText}`:"";throw new d("INTERNAL",`LunoraClient: admin request failed (status ${c.status.toString()}${u})`)}return a}effectiveConnectionContext(t){const e=this.connectionContextHolders.get(t);return e&&e.length>0?e[e.length-1]?.context:this.connectionContexts.get(t)??this.defaultConnectionContext}refreshConnectionContext(t){const e=this.connections.get(t);e?.wsState==="open"&&this.sendConnectEnvelope(e)}sendConnectEnvelope(t){const e=this.effectiveConnectionContext(m(t.shardKey));y(t,{clientId:this.clientId,id:"connect",type:"connect",...e===void 0?{}:{context:e}})}resendShapeSubscriptions(t){for(const e of this.shapeSubscriptions.values())m(e.shardKey)===m(t)&&this.sendShapeSubscribeIfOpen(e)}ensureSocket(t){if(this.closed||this.WebSocketImpl===void 0||this.tabCoordinator&&!this.tabCoordinator.isLeader())return;const e=this.getOrCreateConnection(t);if(!(e.wsState==="open"||e.wsState==="connecting")){if(e.wsState="connecting",this.emitConnectionStatus(),typeof this.wsToken=="function"){this.openSocketWithProvidedToken(e,t,this.wsToken).catch(()=>{});return}this.openSocket(e,t,this.wsToken)}}async openSocketWithProvidedToken(t,e,s){let i;try{i=await s()}catch{this.handleDisconnect(t);return}this.closed||this.WebSocketImpl===void 0||t.wsState!=="connecting"||t.socket!==void 0||this.openSocket(t,e,i)}openSocket(t,e,s){if(this.WebSocketImpl===void 0)return;const i=new this.WebSocketImpl(this.wsUrlFor(e,s));t.socket=i,this.connectTimeoutMs>0&&(t.connectTimer=setTimeout(()=>{if(t.connectTimer=void 0,!(t.socket!==i||t.wsState!=="connecting")){try{i.close()}catch{}this.handleDisconnect(t)}},this.connectTimeoutMs)),i.addEventListener("open",()=>{if(t.socket!==i)return;t.connectTimer!==void 0&&(clearTimeout(t.connectTimer),t.connectTimer=void 0),t.wsState="open",t.wasEverConnected=!0,t.reconnect.reset(),this.emitConnectionStatus(),this.sendConnectEnvelope(t),this.markShardPendingAck(e);for(const r of this.subscriptions.all())m(r.shardKey)===m(e)&&this.sendSubscribeIfOpen(r);if(this.resendShapeSubscriptions(e),t.pendingUnsubscribes.length>0){const r=t.pendingUnsubscribes;t.pendingUnsubscribes=[];for(const{id:o,type:c}of r)y(t,{id:o,type:c})}if(t.pendingStreams&&t.pendingStreams.length>0){const r=t.pendingStreams;t.pendingStreams=[];for(const o of r)y(t,o)}const n=this.whisperHandlers.get(m(e));if(n)for(const r of n.keys())y(t,{topic:r,type:"whisper_subscribe"});this.flushOfflineQueue(e).catch(()=>{}),this.startHeartbeat(t)}),i.addEventListener("message",n=>{this.handleServerMessage(n.data,e)}),i.addEventListener("close",n=>{t.socket===i&&(n?.code===4001&&this.notifyTokenExpired(),this.handleDisconnect(t))}),i.addEventListener("error",()=>{t.socket===i&&(t.wsState==="connecting"||t.wsState==="open")&&this.handleDisconnect(t)})}handleDisconnect(t){if(this.closed||t.wsState==="idle"||t.wsState==="closed")return;this.stopHeartbeat(t),t.connectTimer!==void 0&&(clearTimeout(t.connectTimer),t.connectTimer=void 0),t.socket=void 0,t.wsState="idle",this.emitConnectionStatus(),this.markShardPendingAck(t.shardKey);const e=new Set((t.pendingStreams??[]).map(i=>i.id));for(const[i,n]of this.streams)m(n.shardKey)===m(t.shardKey)&&!e.has(i)&&(n.handle.fail(new d("STREAM_DISCONNECTED","stream terminated: WebSocket disconnected")),this.streams.delete(i));if(this.WebSocketImpl===void 0)return;const s=t.reconnect.next();t.reconnectTimer=setTimeout(()=>{t.reconnectTimer=void 0,this.ensureSocket(t.shardKey)},s)}startHeartbeat(t){this.stopHeartbeat(t),!(this.heartbeatIntervalMs<=0)&&(t.heartbeatTimer=setInterval(()=>{if(!(t.wsState!=="open"||!t.socket))try{t.socket.send(ut)}catch{}},this.heartbeatIntervalMs))}stopHeartbeat(t){t.heartbeatTimer!==void 0&&(clearInterval(t.heartbeatTimer),t.heartbeatTimer=void 0)}markShardPendingAck(t){const e=m(t);for(const s of this.subscriptions.all())m(s.shardKey)===e&&(s.acked=!1)}sendSubscribeIfOpen(t){const e=this.getConnection(t.shardKey);if(e?.wsState!=="open"||t.acked)return;const s=t.fn.__lunoraTable??t.fn.__lunoraRef;y(e,{id:t.id,query:{args:W(t.args),functionPath:t.fn.__lunoraRef,table:s,...t.serverCursor===void 0?{}:{sinceSeq:t.serverCursor},...t.serverEpoch===void 0?{}:{sinceEpoch:t.serverEpoch}},type:"subscribe"})}sendShapeSubscribeIfOpen(t){const e=this.getConnection(t.shardKey);e?.wsState==="open"&&y(e,{id:t.id,shape:{name:t.name,...t.wireArgs===void 0?{}:{args:t.wireArgs}},type:"shape_subscribe",...t.serverCursor===void 0?{}:{sinceCheckpoint:t.serverCursor},...t.serverEpoch===void 0?{}:{sinceEpoch:t.serverEpoch}})}handleServerMessage(t,e){const s=Oe(t);if(s===void 0)return;let i;try{i=JSON.parse(s)}catch{return}switch(i.type){case"ack":{const n=this.subscriptions.getById(i.id);n&&(n.acked=!0);return}case"chunk":{const{data:n,id:r}=i;this.streams.get(r)?.handle.push(g(n));return}case"complete":{this.handleCompleteMessage(i.id);return}case"data":case"delta":{this.handleDataMessage(i);return}case"error":{this.handleErrorMessage(i);break}case"pokeEnd":{this.handlePokeEnd(i);break}case"pokePart":{this.handlePokePart(i);break}case"pokeStart":{this.handlePokeStart(i);break}case"resume":{this.handleResumeMessage(i);break}case"settled":{this.handleSettledMessage(i);break}case"whisper":{this.dispatchWhisper(i,e);break}}}handleErrorMessage(t){if(t.error?.code==="TOKEN_EXPIRED"){this.notifyTokenExpired();return}const{id:e}=t,s=e===void 0?void 0:this.streams.get(e);if(s&&e!==void 0){s.handle.fail(_e(t)),this.streams.delete(e);return}const i=e===void 0?void 0:this.subscriptions.getById(e);if(i){B(i.errorCallbacks,Q(t));return}const n=e===void 0?void 0:this.shapeSubscriptions.get(e);n&&B(n.errorCallbacks,Q(t))}handlePokeStart(t){at(this.pokeBuffers,z.MAX_POKE_BUFFERS),this.pokeBuffers.set(t.pokeId,{baseCheckpoint:t.baseCheckpoint,epoch:t.epoch,lastMutationId:new Map,parts:new Map})}handlePokePart(t){const e=this.pokeBuffers.get(t.pokeId);if(!e)return;const s=e.parts.get(t.shapeId)??[];for(const i of t.rowsPatch)s.push(i.value===void 0?i:{...i,value:g(i.value)});e.parts.set(t.shapeId,s),t.lastMutationId!==void 0&&e.lastMutationId.set(t.shapeId,t.lastMutationId)}handlePokeEnd(t){const e=this.pokeBuffers.get(t.pokeId);if(e){this.pokeBuffers.delete(t.pokeId);for(const[s,i]of e.parts){const n=this.shapeSubscriptions.get(s);if(!n)continue;const r=e.epoch!==void 0&&n.serverEpoch!==void 0&&e.epoch!==n.serverEpoch,o=e.baseCheckpoint!==void 0&&n.serverCursor!==void 0&&n.serverCursor!==e.baseCheckpoint;if(r||o){n.rows.clear(),n.serverCursor=void 0,n.serverEpoch=void 0,this.emitShapeRows(n),this.sendShapeSubscribeIfOpen(n);continue}dt(n.rows,i),t.checkpoint!==void 0&&(n.serverCursor=t.checkpoint),t.epoch!==void 0&&(n.serverEpoch=t.epoch);const c=e.lastMutationId.get(s);c!==void 0&&(n.lastMutationId=c),this.emitShapeRows(n),n.onCheckpoint?.({checkpoint:n.serverCursor,mutationId:n.lastMutationId})}}}emitShapeRows(t){const e=[...t.rows.values()];for(const s of t.callbacks)try{s(e)}catch{}}handleDataMessage(t){const{id:e}=t,s=e?this.subscriptions.getById(e):void 0;if(!s)return;const i=this.resolveDataPayload(t,s);if(s.serverBase=i,t.cursor!==void 0&&(s.serverCursor=t.cursor),t.epoch!==void 0&&(s.serverEpoch=t.epoch),this.persistQueryValue(s),F(s,s.serverCursor),x(s,s.optimisticLayers.length===0?i:A(i,s.optimisticLayers)),this.tabCoordinator?.isLeader()){const n=k.key(s.fn.__lunoraRef,s.args,s.shardKey);this.tabCoordinator.broadcastSubscriptionData(n,i)}}handleResumeMessage(t){const e=this.subscriptions.getById(t.id);e&&this.ackAndAdvanceCursor(e,t.cursor,t.epoch)}handleSettledMessage(t){const e=this.subscriptions.getById(t.id);if(e){this.ackAndAdvanceCursor(e,t.cursor,t.epoch),t.lastMutationId!==void 0&&(e.lastMutationId=t.lastMutationId);for(const s of e.checkpointCallbacks)s({checkpoint:e.serverCursor,mutationId:e.lastMutationId})}}ackAndAdvanceCursor(t,e,s){t.acked=!0,(e!==void 0&&e!==t.serverCursor||s!==void 0&&s!==t.serverEpoch)&&(e!==void 0&&(t.serverCursor=e),s!==void 0&&(t.serverEpoch=s),this.persistQueryValue(t),F(t,t.serverCursor)&&x(t,A(t.serverBase,t.optimisticLayers)))}resolveDataPayload(t,e){if("data"in t&&t.data!==void 0)return g(t.data);const s=g(t.delta);if(J(s)&&e.serverBase!==void 0){const i=X(e.serverBase,s);if(i!==void 0)return i}return s}dispatchWhisper(t,e){const s=this.whisperHandlers.get(m(e))?.get(t.topic);if(!s)return;const i=g(t.data);for(const n of s)try{n(i,t.from)}catch{}}notifyTokenExpired(){this.tokenExpiredListeners.emit()}handleCompleteMessage(t){const e=this.streams.get(t);if(e){e.handle.complete(),this.streams.delete(t);return}const s=this.subscriptions.getById(t);s&&this.subscriptions.remove(s)}unpersist(t){t&&this.persistence?.remove(t).catch(e=>{it(this.onPersistenceError,"remove",e,t)})}identityFingerprint(){if(this.authSubject!==void 0)return this.authSubject===null?null:`subj:${this.authSubject}`;const t=this.authToken;return t===null?null:this.hashToken(t)}hashToken(t){let e=2166136261,s=5381;for(let i=0;i<t.length;i+=1){const n=t.charCodeAt(i);e^=n,e=Math.imul(e,16777619),s=Math.imul(s,33)+n}return`${t.length.toString(36)}:${(e>>>0).toString(36)}:${(s>>>0).toString(36)}`}isSameCredentialUnderTokenHash(t){if(t===null||t.startsWith("subj:"))return!1;const e=this.authToken;return e===null?!1:this.hashToken(e)===t}rejectQueuedForIdentityChange(){const t=this.offlineQueue.drain();for(const e of t){this.queuedIdentities.delete(e.id??""),this.unpersist(e.id);const s=new Error("offline mutation discarded: auth identity changed before replay");s.code="OFFLINE_IDENTITY_CHANGED",e.reject(s),this.emitItemSettled(e,"rejected",s)}this.clearQueryCacheForIdentityChange()}restampQueuedIdentity(t,e){for(const[s,i]of this.queuedIdentities)i===t&&this.queuedIdentities.set(s,e)}clearQueryCacheForIdentityChange(){this.cacheFlushTimer!==void 0&&(clearTimeout(this.cacheFlushTimer),this.cacheFlushTimer=void 0),this.pendingCacheWrites.clear(),this.hydratedQueryCache.clear(),this.queryCache?.clear().catch(()=>{})}async flushOfflineQueue(t){const e=this.offlineQueue.drainConflict();for(const a of e){this.unpersist(a.id),this.queuedIdentities.delete(a.id??"");const u=new Error("offline mutation skipped: precondition failed before replay");u.code="OFFLINE_PRECONDITION_FAILED",this.emitItemSettled(a,"rejected",u)}const s=m(t),i=this.offlineQueue.drain(a=>m(a.shardKey)===s);if(i.length===0)return;const n=this.identityFingerprint(),r=[];for(const a of i)this.passesReplayIdentityGate(a,n)&&r.push(a);if(r.length===0)return;const o=this.encodableOrSettleTerminal(r);if(o.length===0)return;if(o.length===1){await this.replaySequential(o);return}const c=[];for(let a=0;a<o.length;a+=_){const u=o.slice(a,a+_),l=await this.replayBatched(u);if(c.push(...l.requeue),l.stop){c.push(...o.slice(a+_));break}}c.length>0&&this.offlineQueue.requeue(c)}encodableOrSettleTerminal(t){const e=[];for(const s of t)try{v(s.args,`args for '${s.functionPath}'`),e.push(s)}catch(i){this.settleReplayTerminal(s,i instanceof Error?i:new Error(String(i)))}return e}passesReplayIdentityGate(t,e){const s=t.id===void 0?void 0:this.queuedIdentities.get(t.id),i=s===void 0?t.identity:s;if(i!==void 0&&i!==e&&!this.isSameCredentialUnderTokenHash(i)){this.queuedIdentities.delete(t.id??""),this.unpersist(t.id);const n=new Error("offline mutation skipped: auth identity changed before replay");return n.code="OFFLINE_IDENTITY_CHANGED",t.reject(n),this.emitItemSettled(t,"rejected",n),!1}return this.queuedIdentities.delete(t.id??""),!0}settleReplaySuccess(t,e,s){this.unpersist(t.id),t.onCommit?.(s),t.resolve(e),this.emitItemSettled(t,"committed")}settleReplayTerminal(t,e){this.unpersist(t.id),t.reject(e),this.emitItemSettled(t,"rejected",e)}async replaySequential(t){for(let e=0;e<t.length;e+=1){const s=t[e];if(s)try{let i;const n=await this.rpc(s.functionPath,s.args,s.shardKey,{captureBookmark:!0,mutationId:s.id,onCommitCursor:r=>{i=r}});this.settleReplaySuccess(s,n,i)}catch(i){if(i.code!==void 0){this.settleReplayTerminal(s,i);continue}this.offlineQueue.requeue(t.slice(e));return}}}async replayBatched(t){if(!this.fetchImpl)return{requeue:t,stop:!0};let e;try{e=await this.fetchImpl(b(this.url,K),{body:JSON.stringify({calls:t.map((n,r)=>({args:v(n.args,`args for '${n.functionPath}'`),functionPath:n.functionPath,id:r,mutationId:n.id,shardKey:n.shardKey}))}),headers:this.rpcRequestHeaders({attachBookmark:!0}),method:"POST"})}catch{return{requeue:t,stop:!0}}const s=e.headers.get("x-d1-bookmark");s&&this.bookmark.set(s);let i;try{i=await e.json()}catch{return{requeue:t,stop:!0}}if(!i.results){if(i.error){const n=C(i.error);for(const r of t)this.settleReplayTerminal(r,n);return{requeue:[],stop:!1}}return{requeue:t,stop:!0}}return{requeue:this.settleReplayBatchSlots(t,i.results),stop:!1}}settleReplayBatchSlots(t,e){const s=new Map;for(const n of e)typeof n.id=="number"&&n.body!==void 0&&s.set(n.id,n.body);const i=[];for(const[n,r]of t.entries()){const o=s.get(n);o===void 0?i.push(r):"error"in o?Fe.has(o.error.code)?i.push(r):this.settleReplayTerminal(r,C(o.error)):this.settleReplaySuccess(r,g(o.result),o.commitCursor)}return i}}export{z as LunoraClient};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{c as o,d as s,o as t}from"./offline-queue-b-v6bWWd.mjs";export{o as OfflineQueue,s as nextId,t as reportPersistenceError};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const i=n=>{let e=-1;for(const r of n)r.seq>e&&(e=r.seq);return e},l=2,f=(n,e)=>{const r=e.filter(t=>t.role==="user"),c=i(e),o=new Set;return n.filter(t=>{for(const[s,a]of r.entries())if(!o.has(s)&&a.seq>t.maxDurableSeqAtSend&&a.content===t.content)return o.add(s),!1;return c-t.maxDurableSeqAtSend<2})};export{l as RETIRE_AFTER_DURABLE_SEQ_ADVANCE,i as maxSeq,f as reconcileOptimistic};
|
package/dist/packem_shared/{createServerClient-B7KqO8tv.mjs → createServerClient-DX7Dk2w2.mjs}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{LunoraClient as r}from"./LunoraClient-
|
|
1
|
+
import{LunoraClient as r}from"./LunoraClient-DRo2LNe9.mjs";const o=t=>{const e=new r({fetch:t.fetch,url:t.url});return t.token!==void 0&&e.setAuthToken(t.token),e};export{o as createServerClient};
|
|
@@ -1965,9 +1965,17 @@ declare class LunoraClient {
|
|
|
1965
1965
|
chunkSize?: number;
|
|
1966
1966
|
/**
|
|
1967
1967
|
* Stable id for this import run. Each chunk is sent under
|
|
1968
|
-
* `${importId}:${chunkIndex}` as its mutation id, so
|
|
1969
|
-
*
|
|
1970
|
-
*
|
|
1968
|
+
* `${importId}:${chunkIndex}` as its mutation id, so re-running an import
|
|
1969
|
+
* that uses the SAME `chunkSize` re-sends each chunk under its prior key
|
|
1970
|
+
* and the server dedupes it instead of inserting twice.
|
|
1971
|
+
*
|
|
1972
|
+
* CAVEAT — the key is POSITIONAL, not content-based: it pins on the chunk
|
|
1973
|
+
* INDEX, not on the rows inside it. Resume or retry with a DIFFERENT
|
|
1974
|
+
* `chunkSize` (or a changed row ordering) and index N now covers different
|
|
1975
|
+
* rows than the first run's index N; the server sees a duplicate key and
|
|
1976
|
+
* SILENTLY DROPS those rows. Keep `chunkSize` (and the row order) identical
|
|
1977
|
+
* across resumes of the same `importId`. Omit `importId` only for a
|
|
1978
|
+
* throwaway import where double-insertion is acceptable.
|
|
1971
1979
|
*/
|
|
1972
1980
|
importId?: string;
|
|
1973
1981
|
/**
|
|
@@ -1965,9 +1965,17 @@ declare class LunoraClient {
|
|
|
1965
1965
|
chunkSize?: number;
|
|
1966
1966
|
/**
|
|
1967
1967
|
* Stable id for this import run. Each chunk is sent under
|
|
1968
|
-
* `${importId}:${chunkIndex}` as its mutation id, so
|
|
1969
|
-
*
|
|
1970
|
-
*
|
|
1968
|
+
* `${importId}:${chunkIndex}` as its mutation id, so re-running an import
|
|
1969
|
+
* that uses the SAME `chunkSize` re-sends each chunk under its prior key
|
|
1970
|
+
* and the server dedupes it instead of inserting twice.
|
|
1971
|
+
*
|
|
1972
|
+
* CAVEAT — the key is POSITIONAL, not content-based: it pins on the chunk
|
|
1973
|
+
* INDEX, not on the rows inside it. Resume or retry with a DIFFERENT
|
|
1974
|
+
* `chunkSize` (or a changed row ordering) and index N now covers different
|
|
1975
|
+
* rows than the first run's index N; the server sees a duplicate key and
|
|
1976
|
+
* SILENTLY DROPS those rows. Keep `chunkSize` (and the row order) identical
|
|
1977
|
+
* across resumes of the same `importId`. Omit `importId` only for a
|
|
1978
|
+
* throwaway import where double-insertion is acceptable.
|
|
1971
1979
|
*/
|
|
1972
1980
|
importId?: string;
|
|
1973
1981
|
/**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
let h=0;const c=()=>{if(typeof crypto<"u"&&typeof crypto.randomUUID=="function")return crypto.randomUUID();h+=1;const n=typeof crypto<"u"&&typeof crypto.getRandomValues=="function"?Array.from(crypto.getRandomValues(new Uint8Array(8)),t=>t.toString(16).padStart(2,"0")).join(""):Math.random().toString(16).slice(2,12);return`id_${Date.now().toString(36)}_${h.toString(36)}_${n}`},a=(n,t)=>n!==void 0&&t!==n,d=c,r=(n,t,e,s)=>{if(n){n({error:e,mutationId:s,operation:t});return}console.warn(`[lunora] offline-queue persistence ${t} failed`,e)};class f{queueBeforeFirstConnect;maxItems;onPersistenceError;persistence;onEvict;onSizeChange;version;items=[];constructor(t={},e={}){this.maxItems=t.maxItems??1e3,this.queueBeforeFirstConnect=t.queueBeforeFirstConnect??!1,this.onPersistenceError=t.onPersistenceError,this.persistence=e.persistence,this.onEvict=e.onEvict,this.onSizeChange=e.onSizeChange,this.version=e.version}get size(){return this.items.length}enqueue(t){const e=t;for(e.id??=d(),this.items.push(e),this.persistence?.append({args:e.args,functionPath:e.functionPath,id:e.id,identity:e.identity,shardKey:e.shardKey,...this.version===void 0?{}:{version:this.version}}).catch(s=>{r(this.onPersistenceError,"append",s,e.id)});this.items.length>this.maxItems;){const s=this.items.shift();if(s){s.id&&this.persistence?.remove(s.id).catch(o=>{r(this.onPersistenceError,"remove",o,s.id)});const i=new Error("offline queue overflow");i.code="OFFLINE_QUEUE_OVERFLOW",s.reject(i),this.onEvict?.(s,i)}}this.notifySize()}async hydrate(){if(!this.persistence)return[];let t;try{t=await this.persistence.load()}catch(i){throw r(this.onPersistenceError,"load",i),i}const e=new Set,s=[];for(const i of t)if(!(this.items.some(o=>o.id===i.id)||s.some(o=>o.id===i.id))){if(a(this.version,i.version)){this.persistence.remove(i.id).catch(o=>{r(this.onPersistenceError,"remove",o,i.id)});continue}s.push({args:i.args,functionPath:i.functionPath,id:i.id,identity:i.identity,reject:()=>{},resolve:()=>{},shardKey:i.shardKey}),e.add(i.shardKey)}return this.items.unshift(...s),this.notifySize(),[...e]}drain(t){if(!t){const i=[...this.items];return this.items.length=0,this.notifySize(),i}const e=[],s=[];for(const i of this.items)(t(i)?e:s).push(i);return this.items.length=0,this.items.push(...s),this.notifySize(),e}requeue(t){t.length!==0&&(this.items.unshift(...t),this.notifySize())}drainConflict(){const t=[],e=[];for(const s of this.items)if(s.precondition!==void 0&&!s.precondition()){const i=new Error("offline mutation skipped: precondition failed before replay");i.code="OFFLINE_PRECONDITION_FAILED",s.reject(i),t.push(s)}else e.push(s);return t.length>0&&(this.items.length=0,this.items.push(...e),this.notifySize()),t}clear(){for(const t of this.items){const e=new Error("CLIENT_CLOSED");e.code="CLIENT_CLOSED",t.reject(e)}this.items.length=0,this.notifySize()}notifySize(){this.onSizeChange?.(this.items.length)}}export{a,f as c,d,r as o};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as FunctionReference, L as LunoraClient, A as ArgsOf, R as ReturnOf, P as Preloaded } from "./lunora-client.d-
|
|
1
|
+
import { F as FunctionReference, L as LunoraClient, A as ArgsOf, R as ReturnOf, P as Preloaded } from "./lunora-client.d-DLcz4GRz.mjs";
|
|
2
2
|
/**
|
|
3
3
|
* Run a query once on the server (during SSR) and capture its result in a
|
|
4
4
|
* serializable {@link Preloaded} token. Embed the token in the rendered HTML and
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as FunctionReference, L as LunoraClient, A as ArgsOf, R as ReturnOf, P as Preloaded } from "./lunora-client.d-
|
|
1
|
+
import { F as FunctionReference, L as LunoraClient, A as ArgsOf, R as ReturnOf, P as Preloaded } from "./lunora-client.d-DLcz4GRz.js";
|
|
2
2
|
/**
|
|
3
3
|
* Run a query once on the server (during SSR) and capture its result in a
|
|
4
4
|
* serializable {@link Preloaded} token. Embed the token in the rendered HTML and
|
package/dist/query/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as SubscriptionError, F as FunctionReference, A as ArgsOf, R as ReturnOf, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-
|
|
2
|
-
export type { b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-
|
|
1
|
+
import { S as SubscriptionError, F as FunctionReference, A as ArgsOf, R as ReturnOf, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-DLcz4GRz.mjs";
|
|
2
|
+
export type { b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-DLcz4GRz.mjs";
|
|
3
3
|
import '@lunora/runtime';
|
|
4
4
|
/**
|
|
5
5
|
* The sentinel a framework adapter resolves its reactive args to when it wants
|
package/dist/query/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as SubscriptionError, F as FunctionReference, A as ArgsOf, R as ReturnOf, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-
|
|
2
|
-
export type { b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-
|
|
1
|
+
import { S as SubscriptionError, F as FunctionReference, A as ArgsOf, R as ReturnOf, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-DLcz4GRz.js";
|
|
2
|
+
export type { b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-DLcz4GRz.js";
|
|
3
3
|
import '@lunora/runtime';
|
|
4
4
|
/**
|
|
5
5
|
* The sentinel a framework adapter resolves its reactive args to when it wants
|
package/dist/ssr/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-
|
|
2
|
-
export type { A as ArgsOf, F as FunctionReference, R as ReturnOf } from "../packem_shared/lunora-client.d-
|
|
3
|
-
export { p as preloadQuery, a as preloadedQueryResult } from "../packem_shared/preload.d-
|
|
1
|
+
import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-DLcz4GRz.mjs";
|
|
2
|
+
export type { A as ArgsOf, F as FunctionReference, R as ReturnOf } from "../packem_shared/lunora-client.d-DLcz4GRz.mjs";
|
|
3
|
+
export { p as preloadQuery, a as preloadedQueryResult } from "../packem_shared/preload.d-C1M_N5mE.mjs";
|
|
4
4
|
import '@lunora/runtime';
|
|
5
5
|
/**
|
|
6
6
|
* Structural shape of a better-auth `getSession` call's resolved value.
|
package/dist/ssr/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-
|
|
2
|
-
export type { A as ArgsOf, F as FunctionReference, R as ReturnOf } from "../packem_shared/lunora-client.d-
|
|
3
|
-
export { p as preloadQuery, a as preloadedQueryResult } from "../packem_shared/preload.d-
|
|
1
|
+
import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-DLcz4GRz.js";
|
|
2
|
+
export type { A as ArgsOf, F as FunctionReference, R as ReturnOf } from "../packem_shared/lunora-client.d-DLcz4GRz.js";
|
|
3
|
+
export { p as preloadQuery, a as preloadedQueryResult } from "../packem_shared/preload.d-hkFC0Uno.js";
|
|
4
4
|
import '@lunora/runtime';
|
|
5
5
|
/**
|
|
6
6
|
* Structural shape of a better-auth `getSession` call's resolved value.
|
package/dist/ssr/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getServerSession as o}from"../packem_shared/getServerSession-CGjgRBAE.mjs";import{deserializePreloaded as l,serializePreloaded as t}from"../packem_shared/deserializePreloaded-CHfOFpka.mjs";import{createServerClient as i}from"../packem_shared/createServerClient-
|
|
1
|
+
import{getServerSession as o}from"../packem_shared/getServerSession-CGjgRBAE.mjs";import{deserializePreloaded as l,serializePreloaded as t}from"../packem_shared/deserializePreloaded-CHfOFpka.mjs";import{createServerClient as i}from"../packem_shared/createServerClient-DX7Dk2w2.mjs";import{preloadQuery as s,preloadedQueryResult as f}from"../packem_shared/preloadQuery-DjwSjFwt.mjs";export{i as createServerClient,l as deserializePreloaded,o as getServerSession,s as preloadQuery,f as preloadedQueryResult,t as serializePreloaded};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/client",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.32",
|
|
4
4
|
"description": "Lunora browser SDK: WebSocket transport, optimistic updates, and an offline mutation queue",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"access": "public"
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
|
-
"@lunora/errors": "1.0.0-alpha.
|
|
69
|
+
"@lunora/errors": "1.0.0-alpha.9",
|
|
70
70
|
"@visulima/storage-client": "1.0.0"
|
|
71
71
|
},
|
|
72
72
|
"engines": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{c as s,u as o,s as t}from"./offline-queue-D73Dq95V.mjs";export{s as OfflineQueue,o as nextId,t as reportPersistenceError};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const c=(n,e)=>n!==void 0&&e!==n;let h=0;const a=()=>{if(typeof crypto<"u"&&typeof crypto.randomUUID=="function")return crypto.randomUUID();h+=1;const n=typeof crypto<"u"&&typeof crypto.getRandomValues=="function"?[...crypto.getRandomValues(new Uint8Array(8))].map(e=>e.toString(16).padStart(2,"0")).join(""):Math.random().toString(16).slice(2,12);return`m_${Date.now().toString(36)}_${h.toString(36)}_${n}`},r=(n,e,t,s)=>{if(n){n({error:t,mutationId:s,operation:e});return}console.warn(`[lunora] offline-queue persistence ${e} failed`,t)};class d{queueBeforeFirstConnect;maxItems;onPersistenceError;persistence;onEvict;onSizeChange;version;items=[];constructor(e={},t={}){this.maxItems=e.maxItems??1e3,this.queueBeforeFirstConnect=e.queueBeforeFirstConnect??!1,this.onPersistenceError=e.onPersistenceError,this.persistence=t.persistence,this.onEvict=t.onEvict,this.onSizeChange=t.onSizeChange,this.version=t.version}get size(){return this.items.length}enqueue(e){const t=e;for(t.id??=a(),this.items.push(t),this.persistence?.append({args:t.args,functionPath:t.functionPath,id:t.id,identity:t.identity,shardKey:t.shardKey,...this.version===void 0?{}:{version:this.version}}).catch(s=>{r(this.onPersistenceError,"append",s,t.id)});this.items.length>this.maxItems;){const s=this.items.shift();if(s){s.id&&this.persistence?.remove(s.id).catch(o=>{r(this.onPersistenceError,"remove",o,s.id)});const i=new Error("offline queue overflow");i.code="OFFLINE_QUEUE_OVERFLOW",s.reject(i),this.onEvict?.(s,i)}}this.notifySize()}async hydrate(){if(!this.persistence)return[];let e;try{e=await this.persistence.load()}catch(i){throw r(this.onPersistenceError,"load",i),i}const t=new Set,s=[];for(const i of e)if(!(this.items.some(o=>o.id===i.id)||s.some(o=>o.id===i.id))){if(c(this.version,i.version)){this.persistence.remove(i.id).catch(o=>{r(this.onPersistenceError,"remove",o,i.id)});continue}s.push({args:i.args,functionPath:i.functionPath,id:i.id,identity:i.identity,reject:()=>{},resolve:()=>{},shardKey:i.shardKey}),t.add(i.shardKey)}return this.items.unshift(...s),this.notifySize(),[...t]}drain(e){if(!e){const i=[...this.items];return this.items.length=0,this.notifySize(),i}const t=[],s=[];for(const i of this.items)(e(i)?t:s).push(i);return this.items.length=0,this.items.push(...s),this.notifySize(),t}requeue(e){e.length!==0&&(this.items.unshift(...e),this.notifySize())}drainConflict(){const e=[],t=[];for(const s of this.items)if(s.precondition!==void 0&&!s.precondition()){const i=new Error("offline mutation skipped: precondition failed before replay");i.code="OFFLINE_PRECONDITION_FAILED",s.reject(i),e.push(s)}else t.push(s);return e.length>0&&(this.items.length=0,this.items.push(...t),this.notifySize()),e}clear(){for(const e of this.items){const t=new Error("CLIENT_CLOSED");t.code="CLIENT_CLOSED",e.reject(t)}this.items.length=0,this.notifySize()}notifySize(){this.onSizeChange?.(this.items.length)}}export{d as c,c as d,r as s,a as u};
|