UNPKG

json-joy

Version:

Collection of libraries for building collaborative editing apps.

101 lines (100 loc) 3.71 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.apply = void 0; const json_pointer_1 = require("@jsonjoy.com/json-pointer"); const evaluate_1 = require("@jsonjoy.com/json-expression/lib/evaluate"); const util_1 = require("./util"); const constants_1 = require("./constants"); const apply_1 = require("../ot-string-irreversible/apply"); const apply_2 = require("../ot-binary-irreversible/apply"); const Vars_1 = require("@jsonjoy.com/json-expression/lib/Vars"); const apply = (doc, op) => { const [test, pick = [], data = [], drop = [], edit = []] = op; const testLength = test.length; if (testLength) { const expressionContext = { vars: new Vars_1.Vars(doc) }; for (let i = 0; i < testLength; i++) { const testExpr = test[i]; const testValue = (0, evaluate_1.evaluate)(testExpr, expressionContext); if (!testValue) throw new Error('TEST'); } } const registers = new Map(); const picksSorted = pick.sort((a, b) => (0, util_1.comparePath)(a[1], b[1])); for (const [regId, path] of picksSorted) { const ref = (0, json_pointer_1.find)(doc, path); if ((0, json_pointer_1.isArrayReference)(ref)) { const { obj, key, val } = ref; obj.splice(key, 1); registers.set(regId, val); } else if ((0, json_pointer_1.isObjectReference)(ref)) { const { obj, key, val } = ref; delete obj[key]; registers.set(regId, val); } else { doc = undefined; registers.set(regId, ref.val); } } for (const [regId, value] of data) registers.set(regId, value); const dropsSorted = drop.sort((a, b) => (0, util_1.comparePath)(b[1], a[1])); for (const [regId, where] of dropsSorted) { const value = registers.get(regId); if (!where.length) { doc = value; continue; } const path = where.slice(0, -1); const { val } = (0, json_pointer_1.find)(doc, path); if (val instanceof Array) { let index = where[where.length - 1]; if (index === '-') index = val.length; const index2 = ~~index; if (typeof index === 'string') if ('' + index2 !== index) throw new Error('INVALID_INDEX'); if (index2 > val.length || index2 < -1) throw new Error('INVALID_INDEX'); if (index2 === -1 || index2 === val.length) val.push(value); else val.splice(index2, 0, value); } else if (val && typeof val === 'object') { const key = where[where.length - 1]; val[key] = value; } else { throw new Error('NOT_FOUND'); } } for (const [type, path, operation] of edit) { const { val, obj, key } = (0, json_pointer_1.find)(doc, path); let newVal; switch (type) { case constants_1.EDIT_TYPE.OT_STRING: { if (typeof val !== 'string') throw new Error('NOT_STR'); newVal = (0, apply_1.apply)(val, operation); break; } case constants_1.EDIT_TYPE.OT_BINARY: { if (!(val instanceof Uint8Array)) throw new Error('NOT_BIN'); newVal = (0, apply_2.apply)(val, operation); break; } } if (!obj) doc = newVal; else obj[key] = newVal; } return doc; }; exports.apply = apply;