datum-merge
Version:
Simplified diff and merging for deeply nested objects
115 lines (114 loc) • 3.76 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.deepDiffTyped = deepDiffTyped;
exports.antiDiffTyped = antiDiffTyped;
exports.deepDiffLow = deepDiffLow;
exports.deepDiffFlat = deepDiffFlat;
exports.flattenObject = flattenObject;
exports.unflattenObject = unflattenObject;
const type_utils_1 = require("./type-utils");
const deep_diff_1 = require("./diff-lib/deep-diff");
function deepDiffTyped(lhsObj, rhsObj, orderInd = false) {
if ((0, type_utils_1.emptyObject)(rhsObj)) {
return {};
}
if ((0, type_utils_1.emptyObject)(lhsObj)) {
return Object.assign({}, rhsObj);
}
const differences = deepDiffLow(lhsObj, rhsObj, orderInd);
const deltaObj = {};
if (!differences) {
return deltaObj;
}
for (const difference of differences) {
(0, deep_diff_1.applyChange)(deltaObj, undefined, difference);
}
cleanupObjArrays(deltaObj);
return deltaObj;
}
;
function cleanupObjArrays(obj) {
var _a;
for (const objKey of Object.keys(obj)) {
if ((_a = obj[objKey]) === null || _a === void 0 ? void 0 : _a.filter) {
obj[objKey] = obj[objKey].filter((e) => !!e);
}
}
}
function antiDiffTyped(lhsObj, rhsObj, orderInd = false) {
if ((0, type_utils_1.emptyObject)(lhsObj) || (0, type_utils_1.emptyObject)(rhsObj)) {
return {};
}
const differences = deepDiffLow(lhsObj, rhsObj, orderInd);
if (!differences) {
return Object.assign({}, lhsObj);
}
const modFields = new Set();
differences.map((d) => d === null || d === void 0 ? void 0 : d.path)
.filter((p) => !!p && p.length > 0)
.map((p) => (p === null || p === void 0 ? void 0 : p[0]).toString())
.forEach((s) => modFields.add(s));
const shareObj = Object.fromEntries(Object.entries(lhsObj)
.filter(([k, _]) => !modFields.has(k)));
return shareObj;
}
function deepDiffLow(lhsObj, rhsObj, orderInd = false) {
const differences = !orderInd
? (0, deep_diff_1.diff)(lhsObj, rhsObj)
: (0, deep_diff_1.orderIndependentDiff)(lhsObj, rhsObj);
return !(differences === null || differences === void 0 ? void 0 : differences.length)
? false
: differences;
}
;
function deepDiffFlat(oldFlat, newFlat, flatten = true) {
if (flatten) {
oldFlat = flattenObject(oldFlat);
newFlat = flattenObject(newFlat);
}
const updated = Object.assign({}, oldFlat);
const removed = Object.assign({}, newFlat);
for (const key of Object.keys(newFlat)) {
if (newFlat[key] === oldFlat[key]) {
delete updated[key];
delete removed[key];
}
}
return [updated, removed];
}
function flattenObject(obj) {
const flatObj = {};
const path = [];
const isObject = (value) => Object(value) === value;
function dig(obj) {
for (const [key, value] of Object.entries(obj)) {
path.push(key);
if (isObject(value)) {
dig(value);
}
else {
flatObj[path.join('.')] = value;
}
path.pop();
}
}
dig(obj);
return flatObj;
}
function unflattenObject(flatObj) {
const unflatObj = {};
for (const [path, value] of Object.entries(flatObj)) {
const parts = path.split('.');
let obj = unflatObj;
for (const [i, key] of parts.slice(0, -1).entries()) {
if (!obj[key]) {
const needArray = Number.isInteger(Number(parts[+i + 1]));
obj[key] = needArray ? [] : {};
}
obj = obj[key];
}
const lastkey = parts.pop();
obj[lastkey] = value;
}
return unflatObj;
}