UNPKG

vite-plugin-react-server

Version:
164 lines (161 loc) 24.9 kB
/** * vite-plugin-react-server * Copyright (c) Nico Brinkkemper * MIT License */ import { resolve } from 'node:path'; import 'vite'; import { MIME_TYPES } from '../config/mimeTypes.js'; import { requestToRoute } from './requestToRoute.js'; import { routeToURL } from '../utils/routeToURL.js'; function requestInfo(req, handlerOptions, hostDir) { const route = requestToRoute(req, { moduleBasePath: handlerOptions.moduleBasePath, moduleBaseURL: handlerOptions.moduleBaseURL, build: handlerOptions.build }); if (!route) { return { route: "/", url: routeToURL("/", handlerOptions.moduleBaseURL, handlerOptions.build.rscOutputPath), ext: "" }; } const [, value] = handlerOptions.normalizer(route); if (handlerOptions.verbose) { if (value && value !== "") { handlerOptions.logger.info(`[requestInfo] Value: "${value}"`); } if (hostDir && hostDir !== "") { handlerOptions.logger.info(`[requestInfo] Host Dir: "${hostDir}"`); } if (req.url && req.url !== "") { handlerOptions.logger.info(`[requestInfo] Request URL: "${req.url}"`); } } const dotIndex = value.lastIndexOf("."); const ext = dotIndex === -1 ? "" : value.slice(dotIndex); const isVendor = handlerOptions.autoDiscover.vendorPattern.test(value); const isVirtual = handlerOptions.autoDiscover.virtualPattern.test(value); const isJS = handlerOptions.autoDiscover.modulePattern.test(value); const isHtml = handlerOptions.autoDiscover.htmlPattern.test(value); const isCss = handlerOptions.autoDiscover.cssPattern.test(value); const isJson = handlerOptions.autoDiscover.jsonPattern.test(value); const isRsc = handlerOptions.autoDiscover.rscPattern.test(value); const hasJsHeader = req.headers["sec-fetch-dest"] === "script" || req.headers["accept"]?.includes("*/*") || req.headers["accept"]?.includes("text/javascript"); const hasJsonHeader = req.headers["accept"]?.includes("application/json"); const hasHtmlHeader = req.headers.accept?.includes("text/html"); const hasRscHeader = req.headers.accept?.includes("text/x-component"); const hasRscQueryParam = /[?&]_rsc\b/.test(req.url || ""); const hasCssHeader = req.headers.accept?.includes("text/css"); const isFolder = !ext; const isFormContentType = req.headers["content-type"]?.includes( "application/x-www-form-urlencoded" ) || !!req.headers["content-type"]?.includes("multipart/form-data"); const hasRscActionHeader = !!req.headers["x-rsc-action"]; const hasServerActionHeaders = req.method === "POST" && (hasRscActionHeader || (req.headers["sec-fetch-dest"] === "empty" || req.headers["sec-fetch-dest"] === "") && req.headers["sec-fetch-mode"] === "cors"); const isServerActionRequest = hasServerActionHeaders; const isFormActionRequest = !isServerActionRequest && (req.method === "POST" || isFormContentType && req.headers["sec-fetch-dest"] === "document" && req.headers["sec-fetch-mode"] === "navigate"); const isJsRequest = !isFormActionRequest && !isJson && !isHtml && !isCss && !isRsc && (isJS || hasJsHeader); const isJsonRequest = isJson || hasJsonHeader && !isJsRequest; const isHtmlRequest = !hasRscQueryParam && (isHtml || hasHtmlHeader || isFolder && !hasRscHeader && !isRsc && !isJsRequest && !isFormActionRequest); const isRscRequest = hasRscQueryParam || !isJsRequest && !isHtmlRequest && (isRsc || hasRscHeader); const isCssRequest = !isHtmlRequest && !isRscRequest && !isJsRequest && !isJsonRequest && (isCss || hasCssHeader); const routeForFilePath = value; let filePath = resolve(hostDir, routeForFilePath); let contentType; if (isServerActionRequest) { filePath = resolve(hostDir, routeForFilePath); contentType = "application/json; charset=utf-8"; } else if (isHtmlRequest) { if (!isHtml) { filePath = resolve( hostDir, routeForFilePath, handlerOptions.build.htmlOutputPath ); } contentType = "text/html; charset=utf-8"; } else if (isRscRequest) { if (!isRsc) { filePath = resolve( hostDir, routeForFilePath, handlerOptions.build.rscOutputPath ); } contentType = "text/x-component; charset=utf-8"; } else if (isCssRequest) { if (!isCss) { filePath = resolve(hostDir, routeForFilePath + ".css"); } contentType = "text/css; charset=utf-8"; } else if (isJsRequest) { if (!isJS) { filePath = resolve(hostDir, routeForFilePath + ".js"); } contentType = "application/javascript; charset=utf-8"; } else if (isJsonRequest) { if (!isJson) { filePath = resolve(hostDir, routeForFilePath + ".json"); } contentType = "application/json; charset=utf-8"; } else { const mimeType = MIME_TYPES[ext]; if (mimeType) { contentType = mimeType + "; charset=utf-8"; } else { contentType = "application/octet-stream"; } } if (handlerOptions.verbose) { if (isFormActionRequest) { handlerOptions.logger.info(`[react-dev-server] (form-action) ${route}`); } else if (isServerActionRequest) { handlerOptions.logger.info(`[react-dev-server] (server-action) ${route}`); } else if (isHtmlRequest) { handlerOptions.logger.info(`[react-dev-server] (html) ${route}`); } else if (isRscRequest) { handlerOptions.logger.info(`[react-dev-server] (rsc) ${route}`); } else if (isCssRequest) { handlerOptions.logger.info(`[react-dev-server] (css) ${route}`); } else if (isJsRequest) { handlerOptions.logger.info(`[react-dev-server] (js) ${route}`); } else if (isJsonRequest) { handlerOptions.logger.info(`[react-dev-server] (json) ${route}`); } else { handlerOptions.logger.info(`[react-dev-server] (other) ${route}`); } } return { route, url: routeToURL(route, handlerOptions.moduleBaseURL, handlerOptions.build.rscOutputPath), ext, isHtmlRequest, isRscRequest, isCssRequest, isCss, isHtml, isRsc, isFolder, contentType, filePath, isJS, isVendor, isVirtual, hasJsHeader, isJsRequest, isJson, isJsonRequest, hasCssHeader, hasJsonHeader, hasHtmlHeader, hasRscHeader, hasServerActionHeaders, isServerActionRequest, isFormContentType, isFormActionRequest }; } export { requestInfo }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxdWVzdEluZm8uanMiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3BsdWdpbi9oZWxwZXJzL3JlcXVlc3RJbmZvLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHJlc29sdmUgfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgdHlwZSB7IENyZWF0ZUhhbmRsZXJPcHRpb25zIH0gZnJvbSBcIi4uL3R5cGVzLmpzXCI7XG5pbXBvcnQgeyB0eXBlIENvbm5lY3QgfSBmcm9tIFwidml0ZVwiO1xuaW1wb3J0IHsgTUlNRV9UWVBFUyB9IGZyb20gXCIuLi9jb25maWcvbWltZVR5cGVzLmpzXCI7XG5pbXBvcnQgeyByZXF1ZXN0VG9Sb3V0ZSB9IGZyb20gXCIuL3JlcXVlc3RUb1JvdXRlLmpzXCI7XG5pbXBvcnQgeyByb3V0ZVRvVVJMIH0gZnJvbSBcIi4uL3V0aWxzL3JvdXRlVG9VUkwuanNcIjtcblxuLyoqXG4gKiAjIFJlcXVlc3QgaW5mb1xuICpcbiAqIERvZXMgdGhlIGluaXRpYWwgd29yayB0byBjaGVjayBpZiB0aGUgcmVxdWVzdCBpcyBmb3IgaHRtbCwgcnNjLCBqc29uLCBqcywgY3NzLCBzZXJ2ZXItYWN0aW9uLCBvciBzb21ldGhpbmcgZWxzZSBub3QgaGFuZGxlZCBieSB0aGlzIHBsdWdpbi5cbiAqXG4gKiBAcGFyYW0gcmVxXG4gKiBAcGFyYW0gaGFuZGxlck9wdGlvbnNcbiAqIEBwYXJhbSBob3N0RGlyXG4gKiBAcmV0dXJuc1xuICovXG5leHBvcnQgZnVuY3Rpb24gcmVxdWVzdEluZm8oXG4gIHJlcTogQ29ubmVjdC5JbmNvbWluZ01lc3NhZ2UsXG4gIGhhbmRsZXJPcHRpb25zOiBQaWNrPFxuICAgIENyZWF0ZUhhbmRsZXJPcHRpb25zLFxuICAgIHwgXCJub3JtYWxpemVyXCJcbiAgICB8IFwiYnVpbGRcIlxuICAgIHwgXCJhdXRvRGlzY292ZXJcIlxuICAgIHwgXCJ2ZXJib3NlXCJcbiAgICB8IFwibW9kdWxlQmFzZVBhdGhcIlxuICAgIHwgXCJtb2R1bGVCYXNlVVJMXCJcbiAgICB8IFwidmVyYm9zZVwiXG4gICAgfCBcImxvZ2dlclwiXG4gID4sXG4gIGhvc3REaXI6IHN0cmluZyxcbikge1xuICBjb25zdCByb3V0ZSA9IHJlcXVlc3RUb1JvdXRlKHJlcSwge1xuICAgIG1vZHVsZUJhc2VQYXRoOiBoYW5kbGVyT3B0aW9ucy5tb2R1bGVCYXNlUGF0aCxcbiAgICBtb2R1bGVCYXNlVVJMOiBoYW5kbGVyT3B0aW9ucy5tb2R1bGVCYXNlVVJMLFxuICAgIGJ1aWxkOiBoYW5kbGVyT3B0aW9ucy5idWlsZCxcbiAgfSk7XG5cbiAgaWYgKCFyb3V0ZSkge1xuICAgIHJldHVybiB7XG4gICAgICByb3V0ZTogXCIvXCIsXG4gICAgICB1cmw6IHJvdXRlVG9VUkwoXCIvXCIsIGhhbmRsZXJPcHRpb25zLm1vZHVsZUJhc2VVUkwsIGhhbmRsZXJPcHRpb25zLmJ1aWxkLnJzY091dHB1dFBhdGgpLFxuICAgICAgZXh0OiBcIlwiLFxuICAgIH07XG4gIH1cblxuICAvLyBVc2UgdGhlIGNsZWFuZWQgcm91dGUgZm9yIG5vcm1hbGl6YXRpb24sIG5vdCB0aGUgcmF3IHJlcS51cmxcbiAgLy8gVGhpcyBlbnN1cmVzIGJhc2UgVVJMIGlzIHByb3Blcmx5IHN0cmlwcGVkIGJlZm9yZSBub3JtYWxpemF0aW9uXG4gIGNvbnN0IFssIHZhbHVlXSA9IGhhbmRsZXJPcHRpb25zLm5vcm1hbGl6ZXIocm91dGUpO1xuICBpZiAoaGFuZGxlck9wdGlvbnMudmVyYm9zZSkge1xuICAgIGlmICh2YWx1ZSAmJiB2YWx1ZSAhPT0gXCJcIikge1xuICAgICAgaGFuZGxlck9wdGlvbnMubG9nZ2VyLmluZm8oYFtyZXF1ZXN0SW5mb10gVmFsdWU6IFxcXCIke3ZhbHVlfVxcXCJgKTtcbiAgICB9XG4gICAgaWYgKGhvc3REaXIgJiYgaG9zdERpciAhPT0gXCJcIikge1xuICAgICAgaGFuZGxlck9wdGlvbnMubG9nZ2VyLmluZm8oYFtyZXF1ZXN0SW5mb10gSG9zdCBEaXI6IFxcXCIke2hvc3REaXJ9XFxcImApO1xuICAgIH1cbiAgICBpZiAocmVxLnVybCAmJiByZXEudXJsICE9PSBcIlwiKSB7XG4gICAgICBoYW5kbGVyT3B0aW9ucy5sb2dnZXIuaW5mbyhgW3JlcXVlc3RJbmZvXSBSZXF1ZXN0IFVSTDogXFxcIiR7cmVxLnVybH1cXFwiYCk7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgZG90SW5kZXggPSB2YWx1ZS5sYXN0SW5kZXhPZihcIi5cIik7XG4gIGNvbnN0IGV4dCA9IGRvdEluZGV4ID09PSAtMSA/IFwiXCIgOiB2YWx1ZS5zbGljZShkb3RJbmRleCk7XG4gIC8vIGhhbmRsZSBpbmRleC5odG1sXG4gIGNvbnN0IGlzVmVuZG9yID0gaGFuZGxlck9wdGlvbnMuYXV0b0Rpc2NvdmVyLnZlbmRvclBhdHRlcm4udGVzdCh2YWx1ZSk7XG4gIGNvbnN0IGlzVmlydHVhbCA9IGhhbmRsZXJPcHRpb25zLmF1dG9EaXNjb3Zlci52aXJ0dWFsUGF0dGVybi50ZXN0KHZhbHVlKTtcbiAgY29uc3QgaXNKUyA9IGhhbmRsZXJPcHRpb25zLmF1dG9EaXNjb3Zlci5tb2R1bGVQYXR0ZXJuLnRlc3QodmFsdWUpO1xuICBjb25zdCBpc0h0bWwgPSBoYW5kbGVyT3B0aW9ucy5hdXRvRGlzY292ZXIuaHRtbFBhdHRlcm4udGVzdCh2YWx1ZSk7XG4gIGNvbnN0IGlzQ3NzID0gaGFuZGxlck9wdGlvbnMuYXV0b0Rpc2NvdmVyLmNzc1BhdHRlcm4udGVzdCh2YWx1ZSk7XG4gIGNvbnN0IGlzSnNvbiA9IGhhbmRsZXJPcHRpb25zLmF1dG9EaXNjb3Zlci5qc29uUGF0dGVybi50ZXN0KHZhbHVlKTtcbiAgY29uc3QgaXNSc2MgPSBoYW5kbGVyT3B0aW9ucy5hdXRvRGlzY292ZXIucnNjUGF0dGVybi50ZXN0KHZhbHVlKTtcbiAgY29uc3QgaGFzSnNIZWFkZXIgPVxuICAgIHJlcS5oZWFkZXJzW1wic2VjLWZldGNoLWRlc3RcIl0gPT09IFwic2NyaXB0XCIgfHxcbiAgICByZXEuaGVhZGVyc1tcImFjY2VwdFwiXT8uaW5jbHVkZXMoXCIqLypcIikgfHxcbiAgICByZXEuaGVhZGVyc1tcImFjY2VwdFwiXT8uaW5jbHVkZXMoXCJ0ZXh0L2phdmFzY3JpcHRcIik7XG4gIGNvbnN0IGhhc0pzb25IZWFkZXIgPSByZXEuaGVhZGVyc1tcImFjY2VwdFwiXT8uaW5jbHVkZXMoXCJhcHBsaWNhdGlvbi9qc29uXCIpO1xuICBjb25zdCBoYXNIdG1sSGVhZGVyID0gcmVxLmhlYWRlcnMuYWNjZXB0Py5pbmNsdWRlcyhcInRleHQvaHRtbFwiKTtcbiAgY29uc3QgaGFzUnNjSGVhZGVyID0gcmVxLmhlYWRlcnMuYWNjZXB0Py5pbmNsdWRlcyhcInRleHQveC1jb21wb25lbnRcIik7XG4gIC8vIFN1cHBvcnQgP19yc2MgcXVlcnkgcGFyYW0gKGUuZy4gLz9fcnNjIGZvciBicm93c2VyIGRlYnVnZ2luZykgYXMgYWx0ZXJuYXRpdmUgdG8gQWNjZXB0IGhlYWRlciAodXNlZnVsIGZvciBicm93c2VyIGRlYnVnZ2luZylcbiAgY29uc3QgaGFzUnNjUXVlcnlQYXJhbSA9IC9bPyZdX3JzY1xcYi8udGVzdChyZXEudXJsIHx8IFwiXCIpO1xuICBjb25zdCBoYXNDc3NIZWFkZXIgPSByZXEuaGVhZGVycy5hY2NlcHQ/LmluY2x1ZGVzKFwidGV4dC9jc3NcIik7XG4gIGNvbnN0IGlzRm9sZGVyID0gIWV4dDtcbiAgY29uc3QgaXNGb3JtQ29udGVudFR5cGUgPVxuICAgIHJlcS5oZWFkZXJzW1wiY29udGVudC10eXBlXCJdPy5pbmNsdWRlcyhcbiAgICAgIFwiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkXCJcbiAgICApIHx8ICEhcmVxLmhlYWRlcnNbXCJjb250ZW50LXR5cGVcIl0/LmluY2x1ZGVzKFwibXVsdGlwYXJ0L2Zvcm0tZGF0YVwiKTtcblxuICAvLyBTZXJ2ZXIgYWN0aW9uIGRldGVjdGlvblxuICBjb25zdCBoYXNSc2NBY3Rpb25IZWFkZXIgPSAhIXJlcS5oZWFkZXJzW1wieC1yc2MtYWN0aW9uXCJdO1xuICBjb25zdCBoYXNTZXJ2ZXJBY3Rpb25IZWFkZXJzID1cbiAgICByZXEubWV0aG9kID09PSBcIlBPU1RcIiAmJlxuICAgIChoYXNSc2NBY3Rpb25IZWFkZXIgfHwgKFxuICAgICAgKHJlcS5oZWFkZXJzW1wic2VjLWZldGNoLWRlc3RcIl0gPT09IFwiZW1wdHlcIiB8fFxuICAgICAgICByZXEuaGVhZGVyc1tcInNlYy1mZXRjaC1kZXN0XCJdID09PSBcIlwiKSAmJlxuICAgICAgcmVxLmhlYWRlcnNbXCJzZWMtZmV0Y2gtbW9kZVwiXSA9PT0gXCJjb3JzXCJcbiAgICApKTtcbiAgY29uc3QgaXNTZXJ2ZXJBY3Rpb25SZXF1ZXN0ID0gaGFzU2VydmVyQWN0aW9uSGVhZGVycztcblxuICBjb25zdCBpc0Zvcm1BY3Rpb25SZXF1ZXN0ID1cbiAgICAhaXNTZXJ2ZXJBY3Rpb25SZXF1ZXN0ICYmXG4gICAgKHJlcS5tZXRob2QgPT09IFwiUE9TVFwiIHx8XG4gICAgICAoaXNGb3JtQ29udGVudFR5cGUgJiZcbiAgICAgICAgcmVxLmhlYWRlcnNbXCJzZWMtZmV0Y2gtZGVzdFwiXSA9PT0gXCJkb2N1bWVudFwiICYmXG4gICAgICAgIHJlcS5oZWFkZXJzW1wic2VjLWZldGNoLW1vZGVcIl0gPT09IFwibmF2aWdhdGVcIikpO1xuXG4gIGNvbnN0IGlzSnNSZXF1ZXN0ID1cbiAgICAhaXNGb3JtQWN0aW9uUmVxdWVzdCAmJlxuICAgICFpc0pzb24gJiZcbiAgICAhaXNIdG1sICYmXG4gICAgIWlzQ3NzICYmXG4gICAgIWlzUnNjICYmXG4gICAgKGlzSlMgfHwgaGFzSnNIZWFkZXIpO1xuICBjb25zdCBpc0pzb25SZXF1ZXN0ID0gaXNKc29uIHx8IChoYXNKc29uSGVhZGVyICYmICFpc0pzUmVxdWVzdCk7XG4gIC8vIEZvcm0gYWN0aW9uIGRldGVjdGlvblxuXG4gIGNvbnN0IGlzSHRtbFJlcXVlc3QgPVxuICAgICFoYXNSc2NRdWVyeVBhcmFtICYmIChpc0h0bWwgfHxcbiAgICBoYXNIdG1sSGVhZGVyIHx8XG4gICAgKGlzRm9sZGVyICYmXG4gICAgICAhaGFzUnNjSGVhZGVyICYmXG4gICAgICAhaXNSc2MgJiZcbiAgICAgICFpc0pzUmVxdWVzdCAmJlxuICAgICAgIWlzRm9ybUFjdGlvblJlcXVlc3QpKTtcbiAgY29uc3QgaXNSc2NSZXF1ZXN0ID1cbiAgICBoYXNSc2NRdWVyeVBhcmFtIHx8ICghaXNKc1JlcXVlc3QgJiYgIWlzSHRtbFJlcXVlc3QgJiYgKGlzUnNjIHx8IGhhc1JzY0hlYWRlcikpO1xuICBjb25zdCBpc0Nzc1JlcXVlc3QgPVxuICAgICFpc0h0bWxSZXF1ZXN0ICYmXG4gICAgIWlzUnNjUmVxdWVzdCAmJlxuICAgICFpc0pzUmVxdWVzdCAmJlxuICAgICFpc0pzb25SZXF1ZXN0ICYmXG4gICAgKGlzQ3NzIHx8IGhhc0Nzc0hlYWRlcik7XG5cbiAgLy8gVXNlIHRoZSBub3JtYWxpemVkIHZhbHVlIGZvciBmaWxlIHBhdGggY29uc3RydWN0aW9uXG4gIC8vIFRoZSBub3JtYWxpemVyIHNob3VsZCBoYXZlIGFscmVhZHkgc3RyaXBwZWQgYmFzZSBVUkxzIHByb3Blcmx5XG4gIGNvbnN0IHJvdXRlRm9yRmlsZVBhdGggPSB2YWx1ZTtcblxuICBsZXQgZmlsZVBhdGggPSByZXNvbHZlKGhvc3REaXIsIHJvdXRlRm9yRmlsZVBhdGgpO1xuICBsZXQgY29udGVudFR5cGU7XG4gIGlmIChpc1NlcnZlckFjdGlvblJlcXVlc3QpIHtcbiAgICAvLyBGb3Igc2VydmVyIGFjdGlvbnMsIHdlJ2xsIGdldCB0aGUgYWN0dWFsIGZpbGUgcGF0aCBmcm9tIHRoZSByZXF1ZXN0IGJvZHlcbiAgICAvLyBUaGUgcm91dGUgaXMganVzdCBhIHBsYWNlaG9sZGVyXG4gICAgZmlsZVBhdGggPSByZXNvbHZlKGhvc3REaXIsIHJvdXRlRm9yRmlsZVBhdGgpO1xuICAgIGNvbnRlbnRUeXBlID0gXCJhcHBsaWNhdGlvbi9qc29uOyBjaGFyc2V0PXV0Zi04XCI7XG4gIH0gZWxzZSBpZiAoaXNIdG1sUmVxdWVzdCkge1xuICAgIGlmICghaXNIdG1sKSB7XG4gICAgICBmaWxlUGF0aCA9IHJlc29sdmUoXG4gICAgICAgIGhvc3REaXIsXG4gICAgICAgIHJvdXRlRm9yRmlsZVBhdGgsXG4gICAgICAgIGhhbmRsZXJPcHRpb25zLmJ1aWxkLmh0bWxPdXRwdXRQYXRoXG4gICAgICApO1xuICAgIH1cbiAgICBjb250ZW50VHlwZSA9IFwidGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04XCI7XG4gIH0gZWxzZSBpZiAoaXNSc2NSZXF1ZXN0KSB7XG4gICAgaWYgKCFpc1JzYykge1xuICAgICAgLy8gVmFsdWUgZG9lc24ndCBlbmQgd2l0aCAucnNjLCBhcHBlbmQgdGhlIHJzYyBvdXRwdXQgcGF0aFxuICAgICAgZmlsZVBhdGggPSByZXNvbHZlKFxuICAgICAgICBob3N0RGlyLFxuICAgICAgICByb3V0ZUZvckZpbGVQYXRoLFxuICAgICAgICBoYW5kbGVyT3B0aW9ucy5idWlsZC5yc2NPdXRwdXRQYXRoXG4gICAgICApO1xuICAgIH1cbiAgICBjb250ZW50VHlwZSA9IFwidGV4dC94LWNvbXBvbmVudDsgY2hhcnNldD11dGYtOFwiO1xuICB9IGVsc2UgaWYgKGlzQ3NzUmVxdWVzdCkge1xuICAgIGlmICghaXNDc3MpIHtcbiAgICAgIGZpbGVQYXRoID0gcmVzb2x2ZShob3N0RGlyLCByb3V0ZUZvckZpbGVQYXRoICsgXCIuY3NzXCIpO1xuICAgIH1cbiAgICBjb250ZW50VHlwZSA9IFwidGV4dC9jc3M7IGNoYXJzZXQ9dXRmLThcIjtcbiAgfSBlbHNlIGlmIChpc0pzUmVxdWVzdCkge1xuICAgIGlmICghaXNKUykge1xuICAgICAgZmlsZVBhdGggPSByZXNvbHZlKGhvc3REaXIsIHJvdXRlRm9yRmlsZVBhdGggKyBcIi5qc1wiKTtcbiAgICB9XG4gICAgY29udGVudFR5cGUgPSBcImFwcGxpY2F0aW9uL2phdmFzY3JpcHQ7IGNoYXJzZXQ9dXRmLThcIjtcbiAgfSBlbHNlIGlmIChpc0pzb25SZXF1ZXN0KSB7XG4gICAgaWYgKCFpc0pzb24pIHtcbiAgICAgIGZpbGVQYXRoID0gcmVzb2x2ZShob3N0RGlyLCByb3V0ZUZvckZpbGVQYXRoICsgXCIuanNvblwiKTtcbiAgICB9XG4gICAgY29udGVudFR5cGUgPSBcImFwcGxpY2F0aW9uL2pzb247IGNoYXJzZXQ9dXRmLThcIjtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBtaW1lVHlwZSA9IE1JTUVfVFlQRVNbZXh0XTtcbiAgICBpZiAobWltZVR5cGUpIHtcbiAgICAgIGNvbnRlbnRUeXBlID0gbWltZVR5cGUgKyBcIjsgY2hhcnNldD11dGYtOFwiO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb250ZW50VHlwZSA9IFwiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtXCI7XG4gICAgfVxuICB9XG5cbiAgaWYgKGhhbmRsZXJPcHRpb25zLnZlcmJvc2UpIHtcbiAgICBpZiAoaXNGb3JtQWN0aW9uUmVxdWVzdCkge1xuICAgICAgaGFuZGxlck9wdGlvbnMubG9nZ2VyLmluZm8oYFtyZWFjdC1kZXYtc2VydmVyXSAoZm9ybS1hY3Rpb24pICR7cm91dGV9YCk7XG4gICAgfSBlbHNlIGlmIChpc1NlcnZlckFjdGlvblJlcXVlc3QpIHtcbiAgICAgIGhhbmRsZXJPcHRpb25zLmxvZ2dlci5pbmZvKGBbcmVhY3QtZGV2LXNlcnZlcl0gKHNlcnZlci1hY3Rpb24pICR7cm91dGV9YCk7XG4gICAgfSBlbHNlIGlmIChpc0h0bWxSZXF1ZXN0KSB7XG4gICAgICBoYW5kbGVyT3B0aW9ucy5sb2dnZXIuaW5mbyhgW3JlYWN0LWRldi1zZXJ2ZXJdIChodG1sKSAke3JvdXRlfWApO1xuICAgIH0gZWxzZSBpZiAoaXNSc2NSZXF1ZXN0KSB7XG4gICAgICBoYW5kbGVyT3B0aW9ucy5sb2dnZXIuaW5mbyhgW3JlYWN0LWRldi1zZXJ2ZXJdIChyc2MpICR7cm91dGV9YCk7XG4gICAgfSBlbHNlIGlmIChpc0Nzc1JlcXVlc3QpIHtcbiAgICAgIGhhbmRsZXJPcHRpb25zLmxvZ2dlci5pbmZvKGBbcmVhY3QtZGV2LXNlcnZlcl0gKGNzcykgJHtyb3V0ZX1gKTtcbiAgICB9IGVsc2UgaWYgKGlzSnNSZXF1ZXN0KSB7XG4gICAgICBoYW5kbGVyT3B0aW9ucy5sb2dnZXIuaW5mbyhgW3JlYWN0LWRldi1zZXJ2ZXJdIChqcykgJHtyb3V0ZX1gKTtcbiAgICB9IGVsc2UgaWYgKGlzSnNvblJlcXVlc3QpIHtcbiAgICAgIGhhbmRsZXJPcHRpb25zLmxvZ2dlci5pbmZvKGBbcmVhY3QtZGV2LXNlcnZlcl0gKGpzb24pICR7cm91dGV9YCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGhhbmRsZXJPcHRpb25zLmxvZ2dlci5pbmZvKGBbcmVhY3QtZGV2LXNlcnZlcl0gKG90aGVyKSAke3JvdXRlfWApO1xuICAgIH1cbiAgfVxuICByZXR1cm4ge1xuICAgIHJvdXRlLFxuICAgIHVybDogcm91dGVUb1VSTChyb3V0ZSwgaGFuZGxlck9wdGlvbnMubW9kdWxlQmFzZVVSTCwgaGFuZGxlck9wdGlvbnMuYnVpbGQucnNjT3V0cHV0UGF0aCksXG4gICAgZXh0LFxuICAgIGlzSHRtbFJlcXVlc3QsXG4gICAgaXNSc2NSZXF1ZXN0LFxuICAgIGlzQ3NzUmVxdWVzdCxcbiAgICBpc0NzcyxcbiAgICBpc0h0bWwsXG4gICAgaXNSc2MsXG4gICAgaXNGb2xkZXIsXG4gICAgY29udGVudFR5cGUsXG4gICAgZmlsZVBhdGgsXG4gICAgaXNKUyxcbiAgICBpc1ZlbmRvcixcbiAgICBpc1ZpcnR1YWwsXG4gICAgaGFzSnNIZWFkZXIsXG4gICAgaXNKc1JlcXVlc3QsXG4gICAgaXNKc29uLFxuICAgIGlzSnNvblJlcXVlc3QsXG4gICAgaGFzQ3NzSGVhZGVyLFxuICAgIGhhc0pzb25IZWFkZXIsXG4gICAgaGFzSHRtbEhlYWRlcixcbiAgICBoYXNSc2NIZWFkZXIsXG4gICAgaGFzU2VydmVyQWN0aW9uSGVhZGVycyxcbiAgICBpc1NlcnZlckFjdGlvblJlcXVlc3QsXG4gICAgaXNGb3JtQ29udGVudFR5cGUsXG4gICAgaXNGb3JtQWN0aW9uUmVxdWVzdCxcbiAg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