@lunora/client 1.0.0-alpha.232 → 1.0.0-alpha.234

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/auth/index.d.mts +1 -1
  2. package/dist/auth/index.d.ts +1 -1
  3. package/dist/index.d.mts +82 -3
  4. package/dist/index.d.ts +82 -3
  5. package/dist/index.mjs +1 -1
  6. package/dist/packem_shared/LunoraClient-D6Mn3qEX.mjs +1 -0
  7. package/dist/packem_shared/OfflineQueue-BLRESpAe.mjs +1 -0
  8. package/dist/packem_shared/TabCoordinator-DBuR7Dwv.mjs +1 -0
  9. package/dist/packem_shared/client-tuning-C10B2KCO.mjs +1 -0
  10. package/dist/packem_shared/connectLiveStream-CXD8k-Sp.mjs +1 -0
  11. package/dist/packem_shared/{createAsyncStorageQueryCache-f5023fdB.mjs → createAsyncStorageQueryCache-COqH5_SV.mjs} +1 -1
  12. package/dist/packem_shared/{createInMemoryPersistence-Cz2W6XVj.mjs → createInMemoryPersistence-BfgXApi_.mjs} +1 -1
  13. package/dist/packem_shared/{createInMemoryQueryCache-D2uNHLfM.mjs → createInMemoryQueryCache-B5wX-gTy.mjs} +1 -1
  14. package/dist/packem_shared/{createServerClient-BqCdfoE1.mjs → createServerClient-B0TsbJkS.mjs} +1 -1
  15. package/dist/packem_shared/httpStream-DceAMeMf.mjs +9 -0
  16. package/dist/packem_shared/idb-utility-BS7xvou1.mjs +1 -0
  17. package/dist/packem_shared/live-stream-Dil9byXF.mjs +10 -0
  18. package/dist/packem_shared/{liveTopicSubscription-Bs-ULKfs.mjs → liveTopicSubscription-gOmRbuhH.mjs} +1 -1
  19. package/dist/packem_shared/{lunora-client.d-DpmxnYmL.d.ts → lunora-client.d-CZ9TlyaL.d.ts} +207 -19
  20. package/dist/packem_shared/{lunora-client.d-dOEEoF4x.d.mts → lunora-client.d-DZ9gzk9p.d.mts} +207 -19
  21. package/dist/packem_shared/offline-queue-Dt_um8sR.mjs +1 -0
  22. package/dist/packem_shared/{preload.d-XVLTUaah.d.mts → preload.d-BOpEnFP8.d.mts} +1 -1
  23. package/dist/packem_shared/{preload.d-BkXsKMmU.d.ts → preload.d-CXUIU6pE.d.ts} +1 -1
  24. package/dist/packem_shared/stream-idle-C7CsIT_m.mjs +1 -0
  25. package/dist/packem_shared/{wire-errors-Bw04a4ZQ.mjs → wire-errors-BTLdHNoh.mjs} +1 -1
  26. package/dist/query/index.d.mts +2 -2
  27. package/dist/query/index.d.ts +2 -2
  28. package/dist/service.mjs +1 -1
  29. package/dist/ssr/index.d.mts +2 -2
  30. package/dist/ssr/index.d.ts +2 -2
  31. package/dist/ssr/index.mjs +1 -1
  32. package/package.json +1 -1
  33. package/dist/packem_shared/LunoraClient-D6MyuSWy.mjs +0 -1
  34. package/dist/packem_shared/OfflineQueue-BWamzR6p.mjs +0 -1
  35. package/dist/packem_shared/TabCoordinator-CXD7vulJ.mjs +0 -1
  36. package/dist/packem_shared/connectLiveStream-DCgklEjI.mjs +0 -1
  37. package/dist/packem_shared/httpStream-DaqP70Ne.mjs +0 -9
  38. package/dist/packem_shared/idb-utility-C8WS390w.mjs +0 -1
  39. package/dist/packem_shared/live-stream-ct8j7T75.mjs +0 -10
  40. package/dist/packem_shared/offline-queue-D_fr-uQ3.mjs +0 -1
@@ -1,6 +1,18 @@
1
1
  import { LunoraErrorCodeInput, LunoraErrorCode } from '@lunora/errors';
2
2
  import { F as FunctionReference, A as ArgsOf, R as ReturnOf } from "./function-reference.d-Br_hsKje.mjs";
3
3
  import { CronJobInfo, VectorIndexSummary, VectorQueryMatch, PipelineLogQuery, PipelineLogPage, KvNamespaceSummary, KvKeyListResult, KvValueResult, AuthUser, AuthPage, AuthImpersonation, AuthCapabilities, AuthConfigInfo, AuthSession } from '@lunora/runtime';
4
+ /**
5
+ * The `onlineOnly` option a call to the function reference `F` may take. A
6
+ * function with a `v.sensitive` argument is emitted as `… & { readonly sensitive:
7
+ * true }`, and is always online-only: its arguments never reach the offline queue,
8
+ * the outbox or a persistence adapter. For it the option may be omitted or `true`;
9
+ * `false` is a type error. Every other reference is unchanged.
10
+ */
11
+ type OnlineOnlyOption<F> = F extends {
12
+ readonly sensitive: true;
13
+ } ? {
14
+ onlineOnly?: true;
15
+ } : unknown;
4
16
  /**
5
17
  * Typed reference to an HTTP-SSE stream route (`httpRoute.<verb>(path).stream()`)
6
18
  * emitted by `@lunora/codegen` as `httpStreams.<namespace>.<name>`.
@@ -530,6 +542,15 @@ interface LunoraClientOptions {
530
542
  */
531
543
  queryCache?: QueryCacheAdapter | false;
532
544
  reconnect?: ReconnectOptions;
545
+ /**
546
+ * Deadline (ms) for one HTTP RPC round trip (`query`, `mutation`, a replayed
547
+ * write), covering the response body as well as the connection. A request
548
+ * that stalls past it fails with a retryable `TransportError` — and a durable
549
+ * write is re-queued under the same `mutationId` — instead of freezing every
550
+ * write queued behind it on the shard. `action` is exempt: it may legitimately
551
+ * run for longer. Defaults to 30000 (30s); set to `0` (or negative) to disable.
552
+ */
553
+ rpcTimeoutMs?: number;
533
554
  url: string;
534
555
  WebSocket?: typeof WebSocket;
535
556
  /**
@@ -1124,6 +1145,8 @@ interface FunctionArgumentDescriptor {
1124
1145
  name: string;
1125
1146
  /** True when the arg is wrapped in `v.optional(...)`. */
1126
1147
  optional: boolean;
1148
+ /** True when the arg is marked `v.sensitive` — a secret the caller supplies, never queued offline. */
1149
+ sensitive?: true;
1127
1150
  /** Target table for an `id` arg (`v.id("table")`). */
1128
1151
  table?: string;
1129
1152
  }
@@ -1355,6 +1378,14 @@ interface SubscriptionState {
1355
1378
  */
1356
1379
  serverEpoch?: string;
1357
1380
  readonly shardKey?: string;
1381
+ /**
1382
+ * Whether a poll or the leader tab has delivered a value for this subscription on the
1383
+ * CURRENT connection. A polling connection and a follower tab see no server `ack`, so this
1384
+ * is their only evidence of an answer, and `serverBase` cannot stand in for it: a hydrated
1385
+ * cache sets that before anything has arrived. A WebSocket never sets it, `acked` is its
1386
+ * evidence.
1387
+ */
1388
+ valueReceived: boolean;
1358
1389
  /**
1359
1390
  * The wire-encoded form of `args`, computed once at `subscribe` time (so an
1360
1391
  * unsupported value fails loud at the call site, not inside a reconnect's
@@ -1619,6 +1650,22 @@ interface ClientDebugSnapshot {
1619
1650
  shards: ClientDebugShard[];
1620
1651
  subscriptions: ClientDebugSubscription[];
1621
1652
  }
1653
+ /**
1654
+ * Whether the client is actually caught up, which `connectionStatus()` alone cannot
1655
+ * say: it reads `"connected"` as soon as any socket is open, though a subscription
1656
+ * on it may not have been acknowledged yet (it has no data) and writes may still be
1657
+ * waiting in the offline queue. See {@link LunoraClient.syncStatus}.
1658
+ */
1659
+ interface SyncStatus {
1660
+ /** The aggregate socket status, as {@link LunoraClient.connectionStatus} reports it. */
1661
+ connection: ConnectionStatus;
1662
+ /** Live queries and shapes the server has not answered yet on the current connection. */
1663
+ pendingSubscriptions: number;
1664
+ /** Writes queued or being replayed from the built-in offline queue (not the `@lunora/db` outbox). */
1665
+ pendingWrites: number;
1666
+ /** `true` only on a live connection with every subscription answered and no write queued. */
1667
+ synced: boolean;
1668
+ }
1622
1669
  /**
1623
1670
  * Terminal verdict for a mutation that passed through the offline queue,
1624
1671
  * delivered to {@link LunoraClient.onMutationSettled}.
@@ -1670,6 +1717,13 @@ interface MutationSettledEvent {
1670
1717
  interface ActionCallOptions {
1671
1718
  /** Route the call to a specific shard. */
1672
1719
  shardKey?: string;
1720
+ /**
1721
+ * Abort the call. The request is cancelled and the promise rejects with the
1722
+ * signal's reason (an `AbortError` by default). The server may already have
1723
+ * started — or finished — the action, which is not transactional, so an abort
1724
+ * releases the caller; it does not undo the work.
1725
+ */
1726
+ signal?: AbortSignal;
1673
1727
  }
1674
1728
  /**
1675
1729
  * Per-call options for {@link LunoraClient.mutation} — the optimistic-update
@@ -1686,6 +1740,23 @@ interface MutationCallOptions<TCurrent = unknown, TValue = unknown, TArgs = unkn
1686
1740
  * each then gets a fresh key.
1687
1741
  */
1688
1742
  mutationId?: string;
1743
+ /**
1744
+ * Never queue, persist or replay this write. When the shard's connection is
1745
+ * down or reconnecting — the states in which a normal write is queued — the
1746
+ * call rejects at once with `OFFLINE_NOT_QUEUED`, and its args never reach the
1747
+ * offline queue, the persistence adapter or the outbox. Use it for a write whose
1748
+ * arguments must not sit on disk: a credential a person typed in, a one-time
1749
+ * token. A function with a `v.sensitive` argument is always online-only, whatever
1750
+ * this option says: the client forces it on, and `false` is refused.
1751
+ *
1752
+ * Ordering: an online-only call neither waits for a queue flush nor queues
1753
+ * behind writes already queued for its shard. When it is sent it can overtake
1754
+ * them, so it may land on the server before an older queued write to the same
1755
+ * document. Optimistic layers are in-memory and are not applied to a refused call.
1756
+ *
1757
+ * Omit for normal calls, which queue as usual.
1758
+ */
1759
+ onlineOnly?: boolean;
1689
1760
  /**
1690
1761
  * Single-query shortcut: the transform is layered onto the subscription
1691
1762
  * registered under **this write's own** `(functionPath, args, shardKey)`, and
@@ -1753,6 +1824,14 @@ interface MutationCallOptions<TCurrent = unknown, TValue = unknown, TArgs = unkn
1753
1824
  */
1754
1825
  replayCredential?: ReplayCredential;
1755
1826
  shardKey?: string;
1827
+ /**
1828
+ * Stop waiting for the mutation. The promise rejects with the signal's reason
1829
+ * (an `AbortError` by default), and nothing is sent when the signal is already
1830
+ * aborted. A write already on the wire or in the offline queue is NOT
1831
+ * retracted: it still commits or replays on its own, and its optimistic patch
1832
+ * is settled by that outcome — an abort releases the caller, not the write.
1833
+ */
1834
+ signal?: AbortSignal;
1756
1835
  }
1757
1836
  declare const replayCredentialBrand: unique symbol;
1758
1837
  /**
@@ -1811,6 +1890,8 @@ declare class LunoraClient {
1811
1890
  private readonly connectTimeoutMs;
1812
1891
  /** Keepalive cadence (ms); `0` disables the heartbeat. See {@link LunoraClientOptions.heartbeatIntervalMs}. */
1813
1892
  private readonly heartbeatIntervalMs;
1893
+ /** Deadline (ms) for one HTTP RPC round trip; `0` disables it. See {@link LunoraClientOptions.rpcTimeoutMs}. */
1894
+ private readonly rpcTimeoutMs;
1814
1895
  /** The socket-lifecycle inputs, built once after the constructor assigns them (none is reassigned later). */
1815
1896
  private readonly managedSocketOptions;
1816
1897
  /** Failed-open run that engages the HTTP polling fallback; `0` disables it. */
@@ -1880,10 +1961,13 @@ declare class LunoraClient {
1880
1961
  private readonly clientWatermarks;
1881
1962
  /** Monotonic per-client mutation counter backing the server `__client_watermark`. */
1882
1963
  private outboxMutationCounter;
1883
- private readonly onPersistenceError;
1964
+ /** Orders offline-queued writes by when they were issued; see {@link QueuedMutation.issueSeq}. */
1965
+ private mutationIssueCounter;
1884
1966
  private readonly persistence;
1885
1967
  /** App/schema version stamped on persisted writes + cached reads; mismatches are purged. */
1886
1968
  private readonly persistenceVersion;
1969
+ /** Removes the page-hide flush listeners on close (see `installPageHideFlush`). */
1970
+ private releasePageHideFlush;
1887
1971
  /** Releases the multi-tab outbox-leader Web Lock on close (see `hydrateAsOutboxLeader`). */
1888
1972
  private outboxLeaderRelease;
1889
1973
  /** Durable read cache (Pillar 2); `undefined` when `queryCache` is omitted or `false`. */
@@ -2096,6 +2180,9 @@ declare class LunoraClient {
2096
2180
  private readonly mutationSettledListeners;
2097
2181
  /** Subscribers to the offline-queue pending-count (see `onPendingChange`). */
2098
2182
  private readonly pendingChangeListeners;
2183
+ private readonly syncStatusListeners;
2184
+ /** The last value `syncStatusListeners` was told, to emit only on a real change. */
2185
+ private lastSyncStatus;
2099
2186
  /**
2100
2187
  * Whisper-topic handlers, keyed by `connectionKey(shardKey)` → topic → set
2101
2188
  * of callbacks. Membership doubles as the resubscribe set replayed on every
@@ -2173,6 +2260,8 @@ declare class LunoraClient {
2173
2260
  * entry per document it ever wrote.
2174
2261
  */
2175
2262
  private readonly replayRetryState;
2263
+ /** Failed replay attempts collected so far, per ambiguous-send write id (see `spendsLastReplayAttempt`); cleared when the write settles. */
2264
+ private readonly replayAttempts;
2176
2265
  /** Pending rate-limit retry flushes, keyed by {@link connectionKey}, so `close()` can cancel them. */
2177
2266
  private readonly replayRetryTimers;
2178
2267
  private readonly shapeSubscriptions;
@@ -2634,6 +2723,29 @@ declare class LunoraClient {
2634
2723
  * unsubscribe function.
2635
2724
  */
2636
2725
  onConnectionStatus(listener: (status: ConnectionStatus) => void): Unsubscribe;
2726
+ /**
2727
+ * Whether the client is caught up: a live connection, every subscription
2728
+ * answered by the server, and no write waiting in the offline queue. Use this
2729
+ * rather than `connectionStatus() === "connected"` for a "synced" indicator —
2730
+ * that reads `"connected"` the moment a socket opens, while subscriptions still
2731
+ * have no data and queued writes are still waiting to go out.
2732
+ *
2733
+ * Over the HTTP polling fallback (judged per shard, so one polling shard does
2734
+ * not wait on an ack while another holds an open socket), and on a cross-tab
2735
+ * follower (neither sees server acknowledgements), a subscription counts as
2736
+ * answered once the current connection has delivered a value for it; a
2737
+ * hydrated cache does not.
2738
+ * A write counts as pending from the moment it is queued until the server
2739
+ * settles it, including while its replay request is on the wire.
2740
+ */
2741
+ syncStatus(): SyncStatus;
2742
+ /**
2743
+ * Subscribe to {@link syncStatus} changes. Invokes `listener` immediately with
2744
+ * the current value, then whenever the connection status, the number of
2745
+ * unanswered subscriptions or the number of unsettled writes (queued, or
2746
+ * being replayed) changes. Returns an unsubscribe function.
2747
+ */
2748
+ onSyncStatus(listener: (status: SyncStatus) => void): Unsubscribe;
2637
2749
  /**
2638
2750
  * Number of offline writes waiting in the built-in queue to be sent — the
2639
2751
  * depth for a "N changes waiting to sync" indicator. Counts writes that are
@@ -2743,7 +2855,9 @@ declare class LunoraClient {
2743
2855
  * (enabled) render of a live query behind hydration, so the user sees
2744
2856
  * cached data instead of an undefined flash before the socket round-trip.
2745
2857
  */
2746
- whenReady(): Promise<void>;
2858
+ whenReady(options?: {
2859
+ signal?: AbortSignal;
2860
+ }): Promise<void>;
2747
2861
  /**
2748
2862
  * Synchronously reports whether {@link whenReady} has already resolved (the
2749
2863
  * durable read cache is loaded, or none is configured). Framework adapters
@@ -2792,6 +2906,7 @@ declare class LunoraClient {
2792
2906
  };
2793
2907
  query<F extends FunctionReference>(function_: F, args: ArgsOf<F>, options?: {
2794
2908
  shardKey?: string;
2909
+ signal?: AbortSignal;
2795
2910
  }): Promise<ReturnOf<F>>;
2796
2911
  /**
2797
2912
  * Batch several independent calls into ONE round trip (plan 088). Each call is
@@ -2806,6 +2921,12 @@ declare class LunoraClient {
2806
2921
  * No promise pipelining and no capability passing — a call's args cannot
2807
2922
  * reference another call's result (see plan 088 §fence; capabilities are
2808
2923
  * incompatible with DO hibernation).
2924
+ *
2925
+ * The whole exchange, response body included, is bounded by
2926
+ * {@link LunoraClientOptions.rpcTimeoutMs}, rejecting with a retryable
2927
+ * {@link TransportError}. A function's kind is a type-level phantom with no
2928
+ * runtime marker, so unlike {@link action} a batched call cannot be exempted:
2929
+ * call a long-running action through `action()` instead.
2809
2930
  */
2810
2931
  batch(calls: ReadonlyArray<{
2811
2932
  args?: Record<string, unknown>;
@@ -2820,7 +2941,8 @@ declare class LunoraClient {
2820
2941
  * (`wasEverConnected`), so the registry / resubscribe handshake has run.
2821
2942
  * Mutations issued before the very first WS connect to a shard fail fast.
2822
2943
  * Opt into queueing-before-first-connect via
2823
- * `OfflineQueueOptions.queueBeforeFirstConnect`.
2944
+ * `OfflineQueueOptions.queueBeforeFirstConnect`. Pass `onlineOnly: true` to
2945
+ * refuse a write instead of queueing it — see {@link MutationCallOptions.onlineOnly}.
2824
2946
  *
2825
2947
  * **Return-value caveat — the queued paths do not carry the server's result.**
2826
2948
  * The declared `Promise<ReturnOf<F>>` only holds when the write goes straight
@@ -2838,7 +2960,7 @@ declare class LunoraClient {
2838
2960
  * on a mutation's return value in an offline-capable app —
2839
2961
  * {@link LunoraClient.importRows} documents the same caveat for its counts.
2840
2962
  */
2841
- mutation<F extends FunctionReference>(function_: F, args: ArgsOf<F>, options?: MutationCallOptions<unknown, unknown, ArgsOf<F>>): Promise<ReturnOf<F>>;
2963
+ mutation<F extends FunctionReference>(function_: F, args: ArgsOf<F>, options?: MutationCallOptions<unknown, unknown, ArgsOf<F>> & OnlineOnlyOption<F>): Promise<ReturnOf<F>>;
2842
2964
  /**
2843
2965
  * Whether a {@link mutation} on `shardKey` would be queued (offline queue or
2844
2966
  * durable outbox) rather than fail when the network is down. `false` before
@@ -3547,6 +3669,7 @@ declare class LunoraClient {
3547
3669
  onCheckpoint?: (watermark: SyncWatermark) => void;
3548
3670
  onError?: SubscriptionErrorCallback;
3549
3671
  shardKey?: string;
3672
+ signal?: AbortSignal;
3550
3673
  }): Unsubscribe;
3551
3674
  /**
3552
3675
  * Subscribe to a declarative **shape** — server-side partial replication
@@ -3722,7 +3845,7 @@ declare class LunoraClient {
3722
3845
  * stamp elsewhere in this file) — moved verbatim, not reflowed.
3723
3846
  */
3724
3847
  private createTabCoordinator;
3725
- /** The body of {@link batch}, optionally abortable (the polling fallback's timeout). */
3848
+ /** The body of {@link batch}, abortable by the caller's deadline (`batch`'s own, or the polling fallback's timeout). */
3726
3849
  private sendBatch;
3727
3850
  /**
3728
3851
  * The body of {@link mutation}, also saying whether the write committed. `committed` is
@@ -3730,6 +3853,26 @@ declare class LunoraClient {
3730
3853
  * with no server result.
3731
3854
  */
3732
3855
  private runMutation;
3856
+ /**
3857
+ * Refuses an `onlineOnly` write whose shard's connection is down or reconnecting,
3858
+ * the states in which a normal write is queued. Reads the gate synchronously, so
3859
+ * the refusal is immediate. Called again after the optimistic updates have been
3860
+ * applied, which is user code and may have dropped the shard: `optimisticRollbacks`
3861
+ * unwinds those layers before the refusal.
3862
+ */
3863
+ private refuseOnlineOnlyWhenDown;
3864
+ /**
3865
+ * Whether this tab's own socket is open for the shard. A follower tab has no socket
3866
+ * of its own: the status it reads is the leader's, which carried no part of the
3867
+ * request that just failed, so it never counts as open.
3868
+ */
3869
+ private ownSocketOpen;
3870
+ /**
3871
+ * Whether a write on `shardKey` would be queued if it failed right now, and
3872
+ * which gate would queue it. A follower tab has no `ShardConnection` of its own —
3873
+ * `connectionGateState` derives the same triple from the mirrored leader status.
3874
+ */
3875
+ private writeQueueGate;
3733
3876
  /**
3734
3877
  * Unwind a direct write's optimistic layers after its RPC threw — or keep
3735
3878
  * them, when it threw only because a COMMITTED result did not decode: the
@@ -3893,6 +4036,14 @@ declare class LunoraClient {
3893
4036
  private persistQueryValue;
3894
4037
  /** Drain {@link pendingCacheWrites} to the durable store. */
3895
4038
  private flushQueryCacheWrites;
4039
+ /**
4040
+ * Flush what is buffered for durable storage when the page is hidden or going
4041
+ * away: writes whose append was rejected get another try, and the debounced
4042
+ * read-cache writes (which would otherwise wait out their timer on a page
4043
+ * that never gets to run it) are written out. Browser lifecycle events only —
4044
+ * a runtime without them (SSR, workers, React Native) installs nothing.
4045
+ */
4046
+ private installPageHideFlush;
3896
4047
  /** Derive the aggregate status from the per-shard socket states. */
3897
4048
  private computeStatus;
3898
4049
  /**
@@ -3957,6 +4108,8 @@ declare class LunoraClient {
3957
4108
  * (even a refusal) is the proof. `false` only when `fetch` itself rejects.
3958
4109
  */
3959
4110
  private probeOrigin;
4111
+ /** Recompute {@link syncStatus} and notify its listeners if any field changed. */
4112
+ private emitSyncStatus;
3960
4113
  /** Recompute the aggregate status and notify listeners if it changed. */
3961
4114
  private emitConnectionStatus;
3962
4115
  /**
@@ -4118,7 +4271,11 @@ declare class LunoraClient {
4118
4271
  */
4119
4272
  private cancelStream;
4120
4273
  private handleDisconnect;
4121
- /** Mark every subscription bound to `shardKey` as needing a fresh ack. */
4274
+ /**
4275
+ * Mark every subscription and shape bound to `shardKey` as needing a fresh answer from the server.
4276
+ * `socketOpened` also forgets the values a poll delivered: the socket replaces that connection,
4277
+ * whereas a socket that merely failed to open (or dropped) leaves polling, and its answers, in place.
4278
+ */
4122
4279
  private markShardPendingAck;
4123
4280
  /**
4124
4281
  * Re-send `state`'s `subscribe` frame, but only once fewer than
@@ -4135,13 +4292,16 @@ declare class LunoraClient {
4135
4292
  * Cannot wedge: a queued subscription whose frame does not actually go out
4136
4293
  * (socket closed, already acked, unsubscribed while queued) takes no slot,
4137
4294
  * every sent frame is released by the first server frame carrying its id
4138
- * (see {@link handleServerMessage}) or by its own watchdog, and a disconnect
4295
+ * (see {@link handleServerMessage}) or by its watchdog, and a disconnect
4139
4296
  * drops the queue wholesale — the next `open` re-queues every subscription
4140
4297
  * on the shard, because `markShardPendingAck` un-acked them all.
4141
4298
  */
4142
4299
  private drainResubscribeQueue;
4143
- /** Free the in-flight slot `id` holds on `conn` (if any) and let the next queued subscribe go out. */
4144
- private releaseResubscribeSlot;
4300
+ /**
4301
+ * Stand down `id`'s watchdog on `conn` — its `subscribe` frame was answered or the socket went
4302
+ * away — and, if it held a pacing slot, free it so the next queued subscribe goes out.
4303
+ */
4304
+ private settleSubscribeWatchdog;
4145
4305
  /**
4146
4306
  * Abandon this connection's paced resubscribe: clear every watchdog and
4147
4307
  * forget both the in-flight and the waiting entries. Called wherever the
@@ -4151,9 +4311,20 @@ declare class LunoraClient {
4151
4311
  private clearResubscribeQueue;
4152
4312
  /** Send `state`'s `subscribe` frame when the shard's socket can carry it; `true` when a frame actually went out. */
4153
4313
  private sendSubscribeIfOpen;
4314
+ /**
4315
+ * Watch `state`'s `subscribe` frame: if no frame bearing its id arrives within
4316
+ * {@link RESUBSCRIBE_ACK_TIMEOUT_MS}, free the pacing slot it holds (if any) and
4317
+ * re-send the frame once. A server that drops the frame without replying (a
4318
+ * shard still waking, a swallowed message) would otherwise leave the
4319
+ * subscription un-acked on a perfectly live socket until the next reconnect.
4320
+ * One retry, not a loop: a query that is merely slow must not be re-run repeatedly.
4321
+ */
4322
+ private armUnackedWatchdog;
4154
4323
  private sendShapeSubscribeIfOpen;
4155
4324
  private handleServerMessage;
4156
4325
  private handleErrorMessage;
4326
+ /** Count a query the server refused as answered, by the evidence {@link syncStatus} asks of it, emitting only on a change. */
4327
+ private markQueryRejected;
4157
4328
  private handlePokeEnd;
4158
4329
  /**
4159
4330
  * Commit one shape's slice of a poke. The decision and the state change live in
@@ -4198,8 +4369,10 @@ declare class LunoraClient {
4198
4369
  /**
4199
4370
  * Mark `state` acked and, when the frame carries a newer cursor/epoch than
4200
4371
  * the cached position, advance the resume watermark and re-persist. Shared by
4201
- * the `resume` and `settled` frame handlers — both acknowledge "nothing the
4202
- * client must re-render changed, but the resume position may have moved".
4372
+ * the `ack`, `resume` and `settled` frame handlers — each acknowledges the
4373
+ * subscription ("nothing the client must re-render changed, but the resume
4374
+ * position may have moved"; an `ack` carries no position at all). The sync
4375
+ * status is only recomputed when this is the acknowledgement that changes it.
4203
4376
  */
4204
4377
  private ackAndAdvanceCursor;
4205
4378
  /**
@@ -4701,13 +4874,12 @@ declare class LunoraClient {
4701
4874
  * Consume this shard's retry delay and re-flush it once the delay has
4702
4875
  * elapsed.
4703
4876
  *
4704
- * Two things record a delay for it to consume: a failure the server or an
4705
- * edge ANSWERED (see {@link replayRetryDelayMs}) and a flush that HELD every
4706
- * entry it drained (see {@link LunoraClient.noteHeldRetryDelay}). Both happen
4707
- * over a socket that stays open, so without this the writes sit queued
4708
- * indefinitely; a `fetch` that never landed records nothing, because the
4709
- * reconnect that follows flushes the queue anyway. One pending timer per
4710
- * shard; a second delay replaces it rather than stacking flushes.
4877
+ * Two things record a delay for it to consume: a transient failure (a server
4878
+ * or edge answer, or a `fetch` that rejected; see {@link replayRetryDelayMs})
4879
+ * and a flush that HELD every entry it drained (see
4880
+ * {@link LunoraClient.noteHeldRetryDelay}). Both happen over a socket that
4881
+ * stays open, so without this the writes sit queued indefinitely. One pending
4882
+ * timer per shard; a second delay replaces it rather than stacking flushes.
4711
4883
  *
4712
4884
  * Nothing left to retry on this key (drained, closed, or no delay) drops its
4713
4885
  * backoff state, which is both the reset after progress and what bounds the
@@ -4839,6 +5011,22 @@ declare class LunoraClient {
4839
5011
  * rejected with the decode error and the settled event carries it.
4840
5012
  */
4841
5013
  private settleReplayUndecodable;
5014
+ /**
5015
+ * Count a failed replay attempt against `item` and report whether it was the
5016
+ * last attempt the write gets.
5017
+ *
5018
+ * Only a write queued after an ambiguous direct send is capped: its caller is
5019
+ * still waiting, so every transient failure of it except a rate limit or a
5020
+ * refused credential (a transport error, a timeout, `SHARD_UNAVAILABLE`, ...)
5021
+ * counts against {@link MAX_AMBIGUOUS_SEND_ATTEMPTS}. Any other write is never
5022
+ * capped here: a write the shard fails deterministically arrives with a coded
5023
+ * verdict (the handler's own code, `RPC_FAILED`, `BATCH_ENTRY_FAILED`) that
5024
+ * {@link isTransientReplayFailure} settles terminally on the first attempt, and
5025
+ * a transient failure says nothing about the write itself.
5026
+ */
5027
+ private spendsLastReplayAttempt;
5028
+ /** Settle, terminally, the ambiguous-send writes among `items` that `error` was the last attempt for; the rest stay queued. */
5029
+ private keepUnexhaustedAmbiguousWrites;
4842
5030
  /** Settle a write the server reached a coded verdict on: replaying would re-trigger the same failure (a poison-message loop), so drop it. */
4843
5031
  private settleReplayTerminal;
4844
5032
  /**
@@ -4913,4 +5101,4 @@ declare class LunoraClient {
4913
5101
  */
4914
5102
  private settleReplayBatchSlots;
4915
5103
  }
4916
- export { SchedulerStatus as $, ActionCallOptions as A, BookmarkStorage as B, ConnectionStatus as C, DEFAULT_MAX_BUFFER as D, OutboxMutation as E, FunctionArgumentDescriptor as F, GlobalFacetResult as G, HttpStreamRef as H, OutboxSink as I, PersistedMutation as J, ReplayCredential as K, LunoraClient as L, MutationCallOptions as M, ReplayIdentityVerdict as N, OfflineQueueOptions as O, Preloaded as P, QueryCacheAdapter as Q, ReconnectOptions as R, SubscriptionError as S, RoomRef as T, User as U, RowOp as V, RpcEnvelope as W, RpcResponseBody as X, ScheduleRecord as Y, ScheduleRetryPolicy as Z, SchedulerPoolStatus as _, Unsubscribe as a, ServerMessage as a0, ServerPokeEndMessage as a1, ServerPokePartMessage as a2, ServerPokeStartMessage as a3, ShardTrafficEntry as a4, ShardTrafficResult as a5, StorageListPage as a6, StorageObject as a7, StoredQuery as a8, StreamHandle as a9, SubscriptionCallback as aa, SubscriptionRegistry as ab, SubscriptionState as ac, SyncWatermark as ad, WorkflowInstanceAction as ae, WorkflowInstanceDetail as af, WorkflowInstancePage as ag, WorkflowInstanceStatus as ah, WorkflowInstanceSummary as ai, WorkflowStepDetail as aj, WsTokenProvider as ak, createClientQuery as al, createLocalStore as am, createStream as an, SubscriptionErrorCallback as b, PersistenceAdapter as c, HttpStreamArgsOf as d, HttpStreamChunkOf as e, StreamIterable as f, BatchSlot as g, CachedQuery as h, ClientDebugShard as i, ClientDebugSnapshot as j, ClientDebugSubscription as k, ClientMessage as l, ClientQueryRef as m, ClientShapeSubscribeMessage as n, ClientShapeUnsubscribeMessage as o, FunctionDescriptor as p, GlobalFacetValue as q, GlobalFilterClause as r, GlobalTableInfo as s, GlobalTablePage as t, HttpStreamCallArgs as u, LunoraClientError as v, LunoraClientOptions as w, MutationSettledEvent as x, OptimisticLocalStore as y, OptimisticUpdate as z };
5104
+ export { SchedulerPoolStatus as $, ActionCallOptions as A, BookmarkStorage as B, ConnectionStatus as C, DEFAULT_MAX_BUFFER as D, OptimisticUpdate as E, FunctionArgumentDescriptor as F, GlobalFacetResult as G, HttpStreamRef as H, OutboxMutation as I, OutboxSink as J, PersistedMutation as K, LunoraClient as L, MutationCallOptions as M, ReplayCredential as N, OfflineQueueOptions as O, Preloaded as P, QueryCacheAdapter as Q, ReconnectOptions as R, SubscriptionError as S, ReplayIdentityVerdict as T, User as U, RoomRef as V, RowOp as W, RpcEnvelope as X, RpcResponseBody as Y, ScheduleRecord as Z, ScheduleRetryPolicy as _, Unsubscribe as a, SchedulerStatus as a0, ServerMessage as a1, ServerPokeEndMessage as a2, ServerPokePartMessage as a3, ServerPokeStartMessage as a4, ShardTrafficEntry as a5, ShardTrafficResult as a6, StorageListPage as a7, StorageObject as a8, StoredQuery as a9, StreamHandle as aa, SubscriptionCallback as ab, SubscriptionRegistry as ac, SubscriptionState as ad, SyncStatus as ae, SyncWatermark as af, WorkflowInstanceAction as ag, WorkflowInstanceDetail as ah, WorkflowInstancePage as ai, WorkflowInstanceStatus as aj, WorkflowInstanceSummary as ak, WorkflowStepDetail as al, WsTokenProvider as am, createClientQuery as an, createLocalStore as ao, createStream as ap, SubscriptionErrorCallback as b, PersistenceAdapter as c, HttpStreamArgsOf as d, HttpStreamChunkOf as e, StreamIterable as f, BatchSlot as g, CachedQuery as h, ClientDebugShard as i, ClientDebugSnapshot as j, ClientDebugSubscription as k, ClientMessage as l, ClientQueryRef as m, ClientShapeSubscribeMessage as n, ClientShapeUnsubscribeMessage as o, FunctionDescriptor as p, GlobalFacetValue as q, GlobalFilterClause as r, GlobalTableInfo as s, GlobalTablePage as t, HttpStreamCallArgs as u, LunoraClientError as v, LunoraClientOptions as w, MutationSettledEvent as x, OnlineOnlyOption as y, OptimisticLocalStore as z };
@@ -0,0 +1 @@
1
+ let a=0;const d=()=>{if(typeof crypto<"u"&&typeof crypto.randomUUID=="function")return crypto.randomUUID();a+=1;const r=typeof crypto<"u"&&typeof crypto.getRandomValues=="function"?Array.from(crypto.getRandomValues(new Uint8Array(8)),e=>e.toString(16).padStart(2,"0")).join(""):Math.random().toString(16).slice(2,12);return`id_${Date.now().toString(36)}_${a.toString(36)}_${r}`},f=(r,e)=>r!==void 0&&e!==r,l=d,h=(r,e,t,i)=>{if(r)try{r({error:t,mutationId:i,operation:e});return}catch{}console.warn(`[lunora] offline-queue persistence ${e} failed`,t)};class p{queueBeforeFirstConnect;maxItems;onPersistenceError;persistence;onEvict;onSizeChange;onReplayingChange;version;items=[];replayingIds=new Set;appending=new Map;unsettled=new Map;unpersisted=new Set;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.onReplayingChange=t.onReplayingChange,this.version=t.version}get size(){return this.items.length}get replaying(){return this.replayingIds.size}enqueue(e){const t=e;t.id??=l();let i=this.items.length;for(;t.issueSeq!==void 0&&i>0&&(this.items[i-1]?.issueSeq??-1)>t.issueSeq;)i-=1;this.items.splice(i,0,t),this.unsettled.set(t.id,t),this.persist(this.recordOf(t,t.id)),this.evictOverflow(),this.notifySize()}discard(e){this.unsettled.delete(e),this.unpersisted.delete(e),this.replayingIds.delete(e)&&this.onReplayingChange?.();const{persistence:t}=this;t&&(this.appending.get(e)??Promise.resolve()).then(async()=>t.remove(e)).catch(i=>{h(this.onPersistenceError,"remove",i,e)})}flushUnpersisted(){for(const e of this.unpersisted){const t=this.unsettled.get(e);t&&!this.appending.has(e)&&this.persist(this.recordOf(t,e))}}async hydrate(){if(!this.persistence)return[];let e;try{e=await this.persistence.load()}catch(n){throw h(this.onPersistenceError,"load",n),n}const t=[],i=new Set(this.items.map(n=>n.id));for(const n of e)if(!i.has(n.id)){if(f(this.version,n.version)){this.persistence.remove(n.id).catch(c=>{h(this.onPersistenceError,"remove",c,n.id)});continue}i.add(n.id),t.push({args:n.args,baselineSeq:n.baselineSeq,clientId:n.clientId,functionPath:n.functionPath,id:n.id,identity:n.identity,reject:()=>{},resolve:()=>{},shardKey:n.shardKey})}this.items.unshift(...t),this.evictOverflow(),this.notifySize();const s=new Set(this.items),o=new Set;for(const n of t)s.has(n)&&o.add(n.shardKey);return[...o]}restampIdentity(e,t){for(const i of this.items){if(i.identity!==e)continue;i.identity=t;const{id:s}=i;!this.persistence||s===void 0||this.rewriteStamp(s,this.recordOf(i,s)).catch(o=>{h(this.onPersistenceError,"replace",o,s)})}}hasPending(e){return this.items.some(t=>e(t))}drain(e){if(!e){const s=[...this.items];return this.items.length=0,this.markReplaying(s),this.notifySize(),s}const t=[],i=[];for(const s of this.items)(e(s)?t:i).push(s);return this.items.length=0,this.items.push(...i),this.markReplaying(t),this.notifySize(),t}requeue(e){if(e.length!==0){for(const t of e)t.id!==void 0&&this.replayingIds.delete(t.id);this.items.unshift(...e),this.notifySize()}}drainConflict(){const e=[],t=[];for(const i of this.items)if(i.precondition!==void 0&&!i.precondition()){const s=new Error("offline mutation skipped: precondition failed before replay");s.code="OFFLINE_PRECONDITION_FAILED",i.reject(s),e.push(i)}else t.push(i);return e.length>0&&(this.items.length=0,this.items.push(...t),this.notifySize()),e}clear(){for(const e of new Set([...this.items,...this.unsettled.values()])){const t=new Error("CLIENT_CLOSED"),i=e.id??"",s=n=>{t.code="CLIENT_CLOSED",t.persisted=n,e.reject(t)},o=this.appending.get(i);this.replayingIds.has(i)?s(!1):o===void 0?s(this.persistence!==void 0&&!this.unpersisted.has(i)):o.catch(()=>!1).then(s).catch(()=>{})}this.items.length=0,this.replayingIds.clear(),this.unsettled.clear(),this.unpersisted.clear(),this.notifySize()}recordOf(e,t){return{args:e.args,...e.baselineSeq===void 0?{}:{baselineSeq:e.baselineSeq},clientId:e.clientId,functionPath:e.functionPath,id:t,identity:e.identity,shardKey:e.shardKey,...this.version===void 0?{}:{version:this.version}}}persist(e){const{persistence:t}=this;if(!t)return;const i=(async()=>{try{return await t.append(e),this.unpersisted.delete(e.id),!0}catch(s){return this.unsettled.has(e.id)&&this.unpersisted.add(e.id),h(this.onPersistenceError,"append",s,e.id),!1}})();this.appending.set(e.id,i),i.finally(()=>{this.appending.get(e.id)===i&&this.appending.delete(e.id)}).catch(()=>{})}async rewriteStamp(e,t){const i=this.persistence;if(i)try{await this.appending.get(e),await i.replace(t)}catch(s){h(this.onPersistenceError,"replace",s,e)}}evictOverflow(){for(;this.items.length>this.maxItems;){const e=this.items.shift();if(e){e.id&&this.discard(e.id);const t=new Error("offline queue overflow");t.code="OFFLINE_QUEUE_OVERFLOW",e.reject(t),this.onEvict?.(e,t)}}}markReplaying(e){for(const t of e)t.id!==void 0&&this.replayingIds.add(t.id)}notifySize(){this.onSizeChange?.(this.items.length)}}export{p as O,f as i,l as n,h as r};
@@ -1,4 +1,4 @@
1
- import { L as LunoraClient, P as Preloaded } from "./lunora-client.d-dOEEoF4x.mjs";
1
+ import { L as LunoraClient, P as Preloaded } from "./lunora-client.d-DZ9gzk9p.mjs";
2
2
  import { F as FunctionReference, A as ArgsOf, R as ReturnOf } from "./function-reference.d-Br_hsKje.mjs";
3
3
  /**
4
4
  * Run a query once on the server (during SSR) and capture its result in a
@@ -1,4 +1,4 @@
1
- import { L as LunoraClient, P as Preloaded } from "./lunora-client.d-DpmxnYmL.js";
1
+ import { L as LunoraClient, P as Preloaded } from "./lunora-client.d-CZ9TlyaL.js";
2
2
  import { F as FunctionReference, A as ArgsOf, R as ReturnOf } from "./function-reference.d-Br_hsKje.js";
3
3
  /**
4
4
  * Run a query once on the server (during SSR) and capture its result in a
@@ -0,0 +1 @@
1
+ import{LunoraError as v}from"@lunora/errors";import{TransportError as f}from"./CONFLICT_ERROR_CODE-B7qNZMMk.mjs";const c=t=>t.reason??Object.assign(new Error("The operation was aborted"),{name:"AbortError"}),m=async(t,r,o,i=()=>new f(`LunoraClient: request timed out after ${t.toString()}ms`))=>{if(r?.aborted)throw c(r);const n=new AbortController,e=[],u=new Promise((b,d)=>{if(t>0){const a=setTimeout(()=>{d(i()),n.abort()},t);e.push(()=>{clearTimeout(a)})}if(r){const a=()=>{n.abort(),d(c(r))};r.addEventListener("abort",a,{once:!0}),e.push(()=>{r.removeEventListener("abort",a)})}}),s=o(n.signal);s.catch(()=>{});try{return await Promise.race([s,u])}finally{for(const b of e)b()}},E=async(t,r)=>{if(r===void 0)return t;if(r.aborted)throw t.catch(()=>{}),c(r);let o=()=>{};const i=new Promise((n,e)=>{o=()=>{e(c(r))},r.addEventListener("abort",o,{once:!0})});t.catch(()=>{});try{return await Promise.race([t,i])}finally{r.removeEventListener("abort",o)}},y=async(t,r)=>!Number.isFinite(r)||r<=0?t.read():m(r,void 0,async()=>t.read(),()=>new v("STREAM_IDLE",`stream received nothing for ${r.toString()}ms`));export{E as a,c as b,y as r,m as w};
@@ -1 +1 @@
1
- import{LunoraError as a}from"@lunora/errors";import{decodeWire as c}from"@lunora/wire";import{getRetryAfterMs as d,TransportError as f}from"./CONFLICT_ERROR_CODE-B7qNZMMk.mjs";const u=r=>{if(r===null)return;const t=Number(r);if(Number.isFinite(t))return t>0?t*1e3:void 0;const e=Date.parse(r);if(Number.isNaN(e))return;const o=e-Date.now();return o>0?o:void 0},v=(r,t)=>{const e=u(t);if(!(e===void 0||d(r)!==void 0))return r.data===void 0?{retryAfterMs:e}:typeof r.data=="object"&&r.data!==null&&!Array.isArray(r.data)?{...r.data,retryAfterMs:e}:void 0},m=r=>r.why===void 0?{}:{why:r.why},y=r=>{const t=r?.error;if(typeof t!="object"||t===null||Array.isArray(t))return;const{why:e,...o}=t;return typeof e=="string"?{...o,why:e}:o},l=()=>new f("LunoraClient: batch slot carried no error envelope"),n=(r,t)=>{const e=r.error,o=typeof e?.code=="string"?e.code:void 0,s=typeof e?.message=="string"?e.message:void 0;return{code:o,messageText:(typeof r.message=="string"?r.message:void 0)??s??t}},g=r=>{const{code:t,messageText:e}=n(r,"stream error"),o=r.error?.why,s=t===void 0?new Error(e):new a(t,e);return typeof o=="string"&&(s.why=o),s},E=r=>{const{code:t,messageText:e}=n(r,"subscription error"),o=r.error?.why;return{message:e,...t===void 0?{}:{code:t},...typeof o=="string"?{why:o}:{}}},i=r=>{const t=new Error(r.message??"request failed");if(t.code=r.code,r.data!==void 0)try{t.data=c(r.data)}catch{}return r.hint!==void 0&&(t.hint=r.hint),r.docsUrl!==void 0&&(t.docsUrl=r.docsUrl),typeof r.why=="string"&&(t.why=r.why),t},b=(r,t)=>{const e=i(r),o=v(e,t);return o!==void 0&&(e.data=o),e},A=r=>{const t=y(r);return t===void 0?l():i(t)};export{u as a,b,g as c,E as d,y as e,i as r,A as s,m as w};
1
+ import{LunoraError as a}from"@lunora/errors";import{decodeWire as c}from"@lunora/wire";import{TransportError as d,getRetryAfterMs as f}from"./CONFLICT_ERROR_CODE-B7qNZMMk.mjs";const u=r=>{if(r===null)return;const t=Number(r);if(Number.isFinite(t))return t>0?t*1e3:void 0;const e=Date.parse(r);if(Number.isNaN(e))return;const o=e-Date.now();return o>0?o:void 0},v=(r,t)=>{const e=u(t);if(!(e===void 0||f(r)!==void 0))return r.data===void 0?{retryAfterMs:e}:typeof r.data=="object"&&r.data!==null&&!Array.isArray(r.data)?{...r.data,retryAfterMs:e}:void 0},m=r=>r.why===void 0?{}:{why:r.why},y=r=>{const t=r?.error;if(typeof t!="object"||t===null||Array.isArray(t))return;const{why:e,...o}=t;return typeof e=="string"?{...o,why:e}:o},l=()=>new d("LunoraClient: batch slot carried no error envelope"),n=(r,t)=>{const e=r.error,o=typeof e?.code=="string"?e.code:void 0,s=typeof e?.message=="string"?e.message:void 0;return{code:o,messageText:(typeof r.message=="string"?r.message:void 0)??s??t}},g=r=>{const{code:t,messageText:e}=n(r,"stream error"),o=r.error?.why,s=t===void 0?new Error(e):new a(t,e);return typeof o=="string"&&(s.why=o),s},E=r=>{const{code:t,messageText:e}=n(r,"subscription error"),o=r.error?.why;return{message:e,...t===void 0?{}:{code:t},...typeof o=="string"?{why:o}:{}}},i=r=>{const t=new Error(r.message??"request failed");if(t.code=r.code,r.data!==void 0)try{t.data=c(r.data)}catch{}return r.hint!==void 0&&(t.hint=r.hint),r.docsUrl!==void 0&&(t.docsUrl=r.docsUrl),typeof r.why=="string"&&(t.why=r.why),t},b=(r,t)=>{const e=i(r),o=v(e,t);return o!==void 0&&(e.data=o),e},A=r=>{const t=y(r);return t===void 0?l():i(t)};export{u as a,b,g as c,E as d,y as e,i as r,A as s,l as u,m as w};
@@ -1,4 +1,4 @@
1
- import { S as SubscriptionError, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-dOEEoF4x.mjs";
1
+ import { S as SubscriptionError, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-DZ9gzk9p.mjs";
2
2
  export type {
3
3
  /**
4
4
  * `@lunora/client/query` — the framework-neutral live-query state machine shared
@@ -10,7 +10,7 @@ export type {
10
10
  * framework — each adapter supplies thin sinks that write into its own ref /
11
11
  * store / signal / cache.
12
12
  */
13
- b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-dOEEoF4x.mjs";
13
+ b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-DZ9gzk9p.mjs";
14
14
  import { F as FunctionReference, A as ArgsOf, R as ReturnOf } from "../packem_shared/function-reference.d-Br_hsKje.mjs";
15
15
  import '@lunora/errors';
16
16
  import '@lunora/runtime';
@@ -1,4 +1,4 @@
1
- import { S as SubscriptionError, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-DpmxnYmL.js";
1
+ import { S as SubscriptionError, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-CZ9TlyaL.js";
2
2
  export type {
3
3
  /**
4
4
  * `@lunora/client/query` — the framework-neutral live-query state machine shared
@@ -10,7 +10,7 @@ export type {
10
10
  * framework — each adapter supplies thin sinks that write into its own ref /
11
11
  * store / signal / cache.
12
12
  */
13
- b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-DpmxnYmL.js";
13
+ b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-CZ9TlyaL.js";
14
14
  import { F as FunctionReference, A as ArgsOf, R as ReturnOf } from "../packem_shared/function-reference.d-Br_hsKje.js";
15
15
  import '@lunora/errors';
16
16
  import '@lunora/runtime';
package/dist/service.mjs CHANGED
@@ -1 +1 @@
1
- import{LunoraError as c}from"@lunora/errors";import{encodeArgsOrThrow as d,decodeWire as y}from"@lunora/wire";import{e as f,r as w}from"./packem_shared/wire-errors-Bw04a4ZQ.mjs";const v="/_lunora/rpc",N="https://lunora.internal",i=async(n,t,r,o,u)=>{const a=r.__lunoraRef,p=JSON.stringify({args:d("@lunora/client/service",a,o??{}),functionPath:a,...u?.shardKey===void 0?{}:{shardKey:u.shardKey}}),e=await n.fetch(new Request(`${N}${v}`,{body:p,headers:{"content-type":"application/json"},method:"POST"}));let s;try{s=await e.json()}catch{throw new c("INTERNAL",`@lunora/client/service: ${t} "${a}" got a non-JSON response (status ${e.status.toString()}). Check the service binding points at the Lunora Worker that declares this function.`,{status:e.status})}if(s===null||typeof s!="object")throw new c("INTERNAL",`@lunora/client/service: ${t} "${a}" returned a JSON body that is not an object (status ${e.status.toString()}). Check the service binding points at the Lunora Worker that declares this function.`,{status:e.status});const h=s,l=f(h);if(l!==void 0)throw w(l);if(!e.ok)throw new c("INTERNAL",`@lunora/client/service: ${t} "${a}" failed with status ${e.status.toString()} and no error envelope.`,{status:e.status});return y(h.result)},R=n=>({action:async(t,r,o)=>await i(n,"action",t,r,o),mutation:async(t,r,o)=>await i(n,"mutation",t,r,o),query:async(t,r,o)=>await i(n,"query",t,r,o)});export{v as RPC_PATH,R as createServiceClient};
1
+ import{LunoraError as c}from"@lunora/errors";import{encodeArgsOrThrow as d,decodeWire as y}from"@lunora/wire";import{e as f,r as w}from"./packem_shared/wire-errors-BTLdHNoh.mjs";const v="/_lunora/rpc",N="https://lunora.internal",i=async(n,t,r,o,u)=>{const a=r.__lunoraRef,p=JSON.stringify({args:d("@lunora/client/service",a,o??{}),functionPath:a,...u?.shardKey===void 0?{}:{shardKey:u.shardKey}}),e=await n.fetch(new Request(`${N}${v}`,{body:p,headers:{"content-type":"application/json"},method:"POST"}));let s;try{s=await e.json()}catch{throw new c("INTERNAL",`@lunora/client/service: ${t} "${a}" got a non-JSON response (status ${e.status.toString()}). Check the service binding points at the Lunora Worker that declares this function.`,{status:e.status})}if(s===null||typeof s!="object")throw new c("INTERNAL",`@lunora/client/service: ${t} "${a}" returned a JSON body that is not an object (status ${e.status.toString()}). Check the service binding points at the Lunora Worker that declares this function.`,{status:e.status});const h=s,l=f(h);if(l!==void 0)throw w(l);if(!e.ok)throw new c("INTERNAL",`@lunora/client/service: ${t} "${a}" failed with status ${e.status.toString()} and no error envelope.`,{status:e.status});return y(h.result)},R=n=>({action:async(t,r,o)=>await i(n,"action",t,r,o),mutation:async(t,r,o)=>await i(n,"mutation",t,r,o),query:async(t,r,o)=>await i(n,"query",t,r,o)});export{v as RPC_PATH,R as createServiceClient};
@@ -1,4 +1,4 @@
1
- import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-dOEEoF4x.mjs";
1
+ import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-DZ9gzk9p.mjs";
2
2
  export type { A as ArgsOf, F as FunctionReference, R as ReturnOf } from "../packem_shared/function-reference.d-Br_hsKje.mjs";
3
3
  export {
4
4
  /**
@@ -20,7 +20,7 @@ p as preloadQuery,
20
20
  * WebSocket or touches a UI framework, so it is safe to import from any SSR
21
21
  * loader.
22
22
  */
23
- a as preloadedQueryResult } from "../packem_shared/preload.d-XVLTUaah.mjs";
23
+ a as preloadedQueryResult } from "../packem_shared/preload.d-BOpEnFP8.mjs";
24
24
  import '@lunora/errors';
25
25
  import '@lunora/runtime';
26
26
  /**
@@ -1,4 +1,4 @@
1
- import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-DpmxnYmL.js";
1
+ import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-CZ9TlyaL.js";
2
2
  export type { A as ArgsOf, F as FunctionReference, R as ReturnOf } from "../packem_shared/function-reference.d-Br_hsKje.js";
3
3
  export {
4
4
  /**
@@ -20,7 +20,7 @@ p as preloadQuery,
20
20
  * WebSocket or touches a UI framework, so it is safe to import from any SSR
21
21
  * loader.
22
22
  */
23
- a as preloadedQueryResult } from "../packem_shared/preload.d-BkXsKMmU.js";
23
+ a as preloadedQueryResult } from "../packem_shared/preload.d-CXUIU6pE.js";
24
24
  import '@lunora/errors';
25
25
  import '@lunora/runtime';
26
26
  /**
@@ -1 +1 @@
1
- import{getServerSession as o}from"../packem_shared/getServerSession-BaOoo1p6.mjs";import{deserializePreloaded as l,serializePreloaded as t}from"../packem_shared/deserializePreloaded-CyFK_cv6.mjs";import{createServerClient as i}from"../packem_shared/createServerClient-BqCdfoE1.mjs";import{preloadQuery as s,preloadedQueryResult as f}from"../packem_shared/preloadQuery-uFy24PCR.mjs";export{i as createServerClient,l as deserializePreloaded,o as getServerSession,s as preloadQuery,f as preloadedQueryResult,t as serializePreloaded};
1
+ import{getServerSession as o}from"../packem_shared/getServerSession-BaOoo1p6.mjs";import{deserializePreloaded as l,serializePreloaded as t}from"../packem_shared/deserializePreloaded-CyFK_cv6.mjs";import{createServerClient as i}from"../packem_shared/createServerClient-B0TsbJkS.mjs";import{preloadQuery as s,preloadedQueryResult as f}from"../packem_shared/preloadQuery-uFy24PCR.mjs";export{i as createServerClient,l as deserializePreloaded,o as getServerSession,s as preloadQuery,f as preloadedQueryResult,t as serializePreloaded};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/client",
3
- "version": "1.0.0-alpha.232",
3
+ "version": "1.0.0-alpha.234",
4
4
  "description": "Lunora browser SDK: WebSocket transport, optimistic updates, and an offline mutation queue",
5
5
  "keywords": [
6
6
  "cloudflare",