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.cjs
CHANGED
|
@@ -30,7 +30,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
-
OpId: () => OpId,
|
|
34
33
|
RepTree: () => RepTree,
|
|
35
34
|
StateVector: () => StateVector,
|
|
36
35
|
TreeState: () => TreeState,
|
|
@@ -48,54 +47,51 @@ __export(index_exports, {
|
|
|
48
47
|
module.exports = __toCommonJS(index_exports);
|
|
49
48
|
|
|
50
49
|
// src/OpId.ts
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (!(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (!(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
} else {
|
|
74
|
-
return opIdA.peerId.localeCompare(opIdB.peerId);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
static equals(opIdA, opIdB) {
|
|
78
|
-
if (opIdA === opIdB) {
|
|
79
|
-
return true;
|
|
80
|
-
} else if (!opIdA || !opIdB) {
|
|
81
|
-
return false;
|
|
82
|
-
}
|
|
83
|
-
return _OpId.compare(opIdA, opIdB) === 0;
|
|
84
|
-
}
|
|
85
|
-
static tryParseStr(opIdStr) {
|
|
86
|
-
const parts = opIdStr.split("@");
|
|
87
|
-
if (parts.length !== 2) {
|
|
88
|
-
throw new Error(`Invalid OpId string: ${opIdStr}`);
|
|
89
|
-
}
|
|
90
|
-
return new _OpId(parseInt(parts[0], 10), parts[1]);
|
|
50
|
+
function createOpId(counter, peerId) {
|
|
51
|
+
return { counter, peerId };
|
|
52
|
+
}
|
|
53
|
+
function compareOpId(opIdA, opIdB) {
|
|
54
|
+
if (typeof opIdA === "string") {
|
|
55
|
+
const parsedA = tryParseOpIdStr(opIdA);
|
|
56
|
+
if (!parsedA) throw new Error(`Invalid OpId string: ${opIdA}`);
|
|
57
|
+
opIdA = parsedA;
|
|
58
|
+
}
|
|
59
|
+
if (typeof opIdB === "string") {
|
|
60
|
+
const parsedB = tryParseOpIdStr(opIdB);
|
|
61
|
+
if (!parsedB) throw new Error(`Invalid OpId string: ${opIdB}`);
|
|
62
|
+
opIdB = parsedB;
|
|
63
|
+
}
|
|
64
|
+
const counterA = opIdA.counter;
|
|
65
|
+
const counterB = opIdB.counter;
|
|
66
|
+
if (counterA > counterB) {
|
|
67
|
+
return 1;
|
|
68
|
+
} else if (counterA < counterB) {
|
|
69
|
+
return -1;
|
|
70
|
+
} else {
|
|
71
|
+
return opIdA.peerId.localeCompare(opIdB.peerId);
|
|
91
72
|
}
|
|
92
|
-
|
|
93
|
-
|
|
73
|
+
}
|
|
74
|
+
function equalsOpId(opIdA, opIdB) {
|
|
75
|
+
if (opIdA === opIdB) {
|
|
76
|
+
return true;
|
|
77
|
+
} else if (!opIdA || !opIdB) {
|
|
78
|
+
return false;
|
|
94
79
|
}
|
|
95
|
-
|
|
96
|
-
|
|
80
|
+
return compareOpId(opIdA, opIdB) === 0;
|
|
81
|
+
}
|
|
82
|
+
function tryParseOpIdStr(opIdStr) {
|
|
83
|
+
const parts = opIdStr.split("@");
|
|
84
|
+
if (parts.length !== 2) {
|
|
85
|
+
throw new Error(`Invalid OpId string: ${opIdStr}`);
|
|
97
86
|
}
|
|
98
|
-
|
|
87
|
+
return createOpId(parseInt(parts[0], 10), parts[1]);
|
|
88
|
+
}
|
|
89
|
+
function isOpIdGreaterThan(opIdA, opIdB) {
|
|
90
|
+
return compareOpId(opIdA, opIdB) === 1;
|
|
91
|
+
}
|
|
92
|
+
function opIdToString(opId) {
|
|
93
|
+
return `${opId.counter}@${opId.peerId}`;
|
|
94
|
+
}
|
|
99
95
|
|
|
100
96
|
// src/operations.ts
|
|
101
97
|
function isMoveVertexOp(op) {
|
|
@@ -111,13 +107,13 @@ function isModifyPropertyOp(op) {
|
|
|
111
107
|
return "key" in op && "value" in op && typeof op.value === "object" && op.value !== null && "type" in op.value;
|
|
112
108
|
}
|
|
113
109
|
function newMoveVertexOp(clock, peerId, targetId, parentId) {
|
|
114
|
-
return { id:
|
|
110
|
+
return { id: createOpId(clock, peerId), targetId, parentId };
|
|
115
111
|
}
|
|
116
112
|
function newSetVertexPropertyOp(clock, peerId, targetId, key, value) {
|
|
117
|
-
return { id:
|
|
113
|
+
return { id: createOpId(clock, peerId), targetId, key, value, transient: false };
|
|
118
114
|
}
|
|
119
115
|
function newSetTransientVertexPropertyOp(clock, peerId, targetId, key, value) {
|
|
120
|
-
return { id:
|
|
116
|
+
return { id: createOpId(clock, peerId), targetId, key, value, transient: true };
|
|
121
117
|
}
|
|
122
118
|
|
|
123
119
|
// src/VertexState.ts
|
|
@@ -949,7 +945,7 @@ var _RepTree = class _RepTree {
|
|
|
949
945
|
}
|
|
950
946
|
applyOps(ops) {
|
|
951
947
|
for (const op of ops) {
|
|
952
|
-
if (this.knownOps.has(op.id
|
|
948
|
+
if (this.knownOps.has(opIdToString(op.id))) {
|
|
953
949
|
continue;
|
|
954
950
|
}
|
|
955
951
|
this.applyOperation(op);
|
|
@@ -957,16 +953,16 @@ var _RepTree = class _RepTree {
|
|
|
957
953
|
}
|
|
958
954
|
/** Applies operations in an optimized way, sorting move ops by OpId to avoid undo-do-redo cycles */
|
|
959
955
|
applyOpsOptimizedForLotsOfMoves(ops) {
|
|
960
|
-
const newMoveOps = ops.filter((op) => isMoveVertexOp(op) && !this.knownOps.has(op.id
|
|
956
|
+
const newMoveOps = ops.filter((op) => isMoveVertexOp(op) && !this.knownOps.has(opIdToString(op.id)));
|
|
961
957
|
if (newMoveOps.length > 0) {
|
|
962
958
|
const allMoveOps = [...this.moveOps, ...newMoveOps];
|
|
963
|
-
allMoveOps.sort((a, b) =>
|
|
959
|
+
allMoveOps.sort((a, b) => compareOpId(a.id, b.id));
|
|
964
960
|
for (let i = 0, len = allMoveOps.length; i < len; i++) {
|
|
965
961
|
const op = allMoveOps[i];
|
|
966
962
|
this.applyMove(op);
|
|
967
963
|
}
|
|
968
964
|
}
|
|
969
|
-
const propertyOps = ops.filter((op) => isAnyPropertyOp(op) && !this.knownOps.has(op.id
|
|
965
|
+
const propertyOps = ops.filter((op) => isAnyPropertyOp(op) && !this.knownOps.has(opIdToString(op.id)));
|
|
970
966
|
for (let i = 0, len = propertyOps.length; i < len; i++) {
|
|
971
967
|
const op = propertyOps[i];
|
|
972
968
|
this.applyProperty(op);
|
|
@@ -988,7 +984,7 @@ var _RepTree = class _RepTree {
|
|
|
988
984
|
return false;
|
|
989
985
|
}
|
|
990
986
|
for (let i = 0; i < movesA.length; i++) {
|
|
991
|
-
if (!
|
|
987
|
+
if (!equalsOpId(movesA[i].id, movesB[i].id)) {
|
|
992
988
|
return false;
|
|
993
989
|
}
|
|
994
990
|
}
|
|
@@ -1133,7 +1129,7 @@ var _RepTree = class _RepTree {
|
|
|
1133
1129
|
}
|
|
1134
1130
|
this.updateLamportClock(op);
|
|
1135
1131
|
const lastOp = this.moveOps.length > 0 ? this.moveOps[this.moveOps.length - 1] : null;
|
|
1136
|
-
if (lastOp === null || op.id
|
|
1132
|
+
if (lastOp === null || isOpIdGreaterThan(op.id, lastOp.id)) {
|
|
1137
1133
|
this.moveOps.push(op);
|
|
1138
1134
|
this.reportOpAsApplied(op);
|
|
1139
1135
|
this.tryToMove(op);
|
|
@@ -1142,7 +1138,7 @@ var _RepTree = class _RepTree {
|
|
|
1142
1138
|
for (let i = this.moveOps.length - 1; i >= 0; i--) {
|
|
1143
1139
|
const moveOp = this.moveOps[i];
|
|
1144
1140
|
targetIndex = i;
|
|
1145
|
-
if (op.id
|
|
1141
|
+
if (isOpIdGreaterThan(op.id, moveOp.id)) {
|
|
1146
1142
|
break;
|
|
1147
1143
|
} else {
|
|
1148
1144
|
this.undoMove(moveOp);
|
|
@@ -1225,17 +1221,17 @@ var _RepTree = class _RepTree {
|
|
|
1225
1221
|
const prevOpId = this.propertiesAndTheirOpIds.get(`${op.key}@${op.targetId}`);
|
|
1226
1222
|
if (!op.transient) {
|
|
1227
1223
|
this.setPropertyOps.push(op);
|
|
1228
|
-
if (!prevOpId || op.id
|
|
1224
|
+
if (!prevOpId || isOpIdGreaterThan(op.id, prevOpId)) {
|
|
1229
1225
|
this.setLLWPropertyAndItsOpId(op);
|
|
1230
1226
|
} else {
|
|
1231
|
-
this.knownOps.add(op.id
|
|
1227
|
+
this.knownOps.add(opIdToString(op.id));
|
|
1232
1228
|
}
|
|
1233
|
-
if (prevTransientOpId && op.id
|
|
1229
|
+
if (prevTransientOpId && isOpIdGreaterThan(op.id, prevTransientOpId)) {
|
|
1234
1230
|
this.transientPropertiesAndTheirOpIds.delete(`${op.key}@${op.targetId}`);
|
|
1235
1231
|
targetVertex.removeTransientProperty(op.key);
|
|
1236
1232
|
}
|
|
1237
1233
|
} else {
|
|
1238
|
-
if (!prevTransientOpId || op.id
|
|
1234
|
+
if (!prevTransientOpId || isOpIdGreaterThan(op.id, prevTransientOpId)) {
|
|
1239
1235
|
this.setTransientPropertyAndItsOpId(op);
|
|
1240
1236
|
}
|
|
1241
1237
|
}
|
|
@@ -1270,7 +1266,7 @@ var _RepTree = class _RepTree {
|
|
|
1270
1266
|
}
|
|
1271
1267
|
}
|
|
1272
1268
|
reportOpAsApplied(op) {
|
|
1273
|
-
this.knownOps.add(op.id
|
|
1269
|
+
this.knownOps.add(opIdToString(op.id));
|
|
1274
1270
|
if (this._stateVectorEnabled) {
|
|
1275
1271
|
this.stateVector.updateFromOp(op);
|
|
1276
1272
|
}
|
|
@@ -1297,7 +1293,7 @@ var _RepTree = class _RepTree {
|
|
|
1297
1293
|
undoMove(op) {
|
|
1298
1294
|
const targetVertex = this.state.getVertex(op.targetId);
|
|
1299
1295
|
if (!targetVertex) {
|
|
1300
|
-
console.error(`An attempt to undo move operation ${op.id
|
|
1296
|
+
console.error(`An attempt to undo move operation ${opIdToString(op.id)} failed because the target vertex ${op.targetId} not found`);
|
|
1301
1297
|
return;
|
|
1302
1298
|
}
|
|
1303
1299
|
const prevParentId = this.parentIdBeforeMove.get(op.id);
|
|
@@ -1340,7 +1336,7 @@ var _RepTree = class _RepTree {
|
|
|
1340
1336
|
}
|
|
1341
1337
|
}
|
|
1342
1338
|
}
|
|
1343
|
-
missingOps.sort((a, b) =>
|
|
1339
|
+
missingOps.sort((a, b) => compareOpId(a.id, b.id));
|
|
1344
1340
|
return missingOps;
|
|
1345
1341
|
}
|
|
1346
1342
|
/**
|
|
@@ -1368,7 +1364,6 @@ _RepTree.NULL_VERTEX_ID = "0";
|
|
|
1368
1364
|
var RepTree = _RepTree;
|
|
1369
1365
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1370
1366
|
0 && (module.exports = {
|
|
1371
|
-
OpId,
|
|
1372
1367
|
RepTree,
|
|
1373
1368
|
StateVector,
|
|
1374
1369
|
TreeState,
|