electron-compile
Version:
Electron supporting package to compile JS and CSS in Electron applications
632 lines (508 loc) • 51.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 ? 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