{"version":3,"file":"deep-merge.mjs","names":[],"sources":["../src/deep-merge.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n                       🗲 Storm Software - Stryke\n\n This code was released as part of the Stryke project. Stryke\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/stryke.\n\n Website:                  https://stormsoftware.com\n Repository:               https://github.com/storm-software/stryke\n Documentation:            https://docs.stormsoftware.com/projects/stryke\n Contact:                  https://stormsoftware.com/contact\n\n SPDX-License-Identifier:  Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport { isFunction } from \"@stryke/type-checks/is-function\";\nimport { isMergeableObject } from \"@stryke/type-checks/is-mergeable-object\";\nimport { propertyUnsafe } from \"@stryke/type-checks/property-exists\";\n\nconst emptyTarget = (val: any) => {\n  return Array.isArray(val) ? [] : {};\n};\n\nconst cloneUnlessOtherwiseSpecified = (\n  value: any,\n  options: {\n    clone?: boolean;\n    isMergeableObject: (value: any) => boolean;\n  }\n) => {\n  return options.clone !== false && options.isMergeableObject(value)\n    ? deepMerge(emptyTarget(value), value, options)\n    : value;\n};\n\nconst defaultArrayMerge = (target: any[], source: any[], options?: any) => {\n  return [...target, ...source].map(element => {\n    return cloneUnlessOtherwiseSpecified(element, options);\n  });\n};\n\nconst getMergeFunction = (\n  key: string,\n  options: {\n    customMerge?: (key: string) => any;\n  }\n) => {\n  if (!options.customMerge) {\n    return deepMerge;\n  }\n  const customMerge = options.customMerge(key);\n\n  return isFunction(customMerge) ? customMerge : deepMerge;\n};\n\nconst getKeys = (target: Record<string, any>) => {\n  return [\n    ...Object.keys(target),\n    ...((Object.getOwnPropertySymbols\n      ? Object.getOwnPropertySymbols(target).filter(symbol => {\n          return Object.propertyIsEnumerable.call(target, symbol);\n        })\n      : []) as unknown as string[])\n  ];\n};\n\nconst mergeObject = (\n  target: Record<string, any>,\n  source: Record<string, any>,\n  options: {\n    clone?: boolean;\n    customMerge?: (key: string) => any;\n    isMergeableObject: (value: any) => boolean;\n    cloneUnlessOtherwiseSpecified?: (\n      value: any,\n      options: {\n        clone: boolean;\n        isMergeableObject: (value: any) => boolean;\n      }\n    ) => any;\n  }\n) => {\n  const destination: Record<string, any> = {};\n  if (options.isMergeableObject(target)) {\n    for (const key of getKeys(target)) {\n      destination[key] = cloneUnlessOtherwiseSpecified(target[key], options);\n    }\n  }\n  for (const key of getKeys(source)) {\n    destination[key] =\n      propertyUnsafe(target, key) && options.isMergeableObject(source[key])\n        ? getMergeFunction(key, options)(target[key], source[key], options)\n        : cloneUnlessOtherwiseSpecified(source[key], options);\n  }\n  return destination;\n};\n\nexport interface DeepMergeOptions {\n  clone?: boolean;\n  customMerge?: (key: string) => any;\n  isMergeableObject: (value: any) => boolean;\n  cloneUnlessOtherwiseSpecified: (\n    value: any,\n    options: {\n      clone?: boolean;\n      isMergeableObject: (value: any) => boolean;\n    }\n  ) => any;\n  arrayMerge: (target: any[], source: any[], options: any) => any;\n}\n\n/**\n * Deep merge two objects\n *\n * @param target - The target object\n * @param source - The source object\n * @param options - The options object\n * @returns The merged object\n */\nexport function deepMerge<X = any | any[], Y = any | any[], Z = X & Y>(\n  target: X,\n  source: Y,\n  options?: Partial<DeepMergeOptions>\n): Z {\n  if (!target || !source) {\n    return (target || source) as Z;\n  }\n\n  const opts = (options ?? {}) as DeepMergeOptions;\n  opts.arrayMerge ??= defaultArrayMerge;\n  opts.isMergeableObject ??= isMergeableObject;\n  // cloneUnlessOtherwiseSpecified is added to `options` so that custom arrayMerge()\n  // implementations can use it. The caller may not replace it.\n  opts.cloneUnlessOtherwiseSpecified ??= cloneUnlessOtherwiseSpecified;\n\n  const sourceIsArray = Array.isArray(source);\n  const targetIsArray = Array.isArray(target);\n  const sourceAndTargetTypesMatch = sourceIsArray === targetIsArray;\n\n  if (!sourceAndTargetTypesMatch) {\n    return cloneUnlessOtherwiseSpecified(source, opts);\n  }\n  if (sourceIsArray) {\n    return opts.arrayMerge(target as any[], source, opts);\n  }\n  return mergeObject(target, source, opts) as Z;\n}\n\ndeepMerge.all = function deepMergeAll(array: any[], options?: any) {\n  if (!Array.isArray(array)) {\n    throw new TypeError(\"first argument should be an array\");\n  }\n\n  return array.reduce((prev, next) => {\n    return deepMerge(prev, next, options);\n  }, {});\n};\n"],"mappings":";;;;;AAsBA,MAAM,eAAe,QAAa;AAChC,QAAO,MAAM,QAAQ,IAAI,GAAG,EAAE,GAAG,EAAE;;AAGrC,MAAM,iCACJ,OACA,YAIG;AACH,QAAO,QAAQ,UAAU,SAAS,QAAQ,kBAAkB,MAAM,GAC9D,UAAU,YAAY,MAAM,EAAE,OAAO,QAAQ,GAC7C;;AAGN,MAAM,qBAAqB,QAAe,QAAe,YAAkB;AACzE,QAAO,CAAC,GAAG,QAAQ,GAAG,OAAO,CAAC,KAAI,YAAW;AAC3C,SAAO,8BAA8B,SAAS,QAAQ;GACtD;;AAGJ,MAAM,oBACJ,KACA,YAGG;AACH,KAAI,CAAC,QAAQ,YACX,QAAO;CAET,MAAM,cAAc,QAAQ,YAAY,IAAI;AAE5C,QAAO,WAAW,YAAY,GAAG,cAAc;;AAGjD,MAAM,WAAW,WAAgC;AAC/C,QAAO,CACL,GAAG,OAAO,KAAK,OAAO,EACtB,GAAK,OAAO,wBACR,OAAO,sBAAsB,OAAO,CAAC,QAAO,WAAU;AACpD,SAAO,OAAO,qBAAqB,KAAK,QAAQ,OAAO;GACvD,GACF,EAAE,CACP;;AAGH,MAAM,eACJ,QACA,QACA,YAYG;CACH,MAAM,cAAmC,EAAE;AAC3C,KAAI,QAAQ,kBAAkB,OAAO,CACnC,MAAK,MAAM,OAAO,QAAQ,OAAO,CAC/B,aAAY,OAAO,8BAA8B,OAAO,MAAM,QAAQ;AAG1E,MAAK,MAAM,OAAO,QAAQ,OAAO,CAC/B,aAAY,OACV,eAAe,QAAQ,IAAI,IAAI,QAAQ,kBAAkB,OAAO,KAAK,GACjE,iBAAiB,KAAK,QAAQ,CAAC,OAAO,MAAM,OAAO,MAAM,QAAQ,GACjE,8BAA8B,OAAO,MAAM,QAAQ;AAE3D,QAAO;;;;;;;;;;AAyBT,SAAgB,UACd,QACA,QACA,SACG;AACH,KAAI,CAAC,UAAU,CAAC,OACd,QAAQ,UAAU;CAGpB,MAAM,OAAQ,WAAW,EAAE;AAC3B,MAAK,eAAe;AACpB,MAAK,sBAAsB;AAG3B,MAAK,kCAAkC;CAEvC,MAAM,gBAAgB,MAAM,QAAQ,OAAO;AAI3C,KAAI,EAF8B,kBADZ,MAAM,QAAQ,OAC6B,EAG/D,QAAO,8BAA8B,QAAQ,KAAK;AAEpD,KAAI,cACF,QAAO,KAAK,WAAW,QAAiB,QAAQ,KAAK;AAEvD,QAAO,YAAY,QAAQ,QAAQ,KAAK;;AAG1C,UAAU,MAAM,SAAS,aAAa,OAAc,SAAe;AACjE,KAAI,CAAC,MAAM,QAAQ,MAAM,CACvB,OAAM,IAAI,UAAU,oCAAoC;AAG1D,QAAO,MAAM,QAAQ,MAAM,SAAS;AAClC,SAAO,UAAU,MAAM,MAAM,QAAQ;IACpC,EAAE,CAAC"}