@liveblocks/server 1.7.0 → 1.8.0-pre1
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 +233 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +55 -21
- package/dist/index.d.ts +55 -21
- package/dist/index.js +211 -16
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -12,7 +12,7 @@ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "
|
|
|
12
12
|
// src/decoders/ClientMsg.ts
|
|
13
13
|
import { ClientMsgCode } from "@liveblocks/core";
|
|
14
14
|
import {
|
|
15
|
-
array as
|
|
15
|
+
array as array3,
|
|
16
16
|
boolean,
|
|
17
17
|
constant as constant2,
|
|
18
18
|
jsonObject,
|
|
@@ -158,7 +158,9 @@ var jsonObjectYolo = jsonYolo.refine(
|
|
|
158
158
|
// src/decoders/Op.ts
|
|
159
159
|
import { OpCode } from "@liveblocks/core";
|
|
160
160
|
import {
|
|
161
|
+
array as array2,
|
|
161
162
|
constant,
|
|
163
|
+
either as either2,
|
|
162
164
|
number,
|
|
163
165
|
object,
|
|
164
166
|
oneOf,
|
|
@@ -166,7 +168,8 @@ import {
|
|
|
166
168
|
sized as sized2,
|
|
167
169
|
startsWith,
|
|
168
170
|
string as string2,
|
|
169
|
-
taggedUnion
|
|
171
|
+
taggedUnion,
|
|
172
|
+
tuple
|
|
170
173
|
} from "decoders";
|
|
171
174
|
var intent = oneOf(["set", "push"]);
|
|
172
175
|
var storageFileId = sized2(startsWith("fl_"), { size: 24 });
|
|
@@ -174,6 +177,9 @@ var fileSize = number.refine(
|
|
|
174
177
|
(value) => Number.isSafeInteger(value) && value >= 0,
|
|
175
178
|
"Must be a valid file size"
|
|
176
179
|
);
|
|
180
|
+
var liveTextVersion = number.reject(
|
|
181
|
+
(value) => Number.isSafeInteger(value) && value >= 0 ? null : "Must be a non-negative safe integer"
|
|
182
|
+
);
|
|
177
183
|
var updateObjectOp = object({
|
|
178
184
|
type: constant(OpCode.UPDATE_OBJECT),
|
|
179
185
|
opId: string2,
|
|
@@ -218,6 +224,41 @@ var createRegisterOp = object({
|
|
|
218
224
|
intent: optional2(intent),
|
|
219
225
|
deletedId: optional2(string2)
|
|
220
226
|
});
|
|
227
|
+
var liveTextSegment = either2(
|
|
228
|
+
tuple(string2),
|
|
229
|
+
tuple(string2, jsonObjectYolo)
|
|
230
|
+
);
|
|
231
|
+
var liveTextData = array2(liveTextSegment);
|
|
232
|
+
var textOperation = taggedUnion("type", {
|
|
233
|
+
insert: object({
|
|
234
|
+
type: constant("insert"),
|
|
235
|
+
index: number,
|
|
236
|
+
text: string2,
|
|
237
|
+
attributes: optional2(jsonObjectYolo)
|
|
238
|
+
}),
|
|
239
|
+
delete: object({
|
|
240
|
+
type: constant("delete"),
|
|
241
|
+
index: number,
|
|
242
|
+
length: number
|
|
243
|
+
}),
|
|
244
|
+
format: object({
|
|
245
|
+
type: constant("format"),
|
|
246
|
+
index: number,
|
|
247
|
+
length: number,
|
|
248
|
+
attributes: jsonObjectYolo
|
|
249
|
+
})
|
|
250
|
+
});
|
|
251
|
+
var createTextOp = object({
|
|
252
|
+
type: constant(OpCode.CREATE_TEXT),
|
|
253
|
+
opId: string2,
|
|
254
|
+
id: string2,
|
|
255
|
+
parentId: string2,
|
|
256
|
+
parentKey: string2,
|
|
257
|
+
data: liveTextData,
|
|
258
|
+
version: liveTextVersion,
|
|
259
|
+
intent: optional2(intent),
|
|
260
|
+
deletedId: optional2(string2)
|
|
261
|
+
});
|
|
221
262
|
var createFileOp = object({
|
|
222
263
|
type: constant(OpCode.CREATE_FILE),
|
|
223
264
|
opId: string2,
|
|
@@ -233,6 +274,14 @@ var createFileOp = object({
|
|
|
233
274
|
intent: optional2(intent),
|
|
234
275
|
deletedId: optional2(string2)
|
|
235
276
|
});
|
|
277
|
+
var updateTextOp = object({
|
|
278
|
+
type: constant(OpCode.UPDATE_TEXT),
|
|
279
|
+
opId: string2,
|
|
280
|
+
id: string2,
|
|
281
|
+
baseVersion: liveTextVersion,
|
|
282
|
+
version: optional2(liveTextVersion),
|
|
283
|
+
ops: array2(textOperation)
|
|
284
|
+
});
|
|
236
285
|
var deleteCrdtOp = object({
|
|
237
286
|
type: constant(OpCode.DELETE_CRDT),
|
|
238
287
|
opId: string2,
|
|
@@ -256,6 +305,8 @@ var op = taggedUnion("type", {
|
|
|
256
305
|
[OpCode.CREATE_LIST]: createListOp,
|
|
257
306
|
[OpCode.CREATE_MAP]: createMapOp,
|
|
258
307
|
[OpCode.CREATE_REGISTER]: createRegisterOp,
|
|
308
|
+
[OpCode.CREATE_TEXT]: createTextOp,
|
|
309
|
+
[OpCode.UPDATE_TEXT]: updateTextOp,
|
|
259
310
|
[OpCode.CREATE_FILE]: createFileOp,
|
|
260
311
|
[OpCode.DELETE_CRDT]: deleteCrdtOp,
|
|
261
312
|
[OpCode.SET_PARENT_KEY]: setParentKeyOp,
|
|
@@ -282,7 +333,7 @@ var fetchStorageClientMsg = object2({
|
|
|
282
333
|
});
|
|
283
334
|
var updateStorageClientMsg = object2({
|
|
284
335
|
type: constant2(ClientMsgCode.UPDATE_STORAGE),
|
|
285
|
-
ops:
|
|
336
|
+
ops: array3(op)
|
|
286
337
|
});
|
|
287
338
|
var fetchYDocClientMsg = object2({
|
|
288
339
|
type: constant2(ClientMsgCode.FETCH_YDOC),
|
|
@@ -396,6 +447,8 @@ function buildNode(snapshot2, id) {
|
|
|
396
447
|
return buildList(snapshot2, id);
|
|
397
448
|
} else if (node.type === CrdtType.MAP) {
|
|
398
449
|
return buildMap(snapshot2, id);
|
|
450
|
+
} else if (node.type === CrdtType.TEXT) {
|
|
451
|
+
return node.data;
|
|
399
452
|
} else if (node.type === CrdtType.FILE) {
|
|
400
453
|
return node.data;
|
|
401
454
|
} else {
|
|
@@ -441,6 +494,8 @@ function* emit(snapshot2, id) {
|
|
|
441
494
|
yield* emitMap(snapshot2, id);
|
|
442
495
|
} else if (node.type === CrdtType.REGISTER) {
|
|
443
496
|
yield JSON.stringify(node.data);
|
|
497
|
+
} else if (node.type === CrdtType.TEXT) {
|
|
498
|
+
yield JSON.stringify(node.data);
|
|
444
499
|
} else if (node.type === CrdtType.FILE) {
|
|
445
500
|
yield JSON.stringify(node.data);
|
|
446
501
|
}
|
|
@@ -514,6 +569,18 @@ function* iterJson(key, data, parent, state) {
|
|
|
514
569
|
case "LiveMap":
|
|
515
570
|
yield* iterMap(key, data.data, parent, state);
|
|
516
571
|
return;
|
|
572
|
+
case "LiveText":
|
|
573
|
+
yield [
|
|
574
|
+
generateId(state),
|
|
575
|
+
{
|
|
576
|
+
type: CrdtType2.TEXT,
|
|
577
|
+
data: data.data,
|
|
578
|
+
version: data.version ?? 0,
|
|
579
|
+
parentId: parent[0],
|
|
580
|
+
parentKey: key
|
|
581
|
+
}
|
|
582
|
+
];
|
|
583
|
+
return;
|
|
517
584
|
case "LiveFile":
|
|
518
585
|
yield [
|
|
519
586
|
generateId(state),
|
|
@@ -609,6 +676,11 @@ function buildNode2(snapshot2, id) {
|
|
|
609
676
|
return buildList2(snapshot2, id);
|
|
610
677
|
} else if (node.type === CrdtType2.MAP) {
|
|
611
678
|
return buildMap2(snapshot2, id);
|
|
679
|
+
} else if (node.type === CrdtType2.TEXT) {
|
|
680
|
+
return {
|
|
681
|
+
liveblocksType: "LiveText",
|
|
682
|
+
data: node.data
|
|
683
|
+
};
|
|
612
684
|
} else if (node.type === CrdtType2.FILE) {
|
|
613
685
|
return { liveblocksType: "LiveFile", data: node.data };
|
|
614
686
|
} else {
|
|
@@ -657,6 +729,11 @@ function* emit2(snapshot2, id) {
|
|
|
657
729
|
yield* emitMap2(snapshot2, id);
|
|
658
730
|
} else if (node.type === CrdtType2.REGISTER) {
|
|
659
731
|
yield JSON.stringify(node.data ?? null);
|
|
732
|
+
} else if (node.type === CrdtType2.TEXT) {
|
|
733
|
+
yield JSON.stringify({
|
|
734
|
+
liveblocksType: "LiveText",
|
|
735
|
+
data: node.data
|
|
736
|
+
});
|
|
660
737
|
} else if (node.type === CrdtType2.FILE) {
|
|
661
738
|
yield '{"liveblocksType":"LiveFile","data":';
|
|
662
739
|
yield JSON.stringify(node.data);
|
|
@@ -882,7 +959,7 @@ import {
|
|
|
882
959
|
WebsocketCloseCodes as CloseCode
|
|
883
960
|
} from "@liveblocks/core";
|
|
884
961
|
import { Mutex, tryAcquire } from "async-mutex";
|
|
885
|
-
import { array as
|
|
962
|
+
import { array as array4, formatInline } from "decoders";
|
|
886
963
|
import { chunkedByCost } from "itertools";
|
|
887
964
|
import { nanoid as nanoid2 } from "nanoid";
|
|
888
965
|
|
|
@@ -1057,7 +1134,7 @@ function buildReverseLookup(nodes) {
|
|
|
1057
1134
|
delete node.data[key];
|
|
1058
1135
|
}
|
|
1059
1136
|
}
|
|
1060
|
-
const isLeafNode = node.type === CrdtType4.REGISTER || node.type === CrdtType4.FILE;
|
|
1137
|
+
const isLeafNode = node.type === CrdtType4.REGISTER || node.type === CrdtType4.FILE || node.type === CrdtType4.TEXT;
|
|
1061
1138
|
if (!isLeafNode) {
|
|
1062
1139
|
queue.push(...revNodes.valuesAt(nodeId));
|
|
1063
1140
|
} else if (node.type === CrdtType4.REGISTER) {
|
|
@@ -1081,7 +1158,6 @@ function hasStaticDataAt(node, key) {
|
|
|
1081
1158
|
return node.type === CrdtType4.OBJECT && Object.prototype.hasOwnProperty.call(node.data, key) && node.data[key] !== void 0;
|
|
1082
1159
|
}
|
|
1083
1160
|
var InMemoryDriver = class {
|
|
1084
|
-
// Key: `${feedId}:${messageId}`
|
|
1085
1161
|
constructor(options) {
|
|
1086
1162
|
__publicField(this, "_nextActor");
|
|
1087
1163
|
__publicField(this, "_nodes");
|
|
@@ -1091,12 +1167,15 @@ var InMemoryDriver = class {
|
|
|
1091
1167
|
__publicField(this, "_leasedSessions");
|
|
1092
1168
|
__publicField(this, "_feeds");
|
|
1093
1169
|
__publicField(this, "_feedMessages");
|
|
1170
|
+
// Key: `${feedId}:${messageId}`
|
|
1171
|
+
__publicField(this, "_liveTextHistory");
|
|
1094
1172
|
this._nodes = /* @__PURE__ */ new Map();
|
|
1095
1173
|
this._metadb = /* @__PURE__ */ new Map();
|
|
1096
1174
|
this._ydb = /* @__PURE__ */ new Map();
|
|
1097
1175
|
this._leasedSessions = /* @__PURE__ */ new Map();
|
|
1098
1176
|
this._feeds = /* @__PURE__ */ new Map();
|
|
1099
1177
|
this._feedMessages = /* @__PURE__ */ new Map();
|
|
1178
|
+
this._liveTextHistory = /* @__PURE__ */ new Map();
|
|
1100
1179
|
this._nextActor = options?.initialActor ?? -1;
|
|
1101
1180
|
for (const [key, value] of options?.initialNodes ?? []) {
|
|
1102
1181
|
this._nodes.set(key, value);
|
|
@@ -1112,10 +1191,40 @@ var InMemoryDriver = class {
|
|
|
1112
1191
|
DANGEROUSLY_reset_nodes(doc) {
|
|
1113
1192
|
this.reinitialize();
|
|
1114
1193
|
this._nodes.clear();
|
|
1194
|
+
this._liveTextHistory.clear();
|
|
1115
1195
|
for (const [id, node] of plainLsonToNodeStream(doc)) {
|
|
1116
1196
|
this._nodes.set(id, node);
|
|
1117
1197
|
}
|
|
1118
1198
|
}
|
|
1199
|
+
get_live_text_history_since(nodeId, version) {
|
|
1200
|
+
return (this._liveTextHistory.get(nodeId) ?? []).filter((entry) => entry.version > version).sort((left, right) => left.version - right.version).map((entry) => ({ ...entry, ops: [...entry.ops] }));
|
|
1201
|
+
}
|
|
1202
|
+
get_live_text_history_by_op_id(nodeId, opId) {
|
|
1203
|
+
const entry = (this._liveTextHistory.get(nodeId) ?? []).find(
|
|
1204
|
+
(item) => item.opId === opId
|
|
1205
|
+
);
|
|
1206
|
+
return entry === void 0 ? void 0 : { ...entry, ops: [...entry.ops] };
|
|
1207
|
+
}
|
|
1208
|
+
append_live_text_history(entry) {
|
|
1209
|
+
const history = this._liveTextHistory.get(entry.nodeId) ?? [];
|
|
1210
|
+
history.push({ ...entry, ops: [...entry.ops] });
|
|
1211
|
+
history.sort((left, right) => left.version - right.version);
|
|
1212
|
+
this._liveTextHistory.set(entry.nodeId, history);
|
|
1213
|
+
}
|
|
1214
|
+
purge_live_text_history_before(nodeId, minVersionToKeep) {
|
|
1215
|
+
const history = this._liveTextHistory.get(nodeId);
|
|
1216
|
+
if (history === void 0) {
|
|
1217
|
+
return;
|
|
1218
|
+
}
|
|
1219
|
+
const retained = history.filter(
|
|
1220
|
+
(entry) => entry.version >= minVersionToKeep
|
|
1221
|
+
);
|
|
1222
|
+
if (retained.length === 0) {
|
|
1223
|
+
this._liveTextHistory.delete(nodeId);
|
|
1224
|
+
} else {
|
|
1225
|
+
this._liveTextHistory.set(nodeId, retained);
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1119
1228
|
get_meta(key) {
|
|
1120
1229
|
return this._metadb.get(key);
|
|
1121
1230
|
}
|
|
@@ -1391,6 +1500,7 @@ var InMemoryDriver = class {
|
|
|
1391
1500
|
}
|
|
1392
1501
|
_loadNodesApi() {
|
|
1393
1502
|
const nodes = this._nodes;
|
|
1503
|
+
const liveTextHistory = this._liveTextHistory;
|
|
1394
1504
|
if (!nodes.has("root")) {
|
|
1395
1505
|
nodes.set("root", { type: CrdtType4.OBJECT, data: {} });
|
|
1396
1506
|
}
|
|
@@ -1481,6 +1591,7 @@ var InMemoryDriver = class {
|
|
|
1481
1591
|
const currid = queue.pop();
|
|
1482
1592
|
queue.push(...revNodes.valuesAt(currid));
|
|
1483
1593
|
nodes.delete(currid);
|
|
1594
|
+
liveTextHistory.delete(currid);
|
|
1484
1595
|
revNodes.deleteAll(currid);
|
|
1485
1596
|
}
|
|
1486
1597
|
}
|
|
@@ -1600,24 +1711,27 @@ function makeNewInMemoryDriver(options) {
|
|
|
1600
1711
|
|
|
1601
1712
|
// src/Storage.ts
|
|
1602
1713
|
import {
|
|
1714
|
+
applyLiveTextOperations,
|
|
1603
1715
|
asPos as asPos2,
|
|
1604
1716
|
assertNever as assertNever2,
|
|
1605
1717
|
CrdtType as CrdtType5,
|
|
1606
1718
|
makePosition as makePosition2,
|
|
1607
|
-
OpCode as OpCode2
|
|
1719
|
+
OpCode as OpCode2,
|
|
1720
|
+
transformTextOperations
|
|
1608
1721
|
} from "@liveblocks/core";
|
|
1722
|
+
var LIVE_TEXT_HISTORY_LIMIT = 1e3;
|
|
1723
|
+
var LIVE_TEXT_HISTORY_TOO_OLD_REASON = "LiveText operation is older than retained history";
|
|
1609
1724
|
function accept(op2, fix) {
|
|
1610
1725
|
return { action: "accepted", op: op2, fix };
|
|
1611
1726
|
}
|
|
1612
1727
|
function ignore(ignoredOp) {
|
|
1613
1728
|
return { action: "ignored", ignoredOpId: ignoredOp.opId };
|
|
1614
1729
|
}
|
|
1615
|
-
function
|
|
1616
|
-
return {
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
};
|
|
1730
|
+
function reject(op2, reason) {
|
|
1731
|
+
return { action: "rejected", opIds: [op2.opId], reason };
|
|
1732
|
+
}
|
|
1733
|
+
function rectify(ackOp, fix) {
|
|
1734
|
+
return { action: "rectified", ackOp, fix };
|
|
1621
1735
|
}
|
|
1622
1736
|
function nodeFromCreateChildOp(op2) {
|
|
1623
1737
|
switch (op2.type) {
|
|
@@ -1647,6 +1761,14 @@ function nodeFromCreateChildOp(op2) {
|
|
|
1647
1761
|
parentKey: op2.parentKey,
|
|
1648
1762
|
data: op2.data
|
|
1649
1763
|
};
|
|
1764
|
+
case OpCode2.CREATE_TEXT:
|
|
1765
|
+
return {
|
|
1766
|
+
type: CrdtType5.TEXT,
|
|
1767
|
+
parentId: op2.parentId,
|
|
1768
|
+
parentKey: op2.parentKey,
|
|
1769
|
+
data: op2.data,
|
|
1770
|
+
version: op2.version
|
|
1771
|
+
};
|
|
1650
1772
|
case OpCode2.CREATE_FILE:
|
|
1651
1773
|
return {
|
|
1652
1774
|
type: CrdtType5.FILE,
|
|
@@ -1695,10 +1817,13 @@ var Storage = class {
|
|
|
1695
1817
|
case OpCode2.CREATE_MAP:
|
|
1696
1818
|
case OpCode2.CREATE_REGISTER:
|
|
1697
1819
|
case OpCode2.CREATE_OBJECT:
|
|
1820
|
+
case OpCode2.CREATE_TEXT:
|
|
1698
1821
|
case OpCode2.CREATE_FILE:
|
|
1699
1822
|
return this.applyCreateOp(op2);
|
|
1700
1823
|
case OpCode2.UPDATE_OBJECT:
|
|
1701
1824
|
return this.applyUpdateObjectOp(op2);
|
|
1825
|
+
case OpCode2.UPDATE_TEXT:
|
|
1826
|
+
return this.applyUpdateTextOp(op2);
|
|
1702
1827
|
case OpCode2.SET_PARENT_KEY:
|
|
1703
1828
|
return this.applySetParentKeyOp(op2);
|
|
1704
1829
|
case OpCode2.DELETE_OBJECT_KEY:
|
|
@@ -1719,7 +1844,14 @@ var Storage = class {
|
|
|
1719
1844
|
if (op2.intent === "push") {
|
|
1720
1845
|
const stored = this.driver.get_node(op2.id);
|
|
1721
1846
|
if (stored?.parentId !== void 0 && this.driver.get_node(stored.parentId)?.type === CrdtType5.LIST) {
|
|
1722
|
-
return rectify(
|
|
1847
|
+
return rectify(
|
|
1848
|
+
{ ...op2, parentKey: stored.parentKey },
|
|
1849
|
+
{
|
|
1850
|
+
type: OpCode2.SET_PARENT_KEY,
|
|
1851
|
+
id: op2.id,
|
|
1852
|
+
parentKey: stored.parentKey
|
|
1853
|
+
}
|
|
1854
|
+
);
|
|
1723
1855
|
}
|
|
1724
1856
|
}
|
|
1725
1857
|
return ignore(op2);
|
|
@@ -1741,6 +1873,7 @@ var Storage = class {
|
|
|
1741
1873
|
case CrdtType5.LIST:
|
|
1742
1874
|
return this.createChildAsListItem(op2, node);
|
|
1743
1875
|
case CrdtType5.REGISTER:
|
|
1876
|
+
case CrdtType5.TEXT:
|
|
1744
1877
|
case CrdtType5.FILE:
|
|
1745
1878
|
return ignore(op2);
|
|
1746
1879
|
// istanbul ignore next
|
|
@@ -1798,6 +1931,59 @@ var Storage = class {
|
|
|
1798
1931
|
this.driver.set_object_data(op2.id, op2.data, true);
|
|
1799
1932
|
return accept(op2);
|
|
1800
1933
|
}
|
|
1934
|
+
applyUpdateTextOp(op2) {
|
|
1935
|
+
const node = this.driver.get_node(op2.id);
|
|
1936
|
+
if (node?.type !== CrdtType5.TEXT) {
|
|
1937
|
+
return ignore(op2);
|
|
1938
|
+
}
|
|
1939
|
+
const duplicate = this.driver.get_live_text_history_by_op_id(
|
|
1940
|
+
op2.id,
|
|
1941
|
+
op2.opId
|
|
1942
|
+
);
|
|
1943
|
+
if (duplicate !== void 0) {
|
|
1944
|
+
return rectify({
|
|
1945
|
+
...op2,
|
|
1946
|
+
baseVersion: duplicate.baseVersion,
|
|
1947
|
+
version: duplicate.version,
|
|
1948
|
+
ops: [...duplicate.ops]
|
|
1949
|
+
});
|
|
1950
|
+
}
|
|
1951
|
+
if (op2.ops.length === 0) {
|
|
1952
|
+
return ignore(op2);
|
|
1953
|
+
}
|
|
1954
|
+
if (op2.baseVersion > node.version) {
|
|
1955
|
+
return reject(op2, "LiveText operation base version is ahead of storage");
|
|
1956
|
+
}
|
|
1957
|
+
const history = op2.baseVersion < node.version ? this.driver.get_live_text_history_since(op2.id, op2.baseVersion) : [];
|
|
1958
|
+
if (op2.baseVersion < node.version && history.length !== node.version - op2.baseVersion) {
|
|
1959
|
+
return reject(op2, LIVE_TEXT_HISTORY_TOO_OLD_REASON);
|
|
1960
|
+
}
|
|
1961
|
+
const acceptedOps = history.flatMap((entry) => entry.ops);
|
|
1962
|
+
const ops = acceptedOps.length > 0 ? transformTextOperations(op2.ops, acceptedOps, "after") : op2.ops;
|
|
1963
|
+
const version = node.version + 1;
|
|
1964
|
+
const data = applyLiveTextOperations(node.data, ops);
|
|
1965
|
+
this.driver.set_child(
|
|
1966
|
+
op2.id,
|
|
1967
|
+
{
|
|
1968
|
+
...node,
|
|
1969
|
+
data,
|
|
1970
|
+
version
|
|
1971
|
+
},
|
|
1972
|
+
true
|
|
1973
|
+
);
|
|
1974
|
+
this.driver.append_live_text_history({
|
|
1975
|
+
nodeId: op2.id,
|
|
1976
|
+
baseVersion: node.version,
|
|
1977
|
+
version,
|
|
1978
|
+
opId: op2.opId,
|
|
1979
|
+
ops: [...ops]
|
|
1980
|
+
});
|
|
1981
|
+
this.driver.purge_live_text_history_before(
|
|
1982
|
+
op2.id,
|
|
1983
|
+
Math.max(0, version - LIVE_TEXT_HISTORY_LIMIT + 1)
|
|
1984
|
+
);
|
|
1985
|
+
return accept({ ...op2, baseVersion: node.version, version, ops: [...ops] });
|
|
1986
|
+
}
|
|
1801
1987
|
applyDeleteCrdtOp(op2) {
|
|
1802
1988
|
this.driver.delete_node(op2.id);
|
|
1803
1989
|
return accept(op2);
|
|
@@ -2215,7 +2401,7 @@ function isLeasedSessionExpired(leasedSession) {
|
|
|
2215
2401
|
|
|
2216
2402
|
// src/Room.ts
|
|
2217
2403
|
var MB = 1024 * 1024;
|
|
2218
|
-
var messagesDecoder =
|
|
2404
|
+
var messagesDecoder = array4(clientMsgDecoder);
|
|
2219
2405
|
var ServerMsgCode2 = { ...CoreServerMsgCode, ...FeedMsgCode };
|
|
2220
2406
|
var HIGHEST_PROTOCOL_VERSION = Math.max(
|
|
2221
2407
|
...Object.values(ProtocolVersion).filter(
|
|
@@ -3186,9 +3372,11 @@ var Room = class {
|
|
|
3186
3372
|
case "ignored":
|
|
3187
3373
|
return r.ignoredOpId !== void 0 ? [ackIgnoredOp(r.ignoredOpId)] : [];
|
|
3188
3374
|
case "rectified":
|
|
3189
|
-
return [r.ackOp, r.fix];
|
|
3375
|
+
return r.fix !== void 0 ? [r.ackOp, r.fix] : [r.ackOp];
|
|
3190
3376
|
case "accepted":
|
|
3191
3377
|
return r.fix !== void 0 ? [r.fix] : [];
|
|
3378
|
+
case "rejected":
|
|
3379
|
+
return [];
|
|
3192
3380
|
// istanbul ignore next
|
|
3193
3381
|
default:
|
|
3194
3382
|
return assertNever3(r, "Unhandled case");
|
|
@@ -3211,6 +3399,13 @@ var Room = class {
|
|
|
3211
3399
|
ops: opsToSendBack
|
|
3212
3400
|
});
|
|
3213
3401
|
}
|
|
3402
|
+
for (const rejected of result.filter((r) => r.action === "rejected")) {
|
|
3403
|
+
replyImmediately({
|
|
3404
|
+
type: ServerMsgCode2.REJECT_STORAGE_OP,
|
|
3405
|
+
opIds: rejected.opIds,
|
|
3406
|
+
reason: rejected.reason
|
|
3407
|
+
});
|
|
3408
|
+
}
|
|
3214
3409
|
if (opsToForward.length > 0) {
|
|
3215
3410
|
const p$ = this.hooks.postClientMsgStorageDidUpdate?.(ctx, session);
|
|
3216
3411
|
if (p$) defer(p$);
|