json-joy
Version:
Collection of libraries for building collaborative editing apps.
144 lines • 3.85 kB
JavaScript
import { printTree } from 'tree-dump/lib/printTree';
import { compare, printTs } from '../../../json-crdt-patch/clock';
import { ConNode } from '../const/ConNode';
/**
* Represents a `obj` JSON CRDT node, which is a Last-write-wins (LWW) object.
* It is a map of string keys to LWW registers. The value of each register is
* a reference to another JSON CRDT node.
*
* @category CRDT Node
*/
export class ObjNode {
doc;
id;
/**
* @ignore
*/
keys = new Map();
constructor(
/**
* @ignore
*/
doc, id) {
this.doc = doc;
this.id = id;
}
/**
* Retrieves a JSON CRDT node at the given key.
*
* @param key A key of the object.
* @returns JSON CRDT node at the given key, if any.
*/
get(key) {
const id = this.keys.get(key);
if (!id)
return undefined;
return this.doc.index.get(id);
}
/**
* Rewrites object key.
*
* @param key Object key to set.
* @param id ID of the contents of the key.
* @returns Returns old entry ID, if any.
* @ignore
*/
put(key, id) {
const currentId = this.keys.get(key);
if (currentId && compare(currentId, id) >= 0)
return;
this.keys.set(key, id);
return currentId;
}
/**
* Iterate over all key-value pairs in the object.
*
* @param callback Callback to call for each key-value pair.
*/
nodes(callback) {
const index = this.doc.index;
this.keys.forEach((id, key) => callback(index.get(id), key));
}
forEach(callback) {
const index = this.doc.index;
this.keys.forEach((id, key) => {
const value = index.get(id);
if (!value || (value instanceof ConNode && value.val === void 0))
return;
callback(key, value);
});
}
// ----------------------------------------------------------------- JsonNode
/**
* @ignore
*/
children(callback) {
const index = this.doc.index;
this.keys.forEach((id, key) => callback(index.get(id)));
}
/**
* @ignore
*/
child() {
return undefined;
}
/**
* @ignore
*/
container() {
return this;
}
/**
* @ignore
*/
_tick = 0;
/**
* @ignore
*/
_view = {};
/**
* @ignore
*/
view() {
const doc = this.doc;
const tick = doc.clock.time + doc.tick;
const _view = this._view;
if (this._tick === tick)
return _view;
const view = {};
const index = doc.index;
let useCache = true;
this.keys.forEach((id, key) => {
const valueNode = index.get(id);
if (!valueNode) {
useCache = false;
return;
}
const value = valueNode.view();
if (value !== undefined) {
if (_view[key] !== value)
useCache = false;
view[key] = value;
}
else if (_view[key] !== undefined)
useCache = false;
});
return useCache ? _view : ((this._tick = tick), (this._view = view));
}
/**
* @ignore
*/
api = undefined;
name() {
return 'obj';
}
// ---------------------------------------------------------------- Printable
toString(tab = '') {
const header = this.name() + ' ' + printTs(this.id);
return (header +
printTree(tab, [...this.keys.entries()]
.filter(([, id]) => !!this.doc.index.get(id))
.map(([key, id]) => (tab) => JSON.stringify(key) + printTree(tab + ' ', [(tab) => this.doc.index.get(id).toString(tab)]))));
}
}
//# sourceMappingURL=ObjNode.js.map