UNPKG

immutable-json-patch

Version:

Immutable JSON patch with support for reverting operations

107 lines (105 loc) 3.39 kB
import { existsIn, getIn } from './immutabilityHelpers.js'; import { immutableJSONPatch, isArrayItem, parseFrom, parsePath } from './immutableJSONPatch.js'; import { compileJSONPointer } from './jsonPointer.js'; import { startsWith } from './utils.js'; /** * Create the inverse of a set of json patch operations * @param document * @param operations Array with JSON patch actions * @param [options] * @return Returns the operations to revert the changes */ export function revertJSONPatch(document, operations, options) { let allRevertOperations = []; const before = (document, operation) => { let revertOperations; const path = parsePath(document, operation.path); if (operation.op === 'add') { revertOperations = revertAdd(document, path); } else if (operation.op === 'remove') { revertOperations = revertRemove(document, path); } else if (operation.op === 'replace') { revertOperations = revertReplace(document, path); } else if (operation.op === 'copy') { revertOperations = revertCopy(document, path); } else if (operation.op === 'move') { revertOperations = revertMove(document, path, parseFrom(operation.from)); } else if (operation.op === 'test') { revertOperations = []; } else { throw new Error(`Unknown JSONPatch operation ${JSON.stringify(operation)}`); } let updatedJson; if (options?.before) { const res = options.before(document, operation, revertOperations); if (res?.revertOperations) { revertOperations = res.revertOperations; } if (res?.document) { updatedJson = res.document; } // @ts-ignore if (res?.json) { // TODO: deprecated since v5.0.0. Cleanup this warning some day throw new Error('Deprecation warning: returned object property ".json" has been renamed to ".document"'); } } allRevertOperations = revertOperations.concat(allRevertOperations); if (updatedJson !== undefined) { return { document: updatedJson }; } }; immutableJSONPatch(document, operations, { before }); return allRevertOperations; } function revertReplace(document, path) { return existsIn(document, path) ? [{ op: 'replace', path: compileJSONPointer(path), value: getIn(document, path) }] : []; } function revertRemove(document, path) { return [{ op: 'add', path: compileJSONPointer(path), value: getIn(document, path) }]; } function revertAdd(document, path) { if (isArrayItem(document, path) || !existsIn(document, path)) { return [{ op: 'remove', path: compileJSONPointer(path) }]; } return revertReplace(document, path); } function revertCopy(document, path) { return revertAdd(document, path); } function revertMove(document, path, from) { if (path.length < from.length && startsWith(from, path)) { // replacing the parent with the child return [{ op: 'replace', path: compileJSONPointer(path), value: document }]; } const move = { op: 'move', from: compileJSONPointer(path), path: compileJSONPointer(from) }; if (!isArrayItem(document, path) && existsIn(document, path)) { // the move replaces an existing value in an object return [move, ...revertRemove(document, path)]; } return [move]; } //# sourceMappingURL=revertJSONPatch.js.map