electron-compile
Version:
Electron supporting package to compile JS and CSS in Electron applications
589 lines (473 loc) • 44.4 kB
JavaScript
'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 ? null : arguments[1];
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(_x3) {
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 ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee2(file) {
var rootCacheDir = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1];
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(_x5) {
return ref.apply(this, arguments);
};
}();
/**
* Creates a configured {@link CompilerHost} instance from the project root
* directory. This method first searches for a .compilerc, 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 ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee3(rootDir) {
var rootCacheDir = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1];
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:
babelrc = _path2.default.join(rootDir, '.babelrc');
if (!statSyncNoException(babelrc)) {
_context3.next = 12;
break;
}
d('Found a .babelrc at ' + babelrc + ', using it');
_context3.next = 11;
return createCompilerHostFromBabelRc(babelrc, rootCacheDir);
case 11:
return _context3.abrupt('return', _context3.sent);
case 12:
d('Using package.json or default parameters at ' + rootDir);
_context3.next = 15;
return createCompilerHostFromBabelRc(_path2.default.join(rootDir, 'package.json'), rootCacheDir);
case 15:
return _context3.abrupt('return', _context3.sent);
case 16:
case 'end':
return _context3.stop();
}
}
}, _callee3, this);
}));
return function createCompilerHostFromProjectRoot(_x7) {
return ref.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 _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _fs = require('fs');
var _fs2 = _interopRequireDefault(_fs);
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
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 _protocolHook = require('./protocol-hook');
var _requireHook = require('./require-hook');
var _requireHook2 = _interopRequireDefault(_requireHook);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var d = require('debug')('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') {
var _require = require('electron');
var app = _require.app;
var protoify = function protoify() {
(0, _protocolHook.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.
*/
function init(appRoot, mainModule) {
var productionMode = arguments.length <= 2 || arguments[2] === undefined ? null : arguments[2];
var compilerHost = null;
var cacheDir = _path2.default.join(appRoot, '.cache');
if (productionMode === null) {
productionMode = !!statSyncNoException(cacheDir);
}
if (productionMode) {
// In read-only mode, we'll assume that everything is in `appRoot/.cache`
compilerHost = _compilerHost2.default.createReadonlyFromConfigurationSync(cacheDir, appRoot);
} 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 ret = new _compilerHost2.default(rootCacheDir, compilers, fileChangeCache, false, compilers['text/plain']);
_lodash2.default.each((0, _keys2.default)(info.options || {}), function (x) {
var opts = info.options[x];
if (!(x in compilers)) {
throw new Error('Found compiler settings for missing compiler: ' + x);
}
d('Setting options for ' + x + ': ' + (0, _stringify2.default)(opts));
compilers[x].compilerOptions = opts;
});
// 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 ? null : arguments[1];
var info = JSON.parse(_fs2.default.readFileSync(file, 'utf8'));
// package.json
if ('babel' in info) {
info = info.babel;
}
if ('env' in info) {
var _ourEnv2 = process.env.BABEL_ENV || process.env.NODE_ENV || 'development';
info = info.env[_ourEnv2];
}
// 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 ? null : arguments[1];
var info = JSON.parse(_fs2.default.readFileSync(file, 'utf8'));
if ('env' in info) {
var _ourEnv3 = process.env.ELECTRON_COMPILE_ENV || process.env.NODE_ENV || 'development';
info = info.env[_ourEnv3];
}
return createCompilerHostFromConfiguration({
appRoot: _path2.default.dirname(file),
options: info,
rootCacheDir: rootCacheDir
});
}
function createCompilerHostFromProjectRootSync(rootDir) {
var rootCacheDir = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1];
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 = _lodash2.default.map(allCompilerClasses, function (Klass) {
if ('createFromCompilers' in Klass) {
return Klass.createFromCompilers(ret);
} else {
return new Klass();
}
});
_lodash2.default.reduce(instantiatedClasses, 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9jb25maWctcGFyc2VyLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7dUVBdUlPLGlCQUE2QyxJQUE3QztRQUFtRCxxRUFBYTtRQUNqRSxNQVFFOzs7OzswQkFSSzs7bUJBQWlCLGFBQUksUUFBSixDQUFhLElBQWIsRUFBbUIsTUFBbkI7Ozs7QUFBeEIsK0JBQVk7Ozs7QUFHaEIsZ0JBQUksV0FBVyxJQUFYLEVBQWlCO0FBQ25CLHFCQUFPLEtBQUssS0FBTCxDQURZO2FBQXJCOztBQUlBLGdCQUFJLFNBQVMsSUFBVCxFQUFlO0FBQ2IsdUJBQVMsUUFBUSxHQUFSLENBQVksU0FBWixJQUF5QixRQUFRLEdBQVIsQ0FBWSxRQUFaLElBQXdCLGFBQWpELENBREk7O0FBRWpCLHFCQUFPLEtBQUssR0FBTCxDQUFTLE1BQVQsQ0FBUCxDQUZpQjthQUFuQjs7OztrQkFNSSxVQUFVLElBQVYsSUFBa0IsYUFBYSxJQUFiOzs7Ozs2Q0FDYixvQ0FBb0M7QUFDekMsdUJBQVMsZUFBSyxPQUFMLENBQWEsSUFBYixDQUFUO0FBQ0EsdUJBQVMseUJBQVQ7QUFDQSx3Q0FIeUM7YUFBcEM7Ozs2Q0FPRixvQ0FBb0M7QUFDekMsdUJBQVMsZUFBSyxPQUFMLENBQWEsSUFBYixDQUFUO0FBQ0EsdUJBQVM7QUFDUCwwQ0FBMEIsSUFBMUI7ZUFERjtBQUdBLHdDQUx5QzthQUFwQzs7Ozs7Ozs7R0F0QkY7a0JBQWU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozt1RUEwQ2Ysa0JBQWdELElBQWhEO1FBQXNELHFFQUFhOztRQUNwRSxNQUdFOzs7Ozs7MkJBSEs7O21CQUFpQixhQUFJLFFBQUosQ0FBYSxJQUFiLEVBQW1CLE1BQW5COzs7O0FBQXhCLGdDQUFZOzs7QUFFaEIsZ0JBQUksU0FBUyxJQUFULEVBQWU7QUFDYix3QkFBUyxRQUFRLEdBQVIsQ0FBWSxvQkFBWixJQUFvQyxRQUFRLEdBQVIsQ0FBWSxRQUFa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UCxDQUp1QztHQUFYLEVBSzNCLEdBTEgsRUFsQ2dDOztBQXlDaEMsU0FBTyxHQUFQLENBekNnQztDQUEzQiIsImZpbGUiOiJjb25maWctcGFyc2VyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCBmcyBmcm9tICdmcyc7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCBta2RpcnAgZnJvbSAnbWtkaXJwJztcbmltcG9ydCB7cGZzfSBmcm9tICcuL3Byb21pc2UnO1xuXG5pbXBvcnQgRmlsZUNoYW5nZWRDYWNoZSBmcm9tICcuL2ZpbGUtY2hhbmdlLWNhY2hlJztcbmltcG9ydCBDb21waWxlckhvc3QgZnJvbSAnLi9jb21waWxlci1ob3N0JztcbmltcG9ydCB7IGluaXRpYWxpemVQcm90b2NvbEhvb2sgfSBmcm9tICcuL3Byb3RvY29sLWhvb2snO1xuaW1wb3J0IHJlZ2lzdGVyUmVxdWlyZUV4dGVuc2lvbiBmcm9tICcuL3JlcXVpcmUtaG9vayc7XG5cbmNvbnN0IGQgPSByZXF1aXJlKCdkZWJ1ZycpKCdlbGVjdHJvbi1jb21waWxlOmNvbmZpZy1wYXJzZXInKTtcblxuLy8gTkI6IFdlIGludGVudGlvbmFsbHkgZGVsYXktbG9hZCB0aGlzIHNvIHRoYXQgaW4gcHJvZHVjdGlvbiwgeW91IGNhbiBjcmVhdGVcbi8vIGNhY2hlLW9ubHkgdmVyc2lvbnMgb2YgdGhlc2UgY29tcGlsZXJzXG5sZXQgYWxsQ29tcGlsZXJDbGFzc2VzID0gbnVsbDtcblxuZnVuY3Rpb24gc3RhdFN5bmNOb0V4Y2VwdGlvbihmc1BhdGgpIHtcbiAgaWYgKCdzdGF0U3luY05vRXhjZXB0aW9uJyBpbiBmcykge1xuICAgIHJldHVybiBmcy5zdGF0U3luY05vRXhjZXB0aW9uKGZzUGF0aCk7XG4gIH1cbiAgXG4gIHRyeSB7XG4gICAgcmV0dXJuIGZzLnN0YXRTeW5jKGZzUGF0aCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG5cbi8qKlxuICogSW5pdGlhbGl6ZSB0aGUgZ2xvYmFsIGhvb2tzIChwcm90b2NvbCBob29rIGZvciBmaWxlOiwgbm9kZS5qcyBob29rKSBcbiAqIGluZGVwZW5kZW50IG9mIGluaXRpYWxpemluZyB0aGUgY29tcGlsZXIuIFRoaXMgbWV0aG9kIGlzIHVzdWFsbHkgY2FsbGVkIGJ5XG4gKiBpbml0IGluc3RlYWQgb2YgZGlyZWN0bHlcbiAqIFxuICogQHBhcmFtIHtDb21waWxlckhvc3R9IGNvbXBpbGVySG9zdCAgVGhlIGNvbXBpbGVyIGhvc3QgdG8gdXNlLlxuICogIFxuICovIFxuZXhwb3J0IGZ1bmN0aW9uIGluaXRpYWxpemVHbG9iYWxIb29rcyhjb21waWxlckhvc3QpIHtcbiAgbGV0IGdsb2JhbFZhciA9IChnbG9iYWwgfHwgd2luZG93KTtcbiAgZ2xvYmFsVmFyLmdsb2JhbENvbXBpbGVySG9zdCA9IGNvbXBpbGVySG9zdDtcblxuICByZWdpc3RlclJlcXVpcmVFeHRlbnNpb24oY29tcGlsZXJIb3N0KTtcblxuICBpZiAoJ3R5cGUnIGluIHByb2Nlc3MgJiYgcHJvY2Vzcy50eXBlID09PSAnYnJvd3NlcicpIHtcbiAgICBjb25zdCB7IGFwcCB9ID0gcmVxdWlyZSgnZWxlY3Ryb24nKTtcbiAgICBcbiAgICBsZXQgcHJvdG9pZnkgPSBmdW5jdGlvbigpIHsgaW5pdGlhbGl6ZVByb3RvY29sSG9vayhjb21waWxlckhvc3QpOyB9O1xuICAgIGlmIChhcHAuaXNSZWFkeSgpKSB7XG4gICAgICBwcm90b2lmeSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhcHAub24oJ3JlYWR5JywgcHJvdG9pZnkpO1xuICAgIH1cbiAgfVxufVxuXG5cbi8qKlxuICogSW5pdGlhbGl6ZSBlbGVjdHJvbi1jb21waWxlIGFuZCBzZXQgaXQgdXAsIGVpdGhlciBmb3IgZGV2ZWxvcG1lbnQgb3IgXG4gKiBwcm9kdWN0aW9uIHVzZS4gVGhpcyBpcyBhbG1vc3QgYWx3YXlzIHRoZSBvbmx5IG1ldGhvZCB5b3UgbmVlZCB0byB1c2UgaW4gb3JkZXJcbiAqIHRvIHVzZSBlbGVjdHJvbi1jb21waWxlLlxuICogIFxuICogQHBhcmFtICB7c3RyaW5nfSBhcHBSb290ICBUaGUgdG9wLWxldmVsIGRpcmVjdG9yeSBmb3IgeW91ciBhcHBsaWNhdGlvbiAoaS5lLlxuICogICAgICAgICAgICAgICAgICAgICAgICAgICB0aGUgb25lIHdoaWNoIGhhcyB5b3VyIHBhY2thZ2UuanNvbikuXG4gKlxuICogQHBhcmFtICB7c3RyaW5nfSBtYWluTW9kdWxlICBUaGUgbW9kdWxlIHRvIHJlcXVpcmUgaW4sIHJlbGF0aXZlIHRvIHRoZSBtb2R1bGVcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGluZyBpbml0LCB0aGF0IHdpbGwgc3RhcnQgeW91ciBhcHAuIFdyaXRlIHRoaXMgXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzIGlmIHlvdSB3ZXJlIHdyaXRpbmcgYSByZXF1aXJlIGNhbGwgZnJvbSBoZXJlLlxuICpcbiAqIEBwYXJhbSAge2Jvb2x9IHByb2R1Y3Rpb25Nb2RlICAgSWYgZXhwbGljaXRseSBUcnVlL0ZhbHNlLCB3aWxsIHNldCByZWFkLW9ubHlcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZSB0byBiZSBkaXNhYmxlZC9lbmFibGVkLiBJZiBub3QsIHdlJ2xsXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGd1ZXNzIGJhc2VkIG9uIHRoZSBwcmVzZW5jZSBvZiBhIHByb2R1Y3Rpb25cbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FjaGUuXG4gKi8gXG5leHBvcnQgZnVuY3Rpb24gaW5pdChhcHBSb290LCBtYWluTW9kdWxlLCBwcm9kdWN0aW9uTW9kZSA9IG51bGwpIHtcbiAgbGV0IGNvbXBpbGVySG9zdCA9IG51bGw7XG4gIGxldCBjYWNoZURpciA9IHBhdGguam9pbihhcHBSb290LCAnLmNhY2hlJyk7XG4gIFxuICBpZiAocHJvZHVjdGlvbk1vZGUgPT09IG51bGwpIHtcbiAgICBwcm9kdWN0aW9uTW9kZSA9ICEhc3RhdFN5bmNOb0V4Y2VwdGlvbihjYWNoZURpcik7XG4gIH1cbiAgXG4gIGlmIChwcm9kdWN0aW9uTW9kZSkge1xuICAgIC8vIEluIHJlYWQtb25seSBtb2RlLCB3ZSdsbCBhc3N1bWUgdGhhdCBldmVyeXRoaW5nIGlzIGluIGBhcHBSb290Ly5jYWNoZWBcbiAgICBjb21waWxlckhvc3QgPSBDb21waWxlckhvc3QuY3JlYXRlUmVhZG9ubHlGcm9tQ29uZmlndXJhdGlvblN5bmMoY2FjaGVEaXIsIGFwcFJvb3QpO1xuICB9IGVsc2Uge1xuICAgIGNvbXBpbGVySG9zdCA9IGNyZWF0ZUNvbXBpbGVySG9zdEZyb21Qcm9qZWN0Um9vdFN5bmMoYXBwUm9vdCk7XG4gIH1cbiAgXG4gIGluaXRpYWxpemVHbG9iYWxIb29rcyhjb21waWxlckhvc3QpO1xuICByZXF1aXJlLm1haW4ucmVxdWlyZShtYWluTW9kdWxlKTtcbn1cblxuXG4vKipcbiAqIENyZWF0ZXMgYSB7QGxpbmsgQ29tcGlsZXJIb3N0fSB3aXRoIHRoZSBnaXZlbiBpbmZvcm1hdGlvbi4gVGhpcyBtZXRob2QgaXNcbiAqIHVzdWFsbHkgY2FsbGVkIGJ5IHtAbGluayBjcmVhdGVDb21waWxlckhvc3RGcm9tUHJvamVjdFJvb3R9LlxuICogIFxuICogQHByaXZhdGVcbiAqLyBcbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDb21waWxlckhvc3RGcm9tQ29uZmlndXJhdGlvbihpbmZvKSB7XG4gIGxldCBjb21waWxlcnMgPSBjcmVhdGVDb21waWxlcnMoKTtcbiAgbGV0IHJvb3RDYWNoZURpciA9IGluZm8ucm9vdENhY2hlRGlyIHx8IGNhbGN1bGF0ZURlZmF1bHRDb21waWxlQ2FjaGVEaXJlY3RvcnkoKTtcbiAgXG4gIGQoYENyZWF0aW5nIENvbXBpbGVySG9zdDogJHtKU09OLnN0cmluZ2lmeShpbmZvKX0sIHJvb3RDYWNoZURpciA9ICR7cm9vdENhY2hlRGlyfWApO1xuICBsZXQgZmlsZUNoYW5nZUNhY2hlID0gbmV3IEZpbGVDaGFuZ2VkQ2FjaGUoaW5mby5hcHBSb290KTtcbiAgbGV0IHJldCA9IG5ldyBDb21waWxlckhvc3Qocm9vdENhY2hlRGlyLCBjb21waWxlcnMsIGZpbGVDaGFuZ2VDYWNoZSwgZmFsc2UsIGNvbXBpbGVyc1sndGV4dC9wbGFpbiddKTtcbiAgXG4gIF8uZWFjaChPYmplY3Qua2V5cyhpbmZvLm9wdGlvbnMgfHwge30pLCAoeCkgPT4ge1xuICAgIGxldCBvcHRzID0gaW5mby5vcHRpb25zW3hdO1xuICAgIGlmICghKHggaW4gY29tcGlsZXJzKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGb3VuZCBjb21waWxlciBzZXR0aW5ncyBmb3IgbWlzc2luZyBjb21waWxlcjogJHt4fWApO1xuICAgIH1cbiAgICBcbiAgICBkKGBTZXR0aW5nIG9wdGlvbnMgZm9yICR7eH06ICR7SlNPTi5zdHJpbmdpZnkob3B0cyl9YCk7XG4gICAgY29tcGlsZXJzW3hdLmNvbXBpbGVyT3B0aW9ucyA9IG9wdHM7XG4gIH0pO1xuICBcbiAgLy8gTkI6IEl0J3Mgc3VwZXIgaW1wb3J0YW50IHRoYXQgd2UgZ3VhcmFudGVlIHRoYXQgdGhlIGNvbmZpZ3VyYXRpb24gaXMgc2F2ZWRcbiAgLy8gb3V0LCBiZWNhdXNlIHdlJ2xsIG5lZWQgdG8gcmUtcmVhZCBpdCBpbiB0aGUgcmVuZGVyZXIgcHJvY2Vzc1xuICBkKGBDcmVhdGVkIGNvbXBpbGVyIGhvc3Qgd2l0aCBvcHRpb25zOiAke0pTT04uc3RyaW5naWZ5KGluZm8pfWApO1xuICByZXQuc2F2ZUNvbmZpZ3VyYXRpb25TeW5jKCk7XG4gIHJldHVybiByZXQ7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIGNvbXBpbGVyIGhvc3QgZnJvbSBhIC5iYWJlbHJjIGZpbGUuIFRoaXMgbWV0aG9kIGlzIHVzdWFsbHkgY2FsbGVkXG4gKiBmcm9tIHtAbGluayBjcmVhdGVDb21waWxlckhvc3RGcm9tUHJvamVjdFJvb3R9IGluc3RlYWQgb2YgdXNlZCBkaXJlY3RseS5cbiAqICBcbiAqIEBwYXJhbSAge3N0cmluZ30gZmlsZSAgVGhlIHBhdGggdG8gYSAuYmFiZWxyYyBmaWxlXG4gKlxuICogQHBhcmFtICB7c3RyaW5nfSByb290Q2FjaGVEaXIgKG9wdGlvbmFsKSAgVGhlIGRpcmVjdG9yeSB0byB1c2UgYXMgYSBjYWNoZS5cbiAqXG4gKiBAcmV0dXJuIHtQcm9taXNlPENvbXBpbGVySG9zdD59ICBBIHNldC11cCBjb21waWxlciBob3N0XG4gKi8gXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlQ29tcGlsZXJIb3N0RnJvbUJhYmVsUmMoZmlsZSwgcm9vdENhY2hlRGlyPW51bGwpIHtcbiAgbGV0IGluZm8gPSBKU09OLnBhcnNlKGF3YWl0IHBmcy5yZWFkRmlsZShmaWxlLCAndXRmOCcpKTtcbiAgXG4gIC8vIHBhY2thZ2UuanNvblxuICBpZiAoJ2JhYmVsJyBpbiBpbmZvKSB7XG4gICAgaW5mbyA9IGluZm8uYmFiZWw7XG4gIH1cbiAgXG4gIGlmICgnZW52JyBpbiBpbmZvKSB7XG4gICAgbGV0IG91ckVudiA9IHByb2Nlc3MuZW52LkJBQkVMX0VOViB8fCBwcm9jZXNzLmVudi5OT0RFX0VOViB8fCAnZGV2ZWxvcG1lbnQnO1xuICAgIGluZm8gPSBpbmZvLmVudltvdXJFbnZdO1xuICB9XG4gIFxuICAvLyBBcmUgd2Ugc3RpbGwgcGFja2FnZS5qc29uIChpLmUuIGlzIHRoZXJlIG5vIGJhYmVsIGluZm8gd2hhdHNvZXZlcj8pXG4gIGlmICgnbmFtZScgaW4gaW5mbyAmJiAndmVyc2lvbicgaW4gaW5mbykge1xuICAgIHJldHVybiBjcmVhdGVDb21waWxlckhvc3RGcm9tQ29uZmlndXJhdGlvbih7XG4gICAgICBhcHBSb290OiBwYXRoLmRpcm5hbWUoZmlsZSksXG4gICAgICBvcHRpb25zOiBnZXREZWZhdWx0Q29uZmlndXJhdGlvbigpLFxuICAgICAgcm9vdENhY2hlRGlyXG4gICAgfSk7XG4gIH1cbiAgXG4gIHJldHVybiBjcmVhdGVDb21waWxlckhvc3RGcm9tQ29uZmlndXJhdGlvbih7XG4gICAgYXBwUm9vdDogcGF0aC5kaXJuYW1lKGZpbGUpLFxuICAgIG9wdGlvbnM6IHtcbiAgICAgICdhcHBsaWNhdGlvbi9qYXZhc2NyaXB0JzogaW5mb1xuICAgIH0sXG4gICAgcm9vdENhY2hlRGlyXG4gIH0pO1xufVxuXG5cbi8qKlxuICogQ3JlYXRlcyBhIGNvbXBpbGVyIGhvc3QgZnJvbSBhIC5jb21waWxlcmMgZmlsZS4gVGhpcyBtZXRob2QgaXMgdXN1YWxseSBjYWxsZWRcbiAqIGZyb20ge0BsaW5rIGNyZWF0ZUNvbXBpbGVySG9zdEZyb21Qcm9qZWN0Um9vdH0gaW5zdGVhZCBvZiB1c2VkIGRpcmVjdGx5LlxuICogIFxuICogQHBhcmFtICB7c3RyaW5nfSBmaWxlICBUaGUgcGF0aCB0byBhIC5jb21waWxlcmMgZmlsZVxuICpcbiAqIEBwYXJhbSAge3N0cmluZ30gcm9vdENhY2hlRGlyIChvcHRpb25hbCkgIFRoZSBkaXJlY3RvcnkgdG8gdXNlIGFzIGEgY2FjaGUuXG4gKlxuICogQHJldHVybiB7UHJvbWlzZTxDb21waWxlckhvc3Q+fSAgQSBzZXQtdXAgY29tcGlsZXIgaG9zdFxuICovIFxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUNvbXBpbGVySG9zdEZyb21Db25maWdGaWxlKGZpbGUsIHJvb3RDYWNoZURpcj1udWxsKSB7XG4gIGxldCBpbmZvID0gSlNPTi5wYXJzZShhd2FpdCBwZnMucmVhZEZpbGUoZmlsZSwgJ3V0ZjgnKSk7XG4gIFxuICBpZiAoJ2VudicgaW4gaW5mbykge1xuICAgIGxldCBvdXJFbnYgPSBwcm9jZXNzLmVudi5FTEVDVFJPTl9DT01QSUxFX0VOViB8fCBwcm9jZXNzLmVudi5OT0RFX0VOViB8fCAnZGV2ZWxvcG1lbnQnO1xuICAgIGluZm8gPSBpbmZvLmVudltvdXJFbnZdO1xuICB9XG4gIFxuICByZXR1cm4gY3JlYXRlQ29tcGlsZXJIb3N0RnJvbUNvbmZpZ3VyYXRpb24oe1xuICAgIGFwcFJvb3Q6IHBhdGguZGlybmFtZShmaWxlKSxcbiAgICBvcHRpb25zOiBpbmZvLFxuICAgIHJvb3RDYWNoZURpclxuICB9KTtcbn1cblxuXG4vKipcbiAqIENyZWF0ZXMgYSBjb25maWd1cmVkIHtAbGluayBDb21waWxlckhvc3R9IGluc3RhbmNlIGZyb20gdGhlIHByb2plY3Qgcm9vdCBcbiAqIGRpcmVjdG9yeS4gVGhpcyBtZXRob2QgZmlyc3Qgc2VhcmNoZXMgZm9yIGEgLmNvbXBpbGVyYywgdGhlbiBmYWxscyBiYWNrIHRvIHRoZVxuICogZGVmYXVsdCBsb2NhdGlvbnMgZm9yIEJhYmVsIGNvbmZpZ3VyYXRpb24gaW5mby4gSWYgbmVpdGhlciBhcmUgZm91bmQsIGRlZmF1bHRzXG4gKiB0byBzdGFuZGFyZCBzZXR0aW5nc1xuICogIFxuICogQHBhcmFtICB7c3RyaW5nfSByb290RGlyICBUaGUgcm9vdCBhcHBsaWNhdGlvbiBkaXJlY3RvcnkgKGkuZS4gdGhlIGRpcmVjdG9yeVxuICogICAgICAgICAgICAgICAgICAgICAgICAgICB0aGF0IGhhcyB0aGUgYXBwJ3MgcGFja2FnZS5qc29uKVxuICpcbiAqIEBwYXJhbSAge3N0cmluZ30gcm9vdENhY2hlRGlyIChvcHRpb25hbCkgIFRoZSBkaXJlY3RvcnkgdG8gdXNlIGFzIGEgY2FjaGUuXG4gKlxuICogQHJldHVybiB7UHJvbWlzZTxDb21waWxlckhvc3Q+fSAgQSBzZXQtdXAgY29tcGlsZXIgaG9zdFxuICovIFxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUNvbXBpbGVySG9zdEZyb21Qcm9qZWN0Um9vdChyb290RGlyLCByb290Q2FjaGVEaXI9bnVsbCkge1xuICBsZXQgY29tcGlsZXJjID0gcGF0aC5qb2luKHJvb3REaXIsICcuY29tcGlsZXJjJyk7XG4gIGlmIChzdGF0U3luY05vRXhjZXB0aW9uKGNvbXBpbGVyYykpIHtcbiAgICBkKGBGb3VuZCBhIC5jb21waWxlcmMgYXQgJHtjb21waWxlcmN9LCB1c2luZyBpdGApO1xuICAgIHJldHVybiBhd2FpdCBjcmVhdGVDb21waWxlckhvc3RGcm9tQ29uZmlnRmlsZShjb21waWxlcmMsIHJvb3RDYWNoZURpcik7XG4gIH1cbiAgXG4gIGxldCBiYWJlbHJjID0gcGF0aC5qb2luKHJvb3REaXIsICcuYmFiZWxyYycpO1xuICBpZiAoc3RhdFN5bmNOb0V4Y2VwdGlvbihiYWJlbHJjKSkge1xuICAgIGQoYEZvdW5kIGEgLmJhYmVscmMgYXQgJHtiYWJlbHJjfSwgdXNpbmcgaXRgKTtcbiAgICByZXR1cm4gYXdhaXQgY3JlYXRlQ29tcGlsZXJIb3N0RnJvbUJhYmVsUmMoYmFiZWxyYywgcm9vdENhY2hlRGlyKTtcbiAgfVxuICAgIFxuICBkKGBVc2luZyBwYWNrYWdlLmpzb24gb3IgZGVmYXVsdCBwYXJhbWV0ZXJzIGF0ICR7cm9vdERpcn1gKTtcbiAgcmV0dXJuIGF3YWl0IGNyZWF0ZUNvbXBpbGVySG9zdEZyb21CYWJlbFJjKHBhdGguam9pbihyb290RGlyLCAncGFja2FnZS5qc29uJyksIHJvb3RDYWNoZURpcik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDb21waWxlckhvc3RGcm9tQmFiZWxSY1N5bmMoZmlsZSwgcm9vdENhY2hlRGlyPW51bGwpIHtcbiAgbGV0IGluZm8gPSBKU09OLnBhcnNlKGZzLnJlYWRGaWxlU3luYyhmaWxlLCAndXRmOCcpKTtcbiAgXG4gIC8vIHBhY2thZ2UuanNvblxuICBpZiAoJ2JhYmVsJyBpbiBpbmZvKSB7XG4gICAgaW5mbyA9IGluZm8uYmFiZWw7XG4gIH1cbiAgXG4gIGlmICgnZW52JyBpbiBpbmZvKSB7XG4gICAgbGV0IG91ckVudiA9IHByb2Nlc3MuZW52LkJBQkVMX0VOViB8fCBwcm9jZXNzLmVudi5OT0RFX0VOViB8fCAnZGV2ZWxvcG1lbnQnO1xuICAgIGluZm8gPSBpbmZvLmVudltvdXJFbnZdO1xuICB9XG4gIFxuICAvLyBBcmUgd2Ugc3RpbGwgcGFja2FnZS5qc29uIChpLmUuIGlzIHRoZXJlIG5vIGJhYmVsIGluZm8gd2hhdHNvZXZlcj8pXG4gIGlmICgnbmFtZScgaW4gaW5mbyAmJiAndmVyc2lvbicgaW4gaW5mbykge1xuICAgIHJldHVybiBjcmVhdGVDb21waWxlckhvc3RGcm9tQ29uZmlndXJhdGlvbih7XG4gICAgICBhcHBSb290OiBwYXRoLmRpcm5hbWUoZmlsZSksXG4gICAgICBvcHRpb25zOiBnZXREZWZhdWx0Q29uZmlndXJhdGlvbigpLFxuICAgICAgcm9vdENhY2hlRGlyXG4gICAgfSk7XG4gIH1cbiAgXG4gIHJldHVybiBjcmVhdGVDb21waWxlckhvc3RGcm9tQ29uZmlndXJhdGlvbih7XG4gICAgYXBwUm9vdDogcGF0aC5kaXJuYW1lKGZpbGUpLFxuICAgIG9wdGlvbnM6IHtcbiAgICAgICdhcHBsaWNhdGlvbi9qYXZhc2NyaXB0JzogaW5mb1xuICAgIH0sXG4gICAgcm9vdENhY2hlRGlyXG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ29tcGlsZXJIb3N0RnJvbUNvbmZpZ0ZpbGVTeW5jKGZpbGUsIHJvb3RDYWNoZURpcj1udWxsKSB7XG4gIGxldCBpbmZvID0gSlNPTi5wYXJzZShmcy5yZWFkRmlsZVN5bmMoZmlsZSwgJ3V0ZjgnKSk7XG4gIFxuICBpZiAoJ2VudicgaW4gaW5mbykge1xuICAgIGxldCBvdXJFbnYgPSBwcm9jZXNzLmVudi5FTEVDVFJPTl9DT01QSUxFX0VOViB8fCBwcm9jZXNzLmVudi5OT0RFX0VOViB8fCAnZGV2ZWxvcG1lbnQnO1xuICAgIGluZm8gPSBpbmZvLmVudltvdXJFbnZdO1xuICB9XG4gIFxuICByZXR1cm4gY3JlYXRlQ29tcGlsZXJIb3N0RnJvbUNvbmZpZ3VyYXRpb24oe1xuICAgIGFwcFJvb3Q6IHBhdGguZGlybmFtZShmaWxlKSxcbiAgICBvcHRpb25zOiBpbmZvLFxuICAgIHJvb3RDYWNoZURpclxuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUNvbXBpbGVySG9zdEZyb21Qcm9qZWN0Um9vdFN5bmMocm9vdERpciwgcm9vdENhY2hlRGlyPW51bGwpIHtcbiAgbGV0IGNvbXBpbGVyYyA9IHBhdGguam9pbihyb290RGlyLCAnLmNvbXBpbGVyYycpO1xuICBpZiAoc3RhdFN5bmNOb0V4Y2VwdGlvbihjb21waWxlcmMpKSB7XG4gICAgZChgRm91bmQgYSAuY29tcGlsZXJjIGF0ICR7Y29tcGlsZXJjfSwgdXNpbmcgaXRgKTtcbiAgICByZXR1cm4gY3JlYXRlQ29tcGlsZXJIb3N0RnJvbUNvbmZpZ0ZpbGVTeW5jKGNvbXBpbGVyYywgcm9vdENhY2hlRGlyKTtcbiAgfVxuICBcbiAgbGV0IGJhYmVscmMgPSBwYXRoLmpvaW4ocm9vdERpciwgJy5iYWJlbHJjJyk7XG4gIGlmIChzdGF0U3luY05vRXhjZXB0aW9uKGJhYmVscmMpKSB7XG4gICAgZChgRm91bmQgYSAuYmFiZWxyYyBhdCAke2JhYmVscmN9LCB1c2luZyBpdGApO1xuICAgIHJldHVybiBjcmVhdGVDb21waWxlckhvc3RGcm9tQmFiZWxSY1N5bmMoYmFiZWxyYywgcm9vdENhY2hlRGlyKTtcbiAgfVxuICAgIFxuICBkKGBVc2luZyBwYWNrYWdlLmpzb24gb3IgZGVmYXVsdCBwYXJhbWV0ZXJzIGF0ICR7cm9vdERpcn1gKTtcbiAgcmV0dXJuIGNyZWF0ZUNvbXBpbGVySG9zdEZyb21CYWJlbFJjU3luYyhwYXRoLmpvaW4ocm9vdERpciwgJ3BhY2thZ2UuanNvbicpLCByb290Q2FjaGVEaXIpO1xufVxuXG4vKipcbiAqIFJldHVybnMgd2hhdCBlbGVjdHJvbi1jb21waWxlIHdvdWxkIHVzZSBhcyBhIGRlZmF1bHQgcm9vdENhY2hlRGlyLiBVc3VhbGx5IG9ubHlcbiAqIHVzZWQgZm9yIGRlYnVnZ2luZyBwdXJwb3Nlc1xuICogIFxuICogQHJldHVybiB7c3RyaW5nfSAgQSBwYXRoIHRoYXQgbWF5IG9yIG1heSBub3QgZXhpc3Qgd2hlcmUgZWxlY3Ryb24tY29tcGlsZSB3b3VsZFxuICogICAgICAgICAgICAgICAgICAgc2V0IHVwIGEgZGV2ZWxvcG1lbnQgbW9kZSBjYWNoZS5cbiAqLyBcbmV4cG9ydCBmdW5jdGlvbiBjYWxjdWxhdGVEZWZhdWx0Q29tcGlsZUNhY2hlRGlyZWN0b3J5KCkge1xuICBsZXQgdG1wRGlyID0gcHJvY2Vzcy5lbnYuVEVNUCB8fCBwcm9jZXNzLmVudi5UTVBESVIgfHwgJy90bXAnO1xuICBsZXQgaGFzaCA9IHJlcXVpcmUoJ2NyeXB0bycpLmNyZWF0ZUhhc2goJ21kNScpLnVwZGF0ZShwcm9jZXNzLmV4ZWNQYXRoKS5kaWdlc3QoJ2hleCcpO1xuXG4gIGxldCBjYWNoZURpciA9IHBhdGguam9pbih0bXBEaXIsIGBjb21waWxlQ2FjaGVfJHtoYXNofWApO1xuICBta2RpcnAuc3luYyhjYWNoZURpcik7XG4gIFxuICBkKGBVc2luZyBkZWZhdWx0IGNhY2hlIGRpcmVjdG9yeTogJHtjYWNoZURpcn1gKTtcbiAgcmV0dXJuIGNhY2hlRGlyO1xufVxuXG5cbi8qKlxuICogUmV0dXJucyB0aGUgZGVmYXVsdCAuY29uZmlncmMgaWYgbm8gY29uZmlndXJhdGlvbiBpbmZvcm1hdGlvbiBjYW4gYmUgZm91bmQuXG4gKiAgXG4gKiBAcmV0dXJuIHtPYmplY3R9ICBBIGxpc3Qgb2YgZGVmYXVsdCBjb25maWcgc2V0dGluZ3MgZm9yIGVsZWN0cm9uLWNvbXBpbGVyLlxuICovIFxuZXhwb3J0IGZ1bmN0aW9uIGdldERlZmF1bHRDb25maWd1cmF0aW9uKCkge1xuICByZXR1cm4ge1xuICAgICdhcHBsaWNhdGlvbi9qYXZhc2NyaXB0Jzoge1xuICAgICAgXCJwcmVzZXRzXCI6IFtcInN0YWdlLTBcIiwgXCJlczIwMTVcIiwgXCJyZWFjdFwiXSxcbiAgICAgIFwic291cmNlTWFwc1wiOiBcImlubGluZVwiXG4gICAgfVxuICB9O1xufVxuXG4vKipcbiAqIEFsbG93cyB5b3UgdG8gY3JlYXRlIG5ldyBpbnN0YW5jZXMgb2YgYWxsIGNvbXBpbGVycyB0aGF0IGFyZSBzdXBwb3J0ZWQgYnkgXG4gKiBlbGVjdHJvbi1jb21waWxlIGFuZCB1c2UgdGhlbSBkaXJlY3RseS4gQ3VycmVudGx5IHN1cHBvcnRzIEJhYmVsLCBDb2ZmZWVTY3JpcHQsIFxuICogVHlwZVNjcmlwdCwgTEVTUywgYW5kIEphZGUuXG4gKiAgXG4gKiBAcmV0dXJuIHtPYmplY3R9ICBBbiBPYmplY3Qgd2hvc2UgS2V5cyBhcmUgTUlNRSB0eXBlcywgYW5kIHdob3NlIHZhbHVlcyBcbiAqIGFyZSBpbnN0YW5jZXMgb2YgQHtsaW5rIENvbXBpbGVyQmFzZX0uXG4gKi8gXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQ29tcGlsZXJzKCkge1xuICBpZiAoIWFsbENvbXBpbGVyQ2xhc3Nlcykge1xuICAgIC8vIEZpcnN0IHdlIHdhbnQgdG8gc2VlIGlmIGVsZWN0cm9uLWNvbXBpbGVycyBpdHNlbGYgaGFzIGJlZW4gaW5zdGFsbGVkIHdpdGhcbiAgICAvLyBkZXZEZXBlbmRlbmNpZXMuIElmIHRoYXQncyBub3QgdGhlIGNhc2UsIGNoZWNrIHRvIHNlZSBpZlxuICAgIC8vIGVsZWN0cm9uLWNvbXBpbGVycyBpcyBpbnN0YWxsZWQgYXMgYSBwZWVyIGRlcGVuZGVuY3kgKHByb2JhYmx5IGFzIGFcbiAgICAvLyBkZXZEZXBlbmRlbmN5IG9mIHRoZSByb290IHByb2plY3QpLlxuICAgIGNvbnN0IGxvY2F0aW9ucyA9IFsnZWxlY3Ryb24tY29tcGlsZXJzJywgJy4uLy4uL2VsZWN0cm9uLWNvbXBpbGVycyddO1xuXG4gICAgZm9yIChsZXQgbG9jYXRpb24gb2YgbG9jYXRpb25zKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhbGxDb21waWxlckNsYXNzZXMgPSByZXF1aXJlKGxvY2F0aW9uKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgLy8gWW9sb1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICghYWxsQ29tcGlsZXJDbGFzc2VzKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJFbGVjdHJvbiBjb21waWxlcnMgbm90IGZvdW5kIGJ1dCB3ZXJlIHJlcXVlc3RlZCB0byBiZSBsb2FkZWRcIik7XG4gICAgfVxuICB9XG5cbiAgLy8gTkI6IE5vdGUgdGhhdCB0aGlzIGNvZGUgaXMgY2FyZWZ1bGx5IHNldCB1cCBzbyB0aGF0IElubGluZUh0bWxDb21waWxlciBcbiAgLy8gKGkuZS4gY2xhc3NlcyB3aXRoIGBjcmVhdGVGcm9tQ29tcGlsZXJzYCkgaW5pdGlhbGx5IGdldCBhbiBlbXB0eSBvYmplY3QsXG4gIC8vIGJ1dCB3aWxsIGhhdmUgYSByZWZlcmVuY2UgdG8gdGhlIGZpbmFsIHJlc3VsdCBvZiB3aGF0IHdlIHJldHVybiwgd2hpY2hcbiAgLy8gcmVzb2x2ZXMgdGhlIGNpcmN1bGFyIGRlcGVuZGVuY3kgd2UnZCBvdGhlcndpc2UgaGF2ZSBoZXJlLlxuICBsZXQgcmV0ID0ge307XG4gIGxldCBpbnN0YW50aWF0ZWRDbGFzc2VzID0gXy5tYXAoYWxsQ29tcGlsZXJDbGFzc2VzLCAoS2xhc3MpID0+IHtcbiAgICBpZiAoJ2NyZWF0ZUZyb21Db21waWxlcnMnIGluIEtsYXNzKSB7XG4gICAgICByZXR1cm4gS2xhc3MuY3JlYXRlRnJvbUNvbXBpbGVycyhyZXQpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbmV3IEtsYXNzKCk7XG4gICAgfVxuICB9KTtcblxuICBfLnJlZHVjZShpbnN0YW50aWF0ZWRDbGFzc2VzLCAoYWNjLHgpID0+IHtcbiAgICBsZXQgS2xhc3MgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YoeCkuY29uc3RydWN0b3I7XG5cbiAgICBmb3IgKGxldCB0eXBlIG9mIEtsYXNzLmdldElucHV0TWltZVR5cGVzKCkpIHsgYWNjW3R5cGVdID0geDsgfVxuICAgIHJldHVybiBhY2M7XG4gIH0sIHJldCk7XG4gIFxuICByZXR1cm4gcmV0O1xufVxuIl19