@lunora/client 1.0.0-alpha.21 → 1.0.0-alpha.23

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 (32) 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 +249 -4
  4. package/dist/index.d.ts +249 -4
  5. package/dist/index.mjs +10 -4
  6. package/dist/packem_shared/ClientServiceWorker-C3PAFwy0.mjs +100 -0
  7. package/dist/packem_shared/{LunoraClient-kXpHNyaE.mjs → LunoraClient-BBCQjjbl.mjs} +382 -243
  8. package/dist/packem_shared/{OfflineQueue-GGYJRmhF.mjs → OfflineQueue-B4HUF7rt.mjs} +1 -1
  9. package/dist/packem_shared/SubscriptionRegistry-CxS_Inha.mjs +31 -0
  10. package/dist/packem_shared/TabCoordinator-BwRR8H06.mjs +222 -0
  11. package/dist/packem_shared/createClientQuery-CQ51bWAE.mjs +71 -0
  12. package/dist/packem_shared/createLocalStore-BtqUmOQA.mjs +2 -0
  13. package/dist/packem_shared/createReply-lI4tVS2w.mjs +36 -0
  14. package/dist/packem_shared/{createServerClient-DF-3mLmb.mjs → createServerClient-CTTAmvMx.mjs} +1 -1
  15. package/dist/packem_shared/createSnapshotPrecondition-CxQ1T4ZP.mjs +18 -0
  16. package/dist/packem_shared/httpStream-BJU-aflc.mjs +159 -0
  17. package/dist/packem_shared/{local-store-BveBeFEo.mjs → local-store-DIq-UWfD.mjs} +1 -1
  18. package/dist/packem_shared/{lunora-client.d-BYkEjCEJ.d.mts → lunora-client.d-JvtVpf8A.d.mts} +302 -18
  19. package/dist/packem_shared/{lunora-client.d-BYkEjCEJ.d.ts → lunora-client.d-JvtVpf8A.d.ts} +302 -18
  20. package/dist/packem_shared/{offline-queue-B9vfdSqp.mjs → offline-queue-CF4_Co5k.mjs} +29 -0
  21. package/dist/packem_shared/{preload.d-B-vyHnml.d.ts → preload.d-C4_d_l5v.d.ts} +1 -1
  22. package/dist/packem_shared/{preload.d-DrfuisCE.d.mts → preload.d-DKbjGN5O.d.mts} +1 -1
  23. package/dist/packem_shared/wire-key-Djie6aaR.mjs +266 -0
  24. package/dist/query/index.d.mts +2 -2
  25. package/dist/query/index.d.ts +2 -2
  26. package/dist/ssr/index.d.mts +3 -3
  27. package/dist/ssr/index.d.ts +3 -3
  28. package/dist/ssr/index.mjs +1 -1
  29. package/package.json +2 -2
  30. package/dist/packem_shared/SubscriptionRegistry-DjGKZsqq.mjs +0 -1
  31. package/dist/packem_shared/createLocalStore-jRoqmazl.mjs +0 -2
  32. package/dist/packem_shared/subscription-BjynOXCU.mjs +0 -68
@@ -1,5 +1,42 @@
1
1
  import { CronJobInfo, VectorIndexSummary, VectorQueryMatch, KvNamespaceSummary, KvKeyListResult, KvValueResult, AuthUser, AuthPage, AuthImpersonation, AuthCapabilities, AuthConfigInfo, AuthSession } from '@lunora/runtime';
2
2
  /**
3
+ * Reactive key-value store for local-only client state.
4
+ *
5
+ * Unlike a server {@link SubscriptionState} (which tracks a live WS connection,
6
+ * an `acked` flag, `serverBase`, optimistic layers, and the full subscription
7
+ * machinery), a `ClientQueryRef` is purely local — no server round-trip, no
8
+ * WebSocket, no persistence. It exists so framework adapters can offer a
9
+ * `useClientQuery` hook whose values survive component remounts and are shared
10
+ * across every consumer of the same ref, with none of the ceremony or coupling
11
+ * of a dedicated context provider.
12
+ *
13
+ * The store lives inside `LunoraClient` (a private field) and is surfaced through
14
+ * `client.getClientQuery(ref)` / `setClientQuery(ref, value)` /
15
+ * `subscribeClientQuery(ref, callback)`.
16
+ */
17
+ /** Opaque handle for a typed client-local query slot. */
18
+ interface ClientQueryRef<T = unknown> {
19
+ /** Default value when no value has been set explicitly. */
20
+ readonly defaultValue: T;
21
+ /** Stable identity for the slot. Must be unique within a client instance. */
22
+ readonly key: string;
23
+ }
24
+ /** A subscriber callback for value changes to a {@link ClientQueryRef}. */
25
+
26
+ /**
27
+ * Create a typed {@link ClientQueryRef}. Call once per slot at module scope
28
+ * (or inside a component module) — the ref object is the stable identity.
29
+ * @example
30
+ * ```ts
31
+ * // lunora/client-queries.ts
32
+ * import { createClientQuery } from "@lunora/client";
33
+ *
34
+ * export const sidebarOpen = createClientQuery("sidebarOpen", true);
35
+ * export const selectedMessageId = createClientQuery("selectedMessageId", undefined as string | undefined);
36
+ * ```
37
+ */
38
+ declare const createClientQuery: <T>(key: string, defaultValue: T) => ClientQueryRef<T>;
39
+ /**
3
40
  * The machine-readable error codes a client can observe on a failed
4
41
  * RPC/batch/subscription. Mirrors the server's `CODE_STATUS` keys
5
42
  * (`@lunora/server`'s `error.ts`) by hand — the client is framework-neutral and
@@ -80,6 +117,55 @@ interface FunctionReference<Kind extends FunctionKind = FunctionKind, Args = unk
80
117
  type ArgsOf<F> = F extends FunctionReference<infer _K, infer A, infer _R> ? A : never;
81
118
  /** Extract the return type from a {@link FunctionReference}. */
82
119
  type ReturnOf<F> = F extends FunctionReference<infer _K, infer _A, infer R> ? R : never;
120
+ /**
121
+ * Typed reference to an HTTP-SSE stream route (`httpRoute.&lt;verb>(path).stream()`)
122
+ * emitted by `@lunora/codegen` as `httpStreams.&lt;namespace>.&lt;name>`.
123
+ *
124
+ * Distinct from {@link FunctionReference}: this is the **HTTP-SSE route stream**
125
+ * (opened with `fetch` + `ReadableStream` against the route's own URL), not the
126
+ * WS procedure stream (`kind: "stream"`). At runtime it carries the HTTP verb
127
+ * and the route path; the phantom marker carries the chunk / searchParams /
128
+ * params types so `httpStream` (and the framework hooks over it) infer the
129
+ * chunk type end-to-end.
130
+ * @experimental Reconnect/POST-body/wire-fidelity design questions are still open, so the shape may change.
131
+ */
132
+ interface HttpStreamRef<Chunk = unknown, SearchParams = unknown, Params = unknown> {
133
+ /**
134
+ * Phantom marker carrying the `Chunk`/`SearchParams`/`Params` type
135
+ * parameters for inference. Never present at runtime; declared in a
136
+ * covariant (output) position so a concrete reference stays assignable to
137
+ * a widened one.
138
+ */
139
+ readonly __lunoraHttpStream?: {
140
+ chunk: Chunk;
141
+ params: Params;
142
+ searchParams: SearchParams;
143
+ };
144
+ /** HTTP verb the route binds to (uppercased), e.g. `"GET"`. */
145
+ readonly method: string;
146
+ /** The route path as declared, e.g. `/api/tokens/:id` — `:name` segments are filled from `params`. */
147
+ readonly path: string;
148
+ }
149
+ /**
150
+ * The call-side args of an HTTP-SSE stream route: `:name` path params plus URL query params.
151
+ * @experimental Part of the HTTP-SSE stream surface.
152
+ */
153
+ interface HttpStreamCallArgs<SearchParams = unknown, Params = unknown> {
154
+ /** Values for the route path's `:name` segments. */
155
+ params?: Params;
156
+ /** URL query params, appended to the request URL (undefined entries are skipped). */
157
+ searchParams?: SearchParams;
158
+ }
159
+ /**
160
+ * Extract the chunk type from a {@link HttpStreamRef}.
161
+ * @experimental Part of the HTTP-SSE stream surface.
162
+ */
163
+ type HttpStreamChunkOf<R> = R extends HttpStreamRef<infer Chunk, infer _S, infer _P> ? Chunk : never;
164
+ /**
165
+ * Extract the call-side args type from a {@link HttpStreamRef}.
166
+ * @experimental Part of the HTTP-SSE stream surface.
167
+ */
168
+ type HttpStreamArgsOf<R> = R extends HttpStreamRef<infer _C, infer S, infer P> ? HttpStreamCallArgs<S, P> : never;
83
169
  type Unsubscribe = () => void;
84
170
  /**
85
171
  * Serializable result of `preloadQuery`. Produced on the server during SSR,
@@ -272,6 +358,15 @@ interface QueryCacheAdapter {
272
358
  /** Remove one cached query by key. */
273
359
  remove: (key: string) => Promise<void>;
274
360
  }
361
+ /**
362
+ * Resolves the WS `?token=` credential fresh at every (re)connect — the channel
363
+ * for short-lived tokens (e.g. the ephemeral admin sub-token the worker mints
364
+ * at `POST /_lunora/admin/ws-token`) instead of a static secret in the URL.
365
+ * May return the token synchronously or as a Promise; returning `undefined`
366
+ * connects without a token. A thrown error / rejected Promise fails that
367
+ * connect attempt, and the client retries with its normal reconnect backoff.
368
+ */
369
+ type WsTokenProvider = () => Promise<string | undefined> | string | undefined;
275
370
  interface LunoraClientOptions {
276
371
  /**
277
372
  * Base path the worker mounts better-auth at, used by the client's
@@ -308,6 +403,16 @@ interface LunoraClientOptions {
308
403
  * Defaults to 10000 (10s); set to `0` (or negative) to disable.
309
404
  */
310
405
  connectTimeoutMs?: number;
406
+ /**
407
+ * When `true`, tabs sharing the same origin coordinate via BroadcastChannel
408
+ * so only one tab (the "leader") opens WebSocket connections to the server.
409
+ * Follower tabs receive subscription data through the channel instead.
410
+ *
411
+ * Reduces simultaneous WS connections, bandwidth, and cross-tab state drift.
412
+ * Requires `BroadcastChannel` (browser-only); silently ignored otherwise.
413
+ * Defaults to `false`.
414
+ */
415
+ crossTabSync?: boolean;
311
416
  fetch?: typeof fetch;
312
417
  /**
313
418
  * Interval (ms) between keepalive pings sent on each open subscription
@@ -317,6 +422,15 @@ interface LunoraClientOptions {
317
422
  * `0` (or a negative value) to disable the heartbeat entirely.
318
423
  */
319
424
  heartbeatIntervalMs?: number;
425
+ /**
426
+ * When `true` and a `queryCache` is active, framework hooks (React, Vue, …)
427
+ * wait for the durable cache to finish hydrating before their first render
428
+ * with an enabled subscription, so users see cached data instead of an
429
+ * undefined flash before the socket round-trip. Defaults to `false`.
430
+ *
431
+ * Requires `queryCache` to be set (not `false`); silently ignored otherwise.
432
+ */
433
+ hydrateOnStart?: boolean;
320
434
  offlineQueue?: OfflineQueueOptions;
321
435
  /**
322
436
  * Durable outbox seam for offline writes. When supplied (the `@lunora/db`
@@ -365,15 +479,21 @@ interface LunoraClientOptions {
365
479
  url: string;
366
480
  WebSocket?: typeof WebSocket;
367
481
  /**
368
- * Token appended to the WebSocket URL as `?token=…`. The server matches it
369
- * against `LUNORA_WS_BEARER` (to clear the upgrade gate) and/or
482
+ * Credential appended to the WebSocket URL as `?token=…`. The server matches
483
+ * it against `LUNORA_WS_BEARER` (to clear the upgrade gate) and/or
370
484
  * `LUNORA_ADMIN_TOKEN` (to authorize `__lunora_admin__:*` subscriptions —
371
- * what the studio sets it to). Browsers can't set headers on the
372
- * `WebSocket` constructor, so the query parameter is the only channel; it
373
- * ends up in server logs and history, so prefer a short-lived rotating
374
- * token in production.
485
+ * what the studio supplies). Browsers can't set headers on the `WebSocket`
486
+ * constructor, so the query parameter is the only channel; it ends up in
487
+ * server logs and history, so prefer a short-lived rotating token in
488
+ * production over a static secret.
489
+ *
490
+ * Pass a {@link WsTokenProvider} function to resolve the token fresh at
491
+ * every (re)connect — the channel for short-lived credentials such as the
492
+ * ephemeral admin sub-token minted by `POST /_lunora/admin/ws-token`: the
493
+ * provider re-mints on each reconnect, including the one following a `4001`
494
+ * token-expired drop, so a static master token never has to ride the URL.
375
495
  */
376
- wsToken?: string;
496
+ wsToken?: string | WsTokenProvider;
377
497
  wsUrl?: string;
378
498
  }
379
499
  /** Wire envelope sent on `POST /_lunora/rpc`. */
@@ -941,9 +1061,10 @@ interface SubscriptionState {
941
1061
  acked: boolean;
942
1062
  readonly args: Record<string, unknown>;
943
1063
  /**
944
- * Stable-stringified `args`, computed once at subscribe time. Cached so the
945
- * optimistic-update fan-out can compare against a mutation's args key without
946
- * re-serializing every subscription's args on every mutation.
1064
+ * Stable wire-key of `args` (`stableWireKey`), computed once at subscribe
1065
+ * time. Cached so the optimistic-update fan-out can compare against a
1066
+ * mutation's args key without re-serializing every subscription's args on
1067
+ * every mutation.
947
1068
  */
948
1069
  readonly argsKey: string;
949
1070
  readonly callbacks: Set<SubscriptionCallback>;
@@ -1012,11 +1133,13 @@ interface SubscriptionState {
1012
1133
  }
1013
1134
  /**
1014
1135
  * Active subscription registry. The client keys subscriptions by
1015
- * `(functionPath, stableStringify(args), shardKey)` so duplicate calls share a
1136
+ * `(functionPath, stableWireKey(args), shardKey)` so duplicate calls share a
1016
1137
  * single server-side registration. Args are stably encoded (keys sorted at every
1017
1138
  * depth) so two structurally-equal arg records constructed with a different key
1018
1139
  * order (`{ a, b }` vs `{ b, a }`) collapse to the same key instead of leaking a
1019
- * duplicate subscription.
1140
+ * duplicate subscription. Encoding the args' **wire form** keeps the key
1141
+ * byte-identical for pure-JSON args while giving wire-typed args (`bigint`,
1142
+ * `Date`, bytes, …) distinct stable tokens instead of a throw.
1020
1143
  */
1021
1144
  declare class SubscriptionRegistry {
1022
1145
  static key(functionPath: string, args: Record<string, unknown>, shardKey?: string): string;
@@ -1178,6 +1301,14 @@ interface MutationCallOptions<TCurrent = unknown, TValue = unknown, TArgs = unkn
1178
1301
  * once; every write is rolled back atomically if the mutation fails.
1179
1302
  */
1180
1303
  optimisticUpdate?: OptimisticUpdate<TArgs>;
1304
+ /**
1305
+ * Sync predicate evaluated just before the offline queue replays this
1306
+ * write on reconnect. When it returns `false` the mutation is dropped
1307
+ * instead of replayed — use it to guard against replaying writes whose
1308
+ * assumptions are no longer valid (e.g. the document it referred to was
1309
+ * deleted by another client while this tab was offline).
1310
+ */
1311
+ precondition?: () => boolean;
1181
1312
  shardKey?: string;
1182
1313
  }
1183
1314
  /** Callback a shape subscription invokes with its materialized rowset on every applied poke. */
@@ -1226,8 +1357,19 @@ type BatchSlot = {
1226
1357
  declare class LunoraClient {
1227
1358
  /** Hard cap on concurrently-buffered pokes — a backstop that reclaims buffers abandoned by a mid-poke disconnect (no `pokeEnd`). Far above any real concurrent-in-flight count. */
1228
1359
  private static readonly MAX_POKE_BUFFERS;
1360
+ /**
1361
+ * Create a typed {@link ClientQueryRef}. Convenience wrapper around
1362
+ * {@link createClientQuery} so you don't need a separate import.
1363
+ * @example
1364
+ * ```ts
1365
+ * const sidebarOpen = LunoraClient.createClientQuery("sidebarOpen", true);
1366
+ * ```
1367
+ */
1368
+ static createClientQuery<T>(key: string, defaultValue: T): ClientQueryRef<T>;
1229
1369
  readonly url: string;
1230
1370
  readonly wsUrl: string;
1371
+ /** Local reactive store for {@link ClientQueryRef} values — no server round-trip. Private; reach it via `getClientQuery` / `setClientQuery` / `subscribeClientQuery`. */
1372
+ private readonly clientQueryStore;
1231
1373
  private wsToken;
1232
1374
  /** Better-auth base path (trailing slash stripped) for the `get-session` lookup. */
1233
1375
  private readonly authBasePath;
@@ -1249,6 +1391,20 @@ declare class LunoraClient {
1249
1391
  /** Stable per-client id stamped onto every `OutboxMutation` (custom-mutator watermark). */
1250
1392
  private readonly clientId;
1251
1393
  /**
1394
+ * `true` when the constructor's hydration microtask has finished loading the
1395
+ * durable read cache (Pillar 2) into `hydratedQueryCache`. Signals that
1396
+ * the cache is ready for synchronous `peekHydratedQuery` reads.
1397
+ */
1398
+ private readyResolved;
1399
+ /** Resolvers for `whenReady()` — called once hydration completes. */
1400
+ private readyResolve;
1401
+ /**
1402
+ * Promise that resolves once the durable read cache has been loaded. When
1403
+ * `hydrateOnStart` is not set or no query cache is configured, resolves
1404
+ * immediately (the constructor creates an already-resolved promise).
1405
+ */
1406
+ private readonly readyPromise;
1407
+ /**
1252
1408
  * Highest custom-mutator watermark the server has echoed for this client,
1253
1409
  * keyed by shard bucket (`shardKey ?? ""`) since the DO tracks one
1254
1410
  * `__client_watermark` per shard. `callMutator` bumps it from every
@@ -1281,6 +1437,12 @@ declare class LunoraClient {
1281
1437
  private readonly pendingCacheWrites;
1282
1438
  private cacheFlushTimer;
1283
1439
  private readonly subscriptions;
1440
+ /**
1441
+ * Cross-tab coordinator; created only when `crossTabSync: true`. When the
1442
+ * client is not the elected leader, all WebSocket operations are skipped.
1443
+ * Not `readonly` — `close()` clears it (mirrors `outboxLeaderRelease`).
1444
+ */
1445
+ private tabCoordinator;
1284
1446
  /** One {@link ShardConnection} per shard key (keyed by `shardKey ?? ""`). */
1285
1447
  private readonly connections;
1286
1448
  /** Default `connect`-envelope context applied to a shard with no explicit override. */
@@ -1444,10 +1606,12 @@ declare class LunoraClient {
1444
1606
  * Replace the token appended to WS upgrade URLs as `?token=…` and close
1445
1607
  * every open shard socket so the reconnect picks up the new value. Call
1446
1608
  * this whenever the user's WS credential changes (rotating the admin token
1447
- * in the studio, switching workspaces, etc.). Bearer tokens for HTTP
1448
- * RPC are independentsee {@link setAuthToken}.
1609
+ * in the studio, switching workspaces, etc.). Accepts a static string or a
1610
+ * {@link WsTokenProvider} resolved fresh at every (re)connect the channel
1611
+ * for short-lived credentials like the minted ephemeral admin sub-token.
1612
+ * Bearer tokens for HTTP RPC are independent — see {@link setAuthToken}.
1449
1613
  */
1450
- setWsToken(token: string | undefined): void;
1614
+ setWsToken(token: string | undefined | WsTokenProvider): void;
1451
1615
  /**
1452
1616
  * Register (or clear, with `undefined`) the app context sent in the `connect`
1453
1617
  * envelope for a shard's socket, overriding the client-wide
@@ -1559,6 +1723,93 @@ declare class LunoraClient {
1559
1723
  * unsubscribe function. See {@link MutationSettledEvent}.
1560
1724
  */
1561
1725
  onMutationSettled(listener: (event: MutationSettledEvent) => void): Unsubscribe;
1726
+ /**
1727
+ * Read the current value for a {@link ClientQueryRef}. Returns
1728
+ * `ref.defaultValue` when no value has been explicitly set.
1729
+ */
1730
+ getClientQuery<T>(ref: ClientQueryRef<T>): T;
1731
+ /**
1732
+ * Set a new value for `ref` and notify every subscriber. Pass `undefined`
1733
+ * to reset the slot to `ref.defaultValue`.
1734
+ */
1735
+ setClientQuery<T>(ref: ClientQueryRef<T>, value: T): void;
1736
+ /**
1737
+ * Subscribe to changes for `ref`. The callback is NOT invoked on
1738
+ * registration — call {@link getClientQuery} for the current value.
1739
+ * Returns an unsubscribe function.
1740
+ */
1741
+ subscribeClientQuery(ref: ClientQueryRef, callback: (value: unknown) => void): Unsubscribe;
1742
+ /**
1743
+ * Reset a {@link ClientQueryRef} to its default value, notifying every
1744
+ * subscriber. Equivalent to `setClientQuery(ref, ref.defaultValue)` but
1745
+ * removes the stored entry so a future {@link getClientQuery} returns
1746
+ * the default rather than an explicitly-set value.
1747
+ */
1748
+ resetClientQuery(ref: ClientQueryRef): void;
1749
+ /**
1750
+ * Capture a snapshot of the current live query value at call time and
1751
+ * produce a `() => boolean` precondition that compares it against the
1752
+ * value at replay time (on queue drain / reconnect).
1753
+ *
1754
+ * When the precondition is checked it re-reads the query's current value
1755
+ * via `peekActiveQueryValue`. If the value differs from what was
1756
+ * captured at call time the precondition returns `false` and the offline
1757
+ * mutation is dropped as stale.
1758
+ *
1759
+ * This is a method wrapper around `createSnapshotPrecondition` that
1760
+ * binds the client instance for you — no need to pass `client` explicitly.
1761
+ * @example
1762
+ * ```ts
1763
+ * client.mutation(api.todos.update, { id, text }, {
1764
+ * precondition: client.snapshotPrecondition(api.todos.list, { userId }),
1765
+ * });
1766
+ * ```
1767
+ */
1768
+ snapshotPrecondition(functionRef: FunctionReference, args: Record<string, unknown>, shardKey?: string): () => boolean;
1769
+ /**
1770
+ * Resolves once the durable read cache has been loaded into memory. When
1771
+ * `hydrateOnStart` is not configured or no query cache adapter is active,
1772
+ * returns an already-resolved promise so callers can always await it
1773
+ * unconditionally.
1774
+ *
1775
+ * Framework adapters (React, Vue, etc.) use this to gate the first
1776
+ * (enabled) render of a live query behind hydration, so the user sees
1777
+ * cached data instead of an undefined flash before the socket round-trip.
1778
+ */
1779
+ whenReady(): Promise<void>;
1780
+ /**
1781
+ * Synchronously reports whether {@link whenReady} has already resolved (the
1782
+ * durable read cache is loaded, or none is configured). Framework adapters
1783
+ * read this to seed the hydration-gate state on the first render without
1784
+ * awaiting, then subscribe via {@link whenReady} for the pending case.
1785
+ */
1786
+ get isReady(): boolean;
1787
+ /**
1788
+ * Synchronously peek at a value the durable read cache loaded for the given
1789
+ * function path + args + shard key. Returns `undefined` when:
1790
+ *
1791
+ * - No query cache adapter is configured.
1792
+ * - Hydration hasn't completed yet (race — await {@link whenReady} first).
1793
+ * - The cached value's identity fingerprint doesn't match the current auth.
1794
+ *
1795
+ * Unlike the internal {@link takeHydratedCache}, this is a READ-ONLY peek:
1796
+ * the cached entry stays in `hydratedQueryCache` so the subscription created
1797
+ * later by {@link subscribe} consumes it normally.
1798
+ */
1799
+ peekHydratedQuery(functionPath: string, args: Record<string, unknown>, shardKey?: string): unknown;
1800
+ /**
1801
+ * Peek at the **current live value** of an active subscription, if one
1802
+ * exists. Returns the subscription's `lastValue` (which includes any
1803
+ * optimistic overlay) or `undefined` if no subscription is active for the
1804
+ * given `(functionPath, args, shardKey)`.
1805
+ *
1806
+ * Unlike {@link peekHydratedQuery} (which reads from the durable read cache
1807
+ * and is independent of active subscriptions), this method reflects the
1808
+ * current in-memory state of an already-opened subscription — useful for
1809
+ * offline mutation preconditions that need to snapshot the value at call time
1810
+ * and compare it at replay time.
1811
+ */
1812
+ peekActiveQueryValue(functionPath: string, args: Record<string, unknown>, shardKey?: string): unknown;
1562
1813
  query<F extends FunctionReference>(function_: F, args: ArgsOf<F>, options?: {
1563
1814
  shardKey?: string;
1564
1815
  }): Promise<ReturnOf<F>>;
@@ -1687,8 +1938,10 @@ declare class LunoraClient {
1687
1938
  * Subscribe to the live scheduled-jobs list over the SchedulerDO's admin
1688
1939
  * WebSocket. `onJobs` fires with the full list on connect and on every
1689
1940
  * change (schedule / cancel / alarm-fire). Reconnects with the client's
1690
- * configured backoff. Requires `wsToken` to be set to the admin token (the
1691
- * browser can't send an `Authorization` header on a WS). Returns an
1941
+ * configured backoff. Requires `wsToken` to be set to an admin credential
1942
+ * (the browser can't send an `Authorization` header on a WS) the master
1943
+ * token, or preferably a {@link WsTokenProvider} minting the ephemeral
1944
+ * sub-token so the master credential stays out of the URL. Returns an
1692
1945
  * unsubscribe function that closes the socket and stops reconnecting.
1693
1946
  */
1694
1947
  subscribeScheduledJobs(onJobs: (jobs: ScheduleRecord[]) => void): Unsubscribe;
@@ -2188,6 +2441,25 @@ declare class LunoraClient {
2188
2441
  maxBuffer?: number;
2189
2442
  shardKey?: string;
2190
2443
  }): StreamIterable<ReturnOf<F>>;
2444
+ /**
2445
+ * Open a typed **HTTP-SSE route stream** (`httpRoute.&lt;verb>(path).stream()`).
2446
+ * Distinct from {@link LunoraClient.stream}, which consumes the WS procedure
2447
+ * stream (`kind: "stream"`): this one opens the route's own URL with `fetch`
2448
+ * and parses the Server-Sent Events framing the route pump writes (`data:`
2449
+ * chunks, a final `event: complete`, an `event: error` on throw).
2450
+ *
2451
+ * The reference comes from the generated `httpStreams.*` registry, so the
2452
+ * yielded chunk type is the route handler's yielded type. Cancelling the
2453
+ * returned iterable (or aborting `options.signal`) aborts the fetch, which
2454
+ * the server handler observes via its `signal`. The client's bearer token
2455
+ * (when set) rides as an `authorization` header.
2456
+ * @experimental Reconnect/POST-body/wire-fidelity design questions are still open, so the shape may change.
2457
+ */
2458
+ httpStream<Ref extends HttpStreamRef>(route: Ref, args?: HttpStreamArgsOf<Ref>, options?: {
2459
+ headers?: Record<string, string>;
2460
+ maxBuffer?: number;
2461
+ signal?: AbortSignal;
2462
+ }): StreamIterable<HttpStreamChunkOf<Ref>>;
2191
2463
  close(): void;
2192
2464
  /**
2193
2465
  * Persist a mutation that can't go out on the wire right now (offline, or
@@ -2333,6 +2605,18 @@ declare class LunoraClient {
2333
2605
  */
2334
2606
  private resendShapeSubscriptions;
2335
2607
  private ensureSocket;
2608
+ /**
2609
+ * Resolve the {@link WsTokenProvider} and open the shard socket with the
2610
+ * minted token. The connection is already in the `connecting` state, so the
2611
+ * async gap is race-guarded: a client `close()`, a `setWsToken` bounce, or a
2612
+ * competing connect that landed first all abandon this attempt. A provider
2613
+ * failure fails the attempt through {@link handleDisconnect}, which arms the
2614
+ * normal reconnect backoff — a broken mint endpoint degrades to retries, not
2615
+ * a silent tokenless socket the admin gate would reject.
2616
+ */
2617
+ private openSocketWithProvidedToken;
2618
+ /** Construct the shard socket and wire its lifecycle handlers. The connection must already be in the `connecting` state. */
2619
+ private openSocket;
2336
2620
  private handleDisconnect;
2337
2621
  /**
2338
2622
  * Begin the keepalive heartbeat on an open connection. Each tick sends a
@@ -2537,4 +2821,4 @@ declare class LunoraClient {
2537
2821
  */
2538
2822
  private settleReplayBatchSlots;
2539
2823
  }
2540
- export { StreamHandle as $, ArgsOf as A, BookmarkStorage as B, CONFLICT_ERROR_CODE as C, DEFAULT_MAX_BUFFER as D, RpcEnvelope as E, FunctionReference as F, GlobalFacetResult as G, RpcResponseBody as H, ScheduleRecord as I, SchedulerPoolStatus as J, SchedulerStatus as K, LunoraClient as L, MutationCallOptions as M, ServerMessage as N, OfflineQueueOptions as O, Preloaded as P, QueryCacheAdapter as Q, ReturnOf as R, SubscriptionError as S, ServerPokeEndMessage as T, User as U, ServerPokePartMessage as V, ServerPokeStartMessage as W, ShardTrafficEntry as X, ShardTrafficResult as Y, StorageListPage as Z, StorageObject as _, Unsubscribe as a, StreamIterable as a0, SubscriptionCallback as a1, SubscriptionRegistry as a2, SubscriptionState as a3, SyncWatermark as a4, WorkflowInstanceAction as a5, WorkflowInstanceDetail as a6, WorkflowInstancePage as a7, WorkflowInstanceStatus as a8, WorkflowInstanceSummary as a9, WorkflowStepDetail as aa, createLocalStore as ab, createStream as ac, getErrorCode as ad, getRetryAfterMs as ae, isConflictError as af, isForbiddenError as ag, isRateLimitedError as ah, isUnauthorizedError as ai, SubscriptionErrorCallback as b, PersistenceAdapter as c, ReconnectOptions as d, BatchSlot as e, CachedQuery as f, ClientMessage as g, ClientShapeSubscribeMessage as h, ClientShapeUnsubscribeMessage as i, ConnectionStatus as j, FunctionArgumentDescriptor as k, FunctionDescriptor as l, GlobalFacetValue as m, GlobalFilterClause as n, GlobalTableInfo as o, GlobalTablePage as p, LunoraClientError as q, LunoraClientOptions as r, LunoraErrorCode as s, MutationSettledEvent as t, OptimisticLocalStore as u, OptimisticUpdate as v, OutboxMutation as w, OutboxSink as x, PersistedMutation as y, RowOp as z };
2824
+ export { ServerPokePartMessage as $, ArgsOf as A, BookmarkStorage as B, CONFLICT_ERROR_CODE as C, DEFAULT_MAX_BUFFER as D, OptimisticUpdate as E, FunctionReference as F, GlobalFacetResult as G, HttpStreamRef as H, OutboxMutation as I, OutboxSink as J, PersistedMutation as K, LunoraClient as L, MutationCallOptions as M, RowOp as N, OfflineQueueOptions as O, Preloaded as P, QueryCacheAdapter as Q, ReturnOf as R, SubscriptionError as S, RpcEnvelope as T, User as U, RpcResponseBody as V, ScheduleRecord as W, SchedulerPoolStatus as X, SchedulerStatus as Y, ServerMessage as Z, ServerPokeEndMessage as _, Unsubscribe as a, ServerPokeStartMessage as a0, ShardTrafficEntry as a1, ShardTrafficResult as a2, StorageListPage as a3, StorageObject as a4, StreamHandle as a5, SubscriptionCallback as a6, SubscriptionRegistry as a7, SubscriptionState as a8, SyncWatermark as a9, WorkflowInstanceAction as aa, WorkflowInstanceDetail as ab, WorkflowInstancePage as ac, WorkflowInstanceStatus as ad, WorkflowInstanceSummary as ae, WorkflowStepDetail as af, WsTokenProvider as ag, createClientQuery as ah, createLocalStore as ai, createStream as aj, getErrorCode as ak, getRetryAfterMs as al, isConflictError as am, isForbiddenError as an, isRateLimitedError as ao, isUnauthorizedError as ap, SubscriptionErrorCallback as b, PersistenceAdapter as c, HttpStreamArgsOf as d, HttpStreamChunkOf as e, StreamIterable as f, ReconnectOptions as g, BatchSlot as h, CachedQuery as i, ClientMessage as j, ClientQueryRef as k, ClientShapeSubscribeMessage as l, ClientShapeUnsubscribeMessage as m, ConnectionStatus as n, FunctionArgumentDescriptor 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, LunoraErrorCode as x, MutationSettledEvent as y, OptimisticLocalStore as z };