foldkit-remote 0.15.0 → 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,59 +1088,7 @@ 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<{
1337
- readonly version: Schema.Number;
1338
- readonly requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
1339
- }>, Schema.Struct<{
1340
- readonly entities: Schema.$Array<Schema.Struct<{
1341
- readonly entity: Schema.String;
1342
- readonly id: Schema.String;
1343
- readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
1344
- }>>;
1345
- readonly settled: Schema.$Array<Schema.Struct<{
1346
- readonly entity: Schema.String;
1347
- 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<{
1351
- /** Stable across transport retries so a mutation is not applied twice. */
1352
- readonly requestId: Schema.String;
1353
- readonly mutation: Schema.String;
1354
- readonly input: Schema.Unknown;
1355
- /** For a mutation that is a `Write`: the input keys to write, when not all of them. */
1356
- readonly keys: Schema.optional<Schema.$Array<Schema.String>>;
1357
- }>, Schema.Struct<{
1358
- readonly output: Schema.Unknown;
1359
- readonly entities: Schema.$Array<Schema.Struct<{
1360
- readonly entity: Schema.String;
1361
- readonly id: Schema.String;
1362
- readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
1363
- }>>;
1364
- /** Connection changes the mutation made, applied alongside its entity patches. */
1365
- readonly connections: Schema.optional<Schema.$Array<Schema.Union<readonly [Schema.Struct<{
1366
- readonly _tag: Schema.Literal<"Insert">;
1367
- readonly connection: Schema.String;
1368
- readonly position: Schema.Union<readonly [Schema.Literal<"prepend">, Schema.Literal<"append">]>;
1369
- readonly edge: Schema.Struct<{
1370
- readonly entity: Schema.String;
1371
- readonly id: Schema.String;
1372
- readonly key: Schema.String;
1373
- }>;
1374
- }>, Schema.Struct<{
1375
- readonly _tag: Schema.Literal<"Remove">;
1376
- readonly connection: Schema.String;
1377
- readonly edge: Schema.Struct<{
1378
- readonly entity: Schema.String;
1379
- readonly id: Schema.String;
1380
- readonly key: Schema.String;
1381
- }>;
1382
- }>]>>>;
1383
- /** Entities the mutation deleted; the client knows them absent from then on. */
1384
- readonly deleted: Schema.optional<Schema.$Array<Schema.Struct<{
1385
- readonly entity: Schema.String;
1386
- readonly id: Schema.String;
1387
- }>>>;
1388
- }>, Schema.Union<readonly [typeof RemoteMutationError, typeof RemoteForbidden]>, never, never> | Rpc.Rpc<"FoldkitRemoteLive", Schema.Struct<{
1091
+ declare const RemoteRpc: RpcGroup.RpcGroup<Rpc.Rpc<"FoldkitRemoteLive", Schema.Struct<{
1389
1092
  readonly version: Schema.Number;
1390
1093
  readonly requirements: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
1391
1094
  /** Resume cursor; events at or before it are duplicates. */
@@ -1425,1076 +1128,1284 @@ declare const RemoteRpc: RpcGroup.RpcGroup<Rpc.Rpc<"FoldkitRemoteRead", Schema.S
1425
1128
  readonly _tag: Schema.Literal<"ConnectionInvalidate">;
1426
1129
  readonly cursor: Schema.Number;
1427
1130
  readonly connection: Schema.String;
1428
- }>]>, Schema.Union<readonly [typeof RemoteLiveError, typeof RemoteProtocolError]>>, Schema.Never, never, never> | Rpc.Rpc<"FoldkitRemoteQuery", Schema.Struct<{
1429
- readonly query: Schema.String;
1131
+ }>]>, Schema.Union<readonly [typeof RemoteLiveError, typeof RemoteProtocolError]>>, Schema.Never, never, never> | Rpc.Rpc<"FoldkitRemoteMutate", Schema.Struct<{
1132
+ /** Stable across transport retries so a mutation is not applied twice. */
1133
+ readonly requestId: Schema.String;
1134
+ readonly mutation: Schema.String;
1430
1135
  readonly input: Schema.Unknown;
1431
- readonly window: Schema.Struct<{
1432
- readonly first: Schema.optional<Schema.Number>;
1433
- readonly last: Schema.optional<Schema.Number>;
1434
- readonly after: Schema.optional<Schema.String>;
1435
- readonly before: Schema.optional<Schema.String>;
1436
- }>;
1437
- /**
1438
- * What to read of each item, as the relation slice a read asks the server
1439
- * for. Absent for a query run without one: the response carries only edges,
1440
- * and the client's read entry fetches fields in a second round trip.
1441
- */
1442
- readonly select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
1443
- }>, Schema.Struct<{
1444
- readonly edges: Schema.$Array<Schema.Struct<{
1445
- readonly entity: Schema.String;
1446
- readonly id: Schema.String;
1447
- readonly key: Schema.String;
1448
- }>>;
1449
- readonly start: Schema.Union<readonly [Schema.Struct<{
1450
- readonly _tag: Schema.Literal<"Terminal">;
1451
- }>, Schema.Struct<{
1452
- readonly _tag: Schema.Literal<"Cursor">;
1453
- readonly cursor: Schema.String;
1454
- }>, Schema.Struct<{
1455
- readonly _tag: Schema.Literal<"Unknown">;
1456
- }>]>;
1457
- readonly end: Schema.Union<readonly [Schema.Struct<{
1458
- readonly _tag: Schema.Literal<"Terminal">;
1459
- }>, Schema.Struct<{
1460
- readonly _tag: Schema.Literal<"Cursor">;
1461
- readonly cursor: Schema.String;
1462
- }>, Schema.Struct<{
1463
- readonly _tag: Schema.Literal<"Unknown">;
1464
- }>]>;
1465
- /**
1466
- * The selected fields of the page's items, in the same shape a read batch
1467
- * returns. Absent from a server that predates payload planning: the client
1468
- * reads it as empty and fetches fields as before.
1469
- */
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>>;
1481
- //#endregion
1482
- //#region src/model.d.ts
1483
- /**
1484
- * The normalized cache as a Foldkit Submodel. `Remote.define` returns a schema
1485
- * and an `update` for this shape; `updateRemote` reconciles every producer.
1486
- */
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. */
1499
- 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>;
1544
- /**
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.
1548
- */
1549
- readonly placed: Readonly<Record<string, PlacedOrder>>;
1550
- /** Under `verifyPlacement`, each placement the server's page disagreed with. */
1551
- readonly placementMismatches: ReadonlyArray<PlacementMismatch>;
1552
- }
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>;
1557
- }
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>;
1565
- }
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>;
1574
- }
1575
- /**
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.
1584
- */
1585
- interface Failures {
1586
- readonly connections: Readonly<Record<string, RemoteError>>;
1587
- readonly fields: Readonly<Record<string, RemoteError>>;
1588
- }
1589
- declare const noFailures: Failures;
1590
- /**
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.
1595
- */
1596
- interface RefreshState {
1597
- readonly generation: number;
1598
- readonly requested: ReadonlyMap<string, number>;
1599
- readonly started: ReadonlyMap<string, number>;
1136
+ /** For a mutation that is a `Write`: the input keys to write, when not all of them. */
1137
+ readonly keys: Schema.optional<Schema.$Array<Schema.String>>;
1138
+ }>, Schema.Struct<{
1139
+ readonly output: Schema.Unknown;
1140
+ readonly entities: Schema.$Array<Schema.Struct<{
1141
+ readonly entity: Schema.String;
1142
+ readonly id: Schema.String;
1143
+ readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
1144
+ }>>;
1145
+ /** Connection changes the mutation made, applied alongside its entity patches. */
1146
+ readonly connections: Schema.optional<Schema.$Array<Schema.Union<readonly [Schema.Struct<{
1147
+ readonly _tag: Schema.Literal<"Insert">;
1148
+ readonly connection: Schema.String;
1149
+ readonly position: Schema.Union<readonly [Schema.Literal<"prepend">, Schema.Literal<"append">]>;
1150
+ readonly edge: Schema.Struct<{
1151
+ readonly entity: Schema.String;
1152
+ readonly id: Schema.String;
1153
+ readonly key: Schema.String;
1154
+ }>;
1155
+ }>, Schema.Struct<{
1156
+ readonly _tag: Schema.Literal<"Remove">;
1157
+ readonly connection: Schema.String;
1158
+ readonly edge: Schema.Struct<{
1159
+ readonly entity: Schema.String;
1160
+ readonly id: Schema.String;
1161
+ readonly key: Schema.String;
1162
+ }>;
1163
+ }>]>>>;
1164
+ /** Entities the mutation deleted; the client knows them absent from then on. */
1165
+ readonly deleted: Schema.optional<Schema.$Array<Schema.Struct<{
1166
+ readonly entity: Schema.String;
1167
+ readonly id: Schema.String;
1168
+ }>>>;
1169
+ }>, Schema.Union<readonly [typeof RemoteMutationError, typeof RemoteForbidden]>, never, never> | Rpc.Rpc<"FoldkitRemoteQuery", Schema.Struct<{
1170
+ readonly query: Schema.String;
1171
+ readonly input: Schema.Unknown;
1172
+ readonly window: Schema.Struct<{
1173
+ readonly first: Schema.optional<Schema.Number>;
1174
+ readonly last: Schema.optional<Schema.Number>;
1175
+ readonly after: Schema.optional<Schema.String>;
1176
+ readonly before: Schema.optional<Schema.String>;
1177
+ }>;
1600
1178
  /**
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.
1179
+ * What to read of each item, as the relation slice a read asks the server
1180
+ * for. Absent for a query run without one: the response carries only edges,
1181
+ * and the client's read entry fetches fields in a second round trip.
1604
1182
  */
1605
- readonly floor: number;
1606
- }
1607
- declare const emptyRefresh: RefreshState;
1608
- /**
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.
1614
- */
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;
1183
+ readonly select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
1184
+ }>, Schema.Struct<{
1185
+ readonly edges: Schema.$Array<Schema.Struct<{
1186
+ readonly entity: Schema.String;
1187
+ readonly id: Schema.String;
1188
+ readonly key: Schema.String;
1189
+ }>>;
1190
+ readonly start: Schema.Union<readonly [Schema.Struct<{
1191
+ readonly _tag: Schema.Literal<"Terminal">;
1192
+ }>, Schema.Struct<{
1193
+ readonly _tag: Schema.Literal<"Cursor">;
1194
+ readonly cursor: Schema.String;
1195
+ }>, Schema.Struct<{
1196
+ readonly _tag: Schema.Literal<"Unknown">;
1197
+ }>]>;
1198
+ readonly end: Schema.Union<readonly [Schema.Struct<{
1199
+ readonly _tag: Schema.Literal<"Terminal">;
1200
+ }>, Schema.Struct<{
1201
+ readonly _tag: Schema.Literal<"Cursor">;
1202
+ readonly cursor: Schema.String;
1203
+ }>, Schema.Struct<{
1204
+ readonly _tag: Schema.Literal<"Unknown">;
1205
+ }>]>;
1628
1206
  /**
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.
1207
+ * The selected fields of the page's items, in the same shape a read batch
1208
+ * returns. Absent from a server that predates payload planning: the client
1209
+ * reads it as empty and fetches fields as before.
1633
1210
  */
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;
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 {
1666
1246
  /**
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.
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.
1671
1249
  */
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
- } |
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;
1700
1254
  /**
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;
1733
- /**
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.
1737
- */
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;
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>;
1266
+ //#endregion
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;
1753
1275
  } | {
1754
- readonly _tag: 'ConnectionInvalidated';
1276
+ readonly _tag: 'EntityDeleted';
1277
+ readonly ref: EdgeRef;
1278
+ readonly cursor: LiveCursor;
1279
+ } | {
1280
+ readonly _tag: 'ConnectionInsert';
1755
1281
  readonly connection: string;
1282
+ readonly position: 'prepend' | 'append';
1283
+ readonly edge: Edge;
1284
+ readonly cursor: LiveCursor;
1756
1285
  } | {
1757
- readonly _tag: 'ConnectionRefreshed';
1286
+ readonly _tag: 'ConnectionRemove';
1758
1287
  readonly connection: string;
1759
- } |
1760
- /**
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.
1764
- */
1765
- {
1766
- readonly _tag: 'QueryFailed';
1288
+ readonly edge: Edge;
1289
+ readonly cursor: LiveCursor;
1290
+ } | {
1291
+ readonly _tag: 'ConnectionInvalidate';
1767
1292
  readonly connection: string;
1768
- readonly error: RemoteError;
1769
- } |
1770
- /**
1771
- * What `Data.preload` read for a destination, as the Messages that wrote it,
1772
- * reduced in order into the Model as it is now rather than the one the
1773
- * preload started from.
1774
- */
1775
- {
1776
- readonly _tag: 'Preloaded';
1777
- readonly messages: ReadonlyArray<RemoteMessage>;
1293
+ readonly cursor: LiveCursor;
1778
1294
  };
1779
- declare const retentionRootsSchema: Schema.Struct<{
1780
- readonly requirements: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
1781
- readonly connections: Schema.$Array<Schema.Struct<{
1782
- readonly identity: Schema.String;
1783
- readonly select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
1784
- }>>;
1785
- }>;
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';
1786
1307
  /**
1787
- * The Messages' fields by tag, without `_tag`: what `defineMessageUnion` takes,
1788
- * so an application spreads them into its own union (`Remote.messages`).
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.
1789
1312
  */
1790
- declare const remoteMessageCases: {
1791
- ReadReceived: {
1792
- requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
1793
- result: Schema.Struct<{
1794
- readonly entities: Schema.$Array<Schema.Struct<{
1795
- readonly entity: Schema.String;
1796
- readonly id: Schema.String;
1797
- readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
1798
- }>>;
1799
- readonly settled: Schema.$Array<Schema.Struct<{
1800
- readonly entity: Schema.String;
1801
- readonly id: Schema.String;
1802
- readonly fields: Schema.$Array<Schema.String>;
1803
- }>>;
1804
- }>;
1805
- now: Schema.Number;
1806
- };
1807
- ReadFailed: {
1808
- requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
1809
- error: Schema.Struct<{
1810
- readonly _tag: Schema.String;
1811
- readonly message: Schema.String;
1812
- readonly refusal: Schema.optional<Schema.Unknown>;
1813
- readonly reason: Schema.optional<Schema.String>;
1814
- }>;
1815
- stream: Schema.optional<Schema.String>;
1816
- };
1817
- RefreshStarted: {
1818
- requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
1819
- };
1820
- ReadStarted: {
1821
- requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
1822
- refresh: Schema.optional<Schema.Number>;
1823
- };
1824
- QueryStarted: {
1825
- connections: Schema.$Array<Schema.String>;
1826
- };
1827
- RetentionChanged: {
1828
- roots: Schema.Struct<{
1829
- readonly requirements: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
1830
- readonly connections: Schema.$Array<Schema.Struct<{
1831
- readonly identity: Schema.String;
1832
- readonly select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
1833
- }>>;
1834
- }>;
1835
- };
1836
- Hydrated: {
1837
- connections: Schema.optional<Schema.Unknown>;
1838
- from: Schema.optional<Schema.String>;
1839
- entities: Schema.Unknown;
1840
- merge: Schema.Union<readonly [Schema.Literal<"replace">, Schema.Literal<"preserve-existing">]>;
1841
- };
1842
- MutationStarted: {
1843
- requestId: Schema.String;
1844
- optimistic: Schema.optional<Schema.$Array<Schema.Unknown>>;
1845
- };
1846
- MutationSucceeded: {
1847
- requestId: Schema.String;
1848
- entities: Schema.$Array<Schema.Struct<{
1849
- readonly entity: Schema.String;
1850
- readonly id: Schema.String;
1851
- readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
1852
- }>>;
1853
- connections: Schema.optional<Schema.$Array<Schema.Unknown>>;
1854
- deleted: Schema.optional<Schema.$Array<Schema.Struct<{
1855
- readonly entity: Schema.String;
1856
- readonly id: Schema.String;
1857
- }>>>;
1858
- now: Schema.Number;
1859
- };
1860
- MutationFailed: {
1861
- requestId: Schema.String;
1862
- error: Schema.Struct<{
1863
- readonly _tag: Schema.String;
1864
- readonly message: Schema.String;
1865
- readonly refusal: Schema.optional<Schema.Unknown>;
1866
- readonly reason: Schema.optional<Schema.String>;
1867
- }>;
1868
- };
1869
- OverlayShown: {
1870
- id: Schema.String;
1871
- optimistic: Schema.$Array<Schema.Unknown>;
1872
- };
1873
- OverlayLifted: {
1874
- id: Schema.String;
1875
- };
1876
- WindowGrown: {
1877
- window: Schema.String;
1878
- size: Schema.Number;
1879
- };
1880
- LiveReceived: {
1881
- stream: Schema.String;
1882
- event: Schema.Unknown;
1883
- policy: Schema.optional<Schema.Unknown>;
1884
- now: Schema.Number;
1885
- };
1886
- GapCleared: {
1887
- stream: Schema.String;
1888
- };
1889
- ConnectionMerged: {
1890
- connection: Schema.String;
1891
- page: Schema.Unknown;
1892
- refreshes: Schema.optional<Schema.Boolean>;
1893
- select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
1894
- entities: Schema.optional<Schema.$Array<Schema.Struct<{
1895
- readonly entity: Schema.String;
1896
- readonly id: Schema.String;
1897
- readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
1898
- }>>>;
1899
- settled: Schema.optional<Schema.$Array<Schema.Struct<{
1900
- readonly entity: Schema.String;
1901
- readonly id: Schema.String;
1902
- readonly fields: Schema.$Array<Schema.String>;
1903
- }>>>;
1904
- now: Schema.optional<Schema.Number>;
1905
- };
1906
- ConnectionInvalidated: {
1907
- connection: Schema.String;
1908
- };
1909
- ConnectionRefreshed: {
1910
- connection: Schema.String;
1911
- };
1912
- QueryFailed: {
1913
- connection: Schema.String;
1914
- error: Schema.Struct<{
1915
- readonly _tag: Schema.String;
1916
- readonly message: Schema.String;
1917
- readonly refusal: Schema.optional<Schema.Unknown>;
1918
- readonly reason: Schema.optional<Schema.String>;
1919
- }>;
1920
- };
1921
- Preloaded: {
1922
- messages: Schema.$Array<Schema.suspend<Schema.Codec<RemoteMessage, unknown, never, never>>>;
1923
- };
1924
- };
1925
- type RemoteMessageTag = RemoteMessage['_tag'];
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;
1324
+ readonly optimistic: OptimisticState;
1325
+ readonly outcome: LiveOutcome;
1326
+ /**
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.
1331
+ */
1332
+ readonly invalidated?: string | undefined;
1333
+ }
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
+ }>;
1926
1352
  /**
1927
- * A Remote Message as an application's union constructs it from
1928
- * `remoteMessageCases`: the same shape `RemoteMessage` names, with the runtime
1929
- * slots (`entities`, `event`, `page`) typed `unknown` by their schemas.
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.
1930
1355
  */
1931
- type RemoteMessageInput = { [Tag in RemoteMessageTag]: {
1932
- readonly _tag: Tag;
1933
- } & Schema.Struct.Type<(typeof remoteMessageCases)[Tag]>; }[RemoteMessageTag];
1356
+ declare class RemoteClient extends RemoteClient_base {}
1934
1357
  /**
1935
- * Whether a Message is one of Remote's, by tag. Narrows an application's union
1936
- * to its Remote cases, and its complement to the application's own.
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.
1937
1366
  */
1938
- declare const isRemoteMessage: <M extends {
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>;
1372
+ }
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: {
1939
1378
  readonly _tag: string;
1940
- }>(message: M) => message is Extract<M, {
1941
- readonly _tag: RemoteMessageTag;
1942
- }>;
1943
- declare const remoteMessageSchema: Schema.Codec<RemoteMessage, unknown>;
1944
- /** The ids `OverlayShown` shows now, each once, in the order they are drawn. */
1945
- declare const overlaysOf: (model: RemoteModel) => ReadonlyArray<string>;
1946
- /** The key a grown window is kept under: its connection and the window first asked for. */
1947
- declare const windowGrowthKey: (identity: string, window: string) => 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>;
1948
1384
  /**
1949
- * Whether only overlays show this entity: the server has told the store
1950
- * nothing of it and no request's layer writes it, so nothing will fetch what an
1951
- * overlay leaves out.
1385
+ * `Remote.mutate` as a standalone effect, so `Remote.mutateInto` can reuse it
1386
+ * without the object literal referencing itself.
1952
1387
  */
1953
- declare const onlyOverlaid: (model: RemoteModel, entity: string, id: string) => boolean;
1954
- /** Whether a query for this connection is in flight. */
1955
- declare const isQueryLoading: (model: RemoteModel, identity: string) => boolean;
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;
1408
+ }
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;
1424
+ }
1956
1425
  /**
1957
- * The generation a read is planned under: the highest any of the fields it
1958
- * reads or connections it runs was refreshed at. A read entry carries this as a
1959
- * dependency, so it restarts when what it observes is refreshed and not when
1960
- * anything else is.
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.
1961
1433
  */
1962
- declare const refreshedAt: (refresh: RefreshState, requests: ReadonlyArray<Requirement>, connections?: ReadonlyArray<string>) => number;
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;
1963
1446
  /**
1964
- * Marks every field of `requests` and every connection in `connections`
1965
- * refreshed at the next generation.
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.
1966
1449
  */
1967
- declare const withRefreshRequested: (refresh: RefreshState, requests: ReadonlyArray<Requirement>, connections?: ReadonlyArray<string>) => RefreshState;
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;
1968
1454
  /**
1969
- * Marks connections as needing to be asked again, and restarts a read of them
1970
- * already in flight: a page requested before what invalidated it could land
1971
- * after it, saying what is no longer true. `Remote.refresh` marks the same way.
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.
1972
1458
  */
1973
- declare const invalidateConnections: (model: RemoteModel, connections: ReadonlyArray<string>) => RemoteModel;
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;
1467
+ }
1974
1468
  /**
1975
- * Whether one field's read already began under the generation that field was
1976
- * last refreshed at. Such a read is in flight and would otherwise outlive the
1977
- * refresh, so the refresh takes a new generation to restart it even though the
1978
- * field is already stale.
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`).
1979
1472
  */
1980
- declare const refreshIsInFlight: (refresh: RefreshState, request: Requirement, field: string) => boolean;
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: {
1505
+ /**
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.
1508
+ */
1509
+ from: <Name extends string, S extends Schema.Constraint>(selection: Domain.Selection<Name, unknown, S>) => Selection<S['Type'], Name, 'entity'>;
1510
+ /**
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.
1514
+ */
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'>;
1516
+ /**
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.
1519
+ */
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
+ }
1981
1529
  /**
1982
- * Whether a read is fetching any of `fields` for this entity. Consulted only
1983
- * when the store lacks the value, which is what separates `Loading` from
1984
- * `Initial`.
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.
1985
1534
  */
1986
- declare const isLoading: (model: RemoteModel, entity: string, id: string, fields: ReadonlyArray<string>) => boolean;
1535
+ declare const assemble: (store: EntityStore, key: string, requirement: RelationRequirement) => Assembled | undefined;
1987
1536
  /**
1988
- * The pure reducer all four producers share. A live event that arrives ahead of
1989
- * its cursor is a gap: it is not applied, and the stream is recorded so its
1990
- * live entry restarts it rather than silently missing facts. When every field a Message
1991
- * touches keeps its identity, `model` itself is returned, so the application's
1992
- * root keeps its identity and Foldkit does not render. The common no-ops do (a
1993
- * duplicate live event, a repeated `ReadStarted`); a repeated failure, or a
1994
- * `preserve-existing` restore of entities already held, still makes an equal
1995
- * copy.
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.
1996
1540
  */
1997
- declare const updateRemote: (model: RemoteModel, message: RemoteMessage) => RemoteModel;
1998
- /** Whether this field's last read failed and nothing has settled it since. */
1999
- declare const isFieldFailed: (model: RemoteModel, entity: string, id: string, field: string) => boolean;
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;
2000
1546
  /**
2001
- * Whether a read is fetching any field `relation` reads of an entity, its own
2002
- * or, through each relation the store holds, its targets'. A value whose owner
2003
- * is being fetched is loading, not `Initial`: nothing is missing a fetch.
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.
2004
1549
  */
2005
- declare const isLoadingThrough: (model: RemoteModel, entity: string, id: string, relation: RelationRequirement) => boolean;
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
+ }
2006
1565
  /**
2007
- * The first failure among the fields `relation` reads of an entity, following
2008
- * each relation the store holds into its targets, as `assemble` does. A read
2009
- * that consults it shows `Failed` for a related entity's failure too, rather
2010
- * than waiting on a field nothing will fetch.
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.
2011
1570
  */
2012
- declare const failureOf: (model: RemoteModel, entity: string, id: string, relation: RelationRequirement) => RemoteError | undefined;
2013
1571
  /**
2014
- * Writes a read result into the store, recording each field's applied window so
2015
- * a later request with a different window refetches. A relation page requested
2016
- * with a cursor is merged onto the page already stored, so "load more"
2017
- * accumulates rather than replaces. Every read path should use this rather than
2018
- * reducing `writeEntity` by hand.
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.
2019
1575
  */
2020
- declare const writeRead: (store: EntityStore, requests: ReadonlyArray<Requirement>, result: Schema.Schema.Type<typeof ReadBatchResult>, now?: number) => EntityStore;
2021
- //#endregion
2022
- //#region src/resume.d.ts
1576
+ type RefKey<Name extends string> = `${Name}:${string}`;
2023
1577
  /**
2024
- * A resume part, in the shape `foldkit-ssr`'s `SSR.plan` takes in `parts`.
2025
- * Declared here structurally, so neither package depends on the other.
1578
+ * A patch in wire shape: the values the store holds, so a relation is its ref
1579
+ * key (`Entity.refKey`), not an `EntityRef`.
2026
1580
  */
2027
- interface RemoteResumePart<AppModel> {
1581
+ interface EntityPatch<Name extends string, F extends Schema.Struct.Fields> {
1582
+ readonly entity: Name;
2028
1583
  readonly id: string;
2029
- /** The metadata key names whose reads this part resumes. */
2030
- readonly covers: ReadonlyArray<string>;
2031
- readonly capture: (model: AppModel, projections: ReadonlyArray<{
2032
- readonly metadata: Metadata;
2033
- }>) => unknown;
2034
- readonly restore: (model: AppModel, value: unknown) => Result.Result<AppModel, string>;
2035
- /** Whether a Subscription entry is one of this domain's, which may start late. */
2036
- readonly deferrable: (key: string, entry: unknown) => boolean;
2037
- }
2038
- //#endregion
2039
- //#region src/coalesce.d.ts
2040
- type Batch = Schema.Schema.Type<typeof ReadBatch>;
2041
- type BatchResult = Schema.Schema.Type<typeof ReadBatchResult>;
2042
- type ReadError = RemoteReadError | RemoteProtocolError;
2043
- type BatchRead = (batch: Batch) => Effect.Effect<BatchResult, ReadError>;
2044
- type QueryRequestValue = Schema.Schema.Type<typeof QueryRequest>;
2045
- type QueryResultValue = Schema.Schema.Type<typeof QueryResult>;
2046
- type QueryRun = (request: QueryRequestValue) => Effect.Effect<QueryResultValue, RemoteQueryError>;
2047
- interface CoalesceOptions {
2048
- /**
2049
- * How long a batch waits to collect more requirements before it runs.
2050
- * Requirements issued concurrently coalesce even at the default of no wait.
2051
- */
2052
- readonly window?: Duration.Input | undefined;
1584
+ readonly values: Partial<Schema.Struct.Encoded<F>>;
2053
1585
  }
2054
- /** A stable key for a requirement, so an equal requirement in flight is joined. */
2055
- declare const requirementKey: (requirement: Requirement) => string;
2056
1586
  /**
2057
- * Wraps a raw query so that an identical query in flight (same query, input,
2058
- * and window) is joined rather than run again; distinct queries run
2059
- * concurrently. A page answers exactly one window, so nothing is batched.
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.
2060
1590
  */
2061
- declare const coalesceQueries: (query: QueryRun, options?: CoalesceOptions) => Effect.Effect<QueryRun>;
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;
2062
1598
  /**
2063
- * Wraps a raw batch read so that requirements are batched and deduplicated.
2064
- * Every waiter receives the whole batch result; `Remote.writeRead` is
2065
- * idempotent, so writing it more than once is harmless.
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.
2066
1602
  */
2067
- declare const coalesceReads: (read: BatchRead, options?: CoalesceOptions) => Effect.Effect<BatchRead>;
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
+ };
2068
1644
  //#endregion
2069
- //#region src/client.d.ts
2070
- declare const RemoteClient_base: Context.ServiceClass<RemoteClient, "foldkit-remote/RemoteClient", {
2071
- readonly read: (batch: Schema.Schema.Type<typeof ReadBatch>) => Effect.Effect<Schema.Schema.Type<typeof ReadBatchResult>, RemoteReadError | RemoteProtocolError>;
2072
- readonly query: (request: Schema.Schema.Type<typeof QueryRequest>) => Effect.Effect<Schema.Schema.Type<typeof QueryResult>, RemoteQueryError>;
2073
- readonly mutate: (request: Schema.Schema.Type<typeof MutationRequest>) => Effect.Effect<Schema.Schema.Type<typeof MutationResult>, RemoteMutationError | RemoteForbidden>;
2074
- readonly live: (request: {
2075
- readonly requirements: ReadonlyArray<Requirement>;
2076
- readonly after: LiveCursor;
2077
- }) => Stream.Stream<LiveEvent, RemoteLiveError | RemoteProtocolError>;
2078
- }>;
1645
+ //#region src/matching.d.ts
2079
1646
  /**
2080
- * The transport boundary. `foldkit-remote` never talks to a transport directly;
2081
- * it depends on this Effect service, which a later phase wires to Effect RPC.
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.
2082
1659
  */
2083
- declare class RemoteClient extends RemoteClient_base {}
1660
+ interface Matched<A> {
1661
+ readonly items: ReadonlyArray<A>;
1662
+ /** Whether every row the answer is about was judged. */
1663
+ readonly complete: boolean;
1664
+ }
2084
1665
  /**
2085
- * The methods an Effect RPC client for `RemoteRpc` exposes. `R` is the
2086
- * environment a handler needs; it defaults to `never`, which is what a real
2087
- * transport client satisfies. `RemoteServer.handlers` returns this type with its
2088
- * own `R`, so the two sides cannot drift apart.
1666
+ * What the rows the client holds had to say about a body.
2089
1667
  *
2090
- * `TransportError` is what the transport itself may fail with on top of the
2091
- * declared errors: `RpcClientError` for the client `RpcClient.make` builds,
2092
- * `never` for in-process handlers.
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.
2093
1672
  */
2094
- interface RemoteRpcClient<R = never, TransportError = never> {
2095
- readonly FoldkitRemoteRead: (payload: Schema.Schema.Type<typeof ReadBatch>) => Effect.Effect<Schema.Schema.Type<typeof ReadBatchResult>, RemoteReadError | RemoteProtocolError | TransportError, R>;
2096
- readonly FoldkitRemoteQuery: (payload: Schema.Schema.Type<typeof QueryRequest>) => Effect.Effect<Schema.Schema.Type<typeof QueryResult>, RemoteQueryError | TransportError, R>;
2097
- readonly FoldkitRemoteMutate: (payload: Schema.Schema.Type<typeof MutationRequest>) => Effect.Effect<Schema.Schema.Type<typeof MutationResult>, RemoteMutationError | RemoteForbidden | TransportError, R>;
2098
- readonly FoldkitRemoteLive: (payload: Schema.Schema.Type<typeof LiveRequirement>) => Stream.Stream<Schema.Schema.Type<typeof LiveChange>, RemoteLiveError | RemoteProtocolError | TransportError, R>;
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;
2099
1686
  }
2100
- /** Reconstructs the client's `ConnectionChange` from the wire's flattened edge. */
2101
- declare const connectionChangeOf: (change: Schema.Schema.Type<typeof ConnectionChangeSchema>) => ConnectionChange;
2102
- /** Reconstructs the client's `LiveEvent` from the wire's flattened `LiveChange`. */
2103
- declare const liveEventOf: (change: Schema.Schema.Type<typeof LiveChange>) => LiveEvent;
2104
- declare const remoteError: (error: {
2105
- readonly _tag: string;
2106
- readonly message: string;
2107
- readonly refusal?: unknown;
2108
- readonly reason?: string | undefined;
2109
- }) => RemoteError;
2110
- declare const coalescedLayer: <E, R>(layer: Layer.Layer<RemoteClient, E, R>, options?: CoalesceOptions) => Layer.Layer<RemoteClient, E, R>;
2111
1687
  /**
2112
- * `Remote.mutate` as a standalone effect, so `Remote.mutateInto` can reuse it
2113
- * without the object literal referencing itself.
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.
2114
1702
  */
2115
- declare const mutateRemote: <Name extends string, Input, Output>(mutation: MutationDescriptor<Name, Input, Output, unknown>, input: Input, requestId: string, keys?: readonly string[] | undefined) => Effect.Effect<{
2116
- output: Output;
2117
- entities: readonly {
2118
- readonly entity: string;
2119
- readonly id: string;
2120
- readonly values: {
2121
- readonly [x: string]: unknown;
2122
- };
2123
- }[];
2124
- connections: ConnectionChange[];
2125
- deleted: readonly {
2126
- readonly entity: string;
2127
- readonly id: string;
2128
- }[];
2129
- }, RemoteMutationError | RemoteForbidden, RemoteClient>;
1703
+ declare const matching: <Name extends string, Input>(store: EntityStore, descriptor: QueryDescriptor<Name, Input, unknown>, input: Input, options?: MatchingOptions) => Judged;
1704
+ /**
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.
1718
+ */
1719
+ type Belongs = 'yes' | 'no' | 'unknown';
1720
+ /**
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.
1728
+ */
1729
+ declare const belongsEncoded: <Name extends string, Input>(store: EntityStore, descriptor: QueryDescriptor<Name, Input, unknown>, encoded: Readonly<Record<string, unknown>>, key: EntityKey) => Belongs;
2130
1730
  //#endregion
2131
- //#region src/json.d.ts
2132
- /** A request: which of Remote's calls, and its payload as the RPC protocol encodes it. */
2133
- declare const RemoteJsonRequest: Schema.Struct<{
2134
- readonly operation: Schema.Literals<readonly ["read", "query", "mutate"]>;
2135
- readonly payload: Schema.Unknown;
2136
- }>;
2137
- type RemoteJsonRequest = typeof RemoteJsonRequest.Type;
2138
- /** An answer: the call's result, or why there is none. */
2139
- declare const RemoteJsonAnswer: Schema.Union<readonly [Schema.Struct<{
2140
- readonly result: Schema.Unknown;
2141
- }>, Schema.Struct<{
2142
- readonly error: Schema.String;
2143
- readonly refusal: Schema.optional<Schema.Unknown>;
2144
- /** Who is asking was refused, with the application's reason when it gave one. */
2145
- readonly forbidden: Schema.optional<Schema.Struct<{
2146
- readonly reason: Schema.optional<Schema.String>;
2147
- }>>;
2148
- }>]>;
2149
- type RemoteJsonAnswer = typeof RemoteJsonAnswer.Type;
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
+ }
2150
1747
  /**
2151
- * Sends one request's text and resolves with its answer as parsed JSON. It
2152
- * rejects when nothing came back, and the call fails with that message.
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.
2153
1750
  */
2154
- type RemoteJsonSend = (request: string) => Promise<unknown>;
2155
- //#endregion
2156
- //#region src/sse.d.ts
2157
- /** What `httpWithLive` needs besides the URL. Mirrors `http`, plus the fetch itself. */
2158
- interface LiveFetchOptions {
2159
- /** Read per request, so a token that changes reaches the next call. */
2160
- readonly headers?: (() => Readonly<Record<string, string>>) | undefined;
2161
- /** Defaults to the global one; pass it to route calls elsewhere in tests. */
2162
- readonly fetch?: typeof fetch | undefined;
2163
- }
2164
- /** Remote's live stream over fetch: `serveFetch`'s live open as a `Stream`. */
2165
- declare const liveFetch: (url: string, options?: LiveFetchOptions) => RemoteRpcClient["FoldkitRemoteLive"];
1751
+ declare const reachable: (store: EntityStore, roots: RetentionRoots, connections: Readonly<Record<string, Connection>>, optimistic: OptimisticState, pending: ReadonlySet<string>) => ReadonlySet<EntityKey>;
2166
1752
  /**
2167
- * Remote's client over HTTP with live: reads, queries, and mutations as
2168
- * `http` sends them, live as `liveFetch` streams it, for `clientLayer`.
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.
2169
1756
  */
2170
- declare const httpWithLive: (url: string, options?: LiveFetchOptions) => RemoteRpcClient;
1757
+ declare const gc: (state: Retained & {
1758
+ readonly mutations: MutationState;
1759
+ }, roots: RetentionRoots) => Retained;
2171
1760
  //#endregion
2172
- //#region src/relation.d.ts
2173
- interface RefParts {
2174
- readonly entity: string;
2175
- readonly id: string;
2176
- }
2177
- /** A page of refs as the wire and the store hold it. */
2178
- interface RefPageValue {
2179
- readonly refs: ReadonlyArray<string>;
2180
- readonly hasNext: boolean;
2181
- readonly hasPrevious: boolean;
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;
1764
+ /**
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.
1775
+ */
1776
+ interface Snapshot {
1777
+ readonly entities: EntityStore;
1778
+ /**
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.
1787
+ */
1788
+ readonly connections: Readonly<Record<string, ReadonlyArray<ReadonlyArray<Edge>>>>;
2182
1789
  }
2183
- /** Marks the codec `Entity.ref`/`Entity.refPage` produce, so a Selection can tell the field's shape. */
2184
- declare const RelationAnnotation = "foldkitRemoteRelation";
2185
- /** The target entity's name on the same codec, so a nested selection of another entity is refused. */
2186
- declare const RelationEntityAnnotation = "foldkitRemoteRelationEntity";
2187
- type RelationKind = 'one' | 'many' | 'page';
2188
- interface RelationShape {
2189
- readonly kind: RelationKind;
2190
- readonly nullable: boolean;
2191
- readonly entity: string;
1790
+ /**
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.
1796
+ */
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;
2192
1812
  }
1813
+ /** How a snapshot meets a store that already has entries. */
1814
+ type MergePolicy = 'replace' | 'preserve-existing';
2193
1815
  /**
2194
- * A page of a relation that is a whole list is read under a name of its own, the
2195
- * field's name and the page's size: `comments@first=10`. It is a field like any
2196
- * other to the store, the planner, and the wire, so the whole list and a page of
2197
- * it are held side by side, merged, marked stale, and persisted each on its own.
2198
- * The server reads the name apart, reads the relation with the window, and
2199
- * answers under the alias. A cursor is not part of the name: a page read from a
2200
- * cursor merges onto the page it continues.
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.
2201
1820
  */
2202
- declare const RELATION_ALIAS = "@";
2203
- /** The alias a relation field is read under, for a window of this size. */
2204
- declare const relationAlias: (field: string, window: {
2205
- readonly first?: number | undefined;
2206
- readonly last?: number | undefined;
2207
- readonly after?: string | undefined;
2208
- readonly before?: string | undefined;
2209
- }) => string;
2210
- /** The field an alias reads; a name that is no alias is its own field. */
2211
- declare const aliasedField: (name: string) => string;
2212
- /** Splits a ref key (`"Entity:id"`, the store key too) back into its parts. */
2213
- declare const refParts: (encoded: string) => RefParts;
1821
+ declare function dehydrate(snapshot: Snapshot, options?: SnapshotOptions & {
1822
+ readonly maxBytes?: undefined;
1823
+ }): string;
1824
+ declare function dehydrate(snapshot: Snapshot, options?: SnapshotOptions): string | undefined;
2214
1825
  /**
2215
- * The refs a relation value carries, in order. Anything that is not a ref key,
2216
- * an array of them, or a page of them contributes nothing.
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.
2217
1829
  */
2218
- declare const refsIn: (value: unknown) => ReadonlyArray<RefParts>;
2219
- /** The refs in a relation value that name the relation's target entity, and no other. */
2220
- declare const targetsOf: (value: unknown, relation: RelationRequirement) => ReadonlyArray<RefParts>;
2221
- declare const isRefPage: (value: unknown) => value is RefPageValue;
1830
+ declare const hydrate: (raw: string | undefined | null, options?: SnapshotOptions) => Snapshot | undefined;
2222
1831
  /**
2223
- * The relation shape an entity field schema declares: a ref (`one`), a nullable
2224
- * ref, an array of refs (`many`), or a page of refs (`page`). `undefined` for a
2225
- * scalar field, which cannot take a nested selection.
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.
2226
1836
  */
2227
- declare const relationShape: (schema: Schema.Top) => RelationShape | undefined;
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
+ };
2228
1869
  //#endregion
2229
- //#region src/selection.d.ts
2230
- /** One page of a paginated relation with each target assembled through a nested selection. */
2231
- interface Page<Item> {
2232
- readonly items: ReadonlyArray<Item>;
2233
- readonly hasNext: boolean;
2234
- readonly hasPrevious: boolean;
2235
- }
1870
+ //#region src/model.d.ts
2236
1871
  /**
2237
- * The fields a projection reads of one entity, plus the slice it reads of each
2238
- * relation's target. `Shape` tells a parent selection whether this one is a
2239
- * paginated relation (`connection`) or a plain entity slice (`entity`).
1872
+ * The normalized cache as a Foldkit Submodel. `Remote.define` returns a schema
1873
+ * and an `update` for this shape; `updateRemote` reconciles every producer.
2240
1874
  */
2241
- interface Selection<Value, Name extends string = string, Shape extends 'entity' | 'connection' = 'entity' | 'connection'> {
2242
- readonly entity: Name;
2243
- readonly fields: readonly string[];
2244
- /** A pure codec: entity fields carry no decoding or encoding services. */
2245
- readonly schema: Schema.Codec<Value, unknown, never, never>;
2246
- /** Pagination windows for nested relation fields, keyed by field name. */
2247
- readonly connections?: Readonly<Record<string, QueryWindow>> | undefined;
2248
- /** The slice required of each nested relation's target, keyed by field name. */
2249
- readonly relations?: Readonly<Record<string, RelationRequirement>> | undefined;
2250
- /** Present when this selection is itself a paginated relation. */
2251
- readonly window?: QueryWindow | undefined;
2252
- /** Phantom: see `Shape`. */
2253
- readonly shape?: Shape | undefined;
2254
- }
2255
- /** Flattens a mapped type so hovers show the picked fields, not the machinery. */
2256
- type Simplify<T> = T extends (infer O) ? { readonly [K in keyof O]: O[K]; } : never;
2257
- /** The value a Selection reads: `Selection.Value<typeof ProjectCard>`. */
2258
- type SelectionValueOf<S> = S extends Selection<infer V, any, any> ? V : never;
2259
- /** The nested selections a relation field admits: of its target entity, in the shapes its value takes. */
2260
- 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;
2261
- /** What a selection of an entity with fields `F` may pick: `true` per scalar, a nested selection per relation. */
2262
- type SelectionOf<F extends Schema.Struct.Fields> = { readonly [K in keyof F]?: true | NestedFor<Schema.Schema.Type<F[K]>>; };
2263
- /** `T | null` when the field admits `null` or `undefined` (both assemble to `null`). */
2264
- type Nullable<Field, T> = [Extract<Field, null | undefined>] extends [never] ? T : T | null;
2265
- /** A nested selection's value takes the shape of the field it selects through. */
2266
- 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;
2267
- /** The value a selection `Sel` of fields `F` reads. */
2268
- 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]>; }>;
2269
- declare const pageSchema: (item: AnySchema) => AnySchema;
2270
- /** The requirement a nested selection contributes for its relation's target. */
2271
- declare const relationOf: (selection: Selection<unknown>) => RelationRequirement;
2272
- declare const Selection: {
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;
2273
1926
  /**
2274
- * The Remote Selection of a `foldkit-entity` Selection: the same members, read
2275
- * from Remote's store. `true` on a relation reads its refs, as it does here.
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.
2276
1930
  */
2277
- from: <Name extends string, S extends Schema.Constraint>(selection: Domain.Selection<Name, unknown, S>) => Selection<S["Type"], Name, "entity">;
1931
+ readonly restoredFrom: Option.Option<string>;
2278
1932
  /**
2279
- * The fields to read of `entity`. A nested `Selection` on a relation field
2280
- * reads through the ref (or refs, or page of refs) the field holds into the
2281
- * target's fields; a scalar field cannot take one.
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.
2282
1936
  */
2283
- 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">;
1937
+ readonly placed: Readonly<Record<string, PlacedOrder>>;
1938
+ /** Under `verifyPlacement`, each placement the server's page disagreed with. */
1939
+ readonly placementMismatches: ReadonlyArray<PlacementMismatch>;
1940
+ }
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>;
1945
+ }
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>;
1953
+ }
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>;
1962
+ }
1963
+ /**
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.
1972
+ */
1973
+ interface Failures {
1974
+ readonly connections: Readonly<Record<string, RemoteError>>;
1975
+ readonly fields: Readonly<Record<string, RemoteError>>;
1976
+ }
1977
+ declare const noFailures: Failures;
1978
+ /**
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.
1983
+ */
1984
+ interface RefreshState {
1985
+ readonly generation: number;
1986
+ readonly requested: ReadonlyMap<string, number>;
1987
+ readonly started: ReadonlyMap<string, number>;
2284
1988
  /**
2285
- * A paginated relation: one page of refs to `entity` with a window, or, with
2286
- * a nested selection, one page of targets assembled through it.
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.
2287
1992
  */
2288
- connection: {
2289
- <Name extends string, F extends Schema.Struct.Fields>(entity: EntityDescriptor<Name, F>, window: QueryWindow): Selection<RefPage<Name, F>, Name, "connection">;
2290
- <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">;
2291
- };
2292
- };
2293
- interface Assembled {
2294
- readonly values: unknown;
2295
- readonly refreshing: boolean;
1993
+ readonly floor: number;
2296
1994
  }
1995
+ declare const emptyRefresh: RefreshState;
2297
1996
  /**
2298
- * Reads an entity's selected fields out of the store, following each nested
2299
- * relation into its targets. `undefined` means some field, at any depth, is
2300
- * not present yet. A tombstoned target reads as `null` (or is dropped from a
2301
- * list), so the Selection's codec decides whether that is a failure.
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.
2302
2002
  */
2303
- declare const assemble: (store: EntityStore, key: string, requirement: RelationRequirement) => Assembled | undefined;
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;
2016
+ /**
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.
2021
+ */
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
+ } |
2304
2036
  /**
2305
- * The first field `requirement` reads, at any depth, that the server settled
2306
- * without a value, as `Entity:id.field`. A read that consults it says why it
2307
- * cannot assemble rather than waiting on a field nothing will fetch.
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".
2308
2040
  */
2309
- declare const unavailableOf: (store: EntityStore, key: string, requirement: RelationRequirement) => string | undefined;
2310
- //#endregion
2311
- //#region src/entity.d.ts
2312
- type AnySchema = Schema.Schema<unknown>;
2313
- declare const entityRefFields: unique symbol;
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;
2054
+ /**
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.
2059
+ */
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
+ } |
2314
2088
  /**
2315
- * A normalized reference to an entity. `F` is a phantom carrying the entity's
2316
- * fields so `Entity.patch` can type its patch; it is absent at runtime.
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.
2317
2092
  */
2318
- interface EntityRef<Name extends string, F extends Schema.Struct.Fields = Schema.Struct.Fields> {
2319
- readonly entity: Name;
2093
+ {
2094
+ readonly _tag: 'OverlayShown';
2320
2095
  readonly id: string;
2321
- readonly [entityRefFields]?: F;
2322
- }
2323
- interface EntityDescriptor<Name extends string, F extends Schema.Struct.Fields> {
2324
- readonly name: Name;
2325
- readonly schema: Schema.Struct<F>;
2326
- readonly fields: F;
2327
- ref(id: Schema.Schema.Type<F['id']>): EntityRef<Name, F>;
2328
- /** The fields a Surface reads of this entity; `Selection.make(entity, …)` with the entity as receiver. */
2329
- select<const Sel extends SelectionOf<F>>(selection: Sel): Selection<SelectionValue<F, Sel>, Name, 'entity'>;
2330
- /** A patch of this entity's wire-shaped values; `Entity.patch(entity.ref(id), values)`. */
2331
- patch(id: Schema.Schema.Type<F['id']>, values: Partial<Schema.Struct.Encoded<F>>): EntityPatch<Name, F>;
2332
- }
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;
2121
+ /**
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.
2125
+ */
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
+ } |
2148
+ /**
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.
2152
+ */
2153
+ {
2154
+ readonly _tag: 'QueryFailed';
2155
+ readonly connection: string;
2156
+ readonly error: RemoteError;
2157
+ } |
2333
2158
  /**
2334
- * Relations are **references**, never inline target schemas: a ref cannot
2335
- * reconstruct a full entity, and dereferencing is a store concern. Because the
2336
- * target schema is not inlined, recursive relations cannot arise through the
2337
- * schema graph.
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.
2338
2162
  */
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
+ }>;
2339
2174
  /**
2340
- * A ref as the wire carries it: the target's name, a colon, and its id. Typed
2341
- * with the name, so a relation to `User` takes `'User:u1'` and not a ref to
2342
- * some other entity, which would read as a row that does not exist.
2175
+ * The Messages' fields by tag, without `_tag`: what `defineMessageUnion` takes,
2176
+ * so an application spreads them into its own union (`Remote.messages`).
2343
2177
  */
2344
- type RefKey<Name extends string> = `${Name}:${string}`;
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'];
2345
2314
  /**
2346
- * A patch in wire shape: the values the store holds, so a relation is its ref
2347
- * key (`Entity.refKey`), not an `EntityRef`.
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.
2348
2318
  */
2349
- interface EntityPatch<Name extends string, F extends Schema.Struct.Fields> {
2350
- readonly entity: Name;
2351
- readonly id: string;
2352
- readonly values: Partial<Schema.Struct.Encoded<F>>;
2353
- }
2319
+ type RemoteMessageInput = { [Tag in RemoteMessageTag]: {
2320
+ readonly _tag: Tag;
2321
+ } & Schema.Struct.Type<(typeof remoteMessageCases)[Tag]>; }[RemoteMessageTag];
2354
2322
  /**
2355
- * One authoritative page of a paginated relation: refs (never inline entities)
2356
- * plus whether more exist. The adapter does not hold segmentation state; the
2357
- * client merges pages.
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.
2358
2325
  */
2359
- interface RefPage<Name extends string, F extends Schema.Struct.Fields = Schema.Struct.Fields> {
2360
- readonly refs: ReadonlyArray<EntityRef<Name, F>>;
2361
- readonly hasNext: boolean;
2362
- readonly hasPrevious: boolean;
2363
- }
2364
- /** The ref codec a `foldkit-entity` relation becomes: one ref, a nullable ref, or an array of refs. */
2365
- 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;
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;
2366
2336
  /**
2367
- * The fields Remote stores for a `foldkit-entity` Entity: its own fields, its
2368
- * derived members (the server supplies them like any field), and each relation
2369
- * as refs.
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.
2370
2340
  */
2371
- 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;
2372
- declare const Entity$2: {
2373
- /**
2374
- * The Remote descriptor of a `foldkit-entity` Entity. Relations declared with
2375
- * `Entity.relate` become ref fields, so the store, the planner, and the server
2376
- * treat it as they treat an `Entity.make` descriptor.
2377
- */
2378
- from: <E extends Domain.AnyEntity>(entity: E & {
2379
- readonly fields: {
2380
- readonly id: unknown;
2381
- };
2382
- }) => EntityDescriptor<E["name"], FieldsFrom<E>>;
2383
- make: <const Name extends string, const F extends Schema.Struct.Fields & {
2384
- readonly id: Schema.Schema<unknown>;
2385
- }>(name: Name, schema: Schema.Struct<F>) => EntityDescriptor<Name, F>;
2386
- /** A relation to a known entity, decoded as a reference. */
2387
- ref: <Name extends string, F extends Schema.Struct.Fields>(entity: EntityDescriptor<Name, F>) => Schema.Codec<EntityRef<Name, F>, RefKey<Name>>;
2388
- /** A relation by name, for recursive or forward references. */
2389
- refTo: <Name extends string>(name: Name) => Schema.Codec<EntityRef<Name>, RefKey<Name>>;
2390
- /**
2391
- * The wire key a relation field carries (`"Entity:id"`). Adapters that read a
2392
- * foreign key emit this so the ref codec can decode it on the client.
2393
- */
2394
- refKey: (ref: {
2395
- readonly entity: string;
2396
- readonly id: string;
2397
- }) => string;
2398
- /** Splits a ref key back into its entity and id. */
2399
- refParts: (encoded: string) => RefParts;
2400
- /** A relation value of one authoritative page of refs. */
2401
- refPage: <Name extends string, F extends Schema.Struct.Fields>(entity: EntityDescriptor<Name, F>) => Schema.Codec<RefPage<Name, F>, {
2402
- readonly refs: ReadonlyArray<string>;
2403
- readonly hasNext: boolean;
2404
- readonly hasPrevious: boolean;
2405
- }>;
2406
- /**
2407
- * A normalized patch for an entity, typed against its fields' wire shape:
2408
- * write a relation as its ref key (`Entity.refKey`), as the server does.
2409
- */
2410
- patch: <Name extends string, F extends Schema.Struct.Fields>(ref: EntityRef<Name, F>, patch: Partial<Schema.Struct.Encoded<F>>) => EntityPatch<Name, F>;
2411
- };
2412
- //#endregion
2413
- //#region src/matching.d.ts
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;
2344
+ /**
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.
2349
+ */
2350
+ declare const refreshedAt: (refresh: RefreshState, requests: ReadonlyArray<Requirement>, connections?: ReadonlyArray<string>) => number;
2414
2351
  /**
2415
- * An answer over the rows the client holds — never over the rows that exist.
2416
- *
2417
- * `complete` is the whole reason this is its own type rather than a `Page`. A
2418
- * `Page` carries `hasNext`/`hasPrevious`, which are facts the *server* stated
2419
- * about rows beyond the ones it delivered; a local answer has no such facts and
2420
- * cannot invent them. What it can say is whether the population it judged was
2421
- * all of it, which is decidable: a connection terminal at both ends is wholly
2422
- * held, and nothing was skipped for a missing field.
2423
- *
2424
- * An incomplete answer is not wrong — it is an answer about less than the
2425
- * caller may have meant, and the flag is what lets a view say "3 so far" rather
2426
- * than "3", or a caller decide to ask the server.
2352
+ * Marks every field of `requests` and every connection in `connections`
2353
+ * refreshed at the next generation.
2427
2354
  */
2428
- interface Matched<A> {
2429
- readonly items: ReadonlyArray<A>;
2430
- /** Whether every row the answer is about was judged. */
2431
- readonly complete: boolean;
2432
- }
2355
+ declare const withRefreshRequested: (refresh: RefreshState, requests: ReadonlyArray<Requirement>, connections?: ReadonlyArray<string>) => RefreshState;
2433
2356
  /**
2434
- * What the rows the client holds had to say about a body.
2435
- *
2436
- * `skipped` is the honest half. A row missing a field the body reads cannot be
2437
- * judged — it is neither a match nor a non-match — and dropping it silently
2438
- * would turn "I could not tell" into "no". Naming it lets a caller decide:
2439
- * fetch the field, ask the server, or say the answer is partial.
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.
2440
2360
  */
2441
- interface Judged {
2442
- /** Keys of the rows that satisfy the body, in the order the body asks for. */
2443
- readonly matched: ReadonlyArray<EntityKey>;
2444
- /** Keys of rows held but missing a field the body reads, so not judged either way. */
2445
- readonly skipped: ReadonlyArray<EntityKey>;
2446
- }
2447
- interface MatchingOptions {
2448
- /**
2449
- * Judge only these keys. Without it every row of the body's Entity in the
2450
- * store is a candidate, which is what a filter over a loaded list wants; with
2451
- * it, a caller narrows to a connection's own edges.
2452
- */
2453
- readonly among?: ReadonlyArray<EntityKey> | undefined;
2454
- }
2361
+ declare const invalidateConnections: (model: RemoteModel, connections: ReadonlyArray<string>) => RemoteModel;
2455
2362
  /**
2456
- * The rows of `descriptor`'s Entity that the store holds and the body matches.
2457
- *
2458
- * The input is given **decoded**, as an application writes it, and encoded here
2459
- * through the descriptor's own `Input` codec. That is deliberate and is the
2460
- * whole reason this takes a descriptor rather than a bare body: a store holds
2461
- * wire values, so an input has to be in that space to be compared against them,
2462
- * and handing an interpreter a decoded value is a mistake **no runtime error
2463
- * catches** — the reference interpreter answers "no rows", which reads exactly
2464
- * like a correct answer. Doing it here means a caller cannot get it wrong.
2465
- *
2466
- * Literals in the body are deliberately *not* encoded. A literal written in
2467
- * domain terms is already broken against the server, which binds it to a column
2468
- * the same way; accepting it here would make the client quietly more permissive
2469
- * than the thing it has to agree with.
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.
2470
2367
  */
2471
- declare const matching: <Name extends string, Input>(store: EntityStore, descriptor: QueryDescriptor<Name, Input, unknown>, input: Input, options?: MatchingOptions) => Judged;
2368
+ declare const refreshIsInFlight: (refresh: RefreshState, request: Requirement, field: string) => boolean;
2472
2369
  /**
2473
- * Whether one row belongs to a query, as far as the client can tell.
2474
- *
2475
- * Three answers, and the third is the one that makes this usable. `'unknown'`
2476
- * is a row the store never fetched, or holds without a field the body reads —
2477
- * a caller that collapses it into `'no'` has turned "I could not tell" into an
2478
- * answer, which is the mistake this whole module is shaped against.
2479
- *
2480
- * **Membership is decidable where position is not.** Whether a row satisfies
2481
- * `eq`, `isNull` or `contains` needs no collation: equality on text is exact
2482
- * and `contains` folds ASCII, both stated in §6.0.1. *Where* a row sorts needs
2483
- * text collation, which is the backend's and deliberately outside the
2484
- * conformant subset — so this answers the half that is always answerable, and
2485
- * ordering stays the server's until a query can declare its collation.
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`.
2486
2373
  */
2487
- type Belongs = 'yes' | 'no' | 'unknown';
2374
+ declare const isLoading: (model: RemoteModel, entity: string, id: string, fields: ReadonlyArray<string>) => boolean;
2488
2375
  /**
2489
- * Takes the input **encoded**, because its one caller holds it that way: a
2490
- * connection identity carries the canonical encoded input, and making it decode
2491
- * only for this to encode again would be a round trip that can fail.
2492
- *
2493
- * A decoded-input sibling was written first and deleted: nothing called it. The
2494
- * asymmetry with `matching`, which takes a decoded input, is the shape of the
2495
- * two real callers rather than an oversight.
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.
2496
2384
  */
2497
- declare const belongsEncoded: <Name extends string, Input>(store: EntityStore, descriptor: QueryDescriptor<Name, Input, unknown>, encoded: Readonly<Record<string, unknown>>, key: EntityKey) => Belongs;
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;
2388
+ /**
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.
2392
+ */
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;
2498
2409
  //#endregion
2499
2410
  //#region src/inspect.d.ts
2500
2411
  /** A query body's `Dependencies` as plain data: each field by its Entity's name and key. */
@@ -2544,7 +2455,7 @@ interface RemoteInspection {
2544
2455
  /** A pure, serializable view of the whole cache. */
2545
2456
  declare const inspectRemote: (model: RemoteModel) => RemoteInspection;
2546
2457
  /** A pure, serializable view of one entity, or `undefined` if unknown. */
2547
- declare const inspectEntity: (model: RemoteModel, key: string) => RemoteInspection["entities"][number] | undefined;
2458
+ declare const inspectEntity: (model: RemoteModel, key: string) => RemoteInspection['entities'][number] | undefined;
2548
2459
  /**
2549
2460
  * Why a read shows what it shows, in words, and for `Initial`, which of the
2550
2461
  * usual mistakes it is.
@@ -2696,7 +2607,7 @@ type RemotePolicy =
2696
2607
  declare const RemotePolicy: {
2697
2608
  /** Fetch only what the store lacks. */
2698
2609
  cacheFirst: {
2699
- readonly _tag: "CacheFirst";
2610
+ readonly _tag: 'CacheFirst';
2700
2611
  };
2701
2612
  /** Keep present values visible, read as `Refreshing`, and refetch an entry older than `maxAge` ms. */
2702
2613
  staleWhileRevalidate: (options: {
@@ -2704,7 +2615,7 @@ declare const RemotePolicy: {
2704
2615
  }) => RemotePolicy;
2705
2616
  /** Fetch every selected field regardless of coverage; cached values stay visible meanwhile. */
2706
2617
  networkOnly: {
2707
- readonly _tag: "NetworkOnly";
2618
+ readonly _tag: 'NetworkOnly';
2708
2619
  };
2709
2620
  /** The planner options a policy compiles to at `now`. */
2710
2621
  toPlan: (policy: RemotePolicy, now: number) => PlanOptions;
@@ -2716,6 +2627,89 @@ declare const RemotePolicy: {
2716
2627
  refreshes: (policy: RemotePolicy) => boolean;
2717
2628
  };
2718
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
2719
2713
  //#region src/placement.d.ts
2720
2714
  /** Where a row falls in a loaded list. */
2721
2715
  type RowPlace = Data.TaggedEnum<{
@@ -2736,65 +2730,43 @@ type RowPlace = Data.TaggedEnum<{
2736
2730
  };
2737
2731
  }>;
2738
2732
  declare const RowPlace: {
2739
- readonly Unknown: Data.TaggedEnum.ConstructorFrom<{
2740
- readonly _tag: "Unknown";
2741
- readonly reason: string;
2742
- }, "_tag">;
2743
- readonly Before: Data.TaggedEnum.ConstructorFrom<{
2733
+ readonly $is: <Tag extends "Before" | "End" | "Outside" | "Unknown">(tag: Tag) => (u: unknown) => u is Extract<{
2744
2734
  readonly _tag: "Before";
2745
2735
  readonly segment: number;
2746
2736
  readonly edge: string;
2747
- }, "_tag">;
2748
- readonly End: Data.TaggedEnum.ConstructorFrom<{
2749
- readonly _tag: "End";
2750
- readonly segment: number;
2751
- }, "_tag">;
2752
- readonly Outside: Data.TaggedEnum.ConstructorFrom<{
2753
- readonly _tag: "Outside";
2754
- }, "_tag">;
2755
- readonly $is: <Tag extends "Unknown" | "Before" | "End" | "Outside">(tag: Tag) => (u: unknown) => u is Extract<{
2756
- readonly _tag: "Unknown";
2757
- readonly reason: string;
2758
2737
  }, {
2759
2738
  readonly _tag: Tag;
2760
2739
  }> | Extract<{
2761
- readonly _tag: "Before";
2740
+ readonly _tag: "End";
2762
2741
  readonly segment: number;
2763
- readonly edge: string;
2764
2742
  }, {
2765
2743
  readonly _tag: Tag;
2766
2744
  }> | Extract<{
2767
- readonly _tag: "End";
2768
- readonly segment: number;
2745
+ readonly _tag: "Outside";
2769
2746
  }, {
2770
2747
  readonly _tag: Tag;
2771
2748
  }> | Extract<{
2772
- readonly _tag: "Outside";
2749
+ readonly _tag: "Unknown";
2750
+ readonly reason: string;
2773
2751
  }, {
2774
2752
  readonly _tag: Tag;
2775
2753
  }>;
2776
2754
  readonly $match: {
2777
- <Cases extends {
2778
- readonly Unknown: (args: {
2779
- readonly _tag: "Unknown";
2780
- readonly reason: string;
2781
- }) => any;
2782
- readonly Before: (args: {
2783
- readonly _tag: "Before";
2784
- readonly segment: number;
2785
- readonly edge: string;
2786
- }) => any;
2787
- readonly End: (args: {
2788
- readonly _tag: "End";
2789
- readonly segment: number;
2790
- }) => any;
2791
- readonly Outside: (args: {
2792
- readonly _tag: "Outside";
2793
- }) => any;
2794
- }>(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
+ } | {
2795
2765
  readonly _tag: "Unknown";
2796
2766
  readonly reason: string;
2797
- } | {
2767
+ }, {
2768
+ readonly _tag: Tag;
2769
+ }>) => any; }>(cases: Cases): (value: {
2798
2770
  readonly _tag: "Before";
2799
2771
  readonly segment: number;
2800
2772
  readonly edge: string;
@@ -2803,28 +2775,25 @@ declare const RowPlace: {
2803
2775
  readonly segment: number;
2804
2776
  } | {
2805
2777
  readonly _tag: "Outside";
2806
- }) => import("effect/Unify").Unify<ReturnType<Cases["Unknown" | "Before" | "End" | "Outside"]>>;
2807
- <Cases extends {
2808
- readonly Unknown: (args: {
2809
- readonly _tag: "Unknown";
2810
- readonly reason: string;
2811
- }) => any;
2812
- readonly Before: (args: {
2813
- readonly _tag: "Before";
2814
- readonly segment: number;
2815
- readonly edge: string;
2816
- }) => any;
2817
- readonly End: (args: {
2818
- readonly _tag: "End";
2819
- readonly segment: number;
2820
- }) => any;
2821
- readonly Outside: (args: {
2822
- readonly _tag: "Outside";
2823
- }) => any;
2824
- }>(value: {
2778
+ } | {
2825
2779
  readonly _tag: "Unknown";
2826
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;
2827
2786
  } | {
2787
+ readonly _tag: "End";
2788
+ readonly segment: number;
2789
+ } | {
2790
+ readonly _tag: "Outside";
2791
+ } | {
2792
+ readonly _tag: "Unknown";
2793
+ readonly reason: string;
2794
+ }, {
2795
+ readonly _tag: Tag;
2796
+ }>) => any; }>(value: {
2828
2797
  readonly _tag: "Before";
2829
2798
  readonly segment: number;
2830
2799
  readonly edge: string;
@@ -2833,8 +2802,27 @@ declare const RowPlace: {
2833
2802
  readonly segment: number;
2834
2803
  } | {
2835
2804
  readonly _tag: "Outside";
2836
- }, 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"]>>;
2837
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">;
2838
2826
  };
2839
2827
  /**
2840
2828
  * Where the row stored under `key` falls in `connection`, by `body`'s order
@@ -3352,6 +3340,14 @@ interface LiveOptions {
3352
3340
  /** The longest a restart waits. Default `5 seconds`. */
3353
3341
  readonly maxRetryDelay?: Duration.Input | undefined;
3354
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]>>;
3355
3351
  /** A query the read entry runs, as its dependencies carry it: plain data Foldkit compares. */
3356
3352
  declare const PlannedQuery: Schema.Struct<{
3357
3353
  readonly identity: Schema.String;
@@ -3528,11 +3524,7 @@ declare const Remote: {
3528
3524
  };
3529
3525
  };
3530
3526
  /** Whether a Message is one of Remote's, by tag. */
3531
- reduces: <M extends {
3532
- readonly _tag: string;
3533
- }>(message: M) => message is Extract<M, {
3534
- readonly _tag: RemoteMessageTag;
3535
- }>;
3527
+ reduces: typeof isRemoteMessage;
3536
3528
  /**
3537
3529
  * Remote's Messages as one Schema, for a wrapper variant in the
3538
3530
  * application's union: `GotRemoteMessage: { message: Remote.Message }`. With
@@ -3737,28 +3729,20 @@ declare const Remote: {
3737
3729
  * mutations, plus the submodel. For a domain reused across applications or
3738
3730
  * bound in a test; `Remote.make` is the one-step form.
3739
3731
  */
3740
- 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: {
3741
- readonly entities: Entities;
3742
- readonly queries?: Queries;
3743
- readonly mutations?: Mutations;
3744
- }) => RemoteDescriptor<Entities, Queries, Mutations>;
3732
+ define: typeof defineRemote;
3745
3733
  /**
3746
3734
  * Binds a Remote domain to its store's location in the application Model. The
3747
3735
  * registered entity names are carried on the returned value, so `Remote.select`
3748
3736
  * rejects a selection for an entity this domain never declared.
3749
3737
  */
3750
- 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;
3751
3739
  /**
3752
3740
  * The resume part for this domain, for `foldkit-ssr`'s `SSR.plan({ parts })`:
3753
3741
  * a server render sends what the plan's active Surfaces read from the store,
3754
3742
  * each connection with its boundaries and each live cursor with it, and
3755
3743
  * nothing else. `id` tells two domains in one application apart.
3756
3744
  */
3757
- resume: <AppModel, Store extends RemoteModel>(domain: {
3758
- readonly store: ModelRef<AppModel, Store>;
3759
- }, options?: {
3760
- readonly id?: string | undefined;
3761
- }) => RemoteResumePart<AppModel>;
3745
+ resume: typeof resumePart;
3762
3746
  /**
3763
3747
  * A Projection node that reads a `RemoteData` value out of the store. The id
3764
3748
  * is supplied by the caller, usually from a Surface's params. The assembled
@@ -3766,7 +3750,7 @@ declare const Remote: {
3766
3750
  * as `Failed` instead of being asserted into `Value`. A present value with a
3767
3751
  * stale field reads as `Refreshing`: an observer is refetching it.
3768
3752
  */
3769
- 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>>;
3770
3754
  /**
3771
3755
  * When what a projection shows was last received, and whether it is stale
3772
3756
  * or loading. Pure, so a view can show "updated 5s ago" without I/O.
@@ -3807,7 +3791,7 @@ declare const Remote: {
3807
3791
  * `policy` decides what a present field means (default cache-first); `now`
3808
3792
  * is the clock it reads, so the planner itself stays pure and time-injected.
3809
3793
  */
3810
- 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>;
3811
3795
  /**
3812
3796
  * Marks what a projection, or a Surface without params, requires as due again.
3813
3797
  * Called from `update`: every selected field the store holds reads `Refreshing`,
@@ -3845,7 +3829,7 @@ declare const Remote: {
3845
3829
  * Writes a read result into the store, recording each field's applied window.
3846
3830
  * `requests` are the planned requirements the result answers.
3847
3831
  */
3848
- writeRead: (store: EntityStore, requests: ReadonlyArray<Requirement>, result: Schema.Schema.Type<typeof ReadBatchResult>, now?: number) => EntityStore;
3832
+ writeRead: typeof writeRead;
3849
3833
  /**
3850
3834
  * Adapts an Effect RPC client for `RemoteRpc` to `RemoteClient`, so an
3851
3835
  * application provides the transport's RPC layer instead of writing the
@@ -3859,29 +3843,26 @@ declare const Remote: {
3859
3843
  * answer, for `clientLayer`: a worker, a server in the page. `RemoteServer.answer`
3860
3844
  * is the other end.
3861
3845
  */
3862
- json: (send: RemoteJsonSend) => RemoteRpcClient;
3846
+ json: typeof json;
3863
3847
  /**
3864
3848
  * Remote's client over HTTP, for `clientLayer`: each call a `POST` of the JSON
3865
3849
  * request to `url`. `headers` is read per request (a session token, say).
3866
3850
  */
3867
- http: (url: string, options?: {
3868
- readonly headers?: (() => Readonly<Record<string, string>>) | undefined;
3869
- readonly fetch?: typeof fetch | undefined;
3870
- }) => RemoteRpcClient;
3851
+ http: typeof http;
3871
3852
  /**
3872
3853
  * Remote's client over HTTP with live, for `clientLayer`: reads, queries,
3873
3854
  * and mutations as `http` sends them, live requirements as one `POST`
3874
3855
  * answered with a `text/event-stream` of changes.
3875
3856
  * `foldkit-remote-server/fetch` is the other end.
3876
3857
  */
3877
- httpWithLive: (url: string, options?: LiveFetchOptions) => RemoteRpcClient;
3858
+ httpWithLive: typeof httpWithLive;
3878
3859
  clientLayer: <R = never>(client: RemoteRpcClient<R, RpcClientError.RpcClientError>, options?: CoalesceOptions) => Layer.Layer<RemoteClient, never, R>;
3879
3860
  /**
3880
3861
  * Wraps a `RemoteClient` layer so its reads coalesce: requirements issued
3881
3862
  * together become one batch, and a requirement already in flight is joined.
3882
3863
  * `Remote.clientLayer` applies this; use it on a hand-written client.
3883
3864
  */
3884
- coalesced: <E, R>(layer: Layer.Layer<RemoteClient, E, R>, options?: CoalesceOptions) => Layer.Layer<RemoteClient, E, R>;
3865
+ coalesced: typeof coalescedLayer;
3885
3866
  /**
3886
3867
  * A Foldkit Subscription entry that keeps the cache to what the active
3887
3868
  * Surfaces reach. `projections` are the ones the application observes (the
@@ -3934,9 +3915,9 @@ declare const Remote: {
3934
3915
  /** The `RemoteMessage` that merges a query page into its connection. */
3935
3916
  queryMessage: <Name extends string, Input>(ref: QueryRef<Name, Input>, result: Schema.Schema.Type<typeof QueryResult>, select?: RelationRequirement | undefined, now?: number | undefined) => RemoteMessage;
3936
3917
  /** A pure, serializable view of the whole cache. */
3937
- inspect: (model: RemoteModel) => RemoteInspection;
3918
+ inspect: typeof inspectRemote;
3938
3919
  /** A pure, serializable view of one entity, or `undefined` if unknown. */
3939
- inspectEntity: (model: RemoteModel, key: string) => RemoteInspection["entities"][number] | undefined;
3920
+ inspectEntity: typeof inspectEntity;
3940
3921
  /**
3941
3922
  * Runs a mutation through `RemoteClient`, decoding its typed Output and
3942
3923
  * returning the result's normalized patches so the caller can reconcile them
@@ -3956,7 +3937,7 @@ declare const Remote: {
3956
3937
  readonly entity: string;
3957
3938
  readonly id: string;
3958
3939
  }[];
3959
- }, RemoteMutationError | RemoteForbidden, RemoteClient>;
3940
+ }, RemoteForbidden | RemoteMutationError, RemoteClient>;
3960
3941
  /**
3961
3942
  * Runs a mutation and reconciles its patches into a `RemoteModel` in one step,
3962
3943
  * returning the new model alongside the typed Output. The model-level form of
@@ -3967,7 +3948,7 @@ declare const Remote: {
3967
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<{
3968
3949
  output: Output;
3969
3950
  model: AppModel;
3970
- }, RemoteMutationError | RemoteForbidden, RemoteClient>;
3951
+ }, RemoteForbidden | RemoteMutationError, RemoteClient>;
3971
3952
  /**
3972
3953
  * A Foldkit Subscription entry that plans a Surface's missing fields from the
3973
3954
  * Model and fetches them through `RemoteClient`, emitting a `RemoteMessage`
@@ -3989,5 +3970,5 @@ declare const Remote: {
3989
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>;
3990
3971
  };
3991
3972
  //#endregion
3992
- 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 };
3993
- //# sourceMappingURL=index-elfivniT.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