UNPKG

react-static

Version:

A progressive static site generator for React

404 lines (335 loc) 41 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = runDevServer; exports.reloadClientData = void 0; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); var _webpack = _interopRequireDefault(require("webpack")); var _chalk = _interopRequireDefault(require("chalk")); var _socket = _interopRequireDefault(require("socket.io")); var _webpackDevServer = _interopRequireDefault(require("webpack-dev-server")); var _makeWebpackConfig = _interopRequireDefault(require("./makeWebpackConfig")); var _getRouteData = _interopRequireDefault(require("../getRouteData")); var _plugins = _interopRequireDefault(require("../plugins")); var _utils = require("../../utils"); var _fetchSiteData = _interopRequireDefault(require("../fetchSiteData")); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } var devServer; var latestState; var buildDevRoutes = function buildDevRoutes() {}; var reloadClientData = function reloadClientData() { if (reloadClientData.current) { reloadClientData.current(); } }; // Starts the development server exports.reloadClientData = reloadClientData; function runDevServer(_x) { return _runDevServer.apply(this, arguments); } function _runDevServer() { _runDevServer = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(state) { return _regenerator["default"].wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: if (!devServer) { _context.next = 7; break; } _context.next = 3; return buildDevRoutes(state); case 3: _context.next = 5; return reloadClientData(); case 5: _context.next = 10; break; case 7: _context.next = 9; return runExpressServer(state); case 9: state = _context.sent; case 10: return _context.abrupt("return", state); case 11: case "end": return _context.stop(); } } }, _callee); })); return _runDevServer.apply(this, arguments); } function runExpressServer(_x2) { return _runExpressServer.apply(this, arguments); } function _runExpressServer() { _runExpressServer = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee6(state) { var intendedPort, port, defaultMessagePort, messagePort, messageHost, devConfig, devCompiler, devServerConfig, first, startedAt, skipLog, socket; return _regenerator["default"].wrap(function _callee6$(_context6) { while (1) { switch (_context6.prev = _context6.next) { case 0: // Default to localhost:3000, or use a custom combo if defined in static.config.js // or environment variables intendedPort = Number(state.config.devServer.port); _context6.next = 3; return (0, _utils.findAvailablePort)(intendedPort); case 3: port = _context6.sent; defaultMessagePort = 4000; if (process.env.REACT_STATIC_MESSAGE_SOCKET_PORT) { defaultMessagePort = process.env.REACT_STATIC_MESSAGE_SOCKET_PORT; } // Find an available port for messages, as long as it's not the devServer port _context6.next = 8; return (0, _utils.findAvailablePort)(defaultMessagePort, [port]); case 8: messagePort = _context6.sent; messageHost = process.env.REACT_STATIC_MESSAGE_SOCKET_HOST || 'http://localhost'; if (intendedPort !== port) { console.log(_chalk["default"].red("Warning! Port ".concat(intendedPort, " is not available. Using port ").concat(_chalk["default"].green(port), " instead!"))); } state = _objectSpread(_objectSpread({}, state), {}, { config: _objectSpread(_objectSpread({}, state.config), {}, { devServer: _objectSpread(_objectSpread({}, state.config.devServer), {}, { port: port }) }) }); devConfig = (0, _makeWebpackConfig["default"])(state); devCompiler = (0, _webpack["default"])(devConfig); devServerConfig = _objectSpread(_objectSpread({ contentBase: [state.config.paths.PUBLIC, state.config.paths.DIST], publicPath: '/', historyApiFallback: true, compress: false, clientLogLevel: 'warning', overlay: true, stats: 'errors-only', noInfo: true }, state.config.devServer), {}, { hotOnly: true, proxy: _objectSpread({ '/socket.io': { target: "".concat(messageHost, ":").concat(messagePort), ws: true } }, state.config.devServer ? state.config.devServer.proxy || {} : {}), watchOptions: _objectSpread(_objectSpread({}, state.config.devServer ? state.config.devServer.watchOptions || {} : {}), {}, { ignored: [/node_modules/].concat((0, _toConsumableArray2["default"])((state.config.devServer.watchOptions || {}).ignored || [])) }), before: function before(app) { // Since routes may change during dev, this function can rebuild all of the config // routes. It also references the original config when possible, to make sure it // uses any up to date getData callback generated from new or replacement routes. buildDevRoutes = /*#__PURE__*/function () { var _ref = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee4(newState) { return _regenerator["default"].wrap(function _callee4$(_context4) { while (1) { switch (_context4.prev = _context4.next) { case 0: _context4.next = 2; return (0, _fetchSiteData["default"])(newState); case 2: latestState = _context4.sent; app.get('/__react-static__/siteData', /*#__PURE__*/function () { var _ref2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(req, res, next) { return _regenerator["default"].wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: try { res.send(latestState.siteData); } catch (err) { res.status(500); res.send(err); next(err); } case 1: case "end": return _context2.stop(); } } }, _callee2); })); return function (_x4, _x5, _x6) { return _ref2.apply(this, arguments); }; }()); // Serve each routes data latestState.routes.forEach(function (_ref3) { var routePath = _ref3.path; app.get("/__react-static__/routeInfo/".concat(encodeURI(routePath === '/' ? '' : routePath)), /*#__PURE__*/function () { var _ref4 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3(req, res, next) { var route, err; return _regenerator["default"].wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: // Make sure we have the most up to date route from the config, not // an out of date object. route = latestState.routes.find(function (d) { return d.path === routePath; }); _context3.prev = 1; if (route) { _context3.next = 6; break; } err = new Error("Route could not be found for: ".concat(routePath, "\n\nIf you removed this route, disregard this error.\nIf this is a dynamic route, consider adding it to the prefetchExcludes list:\n\n addPrefetchExcludes(['").concat(routePath, "'])\n")); delete err.stack; throw err; case 6: _context3.next = 8; return (0, _getRouteData["default"])(route, latestState); case 8: route = _context3.sent; _context3.next = 11; return _plugins["default"].routeInfo(route, state); case 11: route = _context3.sent; // Don't use any hashProp, just pass all the data in dev res.json(route); _context3.next = 19; break; case 15: _context3.prev = 15; _context3.t0 = _context3["catch"](1); res.status(404); next(_context3.t0); case 19: case "end": return _context3.stop(); } } }, _callee3, null, [[1, 15]]); })); return function (_x7, _x8, _x9) { return _ref4.apply(this, arguments); }; }()); }); return _context4.abrupt("return", new Promise(function (resolve) { return setTimeout(resolve, 1); })); case 6: case "end": return _context4.stop(); } } }, _callee4); })); return function buildDevRoutes(_x3) { return _ref.apply(this, arguments); }; }(); buildDevRoutes(state); if (state.config.devServer && state.config.devServer.before) { state.config.devServer.before(app); } return app; } }); first = true; startedAt = Date.now(); skipLog = false; console.log('Bundling Application...'); (0, _utils.time)(_chalk["default"].green("[\u2713] Application Bundled")); devCompiler.hooks.invalid.tap({ name: 'React-Static' }, function (file, changed) { // If a file is changed within the first two seconds of // the server starting, we don't bark about it. Less // noise is better! skipLog = changed - startedAt < 2000; if (!skipLog) { console.log('File changed:', file.replace(state.config.paths.ROOT, '')); console.log('Updating bundle...'); (0, _utils.time)(_chalk["default"].green("[\u2713] Bundle Updated")); } }); devCompiler.hooks.done.tap({ name: 'React-Static' }, function (stats) { var messages = stats.toJson({}, true); var isSuccessful = !messages.errors.length; var hasWarnings = messages.warnings.length; if (isSuccessful && !skipLog) { if (first) { // Print out any dev compiler warnings if (hasWarnings) { console.log(_chalk["default"].yellowBright("\n[!] There were ".concat(messages.warnings.length, " warnings during compilation\n"))); messages.warnings.forEach(function (message, index) { console.warn("[warning ".concat(index, "]: ").concat(message, "\n")); }); } (0, _utils.timeEnd)(_chalk["default"].green("[\u2713] Application Bundled")); var protocol = state.config.devServer.https ? 'https' : 'http'; console.log("".concat(_chalk["default"].green("[\u2713] App serving at"), " ").concat(_chalk["default"].blue("".concat(protocol, "://").concat(state.config.devServer.host, ":").concat(state.config.devServer.port)))); } else { (0, _utils.timeEnd)(_chalk["default"].green("[\u2713] Bundle Updated")); } } else if (!skipLog) { console.log(_chalk["default"].redBright("[\u274C] Application bundling failed")); console.error(_chalk["default"].redBright(messages.errors.join('\n'))); console.warn(_chalk["default"].yellowBright(messages.warnings.join('\n'))); } first = false; }); // Start the webpack dev server devServer = new _webpackDevServer["default"](devCompiler, devServerConfig); // Start the messages socket socket = (0, _socket["default"])(); reloadClientData.current = /*#__PURE__*/(0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee5() { return _regenerator["default"].wrap(function _callee5$(_context5) { while (1) { switch (_context5.prev = _context5.next) { case 0: _context5.next = 2; return (0, _fetchSiteData["default"])(latestState); case 2: latestState = _context5.sent; socket.emit('message', { type: 'reloadClientData' }); case 4: case "end": return _context5.stop(); } } }, _callee5); })); _context6.next = 27; return new Promise(function (resolve, reject) { devServer.listen(port, null, function (err) { if (err) { console.error("Listening on ".concat(port, " failed: ").concat(err)); return reject(err); } resolve(); }); }); case 27: // Make sure we start listening on the message port after the dev server. // We do this mostly to appease codesandbox.io, since they autobind to the first // port that opens up for their preview window. socket.listen(messagePort); console.log('Running plugins...'); _context6.next = 31; return _plugins["default"].afterDevServerStart(state); case 31: state = _context6.sent; return _context6.abrupt("return", state); case 33: case "end": return _context6.stop(); } } }, _callee6); })); return _runExpressServer.apply(this, arguments); } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9zdGF0aWMvd2VicGFjay9ydW5EZXZTZXJ2ZXIuanMiXSwibmFtZXMiOlsiZGV2U2VydmVyIiwibGF0ZXN0U3RhdGUiLCJidWlsZERldlJvdXRlcyIsInJlbG9hZENsaWVudERhdGEiLCJjdXJyZW50IiwicnVuRGV2U2VydmVyIiwic3RhdGUiLCJydW5FeHByZXNzU2VydmVyIiwiaW50ZW5kZWRQb3J0IiwiTnVtYmVyIiwiY29uZmlnIiwicG9ydCIsImRlZmF1bHRNZXNzYWdlUG9ydCIsInByb2Nlc3MiLCJlbnYiLCJSRUFDVF9TVEFUSUNfTUVTU0FHRV9TT0NLRVRfUE9SVCIsIm1lc3NhZ2VQb3J0IiwibWVzc2FnZUhvc3QiLCJSRUFDVF9TVEFUSUNfTUVTU0FHRV9TT0NLRVRfSE9TVCIsImNvbnNvbGUiLCJsb2ciLCJjaGFsayIsInJlZCIsImdyZWVuIiwiZGV2Q29uZmlnIiwiZGV2Q29tcGlsZXIiLCJkZXZTZXJ2ZXJDb25maWciLCJjb250ZW50QmFzZSIsInBhdGhzIiwiUFVCTElDIiwiRElTVCIsInB1YmxpY1BhdGgiLCJoaXN0b3J5QXBpRmFsbGJhY2siLCJjb21wcmVzcyIsImNsaWVudExvZ0xldmVsIiwib3ZlcmxheSIsInN0YXRzIiwibm9JbmZvIiwiaG90T25seSIsInByb3h5IiwidGFyZ2V0Iiwid3MiLCJ3YXRjaE9wdGlvbnMiLCJpZ25vcmVkIiwiYmVmb3JlIiwiYXBwIiwibmV3U3RhdGUiLCJnZXQiLCJyZXEiLCJyZXMiLCJuZXh0Iiwic2VuZCIsInNpdGVEYXRhIiwiZXJyIiwic3RhdHVzIiwicm91dGVzIiwiZm9yRWFjaCIsInJvdXRlUGF0aCIsInBhdGgiLCJlbmNvZGVVUkkiLCJyb3V0ZSIsImZpbmQiLCJkIiwiRXJyb3IiLCJzdGFjayIsInBsdWdpbnMiLCJyb3V0ZUluZm8iLCJqc29uIiwiUHJvbWlzZSIsInJlc29sdmUiLCJzZXRUaW1lb3V0IiwiZmlyc3QiLCJzdGFydGVkQXQiLCJEYXRlIiwibm93Iiwic2tpcExvZyIsImhvb2tzIiwiaW52YWxpZCIsInRhcCIsIm5hbWUiLCJmaWxlIiwiY2hhbmdlZCIsInJlcGxhY2UiLCJST09UIiwiZG9uZSIsIm1lc3NhZ2VzIiwidG9Kc29uIiwiaXNTdWNjZXNzZnVsIiwiZXJyb3JzIiwibGVuZ3RoIiwiaGFzV2FybmluZ3MiLCJ3YXJuaW5ncyIsInllbGxvd0JyaWdodCIsIm1lc3NhZ2UiLCJpbmRleCIsIndhcm4iLCJwcm90b2NvbCIsImh0dHBzIiwiYmx1ZSIsImhvc3QiLCJyZWRCcmlnaHQiLCJlcnJvciIsImpvaW4iLCJXZWJwYWNrRGV2U2VydmVyIiwic29ja2V0IiwiZW1pdCIsInR5cGUiLCJyZWplY3QiLCJsaXN0ZW4iLCJhZnRlckRldlNlcnZlclN0YXJ0Il0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFFQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7Ozs7O0FBRUEsSUFBSUEsU0FBSjtBQUNBLElBQUlDLFdBQUo7O0FBQ0EsSUFBSUMsY0FBYyxHQUFHLDBCQUFNLENBQUUsQ0FBN0I7O0FBRU8sSUFBTUMsZ0JBQWdCLEdBQUcsU0FBbkJBLGdCQUFtQixHQUFNO0FBQ3BDLE1BQUlBLGdCQUFnQixDQUFDQyxPQUFyQixFQUE4QjtBQUM1QkQsSUFBQUEsZ0JBQWdCLENBQUNDLE9BQWpCO0FBQ0Q7QUFDRixDQUpNLEMsQ0FNUDs7Ozs7U0FDOEJDLFk7Ozs7O2dHQUFmLGlCQUE0QkMsS0FBNUI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGlCQU9UTixTQVBTO0FBQUE7QUFBQTtBQUFBOztBQUFBO0FBQUEsbUJBUUxFLGNBQWMsQ0FBQ0ksS0FBRCxDQVJUOztBQUFBO0FBQUE7QUFBQSxtQkFTTEgsZ0JBQWdCLEVBVFg7O0FBQUE7QUFBQTtBQUFBOztBQUFBO0FBQUE7QUFBQSxtQkFXR0ksZ0JBQWdCLENBQUNELEtBQUQsQ0FYbkI7O0FBQUE7QUFXWEEsWUFBQUEsS0FYVzs7QUFBQTtBQUFBLDZDQWNO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akIsRUFBdUIsSUFBdkIsRUFBNkIsVUFBQTBDLEdBQUcsRUFBSTtBQUNsQyxvQkFBSUEsR0FBSixFQUFTO0FBQ1BsQyxrQkFBQUEsT0FBTyxDQUFDa0YsS0FBUix3QkFBOEIxRixJQUE5QixzQkFBOEMwQyxHQUE5QztBQUNBLHlCQUFPc0QsTUFBTSxDQUFDdEQsR0FBRCxDQUFiO0FBQ0Q7O0FBQ0RnQixnQkFBQUEsT0FBTztBQUNSLGVBTkQ7QUFPRCxhQVJLLENBdE5SOztBQUFBO0FBZ09FO0FBQ0E7QUFDQTtBQUNBbUMsWUFBQUEsTUFBTSxDQUFDSSxNQUFQLENBQWM1RixXQUFkO0FBRUFHLFlBQUFBLE9BQU8sQ0FBQ0MsR0FBUixDQUFZLG9CQUFaO0FBck9GO0FBQUEsbUJBc09nQjZDLG9CQUFRNEMsbUJBQVIsQ0FBNEJ2RyxLQUE1QixDQXRPaEI7O0FBQUE7QUFzT0VBLFlBQUFBLEtBdE9GO0FBQUEsOENBd09TQSxLQXhPVDs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxHIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgaW1wb3J0L25vLWR5bmFtaWMtcmVxdWlyZSwgcmVhY3Qvbm8tZGFuZ2VyLCBpbXBvcnQvbm8tbXV0YWJsZS1leHBvcnRzICovXG5pbXBvcnQgd2VicGFjayBmcm9tICd3ZWJwYWNrJ1xuaW1wb3J0IGNoYWxrIGZyb20gJ2NoYWxrJ1xuaW1wb3J0IGlvIGZyb20gJ3NvY2tldC5pbydcbmltcG9ydCBXZWJwYWNrRGV2U2VydmVyIGZyb20gJ3dlYnBhY2stZGV2LXNlcnZlcidcbi8vXG5pbXBvcnQgbWFrZVdlYnBhY2tDb25maWcgZnJvbSAnLi9tYWtlV2VicGFja0NvbmZpZydcbmltcG9ydCBnZXRSb3V0ZURhdGEgZnJvbSAnLi4vZ2V0Um91dGVEYXRhJ1xuaW1wb3J0IHBsdWdpbnMgZnJvbSAnLi4vcGx1Z2lucydcbmltcG9ydCB7IGZpbmRBdmFpbGFibGVQb3J0LCB0aW1lLCB0aW1lRW5kIH0gZnJvbSAnLi4vLi4vdXRpbHMnXG5pbXBvcnQgZmV0Y2hTaXRlRGF0YSBmcm9tICcuLi9mZXRjaFNpdGVEYXRhJ1xuXG5sZXQgZGV2U2VydmVyXG5sZXQgbGF0ZXN0U3RhdGVcbmxldCBidWlsZERldlJvdXRlcyA9ICgpID0+IHt9XG5cbmV4cG9ydCBjb25zdCByZWxvYWRDbGllbnREYXRhID0gKCkgPT4ge1xuICBpZiAocmVsb2FkQ2xpZW50RGF0YS5jdXJyZW50KSB7XG4gICAgcmVsb2FkQ2xpZW50RGF0YS5jdXJyZW50KClcbiAgfVxufVxuXG4vLyBTdGFydHMgdGhlIGRldmVsb3BtZW50IHNlcnZlclxuZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gcnVuRGV2U2VydmVyKHN0YXRlKSB7XG4gIC8vIFRPRE8gY2hlY2sgY29uZmlnLmRldlNlcnZlciBmb3IgY2hhbmdlcyBhbmQgbm90aWZ5IHVzZXJcbiAgLy8gaWYgdGhlIHNlcnZlciBuZWVkcyB0byBiZSByZXN0YXJ0ZWQgZm9yIGNoYW5nZXMgdG8gdGFrZVxuICAvLyBlZmZlY3QuXG5cbiAgLy8gSWYgdGhlIHNlcnZlciBpcyBhbHJlYWR5IHJ1bm5pbmcsIHRyaWdnZXIgYSByZWZyZXNoIHRvIHRoZSBjbGllbnRcblxuICBpZiAoZGV2U2VydmVyKSB7XG4gICAgYXdhaXQgYnVpbGREZXZSb3V0ZXMoc3RhdGUpXG4gICAgYXdhaXQgcmVsb2FkQ2xpZW50RGF0YSgpXG4gIH0gZWxzZSB7XG4gICAgc3RhdGUgPSBhd2FpdCBydW5FeHByZXNzU2VydmVyKHN0YXRlKVxuICB9XG5cbiAgcmV0dXJuIHN0YXRlXG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJ1bkV4cHJlc3NTZXJ2ZXIoc3RhdGUpIHtcbiAgLy8gRGVmYXVsdCB0byBsb2NhbGhvc3Q6MzAwMCwgb3IgdXNlIGEgY3VzdG9tIGNvbWJvIGlmIGRlZmluZWQgaW4gc3RhdGljLmNvbmZpZy5qc1xuICAvLyBvciBlbnZpcm9ubWVudCB2YXJpYWJsZXNcbiAgY29uc3QgaW50ZW5kZWRQb3J0ID0gTnVtYmVyKHN0YXRlLmNvbmZpZy5kZXZTZXJ2ZXIucG9ydClcbiAgY29uc3QgcG9ydCA9IGF3YWl0IGZpbmRBdmFpbGFibGVQb3J0KGludGVuZGVkUG9ydClcblxuICBsZXQgZGVmYXVsdE1lc3NhZ2VQb3J0ID0gNDAwMFxuXG4gIGlmIChwcm9jZXNzLmVudi5SRUFDVF9TVEFUSUNfTUVTU0FHRV9TT0NLRVRfUE9SVCkge1xuICAgIGRlZmF1bHRNZXNzYWdlUG9ydCA9IHByb2Nlc3MuZW52LlJFQUNUX1NUQVRJQ19NRVNTQUdFX1NPQ0tFVF9QT1JUXG4gIH1cbiAgLy8gRmluZCBhbiBhdmFpbGFibGUgcG9ydCBmb3IgbWVzc2FnZXMsIGFzIGxvbmcgYXMgaXQncyBub3QgdGhlIGRldlNlcnZlciBwb3J0XG4gIGNvbnN0IG1lc3NhZ2VQb3J0ID0gYXdhaXQgZmluZEF2YWlsYWJsZVBvcnQoZGVmYXVsdE1lc3NhZ2VQb3J0LCBbcG9ydF0pXG5cbiAgY29uc3QgbWVzc2FnZUhvc3QgPVxuICAgIHByb2Nlc3MuZW52LlJFQUNUX1NUQVRJQ19NRVNTQUdFX1NPQ0tFVF9IT1NUIHx8ICdodHRwOi8vbG9jYWxob3N0J1xuXG4gIGlmIChpbnRlbmRlZFBvcnQgIT09IHBvcnQpIHtcbiAgICBjb25zb2xlLmxvZyhcbiAgICAgIGNoYWxrLnJlZChcbiAgICAgICAgYFdhcm5pbmchIFBvcnQgJHtpbnRlbmRlZFBvcnR9IGlzIG5vdCBhdmFpbGFibGUuIFVzaW5nIHBvcnQgJHtjaGFsay5ncmVlbihcbiAgICAgICAgICBwb3J0XG4gICAgICAgICl9IGluc3RlYWQhYFxuICAgICAgKVxuICAgIClcbiAgfVxuXG4gIHN0YXRlID0ge1xuICAgIC4uLnN0YXRlLFxuICAgIGNvbmZpZzoge1xuICAgICAgLi4uc3RhdGUuY29uZmlnLFxuICAgICAgZGV2U2VydmVyOiB7XG4gICAgICAgIC4uLnN0YXRlLmNvbmZpZy5kZXZTZXJ2ZXIsXG4gICAgICAgIHBvcnQsXG4gICAgICB9LFxuICAgIH0sXG4gIH1cblxuICBjb25zdCBkZXZDb25maWcgPSBtYWtlV2VicGFja0NvbmZpZyhzdGF0ZSlcbiAgY29uc3QgZGV2Q29tcGlsZXIgPSB3ZWJwYWNrKGRldkNvbmZpZylcblxuICBjb25zdCBkZXZTZXJ2ZXJDb25maWcgPSB7XG4gICAgY29udGVudEJhc2U6IFtzdGF0ZS5jb25maWcucGF0aHMuUFVCTElDLCBzdGF0ZS5jb25maWcucGF0aHMuRElTVF0sXG4gICAgcHVibGljUGF0aDogJy8nLFxuICAgIGhpc3RvcnlBcGlGYWxsYmFjazogdHJ1ZSxcbiAgICBjb21wcmVzczogZmFsc2UsXG4gICAgY2xpZW50TG9nTGV2ZWw6ICd3YXJuaW5nJyxcbiAgICBvdmVybGF5OiB0cnVlLFxuICAgIHN0YXRzOiAnZXJyb3JzLW9ubHknLFxuICAgIG5vSW5mbzogdHJ1ZSxcbiAgICAuLi5zdGF0ZS5jb25maWcuZGV2U2VydmVyLFxuICAgIGhvdE9ubHk6IHRydWUsXG4gICAgcHJveHk6IHtcbiAgICAgICcvc29ja2V0LmlvJzoge1xuICAgICAgICB0YXJnZXQ6IGAke21lc3NhZ2VIb3N0fToke21lc3NhZ2VQb3J0fWAsXG4gICAgICAgIHdzOiB0cnVlLFxuICAgICAgfSxcbiAgICAgIC4uLihzdGF0ZS5jb25maWcuZGV2U2VydmVyID8gc3RhdGUuY29uZmlnLmRldlNlcnZlci5wcm94eSB8fCB7fSA6IHt9KSxcbiAgICB9LFxuICAgIHdhdGNoT3B0aW9uczoge1xuICAgICAgLi4uKHN0YXRlLmNvbmZpZy5kZXZTZXJ2ZXJcbiAgICAgICAgPyBzdGF0ZS5jb25maWcuZGV2U2VydmVyLndhdGNoT3B0aW9ucyB8fCB7fVxuICAgICAgICA6IHt9KSxcbiAgICAgIGlnbm9yZWQ6IFtcbiAgICAgICAgL25vZGVfbW9kdWxlcy8sXG5cbiAgICAgICAgLi4uKChzdGF0ZS5jb25maWcuZGV2U2VydmVyLndhdGNoT3B0aW9ucyB8fCB7fSkuaWdub3JlZCB8fCBbXSksXG4gICAgICBdLFxuICAgIH0sXG4gICAgYmVmb3JlOiBhcHAgPT4ge1xuICAgICAgLy8gU2luY2Ugcm91dGVzIG1heSBjaGFuZ2UgZHVyaW5nIGRldiwgdGhpcyBmdW5jdGlvbiBjYW4gcmVidWlsZCBhbGwgb2YgdGhlIGNvbmZpZ1xuICAgICAgLy8gcm91dGVzLiBJdCBhbHNvIHJlZmVyZW5jZXMgdGhlIG9yaWdpbmFsIGNvbmZpZyB3aGVuIHBvc3NpYmxlLCB0byBtYWtlIHN1cmUgaXRcbiAgICAgIC8vIHVzZXMgYW55IHVwIHRvIGRhdGUgZ2V0RGF0YSBjYWxsYmFjayBnZW5lcmF0ZWQgZnJvbSBuZXcgb3IgcmVwbGFjZW1lbnQgcm91dGVzLlxuICAgICAgYnVpbGREZXZSb3V0ZXMgPSBhc3luYyBuZXdTdGF0ZSA9PiB7XG4gICAgICAgIGxhdGVzdFN0YXRlID0gYXdhaXQgZmV0Y2hTaXRlRGF0YShuZXdTdGF0ZSlcblxuICAgICAgICBhcHAuZ2V0KCcvX19yZWFjdC1zdGF0aWNfXy9zaXRlRGF0YScsIGFzeW5jIChyZXEsIHJlcywgbmV4dCkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICByZXMuc2VuZChsYXRlc3RTdGF0ZS5zaXRlRGF0YSlcbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIHJlcy5zdGF0dXMoNTAwKVxuICAgICAgICAgICAgcmVzLnNlbmQoZXJyKVxuICAgICAgICAgICAgbmV4dChlcnIpXG4gICAgICAgICAgfVxuICAgICAgICB9KVxuXG4gICAgICAgIC8vIFNlcnZlIGVhY2ggcm91dGVzIGRhdGFcbiAgICAgICAgbGF0ZXN0U3RhdGUucm91dGVzLmZvckVhY2goKHsgcGF0aDogcm91dGVQYXRoIH0pID0+IHtcbiAgICAgICAgICBhcHAuZ2V0KFxuICAgICAgICAgICAgYC9fX3JlYWN0LXN0YXRpY19fL3JvdXRlSW5mby8ke2VuY29kZVVSSShcbiAgICAgICAgICAgICAgcm91dGVQYXRoID09PSAnLycgPyAnJyA6IHJvdXRlUGF0aFxuICAgICAgICAgICAgKX1gLFxuICAgICAgICAgICAgYXN5bmMgKHJlcSwgcmVzLCBuZXh0KSA9PiB7XG4gICAgICAgICAgICAgIC8vIE1ha2Ugc3VyZSB3ZSBoYXZlIHRoZSBtb3N0IHVwIHRvIGRhdGUgcm91dGUgZnJvbSB0aGUgY29uZmlnLCBub3RcbiAgICAgICAgICAgICAgLy8gYW4gb3V0IG9mIGRhdGUgb2JqZWN0LlxuICAgICAgICAgICAgICBsZXQgcm91dGUgPSBsYXRlc3RTdGF0ZS5yb3V0ZXMuZmluZChkID0+IGQucGF0aCA9PT0gcm91dGVQYXRoKVxuICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICghcm91dGUpIHtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGVyciA9IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgYFJvdXRlIGNvdWxkIG5vdCBiZSBmb3VuZCBmb3I6ICR7cm91dGVQYXRofVxuXG5JZiB5b3UgcmVtb3ZlZCB0aGlzIHJvdXRlLCBkaXNyZWdhcmQgdGhpcyBlcnJvci5cbklmIHRoaXMgaXMgYSBkeW5hbWljIHJvdXRlLCBjb25zaWRlciBhZGRpbmcgaXQgdG8gdGhlIHByZWZldGNoRXhjbHVkZXMgbGlzdDpcblxuICBhZGRQcmVmZXRjaEV4Y2x1ZGVzKFsnJHtyb3V0ZVBhdGh9J10pXG5gXG4gICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICBkZWxldGUgZXJyLnN0YWNrXG4gICAgICAgICAgICAgICAgICB0aHJvdyBlcnJcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByb3V0ZSA9IGF3YWl0IGdldFJvdXRlRGF0YShyb3V0ZSwgbGF0ZXN0U3RhdGUpXG4gICAgICAgICAgICAgICAgcm91dGUgPSBhd2FpdCBwbHVnaW5zLnJvdXRlSW5mbyhyb3V0ZSwgc3RhdGUpXG5cbiAgICAgICAgICAgICAgICAvLyBEb24ndCB1c2UgYW55IGhhc2hQcm9wLCBqdXN0IHBhc3MgYWxsIHRoZSBkYXRhIGluIGRldlxuICAgICAgICAgICAgICAgIHJlcy5qc29uKHJvdXRlKVxuICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICByZXMuc3RhdHVzKDQwNClcbiAgICAgICAgICAgICAgICBuZXh0KGVycilcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIClcbiAgICAgICAgfSlcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxKSlcbiAgICAgIH1cblxuICAgICAgYnVpbGREZXZSb3V0ZXMoc3RhdGUpXG5cbiAgICAgIGlmIChzdGF0ZS5jb25maWcuZGV2U2VydmVyICYmIHN0YXRlLmNvbmZpZy5kZXZTZXJ2ZXIuYmVmb3JlKSB7XG4gICAgICAgIHN0YXRlLmNvbmZpZy5kZXZTZXJ2ZXIuYmVmb3JlKGFwcClcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGFwcFxuICAgIH0sXG4gIH1cblxuICBsZXQgZmlyc3QgPSB0cnVlXG4gIGNvbnN0IHN0YXJ0ZWRBdCA9IERhdGUubm93KClcbiAgbGV0IHNraXBMb2cgPSBmYWxzZVxuXG4gIGNvbnNvbGUubG9nKCdCdW5kbGluZyBBcHBsaWNhdGlvbi4uLicpXG4gIHRpbWUoY2hhbGsuZ3JlZW4oJ1tcXHUyNzEzXSBBcHBsaWNhdGlvbiBCdW5kbGVkJykpXG5cbiAgZGV2Q29tcGlsZXIuaG9va3MuaW52YWxpZC50YXAoXG4gICAge1xuICAgICAgbmFtZTogJ1JlYWN0LVN0YXRpYycsXG4gICAgfSxcbiAgICAoZmlsZSwgY2hhbmdlZCkgPT4ge1xuICAgICAgLy8gSWYgYSBmaWxlIGlzIGNoYW5nZWQgd2l0aGluIHRoZSBmaXJzdCB0d28gc2Vjb25kcyBvZlxuICAgICAgLy8gdGhlIHNlcnZlciBzdGFydGluZywgd2UgZG9uJ3QgYmFyayBhYm91dCBpdC4gTGVzc1xuICAgICAgLy8gbm9pc2UgaXMgYmV0dGVyIVxuICAgICAgc2tpcExvZyA9IGNoYW5nZWQgLSBzdGFydGVkQXQgPCAyMDAwXG4gICAgICBpZiAoIXNraXBMb2cpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ0ZpbGUgY2hhbmdlZDonLCBmaWxlLnJlcGxhY2Uoc3RhdGUuY29uZmlnLnBhdGhzLlJPT1QsICcnKSlcbiAgICAgICAgY29uc29sZS5sb2coJ1VwZGF0aW5nIGJ1bmRsZS4uLicpXG4gICAgICAgIHRpbWUoY2hhbGsuZ3JlZW4oJ1tcXHUyNzEzXSBCdW5kbGUgVXBkYXRlZCcpKVxuICAgICAgfVxuICAgIH1cbiAgKVxuXG4gIGRldkNvbXBpbGVyLmhvb2tzLmRvbmUudGFwKFxuICAgIHtcbiAgICAgIG5hbWU6ICdSZWFjdC1TdGF0aWMnLFxuICAgIH0sXG4gICAgc3RhdHMgPT4ge1xuICAgICAgY29uc3QgbWVzc2FnZXMgPSBzdGF0cy50b0pzb24oe30sIHRydWUpXG4gICAgICBjb25zdCBpc1N1Y2Nlc3NmdWwgPSAhbWVzc2FnZXMuZXJyb3JzLmxlbmd0aFxuICAgICAgY29uc3QgaGFzV2FybmluZ3MgPSBtZXNzYWdlcy53YXJuaW5ncy5sZW5ndGhcblxuICAgICAgaWYgKGlzU3VjY2Vzc2Z1bCAmJiAhc2tpcExvZykge1xuICAgICAgICBpZiAoZmlyc3QpIHtcbiAgICAgICAgICAvLyBQcmludCBvdXQgYW55IGRldiBjb21waWxlciB3YXJuaW5nc1xuICAgICAgICAgIGlmIChoYXNXYXJuaW5ncykge1xuICAgICAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgICAgIGNoYWxrLnllbGxvd0JyaWdodChcbiAgICAgICAgICAgICAgICBgXFxuW1xcdTAwMjFdIFRoZXJlIHdlcmUgJHttZXNzYWdlcy53YXJuaW5ncy5sZW5ndGh9IHdhcm5pbmdzIGR1cmluZyBjb21waWxhdGlvblxcbmBcbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgbWVzc2FnZXMud2FybmluZ3MuZm9yRWFjaCgobWVzc2FnZSwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBbd2FybmluZyAke2luZGV4fV06ICR7bWVzc2FnZX1cXG5gKVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB0aW1lRW5kKGNoYWxrLmdyZWVuKCdbXFx1MjcxM10gQXBwbGljYXRpb24gQnVuZGxlZCcpKVxuICAgICAgICAgIGNvbnN0IHByb3RvY29sID0gc3RhdGUuY29uZmlnLmRldlNlcnZlci5odHRwcyA/ICdodHRwcycgOiAnaHR0cCdcbiAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgIGAke2NoYWxrLmdyZWVuKCdbXFx1MjcxM10gQXBwIHNlcnZpbmcgYXQnKX0gJHtjaGFsay5ibHVlKFxuICAgICAgICAgICAgICBgJHtwcm90b2NvbH06Ly8ke3N0YXRlLmNvbmZpZy5kZXZTZXJ2ZXIuaG9zdH06JHtzdGF0ZS5jb25maWcuZGV2U2VydmVyLnBvcnR9YFxuICAgICAgICAgICAgKX1gXG4gICAgICAgICAgKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRpbWVFbmQoY2hhbGsuZ3JlZW4oJ1tcXHUyNzEzXSBCdW5kbGUgVXBkYXRlZCcpKVxuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKCFza2lwTG9nKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGNoYWxrLnJlZEJyaWdodCgnW1xcdTI3NENdIEFwcGxpY2F0aW9uIGJ1bmRsaW5nIGZhaWxlZCcpKVxuICAgICAgICBjb25zb2xlLmVycm9yKGNoYWxrLnJlZEJyaWdodChtZXNzYWdlcy5lcnJvcnMuam9pbignXFxuJykpKVxuICAgICAgICBjb25zb2xlLndhcm4oY2hhbGsueWVsbG93QnJpZ2h0KG1lc3NhZ2VzLndhcm5pbmdzLmpvaW4oJ1xcbicpKSlcbiAgICAgIH1cblxuICAgICAgZmlyc3QgPSBmYWxzZVxuICAgIH1cbiAgKVxuXG4gIC8vIFN0YXJ0IHRoZSB3ZWJwYWNrIGRldiBzZXJ2ZXJcbiAgZGV2U2VydmVyID0gbmV3IFdlYnBhY2tEZXZTZXJ2ZXIoZGV2Q29tcGlsZXIsIGRldlNlcnZlckNvbmZpZylcblxuICAvLyBTdGFydCB0aGUgbWVzc2FnZXMgc29ja2V0XG4gIGNvbnN0IHNvY2tldCA9IGlvKClcblxuICByZWxvYWRDbGllbnREYXRhLmN1cnJlbnQgPSBhc3luYyAoKSA9PiB7XG4gICAgbGF0ZXN0U3RhdGUgPSBhd2FpdCBmZXRjaFNpdGVEYXRhKGxhdGVzdFN0YXRlKVxuICAgIHNvY2tldC5lbWl0KCdtZXNzYWdlJywgeyB0eXBlOiAncmVsb2FkQ2xpZW50RGF0YScgfSlcbiAgfVxuXG4gIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBkZXZTZXJ2ZXIubGlzdGVuKHBvcnQsIG51bGwsIGVyciA9PiB7XG4gICAgICBpZiAoZXJyKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYExpc3RlbmluZyBvbiAke3BvcnR9IGZhaWxlZDogJHtlcnJ9YClcbiAgICAgICAgcmV0dXJuIHJlamVjdChlcnIpXG4gICAgICB9XG4gICAgICByZXNvbHZlKClcbiAgICB9KVxuICB9KVxuXG4gIC8vIE1ha2Ugc3VyZSB3ZSBzdGFydCBsaXN0ZW5pbmcgb24gdGhlIG1lc3NhZ2UgcG9ydCBhZnRlciB0aGUgZGV2IHNlcnZlci5cbiAgLy8gV2UgZG8gdGhpcyBtb3N0bHkgdG8gYXBwZWFzZSBjb2Rlc2FuZGJveC5pbywgc2luY2UgdGhleSBhdXRvYmluZCB0byB0aGUgZmlyc3RcbiAgLy8gcG9ydCB0aGF0IG9wZW5zIHVwIGZvciB0aGVpciBwcmV2aWV3IHdpbmRvdy5cbiAgc29ja2V0Lmxpc3RlbihtZXNzYWdlUG9ydClcblxuICBjb25zb2xlLmxvZygnUnVubmluZyBwbHVnaW5zLi4uJylcbiAgc3RhdGUgPSBhd2FpdCBwbHVnaW5zLmFmdGVyRGV2U2VydmVyU3RhcnQoc3RhdGUpXG5cbiAgcmV0dXJuIHN0YXRlXG59XG4iXX0=