Socket
Socket
Sign inDemoInstall

simple-diff

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

simple-diff - npm Package Compare versions

Comparing version 1.4.0 to 1.5.0

2

bower.json
{
"name": "simple-diff",
"main": "simple-diff.js",
"version": "1.4.0",
"version": "1.5.0",
"homepage": "https://github.com/redexp/simple-diff",

@@ -6,0 +6,0 @@ "authors": [

{
"name": "simple-diff",
"version": "1.4.0",
"version": "1.5.0",
"description": "simple diff for object and arrays with options",

@@ -28,4 +28,6 @@ "main": "simple-diff.js",

"gulp-uglify": "^1.5.4",
"mocha": "^2.5.3"
"mocha": "^2.5.3",
"sinon": "^1.17.7",
"sinon-chai": "^2.8.0"
}
}

@@ -143,2 +143,30 @@ simple-diff

## `comparators: [[Class, function (oldValue, newValue, options)], ...]`
Array of comparators to handle comparison of objects which do not have own properties. For example instead of `user.name` you have `user.getName()` or you need to compare `Date` objects or you just know quick way to compare large objects like by `id` property and you do not need full list of changes of those objects. First value of comparator should be some class and second is function which should return `true` if objects are equal and `false` if they not. In `options` will be `oldPath` and `newPath`.
```javascript
var now = new Date();
var prevHour = new Date();
prevHour.setHours(-1);
var changes = diff(
{
createdAt: now
},
{
createdAt: prevHour
},
{
comparators: [
[Date, function(oldValue, newValue, options) {
options.oldPath; // ['createdAt']
options.newPath; // ['createdAt']
return oldValue.toString() === newValue.toString();
}]
]
}
);
```
## `callback: function (event)`

@@ -145,0 +173,0 @@

@@ -31,2 +31,3 @@ (function (root, factory) {

},
comparators = ops.comparators || [],
i, len, prop, id;

@@ -184,2 +185,25 @@

else {
if (comparators.length > 0) {
for (i = 0, len = comparators.length; i < len; i++) {
if (oldObj instanceof comparators[i][0] === false && newObj instanceof comparators[i][0] === false) continue;
var objEqual = comparators[i][1](oldObj, newObj, {
oldPath: oldPath,
newPath: newPath
});
if (!objEqual) {
callback({
oldPath: oldPath,
newPath: newPath,
type: CHANGE_EVENT,
oldValue: oldObj,
newValue: newObj
});
}
return changes;
}
}
for (prop in oldObj) {

@@ -186,0 +210,0 @@ if (!oldObj.hasOwnProperty(prop)) continue;

@@ -1,1 +0,1 @@

!function(root,factory){"function"==typeof define&&define.amd?define([],factory):"object"==typeof exports?module.exports=factory():root.simpleDiff=factory()}(this,function(){function diff(oldObj,newObj,ops){ops=ops||{};var i,len,prop,id,changes=[],oldPath=ops.oldPath||[],newPath=ops.newPath||[],ID_PROP=ops.idProp||"id",ADD_EVENT=ops.addEvent||"add",REMOVE_EVENT=ops.removeEvent||"remove",CHANGE_EVENT=ops.changeEvent||"change",ADD_ITEM_EVENT=ops.addItemEvent||"add-item",REMOVE_ITEM_EVENT=ops.removeItemEvent||"remove-item",MOVE_ITEM_EVENT=ops.moveItemEvent||"move-item",callback=ops.callback||function(item){changes.push(item)};if(!(isObject(oldObj)&&isObject(newObj)||oldObj===newObj))return callback({oldPath:oldPath,newPath:newPath,type:CHANGE_EVENT,oldValue:oldObj,newValue:newObj}),changes;if(isArray(oldObj)){var idProp=ops.idProps&&(ops.idProps[oldPath.map(numberToAsterisk).join(".")]||ops.idProps[oldPath.join(".")])||ID_PROP;if("*"===idProp){var oldLength=oldObj.length,newLength=newObj.length;for(i=0,len=oldLength>newLength?oldLength:newLength;i<len;i++)i<oldLength&&i<newLength?diff(oldObj[i],newObj[i],extend({},ops,{callback:callback,oldPath:oldPath.concat(i),newPath:newPath.concat(i)})):i>=oldLength?callback({oldPath:oldPath,newPath:newPath,type:ADD_ITEM_EVENT,oldIndex:-1,curIndex:-1,newIndex:i,newValue:newObj[i]}):i>=newLength&&callback({oldPath:oldPath,newPath:newPath,type:REMOVE_ITEM_EVENT,oldIndex:i,curIndex:newLength,newIndex:-1,oldValue:oldObj[i]});return changes}var sample=oldObj.length>0?oldObj[0]:newObj[0];if(sample===UNDEFINED)return changes;var curIndex,oldIndex,objective="object"==typeof sample,oldHash=objective?indexBy(oldObj,idProp):hashOf(oldObj),newHash=objective?indexBy(newObj,idProp):hashOf(newObj),curArray=[].concat(oldObj);for(i=0,len=oldObj.length;i<len;i++)id=objective?oldObj[i][idProp]:oldObj[i],newHash.hasOwnProperty(id)||(curIndex=curArray.indexOf(oldObj[i]),curArray.splice(curIndex,1),callback({oldPath:oldPath,newPath:newPath,type:REMOVE_ITEM_EVENT,oldIndex:i,curIndex:curIndex,newIndex:-1,oldValue:oldObj[i]}));for(i=0,len=newObj.length;i<len;i++)id=objective?newObj[i][idProp]:newObj[i],oldHash.hasOwnProperty(id)||(callback({oldPath:oldPath,newPath:newPath,type:ADD_ITEM_EVENT,oldIndex:-1,curIndex:-1,newIndex:i,newValue:newObj[i]}),i>=curArray.length?curArray.push(newObj[i]):curArray.splice(i,0,newObj[i]));for(i=0,len=newObj.length;i<len;i++)id=objective?newObj[i][idProp]:newObj[i],oldHash.hasOwnProperty(id)&&(oldIndex=oldObj.indexOf(oldHash[id]),curIndex=curArray.indexOf(oldHash[id]),i!==curIndex&&(callback({oldPath:oldPath,newPath:newPath,type:MOVE_ITEM_EVENT,oldIndex:oldIndex,curIndex:curIndex,newIndex:i}),curArray.splice(curIndex,1),curArray.splice(i,0,oldHash[id])),diff(oldHash[id],newObj[i],extend({},ops,{callback:callback,oldPath:oldPath.concat(oldIndex),newPath:newPath.concat(i)})))}else{for(prop in oldObj)oldObj.hasOwnProperty(prop)&&(newObj.hasOwnProperty(prop)?isObject(oldObj[prop])&&isObject(newObj[prop])?diff(oldObj[prop],newObj[prop],extend({},ops,{callback:callback,oldPath:oldPath.concat(prop),newPath:newPath.concat(prop)})):oldObj[prop]!==newObj[prop]&&callback({oldPath:oldPath.concat(prop),newPath:newPath.concat(prop),type:CHANGE_EVENT,oldValue:oldObj[prop],newValue:newObj[prop]}):callback({oldPath:oldPath.concat(prop),newPath:newPath.concat(prop),type:REMOVE_EVENT,oldValue:oldObj[prop],newValue:UNDEFINED}));for(prop in newObj)newObj.hasOwnProperty(prop)&&(oldObj.hasOwnProperty(prop)||callback({oldPath:oldPath.concat(prop),newPath:newPath.concat(prop),type:ADD_EVENT,oldValue:UNDEFINED,newValue:newObj[prop]}))}return changes}function isObject(object){return!!object&&"object"==typeof object}function isArray(array){return Array.isArray?Array.isArray(array):"[object Array]"===Object.prototype.toString.call(array)}function indexBy(array,id){for(var hash={},i=0,len=array.length;i<len;i++)hash[array[i][id]]=array[i];return hash}function hashOf(array){for(var hash={},i=0,len=array.length;i<len;i++)hash[array[i]]=array[i];return hash}function extend(target){for(var i=1,len=arguments.length;i<len;i++){var source=arguments[i];for(var prop in source)source.hasOwnProperty(prop)&&(target[prop]=source[prop])}return target}function numberToAsterisk(value){return"number"==typeof value?"*":value}var UNDEFINED;return diff});
!function(root,factory){"function"==typeof define&&define.amd?define([],factory):"object"==typeof exports?module.exports=factory():root.simpleDiff=factory()}(this,function(){function diff(oldObj,newObj,ops){ops=ops||{};var i,len,prop,id,changes=[],oldPath=ops.oldPath||[],newPath=ops.newPath||[],ID_PROP=ops.idProp||"id",ADD_EVENT=ops.addEvent||"add",REMOVE_EVENT=ops.removeEvent||"remove",CHANGE_EVENT=ops.changeEvent||"change",ADD_ITEM_EVENT=ops.addItemEvent||"add-item",REMOVE_ITEM_EVENT=ops.removeItemEvent||"remove-item",MOVE_ITEM_EVENT=ops.moveItemEvent||"move-item",callback=ops.callback||function(item){changes.push(item)},comparators=ops.comparators||[];if(!(isObject(oldObj)&&isObject(newObj)||oldObj===newObj))return callback({oldPath:oldPath,newPath:newPath,type:CHANGE_EVENT,oldValue:oldObj,newValue:newObj}),changes;if(isArray(oldObj)){var idProp=ops.idProps&&(ops.idProps[oldPath.map(numberToAsterisk).join(".")]||ops.idProps[oldPath.join(".")])||ID_PROP;if("*"===idProp){var oldLength=oldObj.length,newLength=newObj.length;for(i=0,len=oldLength>newLength?oldLength:newLength;i<len;i++)i<oldLength&&i<newLength?diff(oldObj[i],newObj[i],extend({},ops,{callback:callback,oldPath:oldPath.concat(i),newPath:newPath.concat(i)})):i>=oldLength?callback({oldPath:oldPath,newPath:newPath,type:ADD_ITEM_EVENT,oldIndex:-1,curIndex:-1,newIndex:i,newValue:newObj[i]}):i>=newLength&&callback({oldPath:oldPath,newPath:newPath,type:REMOVE_ITEM_EVENT,oldIndex:i,curIndex:newLength,newIndex:-1,oldValue:oldObj[i]});return changes}var sample=oldObj.length>0?oldObj[0]:newObj[0];if(sample===UNDEFINED)return changes;var curIndex,oldIndex,objective="object"==typeof sample,oldHash=objective?indexBy(oldObj,idProp):hashOf(oldObj),newHash=objective?indexBy(newObj,idProp):hashOf(newObj),curArray=[].concat(oldObj);for(i=0,len=oldObj.length;i<len;i++)id=objective?oldObj[i][idProp]:oldObj[i],newHash.hasOwnProperty(id)||(curIndex=curArray.indexOf(oldObj[i]),curArray.splice(curIndex,1),callback({oldPath:oldPath,newPath:newPath,type:REMOVE_ITEM_EVENT,oldIndex:i,curIndex:curIndex,newIndex:-1,oldValue:oldObj[i]}));for(i=0,len=newObj.length;i<len;i++)id=objective?newObj[i][idProp]:newObj[i],oldHash.hasOwnProperty(id)||(callback({oldPath:oldPath,newPath:newPath,type:ADD_ITEM_EVENT,oldIndex:-1,curIndex:-1,newIndex:i,newValue:newObj[i]}),i>=curArray.length?curArray.push(newObj[i]):curArray.splice(i,0,newObj[i]));for(i=0,len=newObj.length;i<len;i++)id=objective?newObj[i][idProp]:newObj[i],oldHash.hasOwnProperty(id)&&(oldIndex=oldObj.indexOf(oldHash[id]),curIndex=curArray.indexOf(oldHash[id]),i!==curIndex&&(callback({oldPath:oldPath,newPath:newPath,type:MOVE_ITEM_EVENT,oldIndex:oldIndex,curIndex:curIndex,newIndex:i}),curArray.splice(curIndex,1),curArray.splice(i,0,oldHash[id])),diff(oldHash[id],newObj[i],extend({},ops,{callback:callback,oldPath:oldPath.concat(oldIndex),newPath:newPath.concat(i)})))}else{if(comparators.length>0)for(i=0,len=comparators.length;i<len;i++)if(oldObj instanceof comparators[i][0]!=!1||newObj instanceof comparators[i][0]!=!1){var objEqual=comparators[i][1](oldObj,newObj,{oldPath:oldPath,newPath:newPath});return objEqual||callback({oldPath:oldPath,newPath:newPath,type:CHANGE_EVENT,oldValue:oldObj,newValue:newObj}),changes}for(prop in oldObj)oldObj.hasOwnProperty(prop)&&(newObj.hasOwnProperty(prop)?isObject(oldObj[prop])&&isObject(newObj[prop])?diff(oldObj[prop],newObj[prop],extend({},ops,{callback:callback,oldPath:oldPath.concat(prop),newPath:newPath.concat(prop)})):oldObj[prop]!==newObj[prop]&&callback({oldPath:oldPath.concat(prop),newPath:newPath.concat(prop),type:CHANGE_EVENT,oldValue:oldObj[prop],newValue:newObj[prop]}):callback({oldPath:oldPath.concat(prop),newPath:newPath.concat(prop),type:REMOVE_EVENT,oldValue:oldObj[prop],newValue:UNDEFINED}));for(prop in newObj)newObj.hasOwnProperty(prop)&&(oldObj.hasOwnProperty(prop)||callback({oldPath:oldPath.concat(prop),newPath:newPath.concat(prop),type:ADD_EVENT,oldValue:UNDEFINED,newValue:newObj[prop]}))}return changes}function isObject(object){return!!object&&"object"==typeof object}function isArray(array){return Array.isArray?Array.isArray(array):"[object Array]"===Object.prototype.toString.call(array)}function indexBy(array,id){for(var hash={},i=0,len=array.length;i<len;i++)hash[array[i][id]]=array[i];return hash}function hashOf(array){for(var hash={},i=0,len=array.length;i<len;i++)hash[array[i]]=array[i];return hash}function extend(target){for(var i=1,len=arguments.length;i<len;i++){var source=arguments[i];for(var prop in source)source.hasOwnProperty(prop)&&(target[prop]=source[prop])}return target}function numberToAsterisk(value){return"number"==typeof value?"*":value}var UNDEFINED;return diff});
var expect = require('chai').expect,
sinon = require('sinon'),
diff = require('../simple-diff'),
undefined;
require('chai').use(require('sinon-chai'));
describe('diff', function () {

@@ -553,2 +556,83 @@ it('should find changes in objects', function () {

});
it('should handle comparators: [] to compare custom class objects', function () {
var cb = sinon.spy(function (a, b, ops) {
expect(a).to.be.instanceOf(Date);
expect(b).to.be.instanceOf(Date);
expect(ops).to.deep.equal({
oldPath: ['prop', 'date'],
newPath: ['prop', 'date']
});
return a.toString() === b.toString();
});
var changes = diff(
{
prop: {
test1: {},
test2: [{}],
date: new Date()
}
},
{
prop: {
test1: {},
test2: [{}],
date: new Date()
}
},
{
comparators: [
[Date, cb]
]
}
);
expect(changes).to.deep.equal([]);
expect(cb).to.have.callCount(1);
var nowDate = new Date();
var prevDate = new Date();
prevDate.setHours(-1);
changes = diff(
{
prop: {
test1: 1,
date: nowDate
}
},
{
prop: {
test1: 2,
date: prevDate
}
},
{
comparators: [
[Date, cb]
]
}
);
expect(cb).to.have.callCount(2);
expect(changes).to.deep.equal([
{
oldPath: ['prop', 'test1'],
newPath: ['prop', 'test1'],
type: 'change',
oldValue: 1,
newValue: 2
},
{
oldPath: ['prop', 'date'],
newPath: ['prop', 'date'],
type: 'change',
oldValue: nowDate,
newValue: prevDate
}
]);
});
});
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