vite-plugin-react-server
Version:
Vite plugin for React Server Components (RSC)
322 lines (318 loc) • 44.9 kB
JavaScript
/**
* vite-plugin-react-server
* Copyright (c) Nico Brinkkemper
* MIT License
*/
import { Worker } from 'node:worker_threads';
import { getNodePath, getMode } from '../config/getPaths.js';
import { getCondition } from '../config/getCondition.js';
import { join } from 'node:path';
import { existsSync } from 'node:fs';
import { pluginRoot } from '../root.js';
import { DEFAULT_CONFIG } from '../config/defaults.js';
import { createLogger } from 'vite';
import { handleError } from '../error/handleError.js';
import { toError } from '../error/toError.js';
const activeWorkers = /* @__PURE__ */ new Set();
async function shutdownAllWorkers(timeout = 1e3) {
if (activeWorkers.size === 0) return;
const shutdownPromises = Array.from(activeWorkers).map((worker) => {
return new Promise((resolve) => {
let messageHandler;
const timeoutId = setTimeout(() => {
worker.removeListener("message", messageHandler);
worker.removeAllListeners();
try {
worker.terminate();
} catch (error) {
}
activeWorkers.delete(worker);
resolve();
}, timeout);
messageHandler = (message) => {
if (message.type === "SHUTDOWN_COMPLETE") {
clearTimeout(timeoutId);
worker.removeListener("message", messageHandler);
worker.removeAllListeners();
activeWorkers.delete(worker);
resolve();
}
};
worker.on("message", messageHandler);
try {
worker.postMessage({
type: "SHUTDOWN",
id: "*"
});
} catch (error) {
clearTimeout(timeoutId);
worker.removeListener("message", messageHandler);
worker.removeAllListeners();
try {
worker.terminate();
} catch (terminateError) {
}
activeWorkers.delete(worker);
resolve();
}
});
});
await Promise.all(shutdownPromises);
activeWorkers.clear();
}
const createWorker = async function _createWorker(options) {
const {
projectRoot = process.cwd(),
nodePath = getNodePath(projectRoot),
currentCondition = getCondition(),
envPrefix = DEFAULT_CONFIG.ENV_PREFIX,
reverseCondition = currentCondition === "react-server" ? "react-client" : "react-server",
maxListeners = 100,
mode = getMode(),
workerPath,
resourceLimits = {
maxOldGenerationSizeMb: 128,
maxYoungGenerationSizeMb: 64
},
htmlChunkSize = 8 * 1024,
transferList = [],
logger = createLogger(),
verbose = false
} = options;
const id = reverseCondition === "react-server" ? "worker/rsc" : "worker/html";
let workerPathWithDefault = typeof workerPath === "string" ? workerPath : void 0;
if (!workerPathWithDefault) {
const isProduction = mode === "production";
const workerFileName = reverseCondition === "react-server" ? `rsc-worker.${isProduction ? "production" : "development"}.js` : `html-worker.${isProduction ? "production" : "development"}.js`;
const sourcePath = join(pluginRoot, id, workerFileName);
if (verbose) {
logger.info(
`[create:${id}] Checking paths - Source: ${sourcePath}, PluginRoot: ${pluginRoot}`
);
}
if (!existsSync(sourcePath)) {
throw new Error(
`[create:${id}] Worker file doesn't exist: ${sourcePath}`
);
} else {
workerPathWithDefault = sourcePath;
if (verbose) {
logger.info(`[create:${id}] Using source worker path: ${sourcePath}`);
}
}
}
if (!workerPathWithDefault.startsWith("/")) {
workerPathWithDefault = join("./", workerPathWithDefault);
}
const workerData = {
...options.workerData,
id: options.workerData.id ?? id
};
try {
if (verbose) {
logger.info(
`[create:${id}] workerData.userOptions.build:
${JSON.stringify(workerData.userOptions?.build)}
Call stack: ${new Error().stack?.split("\n").slice(1, 4).join("\n")}
Creating worker with path: ${workerPathWithDefault}
Node environment: ${mode}
Current condition: ${currentCondition}, Reverse condition: ${reverseCondition}`
);
}
const stripConditionsFromArgv = (argv) => {
const out = [];
for (let i = 0; i < argv.length; i++) {
const arg = argv[i];
if (arg === "--conditions" || arg === "-C") {
i++;
continue;
}
if (arg.startsWith("--conditions=")) {
continue;
}
out.push(arg);
}
return out;
};
const vendorRegisterPath = new URL("../vendor/register-vendor.js", import.meta.url).href;
const computedExecArgv = [
...stripConditionsFromArgv(process.execArgv || []),
"--conditions",
reverseCondition,
"--import",
vendorRegisterPath
];
if (verbose) {
logger.info(
`[create:${id}] Setting up worker with reverse condition: ${reverseCondition}`
);
logger.info(
`[create:${id}] Computed execArgv: ${JSON.stringify(computedExecArgv)}`
);
logger.info(
`[create:${id}] Current NODE_OPTIONS: ${process.env["NODE_OPTIONS"]}`
);
}
const env = {
// Inherit all existing environment variables
...process.env,
// Override with our specific variables
[envPrefix + "DEV"]: mode === "development" ? "1" : "0",
[envPrefix + "MODE"]: mode,
[envPrefix + "PROD"]: mode === "production" ? "1" : "0",
[envPrefix + "SSR"]: "true",
[envPrefix + "BASE_URL"]: workerData.userOptions?.moduleBaseURL ?? "",
[envPrefix + "PUBLIC_ORIGIN"]: workerData.userOptions?.publicOrigin ?? "",
NODE_ENV: process.env["NODE_ENV"] ?? "production",
NODE_PATH: nodePath,
// Ensure NODE_OPTIONS has the correct condition
NODE_OPTIONS: process.env["NODE_OPTIONS"]?.includes(reverseCondition) ? process.env["NODE_OPTIONS"] : currentCondition != null && process.env["NODE_OPTIONS"]?.includes(currentCondition) ? process.env["NODE_OPTIONS"]?.replaceAll(
currentCondition,
reverseCondition
) : `${process.env["NODE_OPTIONS"] ?? ""} --conditions ${reverseCondition}`,
HTML_CHUNK_SIZE: htmlChunkSize.toString()
};
if (verbose) {
logger.info(
`[create:${id}] Worker NODE_OPTIONS will be: ${env.NODE_OPTIONS}`
);
logger.info(
`[create:${id}] Environment variables: ${Object.keys(env).join(", ")}`
);
logger.info(`[create:${id}] execArgv: ${computedExecArgv.join(" ")}`);
}
const worker = new Worker(workerPathWithDefault, {
env,
execArgv: computedExecArgv,
resourceLimits,
workerData,
transferList
});
activeWorkers.add(worker);
worker.setMaxListeners(maxListeners);
if (verbose) {
logger.info(
`[create:${id}] Worker created, waiting for READY message...`
);
}
return await new Promise(
(resolve, reject) => {
const workerType = reverseCondition === "react-server" ? "rsc" : "html";
const startupTimeout = workerType === "rsc" ? options.workerData.userOptions?.rscWorkerStartupTimeout : options.workerData.userOptions?.htmlWorkerStartupTimeout;
const timeout = setTimeout(() => {
reject({ type: "error", error: new Error("Worker ready timeout") });
}, startupTimeout);
const exitHandler = (code) => {
clearTimeout(timeout);
worker.removeListener("message", messageHandler);
activeWorkers.delete(worker);
if (code !== 0) {
reject({
type: "error",
error: new Error(
`[create:${id}] Worker exited with code ${code}`
),
workerPath: workerPathWithDefault
});
}
};
const messageHandler = (msg) => {
if (verbose)
logger.info(`[create:${id}] Initial worker message ${msg.type}`);
if (msg.type === "READY" && msg.id === id) {
if (verbose)
logger.info(`[create:${id}] Worker running for ${msg.env}`);
clearTimeout(timeout);
worker.removeListener("message", messageHandler);
worker.removeListener("exit", exitHandler);
if (msg.env !== mode) {
if (verbose)
logger.info(`[create:${id}] Worker environment mismatch.`);
reject({
type: "error",
error: new Error(
`Worker environment mismatch: ${msg.env} !== ${mode}`
),
workerPath: workerPathWithDefault
});
}
resolve({
type: "success",
worker,
workerPath: workerPathWithDefault
});
}
};
worker.once("message", messageHandler);
worker.once("exit", exitHandler);
worker.on("error", (err) => {
activeWorkers.delete(worker);
if (verbose && err != null) {
logger.error(
`[create:${id}] Worker error: ${err.message}.
${err.stack}`,
{ error: err }
);
}
const panicError = handleError({
error: err,
logger,
panicThreshold: workerData.userOptions?.panicThreshold,
critical: false,
context: `Worker thread error for route ${id}`
});
if (panicError != null) {
if (verbose) {
logger.error(
`[create:${id}] Panic error detected: ${panicError.message}`,
{ error: panicError }
);
}
reject({
type: "error",
error: err,
workerPath: workerPathWithDefault
});
}
reject({
type: "error",
error: new Error("Worker thread error", { cause: err }),
workerPath: workerPathWithDefault
});
});
}
);
} catch (error) {
if (verbose) {
logger.error(
`[create:${id}] Caught error during worker creation: ${toError(error).message}`,
{ error: error instanceof Error ? error : new Error(String(error)) }
);
}
const panicError = handleError({
error,
logger,
panicThreshold: workerData.userOptions?.panicThreshold,
critical: false});
if (panicError != null) {
if (verbose) {
logger.error(
`[create:${id}] Panic error in catch block: ${panicError.message}`,
{ error: panicError }
);
}
return {
type: "error",
error: panicError,
workerPath: workerPathWithDefault
};
}
return {
type: "error",
error: error instanceof Error ? error : new Error(String(error)),
workerPath: workerPathWithDefault
};
}
};
export { createWorker, shutdownAllWorkers };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlV29ya2VyLmpzIiwic291cmNlcyI6WyIuLi8uLi8uLi9wbHVnaW4vd29ya2VyL2NyZWF0ZVdvcmtlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBXb3JrZXIsXG4gIHR5cGUgUmVzb3VyY2VMaW1pdHMsXG4gIHR5cGUgVHJhbnNmZXJMaXN0SXRlbSxcbiAgdHlwZSBNZXNzYWdlUG9ydCxcbn0gZnJvbSBcIm5vZGU6d29ya2VyX3RocmVhZHNcIjtcbmltcG9ydCB0eXBlIHsgQ29uZmlnRW52IH0gZnJvbSBcInZpdGVcIjtcbmltcG9ydCB7IGdldE1vZGUsIGdldE5vZGVQYXRoIH0gZnJvbSBcIi4uL2NvbmZpZy9nZXRQYXRocy5qc1wiO1xuaW1wb3J0IHsgZ2V0Q29uZGl0aW9uIH0gZnJvbSBcIi4uL2NvbmZpZy9nZXRDb25kaXRpb24uanNcIjtcbmltcG9ydCB7IGpvaW4gfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgeyBleGlzdHNTeW5jIH0gZnJvbSBcIm5vZGU6ZnNcIjtcbmltcG9ydCB7IHBsdWdpblJvb3QgfSBmcm9tIFwiLi4vcm9vdC5qc1wiO1xuaW1wb3J0IHsgREVGQVVMVF9DT05GSUcgfSBmcm9tIFwiLi4vY29uZmlnL2RlZmF1bHRzLmpzXCI7XG5pbXBvcnQgeyBjcmVhdGVMb2dnZXIsIHR5cGUgTG9nZ2VyIH0gZnJvbSBcInZpdGVcIjtcbmltcG9ydCB0eXBlIHsgSHRtbFdvcmtlck91dHB1dE1lc3NhZ2UgfSBmcm9tIFwiLi9odG1sL3R5cGVzLmpzXCI7XG5pbXBvcnQgdHlwZSB7IFJzY1dvcmtlck91dHB1dE1lc3NhZ2UgfSBmcm9tIFwiLi9yc2MvdHlwZXMuanNcIjtcbmltcG9ydCB0eXBlIHtcbiAgU2VyaWFsaXplZFJlc29sdmVkQ29uZmlnLFxuICBTZXJpYWxpemVkVXNlck9wdGlvbnMsXG59IGZyb20gXCIuLi90eXBlcy5qc1wiO1xuaW1wb3J0IHR5cGUgeyBNYW5pZmVzdCB9IGZyb20gXCJ2aXRlXCI7XG5pbXBvcnQgdHlwZSB7IE91dHB1dEJ1bmRsZSB9IGZyb20gXCJyb2xsdXBcIjtcbmltcG9ydCB7IGhhbmRsZUVycm9yIH0gZnJvbSBcIi4uL2Vycm9yL2hhbmRsZUVycm9yLmpzXCI7XG5pbXBvcnQgeyB0b0Vycm9yIH0gZnJvbSBcIi4uL2Vycm9yL3RvRXJyb3IuanNcIjtcblxuLy8gR2xvYmFsIHdvcmtlciByZWdpc3RyeSBmb3IgZ3JhY2VmdWwgc2h1dGRvd25cbmNvbnN0IGFjdGl2ZVdvcmtlcnMgPSBuZXcgU2V0PFdvcmtlcj4oKTtcblxuLy8gR3JhY2VmdWwgc2h1dGRvd24gZnVuY3Rpb24gdXNpbmcgdGhlIGV4aXN0aW5nIFNIVVRET1dOIHByb3RvY29sXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2h1dGRvd25BbGxXb3JrZXJzKHRpbWVvdXQ6IG51bWJlciA9IDEwMDApOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKGFjdGl2ZVdvcmtlcnMuc2l6ZSA9PT0gMCkgcmV0dXJuO1xuXG4gIGNvbnN0IHNodXRkb3duUHJvbWlzZXMgPSBBcnJheS5mcm9tKGFjdGl2ZVdvcmtlcnMpLm1hcCh3b3JrZXIgPT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgICAgbGV0IG1lc3NhZ2VIYW5kbGVyOiAoKG1lc3NhZ2U6IGFueSkgPT4gdm9pZCkgfCB1bmRlZmluZWQ7XG4gICAgICBcbiAgICAgIGNvbnN0IHRpbWVvdXRJZCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICB3b3JrZXIucmVtb3ZlTGlzdGVuZXIoXCJtZXNzYWdlXCIsIG1lc3NhZ2VIYW5kbGVyISk7XG4gICAgICAgIHdvcmtlci5yZW1vdmVBbGxMaXN0ZW5lcnMoKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICB3b3JrZXIudGVybWluYXRlKCk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgLy8gSWdub3JlIHRlcm1pbmF0aW9uIGVycm9yc1xuICAgICAgICB9XG4gICAgICAgIGFjdGl2ZVdvcmtlcnMuZGVsZXRlKHdvcmtlcik7XG4gICAgICAgIHJlc29sdmUoKTtcbiAgICAgIH0sIHRpbWVvdXQpO1xuXG4gICAgICBtZXNzYWdlSGFuZGxlciA9IChtZXNzYWdlOiBhbnkpID0+IHtcbiAgICAgICAgaWYgKG1lc3NhZ2UudHlwZSA9PT0gXCJTSFVURE9XTl9DT01QTEVURVwiKSB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXRJZCk7XG4gICAgICAgICAgd29ya2VyLnJlbW92ZUxpc3RlbmVyKFwibWVzc2FnZVwiLCBtZXNzYWdlSGFuZGxlciEpO1xuICAgICAgICAgIHdvcmtlci5yZW1vdmVBbGxMaXN0ZW5lcnMoKTtcbiAgICAgICAgICBhY3RpdmVXb3JrZXJzLmRlbGV0ZSh3b3JrZXIpO1xuICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgd29ya2VyLm9uKFwibWVzc2FnZVwiLCBtZXNzYWdlSGFuZGxlcik7XG4gICAgICBcbiAgICAgIC8vIFNlbmQgZ3JhY2VmdWwgc2h1dGRvd24gbWVzc2FnZVxuICAgICAgdHJ5IHtcbiAgICAgICAgd29ya2VyLnBvc3RNZXNzYWdlKHtcbiAgICAgICAgICB0eXBlOiBcIlNIVVRET1dOXCIsXG4gICAgICAgICAgaWQ6IFwiKlwiLFxuICAgICAgICB9KTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIC8vIElmIHdlIGNhbid0IHNlbmQgdGhlIG1lc3NhZ2UsIGZvcmNlIHRlcm1pbmF0ZVxuICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dElkKTtcbiAgICAgICAgd29ya2VyLnJlbW92ZUxpc3RlbmVyKFwibWVzc2FnZVwiLCBtZXNzYWdlSGFuZGxlciEpO1xuICAgICAgICB3b3JrZXIucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgd29ya2VyLnRlcm1pbmF0ZSgpO1xuICAgICAgICB9IGNhdGNoICh0ZXJtaW5hdGVFcnJvcikge1xuICAgICAgICAgIC8vIElnbm9yZSB0ZXJtaW5hdGlvbiBlcnJvcnNcbiAgICAgICAgfVxuICAgICAgICBhY3RpdmVXb3JrZXJzLmRlbGV0ZSh3b3JrZXIpO1xuICAgICAgICByZXNvbHZlKCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuXG4gIGF3YWl0IFByb21pc2UuYWxsKHNodXRkb3duUHJvbWlzZXMpO1xuICBhY3RpdmVXb3JrZXJzLmNsZWFyKCk7XG59XG5cblxudHlwZSBDcmVhdGVXb3JrZXJTdWNjZXNzID0ge1xuICB0eXBlOiBcInN1Y2Nlc3NcIjtcbiAgd29ya2VyUGF0aDogc3RyaW5nO1xuICByZWFzb24/OiBuZXZlcjtcbiAgZXJyb3I/OiBuZXZlcjtcbiAgd29ya2VyOiBXb3JrZXI7XG59O1xuXG50eXBlIENyZWF0ZVdvcmtlckVycm9yID0ge1xuICB0eXBlOiBcImVycm9yXCI7XG4gIHdvcmtlclBhdGg6IHN0cmluZztcbiAgZXJyb3I6IEVycm9yIHwgbnVsbDtcbiAgd29ya2VyPzogbmV2ZXI7XG4gIHJlYXNvbj86IG5ldmVyO1xufTtcblxudHlwZSBDcmVhdGVXb3JrZXJTa2lwID0ge1xuICB0eXBlOiBcInNraXBcIjtcbiAgcmVhc29uOiBzdHJpbmc7XG4gIHdvcmtlclBhdGg6IHN0cmluZztcbiAgd29ya2VyPzogbmV2ZXI7XG4gIGVycm9yPzogbmV2ZXI7XG59O1xuXG5leHBvcnQgdHlwZSBDcmVhdGVXb3JrZXJSZXR1cm4gPVxuICB8IENyZWF0ZVdvcmtlclN1Y2Nlc3NcbiAgfCBDcmVhdGVXb3JrZXJFcnJvclxuICB8IENyZWF0ZVdvcmtlclNraXA7XG5cbmV4cG9ydCB0eXBlIENyZWF0ZVdvcmtlck9wdGlvbnMgPSB7XG4gIHByb2plY3RSb290Pzogc3RyaW5nO1xuICBjdXJyZW50Q29uZGl0aW9uPzogXCJyZWFjdC1zZXJ2ZXJcIiB8IFwicmVhY3QtY2xpZW50XCI7XG4gIG5vZGVQYXRoPzogc3RyaW5nO1xuICBub2RlT3B0aW9ucz86IHN0cmluZ1tdO1xuICBlbnZQcmVmaXg/OiBzdHJpbmc7XG4gIG1vZGU/OiBcInByb2R1Y3Rpb25cIiB8IFwiZGV2ZWxvcG1lbnRcIiB8IFwidGVzdFwiO1xuICByZXZlcnNlQ29uZGl0aW9uPzogc3RyaW5nO1xuICBtYXhMaXN0ZW5lcnM/OiBudW1iZXI7XG4gIHdvcmtlclBhdGg/OiBzdHJpbmc7XG4gIHJlc291cmNlTGltaXRzPzogUmVzb3VyY2VMaW1pdHM7XG4gIHR5cGVzY3JpcHQ/OiBib29sZWFuO1xuICBodG1sQ2h1bmtTaXplPzogbnVtYmVyOyAvLyBTaXplIG9mIEhUTUwgY2h1bmtzIGluIGJ5dGVzXG4gIHdvcmtlckRhdGE6IHtcbiAgICB1c2VyT3B0aW9ucz86IFNlcmlhbGl6ZWRVc2VyT3B0aW9ucztcbiAgICByZXNvbHZlZENvbmZpZz86IFNlcmlhbGl6ZWRSZXNvbHZlZENvbmZpZztcbiAgICBjb25maWdFbnY/OiBDb25maWdFbnY7XG4gICAgcmVhY3RWZXJzaW9uPzogc3RyaW5nO1xuICAgIGlkPzogc3RyaW5nO1xuICAgIHNlcnZlck1hbmlmZXN0PzogTWFuaWZlc3Q7XG4gICAgYnVuZGxlPzogT3V0cHV0QnVuZGxlO1xuICAgIHN0YXRpY0J1bmRsZT86IE91dHB1dEJ1bmRsZTtcbiAgICBzZXJ2ZXJQaXBlYWJsZVN0cmVhbU9wdGlvbnM/OiBhbnk7XG4gICAgY2xpZW50UGlwZWFibGVTdHJlYW1PcHRpb25zPzogYW55O1xuICAgIGhtclBvcnQ/OiBNZXNzYWdlUG9ydDtcbiAgICBydW5uZXJQb3J0PzogTWVzc2FnZVBvcnQ7XG4gIH07XG4gIHRyYW5zZmVyTGlzdD86IFRyYW5zZmVyTGlzdEl0ZW1bXTtcbiAgbG9nZ2VyPzogTG9nZ2VyO1xuICB2ZXJib3NlPzogYm9vbGVhbjtcbn07XG5cbmV4cG9ydCB0eXBlIENyZWF0ZVdvcmtlckZuID0gKFxuICBvcHRpb25zOiBDcmVhdGVXb3JrZXJPcHRpb25zXG4pID0+IFByb21pc2U8Q3JlYXRlV29ya2VyUmV0dXJuPjtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVdvcmtlcjogQ3JlYXRlV29ya2VyRm4gPSBhc3luYyBmdW5jdGlvbiBfY3JlYXRlV29ya2VyKFxuICBvcHRpb25zXG4pIHtcbiAgY29uc3Qge1xuICAgIHByb2plY3RSb290ID0gcHJvY2Vzcy5jd2QoKSxcbiAgICBub2RlUGF0aCA9IGdldE5vZGVQYXRoKHByb2plY3RSb290KSxcbiAgICBjdXJyZW50Q29uZGl0aW9uID0gZ2V0Q29uZGl0aW9uKCksXG4gICAgZW52UHJlZml4ID0gREVGQVVMVF9DT05GSUcuRU5WX1BSRUZJWCxcbiAgICByZXZlcnNlQ29uZGl0aW9uID0gY3VycmVudENvbmRpdGlvbiA9PT0gXCJyZWFjdC1zZXJ2ZXJcIlxuICAgICAgPyBcInJlYWN0LWNsaWVudFwiXG4gICAgICA6IFwicmVhY3Qtc2VydmVyXCIsXG4gICAgbWF4TGlzdGVuZXJzID0gMTAwLFxuICAgIG1vZGUgPSBnZXRNb2RlKCksXG4gICAgd29ya2VyUGF0aCxcbiAgICByZXNvdXJjZUxpbWl0cyA9IHtcbiAgICAgIG1heE9sZEdlbmVyYXRpb25TaXplTWI6IDEyOCxcbiAgICAgIG1heFlvdW5nR2VuZXJhdGlvblNpemVNYjogNjQsXG4gICAgfSxcbiAgICBodG1sQ2h1bmtTaXplID0gOCAqIDEwMjQsXG4gICAgdHJhbnNmZXJMaXN0ID0gW10sXG4gICAgbG9nZ2VyID0gY3JlYXRlTG9nZ2VyKCksXG4gICAgdmVyYm9zZSA9IGZhbHNlLFxuICB9ID0gb3B0aW9ucztcbiAgY29uc3QgaWQgPSByZXZlcnNlQ29uZGl0aW9uID09PSBcInJlYWN0LXNlcnZlclwiID8gXCJ3b3JrZXIvcnNjXCIgOiBcIndvcmtlci9odG1sXCI7XG4gIGxldCB3b3JrZXJQYXRoV2l0aERlZmF1bHQgPVxuICAgIHR5cGVvZiB3b3JrZXJQYXRoID09PSBcInN0cmluZ1wiID8gd29ya2VyUGF0aCA6IHVuZGVmaW5lZDtcbiAgaWYgKCF3b3JrZXJQYXRoV2l0aERlZmF1bHQpIHtcbiAgICAvLyBVc2UgdGhlIGRlZmF1bHQgd29ya2VyIHBhdGhzIHRoYXQgaW5jbHVkZSB0aGUgZnVsbCBmaWxlbmFtZVxuICAgIGNvbnN0IGlzUHJvZHVjdGlvbiA9IG1vZGUgPT09IFwicHJvZHVjdGlvblwiO1xuICAgIGNvbnN0IHdvcmtlckZpbGVOYW1lID1cbiAgICAgIHJldmVyc2VDb25kaXRpb24gPT09IFwicmVhY3Qtc2VydmVyXCJcbiAgICAgICAgPyBgcnNjLXdvcmtlci4ke2lzUHJvZHVjdGlvbiA/IFwicHJvZHVjdGlvblwiIDogXCJkZXZlbG9wbWVudFwifS5qc2BcbiAgICAgICAgOiBgaHRtbC13b3JrZXIuJHtpc1Byb2R1Y3Rpb24gPyBcInByb2R1Y3Rpb25cIiA6IFwiZGV2ZWxvcG1lbnRcIn0uanNgO1xuXG4gICAgLy8gVHJ5IHNvdXJjZSBkaXJlY3RvcnkgZmlyc3RcbiAgICBjb25zdCBzb3VyY2VQYXRoID0gam9pbihwbHVnaW5Sb290LCBpZCwgd29ya2VyRmlsZU5hbWUpO1xuXG4gICAgLy8gQWx3YXlzIGxvZyB0aGUgcGF0aHMgZm9yIGRlYnVnZ2luZ1xuICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICBsb2dnZXIuaW5mbyhcbiAgICAgICAgYFtjcmVhdGU6JHtpZH1dIENoZWNraW5nIHBhdGhzIC0gU291cmNlOiAke3NvdXJjZVBhdGh9LCBQbHVnaW5Sb290OiAke3BsdWdpblJvb3R9YFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBJZiBzb3VyY2UgcGF0aCBkb2Vzbid0IGV4aXN0LCB0cnkgYnVpbHQgZGlyZWN0b3J5XG4gICAgaWYgKCFleGlzdHNTeW5jKHNvdXJjZVBhdGgpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBbY3JlYXRlOiR7aWR9XSBXb3JrZXIgZmlsZSBkb2Vzbid0IGV4aXN0OiAke3NvdXJjZVBhdGh9YFxuICAgICAgKTtcbiAgICAgIC8vIGNvbnN0IGJ1aWx0UGF0aCA9IGpvaW4ocGx1Z2luUm9vdC5yZXBsYWNlKFwiL3BsdWdpbi9cIiwgXCIvZGlzdC9wbHVnaW4vXCIpLCBpZCwgd29ya2VyRmlsZU5hbWUpO1xuICAgICAgLy8gbG9nZ2VyLmluZm8oYFtjcmVhdGU6JHtpZH1dIFNvdXJjZSBwYXRoIGRvZXNuJ3QgZXhpc3QsIGNoZWNraW5nIGJ1aWx0IHBhdGg6ICR7YnVpbHRQYXRofWApO1xuXG4gICAgICAvLyBpZiAoZXhpc3RzU3luYyhidWlsdFBhdGgpKSB7XG4gICAgICAvLyAgIHdvcmtlclBhdGhXaXRoRGVmYXVsdCA9IGJ1aWx0UGF0aDtcbiAgICAgIC8vICAgbG9nZ2VyLmluZm8oYFtjcmVhdGU6JHtpZH1dIFVzaW5nIGJ1aWx0IHdvcmtlciBwYXRoOiAke2J1aWx0UGF0aH1gKTtcbiAgICAgIC8vIH0gZWxzZSB7XG4gICAgICAvLyAgIHdvcmtlclBhdGhXaXRoRGVmYXVsdCA9IHNvdXJjZVBhdGg7IC8vIEZhbGxiYWNrIHRvIHNvdXJjZSBwYXRoIGZvciBlcnJvciBtZXNzYWdlXG4gICAgICAvLyAgIGxvZ2dlci5pbmZvKGBbY3JlYXRlOiR7aWR9XSBOZWl0aGVyIHNvdXJjZSBub3IgYnVpbHQgcGF0aCBleGlzdHMuIFNvdXJjZTogJHtzb3VyY2VQYXRofSwgQnVpbHQ6ICR7YnVpbHRQYXRofWApO1xuICAgICAgLy8gfVxuICAgIH0gZWxzZSB7XG4gICAgICB3b3JrZXJQYXRoV2l0aERlZmF1bHQgPSBzb3VyY2VQYXRoO1xuICAgICAgaWYgKHZlcmJvc2UpIHtcbiAgICAgICAgbG9nZ2VyLmluZm8oYFtjcmVhdGU6JHtpZH1dIFVzaW5nIHNvdXJjZSB3b3JrZXIgcGF0aDogJHtzb3VyY2VQYXRofWApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBpZiAoIXdvcmtlclBhdGhXaXRoRGVmYXVsdC5zdGFydHNXaXRoKFwiL1wiKSkge1xuICAgIHdvcmtlclBhdGhXaXRoRGVmYXVsdCA9IGpvaW4oXCIuL1wiLCB3b3JrZXJQYXRoV2l0aERlZmF1bHQpO1xuICB9XG4gIC8vIEVuc3VyZSB3b3JrZXIgdXNlcyB0aGUgc2FtZSBSZWFjdCB2ZXJzaW9uXG4gIGNvbnN0IHdvcmtlckRhdGEgPSB7XG4gICAgLi4ub3B0aW9ucy53b3JrZXJEYXRhLFxuICAgIGlkOiBvcHRpb25zLndvcmtlckRhdGEuaWQgPz8gaWQsXG4gIH07XG5cbiAgdHJ5IHtcbiAgICAvLyBFbnN1cmUgY29uc2lzdGVudCBOT0RFX0VOViBiZXR3ZWVuIG1haW4gdGhyZWFkIGFuZCB3b3JrZXJcblxuICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICBsb2dnZXIuaW5mbyhcbiAgICAgICAgYFtjcmVhdGU6JHtpZH1dIHdvcmtlckRhdGEudXNlck9wdGlvbnMuYnVpbGQ6XG4ke0pTT04uc3RyaW5naWZ5KHdvcmtlckRhdGEudXNlck9wdGlvbnM/LmJ1aWxkKX1cblxuQ2FsbCBzdGFjazogJHtuZXcgRXJyb3IoKS5zdGFjaz8uc3BsaXQoXCJcXG5cIikuc2xpY2UoMSwgNCkuam9pbihcIlxcblwiKX1cbkNyZWF0aW5nIHdvcmtlciB3aXRoIHBhdGg6ICR7d29ya2VyUGF0aFdpdGhEZWZhdWx0fVxuTm9kZSBlbnZpcm9ubWVudDogJHttb2RlfVxuQ3VycmVudCBjb25kaXRpb246ICR7Y3VycmVudENvbmRpdGlvbn0sIFJldmVyc2UgY29uZGl0aW9uOiAke3JldmVyc2VDb25kaXRpb259YFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBDb21wdXRlIGV4ZWNBcmd2IGZvciB0aGUgd29ya2VyIHdpdGggZXhhY3RseSBvbmUgLS1jb25kaXRpb25zIGZsYWdcbiAgICBjb25zdCBzdHJpcENvbmRpdGlvbnNGcm9tQXJndiA9IChhcmd2OiBzdHJpbmdbXSkgPT4ge1xuICAgICAgY29uc3Qgb3V0OiBzdHJpbmdbXSA9IFtdO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcmd2Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGFyZyA9IGFyZ3ZbaV07XG4gICAgICAgIGlmIChhcmcgPT09IFwiLS1jb25kaXRpb25zXCIgfHwgYXJnID09PSBcIi1DXCIpIHtcbiAgICAgICAgICBpKys7IC8vIHNraXAgdmFsdWVcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYXJnLnN0YXJ0c1dpdGgoXCItLWNvbmRpdGlvbnM9XCIpKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgb3V0LnB1c2goYXJnKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBvdXQ7XG4gICAgfTtcbiAgICAvLyBSZWdpc3RlciB2ZW5kb3IgcmVzb2x1dGlvbiBob29rIHNvIHRoZSB3b3JrZXIgY2FuIGZpbmQgcmVhY3Qtc2VydmVyLWRvbS1lc21cbiAgICBjb25zdCB2ZW5kb3JSZWdpc3RlclBhdGggPSBuZXcgVVJMKFwiLi4vdmVuZG9yL3JlZ2lzdGVyLXZlbmRvci5qc1wiLCBpbXBvcnQubWV0YS51cmwpLmhyZWY7XG4gICAgY29uc3QgY29tcHV0ZWRFeGVjQXJndiA9IFtcbiAgICAgIC4uLnN0cmlwQ29uZGl0aW9uc0Zyb21Bcmd2KHByb2Nlc3MuZXhlY0FyZ3YgfHwgW10pLFxuICAgICAgXCItLWNvbmRpdGlvbnNcIixcbiAgICAgIHJldmVyc2VDb25kaXRpb24sXG4gICAgICBcIi0taW1wb3J0XCIsXG4gICAgICB2ZW5kb3JSZWdpc3RlclBhdGgsXG4gICAgXTtcblxuICAgIC8vIEFsd2F5cyBsb2cgdGhlIGNvbmRpdGlvbiBzZXR1cCBmb3IgZGVidWdnaW5nXG4gICAgaWYgKHZlcmJvc2UpIHtcbiAgICAgIGxvZ2dlci5pbmZvKFxuICAgICAgICBgW2NyZWF0ZToke2lkfV0gU2V0dGluZyB1cCB3b3JrZXIgd2l0aCByZXZlcnNlIGNvbmRpdGlvbjogJHtyZXZlcnNlQ29uZGl0aW9ufWBcbiAgICAgICk7XG4gICAgICBsb2dnZXIuaW5mbyhcbiAgICAgICAgYFtjcmVhdGU6JHtpZH1dIENvbXB1dGVkIGV4ZWNBcmd2OiAke0pTT04uc3RyaW5naWZ5KGNvbXB1dGVkRXhlY0FyZ3YpfWBcbiAgICAgICk7XG4gICAgICBsb2dnZXIuaW5mbyhcbiAgICAgICAgYFtjcmVhdGU6JHtpZH1dIEN1cnJlbnQgTk9ERV9PUFRJT05TOiAke3Byb2Nlc3MuZW52W1wiTk9ERV9PUFRJT05TXCJdfWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgZW52ID0ge1xuICAgICAgLy8gSW5oZXJpdCBhbGwgZXhpc3RpbmcgZW52aXJvbm1lbnQgdmFyaWFibGVzXG4gICAgICAuLi5wcm9jZXNzLmVudixcblxuICAgICAgLy8gT3ZlcnJpZGUgd2l0aCBvdXIgc3BlY2lmaWMgdmFyaWFibGVzXG4gICAgICBbZW52UHJlZml4ICsgXCJERVZcIl06IG1vZGUgPT09IFwiZGV2ZWxvcG1lbnRcIiA/IFwiMVwiIDogXCIwXCIsXG4gICAgICBbZW52UHJlZml4ICsgXCJNT0RFXCJdOiBtb2RlLFxuICAgICAgW2VudlByZWZpeCArIFwiUFJPRFwiXTogbW9kZSA9PT0gXCJwcm9kdWN0aW9uXCIgPyBcIjFcIiA6IFwiMFwiLFxuICAgICAgW2VudlByZWZpeCArIFwiU1NSXCJdOiBcInRydWVcIixcbiAgICAgIFtlbnZQcmVmaXggKyBcIkJBU0VfVVJMXCJdOiB3b3JrZXJEYXRhLnVzZXJPcHRpb25zPy5tb2R1bGVCYXNlVVJMID8/IFwiXCIsXG4gICAgICBbZW52UHJlZml4ICsgXCJQVUJMSUNfT1JJR0lOXCJdOiB3b3JrZXJEYXRhLnVzZXJPcHRpb25zPy5wdWJsaWNPcmlnaW4gPz8gXCJcIixcbiAgICAgIE5PREVfRU5WOiBwcm9jZXNzLmVudltcIk5PREVfRU5WXCJdID8/IFwicHJvZHVjdGlvblwiLFxuICAgICAgTk9ERV9QQVRIOiBub2RlUGF0aCxcblxuICAgICAgLy8gRW5zdXJlIE5PREVfT1BUSU9OUyBoYXMgdGhlIGNvcnJlY3QgY29uZGl0aW9uXG4gICAgICBOT0RFX09QVElPTlM6IHByb2Nlc3MuZW52W1wiTk9ERV9PUFRJT05TXCJdPy5pbmNsdWRlcyhyZXZlcnNlQ29uZGl0aW9uKVxuICAgICAgICA/IHByb2Nlc3MuZW52W1wiTk9ERV9PUFRJT05TXCJdXG4gICAgICAgIDogY3VycmVudENvbmRpdGlvbiAhPSBudWxsICYmXG4gICAgICAgICAgcHJvY2Vzcy5lbnZbXCJOT0RFX09QVElPTlNcIl0/LmluY2x1ZGVzKGN1cnJlbnRDb25kaXRpb24pXG4gICAgICAgID8gcHJvY2Vzcy5lbnZbXCJOT0RFX09QVElPTlNcIl0/LnJlcGxhY2VBbGwoXG4gICAgICAgICAgICBjdXJyZW50Q29uZGl0aW9uLFxuICAgICAgICAgICAgcmV2ZXJzZUNvbmRpdGlvblxuICAgICAgICAgIClcbiAgICAgICAgOiBgJHtcbiAgICAgICAgICAgIHByb2Nlc3MuZW52W1wiTk9ERV9PUFRJT05TXCJdID8/IFwiXCJcbiAgICAgICAgICB9IC0tY29uZGl0aW9ucyAke3JldmVyc2VDb25kaXRpb259YCxcbiAgICAgIEhUTUxfQ0hVTktfU0laRTogaHRtbENodW5rU2l6ZS50b1N0cmluZygpLFxuICAgIH07XG5cbiAgICBpZiAodmVyYm9zZSkge1xuICAgICAgLy8gQWx3YXlzIGxvZyB0aGUgTk9ERV9PUFRJT05TIGZvciBkZWJ1Z2dpbmdcbiAgICAgIGxvZ2dlci5pbmZvKFxuICAgICAgICBgW2NyZWF0ZToke2lkfV0gV29ya2VyIE5PREVfT1BUSU9OUyB3aWxsIGJlOiAke2Vudi5OT0RFX09QVElPTlN9YFxuICAgICAgKTtcbiAgICAgIGxvZ2dlci5pbmZvKFxuICAgICAgICBgW2NyZWF0ZToke2lkfV0gRW52aXJvbm1lbnQgdmFyaWFibGVzOiAke09iamVjdC5rZXlzKGVudikuam9pbihcIiwgXCIpfWBcbiAgICAgICk7XG4gICAgICBsb2dnZXIuaW5mbyhgW2NyZWF0ZToke2lkfV0gZXhlY0FyZ3Y6ICR7Y29tcHV0ZWRFeGVjQXJndi5qb2luKFwiIFwiKX1gKTtcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgd29ya2VyIHdpdGggcHJvcGVyIGVudmlyb25tZW50IGFuZCBsb2FkZXJzXG4gICAgY29uc3Qgd29ya2VyID0gbmV3IFdvcmtlcih3b3JrZXJQYXRoV2l0aERlZmF1bHQsIHtcbiAgICAgIGVudixcbiAgICAgIGV4ZWNBcmd2OiBjb21wdXRlZEV4ZWNBcmd2LFxuICAgICAgcmVzb3VyY2VMaW1pdHMsXG4gICAgICB3b3JrZXJEYXRhLFxuICAgICAgdHJhbnNmZXJMaXN0LFxuICAgIH0pO1xuXG4gICAgLy8gUmVnaXN0ZXIgd29ya2VyIGZvciBncmFjZWZ1bCBzaHV0ZG93blxuICAgIGFjdGl2ZVdvcmtlcnMuYWRkKHdvcmtlcik7XG5cbiAgICB3b3JrZXIuc2V0TWF4TGlzdGVuZXJzKG1heExpc3RlbmVycyk7XG5cbiAgICBpZiAodmVyYm9zZSkge1xuICAgICAgbG9nZ2VyLmluZm8oXG4gICAgICAgIGBbY3JlYXRlOiR7aWR9XSBXb3JrZXIgY3JlYXRlZCwgd2FpdGluZyBmb3IgUkVBRFkgbWVzc2FnZS4uLmBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGF3YWl0IG5ldyBQcm9taXNlPENyZWF0ZVdvcmtlclN1Y2Nlc3MgfCBDcmVhdGVXb3JrZXJTa2lwPihcbiAgICAgIChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgLy8gVXNlIGFwcHJvcHJpYXRlIHRpbWVvdXQgYmFzZWQgb24gd29ya2VyIHR5cGVcbiAgICAgICAgY29uc3Qgd29ya2VyVHlwZSA9IHJldmVyc2VDb25kaXRpb24gPT09IFwicmVhY3Qtc2VydmVyXCIgPyBcInJzY1wiIDogXCJodG1sXCI7XG4gICAgICAgIGNvbnN0IHN0YXJ0dXBUaW1lb3V0ID1cbiAgICAgICAgICB3b3JrZXJUeXBlID09PSBcInJzY1wiXG4gICAgICAgICAgICA/IG9wdGlvbnMud29ya2VyRGF0YS51c2VyT3B0aW9ucz8ucnNjV29ya2VyU3RhcnR1cFRpbWVvdXRcbiAgICAgICAgICAgIDogb3B0aW9ucy53b3JrZXJEYXRhLnVzZXJPcHRpb25zPy5odG1sV29ya2VyU3RhcnR1cFRpbWVvdXQ7XG5cbiAgICAgICAgY29uc3QgdGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIHJlamVjdCh7IHR5cGU6IFwiZXJyb3JcIiwgZXJyb3I6IG5ldyBFcnJvcihcIldvcmtlciByZWFkeSB0aW1lb3V0XCIpIH0pO1xuICAgICAgICB9LCBzdGFydHVwVGltZW91dCk7XG4gICAgICAgIGNvbnN0IGV4aXRIYW5kbGVyID0gKGNvZGU6IG51bWJlcikgPT4ge1xuICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgICAgICB3b3JrZXIucmVtb3ZlTGlzdGVuZXIoXCJtZXNzYWdlXCIsIG1lc3NhZ2VIYW5kbGVyKTtcbiAgICAgICAgICAvLyBSZW1vdmUgd29ya2VyIGZyb20gcmVnaXN0cnkgd2hlbiBpdCBleGl0c1xuICAgICAgICAgIGFjdGl2ZVdvcmtlcnMuZGVsZXRlKHdvcmtlcik7XG4gICAgICAgICAgLy8gRG8gbm90IHJlbW92ZSBleGl0IGhhbmRsZXIgaGVyZSwgbGV0IGl0IGZpcmUgaWYgbmVlZGVkXG4gICAgICAgICAgaWYgKGNvZGUgIT09IDApIHtcbiAgICAgICAgICAgIHJlamVjdCh7XG4gICAgICAgICAgICAgIHR5cGU6IFwiZXJyb3JcIixcbiAgICAgICAgICAgICAgZXJyb3I6IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgICBgW2NyZWF0ZToke2lkfV0gV29ya2VyIGV4aXRlZCB3aXRoIGNvZGUgJHtjb2RlfWBcbiAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgd29ya2VyUGF0aDogd29ya2VyUGF0aFdpdGhEZWZhdWx0LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBtZXNzYWdlSGFuZGxlciA9IChcbiAgICAgICAgICBtc2c6IFJzY1dvcmtlck91dHB1dE1lc3NhZ2UgfCBIdG1sV29ya2VyT3V0cHV0TWVzc2FnZVxuICAgICAgICApID0+IHtcbiAgICAgICAgICBpZiAodmVyYm9zZSlcbiAgICAgICAgICAgIGxvZ2dlci5pbmZvKGBbY3JlYXRlOiR7aWR9XSBJbml0aWFsIHdvcmtlciBtZXNzYWdlICR7bXNnLnR5cGV9YCk7XG4gICAgICAgICAgaWYgKG1zZy50eXBlID09PSBcIlJFQURZXCIgJiYgbXNnLmlkID09PSBpZCkge1xuICAgICAgICAgICAgaWYgKHZlcmJvc2UpXG4gICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGBbY3JlYXRlOiR7aWR9XSBXb3JrZXIgcnVubmluZyBmb3IgJHttc2cuZW52fWApO1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgICAgICAgICAgd29ya2VyLnJlbW92ZUxpc3RlbmVyKFwibWVzc2FnZVwiLCBtZXNzYWdlSGFuZGxlcik7XG4gICAgICAgICAgICB3b3JrZXIucmVtb3ZlTGlzdGVuZXIoXCJleGl0XCIsIGV4aXRIYW5kbGVyKTtcbiAgICAgICAgICAgIGlmIChtc2cuZW52ICE9PSBtb2RlKSB7XG4gICAgICAgICAgICAgIGlmICh2ZXJib3NlKVxuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGBbY3JlYXRlOiR7aWR9XSBXb3JrZXIgZW52aXJvbm1lbnQgbWlzbWF0Y2guYCk7XG4gICAgICAgICAgICAgIHJlamVjdCh7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJlcnJvclwiLFxuICAgICAgICAgICAgICAgIGVycm9yOiBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgICBgV29ya2VyIGVudmlyb25tZW50IG1pc21hdGNoOiAke21zZy5lbnZ9ICE9PSAke21vZGV9YFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgd29ya2VyUGF0aDogd29ya2VyUGF0aFdpdGhEZWZhdWx0LFxuICAgICAgICAgICAgICB9IHNhdGlzZmllcyBDcmVhdGVXb3JrZXJFcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXNvbHZlKHtcbiAgICAgICAgICAgICAgdHlwZTogXCJzdWNjZXNzXCIsXG4gICAgICAgICAgICAgIHdvcmtlcixcbiAgICAgICAgICAgICAgd29ya2VyUGF0aDogd29ya2VyUGF0aFdpdGhEZWZhdWx0LFxuICAgICAgICAgICAgfSBzYXRpc2ZpZXMgQ3JlYXRlV29ya2VyU3VjY2Vzcyk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB3b3JrZXIub25jZShcIm1lc3NhZ2VcIiwgbWVzc2FnZUhhbmRsZXIpO1xuICAgICAgICB3b3JrZXIub25jZShcImV4aXRcIiwgZXhpdEhhbmRsZXIpO1xuICAgICAgICB3b3JrZXIub24oXCJlcnJvclwiLCAoZXJyKSA9PiB7XG4gICAgICAgICAgLy8gUmVtb3ZlIHdvcmtlciBmcm9tIHJlZ2lzdHJ5IG9uIGVycm9yXG4gICAgICAgICAgYWN0aXZlV29ya2Vycy5kZWxldGUod29ya2VyKTtcbiAgICAgICAgICBcbiAgICAgICAgICBpZiAodmVyYm9zZSAmJiBlcnIgIT0gbnVsbCkge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgICBgW2NyZWF0ZToke2lkfV0gV29ya2VyIGVycm9yOiAke2Vyci5tZXNzYWdlfS5cXG4ke2Vyci5zdGFja31gLFxuICAgICAgICAgICAgICB7IGVycm9yOiBlcnIgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3QgcGFuaWNFcnJvciA9IGhhbmRsZUVycm9yKHtcbiAgICAgICAgICAgIGVycm9yOiBlcnIsXG4gICAgICAgICAgICBsb2dnZXI6IGxvZ2dlcixcbiAgICAgICAgICAgIHBhbmljVGhyZXNob2xkOiB3b3JrZXJEYXRhLnVzZXJPcHRpb25zPy5wYW5pY1RocmVzaG9sZCxcbiAgICAgICAgICAgIGNyaXRpY2FsOiBmYWxzZSxcbiAgICAgICAgICAgIGNvbnRleHQ6IGBXb3JrZXIgdGhyZWFkIGVycm9yIGZvciByb3V0ZSAke2lkfWAsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgaWYgKHBhbmljRXJyb3IgIT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKHZlcmJvc2UpIHtcbiAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgICAgIGBbY3JlYXRlOiR7aWR9XSBQYW5pYyBlcnJvciBkZXRlY3RlZDogJHtwYW5pY0Vycm9yLm1lc3NhZ2V9YCxcbiAgICAgICAgICAgICAgICB7IGVycm9yOiBwYW5pY0Vycm9yIH1cbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlamVjdCh7XG4gICAgICAgICAgICAgIHR5cGU6IFwiZXJyb3JcIixcbiAgICAgICAgICAgICAgZXJyb3I6IGVycixcbiAgICAgICAgICAgICAgd29ya2VyUGF0aDogd29ya2VyUGF0aFdpdGhEZWZhdWx0LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlamVjdCh7XG4gICAgICAgICAgICB0eXBlOiBcImVycm9yXCIsXG4gICAgICAgICAgICBlcnJvcjogbmV3IEVycm9yKFwiV29ya2VyIHRocmVhZCBlcnJvclwiLCB7IGNhdXNlOiBlcnIgfSksXG4gICAgICAgICAgICB3b3JrZXJQYXRoOiB3b3JrZXJQYXRoV2l0aERlZmF1bHQsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgaWYgKHZlcmJvc2UpIHtcbiAgICAgIGxvZ2dlci5lcnJvcihcbiAgICAgICAgYFtjcmVhdGU6JHtpZH1dIENhdWdodCBlcnJvciBkdXJpbmcgd29ya2VyIGNyZWF0aW9uOiAke1xuICAgICAgICAgIHRvRXJyb3IoZXJyb3IpLm1lc3NhZ2VcbiAgICAgICAgfWAsXG4gICAgICAgIHsgZXJyb3I6IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvciA6IG5ldyBFcnJvcihTdHJpbmcoZXJyb3IpKSB9XG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCBwYW5pY0Vycm9yID0gaGFuZGxlRXJyb3Ioe1xuICAgICAgZXJyb3I6IGVycm9yLFxuICAgICAgbG9nZ2VyOiBsb2dnZXIsXG4gICAgICBwYW5pY1RocmVzaG9sZDogd29ya2VyRGF0YS51c2VyT3B0aW9ucz8ucGFuaWNUaHJlc2hvbGQsXG4gICAgICBjcml0aWNhbDogZmFsc2UsXG4gICAgICBjb250ZXh0OiBgV29ya2VyIHRocmVhZCBlcnJvciBmb3Igcm91dGUgJHtpZH1gLFxuICAgIH0pO1xuICAgIGlmIChwYW5pY0Vycm9yICE9IG51bGwpIHtcbiAgICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICAgIGxvZ2dlci5lcnJvcihcbiAgICAgICAgICBgW2NyZWF0ZToke2lkfV0gUGFuaWMgZXJyb3IgaW4gY2F0Y2ggYmxvY2s6ICR7cGFuaWNFcnJvci5tZXNzYWdlfWAsXG4gICAgICAgICAgeyBlcnJvcjogcGFuaWNFcnJvciB9XG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiBcImVycm9yXCIsXG4gICAgICAgIGVycm9yOiBwYW5pY0Vycm9yLFxuICAgICAgICB3b3JrZXJQYXRoOiB3b3JrZXJQYXRoV2l0aERlZmF1bHQsXG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogXCJlcnJvclwiLFxuICAgICAgZXJyb3I6IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvciA6IG5ldyBFcnJvcihTdHJpbmcoZXJyb3IpKSxcbiAgICAgIHdvcmtlclBhdGg6IHdvcmtlclBhdGhXaXRoRGVmYXVsdCxcbiAgICB9O1xuICB9XG59O1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7QUEwQkEsTUFBTSxhQUFBLHVCQUFvQixHQUFZLEVBQUE7QUFHdEMsZUFBc0Isa0JBQUEsQ0FBbUIsVUFBa0IsR0FBcUIsRUFBQTtBQUM5RSxFQUFJLElBQUEsYUFBQSxDQUFjLFNBQVMsQ0FBRyxFQUFBO0FBRTlCLEVBQUEsTUFBTSxtQkFBbUIsS0FBTSxDQUFBLElBQUEsQ0FBSyxhQUFhLENBQUEsQ0FBRSxJQUFJLENBQVUsTUFBQSxLQUFBO0FBQy9ELElBQU8sT0FBQSxJQUFJLE9BQWMsQ0FBQSxDQUFDLE9BQVksS0FBQTtBQUNw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