@orbit/utils
Version:
Core utilities for Orbit.
224 lines • 20.1 kB
JavaScript
/* eslint-disable @typescript-eslint/explicit-module-boundary-types, valid-jsdoc */
/**
* Clones a value. If the value is an object, a deeply nested clone will be
* created.
*
* Traverses all object properties (but not prototype properties).
*/
export function clone(obj) {
if (obj === undefined || obj === null || typeof obj !== 'object') {
return obj;
}
let dup;
let type = Object.prototype.toString.call(obj);
if (type === '[object Date]') {
dup = new Date();
dup.setTime(obj.getTime());
}
else if (type === '[object RegExp]') {
dup = obj.constructor(obj);
}
else if (type === '[object Array]') {
dup = [];
for (let i = 0, len = obj.length; i < len; i++) {
if (obj.hasOwnProperty(i)) {
dup.push(clone(obj[i]));
}
}
}
else {
let val;
dup = {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
val = obj[key];
if (typeof val === 'object') {
val = clone(val);
}
dup[key] = val;
}
}
}
return dup;
}
/**
* Expose properties and methods from one object on another.
*
* Methods will be called on `source` and will maintain `source` as the context.
*
* @deprecated since v0.17
*/
export function expose(destination, source) {
let properties;
if (arguments.length > 2) {
properties = Array.prototype.slice.call(arguments, 2);
}
else {
properties = Object.keys(source);
}
properties.forEach((p) => {
if (typeof source[p] === 'function') {
destination[p] = function () {
return source[p].apply(source, arguments);
};
}
else {
destination[p] = source[p];
}
});
}
/**
* Extend an object with the properties of one or more other objects.
*
* @deprecated since v0.17
*/
export function extend(destination, ...sources) {
sources.forEach((source) => {
for (let p in source) {
if (source.hasOwnProperty(p)) {
destination[p] = source[p];
}
}
});
return destination;
}
/**
* Converts an object to an `Array` if it's not already.
*
* @export
* @param {*} obj
* @returns {any[]}
*/
export function toArray(obj) {
if (isNone(obj)) {
return [];
}
else {
return Array.isArray(obj) ? obj : [obj];
}
}
/**
* Checks whether a value is a non-null object
*
* @export
* @param {*} obj
* @returns {boolean}
*/
export function isObject(obj) {
return obj !== null && typeof obj === 'object';
}
/**
* Checks whether an object is null or undefined
*
* @export
* @param {*} obj
* @returns {boolean}
*/
export function isNone(obj) {
return obj === undefined || obj === null;
}
/**
* Merges properties from other objects into a base object. Properties that
* resolve to `undefined` will not overwrite properties on the base object
* that already exist.
*
* @deprecated since v0.17
*/
export function merge(object, ...sources) {
sources.forEach((source) => {
Object.keys(source).forEach((field) => {
if (source.hasOwnProperty(field)) {
let value = source[field];
if (value !== undefined) {
object[field] = clone(value);
}
}
});
});
return object;
}
/**
* Merges properties from other objects into a base object, traversing and
* merging any objects that are encountered.
*
* Properties that resolve to `undefined` will not overwrite properties on the
* base object that already exist.
*/
export function deepMerge(object, ...sources) {
sources.forEach((source) => {
Object.keys(source).forEach((field) => {
if (source.hasOwnProperty(field)) {
let a = object[field];
let b = source[field];
if (isObject(a) &&
isObject(b) &&
!Array.isArray(a) &&
!Array.isArray(b)) {
deepMerge(a, b);
}
else if (b !== undefined) {
object[field] = clone(b);
}
}
});
});
return object;
}
/**
* Retrieves a value from a nested path on an object.
*
* Returns any falsy value encountered while traversing the path.
*/
export function deepGet(obj, path) {
let index = -1;
let result = obj;
while (++index < path.length) {
result = result[path[index]];
if (!result) {
return result;
}
}
return result;
}
/**
* Sets a value on an object at a nested path.
*
* This function will create objects along the path if necessary to allow
* setting a deeply nested value.
*
* Returns `false` only if the current value is already strictly equal to the
* requested `value` argument. Otherwise returns `true`.
*/
export function deepSet(obj, path, value) {
let ptr = obj;
let prop = path.pop();
let segment;
for (let i = 0, l = path.length; i < l; i++) {
segment = path[i];
if (ptr[segment] === undefined) {
ptr[segment] = typeof segment === 'number' ? [] : {};
}
ptr = ptr[segment];
}
if (ptr[prop] === value) {
return false;
}
else {
ptr[prop] = value;
return true;
}
}
/**
* Find an array of values that correspond to the keys of an object.
*
* This is a ponyfill for `Object.values`, which is still experimental.
*/
export function objectValues(obj) {
if (Object.values) {
return Object.values(obj);
}
else {
return Object.keys(obj).map((k) => obj[k]);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib2JqZWN0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9vYmplY3RzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLG1GQUFtRjtBQUVuRjs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSxLQUFLLENBQUMsR0FBUTtJQUM1QixJQUFJLEdBQUcsS0FBSyxTQUFTLElBQUksR0FBRyxLQUFLLElBQUksSUFBSSxPQUFPLEdBQUcsS0FBSyxRQUFRLEVBQUU7UUFDaEUsT0FBTyxHQUFHLENBQUM7S0FDWjtJQUVELElBQUksR0FBUSxDQUFDO0lBQ2IsSUFBSSxJQUFJLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBRS9DLElBQUksSUFBSSxLQUFLLGVBQWUsRUFBRTtRQUM1QixHQUFHLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUNqQixHQUFHLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO0tBQzVCO1NBQU0sSUFBSSxJQUFJLEtBQUssaUJBQWlCLEVBQUU7UUFDckMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUM7S0FDNUI7U0FBTSxJQUFJLElBQUksS0FBSyxnQkFBZ0IsRUFBRTtRQUNwQyxHQUFHLEdBQUcsRUFBRSxDQUFDO1FBQ1QsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxHQUFHLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUM5QyxJQUFJLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLEVBQUU7Z0JBQ3pCLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDekI7U0FDRjtLQUNGO1NBQU07UUFDTCxJQUFJLEdBQUcsQ0FBQztRQUVS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SSxDQUFDLEtBQUssS0FBSyxFQUFFO1FBQ3ZCLE9BQU8sS0FBSyxDQUFDO0tBQ2Q7U0FBTTtRQUNMLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUM7UUFDbEIsT0FBTyxJQUFJLENBQUM7S0FDYjtBQUNILENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLFlBQVksQ0FBQyxHQUFRO0lBQ25DLElBQUksTUFBTSxDQUFDLE1BQU0sRUFBRTtRQUNqQixPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7S0FDM0I7U0FBTTtRQUNMLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0tBQzVDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9leHBsaWNpdC1tb2R1bGUtYm91bmRhcnktdHlwZXMsIHZhbGlkLWpzZG9jICovXG5cbi8qKlxuICogQ2xvbmVzIGEgdmFsdWUuIElmIHRoZSB2YWx1ZSBpcyBhbiBvYmplY3QsIGEgZGVlcGx5IG5lc3RlZCBjbG9uZSB3aWxsIGJlXG4gKiBjcmVhdGVkLlxuICpcbiAqIFRyYXZlcnNlcyBhbGwgb2JqZWN0IHByb3BlcnRpZXMgKGJ1dCBub3QgcHJvdG90eXBlIHByb3BlcnRpZXMpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xvbmUob2JqOiBhbnkpOiBhbnkge1xuICBpZiAob2JqID09PSB1bmRlZmluZWQgfHwgb2JqID09PSBudWxsIHx8IHR5cGVvZiBvYmogIT09ICdvYmplY3QnKSB7XG4gICAgcmV0dXJuIG9iajtcbiAgfVxuXG4gIGxldCBkdXA6IGFueTtcbiAgbGV0IHR5cGUgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqKTtcblxuICBpZiAodHlwZSA9PT0gJ1tvYmplY3QgRGF0ZV0nKSB7XG4gICAgZHVwID0gbmV3IERhdGUoKTtcbiAgICBkdXAuc2V0VGltZShvYmouZ2V0VGltZSgpKTtcbiAgfSBlbHNlIGlmICh0eXBlID09PSAnW29iamVjdCBSZWdFeHBdJykge1xuICAgIGR1cCA9IG9iai5jb25zdHJ1Y3RvcihvYmopO1xuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdbb2JqZWN0IEFycmF5XScpIHtcbiAgICBkdXAgPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMCwgbGVuID0gb2JqLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBpZiAob2JqLmhhc093blByb3BlcnR5KGkpKSB7XG4gICAgICAgIGR1cC5wdXNoKGNsb25lKG9ialtpXSkpO1xuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBsZXQgdmFsO1xuXG4gICAgZHVwID0ge307XG4gICAgZm9yIChsZXQga2V5IGluIG9iaikge1xuICAgICAgaWYgKG9iai5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgIHZhbCA9IG9ialtrZXldO1xuICAgICAgICBpZiAodHlwZW9mIHZhbCA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICB2YWwgPSBjbG9uZSh2YWwpO1xuICAgICAgICB9XG4gICAgICAgIGR1cFtrZXldID0gdmFsO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gZHVwO1xufVxuXG4vKipcbiAqIEV4cG9zZSBwcm9wZXJ0aWVzIGFuZCBtZXRob2RzIGZyb20gb25lIG9iamVjdCBvbiBhbm90aGVyLlxuICpcbiAqIE1ldGhvZHMgd2lsbCBiZSBjYWxsZWQgb24gYHNvdXJjZWAgYW5kIHdpbGwgbWFpbnRhaW4gYHNvdXJjZWAgYXMgdGhlIGNvbnRleHQuXG4gKlxuICogQGRlcHJlY2F0ZWQgc2luY2UgdjAuMTdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4cG9zZShkZXN0aW5hdGlvbjogYW55LCBzb3VyY2U6IGFueSk6IHZvaWQge1xuICBsZXQgcHJvcGVydGllczogc3RyaW5nW107XG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMikge1xuICAgIHByb3BlcnRpZXMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpO1xuICB9IGVsc2Uge1xuICAgIHByb3BlcnRpZXMgPSBPYmplY3Qua2V5cyhzb3VyY2UpO1xuICB9XG5cbiAgcHJvcGVydGllcy5mb3JFYWNoKChwKSA9PiB7XG4gICAgaWYgKHR5cGVvZiBzb3VyY2VbcF0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGRlc3RpbmF0aW9uW3BdID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gc291cmNlW3BdLmFwcGx5KHNvdXJjZSwgYXJndW1lbnRzKTtcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIGRlc3RpbmF0aW9uW3BdID0gc291cmNlW3BdO1xuICAgIH1cbiAgfSk7XG59XG5cbi8qKlxuICogRXh0ZW5kIGFuIG9iamVjdCB3aXRoIHRoZSBwcm9wZXJ0aWVzIG9mIG9uZSBvciBtb3JlIG90aGVyIG9iamVjdHMuXG4gKlxuICogQGRlcHJlY2F0ZWQgc2luY2UgdjAuMTdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4dGVuZChkZXN0aW5hdGlvbjogYW55LCAuLi5zb3VyY2VzOiBhbnlbXSk6IGFueSB7XG4gIHNvdXJjZXMuZm9yRWFjaCgoc291cmNlKSA9PiB7XG4gICAgZm9yIChsZXQgcCBpbiBzb3VyY2UpIHtcbiAgICAgIGlmIChzb3VyY2UuaGFzT3duUHJvcGVydHkocCkpIHtcbiAgICAgICAgZGVzdGluYXRpb25bcF0gPSBzb3VyY2VbcF07XG4gICAgICB9XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIGRlc3RpbmF0aW9uO1xufVxuXG4vKipcbiAqIENvbnZlcnRzIGFuIG9iamVjdCB0byBhbiBgQXJyYXlgIGlmIGl0J3Mgbm90IGFscmVhZHkuXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHsqfSBvYmpcbiAqIEByZXR1cm5zIHthbnlbXX1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvQXJyYXkob2JqOiB1bmtub3duKTogYW55W10ge1xuICBpZiAoaXNOb25lKG9iaikpIHtcbiAgICByZXR1cm4gW107XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIEFycmF5LmlzQXJyYXkob2JqKSA/IG9iaiA6IFtvYmpdO1xuICB9XG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYSB2YWx1ZSBpcyBhIG5vbi1udWxsIG9iamVjdFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7Kn0gb2JqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzT2JqZWN0KG9iajogdW5rbm93bik6IGJvb2xlYW4ge1xuICByZXR1cm4gb2JqICE9PSBudWxsICYmIHR5cGVvZiBvYmogPT09ICdvYmplY3QnO1xufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIGFuIG9iamVjdCBpcyBudWxsIG9yIHVuZGVmaW5lZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7Kn0gb2JqXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzTm9uZShvYmo6IHVua25vd24pOiBib29sZWFuIHtcbiAgcmV0dXJuIG9iaiA9PT0gdW5kZWZpbmVkIHx8IG9iaiA9PT0gbnVsbDtcbn1cblxuLyoqXG4gKiBNZXJnZXMgcHJvcGVydGllcyBmcm9tIG90aGVyIG9iamVjdHMgaW50byBhIGJhc2Ugb2JqZWN0LiBQcm9wZXJ0aWVzIHRoYXRcbiAqIHJlc29sdmUgdG8gYHVuZGVmaW5lZGAgd2lsbCBub3Qgb3ZlcndyaXRlIHByb3BlcnRpZXMgb24gdGhlIGJhc2Ugb2JqZWN0XG4gKiB0aGF0IGFscmVhZHkgZXhpc3QuXG4gKlxuICogQGRlcHJlY2F0ZWQgc2luY2UgdjAuMTdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1lcmdlKG9iamVjdDogYW55LCAuLi5zb3VyY2VzOiBhbnlbXSk6IGFueSB7XG4gIHNvdXJjZXMuZm9yRWFjaCgoc291cmNlKSA9PiB7XG4gICAgT2JqZWN0LmtleXMoc291cmNlKS5mb3JFYWNoKChmaWVsZCkgPT4ge1xuICAgICAgaWYgKHNvdXJjZS5oYXNPd25Qcm9wZXJ0eShmaWVsZCkpIHtcbiAgICAgICAgbGV0IHZhbHVlID0gc291cmNlW2ZpZWxkXTtcbiAgICAgICAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBvYmplY3RbZmllbGRdID0gY2xvbmUodmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuICByZXR1cm4gb2JqZWN0O1xufVxuXG4vKipcbiAqIE1lcmdlcyBwcm9wZXJ0aWVzIGZyb20gb3RoZXIgb2JqZWN0cyBpbnRvIGEgYmFzZSBvYmplY3QsIHRyYXZlcnNpbmcgYW5kXG4gKiBtZXJnaW5nIGFueSBvYmplY3RzIHRoYXQgYXJlIGVuY291bnRlcmVkLlxuICpcbiAqIFByb3BlcnRpZXMgdGhhdCByZXNvbHZlIHRvIGB1bmRlZmluZWRgIHdpbGwgbm90IG92ZXJ3cml0ZSBwcm9wZXJ0aWVzIG9uIHRoZVxuICogYmFzZSBvYmplY3QgdGhhdCBhbHJlYWR5IGV4aXN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVlcE1lcmdlKG9iamVjdDogYW55LCAuLi5zb3VyY2VzOiBhbnlbXSk6IGFueSB7XG4gIHNvdXJjZXMuZm9yRWFjaCgoc291cmNlKSA9PiB7XG4gICAgT2JqZWN0LmtleXMoc291cmNlKS5mb3JFYWNoKChmaWVsZCkgPT4ge1xuICAgICAgaWYgKHNvdXJjZS5oYXNPd25Qcm9wZXJ0eShmaWVsZCkpIHtcbiAgICAgICAgbGV0IGEgPSBvYmplY3RbZmllbGRdO1xuICAgICAgICBsZXQgYiA9IHNvdXJjZVtmaWVsZF07XG4gICAgICAgIGlmIChcbiAgICAgICAgICBpc09iamVjdChhKSAmJlxuICAgICAgICAgIGlzT2JqZWN0KGIpICYmXG4gICAgICAgICAgIUFycmF5LmlzQXJyYXkoYSkgJiZcbiAgICAgICAgICAhQXJyYXkuaXNBcnJheShiKVxuICAgICAgICApIHtcbiAgICAgICAgICBkZWVwTWVyZ2UoYSwgYik7XG4gICAgICAgIH0gZWxzZSBpZiAoYiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgb2JqZWN0W2ZpZWxkXSA9IGNsb25lKGIpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuICByZXR1cm4gb2JqZWN0O1xufVxuXG4vKipcbiAqIFJldHJpZXZlcyBhIHZhbHVlIGZyb20gYSBuZXN0ZWQgcGF0aCBvbiBhbiBvYmplY3QuXG4gKlxuICogUmV0dXJucyBhbnkgZmFsc3kgdmFsdWUgZW5jb3VudGVyZWQgd2hpbGUgdHJhdmVyc2luZyB0aGUgcGF0aC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlZXBHZXQob2JqOiBhbnksIHBhdGg6IHN0cmluZ1tdKTogYW55IHtcbiAgbGV0IGluZGV4ID0gLTE7XG4gIGxldCByZXN1bHQgPSBvYmo7XG5cbiAgd2hpbGUgKCsraW5kZXggPCBwYXRoLmxlbmd0aCkge1xuICAgIHJlc3VsdCA9IHJlc3VsdFtwYXRoW2luZGV4XV07XG4gICAgaWYgKCFyZXN1bHQpIHtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBTZXRzIGEgdmFsdWUgb24gYW4gb2JqZWN0IGF0IGEgbmVzdGVkIHBhdGguXG4gKlxuICogVGhpcyBmdW5jdGlvbiB3aWxsIGNyZWF0ZSBvYmplY3RzIGFsb25nIHRoZSBwYXRoIGlmIG5lY2Vzc2FyeSB0byBhbGxvd1xuICogc2V0dGluZyBhIGRlZXBseSBuZXN0ZWQgdmFsdWUuXG4gKlxuICogUmV0dXJucyBgZmFsc2VgIG9ubHkgaWYgdGhlIGN1cnJlbnQgdmFsdWUgaXMgYWxyZWFkeSBzdHJpY3RseSBlcXVhbCB0byB0aGVcbiAqIHJlcXVlc3RlZCBgdmFsdWVgIGFyZ3VtZW50LiBPdGhlcndpc2UgcmV0dXJucyBgdHJ1ZWAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWVwU2V0KG9iajogYW55LCBwYXRoOiBzdHJpbmdbXSwgdmFsdWU6IGFueSk6IGJvb2xlYW4ge1xuICBsZXQgcHRyID0gb2JqO1xuICBsZXQgcHJvcCA9IHBhdGgucG9wKCkgYXMgc3RyaW5nO1xuICBsZXQgc2VnbWVudDtcbiAgZm9yIChsZXQgaSA9IDAsIGwgPSBwYXRoLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgIHNlZ21lbnQgPSBwYXRoW2ldO1xuICAgIGlmIChwdHJbc2VnbWVudF0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgcHRyW3NlZ21lbnRdID0gdHlwZW9mIHNlZ21lbnQgPT09ICdudW1iZXInID8gW10gOiB7fTtcbiAgICB9XG4gICAgcHRyID0gcHRyW3NlZ21lbnRdO1xuICB9XG4gIGlmIChwdHJbcHJvcF0gPT09IHZhbHVlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9IGVsc2Uge1xuICAgIHB0cltwcm9wXSA9IHZhbHVlO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG59XG5cbi8qKlxuICogRmluZCBhbiBhcnJheSBvZiB2YWx1ZXMgdGhhdCBjb3JyZXNwb25kIHRvIHRoZSBrZXlzIG9mIGFuIG9iamVjdC5cbiAqXG4gKiBUaGlzIGlzIGEgcG9ueWZpbGwgZm9yIGBPYmplY3QudmFsdWVzYCwgd2hpY2ggaXMgc3RpbGwgZXhwZXJpbWVudGFsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gb2JqZWN0VmFsdWVzKG9iajogYW55KTogYW55W10ge1xuICBpZiAoT2JqZWN0LnZhbHVlcykge1xuICAgIHJldHVybiBPYmplY3QudmFsdWVzKG9iaik7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKG9iaikubWFwKChrKSA9PiBvYmpba10pO1xuICB9XG59XG4iXX0=