jason westover | d248362 | 2025-08-18 09:26:41 -0500 | [diff] [blame^] | 1 | /** |
| 2 | * Deeply merge two plain objects (or arrays) without mutating the inputs. |
| 3 | * |
| 4 | * Rules: |
| 5 | * - Arrays from the source replace arrays on the target. |
| 6 | * - Plain objects are merged recursively. |
| 7 | * - Primitive values from the source overwrite the target. |
| 8 | */ |
| 9 | export function deepMerge(target, source) { |
| 10 | if (typeof target !== 'object' || target === null) return source; |
| 11 | if (typeof source !== 'object' || source === null) return target; |
| 12 | const output = Array.isArray(target) ? target.slice() : { ...target }; |
| 13 | Object.keys(source).forEach((key) => { |
| 14 | const sourceValue = source[key]; |
| 15 | const targetValue = output[key]; |
| 16 | if (Array.isArray(sourceValue)) { |
| 17 | output[key] = sourceValue.slice(); |
| 18 | } else if ( |
| 19 | typeof sourceValue === 'object' && |
| 20 | sourceValue !== null && |
| 21 | typeof targetValue === 'object' && |
| 22 | targetValue !== null && |
| 23 | !Array.isArray(targetValue) |
| 24 | ) { |
| 25 | output[key] = deepMerge(targetValue, sourceValue); |
| 26 | } else { |
| 27 | output[key] = sourceValue; |
| 28 | } |
| 29 | }); |
| 30 | return output; |
| 31 | } |