stellar-drive 1.2.2 → 1.2.4

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 (82) hide show
  1. package/README.md +4 -44
  2. package/dist/actions/scrollGuard.d.ts +14 -0
  3. package/dist/actions/scrollGuard.d.ts.map +1 -0
  4. package/dist/actions/scrollGuard.js +75 -0
  5. package/dist/actions/scrollGuard.js.map +1 -0
  6. package/dist/bin/commands.js +0 -0
  7. package/dist/bin/install-pwa.js +1 -1
  8. package/dist/config.d.ts +0 -13
  9. package/dist/config.d.ts.map +1 -1
  10. package/dist/config.js +7 -23
  11. package/dist/config.js.map +1 -1
  12. package/dist/conflicts.js +1 -1
  13. package/dist/database.d.ts +1 -1
  14. package/dist/database.d.ts.map +1 -1
  15. package/dist/database.js +7 -25
  16. package/dist/database.js.map +1 -1
  17. package/dist/diagnostics.d.ts +0 -75
  18. package/dist/diagnostics.d.ts.map +1 -1
  19. package/dist/diagnostics.js +2 -114
  20. package/dist/diagnostics.js.map +1 -1
  21. package/dist/engine.d.ts.map +1 -1
  22. package/dist/engine.js +1 -21
  23. package/dist/engine.js.map +1 -1
  24. package/dist/entries/actions.d.ts +1 -0
  25. package/dist/entries/actions.d.ts.map +1 -1
  26. package/dist/entries/actions.js +7 -0
  27. package/dist/entries/actions.js.map +1 -1
  28. package/dist/entries/types.d.ts +0 -1
  29. package/dist/entries/types.d.ts.map +1 -1
  30. package/dist/index.d.ts +0 -3
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +0 -7
  33. package/dist/index.js.map +1 -1
  34. package/dist/schema.d.ts +1 -5
  35. package/dist/schema.d.ts.map +1 -1
  36. package/dist/schema.js +0 -54
  37. package/dist/schema.js.map +1 -1
  38. package/dist/sw/build/vite-plugin.d.ts +0 -6
  39. package/dist/sw/build/vite-plugin.d.ts.map +1 -1
  40. package/dist/sw/build/vite-plugin.js +0 -3
  41. package/dist/sw/build/vite-plugin.js.map +1 -1
  42. package/package.json +2 -7
  43. package/dist/crdt/awareness.d.ts +0 -128
  44. package/dist/crdt/awareness.d.ts.map +0 -1
  45. package/dist/crdt/awareness.js +0 -284
  46. package/dist/crdt/awareness.js.map +0 -1
  47. package/dist/crdt/channel.d.ts +0 -167
  48. package/dist/crdt/channel.d.ts.map +0 -1
  49. package/dist/crdt/channel.js +0 -546
  50. package/dist/crdt/channel.js.map +0 -1
  51. package/dist/crdt/config.d.ts +0 -58
  52. package/dist/crdt/config.d.ts.map +0 -1
  53. package/dist/crdt/config.js +0 -123
  54. package/dist/crdt/config.js.map +0 -1
  55. package/dist/crdt/helpers.d.ts +0 -104
  56. package/dist/crdt/helpers.d.ts.map +0 -1
  57. package/dist/crdt/helpers.js +0 -116
  58. package/dist/crdt/helpers.js.map +0 -1
  59. package/dist/crdt/offline.d.ts +0 -58
  60. package/dist/crdt/offline.d.ts.map +0 -1
  61. package/dist/crdt/offline.js +0 -130
  62. package/dist/crdt/offline.js.map +0 -1
  63. package/dist/crdt/persistence.d.ts +0 -74
  64. package/dist/crdt/persistence.d.ts.map +0 -1
  65. package/dist/crdt/persistence.js +0 -207
  66. package/dist/crdt/persistence.js.map +0 -1
  67. package/dist/crdt/provider.d.ts +0 -111
  68. package/dist/crdt/provider.d.ts.map +0 -1
  69. package/dist/crdt/provider.js +0 -615
  70. package/dist/crdt/provider.js.map +0 -1
  71. package/dist/crdt/store.d.ts +0 -111
  72. package/dist/crdt/store.d.ts.map +0 -1
  73. package/dist/crdt/store.js +0 -158
  74. package/dist/crdt/store.js.map +0 -1
  75. package/dist/crdt/types.d.ts +0 -281
  76. package/dist/crdt/types.d.ts.map +0 -1
  77. package/dist/crdt/types.js +0 -26
  78. package/dist/crdt/types.js.map +0 -1
  79. package/dist/entries/crdt.d.ts +0 -32
  80. package/dist/entries/crdt.d.ts.map +0 -1
  81. package/dist/entries/crdt.js +0 -52
  82. package/dist/entries/crdt.js.map +0 -1
@@ -1,615 +0,0 @@
1
- /**
2
- * @fileoverview CRDT Document Provider — Per-Document Lifecycle Manager
3
- *
4
- * The `CRDTProvider` is the central orchestrator for a single collaborative
5
- * document. It manages:
6
- * - Yjs `Y.Doc` creation and state loading (from IndexedDB or Supabase)
7
- * - Wiring `doc.on('update')` to persistence, broadcast, and crash recovery
8
- * - Supabase Broadcast channel for real-time update distribution
9
- * - Periodic Supabase persistence timer
10
- * - Local IndexedDB full-state saves (debounced)
11
- * - Document lifecycle (open → edit → close → destroy)
12
- *
13
- * Module-level `Map<string, CRDTProvider>` tracks all active providers.
14
- * Factory functions {@link openDocument} / {@link closeDocument} manage the lifecycle.
15
- *
16
- * @see {@link ./channel.ts} for Broadcast channel management
17
- * @see {@link ./store.ts} for IndexedDB persistence
18
- * @see {@link ./persistence.ts} for Supabase persistence
19
- * @see {@link ./awareness.ts} for cursor/presence management
20
- *
21
- * @example
22
- * import { openDocument, closeDocument } from 'stellar-drive/crdt';
23
- *
24
- * const provider = await openDocument('doc-1', 'page-1', { offlineEnabled: true });
25
- * // provider.doc is a Y.Doc — use with your editor
26
- * // ...
27
- * await closeDocument('doc-1');
28
- */
29
- import * as Y from 'yjs';
30
- import { debugLog, debugWarn } from '../debug';
31
- import { isOnline } from '../stores/network';
32
- import { getCRDTConfig } from './config';
33
- import { CRDTChannel } from './channel';
34
- import { loadDocumentState, saveDocumentState, appendPendingUpdate, loadPendingUpdates, clearPendingUpdates } from './store';
35
- import { fetchRemoteState, persistDocument } from './persistence';
36
- import { joinPresence, leavePresence } from './awareness';
37
- // =============================================================================
38
- // Active Provider Registry
39
- // =============================================================================
40
- /**
41
- * Tracks all currently active CRDT providers, keyed by `documentId`.
42
- *
43
- * This ensures:
44
- * 1. `openDocument()` is idempotent — returns existing provider if already open
45
- * 2. `closeAllDocuments()` can tear down everything on sign-out
46
- * 3. Reconnection logic can iterate active providers
47
- */
48
- const activeProviders = new Map();
49
- /** Tracks in-flight openDocument init promises for concurrent-safety. */
50
- const initPromises = new Map();
51
- // =============================================================================
52
- // CRDTProvider Implementation (internal)
53
- // =============================================================================
54
- /**
55
- * Internal implementation of the CRDT provider.
56
- *
57
- * Manages the full lifecycle of a collaborative document: loading initial
58
- * state, wiring update handlers, managing the Broadcast channel, and
59
- * coordinating persistence.
60
- *
61
- * @internal
62
- */
63
- class CRDTProviderImpl {
64
- constructor(documentId, pageId, offlineEnabled) {
65
- this._connectionState = 'disconnected';
66
- this._isDirty = false;
67
- /** Broadcast channel for this document. */
68
- this.channel = null;
69
- /** Timer for periodic Supabase persistence. */
70
- this.persistTimer = null;
71
- /** Timer for debounced local IndexedDB full-state saves. */
72
- this.localSaveTimer = null;
73
- /** Yjs update handler reference (for cleanup). */
74
- this.updateHandler = null;
75
- /** Whether this provider has been destroyed. */
76
- this.destroyed = false;
77
- /** Last state vector at the time of last Supabase persist (for dirty detection). */
78
- this.lastPersistedStateVector = null;
79
- /** Guard against concurrent persist operations. */
80
- this.persistInProgress = false;
81
- /** The in-flight persist promise (for awaiting in destroy). */
82
- this.persistPromise = null;
83
- /** Guard against concurrent reconnect operations. */
84
- this.reconnectInProgress = false;
85
- /** Whether the current online state is true. */
86
- this._isOnline = true;
87
- /** Store subscription cleanup function. */
88
- this.onlineUnsubscribe = null;
89
- /** Generation counter for saveToIndexedDB race prevention. */
90
- this.saveGeneration = 0;
91
- /** Resolves when network sync (channel join + sync protocol) completes. */
92
- this.networkReady = Promise.resolve();
93
- this.documentId = documentId;
94
- this.pageId = pageId;
95
- this.offlineEnabled = offlineEnabled;
96
- this.doc = new Y.Doc();
97
- }
98
- get connectionState() {
99
- return this._connectionState;
100
- }
101
- get isDirty() {
102
- return this._isDirty;
103
- }
104
- // ===========================================================================
105
- // Initialization
106
- // ===========================================================================
107
- /**
108
- * Initialize the provider: load state, wire handlers, join channel.
109
- *
110
- * Called by {@link openDocument} after construction.
111
- */
112
- async init(options) {
113
- /* Subscribe to online status. */
114
- this.onlineUnsubscribe = isOnline.subscribe((online) => {
115
- const wasOffline = !this._isOnline;
116
- this._isOnline = online;
117
- /* Reconnect on online transition. */
118
- if (online && wasOffline && !this.destroyed) {
119
- this.handleReconnect();
120
- }
121
- });
122
- /* Step 1: Load initial state. */
123
- await this.loadInitialState();
124
- if (this.destroyed)
125
- return;
126
- /* Step 2: Wire the update handler. */
127
- this.wireUpdateHandler();
128
- /* Step 3: Start periodic Supabase persist timer. */
129
- this.startPersistTimer();
130
- /* Record initial state vector for dirty detection. */
131
- this.lastPersistedStateVector = Y.encodeStateVector(this.doc);
132
- /* Step 4: Join the Broadcast channel (if online) — background, non-blocking. */
133
- if (this._isOnline) {
134
- this.networkReady = this.initNetwork(options).catch((e) => {
135
- debugWarn(`[CRDT] Document ${this.documentId}: network init failed:`, e);
136
- });
137
- }
138
- else {
139
- this.networkReady = Promise.resolve();
140
- }
141
- debugLog(`[CRDT] Opening document ${this.documentId} (pageId=${this.pageId}, offlineEnabled=${this.offlineEnabled})`);
142
- }
143
- /**
144
- * Initialize network layer (channel + sync + presence) — runs in background.
145
- */
146
- async initNetwork(options) {
147
- await this.joinChannel();
148
- if (this.destroyed)
149
- return;
150
- /* Run sync protocol. */
151
- if (this.channel) {
152
- const peersResponded = await this.channel.waitForSync();
153
- if (this.destroyed)
154
- return;
155
- if (!peersResponded) {
156
- /* No peers online — fetch latest state from Supabase if available. */
157
- await this.fetchAndMergeRemoteState();
158
- if (this.destroyed)
159
- return;
160
- }
161
- }
162
- /* Join presence if initial presence was provided. */
163
- if (options.initialPresence) {
164
- joinPresence(this.documentId, this.channel?.connectionState === 'connected', {
165
- name: options.initialPresence.name,
166
- avatarUrl: options.initialPresence.avatarUrl
167
- });
168
- /* Set presence info on the channel so Supabase Presence tracks this user. */
169
- this.channel?.setPresenceInfo({
170
- name: options.initialPresence.name,
171
- avatarUrl: options.initialPresence.avatarUrl
172
- });
173
- }
174
- }
175
- // ===========================================================================
176
- // State Loading
177
- // ===========================================================================
178
- /**
179
- * Load the initial document state from IndexedDB or Supabase.
180
- *
181
- * Priority:
182
- * 1. IndexedDB (if offline-enabled and has stored state)
183
- * 2. Supabase (if online and no local state)
184
- * 3. Empty doc (if offline and no local state)
185
- */
186
- async loadInitialState() {
187
- /* Try IndexedDB first. */
188
- const localRecord = await loadDocumentState(this.documentId);
189
- if (localRecord) {
190
- /* Apply stored full state. */
191
- Y.applyUpdate(this.doc, localRecord.state);
192
- /* Replay any pending updates that weren't captured in the last full save.
193
- * Use 'load' origin to prevent update handler from re-queuing/re-broadcasting. */
194
- const pendingUpdates = await loadPendingUpdates(this.documentId);
195
- if (pendingUpdates.length > 0) {
196
- const merged = Y.mergeUpdates(pendingUpdates.map((p) => p.update));
197
- Y.applyUpdate(this.doc, merged, 'load');
198
- debugLog(`[CRDT] Document ${this.documentId} loaded from IndexedDB (${localRecord.stateSize} bytes, ${pendingUpdates.length} pending updates)`);
199
- }
200
- else {
201
- debugLog(`[CRDT] Document ${this.documentId} loaded from IndexedDB (${localRecord.stateSize} bytes, 0 pending updates)`);
202
- }
203
- return;
204
- }
205
- /* No local state — try Supabase if online. */
206
- if (this._isOnline) {
207
- await this.fetchAndMergeRemoteState();
208
- return;
209
- }
210
- /* Offline with no local state — start with empty doc. */
211
- debugLog(`[CRDT] Document ${this.documentId} started with empty state (offline, no local cache)`);
212
- }
213
- /**
214
- * Fetch the latest document state from Supabase and merge into local doc.
215
- */
216
- async fetchAndMergeRemoteState() {
217
- try {
218
- const remoteState = await fetchRemoteState(this.pageId);
219
- if (remoteState) {
220
- Y.applyUpdate(this.doc, remoteState);
221
- debugLog(`[CRDT] Document ${this.documentId} loaded from Supabase (${remoteState.byteLength} bytes)`);
222
- }
223
- }
224
- catch (e) {
225
- debugWarn(`[CRDT] Document ${this.documentId}: failed to fetch remote state:`, e);
226
- }
227
- }
228
- // ===========================================================================
229
- // Update Handler
230
- // ===========================================================================
231
- /**
232
- * Wire the `doc.on('update')` handler that drives all downstream effects.
233
- *
234
- * On each Yjs update:
235
- * 1. Queue incremental update to IndexedDB (crash safety)
236
- * 2. Broadcast to remote peers (debounced 100ms)
237
- * 3. Broadcast to same-device tabs (immediate)
238
- * 4. Schedule debounced full-state save to IndexedDB (5s)
239
- */
240
- wireUpdateHandler() {
241
- this.updateHandler = (update, origin) => {
242
- /* Skip updates that originated from remote peers or replayed loads. */
243
- if (origin === 'remote' || origin === 'load')
244
- return;
245
- this._isDirty = true;
246
- /* 1. Crash-safe: append incremental update to IndexedDB. */
247
- if (this.offlineEnabled) {
248
- appendPendingUpdate(this.documentId, update).catch(() => {
249
- /* Non-critical — full state save will capture it. */
250
- });
251
- }
252
- /* 2. Broadcast to remote peers (debounced). */
253
- this.channel?.broadcastUpdate(update);
254
- /* 3. Schedule debounced local full-state save. */
255
- if (this.offlineEnabled) {
256
- this.scheduleLocalSave();
257
- }
258
- };
259
- this.doc.on('update', this.updateHandler);
260
- }
261
- // ===========================================================================
262
- // Local Persistence (IndexedDB)
263
- // ===========================================================================
264
- /**
265
- * Schedule a debounced full-state save to IndexedDB.
266
- *
267
- * Resets the timer on each call so rapid edits don't cause excessive writes.
268
- */
269
- scheduleLocalSave() {
270
- if (this.localSaveTimer) {
271
- clearTimeout(this.localSaveTimer);
272
- }
273
- const config = getCRDTConfig();
274
- this.localSaveTimer = setTimeout(() => {
275
- this.localSaveTimer = null;
276
- this.saveToIndexedDB();
277
- }, config.localSaveDebounceMs);
278
- }
279
- /**
280
- * Save the current full document state to IndexedDB.
281
- *
282
- * Also clears pending updates since they're now captured in the full state.
283
- */
284
- async saveToIndexedDB(force = false) {
285
- if (!force && this.destroyed)
286
- return;
287
- /* Record generation before snapshot — only clear updates that existed before this save. */
288
- const gen = ++this.saveGeneration;
289
- const state = Y.encodeStateAsUpdate(this.doc);
290
- const stateVector = Y.encodeStateVector(this.doc);
291
- const record = {
292
- documentId: this.documentId,
293
- pageId: this.pageId,
294
- state,
295
- stateVector,
296
- offlineEnabled: this.offlineEnabled ? 1 : 0,
297
- localUpdatedAt: new Date().toISOString(),
298
- lastPersistedAt: null, // Will be set by Supabase persist
299
- stateSize: state.byteLength
300
- };
301
- /* Preserve existing lastPersistedAt if we're just doing a local save. */
302
- const existing = await loadDocumentState(this.documentId);
303
- if (existing?.lastPersistedAt) {
304
- record.lastPersistedAt = existing.lastPersistedAt;
305
- }
306
- await saveDocumentState(record);
307
- /* Only clear pending updates if no new save was triggered while we were writing. */
308
- if (gen === this.saveGeneration) {
309
- await clearPendingUpdates(this.documentId);
310
- }
311
- }
312
- // ===========================================================================
313
- // Supabase Persistence Timer
314
- // ===========================================================================
315
- /**
316
- * Start the periodic timer that persists dirty documents to Supabase.
317
- */
318
- startPersistTimer() {
319
- const config = getCRDTConfig();
320
- this.persistTimer = setInterval(() => {
321
- this.tryPersistToSupabase();
322
- }, config.persistIntervalMs);
323
- }
324
- /**
325
- * Attempt to persist the document to Supabase if it's dirty and online.
326
- *
327
- * @returns `true` if persist succeeded, `false` if skipped or failed.
328
- */
329
- tryPersistToSupabase(force = false) {
330
- if (!force && this.destroyed)
331
- return Promise.resolve(false);
332
- if (!this._isOnline || !this._isDirty)
333
- return Promise.resolve(false);
334
- /* Check if state has actually changed since last persist. */
335
- const currentStateVector = Y.encodeStateVector(this.doc);
336
- if (this.lastPersistedStateVector &&
337
- arraysEqual(currentStateVector, this.lastPersistedStateVector)) {
338
- debugLog(`[CRDT] Document ${this.documentId}: Supabase persist skipped (not dirty)`);
339
- return Promise.resolve(false);
340
- }
341
- /* Guard against concurrent persists. */
342
- if (this.persistInProgress) {
343
- debugLog(`[CRDT] Document ${this.documentId}: persist already in progress, skipping`);
344
- return Promise.resolve(false);
345
- }
346
- this.persistInProgress = true;
347
- const promise = (async () => {
348
- try {
349
- await persistDocument(this.documentId, this.doc);
350
- this.lastPersistedStateVector = currentStateVector;
351
- this._isDirty = false;
352
- /* Update local record's lastPersistedAt. */
353
- if (this.offlineEnabled) {
354
- const existing = await loadDocumentState(this.documentId);
355
- if (existing) {
356
- existing.lastPersistedAt = new Date().toISOString();
357
- await saveDocumentState(existing);
358
- }
359
- }
360
- return true;
361
- }
362
- catch (e) {
363
- debugWarn(`[CRDT] Document ${this.documentId}: Supabase persist failed:`, e);
364
- return false;
365
- }
366
- finally {
367
- this.persistInProgress = false;
368
- this.persistPromise = null;
369
- }
370
- })();
371
- this.persistPromise = promise.then(() => { });
372
- return promise;
373
- }
374
- // ===========================================================================
375
- // Channel Management
376
- // ===========================================================================
377
- /**
378
- * Join the Supabase Broadcast channel for this document.
379
- */
380
- async joinChannel() {
381
- this.channel = new CRDTChannel(this.documentId, this.doc, (state) => {
382
- this._connectionState = state;
383
- });
384
- await this.channel.join();
385
- }
386
- // ===========================================================================
387
- // Reconnection
388
- // ===========================================================================
389
- /**
390
- * Handle offline → online transition.
391
- *
392
- * Merges pending updates, rejoins the Broadcast channel, runs sync protocol,
393
- * and persists the merged state to Supabase.
394
- */
395
- async handleReconnect() {
396
- /* Guard against concurrent reconnects. */
397
- if (this.reconnectInProgress) {
398
- debugLog(`[CRDT] Document ${this.documentId}: reconnect already in progress, skipping`);
399
- return;
400
- }
401
- this.reconnectInProgress = true;
402
- try {
403
- debugLog(`[CRDT] Document ${this.documentId}: reconnecting after coming online`);
404
- /* Merge any pending updates accumulated while offline.
405
- * Use 'load' origin so the update handler doesn't re-queue or re-broadcast them. */
406
- const pendingUpdates = await loadPendingUpdates(this.documentId);
407
- if (pendingUpdates.length > 0) {
408
- debugLog(`[CRDT] Document ${this.documentId}: merging ${pendingUpdates.length} pending updates after reconnect`);
409
- const merged = Y.mergeUpdates(pendingUpdates.map((p) => p.update));
410
- Y.applyUpdate(this.doc, merged, 'load');
411
- }
412
- /* Rejoin Broadcast channel. */
413
- if (this.channel) {
414
- await this.channel.leave();
415
- }
416
- await this.joinChannel();
417
- /* Run sync protocol. */
418
- if (this.channel) {
419
- const peersResponded = await this.channel.waitForSync();
420
- if (!peersResponded) {
421
- await this.fetchAndMergeRemoteState();
422
- }
423
- }
424
- /* Broadcast our pending updates to peers. */
425
- const state = Y.encodeStateAsUpdate(this.doc);
426
- this.channel?.broadcastUpdate(state);
427
- /* Immediately persist merged state to Supabase. */
428
- this._isDirty = true;
429
- const persisted = await this.tryPersistToSupabase();
430
- /* Only clear pending updates if persist succeeded. */
431
- if (persisted) {
432
- await clearPendingUpdates(this.documentId);
433
- }
434
- debugLog(`[CRDT] Document ${this.documentId}: reconnection sync complete, state size ${state.byteLength} bytes`);
435
- }
436
- finally {
437
- this.reconnectInProgress = false;
438
- }
439
- }
440
- // ===========================================================================
441
- // Destruction
442
- // ===========================================================================
443
- /**
444
- * Destroy this provider: save final state, leave channel, clean up.
445
- */
446
- async destroy() {
447
- if (this.destroyed)
448
- return;
449
- this.destroyed = true;
450
- debugLog(`[CRDT] Closing document ${this.documentId} (dirty=${this._isDirty}, online=${this._isOnline})`);
451
- /* Stop timers. */
452
- if (this.persistTimer) {
453
- clearInterval(this.persistTimer);
454
- this.persistTimer = null;
455
- }
456
- if (this.localSaveTimer) {
457
- clearTimeout(this.localSaveTimer);
458
- this.localSaveTimer = null;
459
- }
460
- /* Unwire update handler. */
461
- if (this.updateHandler) {
462
- this.doc.off('update', this.updateHandler);
463
- this.updateHandler = null;
464
- }
465
- /* Unsubscribe from online store. */
466
- if (this.onlineUnsubscribe) {
467
- this.onlineUnsubscribe();
468
- this.onlineUnsubscribe = null;
469
- }
470
- /* Save final state to IndexedDB. */
471
- if (this.offlineEnabled) {
472
- await this.saveToIndexedDB(true);
473
- }
474
- /* Await any in-flight persist before final persist attempt. */
475
- if (this.persistPromise) {
476
- await this.persistPromise;
477
- }
478
- /* Persist to Supabase if online and dirty (force=true bypasses destroyed check). */
479
- if (this._isOnline && this._isDirty) {
480
- await this.tryPersistToSupabase(true);
481
- }
482
- /* Leave presence. */
483
- leavePresence(this.documentId);
484
- /* Leave Broadcast channel. */
485
- if (this.channel) {
486
- await this.channel.leave();
487
- this.channel = null;
488
- }
489
- /* Destroy Y.Doc. */
490
- this.doc.destroy();
491
- /* Remove from active providers. */
492
- activeProviders.delete(this.documentId);
493
- }
494
- }
495
- // =============================================================================
496
- // Utility
497
- // =============================================================================
498
- /** Compare two Uint8Arrays for equality. */
499
- function arraysEqual(a, b) {
500
- if (a.length !== b.length)
501
- return false;
502
- for (let i = 0; i < a.length; i++) {
503
- if (a[i] !== b[i])
504
- return false;
505
- }
506
- return true;
507
- }
508
- // =============================================================================
509
- // Public Factory Functions
510
- // =============================================================================
511
- /**
512
- * Open a collaborative CRDT document.
513
- *
514
- * Creates a new `CRDTProvider` for the document, loads its initial state
515
- * (from IndexedDB or Supabase), wires update handlers, joins the Broadcast
516
- * channel, and starts the periodic persist timer.
517
- *
518
- * **Idempotent:** If the document is already open, returns the existing provider.
519
- *
520
- * @param documentId - Unique identifier for the document.
521
- * @param pageId - The page/entity this document belongs to.
522
- * @param options - Optional configuration (offline mode, initial presence).
523
- * @returns The active `CRDTProvider` for this document.
524
- *
525
- * @throws {Error} If CRDT is not configured in `initEngine()`.
526
- *
527
- * @example
528
- * const provider = await openDocument('doc-1', 'page-1', {
529
- * offlineEnabled: true,
530
- * initialPresence: { name: 'Alice' },
531
- * });
532
- * const text = provider.doc.getText('content');
533
- */
534
- export async function openDocument(documentId, pageId, options = {}) {
535
- /* Ensure CRDT is configured (getCRDTConfig throws if not). */
536
- getCRDTConfig();
537
- /* Return existing provider if already open (idempotent). */
538
- const existing = activeProviders.get(documentId);
539
- if (existing)
540
- return existing;
541
- /* If init is already in-flight for this document, await the same promise. */
542
- const inflight = initPromises.get(documentId);
543
- if (inflight)
544
- return inflight;
545
- /* Create and initialize a new provider. */
546
- const provider = new CRDTProviderImpl(documentId, pageId, options.offlineEnabled ?? false);
547
- activeProviders.set(documentId, provider);
548
- const promise = (async () => {
549
- try {
550
- await provider.init(options);
551
- return provider;
552
- }
553
- catch (e) {
554
- /* Clean up on initialization failure — use provider.destroy() to release all resources. */
555
- await provider.destroy();
556
- throw e;
557
- }
558
- finally {
559
- initPromises.delete(documentId);
560
- }
561
- })();
562
- initPromises.set(documentId, promise);
563
- return promise;
564
- }
565
- /**
566
- * Close a specific CRDT document.
567
- *
568
- * Saves final state, persists to Supabase if dirty, leaves the Broadcast
569
- * channel, and destroys the Y.Doc.
570
- *
571
- * @param documentId - The document to close.
572
- */
573
- export async function closeDocument(documentId) {
574
- const provider = activeProviders.get(documentId);
575
- if (!provider)
576
- return;
577
- await provider.destroy();
578
- }
579
- /**
580
- * Close all active CRDT documents.
581
- *
582
- * Called during sign-out to ensure all documents are properly saved and
583
- * all channels are cleaned up. Each document is closed in parallel.
584
- */
585
- export async function closeAllDocuments() {
586
- const count = activeProviders.size;
587
- if (count === 0)
588
- return;
589
- const promises = Array.from(activeProviders.values()).map((p) => p.destroy());
590
- await Promise.allSettled(promises);
591
- debugLog(`[CRDT] All documents closed (count=${count})`);
592
- }
593
- /**
594
- * Get the active provider for a document, if open.
595
- *
596
- * @param documentId - The document to look up.
597
- * @returns The active provider, or `undefined` if not open.
598
- * @internal
599
- */
600
- export function getActiveProvider(documentId) {
601
- return activeProviders.get(documentId);
602
- }
603
- /**
604
- * Get all active provider entries for iteration.
605
- *
606
- * Used by {@link persistence.ts#persistAllDirty} to iterate and persist
607
- * all dirty documents. Returns `[documentId, provider]` pairs.
608
- *
609
- * @returns Iterator of `[documentId, CRDTProvider]` entries.
610
- * @internal
611
- */
612
- export function getActiveProviderEntries() {
613
- return activeProviders.entries();
614
- }
615
- //# sourceMappingURL=provider.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/crdt/provider.ts"],"names":[],"mappings":"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"}