@liveblocks/core 3.14.0-pre3 → 3.14.0-pre5
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 +329 -197
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -6
- package/dist/index.d.ts +25 -6
- package/dist/index.js +269 -137
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ var __export = (target, all) => {
|
|
|
6
6
|
|
|
7
7
|
// src/version.ts
|
|
8
8
|
var PKG_NAME = "@liveblocks/core";
|
|
9
|
-
var PKG_VERSION = "3.14.0-
|
|
9
|
+
var PKG_VERSION = "3.14.0-pre5";
|
|
10
10
|
var PKG_FORMAT = "esm";
|
|
11
11
|
|
|
12
12
|
// src/dupe-detection.ts
|
|
@@ -567,6 +567,9 @@ var SortedList = class _SortedList {
|
|
|
567
567
|
this.#lt = lt;
|
|
568
568
|
this.#data = alreadySortedList;
|
|
569
569
|
}
|
|
570
|
+
/**
|
|
571
|
+
* Creates an empty SortedList with the given "less than" function.
|
|
572
|
+
*/
|
|
570
573
|
static with(lt) {
|
|
571
574
|
return _SortedList.fromAlreadySorted([], lt);
|
|
572
575
|
}
|
|
@@ -588,10 +591,12 @@ var SortedList = class _SortedList {
|
|
|
588
591
|
}
|
|
589
592
|
/**
|
|
590
593
|
* Adds a new item to the sorted list, such that it remains sorted.
|
|
594
|
+
* Returns the index where the item was inserted.
|
|
591
595
|
*/
|
|
592
596
|
add(value) {
|
|
593
597
|
const idx = bisectRight(this.#data, value, this.#lt);
|
|
594
598
|
this.#data.splice(idx, 0, value);
|
|
599
|
+
return idx;
|
|
595
600
|
}
|
|
596
601
|
/**
|
|
597
602
|
* Removes all values from the sorted list, making it empty again.
|
|
@@ -636,6 +641,60 @@ var SortedList = class _SortedList {
|
|
|
636
641
|
}
|
|
637
642
|
return false;
|
|
638
643
|
}
|
|
644
|
+
/**
|
|
645
|
+
* Removes the item at the given index.
|
|
646
|
+
* Returns the removed item, or undefined if index is out of bounds.
|
|
647
|
+
*/
|
|
648
|
+
removeAt(index) {
|
|
649
|
+
if (index < 0 || index >= this.#data.length) {
|
|
650
|
+
return void 0;
|
|
651
|
+
}
|
|
652
|
+
const [removed] = this.#data.splice(index, 1);
|
|
653
|
+
return removed;
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Repositions an item to maintain sorted order after its sort key has
|
|
657
|
+
* been mutated in-place. For example:
|
|
658
|
+
*
|
|
659
|
+
* const item = sorted.at(3);
|
|
660
|
+
* item.updatedAt = new Date(); // mutate the item's sort key in-place
|
|
661
|
+
* sorted.reposition(item); // restore sorted order
|
|
662
|
+
*
|
|
663
|
+
* Returns the new index of the item. Throws if the item is not in the list.
|
|
664
|
+
*
|
|
665
|
+
* Semantically equivalent to remove(value) + add(value), but optimized
|
|
666
|
+
* to avoid array shifting when the item only moves a short distance.
|
|
667
|
+
*/
|
|
668
|
+
reposition(value) {
|
|
669
|
+
const oldIdx = this.#data.indexOf(value);
|
|
670
|
+
if (oldIdx < 0) {
|
|
671
|
+
throw new Error("Cannot reposition item that is not in the list");
|
|
672
|
+
}
|
|
673
|
+
const prev = this.#data[oldIdx - 1];
|
|
674
|
+
const next = this.#data[oldIdx + 1];
|
|
675
|
+
const validLeft = prev === void 0 || this.#lt(prev, value);
|
|
676
|
+
const validRight = next === void 0 || this.#lt(value, next);
|
|
677
|
+
if (validLeft && validRight) {
|
|
678
|
+
return oldIdx;
|
|
679
|
+
}
|
|
680
|
+
let newIdx = oldIdx;
|
|
681
|
+
while (newIdx > 0 && this.#lt(value, this.#data[newIdx - 1])) {
|
|
682
|
+
this.#data[newIdx] = this.#data[newIdx - 1];
|
|
683
|
+
newIdx--;
|
|
684
|
+
}
|
|
685
|
+
if (newIdx < oldIdx) {
|
|
686
|
+
this.#data[newIdx] = value;
|
|
687
|
+
return newIdx;
|
|
688
|
+
}
|
|
689
|
+
while (newIdx < this.#data.length - 1 && !this.#lt(value, this.#data[newIdx + 1])) {
|
|
690
|
+
this.#data[newIdx] = this.#data[newIdx + 1];
|
|
691
|
+
newIdx++;
|
|
692
|
+
}
|
|
693
|
+
if (newIdx !== oldIdx) {
|
|
694
|
+
this.#data[newIdx] = value;
|
|
695
|
+
}
|
|
696
|
+
return newIdx;
|
|
697
|
+
}
|
|
639
698
|
at(index) {
|
|
640
699
|
return this.#data[index];
|
|
641
700
|
}
|
|
@@ -5898,16 +5957,68 @@ function before(pos) {
|
|
|
5898
5957
|
}
|
|
5899
5958
|
return ONE;
|
|
5900
5959
|
}
|
|
5960
|
+
var VIEWPORT_START = 2;
|
|
5961
|
+
var VIEWPORT_STEP = 3;
|
|
5901
5962
|
function after(pos) {
|
|
5902
|
-
for (let i = 0; i
|
|
5963
|
+
for (let i = 0; i < pos.length; i++) {
|
|
5903
5964
|
const code = pos.charCodeAt(i);
|
|
5904
|
-
if (code
|
|
5905
|
-
|
|
5965
|
+
if (code < MIN_CODE || code > MAX_CODE) {
|
|
5966
|
+
return pos + ONE;
|
|
5906
5967
|
}
|
|
5907
|
-
|
|
5968
|
+
}
|
|
5969
|
+
while (pos.length > 1 && pos.charCodeAt(pos.length - 1) === MIN_CODE) {
|
|
5970
|
+
pos = pos.slice(0, -1);
|
|
5971
|
+
}
|
|
5972
|
+
if (pos.length === 0 || pos === ZERO) {
|
|
5973
|
+
return ONE;
|
|
5974
|
+
}
|
|
5975
|
+
let viewport = VIEWPORT_START;
|
|
5976
|
+
if (pos.length > VIEWPORT_START) {
|
|
5977
|
+
viewport = VIEWPORT_START + Math.ceil((pos.length - VIEWPORT_START) / VIEWPORT_STEP) * VIEWPORT_STEP;
|
|
5978
|
+
}
|
|
5979
|
+
const result = incrementWithinViewport(pos, viewport);
|
|
5980
|
+
if (result !== null) {
|
|
5981
|
+
return result;
|
|
5982
|
+
}
|
|
5983
|
+
viewport += VIEWPORT_STEP;
|
|
5984
|
+
const extendedResult = incrementWithinViewport(pos, viewport);
|
|
5985
|
+
if (extendedResult !== null) {
|
|
5986
|
+
return extendedResult;
|
|
5908
5987
|
}
|
|
5909
5988
|
return pos + ONE;
|
|
5910
5989
|
}
|
|
5990
|
+
function incrementWithinViewport(pos, viewport) {
|
|
5991
|
+
const digits = [];
|
|
5992
|
+
for (let i = 0; i < viewport; i++) {
|
|
5993
|
+
if (i < pos.length) {
|
|
5994
|
+
digits.push(pos.charCodeAt(i) - MIN_CODE);
|
|
5995
|
+
} else {
|
|
5996
|
+
digits.push(0);
|
|
5997
|
+
}
|
|
5998
|
+
}
|
|
5999
|
+
let carry = 1;
|
|
6000
|
+
for (let i = viewport - 1; i >= 0 && carry; i--) {
|
|
6001
|
+
const sum = digits[i] + carry;
|
|
6002
|
+
if (sum >= NUM_DIGITS) {
|
|
6003
|
+
digits[i] = 0;
|
|
6004
|
+
carry = 1;
|
|
6005
|
+
} else {
|
|
6006
|
+
digits[i] = sum;
|
|
6007
|
+
carry = 0;
|
|
6008
|
+
}
|
|
6009
|
+
}
|
|
6010
|
+
if (carry) {
|
|
6011
|
+
return null;
|
|
6012
|
+
}
|
|
6013
|
+
let result = "";
|
|
6014
|
+
for (const d of digits) {
|
|
6015
|
+
result += String.fromCharCode(d + MIN_CODE);
|
|
6016
|
+
}
|
|
6017
|
+
while (result.length > 1 && result.charCodeAt(result.length - 1) === MIN_CODE) {
|
|
6018
|
+
result = result.slice(0, -1);
|
|
6019
|
+
}
|
|
6020
|
+
return result;
|
|
6021
|
+
}
|
|
5911
6022
|
function between(lo, hi) {
|
|
5912
6023
|
if (lo < hi) {
|
|
5913
6024
|
return _between(lo, hi);
|
|
@@ -6368,29 +6479,27 @@ var LiveRegister = class _LiveRegister extends AbstractCrdt {
|
|
|
6368
6479
|
};
|
|
6369
6480
|
|
|
6370
6481
|
// src/crdts/LiveList.ts
|
|
6371
|
-
function
|
|
6372
|
-
|
|
6373
|
-
const posB = itemB._parentPos;
|
|
6374
|
-
return posA === posB ? 0 : posA < posB ? -1 : 1;
|
|
6482
|
+
function childNodeLt(a, b) {
|
|
6483
|
+
return a._parentPos < b._parentPos;
|
|
6375
6484
|
}
|
|
6376
6485
|
var LiveList = class _LiveList extends AbstractCrdt {
|
|
6377
|
-
// TODO: Naive array at first, find a better data structure. Maybe an Order statistics tree?
|
|
6378
6486
|
#items;
|
|
6379
6487
|
#implicitlyDeletedItems;
|
|
6380
6488
|
#unacknowledgedSets;
|
|
6381
6489
|
constructor(items) {
|
|
6382
6490
|
super();
|
|
6383
|
-
this.#items = [];
|
|
6384
6491
|
this.#implicitlyDeletedItems = /* @__PURE__ */ new WeakSet();
|
|
6385
6492
|
this.#unacknowledgedSets = /* @__PURE__ */ new Map();
|
|
6386
|
-
|
|
6493
|
+
const nodes = [];
|
|
6494
|
+
let lastPos;
|
|
6387
6495
|
for (const item of items) {
|
|
6388
|
-
const
|
|
6496
|
+
const pos = makePosition(lastPos);
|
|
6389
6497
|
const node = lsonToLiveNode(item);
|
|
6390
|
-
node._setParentLink(this,
|
|
6391
|
-
|
|
6392
|
-
|
|
6498
|
+
node._setParentLink(this, pos);
|
|
6499
|
+
nodes.push(node);
|
|
6500
|
+
lastPos = pos;
|
|
6393
6501
|
}
|
|
6502
|
+
this.#items = SortedList.fromAlreadySorted(nodes, childNodeLt);
|
|
6394
6503
|
}
|
|
6395
6504
|
/** @internal */
|
|
6396
6505
|
static _deserialize([id, _], parentToChildren, pool) {
|
|
@@ -6404,7 +6513,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
6404
6513
|
const crdt = node[1];
|
|
6405
6514
|
const child = deserialize(node, parentToChildren, pool);
|
|
6406
6515
|
child._setParentLink(list, crdt.parentKey);
|
|
6407
|
-
list
|
|
6516
|
+
list.#insert(child);
|
|
6408
6517
|
}
|
|
6409
6518
|
return list;
|
|
6410
6519
|
}
|
|
@@ -6440,19 +6549,33 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
6440
6549
|
return ops;
|
|
6441
6550
|
}
|
|
6442
6551
|
/**
|
|
6443
|
-
*
|
|
6444
|
-
*
|
|
6445
|
-
* Adds a new item into the sorted list, in the correct position.
|
|
6552
|
+
* Inserts a new child into the list in the correct location (binary search
|
|
6553
|
+
* finds correct position efficiently). Returns the insertion index.
|
|
6446
6554
|
*/
|
|
6447
|
-
|
|
6448
|
-
this.#items.
|
|
6449
|
-
this.
|
|
6555
|
+
#insert(childNode) {
|
|
6556
|
+
const index = this.#items.add(childNode);
|
|
6557
|
+
this.invalidate();
|
|
6558
|
+
return index;
|
|
6450
6559
|
}
|
|
6451
|
-
/**
|
|
6452
|
-
|
|
6453
|
-
|
|
6560
|
+
/**
|
|
6561
|
+
* Updates an item's position and repositions it in the sorted list.
|
|
6562
|
+
* Encapsulates the remove -> mutate -> add cycle needed when changing sort keys.
|
|
6563
|
+
*
|
|
6564
|
+
* IMPORTANT: Item must exist in this list. List count remains unchanged.
|
|
6565
|
+
*/
|
|
6566
|
+
#updateItemPosition(item, newKey) {
|
|
6567
|
+
item._setParentLink(this, newKey);
|
|
6568
|
+
this.#items.reposition(item);
|
|
6454
6569
|
this.invalidate();
|
|
6455
6570
|
}
|
|
6571
|
+
/**
|
|
6572
|
+
* Updates an item's position by index. Safer than #updateItemPosition when you have
|
|
6573
|
+
* an index, as it ensures the item exists and is from this list.
|
|
6574
|
+
*/
|
|
6575
|
+
#updateItemPositionAt(index, newKey) {
|
|
6576
|
+
const item = nn(this.#items.at(index));
|
|
6577
|
+
this.#updateItemPosition(item, newKey);
|
|
6578
|
+
}
|
|
6456
6579
|
/** @internal */
|
|
6457
6580
|
_indexOfPosition(position) {
|
|
6458
6581
|
return this.#items.findIndex(
|
|
@@ -6484,10 +6607,12 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
6484
6607
|
const deletedId = op.deletedId;
|
|
6485
6608
|
const indexOfItemWithSamePosition = this._indexOfPosition(key);
|
|
6486
6609
|
if (indexOfItemWithSamePosition !== -1) {
|
|
6487
|
-
const itemWithSamePosition =
|
|
6610
|
+
const itemWithSamePosition = nn(
|
|
6611
|
+
this.#items.removeAt(indexOfItemWithSamePosition)
|
|
6612
|
+
);
|
|
6488
6613
|
if (itemWithSamePosition._id === deletedId) {
|
|
6489
6614
|
itemWithSamePosition._detach();
|
|
6490
|
-
this.#items
|
|
6615
|
+
this.#items.add(child);
|
|
6491
6616
|
return {
|
|
6492
6617
|
modified: makeUpdate(this, [
|
|
6493
6618
|
setDelta(indexOfItemWithSamePosition, child)
|
|
@@ -6496,7 +6621,8 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
6496
6621
|
};
|
|
6497
6622
|
} else {
|
|
6498
6623
|
this.#implicitlyDeletedItems.add(itemWithSamePosition);
|
|
6499
|
-
this.#items
|
|
6624
|
+
this.#items.remove(itemWithSamePosition);
|
|
6625
|
+
this.#items.add(child);
|
|
6500
6626
|
const delta = [
|
|
6501
6627
|
setDelta(indexOfItemWithSamePosition, child)
|
|
6502
6628
|
];
|
|
@@ -6519,7 +6645,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
6519
6645
|
if (deleteDelta2) {
|
|
6520
6646
|
updates.push(deleteDelta2);
|
|
6521
6647
|
}
|
|
6522
|
-
this
|
|
6648
|
+
this.#insert(child);
|
|
6523
6649
|
updates.push(insertDelta(this._indexOfPosition(key), child));
|
|
6524
6650
|
return {
|
|
6525
6651
|
reverse: [],
|
|
@@ -6554,16 +6680,15 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
6554
6680
|
};
|
|
6555
6681
|
}
|
|
6556
6682
|
if (indexOfItemWithSamePosition !== -1) {
|
|
6557
|
-
|
|
6558
|
-
this.#items
|
|
6683
|
+
const itemAtPosition = nn(
|
|
6684
|
+
this.#items.removeAt(indexOfItemWithSamePosition)
|
|
6559
6685
|
);
|
|
6560
|
-
|
|
6561
|
-
delta.push(deleteDelta(indexOfItemWithSamePosition,
|
|
6686
|
+
this.#implicitlyDeletedItems.add(itemAtPosition);
|
|
6687
|
+
delta.push(deleteDelta(indexOfItemWithSamePosition, itemAtPosition));
|
|
6562
6688
|
}
|
|
6563
|
-
const prevIndex = this.#items.
|
|
6564
|
-
existingItem
|
|
6565
|
-
this.
|
|
6566
|
-
const newIndex = this.#items.indexOf(existingItem);
|
|
6689
|
+
const prevIndex = this.#items.findIndex((item) => item === existingItem);
|
|
6690
|
+
this.#updateItemPosition(existingItem, op.parentKey);
|
|
6691
|
+
const newIndex = this.#items.findIndex((item) => item === existingItem);
|
|
6567
6692
|
if (newIndex !== prevIndex) {
|
|
6568
6693
|
delta.push(moveDelta(prevIndex, newIndex, existingItem));
|
|
6569
6694
|
}
|
|
@@ -6576,8 +6701,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
6576
6701
|
if (orphan && this.#implicitlyDeletedItems.has(orphan)) {
|
|
6577
6702
|
orphan._setParentLink(this, op.parentKey);
|
|
6578
6703
|
this.#implicitlyDeletedItems.delete(orphan);
|
|
6579
|
-
this
|
|
6580
|
-
const recreatedItemIndex = this.#items.indexOf(orphan);
|
|
6704
|
+
const recreatedItemIndex = this.#insert(orphan);
|
|
6581
6705
|
return {
|
|
6582
6706
|
modified: makeUpdate(this, [
|
|
6583
6707
|
// If there is an item at this position, update is a set, else it's an insert
|
|
@@ -6588,7 +6712,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
6588
6712
|
};
|
|
6589
6713
|
} else {
|
|
6590
6714
|
if (indexOfItemWithSamePosition !== -1) {
|
|
6591
|
-
this.#items.
|
|
6715
|
+
nn(this.#items.removeAt(indexOfItemWithSamePosition));
|
|
6592
6716
|
}
|
|
6593
6717
|
const { newItem, newIndex } = this.#createAttachItemAndSort(
|
|
6594
6718
|
op,
|
|
@@ -6647,12 +6771,13 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
6647
6771
|
modified: false
|
|
6648
6772
|
};
|
|
6649
6773
|
} else {
|
|
6650
|
-
const oldPositionIndex = this.#items.
|
|
6774
|
+
const oldPositionIndex = this.#items.findIndex(
|
|
6775
|
+
(item) => item === existingItem
|
|
6776
|
+
);
|
|
6651
6777
|
if (itemIndexAtPosition !== -1) {
|
|
6652
6778
|
this.#shiftItemPosition(itemIndexAtPosition, key);
|
|
6653
6779
|
}
|
|
6654
|
-
existingItem
|
|
6655
|
-
this._sortItems();
|
|
6780
|
+
this.#updateItemPosition(existingItem, key);
|
|
6656
6781
|
const newIndex = this._indexOfPosition(key);
|
|
6657
6782
|
if (newIndex === oldPositionIndex) {
|
|
6658
6783
|
return { modified: false };
|
|
@@ -6669,7 +6794,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
6669
6794
|
if (orphan && this.#implicitlyDeletedItems.has(orphan)) {
|
|
6670
6795
|
orphan._setParentLink(this, key);
|
|
6671
6796
|
this.#implicitlyDeletedItems.delete(orphan);
|
|
6672
|
-
this
|
|
6797
|
+
this.#insert(orphan);
|
|
6673
6798
|
const newIndex = this._indexOfPosition(key);
|
|
6674
6799
|
return {
|
|
6675
6800
|
modified: makeUpdate(this, [insertDelta(newIndex, orphan)]),
|
|
@@ -6698,12 +6823,12 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
6698
6823
|
const existingItemIndex = this._indexOfPosition(key);
|
|
6699
6824
|
let newKey = key;
|
|
6700
6825
|
if (existingItemIndex !== -1) {
|
|
6701
|
-
const before2 = this.#items
|
|
6702
|
-
const after2 = this.#items
|
|
6826
|
+
const before2 = this.#items.at(existingItemIndex)?._parentPos;
|
|
6827
|
+
const after2 = this.#items.at(existingItemIndex + 1)?._parentPos;
|
|
6703
6828
|
newKey = makePosition(before2, after2);
|
|
6704
6829
|
child._setParentLink(this, newKey);
|
|
6705
6830
|
}
|
|
6706
|
-
this
|
|
6831
|
+
this.#insert(child);
|
|
6707
6832
|
const newIndex = this._indexOfPosition(newKey);
|
|
6708
6833
|
return {
|
|
6709
6834
|
modified: makeUpdate(this, [insertDelta(newIndex, child)]),
|
|
@@ -6722,9 +6847,10 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
6722
6847
|
child._setParentLink(this, key);
|
|
6723
6848
|
const newKey = key;
|
|
6724
6849
|
if (indexOfItemWithSameKey !== -1) {
|
|
6725
|
-
const existingItem = this.#items
|
|
6850
|
+
const existingItem = this.#items.at(indexOfItemWithSameKey);
|
|
6726
6851
|
existingItem._detach();
|
|
6727
|
-
this.#items
|
|
6852
|
+
this.#items.remove(existingItem);
|
|
6853
|
+
this.#items.add(child);
|
|
6728
6854
|
const reverse = HACK_addIntentAndDeletedIdToOperation(
|
|
6729
6855
|
existingItem._toOps(nn(this._id), key),
|
|
6730
6856
|
op.id
|
|
@@ -6741,7 +6867,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
6741
6867
|
reverse
|
|
6742
6868
|
};
|
|
6743
6869
|
} else {
|
|
6744
|
-
this
|
|
6870
|
+
this.#insert(child);
|
|
6745
6871
|
this.#detachItemAssociatedToSetOperation(op.deletedId);
|
|
6746
6872
|
const newIndex = this._indexOfPosition(newKey);
|
|
6747
6873
|
return {
|
|
@@ -6783,13 +6909,14 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
6783
6909
|
if (child) {
|
|
6784
6910
|
const parentKey = nn(child._parentKey);
|
|
6785
6911
|
const reverse = child._toOps(nn(this._id), parentKey);
|
|
6786
|
-
const indexToDelete = this.#items.
|
|
6912
|
+
const indexToDelete = this.#items.findIndex((item) => item === child);
|
|
6787
6913
|
if (indexToDelete === -1) {
|
|
6788
6914
|
return {
|
|
6789
6915
|
modified: false
|
|
6790
6916
|
};
|
|
6791
6917
|
}
|
|
6792
|
-
const
|
|
6918
|
+
const previousNode = this.#items.at(indexToDelete);
|
|
6919
|
+
this.#items.remove(child);
|
|
6793
6920
|
this.invalidate();
|
|
6794
6921
|
child._detach();
|
|
6795
6922
|
return {
|
|
@@ -6803,8 +6930,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
6803
6930
|
if (this.#implicitlyDeletedItems.has(child)) {
|
|
6804
6931
|
this.#implicitlyDeletedItems.delete(child);
|
|
6805
6932
|
child._setParentLink(this, newKey);
|
|
6806
|
-
this
|
|
6807
|
-
const newIndex = this.#items.indexOf(child);
|
|
6933
|
+
const newIndex = this.#insert(child);
|
|
6808
6934
|
return {
|
|
6809
6935
|
modified: makeUpdate(this, [insertDelta(newIndex, child)]),
|
|
6810
6936
|
reverse: []
|
|
@@ -6818,10 +6944,9 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
6818
6944
|
}
|
|
6819
6945
|
const existingItemIndex = this._indexOfPosition(newKey);
|
|
6820
6946
|
if (existingItemIndex === -1) {
|
|
6821
|
-
const previousIndex = this.#items.
|
|
6822
|
-
child
|
|
6823
|
-
this.
|
|
6824
|
-
const newIndex = this.#items.indexOf(child);
|
|
6947
|
+
const previousIndex = this.#items.findIndex((item) => item === child);
|
|
6948
|
+
this.#updateItemPosition(child, newKey);
|
|
6949
|
+
const newIndex = this.#items.findIndex((item) => item === child);
|
|
6825
6950
|
if (newIndex === previousIndex) {
|
|
6826
6951
|
return {
|
|
6827
6952
|
modified: false
|
|
@@ -6832,14 +6957,13 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
6832
6957
|
reverse: []
|
|
6833
6958
|
};
|
|
6834
6959
|
} else {
|
|
6835
|
-
this.#
|
|
6836
|
-
|
|
6837
|
-
makePosition(newKey, this.#items
|
|
6960
|
+
this.#updateItemPositionAt(
|
|
6961
|
+
existingItemIndex,
|
|
6962
|
+
makePosition(newKey, this.#items.at(existingItemIndex + 1)?._parentPos)
|
|
6838
6963
|
);
|
|
6839
|
-
const previousIndex = this.#items.
|
|
6840
|
-
child
|
|
6841
|
-
this.
|
|
6842
|
-
const newIndex = this.#items.indexOf(child);
|
|
6964
|
+
const previousIndex = this.#items.findIndex((item) => item === child);
|
|
6965
|
+
this.#updateItemPosition(child, newKey);
|
|
6966
|
+
const newIndex = this.#items.findIndex((item) => item === child);
|
|
6843
6967
|
if (newIndex === previousIndex) {
|
|
6844
6968
|
return {
|
|
6845
6969
|
modified: false
|
|
@@ -6857,14 +6981,18 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
6857
6981
|
const existingItemIndex = this._indexOfPosition(newKey);
|
|
6858
6982
|
this.#implicitlyDeletedItems.delete(child);
|
|
6859
6983
|
if (existingItemIndex !== -1) {
|
|
6860
|
-
this.#items
|
|
6984
|
+
const existingItem = this.#items.at(existingItemIndex);
|
|
6985
|
+
existingItem._setParentLink(
|
|
6861
6986
|
this,
|
|
6862
|
-
makePosition(
|
|
6987
|
+
makePosition(
|
|
6988
|
+
newKey,
|
|
6989
|
+
this.#items.at(existingItemIndex + 1)?._parentPos
|
|
6990
|
+
)
|
|
6863
6991
|
);
|
|
6992
|
+
this.#items.reposition(existingItem);
|
|
6864
6993
|
}
|
|
6865
6994
|
child._setParentLink(this, newKey);
|
|
6866
|
-
this
|
|
6867
|
-
const newIndex = this.#items.indexOf(child);
|
|
6995
|
+
const newIndex = this.#insert(child);
|
|
6868
6996
|
return {
|
|
6869
6997
|
modified: makeUpdate(this, [insertDelta(newIndex, child)]),
|
|
6870
6998
|
reverse: []
|
|
@@ -6875,17 +7003,19 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
6875
7003
|
modified: false
|
|
6876
7004
|
};
|
|
6877
7005
|
}
|
|
6878
|
-
const previousIndex = this.#items.
|
|
7006
|
+
const previousIndex = this.#items.findIndex((item) => item === child);
|
|
6879
7007
|
const existingItemIndex = this._indexOfPosition(newKey);
|
|
6880
7008
|
if (existingItemIndex !== -1) {
|
|
6881
|
-
this.#
|
|
6882
|
-
|
|
6883
|
-
makePosition(
|
|
7009
|
+
this.#updateItemPositionAt(
|
|
7010
|
+
existingItemIndex,
|
|
7011
|
+
makePosition(
|
|
7012
|
+
newKey,
|
|
7013
|
+
this.#items.at(existingItemIndex + 1)?._parentPos
|
|
7014
|
+
)
|
|
6884
7015
|
);
|
|
6885
7016
|
}
|
|
6886
|
-
child
|
|
6887
|
-
this.
|
|
6888
|
-
const newIndex = this.#items.indexOf(child);
|
|
7017
|
+
this.#updateItemPosition(child, newKey);
|
|
7018
|
+
const newIndex = this.#items.findIndex((item) => item === child);
|
|
6889
7019
|
if (previousIndex === newIndex) {
|
|
6890
7020
|
return {
|
|
6891
7021
|
modified: false
|
|
@@ -6902,18 +7032,17 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
6902
7032
|
}
|
|
6903
7033
|
#applySetChildKeyUndoRedo(newKey, child) {
|
|
6904
7034
|
const previousKey = nn(child._parentKey);
|
|
6905
|
-
const previousIndex = this.#items.
|
|
7035
|
+
const previousIndex = this.#items.findIndex((item) => item === child);
|
|
6906
7036
|
const existingItemIndex = this._indexOfPosition(newKey);
|
|
6907
7037
|
let actualNewKey = newKey;
|
|
6908
7038
|
if (existingItemIndex !== -1) {
|
|
6909
7039
|
actualNewKey = makePosition(
|
|
6910
7040
|
newKey,
|
|
6911
|
-
this.#items
|
|
7041
|
+
this.#items.at(existingItemIndex + 1)?._parentPos
|
|
6912
7042
|
);
|
|
6913
7043
|
}
|
|
6914
|
-
child
|
|
6915
|
-
this.
|
|
6916
|
-
const newIndex = this.#items.indexOf(child);
|
|
7044
|
+
this.#updateItemPosition(child, actualNewKey);
|
|
7045
|
+
const newIndex = this.#items.findIndex((item) => item === child);
|
|
6917
7046
|
if (previousIndex === newIndex) {
|
|
6918
7047
|
return {
|
|
6919
7048
|
modified: false
|
|
@@ -6981,12 +7110,12 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
6981
7110
|
`Cannot insert list item at index "${index}". index should be between 0 and ${this.#items.length}`
|
|
6982
7111
|
);
|
|
6983
7112
|
}
|
|
6984
|
-
const before2 = this.#items
|
|
6985
|
-
const after2 = this.#items
|
|
7113
|
+
const before2 = this.#items.at(index - 1)?._parentPos;
|
|
7114
|
+
const after2 = this.#items.at(index)?._parentPos;
|
|
6986
7115
|
const position = makePosition(before2, after2);
|
|
6987
7116
|
const value = lsonToLiveNode(element);
|
|
6988
7117
|
value._setParentLink(this, position);
|
|
6989
|
-
this
|
|
7118
|
+
this.#insert(value);
|
|
6990
7119
|
if (this._pool && this._id) {
|
|
6991
7120
|
const id = this._pool.generateId();
|
|
6992
7121
|
value._attach(id, this._pool);
|
|
@@ -7023,17 +7152,16 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
7023
7152
|
let beforePosition = null;
|
|
7024
7153
|
let afterPosition = null;
|
|
7025
7154
|
if (index < targetIndex) {
|
|
7026
|
-
afterPosition = targetIndex === this.#items.length - 1 ? void 0 : this.#items
|
|
7027
|
-
beforePosition = this.#items
|
|
7155
|
+
afterPosition = targetIndex === this.#items.length - 1 ? void 0 : this.#items.at(targetIndex + 1)?._parentPos;
|
|
7156
|
+
beforePosition = this.#items.at(targetIndex)._parentPos;
|
|
7028
7157
|
} else {
|
|
7029
|
-
afterPosition = this.#items
|
|
7030
|
-
beforePosition = targetIndex === 0 ? void 0 : this.#items
|
|
7158
|
+
afterPosition = this.#items.at(targetIndex)._parentPos;
|
|
7159
|
+
beforePosition = targetIndex === 0 ? void 0 : this.#items.at(targetIndex - 1)?._parentPos;
|
|
7031
7160
|
}
|
|
7032
7161
|
const position = makePosition(beforePosition, afterPosition);
|
|
7033
|
-
const item = this.#items
|
|
7162
|
+
const item = this.#items.at(index);
|
|
7034
7163
|
const previousPosition = item._getParentKeyOrThrow();
|
|
7035
|
-
|
|
7036
|
-
this._sortItems();
|
|
7164
|
+
this.#updateItemPositionAt(index, position);
|
|
7037
7165
|
if (this._pool && this._id) {
|
|
7038
7166
|
const storageUpdates = /* @__PURE__ */ new Map([
|
|
7039
7167
|
[this._id, makeUpdate(this, [moveDelta(index, targetIndex, item)])]
|
|
@@ -7069,9 +7197,9 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
7069
7197
|
`Cannot delete list item at index "${index}". index should be between 0 and ${this.#items.length - 1}`
|
|
7070
7198
|
);
|
|
7071
7199
|
}
|
|
7072
|
-
const item = this.#items
|
|
7200
|
+
const item = this.#items.at(index);
|
|
7073
7201
|
item._detach();
|
|
7074
|
-
|
|
7202
|
+
this.#items.remove(item);
|
|
7075
7203
|
this.invalidate();
|
|
7076
7204
|
if (this._pool) {
|
|
7077
7205
|
const childRecordId = item._id;
|
|
@@ -7079,7 +7207,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
7079
7207
|
const storageUpdates = /* @__PURE__ */ new Map();
|
|
7080
7208
|
storageUpdates.set(
|
|
7081
7209
|
nn(this._id),
|
|
7082
|
-
makeUpdate(this, [deleteDelta(index,
|
|
7210
|
+
makeUpdate(this, [deleteDelta(index, item)])
|
|
7083
7211
|
);
|
|
7084
7212
|
this._pool.dispatch(
|
|
7085
7213
|
[
|
|
@@ -7116,7 +7244,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
7116
7244
|
updateDelta.push(deleteDelta(0, item));
|
|
7117
7245
|
}
|
|
7118
7246
|
}
|
|
7119
|
-
this.#items
|
|
7247
|
+
this.#items.clear();
|
|
7120
7248
|
this.invalidate();
|
|
7121
7249
|
const storageUpdates = /* @__PURE__ */ new Map();
|
|
7122
7250
|
storageUpdates.set(nn(this._id), makeUpdate(this, updateDelta));
|
|
@@ -7125,7 +7253,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
7125
7253
|
for (const item of this.#items) {
|
|
7126
7254
|
item._detach();
|
|
7127
7255
|
}
|
|
7128
|
-
this.#items
|
|
7256
|
+
this.#items.clear();
|
|
7129
7257
|
this.invalidate();
|
|
7130
7258
|
}
|
|
7131
7259
|
}
|
|
@@ -7136,13 +7264,14 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
7136
7264
|
`Cannot set list item at index "${index}". index should be between 0 and ${this.#items.length - 1}`
|
|
7137
7265
|
);
|
|
7138
7266
|
}
|
|
7139
|
-
const existingItem = this.#items
|
|
7267
|
+
const existingItem = this.#items.at(index);
|
|
7140
7268
|
const position = existingItem._getParentKeyOrThrow();
|
|
7141
7269
|
const existingId = existingItem._id;
|
|
7142
7270
|
existingItem._detach();
|
|
7143
7271
|
const value = lsonToLiveNode(item);
|
|
7144
7272
|
value._setParentLink(this, position);
|
|
7145
|
-
this.#items
|
|
7273
|
+
this.#items.remove(existingItem);
|
|
7274
|
+
this.#items.add(value);
|
|
7146
7275
|
this.invalidate();
|
|
7147
7276
|
if (this._pool && this._id) {
|
|
7148
7277
|
const id = this._pool.generateId();
|
|
@@ -7165,11 +7294,7 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
7165
7294
|
* Returns an Array of all the elements in the LiveList.
|
|
7166
7295
|
*/
|
|
7167
7296
|
toArray() {
|
|
7168
|
-
return this.#items
|
|
7169
|
-
(entry) => liveNodeToLson(entry)
|
|
7170
|
-
// ^^^^^^^^
|
|
7171
|
-
// FIXME! This isn't safe.
|
|
7172
|
-
);
|
|
7297
|
+
return Array.from(this.#items, (entry) => liveNodeToLson(entry));
|
|
7173
7298
|
}
|
|
7174
7299
|
/**
|
|
7175
7300
|
* Tests whether all elements pass the test implemented by the provided function.
|
|
@@ -7219,7 +7344,8 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
7219
7344
|
if (index < 0 || index >= this.#items.length) {
|
|
7220
7345
|
return void 0;
|
|
7221
7346
|
}
|
|
7222
|
-
|
|
7347
|
+
const item = this.#items.at(index);
|
|
7348
|
+
return item ? liveNodeToLson(item) : void 0;
|
|
7223
7349
|
}
|
|
7224
7350
|
/**
|
|
7225
7351
|
* Returns the first index at which a given element can be found in the LiveList, or -1 if it is not present.
|
|
@@ -7245,14 +7371,20 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
7245
7371
|
* @returns An array with each element being the result of the callback function.
|
|
7246
7372
|
*/
|
|
7247
7373
|
map(callback) {
|
|
7248
|
-
|
|
7249
|
-
|
|
7250
|
-
|
|
7251
|
-
|
|
7252
|
-
|
|
7253
|
-
|
|
7254
|
-
|
|
7255
|
-
|
|
7374
|
+
const result = [];
|
|
7375
|
+
let i = 0;
|
|
7376
|
+
for (const entry of this.#items) {
|
|
7377
|
+
result.push(
|
|
7378
|
+
callback(
|
|
7379
|
+
liveNodeToLson(entry),
|
|
7380
|
+
// ^^^^^^^^
|
|
7381
|
+
// FIXME! This isn't safe.
|
|
7382
|
+
i
|
|
7383
|
+
)
|
|
7384
|
+
);
|
|
7385
|
+
i++;
|
|
7386
|
+
}
|
|
7387
|
+
return result;
|
|
7256
7388
|
}
|
|
7257
7389
|
/**
|
|
7258
7390
|
* Tests whether at least one element in the LiveList passes the test implemented by the provided function.
|
|
@@ -7269,26 +7401,30 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
7269
7401
|
const newItem = creationOpToLiveNode(op);
|
|
7270
7402
|
newItem._attach(op.id, nn(this._pool));
|
|
7271
7403
|
newItem._setParentLink(this, key);
|
|
7272
|
-
this
|
|
7404
|
+
this.#insert(newItem);
|
|
7273
7405
|
const newIndex = this._indexOfPosition(key);
|
|
7274
7406
|
return { newItem, newIndex };
|
|
7275
7407
|
}
|
|
7276
7408
|
#shiftItemPosition(index, key) {
|
|
7277
7409
|
const shiftedPosition = makePosition(
|
|
7278
7410
|
key,
|
|
7279
|
-
this.#items.length > index + 1 ? this.#items
|
|
7411
|
+
this.#items.length > index + 1 ? this.#items.at(index + 1)?._parentPos : void 0
|
|
7280
7412
|
);
|
|
7281
|
-
this.#
|
|
7413
|
+
this.#updateItemPositionAt(index, shiftedPosition);
|
|
7282
7414
|
}
|
|
7283
7415
|
/** @internal */
|
|
7284
7416
|
_toTreeNode(key) {
|
|
7417
|
+
const payload = [];
|
|
7418
|
+
let index = 0;
|
|
7419
|
+
for (const item of this.#items) {
|
|
7420
|
+
payload.push(item.toTreeNode(index.toString()));
|
|
7421
|
+
index++;
|
|
7422
|
+
}
|
|
7285
7423
|
return {
|
|
7286
7424
|
type: "LiveList",
|
|
7287
7425
|
id: this._id ?? nanoid(),
|
|
7288
7426
|
key,
|
|
7289
|
-
payload
|
|
7290
|
-
(item, index) => item.toTreeNode(index.toString())
|
|
7291
|
-
)
|
|
7427
|
+
payload
|
|
7292
7428
|
};
|
|
7293
7429
|
}
|
|
7294
7430
|
toImmutable() {
|
|
@@ -7296,11 +7432,13 @@ var LiveList = class _LiveList extends AbstractCrdt {
|
|
|
7296
7432
|
}
|
|
7297
7433
|
/** @internal */
|
|
7298
7434
|
_toImmutable() {
|
|
7299
|
-
const result = this.#items
|
|
7435
|
+
const result = Array.from(this.#items, (node) => node.toImmutable());
|
|
7300
7436
|
return process.env.NODE_ENV === "production" ? result : Object.freeze(result);
|
|
7301
7437
|
}
|
|
7302
7438
|
clone() {
|
|
7303
|
-
return new _LiveList(
|
|
7439
|
+
return new _LiveList(
|
|
7440
|
+
Array.from(this.#items, (item) => item.clone())
|
|
7441
|
+
);
|
|
7304
7442
|
}
|
|
7305
7443
|
};
|
|
7306
7444
|
var LiveListIterator = class {
|
|
@@ -9241,8 +9379,17 @@ function createRoom(options, config) {
|
|
|
9241
9379
|
(me) => me !== null ? userToTreeNode("Me", me) : null
|
|
9242
9380
|
);
|
|
9243
9381
|
function createOrUpdateRootFromMessage(nodes) {
|
|
9382
|
+
if (nodes.size === 0) {
|
|
9383
|
+
throw new Error("Internal error: cannot load storage without items");
|
|
9384
|
+
}
|
|
9244
9385
|
if (context.root !== void 0) {
|
|
9245
|
-
|
|
9386
|
+
const currentItems = /* @__PURE__ */ new Map();
|
|
9387
|
+
for (const [id, crdt] of context.pool.nodes) {
|
|
9388
|
+
currentItems.set(id, crdt._serialize());
|
|
9389
|
+
}
|
|
9390
|
+
const ops = getTreesDiffOperations(currentItems, nodes);
|
|
9391
|
+
const result = applyRemoteOps(ops);
|
|
9392
|
+
notify(result.updates);
|
|
9246
9393
|
} else {
|
|
9247
9394
|
context.root = LiveObject._fromItems(
|
|
9248
9395
|
nodes,
|
|
@@ -9264,21 +9411,6 @@ function createRoom(options, config) {
|
|
|
9264
9411
|
}
|
|
9265
9412
|
context.undoStack.length = stackSizeBefore;
|
|
9266
9413
|
}
|
|
9267
|
-
function updateRoot(nodes) {
|
|
9268
|
-
if (nodes.size === 0) {
|
|
9269
|
-
throw new Error("Internal error: cannot load storage without items");
|
|
9270
|
-
}
|
|
9271
|
-
if (context.root === void 0) {
|
|
9272
|
-
return;
|
|
9273
|
-
}
|
|
9274
|
-
const currentItems = /* @__PURE__ */ new Map();
|
|
9275
|
-
for (const [id, crdt] of context.pool.nodes) {
|
|
9276
|
-
currentItems.set(id, crdt._serialize());
|
|
9277
|
-
}
|
|
9278
|
-
const ops = getTreesDiffOperations(currentItems, nodes);
|
|
9279
|
-
const result = applyRemoteOps(ops);
|
|
9280
|
-
notify(result.updates);
|
|
9281
|
-
}
|
|
9282
9414
|
function _addToRealUndoStack(frames) {
|
|
9283
9415
|
if (context.undoStack.length >= 50) {
|
|
9284
9416
|
context.undoStack.shift();
|