-
-
Save jeffposnick/cd46ff6ca5cf1d2ec1d87edae863f17e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const isPlainObject = require("lodash/isPlainObject"); | |
const OVERRIDE_PREFIX = "override:"; | |
function getMergedItem(target, source, parentKey) { | |
// if key is prefixed with OVERRIDE_PREFIX, it just keeps the new source value (no merging) | |
if (parentKey && parentKey.indexOf(OVERRIDE_PREFIX) === 0) { | |
return source; | |
} | |
const isTargetArray = Array.isArray(target); | |
let isTargetPlainObject; | |
if (isTargetArray) { | |
isTargetPlainObject = false; | |
} | |
const isSourceArray = Array.isArray(source); | |
let isSourcePlainObject; | |
if (isSourceArray) { | |
isSourcePlainObject = false; | |
} | |
// deep copy objects to avoid sharing and to effect key renaming | |
if (!target) { | |
if (isSourcePlainObject === undefined) { | |
isSourcePlainObject = isPlainObject(source); | |
} | |
if (isSourcePlainObject) { | |
target = {}; | |
isTargetPlainObject = true; | |
} | |
} | |
if (isTargetArray && isSourceArray) { | |
return target.concat(source); | |
} else if (isTargetPlainObject !== undefined ? isTargetPlainObject : isPlainObject(target)) { | |
if (isSourcePlainObject !== undefined ? isSourcePlainObject : isPlainObject(source)) { | |
for (var key in source) { | |
let newKey = key; | |
if (key.indexOf(OVERRIDE_PREFIX) === 0) { | |
newKey = key.substr(OVERRIDE_PREFIX.length); | |
} | |
target[newKey] = getMergedItem(target[key], source[key], newKey); | |
} | |
} | |
return target; | |
} else { | |
// number, string, class instance, etc | |
return source; | |
} | |
} | |
function Merge(target, ...sources) { | |
// Remove override prefixes from root target. | |
if (isPlainObject(target)) { | |
for (var key in target) { | |
if (key.indexOf(OVERRIDE_PREFIX) === 0) { | |
target[key.substr(OVERRIDE_PREFIX.length)] = target[key]; | |
delete target[key]; | |
} | |
} | |
} | |
for (var source of sources) { | |
if (!source) { | |
continue; | |
} | |
target = getMergedItem(target, source); | |
} | |
return target; | |
} | |
module.exports = Merge; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment