gst-atom-xcuitest-driver
Version:
ATOM driver for iOS using XCUITest for backend
401 lines (308 loc) • 51.2 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.gesturesChainToString = gesturesChainToString;
exports.default = exports.commands = exports.helpers = exports.extensions = void 0;
require("source-map-support/register");
var _gstAtomBaseDriver = require("gst-atom-base-driver");
var _appiumSupport = require("appium-support");
var _gstAtomIosDriver = require("gst-atom-ios-driver");
var _lodash = _interopRequireDefault(require("lodash"));
var _logger = _interopRequireDefault(require("../logger"));
let helpers = {},
extensions = {},
commands = {};
exports.commands = commands;
exports.extensions = extensions;
exports.helpers = helpers;
commands.moveTo = _gstAtomIosDriver.iosCommands.gesture.moveTo;
function requireFloatParameter(paramName, paramValue, methodName) {
if (_lodash.default.isUndefined(paramValue)) {
_logger.default.errorAndThrow(`"${paramName}" parameter is mandatory for "${methodName}" call`);
}
const result = parseFloat(paramValue);
if (isNaN(result)) {
_logger.default.errorAndThrow(`"${paramName}" parameter should be a valid number. "${paramValue}" is given instead`);
}
return result;
}
function requireIntParameter(paramName, paramValue, methodName) {
if (_lodash.default.isUndefined(paramValue)) {
_logger.default.errorAndThrow(`"${paramName}" parameter is mandatory for "${methodName}" call`);
}
const result = parseInt(paramValue, 10);
if (isNaN(result)) {
_logger.default.errorAndThrow(`"${paramName}" parameter should be a valid integer. "${paramValue}" is given instead`);
}
return result;
}
commands.mobileShake = async function mobileShake() {
if (!this.isSimulator()) {
throw new _gstAtomBaseDriver.errors.UnknownError('Shake is not supported on real devices');
}
await this.opts.device.shake();
};
commands.click = async function click(el) {
if (!this.isWebContext()) {
return await this.nativeClick(el);
}
el = _appiumSupport.util.unwrapElement(el);
if ((await this.settings.getSettings()).nativeWebTap || (await this.settings.getSettings()).nativeWebTapStrict) {
_logger.default.debug('Using native web tap');
await this.nativeWebTap(el);
} else {
const atomsElement = this.useAtomsElement(el);
return await this.executeAtom('click', [atomsElement]);
}
};
function gesturesChainToString(gestures, keysToInclude = ['options']) {
return gestures.map(item => {
let otherKeys = _lodash.default.difference(_lodash.default.keys(item), ['action']);
otherKeys = _lodash.default.isArray(keysToInclude) ? _lodash.default.intersection(otherKeys, keysToInclude) : otherKeys;
if (otherKeys.length) {
return `${item.action}` + `(${_lodash.default.map(otherKeys, x => x + '=' + (_lodash.default.isPlainObject(item[x]) ? JSON.stringify(item[x]) : item[x])).join(', ')})`;
}
return item.action;
}).join('-');
}
commands.performActions = async function performActions(actions) {
_logger.default.debug(`Received the following W3C actions: ${JSON.stringify(actions, null, ' ')}`);
const preprocessedActions = actions.map(action => Object.assign({}, action, action.type === 'pointer' ? {
parameters: {
pointerType: 'touch'
}
} : {})).map(action => {
const modifiedAction = _lodash.default.clone(action) || {};
modifiedAction.actions = (action.actions || []).filter(innerAction => !(innerAction.type === 'pause' && innerAction.duration === 0));
return modifiedAction;
});
_logger.default.debug(`Preprocessed actions: ${JSON.stringify(preprocessedActions, null, ' ')}`);
return await this.proxyCommand('/actions', 'POST', {
actions: preprocessedActions
});
};
commands.performTouch = async function performTouch(gestures) {
_logger.default.debug(`Received the following touch action: ${gesturesChainToString(gestures)}`);
try {
return await this.proxyCommand('/wda/touch/perform', 'POST', {
actions: gestures
});
} catch (e) {
if (!this.isWebContext()) {
throw e;
}
_logger.default.errorAndThrow('The Touch API is aimed for usage in NATIVE context. ' + 'Consider using "execute" API with custom events trigger script ' + `to emulate touch events being in WEBVIEW context. Original error: ${e.message}`);
}
};
commands.performMultiAction = async function performMultiAction(actions) {
_logger.default.debug(`Received the following multi touch action:`);
for (let i in actions) {
_logger.default.debug(` ${parseInt(i, 10) + 1}: ${_lodash.default.map(actions[i], 'action').join('-')}`);
}
try {
return await this.proxyCommand('/wda/touch/multi/perform', 'POST', {
actions
});
} catch (e) {
if (!this.isWebContext()) {
throw e;
}
_logger.default.errorAndThrow('The MultiTouch API is aimed for usage in NATIVE context. ' + 'Consider using "execute" API with custom events trigger script ' + `to emulate multitouch events being in WEBVIEW context. Original error: ${e.message}`);
}
};
commands.nativeClick = async function nativeClick(el) {
el = _appiumSupport.util.unwrapElement(el);
let endpoint = `/element/${el}/click`;
return await this.proxyCommand(endpoint, 'POST', {});
};
helpers.mobileScroll = async function mobileScroll(opts = {}, swipe = false) {
if (!opts.element) {
opts.element = await this.findNativeElementOrElements(`class name`, `XCUIElementTypeApplication`, false);
}
let params = {};
if (opts.name && !swipe) {
params.name = opts.name;
} else if (opts.direction) {
if (!['up', 'down', 'left', 'right'].includes(opts.direction.toLowerCase())) {
let msg = 'Direction must be up, down, left or right';
_logger.default.errorAndThrow(msg);
}
params.direction = opts.direction;
} else if (opts.predicateString && !swipe) {
params.predicateString = opts.predicateString;
} else if (opts.toVisible && !swipe) {
params.toVisible = opts.toVisible;
} else {
let msg = swipe ? 'Mobile swipe requires direction' : 'Mobile scroll supports the following strategies: name, direction, predicateString, and toVisible. Specify one of these';
_logger.default.errorAndThrow(msg);
}
if (!swipe && opts.distance) {
params.distance = opts.distance;
}
let element = _appiumSupport.util.unwrapElement(opts.element);
let endpoint = `/wda/element/${element}/${swipe ? 'swipe' : 'scroll'}`;
return await this.proxyCommand(endpoint, 'POST', params);
};
helpers.mobileSwipe = async function mobileSwipe(opts = {}) {
return await this.mobileScroll(opts, true);
};
helpers.mobilePinch = async function mobilePinch(opts = {}) {
if (!opts.element) {
opts.element = await this.findNativeElementOrElements(`class name`, `XCUIElementTypeApplication`, false);
}
const params = {
scale: requireFloatParameter('scale', opts.scale, 'pinch'),
velocity: requireFloatParameter('velocity', opts.velocity, 'pinch')
};
const el = _appiumSupport.util.unwrapElement(opts.element);
return await this.proxyCommand(`/wda/element/${el}/pinch`, 'POST', params);
};
helpers.mobileDoubleTap = async function mobileDoubleTap(opts = {}) {
if (opts.element) {
const el = _appiumSupport.util.unwrapElement(opts.element);
return await this.proxyCommand(`/wda/element/${el}/doubleTap`, 'POST');
}
const params = {
x: requireFloatParameter('x', opts.x, 'doubleTap'),
y: requireFloatParameter('y', opts.y, 'doubleTap')
};
return await this.proxyCommand('/wda/doubleTap', 'POST', params);
};
helpers.mobileTwoFingerTap = async function mobileTwoFingerTap(opts = {}) {
if (!opts.element) {
opts.element = await this.findNativeElementOrElements(`class name`, `XCUIElementTypeApplication`, false);
}
const el = _appiumSupport.util.unwrapElement(opts.element);
return await this.proxyCommand(`/wda/element/${el}/twoFingerTap`, 'POST');
};
helpers.mobileTouchAndHold = async function mobileTouchAndHold(opts = {}) {
let params = {
duration: requireFloatParameter('duration', opts.duration, 'touchAndHold')
};
if (opts.element) {
const el = _appiumSupport.util.unwrapElement(opts.element);
return await this.proxyCommand(`/wda/element/${el}/touchAndHold`, 'POST', params);
}
params.x = requireFloatParameter('x', opts.x, 'touchAndHold');
params.y = requireFloatParameter('y', opts.y, 'touchAndHold');
return await this.proxyCommand('/wda/touchAndHold', 'POST', params);
};
helpers.mobileTap = async function mobileTap(opts = {}) {
const params = {
x: requireFloatParameter('x', opts.x, 'tap'),
y: requireFloatParameter('y', opts.y, 'tap')
};
const el = opts.element ? _appiumSupport.util.unwrapElement(opts.element) : '0';
return await this.proxyCommand(`/wda/tap/${el}`, 'POST', params);
};
helpers.mobileDragFromToForDuration = async function mobileDragFromToForDuration(opts = {}) {
const params = {
duration: requireFloatParameter('duration', opts.duration, 'dragFromToForDuration'),
fromX: requireFloatParameter('fromX', opts.fromX, 'dragFromToForDuration'),
fromY: requireFloatParameter('fromY', opts.fromY, 'dragFromToForDuration'),
toX: requireFloatParameter('toX', opts.toX, 'dragFromToForDuration'),
toY: requireFloatParameter('toY', opts.toY, 'dragFromToForDuration')
};
if (opts.element) {
const el = _appiumSupport.util.unwrapElement(opts.element);
return await this.proxyCommand(`/wda/element/${el}/dragfromtoforduration`, 'POST', params);
}
return await this.proxyCommand('/wda/dragfromtoforduration', 'POST', params);
};
helpers.mobileTapWithNumberOfTaps = async function mobileTapWithNumberOfTaps(opts = {}) {
if (!opts.element) {
_logger.default.errorAndThrow('Element id is expected to be set for tapWithNumberOfTaps method');
}
const params = {
numberOfTaps: requireIntParameter('numberOfTaps', opts.numberOfTaps, 'tapWithNumberOfTaps'),
numberOfTouches: requireIntParameter('numberOfTouches', opts.numberOfTouches, 'tapWithNumberOfTaps')
};
const el = _appiumSupport.util.unwrapElement(opts.element);
return await this.proxyCommand(`/wda/element/${el}/tapWithNumberOfTaps`, 'POST', params);
};
helpers.mobileSelectPickerWheelValue = async function mobileSelectPickerWheelValue(opts = {}) {
if (!opts.element) {
_logger.default.errorAndThrow('Element id is expected to be set for selectPickerWheelValue method');
}
if (!_lodash.default.isString(opts.order) || !['next', 'previous'].includes(opts.order.toLowerCase())) {
_logger.default.errorAndThrow(`The mandatory 'order' parameter is expected to be equal either to 'next' or 'previous'. ` + `'${opts.order}' is given instead`);
}
const el = _appiumSupport.util.unwrapElement(opts.element);
const params = {
order: opts.order
};
if (opts.offset) {
params.offset = requireFloatParameter('offset', opts.offset, 'selectPickerWheelValue');
}
return await this.proxyCommand(`/wda/pickerwheel/${el}/select`, 'POST', params);
};
helpers.mobileRotateElement = async function mobileRotateElement(opts = {}) {
if (!opts.element) {
_logger.default.errorAndThrow('Element id is expected to be set for rotateElement method');
}
const el = _appiumSupport.util.unwrapElement(opts.element);
const params = {
rotation: requireFloatParameter('rotation', opts.rotation, 'rotateElement'),
velocity: requireFloatParameter('velocity', opts.velocity, 'rotateElement')
};
return await this.proxyCommand(`/wda/element/${el}/rotate`, 'POST', params);
};
helpers.getCoordinates = async function getCoordinates(gesture) {
let el = gesture.options.element;
let coordinates = {
x: 0,
y: 0,
areOffsets: false
};
let optionX = null;
if (gesture.options.x) {
optionX = requireFloatParameter('x', gesture.options.x, 'getCoordinates');
}
let optionY = null;
if (gesture.options.y) {
optionY = requireFloatParameter('y', gesture.options.y, 'getCoordinates');
}
if (el) {
let rect = await this.getElementRect(el);
let pos = {
x: rect.x,
y: rect.y
};
let size = {
w: rect.width,
h: rect.height
};
let offsetX = 0;
let offsetY = 0;
if (optionX || optionY) {
offsetX = optionX || 0;
offsetY = optionY || 0;
} else {
offsetX = size.w / 2;
offsetY = size.h / 2;
}
coordinates.x = pos.x + offsetX;
coordinates.y = pos.y + offsetY;
} else {
coordinates.areOffsets = gesture.action === 'moveTo';
coordinates.x = optionX || 0;
coordinates.y = optionY || 0;
}
return coordinates;
};
helpers.applyMoveToOffset = function applyMoveToOffset(firstCoordinates, secondCoordinates) {
if (secondCoordinates.areOffsets) {
return {
x: firstCoordinates.x + secondCoordinates.x,
y: firstCoordinates.y + secondCoordinates.y
};
} else {
return secondCoordinates;
}
};
Object.assign(extensions, helpers, commands);
var _default = extensions;
exports.default = _default;require('source-map-support').install();
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi9jb21tYW5kcy9nZXN0dXJlLmpzIl0sIm5hbWVzIjpbImhlbHBlcnMiLCJleHRlbnNpb25zIiwiY29tbWFuZHMiLCJtb3ZlVG8iLCJpb3NDb21tYW5kcyIsImdlc3R1cmUiLCJyZXF1aXJlRmxvYXRQYXJhbWV0ZXIiLCJwYXJhbU5hbWUiLCJwYXJhbVZhbHVlIiwibWV0aG9kTmFtZSIsIl8iLCJpc1VuZGVmaW5lZCIsImxvZyIsImVycm9yQW5kVGhyb3ciLCJyZXN1bHQiLCJwYXJzZUZsb2F0IiwiaXNOYU4iLCJyZXF1aXJlSW50UGFyYW1ldGVyIiwicGFyc2VJbnQiLCJtb2JpbGVTaGFrZSIsImlzU2ltdWxhdG9yIiwiZXJyb3JzIiwiVW5rbm93bkVycm9yIiwib3B0cyIsImRldmljZSIsInNoYWtlIiwiY2xpY2siLCJlbCIsImlzV2ViQ29udGV4dCIsIm5hdGl2ZUNsaWNrIiwidXRpbCIsInVud3JhcEVsZW1lbnQiLCJzZXR0aW5ncyIsImdldFNldHRpbmdzIiwibmF0aXZlV2ViVGFwIiwibmF0aXZlV2ViVGFwU3RyaWN0IiwiZGVidWciLCJhdG9tc0VsZW1lbnQiLCJ1c2VBdG9tc0VsZW1lbnQiLCJleGVjdXRlQXRvbSIsImdlc3R1cmVzQ2hhaW5Ub1N0cmluZyIsImdlc3R1cmVzIiwia2V5c1RvSW5jbHVkZSIsIm1hcCIsIml0ZW0iLCJvdGhlcktleXMiLCJkaWZmZXJlbmNlIiwia2V5cyIsImlzQXJyYXkiLCJpbnRlcnNlY3Rpb24iLCJsZW5ndGgiLCJhY3Rpb24iLCJ4IiwiaXNQbGFpbk9iamVjdCIsIkpTT04iLCJzdHJpbmdpZnkiLCJqb2luIiwicGVyZm9ybUFjdGlvbnMiLCJhY3Rpb25zIiwicHJlcHJvY2Vzc2VkQWN0aW9ucyIsIk9iamVjdCIsImFzc2lnbiIsInR5cGUiLCJwYXJhbWV0ZXJzIiwicG9pbnRlclR5cGUiLCJtb2RpZmllZEFjdGlvbiIsImNsb25lIiwiZmlsdGVyIiwiaW5uZXJBY3Rpb24iLCJkdXJhdGlvbiIsInByb3h5Q29tbWFuZCIsInBlcmZvcm1Ub3VjaCIsImUiLCJtZXNzYWdlIiwicGVyZm9ybU11bHRpQWN0aW9uIiwiaSIsImVuZHBvaW50IiwibW9iaWxlU2Nyb2xsIiwic3dpcGUiLCJlbGVtZW50IiwiZmluZE5hdGl2ZUVsZW1lbnRPckVsZW1lbnRzIiwicGFyYW1zIiwibmFtZSIsImRpcmVjdGlvbiIsImluY2x1ZGVzIiwidG9Mb3dlckNhc2UiLCJtc2ciLCJwcmVkaWNhdGVTdHJpbmciLCJ0b1Zpc2libGUiLCJkaXN0YW5jZSIsIm1vYmlsZVN3aXBlIiwibW9iaWxlUGluY2giLCJzY2FsZSIsInZlbG9jaXR5IiwibW9iaWxlRG91YmxlVGFwIiwieSIsIm1vYmlsZVR3b0ZpbmdlclRhcCIsIm1vYmlsZVRvdWNoQW5kSG9sZCIsIm1vYmlsZVRhcCIsIm1vYmlsZURyYWdGcm9tVG9Gb3JEdXJhdGlvbiIsImZyb21YIiwiZnJvbVkiLCJ0b1giLCJ0b1kiLCJtb2JpbGVUYXBXaXRoTnVtYmVyT2ZUYXBzIiwibnVtYmVyT2ZUYXBzIiwibnVtYmVyT2ZUb3VjaGVzIiwibW9iaWxlU2VsZWN0UGlja2VyV2hlZWxWYWx1ZSIsImlzU3RyaW5nIiwib3JkZXIiLCJvZmZzZXQiLCJtb2JpbGVSb3RhdGVFbGVtZW50Iiwicm90YXRpb24iLCJnZXRDb29yZGluYXRlcyIsIm9wdGlvbnMiLCJjb29yZGluYXRlcyIsImFyZU9mZnNldHMiLCJvcHRpb25YIiwib3B0aW9uWSIsInJlY3QiLCJnZXRFbGVtZW50UmVjdCIsInBvcyIsInNpemUiLCJ3Iiwid2lkdGgiLCJoIiwiaGVpZ2h0Iiwib2Zmc2V0WCIsIm9mZnNldFkiLCJhcHBseU1vdmVUb09mZnNldCIsImZpcnN0Q29vcmRpbmF0ZXMiLCJzZWNvbmRDb29yZGluYXRlcyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBR0EsSUFBSUEsT0FBTyxHQUFHLEVBQWQ7QUFBQSxJQUFrQkMsVUFBVSxHQUFHLEVBQS9CO0FBQUEs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V0FBTztBQUNMaEUsTUFBQUEsQ0FBQyxFQUFFOEUsZ0JBQWdCLENBQUM5RSxDQUFqQixHQUFxQitFLGlCQUFpQixDQUFDL0UsQ0FEckM7QUFFTDJDLE1BQUFBLENBQUMsRUFBRW1DLGdCQUFnQixDQUFDbkMsQ0FBakIsR0FBcUJvQyxpQkFBaUIsQ0FBQ3BDO0FBRnJDLEtBQVA7QUFJRCxHQUxELE1BS087QUFDTCxXQUFPb0MsaUJBQVA7QUFDRDtBQUNGLENBVEQ7O0FBV0F2RSxNQUFNLENBQUNDLE1BQVAsQ0FBYzVELFVBQWQsRUFBMEJELE9BQTFCLEVBQW1DRSxRQUFuQztlQUVlRCxVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZXJyb3JzIH0gZnJvbSAnZ3N0LWF0b20tYmFzZS1kcml2ZXInO1xuaW1wb3J0IHsgdXRpbCB9IGZyb20gJ2FwcGl1bS1zdXBwb3J0JztcbmltcG9ydCB7IGlvc0NvbW1hbmRzIH0gZnJvbSAnZ3N0LWF0b20taW9zLWRyaXZlcic7XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IGxvZyBmcm9tICcuLi9sb2dnZXInO1xuXG5cbmxldCBoZWxwZXJzID0ge30sIGV4dGVuc2lvbnMgPSB7fSwgY29tbWFuZHMgPSB7fTtcblxuY29tbWFuZHMubW92ZVRvID0gaW9zQ29tbWFuZHMuZ2VzdHVyZS5tb3ZlVG87XG5cblxuZnVuY3Rpb24gcmVxdWlyZUZsb2F0UGFyYW1ldGVyIChwYXJhbU5hbWUsIHBhcmFtVmFsdWUsIG1ldGhvZE5hbWUpIHtcbiAgaWYgKF8uaXNVbmRlZmluZWQocGFyYW1WYWx1ZSkpIHtcbiAgICBsb2cuZXJyb3JBbmRUaHJvdyhgXCIke3BhcmFtTmFtZX1cIiBwYXJhbWV0ZXIgaXMgbWFuZGF0b3J5IGZvciBcIiR7bWV0aG9kTmFtZX1cIiBjYWxsYCk7XG4gIH1cbiAgY29uc3QgcmVzdWx0ID0gcGFyc2VGbG9hdChwYXJhbVZhbHVlKTtcbiAgaWYgKGlzTmFOKHJlc3VsdCkpIHtcbiAgICBsb2cuZXJyb3JBbmRUaHJvdyhgXCIke3BhcmFtTmFtZX1cIiBwYXJhbWV0ZXIgc2hvdWxkIGJlIGEgdmFsaWQgbnVtYmVyLiBcIiR7cGFyYW1WYWx1ZX1cIiBpcyBnaXZlbiBpbnN0ZWFkYCk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZnVuY3Rpb24gcmVxdWlyZUludFBhcmFtZXRlciAocGFyYW1OYW1lLCBwYXJhbVZhbHVlLCBtZXRob2ROYW1lKSB7XG4gIGlmIChfLmlzVW5kZWZpbmVkKHBhcmFtVmFsdWUpKSB7XG4gICAgbG9nLmVycm9yQW5kVGhyb3coYFwiJHtwYXJhbU5hbWV9XCIgcGFyYW1ldGVyIGlzIG1hbmRhdG9yeSBmb3IgXCIke21ldGhvZE5hbWV9XCIgY2FsbGApO1xuICB9XG4gIGNvbnN0IHJlc3VsdCA9IHBhcnNlSW50KHBhcmFtVmFsdWUsIDEwKTtcbiAgaWYgKGlzTmFOKHJlc3VsdCkpIHtcbiAgICBsb2cuZXJyb3JBbmRUaHJvdyhgXCIke3BhcmFtTmFtZX1cIiBwYXJhbWV0ZXIgc2hvdWxkIGJlIGEgdmFsaWQgaW50ZWdlci4gXCIke3BhcmFtVmFsdWV9XCIgaXMgZ2l2ZW4gaW5zdGVhZGApO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmNvbW1hbmRzLm1vYmlsZVNoYWtlID0gYXN5bmMgZnVuY3Rpb24gbW9iaWxlU2hha2UgKCkge1xuICBpZiAoIXRoaXMuaXNTaW11bGF0b3IoKSkge1xuICAgIHRocm93IG5ldyBlcnJvcnMuVW5rbm93bkVycm9yKCdTaGFrZSBpcyBub3Qgc3VwcG9ydGVkIG9uIHJlYWwgZGV2aWNlcycpO1xuICB9XG4gIGF3YWl0IHRoaXMub3B0cy5kZXZpY2Uuc2hha2UoKTtcbn07XG5cbmNvbW1hbmRzLmNsaWNrID0gYXN5bmMgZnVuY3Rpb24gY2xpY2sgKGVsKSB7XG4gIGlmICghdGhpcy5pc1dlYkNvbnRleHQoKSkge1xuICAgIC8vIHRoZXJlIGFyZSBtdWx0aXBsZSBjb21tYW5kcyB0aGF0IG1hcCBoZXJlLCBzbyBtYW51YWxseSBwcm94eVxuICAgIHJldHVybiBhd2FpdCB0aGlzLm5hdGl2ZUNsaWNrKGVsKTtcbiAgfVxuICBlbCA9IHV0aWwudW53cmFwRWxlbWVudChlbCk7XG4gIGlmICgoYXdhaXQgdGhpcy5zZXR0aW5ncy5nZXRTZXR0aW5ncygpKS5uYXRpdmVXZWJUYXAgfHwgKGF3YWl0IHRoaXMuc2V0dGluZ3MuZ2V0U2V0dGluZ3MoKSkubmF0aXZlV2ViVGFwU3RyaWN0KSB7XG4gICAgLy8gYXRvbXMtYmFzZWQgY2xpY2tzIGRvbid0IGFsd2F5cyB3b3JrIGluIHNhZmFyaSA3XG4gICAgbG9nLmRlYnVnKCdVc2luZyBuYXRpdmUgd2ViIHRhcCcpO1xuICAgIGF3YWl0IHRoaXMubmF0aXZlV2ViVGFwKGVsKTtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBhdG9tc0VsZW1lbnQgPSB0aGlzLnVzZUF0b21zRWxlbWVudChlbCk7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuZXhlY3V0ZUF0b20oJ2NsaWNrJywgW2F0b21zRWxlbWVudF0pO1xuICB9XG59O1xuXG5mdW5jdGlvbiBnZXN0dXJlc0NoYWluVG9TdHJpbmcgKGdlc3R1cmVzLCBrZXlzVG9JbmNsdWRlID0gWydvcHRpb25zJ10pIHtcbiAgcmV0dXJuIGdlc3R1cmVzLm1hcCgoaXRlbSkgPT4ge1xuICAgIGxldCBvdGhlcktleXMgPSBfLmRpZmZlcmVuY2UoXy5rZXlzKGl0ZW0pLCBbJ2FjdGlvbiddKTtcbiAgICBvdGhlcktleXMgPSBfLmlzQXJyYXkoa2V5c1RvSW5jbHVkZSkgPyBfLmludGVyc2VjdGlvbihvdGhlcktleXMsIGtleXNUb0luY2x1ZGUpIDogb3RoZXJLZXlzO1xuICAgIGlmIChvdGhlcktleXMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gYCR7aXRlbS5hY3Rpb259YCArXG4gICAgICAgIGAoJHtfLm1hcChvdGhlcktleXMsICh4KSA9PiB4ICsgJz0nICsgKF8uaXNQbGFpbk9iamVjdChpdGVtW3hdKSA/IEpTT04uc3RyaW5naWZ5KGl0ZW1beF0pIDogaXRlbVt4XSkpLmpvaW4oJywgJyl9KWA7XG4gICAgfVxuICAgIHJldHVybiBpdGVtLmFjdGlvbjtcbiAgfSkuam9pbignLScpO1xufVxuXG5jb21tYW5kcy5wZXJmb3JtQWN0aW9ucyA9IGFzeW5jIGZ1bmN0aW9uIHBlcmZvcm1BY3Rpb25zIChhY3Rpb25zKSB7XG4gIGxvZy5kZWJ1ZyhgUmVjZWl2ZWQgdGhlIGZvbGxvd2luZyBXM0MgYWN0aW9uczogJHtKU09OLnN0cmluZ2lmeShhY3Rpb25zLCBudWxsLCAnICAnKX1gKTtcbiAgLy8gVGhpcyBpcyBtYW5kYXRvcnksIHNpbmNlIFdEQSBvbmx5IHN1cHBvcnRzIFRPVUNIIHBvaW50ZXIgdHlwZVxuICAvLyBhbmQgU2VsZW5pdW0gQVBJIHVzZXMgTU9VU0UgYXMgdGhlIGRlZmF1bHQgb25lXG4gIGNvbnN0IHByZXByb2Nlc3NlZEFjdGlvbnMgPSBhY3Rpb25zXG4gICAgLm1hcCgoYWN0aW9uKSA9PiBPYmplY3QuYXNzaWduKHt9LCBhY3Rpb24sIGFjdGlvbi50eXBlID09PSAncG9pbnRlcicgPyB7XG4gICAgICBwYXJhbWV0ZXJzOiB7XG4gICAgICAgIHBvaW50ZXJUeXBlOiAndG91Y2gnXG4gICAgICB9XG4gICAgfSA6IHt9KSlcbiAgICAubWFwKChhY3Rpb24pID0+IHtcbiAgICAgIGNvbnN0IG1vZGlmaWVkQWN0aW9uID0gXy5jbG9uZShhY3Rpb24pIHx8IHt9O1xuICAgICAgLy8gU2VsZW5pdW0gQVBJIHVuZXhwZWN0ZWRseSBpbnNlcnRzIHplcm8gcGF1c2VzLCB3aGljaCBhcmUgbm90IHN1cHBvcnRlZCBieSBXREFcbiAgICAgIG1vZGlmaWVkQWN0aW9uLmFjdGlvbnMgPSAoYWN0aW9uLmFjdGlvbnMgfHwgW10pXG4gICAgICAgIC5maWx0ZXIoKGlubmVyQWN0aW9uKSA9PiAhKGlubmVyQWN0aW9uLnR5cGUgPT09ICdwYXVzZScgJiYgaW5uZXJBY3Rpb24uZHVyYXRpb24gPT09IDApKTtcbiAgICAgIHJldHVybiBtb2RpZmllZEFjdGlvbjtcbiAgICB9KTtcbiAgbG9nLmRlYnVnKGBQcmVwcm9jZXNzZWQgYWN0aW9uczogJHtKU09OLnN0cmluZ2lmeShwcmVwcm9jZXNzZWRBY3Rpb25zLCBudWxsLCAnICAnKX1gKTtcbiAgcmV0dXJuIGF3YWl0IHRoaXMucHJveHlDb21tYW5kKCcvYWN0aW9ucycsICdQT1NUJywge2FjdGlvbnM6IHByZXByb2Nlc3NlZEFjdGlvbnN9KTtcbn07XG5cbmNvbW1hbmRzLnBlcmZvcm1Ub3VjaCA9IGFzeW5jIGZ1bmN0aW9uIHBlcmZvcm1Ub3VjaCAoZ2VzdHVyZXMpIHtcbiAgbG9nLmRlYnVnKGBSZWNlaXZlZCB0aGUgZm9sbG93aW5nIHRvdWNoIGFjdGlvbjogJHtnZXN0dXJlc0NoYWluVG9TdHJpbmcoZ2VzdHVyZXMpfWApO1xuICB0cnkge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLnByb3h5Q29tbWFuZCgnL3dkYS90b3VjaC9wZXJmb3JtJywgJ1BPU1QnLCB7YWN0aW9uczogZ2VzdHVyZXN9KTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGlmICghdGhpcy5pc1dlYkNvbnRleHQoKSkge1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gICAgbG9nLmVycm9yQW5kVGhyb3coJ1RoZSBUb3VjaCBBUEkgaXMgYWltZWQgZm9yIHVzYWdlIGluIE5BVElWRSBjb250ZXh0LiAnICtcbiAgICAgICdDb25zaWRlciB1c2luZyBcImV4ZWN1dGVcIiBBUEkgd2l0aCBjdXN0b20gZXZlbnRzIHRyaWdnZXIgc2NyaXB0ICcgK1xuICAgICAgYHRvIGVtdWxhdGUgdG91Y2ggZXZlbnRzIGJlaW5nIGluIFdFQlZJRVcgY29udGV4dC4gT3JpZ2luYWwgZXJyb3I6ICR7ZS5tZXNzYWdlfWApO1xuICB9XG59O1xuXG5jb21tYW5kcy5wZXJmb3JtTXVsdGlBY3Rpb24gPSBhc3luYyBmdW5jdGlvbiBwZXJmb3JtTXVsdGlBY3Rpb24gKGFjdGlvbnMpIHtcbiAgbG9nLmRlYnVnKGBSZWNlaXZlZCB0aGUgZm9sbG93aW5nIG11bHRpIHRvdWNoIGFjdGlvbjpgKTtcbiAgZm9yIChsZXQgaSBpbiBhY3Rpb25zKSB7XG4gICAgbG9nLmRlYnVnKGAgICAgJHtwYXJzZUludChpLCAxMCkgKyAxfTogJHtfLm1hcChhY3Rpb25zW2ldLCAnYWN0aW9uJykuam9pbignLScpfWApO1xuICB9XG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMucHJveHlDb21tYW5kKCcvd2RhL3RvdWNoL211bHRpL3BlcmZvcm0nLCAnUE9TVCcsIHthY3Rpb25zfSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoIXRoaXMuaXNXZWJDb250ZXh0KCkpIHtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuICAgIGxvZy5lcnJvckFuZFRocm93KCdUaGUgTXVsdGlUb3VjaCBBUEkgaXMgYWltZWQgZm9yIHVzYWdlIGluIE5BVElWRSBjb250ZXh0LiAnICtcbiAgICAgICdDb25zaWRlciB1c2luZyBcImV4ZWN1dGVcIiBBUEkgd2l0aCBjdXN0b20gZXZlbnRzIHRyaWdnZXIgc2NyaXB0ICcgK1xuICAgICAgYHRvIGVtdWxhdGUgbXVsdGl0b3VjaCBldmVudHMgYmVpbmcgaW4gV0VCVklFVyBjb250ZXh0LiBPcmlnaW5hbCBlcnJvcjogJHtlLm1lc3NhZ2V9YCk7XG4gIH1cbn07XG5cbmNvbW1hbmRzLm5hdGl2ZUNsaWNrID0gYXN5bmMgZnVuY3Rpb24gbmF0aXZlQ2xpY2sgKGVsKSB7XG4gIGVsID0gdXRpbC51bndyYXBFbGVtZW50KGVsKTtcbiAgbGV0IGVuZHBvaW50ID0gYC9lbGVtZW50LyR7ZWx9L2NsaWNrYDtcbiAgcmV0dXJuIGF3YWl0IHRoaXMucHJveHlDb21tYW5kKGVuZHBvaW50LCAnUE9TVCcsIHt9KTtcbn07XG5cbi8qXG4gKiBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2ZhY2Vib29rL1dlYkRyaXZlckFnZW50L2Jsb2IvbWFzdGVyL1dlYkRyaXZlckFnZW50TGliL0NvbW1hbmRzL0ZCRWxlbWVudENvbW1hbmRzLm1cbiAqIHRvIGdldCB0aGUgaW5mbyBhYm91dCBhdmFpbGFibGUgV0RBIGdlc3R1cmVzIEFQSVxuICpcbiAqIFNlZSBodHRwczovL2RldmVsb3Blci5hcHBsZS5jb20vcmVmZXJlbmNlL3hjdGVzdC94Y3VpZWxlbWVudCBhbmRcbiAqIGh0dHBzOi8vZGV2ZWxvcGVyLmFwcGxlLmNvbS9yZWZlcmVuY2UveGN0ZXN0L3hjdWljb29yZGluYXRlIHRvIGdldCB0aGUgZGV0YWlsZWQgZGVzY3JpcHRpb24gb2ZcbiAqIGFsbCBYQ1Rlc3QgZ2VzdHVyZXNcbiovXG5cbmhlbHBlcnMubW9iaWxlU2Nyb2xsID0gYXN5bmMgZnVuY3Rpb24gbW9iaWxlU2Nyb2xsIChvcHRzID0ge30sIHN3aXBlID0gZmFsc2UpIHtcbiAgaWYgKCFvcHRzLmVsZW1lbnQpIHtcbiAgICBvcHRzLmVsZW1lbnQgPSBhd2FpdCB0aGlzLmZpbmROYXRpdmVFbGVtZW50T3JFbGVtZW50cyhgY2xhc3MgbmFtZWAsIGBYQ1VJRWxlbWVudFR5cGVBcHBsaWNhdGlvbmAsIGZhbHNlKTtcbiAgfVxuICAvLyBXREEgc3VwcG9ydHMgZm91ciBzY3JvbGxpbmcgc3RyYXRlZ2llczogcHJlZGljYXRpb24gYmFzZWQgb24gbmFtZSwgZGlyZWN0aW9uLFxuICAvLyBwcmVkaWNhdGVTdHJpbmcsIGFuZCB0b1Zpc2libGUsIGluIHRoYXQgb3JkZXIuIFN3aXBpbmcgcmVxdWlyZXMgZGlyZWN0aW9uLlxuICBsZXQgcGFyYW1zID0ge307XG4gIGlmIChvcHRzLm5hbWUgJiYgIXN3aXBlKSB7XG4gICAgcGFyYW1zLm5hbWUgPSBvcHRzLm5hbWU7XG4gIH0gZWxzZSBpZiAob3B0cy5kaXJlY3Rpb24pIHtcbiAgICBpZiAoIVsndXAnLCAnZG93bicsICdsZWZ0JywgJ3JpZ2h0J10uaW5jbHVkZXMob3B0cy5kaXJlY3Rpb24udG9Mb3dlckNhc2UoKSkpIHtcbiAgICAgIGxldCBtc2cgPSAnRGlyZWN0aW9uIG11c3QgYmUgdXAsIGRvd24sIGxlZnQgb3IgcmlnaHQnO1xuICAgICAgbG9nLmVycm9yQW5kVGhyb3cobXNnKTtcbiAgICB9XG4gICAgcGFyYW1zLmRpcmVjdGlvbiA9IG9wdHMuZGlyZWN0aW9uO1xuICB9IGVsc2UgaWYgKG9wdHMucHJlZGljYXRlU3RyaW5nICYmICFzd2lwZSkge1xuICAgIHBhcmFtcy5wcmVkaWNhdGVTdHJpbmcgPSBvcHRzLnByZWRpY2F0ZVN0cmluZztcbiAgfSBlbHNlIGlmIChvcHRzLnRvVmlzaWJsZSAmJiAhc3dpcGUpIHtcbiAgICBwYXJhbXMudG9WaXNpYmxlID0gb3B0cy50b1Zpc2libGU7XG4gIH0gZWxzZSB7XG4gICAgbGV0IG1zZyA9IHN3aXBlXG4gICAgICA/ICdNb2JpbGUgc3dpcGUgcmVxdWlyZXMgZGlyZWN0aW9uJ1xuICAgICAgOiAnTW9iaWxlIHNjcm9sbCBzdXBwb3J0cyB0aGUgZm9sbG93aW5nIHN0cmF0ZWdpZXM6IG5hbWUsIGRpcmVjdGlvbiwgcHJlZGljYXRlU3RyaW5nLCBhbmQgdG9WaXNpYmxlLiBTcGVjaWZ5IG9uZSBvZiB0aGVzZSc7XG4gICAgbG9nLmVycm9yQW5kVGhyb3cobXNnKTtcbiAgfVxuXG4gIC8vIHdlIGNhbiBhbHNvIG9wdGlvbmFsbHkgcGFzcyBhIGRpc3RhbmNlIHdoaWNoIGFwcGVhcnMgdG8gYmUgYSByYXRpbyBvZlxuICAvLyBzY3JlZW4gaGVpZ2h0LCBzbyAxLjAgbWVhbnMgYSBmdWxsIHNjcmVlbidzIHdvcnRoIG9mIHNjcm9sbGluZ1xuICBpZiAoIXN3aXBlICYmIG9wdHMuZGlzdGFuY2UpIHtcbiAgICBwYXJhbXMuZGlzdGFuY2UgPSBvcHRzLmRpc3RhbmNlO1xuICB9XG5cbiAgbGV0IGVsZW1lbnQgPSB1dGlsLnVud3JhcEVsZW1lbnQob3B0cy5lbGVtZW50KTtcbiAgbGV0IGVuZHBvaW50ID0gYC93ZGEvZWxlbWVudC8ke2VsZW1lbnR9LyR7c3dpcGUgPyAnc3dpcGUnIDogJ3Njcm9sbCd9YDtcbiAgcmV0dXJuIGF3YWl0IHRoaXMucHJveHlDb21tYW5kKGVuZHBvaW50LCAnUE9TVCcsIHBhcmFtcyk7XG59O1xuXG5oZWxwZXJzLm1vYmlsZVN3aXBlID0gYXN5bmMgZnVuY3Rpb24gbW9iaWxlU3dpcGUgKG9wdHMgPSB7fSkge1xuICByZXR1cm4gYXdhaXQgdGhpcy5tb2JpbGVTY3JvbGwob3B0cywgdHJ1ZSk7XG59O1xuXG5oZWxwZXJzLm1vYmlsZVBpbmNoID0gYXN5bmMgZnVuY3Rpb24gbW9iaWxlUGluY2ggKG9wdHMgPSB7fSkge1xuICBpZiAoIW9wdHMuZWxlbWVudCkge1xuICAgIG9wdHMuZWxlbWVudCA9IGF3YWl0IHRoaXMuZmluZE5hdGl2ZUVsZW1lbnRPckVsZW1lbnRzKGBjbGFzcyBuYW1lYCwgYFhDVUlFbGVtZW50VHlwZUFwcGxpY2F0aW9uYCwgZmFsc2UpO1xuICB9XG4gIGNvbnN0IHBhcmFtcyA9IHtcbiAgICBzY2FsZTogcmVxdWlyZUZsb2F0UGFyYW1ldGVyKCdzY2FsZScsIG9wdHMuc2NhbGUsICdwaW5jaCcpLFxuICAgIHZlbG9jaXR5OiByZXF1aXJlRmxvYXRQYXJhbWV0ZXIoJ3ZlbG9jaXR5Jywgb3B0cy52ZWxvY2l0eSwgJ3BpbmNoJylcbiAgfTtcbiAgY29uc3QgZWwgPSB1dGlsLnVud3JhcEVsZW1lbnQob3B0cy5lbGVtZW50KTtcbiAgcmV0dXJuIGF3YWl0IHRoaXMucHJveHlDb21tYW5kKGAvd2RhL2VsZW1lbnQvJHtlbH0vcGluY2hgLCAnUE9TVCcsIHBhcmFtcyk7XG59O1xuXG5oZWxwZXJzLm1vYmlsZURvdWJsZVRhcCA9IGFzeW5jIGZ1bmN0aW9uIG1vYmlsZURvdWJsZVRhcCAob3B0cyA9IHt9KSB7XG4gIGlmIChvcHRzLmVsZW1lbnQpIHtcbiAgICAvLyBEb3VibGUgdGFwIGVsZW1lbnRcbiAgICBjb25zdCBlbCA9IHV0aWwudW53cmFwRWxlbWVudChvcHRzLmVsZW1lbnQpO1xuICAgIHJldHVybiBhd2FpdCB0aGlzLnByb3h5Q29tbWFuZChgL3dkYS9lbGVtZW50LyR7ZWx9L2RvdWJsZVRhcGAsICdQT1NUJyk7XG4gIH1cbiAgLy8gRG91YmxlIHRhcCBjb29yZGluYXRlc1xuICBjb25zdCBwYXJhbXMgPSB7XG4gICAgeDogcmVxdWlyZUZsb2F0UGFyYW1ldGVyKCd4Jywgb3B0cy54LCAnZG91YmxlVGFwJyksXG4gICAgeTogcmVxdWlyZUZsb2F0UGFyYW1ldGVyKCd5Jywgb3B0cy55LCAnZG91YmxlVGFwJylcbiAgfTtcbiAgcmV0dXJuIGF3YWl0IHRoaXMucHJveHlDb21tYW5kKCcvd2RhL2RvdWJsZVRhcCcsICdQT1NUJywgcGFyYW1zKTtcbn07XG5cbmhlbHBlcnMubW9iaWxlVHdvRmluZ2VyVGFwID0gYXN5bmMgZnVuY3Rpb24gbW9iaWxlVHdvRmluZ2VyVGFwIChvcHRzID0ge30pIHtcbiAgaWYgKCFvcHRzLmVsZW1lbnQpIHtcbiAgICBvcHRzLmVsZW1lbnQgPSBhd2FpdCB0aGlzLmZpbmROYXRpdmVFbGVtZW50T3JFbGVtZW50cyhgY2xhc3MgbmFtZWAsIGBYQ1VJRWxlbWVudFR5cGVBcHBsaWNhdGlvbmAsIGZhbHNlKTtcbiAgfVxuICBjb25zdCBlbCA9IHV0aWwudW53cmFwRWxlbWVudChvcHRzLmVsZW1lbnQpO1xuICByZXR1cm4gYXdhaXQgdGhpcy5wcm94eUNvbW1hbmQoYC93ZGEvZWxlbWVudC8ke2VsfS90d29GaW5nZXJUYXBgLCAnUE9TVCcpO1xufTtcblxuaGVscGVycy5tb2JpbGVUb3VjaEFuZEhvbGQgPSBhc3luYyBmdW5jdGlvbiBtb2JpbGVUb3VjaEFuZEhvbGQgKG9wdHMgPSB7fSkge1xuICBsZXQgcGFyYW1zID0ge1xuICAgIGR1cmF0aW9uOiByZXF1aXJlRmxvYXRQYXJhbWV0ZXIoJ2R1cmF0aW9uJywgb3B0cy5kdXJhdGlvbiwgJ3RvdWNoQW5kSG9sZCcpXG4gIH07XG4gIGlmIChvcHRzLmVsZW1lbnQpIHtcbiAgICAvLyBMb25nIHRhcCBlbGVtZW50XG4gICAgY29uc3QgZWwgPSB1dGlsLnVud3JhcEVsZW1lbnQob3B0cy5lbGVtZW50KTtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5wcm94eUNvbW1hbmQoYC93ZGEvZWxlbWVudC8ke2VsfS90b3VjaEFuZEhvbGRgLCAnUE9TVCcsIHBhcmFtcyk7XG4gIH1cbiAgLy8gTG9uZyB0YXAgY29vcmRpbmF0ZXNcbiAgcGFyYW1zLnggPSByZXF1aXJlRmxvYXRQYXJhbWV0ZXIoJ3gnLCBvcHRzLngsICd0b3VjaEFuZEhvbGQnKTtcbiAgcGFyYW1zLnkgPSByZXF1aXJlRmxvYXRQYXJhbWV0ZXIoJ3knLCBvcHRzLnksICd0b3VjaEFuZEhvbGQnKTtcbiAgcmV0dXJuIGF3YWl0IHRoaXMucHJveHlDb21tYW5kKCcvd2RhL3RvdWNoQW5kSG9sZCcsICdQT1NUJywgcGFyYW1zKTtcbn07XG5cbmhlbHBlcnMubW9iaWxlVGFwID0gYXN5bmMgZnVuY3Rpb24gbW9iaWxlVGFwIChvcHRzID0ge30pIHtcbiAgY29uc3QgcGFyYW1zID0ge1xuICAgIHg6IHJlcXVpcmVGbG9hdFBhcmFtZXRlcigneCcsIG9wdHMueCwgJ3RhcCcpLFxuICAgIHk6IHJlcXVpcmVGbG9hdFBhcmFtZXRlcigneScsIG9wdHMueSwgJ3RhcCcpXG4gIH07XG4gIGNvbnN0IGVsID0gb3B0cy5lbGVtZW50ID8gKHV0aWwudW53cmFwRWxlbWVudChvcHRzLmVsZW1lbnQpKSA6ICcwJztcbiAgcmV0dXJuIGF3YWl0IHRoaXMucHJveHlDb21tYW5kKGAvd2RhL3RhcC8ke2VsfWAsICdQT1NUJywgcGFyYW1zKTtcbn07XG5cbmhlbHBlcnMubW9iaWxlRHJhZ0Zyb21Ub0ZvckR1cmF0aW9uID0gYXN5bmMgZnVuY3Rpb24gbW9iaWxlRHJhZ0Zyb21Ub0ZvckR1cmF0aW9uIChvcHRzID0ge30pIHtcbiAgY29uc3QgcGFyYW1zID0ge1xuICAgIGR1cmF0aW9uOiByZXF1aXJlRmxvYXRQYXJhbWV0ZXIoJ2R1cmF0aW9uJywgb3B0cy5kdXJhdGlvbiwgJ2RyYWdGcm9tVG9Gb3JEdXJhdGlvbicpLFxuICAgIGZyb21YOiByZXF1aXJlRmxvYXRQYXJhbWV0ZXIoJ2Zyb21YJywgb3B0cy5mcm9tWCwgJ2RyYWdGcm9tVG9Gb3JEdXJhdGlvbicpLFxuICAgIGZyb21ZOiByZXF1aXJlRmxvYXRQYXJhbWV0ZXIoJ2Zyb21ZJywgb3B0cy5mcm9tWSwgJ2RyYWdGcm9tVG9Gb3JEdXJhdGlvbicpLFxuICAgIHRvWDogcmVxdWlyZUZsb2F0UGFyYW1ldGVyKCd0b1gnLCBvcHRzLnRvWCwgJ2RyYWdGcm9tVG9Gb3JEdXJhdGlvbicpLFxuICAgIHRvWTogcmVxdWlyZUZsb2F0UGFyYW1ldGVyKCd0b1knLCBvcHRzLnRvWSwgJ2RyYWdGcm9tVG9Gb3JEdXJhdGlvbicpXG4gIH07XG4gIGlmIChvcHRzLmVsZW1lbnQpIHtcbiAgICAvLyBEcmFnIGVsZW1lbnRcbiAgICBjb25zdCBlbCA9IHV0aWwudW53cmFwRWxlbWVudChvcHRzLmVsZW1lbnQpO1xuICAgIHJldHVybiBhd2FpdCB0aGlzLnByb3h5Q29tbWFuZChgL3dkYS9lbGVtZW50LyR7ZWx9L2RyYWdmcm9tdG9mb3JkdXJhdGlvbmAsICdQT1NUJywgcGFyYW1zKTtcbiAgfVxuICAvLyBEcmFnIGNvb3JkaW5hdGVzXG4gIHJldHVybiBhd2FpdCB0aGlzLnByb3h5Q29tbWFuZCgnL3dkYS9kcmFnZnJvbXRvZm9yZHVyYXRpb24nLCAnUE9TVCcsIHBhcmFtcyk7XG59O1xuXG5oZWxwZXJzLm1vYmlsZVRhcFdpdGhOdW1iZXJPZlRhcHMgPSBhc3luYyBmdW5jdGlvbiBtb2JpbGVUYXBXaXRoTnVtYmVyT2ZUYXBzIChvcHRzID0ge30pIHtcbiAgaWYgKCFvcHRzLmVsZW1lbnQpIHtcbiAgICBsb2cuZXJyb3JBbmRUaHJvdygnRWxlbWVudCBpZCBpcyBleHBlY3RlZCB0byBiZSBzZXQgZm9yIHRhcFdpdGhOdW1iZXJPZlRhcHMgbWV0aG9kJyk7XG4gIH1cbiAgY29uc3QgcGFyYW1zID0ge1xuICAgIG51bWJlck9mVGFwczogcmVxdWlyZUludFBhcmFtZXRlcignbnVtYmVyT2ZUYXBzJywgb3B0cy5udW1iZXJPZlRhcHMsICd0YXBXaXRoTnVtYmVyT2ZUYXBzJyksXG4gICAgbnVtYmVyT2ZUb3VjaGVzOiByZXF1aXJlSW50UGFyYW1ldGVyKCdudW1iZXJPZlRvdWNoZXMnLCBvcHRzLm51bWJlck9mVG91Y2hlcywgJ3RhcFdpdGhOdW1iZXJPZlRhcHMnKSxcbiAgfTtcbiAgY29uc3QgZWwgPSB1dGlsLnVud3JhcEVsZW1lbnQob3B0cy5lbGVtZW50KTtcbiAgcmV0dXJuIGF3YWl0IHRoaXMucHJveHlDb21tYW5kKGAvd2RhL2VsZW1lbnQvJHtlbH0vdGFwV2l0aE51bWJlck9mVGFwc2AsICdQT1NUJywgcGFyYW1zKTtcbn07XG5cbmhlbHBlcnMubW9iaWxlU2VsZWN0UGlja2VyV2hlZWxWYWx1ZSA9IGFzeW5jIGZ1bmN0aW9uIG1vYmlsZVNlbGVjdFBpY2tlcldoZWVsVmFsdWUgKG9wdHMgPSB7fSkge1xuICBpZiAoIW9wdHMuZWxlbWVudCkge1xuICAgIGxvZy5lcnJvckFuZFRocm93KCdFbGVtZW50IGlkIGlzIGV4cGVjdGVkIHRvIGJlIHNldCBmb3Igc2VsZWN0UGlja2VyV2hlZWxWYWx1ZSBtZXRob2QnKTtcbiAgfVxuICBpZiAoIV8uaXNTdHJpbmcob3B0cy5vcmRlcikgfHwgIVsnbmV4dCcsICdwcmV2aW91cyddLmluY2x1ZGVzKG9wdHMub3JkZXIudG9Mb3dlckNhc2UoKSkpIHtcbiAgICBsb2cuZXJyb3JBbmRUaHJvdyhgVGhlIG1hbmRhdG9yeSAnb3JkZXInIHBhcmFtZXRlciBpcyBleHBlY3RlZCB0byBiZSBlcXVhbCBlaXRoZXIgdG8gJ25leHQnIG9yICdwcmV2aW91cycuIGAgK1xuICAgICAgICAgICAgICAgICAgICAgIGAnJHtvcHRzLm9yZGVyfScgaXMgZ2l2ZW4gaW5zdGVhZGApO1xuICB9XG4gIGNvbnN0IGVsID0gdXRpbC51bndyYXBFbGVtZW50KG9wdHMuZWxlbWVudCk7XG4gIGNvbnN0IHBhcmFtcyA9IHtvcmRlcjogb3B0cy5vcmRlcn07XG4gIGlmIChvcHRzLm9mZnNldCkge1xuICAgIHBhcmFtcy5vZmZzZXQgPSByZXF1aXJlRmxvYXRQYXJhbWV0ZXIoJ29mZnNldCcsIG9wdHMub2Zmc2V0LCAnc2VsZWN0UGlja2VyV2hlZWxWYWx1ZScpO1xuICB9XG4gIHJldHVybiBhd2FpdCB0aGlzLnByb3h5Q29tbWFuZChgL3dkYS9waWNrZXJ3aGVlbC8ke2VsfS9zZWxlY3RgLCAnUE9TVCcsIHBhcmFtcyk7XG59O1xuXG5oZWxwZXJzLm1vYmlsZVJvdGF0ZUVsZW1lbnQgPSBhc3luYyBmdW5jdGlvbiBtb2JpbGVSb3RhdGVFbGVtZW50IChvcHRzID0ge30pIHtcbiAgaWYgKCFvcHRzLmVsZW1lbnQpIHtcbiAgICBsb2cuZXJyb3JBbmRUaHJvdygnRWxlbWVudCBpZCBpcyBleHBlY3RlZCB0byBiZSBzZXQgZm9yIHJvdGF0ZUVsZW1lbnQgbWV0aG9kJyk7XG4gIH1cbiAgY29uc3QgZWwgPSB1dGlsLnVud3JhcEVsZW1lbnQob3B0cy5lbGVtZW50KTtcbiAgY29uc3QgcGFyYW1zID0ge1xuICAgIHJvdGF0aW9uOiByZXF1aXJlRmxvYXRQYXJhbWV0ZXIoJ3JvdGF0aW9uJywgb3B0cy5yb3RhdGlvbiwgJ3JvdGF0ZUVsZW1lbnQnKSxcbiAgICB2ZWxvY2l0eTogcmVxdWlyZUZsb2F0UGFyYW1ldGVyKCd2ZWxvY2l0eScsIG9wdHMudmVsb2NpdHksICdyb3RhdGVFbGVtZW50JyksXG4gIH07XG4gIHJldHVybiBhd2FpdCB0aGlzLnByb3h5Q29tbWFuZChgL3dkYS9lbGVtZW50LyR7ZWx9L3JvdGF0ZWAsICdQT1NUJywgcGFyYW1zKTtcbn07XG5cbmhlbHBlcnMuZ2V0Q29vcmRpbmF0ZXMgPSBhc3luYyBmdW5jdGlvbiBnZXRDb29yZGluYXRlcyAoZ2VzdHVyZSkge1xuICBsZXQgZWwgPSBnZXN0dXJlLm9wdGlvbnMuZWxlbWVudDtcblxuICAvLyBkZWZhdWx0c1xuICBsZXQgY29vcmRpbmF0ZXMgPSB7eDogMCwgeTogMCwgYXJlT2Zmc2V0czogZmFsc2V9O1xuXG4gIGxldCBvcHRpb25YID0gbnVsbDtcbiAgaWYgKGdlc3R1cmUub3B0aW9ucy54KSB7XG4gICAgb3B0aW9uWCA9IHJlcXVpcmVGbG9hdFBhcmFtZXRlcigneCcsIGdlc3R1cmUub3B0aW9ucy54LCAnZ2V0Q29vcmRpbmF0ZXMnKTtcbiAgfVxuICBsZXQgb3B0aW9uWSA9IG51bGw7XG4gIGlmIChnZXN0dXJlLm9wdGlvbnMueSkge1xuICAgIG9wdGlvblkgPSByZXF1aXJlRmxvYXRQYXJhbWV0ZXIoJ3knLCBnZXN0dXJlLm9wdGlvbnMueSwgJ2dldENvb3JkaW5hdGVzJyk7XG4gIH1cblxuICAvLyBmaWd1cmUgb3V0IHRoZSBlbGVtZW50IGNvb3JkaW5hdGVzLlxuICBpZiAoZWwpIHtcbiAgICBsZXQgcmVjdCA9IGF3YWl0IHRoaXMuZ2V0RWxlbWVudFJlY3QoZWwpO1xuICAgIGxldCBwb3MgPSB7eDogcmVjdC54LCB5OiByZWN0Lnl9O1xuICAgIGxldCBzaXplID0ge3c6IHJlY3Qud2lkdGgsIGg6IHJlY3QuaGVpZ2h0fTtcblxuICAgIC8vIGRlZmF1bHRzXG4gICAgbGV0IG9mZnNldFggPSAwO1xuICAgIGxldCBvZmZzZXRZID0gMDtcblxuICAgIC8vIGdldCB0aGUgcmVhbCBvZmZzZXRzXG4gICAgaWYgKG9wdGlvblggfHwgb3B0aW9uWSkge1xuICAgICAgb2Zmc2V0WCA9IChvcHRpb25YIHx8IDApO1xuICAgICAgb2Zmc2V0WSA9IChvcHRpb25ZIHx8IDApO1xuICAgIH0gZWxzZSB7XG4gICAgICBvZmZzZXRYID0gKHNpemUudyAvIDIpO1xuICAgIC