@databutton/liveblocks-client
Version:
**At [Liveblocks](https://liveblocks.io), we’re building tools to help companies create world-class collaborative products that attract, engage and retain users.** This repository is a set of open-source packages for building performant and reliable multi
141 lines (140 loc) • 4.38 kB
JavaScript
import { CrdtType, OpType, } from "./live";
import { LiveList } from "./LiveList";
import { LiveMap } from "./LiveMap";
import { LiveObject } from "./LiveObject";
import { LiveRegister } from "./LiveRegister";
export function remove(array, item) {
for (let i = 0; i < array.length; i++) {
if (array[i] === item) {
array.splice(i, 1);
break;
}
}
}
export function isSameNodeOrChildOf(node, parent) {
if (node === parent) {
return true;
}
if (node._parent) {
return isSameNodeOrChildOf(node._parent, parent);
}
return false;
}
export function deserialize(entry, parentToChildren, doc) {
switch (entry[1].type) {
case CrdtType.Object: {
return LiveObject._deserialize(entry, parentToChildren, doc);
}
case CrdtType.List: {
return LiveList._deserialize(entry, parentToChildren, doc);
}
case CrdtType.Map: {
return LiveMap._deserialize(entry, parentToChildren, doc);
}
case CrdtType.Register: {
return LiveRegister._deserialize(entry, parentToChildren, doc);
}
default: {
throw new Error("Unexpected CRDT type");
}
}
}
export function isCrdt(obj) {
return (obj instanceof LiveObject ||
obj instanceof LiveMap ||
obj instanceof LiveList ||
obj instanceof LiveRegister);
}
export function selfOrRegisterValue(obj) {
if (obj instanceof LiveRegister) {
return obj.data;
}
return obj;
}
export function selfOrRegister(obj) {
if (obj instanceof LiveObject ||
obj instanceof LiveMap ||
obj instanceof LiveList) {
return obj;
}
else if (obj instanceof LiveRegister) {
throw new Error("Internal error. LiveRegister should not be created from selfOrRegister");
}
else {
return new LiveRegister(obj);
}
}
export function getTreesDiffOperations(currentItems, newItems) {
const ops = [];
currentItems.forEach((_, id) => {
if (!newItems.get(id)) {
// Delete crdt
ops.push({
type: OpType.DeleteCrdt,
id: id,
});
}
});
newItems.forEach((crdt, id) => {
const currentCrdt = currentItems.get(id);
if (currentCrdt) {
if (crdt.type === CrdtType.Object) {
if (JSON.stringify(crdt.data) !==
JSON.stringify(currentCrdt.data)) {
ops.push({
type: OpType.UpdateObject,
id: id,
data: crdt.data,
});
}
}
if (crdt.parentKey !== currentCrdt.parentKey) {
ops.push({
type: OpType.SetParentKey,
id: id,
parentKey: crdt.parentKey,
});
}
}
else {
// new Crdt
switch (crdt.type) {
case CrdtType.Register:
ops.push({
type: OpType.CreateRegister,
id: id,
parentId: crdt.parentId,
parentKey: crdt.parentKey,
data: crdt.data,
});
break;
case CrdtType.List:
ops.push({
type: OpType.CreateList,
id: id,
parentId: crdt.parentId,
parentKey: crdt.parentKey,
});
break;
case CrdtType.Object:
ops.push({
type: OpType.CreateObject,
id: id,
parentId: crdt.parentId,
parentKey: crdt.parentKey,
data: crdt.data,
});
break;
case CrdtType.Map:
ops.push({
type: OpType.CreateMap,
id: id,
parentId: crdt.parentId,
parentKey: crdt.parentKey,
});
break;
}
}
});
return ops;
}