@sync-subscribe/client 0.3.2

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.
@@ -0,0 +1,568 @@
1
+ import { filtersEqual, filterUnion, negateFilter, simplifyFilter, isAlwaysFalse, EMPTY_SYNC_TOKEN, } from "@sync-subscribe/core";
2
+ import { InMemoryStore } from "./inMemoryStore.js";
3
+ /**
4
+ * High-level client that manages subscriptions, local state, and sync cycles.
5
+ *
6
+ * Pass a custom `store` to use IndexedDB persistence:
7
+ * new SyncClient(transport, new IdbLocalStore("my-db"))
8
+ *
9
+ * Omit `store` to use the default in-memory store.
10
+ */
11
+ export class SyncClient {
12
+ transport;
13
+ schema;
14
+ listeners = [];
15
+ activeSubs = new Map(); // keyed by subscriptionId
16
+ subActiveListeners = new Map(); // keyed by subscriptionId
17
+ _stopStream = null;
18
+ _streamTimer = null;
19
+ pendingPull = null;
20
+ store;
21
+ constructor(transport, store,
22
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
23
+ schema) {
24
+ this.transport = transport;
25
+ this.schema = schema;
26
+ this.store = store ?? new InMemoryStore();
27
+ }
28
+ // ---------------------------------------------------------------------------
29
+ // Subscriptions
30
+ // ---------------------------------------------------------------------------
31
+ /** Serial queue — subscribe() calls run one at a time to prevent races. */
32
+ subscribeQueue = Promise.resolve();
33
+ subscribe(options) {
34
+ const next = this.subscribeQueue.then(() => this._subscribe(options));
35
+ // Swallow errors on the shared chain so a failure doesn't block future calls.
36
+ this.subscribeQueue = next.catch(() => { });
37
+ return next;
38
+ }
39
+ async _subscribe(options) {
40
+ const { name } = options;
41
+ const inputFilter = simplifyFilter(options.filter);
42
+ let previousSubscriptionId = options.previousSubscriptionId;
43
+ let storedSub;
44
+ // Restore from store if named and no explicit previousSubscriptionId
45
+ if (name && previousSubscriptionId === undefined) {
46
+ storedSub = await this.store.getSubscription(name);
47
+ if (storedSub) {
48
+ previousSubscriptionId = storedSub.subscriptionId;
49
+ }
50
+ }
51
+ else if (previousSubscriptionId !== undefined) {
52
+ storedSub = await this.store.getSubscriptionById(previousSubscriptionId);
53
+ }
54
+ // If filter is unchanged, reuse existing subscription (restores status too)
55
+ if (storedSub && filtersEqual(storedSub.filter, inputFilter)) {
56
+ const result = {
57
+ ...storedSub,
58
+ ...(name !== undefined && { name }),
59
+ };
60
+ this.activeSubs.set(result.subscriptionId, result);
61
+ return result;
62
+ }
63
+ // Generate a client-side UUID — no server call needed
64
+ const newSubscriptionId = crypto.randomUUID();
65
+ let newSub = {
66
+ subscriptionId: newSubscriptionId,
67
+ filter: inputFilter,
68
+ syncToken: EMPTY_SYNC_TOKEN,
69
+ ...(name !== undefined && { name }),
70
+ status: "active",
71
+ };
72
+ const key = name ?? newSubscriptionId;
73
+ // Load all persisted subscriptions from the store (source of truth — activeSubs
74
+ // only reflects the current session). Exclude the old sub being replaced, if any.
75
+ const allPersistedSubs = await this.store.listSubscriptions();
76
+ const existingFilters = allPersistedSubs
77
+ .filter((s) => s.subscriptionId !== storedSub?.subscriptionId)
78
+ .filter((s) => s.syncToken !== EMPTY_SYNC_TOKEN)
79
+ .map((s) => s.filter);
80
+ // Check 1: is the new filter entirely covered by existing data?
81
+ // Check 2: does the old filter contain items that need eviction?
82
+ let newFilterPositive = existingFilters;
83
+ let evictionFilter;
84
+ if (storedSub) {
85
+ newFilterPositive = [
86
+ ...existingFilters,
87
+ storedSub.filter,
88
+ ];
89
+ evictionFilter = [
90
+ ...existingFilters,
91
+ inputFilter,
92
+ ];
93
+ }
94
+ if (newFilterPositive.length > 0) {
95
+ newSub = await this.checkForGap(newFilterPositive, inputFilter, newSub);
96
+ }
97
+ if (storedSub && evictionFilter && evictionFilter.length > 0) {
98
+ await this.checkForEviction(evictionFilter, storedSub.filter);
99
+ }
100
+ // Remove old subscription from store and in-memory map
101
+ if (storedSub) {
102
+ const oldKey = storedSub.name ?? storedSub.subscriptionId;
103
+ await this.store.removeSubscription(oldKey);
104
+ this.activeSubs.delete(storedSub.subscriptionId);
105
+ }
106
+ await this.store.setSubscription(key, newSub);
107
+ this.activeSubs.set(newSubscriptionId, newSub);
108
+ // Automatically kick off a pull and (re)start the stream for the new subscription.
109
+ void this.schedulePull();
110
+ this._syncStream();
111
+ return newSub;
112
+ }
113
+ async checkForEviction(existingFilters, oldFilter) {
114
+ const existingUnion = filterUnion(...existingFilters);
115
+ const negatedUnion = negateFilter(existingUnion);
116
+ const rawGap = {
117
+ $and: [oldFilter, negatedUnion],
118
+ };
119
+ if (isAlwaysFalse(rawGap)) {
120
+ return;
121
+ }
122
+ const fGap = simplifyFilter(rawGap);
123
+ await this.store.evict(fGap);
124
+ }
125
+ /** Checks if the new inputFilter results in a gap we need to fill */
126
+ async checkForGap(existingFilters, inputFilter, newSub) {
127
+ const existingUnion = filterUnion(...existingFilters);
128
+ const negatedUnion = negateFilter(existingUnion);
129
+ const rawGap = {
130
+ $and: [inputFilter, negatedUnion],
131
+ };
132
+ if (isAlwaysFalse(rawGap)) {
133
+ // F_new is fully covered — every possible record matching F_new is already
134
+ // served by an existing subscription. Reconstruct token from local data.
135
+ const reconstructed = await this.store.reconstructSyncToken(inputFilter);
136
+ return {
137
+ ...newSub,
138
+ status: "active",
139
+ syncToken: reconstructed !== EMPTY_SYNC_TOKEN ? reconstructed : newSub.syncToken,
140
+ };
141
+ }
142
+ // Check if F_new and existing subs are completely disjoint (no overlap at all).
143
+ // In this case there's no local data to reuse — use an empty token directly.
144
+ const rawIntersection = {
145
+ $and: [inputFilter, existingUnion],
146
+ };
147
+ if (isAlwaysFalse(rawIntersection)) {
148
+ return newSub;
149
+ }
150
+ // Gap exists — simplify the gap filter (safe after always-false check).
151
+ const fGap = simplifyFilter(rawGap);
152
+ const gapSubId = crypto.randomUUID();
153
+ const gapSub = {
154
+ subscriptionId: gapSubId,
155
+ filter: fGap,
156
+ syncToken: EMPTY_SYNC_TOKEN,
157
+ status: "active",
158
+ };
159
+ await this.store.setSubscription(gapSubId, gapSub);
160
+ return {
161
+ ...newSub,
162
+ status: "pending_gap_fill",
163
+ gapSubscriptionId: gapSubId,
164
+ };
165
+ }
166
+ /**
167
+ * Update an existing subscription to use a new filter.
168
+ * Delegates to subscribe() with previousSubscriptionId set.
169
+ */
170
+ async updateSubscription(subscriptionId, newFilter) {
171
+ const existing = this.activeSubs.get(subscriptionId) ??
172
+ (await this.store.getSubscriptionById(subscriptionId));
173
+ if (!existing)
174
+ throw new Error(`Unknown subscription: ${subscriptionId}`);
175
+ return this.subscribe({
176
+ filter: newFilter,
177
+ previousSubscriptionId: subscriptionId,
178
+ ...(existing.name !== undefined && { name: existing.name }),
179
+ });
180
+ }
181
+ // ---------------------------------------------------------------------------
182
+ // Sync
183
+ // ---------------------------------------------------------------------------
184
+ /**
185
+ * Pull patches for all subscriptions.
186
+ * - ACTIVE subscriptions are included directly.
187
+ * - PENDING subscriptions are excluded; their gap sub is included instead.
188
+ * When a gap sub's token appears in the response the gap is complete:
189
+ * the gap sub is removed, the parent subscription reconstructs its token
190
+ * and transitions to active.
191
+ */
192
+ async pull() {
193
+ const subsForPull = [];
194
+ // Maps gapSubId → parentSubId so we can detect gap completion
195
+ const gapSubToParent = new Map();
196
+ for (const sub of this.activeSubs.values()) {
197
+ const status = sub.status ?? "active";
198
+ if (status === "active") {
199
+ subsForPull.push({
200
+ key: sub.subscriptionId,
201
+ filter: sub.filter,
202
+ syncToken: sub.syncToken,
203
+ });
204
+ }
205
+ else if (status === "pending_gap_fill" && sub.gapSubscriptionId) {
206
+ const gapSub = await this.store.getSubscriptionById(sub.gapSubscriptionId);
207
+ if (gapSub) {
208
+ subsForPull.push({
209
+ key: gapSub.subscriptionId,
210
+ filter: gapSub.filter,
211
+ syncToken: gapSub.syncToken,
212
+ });
213
+ gapSubToParent.set(gapSub.subscriptionId, sub.subscriptionId);
214
+ }
215
+ }
216
+ }
217
+ if (subsForPull.length === 0)
218
+ return;
219
+ const { patches, syncTokens } = await this.transport.pull(subsForPull);
220
+ const applied = await this.store.applyPatches(patches);
221
+ for (const [id, syncToken] of Object.entries(syncTokens)) {
222
+ const parentSubId = gapSubToParent.get(id);
223
+ if (parentSubId) {
224
+ // Gap sub received a response — gap is filled.
225
+ const parentSub = this.activeSubs.get(parentSubId);
226
+ // Remove gap sub from local store only (server is stateless)
227
+ await this.store.removeSubscription(id);
228
+ // Reconstruct the parent's sync token from the now-complete local data
229
+ const reconstructed = await this.store.reconstructSyncToken(parentSub.filter);
230
+ const activeSub = {
231
+ ...parentSub,
232
+ status: "active",
233
+ syncToken: reconstructed !== EMPTY_SYNC_TOKEN
234
+ ? reconstructed
235
+ : parentSub.syncToken,
236
+ };
237
+ delete activeSub.gapSubscriptionId;
238
+ const key = parentSub.name ?? parentSub.subscriptionId;
239
+ await this.store.setSubscription(key, activeSub);
240
+ this.activeSubs.set(parentSubId, activeSub);
241
+ this._emitSubscriptionActive(parentSubId);
242
+ }
243
+ else {
244
+ // Normal active sub — update its token
245
+ const sub = this.activeSubs.get(id);
246
+ if (sub) {
247
+ const updated = { ...sub, syncToken };
248
+ const key = sub.name ?? sub.subscriptionId;
249
+ await this.store.setSubscription(key, updated);
250
+ this.activeSubs.set(id, updated);
251
+ }
252
+ }
253
+ }
254
+ if (applied.length > 0)
255
+ this.emit(applied);
256
+ }
257
+ /**
258
+ * Debounced pull — collapses multiple rapid calls (e.g. several hooks mounting
259
+ * at the same time) into a single transport request. All callers share the same
260
+ * promise and receive the result of the one batched pull.
261
+ *
262
+ * @param delayMs - How long to wait before issuing the pull (default 20 ms).
263
+ */
264
+ schedulePull(delayMs = 20) {
265
+ if (this.pendingPull) {
266
+ clearTimeout(this.pendingPull.timer);
267
+ this.pendingPull.timer = setTimeout(() => this._flushPull(), delayMs);
268
+ return this.pendingPull.promise;
269
+ }
270
+ let resolve;
271
+ let reject;
272
+ const promise = new Promise((res, rej) => {
273
+ resolve = res;
274
+ reject = rej;
275
+ });
276
+ const timer = setTimeout(() => this._flushPull(), delayMs);
277
+ this.pendingPull = { promise, resolve, reject, timer };
278
+ return promise;
279
+ }
280
+ async _flushPull() {
281
+ const pending = this.pendingPull;
282
+ this.pendingPull = null;
283
+ if (!pending)
284
+ return;
285
+ try {
286
+ await this.pull();
287
+ pending.resolve();
288
+ }
289
+ catch (err) {
290
+ pending.reject(err);
291
+ }
292
+ }
293
+ /**
294
+ * Write a record locally (read-your-own-writes) then push to server.
295
+ * Returns true on success, false if a conflict was detected (server wins).
296
+ */
297
+ async mutate(record) {
298
+ const existing = await this.store.getById(record.recordId);
299
+ const stamped = {
300
+ ...record,
301
+ updatedAt: Date.now(),
302
+ revisionCount: (existing?.revisionCount ?? 0) + 1,
303
+ };
304
+ await this.store.write(stamped);
305
+ // Optimistic update — notify listeners immediately so the UI reflects the change.
306
+ this.emit([{ op: "upsert", record: stamped }]);
307
+ const result = await this.transport.push([stamped]);
308
+ if ("conflict" in result && result.conflict) {
309
+ // Server wins: overwrite local record with server version.
310
+ const applied = await this.store.applyPatches([
311
+ { op: "upsert", record: result.serverRecord },
312
+ ]);
313
+ if (applied.length > 0)
314
+ this.emit(applied);
315
+ return false;
316
+ }
317
+ // Stamp serverUpdatedAt on the local copy so reconstructSyncToken stays accurate.
318
+ // Emit again so listeners see the final record with serverUpdatedAt set.
319
+ const serverUpdatedAt = result
320
+ .serverUpdatedAt;
321
+ if (serverUpdatedAt !== undefined) {
322
+ await this.store.setServerUpdatedAt(stamped.recordId, serverUpdatedAt);
323
+ const updated = await this.store.getById(record.recordId);
324
+ if (updated)
325
+ this.emit([{ op: "upsert", record: updated }]);
326
+ }
327
+ return true;
328
+ }
329
+ // ---------------------------------------------------------------------------
330
+ // Queries
331
+ // ---------------------------------------------------------------------------
332
+ /**
333
+ * Returns a reactive handle to a filtered view of the local store.
334
+ * Does NOT register a sync subscription — use this when data is already
335
+ * being synced via a separate `subscribe()` call (e.g. a background sync).
336
+ *
337
+ * Loading starts `true`, becomes `false` after the first local read.
338
+ * Re-runs whenever the store changes (pull patches, mutations).
339
+ */
340
+ query(options) {
341
+ const { filter } = options;
342
+ return {
343
+ subscribe: (run, _invalidate) => {
344
+ let cancelled = false;
345
+ run({ data: [], loading: true });
346
+ this.store
347
+ .query(filter)
348
+ .then((data) => { if (!cancelled)
349
+ run({ data, loading: false }); })
350
+ .catch(console.error);
351
+ const offPatches = this.onPatches(async () => {
352
+ if (cancelled)
353
+ return;
354
+ const data = await this.store.query(filter);
355
+ if (!cancelled)
356
+ run({ data, loading: false });
357
+ });
358
+ return () => {
359
+ cancelled = true;
360
+ offPatches();
361
+ };
362
+ },
363
+ };
364
+ }
365
+ /**
366
+ * Returns a reactive handle that also manages its own sync subscription.
367
+ * The sync subscription is registered when the first caller subscribes and
368
+ * removed when the last caller unsubscribes.
369
+ *
370
+ * Use this when the sync filter and the query filter are the same.
371
+ * For a narrower in-memory view of a broader background sync, use `query()`.
372
+ */
373
+ liveQuery(options) {
374
+ const { filter, name } = options;
375
+ let refCount = 0;
376
+ let sessionCleanup;
377
+ const runs = new Set();
378
+ const refresh = async () => {
379
+ const data = await this.store.query(filter);
380
+ for (const run of runs)
381
+ run({ data, loading: false });
382
+ };
383
+ return {
384
+ subscribe: (run, _invalidate) => {
385
+ refCount++;
386
+ runs.add(run);
387
+ run({ data: [], loading: true });
388
+ if (refCount === 1) {
389
+ // Per-session state so that a React StrictMode unmount+remount
390
+ // (cleanup fires before the subscribe promise resolves) is handled safely.
391
+ let subId;
392
+ let cancelled = false;
393
+ const offPatches = this.onPatches(() => {
394
+ if (!cancelled)
395
+ refresh().catch(console.error);
396
+ });
397
+ this.subscribe({ filter, ...(name !== undefined && { name }) })
398
+ .then((sub) => {
399
+ if (cancelled) {
400
+ // Cleanup raced the subscribe — discard the subscription immediately.
401
+ this.unsubscribe(sub.subscriptionId).catch(console.error);
402
+ return;
403
+ }
404
+ subId = sub.subscriptionId;
405
+ return refresh();
406
+ })
407
+ .catch(console.error);
408
+ sessionCleanup = () => {
409
+ cancelled = true;
410
+ offPatches();
411
+ if (subId !== undefined) {
412
+ this.unsubscribe(subId).catch(console.error);
413
+ subId = undefined;
414
+ }
415
+ sessionCleanup = undefined;
416
+ };
417
+ }
418
+ else {
419
+ refresh().catch(console.error);
420
+ }
421
+ return () => {
422
+ runs.delete(run);
423
+ refCount--;
424
+ if (refCount === 0)
425
+ sessionCleanup?.();
426
+ };
427
+ },
428
+ };
429
+ }
430
+ // ---------------------------------------------------------------------------
431
+ // Streaming (managed internally)
432
+ // ---------------------------------------------------------------------------
433
+ /**
434
+ * Debounced (re)start of the SSE stream. Collapses multiple rapid calls
435
+ * (e.g. several hooks subscribing at once) into a single connection open.
436
+ * Called automatically by subscribe(), unsubscribe(), and gap-fill completion.
437
+ */
438
+ _syncStream(delayMs = 20) {
439
+ if (this._streamTimer !== null) {
440
+ clearTimeout(this._streamTimer);
441
+ }
442
+ this._streamTimer = setTimeout(() => {
443
+ this._streamTimer = null;
444
+ this._applyStreamState();
445
+ }, delayMs);
446
+ }
447
+ _applyStreamState() {
448
+ if (this._stopStream) {
449
+ this._stopStream();
450
+ this._stopStream = null;
451
+ }
452
+ if (!this.transport.stream)
453
+ return;
454
+ const subs = [...this.activeSubs.values()].filter((s) => (s.status ?? "active") === "active");
455
+ if (subs.length === 0)
456
+ return;
457
+ this._stopStream = this.transport.stream(subs.map((s) => ({
458
+ key: s.subscriptionId,
459
+ filter: s.filter,
460
+ syncToken: s.syncToken,
461
+ })), async ({ patches, syncTokens }) => {
462
+ const applied = await this.store.applyPatches(patches);
463
+ for (const [id, syncToken] of Object.entries(syncTokens)) {
464
+ const sub = this.activeSubs.get(id);
465
+ if (sub) {
466
+ const updated = { ...sub, syncToken };
467
+ const key = sub.name ?? sub.subscriptionId;
468
+ await this.store.setSubscription(key, updated);
469
+ this.activeSubs.set(id, updated);
470
+ }
471
+ }
472
+ if (applied.length > 0)
473
+ this.emit(applied);
474
+ }, (err) => console.error("[SyncClient] SSE error:", err));
475
+ }
476
+ /**
477
+ * Remove a subscription and restart the stream without it.
478
+ * If no active subscriptions remain the stream is stopped.
479
+ */
480
+ async unsubscribe(subscriptionId) {
481
+ const sub = this.activeSubs.get(subscriptionId);
482
+ if (!sub)
483
+ return;
484
+ if (sub.gapSubscriptionId) {
485
+ await this.store.removeSubscription(sub.gapSubscriptionId);
486
+ this.subActiveListeners.delete(subscriptionId);
487
+ }
488
+ const key = sub.name ?? subscriptionId;
489
+ await this.store.removeSubscription(key);
490
+ this.activeSubs.delete(subscriptionId);
491
+ this._syncStream();
492
+ }
493
+ // ---------------------------------------------------------------------------
494
+ // Listeners
495
+ // ---------------------------------------------------------------------------
496
+ onPatches(listener) {
497
+ this.listeners.push(listener);
498
+ return () => {
499
+ this.listeners = this.listeners.filter((l) => l !== listener);
500
+ };
501
+ }
502
+ /**
503
+ * Register a one-shot listener that fires when the given subscription
504
+ * transitions from pending_gap_fill → active. Useful for restarting the
505
+ * SSE stream to include the newly-active subscription.
506
+ * Returns an unsubscribe function.
507
+ */
508
+ onSubscriptionActive(subscriptionId, listener) {
509
+ if (!this.subActiveListeners.has(subscriptionId)) {
510
+ this.subActiveListeners.set(subscriptionId, new Set());
511
+ }
512
+ this.subActiveListeners.get(subscriptionId).add(listener);
513
+ return () => {
514
+ this.subActiveListeners.get(subscriptionId)?.delete(listener);
515
+ };
516
+ }
517
+ _emitSubscriptionActive(subscriptionId) {
518
+ const listeners = this.subActiveListeners.get(subscriptionId);
519
+ if (listeners) {
520
+ for (const l of listeners)
521
+ l();
522
+ this.subActiveListeners.delete(subscriptionId);
523
+ }
524
+ // Subscription just became active — restart stream to include it.
525
+ this._syncStream();
526
+ }
527
+ emit(patches) {
528
+ for (const l of this.listeners)
529
+ l(patches);
530
+ }
531
+ // ---------------------------------------------------------------------------
532
+ // Helpers
533
+ // ---------------------------------------------------------------------------
534
+ /**
535
+ * Look up a subscription by name (for named subs) or by subscriptionId
536
+ * (for unnamed subs, where the key IS the subscriptionId).
537
+ */
538
+ getSubscription(key) {
539
+ // Try by subscriptionId first (covers unnamed subs)
540
+ const byId = this.activeSubs.get(key);
541
+ if (byId)
542
+ return byId;
543
+ // Then by name (covers named subs)
544
+ for (const sub of this.activeSubs.values()) {
545
+ if (sub.name === key)
546
+ return sub;
547
+ }
548
+ return undefined;
549
+ }
550
+ getSubscriptionById(id) {
551
+ return this.activeSubs.get(id);
552
+ }
553
+ /** Resets sync state (useful for logout / account switch). */
554
+ async reset() {
555
+ if (this._streamTimer !== null) {
556
+ clearTimeout(this._streamTimer);
557
+ this._streamTimer = null;
558
+ }
559
+ if (this._stopStream) {
560
+ this._stopStream();
561
+ this._stopStream = null;
562
+ }
563
+ this.activeSubs.clear();
564
+ await this.store.clear();
565
+ await this.store.clearSubscriptions();
566
+ }
567
+ }
568
+ //# sourceMappingURL=syncClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"syncClient.js","sourceRoot":"","sources":["../src/syncClient.ts"],"names":[],"mappings":"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"}