UNPKG

@sharekey/meteor-desktop

Version:

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

231 lines (216 loc) 27 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 _fs = _interopRequireDefault(require("fs")); var _path = _interopRequireDefault(require("path")); var _log = _interopRequireDefault(require("./log")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // eslint-disable-next-line no-unused-vars _shelljs.default.config.fatal = true; /** * Checks if the path is empty. * @param {string} searchPath * @returns {boolean} */ function isEmptySync(searchPath) { let stat; try { stat = _fs.default.statSync(searchPath); } catch (e) { return true; } if (stat.isDirectory()) { const items = _fs.default.readdirSync(searchPath); return !items || !items.length; } return false; } /** * Represents the .desktop directory. * @class * @property {desktopSettings} settings */ class Desktop { /** * @param {MeteorDesktop} $ - context * * @constructor */ constructor($) { this.$ = $; this.log = new _log.default('desktop'); this.settings = null; this.dependencies = null; } /** * Tries to read and returns settings.json contents from .desktop dir. * * @returns {desktopSettings|null} */ getSettings() { if (!this.settings) { try { this.settings = JSON.parse(_fs.default.readFileSync(this.$.env.paths.desktop.settings, 'UTF-8')); } catch (e) { this.log.error('error while trying to read \'.desktop/settings.json\': ', e); process.exit(1); } } return this.settings; } /** * Returns a version hash representing current .desktop contents. * @returns {string} */ async getHashVersion() { this.log.info('calculating hash version from .desktop contents'); const version = await this.$.utils.readFilesAndComputeHash(this.$.env.paths.desktop.root); this.log.verbose(`calculated .desktop hash version is ${version.hash}`); return version.hash; } /** * Tries to read a module.json file from a module at provided path. * * @param {string} modulePath - path to the module dir * @returns {Object} */ getModuleConfig(modulePath) { let moduleConfig = {}; try { moduleConfig = JSON.parse(_fs.default.readFileSync(_path.default.join(modulePath, 'module.json'), 'UTF-8')); } catch (e) { this.log.error(`error while trying to read 'module.json' from '${modulePath}' module: `, e); process.exit(1); } if (!('name' in moduleConfig)) { this.log.error(`no 'name' field defined in 'module.json' in '${modulePath}' module.`); process.exit(1); } return moduleConfig; } /** * Scans all modules for module.json and gathers this configuration altogether. * * @returns {[]} */ gatherModuleConfigs() { const configs = []; if (!isEmptySync(this.$.env.paths.desktop.modules)) { _shelljs.default.ls('-d', _path.default.join(this.$.env.paths.desktop.modules, '*')).forEach(module => { if (_fs.default.lstatSync(module).isDirectory()) { const moduleConfig = this.getModuleConfig(module); moduleConfig.dirName = _path.default.parse(module).name; configs.push(moduleConfig); } }); } return configs; } /** * Summarizes all dependencies defined in .desktop. * * @params {Object} settings - settings.json * @params {boolean} checkModules - whether to gather modules dependencies * @params {boolean} refresh - recompute * @returns {{fromSettings: {}, plugins: {}, modules: {}}} */ getDependencies(settings = null, checkModules = true, refresh = false) { if (!refresh && this.dependencies) { return this.dependencies; } const dependencies = { fromSettings: {}, plugins: {}, modules: {} }; /** @type {desktopSettings} * */ const settingsJson = settings || this.getSettings(); // Settings can have a 'dependencies' field. if ('dependencies' in settingsJson) { dependencies.fromSettings = settingsJson.dependencies; } // Plugins are also a npm packages. if ('plugins' in settingsJson) { dependencies.plugins = Object.keys(settingsJson.plugins).reduce((plugins, plugin) => { /* eslint-disable no-param-reassign */ if (typeof settingsJson.plugins[plugin] === 'object') { plugins[plugin] = settingsJson.plugins[plugin].version; } else { plugins[plugin] = settingsJson.plugins[plugin]; } return plugins; }, {}); } // Each module can have its own dependencies defined. const moduleDependencies = {}; if (checkModules) { const configs = this.gatherModuleConfigs(); configs.forEach(moduleConfig => { if (!('dependencies' in moduleConfig)) { moduleConfig.dependencies = {}; } if (moduleConfig.name in moduleDependencies) { this.log.error(`duplicate name '${moduleConfig.name}' in 'module.json' in ` + `'${moduleConfig.dirName}' - another module already registered the same name.`); process.exit(1); } moduleDependencies[moduleConfig.name] = moduleConfig.dependencies; }); } dependencies.modules = moduleDependencies; this.dependencies = dependencies; return dependencies; } /** * Copies the .desktop scaffold into the meteor app dir. * Adds entry to .meteor/.gitignore. */ scaffold() { this.log.info('creating .desktop scaffold in your project'); if (this.$.utils.exists(this.$.env.paths.desktop.root)) { this.log.warn('.desktop already exists - delete it if you want a new one to be ' + 'created'); return; } _shelljs.default.cp('-r', this.$.env.paths.scaffold, this.$.env.paths.desktop.root); _shelljs.default.mkdir(this.$.env.paths.desktop.import); this.log.info('.desktop directory prepared'); } /** * Verifies if all mandatory files are present in the .desktop. * * @returns {boolean} */ check() { this.log.verbose('checking .desktop existence'); return !!(this.$.utils.exists(this.$.env.paths.desktop.root) && this.$.utils.exists(this.$.env.paths.desktop.settings) && this.$.utils.exists(this.$.env.paths.desktop.desktop)); } } /** * @typedef {Object} desktopSettings * @property {string} name * @property {string} projectName * @property {boolean} devTools * @property {boolean} devtron * @property {boolean} desktopHCP * @property {Object} desktopHCPSettings * @property {boolean} desktopHCPSettings.ignoreCompatibilityVersion * @property {boolean} desktopHCPSettings.blockAppUpdateOnDesktopIncompatibility * @property {number} webAppStartupTimeout * @property {Array} linkPackages * @property {Array} exposedModules * @property {Object} window * @property {Object} windowDev * @property {Object} packageJsonFields * @property {Object} builderOptions * @property {Object} builderCliOptions * @property {Object} packagerOptions * @property {Object} plugins * @property {Object} dependencies * @property {boolean} uglify * @property {string} version * */ exports.default = Desktop; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcnVudGltZSIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJyZXF1aXJlIiwiX3NoZWxsanMiLCJfZnMiLCJfcGF0aCIsIl9sb2ciLCJvYmoiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsInNoZWxsIiwiY29uZmlnIiwiZmF0YWwiLCJpc0VtcHR5U3luYyIsInNlYXJjaFBhdGgiLCJzdGF0IiwiZnMiLCJzdGF0U3luYyIsImUiLCJpc0RpcmVjdG9yeSIsIml0ZW1zIiwicmVhZGRpclN5bmMiLCJsZW5ndGgiLCJEZXNrdG9wIiwiY29uc3RydWN0b3IiLCIkIiwibG9nIiwiTG9nIiwic2V0dGluZ3MiLCJkZXBlbmRlbmNpZXMiLCJnZXRTZXR0aW5ncyIsIkpTT04iLCJwYXJzZSIsInJlYWRGaWxlU3luYyIsImVudiIsInBhdGhzIiwiZGVza3RvcCIsImVycm9yIiwicHJvY2VzcyIsImV4aXQiLCJnZXRIYXNoVmVyc2lvbiIsImluZm8iLCJ2ZXJzaW9uIiwidXRpbHMiLCJyZWFkRmlsZXNBbmRDb21wdXRlSGFzaCIsInJvb3QiLCJ2ZXJib3NlIiwiaGFzaCIsImdldE1vZHVsZUNvbmZpZyIsIm1vZHVsZVBhdGgiLCJtb2R1bGVDb25maWciLCJwYXRoIiwiam9pbiIsImdhdGhlck1vZHVsZUNvbmZpZ3MiLCJjb25maWdzIiwibW9kdWxlcyIsImxzIiwiZm9yRWFjaCIsIm1vZHVsZSIsImxzdGF0U3luYyIsImRpck5hbWUiLCJuYW1lIiwicHVzaCIsImdldERlcGVuZGVuY2llcyIsImNoZWNrTW9kdWxlcyIsInJlZnJlc2giLCJmcm9tU2V0dGluZ3MiLCJwbHVnaW5zIiwic2V0dGluZ3NKc29uIiwiT2JqZWN0Iiwia2V5cyIsInJlZHVjZSIsInBsdWdpbiIsIm1vZHVsZURlcGVuZGVuY2llcyIsInNjYWZmb2xkIiwiZXhpc3RzIiwid2FybiIsImNwIiwibWtkaXIiLCJpbXBvcnQiLCJjaGVjayIsImV4cG9ydHMiXSwic291cmNlcyI6WyIuLi9saWIvZGVza3RvcC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW51c2VkLXZhcnNcbmltcG9ydCByZWdlbmVyYXRvclJ1bnRpbWUgZnJvbSAncmVnZW5lcmF0b3ItcnVudGltZS9ydW50aW1lJztcbmltcG9ydCBzaGVsbCBmcm9tICdzaGVsbGpzJztcbmltcG9ydCBmcyBmcm9tICdmcyc7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcblxuaW1wb3J0IExvZyBmcm9tICcuL2xvZyc7XG5cbnNoZWxsLmNvbmZpZy5mYXRhbCA9IHRydWU7XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBwYXRoIGlzIGVtcHR5LlxuICogQHBhcmFtIHtzdHJpbmd9IHNlYXJjaFBhdGhcbiAqIEByZXR1cm5zIHtib29sZWFufVxuICovXG5mdW5jdGlvbiBpc0VtcHR5U3luYyhzZWFyY2hQYXRoKSB7XG4gICAgbGV0IHN0YXQ7XG4gICAgdHJ5IHtcbiAgICAgICAgc3RhdCA9IGZzLnN0YXRTeW5jKHNlYXJjaFBhdGgpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmIChzdGF0LmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgY29uc3QgaXRlbXMgPSBmcy5yZWFkZGlyU3luYyhzZWFyY2hQYXRoKTtcbiAgICAgICAgcmV0dXJuICFpdGVtcyB8fCAhaXRlbXMubGVuZ3RoO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbi8qKlxuICogUmVwcmVzZW50cyB0aGUgLmRlc2t0b3AgZGlyZWN0b3J5LlxuICogQGNsYXNzXG4gKiBAcHJvcGVydHkge2Rlc2t0b3BTZXR0aW5nc30gc2V0dGluZ3NcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgRGVza3RvcCB7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIHtNZXRlb3JEZXNrdG9wfSAkIC0gY29udGV4dFxuICAgICAqXG4gICAgICogQGNvbnN0cnVjdG9yXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoJCkge1xuICAgICAgICB0aGlzLiQgPSAkO1xuICAgICAgICB0aGlzLmxvZyA9IG5ldyBMb2coJ2Rlc2t0b3AnKTtcbiAgICAgICAgdGhpcy5zZXR0aW5ncyA9IG51bGw7XG4gICAgICAgIHRoaXMuZGVwZW5kZW5jaWVzID0gbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUcmllcyB0byByZWFkIGFuZCByZXR1cm5zIHNldHRpbmdzLmpzb24gY29udGVudHMgZnJvbSAuZGVza3RvcCBkaXIuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7ZGVza3RvcFNldHRpbmdzfG51bGx9XG4gICAgICovXG4gICAgZ2V0U2V0dGluZ3MoKSB7XG4gICAgICAgIGlmICghdGhpcy5zZXR0aW5ncykge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzID0gSlNPTi5wYXJzZShcbiAgICAgICAgICAgICAgICAgICAgZnMucmVhZEZpbGVTeW5jKHRoaXMuJC5lbnYucGF0aHMuZGVza3RvcC5zZXR0aW5ncywgJ1VURi04JylcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIHRoaXMubG9nLmVycm9yKCdlcnJvciB3aGlsZSB0cnlpbmcgdG8gcmVhZCBcXCcuZGVza3RvcC9zZXR0aW5ncy5qc29uXFwnOiAnLCBlKTtcbiAgICAgICAgICAgICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuc2V0dGluZ3M7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyBhIHZlcnNpb24gaGFzaCByZXByZXNlbnRpbmcgY3VycmVudCAuZGVza3RvcCBjb250ZW50cy5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIGFzeW5jIGdldEhhc2hWZXJzaW9uKCkge1xuICAgICAgICB0aGlzLmxvZy5pbmZvKCdjYWxjdWxhdGluZyBoYXNoIHZlcnNpb24gZnJvbSAuZGVza3RvcCBjb250ZW50cycpO1xuXG4gICAgICAgIGNvbnN0IHZlcnNpb24gPSBhd2FpdCB0aGlzLiQudXRpbHMucmVhZEZpbGVzQW5kQ29tcHV0ZUhhc2godGhpcy4kLmVudi5wYXRocy5kZXNrdG9wLnJvb3QpO1xuXG4gICAgICAgIHRoaXMubG9nLnZlcmJvc2UoYGNhbGN1bGF0ZWQgLmRlc2t0b3AgaGFzaCB2ZXJzaW9uIGlzICR7dmVyc2lvbi5oYXNofWApO1xuICAgICAgICByZXR1cm4gdmVyc2lvbi5oYXNoO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRyaWVzIHRvIHJlYWQgYSBtb2R1bGUuanNvbiBmaWxlIGZyb20gYSBtb2R1bGUgYXQgcHJvdmlkZWQgcGF0aC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtb2R1bGVQYXRoIC0gcGF0aCB0byB0aGUgbW9kdWxlIGRpclxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9XG4gICAgICovXG4gICAgZ2V0TW9kdWxlQ29uZmlnKG1vZHVsZVBhdGgpIHtcbiAgICAgICAgbGV0IG1vZHVsZUNvbmZpZyA9IHt9O1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgbW9kdWxlQ29uZmlnID0gSlNPTi5wYXJzZShcbiAgICAgICAgICAgICAgICBmcy5yZWFkRmlsZVN5bmMocGF0aC5qb2luKG1vZHVsZVBhdGgsICdtb2R1bGUuanNvbicpLCAnVVRGLTgnKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgdGhpcy5sb2cuZXJyb3IoXG4gICAgICAgICAgICAgICAgYGVycm9yIHdoaWxlIHRyeWluZyB0byByZWFkICdtb2R1bGUuanNvbicgZnJvbSAnJHttb2R1bGVQYXRofScgbW9kdWxlOiBgLFxuICAgICAgICAgICAgICAgIGVcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCEoJ25hbWUnIGluIG1vZHVsZUNvbmZpZykpIHtcbiAgICAgICAgICAgIHRoaXMubG9nLmVycm9yKGBubyAnbmFtZScgZmllbGQgZGVmaW5lZCBpbiAnbW9kdWxlLmpzb24nIGluICcke21vZHVsZVBhdGh9JyBtb2R1bGUuYCk7XG4gICAgICAgICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1vZHVsZUNvbmZpZztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTY2FucyBhbGwgbW9kdWxlcyBmb3IgbW9kdWxlLmpzb24gYW5kIGdhdGhlcnMgdGhpcyBjb25maWd1cmF0aW9uIGFsdG9nZXRoZXIuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7W119XG4gICAgICovXG4gICAgZ2F0aGVyTW9kdWxlQ29uZmlncygpIHtcbiAgICAgICAgY29uc3QgY29uZmlncyA9IFtdO1xuXG4gICAgICAgIGlmICghaXNFbXB0eVN5bmModGhpcy4kLmVudi5wYXRocy5kZXNrdG9wLm1vZHVsZXMpKSB7XG4gICAgICAgICAgICBzaGVsbC5scygnLWQnLCBwYXRoLmpvaW4odGhpcy4kLmVudi5wYXRocy5kZXNrdG9wLm1vZHVsZXMsICcqJykpLmZvckVhY2goXG4gICAgICAgICAgICAgICAgKG1vZHVsZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZnMubHN0YXRTeW5jKG1vZHVsZSkuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbW9kdWxlQ29uZmlnID0gdGhpcy5nZXRNb2R1bGVDb25maWcobW9kdWxlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vZHVsZUNvbmZpZy5kaXJOYW1lID0gcGF0aC5wYXJzZShtb2R1bGUpLm5hbWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25maWdzLnB1c2gobW9kdWxlQ29uZmlnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNvbmZpZ3M7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3VtbWFyaXplcyBhbGwgZGVwZW5kZW5jaWVzIGRlZmluZWQgaW4gLmRlc2t0b3AuXG4gICAgICpcbiAgICAgKiBAcGFyYW1zIHtPYmplY3R9IHNldHRpbmdzICAgICAgLSBzZXR0aW5ncy5qc29uXG4gICAgICogQHBhcmFtcyB7Ym9vbGVhbn0gY2hlY2tNb2R1bGVzIC0gd2hldGhlciB0byBnYXRoZXIgbW9kdWxlcyBkZXBlbmRlbmNpZXNcbiAgICAgKiBAcGFyYW1zIHtib29sZWFufSByZWZyZXNoICAgICAgLSByZWNvbXB1dGVcbiAgICAgKiBAcmV0dXJucyB7e2Zyb21TZXR0aW5nczoge30sIHBsdWdpbnM6IHt9LCBtb2R1bGVzOiB7fX19XG4gICAgICovXG4gICAgZ2V0RGVwZW5kZW5jaWVzKHNldHRpbmdzID0gbnVsbCwgY2hlY2tNb2R1bGVzID0gdHJ1ZSwgcmVmcmVzaCA9IGZhbHNlKSB7XG4gICAgICAgIGlmICghcmVmcmVzaCAmJiB0aGlzLmRlcGVuZGVuY2llcykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVwZW5kZW5jaWVzO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZGVwZW5kZW5jaWVzID0ge1xuICAgICAgICAgICAgZnJvbVNldHRpbmdzOiB7fSxcbiAgICAgICAgICAgIHBsdWdpbnM6IHt9LFxuICAgICAgICAgICAgbW9kdWxlczoge31cbiAgICAgICAgfTtcbiAgICAgICAgLyoqIEB0eXBlIHtkZXNrdG9wU2V0dGluZ3N9ICogKi9cbiAgICAgICAgY29uc3Qgc2V0dGluZ3NKc29uID0gc2V0dGluZ3MgfHwgdGhpcy5nZXRTZXR0aW5ncygpO1xuXG4gICAgICAgIC8vIFNldHRpbmdzIGNhbiBoYXZlIGEgJ2RlcGVuZGVuY2llcycgZmllbGQuXG4gICAgICAgIGlmICgnZGVwZW5kZW5jaWVzJyBpbiBzZXR0aW5nc0pzb24pIHtcbiAgICAgICAgICAgIGRlcGVuZGVuY2llcy5mcm9tU2V0dGluZ3MgPSBzZXR0aW5nc0pzb24uZGVwZW5kZW5jaWVzO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUGx1Z2lucyBhcmUgYWxzbyBhIG5wbSBwYWNrYWdlcy5cbiAgICAgICAgaWYgKCdwbHVnaW5zJyBpbiBzZXR0aW5nc0pzb24pIHtcbiAgICAgICAgICAgIGRlcGVuZGVuY2llcy5wbHVnaW5zID0gT2JqZWN0LmtleXMoc2V0dGluZ3NKc29uLnBsdWdpbnMpLnJlZHVjZSgocGx1Z2lucywgcGx1Z2luKSA9PiB7XG4gICAgICAgICAgICAgICAgLyogZXNsaW50LWRpc2FibGUgbm8tcGFyYW0tcmVhc3NpZ24gKi9cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHNldHRpbmdzSnNvbi5wbHVnaW5zW3BsdWdpbl0gPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgIHBsdWdpbnNbcGx1Z2luXSA9IHNldHRpbmdzSnNvbi5wbHVnaW5zW3BsdWdpbl0udmVyc2lvbjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBwbHVnaW5zW3BsdWdpbl0gPSBzZXR0aW5nc0pzb24ucGx1Z2luc1twbHVnaW5dO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcGx1Z2lucztcbiAgICAgICAgICAgIH0sIHt9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEVhY2ggbW9kdWxlIGNhbiBoYXZlIGl0cyBvd24gZGVwZW5kZW5jaWVzIGRlZmluZWQuXG4gICAgICAgIGNvbnN0IG1vZHVsZURlcGVuZGVuY2llcyA9IHt9O1xuICAgICAgICBpZiAoY2hlY2tNb2R1bGVzKSB7XG4gICAgICAgICAgICBjb25zdCBjb25maWdzID0gdGhpcy5nYXRoZXJNb2R1bGVDb25maWdzKCk7XG5cbiAgICAgICAgICAgIGNvbmZpZ3MuZm9yRWFjaChcbiAgICAgICAgICAgICAgICAobW9kdWxlQ29uZmlnKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKCdkZXBlbmRlbmNpZXMnIGluIG1vZHVsZUNvbmZpZykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vZHVsZUNvbmZpZy5kZXBlbmRlbmNpZXMgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAobW9kdWxlQ29uZmlnLm5hbWUgaW4gbW9kdWxlRGVwZW5kZW5jaWVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZy5lcnJvcihgZHVwbGljYXRlIG5hbWUgJyR7bW9kdWxlQ29uZmlnLm5hbWV9JyBpbiAnbW9kdWxlLmpzb24nIGluIGAgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGAnJHttb2R1bGVDb25maWcuZGlyTmFtZX0nIC0gYW5vdGhlciBtb2R1bGUgYWxyZWFkeSByZWdpc3RlcmVkIHRoZSBzYW1lIG5hbWUuYCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9jZXNzLmV4aXQoMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlRGVwZW5kZW5jaWVzW21vZHVsZUNvbmZpZy5uYW1lXSA9IG1vZHVsZUNvbmZpZy5kZXBlbmRlbmNpZXM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGRlcGVuZGVuY2llcy5tb2R1bGVzID0gbW9kdWxlRGVwZW5kZW5jaWVzO1xuICAgICAgICB0aGlzLmRlcGVuZGVuY2llcyA9IGRlcGVuZGVuY2llcztcbiAgICAgICAgcmV0dXJuIGRlcGVuZGVuY2llcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb3BpZXMgdGhlIC5kZXNrdG9wIHNjYWZmb2xkIGludG8gdGhlIG1ldGVvciBhcHAgZGlyLlxuICAgICAqIEFkZHMgZW50cnkgdG8gLm1ldGVvci8uZ2l0aWdub3JlLlxuICAgICAqL1xuICAgIHNjYWZmb2xkKCkge1xuICAgICAgICB0aGlzLmxvZy5pbmZvKCdjcmVhdGluZyAuZGVza3RvcCBzY2FmZm9sZCBpbiB5b3VyIHByb2plY3QnKTtcblxuICAgICAgICBpZiAodGhpcy4kLnV0aWxzLmV4aXN0cyh0aGlzLiQuZW52LnBhdGhzLmRlc2t0b3Aucm9vdCkpIHtcbiAgICAgICAgICAgIHRoaXMubG9nLndhcm4oJy5kZXNrdG9wIGFscmVhZHkgZXhpc3RzIC0gZGVsZXRlIGl0IGlmIHlvdSB3YW50IGEgbmV3IG9uZSB0byBiZSAnICtcbiAgICAgICAgICAgICAgICAnY3JlYXRlZCcpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgc2hlbGwuY3AoJy1yJywgdGhpcy4kLmVudi5wYXRocy5zY2FmZm9sZCwgdGhpcy4kLmVudi5wYXRocy5kZXNrdG9wLnJvb3QpO1xuICAgICAgICBzaGVsbC5ta2Rpcih0aGlzLiQuZW52LnBhdGhzLmRlc2t0b3AuaW1wb3J0KTtcbiAgICAgICAgdGhpcy5sb2cuaW5mbygnLmRlc2t0b3AgZGlyZWN0b3J5IHByZXBhcmVkJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVmVyaWZpZXMgaWYgYWxsIG1hbmRhdG9yeSBmaWxlcyBhcmUgcHJlc2VudCBpbiB0aGUgLmRlc2t0b3AuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBjaGVjaygpIHtcbiAgICAgICAgdGhpcy5sb2cudmVyYm9zZSgnY2hlY2tpbmcgLmRlc2t0b3AgZXhpc3RlbmNlJyk7XG4gICAgICAgIHJldHVybiAhISh0aGlzLiQudXRpbHMuZXhpc3RzKHRoaXMuJC5lbnYucGF0aHMuZGVza3RvcC5yb290KSAmJlxuICAgICAgICAgICAgdGhpcy4kLnV0aWxzLmV4aXN0cyh0aGlzLiQuZW52LnBhdGhzLmRlc2t0b3Auc2V0dGluZ3MpICYmXG4gICAgICAgICAgICB0aGlzLiQudXRpbHMuZXhpc3RzKHRoaXMuJC5lbnYucGF0aHMuZGVza3RvcC5kZXNrdG9wKSk7XG4gICAgfVxufVxuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IGRlc2t0b3BTZXR0aW5nc1xuICogQHByb3BlcnR5IHtzdHJpbmd9IG5hbWVcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBwcm9qZWN0TmFtZVxuICogQHByb3BlcnR5IHtib29sZWFufSBkZXZUb29sc1xuICogQHByb3BlcnR5IHtib29sZWFufSBkZXZ0cm9uXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IGRlc2t0b3BIQ1BcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBkZXNrdG9wSENQU2V0dGluZ3NcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gZGVza3RvcEhDUFNldHRpbmdzLmlnbm9yZUNvbXBhdGliaWxpdHlWZXJzaW9uXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IGRlc2t0b3BIQ1BTZXR0aW5ncy5ibG9ja0FwcFVwZGF0ZU9uRGVza3RvcEluY29tcGF0aWJpbGl0eVxuICogQHByb3BlcnR5IHtudW1iZXJ9IHdlYkFwcFN0YXJ0dXBUaW1lb3V0XG4gKiBAcHJvcGVydHkge0FycmF5fSBsaW5rUGFja2FnZXNcbiAqIEBwcm9wZXJ0eSB7QXJyYXl9IGV4cG9zZWRNb2R1bGVzXG4gKiBAcHJvcGVydHkge09iamVjdH0gd2luZG93XG4gKiBAcHJvcGVydHkge09iamVjdH0gd2luZG93RGV2XG4gKiBAcHJvcGVydHkge09iamVjdH0gcGFja2FnZUpzb25GaWVsZHNcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBidWlsZGVyT3B0aW9uc1xuICogQHByb3BlcnR5IHtPYmplY3R9IGJ1aWxkZXJDbGlPcHRpb25zXG4gKiBAcHJvcGVydHkge09iamVjdH0gcGFja2FnZXJPcHRpb25zXG4gKiBAcHJvcGVydHkge09iamVjdH0gcGx1Z2luc1xuICogQHByb3BlcnR5IHtPYmplY3R9IGRlcGVuZGVuY2llc1xuICogQHByb3BlcnR5IHtib29sZWFufSB1Z2xpZnlcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSB2ZXJz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