UNPKG

grind-assets

Version:
216 lines (164 loc) 26.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PublishCommand = void 0; var _BaseCommand = require("./BaseCommand.js"); var _grindSupport = require("grind-support"); var _grindCli = require("grind-cli"); function _isnil(val) { return val === null || typeof val === 'undefined'; } const crypto = require('crypto'); const path = require('path'); const Ignore = require('ignore'); class PublishCommand extends _BaseCommand.BaseCommand { constructor(...args) { super(...args); this.name = 'assets:publish'; this.description = 'Compies and publishes all assets'; this.assets = {}; this.oldAssets = {}; this.factory = null; this.publishedBaseUrl = null; this.topLevel = false; this.options = [new _grindCli.InputOption('published-base-url', _grindCli.InputOption.VALUE_OPTIONAL, 'Specify the base URL for published assets.')]; } ready() { this.factory = this.app.assets; this.topLevel = this.app.config.get('assets.top_level') === true; return super.ready(); } async run() { this.oldAssets = await this.loadOldAssets(); if (_isnil(this.oldAssets)) { this.oldAssets = {}; } this.factory.published = {}; const publishedBaseUrl = this.option('published-base-url', this.app.config.get('assets.publish.base_url')); if (typeof publishedBaseUrl === 'string' && publishedBaseUrl.length > 0) { this.publishedBaseUrl = publishedBaseUrl; this.assets.__base_url = `${this.publishedBaseUrl}/`; } else { this.publishedBaseUrl = path.join('/', path.relative(this.app.paths.public('/'), this.publishPath)); } this.publishedBaseUrl = this.publishedBaseUrl.replace(/\/$/g, ''); if (!_isnil(this.oldAssets.__base_url)) { const length = this.oldAssets.__base_url.length; delete this.oldAssets.__base_url; for (const key of Object.keys(this.oldAssets)) { this.oldAssets[key] = this.oldAssets[key].substring(length); } } await this.compile(); await this.writeConfig(this.assets); await this.removeAssets(this.oldAssets); } async compile() { const assets = await this.findAssets(this.sourcePath); for (const asset of assets) { let content = null; try { this.comment('Compiling', path.relative(this.app.paths.base(), asset.path)); content = await asset.compile(); } catch (err) { let message = err.message || 'Unknown error'; if (!_isnil(err.file)) { message += `\n --> File: ${err.file}`; } if (!_isnil(err.line)) { message += `\n --> Line: ${err.line}`; } if (!_isnil(err.column)) { message += `\n --> Column: ${err.column}`; } throw new Error(message); } let storePath = path.relative(this.sourcePath, asset.path); if (!this.topLevel) { storePath = path.join(asset.type, storePath.substr(storePath.indexOf('/'))); } let name = path.basename(storePath, path.extname(storePath)); if (asset.compiler.wantsHashSuffixOnPublish) { const sha1 = crypto.createHash('md5'); sha1.update(content); name += `-${sha1.digest('hex').substring(0, 8)}`; } name += `.${asset.extension}`; await this.storeAsset(asset, path.join(this.publishPath, path.dirname(storePath), name), content); } } async findAssets(pathname) { const files = await _grindSupport.FS.recursiveReaddir(pathname); const ignoreFiles = files.filter(file => path.basename(file) === '.assetsignore'); const ignoreRules = Ignore().add(['**/_*', '**/.*', path.join(path.relative(this.sourcePath, this.publishPath), '/')]); for (const ignoreFile of ignoreFiles) { const content = await _grindSupport.FS.readFile(ignoreFile).then(content => content.toString()); const dirname = path.relative(pathname, path.dirname(ignoreFile)); const rules = content.split(/[\n\r]+/).filter(line => { line = line.trim(); return line.length > 0 && line.substring(0, 1) !== '#'; }).map(line => { if (line.substring(0, 1) === '!') { return `!${path.join(dirname, line.substring(1))}`; } return path.join(dirname, line); }); ignoreRules.add(rules); } return files.filter(file => { if (ignoreRules.filter([path.relative(pathname, file)]).length !== 1) { return false; } if (!this.factory.isPathSupported(file)) { this.comment('Skipping unsupported asset', path.relative(this.app.paths.base(), file)); return false; } return true; }).map(file => this.factory.make(file)).sort((a, b) => b.compareKind(a)); } loadOldAssets() { return this.app.config.get('assets-published'); } async storeAsset(asset, file, contents) { await _grindSupport.FS.mkdirp(path.dirname(file)); if (!(contents instanceof Buffer)) { contents = Buffer.from(contents); } contents = await this.postProcess(asset, file, contents); await _grindSupport.FS.writeFile(file, contents); const lastModified = await asset.lastModified(); if (!_isnil(lastModified)) { await _grindSupport.FS.touch(file, lastModified); } const src = path.relative(this.sourcePath, asset.path); const dest = `${this.publishedBaseUrl}/${path.relative(this.publishPath, file)}`; this.assets[src] = dest; this.factory.published[src] = dest; if (this.oldAssets[src] === dest) { delete this.oldAssets[src]; } } async postProcess(asset, file, contents) { const postProcessors = this.factory.getPostProcessorsFromPath(file); if (postProcessors.length === 0) { return contents; } for (const postProcessor of postProcessors) { this.comment(`Applying ${postProcessor.constructor.name}`, path.relative(this.app.paths.base(), asset.path)); contents = await postProcessor.process(asset.path, file, contents); if (!(contents instanceof Buffer)) { contents = Buffer.from(contents); } } return contents; } async removeAssets(assets) { for (const key of Object.keys(assets)) { await this.removeAsset(assets[key]); } } async writeConfig(config) { await _grindSupport.FS.writeFile(this.app.paths.config('assets-published.json'), JSON.stringify(config, null, ' ')); } } exports.PublishCommand = PublishCommand; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9Db21tYW5kcy9QdWJsaXNoQ29tbWFuZC5qcyJdLCJuYW1lcyI6WyJjcnlwdG8iLCJyZXF1aXJlIiwicGF0aCIsIklnbm9yZSIsIlB1Ymxpc2hDb21tYW5kIiwiQmFzZUNvbW1hbmQiLCJuYW1lIiwiZGVzY3JpcHRpb24iLCJhc3NldHMiLCJvbGRBc3NldHMiLCJmYWN0b3J5IiwicHVibGlzaGVkQmFzZVVybCIsInRvcExldmVsIiwib3B0aW9ucyIsIklucHV0T3B0aW9uIiwiVkFMVUVfT1BUSU9OQUwiLCJyZWFkeSIsImFwcCIsImNvbmZpZyIsImdldCIsInJ1biIsImxvYWRPbGRBc3NldHMiLCJwdWJsaXNoZWQiLCJvcHRpb24iLCJsZW5ndGgiLCJfX2Jhc2VfdXJsIiwiam9pbiIsInJlbGF0aXZlIiwicGF0aHMiLCJwdWJsaWMiLCJwdWJsaXNoUGF0aCIsInJlcGxhY2UiLCJrZXkiLCJPYmplY3QiLCJrZXlzIiwic3Vic3RyaW5nIiwiY29tcGlsZSIsIndyaXRlQ29uZmlnIiwicmVtb3ZlQXNzZXRzIiwiZmluZEFzc2V0cyIsInNvdXJjZVBhdGgiLCJhc3NldCIsImNvbnRlbnQiLCJjb21tZW50IiwiYmFzZSIsImVyciIsIm1lc3NhZ2UiLCJmaWxlIiwibGluZSIsImNvbHVtbiIsIkVycm9yIiwic3RvcmVQYXRoIiwidHlwZSIsInN1YnN0ciIsImluZGV4T2YiLCJiYXNlbmFtZSIsImV4dG5hbWUiLCJjb21waWxlciIsIndhbnRzSGFzaFN1ZmZpeE9uUHVibGlzaCIsInNoYTEiLCJjcmVhdGVIYXNoIiwidXBkYXRlIiwiZGlnZXN0IiwiZXh0ZW5zaW9uIiwic3RvcmVBc3NldCIsImRpcm5hbWUiLCJwYXRobmFtZSIsImZpbGVzIiwiRlMiLCJyZWN1cnNpdmVSZWFkZGlyIiwiaWdub3JlRmlsZXMiLCJmaWx0ZXIiLCJpZ25vcmVSdWxlcyIsImFkZCIsImlnbm9yZUZpbGUiLCJyZWFkRmlsZSIsInRoZW4iLCJ0b1N0cmluZyIsInJ1bGVzIiwic3BsaXQiLCJ0cmltIiwibWFwIiwiaXNQYXRoU3VwcG9ydGVkIiwibWFrZSIsInNvcnQiLCJhIiwiYiIsImNvbXBhcmVLaW5kIiwiY29udGVudHMiLCJta2RpcnAiLCJCdWZmZXIiLCJmcm9tIiwicG9zdFByb2Nlc3MiLCJ3cml0ZUZpbGUiLCJsYXN0TW9kaWZpZWQiLCJ0b3VjaCIsInNyYyIsImRlc3QiLCJwb3N0UHJvY2Vzc29ycyIsImdldFBvc3RQcm9jZXNzb3JzRnJvbVBhdGgiLCJwb3N0UHJvY2Vzc29yIiwiY29uc3RydWN0b3IiLCJwcm9jZXNzIiwicmVtb3ZlQXNzZXQiLCJKU09OIiwic3RyaW5naWZ5Il0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFFQTs7QUFDQTs7OztBQUVBLE1BQU1BLE1BQU0sR0FBR0MsT0FBTyxDQUFDLFFBQUQsQ0FBdEI7O0FBQ0EsTUFBTUMsSUFBSSxHQUFHRCxPQUFPLENBQUMsTUFBRCxDQUFwQjs7QUFDQSxNQUFNRSxNQUFNLEdBQUdGLE9BQU8sQ0FBQyxRQUFELENBQXRCOztBQUVPLE1BQU1HLGNBQU4sU0FBNkJDLHdCQUE3QixDQUF5QztBQUFBO0FBQUE7QUFBQSxTQUMvQ0MsSUFEK0MsR0FDeEMsZ0JBRHdDO0FBQUEsU0FFL0NDLFdBRitDLEdBRWpDLGtDQUZpQztBQUFBLFNBSS9DQyxNQUorQyxHQUl0QyxFQUpzQztBQUFBLFNBSy9DQyxTQUwrQyxHQUtuQyxFQUxtQztBQUFBLFNBTS9DQyxPQU4rQyxHQU1yQyxJQU5xQztBQUFBLFNBTy9DQyxnQkFQK0MsR0FPNUIsSUFQNEI7QUFBQSxTQVEvQ0MsUUFSK0MsR0FRcEMsS0FSb0M7QUFBQSxTQVUvQ0MsT0FWK0MsR0FVckMsQ0FDVCxJQUFJQyxxQkFBSixDQUNDLG9CQURELEVBRUNBLHNCQUFZQyxjQUZiLEVBR0MsNENBSEQsQ0FEUyxDQVZxQztBQUFBOztBQWtCL0NDLEVBQUFBLEtBQUssR0FBRztBQUNQLFNBQUtOLE9BQUwsR0FBZSxLQUFLTyxHQUFMLENBQVNULE1BQXhCO0FBQ0EsU0FBS0ksUUFBTCxHQUFnQixLQUFLSyxHQUFMLENBQVNDLE1BQVQsQ0FBZ0JDLEdBQWhCLENBQW9CLGtCQUFwQixNQUE0QyxJQUE1RDtBQUVBLFdBQU8sTUFBTUgsS0FBTixFQUFQO0FBQ0E7O0FBRVEsUUFBSEksR0FBRyxHQUFHO0FBQ1gsU0FBS1gsU0FBTCxHQUFpQixNQUFNLEtBQUtZLGFBQUwsRUFBdkI7O0FBRUEsZUFBSSxLQUFLWixTQUFULEdBQTBCO0FBQ3pCLFdBQUtBLFNBQUwsR0FBaUIsRUFBakI7QUFDQTs7QUFFRCxTQUFLQyxPQUFMLENBQWFZLFNBQWIsR0FBeUIsRUFBekI7QUFFQSxVQUFNWCxnQkFBZ0IsR0FBRyxLQUFLWSxNQUFMLENBQ3hCLG9CQUR3QixFQUV4QixLQUFLTixHQUFMLENBQVNDLE1BQVQsQ0FBZ0JDLEdBQWhCLENBQW9CLHlCQUFwQixDQUZ3QixDQUF6Qjs7QUFLQSxRQUFJLE9BQU9SLGdCQUFQLEtBQTRCLFFBQTVCLElBQXdDQSxnQkFBZ0IsQ0FBQ2EsTUFBakIsR0FBMEIsQ0FBdEUsRUFBeUU7QUFDeEUsV0FBS2IsZ0JBQUwsR0FBd0JBLGdCQUF4QjtBQUNBLFdBQUtILE1BQUwsQ0FBWWlCLFVBQVosR0FBMEIsR0FBRSxLQUFLZCxnQkFBaUIsR0FBbEQ7QUFDQSxLQUhELE1BR087QUFDTixXQUFLQSxnQkFBTCxHQUF3QlQsSUFBSSxDQUFDd0IsSUFBTCxDQUN2QixHQUR1QixFQUV2QnhCLElBQUksQ0FBQ3lCLFFBQUwsQ0FBYyxLQUFLVixHQUFMLENBQVNXLEtBQVQsQ0FBZUMsTUFBZixDQUFzQixHQUF0QixDQUFkLEVBQTBDLEtBQUtDLFdBQS9DLENBRnVCLENBQXhCO0FBSUE7O0FBRUQsU0FBS25CLGdCQUFMLEdBQXdCLEtBQUtBLGdCQUFMLENBQXNCb0IsT0FBdEIsQ0FBOEIsTUFBOUIsRUFBc0MsRUFBdEMsQ0FBeEI7O0FBRUEsUUFBSSxRQUFDLEtBQUt0QixTQUFMLENBQWVnQixVQUFoQixDQUFKLEVBQXNDO0FBQ3JDLFlBQU1ELE1BQU0sR0FBRyxLQUFLZixTQUFMLENBQWVnQixVQUFmLENBQTBCRCxNQUF6QztBQUNBLGFBQU8sS0FBS2YsU0FBTCxDQUFlZ0IsVUFBdEI7O0FBRUEsV0FBSyxNQUFNTyxHQUFYLElBQWtCQyxNQUFNLENBQUNDLElBQVAsQ0FBWSxLQUFLekIsU0FBakIsQ0FBbEIsRUFBK0M7QUFDOUMsYUFBS0EsU0FBTCxDQUFldUIsR0FBZixJQUFzQixLQUFLdkIsU0FBTCxDQUFldUIsR0FBZixFQUFvQkcsU0FBcEIsQ0FBOEJYLE1BQTlCLENBQXRCO0FBQ0E7QUFDRDs7QUFFRCxVQUFNLEtBQUtZLE9BQUwsRUFBTjtBQUVBLFVBQU0sS0FBS0MsV0FBTCxDQUFpQixLQUFLN0IsTUFBdEIsQ0FBTjtBQUNBLFVBQU0sS0FBSzhCLFlBQUwsQ0FBa0IsS0FBSzdCLFNBQXZCLENBQU47QUFDQTs7QUFFWSxRQUFQMkIsT0FBTyxHQUFHO0FBQ2YsVUFBTTVCLE1BQU0sR0FBRyxNQUFNLEtBQUsrQixVQUFMLENBQWdCLEtBQUtDLFVBQXJCLENBQXJCOztBQUVBLFNBQUssTUFBTUMsS0FBWCxJQUFvQmpDLE1BQXBCLEVBQTRCO0FBQzNCLFVBQUlrQyxPQUFPLEdBQUcsSUFBZDs7QUFFQSxVQUFJO0FBQ0gsYUFBS0MsT0FBTCxDQUFhLFdBQWIsRUFBMEJ6QyxJQUFJLENBQUN5QixRQUFMLENBQWMsS0FBS1YsR0FBTCxDQUFTVyxLQUFULENBQWVnQixJQUFmLEVBQWQsRUFBcUNILEtBQUssQ0FBQ3ZDLElBQTNDLENBQTFCO0FBQ0F3QyxRQUFBQSxPQUFPLEdBQUcsTUFBTUQsS0FBSyxDQUFDTCxPQUFOLEVBQWhCO0FBQ0EsT0FIRCxDQUdFLE9BQU9TLEdBQVAsRUFBWTtBQUNiLFlBQUlDLE9BQU8sR0FBR0QsR0FBRyxDQUFDQyxPQUFKLElBQWUsZUFBN0I7O0FBRUEsWUFBSSxRQUFDRCxHQUFHLENBQUNFLElBQUwsQ0FBSixFQUFxQjtBQUNwQkQsVUFBQUEsT0FBTyxJQUFLLGdCQUFlRCxHQUFHLENBQUNFLElBQUssRUFBcEM7QUFDQTs7QUFFRCxZQUFJLFFBQUNGLEdBQUcsQ0FBQ0csSUFBTCxDQUFKLEVBQXFCO0FBQ3BCRixVQUFBQSxPQUFPLElBQUssZ0JBQWVELEdBQUcsQ0FBQ0csSUFBSyxFQUFwQztBQUNBOztBQUVELFlBQUksUUFBQ0gsR0FBRyxDQUFDSSxNQUFMLENBQUosRUFBdUI7QUFDdEJILFVBQUFBLE9BQU8sSUFBSyxrQkFBaUJELEdBQUcsQ0FBQ0ksTUFBTyxFQUF4QztBQUNBOztBQUVELGNBQU0sSUFBSUMsS0FBSixDQUFVSixPQUFWLENBQU47QUFDQTs7QUFFRCxVQUFJSyxTQUFTLEdBQUdqRCxJQUFJLENBQUN5QixRQUFMLENBQWMsS0FBS2EsVUFBbkIsRUFBK0JDLEtBQUssQ0FBQ3ZDLElBQXJDLENBQWhCOztBQUVBLFVBQUksQ0FBQyxLQUFLVSxRQUFWLEVBQW9CO0FBQ25CdUMsUUFBQUEsU0FBUyxHQUFHakQsSUFBSSxDQUFDd0IsSUFBTCxDQUFVZSxLQUFLLENBQUNXLElBQWhCLEVBQXNCRCxTQUFTLENBQUNFLE1BQVYsQ0FBaUJGLFNBQVMsQ0FBQ0csT0FBVixDQUFrQixHQUFsQixDQUFqQixDQUF0QixDQUFaO0FBQ0E7O0FBRUQsVUFBSWhELElBQUksR0FBR0osSUFBSSxDQUFDcUQsUUFBTCxDQUFjSixTQUFkLEVBQXlCakQsSUFBSSxDQUFDc0QsT0FBTCxDQUFhTCxTQUFiLENBQXpCLENBQVg7O0FBRUEsVUFBSVYsS0FBSyxDQUFDZ0IsUUFBTixDQUFlQyx3QkFBbkIsRUFBNkM7QUFDNUMsY0FBTUMsSUFBSSxHQUFHM0QsTUFBTSxDQUFDNEQsVUFBUCxDQUFrQixLQUFsQixDQUFiO0FBQ0FELFFBQUFBLElBQUksQ0FBQ0UsTUFBTCxDQUFZbkIsT0FBWjtBQUNBcEMsUUFBQUEsSUFBSSxJQUFLLElBQUdxRCxJQUFJLENBQUNHLE1BQUwsQ0FBWSxLQUFaLEVBQW1CM0IsU0FBbkIsQ0FBNkIsQ0FBN0IsRUFBZ0MsQ0FBaEMsQ0FBbUMsRUFBL0M7QUFDQTs7QUFFRDdCLE1BQUFBLElBQUksSUFBSyxJQUFHbUMsS0FBSyxDQUFDc0IsU0FBVSxFQUE1QjtBQUNBLFlBQU0sS0FBS0MsVUFBTCxDQUNMdkIsS0FESyxFQUVMdkMsSUFBSSxDQUFDd0IsSUFBTCxDQUFVLEtBQUtJLFdBQWYsRUFBNEI1QixJQUFJLENBQUMrRCxPQUFMLENBQWFkLFNBQWIsQ0FBNUIsRUFBcUQ3QyxJQUFyRCxDQUZLLEVBR0xvQyxPQUhLLENBQU47QUFLQTtBQUNEOztBQUVlLFFBQVZILFVBQVUsQ0FBQzJCLFFBQUQsRUFBVztBQUMxQixVQUFNQyxLQUFLLEdBQUcsTUFBTUMsaUJBQUdDLGdCQUFILENBQW9CSCxRQUFwQixDQUFwQjtBQUNBLFVBQU1JLFdBQVcsR0FBR0gsS0FBSyxDQUFDSSxNQUFOLENBQWF4QixJQUFJLElBQUk3QyxJQUFJLENBQUNxRCxRQUFMLENBQWNSLElBQWQsTUFBd0IsZUFBN0MsQ0FBcEI7QUFDQSxVQUFNeUIsV0FBVyxHQUFHckUsTUFBTSxHQUFHc0UsR0FBVCxDQUFhLENBQ2hDLE9BRGdDLEVBRWhDLE9BRmdDLEVBR2hDdkUsSUFBSSxDQUFDd0IsSUFBTCxDQUFVeEIsSUFBSSxDQUFDeUIsUUFBTCxDQUFjLEtBQUthLFVBQW5CLEVBQStCLEtBQUtWLFdBQXBDLENBQVYsRUFBNEQsR0FBNUQsQ0FIZ0MsQ0FBYixDQUFwQjs7QUFNQSxTQUFLLE1BQU00QyxVQUFYLElBQXlCSixXQUF6QixFQUFzQztBQUNyQyxZQUFNNUIsT0FBTyxHQUFHLE1BQU0wQixpQkFBR08sUUFBSCxDQUFZRCxVQUFaLEVBQXdCRSxJQUF4QixDQUE2QmxDLE9BQU8sSUFBSUEsT0FBTyxDQUFDbUMsUUFBUixFQUF4QyxDQUF0QjtBQUNBLFlBQU1aLE9BQU8sR0FBRy9ELElBQUksQ0FBQ3lCLFFBQUwsQ0FBY3VDLFFBQWQsRUFBd0JoRSxJQUFJLENBQUMrRCxPQUFMLENBQWFTLFVBQWIsQ0FBeEIsQ0FBaEI7QUFFQSxZQUFNSSxLQUFLLEdBQUdwQyxPQUFPLENBQ25CcUMsS0FEWSxDQUNOLFNBRE0sRUFFWlIsTUFGWSxDQUVMdkIsSUFBSSxJQUFJO0FBQ2ZBLFFBQUFBLElBQUksR0FBR0EsSUFBSSxDQUFDZ0MsSUFBTCxFQUFQO0FBQ0EsZUFBT2hDLElBQUksQ0FBQ3hCLE1BQUwsR0FBYyxDQUFkLElBQW1Cd0IsSUFBSSxDQUFDYixTQUFMLENBQWUsQ0FBZixFQUFrQixDQUFsQixNQUF5QixHQUFuRDtBQUNBLE9BTFksRUFNWjhDLEdBTlksQ0FNUmpDLElBQUksSUFBSTtBQUNaLFlBQUlBLElBQUksQ0FBQ2IsU0FBTCxDQUFlLENBQWYsRUFBa0IsQ0FBbEIsTUFBeUIsR0FBN0IsRUFBa0M7QUFDakMsaUJBQVEsSUFBR2pDLElBQUksQ0FBQ3dCLElBQUwsQ0FBVXVDLE9BQVYsRUFBbUJqQixJQUFJLENBQUNiLFNBQUwsQ0FBZSxDQUFmLENBQW5CLENBQXNDLEVBQWpEO0FBQ0E7O0FBRUQsZUFBT2pDLElBQUksQ0FBQ3dCLElBQUwsQ0FBVXVDLE9BQVYsRUFBbUJqQixJQUFuQixDQUFQO0FBQ0EsT0FaWSxDQUFkO0FBY0F3QixNQUFBQSxXQUFXLENBQUNDLEdBQVosQ0FBZ0JLLEtBQWhCO0FBQ0E7O0FBRUQsV0FBT1gsS0FBSyxDQUNWSSxNQURLLENBQ0V4QixJQUFJLElBQUk7QUFDZixVQUFJeUIsV0FBVyxDQUFDRCxNQUFaLENBQW1CLENBQUNyRSxJQUFJLENBQUN5QixRQUFMLENBQWN1QyxRQUFkLEVBQXdCbkIsSUFBeEIsQ0FBRCxDQUFuQixFQUFvRHZCLE1BQXBELEtBQStELENBQW5FLEVBQXNFO0FBQ3JFLGVBQU8sS0FBUDtBQUNBOztBQUVELFVBQUksQ0FBQyxLQUFLZCxPQUFMLENBQWF3RSxlQUFiLENBQTZCbkMsSUFBN0IsQ0FBTCxFQUF5QztBQUN4QyxhQUFLSixPQUFMLENBQ0MsNEJBREQsRUFFQ3pDLElBQUksQ0FBQ3lCLFFBQUwsQ0FBYyxLQUFLVixHQUFMLENBQVNXLEtBQVQsQ0FBZWdCLElBQWYsRUFBZCxFQUFxQ0csSUFBckMsQ0FGRDtBQUlBLGVBQU8sS0FBUDtBQUNBOztBQUVELGFBQU8sSUFBUDtBQUNBLEtBZkssRUFnQkxrQyxHQWhCSyxDQWdCRGxDLElBQUksSUFBSSxLQUFLckMsT0FBTCxDQUFheUUsSUFBYixDQUFrQnBDLElBQWxCLENBaEJQLEVBaUJMcUMsSUFqQkssQ0FpQkEsQ0FBQ0MsQ0FBRCxFQUFJQyxDQUFKLEtBQVVBLENBQUMsQ0FBQ0MsV0FBRixDQUFjRixDQUFkLENBakJWLENBQVA7QUFrQkE7O0FBRURoRSxFQUFBQSxhQUFhLEdBQUc7QUFDZixXQUFPLEtBQUtKLEdBQUwsQ0FBU0MsTUFBVCxDQUFnQkMsR0FBaEIsQ0FBb0Isa0JBQXBCLENBQVA7QUFDQTs7QUFFZSxRQUFWNkMsVUFBVSxDQUFDdkIsS0FBRCxFQUFRTSxJQUFSLEVBQWN5QyxRQUFkLEVBQXdCO0FBQ3ZDLFVBQU1wQixpQkFBR3FCLE1BQUgsQ0FBVXZGLElBQUksQ0FBQytELE9BQUwsQ0FBYWxCLElBQWIsQ0FBVixDQUFOOztBQUVBLFFBQUksRUFBRXlDLFFBQVEsWUFBWUUsTUFBdEIsQ0FBSixFQUFtQztBQUNsQ0YsTUFBQUEsUUFBUSxHQUFHRSxNQUFNLENBQUNDLElBQVAsQ0FBWUgsUUFBWixDQUFYO0FBQ0E7O0FBRURBLElBQUFBLFFBQVEsR0FBRyxNQUFNLEtBQUtJLFdBQUwsQ0FBaUJuRCxLQUFqQixFQUF3Qk0sSUFBeEIsRUFBOEJ5QyxRQUE5QixDQUFqQjtBQUVBLFVBQU1wQixpQkFBR3lCLFNBQUgsQ0FBYTlDLElBQWIsRUFBbUJ5QyxRQUFuQixDQUFOO0FBQ0EsVUFBTU0sWUFBWSxHQUFHLE1BQU1yRCxLQUFLLENBQUNxRCxZQUFOLEVBQTNCOztBQUVBLFFBQUksUUFBQ0EsWUFBRCxDQUFKLEVBQXlCO0FBQ3hCLFlBQU0xQixpQkFBRzJCLEtBQUgsQ0FBU2hELElBQVQsRUFBZStDLFlBQWYsQ0FBTjtBQUNBOztBQUVELFVBQU1FLEdBQUcsR0FBRzlGLElBQUksQ0FBQ3lCLFFBQUwsQ0FBYyxLQUFLYSxVQUFuQixFQUErQkMsS0FBSyxDQUFDdkMsSUFBckMsQ0FBWjtBQUNBLFVBQU0rRixJQUFJLEdBQUksR0FBRSxLQUFLdEYsZ0JBQWlCLElBQUdULElBQUksQ0FBQ3lCLFFBQUwsQ0FBYyxLQUFLRyxXQUFuQixFQUFnQ2lCLElBQWhDLENBQXNDLEVBQS9FO0FBQ0EsU0FBS3ZDLE1BQUwsQ0FBWXdGLEdBQVosSUFBbUJDLElBQW5CO0FBQ0EsU0FBS3ZGLE9BQUwsQ0FBYVksU0FBYixDQUF1QjBFLEdBQXZCLElBQThCQyxJQUE5Qjs7QUFFQSxRQUFJLEtBQUt4RixTQUFMLENBQWV1RixHQUFmLE1BQXdCQyxJQUE1QixFQUFrQztBQUNqQyxhQUFPLEtBQUt4RixTQUFMLENBQWV1RixHQUFmLENBQVA7QUFDQTtBQUNEOztBQUVnQixRQUFYSixXQUFXLENBQUNuRCxLQUFELEVBQVFNLElBQVIsRUFBY3lDLFFBQWQsRUFBd0I7QUFDeEMsVUFBTVUsY0FBYyxHQUFHLEtBQUt4RixPQUFMLENBQWF5Rix5QkFBYixDQUF1Q3BELElBQXZDLENBQXZCOztBQUVBLFFBQUltRCxjQUFjLENBQUMxRSxNQUFmLEtBQTBCLENBQTlCLEVBQWlDO0FBQ2hDLGFBQU9nRSxRQUFQO0FBQ0E7O0FBRUQsU0FBSyxNQUFNWSxhQUFYLElBQTRCRixjQUE1QixFQUE0QztBQUMzQyxXQUFLdkQsT0FBTCxDQUNFLFlBQVd5RCxhQUFhLENBQUNDLFdBQWQsQ0FBMEIvRixJQUFLLEVBRDVDLEVBRUNKLElBQUksQ0FBQ3lCLFFBQUwsQ0FBYyxLQUFLVixHQUFMLENBQVNXLEtBQVQsQ0FBZWdCLElBQWYsRUFBZCxFQUFxQ0gsS0FBSyxDQUFDdkMsSUFBM0MsQ0FGRDtBQUlBc0YsTUFBQUEsUUFBUSxHQUFHLE1BQU1ZLGFBQWEsQ0FBQ0UsT0FBZCxDQUFzQjdELEtBQUssQ0FBQ3ZDLElBQTVCLEVBQWtDNkMsSUFBbEMsRUFBd0N5QyxRQUF4QyxDQUFqQjs7QUFFQSxVQUFJLEVBQUVBLFFBQVEsWUFBWUUsTUFBdEIsQ0FBSixFQUFtQztBQUNsQ0YsUUFBQUEsUUFBUSxHQUFHRSxNQUFNLENBQUNDLElBQVAsQ0FBWUgsUUFBWixDQUFYO0FBQ0E7QUFDRDs7QUFFRCxXQUFPQSxRQUFQO0FBQ0E7O0FBRWlCLFFBQVpsRCxZQUFZLENBQUM5QixNQUFELEVBQVM7QUFDMUIsU0FBSyxNQUFNd0IsR0FBWCxJQUFrQkMsTUFBTSxDQUFDQyxJQUFQLENBQVkxQixNQUFaLENBQWxCLEVBQXVDO0FBQ3RDLFlBQU0sS0FBSytGLFdBQUwsQ0FBaUIvRixNQUFNLENBQUN3QixHQUFELENBQXZCLENBQU47QUFDQTtBQUNEOztBQUVnQixRQUFYSyxXQUFXLENBQUNuQixNQUFELEVBQVM7QUFDekIsVUFBTWtELGlCQUFHeUIsU0FBSCxDQUNMLEtBQUs1RSxHQUFMLENBQVNXLEtBQVQsQ0FBZVYsTUFBZixDQUFzQix1QkFBdEIsQ0FESyxFQUVMc0YsSUFBSSxDQUFDQyxTQUFMLENBQWV2RixNQUFmLEVBQXVCLElBQXZCLEVBQTZCLEdBQTdCLENBRkssQ0FBTjtBQUlBOztBQXJPOEMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgJy4vQmFzZUNvbW1hbmQnXG5cbmltcG9ydCB7IEZTIH0gZnJvbSAnZ3JpbmQtc3VwcG9ydCdcbmltcG9ydCB7IElucHV0T3B0aW9uIH0gZnJvbSAnZ3JpbmQtY2xpJ1xuXG5jb25zdCBjcnlwdG8gPSByZXF1aXJlKCdjcnlwdG8nKVxuY29uc3QgcGF0aCA9IHJlcXVpcmUoJ3BhdGgnKVxuY29uc3QgSWdub3JlID0gcmVxdWlyZSgnaWdub3JlJylcblxuZXhwb3J0IGNsYXNzIFB1Ymxpc2hDb21tYW5kIGV4dGVuZHMgQmFzZUNvbW1hbmQge1xuXHRuYW1lID0gJ2Fzc2V0czpwdWJsaXNoJ1xuXHRkZXNjcmlwdGlvbiA9ICdDb21waWVzIGFuZCBwdWJsaXNoZXMgYWxsIGFzc2V0cydcblxuXHRhc3NldHMgPSB7fVxuXHRvbGRBc3NldHMgPSB7fVxuXHRmYWN0b3J5ID0gbnVsbFxuXHRwdWJsaXNoZWRCYXNlVXJsID0gbnVsbFxuXHR0b3BMZXZlbCA9IGZhbHNlXG5cblx0b3B0aW9ucyA9IFtcblx0XHRuZXcgSW5wdXRPcHRpb24oXG5cdFx0XHQncHVibGlzaGVkLWJhc2UtdXJsJyxcblx0XHRcdElucHV0T3B0aW9uLlZBTFVFX09QVElPTkFMLFxuXHRcdFx0J1NwZWNpZnkgdGhlIGJhc2UgVVJMIGZvciBwdWJsaXNoZWQgYXNzZXRzLicsXG5cdFx0KSxcblx0XVxuXG5cdHJlYWR5KCkge1xuXHRcdHRoaXMuZmFjdG9yeSA9IHRoaXMuYXBwLmFzc2V0c1xuXHRcdHRoaXMudG9wTGV2ZWwgPSB0aGlzLmFwcC5jb25maWcuZ2V0KCdhc3NldHMudG9wX2xldmVsJykgPT09IHRydWVcblxuXHRcdHJldHVybiBzdXBlci5yZWFkeSgpXG5cdH1cblxuXHRhc3luYyBydW4oKSB7XG5cdFx0dGhpcy5vbGRBc3NldHMgPSBhd2FpdCB0aGlzLmxvYWRPbGRBc3NldHMoKVxuXG5cdFx0aWYgKHRoaXMub2xkQXNzZXRzLmlzTmlsKSB7XG5cdFx0XHR0aGlzLm9sZEFzc2V0cyA9IHt9XG5cdFx0fVxuXG5cdFx0dGhpcy5mYWN0b3J5LnB1Ymxpc2hlZCA9IHt9XG5cblx0XHRjb25zdCBwdWJsaXNoZWRCYXNlVXJsID0gdGhpcy5vcHRpb24oXG5cdFx0XHQncHVibGlzaGVkLWJhc2UtdXJsJyxcblx0XHRcdHRoaXMuYXBwLmNvbmZpZy5nZXQoJ2Fzc2V0cy5wdWJsaXNoLmJhc2VfdXJsJyksXG5cdFx0KVxuXG5cdFx0aWYgKHR5cGVvZiBwdWJsaXNoZWRCYXNlVXJsID09PSAnc3RyaW5nJyAmJiBwdWJsaXNoZWRCYXNlVXJsLmxlbmd0aCA+IDApIHtcblx0XHRcdHRoaXMucHVibGlzaGVkQmFzZVVybCA9IHB1Ymxpc2hlZEJhc2VVcmxcblx0XHRcdHRoaXMuYXNzZXRzLl9fYmFzZV91cmwgPSBgJHt0aGlzLnB1Ymxpc2hlZEJhc2VVcmx9L2Bcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5wdWJsaXNoZWRCYXNlVXJsID0gcGF0aC5qb2luKFxuXHRcdFx0XHQnLycsXG5cdFx0XHRcdHBhdGgucmVsYXRpdmUodGhpcy5hcHAucGF0aHMucHVibGljKCcvJyksIHRoaXMucHVibGlzaFBhdGgpLFxuXHRcdFx0KVxuXHRcdH1cblxuXHRcdHRoaXMucHVibGlzaGVkQmFzZVVybCA9IHRoaXMucHVibGlzaGVkQmFzZVVybC5yZXBsYWNlKC9cXC8kL2csICcnKVxuXG5cdFx0aWYgKCF0aGlzLm9sZEFzc2V0cy5fX2Jhc2VfdXJsLmlzTmlsKSB7XG5cdFx0XHRjb25zdCBsZW5ndGggPSB0aGlzLm9sZEFzc2V0cy5fX2Jhc2VfdXJsLmxlbmd0aFxuXHRcdFx0ZGVsZXRlIHRoaXMub2xkQXNzZXRzLl9fYmFzZV91cmxcblxuXHRcdFx0Zm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXModGhpcy5vbGRBc3NldHMpKSB7XG5cdFx0XHRcdHRoaXMub2xkQXNzZXRzW2tleV0gPSB0aGlzLm9sZEFzc2V0c1trZXldLnN1YnN0cmluZyhsZW5ndGgpXG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0YXdhaXQgdGhpcy5jb21waWxlKClcblxuXHRcdGF3YWl0IHRoaXMud3JpdGVDb25maWcodGhpcy5hc3NldHMpXG5cdFx0YXdhaXQgdGhpcy5yZW1vdmVBc3NldHModGhpcy5vbGRBc3NldHMpXG5cdH1cblxuXHRhc3luYyBjb21waWxlKCkge1xuXHRcdGNvbnN0IGFzc2V0cyA9IGF3YWl0IHRoaXMuZmluZEFzc2V0cyh0aGlzLnNvdXJjZVBhdGgpXG5cblx0XHRmb3IgKGNvbnN0IGFzc2V0IG9mIGFzc2V0cykge1xuXHRcdFx0bGV0IGNvbnRlbnQgPSBudWxsXG5cblx0XHRcdHRyeSB7XG5cdFx0XHRcdHRoaXMuY29tbWVudCgnQ29tcGlsaW5nJywgcGF0aC5yZWxhdGl2ZSh0aGlzLmFwcC5wYXRocy5iYXNlKCksIGFzc2V0LnBhdGgpKVxuXHRcdFx0XHRjb250ZW50ID0gYXdhaXQgYXNzZXQuY29tcGlsZSgpXG5cdFx0XHR9IGNhdGNoIChlcnIpIHtcblx0XHRcdFx0bGV0IG1lc3NhZ2UgPSBlcnIubWVzc2FnZSB8fCAnVW5rbm93biBlcnJvcidcblxuXHRcdFx0XHRpZiAoIWVyci5maWxlLmlzTmlsKSB7XG5cdFx0XHRcdFx0bWVzc2FnZSArPSBgXFxuIC0tPiBGaWxlOiAke2Vyci5maWxlfWBcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICghZXJyLmxpbmUuaXNOaWwpIHtcblx0XHRcdFx0XHRtZXNzYWdlICs9IGBcXG4gLS0+IExpbmU6ICR7ZXJyLmxpbmV9YFxuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKCFlcnIuY29sdW1uLmlzTmlsKSB7XG5cdFx0XHRcdFx0bWVzc2FnZSArPSBgXFxuIC0tPiBDb2x1bW46ICR7ZXJyLmNvbHVtbn1gXG5cdFx0XHRcdH1cblxuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSlcblx0XHRcdH1cblxuXHRcdFx0bGV0IHN0b3JlUGF0aCA9IHBhdGgucmVsYXRpdmUodGhpcy5zb3VyY2VQYXRoLCBhc3NldC5wYXRoKVxuXG5cdFx0XHRpZiAoIXRoaXMudG9wTGV2ZWwpIHtcblx0XHRcdFx0c3RvcmVQYXRoID0gcGF0aC5qb2luKGFzc2V0LnR5cGUsIHN0b3JlUGF0aC5zdWJzdHIoc3RvcmVQYXRoLmluZGV4T2YoJy8nKSkpXG5cdFx0XHR9XG5cblx0XHRcdGxldCBuYW1lID0gcGF0aC5iYXNlbmFtZShzdG9yZVBhdGgsIHBhdGguZXh0bmFtZShzdG9yZVBhdGgpKVxuXG5cdFx0XHRpZiAoYXNzZXQuY29tcGlsZXIud2FudHNIYXNoU3VmZml4T25QdWJsaXNoKSB7XG5cdFx0XHRcdGNvbnN0IHNoYTEgPSBjcnlwdG8uY3JlYXRlSGFzaCgnbWQ1Jylcblx0XHRcdFx0c2hhMS51cGRhdGUoY29udGVudClcblx0XHRcdFx0bmFtZSArPSBgLSR7c2hhMS5kaWdlc3QoJ2hleCcpLnN1YnN0cmluZygwLCA4KX1gXG5cdFx0XHR9XG5cblx0XHRcdG5hbWUgKz0gYC4ke2Fzc2V0LmV4dGVuc2lvbn1gXG5cdFx0XHRhd2FpdCB0aGlzLnN0b3JlQXNzZXQoXG5cdFx0XHRcdGFzc2V0LFxuXHRcdFx0XHRwYXRoLmpvaW4odGhpcy5wdWJsaXNoUGF0aCwgcGF0aC5kaXJuYW1lKHN0b3JlUGF0aCksIG5hbWUpLFxuXHRcdFx0XHRjb250ZW50LFxuXHRcdFx0KVxuXHRcdH1cblx0fVxuXG5cdGFzeW5jIGZpbmRBc3NldHMocGF0aG5hbWUpIHtcblx0XHRjb25zdCBmaWxlcyA9IGF3YWl0IEZTLnJlY3Vyc2l2ZVJlYWRkaXIocGF0aG5hbWUpXG5cdFx0Y29uc3QgaWdub3JlRmlsZXMgPSBmaWxlcy5maWx0ZXIoZmlsZSA9PiBwYXRoLmJhc2VuYW1lKGZpbGUpID09PSAnLmFzc2V0c2lnbm9yZScpXG5cdFx0Y29uc3QgaWdub3JlUnVsZXMgPSBJZ25vcmUoKS5hZGQoW1xuXHRcdFx0JyoqL18qJyxcblx0XHRcdCcqKi8uKicsXG5cdFx0XHRwYXRoLmpvaW4ocGF0aC5yZWxhdGl2ZSh0aGlzLnNvdXJjZVBhdGgsIHRoaXMucHVibGlzaFBhdGgpLCAnLycpLFxuXHRcdF0pXG5cblx0XHRmb3IgKGNvbnN0IGlnbm9yZUZpbGUgb2YgaWdub3JlRmlsZXMpIHtcblx0XHRcdGNvbnN0IGNvbnRlbnQgPSBhd2FpdCBGUy5yZWFkRmlsZShpZ25vcmVGaWxlKS50aGVuKGNvbnRlbnQgPT4gY29udGVudC50b1N0cmluZygpKVxuXHRcdFx0Y29uc3QgZGlybmFtZSA9IHBhdGgucmVsYXRpdmUocGF0aG5hbWUsIHBhdGguZGlybmFtZShpZ25vcmVGaWxlKSlcblxuXHRcdFx0Y29uc3QgcnVsZXMgPSBjb250ZW50XG5cdFx0XHRcdC5zcGxpdCgvW1xcblxccl0rLylcblx0XHRcdFx0LmZpbHRlcihsaW5lID0+IHtcblx0XHRcdFx0XHRsaW5lID0gbGluZS50cmltKClcblx0XHRcdFx0XHRyZXR1cm4gbGluZS5sZW5ndGggPiAwICYmIGxpbmUuc3Vic3RyaW5nKDAsIDEpICE9PSAnIydcblx0XHRcdFx0fSlcblx0XHRcdFx0Lm1hcChsaW5lID0+IHtcblx0XHRcdFx0XHRpZiAobGluZS5zdWJzdHJpbmcoMCwgMSkgPT09ICchJykge1xuXHRcdFx0XHRcdFx0cmV0dXJuIGAhJHtwYXRoLmpvaW4oZGlybmFtZSwgbGluZS5zdWJzdHJpbmcoMSkpfWBcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRyZXR1cm4gcGF0aC5qb2luKGRpcm5hbWUsIGxpbmUpXG5cdFx0XHRcdH0pXG5cblx0XHRcdGlnbm9yZVJ1bGVzLmFkZChydWxlcylcblx0XHR9XG5cblx0XHRyZXR1cm4gZmlsZXNcblx0XHRcdC5maWx0ZXIoZmlsZSA9PiB7XG5cdFx0XHRcdGlmIChpZ25vcmVSdWxlcy5maWx0ZXIoW3BhdGgucmVsYXRpdmUocGF0aG5hbWUsIGZpbGUpXSkubGVuZ3RoICE9PSAxKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlXG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIXRoaXMuZmFjdG9yeS5pc1BhdGhTdXBwb3J0ZWQoZmlsZSkpIHtcblx0XHRcdFx0XHR0aGlzLmNvbW1lbnQoXG5cdFx0XHRcdFx0XHQnU2tpcHBpbmcgdW5zdXBwb3J0ZWQgYXNzZXQnLFxuXHRcdFx0XHRcdFx0cGF0aC5yZWxhdGl2ZSh0aGlzLmFwcC5wYXRocy5iYXNlKCksIGZpbGUpLFxuXHRcdFx0XHRcdClcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2Vcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHJldHVybiB0cnVlXG5cdFx0XHR9KVxuXHRcdFx0Lm1hcChmaWxlID0+IHRoaXMuZmFjdG9yeS5tYWtlKGZpbGUpKVxuXHRcdFx0LnNvcnQoKGEsIGIpID0+IGIuY29tcGFyZUtpbmQoYSkpXG5cdH1cblxuXHRsb2FkT2xkQXNzZXRzKCkge1xuXHRcdHJldHVybiB0aGlzLmFwcC5jb25maWcuZ2V0KCdhc3NldHMtcHVibGlzaGVkJylcblx0fVxuXG5cdGFzeW5jIHN0b3JlQXNzZXQoYXNzZXQsIGZpbGUsIGNvbnRlbnRzKSB7XG5cdFx0YXdhaXQgRlMubWtkaXJwKHBhdGguZGlybmFtZShmaWxlKSlcblxuXHRcdGlmICghKGNvbnRlbnRzIGluc3RhbmNlb2YgQnVmZmVyKSkge1xuXHRcdFx0Y29udGVudHMgPSBCdWZmZXIuZnJvbShjb250ZW50cylcblx0XHR9XG5cblx0XHRjb250ZW50cyA9IGF3YWl0IHRoaXMucG9zdFByb2Nlc3MoYXNzZXQsIGZpbGUsIGNvbnRlbnRzKVxuXG5cdFx0YXdhaXQgRlMud3JpdGVGaWxlKGZpbGUsIGNvbnRlbnRzKVxuXHRcdGNvbnN0IGxhc3RNb2RpZmllZCA9IGF3YWl0IGFzc2V0Lmxhc3RNb2RpZmllZCgpXG5cblx0XHRpZiAoIWxhc3RNb2RpZmllZC5pc05pbCkge1xuXHRcdFx0YXdhaXQgRlMudG91Y2goZmlsZSwgbGFzdE1vZGlmaWVkKVxuXHRcdH1cblxuXHRcdGNvbnN0IHNyYyA9IHBhdGgucmVsYXRpdmUodGhpcy5zb3VyY2VQYXRoLCBhc3NldC5wYXRoKVxuXHRcdGNvbnN0IGRlc3QgPSBgJHt0aGlzLnB1Ymxpc2hlZEJhc2VVcmx9LyR7cGF0aC5yZWxhdGl2ZSh0aGlzLnB1Ymxpc2hQYXRoLCBmaWxlKX1gXG5cdFx0dGhpcy5hc3NldHNbc3JjXSA9IGRlc3Rcblx0XHR0aGlzLmZhY3RvcnkucHVibGlzaGVkW3NyY10gPSBkZXN0XG5cblx0XHRpZiAodGhpcy5vbGRBc3NldHNbc3JjXSA9PT0gZGVzdCkge1xuXHRcdFx0ZGVsZXRlIHRoaXMub2xkQXNzZXRzW3NyY11cblx0XHR9XG5cdH1cblxuXHRhc3luYyBwb3N0UHJvY2Vzcyhhc3NldCwgZmlsZSwgY29udGVudHMpIHtcblx0XHRjb25zdCBwb3N0UHJvY2Vzc29ycyA9IHRoaXMuZmFjdG9yeS5nZXRQb3N0UHJvY2Vzc29yc0Zyb21QYXRoKGZpbGUpXG5cblx0XHRpZiAocG9zdFByb2Nlc3NvcnMubGVuZ3RoID09PSAwKSB7XG5cdFx0XHRyZXR1cm4gY29udGVudHNcblx0XHR9XG5cblx0XHRmb3IgKGNvbnN0IHBvc3RQcm9jZXNzb3Igb2YgcG9zdFByb2Nlc3NvcnMpIHtcblx0XHRcdHRoaXMuY29tbWVudChcblx0XHRcdFx0YEFwcGx5aW5nICR7cG9zdFByb2Nlc3Nvci5jb25zdHJ1Y3Rvci5uYW1lfWAsXG5cdFx0XHRcdHBhdGgucmVsYXRpdmUodGhpcy5hcHAucGF0aHMuYmFzZSgpLCBhc3NldC5wYXRoKSxcblx0XHRcdClcblx0XHRcdGNvbnRlbnRzID0gYXdhaXQgcG9zdFByb2Nlc3Nvci5wcm9jZXNzKGFzc2V0LnBhdGgsIGZpbGUsIGNvbnRlbnRzKVxuXG5cdFx0XHRpZiAoIShjb250ZW50cyBpbnN0YW5jZW9mIEJ1ZmZlcikpIHtcblx0XHRcdFx0Y29udGVudHMgPSBCdWZmZXIuZnJvbShjb250ZW50cylcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gY29udGVudHNcblx0fVxuXG5cdGFzeW5jIHJlbW92ZUFzc2V0cyhhc3NldHMpIHtcblx0XHRmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhhc3NldHMpKSB7XG5cdFx0XHRhd2FpdCB0aGlzLnJlbW92ZUFzc2V0KGFzc2V0c1trZXldKVxuXHRcdH1cblx0fVxuXG5cdGFzeW5jIHdyaXRlQ29uZmlnKGNvbmZpZykge1xuXHRcdGF3YWl0IEZTLndyaXRlRmlsZShcblx0XHRcdHRoaXMuYXBwLnBhdGhzLmNvbmZpZygnYXNzZXRzLXB1Ymxpc2hlZC5qc29uJyksXG5cdFx0XHRKU09OLnN0cmluZ2lmeShjb25maWcsIG51bGwsICcgJyksXG5cdFx0KVxuXHR9XG59XG4iXX0=