@yorkie-js/sdk 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-sdk.d.ts +101 -13
- package/dist/yorkie-js-sdk.es.js +299 -44
- package/dist/yorkie-js-sdk.es.js.map +1 -1
- package/dist/yorkie-js-sdk.js +299 -44
- package/dist/yorkie-js-sdk.js.map +1 -1
- package/package.json +5 -5
package/dist/yorkie-js-sdk.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) {
|
|
@@ -20101,6 +20232,11 @@
|
|
|
20101
20232
|
}
|
|
20102
20233
|
]);
|
|
20103
20234
|
}
|
|
20235
|
+
/**
|
|
20236
|
+
* `clearHistory` flushes both undo and redo stacks. This is used
|
|
20237
|
+
* after applying a snapshot or initialRoot so that setup operations
|
|
20238
|
+
* are not reachable via undo.
|
|
20239
|
+
*/
|
|
20104
20240
|
clearHistory() {
|
|
20105
20241
|
this.internalHistory.clearRedo();
|
|
20106
20242
|
this.internalHistory.clearUndo();
|
|
@@ -20560,10 +20696,7 @@
|
|
|
20560
20696
|
}
|
|
20561
20697
|
const ops = isUndo ? this.internalHistory.popUndo() : this.internalHistory.popRedo();
|
|
20562
20698
|
if (!ops) {
|
|
20563
|
-
|
|
20564
|
-
Code.ErrRefused,
|
|
20565
|
-
`There is no operation to be ${isUndo ? "undone" : "redone"}`
|
|
20566
|
-
);
|
|
20699
|
+
return;
|
|
20567
20700
|
}
|
|
20568
20701
|
this.ensureClone();
|
|
20569
20702
|
const ctx = ChangeContext.create(
|
|
@@ -20656,6 +20789,8 @@
|
|
|
20656
20789
|
syncMode;
|
|
20657
20790
|
changeEventReceived;
|
|
20658
20791
|
lastHeartbeatTime;
|
|
20792
|
+
pollInterval;
|
|
20793
|
+
pollIntervalPinned;
|
|
20659
20794
|
reconnectStreamDelay;
|
|
20660
20795
|
cancelled;
|
|
20661
20796
|
watchStream;
|
|
@@ -20663,13 +20798,15 @@
|
|
|
20663
20798
|
watchAbortController;
|
|
20664
20799
|
syncPromise;
|
|
20665
20800
|
_detaching = false;
|
|
20666
|
-
constructor(reconnectStreamDelay, resource, resourceID, syncMode) {
|
|
20801
|
+
constructor(reconnectStreamDelay, resource, resourceID, syncMode, pollInterval = 0, pollIntervalPinned = false) {
|
|
20667
20802
|
this.reconnectStreamDelay = reconnectStreamDelay;
|
|
20668
20803
|
this.resource = resource;
|
|
20669
20804
|
this.resourceID = resourceID;
|
|
20670
20805
|
this.syncMode = syncMode;
|
|
20671
20806
|
this.changeEventReceived = syncMode !== void 0 ? false : void 0;
|
|
20672
20807
|
this.lastHeartbeatTime = Date.now();
|
|
20808
|
+
this.pollInterval = pollInterval;
|
|
20809
|
+
this.pollIntervalPinned = pollIntervalPinned;
|
|
20673
20810
|
this.cancelled = false;
|
|
20674
20811
|
}
|
|
20675
20812
|
/**
|
|
@@ -20689,6 +20826,9 @@
|
|
|
20689
20826
|
if (this.syncMode === SyncMode.RealtimePushOnly) {
|
|
20690
20827
|
return this.resource.hasLocalChanges();
|
|
20691
20828
|
}
|
|
20829
|
+
if (this.syncMode === SyncMode.Polling) {
|
|
20830
|
+
return Date.now() - this.lastHeartbeatTime >= this.pollInterval;
|
|
20831
|
+
}
|
|
20692
20832
|
return this.syncMode !== SyncMode.Manual && (this.resource.hasLocalChanges() || (this.changeEventReceived ?? false));
|
|
20693
20833
|
}
|
|
20694
20834
|
/**
|
|
@@ -20702,7 +20842,8 @@
|
|
|
20702
20842
|
if (this.syncMode === SyncMode.Manual) {
|
|
20703
20843
|
return false;
|
|
20704
20844
|
}
|
|
20705
|
-
|
|
20845
|
+
const interval = this.pollInterval > 0 ? this.pollInterval : heartbeatInterval;
|
|
20846
|
+
return Date.now() - this.lastHeartbeatTime >= interval;
|
|
20706
20847
|
}
|
|
20707
20848
|
/**
|
|
20708
20849
|
* `updateHeartbeatTime` updates the last heartbeat time.
|
|
@@ -20781,6 +20922,16 @@
|
|
|
20781
20922
|
}
|
|
20782
20923
|
}
|
|
20783
20924
|
}
|
|
20925
|
+
/**
|
|
20926
|
+
* `resetCancelled` clears the cancelled flag so the watch loop can run again
|
|
20927
|
+
* after a previous cancellation (e.g., after changeSyncMode back to Realtime).
|
|
20928
|
+
* Caller must invoke `runWatchLoop` immediately after to claim the stream slot;
|
|
20929
|
+
* `doLoop`'s `if (this.watchStream)` guard prevents double-stream creation if a
|
|
20930
|
+
* delayed `onDisconnect` callback from the previously-cancelled stream races.
|
|
20931
|
+
*/
|
|
20932
|
+
resetCancelled() {
|
|
20933
|
+
this.cancelled = false;
|
|
20934
|
+
}
|
|
20784
20935
|
/**
|
|
20785
20936
|
* `cancelWatchStream` cancels the watch stream.
|
|
20786
20937
|
*/
|
|
@@ -20815,7 +20966,7 @@
|
|
|
20815
20966
|
};
|
|
20816
20967
|
}
|
|
20817
20968
|
const name = "@yorkie-js/sdk";
|
|
20818
|
-
const version = "0.7.
|
|
20969
|
+
const version = "0.7.8";
|
|
20819
20970
|
const pkg = {
|
|
20820
20971
|
name,
|
|
20821
20972
|
version
|
|
@@ -21098,6 +21249,7 @@
|
|
|
21098
21249
|
SyncMode2["Realtime"] = "realtime";
|
|
21099
21250
|
SyncMode2["RealtimePushOnly"] = "realtime-pushonly";
|
|
21100
21251
|
SyncMode2["RealtimeSyncOff"] = "realtime-syncoff";
|
|
21252
|
+
SyncMode2["Polling"] = "polling";
|
|
21101
21253
|
return SyncMode2;
|
|
21102
21254
|
})(SyncMode || {});
|
|
21103
21255
|
var ClientStatus = /* @__PURE__ */ ((ClientStatus2) => {
|
|
@@ -21110,6 +21262,7 @@
|
|
|
21110
21262
|
ClientCondition2["WatchLoop"] = "WatchLoop";
|
|
21111
21263
|
return ClientCondition2;
|
|
21112
21264
|
})(ClientCondition || {});
|
|
21265
|
+
const DefaultPollingIntervalMs = 3e3;
|
|
21113
21266
|
const DefaultClientOptions = {
|
|
21114
21267
|
rpcAddr: "https://api.yorkie.dev",
|
|
21115
21268
|
syncLoopDuration: 50,
|
|
@@ -21305,6 +21458,14 @@
|
|
|
21305
21458
|
doc.setActor(this.id);
|
|
21306
21459
|
doc.update((_, p) => p.set(opts.initialPresence || {}));
|
|
21307
21460
|
const syncMode = opts.syncMode ?? "realtime";
|
|
21461
|
+
if (opts.documentPollInterval !== void 0 && opts.documentPollInterval <= 0) {
|
|
21462
|
+
throw new YorkieError(
|
|
21463
|
+
Code.ErrInvalidArgument,
|
|
21464
|
+
"documentPollInterval must be greater than 0"
|
|
21465
|
+
);
|
|
21466
|
+
}
|
|
21467
|
+
const pollIntervalPinned = opts.documentPollInterval !== void 0;
|
|
21468
|
+
const pollInterval = pollIntervalPinned ? opts.documentPollInterval : syncMode === "polling" ? DefaultPollingIntervalMs : 0;
|
|
21308
21469
|
return this.enqueueTask(async () => {
|
|
21309
21470
|
try {
|
|
21310
21471
|
const res = await this.rpcClient.attachDocument(
|
|
@@ -21334,10 +21495,12 @@
|
|
|
21334
21495
|
this.reconnectStreamDelay,
|
|
21335
21496
|
doc,
|
|
21336
21497
|
res.documentId,
|
|
21337
|
-
syncMode
|
|
21498
|
+
syncMode,
|
|
21499
|
+
pollInterval,
|
|
21500
|
+
pollIntervalPinned
|
|
21338
21501
|
)
|
|
21339
21502
|
);
|
|
21340
|
-
if (syncMode !== "manual") {
|
|
21503
|
+
if (syncMode !== "manual" && syncMode !== "polling") {
|
|
21341
21504
|
await this.runWatchLoop(doc.getKey());
|
|
21342
21505
|
}
|
|
21343
21506
|
logger.info(`[AD] c:"${this.getKey()}" attaches d:"${doc.getKey()}"`);
|
|
@@ -21353,6 +21516,7 @@
|
|
|
21353
21516
|
}
|
|
21354
21517
|
});
|
|
21355
21518
|
}
|
|
21519
|
+
doc.clearHistory();
|
|
21356
21520
|
return doc;
|
|
21357
21521
|
} catch (err) {
|
|
21358
21522
|
logger.error(`[AD] c:"${this.getKey()}" err :`, err);
|
|
@@ -21463,12 +21627,23 @@
|
|
|
21463
21627
|
channel.setSessionID(res.sessionId);
|
|
21464
21628
|
channel.updateSessionCount(Number(res.sessionCount), 0);
|
|
21465
21629
|
channel.applyStatus(ChannelStatus.Attached);
|
|
21466
|
-
const syncMode = opts.
|
|
21630
|
+
const syncMode = opts.syncMode ?? "realtime";
|
|
21631
|
+
this.assertValidChannelSyncMode(syncMode);
|
|
21632
|
+
if (opts.channelHeartbeatInterval !== void 0 && opts.channelHeartbeatInterval <= 0) {
|
|
21633
|
+
throw new YorkieError(
|
|
21634
|
+
Code.ErrInvalidArgument,
|
|
21635
|
+
"channelHeartbeatInterval must be greater than 0"
|
|
21636
|
+
);
|
|
21637
|
+
}
|
|
21638
|
+
const pollIntervalPinned = opts.channelHeartbeatInterval !== void 0;
|
|
21639
|
+
const pollInterval = pollIntervalPinned ? opts.channelHeartbeatInterval : syncMode === "polling" ? DefaultPollingIntervalMs : this.channelHeartbeatInterval;
|
|
21467
21640
|
const attachment = new Attachment(
|
|
21468
21641
|
this.reconnectStreamDelay,
|
|
21469
21642
|
channel,
|
|
21470
21643
|
res.sessionId,
|
|
21471
|
-
syncMode
|
|
21644
|
+
syncMode,
|
|
21645
|
+
pollInterval,
|
|
21646
|
+
pollIntervalPinned
|
|
21472
21647
|
);
|
|
21473
21648
|
channel.subscribe("local-broadcast", (event) => {
|
|
21474
21649
|
const { topic, payload, options } = event;
|
|
@@ -21544,9 +21719,17 @@
|
|
|
21544
21719
|
return this.enqueueTask(task);
|
|
21545
21720
|
}
|
|
21546
21721
|
/**
|
|
21547
|
-
* `changeSyncMode` changes the synchronization mode of the given
|
|
21722
|
+
* `changeSyncMode` changes the synchronization mode of the given resource.
|
|
21548
21723
|
*/
|
|
21549
|
-
async changeSyncMode(
|
|
21724
|
+
async changeSyncMode(resource, syncMode) {
|
|
21725
|
+
return this.enqueueTask(async () => {
|
|
21726
|
+
if (resource instanceof Channel) {
|
|
21727
|
+
return this.changeChannelSyncMode(resource, syncMode);
|
|
21728
|
+
}
|
|
21729
|
+
return this.changeDocumentSyncMode(resource, syncMode);
|
|
21730
|
+
});
|
|
21731
|
+
}
|
|
21732
|
+
async changeDocumentSyncMode(doc, syncMode) {
|
|
21550
21733
|
if (!this.isActive()) {
|
|
21551
21734
|
throw new YorkieError(
|
|
21552
21735
|
Code.ErrClientNotActivated,
|
|
@@ -21564,19 +21747,66 @@
|
|
|
21564
21747
|
if (prevSyncMode === syncMode) {
|
|
21565
21748
|
return doc;
|
|
21566
21749
|
}
|
|
21567
|
-
|
|
21568
|
-
if (syncMode === "manual") {
|
|
21750
|
+
if (syncMode === "manual" || syncMode === "polling") {
|
|
21569
21751
|
attachment.cancelWatchStream();
|
|
21570
|
-
return doc;
|
|
21571
21752
|
}
|
|
21753
|
+
attachment.changeSyncMode(syncMode);
|
|
21572
21754
|
if (syncMode === "realtime") {
|
|
21573
21755
|
attachment.changeEventReceived = true;
|
|
21574
21756
|
}
|
|
21575
|
-
if (
|
|
21757
|
+
if (!attachment.pollIntervalPinned) {
|
|
21758
|
+
attachment.pollInterval = syncMode === "polling" ? DefaultPollingIntervalMs : 0;
|
|
21759
|
+
}
|
|
21760
|
+
if ((prevSyncMode === "manual" || prevSyncMode === "polling") && syncMode !== "manual" && syncMode !== "polling") {
|
|
21761
|
+
attachment.resetCancelled();
|
|
21576
21762
|
await this.runWatchLoop(doc.getKey());
|
|
21577
21763
|
}
|
|
21578
21764
|
return doc;
|
|
21579
21765
|
}
|
|
21766
|
+
/**
|
|
21767
|
+
* `assertValidChannelSyncMode` rejects sync modes that are not valid for
|
|
21768
|
+
* channels. `RealtimePushOnly` and `RealtimeSyncOff` are document-only.
|
|
21769
|
+
*/
|
|
21770
|
+
assertValidChannelSyncMode(syncMode) {
|
|
21771
|
+
if (syncMode !== "manual" && syncMode !== "realtime" && syncMode !== "polling") {
|
|
21772
|
+
throw new YorkieError(
|
|
21773
|
+
Code.ErrInvalidArgument,
|
|
21774
|
+
`invalid channel sync mode: ${syncMode}`
|
|
21775
|
+
);
|
|
21776
|
+
}
|
|
21777
|
+
}
|
|
21778
|
+
async changeChannelSyncMode(channel, syncMode) {
|
|
21779
|
+
if (!this.isActive()) {
|
|
21780
|
+
throw new YorkieError(
|
|
21781
|
+
Code.ErrClientNotActivated,
|
|
21782
|
+
`${this.key} is not active`
|
|
21783
|
+
);
|
|
21784
|
+
}
|
|
21785
|
+
const attachment = this.attachmentMap.get(channel.getKey());
|
|
21786
|
+
if (!attachment) {
|
|
21787
|
+
throw new YorkieError(
|
|
21788
|
+
Code.ErrNotAttached,
|
|
21789
|
+
`${channel.getKey()} is not attached`
|
|
21790
|
+
);
|
|
21791
|
+
}
|
|
21792
|
+
const prevSyncMode = attachment.syncMode;
|
|
21793
|
+
if (prevSyncMode === syncMode) {
|
|
21794
|
+
return channel;
|
|
21795
|
+
}
|
|
21796
|
+
this.assertValidChannelSyncMode(syncMode);
|
|
21797
|
+
if (prevSyncMode === "realtime") {
|
|
21798
|
+
attachment.cancelWatchStream();
|
|
21799
|
+
}
|
|
21800
|
+
attachment.changeSyncMode(syncMode);
|
|
21801
|
+
if (!attachment.pollIntervalPinned) {
|
|
21802
|
+
attachment.pollInterval = syncMode === "polling" ? DefaultPollingIntervalMs : syncMode === "realtime" ? this.channelHeartbeatInterval : 0;
|
|
21803
|
+
}
|
|
21804
|
+
if (syncMode === "realtime") {
|
|
21805
|
+
attachment.resetCancelled();
|
|
21806
|
+
await this.runWatchLoop(channel.getKey());
|
|
21807
|
+
}
|
|
21808
|
+
return channel;
|
|
21809
|
+
}
|
|
21580
21810
|
/**
|
|
21581
21811
|
* `sync` implementation that handles both Document and Channel.
|
|
21582
21812
|
*/
|
|
@@ -22421,6 +22651,7 @@
|
|
|
22421
22651
|
return doc;
|
|
22422
22652
|
}
|
|
22423
22653
|
doc.applyChangePack(respPack);
|
|
22654
|
+
attachment.updateHeartbeatTime();
|
|
22424
22655
|
attachment.resource.publish([
|
|
22425
22656
|
{
|
|
22426
22657
|
type: DocEventType.SyncStatusChanged,
|
|
@@ -22531,8 +22762,11 @@
|
|
|
22531
22762
|
function isCounter(value) {
|
|
22532
22763
|
return typeof value === "object" && value !== null && value.type === "Counter" && typeof value.value === "object";
|
|
22533
22764
|
}
|
|
22765
|
+
function isDedupCounter(value) {
|
|
22766
|
+
return typeof value === "object" && value !== null && value.type === "DedupCounter" && typeof value.value === "object" && typeof value.registers === "string";
|
|
22767
|
+
}
|
|
22534
22768
|
function isObject(value) {
|
|
22535
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) && !isText(value) && !isTree(value) && !isInt(value) && !isLong(value) && !isDate(value) && !isBinData(value) && !isCounter(value);
|
|
22769
|
+
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);
|
|
22536
22770
|
}
|
|
22537
22771
|
function parse(yson) {
|
|
22538
22772
|
try {
|
|
@@ -22548,6 +22782,12 @@
|
|
|
22548
22782
|
}
|
|
22549
22783
|
function preprocessYSON(yson) {
|
|
22550
22784
|
let result = yson;
|
|
22785
|
+
result = result.replace(
|
|
22786
|
+
/DedupCounter\(Int\((-?\d+)\),"([^"]+)"\)/g,
|
|
22787
|
+
(_, value, registers) => {
|
|
22788
|
+
return `{"__yson_type":"DedupCounter","__yson_data":{"__yson_type":"Int","__yson_data":${value}},"__yson_registers":"${registers}"}`;
|
|
22789
|
+
}
|
|
22790
|
+
);
|
|
22551
22791
|
result = result.replace(
|
|
22552
22792
|
/Counter\((Int|Long)\((-?\d+)\)\)/g,
|
|
22553
22793
|
(_, type, value) => {
|
|
@@ -22608,6 +22848,20 @@
|
|
|
22608
22848
|
value: value.__yson_data
|
|
22609
22849
|
};
|
|
22610
22850
|
}
|
|
22851
|
+
if (value.__yson_type === "DedupCounter" && typeof value.__yson_data === "object" && typeof value.__yson_registers === "string") {
|
|
22852
|
+
const counterValue = postprocessValue(value.__yson_data);
|
|
22853
|
+
if (typeof counterValue === "object" && counterValue !== null && "type" in counterValue && counterValue.type === "Int") {
|
|
22854
|
+
return {
|
|
22855
|
+
type: "DedupCounter",
|
|
22856
|
+
value: counterValue,
|
|
22857
|
+
registers: value.__yson_registers
|
|
22858
|
+
};
|
|
22859
|
+
}
|
|
22860
|
+
throw new YorkieError(
|
|
22861
|
+
Code.ErrInvalidArgument,
|
|
22862
|
+
"DedupCounter must contain Int"
|
|
22863
|
+
);
|
|
22864
|
+
}
|
|
22611
22865
|
if (value.__yson_type === "Counter" && typeof value.__yson_data === "object") {
|
|
22612
22866
|
const counterValue = postprocessValue(value.__yson_data);
|
|
22613
22867
|
if (typeof counterValue === "object" && counterValue !== null && "type" in counterValue && (counterValue.type === "Int" || counterValue.type === "Long")) {
|
|
@@ -22696,6 +22950,7 @@
|
|
|
22696
22950
|
isBinData,
|
|
22697
22951
|
isCounter,
|
|
22698
22952
|
isDate,
|
|
22953
|
+
isDedupCounter,
|
|
22699
22954
|
isInt,
|
|
22700
22955
|
isLong,
|
|
22701
22956
|
isObject,
|