reptree 0.2.1 → 0.2.2
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/index.cjs +59 -64
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -8
- package/dist/index.d.ts +2 -8
- package/dist/index.js +59 -63
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,52 +1,49 @@
|
|
|
1
1
|
// src/OpId.ts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
if (!(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
if (!(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
} else {
|
|
25
|
-
return opIdA.peerId.localeCompare(opIdB.peerId);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
static equals(opIdA, opIdB) {
|
|
29
|
-
if (opIdA === opIdB) {
|
|
30
|
-
return true;
|
|
31
|
-
} else if (!opIdA || !opIdB) {
|
|
32
|
-
return false;
|
|
33
|
-
}
|
|
34
|
-
return _OpId.compare(opIdA, opIdB) === 0;
|
|
35
|
-
}
|
|
36
|
-
static tryParseStr(opIdStr) {
|
|
37
|
-
const parts = opIdStr.split("@");
|
|
38
|
-
if (parts.length !== 2) {
|
|
39
|
-
throw new Error(`Invalid OpId string: ${opIdStr}`);
|
|
40
|
-
}
|
|
41
|
-
return new _OpId(parseInt(parts[0], 10), parts[1]);
|
|
2
|
+
function createOpId(counter, peerId) {
|
|
3
|
+
return { counter, peerId };
|
|
4
|
+
}
|
|
5
|
+
function compareOpId(opIdA, opIdB) {
|
|
6
|
+
if (typeof opIdA === "string") {
|
|
7
|
+
const parsedA = tryParseOpIdStr(opIdA);
|
|
8
|
+
if (!parsedA) throw new Error(`Invalid OpId string: ${opIdA}`);
|
|
9
|
+
opIdA = parsedA;
|
|
10
|
+
}
|
|
11
|
+
if (typeof opIdB === "string") {
|
|
12
|
+
const parsedB = tryParseOpIdStr(opIdB);
|
|
13
|
+
if (!parsedB) throw new Error(`Invalid OpId string: ${opIdB}`);
|
|
14
|
+
opIdB = parsedB;
|
|
15
|
+
}
|
|
16
|
+
const counterA = opIdA.counter;
|
|
17
|
+
const counterB = opIdB.counter;
|
|
18
|
+
if (counterA > counterB) {
|
|
19
|
+
return 1;
|
|
20
|
+
} else if (counterA < counterB) {
|
|
21
|
+
return -1;
|
|
22
|
+
} else {
|
|
23
|
+
return opIdA.peerId.localeCompare(opIdB.peerId);
|
|
42
24
|
}
|
|
43
|
-
|
|
44
|
-
|
|
25
|
+
}
|
|
26
|
+
function equalsOpId(opIdA, opIdB) {
|
|
27
|
+
if (opIdA === opIdB) {
|
|
28
|
+
return true;
|
|
29
|
+
} else if (!opIdA || !opIdB) {
|
|
30
|
+
return false;
|
|
45
31
|
}
|
|
46
|
-
|
|
47
|
-
|
|
32
|
+
return compareOpId(opIdA, opIdB) === 0;
|
|
33
|
+
}
|
|
34
|
+
function tryParseOpIdStr(opIdStr) {
|
|
35
|
+
const parts = opIdStr.split("@");
|
|
36
|
+
if (parts.length !== 2) {
|
|
37
|
+
throw new Error(`Invalid OpId string: ${opIdStr}`);
|
|
48
38
|
}
|
|
49
|
-
|
|
39
|
+
return createOpId(parseInt(parts[0], 10), parts[1]);
|
|
40
|
+
}
|
|
41
|
+
function isOpIdGreaterThan(opIdA, opIdB) {
|
|
42
|
+
return compareOpId(opIdA, opIdB) === 1;
|
|
43
|
+
}
|
|
44
|
+
function opIdToString(opId) {
|
|
45
|
+
return `${opId.counter}@${opId.peerId}`;
|
|
46
|
+
}
|
|
50
47
|
|
|
51
48
|
// src/operations.ts
|
|
52
49
|
function isMoveVertexOp(op) {
|
|
@@ -62,13 +59,13 @@ function isModifyPropertyOp(op) {
|
|
|
62
59
|
return "key" in op && "value" in op && typeof op.value === "object" && op.value !== null && "type" in op.value;
|
|
63
60
|
}
|
|
64
61
|
function newMoveVertexOp(clock, peerId, targetId, parentId) {
|
|
65
|
-
return { id:
|
|
62
|
+
return { id: createOpId(clock, peerId), targetId, parentId };
|
|
66
63
|
}
|
|
67
64
|
function newSetVertexPropertyOp(clock, peerId, targetId, key, value) {
|
|
68
|
-
return { id:
|
|
65
|
+
return { id: createOpId(clock, peerId), targetId, key, value, transient: false };
|
|
69
66
|
}
|
|
70
67
|
function newSetTransientVertexPropertyOp(clock, peerId, targetId, key, value) {
|
|
71
|
-
return { id:
|
|
68
|
+
return { id: createOpId(clock, peerId), targetId, key, value, transient: true };
|
|
72
69
|
}
|
|
73
70
|
|
|
74
71
|
// src/VertexState.ts
|
|
@@ -900,7 +897,7 @@ var _RepTree = class _RepTree {
|
|
|
900
897
|
}
|
|
901
898
|
applyOps(ops) {
|
|
902
899
|
for (const op of ops) {
|
|
903
|
-
if (this.knownOps.has(op.id
|
|
900
|
+
if (this.knownOps.has(opIdToString(op.id))) {
|
|
904
901
|
continue;
|
|
905
902
|
}
|
|
906
903
|
this.applyOperation(op);
|
|
@@ -908,16 +905,16 @@ var _RepTree = class _RepTree {
|
|
|
908
905
|
}
|
|
909
906
|
/** Applies operations in an optimized way, sorting move ops by OpId to avoid undo-do-redo cycles */
|
|
910
907
|
applyOpsOptimizedForLotsOfMoves(ops) {
|
|
911
|
-
const newMoveOps = ops.filter((op) => isMoveVertexOp(op) && !this.knownOps.has(op.id
|
|
908
|
+
const newMoveOps = ops.filter((op) => isMoveVertexOp(op) && !this.knownOps.has(opIdToString(op.id)));
|
|
912
909
|
if (newMoveOps.length > 0) {
|
|
913
910
|
const allMoveOps = [...this.moveOps, ...newMoveOps];
|
|
914
|
-
allMoveOps.sort((a, b) =>
|
|
911
|
+
allMoveOps.sort((a, b) => compareOpId(a.id, b.id));
|
|
915
912
|
for (let i = 0, len = allMoveOps.length; i < len; i++) {
|
|
916
913
|
const op = allMoveOps[i];
|
|
917
914
|
this.applyMove(op);
|
|
918
915
|
}
|
|
919
916
|
}
|
|
920
|
-
const propertyOps = ops.filter((op) => isAnyPropertyOp(op) && !this.knownOps.has(op.id
|
|
917
|
+
const propertyOps = ops.filter((op) => isAnyPropertyOp(op) && !this.knownOps.has(opIdToString(op.id)));
|
|
921
918
|
for (let i = 0, len = propertyOps.length; i < len; i++) {
|
|
922
919
|
const op = propertyOps[i];
|
|
923
920
|
this.applyProperty(op);
|
|
@@ -939,7 +936,7 @@ var _RepTree = class _RepTree {
|
|
|
939
936
|
return false;
|
|
940
937
|
}
|
|
941
938
|
for (let i = 0; i < movesA.length; i++) {
|
|
942
|
-
if (!
|
|
939
|
+
if (!equalsOpId(movesA[i].id, movesB[i].id)) {
|
|
943
940
|
return false;
|
|
944
941
|
}
|
|
945
942
|
}
|
|
@@ -1084,7 +1081,7 @@ var _RepTree = class _RepTree {
|
|
|
1084
1081
|
}
|
|
1085
1082
|
this.updateLamportClock(op);
|
|
1086
1083
|
const lastOp = this.moveOps.length > 0 ? this.moveOps[this.moveOps.length - 1] : null;
|
|
1087
|
-
if (lastOp === null || op.id
|
|
1084
|
+
if (lastOp === null || isOpIdGreaterThan(op.id, lastOp.id)) {
|
|
1088
1085
|
this.moveOps.push(op);
|
|
1089
1086
|
this.reportOpAsApplied(op);
|
|
1090
1087
|
this.tryToMove(op);
|
|
@@ -1093,7 +1090,7 @@ var _RepTree = class _RepTree {
|
|
|
1093
1090
|
for (let i = this.moveOps.length - 1; i >= 0; i--) {
|
|
1094
1091
|
const moveOp = this.moveOps[i];
|
|
1095
1092
|
targetIndex = i;
|
|
1096
|
-
if (op.id
|
|
1093
|
+
if (isOpIdGreaterThan(op.id, moveOp.id)) {
|
|
1097
1094
|
break;
|
|
1098
1095
|
} else {
|
|
1099
1096
|
this.undoMove(moveOp);
|
|
@@ -1176,17 +1173,17 @@ var _RepTree = class _RepTree {
|
|
|
1176
1173
|
const prevOpId = this.propertiesAndTheirOpIds.get(`${op.key}@${op.targetId}`);
|
|
1177
1174
|
if (!op.transient) {
|
|
1178
1175
|
this.setPropertyOps.push(op);
|
|
1179
|
-
if (!prevOpId || op.id
|
|
1176
|
+
if (!prevOpId || isOpIdGreaterThan(op.id, prevOpId)) {
|
|
1180
1177
|
this.setLLWPropertyAndItsOpId(op);
|
|
1181
1178
|
} else {
|
|
1182
|
-
this.knownOps.add(op.id
|
|
1179
|
+
this.knownOps.add(opIdToString(op.id));
|
|
1183
1180
|
}
|
|
1184
|
-
if (prevTransientOpId && op.id
|
|
1181
|
+
if (prevTransientOpId && isOpIdGreaterThan(op.id, prevTransientOpId)) {
|
|
1185
1182
|
this.transientPropertiesAndTheirOpIds.delete(`${op.key}@${op.targetId}`);
|
|
1186
1183
|
targetVertex.removeTransientProperty(op.key);
|
|
1187
1184
|
}
|
|
1188
1185
|
} else {
|
|
1189
|
-
if (!prevTransientOpId || op.id
|
|
1186
|
+
if (!prevTransientOpId || isOpIdGreaterThan(op.id, prevTransientOpId)) {
|
|
1190
1187
|
this.setTransientPropertyAndItsOpId(op);
|
|
1191
1188
|
}
|
|
1192
1189
|
}
|
|
@@ -1221,7 +1218,7 @@ var _RepTree = class _RepTree {
|
|
|
1221
1218
|
}
|
|
1222
1219
|
}
|
|
1223
1220
|
reportOpAsApplied(op) {
|
|
1224
|
-
this.knownOps.add(op.id
|
|
1221
|
+
this.knownOps.add(opIdToString(op.id));
|
|
1225
1222
|
if (this._stateVectorEnabled) {
|
|
1226
1223
|
this.stateVector.updateFromOp(op);
|
|
1227
1224
|
}
|
|
@@ -1248,7 +1245,7 @@ var _RepTree = class _RepTree {
|
|
|
1248
1245
|
undoMove(op) {
|
|
1249
1246
|
const targetVertex = this.state.getVertex(op.targetId);
|
|
1250
1247
|
if (!targetVertex) {
|
|
1251
|
-
console.error(`An attempt to undo move operation ${op.id
|
|
1248
|
+
console.error(`An attempt to undo move operation ${opIdToString(op.id)} failed because the target vertex ${op.targetId} not found`);
|
|
1252
1249
|
return;
|
|
1253
1250
|
}
|
|
1254
1251
|
const prevParentId = this.parentIdBeforeMove.get(op.id);
|
|
@@ -1291,7 +1288,7 @@ var _RepTree = class _RepTree {
|
|
|
1291
1288
|
}
|
|
1292
1289
|
}
|
|
1293
1290
|
}
|
|
1294
|
-
missingOps.sort((a, b) =>
|
|
1291
|
+
missingOps.sort((a, b) => compareOpId(a.id, b.id));
|
|
1295
1292
|
return missingOps;
|
|
1296
1293
|
}
|
|
1297
1294
|
/**
|
|
@@ -1318,7 +1315,6 @@ var _RepTree = class _RepTree {
|
|
|
1318
1315
|
_RepTree.NULL_VERTEX_ID = "0";
|
|
1319
1316
|
var RepTree = _RepTree;
|
|
1320
1317
|
export {
|
|
1321
|
-
OpId,
|
|
1322
1318
|
RepTree,
|
|
1323
1319
|
StateVector,
|
|
1324
1320
|
TreeState,
|