jiff
Version:
JSON diff and patch based on rfc6902
69 lines (55 loc) • 1.86 kB
JavaScript
/** @license MIT License (c) copyright 2010-2014 original author or authors */
/** @author Brian Cavalier */
/** @author John Hann */
var patches = require('./patches');
var clone = require('./clone');
var InvalidPatchOperationError = require('./InvalidPatchOperationError');
exports.apply = patch;
exports.applyInPlace = patchInPlace;
exports.clone = clone;
exports.isValidObject = isValidObject;
exports.defaultHash = defaultHash;
var defaultOptions = {};
/**
* Apply the supplied JSON Patch to x
* @param {array} changes JSON Patch
* @param {object|array|string|number} x object/array/value to patch
* @param {object} options
* @param {function(index:Number, array:Array, context:object):Number} options.findContext
* function used adjust array indexes for smarty/fuzzy patching, for
* patches containing context
* @returns {object|array|string|number} patched version of x. If x is
* an array or object, it will be mutated and returned. Otherwise, if
* x is a value, the new value will be returned.
*/
function patch(changes, x, options) {
return patchInPlace(changes, clone(x), options);
}
function patchInPlace(changes, x, options) {
if(!options) {
options = defaultOptions;
}
// TODO: Consider throwing if changes is not an array
if(!Array.isArray(changes)) {
return x;
}
var patch, p;
for(var i=0; i<changes.length; ++i) {
p = changes[i];
patch = patches[p.op];
if(patch === void 0) {
throw new InvalidPatchOperationError('invalid op ' + JSON.stringify(p));
}
x = patch.apply(x, p, options);
}
return x;
}
function defaultHash(x) {
return isValidObject(x) || isArray(x) ? JSON.stringify(x) : x;
}
function isValidObject (x) {
return x !== null && Object.prototype.toString.call(x) === '[object Object]';
}
function isArray (x) {
return Object.prototype.toString.call(x) === '[object Array]';
}