@lunora/client 1.0.0-alpha.3 → 1.0.0-alpha.5
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/README.md +2 -0
- package/dist/auth/index.d.mts +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/index.d.mts +67 -4
- package/dist/index.d.ts +67 -4
- package/dist/index.mjs +4 -3
- package/dist/packem_shared/{LunoraClient-UiULzH_1.mjs → LunoraClient-BPQx0T7W.mjs} +393 -61
- package/dist/packem_shared/{OfflineQueue-D5p_QgF_.mjs → OfflineQueue-D-ASeqL7.mjs} +5 -1
- package/dist/packem_shared/SubscriptionRegistry-Dn-7k7eo.mjs +1 -0
- package/dist/packem_shared/createMutatorRunner-BETvCd0p.mjs +31 -0
- package/dist/packem_shared/{createServerClient-BjZc3gD8.mjs → createServerClient-BgzEOQ46.mjs} +1 -1
- package/dist/packem_shared/{lunora-client.d-DGvyuJ_p.d.mts → lunora-client.d-CL9inoxa.d.mts} +354 -10
- package/dist/packem_shared/{lunora-client.d-DGvyuJ_p.d.ts → lunora-client.d-CL9inoxa.d.ts} +354 -10
- package/dist/packem_shared/{preload.d-BoDmFqSG.d.ts → preload.d-B0O7Zm9z.d.ts} +1 -1
- package/dist/packem_shared/{preload.d-dSaRMuhL.d.mts → preload.d-Da_yjk6L.d.mts} +1 -1
- package/dist/packem_shared/subscription-C1Jy7HiF.mjs +55 -0
- package/dist/query/index.d.mts +2 -2
- package/dist/query/index.d.ts +2 -2
- package/dist/ssr/index.d.mts +3 -3
- package/dist/ssr/index.d.ts +3 -3
- package/dist/ssr/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/packem_shared/SubscriptionRegistry-B-Qx_Gux.mjs +0 -26
|
@@ -120,6 +120,40 @@ interface PersistenceAdapter {
|
|
|
120
120
|
remove: (id: string) => Promise<void>;
|
|
121
121
|
}
|
|
122
122
|
/**
|
|
123
|
+
* One write handed to an {@link OutboxSink}. Mirrors {@link PersistedMutation}
|
|
124
|
+
* plus the custom-mutator identity (`clientId`/`mutationId`/`idempotencyKey`)
|
|
125
|
+
* the durable outbox needs to dedupe and watermark replays.
|
|
126
|
+
*/
|
|
127
|
+
interface OutboxMutation {
|
|
128
|
+
args: Record<string, unknown>;
|
|
129
|
+
/** Stable per-client id; pairs with {@link OutboxMutation.mutationId} as `idempotencyKey`. */
|
|
130
|
+
clientId: string;
|
|
131
|
+
functionPath: string;
|
|
132
|
+
/** `${clientId}:${mutationId}` — sent as `x-lunora-mutation-id` so a replay is server-idempotent. */
|
|
133
|
+
idempotencyKey: string;
|
|
134
|
+
/** Issuing identity fingerprint (`null` = signed out); drives the sink's identity guard. */
|
|
135
|
+
identity: string | null;
|
|
136
|
+
/** Monotonic per-client mutation id, backing the server `__client_watermark`. */
|
|
137
|
+
mutationId: number;
|
|
138
|
+
shardKey?: string;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Pluggable durable outbox seam. When set on {@link LunoraClientOptions.outbox},
|
|
142
|
+
* the client delegates offline write durability + at-least-once replay to this
|
|
143
|
+
* sink instead of its built-in {@link PersistenceAdapter}-backed `OfflineQueue`.
|
|
144
|
+
* `@lunora/db` supplies the blessed implementation (`createExecutorOutboxSink`,
|
|
145
|
+
* backed by the TanStack `OfflineExecutor`); the interface itself is
|
|
146
|
+
* dependency-free so `@lunora/client` stays TanStack-free.
|
|
147
|
+
*/
|
|
148
|
+
interface OutboxSink {
|
|
149
|
+
/**
|
|
150
|
+
* Persist and schedule a write for replay. Rejects with an
|
|
151
|
+
* `OFFLINE_QUEUE_OVERFLOW`-coded error when the sink's cap is exceeded, so
|
|
152
|
+
* the caller can surface back-pressure to the issuing mutation.
|
|
153
|
+
*/
|
|
154
|
+
enqueue: (mutation: OutboxMutation) => Promise<void>;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
123
157
|
* One persisted query result in the durable read cache (Pillar 2). Keyed in the
|
|
124
158
|
* store by `shardKey + functionPath + argsKey`; the record carries everything
|
|
125
159
|
* needed to render offline on reload and to resume the live subscription.
|
|
@@ -177,6 +211,16 @@ interface LunoraClientOptions {
|
|
|
177
211
|
authBasePath?: string;
|
|
178
212
|
bookmarkStorage?: BookmarkStorage;
|
|
179
213
|
/**
|
|
214
|
+
* Stable per-client id backing the custom-mutator watermark. Sent on the
|
|
215
|
+
* `connect` envelope (so the server can scope this client's
|
|
216
|
+
* `__client_watermark`) and stamped onto every {@link OutboxMutation} the
|
|
217
|
+
* {@link LunoraClientOptions.outbox} sink persists, where it pairs with the
|
|
218
|
+
* monotonic mutation id to form the idempotency key. The `@lunora/db` path
|
|
219
|
+
* persists a stable id alongside the outbox and passes it here; omit for the
|
|
220
|
+
* standalone client, which generates an ephemeral per-session id.
|
|
221
|
+
*/
|
|
222
|
+
clientId?: string;
|
|
223
|
+
/**
|
|
180
224
|
* Default app context sent in the `connect` envelope right after each socket
|
|
181
225
|
* opens, forwarded to the server's `onConnect`/`onDisconnect` lifecycle hooks
|
|
182
226
|
* as `event.context`. A per-shard context registered via
|
|
@@ -184,6 +228,16 @@ interface LunoraClientOptions {
|
|
|
184
228
|
* hook needs connection context.
|
|
185
229
|
*/
|
|
186
230
|
connectionContext?: Record<string, unknown>;
|
|
231
|
+
/**
|
|
232
|
+
* Fail-fast timeout (ms) for opening a subscription WebSocket. If the
|
|
233
|
+
* handshake doesn't complete within this window — a hung dev proxy or a cold
|
|
234
|
+
* worker that never upgrades — the client force-closes the socket and routes
|
|
235
|
+
* through its normal reconnect/backoff (surfacing `offline` status) instead
|
|
236
|
+
* of leaving the live channel silently stuck on the browser's much longer
|
|
237
|
+
* default. Does not affect HTTP queries/mutations (those never ride the WS).
|
|
238
|
+
* Defaults to 10000 (10s); set to `0` (or negative) to disable.
|
|
239
|
+
*/
|
|
240
|
+
connectTimeoutMs?: number;
|
|
187
241
|
fetch?: typeof fetch;
|
|
188
242
|
/**
|
|
189
243
|
* Interval (ms) between keepalive pings sent on each open subscription
|
|
@@ -194,6 +248,14 @@ interface LunoraClientOptions {
|
|
|
194
248
|
*/
|
|
195
249
|
heartbeatIntervalMs?: number;
|
|
196
250
|
offlineQueue?: OfflineQueueOptions;
|
|
251
|
+
/**
|
|
252
|
+
* Durable outbox seam for offline writes. When supplied (the `@lunora/db`
|
|
253
|
+
* path wires `createExecutorOutboxSink`), offline mutations are delegated to
|
|
254
|
+
* the sink and the built-in {@link PersistenceAdapter}-backed `OfflineQueue`
|
|
255
|
+
* is bypassed, so a db app has exactly one durable write path. Omit for the
|
|
256
|
+
* standalone client, which keeps using {@link LunoraClientOptions.persistence}.
|
|
257
|
+
*/
|
|
258
|
+
outbox?: OutboxSink;
|
|
197
259
|
/** Durable store for the offline mutation queue; omit to keep it in memory. */
|
|
198
260
|
persistence?: PersistenceAdapter;
|
|
199
261
|
/**
|
|
@@ -222,17 +284,43 @@ interface LunoraClientOptions {
|
|
|
222
284
|
/** Wire envelope sent on `POST /_lunora/rpc`. */
|
|
223
285
|
interface RpcEnvelope {
|
|
224
286
|
args?: Record<string, unknown>;
|
|
287
|
+
/**
|
|
288
|
+
* Stable per-client identifier (custom-mutator push path). Pairs with
|
|
289
|
+
* {@link RpcEnvelope.mutationId} to form `idempotencyKey` and scope the
|
|
290
|
+
* server `__client_watermark`. Absent on plain `client.mutation` calls.
|
|
291
|
+
*/
|
|
292
|
+
clientId?: string;
|
|
225
293
|
functionPath: string;
|
|
294
|
+
/**
|
|
295
|
+
* Idempotency key (`${clientId}:${mutationId}`) for the custom-mutator push
|
|
296
|
+
* path, mirrored into the `x-lunora-mutation-id` header. Absent on plain
|
|
297
|
+
* `client.mutation` calls.
|
|
298
|
+
*/
|
|
299
|
+
idempotencyKey?: string;
|
|
300
|
+
/**
|
|
301
|
+
* Monotonic per-client mutation id (custom-mutator push path), backing the
|
|
302
|
+
* server-side per-client watermark: `id <= watermark` is a replay (skipped),
|
|
303
|
+
* `id == watermark + 1` runs authoritatively, `id > watermark + 1` halts the
|
|
304
|
+
* batch so the client resends from `watermark + 1`. Absent on plain
|
|
305
|
+
* `client.mutation` calls.
|
|
306
|
+
*/
|
|
307
|
+
mutationId?: number;
|
|
226
308
|
shardKey?: string;
|
|
227
309
|
}
|
|
228
|
-
/**
|
|
310
|
+
/**
|
|
311
|
+
* Wire response from the shard's `/rpc` endpoint (forwarded by the runtime). A
|
|
312
|
+
* watermarked custom-mutator push additionally carries `lastMutationId` — the
|
|
313
|
+
* highest per-client sequence the DO has applied — which the client uses to keep
|
|
314
|
+
* its `clientSeq` generator monotonic across reloads (see `LunoraClient.callMutator`).
|
|
315
|
+
*/
|
|
229
316
|
type RpcResponseBody = {
|
|
230
|
-
result: unknown;
|
|
231
|
-
} | {
|
|
232
317
|
error: {
|
|
233
318
|
code: string;
|
|
234
319
|
message: string;
|
|
235
320
|
};
|
|
321
|
+
} | {
|
|
322
|
+
lastMutationId?: number;
|
|
323
|
+
result: unknown;
|
|
236
324
|
};
|
|
237
325
|
/** Subscription protocol — client → server. */
|
|
238
326
|
interface ClientSubscribeMessage {
|
|
@@ -265,10 +353,51 @@ interface ClientUnsubscribeMessage {
|
|
|
265
353
|
* `onDisconnect` when the socket drops.
|
|
266
354
|
*/
|
|
267
355
|
interface ClientConnectMessage {
|
|
356
|
+
/**
|
|
357
|
+
* Stable per-client id (persisted alongside the outbox). Lets the server
|
|
358
|
+
* scope this connection's `__client_watermark` so custom-mutator pokes can
|
|
359
|
+
* echo the right per-client `lastMutationId`. Omitted by clients that don't
|
|
360
|
+
* use custom mutators.
|
|
361
|
+
*/
|
|
362
|
+
clientId?: string;
|
|
268
363
|
context?: Record<string, unknown>;
|
|
269
364
|
id: string;
|
|
270
365
|
type: "connect";
|
|
271
366
|
}
|
|
367
|
+
/**
|
|
368
|
+
* Subscribe to a declarative **shape** — server-side partial replication scoped
|
|
369
|
+
* by `shardBy` + the shape's predicate + RLS. The client sends the shape *name*
|
|
370
|
+
* + validated `args`; the server resolves the trusted `where` (identity/RLS
|
|
371
|
+
* `baseWhere` the client can't forge) and streams the matching rowset, then live
|
|
372
|
+
* {@link ServerPokePartMessage} diffs. `id` namespaces the subscription and is
|
|
373
|
+
* echoed as `shapeId` on every poke part.
|
|
374
|
+
*/
|
|
375
|
+
interface ClientShapeSubscribeMessage {
|
|
376
|
+
id: string;
|
|
377
|
+
shape: {
|
|
378
|
+
args?: Record<string, unknown>;
|
|
379
|
+
name: string;
|
|
380
|
+
};
|
|
381
|
+
/**
|
|
382
|
+
* Resume from this checkpoint (the `__cdc_log` cursor the client last
|
|
383
|
+
* applied for this shape). When absent or below the server's retained floor
|
|
384
|
+
* (`minCdcSeq`), the server re-seeds with a full insert-poke instead of a
|
|
385
|
+
* delta.
|
|
386
|
+
*/
|
|
387
|
+
sinceCheckpoint?: number;
|
|
388
|
+
/**
|
|
389
|
+
* The CDC epoch {@link ClientShapeSubscribeMessage.sinceCheckpoint} belongs
|
|
390
|
+
* to. A mismatch (forked changelog timeline) forces a full re-seed even when
|
|
391
|
+
* the cursor is numerically in range.
|
|
392
|
+
*/
|
|
393
|
+
sinceEpoch?: string;
|
|
394
|
+
type: "shape_subscribe";
|
|
395
|
+
}
|
|
396
|
+
/** Cancel a shape subscription started with the same `id`. */
|
|
397
|
+
interface ClientShapeUnsubscribeMessage {
|
|
398
|
+
id: string;
|
|
399
|
+
type: "shape_unsubscribe";
|
|
400
|
+
}
|
|
272
401
|
interface ClientAckMessage {
|
|
273
402
|
id: string;
|
|
274
403
|
type: "ack";
|
|
@@ -309,7 +438,7 @@ interface ClientWhisperMessage {
|
|
|
309
438
|
topic: string;
|
|
310
439
|
type: "whisper";
|
|
311
440
|
}
|
|
312
|
-
type ClientMessage = ClientAckMessage | ClientConnectMessage | ClientStreamMessage | ClientSubscribeMessage | ClientUnsubscribeMessage | ClientWhisperMessage | ClientWhisperSubscribeMessage;
|
|
441
|
+
type ClientMessage = ClientAckMessage | ClientConnectMessage | ClientShapeSubscribeMessage | ClientShapeUnsubscribeMessage | ClientStreamMessage | ClientSubscribeMessage | ClientUnsubscribeMessage | ClientWhisperMessage | ClientWhisperSubscribeMessage;
|
|
313
442
|
/** Subscription protocol — server → client. */
|
|
314
443
|
interface ServerDataMessage {
|
|
315
444
|
/**
|
|
@@ -323,6 +452,13 @@ interface ServerDataMessage {
|
|
|
323
452
|
/** The CDC epoch this frame's cursor belongs to (see {@link CachedQuery.serverEpoch}). */
|
|
324
453
|
epoch?: string;
|
|
325
454
|
id: string;
|
|
455
|
+
/**
|
|
456
|
+
* The highest custom-mutator `mutationId` from this client the server has
|
|
457
|
+
* now applied (the per-client `__client_watermark`). Echoed so the client's
|
|
458
|
+
* outbox can drop confirmed pending mutations and let TanStack DB collapse
|
|
459
|
+
* the matching optimistic overlay. Absent on shards without custom mutators.
|
|
460
|
+
*/
|
|
461
|
+
lastMutationId?: number;
|
|
326
462
|
type: "data" | "delta";
|
|
327
463
|
}
|
|
328
464
|
/**
|
|
@@ -336,6 +472,8 @@ interface ServerResumeMessage {
|
|
|
336
472
|
/** The CDC epoch this resume's cursor belongs to (see {@link CachedQuery.serverEpoch}). */
|
|
337
473
|
epoch?: string;
|
|
338
474
|
id: string;
|
|
475
|
+
/** Per-client custom-mutator watermark (see {@link ServerDataMessage.lastMutationId}). */
|
|
476
|
+
lastMutationId?: number;
|
|
339
477
|
type: "resume";
|
|
340
478
|
}
|
|
341
479
|
interface ServerErrorMessage {
|
|
@@ -370,7 +508,65 @@ interface ServerWhisperMessage {
|
|
|
370
508
|
topic: string;
|
|
371
509
|
type: "whisper";
|
|
372
510
|
}
|
|
373
|
-
|
|
511
|
+
/**
|
|
512
|
+
* One row-level change in a shape's replication stream — the wire form of the
|
|
513
|
+
* DO's `__cdc_log` `CdcChange`. `insert`/`update` carry the post-image in
|
|
514
|
+
* `value` (projected to the shape's `columns`); `delete` omits it, identifying
|
|
515
|
+
* the removed row by `key` alone. The client applies these to its local
|
|
516
|
+
* collection; an unknown `key` on a `delete` is a safe no-op (a row the client
|
|
517
|
+
* never had in this shape).
|
|
518
|
+
*/
|
|
519
|
+
interface RowOp {
|
|
520
|
+
/** Row primary key (`_id`). */
|
|
521
|
+
key: string;
|
|
522
|
+
op: "delete" | "insert" | "update";
|
|
523
|
+
/** Logical table the row belongs to. */
|
|
524
|
+
table: string;
|
|
525
|
+
/** Post-image document for insert/update; absent on delete. */
|
|
526
|
+
value?: Record<string, unknown>;
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Opens a **poke** — an atomically-applied batch of shape diffs (Zero's poke
|
|
530
|
+
* protocol). A `pokeStart` is followed by zero or more {@link ServerPokePartMessage}
|
|
531
|
+
* frames and closed by exactly one {@link ServerPokeEndMessage}; the client
|
|
532
|
+
* buffers every part and applies them in a single transaction at `pokeEnd`, so a
|
|
533
|
+
* socket that drops mid-poke simply re-seeds on reconnect (no torn view).
|
|
534
|
+
*/
|
|
535
|
+
interface ServerPokeStartMessage {
|
|
536
|
+
/** The checkpoint the client's view is expected to be at before this poke applies (for ordering/gap detection). */
|
|
537
|
+
baseCheckpoint?: number;
|
|
538
|
+
/** CDC epoch this poke belongs to; a mismatch forces the client to re-seed rather than apply. */
|
|
539
|
+
epoch?: string;
|
|
540
|
+
/** Correlates this poke's `pokeStart`/`pokePart`/`pokeEnd` frames. */
|
|
541
|
+
pokeId: string;
|
|
542
|
+
type: "pokeStart";
|
|
543
|
+
}
|
|
544
|
+
/** One shape's slice of an in-flight poke: the row-ops to apply for `shapeId`. */
|
|
545
|
+
interface ServerPokePartMessage {
|
|
546
|
+
/** Per-client custom-mutator watermark carried with this slice (see {@link ServerDataMessage.lastMutationId}). */
|
|
547
|
+
lastMutationId?: number;
|
|
548
|
+
pokeId: string;
|
|
549
|
+
/** Ordered row-level changes for this shape, applied in sequence at `pokeEnd`. */
|
|
550
|
+
rowsPatch: RowOp[];
|
|
551
|
+
/** The {@link ClientShapeSubscribeMessage.id} these row-ops belong to. */
|
|
552
|
+
shapeId: string;
|
|
553
|
+
type: "pokePart";
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Closes a poke: the client commits the buffered parts atomically and advances
|
|
557
|
+
* its checkpoint to {@link ServerPokeEndMessage.checkpoint} (the `__cdc_log`
|
|
558
|
+
* cursor high-watermark the view now reflects), replayed as `sinceCheckpoint` on
|
|
559
|
+
* the next reconnect.
|
|
560
|
+
*/
|
|
561
|
+
interface ServerPokeEndMessage {
|
|
562
|
+
/** The `__cdc_log` cursor the view is at after applying this poke. */
|
|
563
|
+
checkpoint?: number;
|
|
564
|
+
/** CDC epoch the {@link ServerPokeEndMessage.checkpoint} belongs to. */
|
|
565
|
+
epoch?: string;
|
|
566
|
+
pokeId: string;
|
|
567
|
+
type: "pokeEnd";
|
|
568
|
+
}
|
|
569
|
+
type ServerMessage = ServerAckMessage | ServerChunkMessage | ServerCompleteMessage | ServerDataMessage | ServerErrorMessage | ServerPokeEndMessage | ServerPokePartMessage | ServerPokeStartMessage | ServerResumeMessage | ServerWhisperMessage;
|
|
374
570
|
/**
|
|
375
571
|
* The authenticated user as exposed client-side, mirroring better-auth's
|
|
376
572
|
* `user` row (the `user` field of the `get-session` response). Kept minimal
|
|
@@ -582,6 +778,13 @@ interface WorkflowInstanceDetail extends WorkflowInstanceSummary {
|
|
|
582
778
|
}
|
|
583
779
|
/** A page of workflow instances. */
|
|
584
780
|
interface WorkflowInstancePage {
|
|
781
|
+
/**
|
|
782
|
+
* Whether workflow inspection is configured on the worker (a Cloudflare
|
|
783
|
+
* account id + API token). `false` when the admin proxy reports it can't
|
|
784
|
+
* inspect instances; omitted (treated as configured) otherwise. Lets a
|
|
785
|
+
* caller render a "set credentials" state without a failed request.
|
|
786
|
+
*/
|
|
787
|
+
configured?: boolean;
|
|
585
788
|
instances: WorkflowInstanceSummary[];
|
|
586
789
|
page: number;
|
|
587
790
|
perPage: number;
|
|
@@ -637,8 +840,11 @@ interface SubscriptionState {
|
|
|
637
840
|
}
|
|
638
841
|
/**
|
|
639
842
|
* Active subscription registry. The client keys subscriptions by
|
|
640
|
-
* `(functionPath,
|
|
641
|
-
* single server-side registration.
|
|
843
|
+
* `(functionPath, stableStringify(args), shardKey)` so duplicate calls share a
|
|
844
|
+
* single server-side registration. Args are stably encoded (keys sorted at every
|
|
845
|
+
* depth) so two structurally-equal arg records constructed with a different key
|
|
846
|
+
* order (`{ a, b }` vs `{ b, a }`) collapse to the same key instead of leaking a
|
|
847
|
+
* duplicate subscription.
|
|
642
848
|
*/
|
|
643
849
|
declare class SubscriptionRegistry {
|
|
644
850
|
static key(functionPath: string, args: Record<string, unknown>, shardKey?: string): string;
|
|
@@ -760,6 +966,13 @@ type ConnectionStatus = "connected" | "connecting" | "idle" | "offline";
|
|
|
760
966
|
* re-declaring it.
|
|
761
967
|
*/
|
|
762
968
|
interface MutationCallOptions<TCurrent = unknown, TValue = unknown, TArgs = unknown> {
|
|
969
|
+
/**
|
|
970
|
+
* Override the auto-generated idempotency key (`x-lunora-mutation-id`). Lets a
|
|
971
|
+
* durable outbox replay a committed-but-unacked write under its *original* key
|
|
972
|
+
* so the server dedups it instead of applying it twice. Omit for normal calls —
|
|
973
|
+
* each then gets a fresh key.
|
|
974
|
+
*/
|
|
975
|
+
mutationId?: string;
|
|
763
976
|
optimistic?: (current: TCurrent | undefined) => TValue;
|
|
764
977
|
/**
|
|
765
978
|
* Convex-parity multi-query optimistic update. Receives an
|
|
@@ -770,6 +983,19 @@ interface MutationCallOptions<TCurrent = unknown, TValue = unknown, TArgs = unkn
|
|
|
770
983
|
optimisticUpdate?: OptimisticUpdate<TArgs>;
|
|
771
984
|
shardKey?: string;
|
|
772
985
|
}
|
|
986
|
+
/** Callback a shape subscription invokes with its materialized rowset on every applied poke. */
|
|
987
|
+
type ShapeCallback = (rows: Record<string, unknown>[]) => void;
|
|
988
|
+
/**
|
|
989
|
+
* The high-water marks a shape poke has now synced to the client: `checkpoint`
|
|
990
|
+
* is the op-log cursor and `mutationId` the highest custom-mutator id the server
|
|
991
|
+
* echoed for this client. A `@lunora/db` collection feeds these into its
|
|
992
|
+
* checkpoint registry to drop optimistic overlays once the server's authoritative
|
|
993
|
+
* rows have landed.
|
|
994
|
+
*/
|
|
995
|
+
interface SyncWatermark {
|
|
996
|
+
checkpoint?: number;
|
|
997
|
+
mutationId?: number;
|
|
998
|
+
}
|
|
773
999
|
/**
|
|
774
1000
|
* Lunora browser/edge client. Talks RPC over HTTP and real-time deltas over
|
|
775
1001
|
* a single multiplexed WebSocket.
|
|
@@ -778,6 +1004,8 @@ interface MutationCallOptions<TCurrent = unknown, TValue = unknown, TArgs = unkn
|
|
|
778
1004
|
* see the package README for the wire protocol.
|
|
779
1005
|
*/
|
|
780
1006
|
declare class LunoraClient {
|
|
1007
|
+
/** 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. */
|
|
1008
|
+
private static readonly MAX_POKE_BUFFERS;
|
|
781
1009
|
readonly url: string;
|
|
782
1010
|
readonly wsUrl: string;
|
|
783
1011
|
private wsToken;
|
|
@@ -787,9 +1015,30 @@ declare class LunoraClient {
|
|
|
787
1015
|
private readonly WebSocketImpl;
|
|
788
1016
|
private readonly bookmark;
|
|
789
1017
|
private readonly reconnectOptions;
|
|
1018
|
+
/** WS connect timeout (ms); `0` disables it. See {@link LunoraClientOptions.connectTimeoutMs}. */
|
|
1019
|
+
private readonly connectTimeoutMs;
|
|
790
1020
|
/** Keepalive cadence (ms); `0` disables the heartbeat. See {@link LunoraClientOptions.heartbeatIntervalMs}. */
|
|
791
1021
|
private readonly heartbeatIntervalMs;
|
|
792
1022
|
private readonly offlineQueue;
|
|
1023
|
+
/**
|
|
1024
|
+
* Durable outbox seam (the `@lunora/db` `createExecutorOutboxSink`). When
|
|
1025
|
+
* set, offline writes are delegated here and the built-in {@link OfflineQueue}
|
|
1026
|
+
* is bypassed, so a db app has exactly one durable write path.
|
|
1027
|
+
*/
|
|
1028
|
+
private readonly outbox;
|
|
1029
|
+
/** Stable per-client id stamped onto every `OutboxMutation` (custom-mutator watermark). */
|
|
1030
|
+
private readonly clientId;
|
|
1031
|
+
/**
|
|
1032
|
+
* Highest custom-mutator watermark the server has echoed for this client,
|
|
1033
|
+
* keyed by shard bucket (`shardKey ?? ""`) since the DO tracks one
|
|
1034
|
+
* `__client_watermark` per shard. `callMutator` bumps it from every
|
|
1035
|
+
* ack; the `@lunora/db` mutator runtime seeds its `clientSeq` generator from
|
|
1036
|
+
* it so a reload (which resets the in-memory counter) never reissues a stale
|
|
1037
|
+
* sequence the server would silently swallow as a replay.
|
|
1038
|
+
*/
|
|
1039
|
+
private readonly clientWatermarks;
|
|
1040
|
+
/** Monotonic per-client mutation counter backing the server `__client_watermark`. */
|
|
1041
|
+
private outboxMutationCounter;
|
|
793
1042
|
private readonly onPersistenceError;
|
|
794
1043
|
private readonly persistence;
|
|
795
1044
|
/** Durable read cache (Pillar 2); `undefined` when `queryCache` is omitted or `false`. */
|
|
@@ -866,6 +1115,11 @@ declare class LunoraClient {
|
|
|
866
1115
|
* calls `.cancel()` or the iterator is garbage-collected.
|
|
867
1116
|
*/
|
|
868
1117
|
private readonly streams;
|
|
1118
|
+
/** Live shape subscriptions (partial replication), keyed by their wire id. */
|
|
1119
|
+
private readonly shapeSubscriptions;
|
|
1120
|
+
/** In-flight pokes being assembled between `pokeStart` and `pokeEnd`, keyed by `pokeId`. */
|
|
1121
|
+
private readonly pokeBuffers;
|
|
1122
|
+
private nextShapeId;
|
|
869
1123
|
constructor(options: LunoraClientOptions);
|
|
870
1124
|
/**
|
|
871
1125
|
* Set (or clear) the bearer token sent on every HTTP RPC. Notifies any
|
|
@@ -880,6 +1134,47 @@ declare class LunoraClient {
|
|
|
880
1134
|
setAuthToken(token: string | null): void;
|
|
881
1135
|
getAuthToken(): string | null;
|
|
882
1136
|
/**
|
|
1137
|
+
* The current identity fingerprint (the same stamp queued offline writes
|
|
1138
|
+
* carry). Exposed so a durable {@link OutboxSink}'s replay handler — which
|
|
1139
|
+
* owns its own at-least-once replay outside the built-in `OfflineQueue` —
|
|
1140
|
+
* can drop a persisted write whose captured `identity` no longer matches the
|
|
1141
|
+
* signed-in user, the guard the queue path applies in `flushOfflineQueue`.
|
|
1142
|
+
*/
|
|
1143
|
+
currentIdentity(): string | null;
|
|
1144
|
+
/** This client's stable identifier — the watermark key the server's custom-mutator protocol advances per `clientSeq`. */
|
|
1145
|
+
clientIdentifier(): string;
|
|
1146
|
+
/**
|
|
1147
|
+
* The highest custom-mutator watermark the server has echoed for this client
|
|
1148
|
+
* on the given shard (0 if none yet). The `@lunora/db` mutator runtime seeds
|
|
1149
|
+
* its `clientSeq` generator from this so a reload never reissues a sequence
|
|
1150
|
+
* the server has already applied (which it would swallow as a replay, silently
|
|
1151
|
+
* dropping the write).
|
|
1152
|
+
*/
|
|
1153
|
+
confirmedMutationWatermark(shardKey?: string): number;
|
|
1154
|
+
/**
|
|
1155
|
+
* Push a custom mutator to its authoritative server impl over the watermark
|
|
1156
|
+
* protocol (Phase 4): the request carries `x-lunora-client-id` + a monotonic
|
|
1157
|
+
* `x-lunora-client-seq`, so the DO runs it exactly once and advances this
|
|
1158
|
+
* client's `__client_watermark`.
|
|
1159
|
+
*
|
|
1160
|
+
* Returns the server `result` plus `applied`: `true` when the DO ran this push
|
|
1161
|
+
* as the next-in-order mutation, `false` when it was a replay ack (`clientSeq`
|
|
1162
|
+
* was at or below the stored watermark — e.g. a stale sequence after a reload).
|
|
1163
|
+
* A `false` verdict tells the caller to reissue above the now-known watermark
|
|
1164
|
+
* (echoed into {@link confirmedMutationWatermark}) rather than treat the benign
|
|
1165
|
+
* ack as a confirmed write. Every ack — applied or not — bumps the watermark.
|
|
1166
|
+
*
|
|
1167
|
+
* This is the online transport for `@lunora/db`'s client-mutator runtime; the
|
|
1168
|
+
* optimistic overlay + durable-outbox concerns live in that runtime, not here.
|
|
1169
|
+
*/
|
|
1170
|
+
callMutator(functionPath: string, args: Record<string, unknown>, options?: {
|
|
1171
|
+
clientSeq?: number;
|
|
1172
|
+
shardKey?: string;
|
|
1173
|
+
}): Promise<{
|
|
1174
|
+
applied: boolean;
|
|
1175
|
+
result: unknown;
|
|
1176
|
+
}>;
|
|
1177
|
+
/**
|
|
883
1178
|
* Subscribe to auth-token changes. Returns an unsubscribe function. The
|
|
884
1179
|
* listener is NOT invoked on registration — use {@link getAuthToken} for
|
|
885
1180
|
* the current value.
|
|
@@ -1069,8 +1364,12 @@ declare class LunoraClient {
|
|
|
1069
1364
|
* List a workflow's instances via the admin Workflows proxy
|
|
1070
1365
|
* (`/_lunora/admin/workflows/instances`) — the Cloudflare control-plane data
|
|
1071
1366
|
* the `Workflow` binding can't expose. Requires the worker to be built with a
|
|
1072
|
-
* `workflowsClient` (Cloudflare account id + API token)
|
|
1073
|
-
*
|
|
1367
|
+
* `workflowsClient` (Cloudflare account id + API token). When one isn't
|
|
1368
|
+
* configured this does NOT reject: the proxy returns a `200 { configured:
|
|
1369
|
+
* false }` sentinel, so the result resolves with `configured === false` and an
|
|
1370
|
+
* empty `instances` list — callers should branch on that flag rather than
|
|
1371
|
+
* try/catch. (The instance-detail / status endpoints still reject with 501.)
|
|
1372
|
+
* `name` is the deployed workflow name.
|
|
1074
1373
|
*/
|
|
1075
1374
|
listWorkflowInstances(options: {
|
|
1076
1375
|
name: string;
|
|
@@ -1404,6 +1703,26 @@ declare class LunoraClient {
|
|
|
1404
1703
|
shardKey?: string;
|
|
1405
1704
|
}): Unsubscribe;
|
|
1406
1705
|
/**
|
|
1706
|
+
* Subscribe to a declarative **shape** — server-side partial replication
|
|
1707
|
+
* scoped by `shardBy` + the shape's predicate + RLS. The parallel to
|
|
1708
|
+
* {@link subscribe} for the poke protocol: the client sends the shape *name* +
|
|
1709
|
+
* validated `args` (never a `where` the client could forge), the server seeds
|
|
1710
|
+
* the current membership as an insert-poke and streams live membership diffs.
|
|
1711
|
+
* Each applied poke materializes the shape's rowset and invokes `callback`.
|
|
1712
|
+
*
|
|
1713
|
+
* Unlike {@link subscribe}, shape subscriptions are NOT deduped by
|
|
1714
|
+
* (name, args): the server resolves them under the socket's verified identity,
|
|
1715
|
+
* so every call gets its own id + view. The returned function unsubscribes.
|
|
1716
|
+
*/
|
|
1717
|
+
subscribeShape(shape: {
|
|
1718
|
+
args?: Record<string, unknown>;
|
|
1719
|
+
name: string;
|
|
1720
|
+
}, callback: ShapeCallback, options?: {
|
|
1721
|
+
onCheckpoint?: (watermark: SyncWatermark) => void;
|
|
1722
|
+
onError?: SubscriptionErrorCallback;
|
|
1723
|
+
shardKey?: string;
|
|
1724
|
+
}): Unsubscribe;
|
|
1725
|
+
/**
|
|
1407
1726
|
* Open a streaming query. The function reference must be a
|
|
1408
1727
|
* `kind:"stream"` registration (built with `c.query.input(...).stream(...)`);
|
|
1409
1728
|
* the type constraint catches accidental use of a query/mutation/action
|
|
@@ -1427,6 +1746,18 @@ declare class LunoraClient {
|
|
|
1427
1746
|
}): StreamIterable<ReturnOf<F>>;
|
|
1428
1747
|
close(): void;
|
|
1429
1748
|
/**
|
|
1749
|
+
* Persist a mutation that can't go out on the wire right now (offline, or
|
|
1750
|
+
* mid-reconnect after a prior connect). The optimistic update has already
|
|
1751
|
+
* been applied by `mutation`; this only chooses the durable write path and
|
|
1752
|
+
* rolls the optimistic write back if persistence is rejected.
|
|
1753
|
+
*
|
|
1754
|
+
* Two paths: when an `outbox` sink is wired (the `@lunora/db` executor) it
|
|
1755
|
+
* owns persistence + at-least-once replay, so we delegate and return
|
|
1756
|
+
* optimistically (confirmation rides the synced view). Otherwise the
|
|
1757
|
+
* built-in `OfflineQueue` resolves/rejects the returned promise on replay.
|
|
1758
|
+
*/
|
|
1759
|
+
private enqueueOfflineMutation;
|
|
1760
|
+
/**
|
|
1430
1761
|
* Restore offline mutations persisted in a prior session and open a socket
|
|
1431
1762
|
* for each shard they target so they flush once the WS reconnects. Failures
|
|
1432
1763
|
* are swallowed — a broken durable store must not stop the client booting.
|
|
@@ -1523,6 +1854,13 @@ declare class LunoraClient {
|
|
|
1523
1854
|
* to the lifecycle dispatch.
|
|
1524
1855
|
*/
|
|
1525
1856
|
private sendConnectEnvelope;
|
|
1857
|
+
/**
|
|
1858
|
+
* Re-send every shape subscription bound to `shardKey` over its (now open)
|
|
1859
|
+
* socket. Each frame carries the shape's last applied checkpoint, so the
|
|
1860
|
+
* server resumes from it — or re-seeds when the cursor fell below CDC
|
|
1861
|
+
* retention or the epoch forked.
|
|
1862
|
+
*/
|
|
1863
|
+
private resendShapeSubscriptions;
|
|
1526
1864
|
private ensureSocket;
|
|
1527
1865
|
private handleDisconnect;
|
|
1528
1866
|
/**
|
|
@@ -1538,8 +1876,14 @@ declare class LunoraClient {
|
|
|
1538
1876
|
/** Mark every subscription bound to `shardKey` as needing a fresh ack. */
|
|
1539
1877
|
private markShardPendingAck;
|
|
1540
1878
|
private sendSubscribeIfOpen;
|
|
1879
|
+
private sendShapeSubscribeIfOpen;
|
|
1541
1880
|
private handleServerMessage;
|
|
1542
1881
|
private handleErrorMessage;
|
|
1882
|
+
private handlePokeStart;
|
|
1883
|
+
private handlePokePart;
|
|
1884
|
+
private handlePokeEnd;
|
|
1885
|
+
/** Materialize a shape's keyed view to an array and invoke its callbacks. */
|
|
1886
|
+
private emitShapeRows;
|
|
1543
1887
|
private handleDataMessage;
|
|
1544
1888
|
/**
|
|
1545
1889
|
* Handle a `resume` frame (Pillar 1b): the server proved nothing the
|
|
@@ -1594,4 +1938,4 @@ declare class LunoraClient {
|
|
|
1594
1938
|
private clearQueryCacheForIdentityChange;
|
|
1595
1939
|
private flushOfflineQueue;
|
|
1596
1940
|
}
|
|
1597
|
-
export { ArgsOf as A, BookmarkStorage as B, CachedQuery as C, DEFAULT_MAX_BUFFER as D,
|
|
1941
|
+
export { SyncWatermark as $, ArgsOf as A, BookmarkStorage as B, CachedQuery as C, DEFAULT_MAX_BUFFER as D, ServerMessage as E, FunctionReference as F, GlobalFacetResult as G, ServerPokeEndMessage as H, ServerPokePartMessage as I, ServerPokeStartMessage as J, ShardTrafficEntry as K, LunoraClient as L, MutationCallOptions as M, ShardTrafficResult as N, OfflineQueueOptions as O, Preloaded as P, QueryCacheAdapter as Q, ReturnOf as R, SubscriptionError as S, StorageListPage as T, User as U, StorageObject as V, StreamHandle as W, StreamIterable as X, SubscriptionCallback as Y, SubscriptionRegistry as Z, SubscriptionState as _, Unsubscribe as a, WorkflowInstanceAction as a0, WorkflowInstanceDetail as a1, WorkflowInstancePage as a2, WorkflowInstanceStatus as a3, WorkflowInstanceSummary as a4, WorkflowStepDetail as a5, createLocalStore as a6, createStream as a7, SubscriptionErrorCallback as b, PersistenceAdapter as c, ReconnectOptions as d, ClientMessage as e, ClientShapeSubscribeMessage as f, ClientShapeUnsubscribeMessage as g, ConnectionStatus as h, FunctionArgumentDescriptor as i, FunctionDescriptor as j, GlobalFacetValue as k, GlobalFilterClause as l, GlobalTableInfo as m, GlobalTablePage as n, LunoraClientOptions as o, OptimisticLocalStore as p, OptimisticUpdate as q, OutboxMutation as r, OutboxSink as s, PersistedMutation as t, RowOp as u, RpcEnvelope as v, RpcResponseBody as w, ScheduleRecord as x, SchedulerPoolStatus as y, SchedulerStatus as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as FunctionReference, L as LunoraClient, A as ArgsOf, R as ReturnOf, P as Preloaded } from "./lunora-client.d-
|
|
1
|
+
import { F as FunctionReference, L as LunoraClient, A as ArgsOf, R as ReturnOf, P as Preloaded } from "./lunora-client.d-CL9inoxa.js";
|
|
2
2
|
/**
|
|
3
3
|
* Run a query once on the server (during SSR) and capture its result in a
|
|
4
4
|
* serializable {@link Preloaded} token. Embed the token in the rendered HTML and
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as FunctionReference, L as LunoraClient, A as ArgsOf, R as ReturnOf, P as Preloaded } from "./lunora-client.d-
|
|
1
|
+
import { F as FunctionReference, L as LunoraClient, A as ArgsOf, R as ReturnOf, P as Preloaded } from "./lunora-client.d-CL9inoxa.mjs";
|
|
2
2
|
/**
|
|
3
3
|
* Run a query once on the server (during SSR) and capture its result in a
|
|
4
4
|
* serializable {@link Preloaded} token. Embed the token in the rendered HTML and
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const compareKeys = (a, b) => {
|
|
2
|
+
if (a < b) {
|
|
3
|
+
return -1;
|
|
4
|
+
}
|
|
5
|
+
return a > b ? 1 : 0;
|
|
6
|
+
};
|
|
7
|
+
const stableStringify = (value) => {
|
|
8
|
+
if (value === void 0) {
|
|
9
|
+
return "null";
|
|
10
|
+
}
|
|
11
|
+
if (value === null || typeof value !== "object") {
|
|
12
|
+
return JSON.stringify(value);
|
|
13
|
+
}
|
|
14
|
+
if (Array.isArray(value)) {
|
|
15
|
+
return `[${value.map((item) => stableStringify(item)).join(",")}]`;
|
|
16
|
+
}
|
|
17
|
+
const record = value;
|
|
18
|
+
const keys = Object.keys(record).toSorted(compareKeys);
|
|
19
|
+
const parts = [];
|
|
20
|
+
for (const key of keys) {
|
|
21
|
+
const raw = record[key];
|
|
22
|
+
if (raw === void 0) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
parts.push(`${JSON.stringify(key)}:${stableStringify(raw)}`);
|
|
26
|
+
}
|
|
27
|
+
return `{${parts.join(",")}}`;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
class SubscriptionRegistry {
|
|
31
|
+
static key(functionPath, args, shardKey) {
|
|
32
|
+
return `${functionPath}::${stableStringify(args)}::${shardKey ?? ""}`;
|
|
33
|
+
}
|
|
34
|
+
byKey = /* @__PURE__ */ new Map();
|
|
35
|
+
byId = /* @__PURE__ */ new Map();
|
|
36
|
+
get(key) {
|
|
37
|
+
return this.byKey.get(key);
|
|
38
|
+
}
|
|
39
|
+
getById(id) {
|
|
40
|
+
return this.byId.get(id);
|
|
41
|
+
}
|
|
42
|
+
add(state) {
|
|
43
|
+
this.byKey.set(SubscriptionRegistry.key(state.fn.__lunoraRef, state.args, state.shardKey), state);
|
|
44
|
+
this.byId.set(state.id, state);
|
|
45
|
+
}
|
|
46
|
+
remove(state) {
|
|
47
|
+
this.byKey.delete(SubscriptionRegistry.key(state.fn.__lunoraRef, state.args, state.shardKey));
|
|
48
|
+
this.byId.delete(state.id);
|
|
49
|
+
}
|
|
50
|
+
all() {
|
|
51
|
+
return [...this.byKey.values()];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { SubscriptionRegistry as S, stableStringify as s };
|
package/dist/query/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as SubscriptionError, F as FunctionReference, A as ArgsOf, R as ReturnOf, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-
|
|
2
|
-
export type { b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-
|
|
1
|
+
import { S as SubscriptionError, F as FunctionReference, A as ArgsOf, R as ReturnOf, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-CL9inoxa.mjs";
|
|
2
|
+
export type { b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-CL9inoxa.mjs";
|
|
3
3
|
import '@lunora/runtime';
|
|
4
4
|
/**
|
|
5
5
|
* The sentinel a framework adapter resolves its reactive args to when it wants
|
package/dist/query/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { S as SubscriptionError, F as FunctionReference, A as ArgsOf, R as ReturnOf, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-
|
|
2
|
-
export type { b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-
|
|
1
|
+
import { S as SubscriptionError, F as FunctionReference, A as ArgsOf, R as ReturnOf, L as LunoraClient, a as Unsubscribe } from "../packem_shared/lunora-client.d-CL9inoxa.js";
|
|
2
|
+
export type { b as SubscriptionErrorCallback } from "../packem_shared/lunora-client.d-CL9inoxa.js";
|
|
3
3
|
import '@lunora/runtime';
|
|
4
4
|
/**
|
|
5
5
|
* The sentinel a framework adapter resolves its reactive args to when it wants
|
package/dist/ssr/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-
|
|
2
|
-
export type { A as ArgsOf, F as FunctionReference, R as ReturnOf } from "../packem_shared/lunora-client.d-
|
|
3
|
-
export { p as preloadQuery, a as preloadedQueryResult } from "../packem_shared/preload.d-
|
|
1
|
+
import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-CL9inoxa.mjs";
|
|
2
|
+
export type { A as ArgsOf, F as FunctionReference, R as ReturnOf } from "../packem_shared/lunora-client.d-CL9inoxa.mjs";
|
|
3
|
+
export { p as preloadQuery, a as preloadedQueryResult } from "../packem_shared/preload.d-Da_yjk6L.mjs";
|
|
4
4
|
import '@lunora/runtime';
|
|
5
5
|
/**
|
|
6
6
|
* Structural shape of a better-auth `getSession` call's resolved value.
|
package/dist/ssr/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-
|
|
2
|
-
export type { A as ArgsOf, F as FunctionReference, R as ReturnOf } from "../packem_shared/lunora-client.d-
|
|
3
|
-
export { p as preloadQuery, a as preloadedQueryResult } from "../packem_shared/preload.d-
|
|
1
|
+
import { P as Preloaded, L as LunoraClient } from "../packem_shared/lunora-client.d-CL9inoxa.js";
|
|
2
|
+
export type { A as ArgsOf, F as FunctionReference, R as ReturnOf } from "../packem_shared/lunora-client.d-CL9inoxa.js";
|
|
3
|
+
export { p as preloadQuery, a as preloadedQueryResult } from "../packem_shared/preload.d-B0O7Zm9z.js";
|
|
4
4
|
import '@lunora/runtime';
|
|
5
5
|
/**
|
|
6
6
|
* Structural shape of a better-auth `getSession` call's resolved value.
|
package/dist/ssr/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { getServerSession } from '../packem_shared/getServerSession-8jXewqxd.mjs';
|
|
2
2
|
export { deserializePreloaded, serializePreloaded } from '../packem_shared/deserializePreloaded-C0eJTY_W.mjs';
|
|
3
|
-
export { createServerClient } from '../packem_shared/createServerClient-
|
|
3
|
+
export { createServerClient } from '../packem_shared/createServerClient-BgzEOQ46.mjs';
|
|
4
4
|
export { preloadQuery, preloadedQueryResult } from '../packem_shared/preloadQuery-lobFkD2Z.mjs';
|