foldkit-remote 0.20.0 → 0.22.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.
- package/README.md +987 -198
- package/dist/answerGaps.d.ts +16 -0
- package/dist/answerGaps.d.ts.map +1 -0
- package/dist/answerGaps.js +60 -0
- package/dist/answerGaps.js.map +1 -0
- package/dist/client-B055kQuP.d.ts +110 -0
- package/dist/client-B055kQuP.d.ts.map +1 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.js +142 -0
- package/dist/client.js.map +1 -0
- package/dist/coalesce-CLAr92Nk.d.ts +34 -0
- package/dist/coalesce-CLAr92Nk.d.ts.map +1 -0
- package/dist/coalesce.d.ts +2 -0
- package/dist/coalesce.js +131 -0
- package/dist/coalesce.js.map +1 -0
- package/dist/connection-BRyaJy89.d.ts +45 -0
- package/dist/connection-BRyaJy89.d.ts.map +1 -0
- package/dist/connection.d.ts +2 -0
- package/dist/connection.js +170 -0
- package/dist/connection.js.map +1 -0
- package/dist/data.d.ts +7 -0
- package/dist/data.d.ts.map +1 -0
- package/dist/data.js +21 -0
- package/dist/data.js.map +1 -0
- package/dist/diagnostics-DHhVYflV.d.ts +125 -0
- package/dist/diagnostics-DHhVYflV.d.ts.map +1 -0
- package/dist/diagnostics.d.ts +2 -0
- package/dist/diagnostics.js +60 -0
- package/dist/diagnostics.js.map +1 -0
- package/dist/entity-CgsG5Uel.d.ts +196 -0
- package/dist/entity-CgsG5Uel.d.ts.map +1 -0
- package/dist/entity-DuDxaa3n.js +279 -0
- package/dist/entity-DuDxaa3n.js.map +1 -0
- package/dist/entity.d.ts +2 -0
- package/dist/entity.js +1 -0
- package/dist/held.d.ts +19 -0
- package/dist/held.d.ts.map +1 -0
- package/dist/held.js +70 -0
- package/dist/held.js.map +1 -0
- package/dist/impact.d.ts +79 -0
- package/dist/impact.d.ts.map +1 -0
- package/dist/impact.js +166 -0
- package/dist/impact.js.map +1 -0
- package/dist/index.d.ts +1542 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2791 -0
- package/dist/index.js.map +1 -0
- package/dist/inspect-DtRQGCRP.d.ts +134 -0
- package/dist/inspect-DtRQGCRP.d.ts.map +1 -0
- package/dist/inspect.d.ts +2 -0
- package/dist/inspect.js +33 -0
- package/dist/inspect.js.map +1 -0
- package/dist/json-DowLl1eB.d.ts +52 -0
- package/dist/json-DowLl1eB.d.ts.map +1 -0
- package/dist/json.d.ts +2 -0
- package/dist/json.js +123 -0
- package/dist/json.js.map +1 -0
- package/dist/law.d.ts +56 -0
- package/dist/law.d.ts.map +1 -0
- package/dist/law.js +201 -0
- package/dist/law.js.map +1 -0
- package/dist/live-BpTzlCnY.d.ts +79 -0
- package/dist/live-BpTzlCnY.d.ts.map +1 -0
- package/dist/live.d.ts +2 -0
- package/dist/live.js +126 -0
- package/dist/live.js.map +1 -0
- package/dist/matching-DF5F9Us8.d.ts +100 -0
- package/dist/matching-DF5F9Us8.d.ts.map +1 -0
- package/dist/matching.d.ts +2 -0
- package/dist/matching.js +172 -0
- package/dist/matching.js.map +1 -0
- package/dist/model-B6zk1NMB.d.ts +710 -0
- package/dist/model-B6zk1NMB.d.ts.map +1 -0
- package/dist/model.d.ts +2 -0
- package/dist/model.js +1308 -0
- package/dist/model.js.map +1 -0
- package/dist/mutation.d.ts +2 -0
- package/dist/mutation.js +612 -0
- package/dist/mutation.js.map +1 -0
- package/dist/optimistic-CECsfNGY.d.ts +523 -0
- package/dist/optimistic-CECsfNGY.d.ts.map +1 -0
- package/dist/optimistic.d.ts +2 -0
- package/dist/optimistic.js +336 -0
- package/dist/optimistic.js.map +1 -0
- package/dist/outbox-DNuc4kZp.d.ts +259 -0
- package/dist/outbox-DNuc4kZp.d.ts.map +1 -0
- package/dist/outbox.d.ts +2 -0
- package/dist/outbox.js +326 -0
- package/dist/outbox.js.map +1 -0
- package/dist/patchValues.d.ts +10 -0
- package/dist/patchValues.d.ts.map +1 -0
- package/dist/patchValues.js +57 -0
- package/dist/patchValues.js.map +1 -0
- package/dist/persistence-CCMnvg7-.d.ts +114 -0
- package/dist/persistence-CCMnvg7-.d.ts.map +1 -0
- package/dist/persistence.d.ts +2 -0
- package/dist/persistence.js +205 -0
- package/dist/persistence.js.map +1 -0
- package/dist/placement-jZdsIpmj.d.ts +50 -0
- package/dist/placement-jZdsIpmj.d.ts.map +1 -0
- package/dist/placement.d.ts +2 -0
- package/dist/placement.js +116 -0
- package/dist/placement.js.map +1 -0
- package/dist/plan-D9cftxC_.d.ts +35 -0
- package/dist/plan-D9cftxC_.d.ts.map +1 -0
- package/dist/plan.d.ts +2 -0
- package/dist/plan.js +100 -0
- package/dist/plan.js.map +1 -0
- package/dist/policy-DsWHmIAq.d.ts +42 -0
- package/dist/policy-DsWHmIAq.d.ts.map +1 -0
- package/dist/policy.d.ts +2 -0
- package/dist/policy.js +32 -0
- package/dist/policy.js.map +1 -0
- package/dist/{port.d.mts → port.d.ts} +3 -2
- package/dist/port.d.ts.map +1 -0
- package/dist/{port.mjs → port.js} +3 -2
- package/dist/port.js.map +1 -0
- package/dist/query-BuIU93xA.d.ts +141 -0
- package/dist/query-BuIU93xA.d.ts.map +1 -0
- package/dist/query.d.ts +2 -0
- package/dist/query.js +0 -0
- package/dist/query.js.map +1 -0
- package/dist/record.d.ts +11 -0
- package/dist/record.d.ts.map +1 -0
- package/dist/record.js +21 -0
- package/dist/record.js.map +1 -0
- package/dist/relation-BLBGOZom.d.ts +59 -0
- package/dist/relation-BLBGOZom.d.ts.map +1 -0
- package/dist/relation.d.ts +2 -0
- package/dist/relation.js +93 -0
- package/dist/relation.js.map +1 -0
- package/dist/remoteData-mK1suYi1.d.ts +148 -0
- package/dist/remoteData-mK1suYi1.d.ts.map +1 -0
- package/dist/remoteData.d.ts +2 -0
- package/dist/remoteData.js +179 -0
- package/dist/remoteData.js.map +1 -0
- package/dist/reporting.d.ts +12 -0
- package/dist/reporting.d.ts.map +1 -0
- package/dist/reporting.js +45 -0
- package/dist/reporting.js.map +1 -0
- package/dist/requirement-D57S2LpH.d.ts +64 -0
- package/dist/requirement-D57S2LpH.d.ts.map +1 -0
- package/dist/requirement.d.ts +2 -0
- package/dist/requirement.js +114 -0
- package/dist/requirement.js.map +1 -0
- package/dist/resume-Ct5R6yli.d.ts +92 -0
- package/dist/resume-Ct5R6yli.d.ts.map +1 -0
- package/dist/resume.d.ts +2 -0
- package/dist/resume.js +222 -0
- package/dist/resume.js.map +1 -0
- package/dist/retain-BfNTvBRb.d.ts +48 -0
- package/dist/retain-BfNTvBRb.d.ts.map +1 -0
- package/dist/retain.d.ts +2 -0
- package/dist/retain.js +107 -0
- package/dist/retain.js.map +1 -0
- package/dist/selection.d.ts +2 -0
- package/dist/selection.js +1 -0
- package/dist/shown.d.ts +20 -0
- package/dist/shown.d.ts.map +1 -0
- package/dist/shown.js +40 -0
- package/dist/shown.js.map +1 -0
- package/dist/sse-C7LhdbiQ.d.ts +17 -0
- package/dist/sse-C7LhdbiQ.d.ts.map +1 -0
- package/dist/sse.d.ts +2 -0
- package/dist/sse.js +127 -0
- package/dist/sse.js.map +1 -0
- package/dist/store-ah2qjcJW.d.ts +100 -0
- package/dist/store-ah2qjcJW.d.ts.map +1 -0
- package/dist/store.d.ts +2 -0
- package/dist/store.js +218 -0
- package/dist/store.js.map +1 -0
- package/dist/testing.d.ts +133 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +0 -0
- package/dist/testing.js.map +1 -0
- package/dist/why-kgp_Wr3z.d.ts +483 -0
- package/dist/why-kgp_Wr3z.d.ts.map +1 -0
- package/dist/why.d.ts +2 -0
- package/dist/why.js +293 -0
- package/dist/why.js.map +1 -0
- package/dist/whyReasons.d.ts +42 -0
- package/dist/whyReasons.d.ts.map +1 -0
- package/dist/whyReasons.js +211 -0
- package/dist/whyReasons.js.map +1 -0
- package/dist/wire-DthPcTM6.d.ts +787 -0
- package/dist/wire-DthPcTM6.d.ts.map +1 -0
- package/dist/wire.d.ts +2 -0
- package/dist/wire.js +329 -0
- package/dist/wire.js.map +1 -0
- package/package.json +19 -14
- package/dist/index-BEvVAL76.d.mts +0 -4097
- package/dist/index-BEvVAL76.d.mts.map +0 -1
- package/dist/index.d.mts +0 -2
- package/dist/index.mjs +0 -1
- package/dist/port.d.mts.map +0 -1
- package/dist/port.mjs.map +0 -1
- package/dist/src-BDqn7Ocr.mjs +0 -6344
- package/dist/src-BDqn7Ocr.mjs.map +0 -1
|
@@ -1,4097 +0,0 @@
|
|
|
1
|
-
import { Context, Data, Duration, Effect, Layer, Option, Result, Schema, Stream } from "effect";
|
|
2
|
-
import { KeyValueStore } from "effect/persistence";
|
|
3
|
-
import * as Domain from "foldkit-entity";
|
|
4
|
-
import { AnyEntity, AnyQuery, AnyWrite, BoundWrite, ConditionedWrite, Dependencies, InputExpr, Invariant, MemoryOperators, Query, Write } from "foldkit-entity";
|
|
5
|
-
import { Command } from "foldkit/command";
|
|
6
|
-
import { EntryWithoutKeepAlive } from "foldkit/subscription";
|
|
7
|
-
import { ActiveSurface, Contract, Invalid, Metadata, ModelRef, Projection, Surface, SurfaceSource, Wiring } from "foldkit-surface";
|
|
8
|
-
import { Rpc, RpcClientError, RpcGroup } from "effect/rpc";
|
|
9
|
-
import * as Update from "foldkit/update";
|
|
10
|
-
type EntityKey = string;
|
|
11
|
-
interface EntityEntry {
|
|
12
|
-
readonly values: Readonly<Record<string, unknown>>;
|
|
13
|
-
readonly present: ReadonlySet<string>;
|
|
14
|
-
/** Present fields whose value may be outdated (revalidation needed). */
|
|
15
|
-
readonly stale: ReadonlySet<string>;
|
|
16
|
-
/**
|
|
17
|
-
* Fields the server settled without a value: asked for, and answered without
|
|
18
|
-
* them, whatever the reason. Not planned again until a refresh asks; a later
|
|
19
|
-
* write of the field clears it.
|
|
20
|
-
*/
|
|
21
|
-
readonly unavailable: ReadonlySet<string>;
|
|
22
|
-
/** The entity is known to be absent; a later write clears this. */
|
|
23
|
-
readonly tombstone: boolean;
|
|
24
|
-
/** Injected clock reading of the last write; never read from ambient state. */
|
|
25
|
-
readonly updatedAt: number;
|
|
26
|
-
/**
|
|
27
|
-
* The canonical window each present field was fetched with (`""` for none).
|
|
28
|
-
* A later request with a *known, different* window is planned as missing.
|
|
29
|
-
*/
|
|
30
|
-
readonly windows: Readonly<Record<string, string>>;
|
|
31
|
-
}
|
|
32
|
-
type EntityStore = Readonly<Record<EntityKey, EntityEntry>>;
|
|
33
|
-
/** The separator keeps an untrusted id from colliding with a prototype key. */
|
|
34
|
-
declare const entityKey: (entity: string, id: string) => EntityKey;
|
|
35
|
-
declare const emptyStore: EntityStore;
|
|
36
|
-
interface EntityWrite {
|
|
37
|
-
readonly key: EntityKey;
|
|
38
|
-
readonly values: Readonly<Record<string, unknown>>;
|
|
39
|
-
/** The canonical window each written relation field was fetched with. */
|
|
40
|
-
readonly windows?: Readonly<Record<string, string>> | undefined;
|
|
41
|
-
/** When this write dates the entity, instead of the batch's `now`. */
|
|
42
|
-
readonly updatedAt?: number | undefined;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Merges known values into many entities, copying the store once. Every
|
|
46
|
-
* written field becomes present and non-stale; a tombstone is cleared because
|
|
47
|
-
* the entity is evidently not absent.
|
|
48
|
-
*/
|
|
49
|
-
declare const writeEntities: (store: EntityStore, writes: ReadonlyArray<EntityWrite>, now?: number) => EntityStore;
|
|
50
|
-
/** `writeEntities` for one entity. */
|
|
51
|
-
declare const writeEntity: (store: EntityStore, key: EntityKey, values: Readonly<Record<string, unknown>>, now?: number, windows?: Readonly<Record<string, string>>) => EntityStore;
|
|
52
|
-
/**
|
|
53
|
-
* Marks present fields stale (`true`) or ends their staleness (`false`) across
|
|
54
|
-
* many entities, copying the store once. A field never present stays missing;
|
|
55
|
-
* an unknown entity is left alone.
|
|
56
|
-
*/
|
|
57
|
-
declare const setStale: (store: EntityStore, marks: ReadonlyArray<readonly [key: EntityKey, fields: Iterable<string>]>, stale: boolean) => EntityStore;
|
|
58
|
-
/** Marks present fields stale; fields that were never present stay missing. */
|
|
59
|
-
declare const markStale: (store: EntityStore, key: EntityKey, fields: Iterable<string>) => EntityStore;
|
|
60
|
-
/** Ends a refresh that did not land: the fields are present again as they were. */
|
|
61
|
-
declare const clearStale: (store: EntityStore, key: EntityKey, fields: Iterable<string>) => EntityStore;
|
|
62
|
-
/**
|
|
63
|
-
* Records fields the server settled without a value. A present field is left
|
|
64
|
-
* as it is: the answer that settled it was not about the value it holds.
|
|
65
|
-
* `false` forgets the marks, which is how a refresh asks again.
|
|
66
|
-
*/
|
|
67
|
-
declare const setUnavailable: (store: EntityStore, marks: ReadonlyArray<readonly [key: EntityKey, fields: Iterable<string>]>, unavailable: boolean) => EntityStore;
|
|
68
|
-
/** Whether the server settled this field without a value, and nothing has written it since. */
|
|
69
|
-
declare const isFieldUnavailable: (store: EntityStore, key: EntityKey, field: string) => boolean;
|
|
70
|
-
/** Records that the entity is known to be absent, so it is not refetched. */
|
|
71
|
-
declare const tombstone: (store: EntityStore, key: EntityKey) => EntityStore;
|
|
72
|
-
/** Forgets everything known about the entity, including a tombstone. */
|
|
73
|
-
declare const remove: (store: EntityStore, key: EntityKey) => EntityStore;
|
|
74
|
-
declare const entry: (store: EntityStore, key: EntityKey) => Option.Option<EntityEntry>;
|
|
75
|
-
declare const isTombstone: (store: EntityStore, key: EntityKey) => boolean;
|
|
76
|
-
/** A field is known only if it is present and not stale. */
|
|
77
|
-
declare const hasField: (store: EntityStore, key: EntityKey, field: string) => boolean;
|
|
78
|
-
/** A present field whose value may be outdated; absent fields are not stale. */
|
|
79
|
-
declare const isFieldStale: (store: EntityStore, key: EntityKey, field: string) => boolean;
|
|
80
|
-
/**
|
|
81
|
-
* Reads a present field, stale or not. Absence and a tombstone both yield
|
|
82
|
-
* `Option.none()`; a present `undefined`/`null` yields `Option.some`.
|
|
83
|
-
*/
|
|
84
|
-
declare const readField: (store: EntityStore, key: EntityKey, field: string) => Option.Option<unknown>;
|
|
85
|
-
/**
|
|
86
|
-
* The fields the planner must fetch. A tombstone makes every field known
|
|
87
|
-
* (absent), so it returns an empty list and the entity is not refetched, and a
|
|
88
|
-
* field the server settled without a value is known the same way. A
|
|
89
|
-
* requested window that differs from the one a field was fetched with also
|
|
90
|
-
* marks it missing, but only when the stored window is known (never `""`), so a
|
|
91
|
-
* writer that does not record windows cannot cause a refetch loop.
|
|
92
|
-
*/
|
|
93
|
-
declare const missingFields: (store: EntityStore, key: EntityKey, fields: Iterable<string>, windows?: Readonly<Record<string, string>>) => ReadonlyArray<string>;
|
|
94
|
-
interface EdgeRef {
|
|
95
|
-
readonly entity: string;
|
|
96
|
-
readonly id: string;
|
|
97
|
-
}
|
|
98
|
-
/** `key` is the edge identity used for de-duplication. */
|
|
99
|
-
interface Edge {
|
|
100
|
-
readonly key: string;
|
|
101
|
-
readonly ref: EdgeRef;
|
|
102
|
-
}
|
|
103
|
-
declare const edge: (ref: EdgeRef, key?: string) => Edge;
|
|
104
|
-
type Cursor = string;
|
|
105
|
-
type Boundary = {
|
|
106
|
-
readonly _tag: 'Terminal';
|
|
107
|
-
} | {
|
|
108
|
-
readonly _tag: 'Cursor';
|
|
109
|
-
readonly cursor: Cursor;
|
|
110
|
-
} | {
|
|
111
|
-
readonly _tag: 'Unknown';
|
|
112
|
-
};
|
|
113
|
-
declare const terminal: Boundary;
|
|
114
|
-
declare const unknown: Boundary;
|
|
115
|
-
declare const cursor: (value: Cursor) => Boundary;
|
|
116
|
-
interface Segment {
|
|
117
|
-
readonly edges: readonly Edge[];
|
|
118
|
-
readonly start: Boundary;
|
|
119
|
-
readonly end: Boundary;
|
|
120
|
-
}
|
|
121
|
-
interface Connection {
|
|
122
|
-
readonly segments: readonly Segment[];
|
|
123
|
-
readonly stale: boolean;
|
|
124
|
-
}
|
|
125
|
-
declare const emptyConnection: Connection;
|
|
126
|
-
declare const segment: (edges: readonly Edge[], start: Boundary, end: Boundary) => Segment;
|
|
127
|
-
/** Adds a page to the connection, joining contiguous or overlapping segments. */
|
|
128
|
-
declare const merge: (current: Connection, page: Segment) => Connection;
|
|
129
|
-
/** Visible edges, segment by segment. */
|
|
130
|
-
declare const items: (connection: Connection) => ReadonlyArray<Edge>;
|
|
131
|
-
/** There is more before the known region. Derived from boundaries, never row count. */
|
|
132
|
-
declare const hasPrevious: (connection: Connection) => boolean;
|
|
133
|
-
/** There is more after the known region. Derived from boundaries, never row count. */
|
|
134
|
-
declare const hasNext: (connection: Connection) => boolean;
|
|
135
|
-
/** A connection with more than one segment has an explicit unknown gap. */
|
|
136
|
-
declare const isGapped: (connection: Connection) => boolean;
|
|
137
|
-
interface RemoteError {
|
|
138
|
-
readonly _tag: string;
|
|
139
|
-
readonly message: string;
|
|
140
|
-
/**
|
|
141
|
-
* A refused mutation's refusal, encoded as the server sent it. Read it
|
|
142
|
-
* decoded, by its mutation, with `Data.refusal`.
|
|
143
|
-
*/
|
|
144
|
-
readonly refusal?: unknown;
|
|
145
|
-
/**
|
|
146
|
-
* Why the server refused who is asking (`_tag: 'Unauthenticated'` or
|
|
147
|
-
* `'Forbidden'`), when it said. Read it with `RemoteData.denied`.
|
|
148
|
-
*/
|
|
149
|
-
readonly reason?: string | undefined;
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* The server would not answer who is asking: their session ended or was
|
|
153
|
-
* never there (`Unauthenticated`, a 401), or they may not (`Forbidden`, a
|
|
154
|
-
* 403). `reason` is the server's sentence, when it gave one. Not a mutation's
|
|
155
|
-
* declared `refusal`, which the server answered and `Data.refusal` reads.
|
|
156
|
-
*/
|
|
157
|
-
declare const Denied: import("foldkit/schema").TaggedUnion<{
|
|
158
|
-
readonly Unauthenticated: {
|
|
159
|
-
reason: Schema.Option<Schema.String>;
|
|
160
|
-
};
|
|
161
|
-
readonly Forbidden: {
|
|
162
|
-
reason: Schema.Option<Schema.String>;
|
|
163
|
-
};
|
|
164
|
-
}>;
|
|
165
|
-
type Denied = typeof Denied.Type;
|
|
166
|
-
type RemoteData<A> = {
|
|
167
|
-
readonly _tag: 'Initial';
|
|
168
|
-
} | {
|
|
169
|
-
readonly _tag: 'Loading';
|
|
170
|
-
} | {
|
|
171
|
-
readonly _tag: 'Ready';
|
|
172
|
-
readonly value: A;
|
|
173
|
-
} | {
|
|
174
|
-
readonly _tag: 'Refreshing';
|
|
175
|
-
readonly value: A;
|
|
176
|
-
} | {
|
|
177
|
-
readonly _tag: 'Failed';
|
|
178
|
-
readonly error: RemoteError;
|
|
179
|
-
readonly previous?: A;
|
|
180
|
-
} | {
|
|
181
|
-
readonly _tag: 'NotFound';
|
|
182
|
-
};
|
|
183
|
-
/**
|
|
184
|
-
* What `RemoteData.render` tells the `data` branch about the value it is
|
|
185
|
-
* given: whether a newer answer is on its way, and whether this one is what
|
|
186
|
-
* was last known good before a read failed. It is one tag rather than two
|
|
187
|
-
* booleans because a value cannot be both at once, and a type that can say so
|
|
188
|
-
* invites a view to handle a state that never arrives.
|
|
189
|
-
*/
|
|
190
|
-
type Freshness = {
|
|
191
|
-
readonly _tag: 'Fresh';
|
|
192
|
-
} | {
|
|
193
|
-
readonly _tag: 'Refreshing';
|
|
194
|
-
} | {
|
|
195
|
-
readonly _tag: 'Stale';
|
|
196
|
-
readonly error: RemoteError;
|
|
197
|
-
};
|
|
198
|
-
declare const remoteErrorSchema: Schema.Struct<{
|
|
199
|
-
readonly _tag: Schema.String;
|
|
200
|
-
readonly message: Schema.String;
|
|
201
|
-
readonly refusal: Schema.optional<Schema.Unknown>;
|
|
202
|
-
readonly reason: Schema.optional<Schema.String>;
|
|
203
|
-
}>;
|
|
204
|
-
declare const remoteDataSchema: <A>(value: Schema.Schema<A>) => Schema.Codec<RemoteData<A>, unknown>;
|
|
205
|
-
declare const RemoteData: {
|
|
206
|
-
/**
|
|
207
|
-
* The `RemoteData` schema for a value schema. Exposed so a `RemoteData` can
|
|
208
|
-
* be embedded in a hand-written Model schema, not only through `Remote.select`.
|
|
209
|
-
*/
|
|
210
|
-
schema: <A>(value: Schema.Schema<A>) => Schema.Schema<RemoteData<A>>;
|
|
211
|
-
/**
|
|
212
|
-
* Whether the read has an answer: `Ready`, `Refreshing`, `Failed` or
|
|
213
|
-
* `NotFound`. `Initial` and `Loading` are still waiting for one.
|
|
214
|
-
*/
|
|
215
|
-
answered: <A>(data: RemoteData<A>) => boolean;
|
|
216
|
-
/** Exhaustive: omitting a state is a compile error. */
|
|
217
|
-
match: <A, R>(data: RemoteData<A>, cases: {
|
|
218
|
-
readonly Initial: () => R;
|
|
219
|
-
readonly Loading: () => R;
|
|
220
|
-
readonly Ready: (value: A) => R;
|
|
221
|
-
readonly Refreshing: (value: A) => R;
|
|
222
|
-
readonly Failed: (error: RemoteError, previous: Option.Option<A>) => R;
|
|
223
|
-
readonly NotFound: () => R;
|
|
224
|
-
}) => R;
|
|
225
|
-
/**
|
|
226
|
-
* The view-oriented fold: the six states as the three things a view actually
|
|
227
|
-
* draws, under the policy that useful data stays on screen. A value that is
|
|
228
|
-
* being refetched, or that a later read failed to replace, still reaches
|
|
229
|
-
* `data` — with `freshness` saying which — instead of being replaced by a
|
|
230
|
-
* spinner or an error the reader cannot act on.
|
|
231
|
-
*
|
|
232
|
-
* ```ts
|
|
233
|
-
* RemoteData.render(model.user, {
|
|
234
|
-
* loading: () => UserSkeleton(),
|
|
235
|
-
* notFound: () => NoSuchUser(),
|
|
236
|
-
* failed: error => ErrorView(error),
|
|
237
|
-
* data: (user, freshness) => UserView({ user, dimmed: freshness._tag !== 'Fresh' }),
|
|
238
|
-
* })
|
|
239
|
-
* ```
|
|
240
|
-
*
|
|
241
|
-
* `notFound` is its own branch and not optional: a row the server answered
|
|
242
|
-
* for and does not have is neither loading nor a failure, and drawing it as
|
|
243
|
-
* either is a spinner that never ends or an error nobody can fix.
|
|
244
|
-
*
|
|
245
|
-
* This does not replace `match`, which is the exhaustive fold over the states
|
|
246
|
-
* themselves. Reach for `match` when the six states really do draw
|
|
247
|
-
* differently, and for this when they draw the usual three ways.
|
|
248
|
-
*/
|
|
249
|
-
render: <A, R>(data: RemoteData<A>, cases: {
|
|
250
|
-
readonly loading: () => R;
|
|
251
|
-
readonly notFound: () => R;
|
|
252
|
-
readonly failed: (error: RemoteError) => R;
|
|
253
|
-
readonly data: (value: A, freshness: Freshness) => R;
|
|
254
|
-
}) => R;
|
|
255
|
-
/**
|
|
256
|
-
* The denial a failure was, typed, or none for any other failure (a
|
|
257
|
-
* network error, a protocol mismatch): what to read before telling a reader
|
|
258
|
-
* to sign in again.
|
|
259
|
-
*
|
|
260
|
-
* ```ts
|
|
261
|
-
* Option.match(RemoteData.denied(error), {
|
|
262
|
-
* onNone: () => 'Could not load',
|
|
263
|
-
* onSome: Denied.match({ Unauthenticated: () => 'Sign in again', Forbidden: () => 'Not yours' }),
|
|
264
|
-
* })
|
|
265
|
-
* ```
|
|
266
|
-
*/
|
|
267
|
-
denied: (error: RemoteError) => Option.Option<Denied>;
|
|
268
|
-
map: <A, B>(data: RemoteData<A>, f: (value: A) => B) => RemoteData<B>;
|
|
269
|
-
};
|
|
270
|
-
interface NormalizedPatch {
|
|
271
|
-
readonly entity: string;
|
|
272
|
-
readonly id: string;
|
|
273
|
-
readonly values: Readonly<Record<string, unknown>>;
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* A patch a pending request shows, and the amounts it moves fields by: each
|
|
277
|
-
* added, whenever the store is read, to the value under it, so a change that
|
|
278
|
-
* reaches the store meanwhile is added to, not hidden.
|
|
279
|
-
*/
|
|
280
|
-
interface PendingPatch extends NormalizedPatch {
|
|
281
|
-
readonly adds?: Readonly<Record<string, number>>;
|
|
282
|
-
}
|
|
283
|
-
interface MutationState {
|
|
284
|
-
readonly pending: ReadonlySet<string>;
|
|
285
|
-
readonly applied: ReadonlySet<string>;
|
|
286
|
-
readonly failed: ReadonlySet<string>;
|
|
287
|
-
/** Why each request in `failed` failed, kept exactly as long as `failed` keeps its id. */
|
|
288
|
-
readonly errors: ReadonlyMap<string, RemoteError>;
|
|
289
|
-
/**
|
|
290
|
-
* The operation id each request in `failed` was sent with, kept as `errors`
|
|
291
|
-
* is: a retry of that request id sends it again, so a server recognises it.
|
|
292
|
-
*/
|
|
293
|
-
readonly operations: ReadonlyMap<string, string>;
|
|
294
|
-
/**
|
|
295
|
-
* How many mutations this model has started. A bound domain takes its next
|
|
296
|
-
* request id from here, so `update` stays pure and the id exists before the
|
|
297
|
-
* Command runs.
|
|
298
|
-
*/
|
|
299
|
-
readonly sequence: number;
|
|
300
|
-
}
|
|
301
|
-
declare const emptyMutationState: MutationState;
|
|
302
|
-
declare const beginMutation: (state: MutationState, requestId: string) => MutationState;
|
|
303
|
-
declare const failMutation: (state: MutationState, requestId: string, error: RemoteError, operation: string) => MutationState;
|
|
304
|
-
/** What Remote knows of one mutation request, by the id `mutate` returned. */
|
|
305
|
-
type MutationStatus =
|
|
306
|
-
/** Never started here, or settled so long ago its id has left the window. */
|
|
307
|
-
{
|
|
308
|
-
readonly _tag: 'Unknown';
|
|
309
|
-
} | {
|
|
310
|
-
readonly _tag: 'Pending';
|
|
311
|
-
} | {
|
|
312
|
-
readonly _tag: 'Applied';
|
|
313
|
-
} | {
|
|
314
|
-
readonly _tag: 'Failed';
|
|
315
|
-
readonly error: RemoteError;
|
|
316
|
-
};
|
|
317
|
-
declare const mutationStatus: (state: MutationState, requestId: string) => MutationStatus;
|
|
318
|
-
interface Reconciled {
|
|
319
|
-
readonly store: EntityStore;
|
|
320
|
-
readonly state: MutationState;
|
|
321
|
-
}
|
|
322
|
-
/** What a settled mutation wrote, as `MutationSucceeded` carries it. */
|
|
323
|
-
interface MutationAnswer {
|
|
324
|
-
readonly entities: ReadonlyArray<NormalizedPatch>;
|
|
325
|
-
/** Entities the mutation deleted; each is tombstoned. */
|
|
326
|
-
readonly deleted?: ReadonlyArray<{
|
|
327
|
-
readonly entity: string;
|
|
328
|
-
readonly id: string;
|
|
329
|
-
}> | undefined;
|
|
330
|
-
/** Injected clock reading of the answer, which dates what it writes. */
|
|
331
|
-
readonly now: number;
|
|
332
|
-
}
|
|
333
|
-
/**
|
|
334
|
-
* Applies a mutation result once and marks the request settled. A second call
|
|
335
|
-
* with the same `requestId` (a retry, or a live event describing the same change)
|
|
336
|
-
* does not re-apply the entities, but still clears `pending`.
|
|
337
|
-
*/
|
|
338
|
-
declare const reconcileMutation: (store: EntityStore, state: MutationState, requestId: string, answer: MutationAnswer) => Reconciled;
|
|
339
|
-
/** A mutation an application declares: its name and input/output codecs. */
|
|
340
|
-
interface MutationDescriptor<Name extends string, Input, Output, Refused = unknown> {
|
|
341
|
-
readonly name: Name;
|
|
342
|
-
readonly Input: Schema.Codec<Input>;
|
|
343
|
-
readonly Output: Schema.Codec<Output>;
|
|
344
|
-
/**
|
|
345
|
-
* What the server may refuse the mutation with, as a value a client can
|
|
346
|
-
* match on rather than a message to parse: `Schema.Never` when it declares
|
|
347
|
-
* none.
|
|
348
|
-
*/
|
|
349
|
-
readonly Refusal: Schema.Codec<Refused, unknown>;
|
|
350
|
-
/**
|
|
351
|
-
* What the mutation writes, when it was declared as a `Write`: the optimistic
|
|
352
|
-
* patch a client shows, and what a server can run without a handler.
|
|
353
|
-
*/
|
|
354
|
-
readonly write?: AnyWrite | undefined;
|
|
355
|
-
}
|
|
356
|
-
declare const conflict: Schema.TaggedStruct<"Conflict", {}>;
|
|
357
|
-
declare const unmet: Schema.TaggedStruct<"Unmet", {}>;
|
|
358
|
-
/**
|
|
359
|
-
* The row the write would leave breaks one of its Entity's invariants: which
|
|
360
|
-
* one, what to tell the author, and the fields to show it beside. None and
|
|
361
|
-
* empty when the invariant reads a member hidden from whoever asked.
|
|
362
|
-
*/
|
|
363
|
-
declare const invalid: Schema.TaggedStruct<"Invalid", {
|
|
364
|
-
readonly rule: Schema.OptionFromNullOr<Schema.String>;
|
|
365
|
-
readonly message: Schema.String;
|
|
366
|
-
readonly path: Schema.$Array<Schema.String>;
|
|
367
|
-
}>;
|
|
368
|
-
/** Refusals a form or an editor knows how to show. */
|
|
369
|
-
declare const Refusal: {
|
|
370
|
-
/** One input key was refused, for `reason`, which a form shows beside that key. */
|
|
371
|
-
field: <const Key extends string, Reason extends Schema.Top>(key: Key, reason: Reason) => Schema.TaggedStruct<"Field", {
|
|
372
|
-
readonly key: Schema.Literal<Key>;
|
|
373
|
-
readonly reason: Reason;
|
|
374
|
-
}>;
|
|
375
|
-
/** The row moved on since the client read it; the author decides what wins. */
|
|
376
|
-
conflict: Schema.TaggedStruct<"Conflict", {}>;
|
|
377
|
-
/** The row does not hold what the write's `when` asks of it, where it would commit. */
|
|
378
|
-
unmet: Schema.TaggedStruct<"Unmet", {}>;
|
|
379
|
-
/** The row the write would leave breaks an invariant of its Entity. */
|
|
380
|
-
invalid: Schema.TaggedStruct<"Invalid", {
|
|
381
|
-
readonly rule: Schema.OptionFromNullOr<Schema.String>;
|
|
382
|
-
readonly message: Schema.String;
|
|
383
|
-
readonly path: Schema.$Array<Schema.String>;
|
|
384
|
-
}>;
|
|
385
|
-
/** Whether a refusal, of whatever mutation, is a `Refusal.field`. */
|
|
386
|
-
isField: <I>(input: I) => input is I & {
|
|
387
|
-
readonly _tag: "Field";
|
|
388
|
-
readonly key: string;
|
|
389
|
-
readonly reason: unknown;
|
|
390
|
-
};
|
|
391
|
-
/** Whether a refusal, of whatever mutation, is `Refusal.conflict`. */
|
|
392
|
-
isConflict: <I>(input: I) => input is I & {
|
|
393
|
-
readonly _tag: "Conflict";
|
|
394
|
-
};
|
|
395
|
-
/** Whether a refusal, of whatever mutation, is `Refusal.unmet`. */
|
|
396
|
-
isUnmet: <I>(input: I) => input is I & {
|
|
397
|
-
readonly _tag: "Unmet";
|
|
398
|
-
};
|
|
399
|
-
/** Whether a refusal, of whatever mutation, is `Refusal.invalid`. */
|
|
400
|
-
isInvalid: <I>(input: I) => input is I & {
|
|
401
|
-
readonly _tag: "Invalid";
|
|
402
|
-
readonly rule: Option.Option<string>;
|
|
403
|
-
readonly message: string;
|
|
404
|
-
readonly path: readonly string[];
|
|
405
|
-
};
|
|
406
|
-
/**
|
|
407
|
-
* Whether a refusal is `Refusal.invalid` naming this invariant: the one
|
|
408
|
-
* `Entity.invariant` returned, or one `Entity.invariants` reads. An invariant
|
|
409
|
-
* over a member hidden from the asker names none, so it matches nothing.
|
|
410
|
-
*/
|
|
411
|
-
isInvalidBy: (refusal: unknown, invariant: Pick<Invariant, 'id'>) => boolean;
|
|
412
|
-
};
|
|
413
|
-
/**
|
|
414
|
-
* What a declared write may be refused with: unmet too, when it has a `when`,
|
|
415
|
-
* and invalid always, since the server's Entity may hold invariants the
|
|
416
|
-
* client's does not show.
|
|
417
|
-
*/
|
|
418
|
-
type RefusalOfWrite<W> = (W extends ConditionedWrite<any, any> ? typeof conflict.Type | typeof unmet.Type : typeof conflict.Type) | typeof invalid.Type;
|
|
419
|
-
/** A codec, or the fields of a `Schema.Struct` where one is expected. */
|
|
420
|
-
type SchemaOrFields = Schema.Codec<any, any, any, any> | Schema.Struct.Fields;
|
|
421
|
-
/** The decoded type of a codec, or of the Struct the fields describe. */
|
|
422
|
-
type TypeOf<S extends SchemaOrFields> = S extends Schema.Codec<infer T, any, any, any> ? T : S extends Schema.Struct.Fields ? Schema.Struct.Type<S> : never;
|
|
423
|
-
/** The codec itself, or a `Schema.Struct` over the fields. */
|
|
424
|
-
declare const schemaOf: <S extends SchemaOrFields>(shape: S) => Schema.Codec<TypeOf<S>>;
|
|
425
|
-
/**
|
|
426
|
-
* A bound write as the store patches it: its fields as they are, and each
|
|
427
|
-
* relation it points as the ref key the store holds (`'User:u1'`), or null.
|
|
428
|
-
*/
|
|
429
|
-
declare const patchOfWrite: (bound: BoundWrite) => NormalizedPatch;
|
|
430
|
-
/**
|
|
431
|
-
* What a declared write shows before the server answers: an update's or an
|
|
432
|
-
* insert's row as a patch (an update's only for the keys named, when some
|
|
433
|
-
* are), and an update's increments as amounts over the value the store holds. A delete shows nothing, since no operation removes a row from every
|
|
434
|
-
* list it is in; its answer does.
|
|
435
|
-
*/
|
|
436
|
-
declare const optimisticOfWrite: (write: AnyWrite, input: unknown, keys: ReadonlyArray<string> | undefined) => ReadonlyArray<PendingPatch>;
|
|
437
|
-
declare const Mutation: {
|
|
438
|
-
/**
|
|
439
|
-
* Declares a mutation. `Input` and `Output` are codecs, or the fields of the
|
|
440
|
-
* `Schema.Struct` they would be (`{ id: ProjectId, name: Schema.String }`).
|
|
441
|
-
* `Refusal`, when given, is what the server may refuse with: a codec, usually
|
|
442
|
-
* a union of `Refusal.field(...)` and `Refusal.conflict`.
|
|
443
|
-
*/
|
|
444
|
-
/**
|
|
445
|
-
* A mutation that is a declared `Write` (`update`, `insert` or `delete`): its
|
|
446
|
-
* input is the write's, and it answers nothing but the row it changed, as a
|
|
447
|
-
* patch, or its deletion. It may be refused as a conflict, for a write that
|
|
448
|
-
* `expect`s a revision the row has moved past, for a write with a `when` as
|
|
449
|
-
* unmet, and as invalid when the row it would leave breaks an invariant.
|
|
450
|
-
*/
|
|
451
|
-
write: <const Name extends string, Fields extends Schema.Struct.Fields, W extends Write<any, Fields> = Write<any, Fields>>(name: Name, write: W & Write<any, Fields>) => MutationDescriptor<Name, Schema.Struct.Type<Fields>, {}, RefusalOfWrite<W>> & {
|
|
452
|
-
readonly write: W;
|
|
453
|
-
};
|
|
454
|
-
make: <const Name extends string, Input extends SchemaOrFields, Output extends SchemaOrFields, Refused = never>(name: Name, config: {
|
|
455
|
-
readonly Input: Input;
|
|
456
|
-
readonly Output: Output;
|
|
457
|
-
readonly Refusal?: Schema.Codec<Refused, any>;
|
|
458
|
-
}) => MutationDescriptor<Name, TypeOf<Input>, TypeOf<Output>, Refused>;
|
|
459
|
-
};
|
|
460
|
-
interface EntityLayer {
|
|
461
|
-
readonly id: string;
|
|
462
|
-
readonly patches: ReadonlyArray<PendingPatch>;
|
|
463
|
-
}
|
|
464
|
-
/**
|
|
465
|
-
* Edges placed outside a connection's server-known region (`prepend`,
|
|
466
|
-
* `append`) or hidden from it (`remove`), owned by the request or live event
|
|
467
|
-
* that produced them.
|
|
468
|
-
*/
|
|
469
|
-
interface ConnectionOverlay {
|
|
470
|
-
readonly id: string;
|
|
471
|
-
readonly connection: string;
|
|
472
|
-
readonly edges: ReadonlyArray<Edge>;
|
|
473
|
-
readonly position: 'prepend' | 'append' | 'remove';
|
|
474
|
-
}
|
|
475
|
-
/** A connection change a request makes optimistically or a mutation result confirms. */
|
|
476
|
-
type ConnectionChange = {
|
|
477
|
-
readonly _tag: 'Insert';
|
|
478
|
-
readonly connection: string;
|
|
479
|
-
readonly position: 'prepend' | 'append';
|
|
480
|
-
readonly edge: Edge;
|
|
481
|
-
} | {
|
|
482
|
-
readonly _tag: 'Remove';
|
|
483
|
-
readonly connection: string;
|
|
484
|
-
readonly edge: Edge;
|
|
485
|
-
};
|
|
486
|
-
/** What a request changes before the server answers: entity patches and connection changes. */
|
|
487
|
-
type OptimisticOperation = PendingPatch | ConnectionChange;
|
|
488
|
-
/** A connection, by identity string or by anything that carries one (a `QueryRef`). */
|
|
489
|
-
type ConnectionIdentity = string | {
|
|
490
|
-
readonly identity: string;
|
|
491
|
-
};
|
|
492
|
-
declare const connectionIdentity: (connection: ConnectionIdentity) => string;
|
|
493
|
-
/**
|
|
494
|
-
* Constructors for connection changes: what a request shows optimistically
|
|
495
|
-
* (`MutateOptions.optimistic`) and what a mutation source reports it made
|
|
496
|
-
* (`MutationOutcome.connections`).
|
|
497
|
-
*/
|
|
498
|
-
declare const ConnectionChange: {
|
|
499
|
-
/** Show `ref` at the front of the connection until the request settles. */
|
|
500
|
-
prepend: (connection: ConnectionIdentity, ref: {
|
|
501
|
-
readonly entity: string;
|
|
502
|
-
readonly id: string;
|
|
503
|
-
}) => ConnectionChange;
|
|
504
|
-
/** Show `ref` at the end of the connection until the request settles. */
|
|
505
|
-
append: (connection: ConnectionIdentity, ref: {
|
|
506
|
-
readonly entity: string;
|
|
507
|
-
readonly id: string;
|
|
508
|
-
}) => ConnectionChange;
|
|
509
|
-
/** Hide `ref` from the connection until the request settles. */
|
|
510
|
-
remove: (connection: ConnectionIdentity, ref: {
|
|
511
|
-
readonly entity: string;
|
|
512
|
-
readonly id: string;
|
|
513
|
-
}) => ConnectionChange;
|
|
514
|
-
};
|
|
515
|
-
/**
|
|
516
|
-
* Applies a request's operations: its patches become one layer and its
|
|
517
|
-
* connection changes become overlays, all owned by `requestId` so settling
|
|
518
|
-
* removes every one of them together.
|
|
519
|
-
*/
|
|
520
|
-
declare const beginOptimistic: (optimistic: OptimisticState, requestId: string, operations: ReadonlyArray<OptimisticOperation>) => OptimisticState;
|
|
521
|
-
/** Pending entity layers and connection overlays over the base store. */
|
|
522
|
-
interface OptimisticState {
|
|
523
|
-
readonly layers: ReadonlyArray<EntityLayer>;
|
|
524
|
-
readonly overlays: ReadonlyArray<ConnectionOverlay>;
|
|
525
|
-
}
|
|
526
|
-
declare const emptyOptimistic: OptimisticState;
|
|
527
|
-
declare const addLayer: (optimistic: OptimisticState, layer: EntityLayer) => OptimisticState;
|
|
528
|
-
declare const removeLayer: (optimistic: OptimisticState, id: string) => OptimisticState;
|
|
529
|
-
declare const addOverlay: (optimistic: OptimisticState, overlay: ConnectionOverlay) => OptimisticState;
|
|
530
|
-
declare const removeOverlay: (optimistic: OptimisticState, id: string) => OptimisticState;
|
|
531
|
-
/**
|
|
532
|
-
* Base store with every layer applied in order. Later layers win. A patch is
|
|
533
|
-
* not news from the server, so it keeps the date of the value under it; an
|
|
534
|
-
* entity only a request holds (a temporary id) is not the server's to age, and
|
|
535
|
-
* is dated `Infinity`, so freshness never plans or times it.
|
|
536
|
-
*/
|
|
537
|
-
declare const visibleStore: (base: EntityStore, optimistic: OptimisticState) => EntityStore;
|
|
538
|
-
/**
|
|
539
|
-
* Every pending patch in order, each amount added to the value under it: the
|
|
540
|
-
* store's, or an earlier layer's. A prediction, so only over a number the
|
|
541
|
-
* client holds: a field it has not read, or holds as anything else, keeps
|
|
542
|
-
* what it shows until the server answers with the sum.
|
|
543
|
-
*/
|
|
544
|
-
declare const resolvedPatches: (base: EntityStore, optimistic: OptimisticState) => ReadonlyArray<NormalizedPatch>;
|
|
545
|
-
/**
|
|
546
|
-
* A fresh page is newer than any settled overlay it covers: an edge the page
|
|
547
|
-
* carries no longer needs an insert overlay, and a `remove` overlay hiding it
|
|
548
|
-
* is stale (the server says it is back). A pending request's overlays are
|
|
549
|
-
* left alone; they settle with the request.
|
|
550
|
-
*/
|
|
551
|
-
declare const pruneOverlays: (optimistic: OptimisticState, connection: string, covered: ReadonlySet<string>, pending: ReadonlySet<string>) => OptimisticState;
|
|
552
|
-
/**
|
|
553
|
-
* Applies a result idempotently and releases the request's layer and overlays:
|
|
554
|
-
* a later layer re-wins on rebase. Confirmed connection changes are recorded
|
|
555
|
-
* once per request, as overlays the request no longer owns.
|
|
556
|
-
*/
|
|
557
|
-
declare const settleSuccess: (base: EntityStore, optimistic: OptimisticState, state: MutationState, requestId: string, answer: MutationAnswer & {
|
|
558
|
-
/** Connection changes the server confirmed; they replace the request's own. */
|
|
559
|
-
readonly connections?: ReadonlyArray<ConnectionChange> | undefined;
|
|
560
|
-
}) => {
|
|
561
|
-
readonly store: EntityStore;
|
|
562
|
-
readonly state: MutationState;
|
|
563
|
-
readonly optimistic: OptimisticState;
|
|
564
|
-
};
|
|
565
|
-
/** A failed request's layer and overlays are dropped; the base was never mutated. */
|
|
566
|
-
declare const settleFailure: (optimistic: OptimisticState, requestId: string) => OptimisticState;
|
|
567
|
-
/**
|
|
568
|
-
* Visible edges for one connection: applicable overlays are placed outside the
|
|
569
|
-
* server-known segments and de-duplicated by edge identity (across overlays too),
|
|
570
|
-
* so a pending insert never corrupts server-known ordering; a `remove` overlay
|
|
571
|
-
* hides its edges wherever they are, and so does a tombstone on the edge's
|
|
572
|
-
* target when `store` is given. A later prepend lands before an earlier one, a
|
|
573
|
-
* later append after, so pending inserts read in the order they were made.
|
|
574
|
-
* Boundaries still come from the connection's segments.
|
|
575
|
-
*/
|
|
576
|
-
declare const visibleItems: (connection: Connection, connectionId: string, overlays: ReadonlyArray<ConnectionOverlay>, store?: EntityStore) => ReadonlyArray<Edge>;
|
|
577
|
-
type LiveInsertion = 'visible' | 'boundary' | 'invalidate' | 'ignore';
|
|
578
|
-
interface LivePolicy {
|
|
579
|
-
readonly prepend?: LiveInsertion;
|
|
580
|
-
readonly append?: LiveInsertion;
|
|
581
|
-
}
|
|
582
|
-
interface ConnectionSpec<Entity extends string = string> {
|
|
583
|
-
readonly entity: Entity;
|
|
584
|
-
readonly edgeKey?: Schema.Schema<unknown>;
|
|
585
|
-
readonly live?: LivePolicy;
|
|
586
|
-
}
|
|
587
|
-
interface QueryWindow {
|
|
588
|
-
readonly first?: number | undefined;
|
|
589
|
-
readonly last?: number | undefined;
|
|
590
|
-
readonly after?: Cursor | undefined;
|
|
591
|
-
readonly before?: Cursor | undefined;
|
|
592
|
-
}
|
|
593
|
-
interface QueryRef<Name extends string, Input> {
|
|
594
|
-
readonly query: Name;
|
|
595
|
-
readonly input: Input;
|
|
596
|
-
/** The input codec, so a `QueryRef` can encode itself without its descriptor. */
|
|
597
|
-
readonly Input: Schema.Codec<Input>;
|
|
598
|
-
readonly window: QueryWindow;
|
|
599
|
-
/** Connection identity: descriptor + canonical input, excluding the window. */
|
|
600
|
-
readonly identity: string;
|
|
601
|
-
}
|
|
602
|
-
interface QueryDescriptor<Name extends string, Input, Result> {
|
|
603
|
-
readonly name: Name;
|
|
604
|
-
readonly Input: Schema.Codec<Input>;
|
|
605
|
-
readonly Result: Result;
|
|
606
|
-
readonly ref: (input: Input) => QueryRef<Name, Input>;
|
|
607
|
-
/**
|
|
608
|
-
* What the query means, when it was declared with `Query.define`: the rows it
|
|
609
|
-
* is about, as a value an interpreter can compile. A descriptor from
|
|
610
|
-
* `Query.make` has none — its meaning lives in whatever the server registered
|
|
611
|
-
* to answer it — and a source is free to answer either.
|
|
612
|
-
*/
|
|
613
|
-
readonly body?: AnyQuery | undefined;
|
|
614
|
-
}
|
|
615
|
-
/**
|
|
616
|
-
* The inputs of a definition's body: one placeholder per key of `Input`, typed
|
|
617
|
-
* as that key's value. A body is built once, so these stand for what the query
|
|
618
|
-
* will be given rather than being it.
|
|
619
|
-
*/
|
|
620
|
-
type QueryInputs<Input> = { readonly [K in keyof Input & string]: InputExpr<Input[K]>; };
|
|
621
|
-
/**
|
|
622
|
-
* What separates a query's name from its canonical encoded input in a
|
|
623
|
-
* connection identity.
|
|
624
|
-
*
|
|
625
|
-
* NUL, because `JSON.stringify` escapes it inside a string (`\u0000`) and a
|
|
626
|
-
* query name is a TypeScript identifier — so the first occurrence is always the
|
|
627
|
-
* boundary, and a name or an input value cannot forge one. Anything recovering
|
|
628
|
-
* the query from an identity splits here.
|
|
629
|
-
*/
|
|
630
|
-
declare const IDENTITY_SEPARATOR = "\0";
|
|
631
|
-
/** Stable stringify: object keys sorted, undefined-valued keys dropped, so equal inputs encode equally. */
|
|
632
|
-
declare const stableStringify: (value: unknown) => string;
|
|
633
|
-
/**
|
|
634
|
-
* `Result: Project` (or anything with the entity's `name`, as `Query.connection`
|
|
635
|
-
* takes) means a connection over it; a `ConnectionSpec` names its `entity`
|
|
636
|
-
* instead and is the result as given.
|
|
637
|
-
*/
|
|
638
|
-
type ResultOf<Result> = Result extends {
|
|
639
|
-
readonly name: infer Entity extends string;
|
|
640
|
-
} ? ConnectionSpec<Entity> : Result;
|
|
641
|
-
/** A relational `Query` over one Entity, as `Query.define`'s body returns. */
|
|
642
|
-
type RelationalQueryOf<E extends AnyEntity> = ReturnType<typeof Query.from<E>>;
|
|
643
|
-
declare const Query$1: {
|
|
644
|
-
from: <E extends AnyEntity>(entity: E) => Query<E>;
|
|
645
|
-
where: <const P extends ReadonlyArray<import("foldkit-entity").Predicate>>(...predicates: P) => <E extends AnyEntity>(self: Query<E> & (string extends import("foldkit-entity").ReadsOf<P[number]> ? unknown : [import("foldkit-entity").ReadsOf<P[number]>] extends [E["name"]] ? unknown : import("foldkit-entity").Invalid<`foldkit-entity: a predicate reads ${Exclude<import("foldkit-entity").ReadsOf<P[number]>, E["name"]>}, but the query is from ${E["name"]}`>)) => Query<E>;
|
|
646
|
-
orderBy: <const T extends ReadonlyArray<import("foldkit-entity").Ordering>>(...terms: T) => <E extends AnyEntity>(self: Query<E> & (string extends import("foldkit-entity").ReadsOf<T[number]> ? unknown : [import("foldkit-entity").ReadsOf<T[number]>] extends [E["name"]] ? unknown : import("foldkit-entity").Invalid<`foldkit-entity: an ordering term reads ${Exclude<import("foldkit-entity").ReadsOf<T[number]>, E["name"]>}, but the query is from ${E["name"]}`>)) => Query<E>;
|
|
647
|
-
orderFor: (self: AnyQuery, input: Readonly<Record<string, unknown>>) => ReadonlyArray<import("foldkit-entity").OrderTerm>;
|
|
648
|
-
placement: (self: AnyQuery, input: Readonly<Record<string, unknown>>, options?: {
|
|
649
|
-
readonly operators?: import("foldkit-entity").OperatorTable | undefined;
|
|
650
|
-
}) => import("foldkit-entity").Placement;
|
|
651
|
-
dependencies: (self: AnyQuery) => import("foldkit-entity").QueryDependencies;
|
|
652
|
-
unsupported: (self: AnyQuery, supported: ReadonlyArray<import("foldkit-entity").Operation>, operators?: import("foldkit-entity").OperatorTable) => ReadonlyArray<string>;
|
|
653
|
-
show: (self: AnyQuery) => string;
|
|
654
|
-
/** Declares the entity and options a query's result is a connection over. */
|
|
655
|
-
connection: <Entity extends string>(entity: {
|
|
656
|
-
readonly name: Entity;
|
|
657
|
-
}, options?: {
|
|
658
|
-
readonly edgeKey?: Schema.Schema<unknown>;
|
|
659
|
-
readonly live?: LivePolicy;
|
|
660
|
-
}) => ConnectionSpec<Entity>;
|
|
661
|
-
/**
|
|
662
|
-
* Declares a query. `Input` is a codec or the fields of the `Schema.Struct` it
|
|
663
|
-
* would be; `Result` is a `Query.connection(...)`, or the entity the result is
|
|
664
|
-
* a connection over.
|
|
665
|
-
*/
|
|
666
|
-
make: <const Name extends string, Input extends SchemaOrFields, Result>(name: Name, config: {
|
|
667
|
-
readonly Input: Input;
|
|
668
|
-
readonly Result: Result;
|
|
669
|
-
}) => QueryDescriptor<Name, TypeOf<Input>, ResultOf<Result>>;
|
|
670
|
-
/**
|
|
671
|
-
* Declares a query by what it means. The body is built once, here, and the
|
|
672
|
-
* `input` it is given holds placeholders rather than values — there is
|
|
673
|
-
* nothing yet to branch on, so a condition that depends on what was passed is
|
|
674
|
-
* a comparison over the placeholder:
|
|
675
|
-
*
|
|
676
|
-
* ```ts
|
|
677
|
-
* const PostsBySlug = Query.define('PostsBySlug', { slug: Schema.String }, ({ input }) =>
|
|
678
|
-
* Query.from(Post).pipe(
|
|
679
|
-
* Query.where(Expr.eq(Post.fields.slug, input.slug)),
|
|
680
|
-
* Query.orderBy(Order.asc(Post.fields.id)),
|
|
681
|
-
* ),
|
|
682
|
-
* )
|
|
683
|
-
* ```
|
|
684
|
-
*
|
|
685
|
-
* What comes back is an ordinary `QueryDescriptor` — the same name, `Input`,
|
|
686
|
-
* `ref` and connection identity `Query.make` gives — carrying its `body`
|
|
687
|
-
* besides. A server can compile that body instead of being told the same
|
|
688
|
-
* thing again in its own dialect, and one that would rather answer the query
|
|
689
|
-
* its own way still can.
|
|
690
|
-
*
|
|
691
|
-
* The result is a connection over the Entity the body reads, so it is not
|
|
692
|
-
* named twice.
|
|
693
|
-
*/
|
|
694
|
-
define: <const Name extends string, Input extends SchemaOrFields, E extends AnyEntity>(name: Name, Input: Input, body: (context: {
|
|
695
|
-
readonly input: QueryInputs<TypeOf<Input>>;
|
|
696
|
-
}) => RelationalQueryOf<E>, options?: {
|
|
697
|
-
readonly edgeKey?: Schema.Schema<unknown>;
|
|
698
|
-
readonly live?: LivePolicy;
|
|
699
|
-
}) => QueryDescriptor<Name, TypeOf<Input>, ConnectionSpec<E['name']>>;
|
|
700
|
-
first: (count: number) => <R extends QueryRef<string, unknown>>(ref: R) => R;
|
|
701
|
-
last: (count: number) => <R extends QueryRef<string, unknown>>(ref: R) => R;
|
|
702
|
-
after: (cursor: Cursor) => <R extends QueryRef<string, unknown>>(ref: R) => R;
|
|
703
|
-
before: (cursor: Cursor) => <R extends QueryRef<string, unknown>>(ref: R) => R;
|
|
704
|
-
};
|
|
705
|
-
/**
|
|
706
|
-
* The slice required of an entity. `windows` carries a pagination window per
|
|
707
|
-
* relation field, and `relations` the slice required of each relation's
|
|
708
|
-
* target, so one requirement describes a whole selection graph.
|
|
709
|
-
*/
|
|
710
|
-
interface RelationRequirement {
|
|
711
|
-
readonly entity: string;
|
|
712
|
-
readonly fields: readonly string[];
|
|
713
|
-
readonly windows?: Readonly<Record<string, QueryWindow>> | undefined;
|
|
714
|
-
readonly relations?: Readonly<Record<string, RelationRequirement>> | undefined;
|
|
715
|
-
}
|
|
716
|
-
interface Requirement extends RelationRequirement {
|
|
717
|
-
readonly id: string;
|
|
718
|
-
/** The projection also subscribes to changes of this entity (`Data.live`). */
|
|
719
|
-
readonly live?: boolean | undefined;
|
|
720
|
-
}
|
|
721
|
-
/**
|
|
722
|
-
* A query connection a projection reads: the page it first asks for and the
|
|
723
|
-
* slice it selects of each item. `identity` is the connection's (query plus
|
|
724
|
-
* canonical input, excluding the window).
|
|
725
|
-
*/
|
|
726
|
-
interface ConnectionRequirement {
|
|
727
|
-
readonly identity: string;
|
|
728
|
-
readonly window: QueryWindow;
|
|
729
|
-
readonly select: RelationRequirement;
|
|
730
|
-
}
|
|
731
|
-
/**
|
|
732
|
-
* Merges connection requirements for the same connection and window into one,
|
|
733
|
-
* unioning what they select of each item; the first keeps its other properties.
|
|
734
|
-
*/
|
|
735
|
-
declare function mergeConnections(connections: readonly ConnectionRequirement[]): readonly ConnectionRequirement[];
|
|
736
|
-
/** Unions two relation slices for the same target: fields, windows, and nested relations. */
|
|
737
|
-
declare function mergeRelation(current: RelationRequirement, next: RelationRequirement): RelationRequirement;
|
|
738
|
-
/** Unions requirements for the same entity + id, dropping duplicate fields. */
|
|
739
|
-
declare function mergeRequirements(requirements: readonly Requirement[]): readonly Requirement[];
|
|
740
|
-
/**
|
|
741
|
-
* Requirement helpers, for the packages that plan and serve requirements.
|
|
742
|
-
* `merge` unions same-entity+id requirements; `mergeRelation` unions two
|
|
743
|
-
* slices of one target (fields, windows, nested relations).
|
|
744
|
-
*/
|
|
745
|
-
declare const Requirement: {
|
|
746
|
-
merge: typeof mergeRequirements;
|
|
747
|
-
mergeRelation: typeof mergeRelation;
|
|
748
|
-
mergeConnections: typeof mergeConnections;
|
|
749
|
-
};
|
|
750
|
-
/** Remote's entity requirements on a Projection, unioned per entity and id as nodes compose. */
|
|
751
|
-
declare const RemoteRequirements: import("foldkit-metadata").MetadataKey<Requirement>;
|
|
752
|
-
/** Remote's query connections on a Projection, unioned per connection and window. */
|
|
753
|
-
declare const RemoteConnections: import("foldkit-metadata").MetadataKey<ConnectionRequirement>;
|
|
754
|
-
/** The entity requirements a Projection carries. */
|
|
755
|
-
declare const requirementsOf: (projection: {
|
|
756
|
-
readonly metadata: Metadata;
|
|
757
|
-
}) => ReadonlyArray<Requirement>;
|
|
758
|
-
/** The query connections a Projection carries. */
|
|
759
|
-
declare const connectionsOf: (projection: {
|
|
760
|
-
readonly metadata: Metadata;
|
|
761
|
-
}) => ReadonlyArray<ConnectionRequirement>;
|
|
762
|
-
/**
|
|
763
|
-
* The read/live protocol version. A batch names the version it speaks and the
|
|
764
|
-
* server refuses a mismatch with `RemoteProtocolError`, so a shape change never
|
|
765
|
-
* drifts silently: bump it whenever `ReadRequest` or `LiveRequirement` change.
|
|
766
|
-
*/
|
|
767
|
-
declare const REMOTE_PROTOCOL_VERSION = 4;
|
|
768
|
-
declare const RemoteReadError_base: Schema.Class<RemoteReadError, Schema.TaggedStruct<"RemoteReadError", {
|
|
769
|
-
readonly message: Schema.String;
|
|
770
|
-
}>, import("effect/Cause").YieldableError>;
|
|
771
|
-
declare class RemoteReadError extends RemoteReadError_base {}
|
|
772
|
-
declare const RemoteMutationError_base: Schema.Class<RemoteMutationError, Schema.TaggedStruct<"RemoteMutationError", {
|
|
773
|
-
readonly message: Schema.String;
|
|
774
|
-
/** The mutation's own `Refusal`, encoded, when the server refused it as one. */
|
|
775
|
-
readonly refusal: Schema.optional<Schema.Unknown>;
|
|
776
|
-
}>, import("effect/Cause").YieldableError>;
|
|
777
|
-
declare class RemoteMutationError extends RemoteMutationError_base {}
|
|
778
|
-
declare const RemoteForbidden_base: Schema.Class<RemoteForbidden, Schema.TaggedStruct<"Forbidden", {
|
|
779
|
-
readonly message: Schema.String;
|
|
780
|
-
readonly reason: Schema.optional<Schema.String>;
|
|
781
|
-
}>, import("effect/Cause").YieldableError>;
|
|
782
|
-
/**
|
|
783
|
-
* The server refused who is asking: they may not do this, and asking again
|
|
784
|
-
* as the same principal is refused again. `reason` is the application's own
|
|
785
|
-
* words for the person who asked; without it the refusal says nothing of why.
|
|
786
|
-
*/
|
|
787
|
-
declare class RemoteForbidden extends RemoteForbidden_base {}
|
|
788
|
-
declare const RemoteUnauthenticated_base: Schema.Class<RemoteUnauthenticated, Schema.TaggedStruct<"Unauthenticated", {
|
|
789
|
-
readonly message: Schema.String;
|
|
790
|
-
readonly reason: Schema.optional<Schema.String>;
|
|
791
|
-
}>, import("effect/Cause").YieldableError>;
|
|
792
|
-
/**
|
|
793
|
-
* The server could not tell who is asking: a credential was sent and no
|
|
794
|
-
* longer holds, or none was sent where one is needed. Asking again as the
|
|
795
|
-
* same caller is refused again; signing in again is the remedy. `reason` is
|
|
796
|
-
* words for the person who asked; without it the refusal says nothing of why.
|
|
797
|
-
*/
|
|
798
|
-
declare class RemoteUnauthenticated extends RemoteUnauthenticated_base {}
|
|
799
|
-
declare const RemoteLiveError_base: Schema.Class<RemoteLiveError, Schema.TaggedStruct<"RemoteLiveError", {
|
|
800
|
-
readonly message: Schema.String;
|
|
801
|
-
}>, import("effect/Cause").YieldableError>;
|
|
802
|
-
declare class RemoteLiveError extends RemoteLiveError_base {}
|
|
803
|
-
declare const RemoteProtocolError_base: Schema.Class<RemoteProtocolError, Schema.TaggedStruct<"RemoteProtocolError", {
|
|
804
|
-
readonly message: Schema.String;
|
|
805
|
-
readonly expected: Schema.Number;
|
|
806
|
-
readonly received: Schema.Number;
|
|
807
|
-
}>, import("effect/Cause").YieldableError>;
|
|
808
|
-
/** The peer speaks another protocol version; nothing was read. */
|
|
809
|
-
declare class RemoteProtocolError extends RemoteProtocolError_base {}
|
|
810
|
-
/** A page size: a non-negative integer, refused at decode otherwise rather than defaulted. */
|
|
811
|
-
declare const PageSize: Schema.Number;
|
|
812
|
-
declare const WindowSchema: Schema.Struct<{
|
|
813
|
-
readonly first: Schema.optional<Schema.Number>;
|
|
814
|
-
readonly last: Schema.optional<Schema.Number>;
|
|
815
|
-
readonly after: Schema.optional<Schema.String>;
|
|
816
|
-
readonly before: Schema.optional<Schema.String>;
|
|
817
|
-
}>;
|
|
818
|
-
/** A request may not name more fields of one entity than this; a selection never does. */
|
|
819
|
-
declare const MAX_FIELDS_PER_REQUEST = 256;
|
|
820
|
-
/** A selection may not nest relations deeper than this; the wire refuses more. */
|
|
821
|
-
declare const MAX_RELATION_DEPTH = 8;
|
|
822
|
-
declare const RelationRequest: Schema.Codec<RelationRequirement, RelationRequirement, never, never>;
|
|
823
|
-
declare const ReadRequest: Schema.Codec<Requirement, Requirement>;
|
|
824
|
-
declare const ReadBatch: Schema.Struct<{
|
|
825
|
-
readonly version: Schema.Number;
|
|
826
|
-
readonly requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
827
|
-
}>;
|
|
828
|
-
declare const NormalizedEntity: Schema.Struct<{
|
|
829
|
-
readonly entity: Schema.String;
|
|
830
|
-
readonly id: Schema.String;
|
|
831
|
-
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
832
|
-
}>;
|
|
833
|
-
/**
|
|
834
|
-
* Fields a read asked for that the server answered without, and will not
|
|
835
|
-
* answer with: the client stops asking. It says nothing about why, so a rule
|
|
836
|
-
* that withholds a field is not itself on the wire.
|
|
837
|
-
*/
|
|
838
|
-
declare const SettledFields: Schema.Struct<{
|
|
839
|
-
readonly entity: Schema.String;
|
|
840
|
-
readonly id: Schema.String;
|
|
841
|
-
readonly fields: Schema.$Array<Schema.String>;
|
|
842
|
-
}>;
|
|
843
|
-
declare const ReadBatchResult: Schema.Struct<{
|
|
844
|
-
readonly entities: Schema.$Array<Schema.Struct<{
|
|
845
|
-
readonly entity: Schema.String;
|
|
846
|
-
readonly id: Schema.String;
|
|
847
|
-
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
848
|
-
}>>;
|
|
849
|
-
readonly settled: Schema.$Array<Schema.Struct<{
|
|
850
|
-
readonly entity: Schema.String;
|
|
851
|
-
readonly id: Schema.String;
|
|
852
|
-
readonly fields: Schema.$Array<Schema.String>;
|
|
853
|
-
}>>;
|
|
854
|
-
}>;
|
|
855
|
-
/**
|
|
856
|
-
* One operation's identity across every client: minted where it is first sent
|
|
857
|
-
* and sent again with each retry of it. Bounded, since a server keys a record
|
|
858
|
-
* of the write by it.
|
|
859
|
-
*/
|
|
860
|
-
declare const OperationId: Schema.String;
|
|
861
|
-
declare const MutationRequest: Schema.Struct<{
|
|
862
|
-
/**
|
|
863
|
-
* This client's id for the request, the same on each retry of it. It is
|
|
864
|
-
* unique within one client's Model only (a counter there), so it names a
|
|
865
|
-
* request to that client; `operation` names it to a server.
|
|
866
|
-
*/
|
|
867
|
-
readonly requestId: Schema.String;
|
|
868
|
-
/** The operation's identity across clients: what a server keys a record of the write by. */
|
|
869
|
-
readonly operation: Schema.optional<Schema.String>;
|
|
870
|
-
readonly mutation: Schema.String;
|
|
871
|
-
readonly input: Schema.Unknown;
|
|
872
|
-
/** For a mutation that is a `Write`: the input keys to write, when not all of them. */
|
|
873
|
-
readonly keys: Schema.optional<Schema.$Array<Schema.String>>;
|
|
874
|
-
}>;
|
|
875
|
-
declare const LiveEdge: Schema.Struct<{
|
|
876
|
-
readonly entity: Schema.String;
|
|
877
|
-
readonly id: Schema.String;
|
|
878
|
-
readonly key: Schema.String;
|
|
879
|
-
}>;
|
|
880
|
-
/** A connection change a mutation confirms: the same facts a live event carries, without a cursor. */
|
|
881
|
-
declare const ConnectionChangeSchema: Schema.Union<readonly [Schema.Struct<{
|
|
882
|
-
readonly _tag: Schema.Literal<"Insert">;
|
|
883
|
-
readonly connection: Schema.String;
|
|
884
|
-
readonly position: Schema.Union<readonly [Schema.Literal<"prepend">, Schema.Literal<"append">]>;
|
|
885
|
-
readonly edge: Schema.Struct<{
|
|
886
|
-
readonly entity: Schema.String;
|
|
887
|
-
readonly id: Schema.String;
|
|
888
|
-
readonly key: Schema.String;
|
|
889
|
-
}>;
|
|
890
|
-
}>, Schema.Struct<{
|
|
891
|
-
readonly _tag: Schema.Literal<"Remove">;
|
|
892
|
-
readonly connection: Schema.String;
|
|
893
|
-
readonly edge: Schema.Struct<{
|
|
894
|
-
readonly entity: Schema.String;
|
|
895
|
-
readonly id: Schema.String;
|
|
896
|
-
readonly key: Schema.String;
|
|
897
|
-
}>;
|
|
898
|
-
}>]>;
|
|
899
|
-
declare const MutationResult: Schema.Struct<{
|
|
900
|
-
readonly output: Schema.Unknown;
|
|
901
|
-
readonly entities: Schema.$Array<Schema.Struct<{
|
|
902
|
-
readonly entity: Schema.String;
|
|
903
|
-
readonly id: Schema.String;
|
|
904
|
-
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
905
|
-
}>>;
|
|
906
|
-
/** Connection changes the mutation made, applied alongside its entity patches. */
|
|
907
|
-
readonly connections: Schema.optional<Schema.$Array<Schema.Union<readonly [Schema.Struct<{
|
|
908
|
-
readonly _tag: Schema.Literal<"Insert">;
|
|
909
|
-
readonly connection: Schema.String;
|
|
910
|
-
readonly position: Schema.Union<readonly [Schema.Literal<"prepend">, Schema.Literal<"append">]>;
|
|
911
|
-
readonly edge: Schema.Struct<{
|
|
912
|
-
readonly entity: Schema.String;
|
|
913
|
-
readonly id: Schema.String;
|
|
914
|
-
readonly key: Schema.String;
|
|
915
|
-
}>;
|
|
916
|
-
}>, Schema.Struct<{
|
|
917
|
-
readonly _tag: Schema.Literal<"Remove">;
|
|
918
|
-
readonly connection: Schema.String;
|
|
919
|
-
readonly edge: Schema.Struct<{
|
|
920
|
-
readonly entity: Schema.String;
|
|
921
|
-
readonly id: Schema.String;
|
|
922
|
-
readonly key: Schema.String;
|
|
923
|
-
}>;
|
|
924
|
-
}>]>>>;
|
|
925
|
-
/** Entities the mutation deleted; the client knows them absent from then on. */
|
|
926
|
-
readonly deleted: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
927
|
-
readonly entity: Schema.String;
|
|
928
|
-
readonly id: Schema.String;
|
|
929
|
-
}>>>;
|
|
930
|
-
}>;
|
|
931
|
-
declare const LiveRequirement: Schema.Struct<{
|
|
932
|
-
readonly version: Schema.Number;
|
|
933
|
-
readonly requirements: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
934
|
-
/** Resume cursor; events at or before it are duplicates. */
|
|
935
|
-
readonly after: Schema.Number;
|
|
936
|
-
}>;
|
|
937
|
-
/**
|
|
938
|
-
* A live change. Entity changes update the store; connection changes alter
|
|
939
|
-
* membership and ordering; both carry a per-stream cursor.
|
|
940
|
-
*/
|
|
941
|
-
declare const LiveChange: Schema.Union<readonly [Schema.Struct<{
|
|
942
|
-
readonly _tag: Schema.Literal<"EntityPatched">;
|
|
943
|
-
readonly cursor: Schema.Number;
|
|
944
|
-
readonly entity: Schema.String;
|
|
945
|
-
readonly id: Schema.String;
|
|
946
|
-
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
947
|
-
readonly changed: Schema.$Array<Schema.String>;
|
|
948
|
-
}>, Schema.Struct<{
|
|
949
|
-
readonly _tag: Schema.Literal<"EntityDeleted">;
|
|
950
|
-
readonly cursor: Schema.Number;
|
|
951
|
-
readonly entity: Schema.String;
|
|
952
|
-
readonly id: Schema.String;
|
|
953
|
-
}>, Schema.Struct<{
|
|
954
|
-
readonly _tag: Schema.Literal<"ConnectionInsert">;
|
|
955
|
-
readonly cursor: Schema.Number;
|
|
956
|
-
readonly connection: Schema.String;
|
|
957
|
-
readonly position: Schema.Union<readonly [Schema.Literal<"prepend">, Schema.Literal<"append">]>;
|
|
958
|
-
readonly edge: Schema.Struct<{
|
|
959
|
-
readonly entity: Schema.String;
|
|
960
|
-
readonly id: Schema.String;
|
|
961
|
-
readonly key: Schema.String;
|
|
962
|
-
}>;
|
|
963
|
-
}>, Schema.Struct<{
|
|
964
|
-
readonly _tag: Schema.Literal<"ConnectionRemove">;
|
|
965
|
-
readonly cursor: Schema.Number;
|
|
966
|
-
readonly connection: Schema.String;
|
|
967
|
-
readonly edge: Schema.Struct<{
|
|
968
|
-
readonly entity: Schema.String;
|
|
969
|
-
readonly id: Schema.String;
|
|
970
|
-
readonly key: Schema.String;
|
|
971
|
-
}>;
|
|
972
|
-
}>, Schema.Struct<{
|
|
973
|
-
readonly _tag: Schema.Literal<"ConnectionInvalidate">;
|
|
974
|
-
readonly cursor: Schema.Number;
|
|
975
|
-
readonly connection: Schema.String;
|
|
976
|
-
}>]>;
|
|
977
|
-
declare const Read: Rpc.Rpc<"FoldkitRemoteRead", Schema.Struct<{
|
|
978
|
-
readonly version: Schema.Number;
|
|
979
|
-
readonly requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
980
|
-
}>, Schema.Struct<{
|
|
981
|
-
readonly entities: Schema.$Array<Schema.Struct<{
|
|
982
|
-
readonly entity: Schema.String;
|
|
983
|
-
readonly id: Schema.String;
|
|
984
|
-
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
985
|
-
}>>;
|
|
986
|
-
readonly settled: Schema.$Array<Schema.Struct<{
|
|
987
|
-
readonly entity: Schema.String;
|
|
988
|
-
readonly id: Schema.String;
|
|
989
|
-
readonly fields: Schema.$Array<Schema.String>;
|
|
990
|
-
}>>;
|
|
991
|
-
}>, Schema.Union<readonly [typeof RemoteReadError, typeof RemoteProtocolError, typeof RemoteUnauthenticated]>, never, never>;
|
|
992
|
-
declare const Mutate: Rpc.Rpc<"FoldkitRemoteMutate", Schema.Struct<{
|
|
993
|
-
/**
|
|
994
|
-
* This client's id for the request, the same on each retry of it. It is
|
|
995
|
-
* unique within one client's Model only (a counter there), so it names a
|
|
996
|
-
* request to that client; `operation` names it to a server.
|
|
997
|
-
*/
|
|
998
|
-
readonly requestId: Schema.String;
|
|
999
|
-
/** The operation's identity across clients: what a server keys a record of the write by. */
|
|
1000
|
-
readonly operation: Schema.optional<Schema.String>;
|
|
1001
|
-
readonly mutation: Schema.String;
|
|
1002
|
-
readonly input: Schema.Unknown;
|
|
1003
|
-
/** For a mutation that is a `Write`: the input keys to write, when not all of them. */
|
|
1004
|
-
readonly keys: Schema.optional<Schema.$Array<Schema.String>>;
|
|
1005
|
-
}>, Schema.Struct<{
|
|
1006
|
-
readonly output: Schema.Unknown;
|
|
1007
|
-
readonly entities: Schema.$Array<Schema.Struct<{
|
|
1008
|
-
readonly entity: Schema.String;
|
|
1009
|
-
readonly id: Schema.String;
|
|
1010
|
-
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
1011
|
-
}>>;
|
|
1012
|
-
/** Connection changes the mutation made, applied alongside its entity patches. */
|
|
1013
|
-
readonly connections: Schema.optional<Schema.$Array<Schema.Union<readonly [Schema.Struct<{
|
|
1014
|
-
readonly _tag: Schema.Literal<"Insert">;
|
|
1015
|
-
readonly connection: Schema.String;
|
|
1016
|
-
readonly position: Schema.Union<readonly [Schema.Literal<"prepend">, Schema.Literal<"append">]>;
|
|
1017
|
-
readonly edge: Schema.Struct<{
|
|
1018
|
-
readonly entity: Schema.String;
|
|
1019
|
-
readonly id: Schema.String;
|
|
1020
|
-
readonly key: Schema.String;
|
|
1021
|
-
}>;
|
|
1022
|
-
}>, Schema.Struct<{
|
|
1023
|
-
readonly _tag: Schema.Literal<"Remove">;
|
|
1024
|
-
readonly connection: Schema.String;
|
|
1025
|
-
readonly edge: Schema.Struct<{
|
|
1026
|
-
readonly entity: Schema.String;
|
|
1027
|
-
readonly id: Schema.String;
|
|
1028
|
-
readonly key: Schema.String;
|
|
1029
|
-
}>;
|
|
1030
|
-
}>]>>>;
|
|
1031
|
-
/** Entities the mutation deleted; the client knows them absent from then on. */
|
|
1032
|
-
readonly deleted: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
1033
|
-
readonly entity: Schema.String;
|
|
1034
|
-
readonly id: Schema.String;
|
|
1035
|
-
}>>>;
|
|
1036
|
-
}>, Schema.Union<readonly [typeof RemoteMutationError, typeof RemoteForbidden, typeof RemoteUnauthenticated]>, never, never>;
|
|
1037
|
-
declare const Live: Rpc.Rpc<"FoldkitRemoteLive", Schema.Struct<{
|
|
1038
|
-
readonly version: Schema.Number;
|
|
1039
|
-
readonly requirements: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
1040
|
-
/** Resume cursor; events at or before it are duplicates. */
|
|
1041
|
-
readonly after: Schema.Number;
|
|
1042
|
-
}>, import("effect/rpc/RpcSchema").Stream<Schema.Union<readonly [Schema.Struct<{
|
|
1043
|
-
readonly _tag: Schema.Literal<"EntityPatched">;
|
|
1044
|
-
readonly cursor: Schema.Number;
|
|
1045
|
-
readonly entity: Schema.String;
|
|
1046
|
-
readonly id: Schema.String;
|
|
1047
|
-
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
1048
|
-
readonly changed: Schema.$Array<Schema.String>;
|
|
1049
|
-
}>, Schema.Struct<{
|
|
1050
|
-
readonly _tag: Schema.Literal<"EntityDeleted">;
|
|
1051
|
-
readonly cursor: Schema.Number;
|
|
1052
|
-
readonly entity: Schema.String;
|
|
1053
|
-
readonly id: Schema.String;
|
|
1054
|
-
}>, Schema.Struct<{
|
|
1055
|
-
readonly _tag: Schema.Literal<"ConnectionInsert">;
|
|
1056
|
-
readonly cursor: Schema.Number;
|
|
1057
|
-
readonly connection: Schema.String;
|
|
1058
|
-
readonly position: Schema.Union<readonly [Schema.Literal<"prepend">, Schema.Literal<"append">]>;
|
|
1059
|
-
readonly edge: Schema.Struct<{
|
|
1060
|
-
readonly entity: Schema.String;
|
|
1061
|
-
readonly id: Schema.String;
|
|
1062
|
-
readonly key: Schema.String;
|
|
1063
|
-
}>;
|
|
1064
|
-
}>, Schema.Struct<{
|
|
1065
|
-
readonly _tag: Schema.Literal<"ConnectionRemove">;
|
|
1066
|
-
readonly cursor: Schema.Number;
|
|
1067
|
-
readonly connection: Schema.String;
|
|
1068
|
-
readonly edge: Schema.Struct<{
|
|
1069
|
-
readonly entity: Schema.String;
|
|
1070
|
-
readonly id: Schema.String;
|
|
1071
|
-
readonly key: Schema.String;
|
|
1072
|
-
}>;
|
|
1073
|
-
}>, Schema.Struct<{
|
|
1074
|
-
readonly _tag: Schema.Literal<"ConnectionInvalidate">;
|
|
1075
|
-
readonly cursor: Schema.Number;
|
|
1076
|
-
readonly connection: Schema.String;
|
|
1077
|
-
}>]>, Schema.Union<readonly [typeof RemoteLiveError, typeof RemoteProtocolError, typeof RemoteUnauthenticated]>>, Schema.Never, never, never>;
|
|
1078
|
-
declare const RemoteQueryError_base: Schema.Class<RemoteQueryError, Schema.TaggedStruct<"RemoteQueryError", {
|
|
1079
|
-
readonly message: Schema.String;
|
|
1080
|
-
}>, import("effect/Cause").YieldableError>;
|
|
1081
|
-
declare class RemoteQueryError extends RemoteQueryError_base {}
|
|
1082
|
-
declare const WireBoundary: Schema.Union<readonly [Schema.Struct<{
|
|
1083
|
-
readonly _tag: Schema.Literal<"Terminal">;
|
|
1084
|
-
}>, Schema.Struct<{
|
|
1085
|
-
readonly _tag: Schema.Literal<"Cursor">;
|
|
1086
|
-
readonly cursor: Schema.String;
|
|
1087
|
-
}>, Schema.Struct<{
|
|
1088
|
-
readonly _tag: Schema.Literal<"Unknown">;
|
|
1089
|
-
}>]>;
|
|
1090
|
-
declare const QueryRequest: Schema.Struct<{
|
|
1091
|
-
readonly query: Schema.String;
|
|
1092
|
-
readonly input: Schema.Unknown;
|
|
1093
|
-
readonly window: Schema.Struct<{
|
|
1094
|
-
readonly first: Schema.optional<Schema.Number>;
|
|
1095
|
-
readonly last: Schema.optional<Schema.Number>;
|
|
1096
|
-
readonly after: Schema.optional<Schema.String>;
|
|
1097
|
-
readonly before: Schema.optional<Schema.String>;
|
|
1098
|
-
}>;
|
|
1099
|
-
/**
|
|
1100
|
-
* What to read of each item, as the relation slice a read asks the server
|
|
1101
|
-
* for. Absent for a query run without one: the response carries only edges,
|
|
1102
|
-
* and the client's read entry fetches fields in a second round trip.
|
|
1103
|
-
*/
|
|
1104
|
-
readonly select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
1105
|
-
}>;
|
|
1106
|
-
declare const QueryEdge: Schema.Struct<{
|
|
1107
|
-
readonly entity: Schema.String;
|
|
1108
|
-
readonly id: Schema.String;
|
|
1109
|
-
readonly key: Schema.String;
|
|
1110
|
-
}>;
|
|
1111
|
-
declare const QueryResult: Schema.Struct<{
|
|
1112
|
-
readonly edges: Schema.$Array<Schema.Struct<{
|
|
1113
|
-
readonly entity: Schema.String;
|
|
1114
|
-
readonly id: Schema.String;
|
|
1115
|
-
readonly key: Schema.String;
|
|
1116
|
-
}>>;
|
|
1117
|
-
readonly start: Schema.Union<readonly [Schema.Struct<{
|
|
1118
|
-
readonly _tag: Schema.Literal<"Terminal">;
|
|
1119
|
-
}>, Schema.Struct<{
|
|
1120
|
-
readonly _tag: Schema.Literal<"Cursor">;
|
|
1121
|
-
readonly cursor: Schema.String;
|
|
1122
|
-
}>, Schema.Struct<{
|
|
1123
|
-
readonly _tag: Schema.Literal<"Unknown">;
|
|
1124
|
-
}>]>;
|
|
1125
|
-
readonly end: Schema.Union<readonly [Schema.Struct<{
|
|
1126
|
-
readonly _tag: Schema.Literal<"Terminal">;
|
|
1127
|
-
}>, Schema.Struct<{
|
|
1128
|
-
readonly _tag: Schema.Literal<"Cursor">;
|
|
1129
|
-
readonly cursor: Schema.String;
|
|
1130
|
-
}>, Schema.Struct<{
|
|
1131
|
-
readonly _tag: Schema.Literal<"Unknown">;
|
|
1132
|
-
}>]>;
|
|
1133
|
-
/**
|
|
1134
|
-
* The selected fields of the page's items, in the same shape a read batch
|
|
1135
|
-
* returns. Absent from a server that predates payload planning: the client
|
|
1136
|
-
* reads it as empty and fetches fields as before.
|
|
1137
|
-
*/
|
|
1138
|
-
readonly entities: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
1139
|
-
readonly entity: Schema.String;
|
|
1140
|
-
readonly id: Schema.String;
|
|
1141
|
-
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
1142
|
-
}>>>;
|
|
1143
|
-
readonly settled: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
1144
|
-
readonly entity: Schema.String;
|
|
1145
|
-
readonly id: Schema.String;
|
|
1146
|
-
readonly fields: Schema.$Array<Schema.String>;
|
|
1147
|
-
}>>>;
|
|
1148
|
-
}>;
|
|
1149
|
-
declare const QueryRpc: Rpc.Rpc<"FoldkitRemoteQuery", Schema.Struct<{
|
|
1150
|
-
readonly query: Schema.String;
|
|
1151
|
-
readonly input: Schema.Unknown;
|
|
1152
|
-
readonly window: Schema.Struct<{
|
|
1153
|
-
readonly first: Schema.optional<Schema.Number>;
|
|
1154
|
-
readonly last: Schema.optional<Schema.Number>;
|
|
1155
|
-
readonly after: Schema.optional<Schema.String>;
|
|
1156
|
-
readonly before: Schema.optional<Schema.String>;
|
|
1157
|
-
}>;
|
|
1158
|
-
/**
|
|
1159
|
-
* What to read of each item, as the relation slice a read asks the server
|
|
1160
|
-
* for. Absent for a query run without one: the response carries only edges,
|
|
1161
|
-
* and the client's read entry fetches fields in a second round trip.
|
|
1162
|
-
*/
|
|
1163
|
-
readonly select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
1164
|
-
}>, Schema.Struct<{
|
|
1165
|
-
readonly edges: Schema.$Array<Schema.Struct<{
|
|
1166
|
-
readonly entity: Schema.String;
|
|
1167
|
-
readonly id: Schema.String;
|
|
1168
|
-
readonly key: Schema.String;
|
|
1169
|
-
}>>;
|
|
1170
|
-
readonly start: Schema.Union<readonly [Schema.Struct<{
|
|
1171
|
-
readonly _tag: Schema.Literal<"Terminal">;
|
|
1172
|
-
}>, Schema.Struct<{
|
|
1173
|
-
readonly _tag: Schema.Literal<"Cursor">;
|
|
1174
|
-
readonly cursor: Schema.String;
|
|
1175
|
-
}>, Schema.Struct<{
|
|
1176
|
-
readonly _tag: Schema.Literal<"Unknown">;
|
|
1177
|
-
}>]>;
|
|
1178
|
-
readonly end: Schema.Union<readonly [Schema.Struct<{
|
|
1179
|
-
readonly _tag: Schema.Literal<"Terminal">;
|
|
1180
|
-
}>, Schema.Struct<{
|
|
1181
|
-
readonly _tag: Schema.Literal<"Cursor">;
|
|
1182
|
-
readonly cursor: Schema.String;
|
|
1183
|
-
}>, Schema.Struct<{
|
|
1184
|
-
readonly _tag: Schema.Literal<"Unknown">;
|
|
1185
|
-
}>]>;
|
|
1186
|
-
/**
|
|
1187
|
-
* The selected fields of the page's items, in the same shape a read batch
|
|
1188
|
-
* returns. Absent from a server that predates payload planning: the client
|
|
1189
|
-
* reads it as empty and fetches fields as before.
|
|
1190
|
-
*/
|
|
1191
|
-
readonly entities: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
1192
|
-
readonly entity: Schema.String;
|
|
1193
|
-
readonly id: Schema.String;
|
|
1194
|
-
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
1195
|
-
}>>>;
|
|
1196
|
-
readonly settled: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
1197
|
-
readonly entity: Schema.String;
|
|
1198
|
-
readonly id: Schema.String;
|
|
1199
|
-
readonly fields: Schema.$Array<Schema.String>;
|
|
1200
|
-
}>>>;
|
|
1201
|
-
}>, Schema.Union<readonly [typeof RemoteQueryError, typeof RemoteUnauthenticated]>, never, never>;
|
|
1202
|
-
declare const RemoteRpc: RpcGroup.RpcGroup<Rpc.Rpc<"FoldkitRemoteLive", Schema.Struct<{
|
|
1203
|
-
readonly version: Schema.Number;
|
|
1204
|
-
readonly requirements: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
1205
|
-
/** Resume cursor; events at or before it are duplicates. */
|
|
1206
|
-
readonly after: Schema.Number;
|
|
1207
|
-
}>, import("effect/rpc/RpcSchema").Stream<Schema.Union<readonly [Schema.Struct<{
|
|
1208
|
-
readonly _tag: Schema.Literal<"EntityPatched">;
|
|
1209
|
-
readonly cursor: Schema.Number;
|
|
1210
|
-
readonly entity: Schema.String;
|
|
1211
|
-
readonly id: Schema.String;
|
|
1212
|
-
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
1213
|
-
readonly changed: Schema.$Array<Schema.String>;
|
|
1214
|
-
}>, Schema.Struct<{
|
|
1215
|
-
readonly _tag: Schema.Literal<"EntityDeleted">;
|
|
1216
|
-
readonly cursor: Schema.Number;
|
|
1217
|
-
readonly entity: Schema.String;
|
|
1218
|
-
readonly id: Schema.String;
|
|
1219
|
-
}>, Schema.Struct<{
|
|
1220
|
-
readonly _tag: Schema.Literal<"ConnectionInsert">;
|
|
1221
|
-
readonly cursor: Schema.Number;
|
|
1222
|
-
readonly connection: Schema.String;
|
|
1223
|
-
readonly position: Schema.Union<readonly [Schema.Literal<"prepend">, Schema.Literal<"append">]>;
|
|
1224
|
-
readonly edge: Schema.Struct<{
|
|
1225
|
-
readonly entity: Schema.String;
|
|
1226
|
-
readonly id: Schema.String;
|
|
1227
|
-
readonly key: Schema.String;
|
|
1228
|
-
}>;
|
|
1229
|
-
}>, Schema.Struct<{
|
|
1230
|
-
readonly _tag: Schema.Literal<"ConnectionRemove">;
|
|
1231
|
-
readonly cursor: Schema.Number;
|
|
1232
|
-
readonly connection: Schema.String;
|
|
1233
|
-
readonly edge: Schema.Struct<{
|
|
1234
|
-
readonly entity: Schema.String;
|
|
1235
|
-
readonly id: Schema.String;
|
|
1236
|
-
readonly key: Schema.String;
|
|
1237
|
-
}>;
|
|
1238
|
-
}>, Schema.Struct<{
|
|
1239
|
-
readonly _tag: Schema.Literal<"ConnectionInvalidate">;
|
|
1240
|
-
readonly cursor: Schema.Number;
|
|
1241
|
-
readonly connection: Schema.String;
|
|
1242
|
-
}>]>, Schema.Union<readonly [typeof RemoteLiveError, typeof RemoteProtocolError, typeof RemoteUnauthenticated]>>, Schema.Never, never, never> | Rpc.Rpc<"FoldkitRemoteMutate", Schema.Struct<{
|
|
1243
|
-
/**
|
|
1244
|
-
* This client's id for the request, the same on each retry of it. It is
|
|
1245
|
-
* unique within one client's Model only (a counter there), so it names a
|
|
1246
|
-
* request to that client; `operation` names it to a server.
|
|
1247
|
-
*/
|
|
1248
|
-
readonly requestId: Schema.String;
|
|
1249
|
-
/** The operation's identity across clients: what a server keys a record of the write by. */
|
|
1250
|
-
readonly operation: Schema.optional<Schema.String>;
|
|
1251
|
-
readonly mutation: Schema.String;
|
|
1252
|
-
readonly input: Schema.Unknown;
|
|
1253
|
-
/** For a mutation that is a `Write`: the input keys to write, when not all of them. */
|
|
1254
|
-
readonly keys: Schema.optional<Schema.$Array<Schema.String>>;
|
|
1255
|
-
}>, Schema.Struct<{
|
|
1256
|
-
readonly output: Schema.Unknown;
|
|
1257
|
-
readonly entities: Schema.$Array<Schema.Struct<{
|
|
1258
|
-
readonly entity: Schema.String;
|
|
1259
|
-
readonly id: Schema.String;
|
|
1260
|
-
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
1261
|
-
}>>;
|
|
1262
|
-
/** Connection changes the mutation made, applied alongside its entity patches. */
|
|
1263
|
-
readonly connections: Schema.optional<Schema.$Array<Schema.Union<readonly [Schema.Struct<{
|
|
1264
|
-
readonly _tag: Schema.Literal<"Insert">;
|
|
1265
|
-
readonly connection: Schema.String;
|
|
1266
|
-
readonly position: Schema.Union<readonly [Schema.Literal<"prepend">, Schema.Literal<"append">]>;
|
|
1267
|
-
readonly edge: Schema.Struct<{
|
|
1268
|
-
readonly entity: Schema.String;
|
|
1269
|
-
readonly id: Schema.String;
|
|
1270
|
-
readonly key: Schema.String;
|
|
1271
|
-
}>;
|
|
1272
|
-
}>, Schema.Struct<{
|
|
1273
|
-
readonly _tag: Schema.Literal<"Remove">;
|
|
1274
|
-
readonly connection: Schema.String;
|
|
1275
|
-
readonly edge: Schema.Struct<{
|
|
1276
|
-
readonly entity: Schema.String;
|
|
1277
|
-
readonly id: Schema.String;
|
|
1278
|
-
readonly key: Schema.String;
|
|
1279
|
-
}>;
|
|
1280
|
-
}>]>>>;
|
|
1281
|
-
/** Entities the mutation deleted; the client knows them absent from then on. */
|
|
1282
|
-
readonly deleted: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
1283
|
-
readonly entity: Schema.String;
|
|
1284
|
-
readonly id: Schema.String;
|
|
1285
|
-
}>>>;
|
|
1286
|
-
}>, Schema.Union<readonly [typeof RemoteMutationError, typeof RemoteForbidden, typeof RemoteUnauthenticated]>, never, never> | Rpc.Rpc<"FoldkitRemoteQuery", Schema.Struct<{
|
|
1287
|
-
readonly query: Schema.String;
|
|
1288
|
-
readonly input: Schema.Unknown;
|
|
1289
|
-
readonly window: Schema.Struct<{
|
|
1290
|
-
readonly first: Schema.optional<Schema.Number>;
|
|
1291
|
-
readonly last: Schema.optional<Schema.Number>;
|
|
1292
|
-
readonly after: Schema.optional<Schema.String>;
|
|
1293
|
-
readonly before: Schema.optional<Schema.String>;
|
|
1294
|
-
}>;
|
|
1295
|
-
/**
|
|
1296
|
-
* What to read of each item, as the relation slice a read asks the server
|
|
1297
|
-
* for. Absent for a query run without one: the response carries only edges,
|
|
1298
|
-
* and the client's read entry fetches fields in a second round trip.
|
|
1299
|
-
*/
|
|
1300
|
-
readonly select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
1301
|
-
}>, Schema.Struct<{
|
|
1302
|
-
readonly edges: Schema.$Array<Schema.Struct<{
|
|
1303
|
-
readonly entity: Schema.String;
|
|
1304
|
-
readonly id: Schema.String;
|
|
1305
|
-
readonly key: Schema.String;
|
|
1306
|
-
}>>;
|
|
1307
|
-
readonly start: Schema.Union<readonly [Schema.Struct<{
|
|
1308
|
-
readonly _tag: Schema.Literal<"Terminal">;
|
|
1309
|
-
}>, Schema.Struct<{
|
|
1310
|
-
readonly _tag: Schema.Literal<"Cursor">;
|
|
1311
|
-
readonly cursor: Schema.String;
|
|
1312
|
-
}>, Schema.Struct<{
|
|
1313
|
-
readonly _tag: Schema.Literal<"Unknown">;
|
|
1314
|
-
}>]>;
|
|
1315
|
-
readonly end: Schema.Union<readonly [Schema.Struct<{
|
|
1316
|
-
readonly _tag: Schema.Literal<"Terminal">;
|
|
1317
|
-
}>, Schema.Struct<{
|
|
1318
|
-
readonly _tag: Schema.Literal<"Cursor">;
|
|
1319
|
-
readonly cursor: Schema.String;
|
|
1320
|
-
}>, Schema.Struct<{
|
|
1321
|
-
readonly _tag: Schema.Literal<"Unknown">;
|
|
1322
|
-
}>]>;
|
|
1323
|
-
/**
|
|
1324
|
-
* The selected fields of the page's items, in the same shape a read batch
|
|
1325
|
-
* returns. Absent from a server that predates payload planning: the client
|
|
1326
|
-
* reads it as empty and fetches fields as before.
|
|
1327
|
-
*/
|
|
1328
|
-
readonly entities: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
1329
|
-
readonly entity: Schema.String;
|
|
1330
|
-
readonly id: Schema.String;
|
|
1331
|
-
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
1332
|
-
}>>>;
|
|
1333
|
-
readonly settled: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
1334
|
-
readonly entity: Schema.String;
|
|
1335
|
-
readonly id: Schema.String;
|
|
1336
|
-
readonly fields: Schema.$Array<Schema.String>;
|
|
1337
|
-
}>>>;
|
|
1338
|
-
}>, Schema.Union<readonly [typeof RemoteQueryError, typeof RemoteUnauthenticated]>, never, never> | Rpc.Rpc<"FoldkitRemoteRead", Schema.Struct<{
|
|
1339
|
-
readonly version: Schema.Number;
|
|
1340
|
-
readonly requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
1341
|
-
}>, Schema.Struct<{
|
|
1342
|
-
readonly entities: Schema.$Array<Schema.Struct<{
|
|
1343
|
-
readonly entity: Schema.String;
|
|
1344
|
-
readonly id: Schema.String;
|
|
1345
|
-
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
1346
|
-
}>>;
|
|
1347
|
-
readonly settled: Schema.$Array<Schema.Struct<{
|
|
1348
|
-
readonly entity: Schema.String;
|
|
1349
|
-
readonly id: Schema.String;
|
|
1350
|
-
readonly fields: Schema.$Array<Schema.String>;
|
|
1351
|
-
}>>;
|
|
1352
|
-
}>, Schema.Union<readonly [typeof RemoteReadError, typeof RemoteProtocolError, typeof RemoteUnauthenticated]>, never, never>>;
|
|
1353
|
-
type Batch = Schema.Schema.Type<typeof ReadBatch>;
|
|
1354
|
-
type BatchResult = Schema.Schema.Type<typeof ReadBatchResult>;
|
|
1355
|
-
type ReadError = RemoteReadError | RemoteProtocolError | RemoteUnauthenticated;
|
|
1356
|
-
type QueryError = RemoteQueryError | RemoteUnauthenticated;
|
|
1357
|
-
type BatchRead = (batch: Batch) => Effect.Effect<BatchResult, ReadError>;
|
|
1358
|
-
type QueryRequestValue = Schema.Schema.Type<typeof QueryRequest>;
|
|
1359
|
-
type QueryResultValue = Schema.Schema.Type<typeof QueryResult>;
|
|
1360
|
-
type QueryRun = (request: QueryRequestValue) => Effect.Effect<QueryResultValue, QueryError>;
|
|
1361
|
-
interface CoalesceOptions {
|
|
1362
|
-
/**
|
|
1363
|
-
* How long a batch waits to collect more requirements before it runs.
|
|
1364
|
-
* Requirements issued concurrently coalesce even at the default of no wait.
|
|
1365
|
-
*/
|
|
1366
|
-
readonly window?: Duration.Input | undefined;
|
|
1367
|
-
}
|
|
1368
|
-
/** A stable key for a requirement, so an equal requirement in flight is joined. */
|
|
1369
|
-
declare const requirementKey: (requirement: Requirement) => string;
|
|
1370
|
-
/**
|
|
1371
|
-
* Wraps a raw query so that an identical query in flight (same query, input,
|
|
1372
|
-
* and window) is joined rather than run again; distinct queries run
|
|
1373
|
-
* concurrently. A page answers exactly one window, so nothing is batched.
|
|
1374
|
-
*/
|
|
1375
|
-
declare const coalesceQueries: (query: QueryRun, options?: CoalesceOptions) => Effect.Effect<QueryRun>;
|
|
1376
|
-
/**
|
|
1377
|
-
* Wraps a raw batch read so that requirements are batched and deduplicated.
|
|
1378
|
-
* Every waiter receives the whole batch result; `Remote.writeRead` is
|
|
1379
|
-
* idempotent, so writing it more than once is harmless.
|
|
1380
|
-
*/
|
|
1381
|
-
declare const coalesceReads: (read: BatchRead, options?: CoalesceOptions) => Effect.Effect<BatchRead>;
|
|
1382
|
-
type LiveCursor = number;
|
|
1383
|
-
type LiveEvent = {
|
|
1384
|
-
readonly _tag: 'EntityPatched';
|
|
1385
|
-
readonly ref: EdgeRef;
|
|
1386
|
-
readonly values: Readonly<Record<string, unknown>>;
|
|
1387
|
-
readonly changed: ReadonlyArray<string>;
|
|
1388
|
-
readonly cursor: LiveCursor;
|
|
1389
|
-
} | {
|
|
1390
|
-
readonly _tag: 'EntityDeleted';
|
|
1391
|
-
readonly ref: EdgeRef;
|
|
1392
|
-
readonly cursor: LiveCursor;
|
|
1393
|
-
} | {
|
|
1394
|
-
readonly _tag: 'ConnectionInsert';
|
|
1395
|
-
readonly connection: string;
|
|
1396
|
-
readonly position: 'prepend' | 'append';
|
|
1397
|
-
readonly edge: Edge;
|
|
1398
|
-
readonly cursor: LiveCursor;
|
|
1399
|
-
} | {
|
|
1400
|
-
readonly _tag: 'ConnectionRemove';
|
|
1401
|
-
readonly connection: string;
|
|
1402
|
-
readonly edge: Edge;
|
|
1403
|
-
readonly cursor: LiveCursor;
|
|
1404
|
-
} | {
|
|
1405
|
-
readonly _tag: 'ConnectionInvalidate';
|
|
1406
|
-
readonly connection: string;
|
|
1407
|
-
readonly cursor: LiveCursor;
|
|
1408
|
-
};
|
|
1409
|
-
interface BoundaryCounts {
|
|
1410
|
-
readonly before: number;
|
|
1411
|
-
readonly after: number;
|
|
1412
|
-
}
|
|
1413
|
-
interface LiveState {
|
|
1414
|
-
/** Last applied cursor for this stream. */
|
|
1415
|
-
readonly cursor: LiveCursor;
|
|
1416
|
-
/** Edges recorded outside the loaded boundary, not visible in `items`. */
|
|
1417
|
-
readonly boundary: Readonly<Record<string, BoundaryCounts>>;
|
|
1418
|
-
}
|
|
1419
|
-
declare const emptyLiveState: LiveState;
|
|
1420
|
-
type LiveOutcome = 'applied' | 'duplicate' | 'gap';
|
|
1421
|
-
/**
|
|
1422
|
-
* Ordering per stream: at most the next cursor; ahead is a gap. Cursor `0` means
|
|
1423
|
-
* "no baseline yet" (cursors are 1-based), so the first event of a stream is
|
|
1424
|
-
* accepted whatever its cursor — otherwise a stream not starting at 1 would be a
|
|
1425
|
-
* spurious gap.
|
|
1426
|
-
*/
|
|
1427
|
-
declare const classifyLive: (state: LiveState, cursor: LiveCursor) => LiveOutcome;
|
|
1428
|
-
interface EntityApplied {
|
|
1429
|
-
readonly state: LiveState;
|
|
1430
|
-
readonly store: EntityStore;
|
|
1431
|
-
readonly outcome: LiveOutcome;
|
|
1432
|
-
}
|
|
1433
|
-
declare const applyEntityEvent: (state: LiveState, store: EntityStore, event: Extract<LiveEvent, {
|
|
1434
|
-
_tag: 'EntityPatched' | 'EntityDeleted';
|
|
1435
|
-
}>, now?: number) => EntityApplied;
|
|
1436
|
-
interface ConnectionApplied {
|
|
1437
|
-
readonly state: LiveState;
|
|
1438
|
-
readonly optimistic: OptimisticState;
|
|
1439
|
-
readonly outcome: LiveOutcome;
|
|
1440
|
-
/**
|
|
1441
|
-
* A connection the event says to refetch. Reported rather than recorded here,
|
|
1442
|
-
* because staleness lives on the connection in the Model — which is what the
|
|
1443
|
-
* planner and every read consult. It used to be written into a set on this
|
|
1444
|
-
* live state that nothing read, so an invalidating event did nothing at all.
|
|
1445
|
-
*/
|
|
1446
|
-
readonly invalidated?: string | undefined;
|
|
1447
|
-
}
|
|
1448
|
-
declare const applyConnectionEvent: (state: LiveState, optimistic: OptimisticState, event: Extract<LiveEvent, {
|
|
1449
|
-
_tag: 'ConnectionInsert' | 'ConnectionRemove' | 'ConnectionInvalidate';
|
|
1450
|
-
}>, policy?: LivePolicy) => ConnectionApplied;
|
|
1451
|
-
/** `hasPrevious` accounting for edges recorded outside the loaded boundary. */
|
|
1452
|
-
declare const liveHasPrevious: (connection: Connection, state: LiveState, connectionId: string) => boolean;
|
|
1453
|
-
/** `hasNext` accounting for edges recorded outside the loaded boundary. */
|
|
1454
|
-
declare const liveHasNext: (connection: Connection, state: LiveState, connectionId: string) => boolean;
|
|
1455
|
-
declare const RemoteClient_base: Context.ServiceClass<RemoteClient, "foldkit-remote/RemoteClient", {
|
|
1456
|
-
readonly read: (batch: Schema.Schema.Type<typeof ReadBatch>) => Effect.Effect<Schema.Schema.Type<typeof ReadBatchResult>, RemoteReadError | RemoteProtocolError | RemoteUnauthenticated>;
|
|
1457
|
-
readonly query: (request: Schema.Schema.Type<typeof QueryRequest>) => Effect.Effect<Schema.Schema.Type<typeof QueryResult>, RemoteQueryError | RemoteUnauthenticated>;
|
|
1458
|
-
readonly mutate: (request: Schema.Schema.Type<typeof MutationRequest>) => Effect.Effect<Schema.Schema.Type<typeof MutationResult>, RemoteMutationError | RemoteForbidden | RemoteUnauthenticated>;
|
|
1459
|
-
readonly live: (request: {
|
|
1460
|
-
readonly requirements: ReadonlyArray<Requirement>;
|
|
1461
|
-
readonly after: LiveCursor;
|
|
1462
|
-
}) => Stream.Stream<LiveEvent, RemoteLiveError | RemoteProtocolError | RemoteUnauthenticated>;
|
|
1463
|
-
}>;
|
|
1464
|
-
/**
|
|
1465
|
-
* The transport boundary. `foldkit-remote` never talks to a transport directly;
|
|
1466
|
-
* it depends on this Effect service, which a later phase wires to Effect RPC.
|
|
1467
|
-
*/
|
|
1468
|
-
declare class RemoteClient extends RemoteClient_base {}
|
|
1469
|
-
/**
|
|
1470
|
-
* The methods an Effect RPC client for `RemoteRpc` exposes. `R` is the
|
|
1471
|
-
* environment a handler needs; it defaults to `never`, which is what a real
|
|
1472
|
-
* transport client satisfies. `RemoteServer.handlers` returns this type with its
|
|
1473
|
-
* own `R`, so the two sides cannot drift apart.
|
|
1474
|
-
*
|
|
1475
|
-
* `TransportError` is what the transport itself may fail with on top of the
|
|
1476
|
-
* declared errors: `RpcClientError` for the client `RpcClient.make` builds,
|
|
1477
|
-
* `never` for in-process handlers.
|
|
1478
|
-
*/
|
|
1479
|
-
interface RemoteRpcClient<R = never, TransportError = never> {
|
|
1480
|
-
readonly FoldkitRemoteRead: (payload: Schema.Schema.Type<typeof ReadBatch>) => Effect.Effect<Schema.Schema.Type<typeof ReadBatchResult>, RemoteReadError | RemoteProtocolError | RemoteUnauthenticated | TransportError, R>;
|
|
1481
|
-
readonly FoldkitRemoteQuery: (payload: Schema.Schema.Type<typeof QueryRequest>) => Effect.Effect<Schema.Schema.Type<typeof QueryResult>, RemoteQueryError | RemoteUnauthenticated | TransportError, R>;
|
|
1482
|
-
readonly FoldkitRemoteMutate: (payload: Schema.Schema.Type<typeof MutationRequest>) => Effect.Effect<Schema.Schema.Type<typeof MutationResult>, RemoteMutationError | RemoteForbidden | RemoteUnauthenticated | TransportError, R>;
|
|
1483
|
-
readonly FoldkitRemoteLive: (payload: Schema.Schema.Type<typeof LiveRequirement>) => Stream.Stream<Schema.Schema.Type<typeof LiveChange>, RemoteLiveError | RemoteProtocolError | RemoteUnauthenticated | TransportError, R>;
|
|
1484
|
-
}
|
|
1485
|
-
/** Reconstructs the client's `ConnectionChange` from the wire's flattened edge. */
|
|
1486
|
-
declare const connectionChangeOf: (change: Schema.Schema.Type<typeof ConnectionChangeSchema>) => ConnectionChange;
|
|
1487
|
-
/** Reconstructs the client's `LiveEvent` from the wire's flattened `LiveChange`. */
|
|
1488
|
-
declare const liveEventOf: (change: Schema.Schema.Type<typeof LiveChange>) => LiveEvent;
|
|
1489
|
-
declare const remoteError: (error: {
|
|
1490
|
-
readonly _tag: string;
|
|
1491
|
-
readonly message: string;
|
|
1492
|
-
readonly refusal?: unknown;
|
|
1493
|
-
readonly reason?: string | undefined;
|
|
1494
|
-
}) => RemoteError;
|
|
1495
|
-
declare const coalescedLayer: <E, R>(layer: Layer.Layer<RemoteClient, E, R>, options?: CoalesceOptions) => Layer.Layer<RemoteClient, E, R>;
|
|
1496
|
-
/**
|
|
1497
|
-
* A new operation's identity: random, so unique across clients and reloads.
|
|
1498
|
-
* `randomUUID` exists only in a secure context, so a page served over plain
|
|
1499
|
-
* HTTP draws 128 random bits from `getRandomValues`, which exists in all.
|
|
1500
|
-
*/
|
|
1501
|
-
declare const mintOperation: () => string;
|
|
1502
|
-
/**
|
|
1503
|
-
* `Remote.mutate` as a standalone effect, so `Remote.mutateInto` can reuse it
|
|
1504
|
-
* without the object literal referencing itself.
|
|
1505
|
-
*/
|
|
1506
|
-
declare const mutateRemote: <Name extends string, Input, Output>(mutation: MutationDescriptor<Name, Input, Output, unknown>, input: Input, requestId: string, options?: {
|
|
1507
|
-
readonly keys?: ReadonlyArray<string> | undefined;
|
|
1508
|
-
/**
|
|
1509
|
-
* The operation's identity across clients, the same on each retry of it:
|
|
1510
|
-
* minted here when not given, so a retry must pass the one first sent.
|
|
1511
|
-
*/
|
|
1512
|
-
readonly operation?: string | undefined;
|
|
1513
|
-
} | undefined) => Effect.Effect<{
|
|
1514
|
-
output: Output;
|
|
1515
|
-
entities: readonly {
|
|
1516
|
-
readonly entity: string;
|
|
1517
|
-
readonly id: string;
|
|
1518
|
-
readonly values: {
|
|
1519
|
-
readonly [x: string]: unknown;
|
|
1520
|
-
};
|
|
1521
|
-
}[];
|
|
1522
|
-
connections: ConnectionChange[];
|
|
1523
|
-
deleted: readonly {
|
|
1524
|
-
readonly entity: string;
|
|
1525
|
-
readonly id: string;
|
|
1526
|
-
}[];
|
|
1527
|
-
}, RemoteForbidden | RemoteMutationError | RemoteUnauthenticated, RemoteClient>;
|
|
1528
|
-
interface RefParts {
|
|
1529
|
-
readonly entity: string;
|
|
1530
|
-
readonly id: string;
|
|
1531
|
-
}
|
|
1532
|
-
/** A page of refs as the wire and the store hold it. */
|
|
1533
|
-
interface RefPageValue {
|
|
1534
|
-
readonly refs: ReadonlyArray<string>;
|
|
1535
|
-
readonly hasNext: boolean;
|
|
1536
|
-
readonly hasPrevious: boolean;
|
|
1537
|
-
}
|
|
1538
|
-
/** Marks the codec `Entity.ref`/`Entity.refPage` produce, so a Selection can tell the field's shape. */
|
|
1539
|
-
declare const RelationAnnotation = "foldkitRemoteRelation";
|
|
1540
|
-
/** The target entity's name on the same codec, so a nested selection of another entity is refused. */
|
|
1541
|
-
declare const RelationEntityAnnotation = "foldkitRemoteRelationEntity";
|
|
1542
|
-
type RelationKind = 'one' | 'many' | 'page';
|
|
1543
|
-
interface RelationShape {
|
|
1544
|
-
readonly kind: RelationKind;
|
|
1545
|
-
readonly nullable: boolean;
|
|
1546
|
-
readonly entity: string;
|
|
1547
|
-
}
|
|
1548
|
-
/**
|
|
1549
|
-
* A page of a relation that is a whole list is read under a name of its own, the
|
|
1550
|
-
* field's name and the page's size: `comments@first=10`. It is a field like any
|
|
1551
|
-
* other to the store, the planner, and the wire, so the whole list and a page of
|
|
1552
|
-
* it are held side by side, merged, marked stale, and persisted each on its own.
|
|
1553
|
-
* The server reads the name apart, reads the relation with the window, and
|
|
1554
|
-
* answers under the alias. A cursor is not part of the name: a page read from a
|
|
1555
|
-
* cursor merges onto the page it continues.
|
|
1556
|
-
*/
|
|
1557
|
-
declare const RELATION_ALIAS = "@";
|
|
1558
|
-
/** The alias a relation field is read under, for a window of this size. */
|
|
1559
|
-
declare const relationAlias: (field: string, window: {
|
|
1560
|
-
readonly first?: number | undefined;
|
|
1561
|
-
readonly last?: number | undefined;
|
|
1562
|
-
readonly after?: string | undefined;
|
|
1563
|
-
readonly before?: string | undefined;
|
|
1564
|
-
}) => string;
|
|
1565
|
-
/** The field an alias reads; a name that is no alias is its own field. */
|
|
1566
|
-
declare const aliasedField: (name: string) => string;
|
|
1567
|
-
/** Splits a ref key (`"Entity:id"`, the store key too) back into its parts. */
|
|
1568
|
-
declare const refParts: (encoded: string) => RefParts;
|
|
1569
|
-
/**
|
|
1570
|
-
* The refs a relation value carries, in order. Anything that is not a ref key,
|
|
1571
|
-
* an array of them, or a page of them contributes nothing.
|
|
1572
|
-
*/
|
|
1573
|
-
declare const refsIn: (value: unknown) => ReadonlyArray<RefParts>;
|
|
1574
|
-
/** The refs in a relation value that name the relation's target entity, and no other. */
|
|
1575
|
-
declare const targetsOf: (value: unknown, relation: RelationRequirement) => ReadonlyArray<RefParts>;
|
|
1576
|
-
declare const isRefPage: (value: unknown) => value is RefPageValue;
|
|
1577
|
-
/**
|
|
1578
|
-
* The relation shape an entity field schema declares: a ref (`one`), a nullable
|
|
1579
|
-
* ref, an array of refs (`many`), or a page of refs (`page`). `undefined` for a
|
|
1580
|
-
* scalar field, which cannot take a nested selection.
|
|
1581
|
-
*/
|
|
1582
|
-
declare const relationShape: (schema: Schema.Top) => RelationShape | undefined;
|
|
1583
|
-
/** One page of a paginated relation with each target assembled through a nested selection. */
|
|
1584
|
-
interface Page<Item> {
|
|
1585
|
-
readonly items: ReadonlyArray<Item>;
|
|
1586
|
-
readonly hasNext: boolean;
|
|
1587
|
-
readonly hasPrevious: boolean;
|
|
1588
|
-
}
|
|
1589
|
-
/**
|
|
1590
|
-
* The fields a projection reads of one entity, plus the slice it reads of each
|
|
1591
|
-
* relation's target. `Shape` tells a parent selection whether this one is a
|
|
1592
|
-
* paginated relation (`connection`) or a plain entity slice (`entity`).
|
|
1593
|
-
*/
|
|
1594
|
-
interface Selection<Value, Name extends string = string, Shape extends 'entity' | 'connection' = 'entity' | 'connection'> {
|
|
1595
|
-
readonly entity: Name;
|
|
1596
|
-
readonly fields: readonly string[];
|
|
1597
|
-
/** A pure codec: entity fields carry no decoding or encoding services. */
|
|
1598
|
-
readonly schema: Schema.Codec<Value, unknown, never, never>;
|
|
1599
|
-
/** Pagination windows for nested relation fields, keyed by field name. */
|
|
1600
|
-
readonly connections?: Readonly<Record<string, QueryWindow>> | undefined;
|
|
1601
|
-
/** The slice required of each nested relation's target, keyed by field name. */
|
|
1602
|
-
readonly relations?: Readonly<Record<string, RelationRequirement>> | undefined;
|
|
1603
|
-
/** Present when this selection is itself a paginated relation. */
|
|
1604
|
-
readonly window?: QueryWindow | undefined;
|
|
1605
|
-
/** Phantom: see `Shape`. */
|
|
1606
|
-
readonly shape?: Shape | undefined;
|
|
1607
|
-
}
|
|
1608
|
-
/** Flattens a mapped type so hovers show the picked fields, not the machinery. */
|
|
1609
|
-
type Simplify<T> = T extends (infer O) ? { readonly [K in keyof O]: O[K]; } : never;
|
|
1610
|
-
/** The value a Selection reads: `Selection.Value<typeof ProjectCard>`. */
|
|
1611
|
-
type SelectionValueOf<S> = S extends Selection<infer V, any, any> ? V : never;
|
|
1612
|
-
/** The nested selections a relation field admits: of its target entity, in the shapes its value takes. */
|
|
1613
|
-
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;
|
|
1614
|
-
/** What a selection of an entity with fields `F` may pick: `true` per scalar, a nested selection per relation. */
|
|
1615
|
-
type SelectionOf<F extends Schema.Struct.Fields> = { readonly [K in keyof F]?: true | NestedFor<Schema.Schema.Type<F[K]>>; };
|
|
1616
|
-
/** `T | null` when the field admits `null` or `undefined` (both assemble to `null`). */
|
|
1617
|
-
type Nullable<Field, T> = [Extract<Field, null | undefined>] extends [never] ? T : T | null;
|
|
1618
|
-
/** A nested selection's value takes the shape of the field it selects through. */
|
|
1619
|
-
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;
|
|
1620
|
-
/** The value a selection `Sel` of fields `F` reads. */
|
|
1621
|
-
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]>; }>;
|
|
1622
|
-
declare const pageSchema: (item: AnySchema) => AnySchema;
|
|
1623
|
-
/** The requirement a nested selection contributes for its relation's target. */
|
|
1624
|
-
declare const relationOf: (selection: Selection<unknown>) => RelationRequirement;
|
|
1625
|
-
declare const Selection: {
|
|
1626
|
-
/**
|
|
1627
|
-
* The Remote Selection of a `foldkit-entity` Selection: the same members, read
|
|
1628
|
-
* from Remote's store. `true` on a relation reads its refs, as it does here.
|
|
1629
|
-
*/
|
|
1630
|
-
from: <Name extends string, S extends Schema.Constraint>(selection: Domain.Selection<Name, unknown, S>) => Selection<S['Type'], Name, 'entity'>;
|
|
1631
|
-
/**
|
|
1632
|
-
* The fields to read of `entity`. A nested `Selection` on a relation field
|
|
1633
|
-
* reads through the ref (or refs, or page of refs) the field holds into the
|
|
1634
|
-
* target's fields; a scalar field cannot take one.
|
|
1635
|
-
*/
|
|
1636
|
-
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'>;
|
|
1637
|
-
/**
|
|
1638
|
-
* A paginated relation: one page of refs to `entity` with a window, or, with
|
|
1639
|
-
* a nested selection, one page of targets assembled through it.
|
|
1640
|
-
*/
|
|
1641
|
-
connection: {
|
|
1642
|
-
<Name extends string, F extends Schema.Struct.Fields>(entity: EntityDescriptor<Name, F>, window: QueryWindow): Selection<RefPage<Name, F>, Name, 'connection'>;
|
|
1643
|
-
<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'>;
|
|
1644
|
-
};
|
|
1645
|
-
};
|
|
1646
|
-
interface Assembled {
|
|
1647
|
-
readonly values: unknown;
|
|
1648
|
-
readonly refreshing: boolean;
|
|
1649
|
-
}
|
|
1650
|
-
/**
|
|
1651
|
-
* Reads an entity's selected fields out of the store, following each nested
|
|
1652
|
-
* relation into its targets. `undefined` means some field, at any depth, is
|
|
1653
|
-
* not present yet. A tombstoned target reads as `null` (or is dropped from a
|
|
1654
|
-
* list), so the Selection's codec decides whether that is a failure.
|
|
1655
|
-
*/
|
|
1656
|
-
declare const assemble: (store: EntityStore, key: string, requirement: RelationRequirement) => Assembled | undefined;
|
|
1657
|
-
/**
|
|
1658
|
-
* The first field `requirement` reads, at any depth, that the server settled
|
|
1659
|
-
* without a value, as `Entity:id.field`. A read that consults it says why it
|
|
1660
|
-
* cannot assemble rather than waiting on a field nothing will fetch.
|
|
1661
|
-
*/
|
|
1662
|
-
declare const unavailableOf: (store: EntityStore, key: string, requirement: RelationRequirement) => string | undefined;
|
|
1663
|
-
type AnySchema = Schema.Schema<unknown>;
|
|
1664
|
-
declare const entityRefFields: unique symbol;
|
|
1665
|
-
/**
|
|
1666
|
-
* A normalized reference to an entity. `F` is a phantom carrying the entity's
|
|
1667
|
-
* fields so `Entity.patch` can type its patch; it is absent at runtime.
|
|
1668
|
-
*/
|
|
1669
|
-
interface EntityRef<Name extends string, F extends Schema.Struct.Fields = Schema.Struct.Fields> {
|
|
1670
|
-
readonly entity: Name;
|
|
1671
|
-
readonly id: string;
|
|
1672
|
-
readonly [entityRefFields]?: F;
|
|
1673
|
-
}
|
|
1674
|
-
interface EntityDescriptor<Name extends string, F extends Schema.Struct.Fields> {
|
|
1675
|
-
readonly name: Name;
|
|
1676
|
-
readonly schema: Schema.Struct<F>;
|
|
1677
|
-
readonly fields: F;
|
|
1678
|
-
ref(id: Schema.Schema.Type<F['id']>): EntityRef<Name, F>;
|
|
1679
|
-
/** The fields a Surface reads of this entity; `Selection.make(entity, …)` with the entity as receiver. */
|
|
1680
|
-
select<const Sel extends SelectionOf<F>>(selection: Sel): Selection<SelectionValue<F, Sel>, Name, 'entity'>;
|
|
1681
|
-
/** A patch of this entity's wire-shaped values; `Entity.patch(entity.ref(id), values)`. */
|
|
1682
|
-
patch(id: Schema.Schema.Type<F['id']>, values: Partial<Schema.Struct.Encoded<F>>): EntityPatch<Name, F>;
|
|
1683
|
-
}
|
|
1684
|
-
/**
|
|
1685
|
-
* Relations are **references**, never inline target schemas: a ref cannot
|
|
1686
|
-
* reconstruct a full entity, and dereferencing is a store concern. Because the
|
|
1687
|
-
* target schema is not inlined, recursive relations cannot arise through the
|
|
1688
|
-
* schema graph.
|
|
1689
|
-
*/
|
|
1690
|
-
/**
|
|
1691
|
-
* A ref as the wire carries it: the target's name, a colon, and its id. Typed
|
|
1692
|
-
* with the name, so a relation to `User` takes `'User:u1'` and not a ref to
|
|
1693
|
-
* some other entity, which would read as a row that does not exist.
|
|
1694
|
-
*/
|
|
1695
|
-
type RefKey<Name extends string> = `${Name}:${string}`;
|
|
1696
|
-
/**
|
|
1697
|
-
* A patch in wire shape: the values the store holds, so a relation is its ref
|
|
1698
|
-
* key (`Entity.refKey`), not an `EntityRef`.
|
|
1699
|
-
*/
|
|
1700
|
-
interface EntityPatch<Name extends string, F extends Schema.Struct.Fields> {
|
|
1701
|
-
readonly entity: Name;
|
|
1702
|
-
readonly id: string;
|
|
1703
|
-
readonly values: Partial<Schema.Struct.Encoded<F>>;
|
|
1704
|
-
}
|
|
1705
|
-
/**
|
|
1706
|
-
* One authoritative page of a paginated relation: refs (never inline entities)
|
|
1707
|
-
* plus whether more exist. The adapter does not hold segmentation state; the
|
|
1708
|
-
* client merges pages.
|
|
1709
|
-
*/
|
|
1710
|
-
interface RefPage<Name extends string, F extends Schema.Struct.Fields = Schema.Struct.Fields> {
|
|
1711
|
-
readonly refs: ReadonlyArray<EntityRef<Name, F>>;
|
|
1712
|
-
readonly hasNext: boolean;
|
|
1713
|
-
readonly hasPrevious: boolean;
|
|
1714
|
-
}
|
|
1715
|
-
/** The ref codec a `foldkit-entity` relation becomes: one ref, a nullable ref, or an array of refs. */
|
|
1716
|
-
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;
|
|
1717
|
-
/**
|
|
1718
|
-
* The fields Remote stores for a `foldkit-entity` Entity: its own fields, its
|
|
1719
|
-
* derived members (the server supplies them like any field), and each relation
|
|
1720
|
-
* as refs.
|
|
1721
|
-
*/
|
|
1722
|
-
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;
|
|
1723
|
-
declare const Entity$2: {
|
|
1724
|
-
/**
|
|
1725
|
-
* The Remote descriptor of a `foldkit-entity` Entity. Relations declared with
|
|
1726
|
-
* `Entity.relate` become ref fields, so the store, the planner, and the server
|
|
1727
|
-
* treat it as they treat an `Entity.make` descriptor.
|
|
1728
|
-
*/
|
|
1729
|
-
from: <E extends Domain.AnyEntity>(entity: E & {
|
|
1730
|
-
readonly fields: {
|
|
1731
|
-
readonly id: unknown;
|
|
1732
|
-
};
|
|
1733
|
-
}) => EntityDescriptor<E['name'], FieldsFrom<E>>;
|
|
1734
|
-
make: <const Name extends string, const F extends Schema.Struct.Fields & {
|
|
1735
|
-
readonly id: Schema.Schema<unknown>;
|
|
1736
|
-
}>(name: Name, schema: Schema.Struct<F>) => EntityDescriptor<Name, F>;
|
|
1737
|
-
/** A relation to a known entity, decoded as a reference. */
|
|
1738
|
-
ref: <Name extends string, F extends Schema.Struct.Fields>(entity: EntityDescriptor<Name, F>) => Schema.Codec<EntityRef<Name, F>, RefKey<Name>>;
|
|
1739
|
-
/** A relation by name, for recursive or forward references. */
|
|
1740
|
-
refTo: <Name extends string>(name: Name) => Schema.Codec<EntityRef<Name>, RefKey<Name>>;
|
|
1741
|
-
/**
|
|
1742
|
-
* The wire key a relation field carries (`"Entity:id"`). Adapters that read a
|
|
1743
|
-
* foreign key emit this so the ref codec can decode it on the client.
|
|
1744
|
-
*/
|
|
1745
|
-
refKey: (ref: {
|
|
1746
|
-
readonly entity: string;
|
|
1747
|
-
readonly id: string;
|
|
1748
|
-
}) => string;
|
|
1749
|
-
/** Splits a ref key back into its entity and id. */
|
|
1750
|
-
refParts: typeof refParts;
|
|
1751
|
-
/** A relation value of one authoritative page of refs. */
|
|
1752
|
-
refPage: <Name extends string, F extends Schema.Struct.Fields>(entity: EntityDescriptor<Name, F>) => Schema.Codec<RefPage<Name, F>, {
|
|
1753
|
-
readonly refs: ReadonlyArray<string>;
|
|
1754
|
-
readonly hasNext: boolean;
|
|
1755
|
-
readonly hasPrevious: boolean;
|
|
1756
|
-
}>;
|
|
1757
|
-
/**
|
|
1758
|
-
* A normalized patch for an entity, typed against its fields' wire shape:
|
|
1759
|
-
* write a relation as its ref key (`Entity.refKey`), as the server does.
|
|
1760
|
-
*/
|
|
1761
|
-
patch: <Name extends string, F extends Schema.Struct.Fields>(ref: EntityRef<Name, F>, patch: Partial<Schema.Struct.Encoded<F>>) => EntityPatch<Name, F>;
|
|
1762
|
-
};
|
|
1763
|
-
/**
|
|
1764
|
-
* An answer over the rows the client holds — never over the rows that exist.
|
|
1765
|
-
*
|
|
1766
|
-
* `complete` is the whole reason this is its own type rather than a `Page`. A
|
|
1767
|
-
* `Page` carries `hasNext`/`hasPrevious`, which are facts the *server* stated
|
|
1768
|
-
* about rows beyond the ones it delivered; a local answer has no such facts and
|
|
1769
|
-
* cannot invent them. What it can say is whether the population it judged was
|
|
1770
|
-
* all of it, which is decidable: a connection terminal at both ends is wholly
|
|
1771
|
-
* held, and nothing was skipped for a missing field.
|
|
1772
|
-
*
|
|
1773
|
-
* An incomplete answer is not wrong — it is an answer about less than the
|
|
1774
|
-
* caller may have meant, and the flag is what lets a view say "3 so far" rather
|
|
1775
|
-
* than "3", or a caller decide to ask the server.
|
|
1776
|
-
*/
|
|
1777
|
-
interface Matched<A> {
|
|
1778
|
-
readonly items: ReadonlyArray<A>;
|
|
1779
|
-
/** Whether every row the answer is about was judged. */
|
|
1780
|
-
readonly complete: boolean;
|
|
1781
|
-
}
|
|
1782
|
-
/**
|
|
1783
|
-
* What the rows the client holds had to say about a body.
|
|
1784
|
-
*
|
|
1785
|
-
* `skipped` is the honest half. A row missing a field the body reads cannot be
|
|
1786
|
-
* judged — it is neither a match nor a non-match — and dropping it silently
|
|
1787
|
-
* would turn "I could not tell" into "no". Naming it lets a caller decide:
|
|
1788
|
-
* fetch the field, ask the server, or say the answer is partial.
|
|
1789
|
-
*/
|
|
1790
|
-
interface Judged {
|
|
1791
|
-
/** Keys of the rows that satisfy the body, in the order the body asks for. */
|
|
1792
|
-
readonly matched: ReadonlyArray<EntityKey>;
|
|
1793
|
-
/** Keys of rows held but missing a field the body reads, so not judged either way. */
|
|
1794
|
-
readonly skipped: ReadonlyArray<EntityKey>;
|
|
1795
|
-
}
|
|
1796
|
-
interface MatchingOptions {
|
|
1797
|
-
/**
|
|
1798
|
-
* Judge only these keys. Without it every row of the body's Entity in the
|
|
1799
|
-
* store is a candidate, which is what a filter over a loaded list wants; with
|
|
1800
|
-
* it, a caller narrows to a connection's own edges.
|
|
1801
|
-
*/
|
|
1802
|
-
readonly among?: ReadonlyArray<EntityKey> | undefined;
|
|
1803
|
-
/** How the body's primitive operators are run: `Remote.make`'s `operators`. */
|
|
1804
|
-
readonly operators?: MemoryOperators | undefined;
|
|
1805
|
-
}
|
|
1806
|
-
/**
|
|
1807
|
-
* The rows of `descriptor`'s Entity that the store holds and the body matches.
|
|
1808
|
-
*
|
|
1809
|
-
* The input is given **decoded**, as an application writes it, and encoded here
|
|
1810
|
-
* through the descriptor's own `Input` codec. That is deliberate and is the
|
|
1811
|
-
* whole reason this takes a descriptor rather than a bare body: a store holds
|
|
1812
|
-
* wire values, so an input has to be in that space to be compared against them,
|
|
1813
|
-
* and handing an interpreter a decoded value is a mistake **no runtime error
|
|
1814
|
-
* catches** — the reference interpreter answers "no rows", which reads exactly
|
|
1815
|
-
* like a correct answer. Doing it here means a caller cannot get it wrong.
|
|
1816
|
-
*
|
|
1817
|
-
* Literals in the body are deliberately *not* encoded. A literal written in
|
|
1818
|
-
* domain terms is already broken against the server, which binds it to a column
|
|
1819
|
-
* the same way; accepting it here would make the client quietly more permissive
|
|
1820
|
-
* than the thing it has to agree with.
|
|
1821
|
-
*/
|
|
1822
|
-
declare const matching: <Name extends string, Input>(store: EntityStore, descriptor: QueryDescriptor<Name, Input, unknown>, input: Input, options?: MatchingOptions) => Judged;
|
|
1823
|
-
/**
|
|
1824
|
-
* Whether one row belongs to a query, as far as the client can tell.
|
|
1825
|
-
*
|
|
1826
|
-
* Three answers, and the third is the one that makes this usable. `'unknown'`
|
|
1827
|
-
* is a row the store never fetched, or holds without a field the body reads —
|
|
1828
|
-
* a caller that collapses it into `'no'` has turned "I could not tell" into an
|
|
1829
|
-
* answer, which is the mistake this whole module is shaped against.
|
|
1830
|
-
*
|
|
1831
|
-
* **Membership is decidable where position is not.** Whether a row satisfies
|
|
1832
|
-
* `eq`, `isNull` or `contains` needs no collation: equality on text is exact
|
|
1833
|
-
* and `contains` folds ASCII, both stated in §6.0.1. *Where* a row sorts needs
|
|
1834
|
-
* text collation, which is the backend's and deliberately outside the
|
|
1835
|
-
* conformant subset — so this answers the half that is always answerable, and
|
|
1836
|
-
* ordering stays the server's until a query can declare its collation.
|
|
1837
|
-
*/
|
|
1838
|
-
type Belongs = 'yes' | 'no' | 'unknown';
|
|
1839
|
-
/**
|
|
1840
|
-
* Takes the input **encoded**, because its one caller holds it that way: a
|
|
1841
|
-
* connection identity carries the canonical encoded input, and making it decode
|
|
1842
|
-
* only for this to encode again would be a round trip that can fail.
|
|
1843
|
-
*
|
|
1844
|
-
* A decoded-input sibling was written first and deleted: nothing called it. The
|
|
1845
|
-
* asymmetry with `matching`, which takes a decoded input, is the shape of the
|
|
1846
|
-
* two real callers rather than an oversight.
|
|
1847
|
-
*/
|
|
1848
|
-
declare const belongsEncoded: <Name extends string, Input>(store: EntityStore, descriptor: QueryDescriptor<Name, Input, unknown>, encoded: Readonly<Record<string, unknown>>, key: EntityKey, operators?: MemoryOperators | undefined) => Belongs;
|
|
1849
|
-
/** A connection to keep: its identity, and what a page of it selects of each item, if a projection reads it. */
|
|
1850
|
-
interface ConnectionRoot {
|
|
1851
|
-
readonly identity: string;
|
|
1852
|
-
readonly select?: RelationRequirement | undefined;
|
|
1853
|
-
}
|
|
1854
|
-
interface RetentionRoots {
|
|
1855
|
-
readonly requirements: ReadonlyArray<Requirement>;
|
|
1856
|
-
/** Connections (`QueryRef.identity`) to keep, with their edges' targets and what `select` reaches through them. */
|
|
1857
|
-
readonly connections: ReadonlyArray<ConnectionRoot>;
|
|
1858
|
-
}
|
|
1859
|
-
interface Retained {
|
|
1860
|
-
readonly entities: EntityStore;
|
|
1861
|
-
readonly connections: Readonly<Record<string, Connection>>;
|
|
1862
|
-
readonly optimistic: OptimisticState;
|
|
1863
|
-
}
|
|
1864
|
-
/**
|
|
1865
|
-
* The entity keys the roots reach: each root entity, the targets its retained
|
|
1866
|
-
* fields refer to, and recursively the targets a nested relation selects.
|
|
1867
|
-
*/
|
|
1868
|
-
declare const reachable: (store: EntityStore, roots: RetentionRoots, connections: Readonly<Record<string, Connection>>, optimistic: OptimisticState, pending: ReadonlySet<string>) => ReadonlySet<EntityKey>;
|
|
1869
|
-
/**
|
|
1870
|
-
* Drops every entity the roots do not reach, every connection they do not
|
|
1871
|
-
* name, and every settled overlay on a dropped connection, keeping whatever a
|
|
1872
|
-
* pending request's layer or overlays touch. Pure.
|
|
1873
|
-
*/
|
|
1874
|
-
declare const gc: (state: Retained & {
|
|
1875
|
-
readonly mutations: MutationState;
|
|
1876
|
-
}, roots: RetentionRoots) => Retained;
|
|
1877
|
-
/** Bump when the serialized shape changes; a mismatch discards the cache. */
|
|
1878
|
-
declare const REMOTE_CACHE_VERSION = 5;
|
|
1879
|
-
/**
|
|
1880
|
-
* What survives a reload: the entity cache, and the connections an application
|
|
1881
|
-
* **declared** should come back.
|
|
1882
|
-
*
|
|
1883
|
-
* Connections are session state by default and stay that way — `snapshotOf`
|
|
1884
|
-
* takes none unless asked. What a declared one keeps is its **edges and
|
|
1885
|
-
* nothing else**, which is not a simplification but the rule: a connection's
|
|
1886
|
-
* boundaries are cursors the server minted, and a cursor may name server state
|
|
1887
|
-
* that no longer exists. Restoring one would be claiming to know where the
|
|
1888
|
-
* page ends. The shape has nowhere to put a cursor, so that cannot be got
|
|
1889
|
-
* wrong later.
|
|
1890
|
-
*/
|
|
1891
|
-
interface Snapshot {
|
|
1892
|
-
readonly entities: EntityStore;
|
|
1893
|
-
/**
|
|
1894
|
-
* By connection identity: its **segments**, each a run of edges. No
|
|
1895
|
-
* boundaries.
|
|
1896
|
-
*
|
|
1897
|
-
* Segments rather than one flat list, because the gaps between them are
|
|
1898
|
-
* knowledge too. A connection paged from both ends holds a head and a tail
|
|
1899
|
-
* with an unfetched middle; flattening those into one run would claim the
|
|
1900
|
-
* tail's first row follows the head's last, which is a thing the client was
|
|
1901
|
-
* never told.
|
|
1902
|
-
*/
|
|
1903
|
-
readonly connections: Readonly<Record<string, ReadonlyArray<ReadonlyArray<Edge>>>>;
|
|
1904
|
-
}
|
|
1905
|
-
/**
|
|
1906
|
-
* A snapshot of a Model, keeping the entity cache and only the connections
|
|
1907
|
-
* named.
|
|
1908
|
-
*
|
|
1909
|
-
* Naming none — the default — is exactly what Remote did before connections
|
|
1910
|
-
* could be kept at all: a disposable, server-derived cache.
|
|
1911
|
-
*/
|
|
1912
|
-
declare const snapshotOf: (model: {
|
|
1913
|
-
readonly entities: EntityStore;
|
|
1914
|
-
readonly connections: Readonly<Record<string, Connection>>;
|
|
1915
|
-
}, options?: {
|
|
1916
|
-
readonly connections?: ReadonlyArray<ConnectionIdentity> | undefined;
|
|
1917
|
-
}) => Snapshot;
|
|
1918
|
-
interface SnapshotOptions {
|
|
1919
|
-
/**
|
|
1920
|
-
* Who or what the snapshot is for (a user id, a tenant, a build). A snapshot
|
|
1921
|
-
* taken under another scope is discarded rather than shown to the wrong
|
|
1922
|
-
* reader. Default: unscoped, which only matches unscoped.
|
|
1923
|
-
*/
|
|
1924
|
-
readonly scope?: string | undefined;
|
|
1925
|
-
/** Snapshots larger than this many bytes are not written and not read. */
|
|
1926
|
-
readonly maxBytes?: number | undefined;
|
|
1927
|
-
}
|
|
1928
|
-
/** How a snapshot meets a store that already has entries. */
|
|
1929
|
-
type MergePolicy = 'replace' | 'preserve-existing';
|
|
1930
|
-
/**
|
|
1931
|
-
* The snapshot text, or `undefined` when it would exceed `maxBytes`. Build the
|
|
1932
|
-
* snapshot with `snapshotOf`, which is where the connections that survive are
|
|
1933
|
-
* named; runtime state — optimistic layers, live cursors, gaps, the mutation
|
|
1934
|
-
* ledger — is never in one.
|
|
1935
|
-
*/
|
|
1936
|
-
declare function dehydrate(snapshot: Snapshot, options?: SnapshotOptions & {
|
|
1937
|
-
readonly maxBytes?: undefined;
|
|
1938
|
-
}): string;
|
|
1939
|
-
declare function dehydrate(snapshot: Snapshot, options?: SnapshotOptions): string | undefined;
|
|
1940
|
-
/**
|
|
1941
|
-
* The store a snapshot text holds, or `undefined` when the text is missing,
|
|
1942
|
-
* oversized, not this version, for another scope, or malformed. Hydrating the
|
|
1943
|
-
* same text twice yields equal stores.
|
|
1944
|
-
*/
|
|
1945
|
-
declare const hydrate: (raw: string | undefined | null, options?: SnapshotOptions) => Snapshot | undefined;
|
|
1946
|
-
/**
|
|
1947
|
-
* Brings a snapshot into a store that may already hold entries. `replace`
|
|
1948
|
-
* takes the snapshot's entry for every key it has; `preserve-existing` keeps
|
|
1949
|
-
* an entry the current store already has (it is at least as fresh as a
|
|
1950
|
-
* snapshot taken earlier). Either way, keys only the current store has stay.
|
|
1951
|
-
*/
|
|
1952
|
-
declare const mergeStores: (current: EntityStore, snapshot: EntityStore, policy: MergePolicy) => EntityStore;
|
|
1953
|
-
declare const RemotePersistence: {
|
|
1954
|
-
/** The snapshot text, or `undefined` when it would exceed `maxBytes`. */
|
|
1955
|
-
dehydrate: typeof dehydrate;
|
|
1956
|
-
/** What a snapshot text holds, or `undefined` when it is refused. */
|
|
1957
|
-
hydrate: typeof hydrate;
|
|
1958
|
-
/**
|
|
1959
|
-
* What to keep of a Model, naming the connections that should survive a
|
|
1960
|
-
* reload. Naming none is the default and is what Remote always did.
|
|
1961
|
-
*/
|
|
1962
|
-
snapshotOf: typeof snapshotOf;
|
|
1963
|
-
/** A snapshot's entities brought into a store by policy. */
|
|
1964
|
-
mergeStores: typeof mergeStores;
|
|
1965
|
-
/** The cache as a fresh session has it; what a refused `restore` yields. */
|
|
1966
|
-
emptySnapshot: Snapshot;
|
|
1967
|
-
/**
|
|
1968
|
-
* Writes the snapshot under `key`, or removes the key when the store would
|
|
1969
|
-
* exceed `maxBytes`, so a stale smaller snapshot cannot outlive a larger
|
|
1970
|
-
* store it no longer describes.
|
|
1971
|
-
*/
|
|
1972
|
-
save: (snapshot: Snapshot, options: {
|
|
1973
|
-
readonly key: string;
|
|
1974
|
-
} & SnapshotOptions) => Effect.Effect<void, KeyValueStore.KeyValueStoreError, KeyValueStore.KeyValueStore>;
|
|
1975
|
-
/**
|
|
1976
|
-
* Reads the cache. A missing key yields `emptySnapshot`; anything `hydrate`
|
|
1977
|
-
* refuses yields `emptySnapshot` and removes the key, so the next `restore`
|
|
1978
|
-
* is clean and the planner refetches.
|
|
1979
|
-
*/
|
|
1980
|
-
restore: (options: {
|
|
1981
|
-
readonly key: string;
|
|
1982
|
-
} & SnapshotOptions) => Effect.Effect<Snapshot, KeyValueStore.KeyValueStoreError, KeyValueStore.KeyValueStore>;
|
|
1983
|
-
};
|
|
1984
|
-
/**
|
|
1985
|
-
* The normalized cache as a Foldkit Submodel. `Remote.define` returns a schema
|
|
1986
|
-
* and an `update` for this shape; `updateRemote` reconciles every producer.
|
|
1987
|
-
*/
|
|
1988
|
-
interface RemoteModel {
|
|
1989
|
-
/** Entity values, presence, staleness, tombstones, and applied windows. */
|
|
1990
|
-
readonly entities: EntityStore;
|
|
1991
|
-
/** Normalized ordered connections, keyed by connection identity. */
|
|
1992
|
-
readonly connections: Readonly<Record<string, Connection>>;
|
|
1993
|
-
/**
|
|
1994
|
-
* How many rows `Data.more` has grown a read's window to, by
|
|
1995
|
-
* `windowGrowthKey`. A read shows at most its window, so this is what "load
|
|
1996
|
-
* more" changes; it lives here because a list holds no state of its own.
|
|
1997
|
-
*/
|
|
1998
|
-
readonly grown: Readonly<Record<string, number>>;
|
|
1999
|
-
/** Optimistic entity layers and connection overlays over the base store. */
|
|
2000
|
-
readonly optimistic: OptimisticState;
|
|
2001
|
-
/** Live cursor and boundary state, keyed by the subscription's stream key. */
|
|
2002
|
-
readonly live: Readonly<Record<string, LiveState>>;
|
|
2003
|
-
/** Mutation pending/applied/failed ledger. */
|
|
2004
|
-
readonly mutations: MutationState;
|
|
2005
|
-
/**
|
|
2006
|
-
* Streams that broke, by an error or by an event ahead of their cursor, and
|
|
2007
|
-
* have not resubscribed since: changes after the break are missed until the
|
|
2008
|
-
* live entry restarts them and refetches what they cover.
|
|
2009
|
-
*/
|
|
2010
|
-
readonly gaps: ReadonlySet<string>;
|
|
2011
|
-
/** Each live stream that has ever broken, by stream key. One that never broke is absent. */
|
|
2012
|
-
readonly streams: Readonly<Record<string, StreamHealth>>;
|
|
2013
|
-
/**
|
|
2014
|
-
* The `entity\0id\0field` marks a read is currently fetching. A field absent
|
|
2015
|
-
* from the store reads as `Loading` while its mark is here and `Initial`
|
|
2016
|
-
* otherwise, which is what separates "being fetched" from "nothing is
|
|
2017
|
-
* fetching this".
|
|
2018
|
-
*/
|
|
2019
|
-
readonly loading: ReadonlySet<string>;
|
|
2020
|
-
/**
|
|
2021
|
-
* `Remote.refresh` generations, held per field rather than for the store as a
|
|
2022
|
-
* whole. A read entry restarts when the generation over the fields it plans
|
|
2023
|
-
* moves, so a read sent before a refresh of its own fields cannot land after
|
|
2024
|
-
* it, and a refresh of one field leaves every other entry's read alone.
|
|
2025
|
-
*/
|
|
2026
|
-
readonly refresh: RefreshState;
|
|
2027
|
-
/**
|
|
2028
|
-
* The reads that failed and have not been settled since, so a read can say
|
|
2029
|
-
* `Failed` rather than `Initial`.
|
|
2030
|
-
*
|
|
2031
|
-
* Without them a read that failed before anything loaded read exactly like
|
|
2032
|
-
* one nobody had asked for, and nothing asked again: a read entry restarts
|
|
2033
|
-
* only when what it plans changes, and a failure changed nothing. What failed
|
|
2034
|
-
* is not planned again on its own either, so a persistent error is not
|
|
2035
|
-
* retried every time an unrelated read restarts the entry. `Remote.refresh`
|
|
2036
|
-
* is how a view retries.
|
|
2037
|
-
*/
|
|
2038
|
-
readonly failures: Failures;
|
|
2039
|
-
/**
|
|
2040
|
-
* The storage key the cache was last restored from, through `Hydrated`'s
|
|
2041
|
-
* `from`. `Data.persistence` saves under a key only once its own snapshot is
|
|
2042
|
-
* in, so a save at startup cannot write the empty store over it.
|
|
2043
|
-
*/
|
|
2044
|
-
readonly restoredFrom: Option.Option<string>;
|
|
2045
|
-
/**
|
|
2046
|
-
* Under `verifyPlacement`, the order each list was placed in, by edge key,
|
|
2047
|
-
* and the rows placing took out of its first page, until the server's page
|
|
2048
|
-
* for it arrives to be compared with them.
|
|
2049
|
-
*/
|
|
2050
|
-
readonly placed: Readonly<Record<string, PlacedOrder>>;
|
|
2051
|
-
/** Under `verifyPlacement`, each placement the server's page disagreed with. */
|
|
2052
|
-
readonly placementMismatches: ReadonlyArray<PlacementMismatch>;
|
|
2053
|
-
}
|
|
2054
|
-
/** A list's first page as the client placed it: its keys in order, and those it took out. */
|
|
2055
|
-
interface PlacedOrder {
|
|
2056
|
-
readonly order: ReadonlyArray<string>;
|
|
2057
|
-
readonly dropped: ReadonlyArray<string>;
|
|
2058
|
-
}
|
|
2059
|
-
/** A list the client placed rows in one order and the server then listed in another. */
|
|
2060
|
-
interface PlacementMismatch {
|
|
2061
|
-
readonly connection: string;
|
|
2062
|
-
/** The keys as placed, as far as the server's page reached. */
|
|
2063
|
-
readonly placed: ReadonlyArray<string>;
|
|
2064
|
-
/** The keys of the server's first page. */
|
|
2065
|
-
readonly served: ReadonlyArray<string>;
|
|
2066
|
-
}
|
|
2067
|
-
/** How a live stream has fared, as its live entry restarts it. */
|
|
2068
|
-
interface StreamHealth {
|
|
2069
|
-
/** How many times it broke. The live entry restarts on each, so it only grows. */
|
|
2070
|
-
readonly restarts: number;
|
|
2071
|
-
/** Breaks since its last applied event: what the restart's backoff grows with. */
|
|
2072
|
-
readonly failures: number;
|
|
2073
|
-
/** Why it last broke; none for a gap, which is not an error. */
|
|
2074
|
-
readonly error: Option.Option<RemoteError>;
|
|
2075
|
-
}
|
|
2076
|
-
/**
|
|
2077
|
-
* Failed reads, as the errors they failed with.
|
|
2078
|
-
*
|
|
2079
|
-
* `connections` is by connection identity, and is settled by a page arriving,
|
|
2080
|
-
* an invalidation, or retention dropping the connection. `fields` is by field
|
|
2081
|
-
* mark (`entity\0id\0field`, the marks `loading` uses), and is settled by the
|
|
2082
|
-
* field being written again, a refresh asking for it, or retention dropping the
|
|
2083
|
-
* entity. A read of it in flight reads `Loading` over the failure without
|
|
2084
|
-
* settling it: if that read fails too, the failure is simply recorded again.
|
|
2085
|
-
*/
|
|
2086
|
-
interface Failures {
|
|
2087
|
-
readonly connections: Readonly<Record<string, RemoteError>>;
|
|
2088
|
-
readonly fields: Readonly<Record<string, RemoteError>>;
|
|
2089
|
-
}
|
|
2090
|
-
declare const noFailures: Failures;
|
|
2091
|
-
/**
|
|
2092
|
-
* `Remote.refresh` generations, per field mark. `generation` is the last one
|
|
2093
|
-
* handed out; `requested` is when each field was last refreshed, and `started`
|
|
2094
|
-
* is the generation each field's read last began under. Holding them per field
|
|
2095
|
-
* is what keeps one Projection's refresh from restarting every read entry.
|
|
2096
|
-
*/
|
|
2097
|
-
interface RefreshState {
|
|
2098
|
-
readonly generation: number;
|
|
2099
|
-
readonly requested: ReadonlyMap<string, number>;
|
|
2100
|
-
readonly started: ReadonlyMap<string, number>;
|
|
2101
|
-
/**
|
|
2102
|
-
* The generation every entry is refreshed at, at least: `forgetRemote` moves
|
|
2103
|
-
* it, so every read and live entry restarts, and a read or stream begun for
|
|
2104
|
-
* the principal before is interrupted rather than landing after.
|
|
2105
|
-
*/
|
|
2106
|
-
readonly floor: number;
|
|
2107
|
-
}
|
|
2108
|
-
declare const emptyRefresh: RefreshState;
|
|
2109
|
-
/**
|
|
2110
|
-
* The Model with everything the server told it forgotten: values, tombstones,
|
|
2111
|
-
* unavailable fields, connections, live cursors, failures, and what is in
|
|
2112
|
-
* flight. For a change of principal, whose facts these were. The mutation
|
|
2113
|
-
* sequence is kept, so request ids stay unique, and a mutation in flight is
|
|
2114
|
-
* treated as applied: its answer, when it comes, writes nothing here.
|
|
2115
|
-
*/
|
|
2116
|
-
declare const forgetRemote: (model: RemoteModel) => RemoteModel;
|
|
2117
|
-
declare const initialRemoteModel: RemoteModel;
|
|
2118
|
-
declare const remoteModelSchema: () => Schema.Codec<RemoteModel, unknown>;
|
|
2119
|
-
/** The submodel's Messages; each reduces to `RemoteModel` through `updateRemote`. */
|
|
2120
|
-
type RemoteMessage = {
|
|
2121
|
-
readonly _tag: 'ReadReceived';
|
|
2122
|
-
readonly requests: readonly Requirement[];
|
|
2123
|
-
readonly result: Schema.Schema.Type<typeof ReadBatchResult>;
|
|
2124
|
-
readonly now: number;
|
|
2125
|
-
} | {
|
|
2126
|
-
readonly _tag: 'ReadFailed';
|
|
2127
|
-
readonly requests: readonly Requirement[];
|
|
2128
|
-
readonly error: RemoteError;
|
|
2129
|
-
/**
|
|
2130
|
-
* The live stream whose subscription broke, when this is that rather
|
|
2131
|
-
* than a read. Nothing was being read, so no field failed: the stream is
|
|
2132
|
-
* recorded as a gap, since changes after it are missed until the live
|
|
2133
|
-
* entry restarts it.
|
|
2134
|
-
*/
|
|
2135
|
-
readonly stream?: string | undefined;
|
|
2136
|
-
} |
|
|
2137
|
-
/** A refetch of present fields began; they read as `Refreshing` until it lands. */
|
|
2138
|
-
{
|
|
2139
|
-
readonly _tag: 'RefreshStarted';
|
|
2140
|
-
readonly requests: readonly Requirement[];
|
|
2141
|
-
} |
|
|
2142
|
-
/** A read began; the fields it asks for that the store lacks read as `Loading`. */
|
|
2143
|
-
{
|
|
2144
|
-
readonly _tag: 'ReadStarted';
|
|
2145
|
-
readonly requests: readonly Requirement[];
|
|
2146
|
-
/** The refresh generation the read was planned under. */
|
|
2147
|
-
readonly refresh?: number | undefined;
|
|
2148
|
-
} |
|
|
2149
|
-
/**
|
|
2150
|
-
* Queries for these connections were sent. One with nothing to show reads
|
|
2151
|
-
* `Loading` until its page or its failure arrives, which is what separates
|
|
2152
|
-
* "being fetched" from `Initial`, "nothing is fetching this".
|
|
2153
|
-
*/
|
|
2154
|
-
{
|
|
2155
|
-
readonly _tag: 'QueryStarted';
|
|
2156
|
-
readonly connections: readonly string[];
|
|
2157
|
-
} |
|
|
2158
|
-
/** The active Surfaces' roots changed; everything they do not reach is collected. */
|
|
2159
|
-
{
|
|
2160
|
-
readonly _tag: 'RetentionChanged';
|
|
2161
|
-
readonly roots: RetentionRoots;
|
|
2162
|
-
} |
|
|
2163
|
-
/** A restored snapshot meets the store; runtime state is untouched. */
|
|
2164
|
-
{
|
|
2165
|
-
readonly _tag: 'Hydrated';
|
|
2166
|
-
readonly entities: EntityStore;
|
|
2167
|
-
/**
|
|
2168
|
-
* The connections a snapshot declared should survive, as their edges.
|
|
2169
|
-
* Restored with **unknown** boundaries and marked stale: the rows show
|
|
2170
|
-
* at once and the connection is refetched, because a persisted cursor
|
|
2171
|
-
* may name server state that is gone.
|
|
2172
|
-
*/
|
|
2173
|
-
readonly connections?: Readonly<Record<string, ReadonlyArray<ReadonlyArray<Edge>>>> | undefined;
|
|
2174
|
-
readonly merge: MergePolicy;
|
|
2175
|
-
/** The storage key the snapshot was read from, when it was: `restoredFrom`. */
|
|
2176
|
-
readonly from?: string | undefined;
|
|
2177
|
-
} |
|
|
2178
|
-
/** A mutation began; its optimistic operations show until it settles. */
|
|
2179
|
-
{
|
|
2180
|
-
readonly _tag: 'MutationStarted';
|
|
2181
|
-
readonly requestId: string;
|
|
2182
|
-
readonly optimistic?: ReadonlyArray<OptimisticOperation> | undefined;
|
|
2183
|
-
} | {
|
|
2184
|
-
readonly _tag: 'MutationSucceeded';
|
|
2185
|
-
readonly requestId: string;
|
|
2186
|
-
readonly entities: readonly NormalizedPatch[];
|
|
2187
|
-
/** Connection changes the server confirmed; they replace the request's own. */
|
|
2188
|
-
readonly connections?: ReadonlyArray<ConnectionChange> | undefined;
|
|
2189
|
-
/** Entities the mutation deleted: tombstoned, which hides them from every connection. */
|
|
2190
|
-
readonly deleted?: ReadonlyArray<{
|
|
2191
|
-
readonly entity: string;
|
|
2192
|
-
readonly id: string;
|
|
2193
|
-
}> | undefined;
|
|
2194
|
-
/** Injected clock reading of the answer: how fresh the written entities are. */
|
|
2195
|
-
readonly now: number;
|
|
2196
|
-
} | {
|
|
2197
|
-
readonly _tag: 'MutationFailed';
|
|
2198
|
-
readonly requestId: string;
|
|
2199
|
-
readonly error: RemoteError;
|
|
2200
|
-
/** The operation id it was sent with, for a retry to send again. */
|
|
2201
|
-
readonly operation: string;
|
|
2202
|
-
} |
|
|
2203
|
-
/**
|
|
2204
|
-
* Operations shown over the store with no request behind them, until they are
|
|
2205
|
-
* lifted: a preview of a change nobody has made. Showing an id again replaces
|
|
2206
|
-
* what it showed.
|
|
2207
|
-
*/
|
|
2208
|
-
{
|
|
2209
|
-
readonly _tag: 'OverlayShown';
|
|
2210
|
-
readonly id: string;
|
|
2211
|
-
readonly optimistic: ReadonlyArray<OptimisticOperation>;
|
|
2212
|
-
} | {
|
|
2213
|
-
readonly _tag: 'OverlayLifted';
|
|
2214
|
-
readonly id: string;
|
|
2215
|
-
} |
|
|
2216
|
-
/** `Data.more`: a read's window, by `windowGrowthKey`, now shows `size` rows. */
|
|
2217
|
-
{
|
|
2218
|
-
readonly _tag: 'WindowGrown';
|
|
2219
|
-
readonly window: string;
|
|
2220
|
-
readonly size: number;
|
|
2221
|
-
} | {
|
|
2222
|
-
readonly _tag: 'LiveReceived';
|
|
2223
|
-
readonly stream: string;
|
|
2224
|
-
readonly event: LiveEvent;
|
|
2225
|
-
readonly policy?: LivePolicy;
|
|
2226
|
-
readonly now: number;
|
|
2227
|
-
} | {
|
|
2228
|
-
readonly _tag: 'GapCleared';
|
|
2229
|
-
readonly stream: string;
|
|
2230
|
-
} | {
|
|
2231
|
-
readonly _tag: 'ConnectionMerged';
|
|
2232
|
-
readonly connection: string;
|
|
2233
|
-
readonly page: Segment;
|
|
2234
|
-
/** The page answers the connection's refresh, so the merge also clears `stale`. */
|
|
2235
|
-
readonly refreshes?: boolean | undefined;
|
|
2236
|
-
/**
|
|
2237
|
-
* The slice the query asked for, so the payload's entities write like a
|
|
2238
|
-
* read: one request per matching edge. Absent for a page from a server
|
|
2239
|
-
* that predates payload planning, which carries edges only.
|
|
2240
|
-
*/
|
|
2241
|
-
readonly select?: RelationRequirement | undefined;
|
|
2242
|
-
/** The selected fields of the page's items, as a read batch returns them. */
|
|
2243
|
-
readonly entities?: ReadonlyArray<{
|
|
2244
|
-
readonly entity: string;
|
|
2245
|
-
readonly id: string;
|
|
2246
|
-
readonly values: Record<string, unknown>;
|
|
2247
|
-
}> | undefined;
|
|
2248
|
-
/** Fields asked for that the server settled without a value. */
|
|
2249
|
-
readonly settled?: ReadonlyArray<{
|
|
2250
|
-
readonly entity: string;
|
|
2251
|
-
readonly id: string;
|
|
2252
|
-
readonly fields: ReadonlyArray<string>;
|
|
2253
|
-
}> | undefined;
|
|
2254
|
-
/** Injected clock reading of the answer, dating what the payload writes. */
|
|
2255
|
-
readonly now?: number | undefined;
|
|
2256
|
-
} | {
|
|
2257
|
-
readonly _tag: 'ConnectionInvalidated';
|
|
2258
|
-
readonly connection: string;
|
|
2259
|
-
} | {
|
|
2260
|
-
readonly _tag: 'ConnectionRefreshed';
|
|
2261
|
-
readonly connection: string;
|
|
2262
|
-
} |
|
|
2263
|
-
/**
|
|
2264
|
-
* A query for the connection failed. Its pages stay as they were, and it
|
|
2265
|
-
* reads `Failed` — with them as `previous`, when it has any — until a page
|
|
2266
|
-
* arrives, it is invalidated, or retention drops it.
|
|
2267
|
-
*/
|
|
2268
|
-
{
|
|
2269
|
-
readonly _tag: 'QueryFailed';
|
|
2270
|
-
readonly connection: string;
|
|
2271
|
-
readonly error: RemoteError;
|
|
2272
|
-
} |
|
|
2273
|
-
/**
|
|
2274
|
-
* What `Data.preload` read for a destination, as the Messages that wrote it,
|
|
2275
|
-
* reduced in order into the Model as it is now rather than the one the
|
|
2276
|
-
* preload started from.
|
|
2277
|
-
*/
|
|
2278
|
-
{
|
|
2279
|
-
readonly _tag: 'Preloaded';
|
|
2280
|
-
readonly messages: ReadonlyArray<RemoteMessage>;
|
|
2281
|
-
};
|
|
2282
|
-
declare const retentionRootsSchema: Schema.Struct<{
|
|
2283
|
-
readonly requirements: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
2284
|
-
readonly connections: Schema.$Array<Schema.Struct<{
|
|
2285
|
-
readonly identity: Schema.String;
|
|
2286
|
-
readonly select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
2287
|
-
}>>;
|
|
2288
|
-
}>;
|
|
2289
|
-
/**
|
|
2290
|
-
* The Messages' fields by tag, without `_tag`: what `defineMessageUnion` takes,
|
|
2291
|
-
* so an application spreads them into its own union (`Remote.messages`).
|
|
2292
|
-
*/
|
|
2293
|
-
declare const remoteMessageCases: {
|
|
2294
|
-
ReadReceived: {
|
|
2295
|
-
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
2296
|
-
result: Schema.Struct<{
|
|
2297
|
-
readonly entities: Schema.$Array<Schema.Struct<{
|
|
2298
|
-
readonly entity: Schema.String;
|
|
2299
|
-
readonly id: Schema.String;
|
|
2300
|
-
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
2301
|
-
}>>;
|
|
2302
|
-
readonly settled: Schema.$Array<Schema.Struct<{
|
|
2303
|
-
readonly entity: Schema.String;
|
|
2304
|
-
readonly id: Schema.String;
|
|
2305
|
-
readonly fields: Schema.$Array<Schema.String>;
|
|
2306
|
-
}>>;
|
|
2307
|
-
}>;
|
|
2308
|
-
now: Schema.Number;
|
|
2309
|
-
};
|
|
2310
|
-
ReadFailed: {
|
|
2311
|
-
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
2312
|
-
error: Schema.Struct<{
|
|
2313
|
-
readonly _tag: Schema.String;
|
|
2314
|
-
readonly message: Schema.String;
|
|
2315
|
-
readonly refusal: Schema.optional<Schema.Unknown>;
|
|
2316
|
-
readonly reason: Schema.optional<Schema.String>;
|
|
2317
|
-
}>;
|
|
2318
|
-
stream: Schema.optional<Schema.String>;
|
|
2319
|
-
};
|
|
2320
|
-
RefreshStarted: {
|
|
2321
|
-
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
2322
|
-
};
|
|
2323
|
-
ReadStarted: {
|
|
2324
|
-
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
2325
|
-
refresh: Schema.optional<Schema.Number>;
|
|
2326
|
-
};
|
|
2327
|
-
QueryStarted: {
|
|
2328
|
-
connections: Schema.$Array<Schema.String>;
|
|
2329
|
-
};
|
|
2330
|
-
RetentionChanged: {
|
|
2331
|
-
roots: Schema.Struct<{
|
|
2332
|
-
readonly requirements: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
2333
|
-
readonly connections: Schema.$Array<Schema.Struct<{
|
|
2334
|
-
readonly identity: Schema.String;
|
|
2335
|
-
readonly select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
2336
|
-
}>>;
|
|
2337
|
-
}>;
|
|
2338
|
-
};
|
|
2339
|
-
Hydrated: {
|
|
2340
|
-
connections: Schema.optional<Schema.Unknown>;
|
|
2341
|
-
from: Schema.optional<Schema.String>;
|
|
2342
|
-
entities: Schema.Unknown;
|
|
2343
|
-
merge: Schema.Union<readonly [Schema.Literal<"replace">, Schema.Literal<"preserve-existing">]>;
|
|
2344
|
-
};
|
|
2345
|
-
MutationStarted: {
|
|
2346
|
-
requestId: Schema.String;
|
|
2347
|
-
optimistic: Schema.optional<Schema.$Array<Schema.Unknown>>;
|
|
2348
|
-
};
|
|
2349
|
-
MutationSucceeded: {
|
|
2350
|
-
requestId: Schema.String;
|
|
2351
|
-
entities: Schema.$Array<Schema.Struct<{
|
|
2352
|
-
readonly entity: Schema.String;
|
|
2353
|
-
readonly id: Schema.String;
|
|
2354
|
-
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
2355
|
-
}>>;
|
|
2356
|
-
connections: Schema.optional<Schema.$Array<Schema.Unknown>>;
|
|
2357
|
-
deleted: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
2358
|
-
readonly entity: Schema.String;
|
|
2359
|
-
readonly id: Schema.String;
|
|
2360
|
-
}>>>;
|
|
2361
|
-
now: Schema.Number;
|
|
2362
|
-
};
|
|
2363
|
-
MutationFailed: {
|
|
2364
|
-
requestId: Schema.String;
|
|
2365
|
-
error: Schema.Struct<{
|
|
2366
|
-
readonly _tag: Schema.String;
|
|
2367
|
-
readonly message: Schema.String;
|
|
2368
|
-
readonly refusal: Schema.optional<Schema.Unknown>;
|
|
2369
|
-
readonly reason: Schema.optional<Schema.String>;
|
|
2370
|
-
}>;
|
|
2371
|
-
operation: Schema.String;
|
|
2372
|
-
};
|
|
2373
|
-
OverlayShown: {
|
|
2374
|
-
id: Schema.String;
|
|
2375
|
-
optimistic: Schema.$Array<Schema.Unknown>;
|
|
2376
|
-
};
|
|
2377
|
-
OverlayLifted: {
|
|
2378
|
-
id: Schema.String;
|
|
2379
|
-
};
|
|
2380
|
-
WindowGrown: {
|
|
2381
|
-
window: Schema.String;
|
|
2382
|
-
size: Schema.Number;
|
|
2383
|
-
};
|
|
2384
|
-
LiveReceived: {
|
|
2385
|
-
stream: Schema.String;
|
|
2386
|
-
event: Schema.Unknown;
|
|
2387
|
-
policy: Schema.optional<Schema.Unknown>;
|
|
2388
|
-
now: Schema.Number;
|
|
2389
|
-
};
|
|
2390
|
-
GapCleared: {
|
|
2391
|
-
stream: Schema.String;
|
|
2392
|
-
};
|
|
2393
|
-
ConnectionMerged: {
|
|
2394
|
-
connection: Schema.String;
|
|
2395
|
-
page: Schema.Unknown;
|
|
2396
|
-
refreshes: Schema.optional<Schema.Boolean>;
|
|
2397
|
-
select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
2398
|
-
entities: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
2399
|
-
readonly entity: Schema.String;
|
|
2400
|
-
readonly id: Schema.String;
|
|
2401
|
-
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
2402
|
-
}>>>;
|
|
2403
|
-
settled: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
2404
|
-
readonly entity: Schema.String;
|
|
2405
|
-
readonly id: Schema.String;
|
|
2406
|
-
readonly fields: Schema.$Array<Schema.String>;
|
|
2407
|
-
}>>>;
|
|
2408
|
-
now: Schema.optional<Schema.Number>;
|
|
2409
|
-
};
|
|
2410
|
-
ConnectionInvalidated: {
|
|
2411
|
-
connection: Schema.String;
|
|
2412
|
-
};
|
|
2413
|
-
ConnectionRefreshed: {
|
|
2414
|
-
connection: Schema.String;
|
|
2415
|
-
};
|
|
2416
|
-
QueryFailed: {
|
|
2417
|
-
connection: Schema.String;
|
|
2418
|
-
error: Schema.Struct<{
|
|
2419
|
-
readonly _tag: Schema.String;
|
|
2420
|
-
readonly message: Schema.String;
|
|
2421
|
-
readonly refusal: Schema.optional<Schema.Unknown>;
|
|
2422
|
-
readonly reason: Schema.optional<Schema.String>;
|
|
2423
|
-
}>;
|
|
2424
|
-
};
|
|
2425
|
-
Preloaded: {
|
|
2426
|
-
messages: Schema.$Array<Schema.suspend<Schema.Codec<RemoteMessage, unknown, never, never>>>;
|
|
2427
|
-
};
|
|
2428
|
-
};
|
|
2429
|
-
type RemoteMessageTag = RemoteMessage['_tag'];
|
|
2430
|
-
/**
|
|
2431
|
-
* A Remote Message as an application's union constructs it from
|
|
2432
|
-
* `remoteMessageCases`: the same shape `RemoteMessage` names, with the runtime
|
|
2433
|
-
* slots (`entities`, `event`, `page`) typed `unknown` by their schemas.
|
|
2434
|
-
*/
|
|
2435
|
-
type RemoteMessageInput = { [Tag in RemoteMessageTag]: {
|
|
2436
|
-
readonly _tag: Tag;
|
|
2437
|
-
} & Schema.Struct.Type<(typeof remoteMessageCases)[Tag]>; }[RemoteMessageTag];
|
|
2438
|
-
/**
|
|
2439
|
-
* Whether a Message is one of Remote's, by tag. Narrows an application's union
|
|
2440
|
-
* to its Remote cases, and its complement to the application's own.
|
|
2441
|
-
*/
|
|
2442
|
-
declare const isRemoteMessage: <M extends {
|
|
2443
|
-
readonly _tag: string;
|
|
2444
|
-
}>(message: M) => message is Extract<M, {
|
|
2445
|
-
readonly _tag: RemoteMessageTag;
|
|
2446
|
-
}>;
|
|
2447
|
-
declare const remoteMessageSchema: Schema.Codec<RemoteMessage, unknown>;
|
|
2448
|
-
/** The ids `OverlayShown` shows now, each once, in the order they are drawn. */
|
|
2449
|
-
declare const overlaysOf: (model: RemoteModel) => ReadonlyArray<string>;
|
|
2450
|
-
/** The key a grown window is kept under: its connection and the window first asked for. */
|
|
2451
|
-
declare const windowGrowthKey: (identity: string, window: string) => string;
|
|
2452
|
-
/**
|
|
2453
|
-
* Whether only overlays show this entity: the server has told the store
|
|
2454
|
-
* nothing of it and no request's layer writes it, so nothing will fetch what an
|
|
2455
|
-
* overlay leaves out.
|
|
2456
|
-
*/
|
|
2457
|
-
declare const onlyOverlaid: (model: RemoteModel, entity: string, id: string) => boolean;
|
|
2458
|
-
/** Whether a query for this connection is in flight. */
|
|
2459
|
-
declare const isQueryLoading: (model: RemoteModel, identity: string) => boolean;
|
|
2460
|
-
/**
|
|
2461
|
-
* The generation a read is planned under: the highest any of the fields it
|
|
2462
|
-
* reads or connections it runs was refreshed at. A read entry carries this as a
|
|
2463
|
-
* dependency, so it restarts when what it observes is refreshed and not when
|
|
2464
|
-
* anything else is.
|
|
2465
|
-
*/
|
|
2466
|
-
declare const refreshedAt: (refresh: RefreshState, requests: ReadonlyArray<Requirement>, connections?: ReadonlyArray<string>) => number;
|
|
2467
|
-
/**
|
|
2468
|
-
* Marks every field of `requests` and every connection in `connections`
|
|
2469
|
-
* refreshed at the next generation.
|
|
2470
|
-
*/
|
|
2471
|
-
declare const withRefreshRequested: (refresh: RefreshState, requests: ReadonlyArray<Requirement>, connections?: ReadonlyArray<string>) => RefreshState;
|
|
2472
|
-
/**
|
|
2473
|
-
* Marks connections as needing to be asked again, and restarts a read of them
|
|
2474
|
-
* already in flight: a page requested before what invalidated it could land
|
|
2475
|
-
* after it, saying what is no longer true. `Remote.refresh` marks the same way.
|
|
2476
|
-
*/
|
|
2477
|
-
declare const invalidateConnections: (model: RemoteModel, connections: ReadonlyArray<string>) => RemoteModel;
|
|
2478
|
-
/**
|
|
2479
|
-
* Whether one field's read already began under the generation that field was
|
|
2480
|
-
* last refreshed at. Such a read is in flight and would otherwise outlive the
|
|
2481
|
-
* refresh, so the refresh takes a new generation to restart it even though the
|
|
2482
|
-
* field is already stale.
|
|
2483
|
-
*/
|
|
2484
|
-
declare const refreshIsInFlight: (refresh: RefreshState, request: Requirement, field: string) => boolean;
|
|
2485
|
-
/**
|
|
2486
|
-
* Whether a read is fetching any of `fields` for this entity. Consulted only
|
|
2487
|
-
* when the store lacks the value, which is what separates `Loading` from
|
|
2488
|
-
* `Initial`.
|
|
2489
|
-
*/
|
|
2490
|
-
declare const isLoading: (model: RemoteModel, entity: string, id: string, fields: ReadonlyArray<string>) => boolean;
|
|
2491
|
-
/**
|
|
2492
|
-
* The pure reducer all four producers share. A live event that arrives ahead of
|
|
2493
|
-
* its cursor is a gap: it is not applied, and the stream is recorded so its
|
|
2494
|
-
* live entry restarts it rather than silently missing facts. When every field a Message
|
|
2495
|
-
* touches keeps its identity, `model` itself is returned, so the application's
|
|
2496
|
-
* root keeps its identity and Foldkit does not render. The common no-ops do (a
|
|
2497
|
-
* duplicate live event, a repeated `ReadStarted`); a repeated failure, or a
|
|
2498
|
-
* `preserve-existing` restore of entities already held, still makes an equal
|
|
2499
|
-
* copy.
|
|
2500
|
-
*/
|
|
2501
|
-
declare const updateRemote: (model: RemoteModel, message: RemoteMessage) => RemoteModel;
|
|
2502
|
-
/** Whether this field's last read failed and nothing has settled it since. */
|
|
2503
|
-
declare const isFieldFailed: (model: RemoteModel, entity: string, id: string, field: string) => boolean;
|
|
2504
|
-
/**
|
|
2505
|
-
* Whether a read is fetching any field `relation` reads of an entity, its own
|
|
2506
|
-
* or, through each relation the store holds, its targets'. A value whose owner
|
|
2507
|
-
* is being fetched is loading, not `Initial`: nothing is missing a fetch.
|
|
2508
|
-
*/
|
|
2509
|
-
declare const isLoadingThrough: (model: RemoteModel, entity: string, id: string, relation: RelationRequirement) => boolean;
|
|
2510
|
-
/**
|
|
2511
|
-
* The first failure among the fields `relation` reads of an entity, following
|
|
2512
|
-
* each relation the store holds into its targets, as `assemble` does. A read
|
|
2513
|
-
* that consults it shows `Failed` for a related entity's failure too, rather
|
|
2514
|
-
* than waiting on a field nothing will fetch.
|
|
2515
|
-
*/
|
|
2516
|
-
declare const failureOf: (model: RemoteModel, entity: string, id: string, relation: RelationRequirement) => RemoteError | undefined;
|
|
2517
|
-
/**
|
|
2518
|
-
* Writes a read result into the store, recording each field's applied window so
|
|
2519
|
-
* a later request with a different window refetches. A relation page requested
|
|
2520
|
-
* with a cursor is merged onto the page already stored, so "load more"
|
|
2521
|
-
* accumulates rather than replaces. Every read path should use this rather than
|
|
2522
|
-
* reducing `writeEntity` by hand.
|
|
2523
|
-
*/
|
|
2524
|
-
declare const writeRead: (store: EntityStore, requests: ReadonlyArray<Requirement>, result: Schema.Schema.Type<typeof ReadBatchResult>, now?: number) => EntityStore;
|
|
2525
|
-
/** A query body's `Dependencies` as plain data: each field by its Entity's name and key. */
|
|
2526
|
-
interface ExplainedDependencies {
|
|
2527
|
-
readonly fields: ReadonlyArray<{
|
|
2528
|
-
readonly entity: string;
|
|
2529
|
-
readonly key: string;
|
|
2530
|
-
}>;
|
|
2531
|
-
readonly inputs: Dependencies['inputs'];
|
|
2532
|
-
readonly operations: Dependencies['operations'];
|
|
2533
|
-
/** Each operator it calls, by its id and version. */
|
|
2534
|
-
readonly operators: ReadonlyArray<{
|
|
2535
|
-
readonly id: string;
|
|
2536
|
-
readonly version: number;
|
|
2537
|
-
}>;
|
|
2538
|
-
}
|
|
2539
|
-
/** A serializable summary of a RemoteModel for DevTools and diagnostics. */
|
|
2540
|
-
interface RemoteInspection {
|
|
2541
|
-
readonly entities: ReadonlyArray<{
|
|
2542
|
-
readonly key: string;
|
|
2543
|
-
readonly present: ReadonlyArray<string>;
|
|
2544
|
-
readonly stale: ReadonlyArray<string>;
|
|
2545
|
-
readonly unavailable: ReadonlyArray<string>;
|
|
2546
|
-
readonly tombstone: boolean;
|
|
2547
|
-
readonly updatedAt: number;
|
|
2548
|
-
readonly windows: Readonly<Record<string, string>>;
|
|
2549
|
-
}>;
|
|
2550
|
-
readonly connections: ReadonlyArray<string>;
|
|
2551
|
-
readonly live: ReadonlyArray<string>;
|
|
2552
|
-
readonly gaps: ReadonlyArray<string>;
|
|
2553
|
-
/** Under `verifyPlacement`, each placement the server's page disagreed with. */
|
|
2554
|
-
readonly placementMismatches: ReadonlyArray<PlacementMismatch>;
|
|
2555
|
-
/**
|
|
2556
|
-
* The `entity\0id\0field` marks of reads in flight, and a
|
|
2557
|
-
* `\0connection\0identity` mark for each query in flight. This is what "Remote is
|
|
2558
|
-
* working" means here, and it is read from the Model rather than from the
|
|
2559
|
-
* fibers doing the work: a tool that shows it shows something the Model can
|
|
2560
|
-
* be replayed to, and nothing that needs the runtime to be asked.
|
|
2561
|
-
*/
|
|
2562
|
-
readonly loading: ReadonlyArray<string>;
|
|
2563
|
-
/**
|
|
2564
|
-
* The reads that failed and are not yet settled: queries by connection
|
|
2565
|
-
* identity, entity fields by `entity\0id\0field` mark, each with its error.
|
|
2566
|
-
*/
|
|
2567
|
-
readonly failures: Failures;
|
|
2568
|
-
readonly mutations: {
|
|
2569
|
-
readonly pending: ReadonlyArray<string>;
|
|
2570
|
-
readonly failed: ReadonlyArray<string>;
|
|
2571
|
-
readonly applied: number;
|
|
2572
|
-
};
|
|
2573
|
-
}
|
|
2574
|
-
/** A pure, serializable view of the whole cache. */
|
|
2575
|
-
declare const inspectRemote: (model: RemoteModel) => RemoteInspection;
|
|
2576
|
-
/** A pure, serializable view of one entity, or `undefined` if unknown. */
|
|
2577
|
-
declare const inspectEntity: (model: RemoteModel, key: string) => RemoteInspection['entities'][number] | undefined;
|
|
2578
|
-
/**
|
|
2579
|
-
* Why a read shows what it shows, in words, and for `Initial`, which of the
|
|
2580
|
-
* usual mistakes it is.
|
|
2581
|
-
*
|
|
2582
|
-
* `Initial` means nothing is fetching the read, and that is almost always
|
|
2583
|
-
* wiring rather than the network: no active Surface reads it, or one does and
|
|
2584
|
-
* Remote's Subscriptions are not running. The Model can tell those apart when
|
|
2585
|
-
* it is given the active record, so this says which, and what to do.
|
|
2586
|
-
*/
|
|
2587
|
-
interface ReadDiagnosis {
|
|
2588
|
-
readonly state: RemoteData<unknown>['_tag'];
|
|
2589
|
-
/**
|
|
2590
|
-
* For `Initial` only. `NotObserved`: no active Surface reads it.
|
|
2591
|
-
* `NotFetching`: one does, and nothing is fetching it, so Remote's
|
|
2592
|
-
* Subscriptions are most likely not installed. `Unknown`: no active record
|
|
2593
|
-
* was given to tell.
|
|
2594
|
-
*/
|
|
2595
|
-
readonly reason?: 'NotObserved' | 'NotFetching' | 'Unknown' | undefined;
|
|
2596
|
-
/** One or two sentences a developer can act on. */
|
|
2597
|
-
readonly message: string;
|
|
2598
|
-
/** The active Surfaces reading it, when the active record was given. */
|
|
2599
|
-
readonly surfaces?: ReadonlyArray<string> | undefined;
|
|
2600
|
-
}
|
|
2601
|
-
/**
|
|
2602
|
-
* What one query read is, and what it currently is — data-query-DESIGN §29.1.
|
|
2603
|
-
*
|
|
2604
|
-
* Every member is gathered from something that already existed: the read was
|
|
2605
|
-
* always this many pieces, and nothing had ever been asked to put them in one
|
|
2606
|
-
* place. It is plain serializable data, so a DevTools panel, a log line and a
|
|
2607
|
-
* test assert on the same value.
|
|
2608
|
-
*
|
|
2609
|
-
* Two members of §29.1's sketch are **not** here, and their absence is the
|
|
2610
|
-
* finding rather than an omission:
|
|
2611
|
-
*
|
|
2612
|
-
* - **Surface.** A Projection does not know which Surface reads it, and often
|
|
2613
|
-
* several do — so it is not a property of the read, and `explain` cannot
|
|
2614
|
-
* recover it alone. Given the active Surfaces (the same record
|
|
2615
|
-
* `subscriptions` takes), it reports **every** Surface reading the connection
|
|
2616
|
-
* rather than guessing one, and omits the member entirely when it was not
|
|
2617
|
-
* given them.
|
|
2618
|
-
* - **Executor.** The thing that answers a query is a `RemoteClient` Layer in
|
|
2619
|
-
* the runtime, not a value in the Model, and a pure read of the Model cannot
|
|
2620
|
-
* see it. That is the same boundary that makes this function pure and
|
|
2621
|
-
* replayable, so it is worth more than the line of text.
|
|
2622
|
-
*
|
|
2623
|
-
* And one that the design proposed and this does not want: *expectation*
|
|
2624
|
-
* (required versus optional). §11 left it unbuilt for want of a consumer, and
|
|
2625
|
-
* the explanation was the likeliest consumer. It turns out not to need it — a
|
|
2626
|
-
* query's result is a connection, so the shape is a `Page`, decided by the
|
|
2627
|
-
* definition rather than by the read. Nothing here has an opinion about whether
|
|
2628
|
-
* an empty one is an error, because nothing here has to have one.
|
|
2629
|
-
*/
|
|
2630
|
-
interface QueryExplanation {
|
|
2631
|
-
/** The bound Remote domain that answers it. */
|
|
2632
|
-
readonly domain: string;
|
|
2633
|
-
/** The definition's name. */
|
|
2634
|
-
readonly query: string;
|
|
2635
|
-
/** The input as encoded, which is what the identity is built from. */
|
|
2636
|
-
readonly input: unknown;
|
|
2637
|
-
/** The connection identity: definition plus canonical input, excluding the window. */
|
|
2638
|
-
readonly identity: string;
|
|
2639
|
-
/** How much of the connection this read asks for. */
|
|
2640
|
-
readonly window: QueryWindow;
|
|
2641
|
-
/** What it reads of each item, as the slice asked of the server. */
|
|
2642
|
-
readonly select: RelationRequirement;
|
|
2643
|
-
/**
|
|
2644
|
-
* What the query means, as readable text — `Query.show`, and so neither SQL
|
|
2645
|
-
* nor whatever the backend compiled. Absent for a definition made with
|
|
2646
|
-
* `Query.make`, whose meaning lives on the server that answers it.
|
|
2647
|
-
*/
|
|
2648
|
-
readonly body?: string | undefined;
|
|
2649
|
-
/**
|
|
2650
|
-
* The fields, inputs and operations the body reads; absent with the body.
|
|
2651
|
-
* Plain data, so it serializes: a field is its Entity's name and key, which
|
|
2652
|
-
* is unambiguous because a query reads one Entity.
|
|
2653
|
-
*/
|
|
2654
|
-
readonly dependencies?: ExplainedDependencies | undefined;
|
|
2655
|
-
/** What the read answers from this Model right now. */
|
|
2656
|
-
readonly state: RemoteData<unknown>['_tag'];
|
|
2657
|
-
/**
|
|
2658
|
-
* The active Surfaces reading this connection at this Model, if the active
|
|
2659
|
-
* record was supplied. Plural because several may, which is why a Projection
|
|
2660
|
-
* cannot carry the answer itself.
|
|
2661
|
-
*/
|
|
2662
|
-
readonly surfaces?: ReadonlyArray<string> | undefined;
|
|
2663
|
-
/**
|
|
2664
|
-
* Why each of those Surfaces is active, where it was placed with
|
|
2665
|
-
* `Surface.when` — the Model path and the tag, without running anything. A
|
|
2666
|
-
* Surface placed with `Surface.at` has no entry: a callback cannot be read.
|
|
2667
|
-
*/
|
|
2668
|
-
readonly activation?: ReadonlyArray<{
|
|
2669
|
-
readonly surface: string;
|
|
2670
|
-
readonly path: readonly string[];
|
|
2671
|
-
readonly tag: string;
|
|
2672
|
-
}> | undefined;
|
|
2673
|
-
}
|
|
2674
|
-
type Window = NonNullable<Requirement['windows']>[string];
|
|
2675
|
-
/** A stable key for a window, so two equal windows compare equal. */
|
|
2676
|
-
declare const windowKey: (window: Window) => string;
|
|
2677
|
-
interface PlanFreshness {
|
|
2678
|
-
readonly now: number;
|
|
2679
|
-
/** A present entry older than this many milliseconds is refreshed whole. */
|
|
2680
|
-
readonly freshness: number;
|
|
2681
|
-
}
|
|
2682
|
-
interface PlanOptions {
|
|
2683
|
-
readonly freshness?: PlanFreshness | undefined;
|
|
2684
|
-
/** Plan every requested field, present or not, tombstoned or not. */
|
|
2685
|
-
readonly force?: boolean | undefined;
|
|
2686
|
-
}
|
|
2687
|
-
/** When present values next go stale, and the requirements of the entities that do. */
|
|
2688
|
-
interface Deadline {
|
|
2689
|
-
readonly at: number;
|
|
2690
|
-
readonly due: ReadonlyArray<Requirement>;
|
|
2691
|
-
}
|
|
2692
|
-
/**
|
|
2693
|
-
* The earliest moment a value `requirements` read, following the relations the
|
|
2694
|
-
* store holds as `plan` does, goes stale under `freshness`, with the
|
|
2695
|
-
* requirements of the entities that go stale then. A field the server settled
|
|
2696
|
-
* without a value ages with its entity too, since `plan` asks for it again once
|
|
2697
|
-
* the entity expires. Nothing when no such field is still fresh: what is
|
|
2698
|
-
* already expired or stale is planned, not awaited, which is what keeps a
|
|
2699
|
-
* timer from firing on what it already fired on. It is the next moment the
|
|
2700
|
-
* plan can change with the clock alone, which the read entry relies on to
|
|
2701
|
-
* reuse its plan until then.
|
|
2702
|
-
*/
|
|
2703
|
-
declare const deadlineOf: (store: EntityStore, requirements: readonly Requirement[], freshness: PlanFreshness) => Deadline | undefined;
|
|
2704
|
-
declare const plan: (store: EntityStore, requirements: readonly Requirement[], options?: PlanOptions) => ReadonlyArray<Requirement>;
|
|
2705
|
-
type RemotePolicy =
|
|
2706
|
-
/** Fetch only fields the store lacks (missing, stale, or re-windowed). */
|
|
2707
|
-
{
|
|
2708
|
-
readonly _tag: 'CacheFirst';
|
|
2709
|
-
} |
|
|
2710
|
-
/**
|
|
2711
|
-
* Keep present values visible, read them as `Refreshing`, and refetch an
|
|
2712
|
-
* entry older than `maxAge` milliseconds.
|
|
2713
|
-
*/
|
|
2714
|
-
{
|
|
2715
|
-
readonly _tag: 'StaleWhileRevalidate';
|
|
2716
|
-
readonly maxAge: number;
|
|
2717
|
-
} |
|
|
2718
|
-
/** Fetch every selected field regardless of coverage; cached values stay visible meanwhile. */
|
|
2719
|
-
{
|
|
2720
|
-
readonly _tag: 'NetworkOnly';
|
|
2721
|
-
};
|
|
2722
|
-
declare const RemotePolicy: {
|
|
2723
|
-
/** Fetch only what the store lacks. */
|
|
2724
|
-
cacheFirst: {
|
|
2725
|
-
readonly _tag: 'CacheFirst';
|
|
2726
|
-
};
|
|
2727
|
-
/** Keep present values visible, read as `Refreshing`, and refetch an entry older than `maxAge` ms. */
|
|
2728
|
-
staleWhileRevalidate: (options: {
|
|
2729
|
-
readonly maxAge: number;
|
|
2730
|
-
}) => RemotePolicy;
|
|
2731
|
-
/** Fetch every selected field regardless of coverage; cached values stay visible meanwhile. */
|
|
2732
|
-
networkOnly: {
|
|
2733
|
-
readonly _tag: 'NetworkOnly';
|
|
2734
|
-
};
|
|
2735
|
-
/** The planner options a policy compiles to at `now`. */
|
|
2736
|
-
toPlan: (policy: RemotePolicy, now: number) => PlanOptions;
|
|
2737
|
-
/**
|
|
2738
|
-
* Whether a read under this policy may refetch fields the store already
|
|
2739
|
-
* holds, so an observer marks them stale (read as `Refreshing`) while the
|
|
2740
|
-
* request is pending.
|
|
2741
|
-
*/
|
|
2742
|
-
refreshes: (policy: RemotePolicy) => boolean;
|
|
2743
|
-
};
|
|
2744
|
-
/**
|
|
2745
|
-
* A resume part, in the shape `foldkit-ssr`'s `SSR.plan` takes in `parts`.
|
|
2746
|
-
* Declared here structurally, so neither package depends on the other.
|
|
2747
|
-
*/
|
|
2748
|
-
interface RemoteResumePart<AppModel> {
|
|
2749
|
-
readonly id: string;
|
|
2750
|
-
/** The metadata key names whose reads this part resumes. */
|
|
2751
|
-
readonly covers: ReadonlyArray<string>;
|
|
2752
|
-
readonly capture: (model: AppModel, projections: ReadonlyArray<{
|
|
2753
|
-
readonly metadata: Metadata;
|
|
2754
|
-
}>) => unknown;
|
|
2755
|
-
readonly restore: (model: AppModel, value: unknown) => Result.Result<AppModel, string>;
|
|
2756
|
-
/** Whether a Subscription entry is one of this domain's, which may start late. */
|
|
2757
|
-
readonly deferrable: (key: string, entry: unknown) => boolean;
|
|
2758
|
-
}
|
|
2759
|
-
/**
|
|
2760
|
-
* The resume part for a Remote domain, for `SSR.plan`'s `parts`: it sends
|
|
2761
|
-
* what the plan's active Surfaces read from this domain's store, and nothing
|
|
2762
|
-
* else of it. `id` tells two domains in one application apart.
|
|
2763
|
-
*/
|
|
2764
|
-
declare const resumePart: <AppModel, Store extends RemoteModel>(domain: {
|
|
2765
|
-
readonly store: ModelRef<AppModel, Store>;
|
|
2766
|
-
}, options?: {
|
|
2767
|
-
readonly id?: string | undefined;
|
|
2768
|
-
}) => RemoteResumePart<AppModel>;
|
|
2769
|
-
/** A request: which of Remote's calls, and its payload as the RPC protocol encodes it. */
|
|
2770
|
-
declare const RemoteJsonRequest: Schema.Struct<{
|
|
2771
|
-
readonly operation: Schema.Literals<readonly ["read", "query", "mutate"]>;
|
|
2772
|
-
readonly payload: Schema.Unknown;
|
|
2773
|
-
}>;
|
|
2774
|
-
type RemoteJsonRequest = typeof RemoteJsonRequest.Type;
|
|
2775
|
-
/** An answer: the call's result, or why there is none. */
|
|
2776
|
-
declare const RemoteJsonAnswer: Schema.Union<readonly [Schema.Struct<{
|
|
2777
|
-
readonly result: Schema.Unknown;
|
|
2778
|
-
}>, Schema.Struct<{
|
|
2779
|
-
readonly error: Schema.String;
|
|
2780
|
-
readonly refusal: Schema.optional<Schema.Unknown>;
|
|
2781
|
-
/** Who is asking was refused, with the application's reason when it gave one. */
|
|
2782
|
-
readonly forbidden: Schema.optional<Schema.Struct<{
|
|
2783
|
-
readonly reason: Schema.optional<Schema.String>;
|
|
2784
|
-
}>>;
|
|
2785
|
-
/** Who is asking could not be told, with the reason when one was given; a 401. */
|
|
2786
|
-
readonly unauthenticated: Schema.optional<Schema.Struct<{
|
|
2787
|
-
readonly reason: Schema.optional<Schema.String>;
|
|
2788
|
-
}>>;
|
|
2789
|
-
}>]>;
|
|
2790
|
-
type RemoteJsonAnswer = typeof RemoteJsonAnswer.Type;
|
|
2791
|
-
/**
|
|
2792
|
-
* Sends one request's text and resolves with its answer as parsed JSON. It
|
|
2793
|
-
* rejects when nothing came back, and the call fails with that message.
|
|
2794
|
-
*/
|
|
2795
|
-
type RemoteJsonSend = (request: string) => Promise<unknown>;
|
|
2796
|
-
/** Remote's client over `send`, for `Remote.clientLayer`. */
|
|
2797
|
-
declare const json: (send: RemoteJsonSend) => RemoteRpcClient;
|
|
2798
|
-
/**
|
|
2799
|
-
* Remote's client over HTTP: each call a `POST` of the request to `url`, the
|
|
2800
|
-
* answer its JSON body whatever its status. A 401 is answered as
|
|
2801
|
-
* unauthenticated, for every call kind, and a 403 as forbidden, whatever the
|
|
2802
|
-
* body says: the server's own says why, and middleware in front of Remote
|
|
2803
|
-
* may say anything.
|
|
2804
|
-
* `headers` is read per request, so a token that changes reaches the next
|
|
2805
|
-
* call. `fetch` defaults to the global one; pass it to route calls through
|
|
2806
|
-
* another implementation in tests.
|
|
2807
|
-
*/
|
|
2808
|
-
declare const http: (url: string, options?: {
|
|
2809
|
-
readonly headers?: (() => Readonly<Record<string, string>>) | undefined;
|
|
2810
|
-
readonly fetch?: typeof fetch | undefined;
|
|
2811
|
-
}) => RemoteRpcClient;
|
|
2812
|
-
/** What `httpWithLive` needs besides the URL. Mirrors `http`, plus the fetch itself. */
|
|
2813
|
-
interface LiveFetchOptions {
|
|
2814
|
-
/** Read per request, so a token that changes reaches the next call. */
|
|
2815
|
-
readonly headers?: (() => Readonly<Record<string, string>>) | undefined;
|
|
2816
|
-
/** Defaults to the global one; pass it to route calls elsewhere in tests. */
|
|
2817
|
-
readonly fetch?: typeof fetch | undefined;
|
|
2818
|
-
}
|
|
2819
|
-
/** Remote's live stream over fetch: `serveFetch`'s live open as a `Stream`. */
|
|
2820
|
-
declare const liveFetch: (url: string, options?: LiveFetchOptions) => RemoteRpcClient['FoldkitRemoteLive'];
|
|
2821
|
-
/**
|
|
2822
|
-
* Remote's client over HTTP with live: reads, queries, and mutations as
|
|
2823
|
-
* `http` sends them, live as `liveFetch` streams it, for `clientLayer`.
|
|
2824
|
-
*/
|
|
2825
|
-
declare const httpWithLive: (url: string, options?: LiveFetchOptions) => RemoteRpcClient;
|
|
2826
|
-
/** Where a row falls in a loaded list. */
|
|
2827
|
-
type RowPlace = Data.TaggedEnum<{
|
|
2828
|
-
/** Just before this edge, in this segment. */
|
|
2829
|
-
Before: {
|
|
2830
|
-
readonly segment: number;
|
|
2831
|
-
readonly edge: string;
|
|
2832
|
-
};
|
|
2833
|
-
/** After every edge of this segment, which ends the list. */
|
|
2834
|
-
End: {
|
|
2835
|
-
readonly segment: number;
|
|
2836
|
-
};
|
|
2837
|
-
/** In rows the list has not loaded: past a `Cursor` boundary, or in a gap. */
|
|
2838
|
-
Outside: {};
|
|
2839
|
-
/** Not judged exactly, and why. */
|
|
2840
|
-
Unknown: {
|
|
2841
|
-
readonly reason: string;
|
|
2842
|
-
};
|
|
2843
|
-
}>;
|
|
2844
|
-
declare const RowPlace: {
|
|
2845
|
-
readonly $is: <Tag extends "Before" | "End" | "Outside" | "Unknown">(tag: Tag) => (u: unknown) => u is Extract<{
|
|
2846
|
-
readonly _tag: "Before";
|
|
2847
|
-
readonly segment: number;
|
|
2848
|
-
readonly edge: string;
|
|
2849
|
-
}, {
|
|
2850
|
-
readonly _tag: Tag;
|
|
2851
|
-
}> | Extract<{
|
|
2852
|
-
readonly _tag: "End";
|
|
2853
|
-
readonly segment: number;
|
|
2854
|
-
}, {
|
|
2855
|
-
readonly _tag: Tag;
|
|
2856
|
-
}> | Extract<{
|
|
2857
|
-
readonly _tag: "Outside";
|
|
2858
|
-
}, {
|
|
2859
|
-
readonly _tag: Tag;
|
|
2860
|
-
}> | Extract<{
|
|
2861
|
-
readonly _tag: "Unknown";
|
|
2862
|
-
readonly reason: string;
|
|
2863
|
-
}, {
|
|
2864
|
-
readonly _tag: Tag;
|
|
2865
|
-
}>;
|
|
2866
|
-
readonly $match: {
|
|
2867
|
-
<Cases extends { readonly [Tag in "Before" | "End" | "Outside" | "Unknown"]: (args: Extract<{
|
|
2868
|
-
readonly _tag: "Before";
|
|
2869
|
-
readonly segment: number;
|
|
2870
|
-
readonly edge: string;
|
|
2871
|
-
} | {
|
|
2872
|
-
readonly _tag: "End";
|
|
2873
|
-
readonly segment: number;
|
|
2874
|
-
} | {
|
|
2875
|
-
readonly _tag: "Outside";
|
|
2876
|
-
} | {
|
|
2877
|
-
readonly _tag: "Unknown";
|
|
2878
|
-
readonly reason: string;
|
|
2879
|
-
}, {
|
|
2880
|
-
readonly _tag: Tag;
|
|
2881
|
-
}>) => any; }>(cases: Cases): (value: {
|
|
2882
|
-
readonly _tag: "Before";
|
|
2883
|
-
readonly segment: number;
|
|
2884
|
-
readonly edge: string;
|
|
2885
|
-
} | {
|
|
2886
|
-
readonly _tag: "End";
|
|
2887
|
-
readonly segment: number;
|
|
2888
|
-
} | {
|
|
2889
|
-
readonly _tag: "Outside";
|
|
2890
|
-
} | {
|
|
2891
|
-
readonly _tag: "Unknown";
|
|
2892
|
-
readonly reason: string;
|
|
2893
|
-
}) => import("effect/Unify").Unify<ReturnType<Cases["Before" | "End" | "Outside" | "Unknown"]>>;
|
|
2894
|
-
<Cases extends { readonly [Tag in "Before" | "End" | "Outside" | "Unknown"]: (args: Extract<{
|
|
2895
|
-
readonly _tag: "Before";
|
|
2896
|
-
readonly segment: number;
|
|
2897
|
-
readonly edge: string;
|
|
2898
|
-
} | {
|
|
2899
|
-
readonly _tag: "End";
|
|
2900
|
-
readonly segment: number;
|
|
2901
|
-
} | {
|
|
2902
|
-
readonly _tag: "Outside";
|
|
2903
|
-
} | {
|
|
2904
|
-
readonly _tag: "Unknown";
|
|
2905
|
-
readonly reason: string;
|
|
2906
|
-
}, {
|
|
2907
|
-
readonly _tag: Tag;
|
|
2908
|
-
}>) => any; }>(value: {
|
|
2909
|
-
readonly _tag: "Before";
|
|
2910
|
-
readonly segment: number;
|
|
2911
|
-
readonly edge: string;
|
|
2912
|
-
} | {
|
|
2913
|
-
readonly _tag: "End";
|
|
2914
|
-
readonly segment: number;
|
|
2915
|
-
} | {
|
|
2916
|
-
readonly _tag: "Outside";
|
|
2917
|
-
} | {
|
|
2918
|
-
readonly _tag: "Unknown";
|
|
2919
|
-
readonly reason: string;
|
|
2920
|
-
}, cases: Cases): import("effect/Unify").Unify<ReturnType<Cases["Before" | "End" | "Outside" | "Unknown"]>>;
|
|
2921
|
-
};
|
|
2922
|
-
readonly Before: Data.TaggedEnum.ConstructorFrom<{
|
|
2923
|
-
readonly _tag: "Before";
|
|
2924
|
-
readonly segment: number;
|
|
2925
|
-
readonly edge: string;
|
|
2926
|
-
}, "_tag">;
|
|
2927
|
-
readonly End: Data.TaggedEnum.ConstructorFrom<{
|
|
2928
|
-
readonly _tag: "End";
|
|
2929
|
-
readonly segment: number;
|
|
2930
|
-
}, "_tag">;
|
|
2931
|
-
readonly Outside: Data.TaggedEnum.ConstructorFrom<{
|
|
2932
|
-
readonly _tag: "Outside";
|
|
2933
|
-
}, "_tag">;
|
|
2934
|
-
readonly Unknown: Data.TaggedEnum.ConstructorFrom<{
|
|
2935
|
-
readonly _tag: "Unknown";
|
|
2936
|
-
readonly reason: string;
|
|
2937
|
-
}, "_tag">;
|
|
2938
|
-
};
|
|
2939
|
-
/**
|
|
2940
|
-
* Where the row stored under `key` falls in `connection`, by `body`'s order
|
|
2941
|
-
* for `input` (encoded, as a connection's identity carries it), a call in it
|
|
2942
|
-
* run by `operators`. The row's own edge, if the list holds it, is left out:
|
|
2943
|
-
* placing a row that moved asks where it goes now.
|
|
2944
|
-
*/
|
|
2945
|
-
declare const placeIn: (store: EntityStore, connection: Connection, body: AnyQuery, input: Readonly<Record<string, unknown>>, key: string, operators: MemoryOperators) => RowPlace;
|
|
2946
|
-
/** What a domain registers: a Remote descriptor, or a `foldkit-entity` Entity (read through `Entity.from`). */
|
|
2947
|
-
type EntityLike = EntityDescriptor<any, any> | Domain.AnyEntity;
|
|
2948
|
-
/**
|
|
2949
|
-
* What a read selects: a Remote Selection, or a `foldkit-entity` Selection
|
|
2950
|
-
* (read through `Selection.from`).
|
|
2951
|
-
*/
|
|
2952
|
-
type EntitySelection<Value, Name extends string, Id extends string = string> = Selection<Value, Name, 'entity'> | Domain.Selection<Name, unknown, Schema.Constraint & {
|
|
2953
|
-
readonly Type: Value;
|
|
2954
|
-
}, Id>;
|
|
2955
|
-
/** The Remote descriptor either kind of entity reads as, at the type level. */
|
|
2956
|
-
type DescriptorOf<E extends EntityLike> = E extends EntityDescriptor<any, any> ? E : E extends Domain.AnyEntity ? EntityDescriptor<E['name'], FieldsFrom<E>> : never;
|
|
2957
|
-
type NameOf<E extends EntityLike> = DescriptorOf<E> extends EntityDescriptor<infer N, any> ? N : never;
|
|
2958
|
-
type FieldsOf<E extends EntityLike> = DescriptorOf<E> extends EntityDescriptor<any, infer F> ? F : never;
|
|
2959
|
-
type EntityName<D> = D extends {
|
|
2960
|
-
readonly name: infer Name extends string;
|
|
2961
|
-
} ? Name : never;
|
|
2962
|
-
type QueryName<D> = D extends QueryDescriptor<infer Name, any, any> ? Name : never;
|
|
2963
|
-
type MutationName<D> = D extends MutationDescriptor<infer Name, any, any> ? Name : never;
|
|
2964
|
-
/**
|
|
2965
|
-
* Nothing when `Name` is one of the domain's registered `Names`; otherwise a
|
|
2966
|
-
* branded failure naming the descriptor, so `Data.get(Team.select(…))` for an
|
|
2967
|
-
* unregistered `Team` errors at the selection in one line.
|
|
2968
|
-
*/
|
|
2969
|
-
type Registered<Name extends string, Names extends string, Kind extends string> = [Name] extends [Names] ? unknown : Invalid<`${Kind} "${Name}" is not registered with this Remote domain`>;
|
|
2970
|
-
/** Nothing when a selection is of the query's entity; otherwise a branded failure naming both. */
|
|
2971
|
-
type SelectsEntity<Entity extends string, Of extends string> = [Entity] extends [Of] ? unknown : Invalid<`the selection is of "${Entity}", but the query lists "${Of}"`>;
|
|
2972
|
-
interface RemoteDescriptor<Entities extends readonly EntityLike[] = readonly EntityLike[], Queries extends readonly QueryDescriptor<any, any, any>[] = readonly QueryDescriptor<any, any, any>[], Mutations extends readonly MutationDescriptor<any, any, any>[] = readonly MutationDescriptor<any, any, any>[]> {
|
|
2973
|
-
readonly entities: Entities;
|
|
2974
|
-
readonly queries: Queries;
|
|
2975
|
-
readonly mutations: Mutations;
|
|
2976
|
-
readonly Model: Schema.Codec<RemoteModel, unknown>;
|
|
2977
|
-
readonly initial: RemoteModel;
|
|
2978
|
-
readonly Message: Schema.Schema<RemoteMessage>;
|
|
2979
|
-
readonly update: (model: RemoteModel, message: RemoteMessage) => RemoteModel;
|
|
2980
|
-
readonly rpc: typeof RemoteRpc;
|
|
2981
|
-
/** Name-keyed lookups built from the declared entities, queries, and mutations. */
|
|
2982
|
-
readonly registry: {
|
|
2983
|
-
readonly entities: ReadonlyMap<string, EntityDescriptor<any, any>>;
|
|
2984
|
-
readonly queries: ReadonlyMap<string, QueryDescriptor<any, any, any>>;
|
|
2985
|
-
readonly mutations: ReadonlyMap<string, MutationDescriptor<any, any, any>>;
|
|
2986
|
-
/**
|
|
2987
|
-
* Per entity name, the members its server filters rows by under a rule
|
|
2988
|
-
* the client does not run (`ReadFilter`), so a change to one is fetched,
|
|
2989
|
-
* not placed.
|
|
2990
|
-
*/
|
|
2991
|
-
readonly filtered: ReadonlyMap<string, ReadonlyArray<string>>;
|
|
2992
|
-
};
|
|
2993
|
-
}
|
|
2994
|
-
declare const boundRemoteNames: unique symbol;
|
|
2995
|
-
interface BoundRemote<AppModel, Store extends RemoteModel, Names extends string = string> {
|
|
2996
|
-
readonly definition: RemoteDescriptor;
|
|
2997
|
-
readonly store: ModelRef<AppModel, Store>;
|
|
2998
|
-
/** For `Module`: owns the store's Model path. */
|
|
2999
|
-
readonly contract: Contract;
|
|
3000
|
-
/** Phantom: the entity names this Remote definition registers. */
|
|
3001
|
-
readonly [boundRemoteNames]?: Names;
|
|
3002
|
-
}
|
|
3003
|
-
type MutationInput<M> = M extends MutationDescriptor<any, infer Input, any> ? Input : never;
|
|
3004
|
-
/** How `Data.persistence` keeps the cache across a reload. */
|
|
3005
|
-
interface PersistenceOptions<AppModel> {
|
|
3006
|
-
/**
|
|
3007
|
-
* Where the snapshot is stored, from the Model: one key per principal, so a
|
|
3008
|
-
* change of principal reads and writes another snapshot.
|
|
3009
|
-
*/
|
|
3010
|
-
readonly key: (model: AppModel) => string;
|
|
3011
|
-
/** Who the snapshot is for; one taken under another scope is discarded. */
|
|
3012
|
-
readonly scope: (model: AppModel) => string;
|
|
3013
|
-
/** The query connections whose rows survive a reload; none by default. */
|
|
3014
|
-
readonly connections?: ReadonlyArray<ConnectionIdentity> | undefined;
|
|
3015
|
-
/** What to keep, when it is not `snapshotOf` the `connections`. */
|
|
3016
|
-
readonly snapshot?: ((remote: RemoteModel) => Snapshot) | undefined;
|
|
3017
|
-
/** A snapshot larger than this is neither written nor read. */
|
|
3018
|
-
readonly maxBytes?: number | undefined;
|
|
3019
|
-
/** How long the cache must be unchanged before it is written; default 250 milliseconds. */
|
|
3020
|
-
readonly debounce?: Duration.Input | undefined;
|
|
3021
|
-
}
|
|
3022
|
-
interface DomainMutateOptions {
|
|
3023
|
-
/** Overrides the generated id, for a retry, a durable bridge, or a test. */
|
|
3024
|
-
readonly requestId?: string | undefined;
|
|
3025
|
-
/**
|
|
3026
|
-
* What the request changes before the server answers, released when it
|
|
3027
|
-
* settles. A function receives the generated ids, so a created entity can
|
|
3028
|
-
* carry `tempId` until the result names the real one.
|
|
3029
|
-
*/
|
|
3030
|
-
readonly optimistic?: ReadonlyArray<OptimisticOperation> | ((ids: {
|
|
3031
|
-
readonly requestId: string;
|
|
3032
|
-
readonly tempId: string;
|
|
3033
|
-
}) => ReadonlyArray<OptimisticOperation>) | undefined;
|
|
3034
|
-
/** The clock `MutationSucceeded` stamps the answer with; default `Date.now`, read at each use. */
|
|
3035
|
-
readonly now?: (() => number) | undefined;
|
|
3036
|
-
/**
|
|
3037
|
-
* For a mutation that is a `Write`: the input keys to write, when only some
|
|
3038
|
-
* changed (what an author edited). The rest of the input is still sent, whole.
|
|
3039
|
-
*/
|
|
3040
|
-
readonly keys?: ReadonlyArray<string> | undefined;
|
|
3041
|
-
}
|
|
3042
|
-
/**
|
|
3043
|
-
* One entry of the active record `subscriptions`, `wiring` and `satisfy`
|
|
3044
|
-
* take: a Surface as the Model activates it (`Surface.at`/`Surface.when`),
|
|
3045
|
-
* a source of keyed instances (`Surface.each`, or any `SurfaceSource`), or a
|
|
3046
|
-
* Surface without params read whole. A family joins its parent's
|
|
3047
|
-
* requirements with its instances', so passing the family alone fetches both
|
|
3048
|
-
* the page and what the page reveals.
|
|
3049
|
-
*/
|
|
3050
|
-
type ActiveEntry<AppModel> = ActiveSurface<AppModel> | Surface<AppModel, any, any, void> | SurfaceSource<AppModel>;
|
|
3051
|
-
/** A Foldkit Subscription entry of the Remote domain, emitting its Messages through `RemoteClient`. */
|
|
3052
|
-
type RemoteEntry<AppModel, Dependencies> = EntryWithoutKeepAlive<AppModel, RemoteMessage, Dependencies, RemoteClient>;
|
|
3053
|
-
/**
|
|
3054
|
-
* The entries `RemoteDomain.subscriptions` returns for an active record: a read
|
|
3055
|
-
* and a live entry per key (the live one idles when nothing is read live), and
|
|
3056
|
-
* `retain`.
|
|
3057
|
-
*/
|
|
3058
|
-
type SubscriptionEntries<AppModel, Active, Message = RemoteMessage> = { readonly [K in keyof Active & (string | number) as `${K}.read`]: EntryWithoutKeepAlive<AppModel, Message, ReadDependencies, RemoteClient>; } & { readonly [K in keyof Active & (string | number) as `${K}.live`]: EntryWithoutKeepAlive<AppModel, Message, LiveDependencies, RemoteClient>; } & {
|
|
3059
|
-
readonly retain: EntryWithoutKeepAlive<AppModel, Message, RetentionRoots, never>;
|
|
3060
|
-
};
|
|
3061
|
-
/** The dependencies of a live entry: what it subscribes to, and where a restart resumes. */
|
|
3062
|
-
interface LiveDependencies {
|
|
3063
|
-
readonly requirements: ReadonlyArray<Requirement>;
|
|
3064
|
-
readonly cursor: LiveCursor;
|
|
3065
|
-
readonly floor: number;
|
|
3066
|
-
/** How many times the stream broke; each break restarts it. */
|
|
3067
|
-
readonly restarts: number;
|
|
3068
|
-
/** Breaks since its last applied event, which the restart's backoff grows with. */
|
|
3069
|
-
readonly failures: number;
|
|
3070
|
-
}
|
|
3071
|
-
/**
|
|
3072
|
-
* Whether what an active entry reads live is arriving. `Reconnecting` is a
|
|
3073
|
-
* stream that broke and waits to resubscribe; until it has, changes are
|
|
3074
|
-
* missed, and its rows may be out of date.
|
|
3075
|
-
*/
|
|
3076
|
-
type LiveStatus =
|
|
3077
|
-
/** It reads nothing live. */
|
|
3078
|
-
{
|
|
3079
|
-
readonly _tag: 'Idle';
|
|
3080
|
-
} |
|
|
3081
|
-
/** Subscribed, and not broken since. */
|
|
3082
|
-
{
|
|
3083
|
-
readonly _tag: 'Live';
|
|
3084
|
-
} | {
|
|
3085
|
-
readonly _tag: 'Reconnecting';
|
|
3086
|
-
/** Breaks in a row, the first being 1. */
|
|
3087
|
-
readonly attempt: number;
|
|
3088
|
-
/** Why it broke; none for a gap in its events. */
|
|
3089
|
-
readonly error: Option.Option<RemoteError>;
|
|
3090
|
-
};
|
|
3091
|
-
interface SubscriptionsOptions extends ObserveOptions, LiveOptions, RetainOptions {}
|
|
3092
|
-
/** A Remote domain's wiring for an assembly: it routes Remote's Messages into `reduce`, brings its Subscriptions and contract, and requires `RemoteClient` from the runtime's resources Layer. */
|
|
3093
|
-
type RemoteWiring<AppModel> = Wiring<AppModel, RemoteMessage | RemoteMessageInput, RemoteClient, keyof typeof remoteMessageCases>;
|
|
3094
|
-
/** What `RemoteDomain.mutate` hands `update`: the Model with the request started, and the Command that settles it. */
|
|
3095
|
-
interface MutationStarted<AppModel> {
|
|
3096
|
-
readonly model: AppModel;
|
|
3097
|
-
readonly requestId: string;
|
|
3098
|
-
readonly tempId: string;
|
|
3099
|
-
/** Yields `MutationSucceeded` or `MutationFailed`; never fails. */
|
|
3100
|
-
readonly command: Command<RemoteMessage, never, RemoteClient>;
|
|
3101
|
-
}
|
|
3102
|
-
/**
|
|
3103
|
-
* A Remote domain bound to its place in the application Model: the descriptor
|
|
3104
|
-
* (`Remote.define`), the binding (`Remote.at`), and the application-facing
|
|
3105
|
-
* operations over them. Every method compiles to the `Remote.*` function of the
|
|
3106
|
-
* same name, which stays exported for tooling, SSR, and tests.
|
|
3107
|
-
*/
|
|
3108
|
-
interface RemoteDomain<AppModel, Store extends RemoteModel, Entities extends readonly EntityLike[], Queries extends readonly QueryDescriptor<any, any, any>[], Mutations extends readonly MutationDescriptor<any, any, any>[]> extends BoundRemote<AppModel, Store, EntityName<Entities[number]>>, RemoteDescriptor<Entities, Queries, Mutations> {
|
|
3109
|
-
/** `Remote.select`: a Projection reading one entity through a selection of a registered entity. */
|
|
3110
|
-
get<Value, Name extends string, Id extends string = string>(selection: EntitySelection<Value, Name, Id> & Registered<Name, EntityName<Entities[number]>, 'Entity'>, id: NoInfer<Id>): Projection<AppModel, RemoteData<Value>>;
|
|
3111
|
-
/**
|
|
3112
|
-
* `get`, and the projection also subscribes to the entity's changes: its
|
|
3113
|
-
* requirements are marked `live`, so `subscriptions` derives a live entry for
|
|
3114
|
-
* the Surfaces that read it.
|
|
3115
|
-
*/
|
|
3116
|
-
live<Value, Name extends string, Id extends string = string>(selection: EntitySelection<Value, Name, Id> & Registered<Name, EntityName<Entities[number]>, 'Entity'>, id: NoInfer<Id>): Projection<AppModel, RemoteData<Value>>;
|
|
3117
|
-
/**
|
|
3118
|
-
* A query connection read as a `Page` of items selected of the query's
|
|
3119
|
-
* entity: `Initial` until the page and every item's selected fields are
|
|
3120
|
-
* present, `Refreshing` while any of them is being refetched. The window is
|
|
3121
|
-
* the page first asked for; the pages `next`, `previous` and `fetch` merge
|
|
3122
|
-
* onto the connection read through the same projection.
|
|
3123
|
-
*/
|
|
3124
|
-
query<Q extends QueryDescriptor<any, any, any>, Value, Entity extends string>(query: Q & Registered<Q['name'], QueryName<Queries[number]>, 'Query'>, input: QueryInput<Q>, options: QueryOptions<Value, Entity, QueryEntity<Q>>): QueryProjection<AppModel, Value, Q['name'], QueryInput<Q>>;
|
|
3125
|
-
/**
|
|
3126
|
-
* "Load more": the Model with the read's window grown by one page, so it
|
|
3127
|
-
* shows that many more rows; the read entry fetches what the connection
|
|
3128
|
-
* lacks. None when the read shows everything there is (or is not a sized
|
|
3129
|
-
* window). Called from `update`.
|
|
3130
|
-
*/
|
|
3131
|
-
more<Name extends string, Input>(model: AppModel, projection: QueryProjection<AppModel, any, Name, Input>): Option.Option<AppModel>;
|
|
3132
|
-
/**
|
|
3133
|
-
* What a query read is and what it currently is, as one serializable value —
|
|
3134
|
-
* data-query-DESIGN §29.1: the domain, the definition and its input, the
|
|
3135
|
-
* connection identity, the window, the Selection, the body as readable text
|
|
3136
|
-
* with what it depends on, and what the read answers from this Model.
|
|
3137
|
-
*
|
|
3138
|
-
* Pure, so a DevTools panel showing it shows something the Model can be
|
|
3139
|
-
* replayed to.
|
|
3140
|
-
*
|
|
3141
|
-
* Given `surfaces` — the same active record `subscriptions` takes — it also
|
|
3142
|
-
* reports which of them read this connection, and why each is active where
|
|
3143
|
-
* that is a readable fact (`Surface.when`) rather than a callback
|
|
3144
|
-
* (`Surface.at`). A Projection cannot carry this itself: several Surfaces may
|
|
3145
|
-
* read one connection, so it is not a property of the read.
|
|
3146
|
-
*/
|
|
3147
|
-
explain<Name extends string, Input>(model: AppModel, projection: QueryProjection<AppModel, any, Name, Input>, options?: {
|
|
3148
|
-
readonly surfaces?: Readonly<Record<string, ActiveSurface<AppModel> | SurfaceSource<AppModel>>> | undefined;
|
|
3149
|
-
}): QueryExplanation;
|
|
3150
|
-
/**
|
|
3151
|
-
* Why a read shows what it shows, in words. Any Remote read: `Data.get`,
|
|
3152
|
-
* `Data.live` or `Data.query`.
|
|
3153
|
-
*
|
|
3154
|
-
* Its point is `Initial`, which means nothing is fetching the read and is
|
|
3155
|
-
* almost always a wiring mistake. Given `surfaces`, the same active record
|
|
3156
|
-
* `subscriptions` takes, it says which: no active Surface reads it, or one
|
|
3157
|
-
* does and Remote's Subscriptions are not running. Pure, like `explain`.
|
|
3158
|
-
*/
|
|
3159
|
-
why(model: AppModel, projection: Projection<AppModel, RemoteData<unknown>>, options?: {
|
|
3160
|
-
readonly surfaces?: Readonly<Record<string, ActiveSurface<AppModel> | SurfaceSource<AppModel>>> | undefined;
|
|
3161
|
-
}): ReadDiagnosis;
|
|
3162
|
-
/**
|
|
3163
|
-
* The rows of a loaded list that a body matches, decoded as the list decodes
|
|
3164
|
-
* them — a filter that asks the server nothing.
|
|
3165
|
-
*
|
|
3166
|
-
* **It filters a list; it does not run a query.** That distinction is what
|
|
3167
|
-
* keeps it honest. "Which rows match" would need to know that the list holds
|
|
3168
|
-
* every row the body could match, which is predicate containment and is
|
|
3169
|
-
* deliberately not built. "Which rows *of this list* match" is decidable from
|
|
3170
|
-
* what is already here, and is what a search box over a loaded page actually
|
|
3171
|
-
* wants.
|
|
3172
|
-
*
|
|
3173
|
-
* `complete` says whether the answer is about the whole list: every edge
|
|
3174
|
-
* judged, and the connection terminal at both ends. An incomplete answer is
|
|
3175
|
-
* not wrong — it is about less than the caller may have meant, which is why
|
|
3176
|
-
* it is said rather than left for a view to assume.
|
|
3177
|
-
*
|
|
3178
|
-
* Creates no connection, so there is nothing new to retain and nothing new to
|
|
3179
|
-
* fetch. The server stays authoritative for which rows exist.
|
|
3180
|
-
*/
|
|
3181
|
-
filtered<Value, Name extends string, Input, Q extends QueryDescriptor<any, any, any>>(model: AppModel, over: QueryProjection<AppModel, Value, Name, Input>, by: Q & Registered<Q['name'], QueryName<Queries[number]>, 'Query'>, input: QueryInput<Q>): Matched<Value>;
|
|
3182
|
-
/**
|
|
3183
|
-
* Shows operations over the store with no request behind them, as a mutation's
|
|
3184
|
-
* `optimistic` ones show while it is in flight: every Selection and view draws
|
|
3185
|
-
* them. For a preview of a change nobody has made. They stay until `lift`;
|
|
3186
|
-
* showing an id again replaces what it showed. Called from `update`. A read
|
|
3187
|
-
* of an entity only overlays show, lacking a field it selects, is `Failed`
|
|
3188
|
-
* (`Overlaid`): nothing will fetch that field.
|
|
3189
|
-
*/
|
|
3190
|
-
overlay(model: AppModel, id: string, optimistic: ReadonlyArray<OptimisticOperation>): AppModel;
|
|
3191
|
-
/** Lifts what `overlay` showed under this id. Lifting nothing returns the same Model. */
|
|
3192
|
-
lift(model: AppModel, id: string): AppModel;
|
|
3193
|
-
/**
|
|
3194
|
-
* The ids `overlay` shows now, in the order they are drawn, a later one over
|
|
3195
|
-
* an earlier: what a caller that overlays from its own state reconciles
|
|
3196
|
-
* against.
|
|
3197
|
-
*/
|
|
3198
|
-
overlays(model: AppModel): ReadonlyArray<string>;
|
|
3199
|
-
/**
|
|
3200
|
-
* The edges a connection shows, as its reads draw them: the server's pages
|
|
3201
|
-
* with pending edits placed, each inserted row where the body's order puts
|
|
3202
|
-
* it (or at the end its overlay names, when it cannot be placed), minus
|
|
3203
|
-
* removed edges and tombstones. Takes the `RemoteModel`, so a persistence
|
|
3204
|
-
* `snapshot` can store a list as it is shown.
|
|
3205
|
-
*/
|
|
3206
|
-
visibleItems(remote: RemoteModel, connection: ConnectionIdentity): ReadonlyArray<Edge>;
|
|
3207
|
-
/** `Remote.refresh`: marks what a projection or a Surface requires as due, for its read entry to refetch. */
|
|
3208
|
-
refresh(model: AppModel, target: Projection<AppModel, unknown> | Surface<AppModel, any, any, void>): AppModel;
|
|
3209
|
-
/** `Remote.forget`: the Model with every server-derived fact gone, for a change of principal. */
|
|
3210
|
-
forget(model: AppModel): AppModel;
|
|
3211
|
-
/**
|
|
3212
|
-
* A read of this domain as an active Surface, for `subscriptions` and
|
|
3213
|
-
* `wiring`: `projectionOf` is what it reads for a Model, none while it
|
|
3214
|
-
* reads nothing. It belongs to the domain's application, and lists no
|
|
3215
|
-
* Messages: it is a requirement, not a sender. A domain made from a raw
|
|
3216
|
-
* optic names no application, so this throws for one.
|
|
3217
|
-
*/
|
|
3218
|
-
active<Value>(name: string, projectionOf: (model: AppModel) => Option.Option<Projection<AppModel, Value>>): ActiveSurface<AppModel>;
|
|
3219
|
-
/**
|
|
3220
|
-
* The Foldkit Subscription entries for the active record, keyed for
|
|
3221
|
-
* `Subscription.make`: a read entry per record entry (`Remote.observe`), a
|
|
3222
|
-
* live entry per record entry that reads through `live` (`Remote.live`), and
|
|
3223
|
-
* one retain entry (`Remote.retain`). A `Surface.each` family is one record
|
|
3224
|
-
* entry whose read unions its parent's requirements with its instances'.
|
|
3225
|
-
* Retention is the domain's: the retain entry of every call roots the active
|
|
3226
|
-
* Surfaces of every call, so reads split over calls (one per policy) do not
|
|
3227
|
-
* collect each other's data. A Surface's params are a function of the Model
|
|
3228
|
-
* (`Surface.at`), so what is fetched, subscribed, and retained follows the
|
|
3229
|
-
* Model.
|
|
3230
|
-
*/
|
|
3231
|
-
subscriptions<const Active extends Readonly<Record<string, ActiveEntry<AppModel>>>>(active: Active, options?: SubscriptionsOptions): SubscriptionEntries<AppModel, Active>;
|
|
3232
|
-
/** `Remote.plan`: the requirements the store does not satisfy. */
|
|
3233
|
-
plan<Value>(model: AppModel, projection: Projection<AppModel, Value>, options?: PlanOptions): ReadonlyArray<Requirement>;
|
|
3234
|
-
/** `Remote.meta`: when what a projection shows was last received, and whether it is stale or loading. */
|
|
3235
|
-
meta<Value>(model: AppModel, projection: Projection<AppModel, Value>): ReadMeta;
|
|
3236
|
-
/** `Remote.storeOf`: the visible store, base under the pending optimistic layers. */
|
|
3237
|
-
storeOf(model: AppModel): EntityStore;
|
|
3238
|
-
/**
|
|
3239
|
-
* `Remote.confirmed`: the same projection read against the server-derived
|
|
3240
|
-
* store alone, with every pending optimistic layer and connection overlay
|
|
3241
|
-
* left off. What it plans is unchanged — the requirements are the
|
|
3242
|
-
* projection's own — so observing it reads exactly what observing the
|
|
3243
|
-
* projection reads; only what it *shows* differs.
|
|
3244
|
-
*
|
|
3245
|
-
* A view usually wants the projection itself, which is the visible read:
|
|
3246
|
-
* the optimistic layers are there so a change shows before the server has
|
|
3247
|
-
* agreed to it. This is for the reader that must not believe a change until
|
|
3248
|
-
* the server has confirmed it, which in practice is an Agent capability
|
|
3249
|
-
* reporting that what it was asked to do is done:
|
|
3250
|
-
*
|
|
3251
|
-
* ```ts
|
|
3252
|
-
* Agent.when({
|
|
3253
|
-
* projection: Data.confirmed(ProjectPage.model.project),
|
|
3254
|
-
* predicate: (project, request) => project.name === request.name,
|
|
3255
|
-
* })
|
|
3256
|
-
* ```
|
|
3257
|
-
*
|
|
3258
|
-
* There is deliberately no `visible`: a projection is already the visible
|
|
3259
|
-
* read, and a wrapper that only forwards would be a second name for it.
|
|
3260
|
-
*/
|
|
3261
|
-
confirmed<P extends Projection<AppModel, any>>(projection: P): P;
|
|
3262
|
-
/**
|
|
3263
|
-
* The plan run through `RemoteClient` and reduced into the Model: the
|
|
3264
|
-
* projection's pending queries first, then the fields it lacks (the pages'
|
|
3265
|
-
* items included). For SSR, route or hover prefetch, and tests.
|
|
3266
|
-
*/
|
|
3267
|
-
prefetch<Value>(model: AppModel, projection: Projection<AppModel, Value>, options?: ObserveOptions): Effect.Effect<AppModel, RemoteReadError | RemoteProtocolError | RemoteQueryError | RemoteUnauthenticated, RemoteClient>;
|
|
3268
|
-
/**
|
|
3269
|
-
* The Model with everything the active Surfaces read, for a render that
|
|
3270
|
-
* fetches nothing (SSR, a prerender). Each pass prefetches every Surface
|
|
3271
|
-
* that plans a read, over the Model the one before it left, so a Surface
|
|
3272
|
-
* active only once another's read has arrived is read in the next pass (or
|
|
3273
|
-
* the same one, when it comes later in `active`). It stops at the first
|
|
3274
|
-
* pass that plans nothing, and fails with `RemoteUnsatisfied` when
|
|
3275
|
-
* `options.passes` run out first. Reads are cache-first: a field already
|
|
3276
|
-
* held is not asked again. A server that could not tell who is asking
|
|
3277
|
-
* fails it with `RemoteUnauthenticated`, for the host to answer as it
|
|
3278
|
-
* answers a lost session.
|
|
3279
|
-
*/
|
|
3280
|
-
satisfy(model: AppModel, active: Readonly<Record<string, ActiveEntry<AppModel>>>, options?: SatisfyOptions): Effect.Effect<AppModel, RemoteReadError | RemoteProtocolError | RemoteQueryError | RemoteUnauthenticated | RemoteUnsatisfied, RemoteClient>;
|
|
3281
|
-
/**
|
|
3282
|
-
* `satisfy` from `update`, for a destination the reader has not reached:
|
|
3283
|
-
* a hover over a link, or a navigation the app expects. `model` is the
|
|
3284
|
-
* Model as it would be there (the route set to the target's); the Command
|
|
3285
|
-
* reads what `active` would read in it and yields one `Preloaded`
|
|
3286
|
-
* carrying the Messages that wrote it, which reduce into the Model as it is
|
|
3287
|
-
* by then. It never fails: a read that fails is one the destination makes
|
|
3288
|
-
* again, and what was read before it still arrives.
|
|
3289
|
-
*
|
|
3290
|
-
* What it reads is kept like any other read until the next change of what
|
|
3291
|
-
* is retained, so preload close to the navigation it expects.
|
|
3292
|
-
*/
|
|
3293
|
-
preload(model: AppModel, active: Readonly<Record<string, ActiveEntry<AppModel>>>, options?: SatisfyOptions): Command<RemoteMessage, never, RemoteClient>;
|
|
3294
|
-
/**
|
|
3295
|
-
* Starts a registered mutation from `update`: applies `MutationStarted` (with
|
|
3296
|
-
* the optimistic operations) to the Model and returns the Command that runs
|
|
3297
|
-
* it and yields the settling Message. The request id comes from the model's
|
|
3298
|
-
* mutation sequence unless `options.requestId` is given.
|
|
3299
|
-
*/
|
|
3300
|
-
mutate<M extends MutationDescriptor<any, any, any>>(model: AppModel, mutation: M & Registered<M['name'], MutationName<Mutations[number]>, 'Mutation'>, input: MutationInput<M>, options?: DomainMutateOptions): MutationStarted<AppModel>;
|
|
3301
|
-
/**
|
|
3302
|
-
* What Remote knows of a mutation `mutate` started, by its request id:
|
|
3303
|
-
* pending, applied, or failed with the error the server or transport gave.
|
|
3304
|
-
*/
|
|
3305
|
-
mutation(model: AppModel, requestId: string): MutationStatus;
|
|
3306
|
-
/**
|
|
3307
|
-
* Why the server refused a mutation, as the value its `Refusal` declares:
|
|
3308
|
-
* none while it is pending or applied, when it failed for another reason,
|
|
3309
|
-
* or when the refusal does not decode as `mutation`'s.
|
|
3310
|
-
*/
|
|
3311
|
-
refusal<Refused>(model: AppModel, requestId: string, mutation: MutationDescriptor<string, any, any, Refused>): Option.Option<Refused>;
|
|
3312
|
-
/**
|
|
3313
|
-
* Whether what `active` reads live is arriving: `Reconnecting` from the
|
|
3314
|
-
* moment its stream breaks until it resubscribes, which its live entry does
|
|
3315
|
-
* on its own, with backoff.
|
|
3316
|
-
*/
|
|
3317
|
-
liveStatus(model: AppModel, active: ActiveEntry<AppModel>): LiveStatus;
|
|
3318
|
-
/** `updateRemote` on the bound slice: reduces one of Remote's Messages, as `RemoteMessage` or as the application's union constructs it. */
|
|
3319
|
-
reduce(model: AppModel, message: RemoteMessage | RemoteMessageInput): AppModel;
|
|
3320
|
-
/**
|
|
3321
|
-
* How this domain joins an assembly: it routes Remote's Messages into
|
|
3322
|
-
* `reduce`, brings its Subscriptions and contract, and requires
|
|
3323
|
-
* `RemoteClient` from the runtime's resources Layer. One assembly holds at
|
|
3324
|
-
* most one Remote wiring: every domain claims the same tags, and routing
|
|
3325
|
-
* takes the first claimant.
|
|
3326
|
-
*/
|
|
3327
|
-
wiring: <const Active extends Readonly<Record<string, ActiveEntry<AppModel>>>>(active: Active, options?: SubscriptionsOptions) => RemoteWiring<AppModel>;
|
|
3328
|
-
/**
|
|
3329
|
-
* Keeps the cache across a reload, as a wiring beside `wiring`: at start and
|
|
3330
|
-
* whenever `key` changes, the stored snapshot is restored (`Hydrated`, with
|
|
3331
|
-
* what the store already holds kept over it, so a page resumed from the
|
|
3332
|
-
* server wins); and the cache is written back when it changes, once its own
|
|
3333
|
-
* snapshot is in. Overlays, optimistic layers, the mutation ledger, live
|
|
3334
|
-
* cursors and gaps are never stored. A change of principal should `forget`
|
|
3335
|
-
* in `update`, and name another `key`.
|
|
3336
|
-
*/
|
|
3337
|
-
persistence(options: PersistenceOptions<AppModel>): Wiring<AppModel, RemoteMessage, KeyValueStore.KeyValueStore>;
|
|
3338
|
-
/** `Remote.inspect` of the bound slice. */
|
|
3339
|
-
inspect(model: AppModel): RemoteInspection;
|
|
3340
|
-
}
|
|
3341
|
-
/** What `Remote.fold(Data, …).mutate` starts: `Data.mutate`'s result with its Command lifted. */
|
|
3342
|
-
type FoldedMutationStarted<AppModel, ParentMessage> = Omit<MutationStarted<AppModel>, 'command'> & {
|
|
3343
|
-
readonly command: Command<ParentMessage, never, RemoteClient>;
|
|
3344
|
-
};
|
|
3345
|
-
/**
|
|
3346
|
-
* A bound domain folded under one of the application's own Message variants,
|
|
3347
|
-
* from `Remote.fold`. Calling it reduces a Remote Message into the Model; the
|
|
3348
|
-
* members that produce Messages, `fetch`, `mutate`, and `subscriptions`,
|
|
3349
|
-
* yield the wrapper Message instead of `RemoteMessage`, with the lift recorded
|
|
3350
|
-
* so Story and Scene can resolve a fetch or a mutation by Remote's own answer.
|
|
3351
|
-
* Members that only read or write the Model (`get`, `refresh`, `next`,
|
|
3352
|
-
* `overlay`, and the rest) stay on the domain itself.
|
|
3353
|
-
*/
|
|
3354
|
-
interface RemoteFold<AppModel, ParentMessage, Domain extends RemoteDomain<AppModel, any, any, any, any>> {
|
|
3355
|
-
(model: AppModel, message: RemoteMessage | RemoteMessageInput): Update.Return<AppModel, ParentMessage>;
|
|
3356
|
-
/** `Data.mutate`, its Command lifted. */
|
|
3357
|
-
readonly mutate: (...args: Parameters<Domain['mutate']>) => FoldedMutationStarted<AppModel, ParentMessage>;
|
|
3358
|
-
/** `Data.preload`, its Command lifted. */
|
|
3359
|
-
readonly preload: (...args: Parameters<Domain['preload']>) => Command<ParentMessage, never, RemoteClient>;
|
|
3360
|
-
/** `Data.subscriptions`, every entry lifted to the wrapper Message. */
|
|
3361
|
-
readonly subscriptions: <const Active extends Readonly<Record<string, ActiveEntry<AppModel>>>>(active: Active, options?: SubscriptionsOptions) => SubscriptionEntries<AppModel, Active, ParentMessage>;
|
|
3362
|
-
}
|
|
3363
|
-
/** The application Model a bound domain is over. */
|
|
3364
|
-
type ModelOfDomain<Domain> = Domain extends RemoteDomain<infer AppModel, any, any, any, any> ? AppModel : never;
|
|
3365
|
-
/** A projection's connection requirement with the `QueryRef` that runs it. */
|
|
3366
|
-
interface QueryRequirement extends ConnectionRequirement {
|
|
3367
|
-
readonly ref: QueryRef<string, unknown>;
|
|
3368
|
-
}
|
|
3369
|
-
/** A page forward (`first`, `after`) or back (`last`, `before`); mixing the two is a type error. */
|
|
3370
|
-
type QueryWindowOptions = {
|
|
3371
|
-
readonly first?: number | undefined;
|
|
3372
|
-
readonly after?: string | undefined;
|
|
3373
|
-
readonly last?: undefined;
|
|
3374
|
-
readonly before?: undefined;
|
|
3375
|
-
} | {
|
|
3376
|
-
readonly last: number;
|
|
3377
|
-
readonly before?: string | undefined;
|
|
3378
|
-
readonly first?: undefined;
|
|
3379
|
-
readonly after?: undefined;
|
|
3380
|
-
};
|
|
3381
|
-
type QueryOptions<Value, Entity extends string, Of extends string = Entity> = {
|
|
3382
|
-
/** What to read of each item: a selection of the query's entity (`Of`). */
|
|
3383
|
-
readonly select: EntitySelection<Value, Entity> & SelectsEntity<Entity, Of>;
|
|
3384
|
-
} & QueryWindowOptions;
|
|
3385
|
-
/** A query connection read as a `Page` of selected items; `ref` is the connection with its first window. */
|
|
3386
|
-
interface QueryProjection<AppModel, Value, Name extends string, Input> extends Projection<AppModel, RemoteData<Page<Value>>> {
|
|
3387
|
-
readonly ref: QueryRef<Name, Input>;
|
|
3388
|
-
/** What it reads of each item, so a filter over the same list decodes identically. */
|
|
3389
|
-
readonly selection: Selection<Value, string>;
|
|
3390
|
-
}
|
|
3391
|
-
/** The input of a query descriptor. */
|
|
3392
|
-
type QueryInput<Q> = Q extends QueryDescriptor<any, infer Input, any> ? Input : never;
|
|
3393
|
-
/** The entity a query's connection is over. */
|
|
3394
|
-
type QueryEntity<Q> = Q extends QueryDescriptor<any, any, ConnectionSpec<infer Entity>> ? Entity : string;
|
|
3395
|
-
/**
|
|
3396
|
-
* When what a projection shows was last received, and whether it is stale
|
|
3397
|
-
* or loading. See `Remote.meta`.
|
|
3398
|
-
*/
|
|
3399
|
-
interface ReadMeta {
|
|
3400
|
-
/** The newest server write among what is shown; none received reads `undefined`. */
|
|
3401
|
-
readonly updatedAt: number | undefined;
|
|
3402
|
-
/** Any shown field or connection is marked stale. */
|
|
3403
|
-
readonly stale: boolean;
|
|
3404
|
-
/** Any shown field or connection is in flight. */
|
|
3405
|
-
readonly loading: boolean;
|
|
3406
|
-
}
|
|
3407
|
-
interface MutateOptions {
|
|
3408
|
-
/** What the request changes before the server answers; released when it settles. */
|
|
3409
|
-
readonly optimistic?: ReadonlyArray<OptimisticOperation> | undefined;
|
|
3410
|
-
/** The clock `MutationSucceeded` stamps the answer with; default `Date.now`, read at each use. */
|
|
3411
|
-
readonly now?: (() => number) | undefined;
|
|
3412
|
-
}
|
|
3413
|
-
interface RetainOptions {
|
|
3414
|
-
/** The query connections the application shows, by `QueryRef` or identity. */
|
|
3415
|
-
readonly connections?: ReadonlyArray<ConnectionIdentity> | undefined;
|
|
3416
|
-
/** How long the roots must be stable before collecting; default none. */
|
|
3417
|
-
readonly grace?: Duration.Input | undefined;
|
|
3418
|
-
}
|
|
3419
|
-
/** How `Remote.observe` and `Remote.prefetch` treat fields the store already holds. */
|
|
3420
|
-
interface ObserveOptions {
|
|
3421
|
-
/** Default `RemotePolicy.cacheFirst`. */
|
|
3422
|
-
readonly policy?: RemotePolicy | undefined;
|
|
3423
|
-
/** The clock a refreshing policy reads; default `Date.now`, read at each use. */
|
|
3424
|
-
readonly now?: (() => number) | undefined;
|
|
3425
|
-
}
|
|
3426
|
-
/** How `Data.satisfy` reads: how many passes it may take, and the clock. */
|
|
3427
|
-
interface SatisfyOptions {
|
|
3428
|
-
/** At most this many passes over the Surfaces; default 8. */
|
|
3429
|
-
readonly passes?: number | undefined;
|
|
3430
|
-
/** The clock the reads are stamped with; default `Date.now`, read at each use. */
|
|
3431
|
-
readonly now?: (() => number) | undefined;
|
|
3432
|
-
}
|
|
3433
|
-
declare const RemoteUnsatisfied_base: Schema.Class<RemoteUnsatisfied, Schema.TaggedStruct<"RemoteUnsatisfied", {
|
|
3434
|
-
readonly surfaces: Schema.$Array<Schema.String>;
|
|
3435
|
-
readonly passes: Schema.Number;
|
|
3436
|
-
}>, import("effect/Cause").YieldableError>;
|
|
3437
|
-
/**
|
|
3438
|
-
* `Data.satisfy` reached its bound with Surfaces still reading, such as a
|
|
3439
|
-
* chain whose every read reveals one more. It names them, so a page that
|
|
3440
|
-
* would have rendered them loading fails instead. (A read the server leaves
|
|
3441
|
-
* unanswered settles as missing and ends the loop.)
|
|
3442
|
-
*/
|
|
3443
|
-
declare class RemoteUnsatisfied extends RemoteUnsatisfied_base {}
|
|
3444
|
-
interface LiveOptions {
|
|
3445
|
-
/** The clock `LiveReceived` stamps events with; default `Date.now`, read at each use. */
|
|
3446
|
-
readonly now?: (() => number) | undefined;
|
|
3447
|
-
/**
|
|
3448
|
-
* The first restart's delay after a stream breaks, doubled for each break in
|
|
3449
|
-
* a row, with ±20% jitter: Sync's transport policy. Default `50 millis`.
|
|
3450
|
-
*/
|
|
3451
|
-
readonly retryBase?: Duration.Input | undefined;
|
|
3452
|
-
/** The longest a restart waits. Default `5 seconds`. */
|
|
3453
|
-
readonly maxRetryDelay?: Duration.Input | undefined;
|
|
3454
|
-
}
|
|
3455
|
-
/** Declares a Remote domain: its entities, queries, and mutations, plus the submodel. */
|
|
3456
|
-
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: {
|
|
3457
|
-
readonly entities: Entities;
|
|
3458
|
-
readonly queries?: Queries;
|
|
3459
|
-
readonly mutations?: Mutations;
|
|
3460
|
-
}) => RemoteDescriptor<Entities, Queries, Mutations>;
|
|
3461
|
-
/** Binds a Remote domain to its store's location in the application Model. */
|
|
3462
|
-
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]>>;
|
|
3463
|
-
/** A query the read entry runs, as its dependencies carry it: plain data Foldkit compares. */
|
|
3464
|
-
declare const PlannedQuery: Schema.Struct<{
|
|
3465
|
-
readonly identity: Schema.String;
|
|
3466
|
-
readonly window: Schema.Struct<{
|
|
3467
|
-
readonly first: Schema.optional<Schema.Number>;
|
|
3468
|
-
readonly last: Schema.optional<Schema.Number>;
|
|
3469
|
-
readonly after: Schema.optional<Schema.String>;
|
|
3470
|
-
readonly before: Schema.optional<Schema.String>;
|
|
3471
|
-
}>;
|
|
3472
|
-
readonly select: Schema.Codec<RelationRequirement, RelationRequirement, never, never>;
|
|
3473
|
-
}>;
|
|
3474
|
-
/** The dependencies of the read entry: the entity fields to read and the queries to run. */
|
|
3475
|
-
interface ReadDependencies {
|
|
3476
|
-
readonly requirements: ReadonlyArray<Requirement>;
|
|
3477
|
-
readonly queries: ReadonlyArray<Schema.Schema.Type<typeof PlannedQuery>>;
|
|
3478
|
-
/**
|
|
3479
|
-
* The highest generation the fields this entry reads were refreshed at: a
|
|
3480
|
-
* refresh of any of them restarts the entry, and a refresh of anything else
|
|
3481
|
-
* leaves it running.
|
|
3482
|
-
*/
|
|
3483
|
-
readonly refresh: number;
|
|
3484
|
-
/**
|
|
3485
|
-
* Under a refreshing policy, when a value the entry holds next ages out and
|
|
3486
|
-
* what is due then. Time reaches Remote only as a Message: the entry sleeps
|
|
3487
|
-
* until then and emits `RefreshStarted`, which marks the fields stale, and
|
|
3488
|
-
* the plan that follows fetches them. A Model that does not change past its
|
|
3489
|
-
* `maxAge` is otherwise never looked at again.
|
|
3490
|
-
*/
|
|
3491
|
-
readonly expires: Deadline | null;
|
|
3492
|
-
}
|
|
3493
|
-
declare const Remote: {
|
|
3494
|
-
/** The submodel's schema, the same for every domain; embed it in the application Model. */
|
|
3495
|
-
Model: Schema.Codec<RemoteModel, unknown, never, never>;
|
|
3496
|
-
/** The submodel's initial value. */
|
|
3497
|
-
initial: RemoteModel;
|
|
3498
|
-
/**
|
|
3499
|
-
* Remote's Message cases for `defineMessageUnion`: spread them into the
|
|
3500
|
-
* application's union, and reduce the ones `Remote.reduces` recognizes with
|
|
3501
|
-
* `RemoteDomain.reduce`.
|
|
3502
|
-
*/
|
|
3503
|
-
messages: {
|
|
3504
|
-
ReadReceived: {
|
|
3505
|
-
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
3506
|
-
result: Schema.Struct<{
|
|
3507
|
-
readonly entities: Schema.$Array<Schema.Struct<{
|
|
3508
|
-
readonly entity: Schema.String;
|
|
3509
|
-
readonly id: Schema.String;
|
|
3510
|
-
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
3511
|
-
}>>;
|
|
3512
|
-
readonly settled: Schema.$Array<Schema.Struct<{
|
|
3513
|
-
readonly entity: Schema.String;
|
|
3514
|
-
readonly id: Schema.String;
|
|
3515
|
-
readonly fields: Schema.$Array<Schema.String>;
|
|
3516
|
-
}>>;
|
|
3517
|
-
}>;
|
|
3518
|
-
now: Schema.Number;
|
|
3519
|
-
};
|
|
3520
|
-
ReadFailed: {
|
|
3521
|
-
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
3522
|
-
error: Schema.Struct<{
|
|
3523
|
-
readonly _tag: Schema.String;
|
|
3524
|
-
readonly message: Schema.String;
|
|
3525
|
-
readonly refusal: Schema.optional<Schema.Unknown>;
|
|
3526
|
-
readonly reason: Schema.optional<Schema.String>;
|
|
3527
|
-
}>;
|
|
3528
|
-
stream: Schema.optional<Schema.String>;
|
|
3529
|
-
};
|
|
3530
|
-
RefreshStarted: {
|
|
3531
|
-
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
3532
|
-
};
|
|
3533
|
-
ReadStarted: {
|
|
3534
|
-
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
3535
|
-
refresh: Schema.optional<Schema.Number>;
|
|
3536
|
-
};
|
|
3537
|
-
QueryStarted: {
|
|
3538
|
-
connections: Schema.$Array<Schema.String>;
|
|
3539
|
-
};
|
|
3540
|
-
RetentionChanged: {
|
|
3541
|
-
roots: Schema.Struct<{
|
|
3542
|
-
readonly requirements: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
3543
|
-
readonly connections: Schema.$Array<Schema.Struct<{
|
|
3544
|
-
readonly identity: Schema.String;
|
|
3545
|
-
readonly select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
3546
|
-
}>>;
|
|
3547
|
-
}>;
|
|
3548
|
-
};
|
|
3549
|
-
Hydrated: {
|
|
3550
|
-
connections: Schema.optional<Schema.Unknown>;
|
|
3551
|
-
from: Schema.optional<Schema.String>;
|
|
3552
|
-
entities: Schema.Unknown;
|
|
3553
|
-
merge: Schema.Union<readonly [Schema.Literal<"replace">, Schema.Literal<"preserve-existing">]>;
|
|
3554
|
-
};
|
|
3555
|
-
MutationStarted: {
|
|
3556
|
-
requestId: Schema.String;
|
|
3557
|
-
optimistic: Schema.optional<Schema.$Array<Schema.Unknown>>;
|
|
3558
|
-
};
|
|
3559
|
-
MutationSucceeded: {
|
|
3560
|
-
requestId: Schema.String;
|
|
3561
|
-
entities: Schema.$Array<Schema.Struct<{
|
|
3562
|
-
readonly entity: Schema.String;
|
|
3563
|
-
readonly id: Schema.String;
|
|
3564
|
-
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
3565
|
-
}>>;
|
|
3566
|
-
connections: Schema.optional<Schema.$Array<Schema.Unknown>>;
|
|
3567
|
-
deleted: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
3568
|
-
readonly entity: Schema.String;
|
|
3569
|
-
readonly id: Schema.String;
|
|
3570
|
-
}>>>;
|
|
3571
|
-
now: Schema.Number;
|
|
3572
|
-
};
|
|
3573
|
-
MutationFailed: {
|
|
3574
|
-
requestId: Schema.String;
|
|
3575
|
-
error: Schema.Struct<{
|
|
3576
|
-
readonly _tag: Schema.String;
|
|
3577
|
-
readonly message: Schema.String;
|
|
3578
|
-
readonly refusal: Schema.optional<Schema.Unknown>;
|
|
3579
|
-
readonly reason: Schema.optional<Schema.String>;
|
|
3580
|
-
}>;
|
|
3581
|
-
operation: Schema.String;
|
|
3582
|
-
};
|
|
3583
|
-
OverlayShown: {
|
|
3584
|
-
id: Schema.String;
|
|
3585
|
-
optimistic: Schema.$Array<Schema.Unknown>;
|
|
3586
|
-
};
|
|
3587
|
-
OverlayLifted: {
|
|
3588
|
-
id: Schema.String;
|
|
3589
|
-
};
|
|
3590
|
-
WindowGrown: {
|
|
3591
|
-
window: Schema.String;
|
|
3592
|
-
size: Schema.Number;
|
|
3593
|
-
};
|
|
3594
|
-
LiveReceived: {
|
|
3595
|
-
stream: Schema.String;
|
|
3596
|
-
event: Schema.Unknown;
|
|
3597
|
-
policy: Schema.optional<Schema.Unknown>;
|
|
3598
|
-
now: Schema.Number;
|
|
3599
|
-
};
|
|
3600
|
-
GapCleared: {
|
|
3601
|
-
stream: Schema.String;
|
|
3602
|
-
};
|
|
3603
|
-
ConnectionMerged: {
|
|
3604
|
-
connection: Schema.String;
|
|
3605
|
-
page: Schema.Unknown;
|
|
3606
|
-
refreshes: Schema.optional<Schema.Boolean>;
|
|
3607
|
-
select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
3608
|
-
entities: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
3609
|
-
readonly entity: Schema.String;
|
|
3610
|
-
readonly id: Schema.String;
|
|
3611
|
-
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
3612
|
-
}>>>;
|
|
3613
|
-
settled: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
3614
|
-
readonly entity: Schema.String;
|
|
3615
|
-
readonly id: Schema.String;
|
|
3616
|
-
readonly fields: Schema.$Array<Schema.String>;
|
|
3617
|
-
}>>>;
|
|
3618
|
-
now: Schema.optional<Schema.Number>;
|
|
3619
|
-
};
|
|
3620
|
-
ConnectionInvalidated: {
|
|
3621
|
-
connection: Schema.String;
|
|
3622
|
-
};
|
|
3623
|
-
ConnectionRefreshed: {
|
|
3624
|
-
connection: Schema.String;
|
|
3625
|
-
};
|
|
3626
|
-
QueryFailed: {
|
|
3627
|
-
connection: Schema.String;
|
|
3628
|
-
error: Schema.Struct<{
|
|
3629
|
-
readonly _tag: Schema.String;
|
|
3630
|
-
readonly message: Schema.String;
|
|
3631
|
-
readonly refusal: Schema.optional<Schema.Unknown>;
|
|
3632
|
-
readonly reason: Schema.optional<Schema.String>;
|
|
3633
|
-
}>;
|
|
3634
|
-
};
|
|
3635
|
-
Preloaded: {
|
|
3636
|
-
messages: Schema.$Array<Schema.suspend<Schema.Codec<RemoteMessage, unknown, never, never>>>;
|
|
3637
|
-
};
|
|
3638
|
-
};
|
|
3639
|
-
/** Whether a Message is one of Remote's, by tag. */
|
|
3640
|
-
reduces: typeof isRemoteMessage;
|
|
3641
|
-
/**
|
|
3642
|
-
* Remote's Messages as one Schema, for a wrapper variant in the
|
|
3643
|
-
* application's union: `GotRemoteMessage: { message: Remote.Message }`. With
|
|
3644
|
-
* a wrapper, `update` matches the application's union exhaustively and
|
|
3645
|
-
* `Remote.fold` reduces what arrives inside it.
|
|
3646
|
-
*/
|
|
3647
|
-
Message: import("foldkit/message").MessageUnion<{
|
|
3648
|
-
ReadReceived: {
|
|
3649
|
-
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
3650
|
-
result: Schema.Struct<{
|
|
3651
|
-
readonly entities: Schema.$Array<Schema.Struct<{
|
|
3652
|
-
readonly entity: Schema.String;
|
|
3653
|
-
readonly id: Schema.String;
|
|
3654
|
-
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
3655
|
-
}>>;
|
|
3656
|
-
readonly settled: Schema.$Array<Schema.Struct<{
|
|
3657
|
-
readonly entity: Schema.String;
|
|
3658
|
-
readonly id: Schema.String;
|
|
3659
|
-
readonly fields: Schema.$Array<Schema.String>;
|
|
3660
|
-
}>>;
|
|
3661
|
-
}>;
|
|
3662
|
-
now: Schema.Number;
|
|
3663
|
-
};
|
|
3664
|
-
ReadFailed: {
|
|
3665
|
-
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
3666
|
-
error: Schema.Struct<{
|
|
3667
|
-
readonly _tag: Schema.String;
|
|
3668
|
-
readonly message: Schema.String;
|
|
3669
|
-
readonly refusal: Schema.optional<Schema.Unknown>;
|
|
3670
|
-
readonly reason: Schema.optional<Schema.String>;
|
|
3671
|
-
}>;
|
|
3672
|
-
stream: Schema.optional<Schema.String>;
|
|
3673
|
-
};
|
|
3674
|
-
RefreshStarted: {
|
|
3675
|
-
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
3676
|
-
};
|
|
3677
|
-
ReadStarted: {
|
|
3678
|
-
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
3679
|
-
refresh: Schema.optional<Schema.Number>;
|
|
3680
|
-
};
|
|
3681
|
-
QueryStarted: {
|
|
3682
|
-
connections: Schema.$Array<Schema.String>;
|
|
3683
|
-
};
|
|
3684
|
-
RetentionChanged: {
|
|
3685
|
-
roots: Schema.Struct<{
|
|
3686
|
-
readonly requirements: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
3687
|
-
readonly connections: Schema.$Array<Schema.Struct<{
|
|
3688
|
-
readonly identity: Schema.String;
|
|
3689
|
-
readonly select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
3690
|
-
}>>;
|
|
3691
|
-
}>;
|
|
3692
|
-
};
|
|
3693
|
-
Hydrated: {
|
|
3694
|
-
connections: Schema.optional<Schema.Unknown>;
|
|
3695
|
-
from: Schema.optional<Schema.String>;
|
|
3696
|
-
entities: Schema.Unknown;
|
|
3697
|
-
merge: Schema.Union<readonly [Schema.Literal<"replace">, Schema.Literal<"preserve-existing">]>;
|
|
3698
|
-
};
|
|
3699
|
-
MutationStarted: {
|
|
3700
|
-
requestId: Schema.String;
|
|
3701
|
-
optimistic: Schema.optional<Schema.$Array<Schema.Unknown>>;
|
|
3702
|
-
};
|
|
3703
|
-
MutationSucceeded: {
|
|
3704
|
-
requestId: Schema.String;
|
|
3705
|
-
entities: Schema.$Array<Schema.Struct<{
|
|
3706
|
-
readonly entity: Schema.String;
|
|
3707
|
-
readonly id: Schema.String;
|
|
3708
|
-
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
3709
|
-
}>>;
|
|
3710
|
-
connections: Schema.optional<Schema.$Array<Schema.Unknown>>;
|
|
3711
|
-
deleted: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
3712
|
-
readonly entity: Schema.String;
|
|
3713
|
-
readonly id: Schema.String;
|
|
3714
|
-
}>>>;
|
|
3715
|
-
now: Schema.Number;
|
|
3716
|
-
};
|
|
3717
|
-
MutationFailed: {
|
|
3718
|
-
requestId: Schema.String;
|
|
3719
|
-
error: Schema.Struct<{
|
|
3720
|
-
readonly _tag: Schema.String;
|
|
3721
|
-
readonly message: Schema.String;
|
|
3722
|
-
readonly refusal: Schema.optional<Schema.Unknown>;
|
|
3723
|
-
readonly reason: Schema.optional<Schema.String>;
|
|
3724
|
-
}>;
|
|
3725
|
-
operation: Schema.String;
|
|
3726
|
-
};
|
|
3727
|
-
OverlayShown: {
|
|
3728
|
-
id: Schema.String;
|
|
3729
|
-
optimistic: Schema.$Array<Schema.Unknown>;
|
|
3730
|
-
};
|
|
3731
|
-
OverlayLifted: {
|
|
3732
|
-
id: Schema.String;
|
|
3733
|
-
};
|
|
3734
|
-
WindowGrown: {
|
|
3735
|
-
window: Schema.String;
|
|
3736
|
-
size: Schema.Number;
|
|
3737
|
-
};
|
|
3738
|
-
LiveReceived: {
|
|
3739
|
-
stream: Schema.String;
|
|
3740
|
-
event: Schema.Unknown;
|
|
3741
|
-
policy: Schema.optional<Schema.Unknown>;
|
|
3742
|
-
now: Schema.Number;
|
|
3743
|
-
};
|
|
3744
|
-
GapCleared: {
|
|
3745
|
-
stream: Schema.String;
|
|
3746
|
-
};
|
|
3747
|
-
ConnectionMerged: {
|
|
3748
|
-
connection: Schema.String;
|
|
3749
|
-
page: Schema.Unknown;
|
|
3750
|
-
refreshes: Schema.optional<Schema.Boolean>;
|
|
3751
|
-
select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
3752
|
-
entities: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
3753
|
-
readonly entity: Schema.String;
|
|
3754
|
-
readonly id: Schema.String;
|
|
3755
|
-
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
3756
|
-
}>>>;
|
|
3757
|
-
settled: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
3758
|
-
readonly entity: Schema.String;
|
|
3759
|
-
readonly id: Schema.String;
|
|
3760
|
-
readonly fields: Schema.$Array<Schema.String>;
|
|
3761
|
-
}>>>;
|
|
3762
|
-
now: Schema.optional<Schema.Number>;
|
|
3763
|
-
};
|
|
3764
|
-
ConnectionInvalidated: {
|
|
3765
|
-
connection: Schema.String;
|
|
3766
|
-
};
|
|
3767
|
-
ConnectionRefreshed: {
|
|
3768
|
-
connection: Schema.String;
|
|
3769
|
-
};
|
|
3770
|
-
QueryFailed: {
|
|
3771
|
-
connection: Schema.String;
|
|
3772
|
-
error: Schema.Struct<{
|
|
3773
|
-
readonly _tag: Schema.String;
|
|
3774
|
-
readonly message: Schema.String;
|
|
3775
|
-
readonly refusal: Schema.optional<Schema.Unknown>;
|
|
3776
|
-
readonly reason: Schema.optional<Schema.String>;
|
|
3777
|
-
}>;
|
|
3778
|
-
};
|
|
3779
|
-
Preloaded: {
|
|
3780
|
-
messages: Schema.$Array<Schema.suspend<Schema.Codec<RemoteMessage, unknown, never, never>>>;
|
|
3781
|
-
};
|
|
3782
|
-
}>;
|
|
3783
|
-
/**
|
|
3784
|
-
* A bound domain under one wrapper variant of the application's union, the
|
|
3785
|
-
* same shape Foldkit gives a Submodel: `toParentMessage` wraps Remote's
|
|
3786
|
-
* Messages, the fold reduces them, and its `fetch`, `mutate`, and
|
|
3787
|
-
* `subscriptions` yield the wrapper. Spreading `Remote.messages` and
|
|
3788
|
-
* narrowing with `Remote.reduces` remains the shorter path for an
|
|
3789
|
-
* application whose `update` only reduces.
|
|
3790
|
-
*
|
|
3791
|
-
* @example
|
|
3792
|
-
* ```ts
|
|
3793
|
-
* const Message = defineMessageUnion({ GotRemoteMessage: { message: Remote.Message } })
|
|
3794
|
-
* const foldData = Remote.fold(Data, message => Message.GotRemoteMessage({ message }))
|
|
3795
|
-
*
|
|
3796
|
-
* const update = (model: Model, message: Message): Return =>
|
|
3797
|
-
* Message.match(message, {
|
|
3798
|
-
* GotRemoteMessage: ({ message }) => foldData(model, message),
|
|
3799
|
-
* })
|
|
3800
|
-
* const subscriptions = Subscription.make<Model, Message, RemoteClient>()(() =>
|
|
3801
|
-
* foldData.subscriptions({ page: Surface.at(ProjectPage, …) }),
|
|
3802
|
-
* )
|
|
3803
|
-
* ```
|
|
3804
|
-
*/
|
|
3805
|
-
fold: <Domain extends RemoteDomain<any, any, any, any, any>, ParentMessage>(domain: Domain, toParentMessage: (message: RemoteMessage) => ParentMessage) => RemoteFold<ModelOfDomain<Domain>, ParentMessage, Domain>;
|
|
3806
|
-
/**
|
|
3807
|
-
* A patch of one entity's values, for a mutation's `optimistic` list or an
|
|
3808
|
-
* overlay. Takes a `foldkit-entity` Entity or a Remote descriptor alike, so
|
|
3809
|
-
* the domain you declared once is the one you patch:
|
|
3810
|
-
* `Remote.patch(Project, 'p1', { name: 'Apollo II' })`. Values are the
|
|
3811
|
-
* fields' wire shape, as the server writes them; a relation is its ref key
|
|
3812
|
-
* (`'User:u1'`).
|
|
3813
|
-
*/
|
|
3814
|
-
patch: <E extends EntityLike>(entity: E, id: string, values: Partial<Schema.Struct.Encoded<FieldsOf<E>>>) => EntityPatch<NameOf<E>, FieldsOf<E>>;
|
|
3815
|
-
/**
|
|
3816
|
-
* A reference to one entity, for `ConnectionChange` and anything else that
|
|
3817
|
-
* names a row: `Remote.ref(Project, 'p3')`. Either kind of entity, as with
|
|
3818
|
-
* `Remote.patch`.
|
|
3819
|
-
*/
|
|
3820
|
-
ref: <E extends EntityLike>(entity: E, id: string) => EntityRef<NameOf<E>, FieldsOf<E>>;
|
|
3821
|
-
/**
|
|
3822
|
-
* Declares a Remote domain and binds it to its place in the application Model
|
|
3823
|
-
* in one step; the result carries the application-facing operations. The
|
|
3824
|
-
* descriptor alone is `Remote.define`, the binding alone `Remote.at`.
|
|
3825
|
-
*/
|
|
3826
|
-
make: <AppModel, Store extends RemoteModel, const Entities extends readonly EntityLike[], const Queries extends readonly QueryDescriptor<any, any, any>[] = readonly [], const Mutations extends readonly MutationDescriptor<any, any, any>[] = readonly []>(config: {
|
|
3827
|
-
readonly model: ModelRef<AppModel, Store>;
|
|
3828
|
-
readonly entities: Entities;
|
|
3829
|
-
readonly queries?: Queries;
|
|
3830
|
-
readonly mutations?: Mutations;
|
|
3831
|
-
/**
|
|
3832
|
-
* Places what the server said (a mutation's answer, a read, a live
|
|
3833
|
-
* patch) as usual, and also fetches each list it placed in, comparing the
|
|
3834
|
-
* server's first page with the order it placed: a disagreement is kept in
|
|
3835
|
-
* `placementMismatches` (`Data.inspect`). A pending edit is not checked,
|
|
3836
|
-
* since the server does not have it yet. For development and tests, where
|
|
3837
|
-
* a collation that drifts should be found.
|
|
3838
|
-
*/
|
|
3839
|
-
readonly verifyPlacement?: boolean | undefined;
|
|
3840
|
-
/**
|
|
3841
|
-
* How the client runs a body's primitive operators when it judges rows it
|
|
3842
|
-
* holds (`Operators`): the kernel's when not given. A body calling one this
|
|
3843
|
-
* table lacks is judged by the server instead, as any row the client cannot
|
|
3844
|
-
* judge is.
|
|
3845
|
-
*/
|
|
3846
|
-
readonly operators?: MemoryOperators | undefined;
|
|
3847
|
-
}) => RemoteDomain<AppModel, Store, Entities, Queries, Mutations>;
|
|
3848
|
-
/**
|
|
3849
|
-
* Declares a Remote domain without binding it: its entities, queries, and
|
|
3850
|
-
* mutations, plus the submodel. For a domain reused across applications or
|
|
3851
|
-
* bound in a test; `Remote.make` is the one-step form.
|
|
3852
|
-
*/
|
|
3853
|
-
define: typeof defineRemote;
|
|
3854
|
-
/**
|
|
3855
|
-
* Binds a Remote domain to its store's location in the application Model. The
|
|
3856
|
-
* registered entity names are carried on the returned value, so `Remote.select`
|
|
3857
|
-
* rejects a selection for an entity this domain never declared.
|
|
3858
|
-
*/
|
|
3859
|
-
at: typeof bindRemote;
|
|
3860
|
-
/**
|
|
3861
|
-
* The resume part for this domain, for `foldkit-ssr`'s `SSR.plan({ parts })`:
|
|
3862
|
-
* a server render sends what the plan's active Surfaces read from the store,
|
|
3863
|
-
* each connection with its boundaries and each live cursor with it, and
|
|
3864
|
-
* nothing else. `id` tells two domains in one application apart.
|
|
3865
|
-
*/
|
|
3866
|
-
resume: typeof resumePart;
|
|
3867
|
-
/**
|
|
3868
|
-
* A Projection node that reads a `RemoteData` value out of the store. The id
|
|
3869
|
-
* is supplied by the caller, usually from a Surface's params. The assembled
|
|
3870
|
-
* value is decoded against the Selection, so malformed server data surfaces
|
|
3871
|
-
* as `Failed` instead of being asserted into `Value`. A present value with a
|
|
3872
|
-
* stale field reads as `Refreshing`: an observer is refetching it.
|
|
3873
|
-
*/
|
|
3874
|
-
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>>;
|
|
3875
|
-
/**
|
|
3876
|
-
* When what a projection shows was last received, and whether it is stale
|
|
3877
|
-
* or loading. Pure, so a view can show "updated 5s ago" without I/O.
|
|
3878
|
-
*
|
|
3879
|
-
* `updatedAt` is the newest server write among what is shown, as the
|
|
3880
|
-
* store dates it; `undefined` when nothing shown was received (nothing
|
|
3881
|
-
* loaded, or only an optimistic preview). `stale` is any shown field or
|
|
3882
|
-
* connection marked stale; `loading` is any of them in flight. Optimistic
|
|
3883
|
-
* previews do not date: showing only one reads `updatedAt: undefined`.
|
|
3884
|
-
*/
|
|
3885
|
-
meta: <AppModel, Store extends RemoteModel, Value>(bound: BoundRemote<AppModel, Store>, model: AppModel, projection: Projection<AppModel, Value>) => ReadMeta;
|
|
3886
|
-
/**
|
|
3887
|
-
* The pure plan for a projection against a Model: the requirements its
|
|
3888
|
-
* remote store does not satisfy, under `options` (freshness, force). A
|
|
3889
|
-
* Surface's projection is `surface.projection(params)`.
|
|
3890
|
-
*/
|
|
3891
|
-
plan: <AppModel, Store extends RemoteModel, Value>(bound: BoundRemote<AppModel, Store>, model: AppModel, projection: Projection<AppModel, Value>, options?: PlanOptions) => ReadonlyArray<Requirement>;
|
|
3892
|
-
/**
|
|
3893
|
-
* The queries a projection needs run before its connections read: those the
|
|
3894
|
-
* Model does not hold, or holds stale (every one under `force`).
|
|
3895
|
-
*/
|
|
3896
|
-
planQueries: <AppModel, Store extends RemoteModel, Value>(bound: BoundRemote<AppModel, Store>, model: AppModel, projection: Projection<AppModel, Value>, options?: PlanOptions) => ReadonlyArray<QueryRef<string, unknown>>;
|
|
3897
|
-
/**
|
|
3898
|
-
* The store reads see: the base store under the pending optimistic layers.
|
|
3899
|
-
* One store is shared by every read and plan of a Model whose remote state
|
|
3900
|
-
* has not changed.
|
|
3901
|
-
*/
|
|
3902
|
-
storeOf: <AppModel, Store extends RemoteModel>(bound: BoundRemote<AppModel, Store>, model: AppModel) => EntityStore;
|
|
3903
|
-
/**
|
|
3904
|
-
* The projection read against the server-derived store alone: the same
|
|
3905
|
-
* requirements, planned the same way, with the pending optimistic layers and
|
|
3906
|
-
* connection overlays left off. See the bound `Remote.confirmed`.
|
|
3907
|
-
*/
|
|
3908
|
-
confirmed: <AppModel, Store extends RemoteModel, P extends Projection<AppModel, any>>(bound: BoundRemote<AppModel, Store>, projection: P) => P;
|
|
3909
|
-
/**
|
|
3910
|
-
* Executes the plan against the `RemoteClient` and returns a new store. Used
|
|
3911
|
-
* for SSR route prefetch, hover prefetch, and tests. Never called during render.
|
|
3912
|
-
* `policy` decides what a present field means (default cache-first); `now`
|
|
3913
|
-
* is the clock it reads, so the planner itself stays pure and time-injected.
|
|
3914
|
-
*/
|
|
3915
|
-
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 | RemoteUnauthenticated, RemoteClient>;
|
|
3916
|
-
/**
|
|
3917
|
-
* Marks what a projection, or a Surface without params, requires as due again.
|
|
3918
|
-
* Called from `update`: every selected field the store holds reads `Refreshing`,
|
|
3919
|
-
* and every loaded query connection is invalidated. Nothing is fetched here.
|
|
3920
|
-
* The read entries `Data.subscriptions` derives refetch it, because a stale
|
|
3921
|
-
* field or connection is planned again under every policy, so a refresh never
|
|
3922
|
-
* sends a request beside the entry already observing the same data.
|
|
3923
|
-
*
|
|
3924
|
-
* A refreshed connection's page replaces its pages, so items the server removed
|
|
3925
|
-
* or reordered follow it; pages loaded past the first are dropped and paged
|
|
3926
|
-
* again with `next`/`previous`. The read entries restart, so a read or query
|
|
3927
|
-
* sent before the refresh is not applied after it.
|
|
3928
|
-
*
|
|
3929
|
-
* It is also how a failed query is retried: a connection whose query failed
|
|
3930
|
-
* is not run again on its own, so its read stays `Failed` until this asks.
|
|
3931
|
-
*
|
|
3932
|
-
* The projection must be observed, which it is while it is on screen. Live
|
|
3933
|
-
* subscriptions are left as they are. For data nothing observes (SSR, tests),
|
|
3934
|
-
* use `Remote.prefetch` with `RemotePolicy.networkOnly`. Refreshing what is
|
|
3935
|
-
* already being refreshed returns the same Model.
|
|
3936
|
-
*/
|
|
3937
|
-
refresh: <AppModel, Store extends RemoteModel>(bound: BoundRemote<AppModel, Store>, model: AppModel, target: Projection<AppModel, unknown> | Surface<AppModel, any, any, void>) => AppModel;
|
|
3938
|
-
/**
|
|
3939
|
-
* Forgets everything the server told this Model: values, tombstones,
|
|
3940
|
-
* unavailable fields, connections, live cursors, failures. What is known is
|
|
3941
|
-
* known for a principal, and this is the one boundary for a login, a logout
|
|
3942
|
-
* or a switch of organization: called from `update`, it performs no I/O, and
|
|
3943
|
-
* every active Surface's read and live entries restart, so the screen asks
|
|
3944
|
-
* again as whoever the client now is. A read or stream begun before is
|
|
3945
|
-
* interrupted rather than landing after. A mutation in flight is treated as
|
|
3946
|
-
* applied: its answer writes nothing here.
|
|
3947
|
-
*/
|
|
3948
|
-
forget: <AppModel, Store extends RemoteModel>(bound: BoundRemote<AppModel, Store>, model: AppModel) => AppModel;
|
|
3949
|
-
/**
|
|
3950
|
-
* Writes a read result into the store, recording each field's applied window.
|
|
3951
|
-
* `requests` are the planned requirements the result answers.
|
|
3952
|
-
*/
|
|
3953
|
-
writeRead: typeof writeRead;
|
|
3954
|
-
/**
|
|
3955
|
-
* Adapts an Effect RPC client for `RemoteRpc` to `RemoteClient`, so an
|
|
3956
|
-
* application provides the transport's RPC layer instead of writing the
|
|
3957
|
-
* `LiveChange`-to-`LiveEvent` mapping by hand. The client `RpcClient.make`
|
|
3958
|
-
* builds is accepted as it is: when its transport fails (`RpcClientError`),
|
|
3959
|
-
* the call fails with its own Remote error, which the application shows and
|
|
3960
|
-
* retries like any failed read, query, mutation or live stream.
|
|
3961
|
-
*/
|
|
3962
|
-
/**
|
|
3963
|
-
* Remote's client over any way of sending one JSON request and receiving its
|
|
3964
|
-
* answer, for `clientLayer`: a worker, a server in the page. `RemoteServer.answer`
|
|
3965
|
-
* is the other end.
|
|
3966
|
-
*/
|
|
3967
|
-
json: typeof json;
|
|
3968
|
-
/**
|
|
3969
|
-
* Remote's client over HTTP, for `clientLayer`: each call a `POST` of the JSON
|
|
3970
|
-
* request to `url`. `headers` is read per request (a session token, say).
|
|
3971
|
-
*/
|
|
3972
|
-
http: typeof http;
|
|
3973
|
-
/**
|
|
3974
|
-
* Remote's client over HTTP with live, for `clientLayer`: reads, queries,
|
|
3975
|
-
* and mutations as `http` sends them, live requirements as one `POST`
|
|
3976
|
-
* answered with a `text/event-stream` of changes.
|
|
3977
|
-
* `foldkit-remote-server/fetch` is the other end.
|
|
3978
|
-
*/
|
|
3979
|
-
httpWithLive: typeof httpWithLive;
|
|
3980
|
-
clientLayer: <R = never>(client: RemoteRpcClient<R, RpcClientError.RpcClientError>, options?: CoalesceOptions) => Layer.Layer<RemoteClient, never, R>;
|
|
3981
|
-
/**
|
|
3982
|
-
* Wraps a `RemoteClient` layer so its reads coalesce: requirements issued
|
|
3983
|
-
* together become one batch, and a requirement already in flight is joined.
|
|
3984
|
-
* `Remote.clientLayer` applies this; use it on a hand-written client.
|
|
3985
|
-
*/
|
|
3986
|
-
coalesced: typeof coalescedLayer;
|
|
3987
|
-
/**
|
|
3988
|
-
* A Foldkit Subscription entry that keeps the cache to what the active
|
|
3989
|
-
* Surfaces reach. `projections` are the ones the application observes (the
|
|
3990
|
-
* same it passes to `Remote.observe`), `connections` the query connections
|
|
3991
|
-
* it shows; anything else is collected once the roots have been stable for
|
|
3992
|
-
* `grace`, so a route transition that comes straight back does not thrash.
|
|
3993
|
-
*/
|
|
3994
|
-
retain: <AppModel, Message = RemoteMessage>(projections: ReadonlyArray<Projection<AppModel, unknown>>, toMessage?: (message: RemoteMessage) => Message, options?: RetainOptions) => EntryWithoutKeepAlive<AppModel, Message, RetentionRoots, never>;
|
|
3995
|
-
/**
|
|
3996
|
-
* Runs a `Query` through `RemoteClient`, encoding its input from the ref.
|
|
3997
|
-
* Pair the result with `Remote.queryMessage` to merge the page into the Model.
|
|
3998
|
-
* With `select`, the server also returns the selected fields of the page's
|
|
3999
|
-
* items, so one response populates both the connection and the store.
|
|
4000
|
-
*/
|
|
4001
|
-
query: <Name extends string, Input>(ref: QueryRef<Name, Input>, select?: RelationRequirement | undefined) => Effect.Effect<{
|
|
4002
|
-
readonly edges: readonly {
|
|
4003
|
-
readonly entity: string;
|
|
4004
|
-
readonly id: string;
|
|
4005
|
-
readonly key: string;
|
|
4006
|
-
}[];
|
|
4007
|
-
readonly start: {
|
|
4008
|
-
readonly _tag: "Terminal";
|
|
4009
|
-
} | {
|
|
4010
|
-
readonly _tag: "Cursor";
|
|
4011
|
-
readonly cursor: string;
|
|
4012
|
-
} | {
|
|
4013
|
-
readonly _tag: "Unknown";
|
|
4014
|
-
};
|
|
4015
|
-
readonly end: {
|
|
4016
|
-
readonly _tag: "Terminal";
|
|
4017
|
-
} | {
|
|
4018
|
-
readonly _tag: "Cursor";
|
|
4019
|
-
readonly cursor: string;
|
|
4020
|
-
} | {
|
|
4021
|
-
readonly _tag: "Unknown";
|
|
4022
|
-
};
|
|
4023
|
-
readonly entities?: readonly {
|
|
4024
|
-
readonly entity: string;
|
|
4025
|
-
readonly id: string;
|
|
4026
|
-
readonly values: {
|
|
4027
|
-
readonly [x: string]: unknown;
|
|
4028
|
-
};
|
|
4029
|
-
}[] | undefined;
|
|
4030
|
-
readonly settled?: readonly {
|
|
4031
|
-
readonly entity: string;
|
|
4032
|
-
readonly id: string;
|
|
4033
|
-
readonly fields: readonly string[];
|
|
4034
|
-
}[] | undefined;
|
|
4035
|
-
}, RemoteQueryError | RemoteUnauthenticated, RemoteClient>;
|
|
4036
|
-
/** The `RemoteMessage` that merges a query page into its connection. */
|
|
4037
|
-
queryMessage: <Name extends string, Input>(ref: QueryRef<Name, Input>, result: Schema.Schema.Type<typeof QueryResult>, select?: RelationRequirement | undefined, now?: number | undefined) => RemoteMessage;
|
|
4038
|
-
/** A pure, serializable view of the whole cache. */
|
|
4039
|
-
inspect: typeof inspectRemote;
|
|
4040
|
-
/** A pure, serializable view of one entity, or `undefined` if unknown. */
|
|
4041
|
-
inspectEntity: typeof inspectEntity;
|
|
4042
|
-
/**
|
|
4043
|
-
* Runs a mutation through `RemoteClient`, decoding its typed Output and
|
|
4044
|
-
* returning the result's normalized patches so the caller can reconcile them
|
|
4045
|
-
* through `updateRemote`'s `MutationSucceeded` (or `Remote.mutateInto`).
|
|
4046
|
-
*/
|
|
4047
|
-
mutate: <Name extends string, Input, Output>(mutation: MutationDescriptor<Name, Input, Output, unknown>, input: Input, requestId: string, options?: {
|
|
4048
|
-
readonly keys?: ReadonlyArray<string> | undefined;
|
|
4049
|
-
readonly operation?: string | undefined;
|
|
4050
|
-
} | undefined) => Effect.Effect<{
|
|
4051
|
-
output: Output;
|
|
4052
|
-
entities: readonly {
|
|
4053
|
-
readonly entity: string;
|
|
4054
|
-
readonly id: string;
|
|
4055
|
-
readonly values: {
|
|
4056
|
-
readonly [x: string]: unknown;
|
|
4057
|
-
};
|
|
4058
|
-
}[];
|
|
4059
|
-
connections: ConnectionChange[];
|
|
4060
|
-
deleted: readonly {
|
|
4061
|
-
readonly entity: string;
|
|
4062
|
-
readonly id: string;
|
|
4063
|
-
}[];
|
|
4064
|
-
}, RemoteForbidden | RemoteMutationError | RemoteUnauthenticated, RemoteClient>;
|
|
4065
|
-
/**
|
|
4066
|
-
* Runs a mutation and reconciles its patches into a `RemoteModel` in one step,
|
|
4067
|
-
* returning the new model alongside the typed Output. The model-level form of
|
|
4068
|
-
* `MutationStarted` → `RemoteClient.mutate` → `MutationSucceeded`; in an
|
|
4069
|
-
* application the three are `update` (with `optimistic`), a Command, and the
|
|
4070
|
-
* Message the Command returns, so the optimistic operations show meanwhile.
|
|
4071
|
-
*/
|
|
4072
|
-
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<{
|
|
4073
|
-
output: Output;
|
|
4074
|
-
model: AppModel;
|
|
4075
|
-
}, RemoteForbidden | RemoteMutationError | RemoteUnauthenticated, RemoteClient>;
|
|
4076
|
-
/**
|
|
4077
|
-
* A Foldkit Subscription entry that plans a Surface's missing fields from the
|
|
4078
|
-
* Model and fetches them through `RemoteClient`, emitting a `RemoteMessage`
|
|
4079
|
-
* per outcome. Wrap it in an application Message (`toMessage`) and reduce it
|
|
4080
|
-
* with the domain's `update`. Under a refreshing `policy` the entry first
|
|
4081
|
-
* emits `RefreshStarted`, so the fields being refetched read as `Refreshing`
|
|
4082
|
-
* while the request is pending.
|
|
4083
|
-
*/
|
|
4084
|
-
observe: <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?: ObserveOptions) => EntryWithoutKeepAlive<AppModel, Message, ReadDependencies, RemoteClient>;
|
|
4085
|
-
/**
|
|
4086
|
-
* A Foldkit Subscription entry that consumes the live stream for a Surface's
|
|
4087
|
-
* requirements, emitting a `LiveReceived` per event and a `ReadFailed`
|
|
4088
|
-
* carrying its `stream` when the stream breaks (including
|
|
4089
|
-
* `ResumeUnavailable`). That records a gap on the stream rather than a failed
|
|
4090
|
-
* read, since nothing was being read, and restarts the entry after a
|
|
4091
|
-
* backoff; the restart refetches what it covers. The resume cursor is read
|
|
4092
|
-
* from `RemoteModel.live`, so the application tracks no cursor of its own.
|
|
4093
|
-
*/
|
|
4094
|
-
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>;
|
|
4095
|
-
};
|
|
4096
|
-
export { QueryExplanation as $, emptyConnection as $i, coalesceQueries as $n, stableStringify as $r, Entity$2 as $t, RemoteWiring as A, TypeOf as Ai, RemoteRpcClient as An, RemoteReadError as Ar, remoteModelSchema as At, liveFetch as B, Freshness as Bi, LiveCursor as Bn, Requirement as Br, SnapshotOptions as Bt, Registered as C, remove as Ca, MutationStatus as Ci, isRefPage as Cn, ReadRequest as Cr, noFailures as Ct, RemoteEntry as D, writeEntities as Da, Refusal as Di, relationShape as Dn, RemoteMutationError as Dr, refreshedAt as Dt, RemoteDomain as E, tombstone as Ea, Reconciled as Ei, relationAlias as En, RemoteLiveError as Er, refreshIsInFlight as Et, SubscriptionsOptions as F, optimisticOfWrite as Fi, mutateRemote as Fn, WireBoundary as Fr, writeRead as Ft, RemotePolicy as G, Boundary as Gi, applyEntityEvent as Gn, LiveInsertion as Gr, reachable as Gt, RemoteJsonRequest as H, RemoteError as Hi, LiveOutcome as Hn, requirementsOf as Hr, Retained as Ht, RowPlace as I, patchOfWrite as Ii, remoteError as In, ConnectionRequirement as Ir, MergePolicy as It, PlanOptions as J, Edge as Ji, liveHasNext as Jn, QueryDescriptor as Jr, Matched as Jt, Deadline as K, Connection as Ki, classifyLive as Kn, LivePolicy as Kr, Belongs as Kt, placeIn as L, reconcileMutation as Li, BoundaryCounts as Ln, RelationRequirement as Lr, REMOTE_CACHE_VERSION as Lt, SatisfyOptions as M, emptyMutationState as Mi, connectionChangeOf as Mn, RemoteUnauthenticated as Mr, updateRemote as Mt, SelectsEntity as N, failMutation as Ni, liveEventOf as Nn, SettledFields as Nr, windowGrowthKey as Nt, RemoteFold as O, writeEntity as Oa, RefusalOfWrite as Oi, targetsOf as On, RemoteProtocolError as Or, remoteMessageCases as Ot, SubscriptionEntries as P, mutationStatus as Pi, mintOperation as Pn, WindowSchema as Pr, withRefreshRequested as Pt, ExplainedDependencies as Q, edge as Qi, QueryRun as Qn, ResultOf as Qr, AnySchema as Qt, LiveFetchOptions as R, schemaOf as Ri, ConnectionApplied as Rn, RemoteConnections as Rr, RemotePersistence as Rt, ReadMeta as S, readField as Sa, MutationState as Si, aliasedField as Sn, ReadBatchResult as Sr, isRemoteMessage as St, RemoteDescriptor as T, setUnavailable as Ta, PendingPatch as Ti, refsIn as Tn, RemoteForbidden as Tr, overlaysOf as Tt, RemoteJsonSend as U, remoteDataSchema as Ui, LiveState as Un, ConnectionSpec as Ur, RetentionRoots as Ut, RemoteJsonAnswer as V, RemoteData as Vi, LiveEvent as Vn, connectionsOf as Vr, ConnectionRoot as Vt, RemoteResumePart as W, remoteErrorSchema as Wi, applyConnectionEvent as Wn, IDENTITY_SEPARATOR as Wr, gc as Wt, plan as X, Segment as Xi, BatchRead as Xn, QueryRef as Xr, belongsEncoded as Xt, deadlineOf as Y, EdgeRef as Yi, liveHasPrevious as Yn, QueryInputs as Yr, MatchingOptions as Yt, windowKey as Z, cursor as Zi, CoalesceOptions as Zn, QueryWindow as Zr, matching as Zt, QueryOptions as _, isFieldStale as _a, visibleItems as _i, RefParts as _n, QueryResult as _r, invalidateConnections as _t, EntitySelection as a, segment as aa, OptimisticState as ai, RefPage as an, LiveEdge as ar, PlacedOrder as at, QueryWindowOptions as b, markStale as ba, MutationAnswer as bi, RelationKind as bn, Read as br, isLoadingThrough as bt, LiveOptions as c, EntityEntry as ca, beginOptimistic as ci, SelectionOf as cn, MAX_RELATION_DEPTH as cr, RemoteMessage as ct, MutateOptions as d, EntityWrite as da, pruneOverlays as di, assemble as dn, MutationResult as dr, RemoteModel as dt, hasNext as ea, ConnectionChange as ei, EntityDescriptor as en, coalesceReads as er, ReadDiagnosis as et, MutationStarted as f, clearStale as fa, removeLayer as fi, pageSchema as fn, NormalizedEntity as fr, StreamHealth as ft, QueryInput as g, hasField as ga, settleSuccess as gi, RefPageValue as gn, QueryRequest as gr, initialRemoteModel as gt, QueryEntity as h, entry as ha, settleFailure as hi, RELATION_ALIAS as hn, QueryEdge as hr, forgetRemote as ht, EntityLike as i, merge as ia, OptimisticOperation as ii, RefKey as in, LiveChange as ir, Failures as it, RetainOptions as j, beginMutation as ji, coalescedLayer as jn, RemoteRpc as jr, retentionRootsSchema as jt, RemoteUnsatisfied as k, SchemaOrFields as ki, RemoteClient as kn, RemoteQueryError as kr, remoteMessageSchema as kt, LiveStatus as l, EntityKey as la, connectionIdentity as li, SelectionValue as ln, Mutate as lr, RemoteMessageInput as lt, PersistenceOptions as m, entityKey as ma, resolvedPatches as mi, unavailableOf as mn, PageSize as mr, failureOf as mt, BoundRemote as n, isGapped as na, ConnectionOverlay as ni, EntityRef as nn, ConnectionChangeSchema as nr, inspectEntity as nt, FoldedMutationStarted as o, terminal as oa, addLayer as oi, Page as on, LiveRequirement as or, PlacementMismatch as ot, ObserveOptions as p, emptyStore as pa, removeOverlay as pi, relationOf as pn, OperationId as pr, emptyRefresh as pt, PlanFreshness as q, Cursor as qi, emptyLiveState as qn, Query$1 as qr, Judged as qt, DomainMutateOptions as r, items as ra, EntityLayer as ri, FieldsFrom as rn, Live as rr, inspectRemote as rt, LiveDependencies as s, unknown as sa, addOverlay as si, Selection as sn, MAX_FIELDS_PER_REQUEST as sr, RefreshState as st, ActiveEntry as t, hasPrevious as ta, ConnectionIdentity as ti, EntityPatch as tn, requirementKey as tr, RemoteInspection as tt, ModelOfDomain as u, EntityStore as ua, emptyOptimistic as ui, SelectionValueOf as un, MutationRequest as ur, RemoteMessageTag as ut, QueryProjection as v, isFieldUnavailable as va, visibleStore as vi, RelationAnnotation as vn, QueryRpc as vr, isFieldFailed as vt, Remote as w, setStale as wa, NormalizedPatch as wi, refParts as wn, RelationRequest as wr, onlyOverlaid as wt, ReadDependencies as x, missingFields as xa, MutationDescriptor as xi, RelationShape as xn, ReadBatch as xr, isQueryLoading as xt, QueryRequirement as y, isTombstone as ya, Mutation as yi, RelationEntityAnnotation as yn, REMOTE_PROTOCOL_VERSION as yr, isLoading as yt, httpWithLive as z, Denied as zi, EntityApplied as zn, RemoteRequirements as zr, Snapshot as zt };
|
|
4097
|
-
//# sourceMappingURL=index-BEvVAL76.d.mts.map
|