@opentelemetry/core
Version:
OpenTelemetry Core provides constants and utilities shared by all OpenTelemetry SDK packages.
114 lines (113 loc) • 3.52 kB
JavaScript
const require_lodash_merge = require("./lodash.merge.cjs");
//#region src/utils/merge.ts
const MAX_LEVEL = 20;
/**
* Merges objects together
* @param args - objects / values to be merged
*/
function merge(...args) {
let result = args.shift();
const objects = /* @__PURE__ */ 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;
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];
if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
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];
if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
const twoValue = two[key];
if (isPrimitive(twoValue)) {
if (typeof twoValue === "undefined") delete result[key];
else 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 (!require_lodash_merge.isPlainObject(one) || !require_lodash_merge.isPlainObject(two)) return false;
return true;
}
//#endregion
exports.merge = merge;
//# sourceMappingURL=merge.cjs.map