foldkit-remote 0.14.1 → 0.16.0

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.
@@ -7,57 +7,91 @@ import { EntryWithoutKeepAlive } from "foldkit/subscription";
7
7
  import { ActiveSurface, Contract, Invalid, Metadata, ModelRef, Projection, Surface, SurfaceSource, Wiring } from "foldkit-surface";
8
8
  import { Rpc, RpcClientError, RpcGroup } from "effect/rpc";
9
9
  import * as Update from "foldkit/update";
10
- //#region ../metadata/src/index.d.ts
11
- /** Marks a `Metadata` value. Its entries are private to this module. */
12
- declare const MetadataTypeId: unique symbol;
13
- type MetadataTypeId = typeof MetadataTypeId;
14
- /**
15
- * Declarative facts an interpreter attaches to a node it does not own, such as
16
- * the server data a Remote selection needs. The carrier holds and combines
17
- * them without knowing what they mean; a package reads only the key it owns.
18
- *
19
- * Opaque: only a key's `of` and `Metadata.combine` make one, so entries cannot
20
- * be forged past a key's type or `merge`, and they are frozen.
21
- */
22
- interface Metadata$1 {
23
- readonly [MetadataTypeId]: MetadataTypeId;
24
- }
25
- /**
26
- * An interpreter's typed slot in `Metadata`. Lookup is by the key object, never
27
- * its `name`, so two packages cannot collide by choosing the same string.
28
- */
29
- interface MetadataKey<A> {
30
- /** For tooling output only. */
31
- readonly name: string;
32
- /** Normalizes the entries gathered from combined values, e.g. unioning duplicates. */
33
- readonly merge: (values: ReadonlyArray<A>) => ReadonlyArray<A>;
34
- /** One line per entry for tooling output. */
35
- readonly summarize: (value: A) => string;
36
- readonly of: (...values: ReadonlyArray<A>) => Metadata$1;
37
- readonly get: (metadata: Metadata$1) => ReadonlyArray<A>;
38
- }
39
- /** One key's entries as serializable text, named by the key. */
40
- interface MetadataSummary {
41
- readonly name: string;
42
- readonly entries: readonly string[];
43
- }
44
- declare const Metadata$1: {
45
- /**
46
- * Declares an interpreter's slot. Call once per package, at module level:
47
- * entries are found by the key object, so two copies of a package (a
48
- * duplicated install, a reloaded module) do not see each other's entries.
49
- */
50
- key: <A>(name: string, options: {
51
- readonly merge: (values: ReadonlyArray<A>) => ReadonlyArray<A>;
52
- readonly summarize: (value: A) => string;
53
- }) => MetadataKey<A>;
54
- empty: Metadata$1;
55
- /** True only for a value this module made; a copy or a hand-built brand is not one. */
56
- is: (value: unknown) => value is Metadata$1;
57
- /** Gathers every part's entries and runs each key's `merge` over its group. */
58
- combine: (parts: ReadonlyArray<Metadata$1>) => Metadata$1;
59
- summarize: (metadata: Metadata$1) => readonly MetadataSummary[];
60
- };
10
+ //#region src/store.d.ts
11
+ type EntityKey = string;
12
+ interface EntityEntry {
13
+ readonly values: Readonly<Record<string, unknown>>;
14
+ readonly present: ReadonlySet<string>;
15
+ /** Present fields whose value may be outdated (revalidation needed). */
16
+ readonly stale: ReadonlySet<string>;
17
+ /**
18
+ * Fields the server settled without a value: asked for, and answered without
19
+ * them, whatever the reason. Not planned again until a refresh asks; a later
20
+ * write of the field clears it.
21
+ */
22
+ readonly unavailable: ReadonlySet<string>;
23
+ /** The entity is known to be absent; a later write clears this. */
24
+ readonly tombstone: boolean;
25
+ /** Injected clock reading of the last write; never read from ambient state. */
26
+ readonly updatedAt: number;
27
+ /**
28
+ * The canonical window each present field was fetched with (`""` for none).
29
+ * A later request with a *known, different* window is planned as missing.
30
+ */
31
+ readonly windows: Readonly<Record<string, string>>;
32
+ }
33
+ type EntityStore = Readonly<Record<EntityKey, EntityEntry>>;
34
+ /** The separator keeps an untrusted id from colliding with a prototype key. */
35
+ declare const entityKey: (entity: string, id: string) => EntityKey;
36
+ declare const emptyStore: EntityStore;
37
+ interface EntityWrite {
38
+ readonly key: EntityKey;
39
+ readonly values: Readonly<Record<string, unknown>>;
40
+ /** The canonical window each written relation field was fetched with. */
41
+ readonly windows?: Readonly<Record<string, string>> | undefined;
42
+ /** When this write dates the entity, instead of the batch's `now`. */
43
+ readonly updatedAt?: number | undefined;
44
+ }
45
+ /**
46
+ * Merges known values into many entities, copying the store once. Every
47
+ * written field becomes present and non-stale; a tombstone is cleared because
48
+ * the entity is evidently not absent.
49
+ */
50
+ declare const writeEntities: (store: EntityStore, writes: ReadonlyArray<EntityWrite>, now?: number) => EntityStore;
51
+ /** `writeEntities` for one entity. */
52
+ declare const writeEntity: (store: EntityStore, key: EntityKey, values: Readonly<Record<string, unknown>>, now?: number, windows?: Readonly<Record<string, string>>) => EntityStore;
53
+ /**
54
+ * Marks present fields stale (`true`) or ends their staleness (`false`) across
55
+ * many entities, copying the store once. A field never present stays missing;
56
+ * an unknown entity is left alone.
57
+ */
58
+ declare const setStale: (store: EntityStore, marks: ReadonlyArray<readonly [key: EntityKey, fields: Iterable<string>]>, stale: boolean) => EntityStore;
59
+ /** Marks present fields stale; fields that were never present stay missing. */
60
+ declare const markStale: (store: EntityStore, key: EntityKey, fields: Iterable<string>) => EntityStore;
61
+ /** Ends a refresh that did not land: the fields are present again as they were. */
62
+ declare const clearStale: (store: EntityStore, key: EntityKey, fields: Iterable<string>) => EntityStore;
63
+ /**
64
+ * Records fields the server settled without a value. A present field is left
65
+ * as it is: the answer that settled it was not about the value it holds.
66
+ * `false` forgets the marks, which is how a refresh asks again.
67
+ */
68
+ declare const setUnavailable: (store: EntityStore, marks: ReadonlyArray<readonly [key: EntityKey, fields: Iterable<string>]>, unavailable: boolean) => EntityStore;
69
+ /** Whether the server settled this field without a value, and nothing has written it since. */
70
+ declare const isFieldUnavailable: (store: EntityStore, key: EntityKey, field: string) => boolean;
71
+ /** Records that the entity is known to be absent, so it is not refetched. */
72
+ declare const tombstone: (store: EntityStore, key: EntityKey) => EntityStore;
73
+ /** Forgets everything known about the entity, including a tombstone. */
74
+ declare const remove: (store: EntityStore, key: EntityKey) => EntityStore;
75
+ declare const entry: (store: EntityStore, key: EntityKey) => Option.Option<EntityEntry>;
76
+ declare const isTombstone: (store: EntityStore, key: EntityKey) => boolean;
77
+ /** A field is known only if it is present and not stale. */
78
+ declare const hasField: (store: EntityStore, key: EntityKey, field: string) => boolean;
79
+ /** A present field whose value may be outdated; absent fields are not stale. */
80
+ declare const isFieldStale: (store: EntityStore, key: EntityKey, field: string) => boolean;
81
+ /**
82
+ * Reads a present field, stale or not. Absence and a tombstone both yield
83
+ * `Option.none()`; a present `undefined`/`null` yields `Option.some`.
84
+ */
85
+ declare const readField: (store: EntityStore, key: EntityKey, field: string) => Option.Option<unknown>;
86
+ /**
87
+ * The fields the planner must fetch. A tombstone makes every field known
88
+ * (absent), so it returns an empty list and the entity is not refetched, and a
89
+ * field the server settled without a value is known the same way. A
90
+ * requested window that differs from the one a field was fetched with also
91
+ * marks it missing, but only when the stored window is known (never `""`), so a
92
+ * writer that does not record windows cannot cause a refetch loop.
93
+ */
94
+ declare const missingFields: (store: EntityStore, key: EntityKey, fields: Iterable<string>, windows?: Readonly<Record<string, string>>) => ReadonlyArray<string>;
61
95
  //#endregion
62
96
  //#region src/connection.d.ts
63
97
  interface EdgeRef {
@@ -208,92 +242,6 @@ declare const RemoteData: {
208
242
  map: <A, B>(data: RemoteData<A>, f: (value: A) => B) => RemoteData<B>;
209
243
  };
210
244
  //#endregion
211
- //#region src/store.d.ts
212
- type EntityKey = string;
213
- interface EntityEntry {
214
- readonly values: Readonly<Record<string, unknown>>;
215
- readonly present: ReadonlySet<string>;
216
- /** Present fields whose value may be outdated (revalidation needed). */
217
- readonly stale: ReadonlySet<string>;
218
- /**
219
- * Fields the server settled without a value: asked for, and answered without
220
- * them, whatever the reason. Not planned again until a refresh asks; a later
221
- * write of the field clears it.
222
- */
223
- readonly unavailable: ReadonlySet<string>;
224
- /** The entity is known to be absent; a later write clears this. */
225
- readonly tombstone: boolean;
226
- /** Injected clock reading of the last write; never read from ambient state. */
227
- readonly updatedAt: number;
228
- /**
229
- * The canonical window each present field was fetched with (`""` for none).
230
- * A later request with a *known, different* window is planned as missing.
231
- */
232
- readonly windows: Readonly<Record<string, string>>;
233
- }
234
- type EntityStore = Readonly<Record<EntityKey, EntityEntry>>;
235
- /** The separator keeps an untrusted id from colliding with a prototype key. */
236
- declare const entityKey: (entity: string, id: string) => EntityKey;
237
- declare const emptyStore: EntityStore;
238
- interface EntityWrite {
239
- readonly key: EntityKey;
240
- readonly values: Readonly<Record<string, unknown>>;
241
- /** The canonical window each written relation field was fetched with. */
242
- readonly windows?: Readonly<Record<string, string>> | undefined;
243
- /** When this write dates the entity, instead of the batch's `now`. */
244
- readonly updatedAt?: number | undefined;
245
- }
246
- /**
247
- * Merges known values into many entities, copying the store once. Every
248
- * written field becomes present and non-stale; a tombstone is cleared because
249
- * the entity is evidently not absent.
250
- */
251
- declare const writeEntities: (store: EntityStore, writes: ReadonlyArray<EntityWrite>, now?: number) => EntityStore;
252
- /** `writeEntities` for one entity. */
253
- declare const writeEntity: (store: EntityStore, key: EntityKey, values: Readonly<Record<string, unknown>>, now?: number, windows?: Readonly<Record<string, string>>) => EntityStore;
254
- /**
255
- * Marks present fields stale (`true`) or ends their staleness (`false`) across
256
- * many entities, copying the store once. A field never present stays missing;
257
- * an unknown entity is left alone.
258
- */
259
- declare const setStale: (store: EntityStore, marks: ReadonlyArray<readonly [key: EntityKey, fields: Iterable<string>]>, stale: boolean) => EntityStore;
260
- /** Marks present fields stale; fields that were never present stay missing. */
261
- declare const markStale: (store: EntityStore, key: EntityKey, fields: Iterable<string>) => EntityStore;
262
- /** Ends a refresh that did not land: the fields are present again as they were. */
263
- declare const clearStale: (store: EntityStore, key: EntityKey, fields: Iterable<string>) => EntityStore;
264
- /**
265
- * Records fields the server settled without a value. A present field is left
266
- * as it is: the answer that settled it was not about the value it holds.
267
- * `false` forgets the marks, which is how a refresh asks again.
268
- */
269
- declare const setUnavailable: (store: EntityStore, marks: ReadonlyArray<readonly [key: EntityKey, fields: Iterable<string>]>, unavailable: boolean) => EntityStore;
270
- /** Whether the server settled this field without a value, and nothing has written it since. */
271
- declare const isFieldUnavailable: (store: EntityStore, key: EntityKey, field: string) => boolean;
272
- /** Records that the entity is known to be absent, so it is not refetched. */
273
- declare const tombstone: (store: EntityStore, key: EntityKey) => EntityStore;
274
- /** Forgets everything known about the entity, including a tombstone. */
275
- declare const remove: (store: EntityStore, key: EntityKey) => EntityStore;
276
- declare const entry: (store: EntityStore, key: EntityKey) => Option.Option<EntityEntry>;
277
- declare const isTombstone: (store: EntityStore, key: EntityKey) => boolean;
278
- /** A field is known only if it is present and not stale. */
279
- declare const hasField: (store: EntityStore, key: EntityKey, field: string) => boolean;
280
- /** A present field whose value may be outdated; absent fields are not stale. */
281
- declare const isFieldStale: (store: EntityStore, key: EntityKey, field: string) => boolean;
282
- /**
283
- * Reads a present field, stale or not. Absence and a tombstone both yield
284
- * `Option.none()`; a present `undefined`/`null` yields `Option.some`.
285
- */
286
- declare const readField: (store: EntityStore, key: EntityKey, field: string) => Option.Option<unknown>;
287
- /**
288
- * The fields the planner must fetch. A tombstone makes every field known
289
- * (absent), so it returns an empty list and the entity is not refetched, and a
290
- * field the server settled without a value is known the same way. A
291
- * requested window that differs from the one a field was fetched with also
292
- * marks it missing, but only when the stored window is known (never `""`), so a
293
- * writer that does not record windows cannot cause a refetch loop.
294
- */
295
- declare const missingFields: (store: EntityStore, key: EntityKey, fields: Iterable<string>, windows?: Readonly<Record<string, string>>) => ReadonlyArray<string>;
296
- //#endregion
297
245
  //#region src/mutation.d.ts
298
246
  interface NormalizedPatch {
299
247
  readonly entity: string;
@@ -429,59 +377,171 @@ declare const Mutation: {
429
377
  }) => MutationDescriptor<Name, TypeOf<Input>, TypeOf<Output>, Refused>;
430
378
  };
431
379
  //#endregion
432
- //#region src/query.d.ts
433
- type LiveInsertion = 'visible' | 'boundary' | 'invalidate' | 'ignore';
434
- interface LivePolicy {
435
- readonly prepend?: LiveInsertion;
436
- readonly append?: LiveInsertion;
437
- }
438
- interface ConnectionSpec<Entity extends string = string> {
439
- readonly entity: Entity;
440
- readonly edgeKey?: Schema.Schema<unknown>;
441
- readonly live?: LivePolicy;
442
- }
443
- interface QueryWindow {
444
- readonly first?: number | undefined;
445
- readonly last?: number | undefined;
446
- readonly after?: Cursor | undefined;
447
- readonly before?: Cursor | undefined;
448
- }
449
- interface QueryRef<Name extends string, Input> {
450
- readonly query: Name;
451
- readonly input: Input;
452
- /** The input codec, so a `QueryRef` can encode itself without its descriptor. */
453
- readonly Input: Schema.Codec<Input>;
454
- readonly window: QueryWindow;
455
- /** Connection identity: descriptor + canonical input, excluding the window. */
456
- readonly identity: string;
457
- }
458
- interface QueryDescriptor<Name extends string, Input, Result> {
459
- readonly name: Name;
460
- readonly Input: Schema.Codec<Input>;
461
- readonly Result: Result;
462
- readonly ref: (input: Input) => QueryRef<Name, Input>;
463
- /**
464
- * What the query means, when it was declared with `Query.define`: the rows it
465
- * is about, as a value an interpreter can compile. A descriptor from
466
- * `Query.make` has none — its meaning lives in whatever the server registered
467
- * to answer it — and a source is free to answer either.
468
- */
469
- readonly body?: AnyQuery | undefined;
380
+ //#region src/optimistic.d.ts
381
+ interface EntityLayer {
382
+ readonly id: string;
383
+ readonly patches: ReadonlyArray<NormalizedPatch>;
470
384
  }
471
385
  /**
472
- * The inputs of a definition's body: one placeholder per key of `Input`, typed
473
- * as that key's value. A body is built once, so these stand for what the query
474
- * will be given rather than being it.
386
+ * Edges placed outside a connection's server-known region (`prepend`,
387
+ * `append`) or hidden from it (`remove`), owned by the request or live event
388
+ * that produced them.
475
389
  */
476
- type QueryInputs<Input> = { readonly [K in keyof Input & string]: InputExpr<Input[K]>; };
390
+ interface ConnectionOverlay {
391
+ readonly id: string;
392
+ readonly connection: string;
393
+ readonly edges: ReadonlyArray<Edge>;
394
+ readonly position: 'prepend' | 'append' | 'remove';
395
+ }
396
+ /** A connection change a request makes optimistically or a mutation result confirms. */
397
+ type ConnectionChange = {
398
+ readonly _tag: 'Insert';
399
+ readonly connection: string;
400
+ readonly position: 'prepend' | 'append';
401
+ readonly edge: Edge;
402
+ } | {
403
+ readonly _tag: 'Remove';
404
+ readonly connection: string;
405
+ readonly edge: Edge;
406
+ };
407
+ /** What a request changes before the server answers: entity patches and connection changes. */
408
+ type OptimisticOperation = NormalizedPatch | ConnectionChange;
409
+ /** A connection, by identity string or by anything that carries one (a `QueryRef`). */
410
+ type ConnectionIdentity = string | {
411
+ readonly identity: string;
412
+ };
413
+ declare const connectionIdentity: (connection: ConnectionIdentity) => string;
477
414
  /**
478
- * What separates a query's name from its canonical encoded input in a
479
- * connection identity.
480
- *
481
- * NUL, because `JSON.stringify` escapes it inside a string (`\u0000`) and a
482
- * query name is a TypeScript identifier — so the first occurrence is always the
483
- * boundary, and a name or an input value cannot forge one. Anything recovering
484
- * the query from an identity splits here.
415
+ * Constructors for connection changes: what a request shows optimistically
416
+ * (`MutateOptions.optimistic`) and what a mutation source reports it made
417
+ * (`MutationOutcome.connections`).
418
+ */
419
+ declare const ConnectionChange: {
420
+ /** Show `ref` at the front of the connection until the request settles. */
421
+ prepend: (connection: ConnectionIdentity, ref: {
422
+ readonly entity: string;
423
+ readonly id: string;
424
+ }) => ConnectionChange;
425
+ /** Show `ref` at the end of the connection until the request settles. */
426
+ append: (connection: ConnectionIdentity, ref: {
427
+ readonly entity: string;
428
+ readonly id: string;
429
+ }) => ConnectionChange;
430
+ /** Hide `ref` from the connection until the request settles. */
431
+ remove: (connection: ConnectionIdentity, ref: {
432
+ readonly entity: string;
433
+ readonly id: string;
434
+ }) => ConnectionChange;
435
+ };
436
+ /**
437
+ * Applies a request's operations: its patches become one layer and its
438
+ * connection changes become overlays, all owned by `requestId` so settling
439
+ * removes every one of them together.
440
+ */
441
+ declare const beginOptimistic: (optimistic: OptimisticState, requestId: string, operations: ReadonlyArray<OptimisticOperation>) => OptimisticState;
442
+ /** Pending entity layers and connection overlays over the base store. */
443
+ interface OptimisticState {
444
+ readonly layers: ReadonlyArray<EntityLayer>;
445
+ readonly overlays: ReadonlyArray<ConnectionOverlay>;
446
+ }
447
+ declare const emptyOptimistic: OptimisticState;
448
+ declare const addLayer: (optimistic: OptimisticState, layer: EntityLayer) => OptimisticState;
449
+ declare const removeLayer: (optimistic: OptimisticState, id: string) => OptimisticState;
450
+ declare const addOverlay: (optimistic: OptimisticState, overlay: ConnectionOverlay) => OptimisticState;
451
+ declare const removeOverlay: (optimistic: OptimisticState, id: string) => OptimisticState;
452
+ /**
453
+ * Base store with every layer applied in order. Later layers win. A patch is
454
+ * not news from the server, so it keeps the date of the value under it; an
455
+ * entity only a request holds (a temporary id) is not the server's to age, and
456
+ * is dated `Infinity`, so freshness never plans or times it.
457
+ */
458
+ declare const visibleStore: (base: EntityStore, optimistic: OptimisticState) => EntityStore;
459
+ /**
460
+ * A fresh page is newer than any settled overlay it covers: an edge the page
461
+ * carries no longer needs an insert overlay, and a `remove` overlay hiding it
462
+ * is stale (the server says it is back). A pending request's overlays are
463
+ * left alone; they settle with the request.
464
+ */
465
+ declare const pruneOverlays: (optimistic: OptimisticState, connection: string, covered: ReadonlySet<string>, pending: ReadonlySet<string>) => OptimisticState;
466
+ /**
467
+ * Applies a result idempotently and releases the request's layer and overlays:
468
+ * a later layer re-wins on rebase. Confirmed connection changes are recorded
469
+ * once per request, as overlays the request no longer owns.
470
+ */
471
+ declare const settleSuccess: (base: EntityStore, optimistic: OptimisticState, state: MutationState, requestId: string, answer: MutationAnswer & {
472
+ /** Connection changes the server confirmed; they replace the request's own. */
473
+ readonly connections?: ReadonlyArray<ConnectionChange> | undefined;
474
+ }) => {
475
+ readonly store: EntityStore;
476
+ readonly state: MutationState;
477
+ readonly optimistic: OptimisticState;
478
+ };
479
+ /** A failed request's layer and overlays are dropped; the base was never mutated. */
480
+ declare const settleFailure: (optimistic: OptimisticState, requestId: string) => OptimisticState;
481
+ /**
482
+ * Visible edges for one connection: applicable overlays are placed outside the
483
+ * server-known segments and de-duplicated by edge identity (across overlays too),
484
+ * so a pending insert never corrupts server-known ordering; a `remove` overlay
485
+ * hides its edges wherever they are, and so does a tombstone on the edge's
486
+ * target when `store` is given. A later prepend lands before an earlier one, a
487
+ * later append after, so pending inserts read in the order they were made.
488
+ * Boundaries still come from the connection's segments.
489
+ */
490
+ declare const visibleItems: (connection: Connection, connectionId: string, overlays: ReadonlyArray<ConnectionOverlay>, store?: EntityStore) => ReadonlyArray<Edge>;
491
+ //#endregion
492
+ //#region src/query.d.ts
493
+ type LiveInsertion = 'visible' | 'boundary' | 'invalidate' | 'ignore';
494
+ interface LivePolicy {
495
+ readonly prepend?: LiveInsertion;
496
+ readonly append?: LiveInsertion;
497
+ }
498
+ interface ConnectionSpec<Entity extends string = string> {
499
+ readonly entity: Entity;
500
+ readonly edgeKey?: Schema.Schema<unknown>;
501
+ readonly live?: LivePolicy;
502
+ }
503
+ interface QueryWindow {
504
+ readonly first?: number | undefined;
505
+ readonly last?: number | undefined;
506
+ readonly after?: Cursor | undefined;
507
+ readonly before?: Cursor | undefined;
508
+ }
509
+ interface QueryRef<Name extends string, Input> {
510
+ readonly query: Name;
511
+ readonly input: Input;
512
+ /** The input codec, so a `QueryRef` can encode itself without its descriptor. */
513
+ readonly Input: Schema.Codec<Input>;
514
+ readonly window: QueryWindow;
515
+ /** Connection identity: descriptor + canonical input, excluding the window. */
516
+ readonly identity: string;
517
+ }
518
+ interface QueryDescriptor<Name extends string, Input, Result> {
519
+ readonly name: Name;
520
+ readonly Input: Schema.Codec<Input>;
521
+ readonly Result: Result;
522
+ readonly ref: (input: Input) => QueryRef<Name, Input>;
523
+ /**
524
+ * What the query means, when it was declared with `Query.define`: the rows it
525
+ * is about, as a value an interpreter can compile. A descriptor from
526
+ * `Query.make` has none — its meaning lives in whatever the server registered
527
+ * to answer it — and a source is free to answer either.
528
+ */
529
+ readonly body?: AnyQuery | undefined;
530
+ }
531
+ /**
532
+ * The inputs of a definition's body: one placeholder per key of `Input`, typed
533
+ * as that key's value. A body is built once, so these stand for what the query
534
+ * will be given rather than being it.
535
+ */
536
+ type QueryInputs<Input> = { readonly [K in keyof Input & string]: InputExpr<Input[K]>; };
537
+ /**
538
+ * What separates a query's name from its canonical encoded input in a
539
+ * connection identity.
540
+ *
541
+ * NUL, because `JSON.stringify` escapes it inside a string (`\u0000`) and a
542
+ * query name is a TypeScript identifier — so the first occurrence is always the
543
+ * boundary, and a name or an input value cannot forge one. Anything recovering
544
+ * the query from an identity splits here.
485
545
  */
486
546
  declare const IDENTITY_SEPARATOR = "\0";
487
547
  /** Stable stringify: object keys sorted, undefined-valued keys dropped, so equal inputs encode equally. */
@@ -497,6 +557,14 @@ type ResultOf<Result> = Result extends {
497
557
  /** A relational `Query` over one Entity, as `Query.define`'s body returns. */
498
558
  type RelationalQueryOf<E extends AnyEntity> = ReturnType<typeof Query.from<E>>;
499
559
  declare const Query$1: {
560
+ from: <E extends AnyEntity>(entity: E) => Query<E>;
561
+ where: (...predicates: ReadonlyArray<import("foldkit-entity").Predicate>) => <E extends AnyEntity>(self: Query<E>) => Query<E>;
562
+ orderBy: (...terms: ReadonlyArray<import("foldkit-entity").Ordering>) => <E extends AnyEntity>(self: Query<E>) => Query<E>;
563
+ orderFor: (self: AnyQuery, input: Readonly<Record<string, unknown>>) => ReadonlyArray<import("foldkit-entity").OrderTerm>;
564
+ placement: (self: AnyQuery, input: Readonly<Record<string, unknown>>) => import("foldkit-entity").Placement;
565
+ dependencies: (self: AnyQuery) => import("foldkit-entity").QueryDependencies;
566
+ unsupported: (self: AnyQuery, supported: ReadonlyArray<import("foldkit-entity").Operation>) => ReadonlyArray<import("foldkit-entity").Operation>;
567
+ show: (self: AnyQuery) => string;
500
568
  /** Declares the entity and options a query's result is a connection over. */
501
569
  connection: <Entity extends string>(entity: {
502
570
  readonly name: Entity;
@@ -542,19 +610,11 @@ declare const Query$1: {
542
610
  }) => RelationalQueryOf<E>, options?: {
543
611
  readonly edgeKey?: Schema.Schema<unknown>;
544
612
  readonly live?: LivePolicy;
545
- }) => QueryDescriptor<Name, TypeOf<Input>, ConnectionSpec<E["name"]>>;
613
+ }) => QueryDescriptor<Name, TypeOf<Input>, ConnectionSpec<E['name']>>;
546
614
  first: (count: number) => <R extends QueryRef<string, unknown>>(ref: R) => R;
547
615
  last: (count: number) => <R extends QueryRef<string, unknown>>(ref: R) => R;
548
616
  after: (cursor: Cursor) => <R extends QueryRef<string, unknown>>(ref: R) => R;
549
617
  before: (cursor: Cursor) => <R extends QueryRef<string, unknown>>(ref: R) => R;
550
- from: <E extends AnyEntity>(entity: E) => Query<E>;
551
- where: (...predicates: ReadonlyArray<import("foldkit-entity").Predicate>) => <E extends AnyEntity>(self: Query<E>) => Query<E>;
552
- orderBy: (...terms: ReadonlyArray<import("foldkit-entity").Ordering>) => <E extends AnyEntity>(self: Query<E>) => Query<E>;
553
- orderFor: (self: AnyQuery, input: Readonly<Record<string, unknown>>) => ReadonlyArray<import("foldkit-entity").OrderTerm>;
554
- placement: (self: AnyQuery, input: Readonly<Record<string, unknown>>) => import("foldkit-entity").Placement;
555
- dependencies: (self: AnyQuery) => import("foldkit-entity").QueryDependencies;
556
- unsupported: (self: AnyQuery, supported: ReadonlyArray<import("foldkit-entity").Operation>) => ReadonlyArray<import("foldkit-entity").Operation>;
557
- show: (self: AnyQuery) => string;
558
618
  };
559
619
  //#endregion
560
620
  //#region src/requirement.d.ts
@@ -604,9 +664,9 @@ declare const Requirement: {
604
664
  mergeConnections: typeof mergeConnections;
605
665
  };
606
666
  /** Remote's entity requirements on a Projection, unioned per entity and id as nodes compose. */
607
- declare const RemoteRequirements: MetadataKey<Requirement>;
667
+ declare const RemoteRequirements: import("foldkit-metadata").MetadataKey<Requirement>;
608
668
  /** Remote's query connections on a Projection, unioned per connection and window. */
609
- declare const RemoteConnections: MetadataKey<ConnectionRequirement>;
669
+ declare const RemoteConnections: import("foldkit-metadata").MetadataKey<ConnectionRequirement>;
610
670
  /** The entity requirements a Projection carries. */
611
671
  declare const requirementsOf: (projection: {
612
672
  readonly metadata: Metadata;
@@ -616,372 +676,67 @@ declare const connectionsOf: (projection: {
616
676
  readonly metadata: Metadata;
617
677
  }) => ReadonlyArray<ConnectionRequirement>;
618
678
  //#endregion
619
- //#region src/optimistic.d.ts
620
- interface EntityLayer {
621
- readonly id: string;
622
- readonly patches: ReadonlyArray<NormalizedPatch>;
623
- }
679
+ //#region src/wire.d.ts
624
680
  /**
625
- * Edges placed outside a connection's server-known region (`prepend`,
626
- * `append`) or hidden from it (`remove`), owned by the request or live event
627
- * that produced them.
681
+ * The read/live protocol version. A batch names the version it speaks and the
682
+ * server refuses a mismatch with `RemoteProtocolError`, so a shape change never
683
+ * drifts silently: bump it whenever `ReadRequest` or `LiveRequirement` change.
628
684
  */
629
- interface ConnectionOverlay {
630
- readonly id: string;
631
- readonly connection: string;
632
- readonly edges: ReadonlyArray<Edge>;
633
- readonly position: 'prepend' | 'append' | 'remove';
634
- }
635
- /** A connection change a request makes optimistically or a mutation result confirms. */
636
- type ConnectionChange = {
637
- readonly _tag: 'Insert';
638
- readonly connection: string;
639
- readonly position: 'prepend' | 'append';
640
- readonly edge: Edge;
641
- } | {
642
- readonly _tag: 'Remove';
643
- readonly connection: string;
644
- readonly edge: Edge;
645
- };
646
- /** What a request changes before the server answers: entity patches and connection changes. */
647
- type OptimisticOperation = NormalizedPatch | ConnectionChange;
648
- /** A connection, by identity string or by anything that carries one (a `QueryRef`). */
649
- type ConnectionIdentity = string | {
650
- readonly identity: string;
651
- };
652
- declare const connectionIdentity: (connection: ConnectionIdentity) => string;
685
+ declare const REMOTE_PROTOCOL_VERSION = 4;
686
+ declare const RemoteReadError_base: Schema.Class<RemoteReadError, Schema.TaggedStruct<"RemoteReadError", {
687
+ readonly message: Schema.String;
688
+ }>, import("effect/Cause").YieldableError>;
689
+ declare class RemoteReadError extends RemoteReadError_base {}
690
+ declare const RemoteMutationError_base: Schema.Class<RemoteMutationError, Schema.TaggedStruct<"RemoteMutationError", {
691
+ readonly message: Schema.String;
692
+ /** The mutation's own `Refusal`, encoded, when the server refused it as one. */
693
+ readonly refusal: Schema.optional<Schema.Unknown>;
694
+ }>, import("effect/Cause").YieldableError>;
695
+ declare class RemoteMutationError extends RemoteMutationError_base {}
696
+ declare const RemoteForbidden_base: Schema.Class<RemoteForbidden, Schema.TaggedStruct<"Forbidden", {
697
+ readonly message: Schema.String;
698
+ readonly reason: Schema.optional<Schema.String>;
699
+ }>, import("effect/Cause").YieldableError>;
653
700
  /**
654
- * Constructors for connection changes: what a request shows optimistically
655
- * (`MutateOptions.optimistic`) and what a mutation source reports it made
656
- * (`MutationOutcome.connections`).
701
+ * The server refused who is asking: they may not do this, and asking again
702
+ * as the same principal is refused again. `reason` is the application's own
703
+ * words for the person who asked; without it the refusal says nothing of why.
657
704
  */
658
- declare const ConnectionChange: {
659
- /** Show `ref` at the front of the connection until the request settles. */
660
- prepend: (connection: ConnectionIdentity, ref: {
661
- readonly entity: string;
662
- readonly id: string;
663
- }) => ConnectionChange;
664
- /** Show `ref` at the end of the connection until the request settles. */
665
- append: (connection: ConnectionIdentity, ref: {
666
- readonly entity: string;
667
- readonly id: string;
668
- }) => ConnectionChange;
669
- /** Hide `ref` from the connection until the request settles. */
670
- remove: (connection: ConnectionIdentity, ref: {
671
- readonly entity: string;
672
- readonly id: string;
673
- }) => ConnectionChange;
674
- };
675
- /**
676
- * Applies a request's operations: its patches become one layer and its
677
- * connection changes become overlays, all owned by `requestId` so settling
678
- * removes every one of them together.
679
- */
680
- declare const beginOptimistic: (optimistic: OptimisticState, requestId: string, operations: ReadonlyArray<OptimisticOperation>) => OptimisticState;
681
- /** Pending entity layers and connection overlays over the base store. */
682
- interface OptimisticState {
683
- readonly layers: ReadonlyArray<EntityLayer>;
684
- readonly overlays: ReadonlyArray<ConnectionOverlay>;
685
- }
686
- declare const emptyOptimistic: OptimisticState;
687
- declare const addLayer: (optimistic: OptimisticState, layer: EntityLayer) => OptimisticState;
688
- declare const removeLayer: (optimistic: OptimisticState, id: string) => OptimisticState;
689
- declare const addOverlay: (optimistic: OptimisticState, overlay: ConnectionOverlay) => OptimisticState;
690
- declare const removeOverlay: (optimistic: OptimisticState, id: string) => OptimisticState;
691
- /**
692
- * Base store with every layer applied in order. Later layers win. A patch is
693
- * not news from the server, so it keeps the date of the value under it; an
694
- * entity only a request holds (a temporary id) is not the server's to age, and
695
- * is dated `Infinity`, so freshness never plans or times it.
696
- */
697
- declare const visibleStore: (base: EntityStore, optimistic: OptimisticState) => EntityStore;
698
- /**
699
- * A fresh page is newer than any settled overlay it covers: an edge the page
700
- * carries no longer needs an insert overlay, and a `remove` overlay hiding it
701
- * is stale (the server says it is back). A pending request's overlays are
702
- * left alone; they settle with the request.
703
- */
704
- declare const pruneOverlays: (optimistic: OptimisticState, connection: string, covered: ReadonlySet<string>, pending: ReadonlySet<string>) => OptimisticState;
705
- /**
706
- * Applies a result idempotently and releases the request's layer and overlays:
707
- * a later layer re-wins on rebase. Confirmed connection changes are recorded
708
- * once per request, as overlays the request no longer owns.
709
- */
710
- declare const settleSuccess: (base: EntityStore, optimistic: OptimisticState, state: MutationState, requestId: string, answer: MutationAnswer & {
711
- /** Connection changes the server confirmed; they replace the request's own. */
712
- readonly connections?: ReadonlyArray<ConnectionChange> | undefined;
713
- }) => {
714
- readonly store: EntityStore;
715
- readonly state: MutationState;
716
- readonly optimistic: OptimisticState;
717
- };
718
- /** A failed request's layer and overlays are dropped; the base was never mutated. */
719
- declare const settleFailure: (optimistic: OptimisticState, requestId: string) => OptimisticState;
720
- /**
721
- * Visible edges for one connection: applicable overlays are placed outside the
722
- * server-known segments and de-duplicated by edge identity (across overlays too),
723
- * so a pending insert never corrupts server-known ordering; a `remove` overlay
724
- * hides its edges wherever they are, and so does a tombstone on the edge's
725
- * target when `store` is given. A later prepend lands before an earlier one, a
726
- * later append after, so pending inserts read in the order they were made.
727
- * Boundaries still come from the connection's segments.
728
- */
729
- declare const visibleItems: (connection: Connection, connectionId: string, overlays: ReadonlyArray<ConnectionOverlay>, store?: EntityStore) => ReadonlyArray<Edge>;
730
- //#endregion
731
- //#region src/live.d.ts
732
- type LiveCursor = number;
733
- type LiveEvent = {
734
- readonly _tag: 'EntityPatched';
735
- readonly ref: EdgeRef;
736
- readonly values: Readonly<Record<string, unknown>>;
737
- readonly changed: ReadonlyArray<string>;
738
- readonly cursor: LiveCursor;
739
- } | {
740
- readonly _tag: 'EntityDeleted';
741
- readonly ref: EdgeRef;
742
- readonly cursor: LiveCursor;
743
- } | {
744
- readonly _tag: 'ConnectionInsert';
745
- readonly connection: string;
746
- readonly position: 'prepend' | 'append';
747
- readonly edge: Edge;
748
- readonly cursor: LiveCursor;
749
- } | {
750
- readonly _tag: 'ConnectionRemove';
751
- readonly connection: string;
752
- readonly edge: Edge;
753
- readonly cursor: LiveCursor;
754
- } | {
755
- readonly _tag: 'ConnectionInvalidate';
756
- readonly connection: string;
757
- readonly cursor: LiveCursor;
758
- };
759
- interface BoundaryCounts {
760
- readonly before: number;
761
- readonly after: number;
762
- }
763
- interface LiveState {
764
- /** Last applied cursor for this stream. */
765
- readonly cursor: LiveCursor;
766
- /** Edges recorded outside the loaded boundary, not visible in `items`. */
767
- readonly boundary: Readonly<Record<string, BoundaryCounts>>;
768
- }
769
- declare const emptyLiveState: LiveState;
770
- type LiveOutcome = 'applied' | 'duplicate' | 'gap';
771
- /**
772
- * Ordering per stream: at most the next cursor; ahead is a gap. Cursor `0` means
773
- * "no baseline yet" (cursors are 1-based), so the first event of a stream is
774
- * accepted whatever its cursor — otherwise a stream not starting at 1 would be a
775
- * spurious gap.
776
- */
777
- declare const classifyLive: (state: LiveState, cursor: LiveCursor) => LiveOutcome;
778
- interface EntityApplied {
779
- readonly state: LiveState;
780
- readonly store: EntityStore;
781
- readonly outcome: LiveOutcome;
782
- }
783
- declare const applyEntityEvent: (state: LiveState, store: EntityStore, event: Extract<LiveEvent, {
784
- _tag: "EntityPatched" | "EntityDeleted";
785
- }>, now?: number) => EntityApplied;
786
- interface ConnectionApplied {
787
- readonly state: LiveState;
788
- readonly optimistic: OptimisticState;
789
- readonly outcome: LiveOutcome;
790
- /**
791
- * A connection the event says to refetch. Reported rather than recorded here,
792
- * because staleness lives on the connection in the Model — which is what the
793
- * planner and every read consult. It used to be written into a set on this
794
- * live state that nothing read, so an invalidating event did nothing at all.
795
- */
796
- readonly invalidated?: string | undefined;
797
- }
798
- declare const applyConnectionEvent: (state: LiveState, optimistic: OptimisticState, event: Extract<LiveEvent, {
799
- _tag: "ConnectionInsert" | "ConnectionRemove" | "ConnectionInvalidate";
800
- }>, policy?: LivePolicy) => ConnectionApplied;
801
- /** `hasPrevious` accounting for edges recorded outside the loaded boundary. */
802
- declare const liveHasPrevious: (connection: Connection, state: LiveState, connectionId: string) => boolean;
803
- /** `hasNext` accounting for edges recorded outside the loaded boundary. */
804
- declare const liveHasNext: (connection: Connection, state: LiveState, connectionId: string) => boolean;
805
- //#endregion
806
- //#region src/retain.d.ts
807
- /** A connection to keep: its identity, and what a page of it selects of each item, if a projection reads it. */
808
- interface ConnectionRoot {
809
- readonly identity: string;
810
- readonly select?: RelationRequirement | undefined;
811
- }
812
- interface RetentionRoots {
813
- readonly requirements: ReadonlyArray<Requirement>;
814
- /** Connections (`QueryRef.identity`) to keep, with their edges' targets and what `select` reaches through them. */
815
- readonly connections: ReadonlyArray<ConnectionRoot>;
816
- }
817
- interface Retained {
818
- readonly entities: EntityStore;
819
- readonly connections: Readonly<Record<string, Connection>>;
820
- readonly optimistic: OptimisticState;
821
- }
822
- /**
823
- * The entity keys the roots reach: each root entity, the targets its retained
824
- * fields refer to, and recursively the targets a nested relation selects.
825
- */
826
- declare const reachable: (store: EntityStore, roots: RetentionRoots, connections: Readonly<Record<string, Connection>>, optimistic: OptimisticState, pending: ReadonlySet<string>) => ReadonlySet<EntityKey>;
827
- /**
828
- * Drops every entity the roots do not reach, every connection they do not
829
- * name, and every settled overlay on a dropped connection, keeping whatever a
830
- * pending request's layer or overlays touch. Pure.
831
- */
832
- declare const gc: (state: Retained & {
833
- readonly mutations: MutationState;
834
- }, roots: RetentionRoots) => Retained;
835
- //#endregion
836
- //#region src/persistence.d.ts
837
- /** Bump when the serialized shape changes; a mismatch discards the cache. */
838
- declare const REMOTE_CACHE_VERSION = 5;
839
- /**
840
- * What survives a reload: the entity cache, and the connections an application
841
- * **declared** should come back.
842
- *
843
- * Connections are session state by default and stay that way — `snapshotOf`
844
- * takes none unless asked. What a declared one keeps is its **edges and
845
- * nothing else**, which is not a simplification but the rule: a connection's
846
- * boundaries are cursors the server minted, and a cursor may name server state
847
- * that no longer exists. Restoring one would be claiming to know where the
848
- * page ends. The shape has nowhere to put a cursor, so that cannot be got
849
- * wrong later.
850
- */
851
- interface Snapshot {
852
- readonly entities: EntityStore;
853
- /**
854
- * By connection identity: its **segments**, each a run of edges. No
855
- * boundaries.
856
- *
857
- * Segments rather than one flat list, because the gaps between them are
858
- * knowledge too. A connection paged from both ends holds a head and a tail
859
- * with an unfetched middle; flattening those into one run would claim the
860
- * tail's first row follows the head's last, which is a thing the client was
861
- * never told.
862
- */
863
- readonly connections: Readonly<Record<string, ReadonlyArray<ReadonlyArray<Edge>>>>;
864
- }
865
- interface SnapshotOptions {
866
- /**
867
- * Who or what the snapshot is for (a user id, a tenant, a build). A snapshot
868
- * taken under another scope is discarded rather than shown to the wrong
869
- * reader. Default: unscoped, which only matches unscoped.
870
- */
871
- readonly scope?: string | undefined;
872
- /** Snapshots larger than this many bytes are not written and not read. */
873
- readonly maxBytes?: number | undefined;
874
- }
875
- /** How a snapshot meets a store that already has entries. */
876
- type MergePolicy = 'replace' | 'preserve-existing';
877
- /**
878
- * The snapshot text, or `undefined` when it would exceed `maxBytes`. Build the
879
- * snapshot with `snapshotOf`, which is where the connections that survive are
880
- * named; runtime state — optimistic layers, live cursors, gaps, the mutation
881
- * ledger — is never in one.
882
- */
883
- declare function dehydrate(snapshot: Snapshot, options?: SnapshotOptions & {
884
- readonly maxBytes?: undefined;
885
- }): string;
886
- declare function dehydrate(snapshot: Snapshot, options?: SnapshotOptions): string | undefined;
887
- declare const RemotePersistence: {
888
- /** The snapshot text, or `undefined` when it would exceed `maxBytes`. */
889
- dehydrate: typeof dehydrate;
890
- /** What a snapshot text holds, or `undefined` when it is refused. */
891
- hydrate: (raw: string | undefined | null, options?: SnapshotOptions) => Snapshot | undefined;
892
- /**
893
- * What to keep of a Model, naming the connections that should survive a
894
- * reload. Naming none is the default and is what Remote always did.
895
- */
896
- snapshotOf: (model: {
897
- readonly entities: EntityStore;
898
- readonly connections: Readonly<Record<string, Connection>>;
899
- }, options?: {
900
- readonly connections?: ReadonlyArray<ConnectionIdentity> | undefined;
901
- }) => Snapshot;
902
- /** A snapshot's entities brought into a store by policy. */
903
- mergeStores: (current: EntityStore, snapshot: EntityStore, policy: MergePolicy) => EntityStore;
904
- /** The cache as a fresh session has it; what a refused `restore` yields. */
905
- emptySnapshot: Snapshot;
906
- /**
907
- * Writes the snapshot under `key`, or removes the key when the store would
908
- * exceed `maxBytes`, so a stale smaller snapshot cannot outlive a larger
909
- * store it no longer describes.
910
- */
911
- save: (snapshot: Snapshot, options: {
912
- readonly key: string;
913
- } & SnapshotOptions) => Effect.Effect<void, KeyValueStore.KeyValueStoreError, KeyValueStore.KeyValueStore>;
914
- /**
915
- * Reads the cache. A missing key yields `emptySnapshot`; anything `hydrate`
916
- * refuses yields `emptySnapshot` and removes the key, so the next `restore`
917
- * is clean and the planner refetches.
918
- */
919
- restore: (options: {
920
- readonly key: string;
921
- } & SnapshotOptions) => Effect.Effect<Snapshot, KeyValueStore.KeyValueStoreError, KeyValueStore.KeyValueStore>;
922
- };
923
- //#endregion
924
- //#region src/wire.d.ts
925
- /**
926
- * The read/live protocol version. A batch names the version it speaks and the
927
- * server refuses a mismatch with `RemoteProtocolError`, so a shape change never
928
- * drifts silently: bump it whenever `ReadRequest` or `LiveRequirement` change.
929
- */
930
- declare const REMOTE_PROTOCOL_VERSION = 4;
931
- declare const RemoteReadError_base: Schema.Class<RemoteReadError, Schema.TaggedStruct<"RemoteReadError", {
932
- readonly message: Schema.String;
933
- }>, import("effect/Cause").YieldableError>;
934
- declare class RemoteReadError extends RemoteReadError_base {}
935
- declare const RemoteMutationError_base: Schema.Class<RemoteMutationError, Schema.TaggedStruct<"RemoteMutationError", {
936
- readonly message: Schema.String;
937
- /** The mutation's own `Refusal`, encoded, when the server refused it as one. */
938
- readonly refusal: Schema.optional<Schema.Unknown>;
939
- }>, import("effect/Cause").YieldableError>;
940
- declare class RemoteMutationError extends RemoteMutationError_base {}
941
- declare const RemoteForbidden_base: Schema.Class<RemoteForbidden, Schema.TaggedStruct<"Forbidden", {
942
- readonly message: Schema.String;
943
- readonly reason: Schema.optional<Schema.String>;
944
- }>, import("effect/Cause").YieldableError>;
945
- /**
946
- * The server refused who is asking: they may not do this, and asking again
947
- * as the same principal is refused again. `reason` is the application's own
948
- * words for the person who asked; without it the refusal says nothing of why.
949
- */
950
- declare class RemoteForbidden extends RemoteForbidden_base {}
951
- declare const RemoteLiveError_base: Schema.Class<RemoteLiveError, Schema.TaggedStruct<"RemoteLiveError", {
952
- readonly message: Schema.String;
953
- }>, import("effect/Cause").YieldableError>;
954
- declare class RemoteLiveError extends RemoteLiveError_base {}
955
- declare const RemoteProtocolError_base: Schema.Class<RemoteProtocolError, Schema.TaggedStruct<"RemoteProtocolError", {
956
- readonly message: Schema.String;
957
- readonly expected: Schema.Number;
958
- readonly received: Schema.Number;
959
- }>, import("effect/Cause").YieldableError>;
960
- /** The peer speaks another protocol version; nothing was read. */
961
- declare class RemoteProtocolError extends RemoteProtocolError_base {}
962
- /** A page size: a non-negative integer, refused at decode otherwise rather than defaulted. */
963
- declare const PageSize: Schema.Number;
964
- declare const WindowSchema: Schema.Struct<{
965
- readonly first: Schema.optional<Schema.Number>;
966
- readonly last: Schema.optional<Schema.Number>;
967
- readonly after: Schema.optional<Schema.String>;
968
- readonly before: Schema.optional<Schema.String>;
969
- }>;
970
- /** A request may not name more fields of one entity than this; a selection never does. */
971
- declare const MAX_FIELDS_PER_REQUEST = 256;
972
- /** A selection may not nest relations deeper than this; the wire refuses more. */
973
- declare const MAX_RELATION_DEPTH = 8;
974
- declare const RelationRequest: Schema.Codec<RelationRequirement, RelationRequirement, never, never>;
975
- declare const ReadRequest: Schema.Codec<Requirement, Requirement>;
976
- declare const ReadBatch: Schema.Struct<{
977
- readonly version: Schema.Number;
978
- readonly requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
979
- }>;
980
- declare const NormalizedEntity: Schema.Struct<{
981
- readonly entity: Schema.String;
982
- readonly id: Schema.String;
983
- readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
984
- }>;
705
+ declare class RemoteForbidden extends RemoteForbidden_base {}
706
+ declare const RemoteLiveError_base: Schema.Class<RemoteLiveError, Schema.TaggedStruct<"RemoteLiveError", {
707
+ readonly message: Schema.String;
708
+ }>, import("effect/Cause").YieldableError>;
709
+ declare class RemoteLiveError extends RemoteLiveError_base {}
710
+ declare const RemoteProtocolError_base: Schema.Class<RemoteProtocolError, Schema.TaggedStruct<"RemoteProtocolError", {
711
+ readonly message: Schema.String;
712
+ readonly expected: Schema.Number;
713
+ readonly received: Schema.Number;
714
+ }>, import("effect/Cause").YieldableError>;
715
+ /** The peer speaks another protocol version; nothing was read. */
716
+ declare class RemoteProtocolError extends RemoteProtocolError_base {}
717
+ /** A page size: a non-negative integer, refused at decode otherwise rather than defaulted. */
718
+ declare const PageSize: Schema.Number;
719
+ declare const WindowSchema: Schema.Struct<{
720
+ readonly first: Schema.optional<Schema.Number>;
721
+ readonly last: Schema.optional<Schema.Number>;
722
+ readonly after: Schema.optional<Schema.String>;
723
+ readonly before: Schema.optional<Schema.String>;
724
+ }>;
725
+ /** A request may not name more fields of one entity than this; a selection never does. */
726
+ declare const MAX_FIELDS_PER_REQUEST = 256;
727
+ /** A selection may not nest relations deeper than this; the wire refuses more. */
728
+ declare const MAX_RELATION_DEPTH = 8;
729
+ declare const RelationRequest: Schema.Codec<RelationRequirement, RelationRequirement, never, never>;
730
+ declare const ReadRequest: Schema.Codec<Requirement, Requirement>;
731
+ declare const ReadBatch: Schema.Struct<{
732
+ readonly version: Schema.Number;
733
+ readonly requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
734
+ }>;
735
+ declare const NormalizedEntity: Schema.Struct<{
736
+ readonly entity: Schema.String;
737
+ readonly id: Schema.String;
738
+ readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
739
+ }>;
985
740
  /**
986
741
  * Fields a read asked for that the server answered without, and will not
987
742
  * answer with: the client stops asking. It says nothing about why, so a rule
@@ -1333,21 +1088,47 @@ declare const QueryRpc: Rpc.Rpc<"FoldkitRemoteQuery", Schema.Struct<{
1333
1088
  readonly fields: Schema.$Array<Schema.String>;
1334
1089
  }>>>;
1335
1090
  }>, typeof RemoteQueryError, never, never>;
1336
- declare const RemoteRpc: RpcGroup.RpcGroup<Rpc.Rpc<"FoldkitRemoteRead", Schema.Struct<{
1091
+ declare const RemoteRpc: RpcGroup.RpcGroup<Rpc.Rpc<"FoldkitRemoteLive", Schema.Struct<{
1337
1092
  readonly version: Schema.Number;
1338
- readonly requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
1093
+ readonly requirements: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
1094
+ /** Resume cursor; events at or before it are duplicates. */
1095
+ readonly after: Schema.Number;
1096
+ }>, import("effect/rpc/RpcSchema").Stream<Schema.Union<readonly [Schema.Struct<{
1097
+ readonly _tag: Schema.Literal<"EntityPatched">;
1098
+ readonly cursor: Schema.Number;
1099
+ readonly entity: Schema.String;
1100
+ readonly id: Schema.String;
1101
+ readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
1102
+ readonly changed: Schema.$Array<Schema.String>;
1339
1103
  }>, Schema.Struct<{
1340
- readonly entities: Schema.$Array<Schema.Struct<{
1104
+ readonly _tag: Schema.Literal<"EntityDeleted">;
1105
+ readonly cursor: Schema.Number;
1106
+ readonly entity: Schema.String;
1107
+ readonly id: Schema.String;
1108
+ }>, Schema.Struct<{
1109
+ readonly _tag: Schema.Literal<"ConnectionInsert">;
1110
+ readonly cursor: Schema.Number;
1111
+ readonly connection: Schema.String;
1112
+ readonly position: Schema.Union<readonly [Schema.Literal<"prepend">, Schema.Literal<"append">]>;
1113
+ readonly edge: Schema.Struct<{
1341
1114
  readonly entity: Schema.String;
1342
1115
  readonly id: Schema.String;
1343
- readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
1344
- }>>;
1345
- readonly settled: Schema.$Array<Schema.Struct<{
1116
+ readonly key: Schema.String;
1117
+ }>;
1118
+ }>, Schema.Struct<{
1119
+ readonly _tag: Schema.Literal<"ConnectionRemove">;
1120
+ readonly cursor: Schema.Number;
1121
+ readonly connection: Schema.String;
1122
+ readonly edge: Schema.Struct<{
1346
1123
  readonly entity: Schema.String;
1347
1124
  readonly id: Schema.String;
1348
- readonly fields: Schema.$Array<Schema.String>;
1349
- }>>;
1350
- }>, Schema.Union<readonly [typeof RemoteReadError, typeof RemoteProtocolError]>, never, never> | Rpc.Rpc<"FoldkitRemoteMutate", Schema.Struct<{
1125
+ readonly key: Schema.String;
1126
+ }>;
1127
+ }>, Schema.Struct<{
1128
+ readonly _tag: Schema.Literal<"ConnectionInvalidate">;
1129
+ readonly cursor: Schema.Number;
1130
+ readonly connection: Schema.String;
1131
+ }>]>, Schema.Union<readonly [typeof RemoteLiveError, typeof RemoteProtocolError]>>, Schema.Never, never, never> | Rpc.Rpc<"FoldkitRemoteMutate", Schema.Struct<{
1351
1132
  /** Stable across transport retries so a mutation is not applied twice. */
1352
1133
  readonly requestId: Schema.String;
1353
1134
  readonly mutation: Schema.String;
@@ -1385,47 +1166,7 @@ declare const RemoteRpc: RpcGroup.RpcGroup<Rpc.Rpc<"FoldkitRemoteRead", Schema.S
1385
1166
  readonly entity: Schema.String;
1386
1167
  readonly id: Schema.String;
1387
1168
  }>>>;
1388
- }>, Schema.Union<readonly [typeof RemoteMutationError, typeof RemoteForbidden]>, never, never> | Rpc.Rpc<"FoldkitRemoteLive", Schema.Struct<{
1389
- readonly version: Schema.Number;
1390
- readonly requirements: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
1391
- /** Resume cursor; events at or before it are duplicates. */
1392
- readonly after: Schema.Number;
1393
- }>, import("effect/rpc/RpcSchema").Stream<Schema.Union<readonly [Schema.Struct<{
1394
- readonly _tag: Schema.Literal<"EntityPatched">;
1395
- readonly cursor: Schema.Number;
1396
- readonly entity: Schema.String;
1397
- readonly id: Schema.String;
1398
- readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
1399
- readonly changed: Schema.$Array<Schema.String>;
1400
- }>, Schema.Struct<{
1401
- readonly _tag: Schema.Literal<"EntityDeleted">;
1402
- readonly cursor: Schema.Number;
1403
- readonly entity: Schema.String;
1404
- readonly id: Schema.String;
1405
- }>, Schema.Struct<{
1406
- readonly _tag: Schema.Literal<"ConnectionInsert">;
1407
- readonly cursor: Schema.Number;
1408
- readonly connection: Schema.String;
1409
- readonly position: Schema.Union<readonly [Schema.Literal<"prepend">, Schema.Literal<"append">]>;
1410
- readonly edge: Schema.Struct<{
1411
- readonly entity: Schema.String;
1412
- readonly id: Schema.String;
1413
- readonly key: Schema.String;
1414
- }>;
1415
- }>, Schema.Struct<{
1416
- readonly _tag: Schema.Literal<"ConnectionRemove">;
1417
- readonly cursor: Schema.Number;
1418
- readonly connection: Schema.String;
1419
- readonly edge: Schema.Struct<{
1420
- readonly entity: Schema.String;
1421
- readonly id: Schema.String;
1422
- readonly key: Schema.String;
1423
- }>;
1424
- }>, Schema.Struct<{
1425
- readonly _tag: Schema.Literal<"ConnectionInvalidate">;
1426
- readonly cursor: Schema.Number;
1427
- readonly connection: Schema.String;
1428
- }>]>, Schema.Union<readonly [typeof RemoteLiveError, typeof RemoteProtocolError]>>, Schema.Never, never, never> | Rpc.Rpc<"FoldkitRemoteQuery", Schema.Struct<{
1169
+ }>, Schema.Union<readonly [typeof RemoteMutationError, typeof RemoteForbidden]>, never, never> | Rpc.Rpc<"FoldkitRemoteQuery", Schema.Struct<{
1429
1170
  readonly query: Schema.String;
1430
1171
  readonly input: Schema.Unknown;
1431
1172
  readonly window: Schema.Struct<{
@@ -1467,1022 +1208,1204 @@ declare const RemoteRpc: RpcGroup.RpcGroup<Rpc.Rpc<"FoldkitRemoteRead", Schema.S
1467
1208
  * returns. Absent from a server that predates payload planning: the client
1468
1209
  * reads it as empty and fetches fields as before.
1469
1210
  */
1470
- readonly entities: Schema.optional<Schema.$Array<Schema.Struct<{
1471
- readonly entity: Schema.String;
1472
- readonly id: Schema.String;
1473
- readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
1474
- }>>>;
1475
- readonly settled: Schema.optional<Schema.$Array<Schema.Struct<{
1476
- readonly entity: Schema.String;
1477
- readonly id: Schema.String;
1478
- readonly fields: Schema.$Array<Schema.String>;
1479
- }>>>;
1480
- }>, typeof RemoteQueryError, never, never>>;
1211
+ readonly entities: Schema.optional<Schema.$Array<Schema.Struct<{
1212
+ readonly entity: Schema.String;
1213
+ readonly id: Schema.String;
1214
+ readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
1215
+ }>>>;
1216
+ readonly settled: Schema.optional<Schema.$Array<Schema.Struct<{
1217
+ readonly entity: Schema.String;
1218
+ readonly id: Schema.String;
1219
+ readonly fields: Schema.$Array<Schema.String>;
1220
+ }>>>;
1221
+ }>, typeof RemoteQueryError, never, never> | Rpc.Rpc<"FoldkitRemoteRead", Schema.Struct<{
1222
+ readonly version: Schema.Number;
1223
+ readonly requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
1224
+ }>, Schema.Struct<{
1225
+ readonly entities: Schema.$Array<Schema.Struct<{
1226
+ readonly entity: Schema.String;
1227
+ readonly id: Schema.String;
1228
+ readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
1229
+ }>>;
1230
+ readonly settled: Schema.$Array<Schema.Struct<{
1231
+ readonly entity: Schema.String;
1232
+ readonly id: Schema.String;
1233
+ readonly fields: Schema.$Array<Schema.String>;
1234
+ }>>;
1235
+ }>, Schema.Union<readonly [typeof RemoteReadError, typeof RemoteProtocolError]>, never, never>>;
1236
+ //#endregion
1237
+ //#region src/coalesce.d.ts
1238
+ type Batch = Schema.Schema.Type<typeof ReadBatch>;
1239
+ type BatchResult = Schema.Schema.Type<typeof ReadBatchResult>;
1240
+ type ReadError = RemoteReadError | RemoteProtocolError;
1241
+ type BatchRead = (batch: Batch) => Effect.Effect<BatchResult, ReadError>;
1242
+ type QueryRequestValue = Schema.Schema.Type<typeof QueryRequest>;
1243
+ type QueryResultValue = Schema.Schema.Type<typeof QueryResult>;
1244
+ type QueryRun = (request: QueryRequestValue) => Effect.Effect<QueryResultValue, RemoteQueryError>;
1245
+ interface CoalesceOptions {
1246
+ /**
1247
+ * How long a batch waits to collect more requirements before it runs.
1248
+ * Requirements issued concurrently coalesce even at the default of no wait.
1249
+ */
1250
+ readonly window?: Duration.Input | undefined;
1251
+ }
1252
+ /** A stable key for a requirement, so an equal requirement in flight is joined. */
1253
+ declare const requirementKey: (requirement: Requirement) => string;
1254
+ /**
1255
+ * Wraps a raw query so that an identical query in flight (same query, input,
1256
+ * and window) is joined rather than run again; distinct queries run
1257
+ * concurrently. A page answers exactly one window, so nothing is batched.
1258
+ */
1259
+ declare const coalesceQueries: (query: QueryRun, options?: CoalesceOptions) => Effect.Effect<QueryRun>;
1260
+ /**
1261
+ * Wraps a raw batch read so that requirements are batched and deduplicated.
1262
+ * Every waiter receives the whole batch result; `Remote.writeRead` is
1263
+ * idempotent, so writing it more than once is harmless.
1264
+ */
1265
+ declare const coalesceReads: (read: BatchRead, options?: CoalesceOptions) => Effect.Effect<BatchRead>;
1481
1266
  //#endregion
1482
- //#region src/model.d.ts
1267
+ //#region src/live.d.ts
1268
+ type LiveCursor = number;
1269
+ type LiveEvent = {
1270
+ readonly _tag: 'EntityPatched';
1271
+ readonly ref: EdgeRef;
1272
+ readonly values: Readonly<Record<string, unknown>>;
1273
+ readonly changed: ReadonlyArray<string>;
1274
+ readonly cursor: LiveCursor;
1275
+ } | {
1276
+ readonly _tag: 'EntityDeleted';
1277
+ readonly ref: EdgeRef;
1278
+ readonly cursor: LiveCursor;
1279
+ } | {
1280
+ readonly _tag: 'ConnectionInsert';
1281
+ readonly connection: string;
1282
+ readonly position: 'prepend' | 'append';
1283
+ readonly edge: Edge;
1284
+ readonly cursor: LiveCursor;
1285
+ } | {
1286
+ readonly _tag: 'ConnectionRemove';
1287
+ readonly connection: string;
1288
+ readonly edge: Edge;
1289
+ readonly cursor: LiveCursor;
1290
+ } | {
1291
+ readonly _tag: 'ConnectionInvalidate';
1292
+ readonly connection: string;
1293
+ readonly cursor: LiveCursor;
1294
+ };
1295
+ interface BoundaryCounts {
1296
+ readonly before: number;
1297
+ readonly after: number;
1298
+ }
1299
+ interface LiveState {
1300
+ /** Last applied cursor for this stream. */
1301
+ readonly cursor: LiveCursor;
1302
+ /** Edges recorded outside the loaded boundary, not visible in `items`. */
1303
+ readonly boundary: Readonly<Record<string, BoundaryCounts>>;
1304
+ }
1305
+ declare const emptyLiveState: LiveState;
1306
+ type LiveOutcome = 'applied' | 'duplicate' | 'gap';
1483
1307
  /**
1484
- * The normalized cache as a Foldkit Submodel. `Remote.define` returns a schema
1485
- * and an `update` for this shape; `updateRemote` reconciles every producer.
1308
+ * Ordering per stream: at most the next cursor; ahead is a gap. Cursor `0` means
1309
+ * "no baseline yet" (cursors are 1-based), so the first event of a stream is
1310
+ * accepted whatever its cursor — otherwise a stream not starting at 1 would be a
1311
+ * spurious gap.
1486
1312
  */
1487
- interface RemoteModel {
1488
- /** Entity values, presence, staleness, tombstones, and applied windows. */
1489
- readonly entities: EntityStore;
1490
- /** Normalized ordered connections, keyed by connection identity. */
1491
- readonly connections: Readonly<Record<string, Connection>>;
1492
- /**
1493
- * How many rows `Data.more` has grown a read's window to, by
1494
- * `windowGrowthKey`. A read shows at most its window, so this is what "load
1495
- * more" changes; it lives here because a list holds no state of its own.
1496
- */
1497
- readonly grown: Readonly<Record<string, number>>;
1498
- /** Optimistic entity layers and connection overlays over the base store. */
1313
+ declare const classifyLive: (state: LiveState, cursor: LiveCursor) => LiveOutcome;
1314
+ interface EntityApplied {
1315
+ readonly state: LiveState;
1316
+ readonly store: EntityStore;
1317
+ readonly outcome: LiveOutcome;
1318
+ }
1319
+ declare const applyEntityEvent: (state: LiveState, store: EntityStore, event: Extract<LiveEvent, {
1320
+ _tag: 'EntityPatched' | 'EntityDeleted';
1321
+ }>, now?: number) => EntityApplied;
1322
+ interface ConnectionApplied {
1323
+ readonly state: LiveState;
1499
1324
  readonly optimistic: OptimisticState;
1500
- /** Live cursor and boundary state, keyed by the subscription's stream key. */
1501
- readonly live: Readonly<Record<string, LiveState>>;
1502
- /** Mutation pending/applied/failed ledger. */
1503
- readonly mutations: MutationState;
1504
- /**
1505
- * Streams that broke, by an error or by an event ahead of their cursor, and
1506
- * have not resubscribed since: changes after the break are missed until the
1507
- * live entry restarts them and refetches what they cover.
1508
- */
1509
- readonly gaps: ReadonlySet<string>;
1510
- /** Each live stream that has ever broken, by stream key. One that never broke is absent. */
1511
- readonly streams: Readonly<Record<string, StreamHealth>>;
1512
- /**
1513
- * The `entity\0id\0field` marks a read is currently fetching. A field absent
1514
- * from the store reads as `Loading` while its mark is here and `Initial`
1515
- * otherwise, which is what separates "being fetched" from "nothing is
1516
- * fetching this".
1517
- */
1518
- readonly loading: ReadonlySet<string>;
1519
- /**
1520
- * `Remote.refresh` generations, held per field rather than for the store as a
1521
- * whole. A read entry restarts when the generation over the fields it plans
1522
- * moves, so a read sent before a refresh of its own fields cannot land after
1523
- * it, and a refresh of one field leaves every other entry's read alone.
1524
- */
1525
- readonly refresh: RefreshState;
1526
- /**
1527
- * The reads that failed and have not been settled since, so a read can say
1528
- * `Failed` rather than `Initial`.
1529
- *
1530
- * Without them a read that failed before anything loaded read exactly like
1531
- * one nobody had asked for, and nothing asked again: a read entry restarts
1532
- * only when what it plans changes, and a failure changed nothing. What failed
1533
- * is not planned again on its own either, so a persistent error is not
1534
- * retried every time an unrelated read restarts the entry. `Remote.refresh`
1535
- * is how a view retries.
1536
- */
1537
- readonly failures: Failures;
1538
- /**
1539
- * The storage key the cache was last restored from, through `Hydrated`'s
1540
- * `from`. `Data.persistence` saves under a key only once its own snapshot is
1541
- * in, so a save at startup cannot write the empty store over it.
1542
- */
1543
- readonly restoredFrom: Option.Option<string>;
1325
+ readonly outcome: LiveOutcome;
1544
1326
  /**
1545
- * Under `verifyPlacement`, the order each list was placed in, by edge key,
1546
- * and the rows placing took out of its first page, until the server's page
1547
- * for it arrives to be compared with them.
1327
+ * A connection the event says to refetch. Reported rather than recorded here,
1328
+ * because staleness lives on the connection in the Model — which is what the
1329
+ * planner and every read consult. It used to be written into a set on this
1330
+ * live state that nothing read, so an invalidating event did nothing at all.
1548
1331
  */
1549
- readonly placed: Readonly<Record<string, PlacedOrder>>;
1550
- /** Under `verifyPlacement`, each placement the server's page disagreed with. */
1551
- readonly placementMismatches: ReadonlyArray<PlacementMismatch>;
1332
+ readonly invalidated?: string | undefined;
1552
1333
  }
1553
- /** A list's first page as the client placed it: its keys in order, and those it took out. */
1554
- interface PlacedOrder {
1555
- readonly order: ReadonlyArray<string>;
1556
- readonly dropped: ReadonlyArray<string>;
1334
+ declare const applyConnectionEvent: (state: LiveState, optimistic: OptimisticState, event: Extract<LiveEvent, {
1335
+ _tag: 'ConnectionInsert' | 'ConnectionRemove' | 'ConnectionInvalidate';
1336
+ }>, policy?: LivePolicy) => ConnectionApplied;
1337
+ /** `hasPrevious` accounting for edges recorded outside the loaded boundary. */
1338
+ declare const liveHasPrevious: (connection: Connection, state: LiveState, connectionId: string) => boolean;
1339
+ /** `hasNext` accounting for edges recorded outside the loaded boundary. */
1340
+ declare const liveHasNext: (connection: Connection, state: LiveState, connectionId: string) => boolean;
1341
+ //#endregion
1342
+ //#region src/client.d.ts
1343
+ declare const RemoteClient_base: Context.ServiceClass<RemoteClient, "foldkit-remote/RemoteClient", {
1344
+ readonly read: (batch: Schema.Schema.Type<typeof ReadBatch>) => Effect.Effect<Schema.Schema.Type<typeof ReadBatchResult>, RemoteReadError | RemoteProtocolError>;
1345
+ readonly query: (request: Schema.Schema.Type<typeof QueryRequest>) => Effect.Effect<Schema.Schema.Type<typeof QueryResult>, RemoteQueryError>;
1346
+ readonly mutate: (request: Schema.Schema.Type<typeof MutationRequest>) => Effect.Effect<Schema.Schema.Type<typeof MutationResult>, RemoteMutationError | RemoteForbidden>;
1347
+ readonly live: (request: {
1348
+ readonly requirements: ReadonlyArray<Requirement>;
1349
+ readonly after: LiveCursor;
1350
+ }) => Stream.Stream<LiveEvent, RemoteLiveError | RemoteProtocolError>;
1351
+ }>;
1352
+ /**
1353
+ * The transport boundary. `foldkit-remote` never talks to a transport directly;
1354
+ * it depends on this Effect service, which a later phase wires to Effect RPC.
1355
+ */
1356
+ declare class RemoteClient extends RemoteClient_base {}
1357
+ /**
1358
+ * The methods an Effect RPC client for `RemoteRpc` exposes. `R` is the
1359
+ * environment a handler needs; it defaults to `never`, which is what a real
1360
+ * transport client satisfies. `RemoteServer.handlers` returns this type with its
1361
+ * own `R`, so the two sides cannot drift apart.
1362
+ *
1363
+ * `TransportError` is what the transport itself may fail with on top of the
1364
+ * declared errors: `RpcClientError` for the client `RpcClient.make` builds,
1365
+ * `never` for in-process handlers.
1366
+ */
1367
+ interface RemoteRpcClient<R = never, TransportError = never> {
1368
+ readonly FoldkitRemoteRead: (payload: Schema.Schema.Type<typeof ReadBatch>) => Effect.Effect<Schema.Schema.Type<typeof ReadBatchResult>, RemoteReadError | RemoteProtocolError | TransportError, R>;
1369
+ readonly FoldkitRemoteQuery: (payload: Schema.Schema.Type<typeof QueryRequest>) => Effect.Effect<Schema.Schema.Type<typeof QueryResult>, RemoteQueryError | TransportError, R>;
1370
+ readonly FoldkitRemoteMutate: (payload: Schema.Schema.Type<typeof MutationRequest>) => Effect.Effect<Schema.Schema.Type<typeof MutationResult>, RemoteMutationError | RemoteForbidden | TransportError, R>;
1371
+ readonly FoldkitRemoteLive: (payload: Schema.Schema.Type<typeof LiveRequirement>) => Stream.Stream<Schema.Schema.Type<typeof LiveChange>, RemoteLiveError | RemoteProtocolError | TransportError, R>;
1557
1372
  }
1558
- /** A list the client placed rows in one order and the server then listed in another. */
1559
- interface PlacementMismatch {
1560
- readonly connection: string;
1561
- /** The keys as placed, as far as the server's page reached. */
1562
- readonly placed: ReadonlyArray<string>;
1563
- /** The keys of the server's first page. */
1564
- readonly served: ReadonlyArray<string>;
1373
+ /** Reconstructs the client's `ConnectionChange` from the wire's flattened edge. */
1374
+ declare const connectionChangeOf: (change: Schema.Schema.Type<typeof ConnectionChangeSchema>) => ConnectionChange;
1375
+ /** Reconstructs the client's `LiveEvent` from the wire's flattened `LiveChange`. */
1376
+ declare const liveEventOf: (change: Schema.Schema.Type<typeof LiveChange>) => LiveEvent;
1377
+ declare const remoteError: (error: {
1378
+ readonly _tag: string;
1379
+ readonly message: string;
1380
+ readonly refusal?: unknown;
1381
+ readonly reason?: string | undefined;
1382
+ }) => RemoteError;
1383
+ declare const coalescedLayer: <E, R>(layer: Layer.Layer<RemoteClient, E, R>, options?: CoalesceOptions) => Layer.Layer<RemoteClient, E, R>;
1384
+ /**
1385
+ * `Remote.mutate` as a standalone effect, so `Remote.mutateInto` can reuse it
1386
+ * without the object literal referencing itself.
1387
+ */
1388
+ declare const mutateRemote: <Name extends string, Input, Output>(mutation: MutationDescriptor<Name, Input, Output, unknown>, input: Input, requestId: string, keys?: readonly string[] | undefined) => Effect.Effect<{
1389
+ output: Output;
1390
+ entities: readonly {
1391
+ readonly entity: string;
1392
+ readonly id: string;
1393
+ readonly values: {
1394
+ readonly [x: string]: unknown;
1395
+ };
1396
+ }[];
1397
+ connections: ConnectionChange[];
1398
+ deleted: readonly {
1399
+ readonly entity: string;
1400
+ readonly id: string;
1401
+ }[];
1402
+ }, RemoteForbidden | RemoteMutationError, RemoteClient>;
1403
+ //#endregion
1404
+ //#region src/relation.d.ts
1405
+ interface RefParts {
1406
+ readonly entity: string;
1407
+ readonly id: string;
1565
1408
  }
1566
- /** How a live stream has fared, as its live entry restarts it. */
1567
- interface StreamHealth {
1568
- /** How many times it broke. The live entry restarts on each, so it only grows. */
1569
- readonly restarts: number;
1570
- /** Breaks since its last applied event: what the restart's backoff grows with. */
1571
- readonly failures: number;
1572
- /** Why it last broke; none for a gap, which is not an error. */
1573
- readonly error: Option.Option<RemoteError>;
1409
+ /** A page of refs as the wire and the store hold it. */
1410
+ interface RefPageValue {
1411
+ readonly refs: ReadonlyArray<string>;
1412
+ readonly hasNext: boolean;
1413
+ readonly hasPrevious: boolean;
1414
+ }
1415
+ /** Marks the codec `Entity.ref`/`Entity.refPage` produce, so a Selection can tell the field's shape. */
1416
+ declare const RelationAnnotation = "foldkitRemoteRelation";
1417
+ /** The target entity's name on the same codec, so a nested selection of another entity is refused. */
1418
+ declare const RelationEntityAnnotation = "foldkitRemoteRelationEntity";
1419
+ type RelationKind = 'one' | 'many' | 'page';
1420
+ interface RelationShape {
1421
+ readonly kind: RelationKind;
1422
+ readonly nullable: boolean;
1423
+ readonly entity: string;
1574
1424
  }
1575
1425
  /**
1576
- * Failed reads, as the errors they failed with.
1577
- *
1578
- * `connections` is by connection identity, and is settled by a page arriving,
1579
- * an invalidation, or retention dropping the connection. `fields` is by field
1580
- * mark (`entity\0id\0field`, the marks `loading` uses), and is settled by the
1581
- * field being written again, a refresh asking for it, or retention dropping the
1582
- * entity. A read of it in flight reads `Loading` over the failure without
1583
- * settling it: if that read fails too, the failure is simply recorded again.
1426
+ * A page of a relation that is a whole list is read under a name of its own, the
1427
+ * field's name and the page's size: `comments@first=10`. It is a field like any
1428
+ * other to the store, the planner, and the wire, so the whole list and a page of
1429
+ * it are held side by side, merged, marked stale, and persisted each on its own.
1430
+ * The server reads the name apart, reads the relation with the window, and
1431
+ * answers under the alias. A cursor is not part of the name: a page read from a
1432
+ * cursor merges onto the page it continues.
1584
1433
  */
1585
- interface Failures {
1586
- readonly connections: Readonly<Record<string, RemoteError>>;
1587
- readonly fields: Readonly<Record<string, RemoteError>>;
1588
- }
1589
- declare const noFailures: Failures;
1434
+ declare const RELATION_ALIAS = "@";
1435
+ /** The alias a relation field is read under, for a window of this size. */
1436
+ declare const relationAlias: (field: string, window: {
1437
+ readonly first?: number | undefined;
1438
+ readonly last?: number | undefined;
1439
+ readonly after?: string | undefined;
1440
+ readonly before?: string | undefined;
1441
+ }) => string;
1442
+ /** The field an alias reads; a name that is no alias is its own field. */
1443
+ declare const aliasedField: (name: string) => string;
1444
+ /** Splits a ref key (`"Entity:id"`, the store key too) back into its parts. */
1445
+ declare const refParts: (encoded: string) => RefParts;
1590
1446
  /**
1591
- * `Remote.refresh` generations, per field mark. `generation` is the last one
1592
- * handed out; `requested` is when each field was last refreshed, and `started`
1593
- * is the generation each field's read last began under. Holding them per field
1594
- * is what keeps one Projection's refresh from restarting every read entry.
1447
+ * The refs a relation value carries, in order. Anything that is not a ref key,
1448
+ * an array of them, or a page of them contributes nothing.
1595
1449
  */
1596
- interface RefreshState {
1597
- readonly generation: number;
1598
- readonly requested: ReadonlyMap<string, number>;
1599
- readonly started: ReadonlyMap<string, number>;
1600
- /**
1601
- * The generation every entry is refreshed at, at least: `forgetRemote` moves
1602
- * it, so every read and live entry restarts, and a read or stream begun for
1603
- * the principal before is interrupted rather than landing after.
1604
- */
1605
- readonly floor: number;
1450
+ declare const refsIn: (value: unknown) => ReadonlyArray<RefParts>;
1451
+ /** The refs in a relation value that name the relation's target entity, and no other. */
1452
+ declare const targetsOf: (value: unknown, relation: RelationRequirement) => ReadonlyArray<RefParts>;
1453
+ declare const isRefPage: (value: unknown) => value is RefPageValue;
1454
+ /**
1455
+ * The relation shape an entity field schema declares: a ref (`one`), a nullable
1456
+ * ref, an array of refs (`many`), or a page of refs (`page`). `undefined` for a
1457
+ * scalar field, which cannot take a nested selection.
1458
+ */
1459
+ declare const relationShape: (schema: Schema.Top) => RelationShape | undefined;
1460
+ //#endregion
1461
+ //#region src/selection.d.ts
1462
+ /** One page of a paginated relation with each target assembled through a nested selection. */
1463
+ interface Page<Item> {
1464
+ readonly items: ReadonlyArray<Item>;
1465
+ readonly hasNext: boolean;
1466
+ readonly hasPrevious: boolean;
1606
1467
  }
1607
- declare const emptyRefresh: RefreshState;
1608
1468
  /**
1609
- * The Model with everything the server told it forgotten: values, tombstones,
1610
- * unavailable fields, connections, live cursors, failures, and what is in
1611
- * flight. For a change of principal, whose facts these were. The mutation
1612
- * sequence is kept, so request ids stay unique, and a mutation in flight is
1613
- * treated as applied: its answer, when it comes, writes nothing here.
1469
+ * The fields a projection reads of one entity, plus the slice it reads of each
1470
+ * relation's target. `Shape` tells a parent selection whether this one is a
1471
+ * paginated relation (`connection`) or a plain entity slice (`entity`).
1614
1472
  */
1615
- declare const forgetRemote: (model: RemoteModel) => RemoteModel;
1616
- declare const initialRemoteModel: RemoteModel;
1617
- declare const remoteModelSchema: () => Schema.Codec<RemoteModel, unknown>;
1618
- /** The submodel's Messages; each reduces to `RemoteModel` through `updateRemote`. */
1619
- type RemoteMessage = {
1620
- readonly _tag: 'ReadReceived';
1621
- readonly requests: readonly Requirement[];
1622
- readonly result: Schema.Schema.Type<typeof ReadBatchResult>;
1623
- readonly now: number;
1624
- } | {
1625
- readonly _tag: 'ReadFailed';
1626
- readonly requests: readonly Requirement[];
1627
- readonly error: RemoteError;
1473
+ interface Selection<Value, Name extends string = string, Shape extends 'entity' | 'connection' = 'entity' | 'connection'> {
1474
+ readonly entity: Name;
1475
+ readonly fields: readonly string[];
1476
+ /** A pure codec: entity fields carry no decoding or encoding services. */
1477
+ readonly schema: Schema.Codec<Value, unknown, never, never>;
1478
+ /** Pagination windows for nested relation fields, keyed by field name. */
1479
+ readonly connections?: Readonly<Record<string, QueryWindow>> | undefined;
1480
+ /** The slice required of each nested relation's target, keyed by field name. */
1481
+ readonly relations?: Readonly<Record<string, RelationRequirement>> | undefined;
1482
+ /** Present when this selection is itself a paginated relation. */
1483
+ readonly window?: QueryWindow | undefined;
1484
+ /** Phantom: see `Shape`. */
1485
+ readonly shape?: Shape | undefined;
1486
+ }
1487
+ /** Flattens a mapped type so hovers show the picked fields, not the machinery. */
1488
+ type Simplify<T> = T extends (infer O) ? { readonly [K in keyof O]: O[K]; } : never;
1489
+ /** The value a Selection reads: `Selection.Value<typeof ProjectCard>`. */
1490
+ type SelectionValueOf<S> = S extends Selection<infer V, any, any> ? V : never;
1491
+ /** The nested selections a relation field admits: of its target entity, in the shapes its value takes. */
1492
+ type NestedFor<Field> = Exclude<Field, null | undefined> extends ReadonlyArray<EntityRef<infer Name, any>> ? Selection<unknown, Name, 'entity' | 'connection'> : Exclude<Field, null | undefined> extends RefPage<infer Name, any> ? Selection<unknown, Name, 'entity' | 'connection'> : Exclude<Field, null | undefined> extends EntityRef<infer Name, any> ? Selection<unknown, Name, 'entity'> : never;
1493
+ /** What a selection of an entity with fields `F` may pick: `true` per scalar, a nested selection per relation. */
1494
+ type SelectionOf<F extends Schema.Struct.Fields> = { readonly [K in keyof F]?: true | NestedFor<Schema.Schema.Type<F[K]>>; };
1495
+ /** `T | null` when the field admits `null` or `undefined` (both assemble to `null`). */
1496
+ type Nullable<Field, T> = [Extract<Field, null | undefined>] extends [never] ? T : T | null;
1497
+ /** A nested selection's value takes the shape of the field it selects through. */
1498
+ type NestedValue<Field, Sel> = Sel extends Selection<infer V, string, 'connection'> ? Nullable<Field, V> : Sel extends Selection<infer V, string, 'entity'> ? Nullable<Field, Exclude<Field, null | undefined> extends ReadonlyArray<EntityRef<any, any>> ? ReadonlyArray<V> : Exclude<Field, null | undefined> extends RefPage<any, any> ? Page<V> : V> : never;
1499
+ /** The value a selection `Sel` of fields `F` reads. */
1500
+ type SelectionValue<F extends Schema.Struct.Fields, Sel> = Simplify<{ readonly [K in keyof Sel & keyof F]: Sel[K] extends true ? Schema.Schema.Type<F[K]> : NestedValue<Schema.Schema.Type<F[K]>, Sel[K]>; }>;
1501
+ declare const pageSchema: (item: AnySchema) => AnySchema;
1502
+ /** The requirement a nested selection contributes for its relation's target. */
1503
+ declare const relationOf: (selection: Selection<unknown>) => RelationRequirement;
1504
+ declare const Selection: {
1628
1505
  /**
1629
- * The live stream whose subscription broke, when this is that rather
1630
- * than a read. Nothing was being read, so no field failed: the stream is
1631
- * recorded as a gap, since changes after it are missed until the live
1632
- * entry restarts it.
1506
+ * The Remote Selection of a `foldkit-entity` Selection: the same members, read
1507
+ * from Remote's store. `true` on a relation reads its refs, as it does here.
1633
1508
  */
1634
- readonly stream?: string | undefined;
1635
- } |
1636
- /** A refetch of present fields began; they read as `Refreshing` until it lands. */
1637
- {
1638
- readonly _tag: 'RefreshStarted';
1639
- readonly requests: readonly Requirement[];
1640
- } |
1641
- /** A read began; the fields it asks for that the store lacks read as `Loading`. */
1642
- {
1643
- readonly _tag: 'ReadStarted';
1644
- readonly requests: readonly Requirement[];
1645
- /** The refresh generation the read was planned under. */
1646
- readonly refresh?: number | undefined;
1647
- } |
1648
- /**
1649
- * Queries for these connections were sent. One with nothing to show reads
1650
- * `Loading` until its page or its failure arrives, which is what separates
1651
- * "being fetched" from `Initial`, "nothing is fetching this".
1652
- */
1653
- {
1654
- readonly _tag: 'QueryStarted';
1655
- readonly connections: readonly string[];
1656
- } |
1657
- /** The active Surfaces' roots changed; everything they do not reach is collected. */
1658
- {
1659
- readonly _tag: 'RetentionChanged';
1660
- readonly roots: RetentionRoots;
1661
- } |
1662
- /** A restored snapshot meets the store; runtime state is untouched. */
1663
- {
1664
- readonly _tag: 'Hydrated';
1665
- readonly entities: EntityStore;
1509
+ from: <Name extends string, S extends Schema.Constraint>(selection: Domain.Selection<Name, unknown, S>) => Selection<S['Type'], Name, 'entity'>;
1666
1510
  /**
1667
- * The connections a snapshot declared should survive, as their edges.
1668
- * Restored with **unknown** boundaries and marked stale: the rows show
1669
- * at once and the connection is refetched, because a persisted cursor
1670
- * may name server state that is gone.
1511
+ * The fields to read of `entity`. A nested `Selection` on a relation field
1512
+ * reads through the ref (or refs, or page of refs) the field holds into the
1513
+ * target's fields; a scalar field cannot take one.
1671
1514
  */
1672
- readonly connections?: Readonly<Record<string, ReadonlyArray<ReadonlyArray<Edge>>>> | undefined;
1673
- readonly merge: MergePolicy;
1674
- /** The storage key the snapshot was read from, when it was: `restoredFrom`. */
1675
- readonly from?: string | undefined;
1676
- } |
1677
- /** A mutation began; its optimistic operations show until it settles. */
1678
- {
1679
- readonly _tag: 'MutationStarted';
1680
- readonly requestId: string;
1681
- readonly optimistic?: ReadonlyArray<OptimisticOperation> | undefined;
1682
- } | {
1683
- readonly _tag: 'MutationSucceeded';
1684
- readonly requestId: string;
1685
- readonly entities: readonly NormalizedPatch[];
1686
- /** Connection changes the server confirmed; they replace the request's own. */
1687
- readonly connections?: ReadonlyArray<ConnectionChange> | undefined;
1688
- /** Entities the mutation deleted: tombstoned, which hides them from every connection. */
1689
- readonly deleted?: ReadonlyArray<{
1690
- readonly entity: string;
1691
- readonly id: string;
1692
- }> | undefined;
1693
- /** Injected clock reading of the answer: how fresh the written entities are. */
1694
- readonly now: number;
1695
- } | {
1696
- readonly _tag: 'MutationFailed';
1697
- readonly requestId: string;
1698
- readonly error: RemoteError;
1699
- } |
1700
- /**
1701
- * Operations shown over the store with no request behind them, until they are
1702
- * lifted: a preview of a change nobody has made. Showing an id again replaces
1703
- * what it showed.
1704
- */
1705
- {
1706
- readonly _tag: 'OverlayShown';
1707
- readonly id: string;
1708
- readonly optimistic: ReadonlyArray<OptimisticOperation>;
1709
- } | {
1710
- readonly _tag: 'OverlayLifted';
1711
- readonly id: string;
1712
- } |
1713
- /** `Data.more`: a read's window, by `windowGrowthKey`, now shows `size` rows. */
1714
- {
1715
- readonly _tag: 'WindowGrown';
1716
- readonly window: string;
1717
- readonly size: number;
1718
- } | {
1719
- readonly _tag: 'LiveReceived';
1720
- readonly stream: string;
1721
- readonly event: LiveEvent;
1722
- readonly policy?: LivePolicy;
1723
- readonly now: number;
1724
- } | {
1725
- readonly _tag: 'GapCleared';
1726
- readonly stream: string;
1727
- } | {
1728
- readonly _tag: 'ConnectionMerged';
1729
- readonly connection: string;
1730
- readonly page: Segment;
1731
- /** The page answers the connection's refresh, so the merge also clears `stale`. */
1732
- readonly refreshes?: boolean | undefined;
1515
+ make: <Name extends string, F extends Schema.Struct.Fields, const Sel extends SelectionOf<F>>(entity: EntityDescriptor<Name, F>, selection: Sel) => Selection<SelectionValue<F, Sel>, Name, 'entity'>;
1733
1516
  /**
1734
- * The slice the query asked for, so the payload's entities write like a
1735
- * read: one request per matching edge. Absent for a page from a server
1736
- * that predates payload planning, which carries edges only.
1517
+ * A paginated relation: one page of refs to `entity` with a window, or, with
1518
+ * a nested selection, one page of targets assembled through it.
1737
1519
  */
1738
- readonly select?: RelationRequirement | undefined;
1739
- /** The selected fields of the page's items, as a read batch returns them. */
1740
- readonly entities?: ReadonlyArray<{
1741
- readonly entity: string;
1742
- readonly id: string;
1743
- readonly values: Record<string, unknown>;
1744
- }> | undefined;
1745
- /** Fields asked for that the server settled without a value. */
1746
- readonly settled?: ReadonlyArray<{
1747
- readonly entity: string;
1748
- readonly id: string;
1749
- readonly fields: ReadonlyArray<string>;
1750
- }> | undefined;
1751
- /** Injected clock reading of the answer, dating what the payload writes. */
1752
- readonly now?: number | undefined;
1753
- } | {
1754
- readonly _tag: 'ConnectionInvalidated';
1755
- readonly connection: string;
1756
- } | {
1757
- readonly _tag: 'ConnectionRefreshed';
1758
- readonly connection: string;
1759
- } |
1520
+ connection: {
1521
+ <Name extends string, F extends Schema.Struct.Fields>(entity: EntityDescriptor<Name, F>, window: QueryWindow): Selection<RefPage<Name, F>, Name, 'connection'>;
1522
+ <Name extends string, F extends Schema.Struct.Fields, Item>(entity: EntityDescriptor<Name, F>, window: QueryWindow, selection: Selection<Item, NoInfer<Name>, 'entity'>): Selection<Page<Item>, Name, 'connection'>;
1523
+ };
1524
+ };
1525
+ interface Assembled {
1526
+ readonly values: unknown;
1527
+ readonly refreshing: boolean;
1528
+ }
1760
1529
  /**
1761
- * A query for the connection failed. Its pages stay as they were, and it
1762
- * reads `Failed` — with them as `previous`, when it has any — until a page
1763
- * arrives, it is invalidated, or retention drops it.
1530
+ * Reads an entity's selected fields out of the store, following each nested
1531
+ * relation into its targets. `undefined` means some field, at any depth, is
1532
+ * not present yet. A tombstoned target reads as `null` (or is dropped from a
1533
+ * list), so the Selection's codec decides whether that is a failure.
1764
1534
  */
1765
- {
1766
- readonly _tag: 'QueryFailed';
1767
- readonly connection: string;
1768
- readonly error: RemoteError;
1769
- };
1770
- declare const retentionRootsSchema: Schema.Struct<{
1771
- readonly requirements: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
1772
- readonly connections: Schema.$Array<Schema.Struct<{
1773
- readonly identity: Schema.String;
1774
- readonly select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
1775
- }>>;
1776
- }>;
1535
+ declare const assemble: (store: EntityStore, key: string, requirement: RelationRequirement) => Assembled | undefined;
1777
1536
  /**
1778
- * The Messages' fields by tag, without `_tag`: what `defineMessageUnion` takes,
1779
- * so an application spreads them into its own union (`Remote.messages`).
1537
+ * The first field `requirement` reads, at any depth, that the server settled
1538
+ * without a value, as `Entity:id.field`. A read that consults it says why it
1539
+ * cannot assemble rather than waiting on a field nothing will fetch.
1780
1540
  */
1781
- declare const remoteMessageCases: {
1782
- ReadReceived: {
1783
- requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
1784
- result: Schema.Struct<{
1785
- readonly entities: Schema.$Array<Schema.Struct<{
1786
- readonly entity: Schema.String;
1787
- readonly id: Schema.String;
1788
- readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
1789
- }>>;
1790
- readonly settled: Schema.$Array<Schema.Struct<{
1791
- readonly entity: Schema.String;
1792
- readonly id: Schema.String;
1793
- readonly fields: Schema.$Array<Schema.String>;
1794
- }>>;
1795
- }>;
1796
- now: Schema.Number;
1797
- };
1798
- ReadFailed: {
1799
- requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
1800
- error: Schema.Struct<{
1801
- readonly _tag: Schema.String;
1802
- readonly message: Schema.String;
1803
- readonly refusal: Schema.optional<Schema.Unknown>;
1804
- readonly reason: Schema.optional<Schema.String>;
1805
- }>;
1806
- stream: Schema.optional<Schema.String>;
1807
- };
1808
- RefreshStarted: {
1809
- requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
1810
- };
1811
- ReadStarted: {
1812
- requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
1813
- refresh: Schema.optional<Schema.Number>;
1814
- };
1815
- QueryStarted: {
1816
- connections: Schema.$Array<Schema.String>;
1817
- };
1818
- RetentionChanged: {
1819
- roots: Schema.Struct<{
1820
- readonly requirements: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
1821
- readonly connections: Schema.$Array<Schema.Struct<{
1822
- readonly identity: Schema.String;
1823
- readonly select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
1824
- }>>;
1825
- }>;
1826
- };
1827
- Hydrated: {
1828
- connections: Schema.optional<Schema.Unknown>;
1829
- from: Schema.optional<Schema.String>;
1830
- entities: Schema.Unknown;
1831
- merge: Schema.Union<readonly [Schema.Literal<"replace">, Schema.Literal<"preserve-existing">]>;
1832
- };
1833
- MutationStarted: {
1834
- requestId: Schema.String;
1835
- optimistic: Schema.optional<Schema.$Array<Schema.Unknown>>;
1836
- };
1837
- MutationSucceeded: {
1838
- requestId: Schema.String;
1839
- entities: Schema.$Array<Schema.Struct<{
1840
- readonly entity: Schema.String;
1841
- readonly id: Schema.String;
1842
- readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
1843
- }>>;
1844
- connections: Schema.optional<Schema.$Array<Schema.Unknown>>;
1845
- deleted: Schema.optional<Schema.$Array<Schema.Struct<{
1846
- readonly entity: Schema.String;
1847
- readonly id: Schema.String;
1848
- }>>>;
1849
- now: Schema.Number;
1850
- };
1851
- MutationFailed: {
1852
- requestId: Schema.String;
1853
- error: Schema.Struct<{
1854
- readonly _tag: Schema.String;
1855
- readonly message: Schema.String;
1856
- readonly refusal: Schema.optional<Schema.Unknown>;
1857
- readonly reason: Schema.optional<Schema.String>;
1858
- }>;
1859
- };
1860
- OverlayShown: {
1861
- id: Schema.String;
1862
- optimistic: Schema.$Array<Schema.Unknown>;
1863
- };
1864
- OverlayLifted: {
1865
- id: Schema.String;
1866
- };
1867
- WindowGrown: {
1868
- window: Schema.String;
1869
- size: Schema.Number;
1870
- };
1871
- LiveReceived: {
1872
- stream: Schema.String;
1873
- event: Schema.Unknown;
1874
- policy: Schema.optional<Schema.Unknown>;
1875
- now: Schema.Number;
1876
- };
1877
- GapCleared: {
1878
- stream: Schema.String;
1879
- };
1880
- ConnectionMerged: {
1881
- connection: Schema.String;
1882
- page: Schema.Unknown;
1883
- refreshes: Schema.optional<Schema.Boolean>;
1884
- select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
1885
- entities: Schema.optional<Schema.$Array<Schema.Struct<{
1886
- readonly entity: Schema.String;
1887
- readonly id: Schema.String;
1888
- readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
1889
- }>>>;
1890
- settled: Schema.optional<Schema.$Array<Schema.Struct<{
1891
- readonly entity: Schema.String;
1892
- readonly id: Schema.String;
1893
- readonly fields: Schema.$Array<Schema.String>;
1894
- }>>>;
1895
- now: Schema.optional<Schema.Number>;
1896
- };
1897
- ConnectionInvalidated: {
1898
- connection: Schema.String;
1899
- };
1900
- ConnectionRefreshed: {
1901
- connection: Schema.String;
1902
- };
1903
- QueryFailed: {
1904
- connection: Schema.String;
1905
- error: Schema.Struct<{
1906
- readonly _tag: Schema.String;
1907
- readonly message: Schema.String;
1908
- readonly refusal: Schema.optional<Schema.Unknown>;
1909
- readonly reason: Schema.optional<Schema.String>;
1910
- }>;
1911
- };
1912
- };
1913
- type RemoteMessageTag = RemoteMessage['_tag'];
1541
+ declare const unavailableOf: (store: EntityStore, key: string, requirement: RelationRequirement) => string | undefined;
1542
+ //#endregion
1543
+ //#region src/entity.d.ts
1544
+ type AnySchema = Schema.Schema<unknown>;
1545
+ declare const entityRefFields: unique symbol;
1914
1546
  /**
1915
- * A Remote Message as an application's union constructs it from
1916
- * `remoteMessageCases`: the same shape `RemoteMessage` names, with the runtime
1917
- * slots (`entities`, `event`, `page`) typed `unknown` by their schemas.
1547
+ * A normalized reference to an entity. `F` is a phantom carrying the entity's
1548
+ * fields so `Entity.patch` can type its patch; it is absent at runtime.
1918
1549
  */
1919
- type RemoteMessageInput = { [Tag in RemoteMessageTag]: {
1920
- readonly _tag: Tag;
1921
- } & Schema.Struct.Type<(typeof remoteMessageCases)[Tag]>; }[RemoteMessageTag];
1550
+ interface EntityRef<Name extends string, F extends Schema.Struct.Fields = Schema.Struct.Fields> {
1551
+ readonly entity: Name;
1552
+ readonly id: string;
1553
+ readonly [entityRefFields]?: F;
1554
+ }
1555
+ interface EntityDescriptor<Name extends string, F extends Schema.Struct.Fields> {
1556
+ readonly name: Name;
1557
+ readonly schema: Schema.Struct<F>;
1558
+ readonly fields: F;
1559
+ ref(id: Schema.Schema.Type<F['id']>): EntityRef<Name, F>;
1560
+ /** The fields a Surface reads of this entity; `Selection.make(entity, …)` with the entity as receiver. */
1561
+ select<const Sel extends SelectionOf<F>>(selection: Sel): Selection<SelectionValue<F, Sel>, Name, 'entity'>;
1562
+ /** A patch of this entity's wire-shaped values; `Entity.patch(entity.ref(id), values)`. */
1563
+ patch(id: Schema.Schema.Type<F['id']>, values: Partial<Schema.Struct.Encoded<F>>): EntityPatch<Name, F>;
1564
+ }
1922
1565
  /**
1923
- * Whether a Message is one of Remote's, by tag. Narrows an application's union
1924
- * to its Remote cases, and its complement to the application's own.
1566
+ * Relations are **references**, never inline target schemas: a ref cannot
1567
+ * reconstruct a full entity, and dereferencing is a store concern. Because the
1568
+ * target schema is not inlined, recursive relations cannot arise through the
1569
+ * schema graph.
1925
1570
  */
1926
- declare const isRemoteMessage: <M extends {
1927
- readonly _tag: string;
1928
- }>(message: M) => message is Extract<M, {
1929
- readonly _tag: RemoteMessageTag;
1930
- }>;
1931
- declare const remoteMessageSchema: Schema.Schema<RemoteMessage>;
1932
- /** The ids `OverlayShown` shows now, each once, in the order they are drawn. */
1933
- declare const overlaysOf: (model: RemoteModel) => ReadonlyArray<string>;
1934
- /** The key a grown window is kept under: its connection and the window first asked for. */
1935
- declare const windowGrowthKey: (identity: string, window: string) => string;
1936
1571
  /**
1937
- * Whether only overlays show this entity: the server has told the store
1938
- * nothing of it and no request's layer writes it, so nothing will fetch what an
1939
- * overlay leaves out.
1572
+ * A ref as the wire carries it: the target's name, a colon, and its id. Typed
1573
+ * with the name, so a relation to `User` takes `'User:u1'` and not a ref to
1574
+ * some other entity, which would read as a row that does not exist.
1940
1575
  */
1941
- declare const onlyOverlaid: (model: RemoteModel, entity: string, id: string) => boolean;
1942
- /** Whether a query for this connection is in flight. */
1943
- declare const isQueryLoading: (model: RemoteModel, identity: string) => boolean;
1576
+ type RefKey<Name extends string> = `${Name}:${string}`;
1944
1577
  /**
1945
- * The generation a read is planned under: the highest any of the fields it
1946
- * reads or connections it runs was refreshed at. A read entry carries this as a
1947
- * dependency, so it restarts when what it observes is refreshed and not when
1948
- * anything else is.
1578
+ * A patch in wire shape: the values the store holds, so a relation is its ref
1579
+ * key (`Entity.refKey`), not an `EntityRef`.
1949
1580
  */
1950
- declare const refreshedAt: (refresh: RefreshState, requests: ReadonlyArray<Requirement>, connections?: ReadonlyArray<string>) => number;
1581
+ interface EntityPatch<Name extends string, F extends Schema.Struct.Fields> {
1582
+ readonly entity: Name;
1583
+ readonly id: string;
1584
+ readonly values: Partial<Schema.Struct.Encoded<F>>;
1585
+ }
1951
1586
  /**
1952
- * Marks every field of `requests` and every connection in `connections`
1953
- * refreshed at the next generation.
1587
+ * One authoritative page of a paginated relation: refs (never inline entities)
1588
+ * plus whether more exist. The adapter does not hold segmentation state; the
1589
+ * client merges pages.
1954
1590
  */
1955
- declare const withRefreshRequested: (refresh: RefreshState, requests: ReadonlyArray<Requirement>, connections?: ReadonlyArray<string>) => RefreshState;
1591
+ interface RefPage<Name extends string, F extends Schema.Struct.Fields = Schema.Struct.Fields> {
1592
+ readonly refs: ReadonlyArray<EntityRef<Name, F>>;
1593
+ readonly hasNext: boolean;
1594
+ readonly hasPrevious: boolean;
1595
+ }
1596
+ /** The ref codec a `foldkit-entity` relation becomes: one ref, a nullable ref, or an array of refs. */
1597
+ type RelationField<Spec> = Spec extends Domain.RelationSpec<infer Target, infer Cardinality, infer Optional> ? Cardinality extends 'many' ? Schema.$Array<Schema.Codec<EntityRef<Target['name']>, RefKey<Target['name']>>> : Optional extends true ? Schema.NullOr<Schema.Codec<EntityRef<Target['name']>, RefKey<Target['name']>>> : Schema.Codec<EntityRef<Target['name']>, RefKey<Target['name']>> : never;
1598
+ /**
1599
+ * The fields Remote stores for a `foldkit-entity` Entity: its own fields, its
1600
+ * derived members (the server supplies them like any field), and each relation
1601
+ * as refs.
1602
+ */
1603
+ type FieldsFrom<E> = E extends Domain.Entity<any, infer Fields, infer Relations, infer Derived> ? Fields & { readonly [K in keyof Derived]: Derived[K]['schema']; } & { readonly [K in keyof Relations]: RelationField<Relations[K]>; } : never;
1604
+ declare const Entity$2: {
1605
+ /**
1606
+ * The Remote descriptor of a `foldkit-entity` Entity. Relations declared with
1607
+ * `Entity.relate` become ref fields, so the store, the planner, and the server
1608
+ * treat it as they treat an `Entity.make` descriptor.
1609
+ */
1610
+ from: <E extends Domain.AnyEntity>(entity: E & {
1611
+ readonly fields: {
1612
+ readonly id: unknown;
1613
+ };
1614
+ }) => EntityDescriptor<E['name'], FieldsFrom<E>>;
1615
+ make: <const Name extends string, const F extends Schema.Struct.Fields & {
1616
+ readonly id: Schema.Schema<unknown>;
1617
+ }>(name: Name, schema: Schema.Struct<F>) => EntityDescriptor<Name, F>;
1618
+ /** A relation to a known entity, decoded as a reference. */
1619
+ ref: <Name extends string, F extends Schema.Struct.Fields>(entity: EntityDescriptor<Name, F>) => Schema.Codec<EntityRef<Name, F>, RefKey<Name>>;
1620
+ /** A relation by name, for recursive or forward references. */
1621
+ refTo: <Name extends string>(name: Name) => Schema.Codec<EntityRef<Name>, RefKey<Name>>;
1622
+ /**
1623
+ * The wire key a relation field carries (`"Entity:id"`). Adapters that read a
1624
+ * foreign key emit this so the ref codec can decode it on the client.
1625
+ */
1626
+ refKey: (ref: {
1627
+ readonly entity: string;
1628
+ readonly id: string;
1629
+ }) => string;
1630
+ /** Splits a ref key back into its entity and id. */
1631
+ refParts: typeof refParts;
1632
+ /** A relation value of one authoritative page of refs. */
1633
+ refPage: <Name extends string, F extends Schema.Struct.Fields>(entity: EntityDescriptor<Name, F>) => Schema.Codec<RefPage<Name, F>, {
1634
+ readonly refs: ReadonlyArray<string>;
1635
+ readonly hasNext: boolean;
1636
+ readonly hasPrevious: boolean;
1637
+ }>;
1638
+ /**
1639
+ * A normalized patch for an entity, typed against its fields' wire shape:
1640
+ * write a relation as its ref key (`Entity.refKey`), as the server does.
1641
+ */
1642
+ patch: <Name extends string, F extends Schema.Struct.Fields>(ref: EntityRef<Name, F>, patch: Partial<Schema.Struct.Encoded<F>>) => EntityPatch<Name, F>;
1643
+ };
1644
+ //#endregion
1645
+ //#region src/matching.d.ts
1956
1646
  /**
1957
- * Marks connections as needing to be asked again, and restarts a read of them
1958
- * already in flight: a page requested before what invalidated it could land
1959
- * after it, saying what is no longer true. `Remote.refresh` marks the same way.
1647
+ * An answer over the rows the client holds — never over the rows that exist.
1648
+ *
1649
+ * `complete` is the whole reason this is its own type rather than a `Page`. A
1650
+ * `Page` carries `hasNext`/`hasPrevious`, which are facts the *server* stated
1651
+ * about rows beyond the ones it delivered; a local answer has no such facts and
1652
+ * cannot invent them. What it can say is whether the population it judged was
1653
+ * all of it, which is decidable: a connection terminal at both ends is wholly
1654
+ * held, and nothing was skipped for a missing field.
1655
+ *
1656
+ * An incomplete answer is not wrong — it is an answer about less than the
1657
+ * caller may have meant, and the flag is what lets a view say "3 so far" rather
1658
+ * than "3", or a caller decide to ask the server.
1960
1659
  */
1961
- declare const invalidateConnections: (model: RemoteModel, connections: ReadonlyArray<string>) => RemoteModel;
1660
+ interface Matched<A> {
1661
+ readonly items: ReadonlyArray<A>;
1662
+ /** Whether every row the answer is about was judged. */
1663
+ readonly complete: boolean;
1664
+ }
1962
1665
  /**
1963
- * Whether one field's read already began under the generation that field was
1964
- * last refreshed at. Such a read is in flight and would otherwise outlive the
1965
- * refresh, so the refresh takes a new generation to restart it even though the
1966
- * field is already stale.
1666
+ * What the rows the client holds had to say about a body.
1667
+ *
1668
+ * `skipped` is the honest half. A row missing a field the body reads cannot be
1669
+ * judged — it is neither a match nor a non-match — and dropping it silently
1670
+ * would turn "I could not tell" into "no". Naming it lets a caller decide:
1671
+ * fetch the field, ask the server, or say the answer is partial.
1967
1672
  */
1968
- declare const refreshIsInFlight: (refresh: RefreshState, request: Requirement, field: string) => boolean;
1673
+ interface Judged {
1674
+ /** Keys of the rows that satisfy the body, in the order the body asks for. */
1675
+ readonly matched: ReadonlyArray<EntityKey>;
1676
+ /** Keys of rows held but missing a field the body reads, so not judged either way. */
1677
+ readonly skipped: ReadonlyArray<EntityKey>;
1678
+ }
1679
+ interface MatchingOptions {
1680
+ /**
1681
+ * Judge only these keys. Without it every row of the body's Entity in the
1682
+ * store is a candidate, which is what a filter over a loaded list wants; with
1683
+ * it, a caller narrows to a connection's own edges.
1684
+ */
1685
+ readonly among?: ReadonlyArray<EntityKey> | undefined;
1686
+ }
1969
1687
  /**
1970
- * Whether a read is fetching any of `fields` for this entity. Consulted only
1971
- * when the store lacks the value, which is what separates `Loading` from
1972
- * `Initial`.
1688
+ * The rows of `descriptor`'s Entity that the store holds and the body matches.
1689
+ *
1690
+ * The input is given **decoded**, as an application writes it, and encoded here
1691
+ * through the descriptor's own `Input` codec. That is deliberate and is the
1692
+ * whole reason this takes a descriptor rather than a bare body: a store holds
1693
+ * wire values, so an input has to be in that space to be compared against them,
1694
+ * and handing an interpreter a decoded value is a mistake **no runtime error
1695
+ * catches** — the reference interpreter answers "no rows", which reads exactly
1696
+ * like a correct answer. Doing it here means a caller cannot get it wrong.
1697
+ *
1698
+ * Literals in the body are deliberately *not* encoded. A literal written in
1699
+ * domain terms is already broken against the server, which binds it to a column
1700
+ * the same way; accepting it here would make the client quietly more permissive
1701
+ * than the thing it has to agree with.
1973
1702
  */
1974
- declare const isLoading: (model: RemoteModel, entity: string, id: string, fields: ReadonlyArray<string>) => boolean;
1703
+ declare const matching: <Name extends string, Input>(store: EntityStore, descriptor: QueryDescriptor<Name, Input, unknown>, input: Input, options?: MatchingOptions) => Judged;
1975
1704
  /**
1976
- * The pure reducer all four producers share. A live event that arrives ahead of
1977
- * its cursor is a gap: it is not applied, and the stream is recorded so its
1978
- * live entry restarts it rather than silently missing facts. When every field a Message
1979
- * touches keeps its identity, `model` itself is returned, so the application's
1980
- * root keeps its identity and Foldkit does not render. The common no-ops do (a
1981
- * duplicate live event, a repeated `ReadStarted`); a repeated failure, or a
1982
- * `preserve-existing` restore of entities already held, still makes an equal
1983
- * copy.
1705
+ * Whether one row belongs to a query, as far as the client can tell.
1706
+ *
1707
+ * Three answers, and the third is the one that makes this usable. `'unknown'`
1708
+ * is a row the store never fetched, or holds without a field the body reads —
1709
+ * a caller that collapses it into `'no'` has turned "I could not tell" into an
1710
+ * answer, which is the mistake this whole module is shaped against.
1711
+ *
1712
+ * **Membership is decidable where position is not.** Whether a row satisfies
1713
+ * `eq`, `isNull` or `contains` needs no collation: equality on text is exact
1714
+ * and `contains` folds ASCII, both stated in §6.0.1. *Where* a row sorts needs
1715
+ * text collation, which is the backend's and deliberately outside the
1716
+ * conformant subset — so this answers the half that is always answerable, and
1717
+ * ordering stays the server's until a query can declare its collation.
1984
1718
  */
1985
- declare const updateRemote: (model: RemoteModel, message: RemoteMessage) => RemoteModel;
1986
- /** Whether this field's last read failed and nothing has settled it since. */
1987
- declare const isFieldFailed: (model: RemoteModel, entity: string, id: string, field: string) => boolean;
1719
+ type Belongs = 'yes' | 'no' | 'unknown';
1988
1720
  /**
1989
- * Whether a read is fetching any field `relation` reads of an entity, its own
1990
- * or, through each relation the store holds, its targets'. A value whose owner
1991
- * is being fetched is loading, not `Initial`: nothing is missing a fetch.
1721
+ * Takes the input **encoded**, because its one caller holds it that way: a
1722
+ * connection identity carries the canonical encoded input, and making it decode
1723
+ * only for this to encode again would be a round trip that can fail.
1724
+ *
1725
+ * A decoded-input sibling was written first and deleted: nothing called it. The
1726
+ * asymmetry with `matching`, which takes a decoded input, is the shape of the
1727
+ * two real callers rather than an oversight.
1992
1728
  */
1993
- declare const isLoadingThrough: (model: RemoteModel, entity: string, id: string, relation: RelationRequirement) => boolean;
1729
+ declare const belongsEncoded: <Name extends string, Input>(store: EntityStore, descriptor: QueryDescriptor<Name, Input, unknown>, encoded: Readonly<Record<string, unknown>>, key: EntityKey) => Belongs;
1730
+ //#endregion
1731
+ //#region src/retain.d.ts
1732
+ /** A connection to keep: its identity, and what a page of it selects of each item, if a projection reads it. */
1733
+ interface ConnectionRoot {
1734
+ readonly identity: string;
1735
+ readonly select?: RelationRequirement | undefined;
1736
+ }
1737
+ interface RetentionRoots {
1738
+ readonly requirements: ReadonlyArray<Requirement>;
1739
+ /** Connections (`QueryRef.identity`) to keep, with their edges' targets and what `select` reaches through them. */
1740
+ readonly connections: ReadonlyArray<ConnectionRoot>;
1741
+ }
1742
+ interface Retained {
1743
+ readonly entities: EntityStore;
1744
+ readonly connections: Readonly<Record<string, Connection>>;
1745
+ readonly optimistic: OptimisticState;
1746
+ }
1994
1747
  /**
1995
- * The first failure among the fields `relation` reads of an entity, following
1996
- * each relation the store holds into its targets, as `assemble` does. A read
1997
- * that consults it shows `Failed` for a related entity's failure too, rather
1998
- * than waiting on a field nothing will fetch.
1748
+ * The entity keys the roots reach: each root entity, the targets its retained
1749
+ * fields refer to, and recursively the targets a nested relation selects.
1999
1750
  */
2000
- declare const failureOf: (model: RemoteModel, entity: string, id: string, relation: RelationRequirement) => RemoteError | undefined;
1751
+ declare const reachable: (store: EntityStore, roots: RetentionRoots, connections: Readonly<Record<string, Connection>>, optimistic: OptimisticState, pending: ReadonlySet<string>) => ReadonlySet<EntityKey>;
2001
1752
  /**
2002
- * Writes a read result into the store, recording each field's applied window so
2003
- * a later request with a different window refetches. A relation page requested
2004
- * with a cursor is merged onto the page already stored, so "load more"
2005
- * accumulates rather than replaces. Every read path should use this rather than
2006
- * reducing `writeEntity` by hand.
1753
+ * Drops every entity the roots do not reach, every connection they do not
1754
+ * name, and every settled overlay on a dropped connection, keeping whatever a
1755
+ * pending request's layer or overlays touch. Pure.
2007
1756
  */
2008
- declare const writeRead: (store: EntityStore, requests: ReadonlyArray<Requirement>, result: Schema.Schema.Type<typeof ReadBatchResult>, now?: number) => EntityStore;
1757
+ declare const gc: (state: Retained & {
1758
+ readonly mutations: MutationState;
1759
+ }, roots: RetentionRoots) => Retained;
2009
1760
  //#endregion
2010
- //#region src/resume.d.ts
1761
+ //#region src/persistence.d.ts
1762
+ /** Bump when the serialized shape changes; a mismatch discards the cache. */
1763
+ declare const REMOTE_CACHE_VERSION = 5;
2011
1764
  /**
2012
- * A resume part, in the shape `foldkit-ssr`'s `SSR.plan` takes in `parts`.
2013
- * Declared here structurally, so neither package depends on the other.
1765
+ * What survives a reload: the entity cache, and the connections an application
1766
+ * **declared** should come back.
1767
+ *
1768
+ * Connections are session state by default and stay that way — `snapshotOf`
1769
+ * takes none unless asked. What a declared one keeps is its **edges and
1770
+ * nothing else**, which is not a simplification but the rule: a connection's
1771
+ * boundaries are cursors the server minted, and a cursor may name server state
1772
+ * that no longer exists. Restoring one would be claiming to know where the
1773
+ * page ends. The shape has nowhere to put a cursor, so that cannot be got
1774
+ * wrong later.
2014
1775
  */
2015
- interface RemoteResumePart<AppModel> {
2016
- readonly id: string;
2017
- /** The metadata key names whose reads this part resumes. */
2018
- readonly covers: ReadonlyArray<string>;
2019
- readonly capture: (model: AppModel, projections: ReadonlyArray<{
2020
- readonly metadata: Metadata;
2021
- }>) => unknown;
2022
- readonly restore: (model: AppModel, value: unknown) => Result.Result<AppModel, string>;
2023
- /** Whether a Subscription entry is one of this domain's, which may start late. */
2024
- readonly deferrable: (key: string, entry: unknown) => boolean;
2025
- }
2026
- //#endregion
2027
- //#region src/coalesce.d.ts
2028
- type Batch = Schema.Schema.Type<typeof ReadBatch>;
2029
- type BatchResult = Schema.Schema.Type<typeof ReadBatchResult>;
2030
- type ReadError = RemoteReadError | RemoteProtocolError;
2031
- type BatchRead = (batch: Batch) => Effect.Effect<BatchResult, ReadError>;
2032
- type QueryRequestValue = Schema.Schema.Type<typeof QueryRequest>;
2033
- type QueryResultValue = Schema.Schema.Type<typeof QueryResult>;
2034
- type QueryRun = (request: QueryRequestValue) => Effect.Effect<QueryResultValue, RemoteQueryError>;
2035
- interface CoalesceOptions {
1776
+ interface Snapshot {
1777
+ readonly entities: EntityStore;
2036
1778
  /**
2037
- * How long a batch waits to collect more requirements before it runs.
2038
- * Requirements issued concurrently coalesce even at the default of no wait.
1779
+ * By connection identity: its **segments**, each a run of edges. No
1780
+ * boundaries.
1781
+ *
1782
+ * Segments rather than one flat list, because the gaps between them are
1783
+ * knowledge too. A connection paged from both ends holds a head and a tail
1784
+ * with an unfetched middle; flattening those into one run would claim the
1785
+ * tail's first row follows the head's last, which is a thing the client was
1786
+ * never told.
2039
1787
  */
2040
- readonly window?: Duration.Input | undefined;
1788
+ readonly connections: Readonly<Record<string, ReadonlyArray<ReadonlyArray<Edge>>>>;
2041
1789
  }
2042
- /** A stable key for a requirement, so an equal requirement in flight is joined. */
2043
- declare const requirementKey: (requirement: Requirement) => string;
2044
- /**
2045
- * Wraps a raw query so that an identical query in flight (same query, input,
2046
- * and window) is joined rather than run again; distinct queries run
2047
- * concurrently. A page answers exactly one window, so nothing is batched.
2048
- */
2049
- declare const coalesceQueries: (query: QueryRun, options?: CoalesceOptions) => Effect.Effect<QueryRun>;
2050
1790
  /**
2051
- * Wraps a raw batch read so that requirements are batched and deduplicated.
2052
- * Every waiter receives the whole batch result; `Remote.writeRead` is
2053
- * idempotent, so writing it more than once is harmless.
1791
+ * A snapshot of a Model, keeping the entity cache and only the connections
1792
+ * named.
1793
+ *
1794
+ * Naming none — the default — is exactly what Remote did before connections
1795
+ * could be kept at all: a disposable, server-derived cache.
2054
1796
  */
2055
- declare const coalesceReads: (read: BatchRead, options?: CoalesceOptions) => Effect.Effect<BatchRead>;
2056
- //#endregion
2057
- //#region src/client.d.ts
2058
- declare const RemoteClient_base: Context.ServiceClass<RemoteClient, "foldkit-remote/RemoteClient", {
2059
- readonly read: (batch: Schema.Schema.Type<typeof ReadBatch>) => Effect.Effect<Schema.Schema.Type<typeof ReadBatchResult>, RemoteReadError | RemoteProtocolError>;
2060
- readonly query: (request: Schema.Schema.Type<typeof QueryRequest>) => Effect.Effect<Schema.Schema.Type<typeof QueryResult>, RemoteQueryError>;
2061
- readonly mutate: (request: Schema.Schema.Type<typeof MutationRequest>) => Effect.Effect<Schema.Schema.Type<typeof MutationResult>, RemoteMutationError | RemoteForbidden>;
2062
- readonly live: (request: {
2063
- readonly requirements: ReadonlyArray<Requirement>;
2064
- readonly after: LiveCursor;
2065
- }) => Stream.Stream<LiveEvent, RemoteLiveError | RemoteProtocolError>;
2066
- }>;
1797
+ declare const snapshotOf: (model: {
1798
+ readonly entities: EntityStore;
1799
+ readonly connections: Readonly<Record<string, Connection>>;
1800
+ }, options?: {
1801
+ readonly connections?: ReadonlyArray<ConnectionIdentity> | undefined;
1802
+ }) => Snapshot;
1803
+ interface SnapshotOptions {
1804
+ /**
1805
+ * Who or what the snapshot is for (a user id, a tenant, a build). A snapshot
1806
+ * taken under another scope is discarded rather than shown to the wrong
1807
+ * reader. Default: unscoped, which only matches unscoped.
1808
+ */
1809
+ readonly scope?: string | undefined;
1810
+ /** Snapshots larger than this many bytes are not written and not read. */
1811
+ readonly maxBytes?: number | undefined;
1812
+ }
1813
+ /** How a snapshot meets a store that already has entries. */
1814
+ type MergePolicy = 'replace' | 'preserve-existing';
2067
1815
  /**
2068
- * The transport boundary. `foldkit-remote` never talks to a transport directly;
2069
- * it depends on this Effect service, which a later phase wires to Effect RPC.
1816
+ * The snapshot text, or `undefined` when it would exceed `maxBytes`. Build the
1817
+ * snapshot with `snapshotOf`, which is where the connections that survive are
1818
+ * named; runtime state — optimistic layers, live cursors, gaps, the mutation
1819
+ * ledger — is never in one.
2070
1820
  */
2071
- declare class RemoteClient extends RemoteClient_base {}
1821
+ declare function dehydrate(snapshot: Snapshot, options?: SnapshotOptions & {
1822
+ readonly maxBytes?: undefined;
1823
+ }): string;
1824
+ declare function dehydrate(snapshot: Snapshot, options?: SnapshotOptions): string | undefined;
2072
1825
  /**
2073
- * The methods an Effect RPC client for `RemoteRpc` exposes. `R` is the
2074
- * environment a handler needs; it defaults to `never`, which is what a real
2075
- * transport client satisfies. `RemoteServer.handlers` returns this type with its
2076
- * own `R`, so the two sides cannot drift apart.
2077
- *
2078
- * `TransportError` is what the transport itself may fail with on top of the
2079
- * declared errors: `RpcClientError` for the client `RpcClient.make` builds,
2080
- * `never` for in-process handlers.
1826
+ * The store a snapshot text holds, or `undefined` when the text is missing,
1827
+ * oversized, not this version, for another scope, or malformed. Hydrating the
1828
+ * same text twice yields equal stores.
2081
1829
  */
2082
- interface RemoteRpcClient<R = never, TransportError = never> {
2083
- readonly FoldkitRemoteRead: (payload: Schema.Schema.Type<typeof ReadBatch>) => Effect.Effect<Schema.Schema.Type<typeof ReadBatchResult>, RemoteReadError | RemoteProtocolError | TransportError, R>;
2084
- readonly FoldkitRemoteQuery: (payload: Schema.Schema.Type<typeof QueryRequest>) => Effect.Effect<Schema.Schema.Type<typeof QueryResult>, RemoteQueryError | TransportError, R>;
2085
- readonly FoldkitRemoteMutate: (payload: Schema.Schema.Type<typeof MutationRequest>) => Effect.Effect<Schema.Schema.Type<typeof MutationResult>, RemoteMutationError | RemoteForbidden | TransportError, R>;
2086
- readonly FoldkitRemoteLive: (payload: Schema.Schema.Type<typeof LiveRequirement>) => Stream.Stream<Schema.Schema.Type<typeof LiveChange>, RemoteLiveError | RemoteProtocolError | TransportError, R>;
2087
- }
2088
- /** Reconstructs the client's `ConnectionChange` from the wire's flattened edge. */
2089
- declare const connectionChangeOf: (change: Schema.Schema.Type<typeof ConnectionChangeSchema>) => ConnectionChange;
2090
- /** Reconstructs the client's `LiveEvent` from the wire's flattened `LiveChange`. */
2091
- declare const liveEventOf: (change: Schema.Schema.Type<typeof LiveChange>) => LiveEvent;
2092
- declare const remoteError: (error: {
2093
- readonly _tag: string;
2094
- readonly message: string;
2095
- readonly refusal?: unknown;
2096
- readonly reason?: string | undefined;
2097
- }) => RemoteError;
2098
- declare const coalescedLayer: <E, R>(layer: Layer.Layer<RemoteClient, E, R>, options?: CoalesceOptions) => Layer.Layer<RemoteClient, E, R>;
1830
+ declare const hydrate: (raw: string | undefined | null, options?: SnapshotOptions) => Snapshot | undefined;
2099
1831
  /**
2100
- * `Remote.mutate` as a standalone effect, so `Remote.mutateInto` can reuse it
2101
- * without the object literal referencing itself.
1832
+ * Brings a snapshot into a store that may already hold entries. `replace`
1833
+ * takes the snapshot's entry for every key it has; `preserve-existing` keeps
1834
+ * an entry the current store already has (it is at least as fresh as a
1835
+ * snapshot taken earlier). Either way, keys only the current store has stay.
2102
1836
  */
2103
- declare const mutateRemote: <Name extends string, Input, Output>(mutation: MutationDescriptor<Name, Input, Output, unknown>, input: Input, requestId: string, keys?: readonly string[] | undefined) => Effect.Effect<{
2104
- output: Output;
2105
- entities: readonly {
2106
- readonly entity: string;
2107
- readonly id: string;
2108
- readonly values: {
2109
- readonly [x: string]: unknown;
2110
- };
2111
- }[];
2112
- connections: ConnectionChange[];
2113
- deleted: readonly {
2114
- readonly entity: string;
2115
- readonly id: string;
2116
- }[];
2117
- }, RemoteMutationError | RemoteForbidden, RemoteClient>;
1837
+ declare const mergeStores: (current: EntityStore, snapshot: EntityStore, policy: MergePolicy) => EntityStore;
1838
+ declare const RemotePersistence: {
1839
+ /** The snapshot text, or `undefined` when it would exceed `maxBytes`. */
1840
+ dehydrate: typeof dehydrate;
1841
+ /** What a snapshot text holds, or `undefined` when it is refused. */
1842
+ hydrate: typeof hydrate;
1843
+ /**
1844
+ * What to keep of a Model, naming the connections that should survive a
1845
+ * reload. Naming none is the default and is what Remote always did.
1846
+ */
1847
+ snapshotOf: typeof snapshotOf;
1848
+ /** A snapshot's entities brought into a store by policy. */
1849
+ mergeStores: typeof mergeStores;
1850
+ /** The cache as a fresh session has it; what a refused `restore` yields. */
1851
+ emptySnapshot: Snapshot;
1852
+ /**
1853
+ * Writes the snapshot under `key`, or removes the key when the store would
1854
+ * exceed `maxBytes`, so a stale smaller snapshot cannot outlive a larger
1855
+ * store it no longer describes.
1856
+ */
1857
+ save: (snapshot: Snapshot, options: {
1858
+ readonly key: string;
1859
+ } & SnapshotOptions) => Effect.Effect<void, KeyValueStore.KeyValueStoreError, KeyValueStore.KeyValueStore>;
1860
+ /**
1861
+ * Reads the cache. A missing key yields `emptySnapshot`; anything `hydrate`
1862
+ * refuses yields `emptySnapshot` and removes the key, so the next `restore`
1863
+ * is clean and the planner refetches.
1864
+ */
1865
+ restore: (options: {
1866
+ readonly key: string;
1867
+ } & SnapshotOptions) => Effect.Effect<Snapshot, KeyValueStore.KeyValueStoreError, KeyValueStore.KeyValueStore>;
1868
+ };
2118
1869
  //#endregion
2119
- //#region src/json.d.ts
2120
- /** A request: which of Remote's calls, and its payload as the RPC protocol encodes it. */
2121
- declare const RemoteJsonRequest: Schema.Struct<{
2122
- readonly operation: Schema.Literals<readonly ["read", "query", "mutate"]>;
2123
- readonly payload: Schema.Unknown;
2124
- }>;
2125
- type RemoteJsonRequest = typeof RemoteJsonRequest.Type;
2126
- /** An answer: the call's result, or why there is none. */
2127
- declare const RemoteJsonAnswer: Schema.Union<readonly [Schema.Struct<{
2128
- readonly result: Schema.Unknown;
2129
- }>, Schema.Struct<{
2130
- readonly error: Schema.String;
2131
- readonly refusal: Schema.optional<Schema.Unknown>;
2132
- /** Who is asking was refused, with the application's reason when it gave one. */
2133
- readonly forbidden: Schema.optional<Schema.Struct<{
2134
- readonly reason: Schema.optional<Schema.String>;
2135
- }>>;
2136
- }>]>;
2137
- type RemoteJsonAnswer = typeof RemoteJsonAnswer.Type;
1870
+ //#region src/model.d.ts
2138
1871
  /**
2139
- * Sends one request's text and resolves with its answer as parsed JSON. It
2140
- * rejects when nothing came back, and the call fails with that message.
1872
+ * The normalized cache as a Foldkit Submodel. `Remote.define` returns a schema
1873
+ * and an `update` for this shape; `updateRemote` reconciles every producer.
2141
1874
  */
2142
- type RemoteJsonSend = (request: string) => Promise<unknown>;
2143
- //#endregion
2144
- //#region src/sse.d.ts
2145
- /** What `httpWithLive` needs besides the URL. Mirrors `http`, plus the fetch itself. */
2146
- interface LiveFetchOptions {
2147
- /** Read per request, so a token that changes reaches the next call. */
2148
- readonly headers?: (() => Readonly<Record<string, string>>) | undefined;
2149
- /** Defaults to the global one; pass it to route calls elsewhere in tests. */
2150
- readonly fetch?: typeof fetch | undefined;
1875
+ interface RemoteModel {
1876
+ /** Entity values, presence, staleness, tombstones, and applied windows. */
1877
+ readonly entities: EntityStore;
1878
+ /** Normalized ordered connections, keyed by connection identity. */
1879
+ readonly connections: Readonly<Record<string, Connection>>;
1880
+ /**
1881
+ * How many rows `Data.more` has grown a read's window to, by
1882
+ * `windowGrowthKey`. A read shows at most its window, so this is what "load
1883
+ * more" changes; it lives here because a list holds no state of its own.
1884
+ */
1885
+ readonly grown: Readonly<Record<string, number>>;
1886
+ /** Optimistic entity layers and connection overlays over the base store. */
1887
+ readonly optimistic: OptimisticState;
1888
+ /** Live cursor and boundary state, keyed by the subscription's stream key. */
1889
+ readonly live: Readonly<Record<string, LiveState>>;
1890
+ /** Mutation pending/applied/failed ledger. */
1891
+ readonly mutations: MutationState;
1892
+ /**
1893
+ * Streams that broke, by an error or by an event ahead of their cursor, and
1894
+ * have not resubscribed since: changes after the break are missed until the
1895
+ * live entry restarts them and refetches what they cover.
1896
+ */
1897
+ readonly gaps: ReadonlySet<string>;
1898
+ /** Each live stream that has ever broken, by stream key. One that never broke is absent. */
1899
+ readonly streams: Readonly<Record<string, StreamHealth>>;
1900
+ /**
1901
+ * The `entity\0id\0field` marks a read is currently fetching. A field absent
1902
+ * from the store reads as `Loading` while its mark is here and `Initial`
1903
+ * otherwise, which is what separates "being fetched" from "nothing is
1904
+ * fetching this".
1905
+ */
1906
+ readonly loading: ReadonlySet<string>;
1907
+ /**
1908
+ * `Remote.refresh` generations, held per field rather than for the store as a
1909
+ * whole. A read entry restarts when the generation over the fields it plans
1910
+ * moves, so a read sent before a refresh of its own fields cannot land after
1911
+ * it, and a refresh of one field leaves every other entry's read alone.
1912
+ */
1913
+ readonly refresh: RefreshState;
1914
+ /**
1915
+ * The reads that failed and have not been settled since, so a read can say
1916
+ * `Failed` rather than `Initial`.
1917
+ *
1918
+ * Without them a read that failed before anything loaded read exactly like
1919
+ * one nobody had asked for, and nothing asked again: a read entry restarts
1920
+ * only when what it plans changes, and a failure changed nothing. What failed
1921
+ * is not planned again on its own either, so a persistent error is not
1922
+ * retried every time an unrelated read restarts the entry. `Remote.refresh`
1923
+ * is how a view retries.
1924
+ */
1925
+ readonly failures: Failures;
1926
+ /**
1927
+ * The storage key the cache was last restored from, through `Hydrated`'s
1928
+ * `from`. `Data.persistence` saves under a key only once its own snapshot is
1929
+ * in, so a save at startup cannot write the empty store over it.
1930
+ */
1931
+ readonly restoredFrom: Option.Option<string>;
1932
+ /**
1933
+ * Under `verifyPlacement`, the order each list was placed in, by edge key,
1934
+ * and the rows placing took out of its first page, until the server's page
1935
+ * for it arrives to be compared with them.
1936
+ */
1937
+ readonly placed: Readonly<Record<string, PlacedOrder>>;
1938
+ /** Under `verifyPlacement`, each placement the server's page disagreed with. */
1939
+ readonly placementMismatches: ReadonlyArray<PlacementMismatch>;
2151
1940
  }
2152
- /** Remote's live stream over fetch: `serveFetch`'s live open as a `Stream`. */
2153
- declare const liveFetch: (url: string, options?: LiveFetchOptions) => RemoteRpcClient["FoldkitRemoteLive"];
2154
- /**
2155
- * Remote's client over HTTP with live: reads, queries, and mutations as
2156
- * `http` sends them, live as `liveFetch` streams it, for `clientLayer`.
2157
- */
2158
- declare const httpWithLive: (url: string, options?: LiveFetchOptions) => RemoteRpcClient;
2159
- //#endregion
2160
- //#region src/relation.d.ts
2161
- interface RefParts {
2162
- readonly entity: string;
2163
- readonly id: string;
1941
+ /** A list's first page as the client placed it: its keys in order, and those it took out. */
1942
+ interface PlacedOrder {
1943
+ readonly order: ReadonlyArray<string>;
1944
+ readonly dropped: ReadonlyArray<string>;
2164
1945
  }
2165
- /** A page of refs as the wire and the store hold it. */
2166
- interface RefPageValue {
2167
- readonly refs: ReadonlyArray<string>;
2168
- readonly hasNext: boolean;
2169
- readonly hasPrevious: boolean;
1946
+ /** A list the client placed rows in one order and the server then listed in another. */
1947
+ interface PlacementMismatch {
1948
+ readonly connection: string;
1949
+ /** The keys as placed, as far as the server's page reached. */
1950
+ readonly placed: ReadonlyArray<string>;
1951
+ /** The keys of the server's first page. */
1952
+ readonly served: ReadonlyArray<string>;
2170
1953
  }
2171
- /** Marks the codec `Entity.ref`/`Entity.refPage` produce, so a Selection can tell the field's shape. */
2172
- declare const RelationAnnotation = "foldkitRemoteRelation";
2173
- /** The target entity's name on the same codec, so a nested selection of another entity is refused. */
2174
- declare const RelationEntityAnnotation = "foldkitRemoteRelationEntity";
2175
- type RelationKind = 'one' | 'many' | 'page';
2176
- interface RelationShape {
2177
- readonly kind: RelationKind;
2178
- readonly nullable: boolean;
2179
- readonly entity: string;
1954
+ /** How a live stream has fared, as its live entry restarts it. */
1955
+ interface StreamHealth {
1956
+ /** How many times it broke. The live entry restarts on each, so it only grows. */
1957
+ readonly restarts: number;
1958
+ /** Breaks since its last applied event: what the restart's backoff grows with. */
1959
+ readonly failures: number;
1960
+ /** Why it last broke; none for a gap, which is not an error. */
1961
+ readonly error: Option.Option<RemoteError>;
2180
1962
  }
2181
1963
  /**
2182
- * A page of a relation that is a whole list is read under a name of its own, the
2183
- * field's name and the page's size: `comments@first=10`. It is a field like any
2184
- * other to the store, the planner, and the wire, so the whole list and a page of
2185
- * it are held side by side, merged, marked stale, and persisted each on its own.
2186
- * The server reads the name apart, reads the relation with the window, and
2187
- * answers under the alias. A cursor is not part of the name: a page read from a
2188
- * cursor merges onto the page it continues.
2189
- */
2190
- declare const RELATION_ALIAS = "@";
2191
- /** The alias a relation field is read under, for a window of this size. */
2192
- declare const relationAlias: (field: string, window: {
2193
- readonly first?: number | undefined;
2194
- readonly last?: number | undefined;
2195
- readonly after?: string | undefined;
2196
- readonly before?: string | undefined;
2197
- }) => string;
2198
- /** The field an alias reads; a name that is no alias is its own field. */
2199
- declare const aliasedField: (name: string) => string;
2200
- /** Splits a ref key (`"Entity:id"`, the store key too) back into its parts. */
2201
- declare const refParts: (encoded: string) => RefParts;
2202
- /**
2203
- * The refs a relation value carries, in order. Anything that is not a ref key,
2204
- * an array of them, or a page of them contributes nothing.
1964
+ * Failed reads, as the errors they failed with.
1965
+ *
1966
+ * `connections` is by connection identity, and is settled by a page arriving,
1967
+ * an invalidation, or retention dropping the connection. `fields` is by field
1968
+ * mark (`entity\0id\0field`, the marks `loading` uses), and is settled by the
1969
+ * field being written again, a refresh asking for it, or retention dropping the
1970
+ * entity. A read of it in flight reads `Loading` over the failure without
1971
+ * settling it: if that read fails too, the failure is simply recorded again.
2205
1972
  */
2206
- declare const refsIn: (value: unknown) => ReadonlyArray<RefParts>;
2207
- /** The refs in a relation value that name the relation's target entity, and no other. */
2208
- declare const targetsOf: (value: unknown, relation: RelationRequirement) => ReadonlyArray<RefParts>;
2209
- declare const isRefPage: (value: unknown) => value is RefPageValue;
1973
+ interface Failures {
1974
+ readonly connections: Readonly<Record<string, RemoteError>>;
1975
+ readonly fields: Readonly<Record<string, RemoteError>>;
1976
+ }
1977
+ declare const noFailures: Failures;
2210
1978
  /**
2211
- * The relation shape an entity field schema declares: a ref (`one`), a nullable
2212
- * ref, an array of refs (`many`), or a page of refs (`page`). `undefined` for a
2213
- * scalar field, which cannot take a nested selection.
1979
+ * `Remote.refresh` generations, per field mark. `generation` is the last one
1980
+ * handed out; `requested` is when each field was last refreshed, and `started`
1981
+ * is the generation each field's read last began under. Holding them per field
1982
+ * is what keeps one Projection's refresh from restarting every read entry.
2214
1983
  */
2215
- declare const relationShape: (schema: Schema.Top) => RelationShape | undefined;
2216
- //#endregion
2217
- //#region src/selection.d.ts
2218
- /** One page of a paginated relation with each target assembled through a nested selection. */
2219
- interface Page<Item> {
2220
- readonly items: ReadonlyArray<Item>;
2221
- readonly hasNext: boolean;
2222
- readonly hasPrevious: boolean;
1984
+ interface RefreshState {
1985
+ readonly generation: number;
1986
+ readonly requested: ReadonlyMap<string, number>;
1987
+ readonly started: ReadonlyMap<string, number>;
1988
+ /**
1989
+ * The generation every entry is refreshed at, at least: `forgetRemote` moves
1990
+ * it, so every read and live entry restarts, and a read or stream begun for
1991
+ * the principal before is interrupted rather than landing after.
1992
+ */
1993
+ readonly floor: number;
2223
1994
  }
1995
+ declare const emptyRefresh: RefreshState;
2224
1996
  /**
2225
- * The fields a projection reads of one entity, plus the slice it reads of each
2226
- * relation's target. `Shape` tells a parent selection whether this one is a
2227
- * paginated relation (`connection`) or a plain entity slice (`entity`).
1997
+ * The Model with everything the server told it forgotten: values, tombstones,
1998
+ * unavailable fields, connections, live cursors, failures, and what is in
1999
+ * flight. For a change of principal, whose facts these were. The mutation
2000
+ * sequence is kept, so request ids stay unique, and a mutation in flight is
2001
+ * treated as applied: its answer, when it comes, writes nothing here.
2228
2002
  */
2229
- interface Selection<Value, Name extends string = string, Shape extends 'entity' | 'connection' = 'entity' | 'connection'> {
2230
- readonly entity: Name;
2231
- readonly fields: readonly string[];
2232
- /** A pure codec: entity fields carry no decoding or encoding services. */
2233
- readonly schema: Schema.Codec<Value, unknown, never, never>;
2234
- /** Pagination windows for nested relation fields, keyed by field name. */
2235
- readonly connections?: Readonly<Record<string, QueryWindow>> | undefined;
2236
- /** The slice required of each nested relation's target, keyed by field name. */
2237
- readonly relations?: Readonly<Record<string, RelationRequirement>> | undefined;
2238
- /** Present when this selection is itself a paginated relation. */
2239
- readonly window?: QueryWindow | undefined;
2240
- /** Phantom: see `Shape`. */
2241
- readonly shape?: Shape | undefined;
2242
- }
2243
- /** Flattens a mapped type so hovers show the picked fields, not the machinery. */
2244
- type Simplify<T> = T extends (infer O) ? { readonly [K in keyof O]: O[K]; } : never;
2245
- /** The value a Selection reads: `Selection.Value<typeof ProjectCard>`. */
2246
- type SelectionValueOf<S> = S extends Selection<infer V, any, any> ? V : never;
2247
- /** The nested selections a relation field admits: of its target entity, in the shapes its value takes. */
2248
- type NestedFor<Field> = Exclude<Field, null | undefined> extends ReadonlyArray<EntityRef<infer Name, any>> ? Selection<unknown, Name, 'entity' | 'connection'> : Exclude<Field, null | undefined> extends RefPage<infer Name, any> ? Selection<unknown, Name, 'entity' | 'connection'> : Exclude<Field, null | undefined> extends EntityRef<infer Name, any> ? Selection<unknown, Name, 'entity'> : never;
2249
- /** What a selection of an entity with fields `F` may pick: `true` per scalar, a nested selection per relation. */
2250
- type SelectionOf<F extends Schema.Struct.Fields> = { readonly [K in keyof F]?: true | NestedFor<Schema.Schema.Type<F[K]>>; };
2251
- /** `T | null` when the field admits `null` or `undefined` (both assemble to `null`). */
2252
- type Nullable<Field, T> = [Extract<Field, null | undefined>] extends [never] ? T : T | null;
2253
- /** A nested selection's value takes the shape of the field it selects through. */
2254
- type NestedValue<Field, Sel> = Sel extends Selection<infer V, string, 'connection'> ? Nullable<Field, V> : Sel extends Selection<infer V, string, 'entity'> ? Nullable<Field, Exclude<Field, null | undefined> extends ReadonlyArray<EntityRef<any, any>> ? ReadonlyArray<V> : Exclude<Field, null | undefined> extends RefPage<any, any> ? Page<V> : V> : never;
2255
- /** The value a selection `Sel` of fields `F` reads. */
2256
- type SelectionValue<F extends Schema.Struct.Fields, Sel> = Simplify<{ readonly [K in keyof Sel & keyof F]: Sel[K] extends true ? Schema.Schema.Type<F[K]> : NestedValue<Schema.Schema.Type<F[K]>, Sel[K]>; }>;
2257
- declare const pageSchema: (item: AnySchema) => AnySchema;
2258
- /** The requirement a nested selection contributes for its relation's target. */
2259
- declare const relationOf: (selection: Selection<unknown>) => RelationRequirement;
2260
- declare const Selection: {
2003
+ declare const forgetRemote: (model: RemoteModel) => RemoteModel;
2004
+ declare const initialRemoteModel: RemoteModel;
2005
+ declare const remoteModelSchema: () => Schema.Codec<RemoteModel, unknown>;
2006
+ /** The submodel's Messages; each reduces to `RemoteModel` through `updateRemote`. */
2007
+ type RemoteMessage = {
2008
+ readonly _tag: 'ReadReceived';
2009
+ readonly requests: readonly Requirement[];
2010
+ readonly result: Schema.Schema.Type<typeof ReadBatchResult>;
2011
+ readonly now: number;
2012
+ } | {
2013
+ readonly _tag: 'ReadFailed';
2014
+ readonly requests: readonly Requirement[];
2015
+ readonly error: RemoteError;
2261
2016
  /**
2262
- * The Remote Selection of a `foldkit-entity` Selection: the same members, read
2263
- * from Remote's store. `true` on a relation reads its refs, as it does here.
2017
+ * The live stream whose subscription broke, when this is that rather
2018
+ * than a read. Nothing was being read, so no field failed: the stream is
2019
+ * recorded as a gap, since changes after it are missed until the live
2020
+ * entry restarts it.
2264
2021
  */
2265
- from: <Name extends string, S extends Schema.Constraint>(selection: Domain.Selection<Name, unknown, S>) => Selection<S["Type"], Name, "entity">;
2022
+ readonly stream?: string | undefined;
2023
+ } |
2024
+ /** A refetch of present fields began; they read as `Refreshing` until it lands. */
2025
+ {
2026
+ readonly _tag: 'RefreshStarted';
2027
+ readonly requests: readonly Requirement[];
2028
+ } |
2029
+ /** A read began; the fields it asks for that the store lacks read as `Loading`. */
2030
+ {
2031
+ readonly _tag: 'ReadStarted';
2032
+ readonly requests: readonly Requirement[];
2033
+ /** The refresh generation the read was planned under. */
2034
+ readonly refresh?: number | undefined;
2035
+ } |
2036
+ /**
2037
+ * Queries for these connections were sent. One with nothing to show reads
2038
+ * `Loading` until its page or its failure arrives, which is what separates
2039
+ * "being fetched" from `Initial`, "nothing is fetching this".
2040
+ */
2041
+ {
2042
+ readonly _tag: 'QueryStarted';
2043
+ readonly connections: readonly string[];
2044
+ } |
2045
+ /** The active Surfaces' roots changed; everything they do not reach is collected. */
2046
+ {
2047
+ readonly _tag: 'RetentionChanged';
2048
+ readonly roots: RetentionRoots;
2049
+ } |
2050
+ /** A restored snapshot meets the store; runtime state is untouched. */
2051
+ {
2052
+ readonly _tag: 'Hydrated';
2053
+ readonly entities: EntityStore;
2266
2054
  /**
2267
- * The fields to read of `entity`. A nested `Selection` on a relation field
2268
- * reads through the ref (or refs, or page of refs) the field holds into the
2269
- * target's fields; a scalar field cannot take one.
2055
+ * The connections a snapshot declared should survive, as their edges.
2056
+ * Restored with **unknown** boundaries and marked stale: the rows show
2057
+ * at once and the connection is refetched, because a persisted cursor
2058
+ * may name server state that is gone.
2270
2059
  */
2271
- make: <Name extends string, F extends Schema.Struct.Fields, const Sel extends SelectionOf<F>>(entity: EntityDescriptor<Name, F>, selection: Sel) => Selection<SelectionValue<F, Sel>, Name, "entity">;
2060
+ readonly connections?: Readonly<Record<string, ReadonlyArray<ReadonlyArray<Edge>>>> | undefined;
2061
+ readonly merge: MergePolicy;
2062
+ /** The storage key the snapshot was read from, when it was: `restoredFrom`. */
2063
+ readonly from?: string | undefined;
2064
+ } |
2065
+ /** A mutation began; its optimistic operations show until it settles. */
2066
+ {
2067
+ readonly _tag: 'MutationStarted';
2068
+ readonly requestId: string;
2069
+ readonly optimistic?: ReadonlyArray<OptimisticOperation> | undefined;
2070
+ } | {
2071
+ readonly _tag: 'MutationSucceeded';
2072
+ readonly requestId: string;
2073
+ readonly entities: readonly NormalizedPatch[];
2074
+ /** Connection changes the server confirmed; they replace the request's own. */
2075
+ readonly connections?: ReadonlyArray<ConnectionChange> | undefined;
2076
+ /** Entities the mutation deleted: tombstoned, which hides them from every connection. */
2077
+ readonly deleted?: ReadonlyArray<{
2078
+ readonly entity: string;
2079
+ readonly id: string;
2080
+ }> | undefined;
2081
+ /** Injected clock reading of the answer: how fresh the written entities are. */
2082
+ readonly now: number;
2083
+ } | {
2084
+ readonly _tag: 'MutationFailed';
2085
+ readonly requestId: string;
2086
+ readonly error: RemoteError;
2087
+ } |
2088
+ /**
2089
+ * Operations shown over the store with no request behind them, until they are
2090
+ * lifted: a preview of a change nobody has made. Showing an id again replaces
2091
+ * what it showed.
2092
+ */
2093
+ {
2094
+ readonly _tag: 'OverlayShown';
2095
+ readonly id: string;
2096
+ readonly optimistic: ReadonlyArray<OptimisticOperation>;
2097
+ } | {
2098
+ readonly _tag: 'OverlayLifted';
2099
+ readonly id: string;
2100
+ } |
2101
+ /** `Data.more`: a read's window, by `windowGrowthKey`, now shows `size` rows. */
2102
+ {
2103
+ readonly _tag: 'WindowGrown';
2104
+ readonly window: string;
2105
+ readonly size: number;
2106
+ } | {
2107
+ readonly _tag: 'LiveReceived';
2108
+ readonly stream: string;
2109
+ readonly event: LiveEvent;
2110
+ readonly policy?: LivePolicy;
2111
+ readonly now: number;
2112
+ } | {
2113
+ readonly _tag: 'GapCleared';
2114
+ readonly stream: string;
2115
+ } | {
2116
+ readonly _tag: 'ConnectionMerged';
2117
+ readonly connection: string;
2118
+ readonly page: Segment;
2119
+ /** The page answers the connection's refresh, so the merge also clears `stale`. */
2120
+ readonly refreshes?: boolean | undefined;
2272
2121
  /**
2273
- * A paginated relation: one page of refs to `entity` with a window, or, with
2274
- * a nested selection, one page of targets assembled through it.
2122
+ * The slice the query asked for, so the payload's entities write like a
2123
+ * read: one request per matching edge. Absent for a page from a server
2124
+ * that predates payload planning, which carries edges only.
2275
2125
  */
2276
- connection: {
2277
- <Name extends string, F extends Schema.Struct.Fields>(entity: EntityDescriptor<Name, F>, window: QueryWindow): Selection<RefPage<Name, F>, Name, "connection">;
2278
- <Name extends string, F extends Schema.Struct.Fields, Item>(entity: EntityDescriptor<Name, F>, window: QueryWindow, selection: Selection<Item, NoInfer<Name>, "entity">): Selection<Page<Item>, Name, "connection">;
2279
- };
2280
- };
2281
- interface Assembled {
2282
- readonly values: unknown;
2283
- readonly refreshing: boolean;
2284
- }
2126
+ readonly select?: RelationRequirement | undefined;
2127
+ /** The selected fields of the page's items, as a read batch returns them. */
2128
+ readonly entities?: ReadonlyArray<{
2129
+ readonly entity: string;
2130
+ readonly id: string;
2131
+ readonly values: Record<string, unknown>;
2132
+ }> | undefined;
2133
+ /** Fields asked for that the server settled without a value. */
2134
+ readonly settled?: ReadonlyArray<{
2135
+ readonly entity: string;
2136
+ readonly id: string;
2137
+ readonly fields: ReadonlyArray<string>;
2138
+ }> | undefined;
2139
+ /** Injected clock reading of the answer, dating what the payload writes. */
2140
+ readonly now?: number | undefined;
2141
+ } | {
2142
+ readonly _tag: 'ConnectionInvalidated';
2143
+ readonly connection: string;
2144
+ } | {
2145
+ readonly _tag: 'ConnectionRefreshed';
2146
+ readonly connection: string;
2147
+ } |
2285
2148
  /**
2286
- * Reads an entity's selected fields out of the store, following each nested
2287
- * relation into its targets. `undefined` means some field, at any depth, is
2288
- * not present yet. A tombstoned target reads as `null` (or is dropped from a
2289
- * list), so the Selection's codec decides whether that is a failure.
2149
+ * A query for the connection failed. Its pages stay as they were, and it
2150
+ * reads `Failed` — with them as `previous`, when it has any — until a page
2151
+ * arrives, it is invalidated, or retention drops it.
2290
2152
  */
2291
- declare const assemble: (store: EntityStore, key: string, requirement: RelationRequirement) => Assembled | undefined;
2153
+ {
2154
+ readonly _tag: 'QueryFailed';
2155
+ readonly connection: string;
2156
+ readonly error: RemoteError;
2157
+ } |
2292
2158
  /**
2293
- * The first field `requirement` reads, at any depth, that the server settled
2294
- * without a value, as `Entity:id.field`. A read that consults it says why it
2295
- * cannot assemble rather than waiting on a field nothing will fetch.
2159
+ * What `Data.preload` read for a destination, as the Messages that wrote it,
2160
+ * reduced in order into the Model as it is now rather than the one the
2161
+ * preload started from.
2296
2162
  */
2297
- declare const unavailableOf: (store: EntityStore, key: string, requirement: RelationRequirement) => string | undefined;
2298
- //#endregion
2299
- //#region src/entity.d.ts
2300
- type AnySchema = Schema.Schema<unknown>;
2301
- declare const entityRefFields: unique symbol;
2163
+ {
2164
+ readonly _tag: 'Preloaded';
2165
+ readonly messages: ReadonlyArray<RemoteMessage>;
2166
+ };
2167
+ declare const retentionRootsSchema: Schema.Struct<{
2168
+ readonly requirements: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
2169
+ readonly connections: Schema.$Array<Schema.Struct<{
2170
+ readonly identity: Schema.String;
2171
+ readonly select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
2172
+ }>>;
2173
+ }>;
2302
2174
  /**
2303
- * A normalized reference to an entity. `F` is a phantom carrying the entity's
2304
- * fields so `Entity.patch` can type its patch; it is absent at runtime.
2175
+ * The Messages' fields by tag, without `_tag`: what `defineMessageUnion` takes,
2176
+ * so an application spreads them into its own union (`Remote.messages`).
2305
2177
  */
2306
- interface EntityRef<Name extends string, F extends Schema.Struct.Fields = Schema.Struct.Fields> {
2307
- readonly entity: Name;
2308
- readonly id: string;
2309
- readonly [entityRefFields]?: F;
2310
- }
2311
- interface EntityDescriptor<Name extends string, F extends Schema.Struct.Fields> {
2312
- readonly name: Name;
2313
- readonly schema: Schema.Struct<F>;
2314
- readonly fields: F;
2315
- ref(id: Schema.Schema.Type<F['id']>): EntityRef<Name, F>;
2316
- /** The fields a Surface reads of this entity; `Selection.make(entity, …)` with the entity as receiver. */
2317
- select<const Sel extends SelectionOf<F>>(selection: Sel): Selection<SelectionValue<F, Sel>, Name, 'entity'>;
2318
- /** A patch of this entity's wire-shaped values; `Entity.patch(entity.ref(id), values)`. */
2319
- patch(id: Schema.Schema.Type<F['id']>, values: Partial<Schema.Struct.Encoded<F>>): EntityPatch<Name, F>;
2320
- }
2178
+ declare const remoteMessageCases: {
2179
+ ReadReceived: {
2180
+ requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
2181
+ result: Schema.Struct<{
2182
+ readonly entities: Schema.$Array<Schema.Struct<{
2183
+ readonly entity: Schema.String;
2184
+ readonly id: Schema.String;
2185
+ readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
2186
+ }>>;
2187
+ readonly settled: Schema.$Array<Schema.Struct<{
2188
+ readonly entity: Schema.String;
2189
+ readonly id: Schema.String;
2190
+ readonly fields: Schema.$Array<Schema.String>;
2191
+ }>>;
2192
+ }>;
2193
+ now: Schema.Number;
2194
+ };
2195
+ ReadFailed: {
2196
+ requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
2197
+ error: Schema.Struct<{
2198
+ readonly _tag: Schema.String;
2199
+ readonly message: Schema.String;
2200
+ readonly refusal: Schema.optional<Schema.Unknown>;
2201
+ readonly reason: Schema.optional<Schema.String>;
2202
+ }>;
2203
+ stream: Schema.optional<Schema.String>;
2204
+ };
2205
+ RefreshStarted: {
2206
+ requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
2207
+ };
2208
+ ReadStarted: {
2209
+ requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
2210
+ refresh: Schema.optional<Schema.Number>;
2211
+ };
2212
+ QueryStarted: {
2213
+ connections: Schema.$Array<Schema.String>;
2214
+ };
2215
+ RetentionChanged: {
2216
+ roots: Schema.Struct<{
2217
+ readonly requirements: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
2218
+ readonly connections: Schema.$Array<Schema.Struct<{
2219
+ readonly identity: Schema.String;
2220
+ readonly select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
2221
+ }>>;
2222
+ }>;
2223
+ };
2224
+ Hydrated: {
2225
+ connections: Schema.optional<Schema.Unknown>;
2226
+ from: Schema.optional<Schema.String>;
2227
+ entities: Schema.Unknown;
2228
+ merge: Schema.Union<readonly [Schema.Literal<"replace">, Schema.Literal<"preserve-existing">]>;
2229
+ };
2230
+ MutationStarted: {
2231
+ requestId: Schema.String;
2232
+ optimistic: Schema.optional<Schema.$Array<Schema.Unknown>>;
2233
+ };
2234
+ MutationSucceeded: {
2235
+ requestId: Schema.String;
2236
+ entities: Schema.$Array<Schema.Struct<{
2237
+ readonly entity: Schema.String;
2238
+ readonly id: Schema.String;
2239
+ readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
2240
+ }>>;
2241
+ connections: Schema.optional<Schema.$Array<Schema.Unknown>>;
2242
+ deleted: Schema.optional<Schema.$Array<Schema.Struct<{
2243
+ readonly entity: Schema.String;
2244
+ readonly id: Schema.String;
2245
+ }>>>;
2246
+ now: Schema.Number;
2247
+ };
2248
+ MutationFailed: {
2249
+ requestId: Schema.String;
2250
+ error: Schema.Struct<{
2251
+ readonly _tag: Schema.String;
2252
+ readonly message: Schema.String;
2253
+ readonly refusal: Schema.optional<Schema.Unknown>;
2254
+ readonly reason: Schema.optional<Schema.String>;
2255
+ }>;
2256
+ };
2257
+ OverlayShown: {
2258
+ id: Schema.String;
2259
+ optimistic: Schema.$Array<Schema.Unknown>;
2260
+ };
2261
+ OverlayLifted: {
2262
+ id: Schema.String;
2263
+ };
2264
+ WindowGrown: {
2265
+ window: Schema.String;
2266
+ size: Schema.Number;
2267
+ };
2268
+ LiveReceived: {
2269
+ stream: Schema.String;
2270
+ event: Schema.Unknown;
2271
+ policy: Schema.optional<Schema.Unknown>;
2272
+ now: Schema.Number;
2273
+ };
2274
+ GapCleared: {
2275
+ stream: Schema.String;
2276
+ };
2277
+ ConnectionMerged: {
2278
+ connection: Schema.String;
2279
+ page: Schema.Unknown;
2280
+ refreshes: Schema.optional<Schema.Boolean>;
2281
+ select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
2282
+ entities: Schema.optional<Schema.$Array<Schema.Struct<{
2283
+ readonly entity: Schema.String;
2284
+ readonly id: Schema.String;
2285
+ readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
2286
+ }>>>;
2287
+ settled: Schema.optional<Schema.$Array<Schema.Struct<{
2288
+ readonly entity: Schema.String;
2289
+ readonly id: Schema.String;
2290
+ readonly fields: Schema.$Array<Schema.String>;
2291
+ }>>>;
2292
+ now: Schema.optional<Schema.Number>;
2293
+ };
2294
+ ConnectionInvalidated: {
2295
+ connection: Schema.String;
2296
+ };
2297
+ ConnectionRefreshed: {
2298
+ connection: Schema.String;
2299
+ };
2300
+ QueryFailed: {
2301
+ connection: Schema.String;
2302
+ error: Schema.Struct<{
2303
+ readonly _tag: Schema.String;
2304
+ readonly message: Schema.String;
2305
+ readonly refusal: Schema.optional<Schema.Unknown>;
2306
+ readonly reason: Schema.optional<Schema.String>;
2307
+ }>;
2308
+ };
2309
+ Preloaded: {
2310
+ messages: Schema.$Array<Schema.suspend<Schema.Codec<RemoteMessage, unknown, never, never>>>;
2311
+ };
2312
+ };
2313
+ type RemoteMessageTag = RemoteMessage['_tag'];
2321
2314
  /**
2322
- * Relations are **references**, never inline target schemas: a ref cannot
2323
- * reconstruct a full entity, and dereferencing is a store concern. Because the
2324
- * target schema is not inlined, recursive relations cannot arise through the
2325
- * schema graph.
2315
+ * A Remote Message as an application's union constructs it from
2316
+ * `remoteMessageCases`: the same shape `RemoteMessage` names, with the runtime
2317
+ * slots (`entities`, `event`, `page`) typed `unknown` by their schemas.
2326
2318
  */
2319
+ type RemoteMessageInput = { [Tag in RemoteMessageTag]: {
2320
+ readonly _tag: Tag;
2321
+ } & Schema.Struct.Type<(typeof remoteMessageCases)[Tag]>; }[RemoteMessageTag];
2327
2322
  /**
2328
- * A ref as the wire carries it: the target's name, a colon, and its id. Typed
2329
- * with the name, so a relation to `User` takes `'User:u1'` and not a ref to
2330
- * some other entity, which would read as a row that does not exist.
2323
+ * Whether a Message is one of Remote's, by tag. Narrows an application's union
2324
+ * to its Remote cases, and its complement to the application's own.
2331
2325
  */
2332
- type RefKey<Name extends string> = `${Name}:${string}`;
2326
+ declare const isRemoteMessage: <M extends {
2327
+ readonly _tag: string;
2328
+ }>(message: M) => message is Extract<M, {
2329
+ readonly _tag: RemoteMessageTag;
2330
+ }>;
2331
+ declare const remoteMessageSchema: Schema.Codec<RemoteMessage, unknown>;
2332
+ /** The ids `OverlayShown` shows now, each once, in the order they are drawn. */
2333
+ declare const overlaysOf: (model: RemoteModel) => ReadonlyArray<string>;
2334
+ /** The key a grown window is kept under: its connection and the window first asked for. */
2335
+ declare const windowGrowthKey: (identity: string, window: string) => string;
2333
2336
  /**
2334
- * A patch in wire shape: the values the store holds, so a relation is its ref
2335
- * key (`Entity.refKey`), not an `EntityRef`.
2337
+ * Whether only overlays show this entity: the server has told the store
2338
+ * nothing of it and no request's layer writes it, so nothing will fetch what an
2339
+ * overlay leaves out.
2336
2340
  */
2337
- interface EntityPatch<Name extends string, F extends Schema.Struct.Fields> {
2338
- readonly entity: Name;
2339
- readonly id: string;
2340
- readonly values: Partial<Schema.Struct.Encoded<F>>;
2341
- }
2341
+ declare const onlyOverlaid: (model: RemoteModel, entity: string, id: string) => boolean;
2342
+ /** Whether a query for this connection is in flight. */
2343
+ declare const isQueryLoading: (model: RemoteModel, identity: string) => boolean;
2342
2344
  /**
2343
- * One authoritative page of a paginated relation: refs (never inline entities)
2344
- * plus whether more exist. The adapter does not hold segmentation state; the
2345
- * client merges pages.
2345
+ * The generation a read is planned under: the highest any of the fields it
2346
+ * reads or connections it runs was refreshed at. A read entry carries this as a
2347
+ * dependency, so it restarts when what it observes is refreshed and not when
2348
+ * anything else is.
2346
2349
  */
2347
- interface RefPage<Name extends string, F extends Schema.Struct.Fields = Schema.Struct.Fields> {
2348
- readonly refs: ReadonlyArray<EntityRef<Name, F>>;
2349
- readonly hasNext: boolean;
2350
- readonly hasPrevious: boolean;
2351
- }
2352
- /** The ref codec a `foldkit-entity` relation becomes: one ref, a nullable ref, or an array of refs. */
2353
- type RelationField<Spec> = Spec extends Domain.RelationSpec<infer Target, infer Cardinality, infer Optional> ? Cardinality extends 'many' ? Schema.$Array<Schema.Codec<EntityRef<Target['name']>, RefKey<Target['name']>>> : Optional extends true ? Schema.NullOr<Schema.Codec<EntityRef<Target['name']>, RefKey<Target['name']>>> : Schema.Codec<EntityRef<Target['name']>, RefKey<Target['name']>> : never;
2350
+ declare const refreshedAt: (refresh: RefreshState, requests: ReadonlyArray<Requirement>, connections?: ReadonlyArray<string>) => number;
2354
2351
  /**
2355
- * The fields Remote stores for a `foldkit-entity` Entity: its own fields, its
2356
- * derived members (the server supplies them like any field), and each relation
2357
- * as refs.
2358
- */
2359
- type FieldsFrom<E> = E extends Domain.Entity<any, infer Fields, infer Relations, infer Derived> ? Fields & { readonly [K in keyof Derived]: Derived[K]['schema']; } & { readonly [K in keyof Relations]: RelationField<Relations[K]>; } : never;
2360
- declare const Entity$2: {
2361
- /**
2362
- * The Remote descriptor of a `foldkit-entity` Entity. Relations declared with
2363
- * `Entity.relate` become ref fields, so the store, the planner, and the server
2364
- * treat it as they treat an `Entity.make` descriptor.
2365
- */
2366
- from: <E extends Domain.AnyEntity>(entity: E & {
2367
- readonly fields: {
2368
- readonly id: unknown;
2369
- };
2370
- }) => EntityDescriptor<E["name"], FieldsFrom<E>>;
2371
- make: <const Name extends string, const F extends Schema.Struct.Fields & {
2372
- readonly id: Schema.Schema<unknown>;
2373
- }>(name: Name, schema: Schema.Struct<F>) => EntityDescriptor<Name, F>;
2374
- /** A relation to a known entity, decoded as a reference. */
2375
- ref: <Name extends string, F extends Schema.Struct.Fields>(entity: EntityDescriptor<Name, F>) => Schema.Codec<EntityRef<Name, F>, RefKey<Name>>;
2376
- /** A relation by name, for recursive or forward references. */
2377
- refTo: <Name extends string>(name: Name) => Schema.Codec<EntityRef<Name>, RefKey<Name>>;
2378
- /**
2379
- * The wire key a relation field carries (`"Entity:id"`). Adapters that read a
2380
- * foreign key emit this so the ref codec can decode it on the client.
2381
- */
2382
- refKey: (ref: {
2383
- readonly entity: string;
2384
- readonly id: string;
2385
- }) => string;
2386
- /** Splits a ref key back into its entity and id. */
2387
- refParts: (encoded: string) => RefParts;
2388
- /** A relation value of one authoritative page of refs. */
2389
- refPage: <Name extends string, F extends Schema.Struct.Fields>(entity: EntityDescriptor<Name, F>) => Schema.Codec<RefPage<Name, F>, {
2390
- readonly refs: ReadonlyArray<string>;
2391
- readonly hasNext: boolean;
2392
- readonly hasPrevious: boolean;
2393
- }>;
2394
- /**
2395
- * A normalized patch for an entity, typed against its fields' wire shape:
2396
- * write a relation as its ref key (`Entity.refKey`), as the server does.
2397
- */
2398
- patch: <Name extends string, F extends Schema.Struct.Fields>(ref: EntityRef<Name, F>, patch: Partial<Schema.Struct.Encoded<F>>) => EntityPatch<Name, F>;
2399
- };
2400
- //#endregion
2401
- //#region src/matching.d.ts
2352
+ * Marks every field of `requests` and every connection in `connections`
2353
+ * refreshed at the next generation.
2354
+ */
2355
+ declare const withRefreshRequested: (refresh: RefreshState, requests: ReadonlyArray<Requirement>, connections?: ReadonlyArray<string>) => RefreshState;
2402
2356
  /**
2403
- * An answer over the rows the client holds — never over the rows that exist.
2404
- *
2405
- * `complete` is the whole reason this is its own type rather than a `Page`. A
2406
- * `Page` carries `hasNext`/`hasPrevious`, which are facts the *server* stated
2407
- * about rows beyond the ones it delivered; a local answer has no such facts and
2408
- * cannot invent them. What it can say is whether the population it judged was
2409
- * all of it, which is decidable: a connection terminal at both ends is wholly
2410
- * held, and nothing was skipped for a missing field.
2411
- *
2412
- * An incomplete answer is not wrong — it is an answer about less than the
2413
- * caller may have meant, and the flag is what lets a view say "3 so far" rather
2414
- * than "3", or a caller decide to ask the server.
2357
+ * Marks connections as needing to be asked again, and restarts a read of them
2358
+ * already in flight: a page requested before what invalidated it could land
2359
+ * after it, saying what is no longer true. `Remote.refresh` marks the same way.
2415
2360
  */
2416
- interface Matched<A> {
2417
- readonly items: ReadonlyArray<A>;
2418
- /** Whether every row the answer is about was judged. */
2419
- readonly complete: boolean;
2420
- }
2361
+ declare const invalidateConnections: (model: RemoteModel, connections: ReadonlyArray<string>) => RemoteModel;
2421
2362
  /**
2422
- * What the rows the client holds had to say about a body.
2423
- *
2424
- * `skipped` is the honest half. A row missing a field the body reads cannot be
2425
- * judged — it is neither a match nor a non-match — and dropping it silently
2426
- * would turn "I could not tell" into "no". Naming it lets a caller decide:
2427
- * fetch the field, ask the server, or say the answer is partial.
2363
+ * Whether one field's read already began under the generation that field was
2364
+ * last refreshed at. Such a read is in flight and would otherwise outlive the
2365
+ * refresh, so the refresh takes a new generation to restart it even though the
2366
+ * field is already stale.
2428
2367
  */
2429
- interface Judged {
2430
- /** Keys of the rows that satisfy the body, in the order the body asks for. */
2431
- readonly matched: ReadonlyArray<EntityKey>;
2432
- /** Keys of rows held but missing a field the body reads, so not judged either way. */
2433
- readonly skipped: ReadonlyArray<EntityKey>;
2434
- }
2435
- interface MatchingOptions {
2436
- /**
2437
- * Judge only these keys. Without it every row of the body's Entity in the
2438
- * store is a candidate, which is what a filter over a loaded list wants; with
2439
- * it, a caller narrows to a connection's own edges.
2440
- */
2441
- readonly among?: ReadonlyArray<EntityKey> | undefined;
2442
- }
2368
+ declare const refreshIsInFlight: (refresh: RefreshState, request: Requirement, field: string) => boolean;
2443
2369
  /**
2444
- * The rows of `descriptor`'s Entity that the store holds and the body matches.
2445
- *
2446
- * The input is given **decoded**, as an application writes it, and encoded here
2447
- * through the descriptor's own `Input` codec. That is deliberate and is the
2448
- * whole reason this takes a descriptor rather than a bare body: a store holds
2449
- * wire values, so an input has to be in that space to be compared against them,
2450
- * and handing an interpreter a decoded value is a mistake **no runtime error
2451
- * catches** — the reference interpreter answers "no rows", which reads exactly
2452
- * like a correct answer. Doing it here means a caller cannot get it wrong.
2453
- *
2454
- * Literals in the body are deliberately *not* encoded. A literal written in
2455
- * domain terms is already broken against the server, which binds it to a column
2456
- * the same way; accepting it here would make the client quietly more permissive
2457
- * than the thing it has to agree with.
2370
+ * Whether a read is fetching any of `fields` for this entity. Consulted only
2371
+ * when the store lacks the value, which is what separates `Loading` from
2372
+ * `Initial`.
2458
2373
  */
2459
- declare const matching: <Name extends string, Input>(store: EntityStore, descriptor: QueryDescriptor<Name, Input, unknown>, input: Input, options?: MatchingOptions) => Judged;
2374
+ declare const isLoading: (model: RemoteModel, entity: string, id: string, fields: ReadonlyArray<string>) => boolean;
2460
2375
  /**
2461
- * Whether one row belongs to a query, as far as the client can tell.
2462
- *
2463
- * Three answers, and the third is the one that makes this usable. `'unknown'`
2464
- * is a row the store never fetched, or holds without a field the body reads —
2465
- * a caller that collapses it into `'no'` has turned "I could not tell" into an
2466
- * answer, which is the mistake this whole module is shaped against.
2467
- *
2468
- * **Membership is decidable where position is not.** Whether a row satisfies
2469
- * `eq`, `isNull` or `contains` needs no collation: equality on text is exact
2470
- * and `contains` folds ASCII, both stated in §6.0.1. *Where* a row sorts needs
2471
- * text collation, which is the backend's and deliberately outside the
2472
- * conformant subset — so this answers the half that is always answerable, and
2473
- * ordering stays the server's until a query can declare its collation.
2376
+ * The pure reducer all four producers share. A live event that arrives ahead of
2377
+ * its cursor is a gap: it is not applied, and the stream is recorded so its
2378
+ * live entry restarts it rather than silently missing facts. When every field a Message
2379
+ * touches keeps its identity, `model` itself is returned, so the application's
2380
+ * root keeps its identity and Foldkit does not render. The common no-ops do (a
2381
+ * duplicate live event, a repeated `ReadStarted`); a repeated failure, or a
2382
+ * `preserve-existing` restore of entities already held, still makes an equal
2383
+ * copy.
2474
2384
  */
2475
- type Belongs = 'yes' | 'no' | 'unknown';
2385
+ declare const updateRemote: (model: RemoteModel, message: RemoteMessage) => RemoteModel;
2386
+ /** Whether this field's last read failed and nothing has settled it since. */
2387
+ declare const isFieldFailed: (model: RemoteModel, entity: string, id: string, field: string) => boolean;
2476
2388
  /**
2477
- * Takes the input **encoded**, because its one caller holds it that way: a
2478
- * connection identity carries the canonical encoded input, and making it decode
2479
- * only for this to encode again would be a round trip that can fail.
2480
- *
2481
- * A decoded-input sibling was written first and deleted: nothing called it. The
2482
- * asymmetry with `matching`, which takes a decoded input, is the shape of the
2483
- * two real callers rather than an oversight.
2389
+ * Whether a read is fetching any field `relation` reads of an entity, its own
2390
+ * or, through each relation the store holds, its targets'. A value whose owner
2391
+ * is being fetched is loading, not `Initial`: nothing is missing a fetch.
2484
2392
  */
2485
- declare const belongsEncoded: <Name extends string, Input>(store: EntityStore, descriptor: QueryDescriptor<Name, Input, unknown>, encoded: Readonly<Record<string, unknown>>, key: EntityKey) => Belongs;
2393
+ declare const isLoadingThrough: (model: RemoteModel, entity: string, id: string, relation: RelationRequirement) => boolean;
2394
+ /**
2395
+ * The first failure among the fields `relation` reads of an entity, following
2396
+ * each relation the store holds into its targets, as `assemble` does. A read
2397
+ * that consults it shows `Failed` for a related entity's failure too, rather
2398
+ * than waiting on a field nothing will fetch.
2399
+ */
2400
+ declare const failureOf: (model: RemoteModel, entity: string, id: string, relation: RelationRequirement) => RemoteError | undefined;
2401
+ /**
2402
+ * Writes a read result into the store, recording each field's applied window so
2403
+ * a later request with a different window refetches. A relation page requested
2404
+ * with a cursor is merged onto the page already stored, so "load more"
2405
+ * accumulates rather than replaces. Every read path should use this rather than
2406
+ * reducing `writeEntity` by hand.
2407
+ */
2408
+ declare const writeRead: (store: EntityStore, requests: ReadonlyArray<Requirement>, result: Schema.Schema.Type<typeof ReadBatchResult>, now?: number) => EntityStore;
2486
2409
  //#endregion
2487
2410
  //#region src/inspect.d.ts
2488
2411
  /** A query body's `Dependencies` as plain data: each field by its Entity's name and key. */
@@ -2532,7 +2455,7 @@ interface RemoteInspection {
2532
2455
  /** A pure, serializable view of the whole cache. */
2533
2456
  declare const inspectRemote: (model: RemoteModel) => RemoteInspection;
2534
2457
  /** A pure, serializable view of one entity, or `undefined` if unknown. */
2535
- declare const inspectEntity: (model: RemoteModel, key: string) => RemoteInspection["entities"][number] | undefined;
2458
+ declare const inspectEntity: (model: RemoteModel, key: string) => RemoteInspection['entities'][number] | undefined;
2536
2459
  /**
2537
2460
  * Why a read shows what it shows, in words, and for `Initial`, which of the
2538
2461
  * usual mistakes it is.
@@ -2684,7 +2607,7 @@ type RemotePolicy =
2684
2607
  declare const RemotePolicy: {
2685
2608
  /** Fetch only what the store lacks. */
2686
2609
  cacheFirst: {
2687
- readonly _tag: "CacheFirst";
2610
+ readonly _tag: 'CacheFirst';
2688
2611
  };
2689
2612
  /** Keep present values visible, read as `Refreshing`, and refetch an entry older than `maxAge` ms. */
2690
2613
  staleWhileRevalidate: (options: {
@@ -2692,7 +2615,7 @@ declare const RemotePolicy: {
2692
2615
  }) => RemotePolicy;
2693
2616
  /** Fetch every selected field regardless of coverage; cached values stay visible meanwhile. */
2694
2617
  networkOnly: {
2695
- readonly _tag: "NetworkOnly";
2618
+ readonly _tag: 'NetworkOnly';
2696
2619
  };
2697
2620
  /** The planner options a policy compiles to at `now`. */
2698
2621
  toPlan: (policy: RemotePolicy, now: number) => PlanOptions;
@@ -2704,6 +2627,89 @@ declare const RemotePolicy: {
2704
2627
  refreshes: (policy: RemotePolicy) => boolean;
2705
2628
  };
2706
2629
  //#endregion
2630
+ //#region src/resume.d.ts
2631
+ /**
2632
+ * A resume part, in the shape `foldkit-ssr`'s `SSR.plan` takes in `parts`.
2633
+ * Declared here structurally, so neither package depends on the other.
2634
+ */
2635
+ interface RemoteResumePart<AppModel> {
2636
+ readonly id: string;
2637
+ /** The metadata key names whose reads this part resumes. */
2638
+ readonly covers: ReadonlyArray<string>;
2639
+ readonly capture: (model: AppModel, projections: ReadonlyArray<{
2640
+ readonly metadata: Metadata;
2641
+ }>) => unknown;
2642
+ readonly restore: (model: AppModel, value: unknown) => Result.Result<AppModel, string>;
2643
+ /** Whether a Subscription entry is one of this domain's, which may start late. */
2644
+ readonly deferrable: (key: string, entry: unknown) => boolean;
2645
+ }
2646
+ /**
2647
+ * The resume part for a Remote domain, for `SSR.plan`'s `parts`: it sends
2648
+ * what the plan's active Surfaces read from this domain's store, and nothing
2649
+ * else of it. `id` tells two domains in one application apart.
2650
+ */
2651
+ declare const resumePart: <AppModel, Store extends RemoteModel>(domain: {
2652
+ readonly store: ModelRef<AppModel, Store>;
2653
+ }, options?: {
2654
+ readonly id?: string | undefined;
2655
+ }) => RemoteResumePart<AppModel>;
2656
+ //#endregion
2657
+ //#region src/json.d.ts
2658
+ /** A request: which of Remote's calls, and its payload as the RPC protocol encodes it. */
2659
+ declare const RemoteJsonRequest: Schema.Struct<{
2660
+ readonly operation: Schema.Literals<readonly ["read", "query", "mutate"]>;
2661
+ readonly payload: Schema.Unknown;
2662
+ }>;
2663
+ type RemoteJsonRequest = typeof RemoteJsonRequest.Type;
2664
+ /** An answer: the call's result, or why there is none. */
2665
+ declare const RemoteJsonAnswer: Schema.Union<readonly [Schema.Struct<{
2666
+ readonly result: Schema.Unknown;
2667
+ }>, Schema.Struct<{
2668
+ readonly error: Schema.String;
2669
+ readonly refusal: Schema.optional<Schema.Unknown>;
2670
+ /** Who is asking was refused, with the application's reason when it gave one. */
2671
+ readonly forbidden: Schema.optional<Schema.Struct<{
2672
+ readonly reason: Schema.optional<Schema.String>;
2673
+ }>>;
2674
+ }>]>;
2675
+ type RemoteJsonAnswer = typeof RemoteJsonAnswer.Type;
2676
+ /**
2677
+ * Sends one request's text and resolves with its answer as parsed JSON. It
2678
+ * rejects when nothing came back, and the call fails with that message.
2679
+ */
2680
+ type RemoteJsonSend = (request: string) => Promise<unknown>;
2681
+ /** Remote's client over `send`, for `Remote.clientLayer`. */
2682
+ declare const json: (send: RemoteJsonSend) => RemoteRpcClient;
2683
+ /**
2684
+ * Remote's client over HTTP: each call a `POST` of the request to `url`, the
2685
+ * answer its JSON body whatever its status. A 403 is answered as forbidden
2686
+ * unless its body says so itself, as the server's own does: one from
2687
+ * middleware in front of Remote (a refused session) may say only `{ error }`.
2688
+ * `headers` is read per request, so a token that changes reaches the next
2689
+ * call. `fetch` defaults to the global one; pass it to route calls through
2690
+ * another implementation in tests.
2691
+ */
2692
+ declare const http: (url: string, options?: {
2693
+ readonly headers?: (() => Readonly<Record<string, string>>) | undefined;
2694
+ readonly fetch?: typeof fetch | undefined;
2695
+ }) => RemoteRpcClient;
2696
+ //#endregion
2697
+ //#region src/sse.d.ts
2698
+ /** What `httpWithLive` needs besides the URL. Mirrors `http`, plus the fetch itself. */
2699
+ interface LiveFetchOptions {
2700
+ /** Read per request, so a token that changes reaches the next call. */
2701
+ readonly headers?: (() => Readonly<Record<string, string>>) | undefined;
2702
+ /** Defaults to the global one; pass it to route calls elsewhere in tests. */
2703
+ readonly fetch?: typeof fetch | undefined;
2704
+ }
2705
+ /** Remote's live stream over fetch: `serveFetch`'s live open as a `Stream`. */
2706
+ declare const liveFetch: (url: string, options?: LiveFetchOptions) => RemoteRpcClient['FoldkitRemoteLive'];
2707
+ /**
2708
+ * Remote's client over HTTP with live: reads, queries, and mutations as
2709
+ * `http` sends them, live as `liveFetch` streams it, for `clientLayer`.
2710
+ */
2711
+ declare const httpWithLive: (url: string, options?: LiveFetchOptions) => RemoteRpcClient;
2712
+ //#endregion
2707
2713
  //#region src/placement.d.ts
2708
2714
  /** Where a row falls in a loaded list. */
2709
2715
  type RowPlace = Data.TaggedEnum<{
@@ -2724,65 +2730,43 @@ type RowPlace = Data.TaggedEnum<{
2724
2730
  };
2725
2731
  }>;
2726
2732
  declare const RowPlace: {
2727
- readonly Unknown: Data.TaggedEnum.ConstructorFrom<{
2728
- readonly _tag: "Unknown";
2729
- readonly reason: string;
2730
- }, "_tag">;
2731
- readonly Before: Data.TaggedEnum.ConstructorFrom<{
2733
+ readonly $is: <Tag extends "Before" | "End" | "Outside" | "Unknown">(tag: Tag) => (u: unknown) => u is Extract<{
2732
2734
  readonly _tag: "Before";
2733
2735
  readonly segment: number;
2734
2736
  readonly edge: string;
2735
- }, "_tag">;
2736
- readonly End: Data.TaggedEnum.ConstructorFrom<{
2737
- readonly _tag: "End";
2738
- readonly segment: number;
2739
- }, "_tag">;
2740
- readonly Outside: Data.TaggedEnum.ConstructorFrom<{
2741
- readonly _tag: "Outside";
2742
- }, "_tag">;
2743
- readonly $is: <Tag extends "Unknown" | "Before" | "End" | "Outside">(tag: Tag) => (u: unknown) => u is Extract<{
2744
- readonly _tag: "Unknown";
2745
- readonly reason: string;
2746
2737
  }, {
2747
2738
  readonly _tag: Tag;
2748
2739
  }> | Extract<{
2749
- readonly _tag: "Before";
2740
+ readonly _tag: "End";
2750
2741
  readonly segment: number;
2751
- readonly edge: string;
2752
2742
  }, {
2753
2743
  readonly _tag: Tag;
2754
2744
  }> | Extract<{
2755
- readonly _tag: "End";
2756
- readonly segment: number;
2745
+ readonly _tag: "Outside";
2757
2746
  }, {
2758
2747
  readonly _tag: Tag;
2759
2748
  }> | Extract<{
2760
- readonly _tag: "Outside";
2749
+ readonly _tag: "Unknown";
2750
+ readonly reason: string;
2761
2751
  }, {
2762
2752
  readonly _tag: Tag;
2763
2753
  }>;
2764
2754
  readonly $match: {
2765
- <Cases extends {
2766
- readonly Unknown: (args: {
2767
- readonly _tag: "Unknown";
2768
- readonly reason: string;
2769
- }) => any;
2770
- readonly Before: (args: {
2771
- readonly _tag: "Before";
2772
- readonly segment: number;
2773
- readonly edge: string;
2774
- }) => any;
2775
- readonly End: (args: {
2776
- readonly _tag: "End";
2777
- readonly segment: number;
2778
- }) => any;
2779
- readonly Outside: (args: {
2780
- readonly _tag: "Outside";
2781
- }) => any;
2782
- }>(cases: Cases): (value: {
2755
+ <Cases extends { readonly [Tag in "Before" | "End" | "Outside" | "Unknown"]: (args: Extract<{
2756
+ readonly _tag: "Before";
2757
+ readonly segment: number;
2758
+ readonly edge: string;
2759
+ } | {
2760
+ readonly _tag: "End";
2761
+ readonly segment: number;
2762
+ } | {
2763
+ readonly _tag: "Outside";
2764
+ } | {
2783
2765
  readonly _tag: "Unknown";
2784
2766
  readonly reason: string;
2785
- } | {
2767
+ }, {
2768
+ readonly _tag: Tag;
2769
+ }>) => any; }>(cases: Cases): (value: {
2786
2770
  readonly _tag: "Before";
2787
2771
  readonly segment: number;
2788
2772
  readonly edge: string;
@@ -2791,28 +2775,25 @@ declare const RowPlace: {
2791
2775
  readonly segment: number;
2792
2776
  } | {
2793
2777
  readonly _tag: "Outside";
2794
- }) => import("effect/Unify").Unify<ReturnType<Cases["Unknown" | "Before" | "End" | "Outside"]>>;
2795
- <Cases extends {
2796
- readonly Unknown: (args: {
2797
- readonly _tag: "Unknown";
2798
- readonly reason: string;
2799
- }) => any;
2800
- readonly Before: (args: {
2801
- readonly _tag: "Before";
2802
- readonly segment: number;
2803
- readonly edge: string;
2804
- }) => any;
2805
- readonly End: (args: {
2806
- readonly _tag: "End";
2807
- readonly segment: number;
2808
- }) => any;
2809
- readonly Outside: (args: {
2810
- readonly _tag: "Outside";
2811
- }) => any;
2812
- }>(value: {
2778
+ } | {
2813
2779
  readonly _tag: "Unknown";
2814
2780
  readonly reason: string;
2781
+ }) => import("effect/Unify").Unify<ReturnType<Cases["Before" | "End" | "Outside" | "Unknown"]>>;
2782
+ <Cases extends { readonly [Tag in "Before" | "End" | "Outside" | "Unknown"]: (args: Extract<{
2783
+ readonly _tag: "Before";
2784
+ readonly segment: number;
2785
+ readonly edge: string;
2786
+ } | {
2787
+ readonly _tag: "End";
2788
+ readonly segment: number;
2789
+ } | {
2790
+ readonly _tag: "Outside";
2815
2791
  } | {
2792
+ readonly _tag: "Unknown";
2793
+ readonly reason: string;
2794
+ }, {
2795
+ readonly _tag: Tag;
2796
+ }>) => any; }>(value: {
2816
2797
  readonly _tag: "Before";
2817
2798
  readonly segment: number;
2818
2799
  readonly edge: string;
@@ -2821,8 +2802,27 @@ declare const RowPlace: {
2821
2802
  readonly segment: number;
2822
2803
  } | {
2823
2804
  readonly _tag: "Outside";
2824
- }, cases: Cases): import("effect/Unify").Unify<ReturnType<Cases["Unknown" | "Before" | "End" | "Outside"]>>;
2805
+ } | {
2806
+ readonly _tag: "Unknown";
2807
+ readonly reason: string;
2808
+ }, cases: Cases): import("effect/Unify").Unify<ReturnType<Cases["Before" | "End" | "Outside" | "Unknown"]>>;
2825
2809
  };
2810
+ readonly Before: Data.TaggedEnum.ConstructorFrom<{
2811
+ readonly _tag: "Before";
2812
+ readonly segment: number;
2813
+ readonly edge: string;
2814
+ }, "_tag">;
2815
+ readonly End: Data.TaggedEnum.ConstructorFrom<{
2816
+ readonly _tag: "End";
2817
+ readonly segment: number;
2818
+ }, "_tag">;
2819
+ readonly Outside: Data.TaggedEnum.ConstructorFrom<{
2820
+ readonly _tag: "Outside";
2821
+ }, "_tag">;
2822
+ readonly Unknown: Data.TaggedEnum.ConstructorFrom<{
2823
+ readonly _tag: "Unknown";
2824
+ readonly reason: string;
2825
+ }, "_tag">;
2826
2826
  };
2827
2827
  /**
2828
2828
  * Where the row stored under `key` falls in `connection`, by `body`'s order
@@ -3166,6 +3166,19 @@ interface RemoteDomain<AppModel, Store extends RemoteModel, Entities extends rea
3166
3166
  * held is not asked again.
3167
3167
  */
3168
3168
  satisfy(model: AppModel, active: Readonly<Record<string, ActiveEntry<AppModel>>>, options?: SatisfyOptions): Effect.Effect<AppModel, RemoteReadError | RemoteProtocolError | RemoteQueryError | RemoteUnsatisfied, RemoteClient>;
3169
+ /**
3170
+ * `satisfy` from `update`, for a destination the reader has not reached:
3171
+ * a hover over a link, or a navigation the app expects. `model` is the
3172
+ * Model as it would be there (the route set to the target's); the Command
3173
+ * reads what `active` would read in it and yields one `Preloaded`
3174
+ * carrying the Messages that wrote it, which reduce into the Model as it is
3175
+ * by then. It never fails: a read that fails is one the destination makes
3176
+ * again, and what was read before it still arrives.
3177
+ *
3178
+ * What it reads is kept like any other read until the next change of what
3179
+ * is retained, so preload close to the navigation it expects.
3180
+ */
3181
+ preload(model: AppModel, active: Readonly<Record<string, ActiveEntry<AppModel>>>, options?: SatisfyOptions): Command<RemoteMessage, never, RemoteClient>;
3169
3182
  /**
3170
3183
  * Starts a registered mutation from `update`: applies `MutationStarted` (with
3171
3184
  * the optimistic operations) to the Model and returns the Command that runs
@@ -3230,6 +3243,8 @@ interface RemoteFold<AppModel, ParentMessage, Domain extends RemoteDomain<AppMod
3230
3243
  (model: AppModel, message: RemoteMessage | RemoteMessageInput): Update.Return<AppModel, ParentMessage>;
3231
3244
  /** `Data.mutate`, its Command lifted. */
3232
3245
  readonly mutate: (...args: Parameters<Domain['mutate']>) => FoldedMutationStarted<AppModel, ParentMessage>;
3246
+ /** `Data.preload`, its Command lifted. */
3247
+ readonly preload: (...args: Parameters<Domain['preload']>) => Command<ParentMessage, never, RemoteClient>;
3233
3248
  /** `Data.subscriptions`, every entry lifted to the wrapper Message. */
3234
3249
  readonly subscriptions: <const Active extends Readonly<Record<string, ActiveEntry<AppModel>>>>(active: Active, options?: SubscriptionsOptions) => SubscriptionEntries<AppModel, Active, ParentMessage>;
3235
3250
  }
@@ -3325,6 +3340,14 @@ interface LiveOptions {
3325
3340
  /** The longest a restart waits. Default `5 seconds`. */
3326
3341
  readonly maxRetryDelay?: Duration.Input | undefined;
3327
3342
  }
3343
+ /** Declares a Remote domain: its entities, queries, and mutations, plus the submodel. */
3344
+ declare const defineRemote: <const Entities extends readonly EntityLike[], const Queries extends readonly QueryDescriptor<any, any, any>[] = readonly QueryDescriptor<any, any, any>[], const Mutations extends readonly MutationDescriptor<any, any, any>[] = readonly MutationDescriptor<any, any, any>[]>(config: {
3345
+ readonly entities: Entities;
3346
+ readonly queries?: Queries;
3347
+ readonly mutations?: Mutations;
3348
+ }) => RemoteDescriptor<Entities, Queries, Mutations>;
3349
+ /** Binds a Remote domain to its store's location in the application Model. */
3350
+ declare const bindRemote: <AppModel, Store extends RemoteModel, Entities extends readonly EntityLike[], Queries extends readonly QueryDescriptor<any, any, any>[], Mutations extends readonly MutationDescriptor<any, any, any>[]>(definition: RemoteDescriptor<Entities, Queries, Mutations>, store: ModelRef<AppModel, Store>) => BoundRemote<AppModel, Store, EntityName<Entities[number]>>;
3328
3351
  /** A query the read entry runs, as its dependencies carry it: plain data Foldkit compares. */
3329
3352
  declare const PlannedQuery: Schema.Struct<{
3330
3353
  readonly identity: Schema.String;
@@ -3496,13 +3519,12 @@ declare const Remote: {
3496
3519
  readonly reason: Schema.optional<Schema.String>;
3497
3520
  }>;
3498
3521
  };
3522
+ Preloaded: {
3523
+ messages: Schema.$Array<Schema.suspend<Schema.Codec<RemoteMessage, unknown, never, never>>>;
3524
+ };
3499
3525
  };
3500
3526
  /** Whether a Message is one of Remote's, by tag. */
3501
- reduces: <M extends {
3502
- readonly _tag: string;
3503
- }>(message: M) => message is Extract<M, {
3504
- readonly _tag: RemoteMessageTag;
3505
- }>;
3527
+ reduces: typeof isRemoteMessage;
3506
3528
  /**
3507
3529
  * Remote's Messages as one Schema, for a wrapper variant in the
3508
3530
  * application's union: `GotRemoteMessage: { message: Remote.Message }`. With
@@ -3640,6 +3662,9 @@ declare const Remote: {
3640
3662
  readonly reason: Schema.optional<Schema.String>;
3641
3663
  }>;
3642
3664
  };
3665
+ Preloaded: {
3666
+ messages: Schema.$Array<Schema.suspend<Schema.Codec<RemoteMessage, unknown, never, never>>>;
3667
+ };
3643
3668
  }>;
3644
3669
  /**
3645
3670
  * A bound domain under one wrapper variant of the application's union, the
@@ -3704,28 +3729,20 @@ declare const Remote: {
3704
3729
  * mutations, plus the submodel. For a domain reused across applications or
3705
3730
  * bound in a test; `Remote.make` is the one-step form.
3706
3731
  */
3707
- define: <const Entities extends readonly EntityLike[], const Queries extends readonly QueryDescriptor<any, any, any>[] = readonly QueryDescriptor<any, any, any>[], const Mutations extends readonly MutationDescriptor<any, any, any>[] = readonly MutationDescriptor<any, any, any, unknown>[]>(config: {
3708
- readonly entities: Entities;
3709
- readonly queries?: Queries;
3710
- readonly mutations?: Mutations;
3711
- }) => RemoteDescriptor<Entities, Queries, Mutations>;
3732
+ define: typeof defineRemote;
3712
3733
  /**
3713
3734
  * Binds a Remote domain to its store's location in the application Model. The
3714
3735
  * registered entity names are carried on the returned value, so `Remote.select`
3715
3736
  * rejects a selection for an entity this domain never declared.
3716
3737
  */
3717
- at: <AppModel, Store extends RemoteModel, Entities extends readonly EntityLike[], Queries extends readonly QueryDescriptor<any, any, any>[], Mutations extends readonly MutationDescriptor<any, any, any>[]>(definition: RemoteDescriptor<Entities, Queries, Mutations>, store: ModelRef<AppModel, Store>) => BoundRemote<AppModel, Store, EntityName<Entities[number]>>;
3738
+ at: typeof bindRemote;
3718
3739
  /**
3719
3740
  * The resume part for this domain, for `foldkit-ssr`'s `SSR.plan({ parts })`:
3720
3741
  * a server render sends what the plan's active Surfaces read from the store,
3721
3742
  * each connection with its boundaries and each live cursor with it, and
3722
3743
  * nothing else. `id` tells two domains in one application apart.
3723
3744
  */
3724
- resume: <AppModel, Store extends RemoteModel>(domain: {
3725
- readonly store: ModelRef<AppModel, Store>;
3726
- }, options?: {
3727
- readonly id?: string | undefined;
3728
- }) => RemoteResumePart<AppModel>;
3745
+ resume: typeof resumePart;
3729
3746
  /**
3730
3747
  * A Projection node that reads a `RemoteData` value out of the store. The id
3731
3748
  * is supplied by the caller, usually from a Surface's params. The assembled
@@ -3733,7 +3750,7 @@ declare const Remote: {
3733
3750
  * as `Failed` instead of being asserted into `Value`. A present value with a
3734
3751
  * stale field reads as `Refreshing`: an observer is refetching it.
3735
3752
  */
3736
- select: <AppModel, Store extends RemoteModel, Names extends string, Value, Name extends string>(bound: BoundRemote<AppModel, Store, Names>, given: EntitySelection<Value, Name> & Registered<Name, Names, "Entity">) => (id: string) => Projection<AppModel, RemoteData<Value>>;
3753
+ select: <AppModel, Store extends RemoteModel, Names extends string, Value, Name extends string>(bound: BoundRemote<AppModel, Store, Names>, given: EntitySelection<Value, Name> & Registered<Name, Names, 'Entity'>) => (id: string) => Projection<AppModel, RemoteData<Value>>;
3737
3754
  /**
3738
3755
  * When what a projection shows was last received, and whether it is stale
3739
3756
  * or loading. Pure, so a view can show "updated 5s ago" without I/O.
@@ -3774,7 +3791,7 @@ declare const Remote: {
3774
3791
  * `policy` decides what a present field means (default cache-first); `now`
3775
3792
  * is the clock it reads, so the planner itself stays pure and time-injected.
3776
3793
  */
3777
- prefetch: <AppModel, Store extends RemoteModel, Value>(bound: BoundRemote<AppModel, Store, string>, model: AppModel, projection: Projection<AppModel, Value>, options?: ObserveOptions | undefined) => Effect.Effect<Readonly<Record<string, EntityEntry>>, RemoteReadError | RemoteProtocolError, RemoteClient>;
3794
+ prefetch: <AppModel, Store extends RemoteModel, Value>(bound: BoundRemote<AppModel, Store, string>, model: AppModel, projection: Projection<AppModel, Value>, options?: ObserveOptions | undefined) => Effect.Effect<Readonly<Record<string, EntityEntry>>, RemoteProtocolError | RemoteReadError, RemoteClient>;
3778
3795
  /**
3779
3796
  * Marks what a projection, or a Surface without params, requires as due again.
3780
3797
  * Called from `update`: every selected field the store holds reads `Refreshing`,
@@ -3812,7 +3829,7 @@ declare const Remote: {
3812
3829
  * Writes a read result into the store, recording each field's applied window.
3813
3830
  * `requests` are the planned requirements the result answers.
3814
3831
  */
3815
- writeRead: (store: EntityStore, requests: ReadonlyArray<Requirement>, result: Schema.Schema.Type<typeof ReadBatchResult>, now?: number) => EntityStore;
3832
+ writeRead: typeof writeRead;
3816
3833
  /**
3817
3834
  * Adapts an Effect RPC client for `RemoteRpc` to `RemoteClient`, so an
3818
3835
  * application provides the transport's RPC layer instead of writing the
@@ -3826,29 +3843,26 @@ declare const Remote: {
3826
3843
  * answer, for `clientLayer`: a worker, a server in the page. `RemoteServer.answer`
3827
3844
  * is the other end.
3828
3845
  */
3829
- json: (send: RemoteJsonSend) => RemoteRpcClient;
3846
+ json: typeof json;
3830
3847
  /**
3831
3848
  * Remote's client over HTTP, for `clientLayer`: each call a `POST` of the JSON
3832
3849
  * request to `url`. `headers` is read per request (a session token, say).
3833
3850
  */
3834
- http: (url: string, options?: {
3835
- readonly headers?: (() => Readonly<Record<string, string>>) | undefined;
3836
- readonly fetch?: typeof fetch | undefined;
3837
- }) => RemoteRpcClient;
3851
+ http: typeof http;
3838
3852
  /**
3839
3853
  * Remote's client over HTTP with live, for `clientLayer`: reads, queries,
3840
3854
  * and mutations as `http` sends them, live requirements as one `POST`
3841
3855
  * answered with a `text/event-stream` of changes.
3842
3856
  * `foldkit-remote-server/fetch` is the other end.
3843
3857
  */
3844
- httpWithLive: (url: string, options?: LiveFetchOptions) => RemoteRpcClient;
3858
+ httpWithLive: typeof httpWithLive;
3845
3859
  clientLayer: <R = never>(client: RemoteRpcClient<R, RpcClientError.RpcClientError>, options?: CoalesceOptions) => Layer.Layer<RemoteClient, never, R>;
3846
3860
  /**
3847
3861
  * Wraps a `RemoteClient` layer so its reads coalesce: requirements issued
3848
3862
  * together become one batch, and a requirement already in flight is joined.
3849
3863
  * `Remote.clientLayer` applies this; use it on a hand-written client.
3850
3864
  */
3851
- coalesced: <E, R>(layer: Layer.Layer<RemoteClient, E, R>, options?: CoalesceOptions) => Layer.Layer<RemoteClient, E, R>;
3865
+ coalesced: typeof coalescedLayer;
3852
3866
  /**
3853
3867
  * A Foldkit Subscription entry that keeps the cache to what the active
3854
3868
  * Surfaces reach. `projections` are the ones the application observes (the
@@ -3901,9 +3915,9 @@ declare const Remote: {
3901
3915
  /** The `RemoteMessage` that merges a query page into its connection. */
3902
3916
  queryMessage: <Name extends string, Input>(ref: QueryRef<Name, Input>, result: Schema.Schema.Type<typeof QueryResult>, select?: RelationRequirement | undefined, now?: number | undefined) => RemoteMessage;
3903
3917
  /** A pure, serializable view of the whole cache. */
3904
- inspect: (model: RemoteModel) => RemoteInspection;
3918
+ inspect: typeof inspectRemote;
3905
3919
  /** A pure, serializable view of one entity, or `undefined` if unknown. */
3906
- inspectEntity: (model: RemoteModel, key: string) => RemoteInspection["entities"][number] | undefined;
3920
+ inspectEntity: typeof inspectEntity;
3907
3921
  /**
3908
3922
  * Runs a mutation through `RemoteClient`, decoding its typed Output and
3909
3923
  * returning the result's normalized patches so the caller can reconcile them
@@ -3923,7 +3937,7 @@ declare const Remote: {
3923
3937
  readonly entity: string;
3924
3938
  readonly id: string;
3925
3939
  }[];
3926
- }, RemoteMutationError | RemoteForbidden, RemoteClient>;
3940
+ }, RemoteForbidden | RemoteMutationError, RemoteClient>;
3927
3941
  /**
3928
3942
  * Runs a mutation and reconciles its patches into a `RemoteModel` in one step,
3929
3943
  * returning the new model alongside the typed Output. The model-level form of
@@ -3934,7 +3948,7 @@ declare const Remote: {
3934
3948
  mutateInto: <Name extends string, Input, Output, AppModel, Store extends RemoteModel>(bound: BoundRemote<AppModel, Store, string>, model: AppModel, mutation: MutationDescriptor<Name, Input, Output, unknown>, input: Input, requestId: string, options?: MutateOptions | undefined) => Effect.Effect<{
3935
3949
  output: Output;
3936
3950
  model: AppModel;
3937
- }, RemoteMutationError | RemoteForbidden, RemoteClient>;
3951
+ }, RemoteForbidden | RemoteMutationError, RemoteClient>;
3938
3952
  /**
3939
3953
  * A Foldkit Subscription entry that plans a Surface's missing fields from the
3940
3954
  * Model and fetches them through `RemoteClient`, emitting a `RemoteMessage`
@@ -3956,5 +3970,5 @@ declare const Remote: {
3956
3970
  live: <AppModel, Store extends RemoteModel, Names extends string, Model, SurfaceMessage, Params, Message = RemoteMessage>(bound: BoundRemote<AppModel, Store, Names>, surface: Surface<AppModel, Model, SurfaceMessage, Params>, params: Params, toMessage?: (message: RemoteMessage) => Message, options?: LiveOptions) => EntryWithoutKeepAlive<AppModel, Message, LiveDependencies, RemoteClient>;
3957
3971
  };
3958
3972
  //#endregion
3959
- export { Matched as $, writeEntity as $i, RelationRequest as $n, RemoteConnections as $r, RemoteResumePart as $t, RemoteWiring as A, patchOfWrite as Ai, withRefreshRequested as An, emptyLiveState as Ar, refsIn as At, PlanFreshness as B, entry as Bi, MutationRequest as Bn, addOverlay as Br, RemoteClient as Bt, Registered as C, SchemaOrFields as Ci, refreshedAt as Cn, LiveCursor as Cr, RelationAnnotation as Ct, RemoteEntry as D, failMutation as Di, retentionRootsSchema as Dn, applyConnectionEvent as Dr, aliasedField as Dt, RemoteDomain as E, emptyMutationState as Ei, remoteModelSchema as En, LiveState as Er, RelationShape as Et, SubscriptionsOptions as F, EntityStore as Fi, LiveEdge as Fn, ConnectionOverlay as Fr, httpWithLive as Ft, ExplainedDependencies as G, markStale as Gi, QueryRequest as Gn, removeLayer as Gr, mutateRemote as Gt, deadlineOf as H, isFieldStale as Hi, NormalizedEntity as Hn, connectionIdentity as Hr, coalescedLayer as Ht, RowPlace as I, EntityWrite as Ii, LiveRequirement as In, EntityLayer as Ir, liveFetch as It, RemoteInspection as J, remove as Ji, REMOTE_PROTOCOL_VERSION as Jn, settleSuccess as Jr, CoalesceOptions as Jt, QueryExplanation as K, missingFields as Ki, QueryResult as Kn, removeOverlay as Kr, remoteError as Kt, placeIn as L, clearStale as Li, MAX_FIELDS_PER_REQUEST as Ln, OptimisticOperation as Lr, RemoteJsonAnswer as Lt, SatisfyOptions as M, schemaOf as Mi, ConnectionChangeSchema as Mn, liveHasPrevious as Mr, relationShape as Mt, SelectsEntity as N, EntityEntry as Ni, Live as Nn, ConnectionChange as Nr, targetsOf as Nt, RemoteFold as O, mutationStatus as Oi, updateRemote as On, applyEntityEvent as Or, isRefPage as Ot, SubscriptionEntries as P, EntityKey as Pi, LiveChange as Pn, ConnectionIdentity as Pr, LiveFetchOptions as Pt, Judged as Q, writeEntities as Qi, ReadRequest as Qn, RelationRequirement as Qr, requirementKey as Qt, RemotePolicy as R, emptyStore as Ri, MAX_RELATION_DEPTH as Rn, OptimisticState as Rr, RemoteJsonRequest as Rt, ReadMeta as S, Refusal as Si, refreshIsInFlight as Sn, EntityApplied as Sr, RefParts as St, RemoteDescriptor as T, beginMutation as Ti, remoteMessageSchema as Tn, LiveOutcome as Tr, RelationKind as Tt, plan as U, isFieldUnavailable as Ui, PageSize as Un, emptyOptimistic as Ur, connectionChangeOf as Ut, PlanOptions as V, hasField as Vi, MutationResult as Vn, beginOptimistic as Vr, RemoteRpcClient as Vt, windowKey as W, isTombstone as Wi, QueryEdge as Wn, pruneOverlays as Wr, liveEventOf as Wt, inspectRemote as X, setUnavailable as Xi, ReadBatch as Xn, visibleStore as Xr, coalesceQueries as Xt, inspectEntity as Y, setStale as Yi, Read as Yn, visibleItems as Yr, QueryRun as Yt, Belongs as Z, tombstone as Zi, ReadBatchResult as Zn, ConnectionRequirement as Zr, coalesceReads as Zt, QueryOptions as _, items as _a, MutationDescriptor as _i, isQueryLoading as _n, RetentionRoots as _r, pageSchema as _t, EntitySelection as a, Boundary as aa, IDENTITY_SEPARATOR as ai, RemoteMessageInput as an, RemoteReadError as ar, EntityDescriptor as at, QueryWindowOptions as b, terminal as ba, NormalizedPatch as bi, onlyOverlaid as bn, BoundaryCounts as br, RELATION_ALIAS as bt, LiveOptions as c, Edge as ca, Query$1 as ci, StreamHealth as cn, WindowSchema as cr, FieldsFrom as ct, MutateOptions as d, cursor as da, QueryRef as di, forgetRemote as dn, REMOTE_CACHE_VERSION as dr, Page as dt, Freshness as ea, RemoteRequirements as ei, Failures as en, RemoteForbidden as er, MatchingOptions as et, MutationStarted as f, edge as fa, QueryWindow as fi, initialRemoteModel as fn, RemotePersistence as fr, Selection as ft, QueryInput as g, isGapped as ga, MutationAnswer as gi, isLoadingThrough as gn, Retained as gr, assemble as gt, QueryEntity as h, hasPrevious as ha, Mutation as hi, isLoading as hn, ConnectionRoot as hr, SelectionValueOf as ht, EntityLike as i, remoteErrorSchema as ia, ConnectionSpec as ii, RemoteMessage as in, RemoteQueryError as ir, Entity$2 as it, RetainOptions as j, reconcileMutation as ji, writeRead as jn, liveHasNext as jr, relationAlias as jt, RemoteUnsatisfied as k, optimisticOfWrite as ki, windowGrowthKey as kn, classifyLive as kr, refParts as kt, LiveStatus as l, EdgeRef as la, QueryDescriptor as li, emptyRefresh as ln, WireBoundary as lr, RefKey as lt, PersistenceOptions as m, hasNext as ma, stableStringify as mi, isFieldFailed as mn, SnapshotOptions as mr, SelectionValue as mt, BoundRemote as n, RemoteError as na, connectionsOf as ni, PlacementMismatch as nn, RemoteMutationError as nr, matching as nt, FoldedMutationStarted as o, Connection as oa, LiveInsertion as oi, RemoteMessageTag as on, RemoteRpc as or, EntityPatch as ot, ObserveOptions as p, emptyConnection as pa, ResultOf as pi, invalidateConnections as pn, Snapshot as pr, SelectionOf as pt, ReadDiagnosis as q, readField as qi, QueryRpc as qn, settleFailure as qr, BatchRead as qt, DomainMutateOptions as r, remoteDataSchema as ra, requirementsOf as ri, RefreshState as rn, RemoteProtocolError as rr, AnySchema as rt, LiveDependencies as s, Cursor as sa, LivePolicy as si, RemoteModel as sn, SettledFields as sr, EntityRef as st, ActiveEntry as t, RemoteData as ta, Requirement as ti, PlacedOrder as tn, RemoteLiveError as tr, belongsEncoded as tt, ModelOfDomain as u, Segment as ua, QueryInputs as ui, failureOf as un, MergePolicy as ur, RefPage as ut, QueryProjection as v, merge as va, MutationState as vi, isRemoteMessage as vn, gc as vr, relationOf as vt, Remote as w, TypeOf as wi, remoteMessageCases as wn, LiveEvent as wr, RelationEntityAnnotation as wt, ReadDependencies as x, unknown as xa, Reconciled as xi, overlaysOf as xn, ConnectionApplied as xr, RefPageValue as xt, QueryRequirement as y, segment as ya, MutationStatus as yi, noFailures as yn, reachable as yr, unavailableOf as yt, Deadline as z, entityKey as zi, Mutate as zn, addLayer as zr, RemoteJsonSend as zt };
3960
- //# sourceMappingURL=index-CXAGo7Dz.d.mts.map
3973
+ export { QueryExplanation as $, terminal as $i, coalesceReads as $n, ConnectionOverlay as $r, Entity$2 as $t, RemoteWiring as A, patchOfWrite as Ai, RemoteRpcClient as An, SettledFields as Ar, remoteModelSchema as At, liveFetch as B, Cursor as Bi, LiveEvent as Bn, ConnectionSpec as Br, SnapshotOptions as Bt, Registered as C, SchemaOrFields as Ci, isRefPage as Cn, RemoteForbidden as Cr, noFailures as Ct, RemoteEntry as D, failMutation as Di, relationShape as Dn, RemoteQueryError as Dr, refreshedAt as Dt, RemoteDomain as E, emptyMutationState as Ei, relationAlias as En, RemoteProtocolError as Er, refreshIsInFlight as Et, SubscriptionsOptions as F, RemoteError as Fi, remoteError as Fn, RemoteConnections as Fr, writeRead as Ft, RemotePolicy as G, edge as Gi, classifyLive as Gn, QueryDescriptor as Gr, reachable as Gt, RemoteJsonRequest as H, EdgeRef as Hi, LiveState as Hn, LiveInsertion as Hr, Retained as Ht, RowPlace as I, remoteDataSchema as Ii, BoundaryCounts as In, RemoteRequirements as Ir, MergePolicy as It, PlanOptions as J, hasPrevious as Ji, liveHasPrevious as Jn, QueryWindow as Jr, Matched as Jt, Deadline as K, emptyConnection as Ki, emptyLiveState as Kn, QueryInputs as Kr, Belongs as Kt, placeIn as L, remoteErrorSchema as Li, ConnectionApplied as Ln, Requirement as Lr, REMOTE_CACHE_VERSION as Lt, SatisfyOptions as M, schemaOf as Mi, connectionChangeOf as Mn, WireBoundary as Mr, updateRemote as Mt, SelectsEntity as N, Freshness as Ni, liveEventOf as Nn, ConnectionRequirement as Nr, windowGrowthKey as Nt, RemoteFold as O, mutationStatus as Oi, targetsOf as On, RemoteReadError as Or, remoteMessageCases as Ot, SubscriptionEntries as P, RemoteData as Pi, mutateRemote as Pn, RelationRequirement as Pr, withRefreshRequested as Pt, ExplainedDependencies as Q, segment as Qi, coalesceQueries as Qn, ConnectionIdentity as Qr, AnySchema as Qt, LiveFetchOptions as R, Boundary as Ri, EntityApplied as Rn, connectionsOf as Rr, RemotePersistence as Rt, ReadMeta as S, Refusal as Si, aliasedField as Sn, RelationRequest as Sr, isRemoteMessage as St, RemoteDescriptor as T, beginMutation as Ti, refsIn as Tn, RemoteMutationError as Tr, overlaysOf as Tt, RemoteJsonSend as U, Segment as Ui, applyConnectionEvent as Un, LivePolicy as Ur, RetentionRoots as Ut, RemoteJsonAnswer as V, Edge as Vi, LiveOutcome as Vn, IDENTITY_SEPARATOR as Vr, ConnectionRoot as Vt, RemoteResumePart as W, cursor as Wi, applyEntityEvent as Wn, Query$1 as Wr, gc as Wt, plan as X, items as Xi, CoalesceOptions as Xn, stableStringify as Xr, belongsEncoded as Xt, deadlineOf as Y, isGapped as Yi, BatchRead as Yn, ResultOf as Yr, MatchingOptions as Yt, windowKey as Z, merge as Zi, QueryRun as Zn, ConnectionChange as Zr, matching as Zt, QueryOptions as _, setStale as _a, MutationDescriptor as _i, RefParts as _n, REMOTE_PROTOCOL_VERSION as _r, invalidateConnections as _t, EntitySelection as a, clearStale as aa, beginOptimistic as ai, RefPage as an, LiveRequirement as ar, PlacedOrder as at, QueryWindowOptions as b, writeEntities as ba, NormalizedPatch as bi, RelationKind as bn, ReadBatchResult as br, isLoadingThrough as bt, LiveOptions as c, entry as ca, pruneOverlays as ci, SelectionOf as cn, Mutate as cr, RemoteMessage as ct, MutateOptions as d, isFieldUnavailable as da, settleFailure as di, assemble as dn, NormalizedEntity as dr, RemoteModel as dt, unknown as ea, EntityLayer as ei, EntityDescriptor as en, requirementKey as er, ReadDiagnosis as et, MutationStarted as f, isTombstone as fa, settleSuccess as fi, pageSchema as fn, PageSize as fr, StreamHealth as ft, QueryInput as g, remove as ga, MutationAnswer as gi, RefPageValue as gn, QueryRpc as gr, initialRemoteModel as gt, QueryEntity as h, readField as ha, Mutation as hi, RELATION_ALIAS as hn, QueryResult as hr, forgetRemote as ht, EntityLike as i, EntityWrite as ia, addOverlay as ii, RefKey as in, LiveEdge as ir, Failures as it, RetainOptions as j, reconcileMutation as ji, coalescedLayer as jn, WindowSchema as jr, retentionRootsSchema as jt, RemoteUnsatisfied as k, optimisticOfWrite as ki, RemoteClient as kn, RemoteRpc as kr, remoteMessageSchema as kt, LiveStatus as l, hasField as la, removeLayer as li, SelectionValue as ln, MutationRequest as lr, RemoteMessageInput as lt, PersistenceOptions as m, missingFields as ma, visibleStore as mi, unavailableOf as mn, QueryRequest as mr, failureOf as mt, BoundRemote as n, EntityKey as na, OptimisticState as ni, EntityRef as nn, Live as nr, inspectEntity as nt, FoldedMutationStarted as o, emptyStore as oa, connectionIdentity as oi, Page as on, MAX_FIELDS_PER_REQUEST as or, PlacementMismatch as ot, ObserveOptions as p, markStale as pa, visibleItems as pi, relationOf as pn, QueryEdge as pr, emptyRefresh as pt, PlanFreshness as q, hasNext as qi, liveHasNext as qn, QueryRef as qr, Judged as qt, DomainMutateOptions as r, EntityStore as ra, addLayer as ri, FieldsFrom as rn, LiveChange as rr, inspectRemote as rt, LiveDependencies as s, entityKey as sa, emptyOptimistic as si, Selection as sn, MAX_RELATION_DEPTH as sr, RefreshState as st, ActiveEntry as t, EntityEntry as ta, OptimisticOperation as ti, EntityPatch as tn, ConnectionChangeSchema as tr, RemoteInspection as tt, ModelOfDomain as u, isFieldStale as ua, removeOverlay as ui, SelectionValueOf as un, MutationResult as ur, RemoteMessageTag as ut, QueryProjection as v, setUnavailable as va, MutationState as vi, RelationAnnotation as vn, Read as vr, isFieldFailed as vt, Remote as w, TypeOf as wi, refParts as wn, RemoteLiveError as wr, onlyOverlaid as wt, ReadDependencies as x, writeEntity as xa, Reconciled as xi, RelationShape as xn, ReadRequest as xr, isQueryLoading as xt, QueryRequirement as y, tombstone as ya, MutationStatus as yi, RelationEntityAnnotation as yn, ReadBatch as yr, isLoading as yt, httpWithLive as z, Connection as zi, LiveCursor as zn, requirementsOf as zr, Snapshot as zt };
3974
+ //# sourceMappingURL=index-eVkkbhPA.d.mts.map