fast-json-patch
Advanced tools
Comparing version 1.1.10 to 1.2.0
/*! | ||
* https://github.com/Starcounter-Jack/JSON-Patch | ||
* json-patch-duplex.js version: 1.1.10 | ||
* json-patch-duplex.js version: 1.2.0 | ||
* (c) 2013 Joachim Wester | ||
* MIT license | ||
*/ | ||
var jsonpatch;if(function(a){function b(a,c){switch(typeof a){case"undefined":case"boolean":case"string":case"number":return a===c;case"object":if(null===a)return null===c;if(z(a)){if(!z(c)||a.length!==c.length)return!1;for(var d=0,e=a.length;d<e;d++)if(!b(a[d],c[d]))return!1;return!0}var f=s(c),g=f.length;if(s(a).length!==g)return!1;for(var d=0;d<g;d++)if(!b(a[d],c[d]))return!1;return!0;default:return!1}}function c(a){return a.indexOf("/")===-1&&a.indexOf("~")===-1?a:a.replace(/~/g,"~0").replace(/\//g,"~1")}function d(a){for(var b=0,c=w.length;b<c;b++)if(w[b].obj===a)return w[b]}function e(a,b){for(var c=0,d=a.observers.length;c<d;c++)if(a.observers[c].callback===b)return a.observers[c].observer}function f(a,b){for(var c=0,d=a.observers.length;c<d;c++)if(a.observers[c].observer===b)return void a.observers.splice(c,1)}function g(a,b){b.unobserve()}function h(a){switch(typeof a){case"object":return JSON.parse(JSON.stringify(a));case"undefined":return null;default:return a}}function i(a,b){var c,g=[],i=d(a);if(i?c=e(i,b):(i=new x(a),w.push(i)),c)return c;if(c={},i.value=h(a),b){c.callback=b,c.next=null;var k=function(){j(c)},l=function(){clearTimeout(c.next),c.next=setTimeout(k)};"undefined"!=typeof window&&(window.addEventListener?(window.addEventListener("mouseup",l),window.addEventListener("keyup",l),window.addEventListener("mousedown",l),window.addEventListener("keydown",l),window.addEventListener("change",l)):(document.documentElement.attachEvent("onmouseup",l),document.documentElement.attachEvent("onkeyup",l),document.documentElement.attachEvent("onmousedown",l),document.documentElement.attachEvent("onkeydown",l),document.documentElement.attachEvent("onchange",l)))}return c.patches=g,c.object=a,c.unobserve=function(){j(c),clearTimeout(c.next),f(i,c),"undefined"!=typeof window&&(window.removeEventListener?(window.removeEventListener("mouseup",l),window.removeEventListener("keyup",l),window.removeEventListener("mousedown",l),window.removeEventListener("keydown",l)):(document.documentElement.detachEvent("onmouseup",l),document.documentElement.detachEvent("onkeyup",l),document.documentElement.detachEvent("onmousedown",l),document.documentElement.detachEvent("onkeydown",l)))},i.observers.push(new y(b,c)),c}function j(a){for(var b,c=0,d=w.length;c<d;c++)if(w[c].obj===a.object){b=w[c];break}k(b.value,a.object,a.patches,""),a.patches.length&&m(b.value,a.patches);var e=a.patches;return e.length>0&&(a.patches=[],a.callback&&a.callback(e)),e}function k(a,b,d,e){if(b!==a){"function"==typeof b.toJSON&&(b=b.toJSON());for(var f=s(b),g=s(a),i=!1,j=!1,l=g.length-1;l>=0;l--){var m=g[l],n=a[m];if(!b.hasOwnProperty(m)||void 0===b[m]&&void 0!==n&&z(b)===!1)d.push({op:"remove",path:e+"/"+c(m)}),j=!0;else{var o=b[m];"object"==typeof n&&null!=n&&"object"==typeof o&&null!=o?k(n,o,d,e+"/"+c(m)):n!==o&&(i=!0,d.push({op:"replace",path:e+"/"+c(m),value:h(o)}))}}if(j||f.length!=g.length)for(var l=0;l<f.length;l++){var m=f[l];a.hasOwnProperty(m)||void 0===b[m]||d.push({op:"add",path:e+"/"+c(m),value:h(b[m])})}}}function l(a){for(var b,c=0,d=a.length;c<d;){b=a.charCodeAt(c);{if(!(b>=48&&b<=57))return!1;c++}}return!0}function m(a,b,c){for(var d,e,f=[],g=0,h=b.length;g<h;){d=b[g],g++;for(var i=d.path||"",j=i.split("/"),k=a,m=1,n=j.length,o=void 0;;){if(e=j[m],c&&void 0===o&&(void 0===k[e]?o=j.slice(0,m).join("/"):m==n-1&&(o=d.path),void 0!==o&&this.validator(d,g-1,a,o)),m++,void 0===e&&m>=n){f.push(v[d.op].call(d,k,e,a));break}if(z(k)){if("-"===e)e=k.length;else{if(c&&!l(e))throw new A("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index","OPERATION_PATH_ILLEGAL_ARRAY_INDEX",g-1,d.path,d);e=parseInt(e,10)}if(m>=n){if(c&&"add"===d.op&&e>k.length)throw new A("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",g-1,d.path,d);f.push(u[d.op].call(d,k,e,a));break}}else if(e&&e.indexOf("~")!=-1&&(e=e.replace(/~1/g,"/").replace(/~0/g,"~")),m>=n){f.push(t[d.op].call(d,k,e,a));break}k=k[e]}}return f}function n(a,b){var c=[];return k(a,b,c,""),c}function o(a,b){function c(){this.constructor=a}for(var d in b)b.hasOwnProperty(d)&&(a[d]=b[d]);a.prototype=null===b?Object.create(b):(c.prototype=b.prototype,new c)}function p(a){if(void 0===a)return!0;if("array"==typeof a||"object"==typeof a)for(var b in a)if(p(a[b]))return!0;return!1}function q(b,c,d,e){if("object"!=typeof b||null===b||z(b))throw new A("Operation is not an object","OPERATION_NOT_AN_OBJECT",c,b,d);if(!t[b.op])throw new A("Operation `op` property is not one of operations defined in RFC-6902","OPERATION_OP_INVALID",c,b,d);if("string"!=typeof b.path)throw new A("Operation `path` property is not a string","OPERATION_PATH_INVALID",c,b,d);if(0!==b.path.indexOf("/")&&b.path.length>0)throw new A('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",c,b,d);if(("move"===b.op||"copy"===b.op)&&"string"!=typeof b.from)throw new A("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",c,b,d);if(("add"===b.op||"replace"===b.op||"test"===b.op)&&void 0===b.value)throw new A("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",c,b,d);if(("add"===b.op||"replace"===b.op||"test"===b.op)&&p(b.value))throw new A("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",c,b,d);if(d)if("add"==b.op){var f=b.path.split("/").length,g=e.split("/").length;if(f!==g+1&&f!==g)throw new A("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",c,b,d)}else if("replace"===b.op||"remove"===b.op||"_get"===b.op){if(b.path!==e)throw new A("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",c,b,d)}else if("move"===b.op||"copy"===b.op){var h={op:"_get",path:b.from,value:void 0},i=a.validate([h],d);if(i&&"OPERATION_PATH_UNRESOLVABLE"===i.name)throw new A("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",c,b,d)}}function r(a,b){try{if(!z(a))throw new A("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(b)b=JSON.parse(JSON.stringify(b)),m.call(this,b,a,!0);else for(var c=0;c<a.length;c++)this.validator(a[c],c)}catch(a){if(a instanceof A)return a;throw a}}var s=function(a){if(z(a)){for(var b=new Array(a.length),c=0;c<b.length;c++)b[c]=""+c;return b}if(Object.keys)return Object.keys(a);var b=[];for(var d in a)a.hasOwnProperty(d)&&b.push(d);return b},t={add:function(a,b){a[b]=this.value},remove:function(a,b){var c=a[b];return delete a[b],c},replace:function(a,b){var c=a[b];return a[b]=this.value,c},move:function(a,b,c){var d={op:"_get",path:this.path};m(c,[d]);var e=void 0===d.value?void 0:JSON.parse(JSON.stringify(d.value)),f={op:"_get",path:this.from};return m(c,[f]),m(c,[{op:"remove",path:this.from}]),m(c,[{op:"add",path:this.path,value:f.value}]),e},copy:function(a,b,c){var d={op:"_get",path:this.from};m(c,[d]),m(c,[{op:"add",path:this.path,value:d.value}])},test:function(a,c){return b(a[c],this.value)},_get:function(a,b){this.value=a[b]}},u={add:function(a,b){return a.splice(b,0,this.value),b},remove:function(a,b){var c=a.splice(b,1);return c[0]},replace:function(a,b){var c=a[b];return a[b]=this.value,c},move:t.move,copy:t.copy,test:t.test,_get:t._get},v={add:function(a){v.remove.call(this,a);for(var b in this.value)this.value.hasOwnProperty(b)&&(a[b]=this.value[b])},remove:function(a){var b={};for(var c in a)a.hasOwnProperty(c)&&(b[c]=a[c],t.remove.call(this,a,c));return b},replace:function(a){var b=m(a,[{op:"remove",path:this.path}]);return m(a,[{op:"add",path:this.path,value:this.value}]),b[0]},move:t.move,copy:t.copy,test:function(a){return JSON.stringify(a)===JSON.stringify(this.value)},_get:function(a){this.value=a}},w=[],x=function(){function a(a){this.observers=[],this.obj=a}return a}(),y=function(){function a(a,b){this.callback=a,this.observer=b}return a}();a.unobserve=g,a.observe=i,a.generate=j;var z;z=Array.isArray?Array.isArray:function(a){return a.push&&"number"==typeof a.length},a.apply=m,a.compare=n;var A=function(a){function b(b,c,d,e,f){a.call(this,b),this.message=b,this.name=c,this.index=d,this.operation=e,this.tree=f}return o(b,a),b}(Error);a.JsonPatchError=A,a.validator=q,a.validate=r}(jsonpatch||(jsonpatch={})),"undefined"!=typeof exports)exports.apply=jsonpatch.apply,exports.observe=jsonpatch.observe,exports.unobserve=jsonpatch.unobserve,exports.generate=jsonpatch.generate,exports.compare=jsonpatch.compare,exports.validate=jsonpatch.validate,exports.validator=jsonpatch.validator,exports.JsonPatchError=jsonpatch.JsonPatchError;else var exports={},isBrowser=!0;Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=jsonpatch,isBrowser&&(exports=void 0); | ||
var jsonpatch;if(function(a){function b(a,c){switch(typeof a){case"undefined":case"boolean":case"string":case"number":return a===c;case"object":if(null===a)return null===c;if(x(a)){if(!x(c)||a.length!==c.length)return!1;for(var d=0,e=a.length;d<e;d++)if(!b(a[d],c[d]))return!1;return!0}for(var f=y(a),g=y(c),h=0;h<f.length;h++){var i=f[h];if(!b(a[i],c[i]))return!1;var j=g.indexOf(i);j>=0&&g.splice(j,1)}for(var k=0;k<g.length;k++){var l=g[k];if(!b(a[l],c[l]))return!1}return!0;default:return!1}}function c(a){for(var b=0,c=B.length;b<c;b++)if(B[b].obj===a)return B[b]}function d(a,b){for(var c=0,d=a.observers.length;c<d;c++)if(a.observers[c].callback===b)return a.observers[c].observer}function e(a,b){for(var c=0,d=a.observers.length;c<d;c++)if(a.observers[c].observer===b)return void a.observers.splice(c,1)}function f(a,b){b.unobserve()}function g(a){switch(typeof a){case"object":return JSON.parse(JSON.stringify(a));case"undefined":return null;default:return a}}function h(a,b){var f,h=[],j=c(a);if(j?f=d(j,b):(j=new C(a),B.push(j)),f)return f;if(f={},j.value=g(a),b){f.callback=b,f.next=null;var k=function(){i(f)},l=function(){clearTimeout(f.next),f.next=setTimeout(k)};"undefined"!=typeof window&&(window.addEventListener?(window.addEventListener("mouseup",l),window.addEventListener("keyup",l),window.addEventListener("mousedown",l),window.addEventListener("keydown",l),window.addEventListener("change",l)):(document.documentElement.attachEvent("onmouseup",l),document.documentElement.attachEvent("onkeyup",l),document.documentElement.attachEvent("onmousedown",l),document.documentElement.attachEvent("onkeydown",l),document.documentElement.attachEvent("onchange",l)))}return f.patches=h,f.object=a,f.unobserve=function(){i(f),clearTimeout(f.next),e(j,f),"undefined"!=typeof window&&(window.removeEventListener?(window.removeEventListener("mouseup",l),window.removeEventListener("keyup",l),window.removeEventListener("mousedown",l),window.removeEventListener("keydown",l)):(document.documentElement.detachEvent("onmouseup",l),document.documentElement.detachEvent("onkeyup",l),document.documentElement.detachEvent("onmousedown",l),document.documentElement.detachEvent("onkeydown",l)))},j.observers.push(new D(b,f)),f}function i(a){for(var b,c=0,d=B.length;c<d;c++)if(B[c].obj===a.object){b=B[c];break}j(b.value,a.object,a.patches,""),a.patches.length&&p(b.value,a.patches);var e=a.patches;return e.length>0&&(a.patches=[],a.callback&&a.callback(e)),e}function j(a,b,c,d){if(b!==a){"function"==typeof b.toJSON&&(b=b.toJSON());for(var e=y(b),f=y(a),h=!1,i=f.length-1;i>=0;i--){var k=f[i],m=a[k];if(!b.hasOwnProperty(k)||void 0===b[k]&&void 0!==m&&!1===x(b))c.push({op:"remove",path:d+"/"+l(k)}),h=!0;else{var n=b[k];"object"==typeof m&&null!=m&&"object"==typeof n&&null!=n?j(m,n,c,d+"/"+l(k)):m!==n&&(!0,c.push({op:"replace",path:d+"/"+l(k),value:g(n)}))}}if(h||e.length!=f.length)for(var i=0;i<e.length;i++){var k=e[i];a.hasOwnProperty(k)||void 0===b[k]||c.push({op:"add",path:d+"/"+l(k),value:g(b[k])})}}}function k(a){for(var b,c=0,d=a.length;c<d;){b=a.charCodeAt(c);{if(!(b>=48&&b<=57))return!1;c++}}return!0}function l(a){return-1===a.indexOf("/")&&-1===a.indexOf("~")?a:a.replace(/~/g,"~0").replace(/\//g,"~1")}function m(a){return a.replace(/~1/g,"/").replace(/~0/g,"~")}function n(a,b){var c={op:"_get",path:b};return o(a,c),c.value}function o(a,c,d,e){void 0===d&&(d=!1),void 0===e&&(e=!0),d&&("function"==typeof d?d(c,0,a,c.path):u(c,0));var f={newDocument:a};if(""===c.path){if("add"===c.op)return f.newDocument=c.value,f;if("replace"===c.op)return f.newDocument=c.value,f.removed=a,f;if("move"===c.op||"copy"===c.op)return f.newDocument=n(a,c.from),"move"===c.op&&(f.removed=a),f;if("test"===c.op){if(f.test=b(a,c.value),!1===f.test)throw new E("Test operation failed","TEST_OPERATION_FAILED",0,c,a);return f.newDocument=a,f}if("remove"===c.op)return f.removed=a,f.newDocument=null,f;if(d)throw new E("Operation `op` property is not one of operations defined in RFC-6902","OPERATION_OP_INVALID",0,c,a);return f}e||(a=g(a));var h=c.path||"",i=h.split("/"),j=a,l=1,o=i.length,p=void 0,q=void 0,r=void 0;for(r="function"==typeof d?d:u;;){if(q=i[l],d&&void 0===p&&(void 0===j[q]?p=i.slice(0,l).join("/"):l==o-1&&(p=c.path),void 0!==p&&r(c,0,a,p)),l++,x(j)){if("-"===q)q=j.length;else{if(d&&!k(q))throw new E("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index","OPERATION_PATH_ILLEGAL_ARRAY_INDEX",0,c.path,c);q=~~q}if(l>=o){if(d&&"add"===c.op&&q>j.length)throw new E("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",0,c.path,c);if(f=A[c.op].call(c,j,q,a),!1===f.test)throw new E("Test operation failed","TEST_OPERATION_FAILED",0,c,a);return f}}else if(q&&-1!=q.indexOf("~")&&(q=m(q)),l>=o){if(f=z[c.op].call(c,j,q,a),!1===f.test)throw new E("Test operation failed","TEST_OPERATION_FAILED",0,c,a);return f}j=j[q]}}function p(a,b,c){for(var d=new Array(b.length),e=0,f=b.length;e<f;e++)d[e]=o(a,b[e],c),a=d[e].newDocument;return d.newDocument=a,d}function q(a,b,c){console.warn("jsonpatch.apply is deprecated, please use `applyPatch` for applying patch sequences, or `applyOperation` to apply individual operations.");for(var d=new Array(b.length),e=function(e,f){if(""==b[e].path&&"remove"!=b[e].op&&"test"!=b[e].op){var h;"replace"!=b[e].op&&"move"!=b[e].op||(d[e]=g(a)),"copy"!=b[e].op&&"move"!=b[e].op||(h=n(a,b[e].from)),"replace"!=b[e].op&&"add"!=b[e].op||(h=b[e].value),Object.keys(a).forEach(function(b){return delete a[b]}),Object.keys(h).forEach(function(b){return a[b]=h[b]})}else d[e]=o(a,b[e],c),d[e]=d[e].removed||d[e].test},f=0,h=b.length;f<h;f++)e(f,h);return d}function r(a,b){var c=o(a,b);if(!1===c.test)throw new E("Test operation failed","TEST_OPERATION_FAILED",0,b,a);return c.newDocument}function s(a,b){function c(){this.constructor=a}for(var d in b)b.hasOwnProperty(d)&&(a[d]=b[d]);a.prototype=null===b?Object.create(b):(c.prototype=b.prototype,new c)}function t(a){if(void 0===a)return!0;if(a)if(x(a)){for(var b=0,c=a.length;b<c;b++)if(t(a[b]))return!0}else if("object"==typeof a)for(var d=y(a),e=d.length,b=0;b<e;b++)if(t(a[d[b]]))return!0;return!1}function u(a,b,c,d){if("object"!=typeof a||null===a||x(a))throw new E("Operation is not an object","OPERATION_NOT_AN_OBJECT",b,a,c);if(!z[a.op])throw new E("Operation `op` property is not one of operations defined in RFC-6902","OPERATION_OP_INVALID",b,a,c);if("string"!=typeof a.path)throw new E("Operation `path` property is not a string","OPERATION_PATH_INVALID",b,a,c);if(0!==a.path.indexOf("/")&&a.path.length>0)throw new E('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",b,a,c);if(("move"===a.op||"copy"===a.op)&&"string"!=typeof a.from)throw new E("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",b,a,c);if(("add"===a.op||"replace"===a.op||"test"===a.op)&&void 0===a.value)throw new E("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",b,a,c);if(("add"===a.op||"replace"===a.op||"test"===a.op)&&t(a.value))throw new E("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",b,a,c);if(c)if("add"==a.op){var e=a.path.split("/").length,f=d.split("/").length;if(e!==f+1&&e!==f)throw new E("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",b,a,c)}else if("replace"===a.op||"remove"===a.op||"_get"===a.op){if(a.path!==d)throw new E("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",b,a,c)}else if("move"===a.op||"copy"===a.op){var g={op:"_get",path:a.from,value:void 0},h=v([g],c);if(h&&"OPERATION_PATH_UNRESOLVABLE"===h.name)throw new E("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",b,a,c)}}function v(a,b,c){try{if(!x(a))throw new E("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(b)b=JSON.parse(JSON.stringify(b)),p(b,a,c||!0);else{c=c||u;for(var d=0;d<a.length;d++)c(a[d],d,b,void 0)}}catch(a){if(a instanceof E)return a;throw a}}function w(a,b){var c=[];return j(a,b,c,""),c}var x,y=function(a){if(x(a)){for(var b=new Array(a.length),c=0;c<b.length;c++)b[c]=""+c;return b}if(Object.keys)return Object.keys(a);var b=[];for(var d in a)a.hasOwnProperty(d)&&b.push(d);return b},z={add:function(a,b,c){return a[b]=this.value,{newDocument:c}},remove:function(a,b,c){var d=a[b];return delete a[b],{newDocument:c,removed:d}},replace:function(a,b,c){var d=a[b];return a[b]=this.value,{newDocument:c,removed:d}},move:function(a,b,c){var d=n(c,this.path);d&&(d=g(d));var e=o(c,{op:"remove",path:this.from}).removed;return o(c,{op:"add",path:this.path,value:e}),{newDocument:c,removed:d}},copy:function(a,b,c){var d=n(c,this.from);return o(c,{op:"add",path:this.path,value:d}),{newDocument:c}},test:function(a,c,d){return{newDocument:d,test:b(a[c],this.value)}},_get:function(a,b,c){return this.value=a[b],{newDocument:c}}},A={add:function(a,b,c){return a.splice(b,0,this.value),{newDocument:c,index:b}},remove:function(a,b,c){return{newDocument:c,removed:a.splice(b,1)[0]}},replace:function(a,b,c){var d=a[b];return a[b]=this.value,{newDocument:c,removed:d}},move:z.move,copy:z.copy,test:z.test,_get:z._get};x=Array.isArray?Array.isArray:function(a){return a.push&&"number"==typeof a.length};var B=[],C=function(){function a(a){this.observers=[],this.obj=a}return a}(),D=function(){function a(a,b){this.callback=a,this.observer=b}return a}();a.unobserve=f,a.observe=h,a.generate=i;var x;x=Array.isArray?Array.isArray:function(a){return a.push&&"number"==typeof a.length},a.escapePathComponent=l,a.unescapePathComponent=m,a.getValueByPointer=n,a.applyOperation=o,a.applyPatch=p,a.apply=q,a.applyReducer=r;var E=function(a){function b(b,c,d,e,f){a.call(this,b),this.message=b,this.name=c,this.index=d,this.operation=e,this.tree=f}return s(b,a),b}(Error);a.JsonPatchError=E,a.validator=u,a.validate=v,a.compare=w}(jsonpatch||(jsonpatch={})),void 0!==exports)exports.apply=jsonpatch.apply,exports.applyPatch=jsonpatch.applyPatch,exports.applyOperation=jsonpatch.applyOperation,exports.applyReducer=jsonpatch.applyReducer,exports.getValueByPointer=jsonpatch.getValueByPointer,exports.escapePathComponent=jsonpatch.escapePathComponent,exports.unescapePathComponent=jsonpatch.unescapePathComponent,exports.observe=jsonpatch.observe,exports.unobserve=jsonpatch.unobserve,exports.generate=jsonpatch.generate,exports.compare=jsonpatch.compare,exports.validate=jsonpatch.validate,exports.validator=jsonpatch.validator,exports.JsonPatchError=jsonpatch.JsonPatchError;else var exports={},isBrowser=!0;Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=jsonpatch,isBrowser&&(exports=void 0); |
/*! | ||
* https://github.com/Starcounter-Jack/JSON-Patch | ||
* json-patch-duplex.js version: 1.1.10 | ||
* json-patch-duplex.js version: 1.2.0 | ||
* (c) 2013 Joachim Wester | ||
* MIT license | ||
*/ | ||
var jsonpatch;if(function(a){function b(a,c){switch(typeof a){case"undefined":case"boolean":case"string":case"number":return a===c;case"object":if(null===a)return null===c;if(i(a)){if(!i(c)||a.length!==c.length)return!1;for(var d=0,e=a.length;d<e;d++)if(!b(a[d],c[d]))return!1;return!0}var f=j(c),g=f.length;if(j(a).length!==g)return!1;for(var d=0;d<g;d++)if(!b(a[d],c[d]))return!1;return!0;default:return!1}}function c(a){for(var b,c=0,d=a.length;c<d;){b=a.charCodeAt(c);{if(!(b>=48&&b<=57))return!1;c++}}return!0}function d(a,b,d){for(var e,f,g=new Array(b.length),h=0,j=b.length;h<j;){e=b[h],h++;for(var o=e.path||"",p=o.split("/"),q=a,r=1,s=p.length,t=void 0;;){if(f=p[r],d&&void 0===t&&(void 0===q[f]?t=p.slice(0,r).join("/"):r==s-1&&(t=e.path),void 0!==t&&this.validator(e,h-1,a,t)),r++,void 0===f&&r>=s){g[h-1]=m[e.op].call(e,q,f,a);break}if(i(q)){if("-"===f)f=q.length;else{if(d&&!c(f))throw new n("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index","OPERATION_PATH_ILLEGAL_ARRAY_INDEX",h-1,e.path,e);f=parseInt(f,10)}if(r>=s){if(d&&"add"===e.op&&f>q.length)throw new n("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",h-1,e.path,e);g[h-1]=l[e.op].call(e,q,f,a);break}}else if(f&&f.indexOf("~")!=-1&&(f=f.replace(/~1/g,"/").replace(/~0/g,"~")),r>=s){g[h-1]=k[e.op].call(e,q,f,a);break}q=q[f]}}return g}function e(a,b){function c(){this.constructor=a}for(var d in b)b.hasOwnProperty(d)&&(a[d]=b[d]);a.prototype=null===b?Object.create(b):(c.prototype=b.prototype,new c)}function f(a){if(void 0===a)return!0;if("array"==typeof a||"object"==typeof a)for(var b in a)if(f(a[b]))return!0;return!1}function g(b,c,d,e){if("object"!=typeof b||null===b||i(b))throw new n("Operation is not an object","OPERATION_NOT_AN_OBJECT",c,b,d);if(!k[b.op])throw new n("Operation `op` property is not one of operations defined in RFC-6902","OPERATION_OP_INVALID",c,b,d);if("string"!=typeof b.path)throw new n("Operation `path` property is not a string","OPERATION_PATH_INVALID",c,b,d);if(0!==b.path.indexOf("/")&&b.path.length>0)throw new n('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",c,b,d);if(("move"===b.op||"copy"===b.op)&&"string"!=typeof b.from)throw new n("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",c,b,d);if(("add"===b.op||"replace"===b.op||"test"===b.op)&&void 0===b.value)throw new n("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",c,b,d);if(("add"===b.op||"replace"===b.op||"test"===b.op)&&f(b.value))throw new n("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",c,b,d);if(d)if("add"==b.op){var g=b.path.split("/").length,h=e.split("/").length;if(g!==h+1&&g!==h)throw new n("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",c,b,d)}else if("replace"===b.op||"remove"===b.op||"_get"===b.op){if(b.path!==e)throw new n("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",c,b,d)}else if("move"===b.op||"copy"===b.op){var j={op:"_get",path:b.from,value:void 0},l=a.validate([j],d);if(l&&"OPERATION_PATH_UNRESOLVABLE"===l.name)throw new n("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",c,b,d)}}function h(a,b){try{if(!i(a))throw new n("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(b)b=JSON.parse(JSON.stringify(b)),d.call(this,b,a,!0);else for(var c=0;c<a.length;c++)this.validator(a[c],c)}catch(a){if(a instanceof n)return a;throw a}}var i,j=function(a){if(i(a)){for(var b=new Array(a.length),c=0;c<b.length;c++)b[c]=""+c;return b}if(Object.keys)return Object.keys(a);var b=[];for(var d in a)a.hasOwnProperty(d)&&b.push(d);return b},k={add:function(a,b){a[b]=this.value},remove:function(a,b){var c=a[b];return delete a[b],c},replace:function(a,b){var c=a[b];return a[b]=this.value,c},move:function(a,b,c){var e={op:"_get",path:this.path};d(c,[e]);var f=void 0===e.value?void 0:JSON.parse(JSON.stringify(e.value)),g={op:"_get",path:this.from};return d(c,[g]),d(c,[{op:"remove",path:this.from}]),d(c,[{op:"add",path:this.path,value:g.value}]),f},copy:function(a,b,c){var e={op:"_get",path:this.from};d(c,[e]),d(c,[{op:"add",path:this.path,value:e.value}])},test:function(a,c){return b(a[c],this.value)},_get:function(a,b){this.value=a[b]}},l={add:function(a,b){return a.splice(b,0,this.value),b},remove:function(a,b){var c=a.splice(b,1);return c[0]},replace:function(a,b){var c=a[b];return a[b]=this.value,c},move:k.move,copy:k.copy,test:k.test,_get:k._get},m={add:function(a){m.remove.call(this,a);for(var b in this.value)this.value.hasOwnProperty(b)&&(a[b]=this.value[b])},remove:function(a){var b={};for(var c in a)a.hasOwnProperty(c)&&(b[c]=a[c],k.remove.call(this,a,c));return b},replace:function(a){var b=d(a,[{op:"remove",path:this.path}]);return d(a,[{op:"add",path:this.path,value:this.value}]),b[0]},move:k.move,copy:k.copy,test:function(a){return JSON.stringify(a)===JSON.stringify(this.value)},_get:function(a){this.value=a}};i=Array.isArray?Array.isArray:function(a){return a.push&&"number"==typeof a.length},a.apply=d;var n=function(a){function b(b,c,d,e,f){a.call(this,b),this.message=b,this.name=c,this.index=d,this.operation=e,this.tree=f}return e(b,a),b}(Error);a.JsonPatchError=n,a.validator=g,a.validate=h}(jsonpatch||(jsonpatch={})),"undefined"!=typeof exports)exports.apply=jsonpatch.apply,exports.validate=jsonpatch.validate,exports.validator=jsonpatch.validator,exports.JsonPatchError=jsonpatch.JsonPatchError;else var exports={},isBrowser=!0;Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=jsonpatch,isBrowser&&(exports=void 0); | ||
var jsonpatch;if(function(a){function b(a,c){switch(typeof a){case"undefined":case"boolean":case"string":case"number":return a===c;case"object":if(null===a)return null===c;if(p(a)){if(!p(c)||a.length!==c.length)return!1;for(var d=0,e=a.length;d<e;d++)if(!b(a[d],c[d]))return!1;return!0}for(var f=q(a),g=q(c),h=0;h<f.length;h++){var i=f[h];if(!b(a[i],c[i]))return!1;var j=g.indexOf(i);j>=0&&g.splice(j,1)}for(var k=0;k<g.length;k++){var l=g[k];if(!b(a[l],c[l]))return!1}return!0;default:return!1}}function c(a){switch(typeof a){case"object":return JSON.parse(JSON.stringify(a));case"undefined":return null;default:return a}}function d(a){for(var b,c=0,d=a.length;c<d;){b=a.charCodeAt(c);{if(!(b>=48&&b<=57))return!1;c++}}return!0}function e(a){return-1===a.indexOf("/")&&-1===a.indexOf("~")?a:a.replace(/~/g,"~0").replace(/\//g,"~1")}function f(a){return a.replace(/~1/g,"/").replace(/~0/g,"~")}function g(a,b){var c={op:"_get",path:b};return h(a,c),c.value}function h(a,e,h,i){if(void 0===h&&(h=!1),void 0===i&&(i=!0),h&&("function"==typeof h?h(e,0,a,e.path):n(e,0)),""===e.path){var j={newDocument:a};if("add"===e.op)return j.newDocument=e.value,j;if("replace"===e.op)return j.newDocument=e.value,j.removed=a,j;if("move"===e.op||"copy"===e.op)return j.newDocument=g(a,e.from),"move"===e.op&&(j.removed=a),j;if("test"===e.op){if(j.test=b(a,e.value),!1===j.test)throw new t("Test operation failed","TEST_OPERATION_FAILED",0,e,a);return j.newDocument=a,j}if("remove"===e.op)return j.removed=a,j.newDocument=null,j;if(h)throw new t("Operation `op` property is not one of operations defined in RFC-6902","OPERATION_OP_INVALID",0,e,a);return j}i||(a=c(a));var k=e.path||"",l=k.split("/"),m=a,o=1,q=l.length,u=void 0,v=void 0,w=void 0;for(w="function"==typeof h?h:n;;){if(v=l[o],h&&void 0===u&&(void 0===m[v]?u=l.slice(0,o).join("/"):o==q-1&&(u=e.path),void 0!==u&&w(e,0,a,u)),o++,p(m)){if("-"===v)v=m.length;else{if(h&&!d(v))throw new t("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index","OPERATION_PATH_ILLEGAL_ARRAY_INDEX",0,e.path,e);v=~~v}if(o>=q){if(h&&"add"===e.op&&v>m.length)throw new t("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",0,e.path,e);var j=s[e.op].call(e,m,v,a);if(!1===j.test)throw new t("Test operation failed","TEST_OPERATION_FAILED",0,e,a);return j}}else if(v&&-1!=v.indexOf("~")&&(v=f(v)),o>=q){var j=r[e.op].call(e,m,v,a);if(!1===j.test)throw new t("Test operation failed","TEST_OPERATION_FAILED",0,e,a);return j}m=m[v]}}function i(a,b,c){for(var d=new Array(b.length),e=0,f=b.length;e<f;e++)d[e]=h(a,b[e],c),a=d[e].newDocument;return d.newDocument=a,d}function j(a,b,d){console.warn("jsonpatch.apply is deprecated, please use `applyPatch` for applying patch sequences, or `applyOperation` to apply individual operations.");for(var e=new Array(b.length),f=function(f,i){if(""==b[f].path&&"remove"!=b[f].op&&"test"!=b[f].op){var j;"replace"!=b[f].op&&"move"!=b[f].op||(e[f]=c(a)),"copy"!=b[f].op&&"move"!=b[f].op||(j=g(a,b[f].from)),"replace"!=b[f].op&&"add"!=b[f].op||(j=b[f].value),Object.keys(a).forEach(function(b){return delete a[b]}),Object.keys(j).forEach(function(b){return a[b]=j[b]})}else e[f]=h(a,b[f],d),e[f]=e[f].removed||e[f].test},i=0,j=b.length;i<j;i++)f(i,j);return e}function k(a,b){var c=h(a,b);if(!1===c.test)throw new t("Test operation failed","TEST_OPERATION_FAILED",0,b,a);return c.newDocument}function l(a,b){function c(){this.constructor=a}for(var d in b)b.hasOwnProperty(d)&&(a[d]=b[d]);a.prototype=null===b?Object.create(b):(c.prototype=b.prototype,new c)}function m(a){if(void 0===a)return!0;if(a)if(p(a)){for(var b=0,c=a.length;b<c;b++)if(m(a[b]))return!0}else if("object"==typeof a)for(var d=q(a),e=d.length,b=0;b<e;b++)if(m(a[d[b]]))return!0;return!1}function n(a,b,c,d){if("object"!=typeof a||null===a||p(a))throw new t("Operation is not an object","OPERATION_NOT_AN_OBJECT",b,a,c);if(!r[a.op])throw new t("Operation `op` property is not one of operations defined in RFC-6902","OPERATION_OP_INVALID",b,a,c);if("string"!=typeof a.path)throw new t("Operation `path` property is not a string","OPERATION_PATH_INVALID",b,a,c);if(0!==a.path.indexOf("/")&&a.path.length>0)throw new t('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",b,a,c);if(("move"===a.op||"copy"===a.op)&&"string"!=typeof a.from)throw new t("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",b,a,c);if(("add"===a.op||"replace"===a.op||"test"===a.op)&&void 0===a.value)throw new t("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",b,a,c);if(("add"===a.op||"replace"===a.op||"test"===a.op)&&m(a.value))throw new t("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",b,a,c);if(c)if("add"==a.op){var e=a.path.split("/").length,f=d.split("/").length;if(e!==f+1&&e!==f)throw new t("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",b,a,c)}else if("replace"===a.op||"remove"===a.op||"_get"===a.op){if(a.path!==d)throw new t("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",b,a,c)}else if("move"===a.op||"copy"===a.op){var g={op:"_get",path:a.from,value:void 0},h=o([g],c);if(h&&"OPERATION_PATH_UNRESOLVABLE"===h.name)throw new t("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",b,a,c)}}function o(a,b,c){try{if(!p(a))throw new t("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(b)b=JSON.parse(JSON.stringify(b)),i(b,a,c||!0);else{c=c||n;for(var d=0;d<a.length;d++)c(a[d],d,b,void 0)}}catch(a){if(a instanceof t)return a;throw a}}var p,q=function(a){if(p(a)){for(var b=new Array(a.length),c=0;c<b.length;c++)b[c]=""+c;return b}if(Object.keys)return Object.keys(a);var b=[];for(var d in a)a.hasOwnProperty(d)&&b.push(d);return b},r={add:function(a,b,c){return a[b]=this.value,{newDocument:c}},remove:function(a,b,c){var d=a[b];return delete a[b],{newDocument:c,removed:d}},replace:function(a,b,c){var d=a[b];return a[b]=this.value,{newDocument:c,removed:d}},move:function(a,b,d){var e=g(d,this.path);e&&(e=c(e));var f=h(d,{op:"remove",path:this.from}).removed;return h(d,{op:"add",path:this.path,value:f}),{newDocument:d,removed:e}},copy:function(a,b,c){var d=g(c,this.from);return h(c,{op:"add",path:this.path,value:d}),{newDocument:c}},test:function(a,c,d){return{newDocument:d,test:b(a[c],this.value)}},_get:function(a,b,c){return this.value=a[b],{newDocument:c}}},s={add:function(a,b,c){return a.splice(b,0,this.value),{newDocument:c,index:b}},remove:function(a,b,c){return{newDocument:c,removed:a.splice(b,1)[0]}},replace:function(a,b,c){var d=a[b];return a[b]=this.value,{newDocument:c,removed:d}},move:r.move,copy:r.copy,test:r.test,_get:r._get};p=Array.isArray?Array.isArray:function(a){return a.push&&"number"==typeof a.length},a.escapePathComponent=e,a.unescapePathComponent=f,a.getValueByPointer=g,a.applyOperation=h,a.applyPatch=i,a.apply=j,a.applyReducer=k;var t=function(a){function b(b,c,d,e,f){a.call(this,b),this.message=b,this.name=c,this.index=d,this.operation=e,this.tree=f}return l(b,a),b}(Error);a.JsonPatchError=t,a.validator=n,a.validate=o}(jsonpatch||(jsonpatch={})),void 0!==exports)exports.apply=jsonpatch.apply,exports.applyPatch=jsonpatch.applyPatch,exports.applyOperation=jsonpatch.applyOperation,exports.applyReducer=jsonpatch.applyReducer,exports.getValueByPointer=jsonpatch.getValueByPointer,exports.escapePathComponent=jsonpatch.escapePathComponent,exports.unescapePathComponent=jsonpatch.unescapePathComponent,exports.validate=jsonpatch.validate,exports.validator=jsonpatch.validator,exports.JsonPatchError=jsonpatch.JsonPatchError;else var exports={},isBrowser=!0;Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=jsonpatch,isBrowser&&(exports=void 0); |
{ | ||
"name": "fast-json-patch", | ||
"version": "1.1.10", | ||
"version": "1.2.0", | ||
"description": "Fast implementation of JSON-Patch (RFC-6902) with duplex (observe changes) capabilities", | ||
@@ -5,0 +5,0 @@ "homepage": "https://github.com/Starcounter-Jack/JSON-Patch", |
187
README.md
@@ -86,34 +86,63 @@ JSON-Patch | ||
Applying patches: | ||
#### Applying patches: | ||
```js | ||
var myobj = { firstName:"Albert", contactDetails: { phoneNumbers: [ ] } }; | ||
var patches = [ | ||
{op:"replace", path:"/firstName", value:"Joachim" }, | ||
{op:"add", path:"/lastName", value:"Wester" }, | ||
{op:"add", path:"/contactDetails/phoneNumbers/0", value:{ number:"555-123" } } | ||
]; | ||
jsonpatch.apply( myobj, patches ); | ||
// myobj == { firstName:"Joachim", lastName:"Wester", contactDetails:{ phoneNumbers[ {number:"555-123"} ] } }; | ||
var document = { firstName: "Albert", contactDetails: { phoneNumbers: [] } }; | ||
var patch = [ | ||
{ op: "replace", path: "/firstName", value: "Joachim" }, | ||
{ op: "add", path: "/lastName", value: "Wester" }, | ||
{ op: "add", path: "/contactDetails/phoneNumbers/0", value: { number: "555-123" } } | ||
]; | ||
document = jsonpatch.applyPatch(document, patch).newDocument; | ||
// document == { firstName: "Joachim", lastName: "Wester", contactDetails: { phoneNumbers: [{number:"555-123"}] } }; | ||
``` | ||
##### For apply individual operations you can use `applyOperation` | ||
`jsonpatch.applyOperation` accepts a single operation object instead of a sequence, and returns the object after applying the operation. It works with all the standard JSON patch operations (`add, replace, move, test, remove and copy`). | ||
```js | ||
var document = { firstName: "Albert", contactDetails: { phoneNumbers: [] } }; | ||
var operation = { op: "replace", path: "/firstName", value: "Joachim" }; | ||
document = jsonpatch.applyOperation(document, operation).newDocument; | ||
// document == { firstName: "Joachim", contactDetails: { phoneNumbers: [] }} | ||
``` | ||
#### Using `applyReducer` with `reduce` | ||
If you have an array of operations, you can simple reduce them using `applyReducer` as your reducer: | ||
```js | ||
var document = { firstName: "Albert", contactDetails: { phoneNumbers: [ ] } }; | ||
var patch = [ | ||
{ op:"replace", path: "/firstName", value: "Joachim" }, | ||
{ op:"add", path: "/lastName", value: "Wester" }, | ||
{ op:"add", path: "/contactDetails/phoneNumbers/0", value: { number: "555-123" } } | ||
]; | ||
var updatedDocument = patch.reduce(applyReducer, document); | ||
// updatedDocument == { firstName:"Joachim", lastName:"Wester", contactDetails:{ phoneNumbers[ {number:"555-123"} ] } }; | ||
``` | ||
Generating patches: | ||
```js | ||
var myobj = { firstName:"Joachim", lastName:"Wester", contactDetails: { phoneNumbers: [ { number:"555-123" }] } }; | ||
var observer = jsonpatch.observe( myobj ); | ||
myobj.firstName = "Albert"; | ||
myobj.contactDetails.phoneNumbers[0].number = "123"; | ||
myobj.contactDetails.phoneNumbers.push({number:"456"}); | ||
var patches = jsonpatch.generate(observer); | ||
// patches == [ | ||
// { op:"replace", path="/firstName", value:"Albert"}, | ||
// { op:"replace", path="/contactDetails/phoneNumbers/0/number", value:"123"}, | ||
// { op:"add", path="/contactDetails/phoneNumbers/1", value:{number:"456"}}]; | ||
var document = { firstName: "Joachim", lastName: "Wester", contactDetails: { phoneNumbers: [ { number:"555-123" }] } }; | ||
var observer = jsonpatch.observe(document); | ||
document.firstName = "Albert"; | ||
document.contactDetails.phoneNumbers[0].number = "123"; | ||
document.contactDetails.phoneNumbers.push({ number:"456" }); | ||
var patch = jsonpatch.generate(observer); | ||
// patch == [ | ||
// { op: "replace", path: "/firstName", value: "Albert"}, | ||
// { op: "replace", path: "/contactDetails/phoneNumbers/0/number", value: "123" }, | ||
// { op: "add", path: "/contactDetails/phoneNumbers/1", value: {number:"456"}} | ||
// ]; | ||
``` | ||
Comparing two object trees: | ||
```js | ||
var objA = {user: {firstName: "Albert", lastName: "Einstein"}}; | ||
var objB = {user: {firstName: "Albert", lastName: "Collins"}}; | ||
var diff = jsonpatch.compare(objA, objB)); | ||
var documentA = {user: {firstName: "Albert", lastName: "Einstein"}}; | ||
var documentB = {user: {firstName: "Albert", lastName: "Collins"}}; | ||
var diff = jsonpatch.compare(documentA, documentB)); | ||
//diff == [{op: "replace", path: "/user/lastName", value: "Collins"}] | ||
@@ -145,12 +174,12 @@ ``` | ||
#### jsonpatch.apply (`obj` Object, `patches` Array, `validate` Boolean) : boolean | ||
#### `jsonpatch.applyPatch<T>(document: any, patch: Operation[], validateOperation: Boolean | Function = false): OperationResult<T>[]` | ||
Available in *json-patch.js* and *json-patch-duplex.js* | ||
Applies `patches` array on `obj`. | ||
Applies `patch` array on `obj`. | ||
If the `validate` parameter is set to `true`, the patch is extensively validated before applying. | ||
An invalid patch results in throwing an error (see `jsonpatch.validate` for more information about the error object). | ||
Returns an array of results - one item for each item in `patches`. The type of each item depends on type of operation applied | ||
Returns an array of [`OperationResult`](#operationresult-type) objects - one item for each item in `patches`, each item is an object `{newDocument: any, test?: boolean, removed?: any}`. | ||
* `test` - boolean result of the test | ||
@@ -160,7 +189,58 @@ * `remove`, `replace` and `move` - original object that has been removed | ||
#### jsonpatch.observe (`obj` Object, `callback` Function (optional)) : `observer` Object | ||
**Note: the returned array has `newDocument` property that you can use as the final state of the patched document**. | ||
- See [Validation notes](#validation-notes). | ||
#### `applyOperation<T>(document: any, operation: Operation, validateOperation: <Boolean | Function> = false, mutateDocument = true): OperationResult<T>` | ||
Available in *json-patch.js* and *json-patch-duplex.js* | ||
Applies single operation object `operation` on `document`. | ||
- `document` The document to patch | ||
- `operation` The operation to apply | ||
- `validateOperation` Whether to validate the operation, or to pass a validator callback | ||
- `mutateDocument` Whether to mutate the original document or clone it before applying | ||
Returns an [`OperationResult`](#operationresult-type) object `{newDocument: any, test?: boolean, removed?: any}`. | ||
- See [Validation notes](#validation-notes). | ||
#### `jsonpatch.applyReducer<T>(document: T, operation: Operation): T` | ||
Available in *json-patch.js* and *json-patch-duplex.js* | ||
**Ideal for `patch.reduce(jsonpatch.applyReducer, document)`**. | ||
Applies single operation object `operation` on `document`. | ||
Returns the a modified document. | ||
Note: It throws `TEST_OPERATION_FAILED` error if `test` operation fails. | ||
#### `jsonpatch.escapePathComponent(path: string): string` | ||
Available in *json-patch.js* and *json-patch-duplex.js* | ||
Returns the escaped path. | ||
#### `jsonpatch.unescapePathComponent(path: string): string` | ||
Available in *json-patch.js* and *json-patch-duplex.js* | ||
Returns the unescaped path. | ||
#### `jsonpatch.getValueByPointer(document: object, pointer: string)` | ||
Available in *json-patch.js* and *json-patch-duplex.js* | ||
Retrieves a value from a JSON document by a JSON pointer. | ||
Returns the value. | ||
#### `jsonpatch.observe(document: any, callback?: Function): Observer` | ||
Available in *json-patch-duplex.js* | ||
Sets up an deep observer on `obj` that listens for changes in object tree. When changes are detected, the optional | ||
Sets up an deep observer on `document` that listens for changes in object tree. When changes are detected, the optional | ||
callback is called with the generated patches array as the parameter. | ||
@@ -170,3 +250,3 @@ | ||
#### jsonpatch.generate (`obj` Object, `observer` Object) : `patches` Array | ||
#### `jsonpatch.generate(document: any, observer: Observer): Operation[]` | ||
@@ -180,23 +260,25 @@ Available in *json-patch-duplex.js* | ||
#### jsonpatch.unobserve (`obj` Object, `observer` Object) : void | ||
#### `jsonpatch.unobserve(document: any, observer: Observer): void` | ||
Available in *json-patch-duplex.js* | ||
Destroys the observer set up on `obj`. | ||
Destroys the observer set up on `document`. | ||
Any remaining changes are delivered synchronously (as in `jsonpatch.generate`). Note: this is different that ES6/7 `Object.unobserve`, which delivers remaining changes asynchronously. | ||
#### jsonpatch.compare (`obj1` Object, `obj2` Object) : `patches` Array | ||
#### `jsonpatch.compare(document1: any, document2: any): Operation[]` | ||
Available in *json-patch-duplex.js* | ||
Compares object trees `obj1` and `obj2` and returns the difference relative to `obj1` as a patches array. | ||
Compares object trees `document1` and `document2` and returns the difference relative to `document1` as a patches array. | ||
If there are no differences, returns an empty array (length 0). | ||
#### jsonpatch.validate (`patches` Array, `tree` Object (optional)) : `error` JsonPatchError | ||
#### `jsonpatch.validate(patch: Operation[], document?: any, validator?: Function): JsonPatchError` | ||
See [Validation notes](#validation-notes) | ||
Available in *json-patch.js* and *json-patch-duplex.js* | ||
Validates a sequence of operations. If `tree` parameter is provided, the sequence is additionally validated against the object tree. | ||
Validates a sequence of operations. If `document` parameter is provided, the sequence is additionally validated against the object tree. | ||
@@ -227,3 +309,38 @@ If there are no errors, returns undefined. If there is an errors, returns a JsonPatchError object with the following properties: | ||
OPERATION_VALUE_OUT_OF_BOUNDS | The specified index MUST NOT be greater than the number of elements in the array | ||
TEST_OPERATION_FAILED | When operation is `test` and the test fails, applies to `applyReducer`. | ||
## `OperationResult` Type | ||
Functions `applyPatch` and `applyOperation` both return `OperationResult` object. This object is: | ||
```ts | ||
{newDocument: any, test?: boolean, removed?: any} | ||
``` | ||
Where: | ||
- `newDocument`: the new state of the document after the patch/operation is applied. | ||
- `test`: if the operation was a `test` operation. This will be its result. | ||
- `removed`: contains the removed, moved, or replaced values from the document after a `remove`, `move` or `replace` operation. | ||
## Validation Notes | ||
Functions `applyPatch`, `applyOperation`, and `validate` accept a `validate`/ `validator` parameter: | ||
- If the `validateOperation` parameter is set to `false`, validation will not occur. | ||
- If set to `true`, the patch is extensively validated before applying using jsonpatch's default validation. | ||
- If set to a `function` callback, the patch is validated using that function. | ||
If you pass a validator, it will be called with four parameters for each operation, `function(operation, index, tree, existingPath)` and it is expected to throw `JsonPatchError` when your conditions are not met. | ||
- `operation` The operation it self. | ||
- `index` `operation`'s index in the patch array (if application). | ||
- `tree` The object that is supposed to be patched. | ||
- `existingPath` the path `operation` points to. | ||
## Overwriting and `move` Operation | ||
When the target of the move operation already exists, it is cached, deep cloned and returned as `removed` in `OperationResult`. | ||
## `undefined`s (JS to JSON projection) | ||
@@ -230,0 +347,0 @@ |
/*! | ||
* https://github.com/Starcounter-Jack/JSON-Patch | ||
* json-patch-duplex.js version: 1.1.10 | ||
* json-patch-duplex.js version: 1.2.0 | ||
* (c) 2013 Joachim Wester | ||
@@ -8,30 +8,59 @@ * MIT license | ||
declare module jsonpatch { | ||
type Patch<T> = AddPatch<T> | RemovePatch | ReplacePatch<T> | MovePatch | CopyPatch | TestPatch<T>; | ||
interface PatchBase { | ||
type Operation = AddOperation<any> | RemoveOperation | ReplaceOperation<any> | MoveOperation | CopyOperation | TestOperation<any> | GetOperation<any>; | ||
interface Validator<T> { | ||
(operation: Operation, index: number, document: T, existingPathFragment: string): void; | ||
} | ||
interface OperationResult<T> { | ||
removed?: any; | ||
test?: boolean; | ||
newDocument: T; | ||
} | ||
interface BaseOperation { | ||
path: string; | ||
} | ||
interface AddPatch<T> extends PatchBase { | ||
interface AddOperation<T> extends BaseOperation { | ||
op: 'add'; | ||
value: T; | ||
} | ||
interface RemovePatch extends PatchBase { | ||
interface RemoveOperation extends BaseOperation { | ||
op: 'remove'; | ||
} | ||
interface ReplacePatch<T> extends PatchBase { | ||
interface ReplaceOperation<T> extends BaseOperation { | ||
op: 'replace'; | ||
value: T; | ||
} | ||
interface MovePatch extends PatchBase { | ||
interface MoveOperation extends BaseOperation { | ||
op: 'move'; | ||
from: string; | ||
} | ||
interface CopyPatch extends PatchBase { | ||
interface CopyOperation extends BaseOperation { | ||
op: 'copy'; | ||
from: string; | ||
} | ||
interface TestPatch<T> extends PatchBase { | ||
interface TestOperation<T> extends BaseOperation { | ||
op: 'test'; | ||
value: T; | ||
} | ||
type JsonPatchErrorName = 'SEQUENCE_NOT_AN_ARRAY' | 'OPERATION_NOT_AN_OBJECT' | 'OPERATION_OP_INVALID' | 'OPERATION_PATH_INVALID' | 'OPERATION_FROM_REQUIRED' | 'OPERATION_VALUE_REQUIRED' | 'OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED' | 'OPERATION_PATH_CANNOT_ADD' | 'OPERATION_PATH_UNRESOLVABLE' | 'OPERATION_FROM_UNRESOLVABLE' | 'OPERATION_PATH_ILLEGAL_ARRAY_INDEX' | 'OPERATION_VALUE_OUT_OF_BOUNDS'; | ||
interface GetOperation<T> extends BaseOperation { | ||
op: '_get'; | ||
value: T; | ||
} | ||
interface PatchResult<T> extends Array<OperationResult<T>> { | ||
newDocument: T; | ||
} | ||
/** DEPRECATED. Use `Operation` */ | ||
type Patch<T> = Operation; | ||
/** DEPRECATED. Use `AddOperation` */ | ||
type AddPatch<T> = AddOperation<T>; | ||
/** DEPRECATED. Use `RemoveOperation` */ | ||
type RemovePatch = RemoveOperation; | ||
/** DEPRECATED. Use `ReplaceOperation` */ | ||
type ReplacePatch<T> = ReplaceOperation<T>; | ||
/** DEPRECATED. Use `MoveOperation` */ | ||
type MovePatch = MoveOperation; | ||
/** DEPRECATED. Use `CopyOperation` */ | ||
type CopyPatch = CopyOperation; | ||
/** DEPRECATED. Use `TestOperation` */ | ||
type TestPatch<T> = TestOperation<T>; | ||
type JsonPatchErrorName = 'SEQUENCE_NOT_AN_ARRAY' | 'OPERATION_NOT_AN_OBJECT' | 'OPERATION_OP_INVALID' | 'OPERATION_PATH_INVALID' | 'OPERATION_FROM_REQUIRED' | 'OPERATION_VALUE_REQUIRED' | 'OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED' | 'OPERATION_PATH_CANNOT_ADD' | 'OPERATION_PATH_UNRESOLVABLE' | 'OPERATION_FROM_UNRESOLVABLE' | 'OPERATION_PATH_ILLEGAL_ARRAY_INDEX' | 'OPERATION_VALUE_OUT_OF_BOUNDS' | 'TEST_OPERATION_FAILED'; | ||
interface Observer<T> { | ||
@@ -56,3 +85,45 @@ object: T; | ||
/** | ||
* Apply a json-patch operation on an object tree | ||
* Escapes a json pointer path | ||
* @param path The raw pointer | ||
* @return the Escaped path | ||
*/ | ||
function escapePathComponent(path: string): string; | ||
/** | ||
* Unescapes a json pointer path | ||
* @param path The escaped pointer | ||
* @return The unescaped path | ||
*/ | ||
function unescapePathComponent(path: string): string; | ||
/** | ||
* Retrieves a value from a JSON document by a JSON pointer. | ||
* Returns the value. | ||
* | ||
* @param document The document to get the value from | ||
* @param pointer an escaped JSON pointer | ||
* @return The retrieved value | ||
*/ | ||
function getValueByPointer(document: any, pointer: string): any; | ||
/** | ||
* Apply a single JSON Patch Operation on a JSON document. | ||
* Returns the {newDocument, result} of the operation. | ||
* | ||
* @param document The document to patch | ||
* @param operation The operation to apply | ||
* @param validateOperation `false` is without validation, `true` to use default jsonpatch's validation, or you can pass a `validateOperation` callback to be used for validation. | ||
* @param mutateDocument Whether to mutate the original document or clone it before applying | ||
* @return `{newDocument, result}` after the operation | ||
*/ | ||
function applyOperation<T>(document: T, operation: Operation, validateOperation?: boolean | Validator<T>, mutateDocument?: boolean): OperationResult<T>; | ||
/** | ||
* Apply a full JSON Patch array on a JSON document. | ||
* Returns the {newDocument, result} of the patch. | ||
* | ||
* @param document The document to patch | ||
* @param patch The patch to apply | ||
* @param validateOperation `false` is without validation, `true` to use default jsonpatch's validation, or you can pass a `validateOperation` callback to be used for validation. | ||
* @return An array of `{newDocument, result}` after the patch | ||
*/ | ||
function applyPatch<T>(document: T, patch: Operation[], validateOperation?: boolean | Validator<T>): PatchResult<T>; | ||
/** | ||
* Apply a JSON Patch on a JSON document. | ||
* Returns an array of results of operations. | ||
@@ -62,8 +133,15 @@ * Each element can either be a boolean (if op == 'test') or | ||
* or just be undefined | ||
* @deprecated | ||
*/ | ||
function apply(tree: any, patches: Patch<any>[], validate?: boolean): any[]; | ||
function apply<T>(document: T, patch: Operation[], validateOperation?: boolean | Validator<T>): any[]; | ||
/** | ||
* Create an array of patches from the differences in two objects | ||
* Apply a single JSON Patch Operation on a JSON document. | ||
* Returns the updated document. | ||
* Suitable as a reducer. | ||
* | ||
* @param document The document to patch | ||
* @param operation The operation to apply | ||
* @return The updated document | ||
*/ | ||
function compare(tree1: any, tree2: any): Patch<any>[]; | ||
function applyReducer<T>(document: T, operation: Operation): T; | ||
class JsonPatchError extends Error { | ||
@@ -81,15 +159,19 @@ message: string; | ||
* @param {number} index - index of operation in the sequence | ||
* @param {object} [tree] - object where the operation is supposed to be applied | ||
* @param {string} [existingPathFragment] - comes along with `tree` | ||
* @param {object} [document] - object where the operation is supposed to be applied | ||
* @param {string} [existingPathFragment] - comes along with `document` | ||
*/ | ||
function validator(operation: Patch<any>, index: number, tree?: any, existingPathFragment?: string): void; | ||
function validator(operation: Patch<any>, index: number, document?: any, existingPathFragment?: string): void; | ||
/** | ||
* Validates a sequence of operations. If `tree` parameter is provided, the sequence is additionally validated against the object tree. | ||
* Validates a sequence of operations. If `document` parameter is provided, the sequence is additionally validated against the object document. | ||
* If error is encountered, returns a JsonPatchError object | ||
* @param sequence | ||
* @param tree | ||
* @param document | ||
* @returns {JsonPatchError|undefined} | ||
*/ | ||
function validate(sequence: Patch<any>[], tree?: any): JsonPatchError; | ||
function validate<T>(sequence: Operation[], document?: T, externalValidator?: Validator<T>): JsonPatchError; | ||
/** | ||
* Create an array of patches from the differences in two objects | ||
*/ | ||
function compare(tree1: any, tree2: any): Patch<any>[]; | ||
} | ||
export default jsonpatch; |
/*! | ||
* https://github.com/Starcounter-Jack/JSON-Patch | ||
* json-patch-duplex.js version: 1.1.10 | ||
* json-patch-duplex.js version: 1.2.0 | ||
* (c) 2013 Joachim Wester | ||
@@ -30,3 +30,3 @@ * MIT license | ||
switch (typeof a) { | ||
case 'undefined': //backward compatibility, but really I think we should return false | ||
case 'undefined': | ||
case 'boolean': | ||
@@ -43,13 +43,28 @@ case 'string': | ||
for (var i = 0, l = a.length; i < l; i++) | ||
if (!_equals(a[i], b[i])) | ||
if (!_equals(a[i], b[i])) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
var aKeys = _objectKeys(a); | ||
var bKeys = _objectKeys(b); | ||
var bLength = bKeys.length; | ||
if (_objectKeys(a).length !== bLength) | ||
return false; | ||
for (var i = 0; i < bLength; i++) | ||
if (!_equals(a[i], b[i])) | ||
for (var i_1 = 0; i_1 < aKeys.length; i_1++) { | ||
var key_1 = aKeys[i_1]; | ||
// check all properties of `a` to equal their `b` counterpart | ||
if (!_equals(a[key_1], b[key_1])) { | ||
return false; | ||
} | ||
// remove the key from consideration in next step since we know it's "equal" | ||
var bKeysIdx = bKeys.indexOf(key_1); | ||
if (bKeysIdx >= 0) { | ||
bKeys.splice(bKeysIdx, 1); | ||
} | ||
} | ||
for (var i_2 = 0; i_2 < bKeys.length; i_2++) { | ||
var key = bKeys[i_2]; | ||
// lastly, test any untested properties of `b` | ||
if (!_equals(a[key], b[key])) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
@@ -68,43 +83,39 @@ default: | ||
var objOps = { | ||
add: function (obj, key) { | ||
add: function (obj, key, document) { | ||
obj[key] = this.value; | ||
return { newDocument: document }; | ||
}, | ||
remove: function (obj, key) { | ||
remove: function (obj, key, document) { | ||
var removed = obj[key]; | ||
delete obj[key]; | ||
return removed; | ||
return { newDocument: document, removed: removed }; | ||
}, | ||
replace: function (obj, key) { | ||
replace: function (obj, key, document) { | ||
var removed = obj[key]; | ||
obj[key] = this.value; | ||
return removed; | ||
return { newDocument: document, removed: removed }; | ||
}, | ||
move: function (obj, key, tree) { | ||
var getOriginalDestination = { op: "_get", path: this.path }; | ||
apply(tree, [getOriginalDestination]); | ||
// In case value is moved up and overwrites its ancestor | ||
var original = getOriginalDestination.value === undefined ? | ||
undefined : JSON.parse(JSON.stringify(getOriginalDestination.value)); | ||
var temp = { op: "_get", path: this.from }; | ||
apply(tree, [temp]); | ||
apply(tree, [ | ||
{ op: "remove", path: this.from } | ||
]); | ||
apply(tree, [ | ||
{ op: "add", path: this.path, value: temp.value } | ||
]); | ||
return original; | ||
move: function (obj, key, document) { | ||
/* in case move target overwrites an existing value, | ||
return the removed value, this can be taxing performance-wise, | ||
and is potentially unneeded */ | ||
var removed = getValueByPointer(document, this.path); | ||
if (removed) { | ||
removed = deepClone(removed); | ||
} | ||
var originalValue = applyOperation(document, { op: "remove", path: this.from }).removed; | ||
applyOperation(document, { op: "add", path: this.path, value: originalValue }); | ||
return { newDocument: document, removed: removed }; | ||
}, | ||
copy: function (obj, key, tree) { | ||
var temp = { op: "_get", path: this.from }; | ||
apply(tree, [temp]); | ||
apply(tree, [ | ||
{ op: "add", path: this.path, value: temp.value } | ||
]); | ||
copy: function (obj, key, document) { | ||
var valueToCopy = getValueByPointer(document, this.from); | ||
applyOperation(document, { op: "add", path: this.path, value: valueToCopy }); | ||
return { newDocument: document }; | ||
}, | ||
test: function (obj, key) { | ||
return _equals(obj[key], this.value); | ||
test: function (obj, key, document) { | ||
return { newDocument: document, test: _equals(obj[key], this.value) }; | ||
}, | ||
_get: function (obj, key) { | ||
_get: function (obj, key, document) { | ||
this.value = obj[key]; | ||
return { newDocument: document }; | ||
} | ||
@@ -114,15 +125,15 @@ }; | ||
var arrOps = { | ||
add: function (arr, i) { | ||
add: function (arr, i, document) { | ||
arr.splice(i, 0, this.value); | ||
// this may be needed when using '-' in an array | ||
return i; | ||
return { newDocument: document, index: i }; | ||
}, | ||
remove: function (arr, i) { | ||
remove: function (arr, i, document) { | ||
var removedList = arr.splice(i, 1); | ||
return removedList[0]; | ||
return { newDocument: document, removed: removedList[0] }; | ||
}, | ||
replace: function (arr, i) { | ||
replace: function (arr, i, document) { | ||
var removed = arr[i]; | ||
arr[i] = this.value; | ||
return removed; | ||
return { newDocument: document, removed: removed }; | ||
}, | ||
@@ -134,45 +145,11 @@ move: objOps.move, | ||
}; | ||
/* The operations applicable to object root. Many are the same as for the object */ | ||
var rootOps = { | ||
add: function (obj) { | ||
rootOps.remove.call(this, obj); | ||
for (var key in this.value) { | ||
if (this.value.hasOwnProperty(key)) { | ||
obj[key] = this.value[key]; | ||
} | ||
} | ||
}, | ||
remove: function (obj) { | ||
var removed = {}; | ||
for (var key in obj) { | ||
if (obj.hasOwnProperty(key)) { | ||
removed[key] = obj[key]; | ||
objOps.remove.call(this, obj, key); | ||
} | ||
} | ||
return removed; | ||
}, | ||
replace: function (obj) { | ||
var removed = apply(obj, [ | ||
{ op: "remove", path: this.path } | ||
]); | ||
apply(obj, [ | ||
{ op: "add", path: this.path, value: this.value } | ||
]); | ||
return removed[0]; | ||
}, | ||
move: objOps.move, | ||
copy: objOps.copy, | ||
test: function (obj) { | ||
return (JSON.stringify(obj) === JSON.stringify(this.value)); | ||
}, | ||
_get: function (obj) { | ||
this.value = obj; | ||
} | ||
}; | ||
function escapePathComponent(str) { | ||
if (str.indexOf('/') === -1 && str.indexOf('~') === -1) | ||
return str; | ||
return str.replace(/~/g, '~0').replace(/\//g, '~1'); | ||
var _isArray; | ||
if (Array.isArray) { | ||
_isArray = Array.isArray; | ||
} | ||
else { | ||
_isArray = function (obj) { | ||
return obj.push && typeof obj.length === 'number'; | ||
}; | ||
} | ||
function _getPathRecursive(root, obj) { | ||
@@ -344,3 +321,3 @@ var found; | ||
if (observer.patches.length) { | ||
apply(mirror.value, observer.patches); | ||
applyPatch(mirror.value, observer.patches); | ||
} | ||
@@ -425,23 +402,118 @@ var temp = observer.patches; | ||
/** | ||
* Apply a json-patch operation on an object tree | ||
* Returns an array of results of operations. | ||
* Each element can either be a boolean (if op == 'test') or | ||
* the removed object (operations that remove things) | ||
* or just be undefined | ||
* Escapes a json pointer path | ||
* @param path The raw pointer | ||
* @return the Escaped path | ||
*/ | ||
function escapePathComponent(path) { | ||
if (path.indexOf('/') === -1 && path.indexOf('~') === -1) | ||
return path; | ||
return path.replace(/~/g, '~0').replace(/\//g, '~1'); | ||
} | ||
jsonpatch.escapePathComponent = escapePathComponent; | ||
/** | ||
* Unescapes a json pointer path | ||
* @param path The escaped pointer | ||
* @return The unescaped path | ||
*/ | ||
function apply(tree, patches, validate) { | ||
var results = [], p = 0, plen = patches.length, patch, key; | ||
while (p < plen) { | ||
patch = patches[p]; | ||
p++; | ||
// Find the object | ||
var path = patch.path || ""; | ||
function unescapePathComponent(path) { | ||
return path.replace(/~1/g, '/').replace(/~0/g, '~'); | ||
} | ||
jsonpatch.unescapePathComponent = unescapePathComponent; | ||
/** | ||
* Retrieves a value from a JSON document by a JSON pointer. | ||
* Returns the value. | ||
* | ||
* @param document The document to get the value from | ||
* @param pointer an escaped JSON pointer | ||
* @return The retrieved value | ||
*/ | ||
function getValueByPointer(document, pointer) { | ||
var getOriginalDestination = { op: "_get", path: pointer }; | ||
applyOperation(document, getOriginalDestination); | ||
return getOriginalDestination.value; | ||
} | ||
jsonpatch.getValueByPointer = getValueByPointer; | ||
/** | ||
* Apply a single JSON Patch Operation on a JSON document. | ||
* Returns the {newDocument, result} of the operation. | ||
* | ||
* @param document The document to patch | ||
* @param operation The operation to apply | ||
* @param validateOperation `false` is without validation, `true` to use default jsonpatch's validation, or you can pass a `validateOperation` callback to be used for validation. | ||
* @param mutateDocument Whether to mutate the original document or clone it before applying | ||
* @return `{newDocument, result}` after the operation | ||
*/ | ||
function applyOperation(document, operation, validateOperation, mutateDocument) { | ||
if (validateOperation === void 0) { validateOperation = false; } | ||
if (mutateDocument === void 0) { mutateDocument = true; } | ||
if (validateOperation) { | ||
if (typeof validateOperation == 'function') { | ||
validateOperation(operation, 0, document, operation.path); | ||
} | ||
else { | ||
validator(operation, 0); | ||
} | ||
} | ||
var returnValue = { newDocument: document }; | ||
/* ROOT OPERATIONS */ | ||
if (operation.path === "") { | ||
if (operation.op === 'add') { | ||
returnValue.newDocument = operation.value; | ||
return returnValue; | ||
} | ||
else if (operation.op === 'replace') { | ||
returnValue.newDocument = operation.value; | ||
returnValue.removed = document; //document we removed | ||
return returnValue; | ||
} | ||
else if (operation.op === 'move' || operation.op === 'copy') { | ||
returnValue.newDocument = getValueByPointer(document, operation.from); // get the value by json-pointer in `from` field | ||
if (operation.op === 'move') { | ||
returnValue.removed = document; | ||
} | ||
return returnValue; | ||
} | ||
else if (operation.op === 'test') { | ||
returnValue.test = _equals(document, operation.value); | ||
if (returnValue.test === false) { | ||
throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', 0, operation, document); | ||
} | ||
returnValue.newDocument = document; | ||
return returnValue; | ||
} | ||
else if (operation.op === 'remove') { | ||
returnValue.removed = document; | ||
returnValue.newDocument = null; | ||
return returnValue; | ||
} | ||
else { | ||
if (validateOperation) { | ||
throw new JsonPatchError('Operation `op` property is not one of operations defined in RFC-6902', 'OPERATION_OP_INVALID', 0, operation, document); | ||
} | ||
else { | ||
return returnValue; | ||
} | ||
} | ||
} /* END ROOT OPERATIONS */ | ||
else { | ||
if (!mutateDocument) { | ||
document = deepClone(document); | ||
} | ||
var path = operation.path || ""; | ||
var keys = path.split('/'); | ||
var obj = tree; | ||
var obj = document; | ||
var t = 1; //skip empty element - http://jsperf.com/to-shift-or-not-to-shift | ||
var len = keys.length; | ||
var existingPathFragment = undefined; | ||
var key = void 0; | ||
var validateFunction = void 0; | ||
if (typeof validateOperation == 'function') { | ||
validateFunction = validateOperation; | ||
} | ||
else { | ||
validateFunction = validator; | ||
} | ||
while (true) { | ||
key = keys[t]; | ||
if (validate) { | ||
if (validateOperation) { | ||
if (existingPathFragment === undefined) { | ||
@@ -452,6 +524,6 @@ if (obj[key] === undefined) { | ||
else if (t == len - 1) { | ||
existingPathFragment = patch.path; | ||
existingPathFragment = operation.path; | ||
} | ||
if (existingPathFragment !== undefined) { | ||
this.validator(patch, p - 1, tree, existingPathFragment); | ||
validateFunction(operation, 0, document, existingPathFragment); | ||
} | ||
@@ -461,8 +533,2 @@ } | ||
t++; | ||
if (key === undefined) { | ||
if (t >= len) { | ||
results.push(rootOps[patch.op].call(patch, obj, key, tree)); // Apply patch | ||
break; | ||
} | ||
} | ||
if (_isArray(obj)) { | ||
@@ -473,21 +539,28 @@ if (key === '-') { | ||
else { | ||
if (validate && !isInteger(key)) { | ||
throw new JsonPatchError("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index", "OPERATION_PATH_ILLEGAL_ARRAY_INDEX", p - 1, patch.path, patch); | ||
if (validateOperation && !isInteger(key)) { | ||
throw new JsonPatchError("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index", "OPERATION_PATH_ILLEGAL_ARRAY_INDEX", 0, operation.path, operation); | ||
} | ||
key = parseInt(key, 10); | ||
key = ~~key; | ||
} | ||
if (t >= len) { | ||
if (validate && patch.op === "add" && key > obj.length) { | ||
throw new JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array", "OPERATION_VALUE_OUT_OF_BOUNDS", p - 1, patch.path, patch); | ||
if (validateOperation && operation.op === "add" && key > obj.length) { | ||
throw new JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array", "OPERATION_VALUE_OUT_OF_BOUNDS", 0, operation.path, operation); | ||
} | ||
results.push(arrOps[patch.op].call(patch, obj, key, tree)); // Apply patch | ||
break; | ||
returnValue = arrOps[operation.op].call(operation, obj, key, document); // Apply patch | ||
if (returnValue.test === false) { | ||
throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', 0, operation, document); | ||
} | ||
return returnValue; | ||
} | ||
} | ||
else { | ||
if (key && key.indexOf('~') != -1) | ||
key = key.replace(/~1/g, '/').replace(/~0/g, '~'); // escape chars | ||
if (key && key.indexOf('~') != -1) { | ||
key = unescapePathComponent(key); | ||
} | ||
if (t >= len) { | ||
results.push(objOps[patch.op].call(patch, obj, key, tree)); // Apply patch | ||
break; | ||
returnValue = objOps[operation.op].call(operation, obj, key, document); // Apply patch | ||
if (returnValue.test === false) { | ||
throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', 0, operation, document); | ||
} | ||
return returnValue; | ||
} | ||
@@ -498,14 +571,80 @@ } | ||
} | ||
} | ||
jsonpatch.applyOperation = applyOperation; | ||
/** | ||
* Apply a full JSON Patch array on a JSON document. | ||
* Returns the {newDocument, result} of the patch. | ||
* | ||
* @param document The document to patch | ||
* @param patch The patch to apply | ||
* @param validateOperation `false` is without validation, `true` to use default jsonpatch's validation, or you can pass a `validateOperation` callback to be used for validation. | ||
* @return An array of `{newDocument, result}` after the patch | ||
*/ | ||
function applyPatch(document, patch, validateOperation) { | ||
var results = new Array(patch.length); | ||
for (var i = 0, length_1 = patch.length; i < length_1; i++) { | ||
results[i] = applyOperation(document, patch[i], validateOperation); | ||
document = results[i].newDocument; // in case root was replaced | ||
} | ||
results.newDocument = document; | ||
return results; | ||
} | ||
jsonpatch.applyPatch = applyPatch; | ||
/** | ||
* Apply a JSON Patch on a JSON document. | ||
* Returns an array of results of operations. | ||
* Each element can either be a boolean (if op == 'test') or | ||
* the removed object (operations that remove things) | ||
* or just be undefined | ||
* @deprecated | ||
*/ | ||
function apply(document, patch, validateOperation) { | ||
console.warn('jsonpatch.apply is deprecated, please use `applyPatch` for applying patch sequences, or `applyOperation` to apply individual operations.'); | ||
var results = new Array(patch.length); | ||
/* this code might be overkill, but will be removed soon, it is to prevent the breaking change of root operations */ | ||
var _loop_1 = function(i, length_2) { | ||
if (patch[i].path == "" && patch[i].op != "remove" && patch[i].op != "test") { | ||
var value_1; | ||
if (patch[i].op == "replace" || patch[i].op == "move") { | ||
results[i] = deepClone(document); | ||
} | ||
if (patch[i].op == "copy" || patch[i].op == "move") { | ||
value_1 = getValueByPointer(document, patch[i].from); | ||
} | ||
if (patch[i].op == "replace" || patch[i].op == "add") { | ||
value_1 = patch[i].value; | ||
} | ||
// empty the object | ||
Object.keys(document).forEach(function (key) { return delete document[key]; }); | ||
//copy everything from value | ||
Object.keys(value_1).forEach(function (key) { return document[key] = value_1[key]; }); | ||
} | ||
else { | ||
results[i] = applyOperation(document, patch[i], validateOperation); | ||
results[i] = results[i].removed || results[i].test; | ||
} | ||
}; | ||
for (var i = 0, length_2 = patch.length; i < length_2; i++) { | ||
_loop_1(i, length_2); | ||
} | ||
return results; | ||
} | ||
jsonpatch.apply = apply; | ||
/** | ||
* Create an array of patches from the differences in two objects | ||
* Apply a single JSON Patch Operation on a JSON document. | ||
* Returns the updated document. | ||
* Suitable as a reducer. | ||
* | ||
* @param document The document to patch | ||
* @param operation The operation to apply | ||
* @return The updated document | ||
*/ | ||
function compare(tree1, tree2) { | ||
var patches = []; | ||
_generate(tree1, tree2, patches, ''); | ||
return patches; | ||
function applyReducer(document, operation) { | ||
var operationResult = applyOperation(document, operation); | ||
if (operationResult.test === false) { | ||
throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', 0, operation, document); | ||
} | ||
return operationResult.newDocument; | ||
} | ||
jsonpatch.compare = compare; | ||
jsonpatch.applyReducer = applyReducer; | ||
// provide scoped __extends for TypeScript's `extend` keyword so it will not provide global one during compilation | ||
@@ -563,29 +702,29 @@ function __extends(d, b) { | ||
* @param {number} index - index of operation in the sequence | ||
* @param {object} [tree] - object where the operation is supposed to be applied | ||
* @param {string} [existingPathFragment] - comes along with `tree` | ||
* @param {object} [document] - object where the operation is supposed to be applied | ||
* @param {string} [existingPathFragment] - comes along with `document` | ||
*/ | ||
function validator(operation, index, tree, existingPathFragment) { | ||
function validator(operation, index, document, existingPathFragment) { | ||
if (typeof operation !== 'object' || operation === null || _isArray(operation)) { | ||
throw new JsonPatchError('Operation is not an object', 'OPERATION_NOT_AN_OBJECT', index, operation, tree); | ||
throw new JsonPatchError('Operation is not an object', 'OPERATION_NOT_AN_OBJECT', index, operation, document); | ||
} | ||
else if (!objOps[operation.op]) { | ||
throw new JsonPatchError('Operation `op` property is not one of operations defined in RFC-6902', 'OPERATION_OP_INVALID', index, operation, tree); | ||
throw new JsonPatchError('Operation `op` property is not one of operations defined in RFC-6902', 'OPERATION_OP_INVALID', index, operation, document); | ||
} | ||
else if (typeof operation.path !== 'string') { | ||
throw new JsonPatchError('Operation `path` property is not a string', 'OPERATION_PATH_INVALID', index, operation, tree); | ||
throw new JsonPatchError('Operation `path` property is not a string', 'OPERATION_PATH_INVALID', index, operation, document); | ||
} | ||
else if (operation.path.indexOf('/') !== 0 && operation.path.length > 0) { | ||
// paths that aren't emptystring should start with "/" | ||
throw new JsonPatchError('Operation `path` property must start with "/"', 'OPERATION_PATH_INVALID', index, operation, tree); | ||
// paths that aren't empty string should start with "/" | ||
throw new JsonPatchError('Operation `path` property must start with "/"', 'OPERATION_PATH_INVALID', index, operation, document); | ||
} | ||
else if ((operation.op === 'move' || operation.op === 'copy') && typeof operation.from !== 'string') { | ||
throw new JsonPatchError('Operation `from` property is not present (applicable in `move` and `copy` operations)', 'OPERATION_FROM_REQUIRED', index, operation, tree); | ||
throw new JsonPatchError('Operation `from` property is not present (applicable in `move` and `copy` operations)', 'OPERATION_FROM_REQUIRED', index, operation, document); | ||
} | ||
else if ((operation.op === 'add' || operation.op === 'replace' || operation.op === 'test') && operation.value === undefined) { | ||
throw new JsonPatchError('Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)', 'OPERATION_VALUE_REQUIRED', index, operation, tree); | ||
throw new JsonPatchError('Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)', 'OPERATION_VALUE_REQUIRED', index, operation, document); | ||
} | ||
else if ((operation.op === 'add' || operation.op === 'replace' || operation.op === 'test') && hasUndefined(operation.value)) { | ||
throw new JsonPatchError('Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)', 'OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED', index, operation, tree); | ||
throw new JsonPatchError('Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)', 'OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED', index, operation, document); | ||
} | ||
else if (tree) { | ||
else if (document) { | ||
if (operation.op == "add") { | ||
@@ -595,3 +734,3 @@ var pathLen = operation.path.split("/").length; | ||
if (pathLen !== existingPathLen + 1 && pathLen !== existingPathLen) { | ||
throw new JsonPatchError('Cannot perform an `add` operation at the desired path', 'OPERATION_PATH_CANNOT_ADD', index, operation, tree); | ||
throw new JsonPatchError('Cannot perform an `add` operation at the desired path', 'OPERATION_PATH_CANNOT_ADD', index, operation, document); | ||
} | ||
@@ -601,3 +740,3 @@ } | ||
if (operation.path !== existingPathFragment) { | ||
throw new JsonPatchError('Cannot perform the operation at a path that does not exist', 'OPERATION_PATH_UNRESOLVABLE', index, operation, tree); | ||
throw new JsonPatchError('Cannot perform the operation at a path that does not exist', 'OPERATION_PATH_UNRESOLVABLE', index, operation, document); | ||
} | ||
@@ -607,5 +746,5 @@ } | ||
var existingValue = { op: "_get", path: operation.from, value: undefined }; | ||
var error = jsonpatch.validate([existingValue], tree); | ||
var error = validate([existingValue], document); | ||
if (error && error.name === 'OPERATION_PATH_UNRESOLVABLE') { | ||
throw new JsonPatchError('Cannot perform the operation from a path that does not exist', 'OPERATION_FROM_UNRESOLVABLE', index, operation, tree); | ||
throw new JsonPatchError('Cannot perform the operation from a path that does not exist', 'OPERATION_FROM_UNRESOLVABLE', index, operation, document); | ||
} | ||
@@ -617,9 +756,9 @@ } | ||
/** | ||
* Validates a sequence of operations. If `tree` parameter is provided, the sequence is additionally validated against the object tree. | ||
* Validates a sequence of operations. If `document` parameter is provided, the sequence is additionally validated against the object document. | ||
* If error is encountered, returns a JsonPatchError object | ||
* @param sequence | ||
* @param tree | ||
* @param document | ||
* @returns {JsonPatchError|undefined} | ||
*/ | ||
function validate(sequence, tree) { | ||
function validate(sequence, document, externalValidator) { | ||
try { | ||
@@ -629,9 +768,10 @@ if (!_isArray(sequence)) { | ||
} | ||
if (tree) { | ||
tree = JSON.parse(JSON.stringify(tree)); //clone tree so that we can safely try applying operations | ||
apply.call(this, tree, sequence, true); | ||
if (document) { | ||
document = JSON.parse(JSON.stringify(document)); //clone document so that we can safely try applying operations | ||
applyPatch(document, sequence, externalValidator || true); | ||
} | ||
else { | ||
externalValidator = externalValidator || validator; | ||
for (var i = 0; i < sequence.length; i++) { | ||
this.validator(sequence[i], i); | ||
externalValidator(sequence[i], i, document, undefined); | ||
} | ||
@@ -650,5 +790,20 @@ } | ||
jsonpatch.validate = validate; | ||
/** | ||
* Create an array of patches from the differences in two objects | ||
*/ | ||
function compare(tree1, tree2) { | ||
var patches = []; | ||
_generate(tree1, tree2, patches, ''); | ||
return patches; | ||
} | ||
jsonpatch.compare = compare; | ||
})(jsonpatch || (jsonpatch = {})); | ||
if (typeof exports !== "undefined") { | ||
exports.apply = jsonpatch.apply; | ||
exports.applyPatch = jsonpatch.applyPatch; | ||
exports.applyOperation = jsonpatch.applyOperation; | ||
exports.applyReducer = jsonpatch.applyReducer; | ||
exports.getValueByPointer = jsonpatch.getValueByPointer; | ||
exports.escapePathComponent = jsonpatch.escapePathComponent; | ||
exports.unescapePathComponent = jsonpatch.unescapePathComponent; | ||
exports.observe = jsonpatch.observe; | ||
@@ -672,3 +827,3 @@ exports.unobserve = jsonpatch.unobserve; | ||
running in a node environment, which breaks | ||
some of them. Here is super light wieght fix. | ||
some of them. Here is super light weight fix. | ||
*/ | ||
@@ -675,0 +830,0 @@ if (isBrowser) { |
/*! | ||
* https://github.com/Starcounter-Jack/JSON-Patch | ||
* json-patch-duplex.js version: 1.1.10 | ||
* json-patch-duplex.js version: 1.2.0 | ||
* (c) 2013 Joachim Wester | ||
* MIT license | ||
*/ | ||
declare module jsonpatch { | ||
type Patch<T> = AddPatch<T> | RemovePatch | ReplacePatch<T> | MovePatch | CopyPatch | TestPatch<T>; | ||
interface PatchBase { | ||
declare namespace jsonpatch { | ||
type Operation = AddOperation<any> | RemoveOperation | ReplaceOperation<any> | MoveOperation | CopyOperation | TestOperation<any> | GetOperation<any>; | ||
interface Validator<T> { | ||
(operation: Operation, index: number, document: T, existingPathFragment: string): void; | ||
} | ||
interface OperationResult<T> { | ||
removed?: any; | ||
test?: boolean; | ||
newDocument: T; | ||
} | ||
interface BaseOperation { | ||
path: string; | ||
} | ||
interface AddPatch<T> extends PatchBase { | ||
interface AddOperation<T> extends BaseOperation { | ||
op: 'add'; | ||
value: T; | ||
} | ||
interface RemovePatch extends PatchBase { | ||
interface RemoveOperation extends BaseOperation { | ||
op: 'remove'; | ||
} | ||
interface ReplacePatch<T> extends PatchBase { | ||
interface ReplaceOperation<T> extends BaseOperation { | ||
op: 'replace'; | ||
value: T; | ||
} | ||
interface MovePatch extends PatchBase { | ||
interface MoveOperation extends BaseOperation { | ||
op: 'move'; | ||
from: string; | ||
} | ||
interface CopyPatch extends PatchBase { | ||
interface CopyOperation extends BaseOperation { | ||
op: 'copy'; | ||
from: string; | ||
} | ||
interface TestPatch<T> extends PatchBase { | ||
interface TestOperation<T> extends BaseOperation { | ||
op: 'test'; | ||
value: T; | ||
} | ||
type JsonPatchErrorName = 'SEQUENCE_NOT_AN_ARRAY' | 'OPERATION_NOT_AN_OBJECT' | 'OPERATION_OP_INVALID' | 'OPERATION_PATH_INVALID' | 'OPERATION_FROM_REQUIRED' | 'OPERATION_VALUE_REQUIRED' | 'OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED' | 'OPERATION_PATH_CANNOT_ADD' | 'OPERATION_PATH_UNRESOLVABLE' | 'OPERATION_FROM_UNRESOLVABLE' | 'OPERATION_PATH_ILLEGAL_ARRAY_INDEX' | 'OPERATION_VALUE_OUT_OF_BOUNDS'; | ||
interface GetOperation<T> extends BaseOperation { | ||
op: '_get'; | ||
value: T; | ||
} | ||
interface PatchResult<T> extends Array<OperationResult<T>> { | ||
newDocument: T; | ||
} | ||
/** DEPRECATED. Use `Operation` */ | ||
type Patch<T> = Operation; | ||
/** DEPRECATED. Use `AddOperation` */ | ||
type AddPatch<T> = AddOperation<T>; | ||
/** DEPRECATED. Use `RemoveOperation` */ | ||
type RemovePatch = RemoveOperation; | ||
/** DEPRECATED. Use `ReplaceOperation` */ | ||
type ReplacePatch<T> = ReplaceOperation<T>; | ||
/** DEPRECATED. Use `MoveOperation` */ | ||
type MovePatch = MoveOperation; | ||
/** DEPRECATED. Use `CopyOperation` */ | ||
type CopyPatch = CopyOperation; | ||
/** DEPRECATED. Use `TestOperation` */ | ||
type TestPatch<T> = TestOperation<T>; | ||
type JsonPatchErrorName = 'SEQUENCE_NOT_AN_ARRAY' | 'OPERATION_NOT_AN_OBJECT' | 'OPERATION_OP_INVALID' | 'OPERATION_PATH_INVALID' | 'OPERATION_FROM_REQUIRED' | 'OPERATION_VALUE_REQUIRED' | 'OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED' | 'OPERATION_PATH_CANNOT_ADD' | 'OPERATION_PATH_UNRESOLVABLE' | 'OPERATION_FROM_UNRESOLVABLE' | 'OPERATION_PATH_ILLEGAL_ARRAY_INDEX' | 'OPERATION_VALUE_OUT_OF_BOUNDS' | 'TEST_OPERATION_FAILED'; | ||
/** | ||
* Apply a json-patch operation on an object tree | ||
* Escapes a json pointer path | ||
* @param path The raw pointer | ||
* @return the Escaped path | ||
*/ | ||
function escapePathComponent(path: string): string; | ||
/** | ||
* Unescapes a json pointer path | ||
* @param path The escaped pointer | ||
* @return The unescaped path | ||
*/ | ||
function unescapePathComponent(path: string): string; | ||
/** | ||
* Retrieves a value from a JSON document by a JSON pointer. | ||
* Returns the value. | ||
* | ||
* @param document The document to get the value from | ||
* @param pointer an escaped JSON pointer | ||
* @return The retrieved value | ||
*/ | ||
function getValueByPointer(document: any, pointer: string): any; | ||
/** | ||
* Apply a single JSON Patch Operation on a JSON document. | ||
* Returns the {newDocument, result} of the operation. | ||
* | ||
* @param document The document to patch | ||
* @param operation The operation to apply | ||
* @param validateOperation `false` is without validation, `true` to use default jsonpatch's validation, or you can pass a `validateOperation` callback to be used for validation. | ||
* @param mutateDocument Whether to mutate the original document or clone it before applying | ||
* @return `{newDocument, result}` after the operation | ||
*/ | ||
function applyOperation<T>(document: T, operation: Operation, validateOperation?: boolean | Validator<T>, mutateDocument?: boolean): OperationResult<T>; | ||
/** | ||
* Apply a full JSON Patch array on a JSON document. | ||
* Returns the {newDocument, result} of the patch. | ||
* | ||
* @param document The document to patch | ||
* @param patch The patch to apply | ||
* @param validateOperation `false` is without validation, `true` to use default jsonpatch's validation, or you can pass a `validateOperation` callback to be used for validation. | ||
* @return An array of `{newDocument, result}` after the patch, with a `newDocument` property for accessing the final state with ease. | ||
*/ | ||
function applyPatch<T>(document: T, patch: Operation[], validateOperation?: boolean | Validator<T>): PatchResult<T>; | ||
/** | ||
* Apply a JSON Patch on a JSON document. | ||
* Returns an array of results of operations. | ||
@@ -42,4 +113,15 @@ * Each element can either be a boolean (if op == 'test') or | ||
* or just be undefined | ||
* @deprecated | ||
*/ | ||
function apply(tree: any, patches: Patch<any>[], validate?: boolean): any[]; | ||
function apply<T>(document: T, patch: Operation[], validateOperation?: boolean | Validator<T>): any[]; | ||
/** | ||
* Apply a single JSON Patch Operation on a JSON document. | ||
* Returns the updated document. | ||
* Suitable as a reducer. | ||
* | ||
* @param document The document to patch | ||
* @param operation The operation to apply | ||
* @return The updated document | ||
*/ | ||
function applyReducer<T>(document: T, operation: Operation): T; | ||
class JsonPatchError extends Error { | ||
@@ -57,15 +139,15 @@ message: string; | ||
* @param {number} index - index of operation in the sequence | ||
* @param {object} [tree] - object where the operation is supposed to be applied | ||
* @param {string} [existingPathFragment] - comes along with `tree` | ||
* @param {object} [document] - object where the operation is supposed to be applied | ||
* @param {string} [existingPathFragment] - comes along with `document` | ||
*/ | ||
function validator(operation: Patch<any>, index: number, tree?: any, existingPathFragment?: string): void; | ||
function validator(operation: Patch<any>, index: number, document?: any, existingPathFragment?: string): void; | ||
/** | ||
* Validates a sequence of operations. If `tree` parameter is provided, the sequence is additionally validated against the object tree. | ||
* Validates a sequence of operations. If `document` parameter is provided, the sequence is additionally validated against the object document. | ||
* If error is encountered, returns a JsonPatchError object | ||
* @param sequence | ||
* @param tree | ||
* @param document | ||
* @returns {JsonPatchError|undefined} | ||
*/ | ||
function validate(sequence: Patch<any>[], tree?: any): JsonPatchError; | ||
function validate<T>(sequence: Operation[], document?: T, externalValidator?: Validator<T>): JsonPatchError; | ||
} | ||
export default jsonpatch; |
/*! | ||
* https://github.com/Starcounter-Jack/JSON-Patch | ||
* json-patch-duplex.js version: 1.1.10 | ||
* json-patch-duplex.js version: 1.2.0 | ||
* (c) 2013 Joachim Wester | ||
@@ -30,3 +30,3 @@ * MIT license | ||
switch (typeof a) { | ||
case 'undefined': //backward compatibility, but really I think we should return false | ||
case 'undefined': | ||
case 'boolean': | ||
@@ -43,13 +43,28 @@ case 'string': | ||
for (var i = 0, l = a.length; i < l; i++) | ||
if (!_equals(a[i], b[i])) | ||
if (!_equals(a[i], b[i])) { | ||
return false; | ||
} | ||
return true; | ||
} | ||
var aKeys = _objectKeys(a); | ||
var bKeys = _objectKeys(b); | ||
var bLength = bKeys.length; | ||
if (_objectKeys(a).length !== bLength) | ||
return false; | ||
for (var i = 0; i < bLength; i++) | ||
if (!_equals(a[i], b[i])) | ||
for (var i_1 = 0; i_1 < aKeys.length; i_1++) { | ||
var key_1 = aKeys[i_1]; | ||
// check all properties of `a` to equal their `b` counterpart | ||
if (!_equals(a[key_1], b[key_1])) { | ||
return false; | ||
} | ||
// remove the key from consideration in next step since we know it's "equal" | ||
var bKeysIdx = bKeys.indexOf(key_1); | ||
if (bKeysIdx >= 0) { | ||
bKeys.splice(bKeysIdx, 1); | ||
} | ||
} | ||
for (var i_2 = 0; i_2 < bKeys.length; i_2++) { | ||
var key = bKeys[i_2]; | ||
// lastly, test any untested properties of `b` | ||
if (!_equals(a[key], b[key])) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
@@ -60,2 +75,12 @@ default: | ||
} | ||
function deepClone(obj) { | ||
switch (typeof obj) { | ||
case "object": | ||
return JSON.parse(JSON.stringify(obj)); //Faster than ES5 clone - http://jsperf.com/deep-cloning-of-objects/5 | ||
case "undefined": | ||
return null; //this is how JSON.stringify behaves for array items | ||
default: | ||
return obj; //no need to clone primitives | ||
} | ||
} | ||
/* We use a Javascript hash to store each | ||
@@ -69,43 +94,39 @@ function. Each hash entry (property) uses | ||
var objOps = { | ||
add: function (obj, key) { | ||
add: function (obj, key, document) { | ||
obj[key] = this.value; | ||
return { newDocument: document }; | ||
}, | ||
remove: function (obj, key) { | ||
remove: function (obj, key, document) { | ||
var removed = obj[key]; | ||
delete obj[key]; | ||
return removed; | ||
return { newDocument: document, removed: removed }; | ||
}, | ||
replace: function (obj, key) { | ||
replace: function (obj, key, document) { | ||
var removed = obj[key]; | ||
obj[key] = this.value; | ||
return removed; | ||
return { newDocument: document, removed: removed }; | ||
}, | ||
move: function (obj, key, tree) { | ||
var getOriginalDestination = { op: "_get", path: this.path }; | ||
apply(tree, [getOriginalDestination]); | ||
// In case value is moved up and overwrites its ancestor | ||
var original = getOriginalDestination.value === undefined ? | ||
undefined : JSON.parse(JSON.stringify(getOriginalDestination.value)); | ||
var temp = { op: "_get", path: this.from }; | ||
apply(tree, [temp]); | ||
apply(tree, [ | ||
{ op: "remove", path: this.from } | ||
]); | ||
apply(tree, [ | ||
{ op: "add", path: this.path, value: temp.value } | ||
]); | ||
return original; | ||
move: function (obj, key, document) { | ||
/* in case move target overwrites an existing value, | ||
return the removed value, this can be taxing performance-wise, | ||
and is potentially unneeded */ | ||
var removed = getValueByPointer(document, this.path); | ||
if (removed) { | ||
removed = deepClone(removed); | ||
} | ||
var originalValue = applyOperation(document, { op: "remove", path: this.from }).removed; | ||
applyOperation(document, { op: "add", path: this.path, value: originalValue }); | ||
return { newDocument: document, removed: removed }; | ||
}, | ||
copy: function (obj, key, tree) { | ||
var temp = { op: "_get", path: this.from }; | ||
apply(tree, [temp]); | ||
apply(tree, [ | ||
{ op: "add", path: this.path, value: temp.value } | ||
]); | ||
copy: function (obj, key, document) { | ||
var valueToCopy = getValueByPointer(document, this.from); | ||
applyOperation(document, { op: "add", path: this.path, value: valueToCopy }); | ||
return { newDocument: document }; | ||
}, | ||
test: function (obj, key) { | ||
return _equals(obj[key], this.value); | ||
test: function (obj, key, document) { | ||
return { newDocument: document, test: _equals(obj[key], this.value) }; | ||
}, | ||
_get: function (obj, key) { | ||
_get: function (obj, key, document) { | ||
this.value = obj[key]; | ||
return { newDocument: document }; | ||
} | ||
@@ -115,15 +136,15 @@ }; | ||
var arrOps = { | ||
add: function (arr, i) { | ||
add: function (arr, i, document) { | ||
arr.splice(i, 0, this.value); | ||
// this may be needed when using '-' in an array | ||
return i; | ||
return { newDocument: document, index: i }; | ||
}, | ||
remove: function (arr, i) { | ||
remove: function (arr, i, document) { | ||
var removedList = arr.splice(i, 1); | ||
return removedList[0]; | ||
return { newDocument: document, removed: removedList[0] }; | ||
}, | ||
replace: function (arr, i) { | ||
replace: function (arr, i, document) { | ||
var removed = arr[i]; | ||
arr[i] = this.value; | ||
return removed; | ||
return { newDocument: document, removed: removed }; | ||
}, | ||
@@ -135,40 +156,2 @@ move: objOps.move, | ||
}; | ||
/* The operations applicable to object root. Many are the same as for the object */ | ||
var rootOps = { | ||
add: function (obj) { | ||
rootOps.remove.call(this, obj); | ||
for (var key in this.value) { | ||
if (this.value.hasOwnProperty(key)) { | ||
obj[key] = this.value[key]; | ||
} | ||
} | ||
}, | ||
remove: function (obj) { | ||
var removed = {}; | ||
for (var key in obj) { | ||
if (obj.hasOwnProperty(key)) { | ||
removed[key] = obj[key]; | ||
objOps.remove.call(this, obj, key); | ||
} | ||
} | ||
return removed; | ||
}, | ||
replace: function (obj) { | ||
var removed = apply(obj, [ | ||
{ op: "remove", path: this.path } | ||
]); | ||
apply(obj, [ | ||
{ op: "add", path: this.path, value: this.value } | ||
]); | ||
return removed[0]; | ||
}, | ||
move: objOps.move, | ||
copy: objOps.copy, | ||
test: function (obj) { | ||
return (JSON.stringify(obj) === JSON.stringify(this.value)); | ||
}, | ||
_get: function (obj) { | ||
this.value = obj; | ||
} | ||
}; | ||
var _isArray; | ||
@@ -199,23 +182,118 @@ if (Array.isArray) { | ||
/** | ||
* Apply a json-patch operation on an object tree | ||
* Returns an array of results of operations. | ||
* Each element can either be a boolean (if op == 'test') or | ||
* the removed object (operations that remove things) | ||
* or just be undefined | ||
* Escapes a json pointer path | ||
* @param path The raw pointer | ||
* @return the Escaped path | ||
*/ | ||
function escapePathComponent(path) { | ||
if (path.indexOf('/') === -1 && path.indexOf('~') === -1) | ||
return path; | ||
return path.replace(/~/g, '~0').replace(/\//g, '~1'); | ||
} | ||
jsonpatch.escapePathComponent = escapePathComponent; | ||
/** | ||
* Unescapes a json pointer path | ||
* @param path The escaped pointer | ||
* @return The unescaped path | ||
*/ | ||
function apply(tree, patches, validate) { | ||
var results = new Array(patches.length), p = 0, plen = patches.length, patch, key; | ||
while (p < plen) { | ||
patch = patches[p]; | ||
p++; | ||
// Find the object | ||
var path = patch.path || ""; | ||
function unescapePathComponent(path) { | ||
return path.replace(/~1/g, '/').replace(/~0/g, '~'); | ||
} | ||
jsonpatch.unescapePathComponent = unescapePathComponent; | ||
/** | ||
* Retrieves a value from a JSON document by a JSON pointer. | ||
* Returns the value. | ||
* | ||
* @param document The document to get the value from | ||
* @param pointer an escaped JSON pointer | ||
* @return The retrieved value | ||
*/ | ||
function getValueByPointer(document, pointer) { | ||
var getOriginalDestination = { op: "_get", path: pointer }; | ||
applyOperation(document, getOriginalDestination); | ||
return getOriginalDestination.value; | ||
} | ||
jsonpatch.getValueByPointer = getValueByPointer; | ||
/** | ||
* Apply a single JSON Patch Operation on a JSON document. | ||
* Returns the {newDocument, result} of the operation. | ||
* | ||
* @param document The document to patch | ||
* @param operation The operation to apply | ||
* @param validateOperation `false` is without validation, `true` to use default jsonpatch's validation, or you can pass a `validateOperation` callback to be used for validation. | ||
* @param mutateDocument Whether to mutate the original document or clone it before applying | ||
* @return `{newDocument, result}` after the operation | ||
*/ | ||
function applyOperation(document, operation, validateOperation, mutateDocument) { | ||
if (validateOperation === void 0) { validateOperation = false; } | ||
if (mutateDocument === void 0) { mutateDocument = true; } | ||
if (validateOperation) { | ||
if (typeof validateOperation == 'function') { | ||
validateOperation(operation, 0, document, operation.path); | ||
} | ||
else { | ||
validator(operation, 0); | ||
} | ||
} | ||
/* ROOT OPERATIONS */ | ||
if (operation.path === "") { | ||
var returnValue = { newDocument: document }; | ||
if (operation.op === 'add') { | ||
returnValue.newDocument = operation.value; | ||
return returnValue; | ||
} | ||
else if (operation.op === 'replace') { | ||
returnValue.newDocument = operation.value; | ||
returnValue.removed = document; //document we removed | ||
return returnValue; | ||
} | ||
else if (operation.op === 'move' || operation.op === 'copy') { | ||
returnValue.newDocument = getValueByPointer(document, operation.from); // get the value by json-pointer in `from` field | ||
if (operation.op === 'move') { | ||
returnValue.removed = document; | ||
} | ||
return returnValue; | ||
} | ||
else if (operation.op === 'test') { | ||
returnValue.test = _equals(document, operation.value); | ||
if (returnValue.test === false) { | ||
throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', 0, operation, document); | ||
} | ||
returnValue.newDocument = document; | ||
return returnValue; | ||
} | ||
else if (operation.op === 'remove') { | ||
returnValue.removed = document; | ||
returnValue.newDocument = null; | ||
return returnValue; | ||
} | ||
else { | ||
if (validateOperation) { | ||
throw new JsonPatchError('Operation `op` property is not one of operations defined in RFC-6902', 'OPERATION_OP_INVALID', 0, operation, document); | ||
} | ||
else { | ||
return returnValue; | ||
} | ||
} | ||
} /* END ROOT OPERATIONS */ | ||
else { | ||
if (!mutateDocument) { | ||
document = deepClone(document); | ||
} | ||
var path = operation.path || ""; | ||
var keys = path.split('/'); | ||
var obj = tree; | ||
var obj = document; | ||
var t = 1; //skip empty element - http://jsperf.com/to-shift-or-not-to-shift | ||
var len = keys.length; | ||
var existingPathFragment = undefined; | ||
var key = void 0; | ||
var validateFunction = void 0; | ||
if (typeof validateOperation == 'function') { | ||
validateFunction = validateOperation; | ||
} | ||
else { | ||
validateFunction = validator; | ||
} | ||
while (true) { | ||
key = keys[t]; | ||
if (validate) { | ||
if (validateOperation) { | ||
if (existingPathFragment === undefined) { | ||
@@ -226,6 +304,6 @@ if (obj[key] === undefined) { | ||
else if (t == len - 1) { | ||
existingPathFragment = patch.path; | ||
existingPathFragment = operation.path; | ||
} | ||
if (existingPathFragment !== undefined) { | ||
this.validator(patch, p - 1, tree, existingPathFragment); | ||
validateFunction(operation, 0, document, existingPathFragment); | ||
} | ||
@@ -235,8 +313,2 @@ } | ||
t++; | ||
if (key === undefined) { | ||
if (t >= len) { | ||
results[p - 1] = rootOps[patch.op].call(patch, obj, key, tree); // Apply patch | ||
break; | ||
} | ||
} | ||
if (_isArray(obj)) { | ||
@@ -247,21 +319,28 @@ if (key === '-') { | ||
else { | ||
if (validate && !isInteger(key)) { | ||
throw new JsonPatchError("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index", "OPERATION_PATH_ILLEGAL_ARRAY_INDEX", p - 1, patch.path, patch); | ||
if (validateOperation && !isInteger(key)) { | ||
throw new JsonPatchError("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index", "OPERATION_PATH_ILLEGAL_ARRAY_INDEX", 0, operation.path, operation); | ||
} | ||
key = parseInt(key, 10); | ||
key = ~~key; | ||
} | ||
if (t >= len) { | ||
if (validate && patch.op === "add" && key > obj.length) { | ||
throw new JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array", "OPERATION_VALUE_OUT_OF_BOUNDS", p - 1, patch.path, patch); | ||
if (validateOperation && operation.op === "add" && key > obj.length) { | ||
throw new JsonPatchError("The specified index MUST NOT be greater than the number of elements in the array", "OPERATION_VALUE_OUT_OF_BOUNDS", 0, operation.path, operation); | ||
} | ||
results[p - 1] = arrOps[patch.op].call(patch, obj, key, tree); // Apply patch | ||
break; | ||
var returnValue = arrOps[operation.op].call(operation, obj, key, document); // Apply patch | ||
if (returnValue.test === false) { | ||
throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', 0, operation, document); | ||
} | ||
return returnValue; | ||
} | ||
} | ||
else { | ||
if (key && key.indexOf('~') != -1) | ||
key = key.replace(/~1/g, '/').replace(/~0/g, '~'); // escape chars | ||
if (key && key.indexOf('~') != -1) { | ||
key = unescapePathComponent(key); | ||
} | ||
if (t >= len) { | ||
results[p - 1] = objOps[patch.op].call(patch, obj, key, tree); // Apply patch | ||
break; | ||
var returnValue = objOps[operation.op].call(operation, obj, key, document); // Apply patch | ||
if (returnValue.test === false) { | ||
throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', 0, operation, document); | ||
} | ||
return returnValue; | ||
} | ||
@@ -272,5 +351,80 @@ } | ||
} | ||
} | ||
jsonpatch.applyOperation = applyOperation; | ||
/** | ||
* Apply a full JSON Patch array on a JSON document. | ||
* Returns the {newDocument, result} of the patch. | ||
* | ||
* @param document The document to patch | ||
* @param patch The patch to apply | ||
* @param validateOperation `false` is without validation, `true` to use default jsonpatch's validation, or you can pass a `validateOperation` callback to be used for validation. | ||
* @return An array of `{newDocument, result}` after the patch, with a `newDocument` property for accessing the final state with ease. | ||
*/ | ||
function applyPatch(document, patch, validateOperation) { | ||
var results = new Array(patch.length); | ||
for (var i = 0, length_1 = patch.length; i < length_1; i++) { | ||
results[i] = applyOperation(document, patch[i], validateOperation); | ||
document = results[i].newDocument; // in case root was replaced | ||
} | ||
results.newDocument = document; | ||
return results; | ||
} | ||
jsonpatch.applyPatch = applyPatch; | ||
/** | ||
* Apply a JSON Patch on a JSON document. | ||
* Returns an array of results of operations. | ||
* Each element can either be a boolean (if op == 'test') or | ||
* the removed object (operations that remove things) | ||
* or just be undefined | ||
* @deprecated | ||
*/ | ||
function apply(document, patch, validateOperation) { | ||
console.warn('jsonpatch.apply is deprecated, please use `applyPatch` for applying patch sequences, or `applyOperation` to apply individual operations.'); | ||
var results = new Array(patch.length); | ||
/* this code might be overkill, but will be removed soon, it is to prevent the breaking change of root operations */ | ||
var _loop_1 = function(i, length_2) { | ||
if (patch[i].path == "" && patch[i].op != "remove" && patch[i].op != "test") { | ||
var value_1; | ||
if (patch[i].op == "replace" || patch[i].op == "move") { | ||
results[i] = deepClone(document); | ||
} | ||
if (patch[i].op == "copy" || patch[i].op == "move") { | ||
value_1 = getValueByPointer(document, patch[i].from); | ||
} | ||
if (patch[i].op == "replace" || patch[i].op == "add") { | ||
value_1 = patch[i].value; | ||
} | ||
// empty the object | ||
Object.keys(document).forEach(function (key) { return delete document[key]; }); | ||
//copy everything from value | ||
Object.keys(value_1).forEach(function (key) { return document[key] = value_1[key]; }); | ||
} | ||
else { | ||
results[i] = applyOperation(document, patch[i], validateOperation); | ||
results[i] = results[i].removed || results[i].test; | ||
} | ||
}; | ||
for (var i = 0, length_2 = patch.length; i < length_2; i++) { | ||
_loop_1(i, length_2); | ||
} | ||
return results; | ||
} | ||
jsonpatch.apply = apply; | ||
/** | ||
* Apply a single JSON Patch Operation on a JSON document. | ||
* Returns the updated document. | ||
* Suitable as a reducer. | ||
* | ||
* @param document The document to patch | ||
* @param operation The operation to apply | ||
* @return The updated document | ||
*/ | ||
function applyReducer(document, operation) { | ||
var operationResult = applyOperation(document, operation); | ||
if (operationResult.test === false) { | ||
throw new JsonPatchError("Test operation failed", 'TEST_OPERATION_FAILED', 0, operation, document); | ||
} | ||
return operationResult.newDocument; | ||
} | ||
jsonpatch.applyReducer = applyReducer; | ||
// provide scoped __extends for TypeScript's `extend` keyword so it will not provide global one during compilation | ||
@@ -328,29 +482,29 @@ function __extends(d, b) { | ||
* @param {number} index - index of operation in the sequence | ||
* @param {object} [tree] - object where the operation is supposed to be applied | ||
* @param {string} [existingPathFragment] - comes along with `tree` | ||
* @param {object} [document] - object where the operation is supposed to be applied | ||
* @param {string} [existingPathFragment] - comes along with `document` | ||
*/ | ||
function validator(operation, index, tree, existingPathFragment) { | ||
function validator(operation, index, document, existingPathFragment) { | ||
if (typeof operation !== 'object' || operation === null || _isArray(operation)) { | ||
throw new JsonPatchError('Operation is not an object', 'OPERATION_NOT_AN_OBJECT', index, operation, tree); | ||
throw new JsonPatchError('Operation is not an object', 'OPERATION_NOT_AN_OBJECT', index, operation, document); | ||
} | ||
else if (!objOps[operation.op]) { | ||
throw new JsonPatchError('Operation `op` property is not one of operations defined in RFC-6902', 'OPERATION_OP_INVALID', index, operation, tree); | ||
throw new JsonPatchError('Operation `op` property is not one of operations defined in RFC-6902', 'OPERATION_OP_INVALID', index, operation, document); | ||
} | ||
else if (typeof operation.path !== 'string') { | ||
throw new JsonPatchError('Operation `path` property is not a string', 'OPERATION_PATH_INVALID', index, operation, tree); | ||
throw new JsonPatchError('Operation `path` property is not a string', 'OPERATION_PATH_INVALID', index, operation, document); | ||
} | ||
else if (operation.path.indexOf('/') !== 0 && operation.path.length > 0) { | ||
// paths that aren't emptystring should start with "/" | ||
throw new JsonPatchError('Operation `path` property must start with "/"', 'OPERATION_PATH_INVALID', index, operation, tree); | ||
// paths that aren't empty string should start with "/" | ||
throw new JsonPatchError('Operation `path` property must start with "/"', 'OPERATION_PATH_INVALID', index, operation, document); | ||
} | ||
else if ((operation.op === 'move' || operation.op === 'copy') && typeof operation.from !== 'string') { | ||
throw new JsonPatchError('Operation `from` property is not present (applicable in `move` and `copy` operations)', 'OPERATION_FROM_REQUIRED', index, operation, tree); | ||
throw new JsonPatchError('Operation `from` property is not present (applicable in `move` and `copy` operations)', 'OPERATION_FROM_REQUIRED', index, operation, document); | ||
} | ||
else if ((operation.op === 'add' || operation.op === 'replace' || operation.op === 'test') && operation.value === undefined) { | ||
throw new JsonPatchError('Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)', 'OPERATION_VALUE_REQUIRED', index, operation, tree); | ||
throw new JsonPatchError('Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)', 'OPERATION_VALUE_REQUIRED', index, operation, document); | ||
} | ||
else if ((operation.op === 'add' || operation.op === 'replace' || operation.op === 'test') && hasUndefined(operation.value)) { | ||
throw new JsonPatchError('Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)', 'OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED', index, operation, tree); | ||
throw new JsonPatchError('Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)', 'OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED', index, operation, document); | ||
} | ||
else if (tree) { | ||
else if (document) { | ||
if (operation.op == "add") { | ||
@@ -360,3 +514,3 @@ var pathLen = operation.path.split("/").length; | ||
if (pathLen !== existingPathLen + 1 && pathLen !== existingPathLen) { | ||
throw new JsonPatchError('Cannot perform an `add` operation at the desired path', 'OPERATION_PATH_CANNOT_ADD', index, operation, tree); | ||
throw new JsonPatchError('Cannot perform an `add` operation at the desired path', 'OPERATION_PATH_CANNOT_ADD', index, operation, document); | ||
} | ||
@@ -366,3 +520,3 @@ } | ||
if (operation.path !== existingPathFragment) { | ||
throw new JsonPatchError('Cannot perform the operation at a path that does not exist', 'OPERATION_PATH_UNRESOLVABLE', index, operation, tree); | ||
throw new JsonPatchError('Cannot perform the operation at a path that does not exist', 'OPERATION_PATH_UNRESOLVABLE', index, operation, document); | ||
} | ||
@@ -372,5 +526,5 @@ } | ||
var existingValue = { op: "_get", path: operation.from, value: undefined }; | ||
var error = jsonpatch.validate([existingValue], tree); | ||
var error = validate([existingValue], document); | ||
if (error && error.name === 'OPERATION_PATH_UNRESOLVABLE') { | ||
throw new JsonPatchError('Cannot perform the operation from a path that does not exist', 'OPERATION_FROM_UNRESOLVABLE', index, operation, tree); | ||
throw new JsonPatchError('Cannot perform the operation from a path that does not exist', 'OPERATION_FROM_UNRESOLVABLE', index, operation, document); | ||
} | ||
@@ -382,9 +536,9 @@ } | ||
/** | ||
* Validates a sequence of operations. If `tree` parameter is provided, the sequence is additionally validated against the object tree. | ||
* Validates a sequence of operations. If `document` parameter is provided, the sequence is additionally validated against the object document. | ||
* If error is encountered, returns a JsonPatchError object | ||
* @param sequence | ||
* @param tree | ||
* @param document | ||
* @returns {JsonPatchError|undefined} | ||
*/ | ||
function validate(sequence, tree) { | ||
function validate(sequence, document, externalValidator) { | ||
try { | ||
@@ -394,9 +548,10 @@ if (!_isArray(sequence)) { | ||
} | ||
if (tree) { | ||
tree = JSON.parse(JSON.stringify(tree)); //clone tree so that we can safely try applying operations | ||
apply.call(this, tree, sequence, true); | ||
if (document) { | ||
document = JSON.parse(JSON.stringify(document)); //clone document so that we can safely try applying operations | ||
applyPatch(document, sequence, externalValidator || true); | ||
} | ||
else { | ||
externalValidator = externalValidator || validator; | ||
for (var i = 0; i < sequence.length; i++) { | ||
this.validator(sequence[i], i); | ||
externalValidator(sequence[i], i, document, undefined); | ||
} | ||
@@ -418,2 +573,8 @@ } | ||
exports.apply = jsonpatch.apply; | ||
exports.applyPatch = jsonpatch.applyPatch; | ||
exports.applyOperation = jsonpatch.applyOperation; | ||
exports.applyReducer = jsonpatch.applyReducer; | ||
exports.getValueByPointer = jsonpatch.getValueByPointer; | ||
exports.escapePathComponent = jsonpatch.escapePathComponent; | ||
exports.unescapePathComponent = jsonpatch.unescapePathComponent; | ||
exports.validate = jsonpatch.validate; | ||
@@ -433,3 +594,3 @@ exports.validator = jsonpatch.validator; | ||
running in a node environment, which breaks | ||
some of them. Here is super light wieght fix. | ||
some of them. Here is super light weight fix. | ||
*/ | ||
@@ -436,0 +597,0 @@ if (isBrowser) { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
114636
1745
365
0