@firtoz/collection-sync 4.0.0 → 6.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 (130) hide show
  1. package/README.md +46 -0
  2. package/dist/cache-manager.d.ts +52 -0
  3. package/dist/cache-manager.js +5 -0
  4. package/dist/cache-manager.js.map +1 -0
  5. package/dist/chunk-3EHHMLSV.js +57 -0
  6. package/dist/chunk-3EHHMLSV.js.map +1 -0
  7. package/dist/chunk-43KYAIKY.js +46 -0
  8. package/dist/chunk-43KYAIKY.js.map +1 -0
  9. package/dist/chunk-4BEXLBCH.js +64 -0
  10. package/dist/chunk-4BEXLBCH.js.map +1 -0
  11. package/dist/chunk-5V6BSQAB.js +148 -0
  12. package/dist/chunk-5V6BSQAB.js.map +1 -0
  13. package/dist/chunk-5VMFQT5Z.js +112 -0
  14. package/dist/chunk-5VMFQT5Z.js.map +1 -0
  15. package/dist/chunk-6EHROJFY.js +111 -0
  16. package/dist/chunk-6EHROJFY.js.map +1 -0
  17. package/dist/chunk-6X3434GJ.js +21 -0
  18. package/dist/chunk-6X3434GJ.js.map +1 -0
  19. package/dist/chunk-BGJH6PH2.js +175 -0
  20. package/dist/chunk-BGJH6PH2.js.map +1 -0
  21. package/dist/chunk-BJJEAKXL.js +252 -0
  22. package/dist/chunk-BJJEAKXL.js.map +1 -0
  23. package/dist/chunk-GWIOC5CP.js +51 -0
  24. package/dist/chunk-GWIOC5CP.js.map +1 -0
  25. package/dist/chunk-HMLY7DHA.js +12 -0
  26. package/dist/chunk-HMLY7DHA.js.map +1 -0
  27. package/dist/chunk-I6RJWBGF.js +112 -0
  28. package/dist/chunk-I6RJWBGF.js.map +1 -0
  29. package/dist/chunk-M5MJHS6A.js +10 -0
  30. package/dist/chunk-M5MJHS6A.js.map +1 -0
  31. package/dist/chunk-O3KBDCEI.js +615 -0
  32. package/dist/chunk-O3KBDCEI.js.map +1 -0
  33. package/dist/chunk-OP53UBPN.js +19 -0
  34. package/dist/chunk-OP53UBPN.js.map +1 -0
  35. package/dist/chunk-P3JOTUAB.js +802 -0
  36. package/dist/chunk-P3JOTUAB.js.map +1 -0
  37. package/dist/chunk-QJP4GSJH.js +373 -0
  38. package/dist/chunk-QJP4GSJH.js.map +1 -0
  39. package/dist/chunk-RDDS7JQW.js +623 -0
  40. package/dist/chunk-RDDS7JQW.js.map +1 -0
  41. package/dist/chunk-TEH7V76G.js +209 -0
  42. package/dist/chunk-TEH7V76G.js.map +1 -0
  43. package/dist/chunk-UJ24XW52.js +20 -0
  44. package/dist/chunk-UJ24XW52.js.map +1 -0
  45. package/dist/chunk-UVZJL6QV.js +18 -0
  46. package/dist/chunk-UVZJL6QV.js.map +1 -0
  47. package/dist/chunk-XC4QNFSQ.js +238 -0
  48. package/dist/chunk-XC4QNFSQ.js.map +1 -0
  49. package/dist/chunk-YD5LVGWX.js +125 -0
  50. package/dist/chunk-YD5LVGWX.js.map +1 -0
  51. package/dist/chunk-YYGPIHHJ.js +166 -0
  52. package/dist/chunk-YYGPIHHJ.js.map +1 -0
  53. package/dist/connect-partial-sync.d.ts +41 -0
  54. package/dist/connect-partial-sync.js +6 -0
  55. package/dist/connect-partial-sync.js.map +1 -0
  56. package/dist/connect-sync.d.ts +26 -0
  57. package/dist/connect-sync.js +5 -0
  58. package/dist/connect-sync.js.map +1 -0
  59. package/dist/create-partial-synced-collection.d.ts +24 -0
  60. package/dist/create-partial-synced-collection.js +8 -0
  61. package/dist/create-partial-synced-collection.js.map +1 -0
  62. package/dist/create-synced-collection.d.ts +26 -0
  63. package/dist/create-synced-collection.js +8 -0
  64. package/dist/create-synced-collection.js.map +1 -0
  65. package/dist/index.d.ts +18 -0
  66. package/dist/index.js +18 -0
  67. package/dist/index.js.map +1 -0
  68. package/dist/partial-sync-client-bridge.d.ts +157 -0
  69. package/dist/partial-sync-client-bridge.js +6 -0
  70. package/dist/partial-sync-client-bridge.js.map +1 -0
  71. package/dist/partial-sync-interest.d.ts +48 -0
  72. package/dist/partial-sync-interest.js +6 -0
  73. package/dist/partial-sync-interest.js.map +1 -0
  74. package/dist/partial-sync-mutation-handler.d.ts +31 -0
  75. package/dist/partial-sync-mutation-handler.js +6 -0
  76. package/dist/partial-sync-mutation-handler.js.map +1 -0
  77. package/dist/partial-sync-predicate-match.d.ts +8 -0
  78. package/dist/partial-sync-predicate-match.js +4 -0
  79. package/dist/partial-sync-predicate-match.js.map +1 -0
  80. package/dist/partial-sync-row-key.d.ts +41 -0
  81. package/dist/partial-sync-row-key.js +4 -0
  82. package/dist/partial-sync-row-key.js.map +1 -0
  83. package/dist/partial-sync-server-bridge.d.ts +102 -0
  84. package/dist/partial-sync-server-bridge.js +8 -0
  85. package/dist/partial-sync-server-bridge.js.map +1 -0
  86. package/dist/react/constants.d.ts +12 -0
  87. package/dist/react/constants.js +4 -0
  88. package/dist/react/constants.js.map +1 -0
  89. package/dist/react/index.d.ts +19 -0
  90. package/dist/react/index.js +17 -0
  91. package/dist/react/index.js.map +1 -0
  92. package/dist/react/partial-sync-adapter.d.ts +40 -0
  93. package/dist/react/partial-sync-adapter.js +4 -0
  94. package/dist/react/partial-sync-adapter.js.map +1 -0
  95. package/dist/react/partial-sync-utils.d.ts +42 -0
  96. package/dist/react/partial-sync-utils.js +5 -0
  97. package/dist/react/partial-sync-utils.js.map +1 -0
  98. package/dist/react/range-conditions-expression.d.ts +49 -0
  99. package/dist/react/range-conditions-expression.js +4 -0
  100. package/dist/react/range-conditions-expression.js.map +1 -0
  101. package/dist/react/types.d.ts +196 -0
  102. package/dist/react/types.js +3 -0
  103. package/dist/react/types.js.map +1 -0
  104. package/dist/react/usePartialSyncCollection.d.ts +20 -0
  105. package/dist/react/usePartialSyncCollection.js +10 -0
  106. package/dist/react/usePartialSyncCollection.js.map +1 -0
  107. package/dist/react/usePartialSyncViewport.d.ts +20 -0
  108. package/dist/react/usePartialSyncViewport.js +7 -0
  109. package/dist/react/usePartialSyncViewport.js.map +1 -0
  110. package/dist/react/usePartialSyncWindow.d.ts +17 -0
  111. package/dist/react/usePartialSyncWindow.js +12 -0
  112. package/dist/react/usePartialSyncWindow.js.map +1 -0
  113. package/dist/react/usePredicateFilteredRows.d.ts +20 -0
  114. package/dist/react/usePredicateFilteredRows.js +6 -0
  115. package/dist/react/usePredicateFilteredRows.js.map +1 -0
  116. package/dist/sync-client-bridge.d.ts +48 -0
  117. package/dist/sync-client-bridge.js +6 -0
  118. package/dist/sync-client-bridge.js.map +1 -0
  119. package/dist/sync-protocol.d.ts +378 -0
  120. package/dist/sync-protocol.js +4 -0
  121. package/dist/sync-protocol.js.map +1 -0
  122. package/dist/sync-server-bridge.d.ts +35 -0
  123. package/dist/sync-server-bridge.js +6 -0
  124. package/dist/sync-server-bridge.js.map +1 -0
  125. package/dist/with-sync.d.ts +107 -0
  126. package/dist/with-sync.js +7 -0
  127. package/dist/with-sync.js.map +1 -0
  128. package/package.json +27 -21
  129. package/src/connect-partial-sync.ts +16 -12
  130. package/src/connect-sync.ts +12 -10
@@ -0,0 +1,802 @@
1
+ import { DEFAULT_SYNC_COLLECTION_ID, createClientMutationId } from './chunk-BJJEAKXL.js';
2
+ import { partialSyncRowKey, partialSyncRowVersionWatermarkMs } from './chunk-UJ24XW52.js';
3
+ import { __privateAdd, __privateSet, __privateGet, __privateMethod } from './chunk-HMLY7DHA.js';
4
+ import { exhaustiveGuard } from '@firtoz/maybe-error';
5
+
6
+ function serverRowSupersedesLocal(local, server) {
7
+ const lm = partialSyncRowVersionWatermarkMs(local);
8
+ const sm = partialSyncRowVersionWatermarkMs(server);
9
+ if (sm > lm) return true;
10
+ if (sm < lm) return false;
11
+ try {
12
+ return JSON.stringify(local) !== JSON.stringify(server);
13
+ } catch {
14
+ return true;
15
+ }
16
+ }
17
+ var _connected, _state, _inFlightRequests, _inFlightReconcileRequests, _cachedIds, _cacheUtilization, _totalCount, _sendFn, _serverConfirmedKeys, _serverConfirmedKeysRevision, _confirmedRevisionListeners, _rangeFetchApplySerial, _pendingCoalescedUpdatesByKey, _PartialSyncClientBridge_instances, out_fn, scheduleRangeFetchApply_fn, exitFetchingAfterApplyFailure_fn, notifyConfirmedKeysRevision_fn, buildReconcileManifest_fn, handleRangePatch_fn, replaceServerConfirmedKeysFromRows_fn, prunePartialInterestTrackingAfterExitView_fn, mergeServerConfirmedKeysFromMessages_fn, isActiveRangeRequest_fn, handleQueryRangeChunk_fn, handleRangeUpToDate_fn, handleRangeDelta_fn, handleRangeReconcileResult_fn, refreshCachedCountInState_fn, drainPendingCoalescedUpdates_fn, receiveSyncAndTrack_fn, applyAndTrack_fn, setState_fn;
18
+ var PartialSyncClientBridge = class {
19
+ constructor(options) {
20
+ this.options = options;
21
+ __privateAdd(this, _PartialSyncClientBridge_instances);
22
+ __privateAdd(this, _connected, false);
23
+ __privateAdd(this, _state, { status: "offline" });
24
+ __privateAdd(this, _inFlightRequests, /* @__PURE__ */ new Map());
25
+ __privateAdd(this, _inFlightReconcileRequests, /* @__PURE__ */ new Map());
26
+ __privateAdd(this, _cachedIds, /* @__PURE__ */ new Set());
27
+ __privateAdd(this, _cacheUtilization, 0);
28
+ __privateAdd(this, _totalCount, 0);
29
+ __privateAdd(this, _sendFn);
30
+ /** Row keys last delivered by a completed server range response (see viewport `cacheDisplayMode`). */
31
+ __privateAdd(this, _serverConfirmedKeys, /* @__PURE__ */ new Set());
32
+ __privateAdd(this, _serverConfirmedKeysRevision, 0);
33
+ __privateAdd(this, _confirmedRevisionListeners, /* @__PURE__ */ new Set());
34
+ /**
35
+ * Ensures `queryRangeChunk` / `rangeDelta` handlers never overlap: concurrent
36
+ * {@link handleServerMessage} calls must not run `receiveSync` in parallel for range fetches.
37
+ */
38
+ __privateAdd(this, _rangeFetchApplySerial, Promise.resolve());
39
+ /**
40
+ * Plain `rangePatch` updates: merge by row key. `connectPartialSync` calls
41
+ * `flushPendingCoalescedInboundUpdates` after each inbound pump pass; call it yourself if you use
42
+ * the bridge without that helper.
43
+ */
44
+ __privateAdd(this, _pendingCoalescedUpdatesByKey, /* @__PURE__ */ new Map());
45
+ this.clientId = options.clientId ?? crypto.randomUUID();
46
+ this.collectionId = options.collectionId ?? DEFAULT_SYNC_COLLECTION_ID;
47
+ __privateSet(this, _sendFn, options.send);
48
+ }
49
+ get state() {
50
+ return __privateGet(this, _state);
51
+ }
52
+ get cachedCount() {
53
+ return __privateGet(this, _cachedIds).size;
54
+ }
55
+ setConnecting() {
56
+ __privateGet(this, _pendingCoalescedUpdatesByKey).clear();
57
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, { status: "connecting" });
58
+ }
59
+ setConnected(connected) {
60
+ __privateSet(this, _connected, connected);
61
+ if (!connected) {
62
+ __privateGet(this, _pendingCoalescedUpdatesByKey).clear();
63
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, { status: "disconnected", cachedCount: this.cachedCount });
64
+ return;
65
+ }
66
+ if (this.cachedCount > 0) {
67
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, {
68
+ status: "realtime",
69
+ cachedCount: this.cachedCount,
70
+ totalCount: __privateGet(this, _totalCount),
71
+ cacheUtilization: __privateGet(this, _cacheUtilization)
72
+ });
73
+ return;
74
+ }
75
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, { status: "connected" });
76
+ }
77
+ setOffline() {
78
+ __privateSet(this, _connected, false);
79
+ __privateGet(this, _pendingCoalescedUpdatesByKey).clear();
80
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, { status: "offline" });
81
+ }
82
+ setSend(send) {
83
+ __privateSet(this, _sendFn, send);
84
+ }
85
+ setError(message) {
86
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, { status: "error", message });
87
+ }
88
+ setCacheUtilization(utilization) {
89
+ __privateSet(this, _cacheUtilization, Math.max(0, utilization));
90
+ if (__privateGet(this, _state).status === "partial" || __privateGet(this, _state).status === "realtime") {
91
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, {
92
+ ...__privateGet(this, _state),
93
+ cacheUtilization: __privateGet(this, _cacheUtilization)
94
+ });
95
+ }
96
+ }
97
+ setEvicting(evictingCount) {
98
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, {
99
+ status: "evicting",
100
+ cachedCount: this.cachedCount,
101
+ evictingCount
102
+ });
103
+ }
104
+ clearEvictingState() {
105
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, {
106
+ status: __privateGet(this, _connected) ? "realtime" : "partial",
107
+ cachedCount: this.cachedCount,
108
+ totalCount: __privateGet(this, _totalCount),
109
+ cacheUtilization: __privateGet(this, _cacheUtilization)
110
+ });
111
+ }
112
+ /**
113
+ * Drop in-flight `queryRange` / `queryByOffset` / `rangeQuery` requests (e.g. user seek / sort reset).
114
+ * {@link requestRange}, {@link requestByOffset}, and {@link requestRangeQuery} call this first so
115
+ * overlapping viewport debounces cannot double-apply the same rows.
116
+ */
117
+ abortRangeRequests() {
118
+ for (const inflight of __privateGet(this, _inFlightRequests).values()) {
119
+ inflight.reject(
120
+ Object.assign(new Error("Range request aborted"), {
121
+ name: "AbortError"
122
+ })
123
+ );
124
+ }
125
+ __privateGet(this, _inFlightRequests).clear();
126
+ for (const inflight of __privateGet(this, _inFlightReconcileRequests).values()) {
127
+ inflight.reject(
128
+ Object.assign(new Error("Range request aborted"), {
129
+ name: "AbortError"
130
+ })
131
+ );
132
+ }
133
+ __privateGet(this, _inFlightReconcileRequests).clear();
134
+ }
135
+ /**
136
+ * Clear tracked row ids (e.g. after a local `truncate()` on the collection). Local truncate
137
+ * does not flow through `receiveSync`, so the bridge must be reset to match.
138
+ */
139
+ clearServerConfirmedKeys() {
140
+ __privateGet(this, _serverConfirmedKeys).clear();
141
+ __privateSet(this, _serverConfirmedKeysRevision, __privateGet(this, _serverConfirmedKeysRevision) + 1);
142
+ __privateMethod(this, _PartialSyncClientBridge_instances, notifyConfirmedKeysRevision_fn).call(this);
143
+ }
144
+ /** Keys from the latest completed `rangeQuery` / chunk response. */
145
+ get serverConfirmedKeys() {
146
+ return __privateGet(this, _serverConfirmedKeys);
147
+ }
148
+ /** Bumps when {@link serverConfirmedKeys} changes; pass into predicate hooks as a dependency. */
149
+ get serverConfirmedKeysRevision() {
150
+ return __privateGet(this, _serverConfirmedKeysRevision);
151
+ }
152
+ /** Subscribe to {@link serverConfirmedKeysRevision} changes (for `useSyncExternalStore`). */
153
+ subscribeConfirmedKeysRevision(listener) {
154
+ __privateGet(this, _confirmedRevisionListeners).add(listener);
155
+ return () => {
156
+ __privateGet(this, _confirmedRevisionListeners).delete(listener);
157
+ };
158
+ }
159
+ clearTrackedRowIds() {
160
+ __privateGet(this, _cachedIds).clear();
161
+ __privateGet(this, _serverConfirmedKeys).clear();
162
+ __privateSet(this, _serverConfirmedKeysRevision, __privateGet(this, _serverConfirmedKeysRevision) + 1);
163
+ __privateMethod(this, _PartialSyncClientBridge_instances, notifyConfirmedKeysRevision_fn).call(this);
164
+ const s = __privateGet(this, _state);
165
+ if (s.status === "partial" || s.status === "realtime") {
166
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, { ...s, cachedCount: 0 });
167
+ } else if (s.status === "disconnected") {
168
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, { status: "disconnected", cachedCount: 0 });
169
+ } else if (s.status === "evicting") {
170
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, { ...s, cachedCount: 0 });
171
+ }
172
+ }
173
+ requestRange(sort, limit, afterCursor) {
174
+ this.abortRangeRequests();
175
+ const requestId = createClientMutationId("qr");
176
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, {
177
+ status: "fetching",
178
+ requestId,
179
+ chunksReceived: 0
180
+ });
181
+ return new Promise((resolve, reject) => {
182
+ __privateGet(this, _inFlightRequests).set(requestId, {
183
+ requestId,
184
+ rows: [],
185
+ totalCount: 0,
186
+ lastCursor: afterCursor,
187
+ hasMore: false,
188
+ chunksReceived: 0,
189
+ resolve,
190
+ reject
191
+ });
192
+ __privateMethod(this, _PartialSyncClientBridge_instances, out_fn).call(this, {
193
+ type: "queryRange",
194
+ clientId: this.clientId,
195
+ requestId,
196
+ sort,
197
+ limit,
198
+ afterCursor
199
+ });
200
+ });
201
+ }
202
+ requestByOffset(sort, limit, offset) {
203
+ this.abortRangeRequests();
204
+ const requestId = createClientMutationId("qo");
205
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, {
206
+ status: "fetching",
207
+ requestId,
208
+ chunksReceived: 0
209
+ });
210
+ return new Promise((resolve, reject) => {
211
+ __privateGet(this, _inFlightRequests).set(requestId, {
212
+ requestId,
213
+ rows: [],
214
+ totalCount: 0,
215
+ lastCursor: null,
216
+ hasMore: false,
217
+ chunksReceived: 0,
218
+ resolve,
219
+ reject
220
+ });
221
+ __privateMethod(this, _PartialSyncClientBridge_instances, out_fn).call(this, {
222
+ type: "queryByOffset",
223
+ clientId: this.clientId,
224
+ requestId,
225
+ sort,
226
+ limit,
227
+ offset
228
+ });
229
+ });
230
+ }
231
+ requestRangeQuery(range, fingerprint) {
232
+ this.abortRangeRequests();
233
+ const requestId = createClientMutationId("rq");
234
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, {
235
+ status: "fetching",
236
+ requestId,
237
+ chunksReceived: 0
238
+ });
239
+ return new Promise((resolve, reject) => {
240
+ __privateGet(this, _inFlightRequests).set(requestId, {
241
+ requestId,
242
+ rows: [],
243
+ totalCount: 0,
244
+ lastCursor: null,
245
+ hasMore: false,
246
+ chunksReceived: 0,
247
+ resolve,
248
+ reject
249
+ });
250
+ __privateMethod(this, _PartialSyncClientBridge_instances, out_fn).call(this, {
251
+ type: "rangeQuery",
252
+ clientId: this.clientId,
253
+ requestId,
254
+ range,
255
+ ...fingerprint !== void 0 ? { fingerprint } : {}
256
+ });
257
+ });
258
+ }
259
+ /**
260
+ * Reconcile the client's cached window against the server using a row manifest (id + version ms).
261
+ * Pass `manifest` to override rows; otherwise uses {@link PartialSyncClientBridge.serverConfirmedKeys} and {@link PartialSyncClientBridgeOptions.collection} `get`.
262
+ */
263
+ requestRangeReconcile(range, manifest) {
264
+ this.abortRangeRequests();
265
+ const requestId = createClientMutationId("rc");
266
+ const resolvedManifest = manifest ?? __privateMethod(this, _PartialSyncClientBridge_instances, buildReconcileManifest_fn).call(this);
267
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, {
268
+ status: "fetching",
269
+ requestId,
270
+ chunksReceived: 0
271
+ });
272
+ return new Promise((resolve, reject) => {
273
+ __privateGet(this, _inFlightReconcileRequests).set(requestId, {
274
+ requestId,
275
+ resolve,
276
+ reject
277
+ });
278
+ __privateMethod(this, _PartialSyncClientBridge_instances, out_fn).call(this, {
279
+ type: "rangeReconcile",
280
+ clientId: this.clientId,
281
+ requestId,
282
+ range,
283
+ manifest: resolvedManifest
284
+ });
285
+ });
286
+ }
287
+ async handleServerMessage(message) {
288
+ const mid = message.collectionId ?? DEFAULT_SYNC_COLLECTION_ID;
289
+ if (mid !== this.collectionId) return;
290
+ switch (message.type) {
291
+ case "queryRangeChunk":
292
+ await __privateMethod(this, _PartialSyncClientBridge_instances, scheduleRangeFetchApply_fn).call(this, () => __privateMethod(this, _PartialSyncClientBridge_instances, handleQueryRangeChunk_fn).call(this, message));
293
+ return;
294
+ case "rangeUpToDate":
295
+ __privateMethod(this, _PartialSyncClientBridge_instances, handleRangeUpToDate_fn).call(this, message);
296
+ return;
297
+ case "rangeDelta":
298
+ await __privateMethod(this, _PartialSyncClientBridge_instances, scheduleRangeFetchApply_fn).call(this, () => __privateMethod(this, _PartialSyncClientBridge_instances, handleRangeDelta_fn).call(this, message));
299
+ return;
300
+ case "rangeReconcileResult":
301
+ await __privateMethod(this, _PartialSyncClientBridge_instances, scheduleRangeFetchApply_fn).call(this, () => __privateMethod(this, _PartialSyncClientBridge_instances, handleRangeReconcileResult_fn).call(this, message));
302
+ return;
303
+ case "rangePatch":
304
+ await __privateMethod(this, _PartialSyncClientBridge_instances, handleRangePatch_fn).call(this, message);
305
+ return;
306
+ case "syncBatch":
307
+ await __privateMethod(this, _PartialSyncClientBridge_instances, applyAndTrack_fn).call(this, message.changes);
308
+ return;
309
+ case "ack":
310
+ await __privateMethod(this, _PartialSyncClientBridge_instances, applyAndTrack_fn).call(this, message.changes);
311
+ return;
312
+ case "syncBackfill":
313
+ await __privateMethod(this, _PartialSyncClientBridge_instances, applyAndTrack_fn).call(this, message.changes);
314
+ return;
315
+ case "reject":
316
+ this.setError(message.reason);
317
+ return;
318
+ case "pong":
319
+ return;
320
+ default:
321
+ exhaustiveGuard(message);
322
+ }
323
+ }
324
+ /**
325
+ * Merge rows already present in the local collection (e.g. IndexedDB eager `initialLoad`) into
326
+ * `#cachedIds` so {@link cachedCount} and React-driven `bridgeState` match durable storage after reload.
327
+ * Safe to call multiple times; ids are a set. Does not call `receiveSync`.
328
+ */
329
+ seedHydratedLocalRows(rows) {
330
+ if (rows.length === 0) return;
331
+ for (const row of rows) {
332
+ __privateGet(this, _cachedIds).add(partialSyncRowKey(row.id));
333
+ }
334
+ __privateMethod(this, _PartialSyncClientBridge_instances, refreshCachedCountInState_fn).call(this);
335
+ }
336
+ /**
337
+ * Updates `#cachedIds` after {@link SyncClientBridge} has already applied the same messages via `receiveSync`
338
+ * (e.g. `syncBatch`) so we do not double-apply.
339
+ */
340
+ syncTrackedIdsFromMessages(changes) {
341
+ for (const change of changes) {
342
+ switch (change.type) {
343
+ case "insert":
344
+ __privateGet(this, _cachedIds).add(partialSyncRowKey(change.value.id));
345
+ break;
346
+ case "update":
347
+ __privateGet(this, _cachedIds).add(partialSyncRowKey(change.value.id));
348
+ break;
349
+ case "delete":
350
+ __privateGet(this, _cachedIds).delete(change.key);
351
+ break;
352
+ case "truncate":
353
+ __privateGet(this, _cachedIds).clear();
354
+ break;
355
+ default:
356
+ exhaustiveGuard(change);
357
+ }
358
+ }
359
+ }
360
+ /**
361
+ * Apply pending plain `rangePatch` updates coalesced by row id. Idempotent when the map is empty.
362
+ * Invoked automatically by `connectPartialSync` after each inbound pump drain.
363
+ */
364
+ async flushPendingCoalescedInboundUpdates() {
365
+ await __privateMethod(this, _PartialSyncClientBridge_instances, drainPendingCoalescedUpdates_fn).call(this);
366
+ }
367
+ };
368
+ _connected = new WeakMap();
369
+ _state = new WeakMap();
370
+ _inFlightRequests = new WeakMap();
371
+ _inFlightReconcileRequests = new WeakMap();
372
+ _cachedIds = new WeakMap();
373
+ _cacheUtilization = new WeakMap();
374
+ _totalCount = new WeakMap();
375
+ _sendFn = new WeakMap();
376
+ _serverConfirmedKeys = new WeakMap();
377
+ _serverConfirmedKeysRevision = new WeakMap();
378
+ _confirmedRevisionListeners = new WeakMap();
379
+ _rangeFetchApplySerial = new WeakMap();
380
+ _pendingCoalescedUpdatesByKey = new WeakMap();
381
+ _PartialSyncClientBridge_instances = new WeakSet();
382
+ out_fn = function(msg) {
383
+ __privateGet(this, _sendFn).call(this, {
384
+ ...msg,
385
+ collectionId: this.collectionId
386
+ });
387
+ };
388
+ scheduleRangeFetchApply_fn = function(fn) {
389
+ const next = __privateGet(this, _rangeFetchApplySerial).catch(() => {
390
+ }).then(fn);
391
+ __privateSet(this, _rangeFetchApplySerial, next);
392
+ return next;
393
+ };
394
+ exitFetchingAfterApplyFailure_fn = function() {
395
+ if (__privateGet(this, _connected)) {
396
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, {
397
+ status: "realtime",
398
+ cachedCount: this.cachedCount,
399
+ totalCount: __privateGet(this, _totalCount),
400
+ cacheUtilization: __privateGet(this, _cacheUtilization)
401
+ });
402
+ } else {
403
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, {
404
+ status: "partial",
405
+ cachedCount: this.cachedCount,
406
+ totalCount: __privateGet(this, _totalCount),
407
+ cacheUtilization: __privateGet(this, _cacheUtilization)
408
+ });
409
+ }
410
+ };
411
+ notifyConfirmedKeysRevision_fn = function() {
412
+ for (const listener of __privateGet(this, _confirmedRevisionListeners)) {
413
+ listener();
414
+ }
415
+ };
416
+ buildReconcileManifest_fn = function() {
417
+ const get = this.options.collection.get;
418
+ if (get === void 0) return [];
419
+ const out = [];
420
+ for (const key of __privateGet(this, _serverConfirmedKeys)) {
421
+ let local = get(key);
422
+ if (local === void 0 && typeof key === "number") {
423
+ local = get(String(key));
424
+ } else if (local === void 0 && typeof key === "string") {
425
+ const asNum = Number(key);
426
+ if (!Number.isNaN(asNum)) {
427
+ local = get(asNum);
428
+ }
429
+ }
430
+ if (local === void 0) continue;
431
+ const rowId = local.id;
432
+ if (typeof rowId !== "string" && typeof rowId !== "number") {
433
+ continue;
434
+ }
435
+ out.push({
436
+ id: rowId,
437
+ version: partialSyncRowVersionWatermarkMs(local)
438
+ });
439
+ }
440
+ return out;
441
+ };
442
+ handleRangePatch_fn = async function(message) {
443
+ const { change, viewTransition } = message;
444
+ if (viewTransition === "exitView") {
445
+ if (change.type === "update") {
446
+ this.options.onViewTransition?.({ type: "exitView", change });
447
+ }
448
+ await __privateMethod(this, _PartialSyncClientBridge_instances, applyAndTrack_fn).call(this, [change]);
449
+ __privateMethod(this, _PartialSyncClientBridge_instances, prunePartialInterestTrackingAfterExitView_fn).call(this, change);
450
+ this.options.onRangePatchApplied?.({ change, viewTransition });
451
+ return;
452
+ }
453
+ if (viewTransition === "enterView") {
454
+ if (change.type === "update") {
455
+ this.options.onViewTransition?.({ type: "enterView", change });
456
+ const key = partialSyncRowKey(change.value.id);
457
+ const getRow = this.options.collection.get;
458
+ let local = getRow !== void 0 ? getRow(key) : void 0;
459
+ if (local === void 0 && getRow !== void 0) {
460
+ if (typeof key === "number") {
461
+ local = getRow(String(key));
462
+ } else {
463
+ const asNum = Number(key);
464
+ if (!Number.isNaN(asNum)) {
465
+ local = getRow(asNum);
466
+ }
467
+ }
468
+ }
469
+ const alreadyInCollection = __privateGet(this, _cachedIds).has(key) || local !== void 0;
470
+ const toApply = alreadyInCollection ? [change] : [{ type: "insert", value: change.value }];
471
+ await __privateMethod(this, _PartialSyncClientBridge_instances, applyAndTrack_fn).call(this, toApply);
472
+ this.options.onRangePatchApplied?.({ change, viewTransition });
473
+ return;
474
+ }
475
+ await __privateMethod(this, _PartialSyncClientBridge_instances, applyAndTrack_fn).call(this, [change]);
476
+ this.options.onRangePatchApplied?.({ change, viewTransition });
477
+ return;
478
+ }
479
+ await __privateMethod(this, _PartialSyncClientBridge_instances, applyAndTrack_fn).call(this, [change], change.type === "update");
480
+ __privateMethod(this, _PartialSyncClientBridge_instances, mergeServerConfirmedKeysFromMessages_fn).call(this, [change]);
481
+ this.options.onRangePatchApplied?.({ change, viewTransition });
482
+ };
483
+ replaceServerConfirmedKeysFromRows_fn = function(rows) {
484
+ __privateGet(this, _serverConfirmedKeys).clear();
485
+ for (const row of rows) {
486
+ __privateGet(this, _serverConfirmedKeys).add(partialSyncRowKey(row.id));
487
+ }
488
+ __privateSet(this, _serverConfirmedKeysRevision, __privateGet(this, _serverConfirmedKeysRevision) + 1);
489
+ __privateMethod(this, _PartialSyncClientBridge_instances, notifyConfirmedKeysRevision_fn).call(this);
490
+ };
491
+ /** Row left the client's server-confirmed window; stop counting it as partial-sync cached. */
492
+ prunePartialInterestTrackingAfterExitView_fn = function(change) {
493
+ switch (change.type) {
494
+ case "insert":
495
+ case "update": {
496
+ const key = partialSyncRowKey(change.value.id);
497
+ __privateGet(this, _cachedIds).delete(key);
498
+ __privateGet(this, _serverConfirmedKeys).delete(key);
499
+ break;
500
+ }
501
+ case "delete": {
502
+ __privateGet(this, _cachedIds).delete(change.key);
503
+ __privateGet(this, _serverConfirmedKeys).delete(change.key);
504
+ break;
505
+ }
506
+ case "truncate":
507
+ __privateGet(this, _cachedIds).clear();
508
+ __privateGet(this, _serverConfirmedKeys).clear();
509
+ break;
510
+ default:
511
+ exhaustiveGuard(change);
512
+ }
513
+ __privateSet(this, _serverConfirmedKeysRevision, __privateGet(this, _serverConfirmedKeysRevision) + 1);
514
+ __privateMethod(this, _PartialSyncClientBridge_instances, notifyConfirmedKeysRevision_fn).call(this);
515
+ __privateMethod(this, _PartialSyncClientBridge_instances, refreshCachedCountInState_fn).call(this);
516
+ };
517
+ mergeServerConfirmedKeysFromMessages_fn = function(changes) {
518
+ if (changes.length === 0) return;
519
+ for (const change of changes) {
520
+ switch (change.type) {
521
+ case "insert":
522
+ case "update":
523
+ __privateGet(this, _serverConfirmedKeys).add(partialSyncRowKey(change.value.id));
524
+ break;
525
+ case "delete":
526
+ __privateGet(this, _serverConfirmedKeys).delete(change.key);
527
+ break;
528
+ case "truncate":
529
+ __privateGet(this, _serverConfirmedKeys).clear();
530
+ break;
531
+ default:
532
+ exhaustiveGuard(change);
533
+ }
534
+ }
535
+ __privateSet(this, _serverConfirmedKeysRevision, __privateGet(this, _serverConfirmedKeysRevision) + 1);
536
+ __privateMethod(this, _PartialSyncClientBridge_instances, notifyConfirmedKeysRevision_fn).call(this);
537
+ };
538
+ /** True only if this handler still owns the in-flight entry (not superseded by {@link abortRangeRequests}). */
539
+ isActiveRangeRequest_fn = function(requestId, inFlight) {
540
+ return __privateGet(this, _inFlightRequests).get(requestId) === inFlight;
541
+ };
542
+ handleQueryRangeChunk_fn = async function(message) {
543
+ const inFlight = __privateGet(this, _inFlightRequests).get(message.requestId);
544
+ if (!inFlight) return;
545
+ inFlight.chunksReceived += 1;
546
+ inFlight.totalCount = message.totalCount;
547
+ inFlight.lastCursor = message.lastCursor;
548
+ inFlight.hasMore = message.hasMore;
549
+ __privateSet(this, _totalCount, message.totalCount);
550
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, {
551
+ status: "fetching",
552
+ requestId: message.requestId,
553
+ chunksReceived: inFlight.chunksReceived
554
+ });
555
+ if (message.rows.length > 0) {
556
+ await this.options.beforeApplyRows?.(message.rows);
557
+ if (!__privateMethod(this, _PartialSyncClientBridge_instances, isActiveRangeRequest_fn).call(this, message.requestId, inFlight)) return;
558
+ const getRow = this.options.collection.get;
559
+ const changes = [];
560
+ let cacheTouched = false;
561
+ for (const row of message.rows) {
562
+ const pk = partialSyncRowKey(row.id);
563
+ const local = getRow !== void 0 ? getRow(pk) : void 0;
564
+ if (local !== void 0) {
565
+ if (!__privateGet(this, _cachedIds).has(pk)) {
566
+ __privateGet(this, _cachedIds).add(pk);
567
+ cacheTouched = true;
568
+ }
569
+ if (serverRowSupersedesLocal(local, row)) {
570
+ changes.push({
571
+ type: "update",
572
+ value: row,
573
+ previousValue: local
574
+ });
575
+ }
576
+ continue;
577
+ }
578
+ if (!__privateGet(this, _cachedIds).has(pk)) {
579
+ changes.push({ type: "insert", value: row });
580
+ }
581
+ }
582
+ if (changes.length > 0) {
583
+ try {
584
+ await __privateMethod(this, _PartialSyncClientBridge_instances, applyAndTrack_fn).call(this, changes);
585
+ } catch (err) {
586
+ if (!__privateMethod(this, _PartialSyncClientBridge_instances, isActiveRangeRequest_fn).call(this, message.requestId, inFlight)) {
587
+ return;
588
+ }
589
+ __privateGet(this, _inFlightRequests).delete(message.requestId);
590
+ inFlight.reject(err);
591
+ __privateMethod(this, _PartialSyncClientBridge_instances, exitFetchingAfterApplyFailure_fn).call(this);
592
+ return;
593
+ }
594
+ if (!__privateMethod(this, _PartialSyncClientBridge_instances, isActiveRangeRequest_fn).call(this, message.requestId, inFlight)) {
595
+ return;
596
+ }
597
+ } else if (cacheTouched) {
598
+ __privateMethod(this, _PartialSyncClientBridge_instances, refreshCachedCountInState_fn).call(this);
599
+ }
600
+ inFlight.rows.push(...message.rows);
601
+ }
602
+ if (!message.done) return;
603
+ if (!__privateMethod(this, _PartialSyncClientBridge_instances, isActiveRangeRequest_fn).call(this, message.requestId, inFlight)) return;
604
+ __privateMethod(this, _PartialSyncClientBridge_instances, replaceServerConfirmedKeysFromRows_fn).call(this, inFlight.rows);
605
+ __privateGet(this, _inFlightRequests).delete(message.requestId);
606
+ const result = {
607
+ rows: inFlight.rows,
608
+ totalCount: inFlight.totalCount,
609
+ lastCursor: inFlight.lastCursor,
610
+ hasMore: inFlight.hasMore
611
+ };
612
+ inFlight.resolve(result);
613
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, {
614
+ status: __privateGet(this, _connected) ? "realtime" : "partial",
615
+ cachedCount: this.cachedCount,
616
+ totalCount: __privateGet(this, _totalCount),
617
+ cacheUtilization: __privateGet(this, _cacheUtilization)
618
+ });
619
+ };
620
+ handleRangeUpToDate_fn = function(message) {
621
+ const inFlight = __privateGet(this, _inFlightRequests).get(message.requestId);
622
+ if (!inFlight) return;
623
+ __privateGet(this, _inFlightRequests).delete(message.requestId);
624
+ __privateSet(this, _totalCount, message.totalCount);
625
+ inFlight.resolve({
626
+ rows: [],
627
+ totalCount: message.totalCount,
628
+ lastCursor: null,
629
+ hasMore: false,
630
+ upToDate: true
631
+ });
632
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, {
633
+ status: __privateGet(this, _connected) ? "realtime" : "partial",
634
+ cachedCount: this.cachedCount,
635
+ totalCount: __privateGet(this, _totalCount),
636
+ cacheUtilization: __privateGet(this, _cacheUtilization)
637
+ });
638
+ };
639
+ handleRangeDelta_fn = async function(message) {
640
+ const inFlight = __privateGet(this, _inFlightRequests).get(message.requestId);
641
+ if (!inFlight) return;
642
+ const delta = message.changes;
643
+ await __privateMethod(this, _PartialSyncClientBridge_instances, applyAndTrack_fn).call(this, delta);
644
+ if (!__privateMethod(this, _PartialSyncClientBridge_instances, isActiveRangeRequest_fn).call(this, message.requestId, inFlight)) return;
645
+ __privateMethod(this, _PartialSyncClientBridge_instances, mergeServerConfirmedKeysFromMessages_fn).call(this, delta);
646
+ __privateGet(this, _inFlightRequests).delete(message.requestId);
647
+ __privateSet(this, _totalCount, message.totalCount);
648
+ inFlight.resolve({
649
+ rows: [],
650
+ totalCount: message.totalCount,
651
+ lastCursor: message.lastCursor ?? null,
652
+ hasMore: false,
653
+ invalidateWindow: true
654
+ });
655
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, {
656
+ status: __privateGet(this, _connected) ? "realtime" : "partial",
657
+ cachedCount: this.cachedCount,
658
+ totalCount: __privateGet(this, _totalCount),
659
+ cacheUtilization: __privateGet(this, _cacheUtilization)
660
+ });
661
+ };
662
+ handleRangeReconcileResult_fn = async function(message) {
663
+ const inFlight = __privateGet(this, _inFlightReconcileRequests).get(message.requestId);
664
+ if (!inFlight) return;
665
+ const get = this.options.collection.get;
666
+ const toApply = [
667
+ ...message.added,
668
+ ...message.updated
669
+ ];
670
+ for (const staleKey of message.stale) {
671
+ let local;
672
+ if (get !== void 0) {
673
+ local = get(staleKey);
674
+ if (local === void 0 && typeof staleKey === "number") {
675
+ local = get(String(staleKey));
676
+ } else if (local === void 0 && typeof staleKey === "string") {
677
+ const asNum = Number(staleKey);
678
+ if (!Number.isNaN(asNum)) {
679
+ local = get(asNum);
680
+ }
681
+ }
682
+ }
683
+ if (local !== void 0) {
684
+ const syn = {
685
+ type: "update",
686
+ value: local,
687
+ previousValue: local
688
+ };
689
+ this.options.onViewTransition?.({ type: "exitView", change: syn });
690
+ }
691
+ toApply.push({ type: "delete", key: staleKey });
692
+ }
693
+ if (toApply.length > 0) {
694
+ await __privateMethod(this, _PartialSyncClientBridge_instances, applyAndTrack_fn).call(this, toApply);
695
+ if (__privateGet(this, _inFlightReconcileRequests).get(message.requestId) !== inFlight) {
696
+ return;
697
+ }
698
+ __privateMethod(this, _PartialSyncClientBridge_instances, mergeServerConfirmedKeysFromMessages_fn).call(this, toApply);
699
+ }
700
+ __privateGet(this, _inFlightReconcileRequests).delete(message.requestId);
701
+ __privateSet(this, _totalCount, message.totalCount);
702
+ const addedRows = [];
703
+ for (const ch of message.added) {
704
+ if (ch.type === "insert") {
705
+ addedRows.push(ch.value);
706
+ }
707
+ }
708
+ const updatedRows = [];
709
+ for (const ch of message.updated) {
710
+ if (ch.type === "update") {
711
+ updatedRows.push(ch.value);
712
+ }
713
+ }
714
+ inFlight.resolve({
715
+ added: addedRows,
716
+ updated: updatedRows,
717
+ staleIds: [...message.stale],
718
+ movedHints: [...message.movedHints],
719
+ totalCount: message.totalCount
720
+ });
721
+ __privateMethod(this, _PartialSyncClientBridge_instances, refreshCachedCountInState_fn).call(this);
722
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, {
723
+ status: __privateGet(this, _connected) ? "realtime" : "partial",
724
+ cachedCount: this.cachedCount,
725
+ totalCount: __privateGet(this, _totalCount),
726
+ cacheUtilization: __privateGet(this, _cacheUtilization)
727
+ });
728
+ };
729
+ refreshCachedCountInState_fn = function() {
730
+ const s = __privateGet(this, _state);
731
+ switch (s.status) {
732
+ case "partial":
733
+ case "realtime":
734
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, { ...s, cachedCount: this.cachedCount });
735
+ break;
736
+ case "disconnected":
737
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, {
738
+ status: "disconnected",
739
+ cachedCount: this.cachedCount
740
+ });
741
+ break;
742
+ case "evicting":
743
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, { ...s, cachedCount: this.cachedCount });
744
+ break;
745
+ case "connected":
746
+ if (__privateGet(this, _connected) && this.cachedCount > 0) {
747
+ __privateMethod(this, _PartialSyncClientBridge_instances, setState_fn).call(this, {
748
+ status: "realtime",
749
+ cachedCount: this.cachedCount,
750
+ totalCount: __privateGet(this, _totalCount),
751
+ cacheUtilization: __privateGet(this, _cacheUtilization)
752
+ });
753
+ }
754
+ break;
755
+ }
756
+ };
757
+ drainPendingCoalescedUpdates_fn = async function() {
758
+ if (__privateGet(this, _pendingCoalescedUpdatesByKey).size === 0) return;
759
+ const batch = [...__privateGet(this, _pendingCoalescedUpdatesByKey).values()];
760
+ __privateGet(this, _pendingCoalescedUpdatesByKey).clear();
761
+ const get = this.options.collection.get;
762
+ const toApply = get === void 0 ? batch : batch.map((ch) => {
763
+ if (ch.type !== "update") return ch;
764
+ const id = ch.value.id;
765
+ const current = (typeof id === "string" || typeof id === "number" ? get(id) : void 0) ?? get(partialSyncRowKey(id));
766
+ if (current === void 0) return ch;
767
+ return { ...ch, previousValue: current };
768
+ });
769
+ await __privateMethod(this, _PartialSyncClientBridge_instances, receiveSyncAndTrack_fn).call(this, toApply);
770
+ };
771
+ receiveSyncAndTrack_fn = async function(changes) {
772
+ if (changes.length === 0) return;
773
+ await this.options.collection.utils.receiveSync(changes);
774
+ this.syncTrackedIdsFromMessages(changes);
775
+ };
776
+ applyAndTrack_fn = async function(changes, coalesceSameRowUpdates = false) {
777
+ if (changes.length === 0) return;
778
+ if (!coalesceSameRowUpdates) {
779
+ await __privateMethod(this, _PartialSyncClientBridge_instances, drainPendingCoalescedUpdates_fn).call(this);
780
+ await __privateMethod(this, _PartialSyncClientBridge_instances, receiveSyncAndTrack_fn).call(this, changes);
781
+ return;
782
+ }
783
+ for (const ch of changes) {
784
+ if (ch.type !== "update") {
785
+ await __privateMethod(this, _PartialSyncClientBridge_instances, drainPendingCoalescedUpdates_fn).call(this);
786
+ await __privateMethod(this, _PartialSyncClientBridge_instances, receiveSyncAndTrack_fn).call(this, changes);
787
+ return;
788
+ }
789
+ __privateGet(this, _pendingCoalescedUpdatesByKey).set(
790
+ partialSyncRowKey(ch.value.id),
791
+ ch
792
+ );
793
+ }
794
+ };
795
+ setState_fn = function(state) {
796
+ __privateSet(this, _state, state);
797
+ this.options.onStateChange?.(state);
798
+ };
799
+
800
+ export { PartialSyncClientBridge };
801
+ //# sourceMappingURL=chunk-P3JOTUAB.js.map
802
+ //# sourceMappingURL=chunk-P3JOTUAB.js.map