UNPKG

merge-change

Version:

Advanced library for deep merging, patching, and immutable updates of data structures. Features declarative operations for specific merging behaviors, property management, custom type merging rules, and difference tracking. Supports complex data transform

78 lines 3.36 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.diff = diff; const type_1 = require("../type"); const has_method_1 = require("../has-method"); function isEqual(first, second) { return first === second; } /** * Calculates the difference, the result is an object with $set and $unset operators * @param source {*} Source value * @param compare {*} Compared (new) value * @param [ignore] {Array<string>} Names of ignored properties * @param [white] {Array<string>} Names of compared properties, if the array is not empty * @param [path] {String} Path to the current property in recursive processing * @param [equal] {Function} Function for comparing values * @param separator * @param [result] {String} Returned result in recursive processing. Should not be used. * @returns {{$unset: [], $set: {}}} */ function diff(source, compare, { ignore = [], white = [], path = '', equal = isEqual, separator = '.' }, result) { if (!result) result = { $set: {}, $unset: [] }; // This is not JSON.stringify! We call a method that provides a value for conversion to JSON, but the conversion is not performed // Property types remain original, but we can compare the internals of custom objects const sourcePlain = (0, has_method_1.hasMethod)(source, 'toJSON') ? source.toJSON() : source; const comparePlain = (0, has_method_1.hasMethod)(compare, 'toJSON') ? compare.toJSON() : compare; const sourceType = (0, type_1.type)(sourcePlain); const compareType = (0, type_1.type)(comparePlain); if (sourceType === compareType && sourceType === 'object') { const sourceObject = sourcePlain; const compareObject = comparePlain; const sourceKeys = Object.keys(sourceObject); const compareKeys = Object.keys(compareObject); // set property for (const key of compareKeys) { const p = path ? path + separator + key : key; // If the property is not in the ignore list and if a whitelist is defined, then it is in it if (!ignore.includes(p) && (white.length === 0 || white.includes(p))) { // new property if (!(key in sourceObject)) { result.$set[p] = compareObject[key]; } else if (!equal(compareObject[key], sourceObject[key])) { // change property diff(sourceObject[key], compareObject[key], { ignore, white, path: p, equal, separator, }, result); } } } // unset property for (const key of sourceKeys) { if (!(key in compareObject)) { const p = path ? path + separator + key : key; if (!ignore.includes(p) && (white.length === 0 || white.includes(p))) { result.$unset.push(p); } } } } else { if (!path) { return compare; } else { if (!ignore.includes(path) && (white.length === 0 || white.includes(path))) { result.$set[path] = compare; } } } return result; } //# sourceMappingURL=index.js.map