recursive-diff
Advanced tools
Comparing version 1.0.3 to 1.0.4
@@ -1,18 +0,17 @@ | ||
- 0.1.1 - Added support of **null** value for any key in a object. | ||
- 0.1.1 - Added support of **null** value for any key in a object. | ||
- 0.1.2 - Added support of an Optional **callBack** function in applyDiff method and improving tests. Please check the sample code to know how to use callback. Thanks to [Isabella Cerbinos][1] contribution | ||
- 0.1.4 - Improved error handling, included stack trace in errors. Credits: [Giannis Poulis][2] | ||
- 0.2.0 - Added support for `DATE` type | ||
- 1.0.0 - following are the major changes | ||
- Removed string based path representation | ||
- introduced Array based path | ||
- Refactored code, improved code coverage | ||
- integrated repo badges | ||
- 1.0.1 - security patch and Updated README | ||
- 1.0.2 - Updated README | ||
- 1.0.3 - Added support for typescript | ||
- 1.0.4 - Updated README | ||
- 0.1.2 - Added support of an Optional **callBack** function in applyDiff method and improving tests. Please check the sample code to know how to use callback. Thanks to Isabella Cerbino's contribution ( https://github.com/IsabellaCerbino ) . | ||
[1]: https://github.com/IsabellaCerbino | ||
- 0.1.4 - Improved error handling, included stack trace in errors. Credits: Giannis Poulis | ||
( https://github.com/ioanniswd ) | ||
- 0.2.0 - Added support for `DATE` type | ||
- 1.0.0 - following are the major changes | ||
- Removed string based path representation | ||
- introduced Array based path | ||
- Refactored code, improved code coverage | ||
- integrated repo badges | ||
- 1.0.1 - security patch and Updated README | ||
- 1.0.2 - Updated README | ||
- 1.0.3 - Added support for typescript | ||
[2]: https://github.com/ioanniswd |
@@ -117,3 +117,3 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
eval("const { types, iterableTypes, errors } = __webpack_require__(/*! ./config */ \"./src/config.js\");\nconst utils = __webpack_require__(/*! ./utils */ \"./src/utils.js\");\n\nconst checkType = {\n [types.NUMBER]: utils.isNumber,\n [types.BOOLEAN]: utils.isBoolean,\n [types.STRING]: utils.isString,\n [types.DATE]: utils.isDate,\n [types.UNDEFINED]: utils.isUndefined,\n [types.NULL]: utils.isNull,\n [types.ARRAY]: utils.isArray,\n [types.MAP]: utils.isMap,\n [types.SET]: utils.isSet,\n [types.ITERABLE_OBJECT]: utils.isIterableObject,\n};\n\nconst checkEqualityForComplexTypes = {\n [types.DATE]: utils.areDatesEqual,\n};\n\nfunction getType(x) {\n const keys = Object.keys(checkType);\n let type = types.DEFAULT;\n for (let i = 0; i < keys.length; i += 1) {\n if (checkType[keys[i]](x)) {\n type = keys[i];\n break;\n }\n }\n return type;\n}\n\nfunction isTraversalNeeded(type1, type2) {\n return type1 === type2 && iterableTypes.indexOf(type1) >= 0;\n}\n\nfunction areEqual(x, y, type1, type2) {\n if (type1 !== type2) {\n return false;\n }\n return checkEqualityForComplexTypes[type1] ? checkEqualityForComplexTypes[type1](x, y) : x === y;\n}\n\nfunction compareValuesAndGetDiff(x, y, type1, type2, path, diff) {\n if (type1 === types.UNDEFINED && type2 !== types.UNDEFINED) {\n diff.push({\n path,\n op: 'add',\n val: y,\n });\n } else if (type1 !== types.UNDEFINED && type2 === types.UNDEFINED) {\n diff.push({\n path,\n op: 'delete',\n val: y,\n });\n } else if (!(areEqual(x, y, type1, type2))) {\n diff.push({\n path,\n op: 'update',\n val: y,\n });\n } else {\n utils.noop();\n }\n}\n\nfunction getKeys(x, y, type) {\n let keys;\n if (type === types.ITERABLE_OBJECT) {\n keys = new Set(Object.keys(x).concat(Object.keys(y)));\n } else if (type === types.ARRAY) {\n keys = x.length > y.length ? new Array(x.length) : new Array(y.length);\n keys = keys.fill(0, 0);\n keys = keys.map((el, i) => i);\n keys = new Set(keys);\n }\n return keys;\n}\n\nfunction getDiff(x, y, path, diff) {\n const type1 = getType(x);\n const type2 = getType(y);\n const currPath = path || [];\n const currDiff = diff || [];\n if (isTraversalNeeded(type1, type2)) {\n const iterator = getKeys(x, y, type1).values();\n let key;\n // eslint-disable-next-line no-cond-assign\n while ((key = iterator.next().value) != null) {\n getDiff(x[key], y[key], currPath.concat(key), currDiff);\n }\n } else {\n compareValuesAndGetDiff(x, y, type1, type2, path, currDiff);\n }\n return currDiff;\n}\n\n\nconst opHandlers = {\n add: utils.setValueByPath,\n update: utils.setValueByPath,\n delete: utils.deleteValueByPath,\n};\n\nfunction applyDiff(x, diff, visitorCallback) {\n if (!(diff instanceof Array)) throw new Error(errors.INVALID_DIFF_FORMAT);\n diff.forEach((diffItem) => {\n const { op, val, path } = diffItem;\n if (!opHandlers[op]) {\n throw new Error(errors.INVALID_DIFF_OP);\n }\n // eslint-disable-next-line no-param-reassign\n x = opHandlers[op](x, path, val, visitorCallback);\n });\n return x;\n}\n\nmodule.exports = {\n getDiff,\n applyDiff,\n};\n\n\n//# sourceURL=webpack://recursiveDiff/./src/recursive-diff.js?"); | ||
eval("const { types, iterableTypes, errors } = __webpack_require__(/*! ./config */ \"./src/config.js\");\nconst utils = __webpack_require__(/*! ./utils */ \"./src/utils.js\");\n\nconst checkType = {\n [types.NUMBER]: utils.isNumber,\n [types.BOOLEAN]: utils.isBoolean,\n [types.STRING]: utils.isString,\n [types.DATE]: utils.isDate,\n [types.UNDEFINED]: utils.isUndefined,\n [types.NULL]: utils.isNull,\n [types.ARRAY]: utils.isArray,\n [types.MAP]: utils.isMap,\n [types.SET]: utils.isSet,\n [types.ITERABLE_OBJECT]: utils.isIterableObject,\n};\n\nconst checkEqualityForComplexTypes = {\n [types.DATE]: utils.areDatesEqual,\n};\n\nfunction getType(x) {\n const keys = Object.keys(checkType);\n let type = types.DEFAULT;\n for (let i = 0; i < keys.length; i += 1) {\n if (checkType[keys[i]](x)) {\n type = keys[i];\n break;\n }\n }\n return type;\n}\n\nfunction isTraversalNeeded(type1, type2) {\n return type1 === type2 && iterableTypes.indexOf(type1) >= 0;\n}\n\nfunction areEqual(x, y, type1, type2) {\n if (type1 !== type2) {\n return false;\n }\n return checkEqualityForComplexTypes[type1] ? checkEqualityForComplexTypes[type1](x, y) : x === y;\n}\n\nfunction compareValuesAndGetDiff(x, y, type1, type2, path, diff) {\n if (type1 === types.UNDEFINED && type2 !== types.UNDEFINED) {\n diff.push({\n path,\n op: 'add',\n val: y,\n });\n } else if (type1 !== types.UNDEFINED && type2 === types.UNDEFINED) {\n diff.push({\n path,\n op: 'delete',\n val: y,\n });\n } else if (!(areEqual(x, y, type1, type2))) {\n diff.push({\n path,\n op: 'update',\n val: y,\n });\n } else {\n utils.noop();\n }\n}\n\nfunction getKeys(x, y, type) {\n let keys;\n if (type === types.ITERABLE_OBJECT) {\n keys = new Set(Object.keys(x).concat(Object.keys(y)));\n } else if (type === types.ARRAY) {\n keys = x.length > y.length ? new Array(x.length) : new Array(y.length);\n keys = keys.fill(0, 0);\n keys = keys.map((el, i) => i);\n keys = new Set(keys);\n }\n return keys;\n}\n\nfunction getDiff(x, y, path, diff) {\n const type1 = getType(x);\n const type2 = getType(y);\n const currPath = path || [];\n const currDiff = diff || [];\n if (isTraversalNeeded(type1, type2)) {\n const iterator = getKeys(x, y, type1).values();\n let key = iterator.next().value;\n while (key != null) {\n getDiff(x[key], y[key], currPath.concat(key), currDiff);\n key = iterator.next().value;\n }\n } else {\n compareValuesAndGetDiff(x, y, type1, type2, path, currDiff);\n }\n return currDiff;\n}\n\n\nconst opHandlers = {\n add: utils.setValueByPath,\n update: utils.setValueByPath,\n delete: utils.deleteValueByPath,\n};\n\nfunction applyDiff(x, diff, visitorCallback) {\n if (!(diff instanceof Array)) throw new Error(errors.INVALID_DIFF_FORMAT);\n let y = x;\n diff.forEach((diffItem) => {\n const { op, val, path } = diffItem;\n if (!opHandlers[op]) {\n throw new Error(errors.INVALID_DIFF_OP);\n }\n y = opHandlers[op](y, path, val, visitorCallback);\n });\n return y;\n}\n\nmodule.exports = {\n getDiff,\n applyDiff,\n};\n\n\n//# sourceURL=webpack://recursiveDiff/./src/recursive-diff.js?"); | ||
@@ -120,0 +120,0 @@ /***/ }), |
@@ -1,1 +0,1 @@ | ||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.recursiveDiff=t():e.recursiveDiff=t()}("undefined"!=typeof self?self:this,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){const{types:r,iterableTypes:o,errors:i}=n(1),f=n(2),l={[r.NUMBER]:f.isNumber,[r.BOOLEAN]:f.isBoolean,[r.STRING]:f.isString,[r.DATE]:f.isDate,[r.UNDEFINED]:f.isUndefined,[r.NULL]:f.isNull,[r.ARRAY]:f.isArray,[r.MAP]:f.isMap,[r.SET]:f.isSet,[r.ITERABLE_OBJECT]:f.isIterableObject},u={[r.DATE]:f.areDatesEqual};function a(e){const t=Object.keys(l);let n=r.DEFAULT;for(let r=0;r<t.length;r+=1)if(l[t[r]](e)){n=t[r];break}return n}function s(e,t,n,o,i,l){n===r.UNDEFINED&&o!==r.UNDEFINED?l.push({path:i,op:"add",val:t}):n!==r.UNDEFINED&&o===r.UNDEFINED?l.push({path:i,op:"delete",val:t}):!function(e,t,n,r){return n===r&&(u[n]?u[n](e,t):e===t)}(e,t,n,o)?l.push({path:i,op:"update",val:t}):f.noop()}const c={add:f.setValueByPath,update:f.setValueByPath,delete:f.deleteValueByPath};e.exports={getDiff:function e(t,n,i,f){const l=a(t),u=a(n),c=i||[],p=f||[];if(function(e,t){return e===t&&o.indexOf(e)>=0}(l,u)){const o=function(e,t,n){let o;return n===r.ITERABLE_OBJECT?o=new Set(Object.keys(e).concat(Object.keys(t))):n===r.ARRAY&&(o=e.length>t.length?new Array(e.length):new Array(t.length),o=o.fill(0,0),o=o.map((e,t)=>t),o=new Set(o)),o}(t,n,l).values();let i;for(;null!=(i=o.next().value);)e(t[i],n[i],c.concat(i),p)}else s(t,n,l,u,i,p);return p},applyDiff:function(e,t,n){if(!(t instanceof Array))throw new Error(i.INVALID_DIFF_FORMAT);return t.forEach(t=>{const{op:r,val:o,path:f}=t;if(!c[r])throw new Error(i.INVALID_DIFF_OP);e=c[r](e,f,o,n)}),e}}},function(e,t){const n={NUMBER:"NUMBER",BOOLEAN:"BOOLEAN",STRING:"STRING",NULL:"NULL",UNDEFINED:"UNDEFINED",DATE:"DATE",ARRAY:"ARRAY",MAP:"MAP",SET:"SET",ITERABLE_OBJECT:"ITERABLE_OBJECT",DEFAULT:"OBJECT"};e.exports={types:n,iterableTypes:[n.ITERABLE_OBJECT,n.MAP,n.ARRAY,n.SET],errors:{EMPTY_DIFF:"No diff object is provided, Nothing to apply",INVALID_DIFF_FORMAT:"Invalid diff format",INVALID_DIFF_OP:"Unsupported operation provided into diff object"}}},function(e,t){const n=e=>t=>t instanceof e,r=n(Date),o=n(Array),i=n(Map),f=n(Set),l=e=>"[object Object]"===Object.prototype.toString.call(e);e.exports={isNumber:e=>"number"==typeof e,isBoolean:e=>"boolean"==typeof e,isString:e=>"string"==typeof e,isDate:r,isUndefined:e=>void 0===e,isNull:e=>null===e,isArray:o,isMap:i,isSet:f,isIterableObject:l,noop:()=>{},areDatesEqual:(e,t)=>e.getTime()===t.getTime(),setValueByPath:function(e,t=[],n,r){if(!o(t))throw new Error(`Diff path: "${t}" is not valid`);const{length:i}=t;if(0===i)return n;let f=e;for(let o=0;o<i;o+=1){const l=t[o];if(!f)throw new Error(`Invalid path: "${t}" for object: ${JSON.stringify(e,null,2)}`);if(null==l)throw new Error(`Invalid path: "${t}" for object: ${JSON.stringify(e,null,2)}`);o!==i-1?(f=f[l],r&&r(f)):f[l]=n}return e},deleteValueByPath:function(e,t){const n=t||[];if(0===n.length)return;let r=e;const{length:o}=n;for(let i=0;i<o;i+=1)if(i!==o-1){if(!r[n[i]])throw new Error(`Invalid path: "${t}" for object: ${JSON.stringify(e,null,2)}`);r=r[n[i]]}else if(l(r))delete r[n[i]];else{const e=parseInt(n[i],10);for(;r.length>e;)r.pop()}return e}}}])})); | ||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.recursiveDiff=t():e.recursiveDiff=t()}("undefined"!=typeof self?self:this,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){const{types:r,iterableTypes:o,errors:i}=n(1),l=n(2),f={[r.NUMBER]:l.isNumber,[r.BOOLEAN]:l.isBoolean,[r.STRING]:l.isString,[r.DATE]:l.isDate,[r.UNDEFINED]:l.isUndefined,[r.NULL]:l.isNull,[r.ARRAY]:l.isArray,[r.MAP]:l.isMap,[r.SET]:l.isSet,[r.ITERABLE_OBJECT]:l.isIterableObject},u={[r.DATE]:l.areDatesEqual};function a(e){const t=Object.keys(f);let n=r.DEFAULT;for(let r=0;r<t.length;r+=1)if(f[t[r]](e)){n=t[r];break}return n}function s(e,t,n,o,i,f){n===r.UNDEFINED&&o!==r.UNDEFINED?f.push({path:i,op:"add",val:t}):n!==r.UNDEFINED&&o===r.UNDEFINED?f.push({path:i,op:"delete",val:t}):!function(e,t,n,r){return n===r&&(u[n]?u[n](e,t):e===t)}(e,t,n,o)?f.push({path:i,op:"update",val:t}):l.noop()}const c={add:l.setValueByPath,update:l.setValueByPath,delete:l.deleteValueByPath};e.exports={getDiff:function e(t,n,i,l){const f=a(t),u=a(n),c=i||[],p=l||[];if(function(e,t){return e===t&&o.indexOf(e)>=0}(f,u)){const o=function(e,t,n){let o;return n===r.ITERABLE_OBJECT?o=new Set(Object.keys(e).concat(Object.keys(t))):n===r.ARRAY&&(o=e.length>t.length?new Array(e.length):new Array(t.length),o=o.fill(0,0),o=o.map((e,t)=>t),o=new Set(o)),o}(t,n,f).values();let i=o.next().value;for(;null!=i;)e(t[i],n[i],c.concat(i),p),i=o.next().value}else s(t,n,f,u,i,p);return p},applyDiff:function(e,t,n){if(!(t instanceof Array))throw new Error(i.INVALID_DIFF_FORMAT);let r=e;return t.forEach(e=>{const{op:t,val:o,path:l}=e;if(!c[t])throw new Error(i.INVALID_DIFF_OP);r=c[t](r,l,o,n)}),r}}},function(e,t){const n={NUMBER:"NUMBER",BOOLEAN:"BOOLEAN",STRING:"STRING",NULL:"NULL",UNDEFINED:"UNDEFINED",DATE:"DATE",ARRAY:"ARRAY",MAP:"MAP",SET:"SET",ITERABLE_OBJECT:"ITERABLE_OBJECT",DEFAULT:"OBJECT"};e.exports={types:n,iterableTypes:[n.ITERABLE_OBJECT,n.MAP,n.ARRAY,n.SET],errors:{EMPTY_DIFF:"No diff object is provided, Nothing to apply",INVALID_DIFF_FORMAT:"Invalid diff format",INVALID_DIFF_OP:"Unsupported operation provided into diff object"}}},function(e,t){const n=e=>t=>t instanceof e,r=n(Date),o=n(Array),i=n(Map),l=n(Set),f=e=>"[object Object]"===Object.prototype.toString.call(e);e.exports={isNumber:e=>"number"==typeof e,isBoolean:e=>"boolean"==typeof e,isString:e=>"string"==typeof e,isDate:r,isUndefined:e=>void 0===e,isNull:e=>null===e,isArray:o,isMap:i,isSet:l,isIterableObject:f,noop:()=>{},areDatesEqual:(e,t)=>e.getTime()===t.getTime(),setValueByPath:function(e,t=[],n,r){if(!o(t))throw new Error(`Diff path: "${t}" is not valid`);const{length:i}=t;if(0===i)return n;let l=e;for(let o=0;o<i;o+=1){const f=t[o];if(!l)throw new Error(`Invalid path: "${t}" for object: ${JSON.stringify(e,null,2)}`);if(null==f)throw new Error(`Invalid path: "${t}" for object: ${JSON.stringify(e,null,2)}`);o!==i-1?(l=l[f],r&&r(l)):l[f]=n}return e},deleteValueByPath:function(e,t){const n=t||[];if(0===n.length)return;let r=e;const{length:o}=n;for(let i=0;i<o;i+=1)if(i!==o-1){if(!r[n[i]])throw new Error(`Invalid path: "${t}" for object: ${JSON.stringify(e,null,2)}`);r=r[n[i]]}else if(f(r))delete r[n[i]];else{const e=parseInt(n[i],10);for(;r.length>e;)r.pop()}return e}}}])})); |
{ | ||
"name": "recursive-diff", | ||
"version": "1.0.3", | ||
"version": "1.0.4", | ||
"description": "Find diff between any two variables where variables be any valid JavaScript data type like string, numeric, array or object", | ||
@@ -21,3 +21,3 @@ "main": "src/recursive-diff.js", | ||
"test": "NODE_ENV=test mocha --timeout 10000 test/**/*.spec.js --reporter spec", | ||
"lint": "eslint src", | ||
"lint": "eslint src test", | ||
"build": "webpack --config webpack.config.js", | ||
@@ -32,12 +32,12 @@ "build:dev": "webpack --config webpack.dev.config.js", | ||
"devDependencies": { | ||
"chai": "4.2.0", | ||
"eslint": "^6.6.0", | ||
"eslint-config-airbnb-base": "^14.0.0", | ||
"eslint-plugin-import": "^2.18.2", | ||
"chai": "^4.2.0", | ||
"eslint": "^6.8.0", | ||
"eslint-config-airbnb-base": "^14.1.0", | ||
"eslint-plugin-import": "^2.20.2", | ||
"istanbul": "^0.4.5", | ||
"mocha": "^5.2.0", | ||
"mocha": "^7.1.1", | ||
"nyc": "^15.0.0", | ||
"pre-commit": "^1.2.2", | ||
"webpack": "^4.41.2", | ||
"webpack-cli": "^3.3.10" | ||
"webpack": "^4.42.1", | ||
"webpack-cli": "^3.3.11" | ||
}, | ||
@@ -44,0 +44,0 @@ "keywords": [ |
@@ -10,17 +10,20 @@ [![NPM Version][npm-image]][npm-url] | ||
## A JavaScript library (with TypeScript support) to find diff between two JS Objects/Array, support for complex nested JS Objects | ||
-------- | ||
This library can be used to get diff between two JS Objects/Arrays(or other primitive values). Diff are returned in the form of Array where each ARRAY item represents a change in the original Object/Array. A diff item can have following three properties : | ||
- `path` : An array representation of nested path | ||
- `op` : Can be any one of the following - add, update or delete | ||
- `val` : New value after change | ||
* * * | ||
This library can be used to get diff between two JS Objects/Arrays(or other primitive values). Diff are returned in the form of Array where each ARRAY item represents a change in the original Object/Array. A diff item can have following three properties: | ||
- `path`: An array representation of nested path | ||
- `op`: Can be any one of the following - add, update or delete | ||
- `val`: New value after change | ||
``` | ||
const rdiff = require('recursive-diff'); | ||
const x = { | ||
a: { | ||
const x = { | ||
a: { | ||
b: 1, | ||
c: 2, | ||
d: [1] | ||
} | ||
d: [1] | ||
} | ||
} | ||
@@ -69,15 +72,16 @@ const y = { | ||
## Api details: | ||
## Api details | ||
- **`getDiff(x, y)`:** `getDiff` takes two arguments `x` and `y` and return their diff. `x` and `y` can be Array/Object or even other primitive types such as number, boolean or string. | ||
- **`getDiff(x, y)`:** `getDiff` takes two arguments `x` and `y` and return their diff. `x` and `y` can be Array/Object or even other primitive types such as number, boolean or string. | ||
- **`applyDiff (x, diff, visitorCallbackFn )`**: `applyDiff` takes three arguments: | ||
- x: original value, | ||
- diff: diff returned by `getDiff` API | ||
- visitorCallbackFn (optional): This callback function is called at each depth level while applying the diff. It can be used to stamp the mutation path with some informative labels( eg: `{ isMutated: true}`) by assigning new properties. For more details, please check the examples directory of this repo. | ||
- **`applyDiff (x, diff, visitorCallbackFn)`** `applyDiff` takes three arguments: | ||
- x: original value, | ||
- diff: diff returned by `getDiff` API | ||
- visitorCallbackFn (optional): This callback function is called at each depth level while applying the diff. It can be used to mark the mutation path with some meta properties eg: `{ isMutated: true }`. For more details, please check the examples directory of this repo. | ||
## Using recursive diff library in Node | ||
## Using recursive diff library in Node: | ||
- Install library using the command : `npm install recursive-diff` | ||
- sample code is given below | ||
- Install library using the command : `npm install recursive-diff` | ||
- sample code is given below | ||
``` | ||
@@ -93,31 +97,31 @@ const diff = require('recursive-diff'); | ||
## Using recursive diff library in the Browser: | ||
## Using recursive diff library in the Browser | ||
`'dist/recursive-diff.min.js'` can be directly injected into a HTML page using the URL `https://unpkg.com/recursive-diff@1.0.2/dist/recursive-diff.min.js`. Once it is included into the HTML file, diff API is accessible using `window.recursiveDiff`. Example given below. | ||
``` | ||
<script type="text" src="https://unpkg.com/recursive-diff@1.0.2/dist/recursive-diff.min.js"/> | ||
<script type="text/javascript"> | ||
const ob1 = {a:1}; | ||
const ob2 = {a:2}; | ||
const delta = recursiveDiff.getDiff(ob1,ob2); | ||
const ob3 = recursiveDiff.applyDiff(ob1, delta); //expect ob3 is deep equal to ob2 | ||
</script> | ||
``` | ||
## Using recursive diff library in TypeScript: | ||
``` | ||
import { getDiff, applyDiff, rdiffResult } from 'recursive-diff'; | ||
<script type="text" src="https://unpkg.com/recursive-diff@1.0.2/dist/recursive-diff.min.js"/> | ||
<script type="text/javascript"> | ||
const ob1 = {a:1}; | ||
const ob2 = {a:2}; | ||
const delta = recursiveDiff.getDiff(ob1,ob2); | ||
const ob3 = recursiveDiff.applyDiff(ob1, delta); //expect ob3 is deep equal to ob2 | ||
</script> | ||
const x = [1, 2]; | ||
const y = [2, 3, 4]; | ||
const diff:rdiffResult[] = getDiff([1, 2], 3); | ||
console.log('diff', diff); | ||
const final = applyDiff(x, diff); | ||
console.log('applydiff', final); | ||
``` | ||
## Using recursive diff library in TypeScript | ||
import { getDiff, applyDiff, rdiffResult } from 'recursive-diff'; | ||
const x = [1, 2]; | ||
const y = [2, 3, 4]; | ||
const diff:rdiffResult[] = getDiff([1, 2], 3); | ||
console.log('diff', diff); | ||
const final = applyDiff(x, diff); | ||
console.log('applydiff', final); | ||
## Tests | ||
Unit test can be run using the command `npm test`. This repo has more than 99% code coverage. | ||
## Examples: | ||
## Examples | ||
You can find more examples in the example folder of this repo. Few of the examples are listed below. | ||
@@ -230,8 +234,15 @@ | ||
[npm-image]: https://img.shields.io/npm/v/recursive-diff.svg | ||
[npm-url]: https://npmjs.org/package/recursive-diff | ||
[downloads-image]: https://img.shields.io/npm/dm/recursive-diff.svg | ||
[downloads-url]: https://npmjs.org/package/recursive-diff | ||
[travis-image]: https://img.shields.io/travis/cosmicanant/recursive-diff/master.svg | ||
[travis-url]: https://travis-ci.org/cosmicanant/recursive-diff | ||
[coveralls-image]: https://coveralls.io/repos/github/cosmicanant/recursive-diff/badge.svg?branch=master | ||
[coveralls-url]: https://coveralls.io/github/cosmicanant/recursive-diff?branch=master |
@@ -88,6 +88,6 @@ const { types, iterableTypes, errors } = require('./config'); | ||
const iterator = getKeys(x, y, type1).values(); | ||
let key; | ||
// eslint-disable-next-line no-cond-assign | ||
while ((key = iterator.next().value) != null) { | ||
let key = iterator.next().value; | ||
while (key != null) { | ||
getDiff(x[key], y[key], currPath.concat(key), currDiff); | ||
key = iterator.next().value; | ||
} | ||
@@ -109,2 +109,3 @@ } else { | ||
if (!(diff instanceof Array)) throw new Error(errors.INVALID_DIFF_FORMAT); | ||
let y = x; | ||
diff.forEach((diffItem) => { | ||
@@ -115,6 +116,5 @@ const { op, val, path } = diffItem; | ||
} | ||
// eslint-disable-next-line no-param-reassign | ||
x = opHandlers[op](x, path, val, visitorCallback); | ||
y = opHandlers[op](y, path, val, visitorCallback); | ||
}); | ||
return x; | ||
return y; | ||
} | ||
@@ -121,0 +121,0 @@ |
30896
245