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.
Files changed (198) hide show
  1. package/README.md +987 -198
  2. package/dist/answerGaps.d.ts +16 -0
  3. package/dist/answerGaps.d.ts.map +1 -0
  4. package/dist/answerGaps.js +60 -0
  5. package/dist/answerGaps.js.map +1 -0
  6. package/dist/client-B055kQuP.d.ts +110 -0
  7. package/dist/client-B055kQuP.d.ts.map +1 -0
  8. package/dist/client.d.ts +2 -0
  9. package/dist/client.js +142 -0
  10. package/dist/client.js.map +1 -0
  11. package/dist/coalesce-CLAr92Nk.d.ts +34 -0
  12. package/dist/coalesce-CLAr92Nk.d.ts.map +1 -0
  13. package/dist/coalesce.d.ts +2 -0
  14. package/dist/coalesce.js +131 -0
  15. package/dist/coalesce.js.map +1 -0
  16. package/dist/connection-BRyaJy89.d.ts +45 -0
  17. package/dist/connection-BRyaJy89.d.ts.map +1 -0
  18. package/dist/connection.d.ts +2 -0
  19. package/dist/connection.js +170 -0
  20. package/dist/connection.js.map +1 -0
  21. package/dist/data.d.ts +7 -0
  22. package/dist/data.d.ts.map +1 -0
  23. package/dist/data.js +21 -0
  24. package/dist/data.js.map +1 -0
  25. package/dist/diagnostics-DHhVYflV.d.ts +125 -0
  26. package/dist/diagnostics-DHhVYflV.d.ts.map +1 -0
  27. package/dist/diagnostics.d.ts +2 -0
  28. package/dist/diagnostics.js +60 -0
  29. package/dist/diagnostics.js.map +1 -0
  30. package/dist/entity-CgsG5Uel.d.ts +196 -0
  31. package/dist/entity-CgsG5Uel.d.ts.map +1 -0
  32. package/dist/entity-DuDxaa3n.js +279 -0
  33. package/dist/entity-DuDxaa3n.js.map +1 -0
  34. package/dist/entity.d.ts +2 -0
  35. package/dist/entity.js +1 -0
  36. package/dist/held.d.ts +19 -0
  37. package/dist/held.d.ts.map +1 -0
  38. package/dist/held.js +70 -0
  39. package/dist/held.js.map +1 -0
  40. package/dist/impact.d.ts +79 -0
  41. package/dist/impact.d.ts.map +1 -0
  42. package/dist/impact.js +166 -0
  43. package/dist/impact.js.map +1 -0
  44. package/dist/index.d.ts +1542 -0
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +2791 -0
  47. package/dist/index.js.map +1 -0
  48. package/dist/inspect-DtRQGCRP.d.ts +134 -0
  49. package/dist/inspect-DtRQGCRP.d.ts.map +1 -0
  50. package/dist/inspect.d.ts +2 -0
  51. package/dist/inspect.js +33 -0
  52. package/dist/inspect.js.map +1 -0
  53. package/dist/json-DowLl1eB.d.ts +52 -0
  54. package/dist/json-DowLl1eB.d.ts.map +1 -0
  55. package/dist/json.d.ts +2 -0
  56. package/dist/json.js +123 -0
  57. package/dist/json.js.map +1 -0
  58. package/dist/law.d.ts +56 -0
  59. package/dist/law.d.ts.map +1 -0
  60. package/dist/law.js +201 -0
  61. package/dist/law.js.map +1 -0
  62. package/dist/live-BpTzlCnY.d.ts +79 -0
  63. package/dist/live-BpTzlCnY.d.ts.map +1 -0
  64. package/dist/live.d.ts +2 -0
  65. package/dist/live.js +126 -0
  66. package/dist/live.js.map +1 -0
  67. package/dist/matching-DF5F9Us8.d.ts +100 -0
  68. package/dist/matching-DF5F9Us8.d.ts.map +1 -0
  69. package/dist/matching.d.ts +2 -0
  70. package/dist/matching.js +172 -0
  71. package/dist/matching.js.map +1 -0
  72. package/dist/model-B6zk1NMB.d.ts +710 -0
  73. package/dist/model-B6zk1NMB.d.ts.map +1 -0
  74. package/dist/model.d.ts +2 -0
  75. package/dist/model.js +1308 -0
  76. package/dist/model.js.map +1 -0
  77. package/dist/mutation.d.ts +2 -0
  78. package/dist/mutation.js +612 -0
  79. package/dist/mutation.js.map +1 -0
  80. package/dist/optimistic-CECsfNGY.d.ts +523 -0
  81. package/dist/optimistic-CECsfNGY.d.ts.map +1 -0
  82. package/dist/optimistic.d.ts +2 -0
  83. package/dist/optimistic.js +336 -0
  84. package/dist/optimistic.js.map +1 -0
  85. package/dist/outbox-DNuc4kZp.d.ts +259 -0
  86. package/dist/outbox-DNuc4kZp.d.ts.map +1 -0
  87. package/dist/outbox.d.ts +2 -0
  88. package/dist/outbox.js +326 -0
  89. package/dist/outbox.js.map +1 -0
  90. package/dist/patchValues.d.ts +10 -0
  91. package/dist/patchValues.d.ts.map +1 -0
  92. package/dist/patchValues.js +57 -0
  93. package/dist/patchValues.js.map +1 -0
  94. package/dist/persistence-CCMnvg7-.d.ts +114 -0
  95. package/dist/persistence-CCMnvg7-.d.ts.map +1 -0
  96. package/dist/persistence.d.ts +2 -0
  97. package/dist/persistence.js +205 -0
  98. package/dist/persistence.js.map +1 -0
  99. package/dist/placement-jZdsIpmj.d.ts +50 -0
  100. package/dist/placement-jZdsIpmj.d.ts.map +1 -0
  101. package/dist/placement.d.ts +2 -0
  102. package/dist/placement.js +116 -0
  103. package/dist/placement.js.map +1 -0
  104. package/dist/plan-D9cftxC_.d.ts +35 -0
  105. package/dist/plan-D9cftxC_.d.ts.map +1 -0
  106. package/dist/plan.d.ts +2 -0
  107. package/dist/plan.js +100 -0
  108. package/dist/plan.js.map +1 -0
  109. package/dist/policy-DsWHmIAq.d.ts +42 -0
  110. package/dist/policy-DsWHmIAq.d.ts.map +1 -0
  111. package/dist/policy.d.ts +2 -0
  112. package/dist/policy.js +32 -0
  113. package/dist/policy.js.map +1 -0
  114. package/dist/{port.d.mts → port.d.ts} +3 -2
  115. package/dist/port.d.ts.map +1 -0
  116. package/dist/{port.mjs → port.js} +3 -2
  117. package/dist/port.js.map +1 -0
  118. package/dist/query-BuIU93xA.d.ts +141 -0
  119. package/dist/query-BuIU93xA.d.ts.map +1 -0
  120. package/dist/query.d.ts +2 -0
  121. package/dist/query.js +0 -0
  122. package/dist/query.js.map +1 -0
  123. package/dist/record.d.ts +11 -0
  124. package/dist/record.d.ts.map +1 -0
  125. package/dist/record.js +21 -0
  126. package/dist/record.js.map +1 -0
  127. package/dist/relation-BLBGOZom.d.ts +59 -0
  128. package/dist/relation-BLBGOZom.d.ts.map +1 -0
  129. package/dist/relation.d.ts +2 -0
  130. package/dist/relation.js +93 -0
  131. package/dist/relation.js.map +1 -0
  132. package/dist/remoteData-mK1suYi1.d.ts +148 -0
  133. package/dist/remoteData-mK1suYi1.d.ts.map +1 -0
  134. package/dist/remoteData.d.ts +2 -0
  135. package/dist/remoteData.js +179 -0
  136. package/dist/remoteData.js.map +1 -0
  137. package/dist/reporting.d.ts +12 -0
  138. package/dist/reporting.d.ts.map +1 -0
  139. package/dist/reporting.js +45 -0
  140. package/dist/reporting.js.map +1 -0
  141. package/dist/requirement-D57S2LpH.d.ts +64 -0
  142. package/dist/requirement-D57S2LpH.d.ts.map +1 -0
  143. package/dist/requirement.d.ts +2 -0
  144. package/dist/requirement.js +114 -0
  145. package/dist/requirement.js.map +1 -0
  146. package/dist/resume-Ct5R6yli.d.ts +92 -0
  147. package/dist/resume-Ct5R6yli.d.ts.map +1 -0
  148. package/dist/resume.d.ts +2 -0
  149. package/dist/resume.js +222 -0
  150. package/dist/resume.js.map +1 -0
  151. package/dist/retain-BfNTvBRb.d.ts +48 -0
  152. package/dist/retain-BfNTvBRb.d.ts.map +1 -0
  153. package/dist/retain.d.ts +2 -0
  154. package/dist/retain.js +107 -0
  155. package/dist/retain.js.map +1 -0
  156. package/dist/selection.d.ts +2 -0
  157. package/dist/selection.js +1 -0
  158. package/dist/shown.d.ts +20 -0
  159. package/dist/shown.d.ts.map +1 -0
  160. package/dist/shown.js +40 -0
  161. package/dist/shown.js.map +1 -0
  162. package/dist/sse-C7LhdbiQ.d.ts +17 -0
  163. package/dist/sse-C7LhdbiQ.d.ts.map +1 -0
  164. package/dist/sse.d.ts +2 -0
  165. package/dist/sse.js +127 -0
  166. package/dist/sse.js.map +1 -0
  167. package/dist/store-ah2qjcJW.d.ts +100 -0
  168. package/dist/store-ah2qjcJW.d.ts.map +1 -0
  169. package/dist/store.d.ts +2 -0
  170. package/dist/store.js +218 -0
  171. package/dist/store.js.map +1 -0
  172. package/dist/testing.d.ts +133 -0
  173. package/dist/testing.d.ts.map +1 -0
  174. package/dist/testing.js +0 -0
  175. package/dist/testing.js.map +1 -0
  176. package/dist/why-kgp_Wr3z.d.ts +483 -0
  177. package/dist/why-kgp_Wr3z.d.ts.map +1 -0
  178. package/dist/why.d.ts +2 -0
  179. package/dist/why.js +293 -0
  180. package/dist/why.js.map +1 -0
  181. package/dist/whyReasons.d.ts +42 -0
  182. package/dist/whyReasons.d.ts.map +1 -0
  183. package/dist/whyReasons.js +211 -0
  184. package/dist/whyReasons.js.map +1 -0
  185. package/dist/wire-DthPcTM6.d.ts +787 -0
  186. package/dist/wire-DthPcTM6.d.ts.map +1 -0
  187. package/dist/wire.d.ts +2 -0
  188. package/dist/wire.js +329 -0
  189. package/dist/wire.js.map +1 -0
  190. package/package.json +19 -14
  191. package/dist/index-BEvVAL76.d.mts +0 -4097
  192. package/dist/index-BEvVAL76.d.mts.map +0 -1
  193. package/dist/index.d.mts +0 -2
  194. package/dist/index.mjs +0 -1
  195. package/dist/port.d.mts.map +0 -1
  196. package/dist/port.mjs.map +0 -1
  197. package/dist/src-BDqn7Ocr.mjs +0 -6344
  198. package/dist/src-BDqn7Ocr.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutation.js","names":["Rec","DomainWrite","DomainEntity"],"sources":["../src/mutation.ts"],"sourcesContent":["/**\n * Mutation status and idempotent reconciliation.\n *\n * A mutation result is reconciled into the store **at most once per\n * `requestId`**, so a transport retry cannot apply the same change twice. An\n * unknown or already-applied result is a no-op.\n */\nimport { Data, Effect, Match, Option, Record as Rec, Schema } from 'effect'\nimport {\n Entity as DomainEntity,\n Write as DomainWrite,\n type AnyWrite,\n type BoundWrite,\n type Computation,\n type ConditionedWrite,\n type ContextRead,\n Derivation,\n Held,\n type AnyEntity,\n type EntityDerived,\n type Forbids,\n type HeldRow,\n type WriteSurface,\n type ExprContext,\n type Invariant,\n type MemoryOperators,\n type Predict,\n type Write,\n type WriteKind,\n} from 'foldkit-entity'\nimport { holderOf } from './held.js'\nimport type { OptimisticOperation } from './optimistic.js'\nimport { own, put } from './record.js'\nimport { refParts } from './relation.js'\nimport type { RemoteError } from './remoteData.js'\nimport { emptyStore, entityKey, tombstone, writeEntities, type EntityStore } from './store.js'\n\nexport interface NormalizedPatch {\n readonly entity: string\n readonly id: string\n readonly values: Readonly<Record<string, unknown>>\n}\n\n/**\n * A patch a pending request shows, the amounts it moves fields by, and the\n * fields it computes: each worked out, whenever the store is read, over the\n * row as it then is, so a change that reaches the store meanwhile is added\n * to or computed from, not hidden. A computation is data (operators by name),\n * never a descriptor, since a pending patch sits in the Model.\n */\nexport interface PendingPatch extends NormalizedPatch {\n readonly adds?: Readonly<Record<string, number>>\n readonly computes?: Readonly<Record<string, Computation>>\n}\n\n/**\n * A row a pending request deletes: until the request settles it reads\n * `NotFound` and leaves every list and relation, as a settled delete does.\n */\nexport interface PendingDelete {\n readonly _tag: 'Delete'\n readonly entity: string\n readonly id: string\n}\n\n/**\n * What a request writes, as `Data.mutate` started it: enough to list it once it\n * fails, with its input, and to send it again as itself.\n */\nexport interface StartedWrite {\n /** The registered mutation's name. */\n readonly mutation: string\n /** The input as `Data.mutate` was given it, decoded. */\n readonly input: unknown\n readonly keys?: ReadonlyArray<string> | undefined\n /**\n * When the reader acted, as `Data.mutate` was given it: what it predicted\n * `Expr.now` as and sent, and what a retry sends again. None when it was\n * given none, and the server's clock decides.\n */\n readonly now: Option.Option<number>\n /** What it showed until it settled, shown again by a retry. */\n readonly optimistic: ReadonlyArray<OptimisticOperation>\n}\n\nexport interface MutationState {\n readonly pending: ReadonlySet<string>\n readonly applied: ReadonlySet<string>\n readonly failed: ReadonlySet<string>\n /** Why each request in `failed` failed, kept exactly as long as `failed` keeps its id. */\n readonly errors: ReadonlyMap<string, RemoteError>\n /**\n * The operation id each request in `failed` was sent with, kept as `errors`\n * is: a retry of that request id sends it again, so a server recognises it.\n */\n readonly operations: ReadonlyMap<string, string>\n /**\n * What each pending or failed request writes. A request settled as applied,\n * or dismissed, takes its write with it.\n */\n readonly writes: ReadonlyMap<string, StartedWrite>\n /**\n * How many mutations this model has started. A bound domain takes its next\n * request id from here, so `update` stays pure and the id exists before the\n * Command runs.\n */\n readonly sequence: number\n /** Where each pending request falls in `sequence`: the order its answer is applied in. */\n readonly order: ReadonlyMap<string, number>\n /**\n * The order of the last answer that wrote each row field (`entity:id\\0field`)\n * or deleted each row (`entity:id`), kept only while a request started\n * before it is pending, since only that request's answer is compared with it.\n */\n readonly settled: ReadonlyMap<string, number>\n}\n\nexport const emptyMutationState: MutationState = {\n pending: new Set(),\n applied: new Set(),\n failed: new Set(),\n errors: new Map(),\n operations: new Map(),\n writes: new Map(),\n sequence: 0,\n order: new Map(),\n settled: new Map(),\n}\n\n/**\n * How many settled request ids a mutation state retains. A retry settles well\n * inside this window, so bounding the ledger stops a long-lived application\n * from growing it without limit; a retry older than the window would re-apply\n * its entities.\n */\nconst MUTATION_ID_WINDOW = 1024\n\n/** Records `id` as most recent, evicting the oldest once the window is full. */\nconst remember = (ids: ReadonlySet<string>, id: string): ReadonlySet<string> => {\n const next = new Set(ids)\n // Re-inserting an existing id moves it to the most-recent end.\n next.delete(id)\n next.add(id)\n if (next.size <= MUTATION_ID_WINDOW) return next\n return new Set([...next].slice(next.size - MUTATION_ID_WINDOW))\n}\n\nexport const beginMutation = (\n state: MutationState,\n requestId: string,\n write?: StartedWrite,\n): MutationState => ({\n ...state,\n pending: new Set([...state.pending, requestId]),\n writes: write === undefined ? state.writes : new Map([...state.writes, [requestId, write]]),\n sequence: state.sequence + 1,\n order: new Map([...state.order, [requestId, state.sequence + 1]]),\n})\n\nexport const failMutation = (\n state: MutationState,\n requestId: string,\n error: RemoteError,\n operation: string,\n): MutationState => {\n // Only a request in flight can fail: a repeated failure, one after the\n // request applied or was dismissed, or one `forget` settled, changes nothing.\n if (!state.pending.has(requestId)) return state\n const pending = new Set(state.pending)\n pending.delete(requestId)\n const failed = remember(state.failed, requestId)\n const errors = new Map([...state.errors, [requestId, error] as const])\n const operations = new Map([...state.operations, [requestId, operation] as const])\n const writes = new Map(state.writes)\n // `failed` is a bounded window; an error, an operation or a write outlives its id by nothing.\n for (const id of errors.keys()) if (!failed.has(id)) errors.delete(id)\n for (const id of operations.keys()) if (!failed.has(id)) operations.delete(id)\n for (const id of writes.keys()) if (!failed.has(id) && !pending.has(id)) writes.delete(id)\n return { ...state, pending, failed, errors, operations, writes, ...ordered(state, requestId, []) }\n}\n\n/**\n * `order` without a request that settled, and `settled` with what its answer\n * wrote (`marks`), each kept only while a request started before it is pending.\n */\nconst ordered = (\n state: MutationState,\n requestId: string,\n marks: ReadonlyArray<string>,\n): Pick<MutationState, 'order' | 'settled'> => {\n const at = state.order.get(requestId)\n const order = new Map(state.order)\n order.delete(requestId)\n const earliest = Math.min(...order.values())\n const settled = new Map<string, number>()\n for (const [mark, by] of state.settled) if (by > earliest) settled.set(mark, by)\n if (at !== undefined && at > earliest) for (const mark of marks) settled.set(mark, at)\n return { order, settled }\n}\n\n/** The ledger with a request's failure forgotten: its id, error, operation and write. */\nexport const forgetFailure = (state: MutationState, requestId: string): MutationState => {\n const without = <V>(map: ReadonlyMap<string, V>): ReadonlyMap<string, V> => {\n if (!map.has(requestId)) return map\n const next = new Map(map)\n next.delete(requestId)\n return next\n }\n return {\n ...state,\n failed: state.failed.has(requestId)\n ? new Set([...state.failed].filter(id => id !== requestId))\n : state.failed,\n errors: without(state.errors),\n operations: without(state.operations),\n writes: without(state.writes),\n }\n}\n\n/** What Remote knows of one mutation request, by the id `mutate` returned. */\nexport type MutationStatus =\n /** Never started here, or settled so long ago its id has left the window. */\n | { readonly _tag: 'Unknown' }\n | { readonly _tag: 'Pending' }\n | { readonly _tag: 'Applied' }\n | { readonly _tag: 'Failed'; readonly error: RemoteError }\n\nexport const mutationStatus = (state: MutationState, requestId: string): MutationStatus => {\n // A retry reuses its request id, so the latest outcome wins: in flight, then\n // applied (a request cannot fail once applied), then the failure it last had.\n if (state.pending.has(requestId)) return { _tag: 'Pending' }\n if (state.applied.has(requestId)) return { _tag: 'Applied' }\n const error = state.errors.get(requestId)\n return error === undefined ? { _tag: 'Unknown' } : { _tag: 'Failed', error }\n}\n\nexport interface Reconciled {\n readonly store: EntityStore\n readonly state: MutationState\n}\n\n/** What a settled mutation wrote, as `MutationSucceeded` carries it. */\nexport interface MutationAnswer {\n readonly entities: ReadonlyArray<NormalizedPatch>\n /** Entities the mutation deleted; each is tombstoned. */\n readonly deleted?: ReadonlyArray<{ readonly entity: string; readonly id: string }> | undefined\n /** Injected clock reading of the answer, which dates what it writes. */\n readonly now: number\n}\n\n/**\n * What requests started after `requestId` already settled, which its answer\n * leaves alone. The server applied requests in the order they started, so a\n * later one's answer is newer: `newer` holds of a field it wrote (its mark)\n * and of a row it deleted (its key), `rewritten` of a row it wrote any field\n * of. An answer of a request no longer pending (after `forget`, or a failure)\n * has no order, and nothing is newer than it.\n */\nexport const settledLater = (\n state: MutationState,\n requestId: string,\n): {\n readonly newer: (mark: string) => boolean\n readonly rewritten: (key: string) => boolean\n} => {\n const at = state.order.get(requestId) ?? Infinity\n return {\n newer: mark => (state.settled.get(mark) ?? -Infinity) > at,\n rewritten: key =>\n [...state.settled].some(([mark, by]) => by > at && mark.startsWith(`${key}\\u0000`)),\n }\n}\n\n/**\n * Applies a mutation result once and marks the request settled. A second call\n * with the same `requestId` (a retry, or a live event describing the same change)\n * does not re-apply the entities, but still clears `pending`.\n */\nexport const reconcileMutation = (\n store: EntityStore,\n state: MutationState,\n requestId: string,\n answer: MutationAnswer,\n): Reconciled => {\n const repeated = state.applied.has(requestId)\n if (repeated && !state.pending.has(requestId) && !state.failed.has(requestId))\n return { store, state }\n const { newer, rewritten } = settledLater(state, requestId)\n const writes = repeated\n ? []\n : answer.entities.flatMap(entity => {\n const key = entityKey(entity.entity, entity.id)\n if (newer(key)) return []\n const values = Object.fromEntries(\n Object.entries(entity.values).filter(([field]) => !newer(`${key}\\u0000${field}`)),\n )\n return Object.keys(values).length === 0 ? [] : [{ key, values }]\n })\n const deleted = repeated\n ? []\n : (answer.deleted ?? [])\n .map(gone => entityKey(gone.entity, gone.id))\n .filter(key => !rewritten(key))\n // Patches first, then deletions: a mutation that names an entity both ways has deleted it.\n const next = deleted.reduce(tombstone, writeEntities(store, writes, answer.now))\n const applied = remember(state.applied, requestId)\n const pending = new Set(state.pending)\n pending.delete(requestId)\n const marks = [\n ...writes.flatMap(write =>\n Object.keys(write.values).map(field => `${write.key}\\u0000${field}`),\n ),\n ...deleted,\n ]\n // A retry that applies is no longer a failure to list.\n return {\n store: next,\n state: {\n ...forgetFailure(state, requestId),\n applied,\n pending,\n ...ordered(state, requestId, marks),\n },\n }\n}\n\n/** A mutation an application declares: its name and input/output codecs. */\nexport interface MutationDescriptor<Name extends string, Input, Output, Refused = unknown> {\n readonly name: Name\n readonly Input: Schema.Codec<Input>\n readonly Output: Schema.Codec<Output>\n /**\n * What the server may refuse the mutation with, as a value a client can\n * match on rather than a message to parse: `Schema.Never` when it declares\n * none.\n */\n readonly Refusal: Schema.Codec<Refused, unknown>\n /**\n * What the mutation writes, when it was declared as a `Write`: the optimistic\n * patch a client shows, and what a server can run without a handler.\n */\n readonly write?: AnyWrite | undefined\n}\n\nconst conflict = Schema.TaggedStruct('Conflict', {})\nconst unmet = Schema.TaggedStruct('Unmet', {})\n/**\n * Another row already holds the id an insert names: its Entity and that id,\n * both the caller's own, and nothing of the row, which may be hidden from them.\n */\nconst taken = Schema.TaggedStruct('Taken', { entity: Schema.String, id: Schema.String })\n/**\n * The row the write would leave breaks one of its Entity's invariants: which\n * one (its Entity and its id, since an id is unique only within one), what to\n * tell the author, and the fields to show it beside. None and empty when the\n * invariant reads a member hidden from whoever asked.\n */\nconst invalid = Schema.TaggedStruct('Invalid', {\n entity: Schema.OptionFromOptionalNullOr(Schema.String),\n rule: Schema.OptionFromNullOr(Schema.String),\n message: Schema.String,\n path: Schema.Array(Schema.String),\n})\nconst conflictOrInvalid = Schema.Union([conflict, invalid])\nconst conflictUnmetOrInvalid = Schema.Union([conflict, unmet, invalid])\nconst takenOrInvalid = Schema.Union([taken, invalid])\n/** What the constructors typed a write by: its kind, and whether it holds a `when`. */\nconst refusalOfWrite = (write: AnyWrite) => {\n const moved = () => (Option.isSome(write.when) ? conflictUnmetOrInvalid : conflictOrInvalid)\n return Match.value(write).pipe(\n Match.tagsExhaustive({\n Insert: (): Schema.Top => takenOrInvalid,\n Update: moved,\n Delete: moved,\n }),\n )\n}\nconst anyField = Schema.TaggedStruct('Field', { key: Schema.String, reason: Schema.Unknown })\n\n/** Refusals a form or an editor knows how to show. */\nexport const Refusal = {\n /** One input key was refused, for `reason`, which a form shows beside that key. */\n field: <const Key extends string, Reason extends Schema.Top>(key: Key, reason: Reason) =>\n Schema.TaggedStruct('Field', { key: Schema.Literal(key), reason }),\n /** The row moved on since the client read it; the author decides what wins. */\n conflict,\n /** The row does not hold what the write's `when` asks of it, where it would commit. */\n unmet,\n /** The id an insert names is taken: another create made it, or a retry the server could not tell. */\n taken,\n /** The row the write would leave breaks an invariant of its Entity. */\n invalid,\n /** Whether a refusal, of whatever mutation, is a `Refusal.field`. */\n isField: Schema.is(anyField),\n /** Whether a refusal, of whatever mutation, is `Refusal.conflict`. */\n isConflict: Schema.is(conflict),\n /** Whether a refusal, of whatever mutation, is `Refusal.unmet`. */\n isUnmet: Schema.is(unmet),\n /** Whether a refusal, of whatever mutation, is `Refusal.taken`. */\n isTaken: Schema.is(taken),\n /** Whether a refusal, of whatever mutation, is `Refusal.invalid`. */\n isInvalid: Schema.is(invalid),\n /**\n * Whether a refusal is `Refusal.invalid` naming this invariant, by its\n * Entity and its id: the declaration `Entity.invariant` returned, once\n * attached, or one `Entity.invariants` reads. An invariant over a member\n * hidden from the asker names none, so it matches nothing.\n */\n isInvalidBy: (refusal: unknown, invariant: Pick<Invariant, 'entity' | 'id'>): boolean =>\n Schema.is(invalid)(refusal) &&\n Option.contains(refusal.entity, invariant.entity) &&\n Option.contains(refusal.rule, invariant.id),\n}\n\ntype KindOf<W> = W extends { readonly _tag: infer Kind extends WriteKind } ? Kind : WriteKind\n\n/**\n * What a declared write may be refused with: an insert as taken, an update or\n * a delete as a conflict (unmet too, when it has a `when`), and every one as\n * invalid, since the server's Entity may hold invariants the client's does\n * not show. A write whose kind its type leaves open may be refused as any.\n */\nexport type RefusalOfWrite<W> =\n | ('Insert' extends KindOf<W> ? typeof taken.Type : never)\n | ([Exclude<KindOf<W>, 'Insert'>] extends [never]\n ? never\n : W extends ConditionedWrite<any, any>\n ? typeof conflict.Type | typeof unmet.Type\n : typeof conflict.Type)\n | typeof invalid.Type\n\n/** A codec, or the fields of a `Schema.Struct` where one is expected. */\nexport type SchemaOrFields = Schema.Codec<any, any, any, any> | Schema.Struct.Fields\n\n/** The decoded type of a codec, or of the Struct the fields describe. */\nexport type TypeOf<S extends SchemaOrFields> =\n S extends Schema.Codec<infer T, any, any, any>\n ? T\n : S extends Schema.Struct.Fields\n ? Schema.Struct.Type<S>\n : never\n\n/** The codec itself, or a `Schema.Struct` over the fields. */\nexport const schemaOf = <S extends SchemaOrFields>(shape: S): Schema.Codec<TypeOf<S>> =>\n (Schema.isSchema(shape) ? shape : Schema.Struct(shape as Schema.Struct.Fields)) as Schema.Codec<\n TypeOf<S>\n >\n\n/**\n * A bound write as the store patches it: its fields as they are, and each\n * relation it points as the ref key the store holds (`'User:u1'`), or null.\n */\nexport const patchOfWrite = (bound: BoundWrite): NormalizedPatch => ({\n entity: bound.entity,\n id: bound.id,\n values: {\n ...bound.values,\n ...Rec.map(bound.links, link =>\n Option.match(link, { onNone: () => null, onSome: ref => entityKey(ref.entity, ref.id) }),\n ),\n },\n})\n\n/**\n * One member of a row as `store` holds it, for a path from the viewer: a row\n * known gone reaches no row (null), and a row or a field never read is unheld.\n */\nconst heldIn =\n (store: EntityStore): ContextRead<never, never> =>\n (row, key) => {\n const entry = store[entityKey(row.entity, row.id)]\n if (entry === undefined)\n return Effect.succeed(Held.unheld(`${row.entity} ${row.id} is not held`))\n if (entry.tombstone) return Effect.succeed(Held.of(null))\n return Effect.succeed(\n entry.present.has(key)\n ? Held.of(entry.values[key])\n : Held.unheld(`${row.entity}.${key} of ${row.id} is not held`),\n )\n }\n\n/**\n * A write bound to its input, with what its Entity sets from the context\n * (`Entity.sets`) as `context` gives it: who asks (`Remote.make`'s viewer),\n * what their row holds (read from `store`), and when the reader acted\n * (`Data.mutate`'s `now`). A member with no value to give is left out of the\n * prediction, and the answer brings it.\n */\nconst contextBound = (\n write: AnyWrite,\n input: unknown,\n keys: ReadonlyArray<string> | undefined,\n context: ExprContext,\n store: EntityStore,\n): BoundWrite => {\n const bound = DomainWrite.bind(write, input as never, keys)\n const set = Effect.runSync(DomainWrite.contextValues(write, context, heldIn(store)))\n return {\n ...bound,\n values: { ...bound.values, ...set.values },\n links: { ...bound.links, ...set.links },\n }\n}\n\nconst nobody: ExprContext = { viewer: Option.none(), now: Option.none() }\n\n/**\n * What a declared write shows before the server answers: an update's or an\n * insert's row as a patch (an update's only for the keys named, when some\n * are), and an update's increments and computed fields, worked out over the\n * row the store holds when it is read. A delete shows its row deleted. What\n * the context sets is filled from `context` and `store`, where it can be.\n */\nexport const optimisticOfWrite = (\n write: AnyWrite,\n input: unknown,\n keys: ReadonlyArray<string> | undefined,\n context: ExprContext = nobody,\n store: EntityStore = emptyStore,\n): ReadonlyArray<PendingPatch | PendingDelete> =>\n Match.value(write).pipe(\n Match.tagsExhaustive({\n Update: () => {\n const bound = contextBound(write, input, keys, context, store)\n const patch = patchOfWrite(bound)\n return [\n {\n ...patch,\n ...(Object.keys(bound.increments).length === 0 ? {} : { adds: bound.increments }),\n ...(Object.keys(bound.assignments).length === 0 ? {} : { computes: bound.assignments }),\n },\n ]\n },\n // A new row is read like any other, so it carries its own id.\n Insert: () => {\n const patch = patchOfWrite(contextBound(write, input, undefined, context, store))\n return [{ ...patch, values: { id: patch.id, ...patch.values } }]\n },\n Delete: (): ReadonlyArray<PendingDelete> => {\n const { entity, id } = DomainWrite.bind(write, input as never)\n return [{ _tag: 'Delete', entity, id }]\n },\n }),\n )\n\n/**\n * A member a registered Entity derives over a relation of another, under the\n * pointing Entity: `Post.likeCount` (`Derived.count(Like.relations.post)`) is\n * `Count { relation: 'post', owner: 'Post', field: 'likeCount' }`, and\n * `Post.liked` (`Derived.exists(Like.relations.post, { viewer: Like.relations.user })`)\n * is `Exists { relation: 'post', viewer: 'user', owner: 'Post', field: 'liked' }`.\n */\nexport type DerivedBy = Data.TaggedEnum<{\n Count: { readonly relation: string; readonly owner: string; readonly field: string }\n Exists: {\n readonly relation: string\n readonly viewer: string\n readonly owner: string\n readonly field: string\n }\n}>\nexport const DerivedBy = Data.taggedEnum<DerivedBy>()\ntype ExistsBy = Extract<DerivedBy, { readonly _tag: 'Exists' }>\n\n/**\n * The derived members a declared write moves, as pending patches of the rows\n * its row points at. A count: an insert adds one where it points, a delete\n * takes one away where the row pointed, and a relink does both. An exists:\n * a row now pointing here and at `viewer` is found (its id), and a row the\n * store shows as found by this one is no longer, once the write deletes it or\n * points it elsewhere.\n *\n * Where the row pointed before is read from `store`: the row as held, or,\n * when the store holds an exists found by this row, the row it is found on\n * and the viewer. When neither says, nothing is predicted and the answer\n * decides. A member is moved only on a row that `store` holds it on.\n */\nexport const derivedOfWrite = (\n write: AnyWrite,\n input: unknown,\n keys: ReadonlyArray<string> | undefined,\n derived: ReadonlyArray<DerivedBy>,\n store: EntityStore,\n context: ExprContext,\n): ReadonlyArray<PendingPatch> => {\n if (derived.length === 0) return []\n // A link the context sets (whoever asks) moves what it points at as an input's would.\n const bound = contextBound(\n write,\n input,\n write._tag === 'Update' ? keys : undefined,\n context,\n store,\n )\n const row = store[entityKey(bound.entity, bound.id)]\n const held = row === undefined || row.tombstone ? undefined : row\n const viewerKey = Option.map(context.viewer, ref => entityKey(ref.entity, ref.id))\n /** What a live row holds in `field`, as the store has it; none for a row gone or not held. */\n const holding = (key: string, field: string): Option.Option<unknown> =>\n Option.flatMap(Option.fromUndefinedOr(store[key]), entry =>\n entry.tombstone ? Option.none() : Option.some(entry.values[field]),\n )\n // The rows each exists shows as found by this row: a new row is found on none yet.\n const found = new Map<ExistsBy, ReadonlyArray<string>>()\n if (write._tag !== 'Insert')\n for (const member of derived.filter(DerivedBy.$is('Exists')))\n found.set(\n member,\n Object.keys(store).filter(\n key =>\n key.startsWith(`${member.owner}:`) &&\n Option.contains(holding(key, member.field), bound.id),\n ),\n )\n // Where the row points through `relation`: a ref key, null for nowhere, none when unknown.\n const before = (relation: string): Option.Option<unknown> => {\n if (held !== undefined && held.present.has(relation)) return Option.some(held.values[relation])\n for (const [member, rows] of found) {\n if (rows.length === 0) continue\n if (member.relation === relation) return Option.some(rows[0])\n if (member.viewer === relation && Option.isSome(viewerKey)) return viewerKey\n }\n // A row not there points nowhere, unless an update or a delete expected one.\n return write._tag === 'Insert' ? Option.some(null) : Option.none()\n }\n const patched = patchOfWrite(bound).values\n const after = (relation: string): Option.Option<unknown> =>\n Match.value(write).pipe(\n Match.tagsExhaustive({\n Delete: () => Option.some<unknown>(null),\n Insert: () => Option.some(Object.hasOwn(bound.links, relation) ? patched[relation] : null),\n Update: () =>\n Object.hasOwn(bound.links, relation) ? Option.some(patched[relation]) : before(relation),\n }),\n )\n const moves = new Map<\n string,\n { owner: string; values: Record<string, unknown>; adds: Record<string, number> }\n >()\n const at = (ref: string, owner: string) => {\n const move = moves.get(ref) ?? { owner, values: {}, adds: {} }\n moves.set(ref, move)\n return move\n }\n const count = (ref: unknown, owner: string, field: string, by: number): void => {\n if (typeof ref !== 'string') return\n if (!Option.exists(holding(ref, field), value => typeof value === 'number')) return\n const move = at(ref, owner)\n put(move.adds, field, (own(move.adds, field) ?? 0) + by)\n }\n for (const member of derived)\n DerivedBy.$match(member, {\n Count: ({ relation, owner, field }) => {\n const from = before(relation)\n const to = after(relation)\n if (Option.isNone(from) || Option.isNone(to) || from.value === to.value) return\n count(from.value, owner, field, -1)\n count(to.value, owner, field, 1)\n },\n Exists: exists => {\n const { relation, viewer: by, owner, field } = exists\n const pointed = after(relation)\n // Whether the row points at the viewer after the write: none when either is unknown.\n const viewing = Option.flatMap(after(by), ref => Option.map(viewerKey, key => ref === key))\n for (const ref of found.get(exists) ?? []) {\n // A delete points it nowhere, so it leaves every row it was found on.\n if (Option.exists(pointed, to => to !== ref) || Option.contains(viewing, false))\n put(at(ref, owner).values, field, null)\n }\n if (!Option.contains(viewing, true) || Option.isNone(pointed)) return\n const to = pointed.value\n if (typeof to === 'string' && Option.contains(holding(to, field), null))\n put(at(to, owner).values, field, bound.id)\n },\n })\n return [...moves].flatMap(([ref, { owner, values, adds }]) => {\n const moved = Object.fromEntries(Object.entries(adds).filter(([, by]) => by !== 0))\n return Object.keys(values).length === 0 && Object.keys(moved).length === 0\n ? []\n : [\n {\n entity: owner,\n id: refParts(ref).id,\n values,\n ...(Object.keys(moved).length === 0 ? {} : { adds: moved }),\n },\n ]\n })\n}\n\n/**\n * A new row's derived members over relations: each count 0 and each exists\n * none, since no row points at a row not yet made. A later pending write that\n * points at it moves them as it would any held row's.\n */\nconst freshDerived = (\n write: AnyWrite,\n input: unknown,\n derived: ReadonlyMap<string, ReadonlyArray<DerivedBy>>,\n): ReadonlyArray<PendingPatch> => {\n const entity = write.input.entity.name\n const values: Record<string, unknown> = {}\n for (const members of derived.values())\n for (const member of members)\n if (member.owner === entity)\n put(values, member.field, DerivedBy.$match(member, { Count: () => 0, Exists: () => null }))\n if (Object.keys(values).length === 0) return []\n const { id } = DomainWrite.bind(write, input as never)\n return [{ entity, id, values }]\n}\n\n/** Each supplied member of `entity` that says how a client foresees it, by key. */\nconst predicted = new WeakMap<AnyEntity, ReadonlyArray<readonly [string, Predict]>>()\nconst predictorsOf = (entity: AnyEntity): ReadonlyArray<readonly [string, Predict]> => {\n const known = predicted.get(entity)\n if (known !== undefined) return known\n const derived: Readonly<Record<string, EntityDerived<string, string, Schema.Constraint>>> =\n entity.derived\n const found = Object.entries(derived).flatMap(([key, member]) =>\n Derivation.$match(member.derives, {\n Supplied: ({ predict }) =>\n Option.match(predict, { onNone: () => [], onSome: run => [[key, run] as const] }),\n Count: () => [],\n Exists: () => [],\n }),\n )\n predicted.set(entity, found)\n return found\n}\n\n/**\n * The supplied members a write's row foresees (`Derived.make`'s `predict`),\n * judged over the row it leaves, held over the store with the write's values:\n * a member foreseen as none is left out, so the row waits for the answer.\n */\nconst suppliedOfWrite = (\n write: AnyWrite,\n own: PendingPatch,\n by: ExprContext,\n store: EntityStore,\n): ReadonlyArray<PendingPatch> => {\n const entity = write.input.entity\n const predictors = predictorsOf(entity)\n if (predictors.length === 0) return []\n const holder = holderOf(store)\n const row = holder.written(entity, own.id, own.values, [\n ...Object.keys(own.adds ?? {}),\n ...Object.keys(own.computes ?? {}),\n ])\n const values: Record<string, unknown> = {}\n for (const [key, predict] of predictors) {\n Option.map(predict({ entity, row, rows: holder.rows, context: by }), value => {\n put(values, key, value)\n })\n }\n return Object.keys(values).length === 0 ? [] : [{ entity: entity.name, id: own.id, values }]\n}\n\n/**\n * Everything a declared write shows before the server answers, from its\n * declarations alone: its own row (`optimisticOfWrite`), with what the\n * context sets filled from `viewer` and `now`, a new row's\n * derived members (`freshDerived`), what its supplied members foresee\n * (`suppliedOfWrite`, Guard's `may`), and the derived members it moves on\n * the rows it points at (`derivedOfWrite`). `derived` is the registry's, by\n * the pointing Entity; `store` is the store as shown, layers and all.\n */\nexport const predictionOfWrite = (\n write: AnyWrite,\n input: unknown,\n keys: ReadonlyArray<string> | undefined,\n context: {\n readonly derived: ReadonlyMap<string, ReadonlyArray<DerivedBy>>\n readonly store: EntityStore\n readonly viewer: Option.Option<{ readonly entity: string; readonly id: string }>\n readonly now: Option.Option<number>\n },\n): ReadonlyArray<PendingPatch | PendingDelete> => {\n const by: ExprContext = { viewer: context.viewer, now: context.now }\n const own = optimisticOfWrite(write, input, keys, by, context.store)\n return [\n ...Match.value(write).pipe(\n Match.tagsExhaustive({\n Insert: () => freshDerived(write, input, context.derived),\n Update: () => [],\n Delete: () => [],\n }),\n ),\n ...own,\n ...own.flatMap(patch =>\n '_tag' in patch ? [] : suppliedOfWrite(write, patch, by, context.store),\n ),\n ...derivedOfWrite(\n write,\n input,\n keys,\n context.derived.get(write.input.entity.name) ?? [],\n context.store,\n by,\n ),\n ]\n}\n\n/** The held fields of `row`, plain and encoded, as an invariant is judged over them. */\nconst plainRow = (entity: AnyEntity, row: HeldRow): Record<string, unknown> => {\n const plain: Record<string, unknown> = {}\n for (const key of Object.keys(entity.fields))\n Held.match(row.field(key), {\n onHeld: value => {\n put(plain, key, value)\n },\n onUnheld: () => undefined,\n })\n return plain\n}\n\n/**\n * The invariant a declared write's row would break, as the client holds it:\n * the store's row with the write's values over it, a field the write moves\n * (an increment, a computed value) not held, and for an update the row\n * before. Only a definite failure counts: an invariant over a field the\n * client lacks is undecided, and refuses nothing. A delete leaves no row.\n */\nexport const brokenByWrite = (\n write: AnyWrite,\n input: unknown,\n keys: ReadonlyArray<string> | undefined,\n context: ExprContext,\n store: EntityStore,\n operators: MemoryOperators,\n): Option.Option<Invariant> => {\n const entity = write.input.entity\n const patch = optimisticOfWrite(write, input, keys, context, store).find(\n (each): each is PendingPatch => !('_tag' in each),\n )\n if (patch === undefined) return Option.none()\n const holder = holderOf(store)\n const after = plainRow(\n entity,\n holder.written(entity, patch.id, patch.values, [\n ...Object.keys(patch.adds ?? {}),\n ...Object.keys(patch.computes ?? {}),\n ]),\n )\n const before = Option.getOrUndefined(\n Option.map(holder.rows.row(entity, patch.id), row => plainRow(entity, row)),\n )\n const judged = DomainEntity.judge(\n entity,\n write._tag === 'Insert' || before === undefined ? { after } : { after, before },\n operators,\n )\n return judged._tag === 'Invalid' ? Option.fromUndefinedOr(judged.failures[0]) : Option.none()\n}\n\n/** Each supplied member of `entity` that says which write its value refuses, by key. */\nconst forbidding = new WeakMap<AnyEntity, ReadonlyArray<readonly [string, Forbids]>>()\nconst forbiddersOf = (entity: AnyEntity): ReadonlyArray<readonly [string, Forbids]> => {\n const known = forbidding.get(entity)\n if (known !== undefined) return known\n const derived: Readonly<Record<string, EntityDerived<string, string, Schema.Constraint>>> =\n entity.derived\n const found = Object.entries(derived).flatMap(([key, member]) =>\n Derivation.$match(member.derives, {\n Supplied: ({ forbids }) =>\n Option.match(forbids, { onNone: () => [], onSome: run => [[key, run] as const] }),\n Count: () => [],\n Exists: () => [],\n }),\n )\n forbidding.set(entity, found)\n return found\n}\n\n/**\n * Why a declared write is refused by what the client holds of its row: a\n * supplied member (Guard's `may`) whose value, as the store shows it, forbids\n * what the write does to the row. None where nothing held says so: an\n * insert, a row not held, or a member not held or not refusing.\n */\nexport const forbiddenByWrite = (\n write: AnyWrite,\n input: unknown,\n keys: ReadonlyArray<string> | undefined,\n store: EntityStore,\n): Option.Option<{ readonly reason: Option.Option<string> }> => {\n const entity = write.input.entity\n const forbidders = forbiddersOf(entity)\n if (forbidders.length === 0) return Option.none()\n const bound = DomainWrite.bind(write, input as never, keys)\n const held = store[entityKey(entity.name, bound.id)]\n if (held === undefined) return Option.none()\n // An insert finds no row, so nothing held of one can refuse it.\n const surface = Match.valueTags(write, {\n Insert: (): Option.Option<WriteSurface> => Option.none(),\n Delete: () => Option.some<WriteSurface>({ kind: 'Delete', members: [], relations: [] }),\n Update: () =>\n Option.some<WriteSurface>({\n kind: 'Update',\n members: [\n ...Object.keys(bound.values),\n ...Object.keys(bound.increments),\n ...Object.keys(bound.assignments),\n ],\n relations: Object.entries(bound.links).map(([relation, link]) => ({\n relation,\n interaction: Option.isSome(link) ? 'Link' : 'Unlink',\n })),\n }),\n })\n return Option.flatMap(surface, asked =>\n Option.firstSomeOf(\n forbidders.map(([key, forbids]) =>\n held.present.has(key) ? forbids(held.values[key], asked) : Option.none(),\n ),\n ),\n )\n}\n\nexport const Mutation = {\n /**\n * Declares a mutation. `Input` and `Output` are codecs, or the fields of the\n * `Schema.Struct` they would be (`{ id: ProjectId, name: Schema.String }`).\n * `Refusal`, when given, is what the server may refuse with: a codec, usually\n * a union of `Refusal.field(...)` and `Refusal.conflict`.\n */\n /**\n * A mutation that is a declared `Write` (`update`, `insert` or `delete`): its\n * input is the write's, and it answers nothing but the row it changed, as a\n * patch, or its deletion. An insert may be refused as taken, when a row\n * already holds its id; an update or a delete as a conflict, when it\n * `expect`s a revision the row has moved past, and as unmet, when it has a\n * `when`; and any as invalid, when the row it would leave breaks an invariant.\n */\n write: <\n const Name extends string,\n Fields extends Schema.Struct.Fields,\n W extends Write<any, Fields> = Write<any, Fields>,\n >(\n name: Name,\n write: W & Write<any, Fields>,\n ): MutationDescriptor<Name, Schema.Struct.Type<Fields>, {}, RefusalOfWrite<W>> & {\n readonly write: W\n } => ({\n name,\n Input: write.input.schema as unknown as Schema.Codec<Schema.Struct.Type<Fields>>,\n Output: Schema.Struct({}),\n Refusal: refusalOfWrite(write) as unknown as Schema.Codec<RefusalOfWrite<W>, unknown>,\n write,\n }),\n\n make: <\n const Name extends string,\n Input extends SchemaOrFields,\n Output extends SchemaOrFields,\n Refused = never,\n >(\n name: Name,\n config: {\n readonly Input: Input\n readonly Output: Output\n readonly Refusal?: Schema.Codec<Refused, any>\n },\n ): MutationDescriptor<Name, TypeOf<Input>, TypeOf<Output>, Refused> => ({\n name,\n Input: schemaOf(config.Input),\n Output: schemaOf(config.Output),\n Refusal: config.Refusal ?? Schema.Never,\n }),\n}\n"],"mappings":"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"}
@@ -0,0 +1,523 @@
1
+ import { i as RemoteError } from "./remoteData-mK1suYi1.js";
2
+ import { i as Edge, n as Connection } from "./connection-BRyaJy89.js";
3
+ import { n as EntityKey, r as EntityStore } from "./store-ah2qjcJW.js";
4
+ import { Data, Option, Schema } from "effect";
5
+ import { AnyWrite, BoundWrite, Computation, ConditionedWrite, EntityRef, ExprContext, Invariant, MemoryOperators, Write, WriteKind } from "foldkit-entity";
6
+ interface NormalizedPatch {
7
+ readonly entity: string;
8
+ readonly id: string;
9
+ readonly values: Readonly<Record<string, unknown>>;
10
+ }
11
+ /**
12
+ * A patch a pending request shows, the amounts it moves fields by, and the
13
+ * fields it computes: each worked out, whenever the store is read, over the
14
+ * row as it then is, so a change that reaches the store meanwhile is added
15
+ * to or computed from, not hidden. A computation is data (operators by name),
16
+ * never a descriptor, since a pending patch sits in the Model.
17
+ */
18
+ interface PendingPatch extends NormalizedPatch {
19
+ readonly adds?: Readonly<Record<string, number>>;
20
+ readonly computes?: Readonly<Record<string, Computation>>;
21
+ }
22
+ /**
23
+ * A row a pending request deletes: until the request settles it reads
24
+ * `NotFound` and leaves every list and relation, as a settled delete does.
25
+ */
26
+ interface PendingDelete {
27
+ readonly _tag: 'Delete';
28
+ readonly entity: string;
29
+ readonly id: string;
30
+ }
31
+ /**
32
+ * What a request writes, as `Data.mutate` started it: enough to list it once it
33
+ * fails, with its input, and to send it again as itself.
34
+ */
35
+ interface StartedWrite {
36
+ /** The registered mutation's name. */
37
+ readonly mutation: string;
38
+ /** The input as `Data.mutate` was given it, decoded. */
39
+ readonly input: unknown;
40
+ readonly keys?: ReadonlyArray<string> | undefined;
41
+ /**
42
+ * When the reader acted, as `Data.mutate` was given it: what it predicted
43
+ * `Expr.now` as and sent, and what a retry sends again. None when it was
44
+ * given none, and the server's clock decides.
45
+ */
46
+ readonly now: Option.Option<number>;
47
+ /** What it showed until it settled, shown again by a retry. */
48
+ readonly optimistic: ReadonlyArray<OptimisticOperation>;
49
+ }
50
+ interface MutationState {
51
+ readonly pending: ReadonlySet<string>;
52
+ readonly applied: ReadonlySet<string>;
53
+ readonly failed: ReadonlySet<string>;
54
+ /** Why each request in `failed` failed, kept exactly as long as `failed` keeps its id. */
55
+ readonly errors: ReadonlyMap<string, RemoteError>;
56
+ /**
57
+ * The operation id each request in `failed` was sent with, kept as `errors`
58
+ * is: a retry of that request id sends it again, so a server recognises it.
59
+ */
60
+ readonly operations: ReadonlyMap<string, string>;
61
+ /**
62
+ * What each pending or failed request writes. A request settled as applied,
63
+ * or dismissed, takes its write with it.
64
+ */
65
+ readonly writes: ReadonlyMap<string, StartedWrite>;
66
+ /**
67
+ * How many mutations this model has started. A bound domain takes its next
68
+ * request id from here, so `update` stays pure and the id exists before the
69
+ * Command runs.
70
+ */
71
+ readonly sequence: number;
72
+ /** Where each pending request falls in `sequence`: the order its answer is applied in. */
73
+ readonly order: ReadonlyMap<string, number>;
74
+ /**
75
+ * The order of the last answer that wrote each row field (`entity:id\0field`)
76
+ * or deleted each row (`entity:id`), kept only while a request started
77
+ * before it is pending, since only that request's answer is compared with it.
78
+ */
79
+ readonly settled: ReadonlyMap<string, number>;
80
+ }
81
+ declare const emptyMutationState: MutationState;
82
+ declare const beginMutation: (state: MutationState, requestId: string, write?: StartedWrite) => MutationState;
83
+ declare const failMutation: (state: MutationState, requestId: string, error: RemoteError, operation: string) => MutationState;
84
+ /** The ledger with a request's failure forgotten: its id, error, operation and write. */
85
+ declare const forgetFailure: (state: MutationState, requestId: string) => MutationState;
86
+ /** What Remote knows of one mutation request, by the id `mutate` returned. */
87
+ type MutationStatus =
88
+ /** Never started here, or settled so long ago its id has left the window. */
89
+ {
90
+ readonly _tag: 'Unknown';
91
+ } | {
92
+ readonly _tag: 'Pending';
93
+ } | {
94
+ readonly _tag: 'Applied';
95
+ } | {
96
+ readonly _tag: 'Failed';
97
+ readonly error: RemoteError;
98
+ };
99
+ declare const mutationStatus: (state: MutationState, requestId: string) => MutationStatus;
100
+ interface Reconciled {
101
+ readonly store: EntityStore;
102
+ readonly state: MutationState;
103
+ }
104
+ /** What a settled mutation wrote, as `MutationSucceeded` carries it. */
105
+ interface MutationAnswer {
106
+ readonly entities: ReadonlyArray<NormalizedPatch>;
107
+ /** Entities the mutation deleted; each is tombstoned. */
108
+ readonly deleted?: ReadonlyArray<{
109
+ readonly entity: string;
110
+ readonly id: string;
111
+ }> | undefined;
112
+ /** Injected clock reading of the answer, which dates what it writes. */
113
+ readonly now: number;
114
+ }
115
+ /**
116
+ * What requests started after `requestId` already settled, which its answer
117
+ * leaves alone. The server applied requests in the order they started, so a
118
+ * later one's answer is newer: `newer` holds of a field it wrote (its mark)
119
+ * and of a row it deleted (its key), `rewritten` of a row it wrote any field
120
+ * of. An answer of a request no longer pending (after `forget`, or a failure)
121
+ * has no order, and nothing is newer than it.
122
+ */
123
+ declare const settledLater: (state: MutationState, requestId: string) => {
124
+ readonly newer: (mark: string) => boolean;
125
+ readonly rewritten: (key: string) => boolean;
126
+ };
127
+ /**
128
+ * Applies a mutation result once and marks the request settled. A second call
129
+ * with the same `requestId` (a retry, or a live event describing the same change)
130
+ * does not re-apply the entities, but still clears `pending`.
131
+ */
132
+ declare const reconcileMutation: (store: EntityStore, state: MutationState, requestId: string, answer: MutationAnswer) => Reconciled;
133
+ /** A mutation an application declares: its name and input/output codecs. */
134
+ interface MutationDescriptor<Name extends string, Input, Output, Refused = unknown> {
135
+ readonly name: Name;
136
+ readonly Input: Schema.Codec<Input>;
137
+ readonly Output: Schema.Codec<Output>;
138
+ /**
139
+ * What the server may refuse the mutation with, as a value a client can
140
+ * match on rather than a message to parse: `Schema.Never` when it declares
141
+ * none.
142
+ */
143
+ readonly Refusal: Schema.Codec<Refused, unknown>;
144
+ /**
145
+ * What the mutation writes, when it was declared as a `Write`: the optimistic
146
+ * patch a client shows, and what a server can run without a handler.
147
+ */
148
+ readonly write?: AnyWrite | undefined;
149
+ }
150
+ declare const conflict: Schema.TaggedStruct<"Conflict", {}>;
151
+ declare const unmet: Schema.TaggedStruct<"Unmet", {}>;
152
+ /**
153
+ * Another row already holds the id an insert names: its Entity and that id,
154
+ * both the caller's own, and nothing of the row, which may be hidden from them.
155
+ */
156
+ declare const taken: Schema.TaggedStruct<"Taken", {
157
+ readonly entity: Schema.String;
158
+ readonly id: Schema.String;
159
+ }>;
160
+ /**
161
+ * The row the write would leave breaks one of its Entity's invariants: which
162
+ * one (its Entity and its id, since an id is unique only within one), what to
163
+ * tell the author, and the fields to show it beside. None and empty when the
164
+ * invariant reads a member hidden from whoever asked.
165
+ */
166
+ declare const invalid: Schema.TaggedStruct<"Invalid", {
167
+ readonly entity: Schema.OptionFromOptionalNullOr<Schema.String>;
168
+ readonly rule: Schema.OptionFromNullOr<Schema.String>;
169
+ readonly message: Schema.String;
170
+ readonly path: Schema.$Array<Schema.String>;
171
+ }>;
172
+ /** Refusals a form or an editor knows how to show. */
173
+ declare const Refusal: {
174
+ /** One input key was refused, for `reason`, which a form shows beside that key. */
175
+ field: <const Key extends string, Reason extends Schema.Top>(key: Key, reason: Reason) => Schema.TaggedStruct<"Field", {
176
+ readonly key: Schema.Literal<Key>;
177
+ readonly reason: Reason;
178
+ }>;
179
+ /** The row moved on since the client read it; the author decides what wins. */
180
+ conflict: Schema.TaggedStruct<"Conflict", {}>;
181
+ /** The row does not hold what the write's `when` asks of it, where it would commit. */
182
+ unmet: Schema.TaggedStruct<"Unmet", {}>;
183
+ /** The id an insert names is taken: another create made it, or a retry the server could not tell. */
184
+ taken: Schema.TaggedStruct<"Taken", {
185
+ readonly entity: Schema.String;
186
+ readonly id: Schema.String;
187
+ }>;
188
+ /** The row the write would leave breaks an invariant of its Entity. */
189
+ invalid: Schema.TaggedStruct<"Invalid", {
190
+ readonly entity: Schema.OptionFromOptionalNullOr<Schema.String>;
191
+ readonly rule: Schema.OptionFromNullOr<Schema.String>;
192
+ readonly message: Schema.String;
193
+ readonly path: Schema.$Array<Schema.String>;
194
+ }>;
195
+ /** Whether a refusal, of whatever mutation, is a `Refusal.field`. */
196
+ isField: <I>(input: I) => input is I & {
197
+ readonly _tag: "Field";
198
+ readonly key: string;
199
+ readonly reason: unknown;
200
+ };
201
+ /** Whether a refusal, of whatever mutation, is `Refusal.conflict`. */
202
+ isConflict: <I>(input: I) => input is I & {
203
+ readonly _tag: "Conflict";
204
+ };
205
+ /** Whether a refusal, of whatever mutation, is `Refusal.unmet`. */
206
+ isUnmet: <I>(input: I) => input is I & {
207
+ readonly _tag: "Unmet";
208
+ };
209
+ /** Whether a refusal, of whatever mutation, is `Refusal.taken`. */
210
+ isTaken: <I>(input: I) => input is I & {
211
+ readonly _tag: "Taken";
212
+ readonly entity: string;
213
+ readonly id: string;
214
+ };
215
+ /** Whether a refusal, of whatever mutation, is `Refusal.invalid`. */
216
+ isInvalid: <I>(input: I) => input is I & {
217
+ readonly _tag: "Invalid";
218
+ readonly entity: Option.Option<string>;
219
+ readonly rule: Option.Option<string>;
220
+ readonly message: string;
221
+ readonly path: readonly string[];
222
+ };
223
+ /**
224
+ * Whether a refusal is `Refusal.invalid` naming this invariant, by its
225
+ * Entity and its id: the declaration `Entity.invariant` returned, once
226
+ * attached, or one `Entity.invariants` reads. An invariant over a member
227
+ * hidden from the asker names none, so it matches nothing.
228
+ */
229
+ isInvalidBy: (refusal: unknown, invariant: Pick<Invariant, 'entity' | 'id'>) => boolean;
230
+ };
231
+ type KindOf<W> = W extends {
232
+ readonly _tag: infer Kind extends WriteKind;
233
+ } ? Kind : WriteKind;
234
+ /**
235
+ * What a declared write may be refused with: an insert as taken, an update or
236
+ * a delete as a conflict (unmet too, when it has a `when`), and every one as
237
+ * invalid, since the server's Entity may hold invariants the client's does
238
+ * not show. A write whose kind its type leaves open may be refused as any.
239
+ */
240
+ type RefusalOfWrite<W> = ('Insert' extends KindOf<W> ? typeof taken.Type : never) | ([Exclude<KindOf<W>, 'Insert'>] extends [never] ? never : W extends ConditionedWrite<any, any> ? typeof conflict.Type | typeof unmet.Type : typeof conflict.Type) | typeof invalid.Type;
241
+ /** A codec, or the fields of a `Schema.Struct` where one is expected. */
242
+ type SchemaOrFields = Schema.Codec<any, any, any, any> | Schema.Struct.Fields;
243
+ /** The decoded type of a codec, or of the Struct the fields describe. */
244
+ type TypeOf<S extends SchemaOrFields> = S extends Schema.Codec<infer T, any, any, any> ? T : S extends Schema.Struct.Fields ? Schema.Struct.Type<S> : never;
245
+ /** The codec itself, or a `Schema.Struct` over the fields. */
246
+ declare const schemaOf: <S extends SchemaOrFields>(shape: S) => Schema.Codec<TypeOf<S>>;
247
+ /**
248
+ * A bound write as the store patches it: its fields as they are, and each
249
+ * relation it points as the ref key the store holds (`'User:u1'`), or null.
250
+ */
251
+ declare const patchOfWrite: (bound: BoundWrite) => NormalizedPatch;
252
+ /**
253
+ * What a declared write shows before the server answers: an update's or an
254
+ * insert's row as a patch (an update's only for the keys named, when some
255
+ * are), and an update's increments and computed fields, worked out over the
256
+ * row the store holds when it is read. A delete shows its row deleted. What
257
+ * the context sets is filled from `context` and `store`, where it can be.
258
+ */
259
+ declare const optimisticOfWrite: (write: AnyWrite, input: unknown, keys: ReadonlyArray<string> | undefined, context?: ExprContext, store?: EntityStore) => ReadonlyArray<PendingPatch | PendingDelete>;
260
+ /**
261
+ * A member a registered Entity derives over a relation of another, under the
262
+ * pointing Entity: `Post.likeCount` (`Derived.count(Like.relations.post)`) is
263
+ * `Count { relation: 'post', owner: 'Post', field: 'likeCount' }`, and
264
+ * `Post.liked` (`Derived.exists(Like.relations.post, { viewer: Like.relations.user })`)
265
+ * is `Exists { relation: 'post', viewer: 'user', owner: 'Post', field: 'liked' }`.
266
+ */
267
+ type DerivedBy = Data.TaggedEnum<{
268
+ Count: {
269
+ readonly relation: string;
270
+ readonly owner: string;
271
+ readonly field: string;
272
+ };
273
+ Exists: {
274
+ readonly relation: string;
275
+ readonly viewer: string;
276
+ readonly owner: string;
277
+ readonly field: string;
278
+ };
279
+ }>;
280
+ declare const DerivedBy: Data.TaggedEnum.Constructor<{
281
+ readonly _tag: "Count";
282
+ readonly relation: string;
283
+ readonly owner: string;
284
+ readonly field: string;
285
+ } | {
286
+ readonly _tag: "Exists";
287
+ readonly relation: string;
288
+ readonly viewer: string;
289
+ readonly owner: string;
290
+ readonly field: string;
291
+ }>;
292
+ /**
293
+ * The derived members a declared write moves, as pending patches of the rows
294
+ * its row points at. A count: an insert adds one where it points, a delete
295
+ * takes one away where the row pointed, and a relink does both. An exists:
296
+ * a row now pointing here and at `viewer` is found (its id), and a row the
297
+ * store shows as found by this one is no longer, once the write deletes it or
298
+ * points it elsewhere.
299
+ *
300
+ * Where the row pointed before is read from `store`: the row as held, or,
301
+ * when the store holds an exists found by this row, the row it is found on
302
+ * and the viewer. When neither says, nothing is predicted and the answer
303
+ * decides. A member is moved only on a row that `store` holds it on.
304
+ */
305
+ declare const derivedOfWrite: (write: AnyWrite, input: unknown, keys: ReadonlyArray<string> | undefined, derived: ReadonlyArray<DerivedBy>, store: EntityStore, context: ExprContext) => ReadonlyArray<PendingPatch>;
306
+ /**
307
+ * Everything a declared write shows before the server answers, from its
308
+ * declarations alone: its own row (`optimisticOfWrite`), with what the
309
+ * context sets filled from `viewer` and `now`, a new row's
310
+ * derived members (`freshDerived`), what its supplied members foresee
311
+ * (`suppliedOfWrite`, Guard's `may`), and the derived members it moves on
312
+ * the rows it points at (`derivedOfWrite`). `derived` is the registry's, by
313
+ * the pointing Entity; `store` is the store as shown, layers and all.
314
+ */
315
+ declare const predictionOfWrite: (write: AnyWrite, input: unknown, keys: ReadonlyArray<string> | undefined, context: {
316
+ readonly derived: ReadonlyMap<string, ReadonlyArray<DerivedBy>>;
317
+ readonly store: EntityStore;
318
+ readonly viewer: Option.Option<{
319
+ readonly entity: string;
320
+ readonly id: string;
321
+ }>;
322
+ readonly now: Option.Option<number>;
323
+ }) => ReadonlyArray<PendingPatch | PendingDelete>;
324
+ /**
325
+ * The invariant a declared write's row would break, as the client holds it:
326
+ * the store's row with the write's values over it, a field the write moves
327
+ * (an increment, a computed value) not held, and for an update the row
328
+ * before. Only a definite failure counts: an invariant over a field the
329
+ * client lacks is undecided, and refuses nothing. A delete leaves no row.
330
+ */
331
+ declare const brokenByWrite: (write: AnyWrite, input: unknown, keys: ReadonlyArray<string> | undefined, context: ExprContext, store: EntityStore, operators: MemoryOperators) => Option.Option<Invariant>;
332
+ /**
333
+ * Why a declared write is refused by what the client holds of its row: a
334
+ * supplied member (Guard's `may`) whose value, as the store shows it, forbids
335
+ * what the write does to the row. None where nothing held says so: an
336
+ * insert, a row not held, or a member not held or not refusing.
337
+ */
338
+ declare const forbiddenByWrite: (write: AnyWrite, input: unknown, keys: ReadonlyArray<string> | undefined, store: EntityStore) => Option.Option<{
339
+ readonly reason: Option.Option<string>;
340
+ }>;
341
+ declare const Mutation: {
342
+ /**
343
+ * Declares a mutation. `Input` and `Output` are codecs, or the fields of the
344
+ * `Schema.Struct` they would be (`{ id: ProjectId, name: Schema.String }`).
345
+ * `Refusal`, when given, is what the server may refuse with: a codec, usually
346
+ * a union of `Refusal.field(...)` and `Refusal.conflict`.
347
+ */
348
+ /**
349
+ * A mutation that is a declared `Write` (`update`, `insert` or `delete`): its
350
+ * input is the write's, and it answers nothing but the row it changed, as a
351
+ * patch, or its deletion. An insert may be refused as taken, when a row
352
+ * already holds its id; an update or a delete as a conflict, when it
353
+ * `expect`s a revision the row has moved past, and as unmet, when it has a
354
+ * `when`; and any as invalid, when the row it would leave breaks an invariant.
355
+ */
356
+ write: <const Name extends string, Fields extends Schema.Struct.Fields, W extends Write<any, Fields> = Write<any, Fields>>(name: Name, write: W & Write<any, Fields>) => MutationDescriptor<Name, Schema.Struct.Type<Fields>, {}, RefusalOfWrite<W>> & {
357
+ readonly write: W;
358
+ };
359
+ make: <const Name extends string, Input extends SchemaOrFields, Output extends SchemaOrFields, Refused = never>(name: Name, config: {
360
+ readonly Input: Input;
361
+ readonly Output: Output;
362
+ readonly Refusal?: Schema.Codec<Refused, any>;
363
+ }) => MutationDescriptor<Name, TypeOf<Input>, TypeOf<Output>, Refused>;
364
+ };
365
+ interface EntityLayer {
366
+ readonly id: string;
367
+ readonly patches: ReadonlyArray<PendingPatch>;
368
+ /** Rows it deletes. A delete wins over every layer's patch of its row, as in an answer. */
369
+ readonly deletes: ReadonlyArray<PendingDelete>;
370
+ /**
371
+ * Who the operation was predicted for (`Remote.make`'s viewer when it
372
+ * started): what a list body's `Expr.viewer` reads when the client places
373
+ * the rows this layer changes. None for a preview with no operation.
374
+ */
375
+ readonly viewer: Option.Option<EntityRef>;
376
+ }
377
+ /**
378
+ * Edges placed outside a connection's server-known region (`prepend`,
379
+ * `append`) or hidden from it (`remove`), owned by the request or live event
380
+ * that produced them.
381
+ */
382
+ interface ConnectionOverlay {
383
+ readonly id: string;
384
+ readonly connection: string;
385
+ readonly edges: ReadonlyArray<Edge>;
386
+ readonly position: 'prepend' | 'append' | 'remove';
387
+ }
388
+ /** A connection change a request makes optimistically or a mutation result confirms. */
389
+ type ConnectionChange = {
390
+ readonly _tag: 'Insert';
391
+ readonly connection: string;
392
+ readonly position: 'prepend' | 'append';
393
+ readonly edge: Edge;
394
+ } | {
395
+ readonly _tag: 'Remove';
396
+ readonly connection: string;
397
+ readonly edge: Edge;
398
+ };
399
+ /** What a request changes before the server answers: entity patches, deletions and connection changes. */
400
+ type OptimisticOperation = PendingPatch | PendingDelete | ConnectionChange;
401
+ /** A connection, by identity string or by anything that carries one (a `QueryRef`). */
402
+ type ConnectionIdentity = string | {
403
+ readonly identity: string;
404
+ };
405
+ declare const connectionIdentity: (connection: ConnectionIdentity) => string;
406
+ /**
407
+ * Constructors for connection changes: what a request shows optimistically
408
+ * (`MutateOptions.optimistic`) and what a mutation source reports it made
409
+ * (`MutationOutcome.connections`).
410
+ */
411
+ declare const ConnectionChange: {
412
+ /** Show `ref` at the front of the connection until the request settles. */
413
+ prepend: (connection: ConnectionIdentity, ref: {
414
+ readonly entity: string;
415
+ readonly id: string;
416
+ }) => ConnectionChange;
417
+ /** Show `ref` at the end of the connection until the request settles. */
418
+ append: (connection: ConnectionIdentity, ref: {
419
+ readonly entity: string;
420
+ readonly id: string;
421
+ }) => ConnectionChange;
422
+ /** Hide `ref` from the connection until the request settles. */
423
+ remove: (connection: ConnectionIdentity, ref: {
424
+ readonly entity: string;
425
+ readonly id: string;
426
+ }) => ConnectionChange;
427
+ };
428
+ /**
429
+ * Applies a request's operations: its patches and deletions become one layer
430
+ * and its connection changes become overlays, all owned by `requestId` so
431
+ * settling removes every one of them together.
432
+ */
433
+ declare const beginOptimistic: (optimistic: OptimisticState, requestId: string, operations: ReadonlyArray<OptimisticOperation>, viewer?: Option.Option<EntityRef>) => OptimisticState;
434
+ /** Pending entity layers and connection overlays over the base store. */
435
+ interface OptimisticState {
436
+ readonly layers: ReadonlyArray<EntityLayer>;
437
+ readonly overlays: ReadonlyArray<ConnectionOverlay>;
438
+ }
439
+ declare const emptyOptimistic: OptimisticState;
440
+ declare const addLayer: (optimistic: OptimisticState, layer: EntityLayer) => OptimisticState;
441
+ declare const removeLayer: (optimistic: OptimisticState, id: string) => OptimisticState;
442
+ declare const addOverlay: (optimistic: OptimisticState, overlay: ConnectionOverlay) => OptimisticState;
443
+ declare const removeOverlay: (optimistic: OptimisticState, id: string) => OptimisticState;
444
+ /**
445
+ * Base store with every layer applied in order. Later layers win. A patch is
446
+ * not news from the server, so it keeps the date of the value under it; an
447
+ * entity only a request holds (a temporary id) is not the server's to age, and
448
+ * is dated `Infinity`, so freshness never plans or times it. A row a layer
449
+ * deletes is a tombstone over all of them. A patch over a row the server
450
+ * holds deleted shows it, as a create of a row known absent does; a patch a
451
+ * later request's delete settled is taken out of its layer (`settleSuccess`).
452
+ */
453
+ declare const visibleStore: (base: EntityStore, optimistic: OptimisticState, operators?: MemoryOperators) => EntityStore;
454
+ /**
455
+ * The store a read plans over: the visible store, except that a row the
456
+ * server holds is planned by what the server holds of it, so a field only a
457
+ * layer shows is still fetched. Its values stay the visible ones, so a
458
+ * relation a layer points elsewhere is followed where it points. A row only a
459
+ * request holds and a row a layer deletes are planned as shown; the first is
460
+ * then left out of the read (`heldOnlyByRequests`).
461
+ */
462
+ declare const plannedStore: (base: EntityStore, visible: EntityStore, optimistic: OptimisticState) => EntityStore;
463
+ /**
464
+ * The rows only a pending request holds: a layer shows each over a row the
465
+ * server holds nothing of (never read, or read as absent). A read of one is
466
+ * not sent. The server has nothing for it until the request lands, so it would
467
+ * answer "absent", which leaves the plan as it was. Once the answer lands
468
+ * the plan would also be unchanged, so the read entry would never restart and
469
+ * a field the answer omits (a guard's `may`) would never be fetched. Left out
470
+ * now, the row's missing fields enter the plan when its answer lands, and that
471
+ * change starts the read.
472
+ */
473
+ declare const heldOnlyByRequests: (base: EntityStore, optimistic: OptimisticState) => ReadonlySet<EntityKey>;
474
+ /**
475
+ * Whether a list hides a row: the store holds it deleted, or a pending layer
476
+ * deletes it. Read from the server's store, not the visible one, where a
477
+ * pending patch over a deleted row clears its tombstone.
478
+ */
479
+ declare const goneIn: (store: EntityStore, optimistic: OptimisticState) => ((key: EntityKey) => boolean);
480
+ /**
481
+ * Every pending patch in order, each amount added and each computed field
482
+ * worked out over the row under it (the store's, with earlier layers over
483
+ * it) by `Write.apply`, with the client's table (the kernel's when not
484
+ * given). A prediction, so only over
485
+ * what the client holds: a field it has not read, an amount over anything
486
+ * but a number, or a computation by an operator its table lacks keeps what
487
+ * it shows until the server answers.
488
+ */
489
+ declare const resolvedPatches: (base: EntityStore, optimistic: OptimisticState, operators?: MemoryOperators) => ReadonlyArray<NormalizedPatch>;
490
+ /**
491
+ * A fresh page is newer than any settled overlay it covers: an edge the page
492
+ * carries no longer needs an insert overlay, and a `remove` overlay hiding it
493
+ * is stale (the server says it is back). A pending request's overlays are
494
+ * left alone; they settle with the request.
495
+ */
496
+ declare const pruneOverlays: (optimistic: OptimisticState, connection: string, covered: ReadonlySet<string>, pending: ReadonlySet<string>) => OptimisticState;
497
+ /**
498
+ * Applies a result idempotently and releases the request's layer and overlays:
499
+ * a later layer re-wins on rebase. Confirmed connection changes are recorded
500
+ * once per request, as overlays the request no longer owns.
501
+ */
502
+ declare const settleSuccess: (base: EntityStore, optimistic: OptimisticState, state: MutationState, requestId: string, answer: MutationAnswer & {
503
+ /** Connection changes the server confirmed; they replace the request's own. */
504
+ readonly connections?: ReadonlyArray<ConnectionChange> | undefined;
505
+ }) => {
506
+ readonly store: EntityStore;
507
+ readonly state: MutationState;
508
+ readonly optimistic: OptimisticState;
509
+ };
510
+ /** A failed request's layer and overlays are dropped; the base was never mutated. */
511
+ declare const settleFailure: (optimistic: OptimisticState, requestId: string) => OptimisticState;
512
+ /**
513
+ * Visible edges for one connection: applicable overlays are placed outside the
514
+ * server-known segments and de-duplicated by edge identity (across overlays too),
515
+ * so a pending insert never corrupts server-known ordering; a `remove` overlay
516
+ * hides its edges wherever they are, and so does `gone` (`goneIn`) of the
517
+ * edge's target. A later prepend lands before an earlier one, a later append
518
+ * after, so pending inserts read in the order they were made. Boundaries still
519
+ * come from the connection's segments.
520
+ */
521
+ declare const visibleItems: (connection: Connection, connectionId: string, overlays: ReadonlyArray<ConnectionOverlay>, gone?: (key: EntityKey) => boolean) => ReadonlyArray<Edge>;
522
+ export { PendingDelete as A, derivedOfWrite as B, DerivedBy as C, MutationState as D, MutationDescriptor as E, SchemaOrFields as F, mutationStatus as G, failMutation as H, StartedWrite as I, predictionOfWrite as J, optimisticOfWrite as K, TypeOf as L, Reconciled as M, Refusal as N, MutationStatus as O, RefusalOfWrite as P, beginMutation as R, visibleStore as S, MutationAnswer as T, forbiddenByWrite as U, emptyMutationState as V, forgetFailure as W, schemaOf as X, reconcileMutation as Y, settledLater as Z, removeOverlay as _, OptimisticOperation as a, settleSuccess as b, addOverlay as c, emptyOptimistic as d, goneIn as f, removeLayer as g, pruneOverlays as h, EntityLayer as i, PendingPatch as j, NormalizedPatch as k, beginOptimistic as l, plannedStore as m, ConnectionIdentity as n, OptimisticState as o, heldOnlyByRequests as p, patchOfWrite as q, ConnectionOverlay as r, addLayer as s, ConnectionChange as t, connectionIdentity as u, resolvedPatches as v, Mutation as w, visibleItems as x, settleFailure as y, brokenByWrite as z };
523
+ //# sourceMappingURL=optimistic-CECsfNGY.d.ts.map