text: 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 getMergeFunction(key, options) {
  	if (!options.customMerge) {
  		return deepmerge
  	}
  	var customMerge = options.customMerge(key)
  	return typeof customMerge === 'function' ? customMerge : deepmerge
  }
  
  function getEnumerableOwnPropertySymbols(target) {
  	return Object.getOwnPropertySymbols
  		? Object.getOwnPropertySymbols(target).filter(function(symbol) {
  			return target.propertyIsEnumerable(symbol)
  		})
  		: []
  }
  
  function getKeys(target) {
  	return Object.keys(target).concat(getEnumerableOwnPropertySymbols(target))
  }
  
  function mergeObject(target, source, options) {
  	var destination = {}
  	if (options.isMergeableObject(target)) {
  		getKeys(target).forEach(function(key) {
  			destination[key] = cloneUnlessOtherwiseSpecified(target[key], options)
  		})
  	}
  	getKeys(source).forEach(function(key) {
  		if (!options.isMergeableObject(source[key]) || !target[key]) {
  			destination[key] = cloneUnlessOtherwiseSpecified(source[key], options)
  		} else {
  			destination[key] = getMergeFunction(key, options)(target[key], source[key], options)
  		}
  	})
  	return destination
  }
  
  function deepmerge(target, source, options) {
  	options = Object.assign({
  		arrayMerge: defaultArrayMerge,
  		isMergeableObject: defaultIsMergeableObject
  	}, options, {
  		cloneUnlessOtherwiseSpecified: cloneUnlessOtherwiseSpecified
  	})
  
  	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
  