merge-left-utils
Version:
Merge objects without structure changes
102 lines (87 loc) • 3.41 kB
JavaScript
/*
naive check is input is like Object
source: https://stackoverflow.com/a/38555871
*/
const isLikeObject = (value) => typeof value === 'object' &&
value !== null &&
value.constructor === Object &&
Object.prototype.toString.call(value) === '[object Object]';
/*
Function which always return true
*/
const alwaysTrue = () => true;
/**
Function merge objects {a} and {b} by [keys]
If key from {b} is not presented in {a} - it does nothing
If both objects has key - result will get key from {b}
if value is seems like object - then we run function recursive for value
keys - which keys will be checked for objects
a - left
b - right
customLogic (a[key], target[key]) : boolean -
if it returns true - then get value from {b}, else from {a}
*/
function mergeLeftKeys(keys, source, target, customLogic = alwaysTrue) {
if (!target) {
return source;
}
return keys.reduce((prev, key) => {
if (Object.prototype.hasOwnProperty.call(target, key) && customLogic(key, source, target)) {
if (isLikeObject(source[key])) {
return Object.assign(Object.assign({}, prev), { [key]: mergeLeftKeys(Object.keys(source[key]), source[key], target[key], customLogic) });
}
else {
return Object.assign(Object.assign({}, prev), { [key]: target[key] });
}
}
else {
return Object.assign(Object.assign({}, prev), { [key]: source[key] });
}
}, {});
}
/**
Shortcut function
Replace only existing fields in {a} with {b}
ex: ({ a: 0, b: 0 }, { a: 1, x: 1 }) -> { a: 1, b: 0 }
*/
function mergeLeft(source, target, customLogic = alwaysTrue) {
return mergeLeftKeys(Object.keys(source), source, target, customLogic);
}
/**
Shortcut function
Drops keys listed in {dropKeys} and replace existing fields in {a} with {b}
ex: (['a'], { a: 0, b: 0 }, { a: 1, x: 1 }) -> { b: 0 }
*/
function mergeLeftDropping(dropKeys, source, target) {
const replaceableKeys = Object.keys(source).filter((keyOfSource) => dropKeys.indexOf(keyOfSource) === -1);
return mergeLeftKeys(replaceableKeys, source, target);
}
/**
Shortcut function
Replace only existing fields in {a} with {b} skipping {b} keys from {keys}
ex: (['a'], { a: 0, b: 0 }, { a: 1, b: 1 }) -> { a: 0, b: 1 }
*/
function mergeLeftExcept(skippingKeys, source, target) {
return mergeLeftKeys(Object.keys(source), source, target, (keyOfSource) => skippingKeys.indexOf(keyOfSource) === -1);
}
/**
Shortcut function
Replace only fields from [keys] arg in {a} with {b}
ex: (['b'], { a: 0, b: 0 }, { a: 1, b: 1 }) -> { a: 0, b: 1 }
*/
function mergeLeftOnly(keys, source, target) {
return mergeLeft(source, target, (key) => keys.includes(key));
}
/**
Shortcut function
Replace only existing fields in {a} with {b}
When field from {b} is truthy
ex: ({ a: 0, b: 0 }, { a: 1, x: 1 }) -> { a: 1, b: 0 }
*/
function mergeLeftTruthy(source, target, customLogic = alwaysTrue) {
return mergeLeftKeys(Object.keys(source), source, target, (key, source, target) => {
return !!target[key] && customLogic(key, source, target);
});
}
export { mergeLeft, mergeLeftDropping, mergeLeftExcept, mergeLeftKeys, mergeLeftOnly, mergeLeftTruthy };
//# sourceMappingURL=index.es.js.map