UNPKG

appium-doctor

Version:

Test environment for fitness to run Appium

299 lines (217 loc) 29.8 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.fixes = exports.default = exports.XcodeCmdLineToolsCheck = exports.XcodeCheck = exports.OptionalLyftCommandCheck = exports.OptionalIdbCommandCheck = exports.OptionalIOSDeployCommandCheck = exports.OptionalApplesimutilsCommandCheck = exports.DevToolsSecurityCheck = exports.CarthageCheck = exports.AuthorizationDbCheck = void 0; require("source-map-support/register"); var _utils = require("./utils"); var _appiumSupport = require("appium-support"); var _teen_process = require("teen_process"); var _doctor = require("./doctor"); var _logger = _interopRequireDefault(require("./logger")); var _carthageDetector = _interopRequireDefault(require("./carthage-detector")); var _prompt = require("./prompt"); var _env = _interopRequireDefault(require("./env")); var _lodash = _interopRequireDefault(require("lodash")); require("@colors/colors"); let checks = []; let fixes = {}; exports.fixes = fixes; class XcodeCheck extends _doctor.DoctorCheck { async diagnose() { let xcodePath; try { await (0, _teen_process.exec)('xcrun', ['simctl', 'help']); } catch (err) { return (0, _utils.nok)('Error running xcrun simctl'); } try { const { stdout } = await (0, _teen_process.exec)('xcode-select', ['-p']); xcodePath = (stdout || '').replace('\n', ''); } catch (err) { return (0, _utils.nok)('Xcode is NOT installed!'); } return xcodePath && (await _appiumSupport.fs.exists(xcodePath)) ? (0, _utils.ok)(`Xcode is installed at: ${xcodePath}`) : (0, _utils.nok)(`Xcode cannot be found at '${xcodePath}'!`); } async fix() { return `Manually install ${'Xcode'.bold}, and make sure 'xcode-select -p' command shows proper path like '/Applications/Xcode.app/Contents/Developer'`; } } exports.XcodeCheck = XcodeCheck; checks.push(new XcodeCheck()); class XcodeCmdLineToolsCheck extends _doctor.DoctorCheck { constructor() { super({ autofix: true }); } async diagnose() { const errMess = 'Xcode Command Line Tools are NOT installed!'; try { const stdout = (await (0, _teen_process.exec)('xcode-select', ['-p'])).stdout; return (0, _utils.ok)(`Xcode Command Line Tools are installed in: ${stdout.trim()}`); } catch (err) { _logger.default.debug(err); return (0, _utils.nok)(errMess); } } async fix() { _logger.default.info(`The following command need be executed: xcode-select --install`); let yesno = await (0, _prompt.fixIt)(); if (yesno === 'yes') { await (0, _teen_process.exec)('xcode-select', ['--install']); } else { _logger.default.info(`Skipping you will need to install ${'Xcode'.bold} manually.`); throw new _doctor.FixSkippedError(); } } } exports.XcodeCmdLineToolsCheck = XcodeCmdLineToolsCheck; checks.push(new XcodeCmdLineToolsCheck()); fixes.authorizeIosFix = async function () { _logger.default.info(`The authorize iOS script need to be run.`); let yesno = await (0, _prompt.fixIt)(); if (yesno === 'yes') { await (0, _utils.authorizeIos)(); } else { _logger.default.info(`Skipping you will need to run ${'the authorize iOS'.bold} manually.`); throw new _doctor.FixSkippedError(); } }; class DevToolsSecurityCheck extends _doctor.DoctorCheck { constructor() { super({ autofix: true }); } async diagnose() { const errMess = 'DevToolsSecurity is NOT enabled!'; let stdout; try { stdout = (await (0, _teen_process.exec)('DevToolsSecurity', [])).stdout; } catch (err) { _logger.default.debug(err); return (0, _utils.nok)(errMess); } return stdout && stdout.match(/enabled/) ? (0, _utils.ok)('DevToolsSecurity is enabled.') : (0, _utils.nok)(errMess); } async fix() { return await fixes.authorizeIosFix(); } } exports.DevToolsSecurityCheck = DevToolsSecurityCheck; checks.push(new DevToolsSecurityCheck()); class AuthorizationDbCheck extends _doctor.DoctorCheck { constructor() { super({ autofix: true }); } async diagnose() { const successMess = 'The Authorization DB is set up properly.'; const errMess = 'The Authorization DB is NOT set up properly.'; let stdout; try { ({ stdout } = await (0, _teen_process.exec)('security', ['authorizationdb', 'read', 'system.privilege.taskport'])); } catch (err) { _logger.default.warn(err); return (0, _utils.nok)(errMess); } return stdout && (stdout.match(/is-developer/) || stdout.match(/allow/)) ? (0, _utils.ok)(successMess) : (0, _utils.nok)(errMess); } async fix() { return await fixes.authorizeIosFix(); } } exports.AuthorizationDbCheck = AuthorizationDbCheck; checks.push(new AuthorizationDbCheck()); class CarthageCheck extends _doctor.DoctorCheck { async diagnose() { let carthagePath = await _carthageDetector.default.detect(); let version; if (carthagePath) { try { const { stdout } = await (0, _teen_process.exec)(carthagePath, ['version']); version = _lodash.default.last(stdout.match(/(\d+\.\d+\.\d+)/g)); if (!_appiumSupport.util.coerceVersion(version, false)) { _logger.default.warn(`Cannot parse Carthage version from ${stdout}`); } } catch (err) { _logger.default.warn(err); } } return carthagePath ? (0, _utils.ok)(`Carthage was found at: ${carthagePath}${version ? `. Installed version is: ${version}` : ''}`) : (0, _utils.nok)(`Carthage was NOT found!`); } async fix() { return `${'[For lower than Appium 1.20.0]'.bold} Please install ${'Carthage'.bold}. Visit https://github.com/Carthage` + '/Carthage#installing-carthage for more information.'; } } exports.CarthageCheck = CarthageCheck; checks.push(new CarthageCheck()); checks.push(new _env.default('HOME')); class OptionalLyftCommandCheck extends _doctor.DoctorCheck { async diagnose() { const lyftCmd = await (0, _utils.resolveExecutablePath)('set-simulator-location'); if (lyftCmd) { return (0, _utils.okOptional)('set-simulator-location is installed'); } return (0, _utils.nokOptional)('set-simulator-location is not installed'); } async fix() { return `${'set-simulator-location'.bold} is needed to set location for Simulator. ` + 'Please read https://github.com/lyft/set-simulator-location to install it'; } } exports.OptionalLyftCommandCheck = OptionalLyftCommandCheck; checks.push(new OptionalLyftCommandCheck()); class OptionalIdbCommandCheck extends _doctor.DoctorCheck { async diagnose() { const fbIdbPath = await (0, _utils.resolveExecutablePath)('idb'); const fbCompanionIdbPath = await (0, _utils.resolveExecutablePath)('idb_companion'); if (fbIdbPath && fbCompanionIdbPath) { return (0, _utils.okOptional)('idb and idb_companion are installed'); } if (!fbIdbPath && fbCompanionIdbPath) { return (0, _utils.nokOptional)('idb is not installed'); } else if (fbIdbPath && !fbCompanionIdbPath) { return (0, _utils.nokOptional)('idb_companion is not installed'); } return (0, _utils.nokOptional)('idb and idb_companion are not installed'); } async fix() { return `Why ${'idb'.bold} is needed and how to install it: https://github.com/appium/appium-idb`; } } exports.OptionalIdbCommandCheck = OptionalIdbCommandCheck; checks.push(new OptionalIdbCommandCheck()); class OptionalApplesimutilsCommandCheck extends _doctor.DoctorCheck { async diagnose() { const applesimutilsPath = await (0, _utils.resolveExecutablePath)('applesimutils'); return applesimutilsPath ? (0, _utils.okOptional)(`applesimutils is installed at: ${applesimutilsPath}. Installed versions are: ${(await (0, _teen_process.exec)('brew', ['list', '--versions', 'applesimutils'])).stdout.trim()}`) : (0, _utils.nokOptional)('applesimutils cannot be found'); } async fix() { return `Why ${'applesimutils'.bold} is needed and how to install it: http://appium.io/docs/en/drivers/ios-xcuitest/`; } } exports.OptionalApplesimutilsCommandCheck = OptionalApplesimutilsCommandCheck; checks.push(new OptionalApplesimutilsCommandCheck()); class OptionalIOSDeployCommandCheck extends _doctor.DoctorCheck { async diagnose() { const iosDeployPath = await (0, _utils.resolveExecutablePath)('ios-deploy'); return iosDeployPath ? (0, _utils.okOptional)(`ios-deploy is installed at: ${iosDeployPath}. Installed version is: ${(await (0, _teen_process.exec)(iosDeployPath, ['-V'])).stdout.trim()}`) : (0, _utils.nokOptional)('ios-deploy cannot be found'); } async fix() { return `${'ios-deploy'.bold} is used as a fallback command to install iOS applications to real device. Please read https://github.com/ios-control/ios-deploy/ to install it`; } } exports.OptionalIOSDeployCommandCheck = OptionalIOSDeployCommandCheck; checks.push(new OptionalIOSDeployCommandCheck()); var _default = checks; exports.default = _default;require('source-map-support').install(); //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGliL2lvcy5qcyIsIm5hbWVzIjpbImNoZWNrcyIsImZpeGVzIiwiWGNvZGVDaGVjayIsIkRvY3RvckNoZWNrIiwiZGlhZ25vc2UiLCJ4Y29kZVBhdGgiLCJleGVjIiwiZXJyIiwibm9rIiwic3Rkb3V0IiwicmVwbGFjZSIsImZzIiwiZXhpc3RzIiwib2siLCJmaXgiLCJib2xkIiwicHVzaCIsIlhjb2RlQ21kTGluZVRvb2xzQ2hlY2siLCJjb25zdHJ1Y3RvciIsImF1dG9maXgiLCJlcnJNZXNzIiwidHJpbSIsImxvZyIsImRlYnVnIiwiaW5mbyIsInllc25vIiwiZml4SXQiLCJGaXhTa2lwcGVkRXJyb3IiLCJhdXRob3JpemVJb3NGaXgiLCJhdXRob3JpemVJb3MiLCJEZXZUb29sc1NlY3VyaXR5Q2hlY2siLCJtYXRjaCIsIkF1dGhvcml6YXRpb25EYkNoZWNrIiwic3VjY2Vzc01lc3MiLCJ3YXJuIiwiQ2FydGhhZ2VDaGVjayIsImNhcnRoYWdlUGF0aCIsIkNhcnRoYWdlRGV0ZWN0b3IiLCJkZXRlY3QiLCJ2ZXJzaW9uIiwiXyIsImxhc3QiLCJ1dGlsIiwiY29lcmNlVmVyc2lvbiIsIkVudlZhckFuZFBhdGhDaGVjayIsIk9wdGlvbmFsTHlmdENvbW1hbmRDaGVjayIsImx5ZnRDbWQiLCJyZXNvbHZlRXhlY3V0YWJsZVBhdGgiLCJva09wdGlvbmFsIiwibm9rT3B0aW9uYWwiLCJPcHRpb25hbElkYkNvbW1hbmRDaGVjayIsImZiSWRiUGF0aCIsImZiQ29tcGFuaW9uSWRiUGF0aCIsIk9wdGlvbmFsQXBwbGVzaW11dGlsc0NvbW1hbmRDaGVjayIsImFwcGxlc2ltdXRpbHNQYXRoIiwiT3B0aW9uYWxJT1NEZXBsb3lDb21tYW5kQ2hlY2siLCJpb3NEZXBsb3lQYXRoIl0sInNvdXJjZVJvb3QiOiIuLi8uLiIsInNvdXJjZXMiOlsibGliL2lvcy5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBvaywgbm9rLCBva09wdGlvbmFsLCBub2tPcHRpb25hbCwgYXV0aG9yaXplSW9zLCByZXNvbHZlRXhlY3V0YWJsZVBhdGggfSBmcm9tICcuL3V0aWxzJzsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuaW1wb3J0IHsgZnMsIHV0aWwgfSBmcm9tICdhcHBpdW0tc3VwcG9ydCc7XG5pbXBvcnQgeyBleGVjIH0gZnJvbSAndGVlbl9wcm9jZXNzJztcbmltcG9ydCB7IERvY3RvckNoZWNrLCBGaXhTa2lwcGVkRXJyb3IgfSBmcm9tICcuL2RvY3Rvcic7XG5pbXBvcnQgbG9nIGZyb20gJy4vbG9nZ2VyJztcbmltcG9ydCBDYXJ0aGFnZURldGVjdG9yIGZyb20gJy4vY2FydGhhZ2UtZGV0ZWN0b3InO1xuaW1wb3J0IHsgZml4SXQgfSBmcm9tICcuL3Byb21wdCc7XG5pbXBvcnQgRW52VmFyQW5kUGF0aENoZWNrIGZyb20gJy4vZW52JztcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgJ0Bjb2xvcnMvY29sb3JzJztcblxubGV0IGNoZWNrcyA9IFtdO1xubGV0IGZpeGVzID0ge307XG5cbi8vIENoZWNrIGZvciBYY29kZS5cbmNsYXNzIFhjb2RlQ2hlY2sgZXh0ZW5kcyBEb2N0b3JDaGVjayB7XG4gIGFzeW5jIGRpYWdub3NlICgpIHtcbiAgICBsZXQgeGNvZGVQYXRoO1xuICAgIHRyeSB7XG4gICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vYXBwaXVtL2FwcGl1bS9pc3N1ZXMvMTIwOTMjaXNzdWVjb21tZW50LTQ1OTM1ODEyMCBjYW4gaGFwcGVuXG4gICAgICBhd2FpdCBleGVjKCd4Y3J1bicsIFsnc2ltY3RsJywgJ2hlbHAnXSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICByZXR1cm4gbm9rKCdFcnJvciBydW5uaW5nIHhjcnVuIHNpbWN0bCcpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgY29uc3Qge3N0ZG91dH0gPSBhd2FpdCBleGVjKCd4Y29kZS1zZWxlY3QnLCBbJy1wJ10pO1xuICAgICAgeGNvZGVQYXRoID0gKHN0ZG91dCB8fCAnJykucmVwbGFjZSgnXFxuJywgJycpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgcmV0dXJuIG5vaygnWGNvZGUgaXMgTk9UIGluc3RhbGxlZCEnKTtcbiAgICB9XG4gICAgcmV0dXJuIHhjb2RlUGF0aCAmJiBhd2FpdCBmcy5leGlzdHMoeGNvZGVQYXRoKSA/IG9rKGBYY29kZSBpcyBpbnN0YWxsZWQgYXQ6ICR7eGNvZGVQYXRofWApIDpcbiAgICAgIG5vayhgWGNvZGUgY2Fubm90IGJlIGZvdW5kIGF0ICcke3hjb2RlUGF0aH0nIWApO1xuICB9XG5cbiAgYXN5bmMgZml4ICgpIHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSByZXF1aXJlLWF3YWl0XG4gICAgcmV0dXJuIGBNYW51YWxseSBpbnN0YWxsICR7J1hjb2RlJy5ib2xkfSwgYW5kIG1ha2Ugc3VyZSAneGNvZGUtc2VsZWN0IC1wJyBjb21tYW5kIHNob3dzIHByb3BlciBwYXRoIGxpa2UgJy9BcHBsaWNhdGlvbnMvWGNvZGUuYXBwL0NvbnRlbnRzL0RldmVsb3BlcidgO1xuICB9XG59XG5jaGVja3MucHVzaChuZXcgWGNvZGVDaGVjaygpKTtcblxuLy8gQ2hlY2sgZm9yIFhjb2RlIENvbW1hbmQgTGluZSBUb29scy5cbmNsYXNzIFhjb2RlQ21kTGluZVRvb2xzQ2hlY2sgZXh0ZW5kcyBEb2N0b3JDaGVjayB7XG4gIGNvbnN0cnVjdG9yICgpIHtcbiAgICBzdXBlcih7YXV0b2ZpeDogdHJ1ZX0pO1xuICB9XG5cbiAgYXN5bmMgZGlhZ25vc2UgKCkge1xuICAgIGNvbnN0IGVyck1lc3MgPSAnWGNvZGUgQ29tbWFuZCBMaW5lIFRvb2xzIGFyZSBOT1QgaW5zdGFsbGVkISc7XG4gICAgdHJ5IHtcbiAgICAgIC8vIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzE1MzcxOTI1L2hvdy10by1jaGVjay1pZi1jb21tYW5kLWxpbmUtdG9vbHMtaXMtaW5zdGFsbGVkXG4gICAgICBjb25zdCBzdGRvdXQgPSAoYXdhaXQgZXhlYygneGNvZGUtc2VsZWN0JywgWyctcCddKSkuc3Rkb3V0O1xuICAgICAgcmV0dXJuIG9rKGBYY29kZSBDb21tYW5kIExpbmUgVG9vbHMgYXJlIGluc3RhbGxlZCBpbjogJHtzdGRvdXQudHJpbSgpfWApO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgbG9nLmRlYnVnKGVycik7XG4gICAgICByZXR1cm4gbm9rKGVyck1lc3MpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGZpeCAoKSB7XG4gICAgbG9nLmluZm8oYFRoZSBmb2xsb3dpbmcgY29tbWFuZCBuZWVkIGJlIGV4ZWN1dGVkOiB4Y29kZS1zZWxlY3QgLS1pbnN0YWxsYCk7XG4gICAgbGV0IHllc25vID0gYXdhaXQgZml4SXQoKTtcbiAgICBpZiAoeWVzbm8gPT09ICd5ZXMnKSB7XG4gICAgICBhd2FpdCBleGVjKCd4Y29kZS1zZWxlY3QnLCBbJy0taW5zdGFsbCddKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbG9nLmluZm8oYFNraXBwaW5nIHlvdSB3aWxsIG5lZWQgdG8gaW5zdGFsbCAkeydYY29kZScuYm9sZH0gbWFudWFsbHkuYCk7XG4gICAgICB0aHJvdyBuZXcgRml4U2tpcHBlZEVycm9yKCk7XG4gICAgfVxuICB9XG59XG5cbmNoZWNrcy5wdXNoKG5ldyBYY29kZUNtZExpbmVUb29sc0NoZWNrKCkpO1xuXG4vLyBBdXRvbWF0aWNhbGx5IHJ1biBhdXRob3JpemUgaU9TIGlmIHJlcXVlc3RlZFxuZml4ZXMuYXV0aG9yaXplSW9zRml4ID0gYXN5bmMgZnVuY3Rpb24gKCkge1xuICBsb2cuaW5mbyhgVGhlIGF1dGhvcml6ZSBpT1Mgc2NyaXB0IG5lZWQgdG8gYmUgcnVuLmApO1xuICBsZXQgeWVzbm8gPSBhd2FpdCBmaXhJdCgpO1xuICBpZiAoeWVzbm8gPT09ICd5ZXMnKSB7XG4gICAgYXdhaXQgYXV0aG9yaXplSW9zKCk7XG4gIH0gZWxzZSB7XG4gICAgbG9nLmluZm8oYFNraXBwaW5nIHlvdSB3aWxsIG5lZWQgdG8gcnVuICR7J3RoZSBhdXRob3JpemUgaU9TJy5ib2xkfSBtYW51YWxseS5gKTtcbiAgICB0aHJvdyBuZXcgRml4U2tpcHBlZEVycm9yKCk7XG4gIH1cbn07XG5cbi8vIERldiBUb29scyBTZWN1cml0eVxuY2xhc3MgRGV2VG9vbHNTZWN1cml0eUNoZWNrIGV4dGVuZHMgRG9jdG9yQ2hlY2sge1xuICBjb25zdHJ1Y3RvciAoKSB7XG4gICAgc3VwZXIoe2F1dG9maXg6IHRydWV9KTtcbiAgfVxuXG4gIGFzeW5jIGRpYWdub3NlICgpIHtcbiAgICBjb25zdCBlcnJNZXNzID0gJ0RldlRvb2xzU2VjdXJpdHkgaXMgTk9UIGVuYWJsZWQhJztcbiAgICBsZXQgc3Rkb3V0O1xuICAgIHRyeSB7XG4gICAgICBzdGRvdXQgPSAoYXdhaXQgZXhlYygnRGV2VG9vbHNTZWN1cml0eScsIFtdKSkuc3Rkb3V0O1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgbG9nLmRlYnVnKGVycik7XG4gICAgICByZXR1cm4gbm9rKGVyck1lc3MpO1xuICAgIH1cbiAgICByZXR1cm4gc3Rkb3V0ICYmIHN0ZG91dC5tYXRjaCgvZW5hYmxlZC8pID8gb2soJ0RldlRvb2xzU2VjdXJpdHkgaXMgZW5hYmxlZC4nKVxuICAgICAgOiBub2soZXJyTWVzcyk7XG4gIH1cbiAgYXN5bmMgZml4ICgpIHtcbiAgICByZXR1cm4gYXdhaXQgZml4ZXMuYXV0aG9yaXplSW9zRml4KCk7XG4gIH1cbn1cbmNoZWNrcy5wdXNoKG5ldyBEZXZUb29sc1NlY3VyaXR5Q2hlY2soKSk7XG5cbi8vIEF1dGhvcml6YXRpb24gREJcbmNsYXNzIEF1dGhvcml6YXRpb25EYkNoZWNrIGV4dGVuZHMgRG9jdG9yQ2hlY2sge1xuICBjb25zdHJ1Y3RvciAoKSB7XG4gICAgc3VwZXIoe2F1dG9maXg6IHRydWV9KTtcbiAgfVxuXG4gIGFzeW5jIGRpYWdub3NlICgpIHtcbiAgICBjb25zdCBzdWNjZXNzTWVzcyA9ICdUaGUgQXV0aG9yaXphdGlvbiBEQiBpcyBzZXQgdXAgcHJvcGVybHkuJztcbiAgICBjb25zdCBlcnJNZXNzID0gJ1RoZSBBdXRob3JpemF0aW9uIERCIGlzIE5PVCBzZXQgdXAgcHJvcGVybHkuJztcbiAgICBsZXQgc3Rkb3V0O1xuICAgIHRyeSB7XG4gICAgICAoe3N0ZG91dH0gPSBhd2FpdCBleGVjKCdzZWN1cml0eScsIFsnYXV0aG9yaXphdGlvbmRiJywgJ3JlYWQnLCAnc3lzdGVtLnByaXZpbGVnZS50YXNrcG9ydCddKSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBsb2cud2FybihlcnIpO1xuICAgICAgcmV0dXJuIG5vayhlcnJNZXNzKTtcbiAgICB9XG4gICAgcmV0dXJuIHN0ZG91dCAmJiAoc3Rkb3V0Lm1hdGNoKC9pcy1kZXZlbG9wZXIvKSB8fCBzdGRvdXQubWF0Y2goL2FsbG93LykpID9cbiAgICAgIG9rKHN1Y2Nlc3NNZXNzKSA6IG5vayhlcnJNZXNzKTtcbiAgfVxuICBhc3luYyBmaXggKCkge1xuICAgIHJldHVybiBhd2FpdCBmaXhlcy5hdXRob3JpemVJb3NGaXgoKTtcbiAgfVxufVxuY2hlY2tzLnB1c2gobmV3IEF1dGhvcml6YXRpb25EYkNoZWNrKCkpO1xuXG4vLyBDaGVjayBmb3IgQ2FydGhhZ2UgKGZvciBXREEpXG5jbGFzcyBDYXJ0aGFnZUNoZWNrIGV4dGVuZHMgRG9jdG9yQ2hlY2sge1xuICBhc3luYyBkaWFnbm9zZSAoKSB7XG4gICAgbGV0IGNhcnRoYWdlUGF0aCA9IGF3YWl0IENhcnRoYWdlRGV0ZWN0b3IuZGV0ZWN0KCk7XG5cbiAgICBsZXQgdmVyc2lvbjtcbiAgICBpZiAoY2FydGhhZ2VQYXRoKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCB7c3Rkb3V0fSA9IGF3YWl0IGV4ZWMoY2FydGhhZ2VQYXRoLCBbJ3ZlcnNpb24nXSk7XG4gICAgICAgIC8vICdQbGVhc2UgdXBkYXRlIHRvIHRoZSBsYXRlc3QgQ2FydGhhZ2UgdmVyc2lvbjogMC4zMy4wLiBZb3UgY3VycmVudGx5IGFyZSBvbiAwLjMyLjBcXG4wLjMyLjBcXG4nIG9yICcwLjMyLjBcXG4nXG4gICAgICAgIC8vIDAuMzIuMCBpcyB0aGUgY3VycmVudCB2ZXJzaW9uLiAwLjMzLjAgaXMgYW4gYXZhaWxhYmxlIG5ld2VyIHZlcnNpb24uXG4gICAgICAgIHZlcnNpb24gPSBfLmxhc3Qoc3Rkb3V0Lm1hdGNoKC8oXFxkK1xcLlxcZCtcXC5cXGQrKS9nKSk7XG4gICAgICAgIGlmICghdXRpbC5jb2VyY2VWZXJzaW9uKHZlcnNpb24sIGZhbHNlKSkge1xuICAgICAgICAgIGxvZy53YXJuKGBDYW5ub3QgcGFyc2UgQ2FydGhhZ2UgdmVyc2lvbiBmcm9tICR7c3Rkb3V0fWApO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgbG9nLndhcm4oZXJyKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY2FydGhhZ2VQYXRoXG4gICAgICA/IG9rKGBDYXJ0aGFnZSB3YXMgZm91bmQgYXQ6ICR7Y2FydGhhZ2VQYXRofSR7IHZlcnNpb24gPyBgLiBJbnN0YWxsZWQgdmVyc2lvbiBpczogJHt2ZXJzaW9ufWAgOiAnJ31gKVxuICAgICAgOiBub2soYENhcnRoYWdlIHdhcyBOT1QgZm91bmQhYCk7XG4gIH1cblxuICBhc3luYyBmaXggKCkgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIHJlcXVpcmUtYXdhaXRcbiAgICByZXR1cm4gYCR7J1tGb3IgbG93ZXIgdGhhbiBBcHBpdW0gMS4yMC4wXScuYm9sZH0gUGxlYXNlIGluc3RhbGwgJHsnQ2FydGhhZ2UnLmJvbGR9LiBWaXNpdCBodHRwczovL2dpdGh1Yi5jb20vQ2FydGhhZ2VgICtcbiAgICAgICAgICAgJy9DYXJ0aGFnZSNpbnN0YWxsaW5nLWNhcnRoYWdlIGZvciBtb3JlIGluZm9ybWF0aW9uLic7XG4gIH1cbn1cbmNoZWNrcy5wdXNoKG5ldyBDYXJ0aGFnZUNoZWNrKCkpO1xuXG5jaGVja3MucHVzaChuZXcgRW52VmFyQW5kUGF0aENoZWNrKCdIT01FJykpO1xuXG5jbGFzcyBPcHRpb25hbEx5ZnRDb21tYW5kQ2hlY2sgZXh0ZW5kcyBEb2N0b3JDaGVjayB7XG4gIGFzeW5jIGRpYWdub3NlICgpIHtcbiAgICBjb25zdCBseWZ0Q21kID0gYXdhaXQgcmVzb2x2ZUV4ZWN1dGFibGVQYXRoKCdzZXQtc2ltdWxhdG9yLWxvY2F0aW9uJyk7XG4gICAgaWYgKGx5ZnRDbWQpIHtcbiAgICAgIHJldHVybiBva09wdGlvbmFsKCdzZXQtc2ltdWxhdG9yLWxvY2F0aW9uIGlzIGluc3RhbGxlZCcpO1xuICAgIH1cblxuICAgIHJldHVybiBub2tPcHRpb25hbCgnc2V0LXNpbXVsYXRvci1sb2NhdGlvbiBpcyBub3QgaW5zdGFsbGVkJyk7XG4gIH1cblxuICBhc3luYyBmaXggKCkgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIHJlcXVpcmUtYXdhaXRcbiAgICByZXR1cm4gYCR7J3NldC1zaW11bGF0b3ItbG9jYXRpb24nLmJvbGR9IGlzIG5lZWRlZCB0byBzZXQgbG9jYXRpb24gZm9yIFNpbXVsYXRvci4gYCArXG4gICAgICAnUGxlYXNlIHJlYWQgaHR0cHM6Ly9naXRodWIuY29tL2x5ZnQvc2V0LXNpbXVsYXRvci1sb2NhdGlvbiB0byBpbnN0YWxsIGl0JztcbiAgfVxufVxuY2hlY2tzLnB1c2gobmV3IE9wdGlvbmFsTHlmdENvbW1hbmRDaGVjaygpKTtcblxuXG5jbGFzcyBPcHRpb25hbElkYkNvbW1hbmRDaGVjayBleHRlbmRzIERvY3RvckNoZWNrIHtcbiAgYXN5bmMgZGlhZ25vc2UgKCkge1xuICAgIGNvbnN0IGZiSWRiUGF0aCA9IGF3YWl0IHJlc29sdmVFeGVjdXRhYmxlUGF0aCgnaWRiJyk7XG4gICAgY29uc3QgZmJDb21wYW5pb25JZGJQYXRoID0gYXdhaXQgcmVzb2x2ZUV4ZWN1dGFibGVQYXRoKCdpZGJfY29tcGFuaW9uJyk7XG4gICAgaWYgKGZiSWRiUGF0aCAmJiBmYkNvbXBhbmlvbklkYlBhdGgpIHtcbiAgICAgIHJldHVybiBva09wdGlvbmFsKCdpZGIgYW5kIGlkYl9jb21wYW5pb24gYXJlIGluc3RhbGxlZCcpO1xuICAgIH1cblxuICAgIGlmICghZmJJZGJQYXRoICYmIGZiQ29tcGFuaW9uSWRiUGF0aCkge1xuICAgICAgcmV0dXJuIG5va09wdGlvbmFsKCdpZGIgaXMgbm90IGluc3RhbGxlZCcpO1xuICAgIH0gZWxzZSBpZiAoZmJJZGJQYXRoICYmICFmYkNvbXBhbmlvbklkYlBhdGgpIHtcbiAgICAgIHJldHVybiBub2tPcHRpb25hbCgnaWRiX2NvbXBhbmlvbiBpcyBub3QgaW5zdGFsbGVkJyk7XG4gICAgfVxuICAgIHJldHVybiBub2tPcHRpb25hbCgnaWRiIGFuZCBpZGJfY29tcGFuaW9uIGFyZSBub3QgaW5zdGFsbGVkJyk7XG4gIH1cblxuICBhc3luYyBmaXggKCkgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIHJlcXVpcmUtYXdhaXRcbiAgICByZXR1cm4gYFdoeSAkeydpZGInLmJvbGR9IGlzIG5lZWRlZCBhbmQgaG93IHRvIGluc3RhbGwgaXQ6IGh0dHBzOi8vZ2l0aHViLmNvbS9hcHBpdW0vYXBwaXVtLWlkYmA7XG4gIH1cbn1cbmNoZWNrcy5wdXNoKG5ldyBPcHRpb25hbElkYkNvbW1hbmRDaGVjaygpKTtcblxuY2xhc3MgT3B0aW9uYWxBcHBsZXNpbXV0aWxzQ29tbWFuZENoZWNrIGV4dGVuZHMgRG9jdG9yQ2hlY2sge1xuICBhc3luYyBkaWFnbm9zZSAoKSB7XG4gICAgY29uc3QgYXBwbGVzaW11dGlsc1BhdGggPSBhd2FpdCByZXNvbHZlRXhlY3V0YWJsZVBhdGgoJ2FwcGxlc2ltdXRpbHMnKTtcbiAgICByZXR1cm4gYXBwbGVzaW11dGlsc1BhdGhcbiAgICAgID8gb2tPcHRpb25hbChgYXBwbGVzaW11dGlscyBpcyBpbnN0YWxsZWQgYXQ6ICR7YXBwbGVzaW11dGlsc1BhdGh9LiBJbnN0YWxsZWQgdmVyc2lvbnMgYXJlOiAkeyhhd2FpdCBleGVjKCdicmV3JywgWydsaXN0JywgJy0tdmVyc2lvbnMnLCAnYXBwbGVzaW11dGlscyddKSkuc3Rkb3V0LnRyaW0oKX1gKVxuICAgICAgOiBub2tPcHRpb25hbCgnYXBwbGVzaW11dGlscyBjYW5ub3QgYmUgZm91bmQnKTtcbiAgfVxuXG4gIGFzeW5jIGZpeCAoKSB7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgcmVxdWlyZS1hd2FpdFxuICAgIHJldHVybiBgV2h5ICR7J2FwcGxlc2ltdXRpbHMnLmJvbGR9IGlzIG5lZWRlZCBhbmQgaG93IHRvIGluc3RhbGwgaXQ6IGh0dHA6Ly9hcHBpdW0uaW8vZG9jcy9lbi9kcml2ZXJzL2lvcy14Y3VpdGVzdC9gO1xuICB9XG59XG5jaGVja3MucHVzaChuZXcgT3B0aW9uYWxBcHBsZXNpbXV0aWxzQ29tbWFuZENoZWNrKCkpO1xuXG5jbGFzcyBPcHRpb25hbElPU0RlcGxveUNvbW1hbmRDaGVjayBleHRlbmRzIERvY3RvckNoZWNrIHtcbiAgYXN5bmMgZGlhZ25vc2UgKCkge1xuICAgIGNvbnN0IGlvc0RlcGxveVBhdGggPSBhd2FpdCByZXNvbHZlRXhlY3V0YWJsZVBhdGgoJ2lvcy1kZXBsb3knKTtcbiAgICByZXR1cm4gaW9zRGVwbG95UGF0aFxuICAgICAgPyBva09wdGlvbmFsKGBpb3MtZGVwbG95IGlzIGluc3RhbGxlZCBhdDogJHtpb3NEZXBsb3lQYXRofS4gSW5zdGFsbGVkIHZlcnNpb24gaXM6ICR7KGF3YWl0IGV4ZWMoaW9zRGVwbG95UGF0aCwgWyctViddKSkuc3Rkb3V0LnRyaW0oKX1gKVxuICAgICAgOiBub2tPcHRpb25hbCgnaW9zLWRlcGxveSBjYW5ub3QgYmUgZm91bmQnKTtcbiAgfVxuXG4gIGFzeW5jIGZpeCAoKSB7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgcmVxdWlyZS1hd2FpdFxuICAgIHJldHVybiBgJHsnaW9zLWRlcGxveScuYm9sZH0gaXMgdXNlZCBhcyBhIGZhbGxiYWNrIGNvbW1hbmQgdG8gaW5zdGFsbCBpT1MgYXBwbGljYXRpb25zIHRvIHJlYWwgZGV2aWNlLiBQbGVhc2UgcmVhZCBodHRwczovL2dpdGh1Yi5jb20vaW9zLWNvbnRyb2wvaW9zLWRlcGxveS8gdG8gaW5zdGFsbCBpdGA7XG4gIH1cbn1cbmNoZWNrcy5wdXNoKG5ldyBPcHRpb25hbElPU0RlcGxveUNvbW1hbmRDaGVjaygpKTtcblxuZXhwb3J0IHtcbiAgZml4ZXMsIFhjb2RlQ2hlY2ssIFhjb2RlQ21kTGluZVRvb2xzQ2hlY2ssIERldlRvb2xzU2VjdXJpdHlDaGVjayxcbiAgQXV0aG9yaXphdGlvbkRiQ2hlY2ssIENhcnRoYWdlQ2hlY2ssIE9wdGlvbmFsSWRiQ29tbWFuZENoZWNrLCBPcHRpb25hbEFwcGxlc2ltdXRpbHNDb21tYW5kQ2hlY2ssXG4gIE9wdGlvbmFsSU9TRGVwbG95Q29tbWFuZENoZWNrLCBPcHRpb25hbEx5ZnRDb21tYW5kQ2hlY2tcbn07XG5leHBvcnQgZGVmYXVsdCBjaGVja3M7XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBRUEsSUFBSUEsTUFBTSxHQUFHLEVBQWI7QUFDQSxJQUFJQyxLQUFLLEdBQUcsRUFBWjs7O0FBR0EsTUFBTUMsVUFBTixTQUF5QkMsbUJBQXpCLENBQXFDO0VBQ3JCLE1BQVJDLFFBQVEsR0FBSTtJQUNoQixJQUFJQyxTQUFKOztJQUNBLElBQUk7TUFFRixNQUFNLElBQUFDLGtCQUFBLEVBQUssT0FBTCxFQUFjLENBQUMsUUFBRCxFQUFXLE1BQVgsQ0FBZCxDQUFOO0lBQ0QsQ0FIRCxDQUdFLE9BQU9DLEdBQVAsRUFBWTtNQUNaLE9BQU8sSUFBQUMsVUFBQSxFQUFJLDRCQUFKLENBQVA7SUFDRDs7SUFDRCxJQUFJO01BQ0YsTUFBTTtRQUFDQztNQUFELElBQVcsTUFBTSxJQUFBSCxrQkFBQSxFQUFLLGNBQUwsRUFBcUIsQ0FBQyxJQUFELENBQXJCLENBQXZCO01BQ0FELFNBQVMsR0FBRyxDQUFDSSxNQUFNLElBQUksRUFBWCxFQUFlQyxPQUFmLENBQXVCLElBQXZCLEVBQTZCLEVBQTdCLENBQVo7SUFDRCxDQUhELENBR0UsT0FBT0gs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