Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

fast-json-patch

Package Overview
Dependencies
Maintainers
3
Versions
46
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fast-json-patch - npm Package Compare versions

Comparing version 1.1.10 to 1.2.0

4

dist/json-patch-duplex.min.js
/*!
* 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",

@@ -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) {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc