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