@dabble/patches 0.4.5 → 0.4.7
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/algorithms/client/applyCommittedChanges.d.ts +8 -2
- package/dist/algorithms/client/applyCommittedChanges.js +30 -38
- package/dist/algorithms/client/batching.d.ts +8 -2
- package/dist/algorithms/client/batching.js +38 -37
- package/dist/algorithms/client/breakChange.d.ts +8 -2
- package/dist/algorithms/client/breakChange.js +191 -240
- package/dist/algorithms/client/createStateFromSnapshot.d.ts +8 -2
- package/dist/algorithms/client/createStateFromSnapshot.js +7 -8
- package/dist/algorithms/client/getJSONByteSize.d.ts +3 -1
- package/dist/algorithms/client/getJSONByteSize.js +12 -11
- package/dist/algorithms/client/makeChange.d.ts +8 -2
- package/dist/algorithms/client/makeChange.js +28 -36
- package/dist/algorithms/server/commitChanges.d.ts +9 -3
- package/dist/algorithms/server/commitChanges.js +69 -78
- package/dist/algorithms/server/createVersion.d.ts +9 -3
- package/dist/algorithms/server/createVersion.js +21 -27
- package/dist/algorithms/server/getSnapshotAtRevision.d.ts +9 -3
- package/dist/algorithms/server/getSnapshotAtRevision.js +27 -28
- package/dist/algorithms/server/getStateAtRevision.d.ts +9 -3
- package/dist/algorithms/server/getStateAtRevision.js +13 -17
- package/dist/algorithms/server/handleOfflineSessionsAndBatches.d.ts +9 -3
- package/dist/algorithms/server/handleOfflineSessionsAndBatches.js +60 -77
- package/dist/algorithms/server/transformIncomingChanges.d.ts +8 -2
- package/dist/algorithms/server/transformIncomingChanges.js +27 -39
- package/dist/algorithms/shared/applyChanges.d.ts +8 -2
- package/dist/algorithms/shared/applyChanges.js +11 -16
- package/dist/algorithms/shared/rebaseChanges.d.ts +8 -2
- package/dist/algorithms/shared/rebaseChanges.js +30 -49
- package/dist/chunk-IZ2YBCUP.js +56 -0
- package/dist/client/InMemoryStore.d.ts +9 -3
- package/dist/client/InMemoryStore.js +92 -101
- package/dist/client/IndexedDBStore.d.ts +9 -3
- package/dist/client/IndexedDBStore.js +378 -491
- package/dist/client/Patches.d.ts +18 -13
- package/dist/client/Patches.js +152 -207
- package/dist/client/PatchesDoc.d.ts +14 -8
- package/dist/client/PatchesDoc.js +147 -154
- package/dist/client/PatchesHistoryClient.d.ts +12 -5
- package/dist/client/PatchesHistoryClient.js +110 -117
- package/dist/client/PatchesStore.d.ts +9 -3
- package/dist/client/PatchesStore.js +0 -1
- package/dist/client/index.d.ts +12 -6
- package/dist/client/index.js +5 -5
- package/dist/data/change.d.ts +9 -3
- package/dist/data/change.js +23 -15
- package/dist/data/version.d.ts +9 -3
- package/dist/data/version.js +11 -15
- package/dist/event-signal.d.ts +7 -6
- package/dist/event-signal.js +24 -39
- package/dist/index-CvQws3AB.d.ts +36 -0
- package/dist/index.d.ts +27 -5
- package/dist/index.js +10 -4
- package/dist/json-patch/JSONPatch.d.ts +9 -5
- package/dist/json-patch/JSONPatch.js +175 -183
- package/dist/json-patch/applyPatch.d.ts +5 -2
- package/dist/json-patch/applyPatch.js +27 -35
- package/dist/json-patch/composePatch.d.ts +5 -2
- package/dist/json-patch/composePatch.js +34 -34
- package/dist/json-patch/createJSONPatch.d.ts +7 -2
- package/dist/json-patch/createJSONPatch.js +11 -38
- package/dist/json-patch/index.d.ts +14 -6
- package/dist/json-patch/index.js +20 -9
- package/dist/json-patch/invertPatch.d.ts +5 -2
- package/dist/json-patch/invertPatch.js +31 -30
- package/dist/json-patch/ops/add.d.ts +5 -2
- package/dist/json-patch/ops/add.js +53 -51
- package/dist/json-patch/ops/bitmask.d.ts +8 -5
- package/dist/json-patch/ops/bitmask.js +41 -44
- package/dist/json-patch/ops/copy.d.ts +5 -2
- package/dist/json-patch/ops/copy.js +32 -33
- package/dist/json-patch/ops/increment.d.ts +5 -2
- package/dist/json-patch/ops/increment.js +21 -20
- package/dist/json-patch/ops/index.d.ts +10 -21
- package/dist/json-patch/ops/index.js +34 -24
- package/dist/json-patch/ops/move.d.ts +5 -2
- package/dist/json-patch/ops/move.js +132 -198
- package/dist/json-patch/ops/remove.d.ts +5 -2
- package/dist/json-patch/ops/remove.js +33 -30
- package/dist/json-patch/ops/replace.d.ts +5 -2
- package/dist/json-patch/ops/replace.js +45 -43
- package/dist/json-patch/ops/test.d.ts +5 -2
- package/dist/json-patch/ops/test.js +25 -21
- package/dist/json-patch/ops/text.d.ts +5 -2
- package/dist/json-patch/ops/text.js +54 -54
- package/dist/json-patch/pathProxy.d.ts +9 -3
- package/dist/json-patch/pathProxy.js +27 -48
- package/dist/json-patch/state.d.ts +5 -2
- package/dist/json-patch/state.js +11 -7
- package/dist/json-patch/transformPatch.d.ts +6 -2
- package/dist/json-patch/transformPatch.js +21 -24
- package/dist/json-patch/types.d.ts +9 -7
- package/dist/json-patch/types.js +0 -1
- package/dist/json-patch/utils/deepEqual.d.ts +3 -1
- package/dist/json-patch/utils/deepEqual.js +32 -28
- package/dist/json-patch/utils/exit.d.ts +5 -2
- package/dist/json-patch/utils/exit.js +7 -3
- package/dist/json-patch/utils/get.d.ts +5 -2
- package/dist/json-patch/utils/get.js +8 -4
- package/dist/json-patch/utils/getOpData.d.ts +5 -2
- package/dist/json-patch/utils/getOpData.js +12 -9
- package/dist/json-patch/utils/getType.d.ts +6 -3
- package/dist/json-patch/utils/getType.js +9 -4
- package/dist/json-patch/utils/index.d.ts +15 -14
- package/dist/json-patch/utils/index.js +14 -14
- package/dist/json-patch/utils/log.d.ts +4 -5
- package/dist/json-patch/utils/log.js +8 -3
- package/dist/json-patch/utils/ops.d.ts +8 -5
- package/dist/json-patch/utils/ops.js +83 -100
- package/dist/json-patch/utils/paths.d.ts +12 -9
- package/dist/json-patch/utils/paths.js +54 -51
- package/dist/json-patch/utils/pluck.d.ts +8 -5
- package/dist/json-patch/utils/pluck.js +32 -26
- package/dist/json-patch/utils/shallowCopy.d.ts +3 -1
- package/dist/json-patch/utils/shallowCopy.js +22 -18
- package/dist/json-patch/utils/softWrites.d.ts +6 -3
- package/dist/json-patch/utils/softWrites.js +17 -16
- package/dist/json-patch/utils/toArrayIndex.d.ts +3 -1
- package/dist/json-patch/utils/toArrayIndex.js +14 -10
- package/dist/json-patch/utils/toKeys.d.ts +3 -1
- package/dist/json-patch/utils/toKeys.js +15 -11
- package/dist/json-patch/utils/updateArrayIndexes.d.ts +5 -2
- package/dist/json-patch/utils/updateArrayIndexes.js +33 -37
- package/dist/json-patch/utils/updateArrayPath.d.ts +5 -2
- package/dist/json-patch/utils/updateArrayPath.js +29 -42
- package/dist/net/PatchesClient.d.ts +128 -0
- package/dist/net/PatchesClient.js +161 -0
- package/dist/net/PatchesSync.d.ts +19 -9
- package/dist/net/PatchesSync.js +291 -386
- package/dist/net/error.d.ts +3 -1
- package/dist/net/error.js +9 -6
- package/dist/net/http/FetchTransport.d.ts +21 -0
- package/dist/net/http/FetchTransport.js +34 -0
- package/dist/net/index.d.ts +26 -12
- package/dist/net/index.js +12 -10
- package/dist/net/protocol/JSONRPCClient.d.ts +11 -4
- package/dist/net/protocol/JSONRPCClient.js +95 -103
- package/dist/net/protocol/JSONRPCServer.d.ts +15 -8
- package/dist/net/protocol/JSONRPCServer.js +101 -123
- package/dist/net/protocol/types.d.ts +21 -15
- package/dist/net/protocol/types.js +0 -1
- package/dist/net/protocol/utils.d.ts +12 -0
- package/dist/net/protocol/utils.js +15 -0
- package/dist/net/types.d.ts +4 -2
- package/dist/net/types.js +0 -1
- package/dist/net/webrtc/WebRTCAwareness.d.ts +14 -4
- package/dist/net/webrtc/WebRTCAwareness.js +111 -120
- package/dist/net/webrtc/WebRTCTransport.d.ts +16 -8
- package/dist/net/webrtc/WebRTCTransport.js +149 -157
- package/dist/net/webrtc/index.d.ts +10 -2
- package/dist/net/webrtc/index.js +2 -2
- package/dist/net/websocket/AuthorizationProvider.d.ts +7 -5
- package/dist/net/websocket/AuthorizationProvider.js +12 -17
- package/dist/net/websocket/PatchesWebSocket.d.ts +14 -109
- package/dist/net/websocket/PatchesWebSocket.js +37 -184
- package/dist/net/websocket/RPCServer.d.ts +19 -10
- package/dist/net/websocket/RPCServer.js +190 -192
- package/dist/net/websocket/SignalingService.d.ts +12 -32
- package/dist/net/websocket/SignalingService.js +126 -133
- package/dist/net/websocket/WebSocketServer.d.ts +17 -4
- package/dist/net/websocket/WebSocketServer.js +64 -72
- package/dist/net/websocket/WebSocketTransport.d.ts +13 -5
- package/dist/net/websocket/WebSocketTransport.js +178 -207
- package/dist/net/websocket/onlineState.d.ts +6 -3
- package/dist/net/websocket/onlineState.js +25 -21
- package/dist/server/PatchesBranchManager.d.ts +12 -5
- package/dist/server/PatchesBranchManager.js +132 -142
- package/dist/server/PatchesHistoryManager.d.ts +11 -3
- package/dist/server/PatchesHistoryManager.js +81 -84
- package/dist/server/PatchesServer.d.ts +16 -10
- package/dist/server/PatchesServer.js +131 -137
- package/dist/server/index.d.ts +7 -2
- package/dist/server/index.js +9 -3
- package/dist/server/types.d.ts +9 -3
- package/dist/server/types.js +0 -1
- package/dist/types.d.ts +38 -19
- package/dist/types.js +1 -1
- package/dist/utils/concurrency.d.ts +7 -5
- package/dist/utils/concurrency.js +43 -53
- package/dist/utils/deferred.d.ts +4 -2
- package/dist/utils/deferred.js +25 -21
- package/package.json +13 -15
|
@@ -1,155 +1,148 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
* Updates the syncing state of the document.
|
|
146
|
-
* @param newSyncing The new syncing state.
|
|
147
|
-
*/
|
|
148
|
-
updateSyncing(newSyncing) {
|
|
149
|
-
this._syncing = newSyncing;
|
|
150
|
-
this.onSyncing.emit(newSyncing);
|
|
151
|
-
}
|
|
152
|
-
toJSON() {
|
|
153
|
-
return this.export();
|
|
154
|
-
}
|
|
1
|
+
import "../chunk-IZ2YBCUP.js";
|
|
2
|
+
import { createStateFromSnapshot } from "../algorithms/client/createStateFromSnapshot.js";
|
|
3
|
+
import { makeChange } from "../algorithms/client/makeChange.js";
|
|
4
|
+
import { applyChanges } from "../algorithms/shared/applyChanges.js";
|
|
5
|
+
import { signal } from "../event-signal.js";
|
|
6
|
+
class PatchesDoc {
|
|
7
|
+
_id = null;
|
|
8
|
+
_state;
|
|
9
|
+
_snapshot;
|
|
10
|
+
_changeMetadata = {};
|
|
11
|
+
_syncing = null;
|
|
12
|
+
_maxPayloadBytes;
|
|
13
|
+
/** Subscribe to be notified before local state changes. */
|
|
14
|
+
onBeforeChange = signal();
|
|
15
|
+
/** Subscribe to be notified after local state changes are applied. */
|
|
16
|
+
onChange = signal();
|
|
17
|
+
/** Subscribe to be notified whenever state changes from any source. */
|
|
18
|
+
onUpdate = signal();
|
|
19
|
+
/** Subscribe to be notified when syncing state changes. */
|
|
20
|
+
onSyncing = signal();
|
|
21
|
+
/**
|
|
22
|
+
* Creates an instance of PatchesDoc.
|
|
23
|
+
* @param initialState Optional initial state.
|
|
24
|
+
* @param initialMetadata Optional metadata to add to generated changes.
|
|
25
|
+
* @param options Additional options for the document.
|
|
26
|
+
*/
|
|
27
|
+
constructor(initialState = {}, initialMetadata = {}, options = {}) {
|
|
28
|
+
this._state = structuredClone(initialState);
|
|
29
|
+
this._snapshot = { state: this._state, rev: 0, changes: [] };
|
|
30
|
+
this._changeMetadata = initialMetadata;
|
|
31
|
+
this._maxPayloadBytes = options.maxPayloadBytes;
|
|
32
|
+
}
|
|
33
|
+
/** The unique identifier for this document, once assigned. */
|
|
34
|
+
get id() {
|
|
35
|
+
return this._id;
|
|
36
|
+
}
|
|
37
|
+
/** Current local state (committed + pending). */
|
|
38
|
+
get state() {
|
|
39
|
+
return this._state;
|
|
40
|
+
}
|
|
41
|
+
/** Are we currently syncing this document? */
|
|
42
|
+
get syncing() {
|
|
43
|
+
return this._syncing;
|
|
44
|
+
}
|
|
45
|
+
/** Last committed revision number from the server. */
|
|
46
|
+
get committedRev() {
|
|
47
|
+
return this._snapshot.rev;
|
|
48
|
+
}
|
|
49
|
+
/** Are there local changes that haven't been sent yet? */
|
|
50
|
+
get hasPending() {
|
|
51
|
+
return this._snapshot.changes.length > 0;
|
|
52
|
+
}
|
|
53
|
+
/** Subscribe to be notified whenever the state changes. */
|
|
54
|
+
subscribe(onUpdate) {
|
|
55
|
+
const unsub = this.onUpdate(onUpdate);
|
|
56
|
+
onUpdate(this._state);
|
|
57
|
+
return unsub;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Exports the document state for persistence.
|
|
61
|
+
* NOTE: Any changes currently marked as `sending` are included in the
|
|
62
|
+
* `changes` array alongside `pending` changes. On import, all changes
|
|
63
|
+
* are treated as pending.
|
|
64
|
+
*/
|
|
65
|
+
export() {
|
|
66
|
+
return structuredClone(this._snapshot);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Imports previously exported document state.
|
|
70
|
+
* Resets sending state and treats all imported changes as pending.
|
|
71
|
+
*/
|
|
72
|
+
import(snapshot) {
|
|
73
|
+
this._snapshot = structuredClone(snapshot);
|
|
74
|
+
this._state = createStateFromSnapshot(snapshot);
|
|
75
|
+
this.onUpdate.emit(this._state);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Sets metadata to be added to future changes.
|
|
79
|
+
*/
|
|
80
|
+
setChangeMetadata(metadata) {
|
|
81
|
+
this._changeMetadata = metadata;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Applies an update to the local state, generating a patch and adding it to pending changes.
|
|
85
|
+
* @param mutator Function that uses JSONPatch methods with type-safe paths.
|
|
86
|
+
* @returns The generated Change objects.
|
|
87
|
+
*/
|
|
88
|
+
change(mutator) {
|
|
89
|
+
const changes = makeChange(this._snapshot, mutator, this._changeMetadata, this._maxPayloadBytes);
|
|
90
|
+
if (changes.length === 0) {
|
|
91
|
+
return changes;
|
|
92
|
+
}
|
|
93
|
+
this._state = applyChanges(this._state, changes);
|
|
94
|
+
this._snapshot.changes.push(...changes);
|
|
95
|
+
this.onChange.emit(changes);
|
|
96
|
+
this.onUpdate.emit(this._state);
|
|
97
|
+
return changes;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Returns the pending changes for this document.
|
|
101
|
+
* @returns The pending changes.
|
|
102
|
+
*/
|
|
103
|
+
getPendingChanges() {
|
|
104
|
+
return this._snapshot.changes;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Applies committed changes to the document. Should only be called from a sync provider.
|
|
108
|
+
* @param serverChanges The changes to apply.
|
|
109
|
+
* @param rebasedPendingChanges The rebased pending changes to apply.
|
|
110
|
+
*/
|
|
111
|
+
applyCommittedChanges(serverChanges, rebasedPendingChanges) {
|
|
112
|
+
if (this._snapshot.rev !== serverChanges[0].rev - 1) {
|
|
113
|
+
throw new Error("Cannot apply committed changes to a doc that is not at the correct revision");
|
|
114
|
+
}
|
|
115
|
+
this._snapshot.state = applyChanges(this._snapshot.state, serverChanges);
|
|
116
|
+
this._snapshot.rev = serverChanges[serverChanges.length - 1].rev;
|
|
117
|
+
this._snapshot.changes = rebasedPendingChanges;
|
|
118
|
+
this._state = createStateFromSnapshot(this._snapshot);
|
|
119
|
+
this.onUpdate.emit(this._state);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Assigns an identifier to this document. Can only be set once.
|
|
123
|
+
* @param id The unique identifier for the document.
|
|
124
|
+
* @throws Error if the ID has already been set.
|
|
125
|
+
*/
|
|
126
|
+
setId(id) {
|
|
127
|
+
if (this._id !== null && this._id !== id) {
|
|
128
|
+
throw new Error(`Document ID cannot be changed once set. Current: ${this._id}, Attempted: ${id}`);
|
|
129
|
+
}
|
|
130
|
+
if (this._id === null) {
|
|
131
|
+
this._id = id;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Updates the syncing state of the document.
|
|
136
|
+
* @param newSyncing The new syncing state.
|
|
137
|
+
*/
|
|
138
|
+
updateSyncing(newSyncing) {
|
|
139
|
+
this._syncing = newSyncing;
|
|
140
|
+
this.onSyncing.emit(newSyncing);
|
|
141
|
+
}
|
|
142
|
+
toJSON() {
|
|
143
|
+
return this.export();
|
|
144
|
+
}
|
|
155
145
|
}
|
|
146
|
+
export {
|
|
147
|
+
PatchesDoc
|
|
148
|
+
};
|
|
@@ -1,17 +1,22 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { Signal } from '../event-signal.js';
|
|
2
|
+
import { PatchesAPI } from '../net/protocol/types.js';
|
|
3
|
+
import { VersionMetadata, ListVersionsOptions, EditableVersionMetadata, Change } from '../types.js';
|
|
4
|
+
import '../json-patch/JSONPatch.js';
|
|
5
|
+
import '@dabble/delta';
|
|
6
|
+
import '../json-patch/types.js';
|
|
7
|
+
|
|
3
8
|
/**
|
|
4
9
|
* Client-side history/scrubbing interface for a document.
|
|
5
10
|
* Read-only: allows listing versions, loading states/changes, and scrubbing.
|
|
6
11
|
*/
|
|
7
|
-
|
|
12
|
+
declare class PatchesHistoryClient<T = any> {
|
|
8
13
|
private readonly api;
|
|
9
14
|
/** Document ID */
|
|
10
15
|
readonly id: string;
|
|
11
16
|
/** Event signal for versions changes */
|
|
12
|
-
readonly onVersionsChange:
|
|
17
|
+
readonly onVersionsChange: Signal<(versions: VersionMetadata[]) => void>;
|
|
13
18
|
/** Event signal for state changes */
|
|
14
|
-
readonly onStateChange:
|
|
19
|
+
readonly onStateChange: Signal<(state: T) => void>;
|
|
15
20
|
private _versions;
|
|
16
21
|
private _state;
|
|
17
22
|
private cache;
|
|
@@ -35,3 +40,5 @@ export declare class PatchesHistoryClient<T = any> {
|
|
|
35
40
|
/** Clear caches and listeners */
|
|
36
41
|
clear(): void;
|
|
37
42
|
}
|
|
43
|
+
|
|
44
|
+
export { PatchesHistoryClient };
|
|
@@ -1,125 +1,118 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import "../chunk-IZ2YBCUP.js";
|
|
2
|
+
import { applyChanges } from "../algorithms/shared/applyChanges.js";
|
|
3
|
+
import { signal } from "../event-signal.js";
|
|
3
4
|
class LRUCache {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
constructor(maxSize) {
|
|
6
|
+
this.maxSize = maxSize;
|
|
7
|
+
}
|
|
8
|
+
cache = /* @__PURE__ */ new Map();
|
|
9
|
+
get(key) {
|
|
10
|
+
const value = this.cache.get(key);
|
|
11
|
+
if (value !== void 0) {
|
|
12
|
+
this.cache.delete(key);
|
|
13
|
+
this.cache.set(key, value);
|
|
8
14
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
this.cache.delete(key);
|
|
21
|
-
this.cache.set(key, value);
|
|
22
|
-
if (this.cache.size > this.maxSize) {
|
|
23
|
-
// Remove least recently used
|
|
24
|
-
const firstKeyIter = this.cache.keys().next();
|
|
25
|
-
if (!firstKeyIter.done) {
|
|
26
|
-
const firstKey = firstKeyIter.value;
|
|
27
|
-
this.cache.delete(firstKey);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
clear() {
|
|
32
|
-
this.cache.clear();
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
set(key, value) {
|
|
18
|
+
if (this.cache.has(key)) this.cache.delete(key);
|
|
19
|
+
this.cache.set(key, value);
|
|
20
|
+
if (this.cache.size > this.maxSize) {
|
|
21
|
+
const firstKeyIter = this.cache.keys().next();
|
|
22
|
+
if (!firstKeyIter.done) {
|
|
23
|
+
const firstKey = firstKeyIter.value;
|
|
24
|
+
this.cache.delete(firstKey);
|
|
25
|
+
}
|
|
33
26
|
}
|
|
27
|
+
}
|
|
28
|
+
clear() {
|
|
29
|
+
this.cache.clear();
|
|
30
|
+
}
|
|
34
31
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
let data = this.cache.get(versionId);
|
|
82
|
-
if (!data || data.state === undefined) {
|
|
83
|
-
const { state } = await this.api.getVersionState(this.id, versionId);
|
|
84
|
-
data = { ...data, state };
|
|
85
|
-
this.cache.set(versionId, data);
|
|
86
|
-
}
|
|
87
|
-
this._state = data.state;
|
|
88
|
-
this.onStateChange.emit(this._state);
|
|
89
|
-
return data.state;
|
|
90
|
-
}
|
|
91
|
-
/** Load the changes for a specific version */
|
|
92
|
-
async getVersionChanges(versionId) {
|
|
93
|
-
let data = this.cache.get(versionId);
|
|
94
|
-
if (!data || data.changes === undefined) {
|
|
95
|
-
const changes = await this.api.getVersionChanges(this.id, versionId);
|
|
96
|
-
data = { ...data, changes };
|
|
97
|
-
this.cache.set(versionId, data);
|
|
98
|
-
}
|
|
99
|
-
return data.changes;
|
|
32
|
+
class PatchesHistoryClient {
|
|
33
|
+
constructor(id, api) {
|
|
34
|
+
this.api = api;
|
|
35
|
+
this.id = id;
|
|
36
|
+
}
|
|
37
|
+
/** Document ID */
|
|
38
|
+
id;
|
|
39
|
+
/** Event signal for versions changes */
|
|
40
|
+
onVersionsChange = signal();
|
|
41
|
+
/** Event signal for state changes */
|
|
42
|
+
onStateChange = signal();
|
|
43
|
+
_versions = [];
|
|
44
|
+
_state = null;
|
|
45
|
+
cache = new LRUCache(6);
|
|
46
|
+
/** List of loaded versions */
|
|
47
|
+
get versions() {
|
|
48
|
+
return this._versions;
|
|
49
|
+
}
|
|
50
|
+
/** Current state (for scrubbing) */
|
|
51
|
+
get state() {
|
|
52
|
+
return this._state;
|
|
53
|
+
}
|
|
54
|
+
/** List version metadata for this document (with options) */
|
|
55
|
+
async listVersions(options) {
|
|
56
|
+
this._versions = await this.api.listVersions(this.id, options);
|
|
57
|
+
this.onVersionsChange.emit(this._versions);
|
|
58
|
+
return this._versions;
|
|
59
|
+
}
|
|
60
|
+
/** Create a new named version snapshot of the document's current state. */
|
|
61
|
+
async createVersion(metadata) {
|
|
62
|
+
const versionId = await this.api.createVersion(this.id, metadata);
|
|
63
|
+
await this.listVersions();
|
|
64
|
+
return versionId;
|
|
65
|
+
}
|
|
66
|
+
/** Update the name of a specific version. */
|
|
67
|
+
async updateVersion(versionId, metadata) {
|
|
68
|
+
await this.api.updateVersion(this.id, versionId, metadata);
|
|
69
|
+
await this.listVersions();
|
|
70
|
+
}
|
|
71
|
+
/** Load the state for a specific version */
|
|
72
|
+
async getVersionState(versionId) {
|
|
73
|
+
let data = this.cache.get(versionId);
|
|
74
|
+
if (!data || data.state === void 0) {
|
|
75
|
+
const { state } = await this.api.getVersionState(this.id, versionId);
|
|
76
|
+
data = { ...data, state };
|
|
77
|
+
this.cache.set(versionId, data);
|
|
100
78
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
this.onStateChange.emit(this._state);
|
|
79
|
+
this._state = data.state;
|
|
80
|
+
this.onStateChange.emit(this._state);
|
|
81
|
+
return data.state;
|
|
82
|
+
}
|
|
83
|
+
/** Load the changes for a specific version */
|
|
84
|
+
async getVersionChanges(versionId) {
|
|
85
|
+
let data = this.cache.get(versionId);
|
|
86
|
+
if (!data || data.changes === void 0) {
|
|
87
|
+
const changes = await this.api.getVersionChanges(this.id, versionId);
|
|
88
|
+
data = { ...data, changes };
|
|
89
|
+
this.cache.set(versionId, data);
|
|
114
90
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
91
|
+
return data.changes;
|
|
92
|
+
}
|
|
93
|
+
/** Scrub to a specific change within a version where changeIndex is 1-based and 0 is the parent version */
|
|
94
|
+
async scrubTo(versionId, changeIndex) {
|
|
95
|
+
const version = this.versions.find((v) => v.id === versionId);
|
|
96
|
+
const [state, changes] = await Promise.all([
|
|
97
|
+
version?.parentId ? this.getVersionState(version.parentId) : void 0,
|
|
98
|
+
this.getVersionChanges(versionId)
|
|
99
|
+
]);
|
|
100
|
+
if (changeIndex > 0) {
|
|
101
|
+
this._state = applyChanges(state, changes.slice(0, changeIndex));
|
|
124
102
|
}
|
|
103
|
+
this.onStateChange.emit(this._state);
|
|
104
|
+
}
|
|
105
|
+
/** Clear caches and listeners */
|
|
106
|
+
clear() {
|
|
107
|
+
this._versions = [];
|
|
108
|
+
this._state = null;
|
|
109
|
+
this.onVersionsChange.emit(this._versions);
|
|
110
|
+
this.onStateChange.emit(this._state);
|
|
111
|
+
this.cache.clear();
|
|
112
|
+
this.onVersionsChange.clear();
|
|
113
|
+
this.onStateChange.clear();
|
|
114
|
+
}
|
|
125
115
|
}
|
|
116
|
+
export {
|
|
117
|
+
PatchesHistoryClient
|
|
118
|
+
};
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { PatchesSnapshot, Change, PatchesState } from '../types.js';
|
|
2
|
+
import '../json-patch/JSONPatch.js';
|
|
3
|
+
import '@dabble/delta';
|
|
4
|
+
import '../json-patch/types.js';
|
|
5
|
+
|
|
2
6
|
/** Represents metadata for a document tracked by the store. */
|
|
3
|
-
|
|
7
|
+
interface TrackedDoc {
|
|
4
8
|
docId: string;
|
|
5
9
|
/** The last revision number confirmed by the server. */
|
|
6
10
|
committedRev: number;
|
|
@@ -11,7 +15,7 @@ export interface TrackedDoc {
|
|
|
11
15
|
* Pluggable persistence layer contract used by Patches + PatchesSync.
|
|
12
16
|
* It is *not* strictly offline; an in‑memory implementation fulfils the same contract.
|
|
13
17
|
*/
|
|
14
|
-
|
|
18
|
+
interface PatchesStore {
|
|
15
19
|
/**
|
|
16
20
|
* Registers documents for local tracking and synchronization.
|
|
17
21
|
*
|
|
@@ -214,3 +218,5 @@ export interface PatchesStore {
|
|
|
214
218
|
*/
|
|
215
219
|
close(): Promise<void>;
|
|
216
220
|
}
|
|
221
|
+
|
|
222
|
+
export type { PatchesStore, TrackedDoc };
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
6
|
-
export
|
|
1
|
+
export { IndexedDBStore } from './IndexedDBStore.js';
|
|
2
|
+
export { InMemoryStore } from './InMemoryStore.js';
|
|
3
|
+
export { Patches, PatchesOptions } from './Patches.js';
|
|
4
|
+
export { PatchesDoc, PatchesDocOptions } from './PatchesDoc.js';
|
|
5
|
+
export { PatchesHistoryClient } from './PatchesHistoryClient.js';
|
|
6
|
+
export { PatchesStore, TrackedDoc } from './PatchesStore.js';
|
|
7
|
+
import '../types.js';
|
|
8
|
+
import '../json-patch/JSONPatch.js';
|
|
9
|
+
import '@dabble/delta';
|
|
10
|
+
import '../json-patch/types.js';
|
|
11
|
+
import '../event-signal.js';
|
|
12
|
+
import '../net/protocol/types.js';
|
package/dist/client/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
5
|
-
export * from
|
|
1
|
+
export * from "./IndexedDBStore.js";
|
|
2
|
+
export * from "./InMemoryStore.js";
|
|
3
|
+
export * from "./Patches.js";
|
|
4
|
+
export * from "./PatchesDoc.js";
|
|
5
|
+
export * from "./PatchesHistoryClient.js";
|