UNPKG

@opentelemetry/core

Version:

OpenTelemetry Core provides constants and utilities shared by all OpenTelemetry SDK packages.

158 lines 4.97 kB
/* * Copyright The OpenTelemetry Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* eslint-disable @typescript-eslint/no-explicit-any */ import { isPlainObject } from './lodash.merge'; const MAX_LEVEL = 20; /** * Merges objects together * @param args - objects / values to be merged */ export function merge(...args) { let result = args.shift(); const objects = new WeakMap(); while (args.length > 0) { result = mergeTwoObjects(result, args.shift(), 0, objects); } return result; } function takeValue(value) { if (isArray(value)) { return value.slice(); } return value; } /** * Merges two objects * @param one - first object * @param two - second object * @param level - current deep level * @param objects - objects holder that has been already referenced - to prevent * cyclic dependency */ function mergeTwoObjects(one, two, level = 0, objects) { let result; if (level > MAX_LEVEL) { return undefined; } level++; if (isPrimitive(one) || isPrimitive(two) || isFunction(two)) { result = takeValue(two); } else if (isArray(one)) { result = one.slice(); if (isArray(two)) { for (let i = 0, j = two.length; i < j; i++) { result.push(takeValue(two[i])); } } else if (isObject(two)) { const keys = Object.keys(two); for (let i = 0, j = keys.length; i < j; i++) { const key = keys[i]; result[key] = takeValue(two[key]); } } } else if (isObject(one)) { if (isObject(two)) { if (!shouldMerge(one, two)) { return two; } result = Object.assign({}, one); const keys = Object.keys(two); for (let i = 0, j = keys.length; i < j; i++) { const key = keys[i]; const twoValue = two[key]; if (isPrimitive(twoValue)) { if (typeof twoValue === 'undefined') { delete result[key]; } else { // result[key] = takeValue(twoValue); result[key] = twoValue; } } else { const obj1 = result[key]; const obj2 = twoValue; if (wasObjectReferenced(one, key, objects) || wasObjectReferenced(two, key, objects)) { delete result[key]; } else { if (isObject(obj1) && isObject(obj2)) { const arr1 = objects.get(obj1) || []; const arr2 = objects.get(obj2) || []; arr1.push({ obj: one, key }); arr2.push({ obj: two, key }); objects.set(obj1, arr1); objects.set(obj2, arr2); } result[key] = mergeTwoObjects(result[key], twoValue, level, objects); } } } } else { result = two; } } return result; } /** * Function to check if object has been already reference * @param obj * @param key * @param objects */ function wasObjectReferenced(obj, key, objects) { const arr = objects.get(obj[key]) || []; for (let i = 0, j = arr.length; i < j; i++) { const info = arr[i]; if (info.key === key && info.obj === obj) { return true; } } return false; } function isArray(value) { return Array.isArray(value); } function isFunction(value) { return typeof value === 'function'; } function isObject(value) { return (!isPrimitive(value) && !isArray(value) && !isFunction(value) && typeof value === 'object'); } function isPrimitive(value) { return (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || typeof value === 'undefined' || value instanceof Date || value instanceof RegExp || value === null); } function shouldMerge(one, two) { if (!isPlainObject(one) || !isPlainObject(two)) { return false; } return true; } //# sourceMappingURL=merge.js.map