UNPKG

json-joy

Version:

Collection of libraries for building collaborative editing apps.

361 lines (360 loc) 9.06 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NopOp = exports.DelOp = exports.InsArrOp = exports.InsBinOp = exports.InsStrOp = exports.InsVecOp = exports.InsObjOp = exports.InsValOp = exports.NewArrOp = exports.NewBinOp = exports.NewStrOp = exports.NewVecOp = exports.NewObjOp = exports.NewValOp = exports.NewConOp = void 0; const printTree_1 = require("tree-dump/lib/printTree"); const clock_1 = require("./clock"); /** * Operation which creates a constant "con" data type. * * @category Operations */ class NewConOp { constructor(id, val) { this.id = id; this.val = val; } span() { return 1; } name() { return 'new_con'; } toString(tab = '') { const val = this.val; const klass = 'Uint8Array'; const valFormatted = val instanceof clock_1.Timestamp ? `{ ${(0, clock_1.printTs)(val)} }` : val instanceof Uint8Array ? val.length < 13 ? `${klass} { ${('' + val).replaceAll(',', ', ')} }` : `${klass}(${val.length})` : `{ ${JSON.stringify(val)} }`; return `${this.name()} ${(0, clock_1.printTs)(this.id)} ${valFormatted}`; } } exports.NewConOp = NewConOp; /** * Operation which creates a new value object. * * @category Operations */ class NewValOp { constructor(id) { this.id = id; } span() { return 1; } name() { return 'new_val'; } toString() { return `${this.name()} ${(0, clock_1.printTs)(this.id)}`; } } exports.NewValOp = NewValOp; /** * Operation which creates a new object. * * @category Operations */ class NewObjOp { constructor(id) { this.id = id; } span() { return 1; } name() { return 'new_obj'; } toString() { return `${this.name()} ${(0, clock_1.printTs)(this.id)}`; } } exports.NewObjOp = NewObjOp; /** * Operation which creates a new vector object. * * @category Operations */ class NewVecOp { constructor(id) { this.id = id; } span() { return 1; } name() { return 'new_vec'; } toString() { return `${this.name()} ${(0, clock_1.printTs)(this.id)}`; } } exports.NewVecOp = NewVecOp; /** * Operation which creates a new string object. * * @category Operations */ class NewStrOp { constructor(id) { this.id = id; } span() { return 1; } name() { return 'new_str'; } toString() { return `${this.name()} ${(0, clock_1.printTs)(this.id)}`; } } exports.NewStrOp = NewStrOp; /** * Operation which creates a new binary object. * * @category Operations */ class NewBinOp { constructor(id) { this.id = id; } span() { return 1; } name() { return 'new_bin'; } toString(tab = '') { return `${this.name()} ${(0, clock_1.printTs)(this.id)}`; } } exports.NewBinOp = NewBinOp; /** * Operation which creates a new array object. * * @category Operations */ class NewArrOp { constructor(id) { this.id = id; } span() { return 1; } name() { return 'new_arr'; } toString() { return `${this.name()} ${(0, clock_1.printTs)(this.id)}`; } } exports.NewArrOp = NewArrOp; /** * Operation which writes a new value to a value "val" object. * * @category Operations */ class InsValOp { constructor(id, /** @todo Rename to `node`. */ obj, val) { this.id = id; this.obj = obj; this.val = val; } span() { return 1; } name() { return 'ins_val'; } toString(tab = '') { return `${this.name()} ${(0, clock_1.printTs)(this.id)}!${this.span()}, obj = ${(0, clock_1.printTs)(this.obj)}, val = ${(0, clock_1.printTs)(this.val)}`; } } exports.InsValOp = InsValOp; /** * Operation which sets object keys. * * @category Operations */ class InsObjOp { constructor(id, obj, data) { this.id = id; this.obj = obj; this.data = data; } span() { return 1; } name() { return 'ins_obj'; } toString(tab = '') { const header = `${this.name()} ${(0, clock_1.printTs)(this.id)}!${this.span()}, obj = ${(0, clock_1.printTs)(this.obj)}`; return (header + (0, printTree_1.printTree)(tab, this.data.map((item) => (tab) => `${JSON.stringify(item[0])}: ${(0, clock_1.printTs)(item[1])}`))); } } exports.InsObjOp = InsObjOp; /** * Operation which sets vector elements. * * @category Operations */ class InsVecOp { constructor(id, obj, data) { this.id = id; this.obj = obj; this.data = data; } span() { return 1; } name() { return 'ins_vec'; } toString(tab = '') { const header = `${this.name()} ${(0, clock_1.printTs)(this.id)}!${this.span()}, obj = ${(0, clock_1.printTs)(this.obj)}`; return (header + (0, printTree_1.printTree)(tab, this.data.map((item) => (tab) => `${item[0]}: ${(0, clock_1.printTs)(item[1])}`))); } } exports.InsVecOp = InsVecOp; /** * Operation which inserts text into a "str" string object. * * @category Operations */ class InsStrOp { constructor(id, obj, ref, data) { this.id = id; this.obj = obj; this.ref = ref; this.data = data; } span() { return this.data.length; } name() { return 'ins_str'; } toString() { return `${this.name()} ${(0, clock_1.printTs)(this.id)}!${this.span()}, obj = ${(0, clock_1.printTs)(this.obj)} { ${(0, clock_1.printTs)(this.ref)} ← ${JSON.stringify(this.data)} }`; } } exports.InsStrOp = InsStrOp; /** * Operations which inserts binary data into a "bin" binary object. * * @category Operations */ class InsBinOp { constructor(id, obj, ref, data) { this.id = id; this.obj = obj; this.ref = ref; this.data = data; } span() { return this.data.length; } name() { return 'ins_bin'; } toString(tab = '') { const ref = (0, clock_1.printTs)(this.ref); return `${this.name()} ${(0, clock_1.printTs)(this.id)}!${this.span()}, obj = ${(0, clock_1.printTs)(this.obj)} { ${ref} ← ${this.data} }`; } } exports.InsBinOp = InsBinOp; /** * Operation which inserts elements into an array. * * @category Operations */ class InsArrOp { /** * @param id ID if the first operation in this compound operation. * @param obj ID of the array where to insert elements. In theory `arr` is * not necessary as it is possible to find the `arr` just using the * `after` property, however to efficiently be able to find `arr` just * by `after` at runtime all operations would need to be indexed and * also they each would need to store a pointer to array type, which * would require additional dozens of bytes of RAM for each array * insert operation. * @param ref ID of the element after which to insert elements. * @param data The elements to insert. */ constructor(id, obj, ref, data) { this.id = id; this.obj = obj; this.ref = ref; this.data = data; } span() { return this.data.length; } name() { return 'ins_arr'; } toString() { return `${this.name()} ${(0, clock_1.printTs)(this.id)}!${this.span()}, obj = ${(0, clock_1.printTs)(this.obj)} { ${(0, clock_1.printTs)(this.ref)} ← ${this.data.map(clock_1.printTs).join(', ')} }`; } } exports.InsArrOp = InsArrOp; /** * Operation which deletes one or more ranges of values in some object. * The object could be a string, an array, or a binary. * * @category Operations */ class DelOp { /** * @param id ID of this operation. * @param obj Object in which to delete something. * @param what ID of the first operation to be deleted. */ constructor(id, obj, what) { this.id = id; this.obj = obj; this.what = what; } span() { return 1; } name() { return 'del'; } toString() { const spans = this.what.map((span) => (0, clock_1.printTs)(span) + '!' + span.span).join(', '); return `${this.name()} ${(0, clock_1.printTs)(this.id)}, obj = ${(0, clock_1.printTs)(this.obj)} { ${spans} }`; } } exports.DelOp = DelOp; /** * Operation which does nothing. Useful for skipping clock cycles, so that * operations with a gap in clock can be included in the same patch. * * @category Operations */ class NopOp { constructor(id, len) { this.id = id; this.len = len; } span() { return this.len; } name() { return 'nop'; } toString() { return `${this.name()} ${(0, clock_1.printTs)(this.id)}!${this.len}`; } } exports.NopOp = NopOp;