UNPKG

5.1 kBJavaScriptView Raw
1"use strict";
2/*
3 * Copyright The OpenTelemetry Authors
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17Object.defineProperty(exports, "__esModule", { value: true });
18exports.merge = void 0;
19/* eslint-disable @typescript-eslint/no-explicit-any */
20const lodash_merge_1 = require("./lodash.merge");
21const MAX_LEVEL = 20;
22/**
23 * Merges objects together
24 * @param args - objects / values to be merged
25 */
26function merge(...args) {
27 let result = args.shift();
28 const objects = new WeakMap();
29 while (args.length > 0) {
30 result = mergeTwoObjects(result, args.shift(), 0, objects);
31 }
32 return result;
33}
34exports.merge = merge;
35function takeValue(value) {
36 if (isArray(value)) {
37 return value.slice();
38 }
39 return value;
40}
41/**
42 * Merges two objects
43 * @param one - first object
44 * @param two - second object
45 * @param level - current deep level
46 * @param objects - objects holder that has been already referenced - to prevent
47 * cyclic dependency
48 */
49function mergeTwoObjects(one, two, level = 0, objects) {
50 let result;
51 if (level > MAX_LEVEL) {
52 return undefined;
53 }
54 level++;
55 if (isPrimitive(one) || isPrimitive(two) || isFunction(two)) {
56 result = takeValue(two);
57 }
58 else if (isArray(one)) {
59 result = one.slice();
60 if (isArray(two)) {
61 for (let i = 0, j = two.length; i < j; i++) {
62 result.push(takeValue(two[i]));
63 }
64 }
65 else if (isObject(two)) {
66 const keys = Object.keys(two);
67 for (let i = 0, j = keys.length; i < j; i++) {
68 const key = keys[i];
69 result[key] = takeValue(two[key]);
70 }
71 }
72 }
73 else if (isObject(one)) {
74 if (isObject(two)) {
75 if (!shouldMerge(one, two)) {
76 return two;
77 }
78 result = Object.assign({}, one);
79 const keys = Object.keys(two);
80 for (let i = 0, j = keys.length; i < j; i++) {
81 const key = keys[i];
82 const twoValue = two[key];
83 if (isPrimitive(twoValue)) {
84 if (typeof twoValue === 'undefined') {
85 delete result[key];
86 }
87 else {
88 // result[key] = takeValue(twoValue);
89 result[key] = twoValue;
90 }
91 }
92 else {
93 const obj1 = result[key];
94 const obj2 = twoValue;
95 if (wasObjectReferenced(one, key, objects) ||
96 wasObjectReferenced(two, key, objects)) {
97 delete result[key];
98 }
99 else {
100 if (isObject(obj1) && isObject(obj2)) {
101 const arr1 = objects.get(obj1) || [];
102 const arr2 = objects.get(obj2) || [];
103 arr1.push({ obj: one, key });
104 arr2.push({ obj: two, key });
105 objects.set(obj1, arr1);
106 objects.set(obj2, arr2);
107 }
108 result[key] = mergeTwoObjects(result[key], twoValue, level, objects);
109 }
110 }
111 }
112 }
113 else {
114 result = two;
115 }
116 }
117 return result;
118}
119/**
120 * Function to check if object has been already reference
121 * @param obj
122 * @param key
123 * @param objects
124 */
125function wasObjectReferenced(obj, key, objects) {
126 const arr = objects.get(obj[key]) || [];
127 for (let i = 0, j = arr.length; i < j; i++) {
128 const info = arr[i];
129 if (info.key === key && info.obj === obj) {
130 return true;
131 }
132 }
133 return false;
134}
135function isArray(value) {
136 return Array.isArray(value);
137}
138function isFunction(value) {
139 return typeof value === 'function';
140}
141function isObject(value) {
142 return !isPrimitive(value) && !isArray(value) && !isFunction(value) && typeof value === 'object';
143}
144function isPrimitive(value) {
145 return typeof value === 'string' ||
146 typeof value === 'number' ||
147 typeof value === 'boolean' ||
148 typeof value === 'undefined' ||
149 value instanceof Date ||
150 value instanceof RegExp ||
151 value === null;
152}
153function shouldMerge(one, two) {
154 if (!(0, lodash_merge_1.isPlainObject)(one) || !(0, lodash_merge_1.isPlainObject)(two)) {
155 return false;
156 }
157 return true;
158}
159//# sourceMappingURL=merge.js.map
\No newline at end of file