@dabble/patches 0.7.14 → 0.7.16
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.
- package/README.md +4 -4
- package/dist/{BaseDoc-vaMreJL5.d.ts → BaseDoc-BRIP2YZp.d.ts} +16 -35
- package/dist/algorithms/ot/server/commitChanges.d.ts +1 -1
- package/dist/client/BaseDoc.d.ts +2 -2
- package/dist/client/BaseDoc.js +13 -38
- package/dist/client/ClientAlgorithm.d.ts +2 -2
- package/dist/client/IndexedDBStore.d.ts +2 -2
- package/dist/client/IndexedDBStore.js +3 -8
- package/dist/client/LWWAlgorithm.d.ts +2 -2
- package/dist/client/LWWDoc.d.ts +3 -3
- package/dist/client/LWWDoc.js +10 -7
- package/dist/client/LWWIndexedDBStore.d.ts +1 -1
- package/dist/client/LWWIndexedDBStore.js +4 -4
- package/dist/client/OTAlgorithm.d.ts +2 -2
- package/dist/client/OTDoc.d.ts +2 -2
- package/dist/client/OTDoc.js +7 -8
- package/dist/client/OTIndexedDBStore.d.ts +1 -1
- package/dist/client/OTIndexedDBStore.js +3 -3
- package/dist/client/Patches.d.ts +9 -8
- package/dist/client/Patches.js +9 -6
- package/dist/client/PatchesDoc.d.ts +2 -2
- package/dist/client/PatchesHistoryClient.d.ts +5 -11
- package/dist/client/PatchesHistoryClient.js +14 -29
- package/dist/client/factories.d.ts +2 -2
- package/dist/client/index.d.ts +2 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +23 -2
- package/dist/net/PatchesClient.d.ts +3 -3
- package/dist/net/PatchesClient.js +1 -1
- package/dist/net/PatchesSync.d.ts +14 -29
- package/dist/net/PatchesSync.js +84 -98
- package/dist/net/http/FetchTransport.d.ts +2 -2
- package/dist/net/http/FetchTransport.js +1 -1
- package/dist/net/index.d.ts +2 -2
- package/dist/net/protocol/JSONRPCClient.d.ts +1 -1
- package/dist/net/protocol/JSONRPCClient.js +1 -1
- package/dist/net/protocol/JSONRPCServer.d.ts +1 -1
- package/dist/net/protocol/JSONRPCServer.js +1 -1
- package/dist/net/protocol/types.d.ts +1 -1
- package/dist/net/protocol/utils.d.ts +1 -1
- package/dist/net/webrtc/WebRTCAwareness.d.ts +2 -2
- package/dist/net/webrtc/WebRTCAwareness.js +1 -1
- package/dist/net/webrtc/WebRTCTransport.d.ts +5 -5
- package/dist/net/webrtc/WebRTCTransport.js +1 -1
- package/dist/net/webrtc/index.d.ts +1 -1
- package/dist/net/websocket/PatchesWebSocket.d.ts +1 -1
- package/dist/net/websocket/PatchesWebSocket.js +1 -1
- package/dist/net/websocket/SignalingService.d.ts +1 -1
- package/dist/net/websocket/WebSocketServer.d.ts +1 -1
- package/dist/net/websocket/WebSocketTransport.d.ts +4 -3
- package/dist/net/websocket/WebSocketTransport.js +1 -1
- package/dist/net/websocket/onlineState.d.ts +2 -2
- package/dist/net/websocket/onlineState.js +1 -1
- package/dist/server/LWWBranchManager.d.ts +1 -1
- package/dist/server/LWWServer.d.ts +3 -3
- package/dist/server/LWWServer.js +1 -1
- package/dist/server/OTBranchManager.d.ts +1 -1
- package/dist/server/OTServer.d.ts +3 -3
- package/dist/server/OTServer.js +1 -1
- package/dist/server/PatchesHistoryManager.d.ts +1 -1
- package/dist/server/PatchesServer.d.ts +1 -1
- package/dist/server/branchUtils.d.ts +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/shared/doc-manager.d.ts +2 -2
- package/dist/shared/utils.d.ts +2 -2
- package/dist/shared/utils.js +2 -2
- package/dist/solid/context.d.ts +2 -2
- package/dist/solid/doc-manager.d.ts +2 -2
- package/dist/solid/index.d.ts +2 -2
- package/dist/solid/managed-docs.js +1 -1
- package/dist/solid/primitives.d.ts +2 -2
- package/dist/solid/primitives.js +7 -7
- package/dist/types.d.ts +4 -4
- package/dist/vue/composables.d.ts +2 -2
- package/dist/vue/composables.js +7 -7
- package/dist/vue/doc-manager.d.ts +2 -2
- package/dist/vue/index.d.ts +2 -2
- package/dist/vue/managed-docs.d.ts +2 -2
- package/dist/vue/managed-docs.js +1 -1
- package/dist/vue/provider.d.ts +2 -2
- package/package.json +2 -1
- package/dist/event-signal.d.ts +0 -32
- package/dist/event-signal.js +0 -25
package/dist/net/PatchesSync.js
CHANGED
|
@@ -5,25 +5,29 @@ import {
|
|
|
5
5
|
__publicField,
|
|
6
6
|
__runInitializers
|
|
7
7
|
} from "../chunk-IZ2YBCUP.js";
|
|
8
|
-
var __receiveCommittedChanges_dec, _syncDoc_dec, _init;
|
|
8
|
+
var __receiveCommittedChanges_dec, _syncDoc_dec, _a, _init;
|
|
9
9
|
import { isEqual } from "@dabble/delta";
|
|
10
|
+
import { batch, ReadonlyStoreClass, signal, store } from "easy-signal";
|
|
10
11
|
import { breakChangesIntoBatches } from "../algorithms/ot/shared/changeBatching.js";
|
|
11
12
|
import { BaseDoc } from "../client/BaseDoc.js";
|
|
12
13
|
import { Patches } from "../client/Patches.js";
|
|
13
|
-
import { signal } from "../event-signal.js";
|
|
14
14
|
import { isDocLoaded } from "../shared/utils.js";
|
|
15
15
|
import { blockable } from "../utils/concurrency.js";
|
|
16
16
|
import { PatchesWebSocket } from "./websocket/PatchesWebSocket.js";
|
|
17
17
|
import { onlineState } from "./websocket/onlineState.js";
|
|
18
|
-
const
|
|
18
|
+
const EMPTY_DOC_STATE = {
|
|
19
19
|
committedRev: 0,
|
|
20
20
|
hasPending: false,
|
|
21
21
|
syncStatus: "unsynced",
|
|
22
22
|
isLoaded: false
|
|
23
23
|
};
|
|
24
|
-
_syncDoc_dec = [blockable], __receiveCommittedChanges_dec = [blockable]
|
|
25
|
-
class PatchesSync {
|
|
24
|
+
class PatchesSync extends (_a = ReadonlyStoreClass, _syncDoc_dec = [blockable], __receiveCommittedChanges_dec = [blockable], _a) {
|
|
26
25
|
constructor(patches, url, options) {
|
|
26
|
+
super({
|
|
27
|
+
online: onlineState.isOnline,
|
|
28
|
+
connected: false,
|
|
29
|
+
syncStatus: "unsynced"
|
|
30
|
+
});
|
|
27
31
|
this.options = options;
|
|
28
32
|
__runInitializers(_init, 5, this);
|
|
29
33
|
__publicField(this, "ws");
|
|
@@ -34,17 +38,10 @@ class PatchesSync {
|
|
|
34
38
|
__publicField(this, "trackedDocs");
|
|
35
39
|
/** Maps docId to the algorithm name used for that doc */
|
|
36
40
|
__publicField(this, "docAlgorithms", /* @__PURE__ */ new Map());
|
|
37
|
-
__publicField(this, "_state", {
|
|
38
|
-
online: false,
|
|
39
|
-
connected: false,
|
|
40
|
-
syncStatus: "unsynced",
|
|
41
|
-
syncError: void 0
|
|
42
|
-
});
|
|
43
|
-
__publicField(this, "_syncedDocs", {});
|
|
44
41
|
/**
|
|
45
|
-
*
|
|
42
|
+
* Reactive store tracking per-document sync state.
|
|
46
43
|
*/
|
|
47
|
-
__publicField(this, "
|
|
44
|
+
__publicField(this, "docStates");
|
|
48
45
|
/**
|
|
49
46
|
* Signal emitted when an error occurs.
|
|
50
47
|
*/
|
|
@@ -54,16 +51,12 @@ class PatchesSync {
|
|
|
54
51
|
* Provides the pending changes that were discarded so the application can handle them.
|
|
55
52
|
*/
|
|
56
53
|
__publicField(this, "onRemoteDocDeleted", signal());
|
|
57
|
-
/**
|
|
58
|
-
* Signal emitted when the synced doc map changes.
|
|
59
|
-
*/
|
|
60
|
-
__publicField(this, "onSyncedDocsChange", signal());
|
|
61
54
|
this.patches = patches;
|
|
62
55
|
this.maxPayloadBytes = options?.maxPayloadBytes;
|
|
63
56
|
this.maxStorageBytes = options?.maxStorageBytes ?? patches.docOptions?.maxStorageBytes;
|
|
64
57
|
this.sizeCalculator = options?.sizeCalculator ?? patches.docOptions?.sizeCalculator;
|
|
65
58
|
this.ws = new PatchesWebSocket(url, options?.websocket);
|
|
66
|
-
this.
|
|
59
|
+
this.docStates = store({});
|
|
67
60
|
this.trackedDocs = new Set(patches.trackedDocs);
|
|
68
61
|
onlineState.onOnlineChange((online) => this.updateState({ online }));
|
|
69
62
|
this.ws.onStateChange(this._handleConnectionChange.bind(this));
|
|
@@ -104,19 +97,6 @@ class PatchesSync {
|
|
|
104
97
|
this.ws.connect();
|
|
105
98
|
}
|
|
106
99
|
}
|
|
107
|
-
/**
|
|
108
|
-
* Gets the current sync state.
|
|
109
|
-
*/
|
|
110
|
-
get state() {
|
|
111
|
-
return this._state;
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Map of all tracked documents and their current sync status.
|
|
115
|
-
* Updated immutably — new object reference on every change.
|
|
116
|
-
*/
|
|
117
|
-
get syncedDocs() {
|
|
118
|
-
return this._syncedDocs;
|
|
119
|
-
}
|
|
120
100
|
/**
|
|
121
101
|
* Gets the JSON-RPC client for making custom RPC calls.
|
|
122
102
|
* Useful for application-specific methods not part of the Patches protocol.
|
|
@@ -129,13 +109,12 @@ class PatchesSync {
|
|
|
129
109
|
* @param update - The partial state to update.
|
|
130
110
|
*/
|
|
131
111
|
updateState(update) {
|
|
132
|
-
const newState = { ...this.
|
|
112
|
+
const newState = { ...this.state, ...update };
|
|
133
113
|
if (newState.syncStatus !== "error" && newState.syncError) {
|
|
134
114
|
newState.syncError = void 0;
|
|
135
115
|
}
|
|
136
|
-
if (!isEqual(this.
|
|
137
|
-
this.
|
|
138
|
-
this.onStateChange.emit(this._state);
|
|
116
|
+
if (!isEqual(this.state, newState)) {
|
|
117
|
+
this.state = newState;
|
|
139
118
|
}
|
|
140
119
|
}
|
|
141
120
|
/**
|
|
@@ -193,12 +172,11 @@ class PatchesSync {
|
|
|
193
172
|
syncError: void 0,
|
|
194
173
|
isLoaded: false
|
|
195
174
|
};
|
|
196
|
-
const existing = this.
|
|
197
|
-
entry.isLoaded = existing?.isLoaded || isDocLoaded(entry);
|
|
175
|
+
const existing = this.docStates.state[doc.docId];
|
|
176
|
+
entry.isLoaded = existing?.isLoaded || isDocLoaded(entry.committedRev, entry.hasPending, entry.syncStatus);
|
|
198
177
|
syncedEntries[doc.docId] = entry;
|
|
199
178
|
}
|
|
200
|
-
this.
|
|
201
|
-
this.onSyncedDocsChange.emit(this._syncedDocs);
|
|
179
|
+
this.docStates.state = syncedEntries;
|
|
202
180
|
if (activeDocIds.length > 0) {
|
|
203
181
|
try {
|
|
204
182
|
const subscribeIds = this._filterSubscribeIds(activeDocIds);
|
|
@@ -234,7 +212,7 @@ class PatchesSync {
|
|
|
234
212
|
}
|
|
235
213
|
async syncDoc(docId) {
|
|
236
214
|
if (!this.state.connected) return;
|
|
237
|
-
this.
|
|
215
|
+
this._updateDocSyncState(docId, { syncStatus: "syncing" });
|
|
238
216
|
const doc = this.patches.getOpenDoc(docId);
|
|
239
217
|
const algorithm = this._getAlgorithm(docId);
|
|
240
218
|
const baseDoc = doc;
|
|
@@ -255,13 +233,13 @@ class PatchesSync {
|
|
|
255
233
|
} else {
|
|
256
234
|
const snapshot = await this.ws.getDoc(docId);
|
|
257
235
|
await algorithm.store.saveDoc(docId, snapshot);
|
|
258
|
-
this.
|
|
236
|
+
this._updateDocSyncState(docId, { committedRev: snapshot.rev });
|
|
259
237
|
if (baseDoc) {
|
|
260
238
|
baseDoc.import({ ...snapshot, changes: [] });
|
|
261
239
|
}
|
|
262
240
|
}
|
|
263
241
|
}
|
|
264
|
-
this.
|
|
242
|
+
this._updateDocSyncState(docId, { syncStatus: "synced" });
|
|
265
243
|
if (baseDoc) {
|
|
266
244
|
baseDoc.updateSyncStatus("synced");
|
|
267
245
|
}
|
|
@@ -271,7 +249,7 @@ class PatchesSync {
|
|
|
271
249
|
return;
|
|
272
250
|
}
|
|
273
251
|
const syncError = err instanceof Error ? err : new Error(String(err));
|
|
274
|
-
this.
|
|
252
|
+
this._updateDocSyncState(docId, { syncStatus: "error", syncError });
|
|
275
253
|
console.error(`Error syncing doc ${docId}:`, err);
|
|
276
254
|
this.onError.emit(syncError, { docId });
|
|
277
255
|
if (baseDoc) {
|
|
@@ -304,24 +282,24 @@ class PatchesSync {
|
|
|
304
282
|
maxStorageBytes: this.maxStorageBytes,
|
|
305
283
|
sizeCalculator: this.sizeCalculator
|
|
306
284
|
});
|
|
307
|
-
for (const
|
|
285
|
+
for (const changeBatch of batches) {
|
|
308
286
|
if (!this.state.connected) {
|
|
309
287
|
throw new Error("Disconnected during flush");
|
|
310
288
|
}
|
|
311
|
-
const committed = await this.ws.commitChanges(docId,
|
|
289
|
+
const committed = await this.ws.commitChanges(docId, changeBatch);
|
|
312
290
|
await this._applyServerChangesToDoc(docId, committed);
|
|
313
|
-
await algorithm.confirmSent(docId,
|
|
291
|
+
await algorithm.confirmSent(docId, changeBatch);
|
|
314
292
|
pending = await algorithm.getPendingToSend(docId) ?? [];
|
|
315
293
|
}
|
|
316
294
|
const stillHasPending = pending != null && pending.length > 0;
|
|
317
|
-
this.
|
|
295
|
+
this._updateDocSyncState(docId, { hasPending: stillHasPending, syncStatus: "synced" });
|
|
318
296
|
} catch (err) {
|
|
319
297
|
if (this._isDocDeletedError(err)) {
|
|
320
298
|
await this._handleRemoteDocDeleted(docId);
|
|
321
299
|
return;
|
|
322
300
|
}
|
|
323
301
|
const flushError = err instanceof Error ? err : new Error(String(err));
|
|
324
|
-
this.
|
|
302
|
+
this._updateDocSyncState(docId, { syncStatus: "error", syncError: flushError });
|
|
325
303
|
console.error(`Flush failed for doc ${docId}:`, err);
|
|
326
304
|
this.onError.emit(flushError, { docId });
|
|
327
305
|
throw err;
|
|
@@ -344,7 +322,7 @@ class PatchesSync {
|
|
|
344
322
|
await algorithm.applyServerChanges(docId, serverChanges, doc);
|
|
345
323
|
if (serverChanges.length > 0) {
|
|
346
324
|
const lastRev = serverChanges[serverChanges.length - 1].rev;
|
|
347
|
-
this.
|
|
325
|
+
this._updateDocSyncState(docId, { committedRev: lastRev });
|
|
348
326
|
}
|
|
349
327
|
}
|
|
350
328
|
/**
|
|
@@ -369,7 +347,7 @@ class PatchesSync {
|
|
|
369
347
|
_handleConnectionChange(connectionState) {
|
|
370
348
|
const isConnected = connectionState === "connected";
|
|
371
349
|
const isConnecting = connectionState === "connecting";
|
|
372
|
-
const newSyncStatus = isConnected ? this.
|
|
350
|
+
const newSyncStatus = isConnected ? this.state.syncStatus : isConnecting ? this.state.syncStatus : "unsynced";
|
|
373
351
|
this.updateState({ connected: isConnected, syncStatus: newSyncStatus });
|
|
374
352
|
if (isConnected) {
|
|
375
353
|
void this.syncAllKnownDocs();
|
|
@@ -377,37 +355,48 @@ class PatchesSync {
|
|
|
377
355
|
this._resetSyncingStatuses();
|
|
378
356
|
}
|
|
379
357
|
}
|
|
380
|
-
async _handleDocsTracked(docIds) {
|
|
358
|
+
async _handleDocsTracked(docIds, algorithmName) {
|
|
381
359
|
const newIds = docIds.filter((id) => !this.trackedDocs.has(id));
|
|
382
360
|
if (!newIds.length) return;
|
|
383
361
|
const alreadySubscribed = this._getActiveSubscriptions();
|
|
384
362
|
newIds.forEach((id) => this.trackedDocs.add(id));
|
|
385
|
-
|
|
386
|
-
for (const
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
363
|
+
if (algorithmName) {
|
|
364
|
+
for (const docId of newIds) {
|
|
365
|
+
this.docAlgorithms.set(docId, algorithmName);
|
|
366
|
+
}
|
|
367
|
+
} else {
|
|
368
|
+
for (const docId of newIds) {
|
|
369
|
+
for (const algorithm of Object.values(this.patches.algorithms)) {
|
|
370
|
+
if (!algorithm) continue;
|
|
371
|
+
const docs = await algorithm.listDocs(false);
|
|
372
|
+
const tracked = docs.find((d) => d.docId === docId);
|
|
373
|
+
if (tracked?.algorithm) {
|
|
374
|
+
this.docAlgorithms.set(docId, tracked.algorithm);
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
393
377
|
}
|
|
394
378
|
}
|
|
395
379
|
}
|
|
380
|
+
const docData = [];
|
|
396
381
|
for (const docId of newIds) {
|
|
397
382
|
const algorithm = this._getAlgorithm(docId);
|
|
398
383
|
const committedRev = await algorithm.getCommittedRev(docId);
|
|
399
384
|
const pending = await algorithm.getPendingToSend(docId);
|
|
400
|
-
|
|
385
|
+
docData.push({
|
|
401
386
|
docId,
|
|
402
|
-
|
|
387
|
+
committedRev,
|
|
388
|
+
hasPending: pending != null && pending.length > 0
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
batch(() => {
|
|
392
|
+
for (const { docId, committedRev, hasPending } of docData) {
|
|
393
|
+
this._updateDocSyncState(docId, {
|
|
403
394
|
committedRev,
|
|
404
|
-
hasPending
|
|
395
|
+
hasPending,
|
|
405
396
|
syncStatus: committedRev === 0 ? "unsynced" : "synced"
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
}
|
|
410
|
-
this._emitSyncedChange();
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
});
|
|
411
400
|
if (this.state.connected) {
|
|
412
401
|
try {
|
|
413
402
|
const subscribeIds = this._filterSubscribeIds(newIds).filter((id) => !alreadySubscribed.has(id));
|
|
@@ -426,8 +415,9 @@ class PatchesSync {
|
|
|
426
415
|
if (!existingIds.length) return;
|
|
427
416
|
const subscribedBefore = this._getActiveSubscriptions();
|
|
428
417
|
existingIds.forEach((id) => this.trackedDocs.delete(id));
|
|
429
|
-
|
|
430
|
-
|
|
418
|
+
batch(() => {
|
|
419
|
+
existingIds.forEach((id) => this._updateDocSyncState(id, void 0));
|
|
420
|
+
});
|
|
431
421
|
const subscribedAfter = this._getActiveSubscriptions();
|
|
432
422
|
const unsubscribeIds = [...subscribedBefore].filter((id) => !subscribedAfter.has(id));
|
|
433
423
|
if (this.state.connected && unsubscribeIds.length) {
|
|
@@ -440,10 +430,9 @@ class PatchesSync {
|
|
|
440
430
|
}
|
|
441
431
|
async _handleDocChange(docId) {
|
|
442
432
|
if (!this.trackedDocs.has(docId)) return;
|
|
443
|
-
this.
|
|
433
|
+
this._updateDocSyncState(docId, { hasPending: true });
|
|
444
434
|
if (!this.state.connected) return;
|
|
445
|
-
this.
|
|
446
|
-
await this.flushDoc(docId);
|
|
435
|
+
await this.syncDoc(docId);
|
|
447
436
|
}
|
|
448
437
|
/**
|
|
449
438
|
* Unified handler for remote document deletion (both real-time notifications and offline discovery).
|
|
@@ -457,37 +446,35 @@ class PatchesSync {
|
|
|
457
446
|
await this.patches.closeDoc(docId);
|
|
458
447
|
}
|
|
459
448
|
this.trackedDocs.delete(docId);
|
|
460
|
-
this.
|
|
449
|
+
this._updateDocSyncState(docId, void 0);
|
|
461
450
|
await algorithm.confirmDeleteDoc(docId);
|
|
462
451
|
await this.onRemoteDocDeleted.emit(docId, pendingChanges);
|
|
463
452
|
}
|
|
464
453
|
/**
|
|
465
|
-
* Adds, updates, or removes a
|
|
466
|
-
* - Pass a full
|
|
467
|
-
* - Pass a Partial<
|
|
454
|
+
* Adds, updates, or removes a doc state entry immutably and notifies via store.
|
|
455
|
+
* - Pass a full DocSyncState to add a new entry or overwrite an existing one.
|
|
456
|
+
* - Pass a Partial<DocSyncState> to merge into an existing entry (no-ops if doc not in map).
|
|
468
457
|
* - Pass undefined to remove the entry.
|
|
469
458
|
* No-ops if nothing actually changed.
|
|
470
459
|
*/
|
|
471
|
-
|
|
460
|
+
_updateDocSyncState(docId, updates) {
|
|
461
|
+
const currentDocs = this.docStates.state;
|
|
472
462
|
if (updates === void 0) {
|
|
473
|
-
if (!(docId in
|
|
474
|
-
|
|
475
|
-
delete
|
|
463
|
+
if (!(docId in currentDocs)) return;
|
|
464
|
+
const newDocs = { ...currentDocs };
|
|
465
|
+
delete newDocs[docId];
|
|
466
|
+
this.docStates.state = newDocs;
|
|
476
467
|
} else {
|
|
477
|
-
const updated = { ...
|
|
468
|
+
const updated = { ...EMPTY_DOC_STATE, ...currentDocs[docId], ...updates };
|
|
478
469
|
if (updated.syncStatus !== "error" && updated.syncError) {
|
|
479
470
|
updated.syncError = void 0;
|
|
480
471
|
}
|
|
481
472
|
if (!updated.isLoaded) {
|
|
482
|
-
updated.isLoaded = isDocLoaded(updated);
|
|
473
|
+
updated.isLoaded = isDocLoaded(updated.committedRev, updated.hasPending, updated.syncStatus);
|
|
483
474
|
}
|
|
484
|
-
if (isEqual(
|
|
485
|
-
this.
|
|
475
|
+
if (isEqual(currentDocs[docId], updated)) return;
|
|
476
|
+
this.docStates.state = { ...currentDocs, [docId]: updated };
|
|
486
477
|
}
|
|
487
|
-
if (emit) this._emitSyncedChange();
|
|
488
|
-
}
|
|
489
|
-
_emitSyncedChange() {
|
|
490
|
-
this.onSyncedDocsChange.emit(this._syncedDocs);
|
|
491
478
|
}
|
|
492
479
|
/**
|
|
493
480
|
* Resets any docs with status 'syncing' back to a stable state on disconnect.
|
|
@@ -495,15 +482,14 @@ class PatchesSync {
|
|
|
495
482
|
* docs with no pending and no committed rev become 'unsynced'.
|
|
496
483
|
*/
|
|
497
484
|
_resetSyncingStatuses() {
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
485
|
+
batch(() => {
|
|
486
|
+
for (const [docId, doc] of Object.entries(this.docStates.state)) {
|
|
487
|
+
if (doc.syncStatus === "syncing") {
|
|
488
|
+
const newStatus = doc.committedRev === 0 && !doc.hasPending ? "unsynced" : "synced";
|
|
489
|
+
this._updateDocSyncState(docId, { syncStatus: newStatus });
|
|
490
|
+
}
|
|
504
491
|
}
|
|
505
|
-
}
|
|
506
|
-
if (changed) this._emitSyncedChange();
|
|
492
|
+
});
|
|
507
493
|
}
|
|
508
494
|
/**
|
|
509
495
|
* Applies the subscribeFilter option to a list of doc IDs, returning the subset
|
|
@@ -526,7 +512,7 @@ class PatchesSync {
|
|
|
526
512
|
return typeof err === "object" && err !== null && "code" in err && err.code === 410;
|
|
527
513
|
}
|
|
528
514
|
}
|
|
529
|
-
_init = __decoratorStart(
|
|
515
|
+
_init = __decoratorStart(_a);
|
|
530
516
|
__decorateElement(_init, 1, "syncDoc", _syncDoc_dec, PatchesSync);
|
|
531
517
|
__decorateElement(_init, 1, "_receiveCommittedChanges", __receiveCommittedChanges_dec, PatchesSync);
|
|
532
518
|
__decoratorMetadata(_init, PatchesSync);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as easy_signal from 'easy-signal';
|
|
2
2
|
import { ClientTransport } from '../protocol/types.js';
|
|
3
3
|
import '../../types.js';
|
|
4
4
|
import '../../json-patch/JSONPatch.js';
|
|
@@ -11,7 +11,7 @@ import '../../json-patch/types.js';
|
|
|
11
11
|
declare class FetchTransport implements ClientTransport {
|
|
12
12
|
private url;
|
|
13
13
|
private authHeader;
|
|
14
|
-
readonly onMessage: Signal<(raw: string) => void>;
|
|
14
|
+
readonly onMessage: easy_signal.Signal<(raw: string) => void>;
|
|
15
15
|
private headers;
|
|
16
16
|
constructor(url: string, authHeader: string);
|
|
17
17
|
addHeadersToNextCall(headers: Record<string, string>): void;
|
package/dist/net/index.d.ts
CHANGED
|
@@ -13,11 +13,11 @@ export { JsonRpcMessage, SignalingService } from './websocket/SignalingService.j
|
|
|
13
13
|
export { WebSocketServer, WebSocketServerOptions } from './websocket/WebSocketServer.js';
|
|
14
14
|
export { WebSocketOptions, WebSocketTransport } from './websocket/WebSocketTransport.js';
|
|
15
15
|
export { CommitChangesOptions } from '../types.js';
|
|
16
|
-
import '
|
|
16
|
+
import 'easy-signal';
|
|
17
17
|
import '../algorithms/ot/shared/changeBatching.js';
|
|
18
18
|
import '../client/ClientAlgorithm.js';
|
|
19
19
|
import '../json-patch/types.js';
|
|
20
|
-
import '../BaseDoc-
|
|
20
|
+
import '../BaseDoc-BRIP2YZp.js';
|
|
21
21
|
import '../client/PatchesStore.js';
|
|
22
22
|
import '../client/Patches.js';
|
|
23
23
|
import '../server/types.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Signal, Unsubscriber } from '
|
|
1
|
+
import { Signal, Unsubscriber } from 'easy-signal';
|
|
2
2
|
import { AuthorizationProvider, AuthContext } from '../websocket/AuthorizationProvider.js';
|
|
3
3
|
import { JsonRpcNotification, Message, JsonRpcResponse } from './types.js';
|
|
4
4
|
import '../../server/types.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "../../chunk-IZ2YBCUP.js";
|
|
2
|
-
import { signal } from "
|
|
2
|
+
import { signal } from "easy-signal";
|
|
3
3
|
import { StatusError } from "../error.js";
|
|
4
4
|
import { clearAuthContext, getAuthContext, setAuthContext } from "../serverContext.js";
|
|
5
5
|
import { rpcError, rpcNotification, rpcResponse } from "./utils.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Unsubscriber } from '
|
|
1
|
+
import { Unsubscriber } from 'easy-signal';
|
|
2
2
|
import { PatchesState, Change, ChangeInput, CommitChangesOptions, EditableVersionMetadata, ListVersionsOptions, VersionMetadata } from '../../types.js';
|
|
3
3
|
import '../../json-patch/JSONPatch.js';
|
|
4
4
|
import '@dabble/delta';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as easy_signal from 'easy-signal';
|
|
2
2
|
import { WebRTCTransport } from './WebRTCTransport.js';
|
|
3
3
|
import '../protocol/types.js';
|
|
4
4
|
import '../../types.js';
|
|
@@ -29,7 +29,7 @@ declare class WebRTCAwareness<T extends AwarenessState = AwarenessState> {
|
|
|
29
29
|
* Signal that emits when the awareness state is updated.
|
|
30
30
|
* Subscribers receive the complete new awareness state array.
|
|
31
31
|
*/
|
|
32
|
-
readonly onUpdate: Signal<(states: T[]) => void>;
|
|
32
|
+
readonly onUpdate: easy_signal.Signal<(states: T[]) => void>;
|
|
33
33
|
/**
|
|
34
34
|
* The peer ID of this client, obtained from the WebRTC transport.
|
|
35
35
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ClientTransport, ConnectionState } from '../protocol/types.js';
|
|
2
|
-
import
|
|
2
|
+
import * as easy_signal from 'easy-signal';
|
|
3
3
|
import Peer from 'simple-peer';
|
|
4
4
|
import { WebSocketTransport } from '../websocket/WebSocketTransport.js';
|
|
5
5
|
import '../../types.js';
|
|
@@ -23,22 +23,22 @@ declare class WebRTCTransport implements ClientTransport {
|
|
|
23
23
|
* Signal that emits when a message is received from a peer.
|
|
24
24
|
* Provides the message data, peer ID, and peer instance.
|
|
25
25
|
*/
|
|
26
|
-
readonly onMessage: Signal<(data: string, peerId: string, peer: Peer.Instance) => void>;
|
|
26
|
+
readonly onMessage: easy_signal.Signal<(data: string, peerId: string, peer: Peer.Instance) => void>;
|
|
27
27
|
/**
|
|
28
28
|
* Signal that emits when a new peer connection is established.
|
|
29
29
|
* Provides the peer ID and peer instance.
|
|
30
30
|
*/
|
|
31
|
-
readonly onPeerConnect: Signal<(peerId: string, peer: Peer.Instance) => void>;
|
|
31
|
+
readonly onPeerConnect: easy_signal.Signal<(peerId: string, peer: Peer.Instance) => void>;
|
|
32
32
|
/**
|
|
33
33
|
* Signal that emits when a peer disconnects.
|
|
34
34
|
* Provides the peer ID and peer instance.
|
|
35
35
|
*/
|
|
36
|
-
readonly onPeerDisconnect: Signal<(peerId: string, peer: Peer.Instance) => void>;
|
|
36
|
+
readonly onPeerDisconnect: easy_signal.Signal<(peerId: string, peer: Peer.Instance) => void>;
|
|
37
37
|
/**
|
|
38
38
|
* Signal that emits when the underlying signaling transport's state changes.
|
|
39
39
|
* This is delegated directly from the WebSocketTransport.
|
|
40
40
|
*/
|
|
41
|
-
get onStateChange(): Signal<(state: ConnectionState) => void>;
|
|
41
|
+
get onStateChange(): easy_signal.Signal<(state: ConnectionState) => void>;
|
|
42
42
|
/**
|
|
43
43
|
* Creates a new WebRTC transport instance.
|
|
44
44
|
* @param transport - The WebSocket transport to use for signaling
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "../../chunk-IZ2YBCUP.js";
|
|
2
2
|
import Peer from "simple-peer";
|
|
3
|
-
import { signal } from "
|
|
3
|
+
import { signal } from "easy-signal";
|
|
4
4
|
import { JSONRPCClient } from "../../net/protocol/JSONRPCClient.js";
|
|
5
5
|
import { rpcError } from "../protocol/utils.js";
|
|
6
6
|
class WebRTCTransport {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { WebRTCAwareness } from './WebRTCAwareness.js';
|
|
2
2
|
export { WebRTCTransport } from './WebRTCTransport.js';
|
|
3
|
-
import '
|
|
3
|
+
import 'easy-signal';
|
|
4
4
|
import '../protocol/types.js';
|
|
5
5
|
import '../../types.js';
|
|
6
6
|
import '../../json-patch/JSONPatch.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Signal } from '
|
|
1
|
+
import { Signal } from 'easy-signal';
|
|
2
2
|
import { PatchesClient } from '../PatchesClient.js';
|
|
3
3
|
import { ConnectionState } from '../protocol/types.js';
|
|
4
4
|
import { WebSocketTransport, WebSocketOptions } from './WebSocketTransport.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "../../chunk-IZ2YBCUP.js";
|
|
2
|
-
import {} from "
|
|
2
|
+
import {} from "easy-signal";
|
|
3
3
|
import { PatchesClient } from "../PatchesClient.js";
|
|
4
4
|
import { WebSocketTransport } from "./WebSocketTransport.js";
|
|
5
5
|
class PatchesWebSocket extends PatchesClient {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { JSONRPCServer } from '../protocol/JSONRPCServer.js';
|
|
2
2
|
import { ServerTransport } from '../protocol/types.js';
|
|
3
3
|
import { AuthorizationProvider, AuthContext } from './AuthorizationProvider.js';
|
|
4
|
-
import '
|
|
4
|
+
import 'easy-signal';
|
|
5
5
|
import '../../server/types.js';
|
|
6
6
|
import '../../json-patch/types.js';
|
|
7
7
|
import '../../types.js';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as easy_signal from 'easy-signal';
|
|
2
|
+
import { Unsubscriber } from 'easy-signal';
|
|
2
3
|
import { Deferred } from '../../utils/deferred.js';
|
|
3
4
|
import { ClientTransport, ConnectionState } from '../protocol/types.js';
|
|
4
5
|
import '../../types.js';
|
|
@@ -30,12 +31,12 @@ declare class WebSocketTransport implements ClientTransport {
|
|
|
30
31
|
* Signal that emits when the connection state changes.
|
|
31
32
|
* Subscribers will receive the new connection state as an argument.
|
|
32
33
|
*/
|
|
33
|
-
readonly onStateChange: Signal<(state: ConnectionState) => void>;
|
|
34
|
+
readonly onStateChange: easy_signal.Signal<(state: ConnectionState) => void>;
|
|
34
35
|
/**
|
|
35
36
|
* Signal that emits when a message is received from the transport.
|
|
36
37
|
* Subscribers will receive the message data as a string.
|
|
37
38
|
*/
|
|
38
|
-
readonly onMessage: Signal<(data: string) => void>;
|
|
39
|
+
readonly onMessage: easy_signal.Signal<(data: string) => void>;
|
|
39
40
|
/**
|
|
40
41
|
* Creates a new WebSocket transport instance.
|
|
41
42
|
* @param url - The WebSocket server URL to connect to
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as easy_signal from 'easy-signal';
|
|
2
2
|
|
|
3
3
|
declare class OnlineState {
|
|
4
|
-
onOnlineChange: Signal<(isOnline: boolean) => void>;
|
|
4
|
+
onOnlineChange: easy_signal.Signal<(isOnline: boolean) => void>;
|
|
5
5
|
protected _isOnline: boolean;
|
|
6
6
|
constructor();
|
|
7
7
|
get isOnline(): boolean;
|
|
@@ -3,7 +3,7 @@ import { Branch, EditableBranchMetadata, BranchStatus, Change } from '../types.j
|
|
|
3
3
|
import { BranchManager } from './BranchManager.js';
|
|
4
4
|
import { LWWServer } from './LWWServer.js';
|
|
5
5
|
import { LWWStoreBackend, BranchingStoreBackend } from './types.js';
|
|
6
|
-
import '
|
|
6
|
+
import 'easy-signal';
|
|
7
7
|
import '../net/websocket/AuthorizationProvider.js';
|
|
8
8
|
import '../json-patch/types.js';
|
|
9
9
|
import '../json-patch/JSONPatch.js';
|