1 | import { isSome } from './helpers.js';
|
2 | export function mergeDeep(sources, respectPrototype = false) {
|
3 | const target = sources[0] || {};
|
4 | const output = {};
|
5 | if (respectPrototype) {
|
6 | Object.setPrototypeOf(output, Object.create(Object.getPrototypeOf(target)));
|
7 | }
|
8 | for (const source of sources) {
|
9 | if (isObject(target) && isObject(source)) {
|
10 | if (respectPrototype) {
|
11 | const outputPrototype = Object.getPrototypeOf(output);
|
12 | const sourcePrototype = Object.getPrototypeOf(source);
|
13 | if (sourcePrototype) {
|
14 | for (const key of Object.getOwnPropertyNames(sourcePrototype)) {
|
15 | const descriptor = Object.getOwnPropertyDescriptor(sourcePrototype, key);
|
16 | if (isSome(descriptor)) {
|
17 | Object.defineProperty(outputPrototype, key, descriptor);
|
18 | }
|
19 | }
|
20 | }
|
21 | }
|
22 | for (const key in source) {
|
23 | if (isObject(source[key])) {
|
24 | if (!(key in output)) {
|
25 | Object.assign(output, { [key]: source[key] });
|
26 | }
|
27 | else {
|
28 | output[key] = mergeDeep([output[key], source[key]], respectPrototype);
|
29 | }
|
30 | }
|
31 | else {
|
32 | Object.assign(output, { [key]: source[key] });
|
33 | }
|
34 | }
|
35 | }
|
36 | }
|
37 | return output;
|
38 | }
|
39 | function isObject(item) {
|
40 | return item && typeof item === 'object' && !Array.isArray(item);
|
41 | }
|