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
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1542 @@
|
|
|
1
|
+
import { a as remoteDataSchema, i as RemoteError, n as Freshness, o as remoteErrorSchema, r as RemoteData, t as Denied } from "./remoteData-mK1suYi1.js";
|
|
2
|
+
import { a as PredictionPart, i as PredictionMismatch, n as OutboxUnreadable, o as RemoteDiagnostic, r as OutboxUnsaved, s as WriteUnheard, t as LiveRefused } from "./diagnostics-DHhVYflV.js";
|
|
3
|
+
import { _ as unknown, a as EdgeRef, c as edge, d as hasPrevious, f as isGapped, g as terminal, h as segment, i as Edge, l as emptyConnection, m as merge, n as Connection, o as Segment, p as items, r as Cursor, s as cursor, t as Boundary, u as hasNext } from "./connection-BRyaJy89.js";
|
|
4
|
+
import { S as writeEntity, _ as remove, a as askAgain, b as tombstone, c as entityKey, d as isFieldStale, f as isFieldUnavailable, g as readField, h as missingFields, i as EntityWrite, l as entry, m as markStale, n as EntityKey, o as clearStale, p as isTombstone, r as EntityStore, s as emptyStore, t as EntityEntry, u as hasField, v as setStale, x as writeEntities, y as setUnavailable } from "./store-ah2qjcJW.js";
|
|
5
|
+
import { A as PendingDelete, B as derivedOfWrite, C as DerivedBy, D as MutationState, E as MutationDescriptor, F as SchemaOrFields, G as mutationStatus, H as failMutation, I as StartedWrite, J as predictionOfWrite, K as optimisticOfWrite, L as TypeOf, M as Reconciled, N as Refusal, O as MutationStatus, P as RefusalOfWrite, R as beginMutation, S as visibleStore, T as MutationAnswer, U as forbiddenByWrite, V as emptyMutationState, W as forgetFailure, X as schemaOf, Y as reconcileMutation, Z as settledLater, _ as removeOverlay, a as OptimisticOperation, b as settleSuccess, c as addOverlay, d as emptyOptimistic, f as goneIn, g as removeLayer, h as pruneOverlays, i as EntityLayer, j as PendingPatch, k as NormalizedPatch, l as beginOptimistic, m as plannedStore, n as ConnectionIdentity, o as OptimisticState, p as heldOnlyByRequests, q as patchOfWrite, r as ConnectionOverlay, s as addLayer, t as ConnectionChange, u as connectionIdentity, v as resolvedPatches, w as Mutation, x as visibleItems, y as settleFailure, z as brokenByWrite } from "./optimistic-CECsfNGY.js";
|
|
6
|
+
import { a as Query, c as QueryRef, d as queryIdentity, f as stableStringify, i as LivePolicy, l as QueryWindow, n as IDENTITY_SEPARATOR, o as QueryDescriptor, r as LiveInsertion, s as QueryInputs, t as ConnectionSpec, u as ResultOf } from "./query-BuIU93xA.js";
|
|
7
|
+
import { a as Requirement, i as RemoteRequirements, n as RelationRequirement, o as connectionsOf, r as RemoteConnections, s as requirementsOf, t as ConnectionRequirement } from "./requirement-D57S2LpH.js";
|
|
8
|
+
import { A as RemoteMutationError, B as WireBoundary, C as ReadBatch, D as RemoteForbidden, E as RelationRequest, F as RemoteUnauthenticated, I as RemoteUnreachable, L as SettledFields, M as RemoteQueryError, N as RemoteReadError, O as RemoteLiveError, P as RemoteRpc, R as ShownSlice, S as Read, T as ReadRequest, _ as QueryEdge, a as LiveEdge, b as QueryRpc, c as MAX_LIVE_QUERIES, d as Mutate, f as MutationRequest, g as PageSize, h as OperationId, i as LiveChange, j as RemoteProtocolError, k as RemoteLiveRefused, l as MAX_RELATION_DEPTH, m as NormalizedEntity, n as ConnectionChangeSchema, o as LiveRequirement, p as MutationResult, r as Live, s as MAX_FIELDS_PER_REQUEST, t as AnswerRead, u as MAX_SHOWN_ENTITIES, v as QueryRequest, w as ReadBatchResult, x as REMOTE_PROTOCOL_VERSION, y as QueryResult, z as WindowSchema } from "./wire-DthPcTM6.js";
|
|
9
|
+
import { a as coalesceReads, i as coalesceQueries, n as CoalesceOptions, o as requirementKey, r as QueryRun, t as BatchRead } from "./coalesce-CLAr92Nk.js";
|
|
10
|
+
import { a as LiveEvent, c as applyConnectionEvent, d as emptyLiveState, f as liveHasNext, i as LiveCursor, l as applyEntityEvent, n as ConnectionApplied, o as LiveOutcome, p as liveHasPrevious, r as EntityApplied, s as LiveState, t as BoundaryCounts, u as classifyLive } from "./live-BpTzlCnY.js";
|
|
11
|
+
import { a as connectionChangeOf, c as mutateRemote, i as coalescedLayer, l as remoteError, n as RemoteJsonClient, o as liveEventOf, r as RemoteRpcClient, s as mintOperation, t as RemoteClient } from "./client-B055kQuP.js";
|
|
12
|
+
import { a as RelationEntityAnnotation, c as aliasedField, d as refsIn, f as relationAlias, i as RelationAnnotation, l as isRefPage, m as targetsOf, n as RefPageValue, o as RelationKind, p as relationShape, r as RefParts, s as RelationShape, t as RELATION_ALIAS, u as refParts } from "./relation-BLBGOZom.js";
|
|
13
|
+
import { _ as relationOf, a as EntityRef, c as RefKey, d as Selection, f as SelectionOf, g as pageSchema, h as assemble, i as EntityPatch, l as RefPage, m as SelectionValueOf, n as Entity, o as FieldsFrom, p as SelectionValue, r as EntityDescriptor, s as PatchValues, t as AnySchema, u as Page, v as unavailableOf } from "./entity-CgsG5Uel.js";
|
|
14
|
+
import { a as belongsEncoded, i as MatchingOptions, n as Judged, o as matching, r as Matched, t as Belongs } from "./matching-DF5F9Us8.js";
|
|
15
|
+
import { a as Why, i as ShownBy, n as ReadStep, o as WhyTerm, r as ReadWhy } from "./why-kgp_Wr3z.js";
|
|
16
|
+
import { a as OutboxStatus, l as RetryOptions, n as OutboxItemState, t as OutboxItem } from "./outbox-DNuc4kZp.js";
|
|
17
|
+
import { a as gc, i as departedLimit, n as Retained, o as reachable, r as RetentionRoots, s as recentRoots, t as ConnectionRoot } from "./retain-BfNTvBRb.js";
|
|
18
|
+
import { a as SnapshotOptions, i as Snapshot, n as REMOTE_CACHE_VERSION, r as RemotePersistence, t as MergePolicy } from "./persistence-CCMnvg7-.js";
|
|
19
|
+
import { A as updateRemote, C as overlaysOf, D as remoteMessageSchema, E as remoteMessageCases, M as withRefreshRequested, N as writeRead, O as remoteModelSchema, S as onlyOverlaid, T as refreshedAt, _ as isLoading, a as RemoteMessageInput, b as isRemoteMessage, c as StreamHealth, d as failureOf, f as fieldMark, g as isFieldFailed, h as invalidateConnections, i as RemoteMessage, j as windowGrowthKey, k as retentionRootsSchema, l as dismissQueued, m as initialRemoteModel, n as PlacedOrder, o as RemoteMessageTag, p as forgetRemote, r as RefreshState, s as RemoteModel, t as Failures, u as emptyRefresh, v as isLoadingThrough, w as refreshIsInFlight, x as noFailures, y as isQueryLoading } from "./model-B6zk1NMB.js";
|
|
20
|
+
import { a as inspectRemote, i as inspectEntity, n as QueryExplanation, r as RemoteInspection, t as ExplainedDependencies } from "./inspect-DtRQGCRP.js";
|
|
21
|
+
import { a as plan, i as deadlineOf, n as PlanFreshness, o as windowKey, r as PlanOptions, t as Deadline } from "./plan-D9cftxC_.js";
|
|
22
|
+
import { t as RemotePolicy } from "./policy-DsWHmIAq.js";
|
|
23
|
+
import { r as RemoteResumePart, s as resumePart } from "./resume-Ct5R6yli.js";
|
|
24
|
+
import { a as json, i as http, n as RemoteJsonRequest, r as RemoteJsonSend, t as RemoteJsonAnswer } from "./json-DowLl1eB.js";
|
|
25
|
+
import { n as httpWithLive, r as liveFetch, t as LiveFetchOptions } from "./sse-C7LhdbiQ.js";
|
|
26
|
+
import { n as placeIn, t as RowPlace } from "./placement-jZdsIpmj.js";
|
|
27
|
+
import { Duration, Effect, Layer, Option, Schema } from "effect";
|
|
28
|
+
import { ActiveSurface, Contract, Diagnostic, Diagnostics, Focus, Invalid, ModelRef, Projection, ReportDiagnostic, Surface, SurfaceSource, Wiring } from "foldkit-surface";
|
|
29
|
+
import * as Domain from "foldkit-entity";
|
|
30
|
+
import { MemoryOperators } from "foldkit-entity";
|
|
31
|
+
import { RpcClientError } from "effect/rpc";
|
|
32
|
+
import { KeyValueStore } from "effect/persistence";
|
|
33
|
+
import { Command } from "foldkit/command";
|
|
34
|
+
import { EntryWithoutKeepAlive } from "foldkit/subscription";
|
|
35
|
+
import * as Update from "foldkit/update";
|
|
36
|
+
/** What a domain registers: a Remote descriptor, or a `foldkit-entity` Entity (read through `Entity.from`). */
|
|
37
|
+
export type EntityLike = EntityDescriptor<any, any> | Domain.AnyEntity;
|
|
38
|
+
/**
|
|
39
|
+
* What a read selects: a Remote Selection, or a `foldkit-entity` Selection
|
|
40
|
+
* (read through `Selection.from`).
|
|
41
|
+
*/
|
|
42
|
+
export type EntitySelection<Value, Name extends string, Id extends string = string> = Selection<Value, Name, 'entity'> | Domain.Selection<Name, unknown, Schema.Constraint & {
|
|
43
|
+
readonly Type: Value;
|
|
44
|
+
}, Id>;
|
|
45
|
+
/** The Remote descriptor either kind of entity reads as, at the type level. */
|
|
46
|
+
type DescriptorOf<E extends EntityLike> = E extends EntityDescriptor<any, any> ? E : E extends Domain.AnyEntity ? EntityDescriptor<E['name'], FieldsFrom<E>> : never;
|
|
47
|
+
type NameOf<E extends EntityLike> = DescriptorOf<E> extends EntityDescriptor<infer N, any> ? N : never;
|
|
48
|
+
type FieldsOf<E extends EntityLike> = DescriptorOf<E> extends EntityDescriptor<any, infer F> ? F : never;
|
|
49
|
+
type EntityName<D> = D extends {
|
|
50
|
+
readonly name: infer Name extends string;
|
|
51
|
+
} ? Name : never;
|
|
52
|
+
type QueryName<D> = D extends QueryDescriptor<infer Name, any, any> ? Name : never;
|
|
53
|
+
type MutationName<D> = D extends MutationDescriptor<infer Name, any, any> ? Name : never;
|
|
54
|
+
/**
|
|
55
|
+
* Nothing when `Name` is one of the domain's registered `Names`; otherwise a
|
|
56
|
+
* branded failure naming the descriptor, so `Data.get(Team.select(…))` for an
|
|
57
|
+
* unregistered `Team` errors at the selection in one line.
|
|
58
|
+
*/
|
|
59
|
+
export 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`>;
|
|
60
|
+
/** Nothing when a selection is of the query's entity; otherwise a branded failure naming both. */
|
|
61
|
+
export type SelectsEntity<Entity extends string, Of extends string> = [Entity] extends [Of] ? unknown : Invalid<`the selection is of "${Entity}", but the query lists "${Of}"`>;
|
|
62
|
+
export 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>[]> {
|
|
63
|
+
readonly entities: Entities;
|
|
64
|
+
readonly queries: Queries;
|
|
65
|
+
readonly mutations: Mutations;
|
|
66
|
+
readonly Model: Schema.Codec<RemoteModel, unknown>;
|
|
67
|
+
readonly initial: RemoteModel;
|
|
68
|
+
readonly Message: Schema.Schema<RemoteMessage>;
|
|
69
|
+
readonly update: (model: RemoteModel, message: RemoteMessage) => RemoteModel;
|
|
70
|
+
readonly rpc: typeof RemoteRpc;
|
|
71
|
+
/** Name-keyed lookups built from the declared entities, queries, and mutations. */
|
|
72
|
+
readonly registry: {
|
|
73
|
+
readonly entities: ReadonlyMap<string, EntityDescriptor<any, any>>;
|
|
74
|
+
readonly queries: ReadonlyMap<string, QueryDescriptor<any, any, any>>;
|
|
75
|
+
readonly mutations: ReadonlyMap<string, MutationDescriptor<any, any, any>>;
|
|
76
|
+
/**
|
|
77
|
+
* Per entity name, the members its server filters rows by under a rule
|
|
78
|
+
* the client does not run (`ReadFilter`), so a change to one is fetched,
|
|
79
|
+
* not placed.
|
|
80
|
+
*/
|
|
81
|
+
readonly filtered: ReadonlyMap<string, ReadonlyArray<string>>;
|
|
82
|
+
/**
|
|
83
|
+
* Per entity name, the members other registered Entities derive over its
|
|
84
|
+
* relations (`Derived.count`, `Derived.exists`), which a write of it
|
|
85
|
+
* moves: what a declared write predicts.
|
|
86
|
+
*/
|
|
87
|
+
readonly derived: ReadonlyMap<string, ReadonlyArray<DerivedBy>>;
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
declare const boundRemoteNames: unique symbol;
|
|
91
|
+
export interface BoundRemote<AppModel, Store extends RemoteModel, Names extends string = string> {
|
|
92
|
+
readonly definition: RemoteDescriptor;
|
|
93
|
+
/** The focus of the store's place in the application Model. */
|
|
94
|
+
readonly store: Focus<AppModel, Store>;
|
|
95
|
+
/** For `Module`: owns the store's Model path. */
|
|
96
|
+
readonly contract: Contract;
|
|
97
|
+
/**
|
|
98
|
+
* How the client runs primitive operators: `Remote.make`'s table, which a
|
|
99
|
+
* pending computed assignment is predicted by wherever the store is read.
|
|
100
|
+
*/
|
|
101
|
+
readonly operators: MemoryOperators;
|
|
102
|
+
/** Phantom: the entity names this Remote definition registers. */
|
|
103
|
+
readonly [boundRemoteNames]?: Names;
|
|
104
|
+
}
|
|
105
|
+
type MutationInput<M> = M extends MutationDescriptor<any, infer Input, any> ? Input : never;
|
|
106
|
+
type MutationRefusal<M> = M extends MutationDescriptor<any, any, any, infer Refused> ? Refused : never;
|
|
107
|
+
/** How `Data.persistence` keeps the cache across a reload. */
|
|
108
|
+
export interface PersistenceOptions<AppModel> {
|
|
109
|
+
/**
|
|
110
|
+
* Where the snapshot is stored, from the Model: one key per principal, so a
|
|
111
|
+
* change of principal reads and writes another snapshot.
|
|
112
|
+
*/
|
|
113
|
+
readonly key: (model: AppModel) => string;
|
|
114
|
+
/** Who the snapshot is for; one taken under another scope is discarded. */
|
|
115
|
+
readonly scope: (model: AppModel) => string;
|
|
116
|
+
/** The query connections whose rows survive a reload; none by default. */
|
|
117
|
+
readonly connections?: ReadonlyArray<ConnectionIdentity> | undefined;
|
|
118
|
+
/** What to keep, when it is not `snapshotOf` the `connections`. */
|
|
119
|
+
readonly snapshot?: ((remote: RemoteModel) => Snapshot) | undefined;
|
|
120
|
+
/** A snapshot larger than this is neither written nor read. */
|
|
121
|
+
readonly maxBytes?: number | undefined;
|
|
122
|
+
/** How long the cache must be unchanged before it is written; default 250 milliseconds. */
|
|
123
|
+
readonly debounce?: Duration.Input | undefined;
|
|
124
|
+
}
|
|
125
|
+
/** `Data.persistence`'s wiring, and the restore its runtime's `init` starts from. */
|
|
126
|
+
export interface PersistenceWiring<AppModel> extends Wiring<AppModel, RemoteMessage, KeyValueStore.KeyValueStore> {
|
|
127
|
+
/**
|
|
128
|
+
* The Model with the snapshot stored under its `key` restored, as the wiring
|
|
129
|
+
* would restore it. Resolve it as the runtime's `flags` and start `init`
|
|
130
|
+
* from it, so the first frame draws the stored rows; the wiring then
|
|
131
|
+
* restores only when `key` changes. A store it cannot read leaves the Model
|
|
132
|
+
* as it is, and the wiring tries again.
|
|
133
|
+
*/
|
|
134
|
+
readonly restore: (model: AppModel) => Effect.Effect<AppModel, never, KeyValueStore.KeyValueStore>;
|
|
135
|
+
}
|
|
136
|
+
/** How `Data.outbox` keeps durable writes across a reload. */
|
|
137
|
+
export interface OutboxOptions<AppModel> {
|
|
138
|
+
/**
|
|
139
|
+
* Where the queue is stored, from the Model: one key per principal, so one
|
|
140
|
+
* person's waiting writes are never sent as another's.
|
|
141
|
+
*/
|
|
142
|
+
readonly key: (model: AppModel) => string;
|
|
143
|
+
/**
|
|
144
|
+
* Who the queue is for, the principal. One stored under another scope reads
|
|
145
|
+
* as empty and is never written over; a page whose scope changes sends
|
|
146
|
+
* nothing it read for the old one, and reads the new one's.
|
|
147
|
+
*/
|
|
148
|
+
readonly scope: (model: AppModel) => string;
|
|
149
|
+
/** The wait between sends nothing answered: 1 second doubling to 30, unless given. */
|
|
150
|
+
readonly retry?: RetryOptions | undefined;
|
|
151
|
+
}
|
|
152
|
+
/** `Data.outbox`'s wiring, and the restore its runtime's `init` starts from. */
|
|
153
|
+
export interface OutboxWiring<AppModel> extends Wiring<AppModel, RemoteMessage, KeyValueStore.KeyValueStore | RemoteClient> {
|
|
154
|
+
/**
|
|
155
|
+
* The Model with the stored queue under its `key` read back, as the wiring
|
|
156
|
+
* would read it, and this page's session minted. Resolve it as the runtime's
|
|
157
|
+
* `flags` and start `init` from it: a durable write needs the session, and
|
|
158
|
+
* the first frame then shows the waiting writes.
|
|
159
|
+
*/
|
|
160
|
+
readonly restore: (model: AppModel) => Effect.Effect<AppModel, never, KeyValueStore.KeyValueStore>;
|
|
161
|
+
}
|
|
162
|
+
export interface DomainMutateOptions {
|
|
163
|
+
/** Overrides the generated id, for a retry, a durable bridge, or a test. Not with `durable`. */
|
|
164
|
+
readonly requestId?: string | undefined;
|
|
165
|
+
/**
|
|
166
|
+
* Queues the write in `Data.outbox` rather than sending it: stored first,
|
|
167
|
+
* sent in order by one tab, sent again after a reload with the same
|
|
168
|
+
* operation id and `now`, and after a failure that nothing answered. Its
|
|
169
|
+
* Command answers `MutationQueued`; the outbox's Subscriptions send it. Needs
|
|
170
|
+
* the outbox's `restore` to have run, and an input its Mutation encodes.
|
|
171
|
+
*/
|
|
172
|
+
readonly durable?: boolean | undefined;
|
|
173
|
+
/**
|
|
174
|
+
* What the request changes before the server answers, released when it
|
|
175
|
+
* settles. A function receives the generated ids, so a created entity can
|
|
176
|
+
* carry `tempId` until the result names the real one.
|
|
177
|
+
*/
|
|
178
|
+
readonly optimistic?: ReadonlyArray<OptimisticOperation> | ((ids: {
|
|
179
|
+
readonly requestId: string;
|
|
180
|
+
readonly tempId: string;
|
|
181
|
+
}) => ReadonlyArray<OptimisticOperation>) | undefined;
|
|
182
|
+
/**
|
|
183
|
+
* When the reader acted, in milliseconds since the epoch: what a time the
|
|
184
|
+
* write sets (`Expr.now` in `Entity.sets`) is predicted as, and the same
|
|
185
|
+
* number the request sends, which the server takes within its `clockSkew`.
|
|
186
|
+
* Read it where the action is, with `Remote.now`, since `update` reads no
|
|
187
|
+
* clock. Without it the time is not predicted, and the server's clock decides.
|
|
188
|
+
*/
|
|
189
|
+
readonly now?: number | undefined;
|
|
190
|
+
/**
|
|
191
|
+
* For a mutation that is a `Write`: the input keys to write, when only some
|
|
192
|
+
* changed (what an author edited). The rest of the input is still sent, whole.
|
|
193
|
+
*/
|
|
194
|
+
readonly keys?: ReadonlyArray<string> | undefined;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* One entry of the active record `subscriptions`, `wiring` and `satisfy`
|
|
198
|
+
* take: a Surface as the Model activates it (`Surface.at`/`Surface.when`),
|
|
199
|
+
* a source of keyed instances (`Surface.each`, or any `SurfaceSource`), or a
|
|
200
|
+
* Surface without params read whole. A family joins its parent's
|
|
201
|
+
* requirements with its instances', so passing the family alone fetches both
|
|
202
|
+
* the page and what the page reveals.
|
|
203
|
+
*/
|
|
204
|
+
export type ActiveEntry<AppModel> = ActiveSurface<AppModel> | Surface<AppModel, any, any, void> | SurfaceSource<AppModel>;
|
|
205
|
+
/** A Foldkit Subscription entry of the Remote domain, emitting its Messages through `RemoteClient`. */
|
|
206
|
+
export type RemoteEntry<AppModel, Dependencies> = EntryWithoutKeepAlive<AppModel, RemoteMessage, Dependencies, RemoteClient>;
|
|
207
|
+
/**
|
|
208
|
+
* The entries `RemoteDomain.subscriptions` returns for an active record: a read
|
|
209
|
+
* and a live entry per key (the live one idles when nothing is read live), and
|
|
210
|
+
* `retain`.
|
|
211
|
+
*/
|
|
212
|
+
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>; } & {
|
|
213
|
+
readonly retain: EntryWithoutKeepAlive<AppModel, Message, RetentionRoots, never>;
|
|
214
|
+
};
|
|
215
|
+
/** The dependencies of a live entry: what it subscribes to, and where a restart resumes. */
|
|
216
|
+
export interface LiveDependencies {
|
|
217
|
+
readonly requirements: ReadonlyArray<Requirement>;
|
|
218
|
+
/** The lists read live, each as its read sends it. */
|
|
219
|
+
readonly queries: ReadonlyArray<Schema.Schema.Type<typeof QueryRequest>>;
|
|
220
|
+
readonly cursor: LiveCursor;
|
|
221
|
+
readonly floor: number;
|
|
222
|
+
/** How many times the stream broke; each break restarts it. */
|
|
223
|
+
readonly restarts: number;
|
|
224
|
+
/** Breaks since its last applied event, which the restart's backoff grows with. */
|
|
225
|
+
readonly failures: number;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Whether what an active entry reads live is arriving. `Reconnecting` is a
|
|
229
|
+
* stream that broke and waits to resubscribe; until it has, changes are
|
|
230
|
+
* missed, and its rows may be out of date. `Refused` is a stream the server
|
|
231
|
+
* would not open for what it asks: it is not retried until that changes.
|
|
232
|
+
*/
|
|
233
|
+
export type LiveStatus =
|
|
234
|
+
/** It reads nothing live. */
|
|
235
|
+
{
|
|
236
|
+
readonly _tag: 'Idle';
|
|
237
|
+
} |
|
|
238
|
+
/** Subscribed, and not broken since. */
|
|
239
|
+
{
|
|
240
|
+
readonly _tag: 'Live';
|
|
241
|
+
} | {
|
|
242
|
+
readonly _tag: 'Reconnecting';
|
|
243
|
+
/** Breaks in a row, the first being 1. */
|
|
244
|
+
readonly attempt: number;
|
|
245
|
+
/** Why it broke; none for a gap in its events. */
|
|
246
|
+
readonly error: Option.Option<RemoteError>;
|
|
247
|
+
} |
|
|
248
|
+
/** The server refused it (`RemoteLiveRefused`); it waits for what it asks to change. */
|
|
249
|
+
{
|
|
250
|
+
readonly _tag: 'Refused';
|
|
251
|
+
readonly error: RemoteError;
|
|
252
|
+
};
|
|
253
|
+
export interface SubscriptionsOptions extends ObserveOptions, LiveOptions, RetainOptions {}
|
|
254
|
+
/**
|
|
255
|
+
* A Remote domain's wiring for an assembly: it routes Remote's Messages into
|
|
256
|
+
* `reduce`, brings its Subscriptions and contract, and requires `RemoteClient`
|
|
257
|
+
* from the runtime's resources Layer. The `Shared` tags reach the
|
|
258
|
+
* application's own update too, after Remote has reduced them.
|
|
259
|
+
*/
|
|
260
|
+
export type RemoteWiring<AppModel, Shared extends RemoteMessageTag = never> = Wiring<AppModel, RemoteMessage | RemoteMessageInput, RemoteClient, RemoteMessageTag> & {
|
|
261
|
+
readonly shared: ReadonlyArray<Shared>;
|
|
262
|
+
};
|
|
263
|
+
/** How `Data.wiring` joins an assembly: its Subscriptions' options, and what the application hears. */
|
|
264
|
+
export interface WiringOptions<Shared extends RemoteMessageTag = never> extends SubscriptionsOptions {
|
|
265
|
+
/**
|
|
266
|
+
* Remote's Messages the application's own `update` receives as well, after
|
|
267
|
+
* Remote has reduced them, so the Model it gets already holds what they say:
|
|
268
|
+
* `['MutationFailed']` to react to a write that failed.
|
|
269
|
+
*/
|
|
270
|
+
readonly shared?: ReadonlyArray<Shared> | undefined;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* A write that failed and is neither retried nor dismissed, typed by its
|
|
274
|
+
* mutation: what `Data.failedWrites` lists.
|
|
275
|
+
*/
|
|
276
|
+
export interface FailedWrite<M extends MutationDescriptor<any, any, any, any>> {
|
|
277
|
+
readonly requestId: string;
|
|
278
|
+
readonly mutation: M;
|
|
279
|
+
/** The input it was started with, to show or give back. */
|
|
280
|
+
readonly input: MutationInput<M>;
|
|
281
|
+
readonly error: RemoteError;
|
|
282
|
+
/** Why the server refused it, as `mutation` declares; none for any other failure. */
|
|
283
|
+
readonly refusal: Option.Option<MutationRefusal<M>>;
|
|
284
|
+
}
|
|
285
|
+
/** `FailedWrite` of each of a union of mutations. */
|
|
286
|
+
export type FailedWriteOf<M> = M extends MutationDescriptor<any, any, any, any> ? FailedWrite<M> : never;
|
|
287
|
+
/** What `RemoteDomain.mutate` hands `update`: the Model with the request started, and the Command that settles it. */
|
|
288
|
+
export interface MutationStarted<AppModel> {
|
|
289
|
+
readonly model: AppModel;
|
|
290
|
+
readonly requestId: string;
|
|
291
|
+
readonly tempId: string;
|
|
292
|
+
/** Yields `MutationSucceeded` or `MutationFailed`; never fails. */
|
|
293
|
+
readonly command: Command<RemoteMessage, never, RemoteClient>;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* A Remote domain bound to its place in the application Model: the descriptor
|
|
297
|
+
* (`Remote.define`), the binding (`Remote.at`), and the application-facing
|
|
298
|
+
* operations over them. Every method compiles to the `Remote.*` function of the
|
|
299
|
+
* same name, which stays exported for tooling, SSR, and tests.
|
|
300
|
+
*/
|
|
301
|
+
export 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> {
|
|
302
|
+
/** `Remote.select`: a Projection reading one entity through a selection of a registered entity. */
|
|
303
|
+
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>>;
|
|
304
|
+
/**
|
|
305
|
+
* `get`, and the projection also subscribes to the entity's changes: its
|
|
306
|
+
* requirements are marked `live`, so `subscriptions` derives a live entry for
|
|
307
|
+
* the Surfaces that read it.
|
|
308
|
+
*/
|
|
309
|
+
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>>;
|
|
310
|
+
/**
|
|
311
|
+
* A query connection read as a `Page` of items selected of the query's
|
|
312
|
+
* entity: `Initial` until the page and every item's selected fields are
|
|
313
|
+
* present, `Refreshing` while any of them is being refetched. The window is
|
|
314
|
+
* the page first asked for; the pages `next`, `previous` and `fetch` merge
|
|
315
|
+
* onto the connection read through the same projection.
|
|
316
|
+
*/
|
|
317
|
+
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>>;
|
|
318
|
+
/**
|
|
319
|
+
* "Load more": the Model with the read's window grown by one page, so it
|
|
320
|
+
* shows that many more rows; the read entry fetches what the connection
|
|
321
|
+
* lacks. None when the read shows everything there is (or is not a sized
|
|
322
|
+
* window). Called from `update`.
|
|
323
|
+
*/
|
|
324
|
+
more<Name extends string, Input>(model: AppModel, projection: QueryProjection<AppModel, any, Name, Input>): Option.Option<AppModel>;
|
|
325
|
+
/**
|
|
326
|
+
* What a query read is and what it currently is, as one serializable value —
|
|
327
|
+
* data-query-DESIGN §29.1: the domain, the definition and its input, the
|
|
328
|
+
* connection identity, the window, the Selection, the body as readable text
|
|
329
|
+
* with what it depends on, and what the read answers from this Model.
|
|
330
|
+
*
|
|
331
|
+
* Pure, so a DevTools panel showing it shows something the Model can be
|
|
332
|
+
* replayed to.
|
|
333
|
+
*
|
|
334
|
+
* Given `surfaces` — the same active record `subscriptions` takes — it also
|
|
335
|
+
* reports which of them read this connection, and why each is active where
|
|
336
|
+
* that is a readable fact (`Surface.when`) rather than a callback
|
|
337
|
+
* (`Surface.at`). A Projection cannot carry this itself: several Surfaces may
|
|
338
|
+
* read one connection, so it is not a property of the read.
|
|
339
|
+
*/
|
|
340
|
+
explain<Name extends string, Input>(model: AppModel, projection: QueryProjection<AppModel, any, Name, Input>, options?: {
|
|
341
|
+
readonly surfaces?: Readonly<Record<string, ActiveSurface<AppModel> | SurfaceSource<AppModel>>> | undefined;
|
|
342
|
+
}): QueryExplanation;
|
|
343
|
+
/**
|
|
344
|
+
* Why a read shows what it shows. Any Remote read: `Data.get`, `Data.live`
|
|
345
|
+
* or `Data.query`, or a projection made of them.
|
|
346
|
+
*
|
|
347
|
+
* `because` is every fact the Model holds about what it reads, as typed
|
|
348
|
+
* references: a list or a row's fields missing, stale, in flight or
|
|
349
|
+
* failed; a pending write showing a value, and which `where` term put a row
|
|
350
|
+
* in a list or took it out. The reason that decides the state comes first,
|
|
351
|
+
* and `message` says it, with what restarts it. For `Initial`, given
|
|
352
|
+
* `surfaces` (the record `subscriptions` takes), it tells the two wiring
|
|
353
|
+
* mistakes apart: no active Surface reads it, or one does and Remote's
|
|
354
|
+
* Subscriptions are not running. Pure: it reads the Model and plans nothing.
|
|
355
|
+
*/
|
|
356
|
+
why(model: AppModel, projection: Projection<AppModel, RemoteData<unknown>>, options?: {
|
|
357
|
+
readonly surfaces?: Readonly<Record<string, ActiveSurface<AppModel> | SurfaceSource<AppModel>>> | undefined;
|
|
358
|
+
}): ReadWhy;
|
|
359
|
+
/**
|
|
360
|
+
* Each change of each read's tag across a recorded history (the Messages
|
|
361
|
+
* `update` handled, each with the Model it left, as Foldkit's devtools
|
|
362
|
+
* records them), with the Message that made it and `why` at the Model it
|
|
363
|
+
* changed to. `regression` marks a read that showed a value and stopped
|
|
364
|
+
* with no reason a reader can see (#234).
|
|
365
|
+
*/
|
|
366
|
+
timeline<Message>(start: AppModel, history: ReadonlyArray<{
|
|
367
|
+
readonly message: Message;
|
|
368
|
+
readonly model: AppModel;
|
|
369
|
+
}>, reads: Readonly<Record<string, Projection<AppModel, RemoteData<unknown>>>>, options?: {
|
|
370
|
+
readonly surfaces?: Readonly<Record<string, ActiveSurface<AppModel> | SurfaceSource<AppModel>>> | undefined;
|
|
371
|
+
}): ReadonlyArray<ReadStep<Message>>;
|
|
372
|
+
/**
|
|
373
|
+
* The rows of a loaded list that a body matches, decoded as the list decodes
|
|
374
|
+
* them — a filter that asks the server nothing.
|
|
375
|
+
*
|
|
376
|
+
* **It filters a list; it does not run a query.** That distinction is what
|
|
377
|
+
* keeps it honest. "Which rows match" would need to know that the list holds
|
|
378
|
+
* every row the body could match, which is predicate containment and is
|
|
379
|
+
* deliberately not built. "Which rows *of this list* match" is decidable from
|
|
380
|
+
* what is already here, and is what a search box over a loaded page actually
|
|
381
|
+
* wants.
|
|
382
|
+
*
|
|
383
|
+
* `complete` says whether the answer is about the whole list: every edge
|
|
384
|
+
* judged, and the connection terminal at both ends. An incomplete answer is
|
|
385
|
+
* not wrong — it is about less than the caller may have meant, which is why
|
|
386
|
+
* it is said rather than left for a view to assume.
|
|
387
|
+
*
|
|
388
|
+
* Creates no connection, so there is nothing new to retain and nothing new to
|
|
389
|
+
* fetch. The server stays authoritative for which rows exist.
|
|
390
|
+
*/
|
|
391
|
+
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>;
|
|
392
|
+
/**
|
|
393
|
+
* Shows operations over the store with no request behind them, as a mutation's
|
|
394
|
+
* `optimistic` ones show while it is in flight: every Selection and view draws
|
|
395
|
+
* them. For a preview of a change nobody has made. They stay until `lift`;
|
|
396
|
+
* showing an id again replaces what it showed. Called from `update`. A read
|
|
397
|
+
* of an entity only overlays show, lacking a field it selects, is `Failed`
|
|
398
|
+
* (`Overlaid`): nothing will fetch that field.
|
|
399
|
+
*/
|
|
400
|
+
overlay(model: AppModel, id: string, optimistic: ReadonlyArray<OptimisticOperation>): AppModel;
|
|
401
|
+
/** Lifts what `overlay` showed under this id. Lifting nothing returns the same Model. */
|
|
402
|
+
lift(model: AppModel, id: string): AppModel;
|
|
403
|
+
/**
|
|
404
|
+
* The ids `overlay` shows now, in the order they are drawn, a later one over
|
|
405
|
+
* an earlier: what a caller that overlays from its own state reconciles
|
|
406
|
+
* against.
|
|
407
|
+
*/
|
|
408
|
+
overlays(model: AppModel): ReadonlyArray<string>;
|
|
409
|
+
/**
|
|
410
|
+
* The edges a connection shows, as its reads draw them: the server's pages
|
|
411
|
+
* with pending edits placed, each inserted row where the body's order puts
|
|
412
|
+
* it (or at the end its overlay names, when it cannot be placed), minus
|
|
413
|
+
* removed edges and tombstones. Takes the `RemoteModel`, so a persistence
|
|
414
|
+
* `snapshot` can store a list as it is shown.
|
|
415
|
+
*/
|
|
416
|
+
visibleItems(remote: RemoteModel, connection: ConnectionIdentity): ReadonlyArray<Edge>;
|
|
417
|
+
/**
|
|
418
|
+
* `Remote.refresh`: marks what `target` reads for this Model as due, for its
|
|
419
|
+
* read entries to refetch. `target` is a projection, a Surface without
|
|
420
|
+
* params, one entry of the active record, or the record itself, whose
|
|
421
|
+
* params come from the Model as they do for `subscriptions`; or a
|
|
422
|
+
* registered query's ref, which invalidates that list whatever its window. With
|
|
423
|
+
* `{ failed: true }` only what failed is asked again: a "Try again".
|
|
424
|
+
*/
|
|
425
|
+
refresh(model: AppModel, target: RefreshTarget<AppModel, QueryName<Queries[number]>>, options?: RefreshOptions): AppModel;
|
|
426
|
+
/** `Remote.forget`: the Model with every server-derived fact gone, for a change of principal. */
|
|
427
|
+
forget(model: AppModel): AppModel;
|
|
428
|
+
/**
|
|
429
|
+
* A read of this domain as an active Surface, for `subscriptions` and
|
|
430
|
+
* `wiring`: `projectionOf` is what it reads for a Model, none while it
|
|
431
|
+
* reads nothing. It belongs to the domain's application, and lists no
|
|
432
|
+
* Messages: it is a requirement, not a sender. A domain made from a raw
|
|
433
|
+
* optic names no application, so this throws for one.
|
|
434
|
+
*/
|
|
435
|
+
active<Value>(name: string, projectionOf: (model: AppModel) => Option.Option<Projection<AppModel, Value>>): ActiveSurface<AppModel, Value>;
|
|
436
|
+
/**
|
|
437
|
+
* The Foldkit Subscription entries for the active record, keyed for
|
|
438
|
+
* `Subscription.make`: a read entry per record entry (`Remote.observe`), a
|
|
439
|
+
* live entry per record entry that reads through `live` (`Remote.live`), and
|
|
440
|
+
* one retain entry (`Remote.retain`). A `Surface.each` family is one record
|
|
441
|
+
* entry whose read unions its parent's requirements with its instances'.
|
|
442
|
+
* Retention is the domain's: the retain entry of every call roots the active
|
|
443
|
+
* Surfaces of every call, so reads split over calls (one per policy) do not
|
|
444
|
+
* collect each other's data. A Surface's params are a function of the Model
|
|
445
|
+
* (`Surface.at`), so what is fetched, subscribed, and retained follows the
|
|
446
|
+
* Model.
|
|
447
|
+
*/
|
|
448
|
+
subscriptions<const Active extends Readonly<Record<string, ActiveEntry<AppModel>>>>(active: Active, options?: SubscriptionsOptions): SubscriptionEntries<AppModel, Active>;
|
|
449
|
+
/** `Remote.plan`: the requirements the store does not satisfy. */
|
|
450
|
+
plan<Value>(model: AppModel, projection: Projection<AppModel, Value>, options?: PlanOptions): ReadonlyArray<Requirement>;
|
|
451
|
+
/** `Remote.meta`: when what a projection shows was last received, and whether it is stale or loading. */
|
|
452
|
+
meta<Value>(model: AppModel, projection: Projection<AppModel, Value>): ReadMeta;
|
|
453
|
+
/** `Remote.storeOf`: the visible store, base under the pending optimistic layers. */
|
|
454
|
+
storeOf(model: AppModel): EntityStore;
|
|
455
|
+
/**
|
|
456
|
+
* `Remote.confirmed`: the same projection read against the server-derived
|
|
457
|
+
* store alone, with every pending optimistic layer and connection overlay
|
|
458
|
+
* left off. What it plans is unchanged — the requirements are the
|
|
459
|
+
* projection's own — so observing it reads exactly what observing the
|
|
460
|
+
* projection reads; only what it *shows* differs.
|
|
461
|
+
*
|
|
462
|
+
* A view usually wants the projection itself, which is the visible read:
|
|
463
|
+
* the optimistic layers are there so a change shows before the server has
|
|
464
|
+
* agreed to it. This is for the reader that must not believe a change until
|
|
465
|
+
* the server has confirmed it, which in practice is an Agent capability
|
|
466
|
+
* reporting that what it was asked to do is done:
|
|
467
|
+
*
|
|
468
|
+
* ```ts
|
|
469
|
+
* Agent.when({
|
|
470
|
+
* projection: Data.confirmed(ProjectPage.model.project),
|
|
471
|
+
* predicate: (project, request) => project.name === request.name,
|
|
472
|
+
* })
|
|
473
|
+
* ```
|
|
474
|
+
*
|
|
475
|
+
* There is deliberately no `visible`: a projection is already the visible
|
|
476
|
+
* read, and a wrapper that only forwards would be a second name for it.
|
|
477
|
+
*/
|
|
478
|
+
confirmed<P extends Projection<AppModel, any>>(projection: P): P;
|
|
479
|
+
/**
|
|
480
|
+
* The plan run through `RemoteClient` and reduced into the Model: the
|
|
481
|
+
* projection's pending queries first, then the fields it lacks (the pages'
|
|
482
|
+
* items included). For SSR, route or hover prefetch, and tests.
|
|
483
|
+
*/
|
|
484
|
+
prefetch<Value>(model: AppModel, projection: Projection<AppModel, Value>, options?: ObserveOptions): Effect.Effect<AppModel, RemoteReadError | RemoteProtocolError | RemoteQueryError | RemoteUnauthenticated, RemoteClient>;
|
|
485
|
+
/**
|
|
486
|
+
* The Model with everything the active Surfaces read, for a render that
|
|
487
|
+
* fetches nothing (SSR, a prerender). Each pass prefetches every Surface
|
|
488
|
+
* that plans a read, over the Model the one before it left, so a Surface
|
|
489
|
+
* active only once another's read has arrived is read in the next pass (or
|
|
490
|
+
* the same one, when it comes later in `active`). It stops at the first
|
|
491
|
+
* pass that plans nothing, and fails with `RemoteUnsatisfied` when
|
|
492
|
+
* `options.passes` run out first. Reads are cache-first: a field already
|
|
493
|
+
* held is not asked again. A server that could not tell who is asking
|
|
494
|
+
* fails it with `RemoteUnauthenticated`, for the host to answer as it
|
|
495
|
+
* answers a lost session.
|
|
496
|
+
*/
|
|
497
|
+
satisfy(model: AppModel, active: Readonly<Record<string, ActiveEntry<AppModel>>>, options?: SatisfyOptions): Effect.Effect<AppModel, RemoteReadError | RemoteProtocolError | RemoteQueryError | RemoteUnauthenticated | RemoteUnsatisfied, RemoteClient>;
|
|
498
|
+
/**
|
|
499
|
+
* `satisfy` from `update`, for a destination the reader has not reached:
|
|
500
|
+
* a hover over a link, or a navigation the app expects. `model` is the
|
|
501
|
+
* Model as it would be there (the route set to the target's); the Command
|
|
502
|
+
* reads what `active` would read in it and yields one `Preloaded`
|
|
503
|
+
* carrying the Messages that wrote it, which reduce into the Model as it is
|
|
504
|
+
* by then. It never fails: a read that fails is one the destination makes
|
|
505
|
+
* again, and what was read before it still arrives.
|
|
506
|
+
*
|
|
507
|
+
* What it reads is kept like any other read until the next change of what
|
|
508
|
+
* is retained, so preload close to the navigation it expects.
|
|
509
|
+
*/
|
|
510
|
+
preload(model: AppModel, active: Readonly<Record<string, ActiveEntry<AppModel>>>, options?: SatisfyOptions): Command<RemoteMessage, never, RemoteClient>;
|
|
511
|
+
/**
|
|
512
|
+
* Starts a registered mutation from `update`: applies `MutationStarted` (with
|
|
513
|
+
* the optimistic operations) to the Model and returns the Command that runs
|
|
514
|
+
* it and yields the settling Message. The request id comes from the model's
|
|
515
|
+
* mutation sequence unless `options.requestId` is given.
|
|
516
|
+
*/
|
|
517
|
+
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>;
|
|
518
|
+
/**
|
|
519
|
+
* What Remote knows of a mutation `mutate` started, by its request id:
|
|
520
|
+
* pending, applied, or failed with the error the server or transport gave.
|
|
521
|
+
*/
|
|
522
|
+
mutation(model: AppModel, requestId: string): MutationStatus;
|
|
523
|
+
/**
|
|
524
|
+
* Why the server refused a mutation, as the value its `Refusal` declares:
|
|
525
|
+
* none while it is pending or applied, when it failed for another reason,
|
|
526
|
+
* or when the refusal does not decode as `mutation`'s.
|
|
527
|
+
*/
|
|
528
|
+
refusal<Refused>(model: AppModel, requestId: string, mutation: MutationDescriptor<string, any, any, Refused>): Option.Option<Refused>;
|
|
529
|
+
/**
|
|
530
|
+
* The writes that failed and are still owed an answer, oldest first, each
|
|
531
|
+
* with its mutation, the input it was started with, and why it failed. Given
|
|
532
|
+
* a mutation, only its writes, with its input type. A write is listed until
|
|
533
|
+
* `retry` sends it again, `dismiss` forgets it, or `forget` changes the
|
|
534
|
+
* principal; nothing drops one on a timer, since that would hide a failure
|
|
535
|
+
* the reader has not seen.
|
|
536
|
+
*/
|
|
537
|
+
failedWrites(model: AppModel): ReadonlyArray<FailedWriteOf<Mutations[number]>>;
|
|
538
|
+
failedWrites<M extends MutationDescriptor<any, any, any, any>>(model: AppModel, mutation: M & Registered<M['name'], MutationName<Mutations[number]>, 'Mutation'>): ReadonlyArray<FailedWrite<M>>;
|
|
539
|
+
/**
|
|
540
|
+
* Sends a failed write again as itself: the same input, request id and
|
|
541
|
+
* operation id (so a server that applied it answers from its record), with
|
|
542
|
+
* its optimistic operations shown again. None unless `failedWrites` lists it.
|
|
543
|
+
* A durable one is queued again, and the outbox sends it.
|
|
544
|
+
*/
|
|
545
|
+
retry(model: AppModel, requestId: string): Option.Option<MutationStarted<AppModel>>;
|
|
546
|
+
/**
|
|
547
|
+
* Forgets a failed write, so `failedWrites` no longer lists it; a durable one,
|
|
548
|
+
* or one the outbox cannot read, goes from its store and every tab. Anything
|
|
549
|
+
* else (a write still waiting, too) returns the same Model.
|
|
550
|
+
*/
|
|
551
|
+
dismiss(model: AppModel, requestId: string): AppModel;
|
|
552
|
+
/**
|
|
553
|
+
* The durable writes not yet settled, every tab's, in the order the outbox
|
|
554
|
+
* sends them: how many wait, how many the server refused, and each one's
|
|
555
|
+
* state, for a "3 changes waiting" line.
|
|
556
|
+
*/
|
|
557
|
+
outboxStatus(model: AppModel): OutboxStatus;
|
|
558
|
+
/**
|
|
559
|
+
* Whether what `active` reads live is arriving: `Reconnecting` from the
|
|
560
|
+
* moment its stream breaks until it resubscribes, which its live entry does
|
|
561
|
+
* on its own, with backoff.
|
|
562
|
+
*/
|
|
563
|
+
liveStatus(model: AppModel, active: ActiveEntry<AppModel>): LiveStatus;
|
|
564
|
+
/** `updateRemote` on the bound slice: reduces one of Remote's Messages, as `RemoteMessage` or as the application's union constructs it. */
|
|
565
|
+
reduce(model: AppModel, message: RemoteMessage | RemoteMessageInput): AppModel;
|
|
566
|
+
/**
|
|
567
|
+
* How this domain joins an assembly: it routes Remote's Messages into
|
|
568
|
+
* `reduce`, brings its Subscriptions and contract, and requires
|
|
569
|
+
* `RemoteClient` from the runtime's resources Layer. One assembly holds at
|
|
570
|
+
* most one Remote wiring: every domain claims the same tags, and routing
|
|
571
|
+
* takes the first claimant. `shared` names the Messages the application's
|
|
572
|
+
* own update hears too.
|
|
573
|
+
*/
|
|
574
|
+
wiring: <const Active extends Readonly<Record<string, ActiveEntry<AppModel>>>, const Shared extends RemoteMessageTag = never>(active: Active, options?: WiringOptions<Shared>) => RemoteWiring<AppModel, Shared>;
|
|
575
|
+
/**
|
|
576
|
+
* Keeps the cache across a reload, as a wiring beside `wiring`: the stored
|
|
577
|
+
* snapshot for `key` is restored (`Hydrated`, with what the store already
|
|
578
|
+
* holds kept over it, so a page resumed from the server wins) whenever the
|
|
579
|
+
* Model is not yet restored from `key`; and the cache is written back when it
|
|
580
|
+
* changes, once its own snapshot is in. Start `init` from its `restore` so
|
|
581
|
+
* the first frame already holds the snapshot. Overlays, optimistic layers,
|
|
582
|
+
* the mutation ledger, live cursors and gaps are never stored. A change of
|
|
583
|
+
* principal should `forget` in `update`, and name another `key`.
|
|
584
|
+
*/
|
|
585
|
+
persistence(options: PersistenceOptions<AppModel>): PersistenceWiring<AppModel>;
|
|
586
|
+
/**
|
|
587
|
+
* Keeps durable writes (`mutate`'s `durable`) across a reload and sends
|
|
588
|
+
* them, as a wiring beside `wiring`: the queue is written to `key` before a
|
|
589
|
+
* write is sent, sent oldest first by one tab (a Web Lock), sent again after
|
|
590
|
+
* a failure that nothing answered with a backoff, and read back by every
|
|
591
|
+
* tab. Start `init` from its `restore`. A change of principal should
|
|
592
|
+
* `forget` in `update`, and name another `key`.
|
|
593
|
+
*/
|
|
594
|
+
outbox(options: OutboxOptions<AppModel>): OutboxWiring<AppModel>;
|
|
595
|
+
/** `Remote.inspect` of the bound slice. */
|
|
596
|
+
inspect(model: AppModel): RemoteInspection;
|
|
597
|
+
}
|
|
598
|
+
/** What `Remote.fold(Data, …).mutate` starts: `Data.mutate`'s result with its Command lifted. */
|
|
599
|
+
export type FoldedMutationStarted<AppModel, ParentMessage> = Omit<MutationStarted<AppModel>, 'command'> & {
|
|
600
|
+
readonly command: Command<ParentMessage, never, RemoteClient>;
|
|
601
|
+
};
|
|
602
|
+
/**
|
|
603
|
+
* A bound domain folded under one of the application's own Message variants,
|
|
604
|
+
* from `Remote.fold`. Calling it reduces a Remote Message into the Model; the
|
|
605
|
+
* members that produce Messages, `fetch`, `mutate`, and `subscriptions`,
|
|
606
|
+
* yield the wrapper Message instead of `RemoteMessage`, with the lift recorded
|
|
607
|
+
* so Story and Scene can resolve a fetch or a mutation by Remote's own answer.
|
|
608
|
+
* Members that only read or write the Model (`get`, `refresh`, `next`,
|
|
609
|
+
* `overlay`, and the rest) stay on the domain itself.
|
|
610
|
+
*/
|
|
611
|
+
export interface RemoteFold<AppModel, ParentMessage, Domain extends RemoteDomain<AppModel, any, any, any, any>> {
|
|
612
|
+
(model: AppModel, message: RemoteMessage | RemoteMessageInput): Update.Return<AppModel, ParentMessage>;
|
|
613
|
+
/** `Data.mutate`, its Command lifted. */
|
|
614
|
+
readonly mutate: (...args: Parameters<Domain['mutate']>) => FoldedMutationStarted<AppModel, ParentMessage>;
|
|
615
|
+
/** `Data.retry`, its Command lifted. */
|
|
616
|
+
readonly retry: (...args: Parameters<Domain['retry']>) => Option.Option<FoldedMutationStarted<AppModel, ParentMessage>>;
|
|
617
|
+
/** `Data.preload`, its Command lifted. */
|
|
618
|
+
readonly preload: (...args: Parameters<Domain['preload']>) => Command<ParentMessage, never, RemoteClient>;
|
|
619
|
+
/** `Data.subscriptions`, every entry lifted to the wrapper Message. */
|
|
620
|
+
readonly subscriptions: <const Active extends Readonly<Record<string, ActiveEntry<AppModel>>>>(active: Active, options?: SubscriptionsOptions) => SubscriptionEntries<AppModel, Active, ParentMessage>;
|
|
621
|
+
}
|
|
622
|
+
/** The application Model a bound domain is over. */
|
|
623
|
+
export type ModelOfDomain<Domain> = Domain extends RemoteDomain<infer AppModel, any, any, any, any> ? AppModel : never;
|
|
624
|
+
/** A projection's connection requirement with the `QueryRef` that runs it. */
|
|
625
|
+
export interface QueryRequirement extends ConnectionRequirement {
|
|
626
|
+
readonly ref: QueryRef<string, unknown>;
|
|
627
|
+
}
|
|
628
|
+
/** A page forward (`first`, `after`) or back (`last`, `before`); mixing the two is a type error. */
|
|
629
|
+
export type QueryWindowOptions = {
|
|
630
|
+
readonly first?: number | undefined;
|
|
631
|
+
readonly after?: string | undefined;
|
|
632
|
+
readonly last?: undefined;
|
|
633
|
+
readonly before?: undefined;
|
|
634
|
+
} | {
|
|
635
|
+
readonly last: number;
|
|
636
|
+
readonly before?: string | undefined;
|
|
637
|
+
readonly first?: undefined;
|
|
638
|
+
readonly after?: undefined;
|
|
639
|
+
};
|
|
640
|
+
export type QueryOptions<Value, Entity extends string, Of extends string = Entity> = {
|
|
641
|
+
/** What to read of each item: a selection of the query's entity (`Of`). */
|
|
642
|
+
readonly select: EntitySelection<Value, Entity> & SelectsEntity<Entity, Of>;
|
|
643
|
+
/**
|
|
644
|
+
* Watch the list live while a Surface reads it: rows that join, change or
|
|
645
|
+
* leave it are streamed (by a live source that watches queries, such as
|
|
646
|
+
* `foldkit-remote-drizzle`'s `pollLive`). Needs `first`.
|
|
647
|
+
*/
|
|
648
|
+
readonly live?: boolean | undefined;
|
|
649
|
+
} & QueryWindowOptions;
|
|
650
|
+
/** A query connection read as a `Page` of selected items; `ref` is the connection with its first window. */
|
|
651
|
+
export interface QueryProjection<AppModel, Value, Name extends string, Input> extends Projection<AppModel, RemoteData<Page<Value>>> {
|
|
652
|
+
readonly ref: QueryRef<Name, Input>;
|
|
653
|
+
/** What it reads of each item, so a filter over the same list decodes identically. */
|
|
654
|
+
readonly selection: Selection<Value, string>;
|
|
655
|
+
}
|
|
656
|
+
/** The input of a query descriptor. */
|
|
657
|
+
export type QueryInput<Q> = Q extends QueryDescriptor<any, infer Input, any> ? Input : never;
|
|
658
|
+
/** The entity a query's connection is over. */
|
|
659
|
+
export type QueryEntity<Q> = Q extends QueryDescriptor<any, any, ConnectionSpec<infer Entity>> ? Entity : string;
|
|
660
|
+
/**
|
|
661
|
+
* When what a projection shows was last received, and whether it is stale
|
|
662
|
+
* or loading. See `Remote.meta`.
|
|
663
|
+
*/
|
|
664
|
+
export interface ReadMeta {
|
|
665
|
+
/** The newest server write among what is shown; none received reads `undefined`. */
|
|
666
|
+
readonly updatedAt: number | undefined;
|
|
667
|
+
/** Any shown field or connection is marked stale. */
|
|
668
|
+
readonly stale: boolean;
|
|
669
|
+
/** Any shown field or connection is in flight. */
|
|
670
|
+
readonly loading: boolean;
|
|
671
|
+
}
|
|
672
|
+
export interface MutateOptions {
|
|
673
|
+
/** What the request changes before the server answers; released when it settles. */
|
|
674
|
+
readonly optimistic?: ReadonlyArray<OptimisticOperation> | undefined;
|
|
675
|
+
/**
|
|
676
|
+
* When the reader acted, in milliseconds since the epoch, as `Remote.now`
|
|
677
|
+
* read it: sent for a time the write sets, which the server takes within
|
|
678
|
+
* its `clockSkew`.
|
|
679
|
+
*/
|
|
680
|
+
readonly now?: number | undefined;
|
|
681
|
+
}
|
|
682
|
+
export interface RetainOptions {
|
|
683
|
+
/** The query connections the application shows, by `QueryRef` or identity. */
|
|
684
|
+
readonly connections?: ReadonlyArray<ConnectionIdentity> | undefined;
|
|
685
|
+
/** How long the roots must be stable before collecting; default none. */
|
|
686
|
+
readonly grace?: Duration.Input | undefined;
|
|
687
|
+
}
|
|
688
|
+
/** How `Remote.observe` and `Remote.prefetch` treat fields the store already holds. */
|
|
689
|
+
export interface ObserveOptions {
|
|
690
|
+
/** Default `RemotePolicy.cacheFirst`. */
|
|
691
|
+
readonly policy?: RemotePolicy | undefined;
|
|
692
|
+
/** The clock a refreshing policy reads; default `Date.now`, read at each use. */
|
|
693
|
+
readonly now?: (() => number) | undefined;
|
|
694
|
+
}
|
|
695
|
+
/** How `Data.satisfy` reads: how many passes it may take, and the clock. */
|
|
696
|
+
export interface SatisfyOptions {
|
|
697
|
+
/** At most this many passes over the Surfaces; default 8. */
|
|
698
|
+
readonly passes?: number | undefined;
|
|
699
|
+
/** The clock the reads are stamped with; default `Date.now`, read at each use. */
|
|
700
|
+
readonly now?: (() => number) | undefined;
|
|
701
|
+
}
|
|
702
|
+
declare const RemoteUnsatisfied_base: Schema.Class<RemoteUnsatisfied, Schema.TaggedStruct<"RemoteUnsatisfied", {
|
|
703
|
+
readonly surfaces: Schema.$Array<Schema.String>;
|
|
704
|
+
readonly passes: Schema.Number;
|
|
705
|
+
}>, import("effect/Cause").YieldableError>;
|
|
706
|
+
/**
|
|
707
|
+
* `Data.satisfy` reached its bound with Surfaces still reading, such as a
|
|
708
|
+
* chain whose every read reveals one more. It names them, so a page that
|
|
709
|
+
* would have rendered them loading fails instead. (A read the server leaves
|
|
710
|
+
* unanswered settles as missing and ends the loop.)
|
|
711
|
+
*/
|
|
712
|
+
export declare class RemoteUnsatisfied extends RemoteUnsatisfied_base {}
|
|
713
|
+
export interface LiveOptions {
|
|
714
|
+
/** The clock `LiveReceived` stamps events with; default `Date.now`, read at each use. */
|
|
715
|
+
readonly now?: (() => number) | undefined;
|
|
716
|
+
/**
|
|
717
|
+
* The first restart's delay after a stream breaks, doubled for each break in
|
|
718
|
+
* a row, with ±20% jitter: Sync's transport policy. Default `50 millis`.
|
|
719
|
+
*/
|
|
720
|
+
readonly retryBase?: Duration.Input | undefined;
|
|
721
|
+
/** The longest a restart waits. Default `5 seconds`. */
|
|
722
|
+
readonly maxRetryDelay?: Duration.Input | undefined;
|
|
723
|
+
}
|
|
724
|
+
/** Declares a Remote domain: its entities, queries, and mutations, plus the submodel. */
|
|
725
|
+
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: {
|
|
726
|
+
readonly entities: Entities;
|
|
727
|
+
readonly queries?: Queries;
|
|
728
|
+
readonly mutations?: Mutations;
|
|
729
|
+
}) => RemoteDescriptor<Entities, Queries, Mutations>;
|
|
730
|
+
/** A query the read entry runs, as its dependencies carry it: plain data Foldkit compares. */
|
|
731
|
+
declare const PlannedQuery: Schema.Struct<{
|
|
732
|
+
readonly identity: Schema.String;
|
|
733
|
+
readonly window: Schema.Struct<{
|
|
734
|
+
readonly first: Schema.optional<Schema.Number>;
|
|
735
|
+
readonly last: Schema.optional<Schema.Number>;
|
|
736
|
+
readonly after: Schema.optional<Schema.String>;
|
|
737
|
+
readonly before: Schema.optional<Schema.String>;
|
|
738
|
+
}>;
|
|
739
|
+
readonly select: Schema.Codec<RelationRequirement, RelationRequirement, never, never>;
|
|
740
|
+
}>;
|
|
741
|
+
/** The dependencies of the read entry: the entity fields to read and the queries to run. */
|
|
742
|
+
export interface ReadDependencies {
|
|
743
|
+
readonly requirements: ReadonlyArray<Requirement>;
|
|
744
|
+
readonly queries: ReadonlyArray<Schema.Schema.Type<typeof PlannedQuery>>;
|
|
745
|
+
/**
|
|
746
|
+
* The highest generation the fields this entry reads were refreshed at: a
|
|
747
|
+
* refresh of any of them restarts the entry, and a refresh of anything else
|
|
748
|
+
* leaves it running.
|
|
749
|
+
*/
|
|
750
|
+
readonly refresh: number;
|
|
751
|
+
/**
|
|
752
|
+
* Under a refreshing policy, when a value the entry holds next ages out and
|
|
753
|
+
* what is due then. Time reaches Remote only as a Message: the entry sleeps
|
|
754
|
+
* until then and emits `RefreshStarted`, which marks the fields stale, and
|
|
755
|
+
* the plan that follows fetches them. A Model that does not change past its
|
|
756
|
+
* `maxAge` is otherwise never looked at again.
|
|
757
|
+
*/
|
|
758
|
+
readonly expires: Deadline | null;
|
|
759
|
+
}
|
|
760
|
+
/**
|
|
761
|
+
* What `Data.refresh` asks again: a projection, a Surface without params, one
|
|
762
|
+
* entry of the active record (a `Surface.at`/`Surface.when` value, a family),
|
|
763
|
+
* the whole record, or one list by its query and input (`Everyone.ref({})`),
|
|
764
|
+
* whatever window reads it.
|
|
765
|
+
*/
|
|
766
|
+
export type RefreshTarget<AppModel, Queries extends string = string> = Projection<AppModel, unknown> | ActiveEntry<AppModel> | Readonly<Record<string, ActiveEntry<AppModel>>> | QueryRef<Queries, any>;
|
|
767
|
+
/** How `Data.refresh` asks again. */
|
|
768
|
+
export interface RefreshOptions {
|
|
769
|
+
/** Only what failed: a "Try again" leaves what loaded as it is. */
|
|
770
|
+
readonly failed?: boolean | undefined;
|
|
771
|
+
}
|
|
772
|
+
export declare const Remote: {
|
|
773
|
+
/** The submodel's schema, the same for every domain; embed it in the application Model. */
|
|
774
|
+
Model: Schema.Codec<RemoteModel, unknown, never, never>;
|
|
775
|
+
/** The submodel's initial value. */
|
|
776
|
+
initial: RemoteModel;
|
|
777
|
+
/**
|
|
778
|
+
* Remote's Message cases for `defineMessageUnion`: spread them into the
|
|
779
|
+
* application's union, and reduce the ones `Remote.reduces` recognizes with
|
|
780
|
+
* `RemoteDomain.reduce`.
|
|
781
|
+
*/
|
|
782
|
+
messages: {
|
|
783
|
+
ReadReceived: {
|
|
784
|
+
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
785
|
+
result: Schema.Struct<{
|
|
786
|
+
readonly entities: Schema.$Array<Schema.Struct<{
|
|
787
|
+
readonly entity: Schema.String;
|
|
788
|
+
readonly id: Schema.String;
|
|
789
|
+
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
790
|
+
}>>;
|
|
791
|
+
readonly settled: Schema.$Array<Schema.Struct<{
|
|
792
|
+
readonly entity: Schema.String;
|
|
793
|
+
readonly id: Schema.String;
|
|
794
|
+
readonly fields: Schema.$Array<Schema.String>;
|
|
795
|
+
}>>;
|
|
796
|
+
}>;
|
|
797
|
+
now: Schema.Number;
|
|
798
|
+
};
|
|
799
|
+
ReadFailed: {
|
|
800
|
+
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
801
|
+
error: Schema.Struct<{
|
|
802
|
+
readonly _tag: Schema.String;
|
|
803
|
+
readonly message: Schema.String;
|
|
804
|
+
readonly refusal: Schema.optional<Schema.Unknown>;
|
|
805
|
+
readonly reason: Schema.optional<Schema.String>;
|
|
806
|
+
}>;
|
|
807
|
+
stream: Schema.optional<Schema.String>;
|
|
808
|
+
};
|
|
809
|
+
RefreshStarted: {
|
|
810
|
+
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
811
|
+
};
|
|
812
|
+
ReadStarted: {
|
|
813
|
+
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
814
|
+
refresh: Schema.optional<Schema.Number>;
|
|
815
|
+
};
|
|
816
|
+
QueryStarted: {
|
|
817
|
+
connections: Schema.$Array<Schema.String>;
|
|
818
|
+
};
|
|
819
|
+
RetentionChanged: {
|
|
820
|
+
roots: Schema.Struct<{
|
|
821
|
+
readonly requirements: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
822
|
+
readonly connections: Schema.$Array<Schema.Struct<{
|
|
823
|
+
readonly identity: Schema.String;
|
|
824
|
+
readonly select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
825
|
+
}>>;
|
|
826
|
+
}>;
|
|
827
|
+
};
|
|
828
|
+
Hydrated: {
|
|
829
|
+
connections: Schema.optional<Schema.Unknown>;
|
|
830
|
+
from: Schema.optional<Schema.String>;
|
|
831
|
+
entities: Schema.Unknown;
|
|
832
|
+
merge: Schema.Union<readonly [Schema.Literal<"replace">, Schema.Literal<"preserve-existing">]>;
|
|
833
|
+
};
|
|
834
|
+
MutationStarted: {
|
|
835
|
+
requestId: Schema.String;
|
|
836
|
+
optimistic: Schema.optional<Schema.$Array<Schema.Unknown>>;
|
|
837
|
+
viewer: Schema.optional<Schema.Struct<{
|
|
838
|
+
readonly entity: Schema.String;
|
|
839
|
+
readonly id: Schema.String;
|
|
840
|
+
}>>;
|
|
841
|
+
write: Schema.optional<Schema.Struct<{
|
|
842
|
+
readonly mutation: Schema.String;
|
|
843
|
+
readonly input: Schema.Unknown;
|
|
844
|
+
readonly keys: Schema.optional<Schema.$Array<Schema.String>>;
|
|
845
|
+
readonly now: Schema.optional<Schema.Number>;
|
|
846
|
+
readonly durable: Schema.optional<Schema.Struct<{
|
|
847
|
+
readonly input: Schema.Unknown;
|
|
848
|
+
readonly shown: Schema.$Array<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
849
|
+
}>>;
|
|
850
|
+
}>>;
|
|
851
|
+
};
|
|
852
|
+
MutationQueued: {
|
|
853
|
+
requestId: Schema.String;
|
|
854
|
+
};
|
|
855
|
+
OutboxRead: {
|
|
856
|
+
key: Schema.String;
|
|
857
|
+
scope: Schema.String;
|
|
858
|
+
session: Schema.optional<Schema.String>;
|
|
859
|
+
entries: Schema.$Array<Schema.Unknown>;
|
|
860
|
+
done: Schema.$Array<Schema.String>;
|
|
861
|
+
unsaved: Schema.optional<Schema.String>;
|
|
862
|
+
};
|
|
863
|
+
OutboxDelayed: {
|
|
864
|
+
requestId: Schema.String;
|
|
865
|
+
attempt: Schema.Number;
|
|
866
|
+
error: Schema.Struct<{
|
|
867
|
+
readonly _tag: Schema.String;
|
|
868
|
+
readonly message: Schema.String;
|
|
869
|
+
readonly refusal: Schema.optional<Schema.Unknown>;
|
|
870
|
+
readonly reason: Schema.optional<Schema.String>;
|
|
871
|
+
}>;
|
|
872
|
+
};
|
|
873
|
+
MutationSucceeded: {
|
|
874
|
+
requestId: Schema.String;
|
|
875
|
+
entities: Schema.$Array<Schema.Struct<{
|
|
876
|
+
readonly entity: Schema.String;
|
|
877
|
+
readonly id: Schema.String;
|
|
878
|
+
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
879
|
+
}>>;
|
|
880
|
+
connections: Schema.optional<Schema.$Array<Schema.Unknown>>;
|
|
881
|
+
deleted: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
882
|
+
readonly entity: Schema.String;
|
|
883
|
+
readonly id: Schema.String;
|
|
884
|
+
}>>>;
|
|
885
|
+
read: Schema.optional<Schema.Struct<{
|
|
886
|
+
readonly requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
887
|
+
readonly result: Schema.Struct<{
|
|
888
|
+
readonly entities: Schema.$Array<Schema.Struct<{
|
|
889
|
+
readonly entity: Schema.String;
|
|
890
|
+
readonly id: Schema.String;
|
|
891
|
+
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
892
|
+
}>>;
|
|
893
|
+
readonly settled: Schema.$Array<Schema.Struct<{
|
|
894
|
+
readonly entity: Schema.String;
|
|
895
|
+
readonly id: Schema.String;
|
|
896
|
+
readonly fields: Schema.$Array<Schema.String>;
|
|
897
|
+
}>>;
|
|
898
|
+
}>;
|
|
899
|
+
}>>;
|
|
900
|
+
now: Schema.Number;
|
|
901
|
+
};
|
|
902
|
+
MutationFailed: {
|
|
903
|
+
requestId: Schema.String;
|
|
904
|
+
error: Schema.Struct<{
|
|
905
|
+
readonly _tag: Schema.String;
|
|
906
|
+
readonly message: Schema.String;
|
|
907
|
+
readonly refusal: Schema.optional<Schema.Unknown>;
|
|
908
|
+
readonly reason: Schema.optional<Schema.String>;
|
|
909
|
+
}>;
|
|
910
|
+
operation: Schema.String;
|
|
911
|
+
};
|
|
912
|
+
OverlayShown: {
|
|
913
|
+
id: Schema.String;
|
|
914
|
+
optimistic: Schema.$Array<Schema.Unknown>;
|
|
915
|
+
};
|
|
916
|
+
OverlayLifted: {
|
|
917
|
+
id: Schema.String;
|
|
918
|
+
};
|
|
919
|
+
WindowGrown: {
|
|
920
|
+
window: Schema.String;
|
|
921
|
+
size: Schema.Number;
|
|
922
|
+
};
|
|
923
|
+
LiveReceived: {
|
|
924
|
+
stream: Schema.String;
|
|
925
|
+
event: Schema.Unknown;
|
|
926
|
+
policy: Schema.optional<Schema.Unknown>;
|
|
927
|
+
now: Schema.Number;
|
|
928
|
+
};
|
|
929
|
+
GapCleared: {
|
|
930
|
+
stream: Schema.String;
|
|
931
|
+
};
|
|
932
|
+
ConnectionMerged: {
|
|
933
|
+
connection: Schema.String;
|
|
934
|
+
page: Schema.Unknown;
|
|
935
|
+
refreshes: Schema.optional<Schema.Boolean>;
|
|
936
|
+
select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
937
|
+
entities: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
938
|
+
readonly entity: Schema.String;
|
|
939
|
+
readonly id: Schema.String;
|
|
940
|
+
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
941
|
+
}>>>;
|
|
942
|
+
settled: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
943
|
+
readonly entity: Schema.String;
|
|
944
|
+
readonly id: Schema.String;
|
|
945
|
+
readonly fields: Schema.$Array<Schema.String>;
|
|
946
|
+
}>>>;
|
|
947
|
+
now: Schema.optional<Schema.Number>;
|
|
948
|
+
};
|
|
949
|
+
ConnectionInvalidated: {
|
|
950
|
+
connection: Schema.String;
|
|
951
|
+
};
|
|
952
|
+
ConnectionRefreshed: {
|
|
953
|
+
connection: Schema.String;
|
|
954
|
+
};
|
|
955
|
+
QueryFailed: {
|
|
956
|
+
connection: Schema.String;
|
|
957
|
+
error: Schema.Struct<{
|
|
958
|
+
readonly _tag: Schema.String;
|
|
959
|
+
readonly message: Schema.String;
|
|
960
|
+
readonly refusal: Schema.optional<Schema.Unknown>;
|
|
961
|
+
readonly reason: Schema.optional<Schema.String>;
|
|
962
|
+
}>;
|
|
963
|
+
};
|
|
964
|
+
Preloaded: {
|
|
965
|
+
messages: Schema.$Array<Schema.suspend<Schema.Codec<RemoteMessage, unknown, never, never>>>;
|
|
966
|
+
};
|
|
967
|
+
CompletedReportDiagnostics: {};
|
|
968
|
+
};
|
|
969
|
+
/** Whether a Message is one of Remote's, by tag. */
|
|
970
|
+
reduces: typeof isRemoteMessage;
|
|
971
|
+
/**
|
|
972
|
+
* Remote's Messages as one Schema, for a wrapper variant in the
|
|
973
|
+
* application's union: `GotRemoteMessage: { message: Remote.Message }`. With
|
|
974
|
+
* a wrapper, `update` matches the application's union exhaustively and
|
|
975
|
+
* `Remote.fold` reduces what arrives inside it.
|
|
976
|
+
*/
|
|
977
|
+
Message: import("foldkit/message").MessageUnion<{
|
|
978
|
+
ReadReceived: {
|
|
979
|
+
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
980
|
+
result: 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
|
+
}>;
|
|
992
|
+
now: Schema.Number;
|
|
993
|
+
};
|
|
994
|
+
ReadFailed: {
|
|
995
|
+
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
996
|
+
error: Schema.Struct<{
|
|
997
|
+
readonly _tag: Schema.String;
|
|
998
|
+
readonly message: Schema.String;
|
|
999
|
+
readonly refusal: Schema.optional<Schema.Unknown>;
|
|
1000
|
+
readonly reason: Schema.optional<Schema.String>;
|
|
1001
|
+
}>;
|
|
1002
|
+
stream: Schema.optional<Schema.String>;
|
|
1003
|
+
};
|
|
1004
|
+
RefreshStarted: {
|
|
1005
|
+
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
1006
|
+
};
|
|
1007
|
+
ReadStarted: {
|
|
1008
|
+
requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
1009
|
+
refresh: Schema.optional<Schema.Number>;
|
|
1010
|
+
};
|
|
1011
|
+
QueryStarted: {
|
|
1012
|
+
connections: Schema.$Array<Schema.String>;
|
|
1013
|
+
};
|
|
1014
|
+
RetentionChanged: {
|
|
1015
|
+
roots: Schema.Struct<{
|
|
1016
|
+
readonly requirements: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
1017
|
+
readonly connections: Schema.$Array<Schema.Struct<{
|
|
1018
|
+
readonly identity: Schema.String;
|
|
1019
|
+
readonly select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
1020
|
+
}>>;
|
|
1021
|
+
}>;
|
|
1022
|
+
};
|
|
1023
|
+
Hydrated: {
|
|
1024
|
+
connections: Schema.optional<Schema.Unknown>;
|
|
1025
|
+
from: Schema.optional<Schema.String>;
|
|
1026
|
+
entities: Schema.Unknown;
|
|
1027
|
+
merge: Schema.Union<readonly [Schema.Literal<"replace">, Schema.Literal<"preserve-existing">]>;
|
|
1028
|
+
};
|
|
1029
|
+
MutationStarted: {
|
|
1030
|
+
requestId: Schema.String;
|
|
1031
|
+
optimistic: Schema.optional<Schema.$Array<Schema.Unknown>>;
|
|
1032
|
+
viewer: Schema.optional<Schema.Struct<{
|
|
1033
|
+
readonly entity: Schema.String;
|
|
1034
|
+
readonly id: Schema.String;
|
|
1035
|
+
}>>;
|
|
1036
|
+
write: Schema.optional<Schema.Struct<{
|
|
1037
|
+
readonly mutation: Schema.String;
|
|
1038
|
+
readonly input: Schema.Unknown;
|
|
1039
|
+
readonly keys: Schema.optional<Schema.$Array<Schema.String>>;
|
|
1040
|
+
readonly now: Schema.optional<Schema.Number>;
|
|
1041
|
+
readonly durable: Schema.optional<Schema.Struct<{
|
|
1042
|
+
readonly input: Schema.Unknown;
|
|
1043
|
+
readonly shown: Schema.$Array<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
1044
|
+
}>>;
|
|
1045
|
+
}>>;
|
|
1046
|
+
};
|
|
1047
|
+
MutationQueued: {
|
|
1048
|
+
requestId: Schema.String;
|
|
1049
|
+
};
|
|
1050
|
+
OutboxRead: {
|
|
1051
|
+
key: Schema.String;
|
|
1052
|
+
scope: Schema.String;
|
|
1053
|
+
session: Schema.optional<Schema.String>;
|
|
1054
|
+
entries: Schema.$Array<Schema.Unknown>;
|
|
1055
|
+
done: Schema.$Array<Schema.String>;
|
|
1056
|
+
unsaved: Schema.optional<Schema.String>;
|
|
1057
|
+
};
|
|
1058
|
+
OutboxDelayed: {
|
|
1059
|
+
requestId: Schema.String;
|
|
1060
|
+
attempt: Schema.Number;
|
|
1061
|
+
error: Schema.Struct<{
|
|
1062
|
+
readonly _tag: Schema.String;
|
|
1063
|
+
readonly message: Schema.String;
|
|
1064
|
+
readonly refusal: Schema.optional<Schema.Unknown>;
|
|
1065
|
+
readonly reason: Schema.optional<Schema.String>;
|
|
1066
|
+
}>;
|
|
1067
|
+
};
|
|
1068
|
+
MutationSucceeded: {
|
|
1069
|
+
requestId: Schema.String;
|
|
1070
|
+
entities: Schema.$Array<Schema.Struct<{
|
|
1071
|
+
readonly entity: Schema.String;
|
|
1072
|
+
readonly id: Schema.String;
|
|
1073
|
+
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
1074
|
+
}>>;
|
|
1075
|
+
connections: Schema.optional<Schema.$Array<Schema.Unknown>>;
|
|
1076
|
+
deleted: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
1077
|
+
readonly entity: Schema.String;
|
|
1078
|
+
readonly id: Schema.String;
|
|
1079
|
+
}>>>;
|
|
1080
|
+
read: Schema.optional<Schema.Struct<{
|
|
1081
|
+
readonly requests: Schema.$Array<Schema.Codec<Requirement, Requirement, never, never>>;
|
|
1082
|
+
readonly result: Schema.Struct<{
|
|
1083
|
+
readonly entities: Schema.$Array<Schema.Struct<{
|
|
1084
|
+
readonly entity: Schema.String;
|
|
1085
|
+
readonly id: Schema.String;
|
|
1086
|
+
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
1087
|
+
}>>;
|
|
1088
|
+
readonly settled: Schema.$Array<Schema.Struct<{
|
|
1089
|
+
readonly entity: Schema.String;
|
|
1090
|
+
readonly id: Schema.String;
|
|
1091
|
+
readonly fields: Schema.$Array<Schema.String>;
|
|
1092
|
+
}>>;
|
|
1093
|
+
}>;
|
|
1094
|
+
}>>;
|
|
1095
|
+
now: Schema.Number;
|
|
1096
|
+
};
|
|
1097
|
+
MutationFailed: {
|
|
1098
|
+
requestId: Schema.String;
|
|
1099
|
+
error: Schema.Struct<{
|
|
1100
|
+
readonly _tag: Schema.String;
|
|
1101
|
+
readonly message: Schema.String;
|
|
1102
|
+
readonly refusal: Schema.optional<Schema.Unknown>;
|
|
1103
|
+
readonly reason: Schema.optional<Schema.String>;
|
|
1104
|
+
}>;
|
|
1105
|
+
operation: Schema.String;
|
|
1106
|
+
};
|
|
1107
|
+
OverlayShown: {
|
|
1108
|
+
id: Schema.String;
|
|
1109
|
+
optimistic: Schema.$Array<Schema.Unknown>;
|
|
1110
|
+
};
|
|
1111
|
+
OverlayLifted: {
|
|
1112
|
+
id: Schema.String;
|
|
1113
|
+
};
|
|
1114
|
+
WindowGrown: {
|
|
1115
|
+
window: Schema.String;
|
|
1116
|
+
size: Schema.Number;
|
|
1117
|
+
};
|
|
1118
|
+
LiveReceived: {
|
|
1119
|
+
stream: Schema.String;
|
|
1120
|
+
event: Schema.Unknown;
|
|
1121
|
+
policy: Schema.optional<Schema.Unknown>;
|
|
1122
|
+
now: Schema.Number;
|
|
1123
|
+
};
|
|
1124
|
+
GapCleared: {
|
|
1125
|
+
stream: Schema.String;
|
|
1126
|
+
};
|
|
1127
|
+
ConnectionMerged: {
|
|
1128
|
+
connection: Schema.String;
|
|
1129
|
+
page: Schema.Unknown;
|
|
1130
|
+
refreshes: Schema.optional<Schema.Boolean>;
|
|
1131
|
+
select: Schema.optional<Schema.Codec<RelationRequirement, RelationRequirement, never, never>>;
|
|
1132
|
+
entities: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
1133
|
+
readonly entity: Schema.String;
|
|
1134
|
+
readonly id: Schema.String;
|
|
1135
|
+
readonly values: Schema.$Record<Schema.String, Schema.Unknown>;
|
|
1136
|
+
}>>>;
|
|
1137
|
+
settled: Schema.optional<Schema.$Array<Schema.Struct<{
|
|
1138
|
+
readonly entity: Schema.String;
|
|
1139
|
+
readonly id: Schema.String;
|
|
1140
|
+
readonly fields: Schema.$Array<Schema.String>;
|
|
1141
|
+
}>>>;
|
|
1142
|
+
now: Schema.optional<Schema.Number>;
|
|
1143
|
+
};
|
|
1144
|
+
ConnectionInvalidated: {
|
|
1145
|
+
connection: Schema.String;
|
|
1146
|
+
};
|
|
1147
|
+
ConnectionRefreshed: {
|
|
1148
|
+
connection: Schema.String;
|
|
1149
|
+
};
|
|
1150
|
+
QueryFailed: {
|
|
1151
|
+
connection: Schema.String;
|
|
1152
|
+
error: Schema.Struct<{
|
|
1153
|
+
readonly _tag: Schema.String;
|
|
1154
|
+
readonly message: Schema.String;
|
|
1155
|
+
readonly refusal: Schema.optional<Schema.Unknown>;
|
|
1156
|
+
readonly reason: Schema.optional<Schema.String>;
|
|
1157
|
+
}>;
|
|
1158
|
+
};
|
|
1159
|
+
Preloaded: {
|
|
1160
|
+
messages: Schema.$Array<Schema.suspend<Schema.Codec<RemoteMessage, unknown, never, never>>>;
|
|
1161
|
+
};
|
|
1162
|
+
CompletedReportDiagnostics: {};
|
|
1163
|
+
}>;
|
|
1164
|
+
/**
|
|
1165
|
+
* A bound domain under one wrapper variant of the application's union, the
|
|
1166
|
+
* same shape Foldkit gives a Submodel: `toParentMessage` wraps Remote's
|
|
1167
|
+
* Messages, the fold reduces them, and its `fetch`, `mutate`, and
|
|
1168
|
+
* `subscriptions` yield the wrapper. Spreading `Remote.messages` and
|
|
1169
|
+
* narrowing with `Remote.reduces` remains the shorter path for an
|
|
1170
|
+
* application whose `update` only reduces.
|
|
1171
|
+
*
|
|
1172
|
+
* @example
|
|
1173
|
+
* ```ts
|
|
1174
|
+
* const Message = defineMessageUnion({ GotRemoteMessage: { message: Remote.Message } })
|
|
1175
|
+
* const foldData = Remote.fold(Data, message => Message.GotRemoteMessage({ message }))
|
|
1176
|
+
*
|
|
1177
|
+
* const update = (model: Model, message: Message): Return =>
|
|
1178
|
+
* Message.match(message, {
|
|
1179
|
+
* GotRemoteMessage: ({ message }) => foldData(model, message),
|
|
1180
|
+
* })
|
|
1181
|
+
* const subscriptions = Subscription.make<Model, Message, RemoteClient>()(() =>
|
|
1182
|
+
* foldData.subscriptions({ page: Surface.at(ProjectPage, …) }),
|
|
1183
|
+
* )
|
|
1184
|
+
* ```
|
|
1185
|
+
*/
|
|
1186
|
+
fold: <Domain extends RemoteDomain<any, any, any, any, any>, ParentMessage>(domain: Domain, toParentMessage: (message: RemoteMessage) => ParentMessage) => RemoteFold<ModelOfDomain<Domain>, ParentMessage, Domain>;
|
|
1187
|
+
/**
|
|
1188
|
+
* A patch of one entity's values, for a mutation's `optimistic` list or an
|
|
1189
|
+
* overlay. Takes a `foldkit-entity` Entity or a Remote descriptor alike, so
|
|
1190
|
+
* the domain you declared once is the one you patch:
|
|
1191
|
+
* `Remote.patch(Project, 'p1', { name: 'Apollo II' })`. Values are the
|
|
1192
|
+
* fields' wire shape, as the server writes them, except a relation, which is
|
|
1193
|
+
* a ref (`owner: Remote.ref(User, 'u1')`), an array of refs, or `null` where
|
|
1194
|
+
* it is optional. A ref key typed by hand, or a ref to another Entity, is
|
|
1195
|
+
* refused, in the type and when the patch is made.
|
|
1196
|
+
*/
|
|
1197
|
+
patch: <E extends EntityLike>(entity: E, id: string, values: PatchValues<FieldsOf<E>>) => EntityPatch<NameOf<E>, FieldsOf<E>>;
|
|
1198
|
+
/**
|
|
1199
|
+
* A deletion of one entity, for a mutation's `optimistic` list or an
|
|
1200
|
+
* overlay: `Remote.tombstone(Post, 'p1')`. Until it settles the row reads
|
|
1201
|
+
* `NotFound` and leaves every list and relation, as an answer's `deleted`
|
|
1202
|
+
* does; a failure brings it back. Keeping it gone is the answer's to say.
|
|
1203
|
+
*/
|
|
1204
|
+
tombstone: <E extends EntityLike>(entity: E, id: string) => PendingDelete;
|
|
1205
|
+
/**
|
|
1206
|
+
* A reference to one entity, for `ConnectionChange` and anything else that
|
|
1207
|
+
* names a row: `Remote.ref(Project, 'p3')`. Either kind of entity, as with
|
|
1208
|
+
* `Remote.patch`.
|
|
1209
|
+
*/
|
|
1210
|
+
ref: <E extends EntityLike>(entity: E, id: string) => EntityRef<NameOf<E>, FieldsOf<E>>;
|
|
1211
|
+
/**
|
|
1212
|
+
* Declares a Remote domain and binds it to its place in the application Model
|
|
1213
|
+
* in one step; the result carries the application-facing operations. The
|
|
1214
|
+
* descriptor alone is `Remote.define`, the binding alone `Remote.at`.
|
|
1215
|
+
*/
|
|
1216
|
+
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: {
|
|
1217
|
+
readonly model: ModelRef<AppModel, Store>;
|
|
1218
|
+
readonly entities: Entities;
|
|
1219
|
+
readonly queries?: Queries;
|
|
1220
|
+
readonly mutations?: Mutations;
|
|
1221
|
+
/**
|
|
1222
|
+
* Checks each prediction against the server's answer, and records a
|
|
1223
|
+
* `PredictionMismatch` in `diagnostics` for each part that disagrees:
|
|
1224
|
+
* `Value`, a field a pending write showed that the answer holds otherwise;
|
|
1225
|
+
* `Placement`, a list placed in an order the server's first page does not
|
|
1226
|
+
* keep (each placed list is fetched too, for its page; a pending edit is
|
|
1227
|
+
* not checked, since the server does not have it yet); `Gap`, a row whose
|
|
1228
|
+
* answer left out fields the client showed while it was pending and the
|
|
1229
|
+
* store does not otherwise hold, so they are read again and the row reads
|
|
1230
|
+
* `Loading` meanwhile. Everything else behaves as without it. For
|
|
1231
|
+
* development and tests.
|
|
1232
|
+
*/
|
|
1233
|
+
readonly verifyPredictions?: boolean | undefined;
|
|
1234
|
+
/**
|
|
1235
|
+
* How the client runs a body's primitive operators when it judges rows it
|
|
1236
|
+
* holds (`Operators`): the kernel's when not given. A body calling one this
|
|
1237
|
+
* table lacks is judged by the server instead, as any row the client cannot
|
|
1238
|
+
* judge is.
|
|
1239
|
+
*/
|
|
1240
|
+
readonly operators?: MemoryOperators | undefined;
|
|
1241
|
+
/**
|
|
1242
|
+
* Who reads, as a row (`Remote.ref(User, model.me)`), or none for a
|
|
1243
|
+
* visitor: whom a declared write predicts each `Derived.exists` for. The
|
|
1244
|
+
* store holds one viewer's values, as it holds one principal's: a change
|
|
1245
|
+
* of viewer is a change of principal, which `Data.forget`s. Without it, an
|
|
1246
|
+
* exists is predicted only where a write takes it away.
|
|
1247
|
+
*/
|
|
1248
|
+
readonly viewer?: ((model: AppModel) => Option.Option<{
|
|
1249
|
+
readonly entity: string;
|
|
1250
|
+
readonly id: string;
|
|
1251
|
+
}>) | undefined;
|
|
1252
|
+
}) => RemoteDomain<AppModel, Store, Entities, Queries, Mutations>;
|
|
1253
|
+
/**
|
|
1254
|
+
* Declares a Remote domain without binding it: its entities, queries, and
|
|
1255
|
+
* mutations, plus the submodel. For a domain reused across applications or
|
|
1256
|
+
* bound in a test; `Remote.make` is the one-step form.
|
|
1257
|
+
*/
|
|
1258
|
+
define: typeof defineRemote;
|
|
1259
|
+
/**
|
|
1260
|
+
* Binds a Remote domain to its store's location in the application Model. The
|
|
1261
|
+
* registered entity names are carried on the returned value, so `Remote.select`
|
|
1262
|
+
* rejects a selection for an entity this domain never declared. `operators`
|
|
1263
|
+
* is the client's table, which a pending computed assignment is predicted by
|
|
1264
|
+
* (`Operators.kernel` when not given), as `Remote.make`'s is.
|
|
1265
|
+
*/
|
|
1266
|
+
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>, options?: {
|
|
1267
|
+
readonly operators?: MemoryOperators | undefined;
|
|
1268
|
+
}) => BoundRemote<AppModel, Store, EntityName<Entities[number]>>;
|
|
1269
|
+
/**
|
|
1270
|
+
* The resume part for this domain, for `foldkit-ssr`'s `SSR.plan({ parts })`:
|
|
1271
|
+
* a server render sends what the plan's active Surfaces read from the store,
|
|
1272
|
+
* each connection with its boundaries and each live cursor with it, and
|
|
1273
|
+
* nothing else. `id` tells two domains in one application apart.
|
|
1274
|
+
*/
|
|
1275
|
+
resume: typeof resumePart;
|
|
1276
|
+
/**
|
|
1277
|
+
* A Projection node that reads a `RemoteData` value out of the store. The id
|
|
1278
|
+
* is supplied by the caller, usually from a Surface's params. The assembled
|
|
1279
|
+
* value is decoded against the Selection, so malformed server data surfaces
|
|
1280
|
+
* as `Failed` instead of being asserted into `Value`. A present value with a
|
|
1281
|
+
* stale field reads as `Refreshing`: an observer is refetching it.
|
|
1282
|
+
*/
|
|
1283
|
+
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>>;
|
|
1284
|
+
/**
|
|
1285
|
+
* When what a projection shows was last received, and whether it is stale
|
|
1286
|
+
* or loading. Pure, so a view can show "updated 5s ago" without I/O.
|
|
1287
|
+
*
|
|
1288
|
+
* `updatedAt` is the newest server write among what is shown, as the
|
|
1289
|
+
* store dates it; `undefined` when nothing shown was received (nothing
|
|
1290
|
+
* loaded, or only an optimistic preview). `stale` is any shown field or
|
|
1291
|
+
* connection marked stale; `loading` is any of them in flight. Optimistic
|
|
1292
|
+
* previews do not date: showing only one reads `updatedAt: undefined`.
|
|
1293
|
+
*/
|
|
1294
|
+
meta: <AppModel, Store extends RemoteModel, Value>(bound: BoundRemote<AppModel, Store>, model: AppModel, projection: Projection<AppModel, Value>) => ReadMeta;
|
|
1295
|
+
/**
|
|
1296
|
+
* The pure plan for a projection against a Model: the requirements its
|
|
1297
|
+
* remote store does not satisfy, under `options` (freshness, force). A
|
|
1298
|
+
* Surface's projection is `surface.projection(params)`.
|
|
1299
|
+
*/
|
|
1300
|
+
plan: <AppModel, Store extends RemoteModel, Value>(bound: BoundRemote<AppModel, Store>, model: AppModel, projection: Projection<AppModel, Value>, options?: PlanOptions) => ReadonlyArray<Requirement>;
|
|
1301
|
+
/**
|
|
1302
|
+
* The queries a projection needs run before its connections read: those the
|
|
1303
|
+
* Model does not hold, or holds stale (every one under `force`).
|
|
1304
|
+
*/
|
|
1305
|
+
planQueries: <AppModel, Store extends RemoteModel, Value>(bound: BoundRemote<AppModel, Store>, model: AppModel, projection: Projection<AppModel, Value>, options?: PlanOptions) => ReadonlyArray<QueryRef<string, unknown>>;
|
|
1306
|
+
/**
|
|
1307
|
+
* The store reads see: the base store under the pending optimistic layers.
|
|
1308
|
+
* One store is shared by every read and plan of a Model whose remote state
|
|
1309
|
+
* has not changed.
|
|
1310
|
+
*/
|
|
1311
|
+
storeOf: <AppModel, Store extends RemoteModel>(bound: BoundRemote<AppModel, Store>, model: AppModel) => EntityStore;
|
|
1312
|
+
/**
|
|
1313
|
+
* The projection read against the server-derived store alone: the same
|
|
1314
|
+
* requirements, planned the same way, with the pending optimistic layers and
|
|
1315
|
+
* connection overlays left off. See the bound `Remote.confirmed`.
|
|
1316
|
+
*/
|
|
1317
|
+
confirmed: <AppModel, Store extends RemoteModel, P extends Projection<AppModel, any>>(bound: BoundRemote<AppModel, Store>, projection: P) => P;
|
|
1318
|
+
/**
|
|
1319
|
+
* Executes the plan against the `RemoteClient` and returns a new store. Used
|
|
1320
|
+
* for SSR route prefetch, hover prefetch, and tests. Never called during render.
|
|
1321
|
+
* `policy` decides what a present field means (default cache-first); `now`
|
|
1322
|
+
* is the clock it reads, so the planner itself stays pure and time-injected.
|
|
1323
|
+
*/
|
|
1324
|
+
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>;
|
|
1325
|
+
/**
|
|
1326
|
+
* Marks what a read requires as due again: a projection, a Surface without
|
|
1327
|
+
* params, one entry of the active record, or the whole record, each entry
|
|
1328
|
+
* resolved for this Model as `subscriptions` resolves it. Called from
|
|
1329
|
+
* `update`: every selected field the store holds reads `Refreshing`, and
|
|
1330
|
+
* every loaded query connection is invalidated. Nothing is fetched here.
|
|
1331
|
+
* The read entries `Data.subscriptions` derives refetch it, because a stale
|
|
1332
|
+
* field or connection is planned again under every policy, so a refresh never
|
|
1333
|
+
* sends a request beside the entry already observing the same data.
|
|
1334
|
+
*
|
|
1335
|
+
* A refreshed connection's page replaces its pages, so items the server removed
|
|
1336
|
+
* or reordered follow it; pages loaded past the first are dropped and paged
|
|
1337
|
+
* again with `next`/`previous`. The read entries restart, so a read or query
|
|
1338
|
+
* sent before the refresh is not applied after it.
|
|
1339
|
+
*
|
|
1340
|
+
* It is also how a failed read is retried: nothing that failed is asked
|
|
1341
|
+
* again on its own, so its read stays `Failed` until this asks. A failed
|
|
1342
|
+
* read with nothing to show reads `Loading` from here, and `Failed` again if
|
|
1343
|
+
* the retry fails. `{ failed: true }` asks again only what failed, which is
|
|
1344
|
+
* what a "Try again" means: what loaded keeps its value and its pages.
|
|
1345
|
+
*
|
|
1346
|
+
* The projection must be observed, which it is while it is on screen. Live
|
|
1347
|
+
* subscriptions are left as they are. For data nothing observes (SSR, tests),
|
|
1348
|
+
* use `Remote.prefetch` with `RemotePolicy.networkOnly`. Refreshing what is
|
|
1349
|
+
* already being refreshed returns the same Model.
|
|
1350
|
+
*/
|
|
1351
|
+
refresh: <AppModel, Store extends RemoteModel>(bound: BoundRemote<AppModel, Store>, model: AppModel, target: RefreshTarget<AppModel>, options?: RefreshOptions) => AppModel;
|
|
1352
|
+
/**
|
|
1353
|
+
* Forgets everything the server told this Model: values, tombstones,
|
|
1354
|
+
* unavailable fields, connections, live cursors, failures. What is known is
|
|
1355
|
+
* known for a principal, and this is the one boundary for a login, a logout
|
|
1356
|
+
* or a switch of organization: called from `update`, it performs no I/O, and
|
|
1357
|
+
* every active Surface's read and live entries restart, so the screen asks
|
|
1358
|
+
* again as whoever the client now is. A read or stream begun before is
|
|
1359
|
+
* interrupted rather than landing after. A mutation in flight is treated as
|
|
1360
|
+
* applied: its answer writes nothing here.
|
|
1361
|
+
*/
|
|
1362
|
+
forget: <AppModel, Store extends RemoteModel>(bound: BoundRemote<AppModel, Store>, model: AppModel) => AppModel;
|
|
1363
|
+
/**
|
|
1364
|
+
* Writes a read result into the store, recording each field's applied window.
|
|
1365
|
+
* `requests` are the planned requirements the result answers.
|
|
1366
|
+
*/
|
|
1367
|
+
writeRead: typeof writeRead;
|
|
1368
|
+
/**
|
|
1369
|
+
* Adapts an Effect RPC client for `RemoteRpc` to `RemoteClient`, so an
|
|
1370
|
+
* application provides the transport's RPC layer instead of writing the
|
|
1371
|
+
* `LiveChange`-to-`LiveEvent` mapping by hand. The client `RpcClient.make`
|
|
1372
|
+
* builds is accepted as it is: when its transport fails (`RpcClientError`),
|
|
1373
|
+
* the call fails with its own Remote error, which the application shows and
|
|
1374
|
+
* retries like any failed read, query, mutation or live stream.
|
|
1375
|
+
*/
|
|
1376
|
+
/**
|
|
1377
|
+
* Remote's client over any way of sending one JSON request and receiving its
|
|
1378
|
+
* answer, for `clientLayer`: a worker, a server in the page. `RemoteServer.answer`
|
|
1379
|
+
* is the other end.
|
|
1380
|
+
*/
|
|
1381
|
+
json: typeof json;
|
|
1382
|
+
/**
|
|
1383
|
+
* Remote's client over HTTP, for `clientLayer`: each call a `POST` of the JSON
|
|
1384
|
+
* request to `url`. `headers` is read per request (a session token, say).
|
|
1385
|
+
*/
|
|
1386
|
+
http: typeof http;
|
|
1387
|
+
/**
|
|
1388
|
+
* Remote's client over HTTP with live, for `clientLayer`: reads, queries,
|
|
1389
|
+
* and mutations as `http` sends them, live requirements as one `POST`
|
|
1390
|
+
* answered with a `text/event-stream` of changes.
|
|
1391
|
+
* `foldkit-remote-server/fetch` is the other end.
|
|
1392
|
+
*/
|
|
1393
|
+
httpWithLive: typeof httpWithLive;
|
|
1394
|
+
clientLayer: <R = never>(client: RemoteRpcClient<R, RpcClientError.RpcClientError | RemoteUnreachable>, options?: CoalesceOptions) => Layer.Layer<RemoteClient, never, R>;
|
|
1395
|
+
/**
|
|
1396
|
+
* Wraps a `RemoteClient` layer so its reads coalesce: requirements issued
|
|
1397
|
+
* together become one batch, and a requirement already in flight is joined.
|
|
1398
|
+
* `Remote.clientLayer` applies this; use it on a hand-written client.
|
|
1399
|
+
*/
|
|
1400
|
+
coalesced: typeof coalescedLayer;
|
|
1401
|
+
/**
|
|
1402
|
+
* A Foldkit Subscription entry that keeps the cache to what the active
|
|
1403
|
+
* Surfaces reach. `projections` are the ones the application observes (the
|
|
1404
|
+
* same it passes to `Remote.observe`), `connections` the query connections
|
|
1405
|
+
* it shows; anything else is collected once the roots have been stable for
|
|
1406
|
+
* `grace`, so a route transition that comes straight back does not thrash.
|
|
1407
|
+
*/
|
|
1408
|
+
retain: <AppModel, Message = RemoteMessage>(projections: ReadonlyArray<Projection<AppModel, unknown>>, toMessage?: (message: RemoteMessage) => Message, options?: RetainOptions) => EntryWithoutKeepAlive<AppModel, Message, RetentionRoots, never>;
|
|
1409
|
+
/**
|
|
1410
|
+
* Runs a `Query` through `RemoteClient`, encoding its input from the ref.
|
|
1411
|
+
* Pair the result with `Remote.queryMessage` to merge the page into the Model.
|
|
1412
|
+
* With `select`, the server also returns the selected fields of the page's
|
|
1413
|
+
* items, so one response populates both the connection and the store.
|
|
1414
|
+
*/
|
|
1415
|
+
query: <Name extends string, Input>(ref: QueryRef<Name, Input>, select?: RelationRequirement | undefined) => Effect.Effect<{
|
|
1416
|
+
readonly edges: readonly {
|
|
1417
|
+
readonly entity: string;
|
|
1418
|
+
readonly id: string;
|
|
1419
|
+
readonly key: string;
|
|
1420
|
+
}[];
|
|
1421
|
+
readonly start: {
|
|
1422
|
+
readonly _tag: "Terminal";
|
|
1423
|
+
} | {
|
|
1424
|
+
readonly _tag: "Cursor";
|
|
1425
|
+
readonly cursor: string;
|
|
1426
|
+
} | {
|
|
1427
|
+
readonly _tag: "Unknown";
|
|
1428
|
+
};
|
|
1429
|
+
readonly end: {
|
|
1430
|
+
readonly _tag: "Terminal";
|
|
1431
|
+
} | {
|
|
1432
|
+
readonly _tag: "Cursor";
|
|
1433
|
+
readonly cursor: string;
|
|
1434
|
+
} | {
|
|
1435
|
+
readonly _tag: "Unknown";
|
|
1436
|
+
};
|
|
1437
|
+
readonly entities?: readonly {
|
|
1438
|
+
readonly entity: string;
|
|
1439
|
+
readonly id: string;
|
|
1440
|
+
readonly values: {
|
|
1441
|
+
readonly [x: string]: unknown;
|
|
1442
|
+
};
|
|
1443
|
+
}[] | undefined;
|
|
1444
|
+
readonly settled?: readonly {
|
|
1445
|
+
readonly entity: string;
|
|
1446
|
+
readonly id: string;
|
|
1447
|
+
readonly fields: readonly string[];
|
|
1448
|
+
}[] | undefined;
|
|
1449
|
+
}, RemoteQueryError | RemoteUnauthenticated, RemoteClient>;
|
|
1450
|
+
/** The `RemoteMessage` that merges a query page into its connection. */
|
|
1451
|
+
queryMessage: <Name extends string, Input>(ref: QueryRef<Name, Input>, result: Schema.Schema.Type<typeof QueryResult>, select?: RelationRequirement | undefined, now?: number | undefined) => RemoteMessage;
|
|
1452
|
+
/** A pure, serializable view of the whole cache. */
|
|
1453
|
+
inspect: typeof inspectRemote;
|
|
1454
|
+
/** A pure, serializable view of one entity, or `undefined` if unknown. */
|
|
1455
|
+
inspectEntity: typeof inspectEntity;
|
|
1456
|
+
/**
|
|
1457
|
+
* Runs a mutation through `RemoteClient`, decoding its typed Output and
|
|
1458
|
+
* returning the result's normalized patches so the caller can reconcile them
|
|
1459
|
+
* through `updateRemote`'s `MutationSucceeded` (or `Remote.mutateInto`).
|
|
1460
|
+
*/
|
|
1461
|
+
mutate: <Name extends string, Input, Output>(mutation: MutationDescriptor<Name, Input, Output, unknown>, input: Input, requestId: string, options?: {
|
|
1462
|
+
readonly keys?: ReadonlyArray<string> | undefined;
|
|
1463
|
+
readonly operation?: string | undefined;
|
|
1464
|
+
readonly shown?: ReadonlyArray<RelationRequirement> | undefined;
|
|
1465
|
+
readonly now?: number | undefined;
|
|
1466
|
+
} | undefined) => Effect.Effect<{
|
|
1467
|
+
output: Output;
|
|
1468
|
+
entities: readonly {
|
|
1469
|
+
readonly entity: string;
|
|
1470
|
+
readonly id: string;
|
|
1471
|
+
readonly values: {
|
|
1472
|
+
readonly [x: string]: unknown;
|
|
1473
|
+
};
|
|
1474
|
+
}[];
|
|
1475
|
+
connections: ConnectionChange[];
|
|
1476
|
+
deleted: readonly {
|
|
1477
|
+
readonly entity: string;
|
|
1478
|
+
readonly id: string;
|
|
1479
|
+
}[];
|
|
1480
|
+
read: {
|
|
1481
|
+
readonly requests: readonly Requirement[];
|
|
1482
|
+
readonly result: {
|
|
1483
|
+
readonly entities: readonly {
|
|
1484
|
+
readonly entity: string;
|
|
1485
|
+
readonly id: string;
|
|
1486
|
+
readonly values: {
|
|
1487
|
+
readonly [x: string]: unknown;
|
|
1488
|
+
};
|
|
1489
|
+
}[];
|
|
1490
|
+
readonly settled: readonly {
|
|
1491
|
+
readonly entity: string;
|
|
1492
|
+
readonly id: string;
|
|
1493
|
+
readonly fields: readonly string[];
|
|
1494
|
+
}[];
|
|
1495
|
+
};
|
|
1496
|
+
} | undefined;
|
|
1497
|
+
}, RemoteForbidden | RemoteMutationError | RemoteUnauthenticated | RemoteUnreachable, RemoteClient>;
|
|
1498
|
+
/**
|
|
1499
|
+
* Reads the clock where the reader acts, for `Data.mutate`'s `now`: a
|
|
1500
|
+
* Command that yields `toMessage(now)`, the time in milliseconds since the
|
|
1501
|
+
* epoch. It reads Effect's `Clock`, so a test pins it, and `Trace.run`
|
|
1502
|
+
* runs it at the trace's time. Chirp's compose box answers a submit with
|
|
1503
|
+
* `Remote.now(now => Message.ClockedPost({ post, now }))`, and
|
|
1504
|
+
* `ClockedPost` starts the write.
|
|
1505
|
+
*/
|
|
1506
|
+
now: <M>(toMessage: (now: number) => M) => {
|
|
1507
|
+
readonly name: 'Remote.now';
|
|
1508
|
+
readonly effect: Effect.Effect<M>;
|
|
1509
|
+
};
|
|
1510
|
+
/**
|
|
1511
|
+
* Runs a mutation and reconciles its patches into a `RemoteModel` in one step,
|
|
1512
|
+
* returning the new model alongside the typed Output. The model-level form of
|
|
1513
|
+
* `MutationStarted` → `RemoteClient.mutate` → `MutationSucceeded`; in an
|
|
1514
|
+
* application the three are `update` (with `optimistic`), a Command, and the
|
|
1515
|
+
* Message the Command returns, so the optimistic operations show meanwhile.
|
|
1516
|
+
*/
|
|
1517
|
+
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<{
|
|
1518
|
+
output: Output;
|
|
1519
|
+
model: AppModel;
|
|
1520
|
+
}, RemoteForbidden | RemoteMutationError | RemoteUnauthenticated | RemoteUnreachable, RemoteClient>;
|
|
1521
|
+
/**
|
|
1522
|
+
* A Foldkit Subscription entry that plans a Surface's missing fields from the
|
|
1523
|
+
* Model and fetches them through `RemoteClient`, emitting a `RemoteMessage`
|
|
1524
|
+
* per outcome. Wrap it in an application Message (`toMessage`) and reduce it
|
|
1525
|
+
* with the domain's `update`. Under a refreshing `policy` the entry first
|
|
1526
|
+
* emits `RefreshStarted`, so the fields being refetched read as `Refreshing`
|
|
1527
|
+
* while the request is pending.
|
|
1528
|
+
*/
|
|
1529
|
+
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>;
|
|
1530
|
+
/**
|
|
1531
|
+
* A Foldkit Subscription entry that consumes the live stream for a Surface's
|
|
1532
|
+
* requirements, emitting a `LiveReceived` per event and a `ReadFailed`
|
|
1533
|
+
* carrying its `stream` when the stream breaks (including
|
|
1534
|
+
* `ResumeUnavailable`). That records a gap on the stream rather than a failed
|
|
1535
|
+
* read, since nothing was being read, and restarts the entry after a
|
|
1536
|
+
* backoff; the restart refetches what it covers. The resume cursor is read
|
|
1537
|
+
* from `RemoteModel.live`, so the application tracks no cursor of its own.
|
|
1538
|
+
*/
|
|
1539
|
+
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>;
|
|
1540
|
+
};
|
|
1541
|
+
export { AnswerRead, AnySchema, BatchRead, Belongs, Boundary, BoundaryCounts, CoalesceOptions, Connection, ConnectionApplied, ConnectionChange, ConnectionChangeSchema, ConnectionIdentity, ConnectionOverlay, ConnectionRequirement, ConnectionRoot, ConnectionSpec, Cursor, Deadline, Denied, DerivedBy, type Diagnostic, Diagnostics, Edge, EdgeRef, Entity, EntityApplied, EntityDescriptor, EntityEntry, EntityKey, EntityLayer, EntityPatch, EntityRef, EntityStore, EntityWrite, ExplainedDependencies, Failures, FieldsFrom, Freshness, IDENTITY_SEPARATOR, Judged, Live, LiveChange, LiveCursor, LiveEdge, LiveEvent, type LiveFetchOptions, LiveInsertion, LiveOutcome, LivePolicy, type LiveRefused, LiveRequirement, LiveState, MAX_FIELDS_PER_REQUEST, MAX_LIVE_QUERIES, MAX_RELATION_DEPTH, MAX_SHOWN_ENTITIES, Matched, MatchingOptions, MergePolicy, Mutate, Mutation, MutationAnswer, MutationDescriptor, MutationRequest, MutationResult, MutationState, MutationStatus, NormalizedEntity, NormalizedPatch, OperationId, OptimisticOperation, OptimisticState, type OutboxItem, OutboxItemState, type OutboxStatus, type OutboxUnreadable, type OutboxUnsaved, Page, PageSize, PatchValues, PendingDelete, PendingPatch, PlacedOrder, PlanFreshness, PlanOptions, type PredictionMismatch, PredictionPart, Query, QueryDescriptor, QueryEdge, QueryExplanation, QueryInputs, QueryRef, QueryRequest, QueryResult, QueryRpc, QueryRun, QueryWindow, RELATION_ALIAS, REMOTE_CACHE_VERSION, REMOTE_PROTOCOL_VERSION, Read, ReadBatch, ReadBatchResult, ReadRequest, type ReadStep, ReadWhy, Reconciled, RefKey, RefPage, RefPageValue, RefParts, RefreshState, Refusal, RefusalOfWrite, RelationAnnotation, RelationEntityAnnotation, RelationKind, RelationRequest, RelationRequirement, RelationShape, RemoteClient, RemoteConnections, RemoteData, type RemoteDiagnostic, RemoteError, RemoteForbidden, RemoteInspection, RemoteJsonAnswer, RemoteJsonClient, RemoteJsonRequest, type RemoteJsonSend, RemoteLiveError, RemoteLiveRefused, RemoteMessage, RemoteMessageInput, RemoteMessageTag, RemoteModel, RemoteMutationError, RemotePersistence, RemotePolicy, RemoteProtocolError, RemoteQueryError, RemoteReadError, RemoteRequirements, type RemoteResumePart, RemoteRpc, RemoteRpcClient, RemoteUnauthenticated, RemoteUnreachable, type ReportDiagnostic, Requirement, ResultOf, Retained, RetentionRoots, type RetryOptions, RowPlace, SchemaOrFields, Segment, Selection, SelectionOf, SelectionValue, SelectionValueOf, SettledFields, ShownBy, ShownSlice, Snapshot, SnapshotOptions, StartedWrite, StreamHealth, TypeOf, Why, WhyTerm, WindowSchema, WireBoundary, type WriteUnheard, addLayer, addOverlay, aliasedField, applyConnectionEvent, applyEntityEvent, askAgain, assemble, beginMutation, beginOptimistic, belongsEncoded, brokenByWrite, classifyLive, clearStale, coalesceQueries, coalesceReads, coalescedLayer, connectionChangeOf, connectionIdentity, connectionsOf, cursor, deadlineOf, departedLimit, derivedOfWrite, dismissQueued, edge, emptyConnection, emptyLiveState, emptyMutationState, emptyOptimistic, emptyRefresh, emptyStore, entityKey, entry, failMutation, failureOf, fieldMark, forbiddenByWrite, forgetFailure, forgetRemote, gc, goneIn, hasField, hasNext, hasPrevious, heldOnlyByRequests, httpWithLive, initialRemoteModel, inspectEntity, inspectRemote, invalidateConnections, isFieldFailed, isFieldStale, isFieldUnavailable, isGapped, isLoading, isLoadingThrough, isQueryLoading, isRefPage, isRemoteMessage, isTombstone, items, liveEventOf, liveFetch, liveHasNext, liveHasPrevious, markStale, matching, merge, mintOperation, missingFields, mutateRemote, mutationStatus, noFailures, onlyOverlaid, optimisticOfWrite, overlaysOf, pageSchema, patchOfWrite, placeIn, plan, plannedStore, predictionOfWrite, pruneOverlays, queryIdentity, reachable, readField, recentRoots, reconcileMutation, refParts, refreshIsInFlight, refreshedAt, refsIn, relationAlias, relationOf, relationShape, remoteDataSchema, remoteError, remoteErrorSchema, remoteMessageCases, remoteMessageSchema, remoteModelSchema, remove, removeLayer, removeOverlay, requirementKey, requirementsOf, resolvedPatches, retentionRootsSchema, schemaOf, segment, setStale, setUnavailable, settleFailure, settleSuccess, settledLater, stableStringify, targetsOf, terminal, tombstone, unavailableOf, unknown, updateRemote, visibleItems, visibleStore, windowGrowthKey, windowKey, withRefreshRequested, writeEntities, writeEntity, writeRead };
|
|
1542
|
+
//# sourceMappingURL=index.d.ts.map
|