UNPKG

vite-plugin-react-server

Version:
322 lines (318 loc) 44.9 kB
/** * 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+IHtcbiAgICAgICAgICBpZiAodmVyYm9zZSlcbiAgICAgICAgICAgIGxvZ2dlci5pbmZvKGBbY3JlYXRlOiR7aWR9XSBJbml0aWFsIHdvcmtlciBtZXNzYWdlICR7bXNnLnR5cGV9YCk7XG4gICAgICAgICAgaWYgKG1zZy50eXBlID09PSBcIlJFQURZXCIgJiYgbXNnLmlkID09PSBpZCkge1xuICAgICAgICAgICAgaWYgKHZlcmJvc2UpXG4gICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGBbY3JlYXRlOiR7aWR9XSBXb3JrZXIgcnVubmluZyBmb3IgJHttc2cuZW52fWApO1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgICAgICAgICAgd29ya2VyLnJlbW92ZUxpc3RlbmVyKFwibWVzc2FnZVwiLCBtZXNzYWdlSGFuZGxlcik7XG4gICAgICAgICAgICB3b3JrZXIucmVtb3ZlTGlzdGVuZXIoXCJleGl0XCIsIGV4aXRIYW5kbGVyKTtcbiAgICAgICAgICAgIGlmIChtc2cuZW52ICE9PSBtb2RlKSB7XG4gICAgICAgICAgICAgIGlmICh2ZXJib3NlKVxuICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKGBbY3JlYXRlOiR7aWR9XSBXb3JrZXIgZW52aXJvbm1lbnQgbWlzbWF0Y2guYCk7XG4gICAgICAgICAgICAgIHJlamVjdCh7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJlcnJvclwiLFxuICAgICAgICAgICAgICAgIGVycm9yOiBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgICBgV29ya2VyIGVudmlyb25tZW50IG1pc21hdGNoOiAke21zZy5lbnZ9ICE9PSAke21vZGV9YFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgd29ya2VyUGF0aDogd29ya2VyUGF0aFdpdGhEZWZhdWx0LFxuICAgICAgICAgICAgICB9IHNhdGlzZmllcyBDcmVhdGVXb3JrZXJFcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXNvbHZlKHtcbiAgICAgICAgICAgICAgdHlwZTogXCJzdWNjZXNzXCIsXG4gICAgICAgICAgICAgIHdvcmtlcixcbiAgICAgICAgICAgICAgd29ya2VyUGF0aDogd29ya2VyUGF0aFdpdGhEZWZhdWx0LFxuICAgICAgICAgICAgfSBzYXRpc2ZpZXMgQ3JlYXRlV29ya2VyU3VjY2Vzcyk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB3b3JrZXIub25jZShcIm1lc3NhZ2VcIiwgbWVzc2FnZUhhbmRsZXIpO1xuICAgICAgICB3b3JrZXIub25jZShcImV4aXRcIiwgZXhpdEhhbmRsZXIpO1xuICAgICAgICB3b3JrZXIub24oXCJlcnJvclwiLCAoZXJyKSA9PiB7XG4gICAgICAgICAgLy8gUmVtb3ZlIHdvcmtlciBmcm9tIHJlZ2lzdHJ5IG9uIGVycm9yXG4gICAgICAgICAgYWN0aXZlV29ya2Vycy5kZWxldGUod29ya2VyKTtcbiAgICAgICAgICBcbiAgICAgICAgICBpZiAodmVyYm9zZSAmJiBlcnIgIT0gbnVsbCkge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgICBgW2NyZWF0ZToke2lkfV0gV29ya2VyIGVycm9yOiAke2Vyci5tZXNzYWdlfS5cXG4ke2Vyci5zdGFja31gLFxuICAgICAgICAgICAgICB7IGVycm9yOiBlcnIgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc3QgcGFuaWNFcnJvciA9IGhhbmRsZUVycm9yKHtcbiAgICAgICAgICAgIGVycm9yOiBlcnIsXG4gICAgICAgICAgICBsb2dnZXI6IGxvZ2dlcixcbiAgICAgICAgICAgIHBhbmljVGhyZXNob2xkOiB3b3JrZXJEYXRhLnVzZXJPcHRpb25zPy5wYW5pY1RocmVzaG9sZCxcbiAgICAgICAgICAgIGNyaXRpY2FsOiBmYWxzZSxcbiAgICAgICAgICAgIGNvbnRleHQ6IGBXb3JrZXIgdGhyZWFkIGVycm9yIGZvciByb3V0ZSAke2lkfWAsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgaWYgKHBhbmljRXJyb3IgIT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKHZlcmJvc2UpIHtcbiAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgICAgIGBbY3JlYXRlOiR7aWR9XSBQYW5pYyBlcnJvciBkZXRlY3RlZDogJHtwYW5pY0Vycm9yLm1lc3NhZ2V9YCxcbiAgICAgICAgICAgICAgICB7IGVycm9yOiBwYW5pY0Vycm9yIH1cbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlamVjdCh7XG4gICAgICAgICAgICAgIHR5cGU6IFwiZXJyb3JcIixcbiAgICAgICAgICAgICAgZXJyb3I6IGVycixcbiAgICAgICAgICAgICAgd29ya2VyUGF0aDogd29ya2VyUGF0aFdpdGhEZWZhdWx0LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJlamVjdCh7XG4gICAgICAgICAgICB0eXBlOiBcImVycm9yXCIsXG4gICAgICAgICAgICBlcnJvcjogbmV3IEVycm9yKFwiV29ya2VyIHRocmVhZCBlcnJvclwiLCB7IGNhdXNlOiBlcnIgfSksXG4gICAgICAgICAgICB3b3JrZXJQYXRoOiB3b3JrZXJQYXRoV2l0aERlZmF1bHQsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgaWYgKHZlcmJvc2UpIHtcbiAgICAgIGxvZ2dlci5lcnJvcihcbiAgICAgICAgYFtjcmVhdGU6JHtpZH1dIENhdWdodCBlcnJvciBkdXJpbmcgd29ya2VyIGNyZWF0aW9uOiAke1xuICAgICAgICAgIHRvRXJyb3IoZXJyb3IpLm1lc3NhZ2VcbiAgICAgICAgfWAsXG4gICAgICAgIHsgZXJyb3I6IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvciA6IG5ldyBFcnJvcihTdHJpbmcoZXJyb3IpKSB9XG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCBwYW5pY0Vycm9yID0gaGFuZGxlRXJyb3Ioe1xuICAgICAgZXJyb3I6IGVycm9yLFxuICAgICAgbG9nZ2VyOiBsb2dnZXIsXG4gICAgICBwYW5pY1RocmVzaG9sZDogd29ya2VyRGF0YS51c2VyT3B0aW9ucz8ucGFuaWNUaHJlc2hvbGQsXG4gICAgICBjcml0aWNhbDogZmFsc2UsXG4gICAgICBjb250ZXh0OiBgV29ya2VyIHRocmVhZCBlcnJvciBmb3Igcm91dGUgJHtpZH1gLFxuICAgIH0pO1xuICAgIGlmIChwYW5pY0Vycm9yICE9IG51bGwpIHtcbiAgICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICAgIGxvZ2dlci5lcnJvcihcbiAgICAgICAgICBgW2NyZWF0ZToke2lkfV0gUGFuaWMgZXJyb3IgaW4gY2F0Y2ggYmxvY2s6ICR7cGFuaWNFcnJvci5tZXNzYWdlfWAsXG4gICAgICAgICAgeyBlcnJvcjogcGFuaWNFcnJvciB9XG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiBcImVycm9yXCIsXG4gICAgICAgIGVycm9yOiBwYW5pY0Vycm9yLFxuICAgICAgICB3b3JrZXJQYXRoOiB3b3JrZXJQYXRoV2l0aERlZmF1bHQsXG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogXCJlcnJvclwiLFxuICAgICAgZXJyb3I6IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvciA6IG5ldyBFcnJvcihTdHJpbmcoZXJyb3IpKSxcbiAgICAgIHdvcmtlclBhdGg6IHdvcmtlclBhdGhXaXRoRGVmYXVsdCxcbiAgICB9O1xuICB9XG59O1xuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7QUEwQkEsTUFBTSxhQUFBLHVCQUFvQixHQUFZLEVBQUE7QUFHdEMsZUFBc0Isa0JBQUEsQ0FBbUIsVUFBa0IsR0FBcUIsRUFBQTtBQUM5RSxFQUFJLElBQUEsYUFBQSxDQUFjLFNBQVMsQ0FBRyxFQUFBO0FBRTlCLEVBQUEsTUFBTSxtQkFBbUIsS0FBTSxDQUFBLElBQUEsQ0FBSyxhQUFhLENBQUEsQ0FBRSxJQUFJLENBQVUsTUFBQSxLQUFBO0FBQy9ELElBQU8sT0FBQSxJQUFJLE9BQWMsQ0FBQSxDQUFDLE9BQVksS0FBQTtBQUNwQyxNQUFJLElBQUEsY0FBQTtBQUVKLE1BQU0sTUFBQSxTQUFBLEdBQVksV0FBVyxNQUFNO0FBQ2pDLFFBQU8sTUFBQSxDQUFBLGNBQUEsQ0FBZSxXQUFXLGNBQWUsQ0FBQTtBQUNoRCxRQUFBLE1BQUEsQ0FBTyxrQkFBbUIsRUFBQTtBQUMxQixRQUFJLElBQUE7QUFDRixVQUFBLE1BQUEsQ0FBTyxTQUFVLEVBQUE7QUFBQSxpQkFDVixLQUFPLEVBQUE7QUFBQTtBQUdoQixRQUFBLGFBQUEsQ0FBYyxPQUFPLE1BQU0sQ0FBQTtBQUMzQixRQUFRLE9BQUEsRUFBQTtBQUFBLFNBQ1AsT0FBTyxDQUFBO0FBRVYsTUFBQSxjQUFBLEdBQWlCLENBQUMsT0FBaUIsS0FBQTtBQUNqQyxRQUFJLElBQUEsT0FBQSxDQUFRLFNBQVMsbUJBQXFCLEVBQUE7QUFDeEMsVUFBQSxZQUFBLENBQWEsU0FBUyxDQUFBO0FBQ3RCLFVBQU8sTUFBQSxDQUFBLGNBQUEsQ0FBZSxXQUFXLGNBQWUsQ0FBQTtBQUNoRCxVQUFBLE1BQUEsQ0FBTyxrQkFBbUIsRUFBQTtBQUMxQixVQUFBLGFBQUEsQ0FBYyxPQUFPLE1BQU0sQ0FBQTtBQUMzQixVQUFRLE9BQUEsRUFBQTtBQUFBO0FBQ1YsT0FDRjtBQUVBLE1BQU8sTUFBQSxDQUFBLEVBQUEsQ0FBRyxXQUFXLGNBQWMsQ0FBQTtBQUduQyxNQUFJLElBQUE7QUFDRixRQUFBLE1BQUEsQ0FBTyxXQUFZLENBQUE7QUFBQSxVQUNqQixJQUFNLEVBQUEsVUFBQTtBQUFBLFVBQ04sRUFBSSxFQUFBO0FBQUEsU0FDTCxDQUFBO0FBQUEsZUFDTSxLQUFPLEVBQUE7QUFFZCxRQUFBLFlBQUEsQ0FBYSxTQUFTLENBQUE7QUFDdEIsUUFBTyxNQUFBLENBQUEsY0FBQSxDQUFlLFdBQVcsY0FBZSxDQUFBO0FBQ2hELFFBQUEsTUFBQSxDQUFPLGtCQUFtQixFQUFBO0FBQzFCLFFBQUksSUFBQTtBQUNGLFVBQUEsTUFBQSxDQUFPLFNBQVUsRUFBQTtBQUFBLGlCQUNWLGNBQWdCLEVBQUE7QUFBQTtBQUd6QixRQUFBLGFBQUEsQ0FBYyxPQUFPLE1BQU0sQ0FBQTtBQUMzQixRQUFRLE9BQUEsRUFBQTtBQUFBO0FBQ1YsS0FDRCxDQUFBO0FBQUEsR0FDRixDQUFBO0FBRUQsRUFBTSxNQUFBLE9BQUEsQ0FBUSxJQUFJLGdCQUFnQixDQUFBO0FBQ2xDLEVBQUEsYUFBQSxDQUFjLEtBQU0sRUFBQTtBQUN0QjtBQW9FYSxNQUFBLFlBQUEsR0FBK0IsZUFBZSxhQUFBLENBQ3pELE9BQ0EsRUFBQTtBQUNBLEVBQU0sTUFBQTtBQUFBLElBQ0osV0FBQSxHQUFjLFFBQVEsR0FBSSxFQUFBO0FBQUEsSUFDMUIsUUFBQSxHQUFXLFlBQVksV0FBVyxDQUFBO0FBQUEsSUFDbEMsbUJBQW1CLFlBQWEsRUFBQTtBQUFBLElBQ2hDLFlBQVksY0FBZSxDQUFBLFVBQUE7QUFBQSxJQUMzQixnQkFBQSxHQUFtQixnQkFBcUIsS0FBQSxjQUFBLEdBQ3BDLGNBQ0EsR0FBQSxjQUFBO0FBQUEsSUFDSixZQUFlLEdBQUEsR0FBQTtBQUFBLElBQ2YsT0FBTyxPQUFRLEVBQUE7QUFBQSxJQUNmLFVBQUE7QUFBQSxJQUNBLGNBQWlCLEdBQUE7QUFBQSxNQUNmLHNCQUF3QixFQUFBLEdBQUE7QUFBQSxNQUN4Qix3QkFBMEIsRUFBQTtBQUFBLEtBQzVCO0FBQUEsSUFDQSxnQkFBZ0IsQ0FBSSxHQUFBLElBQUE7QUFBQSxJQUNwQixlQUFlLEVBQUM7QUFBQSxJQUNoQixTQUFTLFlBQWEsRUFBQTtBQUFBLElBQ3RCLE9BQVUsR0FBQTtBQUFBLEdBQ1IsR0FBQSxPQUFBO0FBQ0osRUFBTSxNQUFBLEVBQUEsR0FBSyxnQkFBcUIsS0FBQSxjQUFBLEdBQWlCLFlBQWUsR0FBQSxhQUFBO0FBQ2hFLEVBQUEsSUFBSSxxQkFDRixHQUFBLE9BQU8sVUFBZSxLQUFBLFFBQUEsR0FBVyxVQUFhLEdBQUEsTUFBQTtBQUNoRCxFQUFBLElBQUksQ0FBQyxxQkFBdUIsRUFBQTtBQUUxQixJQUFBLE1BQU0sZUFBZSxJQUFTLEtBQUEsWUFBQTtBQUM5QixJQUFNLE1BQUEsY0FBQSxHQUNKLGdCQUFxQixLQUFBLGNBQUEsR0FDakIsQ0FBYyxXQUFBLEVBQUEsWUFBQSxHQUFlLFlBQWUsR0FBQSxhQUFhLENBQ3pELEdBQUEsQ0FBQSxHQUFBLENBQUEsWUFBQSxFQUFlLFlBQWUsR0FBQSxZQUFBLEdBQWUsYUFBYSxDQUFBLEdBQUEsQ0FBQTtBQUdoRSxJQUFBLE1BQU0sVUFBYSxHQUFBLElBQUEsQ0FBSyxVQUFZLEVBQUEsRUFBQSxFQUFJLGNBQWMsQ0FBQTtBQUd0RCxJQUFBLElBQUksT0FBUyxFQUFBO0FBQ1gsTUFBTyxNQUFBLENBQUEsSUFBQTtBQUFBLFFBQ0wsQ0FBVyxRQUFBLEVBQUEsRUFBRSxDQUE4QiwyQkFBQSxFQUFBLFVBQVUsaUJBQWlCLFVBQVUsQ0FBQTtBQUFBLE9BQ2xGO0FBQUE7QUFJRixJQUFJLElBQUEsQ0FBQyxVQUFXLENBQUEsVUFBVSxDQUFHLEVBQUE7QUFDM0IsTUFBQSxNQUFNLElBQUksS0FBQTtBQUFBLFFBQ1IsQ0FBQSxRQUFBLEVBQVcsRUFBRSxDQUFBLDZCQUFBLEVBQWdDLFVBQVUsQ0FBQTtBQUFBLE9BQ3pEO0FBQUEsS0FXSyxNQUFBO0FBQ0wsTUFBd0IscUJBQUEsR0FBQSxVQUFBO0FBQ3hCLE1BQUEsSUFBSSxPQUFTLEVBQUE7QUFDWCxRQUFBLE1BQUEsQ0FBTyxJQUFLLENBQUEsQ0FBQSxRQUFBLEVBQVcsRUFBRSxDQUFBLDRCQUFBLEVBQStCLFVBQVUsQ0FBRSxDQUFBLENBQUE7QUFBQTtBQUN0RTtBQUNGO0FBRUYsRUFBQSxJQUFJLENBQUMscUJBQUEsQ0FBc0IsVUFBVyxDQUFBLEdBQUcsQ0FBRyxFQUFBO0FBQzFDLElBQXdCLHFCQUFBLEdBQUEsSUFBQSxDQUFLLE1BQU0scUJBQXFCLENBQUE7QUFBQTtBQUcxRCxFQUFBLE1BQU0sVUFBYSxHQUFBO0FBQUEsSUFDakIsR0FBRyxPQUFRLENBQUEsVUFBQTtBQUFBLElBQ1gsRUFBQSxFQUFJLE9BQVEsQ0FBQSxVQUFBLENBQVcsRUFBTSxJQUFBO0FBQUEsR0FDL0I7QUFFQSxFQUFJLElBQUE7QUFHRixJQUFBLElBQUksT0FBUyxFQUFBO0FBQ1gsTUFBTyxNQUFBLENBQUEsSUFBQTtBQUFBLFFBQ0wsV0FBVyxFQUFFLENBQUE7QUFBQSxFQUNuQixJQUFLLENBQUEsU0FBQSxDQUFVLFVBQVcsQ0FBQSxXQUFBLEVBQWEsS0FBSyxDQUFDOztBQUFBLFlBQUEsRUFFakMsSUFBSSxLQUFBLEVBQVEsQ0FBQSxLQUFBLEVBQU8sS0FBTSxDQUFBLElBQUksQ0FBRSxDQUFBLEtBQUEsQ0FBTSxDQUFHLEVBQUEsQ0FBQyxDQUFFLENBQUEsSUFBQSxDQUFLLElBQUksQ0FBQztBQUFBLDJCQUFBLEVBQ3RDLHFCQUFxQjtBQUFBLGtCQUFBLEVBQzlCLElBQUk7QUFBQSxtQkFDSCxFQUFBLGdCQUFnQix3QkFBd0IsZ0JBQWdCLENBQUE7QUFBQSxPQUN2RTtBQUFBO0FBSUYsSUFBTSxNQUFBLHVCQUFBLEdBQTBCLENBQUMsSUFBbUIsS0FBQTtBQUNsRCxNQUFBLE1BQU0sTUFBZ0IsRUFBQztBQUN2QixNQUFBLEtBQUEsSUFBUyxDQUFJLEdBQUEsQ0FBQSxFQUFHLENBQUksR0FBQSxJQUFBLENBQUssUUFBUSxDQUFLLEVBQUEsRUFBQTtBQUNwQyxRQUFNLE1BQUEsR0FBQSxHQUFNLEtBQUssQ0FBQyxDQUFBO0FBQ2xCLFFBQUksSUFBQSxHQUFBLEtBQVEsY0FBa0IsSUFBQSxHQUFBLEtBQVEsSUFBTSxFQUFBO0FBQzFDLFVBQUEsQ0FBQSxFQUFBO0FBQ0EsVUFBQTtBQUFBO0FBRUYsUUFBSSxJQUFBLEdBQUEsQ0FBSSxVQUFXLENBQUEsZUFBZSxDQUFHLEVBQUE7QUFDbkMsVUFBQTtBQUFBO0FBRUYsUUFBQSxHQUFBLENBQUksS0FBSyxHQUFHLENBQUE7QUFBQTtBQUVkLE1BQU8sT0FBQSxHQUFBO0FBQUEsS0FDVDtBQUVBLElBQUEsTUFBTSxxQkFBcUIsSUFBSSxHQUFBLENBQUksOEJBQWdDLEVBQUEsTUFBQSxDQUFBLElBQUEsQ0FBWSxHQUFHLENBQUUsQ0FBQSxJQUFBO0FBQ3BGLElBQUEsTUFBTSxnQkFBbUIsR0FBQTtBQUFBLE1BQ3ZCLEdBQUcsdUJBQUEsQ0FBd0IsT0FBUSxDQUFBLFFBQUEsSUFBWSxFQUFFLENBQUE7QUFBQSxNQUNqRCxjQUFBO0FBQUEsTUFDQSxnQkFBQTtBQUFBLE1BQ0EsVUFBQTtBQUFBLE1BQ0E7QUFBQSxLQUNGO0FBR0EsSUFBQSxJQUFJLE9BQVMsRUFBQTtBQUNYLE1BQU8sTUFBQSxDQUFBLElBQUE7QUFBQSxRQUNMLENBQUEsUUFBQSxFQUFXLEVBQUUsQ0FBQSw0Q0FBQSxFQUErQyxnQkFBZ0IsQ0FBQTtBQUFBLE9BQzlFO0FBQ0EsTUFBTyxNQUFBLENBQUEsSUFBQTtBQUFBLFFBQ0wsV0FBVyxFQUFFLENBQUEscUJBQUEsRUFBd0IsSUFBSyxDQUFBLFNBQUEsQ0FBVSxnQkFBZ0IsQ0FBQyxDQUFBO0FBQUEsT0FDdkU7QUFDQSxNQUFPLE1BQUEsQ0FBQSxJQUFBO0FBQUEsUUFDTCxXQUFXLEVBQUUsQ0FBQSx3QkFBQSxFQUEyQixPQUFRLENBQUEsR0FBQSxDQUFJLGNBQWMsQ0FBQyxDQUFBO0FBQUEsT0FDckU7QUFBQTtBQUdGLElBQUEsTUFBTSxHQUFNLEdBQUE7QUFBQTtBQUFBLE1BRVYsR0FBRyxPQUFRLENBQUEsR0FBQTtBQUFBO0FBQUEsTUFHWCxDQUFDLFNBQVksR0FBQSxLQUFLLEdBQUcsSUFBQSxLQUFTLGdCQUFnQixHQUFNLEdBQUEsR0FBQTtBQUFBLE1BQ3BELENBQUMsU0FBWSxHQUFBLE1BQU0sR0FBRyxJQUFBO0FBQUEsTUFDdEIsQ0FBQyxTQUFZLEdBQUEsTUFBTSxHQUFHLElBQUEsS0FBUyxlQUFlLEdBQU0sR0FBQSxHQUFBO0FBQUEsTUFDcEQsQ0FBQyxTQUFZLEdBQUEsS0FBSyxHQUFHLE1BQUE7QUFBQSxNQUNyQixDQUFDLFNBQVksR0FBQSxVQUFVLEdBQUcsVUFBQSxDQUFXLGFBQWEsYUFBaUIsSUFBQSxFQUFBO0FBQUEsTUFDbkUsQ0FBQyxTQUFZLEdBQUEsZUFBZSxHQUFHLFVBQUEsQ0FBVyxhQUFhLFlBQWdCLElBQUEsRUFBQTtBQUFBLE1BQ3ZFLFFBQVUsRUFBQSxPQUFBLENBQVEsR0FBSSxDQUFBLFVBQVUsQ0FBSyxJQUFBLFlBQUE7QUFBQSxNQUNyQyxTQUFXLEVBQUEsUUFBQTtBQUFBO0FBQUEsTUFHWCxZQUFBLEVBQWMsT0FBUSxDQUFBLEdBQUEsQ0FBSSxjQUFjLENBQUEsRUFBRyxTQUFTLGdCQUFnQixDQUFBLEdBQ2hFLE9BQVEsQ0FBQSxHQUFBLENBQUksY0FBYyxDQUFBLEdBQzFCLG9CQUFvQixJQUNwQixJQUFBLE9BQUEsQ0FBUSxHQUFJLENBQUEsY0FBYyxDQUFHLEVBQUEsUUFBQSxDQUFTLGdCQUFnQixDQUN0RCxHQUFBLE9BQUEsQ0FBUSxHQUFJLENBQUEsY0FBYyxDQUFHLEVBQUEsVUFBQTtBQUFBLFFBQzNCLGdCQUFBO0FBQUEsUUFDQTtBQUFBLE9BQ0YsR0FDQSxHQUNFLE9BQVEsQ0FBQSxHQUFBLENBQUksY0FBYyxDQUFLLElBQUEsRUFDakMsaUJBQWlCLGdCQUFnQixDQUFBLENBQUE7QUFBQSxNQUNyQyxlQUFBLEVBQWlCLGNBQWMsUUFBUztBQUFBLEtBQzFDO0FBRUEsSUFBQSxJQUFJLE9BQVMsRUFBQTtBQUVYLE1BQU8sTUFBQSxDQUFBLElBQUE7QUFBQSxRQUNMLENBQVcsUUFBQSxFQUFBLEVBQUUsQ0FBa0MsK0JBQUEsRUFBQSxHQUFBLENBQUksWUFBWSxDQUFBO0FBQUEsT0FDakU7QUFDQSxNQUFPLE1BQUEsQ0FBQSxJQUFBO0FBQUEsUUFDTCxDQUFBLFFBQUEsRUFBVyxFQUFFLENBQTRCLHlCQUFBLEVBQUEsTUFBQSxDQUFPLEtBQUssR0FBRyxDQUFBLENBQUUsSUFBSyxDQUFBLElBQUksQ0FBQyxDQUFBO0FBQUEsT0FDdEU7QUFDQSxNQUFPLE1BQUEsQ0FBQSxJQUFBLENBQUssV0FBVyxFQUFFLENBQUEsWUFBQSxFQUFlLGlCQUFpQixJQUFLLENBQUEsR0FBRyxDQUFDLENBQUUsQ0FBQSxDQUFBO0FBQUE7QUFJdEUsSUFBTSxNQUFBLE1BQUEsR0FBUyxJQUFJLE1BQUEsQ0FBTyxxQkFBdUIsRUFBQTtBQUFBLE1BQy9DLEdBQUE7QUFBQSxNQUNBLFFBQVUsRUFBQSxnQkFBQTtBQUFBLE1BQ1YsY0FBQTtBQUFBLE1BQ0EsVUFBQTtBQUFBLE1BQ0E7QUFBQSxLQUNELENBQUE7QUFHRCxJQUFBLGFBQUEsQ0FBYyxJQUFJLE1BQU0sQ0FBQTtBQUV4QixJQUFBLE1BQUEsQ0FBTyxnQkFBZ0IsWUFBWSxDQUFBO0FBRW5DLElBQUEsSUFBSSxPQUFTLEVBQUE7QUFDWCxNQUFPLE1BQUEsQ0FBQSxJQUFBO0FBQUEsUUFDTCxXQUFXLEVBQUUsQ0FBQSw4Q0FBQTtBQUFBLE9BQ2Y7QUFBQTtBQUdGLElBQUEsT0FBTyxNQUFNLElBQUksT0FBQTtBQUFBLE1BQ2YsQ0FBQyxTQUFTLE1BQVcsS0FBQTtBQUVuQixRQUFNLE1BQUEsVUFBQSxHQUFhLGdCQUFxQixLQUFBLGNBQUEsR0FBaUIsS0FBUSxHQUFBLE1BQUE7QUFDakUsUUFBTSxNQUFBLGNBQUEsR0FDSixlQUFlLEtBQ1gsR0FBQSxPQUFBLENBQVEsV0FBVyxXQUFhLEVBQUEsdUJBQUEsR0FDaEMsT0FBUSxDQUFBLFVBQUEsQ0FBVyxXQUFhLEVBQUEsd0JBQUE7QUFFdEMsUUFBTSxNQUFBLE9BQUEsR0FBVSxXQUFXLE1BQU07QUFDL0IsVUFBTyxNQUFBLENBQUEsRUFBRSxNQUFNLE9BQVMsRUFBQSxLQUFBLEVBQU8sSUFBSSxLQUFNLENBQUEsc0JBQXNCLEdBQUcsQ0FBQTtBQUFBLFdBQ2pFLGNBQWMsQ0FBQTtBQUNqQixRQUFNLE1BQUEsV0FBQSxHQUFjLENBQUMsSUFBaUIsS0FBQTtBQUNwQyxVQUFBLFlBQUEsQ0FBYSxPQUFPLENBQUE7QUFDcEIsVUFBTyxNQUFBLENBQUEsY0FBQSxDQUFlLFdBQVcsY0FBYyxDQUFBO0FBRS9DLFVBQUEsYUFBQSxDQUFjLE9BQU8sTUFBTSxDQUFBO0FBRTNCLFVBQUEsSUFBSSxTQUFTLENBQUcsRUFBQTtBQUNkLFlBQU8sTUFBQSxDQUFBO0FBQUEsY0FDTCxJQUFNLEVBQUEsT0FBQTtBQUFBLGNBQ04sT0FBTyxJQUFJLEtBQUE7QUFBQSxnQkFDVCxDQUFBLFFBQUEsRUFBVyxFQUFFLENBQUEsMEJBQUEsRUFBNkIsSUFBSSxDQUFBO0FBQUEsZUFDaEQ7QUFBQSxjQUNBLFVBQVksRUFBQTtBQUFBLGFBQ2IsQ0FBQTtBQUFBO0FBQ0gsU0FDRjtBQUNBLFFBQU0sTUFBQSxjQUFBLEdBQWlCLENBQ3JCLEdBQ0csS0FBQTtBQUNILFVBQUksSUFBQSxPQUFBO0FBQ0YsWUFBQSxNQUFBLENBQU8sS0FBSyxDQUFXLFFBQUEsRUFBQSxFQUFFLENBQTRCLHlCQUFBLEVBQUEsR0FBQSxDQUFJLElBQUksQ0FBRSxDQUFBLENBQUE7QUFDakUsVUFBQSxJQUFJLEdBQUksQ0FBQSxJQUFBLEtBQVMsT0FBVyxJQUFBLEdBQUEsQ0FBSSxPQUFPLEVBQUksRUFBQTtBQUN6QyxZQUFJLElBQUEsT0FBQTtBQUNGLGNBQUEsTUFBQSxDQUFPLEtBQUssQ0FBVyxRQUFBLEVBQUEsRUFBRSxDQUF3QixxQkFBQSxFQUFBLEdBQUEsQ0FBSSxHQUFHLENBQUUsQ0FBQSxDQUFBO0FBQzVELFlBQUEsWUFBQSxDQUFhLE9BQU8sQ0FBQTtBQUNwQixZQUFPLE1BQUEsQ0FBQSxjQUFBLENBQWUsV0FBVyxjQUFjLENBQUE7QUFDL0MsWUFBTyxNQUFBLENBQUEsY0FBQSxDQUFlLFFBQVEsV0FBVyxDQUFBO0FBQ3pDLFlBQUksSUFBQSxHQUFBLENBQUksUUFBUSxJQUFNLEVBQUE7QUFDcEIsY0FBSSxJQUFBLE9BQUE7QUFDRixnQkFBTyxNQUFBLENBQUEsSUFBQSxDQUFLLENBQVcsUUFBQSxFQUFBLEVBQUUsQ0FBZ0MsOEJBQUEsQ0FBQSxDQUFBO0FBQzNELGNBQU8sTUFBQSxDQUFBO0FBQUEsZ0JBQ0wsSUFBTSxFQUFBLE9BQUE7QUFBQSxnQkFDTixPQUFPLElBQUksS0FBQTtBQUFBLGtCQUNULENBQWdDLDZCQUFBLEVBQUEsR0FBQSxDQUFJLEdBQUcsQ0FBQSxLQUFBLEVBQVEsSUFBSSxDQUFBO0FBQUEsaUJBQ3JEO0FBQUEsZ0JBQ0EsVUFBWSxFQUFBO0FBQUEsZUFDZSxDQUFBO0FBQUE7QUFFL0IsWUFBUSxPQUFBLENBQUE7QUFBQSxjQUNOLElBQU0sRUFBQSxTQUFBO0FBQUEsY0FDTixNQUFBO0FBQUEsY0FDQSxVQUFZLEVBQUE7QUFBQSxhQUNpQixDQUFBO0FBQUE7QUFDakMsU0FDRjtBQUNBLFFBQU8sTUFBQSxDQUFBLElBQUEsQ0FBSyxXQUFXLGNBQWMsQ0FBQTtBQUNyQyxRQUFPLE1BQUEsQ0FBQSxJQUFBLENBQUssUUFBUSxXQUFXLENBQUE7QUFDL0IsUUFBTyxNQUFBLENBQUEsRUFBQSxDQUFHLE9BQVMsRUFBQSxDQUFDLEdBQVEsS0FBQTtBQUUxQixVQUFBLGFBQUEsQ0FBYyxPQUFPLE1BQU0sQ0FBQTtBQUUzQixVQUFJLElBQUEsT0FBQSxJQUFXLE9BQU8sSUFBTSxFQUFBO0FBQzFCLFlBQU8sTUFBQSxDQUFBLEtBQUE7QUFBQSxjQUNMLENBQVcsUUFBQSxFQUFBLEVBQUUsQ0FBbUIsZ0JBQUEsRUFBQSxHQUFBLENBQUksT0FBTyxDQUFBO0FBQUEsRUFBTSxJQUFJLEtBQUssQ0FBQSxDQUFBO0FBQUEsY0FDMUQsRUFBRSxPQUFPLEdBQUk7QUFBQSxhQUNmO0FBQUE7QUFFRixVQUFBLE1BQU0sYUFBYSxXQUFZLENBQUE7QUFBQSxZQUM3QixLQUFPLEVBQUEsR0FBQTtBQUFBLFlBQ1AsTUFBQTtBQUFBLFlBQ0EsY0FBQSxFQUFnQixXQUFXLFdBQWEsRUFBQSxjQUFBO0FBQUEsWUFDeEMsUUFBVSxFQUFBLEtBQUE7QUFBQSxZQUNWLE9BQUEsRUFBUyxpQ0FBaUMsRUFBRSxDQUFBO0FBQUEsV0FDN0MsQ0FBQTtBQUNELFVBQUEsSUFBSSxjQUFjLElBQU0sRUFBQTtBQUN0QixZQUFBLElBQUksT0FBUyxFQUFBO0FBQ1gsY0FBTyxNQUFBLENBQUEsS0FBQTtBQUFBLGdCQUNMLENBQVcsUUFBQSxFQUFBLEVBQUUsQ0FBMkIsd0JBQUEsRUFBQSxVQUFBLENBQVcsT0FBTyxDQUFBLENBQUE7QUFBQSxnQkFDMUQsRUFBRSxPQUFPLFVBQVc7QUFBQSxlQUN0QjtBQUFBO0FBRUYsWUFBTyxNQUFBLENBQUE7QUFBQSxjQUNMLElBQU0sRUFBQSxPQUFBO0FBQUEsY0FDTixLQUFPLEVBQUEsR0FBQTtBQUFBLGNBQ1AsVUFBWSxFQUFBO0FBQUEsYUFDYixDQUFBO0FBQUE7QUFFSCxVQUFPLE1BQUEsQ0FBQTtBQUFBLFlBQ0wsSUFBTSxFQUFBLE9BQUE7QUFBQSxZQUNOLE9BQU8sSUFBSSxLQUFBLENBQU0sdUJBQXVCLEVBQUUsS0FBQSxFQUFPLEtBQUssQ0FBQTtBQUFBLFlBQ3RELFVBQVksRUFBQTtBQUFBLFdBQ2IsQ0FBQTtBQUFBLFNBQ0YsQ0FBQTtBQUFBO0FBQ0gsS0FDRjtBQUFBLFdBQ08sS0FBTyxFQUFBO0FBQ2QsSUFBQSxJQUFJLE9BQVMsRUFBQTtBQUNYLE1BQU8sTUFBQSxDQUFBLEtBQUE7QUFBQSxRQUNMLFdBQVcsRUFBRSxDQUFBLHVDQUFBLEVBQ1gsT0FBUSxDQUFBLEtBQUssRUFBRSxPQUNqQixDQUFBLENBQUE7QUFBQSxRQUNBLEVBQUUsS0FBTyxFQUFBLEtBQUEsWUFBaUIsS0FBUSxHQUFBLEtBQUEsR0FBUSxJQUFJLEtBQU0sQ0FBQSxNQUFBLENBQU8sS0FBSyxDQUFDLENBQUU7QUFBQSxPQUNyRTtBQUFBO0FBRUYsSUFBQSxNQUFNLGFBQWEsV0FBWSxDQUFBO0FBQUEsTUFDN0IsS0FBQTtBQUFBLE1BQ0EsTUFBQTtBQUFBLE1BQ0EsY0FBQSxFQUFnQixXQUFXLFdBQWEsRUFBQSxjQUFBO0FBQUEsTUFDeEMsUUFBVSxFQUFBLEtBRVosQ0FBQyxDQUFBO0FBQ0QsSUFBQSxJQUFJLGNBQWMsSUFBTSxFQUFBO0FBQ3RCLE1BQUEsSUFBSSxPQUFTLEVBQUE7QUFDWCxRQUFPLE1BQUEsQ0FBQSxLQUFBO0FBQUEsVUFDTCxDQUFXLFFBQUEsRUFBQSxFQUFFLENBQWlDLDhCQUFBLEVBQUEsVUFBQSxDQUFXLE9BQU8sQ0FBQSxDQUFBO0FBQUEsVUFDaEUsRUFBRSxPQUFPLFVBQVc7QUFBQSxTQUN0QjtBQUFBO0FBRUYsTUFBTyxPQUFBO0FBQUEsUUFDTCxJQUFNLEVBQUEsT0FBQTtBQUFBLFFBQ04sS0FBTyxFQUFBLFVBQUE7QUFBQSxRQUNQLFVBQVksRUFBQTtBQUFBLE9BQ2Q7QUFBQTtBQUVGLElBQU8sT0FBQTtBQUFBLE1BQ0wsSUFBTSxFQUFBLE9BQUE7QUFBQSxNQUNOLEtBQUEsRUFBTyxpQkFBaUIsS0FBUSxHQUFBLEtBQUEsR0FBUSxJQUFJLEtBQU0sQ0FBQSxNQUFBLENBQU8sS0FBSyxDQUFDLENBQUE7QUFBQSxNQUMvRCxVQUFZLEVBQUE7QUFBQSxLQUNkO0FBQUE7QUFFSjs7OzsifQ==