chrobject
Version:
Stores chronicles of plain objects as diffs and snapshots
94 lines (93 loc) • 4.13 kB
JavaScript
/**
* Creator: Christian Hotz
* Company: hydra newmedia GmbH
* Date: 15.06.16
*
* Copyright hydra newmedia GmbH
*/
;
/**
* Imports
*/
var _ = require('lodash');
var hash = require('object-hash');
var ArrayDiff_1 = require('./ArrayDiff');
var DeepDiff = (function () {
function DeepDiff(action, propertyPath, oldValue, newValue) {
this.action = action;
this.created = action === 'created' ? true : undefined;
this.edited = action === 'edited' ? true : undefined;
this.deleted = action === 'deleted' ? true : undefined;
this.array = action === 'array' ? true : undefined;
this.propertyPath = propertyPath;
this.oldValue = !_.isNull(oldValue) && !_.isUndefined(oldValue) && action !== 'created' ? oldValue : undefined;
this.newValue = !_.isNull(newValue) && !_.isUndefined(newValue) && action !== 'deleted' ? newValue : undefined;
if (action === 'array') {
this.setArrayDiffs(oldValue, newValue);
}
}
DeepDiff.prototype.setArrayDiffs = function (one, two) {
this.arrayDiffs = [];
var processedItems = {};
var addToProcessed = function (alreadyDoneMap, valHash, idx) {
if (_.has(alreadyDoneMap, valHash)) {
alreadyDoneMap[valHash].push(idx);
}
else {
alreadyDoneMap[valHash] = [idx];
}
};
// indexOf function which checks for object hash equality instead of using SameValueZero
var indexOf = function (array, value, fromIndex) {
var startIndex = fromIndex ? fromIndex : 0;
for (var i = startIndex; i < array.length; i++) {
if (hash(array[i]) === hash(value)) {
return i;
}
}
return -1;
};
// loop through first array to find deletions and index changes
for (var idxInOne = 0; idxInOne < one.length; idxInOne++) {
var val = one[idxInOne];
// check whether item is in second array
if (indexOf(two, val) >= 0) {
// check whether already processed a similar item
var valHash = hash(val);
// get idx in second array where the last processed item was moved to
var idxLastMovedTo = _.has(processedItems, valHash) ? _.last(processedItems[valHash]) + 1 : undefined;
// search from there on
var idxMovedTo = indexOf(two, val, idxLastMovedTo);
if (idxInOne === idxMovedTo) {
// if element stayed, just add it to processed elements
addToProcessed(processedItems, valHash, idxInOne);
}
else if (idxMovedTo >= 0) {
// if moved, add it to processed elements and output change
addToProcessed(processedItems, valHash, idxMovedTo);
this.arrayDiffs.push(new ArrayDiff_1.ArrayDiff('moved', idxInOne, val, idxMovedTo));
}
else {
// if no such element found, output deletion
this.arrayDiffs.push(new ArrayDiff_1.ArrayDiff('removed', idxInOne, val));
}
}
else {
// if not found at all, output deletion
this.arrayDiffs.push(new ArrayDiff_1.ArrayDiff('removed', idxInOne, val));
}
}
// loop through second array to find additions in comparison to first array
for (var idxInTwo = 0; idxInTwo < two.length; idxInTwo++) {
var val = two[idxInTwo];
var valHash = hash(val);
// check if element is not in processed elements map or if it is, then not at the same position
if (!_.has(processedItems, valHash) || _.indexOf(processedItems[valHash], idxInTwo) < 0) {
// output additions
this.arrayDiffs.push(new ArrayDiff_1.ArrayDiff('added', idxInTwo, val));
}
}
};
return DeepDiff;
}());
exports.DeepDiff = DeepDiff;