@yorkie-js/react 0.7.6 → 0.7.8
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/README.md +1 -1
- package/dist/yorkie-js-react.d.ts +27 -5
- package/dist/yorkie-js-react.es.js +308 -50
- package/dist/yorkie-js-react.es.js.map +1 -1
- package/dist/yorkie-js-react.js +308 -50
- package/dist/yorkie-js-react.js.map +1 -1
- package/package.json +3 -3
package/dist/yorkie-js-react.js
CHANGED
|
@@ -362,7 +362,7 @@
|
|
|
362
362
|
}
|
|
363
363
|
}
|
|
364
364
|
const IMPLICIT$3 = 2;
|
|
365
|
-
const unsafeLocal = Symbol.for("reflect unsafe local");
|
|
365
|
+
const unsafeLocal = /* @__PURE__ */ Symbol.for("reflect unsafe local");
|
|
366
366
|
function unsafeOneofCase(target, oneof) {
|
|
367
367
|
const c = target[oneof.localName].case;
|
|
368
368
|
if (c === void 0) {
|
|
@@ -588,7 +588,7 @@
|
|
|
588
588
|
}
|
|
589
589
|
return ret;
|
|
590
590
|
}
|
|
591
|
-
const tokenZeroMessageField = Symbol();
|
|
591
|
+
const tokenZeroMessageField = /* @__PURE__ */ Symbol();
|
|
592
592
|
const messagePrototypes = /* @__PURE__ */ new WeakMap();
|
|
593
593
|
function createZeroMessage(desc) {
|
|
594
594
|
let msg;
|
|
@@ -690,7 +690,7 @@
|
|
|
690
690
|
function isFieldError(arg) {
|
|
691
691
|
return arg instanceof Error && errorNames.includes(arg.name) && "field" in arg && typeof arg.field == "function";
|
|
692
692
|
}
|
|
693
|
-
const symbol = Symbol.for("@bufbuild/protobuf/text-encoding");
|
|
693
|
+
const symbol = /* @__PURE__ */ Symbol.for("@bufbuild/protobuf/text-encoding");
|
|
694
694
|
function getTextEncoding() {
|
|
695
695
|
if (globalThis[symbol] == void 0) {
|
|
696
696
|
const te = new globalThis.TextEncoder();
|
|
@@ -4058,7 +4058,7 @@
|
|
|
4058
4058
|
msg.set(field, scalarValue);
|
|
4059
4059
|
}
|
|
4060
4060
|
}
|
|
4061
|
-
const tokenIgnoredUnknownEnum = Symbol();
|
|
4061
|
+
const tokenIgnoredUnknownEnum = /* @__PURE__ */ Symbol();
|
|
4062
4062
|
function readEnum(desc, json, ignoreUnknownFields, nullAsZeroValue) {
|
|
4063
4063
|
if (json === null) {
|
|
4064
4064
|
if (desc.typeName == "google.protobuf.NullValue") {
|
|
@@ -4084,7 +4084,7 @@
|
|
|
4084
4084
|
}
|
|
4085
4085
|
throw new Error(`cannot decode ${desc} from JSON: ${formatVal(json)}`);
|
|
4086
4086
|
}
|
|
4087
|
-
const tokenNull = Symbol();
|
|
4087
|
+
const tokenNull = /* @__PURE__ */ Symbol();
|
|
4088
4088
|
function scalarFromJson(field, json, nullAsZeroValue) {
|
|
4089
4089
|
if (json === null) {
|
|
4090
4090
|
if (nullAsZeroValue) {
|
|
@@ -5905,6 +5905,8 @@
|
|
|
5905
5905
|
this.message = message;
|
|
5906
5906
|
this.toString = () => `[code=${this.code}]: ${this.message}`;
|
|
5907
5907
|
}
|
|
5908
|
+
code;
|
|
5909
|
+
message;
|
|
5908
5910
|
name = "YorkieError";
|
|
5909
5911
|
stack;
|
|
5910
5912
|
}
|
|
@@ -11134,6 +11136,32 @@
|
|
|
11134
11136
|
}
|
|
11135
11137
|
actualRight.push(child);
|
|
11136
11138
|
}
|
|
11139
|
+
if (versionVector) {
|
|
11140
|
+
const movedToLeft = [];
|
|
11141
|
+
const remaining = [];
|
|
11142
|
+
let boundaryReached = false;
|
|
11143
|
+
for (const child of actualRight) {
|
|
11144
|
+
if (!boundaryReached) {
|
|
11145
|
+
if (child.insPrevID !== void 0 && !child.isText) {
|
|
11146
|
+
remaining.push(child);
|
|
11147
|
+
continue;
|
|
11148
|
+
}
|
|
11149
|
+
const actorID = child.id.getCreatedAt().getActorID();
|
|
11150
|
+
const knownLamport = versionVector.get(actorID);
|
|
11151
|
+
if (knownLamport === void 0 || knownLamport < child.id.getCreatedAt().getLamport()) {
|
|
11152
|
+
movedToLeft.push(child);
|
|
11153
|
+
continue;
|
|
11154
|
+
}
|
|
11155
|
+
}
|
|
11156
|
+
boundaryReached = true;
|
|
11157
|
+
remaining.push(child);
|
|
11158
|
+
}
|
|
11159
|
+
if (movedToLeft.length > 0) {
|
|
11160
|
+
left.push(...movedToLeft);
|
|
11161
|
+
actualRight.length = 0;
|
|
11162
|
+
actualRight.push(...remaining);
|
|
11163
|
+
}
|
|
11164
|
+
}
|
|
11137
11165
|
this._children = left;
|
|
11138
11166
|
clone._children = actualRight;
|
|
11139
11167
|
this.visibleSize = this._children.reduce(
|
|
@@ -11910,8 +11938,14 @@
|
|
|
11910
11938
|
split.insPrevID = this.id;
|
|
11911
11939
|
if (this.insNextID) {
|
|
11912
11940
|
const insNext = tree.findFloorNode(this.insNextID);
|
|
11913
|
-
insNext.insPrevID = split.id;
|
|
11914
11941
|
split.insNextID = this.insNextID;
|
|
11942
|
+
if (insNext) {
|
|
11943
|
+
insNext.insPrevID = split.id;
|
|
11944
|
+
if (!this.isText && insNext.parent && !insNext.isRemoved && insNext.parent !== split.parent && split.allChildren.length === 0) {
|
|
11945
|
+
split.parent.detachChild(split);
|
|
11946
|
+
insNext.parent.insertBefore(split, insNext);
|
|
11947
|
+
}
|
|
11948
|
+
}
|
|
11915
11949
|
}
|
|
11916
11950
|
this.insNextID = split.id;
|
|
11917
11951
|
tree.registerNode(split);
|
|
@@ -12135,7 +12169,7 @@
|
|
|
12135
12169
|
* given node, advancing past element-type split siblings that the editing
|
|
12136
12170
|
* client did not know about (not in versionVector).
|
|
12137
12171
|
*/
|
|
12138
|
-
advancePastUnknownSplitSiblings(node, versionVector) {
|
|
12172
|
+
advancePastUnknownSplitSiblings(node, versionVector, relaxParentCheck = false, skipActorID) {
|
|
12139
12173
|
if (!versionVector || !node) {
|
|
12140
12174
|
return node;
|
|
12141
12175
|
}
|
|
@@ -12145,10 +12179,13 @@
|
|
|
12145
12179
|
if (!next || next.isText) {
|
|
12146
12180
|
break;
|
|
12147
12181
|
}
|
|
12148
|
-
if (next.parent !== current.parent) {
|
|
12182
|
+
if (!relaxParentCheck && next.parent !== current.parent) {
|
|
12149
12183
|
break;
|
|
12150
12184
|
}
|
|
12151
12185
|
const actorID = next.id.getCreatedAt().getActorID();
|
|
12186
|
+
if (skipActorID !== void 0 && actorID === skipActorID) {
|
|
12187
|
+
break;
|
|
12188
|
+
}
|
|
12152
12189
|
const knownLamport = versionVector.get(actorID);
|
|
12153
12190
|
if (knownLamport !== void 0 && knownLamport >= next.id.getCreatedAt().getLamport()) {
|
|
12154
12191
|
break;
|
|
@@ -12489,6 +12526,25 @@
|
|
|
12489
12526
|
addDataSizes(diff, diffTo, diffFrom);
|
|
12490
12527
|
const fromLeft = fromLeftRaw !== fromParent ? this.advancePastUnknownSplitSiblings(fromLeftRaw, versionVector) : fromLeftRaw;
|
|
12491
12528
|
const toLeft = toLeftRaw !== toParent ? this.advancePastUnknownSplitSiblings(toLeftRaw, versionVector) : toLeftRaw;
|
|
12529
|
+
let collectFromParent = fromParent;
|
|
12530
|
+
let collectFromLeft = fromLeft;
|
|
12531
|
+
if (fromLeft !== fromParent && fromParent !== toParent) {
|
|
12532
|
+
let current = fromLeft;
|
|
12533
|
+
while (current.insNextID) {
|
|
12534
|
+
const next = this.findFloorNode(current.insNextID);
|
|
12535
|
+
if (!next || next.isText) {
|
|
12536
|
+
break;
|
|
12537
|
+
}
|
|
12538
|
+
if (next.parent && next.parent === toParent) {
|
|
12539
|
+
if (toLeft !== toParent) {
|
|
12540
|
+
collectFromLeft = next;
|
|
12541
|
+
collectFromParent = toParent;
|
|
12542
|
+
}
|
|
12543
|
+
break;
|
|
12544
|
+
}
|
|
12545
|
+
current = next;
|
|
12546
|
+
}
|
|
12547
|
+
}
|
|
12492
12548
|
const fromIdx = this.toIndex(fromParent, fromLeft);
|
|
12493
12549
|
const fromPath = this.toPath(fromParent, fromLeft);
|
|
12494
12550
|
const nodesToBeRemoved = [];
|
|
@@ -12497,8 +12553,8 @@
|
|
|
12497
12553
|
const toBeMergedNodes = [];
|
|
12498
12554
|
const preTombstoned = /* @__PURE__ */ new Set();
|
|
12499
12555
|
this.traverseInPosRange(
|
|
12500
|
-
|
|
12501
|
-
|
|
12556
|
+
collectFromParent,
|
|
12557
|
+
collectFromLeft,
|
|
12502
12558
|
toParent,
|
|
12503
12559
|
toLeft,
|
|
12504
12560
|
([node, tokenType], ended) => {
|
|
@@ -12546,6 +12602,7 @@
|
|
|
12546
12602
|
tokensToBeRemoved,
|
|
12547
12603
|
editedAt
|
|
12548
12604
|
);
|
|
12605
|
+
const mergeLevel = toBeMergedNodes.length;
|
|
12549
12606
|
const pairs = [];
|
|
12550
12607
|
for (const node of nodesToBeRemoved) {
|
|
12551
12608
|
if (node.remove(editedAt)) {
|
|
@@ -12602,9 +12659,20 @@
|
|
|
12602
12659
|
let parent = fromParent;
|
|
12603
12660
|
let left = fromLeft;
|
|
12604
12661
|
while (splitCount < splitLevel) {
|
|
12662
|
+
if (left !== parent) {
|
|
12663
|
+
left = this.advancePastUnknownSplitSiblings(
|
|
12664
|
+
left,
|
|
12665
|
+
versionVector,
|
|
12666
|
+
true,
|
|
12667
|
+
editedAt.getActorID()
|
|
12668
|
+
);
|
|
12669
|
+
if (left.parent && left.parent !== parent) {
|
|
12670
|
+
parent = left.parent;
|
|
12671
|
+
}
|
|
12672
|
+
}
|
|
12605
12673
|
parent.split(
|
|
12606
12674
|
this,
|
|
12607
|
-
parent.findOffset(left, true) + 1,
|
|
12675
|
+
left !== parent ? parent.findOffset(left, true) + 1 : 0,
|
|
12608
12676
|
issueTimeTicket,
|
|
12609
12677
|
versionVector
|
|
12610
12678
|
);
|
|
@@ -12661,7 +12729,15 @@
|
|
|
12661
12729
|
}
|
|
12662
12730
|
}
|
|
12663
12731
|
}
|
|
12664
|
-
return [
|
|
12732
|
+
return [
|
|
12733
|
+
changes,
|
|
12734
|
+
pairs,
|
|
12735
|
+
diff,
|
|
12736
|
+
nodesToBeRemoved,
|
|
12737
|
+
fromIdx,
|
|
12738
|
+
mergeLevel,
|
|
12739
|
+
preTombstoned
|
|
12740
|
+
];
|
|
12665
12741
|
}
|
|
12666
12742
|
/**
|
|
12667
12743
|
* `editT` edits the given range with the given value.
|
|
@@ -13102,11 +13178,35 @@
|
|
|
13102
13178
|
return [prev, prev.isText ? TokenType.Text : TokenType.End];
|
|
13103
13179
|
}
|
|
13104
13180
|
}
|
|
13105
|
-
function
|
|
13106
|
-
|
|
13181
|
+
function cloneAndDropPreTombstoned(node, preTombstoned) {
|
|
13182
|
+
const clone = node.deepcopy();
|
|
13183
|
+
filterChildren(clone, preTombstoned);
|
|
13184
|
+
traverseAll(clone, (n) => {
|
|
13107
13185
|
n.removedAt = void 0;
|
|
13108
|
-
n.
|
|
13186
|
+
if (n.isText) {
|
|
13187
|
+
n.visibleSize = n.value.length;
|
|
13188
|
+
n.totalSize = n.value.length;
|
|
13189
|
+
return;
|
|
13190
|
+
}
|
|
13191
|
+
let size = 0;
|
|
13192
|
+
for (const child of n._children) size += child.paddedSize();
|
|
13193
|
+
n.visibleSize = size;
|
|
13194
|
+
n.totalSize = size;
|
|
13109
13195
|
});
|
|
13196
|
+
return clone;
|
|
13197
|
+
}
|
|
13198
|
+
function filterChildren(node, preTombstoned) {
|
|
13199
|
+
const all = node._children;
|
|
13200
|
+
if (!all) return;
|
|
13201
|
+
const kept = [];
|
|
13202
|
+
for (const child of all) {
|
|
13203
|
+
if (preTombstoned.has(child.id.toIDString())) {
|
|
13204
|
+
continue;
|
|
13205
|
+
}
|
|
13206
|
+
filterChildren(child, preTombstoned);
|
|
13207
|
+
kept.push(child);
|
|
13208
|
+
}
|
|
13209
|
+
node._children = kept;
|
|
13110
13210
|
}
|
|
13111
13211
|
class TreeEditOperation extends Operation {
|
|
13112
13212
|
fromPos;
|
|
@@ -13178,7 +13278,15 @@
|
|
|
13178
13278
|
this.toPos = tree.findPos(this.toIdx);
|
|
13179
13279
|
}
|
|
13180
13280
|
}
|
|
13181
|
-
const [
|
|
13281
|
+
const [
|
|
13282
|
+
changes,
|
|
13283
|
+
pairs,
|
|
13284
|
+
diff,
|
|
13285
|
+
removedNodes,
|
|
13286
|
+
preEditFromIdx,
|
|
13287
|
+
mergeLevel,
|
|
13288
|
+
preTombstoned
|
|
13289
|
+
] = tree.edit(
|
|
13182
13290
|
[this.fromPos, this.toPos],
|
|
13183
13291
|
this.contents?.map((content) => content.deepcopy()),
|
|
13184
13292
|
this.splitLevel,
|
|
@@ -13211,10 +13319,16 @@
|
|
|
13211
13319
|
);
|
|
13212
13320
|
this.lastToIdx = preEditFromIdx + removedSize;
|
|
13213
13321
|
let reverseOp;
|
|
13214
|
-
const
|
|
13322
|
+
const isPureSplit = this.splitLevel > 0 && !this.contents?.length && removedNodes.length === 0;
|
|
13215
13323
|
if (this.splitLevel === 0) {
|
|
13216
|
-
reverseOp = this.toReverseOperation(
|
|
13217
|
-
|
|
13324
|
+
reverseOp = this.toReverseOperation(
|
|
13325
|
+
tree,
|
|
13326
|
+
removedNodes,
|
|
13327
|
+
preEditFromIdx,
|
|
13328
|
+
preTombstoned,
|
|
13329
|
+
mergeLevel
|
|
13330
|
+
);
|
|
13331
|
+
} else if (isPureSplit) {
|
|
13218
13332
|
reverseOp = this.toSplitReverseOperation(tree, preEditFromIdx);
|
|
13219
13333
|
}
|
|
13220
13334
|
root.acc(diff);
|
|
@@ -13251,7 +13365,7 @@
|
|
|
13251
13365
|
* @param removedNodes - Nodes that were removed by this edit
|
|
13252
13366
|
* @param preEditFromIdx - The from index captured BEFORE the edit
|
|
13253
13367
|
*/
|
|
13254
|
-
toReverseOperation(tree, removedNodes, preEditFromIdx) {
|
|
13368
|
+
toReverseOperation(tree, removedNodes, preEditFromIdx, preTombstoned, mergeLevel) {
|
|
13255
13369
|
if (this.redoSplitLevel !== void 0 && this.redoSplitLevel > 0) {
|
|
13256
13370
|
const splitRedoFromPos = tree.findPos(preEditFromIdx);
|
|
13257
13371
|
const splitRedoOp = TreeEditOperation.create(
|
|
@@ -13270,19 +13384,36 @@
|
|
|
13270
13384
|
);
|
|
13271
13385
|
return splitRedoOp;
|
|
13272
13386
|
}
|
|
13387
|
+
if (mergeLevel && mergeLevel > 0) {
|
|
13388
|
+
const splitFromPos = tree.findPos(preEditFromIdx);
|
|
13389
|
+
const splitUndoOp = TreeEditOperation.create(
|
|
13390
|
+
this.getParentCreatedAt(),
|
|
13391
|
+
splitFromPos,
|
|
13392
|
+
splitFromPos,
|
|
13393
|
+
void 0,
|
|
13394
|
+
// no inserted content — split creates boundaries
|
|
13395
|
+
mergeLevel,
|
|
13396
|
+
// splitLevel = number of merged boundaries
|
|
13397
|
+
void 0,
|
|
13398
|
+
// executedAt assigned at undo time
|
|
13399
|
+
true,
|
|
13400
|
+
// isUndoOp
|
|
13401
|
+
preEditFromIdx,
|
|
13402
|
+
preEditFromIdx
|
|
13403
|
+
);
|
|
13404
|
+
return splitUndoOp;
|
|
13405
|
+
}
|
|
13273
13406
|
const insertedContentSize = this.contents ? this.contents.reduce((sum, node) => sum + node.paddedSize(), 0) : 0;
|
|
13274
13407
|
const maxNeededIdx = preEditFromIdx + insertedContentSize;
|
|
13275
13408
|
if (maxNeededIdx > tree.getSize()) {
|
|
13276
13409
|
return void 0;
|
|
13277
13410
|
}
|
|
13278
13411
|
const topLevelRemoved = removedNodes.filter(
|
|
13279
|
-
(node) => !node.parent || !removedNodes.includes(node.parent)
|
|
13412
|
+
(node) => !preTombstoned.has(node.id.toIDString()) && (!node.parent || !removedNodes.includes(node.parent))
|
|
13280
13413
|
);
|
|
13281
|
-
const reverseContents = topLevelRemoved.length > 0 ? topLevelRemoved.map(
|
|
13282
|
-
|
|
13283
|
-
|
|
13284
|
-
return clone;
|
|
13285
|
-
}) : void 0;
|
|
13414
|
+
const reverseContents = topLevelRemoved.length > 0 ? topLevelRemoved.map(
|
|
13415
|
+
(n) => cloneAndDropPreTombstoned(n, preTombstoned)
|
|
13416
|
+
) : void 0;
|
|
13286
13417
|
const reverseFromPos = tree.findPos(preEditFromIdx);
|
|
13287
13418
|
let reverseToPos;
|
|
13288
13419
|
if (insertedContentSize > 0) {
|
|
@@ -20096,6 +20227,11 @@
|
|
|
20096
20227
|
}
|
|
20097
20228
|
]);
|
|
20098
20229
|
}
|
|
20230
|
+
/**
|
|
20231
|
+
* `clearHistory` flushes both undo and redo stacks. This is used
|
|
20232
|
+
* after applying a snapshot or initialRoot so that setup operations
|
|
20233
|
+
* are not reachable via undo.
|
|
20234
|
+
*/
|
|
20099
20235
|
clearHistory() {
|
|
20100
20236
|
this.internalHistory.clearRedo();
|
|
20101
20237
|
this.internalHistory.clearUndo();
|
|
@@ -20555,10 +20691,7 @@
|
|
|
20555
20691
|
}
|
|
20556
20692
|
const ops = isUndo ? this.internalHistory.popUndo() : this.internalHistory.popRedo();
|
|
20557
20693
|
if (!ops) {
|
|
20558
|
-
|
|
20559
|
-
Code.ErrRefused,
|
|
20560
|
-
`There is no operation to be ${isUndo ? "undone" : "redone"}`
|
|
20561
|
-
);
|
|
20694
|
+
return;
|
|
20562
20695
|
}
|
|
20563
20696
|
this.ensureClone();
|
|
20564
20697
|
const ctx = ChangeContext.create(
|
|
@@ -20651,6 +20784,8 @@
|
|
|
20651
20784
|
syncMode;
|
|
20652
20785
|
changeEventReceived;
|
|
20653
20786
|
lastHeartbeatTime;
|
|
20787
|
+
pollInterval;
|
|
20788
|
+
pollIntervalPinned;
|
|
20654
20789
|
reconnectStreamDelay;
|
|
20655
20790
|
cancelled;
|
|
20656
20791
|
watchStream;
|
|
@@ -20658,13 +20793,15 @@
|
|
|
20658
20793
|
watchAbortController;
|
|
20659
20794
|
syncPromise;
|
|
20660
20795
|
_detaching = false;
|
|
20661
|
-
constructor(reconnectStreamDelay, resource, resourceID, syncMode) {
|
|
20796
|
+
constructor(reconnectStreamDelay, resource, resourceID, syncMode, pollInterval = 0, pollIntervalPinned = false) {
|
|
20662
20797
|
this.reconnectStreamDelay = reconnectStreamDelay;
|
|
20663
20798
|
this.resource = resource;
|
|
20664
20799
|
this.resourceID = resourceID;
|
|
20665
20800
|
this.syncMode = syncMode;
|
|
20666
20801
|
this.changeEventReceived = syncMode !== void 0 ? false : void 0;
|
|
20667
20802
|
this.lastHeartbeatTime = Date.now();
|
|
20803
|
+
this.pollInterval = pollInterval;
|
|
20804
|
+
this.pollIntervalPinned = pollIntervalPinned;
|
|
20668
20805
|
this.cancelled = false;
|
|
20669
20806
|
}
|
|
20670
20807
|
/**
|
|
@@ -20684,6 +20821,9 @@
|
|
|
20684
20821
|
if (this.syncMode === SyncMode.RealtimePushOnly) {
|
|
20685
20822
|
return this.resource.hasLocalChanges();
|
|
20686
20823
|
}
|
|
20824
|
+
if (this.syncMode === SyncMode.Polling) {
|
|
20825
|
+
return Date.now() - this.lastHeartbeatTime >= this.pollInterval;
|
|
20826
|
+
}
|
|
20687
20827
|
return this.syncMode !== SyncMode.Manual && (this.resource.hasLocalChanges() || (this.changeEventReceived ?? false));
|
|
20688
20828
|
}
|
|
20689
20829
|
/**
|
|
@@ -20697,7 +20837,8 @@
|
|
|
20697
20837
|
if (this.syncMode === SyncMode.Manual) {
|
|
20698
20838
|
return false;
|
|
20699
20839
|
}
|
|
20700
|
-
|
|
20840
|
+
const interval = this.pollInterval > 0 ? this.pollInterval : heartbeatInterval;
|
|
20841
|
+
return Date.now() - this.lastHeartbeatTime >= interval;
|
|
20701
20842
|
}
|
|
20702
20843
|
/**
|
|
20703
20844
|
* `updateHeartbeatTime` updates the last heartbeat time.
|
|
@@ -20776,6 +20917,16 @@
|
|
|
20776
20917
|
}
|
|
20777
20918
|
}
|
|
20778
20919
|
}
|
|
20920
|
+
/**
|
|
20921
|
+
* `resetCancelled` clears the cancelled flag so the watch loop can run again
|
|
20922
|
+
* after a previous cancellation (e.g., after changeSyncMode back to Realtime).
|
|
20923
|
+
* Caller must invoke `runWatchLoop` immediately after to claim the stream slot;
|
|
20924
|
+
* `doLoop`'s `if (this.watchStream)` guard prevents double-stream creation if a
|
|
20925
|
+
* delayed `onDisconnect` callback from the previously-cancelled stream races.
|
|
20926
|
+
*/
|
|
20927
|
+
resetCancelled() {
|
|
20928
|
+
this.cancelled = false;
|
|
20929
|
+
}
|
|
20779
20930
|
/**
|
|
20780
20931
|
* `cancelWatchStream` cancels the watch stream.
|
|
20781
20932
|
*/
|
|
@@ -20810,7 +20961,7 @@
|
|
|
20810
20961
|
};
|
|
20811
20962
|
}
|
|
20812
20963
|
const name$1 = "@yorkie-js/sdk";
|
|
20813
|
-
const version$1 = "0.7.
|
|
20964
|
+
const version$1 = "0.7.8";
|
|
20814
20965
|
const pkg$1 = {
|
|
20815
20966
|
name: name$1,
|
|
20816
20967
|
version: version$1
|
|
@@ -21093,8 +21244,10 @@
|
|
|
21093
21244
|
SyncMode2["Realtime"] = "realtime";
|
|
21094
21245
|
SyncMode2["RealtimePushOnly"] = "realtime-pushonly";
|
|
21095
21246
|
SyncMode2["RealtimeSyncOff"] = "realtime-syncoff";
|
|
21247
|
+
SyncMode2["Polling"] = "polling";
|
|
21096
21248
|
return SyncMode2;
|
|
21097
21249
|
})(SyncMode || {});
|
|
21250
|
+
const DefaultPollingIntervalMs = 3e3;
|
|
21098
21251
|
const DefaultClientOptions = {
|
|
21099
21252
|
rpcAddr: "https://api.yorkie.dev",
|
|
21100
21253
|
syncLoopDuration: 50,
|
|
@@ -21290,6 +21443,14 @@
|
|
|
21290
21443
|
doc.setActor(this.id);
|
|
21291
21444
|
doc.update((_, p) => p.set(opts.initialPresence || {}));
|
|
21292
21445
|
const syncMode = opts.syncMode ?? "realtime";
|
|
21446
|
+
if (opts.documentPollInterval !== void 0 && opts.documentPollInterval <= 0) {
|
|
21447
|
+
throw new YorkieError(
|
|
21448
|
+
Code.ErrInvalidArgument,
|
|
21449
|
+
"documentPollInterval must be greater than 0"
|
|
21450
|
+
);
|
|
21451
|
+
}
|
|
21452
|
+
const pollIntervalPinned = opts.documentPollInterval !== void 0;
|
|
21453
|
+
const pollInterval = pollIntervalPinned ? opts.documentPollInterval : syncMode === "polling" ? DefaultPollingIntervalMs : 0;
|
|
21293
21454
|
return this.enqueueTask(async () => {
|
|
21294
21455
|
try {
|
|
21295
21456
|
const res = await this.rpcClient.attachDocument(
|
|
@@ -21319,10 +21480,12 @@
|
|
|
21319
21480
|
this.reconnectStreamDelay,
|
|
21320
21481
|
doc,
|
|
21321
21482
|
res.documentId,
|
|
21322
|
-
syncMode
|
|
21483
|
+
syncMode,
|
|
21484
|
+
pollInterval,
|
|
21485
|
+
pollIntervalPinned
|
|
21323
21486
|
)
|
|
21324
21487
|
);
|
|
21325
|
-
if (syncMode !== "manual") {
|
|
21488
|
+
if (syncMode !== "manual" && syncMode !== "polling") {
|
|
21326
21489
|
await this.runWatchLoop(doc.getKey());
|
|
21327
21490
|
}
|
|
21328
21491
|
logger.info(`[AD] c:"${this.getKey()}" attaches d:"${doc.getKey()}"`);
|
|
@@ -21338,6 +21501,7 @@
|
|
|
21338
21501
|
}
|
|
21339
21502
|
});
|
|
21340
21503
|
}
|
|
21504
|
+
doc.clearHistory();
|
|
21341
21505
|
return doc;
|
|
21342
21506
|
} catch (err) {
|
|
21343
21507
|
logger.error(`[AD] c:"${this.getKey()}" err :`, err);
|
|
@@ -21448,12 +21612,23 @@
|
|
|
21448
21612
|
channel.setSessionID(res.sessionId);
|
|
21449
21613
|
channel.updateSessionCount(Number(res.sessionCount), 0);
|
|
21450
21614
|
channel.applyStatus(ChannelStatus.Attached);
|
|
21451
|
-
const syncMode = opts.
|
|
21615
|
+
const syncMode = opts.syncMode ?? "realtime";
|
|
21616
|
+
this.assertValidChannelSyncMode(syncMode);
|
|
21617
|
+
if (opts.channelHeartbeatInterval !== void 0 && opts.channelHeartbeatInterval <= 0) {
|
|
21618
|
+
throw new YorkieError(
|
|
21619
|
+
Code.ErrInvalidArgument,
|
|
21620
|
+
"channelHeartbeatInterval must be greater than 0"
|
|
21621
|
+
);
|
|
21622
|
+
}
|
|
21623
|
+
const pollIntervalPinned = opts.channelHeartbeatInterval !== void 0;
|
|
21624
|
+
const pollInterval = pollIntervalPinned ? opts.channelHeartbeatInterval : syncMode === "polling" ? DefaultPollingIntervalMs : this.channelHeartbeatInterval;
|
|
21452
21625
|
const attachment = new Attachment(
|
|
21453
21626
|
this.reconnectStreamDelay,
|
|
21454
21627
|
channel,
|
|
21455
21628
|
res.sessionId,
|
|
21456
|
-
syncMode
|
|
21629
|
+
syncMode,
|
|
21630
|
+
pollInterval,
|
|
21631
|
+
pollIntervalPinned
|
|
21457
21632
|
);
|
|
21458
21633
|
channel.subscribe("local-broadcast", (event) => {
|
|
21459
21634
|
const { topic, payload, options } = event;
|
|
@@ -21529,9 +21704,17 @@
|
|
|
21529
21704
|
return this.enqueueTask(task);
|
|
21530
21705
|
}
|
|
21531
21706
|
/**
|
|
21532
|
-
* `changeSyncMode` changes the synchronization mode of the given
|
|
21707
|
+
* `changeSyncMode` changes the synchronization mode of the given resource.
|
|
21533
21708
|
*/
|
|
21534
|
-
async changeSyncMode(
|
|
21709
|
+
async changeSyncMode(resource, syncMode) {
|
|
21710
|
+
return this.enqueueTask(async () => {
|
|
21711
|
+
if (resource instanceof Channel) {
|
|
21712
|
+
return this.changeChannelSyncMode(resource, syncMode);
|
|
21713
|
+
}
|
|
21714
|
+
return this.changeDocumentSyncMode(resource, syncMode);
|
|
21715
|
+
});
|
|
21716
|
+
}
|
|
21717
|
+
async changeDocumentSyncMode(doc, syncMode) {
|
|
21535
21718
|
if (!this.isActive()) {
|
|
21536
21719
|
throw new YorkieError(
|
|
21537
21720
|
Code.ErrClientNotActivated,
|
|
@@ -21549,19 +21732,66 @@
|
|
|
21549
21732
|
if (prevSyncMode === syncMode) {
|
|
21550
21733
|
return doc;
|
|
21551
21734
|
}
|
|
21552
|
-
|
|
21553
|
-
if (syncMode === "manual") {
|
|
21735
|
+
if (syncMode === "manual" || syncMode === "polling") {
|
|
21554
21736
|
attachment.cancelWatchStream();
|
|
21555
|
-
return doc;
|
|
21556
21737
|
}
|
|
21738
|
+
attachment.changeSyncMode(syncMode);
|
|
21557
21739
|
if (syncMode === "realtime") {
|
|
21558
21740
|
attachment.changeEventReceived = true;
|
|
21559
21741
|
}
|
|
21560
|
-
if (
|
|
21742
|
+
if (!attachment.pollIntervalPinned) {
|
|
21743
|
+
attachment.pollInterval = syncMode === "polling" ? DefaultPollingIntervalMs : 0;
|
|
21744
|
+
}
|
|
21745
|
+
if ((prevSyncMode === "manual" || prevSyncMode === "polling") && syncMode !== "manual" && syncMode !== "polling") {
|
|
21746
|
+
attachment.resetCancelled();
|
|
21561
21747
|
await this.runWatchLoop(doc.getKey());
|
|
21562
21748
|
}
|
|
21563
21749
|
return doc;
|
|
21564
21750
|
}
|
|
21751
|
+
/**
|
|
21752
|
+
* `assertValidChannelSyncMode` rejects sync modes that are not valid for
|
|
21753
|
+
* channels. `RealtimePushOnly` and `RealtimeSyncOff` are document-only.
|
|
21754
|
+
*/
|
|
21755
|
+
assertValidChannelSyncMode(syncMode) {
|
|
21756
|
+
if (syncMode !== "manual" && syncMode !== "realtime" && syncMode !== "polling") {
|
|
21757
|
+
throw new YorkieError(
|
|
21758
|
+
Code.ErrInvalidArgument,
|
|
21759
|
+
`invalid channel sync mode: ${syncMode}`
|
|
21760
|
+
);
|
|
21761
|
+
}
|
|
21762
|
+
}
|
|
21763
|
+
async changeChannelSyncMode(channel, syncMode) {
|
|
21764
|
+
if (!this.isActive()) {
|
|
21765
|
+
throw new YorkieError(
|
|
21766
|
+
Code.ErrClientNotActivated,
|
|
21767
|
+
`${this.key} is not active`
|
|
21768
|
+
);
|
|
21769
|
+
}
|
|
21770
|
+
const attachment = this.attachmentMap.get(channel.getKey());
|
|
21771
|
+
if (!attachment) {
|
|
21772
|
+
throw new YorkieError(
|
|
21773
|
+
Code.ErrNotAttached,
|
|
21774
|
+
`${channel.getKey()} is not attached`
|
|
21775
|
+
);
|
|
21776
|
+
}
|
|
21777
|
+
const prevSyncMode = attachment.syncMode;
|
|
21778
|
+
if (prevSyncMode === syncMode) {
|
|
21779
|
+
return channel;
|
|
21780
|
+
}
|
|
21781
|
+
this.assertValidChannelSyncMode(syncMode);
|
|
21782
|
+
if (prevSyncMode === "realtime") {
|
|
21783
|
+
attachment.cancelWatchStream();
|
|
21784
|
+
}
|
|
21785
|
+
attachment.changeSyncMode(syncMode);
|
|
21786
|
+
if (!attachment.pollIntervalPinned) {
|
|
21787
|
+
attachment.pollInterval = syncMode === "polling" ? DefaultPollingIntervalMs : syncMode === "realtime" ? this.channelHeartbeatInterval : 0;
|
|
21788
|
+
}
|
|
21789
|
+
if (syncMode === "realtime") {
|
|
21790
|
+
attachment.resetCancelled();
|
|
21791
|
+
await this.runWatchLoop(channel.getKey());
|
|
21792
|
+
}
|
|
21793
|
+
return channel;
|
|
21794
|
+
}
|
|
21565
21795
|
/**
|
|
21566
21796
|
* `sync` implementation that handles both Document and Channel.
|
|
21567
21797
|
*/
|
|
@@ -22406,6 +22636,7 @@
|
|
|
22406
22636
|
return doc;
|
|
22407
22637
|
}
|
|
22408
22638
|
doc.applyChangePack(respPack);
|
|
22639
|
+
attachment.updateHeartbeatTime();
|
|
22409
22640
|
attachment.resource.publish([
|
|
22410
22641
|
{
|
|
22411
22642
|
type: DocEventType.SyncStatusChanged,
|
|
@@ -22516,8 +22747,11 @@
|
|
|
22516
22747
|
function isCounter(value) {
|
|
22517
22748
|
return typeof value === "object" && value !== null && value.type === "Counter" && typeof value.value === "object";
|
|
22518
22749
|
}
|
|
22750
|
+
function isDedupCounter(value) {
|
|
22751
|
+
return typeof value === "object" && value !== null && value.type === "DedupCounter" && typeof value.value === "object" && typeof value.registers === "string";
|
|
22752
|
+
}
|
|
22519
22753
|
function isObject(value) {
|
|
22520
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) && !isText(value) && !isTree(value) && !isInt(value) && !isLong(value) && !isDate(value) && !isBinData(value) && !isCounter(value);
|
|
22754
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && !isText(value) && !isTree(value) && !isInt(value) && !isLong(value) && !isDate(value) && !isBinData(value) && !isCounter(value) && !isDedupCounter(value);
|
|
22521
22755
|
}
|
|
22522
22756
|
function parse(yson) {
|
|
22523
22757
|
try {
|
|
@@ -22533,6 +22767,12 @@
|
|
|
22533
22767
|
}
|
|
22534
22768
|
function preprocessYSON(yson) {
|
|
22535
22769
|
let result = yson;
|
|
22770
|
+
result = result.replace(
|
|
22771
|
+
/DedupCounter\(Int\((-?\d+)\),"([^"]+)"\)/g,
|
|
22772
|
+
(_, value, registers) => {
|
|
22773
|
+
return `{"__yson_type":"DedupCounter","__yson_data":{"__yson_type":"Int","__yson_data":${value}},"__yson_registers":"${registers}"}`;
|
|
22774
|
+
}
|
|
22775
|
+
);
|
|
22536
22776
|
result = result.replace(
|
|
22537
22777
|
/Counter\((Int|Long)\((-?\d+)\)\)/g,
|
|
22538
22778
|
(_, type, value) => {
|
|
@@ -22593,6 +22833,20 @@
|
|
|
22593
22833
|
value: value.__yson_data
|
|
22594
22834
|
};
|
|
22595
22835
|
}
|
|
22836
|
+
if (value.__yson_type === "DedupCounter" && typeof value.__yson_data === "object" && typeof value.__yson_registers === "string") {
|
|
22837
|
+
const counterValue = postprocessValue(value.__yson_data);
|
|
22838
|
+
if (typeof counterValue === "object" && counterValue !== null && "type" in counterValue && counterValue.type === "Int") {
|
|
22839
|
+
return {
|
|
22840
|
+
type: "DedupCounter",
|
|
22841
|
+
value: counterValue,
|
|
22842
|
+
registers: value.__yson_registers
|
|
22843
|
+
};
|
|
22844
|
+
}
|
|
22845
|
+
throw new YorkieError(
|
|
22846
|
+
Code.ErrInvalidArgument,
|
|
22847
|
+
"DedupCounter must contain Int"
|
|
22848
|
+
);
|
|
22849
|
+
}
|
|
22596
22850
|
if (value.__yson_type === "Counter" && typeof value.__yson_data === "object") {
|
|
22597
22851
|
const counterValue = postprocessValue(value.__yson_data);
|
|
22598
22852
|
if (typeof counterValue === "object" && counterValue !== null && "type" in counterValue && (counterValue.type === "Int" || counterValue.type === "Long")) {
|
|
@@ -22681,6 +22935,7 @@
|
|
|
22681
22935
|
isBinData,
|
|
22682
22936
|
isCounter,
|
|
22683
22937
|
isDate,
|
|
22938
|
+
isDedupCounter,
|
|
22684
22939
|
isInt,
|
|
22685
22940
|
isLong,
|
|
22686
22941
|
isObject,
|
|
@@ -22707,7 +22962,7 @@
|
|
|
22707
22962
|
};
|
|
22708
22963
|
}
|
|
22709
22964
|
const name = "@yorkie-js/react";
|
|
22710
|
-
const version = "0.7.
|
|
22965
|
+
const version = "0.7.8";
|
|
22711
22966
|
const pkg = {
|
|
22712
22967
|
name,
|
|
22713
22968
|
version
|
|
@@ -23163,7 +23418,7 @@
|
|
|
23163
23418
|
const ChannelContext = react.createContext(
|
|
23164
23419
|
void 0
|
|
23165
23420
|
);
|
|
23166
|
-
function useYorkieChannel(client, clientLoading, clientError, channelKey,
|
|
23421
|
+
function useYorkieChannel(client, clientLoading, clientError, channelKey, syncMode, channelStore) {
|
|
23167
23422
|
const channelRef = react.useRef(void 0);
|
|
23168
23423
|
const [didMount, setDidMount] = react.useState(false);
|
|
23169
23424
|
react.useEffect(() => {
|
|
@@ -23192,7 +23447,7 @@
|
|
|
23192
23447
|
}));
|
|
23193
23448
|
try {
|
|
23194
23449
|
const newChannel = new Channel(channelKey);
|
|
23195
|
-
await client.attach(newChannel, {
|
|
23450
|
+
await client.attach(newChannel, { syncMode });
|
|
23196
23451
|
channelRef.current = newChannel;
|
|
23197
23452
|
unsubscribe = newChannel.subscribe(() => {
|
|
23198
23453
|
channelStore.setState((state) => ({
|
|
@@ -23230,12 +23485,13 @@
|
|
|
23230
23485
|
}
|
|
23231
23486
|
detachChannel();
|
|
23232
23487
|
};
|
|
23233
|
-
}, [client, clientLoading, clientError, channelKey,
|
|
23488
|
+
}, [client, clientLoading, clientError, channelKey, syncMode, didMount]);
|
|
23234
23489
|
}
|
|
23235
23490
|
const ChannelProvider = ({
|
|
23236
23491
|
children,
|
|
23237
23492
|
channelKey,
|
|
23238
|
-
|
|
23493
|
+
syncMode,
|
|
23494
|
+
isRealtime
|
|
23239
23495
|
}) => {
|
|
23240
23496
|
const { client, loading: clientLoading, error: clientError } = useYorkie();
|
|
23241
23497
|
const channelStoreRef = react.useRef(
|
|
@@ -23250,12 +23506,13 @@
|
|
|
23250
23506
|
});
|
|
23251
23507
|
}
|
|
23252
23508
|
const channelStore = channelStoreRef.current;
|
|
23509
|
+
const resolvedSyncMode = syncMode ?? (isRealtime === false ? SyncMode.Manual : SyncMode.Realtime);
|
|
23253
23510
|
useYorkieChannel(
|
|
23254
23511
|
client,
|
|
23255
23512
|
clientLoading,
|
|
23256
23513
|
clientError,
|
|
23257
23514
|
channelKey,
|
|
23258
|
-
|
|
23515
|
+
resolvedSyncMode,
|
|
23259
23516
|
channelStore
|
|
23260
23517
|
);
|
|
23261
23518
|
return /* @__PURE__ */ jsxRuntime.jsx(ChannelContext.Provider, { value: channelStore, children });
|
|
@@ -23281,6 +23538,7 @@
|
|
|
23281
23538
|
exports2.ChannelProvider = ChannelProvider;
|
|
23282
23539
|
exports2.Counter = Counter;
|
|
23283
23540
|
exports2.DocumentProvider = DocumentProvider;
|
|
23541
|
+
exports2.SyncMode = SyncMode;
|
|
23284
23542
|
exports2.Text = Text;
|
|
23285
23543
|
exports2.Tree = Tree;
|
|
23286
23544
|
exports2.YorkieProvider = YorkieProvider;
|