vite-plugin-react-server
Version:
Vite plugin for React Server Components (RSC)
344 lines (342 loc) • 51 kB
JavaScript
/**
* vite-plugin-react-server
* Copyright (c) Nico Brinkkemper
* MIT License
*/
import { getRouteFiles } from '../helpers/getRouteFiles.js';
import { routeToURL } from '../utils/routeToURL.js';
import { resolveAutoDiscover } from './autoDiscover/resolveAutoDiscover.js';
import { getStashedUserOptions, getEnvironmentId, getStashedHandlerOptions, stashHandlerOptions } from './stashedOptionsState.js';
import { getNodeEnv } from './getNodeEnv.js';
import { createLogger } from 'vite';
import { DEFAULT_CONFIG } from './defaults.js';
import { resolveComponent } from '../helpers/resolveComponent.js';
import { serializedOptions } from '../helpers/serializeUserOptions.js';
import { createWorker } from '../worker/createWorker.js';
function createDefaultOptions() {
return {
pageExportName: DEFAULT_CONFIG.PAGE_EXPORT_NAME,
propsExportName: DEFAULT_CONFIG.PROPS_EXPORT_NAME,
rootExportName: DEFAULT_CONFIG.ROOT_EXPORT_NAME,
htmlExportName: DEFAULT_CONFIG.HTML_EXPORT_NAME,
cssFiles: /* @__PURE__ */ new Map(),
globalCss: /* @__PURE__ */ new Map(),
manifest: {},
css: DEFAULT_CONFIG.CSS
};
}
async function resolveAutoDiscoveredFiles(options, stashedOptions, logger) {
if (options.autoDiscoveredFiles) {
return options.autoDiscoveredFiles;
}
const result = await resolveAutoDiscover({
config: options.config || {},
configEnv: options.configEnv || { mode: "production", command: "build" },
userOptions: stashedOptions,
logger
});
if (result.type === "error") {
throw result.error || new Error("Failed to resolve autoDiscover");
}
return result.autoDiscoveredFiles;
}
async function createHandlerOptions(route, options = {}) {
const {
mode = getNodeEnv(),
logger = createLogger(),
configEnv = { mode: mode || "production", command: "build" },
id = `${route}-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`,
envId = getEnvironmentId("react-server", mode),
userOptions = getStashedUserOptions(envId)
} = options;
const cachedOptions = getStashedHandlerOptions(id);
if (cachedOptions) {
return cachedOptions;
}
if (!userOptions) {
throw new Error(
`No stashed userOptions found for environment: ${envId}. Make sure resolveOptions() has been called first.`
);
}
const defaults = { ...createDefaultOptions(), ...options.defaults };
const autoDiscoveredFiles = await resolveAutoDiscoveredFiles(
options,
userOptions,
logger
);
const url = routeToURL(
route,
userOptions.moduleBaseURL,
userOptions.build.rscOutputPath
);
const routeFilesResult = await getRouteFiles(
route,
autoDiscoveredFiles,
userOptions,
logger
);
if (routeFilesResult.type === "error") {
throw routeFilesResult.error || new Error("Failed to get route files");
}
let PageComponent = userOptions.components?.Page;
let RootComponent = userOptions.components?.Root;
let HtmlComponent = userOptions.components?.Html;
if (routeFilesResult.page && !PageComponent) {
try {
if (userOptions.verbose) {
logger.info(`[createHandlerOptions] Attempting to load component from: ${routeFilesResult.page} export: ${userOptions.pageExportName}`);
}
const isServeMode2 = configEnv?.command === "serve" || configEnv?.mode === "development" || mode === "development";
const componentLoader = isServeMode2 ? async (path) => {
if (userOptions.verbose) {
logger.info(`[createHandlerOptions] Development mode: loading ${path} via dynamic import`);
}
return await import(path);
} : defaults.loader || (() => Promise.resolve({}));
const pageResult = await resolveComponent({
componentPath: routeFilesResult.page,
exportName: userOptions.pageExportName,
loader: componentLoader
});
if (pageResult.type === "success") {
PageComponent = pageResult.component;
logger.info(`[createHandlerOptions] Loaded Page component from ${routeFilesResult.page}`);
} else {
logger.warn(
`[createHandlerOptions] Failed to load Page component from ${routeFilesResult.page}: ${pageResult.error?.message || "Unknown error"}`
);
}
} catch (error) {
logger.warn(
`[createHandlerOptions] Error loading Page component from ${routeFilesResult.page}: ${error instanceof Error ? error.message : String(error)}`
);
}
}
if (!RootComponent && routeFilesResult.root !== void 0) {
if (routeFilesResult.root === "") {
if (userOptions.verbose) {
logger.info(`[createHandlerOptions] Root component explicitly disabled (headless mode)`);
}
RootComponent = void 0;
} else {
try {
const isServeMode2 = configEnv?.command === "serve" || configEnv?.mode === "development" || mode === "development";
const componentLoader = isServeMode2 ? async (path) => import(path) : defaults.loader || (() => Promise.resolve({}));
const rootResult = await resolveComponent({
componentPath: routeFilesResult.root,
exportName: userOptions.rootExportName,
loader: componentLoader
});
if (rootResult.type === "success") {
RootComponent = rootResult.component;
logger.info(`[createHandlerOptions] Loaded custom Root component from ${routeFilesResult.root}`);
}
} catch (error) {
logger.warn(
`[createHandlerOptions] Error loading custom Root component: ${error instanceof Error ? error.message : String(error)}`
);
}
}
} else if (!RootComponent) {
try {
const { Root } = await import('../components/root.js');
RootComponent = Root;
if (userOptions.verbose) {
logger.info(`[createHandlerOptions] Using default Root component`);
}
} catch (error) {
logger.warn(
`[createHandlerOptions] Error loading default Root component: ${error instanceof Error ? error.message : String(error)}`
);
}
}
if (!HtmlComponent && routeFilesResult.html !== void 0) {
if (routeFilesResult.html === "") {
if (userOptions.verbose) {
logger.info(`[createHandlerOptions] Html component explicitly disabled (headless mode)`);
}
HtmlComponent = void 0;
} else {
try {
const isServeMode2 = configEnv?.command === "serve" || configEnv?.mode === "development" || mode === "development";
const componentLoader = isServeMode2 ? async (path) => await import(path) : defaults.loader || (() => Promise.resolve({}));
const htmlResult = await resolveComponent({
componentPath: routeFilesResult.html,
exportName: userOptions.htmlExportName,
loader: componentLoader
});
if (htmlResult.type === "success") {
HtmlComponent = htmlResult.component;
logger.info(`[createHandlerOptions] Loaded custom Html component from ${routeFilesResult.html}`);
}
} catch (error) {
logger.warn(
`[createHandlerOptions] Error loading custom Html component: ${error instanceof Error ? error.message : String(error)}`
);
}
}
} else if (!HtmlComponent) {
try {
const { Html } = await import('../components/html.js');
HtmlComponent = Html;
if (userOptions.verbose) {
logger.info(`[createHandlerOptions] Using default Html component`);
}
} catch (error) {
logger.warn(
`[createHandlerOptions] Error loading default Html component: ${error instanceof Error ? error.message : String(error)}`
);
}
}
let rscWorker = void 0;
let htmlWorker = void 0;
const isServeMode = configEnv?.command === "serve" || configEnv?.mode === "development" || mode === "development";
const isBuildMode = configEnv?.command === "build";
const shouldCreateRscWorker = userOptions.dev?.useRscWorker && isServeMode || userOptions.build?.useRscWorker && isBuildMode;
if (shouldCreateRscWorker) {
if (userOptions.verbose) {
logger.info(`[createHandlerOptions.server] Creating RSC worker for route: ${route}`);
}
try {
const serializedUserOptions = serializedOptions(userOptions, autoDiscoveredFiles);
const workerResult = await createWorker({
currentCondition: "react-server",
// same CONDITION as the current one (this worker may be redundant)
reverseCondition: "react-server",
workerPath: userOptions.rscWorkerPath,
verbose: userOptions.verbose,
logger,
workerData: {
id: route,
userOptions: serializedUserOptions,
resolvedConfig: {
configEnv,
mode
}
}
});
if (workerResult.type === "error") {
logger.warn(`[createHandlerOptions.server] Failed to create RSC worker: ${workerResult.error?.message}`);
rscWorker = void 0;
} else if (workerResult.type === "skip") {
logger.warn(`[createHandlerOptions.server] RSC worker creation skipped: ${workerResult.reason}`);
rscWorker = void 0;
} else {
rscWorker = workerResult.worker;
if (userOptions.verbose) {
logger.info(`[createHandlerOptions.server] RSC worker created successfully`);
}
}
} catch (error) {
logger.warn(`[createHandlerOptions.server] RSC worker creation failed: ${error instanceof Error ? error.message : String(error)}`);
rscWorker = void 0;
}
}
const shouldCreateHtmlWorker = userOptions.dev?.useHtmlWorker && isServeMode || userOptions.build?.useHtmlWorker && isBuildMode;
if (shouldCreateHtmlWorker) {
if (userOptions.verbose) {
logger.info(`[createHandlerOptions.server] Creating HTML worker for route: ${route}`);
}
try {
const serializedUserOptions = serializedOptions(userOptions, autoDiscoveredFiles);
const workerResult = await createWorker({
currentCondition: "react-server",
reverseCondition: "react-client",
// HTML worker needs react-client condition
workerPath: userOptions.htmlWorkerPath,
verbose: userOptions.verbose,
logger,
workerData: {
id: route,
userOptions: serializedUserOptions,
resolvedConfig: {
configEnv,
mode
}
}
});
if (workerResult.type === "error") {
logger.warn(`[createHandlerOptions.server] Failed to create HTML worker: ${workerResult.error?.message}`);
htmlWorker = void 0;
} else if (workerResult.type === "skip") {
logger.warn(`[createHandlerOptions.server] HTML worker creation skipped: ${workerResult.reason}`);
htmlWorker = void 0;
} else {
htmlWorker = workerResult.worker;
if (userOptions.verbose) {
logger.info(`[createHandlerOptions.server] HTML worker created successfully`);
}
}
} catch (error) {
logger.warn(`[createHandlerOptions.server] HTML worker creation failed: ${error instanceof Error ? error.message : String(error)}`);
htmlWorker = void 0;
}
}
const handlerOptions = {
...userOptions,
// File paths
pagePath: routeFilesResult.page,
propsPath: routeFilesResult.props,
rootPath: routeFilesResult.root,
htmlPath: routeFilesResult.html,
// Export names
pageExportName: userOptions.pageExportName,
propsExportName: userOptions.propsExportName,
rootExportName: userOptions.rootExportName,
htmlExportName: userOptions.htmlExportName,
// Route and loader
route,
loader: defaults.loader || (() => Promise.resolve({})),
// Configuration
panicThreshold: userOptions.panicThreshold,
verbose: userOptions.verbose,
moduleBaseURL: userOptions.moduleBaseURL,
build: userOptions.build,
dev: {
useHtmlWorker: userOptions.dev.useHtmlWorker,
useRscWorker: userOptions.dev.useRscWorker
},
logger,
// Required properties
normalizer: userOptions.normalizer,
onEvent: userOptions.onEvent,
onMetrics: userOptions.onMetrics,
autoDiscover: userOptions.autoDiscover,
css: userOptions.css,
projectRoot: userOptions.projectRoot,
moduleBase: userOptions.moduleBase,
moduleBasePath: userOptions.moduleBasePath,
moduleRootPath: userOptions.moduleRootPath,
moduleID: userOptions.moduleID,
url,
manifest: defaults.manifest,
cssFiles: defaults.cssFiles,
globalCss: defaults.globalCss,
// Timeouts and paths
rscTimeout: userOptions.rscTimeout,
htmlTimeout: userOptions.htmlTimeout,
fileWriteTimeout: userOptions.fileWriteTimeout,
workerShutdownTimeout: userOptions.workerShutdownTimeout,
rscWorkerPath: userOptions.rscWorkerPath,
htmlWorkerPath: userOptions.htmlWorkerPath,
publicOrigin: userOptions.publicOrigin,
// Stream options
serverPipeableStreamOptions: userOptions.serverPipeableStreamOptions,
clientPipeableStreamOptions: userOptions.clientPipeableStreamOptions || {},
components: userOptions.components,
// Server-specific
id,
// Always use the inverse worker for the main "worker" field
worker: htmlWorker,
rscWorker,
htmlWorker,
// Loaded components (server loads them at configuration time)
PageComponent,
RootComponent,
HtmlComponent
};
stashHandlerOptions(id, handlerOptions);
return handlerOptions;
}
export { createHandlerOptions };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlSGFuZGxlck9wdGlvbnMuc2VydmVyLmpzIiwic291cmNlcyI6WyIuLi8uLi8uLi9wbHVnaW4vY29uZmlnL2NyZWF0ZUhhbmRsZXJPcHRpb25zLnNlcnZlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IENyZWF0ZUhhbmRsZXJPcHRpb25zLCBBdXRvRGlzY292ZXJlZEZpbGVzLCBSb290Q29tcG9uZW50VHlwZSwgSHRtbENvbXBvbmVudFR5cGUgfSBmcm9tIFwiLi4vdHlwZXMuanNcIjtcbmltcG9ydCB0eXBlIHsgTG9nZ2VyIH0gZnJvbSBcInZpdGVcIjtcbmltcG9ydCB7IGdldFJvdXRlRmlsZXMgfSBmcm9tIFwiLi4vaGVscGVycy9nZXRSb3V0ZUZpbGVzLmpzXCI7XG5pbXBvcnQgeyByb3V0ZVRvVVJMIH0gZnJvbSBcIi4uL3V0aWxzL3JvdXRlVG9VUkwuanNcIjtcbmltcG9ydCB7IHJlc29sdmVBdXRvRGlzY292ZXIgfSBmcm9tIFwiLi9hdXRvRGlzY292ZXIvcmVzb2x2ZUF1dG9EaXNjb3Zlci5qc1wiO1xuaW1wb3J0IHtcbiAgZ2V0U3Rhc2hlZFVzZXJPcHRpb25zLFxuICBnZXRTdGFzaGVkSGFuZGxlck9wdGlvbnMsXG4gIHN0YXNoSGFuZGxlck9wdGlvbnMsXG4gIGdldEVudmlyb25tZW50SWQsXG59IGZyb20gXCIuL3N0YXNoZWRPcHRpb25zU3RhdGUuanNcIjtcblxuaW1wb3J0IHsgZ2V0Tm9kZUVudiB9IGZyb20gXCIuL2dldE5vZGVFbnYuanNcIjtcbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciB9IGZyb20gXCJ2aXRlXCI7XG5pbXBvcnQgeyBERUZBVUxUX0NPTkZJRyB9IGZyb20gXCIuL2RlZmF1bHRzLmpzXCI7XG5pbXBvcnQgdHlwZSB7IENyZWF0ZUhhbmRsZXJPcHRpb25zUGFyYW1zLCBSZXNvbHZlZERlZmF1bHRzIH0gZnJvbSBcIi4vY3JlYXRlSGFuZGxlck9wdGlvbnMudHlwZXMuanNcIjtcbmltcG9ydCB7IHJlc29sdmVDb21wb25lbnQgfSBmcm9tIFwiLi4vaGVscGVycy9yZXNvbHZlQ29tcG9uZW50LmpzXCI7XG5pbXBvcnQgeyBzZXJpYWxpemVkT3B0aW9ucyB9IGZyb20gXCIuLi9oZWxwZXJzL3NlcmlhbGl6ZVVzZXJPcHRpb25zLmpzXCI7XG5pbXBvcnQgeyBjcmVhdGVXb3JrZXIgfSBmcm9tIFwiLi4vd29ya2VyL2NyZWF0ZVdvcmtlci5qc1wiO1xuXG4vKipcbiAqIFNlcnZlci1zcGVjaWZpYyBoYW5kbGVyIG9wdGlvbnMgY3JlYXRpb24gZm9yIFJlYWN0IFNlcnZlciBDb21wb25lbnRzIChSU0MpLlxuICogXG4gKiBXSEFUIFRISVMgRE9FUzpcbiAqIC0gQ3JlYXRlcyBoYW5kbGVyIG9wdGlvbnMgb3B0aW1pemVkIGZvciBzZXJ2ZXItc2lkZSByZW5kZXJpbmdcbiAqIC0gUmVzb2x2ZXMgZmlsZSBwYXRocyBmb3IgcGFnZXMsIHByb3BzLCByb290LCBhbmQgSFRNTCBjb21wb25lbnRzXG4gKiAtIFNldHMgdXAgc2VydmVyLXNwZWNpZmljIGxvYWRlcnMgYW5kIGNvbmZpZ3VyYXRpb25cbiAqIC0gSGFuZGxlcyBjYWNoaW5nIHdpdGggdW5pcXVlIElEc1xuICogLSBQcm92aWRlcyBhbGwgbmVjZXNzYXJ5IG9wdGlvbnMgZm9yIFJTQyBzdHJlYW0gY3JlYXRpb25cbiAqIFxuICogV0hBVCBUSElTIERPRVNOJ1QgRE86XG4gKiAtIERvZXMgTk9UIGxvYWQgUmVhY3QgY29tcG9uZW50cyAodGhhdCBoYXBwZW5zIGluIHRoZSBhY3R1YWwgaGFuZGxlcnMpXG4gKiAtIERvZXMgTk9UIGNyZWF0ZSBSU0Mgc3RyZWFtcyAodXNlIGNyZWF0ZUhhbmRsZXIgZm9yIHRoYXQpXG4gKiAtIERvZXMgTk9UIGhhbmRsZSBjbGllbnQtc2lkZSByZW5kZXJpbmcgKHVzZSAuY2xpZW50LnRzIGZvciB0aGF0KVxuICogLSBEb2VzIE5PVCBtYW5hZ2UgY29tcG9uZW50IGxpZmVjeWNsZSBvciBzdGF0ZVxuICogXG4gKiBVU0FHRTpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGhhbmRsZXJPcHRpb25zID0gYXdhaXQgY3JlYXRlSGFuZGxlck9wdGlvbnMoXCIvbXktcm91dGVcIiwge1xuICogICBsb2dnZXI6IG15TG9nZ2VyLFxuICogICBkZWZhdWx0czogeyBsb2FkZXI6IHNlcnZlci5zc3JMb2FkTW9kdWxlIH1cbiAqIH0pO1xuICogYGBgXG4gKi9cblxuZnVuY3Rpb24gY3JlYXRlRGVmYXVsdE9wdGlvbnMoKTogUmVzb2x2ZWREZWZhdWx0cyB7XG4gIHJldHVybiB7XG4gICAgcGFnZUV4cG9ydE5hbWU6IERFRkFVTFRfQ09ORklHLlBBR0VfRVhQT1JUX05BTUUsXG4gICAgcHJvcHNFeHBvcnROYW1lOiBERUZBVUxUX0NPTkZJRy5QUk9QU19FWFBPUlRfTkFNRSxcbiAgICByb290RXhwb3J0TmFtZTogREVGQVVMVF9DT05GSUcuUk9PVF9FWFBPUlRfTkFNRSxcbiAgICBodG1sRXhwb3J0TmFtZTogREVGQVVMVF9DT05GSUcuSFRNTF9FWFBPUlRfTkFNRSxcbiAgICBjc3NGaWxlczogbmV3IE1hcCgpLFxuICAgIGdsb2JhbENzczogbmV3IE1hcCgpLFxuICAgIG1hbmlmZXN0OiB7fSxcbiAgICBjc3M6IERFRkFVTFRfQ09ORklHLkNTUyxcbiAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZUF1dG9EaXNjb3ZlcmVkRmlsZXMoXG4gIG9wdGlvbnM6IENyZWF0ZUhhbmRsZXJPcHRpb25zUGFyYW1zLFxuICBzdGFzaGVkT3B0aW9uczogYW55LFxuICBsb2dnZXI6IExvZ2dlclxuKTogUHJvbWlzZTxBdXRvRGlzY292ZXJlZEZpbGVzPiB7XG4gIGlmIChvcHRpb25zLmF1dG9EaXNjb3ZlcmVkRmlsZXMpIHtcbiAgICByZXR1cm4gb3B0aW9ucy5hdXRvRGlzY292ZXJlZEZpbGVzO1xuICB9XG5cbiAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcmVzb2x2ZUF1dG9EaXNjb3Zlcih7XG4gICAgY29uZmlnOiBvcHRpb25zLmNvbmZpZyB8fCB7fSxcbiAgICBjb25maWdFbnY6IG9wdGlvbnMuY29uZmlnRW52IHx8IHsgbW9kZTogXCJwcm9kdWN0aW9uXCIsIGNvbW1hbmQ6IFwiYnVpbGRcIiB9LFxuICAgIHVzZXJPcHRpb25zOiBzdGFzaGVkT3B0aW9ucyxcbiAgICBsb2dnZXIsXG4gIH0pO1xuXG4gIGlmIChyZXN1bHQudHlwZSA9PT0gXCJlcnJvclwiKSB7XG4gICAgdGhyb3cgcmVzdWx0LmVycm9yIHx8IG5ldyBFcnJvcihcIkZhaWxlZCB0byByZXNvbHZlIGF1dG9EaXNjb3ZlclwiKTtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQuYXV0b0Rpc2NvdmVyZWRGaWxlcztcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUhhbmRsZXJPcHRpb25zKFxuICByb3V0ZTogc3RyaW5nLFxuICBvcHRpb25zOiBDcmVhdGVIYW5kbGVyT3B0aW9uc1BhcmFtcyA9IHt9XG4pOiBQcm9taXNlPENyZWF0ZUhhbmRsZXJPcHRpb25zPiB7XG4gIGNvbnN0IHtcbiAgICBtb2RlID0gZ2V0Tm9kZUVudigpLFxuICAgIGxvZ2dlciA9IGNyZWF0ZUxvZ2dlcigpLFxuICAgIGNvbmZpZ0VudiA9IHsgbW9kZTogbW9kZSB8fCBcInByb2R1Y3Rpb25cIiwgY29tbWFuZDogXCJidWlsZFwiIH0sXG4gICAgaWQgPSBgJHtyb3V0ZX0tJHtEYXRlLm5vdygpfS0ke01hdGgucmFuZG9tKClcbiAgICAgIC50b1N0cmluZygzNilcbiAgICAgIC5zdWJzdHJpbmcoMiwgMTEpfWAsXG4gICAgZW52SWQgPSBnZXRFbnZpcm9ubWVudElkKFwicmVhY3Qtc2VydmVyXCIsIG1vZGUpLFxuICAgIHVzZXJPcHRpb25zID0gZ2V0U3Rhc2hlZFVzZXJPcHRpb25zKGVudklkKSxcbiAgfSA9IG9wdGlvbnM7XG5cbiAgLy8gQ2hlY2sgY2FjaGUgZmlyc3RcbiAgY29uc3QgY2FjaGVkT3B0aW9ucyA9IGdldFN0YXNoZWRIYW5kbGVyT3B0aW9ucyhpZCk7XG4gIGlmIChjYWNoZWRPcHRpb25zKSB7XG4gICAgcmV0dXJuIGNhY2hlZE9wdGlvbnM7XG4gIH1cblxuXG4gIGlmICghdXNlck9wdGlvbnMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgTm8gc3Rhc2hlZCB1c2VyT3B0aW9ucyBmb3VuZCBmb3IgZW52aXJvbm1lbnQ6ICR7ZW52SWR9LiBNYWtlIHN1cmUgcmVzb2x2ZU9wdGlvbnMoKSBoYXMgYmVlbiBjYWxsZWQgZmlyc3QuYFxuICAgICk7XG4gIH1cblxuICAvLyBSZXNvbHZlIGRlZmF1bHRzXG4gIGNvbnN0IGRlZmF1bHRzID0geyAuLi5jcmVhdGVEZWZhdWx0T3B0aW9ucygpLCAuLi5vcHRpb25zLmRlZmF1bHRzIH07XG5cbiAgLy8gUmVzb2x2ZSBhdXRvLWRpc2NvdmVyZWQgZmlsZXNcbiAgY29uc3QgYXV0b0Rpc2NvdmVyZWRGaWxlcyA9IGF3YWl0IHJlc29sdmVBdXRvRGlzY292ZXJlZEZpbGVzKFxuICAgIG9wdGlvbnMsXG4gICAgdXNlck9wdGlvbnMsXG4gICAgbG9nZ2VyXG4gICk7XG5cbiAgLy8gQ3JlYXRlIFVSTFxuICBjb25zdCB1cmwgPSByb3V0ZVRvVVJMKFxuICAgIHJvdXRlLFxuICAgIHVzZXJPcHRpb25zLm1vZHVsZUJhc2VVUkwsXG4gICAgdXNlck9wdGlvbnMuYnVpbGQucnNjT3V0cHV0UGF0aFxuICApO1xuXG4gIC8vIEdldCByb3V0ZSBmaWxlc1xuICBjb25zdCByb3V0ZUZpbGVzUmVzdWx0ID0gYXdhaXQgZ2V0Um91dGVGaWxlcyhcbiAgICByb3V0ZSxcbiAgICBhdXRvRGlzY292ZXJlZEZpbGVzLFxuICAgIHVzZXJPcHRpb25zLFxuICAgIGxvZ2dlclxuICApO1xuXG4gIGlmIChyb3V0ZUZpbGVzUmVzdWx0LnR5cGUgPT09IFwiZXJyb3JcIikge1xuICAgIHRocm93IHJvdXRlRmlsZXNSZXN1bHQuZXJyb3IgfHwgbmV3IEVycm9yKFwiRmFpbGVkIHRvIGdldCByb3V0ZSBmaWxlc1wiKTtcbiAgfVxuXG4gIC8vIExvYWQgY29tcG9uZW50cyBmcm9tIHJlc29sdmVkIGZpbGUgcGF0aHNcbiAgbGV0IFBhZ2VDb21wb25lbnQgPSB1c2VyT3B0aW9ucy5jb21wb25lbnRzPy5QYWdlO1xuICBsZXQgUm9vdENvbXBvbmVudCA9IHVzZXJPcHRpb25zLmNvbXBvbmVudHM/LlJvb3Q7XG4gIGxldCBIdG1sQ29tcG9uZW50ID0gdXNlck9wdGlvbnMuY29tcG9uZW50cz8uSHRtbDtcblxuICAvLyBMb2FkIFBhZ2UgY29tcG9uZW50IGlmIHBhZ2VQYXRoIGlzIGF2YWlsYWJsZVxuICBpZiAocm91dGVGaWxlc1Jlc3VsdC5wYWdlICYmICFQYWdlQ29tcG9uZW50KSB7XG4gICAgdHJ5IHtcbiAgICAgIGlmICh1c2VyT3B0aW9ucy52ZXJib3NlKSB7XG4gICAgICAgIGxvZ2dlci5pbmZvKGBbY3JlYXRlSGFuZGxlck9wdGlvbnNdIEF0dGVtcHRpbmcgdG8gbG9hZCBjb21wb25lbnQgZnJvbTogJHtyb3V0ZUZpbGVzUmVzdWx0LnBhZ2V9IGV4cG9ydDogJHt1c2VyT3B0aW9ucy5wYWdlRXhwb3J0TmFtZX1gKTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgLy8gSW4gZGV2ZWxvcG1lbnQgbW9kZSAoc2VydmUpLCB1c2UgZHluYW1pYyBpbXBvcnQgbG9hZGVyIGZvciBUeXBlU2NyaXB0IHN1cHBvcnRcbiAgICAgIGNvbnN0IGlzU2VydmVNb2RlID0gY29uZmlnRW52Py5jb21tYW5kID09PSBcInNlcnZlXCIgfHwgY29uZmlnRW52Py5tb2RlID09PSBcImRldmVsb3BtZW50XCIgfHwgbW9kZSA9PT0gXCJkZXZlbG9wbWVudFwiO1xuICAgICAgY29uc3QgY29tcG9uZW50TG9hZGVyID0gaXNTZXJ2ZU1vZGUgXG4gICAgICAgID8gYXN5bmMgKHBhdGg6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgaWYgKHVzZXJPcHRpb25zLnZlcmJvc2UpIHtcbiAgICAgICAgICAgICAgbG9nZ2VyLmluZm8oYFtjcmVhdGVIYW5kbGVyT3B0aW9uc10gRGV2ZWxvcG1lbnQgbW9kZTogbG9hZGluZyAke3BhdGh9IHZpYSBkeW5hbWljIGltcG9ydGApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IGltcG9ydChwYXRoKTtcbiAgICAgICAgICB9XG4gICAgICAgIDogZGVmYXVsdHMubG9hZGVyIHx8ICgoKSA9PiBQcm9taXNlLnJlc29sdmUoe30pKTtcbiAgICAgIFxuICAgICAgY29uc3QgcGFnZVJlc3VsdCA9IGF3YWl0IHJlc29sdmVDb21wb25lbnQoe1xuICAgICAgICBjb21wb25lbnRQYXRoOiByb3V0ZUZpbGVzUmVzdWx0LnBhZ2UsXG4gICAgICAgIGV4cG9ydE5hbWU6IHVzZXJPcHRpb25zLnBhZ2VFeHBvcnROYW1lLFxuICAgICAgICBsb2FkZXI6IGNvbXBvbmVudExvYWRlcixcbiAgICAgIH0pO1xuXG4gICAgICBpZiAocGFnZVJlc3VsdC50eXBlID09PSBcInN1Y2Nlc3NcIikge1xuICAgICAgICBQYWdlQ29tcG9uZW50ID0gcGFnZVJlc3VsdC5jb21wb25lbnQ7XG4gICAgICAgIGxvZ2dlci5pbmZvKGBbY3JlYXRlSGFuZGxlck9wdGlvbnNdIExvYWRlZCBQYWdlIGNvbXBvbmVudCBmcm9tICR7cm91dGVGaWxlc1Jlc3VsdC5wYWdlfWApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oXG4gICAgICAgICAgYFtjcmVhdGVIYW5kbGVyT3B0aW9uc10gRmFpbGVkIHRvIGxvYWQgUGFnZSBjb21wb25lbnQgZnJvbSAke3JvdXRlRmlsZXNSZXN1bHQucGFnZX06ICR7XG4gICAgICAgICAgICBwYWdlUmVzdWx0LmVycm9yPy5tZXNzYWdlIHx8IFwiVW5rbm93biBlcnJvclwiXG4gICAgICAgICAgfWBcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgbG9nZ2VyLndhcm4oXG4gICAgICAgIGBbY3JlYXRlSGFuZGxlck9wdGlvbnNdIEVycm9yIGxvYWRpbmcgUGFnZSBjb21wb25lbnQgZnJvbSAke3JvdXRlRmlsZXNSZXN1bHQucGFnZX06ICR7XG4gICAgICAgICAgZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpXG4gICAgICAgIH1gXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8vIExvYWQgUm9vdCBjb21wb25lbnQgaWYgcm9vdFBhdGggaXMgYXZhaWxhYmxlLCBvciB1c2UgZGVmYXVsdCBSb290IGNvbXBvbmVudCBpZiByb290UGF0aCBpcyB1bmRlZmluZWRcbiAgaWYgKCFSb290Q29tcG9uZW50ICYmIHJvdXRlRmlsZXNSZXN1bHQucm9vdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgLy8gSWYgcm9vdFBhdGggaXMgZXhwbGljaXRseSBzZXQgdG8gZW1wdHkgc3RyaW5nLCBkb24ndCBsb2FkIGFueSBSb290IGNvbXBvbmVudCAoaGVhZGxlc3MgbW9kZSlcbiAgICBpZiAocm91dGVGaWxlc1Jlc3VsdC5yb290ID09PSAnJykge1xuICAgICAgaWYgKHVzZXJPcHRpb25zLnZlcmJvc2UpIHtcbiAgICAgICAgbG9nZ2VyLmluZm8oYFtjcmVhdGVIYW5kbGVyT3B0aW9uc10gUm9vdCBjb21wb25lbnQgZXhwbGljaXRseSBkaXNhYmxlZCAoaGVhZGxlc3MgbW9kZSlgKTtcbiAgICAgIH1cbiAgICAgIFJvb3RDb21wb25lbnQgPSB1bmRlZmluZWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIExvYWQgY3VzdG9tIFJvb3QgY29tcG9uZW50IGZyb20gc3BlY2lmaWVkIHBhdGhcbiAgICAgIHRyeSB7XG4gICAgICAgIC8vIFVzZSBzYW1lIGRldmVsb3BtZW50IG1vZGUgbG9hZGVyIGxvZ2ljXG4gICAgICAgIGNvbnN0IGlzU2VydmVNb2RlID0gY29uZmlnRW52Py5jb21tYW5kID09PSBcInNlcnZlXCIgfHwgY29uZmlnRW52Py5tb2RlID09PSBcImRldmVsb3BtZW50XCIgfHwgbW9kZSA9PT0gXCJkZXZlbG9wbWVudFwiO1xuICAgICAgICBjb25zdCBjb21wb25lbnRMb2FkZXIgPSBpc1NlcnZlTW9kZSBcbiAgICAgICAgICA/IGFzeW5jIChwYXRoOiBzdHJpbmcpID0+IGltcG9ydChwYXRoKVxuICAgICAgICAgIDogZGVmYXVsdHMubG9hZGVyIHx8ICgoKSA9PiBQcm9taXNlLnJlc29sdmUoe30pKTtcbiAgICAgICAgXG4gICAgICAgIGNvbnN0IHJvb3RSZXN1bHQgPSBhd2FpdCByZXNvbHZlQ29tcG9uZW50KHtcbiAgICAgICAgICBjb21wb25lbnRQYXRoOiByb3V0ZUZpbGVzUmVzdWx0LnJvb3QsXG4gICAgICAgICAgZXhwb3J0TmFtZTogdXNlck9wdGlvbnMucm9vdEV4cG9ydE5hbWUsXG4gICAgICAgICAgbG9hZGVyOiBjb21wb25lbnRMb2FkZXIsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChyb290UmVzdWx0LnR5cGUgPT09IFwic3VjY2Vzc1wiKSB7XG4gICAgICAgICAgUm9vdENvbXBvbmVudCA9IHJvb3RSZXN1bHQuY29tcG9uZW50IGFzIFJvb3RDb21wb25lbnRUeXBlO1xuICAgICAgICAgIGxvZ2dlci5pbmZvKGBbY3JlYXRlSGFuZGxlck9wdGlvbnNdIExvYWRlZCBjdXN0b20gUm9vdCBjb21wb25lbnQgZnJvbSAke3JvdXRlRmlsZXNSZXN1bHQucm9vdH1gKTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oXG4gICAgICAgICAgYFtjcmVhdGVIYW5kbGVyT3B0aW9uc10gRXJyb3IgbG9hZGluZyBjdXN0b20gUm9vdCBjb21wb25lbnQ6ICR7XG4gICAgICAgICAgICBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcilcbiAgICAgICAgICB9YFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIGlmKCFSb290Q29tcG9uZW50KSB7XG4gICAgLy8gcm9vdFBhdGggaXMgdW5kZWZpbmVkLCB1c2UgZGVmYXVsdCBSb290IGNvbXBvbmVudFxuICAgIHRyeSB7XG4gICAgICBjb25zdCB7IFJvb3QgfSA9IGF3YWl0IGltcG9ydChcIi4uL2NvbXBvbmVudHMvcm9vdC5qc1wiKTtcbiAgICAgIFJvb3RDb21wb25lbnQgPSBSb290O1xuICAgICAgaWYgKHVzZXJPcHRpb25zLnZlcmJvc2UpIHtcbiAgICAgICAgbG9nZ2VyLmluZm8oYFtjcmVhdGVIYW5kbGVyT3B0aW9uc10gVXNpbmcgZGVmYXVsdCBSb290IGNvbXBvbmVudGApO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIud2FybihcbiAgICAgICAgYFtjcmVhdGVIYW5kbGVyT3B0aW9uc10gRXJyb3IgbG9hZGluZyBkZWZhdWx0IFJvb3QgY29tcG9uZW50OiAke1xuICAgICAgICAgIGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKVxuICAgICAgICB9YFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvLyBMb2FkIEh0bWwgY29tcG9uZW50IGlmIGh0bWxQYXRoIGlzIGF2YWlsYWJsZSwgb3IgdXNlIGRlZmF1bHQgSHRtbCBjb21wb25lbnQgaWYgaHRtbFBhdGggaXMgdW5kZWZpbmVkXG4gIGlmICghSHRtbENvbXBvbmVudCAmJiByb3V0ZUZpbGVzUmVzdWx0Lmh0bWwgIT09IHVuZGVmaW5lZCkge1xuICAgIC8vIElmIGh0bWxQYXRoIGlzIGV4cGxpY2l0bHkgc2V0IHRvIGVtcHR5IHN0cmluZywgZG9uJ3QgbG9hZCBhbnkgSHRtbCBjb21wb25lbnQgKGhlYWRsZXNzIG1vZGUpXG4gICAgaWYgKHJvdXRlRmlsZXNSZXN1bHQuaHRtbCA9PT0gJycpIHtcbiAgICAgIGlmICh1c2VyT3B0aW9ucy52ZXJib3NlKSB7XG4gICAgICAgIGxvZ2dlci5pbmZvKGBbY3JlYXRlSGFuZGxlck9wdGlvbnNdIEh0bWwgY29tcG9uZW50IGV4cGxpY2l0bHkgZGlzYWJsZWQgKGhlYWRsZXNzIG1vZGUpYCk7XG4gICAgICB9XG4gICAgICBIdG1sQ29tcG9uZW50ID0gdW5kZWZpbmVkO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBMb2FkIGN1c3RvbSBIdG1sIGNvbXBvbmVudCBmcm9tIHNwZWNpZmllZCBwYXRoXG4gICAgICB0cnkge1xuICAgICAgICBcbiAgICAgICAgLy8gVXNlIHNhbWUgZGV2ZWxvcG1lbnQgbW9kZSBsb2FkZXIgbG9naWNcbiAgICAgICAgY29uc3QgaXNTZXJ2ZU1vZGUgPSBjb25maWdFbnY/LmNvbW1hbmQgPT09IFwic2VydmVcIiB8fCBjb25maWdFbnY/Lm1vZGUgPT09IFwiZGV2ZWxvcG1lbnRcIiB8fCBtb2RlID09PSBcImRldmVsb3BtZW50XCI7XG4gICAgICAgIGNvbnN0IGNvbXBvbmVudExvYWRlciA9IGlzU2VydmVNb2RlIFxuICAgICAgICAgID8gYXN5bmMgKHBhdGg6IHN0cmluZykgPT4gYXdhaXQgaW1wb3J0KHBhdGgpXG4gICAgICAgICAgOiBkZWZhdWx0cy5sb2FkZXIgfHwgKCgpID0+IFByb21pc2UucmVzb2x2ZSh7fSkpO1xuICAgICAgICBcbiAgICAgICAgY29uc3QgaHRtbFJlc3VsdCA9IGF3YWl0IHJlc29sdmVDb21wb25lbnQoe1xuICAgICAgICAgIGNvbXBvbmVudFBhdGg6IHJvdXRlRmlsZXNSZXN1bHQuaHRtbCxcbiAgICAgICAgICBleHBvcnROYW1lOiB1c2VyT3B0aW9ucy5odG1sRXhwb3J0TmFtZSxcbiAgICAgICAgICBsb2FkZXI6IGNvbXBvbmVudExvYWRlcixcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKGh0bWxSZXN1bHQudHlwZSA9PT0gXCJzdWNjZXNzXCIpIHtcbiAgICAgICAgICBIdG1sQ29tcG9uZW50ID0gaHRtbFJlc3VsdC5jb21wb25lbnQgYXMgSHRtbENvbXBvbmVudFR5cGU7XG4gICAgICAgICAgbG9nZ2VyLmluZm8oYFtjcmVhdGVIYW5kbGVyT3B0aW9uc10gTG9hZGVkIGN1c3RvbSBIdG1sIGNvbXBvbmVudCBmcm9tICR7cm91dGVGaWxlc1Jlc3VsdC5odG1sfWApO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBsb2dnZXIud2FybihcbiAgICAgICAgICBgW2NyZWF0ZUhhbmRsZXJPcHRpb25zXSBFcnJvciBsb2FkaW5nIGN1c3RvbSBIdG1sIGNvbXBvbmVudDogJHtcbiAgICAgICAgICAgIGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKVxuICAgICAgICAgIH1gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9IGVsc2UgaWYoIUh0bWxDb21wb25lbnQpIHtcbiAgICAvLyBodG1sUGF0aCBpcyB1bmRlZmluZWQsIHVzZSBkZWZhdWx0IEh0bWwgY29tcG9uZW50XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHsgSHRtbCB9ID0gYXdhaXQgaW1wb3J0KFwiLi4vY29tcG9uZW50cy9odG1sLmpzXCIpO1xuICAgICAgSHRtbENvbXBvbmVudCA9IEh0bWw7XG4gICAgICBpZiAodXNlck9wdGlvbnMudmVyYm9zZSkge1xuICAgICAgICBsb2dnZXIuaW5mbyhgW2NyZWF0ZUhhbmRsZXJPcHRpb25zXSBVc2luZyBkZWZhdWx0IEh0bWwgY29tcG9uZW50YCk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci53YXJuKFxuICAgICAgICBgW2NyZWF0ZUhhbmRsZXJPcHRpb25zXSBFcnJvciBsb2FkaW5nIGRlZmF1bHQgSHRtbCBjb21wb25lbnQ6ICR7XG4gICAgICAgICAgZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpXG4gICAgICAgIH1gXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8vIENyZWF0ZSB3b3JrZXJzIGZvciBzZXJ2ZXIgZW52aXJvbm1lbnQgYmFzZWQgb24gY29uZmlndXJhdGlvbiBhbmQgY29uZmlnRW52XG4gIGxldCByc2NXb3JrZXI6IGFueSA9IHVuZGVmaW5lZDtcbiAgbGV0IGh0bWxXb3JrZXI6IGFueSA9IHVuZGVmaW5lZDtcbiAgXG4gIC8vIERldGVybWluZSBpZiB3ZSBuZWVkIHdvcmtlcnMgYmFzZWQgb24gY29uZmlnRW52IGFuZCBkZXYgY29uZmlnXG4gIGNvbnN0IGlzU2VydmVNb2RlID0gY29uZmlnRW52Py5jb21tYW5kID09PSBcInNlcnZlXCIgfHwgY29uZmlnRW52Py5tb2RlID09PSBcImRldmVsb3BtZW50XCIgfHwgbW9kZSA9PT0gXCJkZXZlbG9wbWVudFwiO1xuICBjb25zdCBpc0J1aWxkTW9kZSA9IGNvbmZpZ0Vudj8uY29tbWFuZCA9PT0gXCJidWlsZFwiO1xuICBcbiAgLy8gQ3JlYXRlIFJTQyB3b3JrZXIgaWY6XG4gIC8vIDEuIHVzZVJzY1dvcmtlciBpcyBlbmFibGVkIGluIGRldiBjb25maWcgQU5EIHdlJ3JlIGluIHNlcnZlIG1vZGUsIE9SXG4gIC8vIDIuIHVzZVJzY1dvcmtlciBpcyBlbmFibGVkIGluIGJ1aWxkIGNvbmZpZyBBTkQgd2UncmUgaW4gYnVpbGQgbW9kZVxuICBjb25zdCBzaG91bGRDcmVhdGVSc2NXb3JrZXIgPSAodXNlck9wdGlvbnMuZGV2Py51c2VSc2NXb3JrZXIgJiYgaXNTZXJ2ZU1vZGUpIHx8IFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh1c2VyT3B0aW9ucy5idWlsZD8udXNlUnNjV29ya2VyICYmIGlzQnVpbGRNb2RlKTtcbiAgXG4gIGlmIChzaG91bGRDcmVhdGVSc2NXb3JrZXIpIHtcbiAgICBpZiAodXNlck9wdGlvbnMudmVyYm9zZSkge1xuICAgICAgbG9nZ2VyLmluZm8oYFtjcmVhdGVIYW5kbGVyT3B0aW9ucy5zZXJ2ZXJdIENyZWF0aW5nIFJTQyB3b3JrZXIgZm9yIHJvdXRlOiAke3JvdXRlfWApO1xuICAgIH1cbiAgICBcbiAgICB0cnkge1xuICAgICAgXG4gICAgICBjb25zdCBzZXJpYWxpemVkVXNlck9wdGlvbnMgPSBzZXJpYWxpemVkT3B0aW9ucyh1c2VyT3B0aW9ucywgYXV0b0Rpc2NvdmVyZWRGaWxlcyk7XG4gICAgICBcbiAgICAgIC8vIFdlIGRvbid0IG5lZWQgdG8gY3JlYXRlIHRoZSBSU0Mgd29ya2VyLCBidXQgaWYgdGhlIHVzZXIgd2FudHMgdG8gdXNlIHRoZWlyIG93biB3b3JrZXJcbiAgICAgIC8vIGl0IGNhbiBiZSBkb25lIGJ5IHNldHRpbmcgZGV2LnVzZVJzY1dvcmtlcj10cnVlIG9yIGJ1aWxkLnVzZVJzY1dvcmtlcj10cnVlXG4gICAgICBjb25zdCB3b3JrZXJSZXN1bHQgPSBhd2FpdCBjcmVhdGVXb3JrZXIoe1xuICAgICAgICBjdXJyZW50Q29uZGl0aW9uOiBcInJlYWN0LXNlcnZlclwiLFxuICAgICAgICAvLyBzYW1lIENPTkRJVElPTiBhcyB0aGUgY3VycmVudCBvbmUgKHRoaXMgd29ya2VyIG1heSBiZSByZWR1bmRhbnQpXG4gICAgICAgIHJldmVyc2VDb25kaXRpb246IFwicmVhY3Qtc2VydmVyXCIsXG4gICAgICAgIHdvcmtlclBhdGg6IHVzZXJPcHRpb25zLnJzY1dvcmtlclBhdGgsXG4gICAgICAgIHZlcmJvc2U6IHVzZXJPcHRpb25zLnZlcmJvc2UsXG4gICAgICAgIGxvZ2dlcixcbiAgICAgICAgd29ya2VyRGF0YToge1xuICAgICAgICAgIGlkOiByb3V0ZSxcbiAgICAgICAgICB1c2VyT3B0aW9uczogc2VyaWFsaXplZFVzZXJPcHRpb25zLFxuICAgICAgICAgIHJlc29sdmVkQ29uZmlnOiB7XG4gICAgICAgICAgICBjb25maWdFbnYsXG4gICAgICAgICAgICBtb2RlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgaWYgKHdvcmtlclJlc3VsdC50eXBlID09PSBcImVycm9yXCIpIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oYFtjcmVhdGVIYW5kbGVyT3B0aW9ucy5zZXJ2ZXJdIEZhaWxlZCB0byBjcmVhdGUgUlNDIHdvcmtlcjogJHt3b3JrZXJSZXN1bHQuZXJyb3I/Lm1lc3NhZ2V9YCk7XG4gICAgICAgIHJzY1dvcmtlciA9IHVuZGVmaW5lZDtcbiAgICAgIH0gZWxzZSBpZiAod29ya2VyUmVzdWx0LnR5cGUgPT09IFwic2tpcFwiKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKGBbY3JlYXRlSGFuZGxlck9wdGlvbnMuc2VydmVyXSBSU0Mgd29ya2VyIGNyZWF0aW9uIHNraXBwZWQ6ICR7d29ya2VyUmVzdWx0LnJlYXNvbn1gKTtcbiAgICAgICAgcnNjV29ya2VyID0gdW5kZWZpbmVkO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcnNjV29ya2VyID0gd29ya2VyUmVzdWx0LndvcmtlcjtcbiAgICAgICAgaWYgKHVzZXJPcHRpb25zLnZlcmJvc2UpIHtcbiAgICAgICAgICBsb2dnZXIuaW5mbyhgW2NyZWF0ZUhhbmRsZXJPcHRpb25zLnNlcnZlcl0gUlNDIHdvcmtlciBjcmVhdGVkIHN1Y2Nlc3NmdWxseWApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci53YXJuKGBbY3JlYXRlSGFuZGxlck9wdGlvbnMuc2VydmVyXSBSU0Mgd29ya2VyIGNyZWF0aW9uIGZhaWxlZDogJHtlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcil9YCk7XG4gICAgICByc2NXb3JrZXIgPSB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgLy8gQ3JlYXRlIEhUTUwgd29ya2VyIGlmOlxuICAvLyBDcmVhdGUgSFRNTCB3b3JrZXIgaWY6XG4gIC8vIDEuIHVzZUh0bWxXb3JrZXIgaXMgZW5hYmxlZCBpbiBkZXYgY29uZmlnIEFORCB3ZSdyZSBpbiBzZXJ2ZSBtb2RlLCBPUlxuICAvLyAyLiB1c2VIdG1sV29ya2VyIGlzIGVuYWJsZWQgaW4gYnVpbGQgY29uZmlnIEFORCB3ZSdyZSBpbiBidWlsZCBtb2RlXG4gIGNvbnN0IHNob3VsZENyZWF0ZUh0bWxXb3JrZXIgPSAodXNlck9wdGlvbnMuZGV2Py51c2VIdG1sV29ya2VyICYmIGlzU2VydmVNb2RlKSB8fCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHVzZXJPcHRpb25zLmJ1aWxkPy51c2VIdG1sV29ya2VyICYmIGlzQnVpbGRNb2RlKTtcbiAgXG4gIGlmIChzaG91bGRDcmVhdGVIdG1sV29ya2VyKSB7XG4gICAgaWYgKHVzZXJPcHRpb25zLnZlcmJvc2UpIHtcbiAgICAgIGxvZ2dlci5pbmZvKGBbY3JlYXRlSGFuZGxlck9wdGlvbnMuc2VydmVyXSBDcmVhdGluZyBIVE1MIHdvcmtlciBmb3Igcm91dGU6ICR7cm91dGV9YCk7XG4gICAgfVxuICAgIFxuICAgIHRyeSB7XG4gICAgICBcbiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRVc2VyT3B0aW9ucyA9IHNlcmlhbGl6ZWRPcHRpb25zKHVzZXJPcHRpb25zLCBhdXRvRGlzY292ZXJlZEZpbGVzKTtcbiAgICAgIFxuICAgICAgY29uc3Qgd29ya2VyUmVzdWx0ID0gYXdhaXQgY3JlYXRlV29ya2VyKHtcbiAgICAgICAgY3VycmVudENvbmRpdGlvbjogXCJyZWFjdC1zZXJ2ZXJcIixcbiAgICAgICAgcmV2ZXJzZUNvbmRpdGlvbjogXCJyZWFjdC1jbGllbnRcIiwgLy8gSFRNTCB3b3JrZXIgbmVlZHMgcmVhY3QtY2xpZW50IGNvbmRpdGlvblxuICAgICAgICB3b3JrZXJQYXRoOiB1c2VyT3B0aW9ucy5odG1sV29ya2VyUGF0aCxcbiAgICAgICAgdmVyYm9zZTogdXNlck9wdGlvbnMudmVyYm9zZSxcbiAgICAgICAgbG9nZ2VyLFxuICAgICAgICB3b3JrZXJEYXRhOiB7XG4gICAgICAgICAgaWQ6IHJvdXRlLFxuICAgICAgICAgIHVzZXJPcHRpb25zOiBzZXJpYWxpemVkVXNlck9wdGlvbnMsXG4gICAgICAgICAgcmVzb2x2ZWRDb25maWc6IHtcbiAgICAgICAgICAgIGNvbmZpZ0VudixcbiAgICAgICAgICAgIG1vZGUsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBpZiAod29ya2VyUmVzdWx0LnR5cGUgPT09IFwiZXJyb3JcIikge1xuICAgICAgICBsb2dnZXIud2FybihgW2NyZWF0ZUhhbmRsZXJPcHRpb25zLnNlcnZlcl0gRmFpbGVkIHRvIGNyZWF0ZSBIVE1MIHdvcmtlcjogJHt3b3JrZXJSZXN1bHQuZXJyb3I/Lm1lc3NhZ2V9YCk7XG4gICAgICAgIGh0bWxXb3JrZXIgPSB1bmRlZmluZWQ7XG4gICAgICB9IGVsc2UgaWYgKHdvcmtlclJlc3VsdC50eXBlID09PSBcInNraXBcIikge1xuICAgICAgICBsb2dnZXIud2FybihgW2NyZWF0ZUhhbmRsZXJPcHRpb25zLnNlcnZlcl0gSFRNTCB3b3JrZXIgY3JlYXRpb24gc2tpcHBlZDogJHt3b3JrZXJSZXN1bHQucmVhc29ufWApO1xuICAgICAgICBodG1sV29ya2VyID0gdW5kZWZpbmVkO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaHRtbFdvcmtlciA9IHdvcmtlclJlc3VsdC53b3JrZXI7XG4gICAgICAgIGlmICh1c2VyT3B0aW9ucy52ZXJib3NlKSB7XG4gICAgICAgICAgbG9nZ2VyLmluZm8oYFtjcmVhdGVIYW5kbGVyT3B0aW9ucy5zZXJ2ZXJdIEhUTUwgd29ya2VyIGNyZWF0ZWQgc3VjY2Vzc2Z1bGx5YCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgbG9nZ2VyLndhcm4oYFtjcmVhdGVIYW5kbGVyT3B0aW9ucy5zZXJ2ZXJdIEhUTUwgd29ya2VyIGNyZWF0aW9uIGZhaWxlZDogJHtlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcil9YCk7XG4gICAgICBodG1sV29ya2VyID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgfVxuXG4gIC8vIENyZWF0ZSBzZXJ2ZXItc3BlY2lmaWMgaGFuZGxlciBvcHRpb25zXG4gIGNvbnN0IGhhbmRsZXJPcHRpb25zOiBDcmVhdGVIYW5kbGVyT3B0aW9ucyA9IHtcbiAgICAuLi51c2VyT3B0aW9ucyxcbiAgICAvLyBGaWxlIHBhdGhzXG4gICAgcGFnZVBhdGg6IHJvdXRlRmlsZXNSZXN1bHQucGFnZSxcbiAgICBwcm9wc1BhdGg6IHJvdXRlRmlsZXNSZXN1bHQucHJvcHMsXG4gICAgcm9vdFBhdGg6IHJvdXRlRmlsZXNSZXN1bHQucm9vdCxcbiAgICBodG1sUGF0aDogcm91dGVGaWxlc1Jlc3VsdC5odG1sLFxuICAgIFxuICAgIC8vIEV4cG9ydCBuYW1lc1xuICAgIHBhZ2VFeHBvcnROYW1lOiB1c2VyT3B0aW9ucy5wYWdlRXhwb3J0TmFtZSxcbiAgICBwcm9wc0V4cG9ydE5hbWU6IHVzZXJPcHRpb25zLnByb3BzRXhwb3J0TmFtZSxcbiAgICByb290RXhwb3J0TmFtZTogdXNlck9wdGlvbnMucm9vdEV4cG9ydE5hbWUsXG4gICAgaHRtbEV4cG9ydE5hbWU6IHVzZXJPcHRpb25zLmh0bWxFeHBvcnROYW1lLFxuICAgIFxuICAgIC8vIFJvdXRlIGFuZCBsb2FkZXJcbiAgICByb3V0ZSxcbiAgICBsb2FkZXI6IGRlZmF1bHRzLmxvYWRlciB8fCAoKCkgPT4gUHJvbWlzZS5yZXNvbHZlKHt9KSksXG4gICAgXG4gICAgLy8gQ29uZmlndXJhdGlvblxuICAgIHBhbmljVGhyZXNob2xkOiB1c2VyT3B0aW9ucy5wYW5pY1RocmVzaG9sZCxcbiAgICB2ZXJib3NlOiB1c2VyT3B0aW9ucy52ZXJib3NlLFxuICAgIG1vZHVsZUJhc2VVUkw6IHVzZXJPcHRpb25zLm1vZHVsZUJhc2VVUkwsXG4gICAgYnVpbGQ6IHVzZXJPcHRpb25zLmJ1aWxkLFxuICAgIGRldjoge1xuICAgICAgdXNlSHRtbFdvcmtlcjogdXNlck9wdGlvbnMuZGV2LnVzZUh0bWxXb3JrZXIsXG4gICAgICB1c2VSc2NXb3JrZXI6IHVzZXJPcHRpb25zLmRldi51c2VSc2NXb3JrZXIsXG4gICAgfSxcbiAgICBsb2dnZXIsXG4gICAgXG4gICAgLy8gUmVxdWlyZWQgcHJvcGVydGllc1xuICAgIG5vcm1hbGl6ZXI6IHVzZXJPcHRpb25zLm5vcm1hbGl6ZXIsXG4gICAgb25FdmVudDogdXNlck9wdGlvbnMub25FdmVudCxcbiAgICBvbk1ldHJpY3M6IHVzZXJPcHRpb25zLm9uTWV0cmljcyxcbiAgICBhdXRvRGlzY292ZXI6IHVzZXJPcHRpb25zLmF1dG9EaXNjb3ZlcixcbiAgICBjc3M6IHVzZXJPcHRpb25zLmNzcyxcbiAgICBwcm9qZWN0Um9vdDogdXNlck9wdGlvbnMucHJvamVjdFJvb3QsXG4gICAgbW9kdWxlQmFzZTogdXNlck9wdGlvbnMubW9kdWxlQmFzZSxcbiAgICBtb2R1bGVCYXNlUGF0aDogdXNlck9wdGlvbnMubW9kdWxlQmFzZVBhdGgsXG4gICAgbW9kdWxlUm9vdFBhdGg6IHVzZXJPcHRpb25zLm1vZHVsZVJvb3RQYXRoLFxuICAgIG1vZHVsZUlEOiB1c2VyT3B0aW9ucy5tb2R1bGVJRCxcbiAgICB1cmwsXG4gICAgbWFuaWZlc3Q6IGRlZmF1bHRzLm1hbmlmZXN0LFxuICAgIGNzc0ZpbGVzOiBkZWZhdWx0cy5jc3NGaWxlcyxcbiAgICBnbG9iYWxDc3M6IGRlZmF1bHRzLmdsb2JhbENzcyxcbiAgICBcbiAgICAvLyBUaW1lb3V0cyBhbmQgcGF0aHNcbiAgICByc2NUaW1lb3V0OiB1c2VyT3B0aW9ucy5yc2NUaW1lb3V0LFxuICAgIGh0bWxUaW1lb3V0OiB1c2VyT3B0aW9ucy5odG1sVGltZW91dCxcbiAgICBmaWxlV3JpdGVUaW1lb3V0OiB1c2VyT3B0aW9ucy5maWxlV3JpdGVUaW1lb3V0LFxuICAgIHdvcmtlclNodXRkb3duVGltZW91dDogdXNlck9wdGlvbnMud29ya2VyU2h1dGRvd25UaW1lb3V0LFxuICAgIHJzY1dvcmtlclBhdGg6IHVzZXJPcHRpb25zLnJzY1dvcmtlclBhdGgsXG4gICAgaHRtbFdvcmtlclBhdGg6IHVzZXJPcHRpb25zLmh0bWxXb3JrZXJQYXRoLFxuICAgIHB1YmxpY09yaWdpbjogdXNlck9wdGlvbnMucHVibGljT3JpZ2luLFxuICAgIFxuICAgIC8vIFN0cmVhbSBvcHRpb25zXG4gICAgc2VydmVyUGlwZWFibGVTdHJlYW1PcHRpb25zOiB1c2VyT3B0aW9ucy5zZXJ2ZXJQaXBlYWJsZVN0cmVhbU9wdGlvbnMsXG4gICAgY2xpZW50UGlwZWFibGVTdHJlYW1PcHRpb25zOiB1c2VyT3B0aW9ucy5jbGllbnRQaXBlYWJsZVN0cmVhbU9wdGlvbnMgfHwge30sXG4gICAgY29tcG9uZW50czogdXNlck9wdGlvbnMuY29tcG9uZW50cyxcbiAgICBcbiAgICAvLyBTZXJ2ZXItc3BlY2lmaWNcbiAgICBpZCxcbiAgICAvLyBBbHdheXMgdXNlIHRoZSBpbnZlcnNlIHdvcmtlciBmb3IgdGhlIG1haW4gXCJ3b3JrZXJcIiBmaWVsZFxuICAgIHdvcmtlcjogaHRtbFdvcmtlcixcbiAgICByc2NXb3JrZXIsXG4gICAgaHRtbFdvcmtlcixcbiAgICAvLyBMb2FkZWQgY29tcG9uZW50cyAoc2VydmVyIGxvYWRzIHRoZW0gYXQgY29uZmlndXJhdGlvbiB0aW1lKVxuICAgIFBhZ2VDb21wb25lbnQsXG4gICAgUm9vdENvbXBvbmVudCwgXG4gICAgSHRtbENvbXBvbmVudFxuICB9O1xuXG4gIC8vIENhY2hlIGFuZCByZXR1cm5cbiAgc3Rhc2hIYW5kbGVyT3B0aW9ucyhpZCwgaGFuZGxlck9wdGlvbnMpO1xuICByZXR1cm4gaGFuZGxlck9wdGlvbnM7XG59XG5cblxuZXhwb3J0IHR5cGUge1xuICBDcmVhdGVIYW5kbGVyT3B0aW9uc1BhcmFtcyxcbiAgQ3JlYXRlSGFuZGxlck9wdGlvbnNTZXJ2ZXJGbixcbiAgQ3JlYXRlSGFuZGxlck9wdGlvbnNDbGllbnRGbixcbn0gZnJvbSBcIi4vY3JlYXRlSGFuZGxlck9wdGlvbnMudHlwZXMuanNcIjtcbiJdLCJuYW1lcyI6WyJpc1NlcnZlTW9kZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQTZDQSxTQUFTLG9CQUF5QyxHQUFBO0FBQ2hELEVBQU8sT0FBQTtBQUFBLElBQ0wsZ0JBQWdCLGNBQWUsQ0FB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