human-object-diff
Version:
Human Readable Difference Between Two Objects
97 lines (96 loc) • 3.57 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fast_deep_equal_1 = __importDefault(require("fast-deep-equal"));
function preProcessArray(diffs = [], lhs = [], rhs = []) {
const groupedDiffs = groupDiffsByPath(diffs);
let diffStrings = [];
for (const path in groupedDiffs) {
if (Object.prototype.hasOwnProperty.call(groupedDiffs, path)) {
let lhsValue = lhs;
let rhsValue = rhs;
for (const p of path.split(/[.[]]/gi).filter(Boolean)) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
lhsValue = lhsValue[p];
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
rhsValue = rhsValue[p];
}
const groupedDiff = groupedDiffs[path];
const { insertions, cutoff } = getInsertions(lhsValue, rhsValue);
const changes = [
...insertions,
...groupedDiff
.filter((diff) => Number(diff.index) < cutoff && diff.kind === 'E')
.map((diff) => ({
...diff,
dotPath: path,
kind: 'AE',
path: path.split(/[.[]]/gi).filter(Boolean),
})),
].map((diff) => ({
...diff,
path: path.split(/[.[]]/gi).filter(Boolean),
dotPath: path,
}));
diffStrings = [...diffStrings, ...changes];
}
}
return diffStrings;
}
exports.default = preProcessArray;
function groupDiffsByPath(diffs) {
const diffGroups = {};
for (const diff of diffs) {
diff.index = diff.index ?? (Array.isArray(diff.path) ? Number(diff.path[diff.path.length - 1]) : 0);
if (diffGroups[diff.dotPath] && Array.isArray(diffGroups[diff.dotPath])) {
diffGroups[diff.dotPath].push(diff);
}
else {
diffGroups[diff.dotPath] = [diff];
}
}
return diffGroups;
}
function getInsertions(lhs = [], rhs = []) {
if (!Array.isArray(lhs) || !Array.isArray(rhs)) {
return {
cutoff: 0,
insertions: [],
};
}
const insertionCount = rhs.length - lhs.length;
const kind = insertionCount !== 0 && insertionCount > 0 ? 'I' : 'R';
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const longer = kind === 'I' ? [...rhs] : [...lhs];
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const shorter = kind === 'I' ? [...lhs] : [...rhs];
const longerLength = longer.length;
const insertions = [];
let absCount = Math.abs(insertionCount);
let negIndex = 0;
while (absCount !== 0) {
negIndex -= 1;
if ((0, fast_deep_equal_1.default)(longer[longer.length - 1], shorter[longer.length - 1 - absCount])) {
longer.pop();
shorter.pop();
}
else {
const value = longer.pop();
const index = longerLength - Math.abs(negIndex);
insertions.push({
kind,
index,
val: value,
});
absCount -= 1;
}
}
return {
insertions,
cutoff: Math.min(...insertions.map((ins) => ins.index)),
};
}