@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,463 @@
1
+ import { DIAGNOSTICS_BUNDLE_MARKER } from './types.js';
2
+ import { reportUnhandledError } from '../../lib/report.js';
3
+ import { inspectReplicaCommandArtifact, inspectReplicaOperationArtifact } from './inspect.js';
4
+ const reportUnhandledObserverError = reportUnhandledError;
5
+ const DEFAULT_MAX_EVENTS = 200;
6
+ const MAX_EVENTS = 10_000;
7
+ const MAX_VALUE_DEPTH = 64;
8
+ const MAX_REASON_LENGTH = 160;
9
+ const developmentCapabilities = new WeakSet();
10
+ export function createReplicaDevelopmentCapability() {
11
+ const capability = Object.freeze({ version: 1 });
12
+ developmentCapabilities.add(capability);
13
+ return capability;
14
+ }
15
+ /** Framework-neutral diagnostics store shared by every framework adapter. */
16
+ export function createReplicaDiagnostics(options = {}) {
17
+ return new ReplicaDiagnosticsImpl(options);
18
+ }
19
+ class ReplicaDiagnosticsImpl {
20
+ includeStructuralIdentities;
21
+ #maxEvents;
22
+ #now;
23
+ #reportObserverError;
24
+ #fieldValues;
25
+ #reasons;
26
+ #listeners = new Set();
27
+ #pseudonyms = new Map();
28
+ #operations = new Map();
29
+ #commands = new Map();
30
+ #scope = Object.freeze({
31
+ generation: 0,
32
+ established: false
33
+ });
34
+ #records = Object.freeze([]);
35
+ #indexes = Object.freeze([]);
36
+ #layers = Object.freeze([]);
37
+ #receipts = Object.freeze([]);
38
+ #events = [];
39
+ #sequence = 0;
40
+ #snapshotCache;
41
+ constructor(options) {
42
+ this.#maxEvents = boundedEventLimit(options.maxEvents);
43
+ this.#now = options.now ?? Date.now;
44
+ this.#reportObserverError =
45
+ options.onObserverError ?? reportUnhandledObserverError;
46
+ this.includeStructuralIdentities = validCapability(options.development);
47
+ if (options.fieldValues !== undefined) {
48
+ if (!validCapability(options.fieldValues.capability)) {
49
+ throw new TypeError('diagnostic field values require a development capability');
50
+ }
51
+ if (typeof options.fieldValues.allow !== 'function' ||
52
+ typeof options.fieldValues.redact !== 'function') {
53
+ throw new TypeError('diagnostic field values require explicit allow and redact functions');
54
+ }
55
+ this.#fieldValues = options.fieldValues;
56
+ }
57
+ if (options.reasons !== undefined) {
58
+ if (!validCapability(options.reasons.capability)) {
59
+ throw new TypeError('diagnostic reasons require a development capability');
60
+ }
61
+ if (typeof options.reasons.redact !== 'function') {
62
+ throw new TypeError('diagnostic reasons require an explicit redact function');
63
+ }
64
+ this.#reasons = options.reasons;
65
+ }
66
+ }
67
+ redactRecordValue(context, value) {
68
+ const policy = this.#fieldValues;
69
+ if (policy === undefined || !policy.allow(context))
70
+ return undefined;
71
+ const redacted = policy.redact(value, context);
72
+ return redacted === undefined
73
+ ? undefined
74
+ : cloneDiagnosticValue(redacted, 'diagnostic field value');
75
+ }
76
+ update(state) {
77
+ validateScope(state.scope);
78
+ if (state.scope.generation !== this.#scope.generation) {
79
+ this.#clearScopedState();
80
+ }
81
+ this.#scope = freezeScope(state.scope);
82
+ this.#records = Object.freeze(state.records
83
+ .map((record) => this.#record(record))
84
+ .sort((left, right) => left.key.localeCompare(right.key)));
85
+ this.#indexes = Object.freeze(state.indexes
86
+ .map((index) => this.#index(index))
87
+ .sort((left, right) => left.key.localeCompare(right.key)));
88
+ this.#layers = Object.freeze(state.layers
89
+ .map((layer) => this.#layer(layer))
90
+ .sort((left, right) => left.sequence - right.sequence));
91
+ this.#receipts = Object.freeze(state.receipts
92
+ .map((receipt) => this.#receipt(receipt))
93
+ .sort((left, right) => left.commandId.localeCompare(right.commandId)));
94
+ this.#snapshotCache = undefined;
95
+ this.#notify();
96
+ }
97
+ event(input) {
98
+ const at = this.#now();
99
+ if (!Number.isFinite(at)) {
100
+ throw new TypeError('diagnostic clock must return a finite number');
101
+ }
102
+ const event = this.#event(input, ++this.#sequence, at);
103
+ this.#events.push(event);
104
+ if (this.#events.length > this.#maxEvents) {
105
+ this.#events.splice(0, this.#events.length - this.#maxEvents);
106
+ }
107
+ this.#snapshotCache = undefined;
108
+ this.#notify();
109
+ }
110
+ operation(artifact) {
111
+ const inspection = inspectReplicaOperationArtifact(artifact);
112
+ this.#operations.set(inspection.id, inspection);
113
+ this.#snapshotCache = undefined;
114
+ this.#notify();
115
+ }
116
+ command(artifact) {
117
+ const inspection = inspectReplicaCommandArtifact(artifact);
118
+ this.#commands.set(inspection.name, inspection);
119
+ this.#snapshotCache = undefined;
120
+ this.#notify();
121
+ }
122
+ inspectOperation(artifact) {
123
+ const inspection = inspectReplicaOperationArtifact(artifact);
124
+ this.#operations.set(inspection.id, inspection);
125
+ this.#snapshotCache = undefined;
126
+ this.#notify();
127
+ return inspection;
128
+ }
129
+ inspectCommand(artifact) {
130
+ const inspection = inspectReplicaCommandArtifact(artifact);
131
+ this.#commands.set(inspection.name, inspection);
132
+ this.#snapshotCache = undefined;
133
+ this.#notify();
134
+ return inspection;
135
+ }
136
+ snapshot = () => {
137
+ const cached = this.#snapshotCache;
138
+ if (cached !== undefined)
139
+ return cached;
140
+ const snapshot = Object.freeze({
141
+ version: 1,
142
+ marker: DIAGNOSTICS_BUNDLE_MARKER,
143
+ mode: this.includeStructuralIdentities ? 'development' : 'redacted',
144
+ sequence: this.#sequence,
145
+ scope: this.#scope,
146
+ records: this.#records,
147
+ indexes: this.#indexes,
148
+ layers: this.#layers,
149
+ receipts: this.#receipts,
150
+ artifacts: Object.freeze({
151
+ operations: Object.freeze([...this.#operations.values()].sort((left, right) => left.id.localeCompare(right.id))),
152
+ commands: Object.freeze([...this.#commands.values()].sort((left, right) => left.name.localeCompare(right.name)))
153
+ }),
154
+ events: Object.freeze([...this.#events])
155
+ });
156
+ this.#snapshotCache = snapshot;
157
+ return snapshot;
158
+ };
159
+ getSnapshot = () => this.snapshot();
160
+ subscribe = (listener) => {
161
+ if (typeof listener !== 'function') {
162
+ throw new TypeError('diagnostic listener must be a function');
163
+ }
164
+ this.#listeners.add(listener);
165
+ try {
166
+ listener(this.snapshot());
167
+ }
168
+ catch (error) {
169
+ this.#listeners.delete(listener);
170
+ this.#report([error]);
171
+ }
172
+ return () => this.#listeners.delete(listener);
173
+ };
174
+ clear() {
175
+ this.#scope = Object.freeze({ generation: 0, established: false });
176
+ this.#clearScopedState();
177
+ this.#sequence = 0;
178
+ this.#snapshotCache = undefined;
179
+ this.#notify();
180
+ }
181
+ #clearScopedState() {
182
+ this.#records = Object.freeze([]);
183
+ this.#indexes = Object.freeze([]);
184
+ this.#layers = Object.freeze([]);
185
+ this.#receipts = Object.freeze([]);
186
+ this.#events = [];
187
+ this.#operations.clear();
188
+ this.#commands.clear();
189
+ this.#pseudonyms.clear();
190
+ this.#snapshotCache = undefined;
191
+ }
192
+ #record(input) {
193
+ const values = this.#fieldValues === undefined || input.values === undefined
194
+ ? undefined
195
+ : freezeValueRecord(input.values, 'diagnostic record values');
196
+ return Object.freeze({
197
+ key: this.#identifier('record', input.key),
198
+ ...(input.model === undefined ? {} : { model: input.model }),
199
+ revision: input.revision,
200
+ incarnation: input.incarnation,
201
+ tombstone: input.tombstone,
202
+ ...(input.tombstoneRevision === undefined
203
+ ? {}
204
+ : { tombstoneRevision: input.tombstoneRevision }),
205
+ presentFields: Object.freeze([...input.presentFields].sort()),
206
+ presentLinks: Object.freeze([...input.presentLinks].sort()),
207
+ ...(values === undefined ? {} : { values })
208
+ });
209
+ }
210
+ #index(input) {
211
+ const rawArguments = input.arguments ?? Object.freeze({});
212
+ const argumentsValue = this.includeStructuralIdentities && Object.keys(rawArguments).length > 0
213
+ ? freezeValueRecord(rawArguments, 'diagnostic index arguments')
214
+ : undefined;
215
+ const staleReason = input.staleReason === undefined
216
+ ? undefined
217
+ : this.#reason(input.staleReason, Object.freeze({
218
+ kind: 'index-stale',
219
+ indexKey: input.key
220
+ }), structuralStaleReason(input.staleReason));
221
+ return Object.freeze({
222
+ key: this.#identifier('index', input.key),
223
+ revision: input.revision,
224
+ ...(input.staleRevision === undefined
225
+ ? {}
226
+ : { staleRevision: input.staleRevision }),
227
+ records: Object.freeze(input.records.map((key) => this.#identifier('record', key))),
228
+ complete: input.complete,
229
+ deleted: input.deleted,
230
+ ...(input.field === undefined ? {} : { field: input.field }),
231
+ ...(input.parent === undefined
232
+ ? {}
233
+ : { parent: this.#identifier('record', input.parent) }),
234
+ argumentNames: Object.freeze([...(input.argumentNames ?? Object.keys(rawArguments))].sort()),
235
+ ...(argumentsValue === undefined ? {} : { arguments: argumentsValue }),
236
+ ...(input.coverage === undefined
237
+ ? {}
238
+ : { coverage: freezeCoverage(input.coverage) }),
239
+ dependencies: Object.freeze([...(input.dependencies ?? [])].sort()),
240
+ ...(staleReason === undefined ? {} : { staleReason }),
241
+ nullValue: input.nullValue === true
242
+ });
243
+ }
244
+ #layer(input) {
245
+ return Object.freeze({
246
+ id: this.#identifier('transaction', input.id),
247
+ sequence: input.sequence,
248
+ state: input.state,
249
+ recordChanges: input.recordChanges,
250
+ indexChanges: input.indexChanges,
251
+ semanticChanges: input.semanticChanges
252
+ });
253
+ }
254
+ #receipt(input) {
255
+ return Object.freeze({
256
+ commandId: this.#identifier('transaction', input.commandId),
257
+ state: input.state,
258
+ ...(input.consistency === undefined
259
+ ? {}
260
+ : { consistency: input.consistency }),
261
+ expectations: Object.freeze(input.expectations
262
+ .map((expectation) => Object.freeze({
263
+ projection: expectation.projection,
264
+ model: expectation.model,
265
+ observed: expectation.observed
266
+ }))
267
+ .sort((left, right) => `${left.projection}\0${left.model}`.localeCompare(`${right.projection}\0${right.model}`)))
268
+ });
269
+ }
270
+ #event(input, sequence, at) {
271
+ if (input.kind === 'layer') {
272
+ const reason = input.reason === undefined
273
+ ? undefined
274
+ : this.#reason(input.reason, Object.freeze({
275
+ kind: 'layer',
276
+ layerId: input.layer,
277
+ action: input.action
278
+ }), structuralLayerReason(input.reason));
279
+ return Object.freeze({
280
+ ...input,
281
+ layer: this.#identifier('transaction', input.layer),
282
+ ...(reason === undefined ? {} : { reason }),
283
+ sequence,
284
+ at
285
+ });
286
+ }
287
+ if (input.kind === 'receipt') {
288
+ return Object.freeze({
289
+ ...input,
290
+ command: this.#identifier('transaction', input.command),
291
+ sequence,
292
+ at
293
+ });
294
+ }
295
+ if (input.kind === 'index-decision') {
296
+ const reason = input.reason === undefined
297
+ ? undefined
298
+ : this.#reason(input.reason, Object.freeze({
299
+ kind: 'index-stale',
300
+ indexKey: input.index
301
+ }), structuralStaleReason(input.reason));
302
+ return Object.freeze({
303
+ ...input,
304
+ index: this.#identifier('index', input.index),
305
+ ...(reason === undefined ? {} : { reason }),
306
+ sequence,
307
+ at
308
+ });
309
+ }
310
+ return Object.freeze({ ...input, sequence, at });
311
+ }
312
+ #reason(value, context, fallback) {
313
+ const redacted = this.#reasons?.redact(value, context);
314
+ return redacted === undefined
315
+ ? fallback
316
+ : boundedDiagnosticReason(redacted, fallback);
317
+ }
318
+ #identifier(kind, value) {
319
+ if (this.includeStructuralIdentities)
320
+ return value;
321
+ let values = this.#pseudonyms.get(kind);
322
+ if (values === undefined) {
323
+ values = new Map();
324
+ this.#pseudonyms.set(kind, values);
325
+ }
326
+ let identifier = values.get(value);
327
+ if (identifier === undefined) {
328
+ identifier = `${kind}#${values.size + 1}`;
329
+ values.set(value, identifier);
330
+ }
331
+ return identifier;
332
+ }
333
+ #notify() {
334
+ if (this.#listeners.size === 0)
335
+ return;
336
+ const snapshot = this.snapshot();
337
+ const errors = [];
338
+ for (const listener of this.#listeners) {
339
+ try {
340
+ listener(snapshot);
341
+ }
342
+ catch (error) {
343
+ errors.push(error);
344
+ }
345
+ }
346
+ this.#report(errors);
347
+ }
348
+ #report(errors) {
349
+ if (errors.length === 0)
350
+ return;
351
+ try {
352
+ this.#reportObserverError(new AggregateError(errors, 'replica diagnostic listener failed'));
353
+ }
354
+ catch (reporterError) {
355
+ queueMicrotask(() => {
356
+ throw new AggregateError([...errors, reporterError], 'replica diagnostic error reporter failed');
357
+ });
358
+ }
359
+ }
360
+ }
361
+ function boundedEventLimit(value) {
362
+ if (value === undefined)
363
+ return DEFAULT_MAX_EVENTS;
364
+ if (!Number.isSafeInteger(value) || value < 1 || value > MAX_EVENTS) {
365
+ throw new TypeError(`diagnostic maxEvents must be an integer between 1 and ${MAX_EVENTS}`);
366
+ }
367
+ return value;
368
+ }
369
+ function structuralStaleReason(value) {
370
+ switch (value) {
371
+ case 'application-stale':
372
+ case 'graphql-error':
373
+ case 'graphql-partial-error':
374
+ case 'incomplete-result':
375
+ case 'record-lifecycle-changed':
376
+ case 'revision-conflict':
377
+ return value;
378
+ default: {
379
+ const queryPlan = /^query-plan:([a-z][a-z0-9_]{0,63})(?::.*)?$/.exec(value);
380
+ return queryPlan === null
381
+ ? 'application-stale'
382
+ : `query-plan:${queryPlan[1]}`;
383
+ }
384
+ }
385
+ }
386
+ function structuralLayerReason(value) {
387
+ return value === 'retired-earlier-layer' ||
388
+ value === 'rejected-earlier-layer'
389
+ ? value
390
+ : 'application-layer-change';
391
+ }
392
+ function boundedDiagnosticReason(value, fallback) {
393
+ if (typeof value !== 'string') {
394
+ throw new TypeError('diagnostic reason redactor must return a string');
395
+ }
396
+ const normalized = value
397
+ .replace(/[\u0000-\u001f\u007f]/g, '\ufffd')
398
+ .trim();
399
+ if (normalized.length === 0)
400
+ return fallback;
401
+ return [...normalized].slice(0, MAX_REASON_LENGTH).join('');
402
+ }
403
+ function validCapability(capability) {
404
+ return (capability !== undefined &&
405
+ typeof capability === 'object' &&
406
+ developmentCapabilities.has(capability));
407
+ }
408
+ function validateScope(scope) {
409
+ if (!Number.isSafeInteger(scope.generation) || scope.generation < 0) {
410
+ throw new TypeError('diagnostic scope generation must be an unsigned integer');
411
+ }
412
+ if (scope.established) {
413
+ if (scope.protocolVersion !== 1 || !nonempty(scope.schemaHash)) {
414
+ throw new TypeError('established diagnostic scope requires protocol and schema hash');
415
+ }
416
+ }
417
+ else if (scope.protocolVersion !== undefined || scope.schemaHash !== undefined) {
418
+ throw new TypeError('unestablished diagnostic scope cannot carry protocol identity');
419
+ }
420
+ }
421
+ function freezeScope(scope) {
422
+ return Object.freeze({
423
+ generation: scope.generation,
424
+ established: scope.established,
425
+ ...(scope.protocolVersion === undefined
426
+ ? {}
427
+ : { protocolVersion: scope.protocolVersion }),
428
+ ...(scope.schemaHash === undefined ? {} : { schemaHash: scope.schemaHash })
429
+ });
430
+ }
431
+ function freezeCoverage(coverage) {
432
+ return Object.freeze({ ...coverage });
433
+ }
434
+ function freezeValueRecord(value, description, depth = 0) {
435
+ const entries = Object.entries(value)
436
+ .sort(([left], [right]) => left.localeCompare(right))
437
+ .map(([key, entry]) => [
438
+ key,
439
+ cloneDiagnosticValue(entry, `${description}.${key}`, depth + 1)
440
+ ]);
441
+ return Object.freeze(Object.fromEntries(entries));
442
+ }
443
+ function cloneDiagnosticValue(value, description, depth = 0) {
444
+ if (depth > MAX_VALUE_DEPTH) {
445
+ throw new TypeError(`${description} exceeds diagnostic value depth`);
446
+ }
447
+ if (value === null ||
448
+ typeof value === 'string' ||
449
+ typeof value === 'boolean' ||
450
+ (typeof value === 'number' && Number.isFinite(value))) {
451
+ return value;
452
+ }
453
+ if (Array.isArray(value)) {
454
+ return Object.freeze(value.map((entry, index) => cloneDiagnosticValue(entry, `${description}[${index}]`, depth + 1)));
455
+ }
456
+ if (typeof value !== 'object') {
457
+ throw new TypeError(`${description} must be a JSON-compatible value`);
458
+ }
459
+ return freezeValueRecord(value, description, depth);
460
+ }
461
+ function nonempty(value) {
462
+ return typeof value === 'string' && value.length > 0;
463
+ }
@@ -0,0 +1,4 @@
1
+ /** Re-export surface for diagnostics modules (body-split). */
2
+ export * from './types.js';
3
+ export * from './inspect.js';
4
+ export * from './event-log.js';
@@ -0,0 +1,4 @@
1
+ /** Re-export surface for diagnostics modules (body-split). */
2
+ export * from './types.js';
3
+ export * from './inspect.js';
4
+ export * from './event-log.js';
@@ -0,0 +1,2 @@
1
+ export { createReplicaDevelopmentCapability, createReplicaDiagnostics, inspectReplicaCommandArtifact, inspectReplicaOperationArtifact } from './implementation.js';
2
+ 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 './implementation.js';
@@ -0,0 +1 @@
1
+ export { createReplicaDevelopmentCapability, createReplicaDiagnostics, inspectReplicaCommandArtifact, inspectReplicaOperationArtifact } from './implementation.js';
@@ -0,0 +1,6 @@
1
+ import type { GraphqlVariables } from '../../types.js';
2
+ import type { ReplicaCommandArtifact } from '../commands.js';
3
+ import type { ReplicaOperationArtifact } from '../types.js';
4
+ import type { ReplicaCommandArtifactInspection, ReplicaOperationArtifactInspection } from './types.js';
5
+ export declare function inspectReplicaOperationArtifact<TData, TVariables extends GraphqlVariables>(artifact: ReplicaOperationArtifact<TData, TVariables>): ReplicaOperationArtifactInspection;
6
+ export declare function inspectReplicaCommandArtifact<TInput, TOutput>(artifact: ReplicaCommandArtifact<TInput, TOutput>): ReplicaCommandArtifactInspection;
@@ -0,0 +1,170 @@
1
+ export function inspectReplicaOperationArtifact(artifact) {
2
+ const injected = [];
3
+ const dependencies = new Set();
4
+ const indexes = [];
5
+ for (const root of artifact.roots) {
6
+ const path = root.responseKey;
7
+ inspectRoot(root, path, injected, dependencies, indexes);
8
+ }
9
+ const source = safeArtifactSource(artifact.source);
10
+ return Object.freeze({
11
+ kind: 'operation',
12
+ id: artifact.id,
13
+ ...(source === undefined
14
+ ? {}
15
+ : {
16
+ source: Object.freeze({
17
+ path: source.path,
18
+ line: source.line,
19
+ column: source.column
20
+ })
21
+ }),
22
+ rootFields: Object.freeze(artifact.roots.map((root) => root.field)),
23
+ injectedFields: Object.freeze(injected),
24
+ dependencies: Object.freeze([...dependencies].sort()),
25
+ indexes: Object.freeze(indexes),
26
+ ...(artifact.live === undefined
27
+ ? {}
28
+ : { live: Object.freeze({ operation: artifact.live.id }) })
29
+ });
30
+ }
31
+ export function inspectReplicaCommandArtifact(artifact) {
32
+ const effects = artifact.effects.operations.map((effect) => {
33
+ const models = new Set();
34
+ const fields = new Set();
35
+ const sources = new Set();
36
+ if ('model' in effect)
37
+ models.add(effect.model);
38
+ if ('relationship' in effect) {
39
+ models.add(effect.relationship.sourceModel);
40
+ models.add(effect.relationship.targetModel);
41
+ fields.add(effect.relationship.field);
42
+ }
43
+ if ('key' in effect) {
44
+ for (const field of effect.key.fields) {
45
+ fields.add(field.field);
46
+ sources.add(expressionSource(field.value));
47
+ }
48
+ }
49
+ if ('source' in effect) {
50
+ for (const field of effect.source.fields) {
51
+ fields.add(field.field);
52
+ sources.add(expressionSource(field.value));
53
+ }
54
+ }
55
+ if ('target' in effect) {
56
+ for (const field of effect.target.fields) {
57
+ fields.add(field.field);
58
+ sources.add(expressionSource(field.value));
59
+ }
60
+ }
61
+ if ('fields' in effect) {
62
+ for (const field of effect.fields) {
63
+ fields.add(field.field);
64
+ sources.add(expressionSource(field.value));
65
+ }
66
+ }
67
+ return Object.freeze({
68
+ kind: effect.kind,
69
+ models: Object.freeze([...models].sort()),
70
+ fields: Object.freeze([...fields].sort()),
71
+ valueSources: Object.freeze([...sources].sort())
72
+ });
73
+ });
74
+ return Object.freeze({
75
+ kind: 'command',
76
+ name: artifact.name,
77
+ operation: artifact.operationHash,
78
+ consistency: artifact.consistency,
79
+ effects: Object.freeze(effects),
80
+ revalidation: Object.freeze({
81
+ required: artifact.revalidation.required,
82
+ dependencies: Object.freeze([...artifact.revalidation.dependencies].sort()),
83
+ models: Object.freeze([...artifact.revalidation.models].sort())
84
+ })
85
+ });
86
+ }
87
+ function inspectRoot(root, path, injected, dependencies, indexes) {
88
+ for (const dependency of root.dependencies)
89
+ dependencies.add(dependency);
90
+ indexes.push(Object.freeze({
91
+ path,
92
+ field: root.field,
93
+ cardinality: root.cardinality,
94
+ dependencies: Object.freeze([...root.dependencies].sort()),
95
+ ...(root.coverage === undefined
96
+ ? {}
97
+ : { coverage: root.coverage.kind }),
98
+ filtered: root.filter !== undefined,
99
+ ordered: root.order !== undefined,
100
+ ...(root.pagination === undefined
101
+ ? {}
102
+ : { pagination: root.pagination.kind })
103
+ }));
104
+ inspectSelection(root.selection, path, injected, dependencies, indexes);
105
+ }
106
+ function safeArtifactSource(source) {
107
+ if (source === undefined)
108
+ return undefined;
109
+ const path = source.path;
110
+ const driveAbsolute = path.length >= 2 && path[1] === ':';
111
+ if (path.length === 0 ||
112
+ path.length > 4_096 ||
113
+ /[\u0000-\u001f\u007f]/.test(path) ||
114
+ path.startsWith('/') ||
115
+ driveAbsolute ||
116
+ path.includes('\\') ||
117
+ path.split('/').includes('..') ||
118
+ (!path.endsWith('.graphql') && !path.endsWith('.gql')) ||
119
+ !Number.isSafeInteger(source.line) ||
120
+ source.line < 1 ||
121
+ !Number.isSafeInteger(source.column) ||
122
+ source.column < 1) {
123
+ return undefined;
124
+ }
125
+ return Object.freeze({
126
+ path,
127
+ line: source.line,
128
+ column: source.column
129
+ });
130
+ }
131
+ function inspectSelection(selection, path, injected, dependencies, indexes) {
132
+ for (const member of selection.members) {
133
+ const memberPath = `${path}.${member.responseKey}`;
134
+ if (member.kind === 'scalar') {
135
+ if (member.expose === false) {
136
+ injected.push(Object.freeze({
137
+ path: memberPath,
138
+ responseKey: member.responseKey,
139
+ field: member.field
140
+ }));
141
+ }
142
+ continue;
143
+ }
144
+ const indexDependencies = new Set([
145
+ ...member.dependencies,
146
+ ...(member.relationship?.dependencies ?? [])
147
+ ]);
148
+ for (const dependency of indexDependencies) {
149
+ dependencies.add(dependency);
150
+ }
151
+ indexes.push(Object.freeze({
152
+ path: memberPath,
153
+ field: member.field,
154
+ cardinality: member.cardinality,
155
+ dependencies: Object.freeze([...indexDependencies].sort()),
156
+ ...(member.coverage === undefined
157
+ ? {}
158
+ : { coverage: member.coverage.kind }),
159
+ filtered: member.filter !== undefined,
160
+ ordered: member.order !== undefined,
161
+ ...(member.pagination === undefined
162
+ ? {}
163
+ : { pagination: member.pagination.kind })
164
+ }));
165
+ inspectSelection(member.selection, memberPath, injected, dependencies, indexes);
166
+ }
167
+ }
168
+ function expressionSource(expression) {
169
+ return expression.kind;
170
+ }