@hypernym/merge
Version:
Type-safe deep merge utility.
34 lines (31 loc) • 1.23 kB
JavaScript
const toString = (v) => Object.prototype.toString.call(v).slice(8, -1);
const isNull = (v) => v === null;
const isUndefined = (v) => typeof v === "undefined";
const isArray = (v) => Array.isArray(v);
const isObject = (v) => toString(v) === "Object";
function merge(sources, options) {
const { rules, depth = 6 } = options || {};
return sources.reduce((prev, curr) => {
if (prev && curr) {
Object.keys(curr).forEach((key) => {
if (["__proto__", "constructor", "prototype"].includes(key)) return;
if (depth <= 0 && isObject(curr[key])) {
prev[key] = {};
return;
}
if (isArray(prev[key]) && isArray(curr[key])) {
prev[key] = rules?.array === "override" ? curr[key] : [...prev[key], ...curr[key]];
} else if (isObject(prev[key]) && isObject(curr[key])) {
prev[key] = merge([prev[key], curr[key]], {
...options,
depth: depth - 1
});
} else {
prev[key] = isUndefined(curr[key]) ? rules?.undefined === "skip" ? prev[key] : curr[key] : isNull(curr[key]) ? rules?.null === "skip" ? prev[key] : curr[key] : curr[key];
}
});
}
return prev;
}, {});
}
export { merge };