json-joy
Version:
Collection of libraries for building collaborative editing apps.
179 lines (178 loc) • 5.57 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ArrNode = exports.ArrChunk = void 0;
const AbstractRga_1 = require("../rga/AbstractRga");
const clock_1 = require("../../../json-crdt-patch/clock");
const printBinary_1 = require("tree-dump/lib/printBinary");
const printTree_1 = require("tree-dump/lib/printTree");
/**
* @ignore
* @category CRDT Node
*/
class ArrChunk {
constructor(id, span, data) {
this.id = id;
this.span = span;
this.len = data ? span : 0;
this.del = !data;
this.p = undefined;
this.l = undefined;
this.r = undefined;
this.s = undefined;
this.data = data;
}
merge(data) {
this.data.push(...data);
this.span = this.data.length;
}
split(ticks) {
const span = this.span;
this.span = ticks;
if (!this.del) {
const data = this.data;
const rightData = data.splice(ticks);
const chunk = new ArrChunk((0, clock_1.tick)(this.id, ticks), span - ticks, rightData);
return chunk;
}
return new ArrChunk((0, clock_1.tick)(this.id, ticks), span - ticks, undefined);
}
delete() {
this.del = true;
this.data = undefined;
}
clone() {
return new ArrChunk(this.id, this.span, this.data ? [...this.data] : undefined);
}
view() {
return this.data ? [...this.data] : [];
}
}
exports.ArrChunk = ArrChunk;
/**
* Represents the `arr` JSON CRDT type, which is a Replicated Growable Array
* (RGA). Each element ot the array is a reference to another JSON CRDT node.
*
* @category CRDT Node
*/
class ArrNode extends AbstractRga_1.AbstractRga {
constructor(doc, id) {
super(id);
this.doc = doc;
/** @ignore */
this._tick = 0;
/** @ignore */
this._view = [];
/** @ignore */
this.api = undefined;
}
/**
* Returns a reference to an element at a given position in the array.
*
* @param position The position of the element to get.
* @returns An element of the array, if any.
*/
get(position) {
const pair = this.findChunk(position);
if (!pair)
return undefined;
return pair[0].data[pair[1]];
}
/**
* Returns a JSON node at a given position in the array.
*
* @param position The position of the element to get.
* @returns A JSON node, if any.
*/
getNode(position) {
const id = this.get(position);
if (!id)
return undefined;
return this.doc.index.get(id);
}
getById(id) {
const chunk = this.findById(id);
if (!chunk || chunk.del)
return undefined;
const offset = id.time - chunk.id.time;
return chunk.data[offset];
}
// -------------------------------------------------------------- AbstractRga
/** @ignore */
createChunk(id, data) {
return new ArrChunk(id, data ? data.length : 0, data);
}
/** @ignore */
onChange() { }
toStringName() {
return this.name();
}
// ----------------------------------------------------------------- JsonNode
/** @ignore */
child() {
return undefined;
}
/** @ignore */
container() {
return this;
}
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;
for (let chunk = this.first(); chunk; chunk = this.next(chunk)) {
if (chunk.del)
continue;
for (const node of chunk.data) {
const elementNode = index.get(node);
if (!elementNode) {
useCache = false;
continue;
}
const element = elementNode.view();
if (_view[view.length] !== element)
useCache = false;
view.push(element);
}
}
if (_view.length !== view.length)
useCache = false;
const result = useCache ? _view : ((this._tick = tick), (this._view = view));
return result;
}
/** @ignore */
children(callback) {
const index = this.doc.index;
for (let chunk = this.first(); chunk; chunk = this.next(chunk))
if (!chunk.del)
for (const node of chunk.data)
callback(index.get(node));
}
name() {
return 'arr';
}
// ---------------------------------------------------------------- Printable
/** @ignore */
printChunk(tab, chunk) {
const pos = this.pos(chunk);
let valueTree = '';
if (!chunk.del) {
const index = this.doc.index;
valueTree = (0, printTree_1.printTree)(tab, chunk
.data.map((id) => index.get(id))
.filter((node) => !!node)
.map((node, i) => (tab) => `[${pos + i}]: ${node.toString(tab + ' ' + ' '.repeat(String(i).length))}`));
}
return (this.formatChunk(chunk) +
valueTree +
(0, printBinary_1.printBinary)(tab, [
chunk.l ? (tab) => this.printChunk(tab, chunk.l) : null,
chunk.r ? (tab) => this.printChunk(tab, chunk.r) : null,
]));
}
}
exports.ArrNode = ArrNode;