@hops-ops/distributed 0.0.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 (242) hide show
  1. package/README.md +454 -0
  2. package/dist/auth-headers.d.ts +8 -0
  3. package/dist/auth-headers.js +35 -0
  4. package/dist/diagnostics.d.ts +2 -0
  5. package/dist/diagnostics.js +1 -0
  6. package/dist/document.d.ts +8 -0
  7. package/dist/document.js +6 -0
  8. package/dist/identity.d.ts +23 -0
  9. package/dist/identity.js +73 -0
  10. package/dist/index.d.ts +7 -0
  11. package/dist/index.js +6 -0
  12. package/dist/internal/cache-engine/create.d.ts +5 -0
  13. package/dist/internal/cache-engine/create.js +7 -0
  14. package/dist/internal/cache-engine/engine.d.ts +32 -0
  15. package/dist/internal/cache-engine/engine.js +1287 -0
  16. package/dist/internal/cache-engine/errors.d.ts +5 -0
  17. package/dist/internal/cache-engine/errors.js +10 -0
  18. package/dist/internal/cache-engine/helpers.d.ts +55 -0
  19. package/dist/internal/cache-engine/helpers.js +545 -0
  20. package/dist/internal/cache-engine/index.d.ts +3 -0
  21. package/dist/internal/cache-engine/index.js +2 -0
  22. package/dist/internal/cache-engine/types.d.ts +300 -0
  23. package/dist/internal/cache-engine/types.js +1 -0
  24. package/dist/internal/cache-engine.d.ts +3 -0
  25. package/dist/internal/cache-engine.js +2 -0
  26. package/dist/lib/assert-name.d.ts +2 -0
  27. package/dist/lib/assert-name.js +6 -0
  28. package/dist/lib/compare-code-units.d.ts +2 -0
  29. package/dist/lib/compare-code-units.js +4 -0
  30. package/dist/lib/deep-equal.d.ts +2 -0
  31. package/dist/lib/deep-equal.js +24 -0
  32. package/dist/lib/freeze-record.d.ts +2 -0
  33. package/dist/lib/freeze-record.js +13 -0
  34. package/dist/lib/index.d.ts +6 -0
  35. package/dist/lib/index.js +6 -0
  36. package/dist/lib/is-plain-record.d.ts +2 -0
  37. package/dist/lib/is-plain-record.js +8 -0
  38. package/dist/lib/report.d.ts +7 -0
  39. package/dist/lib/report.js +26 -0
  40. package/dist/protocol.d.ts +179 -0
  41. package/dist/protocol.js +558 -0
  42. package/dist/react/context.d.ts +20 -0
  43. package/dist/react/context.js +24 -0
  44. package/dist/react/index.d.ts +2 -0
  45. package/dist/react/index.js +3 -0
  46. package/dist/react/query.d.ts +20 -0
  47. package/dist/react/query.js +99 -0
  48. package/dist/replica/command-id.d.ts +2 -0
  49. package/dist/replica/command-id.js +19 -0
  50. package/dist/replica/command-runtime/constants.d.ts +5 -0
  51. package/dist/replica/command-runtime/constants.js +5 -0
  52. package/dist/replica/command-runtime/create.d.ts +2 -0
  53. package/dist/replica/command-runtime/create.js +644 -0
  54. package/dist/replica/command-runtime/errors.d.ts +16 -0
  55. package/dist/replica/command-runtime/errors.js +41 -0
  56. package/dist/replica/command-runtime/index.d.ts +5 -0
  57. package/dist/replica/command-runtime/index.js +4 -0
  58. package/dist/replica/command-runtime/lib/binding.d.ts +4 -0
  59. package/dist/replica/command-runtime/lib/binding.js +64 -0
  60. package/dist/replica/command-runtime/lib/effects.d.ts +11 -0
  61. package/dist/replica/command-runtime/lib/effects.js +89 -0
  62. package/dist/replica/command-runtime/lib/index.d.ts +9 -0
  63. package/dist/replica/command-runtime/lib/index.js +9 -0
  64. package/dist/replica/command-runtime/lib/inventory.d.ts +10 -0
  65. package/dist/replica/command-runtime/lib/inventory.js +141 -0
  66. package/dist/replica/command-runtime/lib/output.d.ts +13 -0
  67. package/dist/replica/command-runtime/lib/output.js +190 -0
  68. package/dist/replica/command-runtime/lib/projection.d.ts +20 -0
  69. package/dist/replica/command-runtime/lib/projection.js +255 -0
  70. package/dist/replica/command-runtime/lib/status.d.ts +7 -0
  71. package/dist/replica/command-runtime/lib/status.js +127 -0
  72. package/dist/replica/command-runtime/lib/transport.d.ts +16 -0
  73. package/dist/replica/command-runtime/lib/transport.js +112 -0
  74. package/dist/replica/command-runtime/lib/util.d.ts +16 -0
  75. package/dist/replica/command-runtime/lib/util.js +127 -0
  76. package/dist/replica/command-runtime/lifecycle.d.ts +11 -0
  77. package/dist/replica/command-runtime/lifecycle.js +13 -0
  78. package/dist/replica/command-runtime/symbols.d.ts +30 -0
  79. package/dist/replica/command-runtime/symbols.js +30 -0
  80. package/dist/replica/command-runtime/types.d.ts +222 -0
  81. package/dist/replica/command-runtime/types.js +1 -0
  82. package/dist/replica/command-runtime.d.ts +3 -0
  83. package/dist/replica/command-runtime.js +2 -0
  84. package/dist/replica/commands/clone.d.ts +12 -0
  85. package/dist/replica/commands/clone.js +187 -0
  86. package/dist/replica/commands/constants.d.ts +6 -0
  87. package/dist/replica/commands/constants.js +6 -0
  88. package/dist/replica/commands/errors.d.ts +7 -0
  89. package/dist/replica/commands/errors.js +22 -0
  90. package/dist/replica/commands/implementation.d.ts +8 -0
  91. package/dist/replica/commands/implementation.js +8 -0
  92. package/dist/replica/commands/index.d.ts +5 -0
  93. package/dist/replica/commands/index.js +4 -0
  94. package/dist/replica/commands/prepare.d.ts +27 -0
  95. package/dist/replica/commands/prepare.js +77 -0
  96. package/dist/replica/commands/presets.d.ts +12 -0
  97. package/dist/replica/commands/presets.js +84 -0
  98. package/dist/replica/commands/receipt.d.ts +3 -0
  99. package/dist/replica/commands/receipt.js +36 -0
  100. package/dist/replica/commands/resolve.d.ts +11 -0
  101. package/dist/replica/commands/resolve.js +165 -0
  102. package/dist/replica/commands/types.d.ts +278 -0
  103. package/dist/replica/commands/types.js +2 -0
  104. package/dist/replica/commands/util.d.ts +21 -0
  105. package/dist/replica/commands/util.js +96 -0
  106. package/dist/replica/commands/validate.d.ts +18 -0
  107. package/dist/replica/commands/validate.js +477 -0
  108. package/dist/replica/commands.d.ts +3 -0
  109. package/dist/replica/commands.js +2 -0
  110. package/dist/replica/diagnostics/event-log.d.ts +4 -0
  111. package/dist/replica/diagnostics/event-log.js +463 -0
  112. package/dist/replica/diagnostics/implementation.d.ts +4 -0
  113. package/dist/replica/diagnostics/implementation.js +4 -0
  114. package/dist/replica/diagnostics/index.d.ts +2 -0
  115. package/dist/replica/diagnostics/index.js +1 -0
  116. package/dist/replica/diagnostics/inspect.d.ts +6 -0
  117. package/dist/replica/diagnostics/inspect.js +170 -0
  118. package/dist/replica/diagnostics/types.d.ts +295 -0
  119. package/dist/replica/diagnostics/types.js +2 -0
  120. package/dist/replica/diagnostics.d.ts +3 -0
  121. package/dist/replica/diagnostics.js +2 -0
  122. package/dist/replica/distributed-replica/clocks.d.ts +23 -0
  123. package/dist/replica/distributed-replica/clocks.js +156 -0
  124. package/dist/replica/distributed-replica/constants.d.ts +12 -0
  125. package/dist/replica/distributed-replica/constants.js +10 -0
  126. package/dist/replica/distributed-replica/helpers.d.ts +48 -0
  127. package/dist/replica/distributed-replica/helpers.js +445 -0
  128. package/dist/replica/distributed-replica/hydration.d.ts +19 -0
  129. package/dist/replica/distributed-replica/hydration.js +380 -0
  130. package/dist/replica/distributed-replica/impl-diagnostics.d.ts +22 -0
  131. package/dist/replica/distributed-replica/impl-diagnostics.js +189 -0
  132. package/dist/replica/distributed-replica/impl-fetch-live.d.ts +39 -0
  133. package/dist/replica/distributed-replica/impl-fetch-live.js +395 -0
  134. package/dist/replica/distributed-replica/impl-hydration-orchestrate.d.ts +56 -0
  135. package/dist/replica/distributed-replica/impl-hydration-orchestrate.js +299 -0
  136. package/dist/replica/distributed-replica/impl-optimistic.d.ts +31 -0
  137. package/dist/replica/distributed-replica/impl-optimistic.js +172 -0
  138. package/dist/replica/distributed-replica/impl-protocol.d.ts +53 -0
  139. package/dist/replica/distributed-replica/impl-protocol.js +108 -0
  140. package/dist/replica/distributed-replica/impl.d.ts +44 -0
  141. package/dist/replica/distributed-replica/impl.js +1776 -0
  142. package/dist/replica/distributed-replica/index.d.ts +2 -0
  143. package/dist/replica/distributed-replica/index.js +4 -0
  144. package/dist/replica/distributed-replica/optimistic.d.ts +30 -0
  145. package/dist/replica/distributed-replica/optimistic.js +221 -0
  146. package/dist/replica/distributed-replica/types.d.ts +147 -0
  147. package/dist/replica/distributed-replica/types.js +1 -0
  148. package/dist/replica/distributed-replica/watch.d.ts +19 -0
  149. package/dist/replica/distributed-replica/watch.js +95 -0
  150. package/dist/replica/distributed-replica.d.ts +2 -0
  151. package/dist/replica/distributed-replica.js +2 -0
  152. package/dist/replica/graphql-transport.d.ts +24 -0
  153. package/dist/replica/graphql-transport.js +122 -0
  154. package/dist/replica/identity/clone.d.ts +6 -0
  155. package/dist/replica/identity/clone.js +54 -0
  156. package/dist/replica/identity/codec.d.ts +48 -0
  157. package/dist/replica/identity/codec.js +789 -0
  158. package/dist/replica/identity/constants.d.ts +3 -0
  159. package/dist/replica/identity/constants.js +18 -0
  160. package/dist/replica/identity/implementation.d.ts +5 -0
  161. package/dist/replica/identity/implementation.js +5 -0
  162. package/dist/replica/identity/index.d.ts +3 -0
  163. package/dist/replica/identity/index.js +3 -0
  164. package/dist/replica/identity/keys.d.ts +29 -0
  165. package/dist/replica/identity/keys.js +173 -0
  166. package/dist/replica/identity.d.ts +2 -0
  167. package/dist/replica/identity.js +2 -0
  168. package/dist/replica/index-maintenance/engine.d.ts +84 -0
  169. package/dist/replica/index-maintenance/engine.js +677 -0
  170. package/dist/replica/index-maintenance/implementation.d.ts +4 -0
  171. package/dist/replica/index-maintenance/implementation.js +4 -0
  172. package/dist/replica/index-maintenance/index.d.ts +2 -0
  173. package/dist/replica/index-maintenance/index.js +1 -0
  174. package/dist/replica/index-maintenance/registry.d.ts +2 -0
  175. package/dist/replica/index-maintenance/registry.js +49 -0
  176. package/dist/replica/index-maintenance/types.d.ts +58 -0
  177. package/dist/replica/index-maintenance/types.js +1 -0
  178. package/dist/replica/index-maintenance.d.ts +3 -0
  179. package/dist/replica/index-maintenance.js +2 -0
  180. package/dist/replica/index.d.ts +17 -0
  181. package/dist/replica/index.js +9 -0
  182. package/dist/replica/materialize.d.ts +10 -0
  183. package/dist/replica/materialize.js +163 -0
  184. package/dist/replica/normalize.d.ts +27 -0
  185. package/dist/replica/normalize.js +298 -0
  186. package/dist/replica/operation-binding.d.ts +14 -0
  187. package/dist/replica/operation-binding.js +76 -0
  188. package/dist/replica/persistence/idb.d.ts +20 -0
  189. package/dist/replica/persistence/idb.js +193 -0
  190. package/dist/replica/persistence/implementation.d.ts +4 -0
  191. package/dist/replica/persistence/implementation.js +4 -0
  192. package/dist/replica/persistence/index.d.ts +2 -0
  193. package/dist/replica/persistence/index.js +1 -0
  194. package/dist/replica/persistence/state.d.ts +104 -0
  195. package/dist/replica/persistence/state.js +734 -0
  196. package/dist/replica/persistence/types.d.ts +54 -0
  197. package/dist/replica/persistence/types.js +1 -0
  198. package/dist/replica/persistence.d.ts +3 -0
  199. package/dist/replica/persistence.js +2 -0
  200. package/dist/replica/query-plan/constants.d.ts +13 -0
  201. package/dist/replica/query-plan/constants.js +7 -0
  202. package/dist/replica/query-plan/filter.d.ts +39 -0
  203. package/dist/replica/query-plan/filter.js +544 -0
  204. package/dist/replica/query-plan/index.d.ts +4 -0
  205. package/dist/replica/query-plan/index.js +3 -0
  206. package/dist/replica/query-plan/order.d.ts +11 -0
  207. package/dist/replica/query-plan/order.js +158 -0
  208. package/dist/replica/query-plan/pagination.d.ts +6 -0
  209. package/dist/replica/query-plan/pagination.js +90 -0
  210. package/dist/replica/query-plan/resolve.d.ts +14 -0
  211. package/dist/replica/query-plan/resolve.js +163 -0
  212. package/dist/replica/query-plan/types.d.ts +89 -0
  213. package/dist/replica/query-plan/types.js +1 -0
  214. package/dist/replica/query-plan/util.d.ts +13 -0
  215. package/dist/replica/query-plan/util.js +62 -0
  216. package/dist/replica/query-plan.d.ts +3 -0
  217. package/dist/replica/query-plan.js +2 -0
  218. package/dist/replica/revalidation.d.ts +9 -0
  219. package/dist/replica/revalidation.js +86 -0
  220. package/dist/replica/selection.d.ts +20 -0
  221. package/dist/replica/selection.js +109 -0
  222. package/dist/replica/types.d.ts +657 -0
  223. package/dist/replica/types.js +1 -0
  224. package/dist/request.d.ts +17 -0
  225. package/dist/request.js +123 -0
  226. package/dist/sveltekit/auth.d.ts +18 -0
  227. package/dist/sveltekit/auth.js +9 -0
  228. package/dist/sveltekit/context.d.ts +28 -0
  229. package/dist/sveltekit/context.js +58 -0
  230. package/dist/sveltekit/index.d.ts +4 -0
  231. package/dist/sveltekit/index.js +4 -0
  232. package/dist/sveltekit/replica.d.ts +145 -0
  233. package/dist/sveltekit/replica.js +491 -0
  234. package/dist/sveltekit/server-replica.d.ts +52 -0
  235. package/dist/sveltekit/server-replica.js +176 -0
  236. package/dist/sveltekit/vite.d.ts +103 -0
  237. package/dist/sveltekit/vite.js +878 -0
  238. package/dist/types.d.ts +33 -0
  239. package/dist/types.js +1 -0
  240. package/dist/websocket.d.ts +41 -0
  241. package/dist/websocket.js +187 -0
  242. package/package.json +95 -0
@@ -0,0 +1 @@
1
+ export { createReplicaIndexMaintenanceRegistry, formatReplicaIndexStaleReason } from './implementation.js';
@@ -0,0 +1,2 @@
1
+ import type { ReplicaIndexMaintenanceRegistry } from './types.js';
2
+ export declare function createReplicaIndexMaintenanceRegistry(): ReplicaIndexMaintenanceRegistry;
@@ -0,0 +1,49 @@
1
+ import { canonicalizeOperationVariables } from '../identity.js';
2
+ import { compareCodeUnits } from '../../lib/compare-code-units.js';
3
+ import { applyLayers, canonicalValue, compilePlans, evaluatePlan, instantiatePlans, planAffected, reason, stale, validateIndexes } from './engine.js';
4
+ class PurposeBuiltIndexMaintenanceRegistry {
5
+ #plans = new Map();
6
+ #nextRegistration = 0;
7
+ registerOperation(artifact, variables) {
8
+ const canonicalVariables = canonicalizeOperationVariables(artifact, variables);
9
+ const id = `${artifact.id}:${canonicalValue(canonicalVariables)}:${++this.#nextRegistration}`;
10
+ this.#plans.set(id, compilePlans(id, artifact, canonicalVariables));
11
+ let active = true;
12
+ return Object.freeze({
13
+ id,
14
+ dispose: () => {
15
+ if (!active)
16
+ return;
17
+ active = false;
18
+ this.#plans.delete(id);
19
+ }
20
+ });
21
+ }
22
+ evaluate(snapshot, layers, trustedPresets = Object.freeze([])) {
23
+ const applied = applyLayers(snapshot.records, layers);
24
+ const indexes = validateIndexes(snapshot.indexes);
25
+ const plansByIndex = instantiatePlans([...this.#plans.values()].flat(), indexes);
26
+ const decisions = [];
27
+ for (const [indexKey, plans] of [...plansByIndex].sort(([left], [right]) => compareCodeUnits(left, right))) {
28
+ const index = indexes.get(indexKey);
29
+ if (index === undefined)
30
+ continue;
31
+ const affected = plans.filter((plan) => planAffected(plan, index, applied));
32
+ if (affected.length === 0)
33
+ continue;
34
+ const signatures = new Set(affected.map(({ signature }) => signature));
35
+ if (signatures.size !== 1) {
36
+ decisions.push(stale(indexKey, reason('conflicting_index_plan', ['indexes', indexKey], 'multiple active artifacts disagree about one semantic index plan')));
37
+ continue;
38
+ }
39
+ decisions.push(evaluatePlan(affected[0], index, applied, trustedPresets));
40
+ }
41
+ return Object.freeze(decisions);
42
+ }
43
+ clear() {
44
+ this.#plans.clear();
45
+ }
46
+ }
47
+ export function createReplicaIndexMaintenanceRegistry() {
48
+ return new PurposeBuiltIndexMaintenanceRegistry();
49
+ }
@@ -0,0 +1,58 @@
1
+ import type { GraphqlVariables } from '../../types.js';
2
+ import type { DistributedTrustedPreset } from '../../protocol.js';
3
+ import type { ReplicaIndexCoverage, ReplicaIndexSemanticChange, ReplicaOperationArtifact, ReplicaValue } from '../types.js';
4
+ export type { ReplicaIndexDependencyChange, ReplicaIndexRecordChange, ReplicaIndexRelationshipChange, ReplicaIndexSemanticChange } from '../types.js';
5
+ export type ReplicaIndexMaintenanceRecord = {
6
+ readonly key: string;
7
+ readonly model: string;
8
+ readonly fields: Readonly<Record<string, ReplicaValue>>;
9
+ };
10
+ export type ReplicaIndexMaintenanceIndex = {
11
+ readonly key: string;
12
+ readonly records: readonly string[];
13
+ readonly complete: boolean;
14
+ readonly metadata: {
15
+ readonly parent?: string;
16
+ readonly field: string;
17
+ readonly arguments: Readonly<Record<string, ReplicaValue>>;
18
+ readonly coverage: ReplicaIndexCoverage;
19
+ readonly dependencies: readonly string[];
20
+ readonly staleReason?: string;
21
+ };
22
+ };
23
+ export type ReplicaIndexSemanticLayer = {
24
+ readonly id: string;
25
+ readonly changes: readonly ReplicaIndexSemanticChange[];
26
+ };
27
+ export type ReplicaIndexMaintenanceSnapshot = {
28
+ readonly records: readonly ReplicaIndexMaintenanceRecord[];
29
+ readonly indexes: readonly ReplicaIndexMaintenanceIndex[];
30
+ };
31
+ export type ReplicaIndexMaintenanceReasonCode = 'aggregate_dependency_changed' | 'conflicting_index_plan' | 'dependency_changed' | 'duplicate_index_record' | 'index_incomplete' | 'invalid_index_metadata' | 'missing_index_record' | 'missing_order_plan' | 'missing_parent_record' | 'non_unique_order' | 'relationship_dependency_missing' | 'relationship_maintenance_revalidate' | 'relationship_mapping_unknown' | 'unsupported_cardinality' | import('../query-plan.js').ReplicaQueryPlanReasonCode;
32
+ export type ReplicaIndexMaintenanceReason = {
33
+ readonly code: ReplicaIndexMaintenanceReasonCode;
34
+ readonly path: readonly (string | number)[];
35
+ readonly message: string;
36
+ };
37
+ export type ReplicaIndexMaintenanceDecision = {
38
+ readonly kind: 'write';
39
+ readonly indexKey: string;
40
+ readonly records: readonly string[];
41
+ readonly complete: true;
42
+ } | {
43
+ readonly kind: 'stale';
44
+ readonly indexKey: string;
45
+ readonly reason: ReplicaIndexMaintenanceReason;
46
+ } | {
47
+ readonly kind: 'unchanged';
48
+ readonly indexKey: string;
49
+ };
50
+ export type ReplicaIndexPlanRegistration = {
51
+ readonly id: string;
52
+ dispose(): void;
53
+ };
54
+ export interface ReplicaIndexMaintenanceRegistry {
55
+ registerOperation<TData, TVariables extends GraphqlVariables>(artifact: ReplicaOperationArtifact<TData, TVariables>, variables: TVariables): ReplicaIndexPlanRegistration;
56
+ evaluate(snapshot: ReplicaIndexMaintenanceSnapshot, layers: readonly ReplicaIndexSemanticLayer[], trustedPresets?: readonly DistributedTrustedPreset[]): readonly ReplicaIndexMaintenanceDecision[];
57
+ clear(): void;
58
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ /** Index maintenance registry and plan evaluation; implementation in ./index-maintenance/. */
2
+ export { createReplicaIndexMaintenanceRegistry, formatReplicaIndexStaleReason } from './index-maintenance/index.js';
3
+ export type { ReplicaIndexDependencyChange, ReplicaIndexMaintenanceDecision, ReplicaIndexMaintenanceIndex, ReplicaIndexMaintenanceReason, ReplicaIndexMaintenanceReasonCode, ReplicaIndexMaintenanceRecord, ReplicaIndexMaintenanceRegistry, ReplicaIndexMaintenanceSnapshot, ReplicaIndexPlanRegistration, ReplicaIndexRecordChange, ReplicaIndexRelationshipChange, ReplicaIndexSemanticChange, ReplicaIndexSemanticLayer } from './index-maintenance/index.js';
@@ -0,0 +1,2 @@
1
+ /** Index maintenance registry and plan evaluation; implementation in ./index-maintenance/. */
2
+ export { createReplicaIndexMaintenanceRegistry, formatReplicaIndexStaleReason } from './index-maintenance/index.js';
@@ -0,0 +1,17 @@
1
+ export { createDistributedReplica } from './distributed-replica.js';
2
+ export { createReplicaDevelopmentCapability, createReplicaDiagnostics, inspectReplicaCommandArtifact, inspectReplicaOperationArtifact } from './diagnostics.js';
3
+ export type { ReplicaArtifactSourceLocation, ReplicaCommandArtifactInspection, ReplicaCommandEffectInspection, ReplicaDevelopmentCapability, ReplicaDiagnosticEvent, ReplicaDiagnosticEventInput, ReplicaDiagnosticFieldValueContext, ReplicaDiagnosticFieldValuePolicy, ReplicaDiagnosticIndex, ReplicaDiagnosticIndexInput, ReplicaDiagnosticLayer, ReplicaDiagnosticLayerInput, ReplicaDiagnosticReceipt, ReplicaDiagnosticReceiptExpectationInput, ReplicaDiagnosticReceiptInput, ReplicaDiagnosticRecord, ReplicaDiagnosticRecordInput, ReplicaDiagnosticReasonContext, ReplicaDiagnosticReasonPolicy, ReplicaDiagnostics, ReplicaDiagnosticsOptions, ReplicaDiagnosticsSink, ReplicaDiagnosticsSnapshot, ReplicaDiagnosticScopeInput, ReplicaDiagnosticStateInput, ReplicaOperationArtifactInspection, ReplicaOperationIndexInspection, ReplicaOperationInjectedFieldInspection } from './diagnostics.js';
4
+ export { createReplicaGraphqlTransport } from './graphql-transport.js';
5
+ export type { ReplicaGraphqlTransport, ReplicaGraphqlTransportOptions } from './graphql-transport.js';
6
+ export { canonicalizeOperationVariables, replicaIndexKey, replicaRecordKey } from './identity.js';
7
+ export { prepareReplicaCommand, ReplicaCommandContractError, verifyReplicaCommandReceipt } from './commands.js';
8
+ export { createReplicaCommandRuntime, ReplicaCommandRuntimeError } from './command-runtime.js';
9
+ export { createReplicaIndexedDbPersistence, REPLICA_OFFLINE_COMMAND_OUTBOX_SUPPORTED } from './persistence.js';
10
+ export type { ReplicaBoundCommand, ReplicaBoundCommands, ReplicaCommandCallOptions, ReplicaCommandProjectedOutcome, ReplicaCommandReceipt, ReplicaCommandRecoveryReceipt, ReplicaCommandRuntime, ReplicaCommandRuntimeErrorCode, ReplicaCommandRuntimeOptions, ReplicaCommandStatus, ReplicaCommandStatusArtifact, ReplicaCommandStatusRequest, ReplicaCommandTransport, ReplicaCommandTransportRequest, ReplicaCommandTransportResult } from './command-runtime.js';
11
+ export type { ReplicaIndexedDbFactory, ReplicaIndexedDbPersistence, ReplicaIndexedDbPersistenceOptions, ReplicaPersistenceModelPolicy, ReplicaPersistencePolicy } from './persistence.js';
12
+ export type { PrepareReplicaCommandOptions, ReplicaCommandArtifact, ReplicaCommandConfirmation, ReplicaCommandConfirmations, ReplicaCommandContractErrorCode, ReplicaCommandDirectProjection, ReplicaCommandEffect, ReplicaCommandEffectExpression, ReplicaCommandEffectField, ReplicaCommandEffectKey, ReplicaCommandEffectRelationship, ReplicaCommandEffects, ReplicaCommandGenerators, ReplicaCommandInputDefault, ReplicaCommandInputDefaults, ReplicaCommandRevalidationPlan, ReplicaCommandScalarCodec, ReplicaCommandShape, ReplicaCommandTypeDefinition, ReplicaCommandTypeField, ReplicaCommandVariables, ReplicaTrustedPresetDescriptor, ReplicaPreparedCommand, ReplicaPreparedCommandEffect, ReplicaPreparedConfirmation, ReplicaPreparedConfirmations, ReplicaPreparedEffectField, ReplicaPreparedEffectKey, ReplicaReceiptVerification } from './commands.js';
13
+ export { compareReplicaOrder, decideReplicaPaginationMaintenance, evaluateReplicaFilter } from './query-plan.js';
14
+ export { createReplicaIndexMaintenanceRegistry, formatReplicaIndexStaleReason } from './index-maintenance.js';
15
+ export type { ReplicaIndexDependencyChange, ReplicaIndexMaintenanceDecision, ReplicaIndexMaintenanceIndex, ReplicaIndexMaintenanceReason, ReplicaIndexMaintenanceReasonCode, ReplicaIndexMaintenanceRecord, ReplicaIndexMaintenanceRegistry, ReplicaIndexMaintenanceSnapshot, ReplicaIndexPlanRegistration, ReplicaIndexRecordChange, ReplicaIndexRelationshipChange, ReplicaIndexSemanticChange, ReplicaIndexSemanticLayer } from './index-maintenance.js';
16
+ export type { ReplicaFilterEvaluation, ReplicaFilterEvaluationOptions, ReplicaOrderComparison, ReplicaPaginationChange, ReplicaPaginationMaintenanceDecision, ReplicaQueryPlanPath, ReplicaQueryPlanReason, ReplicaQueryPlanReasonCode, ReplicaRelationshipFilterRequest } from './query-plan.js';
17
+ export type { DistributedReplicaOptions, DistributedReplica, ReplicaArgumentsArtifact, ReplicaArgumentValue, ReplicaAuthoritativeScope, ReplicaBaseWriter, ReplicaBranchSemantic, ReplicaClientSurface, ReplicaCoverageArtifact, ReplicaDehydratedState, ReplicaFilterArtifact, ReplicaFilterExpression, ReplicaFilterFieldArtifact, ReplicaFilterLiteral, ReplicaFilterOperand, ReplicaFilterOperator, ReplicaIdentity, ReplicaIndexCoverage, ReplicaIndexInspection, ReplicaIndexTarget, ReplicaListValue, ReplicaLiveObserver, ReplicaLiveState, ReplicaLiteralValue, ReplicaModelArtifact, ReplicaObjectBranch, ReplicaObjectMember, ReplicaObjectSelection, ReplicaObjectValue, ReplicaOperationArtifact, ReplicaOperationSourceLocation, ReplicaOperationProtocol, ReplicaOrderArtifact, ReplicaOrderFieldArtifact, ReplicaOrderTieBreakerArtifact, ReplicaOptimisticWriter, ReplicaPaginationArtifact, ReplicaPaginationDisposition, ReplicaProtocolOperationArtifact, ReplicaRecordInspection, ReplicaRecordPatch, ReplicaRevalidationPlan, ReplicaRevalidationRelationship, ReplicaRevision, ReplicaRelationshipArtifact, ReplicaRelationshipKeyMapping, ReplicaRelationshipKind, ReplicaResultEnvelope, ReplicaRowPolicyArtifact, ReplicaRootSelection, ReplicaScalarSelection, ReplicaSelectionStorage, ReplicaSparse, ReplicaSnapshot, ReplicaStatus, ReplicaTransport, ReplicaTransportRequest, ReplicaVariableValue, ReplicaVariableCodecArtifact, ReplicaVariableEnumInputRef, ReplicaVariableFilterInputDefinition, ReplicaVariableFilterInputField, ReplicaVariableFilterInputRelationship, ReplicaVariableFilterInputTarget, ReplicaVariableInputDefinition, ReplicaVariableInputRef, ReplicaVariableListInputRef, ReplicaVariableNamedInputRef, ReplicaVariableOrderInputDefinition, ReplicaVariableOrderInputField, ReplicaVariableScalarInputRef, ReplicaValue, ReplicaWatch, ReplicaWriteSource, WatchReplicaOptions } from './types.js';
@@ -0,0 +1,9 @@
1
+ export { createDistributedReplica } from './distributed-replica.js';
2
+ export { createReplicaDevelopmentCapability, createReplicaDiagnostics, inspectReplicaCommandArtifact, inspectReplicaOperationArtifact } from './diagnostics.js';
3
+ export { createReplicaGraphqlTransport } from './graphql-transport.js';
4
+ export { canonicalizeOperationVariables, replicaIndexKey, replicaRecordKey } from './identity.js';
5
+ export { prepareReplicaCommand, ReplicaCommandContractError, verifyReplicaCommandReceipt } from './commands.js';
6
+ export { createReplicaCommandRuntime, ReplicaCommandRuntimeError } from './command-runtime.js';
7
+ export { createReplicaIndexedDbPersistence, REPLICA_OFFLINE_COMMAND_OUTBOX_SUPPORTED } from './persistence.js';
8
+ export { compareReplicaOrder, decideReplicaPaginationMaintenance, evaluateReplicaFilter } from './query-plan.js';
9
+ export { createReplicaIndexMaintenanceRegistry, formatReplicaIndexStaleReason } from './index-maintenance.js';
@@ -0,0 +1,10 @@
1
+ import type { CacheReader } from '../internal/cache-engine.js';
2
+ import type { GraphqlVariables } from '../types.js';
3
+ import type { ReplicaOperationArtifact, ReplicaSparse } from './types.js';
4
+ export type MaterializedReplicaResult<TData> = {
5
+ readonly data: ReplicaSparse<TData>;
6
+ readonly complete: boolean;
7
+ readonly stale: boolean;
8
+ readonly identitySignature: string;
9
+ };
10
+ export declare function materializeReplicaOperation<TData, TVariables extends GraphqlVariables>(reader: CacheReader, artifact: ReplicaOperationArtifact<TData, TVariables>, variables: TVariables): MaterializedReplicaResult<TData>;
@@ -0,0 +1,163 @@
1
+ import { replicaIndexKey, resolveArguments } from './identity.js';
2
+ import { runtimeRoot } from './selection.js';
3
+ export function materializeReplicaOperation(reader, artifact, variables) {
4
+ const output = {};
5
+ let complete = true;
6
+ let stale = false;
7
+ const signatures = [];
8
+ for (const artifactRoot of artifact.roots) {
9
+ const root = runtimeRoot(artifactRoot);
10
+ const argumentsValue = resolveArguments(root.arguments, variables, root.coverage);
11
+ const indexKey = replicaIndexKey({ field: root.field, arguments: argumentsValue });
12
+ const index = reader.index(indexKey);
13
+ const branch = materializeBranch(reader, root, index, variables);
14
+ if (branch.present) {
15
+ defineOutputValue(output, root.responseKey, branch.value);
16
+ }
17
+ complete &&= branch.complete;
18
+ stale ||= branch.stale;
19
+ signatures.push(`${indexKey}:${branch.identitySignature}`);
20
+ }
21
+ return Object.freeze({
22
+ data: Object.freeze(output),
23
+ complete,
24
+ stale,
25
+ identitySignature: signatures.join('|')
26
+ });
27
+ }
28
+ function materializeBranch(reader, selection, index, variables) {
29
+ if (!index || !index.metadata) {
30
+ return {
31
+ present: false,
32
+ complete: false,
33
+ stale: false,
34
+ identitySignature: 'missing-index'
35
+ };
36
+ }
37
+ const stale = index.metadata.staleReason !== undefined;
38
+ /*
39
+ * Completeness and freshness are independent. A stale complete index still
40
+ * has a structurally materializable result and remains visible during
41
+ * stale-while-revalidate. Partial/lifecycle-invalidated indexes explicitly
42
+ * carry `complete=false` and remain sparse.
43
+ */
44
+ const indexComplete = index.complete;
45
+ if (index.metadata.nullValue) {
46
+ return {
47
+ value: null,
48
+ present: true,
49
+ complete: indexComplete && selection.nullable,
50
+ stale,
51
+ identitySignature: `null:${index.metadata.staleReason ?? ''}`
52
+ };
53
+ }
54
+ if (selection.cardinality === 'one') {
55
+ const key = index.records[0];
56
+ if (key === undefined) {
57
+ return {
58
+ present: false,
59
+ complete: false,
60
+ stale,
61
+ identitySignature: `missing-record:${index.metadata.staleReason ?? ''}`
62
+ };
63
+ }
64
+ const object = materializeObject(reader, selection.selection, key, variables);
65
+ return {
66
+ value: object.value,
67
+ present: object.value !== undefined,
68
+ complete: indexComplete && index.records.length === 1 && object.complete,
69
+ stale: stale || object.stale,
70
+ identitySignature: object.identitySignature
71
+ };
72
+ }
73
+ const values = [];
74
+ let childrenComplete = true;
75
+ let childrenStale = false;
76
+ const signatures = [];
77
+ for (const key of index.records) {
78
+ const object = materializeObject(reader, selection.selection, key, variables);
79
+ if (object.value !== undefined)
80
+ values.push(object.value);
81
+ else
82
+ childrenComplete = false;
83
+ childrenComplete &&= object.complete;
84
+ childrenStale ||= object.stale;
85
+ signatures.push(object.identitySignature);
86
+ }
87
+ return {
88
+ value: Object.freeze(values),
89
+ present: true,
90
+ complete: indexComplete && childrenComplete,
91
+ stale: stale || childrenStale,
92
+ identitySignature: signatures.join(',')
93
+ };
94
+ }
95
+ function materializeObject(reader, selection, key, variables) {
96
+ const record = reader.recordMeta(key);
97
+ if (!record) {
98
+ return {
99
+ complete: false,
100
+ stale: false,
101
+ identitySignature: `${key}:missing`
102
+ };
103
+ }
104
+ const output = {};
105
+ let complete = true;
106
+ let stale = false;
107
+ const nestedSignatures = [];
108
+ for (const member of selection.members) {
109
+ if (member.kind !== 'scalar')
110
+ continue;
111
+ const presence = reader.field(key, member.field);
112
+ if (!presence.present || (presence.value === null && !member.nullable)) {
113
+ complete = false;
114
+ continue;
115
+ }
116
+ if (member.expose !== false) {
117
+ defineOutputValue(output, member.responseKey, presence.value);
118
+ }
119
+ }
120
+ for (const member of selection.members) {
121
+ if (member.kind !== 'branch')
122
+ continue;
123
+ const branchResult = materializeNestedBranch(reader, key, record.incarnation, member, variables);
124
+ if (member.expose !== false && branchResult.present) {
125
+ defineOutputValue(output, member.responseKey, branchResult.value);
126
+ }
127
+ complete &&= branchResult.complete;
128
+ stale ||= branchResult.stale;
129
+ nestedSignatures.push(`${member.field}:${branchResult.identitySignature}`);
130
+ }
131
+ return {
132
+ value: Object.freeze(output),
133
+ complete,
134
+ stale,
135
+ identitySignature: `${key}@${record.incarnation}[${nestedSignatures.join('|')}]`
136
+ };
137
+ }
138
+ function materializeNestedBranch(reader, parentKey, parentIncarnation, selection, variables) {
139
+ const argumentsValue = resolveArguments(selection.arguments, variables, selection.coverage);
140
+ const indexKey = replicaIndexKey({
141
+ parent: parentKey,
142
+ field: selection.field,
143
+ arguments: argumentsValue
144
+ });
145
+ const index = reader.index(indexKey);
146
+ if (index?.metadata?.parentIncarnation !== parentIncarnation) {
147
+ return {
148
+ present: false,
149
+ complete: false,
150
+ stale: index !== undefined,
151
+ identitySignature: `parent-incarnation-mismatch:${parentIncarnation}`
152
+ };
153
+ }
154
+ return materializeBranch(reader, selection, index, variables);
155
+ }
156
+ function defineOutputValue(output, key, value) {
157
+ Object.defineProperty(output, key, {
158
+ value,
159
+ enumerable: true,
160
+ configurable: false,
161
+ writable: false
162
+ });
163
+ }
@@ -0,0 +1,27 @@
1
+ import type { BaseCacheWriter, CacheValue } from '../internal/cache-engine.js';
2
+ import type { DistributedRecordRevision } from '../protocol.js';
3
+ import type { GraphqlVariables } from '../types.js';
4
+ import type { ReplicaOperationArtifact, ReplicaRevision, ReplicaResultEnvelope } from './types.js';
5
+ export type ReplicaNormalizationSummary = {
6
+ readonly wrote: boolean;
7
+ readonly partial: boolean;
8
+ readonly indexKeys: readonly string[];
9
+ };
10
+ export type ReplicaProtocolRecordResolution = {
11
+ readonly evidence: DistributedRecordRevision;
12
+ /** False means a same-scope newer base record already won. */
13
+ readonly apply: boolean;
14
+ };
15
+ export type ReplicaNormalizationProtocol = {
16
+ readonly indexRevision: ReplicaRevision;
17
+ readonly writeIndexes: boolean;
18
+ readonly indexesComplete: boolean;
19
+ /**
20
+ * Missing causal record evidence may use operation-local snapshot storage.
21
+ * Such rows remain renderable without impersonating a shared normalized
22
+ * identity.
23
+ */
24
+ readonly allowSnapshotOnlyRecords: boolean;
25
+ readonly record: (path: readonly string[], model: string, key: string, fields: Readonly<Record<string, CacheValue>>) => ReplicaProtocolRecordResolution | undefined;
26
+ };
27
+ export declare function normalizeReplicaResult<TData, TVariables extends GraphqlVariables>(writer: BaseCacheWriter, artifact: ReplicaOperationArtifact<TData, TVariables>, variables: TVariables, envelope: ReplicaResultEnvelope<TData>, protocol: ReplicaNormalizationProtocol): ReplicaNormalizationSummary;
@@ -0,0 +1,298 @@
1
+ import { cloneJsonValue, coverageFromArtifact, replicaIndexKey, replicaRecordKey, resolveArguments } from './identity.js';
2
+ import { embeddedRecordKey, runtimeRoot } from './selection.js';
3
+ import { deepEqual } from '../lib/deep-equal.js';
4
+ export function normalizeReplicaResult(writer, artifact, variables, envelope, protocol) {
5
+ validateArtifact(artifact);
6
+ const snapshotRevision = protocol.indexRevision;
7
+ const errors = collectErrorPaths(envelope.errors ?? []);
8
+ if (errors.global || envelope.data === undefined) {
9
+ return Object.freeze({ wrote: false, partial: errors.global, indexKeys: [] });
10
+ }
11
+ if (envelope.data === null && (envelope.errors?.length ?? 0) > 0) {
12
+ // `data: null` is a valid GraphQL error result after non-null propagation.
13
+ // The ingress coordinator will stale the operation roots without replacing
14
+ // the last known-good memberships.
15
+ return Object.freeze({ wrote: false, partial: true, indexKeys: [] });
16
+ }
17
+ if (envelope.data === null || !isObject(envelope.data)) {
18
+ throw new TypeError(`operation ${artifact.id} returned a non-object GraphQL data value`);
19
+ }
20
+ let wrote = false;
21
+ let partial = false;
22
+ const indexKeys = [];
23
+ for (const artifactRoot of artifact.roots) {
24
+ const root = runtimeRoot(artifactRoot);
25
+ const path = [root.responseKey];
26
+ const hasValue = Object.prototype.hasOwnProperty.call(envelope.data, root.responseKey);
27
+ const blocked = pathBlocked(errors, path);
28
+ const argumentsValue = resolveArguments(root.arguments, variables, root.coverage);
29
+ const key = replicaIndexKey({ field: root.field, arguments: argumentsValue });
30
+ const hasErrors = pathHasErrors(errors, path);
31
+ const rawValue = hasValue ? envelope.data[root.responseKey] : undefined;
32
+ if (blocked || !hasValue || (rawValue === null && hasErrors)) {
33
+ wrote =
34
+ protocol.writeIndexes
35
+ ? writer.markIndexStale(key, hasErrors ? 'graphql-partial-error' : 'incomplete-result', snapshotRevision) || wrote
36
+ : wrote;
37
+ indexKeys.push(key);
38
+ partial = true;
39
+ continue;
40
+ }
41
+ const branch = normalizeBranch(writer, artifact.id, root, rawValue, path, key, snapshotRevision, variables, errors, protocol, indexKeys);
42
+ const rootPartial = branch.partial ||
43
+ hasErrors ||
44
+ !protocol.indexesComplete;
45
+ const metadata = indexMetadata(root, argumentsValue, branch, rootPartial, hasErrors);
46
+ if (protocol.writeIndexes &&
47
+ writer.writeIndex({
48
+ key,
49
+ revision: snapshotRevision,
50
+ records: branch.keys,
51
+ complete: !rootPartial,
52
+ metadata
53
+ })) {
54
+ wrote = true;
55
+ }
56
+ indexKeys.push(key);
57
+ partial ||= rootPartial;
58
+ }
59
+ return Object.freeze({
60
+ wrote,
61
+ partial,
62
+ indexKeys: Object.freeze(indexKeys)
63
+ });
64
+ }
65
+ function normalizeBranch(writer, artifactId, selection, value, path, indexKey, snapshotRevision, variables, errors, protocol, indexKeys) {
66
+ if (value === null) {
67
+ if (!selection.nullable && !pathHasErrors(errors, path)) {
68
+ throw new TypeError(`operation ${artifactId} returned null for non-null field ${pathLabel(path)}`);
69
+ }
70
+ return { keys: [], nullValue: true, partial: false };
71
+ }
72
+ if (value === undefined)
73
+ return { keys: [], nullValue: false, partial: true };
74
+ if (selection.cardinality === 'one') {
75
+ const object = normalizeObject(writer, artifactId, selection.selection, value, path, indexKey, undefined, snapshotRevision, variables, errors, protocol, indexKeys);
76
+ return {
77
+ keys: object.key === undefined ? [] : [object.key],
78
+ nullValue: false,
79
+ partial: object.partial
80
+ };
81
+ }
82
+ if (!Array.isArray(value)) {
83
+ throw new TypeError(`operation ${artifactId} returned a non-list value for ${pathLabel(path)}`);
84
+ }
85
+ const keys = [];
86
+ let partial = false;
87
+ for (const [ordinal, entry] of value.entries()) {
88
+ const entryPath = [...path, ordinal];
89
+ if (entry === null || entry === undefined) {
90
+ if (pathHasErrors(errors, entryPath)) {
91
+ partial = true;
92
+ continue;
93
+ }
94
+ throw new TypeError(`operation ${artifactId} returned null for non-null list item ${pathLabel(entryPath)}`);
95
+ }
96
+ const object = normalizeObject(writer, artifactId, selection.selection, entry, entryPath, indexKey, ordinal, snapshotRevision, variables, errors, protocol, indexKeys);
97
+ if (object.key === undefined)
98
+ partial = true;
99
+ else
100
+ keys.push(object.key);
101
+ partial ||= object.partial;
102
+ }
103
+ return { keys, nullValue: false, partial };
104
+ }
105
+ function normalizeObject(writer, artifactId, selection, value, path, enclosingIndexKey, ordinal, snapshotRevision, variables, errors, protocol, indexKeys) {
106
+ if (pathBlocked(errors, path))
107
+ return { partial: true };
108
+ if (!isObject(value)) {
109
+ throw new TypeError(`operation ${artifactId} returned a non-object value for ${pathLabel(path)}`);
110
+ }
111
+ const fields = Object.create(null);
112
+ let partial = false;
113
+ for (const member of selection.members) {
114
+ if (member.kind !== 'scalar')
115
+ continue;
116
+ const fieldPath = [...path, member.responseKey];
117
+ const hasValue = Object.prototype.hasOwnProperty.call(value, member.responseKey);
118
+ const rawValue = hasValue ? value[member.responseKey] : undefined;
119
+ if (pathBlocked(errors, fieldPath) ||
120
+ !hasValue) {
121
+ partial = true;
122
+ continue;
123
+ }
124
+ if (rawValue === null && !member.nullable) {
125
+ if (pathHasErrors(errors, fieldPath)) {
126
+ partial = true;
127
+ continue;
128
+ }
129
+ throw new TypeError(`operation ${artifactId} returned null for non-null field ${pathLabel(fieldPath)}`);
130
+ }
131
+ const next = cloneJsonValue(rawValue);
132
+ if (Object.prototype.hasOwnProperty.call(fields, member.field)) {
133
+ if (!deepEqual(fields[member.field], next)) {
134
+ throw new TypeError(`operation aliases disagree for ${selection.typename}.${member.field}`);
135
+ }
136
+ continue;
137
+ }
138
+ fields[member.field] = next;
139
+ }
140
+ let key;
141
+ let revision;
142
+ let incarnation;
143
+ let resolution;
144
+ if (selection.storage.kind === 'normalized') {
145
+ const identity = [];
146
+ for (const field of selection.storage.identityFields) {
147
+ if (!Object.prototype.hasOwnProperty.call(fields, field) ||
148
+ fields[field] === null) {
149
+ return { partial: true };
150
+ }
151
+ identity.push(fields[field]);
152
+ }
153
+ key = replicaRecordKey({
154
+ id: selection.storage.model,
155
+ identityFields: selection.storage.identityFields
156
+ }, identity);
157
+ resolution = protocol.record(path.map(String), selection.storage.model, key, fields);
158
+ if (resolution === undefined) {
159
+ if (!protocol.allowSnapshotOnlyRecords) {
160
+ return { key, partial: true };
161
+ }
162
+ /*
163
+ * This row came from an exact authorized query, but the selected
164
+ * surface has no safely comparable record clock for its model.
165
+ * Scope the storage to this operation/index position so a later
166
+ * snapshot can replace it without corrupting causally normalized
167
+ * state shared by another operation.
168
+ */
169
+ key = embeddedRecordKey(artifactId, enclosingIndexKey, ordinal);
170
+ revision = snapshotRevision;
171
+ incarnation = snapshotRevision;
172
+ }
173
+ else {
174
+ if (resolution.evidence.tombstone) {
175
+ throw new TypeError('live GraphQL row carries tombstone record evidence');
176
+ }
177
+ revision = resolution.evidence.revision;
178
+ incarnation = resolution.evidence.incarnation;
179
+ }
180
+ }
181
+ else {
182
+ // Embedded output is an operation-local replacement snapshot, not a
183
+ // normalized server record. Its synthetic incarnation deliberately
184
+ // advances with the enclosing response so removed sparse fields disappear.
185
+ key = embeddedRecordKey(artifactId, enclosingIndexKey, ordinal);
186
+ revision = snapshotRevision;
187
+ incarnation = snapshotRevision;
188
+ }
189
+ if (resolution?.apply !== false) {
190
+ writer.writeRecord({
191
+ key,
192
+ revision,
193
+ ...(incarnation === undefined ? {} : { incarnation }),
194
+ fields
195
+ });
196
+ }
197
+ const storedClock = writer.recordClock(key);
198
+ if (storedClock === undefined ||
199
+ storedClock.tombstoned ||
200
+ (resolution?.apply !== false &&
201
+ (storedClock.revision !== String(revision) ||
202
+ (incarnation !== undefined &&
203
+ storedClock.incarnation !== String(incarnation))))) {
204
+ return { partial: true };
205
+ }
206
+ for (const member of selection.members) {
207
+ if (member.kind !== 'branch')
208
+ continue;
209
+ const branchPath = [...path, member.responseKey];
210
+ const hasValue = Object.prototype.hasOwnProperty.call(value, member.responseKey);
211
+ const blocked = pathBlocked(errors, branchPath);
212
+ const hasErrors = pathHasErrors(errors, branchPath);
213
+ const rawValue = hasValue ? value[member.responseKey] : undefined;
214
+ const argumentsValue = resolveArguments(member.arguments, variables, member.coverage);
215
+ const branchIndexKey = replicaIndexKey({
216
+ parent: key,
217
+ field: member.field,
218
+ arguments: argumentsValue
219
+ });
220
+ indexKeys.push(branchIndexKey);
221
+ if (!hasValue || blocked || (rawValue === null && hasErrors)) {
222
+ if (protocol.writeIndexes) {
223
+ writer.markIndexStale(branchIndexKey, hasErrors ? 'graphql-partial-error' : 'incomplete-result', snapshotRevision);
224
+ }
225
+ partial = true;
226
+ continue;
227
+ }
228
+ const branch = normalizeBranch(writer, artifactId, member, rawValue, branchPath, branchIndexKey, snapshotRevision, variables, errors, protocol, indexKeys);
229
+ const branchPartial = branch.partial ||
230
+ hasErrors ||
231
+ !protocol.indexesComplete;
232
+ if (protocol.writeIndexes) {
233
+ writer.writeIndex({
234
+ key: branchIndexKey,
235
+ revision: snapshotRevision,
236
+ records: branch.keys,
237
+ complete: !branchPartial,
238
+ metadata: indexMetadata(member, argumentsValue, branch, branchPartial, hasErrors, key, storedClock.revision)
239
+ });
240
+ }
241
+ partial ||= branchPartial;
242
+ }
243
+ return { key, partial };
244
+ }
245
+ function indexMetadata(selection, argumentsValue, branch, partial, hasErrors, parent, parentRevision) {
246
+ return Object.freeze({
247
+ ...(parent === undefined ? {} : { parent }),
248
+ ...(parentRevision === undefined ? {} : { parentRevision: String(parentRevision) }),
249
+ field: selection.field,
250
+ arguments: argumentsValue,
251
+ coverage: coverageFromArtifact(selection.coverage, argumentsValue, branch.keys.length),
252
+ dependencies: Object.freeze([...new Set(selection.dependencies)].sort()),
253
+ ...(partial
254
+ ? { staleReason: hasErrors ? 'graphql-partial-error' : 'incomplete-result' }
255
+ : {}),
256
+ nullValue: branch.nullValue
257
+ });
258
+ }
259
+ function collectErrorPaths(errors) {
260
+ const paths = [];
261
+ let global = false;
262
+ for (const error of errors) {
263
+ if (!Array.isArray(error.path) || error.path.length === 0) {
264
+ global = true;
265
+ continue;
266
+ }
267
+ paths.push(Object.freeze([...error.path]));
268
+ }
269
+ return { global, paths };
270
+ }
271
+ function pathBlocked(errors, path) {
272
+ return errors.global || errors.paths.some((errorPath) => isPrefix(errorPath, path));
273
+ }
274
+ function pathHasErrors(errors, path) {
275
+ return (errors.global ||
276
+ errors.paths.some((errorPath) => isPrefix(path, errorPath) || isPrefix(errorPath, path)));
277
+ }
278
+ function isPrefix(prefix, value) {
279
+ return (prefix.length <= value.length &&
280
+ prefix.every((entry, index) => entry === value[index]));
281
+ }
282
+ function validateArtifact(artifact) {
283
+ if (!artifact || typeof artifact !== 'object') {
284
+ throw new TypeError('replica artifact is required');
285
+ }
286
+ if (typeof artifact.id !== 'string' || artifact.id.length === 0) {
287
+ throw new TypeError('replica artifact id must be a non-empty string');
288
+ }
289
+ if (!Array.isArray(artifact.roots) || artifact.roots.length === 0) {
290
+ throw new TypeError(`operation ${artifact.id} must contain at least one root selection`);
291
+ }
292
+ }
293
+ function pathLabel(path) {
294
+ return path.map(String).join('.');
295
+ }
296
+ function isObject(value) {
297
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
298
+ }