grind-http
Version:
HTTP kernel for Grind, powered by Express
144 lines (113 loc) • 14.2 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.HttpServer = void 0;
function _isnil(val) { return val === null || typeof val === 'undefined'; }
const chalk = require('chalk');
const cluster = require('cluster');
const fs = require('fs');
const path = require('path');
class HttpServer {
constructor(bootstrapper) {
this.bootstrapper = null;
this.pidFile = null;
this.bootstrapper = bootstrapper;
}
async start() {
let clustered = false;
let watchDirs = null;
for (const arg of process.argv) {
if (arg === '--cluster') {
clustered = true;
} else if (arg.startsWith('--cluster=')) {
clustered = Number.parseInt(arg.substr(10));
} else if (arg.startsWith('--watch=')) {
watchDirs = [];
for (const dir of arg.substr(8).split(',')) {
if (dir.substring(0, 1) === '/') {
watchDirs.push(dir);
} else {
watchDirs.push(path.join(process.cwd(), dir));
}
}
} else if (arg.startsWith('--pid=') && cluster.isMaster) {
this.pidFile = arg.substr(6);
}
}
if (!_isnil(this.pidFile)) {
// eslint-disable-next-line no-sync,no-empty
try {
fs.writeFileSync(this.pidFile, process.pid);
} catch (err) {}
}
if (clustered && !_isnil(watchDirs)) {
console.log('--watch and --cluster can not be used together');
process.exit(1);
}
if (!_isnil(watchDirs)) {
await this.watch(watchDirs);
} else if (clustered === false) {
await this.serve();
} else {
await this.cluster(clustered);
}
}
async serve(worker = null) {
const app = this.bootstrapper();
const port = app.port;
const server = await app.start(port, () => {
if (!_isnil(worker)) {
process.title = `${process.cwd()} [server:${port}]`;
console.log(chalk.yellow('Worker %d listening on %d'), worker.id, port);
} else {
process.title = `${process.cwd()} [cluster] [worker:${port}]`;
console.log(chalk.yellow('Listening on port %d'), port);
}
});
const teardown = exitCode => {
const exit = () => {
if (!_isnil(this.pidFile)) {
// eslint-disable-next-line no-sync,no-empty
try {
fs.unlinkSync(this.pidFile);
} catch (err) {}
}
process.exit(exitCode);
}; // Attempt a safe teardown
server.close(exit); // After 10s, kill
setTimeout(exit, 10000);
};
process.on('SIGTERM', () => teardown(0));
process.on('SIGINT', () => teardown(0));
return server;
}
cluster(workers = null) {
if (!cluster.isMaster) {
return this.serve(cluster.worker);
}
if (!_isnil(process.env.NODE_CLUSTER)) {
workers = Number.parseInt(process.env.NODE_CLUSTER);
}
if (_isnil(workers) || Number.isNaN(workers) || workers <= 0) {
workers = require('os').cpus().length;
}
process.title = `${process.cwd()} [cluster] [master]`;
for (let i = 0; i < workers; i += 1) {
cluster.fork();
}
cluster.on('exit', (deadWorker, code, signal) => {
if (signal === 'SIGTERM' || signal === 'SIGINT') {
return;
}
console.log('Reloading %s', deadWorker.id);
cluster.fork();
});
}
watch(...dirs) {
const Watcher = require('./Watcher.js').Watcher;
return new Watcher(this, dirs).watch();
}
}
exports.HttpServer = HttpServer;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9IdHRwU2VydmVyL0h0dHBTZXJ2ZXIuanMiXSwibmFtZXMiOlsiY2hhbGsiLCJyZXF1aXJlIiwiY2x1c3RlciIsImZzIiwicGF0aCIsIkh0dHBTZXJ2ZXIiLCJjb25zdHJ1Y3RvciIsImJvb3RzdHJhcHBlciIsInBpZEZpbGUiLCJzdGFydCIsImNsdXN0ZXJlZCIsIndhdGNoRGlycyIsImFyZyIsInByb2Nlc3MiLCJhcmd2Iiwic3RhcnRzV2l0aCIsIk51bWJlciIsInBhcnNlSW50Iiwic3Vic3RyIiwiZGlyIiwic3BsaXQiLCJzdWJzdHJpbmciLCJwdXNoIiwiam9pbiIsImN3ZCIsImlzTWFzdGVyIiwid3JpdGVGaWxlU3luYyIsInBpZCIsImVyciIsImNvbnNvbGUiLCJsb2ciLCJleGl0Iiwid2F0Y2giLCJzZXJ2ZSIsIndvcmtlciIsImFwcCIsInBvcnQiLCJzZXJ2ZXIiLCJ0aXRsZSIsInllbGxvdyIsImlkIiwidGVhcmRvd24iLCJleGl0Q29kZSIsInVubGlua1N5bmMiLCJjbG9zZSIsInNldFRpbWVvdXQiLCJvbiIsIndvcmtlcnMiLCJlbnYiLCJOT0RFX0NMVVNURVIiLCJpc05hTiIsImNwdXMiLCJsZW5ndGgiLCJpIiwiZm9yayIsImRlYWRXb3JrZXIiLCJjb2RlIiwic2lnbmFsIiwiZGlycyIsIldhdGNoZXIiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBLE1BQU1BLEtBQUssR0FBR0MsT0FBTyxDQUFDLE9BQUQsQ0FBckI7O0FBQ0EsTUFBTUMsT0FBTyxHQUFHRCxPQUFPLENBQUMsU0FBRCxDQUF2Qjs7QUFDQSxNQUFNRSxFQUFFLEdBQUdGLE9BQU8sQ0FBQyxJQUFELENBQWxCOztBQUNBLE1BQU1HLElBQUksR0FBR0gsT0FBTyxDQUFDLE1BQUQsQ0FBcEI7O0FBRU8sTUFBTUksVUFBTixDQUFpQjtBQUl2QkMsRUFBQUEsV0FBVyxDQUFDQyxZQUFELEVBQWU7QUFBQSxTQUgxQkEsWUFHMEIsR0FIWCxJQUdXO0FBQUEsU0FGMUJDLE9BRTBCLEdBRmhCLElBRWdCO0FBQ3pCLFNBQUtELFlBQUwsR0FBb0JBLFlBQXBCO0FBQ0E7O0FBRUQsUUFBTUUsS0FBTixHQUFjO0FBQ2IsUUFBSUMsU0FBUyxHQUFHLEtBQWhCO0FBQ0EsUUFBSUMsU0FBUyxHQUFHLElBQWhCOztBQUVBLFNBQUssTUFBTUMsR0FBWCxJQUFrQkMsT0FBTyxDQUFDQyxJQUExQixFQUFnQztBQUMvQixVQUFJRixHQUFHLEtBQUssV0FBWixFQUF5QjtBQUN4QkYsUUFBQUEsU0FBUyxHQUFHLElBQVo7QUFDQSxPQUZELE1BRU8sSUFBSUUsR0FBRyxDQUFDRyxVQUFKLENBQWUsWUFBZixDQUFKLEVBQWtDO0FBQ3hDTCxRQUFBQSxTQUFTLEdBQUdNLE1BQU0sQ0FBQ0MsUUFBUCxDQUFnQkwsR0FBRyxDQUFDTSxNQUFKLENBQVcsRUFBWCxDQUFoQixDQUFaO0FBQ0EsT0FGTSxNQUVBLElBQUlOLEdBQUcsQ0FBQ0csVUFBSixDQUFlLFVBQWYsQ0FBSixFQUFnQztBQUN0Q0osUUFBQUEsU0FBUyxHQUFHLEVBQVo7O0FBRUEsYUFBSyxNQUFNUSxHQUFYLElBQWtCUCxHQUFHLENBQUNNLE1BQUosQ0FBVyxDQUFYLEVBQWNFLEtBQWQsQ0FBb0IsR0FBcEIsQ0FBbEIsRUFBNEM7QUFDM0MsY0FBSUQsR0FBRyxDQUFDRSxTQUFKLENBQWMsQ0FBZCxFQUFpQixDQUFqQixNQUF3QixHQUE1QixFQUFpQztBQUNoQ1YsWUFBQUEsU0FBUyxDQUFDVyxJQUFWLENBQWVILEdBQWY7QUFDQSxXQUZELE1BRU87QUFDTlIsWUFBQUEsU0FBUyxDQUFDVyxJQUFWLENBQWVsQixJQUFJLENBQUNtQixJQUFMLENBQVVWLE9BQU8sQ0FBQ1csR0FBUixFQUFWLEVBQXlCTCxHQUF6QixDQUFmO0FBQ0E7QUFDRDtBQUNELE9BVk0sTUFVQSxJQUFJUCxHQUFHLENBQUNHLFVBQUosQ0FBZSxRQUFmLEtBQTRCYixPQUFPLENBQUN1QixRQUF4QyxFQUFrRDtBQUN4RCxhQUFLakIsT0FBTCxHQUFlSSxHQUFHLENBQUNNLE1BQUosQ0FBVyxDQUFYLENBQWY7QUFDQTtBQUNEOztBQUVELFFBQUksUUFBQyxLQUFLVixPQUFOLENBQUosRUFBeUI7QUFDeEI7QUFDQSxVQUFJO0FBQ0hMLFFBQUFBLEVBQUUsQ0FBQ3VCLGFBQUgsQ0FBaUIsS0FBS2xCLE9BQXRCLEVBQStCSyxPQUFPLENBQUNjLEdBQXZDO0FBQ0EsT0FGRCxDQUVFLE9BQU9DLEdBQVAsRUFBWSxDQUFFO0FBQ2hCOztBQUVELFFBQUlsQixTQUFTLElBQUksUUFBQ0MsU0FBRCxDQUFqQixFQUFtQztBQUNsQ2tCLE1BQUFBLE9BQU8sQ0FBQ0MsR0FBUixDQUFZLGdEQUFaO0FBQ0FqQixNQUFBQSxPQUFPLENBQUNrQixJQUFSLENBQWEsQ0FBYjtBQUNBOztBQUVELFFBQUksUUFBQ3BCLFNBQUQsQ0FBSixFQUFzQjtBQUNyQixZQUFNLEtBQUtxQixLQUFMLENBQVdyQixTQUFYLENBQU47QUFDQSxLQUZELE1BRU8sSUFBSUQsU0FBUyxLQUFLLEtBQWxCLEVBQXlCO0FBQy9CLFlBQU0sS0FBS3VCLEtBQUwsRUFBTjtBQUNBLEtBRk0sTUFFQTtBQUNOLFlBQU0sS0FBSy9CLE9BQUwsQ0FBYVEsU0FBYixDQUFOO0FBQ0E7QUFDRDs7QUFFRCxRQUFNdUIsS0FBTixDQUFZQyxNQUFNLEdBQUcsSUFBckIsRUFBMkI7QUFDMUIsVUFBTUMsR0FBRyxHQUFHLEtBQUs1QixZQUFMLEVBQVo7QUFDQSxVQUFNNkIsSUFBSSxHQUFHRCxHQUFHLENBQUNDLElBQWpCO0FBRUEsVUFBTUMsTUFBTSxHQUFHLE1BQU1GLEdBQUcsQ0FBQzFCLEtBQUosQ0FBVTJCLElBQVYsRUFBZ0IsTUFBTTtBQUMxQyxVQUFJLFFBQUNGLE1BQUQsQ0FBSixFQUFtQjtBQUNsQnJCLFFBQUFBLE9BQU8sQ0FBQ3lCLEtBQVIsR0FBaUIsR0FBRXpCLE9BQU8sQ0FBQ1csR0FBUixFQUFjLFlBQVdZLElBQUssR0FBakQ7QUFDQVAsUUFBQUEsT0FBTyxDQUFDQyxHQUFSLENBQVk5QixLQUFLLENBQUN1QyxNQUFOLENBQWEsMkJBQWIsQ0FBWixFQUF1REwsTUFBTSxDQUFDTSxFQUE5RCxFQUFrRUosSUFBbEU7QUFDQSxPQUhELE1BR087QUFDTnZCLFFBQUFBLE9BQU8sQ0FBQ3lCLEtBQVIsR0FBaUIsR0FBRXpCLE9BQU8sQ0FBQ1csR0FBUixFQUFjLHNCQUFxQlksSUFBSyxHQUEzRDtBQUNBUCxRQUFBQSxPQUFPLENBQUNDLEdBQVIsQ0FBWTlCLEtBQUssQ0FBQ3VDLE1BQU4sQ0FBYSxzQkFBYixDQUFaLEVBQWtESCxJQUFsRDtBQUNBO0FBQ0QsS0FSb0IsQ0FBckI7O0FBVUEsVUFBTUssUUFBUSxHQUFHQyxRQUFRLElBQUk7QUFDNUIsWUFBTVgsSUFBSSxHQUFHLE1BQU07QUFDbEIsWUFBSSxRQUFDLEtBQUt2QixPQUFOLENBQUosRUFBeUI7QUFDeEI7QUFDQSxjQUFJO0FBQ0hMLFlBQUFBLEVBQUUsQ0FBQ3dDLFVBQUgsQ0FBYyxLQUFLbkMsT0FBbkI7QUFDQSxXQUZELENBRUUsT0FBT29CLEdBQVAsRUFBWSxDQUFFO0FBQ2hCOztBQUVEZixRQUFBQSxPQUFPLENBQUNrQixJQUFSLENBQWFXLFFBQWI7QUFDQSxPQVRELENBRDRCLENBWTVCOzs7QUFDQUwsTUFBQUEsTUFBTSxDQUFDTyxLQUFQLENBQWFiLElBQWIsRUFiNEIsQ0FlNUI7O0FBQ0FjLE1BQUFBLFVBQVUsQ0FBQ2QsSUFBRCxFQUFPLEtBQVAsQ0FBVjtBQUNBLEtBakJEOztBQW1CQWxCLElBQUFBLE9BQU8sQ0FBQ2lDLEVBQVIsQ0FBVyxTQUFYLEVBQXNCLE1BQU1MLFFBQVEsQ0FBQyxDQUFELENBQXBDO0FBQ0E1QixJQUFBQSxPQUFPLENBQUNpQyxFQUFSLENBQVcsUUFBWCxFQUFxQixNQUFNTCxRQUFRLENBQUMsQ0FBRCxDQUFuQztBQUVBLFdBQU9KLE1BQVA7QUFDQTs7QUFFRG5DLEVBQUFBLE9BQU8sQ0FBQzZDLE9BQU8sR0FBRyxJQUFYLEVBQWlCO0FBQ3ZCLFFBQUksQ0FBQzdDLE9BQU8sQ0FBQ3VCLFFBQWIsRUFBdUI7QUFDdEIsYUFBTyxLQUFLUSxLQUFMLENBQVcvQixPQUFPLENBQUNnQyxNQUFuQixDQUFQO0FBQ0E7O0FBRUQsUUFBSSxRQUFDckIsT0FBTyxDQUFDbUMsR0FBUixDQUFZQyxZQUFiLENBQUosRUFBcUM7QUFDcENGLE1BQUFBLE9BQU8sR0FBRy9CLE1BQU0sQ0FBQ0MsUUFBUCxDQUFnQkosT0FBTyxDQUFDbUMsR0FBUixDQUFZQyxZQUE1QixDQUFWO0FBQ0E7O0FBRUQsUUFBSSxPQUFBRixPQUFPLEtBQVUvQixNQUFNLENBQUNrQyxLQUFQLENBQWFILE9BQWIsQ0FBakIsSUFBMENBLE9BQU8sSUFBSSxDQUF6RCxFQUE0RDtBQUMzREEsTUFBQUEsT0FBTyxHQUFHOUMsT0FBTyxDQUFDLElBQUQsQ0FBUCxDQUFja0QsSUFBZCxHQUFxQkMsTUFBL0I7QUFDQTs7QUFFRHZDLElBQUFBLE9BQU8sQ0FBQ3lCLEtBQVIsR0FBaUIsR0FBRXpCLE9BQU8sQ0FBQ1csR0FBUixFQUFjLHFCQUFqQzs7QUFFQSxTQUFLLElBQUk2QixDQUFDLEdBQUcsQ0FBYixFQUFnQkEsQ0FBQyxHQUFHTixPQUFwQixFQUE2Qk0sQ0FBQyxJQUFJLENBQWxDLEVBQXFDO0FBQ3BDbkQsTUFBQUEsT0FBTyxDQUFDb0QsSUFBUjtBQUNBOztBQUVEcEQsSUFBQUEsT0FBTyxDQUFDNEMsRUFBUixDQUFXLE1BQVgsRUFBbUIsQ0FBQ1MsVUFBRCxFQUFhQyxJQUFiLEVBQW1CQyxNQUFuQixLQUE4QjtBQUNoRCxVQUFJQSxNQUFNLEtBQUssU0FBWCxJQUF3QkEsTUFBTSxLQUFLLFFBQXZDLEVBQWlEO0FBQ2hEO0FBQ0E7O0FBRUQ1QixNQUFBQSxPQUFPLENBQUNDLEdBQVIsQ0FBWSxjQUFaLEVBQTRCeUIsVUFBVSxDQUFDZixFQUF2QztBQUNBdEMsTUFBQUEsT0FBTyxDQUFDb0QsSUFBUjtBQUNBLEtBUEQ7QUFRQTs7QUFFRHRCLEVBQUFBLEtBQUssQ0FBQyxHQUFHMEIsSUFBSixFQUFVO0FBQ2QsVUFBTUMsT0FBTyxHQUFHMUQsT0FBTyxDQUFDLGNBQUQsQ0FBUCxDQUF3QjBELE9BQXhDOztBQUNBLFdBQU8sSUFBSUEsT0FBSixDQUFZLElBQVosRUFBa0JELElBQWxCLEVBQXdCMUIsS0FBeEIsRUFBUDtBQUNBOztBQTVIc0IiLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBjaGFsayA9IHJlcXVpcmUoJ2NoYWxrJylcbmNvbnN0IGNsdXN0ZXIgPSByZXF1aXJlKCdjbHVzdGVyJylcbmNvbnN0IGZzID0gcmVxdWlyZSgnZnMnKVxuY29uc3QgcGF0aCA9IHJlcXVpcmUoJ3BhdGgnKVxuXG5leHBvcnQgY2xhc3MgSHR0cFNlcnZlciB7XG5cdGJvb3RzdHJhcHBlciA9IG51bGxcblx0cGlkRmlsZSA9IG51bGxcblxuXHRjb25zdHJ1Y3Rvcihib290c3RyYXBwZXIpIHtcblx0XHR0aGlzLmJvb3RzdHJhcHBlciA9IGJvb3RzdHJhcHBlclxuXHR9XG5cblx0YXN5bmMgc3RhcnQoKSB7XG5cdFx0bGV0IGNsdXN0ZXJlZCA9IGZhbHNlXG5cdFx0bGV0IHdhdGNoRGlycyA9IG51bGxcblxuXHRcdGZvciAoY29uc3QgYXJnIG9mIHByb2Nlc3MuYXJndikge1xuXHRcdFx0aWYgKGFyZyA9PT0gJy0tY2x1c3RlcicpIHtcblx0XHRcdFx0Y2x1c3RlcmVkID0gdHJ1ZVxuXHRcdFx0fSBlbHNlIGlmIChhcmcuc3RhcnRzV2l0aCgnLS1jbHVzdGVyPScpKSB7XG5cdFx0XHRcdGNsdXN0ZXJlZCA9IE51bWJlci5wYXJzZUludChhcmcuc3Vic3RyKDEwKSlcblx0XHRcdH0gZWxzZSBpZiAoYXJnLnN0YXJ0c1dpdGgoJy0td2F0Y2g9JykpIHtcblx0XHRcdFx0d2F0Y2hEaXJzID0gW11cblxuXHRcdFx0XHRmb3IgKGNvbnN0IGRpciBvZiBhcmcuc3Vic3RyKDgpLnNwbGl0KCcsJykpIHtcblx0XHRcdFx0XHRpZiAoZGlyLnN1YnN0cmluZygwLCAxKSA9PT0gJy8nKSB7XG5cdFx0XHRcdFx0XHR3YXRjaERpcnMucHVzaChkaXIpXG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHdhdGNoRGlycy5wdXNoKHBhdGguam9pbihwcm9jZXNzLmN3ZCgpLCBkaXIpKVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmIChhcmcuc3RhcnRzV2l0aCgnLS1waWQ9JykgJiYgY2x1c3Rlci5pc01hc3Rlcikge1xuXHRcdFx0XHR0aGlzLnBpZEZpbGUgPSBhcmcuc3Vic3RyKDYpXG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKCF0aGlzLnBpZEZpbGUuaXNOaWwpIHtcblx0XHRcdC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1zeW5jLG5vLWVtcHR5XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRmcy53cml0ZUZpbGVTeW5jKHRoaXMucGlkRmlsZSwgcHJvY2Vzcy5waWQpXG5cdFx0XHR9IGNhdGNoIChlcnIpIHt9XG5cdFx0fVxuXG5cdFx0aWYgKGNsdXN0ZXJlZCAmJiAhd2F0Y2hEaXJzLmlzTmlsKSB7XG5cdFx0XHRjb25zb2xlLmxvZygnLS13YXRjaCBhbmQgLS1jbHVzdGVyIGNhbiBub3QgYmUgdXNlZCB0b2dldGhlcicpXG5cdFx0XHRwcm9jZXNzLmV4aXQoMSlcblx0XHR9XG5cblx0XHRpZiAoIXdhdGNoRGlycy5pc05pbCkge1xuXHRcdFx0YXdhaXQgdGhpcy53YXRjaCh3YXRjaERpcnMpXG5cdFx0fSBlbHNlIGlmIChjbHVzdGVyZWQgPT09IGZhbHNlKSB7XG5cdFx0XHRhd2FpdCB0aGlzLnNlcnZlKClcblx0XHR9IGVsc2Uge1xuXHRcdFx0YXdhaXQgdGhpcy5jbHVzdGVyKGNsdXN0ZXJlZClcblx0XHR9XG5cdH1cblxuXHRhc3luYyBzZXJ2ZSh3b3JrZXIgPSBudWxsKSB7XG5cdFx0Y29uc3QgYXBwID0gdGhpcy5ib290c3RyYXBwZXIoKVxuXHRcdGNvbnN0IHBvcnQgPSBhcHAucG9ydFxuXG5cdFx0Y29uc3Qgc2VydmVyID0gYXdhaXQgYXBwLnN0YXJ0KHBvcnQsICgpID0+IHtcblx0XHRcdGlmICghd29ya2VyLmlzTmlsKSB7XG5cdFx0XHRcdHByb2Nlc3MudGl0bGUgPSBgJHtwcm9jZXNzLmN3ZCgpfSBbc2VydmVyOiR7cG9ydH1dYFxuXHRcdFx0XHRjb25zb2xlLmxvZyhjaGFsay55ZWxsb3coJ1dvcmtlciAlZCBsaXN0ZW5pbmcgb24gJWQnKSwgd29ya2VyLmlkLCBwb3J0KVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cHJvY2Vzcy50aXRsZSA9IGAke3Byb2Nlc3MuY3dkKCl9IFtjbHVzdGVyXSBbd29ya2VyOiR7cG9ydH1dYFxuXHRcdFx0XHRjb25zb2xlLmxvZyhjaGFsay55ZWxsb3coJ0xpc3RlbmluZyBvbiBwb3J0ICVkJyksIHBvcnQpXG5cdFx0XHR9XG5cdFx0fSlcblxuXHRcdGNvbnN0IHRlYXJkb3duID0gZXhpdENvZGUgPT4ge1xuXHRcdFx0Y29uc3QgZXhpdCA9ICgpID0+IHtcblx0XHRcdFx0aWYgKCF0aGlzLnBpZEZpbGUuaXNOaWwpIHtcblx0XHRcdFx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tc3luYyxuby1lbXB0eVxuXHRcdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0XHRmcy51bmxpbmtTeW5jKHRoaXMucGlkRmlsZSlcblx0XHRcdFx0XHR9IGNhdGNoIChlcnIpIHt9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRwcm9jZXNzLmV4aXQoZXhpdENvZGUpXG5cdFx0XHR9XG5cblx0XHRcdC8vIEF0dGVtcHQgYSBzYWZlIHRlYXJkb3duXG5cdFx0XHRzZXJ2ZXIuY2xvc2UoZXhpdClcblxuXHRcdFx0Ly8gQWZ0ZXIgMTBzLCBraWxsXG5cdFx0XHRzZXRUaW1lb3V0KGV4aXQsIDEwMDAwKVxuXHRcdH1cblxuXHRcdHByb2Nlc3Mub24oJ1NJR1RFUk0nLCAoKSA9PiB0ZWFyZG93bigwKSlcblx0XHRwcm9jZXNzLm9uKCdTSUdJTlQnLCAoKSA9PiB0ZWFyZG93bigwKSlcblxuXHRcdHJldHVybiBzZXJ2ZXJcblx0fVxuXG5cdGNsdXN0ZXIod29ya2VycyA9IG51bGwpIHtcblx0XHRpZiAoIWNsdXN0ZXIuaXNNYXN0ZXIpIHtcblx0XHRcdHJldHVybiB0aGlzLnNlcnZlKGNsdXN0ZXIud29ya2VyKVxuXHRcdH1cblxuXHRcdGlmICghcHJvY2Vzcy5lbnYuTk9ERV9DTFVTVEVSLmlzTmlsKSB7XG5cdFx0XHR3b3JrZXJzID0gTnVtYmVyLnBhcnNlSW50KHByb2Nlc3MuZW52Lk5PREVfQ0xVU1RFUilcblx0XHR9XG5cblx0XHRpZiAod29ya2Vycy5pc05pbCB8fCBOdW1iZXIuaXNOYU4od29ya2VycykgfHwgd29ya2VycyA8PSAwKSB7XG5cdFx0XHR3b3JrZXJzID0gcmVxdWlyZSgnb3MnKS5jcHVzKCkubGVuZ3RoXG5cdFx0fVxuXG5cdFx0cHJvY2Vzcy50aXRsZSA9IGAke3Byb2Nlc3MuY3dkKCl9IFtjbHVzdGVyXSBbbWFzdGVyXWBcblxuXHRcdGZvciAobGV0IGkgPSAwOyBpIDwgd29ya2VyczsgaSArPSAxKSB7XG5cdFx0XHRjbHVzdGVyLmZvcmsoKVxuXHRcdH1cblxuXHRcdGNsdXN0ZXIub24oJ2V4aXQnLCAoZGVhZFdvcmtlciwgY29kZSwgc2lnbmFsKSA9PiB7XG5cdFx0XHRpZiAoc2lnbmFsID09PSAnU0lHVEVSTScgfHwgc2lnbmFsID09PSAnU0lHSU5UJykge1xuXHRcdFx0XHRyZXR1cm5cblx0XHRcdH1cblxuXHRcdFx0Y29uc29sZS5sb2coJ1JlbG9hZGluZyAlcycsIGRlYWRXb3JrZXIuaWQpXG5cdFx0XHRjbHVzdGVyLmZvcmsoKVxuXHRcdH0pXG5cdH1cblxuXHR3YXRjaCguLi5kaXJzKSB7XG5cdFx0Y29uc3QgV2F0Y2hlciA9IHJlcXVpcmUoJy4vV2F0Y2hlci5qcycpLldhdGNoZXJcblx0XHRyZXR1cm4gbmV3IFdhdGNoZXIodGhpcywgZGlycykud2F0Y2goKVxuXHR9XG59XG4iXX0=
;