UNPKG

ts-prime

Version:

A utility library for JavaScript and Typescript.

112 lines (111 loc) 4.04 kB
var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __spreadArrays = (this && this.__spreadArrays) || function () { for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j]; return r; }; import { isDefined, isArray, isObject } from './guards'; import { uniq } from './uniq'; import { clone } from './clone'; function isCyclic(object) { var seenObjects = new WeakMap(); // use to keep track of which objects have been seen. function detectCycle(obj) { // If 'obj' is an actual object (i.e., has the form of '{}'), check // if it's been seen already. if (isObject(obj) && Object.prototype.toString.call(obj) == '[object Object]') { if (seenObjects.has(obj)) { return true; } // If 'obj' hasn't been seen, add it to 'seenObjects'. // Since 'obj' is used as a key, the value of 'seenObjects[obj]' // is irrelevant and can be set as literally anything you want. I // just went with 'undefined'. seenObjects.set(obj, undefined); // Recurse through the object, looking for more circular references. for (var key in obj) { if (detectCycle(obj[key])) { return true; } } // If 'obj' is an array, check if any of it's elements are // an object that has been seen already. } else if (Array.isArray(obj)) { for (var i in obj) { if (detectCycle(obj[i])) { return true; } } } return false; } return detectCycle(object); } /** * Merging @param a and @param b recursively @param a is most important */ function recursiveMerge(a, b) { if (isObject(a) && isObject(b)) { var output = __assign({}, a); var keys = uniq(__spreadArrays(Object.keys(a), Object.keys(b))); for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) { var k = keys_1[_i]; // If object cyclic I will not try to merge objects if (isCyclic(a[k])) { output[k] = a[k]; continue; } output[k] = recursiveMerge(a[k], b[k]); } return output; } if (isArray(a) && isArray(b)) { // This step will nicely merge primitive values but will leave objects as duplicates return uniq(a.concat(b)); } // If we here we know that a is primitive value if it's defined we chose a over b // Unless this value is empty string if (isDefined(a)) { return a; } return b; } export function deepMergeLeft(target) { var sources = []; for (var _i = 1; _i < arguments.length; _i++) { sources[_i - 1] = arguments[_i]; } var output = __assign({}, target); for (var _a = 0, sources_1 = sources; _a < sources_1.length; _a++) { var source = sources_1[_a]; output = recursiveMerge(output, source); } return output; } export function deepMergeRight(target) { var sources = []; for (var _i = 1; _i < arguments.length; _i++) { sources[_i - 1] = arguments[_i]; } var output = clone(target); for (var _a = 0, sources_2 = sources; _a < sources_2.length; _a++) { var source = sources_2[_a]; // Only difference from mergeDeepLeft // That source go first and output last output = recursiveMerge(source, output); } return output; }