exhibit-plugin-serve
Version:
No-op transform that serves your filemap over HTTP as a side-effect.
258 lines (190 loc) • 27.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _koa = require('koa');
var _koa2 = _interopRequireDefault(_koa);
var _http = require('http');
var _http2 = _interopRequireDefault(_http);
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
var _portscannerPlus = require('portscanner-plus');
var _lodash = require('lodash');
var _bluebird = require('bluebird');
var _bluebird2 = _interopRequireDefault(_bluebird);
var _socket = require('socket.io');
var _socket2 = _interopRequireDefault(_socket);
var _exhibit = require('exhibit');
var _exhibitDirectory = require('exhibit-directory');
var _exhibitDirectory2 = _interopRequireDefault(_exhibitDirectory);
var _immutable = require('immutable');
var _injectSnippet = require('./injectSnippet');
var _injectSnippet2 = _interopRequireDefault(_injectSnippet);
var _parseRedirects = require('./parseRedirects');
var _parseRedirects2 = _interopRequireDefault(_parseRedirects);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const RELOAD_URL = '/__reload-client.js';
const defaults = {
webRoot: '.',
reload: false,
redirects: true,
log: true
};
exports.default = (...args) => {
let options;
if ((0, _lodash.isString)(args[0])) {
options = Object.assign({}, defaults, args[1]);
options.webRoot = args[0];
} else {
options = Object.assign({}, defaults, args[0]);
}
let files = (0, _exhibit.normalize)({});
let _ready;
let io;
let redirects = [];
let numRedirects = 0;
const redirectsManifestName = _path2.default.normalize(_path2.default.join(options.webRoot, '_redirects'));
const reload = async names => {
io.emit('reload', names.map(name => _path2.default.relative(options.webRoot, name)));
};
// one-time promise factory. the returned promise fulfills when the web server is listening
const ready = () => {
if (!_ready) {
_ready = (async () => {
const app = new _koa2.default();
const snippet = `<script src="${RELOAD_URL}"></script>`;
// precompile the clientside reload script
const reloadScript = options.reload ? await (async () => {
// TODO make a way for plugins to register their own custom extra build tasks, so we can prebuild the client script as part of the main monorepo build process, and get rid of this step.
// until then, this just adds a couple of unnecessary deps and a second or two delay to starting up.
const clientPath = _path2.default.join(__dirname, 'client');
const clientDir = new _exhibitDirectory2.default(clientPath, { force: true });
const clientBuilt = await (0, _exhibit.compose)((0, _exhibit.plugin)('babel', {
root: clientPath
}), (0, _exhibit.plugin)('browserify', {
root: clientPath
}))((await clientDir.read()));
return clientBuilt.get('client.entry.js');
})() : '';
// write the middleware
app.use(async ctx => {
/* eslint-disable no-param-reassign */
// only handle GET and HEAD requests
if (ctx.method !== 'HEAD' && ctx.method !== 'GET') return;
// quickly return the reload script if appropriate
if (options.reload && ctx.path === RELOAD_URL) {
ctx.type = 'js';
if (ctx.method !== 'HEAD') ctx.body = reloadScript;
return;
}
// make an OS-native version of the path (replace slashes with this OS's path delimiter)
const normalPath = ctx.path.substring(1).replace(/\//g, _path2.default.sep);
// work out which file they've actually requested
let requestedFile = _path2.default.normalize(_path2.default.join(options.webRoot, normalPath));
// handle netlify-style 'redirects' (i.e. custom routes)
let rewritten = false;
if (options.redirects) {
for (let i = 0; i < numRedirects; i += 1) {
const { redirect, code } = redirects[i];
const targetPath = redirect(`/${normalPath}`);
if (targetPath) {
switch (code) {
// redirection
case 301:
case 302:
ctx.status = code;
ctx.redirect(`${ctx.protocol}://${ctx.host}${targetPath}`);
return;
// passthrough
case 200:
case 404:
ctx.status = code;
requestedFile = _path2.default.normalize(_path2.default.join(options.webRoot, targetPath));
rewritten = true;
break;
default:
throw new Error(`Unexpected HTTP status: ${redirect.status}`);
}
break;
}
}
}
// add "/index" if it's the root request
if (!rewritten && normalPath === '') requestedFile = _path2.default.join(requestedFile, 'index');
// ...or to any request that ends with a slash
else if (requestedFile.endsWith('/')) requestedFile += 'index';
let type = _path2.default.extname(requestedFile).replace(/^\./, '') || 'html';
let contents = files.get(requestedFile);
// if (!type || !type.length) type = 'html';
if (!contents) {
contents = files.get(`${requestedFile}.html`);
type = 'html';
}
if (options.reload && type === 'html' && contents) {
// console.log('injecting snippet');
contents = (0, _injectSnippet2.default)(String(contents), snippet);
} // else console.log('NOT injecting snippet', type, options.reload, contents);
if (contents) {
if (ctx.method !== 'HEAD') ctx.body = contents;
ctx.type = type;
return;
}
// try redirecting with a slash, if there's an index.html
if (normalPath.length && !normalPath.endsWith('/') && files.get(_path2.default.join(requestedFile, 'index.html'))) {
console.log(`exhibit-plugin-serve: redirecting "${ctx.path}" -> "${ctx.path}/"`);
ctx.status = 301;
ctx.redirect(`${ctx.protocol}://${ctx.host}${ctx.path}/`);
return;
}
// can't find anything to resolve this request, it's a 404
ctx.status = 404;
if (ctx.method !== 'HEAD') {
ctx.body = [`<h1>404 Not Found: ${requestedFile}</h1>`, '<p>Available paths:</p>', '<ul>', ...[...files.keys()].slice(0, 100)
// .filter(name =>
// subdir(servePath, path.resolve(dir._absolutePath, name))
// )
.map(name => {
// const pathname = `/${path.relative(
// servePath, path.resolve(dir._absolutePath, name)
// )}`;
const pathname = name;
return `<li><a href="${pathname}">${pathname}</a></li>`;
}), '</ul>'].join('');
if (options.reload) {
ctx.body = (0, _injectSnippet2.default)(ctx.body, snippet);
}
}
/* eslint-enable no-param-reassign */
});
const [serverPort] = await (0, _portscannerPlus.getPorts)(1, 8000, 9000);
const server = _http2.default.createServer(app.callback());
await _bluebird2.default.promisify(server.listen.bind(server))(serverPort);
if (options.reload) io = new _socket2.default(server);
if (options.onReady) {
options.onReady({ port: serverPort });
}
if (options.log) {
console.log(`exhibit-plugin-serve: serving at http://localhost:${serverPort}/`);
}
})();
}
return _ready;
};
return async _files => {
const changedNames = _immutable.Set.fromKeys((0, _exhibit.diff)(files, _files));
// (re)parse the redirects if they've changed
if (options.redirects && changedNames.has(redirectsManifestName)) {
const config = _files.get(redirectsManifestName);
redirects = config ? (0, _parseRedirects2.default)(String(config)) : [];
numRedirects = redirects.length;
}
// expose new filemap to the server
files = _files;
await ready();
if (options.reload && changedNames.size) {
await reload(changedNames);
}
return _files;
};
};
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImV4aGliaXQtcGx1Z2luLXNlcnZlL2luZGV4LmpzIl0sIm5hbWVzIjpbIlJFTE9BRF9VUkwiLCJkZWZhdWx0cyIsIndlYlJvb3QiLCJyZWxvYWQiLCJyZWRpcmVjdHMiLCJsb2ciLCJhcmdzIiwib3B0aW9ucyIsIk9iamVjdCIsImFzc2lnbiIsImZpbGVzIiwiX3JlYWR5IiwiaW8iLCJudW1SZWRpcmVjdHMiLCJyZWRpcmVjdHNNYW5pZmVzdE5hbWUiLCJub3JtYWxpemUiLCJqb2luIiwibmFtZXMiLCJlbWl0IiwibWFwIiwibmFtZSIsInJlbGF0aXZlIiwicmVhZHkiLCJhcHAiLCJzbmlwcGV0IiwicmVsb2FkU2NyaXB0IiwiY2xpZW50UGF0aCIsIl9fZGlybmFtZSIsImNsaWVudERpciIsImZvcmNlIiwiY2xpZW50QnVpbHQiLCJyb290IiwicmVhZCIsImdldCIsInVzZSIsImN0eCIsIm1ldGhvZCIsInBhdGgiLCJ0eXBlIiwiYm9keSIsIm5vcm1hbFBhdGgiLCJzdWJzdHJpbmciLCJyZXBsYWNlIiwic2VwIiwicmVxdWVzdGVkRmlsZSIsInJld3JpdHRlbiIsImkiLCJyZWRpcmVjdCIsImNvZGUiLCJ0YXJnZXRQYXRoIiwic3RhdHVzIiwicHJvdG9jb2wiLCJob3N0IiwiRXJyb3IiLCJlbmRzV2l0aCIsImV4dG5hbWUiLCJjb250ZW50cyIsIlN0cmluZyIsImxlbmd0aCIsImNvbnNvbGUiLCJrZXlzIiwic2xpY2UiLCJwYXRobmFtZSIsInNlcnZlclBvcnQiLCJzZXJ2ZXIiLCJjcmVhdGVTZXJ2ZXIiLCJjYWxsYmFjayIsInByb21pc2lmeSIsImxpc3RlbiIsImJpbmQiLCJvblJlYWR5IiwicG9ydCIsIl9maWxlcyIsImNoYW5nZWROYW1lcyIsImZyb21LZXlzIiwiaGFzIiwiY29uZmlnIiwic2l6ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBRUE7Ozs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOztBQUNBOzs7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b0QwRCxVQUFXLEdBQTVFO0FBQ0Q7QUFDRixPQXRLUSxHQUFUO0FBdUtEOztBQUVELFdBQU9wRCxNQUFQO0FBQ0QsR0E1S0Q7O0FBOEtBLFNBQU8sTUFBTzZELE1BQVAsSUFBa0I7QUFDdkIsVUFBTUMsZUFBZSxlQUFhQyxRQUFiLENBQXNCLG1CQUFLaEUsS0FBTCxFQUFZOEQsTUFBWixDQUF0QixDQUFyQjs7QUFFQTtBQUNBLFFBQUlqRSxRQUFRSCxTQUFSLElBQXFCcUUsYUFBYUUsR0FBYixDQUFpQjdELHFCQUFqQixDQUF6QixFQUFrRTtBQUNoRSxZQUFNOEQsU0FBU0osT0FBT3ZDLEdBQVAsQ0FBV25CLHFCQUFYLENBQWY7QUFDQVYsa0JBQVl3RSxTQUFTLDhCQUFlbkIsT0FBT21CLE1BQVAsQ0FBZixDQUFULEdBQTBDLEVBQXREO0FBQ0EvRCxxQkFBZVQsVUFBVXNELE1BQXpCO0FBQ0Q7O0FBRUQ7QUFDQWhELFlBQVE4RCxNQUFSOztBQUVBLFVBQU1sRCxPQUFOOztBQUVBLFFBQUlmLFFBQVFKLE1BQVIsSUFBa0JzRSxhQUFhSSxJQUFuQyxFQUF5QztBQUN2QyxZQUFNMUUsT0FBT3NFLFlBQVAsQ0FBTjtBQUNEOztBQUVELFdBQU9ELE1BQVA7QUFDRCxHQXBCRDtBQXFCRCxDIiwiZmlsZSI6ImluZGV4LmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQGZsb3dcblxuaW1wb3J0IEtvYSBmcm9tICdrb2EnO1xuaW1wb3J0IGh0dHAgZnJvbSAnaHR0cCc7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IGdldFBvcnRzIH0gZnJvbSAncG9ydHNjYW5uZXItcGx1cyc7XG5pbXBvcnQgeyBpc1N0cmluZyB9IGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQgQmx1ZWJpcmQgZnJvbSAnYmx1ZWJpcmQnO1xuaW1wb3J0IFNvY2tldElPIGZyb20gJ3NvY2tldC5pbyc7XG5pbXBvcnQgeyBjb21wb3NlLCBkaWZmLCBub3JtYWxpemUsIHBsdWdpbiB9IGZyb20gJ2V4aGliaXQnO1xuaW1wb3J0IERpcmVjdG9yeSBmcm9tICdleGhpYml0LWRpcmVjdG9yeSc7XG5pbXBvcnQgeyBTZXQgYXMgSW1tdXRhYmxlU2V0IH0gZnJvbSAnaW1tdXRhYmxlJztcbmltcG9ydCBpbmplY3RTbmlwcGV0IGZyb20gJy4vaW5qZWN0U25pcHBldCc7XG5pbXBvcnQgcGFyc2VSZWRpcmVjdHMgZnJvbSAnLi9wYXJzZVJlZGlyZWN0cyc7XG5cbmltcG9ydCB0eXBlIHsgVHJhbnNmb3JtIH0gZnJvbSAnLi4vLi4vdHlwZXMnO1xuaW1wb3J0IHR5cGUgeyBSZWRpcmVjdGlvbiB9IGZyb20gJy4vdHlwZXMnO1xuXG5jb25zdCBSRUxPQURfVVJMID0gJy9fX3JlbG9hZC1jbGllbnQuanMnO1xuXG5jb25zdCBkZWZhdWx0cyA9IHtcbiAgd2ViUm9vdDogJy4nLFxuICByZWxvYWQ6IGZhbHNlLFxuICByZWRpcmVjdHM6IHRydWUsXG4gIGxvZzogdHJ1ZSxcbn07XG5cbmV4cG9ydCBkZWZhdWx0ICguLi5hcmdzOiBhbnlbXSk6IFRyYW5zZm9ybSA9PiB7XG4gIGxldCBvcHRpb25zO1xuXG4gIGlmIChpc1N0cmluZyhhcmdzWzBdKSkge1xuICAgIG9wdGlvbnMgPSBPYmplY3QuYXNzaWduKHt9LCBkZWZhdWx0cywgYXJnc1sxXSk7XG4gICAgb3B0aW9ucy53ZWJSb290ID0gYXJnc1swXTtcbiAgfSBlbHNlIHtcbiAgICBvcHRpb25zID0gT2JqZWN0LmFzc2lnbih7fSwgZGVmYXVsdHMsIGFyZ3NbMF0pO1xuICB9XG5cbiAgbGV0IGZpbGVzID0gbm9ybWFsaXplKHt9KTtcbiAgbGV0IF9yZWFkeTtcbiAgbGV0IGlvO1xuICBsZXQgcmVkaXJlY3RzOiBBcnJheTxSZWRpcmVjdGlvbj4gPSBbXTtcbiAgbGV0IG51bVJlZGlyZWN0cyA9IDA7XG4gIGNvbnN0IHJlZGlyZWN0c01hbmlmZXN0TmFtZSA9IHBhdGgubm9ybWFsaXplKHBhdGguam9pbihvcHRpb25zLndlYlJvb3QsICdfcmVkaXJlY3RzJykpO1xuXG4gIGNvbnN0IHJlbG9hZCA9IGFzeW5jIChuYW1lcykgPT4ge1xuICAgIGlvLmVtaXQoJ3JlbG9hZCcsIG5hbWVzLm1hcChuYW1lID0+IHBhdGgucmVsYXRpdmUob3B0aW9ucy53ZWJSb290LCBuYW1lKSkpO1xuICB9O1xuXG4gIC8vIG9uZS10aW1lIHByb21pc2UgZmFjdG9yeS4gdGhlIHJldHVybmVkIHByb21pc2UgZnVsZmlsbHMgd2hlbiB0aGUgd2ViIHNlcnZlciBpcyBsaXN0ZW5pbmdcbiAgY29uc3QgcmVhZHkgPSAoKSA9PiB7XG4gICAgaWYgKCFfcmVhZHkpIHtcbiAgICAgIF9yZWFkeSA9IChhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGFwcCA9IG5ldyBLb2EoKTtcblxuICAgICAgICBjb25zdCBzbmlwcGV0ID0gYDxzY3JpcHQgc3JjPVwiJHtSRUxPQURfVVJMfVwiPjwvc2NyaXB0PmA7XG5cbiAgICAgICAgLy8gcHJlY29tcGlsZSB0aGUgY2xpZW50c2lkZSByZWxvYWQgc2NyaXB0XG4gICAgICAgIGNvbnN0IHJlbG9hZFNjcmlwdCA9IG9wdGlvbnMucmVsb2FkID8gYXdhaXQgKGFzeW5jICgpID0+IHtcbiAgICAgICAgICAvLyBUT0RPIG1ha2UgYSB3YXkgZm9yIHBsdWdpbnMgdG8gcmVnaXN0ZXIgdGhlaXIgb3duIGN1c3RvbSBleHRyYSBidWlsZCB0YXNrcywgc28gd2UgY2FuIHByZWJ1aWxkIHRoZSBjbGllbnQgc2NyaXB0IGFzIHBhcnQgb2YgdGhlIG1haW4gbW9ub3JlcG8gYnVpbGQgcHJvY2VzcywgYW5kIGdldCByaWQgb2YgdGhpcyBzdGVwLlxuICAgICAgICAgIC8vIHVudGlsIHRoZW4sIHRoaXMganVzdCBhZGRzIGEgY291cGxlIG9mIHVubmVjZXNzYXJ5IGRlcHMgYW5kIGEgc2Vjb25kIG9yIHR3byBkZWxheSB0byBzdGFydGluZyB1cC5cbiAgICAgICAgICBjb25zdCBjbGllbnRQYXRoID0gcGF0aC5qb2luKF9fZGlybmFtZSwgJ2NsaWVudCcpO1xuICAgICAgICAgIGNvbnN0IGNsaWVudERpciA9IG5ldyBEaXJlY3RvcnkoY2xpZW50UGF0aCwgeyBmb3JjZTogdHJ1ZSB9KTtcbiAgICAgICAgICBjb25zdCBjbGllbnRCdWlsdCA9IGF3YWl0IGNvbXBvc2UoXG4gICAgICAgICAgICBwbHVnaW4oJ2JhYmVsJywge1xuICAgICAgICAgICAgICByb290OiBjbGllbnRQYXRoLFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBwbHVnaW4oJ2Jyb3dzZXJpZnknLCB7XG4gICAgICAgICAgICAgIHJvb3Q6IGNsaWVudFBhdGgsXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICApKGF3YWl0IGNsaWVudERpci5yZWFkKCkpO1xuXG4gICAgICAgICAgcmV0dXJuIGNsaWVudEJ1aWx0LmdldCgnY2xpZW50LmVudHJ5LmpzJyk7XG4gICAgICAgIH0pKCkgOiAnJztcblxuICAgICAgICAvLyB3cml0ZSB0aGUgbWlkZGxld2FyZVxuICAgICAgICBhcHAudXNlKGFzeW5jIChjdHgpID0+IHtcbiAgICAgICAgICAvKiBlc2xpbnQtZGlzYWJsZSBuby1wYXJhbS1yZWFzc2lnbiAqL1xuXG4gICAgICAgICAgLy8gb25seSBoYW5kbGUgR0VUIGFuZCBIRUFEIHJlcXVlc3RzXG4gICAgICAgICAgaWYgKGN0eC5tZXRob2QgIT09ICdIRUFEJyAmJiBjdHgubWV0aG9kICE9PSAnR0VUJykgcmV0dXJuO1xuXG4gICAgICAgICAgLy8gcXVpY2tseSByZXR1cm4gdGhlIHJlbG9hZCBzY3JpcHQgaWYgYXBwcm9wcmlhdGVcbiAgICAgICAgICBpZiAob3B0aW9ucy5yZWxvYWQgJiYgY3R4LnBhdGggPT09IFJFTE9BRF9VUkwpIHtcbiAgICAgICAgICAgIGN0eC50eXBlID0gJ2pzJztcbiAgICAgICAgICAgIGlmIChjdHgubWV0aG9kICE9PSAnSEVBRCcpIGN0eC5ib2R5ID0gcmVsb2FkU2NyaXB0O1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIG1ha2UgYW4gT1MtbmF0aXZlIHZlcnNpb24gb2YgdGhlIHBhdGggKHJlcGxhY2Ugc2xhc2hlcyB3aXRoIHRoaXMgT1MncyBwYXRoIGRlbGltaXRlcilcbiAgICAgICAgICBjb25zdCBub3JtYWxQYXRoID0gY3R4LnBhdGguc3Vic3RyaW5nKDEpLnJlcGxhY2UoL1xcLy9nLCBwYXRoLnNlcCk7XG5cbiAgICAgICAgICAvLyB3b3JrIG91dCB3aGljaCBmaWxlIHRoZXkndmUgYWN0dWFsbHkgcmVxdWVzdGVkXG4gICAgICAgICAgbGV0IHJlcXVlc3RlZEZpbGUgPSBwYXRoLm5vcm1hbGl6ZShwYXRoLmpvaW4oXG4gICAgICAgICAgICBvcHRpb25zLndlYlJvb3QsXG4gICAgICAgICAgICBub3JtYWxQYXRoLFxuICAgICAgICAgICkpO1xuXG4gICAgICAgICAgLy8gaGFuZGxlIG5ldGxpZnktc3R5bGUgJ3JlZGlyZWN0cycgKGkuZS4gY3VzdG9tIHJvdXRlcylcbiAgICAgICAgICBsZXQgcmV3cml0dGVuID0gZmFsc2U7XG4gICAgICAgICAgaWYgKG9wdGlvbnMucmVkaXJlY3RzKSB7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bVJlZGlyZWN0czsgaSArPSAxKSB7XG4gICAgICAgICAgICAgIGNvbnN0IHsgcmVkaXJlY3QsIGNvZGUgfSA9IHJlZGlyZWN0c1tpXTtcblxuICAgICAgICAgICAgICBjb25zdCB0YXJnZXRQYXRoID0gcmVkaXJlY3QoYC8ke25vcm1hbFBhdGh9YCk7XG5cbiAgICAgICAgICAgICAgaWYgKHRhcmdldFBhdGgpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKGNvZGUpIHtcbiAgICAgICAgICAgICAgICAgIC8vIHJlZGlyZWN0aW9uXG4gICAgICAgICAgICAgICAgICBjYXNlIDMwMTpcbiAgICAgICAgICAgICAgICAgIGNhc2UgMzAyOlxuICAgICAgICAgICAgICAgICAgICBjdHguc3RhdHVzID0gY29kZTtcbiAgICAgICAgICAgICAgICAgICAgY3R4LnJlZGlyZWN0KGAke2N0eC5wcm90b2NvbH06Ly8ke2N0eC5ob3N0fSR7dGFyZ2V0UGF0aH1gKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgICAgICAgICAgICAvLyBwYXNzdGhyb3VnaFxuICAgICAgICAgICAgICAgICAgY2FzZSAyMDA6XG4gICAgICAgICAgICAgICAgICBjYXNlIDQwNDpcbiAgICAgICAgICAgICAgICAgICAgY3R4LnN0YXR1cyA9IGNvZGU7XG4gICAgICAgICAgICAgICAgICAgIHJlcXVlc3RlZEZpbGUgPSBwYXRoLm5vcm1hbGl6ZShwYXRoLmpvaW4oXG4gICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy53ZWJSb290LFxuICAgICAgICAgICAgICAgICAgICAgIHRhcmdldFBhdGgsXG4gICAgICAgICAgICAgICAgICAgICkpO1xuICAgICAgICAgICAgICAgICAgICByZXdyaXR0ZW4gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmV4cGVjdGVkIEhUVFAgc3RhdHVzOiAke3JlZGlyZWN0LnN0YXR1c31gKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIGFkZCBcIi9pbmRleFwiIGlmIGl0J3MgdGhlIHJvb3QgcmVxdWVzdFxuICAgICAgICAgIGlmICghcmV3cml0dGVuICYmIG5vcm1hbFBhdGggPT09ICcnKSByZXF1ZXN0ZWRGaWxlID0gcGF0aC5qb2luKHJlcXVlc3RlZEZpbGUsICdpbmRleCcpO1xuICAgICAgICAgIC8vIC4uLm9yIHRvIGFueSByZXF1ZXN0IHRoYXQgZW5kcyB3aXRoIGEgc2xhc2hcbiAgICAgICAgICBlbHNlIGlmIChyZXF1ZXN0ZWRGaWxlLmVuZHNXaXRoKCcvJykpIHJlcXVlc3RlZEZpbGUgKz0gJ2luZGV4JztcblxuICAgICAgICAgIGxldCB0eXBlID0gcGF0aC5leHRuYW1lKHJlcXVlc3RlZEZpbGUpLnJlcGxhY2UoL15cXC4vLCAnJykgfHwgJ2h0bWwnO1xuICAgICAgICAgIGxldCBjb250ZW50cyA9IGZpbGVzLmdldChyZXF1ZXN0ZWRGaWxlKTtcblxuICAgICAgICAgIC8vIGlmICghdHlwZSB8fCAhdHlwZS5sZW5ndGgpIHR5cGUgPSAnaHRtbCc7XG5cbiAgICAgICAgICBpZiAoIWNvbnRlbnRzKSB7XG4gICAgICAgICAgICBjb250ZW50cyA9IGZpbGVzLmdldChgJHtyZXF1ZXN0ZWRGaWxlfS5odG1sYCk7XG4gICAgICAgICAgICB0eXBlID0gJ2h0bWwnO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChvcHRpb25zLnJlbG9hZCAmJiB0eXBlID09PSAnaHRtbCcgJiYgY29udGVudHMpIHtcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdpbmplY3Rpbmcgc25pcHBldCcpO1xuICAgICAgICAgICAgY29udGVudHMgPSBpbmplY3RTbmlwcGV0KFN0cmluZyhjb250ZW50cyksIHNuaXBwZXQpO1xuICAgICAgICAgIH0gLy8gZWxzZSBjb25zb2xlLmxvZygnTk9UIGluamVjdGluZyBzbmlwcGV0JywgdHlwZSwgb3B0aW9ucy5yZWxvYWQsIGNvbnRlbnRzKTtcblxuICAgICAgICAgIGlmIChjb250ZW50cykge1xuICAgICAgICAgICAgaWYgKGN0eC5tZXRob2QgIT09ICdIRUFEJykgY3R4LmJvZHkgPSBjb250ZW50cztcbiAgICAgICAgICAgIGN0eC50eXBlID0gdHlwZTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyB0cnkgcmVkaXJlY3Rpbmcgd2l0aCBhIHNsYXNoLCBpZiB0aGVyZSdzIGFuIGluZGV4Lmh0bWxcbiAgICAgICAgICBpZiAobm9ybWFsUGF0aC5sZW5ndGggJiYgIW5vcm1hbFBhdGguZW5kc1dpdGgoJy8nKSAmJiBmaWxlcy5nZXQocGF0aC5qb2luKHJlcXVlc3RlZEZpbGUsICdpbmRleC5odG1sJykpKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgZXhoaWJpdC1wbHVnaW4tc2VydmU6IHJlZGlyZWN0aW5nIFwiJHtjdHgucGF0aH1cIiAtPiBcIiR7Y3R4LnBhdGh9L1wiYCk7XG4gICAgICAgICAgICBjdHguc3RhdHVzID0gMzAxO1xuICAgICAgICAgICAgY3R4LnJlZGlyZWN0KGAke2N0eC5wcm90b2NvbH06Ly8ke2N0eC5ob3N0fSR7Y3R4LnBhdGh9L2ApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIGNhbid0IGZpbmQgYW55dGhpbmcgdG8gcmVzb2x2ZSB0aGlzIHJlcXVlc3QsIGl0J3MgYSA0MDRcbiAgICAgICAgICBjdHguc3RhdHVzID0gNDA0O1xuXG4gICAgICAgICAgaWYgKGN0eC5tZXRob2QgIT09ICdIRUFEJykge1xuICAgICAgICAgICAgY3R4LmJvZHkgPSBbXG4gICAgICAgICAgICAgIGA8aDE+NDA0IE5vdCBGb3VuZDogJHtyZXF1ZXN0ZWRGaWxlfTwvaDE+YCxcbiAgICAgICAgICAgICAgJzxwPkF2YWlsYWJsZSBwYXRoczo8L3A+JyxcbiAgICAgICAgICAgICAgJzx1bD4nLFxuICAgICAgICAgICAgICAuLi4oXG4gICAgICAgICAgICAgICAgWy4uLmZpbGVzLmtleXMoKV1cbiAgICAgICAgICAgICAgICAgIC5zbGljZSgwLCAxMDApXG4gICAgICAgICAgICAgICAgICAvLyAuZmlsdGVyKG5hbWUgPT5cbiAgICAgICAgICAgICAgICAgIC8vICAgc3ViZGlyKHNlcnZlUGF0aCwgcGF0aC5yZXNvbHZlKGRpci5fYWJzb2x1dGVQYXRoLCBuYW1lKSlcbiAgICAgICAgICAgICAgICAgIC8vIClcbiAgICAgICAgICAgICAgICAgIC5tYXAoKG5hbWUpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgLy8gY29uc3QgcGF0aG5hbWUgPSBgLyR7cGF0aC5yZWxhdGl2ZShcbiAgICAgICAgICAgICAgICAgICAgLy8gICBzZXJ2ZVBhdGgsIHBhdGgucmVzb2x2ZShkaXIuX2Fic29sdXRlUGF0aCwgbmFtZSlcbiAgICAgICAgICAgICAgICAgICAgLy8gKX1gO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXRobmFtZSA9IG5hbWU7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGA8bGk+PGEgaHJlZj1cIiR7cGF0aG5hbWV9XCI+JHtwYXRobmFtZX08L2E+PC9saT5gO1xuICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgJzwvdWw+JyxcbiAgICAgICAgICAgIF0uam9pbignJyk7XG5cbiAgICAgICAgICAgIGlmIChvcHRpb25zLnJlbG9hZCkge1xuICAgICAgICAgICAgICBjdHguYm9keSA9IGluamVjdFNuaXBwZXQoY3R4LmJvZHksIHNuaXBwZXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIC8qIGVzbGludC1lbmFibGUgbm8tcGFyYW0tcmVhc3NpZ24gKi9cbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgW3NlcnZlclBvcnRdID0gYXdhaXQgZ2V0UG9ydHMoMSwgODAwMCwgOTAwMCk7XG5cbiAgICAgICAgY29uc3Qgc2VydmVyID0gaHR0cC5jcmVhdGVTZXJ2ZXIoYXBwLmNhbGxiYWNrKCkpO1xuXG4gICAgICAgIGF3YWl0IEJsdWViaXJkLnByb21pc2lmeShzZXJ2ZXIubGlzdGVuLmJpbmQoc2VydmVyKSkoc2VydmVyUG9ydCk7XG5cbiAgICAgICAgaWYgKG9wdGlvbnMucmVsb2FkKSBpbyA9IG5ldyBTb2NrZXRJTyhzZXJ2ZXIpO1xuXG4gICAgICAgIGlmIChvcHRpb25zLm9uUmVhZHkpIHtcbiAgICAgICAgICBvcHRpb25zLm9uUmVhZHkoeyBwb3J0OiBzZXJ2ZXJQb3J0IH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG9wdGlvbnMubG9nKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coYGV4aGliaXQtcGx1Z2luLXNlcnZlOiBzZXJ2aW5nIGF0IGh0dHA6Ly9sb2NhbGhvc3Q6JHtzZXJ2ZXJQb3J0fS9gKTtcbiAgICAgICAgfVxuICAgICAgfSkoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gX3JlYWR5O1xuICB9O1xuXG4gIHJldHVybiBhc3luYyAoX2ZpbGVzKSA9PiB7XG4gICAgY29uc3QgY2hhbmdlZE5hbWVzID0gSW1tdXRhYmxlU2V0LmZyb21LZXlzKGRpZmYoZmlsZXMsIF9maWxlcykpO1xuXG4gICAgLy8gKHJlKXBhcnNlIHRoZSByZWRpcmVjdHMgaWYgdGhleSd2ZSBjaGFuZ2VkXG4gICAgaWYgKG9wdGlvbnMucmVkaXJlY3RzICYmIGNoYW5nZWROYW1lcy5oYXMocmVkaXJlY3RzTWFuaWZlc3ROYW1lKSkge1xuICAgICAgY29uc3QgY29uZmlnID0gX2ZpbGVzLmdldChyZWRpcmVjdHNNYW5pZmVzdE5hbWUpO1xuICAgICAgcmVkaXJlY3RzID0gY29uZmlnID8gcGFyc2VSZWRpcmVjdHMoU3RyaW5nKGNvbmZpZykpIDogW107XG4gICAgICBudW1SZWRpcmVjdHMgPSByZWRpcmVjdHMubGVuZ3RoO1xuICAgIH1cblxuICAgIC8vIGV4cG9zZSBuZXcgZmlsZW1hcCB0byB0aGUgc2VydmVyXG4gICAgZmlsZXMgPSBfZmlsZXM7XG5cbiAgICBhd2FpdCByZWFkeSgpO1xuXG4gICAgaWYgKG9wdGlvbnMucmVsb2FkICYmIGNoYW5nZWROYW1lcy5zaXplKSB7XG4gICAgICBhd2FpdCByZWxvYWQoY2hhbmdlZE5hbWVzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gX2ZpbGVzO1xuICB9O1xufTtcbiJdfQ==