UNPKG

json-joy

Version:

Collection of libraries for building collaborative editing apps.

179 lines (178 loc) 5.57 kB
"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;