@dabble/patches 0.7.23 → 0.8.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.
- package/dist/{BaseDoc-CD5wZQMm.d.ts → BaseDoc-BT18xPxU.d.ts} +1 -1
- package/dist/algorithms/ot/server/createVersion.d.ts +1 -1
- package/dist/algorithms/ot/shared/changeBatching.js +3 -3
- package/dist/client/BaseDoc.d.ts +1 -1
- package/dist/client/ClientAlgorithm.d.ts +1 -1
- package/dist/client/LWWAlgorithm.d.ts +1 -1
- package/dist/client/LWWDoc.d.ts +1 -1
- package/dist/client/OTAlgorithm.d.ts +1 -1
- package/dist/client/OTDoc.d.ts +1 -1
- package/dist/client/Patches.d.ts +1 -1
- package/dist/client/Patches.js +1 -0
- package/dist/client/PatchesDoc.d.ts +1 -1
- package/dist/client/factories.d.ts +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/compression/lz.js +3 -4
- package/dist/index.d.ts +1 -1
- package/dist/json-patch/invertPatch.js +2 -1
- package/dist/json-patch/utils/getType.d.ts +1 -1
- package/dist/net/PatchesConnection.d.ts +27 -0
- package/dist/net/PatchesConnection.js +0 -0
- package/dist/net/PatchesSync.d.ts +23 -18
- package/dist/net/PatchesSync.js +38 -29
- package/dist/net/index.d.ts +5 -1
- package/dist/net/index.js +2 -0
- package/dist/net/rest/PatchesREST.d.ts +75 -0
- package/dist/net/rest/PatchesREST.js +234 -0
- package/dist/net/rest/SSEServer.d.ts +151 -0
- package/dist/net/rest/SSEServer.js +248 -0
- package/dist/net/rest/index.d.ts +12 -0
- package/dist/net/rest/index.js +8 -0
- package/dist/net/rest/utils.d.ts +14 -0
- package/dist/net/rest/utils.js +11 -0
- package/dist/net/websocket/PatchesWebSocket.d.ts +5 -1
- package/dist/net/websocket/PatchesWebSocket.js +8 -0
- package/dist/server/PatchesHistoryManager.js +2 -2
- package/dist/server/branchUtils.js +1 -1
- package/dist/shared/doc-manager.d.ts +1 -1
- package/dist/solid/context.d.ts +3 -4
- package/dist/solid/doc-manager.d.ts +1 -1
- package/dist/solid/index.d.ts +3 -4
- package/dist/solid/primitives.d.ts +1 -1
- package/dist/vue/composables.d.ts +1 -1
- package/dist/vue/doc-manager.d.ts +1 -1
- package/dist/vue/index.d.ts +3 -4
- package/dist/vue/managed-docs.d.ts +2 -2
- package/dist/vue/provider.d.ts +3 -4
- package/package.json +13 -12
|
@@ -237,4 +237,4 @@ declare abstract class BaseDoc<T extends object = object> extends ReadonlyStoreC
|
|
|
237
237
|
abstract import(snapshot: PatchesSnapshot<T>): void;
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
-
export { BaseDoc as B, OTDoc as O, type
|
|
240
|
+
export { BaseDoc as B, OTDoc as O, type PatchesDoc as P, type PatchesDocOptions as a };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { OTStoreBackend } from '../../../server/types.js';
|
|
2
|
-
import { EditableVersionMetadata,
|
|
2
|
+
import { EditableVersionMetadata, Change, VersionMetadata } from '../../../types.js';
|
|
3
3
|
import '../../../json-patch/types.js';
|
|
4
4
|
import '../../../json-patch/JSONPatch.js';
|
|
5
5
|
import '@dabble/delta';
|
|
@@ -7,7 +7,7 @@ function getJSONByteSize(data) {
|
|
|
7
7
|
return stringified ? new TextEncoder().encode(stringified).length : 0;
|
|
8
8
|
} catch (e) {
|
|
9
9
|
console.error("Error calculating JSON size:", e);
|
|
10
|
-
throw new Error("Error calculating JSON size
|
|
10
|
+
throw new Error("Error calculating JSON size", { cause: e });
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
function breakChanges(changes, maxBytes, sizeCalculator) {
|
|
@@ -262,14 +262,14 @@ function breakLargeValueOp(origChange, op, maxBytes, startRev, sizeCalculator) {
|
|
|
262
262
|
chunkOp.path = op.path;
|
|
263
263
|
chunkOp.appendArray = currentChunk;
|
|
264
264
|
}
|
|
265
|
-
results.push(deriveNewChange(origChange, rev
|
|
265
|
+
results.push(deriveNewChange(origChange, rev, [chunkOp]));
|
|
266
266
|
}
|
|
267
267
|
return results;
|
|
268
268
|
}
|
|
269
269
|
console.warn(
|
|
270
270
|
`Warning: Single operation of type ${op.op} (path: ${op.path}) could not be split further by breakLargeValueOp despite exceeding maxBytes. Including as is.`
|
|
271
271
|
);
|
|
272
|
-
return [deriveNewChange(origChange, rev
|
|
272
|
+
return [deriveNewChange(origChange, rev, [op])];
|
|
273
273
|
}
|
|
274
274
|
function deriveNewChange(origChange, rev, ops) {
|
|
275
275
|
const { id: _id, ops: _o, rev: _r, baseRev: _br, created: _c, batchId: _bi, ...metadata } = origChange;
|
package/dist/client/BaseDoc.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { JSONPatchOp } from '../json-patch/types.js';
|
|
2
2
|
import { PatchesSnapshot, Change } from '../types.js';
|
|
3
|
-
import {
|
|
3
|
+
import { P as PatchesDoc } from '../BaseDoc-BT18xPxU.js';
|
|
4
4
|
import { PatchesStore, TrackedDoc } from './PatchesStore.js';
|
|
5
5
|
import '../json-patch/JSONPatch.js';
|
|
6
6
|
import '@dabble/delta';
|
|
@@ -2,7 +2,7 @@ import { JSONPatchOp } from '../json-patch/types.js';
|
|
|
2
2
|
import { PatchesSnapshot, Change } from '../types.js';
|
|
3
3
|
import { ClientAlgorithm } from './ClientAlgorithm.js';
|
|
4
4
|
import { LWWClientStore } from './LWWClientStore.js';
|
|
5
|
-
import {
|
|
5
|
+
import { P as PatchesDoc } from '../BaseDoc-BT18xPxU.js';
|
|
6
6
|
import { TrackedDoc } from './PatchesStore.js';
|
|
7
7
|
import '../json-patch/JSONPatch.js';
|
|
8
8
|
import '@dabble/delta';
|
package/dist/client/LWWDoc.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { JSONPatchOp } from '../json-patch/types.js';
|
|
|
2
2
|
import { PatchesSnapshot, Change } from '../types.js';
|
|
3
3
|
import { ClientAlgorithm } from './ClientAlgorithm.js';
|
|
4
4
|
import { OTClientStore } from './OTClientStore.js';
|
|
5
|
-
import {
|
|
5
|
+
import { a as PatchesDocOptions, P as PatchesDoc } from '../BaseDoc-BT18xPxU.js';
|
|
6
6
|
import { TrackedDoc } from './PatchesStore.js';
|
|
7
7
|
import '../json-patch/JSONPatch.js';
|
|
8
8
|
import '@dabble/delta';
|
package/dist/client/OTDoc.d.ts
CHANGED
package/dist/client/Patches.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { Unsubscriber } from 'easy-signal';
|
|
|
3
3
|
import { JSONPatchOp } from '../json-patch/types.js';
|
|
4
4
|
import { Change } from '../types.js';
|
|
5
5
|
import { ClientAlgorithm } from './ClientAlgorithm.js';
|
|
6
|
-
import {
|
|
6
|
+
import { a as PatchesDocOptions, P as PatchesDoc } from '../BaseDoc-BT18xPxU.js';
|
|
7
7
|
import { AlgorithmName } from './PatchesStore.js';
|
|
8
8
|
import '../json-patch/JSONPatch.js';
|
|
9
9
|
import '@dabble/delta';
|
package/dist/client/Patches.js
CHANGED
|
@@ -208,6 +208,7 @@ class Patches {
|
|
|
208
208
|
const current = prev.then(() => this._processDocChange(docId, ops, doc, algorithm, metadata));
|
|
209
209
|
this._changeQueues.set(
|
|
210
210
|
docId,
|
|
211
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
211
212
|
current.catch(() => {
|
|
212
213
|
})
|
|
213
214
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import 'easy-signal';
|
|
2
2
|
import '../json-patch/types.js';
|
|
3
3
|
import '../types.js';
|
|
4
|
-
export { O as OTDoc,
|
|
4
|
+
export { O as OTDoc, P as PatchesDoc, O as PatchesDocClass, a as PatchesDocOptions } from '../BaseDoc-BT18xPxU.js';
|
|
5
5
|
import '../json-patch/JSONPatch.js';
|
|
6
6
|
import '@dabble/delta';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AlgorithmName } from './PatchesStore.js';
|
|
2
2
|
import { Patches } from './Patches.js';
|
|
3
|
-
import {
|
|
3
|
+
import { a as PatchesDocOptions } from '../BaseDoc-BT18xPxU.js';
|
|
4
4
|
import '../types.js';
|
|
5
5
|
import '../json-patch/JSONPatch.js';
|
|
6
6
|
import '@dabble/delta';
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { B as BaseDoc, O as OTDoc,
|
|
1
|
+
export { B as BaseDoc, O as OTDoc, P as PatchesDoc, O as PatchesDocClass, a as PatchesDocOptions } from '../BaseDoc-BT18xPxU.js';
|
|
2
2
|
export { IndexedDBFactoryOptions, MultiAlgorithmFactoryOptions, MultiAlgorithmIndexedDBFactoryOptions, PatchesFactoryOptions, createLWWIndexedDBPatches, createLWWPatches, createMultiAlgorithmIndexedDBPatches, createMultiAlgorithmPatches, createOTIndexedDBPatches, createOTPatches } from './factories.js';
|
|
3
3
|
export { IDBStoreWrapper, IDBTransactionWrapper, IndexedDBStore } from './IndexedDBStore.js';
|
|
4
4
|
export { OTIndexedDBStore } from './OTIndexedDBStore.js';
|
package/dist/compression/lz.js
CHANGED
|
@@ -93,8 +93,8 @@ function _compress(uncompressed, bitsPerChar, getCharFromInt) {
|
|
|
93
93
|
let value;
|
|
94
94
|
const context_dictionary = {};
|
|
95
95
|
const context_dictionaryToCreate = {};
|
|
96
|
-
let context_c
|
|
97
|
-
let context_wc
|
|
96
|
+
let context_c;
|
|
97
|
+
let context_wc;
|
|
98
98
|
let context_w = "";
|
|
99
99
|
let context_enlargeIn = 2;
|
|
100
100
|
let context_dictSize = 3;
|
|
@@ -264,7 +264,6 @@ function _compress(uncompressed, bitsPerChar, getCharFromInt) {
|
|
|
264
264
|
}
|
|
265
265
|
context_enlargeIn--;
|
|
266
266
|
if (context_enlargeIn === 0) {
|
|
267
|
-
context_enlargeIn = Math.pow(2, context_numBits);
|
|
268
267
|
context_numBits++;
|
|
269
268
|
}
|
|
270
269
|
}
|
|
@@ -294,7 +293,7 @@ function _decompress(length, resetValue, getNextValue) {
|
|
|
294
293
|
let enlargeIn = 4;
|
|
295
294
|
let dictSize = 4;
|
|
296
295
|
let numBits = 3;
|
|
297
|
-
let entry
|
|
296
|
+
let entry;
|
|
298
297
|
const result = [];
|
|
299
298
|
let w;
|
|
300
299
|
let bits;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { Delta } from '@dabble/delta';
|
|
2
|
-
export { B as BaseDoc, O as OTDoc,
|
|
2
|
+
export { B as BaseDoc, O as OTDoc, P as PatchesDoc, O as PatchesDocClass, a as PatchesDocOptions } from './BaseDoc-BT18xPxU.js';
|
|
3
3
|
export { IndexedDBFactoryOptions, MultiAlgorithmFactoryOptions, MultiAlgorithmIndexedDBFactoryOptions, PatchesFactoryOptions, createLWWIndexedDBPatches, createLWWPatches, createMultiAlgorithmIndexedDBPatches, createMultiAlgorithmPatches, createOTIndexedDBPatches, createOTPatches } from './client/factories.js';
|
|
4
4
|
export { IDBStoreWrapper, IDBTransactionWrapper, IndexedDBStore } from './client/IndexedDBStore.js';
|
|
5
5
|
export { OTIndexedDBStore } from './client/OTIndexedDBStore.js';
|
|
@@ -18,7 +18,8 @@ function invertPatch(object, ops, custom = {}) {
|
|
|
18
18
|
isIndex = prop >= 0;
|
|
19
19
|
} catch (err) {
|
|
20
20
|
throw new Error(
|
|
21
|
-
`Patch mismatch. This patch was not applied to the provided object and cannot be inverted. ${err.message || err}
|
|
21
|
+
`Patch mismatch. This patch was not applied to the provided object and cannot be inverted. ${err.message || err}`,
|
|
22
|
+
{ cause: err }
|
|
22
23
|
);
|
|
23
24
|
}
|
|
24
25
|
const handler = getType(state, op)?.invert;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { State, JSONPatchOp, JSONPatchOpHandler } from '../types.js';
|
|
2
2
|
|
|
3
3
|
declare function getType(state: State, patch: JSONPatchOp): JSONPatchOpHandler;
|
|
4
|
-
declare function getTypeLike(state: State, patch: JSONPatchOp): "
|
|
4
|
+
declare function getTypeLike(state: State, patch: JSONPatchOp): "test" | "add" | "remove" | "replace" | "copy" | "move";
|
|
5
5
|
|
|
6
6
|
export { getType, getTypeLike };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Signal } from 'easy-signal';
|
|
2
|
+
import { Change, CommitChangesOptions } from '../types.js';
|
|
3
|
+
import { PatchesAPI, ConnectionState } from './protocol/types.js';
|
|
4
|
+
import '../json-patch/JSONPatch.js';
|
|
5
|
+
import '@dabble/delta';
|
|
6
|
+
import '../json-patch/types.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Common interface for transport connections that PatchesSync can use.
|
|
10
|
+
* Implemented by PatchesWebSocket (WebSocket transport) and PatchesREST (SSE + fetch transport).
|
|
11
|
+
*/
|
|
12
|
+
interface PatchesConnection extends PatchesAPI {
|
|
13
|
+
/** The server URL. Readable and writable — setting while connected triggers reconnection. */
|
|
14
|
+
url: string;
|
|
15
|
+
/** Establish the connection to the server. */
|
|
16
|
+
connect(): Promise<void>;
|
|
17
|
+
/** Tear down the connection. */
|
|
18
|
+
disconnect(): void;
|
|
19
|
+
/** Signal emitted when the connection state changes. */
|
|
20
|
+
readonly onStateChange: Signal<(state: ConnectionState) => void>;
|
|
21
|
+
/** Signal emitted when the server pushes committed changes for a subscribed document. */
|
|
22
|
+
readonly onChangesCommitted: Signal<(docId: string, changes: Change[], options?: CommitChangesOptions) => void>;
|
|
23
|
+
/** Signal emitted when a subscribed document is deleted remotely. */
|
|
24
|
+
readonly onDocDeleted: Signal<(docId: string) => void>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type { PatchesConnection };
|
|
File without changes
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import * as easy_signal from 'easy-signal';
|
|
2
2
|
import { ReadonlyStoreClass, Store } from 'easy-signal';
|
|
3
|
-
import { ConnectionState } from './protocol/types.js';
|
|
4
|
-
import { DocSyncStatus, DocSyncState, Change } from '../types.js';
|
|
5
|
-
import { JSONRPCClient } from './protocol/JSONRPCClient.js';
|
|
6
|
-
import { PatchesWebSocket } from './websocket/PatchesWebSocket.js';
|
|
7
|
-
import { WebSocketOptions } from './websocket/WebSocketTransport.js';
|
|
8
3
|
import { SizeCalculator } from '../algorithms/ot/shared/changeBatching.js';
|
|
9
4
|
import { ClientAlgorithm } from '../client/ClientAlgorithm.js';
|
|
10
5
|
import { Patches } from '../client/Patches.js';
|
|
11
6
|
import { AlgorithmName } from '../client/PatchesStore.js';
|
|
7
|
+
import { DocSyncStatus, DocSyncState, Change } from '../types.js';
|
|
8
|
+
import { PatchesConnection } from './PatchesConnection.js';
|
|
9
|
+
import { JSONRPCClient } from './protocol/JSONRPCClient.js';
|
|
10
|
+
import { ConnectionState } from './protocol/types.js';
|
|
11
|
+
import { WebSocketOptions } from './websocket/WebSocketTransport.js';
|
|
12
|
+
import '../json-patch/types.js';
|
|
13
|
+
import '../BaseDoc-BT18xPxU.js';
|
|
12
14
|
import '../json-patch/JSONPatch.js';
|
|
13
15
|
import '@dabble/delta';
|
|
14
|
-
import '../json-patch/types.js';
|
|
15
|
-
import './PatchesClient.js';
|
|
16
16
|
import '../utils/deferred.js';
|
|
17
|
-
import '../BaseDoc-CD5wZQMm.js';
|
|
18
17
|
|
|
19
18
|
interface PatchesSyncState {
|
|
20
19
|
online: boolean;
|
|
@@ -24,6 +23,7 @@ interface PatchesSyncState {
|
|
|
24
23
|
}
|
|
25
24
|
interface PatchesSyncOptions {
|
|
26
25
|
subscribeFilter?: (docIds: string[]) => string[];
|
|
26
|
+
/** WebSocket options. Only used when a URL string is passed to the constructor. */
|
|
27
27
|
websocket?: WebSocketOptions;
|
|
28
28
|
/** Wire batch limit for network transmission. Defaults to 1MB. */
|
|
29
29
|
maxPayloadBytes?: number;
|
|
@@ -33,9 +33,12 @@ interface PatchesSyncOptions {
|
|
|
33
33
|
sizeCalculator?: SizeCalculator;
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
|
-
* Handles
|
|
36
|
+
* Handles server connection, document subscriptions, and syncing logic between
|
|
37
37
|
* the Patches instance and the server.
|
|
38
38
|
*
|
|
39
|
+
* Accepts either a URL string (creates a WebSocket connection) or a PatchesConnection
|
|
40
|
+
* instance (e.g. PatchesREST for SSE + fetch).
|
|
41
|
+
*
|
|
39
42
|
* PatchesSync is algorithm-agnostic. It delegates to algorithm methods for:
|
|
40
43
|
* - Getting pending changes to send
|
|
41
44
|
* - Applying server changes
|
|
@@ -43,7 +46,7 @@ interface PatchesSyncOptions {
|
|
|
43
46
|
*/
|
|
44
47
|
declare class PatchesSync extends ReadonlyStoreClass<PatchesSyncState> {
|
|
45
48
|
protected options?: PatchesSyncOptions | undefined;
|
|
46
|
-
protected
|
|
49
|
+
protected connection: PatchesConnection;
|
|
47
50
|
protected patches: Patches;
|
|
48
51
|
protected maxPayloadBytes?: number;
|
|
49
52
|
protected maxStorageBytes?: number;
|
|
@@ -66,36 +69,38 @@ declare class PatchesSync extends ReadonlyStoreClass<PatchesSyncState> {
|
|
|
66
69
|
* Provides the pending changes that were discarded so the application can handle them.
|
|
67
70
|
*/
|
|
68
71
|
readonly onRemoteDocDeleted: easy_signal.Signal<(docId: string, pendingChanges: Change[]) => void>;
|
|
69
|
-
constructor(patches: Patches, url: string, options?: PatchesSyncOptions
|
|
72
|
+
constructor(patches: Patches, url: string, options?: PatchesSyncOptions);
|
|
73
|
+
constructor(patches: Patches, connection: PatchesConnection, options?: PatchesSyncOptions);
|
|
70
74
|
/**
|
|
71
75
|
* Gets the algorithm for a document. Uses the open doc's algorithm if available,
|
|
72
76
|
* otherwise falls back to the default algorithm.
|
|
73
77
|
*/
|
|
74
78
|
protected _getAlgorithm(docId: string): ClientAlgorithm;
|
|
75
79
|
/**
|
|
76
|
-
* Gets the URL
|
|
80
|
+
* Gets the server URL.
|
|
77
81
|
*/
|
|
78
82
|
get url(): string;
|
|
79
83
|
/**
|
|
80
|
-
* Sets the URL
|
|
84
|
+
* Sets the server URL. Reconnects if currently connected.
|
|
81
85
|
*/
|
|
82
86
|
set url(url: string);
|
|
83
87
|
/**
|
|
84
88
|
* Gets the JSON-RPC client for making custom RPC calls.
|
|
85
|
-
*
|
|
89
|
+
* Only available when using a WebSocket connection (PatchesWebSocket or PatchesClient).
|
|
90
|
+
* Returns undefined when using REST transport.
|
|
86
91
|
*/
|
|
87
|
-
get rpc(): JSONRPCClient;
|
|
92
|
+
get rpc(): JSONRPCClient | undefined;
|
|
88
93
|
/**
|
|
89
94
|
* Updates the sync state.
|
|
90
95
|
* @param update - The partial state to update.
|
|
91
96
|
*/
|
|
92
97
|
protected updateState(update: Partial<PatchesSyncState>): void;
|
|
93
98
|
/**
|
|
94
|
-
* Connects to the
|
|
99
|
+
* Connects to the server and starts syncing if online. If not online, it will wait for online state.
|
|
95
100
|
*/
|
|
96
101
|
connect(): Promise<void>;
|
|
97
102
|
/**
|
|
98
|
-
* Disconnects from the
|
|
103
|
+
* Disconnects from the server and stops syncing.
|
|
99
104
|
*/
|
|
100
105
|
disconnect(): void;
|
|
101
106
|
/**
|
|
@@ -155,7 +160,7 @@ declare class PatchesSync extends ReadonlyStoreClass<PatchesSyncState> {
|
|
|
155
160
|
protected _resetSyncingStatuses(): void;
|
|
156
161
|
/**
|
|
157
162
|
* Applies the subscribeFilter option to a list of doc IDs, returning the subset
|
|
158
|
-
* that should be sent to
|
|
163
|
+
* that should be sent to subscribe/unsubscribe. Returns the full list if no filter is set.
|
|
159
164
|
*/
|
|
160
165
|
protected _filterSubscribeIds(docIds: string[]): string[];
|
|
161
166
|
/**
|
package/dist/net/PatchesSync.js
CHANGED
|
@@ -13,6 +13,7 @@ import { BaseDoc } from "../client/BaseDoc.js";
|
|
|
13
13
|
import { Patches } from "../client/Patches.js";
|
|
14
14
|
import { isDocLoaded } from "../shared/utils.js";
|
|
15
15
|
import { blockable } from "../utils/concurrency.js";
|
|
16
|
+
import { ErrorCodes, StatusError } from "./error.js";
|
|
16
17
|
import { PatchesWebSocket } from "./websocket/PatchesWebSocket.js";
|
|
17
18
|
import { onlineState } from "./websocket/onlineState.js";
|
|
18
19
|
const EMPTY_DOC_STATE = {
|
|
@@ -22,7 +23,7 @@ const EMPTY_DOC_STATE = {
|
|
|
22
23
|
isLoaded: false
|
|
23
24
|
};
|
|
24
25
|
class PatchesSync extends (_a = ReadonlyStoreClass, _syncDoc_dec = [blockable], __receiveCommittedChanges_dec = [blockable], _a) {
|
|
25
|
-
constructor(patches,
|
|
26
|
+
constructor(patches, urlOrConnection, options) {
|
|
26
27
|
super({
|
|
27
28
|
online: onlineState.isOnline,
|
|
28
29
|
connected: false,
|
|
@@ -30,7 +31,7 @@ class PatchesSync extends (_a = ReadonlyStoreClass, _syncDoc_dec = [blockable],
|
|
|
30
31
|
});
|
|
31
32
|
this.options = options;
|
|
32
33
|
__runInitializers(_init, 5, this);
|
|
33
|
-
__publicField(this, "
|
|
34
|
+
__publicField(this, "connection");
|
|
34
35
|
__publicField(this, "patches");
|
|
35
36
|
__publicField(this, "maxPayloadBytes");
|
|
36
37
|
__publicField(this, "maxStorageBytes");
|
|
@@ -55,13 +56,17 @@ class PatchesSync extends (_a = ReadonlyStoreClass, _syncDoc_dec = [blockable],
|
|
|
55
56
|
this.maxPayloadBytes = options?.maxPayloadBytes;
|
|
56
57
|
this.maxStorageBytes = options?.maxStorageBytes ?? patches.docOptions?.maxStorageBytes;
|
|
57
58
|
this.sizeCalculator = options?.sizeCalculator ?? patches.docOptions?.sizeCalculator;
|
|
58
|
-
|
|
59
|
+
if (typeof urlOrConnection === "string") {
|
|
60
|
+
this.connection = new PatchesWebSocket(urlOrConnection, options?.websocket);
|
|
61
|
+
} else {
|
|
62
|
+
this.connection = urlOrConnection;
|
|
63
|
+
}
|
|
59
64
|
this.docStates = store({});
|
|
60
65
|
this.trackedDocs = new Set(patches.trackedDocs);
|
|
61
66
|
onlineState.onOnlineChange((online) => this.updateState({ online }));
|
|
62
|
-
this.
|
|
63
|
-
this.
|
|
64
|
-
this.
|
|
67
|
+
this.connection.onStateChange(this._handleConnectionChange.bind(this));
|
|
68
|
+
this.connection.onChangesCommitted(this._receiveCommittedChanges.bind(this));
|
|
69
|
+
this.connection.onDocDeleted((docId) => this._handleRemoteDocDeleted(docId));
|
|
65
70
|
patches.onTrackDocs(this._handleDocsTracked.bind(this));
|
|
66
71
|
patches.onUntrackDocs(this._handleDocsUntracked.bind(this));
|
|
67
72
|
patches.onDeleteDoc(this._handleDocDeleted.bind(this));
|
|
@@ -82,27 +87,31 @@ class PatchesSync extends (_a = ReadonlyStoreClass, _syncDoc_dec = [blockable],
|
|
|
82
87
|
return algorithm;
|
|
83
88
|
}
|
|
84
89
|
/**
|
|
85
|
-
* Gets the URL
|
|
90
|
+
* Gets the server URL.
|
|
86
91
|
*/
|
|
87
92
|
get url() {
|
|
88
|
-
return this.
|
|
93
|
+
return this.connection.url;
|
|
89
94
|
}
|
|
90
95
|
/**
|
|
91
|
-
* Sets the URL
|
|
96
|
+
* Sets the server URL. Reconnects if currently connected.
|
|
92
97
|
*/
|
|
93
98
|
set url(url) {
|
|
94
|
-
this.
|
|
99
|
+
this.connection.url = url;
|
|
95
100
|
if (this.state.connected) {
|
|
96
|
-
this.
|
|
97
|
-
this.
|
|
101
|
+
this.connection.disconnect();
|
|
102
|
+
this.connection.connect();
|
|
98
103
|
}
|
|
99
104
|
}
|
|
100
105
|
/**
|
|
101
106
|
* Gets the JSON-RPC client for making custom RPC calls.
|
|
102
|
-
*
|
|
107
|
+
* Only available when using a WebSocket connection (PatchesWebSocket or PatchesClient).
|
|
108
|
+
* Returns undefined when using REST transport.
|
|
103
109
|
*/
|
|
104
110
|
get rpc() {
|
|
105
|
-
|
|
111
|
+
if ("rpc" in this.connection) {
|
|
112
|
+
return this.connection.rpc;
|
|
113
|
+
}
|
|
114
|
+
return void 0;
|
|
106
115
|
}
|
|
107
116
|
/**
|
|
108
117
|
* Updates the sync state.
|
|
@@ -118,11 +127,11 @@ class PatchesSync extends (_a = ReadonlyStoreClass, _syncDoc_dec = [blockable],
|
|
|
118
127
|
}
|
|
119
128
|
}
|
|
120
129
|
/**
|
|
121
|
-
* Connects to the
|
|
130
|
+
* Connects to the server and starts syncing if online. If not online, it will wait for online state.
|
|
122
131
|
*/
|
|
123
132
|
async connect() {
|
|
124
133
|
try {
|
|
125
|
-
await this.
|
|
134
|
+
await this.connection.connect();
|
|
126
135
|
} catch (err) {
|
|
127
136
|
console.error("PatchesSync connection failed:", err);
|
|
128
137
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
@@ -132,10 +141,10 @@ class PatchesSync extends (_a = ReadonlyStoreClass, _syncDoc_dec = [blockable],
|
|
|
132
141
|
}
|
|
133
142
|
}
|
|
134
143
|
/**
|
|
135
|
-
* Disconnects from the
|
|
144
|
+
* Disconnects from the server and stops syncing.
|
|
136
145
|
*/
|
|
137
146
|
disconnect() {
|
|
138
|
-
this.
|
|
147
|
+
this.connection.disconnect();
|
|
139
148
|
this.updateState({ connected: false, syncStatus: "unsynced" });
|
|
140
149
|
this._resetSyncingStatuses();
|
|
141
150
|
}
|
|
@@ -181,7 +190,7 @@ class PatchesSync extends (_a = ReadonlyStoreClass, _syncDoc_dec = [blockable],
|
|
|
181
190
|
try {
|
|
182
191
|
const subscribeIds = this._filterSubscribeIds(activeDocIds);
|
|
183
192
|
if (subscribeIds.length) {
|
|
184
|
-
await this.
|
|
193
|
+
await this.connection.subscribe(subscribeIds);
|
|
185
194
|
}
|
|
186
195
|
} catch (err) {
|
|
187
196
|
console.warn("Error subscribing to active docs during sync:", err);
|
|
@@ -192,7 +201,7 @@ class PatchesSync extends (_a = ReadonlyStoreClass, _syncDoc_dec = [blockable],
|
|
|
192
201
|
const deletePromises = deletedDocs.map(async ({ docId }) => {
|
|
193
202
|
try {
|
|
194
203
|
console.info(`Attempting server delete for tombstoned doc: ${docId}`);
|
|
195
|
-
await this.
|
|
204
|
+
await this.connection.deleteDoc(docId);
|
|
196
205
|
const algorithm = this._getAlgorithm(docId);
|
|
197
206
|
await algorithm.confirmDeleteDoc(docId);
|
|
198
207
|
console.info(`Successfully deleted and untracked doc: ${docId}`);
|
|
@@ -226,12 +235,12 @@ class PatchesSync extends (_a = ReadonlyStoreClass, _syncDoc_dec = [blockable],
|
|
|
226
235
|
} else {
|
|
227
236
|
const committedRev = await algorithm.getCommittedRev(docId);
|
|
228
237
|
if (committedRev) {
|
|
229
|
-
const serverChanges = await this.
|
|
238
|
+
const serverChanges = await this.connection.getChangesSince(docId, committedRev);
|
|
230
239
|
if (serverChanges.length > 0) {
|
|
231
240
|
await this._applyServerChangesToDoc(docId, serverChanges);
|
|
232
241
|
}
|
|
233
242
|
} else {
|
|
234
|
-
const snapshot = await this.
|
|
243
|
+
const snapshot = await this.connection.getDoc(docId);
|
|
235
244
|
await algorithm.store.saveDoc(docId, snapshot);
|
|
236
245
|
this._updateDocSyncState(docId, { committedRev: snapshot.rev });
|
|
237
246
|
if (baseDoc) {
|
|
@@ -286,10 +295,10 @@ class PatchesSync extends (_a = ReadonlyStoreClass, _syncDoc_dec = [blockable],
|
|
|
286
295
|
if (!this.state.connected) {
|
|
287
296
|
throw new Error("Disconnected during flush");
|
|
288
297
|
}
|
|
289
|
-
const { changes: committed, docReloadRequired } = await this.
|
|
298
|
+
const { changes: committed, docReloadRequired } = await this.connection.commitChanges(docId, changeBatch);
|
|
290
299
|
if (docReloadRequired) {
|
|
291
300
|
await algorithm.confirmSent(docId, changeBatch);
|
|
292
|
-
const snapshot = await this.
|
|
301
|
+
const snapshot = await this.connection.getDoc(docId);
|
|
293
302
|
await algorithm.store.saveDoc(docId, snapshot);
|
|
294
303
|
this._updateDocSyncState(docId, { committedRev: snapshot.rev });
|
|
295
304
|
const openDoc = this.patches.getOpenDoc(docId);
|
|
@@ -344,7 +353,7 @@ class PatchesSync extends (_a = ReadonlyStoreClass, _syncDoc_dec = [blockable],
|
|
|
344
353
|
if (this.state.connected) {
|
|
345
354
|
try {
|
|
346
355
|
const algorithm = this._getAlgorithm(docId);
|
|
347
|
-
await this.
|
|
356
|
+
await this.connection.deleteDoc(docId);
|
|
348
357
|
await algorithm.confirmDeleteDoc(docId);
|
|
349
358
|
} catch (err) {
|
|
350
359
|
console.error(`Server delete failed for doc ${docId}, will retry on reconnect/resync.`, err);
|
|
@@ -412,7 +421,7 @@ class PatchesSync extends (_a = ReadonlyStoreClass, _syncDoc_dec = [blockable],
|
|
|
412
421
|
try {
|
|
413
422
|
const subscribeIds = this._filterSubscribeIds(newIds).filter((id) => !alreadySubscribed.has(id));
|
|
414
423
|
if (subscribeIds.length) {
|
|
415
|
-
await this.
|
|
424
|
+
await this.connection.subscribe(subscribeIds);
|
|
416
425
|
}
|
|
417
426
|
await Promise.all(newIds.map((id) => this.syncDoc(id)));
|
|
418
427
|
} catch (err) {
|
|
@@ -433,7 +442,7 @@ class PatchesSync extends (_a = ReadonlyStoreClass, _syncDoc_dec = [blockable],
|
|
|
433
442
|
const unsubscribeIds = [...subscribedBefore].filter((id) => !subscribedAfter.has(id));
|
|
434
443
|
if (this.state.connected && unsubscribeIds.length) {
|
|
435
444
|
try {
|
|
436
|
-
await this.
|
|
445
|
+
await this.connection.unsubscribe(unsubscribeIds);
|
|
437
446
|
} catch (err) {
|
|
438
447
|
console.warn(`Failed to unsubscribe docs: ${unsubscribeIds.join(", ")}`, err);
|
|
439
448
|
}
|
|
@@ -504,7 +513,7 @@ class PatchesSync extends (_a = ReadonlyStoreClass, _syncDoc_dec = [blockable],
|
|
|
504
513
|
}
|
|
505
514
|
/**
|
|
506
515
|
* Applies the subscribeFilter option to a list of doc IDs, returning the subset
|
|
507
|
-
* that should be sent to
|
|
516
|
+
* that should be sent to subscribe/unsubscribe. Returns the full list if no filter is set.
|
|
508
517
|
*/
|
|
509
518
|
_filterSubscribeIds(docIds) {
|
|
510
519
|
return this.options?.subscribeFilter?.(docIds) || docIds;
|
|
@@ -520,7 +529,7 @@ class PatchesSync extends (_a = ReadonlyStoreClass, _syncDoc_dec = [blockable],
|
|
|
520
529
|
* Helper to detect DOC_DELETED (410) errors from the server.
|
|
521
530
|
*/
|
|
522
531
|
_isDocDeletedError(err) {
|
|
523
|
-
return
|
|
532
|
+
return err instanceof StatusError && err.code === ErrorCodes.DOC_DELETED;
|
|
524
533
|
}
|
|
525
534
|
}
|
|
526
535
|
_init = __decoratorStart(_a);
|
package/dist/net/index.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
export { FetchTransport } from './http/FetchTransport.js';
|
|
2
2
|
export { PatchesClient } from './PatchesClient.js';
|
|
3
|
+
export { PatchesConnection } from './PatchesConnection.js';
|
|
3
4
|
export { PatchesSync, PatchesSyncOptions, PatchesSyncState } from './PatchesSync.js';
|
|
5
|
+
export { PatchesREST, PatchesRESTOptions } from './rest/PatchesREST.js';
|
|
6
|
+
export { BufferedEvent, SSEServer, SSEServerOptions } from './rest/SSEServer.js';
|
|
7
|
+
export { encodeDocId, normalizeIds } from './rest/utils.js';
|
|
4
8
|
export { JSONRPCClient } from './protocol/JSONRPCClient.js';
|
|
5
9
|
export { AccessLevel, ApiDefinition, ConnectionSignalSubscriber, JSONRPCServer, JSONRPCServerOptions, MessageHandler } from './protocol/JSONRPCServer.js';
|
|
6
10
|
export { getAuthContext, getClientId } from './serverContext.js';
|
|
@@ -17,7 +21,7 @@ import 'easy-signal';
|
|
|
17
21
|
import '../algorithms/ot/shared/changeBatching.js';
|
|
18
22
|
import '../client/ClientAlgorithm.js';
|
|
19
23
|
import '../json-patch/types.js';
|
|
20
|
-
import '../BaseDoc-
|
|
24
|
+
import '../BaseDoc-BT18xPxU.js';
|
|
21
25
|
import '../client/PatchesStore.js';
|
|
22
26
|
import '../client/Patches.js';
|
|
23
27
|
import '../server/types.js';
|
package/dist/net/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import "../chunk-IZ2YBCUP.js";
|
|
2
2
|
export * from "./http/FetchTransport.js";
|
|
3
3
|
export * from "./PatchesClient.js";
|
|
4
|
+
export * from "./PatchesConnection.js";
|
|
4
5
|
export * from "./PatchesSync.js";
|
|
6
|
+
export * from "./rest/index.js";
|
|
5
7
|
export * from "./protocol/JSONRPCClient.js";
|
|
6
8
|
export * from "./protocol/JSONRPCServer.js";
|
|
7
9
|
import { getAuthContext, getClientId } from "./serverContext.js";
|