UNPKG

electron-compile

Version:

Electron supporting package to compile JS and CSS in Electron applications

632 lines (508 loc) 51.4 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.createCompilerHostFromProjectRoot = exports.createCompilerHostFromConfigFile = exports.createCompilerHostFromBabelRc = undefined; var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); var _getIterator2 = require('babel-runtime/core-js/get-iterator'); var _getIterator3 = _interopRequireDefault(_getIterator2); var _regenerator = require('babel-runtime/regenerator'); var _regenerator2 = _interopRequireDefault(_regenerator); var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator'); var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2); var _keys = require('babel-runtime/core-js/object/keys'); var _keys2 = _interopRequireDefault(_keys); var _stringify = require('babel-runtime/core-js/json/stringify'); var _stringify2 = _interopRequireDefault(_stringify); /** * 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 */ var createCompilerHostFromBabelRc = exports.createCompilerHostFromBabelRc = function () { var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(file) { var rootCacheDir = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; var info, ourEnv; return _regenerator2.default.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _context.t0 = JSON; _context.next = 3; return _promise.pfs.readFile(file, 'utf8'); case 3: _context.t1 = _context.sent; info = _context.t0.parse.call(_context.t0, _context.t1); // package.json if ('babel' in info) { info = info.babel; } if ('env' in info) { 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)) { _context.next = 9; break; } return _context.abrupt('return', createCompilerHostFromConfiguration({ appRoot: _path2.default.dirname(file), options: getDefaultConfiguration(), rootCacheDir: rootCacheDir })); case 9: return _context.abrupt('return', createCompilerHostFromConfiguration({ appRoot: _path2.default.dirname(file), options: { 'application/javascript': info }, rootCacheDir: rootCacheDir })); case 10: case 'end': return _context.stop(); } } }, _callee, this); })); return function createCompilerHostFromBabelRc(_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 */ var createCompilerHostFromConfigFile = exports.createCompilerHostFromConfigFile = function () { var _ref2 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee2(file) { var rootCacheDir = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; var info, ourEnv; return _regenerator2.default.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: _context2.t0 = JSON; _context2.next = 3; return _promise.pfs.readFile(file, 'utf8'); case 3: _context2.t1 = _context2.sent; info = _context2.t0.parse.call(_context2.t0, _context2.t1); if ('env' in info) { ourEnv = process.env.ELECTRON_COMPILE_ENV || process.env.NODE_ENV || 'development'; info = info.env[ourEnv]; } return _context2.abrupt('return', createCompilerHostFromConfiguration({ appRoot: _path2.default.dirname(file), options: info, rootCacheDir: rootCacheDir })); case 7: case 'end': return _context2.stop(); } } }, _callee2, this); })); return function createCompilerHostFromConfigFile(_x6) { 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 */ var createCompilerHostFromProjectRoot = exports.createCompilerHostFromProjectRoot = function () { var _ref3 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee3(rootDir) { var rootCacheDir = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; var compilerc, babelrc; return _regenerator2.default.wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: compilerc = _path2.default.join(rootDir, '.compilerc'); if (!statSyncNoException(compilerc)) { _context3.next = 6; break; } d('Found a .compilerc at ' + compilerc + ', using it'); _context3.next = 5; return createCompilerHostFromConfigFile(compilerc, rootCacheDir); case 5: return _context3.abrupt('return', _context3.sent); case 6: compilerc += '.json'; if (!statSyncNoException(compilerc)) { _context3.next = 12; break; } d('Found a .compilerc at ' + compilerc + ', using it'); _context3.next = 11; return createCompilerHostFromConfigFile(compilerc, rootCacheDir); case 11: return _context3.abrupt('return', _context3.sent); case 12: babelrc = _path2.default.join(rootDir, '.babelrc'); if (!statSyncNoException(babelrc)) { _context3.next = 18; break; } d('Found a .babelrc at ' + babelrc + ', using it'); _context3.next = 17; return createCompilerHostFromBabelRc(babelrc, rootCacheDir); case 17: return _context3.abrupt('return', _context3.sent); case 18: d('Using package.json or default parameters at ' + rootDir); _context3.next = 21; return createCompilerHostFromBabelRc(_path2.default.join(rootDir, 'package.json'), rootCacheDir); case 21: return _context3.abrupt('return', _context3.sent); case 22: case 'end': return _context3.stop(); } } }, _callee3, this); })); return function createCompilerHostFromProjectRoot(_x8) { 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 }; } var 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 var 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) { var globalVar = global || window; globalVar.globalCompilerHost = compilerHost; (0, _requireHook2.default)(compilerHost); if ('type' in process && process.type === 'browser') { (function () { var _require = require('electron'); var app = _require.app; var _require2 = require('./protocol-hook'); var initializeProtocolHook = _require2.initializeProtocolHook; var protoify = function protoify() { 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) { var productionMode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; var cacheDir = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; var compilerHost = null; var 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) { var compilers = createCompilers(); var rootCacheDir = info.rootCacheDir || calculateDefaultCompileCacheDirectory(); d('Creating CompilerHost: ' + (0, _stringify2.default)(info) + ', rootCacheDir = ' + rootCacheDir); var fileChangeCache = new _fileChangeCache2.default(info.appRoot); var compilerInfo = _path2.default.join(rootCacheDir, 'compiler-info.json.gz'); if (_fs2.default.existsSync(compilerInfo)) { var buf = _fs2.default.readFileSync(compilerInfo); var json = JSON.parse(_zlib2.default.gunzipSync(buf)); fileChangeCache = _fileChangeCache2.default.loadFromData(json.fileChangeCache, info.appRoot, false); } (0, _keys2.default)(info.options || {}).forEach(function (x) { var 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 + ': ' + (0, _stringify2.default)(opts)); compilers[x].compilerOptions = opts; }); var 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: ' + (0, _stringify2.default)(info)); ret.saveConfigurationSync(); return ret; }function createCompilerHostFromBabelRcSync(file) { var rootCacheDir = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; var info = JSON.parse(_fs2.default.readFileSync(file, 'utf8')); // package.json if ('babel' in info) { info = info.babel; } if ('env' in info) { var 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: rootCacheDir }); } return createCompilerHostFromConfiguration({ appRoot: _path2.default.dirname(file), options: { 'application/javascript': info }, rootCacheDir: rootCacheDir }); } function createCompilerHostFromConfigFileSync(file) { var rootCacheDir = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; var info = JSON.parse(_fs2.default.readFileSync(file, 'utf8')); if ('env' in info) { var 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: rootCacheDir }); } function createCompilerHostFromProjectRootSync(rootDir) { var rootCacheDir = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; var compilerc = _path2.default.join(rootDir, '.compilerc'); if (statSyncNoException(compilerc)) { d('Found a .compilerc at ' + compilerc + ', using it'); return createCompilerHostFromConfigFileSync(compilerc, rootCacheDir); } var 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() { var tmpDir = process.env.TEMP || process.env.TMPDIR || '/tmp'; var hash = require('crypto').createHash('md5').update(process.execPath).digest('hex'); var 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": ["stage-0", "es2015", "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). var locations = ['electron-compilers', '../../electron-compilers']; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = (0, _getIterator3.default)(locations), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var location = _step.value; try { allCompilerClasses = require(location); } catch (e) { // Yolo } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } 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. var ret = {}; var instantiatedClasses = allCompilerClasses.map(function (Klass) { if ('createFromCompilers' in Klass) { return Klass.createFromCompilers(ret); } else { return new Klass(); } }); instantiatedClasses.reduce(function (acc, x) { var Klass = (0, _getPrototypeOf2.default)(x).constructor; var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = (0, _getIterator3.default)(Klass.getInputMimeTypes()), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var type = _step2.value; acc[type] = x; } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2.return) { _iterator2.return(); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } return acc; }, ret); return ret; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9jb25maWctcGFyc2VyLmpzIl0sIm5hbWVzIjpbImZpbGUiLCJyb290Q2FjaGVEaXIiLCJKU09OIiwicmVhZEZpbGUiLCJpbmZvIiwicGFyc2UiLCJiYWJlbCIsIm91ckVudiIsInByb2Nlc3MiLCJlbnYiLCJCQUJFTF9FTlYiLCJOT0RFX0VOViIsImNyZWF0ZUNvbXBpbGVySG9zdEZyb21Db25maWd1cmF0aW9uIiwiYXBwUm9vdCIsImRpcm5hbWUiLCJvcHRpb25zIiwiZ2V0RGVmYXVsdENvbmZpZ3VyYXRpb24iLCJjcmVhdGVDb21waWxlckhvc3RGcm9tQmFiZWxSYyIsIkVMRUNUUk9OX0NPTVBJTEVfRU5WIiwiY3JlYXRlQ29tcGlsZXJIb3N0RnJvbUNvbmZpZ0ZpbGUiLCJyb290RGlyIiwiY29tcGlsZXJjIiwiam9pbiIsInN0YXRTeW5jTm9FeGNlcHRpb24iLCJkIiwiYmFiZWxyYyIsImNyZWF0ZUNvbXBpbGVySG9zdEZyb21Qcm9qZWN0Um9vdCIsImluaXRpYWxpemVHbG9iYWxIb29rcyIsImluaXQiLCJjcmVhdGVDb21waWxlckhvc3RGcm9tQmFiZWxSY1N5bmMiLCJjcmVhdGVDb21waWxlckhvc3RGcm9tQ29uZmlnRmlsZVN5bmMiLCJjcmVhdGVDb21waWxlckhvc3RGcm9tUHJvamVjdFJvb3RTeW5jIiwiY2FsY3VsYXRlRGVmYXVsdENvbXBpbGVDYWNoZURpcmVjdG9yeSIsImNyZWF0ZUNvbXBpbGVycyIsInJlcXVpcmUiLCJhbGxDb21waWxlckNsYXNzZXMiLCJmc1BhdGgiLCJzdGF0U3luYyIsImUiLCJjb21waWxlckhvc3QiLCJnbG9iYWxWYXIiLCJnbG9iYWwiLCJ3aW5kb3ciLCJnbG9iYWxDb21waWxlckhvc3QiLCJ0eXBlIiwiYXBwIiwiaW5pdGlhbGl6ZVByb3RvY29sSG9vayIsInByb3RvaWZ5IiwiaXNSZWFkeSIsIm9uIiwibWFpbk1vZHVsZSIsInByb2R1Y3Rpb25Nb2RlIiwiY2FjaGVEaXIiLCJjcmVhdGVSZWFkb25seUZyb21Db25maWd1cmF0aW9uU3luYyIsIm1haW4iLCJjb21waWxlcnMiLCJmaWxlQ2hhbmdlQ2FjaGUiLCJjb21waWxlckluZm8iLCJleGlzdHNTeW5jIiwiYnVmIiwicmVhZEZpbGVTeW5jIiwianNvbiIsImd1bnppcFN5bmMiLCJsb2FkRnJvbURhdGEiLCJmb3JFYWNoIiwieCIsIm9wdHMiLCJFcnJvciIsInBhc3N0aHJvdWdoIiwiY29tcGlsZXJPcHRpb25zIiwicmV0Iiwic2F2ZUNvbmZpZ3VyYXRpb25TeW5jIiwidG1wRGlyIiwiVEVNUCIsIlRNUERJUiIsImhhc2giLCJjcmVhdGVIYXNoIiwidXBkYXRlIiwiZXhlY1BhdGgiLCJkaWdlc3QiLCJzeW5jIiwibG9jYXRpb25zIiwibG9jYXRpb24iLCJpbnN0YW50aWF0ZWRDbGFzc2VzIiwibWFwIiwiS2xhc3MiLCJjcmVhdGVGcm9tQ29tcGlsZXJzIiwicmVkdWNlIiwiYWNjIiwiY29uc3RydWN0b3IiLCJnZXRJbnB1dE1pbWVUeXBlcyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQXFKQTs7Ozs7Ozs7Ozs7d0VBVU8saUJBQTZDQSxJQUE3QztBQUFBLFFBQW1EQyxZQUFuRCx1RUFBZ0UsSUFBaEU7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsMEJBQ01DLElBRE47QUFBQTtBQUFBLG1CQUN1QixhQUFJQyxRQUFKLENBQWFILElBQWIsRUFBbUIsTUFBbkIsQ0FEdkI7O0FBQUE7QUFBQTtBQUNESSxnQkFEQyxlQUNXQyxLQURYOzs7QUFHTDtBQUNBLGdCQUFJLFdBQVdELElBQWYsRUFBcUI7QUFDbkJBLHFCQUFPQSxLQUFLRSxLQUFaO0FBQ0Q7O0FBRUQsZ0JBQUksU0FBU0YsSUFBYixFQUFtQjtBQUNiRyxvQkFEYSxHQUNKQyxRQUFRQyxHQUFSLENBQVlDLFNBQVosSUFBeUJGLFFBQVFDLEdBQVIsQ0FBWUUsUUFBckMsSUFBaUQsYUFEN0M7O0FBRWpCUCxxQkFBT0EsS0FBS0ssR0FBTCxDQUFTRixN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QTFCOztBQVFBRixzQkFBb0JJLE1BQXBCLENBQTJCLFVBQUNDLEdBQUQsRUFBS3ZCLENBQUwsRUFBVztBQUNwQyxRQUFJb0IsUUFBUSw4QkFBc0JwQixDQUF0QixFQUF5QndCLFdBQXJDOztBQURvQztBQUFBO0FBQUE7O0FBQUE7QUFHcEMsdURBQWlCSixNQUFNSyxpQkFBTixFQUFqQixpSEFBNEM7QUFBQSxZQUFuQzlDLElBQW1DO0FBQUU0QyxZQUFJNUMsSUFBSixJQUFZcUIsQ0FBWjtBQUFnQjtBQUgxQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBOztBQUlwQyxXQUFPdUIsR0FBUDtBQUNELEdBTEQsRUFLR2xCLEdBTEg7O0FBT0EsU0FBT0EsR0FBUDtBQUNEIiwiZmlsZSI6ImNvbmZpZy1wYXJzZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgZnMgZnJvbSAnZnMnO1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgemxpYiBmcm9tICd6bGliJztcbmltcG9ydCBta2RpcnAgZnJvbSAnbWtkaXJwJztcbmltcG9ydCB7cGZzfSBmcm9tICcuL3Byb21pc2UnO1xuXG5pbXBvcnQgRmlsZUNoYW5nZWRDYWNoZSBmcm9tICcuL2ZpbGUtY2hhbmdlLWNhY2hlJztcbmltcG9ydCBDb21waWxlckhvc3QgZnJvbSAnLi9jb21waWxlci1ob3N0JztcbmltcG9ydCByZWdpc3RlclJlcXVpcmVFeHRlbnNpb24gZnJvbSAnLi9yZXF1aXJlLWhvb2snO1xuXG5jb25zdCBkID0gcmVxdWlyZSgnZGVidWctZWxlY3Ryb24nKSgnZWxlY3Ryb24tY29tcGlsZTpjb25maWctcGFyc2VyJyk7XG5cbi8vIE5COiBXZSBpbnRlbnRpb25hbGx5IGRlbGF5LWxvYWQgdGhpcyBzbyB0aGF0IGluIHByb2R1Y3Rpb24sIHlvdSBjYW4gY3JlYXRlXG4vLyBjYWNoZS1vbmx5IHZlcnNpb25zIG9mIHRoZXNlIGNvbXBpbGVyc1xubGV0IGFsbENvbXBpbGVyQ2xhc3NlcyA9IG51bGw7XG5cbmZ1bmN0aW9uIHN0YXRTeW5jTm9FeGNlcHRpb24oZnNQYXRoKSB7XG4gIGlmICgnc3RhdFN5bmNOb0V4Y2VwdGlvbicgaW4gZnMpIHtcbiAgICByZXR1cm4gZnMuc3RhdFN5bmNOb0V4Y2VwdGlvbihmc1BhdGgpO1xuICB9XG5cbiAgdHJ5IHtcbiAgICByZXR1cm4gZnMuc3RhdFN5bmMoZnNQYXRoKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG59XG5cblxuLyoqXG4gKiBJbml0aWFsaXplIHRoZSBnbG9iYWwgaG9va3MgKHByb3RvY29sIGhvb2sgZm9yIGZpbGU6LCBub2RlLmpzIGhvb2spXG4gKiBpbmRlcGVuZGVudCBvZiBpbml0aWFsaXppbmcgdGhlIGNvbXBpbGVyLiBUaGlzIG1ldGhvZCBpcyB1c3VhbGx5IGNhbGxlZCBieVxuICogaW5pdCBpbnN0ZWFkIG9mIGRpcmVjdGx5XG4gKlxuICogQHBhcmFtIHtDb21waWxlckhvc3R9IGNvbXBpbGVySG9zdCAgVGhlIGNvbXBpbGVyIGhvc3QgdG8gdXNlLlxuICpcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemVHbG9iYWxIb29rcyhjb21waWxlckhvc3QpIHtcbiAgbGV0IGdsb2JhbFZhciA9IChnbG9iYWwgfHwgd2luZG93KTtcbiAgZ2xvYmFsVmFyLmdsb2JhbENvbXBpbGVySG9zdCA9IGNvbXBpbGVySG9zdDtcblxuICByZWdpc3RlclJlcXVpcmVFeHRlbnNpb24oY29tcGlsZXJIb3N0KTtcblxuICBpZiAoJ3R5cGUnIGluIHByb2Nlc3MgJiYgcHJvY2Vzcy50eXBlID09PSAnYnJvd3NlcicpIHtcbiAgICBjb25zdCB7IGFwcCB9ID0gcmVxdWlyZSgnZWxlY3Ryb24nKTtcbiAgICBjb25zdCB7IGluaXRpYWxpemVQcm90b2NvbEhvb2sgfSA9IHJlcXVpcmUoJy4vcHJvdG9jb2wtaG9vaycpO1xuXG4gICAgbGV0IHByb3RvaWZ5ID0gZnVuY3Rpb24oKSB7IGluaXRpYWxpemVQcm90b2NvbEhvb2soY29tcGlsZXJIb3N0KTsgfTtcbiAgICBpZiAoYXBwLmlzUmVhZHkoKSkge1xuICAgICAgcHJvdG9pZnkoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYXBwLm9uKCdyZWFkeScsIHByb3RvaWZ5KTtcbiAgICB9XG4gIH1cbn1cblxuXG4vKipcbiAqIEluaXRpYWxpemUgZWxlY3Ryb24tY29tcGlsZSBhbmQgc2V0IGl0IHVwLCBlaXRoZXIgZm9yIGRldmVsb3BtZW50IG9yXG4gKiBwcm9kdWN0aW9uIHVzZS4gVGhpcyBpcyBhbG1vc3QgYWx3YXlzIHRoZSBvbmx5IG1ldGhvZCB5b3UgbmVlZCB0byB1c2UgaW4gb3JkZXJcbiAqIHRvIHVzZSBlbGVjdHJvbi1jb21waWxlLlxuICpcbiAqIEBwYXJhbSAge3N0cmluZ30gYXBwUm9vdCAgVGhlIHRvcC1sZXZlbCBkaXJlY3RvcnkgZm9yIHlvdXIgYXBwbGljYXRpb24gKGkuZS5cbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlIG9uZSB3aGljaCBoYXMgeW91ciBwYWNrYWdlLmpzb24pLlxuICpcbiAqIEBwYXJhbSAge3N0cmluZ30gbWFpbk1vZHVsZSAgVGhlIG1vZHVsZSB0byByZXF1aXJlIGluLCByZWxhdGl2ZSB0byB0aGUgbW9kdWxlXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxpbmcgaW5pdCwgdGhhdCB3aWxsIHN0YXJ0IHlvdXIgYXBwLiBXcml0ZSB0aGlzXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzIGlmIHlvdSB3ZXJlIHdyaXRpbmcgYSByZXF1aXJlIGNhbGwgZnJvbSBoZXJlLlxuICpcbiAqIEBwYXJhbSAge2Jvb2x9IHByb2R1Y3Rpb25Nb2RlICAgSWYgZXhwbGljaXRseSBUcnVlL0ZhbHNlLCB3aWxsIHNldCByZWFkLW9ubHlcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZSB0byBiZSBkaXNhYmxlZC9lbmFibGVkLiBJZiBub3QsIHdlJ2xsXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGd1ZXNzIGJhc2VkIG9uIHRoZSBwcmVzZW5jZSBvZiBhIHByb2R1Y3Rpb25cbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FjaGUuXG4gKlxuICogQHBhcmFtICB7c3RyaW5nfSBjYWNoZURpciAgSWYgbm90IHBhc3NlZCBpbiwgcmVhZC1vbmx5IHdpbGwgbG9vayBpblxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgYGFwcFJvb3QvLmNhY2hlYCBhbmQgZGV2IG1vZGUgd2lsbCBjb21waWxlIHRvIGFcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlbXBvcmFyeSBkaXJlY3RvcnkuIElmIGl0IGlzIHBhc3NlZCBpbiwgYm90aCBtb2Rlc1xuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lsbCBjYWNoZSB0by9mcm9tIGBhcHBSb290L3tjYWNoZURpcn1gXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbml0KGFwcFJvb3QsIG1haW5Nb2R1bGUsIHByb2R1Y3Rpb25Nb2RlID0gbnVsbCwgY2FjaGVEaXIgPSBudWxsKSB7XG4gIGxldCBjb21waWxlckhvc3QgPSBudWxsO1xuICBsZXQgcm9vdENhY2hlRGlyID0gcGF0aC5qb2luKGFwcFJvb3QsIGNhY2hlRGlyIHx8ICcuY2FjaGUnKTtcblxuICBpZiAocHJvZHVjdGlvbk1vZGUgPT09IG51bGwpIHtcbiAgICBwcm9kdWN0aW9uTW9kZSA9ICEhc3RhdFN5bmNOb0V4Y2VwdGlvbihyb290Q2FjaGVEaXIpO1xuICB9XG5cbiAgaWYgKHByb2R1Y3Rpb25Nb2RlKSB7XG4gICAgY29tcGlsZXJIb3N0ID0gQ29tcGlsZXJIb3N0LmNyZWF0ZVJlYWRvbmx5RnJvbUNvbmZpZ3VyYXRpb25TeW5jKHJvb3RDYWNoZURpciwgYXBwUm9vdCk7XG4gIH0gZWxzZSB7XG4gICAgLy8gaWYgY2FjaGVEaXIgd2FzIHBhc3NlZCBpbiwgcGFzcyBpdCBhbG9uZy4gT3RoZXJ3aXNlLCBkZWZhdWx0IHRvIGEgdGVtcGRpci5cbiAgICBpZiAoY2FjaGVEaXIpIHtcbiAgICAgIGNvbXBpbGVySG9zdCA9IGNyZWF0ZUNvbXBpbGVySG9zdEZyb21Qcm9qZWN0Um9vdFN5bmMoYXBwUm9vdCwgcm9vdENhY2hlRGlyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29tcGlsZXJIb3N0ID0gY3JlYXRlQ29tcGlsZXJIb3N0RnJvbVByb2plY3RSb290U3luYyhhcHBSb290KTtcbiAgICB9XG5cbiAgfVxuXG4gIGluaXRpYWxpemVHbG9iYWxIb29rcyhjb21waWxlckhvc3QpO1xuICByZXF1aXJlLm1haW4ucmVxdWlyZShtYWluTW9kdWxlKTtcbn1cblxuXG4vKipcbiAqIENyZWF0ZXMgYSB7QGxpbmsgQ29tcGlsZXJIb3N0fSB3aXRoIHRoZSBnaXZlbiBpbmZvcm1hdGlvbi4gVGhpcyBtZXRob2QgaXNcbiAqIHVzdWFsbHkgY2FsbGVkIGJ5IHtAbGluayBjcmVhdGVDb21waWxlckhvc3RGcm9tUHJvamVjdFJvb3R9LlxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDb21waWxlckhvc3RGcm9tQ29uZmlndXJhdGlvbihpbmZvKSB7XG4gIGxldCBjb21waWxlcnMgPSBjcmVhdGVDb21waWxlcnMoKTtcbiAgbGV0IHJvb3RDYWNoZURpciA9IGluZm8ucm9vdENhY2hlRGlyIHx8IGNhbGN1bGF0ZURlZmF1bHRDb21waWxlQ2FjaGVEaXJlY3RvcnkoKTtcblxuICBkKGBDcmVhdGluZyBDb21waWxlckhvc3Q6ICR7SlNPTi5zdHJpbmdpZnkoaW5mbyl9LCByb290Q2FjaGVEaXIgPSAke3Jvb3RDYWNoZURpcn1gKTtcbiAgbGV0IGZpbGVDaGFuZ2VDYWNoZSA9IG5ldyBGaWxlQ2hhbmdlZENhY2hlKGluZm8uYXBwUm9vdCk7XG5cbiAgbGV0IGNvbXBpbGVySW5mbyA9IHBhdGguam9pbihyb290Q2FjaGVEaXIsICdjb21waWxlci1pbmZvLmpzb24uZ3onKTtcbiAgaWYgKGZzLmV4aXN0c1N5bmMoY29tcGlsZXJJbmZvKSkge1xuICAgIGxldCBidWYgPSBmcy5yZWFkRmlsZVN5bmMoY29tcGlsZXJJbmZvKTtcbiAgICBsZXQganNvbiA9IEpTT04ucGFyc2UoemxpYi5ndW56aXBTeW5jKGJ1ZikpO1xuICAgIGZpbGVDaGFuZ2VDYWNoZSA9IEZpbGVDaGFuZ2VkQ2FjaGUubG9hZEZyb21EYXRhKGpzb24uZmlsZUNoYW5nZUNhY2hlLCBpbmZvLmFwcFJvb3QsIGZhbHNlKTtcbiAgfVxuXG4gIE9iamVjdC5rZXlzKGluZm8ub3B0aW9ucyB8fCB7fSkuZm9yRWFjaCgoeCkgPT4ge1xuICAgIGxldCBvcHRzID0gaW5mby5vcHRpb25zW3hdO1xuICAgIGlmICghKHggaW4gY29tcGlsZXJzKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGb3VuZCBjb21waWxlciBzZXR0aW5ncyBmb3IgbWlzc2luZyBjb21waWxlcjogJHt4fWApO1xuICAgIH1cblxuICAgIC8vIE5COiBMZXQncyBob3BlIHRoaXMgaXNuJ3QgYSB2YWxpZCBjb21waWxlciBvcHRpb24uLi5cbiAgICBpZiAob3B0cy5wYXNzdGhyb3VnaCkge1xuICAgICAgY29tcGlsZXJzW3hdID0gY29tcGlsZXJzWyd0ZXh0L3BsYWluJ107XG4gICAgICBkZWxldGUgb3B0cy5wYXNzdGhyb3VnaDtcbiAgICB9XG5cbiAgICBkKGBTZXR0aW5nIG9wdGlvbnMgZm9yICR7eH06ICR7SlNPTi5zdHJpbmdpZnkob3B0cyl9YCk7XG4gICAgY29tcGlsZXJzW3hdLmNvbXBpbGVyT3B0aW9ucyA9IG9wdHM7XG4gIH0pO1xuXG4gIGxldCByZXQgPSBuZXcgQ29tcGlsZXJIb3N0KHJvb3RDYWNoZURpciwgY29tcGlsZXJzLCBmaWxlQ2hhbmdlQ2FjaGUsIGZhbHNlLCBjb21waWxlcnNbJ3RleHQvcGxhaW4nXSk7XG5cbiAgLy8gTkI6IEl0J3Mgc3VwZXIgaW1wb3J0YW50IHRoYXQgd2UgZ3VhcmFudGVlIHRoYXQgdGhlIGNvbmZpZ3VyYXRpb24gaXMgc2F2ZWRcbiAgLy8gb3V0LCBiZWNhdXNlIHdlJ2xsIG5lZWQgdG8gcmUtcmVhZCBpdCBpbiB0aGUgcmVuZGVyZXIgcHJvY2Vzc1xuICBkKGBDcmVhdGVkIGNvbXBpbGVyIGhvc3Qgd2l0aCBvcHRpb25zOiAke0pTT04uc3RyaW5naWZ5KGluZm8pfWApO1xuICByZXQuc2F2ZUNvbmZpZ3VyYXRpb25TeW5jKCk7XG4gIHJldHVybiByZXQ7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIGNvbXBpbGVyIGhvc3QgZnJvbSBhIC5iYWJlbHJjIGZpbGUuIFRoaXMgbWV0aG9kIGlzIHVzdWFsbHkgY2FsbGVkXG4gKiBmcm9tIHtAbGluayBjcmVhdGVDb21waWxlckhvc3RGcm9tUHJvamVjdFJvb3R9IGluc3RlYWQgb2YgdXNlZCBkaXJlY3RseS5cbiAqXG4gKiBAcGFyYW0gIHtzdHJpbmd9IGZpbGUgIFRoZSBwYXRoIHRvIGEgLmJhYmVscmMgZmlsZVxuICpcbiAqIEBwYXJhbSAge3N0cmluZ30gcm9vdENhY2hlRGlyIChvcHRpb25hbCkgIFRoZSBkaXJlY3RvcnkgdG8gdXNlIGFzIGEgY2FjaGUuXG4gKlxuICogQHJldHVybiB7UHJvbWlzZTxDb21waWxlckhvc3Q+fSAgQSBzZXQtdXAgY29tcGlsZXIgaG9zdFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlQ29tcGlsZXJIb3N0RnJvbUJhYmVsUmMoZmlsZSwgcm9vdENhY2hlRGlyPW51bGwpIHtcbiAgbGV0IGluZm8gPSBKU09OLnBhcnNlKGF3YWl0IHBmcy5yZWFkRmlsZShmaWxlLCAndXRmOCcpKTtcblxuICAvLyBwYWNrYWdlLmpzb25cbiAgaWYgKCdiYWJlbCcgaW4gaW5mbykge1xuICAgIGluZm8gPSBpbmZvLmJhYmVsO1xuICB9XG5cbiAgaWYgKCdlbnYnIGluIGluZm8pIHtcbiAgICBsZXQgb3VyRW52ID0gcHJvY2Vzcy5lbnYuQkFCRUxfRU5WIHx8IHByb2Nlc3MuZW52Lk5PREVfRU5WIHx8ICdkZXZlbG9wbWVudCc7XG4gICAgaW5mbyA9IGluZm8uZW52W291ckVudl07XG4gIH1cblxuICAvLyBBcmUgd2Ugc3RpbGwgcGFja2FnZS5qc29uIChpLmUuIGlzIHRoZXJlIG5vIGJhYmVsIGluZm8gd2hhdHNvZXZlcj8pXG4gIGlmICgnbmFtZScgaW4gaW5mbyAmJiAndmVyc2lvbicgaW4gaW5mbykge1xuICAgIHJldHVybiBjcmVhdGVDb21waWxlckhvc3RGcm9tQ29uZmlndXJhdGlvbih7XG4gICAgICBhcHBSb290OiBwYXRoLmRpcm5hbWUoZmlsZSksXG4gICAgICBvcHRpb25zOiBnZXREZWZhdWx0Q29uZmlndXJhdGlvbigpLFxuICAgICAgcm9vdENhY2hlRGlyXG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gY3JlYXRlQ29tcGlsZXJIb3N0RnJvbUNvbmZpZ3VyYXRpb24oe1xuICAgIGFwcFJvb3Q6IHBhdGguZGlybmFtZShmaWxlKSxcbiAgICBvcHRpb25zOiB7XG4gICAgICAnYXBwbGljYXRpb24vamF2YXNjcmlwdCc6IGluZm9cbiAgICB9LFxuICAgIHJvb3RDYWNoZURpclxuICB9KTtcbn1cblxuXG4vKipcbiAqIENyZWF0ZXMgYSBjb21waWxlciBob3N0IGZyb20gYSAuY29tcGlsZXJjIGZpbGUuIFRoaXMgbWV0aG9kIGlzIHVzdWFsbHkgY2FsbGVkXG4gKiBmcm9tIHtAbGluayBjcmVhdGVDb21waWxlckhvc3RGcm9tUHJvamVjdFJvb3R9IGluc3RlYWQgb2YgdXNlZCBkaXJlY3RseS5cbiAqXG4gKiBAcGFyYW0gIHtzdHJpbmd9IGZpbGUgIFRoZSBwYXRoIHRvIGEgLmNvbXBpbGVyYyBmaWxlXG4gKlxuICogQHBhcmFtICB7c3RyaW5nfSByb290Q2FjaGVEaXIgKG9wdGlvbmFsKSAgVGhlIGRpcmVjdG9yeSB0byB1c2UgYXMgYSBjYWNoZS5cbiAqXG4gKiBAcmV0dXJuIHtQcm9taXNlPENvbXBpbGVySG9zdD59ICBBIHNldC11cCBjb21waWxlciBob3N0XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjcmVhdGVDb21waWxlckhvc3RGcm9tQ29uZmlnRmlsZShmaWxlLCByb290Q2FjaGVEaXI9bnVsbCkge1xuICBsZXQgaW5mbyA9IEpTT04ucGFyc2UoYXdhaXQgcGZzLnJlYWRGaWxlKGZpbGUsICd1dGY4JykpO1xuXG4gIGlmICgnZW52JyBpbiBpbmZvKSB7XG4gICAgbGV0IG91ckVudiA9IHByb2Nlc3MuZW52LkVMRUNUUk9OX0NPTVBJTEVfRU5WIHx8IHByb2Nlc3MuZW52Lk5PREVfRU5WIHx8ICdkZXZlbG9wbWVudCc7XG4gICAgaW5mbyA9IGluZm8uZW52W291ckVudl07XG4gIH1cblxuICByZXR1cm4gY3JlYXRlQ29tcGlsZXJIb3N0RnJvbUNvbmZpZ3VyYXRpb24oe1xuICAgIGFwcFJvb3Q6IHBhdGguZGlybmFtZShmaWxlKSxcbiAgICBvcHRpb25zOiBpbmZvLFxuICAgIHJvb3RDYWNoZURpclxuICB9KTtcbn1cblxuXG4vKipcbiAqIENyZWF0ZXMgYSBjb25maWd1cmVkIHtAbGluayBDb21waWxlckhvc3R9IGluc3RhbmNlIGZyb20gdGhlIHByb2plY3Qgcm9vdFxuICogZGlyZWN0b3J5LiBUaGlzIG1ldGhvZCBmaXJzdCBzZWFyY2hlcyBmb3IgYSAuY29tcGlsZXJjIChvciAuY29tcGlsZXJjLmpzb24pLCB0aGVuIGZhbGxzIGJhY2sgdG8gdGhlXG4gKiBkZWZhdWx0IGxvY2F0aW9ucyBmb3IgQmFiZWwgY29uZmlndXJhdGlvbiBpbmZvLiBJZiBuZWl0aGVyIGFyZSBmb3VuZCwgZGVmYXVsdHNcbiAqIHRvIHN0YW5kYXJkIHNldHRpbmdzXG4gKlxuICogQHBhcmFtICB7c3RyaW5nfSByb290RGlyICBUaGUgcm9vdCBhcHBsaWNhdGlvbiBkaXJlY3RvcnkgKGkuZS4gdGhlIGRpcmVjdG9yeVxuICogICAgICAgICAgICAgICAgICAgICAgICAgICB0aGF0IGhhcyB0aGUgYXBwJ3MgcGFja2FnZS5qc29uKVxuICpcbiAqIEBwYXJhbSAge3N0cmluZ30gcm9vdENhY2hlRGlyIChvcHRpb25hbCkgIFRoZSBkaXJlY3RvcnkgdG8gdXNlIGFzIGEgY2FjaGUuXG4gKlxuICogQHJldHVybiB7UHJvbWlzZTxDb21waWxlckhvc3Q+fSAgQSBzZXQtdXAgY29tcGlsZXIgaG9zdFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlQ29tcGlsZXJIb3N0RnJvbVByb2plY3RSb290KHJvb3REaXIsIHJvb3RDYWNoZURpcj1udWxsKSB7XG4gIGxldCBjb21waWxlcmMgPSBwYXRoLmpvaW4ocm9vdERpciwgJy5jb21waWxlcmMnKTtcbiAgaWYgKHN0YXRTeW5jTm9FeGNlcHRpb24oY29tcGlsZXJjKSkge1xuICAgIGQoYEZvdW5kIGEgLmNvbXBpbGVyYyBhdCAke2NvbXBpbGVyY30sIHVzaW5nIGl0YCk7XG4gICAgcmV0dXJuIGF3YWl0IGNyZWF0ZUNvbXBpbGVySG9zdEZyb21Db25maWdGaWxlKGNvbXBpbGVyYywgcm9vdENhY2hlRGlyKTtcbiAgfVxuICBjb21waWxlcmMgKz0gJy5qc29uJztcbiAgaWYgKHN0YXRTeW5jTm9FeGNlcHRpb24oY29tcGlsZXJjKSkge1xuICAgIGQoYEZvdW5kIGEgLmNvbXBpbGVyYyBhdCAke2NvbXBpbGVyY30sIHVzaW5nIGl0YCk7XG4gICAgcmV0dXJuIGF3YWl0IGNyZWF0ZUNvbXBpbGVySG9zdEZyb21Db25maWdGaWxlKGNvbXBpbGVyYywgcm9vdENhY2hlRGlyKTtcbiAgfVxuXG4gIGxldCBiYWJlbHJjID0gcGF0aC5qb2luKHJvb3REaXIsICcuYmFiZWxyYycpO1xuICBpZiAoc3RhdFN5bmNOb0V4Y2VwdGlvbihiYWJlbHJjKSkge1xuICAgIGQoYEZvdW5kIGEgLmJhYmVscmMgYXQgJHtiYWJlbHJjfSwgdXNpbmcgaXRgKTtcbiAgICByZXR1cm4gYXdhaXQgY3JlYXRlQ29tcGlsZXJIb3N0RnJvbUJhYmVsUmMoYmFiZWxyYywgcm9vdENhY2hlRGlyKTtcbiAgfVxuXG4gIGQoYFVzaW5nIHBhY2thZ2UuanNvbiBvciBkZWZhdWx0IHBhcmFtZXRlcnMgYXQgJHtyb290RGlyfWApO1xuICByZXR1cm4gYXdhaXQgY3JlYXRlQ29tcGlsZXJIb3N0RnJvbUJhYmVsUmMocGF0aC5qb2luKHJvb3REaXIsICdwYWNrYWdlLmpzb24nKSwgcm9vdENhY2hlRGlyKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUNvbXBpbGVySG9zdEZyb21CYWJlbFJjU3luYyhmaWxlLCByb290Q2FjaGVEaXI9bnVsbCkge1xuICBsZXQgaW5mbyA9IEpTT04ucGFyc2UoZnMucmVhZEZpbGVTeW5jKGZpbGUsICd1dGY4JykpO1xuXG4gIC8vIHBhY2thZ2UuanNvblxuICBpZiAoJ2JhYmVsJyBpbiBpbmZvKSB7XG4gICAgaW5mbyA9IGluZm8uYmFiZWw7XG4gIH1cblxuICBpZiAoJ2VudicgaW4gaW5mbykge1xuICAgIGxldCBvdXJFbnYgPSBwcm9jZXNzLmVudi5CQUJFTF9FTlYgfHwgcHJvY2Vzcy5lbnYuTk9ERV9FTlYgfHwgJ2RldmVsb3BtZW50JztcbiAgICBpbmZvID0gaW5mby5lbnZbb3VyRW52XTtcbiAgfVxuXG4gIC8vIEFyZSB3ZSBzdGlsbCBwYWNrYWdlLmpzb24gKGkuZS4gaXMgdGhlcmUgbm8gYmFiZWwgaW5mbyB3aGF0c29ldmVyPylcbiAgaWYgKCduYW1lJyBpbiBpbmZvICYmICd2ZXJzaW9uJyBpbiBpbmZvKSB7XG4gICAgcmV0dXJuIGNyZWF0ZUNvbXBpbGVySG9zdEZyb21Db25maWd1cmF0aW9uKHtcbiAgICAgIGFwcFJvb3Q6IHBhdGguZGlybmFtZShmaWxlKSxcbiAgICAgIG9wdGlvbnM6IGdldERlZmF1bHRDb25maWd1cmF0aW9uKCksXG4gICAgICByb290Q2FjaGVEaXJcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBjcmVhdGVDb21waWxlckhvc3RGcm9tQ29uZmlndXJhdGlvbih7XG4gICAgYXBwUm9vdDogcGF0aC5kaXJuYW1lKGZpbGUpLFxuICAgIG9wdGlvbnM6IHtcbiAgICAgICdhcHBsaWNhdGlvbi9qYXZhc2NyaXB0JzogaW5mb1xuICAgIH0sXG4gICAgcm9vdENhY2hlRGlyXG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ29tcGlsZXJIb3N0RnJvbUNvbmZpZ0ZpbGVTeW5jKGZpbGUsIHJvb3RDYWNoZURpcj1udWxsKSB7XG4gIGxldCBpbmZvID0gSlNPTi5wYXJzZShmcy5yZWFkRmlsZVN5bmMoZmlsZSwgJ3V0ZjgnKSk7XG5cbiAgaWYgKCdlbnYnIGluIGluZm8pIHtcbiAgICBsZXQgb3VyRW52ID0gcHJvY2Vzcy5lbnYuRUxFQ1RST05fQ09NUElMRV9FTlYgfHwgcHJvY2Vzcy5lbnYuTk9ERV9FTlYgfHwgJ2RldmVsb3BtZW50JztcbiAgICBpbmZvID0gaW5mby5lbnZbb3VyRW52XTtcbiAgfVxuXG4gIHJldHVybiBjcmVhdGVDb21waWxlckhvc3RGcm9tQ29uZmlndXJhdGlvbih7XG4gICAgYXBwUm9vdDogcGF0aC5kaXJuYW1lKGZpbGUpLFxuICAgIG9wdGlvbnM6IGluZm8sXG4gICAgcm9vdENhY2hlRGlyXG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ29tcGlsZXJIb3N0RnJvbVByb2plY3RSb290U3luYyhyb290RGlyLCByb290Q2FjaGVEaXI9bnVsbCkge1xuICBsZXQgY29tcGlsZXJjID0gcGF0aC5qb2luKHJvb3REaXIsICcuY29tcGlsZXJjJyk7XG4gIGlmIChzdGF0U3luY05vRXhjZXB0aW9uKGNvbXBpbGVyYykpIHtcbiAgICBkKGBGb3VuZCBhIC5jb21waWxlcmMgYXQgJHtjb21waWxlcmN9LCB1c2luZyBpdGApO1xuICAgIHJldHVybiBjcmVhdGVDb21waWxlckhvc3RGcm9tQ29uZmlnRmlsZVN5bmMoY29tcGlsZXJjLCByb290Q2FjaGVEaXIpO1xuICB9XG5cbiAgbGV0IGJhYmVscmMgPSBwYXRoLmpvaW4ocm9vdERpciwgJy5iYWJlbHJjJyk7XG4gIGlmIChzdGF0U3luY05vRXhjZXB0aW9uKGJhYmVscmMpKSB7XG4gICAgZChgRm91bmQgYSAuYmFiZWxyYyBhdCAke2JhYmVscmN9LCB1c2luZyBpdGApO1xuICAgIHJldHVybiBjcmVhdGVDb21waWxlckhvc3RGcm9tQmFiZWxSY1N5bmMoYmFiZWxyYywgcm9vdENhY2hlRGlyKTtcbiAgfVxuXG4gIGQoYFVzaW5nIHBhY2thZ2UuanNvbiBvciBkZWZhdWx0IHBhcmFtZXRlcnMgYXQgJHtyb290RGlyfWApO1xuICByZXR1cm4gY3JlYXRlQ29tcGlsZXJIb3N0RnJvbUJhYmVsUmNTeW5jKHBhdGguam9pbihyb290RGlyLCAncGFja2FnZS5qc29uJyksIHJvb3RDYWNoZURpcik7XG59XG5cbi8qKlxuICogUmV0dXJucyB3aGF0IGVsZWN0cm9uLWNvbXBpbGUgd291bGQgdXNlIGFzIGEgZGVmYXVsdCByb290Q2FjaGVEaXIuIFVzdWFsbHkgb25seVxuICogdXNlZCBmb3IgZGVidWdnaW5nIHB1cnBvc2VzXG4gKlxuICogQHJldHVybiB7c3RyaW5nfSAgQSBwYXRoIHRoYXQgbWF5IG9yIG1heSBub3QgZXhpc3Qgd2hlcmUgZWxlY3Ryb24tY29tcGlsZSB3b3VsZFxuICogICAgICAgICAgICAgICAgICAgc2V0IHVwIGEgZGV2ZWxvcG1lbnQgbW9kZSBjYWNoZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNhbGN1bGF0ZURlZmF1bHRDb21waWxlQ2FjaGVEaXJlY3RvcnkoKSB7XG4gIGxldCB0bXBEaXIgPSBwcm9jZXNzLmVudi5URU1QIHx8IHByb2Nlc3MuZW52LlRNUERJUiB8fCAnL3RtcCc7XG4gIGxldCBoYXNoID0gcmVxdWlyZSgnY3J5cHRvJykuY3JlYXRlSGFzaCgnbWQ1JykudXBkYXRlKHByb2Nlc3MuZXhlY1BhdGgpLmRpZ2VzdCgnaGV4Jyk7XG5cbiAgbGV0IGNhY2hlRGlyID0gcGF0aC5qb2luKHRtcERpciwgYGNvbXBpbGVDYWNoZV8ke2hhc2h9YCk7XG4gIG1rZGlycC5zeW5jKGNhY2hlRGlyKTtcblxuICBkKGBVc2luZyBkZWZhdWx0IGNhY2hlIGRpcmVjdG9yeTogJHtjYWNoZURpcn1gKTtcbiAgcmV0dXJuIGNhY2hlRGlyO1xufVxuXG5cbi8qKlxuICogUmV0dXJucyB0aGUgZGVmYXVsdCAuY29uZmlncmMgaWYgbm8gY29uZmlndXJhdGlvbiBpbmZvcm1hdGlvbiBjYW4gYmUgZm91bmQuXG4gKlxuICogQHJldHVybiB7T2JqZWN0fSAgQSBsaXN0IG9mIGRlZmF1bHQgY29uZmlnIHNldHRpbmdzIGZvciBlbGVjdHJvbi1jb21waWxlci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldERlZmF1bHRDb25maWd1cmF0aW9uKCkge1xuICByZXR1cm4ge1xuICAgICdhcHBsaWNhdGlvbi9qYXZhc2NyaXB0Jzoge1xuICAgICAgXCJwcmVzZXRzXCI6IFtcInN0YWdlLTBcIiwgXCJlczIwMTVcIiwgXCJyZWFjdFwiXSxcbiAgICAgIFwic291cmNlTWFwc1wiOiBcImlubGluZVwiXG4gICAgfVxuICB9O1xufVxuXG4vKipcbiAqIEFsbG93cyB5b3UgdG8gY3JlYXRlIG5ldyBpbnN0YW5jZXMgb2YgYWxsIGNvbXBpbGVycyB0aGF0IGFyZSBzdXBwb3J0ZWQgYnlcbiAqIGVsZWN0cm9uLWNvbXBpbGUgYW5kIHVzZSB0aGVtIGRpcmVjdGx5LiBDdXJyZW50bHkgc3VwcG9ydHMgQmFiZWwsIENvZmZlZVNjcmlwdCxcbiAqIFR5cGVTY3JpcHQsIExlc3MsIGFuZCBKYWRlLlxuICpcbiAqIEByZXR1cm4ge09iamVjdH0gIEFuIE9iamVjdCB3aG9zZSBLZXlzIGFyZSBNSU1FIHR5cGVzLCBhbmQgd2hvc2UgdmFsdWVzXG4gKiBhcmUgaW5zdGFuY2VzIG9mIEB7bGluayBDb21waWxlckJhc2V9LlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ29tcGlsZXJzKCkge1xuICBpZiAoIWFsbENvbXBpbGVyQ2xhc3Nlcykge1xuICAgIC8vIEZpcnN0IHdlIHdhbnQgdG8gc2VlIGlmIGVsZWN0cm9uLWNvbXBpbGVycyBpdHNlbGYgaGFzIGJlZW4gaW5zdGFsbGVkIHdpdGhcbiAgICAvLyBkZXZEZXBlbmRlbmNpZXMuIElmIHRoYXQncyBub3QgdGhlIGNhc2UsIGNoZWNrIHRvIHNlZSBpZlxuICAgIC8vIGVsZWN0cm9uLWNvbXBpbGVycyBpcyBpbnN0YWxsZWQgYXMgYSBwZWVyIGRlcGVuZGVuY3kgKHByb2JhYmx5IGFzIGFcbiAgICAvLyBkZXZEZXBlbmRlbmN5IG9mIHRoZSByb290IHByb2plY3QpLlxuICAgIGNvbnN0IGxvY2F0aW9ucyA9IFsnZWxlY3Ryb24tY29tcGlsZXJzJywgJy4uLy4uL2VsZWN0cm9uLWNvbXBpbGVycyd