|
|
- var defaultIsMergeableObject = require('is-mergeable-object')
-
- function emptyTarget(val) {
- return Array.isArray(val) ? [] : {}
- }
-
- function cloneUnlessOtherwiseSpecified(value, options) {
- return (options.clone !== false && options.isMergeableObject(value))
- ? deepmerge(emptyTarget(value), value, options)
- : value
- }
-
- function defaultArrayMerge(target, source, options) {
- return target.concat(source).map(function(element) {
- return cloneUnlessOtherwiseSpecified(element, options)
- })
- }
-
- function mergeObject(target, source, options) {
- var destination = {}
- if (options.isMergeableObject(target)) {
- Object.keys(target).forEach(function(key) {
- destination[key] = cloneUnlessOtherwiseSpecified(target[key], options)
- })
- }
- Object.keys(source).forEach(function(key) {
- if (!options.isMergeableObject(source[key]) || !target[key]) {
- destination[key] = cloneUnlessOtherwiseSpecified(source[key], options)
- } else {
- destination[key] = deepmerge(target[key], source[key], options)
- }
- })
- return destination
- }
-
- function deepmerge(target, source, options) {
- options = options || {}
- options.arrayMerge = options.arrayMerge || defaultArrayMerge
- options.isMergeableObject = options.isMergeableObject || defaultIsMergeableObject
-
- var sourceIsArray = Array.isArray(source)
- var targetIsArray = Array.isArray(target)
- var sourceAndTargetTypesMatch = sourceIsArray === targetIsArray
-
- if (!sourceAndTargetTypesMatch) {
- return cloneUnlessOtherwiseSpecified(source, options)
- } else if (sourceIsArray) {
- return options.arrayMerge(target, source, options)
- } else {
- return mergeObject(target, source, options)
- }
- }
-
- deepmerge.all = function deepmergeAll(array, options) {
- if (!Array.isArray(array)) {
- throw new Error('first argument should be an array')
- }
-
- return array.reduce(function(prev, next) {
- return deepmerge(prev, next, options)
- }, {})
- }
-
- module.exports = deepmerge
|