json-joy
Version:
Collection of libraries for building collaborative editing apps.
136 lines (135 loc) • 3.72 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ObjNode = void 0;
const printTree_1 = require("tree-dump/lib/printTree");
const clock_1 = require("../../../json-crdt-patch/clock");
/**
* 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
*/
class ObjNode {
constructor(
/**
* @ignore
*/
doc, id) {
this.doc = doc;
this.id = id;
/**
* @ignore
*/
this.keys = new Map();
/**
* @ignore
*/
this._tick = 0;
/**
* @ignore
*/
this._view = {};
/**
* @ignore
*/
this.api = undefined;
}
/**
* 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 && (0, clock_1.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));
}
// ----------------------------------------------------------------- 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
*/
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));
}
name() {
return 'obj';
}
// ---------------------------------------------------------------- Printable
toString(tab = '') {
const header = this.name() + ' ' + (0, clock_1.printTs)(this.id);
return (header +
(0, printTree_1.printTree)(tab, [...this.keys.entries()]
.filter(([, id]) => !!this.doc.index.get(id))
.map(([key, id]) => (tab) => JSON.stringify(key) + (0, printTree_1.printTree)(tab + ' ', [(tab) => this.doc.index.get(id).toString(tab)]))));
}
}
exports.ObjNode = ObjNode;