Socket
Socket
Sign inDemoInstall

@liveblocks/client

Package Overview
Dependencies
Maintainers
3
Versions
368
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.12.0-beta.13 to 0.12.0-beta.14

189

lib/cjs/doc.d.ts

@@ -12,4 +12,7 @@ import { Op, SerializedCrdtWithId, SerializedList } from "./live";

getItem(id: string): AbstractCrdt | undefined;
apply(op: Op): void;
apply(ops: Op[]): Op[];
get root(): LiveObject<T>;
addToUndoStack(ops: Op[]): void;
undo(): void;
redo(): void;
count(): number;

@@ -36,8 +39,13 @@ generateId(): string;

*/
_setParent(parent: AbstractCrdt): void;
get _parentKey(): string | undefined;
_apply(op: Op): Op[];
/**
* INTERNAL
*/
_setParentLink(parent: AbstractCrdt, key: string): void;
/**
* INTERNAL
*/
_attach(id: string, doc: Doc): void;
abstract _attachChild(id: string, key: string, crdt: AbstractCrdt): void;
abstract _attachChild(id: string, key: string, crdt: AbstractCrdt): Op[];
/**

@@ -48,9 +56,29 @@ * INTERNAL

abstract _detachChild(crdt: AbstractCrdt): void;
/**
* Subscribes to updates.
*/
subscribe(listener: () => void): void;
/**
* Subscribes to updates and children updates.
*/
subscribeDeep(listener: () => void): void;
/**
* Unsubscribes to updates.
*/
unsubscribe(listener: () => void): void;
/**
* Unsubscribes to updates and children updates.
*/
unsubscribeDeep(listener: () => void): void;
notify(onlyDeep?: boolean): void;
/**
* INTERNAL
*/
_notify(onlyDeep?: boolean): void;
abstract _serialize(parentId: string, parentKey: string): Op[];
}
/**
* The LiveObject class is similar to a JavaScript object that is synchronized on all clients.
* Keys should be a string, and values should be serializable to JSON.
* If multiple clients update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.
*/
export declare class LiveObject<T extends Record<string, any> = Record<string, any>> extends AbstractCrdt {

@@ -76,3 +104,3 @@ #private;

*/
_attachChild(id: string, key: keyof T, child: AbstractCrdt): void;
_attachChild(id: string, key: keyof T, child: AbstractCrdt): Op[];
/**

@@ -89,8 +117,29 @@ * INTERNAL

*/
_apply(op: Op): void;
_apply(op: Op): Op[];
/**
* Transform the LiveObject into a javascript object
*/
toObject(): T;
/**
* Adds or updates a property with a specified key and a value.
* @param key The key of the property to add
* @param value The value of the property to add
*/
set<TKey extends keyof T>(key: TKey, value: T[TKey]): void;
/**
* Returns a specified property from the LiveObject.
* @param key The key of the property to get
*/
get<TKey extends keyof T>(key: TKey): T[TKey];
/**
* Adds or updates multiple properties at once with an object.
* @param overrides The object used to overrides properties
*/
update(overrides: Partial<T>): void;
}
/**
* The LiveMap class is similar to a JavaScript Map that is synchronized on all clients.
* Keys should be a string, and values should be serializable to JSON.
* If multiple clients update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.
*/
export declare class LiveMap<TKey extends string, TValue> extends AbstractCrdt {

@@ -114,3 +163,3 @@ #private;

*/
_attachChild(id: string, key: TKey, child: AbstractCrdt): void;
_attachChild(id: string, key: TKey, child: AbstractCrdt): Op[];
/**

@@ -124,13 +173,54 @@ * INTERNAL

_detachChild(child: AbstractCrdt): void;
/**
* Returns a specified element from the LiveMap.
* @param key The key of the element to return.
* @returns The element associated with the specified key, or undefined if the key can't be found in the LiveMap.
*/
get(key: TKey): TValue | undefined;
/**
* Adds or updates an element with a specified key and a value.
* @param key The key of the element to add. Should be a string.
* @param value The value of the element to add. Should be serializable to JSON.
*/
set(key: TKey, value: TValue): void;
/**
* Returns the number of elements in the LiveMap.
*/
get size(): number;
/**
* Returns a boolean indicating whether an element with the specified key exists or not.
* @param key The key of the element to test for presence.
*/
has(key: TKey): boolean;
/**
* Removes the specified element by key.
* @param key The key of the element to remove.
* @returns true if an element existed and has been removed, or false if the element does not exist.
*/
delete(key: TKey): boolean;
/**
* Returns a new Iterator object that contains the [key, value] pairs for each element.
*/
entries(): IterableIterator<[string, TValue]>;
/**
* Same function object as the initial value of the entries method.
*/
[Symbol.iterator](): IterableIterator<[string, TValue]>;
/**
* Returns a new Iterator object that contains the keys for each element.
*/
keys(): IterableIterator<TKey>;
/**
* Returns a new Iterator object that contains the values for each element.
*/
values(): IterableIterator<TValue>;
/**
* Executes a provided function once per each key/value pair in the Map object, in insertion order.
* @param callback Function to execute for each entry in the map.
*/
forEach(callback: (value: TValue, key: TKey, map: LiveMap<TKey, TValue>) => void): void;
}
/**
* The LiveList class represents an ordered collection of items that is synchorinized across clients.
*/
export declare class LiveList<T> extends AbstractCrdt {

@@ -158,3 +248,3 @@ #private;

*/
_attachChild(id: string, key: string, child: AbstractCrdt): void;
_attachChild(id: string, key: string, child: AbstractCrdt): Op[];
/**

@@ -168,17 +258,96 @@ * INTERNAL

_setChildKey(key: string, child: AbstractCrdt): void;
/**
* INTERNAL
*/
_apply(op: Op): Op[];
/**
* Returns the number of elements.
*/
get length(): number;
push(item: T): void;
insert(item: T, index: number): void;
/**
* Adds one element to the end of the LiveList.
* @param element The element to add to the end of the LiveList.
*/
push(element: T): void;
/**
* Inserts one element at a specified index.
* @param element The element to insert.
* @param index The index at which you want to insert the element.
*/
insert(element: T, index: number): void;
/**
* Move one element from one index to another.
* @param index The index of the element to move
* @param targetIndex The index where the element should be after moving.
*/
move(index: number, targetIndex: number): void;
/**
* Deletes an element at the specified index
* @param index The index of the element to delete
*/
delete(index: number): void;
/**
* Returns an Array of all the elements in the LiveList.
*/
toArray(): T[];
/**
* Tests whether all elements pass the test implemented by the provided function.
* @param predicate Function to test for each element, taking two arguments (the element and its index).
* @returns true if the predicate function returns a truthy value for every element. Otherwise, false.
*/
every(predicate: (value: T, index: number) => unknown): boolean;
/**
* Creates an array with all elements that pass the test implemented by the provided function.
* @param predicate Function to test each element of the LiveList. Return a value that coerces to true to keep the element, or to false otherwise.
* @returns An array with the elements that pass the test.
*/
filter(predicate: (value: T, index: number) => unknown): T[];
/**
* Returns the first element that satisfies the provided testing function.
* @param predicate Function to execute on each value.
* @returns The value of the first element in the LiveList that satisfies the provided testing function. Otherwise, undefined is returned.
*/
find(predicate: (value: T, index: number) => unknown): T | undefined;
/**
* Returns the index of the first element in the LiveList that satisfies the provided testing function.
* @param predicate Function to execute on each value until the function returns true, indicating that the satisfying element was found.
* @returns The index of the first element in the LiveList that passes the test. Otherwise, -1.
*/
findIndex(predicate: (value: T, index: number) => unknown): number;
/**
* Executes a provided function once for each element.
* @param callbackfn Function to execute on each element.
*/
forEach(callbackfn: (value: T, index: number) => void): void;
/**
* Get the element at the specified index.
* @param index The index on the element to get.
* @returns The element at the specified index or undefined.
*/
get(index: number): T | undefined;
/**
* Returns the first index at which a given element can be found in the LiveList, or -1 if it is not present.
* @param searchElement Element to locate.
* @param fromIndex The index to start the search at.
* @returns The first index of the element in the LiveList; -1 if not found.
*/
indexOf(searchElement: T, fromIndex?: number): number;
/**
* Returns the last index at which a given element can be found in the LiveList, or -1 if it is not present. The LiveLsit is searched backwards, starting at fromIndex.
* @param searchElement Element to locate.
* @param fromIndex The index at which to start searching backwards.
* @returns
*/
lastIndexOf(searchElement: T, fromIndex?: number): number;
/**
* Creates an array populated with the results of calling a provided function on every element.
* @param callback Function that is called for every element.
* @returns An array with each element being the result of the callback function.
*/
map<U>(callback: (value: T, index: number) => U): U[];
/**
* Tests whether at least one element in the LiveList passes the test implemented by the provided function.
* @param predicate Function to test for each element.
* @returns true if the callback function returns a truthy value for at least one element. Otherwise, false.
*/
some(predicate: (value: T, index: number) => unknown): boolean;

@@ -185,0 +354,0 @@ [Symbol.iterator](): IterableIterator<T>;

653

lib/cjs/doc.js

@@ -13,3 +13,3 @@ "use strict";

};
var _Doc_instances, _Doc_clock, _Doc_opClock, _Doc_items, _Doc_root, _Doc_actor, _Doc_dispatch, _Doc_applyCreateRegister, _Doc_applyDeleteRecordKey, _Doc_applyUpdateRecord, _Doc_applyCreateMap, _Doc_applyCreateList, _Doc_applyCreateObject, _Doc_applyDeleteRecord, _Doc_applySetParentKey, _AbstractCrdt_listeners, _AbstractCrdt_deepListeners, _AbstractCrdt_parent, _AbstractCrdt_doc, _AbstractCrdt_id, _LiveObject_map, _LiveObject_propToLastUpdate, _LiveMap_map, _LiveRegister_data, _LiveList_items, _LiveListIterator_innerIterator;
var _Doc_instances, _Doc_clock, _Doc_opClock, _Doc_items, _Doc_root, _Doc_actor, _Doc_dispatch, _Doc_undoStack, _Doc_redoStack, _Doc_applyOp, _AbstractCrdt_instances, _AbstractCrdt_listeners, _AbstractCrdt_deepListeners, _AbstractCrdt_parent, _AbstractCrdt_doc, _AbstractCrdt_id, _AbstractCrdt_parentKey, _AbstractCrdt_applySetParentKey, _AbstractCrdt_applyRegister, _AbstractCrdt_applyCreateObject, _AbstractCrdt_applyCreateMap, _AbstractCrdt_applyCreateList, _LiveObject_instances, _LiveObject_map, _LiveObject_propToLastUpdate, _LiveObject_applyDeleteObjectKey, _LiveMap_map, _LiveRegister_data, _LiveList_items, _LiveListIterator_innerIterator;
Object.defineProperty(exports, "__esModule", { value: true });

@@ -21,2 +21,3 @@ exports.LiveList = exports.LiveMap = exports.LiveObject = exports.Doc = void 0;

function noOp() { }
const MAX_UNDO_STACK = 50;
class Doc {

@@ -31,2 +32,4 @@ constructor(root, actor = 0, dispatch = noOp) {

_Doc_dispatch.set(this, void 0);
_Doc_undoStack.set(this, []);
_Doc_redoStack.set(this, []);
__classPrivateFieldSet(this, _Doc_root, root, "f");

@@ -72,2 +75,3 @@ __classPrivateFieldSet(this, _Doc_actor, actor, "f");

dispatch(ops) {
__classPrivateFieldSet(this, _Doc_redoStack, [], "f");
__classPrivateFieldGet(this, _Doc_dispatch, "f").call(this, ops);

@@ -84,37 +88,8 @@ }

}
apply(op) {
switch (op.type) {
case live_1.OpType.UpdateObject: {
__classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyUpdateRecord).call(this, op);
break;
}
case live_1.OpType.CreateObject: {
__classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyCreateObject).call(this, op);
break;
}
case live_1.OpType.CreateMap: {
__classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyCreateMap).call(this, op);
break;
}
case live_1.OpType.CreateList: {
__classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyCreateList).call(this, op);
break;
}
case live_1.OpType.DeleteCrdt: {
__classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyDeleteRecord).call(this, op);
break;
}
case live_1.OpType.SetParentKey: {
__classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applySetParentKey).call(this, op);
break;
}
case live_1.OpType.DeleteObjectKey: {
__classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyDeleteRecordKey).call(this, op);
break;
}
case live_1.OpType.CreateRegister: {
__classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyCreateRegister).call(this, op);
break;
}
apply(ops) {
const reverse = [];
for (const op of ops) {
reverse.push(...__classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyOp).call(this, op));
}
return reverse;
}

@@ -124,2 +99,24 @@ get root() {

}
addToUndoStack(ops) {
if (__classPrivateFieldGet(this, _Doc_undoStack, "f").length >= MAX_UNDO_STACK) {
__classPrivateFieldGet(this, _Doc_undoStack, "f").shift();
}
__classPrivateFieldGet(this, _Doc_undoStack, "f").push(ops);
}
undo() {
const ops = __classPrivateFieldGet(this, _Doc_undoStack, "f").pop();
if (ops == null) {
return;
}
__classPrivateFieldGet(this, _Doc_redoStack, "f").push(this.apply(ops));
__classPrivateFieldGet(this, _Doc_dispatch, "f").call(this, ops);
}
redo() {
const ops = __classPrivateFieldGet(this, _Doc_redoStack, "f").pop();
if (ops == null) {
return;
}
__classPrivateFieldGet(this, _Doc_undoStack, "f").push(this.apply(ops));
__classPrivateFieldGet(this, _Doc_dispatch, "f").call(this, ops);
}
count() {

@@ -138,83 +135,32 @@ return __classPrivateFieldGet(this, _Doc_items, "f").size;

exports.Doc = Doc;
_Doc_clock = new WeakMap(), _Doc_opClock = new WeakMap(), _Doc_items = new WeakMap(), _Doc_root = new WeakMap(), _Doc_actor = new WeakMap(), _Doc_dispatch = new WeakMap(), _Doc_instances = new WeakSet(), _Doc_applyCreateRegister = function _Doc_applyCreateRegister(op) {
if (__classPrivateFieldGet(this, _Doc_items, "f").has(op.id)) {
return;
}
const parent = __classPrivateFieldGet(this, _Doc_items, "f").get(op.parentId);
if (parent == null) {
return;
}
if (!(parent instanceof LiveMap) && !(parent instanceof LiveList)) {
throw new Error("LiveRegister can only be attached to a LiveMap or LiveList");
}
const newRegister = new LiveRegister(op.data);
parent._attachChild(op.id, op.parentKey, newRegister);
}, _Doc_applyDeleteRecordKey = function _Doc_applyDeleteRecordKey(op) {
const item = __classPrivateFieldGet(this, _Doc_items, "f").get(op.id);
if (item && item instanceof LiveObject) {
item._apply(op);
}
}, _Doc_applyUpdateRecord = function _Doc_applyUpdateRecord(op) {
const item = __classPrivateFieldGet(this, _Doc_items, "f").get(op.id);
if (item && item instanceof LiveObject) {
item._apply(op);
}
}, _Doc_applyCreateMap = function _Doc_applyCreateMap(op) {
if (__classPrivateFieldGet(this, _Doc_items, "f").has(op.id)) {
return;
}
const parent = __classPrivateFieldGet(this, _Doc_items, "f").get(op.parentId);
if (parent == null) {
return;
}
const newMap = new LiveMap();
parent._attachChild(op.id, op.parentKey, newMap);
}, _Doc_applyCreateList = function _Doc_applyCreateList(op) {
if (__classPrivateFieldGet(this, _Doc_items, "f").has(op.id)) {
return;
}
const parent = __classPrivateFieldGet(this, _Doc_items, "f").get(op.parentId);
if (parent == null) {
return;
}
const list = new LiveList();
parent._attachChild(op.id, op.parentKey, list);
}, _Doc_applyCreateObject = function _Doc_applyCreateObject(op) {
if (__classPrivateFieldGet(this, _Doc_items, "f").has(op.id)) {
return;
}
if (op.parentId && op.parentKey) {
const parent = __classPrivateFieldGet(this, _Doc_items, "f").get(op.parentId);
if (parent == null) {
return;
_Doc_clock = new WeakMap(), _Doc_opClock = new WeakMap(), _Doc_items = new WeakMap(), _Doc_root = new WeakMap(), _Doc_actor = new WeakMap(), _Doc_dispatch = new WeakMap(), _Doc_undoStack = new WeakMap(), _Doc_redoStack = new WeakMap(), _Doc_instances = new WeakSet(), _Doc_applyOp = function _Doc_applyOp(op) {
switch (op.type) {
case live_1.OpType.DeleteObjectKey:
case live_1.OpType.UpdateObject:
case live_1.OpType.DeleteCrdt:
case live_1.OpType.SetParentKey: {
const item = __classPrivateFieldGet(this, _Doc_items, "f").get(op.id);
if (item == null) {
return [];
}
return item._apply(op);
break;
}
const newObj = new LiveObject(op.data);
parent._attachChild(op.id, op.parentKey, newObj);
case live_1.OpType.CreateList:
case live_1.OpType.CreateObject:
case live_1.OpType.CreateMap:
case live_1.OpType.CreateRegister: {
const parent = __classPrivateFieldGet(this, _Doc_items, "f").get(op.parentId);
if (parent == null) {
return [];
}
return parent._apply(op);
break;
}
}
}, _Doc_applyDeleteRecord = function _Doc_applyDeleteRecord(op) {
const item = __classPrivateFieldGet(this, _Doc_items, "f").get(op.id);
if (item == null) {
return;
}
const parent = item._parent;
if (parent == null) {
return;
}
if (parent) {
parent._detachChild(item);
}
}, _Doc_applySetParentKey = function _Doc_applySetParentKey(op) {
const item = __classPrivateFieldGet(this, _Doc_items, "f").get(op.id);
if (item == null) {
return;
}
if (item._parent == null) {
return;
}
if (item._parent instanceof LiveList) {
item._parent._setChildKey(op.parentKey, item);
}
return [];
};
class AbstractCrdt {
constructor() {
_AbstractCrdt_instances.add(this);
_AbstractCrdt_listeners.set(this, []);

@@ -225,2 +171,3 @@ _AbstractCrdt_deepListeners.set(this, []);

_AbstractCrdt_id.set(this, void 0);
_AbstractCrdt_parentKey.set(this, void 0);
}

@@ -248,6 +195,41 @@ /**

*/
_setParent(parent) {
if (__classPrivateFieldGet(this, _AbstractCrdt_parent, "f")) {
get _parentKey() {
return __classPrivateFieldGet(this, _AbstractCrdt_parentKey, "f");
}
_apply(op) {
switch (op.type) {
case live_1.OpType.DeleteCrdt: {
if (this._parent != null && this._parentKey != null) {
const reverse = this._serialize(this._parent._id, this._parentKey);
this._parent._detachChild(this);
return reverse;
}
return [];
}
case live_1.OpType.CreateObject: {
return __classPrivateFieldGet(this, _AbstractCrdt_instances, "m", _AbstractCrdt_applyCreateObject).call(this, op);
}
case live_1.OpType.CreateMap: {
return __classPrivateFieldGet(this, _AbstractCrdt_instances, "m", _AbstractCrdt_applyCreateMap).call(this, op);
}
case live_1.OpType.CreateRegister: {
return __classPrivateFieldGet(this, _AbstractCrdt_instances, "m", _AbstractCrdt_applyRegister).call(this, op);
}
case live_1.OpType.CreateList: {
return __classPrivateFieldGet(this, _AbstractCrdt_instances, "m", _AbstractCrdt_applyCreateList).call(this, op);
}
case live_1.OpType.SetParentKey: {
return __classPrivateFieldGet(this, _AbstractCrdt_instances, "m", _AbstractCrdt_applySetParentKey).call(this, op);
}
}
return [];
}
/**
* INTERNAL
*/
_setParentLink(parent, key) {
if (__classPrivateFieldGet(this, _AbstractCrdt_parent, "f") != null && __classPrivateFieldGet(this, _AbstractCrdt_parent, "f") !== parent) {
throw new Error("Cannot attach parent if it already exist");
}
__classPrivateFieldSet(this, _AbstractCrdt_parentKey, key, "f");
__classPrivateFieldSet(this, _AbstractCrdt_parent, parent, "f");

@@ -276,15 +258,30 @@ }

}
/**
* Subscribes to updates.
*/
subscribe(listener) {
__classPrivateFieldGet(this, _AbstractCrdt_listeners, "f").push(listener);
}
/**
* Subscribes to updates and children updates.
*/
subscribeDeep(listener) {
__classPrivateFieldGet(this, _AbstractCrdt_deepListeners, "f").push(listener);
}
/**
* Unsubscribes to updates.
*/
unsubscribe(listener) {
(0, utils_1.remove)(__classPrivateFieldGet(this, _AbstractCrdt_listeners, "f"), listener);
}
/**
* Unsubscribes to updates and children updates.
*/
unsubscribeDeep(listener) {
(0, utils_1.remove)(__classPrivateFieldGet(this, _AbstractCrdt_deepListeners, "f"), listener);
}
notify(onlyDeep = false) {
/**
* INTERNAL
*/
_notify(onlyDeep = false) {
if (onlyDeep === false) {

@@ -299,10 +296,60 @@ for (const listener of __classPrivateFieldGet(this, _AbstractCrdt_listeners, "f")) {

if (this._parent) {
this._parent.notify(true);
this._parent._notify(true);
}
}
}
_AbstractCrdt_listeners = new WeakMap(), _AbstractCrdt_deepListeners = new WeakMap(), _AbstractCrdt_parent = new WeakMap(), _AbstractCrdt_doc = new WeakMap(), _AbstractCrdt_id = new WeakMap();
_AbstractCrdt_listeners = new WeakMap(), _AbstractCrdt_deepListeners = new WeakMap(), _AbstractCrdt_parent = new WeakMap(), _AbstractCrdt_doc = new WeakMap(), _AbstractCrdt_id = new WeakMap(), _AbstractCrdt_parentKey = new WeakMap(), _AbstractCrdt_instances = new WeakSet(), _AbstractCrdt_applySetParentKey = function _AbstractCrdt_applySetParentKey(op) {
if (this._parent == null) {
return [];
}
if (this._parent instanceof LiveList) {
const previousKey = this._parentKey;
this._parent._setChildKey(op.parentKey, this);
return [
{ type: live_1.OpType.SetParentKey, id: this._id, parentKey: previousKey },
];
}
return [];
}, _AbstractCrdt_applyRegister = function _AbstractCrdt_applyRegister(op) {
if (this._doc == null) {
throw new Error("Internal: doc should exist");
}
if (this._doc.getItem(op.id) != null) {
return [];
}
return this._attachChild(op.id, op.parentKey, new LiveRegister(op.data));
}, _AbstractCrdt_applyCreateObject = function _AbstractCrdt_applyCreateObject(op) {
if (this._doc == null) {
throw new Error("Internal: doc should exist");
}
if (this._doc.getItem(op.id) != null) {
return [];
}
return this._attachChild(op.id, op.parentKey, new LiveObject(op.data));
}, _AbstractCrdt_applyCreateMap = function _AbstractCrdt_applyCreateMap(op) {
if (this._doc == null) {
throw new Error("Internal: doc should exist");
}
if (this._doc.getItem(op.id) != null) {
return [];
}
return this._attachChild(op.id, op.parentKey, new LiveMap());
}, _AbstractCrdt_applyCreateList = function _AbstractCrdt_applyCreateList(op) {
if (this._doc == null) {
throw new Error("Internal: doc should exist");
}
if (this._doc.getItem(op.id) != null) {
return [];
}
return this._attachChild(op.id, op.parentKey, new LiveList());
};
/**
* The LiveObject class is similar to a JavaScript object that is synchronized on all clients.
* Keys should be a string, and values should be serializable to JSON.
* If multiple clients update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.
*/
class LiveObject extends AbstractCrdt {
constructor(object = {}) {
super();
_LiveObject_instances.add(this);
_LiveObject_map.set(this, void 0);

@@ -313,3 +360,3 @@ _LiveObject_propToLastUpdate.set(this, new Map());

if (value instanceof AbstractCrdt) {
value._setParent(this);
value._setParentLink(this, key);
}

@@ -364,3 +411,3 @@ }

const child = deserialize(entry, parentToChildren, doc);
child._setParent(object);
child._setParentLink(object, crdt.parentKey);
__classPrivateFieldGet(object, _LiveObject_map, "f").set(crdt.parentKey, child);

@@ -389,9 +436,26 @@ }

const previousValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
let result;
if (isCrdt(previousValue)) {
result = previousValue._serialize(this._id, key);
previousValue._detach();
}
else if (previousValue === undefined) {
result = [
{ type: live_1.OpType.DeleteObjectKey, id: this._id, key: key },
];
}
else {
result = [
{
type: live_1.OpType.UpdateObject,
id: this._id,
data: { [key]: previousValue },
},
];
}
__classPrivateFieldGet(this, _LiveObject_map, "f").set(key, child);
child._setParent(this);
child._setParentLink(this, key);
child._attach(id, this._doc);
this.notify();
this._notify();
return result;
}

@@ -410,3 +474,3 @@ /**

}
this.notify();
this._notify();
}

@@ -428,7 +492,28 @@ /**

_apply(op) {
var _a;
if (op.type === live_1.OpType.UpdateObject) {
const reverse = [];
const reverseUpdate = {
type: live_1.OpType.UpdateObject,
id: this._id,
data: {},
};
reverse.push(reverseUpdate);
for (const key in op.data) {
const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
if (oldValue !== undefined) {
reverseUpdate.data[key] = oldValue;
}
else if (oldValue === undefined) {
reverse.push({ type: live_1.OpType.DeleteObjectKey, id: this._id, key });
}
}
for (const key in op.data) {
if (op.opId == null) {
op.opId = (_a = this._doc) === null || _a === void 0 ? void 0 : _a.generateOpId();
}
const lastOpId = __classPrivateFieldGet(this, _LiveObject_propToLastUpdate, "f").get(key);
if (lastOpId === op.opId) {
__classPrivateFieldGet(this, _LiveObject_propToLastUpdate, "f").delete(key);
continue;
}

@@ -445,17 +530,21 @@ else if (lastOpId != null) {

}
this.notify();
this._notify();
return reverse;
}
else if (op.type === live_1.OpType.DeleteObjectKey) {
const key = op.key;
const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
if (isCrdt(oldValue)) {
oldValue._detach();
}
__classPrivateFieldGet(this, _LiveObject_map, "f").delete(key);
this.notify();
return __classPrivateFieldGet(this, _LiveObject_instances, "m", _LiveObject_applyDeleteObjectKey).call(this, op);
}
return super._apply(op);
}
/**
* Transform the LiveObject into a javascript object
*/
toObject() {
return Object.fromEntries(__classPrivateFieldGet(this, _LiveObject_map, "f"));
}
/**
* Adds or updates a property with a specified key and a value.
* @param key The key of the property to add
* @param value The value of the property to add
*/
set(key, value) {

@@ -465,20 +554,18 @@ // TODO: Find out why typescript complains

}
/**
* Returns a specified property from the LiveObject.
* @param key The key of the property to get
*/
get(key) {
return __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
}
/**
* Adds or updates multiple properties at once with an object.
* @param overrides The object used to overrides properties
*/
update(overrides) {
if (this._doc && this._id) {
const ops = [];
const opId = this._doc.generateOpId();
const updateOp = {
opId,
id: this._id,
type: live_1.OpType.UpdateObject,
data: {},
};
ops.push(updateOp);
if (this._doc == null || this._id == null) {
for (const key in overrides) {
__classPrivateFieldGet(this, _LiveObject_propToLastUpdate, "f").set(key, opId);
const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
if (oldValue instanceof LiveObject) {
if (oldValue instanceof AbstractCrdt) {
oldValue._detach();

@@ -488,31 +575,81 @@ }

if (newValue instanceof AbstractCrdt) {
newValue._setParent(this);
newValue._attach(this._doc.generateId(), this._doc);
ops.push(...newValue._serialize(this._id, key));
newValue._setParentLink(this, key);
}
else {
updateOp.data[key] = newValue;
}
__classPrivateFieldGet(this, _LiveObject_map, "f").set(key, newValue);
}
this._doc.dispatch(ops);
this.notify();
this._notify();
return;
}
const ops = [];
const reverseOps = [];
const opId = this._doc.generateOpId();
const updateOp = {
opId,
id: this._id,
type: live_1.OpType.UpdateObject,
data: {},
};
ops.push(updateOp);
const reverseUpdateOp = {
id: this._id,
type: live_1.OpType.UpdateObject,
data: {},
};
reverseOps.push(reverseUpdateOp);
for (const key in overrides) {
__classPrivateFieldGet(this, _LiveObject_propToLastUpdate, "f").set(key, opId);
const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
if (oldValue instanceof AbstractCrdt) {
reverseOps.push(...oldValue._serialize(this._id, key));
oldValue._detach();
}
else if (oldValue === undefined) {
reverseOps.push({ type: live_1.OpType.DeleteObjectKey, id: this._id, key });
}
else {
reverseUpdateOp.data[key] = oldValue;
}
const newValue = overrides[key];
if (newValue instanceof AbstractCrdt) {
newValue._setParent(this);
newValue._setParentLink(this, key);
newValue._attach(this._doc.generateId(), this._doc);
ops.push(...newValue._serialize(this._id, key));
}
else {
updateOp.data[key] = newValue;
}
__classPrivateFieldGet(this, _LiveObject_map, "f").set(key, newValue);
}
this.notify();
this._doc.addToUndoStack(reverseOps);
this._doc.dispatch(ops);
this._notify();
}
}
exports.LiveObject = LiveObject;
_LiveObject_map = new WeakMap(), _LiveObject_propToLastUpdate = new WeakMap();
_LiveObject_map = new WeakMap(), _LiveObject_propToLastUpdate = new WeakMap(), _LiveObject_instances = new WeakSet(), _LiveObject_applyDeleteObjectKey = function _LiveObject_applyDeleteObjectKey(op) {
const key = op.key;
const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
let result = [];
if (isCrdt(oldValue)) {
result = oldValue._serialize(this._id, op.key);
oldValue._detach();
}
else if (oldValue !== undefined) {
result = [
{
type: live_1.OpType.UpdateObject,
id: this._id,
data: { [key]: oldValue },
},
];
}
__classPrivateFieldGet(this, _LiveObject_map, "f").delete(key);
this._notify();
return result;
};
/**
* The LiveMap class is similar to a JavaScript Map that is synchronized on all clients.
* Keys should be a string, and values should be serializable to JSON.
* If multiple clients update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.
*/
class LiveMap extends AbstractCrdt {

@@ -526,3 +663,3 @@ constructor(entries) {

const value = selfOrRegister(entry[1]);
value._setParent(this);
value._setParentLink(this, entry[0]);
mappedEntries.push([entry[0], value]);

@@ -578,3 +715,3 @@ }

const child = deserialize(entry, parentToChildren, doc);
child._setParent(map);
child._setParentLink(map, crdt.parentKey);
__classPrivateFieldGet(map, _LiveMap_map, "f").set(crdt.parentKey, child);

@@ -603,9 +740,15 @@ }

const previousValue = __classPrivateFieldGet(this, _LiveMap_map, "f").get(key);
let result;
if (previousValue) {
result = previousValue._serialize(this._id, key);
previousValue._detach();
}
child._setParent(this);
else {
result = [{ type: live_1.OpType.DeleteCrdt, id }];
}
child._setParentLink(this, key);
child._attach(id, this._doc);
__classPrivateFieldGet(this, _LiveMap_map, "f").set(key, child);
this.notify();
this._notify();
return result;
}

@@ -631,4 +774,9 @@ /**

child._detach();
this.notify();
this._notify();
}
/**
* Returns a specified element from the LiveMap.
* @param key The key of the element to return.
* @returns The element associated with the specified key, or undefined if the key can't be found in the LiveMap.
*/
get(key) {

@@ -641,2 +789,7 @@ const value = __classPrivateFieldGet(this, _LiveMap_map, "f").get(key);

}
/**
* Adds or updates an element with a specified key and a value.
* @param key The key of the element to add. Should be a string.
* @param value The value of the element to add. Should be serializable to JSON.
*/
set(key, value) {

@@ -648,17 +801,32 @@ const oldValue = __classPrivateFieldGet(this, _LiveMap_map, "f").get(key);

const item = selfOrRegister(value);
item._setParent(this);
item._setParentLink(this, key);
__classPrivateFieldGet(this, _LiveMap_map, "f").set(key, item);
if (this._doc && this._id) {
item._attach(this._doc.generateId(), this._doc);
const ops = item._serialize(this._id, key);
this._doc.dispatch(ops);
const id = this._doc.generateId();
item._attach(id, this._doc);
this._doc.addToUndoStack(oldValue
? oldValue._serialize(this._id, key)
: [{ type: live_1.OpType.DeleteCrdt, id }]);
this._doc.dispatch(item._serialize(this._id, key));
}
this.notify();
this._notify();
}
/**
* Returns the number of elements in the LiveMap.
*/
get size() {
return __classPrivateFieldGet(this, _LiveMap_map, "f").size;
}
/**
* Returns a boolean indicating whether an element with the specified key exists or not.
* @param key The key of the element to test for presence.
*/
has(key) {
return __classPrivateFieldGet(this, _LiveMap_map, "f").has(key);
}
/**
* Removes the specified element by key.
* @param key The key of the element to remove.
* @returns true if an element existed and has been removed, or false if the element does not exist.
*/
delete(key) {

@@ -671,8 +839,12 @@ const item = __classPrivateFieldGet(this, _LiveMap_map, "f").get(key);

if (this._doc && item._id) {
this._doc.addToUndoStack(item._serialize(this._id, key));
this._doc.dispatch([{ type: live_1.OpType.DeleteCrdt, id: item._id }]);
}
__classPrivateFieldGet(this, _LiveMap_map, "f").delete(key);
this.notify();
this._notify();
return true;
}
/**
* Returns a new Iterator object that contains the [key, value] pairs for each element.
*/
entries() {

@@ -699,8 +871,17 @@ const innerIterator = __classPrivateFieldGet(this, _LiveMap_map, "f").entries();

}
/**
* Same function object as the initial value of the entries method.
*/
[(_LiveMap_map = new WeakMap(), Symbol.iterator)]() {
return this.entries();
}
/**
* Returns a new Iterator object that contains the keys for each element.
*/
keys() {
return __classPrivateFieldGet(this, _LiveMap_map, "f").keys();
}
/**
* Returns a new Iterator object that contains the values for each element.
*/
values() {

@@ -726,2 +907,6 @@ const innerIterator = __classPrivateFieldGet(this, _LiveMap_map, "f").values();

}
/**
* Executes a provided function once per each key/value pair in the Map object, in insertion order.
* @param callback Function to execute for each entry in the map.
*/
forEach(callback) {

@@ -734,2 +919,5 @@ for (const entry of this) {

exports.LiveMap = LiveMap;
/**
* INTERNAL
*/
class LiveRegister extends AbstractCrdt {

@@ -778,4 +966,10 @@ constructor(data) {

}
_apply(op) {
return super._apply(op);
}
}
_LiveRegister_data = new WeakMap();
/**
* The LiveList class represents an ordered collection of items that is synchorinized across clients.
*/
class LiveList extends AbstractCrdt {

@@ -806,3 +1000,3 @@ constructor(items = []) {

const child = deserialize(entry, parentToChildren, doc);
child._setParent(list);
child._setParentLink(list, entry[1].parentKey);
__classPrivateFieldGet(list, _LiveList_items, "f").push([child, entry[1].parentKey]);

@@ -863,3 +1057,3 @@ __classPrivateFieldGet(list, _LiveList_items, "f").sort((itemA, itemB) => (0, position_1.compare)(itemA[1], itemB[1]));

child._attach(id, this._doc);
child._setParent(this);
child._setParentLink(this, key);
const index = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[1] === key);

@@ -872,3 +1066,4 @@ // Assign a temporary position until we get the fix from the backend

__classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => (0, position_1.compare)(itemA[1], itemB[1]));
this.notify();
this._notify();
return [{ type: live_1.OpType.DeleteCrdt, id }];
}

@@ -884,3 +1079,3 @@ /**

}
this.notify();
this._notify();
}

@@ -892,2 +1087,3 @@ /**

var _a;
child._setParentLink(this, key);
const index = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[1] === key);

@@ -903,21 +1099,29 @@ // Assign a temporary position until we get the fix from the backend

__classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => (0, position_1.compare)(itemA[1], itemB[1]));
this.notify();
this._notify();
}
/**
* INTERNAL
*/
_apply(op) {
return super._apply(op);
}
/**
* Returns the number of elements.
*/
get length() {
return __classPrivateFieldGet(this, _LiveList_items, "f").length;
}
push(item) {
const position = __classPrivateFieldGet(this, _LiveList_items, "f").length === 0
? (0, position_1.makePosition)()
: (0, position_1.makePosition)(__classPrivateFieldGet(this, _LiveList_items, "f")[__classPrivateFieldGet(this, _LiveList_items, "f").length - 1][1]);
const value = selfOrRegister(item);
value._setParent(this);
__classPrivateFieldGet(this, _LiveList_items, "f").push([value, position]);
this.notify();
if (this._doc && this._id) {
value._attach(this._doc.generateId(), this._doc);
this._doc.dispatch(value._serialize(this._id, position));
}
/**
* Adds one element to the end of the LiveList.
* @param element The element to add to the end of the LiveList.
*/
push(element) {
return this.insert(element, this.length);
}
insert(item, index) {
/**
* Inserts one element at a specified index.
* @param element The element to insert.
* @param index The index at which you want to insert the element.
*/
insert(element, index) {
if (index < 0 || index > __classPrivateFieldGet(this, _LiveList_items, "f").length) {

@@ -929,12 +1133,19 @@ throw new Error(`Cannot delete list item at index "${index}". index should be between 0 and ${__classPrivateFieldGet(this, _LiveList_items, "f").length}`);

const position = (0, position_1.makePosition)(before, after);
const value = selfOrRegister(item);
value._setParent(this);
const value = selfOrRegister(element);
value._setParentLink(this, position);
__classPrivateFieldGet(this, _LiveList_items, "f").push([value, position]);
__classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => (0, position_1.compare)(itemA[1], itemB[1]));
this.notify();
this._notify();
if (this._doc && this._id) {
value._attach(this._doc.generateId(), this._doc);
const id = this._doc.generateId();
value._attach(id, this._doc);
this._doc.addToUndoStack([{ type: live_1.OpType.DeleteCrdt, id }]);
this._doc.dispatch(value._serialize(this._id, position));
}
}
/**
* Move one element from one index to another.
* @param index The index of the element to move
* @param targetIndex The index where the element should be after moving.
*/
move(index, targetIndex) {

@@ -969,6 +1180,15 @@ if (targetIndex < 0) {

const item = __classPrivateFieldGet(this, _LiveList_items, "f")[index];
const previousPosition = item[1];
item[1] = position;
item[0]._setParentLink(this, position);
__classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => (0, position_1.compare)(itemA[1], itemB[1]));
this.notify();
this._notify();
if (this._doc && this._id) {
this._doc.addToUndoStack([
{
type: live_1.OpType.SetParentKey,
id: item[0]._id,
parentKey: previousPosition,
},
]);
this._doc.dispatch([

@@ -983,2 +1203,6 @@ {

}
/**
* Deletes an element at the specified index
* @param index The index of the element to delete
*/
delete(index) {

@@ -994,2 +1218,3 @@ if (index < 0 || index >= __classPrivateFieldGet(this, _LiveList_items, "f").length) {

if (childRecordId) {
this._doc.addToUndoStack(item[0]._serialize(this._id, item[1]));
this._doc.dispatch([

@@ -1003,22 +1228,54 @@ {

}
this.notify();
this._notify();
}
/**
* Returns an Array of all the elements in the LiveList.
*/
toArray() {
return __classPrivateFieldGet(this, _LiveList_items, "f").map((entry) => selfOrRegisterValue(entry[0]));
}
/**
* Tests whether all elements pass the test implemented by the provided function.
* @param predicate Function to test for each element, taking two arguments (the element and its index).
* @returns true if the predicate function returns a truthy value for every element. Otherwise, false.
*/
every(predicate) {
return this.toArray().every(predicate);
}
/**
* Creates an array with all elements that pass the test implemented by the provided function.
* @param predicate Function to test each element of the LiveList. Return a value that coerces to true to keep the element, or to false otherwise.
* @returns An array with the elements that pass the test.
*/
filter(predicate) {
return this.toArray().filter(predicate);
}
/**
* Returns the first element that satisfies the provided testing function.
* @param predicate Function to execute on each value.
* @returns The value of the first element in the LiveList that satisfies the provided testing function. Otherwise, undefined is returned.
*/
find(predicate) {
return this.toArray().find(predicate);
}
/**
* Returns the index of the first element in the LiveList that satisfies the provided testing function.
* @param predicate Function to execute on each value until the function returns true, indicating that the satisfying element was found.
* @returns The index of the first element in the LiveList that passes the test. Otherwise, -1.
*/
findIndex(predicate) {
return this.toArray().findIndex(predicate);
}
/**
* Executes a provided function once for each element.
* @param callbackfn Function to execute on each element.
*/
forEach(callbackfn) {
return this.toArray().forEach(callbackfn);
}
/**
* Get the element at the specified index.
* @param index The index on the element to get.
* @returns The element at the specified index or undefined.
*/
get(index) {

@@ -1030,11 +1287,33 @@ if (index < 0 || index >= __classPrivateFieldGet(this, _LiveList_items, "f").length) {

}
/**
* Returns the first index at which a given element can be found in the LiveList, or -1 if it is not present.
* @param searchElement Element to locate.
* @param fromIndex The index to start the search at.
* @returns The first index of the element in the LiveList; -1 if not found.
*/
indexOf(searchElement, fromIndex) {
return this.toArray().indexOf(searchElement, fromIndex);
}
/**
* Returns the last index at which a given element can be found in the LiveList, or -1 if it is not present. The LiveLsit is searched backwards, starting at fromIndex.
* @param searchElement Element to locate.
* @param fromIndex The index at which to start searching backwards.
* @returns
*/
lastIndexOf(searchElement, fromIndex) {
return this.toArray().lastIndexOf(searchElement, fromIndex);
}
/**
* Creates an array populated with the results of calling a provided function on every element.
* @param callback Function that is called for every element.
* @returns An array with each element being the result of the callback function.
*/
map(callback) {
return __classPrivateFieldGet(this, _LiveList_items, "f").map((entry, i) => callback(selfOrRegisterValue(entry[0]), i));
}
/**
* Tests whether at least one element in the LiveList passes the test implemented by the provided function.
* @param predicate Function to test for each element.
* @returns true if the callback function returns a truthy value for at least one element. Otherwise, false.
*/
some(predicate) {

@@ -1041,0 +1320,0 @@ return this.toArray().some(predicate);

@@ -117,3 +117,3 @@ import { Presence } from "./types";

export declare type UpdateObjectOp = {
opId: string;
opId?: string;
id: string;

@@ -120,0 +120,0 @@ type: OpType.UpdateObject;

@@ -84,2 +84,4 @@ import { Others, Presence, ClientOptions, Room, MyPresenceCallback, OthersEventCallback, AuthEndpoint, EventCallback, User, Connection, ErrorCallback, AuthenticationToken, ConnectionCallback } from "./types";

broadcastEvent: (event: any) => void;
undo: () => void;
redo: () => void;
getStorage: <TRoot>() => Promise<{

@@ -86,0 +88,0 @@ root: import("./doc").LiveObject<TRoot>;

@@ -503,2 +503,8 @@ "use strict";

}
function undo() {
storage.undo();
}
function redo() {
storage.redo();
}
return {

@@ -522,2 +528,4 @@ // Internal

broadcastEvent,
undo,
redo,
getStorage,

@@ -605,2 +613,4 @@ selectors: {

getStorage: machine.getStorage,
undo: machine.undo,
redo: machine.redo,
};

@@ -607,0 +617,0 @@ return {

@@ -19,2 +19,4 @@ import { Doc as Doc } from "./doc";

onMessage(message: ServerMessage): Promise<void>;
undo(): void;
redo(): void;
}

@@ -53,5 +53,3 @@ "use strict";

case live_1.ServerMessageType.UpdateStorage: {
for (const op of message.ops) {
(_b = this._doc) === null || _b === void 0 ? void 0 : _b.apply(op);
}
(_b = this._doc) === null || _b === void 0 ? void 0 : _b.apply(message.ops);
break;

@@ -62,3 +60,11 @@ }

}
undo() {
var _a;
(_a = this._doc) === null || _a === void 0 ? void 0 : _a.undo();
}
redo() {
var _a;
(_a = this._doc) === null || _a === void 0 ? void 0 : _a.redo();
}
}
exports.default = Storage;

@@ -269,3 +269,5 @@ import { LiveObject } from "./doc";

}>;
undo: () => void;
redo: () => void;
};
export {};

@@ -12,4 +12,7 @@ import { Op, SerializedCrdtWithId, SerializedList } from "./live";

getItem(id: string): AbstractCrdt | undefined;
apply(op: Op): void;
apply(ops: Op[]): Op[];
get root(): LiveObject<T>;
addToUndoStack(ops: Op[]): void;
undo(): void;
redo(): void;
count(): number;

@@ -36,8 +39,13 @@ generateId(): string;

*/
_setParent(parent: AbstractCrdt): void;
get _parentKey(): string | undefined;
_apply(op: Op): Op[];
/**
* INTERNAL
*/
_setParentLink(parent: AbstractCrdt, key: string): void;
/**
* INTERNAL
*/
_attach(id: string, doc: Doc): void;
abstract _attachChild(id: string, key: string, crdt: AbstractCrdt): void;
abstract _attachChild(id: string, key: string, crdt: AbstractCrdt): Op[];
/**

@@ -48,9 +56,29 @@ * INTERNAL

abstract _detachChild(crdt: AbstractCrdt): void;
/**
* Subscribes to updates.
*/
subscribe(listener: () => void): void;
/**
* Subscribes to updates and children updates.
*/
subscribeDeep(listener: () => void): void;
/**
* Unsubscribes to updates.
*/
unsubscribe(listener: () => void): void;
/**
* Unsubscribes to updates and children updates.
*/
unsubscribeDeep(listener: () => void): void;
notify(onlyDeep?: boolean): void;
/**
* INTERNAL
*/
_notify(onlyDeep?: boolean): void;
abstract _serialize(parentId: string, parentKey: string): Op[];
}
/**
* The LiveObject class is similar to a JavaScript object that is synchronized on all clients.
* Keys should be a string, and values should be serializable to JSON.
* If multiple clients update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.
*/
export declare class LiveObject<T extends Record<string, any> = Record<string, any>> extends AbstractCrdt {

@@ -76,3 +104,3 @@ #private;

*/
_attachChild(id: string, key: keyof T, child: AbstractCrdt): void;
_attachChild(id: string, key: keyof T, child: AbstractCrdt): Op[];
/**

@@ -89,8 +117,29 @@ * INTERNAL

*/
_apply(op: Op): void;
_apply(op: Op): Op[];
/**
* Transform the LiveObject into a javascript object
*/
toObject(): T;
/**
* Adds or updates a property with a specified key and a value.
* @param key The key of the property to add
* @param value The value of the property to add
*/
set<TKey extends keyof T>(key: TKey, value: T[TKey]): void;
/**
* Returns a specified property from the LiveObject.
* @param key The key of the property to get
*/
get<TKey extends keyof T>(key: TKey): T[TKey];
/**
* Adds or updates multiple properties at once with an object.
* @param overrides The object used to overrides properties
*/
update(overrides: Partial<T>): void;
}
/**
* The LiveMap class is similar to a JavaScript Map that is synchronized on all clients.
* Keys should be a string, and values should be serializable to JSON.
* If multiple clients update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.
*/
export declare class LiveMap<TKey extends string, TValue> extends AbstractCrdt {

@@ -114,3 +163,3 @@ #private;

*/
_attachChild(id: string, key: TKey, child: AbstractCrdt): void;
_attachChild(id: string, key: TKey, child: AbstractCrdt): Op[];
/**

@@ -124,13 +173,54 @@ * INTERNAL

_detachChild(child: AbstractCrdt): void;
/**
* Returns a specified element from the LiveMap.
* @param key The key of the element to return.
* @returns The element associated with the specified key, or undefined if the key can't be found in the LiveMap.
*/
get(key: TKey): TValue | undefined;
/**
* Adds or updates an element with a specified key and a value.
* @param key The key of the element to add. Should be a string.
* @param value The value of the element to add. Should be serializable to JSON.
*/
set(key: TKey, value: TValue): void;
/**
* Returns the number of elements in the LiveMap.
*/
get size(): number;
/**
* Returns a boolean indicating whether an element with the specified key exists or not.
* @param key The key of the element to test for presence.
*/
has(key: TKey): boolean;
/**
* Removes the specified element by key.
* @param key The key of the element to remove.
* @returns true if an element existed and has been removed, or false if the element does not exist.
*/
delete(key: TKey): boolean;
/**
* Returns a new Iterator object that contains the [key, value] pairs for each element.
*/
entries(): IterableIterator<[string, TValue]>;
/**
* Same function object as the initial value of the entries method.
*/
[Symbol.iterator](): IterableIterator<[string, TValue]>;
/**
* Returns a new Iterator object that contains the keys for each element.
*/
keys(): IterableIterator<TKey>;
/**
* Returns a new Iterator object that contains the values for each element.
*/
values(): IterableIterator<TValue>;
/**
* Executes a provided function once per each key/value pair in the Map object, in insertion order.
* @param callback Function to execute for each entry in the map.
*/
forEach(callback: (value: TValue, key: TKey, map: LiveMap<TKey, TValue>) => void): void;
}
/**
* The LiveList class represents an ordered collection of items that is synchorinized across clients.
*/
export declare class LiveList<T> extends AbstractCrdt {

@@ -158,3 +248,3 @@ #private;

*/
_attachChild(id: string, key: string, child: AbstractCrdt): void;
_attachChild(id: string, key: string, child: AbstractCrdt): Op[];
/**

@@ -168,17 +258,96 @@ * INTERNAL

_setChildKey(key: string, child: AbstractCrdt): void;
/**
* INTERNAL
*/
_apply(op: Op): Op[];
/**
* Returns the number of elements.
*/
get length(): number;
push(item: T): void;
insert(item: T, index: number): void;
/**
* Adds one element to the end of the LiveList.
* @param element The element to add to the end of the LiveList.
*/
push(element: T): void;
/**
* Inserts one element at a specified index.
* @param element The element to insert.
* @param index The index at which you want to insert the element.
*/
insert(element: T, index: number): void;
/**
* Move one element from one index to another.
* @param index The index of the element to move
* @param targetIndex The index where the element should be after moving.
*/
move(index: number, targetIndex: number): void;
/**
* Deletes an element at the specified index
* @param index The index of the element to delete
*/
delete(index: number): void;
/**
* Returns an Array of all the elements in the LiveList.
*/
toArray(): T[];
/**
* Tests whether all elements pass the test implemented by the provided function.
* @param predicate Function to test for each element, taking two arguments (the element and its index).
* @returns true if the predicate function returns a truthy value for every element. Otherwise, false.
*/
every(predicate: (value: T, index: number) => unknown): boolean;
/**
* Creates an array with all elements that pass the test implemented by the provided function.
* @param predicate Function to test each element of the LiveList. Return a value that coerces to true to keep the element, or to false otherwise.
* @returns An array with the elements that pass the test.
*/
filter(predicate: (value: T, index: number) => unknown): T[];
/**
* Returns the first element that satisfies the provided testing function.
* @param predicate Function to execute on each value.
* @returns The value of the first element in the LiveList that satisfies the provided testing function. Otherwise, undefined is returned.
*/
find(predicate: (value: T, index: number) => unknown): T | undefined;
/**
* Returns the index of the first element in the LiveList that satisfies the provided testing function.
* @param predicate Function to execute on each value until the function returns true, indicating that the satisfying element was found.
* @returns The index of the first element in the LiveList that passes the test. Otherwise, -1.
*/
findIndex(predicate: (value: T, index: number) => unknown): number;
/**
* Executes a provided function once for each element.
* @param callbackfn Function to execute on each element.
*/
forEach(callbackfn: (value: T, index: number) => void): void;
/**
* Get the element at the specified index.
* @param index The index on the element to get.
* @returns The element at the specified index or undefined.
*/
get(index: number): T | undefined;
/**
* Returns the first index at which a given element can be found in the LiveList, or -1 if it is not present.
* @param searchElement Element to locate.
* @param fromIndex The index to start the search at.
* @returns The first index of the element in the LiveList; -1 if not found.
*/
indexOf(searchElement: T, fromIndex?: number): number;
/**
* Returns the last index at which a given element can be found in the LiveList, or -1 if it is not present. The LiveLsit is searched backwards, starting at fromIndex.
* @param searchElement Element to locate.
* @param fromIndex The index at which to start searching backwards.
* @returns
*/
lastIndexOf(searchElement: T, fromIndex?: number): number;
/**
* Creates an array populated with the results of calling a provided function on every element.
* @param callback Function that is called for every element.
* @returns An array with each element being the result of the callback function.
*/
map<U>(callback: (value: T, index: number) => U): U[];
/**
* Tests whether at least one element in the LiveList passes the test implemented by the provided function.
* @param predicate Function to test for each element.
* @returns true if the callback function returns a truthy value for at least one element. Otherwise, false.
*/
some(predicate: (value: T, index: number) => unknown): boolean;

@@ -185,0 +354,0 @@ [Symbol.iterator](): IterableIterator<T>;

@@ -12,3 +12,3 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {

};
var _Doc_instances, _Doc_clock, _Doc_opClock, _Doc_items, _Doc_root, _Doc_actor, _Doc_dispatch, _Doc_applyCreateRegister, _Doc_applyDeleteRecordKey, _Doc_applyUpdateRecord, _Doc_applyCreateMap, _Doc_applyCreateList, _Doc_applyCreateObject, _Doc_applyDeleteRecord, _Doc_applySetParentKey, _AbstractCrdt_listeners, _AbstractCrdt_deepListeners, _AbstractCrdt_parent, _AbstractCrdt_doc, _AbstractCrdt_id, _LiveObject_map, _LiveObject_propToLastUpdate, _LiveMap_map, _LiveRegister_data, _LiveList_items, _LiveListIterator_innerIterator;
var _Doc_instances, _Doc_clock, _Doc_opClock, _Doc_items, _Doc_root, _Doc_actor, _Doc_dispatch, _Doc_undoStack, _Doc_redoStack, _Doc_applyOp, _AbstractCrdt_instances, _AbstractCrdt_listeners, _AbstractCrdt_deepListeners, _AbstractCrdt_parent, _AbstractCrdt_doc, _AbstractCrdt_id, _AbstractCrdt_parentKey, _AbstractCrdt_applySetParentKey, _AbstractCrdt_applyRegister, _AbstractCrdt_applyCreateObject, _AbstractCrdt_applyCreateMap, _AbstractCrdt_applyCreateList, _LiveObject_instances, _LiveObject_map, _LiveObject_propToLastUpdate, _LiveObject_applyDeleteObjectKey, _LiveMap_map, _LiveRegister_data, _LiveList_items, _LiveListIterator_innerIterator;
import { remove } from "./utils";

@@ -18,2 +18,3 @@ import { CrdtType, OpType, } from "./live";

function noOp() { }
const MAX_UNDO_STACK = 50;
export class Doc {

@@ -28,2 +29,4 @@ constructor(root, actor = 0, dispatch = noOp) {

_Doc_dispatch.set(this, void 0);
_Doc_undoStack.set(this, []);
_Doc_redoStack.set(this, []);
__classPrivateFieldSet(this, _Doc_root, root, "f");

@@ -69,2 +72,3 @@ __classPrivateFieldSet(this, _Doc_actor, actor, "f");

dispatch(ops) {
__classPrivateFieldSet(this, _Doc_redoStack, [], "f");
__classPrivateFieldGet(this, _Doc_dispatch, "f").call(this, ops);

@@ -81,37 +85,8 @@ }

}
apply(op) {
switch (op.type) {
case OpType.UpdateObject: {
__classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyUpdateRecord).call(this, op);
break;
}
case OpType.CreateObject: {
__classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyCreateObject).call(this, op);
break;
}
case OpType.CreateMap: {
__classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyCreateMap).call(this, op);
break;
}
case OpType.CreateList: {
__classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyCreateList).call(this, op);
break;
}
case OpType.DeleteCrdt: {
__classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyDeleteRecord).call(this, op);
break;
}
case OpType.SetParentKey: {
__classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applySetParentKey).call(this, op);
break;
}
case OpType.DeleteObjectKey: {
__classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyDeleteRecordKey).call(this, op);
break;
}
case OpType.CreateRegister: {
__classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyCreateRegister).call(this, op);
break;
}
apply(ops) {
const reverse = [];
for (const op of ops) {
reverse.push(...__classPrivateFieldGet(this, _Doc_instances, "m", _Doc_applyOp).call(this, op));
}
return reverse;
}

@@ -121,2 +96,24 @@ get root() {

}
addToUndoStack(ops) {
if (__classPrivateFieldGet(this, _Doc_undoStack, "f").length >= MAX_UNDO_STACK) {
__classPrivateFieldGet(this, _Doc_undoStack, "f").shift();
}
__classPrivateFieldGet(this, _Doc_undoStack, "f").push(ops);
}
undo() {
const ops = __classPrivateFieldGet(this, _Doc_undoStack, "f").pop();
if (ops == null) {
return;
}
__classPrivateFieldGet(this, _Doc_redoStack, "f").push(this.apply(ops));
__classPrivateFieldGet(this, _Doc_dispatch, "f").call(this, ops);
}
redo() {
const ops = __classPrivateFieldGet(this, _Doc_redoStack, "f").pop();
if (ops == null) {
return;
}
__classPrivateFieldGet(this, _Doc_undoStack, "f").push(this.apply(ops));
__classPrivateFieldGet(this, _Doc_dispatch, "f").call(this, ops);
}
count() {

@@ -134,83 +131,32 @@ return __classPrivateFieldGet(this, _Doc_items, "f").size;

}
_Doc_clock = new WeakMap(), _Doc_opClock = new WeakMap(), _Doc_items = new WeakMap(), _Doc_root = new WeakMap(), _Doc_actor = new WeakMap(), _Doc_dispatch = new WeakMap(), _Doc_instances = new WeakSet(), _Doc_applyCreateRegister = function _Doc_applyCreateRegister(op) {
if (__classPrivateFieldGet(this, _Doc_items, "f").has(op.id)) {
return;
}
const parent = __classPrivateFieldGet(this, _Doc_items, "f").get(op.parentId);
if (parent == null) {
return;
}
if (!(parent instanceof LiveMap) && !(parent instanceof LiveList)) {
throw new Error("LiveRegister can only be attached to a LiveMap or LiveList");
}
const newRegister = new LiveRegister(op.data);
parent._attachChild(op.id, op.parentKey, newRegister);
}, _Doc_applyDeleteRecordKey = function _Doc_applyDeleteRecordKey(op) {
const item = __classPrivateFieldGet(this, _Doc_items, "f").get(op.id);
if (item && item instanceof LiveObject) {
item._apply(op);
}
}, _Doc_applyUpdateRecord = function _Doc_applyUpdateRecord(op) {
const item = __classPrivateFieldGet(this, _Doc_items, "f").get(op.id);
if (item && item instanceof LiveObject) {
item._apply(op);
}
}, _Doc_applyCreateMap = function _Doc_applyCreateMap(op) {
if (__classPrivateFieldGet(this, _Doc_items, "f").has(op.id)) {
return;
}
const parent = __classPrivateFieldGet(this, _Doc_items, "f").get(op.parentId);
if (parent == null) {
return;
}
const newMap = new LiveMap();
parent._attachChild(op.id, op.parentKey, newMap);
}, _Doc_applyCreateList = function _Doc_applyCreateList(op) {
if (__classPrivateFieldGet(this, _Doc_items, "f").has(op.id)) {
return;
}
const parent = __classPrivateFieldGet(this, _Doc_items, "f").get(op.parentId);
if (parent == null) {
return;
}
const list = new LiveList();
parent._attachChild(op.id, op.parentKey, list);
}, _Doc_applyCreateObject = function _Doc_applyCreateObject(op) {
if (__classPrivateFieldGet(this, _Doc_items, "f").has(op.id)) {
return;
}
if (op.parentId && op.parentKey) {
const parent = __classPrivateFieldGet(this, _Doc_items, "f").get(op.parentId);
if (parent == null) {
return;
_Doc_clock = new WeakMap(), _Doc_opClock = new WeakMap(), _Doc_items = new WeakMap(), _Doc_root = new WeakMap(), _Doc_actor = new WeakMap(), _Doc_dispatch = new WeakMap(), _Doc_undoStack = new WeakMap(), _Doc_redoStack = new WeakMap(), _Doc_instances = new WeakSet(), _Doc_applyOp = function _Doc_applyOp(op) {
switch (op.type) {
case OpType.DeleteObjectKey:
case OpType.UpdateObject:
case OpType.DeleteCrdt:
case OpType.SetParentKey: {
const item = __classPrivateFieldGet(this, _Doc_items, "f").get(op.id);
if (item == null) {
return [];
}
return item._apply(op);
break;
}
const newObj = new LiveObject(op.data);
parent._attachChild(op.id, op.parentKey, newObj);
case OpType.CreateList:
case OpType.CreateObject:
case OpType.CreateMap:
case OpType.CreateRegister: {
const parent = __classPrivateFieldGet(this, _Doc_items, "f").get(op.parentId);
if (parent == null) {
return [];
}
return parent._apply(op);
break;
}
}
}, _Doc_applyDeleteRecord = function _Doc_applyDeleteRecord(op) {
const item = __classPrivateFieldGet(this, _Doc_items, "f").get(op.id);
if (item == null) {
return;
}
const parent = item._parent;
if (parent == null) {
return;
}
if (parent) {
parent._detachChild(item);
}
}, _Doc_applySetParentKey = function _Doc_applySetParentKey(op) {
const item = __classPrivateFieldGet(this, _Doc_items, "f").get(op.id);
if (item == null) {
return;
}
if (item._parent == null) {
return;
}
if (item._parent instanceof LiveList) {
item._parent._setChildKey(op.parentKey, item);
}
return [];
};
class AbstractCrdt {
constructor() {
_AbstractCrdt_instances.add(this);
_AbstractCrdt_listeners.set(this, []);

@@ -221,2 +167,3 @@ _AbstractCrdt_deepListeners.set(this, []);

_AbstractCrdt_id.set(this, void 0);
_AbstractCrdt_parentKey.set(this, void 0);
}

@@ -244,6 +191,41 @@ /**

*/
_setParent(parent) {
if (__classPrivateFieldGet(this, _AbstractCrdt_parent, "f")) {
get _parentKey() {
return __classPrivateFieldGet(this, _AbstractCrdt_parentKey, "f");
}
_apply(op) {
switch (op.type) {
case OpType.DeleteCrdt: {
if (this._parent != null && this._parentKey != null) {
const reverse = this._serialize(this._parent._id, this._parentKey);
this._parent._detachChild(this);
return reverse;
}
return [];
}
case OpType.CreateObject: {
return __classPrivateFieldGet(this, _AbstractCrdt_instances, "m", _AbstractCrdt_applyCreateObject).call(this, op);
}
case OpType.CreateMap: {
return __classPrivateFieldGet(this, _AbstractCrdt_instances, "m", _AbstractCrdt_applyCreateMap).call(this, op);
}
case OpType.CreateRegister: {
return __classPrivateFieldGet(this, _AbstractCrdt_instances, "m", _AbstractCrdt_applyRegister).call(this, op);
}
case OpType.CreateList: {
return __classPrivateFieldGet(this, _AbstractCrdt_instances, "m", _AbstractCrdt_applyCreateList).call(this, op);
}
case OpType.SetParentKey: {
return __classPrivateFieldGet(this, _AbstractCrdt_instances, "m", _AbstractCrdt_applySetParentKey).call(this, op);
}
}
return [];
}
/**
* INTERNAL
*/
_setParentLink(parent, key) {
if (__classPrivateFieldGet(this, _AbstractCrdt_parent, "f") != null && __classPrivateFieldGet(this, _AbstractCrdt_parent, "f") !== parent) {
throw new Error("Cannot attach parent if it already exist");
}
__classPrivateFieldSet(this, _AbstractCrdt_parentKey, key, "f");
__classPrivateFieldSet(this, _AbstractCrdt_parent, parent, "f");

@@ -272,15 +254,30 @@ }

}
/**
* Subscribes to updates.
*/
subscribe(listener) {
__classPrivateFieldGet(this, _AbstractCrdt_listeners, "f").push(listener);
}
/**
* Subscribes to updates and children updates.
*/
subscribeDeep(listener) {
__classPrivateFieldGet(this, _AbstractCrdt_deepListeners, "f").push(listener);
}
/**
* Unsubscribes to updates.
*/
unsubscribe(listener) {
remove(__classPrivateFieldGet(this, _AbstractCrdt_listeners, "f"), listener);
}
/**
* Unsubscribes to updates and children updates.
*/
unsubscribeDeep(listener) {
remove(__classPrivateFieldGet(this, _AbstractCrdt_deepListeners, "f"), listener);
}
notify(onlyDeep = false) {
/**
* INTERNAL
*/
_notify(onlyDeep = false) {
if (onlyDeep === false) {

@@ -295,10 +292,60 @@ for (const listener of __classPrivateFieldGet(this, _AbstractCrdt_listeners, "f")) {

if (this._parent) {
this._parent.notify(true);
this._parent._notify(true);
}
}
}
_AbstractCrdt_listeners = new WeakMap(), _AbstractCrdt_deepListeners = new WeakMap(), _AbstractCrdt_parent = new WeakMap(), _AbstractCrdt_doc = new WeakMap(), _AbstractCrdt_id = new WeakMap();
_AbstractCrdt_listeners = new WeakMap(), _AbstractCrdt_deepListeners = new WeakMap(), _AbstractCrdt_parent = new WeakMap(), _AbstractCrdt_doc = new WeakMap(), _AbstractCrdt_id = new WeakMap(), _AbstractCrdt_parentKey = new WeakMap(), _AbstractCrdt_instances = new WeakSet(), _AbstractCrdt_applySetParentKey = function _AbstractCrdt_applySetParentKey(op) {
if (this._parent == null) {
return [];
}
if (this._parent instanceof LiveList) {
const previousKey = this._parentKey;
this._parent._setChildKey(op.parentKey, this);
return [
{ type: OpType.SetParentKey, id: this._id, parentKey: previousKey },
];
}
return [];
}, _AbstractCrdt_applyRegister = function _AbstractCrdt_applyRegister(op) {
if (this._doc == null) {
throw new Error("Internal: doc should exist");
}
if (this._doc.getItem(op.id) != null) {
return [];
}
return this._attachChild(op.id, op.parentKey, new LiveRegister(op.data));
}, _AbstractCrdt_applyCreateObject = function _AbstractCrdt_applyCreateObject(op) {
if (this._doc == null) {
throw new Error("Internal: doc should exist");
}
if (this._doc.getItem(op.id) != null) {
return [];
}
return this._attachChild(op.id, op.parentKey, new LiveObject(op.data));
}, _AbstractCrdt_applyCreateMap = function _AbstractCrdt_applyCreateMap(op) {
if (this._doc == null) {
throw new Error("Internal: doc should exist");
}
if (this._doc.getItem(op.id) != null) {
return [];
}
return this._attachChild(op.id, op.parentKey, new LiveMap());
}, _AbstractCrdt_applyCreateList = function _AbstractCrdt_applyCreateList(op) {
if (this._doc == null) {
throw new Error("Internal: doc should exist");
}
if (this._doc.getItem(op.id) != null) {
return [];
}
return this._attachChild(op.id, op.parentKey, new LiveList());
};
/**
* The LiveObject class is similar to a JavaScript object that is synchronized on all clients.
* Keys should be a string, and values should be serializable to JSON.
* If multiple clients update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.
*/
export class LiveObject extends AbstractCrdt {
constructor(object = {}) {
super();
_LiveObject_instances.add(this);
_LiveObject_map.set(this, void 0);

@@ -309,3 +356,3 @@ _LiveObject_propToLastUpdate.set(this, new Map());

if (value instanceof AbstractCrdt) {
value._setParent(this);
value._setParentLink(this, key);
}

@@ -360,3 +407,3 @@ }

const child = deserialize(entry, parentToChildren, doc);
child._setParent(object);
child._setParentLink(object, crdt.parentKey);
__classPrivateFieldGet(object, _LiveObject_map, "f").set(crdt.parentKey, child);

@@ -385,9 +432,26 @@ }

const previousValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
let result;
if (isCrdt(previousValue)) {
result = previousValue._serialize(this._id, key);
previousValue._detach();
}
else if (previousValue === undefined) {
result = [
{ type: OpType.DeleteObjectKey, id: this._id, key: key },
];
}
else {
result = [
{
type: OpType.UpdateObject,
id: this._id,
data: { [key]: previousValue },
},
];
}
__classPrivateFieldGet(this, _LiveObject_map, "f").set(key, child);
child._setParent(this);
child._setParentLink(this, key);
child._attach(id, this._doc);
this.notify();
this._notify();
return result;
}

@@ -406,3 +470,3 @@ /**

}
this.notify();
this._notify();
}

@@ -424,7 +488,28 @@ /**

_apply(op) {
var _a;
if (op.type === OpType.UpdateObject) {
const reverse = [];
const reverseUpdate = {
type: OpType.UpdateObject,
id: this._id,
data: {},
};
reverse.push(reverseUpdate);
for (const key in op.data) {
const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
if (oldValue !== undefined) {
reverseUpdate.data[key] = oldValue;
}
else if (oldValue === undefined) {
reverse.push({ type: OpType.DeleteObjectKey, id: this._id, key });
}
}
for (const key in op.data) {
if (op.opId == null) {
op.opId = (_a = this._doc) === null || _a === void 0 ? void 0 : _a.generateOpId();
}
const lastOpId = __classPrivateFieldGet(this, _LiveObject_propToLastUpdate, "f").get(key);
if (lastOpId === op.opId) {
__classPrivateFieldGet(this, _LiveObject_propToLastUpdate, "f").delete(key);
continue;
}

@@ -441,17 +526,21 @@ else if (lastOpId != null) {

}
this.notify();
this._notify();
return reverse;
}
else if (op.type === OpType.DeleteObjectKey) {
const key = op.key;
const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
if (isCrdt(oldValue)) {
oldValue._detach();
}
__classPrivateFieldGet(this, _LiveObject_map, "f").delete(key);
this.notify();
return __classPrivateFieldGet(this, _LiveObject_instances, "m", _LiveObject_applyDeleteObjectKey).call(this, op);
}
return super._apply(op);
}
/**
* Transform the LiveObject into a javascript object
*/
toObject() {
return Object.fromEntries(__classPrivateFieldGet(this, _LiveObject_map, "f"));
}
/**
* Adds or updates a property with a specified key and a value.
* @param key The key of the property to add
* @param value The value of the property to add
*/
set(key, value) {

@@ -461,20 +550,18 @@ // TODO: Find out why typescript complains

}
/**
* Returns a specified property from the LiveObject.
* @param key The key of the property to get
*/
get(key) {
return __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
}
/**
* Adds or updates multiple properties at once with an object.
* @param overrides The object used to overrides properties
*/
update(overrides) {
if (this._doc && this._id) {
const ops = [];
const opId = this._doc.generateOpId();
const updateOp = {
opId,
id: this._id,
type: OpType.UpdateObject,
data: {},
};
ops.push(updateOp);
if (this._doc == null || this._id == null) {
for (const key in overrides) {
__classPrivateFieldGet(this, _LiveObject_propToLastUpdate, "f").set(key, opId);
const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
if (oldValue instanceof LiveObject) {
if (oldValue instanceof AbstractCrdt) {
oldValue._detach();

@@ -484,30 +571,80 @@ }

if (newValue instanceof AbstractCrdt) {
newValue._setParent(this);
newValue._attach(this._doc.generateId(), this._doc);
ops.push(...newValue._serialize(this._id, key));
newValue._setParentLink(this, key);
}
else {
updateOp.data[key] = newValue;
}
__classPrivateFieldGet(this, _LiveObject_map, "f").set(key, newValue);
}
this._doc.dispatch(ops);
this.notify();
this._notify();
return;
}
const ops = [];
const reverseOps = [];
const opId = this._doc.generateOpId();
const updateOp = {
opId,
id: this._id,
type: OpType.UpdateObject,
data: {},
};
ops.push(updateOp);
const reverseUpdateOp = {
id: this._id,
type: OpType.UpdateObject,
data: {},
};
reverseOps.push(reverseUpdateOp);
for (const key in overrides) {
__classPrivateFieldGet(this, _LiveObject_propToLastUpdate, "f").set(key, opId);
const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
if (oldValue instanceof AbstractCrdt) {
reverseOps.push(...oldValue._serialize(this._id, key));
oldValue._detach();
}
else if (oldValue === undefined) {
reverseOps.push({ type: OpType.DeleteObjectKey, id: this._id, key });
}
else {
reverseUpdateOp.data[key] = oldValue;
}
const newValue = overrides[key];
if (newValue instanceof AbstractCrdt) {
newValue._setParent(this);
newValue._setParentLink(this, key);
newValue._attach(this._doc.generateId(), this._doc);
ops.push(...newValue._serialize(this._id, key));
}
else {
updateOp.data[key] = newValue;
}
__classPrivateFieldGet(this, _LiveObject_map, "f").set(key, newValue);
}
this.notify();
this._doc.addToUndoStack(reverseOps);
this._doc.dispatch(ops);
this._notify();
}
}
_LiveObject_map = new WeakMap(), _LiveObject_propToLastUpdate = new WeakMap();
_LiveObject_map = new WeakMap(), _LiveObject_propToLastUpdate = new WeakMap(), _LiveObject_instances = new WeakSet(), _LiveObject_applyDeleteObjectKey = function _LiveObject_applyDeleteObjectKey(op) {
const key = op.key;
const oldValue = __classPrivateFieldGet(this, _LiveObject_map, "f").get(key);
let result = [];
if (isCrdt(oldValue)) {
result = oldValue._serialize(this._id, op.key);
oldValue._detach();
}
else if (oldValue !== undefined) {
result = [
{
type: OpType.UpdateObject,
id: this._id,
data: { [key]: oldValue },
},
];
}
__classPrivateFieldGet(this, _LiveObject_map, "f").delete(key);
this._notify();
return result;
};
/**
* The LiveMap class is similar to a JavaScript Map that is synchronized on all clients.
* Keys should be a string, and values should be serializable to JSON.
* If multiple clients update the same property simultaneously, the last modification received by the Liveblocks servers is the winner.
*/
export class LiveMap extends AbstractCrdt {

@@ -521,3 +658,3 @@ constructor(entries) {

const value = selfOrRegister(entry[1]);
value._setParent(this);
value._setParentLink(this, entry[0]);
mappedEntries.push([entry[0], value]);

@@ -573,3 +710,3 @@ }

const child = deserialize(entry, parentToChildren, doc);
child._setParent(map);
child._setParentLink(map, crdt.parentKey);
__classPrivateFieldGet(map, _LiveMap_map, "f").set(crdt.parentKey, child);

@@ -598,9 +735,15 @@ }

const previousValue = __classPrivateFieldGet(this, _LiveMap_map, "f").get(key);
let result;
if (previousValue) {
result = previousValue._serialize(this._id, key);
previousValue._detach();
}
child._setParent(this);
else {
result = [{ type: OpType.DeleteCrdt, id }];
}
child._setParentLink(this, key);
child._attach(id, this._doc);
__classPrivateFieldGet(this, _LiveMap_map, "f").set(key, child);
this.notify();
this._notify();
return result;
}

@@ -626,4 +769,9 @@ /**

child._detach();
this.notify();
this._notify();
}
/**
* Returns a specified element from the LiveMap.
* @param key The key of the element to return.
* @returns The element associated with the specified key, or undefined if the key can't be found in the LiveMap.
*/
get(key) {

@@ -636,2 +784,7 @@ const value = __classPrivateFieldGet(this, _LiveMap_map, "f").get(key);

}
/**
* Adds or updates an element with a specified key and a value.
* @param key The key of the element to add. Should be a string.
* @param value The value of the element to add. Should be serializable to JSON.
*/
set(key, value) {

@@ -643,17 +796,32 @@ const oldValue = __classPrivateFieldGet(this, _LiveMap_map, "f").get(key);

const item = selfOrRegister(value);
item._setParent(this);
item._setParentLink(this, key);
__classPrivateFieldGet(this, _LiveMap_map, "f").set(key, item);
if (this._doc && this._id) {
item._attach(this._doc.generateId(), this._doc);
const ops = item._serialize(this._id, key);
this._doc.dispatch(ops);
const id = this._doc.generateId();
item._attach(id, this._doc);
this._doc.addToUndoStack(oldValue
? oldValue._serialize(this._id, key)
: [{ type: OpType.DeleteCrdt, id }]);
this._doc.dispatch(item._serialize(this._id, key));
}
this.notify();
this._notify();
}
/**
* Returns the number of elements in the LiveMap.
*/
get size() {
return __classPrivateFieldGet(this, _LiveMap_map, "f").size;
}
/**
* Returns a boolean indicating whether an element with the specified key exists or not.
* @param key The key of the element to test for presence.
*/
has(key) {
return __classPrivateFieldGet(this, _LiveMap_map, "f").has(key);
}
/**
* Removes the specified element by key.
* @param key The key of the element to remove.
* @returns true if an element existed and has been removed, or false if the element does not exist.
*/
delete(key) {

@@ -666,8 +834,12 @@ const item = __classPrivateFieldGet(this, _LiveMap_map, "f").get(key);

if (this._doc && item._id) {
this._doc.addToUndoStack(item._serialize(this._id, key));
this._doc.dispatch([{ type: OpType.DeleteCrdt, id: item._id }]);
}
__classPrivateFieldGet(this, _LiveMap_map, "f").delete(key);
this.notify();
this._notify();
return true;
}
/**
* Returns a new Iterator object that contains the [key, value] pairs for each element.
*/
entries() {

@@ -694,8 +866,17 @@ const innerIterator = __classPrivateFieldGet(this, _LiveMap_map, "f").entries();

}
/**
* Same function object as the initial value of the entries method.
*/
[(_LiveMap_map = new WeakMap(), Symbol.iterator)]() {
return this.entries();
}
/**
* Returns a new Iterator object that contains the keys for each element.
*/
keys() {
return __classPrivateFieldGet(this, _LiveMap_map, "f").keys();
}
/**
* Returns a new Iterator object that contains the values for each element.
*/
values() {

@@ -721,2 +902,6 @@ const innerIterator = __classPrivateFieldGet(this, _LiveMap_map, "f").values();

}
/**
* Executes a provided function once per each key/value pair in the Map object, in insertion order.
* @param callback Function to execute for each entry in the map.
*/
forEach(callback) {

@@ -728,2 +913,5 @@ for (const entry of this) {

}
/**
* INTERNAL
*/
class LiveRegister extends AbstractCrdt {

@@ -772,4 +960,10 @@ constructor(data) {

}
_apply(op) {
return super._apply(op);
}
}
_LiveRegister_data = new WeakMap();
/**
* The LiveList class represents an ordered collection of items that is synchorinized across clients.
*/
export class LiveList extends AbstractCrdt {

@@ -800,3 +994,3 @@ constructor(items = []) {

const child = deserialize(entry, parentToChildren, doc);
child._setParent(list);
child._setParentLink(list, entry[1].parentKey);
__classPrivateFieldGet(list, _LiveList_items, "f").push([child, entry[1].parentKey]);

@@ -857,3 +1051,3 @@ __classPrivateFieldGet(list, _LiveList_items, "f").sort((itemA, itemB) => compare(itemA[1], itemB[1]));

child._attach(id, this._doc);
child._setParent(this);
child._setParentLink(this, key);
const index = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[1] === key);

@@ -866,3 +1060,4 @@ // Assign a temporary position until we get the fix from the backend

__classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => compare(itemA[1], itemB[1]));
this.notify();
this._notify();
return [{ type: OpType.DeleteCrdt, id }];
}

@@ -878,3 +1073,3 @@ /**

}
this.notify();
this._notify();
}

@@ -886,2 +1081,3 @@ /**

var _a;
child._setParentLink(this, key);
const index = __classPrivateFieldGet(this, _LiveList_items, "f").findIndex((entry) => entry[1] === key);

@@ -897,21 +1093,29 @@ // Assign a temporary position until we get the fix from the backend

__classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => compare(itemA[1], itemB[1]));
this.notify();
this._notify();
}
/**
* INTERNAL
*/
_apply(op) {
return super._apply(op);
}
/**
* Returns the number of elements.
*/
get length() {
return __classPrivateFieldGet(this, _LiveList_items, "f").length;
}
push(item) {
const position = __classPrivateFieldGet(this, _LiveList_items, "f").length === 0
? makePosition()
: makePosition(__classPrivateFieldGet(this, _LiveList_items, "f")[__classPrivateFieldGet(this, _LiveList_items, "f").length - 1][1]);
const value = selfOrRegister(item);
value._setParent(this);
__classPrivateFieldGet(this, _LiveList_items, "f").push([value, position]);
this.notify();
if (this._doc && this._id) {
value._attach(this._doc.generateId(), this._doc);
this._doc.dispatch(value._serialize(this._id, position));
}
/**
* Adds one element to the end of the LiveList.
* @param element The element to add to the end of the LiveList.
*/
push(element) {
return this.insert(element, this.length);
}
insert(item, index) {
/**
* Inserts one element at a specified index.
* @param element The element to insert.
* @param index The index at which you want to insert the element.
*/
insert(element, index) {
if (index < 0 || index > __classPrivateFieldGet(this, _LiveList_items, "f").length) {

@@ -923,12 +1127,19 @@ throw new Error(`Cannot delete list item at index "${index}". index should be between 0 and ${__classPrivateFieldGet(this, _LiveList_items, "f").length}`);

const position = makePosition(before, after);
const value = selfOrRegister(item);
value._setParent(this);
const value = selfOrRegister(element);
value._setParentLink(this, position);
__classPrivateFieldGet(this, _LiveList_items, "f").push([value, position]);
__classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => compare(itemA[1], itemB[1]));
this.notify();
this._notify();
if (this._doc && this._id) {
value._attach(this._doc.generateId(), this._doc);
const id = this._doc.generateId();
value._attach(id, this._doc);
this._doc.addToUndoStack([{ type: OpType.DeleteCrdt, id }]);
this._doc.dispatch(value._serialize(this._id, position));
}
}
/**
* Move one element from one index to another.
* @param index The index of the element to move
* @param targetIndex The index where the element should be after moving.
*/
move(index, targetIndex) {

@@ -963,6 +1174,15 @@ if (targetIndex < 0) {

const item = __classPrivateFieldGet(this, _LiveList_items, "f")[index];
const previousPosition = item[1];
item[1] = position;
item[0]._setParentLink(this, position);
__classPrivateFieldGet(this, _LiveList_items, "f").sort((itemA, itemB) => compare(itemA[1], itemB[1]));
this.notify();
this._notify();
if (this._doc && this._id) {
this._doc.addToUndoStack([
{
type: OpType.SetParentKey,
id: item[0]._id,
parentKey: previousPosition,
},
]);
this._doc.dispatch([

@@ -977,2 +1197,6 @@ {

}
/**
* Deletes an element at the specified index
* @param index The index of the element to delete
*/
delete(index) {

@@ -988,2 +1212,3 @@ if (index < 0 || index >= __classPrivateFieldGet(this, _LiveList_items, "f").length) {

if (childRecordId) {
this._doc.addToUndoStack(item[0]._serialize(this._id, item[1]));
this._doc.dispatch([

@@ -997,22 +1222,54 @@ {

}
this.notify();
this._notify();
}
/**
* Returns an Array of all the elements in the LiveList.
*/
toArray() {
return __classPrivateFieldGet(this, _LiveList_items, "f").map((entry) => selfOrRegisterValue(entry[0]));
}
/**
* Tests whether all elements pass the test implemented by the provided function.
* @param predicate Function to test for each element, taking two arguments (the element and its index).
* @returns true if the predicate function returns a truthy value for every element. Otherwise, false.
*/
every(predicate) {
return this.toArray().every(predicate);
}
/**
* Creates an array with all elements that pass the test implemented by the provided function.
* @param predicate Function to test each element of the LiveList. Return a value that coerces to true to keep the element, or to false otherwise.
* @returns An array with the elements that pass the test.
*/
filter(predicate) {
return this.toArray().filter(predicate);
}
/**
* Returns the first element that satisfies the provided testing function.
* @param predicate Function to execute on each value.
* @returns The value of the first element in the LiveList that satisfies the provided testing function. Otherwise, undefined is returned.
*/
find(predicate) {
return this.toArray().find(predicate);
}
/**
* Returns the index of the first element in the LiveList that satisfies the provided testing function.
* @param predicate Function to execute on each value until the function returns true, indicating that the satisfying element was found.
* @returns The index of the first element in the LiveList that passes the test. Otherwise, -1.
*/
findIndex(predicate) {
return this.toArray().findIndex(predicate);
}
/**
* Executes a provided function once for each element.
* @param callbackfn Function to execute on each element.
*/
forEach(callbackfn) {
return this.toArray().forEach(callbackfn);
}
/**
* Get the element at the specified index.
* @param index The index on the element to get.
* @returns The element at the specified index or undefined.
*/
get(index) {

@@ -1024,11 +1281,33 @@ if (index < 0 || index >= __classPrivateFieldGet(this, _LiveList_items, "f").length) {

}
/**
* Returns the first index at which a given element can be found in the LiveList, or -1 if it is not present.
* @param searchElement Element to locate.
* @param fromIndex The index to start the search at.
* @returns The first index of the element in the LiveList; -1 if not found.
*/
indexOf(searchElement, fromIndex) {
return this.toArray().indexOf(searchElement, fromIndex);
}
/**
* Returns the last index at which a given element can be found in the LiveList, or -1 if it is not present. The LiveLsit is searched backwards, starting at fromIndex.
* @param searchElement Element to locate.
* @param fromIndex The index at which to start searching backwards.
* @returns
*/
lastIndexOf(searchElement, fromIndex) {
return this.toArray().lastIndexOf(searchElement, fromIndex);
}
/**
* Creates an array populated with the results of calling a provided function on every element.
* @param callback Function that is called for every element.
* @returns An array with each element being the result of the callback function.
*/
map(callback) {
return __classPrivateFieldGet(this, _LiveList_items, "f").map((entry, i) => callback(selfOrRegisterValue(entry[0]), i));
}
/**
* Tests whether at least one element in the LiveList passes the test implemented by the provided function.
* @param predicate Function to test for each element.
* @returns true if the callback function returns a truthy value for at least one element. Otherwise, false.
*/
some(predicate) {

@@ -1035,0 +1314,0 @@ return this.toArray().some(predicate);

@@ -117,3 +117,3 @@ import { Presence } from "./types";

export declare type UpdateObjectOp = {
opId: string;
opId?: string;
id: string;

@@ -120,0 +120,0 @@ type: OpType.UpdateObject;

@@ -84,2 +84,4 @@ import { Others, Presence, ClientOptions, Room, MyPresenceCallback, OthersEventCallback, AuthEndpoint, EventCallback, User, Connection, ErrorCallback, AuthenticationToken, ConnectionCallback } from "./types";

broadcastEvent: (event: any) => void;
undo: () => void;
redo: () => void;
getStorage: <TRoot>() => Promise<{

@@ -86,0 +88,0 @@ root: import("./doc").LiveObject<TRoot>;

@@ -478,2 +478,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {

}
function undo() {
storage.undo();
}
function redo() {
storage.redo();
}
return {

@@ -497,2 +503,4 @@ // Internal

broadcastEvent,
undo,
redo,
getStorage,

@@ -578,2 +586,4 @@ selectors: {

getStorage: machine.getStorage,
undo: machine.undo,
redo: machine.redo,
};

@@ -580,0 +590,0 @@ return {

@@ -19,2 +19,4 @@ import { Doc as Doc } from "./doc";

onMessage(message: ServerMessage): Promise<void>;
undo(): void;
redo(): void;
}

@@ -51,5 +51,3 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {

case ServerMessageType.UpdateStorage: {
for (const op of message.ops) {
(_b = this._doc) === null || _b === void 0 ? void 0 : _b.apply(op);
}
(_b = this._doc) === null || _b === void 0 ? void 0 : _b.apply(message.ops);
break;

@@ -60,2 +58,10 @@ }

}
undo() {
var _a;
(_a = this._doc) === null || _a === void 0 ? void 0 : _a.undo();
}
redo() {
var _a;
(_a = this._doc) === null || _a === void 0 ? void 0 : _a.redo();
}
}

@@ -269,3 +269,5 @@ import { LiveObject } from "./doc";

}>;
undo: () => void;
redo: () => void;
};
export {};
{
"name": "@liveblocks/client",
"version": "0.12.0-beta.13",
"version": "0.12.0-beta.14",
"description": "",

@@ -5,0 +5,0 @@ "main": "./lib/cjs/index.js",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc