foldkit-remote 0.7.0 → 0.9.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 +582 -193
- package/dist/index.d.mts +596 -42
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1101 -239
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -8
package/dist/index.d.mts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { Context, Duration, Effect, Layer, Option, Schema, Stream } from "effect";
|
|
1
|
+
import { Context, Duration, Effect, Layer, Option, Result, Schema, Stream } from "effect";
|
|
2
2
|
import * as Domain from "foldkit-entity";
|
|
3
3
|
import { AnyEntity, AnyQuery, Dependencies, InputExpr, Query as Query$1 } from "foldkit-entity";
|
|
4
|
+
import { Command } from "foldkit/command";
|
|
4
5
|
import { EntryWithoutKeepAlive } from "foldkit/subscription";
|
|
5
6
|
import { ActiveSurface, Contract, Invalid, Metadata, ModelRef, Projection, Surface, Wiring } from "foldkit-surface";
|
|
6
7
|
import { Rpc, RpcGroup } from "effect/unstable/rpc";
|
|
7
8
|
import { KeyValueStore } from "effect/unstable/persistence";
|
|
8
|
-
import
|
|
9
|
-
//#region ../metadata/
|
|
10
|
-
//#region src/index.d.ts
|
|
9
|
+
import * as Update from "foldkit/update";
|
|
10
|
+
//#region ../metadata/src/index.d.ts
|
|
11
11
|
/** Marks a `Metadata` value. Its entries are private to this module. */
|
|
12
12
|
declare const MetadataTypeId: unique symbol;
|
|
13
13
|
type MetadataTypeId = typeof MetadataTypeId;
|
|
@@ -59,7 +59,6 @@ declare const Metadata$1: {
|
|
|
59
59
|
summarize: (metadata: Metadata$1) => readonly MetadataSummary[];
|
|
60
60
|
};
|
|
61
61
|
//#endregion
|
|
62
|
-
//#endregion
|
|
63
62
|
//#region src/connection.d.ts
|
|
64
63
|
export interface EdgeRef {
|
|
65
64
|
readonly entity: string;
|
|
@@ -202,6 +201,12 @@ export interface EntityEntry {
|
|
|
202
201
|
readonly present: ReadonlySet<string>;
|
|
203
202
|
/** Present fields whose value may be outdated (revalidation needed). */
|
|
204
203
|
readonly stale: ReadonlySet<string>;
|
|
204
|
+
/**
|
|
205
|
+
* Fields the server settled without a value: asked for, and answered without
|
|
206
|
+
* them, whatever the reason. Not planned again until a refresh asks; a later
|
|
207
|
+
* write of the field clears it.
|
|
208
|
+
*/
|
|
209
|
+
readonly unavailable: ReadonlySet<string>;
|
|
205
210
|
/** The entity is known to be absent; a later write clears this. */
|
|
206
211
|
readonly tombstone: boolean;
|
|
207
212
|
/** Injected clock reading of the last write; never read from ambient state. */
|
|
@@ -221,6 +226,8 @@ export interface EntityWrite {
|
|
|
221
226
|
readonly values: Readonly<Record<string, unknown>>;
|
|
222
227
|
/** The canonical window each written relation field was fetched with. */
|
|
223
228
|
readonly windows?: Readonly<Record<string, string>> | undefined;
|
|
229
|
+
/** When this write dates the entity, instead of the batch's `now`. */
|
|
230
|
+
readonly updatedAt?: number | undefined;
|
|
224
231
|
}
|
|
225
232
|
/**
|
|
226
233
|
* Merges known values into many entities, copying the store once. Every
|
|
@@ -240,6 +247,14 @@ export declare const setStale: (store: EntityStore, marks: ReadonlyArray<readonl
|
|
|
240
247
|
export declare const markStale: (store: EntityStore, key: EntityKey, fields: Iterable<string>) => EntityStore;
|
|
241
248
|
/** Ends a refresh that did not land: the fields are present again as they were. */
|
|
242
249
|
export declare const clearStale: (store: EntityStore, key: EntityKey, fields: Iterable<string>) => EntityStore;
|
|
250
|
+
/**
|
|
251
|
+
* Records fields the server settled without a value. A present field is left
|
|
252
|
+
* as it is: the answer that settled it was not about the value it holds.
|
|
253
|
+
* `false` forgets the marks, which is how a refresh asks again.
|
|
254
|
+
*/
|
|
255
|
+
export declare const setUnavailable: (store: EntityStore, marks: ReadonlyArray<readonly [key: EntityKey, fields: Iterable<string>]>, unavailable: boolean) => EntityStore;
|
|
256
|
+
/** Whether the server settled this field without a value, and nothing has written it since. */
|
|
257
|
+
export declare const isFieldUnavailable: (store: EntityStore, key: EntityKey, field: string) => boolean;
|
|
243
258
|
/** Records that the entity is known to be absent, so it is not refetched. */
|
|
244
259
|
export declare const tombstone: (store: EntityStore, key: EntityKey) => EntityStore;
|
|
245
260
|
/** Forgets everything known about the entity, including a tombstone. */
|
|
@@ -257,7 +272,8 @@ export declare const isFieldStale: (store: EntityStore, key: EntityKey, field: s
|
|
|
257
272
|
export declare const readField: (store: EntityStore, key: EntityKey, field: string) => Option.Option<unknown>;
|
|
258
273
|
/**
|
|
259
274
|
* The fields the planner must fetch. A tombstone makes every field known
|
|
260
|
-
* (absent), so it returns an empty list and the entity is not refetched
|
|
275
|
+
* (absent), so it returns an empty list and the entity is not refetched, and a
|
|
276
|
+
* field the server settled without a value is known the same way. A
|
|
261
277
|
* requested window that differs from the one a field was fetched with also
|
|
262
278
|
* marks it missing, but only when the stored window is known (never `""`), so a
|
|
263
279
|
* writer that does not record windows cannot cause a refetch loop.
|
|
@@ -304,15 +320,23 @@ export interface Reconciled {
|
|
|
304
320
|
readonly store: EntityStore;
|
|
305
321
|
readonly state: MutationState;
|
|
306
322
|
}
|
|
323
|
+
/** What a settled mutation wrote, as `MutationSucceeded` carries it. */
|
|
324
|
+
export interface MutationAnswer {
|
|
325
|
+
readonly entities: ReadonlyArray<NormalizedPatch>;
|
|
326
|
+
/** Entities the mutation deleted; each is tombstoned. */
|
|
327
|
+
readonly deleted?: ReadonlyArray<{
|
|
328
|
+
readonly entity: string;
|
|
329
|
+
readonly id: string;
|
|
330
|
+
}> | undefined;
|
|
331
|
+
/** Injected clock reading of the answer, which dates what it writes. */
|
|
332
|
+
readonly now: number;
|
|
333
|
+
}
|
|
307
334
|
/**
|
|
308
335
|
* Applies a mutation result once and marks the request settled. A second call
|
|
309
336
|
* with the same `requestId` (a retry, or a live event describing the same change)
|
|
310
337
|
* does not re-apply the entities, but still clears `pending`.
|
|
311
338
|
*/
|
|
312
|
-
export declare const reconcileMutation: (store: EntityStore, state: MutationState, requestId: string,
|
|
313
|
-
readonly entity: string;
|
|
314
|
-
readonly id: string;
|
|
315
|
-
}>) => Reconciled;
|
|
339
|
+
export declare const reconcileMutation: (store: EntityStore, state: MutationState, requestId: string, answer: MutationAnswer) => Reconciled;
|
|
316
340
|
/** A mutation an application declares: its name and input/output codecs. */
|
|
317
341
|
export interface MutationDescriptor<Name extends string, Input, Output> {
|
|
318
342
|
readonly name: Name;
|
|
@@ -593,7 +617,12 @@ export declare const addLayer: (optimistic: OptimisticState, layer: EntityLayer)
|
|
|
593
617
|
export declare const removeLayer: (optimistic: OptimisticState, id: string) => OptimisticState;
|
|
594
618
|
export declare const addOverlay: (optimistic: OptimisticState, overlay: ConnectionOverlay) => OptimisticState;
|
|
595
619
|
export declare const removeOverlay: (optimistic: OptimisticState, id: string) => OptimisticState;
|
|
596
|
-
/**
|
|
620
|
+
/**
|
|
621
|
+
* Base store with every layer applied in order. Later layers win. A patch is
|
|
622
|
+
* not news from the server, so it keeps the date of the value under it; an
|
|
623
|
+
* entity only a request holds (a temporary id) is not the server's to age, and
|
|
624
|
+
* is dated `Infinity`, so freshness never plans or times it.
|
|
625
|
+
*/
|
|
597
626
|
export declare const visibleStore: (base: EntityStore, optimistic: OptimisticState) => EntityStore;
|
|
598
627
|
/**
|
|
599
628
|
* A fresh page is newer than any settled overlay it covers: an edge the page
|
|
@@ -607,10 +636,10 @@ export declare const pruneOverlays: (optimistic: OptimisticState, connection: st
|
|
|
607
636
|
* a later layer re-wins on rebase. Confirmed connection changes are recorded
|
|
608
637
|
* once per request, as overlays the request no longer owns.
|
|
609
638
|
*/
|
|
610
|
-
export declare const settleSuccess: (base: EntityStore, optimistic: OptimisticState, state: MutationState, requestId: string,
|
|
611
|
-
|
|
612
|
-
readonly
|
|
613
|
-
}
|
|
639
|
+
export declare const settleSuccess: (base: EntityStore, optimistic: OptimisticState, state: MutationState, requestId: string, answer: MutationAnswer & {
|
|
640
|
+
/** Connection changes the server confirmed; they replace the request's own. */
|
|
641
|
+
readonly connections?: ReadonlyArray<ConnectionChange> | undefined;
|
|
642
|
+
}) => {
|
|
614
643
|
readonly store: EntityStore;
|
|
615
644
|
readonly state: MutationState;
|
|
616
645
|
readonly optimistic: OptimisticState;
|
|
@@ -675,11 +704,6 @@ export type LiveOutcome = 'applied' | 'duplicate' | 'gap';
|
|
|
675
704
|
* spurious gap.
|
|
676
705
|
*/
|
|
677
706
|
export declare const classifyLive: (state: LiveState, cursor: LiveCursor) => LiveOutcome;
|
|
678
|
-
/**
|
|
679
|
-
* A subscriber is woken only if the event changed a field it selects. A
|
|
680
|
-
* change to an unselected field is skipped entirely.
|
|
681
|
-
*/
|
|
682
|
-
export declare const shouldWake: (changed: ReadonlyArray<string>, selected: ReadonlyArray<string>) => boolean;
|
|
683
707
|
export interface EntityApplied {
|
|
684
708
|
readonly state: LiveState;
|
|
685
709
|
readonly store: EntityStore;
|
|
@@ -740,7 +764,7 @@ export declare const gc: (state: Retained & {
|
|
|
740
764
|
//#endregion
|
|
741
765
|
//#region src/persistence.d.ts
|
|
742
766
|
/** Bump when the serialized shape changes; a mismatch discards the cache. */
|
|
743
|
-
export declare const REMOTE_CACHE_VERSION =
|
|
767
|
+
export declare const REMOTE_CACHE_VERSION = 5;
|
|
744
768
|
/**
|
|
745
769
|
* What survives a reload: the entity cache, and the connections an application
|
|
746
770
|
* **declared** should come back.
|
|
@@ -832,7 +856,7 @@ export declare const RemotePersistence: {
|
|
|
832
856
|
* server refuses a mismatch with `RemoteProtocolError`, so a shape change never
|
|
833
857
|
* drifts silently: bump it whenever `ReadRequest` or `LiveRequirement` change.
|
|
834
858
|
*/
|
|
835
|
-
export declare const REMOTE_PROTOCOL_VERSION =
|
|
859
|
+
export declare const REMOTE_PROTOCOL_VERSION = 4;
|
|
836
860
|
declare const RemoteReadError_base: Schema.Class<RemoteReadError, Schema.TaggedStruct<"RemoteReadError", {
|
|
837
861
|
readonly message: Schema.String;
|
|
838
862
|
}>, import("effect/Cause").YieldableError>;
|
|
@@ -875,12 +899,27 @@ export declare const NormalizedEntity: Schema.Struct<{
|
|
|
875
899
|
readonly id: Schema.String;
|
|
876
900
|
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
877
901
|
}>;
|
|
902
|
+
/**
|
|
903
|
+
* Fields a read asked for that the server answered without, and will not
|
|
904
|
+
* answer with: the client stops asking. It says nothing about why, so a rule
|
|
905
|
+
* that withholds a field is not itself on the wire.
|
|
906
|
+
*/
|
|
907
|
+
export declare const SettledFields: Schema.Struct<{
|
|
908
|
+
readonly entity: Schema.String;
|
|
909
|
+
readonly id: Schema.String;
|
|
910
|
+
readonly fields: Schema.$Array<Schema.String>;
|
|
911
|
+
}>;
|
|
878
912
|
export declare const ReadBatchResult: Schema.Struct<{
|
|
879
913
|
readonly entities: Schema.$Array<Schema.Struct<{
|
|
880
914
|
readonly entity: Schema.String;
|
|
881
915
|
readonly id: Schema.String;
|
|
882
916
|
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
883
917
|
}>>;
|
|
918
|
+
readonly settled: Schema.$Array<Schema.Struct<{
|
|
919
|
+
readonly entity: Schema.String;
|
|
920
|
+
readonly id: Schema.String;
|
|
921
|
+
readonly fields: Schema.$Array<Schema.String>;
|
|
922
|
+
}>>;
|
|
884
923
|
}>;
|
|
885
924
|
export declare const MutationRequest: Schema.Struct<{
|
|
886
925
|
/** Stable across transport retries so a mutation is not applied twice. */
|
|
@@ -999,6 +1038,11 @@ export declare const Read: Rpc.Rpc<"FoldkitRemoteRead", Schema.Struct<{
|
|
|
999
1038
|
readonly id: Schema.String;
|
|
1000
1039
|
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
1001
1040
|
}>>;
|
|
1041
|
+
readonly settled: Schema.$Array<Schema.Struct<{
|
|
1042
|
+
readonly entity: Schema.String;
|
|
1043
|
+
readonly id: Schema.String;
|
|
1044
|
+
readonly fields: Schema.$Array<Schema.String>;
|
|
1045
|
+
}>>;
|
|
1002
1046
|
}>, Schema.Union<readonly [typeof RemoteReadError, typeof RemoteProtocolError]>, never, never>;
|
|
1003
1047
|
export declare const Mutate: Rpc.Rpc<"FoldkitRemoteMutate", Schema.Struct<{
|
|
1004
1048
|
/** Stable across transport retries so a mutation is not applied twice. */
|
|
@@ -1099,6 +1143,12 @@ export declare const QueryRequest: Schema.Struct<{
|
|
|
1099
1143
|
readonly after: Schema.optional<Schema.String>;
|
|
1100
1144
|
readonly before: Schema.optional<Schema.String>;
|
|
1101
1145
|
}>;
|
|
1146
|
+
/**
|
|
1147
|
+
* What to read of each item, as the relation slice a read asks the server
|
|
1148
|
+
* for. Absent for a query run without one: the response carries only edges,
|
|
1149
|
+
* and the client's read entry fetches fields in a second round trip.
|
|
1150
|
+
*/
|
|
1151
|
+
readonly select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
1102
1152
|
}>;
|
|
1103
1153
|
export declare const QueryEdge: Schema.Struct<{
|
|
1104
1154
|
readonly entity: Schema.String;
|
|
@@ -1127,6 +1177,21 @@ export declare const QueryResult: Schema.Struct<{
|
|
|
1127
1177
|
}>, Schema.Struct<{
|
|
1128
1178
|
readonly _tag: Schema.Literal<"Unknown">;
|
|
1129
1179
|
}>]>;
|
|
1180
|
+
/**
|
|
1181
|
+
* The selected fields of the page's items, in the same shape a read batch
|
|
1182
|
+
* returns. Absent from a server that predates payload planning: the client
|
|
1183
|
+
* reads it as empty and fetches fields as before.
|
|
1184
|
+
*/
|
|
1185
|
+
readonly entities: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
1186
|
+
readonly entity: Schema.String;
|
|
1187
|
+
readonly id: Schema.String;
|
|
1188
|
+
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
1189
|
+
}>>>;
|
|
1190
|
+
readonly settled: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
1191
|
+
readonly entity: Schema.String;
|
|
1192
|
+
readonly id: Schema.String;
|
|
1193
|
+
readonly fields: Schema.$Array<Schema.String>;
|
|
1194
|
+
}>>>;
|
|
1130
1195
|
}>;
|
|
1131
1196
|
export declare const QueryRpc: Rpc.Rpc<"FoldkitRemoteQuery", Schema.Struct<{
|
|
1132
1197
|
readonly query: Schema.String;
|
|
@@ -1137,6 +1202,12 @@ export declare const QueryRpc: Rpc.Rpc<"FoldkitRemoteQuery", Schema.Struct<{
|
|
|
1137
1202
|
readonly after: Schema.optional<Schema.String>;
|
|
1138
1203
|
readonly before: Schema.optional<Schema.String>;
|
|
1139
1204
|
}>;
|
|
1205
|
+
/**
|
|
1206
|
+
* What to read of each item, as the relation slice a read asks the server
|
|
1207
|
+
* for. Absent for a query run without one: the response carries only edges,
|
|
1208
|
+
* and the client's read entry fetches fields in a second round trip.
|
|
1209
|
+
*/
|
|
1210
|
+
readonly select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
1140
1211
|
}>, Schema.Struct<{
|
|
1141
1212
|
readonly edges: Schema.$Array<Schema.Struct<{
|
|
1142
1213
|
readonly entity: Schema.String;
|
|
@@ -1159,6 +1230,21 @@ export declare const QueryRpc: Rpc.Rpc<"FoldkitRemoteQuery", Schema.Struct<{
|
|
|
1159
1230
|
}>, Schema.Struct<{
|
|
1160
1231
|
readonly _tag: Schema.Literal<"Unknown">;
|
|
1161
1232
|
}>]>;
|
|
1233
|
+
/**
|
|
1234
|
+
* The selected fields of the page's items, in the same shape a read batch
|
|
1235
|
+
* returns. Absent from a server that predates payload planning: the client
|
|
1236
|
+
* reads it as empty and fetches fields as before.
|
|
1237
|
+
*/
|
|
1238
|
+
readonly entities: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
1239
|
+
readonly entity: Schema.String;
|
|
1240
|
+
readonly id: Schema.String;
|
|
1241
|
+
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
1242
|
+
}>>>;
|
|
1243
|
+
readonly settled: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
1244
|
+
readonly entity: Schema.String;
|
|
1245
|
+
readonly id: Schema.String;
|
|
1246
|
+
readonly fields: Schema.$Array<Schema.String>;
|
|
1247
|
+
}>>>;
|
|
1162
1248
|
}>, typeof RemoteQueryError, never, never>;
|
|
1163
1249
|
export declare const RemoteRpc: RpcGroup.RpcGroup<Rpc.Rpc<"FoldkitRemoteRead", Schema.Struct<{
|
|
1164
1250
|
readonly version: Schema.Number;
|
|
@@ -1169,6 +1255,11 @@ export declare const RemoteRpc: RpcGroup.RpcGroup<Rpc.Rpc<"FoldkitRemoteRead", S
|
|
|
1169
1255
|
readonly id: Schema.String;
|
|
1170
1256
|
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
1171
1257
|
}>>;
|
|
1258
|
+
readonly settled: Schema.$Array<Schema.Struct<{
|
|
1259
|
+
readonly entity: Schema.String;
|
|
1260
|
+
readonly id: Schema.String;
|
|
1261
|
+
readonly fields: Schema.$Array<Schema.String>;
|
|
1262
|
+
}>>;
|
|
1172
1263
|
}>, Schema.Union<readonly [typeof RemoteReadError, typeof RemoteProtocolError]>, never, never> | Rpc.Rpc<"FoldkitRemoteMutate", Schema.Struct<{
|
|
1173
1264
|
/** Stable across transport retries so a mutation is not applied twice. */
|
|
1174
1265
|
readonly requestId: Schema.String;
|
|
@@ -1254,6 +1345,12 @@ export declare const RemoteRpc: RpcGroup.RpcGroup<Rpc.Rpc<"FoldkitRemoteRead", S
|
|
|
1254
1345
|
readonly after: Schema.optional<Schema.String>;
|
|
1255
1346
|
readonly before: Schema.optional<Schema.String>;
|
|
1256
1347
|
}>;
|
|
1348
|
+
/**
|
|
1349
|
+
* What to read of each item, as the relation slice a read asks the server
|
|
1350
|
+
* for. Absent for a query run without one: the response carries only edges,
|
|
1351
|
+
* and the client's read entry fetches fields in a second round trip.
|
|
1352
|
+
*/
|
|
1353
|
+
readonly select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
1257
1354
|
}>, Schema.Struct<{
|
|
1258
1355
|
readonly edges: Schema.$Array<Schema.Struct<{
|
|
1259
1356
|
readonly entity: Schema.String;
|
|
@@ -1276,6 +1373,21 @@ export declare const RemoteRpc: RpcGroup.RpcGroup<Rpc.Rpc<"FoldkitRemoteRead", S
|
|
|
1276
1373
|
}>, Schema.Struct<{
|
|
1277
1374
|
readonly _tag: Schema.Literal<"Unknown">;
|
|
1278
1375
|
}>]>;
|
|
1376
|
+
/**
|
|
1377
|
+
* The selected fields of the page's items, in the same shape a read batch
|
|
1378
|
+
* returns. Absent from a server that predates payload planning: the client
|
|
1379
|
+
* reads it as empty and fetches fields as before.
|
|
1380
|
+
*/
|
|
1381
|
+
readonly entities: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
1382
|
+
readonly entity: Schema.String;
|
|
1383
|
+
readonly id: Schema.String;
|
|
1384
|
+
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
1385
|
+
}>>>;
|
|
1386
|
+
readonly settled: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
1387
|
+
readonly entity: Schema.String;
|
|
1388
|
+
readonly id: Schema.String;
|
|
1389
|
+
readonly fields: Schema.$Array<Schema.String>;
|
|
1390
|
+
}>>>;
|
|
1279
1391
|
}>, typeof RemoteQueryError, never, never>>;
|
|
1280
1392
|
//#endregion
|
|
1281
1393
|
//#region src/model.d.ts
|
|
@@ -1288,6 +1400,12 @@ export interface RemoteModel {
|
|
|
1288
1400
|
readonly entities: EntityStore;
|
|
1289
1401
|
/** Normalized ordered connections, keyed by connection identity. */
|
|
1290
1402
|
readonly connections: Readonly<Record<string, Connection>>;
|
|
1403
|
+
/**
|
|
1404
|
+
* How many rows `Data.more` has grown a read's window to, by
|
|
1405
|
+
* `windowGrowthKey`. A read shows at most its window, so this is what "load
|
|
1406
|
+
* more" changes; it lives here because a list holds no state of its own.
|
|
1407
|
+
*/
|
|
1408
|
+
readonly grown: Readonly<Record<string, number>>;
|
|
1291
1409
|
/** Optimistic entity layers and connection overlays over the base store. */
|
|
1292
1410
|
readonly optimistic: OptimisticState;
|
|
1293
1411
|
/** Live cursor and boundary state, keyed by the subscription's stream key. */
|
|
@@ -1348,8 +1466,22 @@ export interface RefreshState {
|
|
|
1348
1466
|
readonly generation: number;
|
|
1349
1467
|
readonly requested: ReadonlyMap<string, number>;
|
|
1350
1468
|
readonly started: ReadonlyMap<string, number>;
|
|
1469
|
+
/**
|
|
1470
|
+
* The generation every entry is refreshed at, at least: `forgetRemote` moves
|
|
1471
|
+
* it, so every read and live entry restarts, and a read or stream begun for
|
|
1472
|
+
* the principal before is interrupted rather than landing after.
|
|
1473
|
+
*/
|
|
1474
|
+
readonly floor: number;
|
|
1351
1475
|
}
|
|
1352
1476
|
export declare const emptyRefresh: RefreshState;
|
|
1477
|
+
/**
|
|
1478
|
+
* The Model with everything the server told it forgotten: values, tombstones,
|
|
1479
|
+
* unavailable fields, connections, live cursors, failures, and what is in
|
|
1480
|
+
* flight. For a change of principal, whose facts these were. The mutation
|
|
1481
|
+
* sequence is kept, so request ids stay unique, and a mutation in flight is
|
|
1482
|
+
* treated as applied: its answer, when it comes, writes nothing here.
|
|
1483
|
+
*/
|
|
1484
|
+
export declare const forgetRemote: (model: RemoteModel) => RemoteModel;
|
|
1353
1485
|
export declare const initialRemoteModel: RemoteModel;
|
|
1354
1486
|
export declare const remoteModelSchema: () => Schema.Codec<RemoteModel, unknown>;
|
|
1355
1487
|
/** The submodel's Messages; each reduces to `RemoteModel` through `updateRemote`. */
|
|
@@ -1425,6 +1557,8 @@ export type RemoteMessage = {
|
|
|
1425
1557
|
readonly entity: string;
|
|
1426
1558
|
readonly id: string;
|
|
1427
1559
|
}> | undefined;
|
|
1560
|
+
/** Injected clock reading of the answer: how fresh the written entities are. */
|
|
1561
|
+
readonly now: number;
|
|
1428
1562
|
} | {
|
|
1429
1563
|
readonly _tag: 'MutationFailed';
|
|
1430
1564
|
readonly requestId: string;
|
|
@@ -1442,6 +1576,12 @@ export type RemoteMessage = {
|
|
|
1442
1576
|
} | {
|
|
1443
1577
|
readonly _tag: 'OverlayLifted';
|
|
1444
1578
|
readonly id: string;
|
|
1579
|
+
} |
|
|
1580
|
+
/** `Data.more`: a read's window, by `windowGrowthKey`, now shows `size` rows. */
|
|
1581
|
+
{
|
|
1582
|
+
readonly _tag: 'WindowGrown';
|
|
1583
|
+
readonly window: string;
|
|
1584
|
+
readonly size: number;
|
|
1445
1585
|
} | {
|
|
1446
1586
|
readonly _tag: 'LiveReceived';
|
|
1447
1587
|
readonly stream: string;
|
|
@@ -1457,6 +1597,26 @@ export type RemoteMessage = {
|
|
|
1457
1597
|
readonly page: Segment;
|
|
1458
1598
|
/** The page answers the connection's refresh, so the merge also clears `stale`. */
|
|
1459
1599
|
readonly refreshes?: boolean | undefined;
|
|
1600
|
+
/**
|
|
1601
|
+
* The slice the query asked for, so the payload's entities write like a
|
|
1602
|
+
* read: one request per matching edge. Absent for a page from a server
|
|
1603
|
+
* that predates payload planning, which carries edges only.
|
|
1604
|
+
*/
|
|
1605
|
+
readonly select?: RelationRequirement | undefined;
|
|
1606
|
+
/** The selected fields of the page's items, as a read batch returns them. */
|
|
1607
|
+
readonly entities?: ReadonlyArray<{
|
|
1608
|
+
readonly entity: string;
|
|
1609
|
+
readonly id: string;
|
|
1610
|
+
readonly values: Record<string, unknown>;
|
|
1611
|
+
}> | undefined;
|
|
1612
|
+
/** Fields asked for that the server settled without a value. */
|
|
1613
|
+
readonly settled?: ReadonlyArray<{
|
|
1614
|
+
readonly entity: string;
|
|
1615
|
+
readonly id: string;
|
|
1616
|
+
readonly fields: ReadonlyArray<string>;
|
|
1617
|
+
}> | undefined;
|
|
1618
|
+
/** Injected clock reading of the answer, dating what the payload writes. */
|
|
1619
|
+
readonly now?: number | undefined;
|
|
1460
1620
|
} | {
|
|
1461
1621
|
readonly _tag: 'ConnectionInvalidated';
|
|
1462
1622
|
readonly connection: string;
|
|
@@ -1494,6 +1654,11 @@ export declare const remoteMessageCases: {
|
|
|
1494
1654
|
readonly id: Schema.String;
|
|
1495
1655
|
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
1496
1656
|
}>>;
|
|
1657
|
+
readonly settled: Schema.$Array<Schema.Struct<{
|
|
1658
|
+
readonly entity: Schema.String;
|
|
1659
|
+
readonly id: Schema.String;
|
|
1660
|
+
readonly fields: Schema.$Array<Schema.String>;
|
|
1661
|
+
}>>;
|
|
1497
1662
|
}>;
|
|
1498
1663
|
now: Schema.Number;
|
|
1499
1664
|
};
|
|
@@ -1545,6 +1710,7 @@ export declare const remoteMessageCases: {
|
|
|
1545
1710
|
readonly entity: Schema.String;
|
|
1546
1711
|
readonly id: Schema.String;
|
|
1547
1712
|
}>>>;
|
|
1713
|
+
now: Schema.Number;
|
|
1548
1714
|
};
|
|
1549
1715
|
MutationFailed: {
|
|
1550
1716
|
requestId: Schema.String;
|
|
@@ -1560,6 +1726,10 @@ export declare const remoteMessageCases: {
|
|
|
1560
1726
|
OverlayLifted: {
|
|
1561
1727
|
id: Schema.String;
|
|
1562
1728
|
};
|
|
1729
|
+
WindowGrown: {
|
|
1730
|
+
window: Schema.String;
|
|
1731
|
+
size: Schema.Number;
|
|
1732
|
+
};
|
|
1563
1733
|
LiveReceived: {
|
|
1564
1734
|
stream: Schema.String;
|
|
1565
1735
|
event: Schema.Unknown;
|
|
@@ -1573,6 +1743,18 @@ export declare const remoteMessageCases: {
|
|
|
1573
1743
|
connection: Schema.String;
|
|
1574
1744
|
page: Schema.Unknown;
|
|
1575
1745
|
refreshes: Schema.optional<Schema.Boolean>;
|
|
1746
|
+
select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
1747
|
+
entities: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
1748
|
+
readonly entity: Schema.String;
|
|
1749
|
+
readonly id: Schema.String;
|
|
1750
|
+
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
1751
|
+
}>>>;
|
|
1752
|
+
settled: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
1753
|
+
readonly entity: Schema.String;
|
|
1754
|
+
readonly id: Schema.String;
|
|
1755
|
+
readonly fields: Schema.$Array<Schema.String>;
|
|
1756
|
+
}>>>;
|
|
1757
|
+
now: Schema.optional<Schema.Number>;
|
|
1576
1758
|
};
|
|
1577
1759
|
ConnectionInvalidated: {
|
|
1578
1760
|
connection: Schema.String;
|
|
@@ -1607,6 +1789,14 @@ export declare const isRemoteMessage: <M extends {
|
|
|
1607
1789
|
readonly _tag: RemoteMessageTag;
|
|
1608
1790
|
}>;
|
|
1609
1791
|
export declare const remoteMessageSchema: Schema.Schema<RemoteMessage>;
|
|
1792
|
+
/** The key a grown window is kept under: its connection and the window first asked for. */
|
|
1793
|
+
export declare const windowGrowthKey: (identity: string, window: string) => string;
|
|
1794
|
+
/**
|
|
1795
|
+
* Whether only overlays show this entity: the server has told the store
|
|
1796
|
+
* nothing of it and no request's layer writes it, so nothing will fetch what an
|
|
1797
|
+
* overlay leaves out.
|
|
1798
|
+
*/
|
|
1799
|
+
export declare const onlyOverlaid: (model: RemoteModel, entity: string, id: string) => boolean;
|
|
1610
1800
|
/** Whether a query for this connection is in flight. */
|
|
1611
1801
|
export declare const isQueryLoading: (model: RemoteModel, identity: string) => boolean;
|
|
1612
1802
|
/**
|
|
@@ -1637,7 +1827,12 @@ export declare const isLoading: (model: RemoteModel, entity: string, id: string,
|
|
|
1637
1827
|
/**
|
|
1638
1828
|
* The pure reducer all four producers share. A live event that arrives ahead of
|
|
1639
1829
|
* its cursor is a gap: it is not applied, and the stream is recorded so the host
|
|
1640
|
-
* can resubscribe rather than silently miss facts.
|
|
1830
|
+
* can resubscribe rather than silently miss facts. When every field a Message
|
|
1831
|
+
* touches keeps its identity, `model` itself is returned, so the application's
|
|
1832
|
+
* root keeps its identity and Foldkit does not render. The common no-ops do (a
|
|
1833
|
+
* duplicate live event, a repeated `ReadStarted`); a repeated failure, or a
|
|
1834
|
+
* `preserve-existing` restore of entities already held, still makes an equal
|
|
1835
|
+
* copy.
|
|
1641
1836
|
*/
|
|
1642
1837
|
export declare const updateRemote: (model: RemoteModel, message: RemoteMessage) => RemoteModel;
|
|
1643
1838
|
/** Whether this field's last read failed and nothing has settled it since. */
|
|
@@ -1664,6 +1859,23 @@ export declare const failureOf: (model: RemoteModel, entity: string, id: string,
|
|
|
1664
1859
|
*/
|
|
1665
1860
|
export declare const writeRead: (store: EntityStore, requests: ReadonlyArray<Requirement>, result: Schema.Schema.Type<typeof ReadBatchResult>, now?: number) => EntityStore;
|
|
1666
1861
|
//#endregion
|
|
1862
|
+
//#region src/resume.d.ts
|
|
1863
|
+
/**
|
|
1864
|
+
* A resume part, in the shape `foldkit-ssr`'s `SSR.plan` takes in `parts`.
|
|
1865
|
+
* Declared here structurally, so neither package depends on the other.
|
|
1866
|
+
*/
|
|
1867
|
+
interface RemoteResumePart<AppModel> {
|
|
1868
|
+
readonly id: string;
|
|
1869
|
+
/** The metadata key names whose reads this part resumes. */
|
|
1870
|
+
readonly covers: ReadonlyArray<string>;
|
|
1871
|
+
readonly capture: (model: AppModel, projections: ReadonlyArray<{
|
|
1872
|
+
readonly metadata: Metadata;
|
|
1873
|
+
}>) => unknown;
|
|
1874
|
+
readonly restore: (model: AppModel, value: unknown) => Result.Result<AppModel, string>;
|
|
1875
|
+
/** Whether a Subscription entry is one of this domain's, which may start late. */
|
|
1876
|
+
readonly deferrable: (key: string, entry: unknown) => boolean;
|
|
1877
|
+
}
|
|
1878
|
+
//#endregion
|
|
1667
1879
|
//#region src/coalesce.d.ts
|
|
1668
1880
|
type Batch = Schema.Schema.Type<typeof ReadBatch>;
|
|
1669
1881
|
type BatchResult = Schema.Schema.Type<typeof ReadBatchResult>;
|
|
@@ -1882,6 +2094,12 @@ interface Assembled {
|
|
|
1882
2094
|
* list), so the Selection's codec decides whether that is a failure.
|
|
1883
2095
|
*/
|
|
1884
2096
|
export declare const assemble: (store: EntityStore, key: string, requirement: RelationRequirement) => Assembled | undefined;
|
|
2097
|
+
/**
|
|
2098
|
+
* The first field `requirement` reads, at any depth, that the server settled
|
|
2099
|
+
* without a value, as `Entity:id.field`. A read that consults it says why it
|
|
2100
|
+
* cannot assemble rather than waiting on a field nothing will fetch.
|
|
2101
|
+
*/
|
|
2102
|
+
export declare const unavailableOf: (store: EntityStore, key: string, requirement: RelationRequirement) => string | undefined;
|
|
1885
2103
|
//#endregion
|
|
1886
2104
|
//#region src/entity.d.ts
|
|
1887
2105
|
export type AnySchema = Schema.Schema<unknown>;
|
|
@@ -2078,6 +2296,7 @@ export interface RemoteInspection {
|
|
|
2078
2296
|
readonly key: string;
|
|
2079
2297
|
readonly present: ReadonlyArray<string>;
|
|
2080
2298
|
readonly stale: ReadonlyArray<string>;
|
|
2299
|
+
readonly unavailable: ReadonlyArray<string>;
|
|
2081
2300
|
readonly tombstone: boolean;
|
|
2082
2301
|
readonly updatedAt: number;
|
|
2083
2302
|
readonly windows: Readonly<Record<string, string>>;
|
|
@@ -2215,6 +2434,23 @@ export interface PlanOptions {
|
|
|
2215
2434
|
/** Plan every requested field, present or not, tombstoned or not. */
|
|
2216
2435
|
readonly force?: boolean | undefined;
|
|
2217
2436
|
}
|
|
2437
|
+
/** When present values next go stale, and the requirements of the entities that do. */
|
|
2438
|
+
export interface Deadline {
|
|
2439
|
+
readonly at: number;
|
|
2440
|
+
readonly due: ReadonlyArray<Requirement>;
|
|
2441
|
+
}
|
|
2442
|
+
/**
|
|
2443
|
+
* The earliest moment a value `requirements` read, following the relations the
|
|
2444
|
+
* store holds as `plan` does, goes stale under `freshness`, with the
|
|
2445
|
+
* requirements of the entities that go stale then. A field the server settled
|
|
2446
|
+
* without a value ages with its entity too, since `plan` asks for it again once
|
|
2447
|
+
* the entity expires. Nothing when no such field is still fresh: what is
|
|
2448
|
+
* already expired or stale is planned, not awaited, which is what keeps a
|
|
2449
|
+
* timer from firing on what it already fired on. It is the next moment the
|
|
2450
|
+
* plan can change with the clock alone, which the read entry relies on to
|
|
2451
|
+
* reuse its plan until then.
|
|
2452
|
+
*/
|
|
2453
|
+
export declare const deadlineOf: (store: EntityStore, requirements: readonly Requirement[], freshness: PlanFreshness) => Deadline | undefined;
|
|
2218
2454
|
export declare const plan: (store: EntityStore, requirements: readonly Requirement[], options?: PlanOptions) => ReadonlyArray<Requirement>;
|
|
2219
2455
|
//#endregion
|
|
2220
2456
|
//#region src/policy.d.ts
|
|
@@ -2323,6 +2559,8 @@ export interface DomainMutateOptions {
|
|
|
2323
2559
|
readonly requestId: string;
|
|
2324
2560
|
readonly tempId: string;
|
|
2325
2561
|
}) => ReadonlyArray<OptimisticOperation>) | undefined;
|
|
2562
|
+
/** The clock `MutationSucceeded` stamps the answer with; default `Date.now`, read at each use. */
|
|
2563
|
+
readonly now?: (() => number) | undefined;
|
|
2326
2564
|
}
|
|
2327
2565
|
/** A Foldkit Subscription entry of the Remote domain, emitting its Messages through `RemoteClient`. */
|
|
2328
2566
|
export type RemoteEntry<AppModel, Dependencies> = EntryWithoutKeepAlive<AppModel, RemoteMessage, Dependencies, RemoteClient>;
|
|
@@ -2331,9 +2569,15 @@ export type RemoteEntry<AppModel, Dependencies> = EntryWithoutKeepAlive<AppModel
|
|
|
2331
2569
|
* and a live entry per key (the live one idles when nothing is read live), and
|
|
2332
2570
|
* `retain`.
|
|
2333
2571
|
*/
|
|
2334
|
-
export type SubscriptionEntries<AppModel, Active> = { readonly [K in keyof Active & (string | number) as `${K}.read` | `${K}.live`]:
|
|
2335
|
-
readonly retain:
|
|
2572
|
+
export 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>; } & {
|
|
2573
|
+
readonly retain: EntryWithoutKeepAlive<AppModel, Message, RetentionRoots, never>;
|
|
2336
2574
|
};
|
|
2575
|
+
/** The dependencies of a live entry: what it subscribes to, and where a restart resumes. */
|
|
2576
|
+
export interface LiveDependencies {
|
|
2577
|
+
readonly requirements: ReadonlyArray<Requirement>;
|
|
2578
|
+
readonly cursor: LiveCursor;
|
|
2579
|
+
readonly floor: number;
|
|
2580
|
+
}
|
|
2337
2581
|
export interface SubscriptionsOptions extends ObserveOptions, LiveOptions, RetainOptions {}
|
|
2338
2582
|
/** 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. */
|
|
2339
2583
|
export type RemoteWiring<AppModel> = Wiring<AppModel, RemoteMessage | RemoteMessageInput, RemoteClient>;
|
|
@@ -2368,10 +2612,13 @@ export interface RemoteDomain<AppModel, Store extends RemoteModel, Entities exte
|
|
|
2368
2612
|
* onto the connection read through the same projection.
|
|
2369
2613
|
*/
|
|
2370
2614
|
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>>;
|
|
2371
|
-
/**
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2615
|
+
/**
|
|
2616
|
+
* "Load more": the Model with the read's window grown by one page, so it
|
|
2617
|
+
* shows that many more rows; the read entry fetches what the connection
|
|
2618
|
+
* lacks. None when the read shows everything there is (or is not a sized
|
|
2619
|
+
* window). Called from `update`.
|
|
2620
|
+
*/
|
|
2621
|
+
more<Name extends string, Input>(model: AppModel, projection: QueryProjection<AppModel, any, Name, Input>): Option.Option<AppModel>;
|
|
2375
2622
|
/**
|
|
2376
2623
|
* What a query read is and what it currently is, as one serializable value —
|
|
2377
2624
|
* data-query-DESIGN §29.1: the domain, the definition and its input, the
|
|
@@ -2422,30 +2669,44 @@ export interface RemoteDomain<AppModel, Store extends RemoteModel, Entities exte
|
|
|
2422
2669
|
* fetch. The server stays authoritative for which rows exist.
|
|
2423
2670
|
*/
|
|
2424
2671
|
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>;
|
|
2425
|
-
/** A Command that runs the query and yields the `ConnectionMerged` (or `QueryFailed`) that reduces it: "load more". */
|
|
2426
|
-
fetch(ref: QueryRef<string, unknown>): Command<RemoteMessage, never, RemoteClient>;
|
|
2427
2672
|
/**
|
|
2428
2673
|
* Shows operations over the store with no request behind them, as a mutation's
|
|
2429
2674
|
* `optimistic` ones show while it is in flight: every Selection and view draws
|
|
2430
2675
|
* them. For a preview of a change nobody has made. They stay until `lift`;
|
|
2431
|
-
* showing an id again replaces what it showed. Called from `update`.
|
|
2676
|
+
* showing an id again replaces what it showed. Called from `update`. A read
|
|
2677
|
+
* of an entity only overlays show, lacking a field it selects, is `Failed`
|
|
2678
|
+
* (`Overlaid`): nothing will fetch that field.
|
|
2432
2679
|
*/
|
|
2433
2680
|
overlay(model: AppModel, id: string, optimistic: ReadonlyArray<OptimisticOperation>): AppModel;
|
|
2434
2681
|
/** Lifts what `overlay` showed under this id. Lifting nothing returns the same Model. */
|
|
2435
2682
|
lift(model: AppModel, id: string): AppModel;
|
|
2436
2683
|
/** `Remote.refresh`: marks what a projection or a Surface requires as due, for its read entry to refetch. */
|
|
2437
2684
|
refresh(model: AppModel, target: Projection<AppModel, unknown> | Surface<AppModel, any, any, void>): AppModel;
|
|
2685
|
+
/** `Remote.forget`: the Model with every server-derived fact gone, for a change of principal. */
|
|
2686
|
+
forget(model: AppModel): AppModel;
|
|
2687
|
+
/**
|
|
2688
|
+
* A read of this domain as an active Surface, for `subscriptions` and
|
|
2689
|
+
* `wiring`: `projectionOf` is what it reads for a Model, none while it
|
|
2690
|
+
* reads nothing. It belongs to the domain's application, and lists no
|
|
2691
|
+
* Messages: it is a requirement, not a sender. A domain made from a raw
|
|
2692
|
+
* optic names no application, so this throws for one.
|
|
2693
|
+
*/
|
|
2694
|
+
active<Value>(name: string, projectionOf: (model: AppModel) => Option.Option<Projection<AppModel, Value>>): ActiveSurface<AppModel>;
|
|
2438
2695
|
/**
|
|
2439
2696
|
* The Foldkit Subscription entries for the active Surfaces, keyed for
|
|
2440
2697
|
* `Subscription.make`: a read entry per Surface (`Remote.observe`), a live
|
|
2441
2698
|
* entry per Surface that reads through `live` (`Remote.live`), and one
|
|
2442
|
-
* retain entry
|
|
2699
|
+
* retain entry (`Remote.retain`). Retention is the domain's: the retain
|
|
2700
|
+
* entry of every call roots the active Surfaces of every call, so reads
|
|
2701
|
+
* split over calls (one per policy) do not collect each other's data. A
|
|
2443
2702
|
* Surface's params are a function of the Model (`Surface.at`), so what is
|
|
2444
2703
|
* fetched, subscribed, and retained follows the Model.
|
|
2445
2704
|
*/
|
|
2446
2705
|
subscriptions<const Active extends Readonly<Record<string, ActiveSurface<AppModel> | Surface<AppModel, any, any, void>>>>(active: Active, options?: SubscriptionsOptions): SubscriptionEntries<AppModel, Active>;
|
|
2447
2706
|
/** `Remote.plan`: the requirements the store does not satisfy. */
|
|
2448
2707
|
plan<Value>(model: AppModel, projection: Projection<AppModel, Value>, options?: PlanOptions): ReadonlyArray<Requirement>;
|
|
2708
|
+
/** `Remote.meta`: when what a projection shows was last received, and whether it is stale or loading. */
|
|
2709
|
+
meta<Value>(model: AppModel, projection: Projection<AppModel, Value>): ReadMeta;
|
|
2449
2710
|
/** `Remote.storeOf`: the visible store, base under the pending optimistic layers. */
|
|
2450
2711
|
storeOf(model: AppModel): EntityStore;
|
|
2451
2712
|
/**
|
|
@@ -2478,6 +2739,17 @@ export interface RemoteDomain<AppModel, Store extends RemoteModel, Entities exte
|
|
|
2478
2739
|
* items included). For SSR, route or hover prefetch, and tests.
|
|
2479
2740
|
*/
|
|
2480
2741
|
prefetch<Value>(model: AppModel, projection: Projection<AppModel, Value>, options?: ObserveOptions): Effect.Effect<AppModel, RemoteReadError | RemoteProtocolError | RemoteQueryError, RemoteClient>;
|
|
2742
|
+
/**
|
|
2743
|
+
* The Model with everything the active Surfaces read, for a render that
|
|
2744
|
+
* fetches nothing (SSR, a prerender). Each pass prefetches every Surface
|
|
2745
|
+
* that plans a read, over the Model the one before it left, so a Surface
|
|
2746
|
+
* active only once another's read has arrived is read in the next pass (or
|
|
2747
|
+
* the same one, when it comes later in `active`). It stops at the first
|
|
2748
|
+
* pass that plans nothing, and fails with `RemoteUnsatisfied` when
|
|
2749
|
+
* `options.passes` run out first. Reads are cache-first: a field already
|
|
2750
|
+
* held is not asked again.
|
|
2751
|
+
*/
|
|
2752
|
+
satisfy(model: AppModel, active: Readonly<Record<string, ActiveSurface<AppModel> | Surface<AppModel, any, any, void>>>, options?: SatisfyOptions): Effect.Effect<AppModel, RemoteReadError | RemoteProtocolError | RemoteQueryError | RemoteUnsatisfied, RemoteClient>;
|
|
2481
2753
|
/**
|
|
2482
2754
|
* Starts a registered mutation from `update`: applies `MutationStarted` (with
|
|
2483
2755
|
* the optimistic operations) to the Model and returns the Command that runs
|
|
@@ -2503,6 +2775,28 @@ export interface RemoteDomain<AppModel, Store extends RemoteModel, Entities exte
|
|
|
2503
2775
|
/** `Remote.inspect` of the bound slice. */
|
|
2504
2776
|
inspect(model: AppModel): RemoteInspection;
|
|
2505
2777
|
}
|
|
2778
|
+
/** What `Remote.fold(Data, …).mutate` starts: `Data.mutate`'s result with its Command lifted. */
|
|
2779
|
+
export type FoldedMutationStarted<AppModel, ParentMessage> = Omit<MutationStarted<AppModel>, 'command'> & {
|
|
2780
|
+
readonly command: Command<ParentMessage, never, RemoteClient>;
|
|
2781
|
+
};
|
|
2782
|
+
/**
|
|
2783
|
+
* A bound domain folded under one of the application's own Message variants,
|
|
2784
|
+
* from `Remote.fold`. Calling it reduces a Remote Message into the Model; the
|
|
2785
|
+
* members that produce Messages, `fetch`, `mutate`, and `subscriptions`,
|
|
2786
|
+
* yield the wrapper Message instead of `RemoteMessage`, with the lift recorded
|
|
2787
|
+
* so Story and Scene can resolve a fetch or a mutation by Remote's own answer.
|
|
2788
|
+
* Members that only read or write the Model (`get`, `refresh`, `next`,
|
|
2789
|
+
* `overlay`, and the rest) stay on the domain itself.
|
|
2790
|
+
*/
|
|
2791
|
+
export interface RemoteFold<AppModel, ParentMessage, Domain extends RemoteDomain<AppModel, any, any, any, any>> {
|
|
2792
|
+
(model: AppModel, message: RemoteMessage | RemoteMessageInput): Update.Return<AppModel, ParentMessage>;
|
|
2793
|
+
/** `Data.mutate`, its Command lifted. */
|
|
2794
|
+
readonly mutate: (...args: Parameters<Domain['mutate']>) => FoldedMutationStarted<AppModel, ParentMessage>;
|
|
2795
|
+
/** `Data.subscriptions`, every entry lifted to the wrapper Message. */
|
|
2796
|
+
readonly subscriptions: <const Active extends Readonly<Record<string, ActiveSurface<AppModel> | Surface<AppModel, any, any, void>>>>(active: Active, options?: SubscriptionsOptions) => SubscriptionEntries<AppModel, Active, ParentMessage>;
|
|
2797
|
+
}
|
|
2798
|
+
/** The application Model a bound domain is over. */
|
|
2799
|
+
export type ModelOfDomain<Domain> = Domain extends RemoteDomain<infer AppModel, any, any, any, any> ? AppModel : never;
|
|
2506
2800
|
/** A projection's connection requirement with the `QueryRef` that runs it. */
|
|
2507
2801
|
export interface QueryRequirement extends ConnectionRequirement {
|
|
2508
2802
|
readonly ref: QueryRef<string, unknown>;
|
|
@@ -2533,9 +2827,23 @@ export interface QueryProjection<AppModel, Value, Name extends string, Input> ex
|
|
|
2533
2827
|
export type QueryInput<Q> = Q extends QueryDescriptor<any, infer Input, any> ? Input : never;
|
|
2534
2828
|
/** The entity a query's connection is over. */
|
|
2535
2829
|
export type QueryEntity<Q> = Q extends QueryDescriptor<any, any, ConnectionSpec<infer Entity>> ? Entity : string;
|
|
2830
|
+
/**
|
|
2831
|
+
* When what a projection shows was last received, and whether it is stale
|
|
2832
|
+
* or loading. See `Remote.meta`.
|
|
2833
|
+
*/
|
|
2834
|
+
export interface ReadMeta {
|
|
2835
|
+
/** The newest server write among what is shown; none received reads `undefined`. */
|
|
2836
|
+
readonly updatedAt: number | undefined;
|
|
2837
|
+
/** Any shown field or connection is marked stale. */
|
|
2838
|
+
readonly stale: boolean;
|
|
2839
|
+
/** Any shown field or connection is in flight. */
|
|
2840
|
+
readonly loading: boolean;
|
|
2841
|
+
}
|
|
2536
2842
|
export interface MutateOptions {
|
|
2537
2843
|
/** What the request changes before the server answers; released when it settles. */
|
|
2538
2844
|
readonly optimistic?: ReadonlyArray<OptimisticOperation> | undefined;
|
|
2845
|
+
/** The clock `MutationSucceeded` stamps the answer with; default `Date.now`, read at each use. */
|
|
2846
|
+
readonly now?: (() => number) | undefined;
|
|
2539
2847
|
}
|
|
2540
2848
|
export interface RetainOptions {
|
|
2541
2849
|
/** The query connections the application shows, by `QueryRef` or identity. */
|
|
@@ -2547,11 +2855,29 @@ export interface RetainOptions {
|
|
|
2547
2855
|
export interface ObserveOptions {
|
|
2548
2856
|
/** Default `RemotePolicy.cacheFirst`. */
|
|
2549
2857
|
readonly policy?: RemotePolicy | undefined;
|
|
2550
|
-
/** The clock a refreshing policy reads; default `Date.now
|
|
2858
|
+
/** The clock a refreshing policy reads; default `Date.now`, read at each use. */
|
|
2551
2859
|
readonly now?: (() => number) | undefined;
|
|
2552
2860
|
}
|
|
2861
|
+
/** How `Data.satisfy` reads: how many passes it may take, and the clock. */
|
|
2862
|
+
export interface SatisfyOptions {
|
|
2863
|
+
/** At most this many passes over the Surfaces; default 8. */
|
|
2864
|
+
readonly passes?: number | undefined;
|
|
2865
|
+
/** The clock the reads are stamped with; default `Date.now`, read at each use. */
|
|
2866
|
+
readonly now?: (() => number) | undefined;
|
|
2867
|
+
}
|
|
2868
|
+
declare const RemoteUnsatisfied_base: Schema.Class<RemoteUnsatisfied, Schema.TaggedStruct<"RemoteUnsatisfied", {
|
|
2869
|
+
readonly surfaces: Schema.$Array<Schema.String>;
|
|
2870
|
+
readonly passes: Schema.Number;
|
|
2871
|
+
}>, import("effect/Cause").YieldableError>;
|
|
2872
|
+
/**
|
|
2873
|
+
* `Data.satisfy` reached its bound with Surfaces still reading, such as a
|
|
2874
|
+
* chain whose every read reveals one more. It names them, so a page that
|
|
2875
|
+
* would have rendered them loading fails instead. (A read the server leaves
|
|
2876
|
+
* unanswered settles as missing and ends the loop.)
|
|
2877
|
+
*/
|
|
2878
|
+
export declare class RemoteUnsatisfied extends RemoteUnsatisfied_base {}
|
|
2553
2879
|
export interface LiveOptions {
|
|
2554
|
-
/** The clock `LiveReceived` stamps events with; default `Date.now
|
|
2880
|
+
/** The clock `LiveReceived` stamps events with; default `Date.now`, read at each use. */
|
|
2555
2881
|
readonly now?: (() => number) | undefined;
|
|
2556
2882
|
}
|
|
2557
2883
|
/** A query the read entry runs, as its dependencies carry it: plain data Foldkit compares. */
|
|
@@ -2575,6 +2901,14 @@ export interface ReadDependencies {
|
|
|
2575
2901
|
* leaves it running.
|
|
2576
2902
|
*/
|
|
2577
2903
|
readonly refresh: number;
|
|
2904
|
+
/**
|
|
2905
|
+
* Under a refreshing policy, when a value the entry holds next ages out and
|
|
2906
|
+
* what is due then. Time reaches Remote only as a Message: the entry sleeps
|
|
2907
|
+
* until then and emits `RefreshStarted`, which marks the fields stale, and
|
|
2908
|
+
* the plan that follows fetches them. A Model that does not change past its
|
|
2909
|
+
* `maxAge` is otherwise never looked at again.
|
|
2910
|
+
*/
|
|
2911
|
+
readonly expires: Deadline | null;
|
|
2578
2912
|
}
|
|
2579
2913
|
export declare const Remote: {
|
|
2580
2914
|
/** The submodel's schema, the same for every domain; embed it in the application Model. */
|
|
@@ -2595,6 +2929,11 @@ export declare const Remote: {
|
|
|
2595
2929
|
readonly id: Schema.String;
|
|
2596
2930
|
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
2597
2931
|
}>>;
|
|
2932
|
+
readonly settled: Schema.$Array<Schema.Struct<{
|
|
2933
|
+
readonly entity: Schema.String;
|
|
2934
|
+
readonly id: Schema.String;
|
|
2935
|
+
readonly fields: Schema.$Array<Schema.String>;
|
|
2936
|
+
}>>;
|
|
2598
2937
|
}>;
|
|
2599
2938
|
now: Schema.Number;
|
|
2600
2939
|
};
|
|
@@ -2646,6 +2985,7 @@ export declare const Remote: {
|
|
|
2646
2985
|
readonly entity: Schema.String;
|
|
2647
2986
|
readonly id: Schema.String;
|
|
2648
2987
|
}>>>;
|
|
2988
|
+
now: Schema.Number;
|
|
2649
2989
|
};
|
|
2650
2990
|
MutationFailed: {
|
|
2651
2991
|
requestId: Schema.String;
|
|
@@ -2661,6 +3001,10 @@ export declare const Remote: {
|
|
|
2661
3001
|
OverlayLifted: {
|
|
2662
3002
|
id: Schema.String;
|
|
2663
3003
|
};
|
|
3004
|
+
WindowGrown: {
|
|
3005
|
+
window: Schema.String;
|
|
3006
|
+
size: Schema.Number;
|
|
3007
|
+
};
|
|
2664
3008
|
LiveReceived: {
|
|
2665
3009
|
stream: Schema.String;
|
|
2666
3010
|
event: Schema.Unknown;
|
|
@@ -2674,6 +3018,18 @@ export declare const Remote: {
|
|
|
2674
3018
|
connection: Schema.String;
|
|
2675
3019
|
page: Schema.Unknown;
|
|
2676
3020
|
refreshes: Schema.optional<Schema.Boolean>;
|
|
3021
|
+
select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
3022
|
+
entities: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
3023
|
+
readonly entity: Schema.String;
|
|
3024
|
+
readonly id: Schema.String;
|
|
3025
|
+
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
3026
|
+
}>>>;
|
|
3027
|
+
settled: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
3028
|
+
readonly entity: Schema.String;
|
|
3029
|
+
readonly id: Schema.String;
|
|
3030
|
+
readonly fields: Schema.$Array<Schema.String>;
|
|
3031
|
+
}>>>;
|
|
3032
|
+
now: Schema.optional<Schema.Number>;
|
|
2677
3033
|
};
|
|
2678
3034
|
ConnectionInvalidated: {
|
|
2679
3035
|
connection: Schema.String;
|
|
@@ -2695,6 +3051,160 @@ export declare const Remote: {
|
|
|
2695
3051
|
}>(message: M) => message is Extract<M, {
|
|
2696
3052
|
readonly _tag: RemoteMessageTag;
|
|
2697
3053
|
}>;
|
|
3054
|
+
/**
|
|
3055
|
+
* Remote's Messages as one Schema, for a wrapper variant in the
|
|
3056
|
+
* application's union: `GotRemoteMessage: { message: Remote.Message }`. With
|
|
3057
|
+
* a wrapper, `update` matches the application's union exhaustively and
|
|
3058
|
+
* `Remote.fold` reduces what arrives inside it.
|
|
3059
|
+
*/
|
|
3060
|
+
Message: import("foldkit/message").MessageUnion<{
|
|
3061
|
+
ReadReceived: {
|
|
3062
|
+
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
3063
|
+
result: Schema.Struct<{
|
|
3064
|
+
readonly entities: Schema.$Array<Schema.Struct<{
|
|
3065
|
+
readonly entity: Schema.String;
|
|
3066
|
+
readonly id: Schema.String;
|
|
3067
|
+
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
3068
|
+
}>>;
|
|
3069
|
+
readonly settled: Schema.$Array<Schema.Struct<{
|
|
3070
|
+
readonly entity: Schema.String;
|
|
3071
|
+
readonly id: Schema.String;
|
|
3072
|
+
readonly fields: Schema.$Array<Schema.String>;
|
|
3073
|
+
}>>;
|
|
3074
|
+
}>;
|
|
3075
|
+
now: Schema.Number;
|
|
3076
|
+
};
|
|
3077
|
+
ReadFailed: {
|
|
3078
|
+
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
3079
|
+
error: Schema.Struct<{
|
|
3080
|
+
readonly _tag: Schema.String;
|
|
3081
|
+
readonly message: Schema.String;
|
|
3082
|
+
}>;
|
|
3083
|
+
stream: Schema.optional<Schema.String>;
|
|
3084
|
+
};
|
|
3085
|
+
RefreshStarted: {
|
|
3086
|
+
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
3087
|
+
};
|
|
3088
|
+
ReadStarted: {
|
|
3089
|
+
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
3090
|
+
refresh: Schema.optional<Schema.Number>;
|
|
3091
|
+
};
|
|
3092
|
+
QueryStarted: {
|
|
3093
|
+
connections: Schema.$Array<Schema.String>;
|
|
3094
|
+
};
|
|
3095
|
+
RetentionChanged: {
|
|
3096
|
+
roots: Schema.Struct<{
|
|
3097
|
+
readonly requirements: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
3098
|
+
readonly connections: Schema.$Array<Schema.Struct<{
|
|
3099
|
+
readonly identity: Schema.String;
|
|
3100
|
+
readonly select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
3101
|
+
}>>;
|
|
3102
|
+
}>;
|
|
3103
|
+
};
|
|
3104
|
+
Hydrated: {
|
|
3105
|
+
connections: Schema.optional<Schema.Unknown>;
|
|
3106
|
+
entities: Schema.Unknown;
|
|
3107
|
+
merge: Schema.Union<readonly [Schema.Literal<"replace">, Schema.Literal<"preserve-existing">]>;
|
|
3108
|
+
};
|
|
3109
|
+
MutationStarted: {
|
|
3110
|
+
requestId: Schema.String;
|
|
3111
|
+
optimistic: Schema.optional<Schema.$Array<Schema.Unknown>>;
|
|
3112
|
+
};
|
|
3113
|
+
MutationSucceeded: {
|
|
3114
|
+
requestId: Schema.String;
|
|
3115
|
+
entities: Schema.$Array<Schema.Struct<{
|
|
3116
|
+
readonly entity: Schema.String;
|
|
3117
|
+
readonly id: Schema.String;
|
|
3118
|
+
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
3119
|
+
}>>;
|
|
3120
|
+
connections: Schema.optional<Schema.$Array<Schema.Unknown>>;
|
|
3121
|
+
deleted: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
3122
|
+
readonly entity: Schema.String;
|
|
3123
|
+
readonly id: Schema.String;
|
|
3124
|
+
}>>>;
|
|
3125
|
+
now: Schema.Number;
|
|
3126
|
+
};
|
|
3127
|
+
MutationFailed: {
|
|
3128
|
+
requestId: Schema.String;
|
|
3129
|
+
error: Schema.Struct<{
|
|
3130
|
+
readonly _tag: Schema.String;
|
|
3131
|
+
readonly message: Schema.String;
|
|
3132
|
+
}>;
|
|
3133
|
+
};
|
|
3134
|
+
OverlayShown: {
|
|
3135
|
+
id: Schema.String;
|
|
3136
|
+
optimistic: Schema.$Array<Schema.Unknown>;
|
|
3137
|
+
};
|
|
3138
|
+
OverlayLifted: {
|
|
3139
|
+
id: Schema.String;
|
|
3140
|
+
};
|
|
3141
|
+
WindowGrown: {
|
|
3142
|
+
window: Schema.String;
|
|
3143
|
+
size: Schema.Number;
|
|
3144
|
+
};
|
|
3145
|
+
LiveReceived: {
|
|
3146
|
+
stream: Schema.String;
|
|
3147
|
+
event: Schema.Unknown;
|
|
3148
|
+
policy: Schema.optional<Schema.Unknown>;
|
|
3149
|
+
now: Schema.Number;
|
|
3150
|
+
};
|
|
3151
|
+
GapCleared: {
|
|
3152
|
+
stream: Schema.String;
|
|
3153
|
+
};
|
|
3154
|
+
ConnectionMerged: {
|
|
3155
|
+
connection: Schema.String;
|
|
3156
|
+
page: Schema.Unknown;
|
|
3157
|
+
refreshes: Schema.optional<Schema.Boolean>;
|
|
3158
|
+
select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
3159
|
+
entities: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
3160
|
+
readonly entity: Schema.String;
|
|
3161
|
+
readonly id: Schema.String;
|
|
3162
|
+
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
3163
|
+
}>>>;
|
|
3164
|
+
settled: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
3165
|
+
readonly entity: Schema.String;
|
|
3166
|
+
readonly id: Schema.String;
|
|
3167
|
+
readonly fields: Schema.$Array<Schema.String>;
|
|
3168
|
+
}>>>;
|
|
3169
|
+
now: Schema.optional<Schema.Number>;
|
|
3170
|
+
};
|
|
3171
|
+
ConnectionInvalidated: {
|
|
3172
|
+
connection: Schema.String;
|
|
3173
|
+
};
|
|
3174
|
+
ConnectionRefreshed: {
|
|
3175
|
+
connection: Schema.String;
|
|
3176
|
+
};
|
|
3177
|
+
QueryFailed: {
|
|
3178
|
+
connection: Schema.String;
|
|
3179
|
+
error: Schema.Struct<{
|
|
3180
|
+
readonly _tag: Schema.String;
|
|
3181
|
+
readonly message: Schema.String;
|
|
3182
|
+
}>;
|
|
3183
|
+
};
|
|
3184
|
+
}>;
|
|
3185
|
+
/**
|
|
3186
|
+
* A bound domain under one wrapper variant of the application's union, the
|
|
3187
|
+
* same shape Foldkit gives a Submodel: `toParentMessage` wraps Remote's
|
|
3188
|
+
* Messages, the fold reduces them, and its `fetch`, `mutate`, and
|
|
3189
|
+
* `subscriptions` yield the wrapper. Spreading `Remote.messages` and
|
|
3190
|
+
* narrowing with `Remote.reduces` remains the shorter path for an
|
|
3191
|
+
* application whose `update` only reduces.
|
|
3192
|
+
*
|
|
3193
|
+
* @example
|
|
3194
|
+
* ```ts
|
|
3195
|
+
* const Message = defineMessageUnion({ GotRemoteMessage: { message: Remote.Message } })
|
|
3196
|
+
* const foldData = Remote.fold(Data, message => Message.GotRemoteMessage({ message }))
|
|
3197
|
+
*
|
|
3198
|
+
* const update = (model: Model, message: Message): Return =>
|
|
3199
|
+
* Message.match(message, {
|
|
3200
|
+
* GotRemoteMessage: ({ message }) => foldData(model, message),
|
|
3201
|
+
* })
|
|
3202
|
+
* const subscriptions = Subscription.make<Model, Message, RemoteClient>()(() =>
|
|
3203
|
+
* foldData.subscriptions({ page: Surface.at(ProjectPage, …) }),
|
|
3204
|
+
* )
|
|
3205
|
+
* ```
|
|
3206
|
+
*/
|
|
3207
|
+
fold: <Domain extends RemoteDomain<any, any, any, any, any>, ParentMessage>(domain: Domain, toParentMessage: (message: RemoteMessage) => ParentMessage) => RemoteFold<ModelOfDomain<Domain>, ParentMessage, Domain>;
|
|
2698
3208
|
/**
|
|
2699
3209
|
* A patch of one entity's values, for a mutation's `optimistic` list or an
|
|
2700
3210
|
* overlay. Takes a `foldkit-entity` Entity or a Remote descriptor alike, so
|
|
@@ -2737,6 +3247,17 @@ export declare const Remote: {
|
|
|
2737
3247
|
* rejects a selection for an entity this domain never declared.
|
|
2738
3248
|
*/
|
|
2739
3249
|
at: <AppModel, Store extends RemoteModel, Entities extends readonly EntityLike[], Queries extends readonly QueryDescriptor<any, any, any>[], Mutations extends readonly MutationDescriptor<any, any, any>[]>(definition: RemoteDescriptor<Entities, Queries, Mutations>, store: ModelRef<AppModel, Store>) => BoundRemote<AppModel, Store, EntityName<Entities[number]>>;
|
|
3250
|
+
/**
|
|
3251
|
+
* The resume part for this domain, for `foldkit-ssr`'s `SSR.plan({ parts })`:
|
|
3252
|
+
* a server render sends what the plan's active Surfaces read from the store,
|
|
3253
|
+
* each connection with its boundaries and each live cursor with it, and
|
|
3254
|
+
* nothing else. `id` tells two domains in one application apart.
|
|
3255
|
+
*/
|
|
3256
|
+
resume: <AppModel, Store extends RemoteModel>(domain: {
|
|
3257
|
+
readonly store: ModelRef<AppModel, Store>;
|
|
3258
|
+
}, options?: {
|
|
3259
|
+
readonly id?: string | undefined;
|
|
3260
|
+
}) => RemoteResumePart<AppModel>;
|
|
2740
3261
|
/**
|
|
2741
3262
|
* A Projection node that reads a `RemoteData` value out of the store. The id
|
|
2742
3263
|
* is supplied by the caller, usually from a Surface's params. The assembled
|
|
@@ -2745,6 +3266,17 @@ export declare const Remote: {
|
|
|
2745
3266
|
* stale field reads as `Refreshing`: an observer is refetching it.
|
|
2746
3267
|
*/
|
|
2747
3268
|
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>>;
|
|
3269
|
+
/**
|
|
3270
|
+
* When what a projection shows was last received, and whether it is stale
|
|
3271
|
+
* or loading. Pure, so a view can show "updated 5s ago" without I/O.
|
|
3272
|
+
*
|
|
3273
|
+
* `updatedAt` is the newest server write among what is shown, as the
|
|
3274
|
+
* store dates it; `undefined` when nothing shown was received (nothing
|
|
3275
|
+
* loaded, or only an optimistic preview). `stale` is any shown field or
|
|
3276
|
+
* connection marked stale; `loading` is any of them in flight. Optimistic
|
|
3277
|
+
* previews do not date: showing only one reads `updatedAt: undefined`.
|
|
3278
|
+
*/
|
|
3279
|
+
meta: <AppModel, Store extends RemoteModel, Value>(bound: BoundRemote<AppModel, Store>, model: AppModel, projection: Projection<AppModel, Value>) => ReadMeta;
|
|
2748
3280
|
/**
|
|
2749
3281
|
* The pure plan for a projection against a Model: the requirements its
|
|
2750
3282
|
* remote store does not satisfy, under `options` (freshness, force). A
|
|
@@ -2797,6 +3329,17 @@ export declare const Remote: {
|
|
|
2797
3329
|
* already being refreshed returns the same Model.
|
|
2798
3330
|
*/
|
|
2799
3331
|
refresh: <AppModel, Store extends RemoteModel>(bound: BoundRemote<AppModel, Store>, model: AppModel, target: Projection<AppModel, unknown> | Surface<AppModel, any, any, void>) => AppModel;
|
|
3332
|
+
/**
|
|
3333
|
+
* Forgets everything the server told this Model: values, tombstones,
|
|
3334
|
+
* unavailable fields, connections, live cursors, failures. What is known is
|
|
3335
|
+
* known for a principal, and this is the one boundary for a login, a logout
|
|
3336
|
+
* or a switch of organization: called from `update`, it performs no I/O, and
|
|
3337
|
+
* every active Surface's read and live entries restart, so the screen asks
|
|
3338
|
+
* again as whoever the client now is. A read or stream begun before is
|
|
3339
|
+
* interrupted rather than landing after. A mutation in flight is treated as
|
|
3340
|
+
* applied: its answer writes nothing here.
|
|
3341
|
+
*/
|
|
3342
|
+
forget: <AppModel, Store extends RemoteModel>(bound: BoundRemote<AppModel, Store>, model: AppModel) => AppModel;
|
|
2800
3343
|
/**
|
|
2801
3344
|
* Writes a read result into the store, recording each field's applied window.
|
|
2802
3345
|
* `requests` are the planned requirements the result answers.
|
|
@@ -2825,8 +3368,10 @@ export declare const Remote: {
|
|
|
2825
3368
|
/**
|
|
2826
3369
|
* Runs a `Query` through `RemoteClient`, encoding its input from the ref.
|
|
2827
3370
|
* Pair the result with `Remote.queryMessage` to merge the page into the Model.
|
|
3371
|
+
* With `select`, the server also returns the selected fields of the page's
|
|
3372
|
+
* items, so one response populates both the connection and the store.
|
|
2828
3373
|
*/
|
|
2829
|
-
query: <Name extends string, Input>(ref: QueryRef<Name, Input
|
|
3374
|
+
query: <Name extends string, Input>(ref: QueryRef<Name, Input>, select?: RelationRequirement | undefined) => Effect.Effect<{
|
|
2830
3375
|
readonly edges: readonly {
|
|
2831
3376
|
readonly entity: string;
|
|
2832
3377
|
readonly id: string;
|
|
@@ -2848,9 +3393,21 @@ export declare const Remote: {
|
|
|
2848
3393
|
} | {
|
|
2849
3394
|
readonly _tag: "Unknown";
|
|
2850
3395
|
};
|
|
3396
|
+
readonly entities?: readonly {
|
|
3397
|
+
readonly entity: string;
|
|
3398
|
+
readonly id: string;
|
|
3399
|
+
readonly values: {
|
|
3400
|
+
readonly [x: string]: unknown;
|
|
3401
|
+
};
|
|
3402
|
+
}[] | undefined;
|
|
3403
|
+
readonly settled?: readonly {
|
|
3404
|
+
readonly entity: string;
|
|
3405
|
+
readonly id: string;
|
|
3406
|
+
readonly fields: readonly string[];
|
|
3407
|
+
}[] | undefined;
|
|
2851
3408
|
}, RemoteQueryError, RemoteClient>;
|
|
2852
3409
|
/** The `RemoteMessage` that merges a query page into its connection. */
|
|
2853
|
-
queryMessage: <Name extends string, Input>(ref: QueryRef<Name, Input>, result: Schema.Schema.Type<typeof QueryResult
|
|
3410
|
+
queryMessage: <Name extends string, Input>(ref: QueryRef<Name, Input>, result: Schema.Schema.Type<typeof QueryResult>, select?: RelationRequirement | undefined, now?: number | undefined) => RemoteMessage;
|
|
2854
3411
|
/**
|
|
2855
3412
|
* The edges a connection shows: its server-known region with pending and
|
|
2856
3413
|
* confirmed overlays placed around it, minus removed edges and edges whose
|
|
@@ -2909,11 +3466,8 @@ export declare const Remote: {
|
|
|
2909
3466
|
* read, since nothing was being read. The resume cursor is read
|
|
2910
3467
|
* from `RemoteModel.live`, so the application tracks no cursor of its own.
|
|
2911
3468
|
*/
|
|
2912
|
-
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,
|
|
2913
|
-
readonly requirements: ReadonlyArray<Requirement>;
|
|
2914
|
-
readonly cursor: LiveCursor;
|
|
2915
|
-
}, RemoteClient>;
|
|
3469
|
+
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>;
|
|
2916
3470
|
};
|
|
2917
3471
|
//#endregion
|
|
2918
|
-
export { Entity$1 as Entity };
|
|
3472
|
+
export { Entity$1 as Entity, type RemoteResumePart };
|
|
2919
3473
|
//# sourceMappingURL=index.d.mts.map
|