UNPKG

@jsonjoy.com/json-expression

Version:

High-performance JSON Pointer implementation

116 lines (115 loc) 3.68 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.patchOperators = exports.$add = exports.$$add = void 0; const codegen_steps_1 = require("../codegen-steps"); const util_1 = require("@jsonjoy.com/json-pointer/lib/util"); const codegen_1 = require("@jsonjoy.com/util/lib/codegen"); const findRef_1 = require("@jsonjoy.com/json-pointer/lib/codegen/findRef"); const find_1 = require("@jsonjoy.com/json-pointer/lib/find"); const validateAddOperandCount = (count) => { if (count < 3) { throw new Error('Not enough operands for "jp.add" operand.'); } if (count % 2 !== 0) { throw new Error('Invalid number of operands for "jp.add" operand.'); } }; const validateAddPath = (path) => { if (typeof path !== 'string') { throw new Error('The "path" argument for "jp.add" must be a const string.'); } }; const $$add = (path) => { const find = (0, findRef_1.$findRef)(path); const js = /* js */ ` (function(find, path){ return function(doc, value){ var f = find(doc); var obj = f.obj, key = f.key, val = f.val; if (!obj) doc = value; else if (typeof key === 'string') obj[key] = value; else { var length = obj.length; if (key < length) obj.splice(key, 0, value); else if (key > length) throw new Error('INVALID_INDEX'); else obj.push(value); } return doc; }; })`; return { deps: [find], js: js, }; }; exports.$$add = $$add; const $add = (path) => (0, codegen_1.compileClosure)((0, exports.$$add)(path)); exports.$add = $add; exports.patchOperators = [ [ 'jp.add', [], -1, /** * Applies JSON Patch "add" operations to the input value. * * ``` * ['add', {}, * '/a', 1, * '/b', ['+', 2, 3], * ] * ``` * * Results in: * * ``` * { * a: 1, * b: 5, * } * ``` */ (expr, ctx) => { let i = 1; const length = expr.length; validateAddOperandCount(length); let doc = ctx.eval(expr[i++], ctx); while (i < length) { const path = expr[i++]; validateAddPath(path); const value = ctx.eval(expr[i++], ctx); const { obj, key } = (0, find_1.find)(doc, (0, util_1.toPath)(path)); if (!obj) doc = value; else if (typeof key === 'string') obj[key] = value; else if (obj instanceof Array) { const length = obj.length; if (key < length) obj.splice(key, 0, value); else if (key > length) throw new Error('INVALID_INDEX'); else obj.push(value); } } return doc; }, (ctx) => { const expr = ctx.expr; const length = ctx.operands.length; validateAddOperandCount(length + 1); let i = 0; let curr = ctx.operands[i++]; while (i < length) { const path = expr[1 + i++]; validateAddPath(path); const value = ctx.operands[i++]; const addCompiled = (0, exports.$add)((0, util_1.toPath)(path)); const dAdd = ctx.link(addCompiled); curr = new codegen_steps_1.Expression(`${dAdd}(${curr}, ${value})`); } return curr; }, ], ];