UNPKG

vite-plugin-react-server

Version:
294 lines (291 loc) 38.9 kB
/** * 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 { createWorker } from '../worker/createWorker.js'; import { serializedOptions, serializeResolvedConfig } from '../helpers/serializeUserOptions.js'; import { getEnvironmentId, getStashedUserOptions, getStashedHandlerOptions, stashHandlerOptions } from './stashedOptionsState.js'; import { getNodeEnv } from './getNodeEnv.js'; import { createLogger } from 'vite'; import { DEFAULT_CONFIG } from './defaults.js'; import { getCondition } from './getCondition.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" }, children, id = `${route}-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`, condition = getCondition(), envId = getEnvironmentId(condition, mode), userOptions = getStashedUserOptions(envId), config = void 0 } = 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 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.client] Creating RSC worker for route: ${route}` ); } try { const serializedUserOptions = userOptions ? serializedOptions(userOptions, autoDiscoveredFiles) : void 0; const serializedResolvedConfig = config ? serializeResolvedConfig(config) : void 0; const workerResult = await createWorker({ currentCondition: "react-client", workerPath: userOptions.rscWorkerPath, verbose: userOptions.verbose, logger, workerData: { id: route, userOptions: serializedUserOptions, resolvedConfig: serializedResolvedConfig, configEnv } }); if (workerResult.type === "error") { logger.warn( `[createHandlerOptions.client] Failed to create RSC worker: ${workerResult.error?.message}` ); rscWorker = void 0; } else if (workerResult.type === "skip") { logger.warn( `[createHandlerOptions.client] RSC worker creation skipped: ${workerResult.reason}` ); rscWorker = void 0; } else { rscWorker = workerResult.worker; if (userOptions.verbose) { logger.info( `[createHandlerOptions.client] RSC worker created successfully` ); } } } catch (error) { logger.warn( `[createHandlerOptions.client] 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.client] Creating HTML worker for route: ${route}` ); } try { const fallbackDefaults = { verbose: false, panicThreshold: 1e3, moduleRootPath: "", moduleBaseURL: "", moduleBasePath: "", projectRoot: process.cwd(), htmlTimeout: 3e4, serverPipeableStreamOptions: {}, clientPipeableStreamOptions: {}, build: { useHtmlWorker: isBuildMode, useRscWorker: isBuildMode, pages: [] }, dev: { useHtmlWorker: false, useRscWorker: true } }; const serializedUserOptions = userOptions ? serializedOptions(userOptions, autoDiscoveredFiles) : serializedOptions(fallbackDefaults, autoDiscoveredFiles); const serializedResolvedConfig = config ? serializeResolvedConfig(config) : { mode: configEnv?.mode || mode || "development", root: process.cwd(), logLevel: "info", env: {}, envPrefix: "VITE_", base: "/", publicDir: "public", cacheDir: "node_modules/.vite", command: configEnv?.command || "serve", isSsrBuild: configEnv?.command === "build", isPreview: false }; const htmlWorkerResult = await createWorker({ currentCondition: "react-client", // We are in a .client file reverseCondition: "react-client", // The user still requested a worker, which uses the same condition workerPath: userOptions.htmlWorkerPath, verbose: userOptions.verbose, logger, workerData: { id: route, userOptions: serializedUserOptions, resolvedConfig: serializedResolvedConfig, configEnv } }); if (htmlWorkerResult.type === "error") { logger.warn( `[createHandlerOptions.client] Failed to create HTML worker: ${htmlWorkerResult.error?.message}` ); htmlWorker = void 0; } else if (htmlWorkerResult.type === "skip") { logger.warn( `[createHandlerOptions.client] HTML worker creation skipped: ${htmlWorkerResult.reason}` ); htmlWorker = void 0; } else { htmlWorker = htmlWorkerResult.worker; if (userOptions.verbose) { logger.info( `[createHandlerOptions.client] HTML worker created successfully` ); } } } catch (error) { logger.warn( `[createHandlerOptions.client] HTML worker creation failed: ${error instanceof Error ? error.message : String(error)}` ); htmlWorker = void 0; } } const handlerOptions = { ...userOptions, // File paths - these are passed directly to the worker for component resolution // The worker handles the distinction between undefined vs "" for Root and Html: // - undefined = use built-in default component // - "" = explicitly disable (headless mode for Html, React.Fragment for Root) // - string path = resolve custom component from specified path // This approach maintains consistency between server and client paradigms 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, // Client-specific id, // Client needs component placeholders since it can't load server modules directly HtmlComponent: void 0, PageComponent: void 0, RootComponent: void 0, // Workers for client environment - provide both for specific use cases worker: condition === "react-server" ? rscWorker : htmlWorker, // Backward compatibility: prefer HTML worker if available rscWorker, htmlWorker, // Children provided directly via options children }; stashHandlerOptions(id, handlerOptions); return handlerOptions; } export { createHandlerOptions }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlSGFuZGxlck9wdGlvbnMuY2xpZW50LmpzIiwic291cmNlcyI6WyIuLi8uLi8uLi9wbHVnaW4vY29uZmlnL2NyZWF0ZUhhbmRsZXJPcHRpb25zLmNsaWVudC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IENyZWF0ZUhhbmRsZXJPcHRpb25zLCBBdXRvRGlzY292ZXJlZEZpbGVzIH0gZnJvbSBcIi4uL3R5cGVzLmpzXCI7XG5pbXBvcnQgdHlwZSB7IExvZ2dlciB9IGZyb20gXCJ2aXRlXCI7XG5pbXBvcnQgeyBnZXRSb3V0ZUZpbGVzIH0gZnJvbSBcIi4uL2hlbHBlcnMvZ2V0Um91dGVGaWxlcy5qc1wiO1xuaW1wb3J0IHsgcm91dGVUb1VSTCB9IGZyb20gXCIuLi91dGlscy9yb3V0ZVRvVVJMLmpzXCI7XG5pbXBvcnQgeyByZXNvbHZlQXV0b0Rpc2NvdmVyIH0gZnJvbSBcIi4vYXV0b0Rpc2NvdmVyL3Jlc29sdmVBdXRvRGlzY292ZXIuanNcIjtcbmltcG9ydCB7IGNyZWF0ZVdvcmtlciB9IGZyb20gXCIuLi93b3JrZXIvY3JlYXRlV29ya2VyLmpzXCI7XG5pbXBvcnQge1xuICBzZXJpYWxpemVkT3B0aW9ucyxcbiAgc2VyaWFsaXplUmVzb2x2ZWRDb25maWcsXG59IGZyb20gXCIuLi9oZWxwZXJzL3NlcmlhbGl6ZVVzZXJPcHRpb25zLmpzXCI7XG5cbmltcG9ydCB7XG4gIGdldFN0YXNoZWRVc2VyT3B0aW9ucyxcbiAgZ2V0U3Rhc2hlZEhhbmRsZXJPcHRpb25zLFxuICBzdGFzaEhhbmRsZXJPcHRpb25zLFxuICBnZXRFbnZpcm9ubWVudElkLFxufSBmcm9tIFwiLi9zdGFzaGVkT3B0aW9uc1N0YXRlLmpzXCI7XG5pbXBvcnQgeyBnZXROb2RlRW52IH0gZnJvbSBcIi4vZ2V0Tm9kZUVudi5qc1wiO1xuaW1wb3J0IHsgY3JlYXRlTG9nZ2VyIH0gZnJvbSBcInZpdGVcIjtcbmltcG9ydCB7IERFRkFVTFRfQ09ORklHIH0gZnJvbSBcIi4vZGVmYXVsdHMuanNcIjtcbmltcG9ydCB0eXBlIHtcbiAgQ3JlYXRlSGFuZGxlck9wdGlvbnNQYXJhbXMsXG4gIFJlc29sdmVkRGVmYXVsdHMsXG59IGZyb20gXCIuL2NyZWF0ZUhhbmRsZXJPcHRpb25zLnR5cGVzLmpzXCI7XG5pbXBvcnQgeyBnZXRDb25kaXRpb24gfSBmcm9tIFwiLi9nZXRDb25kaXRpb24uanNcIjtcblxuLyoqXG4gKiBDbGllbnQtc3BlY2lmaWMgaGFuZGxlciBvcHRpb25zIGNyZWF0aW9uIGZvciBIVE1MIGdlbmVyYXRpb24uXG4gKlxuICogV0hBVCBUSElTIERPRVM6XG4gKiAtIENyZWF0ZXMgaGFuZGxlciBvcHRpb25zIG9wdGltaXplZCBmb3IgY2xpZW50LXNpZGUgcmVuZGVyaW5nXG4gKiAtIFJlc29sdmVzIGZpbGUgcGF0aHMgZm9yIHBhZ2VzLCBwcm9wcywgcm9vdCwgYW5kIEhUTUwgY29tcG9uZW50c1xuICogLSBTZXRzIHVwIGNsaWVudC1zcGVjaWZpYyBsb2FkZXJzIGFuZCBjb25maWd1cmF0aW9uXG4gKiAtIEhhbmRsZXMgY2FjaGluZyB3aXRoIHVuaXF1ZSBJRHNcbiAqIC0gUHJvdmlkZXMgY29tcG9uZW50IHBsYWNlaG9sZGVycyAoc2luY2UgY2xpZW50IGNhbid0IGxvYWQgc2VydmVyIG1vZHVsZXMpXG4gKiAtIFByb3ZpZGVzIGFsbCBuZWNlc3Nhcnkgb3B0aW9ucyBmb3IgSFRNTCBzdHJlYW0gY3JlYXRpb25cbiAqXG4gKiBXSEFUIFRISVMgRE9FU04nVCBETzpcbiAqIC0gRG9lcyBOT1QgbG9hZCBSZWFjdCBjb21wb25lbnRzICh0aGF0IGhhcHBlbnMgaW4gd29ya2VycyBvciBoYW5kbGVycylcbiAqIC0gRG9lcyBOT1QgY3JlYXRlIEhUTUwgc3RyZWFtcyAodXNlIGNyZWF0ZUhhbmRsZXIgZm9yIHRoYXQpXG4gKiAtIERvZXMgTk9UIGhhbmRsZSBzZXJ2ZXItc2lkZSByZW5kZXJpbmcgKHVzZSAuc2VydmVyLnRzIGZvciB0aGF0KVxuICogLSBEb2VzIE5PVCBtYW5hZ2UgY29tcG9uZW50IGxpZmVjeWNsZSBvciBzdGF0ZVxuICpcbiAqIFVTQUdFOlxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgaGFuZGxlck9wdGlvbnMgPSBhd2FpdCBjcmVhdGVIYW5kbGVyT3B0aW9ucyhcIi9teS1yb3V0ZVwiLCB7XG4gKiAgIGxvZ2dlcjogbXlMb2dnZXIsXG4gKiAgIGRlZmF1bHRzOiB7IGxvYWRlcjogKCkgPT4gUHJvbWlzZS5yZXNvbHZlKHt9KSB9XG4gKiB9KTtcbiAqIGBgYFxuICovXG5cbmZ1bmN0aW9uIGNyZWF0ZURlZmF1bHRPcHRpb25zKCk6IFJlc29sdmVkRGVmYXVsdHMge1xuICByZXR1cm4ge1xuICAgIHBhZ2VFeHBvcnROYW1lOiBERUZBVUxUX0NPTkZJRy5QQUdFX0VYUE9SVF9OQU1FLFxuICAgIHByb3BzRXhwb3J0TmFtZTogREVGQVVMVF9DT05GSUcuUFJPUFNfRVhQT1JUX05BTUUsXG4gICAgcm9vdEV4cG9ydE5hbWU6IERFRkFVTFRfQ09ORklHLlJPT1RfRVhQT1JUX05BTUUsXG4gICAgaHRtbEV4cG9ydE5hbWU6IERFRkFVTFRfQ09ORklHLkhUTUxfRVhQT1JUX05BTUUsXG4gICAgY3NzRmlsZXM6IG5ldyBNYXAoKSxcbiAgICBnbG9iYWxDc3M6IG5ldyBNYXAoKSxcbiAgICBtYW5pZmVzdDoge30sXG4gICAgY3NzOiBERUZBVUxUX0NPTkZJRy5DU1MsXG4gIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVBdXRvRGlzY292ZXJlZEZpbGVzKFxuICBvcHRpb25zOiBDcmVhdGVIYW5kbGVyT3B0aW9uc1BhcmFtcyxcbiAgc3Rhc2hlZE9wdGlvbnM6IGFueSxcbiAgbG9nZ2VyOiBMb2dnZXJcbik6IFByb21pc2U8QXV0b0Rpc2NvdmVyZWRGaWxlcz4ge1xuICBpZiAob3B0aW9ucy5hdXRvRGlzY292ZXJlZEZpbGVzKSB7XG4gICAgcmV0dXJuIG9wdGlvbnMuYXV0b0Rpc2NvdmVyZWRGaWxlcztcbiAgfVxuXG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHJlc29sdmVBdXRvRGlzY292ZXIoe1xuICAgIGNvbmZpZzogb3B0aW9ucy5jb25maWcgfHwge30sXG4gICAgY29uZmlnRW52OiBvcHRpb25zLmNvbmZpZ0VudiB8fCB7IG1vZGU6IFwicHJvZHVjdGlvblwiLCBjb21tYW5kOiBcImJ1aWxkXCIgfSxcbiAgICB1c2VyT3B0aW9uczogc3Rhc2hlZE9wdGlvbnMsXG4gICAgbG9nZ2VyLFxuICB9KTtcblxuICBpZiAocmVzdWx0LnR5cGUgPT09IFwiZXJyb3JcIikge1xuICAgIHRocm93IHJlc3VsdC5lcnJvciB8fCBuZXcgRXJyb3IoXCJGYWlsZWQgdG8gcmVzb2x2ZSBhdXRvRGlzY292ZXJcIik7XG4gIH1cblxuICByZXR1cm4gcmVzdWx0LmF1dG9EaXNjb3ZlcmVkRmlsZXM7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjcmVhdGVIYW5kbGVyT3B0aW9ucyhcbiAgcm91dGU6IHN0cmluZyxcbiAgb3B0aW9uczogQ3JlYXRlSGFuZGxlck9wdGlvbnNQYXJhbXMgPSB7fVxuKTogUHJvbWlzZTxDcmVhdGVIYW5kbGVyT3B0aW9ucz4ge1xuICBjb25zdCB7XG4gICAgbW9kZSA9IGdldE5vZGVFbnYoKSxcbiAgICBsb2dnZXIgPSBjcmVhdGVMb2dnZXIoKSxcbiAgICBjb25maWdFbnYgPSB7IG1vZGU6IG1vZGUgfHwgXCJwcm9kdWN0aW9uXCIsIGNvbW1hbmQ6IFwiYnVpbGRcIiB9LFxuICAgIGNoaWxkcmVuLFxuICAgIGlkID0gYCR7cm91dGV9LSR7RGF0ZS5ub3coKX0tJHtNYXRoLnJhbmRvbSgpXG4gICAgICAudG9TdHJpbmcoMzYpXG4gICAgICAuc3Vic3RyaW5nKDIsIDExKX1gLFxuICAgIGNvbmRpdGlvbiA9IGdldENvbmRpdGlvbigpLFxuICAgIGVudklkID0gZ2V0RW52aXJvbm1lbnRJZChjb25kaXRpb24sIG1vZGUpLFxuICAgIHVzZXJPcHRpb25zID0gZ2V0U3Rhc2hlZFVzZXJPcHRpb25zKGVudklkKSxcbiAgICBjb25maWcgPSB1bmRlZmluZWQsXG4gIH0gPSBvcHRpb25zO1xuXG4gIC8vIENoZWNrIGNhY2hlIGZpcnN0XG4gIGNvbnN0IGNhY2hlZE9wdGlvbnMgPSBnZXRTdGFzaGVkSGFuZGxlck9wdGlvbnMoaWQpO1xuICBpZiAoY2FjaGVkT3B0aW9ucykge1xuICAgIHJldHVybiBjYWNoZWRPcHRpb25zO1xuICB9XG5cbiAgaWYgKCF1c2VyT3B0aW9ucykge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBObyBzdGFzaGVkIHVzZXJPcHRpb25zIGZvdW5kIGZvciBlbnZpcm9ubWVudDogJHtlbnZJZH0uIE1ha2Ugc3VyZSByZXNvbHZlT3B0aW9ucygpIGhhcyBiZWVuIGNhbGxlZCBmaXJzdC5gXG4gICAgKTtcbiAgfVxuXG4gIC8vIFJlc29sdmUgZGVmYXVsdHNcbiAgY29uc3QgZGVmYXVsdHMgPSB7IC4uLmNyZWF0ZURlZmF1bHRPcHRpb25zKCksIC4uLm9wdGlvbnMuZGVmYXVsdHMgfTtcblxuICAvLyBSZXNvbHZlIGF1dG8tZGlzY292ZXJlZCBmaWxlc1xuICBjb25zdCBhdXRvRGlzY292ZXJlZEZpbGVzID0gYXdhaXQgcmVzb2x2ZUF1dG9EaXNjb3ZlcmVkRmlsZXMoXG4gICAgb3B0aW9ucyxcbiAgICB1c2VyT3B0aW9ucyxcbiAgICBsb2dnZXJcbiAgKTtcblxuICAvLyBDcmVhdGUgVVJMXG4gIGNvbnN0IHVybCA9IHJvdXRlVG9VUkwoXG4gICAgcm91dGUsXG4gICAgdXNlck9wdGlvbnMubW9kdWxlQmFzZVVSTCxcbiAgICB1c2VyT3B0aW9ucy5idWlsZC5yc2NPdXRwdXRQYXRoXG4gICk7XG5cbiAgLy8gR2V0IHJvdXRlIGZpbGVzXG4gIGNvbnN0IHJvdXRlRmlsZXNSZXN1bHQgPSBhd2FpdCBnZXRSb3V0ZUZpbGVzKFxuICAgIHJvdXRlLFxuICAgIGF1dG9EaXNjb3ZlcmVkRmlsZXMsXG4gICAgdXNlck9wdGlvbnMsXG4gICAgbG9nZ2VyXG4gICk7XG5cbiAgaWYgKHJvdXRlRmlsZXNSZXN1bHQudHlwZSA9PT0gXCJlcnJvclwiKSB7XG4gICAgdGhyb3cgcm91dGVGaWxlc1Jlc3VsdC5lcnJvciB8fCBuZXcgRXJyb3IoXCJGYWlsZWQgdG8gZ2V0IHJvdXRlIGZpbGVzXCIpO1xuICB9XG5cbiAgLy8gQ3JlYXRlIHdvcmtlcnMgZm9yIGNsaWVudCBlbnZpcm9ubWVudCBiYXNlZCBvbiBjb25maWd1cmF0aW9uIGFuZCBjb25maWdFbnZcbiAgbGV0IHJzY1dvcmtlcjogYW55ID0gdW5kZWZpbmVkO1xuICBsZXQgaHRtbFdvcmtlcjogYW55ID0gdW5kZWZpbmVkO1xuXG4gIC8vIERldGVybWluZSBpZiB3ZSBuZWVkIHdvcmtlcnMgYmFzZWQgb24gY29uZmlnRW52IGFuZCBkZXYgY29uZmlnXG4gIGNvbnN0IGlzU2VydmVNb2RlID1cbiAgICBjb25maWdFbnY/LmNvbW1hbmQgPT09IFwic2VydmVcIiB8fFxuICAgIGNvbmZpZ0Vudj8ubW9kZSA9PT0gXCJkZXZlbG9wbWVudFwiIHx8XG4gICAgbW9kZSA9PT0gXCJkZXZlbG9wbWVudFwiO1xuICBjb25zdCBpc0J1aWxkTW9kZSA9IGNvbmZpZ0Vudj8uY29tbWFuZCA9PT0gXCJidWlsZFwiO1xuXG4gIC8vIENyZWF0ZSBSU0Mgd29ya2VyIGlmOlxuICAvLyAxLiB1c2VSc2NXb3JrZXIgaXMgZW5hYmxlZCBpbiBkZXYgY29uZmlnIEFORCB3ZSdyZSBpbiBzZXJ2ZSBtb2RlLCBPUlxuICAvLyAyLiB1c2VSc2NXb3JrZXIgaXMgZW5hYmxlZCBpbiBidWlsZCBjb25maWcgQU5EIHdlJ3JlIGluIGJ1aWxkIG1vZGVcbiAgY29uc3Qgc2hvdWxkQ3JlYXRlUnNjV29ya2VyID1cbiAgICAodXNlck9wdGlvbnMuZGV2Py51c2VSc2NXb3JrZXIgJiYgaXNTZXJ2ZU1vZGUpIHx8XG4gICAgKHVzZXJPcHRpb25zLmJ1aWxkPy51c2VSc2NXb3JrZXIgJiYgaXNCdWlsZE1vZGUpO1xuXG4gIGlmIChzaG91bGRDcmVhdGVSc2NXb3JrZXIpIHtcbiAgICBpZiAodXNlck9wdGlvbnMudmVyYm9zZSkge1xuICAgICAgbG9nZ2VyLmluZm8oXG4gICAgICAgIGBbY3JlYXRlSGFuZGxlck9wdGlvbnMuY2xpZW50XSBDcmVhdGluZyBSU0Mgd29ya2VyIGZvciByb3V0ZTogJHtyb3V0ZX1gXG4gICAgICApO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBzZXJpYWxpemVkVXNlck9wdGlvbnMgPSB1c2VyT3B0aW9uc1xuICAgICAgICA/IHNlcmlhbGl6ZWRPcHRpb25zKHVzZXJPcHRpb25zLCBhdXRvRGlzY292ZXJlZEZpbGVzKVxuICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgICAgY29uc3Qgc2VyaWFsaXplZFJlc29sdmVkQ29uZmlnID0gY29uZmlnXG4gICAgICAgID8gc2VyaWFsaXplUmVzb2x2ZWRDb25maWcoY29uZmlnKVxuICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgICAgY29uc3Qgd29ya2VyUmVzdWx0ID0gYXdhaXQgY3JlYXRlV29ya2VyKHtcbiAgICAgICAgY3VycmVudENvbmRpdGlvbjogXCJyZWFjdC1jbGllbnRcIixcbiAgICAgICAgd29ya2VyUGF0aDogdXNlck9wdGlvbnMucnNjV29ya2VyUGF0aCxcbiAgICAgICAgdmVyYm9zZTogdXNlck9wdGlvbnMudmVyYm9zZSxcbiAgICAgICAgbG9nZ2VyLFxuICAgICAgICB3b3JrZXJEYXRhOiB7XG4gICAgICAgICAgaWQ6IHJvdXRlLFxuICAgICAgICAgIHVzZXJPcHRpb25zOiBzZXJpYWxpemVkVXNlck9wdGlvbnMsXG4gICAgICAgICAgcmVzb2x2ZWRDb25maWc6IHNlcmlhbGl6ZWRSZXNvbHZlZENvbmZpZyxcbiAgICAgICAgICBjb25maWdFbnYsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgaWYgKHdvcmtlclJlc3VsdC50eXBlID09PSBcImVycm9yXCIpIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oXG4gICAgICAgICAgYFtjcmVhdGVIYW5kbGVyT3B0aW9ucy5jbGllbnRdIEZhaWxlZCB0byBjcmVhdGUgUlNDIHdvcmtlcjogJHt3b3JrZXJSZXN1bHQuZXJyb3I/Lm1lc3NhZ2V9YFxuICAgICAgICApO1xuICAgICAgICByc2NXb3JrZXIgPSB1bmRlZmluZWQ7XG4gICAgICB9IGVsc2UgaWYgKHdvcmtlclJlc3VsdC50eXBlID09PSBcInNraXBcIikge1xuICAgICAgICBsb2dnZXIud2FybihcbiAgICAgICAgICBgW2NyZWF0ZUhhbmRsZXJPcHRpb25zLmNsaWVudF0gUlNDIHdvcmtlciBjcmVhdGlvbiBza2lwcGVkOiAke3dvcmtlclJlc3VsdC5yZWFzb259YFxuICAgICAgICApO1xuICAgICAgICByc2NXb3JrZXIgPSB1bmRlZmluZWQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByc2NXb3JrZXIgPSB3b3JrZXJSZXN1bHQud29ya2VyO1xuICAgICAgICBpZiAodXNlck9wdGlvbnMudmVyYm9zZSkge1xuICAgICAgICAgIGxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgYFtjcmVhdGVIYW5kbGVyT3B0aW9ucy5jbGllbnRdIFJTQyB3b3JrZXIgY3JlYXRlZCBzdWNjZXNzZnVsbHlgXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIud2FybihcbiAgICAgICAgYFtjcmVhdGVIYW5kbGVyT3B0aW9ucy5jbGllbnRdIFJTQyB3b3JrZXIgY3JlYXRpb24gZmFpbGVkOiAke1xuICAgICAgICAgIGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKVxuICAgICAgICB9YFxuICAgICAgKTtcbiAgICAgIHJzY1dvcmtlciA9IHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cblxuICAvLyBDcmVhdGUgSFRNTCB3b3JrZXIgaWY6XG4gIC8vIDEuIHVzZUh0bWxXb3JrZXIgaXMgZW5hYmxlZCBpbiBkZXYgY29uZmlnIEFORCB3ZSdyZSBpbiBzZXJ2ZSBtb2RlLCBPUlxuICAvLyAyLiB1c2VIdG1sV29ya2VyIGlzIGVuYWJsZWQgaW4gYnVpbGQgY29uZmlnIEFORCB3ZSdyZSBpbiBidWlsZCBtb2RlXG4gIGNvbnN0IHNob3VsZENyZWF0ZUh0bWxXb3JrZXIgPVxuICAgICh1c2VyT3B0aW9ucy5kZXY/LnVzZUh0bWxXb3JrZXIgJiYgaXNTZXJ2ZU1vZGUpIHx8XG4gICAgKHVzZXJPcHRpb25zLmJ1aWxkPy51c2VIdG1sV29ya2VyICYmIGlzQnVpbGRNb2RlKTtcblxuICBpZiAoc2hvdWxkQ3JlYXRlSHRtbFdvcmtlcikge1xuICAgIGlmICh1c2VyT3B0aW9ucy52ZXJib3NlKSB7XG4gICAgICBsb2dnZXIuaW5mbyhcbiAgICAgICAgYFtjcmVhdGVIYW5kbGVyT3B0aW9ucy5jbGllbnRdIENyZWF0aW5nIEhUTUwgd29ya2VyIGZvciByb3V0ZTogJHtyb3V0ZX1gXG4gICAgICApO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICAvLyBDcmVhdGUgZmFsbGJhY2sgZGVmYXVsdHMgYmFzZWQgb24gY29uZmlnRW52XG4gICAgICBjb25zdCBmYWxsYmFja0RlZmF1bHRzID0ge1xuICAgICAgICB2ZXJib3NlOiBmYWxzZSxcbiAgICAgICAgcGFuaWNUaHJlc2hvbGQ6IDEwMDAsXG4gICAgICAgIG1vZHVsZVJvb3RQYXRoOiBcIlwiLFxuICAgICAgICBtb2R1bGVCYXNlVVJMOiBcIlwiLFxuICAgICAgICBtb2R1bGVCYXNlUGF0aDogXCJcIixcbiAgICAgICAgcHJvamVjdFJvb3Q6IHByb2Nlc3MuY3dkKCksXG4gICAgICAgIGh0bWxUaW1lb3V0OiAzMDAwMCxcbiAgICAgICAgc2VydmVyUGlwZWFibGVTdHJlYW1PcHRpb25zOiB7fSxcbiAgICAgICAgY2xpZW50UGlwZWFibGVTdHJlYW1PcHRpb25zOiB7fSxcbiAgICAgICAgYnVpbGQ6IHtcbiAgICAgICAgICB1c2VIdG1sV29ya2VyOiBpc0J1aWxkTW9kZSxcbiAgICAgICAgICB1c2VSc2NXb3JrZXI6IGlzQnVpbGRNb2RlLFxuICAgICAgICAgIHBhZ2VzOiBbXSxcbiAgICAgICAgfSxcbiAgICAgICAgZGV2OiB7XG4gICAgICAgICAgdXNlSHRtbFdvcmtlcjogZmFsc2UsXG4gICAgICAgICAgdXNlUnNjV29ya2VyOiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgfTtcblxuICAgICAgY29uc3Qgc2VyaWFsaXplZFVzZXJPcHRpb25zID0gdXNlck9wdGlvbnNcbiAgICAgICAgPyBzZXJpYWxpemVkT3B0aW9ucyh1c2VyT3B0aW9ucywgYXV0b0Rpc2NvdmVyZWRGaWxlcylcbiAgICAgICAgOiBzZXJpYWxpemVkT3B0aW9ucyhmYWxsYmFja0RlZmF1bHRzIGFzIGFueSwgYXV0b0Rpc2NvdmVyZWRGaWxlcyk7XG5cbiAgICAgIGNvbnN0IHNlcmlhbGl6ZWRSZXNvbHZlZENvbmZpZyA9IGNvbmZpZ1xuICAgICAgICA/IHNlcmlhbGl6ZVJlc29sdmVkQ29uZmlnKGNvbmZpZylcbiAgICAgICAgOiB7XG4gICAgICAgICAgICBtb2RlOiBjb25maWdFbnY/Lm1vZGUgfHwgbW9kZSB8fCBcImRldmVsb3BtZW50XCIsXG4gICAgICAgICAgICByb290OiBwcm9jZXNzLmN3ZCgpLFxuICAgICAgICAgICAgbG9nTGV2ZWw6IFwiaW5mb1wiLFxuICAgICAgICAgICAgZW52OiB7fSxcbiAgICAgICAgICAgIGVudlByZWZpeDogXCJWSVRFX1wiLFxuICAgICAgICAgICAgYmFzZTogXCIvXCIsXG4gICAgICAgICAgICBwdWJsaWNEaXI6IFwicHVibGljXCIsXG4gICAgICAgICAgICBjYWNoZURpcjogXCJub2RlX21vZHVsZXMvLnZpdGVcIixcbiAgICAgICAgICAgIGNvbW1hbmQ6IGNvbmZpZ0Vudj8uY29tbWFuZCB8fCBcInNlcnZlXCIsXG4gICAgICAgICAgICBpc1NzckJ1aWxkOiBjb25maWdFbnY/LmNvbW1hbmQgPT09IFwiYnVpbGRcIixcbiAgICAgICAgICAgIGlzUHJldmlldzogZmFsc2UsXG4gICAgICAgICAgfTtcblxuICAgICAgY29uc3QgaHRtbFdvcmtlclJlc3VsdCA9IGF3YWl0IGNyZWF0ZVdvcmtlcih7XG4gICAgICAgIGN1cnJlbnRDb25kaXRpb246IFwicmVhY3QtY2xpZW50XCIsIC8vIFdlIGFyZSBpbiBhIC5jbGllbnQgZmlsZVxuICAgICAgICByZXZlcnNlQ29uZGl0aW9uOiBcInJlYWN0LWNsaWVudFwiLCAvLyBUaGUgdXNlciBzdGlsbCByZXF1ZXN0ZWQgYSB3b3JrZXIsIHdoaWNoIHVzZXMgdGhlIHNhbWUgY29uZGl0aW9uXG4gICAgICAgIHdvcmtlclBhdGg6IHVzZXJPcHRpb25zLmh0bWxXb3JrZXJQYXRoLFxuICAgICAgICB2ZXJib3NlOiB1c2VyT3B0aW9ucy52ZXJib3NlLFxuICAgICAgICBsb2dnZXIsXG4gICAgICAgIHdvcmtlckRhdGE6IHtcbiAgICAgICAgICBpZDogcm91dGUsXG4gICAgICAgICAgdXNlck9wdGlvbnM6IHNlcmlhbGl6ZWRVc2VyT3B0aW9ucyxcbiAgICAgICAgICByZXNvbHZlZENvbmZpZzogc2VyaWFsaXplZFJlc29sdmVkQ29uZmlnLFxuICAgICAgICAgIGNvbmZpZ0VudixcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoaHRtbFdvcmtlclJlc3VsdC50eXBlID09PSBcImVycm9yXCIpIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oXG4gICAgICAgICAgYFtjcmVhdGVIYW5kbGVyT3B0aW9ucy5jbGllbnRdIEZhaWxlZCB0byBjcmVhdGUgSFRNTCB3b3JrZXI6ICR7aHRtbFdvcmtlclJlc3VsdC5lcnJvcj8ubWVzc2FnZX1gXG4gICAgICAgICk7XG4gICAgICAgIGh0bWxXb3JrZXIgPSB1bmRlZmluZWQ7XG4gICAgICB9IGVsc2UgaWYgKGh0bWxXb3JrZXJSZXN1bHQudHlwZSA9PT0gXCJza2lwXCIpIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oXG4gICAgICAgICAgYFtjcmVhdGVIYW5kbGVyT3B0aW9ucy5jbGllbnRdIEhUTUwgd29ya2VyIGNyZWF0aW9uIHNraXBwZWQ6ICR7aHRtbFdvcmtlclJlc3VsdC5yZWFzb259YFxuICAgICAgICApO1xuICAgICAgICBodG1sV29ya2VyID0gdW5kZWZpbmVkO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaHRtbFdvcmtlciA9IGh0bWxXb3JrZXJSZXN1bHQud29ya2VyO1xuICAgICAgICBpZiAodXNlck9wdGlvbnMudmVyYm9zZSkge1xuICAgICAgICAgIGxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgYFtjcmVhdGVIYW5kbGVyT3B0aW9ucy5jbGllbnRdIEhUTUwgd29ya2VyIGNyZWF0ZWQgc3VjY2Vzc2Z1bGx5YFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgbG9nZ2VyLndhcm4oXG4gICAgICAgIGBbY3JlYXRlSGFuZGxlck9wdGlvbnMuY2xpZW50XSBIVE1MIHdvcmtlciBjcmVhdGlvbiBmYWlsZWQ6ICR7XG4gICAgICAgICAgZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpXG4gICAgICAgIH1gXG4gICAgICApO1xuICAgICAgaHRtbFdvcmtlciA9IHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cblxuICAvLyBDcmVhdGUgY2xpZW50LXNwZWNpZmljIGhhbmRsZXIgb3B0aW9uc1xuICBjb25zdCBoYW5kbGVyT3B0aW9uczogQ3JlYXRlSGFuZGxlck9wdGlvbnMgPSB7XG4gICAgLi4udXNlck9wdGlvbnMsXG4gICAgLy8gRmlsZSBwYXRocyAtIHRoZXNlIGFyZSBwYXNzZWQgZGlyZWN0bHkgdG8gdGhlIHdvcmtlciBmb3IgY29tcG9uZW50IHJlc29sdXRpb25cbiAgICAvLyBUaGUgd29ya2VyIGhhbmRsZXMgdGhlIGRpc3RpbmN0aW9uIGJldHdlZW4gdW5kZWZpbmVkIHZzIFwiXCIgZm9yIFJvb3QgYW5kIEh0bWw6XG4gICAgLy8gLSB1bmRlZmluZWQgPSB1c2UgYnVpbHQtaW4gZGVmYXVsdCBjb21wb25lbnRcbiAgICAvLyAtIFwiXCIgPSBleHBsaWNpdGx5IGRpc2FibGUgKGhlYWRsZXNzIG1vZGUgZm9yIEh0bWwsIFJlYWN0LkZyYWdtZW50IGZvciBSb290KVxuICAgIC8vIC0gc3RyaW5nIHBhdGggPSByZXNvbHZlIGN1c3RvbSBjb21wb25lbnQgZnJvbSBzcGVjaWZpZWQgcGF0aFxuICAgIC8vIFRoaXMgYXBwcm9hY2ggbWFpbnRhaW5zIGNvbnNpc3RlbmN5IGJldHdlZW4gc2VydmVyIGFuZCBjbGllbnQgcGFyYWRpZ21zXG4gICAgcGFnZVBhdGg6IHJvdXRlRmlsZXNSZXN1bHQucGFnZSxcbiAgICBwcm9wc1BhdGg6IHJvdXRlRmlsZXNSZXN1bHQucHJvcHMsXG4gICAgcm9vdFBhdGg6IHJvdXRlRmlsZXNSZXN1bHQucm9vdCxcbiAgICBodG1sUGF0aDogcm91dGVGaWxlc1Jlc3VsdC5odG1sLFxuXG4gICAgLy8gRXhwb3J0IG5hbWVzXG4gICAgcGFnZUV4cG9ydE5hbWU6IHVzZXJPcHRpb25zLnBhZ2VFeHBvcnROYW1lLFxuICAgIHByb3BzRXhwb3J0TmFtZTogdXNlck9wdGlvbnMucHJvcHNFeHBvcnROYW1lLFxuICAgIHJvb3RFeHBvcnROYW1lOiB1c2VyT3B0aW9ucy5yb290RXhwb3J0TmFtZSxcbiAgICBodG1sRXhwb3J0TmFtZTogdXNlck9wdGlvbnMuaHRtbEV4cG9ydE5hbWUsXG5cbiAgICAvLyBSb3V0ZSBhbmQgbG9hZGVyXG4gICAgcm91dGUsXG4gICAgbG9hZGVyOiBkZWZhdWx0cy5sb2FkZXIgfHwgKCgpID0+IFByb21pc2UucmVzb2x2ZSh7fSkpLFxuXG4gICAgLy8gQ29uZmlndXJhdGlvblxuICAgIHBhbmljVGhyZXNob2xkOiB1c2VyT3B0aW9ucy5wYW5pY1RocmVzaG9sZCxcbiAgICB2ZXJib3NlOiB1c2VyT3B0aW9ucy52ZXJib3NlLFxuICAgIG1vZHVsZUJhc2VVUkw6IHVzZXJPcHRpb25zLm1vZHVsZUJhc2VVUkwsXG4gICAgYnVpbGQ6IHVzZXJPcHRpb25zLmJ1aWxkLFxuICAgIGRldjoge1xuICAgICAgdXNlSHRtbFdvcmtlcjogdXNlck9wdGlvbnMuZGV2LnVzZUh0bWxXb3JrZXIsXG4gICAgICB1c2VSc2NXb3JrZXI6IHVzZXJPcHRpb25zLmRldi51c2VSc2NXb3JrZXIsXG4gICAgfSxcbiAgICBsb2dnZXIsXG5cbiAgICAvLyBSZXF1aXJlZCBwcm9wZXJ0aWVzXG4gICAgbm9ybWFsaXplcjogdXNlck9wdGlvbnMubm9ybWFsaXplcixcbiAgICBvbkV2ZW50OiB1c2VyT3B0aW9ucy5vbkV2ZW50LFxuICAgIG9uTWV0cmljczogdXNlck9wdGlvbnMub25NZXRyaWNzLFxuICAgIGF1dG9EaXNjb3ZlcjogdXNlck9wdGlvbnMuYXV0b0Rpc2NvdmVyLFxuICAgIGNzczogdXNlck9wdGlvbnMuY3NzLFxuICAgIHByb2plY3RSb290OiB1c2VyT3B0aW9ucy5wcm9qZWN0Um9vdCxcbiAgICBtb2R1bGVCYXNlOiB1c2VyT3B0aW9ucy5tb2R1bGVCYXNlLFxuICAgIG1vZHVsZUJhc2VQYXRoOiB1c2VyT3B0aW9ucy5tb2R1bGVCYXNlUGF0aCxcbiAgICBtb2R1bGVSb290UGF0aDogdXNlck9wdGlvbnMubW9kdWxlUm9vdFBhdGgsXG4gICAgbW9kdWxlSUQ6IHVzZXJPcHRpb25zLm1vZHVsZUlELFxuICAgIHVybCxcbiAgICBtYW5pZmVzdDogZGVmYXVsdHMubWFuaWZlc3QsXG4gICAgY3NzRmlsZXM6IGRlZmF1bHRzLmNzc0ZpbGVzLFxuICAgIGdsb2JhbENzczogZGVmYXVsdHMuZ2xvYmFsQ3NzLFxuXG4gICAgLy8gVGltZW91dHMgYW5kIHBhdGhzXG4gICAgcnNjVGltZW91dDogdXNlck9wdGlvbnMucnNjVGltZW91dCxcbiAgICBodG1sVGltZW91dDogdXNlck9wdGlvbnMuaHRtbFRpbWVvdXQsXG4gICAgZmlsZVdyaXRlVGltZW91dDogdXNlck9wdGlvbnMuZmlsZVdyaXRlVGltZW91dCxcbiAgICB3b3JrZXJTaHV0ZG93blRpbWVvdXQ6IHVzZXJPcHRpb25zLndvcmtlclNodXRkb3duVGltZW91dCxcbiAgICByc2NXb3JrZXJQYXRoOiB1c2VyT3B0aW9ucy5yc2NXb3JrZXJQYXRoLFxuICAgIGh0bWxXb3JrZXJQYXRoOiB1c2VyT3B0aW9ucy5odG1sV29ya2VyUGF0aCxcbiAgICBwdWJsaWNPcmlnaW46IHVzZXJPcHRpb25zLnB1YmxpY09yaWdpbixcblxuICAgIC8vIFN0cmVhbSBvcHRpb25zXG4gICAgc2VydmVyUGlwZWFibGVTdHJlYW1PcHRpb25zOiB1c2VyT3B0aW9ucy5zZXJ2ZXJQaXBlYWJsZVN0cmVhbU9wdGlvbnMsXG4gICAgY2xpZW50UGlwZWFibGVTdHJlYW1PcHRpb25zOiB1c2VyT3B0aW9ucy5jbGllbnRQaXBlYWJsZVN0cmVhbU9wdGlvbnMsXG5cbiAgICAvLyBDbGllbnQtc3BlY2lmaWNcbiAgICBpZCxcbiAgICAvLyBDbGllbnQgbmVlZHMgY29tcG9uZW50IHBsYWNlaG9sZGVycyBzaW5jZSBpdCBjYW4ndCBsb2FkIHNlcnZlciBtb2R1bGVzIGRpcmVjdGx5XG4gICAgSHRtbENvbXBvbmVudDogdW5kZWZpbmVkLFxuICAgIFBhZ2VDb21wb25lbnQ6IHVuZGVmaW5lZCxcbiAgICBSb290Q29tcG9uZW50OiB1bmRlZmluZWQsXG4gICAgLy8gV29ya2VycyBmb3IgY2xpZW50IGVudmlyb25tZW50IC0gcHJvdmlkZSBib3RoIGZvciBzcGVjaWZpYyB1c2UgY2FzZXNcbiAgICB3b3JrZXI6IGNvbmRpdGlvbiA9PT0gXCJyZWFjdC1zZXJ2ZXJcIiA/IHJzY1dvcmtlciA6IGh0bWxXb3JrZXIsIC8vIEJhY2t3YXJkIGNvbXBhdGliaWxpdHk6IHByZWZlciBIVE1MIHdvcmtlciBpZiBhdmFpbGFibGVcbiAgICByc2NXb3JrZXIsXG4gICAgaHRtbFdvcmtlcixcbiAgICAvLyBDaGlsZHJlbiBwcm92aWRlZCBkaXJlY3RseSB2aWEgb3B0aW9uc1xuICAgIGNoaWxkcmVuLFxuICB9O1xuXG4gIC8vIENhY2hlIGFuZCByZXR1cm5cbiAgc3Rhc2hIYW5kbGVyT3B0aW9ucyhpZCwgaGFuZGxlck9wdGlvbnMpO1xuICByZXR1cm4gaGFuZGxlck9wdGlvbnM7XG59XG5cblxuZXhwb3J0IHR5cGUge1xuICBDcmVhdGVIYW5kbGVyT3B0aW9uc1BhcmFtcyxcbiAgQ3JlYXRlSGFuZGxlck9wdGlvbnNTZXJ2ZXJGbixcbiAgQ3JlYXRlSGFuZGxlck9wdGlvbnNDbGllbnRGbixcbn0gZnJvbSBcIi4vY3JlYXRlSGFuZGxlck9wdGlvbnMudHlwZXMuanNcIjtcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7O0FBb0RBLFNBQVMsb0JBQXlDLEdBQUE7QUFDaEQsRUFBTyxPQUFBO0FBQUEsSUFDTCxnQkFBZ0IsY0FBZSxDQUFBLGdCQUFBO0FBQUEsSUFDL0IsaUJBQWlCLGNBQWUsQ0FBQSxpQkFBQTtBQUFBLElBQ2hDLGdCQUFnQixjQUFlLENBQUEsZ0JBQUE7QUFBQSxJQUMvQixnQkFBZ0IsY0FBZSxDQUFBLGdCQUFBO0FBQUEsSUFDL0IsUUFBQSxzQkFBYyxHQUFJLEVBQUE7QUFBQSxJQUNsQixTQUFBLHNCQUFlLEdBQUksRUFBQTtBQUFBLElBQ25CLFVBQVUsRUFBQztBQUFBLElBQ1gsS0FBSyxjQUFlLENBQUE7QUFBQSxHQUN0QjtBQUNGO0FBRUEsZUFBZSwwQkFBQSxDQUNiLE9BQ0EsRUFBQSxjQUFBLEVBQ0EsTUFDOEIsRUFBQTtBQUM5QixFQUFBLElBQUksUUFBUSxtQkFBcUIsRUFBQTtBQUMvQixJQUFBLE9BQU8sT0FBUSxDQUFBLG1CQUFBO0FBQUE7QUFHakIsRUFBTSxNQUFBLE1BQUEsR0FBUyxNQUFNLG1CQUFvQixDQUFBO0FBQUEsSUFDdkMsTUFBQSxFQUFRLE9BQVEsQ0FBQSxNQUFBLElBQVUsRUFBQztBQUFBLElBQzNCLFdBQVcsT0FBUSxDQUFBLFNBQUEsSUFBYSxFQUFFLElBQU0sRUFBQSxZQUFBLEVBQWMsU0FBUyxPQUFRLEVBQUE7QUFBQSxJQUN2RSxXQUFhLEVBQUEsY0FBQTtBQUFBLElBQ2I7QUFBQSxHQUNELENBQUE7QUFFRCxFQUFJLElBQUEs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