UNPKG

vite-plugin-react-server

Version:
306 lines (303 loc) 42.1 kB
/** * vite-plugin-react-server * Copyright (c) Nico Brinkkemper * MIT License */ import 'node:worker_threads'; import { serializedOptions } from '../helpers/serializeUserOptions.js'; import { requestInfo } from '../helpers/requestInfo.js'; import { restartWorker } from './restartWorker.client.js'; import { handleRscStream } from '../stream/handleRscStream.client.js'; import { getRouteFiles } from '../helpers/getRouteFiles.js'; import { handleServerAction } from './handleServerAction.client.js'; import { handleError } from '../error/handleError.js'; import { getNodeEnv } from '../config/getNodeEnv.js'; import { isReactServerCondition } from '../config/getCondition.js'; import { setupGlobalErrorHandler, cleanupGlobalErrorHandler } from '../error/setupGlobalErrorHandler.js'; import { pipeToResponse } from '../helpers/pipeToResponse.js'; const configureRequestHandler = async function _configureWorkerRequestHandler({ server, autoDiscoveredFiles, userOptions: _userOptions, configEnv, hmrChannel, onWorkerCreated }) { const logger = server.config.customLogger || server.config.logger; const { // remove these moduleBaseURL: _moduleBaseURL, ...handlerUserOptions } = _userOptions; const handlerOptions = Object.assign({}, handlerUserOptions, { moduleBaseURL: server.config.base, projectRoot: _userOptions.projectRoot || server.config.root, logger }); setupGlobalErrorHandler({ panicThreshold: handlerOptions.panicThreshold, logger, verbose: handlerOptions.verbose }); let currentWorker = null; let restartWorkerForHMR = null; server.ws.on("restart", async () => { logger.info("[react-client] Server restarting, shutting down worker..."); if (currentWorker) { currentWorker.postMessage({ type: "SHUTDOWN", id: "*" }); await new Promise((resolve, reject) => { currentWorker?.on("message", (message) => { if (message.type === "SHUTDOWN_COMPLETE") { resolve(true); } else { reject("Did not receive SHUTDOWN_COMPLETE"); } }); }); currentWorker.removeAllListeners(); currentWorker = null; } cleanupGlobalErrorHandler(); }); const handler = async (req, res, next) => { if (!req.url) return next(); const info = requestInfo(req, handlerOptions, ""); const handlerOptionsWithUrl = { ...handlerOptions, url: info.url }; if (handlerOptions.verbose) { server.config.logger.info(`[configureRequestHandler] handlerOptionsWithUrl.projectRoot: ${handlerOptionsWithUrl.projectRoot}`); server.config.logger.info(`[configureRequestHandler] handlerOptions.projectRoot: ${handlerOptions.projectRoot}`); } const serializedUserOptions = serializedOptions( handlerOptionsWithUrl, autoDiscoveredFiles ); if (!restartWorkerForHMR) { restartWorkerForHMR = async () => { if (currentWorker) { currentWorker = await restartWorker({ server, autoDiscoveredFiles, userOptions: serializedUserOptions, configEnv, hmrChannel }); if (currentWorker && restartWorkerForHMR) { onWorkerCreated?.(currentWorker, restartWorkerForHMR); } } else { currentWorker = await restartWorker({ server, autoDiscoveredFiles, userOptions: serializedUserOptions, configEnv, hmrChannel }); if (currentWorker && restartWorkerForHMR) { onWorkerCreated?.(currentWorker, restartWorkerForHMR); } } }; } if (handlerOptions.verbose) { server.config.logger.info(`[configureRequestHandler] serializedUserOptions.projectRoot: ${serializedUserOptions.projectRoot}`); } if (info.isServerActionRequest) { if (!currentWorker) { currentWorker = await restartWorker({ server, autoDiscoveredFiles, userOptions: serializedUserOptions, configEnv, hmrChannel }); } if (!currentWorker) { throw new Error("Failed to start worker"); } return handleServerAction(req, res, currentWorker, logger); } if (!info.isRscRequest) { return next(); } const routeFiles = await getRouteFiles( info.route, autoDiscoveredFiles, handlerOptions, logger ); if (routeFiles.type === "error") { const panicError = handleError({ error: routeFiles.error, logger, mode: getNodeEnv(server.config.mode), panicThreshold: handlerOptions.panicThreshold, critical: false}); if (panicError != null) { throw panicError; } return next(routeFiles.error); } const pagePath = routeFiles.page; const propsPath = routeFiles.props; const rootPath = routeFiles.root; let resolvedPageProps; if (propsPath) { try { const fullPropsPath = `${handlerOptions.projectRoot}/${propsPath}`; const serverEnv = server.environments?.["server"]; let propsModule; if (handlerOptions.verbose) { logger.info(`[configureRequestHandler] Pre-loading props from: ${fullPropsPath}`); } if (isReactServerCondition() && serverEnv && "runner" in serverEnv && serverEnv.runner) { try { propsModule = await serverEnv.runner.import(fullPropsPath); } catch (runnerError) { if (handlerOptions.verbose) { logger.info(`[configureRequestHandler] Main-thread props import failed; worker will load props`); } propsModule = null; } } else { propsModule = null; } const propsExportName = handlerOptions.propsExportName || "props"; if (propsModule) { const propsExport = propsModule[propsExportName]; if (typeof propsExport === "function") { let result = propsExport(info.url); if (result instanceof Promise) { result = await result; } resolvedPageProps = result; if (handlerOptions.verbose) { logger.info(`[configureRequestHandler] Pre-loaded props for ${info.route}: ${Object.keys(resolvedPageProps || {}).length} keys`); } } else if (propsExport && typeof propsExport === "object") { resolvedPageProps = propsExport; } } } catch (error) { if (handlerOptions.verbose) { logger.warn(`[configureRequestHandler] Failed to pre-load props: ${error}`); } } } try { res.setHeader("Content-Type", info.contentType); res.setHeader("Transfer-Encoding", "chunked"); res.setHeader("Connection", "keep-alive"); res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); res.setHeader("Pragma", "no-cache"); res.setHeader("Expires", "0"); const userOnMetrics = handlerOptions.onMetrics; if (!currentWorker) { currentWorker = await restartWorker({ server, autoDiscoveredFiles, userOptions: serializedUserOptions, configEnv, hmrChannel }); } if (!currentWorker) { throw new Error("Failed to start worker"); } onWorkerCreated?.(currentWorker, restartWorkerForHMR); const stream = handleRscStream({ options: { ...serializedUserOptions, worker: currentWorker, id: info.route, type: "INIT", logger, // we make the worker stream aware of the route, pagePath, propsPath, rootPath, htmlPath route: info.route, url: info.url, pagePath, propsPath, // Pass pre-resolved props (loaded via Vite's ssrLoadModule for proper transforms) resolvedPageProps, rootPath, // CRITICAL: For RSC requests, use htmlPath: "" for headless mode (no Html wrapper) // This prevents hydration errors where <html> would be rendered inside #root div htmlPath: "", // Empty string = headless RSC (no Html wrapper) // Component overrides (undefined for file-based components in client dev) HtmlComponent: void 0, RootComponent: void 0, // Use userOptions.projectRoot if available, otherwise fall back to server.config.root projectRoot: serializedUserOptions.projectRoot || server.config.root, build: { ...serializedUserOptions.build || {}, pages: Array.isArray(serializedUserOptions.build?.pages) ? serializedUserOptions.build.pages : [] }, manifest: {}, cssFiles: /* @__PURE__ */ new Map(), globalCss: /* @__PURE__ */ new Map(), serverPipeableStreamOptions: serializedUserOptions.serverPipeableStreamOptions, clientPipeableStreamOptions: serializedUserOptions.clientPipeableStreamOptions }, handlers: { onMetrics: (id, metrics) => { metrics.route = id; userOnMetrics?.(metrics); }, onHmrAccept: () => { }, onHmrUpdate: () => { }, // Always log shell errors. Without this an RSC render failure in // the worker would surface only via `verbose: true`, leaving the // user with a half-streamed RSC response and no explanation. onShellError: (id, error) => { logger.error( `[configureRequestHandler:${id}] RSC shell error: ${error instanceof Error ? error.message : String(error)}`, { error: error instanceof Error ? error : new Error(String(error)) } ); } }, ...handlerOptions }); pipeToResponse({ stream, response: res, contentType: info.contentType, logger, verbose: handlerOptions.verbose, panicThreshold: handlerOptions.panicThreshold, context: "configureWorkerRequestHandler" }); } catch (error) { const panicError = handleError({ error, logger, mode: getNodeEnv(server.config.mode), panicThreshold: handlerOptions.panicThreshold, critical: false, log: true }); if (panicError != null) { throw panicError; } if (!res.headersSent) { res.statusCode = 500; res.setHeader("Content-Type", "text/plain; charset=utf-8"); const message = error instanceof Error ? error.message : String(error); res.end(`RSC render failed: ${message} `); } else { res.end(); } } }; server.middlewares.use(handler); }; export { configureRequestHandler }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlndXJlUmVxdWVzdEhhbmRsZXIuY2xpZW50LmpzIiwic291cmNlcyI6WyIuLi8uLi8uLi9wbHVnaW4vZGV2LXNlcnZlci9jb25maWd1cmVSZXF1ZXN0SGFuZGxlci5jbGllbnQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBSZXF1ZXN0SGFuZGxlciB9IGZyb20gXCIuLi90eXBlcy5qc1wiO1xuaW1wb3J0IHsgdHlwZSBXb3JrZXIgfSBmcm9tIFwibm9kZTp3b3JrZXJfdGhyZWFkc1wiO1xuaW1wb3J0IHsgc2VyaWFsaXplZE9wdGlvbnMgfSBmcm9tIFwiLi4vaGVscGVycy9zZXJpYWxpemVVc2VyT3B0aW9ucy5qc1wiO1xuaW1wb3J0IHsgcmVxdWVzdEluZm8gfSBmcm9tIFwiLi4vaGVscGVycy9yZXF1ZXN0SW5mby5qc1wiO1xuaW1wb3J0IHsgcmVzdGFydFdvcmtlciB9IGZyb20gXCIuL3Jlc3RhcnRXb3JrZXIuY2xpZW50LmpzXCI7XG5pbXBvcnQgeyBoYW5kbGVSc2NTdHJlYW0gfSBmcm9tIFwiLi4vc3RyZWFtL2hhbmRsZVJzY1N0cmVhbS5jbGllbnQuanNcIjtcbmltcG9ydCB7IGdldFJvdXRlRmlsZXMgfSBmcm9tIFwiLi4vaGVscGVycy9nZXRSb3V0ZUZpbGVzLmpzXCI7XG5pbXBvcnQgdHlwZSB7IFJzY1dvcmtlcklucHV0TWVzc2FnZSB9IGZyb20gXCIuLi93b3JrZXIvcnNjL3R5cGVzLmpzXCI7XG5cbmltcG9ydCB7IGhhbmRsZVNlcnZlckFjdGlvbiB9IGZyb20gXCIuL2hhbmRsZVNlcnZlckFjdGlvbi5jbGllbnQuanNcIjtcbmltcG9ydCB0eXBlIHsgQ29uZmlndXJlV29ya2VyUmVxdWVzdEhhbmRsZXJGbiB9IGZyb20gXCIuLi9yZWFjdC1jbGllbnQvdHlwZXMuanNcIjtcbmltcG9ydCB7IGhhbmRsZUVycm9yIH0gZnJvbSBcIi4uL2Vycm9yL2hhbmRsZUVycm9yLmpzXCI7XG5pbXBvcnQgeyBnZXROb2RlRW52IH0gZnJvbSBcIi4uL2NvbmZpZy9nZXROb2RlRW52LmpzXCI7XG5pbXBvcnQgeyBpc1JlYWN0U2VydmVyQ29uZGl0aW9uIH0gZnJvbSBcIi4uL2NvbmZpZy9nZXRDb25kaXRpb24uanNcIjtcbmltcG9ydCB7IHNldHVwR2xvYmFsRXJyb3JIYW5kbGVyLCBjbGVhbnVwR2xvYmFsRXJyb3JIYW5kbGVyIH0gZnJvbSBcIi4uL2Vycm9yL3NldHVwR2xvYmFsRXJyb3JIYW5kbGVyLmpzXCI7XG5pbXBvcnQgeyBwaXBlVG9SZXNwb25zZSB9IGZyb20gXCIuLi9oZWxwZXJzL3BpcGVUb1Jlc3BvbnNlLmpzXCI7XG5cbi8qKlxuICogQ29uZmlndXJlcyB0aGUgd29ya2VyIHJlcXVlc3QgaGFuZGxlci5cbiAqIEBwYXJhbSBzZXJ2ZXIgLSBUaGUgVml0ZSBkZXYgc2VydmVyXG4gKiBAcGFyYW0gYXV0b0Rpc2NvdmVyZWRGaWxlcyAtIFRoZSBhdXRvIGRpc2NvdmVyZWQgZmlsZXNcbiAqIEBwYXJhbSB1c2VyT3B0aW9ucyAtIFRoZSB1c2VyIG9wdGlvbnNcbiAqL1xuZXhwb3J0IGNvbnN0IGNvbmZpZ3VyZVJlcXVlc3RIYW5kbGVyOiBDb25maWd1cmVXb3JrZXJSZXF1ZXN0SGFuZGxlckZuID1cbiAgYXN5bmMgZnVuY3Rpb24gX2NvbmZpZ3VyZVdvcmtlclJlcXVlc3RIYW5kbGVyKHtcbiAgICBzZXJ2ZXIsXG4gICAgYXV0b0Rpc2NvdmVyZWRGaWxlcyxcbiAgICB1c2VyT3B0aW9uczogX3VzZXJPcHRpb25zLFxuICAgIGNvbmZpZ0VudixcbiAgICBobXJDaGFubmVsLFxuICAgIG9uV29ya2VyQ3JlYXRlZCxcbiAgfSkge1xuICAgIGNvbnN0IGxvZ2dlciA9IHNlcnZlci5jb25maWcuY3VzdG9tTG9nZ2VyIHx8IHNlcnZlci5jb25maWcubG9nZ2VyO1xuICAgIGNvbnN0IHtcbiAgICAgIC8vIHJlbW92ZSB0aGVzZVxuICAgICAgbW9kdWxlQmFzZVVSTDogX21vZHVsZUJhc2VVUkwsXG4gICAgICAuLi5oYW5kbGVyVXNlck9wdGlvbnNcbiAgICB9ID0gX3VzZXJPcHRpb25zO1xuICAgIGNvbnN0IGhhbmRsZXJPcHRpb25zID0gT2JqZWN0LmFzc2lnbih7fSwgaGFuZGxlclVzZXJPcHRpb25zLCB7XG4gICAgICBtb2R1bGVCYXNlVVJMOiBzZXJ2ZXIuY29uZmlnLmJhc2UsXG4gICAgICBwcm9qZWN0Um9vdDogX3VzZXJPcHRpb25zLnByb2plY3RSb290IHx8IHNlcnZlci5jb25maWcucm9vdCxcbiAgICAgIGxvZ2dlcjogbG9nZ2VyLFxuICAgIH0pO1xuXG4gICAgLy8gU2V0IHVwIGdsb2JhbCBlcnJvciBoYW5kbGVyIGZvciBhbGxfZXJyb3JzIHBhbmljIHRocmVzaG9sZFxuICAgIHNldHVwR2xvYmFsRXJyb3JIYW5kbGVyKHtcbiAgICAgIHBhbmljVGhyZXNob2xkOiBoYW5kbGVyT3B0aW9ucy5wYW5pY1RocmVzaG9sZCxcbiAgICAgIGxvZ2dlcjogbG9nZ2VyLFxuICAgICAgdmVyYm9zZTogaGFuZGxlck9wdGlvbnMudmVyYm9zZSxcbiAgICB9KTtcblxuICAgIC8vIFN0YXJ0IHRoZSB3b3JrZXJcbiAgICBsZXQgY3VycmVudFdvcmtlcjogV29ya2VyIHwgbnVsbCA9IG51bGw7XG4gICAgbGV0IHJlc3RhcnRXb3JrZXJGb3JITVI6ICgoKSA9PiBQcm9taXNlPHZvaWQ+KSB8IG51bGwgPSBudWxsO1xuXG4gICAgLy8gSGFuZGxlIHNlcnZlciByZXN0YXJ0c1xuICAgIHNlcnZlci53cy5vbihcInJlc3RhcnRcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgbG9nZ2VyLmluZm8oXCJbcmVhY3QtY2xpZW50XSBTZXJ2ZXIgcmVzdGFydGluZywgc2h1dHRpbmcgZG93biB3b3JrZXIuLi5cIik7XG4gICAgICBpZiAoY3VycmVudFdvcmtlcikge1xuICAgICAgICBjdXJyZW50V29ya2VyLnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICB0eXBlOiBcIlNIVVRET1dOXCIsXG4gICAgICAgICAgaWQ6IFwiKlwiLFxuICAgICAgICB9IHNhdGlzZmllcyBSc2NXb3JrZXJJbnB1dE1lc3NhZ2UpO1xuICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgY3VycmVudFdvcmtlcj8ub24oXCJtZXNzYWdlXCIsIChtZXNzYWdlKSA9PiB7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS50eXBlID09PSBcIlNIVVRET1dOX0NPTVBMRVRFXCIpIHtcbiAgICAgICAgICAgICAgcmVzb2x2ZSh0cnVlKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJlamVjdChcIkRpZCBub3QgcmVjZWl2ZSBTSFVURE9XTl9DT01QTEVURVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGN1cnJlbnRXb3JrZXIucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gICAgICAgIGN1cnJlbnRXb3JrZXIgPSBudWxsO1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBDbGVhbiB1cCBnbG9iYWwgZXJyb3IgaGFuZGxlclxuICAgICAgY2xlYW51cEdsb2JhbEVycm9ySGFuZGxlcigpO1xuICAgIH0pO1xuXG4gICAgLy8gQ3JlYXRlIHRoZSByZXF1ZXN0IGhhbmRsZXJcbiAgICBjb25zdCBoYW5kbGVyOiBSZXF1ZXN0SGFuZGxlciA9IGFzeW5jIChyZXEsIHJlcywgbmV4dCkgPT4ge1xuICAgICAgaWYgKCFyZXEudXJsKSByZXR1cm4gbmV4dCgpO1xuXG4gICAgICBjb25zdCBpbmZvID0gcmVxdWVzdEluZm8ocmVxLCBoYW5kbGVyT3B0aW9ucywgXCJcIik7XG4gICAgICBjb25zdCBoYW5kbGVyT3B0aW9uc1dpdGhVcmwgPSB7XG4gICAgICAgIC4uLmhhbmRsZXJPcHRpb25zLFxuICAgICAgICB1cmw6IGluZm8udXJsLFxuICAgICAgfTtcbiAgICAgIFxuICAgICAgaWYgKGhhbmRsZXJPcHRpb25zLnZlcmJvc2UpIHtcbiAgICAgICAgc2VydmVyLmNvbmZpZy5sb2dnZXIuaW5mbyhgW2NvbmZpZ3VyZVJlcXVlc3RIYW5kbGVyXSBoYW5kbGVyT3B0aW9uc1dpdGhVcmwucHJvamVjdFJvb3Q6ICR7aGFuZGxlck9wdGlvbnNXaXRoVXJsLnByb2plY3RSb290fWApO1xuICAgICAgICBzZXJ2ZXIuY29uZmlnLmxvZ2dlci5pbmZvKGBbY29uZmlndXJlUmVxdWVzdEhhbmRsZXJdIGhhbmRsZXJPcHRpb25zLnByb2plY3RSb290OiAke2hhbmRsZXJPcHRpb25zLnByb2plY3RSb290fWApO1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBTZXJpYWxpemUgdXNlciBvcHRpb25zIGZvciB3b3JrZXJcbiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRVc2VyT3B0aW9ucyA9IHNlcmlhbGl6ZWRPcHRpb25zKFxuICAgICAgICBoYW5kbGVyT3B0aW9uc1dpdGhVcmwsXG4gICAgICAgIGF1dG9EaXNjb3ZlcmVkRmlsZXNcbiAgICAgICk7XG4gICAgICBcbiAgICAgIC8vIERlZmluZSByZXN0YXJ0IGZ1bmN0aW9uIGZvciBITVIgKG5lZWRzIHNlcmlhbGl6ZWRVc2VyT3B0aW9ucylcbiAgICAgIGlmICghcmVzdGFydFdvcmtlckZvckhNUikge1xuICAgICAgICByZXN0YXJ0V29ya2VyRm9ySE1SID0gYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGlmIChjdXJyZW50V29ya2VyKSB7XG4gICAgICAgICAgICBjdXJyZW50V29ya2VyID0gYXdhaXQgcmVzdGFydFdvcmtlcih7XG4gICAgICAgICAgICAgIHNlcnZlcixcbiAgICAgICAgICAgICAgYXV0b0Rpc2NvdmVyZWRGaWxlcyxcbiAgICAgICAgICAgICAgdXNlck9wdGlvbnM6IHNlcmlhbGl6ZWRVc2VyT3B0aW9ucyxcbiAgICAgICAgICAgICAgY29uZmlnRW52OiBjb25maWdFbnYsXG4gICAgICAgICAgICAgIGhtckNoYW5uZWwsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChjdXJyZW50V29ya2VyICYmIHJlc3RhcnRXb3JrZXJGb3JITVIpIHtcbiAgICAgICAgICAgICAgb25Xb3JrZXJDcmVhdGVkPy4oY3VycmVudFdvcmtlciwgcmVzdGFydFdvcmtlckZvckhNUik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFdvcmtlciBkb2Vzbid0IGV4aXN0IHlldCwgY3JlYXRlIGl0XG4gICAgICAgICAgICBjdXJyZW50V29ya2VyID0gYXdhaXQgcmVzdGFydFdvcmtlcih7XG4gICAgICAgICAgICAgIHNlcnZlcixcbiAgICAgICAgICAgICAgYXV0b0Rpc2NvdmVyZWRGaWxlcyxcbiAgICAgICAgICAgICAgdXNlck9wdGlvbnM6IHNlcmlhbGl6ZWRVc2VyT3B0aW9ucyxcbiAgICAgICAgICAgICAgY29uZmlnRW52OiBjb25maWdFbnYsXG4gICAgICAgICAgICAgIGhtckNoYW5uZWwsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChjdXJyZW50V29ya2VyICYmIHJlc3RhcnRXb3JrZXJGb3JITVIpIHtcbiAgICAgICAgICAgICAgb25Xb3JrZXJDcmVhdGVkPy4oY3VycmVudFdvcmtlciwgcmVzdGFydFdvcmtlckZvckhNUik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgXG4gICAgICBpZiAoaGFuZGxlck9wdGlvbnMudmVyYm9zZSkge1xuICAgICAgICBzZXJ2ZXIuY29uZmlnLmxvZ2dlci5pbmZvKGBbY29uZmlndXJlUmVxdWVzdEhhbmRsZXJdIHNlcmlhbGl6ZWRVc2VyT3B0aW9ucy5wcm9qZWN0Um9vdDogJHtzZXJpYWxpemVkVXNlck9wdGlvbnMucHJvamVjdFJvb3R9YCk7XG4gICAgICB9XG5cbiAgICAgIC8vIEhhbmRsZSBzZXJ2ZXIgYWN0aW9uIHJlcXVlc3RzXG4gICAgICBpZiAoaW5mby5pc1NlcnZlckFjdGlvblJlcXVlc3QpIHtcbiAgICAgICAgaWYgKCFjdXJyZW50V29ya2VyKSB7XG4gICAgICAgICAgY3VycmVudFdvcmtlciA9IGF3YWl0IHJlc3RhcnRXb3JrZXIoe1xuICAgICAgICAgICAgc2VydmVyLFxuICAgICAgICAgICAgYXV0b0Rpc2NvdmVyZWRGaWxlcyxcbiAgICAgICAgICAgIHVzZXJPcHRpb25zOiBzZXJpYWxpemVkVXNlck9wdGlvbnMsXG4gICAgICAgICAgICBjb25maWdFbnY6IGNvbmZpZ0VudixcbiAgICAgICAgICAgIGhtckNoYW5uZWwsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFjdXJyZW50V29ya2VyKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRmFpbGVkIHRvIHN0YXJ0IHdvcmtlclwiKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaGFuZGxlU2VydmVyQWN0aW9uKHJlcSwgcmVzLCBjdXJyZW50V29ya2VyLCBsb2dnZXIpO1xuICAgICAgfVxuXG4gICAgICAvLyBIYW5kbGUgUlNDIHJlcXVlc3RzXG4gICAgICBpZiAoIWluZm8uaXNSc2NSZXF1ZXN0KSB7XG4gICAgICAgIHJldHVybiBuZXh0KCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJvdXRlRmlsZXMgPSBhd2FpdCBnZXRSb3V0ZUZpbGVzKFxuICAgICAgICBpbmZvLnJvdXRlLFxuICAgICAgICBhdXRvRGlzY292ZXJlZEZpbGVzLFxuICAgICAgICBoYW5kbGVyT3B0aW9ucyxcbiAgICAgICAgbG9nZ2VyXG4gICAgICApO1xuICAgICAgaWYgKHJvdXRlRmlsZXMudHlwZSA9PT0gXCJlcnJvclwiKSB7XG4gICAgICAgIGNvbnN0ICAgcGFuaWNFcnJvciA9IGhhbmRsZUVycm9yKHtcbiAgICAgICAgICBlcnJvcjogcm91dGVGaWxlcy5lcnJvcixcbiAgICAgICAgICBsb2dnZXIsXG4gICAgICAgICAgbW9kZTogZ2V0Tm9kZUVudihzZXJ2ZXIuY29uZmlnLm1vZGUpLFxuICAgICAgICAgIHBhbmljVGhyZXNob2xkOiBoYW5kbGVyT3B0aW9ucy5wYW5pY1RocmVzaG9sZCxcbiAgICAgICAgICBjcml0aWNhbDogZmFsc2UsXG4gICAgICAgICAgY29udGV4dDogXCJjb25maWd1cmVXb3JrZXJSZXF1ZXN0SGFuZGxlclwiLFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKHBhbmljRXJyb3IgIT0gbnVsbCkge1xuICAgICAgICAgIHRocm93IHBhbmljRXJyb3I7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5leHQocm91dGVGaWxlcy5lcnJvcik7XG4gICAgICB9XG4gICAgICBjb25zdCBwYWdlUGF0aCA9IHJvdXRlRmlsZXMucGFnZTtcbiAgICAgIGNvbnN0IHByb3BzUGF0aCA9IHJvdXRlRmlsZXMucHJvcHM7XG4gICAgICBjb25zdCByb290UGF0aCA9IHJvdXRlRmlsZXMucm9vdDtcbiAgICAgIC8vIE5vdGU6IGh0bWxQYXRoIG5vdCB1c2VkIGZvciBSU0MgcmVxdWVzdHMgKGFsd2F5cyBcIlwiIGZvciBoZWFkbGVzcyBtb2RlKVxuICAgICAgXG4gICAgICAvLyBQcmUtbG9hZCBwcm9wcyBvbiBtYWluIHRocmVhZCB0byBhcHBseSBWaXRlIHRyYW5zZm9ybXMgKHNlcnZlciBhY3Rpb25zIG5lZWQgdGhpcykuXG4gICAgICAvLyBPbmx5IHdoZW4gdGhlIG1haW4gcHJvY2VzcyBhY3R1YWxseSBydW5zIHRoZSByZWFjdC1zZXJ2ZXIgY29uZGl0aW9uIChkZXY6cnNjKTpcbiAgICAgIC8vIGEgcHJvcHMgbW9kdWxlIHB1bGxzIHRoZSBzZXJ2ZXIgZ3JhcGggKGFuZCBhbnkgY2xpZW50IGNvbXBvbmVudCBpdCByZWFjaGVzIGxvYWRzXG4gICAgICAvLyBpdHMgcmVnaXN0ZXJDbGllbnRSZWZlcmVuY2UgZm9ybSwgd2hpY2ggaW1wb3J0cyByZWFjdC1zZXJ2ZXItZG9tLWVzbS1zZXJ2ZXIgYW5kXG4gICAgICAvLyBoYXJkLXJlcXVpcmVzIHJlYWN0LXNlcnZlcikuIEluIGRldjpzc3IgdGhlIG1haW4gdGhyZWFkIGlzIE5PVCByZWFjdC1zZXJ2ZXIsIHNvIHdlXG4gICAgICAvLyBtdXN0IE5PVCBhdHRlbXB0IHRoaXMg4oCUIHRoZSB3b3JrZXIgbG9hZHMgcHJvcHMgaW5zdGVhZC4gQXR0ZW1wdGluZyBpdCB0aGVyZSBtYWRlXG4gICAgICAvLyBWaXRlJ3MgTW9kdWxlUnVubmVyIGxvZyBhIFwicmVhY3Qtc2VydmVyIGNvbmRpdGlvbiBtdXN0IGJlIGVuYWJsZWRcIiBlcnJvciBkdXJpbmdcbiAgICAgIC8vIGZ1bGwgcmVsb2FkcyBldmVuIHRob3VnaCB3ZSBjYXVnaHQgdGhlIHJlamVjdGlvbiAoYmQtdTd2KS4gR2F0ZSBvbiB0aGUgY29uZGl0aW9uXG4gICAgICAvLyBzbyB0aGUgZG9vbWVkIGltcG9ydCBuZXZlciBydW5zIGluIGRldjpzc3IuXG4gICAgICBsZXQgcmVzb2x2ZWRQYWdlUHJvcHM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgdW5kZWZpbmVkO1xuICAgICAgaWYgKHByb3BzUGF0aCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IGZ1bGxQcm9wc1BhdGggPSBgJHtoYW5kbGVyT3B0aW9ucy5wcm9qZWN0Um9vdH0vJHtwcm9wc1BhdGh9YDtcbiAgICAgICAgICBjb25zdCBzZXJ2ZXJFbnYgPSBzZXJ2ZXIuZW52aXJvbm1lbnRzPy5bJ3NlcnZlciddO1xuICAgICAgICAgIGxldCBwcm9wc01vZHVsZTogYW55O1xuXG4gICAgICAgICAgaWYgKGhhbmRsZXJPcHRpb25zLnZlcmJvc2UpIHtcbiAgICAgICAgICAgIGxvZ2dlci5pbmZvKGBbY29uZmlndXJlUmVxdWVzdEhhbmRsZXJdIFByZS1sb2FkaW5nIHByb3BzIGZyb206ICR7ZnVsbFByb3BzUGF0aH1gKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBpc1JlYWN0U2VydmVyQ29uZGl0aW9uKCkgJiZcbiAgICAgICAgICAgIHNlcnZlckVudiAmJlxuICAgICAgICAgICAgJ3J1bm5lcicgaW4gc2VydmVyRW52ICYmXG4gICAgICAgICAgICBzZXJ2ZXJFbnYucnVubmVyXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICAvLyBkZXY6cnNjIOKAlCBtYWluIHRocmVhZCBoYXMgdGhlIHJlYWN0LXNlcnZlciBjb25kaXRpb24sIHNvIHRoZSBzZXJ2ZXJcbiAgICAgICAgICAgIC8vIGVudmlyb25tZW50IHJ1bm5lciBjYW4gZXZhbHVhdGUgdGhlIHByb3BzIChhbmQgdGhlIHNlcnZlciBncmFwaCkgZGlyZWN0bHkuXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBwcm9wc01vZHVsZSA9IGF3YWl0IChzZXJ2ZXJFbnYucnVubmVyIGFzIGFueSkuaW1wb3J0KGZ1bGxQcm9wc1BhdGgpO1xuICAgICAgICAgICAgfSBjYXRjaCAocnVubmVyRXJyb3I6IGFueSkge1xuICAgICAgICAgICAgICBpZiAoaGFuZGxlck9wdGlvbnMudmVyYm9zZSkge1xuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGBbY29uZmlndXJlUmVxdWVzdEhhbmRsZXJdIE1haW4tdGhyZWFkIHByb3BzIGltcG9ydCBmYWlsZWQ7IHdvcmtlciB3aWxsIGxvYWQgcHJvcHNgKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBwcm9wc01vZHVsZSA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGRldjpzc3IgKG5vIHJlYWN0LXNlcnZlciBvbiB0aGUgbWFpbiB0aHJlYWQpIG9yIG5vIHNlcnZlciBlbnY6XG4gICAgICAgICAgICAvLyB0aGUgd29ya2VyIGxvYWRzIHByb3BzIGluIGl0cyByZWFjdC1zZXJ2ZXIgY29udGV4dC5cbiAgICAgICAgICAgIHByb3BzTW9kdWxlID0gbnVsbDtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3QgcHJvcHNFeHBvcnROYW1lID0gaGFuZGxlck9wdGlvbnMucHJvcHNFeHBvcnROYW1lIHx8IFwicHJvcHNcIjtcbiAgICAgICAgICBcbiAgICAgICAgICAvLyBPbmx5IHByb2Nlc3MgaWYgd2UgZ290IGEgbW9kdWxlIChzZXJ2ZXIgcnVubmVyIHN1Y2NlZWRlZClcbiAgICAgICAgICBpZiAocHJvcHNNb2R1bGUpIHtcbiAgICAgICAgICAgIGNvbnN0IHByb3BzRXhwb3J0ID0gcHJvcHNNb2R1bGVbcHJvcHNFeHBvcnROYW1lXTtcbiAgICAgICAgICBcbiAgICAgICAgICAgIGlmICh0eXBlb2YgcHJvcHNFeHBvcnQgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgLy8gQ2FsbCB0aGUgcHJvcHMgZnVuY3Rpb24gd2l0aCB0aGUgVVJMXG4gICAgICAgICAgICBsZXQgcmVzdWx0ID0gcHJvcHNFeHBvcnQoaW5mby51cmwpO1xuICAgICAgICAgICAgaWYgKHJlc3VsdCBpbnN0YW5jZW9mIFByb21pc2UpIHtcbiAgICAgICAgICAgICAgcmVzdWx0ID0gYXdhaXQgcmVzdWx0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVzb2x2ZWRQYWdlUHJvcHMgPSByZXN1bHQ7XG4gICAgICAgICAgICBpZiAoaGFuZGxlck9wdGlvbnMudmVyYm9zZSkge1xuICAgICAgICAgICAgICBsb2dnZXIuaW5mbyhgW2NvbmZpZ3VyZVJlcXVlc3RIYW5kbGVyXSBQcmUtbG9hZGVkIHByb3BzIGZvciAke2luZm8ucm91dGV9OiAke09iamVjdC5rZXlzKHJlc29sdmVkUGFnZVByb3BzIHx8IHt9KS5sZW5ndGh9IGtleXNgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2UgaWYgKHByb3BzRXhwb3J0ICYmIHR5cGVvZiBwcm9wc0V4cG9ydCA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgcmVzb2x2ZWRQYWdlUHJvcHMgPSBwcm9wc0V4cG9ydDtcbiAgICAgICAgICB9XG4gICAgICAgICAgfSAgLy8gZW5kIGlmIChwcm9wc01vZHVsZSlcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBpZiAoaGFuZGxlck9wdGlvbnMudmVyYm9zZSkge1xuICAgICAgICAgICAgbG9nZ2VyLndhcm4oYFtjb25maWd1cmVSZXF1ZXN0SGFuZGxlcl0gRmFpbGVkIHRvIHByZS1sb2FkIHByb3BzOiAke2Vycm9yfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBDb250aW51ZSB3aXRob3V0IHByZS1sb2FkZWQgcHJvcHMsIHdvcmtlciB3aWxsIHRyeSB0byBsb2FkIHRoZW1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgXG4gICAgICB0cnkge1xuICAgICAgICAvLyBTZXQgdXAgcmVzcG9uc2UgaGVhZGVycyBmb3Igc3RyZWFtaW5nXG4gICAgICAgIHJlcy5zZXRIZWFkZXIoXCJDb250ZW50LVR5cGVcIiwgaW5mby5jb250ZW50VHlwZSk7XG4gICAgICAgIHJlcy5zZXRIZWFkZXIoXCJUcmFuc2Zlci1FbmNvZGluZ1wiLCBcImNodW5rZWRcIik7XG4gICAgICAgIHJlcy5zZXRIZWFkZXIoXCJDb25uZWN0aW9uXCIsIFwia2VlcC1hbGl2ZVwiKTtcbiAgICAgICAgXG4gICAgICAgIC8vIENSSVRJQ0FMOiBEaXNhYmxlIGNhY2hpbmcgaW4gZGV2ZWxvcG1lbnQgbW9kZVxuICAgICAgICAvLyBXaXRob3V0IHRoaXMsIGJyb3dzZXJzIGNhY2hlIFJTQyBzdHJlYW1zIGFuZCBkb24ndCBzaG93IHVwZGF0ZXNcbiAgICAgICAgcmVzLnNldEhlYWRlcihcIkNhY2hlLUNvbnRyb2xcIiwgXCJuby1jYWNoZSwgbm8tc3RvcmUsIG11c3QtcmV2YWxpZGF0ZVwiKTtcbiAgICAgICAgcmVzLnNldEhlYWRlcihcIlByYWdtYVwiLCBcIm5vLWNhY2hlXCIpO1xuICAgICAgICByZXMuc2V0SGVhZGVyKFwiRXhwaXJlc1wiLCBcIjBcIik7XG5cbiAgICAgICAgY29uc3QgdXNlck9uTWV0cmljcyA9IGhhbmRsZXJPcHRpb25zLm9uTWV0cmljcztcblxuICAgICAgICAvLyBTcGF3biB0aGUgd29ya2VyIGxhemlseSBvbiB0aGUgZmlyc3QgcmVxdWVzdC4gVGhlIE1vZHVsZVJ1bm5lclxuICAgICAgICAvLyBoYW5kbGVzIHBlci1tb2R1bGUgaW52YWxpZGF0aW9uIHZpYSB0aGUgSE1SX1VQREFURSBtZXNzYWdlXG4gICAgICAgIC8vIGhhbmRsZXIsIHNvIGEgbG9uZy1saXZlZCB3b3JrZXIgY2FuIGtlZXAgc2VydmluZyBhY3Jvc3MgZWRpdHMuXG4gICAgICAgIGlmICghY3VycmVudFdvcmtlcikge1xuICAgICAgICAgIGN1cnJlbnRXb3JrZXIgPSBhd2FpdCByZXN0YXJ0V29ya2VyKHtcbiAgICAgICAgICAgIHNlcnZlcixcbiAgICAgICAgICAgIGF1dG9EaXNjb3ZlcmVkRmlsZXMsXG4gICAgICAgICAgICB1c2VyT3B0aW9uczogc2VyaWFsaXplZFVzZXJPcHRpb25zLFxuICAgICAgICAgICAgY29uZmlnRW52OiBjb25maWdFbnYsXG4gICAgICAgICAgICBobXJDaGFubmVsLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmICghY3VycmVudFdvcmtlcikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkZhaWxlZCB0byBzdGFydCB3b3JrZXJcIik7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTm90aWZ5IGFib3V0IHdvcmtlciBjcmVhdGlvblxuICAgICAgICBvbldvcmtlckNyZWF0ZWQ/LihjdXJyZW50V29ya2VyLCByZXN0YXJ0V29ya2VyRm9ySE1SKTtcblxuICAgICAgICBjb25zdCBzdHJlYW0gPSBoYW5kbGVSc2NTdHJlYW0oe1xuICAgICAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgICAgIC4uLnNlcmlhbGl6ZWRVc2VyT3B0aW9ucyxcbiAgICAgICAgICAgIHdvcmtlcjogY3VycmVudFdvcmtlcixcbiAgICAgICAgICAgIGlkOiBpbmZvLnJvdXRlLFxuICAgICAgICAgICAgdHlwZTogXCJJTklUXCIsXG4gICAgICAgICAgICBsb2dnZXIsXG4gICAgICAgICAgICAvLyB3ZSBtYWtlIHRoZSB3b3JrZXIgc3RyZWFtIGF3YXJlIG9mIHRoZSByb3V0ZSwgcGFnZVBhdGgsIHByb3BzUGF0aCwgcm9vdFBhdGgsIGh0bWxQYXRoXG4gICAgICAgICAgICByb3V0ZTogaW5mby5yb3V0ZSxcbiAgICAgICAgICAgIHVybDogaW5mby51cmwsXG4gICAgICAgICAgICBwYWdlUGF0aDogcGFnZVBhdGgsXG4gICAgICAgICAgICBwcm9wc1BhdGg6IHByb3BzUGF0aCxcbiAgICAgICAgICAgIC8vIFBhc3MgcHJlLXJlc29sdmVkIHByb3BzIChsb2FkZWQgdmlhIFZpdGUncyBzc3JMb2FkTW9kdWxlIGZvciBwcm9wZXIgdHJhbnNmb3JtcylcbiAgICAgICAgICAgIHJlc29sdmVkUGFnZVByb3BzOiByZXNvbHZlZFBhZ2VQcm9wcyxcbiAgICAgICAgICAgIHJvb3RQYXRoOiByb290UGF0aCxcbiAgICAgICAgICAgIC8vIENSSVRJQ0FMOiBGb3IgUlNDIHJlcXVlc3RzLCB1c2UgaHRtbFBhdGg6IFwiXCIgZm9yIGhlYWRsZXNzIG1vZGUgKG5vIEh0bWwgd3JhcHBlcilcbiAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgaHlkcmF0aW9uIGVycm9ycyB3aGVyZSA8aHRtbD4gd291bGQgYmUgcmVuZGVyZWQgaW5zaWRlICNyb290IGRpdlxuICAgICAgICAgICAgaHRtbFBhdGg6IFwiXCIsICAvLyBFbXB0eSBzdHJpbmcgPSBoZWFkbGVzcyBSU0MgKG5vIEh0bWwgd3JhcHBlcilcbiAgICAgICAgICAgIC8vIENvbXBvbmVudCBvdmVycmlkZXMgKHVuZGVmaW5lZCBmb3IgZmlsZS1iYXNlZCBjb21wb25lbnRzIGluIGNsaWVudCBkZXYpXG4gICAgICAgICAgICBIdG1sQ29tcG9uZW50OiB1bmRlZmluZWQsXG4gICAgICAgICAgICBSb290Q29tcG9uZW50OiB1bmRlZmluZWQsXG4gICAgICAgICAgICAvLyBVc2UgdXNlck9wdGlvbnMucHJvamVjdFJvb3QgaWYgYXZhaWxhYmxlLCBvdGhlcndpc2UgZmFsbCBiYWNrIHRvIHNlcnZlci5jb25maWcucm9vdFxuICAgICAgICAgICAgcHJvamVjdFJvb3Q6IHNlcmlhbGl6ZWRVc2VyT3B0aW9ucy5wcm9qZWN0Um9vdCB8fCBzZXJ2ZXIuY29uZmlnLnJvb3QsXG4gICAgICAgICAgICBidWlsZDoge1xuICAgICAgICAgICAgICAuLi4oc2VyaWFsaXplZFVzZXJPcHRpb25zLmJ1aWxkIHx8IHt9KSxcbiAgICAgICAgICAgICAgcGFnZXM6IEFycmF5LmlzQXJyYXkoc2VyaWFsaXplZFVzZXJPcHRpb25zLmJ1aWxkPy5wYWdlcylcbiAgICAgICAgICAgICAgICA/IHNlcmlhbGl6ZWRVc2VyT3B0aW9ucy5idWlsZC5wYWdlc1xuICAgICAgICAgICAgICAgIDogW10sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbWFuaWZlc3Q6IHt9LFxuICAgICAgICAgICAgY3NzRmlsZXM6IG5ldyBNYXAoKSxcbiAgICAgICAgICAgIGdsb2JhbENzczogbmV3IE1hcCgpLFxuICAgICAgICAgICAgc2VydmVyUGlwZWFibGVTdHJlYW1PcHRpb25zOiBzZXJpYWxpemVkVXNlck9wdGlvbnMuc2VydmVyUGlwZWFibGVTdHJlYW1PcHRpb25zLFxuICAgICAgICAgICAgY2xpZW50UGlwZWFibGVTdHJlYW1PcHRpb25zOiBzZXJpYWxpemVkVXNlck9wdGlvbnMuY2xpZW50UGlwZWFibGVTdHJlYW1PcHRpb25zLFxuICAgICAgICAgIH0gYXMgYW55LFxuICAgICAgICAgIGhhbmRsZXJzOiB7XG4gICAgICAgICAgICBvbk1ldHJpY3M6IChpZCwgbWV0cmljcykgPT4ge1xuICAgICAgICAgICAgICBtZXRyaWNzLnJvdXRlID0gaWQ7XG4gICAgICAgICAgICAgIHVzZXJPbk1ldHJpY3M/LihtZXRyaWNzKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvbkhtckFjY2VwdDogKCkgPT4ge1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9uSG1yVXBkYXRlOiAoKSA9PiB7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgLy8gQWx3YXlzIGxvZyBzaGVsbCBlcnJvcnMuIFdpdGhvdXQgdGhpcyBhbiBSU0MgcmVuZGVyIGZhaWx1cmUgaW5cbiAgICAgICAgICAgIC8vIHRoZSB3b3JrZXIgd291bGQgc3VyZmFjZSBvbmx5IHZpYSBgdmVyYm9zZTogdHJ1ZWAsIGxlYXZpbmcgdGhlXG4gICAgICAgICAgICAvLyB1c2VyIHdpdGggYSBoYWxmLXN0cmVhbWVkIFJTQyByZXNwb25zZSBhbmQgbm8gZXhwbGFuYXRpb24uXG4gICAgICAgICAgICBvblNoZWxsRXJyb3I6IChpZCwgZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgICAgIGBbY29uZmlndXJlUmVxdWVzdEhhbmRsZXI6JHtpZH1dIFJTQyBzaGVsbCBlcnJvcjogJHtlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcil9YCxcbiAgICAgICAgICAgICAgICB7IGVycm9yOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IgOiBuZXcgRXJyb3IoU3RyaW5nKGVycm9yKSkgfSxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgICAuLi5oYW5kbGVyT3B0aW9ucyxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gUGlwZSB0aGUgc3RyZWFtIHRvIHRoZSByZXNwb25zZSB1c2luZyB0aGUgaGVscGVyXG4gICAgICAgIHBpcGVUb1Jlc3BvbnNlKHtcbiAgICAgICAgICBzdHJlYW0sXG4gICAgICAgICAgcmVzcG9uc2U6IHJlcyxcbiAgICAgICAgICBjb250ZW50VHlwZTogaW5mby5jb250ZW50VHlwZSxcbiAgICAgICAgICBsb2dnZXIsXG4gICAgICAgICAgdmVyYm9zZTogaGFuZGxlck9wdGlvbnMudmVyYm9zZSxcbiAgICAgICAgICBwYW5pY1RocmVzaG9sZDogaGFuZGxlck9wdGlvbnMucGFuaWNUaHJlc2hvbGQsXG4gICAgICAgICAgY29udGV4dDogXCJjb25maWd1cmVXb3JrZXJSZXF1ZXN0SGFuZGxlclwiLFxuICAgICAgICB9KTtcbiAgICAgICAgLy8gUmVzcG9uc2UgaXMgbm93IGJlaW5nIHN0cmVhbWVkIC0gbm8gbmVlZCB0byB3YWl0IGZvciB0aW1lb3V0XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAvLyBBbHdheXMgbG9nOiBtaXNjb25maWd1cmVkIGFwcHMgd291bGQgb3RoZXJ3aXNlIHJldHVybiBhbiBlbXB0eSA1MDBcbiAgICAgICAgLy8gYW5kIGxlYXZlIHRoZSB1c2VyIHN0YXJpbmcgYXQgYSBodW5nIHRhYiB3aXRob3V0IGFueSBjb25zb2xlIG91dHB1dC5cbiAgICAgICAgY29uc3QgcGFuaWNFcnJvciA9IGhhbmRsZUVycm9yKHtcbiAgICAgICAgICBlcnJvcixcbiAgICAgICAgICBsb2dnZXIsXG4gICAgICAgICAgbW9kZTogZ2V0Tm9kZUVudihzZXJ2ZXIuY29uZmlnLm1vZGUpLFxuICAgICAgICAgIHBhbmljVGhyZXNob2xkOiBoYW5kbGVyT3B0aW9ucy5wYW5pY1RocmVzaG9sZCxcbiAgICAgICAgICBjcml0aWNhbDogZmFsc2UsXG4gICAgICAgICAgY29udGV4dDogXCJjb25maWd1cmVXb3JrZXJSZXF1ZXN0SGFuZGxlclwiLFxuICAgICAgICAgIGxvZzogdHJ1ZSxcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChwYW5pY0Vycm9yICE9IG51bGwpIHtcbiAgICAgICAgICB0aHJvdyBwYW5pY0Vycm9yO1xuICAgICAgICB9XG4gICAgICAgIGlmICghcmVzLmhlYWRlcnNTZW50KSB7XG4gICAgICAgICAgcmVzLnN0YXR1c0NvZGUgPSA1MDA7XG4gICAgICAgICAgcmVzLnNldEhlYWRlcihcIkNvbnRlbnQtVHlwZVwiLCBcInRleHQvcGxhaW47IGNoYXJzZXQ9dXRmLThcIik7XG4gICAgICAgICAgY29uc3QgbWVzc2FnZSA9IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKTtcbiAgICAgICAgICByZXMuZW5kKGBSU0MgcmVuZGVyIGZhaWxlZDogJHttZXNzYWdlfVxcbmApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlcy5lbmQoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG4gICAgLy8gYXR0YWNoIGhhbmRsZXIgdG8gdGhlIHNlcnZlclxuICAgIHNlcnZlci5taWRkbGV3YXJlcy51c2UoaGFuZGxlcik7XG4gICAgLy8gcG9ydCBjaGVjaywgc2hvdWxkIGJlIGhhbmRsZWQgYnkgc3RyaWN0UG9ydFxuICB9O1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQXVCYSxNQUFBLHVCQUFBLEdBQ1gsZUFBZSw4QkFBK0IsQ0FBQTtBQUFBLEVBQzVDLE1BQUE7QUFBQSxFQUNBLG1CQUFBO0FBQUEsRUFDQSxXQUFhLEVBQUEsWUFBQTtBQUFBLEVBQ2IsU0FBQTtBQUFBLEVBQ0EsVUFBQTtBQUFBLEVBQ0E7QUFDRixDQUFHLEVBQUE7QUFDRCxFQUFBLE1BQU0sTUFBUyxHQUFBLE1BQUEsQ0FBTyxNQUFPLENBQUEsWUFBQSxJQUFnQixPQUFPLE1BQU8sQ0FBQSxNQUFBO0FBQzNELEVBQU0sTUFBQTtBQUFBO0FBQUEsSUFFSixhQUFlLEVBQUEsY0FBQTtBQUFBLElBQ2YsR0FBRztBQUFBLEdBQ0QsR0FBQSxZQUFBO0FBQ0osRUFBQSxNQUFNLGNBQWlCLEdBQUEsTUFBQSxDQUFPLE1BQU8sQ0FBQSxJQUFJLGtCQUFvQixFQUFBO0FBQUEsSUFDM0QsYUFBQSxFQUFlLE9BQU8sTUFBTyxDQUFBLElBQUE7QUFBQSxJQUM3QixXQUFhLEVBQUEsWUFBQSxDQUFhLFdBQWUsSUFBQSxNQUFBLENBQU8sTUFBTyxDQUFBLElBQUE7QUFBQSxJQUN2RDtBQUFBLEdBQ0QsQ0FBQTtBQUdELEVBQXdCLHVCQUFBLENBQUE7QUFBQSxJQUN0QixnQkFBZ0IsY0FBZSxDQUFBLGNBQUE7QUFBQSxJQUMvQixNQUFB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