vite-plugin-react-server
Version:
Vite plugin for React Server Components (RSC)
306 lines (303 loc) • 42.1 kB
JavaScript
/**
* 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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