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 */ 9export 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} 32