@lunora/client 1.0.0-alpha.68 → 1.0.0-alpha.69
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 +3 -2
- package/dist/auth/index.d.ts +3 -2
- package/dist/index.d.mts +53 -6
- package/dist/index.d.ts +53 -6
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/CONFLICT_ERROR_CODE-CDDneB-G.mjs +1 -0
- package/dist/packem_shared/LunoraClient-NP7mgVkC.mjs +1 -0
- package/dist/packem_shared/{createServerClient-SWMORQWn.mjs → createServerClient-DwpNFoKP.mjs} +1 -1
- package/dist/packem_shared/function-reference.d-Br_hsKje.d.mts +45 -0
- package/dist/packem_shared/function-reference.d-Br_hsKje.d.ts +45 -0
- package/dist/packem_shared/{lunora-client.d-DafpbiD5.d.mts → lunora-client.d-CLwpIj61.d.ts} +1051 -46
- package/dist/packem_shared/{lunora-client.d-BQ0ig3ih.d.ts → lunora-client.d-DWDMVBKE.d.mts} +1051 -46
- package/dist/packem_shared/{preload.d-DGiAgCkV.d.ts → preload.d-BAazUwhn.d.mts} +2 -2
- package/dist/packem_shared/{preload.d-C09vDOAR.d.mts → preload.d-ClHaOfOQ.d.ts} +2 -2
- package/dist/query/index.d.mts +4 -3
- package/dist/query/index.d.ts +4 -3
- package/dist/service.d.mts +1 -1
- package/dist/service.d.ts +1 -1
- package/dist/ssr/index.d.mts +4 -4
- package/dist/ssr/index.d.ts +4 -4
- package/dist/ssr/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/packem_shared/CONFLICT_ERROR_CODE-LjU7z0mB.mjs +0 -1
- package/dist/packem_shared/LunoraClient-D-06gXR2.mjs +0 -1
- package/dist/packem_shared/types.d-Bsj5mGrj.d.mts +0 -1040
- package/dist/packem_shared/types.d-Bsj5mGrj.d.ts +0 -1040
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { F as FunctionReference, A as ArgsOf, R as ReturnOf
|
|
1
|
+
import { F as FunctionReference, A as ArgsOf, R as ReturnOf } from "./function-reference.d-Br_hsKje.js";
|
|
2
|
+
import { LunoraErrorCode } from '@lunora/errors';
|
|
2
3
|
import { CronJobInfo, VectorIndexSummary, VectorQueryMatch, PipelineLogQuery, PipelineLogPage, KvNamespaceSummary, KvKeyListResult, KvValueResult, AuthUser, AuthPage, AuthImpersonation, AuthCapabilities, AuthConfigInfo, AuthSession } from '@lunora/runtime';
|
|
3
4
|
/**
|
|
4
5
|
* Reactive key-value store for local-only client state.
|
|
@@ -36,60 +37,1051 @@ interface ClientQueryRef<T = unknown> {
|
|
|
36
37
|
*/
|
|
37
38
|
declare const createClientQuery: <T>(key: string, defaultValue: T) => ClientQueryRef<T>;
|
|
38
39
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
40
|
+
* Typed reference to an HTTP-SSE stream route (`httpRoute.<verb>(path).stream()`)
|
|
41
|
+
* emitted by `@lunora/codegen` as `httpStreams.<namespace>.<name>`.
|
|
42
|
+
*
|
|
43
|
+
* Distinct from {@link FunctionReference}: this is the **HTTP-SSE route stream**
|
|
44
|
+
* (opened with `fetch` + `ReadableStream` against the route's own URL), not the
|
|
45
|
+
* WS procedure stream (`kind: "stream"`). At runtime it carries the HTTP verb
|
|
46
|
+
* and the route path; the phantom marker carries the chunk / searchParams /
|
|
47
|
+
* params types so `httpStream` (and the framework hooks over it) infer the
|
|
48
|
+
* chunk type end-to-end.
|
|
49
|
+
* @experimental Reconnect/POST-body/wire-fidelity design questions are still open, so the shape may change.
|
|
45
50
|
*/
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
interface HttpStreamRef<Chunk = unknown, SearchParams = unknown, Params = unknown> {
|
|
52
|
+
/**
|
|
53
|
+
* Phantom marker carrying the `Chunk`/`SearchParams`/`Params` type
|
|
54
|
+
* parameters for inference. Never present at runtime; declared in a
|
|
55
|
+
* covariant (output) position so a concrete reference stays assignable to
|
|
56
|
+
* a widened one.
|
|
57
|
+
*/
|
|
58
|
+
readonly __lunoraHttpStream?: {
|
|
59
|
+
chunk: Chunk;
|
|
60
|
+
params: Params;
|
|
61
|
+
searchParams: SearchParams;
|
|
62
|
+
};
|
|
63
|
+
/** HTTP verb the route binds to (uppercased), e.g. `"GET"`. */
|
|
64
|
+
readonly method: string;
|
|
65
|
+
/** The route path as declared, e.g. `/api/tokens/:id` — `:name` segments are filled from `params`. */
|
|
66
|
+
readonly path: string;
|
|
67
|
+
}
|
|
51
68
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* the conflict). Structural check on the `code` property the client attaches
|
|
55
|
-
* when decoding the worker's `{ error: { code, message } }` envelope.
|
|
69
|
+
* The call-side args of an HTTP-SSE stream route: `:name` path params plus URL query params.
|
|
70
|
+
* @experimental Part of the HTTP-SSE stream surface.
|
|
56
71
|
*/
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
72
|
+
interface HttpStreamCallArgs<SearchParams = unknown, Params = unknown> {
|
|
73
|
+
/** Values for the route path's `:name` segments. */
|
|
74
|
+
params?: Params;
|
|
75
|
+
/** URL query params, appended to the request URL (undefined entries are skipped). */
|
|
76
|
+
searchParams?: SearchParams;
|
|
77
|
+
}
|
|
60
78
|
/**
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* common per-call error a UI must handle in an RLS-first app.
|
|
79
|
+
* Extract the chunk type from a {@link HttpStreamRef}.
|
|
80
|
+
* @experimental Part of the HTTP-SSE stream surface.
|
|
64
81
|
*/
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
82
|
+
type HttpStreamChunkOf<R> = R extends HttpStreamRef<infer Chunk, infer _S, infer _P> ? Chunk : never;
|
|
83
|
+
/**
|
|
84
|
+
* Extract the call-side args type from a {@link HttpStreamRef}.
|
|
85
|
+
* @experimental Part of the HTTP-SSE stream surface.
|
|
86
|
+
*/
|
|
87
|
+
type HttpStreamArgsOf<R> = R extends HttpStreamRef<infer _C, infer S, infer P> ? HttpStreamCallArgs<S, P> : never;
|
|
88
|
+
type Unsubscribe = () => void;
|
|
89
|
+
/**
|
|
90
|
+
* Serializable result of `preloadQuery`. Produced on the server during SSR,
|
|
91
|
+
* embedded in the rendered HTML, then handed to `usePreloadedQuery` on the
|
|
92
|
+
* client so the first render shows the server value with no loading flash
|
|
93
|
+
* before a live subscription attaches. Every field survives `JSON.stringify`.
|
|
94
|
+
*/
|
|
95
|
+
interface Preloaded<T = unknown> {
|
|
96
|
+
readonly __lunoraPreloaded: true;
|
|
97
|
+
readonly args: Record<string, unknown>;
|
|
98
|
+
readonly functionPath: string;
|
|
99
|
+
readonly shardKey?: string;
|
|
100
|
+
readonly value: T;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Pluggable storage for the `x-d1-bookmark` value used to provide
|
|
104
|
+
* read-your-writes between a mutation and subsequent queries.
|
|
105
|
+
*/
|
|
106
|
+
interface BookmarkStorage {
|
|
107
|
+
get: () => string | null;
|
|
108
|
+
set: (value: string | null) => void;
|
|
109
|
+
}
|
|
110
|
+
interface ReconnectOptions {
|
|
111
|
+
initialDelayMs?: number;
|
|
112
|
+
jitter?: boolean;
|
|
113
|
+
maxDelayMs?: number;
|
|
114
|
+
}
|
|
115
|
+
/** Which durable-storage operation failed, passed to {@link OfflineQueueOptions.onPersistenceError}. */
|
|
116
|
+
type PersistenceOperation = "append" | "clear" | "load" | "remove";
|
|
117
|
+
/** Context handed to a persistence-error handler. */
|
|
118
|
+
interface PersistenceErrorContext {
|
|
119
|
+
readonly error: unknown;
|
|
120
|
+
/** The mutation id involved, when the failing op was scoped to one (`append`/`remove`). */
|
|
121
|
+
readonly mutationId?: string;
|
|
122
|
+
readonly operation: PersistenceOperation;
|
|
123
|
+
}
|
|
124
|
+
interface OfflineQueueOptions {
|
|
125
|
+
maxItems?: number;
|
|
126
|
+
/**
|
|
127
|
+
* Invoked when a {@link PersistenceAdapter} call rejects (e.g. IndexedDB quota
|
|
128
|
+
* exceeded). Without a handler, failures are logged via `console.warn` so they
|
|
129
|
+
* are never fully silent. Note: a failed `append` means the write is queued in
|
|
130
|
+
* memory but NOT durable — it will not survive a reload.
|
|
131
|
+
*/
|
|
132
|
+
onPersistenceError?: (context: PersistenceErrorContext) => void;
|
|
133
|
+
/**
|
|
134
|
+
* Queue mutations issued before a shard's first successful WebSocket
|
|
135
|
+
* connect (defaults to `false`). The standard behaviour (`LunoraClient`'s
|
|
136
|
+
* `mutation()`) queues only when the targeted shard has been connected at
|
|
137
|
+
* least once (`wasEverConnected`), so the registry / resubscribe handshake
|
|
138
|
+
* has run. Set this to `true` for offline-first apps that want to enqueue
|
|
139
|
+
* writes on the very first session before the WS is up.
|
|
140
|
+
*/
|
|
141
|
+
queueBeforeFirstConnect?: boolean;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Serializable shape of an offline mutation, durably stored by a
|
|
145
|
+
* {@link PersistenceAdapter} so queued writes survive a reload/crash. The live
|
|
146
|
+
* `resolve`/`reject` callbacks of an in-flight `QueuedMutation` are *not*
|
|
147
|
+
* persisted — a restored mutation is replayed with no original awaiter.
|
|
148
|
+
*/
|
|
149
|
+
interface PersistedMutation {
|
|
150
|
+
args: Record<string, unknown>;
|
|
151
|
+
/**
|
|
152
|
+
* The client id that queued this write, persisted so a replay after a reload
|
|
153
|
+
* lands in the SAME server-side dedup namespace it was issued under. The
|
|
154
|
+
* standalone client's own `clientId` is minted per session, so replaying under
|
|
155
|
+
* the live one would miss the `__idempotency` row for an anonymous caller and
|
|
156
|
+
* re-run a write the server already committed. Absent on records written by
|
|
157
|
+
* older client versions, which replay under the live id.
|
|
158
|
+
*/
|
|
159
|
+
clientId?: string;
|
|
160
|
+
functionPath: string;
|
|
161
|
+
id: string;
|
|
162
|
+
/**
|
|
163
|
+
* Issuing identity fingerprint, persisted so a hydrated write replays only
|
|
164
|
+
* under the identity that queued it (`null` = queued while signed out).
|
|
165
|
+
* Absent on records written by older client versions, which replay under
|
|
166
|
+
* the ambient identity for back-compat.
|
|
167
|
+
*/
|
|
168
|
+
identity?: string | null;
|
|
169
|
+
shardKey?: string;
|
|
170
|
+
/**
|
|
171
|
+
* App/schema version stamped at enqueue (from `LunoraClientOptions.persistenceVersion`).
|
|
172
|
+
* On hydrate, a record whose `version` doesn't match the current one is dropped
|
|
173
|
+
* and purged rather than replayed — so a write persisted by an older deploy
|
|
174
|
+
* (with a now-changed function signature) can't replay against the new schema.
|
|
175
|
+
* Absent when no `persistenceVersion` is configured (no version gating).
|
|
176
|
+
*/
|
|
177
|
+
version?: string;
|
|
178
|
+
}
|
|
72
179
|
/**
|
|
73
|
-
*
|
|
74
|
-
*
|
|
180
|
+
* Durable store for the offline mutation queue. The default client keeps the
|
|
181
|
+
* queue in memory; supplying an adapter (e.g. `createIndexedDbPersistence`)
|
|
182
|
+
* makes queued writes survive a page reload. Implementations must preserve FIFO
|
|
183
|
+
* (enqueue) order in `PersistenceAdapter.load`.
|
|
184
|
+
*
|
|
185
|
+
* Replay semantics are at-least-once: a mutation is removed only after the
|
|
186
|
+
* server confirms (or rejects) it, so a crash between commit and `remove` can
|
|
187
|
+
* replay it again on the next load.
|
|
188
|
+
*/
|
|
189
|
+
interface PersistenceAdapter {
|
|
190
|
+
/** Append a mutation to durable storage (called on enqueue). */
|
|
191
|
+
append: (mutation: PersistedMutation) => Promise<void>;
|
|
192
|
+
/** Drop every persisted mutation (e.g. on logout). */
|
|
193
|
+
clear: () => Promise<void>;
|
|
194
|
+
/** Load all persisted mutations in FIFO order — called once at startup. */
|
|
195
|
+
load: () => Promise<PersistedMutation[]>;
|
|
196
|
+
/** Remove a mutation by id once it has been replayed (resolved or rejected). */
|
|
197
|
+
remove: (id: string) => Promise<void>;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* One write handed to an {@link OutboxSink}. Mirrors {@link PersistedMutation}
|
|
201
|
+
* plus the custom-mutator identity (`clientId`/`mutationId`/`idempotencyKey`)
|
|
202
|
+
* the durable outbox needs to dedupe and watermark replays.
|
|
75
203
|
*/
|
|
76
|
-
|
|
77
|
-
|
|
204
|
+
interface OutboxMutation {
|
|
205
|
+
args: Record<string, unknown>;
|
|
206
|
+
/** Stable per-client id; pairs with {@link OutboxMutation.mutationId} as `idempotencyKey`. */
|
|
207
|
+
clientId: string;
|
|
208
|
+
functionPath: string;
|
|
209
|
+
/** `${clientId}:${mutationId}` — sent as `x-lunora-mutation-id` so a replay is server-idempotent. */
|
|
210
|
+
idempotencyKey: string;
|
|
211
|
+
/** Issuing identity fingerprint (`null` = signed out); drives the sink's identity guard. */
|
|
212
|
+
identity: string | null;
|
|
213
|
+
/** Monotonic per-client mutation id, backing the server `__client_watermark`. */
|
|
214
|
+
mutationId: number;
|
|
215
|
+
shardKey?: string;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Pluggable durable outbox seam. When set on {@link LunoraClientOptions.outbox},
|
|
219
|
+
* the client delegates offline write durability + at-least-once replay to this
|
|
220
|
+
* sink instead of its built-in {@link PersistenceAdapter}-backed `OfflineQueue`.
|
|
221
|
+
* `@lunora/db` supplies the blessed implementation (`createExecutorOutboxSink`,
|
|
222
|
+
* backed by the TanStack `OfflineExecutor`); the interface itself is
|
|
223
|
+
* dependency-free so `@lunora/client` stays TanStack-free.
|
|
224
|
+
*/
|
|
225
|
+
interface OutboxSink {
|
|
226
|
+
/**
|
|
227
|
+
* Persist and schedule a write for replay. Rejects with an
|
|
228
|
+
* `OFFLINE_QUEUE_OVERFLOW`-coded error when the sink's cap is exceeded, so
|
|
229
|
+
* the caller can surface back-pressure to the issuing mutation.
|
|
230
|
+
*/
|
|
231
|
+
enqueue: (mutation: OutboxMutation) => Promise<void>;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* One persisted query result in the durable read cache (Pillar 2). Keyed in the
|
|
235
|
+
* store by `shardKey + functionPath + argsKey`; the record carries everything
|
|
236
|
+
* needed to render offline on reload and to resume the live subscription.
|
|
237
|
+
*/
|
|
238
|
+
interface CachedQuery {
|
|
239
|
+
/**
|
|
240
|
+
* Issuing identity fingerprint (same shape the offline queue stamps). A
|
|
241
|
+
* cached value only hydrates when it matches the current identity, so a
|
|
242
|
+
* signed-out cache never leaks into a new session. `null` = cached while
|
|
243
|
+
* signed out.
|
|
244
|
+
*/
|
|
245
|
+
identity: string | null;
|
|
246
|
+
/**
|
|
247
|
+
* The `cursor` high-watermark this value reflects, replayed as `sinceSeq`
|
|
248
|
+
* on reconnect so the server can resume instead of re-snapshotting. Absent
|
|
249
|
+
* when the value predates CDC / no cursor was advertised.
|
|
250
|
+
*/
|
|
251
|
+
serverCursor?: number;
|
|
252
|
+
/**
|
|
253
|
+
* The CDC `epoch` the `serverCursor` belongs to, replayed as `sinceEpoch`
|
|
254
|
+
* on reconnect so the server only resumes when the client is still on the
|
|
255
|
+
* same changelog timeline. Absent when no epoch was advertised.
|
|
256
|
+
*/
|
|
257
|
+
serverEpoch?: string;
|
|
258
|
+
/** Wall-clock millis the value was written — drives LRU eviction. */
|
|
259
|
+
ts: number;
|
|
260
|
+
/** The full query result last seen from the server. */
|
|
261
|
+
value: unknown;
|
|
262
|
+
/**
|
|
263
|
+
* App/schema version stamped when persisted (from `LunoraClientOptions.persistenceVersion`).
|
|
264
|
+
* A cached value whose `version` doesn't match the current one is not hydrated —
|
|
265
|
+
* so a result of a now-changed shape from an older deploy can't render. Absent
|
|
266
|
+
* when no `persistenceVersion` is configured (no version gating).
|
|
267
|
+
*/
|
|
268
|
+
version?: string;
|
|
269
|
+
}
|
|
270
|
+
/** A stored read-cache row: the {@link CachedQuery} plus the key it is stored under. */
|
|
271
|
+
interface StoredQuery extends CachedQuery {
|
|
272
|
+
key: string;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Durable store for the client read cache (Pillar 2): query results survive a
|
|
276
|
+
* reload so reads hydrate from disk and render immediately while the socket
|
|
277
|
+
* reconnects. Opt-in via {@link LunoraClientOptions.queryCache}; omit to keep
|
|
278
|
+
* reads in memory only (today's behaviour). Mirrors {@link PersistenceAdapter}'s
|
|
279
|
+
* shape over the same IndexedDB plumbing.
|
|
280
|
+
*/
|
|
281
|
+
interface QueryCacheAdapter {
|
|
282
|
+
/** Drop every cached query (e.g. on logout / identity change). */
|
|
283
|
+
clear: () => Promise<void>;
|
|
284
|
+
/** Load every cached query — called once at startup to hydrate reads. */
|
|
285
|
+
load: () => Promise<StoredQuery[]>;
|
|
286
|
+
/** Upsert one cached query by key (called when a subscription value advances). */
|
|
287
|
+
put: (key: string, entry: CachedQuery) => Promise<void>;
|
|
288
|
+
/** Remove one cached query by key. */
|
|
289
|
+
remove: (key: string) => Promise<void>;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Resolves the WS `?token=` credential fresh at every (re)connect — the channel
|
|
293
|
+
* for short-lived tokens (e.g. the ephemeral admin sub-token the worker mints
|
|
294
|
+
* at `POST /_lunora/admin/ws-token`) instead of a static secret in the URL.
|
|
295
|
+
* May return the token synchronously or as a Promise; returning `undefined`
|
|
296
|
+
* connects without a token. A thrown error / rejected Promise fails that
|
|
297
|
+
* connect attempt, and the client retries with its normal reconnect backoff.
|
|
298
|
+
*/
|
|
299
|
+
type WsTokenProvider = () => Promise<string | undefined> | string | undefined;
|
|
300
|
+
interface LunoraClientOptions {
|
|
301
|
+
/**
|
|
302
|
+
* Base path the worker mounts better-auth at, used by the client's
|
|
303
|
+
* `getCurrentUser()` to reach the `get-session` route. Defaults to
|
|
304
|
+
* `/api/auth` (matching `@lunora/auth`'s `DEFAULT_AUTH_BASE_PATH`).
|
|
305
|
+
*/
|
|
306
|
+
authBasePath?: string;
|
|
307
|
+
bookmarkStorage?: BookmarkStorage;
|
|
308
|
+
/**
|
|
309
|
+
* Stable per-client id backing the custom-mutator watermark. Sent on the
|
|
310
|
+
* `connect` envelope (so the server can scope this client's
|
|
311
|
+
* `__client_watermark`) and stamped onto every {@link OutboxMutation} the
|
|
312
|
+
* {@link LunoraClientOptions.outbox} sink persists, where it pairs with the
|
|
313
|
+
* monotonic mutation id to form the idempotency key. The `@lunora/db` path
|
|
314
|
+
* persists a stable id alongside the outbox and passes it here; omit for the
|
|
315
|
+
* standalone client, which generates an ephemeral per-session id.
|
|
316
|
+
*/
|
|
317
|
+
clientId?: string;
|
|
318
|
+
/**
|
|
319
|
+
* Default app context sent in the `connect` envelope right after each socket
|
|
320
|
+
* opens, forwarded to the server's `onConnect`/`onDisconnect` lifecycle hooks
|
|
321
|
+
* as `event.context`. A per-shard context registered via
|
|
322
|
+
* `setConnectionContext` overrides this for that shard. Omit when no lifecycle
|
|
323
|
+
* hook needs connection context.
|
|
324
|
+
*/
|
|
325
|
+
connectionContext?: Record<string, unknown>;
|
|
326
|
+
/**
|
|
327
|
+
* Fail-fast timeout (ms) for opening a subscription WebSocket. If the
|
|
328
|
+
* handshake doesn't complete within this window — a hung dev proxy or a cold
|
|
329
|
+
* worker that never upgrades — the client force-closes the socket and routes
|
|
330
|
+
* through its normal reconnect/backoff (surfacing `offline` status) instead
|
|
331
|
+
* of leaving the live channel silently stuck on the browser's much longer
|
|
332
|
+
* default. Does not affect HTTP queries/mutations (those never ride the WS).
|
|
333
|
+
* Defaults to 10000 (10s); set to `0` (or negative) to disable.
|
|
334
|
+
*/
|
|
335
|
+
connectTimeoutMs?: number;
|
|
336
|
+
/**
|
|
337
|
+
* When `true`, tabs sharing the same origin (and the same signed-in identity)
|
|
338
|
+
* coordinate via BroadcastChannel so only one tab — the "leader" — opens
|
|
339
|
+
* WebSocket connections to the server. Reduces simultaneous WS connections,
|
|
340
|
+
* bandwidth, and cross-tab state drift. Requires `BroadcastChannel`
|
|
341
|
+
* (browser-only); silently ignored otherwise. Defaults to `false`.
|
|
342
|
+
*
|
|
343
|
+
* **The channel is one-directional: leader → follower.** The leader
|
|
344
|
+
* broadcasts the values, errors, checkpoints and connection status of the
|
|
345
|
+
* subscriptions *it* holds; there is no frame with which a follower can ask
|
|
346
|
+
* the leader for anything.
|
|
347
|
+
*
|
|
348
|
+
* `subscribe` works on a follower and is how the relay delivers: the
|
|
349
|
+
* registration is what the leader's broadcast key is matched against, so a
|
|
350
|
+
* follower sees a value while the leader independently holds the same
|
|
351
|
+
* `(fn, args, shardKey)`.
|
|
352
|
+
*
|
|
353
|
+
* Nothing else is served, because the leader broadcasts nothing for it and a
|
|
354
|
+
* follower cannot ask. `subscribeShape` and `acquireConnectionContext` are
|
|
355
|
+
* inert on a follower — framework code (`@lunora/db`'s shape sync, every
|
|
356
|
+
* `usePresence` adapter) calls them from an effect the app cannot opt out
|
|
357
|
+
* of, so throwing would unwind the tab rather than degrade one feature.
|
|
358
|
+
* `whisper`, `whisperSubscribe`, `setConnectionContext` and `stream` are
|
|
359
|
+
* only ever called by app code, which can handle a failure, so those throw
|
|
360
|
+
* `NOT_IMPLEMENTED` rather than returning a handle that never fires. (The
|
|
361
|
+
* brief window every tab spends claiming leadership at startup is not a
|
|
362
|
+
* follower state: a lone tab self-promotes and its registered subscriptions
|
|
363
|
+
* are sent then.) HTTP surfaces — `query`, `mutation`, `action`, the offline
|
|
364
|
+
* queue's replay — are unaffected on every tab.
|
|
365
|
+
*
|
|
366
|
+
* So: enable this when your tabs run the SAME app views over plain
|
|
367
|
+
* `subscribe`, and leave it off if tabs can sit on different routes or you
|
|
368
|
+
* use shapes, whispers, streams, or connection context.
|
|
369
|
+
*/
|
|
370
|
+
crossTabSync?: boolean;
|
|
371
|
+
fetch?: typeof fetch;
|
|
372
|
+
/**
|
|
373
|
+
* Interval (ms) between keepalive pings sent on each open subscription
|
|
374
|
+
* socket. The server answers them via the Durable Object's hibernation
|
|
375
|
+
* auto-response WITHOUT waking the DO, so an idle socket stays alive across
|
|
376
|
+
* hibernation without a billable wakeup. Defaults to 30000 (30s); set to
|
|
377
|
+
* `0` (or a negative value) to disable the heartbeat entirely.
|
|
378
|
+
*/
|
|
379
|
+
heartbeatIntervalMs?: number;
|
|
380
|
+
/**
|
|
381
|
+
* When `true` and a `queryCache` is active, framework hooks (React, Vue, …)
|
|
382
|
+
* wait for the durable cache to finish hydrating before their first render
|
|
383
|
+
* with an enabled subscription, so users see cached data instead of an
|
|
384
|
+
* undefined flash before the socket round-trip. Defaults to `false`.
|
|
385
|
+
*
|
|
386
|
+
* Requires `queryCache` to be set (not `false`); silently ignored otherwise.
|
|
387
|
+
*/
|
|
388
|
+
hydrateOnStart?: boolean;
|
|
389
|
+
offlineQueue?: OfflineQueueOptions;
|
|
390
|
+
/**
|
|
391
|
+
* Durable outbox seam for offline writes. When supplied (the `@lunora/db`
|
|
392
|
+
* path wires `createExecutorOutboxSink`), offline mutations are delegated to
|
|
393
|
+
* the sink and the built-in {@link PersistenceAdapter}-backed `OfflineQueue`
|
|
394
|
+
* is bypassed, so a db app has exactly one durable write path. Omit for the
|
|
395
|
+
* standalone client, which keeps using {@link LunoraClientOptions.persistence}.
|
|
396
|
+
*/
|
|
397
|
+
outbox?: OutboxSink;
|
|
398
|
+
/**
|
|
399
|
+
* Durable store for the offline mutation queue. Tri-state — an explicit
|
|
400
|
+
* {@link PersistenceAdapter} is used as-is; `false` opts out (the queue stays
|
|
401
|
+
* in memory, lost on reload); omitted (the default) auto-probes a durable
|
|
402
|
+
* IndexedDB store when the `indexedDB` global is present (browsers), otherwise
|
|
403
|
+
* in-memory, so SSR/Node/React-Native keep the in-memory behaviour and only
|
|
404
|
+
* environments that can persist do. Pass `createAsyncStoragePersistence()` on
|
|
405
|
+
* React Native.
|
|
406
|
+
*/
|
|
407
|
+
persistence?: false | PersistenceAdapter;
|
|
408
|
+
/**
|
|
409
|
+
* App/schema version stamped onto every persisted queued write and cached
|
|
410
|
+
* read. Bump it on a breaking change to a function signature or query shape:
|
|
411
|
+
* on the next boot, persisted writes / cached reads stamped with a different
|
|
412
|
+
* version are dropped (and purged) rather than replayed / hydrated against the
|
|
413
|
+
* new schema. Omit to disable version gating (records are never invalidated by
|
|
414
|
+
* version).
|
|
415
|
+
*
|
|
416
|
+
* **Adoption is itself an invalidation event:** records written before you set
|
|
417
|
+
* `persistenceVersion` carry no version, so the first boot after enabling it
|
|
418
|
+
* purges all currently-queued offline writes (and cached reads) as stale. Adopt
|
|
419
|
+
* it on a build where that clean slate is acceptable — typically the same
|
|
420
|
+
* breaking deploy you're protecting against — not purely speculatively.
|
|
421
|
+
*/
|
|
422
|
+
persistenceVersion?: string;
|
|
423
|
+
/**
|
|
424
|
+
* Durable store for the read cache (Pillar 2). When active, query results
|
|
425
|
+
* are persisted as their subscriptions advance and hydrated on construction
|
|
426
|
+
* so a reload renders cached data before the socket reconnects, then resumes
|
|
427
|
+
* the live subscription from the persisted cursor. Tri-state — an explicit
|
|
428
|
+
* {@link QueryCacheAdapter} is used as-is; `false` opts out (reads stay in
|
|
429
|
+
* memory only); omitted (the default) auto-probes IndexedDB exactly like
|
|
430
|
+
* {@link LunoraClientOptions.persistence}.
|
|
431
|
+
*/
|
|
432
|
+
queryCache?: QueryCacheAdapter | false;
|
|
433
|
+
reconnect?: ReconnectOptions;
|
|
434
|
+
url: string;
|
|
435
|
+
WebSocket?: typeof WebSocket;
|
|
436
|
+
/**
|
|
437
|
+
* Credential appended to the WebSocket URL as `?token=…`. The server matches
|
|
438
|
+
* it against `LUNORA_WS_BEARER` (to clear the upgrade gate) and/or
|
|
439
|
+
* `LUNORA_ADMIN_TOKEN` (to authorize `__lunora_admin__:*` subscriptions —
|
|
440
|
+
* what the studio supplies). Browsers can't set headers on the `WebSocket`
|
|
441
|
+
* constructor, so the query parameter is the only channel; it ends up in
|
|
442
|
+
* server logs and history, so prefer a short-lived rotating token in
|
|
443
|
+
* production over a static secret.
|
|
444
|
+
*
|
|
445
|
+
* Pass a {@link WsTokenProvider} function to resolve the token fresh at
|
|
446
|
+
* every (re)connect — the channel for short-lived credentials such as the
|
|
447
|
+
* ephemeral admin sub-token minted by `POST /_lunora/admin/ws-token`: the
|
|
448
|
+
* provider re-mints on each reconnect, including the one following a `4001`
|
|
449
|
+
* token-expired drop, so a static master token never has to ride the URL.
|
|
450
|
+
*/
|
|
451
|
+
wsToken?: string | WsTokenProvider;
|
|
452
|
+
wsUrl?: string;
|
|
453
|
+
}
|
|
454
|
+
/** Wire envelope sent on `POST /_lunora/rpc`. */
|
|
455
|
+
interface RpcEnvelope {
|
|
456
|
+
args?: Record<string, unknown>;
|
|
457
|
+
/**
|
|
458
|
+
* Stable per-client identifier (custom-mutator push path). Pairs with
|
|
459
|
+
* {@link RpcEnvelope.mutationId} to form `idempotencyKey` and scope the
|
|
460
|
+
* server `__client_watermark`. Absent on plain `client.mutation` calls.
|
|
461
|
+
*/
|
|
462
|
+
clientId?: string;
|
|
463
|
+
functionPath: string;
|
|
464
|
+
/**
|
|
465
|
+
* Idempotency key (`${clientId}:${mutationId}`) for the custom-mutator push
|
|
466
|
+
* path, mirrored into the `x-lunora-mutation-id` header. Absent on plain
|
|
467
|
+
* `client.mutation` calls.
|
|
468
|
+
*/
|
|
469
|
+
idempotencyKey?: string;
|
|
470
|
+
/**
|
|
471
|
+
* Monotonic per-client mutation id (custom-mutator push path), backing the
|
|
472
|
+
* server-side per-client watermark: `id <= watermark` is a replay (skipped),
|
|
473
|
+
* `id == watermark + 1` runs authoritatively, `id > watermark + 1` halts the
|
|
474
|
+
* batch so the client resends from `watermark + 1`. Absent on plain
|
|
475
|
+
* `client.mutation` calls.
|
|
476
|
+
*/
|
|
477
|
+
mutationId?: number;
|
|
478
|
+
shardKey?: string;
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Wire response from the shard's `/rpc` endpoint (forwarded by the runtime). A
|
|
482
|
+
* watermarked custom-mutator push additionally carries `lastMutationId` — the
|
|
483
|
+
* highest per-client sequence the DO has applied — which the client uses to keep
|
|
484
|
+
* its `clientSeq` generator monotonic across reloads (see `LunoraClient.callMutator`).
|
|
485
|
+
* A plain mutation on a CDC shard carries `commitCursor` — the cursor the write
|
|
486
|
+
* committed at — which gates the drop of a per-call optimistic layer.
|
|
487
|
+
*/
|
|
488
|
+
type RpcResponseBody = {
|
|
489
|
+
error: {
|
|
490
|
+
code: string;
|
|
491
|
+
data?: unknown;
|
|
492
|
+
message: string;
|
|
493
|
+
};
|
|
494
|
+
} | {
|
|
495
|
+
commitCursor?: number;
|
|
496
|
+
lastMutationId?: number;
|
|
497
|
+
result: unknown;
|
|
78
498
|
};
|
|
499
|
+
/** Subscription protocol — client → server. */
|
|
500
|
+
interface ClientSubscribeMessage {
|
|
501
|
+
id: string;
|
|
502
|
+
/**
|
|
503
|
+
* `sinceSeq` is the persisted `cursor` high-watermark the client last saw
|
|
504
|
+
* for this shard (Pillar 1b resume). Present only when a durable
|
|
505
|
+
* {@link QueryCacheAdapter} restored a cached value with a cursor; the
|
|
506
|
+
* server replies with a lightweight `resume` frame instead of a full
|
|
507
|
+
* snapshot when nothing the query reads changed since it. Absent on a
|
|
508
|
+
* first-time subscribe.
|
|
509
|
+
*/
|
|
510
|
+
query: {
|
|
511
|
+
args?: Record<string, unknown>;
|
|
512
|
+
functionPath?: string;
|
|
513
|
+
sinceEpoch?: string;
|
|
514
|
+
sinceSeq?: number;
|
|
515
|
+
table?: string;
|
|
516
|
+
};
|
|
517
|
+
type: "subscribe";
|
|
518
|
+
}
|
|
519
|
+
interface ClientUnsubscribeMessage {
|
|
520
|
+
id: string;
|
|
521
|
+
type: "unsubscribe";
|
|
522
|
+
}
|
|
79
523
|
/**
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
524
|
+
* One-shot control frame sent right after the socket opens. Registers the
|
|
525
|
+
* connection's app `context` (e.g. `{ roomId, sessionId }`) with the server and
|
|
526
|
+
* fires the `onConnect` lifecycle hooks; the same context is replayed to
|
|
527
|
+
* `onDisconnect` when the socket drops.
|
|
84
528
|
*/
|
|
85
|
-
|
|
529
|
+
interface ClientConnectMessage {
|
|
530
|
+
/**
|
|
531
|
+
* Wire behaviours this client can handle that an older one cannot, so the
|
|
532
|
+
* server can use them without breaking clients that can't. Currently just
|
|
533
|
+
* `"pageDelta"`; see `shared/page-result.ts` for what it promises and why it
|
|
534
|
+
* must be announced rather than assumed. Omitting it is always safe.
|
|
535
|
+
*/
|
|
536
|
+
caps?: ReadonlyArray<string>;
|
|
537
|
+
/**
|
|
538
|
+
* Stable per-client id (persisted alongside the outbox). Lets the server
|
|
539
|
+
* scope this connection's `__client_watermark` so custom-mutator pokes can
|
|
540
|
+
* echo the right per-client `lastMutationId`. Omitted by clients that don't
|
|
541
|
+
* use custom mutators.
|
|
542
|
+
*/
|
|
543
|
+
clientId?: string;
|
|
544
|
+
context?: Record<string, unknown>;
|
|
545
|
+
id: string;
|
|
546
|
+
type: "connect";
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Subscribe to a declarative **shape** — server-side partial replication scoped
|
|
550
|
+
* by `shardBy` + the shape's predicate + RLS. The client sends the shape *name*
|
|
551
|
+
* + validated `args`; the server resolves the trusted `where` (identity/RLS
|
|
552
|
+
* `baseWhere` the client can't forge) and streams the matching rowset, then live
|
|
553
|
+
* {@link ServerPokePartMessage} diffs. `id` namespaces the subscription and is
|
|
554
|
+
* echoed as `shapeId` on every poke part.
|
|
555
|
+
*/
|
|
556
|
+
interface ClientShapeSubscribeMessage {
|
|
557
|
+
id: string;
|
|
558
|
+
shape: {
|
|
559
|
+
args?: Record<string, unknown>;
|
|
560
|
+
name: string;
|
|
561
|
+
};
|
|
562
|
+
/**
|
|
563
|
+
* Resume from this checkpoint (the `__cdc_log` cursor the client last
|
|
564
|
+
* applied for this shape). When absent or below the server's retained floor
|
|
565
|
+
* (`minCdcSeq`), the server re-seeds with a full insert-poke instead of a
|
|
566
|
+
* delta.
|
|
567
|
+
*/
|
|
568
|
+
sinceCheckpoint?: number;
|
|
569
|
+
/**
|
|
570
|
+
* The CDC epoch {@link ClientShapeSubscribeMessage.sinceCheckpoint} belongs
|
|
571
|
+
* to. A mismatch (forked changelog timeline) forces a full re-seed even when
|
|
572
|
+
* the cursor is numerically in range.
|
|
573
|
+
*/
|
|
574
|
+
sinceEpoch?: string;
|
|
575
|
+
type: "shape_subscribe";
|
|
576
|
+
}
|
|
577
|
+
/** Cancel a shape subscription started with the same `id`. */
|
|
578
|
+
interface ClientShapeUnsubscribeMessage {
|
|
579
|
+
id: string;
|
|
580
|
+
type: "shape_unsubscribe";
|
|
581
|
+
}
|
|
582
|
+
interface ClientAckMessage {
|
|
583
|
+
id: string;
|
|
584
|
+
type: "ack";
|
|
585
|
+
}
|
|
86
586
|
/**
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
587
|
+
* Start a streaming query. The id namespaces a fresh stream and is echoed on
|
|
588
|
+
* every {@link ServerChunkMessage} the server pushes back. Cancel a running
|
|
589
|
+
* stream by sending a {@link ClientUnsubscribeMessage} with the same id —
|
|
590
|
+
* subscription and stream id-spaces share the cancel channel; the prefix
|
|
591
|
+
* (`sub_*` vs `stream_*`) keeps the local registries searchable.
|
|
91
592
|
*/
|
|
92
|
-
|
|
593
|
+
interface ClientStreamMessage {
|
|
594
|
+
/**
|
|
595
|
+
* Run generation the {@link ClientStreamMessage.sinceChunk} watermark
|
|
596
|
+
* belongs to: the `generation` stamp carried by the chunk frames this
|
|
597
|
+
* client already received, echoed back on a resume. The server refuses to
|
|
598
|
+
* splice a different run's tail onto the held prefix — a mismatch fails
|
|
599
|
+
* with `STREAM_INTERRUPTED` instead. Omitted on a first attach.
|
|
600
|
+
*/
|
|
601
|
+
generation?: number;
|
|
602
|
+
id: string;
|
|
603
|
+
query: {
|
|
604
|
+
args?: Record<string, unknown>;
|
|
605
|
+
functionPath: string;
|
|
606
|
+
shardKey?: string;
|
|
607
|
+
};
|
|
608
|
+
/**
|
|
609
|
+
* Resume watermark: the highest chunk `seq` this client already received.
|
|
610
|
+
* Only meaningful for a stream the server declared `durable` — the run
|
|
611
|
+
* replays everything after it and then continues live, which is what turns
|
|
612
|
+
* a reconnect into a resume instead of a lost generation. Omitted on a
|
|
613
|
+
* first attach.
|
|
614
|
+
*
|
|
615
|
+
* Named `sinceChunk`, not `sinceSeq`, because a subscribe envelope already
|
|
616
|
+
* carries a `query.sinceSeq` meaning the CDC cursor.
|
|
617
|
+
*/
|
|
618
|
+
sinceChunk?: number;
|
|
619
|
+
type: "stream";
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* Join or leave a whisper `topic` — an app-chosen ephemeral channel scoped to a
|
|
623
|
+
* shard. While joined, the client receives every {@link ServerWhisperMessage}
|
|
624
|
+
* other members broadcast to the topic.
|
|
625
|
+
*/
|
|
626
|
+
interface ClientWhisperSubscribeMessage {
|
|
627
|
+
topic: string;
|
|
628
|
+
type: "whisper_subscribe" | "whisper_unsubscribe";
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* Broadcast ephemeral `data` to the topic's other members on the shard. The
|
|
632
|
+
* payload is relayed verbatim with no server-side persistence (no SQLite/CDC
|
|
633
|
+
* write) — for typing indicators, live cursors, presence pings. The sender does
|
|
634
|
+
* not receive its own whisper.
|
|
635
|
+
*/
|
|
636
|
+
interface ClientWhisperMessage {
|
|
637
|
+
data?: unknown;
|
|
638
|
+
topic: string;
|
|
639
|
+
type: "whisper";
|
|
640
|
+
}
|
|
641
|
+
type ClientMessage = ClientAckMessage | ClientConnectMessage | ClientShapeSubscribeMessage | ClientShapeUnsubscribeMessage | ClientStreamMessage | ClientSubscribeMessage | ClientUnsubscribeMessage | ClientWhisperMessage | ClientWhisperSubscribeMessage;
|
|
642
|
+
/** Subscription protocol — server → client. */
|
|
643
|
+
interface ServerDataMessage {
|
|
644
|
+
/**
|
|
645
|
+
* The `__cdc_log` high-watermark covered by this frame (Pillar 1b). The
|
|
646
|
+
* client persists it as the query's `serverCursor` and replays it as
|
|
647
|
+
* `sinceSeq` on the next reconnect. Absent on shards that never enabled CDC.
|
|
648
|
+
*/
|
|
649
|
+
cursor?: number;
|
|
650
|
+
data?: unknown;
|
|
651
|
+
delta?: unknown;
|
|
652
|
+
/** The CDC epoch this frame's cursor belongs to (see {@link CachedQuery.serverEpoch}). */
|
|
653
|
+
epoch?: string;
|
|
654
|
+
id: string;
|
|
655
|
+
/**
|
|
656
|
+
* The highest custom-mutator `mutationId` from this client the server has
|
|
657
|
+
* now applied (the per-client `__client_watermark`). Echoed so the client's
|
|
658
|
+
* outbox can drop confirmed pending mutations and let TanStack DB collapse
|
|
659
|
+
* the matching optimistic overlay. Absent on shards without custom mutators.
|
|
660
|
+
*/
|
|
661
|
+
lastMutationId?: number;
|
|
662
|
+
type: "data" | "delta";
|
|
663
|
+
}
|
|
664
|
+
/**
|
|
665
|
+
* Lightweight resume acknowledgement (Pillar 1b): the server determined that
|
|
666
|
+
* nothing the subscription reads changed since the client's `sinceSeq`, so it
|
|
667
|
+
* skips re-sending the snapshot. The client keeps its cached value and only
|
|
668
|
+
* advances `serverCursor` to `cursor`.
|
|
669
|
+
*/
|
|
670
|
+
interface ServerResumeMessage {
|
|
671
|
+
cursor?: number;
|
|
672
|
+
/** The CDC epoch this resume's cursor belongs to (see {@link CachedQuery.serverEpoch}). */
|
|
673
|
+
epoch?: string;
|
|
674
|
+
id: string;
|
|
675
|
+
/** Per-client custom-mutator watermark (see {@link ServerDataMessage.lastMutationId}). */
|
|
676
|
+
lastMutationId?: number;
|
|
677
|
+
type: "resume";
|
|
678
|
+
}
|
|
679
|
+
/**
|
|
680
|
+
* Settled acknowledgement for a **list** subscription: a write touched one of
|
|
681
|
+
* the subscription's read tables but produced a byte-identical result, so the
|
|
682
|
+
* server suppressed the data frame. Sent ONLY to a `@lunora/db` custom-mutator
|
|
683
|
+
* client (one that announced a `clientId`, hence has a server-side
|
|
684
|
+
* `__client_watermark`) so its optimistic list overlay drops even when no data
|
|
685
|
+
* frame arrives. Plain `useQuery` subscribers never receive it, and an older
|
|
686
|
+
* client safely ignores the unknown frame.
|
|
687
|
+
*/
|
|
688
|
+
interface ServerSettledMessage {
|
|
689
|
+
cursor?: number;
|
|
690
|
+
/** The CDC epoch this settled frame's cursor belongs to (see {@link CachedQuery.serverEpoch}). */
|
|
691
|
+
epoch?: string;
|
|
692
|
+
id: string;
|
|
693
|
+
/**
|
|
694
|
+
* The highest custom-mutator `mutationId` from this client the server has
|
|
695
|
+
* now applied (the per-client `__client_watermark`). Forwarded to a
|
|
696
|
+
* collection's `onCheckpoint` so it can drop the overlay for the confirmed
|
|
697
|
+
* write whose result didn't change this list.
|
|
698
|
+
*/
|
|
699
|
+
lastMutationId?: number;
|
|
700
|
+
type: "settled";
|
|
701
|
+
}
|
|
702
|
+
interface ServerErrorMessage {
|
|
703
|
+
error?: unknown;
|
|
704
|
+
id?: string;
|
|
705
|
+
message?: string;
|
|
706
|
+
type: "error";
|
|
707
|
+
}
|
|
708
|
+
interface ServerAckMessage {
|
|
709
|
+
id: string;
|
|
710
|
+
type: "ack";
|
|
711
|
+
}
|
|
712
|
+
interface ServerCompleteMessage {
|
|
713
|
+
id: string;
|
|
714
|
+
type: "complete";
|
|
715
|
+
}
|
|
716
|
+
/** One frame of a streaming query — `data` carries the user-yielded chunk. */
|
|
717
|
+
interface ServerChunkMessage {
|
|
718
|
+
data: unknown;
|
|
719
|
+
/**
|
|
720
|
+
* Generation stamp of the **durable** run this chunk belongs to. The client
|
|
721
|
+
* stores it beside {@link ServerChunkMessage.seq} and echoes it as
|
|
722
|
+
* {@link ClientStreamMessage.generation} on a resume, so the server can
|
|
723
|
+
* tell a genuine resume from an attempt to splice onto a different run
|
|
724
|
+
* under the same key. Absent on an ephemeral stream.
|
|
725
|
+
*/
|
|
726
|
+
generation?: number;
|
|
727
|
+
id: string;
|
|
728
|
+
/**
|
|
729
|
+
* Monotonic position of this chunk within a **durable** run, starting at 1.
|
|
730
|
+
* The client stores the last one it saw and replays it as
|
|
731
|
+
* {@link ClientStreamMessage.sinceChunk} when the socket comes back. Absent
|
|
732
|
+
* on an ephemeral stream, which has nothing to resume from.
|
|
733
|
+
*/
|
|
734
|
+
seq?: number;
|
|
735
|
+
type: "chunk";
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
738
|
+
* An ephemeral whisper relayed from another member of `topic` on the same shard
|
|
739
|
+
* (AnyCable-style whispering). `data` is the sender's payload verbatim; `from`
|
|
740
|
+
* is the sender's verified user id when known (absent for an anonymous sender).
|
|
741
|
+
* Never persisted server-side.
|
|
742
|
+
*/
|
|
743
|
+
interface ServerWhisperMessage {
|
|
744
|
+
data: unknown;
|
|
745
|
+
from?: string;
|
|
746
|
+
topic: string;
|
|
747
|
+
type: "whisper";
|
|
748
|
+
}
|
|
749
|
+
/**
|
|
750
|
+
* One row-level change in a shape's replication stream — the wire form of the
|
|
751
|
+
* DO's `__cdc_log` `CdcChange`. `insert`/`update` carry the post-image in
|
|
752
|
+
* `value` (projected to the shape's `columns`); `delete` omits it, identifying
|
|
753
|
+
* the removed row by `key` alone. The client applies these to its local
|
|
754
|
+
* collection; an unknown `key` on a `delete` is a safe no-op (a row the client
|
|
755
|
+
* never had in this shape).
|
|
756
|
+
*/
|
|
757
|
+
interface RowOp {
|
|
758
|
+
/** Row primary key (`_id`). */
|
|
759
|
+
key: string;
|
|
760
|
+
op: "delete" | "insert" | "update";
|
|
761
|
+
/** Logical table the row belongs to. */
|
|
762
|
+
table: string;
|
|
763
|
+
/** Post-image document for insert/update; absent on delete. */
|
|
764
|
+
value?: Record<string, unknown>;
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Opens a **poke** — an atomically-applied batch of shape diffs (Zero's poke
|
|
768
|
+
* protocol). A `pokeStart` is followed by zero or more {@link ServerPokePartMessage}
|
|
769
|
+
* frames and closed by exactly one {@link ServerPokeEndMessage}; the client
|
|
770
|
+
* buffers every part and applies them in a single transaction at `pokeEnd`, so a
|
|
771
|
+
* socket that drops mid-poke simply re-seeds on reconnect (no torn view).
|
|
772
|
+
*/
|
|
773
|
+
interface ServerPokeStartMessage {
|
|
774
|
+
/**
|
|
775
|
+
* Poke-level fallback base, stamped by single-part senders. Per-shape
|
|
776
|
+
* {@link ServerPokePartMessage.baseCheckpoint} takes precedence; this is what
|
|
777
|
+
* a part without its own base falls back to.
|
|
778
|
+
*/
|
|
779
|
+
baseCheckpoint?: number;
|
|
780
|
+
/** CDC epoch this poke belongs to; a mismatch forces the client to re-seed rather than apply. */
|
|
781
|
+
epoch?: string;
|
|
782
|
+
/** Correlates this poke's `pokeStart`/`pokePart`/`pokeEnd` frames. */
|
|
783
|
+
pokeId: string;
|
|
784
|
+
type: "pokeStart";
|
|
785
|
+
}
|
|
786
|
+
/** One shape's slice of an in-flight poke: the row-ops to apply for `shapeId`. */
|
|
787
|
+
interface ServerPokePartMessage {
|
|
788
|
+
/**
|
|
789
|
+
* The checkpoint this shape's view must be at for `rowsPatch` to splice on
|
|
790
|
+
* cleanly. Per shape, because every shape on a socket has its own
|
|
791
|
+
* delivered-through cursor. Absent when the server cannot name a base — the
|
|
792
|
+
* gap check is then disarmed for this part, never guessed at.
|
|
793
|
+
*/
|
|
794
|
+
baseCheckpoint?: number;
|
|
795
|
+
/** Per-client custom-mutator watermark carried with this slice (see {@link ServerSettledMessage.lastMutationId}). */
|
|
796
|
+
lastMutationId?: number;
|
|
797
|
+
pokeId: string;
|
|
798
|
+
/**
|
|
799
|
+
* `true` when `rowsPatch` is the shape's COMPLETE membership, not a diff (a
|
|
800
|
+
* full seed or re-seed). The client MUST drop its current view for this shape
|
|
801
|
+
* before applying: a seed is inserts-only, so merging it leaves any row that
|
|
802
|
+
* left the shape while the client was disconnected on screen forever.
|
|
803
|
+
*
|
|
804
|
+
* Never inferred from an absent {@link ServerPokePartMessage.baseCheckpoint} —
|
|
805
|
+
* most live poke paths legitimately carry no base.
|
|
806
|
+
*/
|
|
807
|
+
reset?: boolean;
|
|
808
|
+
/** Ordered row-level changes for this shape, applied in sequence at `pokeEnd`. */
|
|
809
|
+
rowsPatch: RowOp[];
|
|
810
|
+
/** The {@link ClientShapeSubscribeMessage.id} these row-ops belong to. */
|
|
811
|
+
shapeId: string;
|
|
812
|
+
type: "pokePart";
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Closes a poke: the client commits the buffered parts atomically and advances
|
|
816
|
+
* its checkpoint to {@link ServerPokeEndMessage.checkpoint} (the `__cdc_log`
|
|
817
|
+
* cursor high-watermark the view now reflects), replayed as `sinceCheckpoint` on
|
|
818
|
+
* the next reconnect.
|
|
819
|
+
*/
|
|
820
|
+
interface ServerPokeEndMessage {
|
|
821
|
+
/** The `__cdc_log` cursor the view is at after applying this poke. */
|
|
822
|
+
checkpoint?: number;
|
|
823
|
+
/** CDC epoch the {@link ServerPokeEndMessage.checkpoint} belongs to. */
|
|
824
|
+
epoch?: string;
|
|
825
|
+
pokeId: string;
|
|
826
|
+
type: "pokeEnd";
|
|
827
|
+
}
|
|
828
|
+
type ServerMessage = ServerAckMessage | ServerChunkMessage | ServerCompleteMessage | ServerDataMessage | ServerErrorMessage | ServerPokeEndMessage | ServerPokePartMessage | ServerPokeStartMessage | ServerResumeMessage | ServerSettledMessage | ServerWhisperMessage;
|
|
829
|
+
/**
|
|
830
|
+
* The authenticated user as exposed client-side, mirroring better-auth's
|
|
831
|
+
* `user` row (the `user` field of the `get-session` response). Kept minimal
|
|
832
|
+
* and structural — only `id` is guaranteed; the rest are the common better-auth
|
|
833
|
+
* fields, and the index signature carries any plugin-contributed extras.
|
|
834
|
+
*/
|
|
835
|
+
interface User {
|
|
836
|
+
readonly createdAt?: NullableTimestamp;
|
|
837
|
+
readonly email?: null | string;
|
|
838
|
+
readonly emailVerified?: boolean | null;
|
|
839
|
+
readonly id: string;
|
|
840
|
+
readonly image?: null | string;
|
|
841
|
+
readonly name?: null | string;
|
|
842
|
+
readonly [key: string]: unknown;
|
|
843
|
+
readonly updatedAt?: NullableTimestamp;
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
* Per-job retry policy carried on a {@link ScheduleRecord}. Mirrors
|
|
847
|
+
* `@lunora/scheduler`'s `RetryPolicy`; absent means the scheduler's defaults.
|
|
848
|
+
*/
|
|
849
|
+
interface ScheduleRetryPolicy {
|
|
850
|
+
/** Backoff growth across attempts. Default `"exponential"`. */
|
|
851
|
+
backoff?: "exponential" | "linear";
|
|
852
|
+
/** Base delay in milliseconds for the first retry. Default `30_000`. */
|
|
853
|
+
baseMs?: number;
|
|
854
|
+
/** Maximum number of dispatch attempts before dead-lettering. Default `5`. */
|
|
855
|
+
maxAttempts?: number;
|
|
856
|
+
/** Optional ceiling clamping the computed backoff delay. */
|
|
857
|
+
maxMs?: number;
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* One pending scheduled function, as returned by the worker's
|
|
861
|
+
* `GET /_lunora/admin/scheduled` endpoint. The route is a byte-for-byte proxy of
|
|
862
|
+
* the SchedulerDO's own `/list`, so this mirrors `@lunora/scheduler`'s
|
|
863
|
+
* `ScheduleRecord` field-for-field — structurally, so the client carries no
|
|
864
|
+
* dependency on it. `packages/client/__tests__/structural-mirrors.test.ts` fails
|
|
865
|
+
* when the two drift.
|
|
866
|
+
*/
|
|
867
|
+
interface ScheduleRecord {
|
|
868
|
+
args: Record<string, unknown>;
|
|
869
|
+
/**
|
|
870
|
+
* Dispatch attempts already made. Absent (treated as 0) until the first
|
|
871
|
+
* failure; on a dead-letter record it is the exhausted count (> the retry
|
|
872
|
+
* budget). Surfaced so the studio can show how hard a job tried before it
|
|
873
|
+
* was parked.
|
|
874
|
+
*/
|
|
875
|
+
attempts?: number;
|
|
876
|
+
enqueuedAt: number;
|
|
877
|
+
/**
|
|
878
|
+
* The `ns:fn` path dispatched on fire. Absent when the job targets a durable
|
|
879
|
+
* workflow/agent instead — exactly one of `functionPath` /
|
|
880
|
+
* {@link ScheduleRecord.workflow} is set, so a view rendering a job's target
|
|
881
|
+
* must fall back to `workflow` rather than assuming a path.
|
|
882
|
+
*/
|
|
883
|
+
functionPath?: string;
|
|
884
|
+
id: string;
|
|
885
|
+
/** Scheduler/workpool instance the job was enqueued through. Absent for the default instance. */
|
|
886
|
+
instanceName?: string;
|
|
887
|
+
/** Logical workpool the job is routed to (concurrency-gated), when any. */
|
|
888
|
+
pool?: string;
|
|
889
|
+
/** Per-job retry policy; absent means the scheduler's built-in defaults. */
|
|
890
|
+
retry?: ScheduleRetryPolicy;
|
|
891
|
+
scheduledFor: number;
|
|
892
|
+
shardKey?: string;
|
|
893
|
+
/**
|
|
894
|
+
* The `WORKFLOW_*`/`AGENT_*` binding a fresh durable instance is started from
|
|
895
|
+
* on fire (the {@link ScheduleRecord.args} become its `params`). Set instead
|
|
896
|
+
* of {@link ScheduleRecord.functionPath}.
|
|
897
|
+
*/
|
|
898
|
+
workflow?: string;
|
|
899
|
+
}
|
|
900
|
+
/**
|
|
901
|
+
* One workpool's live backlog, as returned by the worker's
|
|
902
|
+
* `GET /_lunora/admin/scheduled/status` endpoint. Mirrors `@lunora/scheduler`'s
|
|
903
|
+
* `SchedulerPoolStatus` structurally so the client carries no dependency on it.
|
|
904
|
+
*/
|
|
905
|
+
interface SchedulerPoolStatus {
|
|
906
|
+
/** Jobs currently dispatched-but-not-yet-completed (the held concurrency slots). */
|
|
907
|
+
inFlight: number;
|
|
908
|
+
/** The pool's concurrency cap. */
|
|
909
|
+
maxConcurrency: number;
|
|
910
|
+
/** The logical workpool name. */
|
|
911
|
+
name: string;
|
|
912
|
+
/** Pending jobs routed to this pool but not yet dispatched. */
|
|
913
|
+
queued: number;
|
|
914
|
+
}
|
|
915
|
+
/**
|
|
916
|
+
* The app-level scheduler backlog, as returned by the worker's
|
|
917
|
+
* `GET /_lunora/admin/scheduled/status` endpoint. `pools` is the per-pool
|
|
918
|
+
* breakdown; `backlog` and `inFlight` are the app-wide sums of `queued` and
|
|
919
|
+
* `inFlight` across every pool — the headline numbers for the studio SLO
|
|
920
|
+
* view. Mirrors `@lunora/scheduler`'s `SchedulerStatus` structurally.
|
|
921
|
+
*/
|
|
922
|
+
interface SchedulerStatus {
|
|
923
|
+
/** Sum of every pool's `queued` count — the total pending backlog. */
|
|
924
|
+
backlog: number;
|
|
925
|
+
/** Sum of every pool's `inFlight` count — the total held concurrency slots. */
|
|
926
|
+
inFlight: number;
|
|
927
|
+
/** Per-pool backlog breakdown. */
|
|
928
|
+
pools: SchedulerPoolStatus[];
|
|
929
|
+
}
|
|
930
|
+
/**
|
|
931
|
+
* One shard's request volume, as returned by the worker's
|
|
932
|
+
* `POST /_lunora/admin/shard-traffic` endpoint. The cross-shard traffic feed
|
|
933
|
+
* the studio's `hot_shard` advisor lint consumes: `requests` is the shard's
|
|
934
|
+
* lifetime dispatch total, `shardKey` the DO id name (`""` for the root shard).
|
|
935
|
+
*/
|
|
936
|
+
interface ShardTrafficEntry {
|
|
937
|
+
requests: number;
|
|
938
|
+
shardKey: string;
|
|
939
|
+
}
|
|
940
|
+
/**
|
|
941
|
+
* The whole-shard-set traffic distribution returned by the worker's
|
|
942
|
+
* `POST /_lunora/admin/shard-traffic` endpoint. `shards` is one entry per live
|
|
943
|
+
* shard (a failed shard surfaces with `requests: 0`); `ok`/`failed` count the
|
|
944
|
+
* shards that returned vs. errored. Shaped to feed the advisor's `hot_shard`
|
|
945
|
+
* lint after the studio tags each entry with its sharded function `group`.
|
|
946
|
+
*/
|
|
947
|
+
interface ShardTrafficResult {
|
|
948
|
+
failed: number;
|
|
949
|
+
ok: number;
|
|
950
|
+
shards: ShardTrafficEntry[];
|
|
951
|
+
}
|
|
952
|
+
/**
|
|
953
|
+
* One object in the storage bucket, as returned by the worker's
|
|
954
|
+
* `GET /_lunora/admin/storage` endpoint. Mirrors `@lunora/storage`'s
|
|
955
|
+
* `R2ObjectLike` structurally.
|
|
956
|
+
*/
|
|
957
|
+
interface StorageObject {
|
|
958
|
+
customMetadata?: Record<string, string>;
|
|
959
|
+
etag: string;
|
|
960
|
+
httpMetadata?: {
|
|
961
|
+
contentType?: string;
|
|
962
|
+
};
|
|
963
|
+
key: string;
|
|
964
|
+
size: number;
|
|
965
|
+
/**
|
|
966
|
+
* When the object was stored. R2 emits a `Date`, which JSON-serializes to an
|
|
967
|
+
* ISO string over the wire; a mock may supply epoch ms — so consumers should
|
|
968
|
+
* normalise via `new Date(uploaded)`. Absent if the backend didn't report it.
|
|
969
|
+
*/
|
|
970
|
+
uploaded?: number | string;
|
|
971
|
+
}
|
|
972
|
+
/** One page of {@link StorageObject}s plus the cursor to fetch the next, if any. */
|
|
973
|
+
interface StorageListPage {
|
|
974
|
+
cursor?: string;
|
|
975
|
+
objects: StorageObject[];
|
|
976
|
+
}
|
|
977
|
+
/**
|
|
978
|
+
* One argument of a registered function, derived from its `v.*` validator by the
|
|
979
|
+
* worker. A compact signature shape — enough to render a function's API without
|
|
980
|
+
* the build-time codegen types.
|
|
981
|
+
*/
|
|
982
|
+
interface FunctionArgumentDescriptor {
|
|
983
|
+
/** Element validator kind for an `array` arg (one level), e.g. `string`. */
|
|
984
|
+
element?: string;
|
|
985
|
+
/** The (optional-unwrapped) validator kind, e.g. `string`, `id`, `object`. */
|
|
986
|
+
kind: string;
|
|
987
|
+
/** The argument name. */
|
|
988
|
+
name: string;
|
|
989
|
+
/** True when the arg is wrapped in `v.optional(...)`. */
|
|
990
|
+
optional: boolean;
|
|
991
|
+
/** Target table for an `id` arg (`v.id("table")`). */
|
|
992
|
+
table?: string;
|
|
993
|
+
}
|
|
994
|
+
/**
|
|
995
|
+
* One registered function, as returned by the worker's
|
|
996
|
+
* `GET /_lunora/admin/functions` endpoint: its `<file>:<function>` path, which
|
|
997
|
+
* client method (`query` / `mutation` / `action`) invokes it, and its argument
|
|
998
|
+
* signature. `args` is absent on responses from an older worker.
|
|
999
|
+
*/
|
|
1000
|
+
interface FunctionDescriptor {
|
|
1001
|
+
args?: FunctionArgumentDescriptor[];
|
|
1002
|
+
kind: "action" | "mutation" | "query";
|
|
1003
|
+
path: string;
|
|
1004
|
+
}
|
|
1005
|
+
/** A `.global()` (D1-backed) table plus its row count, from `/_lunora/admin/global/tables`. */
|
|
1006
|
+
interface GlobalTableInfo {
|
|
1007
|
+
name: string;
|
|
1008
|
+
rowCount: number;
|
|
1009
|
+
}
|
|
1010
|
+
/** A window of rows from one global table, from `/_lunora/admin/global/table`. */
|
|
1011
|
+
interface GlobalTablePage {
|
|
1012
|
+
columns: string[];
|
|
1013
|
+
/** FK columns (local column → referenced table) for external tables with real `REFERENCES` constraints, from `PRAGMA foreign_key_list`. */
|
|
1014
|
+
refs?: Record<string, string>;
|
|
1015
|
+
rows: Record<string, unknown>[];
|
|
1016
|
+
total: number;
|
|
1017
|
+
}
|
|
1018
|
+
/**
|
|
1019
|
+
* One equality constraint a facet-value click adds to the global browser's view
|
|
1020
|
+
* (`column = value`). `value` is the raw stored scalar the facet returned, sent
|
|
1021
|
+
* as-is and bound server-side, so it never injects SQL.
|
|
1022
|
+
*/
|
|
1023
|
+
interface GlobalFilterClause {
|
|
1024
|
+
column: string;
|
|
1025
|
+
value: unknown;
|
|
1026
|
+
}
|
|
1027
|
+
/** One distinct value of a faceted global column with its row count, from `/_lunora/admin/global/facet`. */
|
|
1028
|
+
interface GlobalFacetValue {
|
|
1029
|
+
count: number;
|
|
1030
|
+
value: unknown;
|
|
1031
|
+
}
|
|
1032
|
+
/** Per-column distinct-value summary for the global browser, from `/_lunora/admin/global/facet`. */
|
|
1033
|
+
interface GlobalFacetResult {
|
|
1034
|
+
truncated: boolean;
|
|
1035
|
+
values: GlobalFacetValue[];
|
|
1036
|
+
}
|
|
1037
|
+
/** A nullable timestamp field as better-auth serializes it: epoch-ms, ISO string, or null. */
|
|
1038
|
+
type NullableTimestamp = null | number | string;
|
|
1039
|
+
/** A workflow instance's lifecycle status. Mirrors Cloudflare's `InstanceStatus`. */
|
|
1040
|
+
type WorkflowInstanceStatus = "complete" | "errored" | "paused" | "queued" | "running" | "terminated" | "unknown" | "waiting" | "waitingForPause";
|
|
1041
|
+
/** The lifecycle mutations the status endpoint accepts. */
|
|
1042
|
+
type WorkflowInstanceAction = "pause" | "resume" | "terminate";
|
|
1043
|
+
/** One row of the workflow-instances list. */
|
|
1044
|
+
interface WorkflowInstanceSummary {
|
|
1045
|
+
createdOn?: string;
|
|
1046
|
+
endedOn?: string;
|
|
1047
|
+
id: string;
|
|
1048
|
+
startedOn?: string;
|
|
1049
|
+
status: WorkflowInstanceStatus;
|
|
1050
|
+
}
|
|
1051
|
+
/** One durable step of an instance's execution timeline. */
|
|
1052
|
+
interface WorkflowStepDetail {
|
|
1053
|
+
/** 1-based attempt count (`> 1` means the step retried). */
|
|
1054
|
+
attempts?: number;
|
|
1055
|
+
end?: string;
|
|
1056
|
+
error?: unknown;
|
|
1057
|
+
name: string;
|
|
1058
|
+
output?: unknown;
|
|
1059
|
+
start?: string;
|
|
1060
|
+
success?: boolean;
|
|
1061
|
+
/** `step` / `sleep` / `waitForEvent` / … (Cloudflare's step `type`). */
|
|
1062
|
+
type?: string;
|
|
1063
|
+
}
|
|
1064
|
+
/** A workflow instance's full detail: summary plus params/output/error and the step timeline. */
|
|
1065
|
+
interface WorkflowInstanceDetail extends WorkflowInstanceSummary {
|
|
1066
|
+
error?: unknown;
|
|
1067
|
+
output?: unknown;
|
|
1068
|
+
params?: unknown;
|
|
1069
|
+
steps: WorkflowStepDetail[];
|
|
1070
|
+
}
|
|
1071
|
+
/** A page of workflow instances. */
|
|
1072
|
+
interface WorkflowInstancePage {
|
|
1073
|
+
/**
|
|
1074
|
+
* Whether workflow inspection is configured on the worker (a Cloudflare
|
|
1075
|
+
* account id + API token). `false` when the admin proxy reports it can't
|
|
1076
|
+
* inspect instances; omitted (treated as configured) otherwise. Lets a
|
|
1077
|
+
* caller render a "set credentials" state without a failed request.
|
|
1078
|
+
*/
|
|
1079
|
+
configured?: boolean;
|
|
1080
|
+
instances: WorkflowInstanceSummary[];
|
|
1081
|
+
page: number;
|
|
1082
|
+
perPage: number;
|
|
1083
|
+
totalCount?: number;
|
|
1084
|
+
}
|
|
93
1085
|
type SubscriptionCallback = (data: unknown) => void;
|
|
94
1086
|
/** A subscription-scoped error the server pushed for this subscription id. */
|
|
95
1087
|
interface SubscriptionError {
|
|
@@ -1432,8 +2424,15 @@ declare class LunoraClient {
|
|
|
1432
2424
|
/**
|
|
1433
2425
|
* Read a page of rows from one `.global()` table. `filters` AND-narrows the
|
|
1434
2426
|
* page to rows matching each `column = value` eq constraint — the drill-down a
|
|
1435
|
-
* facet-value click applies; the array is JSON-encoded into the
|
|
1436
|
-
* query param and the values are bound server-side.
|
|
2427
|
+
* facet-value click applies; the array is wire-encoded, JSON-encoded into the
|
|
2428
|
+
* `filters` query param, and the values are bound server-side.
|
|
2429
|
+
*
|
|
2430
|
+
* The response is `decodeWire`d. The worker encodes it (`readGlobalTablePage`
|
|
2431
|
+
* in `@lunora/d1`) because JSON cannot carry a `v.bigint()` column at all and
|
|
2432
|
+
* silently flattens a `v.bytes()` one to `{}` — so without the decode here the
|
|
2433
|
+
* grid renders the raw 3-element tagged array instead of the value. The shard
|
|
2434
|
+
* browser's twin already pairs the same way through `rpc`; this is the global
|
|
2435
|
+
* half of that symmetry.
|
|
1437
2436
|
*/
|
|
1438
2437
|
readGlobalTablePage(options: {
|
|
1439
2438
|
filters?: GlobalFilterClause[];
|
|
@@ -1447,6 +2446,12 @@ declare class LunoraClient {
|
|
|
1447
2446
|
* twin of the shard browser's facet. Hits the admin-gated
|
|
1448
2447
|
* `GET /_lunora/admin/global/facet` endpoint; `column` is validated + bound
|
|
1449
2448
|
* server-side. Powers the global data browser's facet sidebar.
|
|
2449
|
+
*
|
|
2450
|
+
* Wire-encoded/decoded on both legs for the same reason
|
|
2451
|
+
* {@link LunoraClient.readGlobalTablePage} is: a facet over a BLOB column
|
|
2452
|
+
* returns bytes, which `Response.json` flattens to `{}` — and since a facet
|
|
2453
|
+
* value is exactly what a click sends back as a `filters` clause, that is a
|
|
2454
|
+
* broken drill-down rather than a display glitch.
|
|
1450
2455
|
*/
|
|
1451
2456
|
facetGlobalColumn(options: {
|
|
1452
2457
|
column: string;
|
|
@@ -2462,4 +3467,4 @@ declare class LunoraClient {
|
|
|
2462
3467
|
*/
|
|
2463
3468
|
private settleReplayBatchSlots;
|
|
2464
3469
|
}
|
|
2465
|
-
export { ActionCallOptions as A,
|
|
3470
|
+
export { ServerPokePartMessage 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, RowOp as K, LunoraClient as L, MutationCallOptions as M, RpcEnvelope as N, OfflineQueueOptions as O, Preloaded as P, QueryCacheAdapter as Q, ReconnectOptions as R, SubscriptionError as S, RpcResponseBody as T, User as U, ScheduleRecord as V, ScheduleRetryPolicy 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, StoredQuery as a5, StreamHandle as a6, SubscriptionCallback as a7, SubscriptionRegistry as a8, SubscriptionState as a9, SyncWatermark as aa, WorkflowInstanceAction as ab, WorkflowInstanceDetail as ac, WorkflowInstancePage as ad, WorkflowInstanceStatus as ae, WorkflowInstanceSummary as af, WorkflowStepDetail as ag, WsTokenProvider as ah, createClientQuery as ai, createLocalStore as aj, createStream as ak, 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 };
|