@dabble/patches 0.8.18 → 0.8.19
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-BT18xPxU.d.ts → BaseDoc-CXHXcW18.d.ts} +11 -2
- package/dist/algorithms/ot/server/createVersion.d.ts +1 -1
- 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/LWWAlgorithm.js +6 -1
- package/dist/client/LWWDoc.d.ts +48 -4
- package/dist/client/LWWDoc.js +80 -11
- package/dist/client/OTAlgorithm.d.ts +1 -1
- package/dist/client/OTDoc.d.ts +1 -1
- package/dist/client/OTDoc.js +29 -4
- package/dist/client/Patches.d.ts +1 -1
- package/dist/client/PatchesBranchClient.d.ts +1 -1
- 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/index.d.ts +1 -1
- package/dist/net/PatchesSync.d.ts +1 -1
- package/dist/net/index.d.ts +1 -1
- package/dist/server/branchUtils.d.ts +1 -1
- package/dist/shared/doc-manager.d.ts +1 -1
- package/dist/solid/context.d.ts +1 -1
- package/dist/solid/doc-manager.d.ts +1 -1
- package/dist/solid/index.d.ts +1 -1
- package/dist/solid/primitives.d.ts +1 -1
- package/dist/vue/composables.d.ts +2 -2
- package/dist/vue/doc-manager.d.ts +1 -1
- package/dist/vue/index.d.ts +1 -1
- package/dist/vue/managed-docs.d.ts +2 -2
- package/dist/vue/provider.d.ts +1 -1
- package/package.json +1 -1
|
@@ -47,7 +47,16 @@ declare class OTDoc<T extends object = object> extends BaseDoc<T> {
|
|
|
47
47
|
getPendingChanges(): Change[];
|
|
48
48
|
/**
|
|
49
49
|
* Imports document state from a snapshot (e.g., for recovery when out of sync).
|
|
50
|
-
* Resets state
|
|
50
|
+
* Resets committed/pending state from the snapshot but PRESERVES outstanding
|
|
51
|
+
* optimistic ops (re-applied on top of the new state, dropping any that fail).
|
|
52
|
+
*
|
|
53
|
+
* Why preserve optimistic ops: import() can be called by sync recovery /
|
|
54
|
+
* cross-tab snapshot broadcast paths while the user is mid-typing. Wiping
|
|
55
|
+
* `_optimisticOps` would silently regress the input back to the snapshot
|
|
56
|
+
* value, causing visible "text jumps" and lost characters.
|
|
57
|
+
*
|
|
58
|
+
* Stale-snapshot guard: snapshots older than the current `_committedRev`
|
|
59
|
+
* are ignored — we already know more than the caller does.
|
|
51
60
|
*/
|
|
52
61
|
import(snapshot: PatchesSnapshot<T>): void;
|
|
53
62
|
/**
|
|
@@ -237,4 +246,4 @@ declare abstract class BaseDoc<T extends object = object> extends ReadonlyStoreC
|
|
|
237
246
|
abstract import(snapshot: PatchesSnapshot<T>): void;
|
|
238
247
|
}
|
|
239
248
|
|
|
240
|
-
export { BaseDoc as B, OTDoc as O, type
|
|
249
|
+
export { BaseDoc as B, OTDoc as O, type PatchesDocOptions as P, type PatchesDoc as a };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { OTStoreBackend } from '../../../server/types.js';
|
|
2
|
-
import { EditableVersionMetadata,
|
|
2
|
+
import { EditableVersionMetadata, VersionMetadata, Change } from '../../../types.js';
|
|
3
3
|
import '../../../json-patch/types.js';
|
|
4
4
|
import '../../../json-patch/JSONPatch.js';
|
|
5
5
|
import '@dabble/delta';
|
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 { a as PatchesDoc } from '../BaseDoc-CXHXcW18.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 { a as PatchesDoc } from '../BaseDoc-CXHXcW18.js';
|
|
6
6
|
import { TrackedDoc } from './PatchesStore.js';
|
|
7
7
|
import '../json-patch/JSONPatch.js';
|
|
8
8
|
import '@dabble/delta';
|
|
@@ -26,7 +26,12 @@ class LWWAlgorithm {
|
|
|
26
26
|
const committedRev = doc?.committedRev ?? await this.store.getCommittedRev(docId);
|
|
27
27
|
const changes = [createChange(committedRev, committedRev + 1, timedOps, metadata)];
|
|
28
28
|
if (doc) {
|
|
29
|
-
|
|
29
|
+
const existingByPath = new Map(existingOps.map((op) => [op.path, op]));
|
|
30
|
+
const retiredInFlightOps = opsToSave.map((op) => existingByPath.get(op.path)).filter((op) => op !== void 0);
|
|
31
|
+
doc.applyChanges(changes, true, {
|
|
32
|
+
inFlightOpsOverride: opsToSave,
|
|
33
|
+
retiredInFlightOps
|
|
34
|
+
});
|
|
30
35
|
}
|
|
31
36
|
return changes;
|
|
32
37
|
}
|
package/dist/client/LWWDoc.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { JSONPatchOp } from '../json-patch/types.js';
|
|
1
2
|
import { PatchesSnapshot, Change } from '../types.js';
|
|
2
|
-
import { B as BaseDoc } from '../BaseDoc-
|
|
3
|
+
import { B as BaseDoc } from '../BaseDoc-CXHXcW18.js';
|
|
3
4
|
import '../json-patch/JSONPatch.js';
|
|
4
5
|
import '@dabble/delta';
|
|
5
|
-
import '../json-patch/types.js';
|
|
6
6
|
import 'easy-signal';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -29,6 +29,22 @@ declare class LWWDoc<T extends object = object> extends BaseDoc<T> {
|
|
|
29
29
|
protected _hasPending: boolean;
|
|
30
30
|
/** Confirmed state (from algorithm pipeline), used to recompute after server changes. */
|
|
31
31
|
protected _baseState: T;
|
|
32
|
+
/**
|
|
33
|
+
* Content keys of pending local ops that have been applied to `_baseState` via the
|
|
34
|
+
* local-confirmation path (`committedAt === 0`) but not yet echoed back from the server.
|
|
35
|
+
*
|
|
36
|
+
* We key by op CONTENT (JSON.stringify) rather than by Change id because the LWW
|
|
37
|
+
* algorithm coalesces pending ops in its store and reissues a fresh sending Change
|
|
38
|
+
* (with a new id) in `getPendingToSend()`. The server then echoes that re-issued id
|
|
39
|
+
* back, so id-based echo detection would always fail. Op content (path + op + value
|
|
40
|
+
* + ts) survives the reissue intact, since the LWW algorithm preserves the original
|
|
41
|
+
* timestamped ops end-to-end.
|
|
42
|
+
*
|
|
43
|
+
* On a pure echo we skip both `_baseState += ops` (already applied locally) and
|
|
44
|
+
* `_recomputeState()` (would just produce a structurally-identical state with a
|
|
45
|
+
* fresh object identity, causing a spurious store emit mid-typing).
|
|
46
|
+
*/
|
|
47
|
+
protected _inFlightOpKeys: Set<string>;
|
|
32
48
|
/**
|
|
33
49
|
* Creates an instance of LWWDoc.
|
|
34
50
|
* @param id The unique identifier for this document.
|
|
@@ -41,7 +57,16 @@ declare class LWWDoc<T extends object = object> extends BaseDoc<T> {
|
|
|
41
57
|
get hasPending(): boolean;
|
|
42
58
|
/**
|
|
43
59
|
* Imports document state from a snapshot (e.g., for recovery when out of sync).
|
|
44
|
-
* Resets
|
|
60
|
+
* Resets `_baseState` from the snapshot but PRESERVES outstanding optimistic ops
|
|
61
|
+
* (re-applied on top of the new state, dropping any that fail).
|
|
62
|
+
*
|
|
63
|
+
* Why preserve optimistic ops: import() can be called by sync recovery /
|
|
64
|
+
* cross-tab snapshot broadcast paths while the user is mid-typing. Wiping
|
|
65
|
+
* `_optimisticOps` would silently regress the input back to the snapshot
|
|
66
|
+
* value, causing visible "text jumps" and lost characters.
|
|
67
|
+
*
|
|
68
|
+
* Stale-snapshot guard: snapshots older than the current `_committedRev`
|
|
69
|
+
* are ignored — we already know more than the caller does.
|
|
45
70
|
*/
|
|
46
71
|
import(snapshot: PatchesSnapshot<T>): void;
|
|
47
72
|
/**
|
|
@@ -61,8 +86,27 @@ declare class LWWDoc<T extends object = object> extends BaseDoc<T> {
|
|
|
61
86
|
* @param changes Array of changes to apply
|
|
62
87
|
* @param hasPending If provided, overrides the inferred pending state.
|
|
63
88
|
* Used by LWWAlgorithm which knows the true pending state from the store.
|
|
89
|
+
* @param options Algorithm-only escape hatches for in-flight echo tracking:
|
|
90
|
+
* - `inFlightOpsOverride`: tracks these ops in `_inFlightOpKeys` (and uses
|
|
91
|
+
* them for echo detection) on local-confirm changes, INSTEAD of `c.ops`.
|
|
92
|
+
* Required for combinable ops (`@inc`/`@bit`/`@max`/`@min`) where the
|
|
93
|
+
* local-confirm Change carries the user's raw intent op but the algorithm
|
|
94
|
+
* ships a consolidated op to the server. Without the override, the server
|
|
95
|
+
* echo of the consolidated op wouldn't match any tracked key and we'd
|
|
96
|
+
* emit a spurious recompute.
|
|
97
|
+
* - `retiredInFlightOps`: drops these keys from `_inFlightOpKeys` on the
|
|
98
|
+
* same call. Used by the algorithm to prune prior pending-op keys at
|
|
99
|
+
* paths that are about to be overwritten by `inFlightOpsOverride`,
|
|
100
|
+
* preventing unbounded orphan accumulation during fast typing into the
|
|
101
|
+
* same field.
|
|
102
|
+
*
|
|
103
|
+
* External callers (Worker-Tab sync, tests) should leave `options` undefined
|
|
104
|
+
* and the legacy `c.ops`-based tracker will run.
|
|
64
105
|
*/
|
|
65
|
-
applyChanges(changes: Change[], hasPending?: boolean
|
|
106
|
+
applyChanges(changes: Change[], hasPending?: boolean, options?: {
|
|
107
|
+
inFlightOpsOverride?: JSONPatchOp[];
|
|
108
|
+
retiredInFlightOps?: JSONPatchOp[];
|
|
109
|
+
}): void;
|
|
66
110
|
}
|
|
67
111
|
|
|
68
112
|
export { LWWDoc };
|
package/dist/client/LWWDoc.js
CHANGED
|
@@ -6,6 +6,22 @@ class LWWDoc extends BaseDoc {
|
|
|
6
6
|
_hasPending;
|
|
7
7
|
/** Confirmed state (from algorithm pipeline), used to recompute after server changes. */
|
|
8
8
|
_baseState;
|
|
9
|
+
/**
|
|
10
|
+
* Content keys of pending local ops that have been applied to `_baseState` via the
|
|
11
|
+
* local-confirmation path (`committedAt === 0`) but not yet echoed back from the server.
|
|
12
|
+
*
|
|
13
|
+
* We key by op CONTENT (JSON.stringify) rather than by Change id because the LWW
|
|
14
|
+
* algorithm coalesces pending ops in its store and reissues a fresh sending Change
|
|
15
|
+
* (with a new id) in `getPendingToSend()`. The server then echoes that re-issued id
|
|
16
|
+
* back, so id-based echo detection would always fail. Op content (path + op + value
|
|
17
|
+
* + ts) survives the reissue intact, since the LWW algorithm preserves the original
|
|
18
|
+
* timestamped ops end-to-end.
|
|
19
|
+
*
|
|
20
|
+
* On a pure echo we skip both `_baseState += ops` (already applied locally) and
|
|
21
|
+
* `_recomputeState()` (would just produce a structurally-identical state with a
|
|
22
|
+
* fresh object identity, causing a spurious store emit mid-typing).
|
|
23
|
+
*/
|
|
24
|
+
_inFlightOpKeys = /* @__PURE__ */ new Set();
|
|
9
25
|
/**
|
|
10
26
|
* Creates an instance of LWWDoc.
|
|
11
27
|
* @param id The unique identifier for this document.
|
|
@@ -19,6 +35,7 @@ class LWWDoc extends BaseDoc {
|
|
|
19
35
|
if (snapshot?.changes && snapshot.changes.length > 0) {
|
|
20
36
|
const allOps = snapshot.changes.flatMap((c) => c.ops);
|
|
21
37
|
this.state = applyPatch(this.state, allOps, { partial: true });
|
|
38
|
+
for (const op of allOps) this._inFlightOpKeys.add(opKey(op));
|
|
22
39
|
}
|
|
23
40
|
this._baseState = this.state;
|
|
24
41
|
this._checkLoaded();
|
|
@@ -33,23 +50,43 @@ class LWWDoc extends BaseDoc {
|
|
|
33
50
|
}
|
|
34
51
|
/**
|
|
35
52
|
* Imports document state from a snapshot (e.g., for recovery when out of sync).
|
|
36
|
-
* Resets
|
|
53
|
+
* Resets `_baseState` from the snapshot but PRESERVES outstanding optimistic ops
|
|
54
|
+
* (re-applied on top of the new state, dropping any that fail).
|
|
55
|
+
*
|
|
56
|
+
* Why preserve optimistic ops: import() can be called by sync recovery /
|
|
57
|
+
* cross-tab snapshot broadcast paths while the user is mid-typing. Wiping
|
|
58
|
+
* `_optimisticOps` would silently regress the input back to the snapshot
|
|
59
|
+
* value, causing visible "text jumps" and lost characters.
|
|
60
|
+
*
|
|
61
|
+
* Stale-snapshot guard: snapshots older than the current `_committedRev`
|
|
62
|
+
* are ignored — we already know more than the caller does.
|
|
37
63
|
*/
|
|
38
64
|
import(snapshot) {
|
|
65
|
+
if (snapshot.rev < this._committedRev) return;
|
|
39
66
|
this._committedRev = snapshot.rev;
|
|
40
67
|
this._hasPending = (snapshot.changes?.length ?? 0) > 0;
|
|
41
|
-
this.
|
|
42
|
-
let
|
|
68
|
+
this._inFlightOpKeys.clear();
|
|
69
|
+
let baseState = snapshot.state;
|
|
43
70
|
if (snapshot.changes && snapshot.changes.length > 0) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
71
|
+
const allOps = snapshot.changes.flatMap((c) => c.ops);
|
|
72
|
+
baseState = applyPatch(baseState, allOps, { partial: true });
|
|
73
|
+
for (const op of allOps) this._inFlightOpKeys.add(opKey(op));
|
|
74
|
+
}
|
|
75
|
+
this._baseState = baseState;
|
|
76
|
+
let nextState = baseState;
|
|
77
|
+
if (this._optimisticOps.length > 0) {
|
|
78
|
+
const surviving = [];
|
|
79
|
+
for (const ops of this._optimisticOps) {
|
|
80
|
+
try {
|
|
81
|
+
nextState = applyPatch(nextState, ops, { strict: true });
|
|
82
|
+
surviving.push(ops);
|
|
83
|
+
} catch {
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
this._optimisticOps = surviving;
|
|
49
87
|
}
|
|
50
|
-
this._baseState = currentState;
|
|
51
88
|
this._checkLoaded();
|
|
52
|
-
this.state =
|
|
89
|
+
this.state = nextState;
|
|
53
90
|
}
|
|
54
91
|
/**
|
|
55
92
|
* Recomputes state from the base state plus remaining optimistic ops.
|
|
@@ -74,8 +111,24 @@ class LWWDoc extends BaseDoc {
|
|
|
74
111
|
* @param changes Array of changes to apply
|
|
75
112
|
* @param hasPending If provided, overrides the inferred pending state.
|
|
76
113
|
* Used by LWWAlgorithm which knows the true pending state from the store.
|
|
114
|
+
* @param options Algorithm-only escape hatches for in-flight echo tracking:
|
|
115
|
+
* - `inFlightOpsOverride`: tracks these ops in `_inFlightOpKeys` (and uses
|
|
116
|
+
* them for echo detection) on local-confirm changes, INSTEAD of `c.ops`.
|
|
117
|
+
* Required for combinable ops (`@inc`/`@bit`/`@max`/`@min`) where the
|
|
118
|
+
* local-confirm Change carries the user's raw intent op but the algorithm
|
|
119
|
+
* ships a consolidated op to the server. Without the override, the server
|
|
120
|
+
* echo of the consolidated op wouldn't match any tracked key and we'd
|
|
121
|
+
* emit a spurious recompute.
|
|
122
|
+
* - `retiredInFlightOps`: drops these keys from `_inFlightOpKeys` on the
|
|
123
|
+
* same call. Used by the algorithm to prune prior pending-op keys at
|
|
124
|
+
* paths that are about to be overwritten by `inFlightOpsOverride`,
|
|
125
|
+
* preventing unbounded orphan accumulation during fast typing into the
|
|
126
|
+
* same field.
|
|
127
|
+
*
|
|
128
|
+
* External callers (Worker-Tab sync, tests) should leave `options` undefined
|
|
129
|
+
* and the legacy `c.ops`-based tracker will run.
|
|
77
130
|
*/
|
|
78
|
-
applyChanges(changes, hasPending) {
|
|
131
|
+
applyChanges(changes, hasPending, options) {
|
|
79
132
|
if (changes.length === 0) return;
|
|
80
133
|
let lastCommittedRev = this._committedRev;
|
|
81
134
|
let hasPendingChanges = false;
|
|
@@ -91,7 +144,20 @@ class LWWDoc extends BaseDoc {
|
|
|
91
144
|
this._committedRev = lastCommittedRev;
|
|
92
145
|
this._hasPending = hasPending ?? hasPendingChanges;
|
|
93
146
|
this._checkLoaded();
|
|
147
|
+
const isPureEcho = hasServerChanges && !hasPendingChanges && changes.every((c) => c.ops.every((op) => this._inFlightOpKeys.has(opKey(op))));
|
|
148
|
+
if (options?.retiredInFlightOps) {
|
|
149
|
+
for (const op of options.retiredInFlightOps) this._inFlightOpKeys.delete(opKey(op));
|
|
150
|
+
}
|
|
151
|
+
for (const c of changes) {
|
|
152
|
+
if (c.committedAt > 0) {
|
|
153
|
+
for (const op of c.ops) this._inFlightOpKeys.delete(opKey(op));
|
|
154
|
+
} else {
|
|
155
|
+
const opsToTrack = options?.inFlightOpsOverride ?? c.ops;
|
|
156
|
+
for (const op of opsToTrack) this._inFlightOpKeys.add(opKey(op));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
94
159
|
if (hasServerChanges) {
|
|
160
|
+
if (isPureEcho) return;
|
|
95
161
|
const allOps = changes.flatMap((c) => c.ops);
|
|
96
162
|
this._baseState = applyPatch(this._baseState, allOps, { partial: true });
|
|
97
163
|
this._recomputeState();
|
|
@@ -106,6 +172,9 @@ class LWWDoc extends BaseDoc {
|
|
|
106
172
|
}
|
|
107
173
|
}
|
|
108
174
|
}
|
|
175
|
+
function opKey(op) {
|
|
176
|
+
return JSON.stringify(op);
|
|
177
|
+
}
|
|
109
178
|
export {
|
|
110
179
|
LWWDoc
|
|
111
180
|
};
|
|
@@ -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 { P as PatchesDocOptions, a as PatchesDoc } from '../BaseDoc-CXHXcW18.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/OTDoc.js
CHANGED
|
@@ -57,15 +57,36 @@ class OTDoc extends BaseDoc {
|
|
|
57
57
|
}
|
|
58
58
|
/**
|
|
59
59
|
* Imports document state from a snapshot (e.g., for recovery when out of sync).
|
|
60
|
-
* Resets state
|
|
60
|
+
* Resets committed/pending state from the snapshot but PRESERVES outstanding
|
|
61
|
+
* optimistic ops (re-applied on top of the new state, dropping any that fail).
|
|
62
|
+
*
|
|
63
|
+
* Why preserve optimistic ops: import() can be called by sync recovery /
|
|
64
|
+
* cross-tab snapshot broadcast paths while the user is mid-typing. Wiping
|
|
65
|
+
* `_optimisticOps` would silently regress the input back to the snapshot
|
|
66
|
+
* value, causing visible "text jumps" and lost characters.
|
|
67
|
+
*
|
|
68
|
+
* Stale-snapshot guard: snapshots older than the current `_committedRev`
|
|
69
|
+
* are ignored — we already know more than the caller does.
|
|
61
70
|
*/
|
|
62
71
|
import(snapshot) {
|
|
72
|
+
if (snapshot.rev < this._committedRev) return;
|
|
63
73
|
this._committedState = snapshot.state;
|
|
64
74
|
this._committedRev = snapshot.rev;
|
|
65
75
|
this._pendingChanges = snapshot.changes;
|
|
66
|
-
this._optimisticOps = [];
|
|
67
76
|
this._checkLoaded();
|
|
68
|
-
|
|
77
|
+
let newState = createStateFromSnapshot(snapshot);
|
|
78
|
+
if (this._optimisticOps.length > 0) {
|
|
79
|
+
const surviving = [];
|
|
80
|
+
for (const ops of this._optimisticOps) {
|
|
81
|
+
try {
|
|
82
|
+
newState = applyPatch(newState, ops, { strict: true });
|
|
83
|
+
surviving.push(ops);
|
|
84
|
+
} catch {
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
this._optimisticOps = surviving;
|
|
88
|
+
}
|
|
89
|
+
this.state = newState;
|
|
69
90
|
}
|
|
70
91
|
/**
|
|
71
92
|
* Recomputes state from committed + pending + remaining optimistic ops.
|
|
@@ -99,11 +120,15 @@ class OTDoc extends BaseDoc {
|
|
|
99
120
|
if (this._committedRev !== serverChanges[0].rev - 1) {
|
|
100
121
|
throw new Error("Cannot apply committed changes to a doc that is not at the correct revision");
|
|
101
122
|
}
|
|
123
|
+
const priorPendingIds = new Set(this._pendingChanges.map((c) => c.id));
|
|
124
|
+
const isPureEcho = serverChanges.length > 0 && serverChanges.every((c) => priorPendingIds.has(c.id));
|
|
102
125
|
this._committedState = applyChangesToState(this._committedState, serverChanges);
|
|
103
126
|
this._committedRev = serverChanges[serverChanges.length - 1].rev;
|
|
104
127
|
this._pendingChanges = rebasedPending;
|
|
105
128
|
this._checkLoaded();
|
|
106
|
-
|
|
129
|
+
if (!isPureEcho) {
|
|
130
|
+
this._recomputeState();
|
|
131
|
+
}
|
|
107
132
|
} else {
|
|
108
133
|
this._pendingChanges.push(...changes);
|
|
109
134
|
this._checkLoaded();
|
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 { P as PatchesDocOptions, a as PatchesDoc } from '../BaseDoc-CXHXcW18.js';
|
|
7
7
|
import { AlgorithmName } from './PatchesStore.js';
|
|
8
8
|
import '../json-patch/JSONPatch.js';
|
|
9
9
|
import '@dabble/delta';
|
|
@@ -8,7 +8,7 @@ import '../json-patch/JSONPatch.js';
|
|
|
8
8
|
import '@dabble/delta';
|
|
9
9
|
import '../json-patch/types.js';
|
|
10
10
|
import './ClientAlgorithm.js';
|
|
11
|
-
import '../BaseDoc-
|
|
11
|
+
import '../BaseDoc-CXHXcW18.js';
|
|
12
12
|
|
|
13
13
|
interface PatchesBranchClientOptions {
|
|
14
14
|
/** Algorithm to use for the branch document (defaults to the Patches instance default). */
|
|
@@ -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, a as PatchesDoc, P as PatchesDocOptions } from '../BaseDoc-CXHXcW18.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 { P as PatchesDocOptions } from '../BaseDoc-CXHXcW18.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, a as PatchesDoc, P as PatchesDocOptions } from '../BaseDoc-CXHXcW18.js';
|
|
2
2
|
export { IndexedDBFactoryOptions, MultiAlgorithmFactoryOptions, MultiAlgorithmIndexedDBFactoryOptions, PatchesFactoryOptions, createLWWIndexedDBPatches, createLWWPatches, createMultiAlgorithmExternalDBPatches, createMultiAlgorithmIndexedDBPatches, createMultiAlgorithmPatches, createOTIndexedDBPatches, createOTPatches, upgradePatchesDB } from './factories.js';
|
|
3
3
|
export { IDBStoreWrapper, IDBTransactionWrapper, IndexedDBStore } from './IndexedDBStore.js';
|
|
4
4
|
export { OTIndexedDBStore } from './OTIndexedDBStore.js';
|
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, a as PatchesDoc, P as PatchesDocOptions } from './BaseDoc-CXHXcW18.js';
|
|
3
3
|
export { IndexedDBFactoryOptions, MultiAlgorithmFactoryOptions, MultiAlgorithmIndexedDBFactoryOptions, PatchesFactoryOptions, createLWWIndexedDBPatches, createLWWPatches, createMultiAlgorithmExternalDBPatches, createMultiAlgorithmIndexedDBPatches, createMultiAlgorithmPatches, createOTIndexedDBPatches, createOTPatches, upgradePatchesDB } from './client/factories.js';
|
|
4
4
|
export { IDBStoreWrapper, IDBTransactionWrapper, IndexedDBStore } from './client/IndexedDBStore.js';
|
|
5
5
|
export { OTIndexedDBStore } from './client/OTIndexedDBStore.js';
|
|
@@ -13,7 +13,7 @@ import { WebSocketOptions } from './websocket/WebSocketTransport.js';
|
|
|
13
13
|
import '../json-patch/JSONPatch.js';
|
|
14
14
|
import '@dabble/delta';
|
|
15
15
|
import '../json-patch/types.js';
|
|
16
|
-
import '../BaseDoc-
|
|
16
|
+
import '../BaseDoc-CXHXcW18.js';
|
|
17
17
|
import '../utils/deferred.js';
|
|
18
18
|
|
|
19
19
|
interface PatchesSyncState {
|
package/dist/net/index.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ import '../algorithms/ot/shared/changeBatching.js';
|
|
|
22
22
|
import '../client/BranchClientStore.js';
|
|
23
23
|
import '../client/ClientAlgorithm.js';
|
|
24
24
|
import '../json-patch/types.js';
|
|
25
|
-
import '../BaseDoc-
|
|
25
|
+
import '../BaseDoc-CXHXcW18.js';
|
|
26
26
|
import '../client/PatchesStore.js';
|
|
27
27
|
import '../client/Patches.js';
|
|
28
28
|
import '../server/types.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ApiDefinition } from '../net/protocol/JSONRPCServer.js';
|
|
2
|
-
import { EditableBranchMetadata,
|
|
2
|
+
import { EditableBranchMetadata, CreateBranchMetadata, Branch } from '../types.js';
|
|
3
3
|
import 'easy-signal';
|
|
4
4
|
import '../net/websocket/AuthorizationProvider.js';
|
|
5
5
|
import './types.js';
|
package/dist/solid/context.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import '../types.js';
|
|
|
7
7
|
import '../json-patch/JSONPatch.js';
|
|
8
8
|
import '@dabble/delta';
|
|
9
9
|
import '../client/ClientAlgorithm.js';
|
|
10
|
-
import '../BaseDoc-
|
|
10
|
+
import '../BaseDoc-CXHXcW18.js';
|
|
11
11
|
import '../client/PatchesStore.js';
|
|
12
12
|
import '../algorithms/ot/shared/changeBatching.js';
|
|
13
13
|
import '../client/BranchClientStore.js';
|
package/dist/solid/index.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ import '../types.js';
|
|
|
11
11
|
import '../json-patch/JSONPatch.js';
|
|
12
12
|
import '@dabble/delta';
|
|
13
13
|
import '../client/ClientAlgorithm.js';
|
|
14
|
-
import '../BaseDoc-
|
|
14
|
+
import '../BaseDoc-CXHXcW18.js';
|
|
15
15
|
import '../client/PatchesStore.js';
|
|
16
16
|
import '../net/PatchesSync.js';
|
|
17
17
|
import '../algorithms/ot/shared/changeBatching.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Accessor } from 'solid-js';
|
|
2
2
|
import { OpenDocOptions } from '../client/Patches.js';
|
|
3
|
-
import {
|
|
3
|
+
import { a as PatchesDoc } from '../BaseDoc-CXHXcW18.js';
|
|
4
4
|
import { ChangeMutator } from '../types.js';
|
|
5
5
|
import 'easy-signal';
|
|
6
6
|
import '../json-patch/types.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ShallowRef, Ref,
|
|
1
|
+
import { ShallowRef, Ref, MaybeRefOrGetter, MaybeRef } from 'vue';
|
|
2
2
|
import { OpenDocOptions } from '../client/Patches.js';
|
|
3
|
-
import {
|
|
3
|
+
import { a as PatchesDoc } from '../BaseDoc-CXHXcW18.js';
|
|
4
4
|
import { ChangeMutator } from '../types.js';
|
|
5
5
|
import 'easy-signal';
|
|
6
6
|
import '../json-patch/types.js';
|
package/dist/vue/index.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ import '../types.js';
|
|
|
11
11
|
import '../json-patch/JSONPatch.js';
|
|
12
12
|
import '@dabble/delta';
|
|
13
13
|
import '../client/ClientAlgorithm.js';
|
|
14
|
-
import '../BaseDoc-
|
|
14
|
+
import '../BaseDoc-CXHXcW18.js';
|
|
15
15
|
import '../client/PatchesStore.js';
|
|
16
16
|
import '../net/PatchesSync.js';
|
|
17
17
|
import '../algorithms/ot/shared/changeBatching.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Ref, ShallowRef } from 'vue';
|
|
2
2
|
import { OpenDocOptions } from '../client/Patches.js';
|
|
3
3
|
import 'easy-signal';
|
|
4
4
|
import '../json-patch/types.js';
|
|
@@ -6,7 +6,7 @@ import '../types.js';
|
|
|
6
6
|
import '../json-patch/JSONPatch.js';
|
|
7
7
|
import '@dabble/delta';
|
|
8
8
|
import '../client/ClientAlgorithm.js';
|
|
9
|
-
import '../BaseDoc-
|
|
9
|
+
import '../BaseDoc-CXHXcW18.js';
|
|
10
10
|
import '../client/PatchesStore.js';
|
|
11
11
|
|
|
12
12
|
/**
|
package/dist/vue/provider.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import '../types.js';
|
|
|
7
7
|
import '../json-patch/JSONPatch.js';
|
|
8
8
|
import '@dabble/delta';
|
|
9
9
|
import '../client/ClientAlgorithm.js';
|
|
10
|
-
import '../BaseDoc-
|
|
10
|
+
import '../BaseDoc-CXHXcW18.js';
|
|
11
11
|
import '../client/PatchesStore.js';
|
|
12
12
|
import '../algorithms/ot/shared/changeBatching.js';
|
|
13
13
|
import '../client/BranchClientStore.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dabble/patches",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.19",
|
|
4
4
|
"description": "Immutable JSON Patch implementation based on RFC 6902 supporting operational transformation and last-writer-wins",
|
|
5
5
|
"author": "Jacob Wright <jacwright@gmail.com>",
|
|
6
6
|
"bugs": {
|