UNPKG

chrobject

Version:

Stores chronicles of plain objects as diffs and snapshots

94 lines (93 loc) 4.13 kB
/** * Creator: Christian Hotz * Company: hydra newmedia GmbH * Date: 15.06.16 * * Copyright hydra newmedia GmbH */ "use strict"; /** * 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;