You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

64 lines
1.9 KiB

4 years ago
  1. var defaultIsMergeableObject = require('is-mergeable-object')
  2. function emptyTarget(val) {
  3. return Array.isArray(val) ? [] : {}
  4. }
  5. function cloneUnlessOtherwiseSpecified(value, options) {
  6. return (options.clone !== false && options.isMergeableObject(value))
  7. ? deepmerge(emptyTarget(value), value, options)
  8. : value
  9. }
  10. function defaultArrayMerge(target, source, options) {
  11. return target.concat(source).map(function(element) {
  12. return cloneUnlessOtherwiseSpecified(element, options)
  13. })
  14. }
  15. function mergeObject(target, source, options) {
  16. var destination = {}
  17. if (options.isMergeableObject(target)) {
  18. Object.keys(target).forEach(function(key) {
  19. destination[key] = cloneUnlessOtherwiseSpecified(target[key], options)
  20. })
  21. }
  22. Object.keys(source).forEach(function(key) {
  23. if (!options.isMergeableObject(source[key]) || !target[key]) {
  24. destination[key] = cloneUnlessOtherwiseSpecified(source[key], options)
  25. } else {
  26. destination[key] = deepmerge(target[key], source[key], options)
  27. }
  28. })
  29. return destination
  30. }
  31. function deepmerge(target, source, options) {
  32. options = options || {}
  33. options.arrayMerge = options.arrayMerge || defaultArrayMerge
  34. options.isMergeableObject = options.isMergeableObject || defaultIsMergeableObject
  35. var sourceIsArray = Array.isArray(source)
  36. var targetIsArray = Array.isArray(target)
  37. var sourceAndTargetTypesMatch = sourceIsArray === targetIsArray
  38. if (!sourceAndTargetTypesMatch) {
  39. return cloneUnlessOtherwiseSpecified(source, options)
  40. } else if (sourceIsArray) {
  41. return options.arrayMerge(target, source, options)
  42. } else {
  43. return mergeObject(target, source, options)
  44. }
  45. }
  46. deepmerge.all = function deepmergeAll(array, options) {
  47. if (!Array.isArray(array)) {
  48. throw new Error('first argument should be an array')
  49. }
  50. return array.reduce(function(prev, next) {
  51. return deepmerge(prev, next, options)
  52. }, {})
  53. }
  54. module.exports = deepmerge