UNPKG

@mjcctech/meteor-desktop

Version:

Build a Meteor's desktop client with hot code push.

384 lines (311 loc) 49.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _runtime = _interopRequireDefault(require("regenerator-runtime/runtime")); var _shelljs = _interopRequireDefault(require("shelljs")); var _path = _interopRequireDefault(require("path")); var _fs = _interopRequireDefault(require("fs")); var _rimraf = _interopRequireDefault(require("rimraf")); var _crossSpawn = _interopRequireDefault(require("cross-spawn")); var _log = _interopRequireDefault(require("./log")); var _defaultDependencies = _interopRequireDefault(require("./defaultDependencies")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // eslint-disable-next-line no-unused-vars /** * Promisfied rimraf. * * @param {string} dirPath - path to the dir to be deleted * @param {number} delay - delay the task by ms * @returns {Promise<any>} */ function removeDir(dirPath, delay = 0) { return new Promise((resolve, reject) => { setTimeout(() => { (0, _rimraf.default)(dirPath, { maxBusyTries: 100 }, err => { if (err) { reject(err); } else { resolve(); } }); }, delay); }); } /** * Wrapper for electron-builder. */ class InstallerBuilder { /** * @param {MeteorDesktop} $ - context * * @constructor */ constructor($) { this.log = new _log.default('electronBuilder'); this.$ = $; this.firstPass = true; this.lastRebuild = {}; this.currentContext = null; this.installerDir = _path.default.join(this.$.env.options.output, this.$.env.paths.installerDir); this.platforms = []; } async init() { this.builder = await this.$.getDependency('electron-builder', _defaultDependencies.default['electron-builder']); const appBuilder = await this.$.getDependency('app-builder-lib', _defaultDependencies.default['electron-builder'], false); this.yarn = require(_path.default.join(appBuilder.path, 'out', 'util', 'yarn')); this.getGypEnv = this.yarn.getGypEnv; this.packageDependencies = require(_path.default.join(appBuilder.path, 'out', 'util', 'packageDependencies')); } /** * Prepares the last rebuild object for electron-builder. * * @param {string} arch * @param {string} platform * @returns {Object} */ prepareLastRebuildObject(arch, platform = process.platform) { const productionDeps = this.packageDependencies.createLazyProductionDeps(this.$.env.paths.electronApp.root); this.lastRebuild = { frameworkInfo: { version: this.$.getElectronVersion(), useCustomDist: true }, platform, arch, productionDeps }; return this.lastRebuild; } /** * Calls npm rebuild from electron-builder. * @param {string} arch * @param {string} platform * @param {boolean} install * @returns {Promise} */ async installOrRebuild(arch, platform = process.platform, install = false) { this.log.debug(`calling installOrRebuild from electron-builder for arch ${arch}`); this.prepareLastRebuildObject(arch, platform); await this.yarn.installOrRebuild(this.$.desktop.getSettings().builderOptions || {}, this.$.env.paths.electronApp.root, this.lastRebuild, install); } /** * Callback invoked before build is made. Ensures that app.asar have the right rebuilt * node_modules. * * @param {Object} context * @returns {Promise} */ beforeBuild(context) { this.currentContext = Object.assign({}, context); return new Promise((resolve, reject) => { const platformMatches = process.platform === context.platform.nodeName; const rebuild = platformMatches && context.arch !== this.lastRebuild.arch; if (!platformMatches) { this.log.warn('skipping dependencies rebuild because platform is different, if you have native ' + 'node modules as your app dependencies you should od the build on the target platform only'); } if (!rebuild) { this.moveNodeModulesOut().catch(e => reject(e)).then(() => setTimeout(() => resolve(false), 2000)); // Timeout helps on Windows to clear the file locks. } else { // Lets rebuild the node_modules for different arch. this.installOrRebuild(context.arch, context.platform.nodeName).catch(e => reject(e)).then(() => this.$.electronApp.installLocalNodeModules(context.arch)).catch(e => reject(e)).then(() => { this.$.electronApp.scaffold.createAppRoot(); this.$.electronApp.scaffold.copySkeletonApp(); return this.$.electronApp.packSkeletonToAsar([this.$.env.paths.electronApp.meteorAsar, this.$.env.paths.electronApp.desktopAsar, this.$.env.paths.electronApp.extracted]); }).catch(e => reject(e)).then(() => this.moveNodeModulesOut()).catch(e => reject(e)).then(() => resolve(false)); } }); } /** * Callback to be invoked after packing. Restores node_modules to the .desktop-build. * @returns {Promise} */ afterPack(context) { this.platforms = this.platforms.filter(platform => platform !== context.electronPlatformName); if (this.platforms.length !== 0) { return Promise.resolve(); } return new Promise((resolve, reject) => { _shelljs.default.config.fatal = true; if (this.$.utils.exists(this.$.env.paths.electronApp.extractedNodeModules)) { this.log.debug('injecting extracted modules'); _shelljs.default.cp('-Rf', this.$.env.paths.electronApp.extractedNodeModules, _path.default.join(this.getPackagedAppPath(context), 'node_modules')); } this.log.debug('moving node_modules back'); // Move node_modules back. try { _shelljs.default.mv(this.$.env.paths.electronApp.tmpNodeModules, this.$.env.paths.electronApp.nodeModules); } catch (e) { reject(e); return; } finally { _shelljs.default.config.reset(); } if (this.firstPass) { this.firstPass = false; } this.log.debug('node_modules moved back'); this.wait().catch(e => reject(e)).then(() => resolve()); }); } /** * This command kills orphaned MSBuild.exe processes. * Sometime after native node_modules compilation they are still writing some logs, * prevent node_modules from being deleted. */ killMSBuild() { if (this.currentContext.platform.nodeName !== 'win32') { return; } try { const out = _crossSpawn.default.sync('wmic', ['process', 'where', 'caption="MSBuild.exe"', 'get', 'processid']).stdout.toString('utf-8').split('\n'); const regex = new RegExp(/(\d+)/, 'gm'); // No we will check for those with the matching params. out.forEach(line => { const match = regex.exec(line) || false; if (match) { this.log.debug(`killing MSBuild.exe at pid: ${match[1]}`); _crossSpawn.default.sync('taskkill', ['/pid', match[1], '/f', '/t']); } regex.lastIndex = 0; }); } catch (e) { this.log.debug('kill MSBuild failed'); } } /** * Returns the path to packaged app. * @returns {string} */ getPackagedAppPath(context = {}) { if (this.currentContext.platform.nodeName === 'darwin') { return _path.default.join(this.installerDir, 'mac', `${context.packager.appInfo.productFilename}.app`, 'Contents', 'Resources', 'app'); } const platformDir = `${this.currentContext.platform.nodeName === 'win32' ? 'win' : 'linux'}-${this.currentContext.arch === 'ia32' ? 'ia32-' : ''}unpacked`; return _path.default.join(this.installerDir, platformDir, 'resources', 'app'); } /** * On Windows it waits for the app.asar in the packed app to be free (no file locks). * @returns {*} */ wait() { if (this.currentContext.platform.nodeName !== 'win32') { return Promise.resolve(); } const appAsarPath = _path.default.join(this.getPackagedAppPath(), 'app.asar'); let retries = 0; const self = this; return new Promise((resolve, reject) => { function check() { _fs.default.open(appAsarPath, 'r+', (err, fd) => { retries += 1; if (err) { if (err.code !== 'ENOENT') { self.log.debug(`waiting for app.asar to be readable, ${'code' in err ? `currently reading it returns ${err.code}` : ''}`); if (retries < 6) { setTimeout(() => check(), 4000); } else { reject(`file is locked: ${appAsarPath}`); } } else { resolve(); } } else { _fs.default.closeSync(fd); resolve(); } }); } check(); }); } /** * Prepares the target object passed to the electron-builder. * * @returns {Map<Platform, Map<Arch, Array<string>>>} */ prepareTargets() { let arch = this.$.env.options.ia32 ? 'ia32' : 'x64'; arch = this.$.env.options.allArchs ? 'all' : arch; const targets = []; if (this.$.env.options.win) { targets.push(this.builder.dependency.Platform.WINDOWS); } if (this.$.env.options.linux) { targets.push(this.builder.dependency.Platform.LINUX); } if (this.$.env.options.mac) { targets.push(this.builder.dependency.Platform.MAC); } if (targets.length === 0) { if (this.$.env.os.isWindows) { targets.push(this.builder.dependency.Platform.WINDOWS); } else if (this.$.env.os.isLinux) { targets.push(this.builder.dependency.Platform.LINUX); } else { targets.push(this.builder.dependency.Platform.MAC); } } return this.builder.dependency.createTargets(targets, null, arch); } async build() { const settings = this.$.desktop.getSettings(); if (!('builderOptions' in settings)) { this.log.error('no builderOptions in settings.json, aborting'); process.exit(1); } const builderOptions = Object.assign({}, settings.builderOptions); builderOptions.asar = false; builderOptions.npmRebuild = true; builderOptions.beforeBuild = this.beforeBuild.bind(this); builderOptions.afterPack = this.afterPack.bind(this); builderOptions.electronVersion = this.$.getElectronVersion(); builderOptions.directories = { app: this.$.env.paths.electronApp.root, output: _path.default.join(this.$.env.options.output, this.$.env.paths.installerDir) }; if ('mac' in builderOptions && 'target' in builderOptions.mac) { if (builderOptions.mac.target.includes('mas')) { this.platforms = ['darwin', 'mas']; } } try { this.log.debug('calling build from electron-builder'); await this.builder.dependency.build(Object.assign({ targets: this.prepareTargets(), config: builderOptions }, settings.builderCliOptions)); if (this.$.utils.exists(this.$.env.paths.electronApp.extractedNodeModules)) { _shelljs.default.rm('-rf', this.$.env.paths.electronApp.extractedNodeModules); } } catch (e) { this.log.error('error while building installer: ', e); } } /** * Moves node_modules out of the app because while the app will be packaged * we do not want it to be there. * @returns {Promise<any>} */ moveNodeModulesOut() { return new Promise((resolve, reject) => { this.log.debug('moving node_modules out, because we have them already in' + ' app.asar'); this.killMSBuild(); removeDir(this.$.env.paths.electronApp.tmpNodeModules).catch(e => reject(e)).then(() => { _shelljs.default.config.fatal = true; _shelljs.default.config.verbose = true; try { _shelljs.default.mv(this.$.env.paths.electronApp.nodeModules, this.$.env.paths.electronApp.tmpNodeModules); _shelljs.default.config.reset(); return this.wait(); } catch (e) { _shelljs.default.config.reset(); return Promise.reject(e); } }).catch(e => reject(e)).then(() => removeDir(this.$.env.paths.electronApp.nodeModules, 1000)).catch(e => reject(e)).then(() => this.wait()).catch(reject).then(resolve); }); } } exports.default = InstallerBuilder; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi9lbGVjdHJvbkJ1aWxkZXIuanMiXSwibmFtZXMiOlsicmVtb3ZlRGlyIiwiZGlyUGF0aCIsImRlbGF5IiwiUHJvbWlzZSIsInJlc29sdmUiLCJyZWplY3QiLCJzZXRUaW1lb3V0IiwibWF4QnVzeVRyaWVzIiwiZXJyIiwiSW5zdGFsbGVyQnVpbGRlciIsImNvbnN0cnVjdG9yIiwiJCIsImxvZyIsIkxvZyIsImZpcnN0UGFzcyIsImxhc3RSZWJ1aWxkIiwiY3VycmVudENvbnRleHQiLCJpbnN0YWxsZXJEaXIiLCJwYXRoIiwiam9pbiIsImVudiIsIm9wdGlvbnMiLCJvdXRwdXQiLCJwYXRocyIsInBsYXRmb3JtcyIsImluaXQiLCJidWlsZGVyIiwiZ2V0RGVwZW5kZW5jeSIsImRlZmF1bHREZXBlbmRlbmNpZXMiLCJhcHBCdWlsZGVyIiwieWFybiIsInJlcXVpcmUiLCJnZXRHeXBFbnYiLCJwYWNrYWdlRGVwZW5kZW5jaWVzIiwicHJlcGFyZUxhc3RSZWJ1aWxkT2JqZWN0IiwiYXJjaCIsInBsYXRmb3JtIiwicHJvY2VzcyIsInByb2R1Y3Rpb25EZXBzIiwiY3JlYXRlTGF6eVByb2R1Y3Rpb25EZXBzIiwiZWxlY3Ryb25BcHAiLCJyb290IiwiZnJhbWV3b3JrSW5mbyIsInZlcnNpb24iLCJnZXRFbGVjdHJvblZlcnNpb24iLCJ1c2VDdXN0b21EaXN0IiwiaW5zdGFsbE9yUmVidWlsZCIsImluc3RhbGwiLCJkZWJ1ZyIsImRlc2t0b3AiLCJnZXRTZXR0aW5ncyIsImJ1aWxkZXJPcHRpb25zIiwiYmVmb3JlQnVpbGQiLCJjb250ZXh0IiwiT2JqZWN0IiwiYXNzaWduIiwicGxhdGZvcm1NYXRjaGVzIiwibm9kZU5hbWUiLCJyZWJ1aWxkIiwid2FybiIsIm1vdmVOb2RlTW9kdWxlc091dCIsImNhdGNoIiwiZSIsInRoZW4iLCJpbnN0YWxsTG9jYWxOb2RlTW9kdWxlcyIsInNjYWZmb2xkIiwiY3JlYXRlQXBwUm9vdCIsImNvcHlTa2VsZXRvbkFwcCIsInBhY2tTa2VsZXRvblRvQXNhciIsIm1ldGVvckFzYXIiLCJkZXNrdG9wQXNhciIsImV4dHJhY3RlZCIsImFmdGVyUGFjayIsImZpbHRlciIsImVsZWN0cm9uUGxhdGZvcm1OYW1lIiwibGVuZ3RoIiwic2hlbGwiLCJjb25maWciLCJmYXRhbCIsInV0aWxzIiwiZXhpc3RzIiwiZXh0cmFjdGVkTm9kZU1vZHVsZXMiLCJjcCIsImdldFBhY2thZ2VkQXBwUGF0aCIsIm12IiwidG1wTm9kZU1vZHVsZXMiLCJub2RlTW9kdWxlcyIsInJlc2V0Iiwid2FpdCIsImtpbGxNU0J1aWxkIiwib3V0Iiwic3Bhd24iLCJzeW5jIiwic3Rkb3V0IiwidG9TdHJpbmciLCJzcGxpdCIsInJlZ2V4IiwiUmVnRXhwIiwiZm9yRWFjaCIsImxpbmUiLCJtYXRjaCIsImV4ZWMiLCJsYXN0SW5kZXgiLCJwYWNrYWdlciIsImFwcEluZm8iLCJwcm9kdWN0RmlsZW5hbWUiLCJwbGF0Zm9ybURpciIsImFwcEFzYXJQYXRoIiwicmV0cmllcyIsInNlbGYiLCJjaGVjayIsImZzIiwib3BlbiIsImZkIiwiY29kZSIsImNsb3NlU3luYyIsInByZXBhcmVUYXJnZXRzIiwiaWEzMiIsImFsbEFyY2hzIiwidGFyZ2V0cyIsIndpbiIsInB1c2giLCJkZXBlbmRlbmN5IiwiUGxhdGZvcm0iLCJXSU5ET1dTIiwibGludXgiLCJMSU5VWCIsIm1hYyIsIk1BQyIsIm9zIiwiaXNXaW5kb3dzIiwiaXNMaW51eCIsImNyZWF0ZVRhcmdldHMiLCJidWlsZCIsInNldHRpbmdzIiwiZXJyb3IiLCJleGl0IiwiYXNhciIsIm5wbVJlYnVpbGQiLCJiaW5kIiwiZWxlY3Ryb25WZXJzaW9uIiwiZGlyZWN0b3JpZXMiLCJhcHAiLCJ0YXJnZXQiLCJpbmNsdWRlcyIsImJ1aWxkZXJDbGlPcHRpb25zIiwicm0iLCJ2ZXJib3NlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7QUFSQTs7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Q0EsaUJBQU9wRixPQUFPLENBQUNFLE1BQVIsQ0FBZXlELENBQWYsQ0FBUDtBQUNIO0FBQ0osT0FoQkwsRUFpQktELEtBakJMLENBaUJXQyxDQUFDLElBQUl6RCxNQUFNLENBQUN5RCxDQUFELENBakJ0QixFQWtCS0MsSUFsQkwsQ0FrQlUsTUFBTS9ELFNBQVMsQ0FBQyxLQUFLVyxDQUFMLENBQU9TLEdBQVAsQ0FBV0csS0FBWCxDQUFpQmlCLFdBQWpCLENBQTZCOEMsV0FBOUIsRUFBMkMsSUFBM0MsQ0FsQnpCLEVBbUJLekIsS0FuQkwsQ0FtQldDLENBQUMsSUFBSXpELE1BQU0sQ0FBQ3lELENBQUQsQ0FuQnRCLEVBb0JLQyxJQXBCTCxDQW9CVSxNQUFNLEtBQUt5QixJQUFMLEVBcEJoQixFQXFCSzNCLEtBckJMLENBcUJXeEQsTUFyQlgsRUFzQkswRCxJQXRCTCxDQXNCVTNELE9BdEJWO0FBdUJILEtBM0JNLENBQVA7QUE0Qkg7O0FBdFdpQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bnVzZWQtdmFyc1xuaW1wb3J0IHJlZ2VuZXJhdG9yUnVudGltZSBmcm9tICdyZWdlbmVyYXRvci1ydW50aW1lL3J1bnRpbWUnO1xuaW1wb3J0IHNoZWxsIGZyb20gJ3NoZWxsanMnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgZnMgZnJvbSAnZnMnO1xuaW1wb3J0IHJpbXJhZiBmcm9tICdyaW1yYWYnO1xuaW1wb3J0IHNwYXduIGZyb20gJ2Nyb3NzLXNwYXduJztcbmltcG9ydCBMb2cgZnJvbSAnLi9sb2cnO1xuaW1wb3J0IGRlZmF1bHREZXBlbmRlbmNpZXMgZnJvbSAnLi9kZWZhdWx0RGVwZW5kZW5jaWVzJztcblxuLyoqXG4gKiBQcm9taXNmaWVkIHJpbXJhZi5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gZGlyUGF0aCAtIHBhdGggdG8gdGhlIGRpciB0byBiZSBkZWxldGVkXG4gKiBAcGFyYW0ge251bWJlcn0gZGVsYXkgLSBkZWxheSB0aGUgdGFzayBieSBtc1xuICogQHJldHVybnMge1Byb21pc2U8YW55Pn1cbiAqL1xuZnVuY3Rpb24gcmVtb3ZlRGlyKGRpclBhdGgsIGRlbGF5ID0gMCkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgcmltcmFmKGRpclBhdGgsIHtcbiAgICAgICAgICAgICAgICBtYXhCdXN5VHJpZXM6IDEwMFxuICAgICAgICAgICAgfSwgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LCBkZWxheSk7XG4gICAgfSk7XG59XG5cbi8qKlxuICogV3JhcHBlciBmb3IgZWxlY3Ryb24tYnVpbGRlci5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgSW5zdGFsbGVyQnVpbGRlciB7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIHtNZXRlb3JEZXNrdG9wfSAkIC0gY29udGV4dFxuICAgICAqXG4gICAgICogQGNvbnN0cnVjdG9yXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoJCkge1xuICAgICAgICB0aGlzLmxvZyA9IG5ldyBMb2coJ2VsZWN0cm9uQnVpbGRlcicpO1xuICAgICAgICB0aGlzLiQgPSAkO1xuICAgICAgICB0aGlzLmZpcnN0UGFzcyA9IHRydWU7XG4gICAgICAgIHRoaXMubGFzdFJlYnVpbGQgPSB7fTtcbiAgICAgICAgdGhpcy5jdXJyZW50Q29udGV4dCA9IG51bGw7XG4gICAgICAgIHRoaXMuaW5zdGFsbGVyRGlyID0gcGF0aC5qb2luKHRoaXMuJC5lbnYub3B0aW9ucy5vdXRwdXQsIHRoaXMuJC5lbnYucGF0aHMuaW5zdGFsbGVyRGlyKTtcbiAgICAgICAgdGhpcy5wbGF0Zm9ybXMgPSBbXTtcbiAgICB9XG5cbiAgICBhc3luYyBpbml0KCkge1xuICAgICAgICB0aGlzLmJ1aWxkZXIgPSBhd2FpdCB0aGlzLiQuZ2V0RGVwZW5kZW5jeSgnZWxlY3Ryb24tYnVpbGRlcicsIGRlZmF1bHREZXBlbmRlbmNpZXNbJ2VsZWN0cm9uLWJ1aWxkZXInXSk7XG4gICAgICAgIGNvbnN0IGFwcEJ1aWxkZXIgPSBhd2FpdCB0aGlzLiQuZ2V0RGVwZW5kZW5jeSgnYXBwLWJ1aWxkZXItbGliJywgZGVmYXVsdERlcGVuZGVuY2llc1snZWxlY3Ryb24tYnVpbGRlciddLCBmYWxzZSk7XG5cbiAgICAgICAgdGhpcy55YXJuID0gcmVxdWlyZShwYXRoLmpvaW4oYXBwQnVpbGRlci5wYXRoLCAnb3V0JywgJ3V0aWwnLCAneWFybicpKTtcbiAgICAgICAgdGhpcy5nZXRHeXBFbnYgPSB0aGlzLnlhcm4uZ2V0R3lwRW52O1xuICAgICAgICB0aGlzLnBhY2thZ2VEZXBlbmRlbmNpZXMgPSByZXF1aXJlKHBhdGguam9pbihhcHBCdWlsZGVyLnBhdGgsICdvdXQnLCAndXRpbCcsICdwYWNrYWdlRGVwZW5kZW5jaWVzJykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFByZXBhcmVzIHRoZSBsYXN0IHJlYnVpbGQgb2JqZWN0IGZvciBlbGVjdHJvbi1idWlsZGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGFyY2hcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcGxhdGZvcm1cbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fVxuICAgICAqL1xuICAgIHByZXBhcmVMYXN0UmVidWlsZE9iamVjdChhcmNoLCBwbGF0Zm9ybSA9IHByb2Nlc3MucGxhdGZvcm0pIHtcbiAgICAgICAgY29uc3QgcHJvZHVjdGlvbkRlcHMgPSB0aGlzLnBhY2thZ2VEZXBlbmRlbmNpZXNcbiAgICAgICAgICAgIC5jcmVhdGVMYXp5UHJvZHVjdGlvbkRlcHModGhpcy4kLmVudi5wYXRocy5lbGVjdHJvbkFwcC5yb290KTtcbiAgICAgICAgdGhpcy5sYXN0UmVidWlsZCA9IHtcbiAgICAgICAgICAgIGZyYW1ld29ya0luZm86IHsgdmVyc2lvbjogdGhpcy4kLmdldEVsZWN0cm9uVmVyc2lvbigpLCB1c2VDdXN0b21EaXN0OiB0cnVlIH0sXG4gICAgICAgICAgICBwbGF0Zm9ybSxcbiAgICAgICAgICAgIGFyY2gsXG4gICAgICAgICAgICBwcm9kdWN0aW9uRGVwc1xuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gdGhpcy5sYXN0UmVidWlsZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYWxscyBucG0gcmVidWlsZCBmcm9tIGVsZWN0cm9uLWJ1aWxkZXIuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGFyY2hcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcGxhdGZvcm1cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGluc3RhbGxcbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZX1cbiAgICAgKi9cbiAgICBhc3luYyBpbnN0YWxsT3JSZWJ1aWxkKGFyY2gsIHBsYXRmb3JtID0gcHJvY2Vzcy5wbGF0Zm9ybSwgaW5zdGFsbCA9IGZhbHNlKSB7XG4gICAgICAgIHRoaXMubG9nLmRlYnVnKGBjYWxsaW5nIGluc3RhbGxPclJlYnVpbGQgZnJvbSBlbGVjdHJvbi1idWlsZGVyIGZvciBhcmNoICR7YXJjaH1gKTtcbiAgICAgICAgdGhpcy5wcmVwYXJlTGFzdFJlYnVpbGRPYmplY3QoYXJjaCwgcGxhdGZvcm0pO1xuICAgICAgICBhd2FpdCB0aGlzLnlhcm4uaW5zdGFsbE9yUmVidWlsZCh0aGlzLiQuZGVza3RvcC5nZXRTZXR0aW5ncygpLmJ1aWxkZXJPcHRpb25zIHx8IHt9LFxuICAgICAgICAgICAgdGhpcy4kLmVudi5wYXRocy5lbGVjdHJvbkFwcC5yb290LCB0aGlzLmxhc3RSZWJ1aWxkLCBpbnN0YWxsKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYWxsYmFjayBpbnZva2VkIGJlZm9yZSBidWlsZCBpcyBtYWRlLiBFbnN1cmVzIHRoYXQgYXBwLmFzYXIgaGF2ZSB0aGUgcmlnaHQgcmVidWlsdFxuICAgICAqIG5vZGVfbW9kdWxlcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBjb250ZXh0XG4gICAgICogQHJldHVybnMge1Byb21pc2V9XG4gICAgICovXG4gICAgYmVmb3JlQnVpbGQoY29udGV4dCkge1xuICAgICAgICB0aGlzLmN1cnJlbnRDb250ZXh0ID0gT2JqZWN0LmFzc2lnbih7fSwgY29udGV4dCk7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBwbGF0Zm9ybU1hdGNoZXMgPSBwcm9jZXNzLnBsYXRmb3JtID09PSBjb250ZXh0LnBsYXRmb3JtLm5vZGVOYW1lO1xuICAgICAgICAgICAgY29uc3QgcmVidWlsZCA9IHBsYXRmb3JtTWF0Y2hlcyAmJiBjb250ZXh0LmFyY2ggIT09IHRoaXMubGFzdFJlYnVpbGQuYXJjaDtcbiAgICAgICAgICAgIGlmICghcGxhdGZvcm1NYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2cud2Fybignc2tpcHBpbmcgZGVwZW5kZW5jaWVzIHJlYnVpbGQgYmVjYXVzZSBwbGF0Zm9ybSBpcyBkaWZmZXJlbnQsIGlmIHlvdSBoYXZlIG5hdGl2ZSAnICtcbiAgICAgICAgICAgICAgICAgICAgJ25vZGUgbW9kdWxlcyBhcyB5b3VyIGFwcCBkZXBlbmRlbmNpZXMgeW91IHNob3VsZCBvZCB0aGUgYnVpbGQgb24gdGhlIHRhcmdldCBwbGF0Zm9ybSBvbmx5Jyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghcmVidWlsZCkge1xuICAgICAgICAgICAgICAgIHRoaXMubW92ZU5vZGVNb2R1bGVzT3V0KClcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGUgPT4gcmVqZWN0KGUpKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiBzZXRUaW1lb3V0KCgpID0+IHJlc29sdmUoZmFsc2UpLCAyMDAwKSk7XG4gICAgICAgICAgICAgICAgLy8gVGltZW91dCBoZWxwcyBvbiBXaW5kb3dzIHRvIGNsZWFyIHRoZSBmaWxlIGxvY2tzLlxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBMZXRzIHJlYnVpbGQgdGhlIG5vZGVfbW9kdWxlcyBmb3IgZGlmZmVyZW50IGFyY2guXG4gICAgICAgICAgICAgICAgdGhpcy5pbnN0YWxsT3JSZWJ1aWxkKGNvbnRleHQuYXJjaCwgY29udGV4dC5wbGF0Zm9ybS5ub2RlTmFtZSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGUgPT4gcmVqZWN0KGUpKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB0aGlzLiQuZWxlY3Ryb25BcHAuaW5zdGFsbExvY2FsTm9kZU1vZHVsZXMoY29udGV4dC5hcmNoKSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGUgPT4gcmVqZWN0KGUpKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiQuZWxlY3Ryb25BcHAuc2NhZmZvbGQuY3JlYXRlQXBwUm9vdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy4kLmVsZWN0cm9uQXBwLnNjYWZmb2xkLmNvcHlTa2VsZXRvbkFwcCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuJC5lbGVjdHJvbkFwcC5wYWNrU2tlbGV0b25Ub0FzYXIoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiQuZW52LnBhdGhzLmVsZWN0cm9uQXBwLm1ldGVvckFzYXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuJC5lbnYucGF0aHMuZWxlY3Ryb25BcHAuZGVza3RvcEFzYXIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuJC5lbnYucGF0aHMuZWxlY3Ryb25BcHAuZXh0cmFjdGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKGUgPT4gcmVqZWN0KGUpKVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB0aGlzLm1vdmVOb2RlTW9kdWxlc091dCgpKVxuICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZSA9PiByZWplY3QoZSkpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHJlc29sdmUoZmFsc2UpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2FsbGJhY2sgdG8gYmUgaW52b2tlZCBhZnRlciBwYWNraW5nLiBSZXN0b3JlcyBub2RlX21vZHVsZXMgdG8gdGhlIC5kZXNrdG9wLWJ1aWxkLlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlfVxuICAgICAqL1xuICAgIGFmdGVyUGFjayhjb250ZXh0KSB7XG4gICAgICAgIHRoaXMucGxhdGZvcm1zID0gdGhpcy5wbGF0Zm9ybXNcbiAgICAgICAgICAgIC5maWx0ZXIocGxhdGZvcm0gPT4gcGxhdGZvcm0gIT09IGNvbnRleHQuZWxlY3Ryb25QbGF0Zm9ybU5hbWUpO1xuICAgICAgICBpZiAodGhpcy5wbGF0Zm9ybXMubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHNoZWxsLmNvbmZpZy5mYXRhbCA9IHRydWU7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLiQudXRpbHMuZXhpc3RzKHRoaXMuJC5lbnYucGF0aHMuZWxlY3Ryb25BcHAuZXh0cmFjdGVkTm9kZU1vZHVsZXMpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2cuZGVidWcoJ2luamVjdGluZyBleHRyYWN0ZWQgbW9kdWxlcycpO1xuICAgICAgICAgICAgICAgIHNoZWxsLmNwKFxuICAgICAgICAgICAgICAgICAgICAnLVJmJyxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy4kLmVudi5wYXRocy5lbGVjdHJvbkFwcC5leHRyYWN0ZWROb2RlTW9kdWxlcyxcbiAgICAgICAgICAgICAgICAgICAgcGF0aC5qb2luKHRoaXMuZ2V0UGFja2FnZWRBcHBQYXRoKGNvbnRleHQpLCAnbm9kZV9tb2R1bGVzJylcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmxvZy5kZWJ1ZygnbW92aW5nIG5vZGVfbW9kdWxlcyBiYWNrJyk7XG4gICAgICAgICAgICAvLyBNb3ZlIG5vZGVfbW9kdWxlcyBiYWNrLlxuXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHNoZWxsLm12KFxuICAgICAgICAgICAgICAgICAgICB0aGlzLiQuZW52LnBhdGhzLmVsZWN0cm9uQXBwLnRtcE5vZGVNb2R1bGVzLFxuICAgICAgICAgICAgICAgICAgICB0aGlzLiQuZW52LnBhdGhzLmVsZWN0cm9uQXBwLm5vZGVNb2R1bGVzXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICBzaGVsbC5jb25maWcucmVzZXQoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuZmlyc3RQYXNzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5maXJzdFBhc3MgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMubG9nLmRlYnVnKCdub2RlX21vZHVsZXMgbW92ZWQgYmFjaycpO1xuXG4gICAgICAgICAgICB0aGlzLndhaXQoKVxuICAgICAgICAgICAgICAgIC5jYXRjaChlID0+IHJlamVjdChlKSlcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiByZXNvbHZlKCkpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGNvbW1hbmQga2lsbHMgb3JwaGFuZWQgTVNCdWlsZC5leGUgcHJvY2Vzc2VzLlxuICAgICAqIFNvbWV0aW1lIGFmdGVyIG5hdGl2ZSBub2RlX21vZHVsZXMgY29tcGlsYXRpb24gdGhleSBhcmUgc3RpbGwgd3JpdGluZyBzb21lIGxvZ3MsXG4gICAgICogcHJldmVudCBub2RlX21vZHVsZXMgZnJvbSBiZWluZyBkZWxldGVkLlxuICAgICAqL1xuICAgIGtpbGxNU0J1aWxkKCkge1xuICAgICAgICBpZiAodGhpcy5jdXJyZW50Q29udGV4dC5wbGF0Zm9ybS5ub2RlTmFtZSAhPT0gJ3dpbjMyJykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBvdXQgPSBzcGF3blxuICAgICAgICAgICAgICAgIC5zeW5jKFxuICAgICAgICAgICAgICAgICAgICAnd21pYycsXG4gICAgICAgICAgICAgICAgICAgIFsncHJvY2VzcycsICd3aGVyZScsICdjYXB0aW9uPVwiTVNCdWlsZC5leGVcIicsICdnZXQnLCAncHJvY2Vzc2lkJ11cbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgLnN0ZG91dC50b1N0cmluZygndXRmLTgnKVxuICAgICAgICAgICAgICAgIC5zcGxpdCgnXFxuJyk7XG5cbiAgICAgICAgICAgIGNvbnN0IHJlZ2V4ID0gbmV3IFJlZ0V4cCgvKFxcZCspLywgJ2dtJyk7XG4gICAgICAgICAgICAvLyBObyB3ZSB3aWxsIGNoZWNrIGZvciB0aG9zZSB3aXRoIHRoZSBtYXRjaGluZyBwYXJhbXMuXG4gICAgICAgICAgICBvdXQuZm9yRWFjaCgobGluZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IG1hdGNoID0gcmVnZXguZXhlYyhsaW5lKSB8fCBmYWxzZTtcbiAgICAgICAgICAgICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2cuZGVidWcoYGtpbGxpbmcgTVNCdWlsZC5leGUgYXQgcGlkOiAke21hdGNoWzFdfWApO1xuICAgICAgICAgICAgICAgICAgICBzcGF3bi5zeW5jKCd0YXNra2lsbCcsIFsnL3BpZCcsIG1hdGNoWzFdLCAnL2YnLCAnL3QnXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlZ2V4Lmxhc3RJbmRleCA9IDA7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgdGhpcy5sb2cuZGVidWcoJ2tpbGwgTVNCdWlsZCBmYWlsZWQnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHBhdGggdG8gcGFja2FnZWQgYXBwLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgZ2V0UGFja2FnZWRBcHBQYXRoKGNvbnRleHQgPSB7fSkge1xuICAgICAgICBpZiAodGhpcy5jdXJyZW50Q29udGV4dC5wbGF0Zm9ybS5ub2RlTmFtZSA9PT0gJ2RhcndpbicpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXRoLmpvaW4oXG4gICAgICAgICAgICAgICAgdGhpcy5pbnN0YWxsZXJEaXIsXG4gICAgICAgICAgICAgICAgJ21hYycsXG4gICAgICAgICAgICAgICAgYCR7Y29udGV4dC5wYWNrYWdlci5hcHBJbmZvLnByb2R1Y3RGaWxlbmFtZX0uYXBwYCxcbiAgICAgICAgICAgICAgICAnQ29udGVudHMnLCAnUmVzb3VyY2VzJywgJ2FwcCdcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcGxhdGZvcm1EaXIgPVxuICAgICAgICAgICAgYCR7dGhpcy5jdXJyZW50Q29udGV4dC5wbGF0Zm9ybS5ub2RlTmFtZSA9PT0gJ3dpbjMyJyA/ICd3aW4nIDogJ2xpbnV4J30tJHt0aGlzLmN1cnJlbnRDb250ZXh0LmFyY2ggPT09ICdpYTMyJyA/ICdpYTMyLScgOiAnJ311bnBhY2tlZGA7XG4gICAgICAgIHJldHVybiBwYXRoLmpvaW4oXG4gICAgICAgICAgICB0aGlzLmluc3RhbGxlckRpcixcbiAgICAgICAgICAgIHBsYXRmb3JtRGlyLFxuICAgICAgICAgICAgJ3Jlc291cmNlcycsICdhcHAnXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogT24gV2luZG93cyBpdCB3YWl0cyBmb3IgdGhlIGFwcC5hc2FyIGluIHRoZSBwYWNrZWQgYXBwIHRvIGJlIGZyZWUgKG5vIGZpbGUgbG9ja3MpLlxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHdhaXQoKSB7XG4gICAgICAgIGlmICh0aGlzLmN1cnJlbnRDb250ZXh0LnBsYXRmb3JtLm5vZGVOYW1lICE9PSAnd2luMzInKSB7XG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgYXBwQXNhclBhdGggPSBwYXRoLmpvaW4oXG4gICAgICAgICAgICB0aGlzLmdldFBhY2thZ2VkQXBwUGF0aCgpLFxuICAgICAgICAgICAgJ2FwcC5hc2FyJ1xuICAgICAgICApO1xuICAgICAgICBsZXQgcmV0cmllcyA9IDA7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgZnVuY3Rpb24gY2hlY2soKSB7XG4gICAgICAgICAgICAgICAgZnMub3BlbihhcHBBc2FyUGF0aCwgJ3IrJywgKGVyciwgZmQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0cmllcyArPSAxO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyLmNvZGUgIT09ICdFTk9FTlQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5sb2cuZGVidWcoYHdhaXRpbmcgZm9yIGFwcC5hc2FyIHRvIGJlIHJlYWRhYmxlLCAkeydjb2RlJyBpbiBlcnIgPyBgY3VycmVudGx5IHJlYWRpbmcgaXQgcmV0dXJucyAke2Vyci5jb2RlfWAgOiAnJ31gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmV0cmllcyA8IDYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiBjaGVjaygpLCA0MDAwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoYGZpbGUgaXMgbG9ja2VkOiAke2FwcEFzYXJQYXRofWApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnMuY2xvc2VTeW5jKGZkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2hlY2soKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJlcGFyZXMgdGhlIHRhcmdldCBvYmplY3QgcGFzc2VkIHRvIHRoZSBlbGVjdHJvbi1idWlsZGVyLlxuICAgICAqXG4gICAgICogQHJldHVybnMge01hcDxQbGF0Zm9ybSwgTWFwPEFyY2gsIEFycmF5PHN0cmluZz4+Pn1cbiAgICAgKi9cbiAgICBwcmVwYXJlVGFyZ2V0cygpIHtcbiAgICAgICAgbGV0IGFyY2ggPSB0aGlzLiQuZW52Lm9wdGlvbnMuaWEzMiA/ICdpYTMyJyA6ICd4NjQnO1xuICAgICAgICBhcmNoID0gdGhpcy4kLmVudi5vcHRpb25zLmFsbEFyY2hzID8gJ2FsbCcgOiBhcmNoO1xuXG4gICAgICAgIGNvbnN0IHRhcmdldHMgPSBbXTtcblxuICAgICAgICBpZiAodGhpcy4kLmVudi5vcHRpb25zLndpbikge1xuICAgICAgICAgICAgdGFyZ2V0cy5wdXNoKHRoaXMuYnVpbGRlci5kZXBlbmRlbmN5LlBsYXRmb3JtLldJTkRPV1MpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLiQuZW52Lm9wdGlvbnMubGludXgpIHtcbiAgICAgICAgICAgIHRhcmdldHMucHVzaCh0aGlzLmJ1aWxkZXIuZGVwZW5kZW5jeS5QbGF0Zm9ybS5MSU5VWCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuJC5lbnYub3B0aW9ucy5tYWMpIHtcbiAgICAgICAgICAgIHRhcmdldHMucHVzaCh0aGlzLmJ1aWxkZXIuZGVwZW5kZW5jeS5QbGF0Zm9ybS5NQUMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRhcmdldHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICBpZiAodGhpcy4kLmVudi5vcy5pc1dpbmRvd3MpIHtcbiAgICAgICAgICAgICAgICB0YXJnZXRzLnB1c2godGhpcy5idWlsZGVyLmRlcGVuZGVuY3kuUGxhdGZvcm0uV0lORE9XUyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuJC5lbnYub3MuaXNMaW51eCkge1xuICAgICAgICAgICAgICAgIHRhcmdldHMucHVzaCh0aGlzLmJ1aWxkZXIuZGVwZW5kZW5jeS5QbGF0Zm9ybS5MSU5VWCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRhcmdldHMucHVzaCh0aGlzLmJ1aWxkZXIuZGVwZW5kZW5jeS5QbGF0Zm9ybS5NQUMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmJ1aWxkZXIuZGVwZW5kZW5jeS5jcmVhdGVUYXJnZXRzKHRhcmdldHMsIG51bGwsIGFyY2gpO1xuICAgIH1cblxuICAgIGFzeW5jIGJ1aWxkKCkge1xuICAgICAgICBjb25zdCBzZXR0aW5ncyA9IHRoaXMuJC5kZXNrdG9wLmdldFNldHRpbmdzKCk7XG4gICAgICAgIGlmICghKCdidWlsZGVyT3B0aW9ucycgaW4gc2V0dGluZ3MpKSB7XG4gICAgICAgICAgICB0aGlzLmxvZy5lcnJvcihcbiAgICAgICAgICAgICAgICAnbm8gYnVpbGRlck9wdGlvbnMgaW4gc2V0dGluZ3MuanNvbiwgYWJvcnRpbmcnXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcHJvY2Vzcy5leGl0KDEpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYnVpbGRlck9wdGlvbnMgPSBPYmplY3QuYXNzaWduKHt9LCBzZXR0aW5ncy5idWlsZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgYnVpbGRlck9wdGlvbnMuYXNhciA9IGZhbHNlO1xuICAgICAgICBidWlsZGVyT3B0aW9ucy5ucG1SZWJ1aWxkID0gdHJ1ZTtcblxuICAgICAgICBidWlsZGVyT3B0aW9ucy5iZWZvcmVCdWlsZCA9IHRoaXMuYmVmb3JlQnVpbGQuYmluZCh0aGlzKTtcbiAgICAgICAgYnVpbGRlck9wdGlvbnMuYWZ0ZXJQYWNrID0gdGhpcy5hZnRlclBhY2suYmluZCh0aGlzKTtcbiAgICAgICAgYnVpbGRlck9wdGlvbnMuZWxlY3Ryb25WZXJzaW9uID0gdGhpcy4kLmdldEVsZWN0cm9uVmVyc2lvbigpO1xuXG4gICAgICAgIGJ1aWxkZXJPcHRpb25zLmRpcmVjdG9yaWVzID0ge1xuICAgICAgICAgICAgYXBwOiB0aGlzLiQuZW52LnBhdGhzLmVsZWN0cm9uQXBwLnJvb3QsXG4gICAgICAgICAgICBvdXRwdXQ6IHBhdGguam9pbih0aGlzLiQuZW52Lm9wdGlvbnMub3V0cHV0LCB0aGlzLiQuZW52LnBhdGhzLmluc3RhbGxlckRpcilcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAoJ21hYycgaW4gYnVpbGRlck9wdGlvbnMgJiYgJ3RhcmdldCcgaW4gYnVpbGRlck9wdGlvbnMubWFjKSB7XG4gICAgICAgICAgICBpZiAoYnVpbGRlck9wdGlvbnMubWFjLnRhcmdldC5pbmNsdWRlcygnbWFzJykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnBsYXRmb3JtcyA9IFsnZGFyd2luJywgJ21hcyddO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHRoaXMubG9nLmRlYnVnKCdjYWxsaW5nIGJ1aWxkIGZyb20gZWxlY3Ryb24tYnVpbGRlcicpO1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5idWlsZGVyLmRlcGVuZGVuY3kuYnVpbGQoT2JqZWN0LmFzc2lnbih7XG4gICAgICAgICAgICAgICAgdGFyZ2V0czogdGhpcy5wcmVwYXJlVGFyZ2V0cygpLFxuICAgICAgICAgICAgICAgIGNvbmZpZzogYnVpbGRlck9wdGlvbnNcbiAgICAgICAgICAgIH0sIHNldHRpbmdzLmJ1aWxkZXJDbGlPcHRpb25zKSk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLiQudXRpbHMuZXhpc3RzKHRoaXMuJC5lbnYucGF0aHMuZWxlY3Ryb25BcHAuZXh0cmFjdGVkTm9kZU1vZHVsZXMpKSB7XG4gICAgICAgICAgICAgICAgc2hlbGwucm0oJy1yZicsIHRoaXMuJC5lbnYucGF0aHMuZWxlY3Ryb25BcHAuZXh0cmFjdGVkTm9kZU1vZHVsZXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICB0aGlzLmxvZy5lcnJvcignZXJyb3Igd2hpbGUgYnVpbGRpbmcgaW5zdGFsbGVyOiAnLCBlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1vdmVzIG5vZGVfbW9kdWxlcyBvdXQgb2YgdGhlIGFwcCBiZWNhdXNlIHdoaWxlIHRoZSBhcHAgd2lsbCBiZSBwYWNrYWdlZFxuICAgICAqIHdlIGRvIG5vdCB3YW50IGl0IHRvIGJlIHRoZXJlLlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPGFueT59XG4gICAgICovXG4gICAgbW92ZU5vZGVNb2R1bGVzT3V0KCkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5sb2cuZGVidWcoJ21vdmluZyBub2RlX21vZHVsZXMgb3V0LCBiZWNhdXNlIHdlIGhhdmUgdGhlbSBhbHJlYWR5IGluJyArXG4gICAgICAgICAgICAgICAgJyBhcHAuYXNhcicpO1xuICAgICAgICAgICAgdGhpcy5raWxsTVNCdWlsZCgpO1xuICAgICAgICAgICAgcmVtb3ZlRGlyKHRoaXMuJC5lbnYucGF0aHMuZWxlY3Ryb25BcHAudG1wTm9kZU1vZHVsZXMpXG4gICAgICAgICAgICAgICAgLmNhdGNoKGUgPT4gcmVqZWN0KGUpKVxuICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgc2hlbGwuY29uZmlnLmZhdGFsID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgc2hlbGwuY29uZmlnLnZlcmJvc2UgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2hlbGwubXYoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy4kLmVudi5wYXRocy5lbGVjdHJvbkFwcC5ub2RlTW9kdWxlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiQuZW52LnBhdGhzLmVsZWN0cm9uQXBwLnRtcE5vZGVNb2R1bGVzXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2hlbGwuY29uZmlnLnJlc2V0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy53YWl0KCk7XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNoZWxsLmNvbmZpZy5yZXNldCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goZSA9PiByZWplY3QoZSkpXG4gICAgICAgICAgICAgICAgLnRoZW4oKCkgPT4gcmVtb3ZlRGlyKHRoaXMuJC5lbnYucGF0aHMuZWxlY3Ryb25BcHAubm9kZU1vZHVsZXMsIDEwMDApKVxuICAgICAgICAgICAgICAgIC5jYXRjaChlID0+IHJlamVjdChlKSlcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB0aGlzLndhaXQoKSlcbiAgICAgICAgICAgICAgICAuY2F0Y2gocmVqZWN0KVxuICAgICAgICAgICAgICAgIC50aGVuKHJlc29sdmUpO1xuICAgICAgICB9KTtcbiAgICB9XG59XG4iXX0=