vite-plugin-react-server
Version:
Vite plugin for React Server Components (RSC)
352 lines (349 loc) • 49.9 kB
JavaScript
/**
* vite-plugin-react-server
* Copyright (c) Nico Brinkkemper
* MIT License
*/
import { createRenderMetrics } from '../../metrics/createRenderMetrics.js';
import { workerData } from 'node:worker_threads';
import { PassThrough } from 'node:stream';
import { createLogger } from 'vite';
import { React, ReactDOMServer } from '../../vendor/vendor.server.js';
import { createElementWithReact } from '../../helpers/createElementWithReact.js';
import { checkReactVersion } from '../../utils/checkReactVersion.js';
const handleRscRender = function _handleRscRender(handlerOptions, handlers, rscStreamOverride, headlessStreamElements, headlessStreamErrors) {
const {
id,
route,
verbose,
reuseHeadlessStreamId,
logger = createLogger(workerData.resolvedConfig?.logLevel ?? "info", {
prefix: "vite:plugin-react-server/worker/rsc"
})
} = handlerOptions;
try {
if (verbose) {
logger?.info(`[rsc-worker:${route}] Creating RSC stream`);
logger?.info(
`[rsc-worker:${route}] htmlPath in handlerOptions: "${handlerOptions.htmlPath}" (type: ${typeof handlerOptions.htmlPath})`
);
logger?.info(
`[rsc-worker:${route}] HtmlComponent in handlerOptions: ${handlerOptions.HtmlComponent ? "present" : "undefined"}`
);
}
let finalHandlerOptions = {
moduleBase: workerData.userOptions.moduleBase || "",
projectRoot: workerData.userOptions.projectRoot || process.cwd(),
cssFiles: handlerOptions["cssFiles"] || /* @__PURE__ */ new Map(),
globalCss: handlerOptions["globalCss"] || /* @__PURE__ */ new Map(),
manifest: handlerOptions["manifest"] || {},
...handlerOptions
};
if (reuseHeadlessStreamId && headlessStreamElements) {
const reusableData = headlessStreamElements.get(reuseHeadlessStreamId);
if (reusableData) {
if (verbose) {
logger?.info(
`[rsc-worker:${route}] Found reusable stream from headless stream ${reuseHeadlessStreamId}`
);
}
finalHandlerOptions = {
...finalHandlerOptions
// Don't override PageComponent, let the full stream create its own HTML structure
// but we'll use the stored Root element instead of creating a new one
};
} else if (reuseHeadlessStreamId) {
if (verbose) {
logger?.info(
`[rsc-worker:${route}] No reusable data found for headless stream ${reuseHeadlessStreamId}`
);
}
}
}
const passThrough = rscStreamOverride || handlers.getWritable?.() || new PassThrough();
let finalOptions = finalHandlerOptions;
if (reuseHeadlessStreamId && headlessStreamElements?.has(reuseHeadlessStreamId)) {
const reusableData = headlessStreamElements.get(reuseHeadlessStreamId);
if (reusableData && !reusableData.errored) {
finalOptions = {
...finalHandlerOptions,
PageComponent: reusableData.PageComponent
};
if (verbose) {
logger?.info(
`[rsc-worker:${route}] Reusing Page component from headless stream ${reuseHeadlessStreamId}`
);
}
}
}
const isHeadless = id.includes("headless");
const element = createElementWithReact(React, {
...finalOptions,
HtmlComponent: isHeadless ? React.Fragment : finalOptions.HtmlComponent,
as: isHeadless ? React.Fragment : "div"
});
if (verbose) {
logger?.info(
`[rsc-worker:${route}] About to render element for route: ${route}`
);
logger?.info(
`[rsc-worker:${route}] Element to render: ${element ? Object.keys(element).length : "null"} keys`
);
logger?.info(
`[rsc-worker:${route}] Props: ${finalHandlerOptions ? Object.keys(finalHandlerOptions).length : "null"} keys`
);
}
const isMessagePortWritable = handlers.getWritable;
if (verbose) {
logger?.info(`[rsc-worker:${route}] isMessagePortWritable: ${!!isMessagePortWritable}`);
}
if (isMessagePortWritable) {
if (verbose) {
logger?.info(`[rsc-worker:${route}] Two-port mode detected`);
}
} else {
if (verbose) {
logger?.info(`[rsc-worker:${route}] Single-port mode detected`);
}
}
const {
onPostpone: optionalOnPostpone,
onError: optionalOnError,
...rest
} = finalHandlerOptions["serverPipeableStreamOptions"] || {};
const serverPipeableStreamOptions = {
...rest,
onPostpone: (reason) => {
if (verbose) {
logger?.info(
`[rsc-worker:${route}] Component postponed (Suspense boundary): ${reason}`
);
}
if (handlers.onPostpone) {
handlers.onPostpone(id, reason);
}
if (optionalOnPostpone) {
optionalOnPostpone(reason);
}
},
onError: (error) => {
if (headlessStreamErrors && handlerOptions.htmlPath === "") {
headlessStreamErrors.set(route, error);
if (verbose) {
logger?.info(
`[rsc-worker:${route}] Tracked headless stream error for route: ${route}`
);
}
}
if (verbose) {
logger?.info(
`[rsc-worker:${route}] Sending error to main thread: ${error.message}`
);
}
handlers.onError(id, error, {
route,
context: "React stream error"
});
if (handlerOptions["onEvent"]) {
handlerOptions["onEvent"]({
type: "route.error",
data: {
error,
route,
panicThreshold: handlerOptions["panicThreshold"]
}
});
}
setImmediate(() => {
if ("destroyed" in passThrough && !passThrough.destroyed) {
passThrough.end();
}
});
if (optionalOnError) {
if (verbose) {
logger?.info(
`[rsc-worker:${route}] Error handling completed, calling optionalOnError`
);
}
optionalOnError(error);
}
if (verbose) {
logger?.info(
`[rsc-worker:${route}] onError handler finished - worker should continue normally`
);
}
}
};
if (verbose) {
logger?.info(
`[rsc-worker:${route}] *** CALLING renderToPipeableStream ***`
);
}
checkReactVersion();
const { pipe } = ReactDOMServer.renderToPipeableStream(
element,
finalHandlerOptions.moduleBasePath,
serverPipeableStreamOptions
);
if (verbose) {
logger?.info(
`[rsc-worker:${route}] *** renderToPipeableStream returned pipe function ***`
);
}
if (verbose) {
logger?.info(`[rsc-worker:${route}] *** CALLING pipe(passThrough) ***`);
}
pipe(passThrough);
if (verbose) {
logger?.info(
`[rsc-worker:${route}] *** pipe(passThrough) call completed ***`
);
}
if (isMessagePortWritable && verbose) {
logger?.info(
`[rsc-worker:${route}] Two-port mode: using standard pipe interface, React will call _final when complete`
);
}
const hasHtml = handlerOptions.htmlPath !== "" || handlerOptions.HtmlComponent;
const renderMetrics = createRenderMetrics({
type: hasHtml ? "rsc-full" : "rsc-headless",
route,
fromMainThread: false,
fromRscWorker: true,
fromHtmlWorker: false,
processingTime: 0,
chunks: 0
// No file paths in dev mode - we're not writing files
});
if (verbose) {
logger?.info(
`[rsc-worker:${route}] Setting up stream completion detection (onAllReady not working in patched version)`
);
}
if (isMessagePortWritable) {
if (verbose) {
logger?.info(`[rsc-worker:${route}] Two-port mode detected`);
}
} else {
passThrough.on("data", (chunk) => {
if (verbose) {
logger?.info(
`[rsc-worker:${route}] Single-port mode data chunk received: ${chunk.length} bytes, content: ${chunk.toString().substring(0, 100)}...`
);
}
if (verbose) {
logger?.info(
`[rsc-worker:${route}] Data chunk received, resetting completion timer. Chunk content: ${chunk.toString().substring(0, 100)}...`
);
}
handlers.onData(id, chunk);
renderMetrics.streamMetrics.chunks++;
renderMetrics.streamMetrics.bytes += chunk.length;
});
}
passThrough.on("end", () => {
if (verbose) {
logger?.info(`[rsc-worker:${route}] *** STREAM END EVENT FIRED ***`);
}
if (verbose) {
logger?.info(
`[rsc-worker:${route}] Stream completed naturally, checking for headless stream reuse`
);
}
if (headlessStreamElements && id.includes("headless") && !headlessStreamErrors?.has(route)) {
const dataToStore = {
PageComponent: finalHandlerOptions["PageComponent"],
// Store the Page component function
errored: false
};
headlessStreamElements.set(id, dataToStore);
if (verbose) {
logger?.info(
`[rsc-worker:${route}] Stored Page component for headless stream ${id}`
);
}
}
if (verbose) {
logger?.info(
`[rsc-worker:${route}] Calling handlers.onEnd(${id}) from end event to trigger completion`
);
}
handlers.onEnd(id);
renderMetrics.streamMetrics.duration = performance.now() - renderMetrics.streamMetrics.startTime;
handlers.onMetrics(id, renderMetrics);
});
passThrough.on("close", () => {
if (verbose) {
logger?.info(`[rsc-worker:${route}] *** STREAM CLOSE EVENT FIRED ***`);
}
if (headlessStreamElements && id.includes("headless") && !headlessStreamErrors?.has(route)) {
const dataToStore = {
PageComponent: finalHandlerOptions["PageComponent"],
// Store the Page component function
errored: false
};
headlessStreamElements.set(id, dataToStore);
if (verbose) {
logger?.info(
`[rsc-worker:${route}] Stored Page component for headless stream ${id} (from close event)`
);
}
}
if (verbose) {
logger?.info(
`[rsc-worker:${route}] Calling handlers.onEnd(${id}) from close event to trigger completion`
);
}
handlers.onEnd(id);
renderMetrics.streamMetrics.duration = performance.now() - renderMetrics.streamMetrics.startTime;
handlers.onMetrics(id, renderMetrics);
});
passThrough.on("pipe", (src) => {
if (verbose) {
logger?.info(
`[rsc-worker:${route}] *** STREAM PIPE EVENT FIRED *** readableEnded: ${src.readableEnded}`
);
}
});
passThrough.on("finish", () => {
if (verbose) {
logger?.info(`[rsc-worker:${route}] *** STREAM FINISH EVENT FIRED ***`);
}
});
passThrough.on("error", (error) => {
if (verbose) {
logger?.error(`[rsc-worker:${route}] Stream error: ${error}`);
}
if ("errored" in passThrough && passThrough.errored) {
return;
}
handlers.onError(id, error, {
route,
context: "RSC Stream Error"
});
handlers.onEnd(id);
if ("destroyed" in passThrough && !passThrough.destroyed) {
passThrough.end();
} else if ("end" in passThrough) {
passThrough.end();
}
});
if (verbose) {
logger?.info(
`[rsc-worker:${route}] Render setup complete for route: ${route} - function returning, worker should continue`
);
}
} catch (error) {
if (verbose) {
logger?.error(
`[rsc-worker:${route}] Error in handleRender: ${error?.message ?? "no message"}`
);
}
handlers.onError(id, error, {
route,
context: "RSC Worker Error"
});
handlers.onEnd(id);
}
};
export { handleRscRender };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFuZGxlUnNjUmVuZGVyLnNlcnZlci5qcyIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcGx1Z2luL3dvcmtlci9yc2MvaGFuZGxlUnNjUmVuZGVyLnNlcnZlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjcmVhdGVSZW5kZXJNZXRyaWNzIH0gZnJvbSBcIi4uLy4uL2hlbHBlcnMvbWV0cmljcy5qc1wiO1xuaW1wb3J0IHsgd29ya2VyRGF0YSB9IGZyb20gXCJub2RlOndvcmtlcl90aHJlYWRzXCI7XG5pbXBvcnQgeyBQYXNzVGhyb3VnaCB9IGZyb20gXCJub2RlOnN0cmVhbVwiO1xuaW1wb3J0IHR5cGUgeyBIYW5kbGVSc2NSZW5kZXJGbiB9IGZyb20gXCIuL3R5cGVzLmpzXCI7XG5pbXBvcnQgeyBjcmVhdGVMb2dnZXIgfSBmcm9tIFwidml0ZVwiO1xuaW1wb3J0IHtcbiAgUmVhY3QsXG4gIFJlYWN0RE9NU2VydmVyLFxuICB0eXBlIFJlbmRlclRvUGlwZWFibGVTdHJlYW1PcHRpb25zLFxufSBmcm9tIFwiLi4vLi4vdmVuZG9yL3ZlbmRvci5zZXJ2ZXIuanNcIjtcbmltcG9ydCB7IGNyZWF0ZUVsZW1lbnRXaXRoUmVhY3QgfSBmcm9tIFwiLi4vLi4vaGVscGVycy9jcmVhdGVFbGVtZW50V2l0aFJlYWN0LmpzXCI7XG5pbXBvcnQgeyBjaGVja1JlYWN0VmVyc2lvbiB9IGZyb20gXCIuLi8uLi91dGlscy9jaGVja1JlYWN0VmVyc2lvbi5qc1wiO1xuLyoqXG4gKiBIYW5kbGVzIHRoZSByZW5kZXJpbmcgb2YgUmVhY3QgU2VydmVyIENvbXBvbmVudCBzdHJlYW1zIGluIHRoZSBSU0Mgd29ya2VyIHRocmVhZC5cbiAqXG4gKiAqKlB1cnBvc2UqKjogQ3JlYXRlcyBSZWFjdCBTZXJ2ZXIgQ29tcG9uZW50IHN0cmVhbXMgdXNpbmcgUmVhY3RET01TZXJ2ZXIucmVuZGVyVG9QaXBlYWJsZVN0cmVhbVxuICogYW5kIG1hbmFnZXMgdGhlIHN0cmVhbSBsaWZlY3ljbGUsIGVycm9yIGhhbmRsaW5nLCBhbmQgZWxlbWVudCByZXVzZSBmb3IgcGVyZm9ybWFuY2Ugb3B0aW1pemF0aW9uLlxuICpcbiAqICoqS2V5IEZlYXR1cmVzKio6XG4gKiAtICoqU3RyZWFtIENyZWF0aW9uKio6IFVzZXMgUmVhY3RET01TZXJ2ZXIucmVuZGVyVG9QaXBlYWJsZVN0cmVhbSBmb3IgUlNDIHJlbmRlcmluZ1xuICogLSAqKkVycm9yIEhhbmRsaW5nKio6IENhdGNoZXMgUmVhY3QgcmVuZGVyaW5nIGVycm9ycyB2aWEgb25FcnJvciBjYWxsYmFjayBhbmQgY29tbXVuaWNhdGVzIHRvIG1haW4gdGhyZWFkXG4gKiAtICoqU3RyZWFtIFJldXNlKio6IE1hbmFnZXMgaGVhZGxlc3Mgc3RyZWFtIGVsZW1lbnQgcmV1c2UgZm9yIHBlcmZvcm1hbmNlIG9wdGltaXphdGlvblxuICogLSAqKk1ldHJpY3MgQ29sbGVjdGlvbioqOiBUcmFja3MgcmVuZGVyaW5nIHBlcmZvcm1hbmNlIGFuZCBtZW1vcnkgdXNhZ2VcbiAqXG4gKiAqKkVycm9yIEhhbmRsaW5nIFN0cmF0ZWd5Kio6XG4gKiAtIFJlYWN0IHJlbmRlcmluZyBlcnJvcnMgYXJlIGNhdWdodCBieSBSZWFjdERPTVNlcnZlci5vbkVycm9yIGNhbGxiYWNrXG4gKiAtIEVycm9ycyBhcmUgc2VudCB0byBtYWluIHRocmVhZCB2aWEgaGFuZGxlcnMub25FcnJvciB3aXRoIGNvbnRleHQgaW5mb3JtYXRpb25cbiAqIC0gSGVhZGxlc3Mgc3RyZWFtIGVycm9ycyBhcmUgdHJhY2tlZCBmb3IgY29uZGl0aW9uYWwgcmV1c2UgbG9naWNcbiAqIC0gU3RyZWFtIGlzIHByb3Blcmx5IGVuZGVkIGV2ZW4gd2hlbiBlcnJvcnMgb2NjdXJcbiAqXG4gKiAqKlN0cmVhbSBUeXBlcyoqOlxuICogLSAqKkhlYWRsZXNzIFN0cmVhbXMqKjogUGFnZSBjb250ZW50IG9ubHkgKG5vIEhUTUwgd3JhcHBlcikgZm9yIC5yc2MgZmlsZXNcbiAqIC0gKipGdWxsIFN0cmVhbXMqKjogQ29tcGxldGUgSFRNTCBzdHJ1Y3R1cmUgZm9yIEhUTUwgZ2VuZXJhdGlvblxuICpcbiAqIEBwYXJhbSBoYW5kbGVyT3B0aW9ucyAtIENvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgUlNDIHJlbmRlcmluZ1xuICogQHBhcmFtIGhhbmRsZXJzIC0gRXZlbnQgaGFuZGxlcnMgZm9yIHN0cmVhbSBsaWZlY3ljbGUgbWFuYWdlbWVudFxuICogQHBhcmFtIHJzY1N0cmVhbU92ZXJyaWRlIC0gT3B0aW9uYWwgb3ZlcnJpZGUgZm9yIFJTQyBzdHJlYW0gKGZvciB0ZXN0aW5nKVxuICogQHBhcmFtIGhlYWRsZXNzU3RyZWFtRWxlbWVudHMgLSBNYXAgZm9yIHN0b3JpbmcgcmV1c2FibGUgaGVhZGxlc3Mgc3RyZWFtIGVsZW1lbnRzXG4gKiBAcGFyYW0gaGVhZGxlc3NTdHJlYW1FcnJvcnMgLSBNYXAgZm9yIHRyYWNraW5nIGhlYWRsZXNzIHN0cmVhbSBlcnJvcnNcbiAqIEByZXR1cm5zIFJTQyBzdHJlYW0gcmVzdWx0IHdpdGggbWV0cmljcyBhbmQgbGlmZWN5Y2xlIG1hbmFnZW1lbnRcbiAqL1xuZXhwb3J0IGNvbnN0IGhhbmRsZVJzY1JlbmRlcjogSGFuZGxlUnNjUmVuZGVyRm4gPSBmdW5jdGlvbiBfaGFuZGxlUnNjUmVuZGVyKFxuICBoYW5kbGVyT3B0aW9ucyxcbiAgaGFuZGxlcnMsXG4gIHJzY1N0cmVhbU92ZXJyaWRlLFxuICBoZWFkbGVzc1N0cmVhbUVsZW1lbnRzLFxuICBoZWFkbGVzc1N0cmVhbUVycm9yc1xuKSB7XG4gIGNvbnN0IHtcbiAgICBpZCxcbiAgICByb3V0ZSxcbiAgICB2ZXJib3NlLFxuICAgIHJldXNlSGVhZGxlc3NTdHJlYW1JZCxcbiAgICBsb2dnZXIgPSBjcmVhdGVMb2dnZXIod29ya2VyRGF0YS5yZXNvbHZlZENvbmZpZz8ubG9nTGV2ZWwgPz8gXCJpbmZvXCIsIHtcbiAgICAgIHByZWZpeDogXCJ2aXRlOnBsdWdpbi1yZWFjdC1zZXJ2ZXIvd29ya2VyL3JzY1wiLFxuICAgIH0pLFxuICB9ID0gaGFuZGxlck9wdGlvbnM7XG5cblxuICB0cnkge1xuICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICBsb2dnZXI/LmluZm8oYFtyc2Mtd29ya2VyOiR7cm91dGV9XSBDcmVhdGluZyBSU0Mgc3RyZWFtYCk7XG4gICAgICBsb2dnZXI/LmluZm8oXG4gICAgICAgIGBbcnNjLXdvcmtlcjoke3JvdXRlfV0gaHRtbFBhdGggaW4gaGFuZGxlck9wdGlvbnM6IFwiJHtcbiAgICAgICAgICBoYW5kbGVyT3B0aW9ucy5odG1sUGF0aFxuICAgICAgICB9XCIgKHR5cGU6ICR7dHlwZW9mIGhhbmRsZXJPcHRpb25zLmh0bWxQYXRofSlgXG4gICAgICApO1xuICAgICAgbG9nZ2VyPy5pbmZvKFxuICAgICAgICBgW3JzYy13b3JrZXI6JHtyb3V0ZX1dIEh0bWxDb21wb25lbnQgaW4gaGFuZGxlck9wdGlvbnM6ICR7XG4gICAgICAgICAgaGFuZGxlck9wdGlvbnMuSHRtbENvbXBvbmVudCA/IFwicHJlc2VudFwiIDogXCJ1bmRlZmluZWRcIlxuICAgICAgICB9YFxuICAgICAgKTtcbiAgICB9XG4gICAgLy8gQ2hlY2sgZm9yIHJldXNhYmxlIGVsZW1lbnRzIGZyb20gaGVhZGxlc3Mgc3RyZWFtXG4gICAgbGV0IGZpbmFsSGFuZGxlck9wdGlvbnMgPSB7XG4gICAgICBtb2R1bGVCYXNlOiB3b3JrZXJEYXRhLnVzZXJPcHRpb25zLm1vZHVsZUJhc2UgfHwgXCJcIixcbiAgICAgIHByb2plY3RSb290OiB3b3JrZXJEYXRhLnVzZXJPcHRpb25zLnByb2plY3RSb290IHx8IHByb2Nlc3MuY3dkKCksXG4gICAgICBjc3NGaWxlczogaGFuZGxlck9wdGlvbnNbXCJjc3NGaWxlc1wiXSB8fCBuZXcgTWFwKCksXG4gICAgICBnbG9iYWxDc3M6IGhhbmRsZXJPcHRpb25zW1wiZ2xvYmFsQ3NzXCJdIHx8IG5ldyBNYXAoKSxcbiAgICAgIG1hbmlmZXN0OiBoYW5kbGVyT3B0aW9uc1tcIm1hbmlmZXN0XCJdIHx8IHt9LFxuICAgICAgLi4uaGFuZGxlck9wdGlvbnMsXG4gICAgfTtcbiAgICBpZiAocmV1c2VIZWFkbGVzc1N0cmVhbUlkICYmIGhlYWRsZXNzU3RyZWFtRWxlbWVudHMpIHtcbiAgICAgIGNvbnN0IHJldXNhYmxlRGF0YSA9IGhlYWRsZXNzU3RyZWFtRWxlbWVudHMuZ2V0KHJldXNlSGVhZGxlc3NTdHJlYW1JZCk7XG4gICAgICBpZiAocmV1c2FibGVEYXRhKSB7XG4gICAgICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICAgICAgbG9nZ2VyPy5pbmZvKFxuICAgICAgICAgICAgYFtyc2Mtd29ya2VyOiR7cm91dGV9XSBGb3VuZCByZXVzYWJsZSBzdHJlYW0gZnJvbSBoZWFkbGVzcyBzdHJlYW0gJHtyZXVzZUhlYWRsZXNzU3RyZWFtSWR9YFxuICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBVc2UgdGhlIHN0b3JlZCBSb290IGVsZW1lbnQgZGlyZWN0bHkgZm9yIHRoZSBmdWxsIHN0cmVhbVxuICAgICAgICBmaW5hbEhhbmRsZXJPcHRpb25zID0ge1xuICAgICAgICAgIC4uLmZpbmFsSGFuZGxlck9wdGlvbnMsXG4gICAgICAgICAgLy8gRG9uJ3Qgb3ZlcnJpZGUgUGFnZUNvbXBvbmVudCwgbGV0IHRoZSBmdWxsIHN0cmVhbSBjcmVhdGUgaXRzIG93biBIVE1MIHN0cnVjdHVyZVxuICAgICAgICAgIC8vIGJ1dCB3ZSdsbCB1c2UgdGhlIHN0b3JlZCBSb290IGVsZW1lbnQgaW5zdGVhZCBvZiBjcmVhdGluZyBhIG5ldyBvbmVcbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSBpZiAocmV1c2VIZWFkbGVzc1N0cmVhbUlkKSB7XG4gICAgICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICAgICAgbG9nZ2VyPy5pbmZvKFxuICAgICAgICAgICAgYFtyc2Mtd29ya2VyOiR7cm91dGV9XSBObyByZXVzYWJsZSBkYXRhIGZvdW5kIGZvciBoZWFkbGVzcyBzdHJlYW0gJHtyZXVzZUhlYWRsZXNzU3RyZWFtSWR9YFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBwYXNzVGhyb3VnaCA9XG4gICAgICByc2NTdHJlYW1PdmVycmlkZSB8fCBoYW5kbGVycy5nZXRXcml0YWJsZT8uKCkgfHwgbmV3IFBhc3NUaHJvdWdoKCk7XG5cbiAgICAvLyBObyBuZWVkIHRvIGNvbGxlY3QgY2h1bmtzIHNpbmNlIHdlJ3JlIHN0b3JpbmcgdGhlIFJlYWN0IGVsZW1lbnQgZGlyZWN0bHlcblxuICAgIC8vIENoZWNrIGlmIHdlIHNob3VsZCByZXVzZSBhIFBhZ2UgY29tcG9uZW50IGZyb20gYSBoZWFkbGVzcyBzdHJlYW1cbiAgICBsZXQgZmluYWxPcHRpb25zID0gZmluYWxIYW5kbGVyT3B0aW9ucztcbiAgICBpZiAoXG4gICAgICByZXVzZUhlYWRsZXNzU3RyZWFtSWQgJiZcbiAgICAgIGhlYWRsZXNzU3RyZWFtRWxlbWVudHM/LmhhcyhyZXVzZUhlYWRsZXNzU3RyZWFtSWQpXG4gICAgKSB7XG4gICAgICBjb25zdCByZXVzYWJsZURhdGEgPSBoZWFkbGVzc1N0cmVhbUVsZW1lbnRzLmdldChyZXVzZUhlYWRsZXNzU3RyZWFtSWQpO1xuICAgICAgaWYgKHJldXNhYmxlRGF0YSAmJiAhcmV1c2FibGVEYXRhLmVycm9yZWQpIHtcbiAgICAgICAgLy8gVXNlIHRoZSBzdG9yZWQgUGFnZSBjb21wb25lbnQgZnJvbSB0aGUgaGVhZGxlc3Mgc3RyZWFtXG4gICAgICAgIGZpbmFsT3B0aW9ucyA9IHtcbiAgICAgICAgICAuLi5maW5hbEhhbmRsZXJPcHRpb25zLFxuICAgICAgICAgIFBhZ2VDb21wb25lbnQ6IHJldXNhYmxlRGF0YS5QYWdlQ29tcG9uZW50LFxuICAgICAgICB9O1xuICAgICAgICBpZiAodmVyYm9zZSkge1xuICAgICAgICAgIGxvZ2dlcj8uaW5mbyhcbiAgICAgICAgICAgIGBbcnNjLXdvcmtlcjoke3JvdXRlfV0gUmV1c2luZyBQYWdlIGNvbXBvbmVudCBmcm9tIGhlYWRsZXNzIHN0cmVhbSAke3JldXNlSGVhZGxlc3NTdHJlYW1JZH1gXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEhlYWRsZXNzIHN0cmVhbXMgdXNlIGEgRnJhZ21lbnQgaW5zdGVhZCBvZiB0aGUgSHRtbCB3cmFwcGVyOyBmdWxsIHN0cmVhbXNcbiAgICAvLyBrZWVwIHRoZSByZWFsIEh0bWwgY29tcG9uZW50LiBjcmVhdGVFbGVtZW50V2l0aFJlYWN0IHJlYWRzIGBIdG1sQ29tcG9uZW50YCxcbiAgICAvLyBOT1QgYEh0bWxgIOKAlCBzbyB0aGUgcHJldmlvdXMgYEh0bWw6IEZyYWdtZW50YCB3YXMgc2lsZW50bHkgaWdub3JlZCwgdGhlXG4gICAgLy8gb3ZlcnJpZGUgbmV2ZXIgYXBwbGllZCwgYW5kIHRoZSBoZWFkbGVzcyBzdHJlYW0gZW1pdHRlZCB0aGUgZnVsbCA8aHRtbD5cbiAgICAvLyBkb2N1bWVudC4gU2V0IHRoZSBrZXkgdGhlIGhlbHBlciBhY3R1YWxseSByZWFkcy5cbiAgICBjb25zdCBpc0hlYWRsZXNzID0gaWQuaW5jbHVkZXMoXCJoZWFkbGVzc1wiKTtcbiAgICBjb25zdCBlbGVtZW50ID0gY3JlYXRlRWxlbWVudFdpdGhSZWFjdChSZWFjdCwge1xuICAgICAgLi4uZmluYWxPcHRpb25zLFxuICAgICAgSHRtbENvbXBvbmVudDogaXNIZWFkbGVzcyA/IFJlYWN0LkZyYWdtZW50IDogZmluYWxPcHRpb25zLkh0bWxDb21wb25lbnQsXG4gICAgICBhczogaXNIZWFkbGVzcyA/IFJlYWN0LkZyYWdtZW50IDogXCJkaXZcIixcbiAgICB9KTtcbiAgICBpZiAodmVyYm9zZSkge1xuICAgICAgbG9nZ2VyPy5pbmZvKFxuICAgICAgICBgW3JzYy13b3JrZXI6JHtyb3V0ZX1dIEFib3V0IHRvIHJlbmRlciBlbGVtZW50IGZvciByb3V0ZTogJHtyb3V0ZX1gXG4gICAgICApO1xuICAgICAgbG9nZ2VyPy5pbmZvKFxuICAgICAgICBgW3JzYy13b3JrZXI6JHtyb3V0ZX1dIEVsZW1lbnQgdG8gcmVuZGVyOiAke2VsZW1lbnQgPyBPYmplY3Qua2V5cyhlbGVtZW50KS5sZW5ndGggOiAnbnVsbCd9IGtleXNgXG4gICAgICApO1xuICAgICAgbG9nZ2VyPy5pbmZvKFxuICAgICAgICBgW3JzYy13b3JrZXI6JHtyb3V0ZX1dIFByb3BzOiAke2ZpbmFsSGFuZGxlck9wdGlvbnMgPyBPYmplY3Qua2V5cyhmaW5hbEhhbmRsZXJPcHRpb25zKS5sZW5ndGggOiAnbnVsbCd9IGtleXNgXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIFNldCB1cCBjb21wbGV0aW9uIGRldGVjdGlvbiBsb2dpYyBiZWZvcmUgUmVhY3QgY2FsbGJhY2tzXG4gICAgY29uc3QgaXNNZXNzYWdlUG9ydFdyaXRhYmxlID0gaGFuZGxlcnMuZ2V0V3JpdGFibGU7XG5cbiAgICBpZiAodmVyYm9zZSkge1xuICAgICAgbG9nZ2VyPy5pbmZvKGBbcnNjLXdvcmtlcjoke3JvdXRlfV0gaXNNZXNzYWdlUG9ydFdyaXRhYmxlOiAkeyEhaXNNZXNzYWdlUG9ydFdyaXRhYmxlfWApO1xuICAgIH1cblxuICAgIGlmIChpc01lc3NhZ2VQb3J0V3JpdGFibGUpIHtcbiAgICAgIC8vIFR3by1wb3J0IG1vZGU6IFRoZSBzdHJlYW0gd2lsbCBjb21wbGV0ZSBuYXR1cmFsbHkgd2hlbiBSZWFjdCBmaW5pc2hlc1xuICAgICAgLy8gTm8gbWFudWFsIGNvbXBsZXRpb24gbG9naWMgbmVlZGVkIC0gUmVhY3Qgd2lsbCBzaWduYWwgY29tcGxldGlvbiB0aHJvdWdoIHByb3BlciBzdHJlYW0gZXZlbnRzXG4gICAgICBpZiAodmVyYm9zZSkge1xuICAgICAgICBsb2dnZXI/LmluZm8oYFtyc2Mtd29ya2VyOiR7cm91dGV9XSBUd28tcG9ydCBtb2RlIGRldGVjdGVkYCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICAgIGxvZ2dlcj8uaW5mbyhgW3JzYy13b3JrZXI6JHtyb3V0ZX1dIFNpbmdsZS1wb3J0IG1vZGUgZGV0ZWN0ZWRgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCB7XG4gICAgICBvblBvc3Rwb25lOiBvcHRpb25hbE9uUG9zdHBvbmUsXG4gICAgICBvbkVycm9yOiBvcHRpb25hbE9uRXJyb3IsXG4gICAgICAuLi5yZXN0XG4gICAgfSA9IGZpbmFsSGFuZGxlck9wdGlvbnNbXCJzZXJ2ZXJQaXBlYWJsZVN0cmVhbU9wdGlvbnNcIl0gfHwge307XG4gICAgY29uc3Qgc2VydmVyUGlwZWFibGVTdHJlYW1PcHRpb25zOiBSZW5kZXJUb1BpcGVhYmxlU3RyZWFtT3B0aW9ucyA9IHtcbiAgICAgIC4uLnJlc3QsXG4gICAgICBvblBvc3Rwb25lOiAocmVhc29uOiBzdHJpbmcpID0+IHtcbiAgICAgICAgaWYgKHZlcmJvc2UpIHtcbiAgICAgICAgICBsb2dnZXI/LmluZm8oXG4gICAgICAgICAgICBgW3JzYy13b3JrZXI6JHtyb3V0ZX1dIENvbXBvbmVudCBwb3N0cG9uZWQgKFN1c3BlbnNlIGJvdW5kYXJ5KTogJHtyZWFzb259YFxuICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBvblBvc3Rwb25lIGlzIGZvciBTdXNwZW5zZSBib3VuZGFyaWVzIHdoZW4gY29tcG9uZW50cyBhcmUgZGVmZXJyZWRcbiAgICAgICAgLy8gVGhpcyBpcyBub3QgYWJvdXQgYmFja3ByZXNzdXJlIC0gaXQncyBhYm91dCBsYXp5IGxvYWRpbmcgYW5kIGNvbXBvbmVudCBzdXNwZW5zaW9uXG4gICAgICAgIC8vIEhhbmRsZSB0aHJvdWdoIG5vcm1hbCBoYW5kbGVyIGNoYWluLCBub3QgYXMgYSBzdHJlYW0gY29udHJvbCBzaWduYWxcblxuICAgICAgICBpZiAoaGFuZGxlcnMub25Qb3N0cG9uZSkge1xuICAgICAgICAgIGhhbmRsZXJzLm9uUG9zdHBvbmUoaWQsIHJlYXNvbik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wdGlvbmFsT25Qb3N0cG9uZSkge1xuICAgICAgICAgIG9wdGlvbmFsT25Qb3N0cG9uZShyZWFzb24pO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgb25FcnJvcjogKGVycm9yOiBhbnkpID0+IHtcbiAgICAgICAgLy8gVHJhY2sgaGVhZGxlc3Mgc3RyZWFtIGVycm9ycyBmb3IgY29uZGl0aW9uYWwgcmV1c2UgbG9naWNcbiAgICAgICAgaWYgKGhlYWRsZXNzU3RyZWFtRXJyb3JzICYmIGhhbmRsZXJPcHRpb25zLmh0bWxQYXRoID09PSBcIlwiKSB7XG4gICAgICAgICAgLy8gVGhpcyBpcyBhIGhlYWRsZXNzIHN0cmVhbSAoaHRtbFBhdGggaXMgZW1wdHkpLCB0cmFjayB0aGUgZXJyb3JcbiAgICAgICAgICBoZWFkbGVzc1N0cmVhbUVycm9ycy5zZXQocm91dGUsIGVycm9yKTtcbiAgICAgICAgICBpZiAodmVyYm9zZSkge1xuICAgICAgICAgICAgbG9nZ2VyPy5pbmZvKFxuICAgICAgICAgICAgICBgW3JzYy13b3JrZXI6JHtyb3V0ZX1dIFRyYWNrZWQgaGVhZGxlc3Mgc3RyZWFtIGVycm9yIGZvciByb3V0ZTogJHtyb3V0ZX1gXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG5cblxuICAgICAgICAvLyBTZW5kIGVycm9yIHRocm91Z2ggdG9Xb3JrZXIgZm9yIG1ldHJpY3MvbG9nZ2luZ1xuICAgICAgICBpZiAodmVyYm9zZSkge1xuICAgICAgICAgIGxvZ2dlcj8uaW5mbyhcbiAgICAgICAgICAgIGBbcnNjLXdvcmtlcjoke3JvdXRlfV0gU2VuZGluZyBlcnJvciB0byBtYWluIHRocmVhZDogJHtlcnJvci5tZXNzYWdlfWBcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGhhbmRsZXJzLm9uRXJyb3IoaWQsIGVycm9yLCB7XG4gICAgICAgICAgcm91dGU6IHJvdXRlLFxuICAgICAgICAgIGNvbnRleHQ6IFwiUmVhY3Qgc3RyZWFtIGVycm9yXCIsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEVtaXQgcm91dGUuZXJyb3IgZXZlbnQgdG8gYWxsb3cgbWFpbiB0aHJlYWQgdG8gaGFuZGxlIHBhbmljIHRocmVzaG9sZCBsb2dpYyAobGlrZSBzZXJ2ZXItc2lkZSlcbiAgICAgICAgaWYgKGhhbmRsZXJPcHRpb25zWydvbkV2ZW50J10pIHtcbiAgICAgICAgICBoYW5kbGVyT3B0aW9uc1snb25FdmVudCddKHtcbiAgICAgICAgICAgIHR5cGU6IFwicm91dGUuZXJyb3JcIixcbiAgICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgICAgZXJyb3I6IGVycm9yLFxuICAgICAgICAgICAgICByb3V0ZTogcm91dGUsXG4gICAgICAgICAgICAgIHBhbmljVGhyZXNob2xkOiBoYW5kbGVyT3B0aW9uc1sncGFuaWNUaHJlc2hvbGQnXVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ1JJVElDQUw6IEVuc3VyZSBzdHJlYW0gaXMgZW5kZWQgd2hlbiBlcnJvciBvY2N1cnMgdG8gcHJldmVudCBoYW5naW5nIChsaWtlIHNlcnZlci1zaWRlIGRvZXMpXG4gICAgICAgIC8vIFVzZSBzZXRJbW1lZGlhdGUgdG8gZW5zdXJlIHRoZSBlcnJvciBoYW5kbGVyIGNvbXBsZXRlcyBiZWZvcmUgZW5kaW5nIHRoZSBzdHJlYW1cbiAgICAgICAgc2V0SW1tZWRpYXRlKCgpID0+IHtcbiAgICAgICAgICBpZiAoJ2Rlc3Ryb3llZCcgaW4gcGFzc1Rocm91Z2ggJiYgIXBhc3NUaHJvdWdoLmRlc3Ryb3llZCkge1xuICAgICAgICAgICAgcGFzc1Rocm91Z2guZW5kKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAob3B0aW9uYWxPbkVycm9yKSB7XG4gICAgICAgICAgaWYgKHZlcmJvc2UpIHtcbiAgICAgICAgICAgIGxvZ2dlcj8uaW5mbyhcbiAgICAgICAgICAgICAgYFtyc2Mtd29ya2VyOiR7cm91dGV9XSBFcnJvciBoYW5kbGluZyBjb21wbGV0ZWQsIGNhbGxpbmcgb3B0aW9uYWxPbkVycm9yYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgb3B0aW9uYWxPbkVycm9yKGVycm9yKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICAgICAgbG9nZ2VyPy5pbmZvKFxuICAgICAgICAgICAgYFtyc2Mtd29ya2VyOiR7cm91dGV9XSBvbkVycm9yIGhhbmRsZXIgZmluaXNoZWQgLSB3b3JrZXIgc2hvdWxkIGNvbnRpbnVlIG5vcm1hbGx5YFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSBzYXRpc2ZpZXMgUmVuZGVyVG9QaXBlYWJsZVN0cmVhbU9wdGlvbnM7XG5cbiAgICBpZiAodmVyYm9zZSkge1xuICAgICAgbG9nZ2VyPy5pbmZvKFxuICAgICAgICBgW3JzYy13b3JrZXI6JHtyb3V0ZX1dICoqKiBDQUxMSU5HIHJlbmRlclRvUGlwZWFibGVTdHJlYW0gKioqYFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjaGVja1JlYWN0VmVyc2lvbigpO1xuICAgIGNvbnN0IHsgcGlwZSB9ID0gUmVhY3RET01TZXJ2ZXIucmVuZGVyVG9QaXBlYWJsZVN0cmVhbShcbiAgICAgIGVsZW1lbnQsXG4gICAgICBmaW5hbEhhbmRsZXJPcHRpb25zLm1vZHVsZUJhc2VQYXRoLFxuICAgICAgc2VydmVyUGlwZWFibGVTdHJlYW1PcHRpb25zXG4gICAgKTtcblxuICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICBsb2dnZXI/LmluZm8oXG4gICAgICAgIGBbcnNjLXdvcmtlcjoke3JvdXRlfV0gKioqIHJlbmRlclRvUGlwZWFibGVTdHJlYW0gcmV0dXJuZWQgcGlwZSBmdW5jdGlvbiAqKipgXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICBsb2dnZXI/LmluZm8oYFtyc2Mtd29ya2VyOiR7cm91dGV9XSAqKiogQ0FMTElORyBwaXBlKHBhc3NUaHJvdWdoKSAqKipgKTtcbiAgICB9XG5cbiAgICBwaXBlKHBhc3NUaHJvdWdoKTtcblxuICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICBsb2dnZXI/LmluZm8oXG4gICAgICAgIGBbcnNjLXdvcmtlcjoke3JvdXRlfV0gKioqIHBpcGUocGFzc1Rocm91Z2gpIGNhbGwgY29tcGxldGVkICoqKmBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gVHdvLXBvcnQgbW9kZTogUmVhY3Qgd2lsbCBuYXR1cmFsbHkgZW5kIHRoZSBzdHJlYW0gd2hlbiBkb25lIHJlbmRlcmluZ1xuICAgIGlmIChpc01lc3NhZ2VQb3J0V3JpdGFibGUgJiYgdmVyYm9zZSkge1xuICAgICAgbG9nZ2VyPy5pbmZvKFxuICAgICAgICBgW3JzYy13b3JrZXI6JHtyb3V0ZX1dIFR3by1wb3J0IG1vZGU6IHVzaW5nIHN0YW5kYXJkIHBpcGUgaW50ZXJmYWNlLCBSZWFjdCB3aWxsIGNhbGwgX2ZpbmFsIHdoZW4gY29tcGxldGVgXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIExldCBlcnJvcnMgZmxvdyB0aHJvdWdoIHRoZSBzdHJlYW0gbmF0dXJhbGx5IC0gbWFpbiB0aHJlYWQgd2lsbCBoYW5kbGUgdGhlbVxuXG4gICAgLy8gU2V0IHVwIHN0cmVhbSBoYW5kbGluZyB1c2luZyBvdXIgaGVscGVyXG4gICAgY29uc3QgaGFzSHRtbCA9XG4gICAgICBoYW5kbGVyT3B0aW9ucy5odG1sUGF0aCAhPT0gXCJcIiB8fCBoYW5kbGVyT3B0aW9ucy5IdG1sQ29tcG9uZW50O1xuXG4gICAgLy8gSW4gZGV2IG1vZGUsIGRvbid0IHVzZSBmaWxlLWJhc2VkIG1ldHJpY3MgYXQgYWxsIC0ganVzdCB0cmFjayB0aGUgc3RyZWFtXG4gICAgY29uc3QgcmVuZGVyTWV0cmljcyA9IGNyZWF0ZVJlbmRlck1ldHJpY3Moe1xuICAgICAgdHlwZTogaGFzSHRtbCA/IFwicnNjLWZ1bGxcIiA6IFwicnNjLWhlYWRsZXNzXCIsXG4gICAgICByb3V0ZSxcbiAgICAgIGZyb21NYWluVGhyZWFkOiBmYWxzZSxcbiAgICAgIGZyb21Sc2NXb3JrZXI6IHRydWUsXG4gICAgICBmcm9tSHRtbFdvcmtlcjogZmFsc2UsXG4gICAgICBwcm9jZXNzaW5nVGltZTogMCxcbiAgICAgIGNodW5rczogMCxcbiAgICAgIC8vIE5vIGZpbGUgcGF0aHMgaW4gZGV2IG1vZGUgLSB3ZSdyZSBub3Qgd3JpdGluZyBmaWxlc1xuICAgIH0pO1xuXG5cbiAgICAvLyBTZXQgdXAgY29tcGxldGlvbiBkZXRlY3Rpb24gYmFzZWQgb24gc3RyZWFtIHR5cGVcblxuICAgIC8vIFNldCB1cCBjb21wbGV0aW9uIGRldGVjdGlvbiBmb3IgYm90aCBzaW5nbGUtcG9ydCBhbmQgdHdvLXBvcnQgbW9kZXNcbiAgICAvLyBTaW5jZSBvbkFsbFJlYWR5IGlzIG5vdCB3b3JraW5nIGluIHRoZSBwYXRjaGVkIHZlcnNpb24sIHVzZSBzdHJlYW0gZW5kIGV2ZW50XG4gICAgaWYgKHZlcmJvc2UpIHtcbiAgICAgIGxvZ2dlcj8uaW5mbyhcbiAgICAgICAgYFtyc2Mtd29ya2VyOiR7cm91dGV9XSBTZXR0aW5nIHVwIHN0cmVhbSBjb21wbGV0aW9uIGRldGVjdGlvbiAob25BbGxSZWFkeSBub3Qgd29ya2luZyBpbiBwYXRjaGVkIHZlcnNpb24pYFxuICAgICAgKTtcbiAgICB9XG4gICAgXG4gICAgaWYgKGlzTWVzc2FnZVBvcnRXcml0YWJsZSkge1xuICAgICAgLy8gVHdvLXBvcnQgbW9kZTogbW9uaXRvciBkYXRhIGZsb3dcbiAgICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICAgIGxvZ2dlcj8uaW5mbyhgW3JzYy13b3JrZXI6JHtyb3V0ZX1dIFR3by1wb3J0IG1vZGUgZGV0ZWN0ZWRgKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gU2luZ2xlLXBvcnQgbW9kZTogU2V0IHVwIGRhdGEtYmFzZWQgY29tcGxldGlvbiBkZXRlY3Rpb25cblxuICAgICAgcGFzc1Rocm91Z2gub24oXCJkYXRhXCIsIChjaHVuazogQnVmZmVyKSA9PiB7XG4gICAgICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICAgICAgbG9nZ2VyPy5pbmZvKFxuICAgICAgICAgICAgYFtyc2Mtd29ya2VyOiR7cm91dGV9XSBTaW5nbGUtcG9ydCBtb2RlIGRhdGEgY2h1bmsgcmVjZWl2ZWQ6ICR7XG4gICAgICAgICAgICAgIGNodW5rLmxlbmd0aFxuICAgICAgICAgICAgfSBieXRlcywgY29udGVudDogJHtjaHVuay50b1N0cmluZygpLnN1YnN0cmluZygwLCAxMDApfS4uLmBcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGF0YSBjaHVuayByZWNlaXZlZFxuXG4gICAgICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICAgICAgbG9nZ2VyPy5pbmZvKFxuICAgICAgICAgICAgYFtyc2Mtd29ya2VyOiR7cm91dGV9XSBEYXRhIGNodW5rIHJlY2VpdmVkLCByZXNldHRpbmcgY29tcGxldGlvbiB0aW1lci4gQ2h1bmsgY29udGVudDogJHtjaHVua1xuICAgICAgICAgICAgICAudG9TdHJpbmcoKVxuICAgICAgICAgICAgICAuc3Vic3RyaW5nKDAsIDEwMCl9Li4uYFxuICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDYWxsIG9uRGF0YSBmb3IgYm90aCBzaW5nbGUtcG9ydCBhbmQgdHdvLXBvcnQgY29tbXVuaWNhdGlvblxuICAgICAgICBoYW5kbGVycy5vbkRhdGEoaWQsIGNodW5rKTtcbiAgICAgICAgcmVuZGVyTWV0cmljcy5zdHJlYW1NZXRyaWNzLmNodW5rcysrO1xuICAgICAgICByZW5kZXJNZXRyaWNzLnN0cmVhbU1ldHJpY3MuYnl0ZXMgKz0gY2h1bmsubGVuZ3RoO1xuXG4gICAgICAgIC8vIERhdGEgcmVjZWl2ZWRcbiAgICAgIH0pO1xuICAgIH0gLy8gRW5kIG9mIHNpbmdsZS1wb3J0IG1vZGUgZWxzZSBibG9ja1xuXG4gICAgLy8gVW5pZmllZCBzdHJlYW0gZW5kIGhhbmRsZXIgZm9yIGJvdGggc2luZ2xlLXBvcnQgYW5kIHR3by1wb3J0IG1vZGVzXG4gICAgcGFzc1Rocm91Z2gub24oXCJlbmRcIiwgKCkgPT4ge1xuICAgICAgaWYgKHZlcmJvc2UpIHtcbiAgICAgICAgbG9nZ2VyPy5pbmZvKGBbcnNjLXdvcmtlcjoke3JvdXRlfV0gKioqIFNUUkVBTSBFTkQgRVZFTlQgRklSRUQgKioqYCk7XG4gICAgICB9XG5cblxuICAgICAgLy8gU3RyZWFtIGNvbXBsZXRlZCBuYXR1cmFsbHlcbiAgICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICAgIGxvZ2dlcj8uaW5mbyhcbiAgICAgICAgICBgW3JzYy13b3JrZXI6JHtyb3V0ZX1dIFN0cmVhbSBjb21wbGV0ZWQgbmF0dXJhbGx5LCBjaGVja2luZyBmb3IgaGVhZGxlc3Mgc3RyZWFtIHJldXNlYFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICAvLyBTdG9yZSBQYWdlIGNvbXBvbmVudCBmb3IgcmV1c2UgaWYgdGhpcyBpcyBhIGhlYWRsZXNzIHN0cmVhbSBhbmQgbm8gZXJyb3JzIG9jY3VycmVkXG4gICAgICBpZiAoXG4gICAgICAgIGhlYWRsZXNzU3RyZWFtRWxlbWVudHMgJiZcbiAgICAgICAgaWQuaW5jbHVkZXMoXCJoZWFkbGVzc1wiKSAmJlxuICAgICAgICAhaGVhZGxlc3NTdHJlYW1FcnJvcnM/Lmhhcyhyb3V0ZSlcbiAgICAgICkge1xuICAgICAgICAvLyBUaGlzIGlzIGEgaGVhZGxlc3Mgc3RyZWFtIHRoYXQgY29tcGxldGVkIHN1Y2Nlc3NmdWxseSwgc3RvcmUgdGhlIFBhZ2UgY29tcG9uZW50IGZvciByZXVzZVxuICAgICAgICBjb25zdCBkYXRhVG9TdG9yZSA9IHtcbiAgICAgICAgICBQYWdlQ29tcG9uZW50OiBmaW5hbEhhbmRsZXJPcHRpb25zW1wiUGFnZUNvbXBvbmVudFwiXSwgLy8gU3RvcmUgdGhlIFBhZ2UgY29tcG9uZW50IGZ1bmN0aW9uXG4gICAgICAgICAgZXJyb3JlZDogZmFsc2UsXG4gICAgICAgIH07XG4gICAgICAgIGhlYWRsZXNzU3RyZWFtRWxlbWVudHMuc2V0KGlkLCBkYXRhVG9TdG9yZSk7XG4gICAgICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICAgICAgbG9nZ2VyPy5pbmZvKFxuICAgICAgICAgICAgYFtyc2Mtd29ya2VyOiR7cm91dGV9XSBTdG9yZWQgUGFnZSBjb21wb25lbnQgZm9yIGhlYWRsZXNzIHN0cmVhbSAke2lkfWBcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIENhbGwgb25FbmQgZm9yIGJvdGggc2luZ2xlLXBvcnQgYW5kIHR3by1wb3J0IGNvbW11bmljYXRpb25cbiAgICAgIC8vIFRoaXMgbWlycm9ycyB0aGUgSFRNTCB3b3JrZXIgcGF0dGVybiBhbmQgZW5zdXJlcyBwcm9wZXIgc3RyZWFtIGNsZWFudXBcbiAgICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICAgIGxvZ2dlcj8uaW5mbyhcbiAgICAgICAgICBgW3JzYy13b3JrZXI6JHtyb3V0ZX1dIENhbGxpbmcgaGFuZGxlcnMub25FbmQoJHtpZH0pIGZyb20gZW5kIGV2ZW50IHRvIHRyaWdnZXIgY29tcGxldGlvbmBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIGhhbmRsZXJzLm9uRW5kKGlkKTtcbiAgICAgIHJlbmRlck1ldHJpY3Muc3RyZWFtTWV0cmljcy5kdXJhdGlvbiA9XG4gICAgICAgIHBlcmZvcm1hbmNlLm5vdygpIC0gcmVuZGVyTWV0cmljcy5zdHJlYW1NZXRyaWNzLnN0YXJ0VGltZTtcbiAgICAgIGhhbmRsZXJzLm9uTWV0cmljcyhpZCwgcmVuZGVyTWV0cmljcyBhcyBhbnkpO1xuICAgIH0pO1xuXG4gICAgLy8gQWxzbyBoYW5kbGUgdGhlICdjbG9zZScgZXZlbnQgYXMgYSBmYWxsYmFja1xuICAgIHBhc3NUaHJvdWdoLm9uKFwiY2xvc2VcIiwgKCkgPT4ge1xuICAgICAgaWYgKHZlcmJvc2UpIHtcbiAgICAgICAgbG9nZ2VyPy5pbmZvKGBbcnNjLXdvcmtlcjoke3JvdXRlfV0gKioqIFNUUkVBTSBDTE9TRSBFVkVOVCBGSVJFRCAqKipgKTtcbiAgICAgIH1cbiAgICAgIC8vIFN0cmVhbSBjb21wbGV0ZWRcblxuICAgICAgLy8gU3RvcmUgUGFnZSBjb21wb25lbnQgZm9yIHJldXNlIGlmIHRoaXMgaXMgYSBoZWFkbGVzcyBzdHJlYW0gYW5kIG5vIGVycm9ycyBvY2N1cnJlZFxuICAgICAgaWYgKFxuICAgICAgICBoZWFkbGVzc1N0cmVhbUVsZW1lbnRzICYmXG4gICAgICAgIGlkLmluY2x1ZGVzKFwiaGVhZGxlc3NcIikgJiZcbiAgICAgICAgIWhlYWRsZXNzU3RyZWFtRXJyb3JzPy5oYXMocm91dGUpXG4gICAgICApIHtcbiAgICAgICAgLy8gVGhpcyBpcyBhIGhlYWRsZXNzIHN0cmVhbSB0aGF0IGNvbXBsZXRlZCBzdWNjZXNzZnVsbHksIHN0b3JlIHRoZSBQYWdlIGNvbXBvbmVudCBmb3IgcmV1c2VcbiAgICAgICAgY29uc3QgZGF0YVRvU3RvcmUgPSB7XG4gICAgICAgICAgUGFnZUNvbXBvbmVudDogZmluYWxIYW5kbGVyT3B0aW9uc1tcIlBhZ2VDb21wb25lbnRcIl0sIC8vIFN0b3JlIHRoZSBQYWdlIGNvbXBvbmVudCBmdW5jdGlvblxuICAgICAgICAgIGVycm9yZWQ6IGZhbHNlLFxuICAgICAgICB9O1xuICAgICAgICBoZWFkbGVzc1N0cmVhbUVsZW1lbnRzLnNldChpZCwgZGF0YVRvU3RvcmUpO1xuICAgICAgICBpZiAodmVyYm9zZSkge1xuICAgICAgICAgIGxvZ2dlcj8uaW5mbyhcbiAgICAgICAgICAgIGBbcnNjLXdvcmtlcjoke3JvdXRlfV0gU3RvcmVkIFBhZ2UgY29tcG9uZW50IGZvciBoZWFkbGVzcyBzdHJlYW0gJHtpZH0gKGZyb20gY2xvc2UgZXZlbnQpYFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gQ2FsbCBvbkVuZCBmb3IgYm90aCBzaW5nbGUtcG9ydCBhbmQgdHdvLXBvcnQgY29tbXVuaWNhdGlvblxuICAgICAgLy8gVGhpcyBtaXJyb3JzIHRoZSBIVE1MIHdvcmtlciBwYXR0ZXJuIGFuZCBlbnN1cmVzIHByb3BlciBzdHJlYW0gY2xlYW51cFxuICAgICAgaWYgKHZlcmJvc2UpIHtcbiAgICAgICAgbG9nZ2VyPy5pbmZvKFxuICAgICAgICAgIGBbcnNjLXdvcmtlcjoke3JvdXRlfV0gQ2FsbGluZyBoYW5kbGVycy5vbkVuZCgke2lkfSkgZnJvbSBjbG9zZSBldmVudCB0byB0cmlnZ2VyIGNvbXBsZXRpb25gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBoYW5kbGVycy5vbkVuZChpZCk7XG4gICAgICByZW5kZXJNZXRyaWNzLnN0cmVhbU1ldHJpY3MuZHVyYXRpb24gPVxuICAgICAgICBwZXJmb3JtYW5jZS5ub3coKSAtIHJlbmRlck1ldHJpY3Muc3RyZWFtTWV0cmljcy5zdGFydFRpbWU7XG4gICAgICBoYW5kbGVycy5vbk1ldHJpY3MoaWQsIHJlbmRlck1ldHJpY3MgYXMgYW55KTtcbiAgICB9KTtcblxuICAgIHBhc3NUaHJvdWdoLm9uKFwicGlwZVwiLCAoc3JjOiBhbnkpID0+IHtcbiAgICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICAgIGxvZ2dlcj8uaW5mbyhcbiAgICAgICAgICBgW3JzYy13b3JrZXI6JHtyb3V0ZX1dICoqKiBTVFJFQU0gUElQRSBFVkVOVCBGSVJFRCAqKiogcmVhZGFibGVFbmRlZDogJHtzcmMucmVhZGFibGVFbmRlZH1gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBwYXNzVGhyb3VnaC5vbihcImZpbmlzaFwiLCAoKSA9PiB7XG4gICAgICBpZiAodmVyYm9zZSkge1xuICAgICAgICBsb2dnZXI/LmluZm8oYFtyc2Mtd29ya2VyOiR7cm91dGV9XSAqKiogU1RSRUFNIEZJTklTSCBFVkVOVCBGSVJFRCAqKipgKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHBhc3NUaHJvdWdoLm9uKFwiZXJyb3JcIiwgKGVycm9yOiB1bmtub3duKSA9PiB7XG4gICAgICBpZiAodmVyYm9zZSkge1xuICAgICAgICBsb2dnZXI/LmVycm9yKGBbcnNjLXdvcmtlcjoke3JvdXRlfV0gU3RyZWFtIGVycm9yOiAke2Vycm9yfWApO1xuICAgICAgfVxuICAgICAgLy8gQ2hlY2sgaWYgaXQncyBhIE5vZGUuanMgc3RyZWFtIHdpdGggZXJyb3JlZCBwcm9wZXJ0eVxuICAgICAgaWYgKFwiZXJyb3JlZFwiIGluIHBhc3NUaHJvdWdoICYmIHBhc3NUaHJvdWdoLmVycm9yZWQpIHtcbiAgICAgICAgLy8gYWxyZWFkeSBoYW5kbGVkIGJ5IHRoZSBzdHJlYW1cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgLy8gU2VuZCBlcnJvciB0aHJvdWdoIHRvV29ya2VyIC0gbGV0IG1haW4gdGhyZWFkIGhhbmRsZSBwYW5pYyB0aHJlc2hvbGQgbG9naWNcbiAgICAgIGhhbmRsZXJzLm9uRXJyb3IoaWQsIGVycm9yLCB7XG4gICAgICAgIHJvdXRlOiByb3V0ZSxcbiAgICAgICAgY29udGV4dDogXCJSU0MgU3RyZWFtIEVycm9yXCIsXG4gICAgICB9KTtcblxuICAgICAgLy8gRW5zdXJlIHN0cmVhbSBpcyBwcm9wZXJseSBlbmRlZCB3aGVuIGVycm9yIG9jY3VycyB0byBwcmV2ZW50IFwiQ29ubmVjdGlvbiBjbG9zZWRcIiBlcnJvcnNcbiAgICAgIGhhbmRsZXJzLm9uRW5kKGlkKTtcblxuICAgICAgLy8gRW5zdXJlIHN0cmVhbSBpcyBlbmRlZCB3aGVuIGVycm9yIG9jY3VycyB0byBwcmV2ZW50IGhhbmdpbmdcbiAgICAgIC8vIENoZWNrIGlmIGl0J3MgYSBOb2RlLmpzIHN0cmVhbSB3aXRoIGRlc3Ryb3llZCBwcm9wZXJ0eVxuICAgICAgaWYgKFwiZGVzdHJveWVkXCIgaW4gcGFzc1Rocm91Z2ggJiYgIXBhc3NUaHJvdWdoLmRlc3Ryb3llZCkge1xuICAgICAgICBwYXNzVGhyb3VnaC5lbmQoKTtcbiAgICAgIH0gZWxzZSBpZiAoXCJlbmRcIiBpbiBwYXNzVGhyb3VnaCkge1xuICAgICAgICAvLyBGb3IgV3JpdGFibGVTdHJlYW0gdGhhdCBkb2Vzbid0IGhhdmUgZGVzdHJveWVkIHByb3BlcnR5XG4gICAgICAgIHBhc3NUaHJvdWdoLmVuZCgpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaWYgKHZlcmJvc2UpIHtcbiAgICAgIGxvZ2dlcj8uaW5mbyhcbiAgICAgICAgYFtyc2Mtd29ya2VyOiR7cm91dGV9XSBSZW5kZXIgc2V0dXAgY29tcGxldGUgZm9yIHJvdXRlOiAke3JvdXRlfSAtIGZ1bmN0aW9uIHJldHVybmluZywgd29ya2VyIHNob3VsZCBjb250aW51ZWBcbiAgICAgICk7XG4gICAgfVxuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICBsb2dnZXI/LmVycm9yKFxuICAgICAgICBgW3JzYy13b3JrZXI6JHtyb3V0ZX1dIEVycm9yIGluIGhhbmRsZVJlbmRlcjogJHtcbiAgICAgICAgICAoZXJyb3IgYXMgRXJyb3IpPy5tZXNzYWdlID8/IFwibm8gbWVzc2FnZVwiXG4gICAgICAgIH1gXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIFNlbmQgZXJyb3IgdGhyb3VnaCB0b1dvcmtlciAtIGxldCBtYWluIHRocmVhZCBoYW5kbGUgcGFuaWMgdGhyZXNob2xkIGxvZ2ljXG4gICAgaGFuZGxlcnMub25FcnJvcihpZCwgZXJyb3IsIHtcbiAgICAgIHJvdXRlOiByb3V0ZSxcbiAgICAgIGNvbnRleHQ6IFwiUlNDIFdvcmtlciBFcnJvclwiLFxuICAgIH0pO1xuXG4gICAgLy8gQ2FsbCBvbkVuZCBmb3IgYm90aCBzaW5nbGUtcG9ydCBhbmQgdHdvLXBvcnQgY29tbXVuaWNhdGlvblxuICAgIGhhbmRsZXJzLm9uRW5kKGlkKTtcbiAgfVxufTtcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7O0FBeUNPLE1BQU0sa0JBQXFDLFNBQVMsZ0JBQUEsQ0FDekQsZ0JBQ0EsUUFDQSxFQUFBLGlCQUFBLEVBQ0Esd0JBQ0Esb0JB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