UNPKG

electron-compile

Version:

Electron supporting package to compile JS and CSS in Electron applications

479 lines (390 loc) 47.7 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.createCompilerHostFromProjectRoot = exports.createCompilerHostFromConfigFile = exports.createCompilerHostFromBabelRc = undefined; /** * Creates a compiler host from a .babelrc file. This method is usually called * from {@link createCompilerHostFromProjectRoot} instead of used directly. * * @param {string} file The path to a .babelrc file * * @param {string} rootCacheDir (optional) The directory to use as a cache. * * @return {Promise<CompilerHost>} A set-up compiler host */ let createCompilerHostFromBabelRc = exports.createCompilerHostFromBabelRc = (() => { var _ref = _asyncToGenerator(function* (file) { let rootCacheDir = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; let info = JSON.parse((yield _promise.pfs.readFile(file, 'utf8'))); // package.json if ('babel' in info) { info = info.babel; } if ('env' in info) { let ourEnv = process.env.BABEL_ENV || process.env.NODE_ENV || 'development'; info = info.env[ourEnv]; } // Are we still package.json (i.e. is there no babel info whatsoever?) if ('name' in info && 'version' in info) { return createCompilerHostFromConfiguration({ appRoot: _path2.default.dirname(file), options: getDefaultConfiguration(), rootCacheDir }); } return createCompilerHostFromConfiguration({ appRoot: _path2.default.dirname(file), options: { 'application/javascript': info }, rootCacheDir }); }); return function createCompilerHostFromBabelRc(_x3, _x4) { return _ref.apply(this, arguments); }; })(); /** * Creates a compiler host from a .compilerc file. This method is usually called * from {@link createCompilerHostFromProjectRoot} instead of used directly. * * @param {string} file The path to a .compilerc file * * @param {string} rootCacheDir (optional) The directory to use as a cache. * * @return {Promise<CompilerHost>} A set-up compiler host */ let createCompilerHostFromConfigFile = exports.createCompilerHostFromConfigFile = (() => { var _ref2 = _asyncToGenerator(function* (file) { let rootCacheDir = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; let info = JSON.parse((yield _promise.pfs.readFile(file, 'utf8'))); if ('env' in info) { let ourEnv = process.env.ELECTRON_COMPILE_ENV || process.env.NODE_ENV || 'development'; info = info.env[ourEnv]; } return createCompilerHostFromConfiguration({ appRoot: _path2.default.dirname(file), options: info, rootCacheDir }); }); return function createCompilerHostFromConfigFile(_x6, _x7) { return _ref2.apply(this, arguments); }; })(); /** * Creates a configured {@link CompilerHost} instance from the project root * directory. This method first searches for a .compilerc (or .compilerc.json), then falls back to the * default locations for Babel configuration info. If neither are found, defaults * to standard settings * * @param {string} rootDir The root application directory (i.e. the directory * that has the app's package.json) * * @param {string} rootCacheDir (optional) The directory to use as a cache. * * @return {Promise<CompilerHost>} A set-up compiler host */ let createCompilerHostFromProjectRoot = exports.createCompilerHostFromProjectRoot = (() => { var _ref3 = _asyncToGenerator(function* (rootDir) { let rootCacheDir = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; let compilerc = _path2.default.join(rootDir, '.compilerc'); if (statSyncNoException(compilerc)) { d(`Found a .compilerc at ${ compilerc }, using it`); return yield createCompilerHostFromConfigFile(compilerc, rootCacheDir); } compilerc += '.json'; if (statSyncNoException(compilerc)) { d(`Found a .compilerc at ${ compilerc }, using it`); return yield createCompilerHostFromConfigFile(compilerc, rootCacheDir); } let babelrc = _path2.default.join(rootDir, '.babelrc'); if (statSyncNoException(babelrc)) { d(`Found a .babelrc at ${ babelrc }, using it`); return yield createCompilerHostFromBabelRc(babelrc, rootCacheDir); } d(`Using package.json or default parameters at ${ rootDir }`); return yield createCompilerHostFromBabelRc(_path2.default.join(rootDir, 'package.json'), rootCacheDir); }); return function createCompilerHostFromProjectRoot(_x9, _x10) { return _ref3.apply(this, arguments); }; })(); exports.initializeGlobalHooks = initializeGlobalHooks; exports.init = init; exports.createCompilerHostFromConfiguration = createCompilerHostFromConfiguration; exports.createCompilerHostFromBabelRcSync = createCompilerHostFromBabelRcSync; exports.createCompilerHostFromConfigFileSync = createCompilerHostFromConfigFileSync; exports.createCompilerHostFromProjectRootSync = createCompilerHostFromProjectRootSync; exports.calculateDefaultCompileCacheDirectory = calculateDefaultCompileCacheDirectory; exports.getDefaultConfiguration = getDefaultConfiguration; exports.createCompilers = createCompilers; var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs); var _path = require('path'); var _path2 = _interopRequireDefault(_path); var _zlib = require('zlib'); var _zlib2 = _interopRequireDefault(_zlib); var _mkdirp = require('mkdirp'); var _mkdirp2 = _interopRequireDefault(_mkdirp); var _promise = require('./promise'); var _fileChangeCache = require('./file-change-cache'); var _fileChangeCache2 = _interopRequireDefault(_fileChangeCache); var _compilerHost = require('./compiler-host'); var _compilerHost2 = _interopRequireDefault(_compilerHost); var _requireHook = require('./require-hook'); var _requireHook2 = _interopRequireDefault(_requireHook); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } const d = require('debug-electron')('electron-compile:config-parser'); // NB: We intentionally delay-load this so that in production, you can create // cache-only versions of these compilers let allCompilerClasses = null; function statSyncNoException(fsPath) { if ('statSyncNoException' in _fs2.default) { return _fs2.default.statSyncNoException(fsPath); } try { return _fs2.default.statSync(fsPath); } catch (e) { return null; } } /** * Initialize the global hooks (protocol hook for file:, node.js hook) * independent of initializing the compiler. This method is usually called by * init instead of directly * * @param {CompilerHost} compilerHost The compiler host to use. * */ function initializeGlobalHooks(compilerHost) { let globalVar = global || window; globalVar.globalCompilerHost = compilerHost; (0, _requireHook2.default)(compilerHost); if ('type' in process && process.type === 'browser') { var _require = require('electron'); const app = _require.app; var _require2 = require('./protocol-hook'); const initializeProtocolHook = _require2.initializeProtocolHook; let protoify = function () { initializeProtocolHook(compilerHost); }; if (app.isReady()) { protoify(); } else { app.on('ready', protoify); } } } /** * Initialize electron-compile and set it up, either for development or * production use. This is almost always the only method you need to use in order * to use electron-compile. * * @param {string} appRoot The top-level directory for your application (i.e. * the one which has your package.json). * * @param {string} mainModule The module to require in, relative to the module * calling init, that will start your app. Write this * as if you were writing a require call from here. * * @param {bool} productionMode If explicitly True/False, will set read-only * mode to be disabled/enabled. If not, we'll * guess based on the presence of a production * cache. * * @param {string} cacheDir If not passed in, read-only will look in * `appRoot/.cache` and dev mode will compile to a * temporary directory. If it is passed in, both modes * will cache to/from `appRoot/{cacheDir}` */ function init(appRoot, mainModule) { let productionMode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; let cacheDir = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; let compilerHost = null; let rootCacheDir = _path2.default.join(appRoot, cacheDir || '.cache'); if (productionMode === null) { productionMode = !!statSyncNoException(rootCacheDir); } if (productionMode) { compilerHost = _compilerHost2.default.createReadonlyFromConfigurationSync(rootCacheDir, appRoot); } else { // if cacheDir was passed in, pass it along. Otherwise, default to a tempdir. if (cacheDir) { compilerHost = createCompilerHostFromProjectRootSync(appRoot, rootCacheDir); } else { compilerHost = createCompilerHostFromProjectRootSync(appRoot); } } initializeGlobalHooks(compilerHost); require.main.require(mainModule); } /** * Creates a {@link CompilerHost} with the given information. This method is * usually called by {@link createCompilerHostFromProjectRoot}. * * @private */ function createCompilerHostFromConfiguration(info) { let compilers = createCompilers(); let rootCacheDir = info.rootCacheDir || calculateDefaultCompileCacheDirectory(); d(`Creating CompilerHost: ${ JSON.stringify(info) }, rootCacheDir = ${ rootCacheDir }`); let fileChangeCache = new _fileChangeCache2.default(info.appRoot); let compilerInfo = _path2.default.join(rootCacheDir, 'compiler-info.json.gz'); if (_fs2.default.existsSync(compilerInfo)) { let buf = _fs2.default.readFileSync(compilerInfo); let json = JSON.parse(_zlib2.default.gunzipSync(buf)); fileChangeCache = _fileChangeCache2.default.loadFromData(json.fileChangeCache, info.appRoot, false); } Object.keys(info.options || {}).forEach(x => { let opts = info.options[x]; if (!(x in compilers)) { throw new Error(`Found compiler settings for missing compiler: ${ x }`); } // NB: Let's hope this isn't a valid compiler option... if (opts.passthrough) { compilers[x] = compilers['text/plain']; delete opts.passthrough; } d(`Setting options for ${ x }: ${ JSON.stringify(opts) }`); compilers[x].compilerOptions = opts; }); let ret = new _compilerHost2.default(rootCacheDir, compilers, fileChangeCache, false, compilers['text/plain']); // NB: It's super important that we guarantee that the configuration is saved // out, because we'll need to re-read it in the renderer process d(`Created compiler host with options: ${ JSON.stringify(info) }`); ret.saveConfigurationSync(); return ret; }function createCompilerHostFromBabelRcSync(file) { let rootCacheDir = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; let info = JSON.parse(_fs2.default.readFileSync(file, 'utf8')); // package.json if ('babel' in info) { info = info.babel; } if ('env' in info) { let ourEnv = process.env.BABEL_ENV || process.env.NODE_ENV || 'development'; info = info.env[ourEnv]; } // Are we still package.json (i.e. is there no babel info whatsoever?) if ('name' in info && 'version' in info) { return createCompilerHostFromConfiguration({ appRoot: _path2.default.dirname(file), options: getDefaultConfiguration(), rootCacheDir }); } return createCompilerHostFromConfiguration({ appRoot: _path2.default.dirname(file), options: { 'application/javascript': info }, rootCacheDir }); } function createCompilerHostFromConfigFileSync(file) { let rootCacheDir = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; let info = JSON.parse(_fs2.default.readFileSync(file, 'utf8')); if ('env' in info) { let ourEnv = process.env.ELECTRON_COMPILE_ENV || process.env.NODE_ENV || 'development'; info = info.env[ourEnv]; } return createCompilerHostFromConfiguration({ appRoot: _path2.default.dirname(file), options: info, rootCacheDir }); } function createCompilerHostFromProjectRootSync(rootDir) { let rootCacheDir = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; let compilerc = _path2.default.join(rootDir, '.compilerc'); if (statSyncNoException(compilerc)) { d(`Found a .compilerc at ${ compilerc }, using it`); return createCompilerHostFromConfigFileSync(compilerc, rootCacheDir); } let babelrc = _path2.default.join(rootDir, '.babelrc'); if (statSyncNoException(babelrc)) { d(`Found a .babelrc at ${ babelrc }, using it`); return createCompilerHostFromBabelRcSync(babelrc, rootCacheDir); } d(`Using package.json or default parameters at ${ rootDir }`); return createCompilerHostFromBabelRcSync(_path2.default.join(rootDir, 'package.json'), rootCacheDir); } /** * Returns what electron-compile would use as a default rootCacheDir. Usually only * used for debugging purposes * * @return {string} A path that may or may not exist where electron-compile would * set up a development mode cache. */ function calculateDefaultCompileCacheDirectory() { let tmpDir = process.env.TEMP || process.env.TMPDIR || '/tmp'; let hash = require('crypto').createHash('md5').update(process.execPath).digest('hex'); let cacheDir = _path2.default.join(tmpDir, `compileCache_${ hash }`); _mkdirp2.default.sync(cacheDir); d(`Using default cache directory: ${ cacheDir }`); return cacheDir; } /** * Returns the default .configrc if no configuration information can be found. * * @return {Object} A list of default config settings for electron-compiler. */ function getDefaultConfiguration() { return { 'application/javascript': { "presets": ["es2016-node5", "react"], "sourceMaps": "inline" } }; } /** * Allows you to create new instances of all compilers that are supported by * electron-compile and use them directly. Currently supports Babel, CoffeeScript, * TypeScript, Less, and Jade. * * @return {Object} An Object whose Keys are MIME types, and whose values * are instances of @{link CompilerBase}. */ function createCompilers() { if (!allCompilerClasses) { // First we want to see if electron-compilers itself has been installed with // devDependencies. If that's not the case, check to see if // electron-compilers is installed as a peer dependency (probably as a // devDependency of the root project). const locations = ['electron-compilers', '../../electron-compilers']; for (let location of locations) { try { allCompilerClasses = require(location); } catch (e) { // Yolo } } if (!allCompilerClasses) { throw new Error("Electron compilers not found but were requested to be loaded"); } } // NB: Note that this code is carefully set up so that InlineHtmlCompiler // (i.e. classes with `createFromCompilers`) initially get an empty object, // but will have a reference to the final result of what we return, which // resolves the circular dependency we'd otherwise have here. let ret = {}; let instantiatedClasses = allCompilerClasses.map(Klass => { if ('createFromCompilers' in Klass) { return Klass.createFromCompilers(ret); } else { return new Klass(); } }); instantiatedClasses.reduce((acc, x) => { let Klass = Object.getPrototypeOf(x).constructor; for (let type of Klass.getInputMimeTypes()) { acc[type] = x; } return acc; }, ret); return ret; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9jb25maWctcGFyc2VyLmpzIl0sIm5hbWVzIjpbImZpbGUiLCJyb290Q2FjaGVEaXIiLCJpbmZvIiwiSlNPTiIsInBhcnNlIiwicmVhZEZpbGUiLCJiYWJlbCIsIm91ckVudiIsInByb2Nlc3MiLCJlbnYiLCJCQUJFTF9FTlYiLCJOT0RFX0VOViIsImNyZWF0ZUNvbXBpbGVySG9zdEZyb21Db25maWd1cmF0aW9uIiwiYXBwUm9vdCIsImRpcm5hbWUiLCJvcHRpb25zIiwiZ2V0RGVmYXVsdENvbmZpZ3VyYXRpb24iLCJjcmVhdGVDb21waWxlckhvc3RGcm9tQmFiZWxSYyIsIkVMRUNUUk9OX0NPTVBJTEVfRU5WIiwiY3JlYXRlQ29tcGlsZXJIb3N0RnJvbUNvbmZpZ0ZpbGUiLCJyb290RGlyIiwiY29tcGlsZXJjIiwiam9pbiIsInN0YXRTeW5jTm9FeGNlcHRpb24iLCJkIiwiYmFiZWxyYyIsImNyZWF0ZUNvbXBpbGVySG9zdEZyb21Qcm9qZWN0Um9vdCIsImluaXRpYWxpemVHbG9iYWxIb29rcyIsImluaXQiLCJjcmVhdGVDb21waWxlckhvc3RGcm9tQmFiZWxSY1N5bmMiLCJjcmVhdGVDb21waWxlckhvc3RGcm9tQ29uZmlnRmlsZVN5bmMiLCJjcmVhdGVDb21waWxlckhvc3RGcm9tUHJvamVjdFJvb3RTeW5jIiwiY2FsY3VsYXRlRGVmYXVsdENvbXBpbGVDYWNoZURpcmVjdG9yeSIsImNyZWF0ZUNvbXBpbGVycyIsInJlcXVpcmUiLCJhbGxDb21waWxlckNsYXNzZXMiLCJmc1BhdGgiLCJzdGF0U3luYyIsImUiLCJjb21waWxlckhvc3QiLCJnbG9iYWxWYXIiLCJnbG9iYWwiLCJ3aW5kb3ciLCJnbG9iYWxDb21waWxlckhvc3QiLCJ0eXBlIiwiYXBwIiwiaW5pdGlhbGl6ZVByb3RvY29sSG9vayIsInByb3RvaWZ5IiwiaXNSZWFkeSIsIm9uIiwibWFpbk1vZHVsZSIsInByb2R1Y3Rpb25Nb2RlIiwiY2FjaGVEaXIiLCJjcmVhdGVSZWFkb25seUZyb21Db25maWd1cmF0aW9uU3luYyIsIm1haW4iLCJjb21waWxlcnMiLCJzdHJpbmdpZnkiLCJmaWxlQ2hhbmdlQ2FjaGUiLCJjb21waWxlckluZm8iLCJleGlzdHNTeW5jIiwiYnVmIiwicmVhZEZpbGVTeW5jIiwianNvbiIsImd1bnppcFN5bmMiLCJsb2FkRnJvbURhdGEiLCJPYmplY3QiLCJrZXlzIiwiZm9yRWFjaCIsIngiLCJvcHRzIiwiRXJyb3IiLCJwYXNzdGhyb3VnaCIsImNvbXBpbGVyT3B0aW9ucyIsInJldCIsInNhdmVDb25maWd1cmF0aW9uU3luYyIsInRtcERpciIsIlRFTVAiLCJUTVBESVIiLCJoYXNoIiwiY3JlYXRlSGFzaCIsInVwZGF0ZSIsImV4ZWNQYXRoIiwiZGlnZXN0Iiwic3luYyIsImxvY2F0aW9ucyIsImxvY2F0aW9uIiwiaW5zdGFudGlhdGVkQ2xhc3NlcyIsIm1hcCIsIktsYXNzIiwiY3JlYXRlRnJvbUNvbXBpbGVycyIsInJlZHVjZSIsImFjYyIsImdldFByb3RvdHlwZU9mIiwiY29uc3RydWN0b3IiLCJnZXRJbnB1dE1pbWVUeXBlcyJdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQXFKQTs7Ozs7Ozs7Ozs7K0JBVU8sV0FBNkNBLElBQTdDLEVBQXNFO0FBQUEsUUFBbkJDLFlBQW1CLHVFQUFOLElBQU07O0FBQzNFLFFBQUlDLE9BQU9DLEtBQUtDLEtBQUwsRUFBVyxNQUFNLGFBQUlDLFFBQUosQ0FBYUwsSUFBYixFQUFtQixNQUFuQixDQUFqQixFQUFYOztBQUVBO0FBQ0EsUUFBSSxXQUFXRSxJQUFmLEVBQXFCO0FBQ25CQSxhQUFPQSxLQUFLSSxLQUFaO0FBQ0Q7O0FBRUQsUUFBSSxTQUFTSixJQUFiLEVBQW1CO0FBQ2pCLFVBQUlLLFNBQVNDLFFBQVFDLEdBQVIsQ0FBWUMsU0FBWixJQUF5QkYsUUFBUUMsR0FBUixDQUFZRSxRQUFyQyxJQUFpRCxhQUE5RDtBQUNBVCxhQUFPQSxLQUFLTyxHQUFMLENBQVNGLE1BQVQsQ0FBUDtBQUNEOztBQUVEO0FBQ0EsUUFBSSxV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U0FBT0EsR0FBUDtBQUNEIiwiZmlsZSI6ImNvbmZpZy1wYXJzZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgZnMgZnJvbSAnZnMnO1xyXG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcclxuaW1wb3J0IHpsaWIgZnJvbSAnemxpYic7XHJcbmltcG9ydCBta2RpcnAgZnJvbSAnbWtkaXJwJztcclxuaW1wb3J0IHtwZnN9IGZyb20gJy4vcHJvbWlzZSc7XHJcblxyXG5pbXBvcnQgRmlsZUNoYW5nZWRDYWNoZSBmcm9tICcuL2ZpbGUtY2hhbmdlLWNhY2hlJztcclxuaW1wb3J0IENvbXBpbGVySG9zdCBmcm9tICcuL2NvbXBpbGVyLWhvc3QnO1xyXG5pbXBvcnQgcmVnaXN0ZXJSZXF1aXJlRXh0ZW5zaW9uIGZyb20gJy4vcmVxdWlyZS1ob29rJztcclxuXHJcbmNvbnN0IGQgPSByZXF1aXJlKCdkZWJ1Zy1lbGVjdHJvbicpKCdlbGVjdHJvbi1jb21waWxlOmNvbmZpZy1wYXJzZXInKTtcclxuXHJcbi8vIE5COiBXZSBpbnRlbnRpb25hbGx5IGRlbGF5LWxvYWQgdGhpcyBzbyB0aGF0IGluIHByb2R1Y3Rpb24sIHlvdSBjYW4gY3JlYXRlXHJcbi8vIGNhY2hlLW9ubHkgdmVyc2lvbnMgb2YgdGhlc2UgY29tcGlsZXJzXHJcbmxldCBhbGxDb21waWxlckNsYXNzZXMgPSBudWxsO1xyXG5cclxuZnVuY3Rpb24gc3RhdFN5bmNOb0V4Y2VwdGlvbihmc1BhdGgpIHtcclxuICBpZiAoJ3N0YXRTeW5jTm9FeGNlcHRpb24nIGluIGZzKSB7XHJcbiAgICByZXR1cm4gZnMuc3RhdFN5bmNOb0V4Y2VwdGlvbihmc1BhdGgpO1xyXG4gIH1cclxuXHJcbiAgdHJ5IHtcclxuICAgIHJldHVybiBmcy5zdGF0U3luYyhmc1BhdGgpO1xyXG4gIH0gY2F0Y2ggKGUpIHtcclxuICAgIHJldHVybiBudWxsO1xyXG4gIH1cclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiBJbml0aWFsaXplIHRoZSBnbG9iYWwgaG9va3MgKHByb3RvY29sIGhvb2sgZm9yIGZpbGU6LCBub2RlLmpzIGhvb2spXHJcbiAqIGluZGVwZW5kZW50IG9mIGluaXRpYWxpemluZyB0aGUgY29tcGlsZXIuIFRoaXMgbWV0aG9kIGlzIHVzdWFsbHkgY2FsbGVkIGJ5XHJcbiAqIGluaXQgaW5zdGVhZCBvZiBkaXJlY3RseVxyXG4gKlxyXG4gKiBAcGFyYW0ge0NvbXBpbGVySG9zdH0gY29tcGlsZXJIb3N0ICBUaGUgY29tcGlsZXIgaG9zdCB0byB1c2UuXHJcbiAqXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gaW5pdGlhbGl6ZUdsb2JhbEhvb2tzKGNvbXBpbGVySG9zdCkge1xyXG4gIGxldCBnbG9iYWxWYXIgPSAoZ2xvYmFsIHx8IHdpbmRvdyk7XHJcbiAgZ2xvYmFsVmFyLmdsb2JhbENvbXBpbGVySG9zdCA9IGNvbXBpbGVySG9zdDtcclxuXHJcbiAgcmVnaXN0ZXJSZXF1aXJlRXh0ZW5zaW9uKGNvbXBpbGVySG9zdCk7XHJcblxyXG4gIGlmICgndHlwZScgaW4gcHJvY2VzcyAmJiBwcm9jZXNzLnR5cGUgPT09ICdicm93c2VyJykge1xyXG4gICAgY29uc3QgeyBhcHAgfSA9IHJlcXVpcmUoJ2VsZWN0cm9uJyk7XHJcbiAgICBjb25zdCB7IGluaXRpYWxpemVQcm90b2NvbEhvb2sgfSA9IHJlcXVpcmUoJy4vcHJvdG9jb2wtaG9vaycpO1xyXG5cclxuICAgIGxldCBwcm90b2lmeSA9IGZ1bmN0aW9uKCkgeyBpbml0aWFsaXplUHJvdG9jb2xIb29rKGNvbXBpbGVySG9zdCk7IH07XHJcbiAgICBpZiAoYXBwLmlzUmVhZHkoKSkge1xyXG4gICAgICBwcm90b2lmeSgpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgYXBwLm9uKCdyZWFkeScsIHByb3RvaWZ5KTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcblxyXG4vKipcclxuICogSW5pdGlhbGl6ZSBlbGVjdHJvbi1jb21waWxlIGFuZCBzZXQgaXQgdXAsIGVpdGhlciBmb3IgZGV2ZWxvcG1lbnQgb3JcclxuICogcHJvZHVjdGlvbiB1c2UuIFRoaXMgaXMgYWxtb3N0IGFsd2F5cyB0aGUgb25seSBtZXRob2QgeW91IG5lZWQgdG8gdXNlIGluIG9yZGVyXHJcbiAqIHRvIHVzZSBlbGVjdHJvbi1jb21waWxlLlxyXG4gKlxyXG4gKiBAcGFyYW0gIHtzdHJpbmd9IGFwcFJvb3QgIFRoZSB0b3AtbGV2ZWwgZGlyZWN0b3J5IGZvciB5b3VyIGFwcGxpY2F0aW9uIChpLmUuXHJcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlIG9uZSB3aGljaCBoYXMgeW91ciBwYWNrYWdlLmpzb24pLlxyXG4gKlxyXG4gKiBAcGFyYW0gIHtzdHJpbmd9IG1haW5Nb2R1bGUgIFRoZSBtb2R1bGUgdG8gcmVxdWlyZSBpbiwgcmVsYXRpdmUgdG8gdGhlIG1vZHVsZVxyXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxpbmcgaW5pdCwgdGhhdCB3aWxsIHN0YXJ0IHlvdXIgYXBwLiBXcml0ZSB0aGlzXHJcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXMgaWYgeW91IHdlcmUgd3JpdGluZyBhIHJlcXVpcmUgY2FsbCBmcm9tIGhlcmUuXHJcbiAqXHJcbiAqIEBwYXJhbSAge2Jvb2x9IHByb2R1Y3Rpb25Nb2RlICAgSWYgZXhwbGljaXRseSBUcnVlL0ZhbHNlLCB3aWxsIHNldCByZWFkLW9ubHlcclxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RlIHRvIGJlIGRpc2FibGVkL2VuYWJsZWQuIElmIG5vdCwgd2UnbGxcclxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBndWVzcyBiYXNlZCBvbiB0aGUgcHJlc2VuY2Ugb2YgYSBwcm9kdWN0aW9uXHJcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FjaGUuXHJcbiAqXHJcbiAqIEBwYXJhbSAge3N0cmluZ30gY2FjaGVEaXIgIElmIG5vdCBwYXNzZWQgaW4sIHJlYWQtb25seSB3aWxsIGxvb2sgaW5cclxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgYGFwcFJvb3QvLmNhY2hlYCBhbmQgZGV2IG1vZGUgd2lsbCBjb21waWxlIHRvIGFcclxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVtcG9yYXJ5IGRpcmVjdG9yeS4gSWYgaXQgaXMgcGFzc2VkIGluLCBib3RoIG1vZGVzXHJcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpbGwgY2FjaGUgdG8vZnJvbSBgYXBwUm9vdC97Y2FjaGVEaXJ9YFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGluaXQoYXBwUm9vdCwgbWFpbk1vZHVsZSwgcHJvZHVjdGlvbk1vZGUgPSBudWxsLCBjYWNoZURpciA9IG51bGwpIHtcclxuICBsZXQgY29tcGlsZXJIb3N0ID0gbnVsbDtcclxuICBsZXQgcm9vdENhY2hlRGlyID0gcGF0aC5qb2luKGFwcFJvb3QsIGNhY2hlRGlyIHx8ICcuY2FjaGUnKTtcclxuXHJcbiAgaWYgKHByb2R1Y3Rpb25Nb2RlID09PSBudWxsKSB7XHJcbiAgICBwcm9kdWN0aW9uTW9kZSA9ICEhc3RhdFN5bmNOb0V4Y2VwdGlvbihyb290Q2FjaGVEaXIpO1xyXG4gIH1cclxuXHJcbiAgaWYgKHByb2R1Y3Rpb25Nb2RlKSB7XHJcbiAgICBjb21waWxlckhvc3QgPSBDb21waWxlckhvc3QuY3JlYXRlUmVhZG9ubHlGcm9tQ29uZmlndXJhdGlvblN5bmMocm9vdENhY2hlRGlyLCBhcHBSb290KTtcclxuICB9IGVsc2Uge1xyXG4gICAgLy8gaWYgY2FjaGVEaXIgd2FzIHBhc3NlZCBpbiwgcGFzcyBpdCBhbG9uZy4gT3RoZXJ3aXNlLCBkZWZhdWx0IHRvIGEgdGVtcGRpci5cclxuICAgIGlmIChjYWNoZURpcikge1xyXG4gICAgICBjb21waWxlckhvc3QgPSBjcmVhdGVDb21waWxlckhvc3RGcm9tUHJvamVjdFJvb3RTeW5jKGFwcFJvb3QsIHJvb3RDYWNoZURpcik7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBjb21waWxlckhvc3QgPSBjcmVhdGVDb21waWxlckhvc3RGcm9tUHJvamVjdFJvb3RTeW5jKGFwcFJvb3QpO1xyXG4gICAgfVxyXG5cclxuICB9XHJcblxyXG4gIGluaXRpYWxpemVHbG9iYWxIb29rcyhjb21waWxlckhvc3QpO1xyXG4gIHJlcXVpcmUubWFpbi5yZXF1aXJlKG1haW5Nb2R1bGUpO1xyXG59XHJcblxyXG5cclxuLyoqXHJcbiAqIENyZWF0ZXMgYSB7QGxpbmsgQ29tcGlsZXJIb3N0fSB3aXRoIHRoZSBnaXZlbiBpbmZvcm1hdGlvbi4gVGhpcyBtZXRob2QgaXNcclxuICogdXN1YWxseSBjYWxsZWQgYnkge0BsaW5rIGNyZWF0ZUNvbXBpbGVySG9zdEZyb21Qcm9qZWN0Um9vdH0uXHJcbiAqXHJcbiAqIEBwcml2YXRlXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ29tcGlsZXJIb3N0RnJvbUNvbmZpZ3VyYXRpb24oaW5mbykge1xyXG4gIGxldCBjb21waWxlcnMgPSBjcmVhdGVDb21waWxlcnMoKTtcclxuICBsZXQgcm9vdENhY2hlRGlyID0gaW5mby5yb290Q2FjaGVEaXIgfHwgY2FsY3VsYXRlRGVmYXVsdENvbXBpbGVDYWNoZURpcmVjdG9yeSgpO1xyXG5cclxuICBkKGBDcmVhdGluZyBDb21waWxlckhvc3Q6ICR7SlNPTi5zdHJpbmdpZnkoaW5mbyl9LCByb290Q2FjaGVEaXIgPSAke3Jvb3RDYWNoZURpcn1gKTtcclxuICBsZXQgZmlsZUNoYW5nZUNhY2hlID0gbmV3IEZpbGVDaGFuZ2VkQ2FjaGUoaW5mby5hcHBSb290KTtcclxuXHJcbiAgbGV0IGNvbXBpbGVySW5mbyA9IHBhdGguam9pbihyb290Q2FjaGVEaXIsICdjb21waWxlci1pbmZvLmpzb24uZ3onKTtcclxuICBpZiAoZnMuZXhpc3RzU3luYyhjb21waWxlckluZm8pKSB7XHJcbiAgICBsZXQgYnVmID0gZnMucmVhZEZpbGVTeW5jKGNvbXBpbGVySW5mbyk7XHJcbiAgICBsZXQganNvbiA9IEpTT04ucGFyc2UoemxpYi5ndW56aXBTeW5jKGJ1ZikpO1xyXG4gICAgZmlsZUNoYW5nZUNhY2hlID0gRmlsZUNoYW5nZWRDYWNoZS5sb2FkRnJvbURhdGEoanNvbi5maWxlQ2hhbmdlQ2FjaGUsIGluZm8uYXBwUm9vdCwgZmFsc2UpO1xyXG4gIH1cclxuXHJcbiAgT2JqZWN0LmtleXMoaW5mby5vcHRpb25zIHx8IHt9KS5mb3JFYWNoKCh4KSA9PiB7XHJcbiAgICBsZXQgb3B0cyA9IGluZm8ub3B0aW9uc1t4XTtcclxuICAgIGlmICghKHggaW4gY29tcGlsZXJzKSkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEZvdW5kIGNvbXBpbGVyIHNldHRpbmdzIGZvciBtaXNzaW5nIGNvbXBpbGVyOiAke3h9YCk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gTkI6IExldCdzIGhvcGUgdGhpcyBpc24ndCBhIHZhbGlkIGNvbXBpbGVyIG9wdGlvbi4uLlxyXG4gICAgaWYgKG9wdHMucGFzc3Rocm91Z2gpIHtcclxuICAgICAgY29tcGlsZXJzW3hdID0gY29tcGlsZXJzWyd0ZXh0L3BsYWluJ107XHJcbiAgICAgIGRlbGV0ZSBvcHRzLnBhc3N0aHJvdWdoO1xyXG4gICAgfVxyXG5cclxuICAgIGQoYFNldHRpbmcgb3B0aW9ucyBmb3IgJHt4fTogJHtKU09OLnN0cmluZ2lmeShvcHRzKX1gKTtcclxuICAgIGNvbXBpbGVyc1t4XS5jb21waWxlck9wdGlvbnMgPSBvcHRzO1xyXG4gIH0pO1xyXG5cclxuICBsZXQgcmV0ID0gbmV3IENvbXBpbGVySG9zdChyb290Q2FjaGVEaXIsIGNvbXBpbGVycywgZmlsZUNoYW5nZUNhY2hlLCBmYWxzZSwgY29tcGlsZXJzWyd0ZXh0L3BsYWluJ10pO1xyXG5cclxuICAvLyBOQjogSXQncyBzdXBlciBpbXBvcnRhbnQgdGhhdCB3ZSBndWFyYW50ZWUgdGhhdCB0aGUgY29uZmlndXJhdGlvbiBpcyBzYXZlZFxyXG4gIC8vIG91dCwgYmVjYXVzZSB3ZSdsbCBuZWVkIHRvIHJlLXJlYWQgaXQgaW4gdGhlIHJlbmRlcmVyIHByb2Nlc3NcclxuICBkKGBDcmVhdGVkIGNvbXBpbGVyIGhvc3Qgd2l0aCBvcHRpb25zOiAke0pTT04uc3RyaW5naWZ5KGluZm8pfWApO1xyXG4gIHJldC5zYXZlQ29uZmlndXJhdGlvblN5bmMoKTtcclxuICByZXR1cm4gcmV0O1xyXG59XHJcblxyXG4vKipcclxuICogQ3JlYXRlcyBhIGNvbXBpbGVyIGhvc3QgZnJvbSBhIC5iYWJlbHJjIGZpbGUuIFRoaXMgbWV0aG9kIGlzIHVzdWFsbHkgY2FsbGVkXHJcbiAqIGZyb20ge0BsaW5rIGNyZWF0ZUNvbXBpbGVySG9zdEZyb21Qcm9qZWN0Um9vdH0gaW5zdGVhZCBvZiB1c2VkIGRpcmVjdGx5LlxyXG4gKlxyXG4gKiBAcGFyYW0gIHtzdHJpbmd9IGZpbGUgIFRoZSBwYXRoIHRvIGEgLmJhYmVscmMgZmlsZVxyXG4gKlxyXG4gKiBAcGFyYW0gIHtzdHJpbmd9IHJvb3RDYWNoZURpciAob3B0aW9uYWwpICBUaGUgZGlyZWN0b3J5IHRvIHVzZSBhcyBhIGNhY2hlLlxyXG4gKlxyXG4gKiBAcmV0dXJuIHtQcm9taXNlPENvbXBpbGVySG9zdD59ICBBIHNldC11cCBjb21waWxlciBob3N0XHJcbiAqL1xyXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlQ29tcGlsZXJIb3N0RnJvbUJhYmVsUmMoZmlsZSwgcm9vdENhY2hlRGlyPW51bGwpIHtcclxuICBsZXQgaW5mbyA9IEpTT04ucGFyc2UoYXdhaXQgcGZzLnJlYWRGaWxlKGZpbGUsICd1dGY4JykpO1xyXG5cclxuICAvLyBwYWNrYWdlLmpzb25cclxuICBpZiAoJ2JhYmVsJyBpbiBpbmZvKSB7XHJcbiAgICBpbmZvID0gaW5mby5iYWJlbDtcclxuICB9XHJcblxyXG4gIGlmICgnZW52JyBpbiBpbmZvKSB7XHJcbiAgICBsZXQgb3VyRW52ID0gcHJvY2Vzcy5lbnYuQkFCRUxfRU5WIHx8IHByb2Nlc3MuZW52Lk5PREVfRU5WIHx8ICdkZXZlbG9wbWVudCc7XHJcbiAgICBpbmZvID0gaW5mby5lbnZbb3VyRW52XTtcclxuICB9XHJcblxyXG4gIC8vIEFyZSB3ZSBzdGlsbCBwYWNrYWdlLmpzb24gKGkuZS4gaXMgdGhlcmUgbm8gYmFiZWwgaW5mbyB3aGF0c29ldmVyPylcclxuICBpZiAoJ25hbWUnIGluIGluZm8gJiYgJ3ZlcnNpb24nIGluIGluZm8pIHtcclxuICAgIHJldHVybiBjcmVhdGVDb21waWxlckhvc3RGcm9tQ29uZmlndXJhdGlvbih7XHJcbiAgICAgIGFwcFJvb3Q6IHBhdGguZGlybmFtZShmaWxlKSxcclxuICAgICAgb3B0aW9uczogZ2V0RGVmYXVsdENvbmZpZ3VyYXRpb24oKSxcclxuICAgICAgcm9vdENhY2hlRGlyXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHJldHVybiBjcmVhdGVDb21waWxlckhvc3RGcm9tQ29uZmlndXJhdGlvbih7XHJcbiAgICBhcHBSb290OiBwYXRoLmRpcm5hbWUoZmlsZSksXHJcbiAgICBvcHRpb25zOiB7XHJcbiAgICAgICdhcHBsaWNhdGlvbi9qYXZhc2NyaXB0JzogaW5mb1xyXG4gICAgfSxcclxuICAgIHJvb3RDYWNoZURpclxyXG4gIH0pO1xyXG59XHJcblxyXG5cclxuLyoqXHJcbiAqIENyZWF0ZXMgYSBjb21waWxlciBob3N0IGZyb20gYSAuY29tcGlsZXJjIGZpbGUuIFRoaXMgbWV0aG9kIGlzIHVzdWFsbHkgY2FsbGVkXHJcbiAqIGZyb20ge0BsaW5rIGNyZWF0ZUNvbXBpbGVySG9zdEZyb21Qcm9qZWN0Um9vdH0gaW5zdGVhZCBvZiB1c2VkIGRpcmVjdGx5LlxyXG4gKlxyXG4gKiBAcGFyYW0gIHtzdHJpbmd9IGZpbGUgIFRoZSBwYXRoIHRvIGEgLmNvbXBpbGVyYyBmaWxlXHJcbiAqXHJcbiAqIEBwYXJhbSAge3N0cmluZ30gcm9vdENhY2hlRGlyIChvcHRpb25hbCkgIFRoZSBkaXJlY3RvcnkgdG8gdXNlIGFzIGEgY2FjaGUuXHJcbiAqXHJcbiAqIEByZXR1cm4ge1Byb21pc2U8Q29tcGlsZXJIb3N0Pn0gIEEgc2V0LXVwIGNvbXBpbGVyIGhvc3RcclxuICovXHJcbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjcmVhdGVDb21waWxlckhvc3RGcm9tQ29uZmlnRmlsZShmaWxlLCByb290Q2FjaGVEaXI9bnVsbCkge1xyXG4gIGxldCBpbmZvID0gSlNPTi5wYXJzZShhd2FpdCBwZnMucmVhZEZpbGUoZmlsZSwgJ3V0ZjgnKSk7XHJcblxyXG4gIGlmICgnZW52JyBpbiBpbmZvKSB7XHJcbiAgICBsZXQgb3VyRW52ID0gcHJvY2Vzcy5lbnYuRUxFQ1RST05fQ09NUElMRV9FTlYgfHwgcHJvY2Vzcy5lbnYuTk9ERV9FTlYgfHwgJ2RldmVsb3BtZW50JztcclxuICAgIGluZm8gPSBpbmZvLmVudltvdXJFbnZdO1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIGNyZWF0ZUNvbXBpbGVySG9zdEZyb21Db25maWd1cmF0aW9uKHtcclxuICAgIGFwcFJvb3Q6IHBhdGguZGlybmFtZShmaWxlKSxcclxuICAgIG9wdGlvbnM6IGluZm8sXHJcbiAgICByb290Q2FjaGVEaXJcclxuICB9KTtcclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiBDcmVhdGVzIGEgY29uZmlndXJlZCB7QGxpbmsgQ29tcGlsZXJIb3N0fSBpbnN0YW5jZSBmcm9tIHRoZSBwcm9qZWN0IHJvb3RcclxuICogZGlyZWN0b3J5LiBUaGlzIG1ldGhvZCBmaXJzdCBzZWFyY2hlcyBmb3IgYSAuY29tcGlsZXJjIChvciAuY29tcGlsZXJjLmpzb24pLCB0aGVuIGZhbGxzIGJhY2sgdG8gdGhlXHJcbiAqIGRlZmF1bHQgbG9jYXRpb25zIGZvciBCYWJlbCBjb25maWd1cmF0aW9uIGluZm8uIElmIG5laXRoZXIgYXJlIGZvdW5kLCBkZWZhdWx0c1xyXG4gKiB0byBzdGFuZGFyZCBzZXR0aW5nc1xyXG4gKlxyXG4gKiBAcGFyYW0gIHtzdHJpbmd9IHJvb3REaXIgIFRoZSByb290IGFwcGxpY2F0aW9uIGRpcmVjdG9yeSAoaS5lLiB0aGUgZGlyZWN0b3J5XHJcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhhdCBoYXMgdGhlIGFwcCdzIHBhY2thZ2UuanNvbilcclxuICpcclxuICogQHBhcmFtICB7c3RyaW5nfSByb290Q2FjaGVEaXIgKG9wdGlvbmFsKSAgVGhlIGRpcmVjdG9yeSB0byB1c2UgYXMgYSBjYWNoZS5cclxuICpcclxuICogQHJldHVybiB7UHJvbWlzZTxDb21waWxlckhvc3Q+fSAgQSBzZXQtdXAgY29tcGlsZXIgaG9zdFxyXG4gKi9cclxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUNvbXBpbGVySG9zdEZyb21Qcm9qZWN0Um9vdChyb290RGlyLCByb290Q2FjaGVEaXI9bnVsbCkge1xyXG4gIGxldCBjb21waWxlcmMgPSBwYXRoLmpvaW4ocm9vdERpciwgJy5jb21waWxlcmMnKTtcclxuICBpZiAoc3RhdFN5bmNOb0V4Y2VwdGlvbihjb21waWxlcmMpKSB7XHJcbiAgICBkKGBGb3VuZCBhIC5jb21waWxlcmMgYXQgJHtjb21waWxlcmN9LCB1c2luZyBpdGApO1xyXG4gICAgcmV0dXJuIGF3YWl0IGNyZWF0ZUNvbXBpbGVySG9zdEZyb21Db25maWdGaWxlKGNvbXBpbGVyYywgcm9vdENhY2hlRGlyKTtcclxuICB9XHJcbiAgY29tcGlsZXJjICs9ICcuanNvbic7XHJcbiAgaWYgKHN0YXRTeW5jTm9FeGNlcHRpb24oY29tcGlsZXJjKSkge1xyXG4gICAgZChgRm91bmQgYSAuY29tcGlsZXJjIGF0ICR7Y29tcGlsZXJjfSwgdXNpbmcgaXRgKTtcclxuICAgIHJldHVybiBhd2FpdCBjcmVhdGVDb21waWxlckhvc3RGcm9tQ29uZmlnRmlsZShjb21waWxlcmMsIHJvb3RDYWNoZURpcik7XHJcbiAgfVxyXG5cclxuICBsZXQgYmFiZWxyYyA9IHBhdGguam9pbihyb290RGlyLCAnLmJhYmVscmMnKTtcclxuICBpZiAoc3RhdFN5bmNOb0V4Y2VwdGlvbihiYWJlbHJjKSkge1xyXG4gICAgZChgRm91bmQgYSAuYmFiZWxyYyBhdCAke2JhYmVscmN9LCB1c2luZyBpdGApO1xyXG4gICAgcmV0dXJuIGF3YWl0IGNyZWF0ZUNvbXBpbGVySG9zdEZyb21CYWJlbFJjKGJhYmVscmMsIHJvb3RDYWNoZURpcik7XHJcbiAgfVxyXG5cclxuICBkKGBVc2luZyBwYWNrYWdlLmpzb24gb3IgZGVmYXVsdCBwYXJhbWV0ZXJzIGF0ICR7cm9vdERpcn1gKTtcclxuICByZXR1cm4gYXdhaXQgY3JlYXRlQ29tcGlsZXJIb3N0RnJvbUJhYmVsUmMocGF0aC5qb2luKHJvb3REaXIsICdwYWNrYWdlLmpzb24nKSwgcm9vdENhY2hlRGlyKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUNvbXBpbGVySG9zdEZyb21CYWJlbFJjU3luYyhmaWxlLCByb290Q2FjaGVEaXI9bnVsbCkge1xyXG4gIGxldCBpbmZvID0gSlNPTi5wYXJzZShmcy5yZWFkRmlsZVN5bmMoZmlsZSwgJ3V0ZjgnKSk7XHJcblxyXG4gIC8vIHBhY2thZ2UuanNvblxyXG4gIGlmICgnYmFiZWwnIGluIGluZm8pIHtcclxuICAgIGluZm8gPSBpbmZvLmJhYmVsO1xyXG4gIH1cclxuXHJcbiAgaWYgKCdlbnYnIGluIGluZm8pIHtcclxuICAgIGxldCBvdXJFbnYgPSBwcm9jZXNzLmVudi5CQUJFTF9FTlYgfHwgcHJvY2Vzcy5lbnYuTk9ERV9FTlYgfHwgJ2RldmVsb3BtZW50JztcclxuICAgIGluZm8gPSBpbmZvLmVudltvdXJFbnZdO1xyXG4gIH1cclxuXHJcbiAgLy8gQXJlIHdlIHN0aWxsIHBhY2thZ2UuanNvbiAoaS5lLiBpcyB0aGVyZSBubyBiYWJlbCBpbmZvIHdoYXRzb2V2ZXI/KVxyXG4gIGlmICgnbmFtZScgaW4gaW5mbyAmJiAndmVyc2lvbicgaW4gaW5mbykge1xyXG4gICAgcmV0dXJuIGNyZWF0ZUNvbXBpbGVySG9zdEZyb21Db25maWd1cmF0aW9uKHtcclxuICAgICAgYXBwUm9vdDogcGF0aC5kaXJuYW1lKGZpbGUpLFxyXG4gICAgICBvcHRpb25zOiBnZXREZWZhdWx0Q29uZmlndXJhdGlvbigpLFxyXG4gICAgICByb290Q2FjaGVEaXJcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIGNyZWF0ZUNvbXBpbGVySG9zdEZyb21Db25maWd1cmF0aW9uKHtcclxuICAgIGFwcFJvb3Q6IHBhdGguZGlybmFtZShmaWxlKSxcclxuICAgIG9wdGlvbnM6IHtcclxuICAgICAgJ2FwcGxpY2F0aW9uL2phdmFzY3JpcHQnOiBpbmZvXHJcbiAgICB9LFxyXG4gICAgcm9vdENhY2hlRGlyXHJcbiAgfSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDb21waWxlckhvc3RGcm9tQ29uZmlnRmlsZVN5bmMoZmlsZSwgcm9vdENhY2hlRGlyPW51bGwpIHtcclxuICBsZXQgaW5mbyA9IEpTT04ucGFyc2UoZnMucmVhZEZpbGVTeW5jKGZpbGUsICd1dGY4JykpO1xyXG5cclxuICBpZiAoJ2VudicgaW4gaW5mbykge1xyXG4gICAgbGV0IG91ckVudiA9IHByb2Nlc3MuZW52LkVMRUNUUk9OX0NPTVBJTEVfRU5WIHx8IHByb2Nlc3MuZW52Lk5PREVfRU5WIHx8ICdkZXZlbG9wbWVudCc7XHJcbiAgICBpbmZvID0gaW5mby5lbnZbb3VyRW52XTtcclxuICB9XHJcblxyXG4gIHJldHVybiBjcmVhdGVDb21waWxlckhvc3RGcm9tQ29uZmlndXJhdGlvbih7XHJcbiAgICBhcHBSb290OiBwYXRoLmRpcm5hbWUoZmlsZSksXHJcbiAgICBvcHRpb25zOiBpbmZvLFxyXG4gICAgcm9vdENhY2hlRGlyXHJcbiAgfSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDb21waWxlckhvc3RGcm9tUHJvamVjdFJvb3RTeW5jKHJvb3REaXIsIHJvb3RDYWNoZURpcj1udWxsKSB7XHJcbiAgbGV0IGNvbXBpbGVyYyA9IHBhdGguam9pbihyb290RGlyLCAnLmNvbXBpbGVyYycpO1xyXG4gIGlmIChzdGF0U3luY05vRXhjZXB0aW9uKGNvbXBpbGVyYykpIHtcclxuICAgIGQoYEZvdW5kIGEgLmNvbXBpbGVyYyBhdCAke2NvbXBpbGVyY30sIHVzaW5nIGl0YCk7XHJcbiAgICByZXR1cm4gY3JlYXRlQ29tcGlsZXJIb3N0RnJvbUNvbmZpZ0ZpbGVTeW5jKGNvbXBpbGVyYywgcm9vdENhY2hlRGlyKTtcclxuICB9XHJcblxyXG4gIGxldCBiYWJlbHJjID0gcGF0aC5qb2luKHJvb3REaXIsICcuYmFiZWxyYycpO1xyXG4gIGlmIChzdGF0U3luY05vRXhjZXB0aW9uKGJhYmVscmMpKSB7XHJcbiAgICBkKGBGb3VuZCBhIC5iYWJlbHJjIGF0ICR7YmFiZWxyY30sIHVzaW5nIGl0YCk7XHJcbiAgICByZXR1cm4gY3JlYXRlQ29tcGlsZXJIb3N0RnJvbUJhYmVsUmNTeW5jKGJhYmVscmMsIHJvb3RDYWNoZURpcik7XHJcbiAgfVxyXG5cclxuICBkKGBVc2luZyBwYWNrYWdlLmpzb24gb3IgZGVmYXVsdCBwYXJhbWV0ZXJzIGF0ICR7cm9vdERpcn1gKTtcclxuICByZXR1cm4gY3JlYXRlQ29tcGlsZXJIb3N0RnJvbUJhYmVsUmNTeW5jKHBhdGguam9pbihyb290RGlyLCAncGFja2FnZS5qc29uJyksIHJvb3RDYWNoZURpcik7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHdoYXQgZWxlY3Ryb24tY29tcGlsZSB3b3VsZCB1c2UgYXMgYSBkZWZhdWx0IHJvb3RDYWNoZURpci4gVXN1YWxseSBvbmx5XHJcbiAqIHVzZWQgZm9yIGRlYnVnZ2luZyBwdXJwb3Nlc1xyXG4gKlxyXG4gKiBAcmV0dXJuIHtzdHJpbmd9ICBBIHBhdGggdGhhdCBtYXkgb3IgbWF5IG5vdCBleGlzdCB3aGVyZSBlbGVjdHJvbi1jb21waWxlIHdvdWxkXHJcbiAqICAgICAgICAgICAgICAgICAgIHNldCB1cCBhIGRldmVsb3BtZW50IG1vZGUgY2FjaGUuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gY2FsY3VsYXRlRGVmYXVsdENvbXBpbGVDYWNoZURpcmVjdG9yeSgpIHtcclxuICBsZXQgdG1wRGlyID0gcHJvY2Vzcy5lbnYuVEVNUCB8fCBwcm9jZXNzLmVudi5UTVBESVIgfHwgJy90bXAnO1xyXG4gIGxldCBoYXNoID0gcmVxdWlyZSgnY3J5cHRvJykuY3JlYXRlSGFzaCgnbWQ1JykudXBkYXRlKHByb2Nlc3MuZXhlY1BhdGgpLmRpZ2VzdCgnaGV4Jyk7XHJcblxyXG4gIGxldCBjYWNoZURpciA9IHBhdGguam9pbih0bXBEaXIsIGBjb21waWxlQ2FjaGVfJHtoYXNofWApO1xyXG4gIG1rZGlycC5zeW5jKGNhY2hlRGlyKTtcclxuXHJcbiAgZChgVXNpbmcgZGVmYXVsdCBjYWNoZSBkaXJlY3Rvcnk6ICR7Y2FjaGVEaXJ9YCk7XHJcbiAgcmV0dXJuIGNhY2hlRGlyO1xyXG59XHJcblxyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhlIGRlZmF1bHQgLmNvbmZpZ3JjIGlmIG5vIGNvbmZpZ3VyYXRpb24gaW5mb3JtYXRpb24gY2FuIGJlIGZvdW5kLlxyXG4gKlxyXG4gKiBAcmV0dXJuIHtPYmplY3R9ICBBIGxpc3Qgb2YgZGVmYXVsdCBjb25maWcgc2V0dGluZ3MgZm9yIGVsZWN0cm9uLWNvbXBpbGVyLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGdldERlZmF1bHRDb25maWd1cmF0aW9uKCkge1xyXG4gIHJldHVybiB7XHJcbiAgICAnYXBwbGljYXRpb24vamF2YXNjcmlwdCc6IHtcclxuICAgICAgXCJwcmVzZXRzXCI6IFtcImVzMjAxNi1ub2RlNVwiLCBcInJlYWN0XCJdLFxyXG4gICAgICBcInNvdXJjZU1hcHNcIjogXCJpbmxpbmVcIlxyXG4gICAgfVxyXG4gIH07XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBBbGxvd3MgeW91IHRvIGNyZWF0ZSBuZXcgaW5zdGFuY2VzIG9mIGFsbCBjb21waWxlcnMgdGhhdCBhcmUgc3VwcG9ydGVkIGJ5XHJcbiAqIGVsZWN0cm9uLWNvbXBpbGUgYW5kIHVzZSB0aGVtIGRpcmVjdGx5LiBDdXJyZW50bHkgc3VwcG9ydHMgQmFiZWwsIENvZmZlZVNjcmlwdCxcclxuICogVHlwZVNjcmlwdCwgTGVzcywgYW5kIEphZGUuXHJcbiAqXHJcbiAqIEByZXR1cm4ge09iamVjdH0gIEFuIE9iamVjdCB3aG9zZSBLZXlzIGFyZSBNSU1FIHR5cGVzLCBhbmQgd2hvc2UgdmFsdWVzXHJcbiAqIGFyZSBpbnN0YW5jZXMgb2YgQHtsaW5rIENvbXBpbGVyQmFzZX0uXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ29tcGlsZXJzKCkge1xyXG4gIGlmICghYWxsQ29tcGlsZXJDbGFzc2VzKSB7XHJcbiAgICAvLyBGaXJzdCB3ZSB3YW50IHRvIHNlZSBpZiBlbGVjdHJvbi1jb21waWxlcnMgaXRzZWxmIGhhcyBiZWVuIGluc3RhbGxlZCB3aXRoXHJcbiAgICAvLyBkZXZEZXBlbmRlbmNpZXMuIElmIHRoYXQncyBub3QgdGhlIGNhc2UsIGNoZWNrIHRvIHNlZSBpZlxyXG4gICAgLy8gZWxlY3Ryb24tY29tcGlsZXJzIGlzIGluc3RhbGxlZCBhcyBhIHBlZXIgZGVwZW5kZW5jeSAocHJvYmFibHkgYXMgYVxyXG4gICAgLy8gZGV2RGVwZW5kZW5jeSBvZiB0aGUgcm9vdCBwcm9qZWN0KS5cclxuICAgIGNvbnN0IGxvY2F0aW9ucyA9IFsnZWxlY3Ryb24tY29tcGlsZXJzJywgJy4uLy4uL2VsZWN0cm9uLWNvbXBpbGVycyddO1xyXG5cclxuICAgIGZvciAobGV0IGxvY2F0aW9uIG9mIGxvY2F0aW9ucykge1xyXG4gICAgICB0cnkge1xyXG4gICAgICAgIGFsbENvbXBpbGVyQ2xhc3NlcyA9IHJlcXVpcmUobG9jYXRpb24pO1xyXG4gICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgLy8gWW9sb1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCFhbGxDb21waWxlckNsYXNzZXMpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRWxlY3Ryb24gY29tcGlsZXJzIG5vdCBmb3VuZCBidXQgd2VyZSByZXF1ZXN0ZWQgdG8gYmUgbG9hZGVkXCIpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8gTkI6IE5vdGUgdGhhdCB0aGlzIGNvZGUgaXMgY2FyZWZ1bGx5IHNldCB1cCBzbyB0aGF0IElubGluZUh0bWxDb21waWxlclxyXG4gIC8vIChpLmUuIGNsYXNzZXMgd2l0aCBgY3JlYXRlRnJvbUNvbXBpbGVyc2ApIGluaXRpYWxseSBnZXQgYW4gZW1wdHkgb2JqZWN0LFxyXG4gIC8vIGJ1dCB3aWxsIGhhdmUgYSByZWZlcmVuY2UgdG8gdGhlIGZpbmFsIHJlc3VsdCBvZiB3aGF0IHdlIHJldHVybiwgd2hpY2hcclxuICAvLyByZXNvbHZlcyB0aGUgY2lyY3VsYXIgZGVwZW5kZW5jeSB3ZSdkIG90aGVyd2lzZSBoYXZlIGhlcmUuXHJcbiAgbGV0IHJldCA9IHt9O1xyXG4gIGxldCBpbnN0YW50aWF0ZWRDbGFzc2VzID0gYWxsQ29tcGlsZXJDbGFzc2VzLm1hcCgoS2xhc3MpID0+IHtcclxuICAgIGlmICgnY3JlYXRlRnJvbUNvbXBpbGVycycgaW4gS2xhc3MpIHtcclxuICAgICAgcmV0dXJuIEtsYXNzLmNyZWF0ZUZyb21Db21waWxlcnMocmV0KTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHJldHVybiBuZXcgS2xhc3MoKTtcclxuICAgIH1cclxuICB9KTtcclxuXHJcbiAgaW5zdGFudGlhdGVkQ2xhc3Nlcy5yZWR1Y2UoKGFjYyx4KSA9PiB7XHJcbiAgICBsZXQgS2xhc3MgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YoeCkuY29uc3RydWN0b3I7XHJcblxyXG4gICAgZm9yIChsZXQgdHlwZSBvZiBLbGFzcy5nZXRJbnB1dE1pbWVUeXBlcygpKSB7IGFjY1t0eXBlXSA9IHg7IH1cclxuICAgIHJldHVybiBhY2M7XHJcbiAgfSwgcmV0KTtcclxuXHJcbiAgcmV0dXJuIHJldDtcclxufVxyXG4iXX0=