UNPKG

vite-plugin-react-server

Version:
142 lines (139 loc) 22.5 kB
/** * vite-plugin-react-server * Copyright (c) Nico Brinkkemper * MIT License */ import { isMainThread } from 'node:worker_threads'; const pageMetricsMap = /* @__PURE__ */ new Map(); function formatFileSize(bytes) { if (bytes < 1024) { return `${bytes} B`; } else if (bytes < 1024 * 1024) { return `${(bytes / 1024).toFixed(1)} kB`; } else { return `${(bytes / 1024 / 1024).toFixed(1)} MB`; } } function formatTime(ms) { if (ms < 1) { return `${Math.round(ms * 1e3)}μs`; } else if (ms < 1e3) { return `${Math.round(ms)}ms`; } else { return `${(ms / 1e3).toFixed(2)}s`; } } let startedLogging = false; const loggedWorkerStartups = /* @__PURE__ */ new Set(); function metricWatcher({ maxTime = 200, maxBackpressure = 1, warnOnly = false, warn = console.warn, info = console.info } = {}) { if (!isMainThread) { return () => { }; } return (metrics) => { if (!startedLogging) { startedLogging = true; info("_______ vite-plugin-react-server ______"); } const route = metrics.route; let pageMetrics = pageMetricsMap.get(route); if (!pageMetrics) { pageMetrics = { route, metrics: {}, workerStartupMetrics: [], moduleResolutionMetrics: [], startTime: performance.now() }; pageMetricsMap.set(route, pageMetrics); } if (metrics.type === "rsc-full") { pageMetrics.metrics.rscFull = metrics; } else if (metrics.type === "rsc-headless") { pageMetrics.metrics.rscHeadless = metrics; } else if (metrics.type === "html") { pageMetrics.metrics.html = metrics; } else if (metrics.type === "worker-startup") { pageMetrics.workerStartupMetrics.push(metrics); if (!warnOnly) { const workerStartupMetric = metrics; const workerKey = `${workerStartupMetric.workerType}-${workerStartupMetric.route}`; if (!loggedWorkerStartups.has(workerKey)) { loggedWorkerStartups.add(workerKey); const startupTime = formatTime(workerStartupMetric.startupTime); const workerType = workerStartupMetric.workerType; info( `\x1B[35m${workerType.toUpperCase()}-worker started in \x1B[0m ${startupTime} (initial route: ${route})` ); } } return; } else if (metrics.type === "module-resolution") { pageMetrics.moduleResolutionMetrics.push( metrics ); if (metrics.type === "module-resolution" && "resolutionTime" in metrics && metrics.resolutionTime > maxTime) { const moduleResolutionMetric = metrics; const resolutionTime = formatTime( moduleResolutionMetric.resolutionTime ); warn( `${moduleResolutionMetric.workerType} worker took ${resolutionTime} for route ${route}` ); } return; } const renderMetrics = metrics; if (renderMetrics.streamMetrics.backpressureCount > maxBackpressure) { warn( `Backpressure detected on ${route} (${renderMetrics.type}): ${renderMetrics.streamMetrics.backpressureCount} occurrences` ); } const totalWorkerStartupTime = pageMetrics.workerStartupMetrics.reduce( (total, startup) => total + startup.startupTime, 0 ); const totalModuleResolutionTime = pageMetrics.moduleResolutionMetrics.reduce( (total, resolution) => total + resolution.resolutionTime, 0 ); const actualProcessingTime = renderMetrics.processingTime - totalWorkerStartupTime - totalModuleResolutionTime; if (actualProcessingTime > maxTime) { const startupTimeMsg = totalWorkerStartupTime > 0 ? ` (worker startup: ${formatTime(totalWorkerStartupTime)})` : ""; const resolutionTimeMsg = totalModuleResolutionTime > 0 ? ` (module resolution: ${formatTime(totalModuleResolutionTime)})` : ""; warn( `It took ${actualProcessingTime}ms to render ${route} (${renderMetrics.type})${startupTimeMsg}${resolutionTimeMsg}` ); } const hasAllMetrics = pageMetrics.metrics.rscFull && pageMetrics.metrics.rscHeadless && pageMetrics.metrics.html; if (hasAllMetrics && !warnOnly) { const htmlMetrics = pageMetrics.metrics.html; const rscMetrics = pageMetrics.metrics.rscHeadless; const formatFileOutput = (metrics2) => { if (!metrics2.fileSize) { return null; } const fileSize = formatFileSize(metrics2.fileSize); const processingTime = formatTime(metrics2.processingTime); const isRootRoute = metrics2.route === "/"; const baseDirDisplay = `\x1B[2m${metrics2.baseDir}\x1B[0m`; const routeDisplay = isRootRoute ? "" : `\x1B[33m/${metrics2.routePath}\x1B[0m`; const coloredPath = `${baseDirDisplay}${routeDisplay}\x1B[36m/${metrics2.fileName}\x1B[0m`; return `${coloredPath} \x1B[1m${fileSize}\x1B[0m \x1B[90m${processingTime}\x1B[0m`; }; const htmlOutput = formatFileOutput(htmlMetrics); const rscOutput = formatFileOutput(rscMetrics); if (typeof htmlOutput === "string") info(htmlOutput); if (typeof rscOutput === "string") info(rscOutput); pageMetricsMap.delete(route); } }; } export { metricWatcher }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljV2F0Y2hlci5qcyIsInNvdXJjZXMiOlsiLi4vLi4vLi4vcGx1Z2luL21ldHJpY3MvbWV0cmljV2F0Y2hlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7XG4gIFJlbmRlck1ldHJpY3MsXG4gIFdvcmtlclN0YXJ0dXBNZXRyaWNzLFxuICBNb2R1bGVSZXNvbHV0aW9uTWV0cmljcyxcbn0gZnJvbSBcIi4vdHlwZXMuanNcIjtcbmltcG9ydCB7IGlzTWFpblRocmVhZCB9IGZyb20gXCJub2RlOndvcmtlcl90aHJlYWRzXCI7XG5cbmludGVyZmFjZSBQYWdlTWV0cmljcyB7XG4gIHJvdXRlOiBzdHJpbmc7IC8vIHJvdXRlIGFzIGRlZmluZWQgaW4gYnVpbGQucGFnZXNcbiAgbWV0cmljczoge1xuICAgIHJzY0Z1bGw/OiBSZW5kZXJNZXRyaWNzOyAvLyB0aGUgc2VydmVyLXNpZGUgcmVuZGVyVG9QaXBlYWJsZVN0cmVhbSBtZXRyaWNzLCBmb3IgaHRtbCtyb290K3BhZ2VcbiAgICByc2NIZWFkbGVzcz86IFJlbmRlck1ldHJpY3M7IC8vIHRoZSBzZXJ2ZXItc2lkZSByZW5kZXJUb1BpcGVhYmxlU3RyZWFtIG1ldHJpY3MsIG9ubHkgdGhlIHJvb3QrcGFnZVxuICAgIGh0bWw/OiBSZW5kZXJNZXRyaWNzOyAvLyB0aGUgY2xpZW50LXNpZGUgcmVuZGVyVG9QaXBlYWJsZVN0cmVhbSBtZXRyaWNzLCBmb3IgcnNjRnVsbCAtPiBodG1sXG4gIH07XG4gIHdvcmtlclN0YXJ0dXBNZXRyaWNzOiBXb3JrZXJTdGFydHVwTWV0cmljc1tdOyAvLyBUcmFjayB3b3JrZXIgc3RhcnR1cCB0aW1lcyBmb3IgdGhpcyBwYWdlXG4gIG1vZHVsZVJlc29sdXRpb25NZXRyaWNzOiBNb2R1bGVSZXNvbHV0aW9uTWV0cmljc1tdOyAvLyBUcmFjayBtb2R1bGUgcmVzb2x1dGlvbiB0aW1lcyBmb3IgdGhpcyBwYWdlXG4gIHN0YXJ0VGltZTogbnVtYmVyO1xufVxuXG5jb25zdCBwYWdlTWV0cmljc01hcCA9IG5ldyBNYXA8c3RyaW5nLCBQYWdlTWV0cmljcz4oKTtcblxuZnVuY3Rpb24gZm9ybWF0RmlsZVNpemUoYnl0ZXM6IG51bWJlcik6IHN0cmluZyB7XG4gIGlmIChieXRlcyA8IDEwMjQpIHtcbiAgICByZXR1cm4gYCR7Ynl0ZXN9IEJgO1xuICB9IGVsc2UgaWYgKGJ5dGVzIDwgMTAyNCAqIDEwMjQpIHtcbiAgICByZXR1cm4gYCR7KGJ5dGVzIC8gMTAyNCkudG9GaXhlZCgxKX0ga0JgO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBgJHsoYnl0ZXMgLyAxMDI0IC8gMTAyNCkudG9GaXhlZCgxKX0gTUJgO1xuICB9XG59XG5cbmZ1bmN0aW9uIGZvcm1hdFRpbWUobXM6IG51bWJlcik6IHN0cmluZyB7XG4gIGlmIChtcyA8IDEpIHtcbiAgICByZXR1cm4gYCR7TWF0aC5yb3VuZChtcyAqIDEwMDApfc68c2A7XG4gIH0gZWxzZSBpZiAobXMgPCAxMDAwKSB7XG4gICAgcmV0dXJuIGAke01hdGgucm91bmQobXMpfW1zYDtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gYCR7KG1zIC8gMTAwMCkudG9GaXhlZCgyKX1zYDtcbiAgfVxufVxuXG5sZXQgc3RhcnRlZExvZ2dpbmcgPSBmYWxzZTtcbi8vIFRyYWNrIGxvZ2dlZCB3b3JrZXIgc3RhcnR1cHMgdG8gcHJldmVudCBkdXBsaWNhdGVzXG5jb25zdCBsb2dnZWRXb3JrZXJTdGFydHVwcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG5leHBvcnQgZnVuY3Rpb24gbWV0cmljV2F0Y2hlcih7XG4gIG1heFRpbWUgPSAyMDAsXG4gIG1heEJhY2twcmVzc3VyZSA9IDEsXG4gIHdhcm5Pbmx5ID0gZmFsc2UsXG4gIHdhcm4gPSBjb25zb2xlLndhcm4sXG4gIGluZm8gPSBjb25zb2xlLmluZm8sXG59OiB7XG4gIG1heFRpbWU/OiBudW1iZXI7XG4gIG1heEJhY2twcmVzc3VyZT86IG51bWJlcjtcbiAgd2Fybk9ubHk/OiBib29sZWFuO1xuICB3YXJuPzogKC4uLmFyZ3M6IHVua25vd25bXSkgPT4gdm9pZDtcbiAgaW5mbz86ICguLi5hcmdzOiB1bmtub3duW10pID0+IHZvaWQ7XG59ID0ge30pIHtcbiAgaWYgKCFpc01haW5UaHJlYWQpIHtcbiAgICByZXR1cm4gKCkgPT4ge307XG4gIH1cbiAgcmV0dXJuIChcbiAgICBtZXRyaWNzOiBSZW5kZXJNZXRyaWNzIHwgV29ya2VyU3RhcnR1cE1ldHJpY3MgfCBNb2R1bGVSZXNvbHV0aW9uTWV0cmljc1xuICApID0+IHtcbiAgICBpZiAoIXN0YXJ0ZWRMb2dnaW5nKSB7XG4gICAgICBzdGFydGVkTG9nZ2luZyA9IHRydWU7XG4gICAgICBpbmZvKFwiX19fX19fXyB2aXRlLXBsdWdpbi1yZWFjdC1zZXJ2ZXIgX19fX19fXCIpO1xuICAgIH1cbiAgICBjb25zdCByb3V0ZSA9IG1ldHJpY3Mucm91dGU7XG5cbiAgICAvLyBHZXQgb3IgY3JlYXRlIHBhZ2UgbWV0cmljc1xuICAgIGxldCBwYWdlTWV0cmljcyA9IHBhZ2VNZXRyaWNzTWFwLmdldChyb3V0ZSk7XG4gICAgaWYgKCFwYWdlTWV0cmljcykge1xuICAgICAgcGFnZU1ldHJpY3MgPSB7XG4gICAgICAgIHJvdXRlLFxuICAgICAgICBtZXRyaWNzOiB7fSxcbiAgICAgICAgd29ya2VyU3RhcnR1cE1ldHJpY3M6IFtdLFxuICAgICAgICBtb2R1bGVSZXNvbHV0aW9uTWV0cmljczogW10sXG4gICAgICAgIHN0YXJ0VGltZTogcGVyZm9ybWFuY2Uubm93KCksXG4gICAgICB9O1xuICAgICAgcGFnZU1ldHJpY3NNYXAuc2V0KHJvdXRlLCBwYWdlTWV0cmljcyk7XG4gICAgfVxuXG4gICAgLy8gU3RvcmUgdGhlIG1ldHJpYyBieSB0eXBlXG4gICAgaWYgKG1ldHJpY3MudHlwZSA9PT0gXCJyc2MtZnVsbFwiKSB7XG4gICAgICBwYWdlTWV0cmljcy5tZXRyaWNzLnJzY0Z1bGwgPSBtZXRyaWNzIGFzIFJlbmRlck1ldHJpY3M7XG4gICAgfSBlbHNlIGlmIChtZXRyaWNzLnR5cGUgPT09IFwicnNjLWhlYWRsZXNzXCIpIHtcbiAgICAgIHBhZ2VNZXRyaWNzLm1ldHJpY3MucnNjSGVhZGxlc3MgPSBtZXRyaWNzIGFzIFJlbmRlck1ldHJpY3M7XG4gICAgfSBlbHNlIGlmIChtZXRyaWNzLnR5cGUgPT09IFwiaHRtbFwiKSB7XG4gICAgICBwYWdlTWV0cmljcy5tZXRyaWNzLmh0bWwgPSBtZXRyaWNzIGFzIFJlbmRlck1ldHJpY3M7XG4gICAgfSBlbHNlIGlmIChtZXRyaWNzLnR5cGUgPT09IFwid29ya2VyLXN0YXJ0dXBcIikge1xuICAgICAgLy8gU3RvcmUgd29ya2VyIHN0YXJ0dXAgbWV0cmljcyBzZXBhcmF0ZWx5XG4gICAgICBwYWdlTWV0cmljcy53b3JrZXJTdGFydHVwTWV0cmljcy5wdXNoKG1ldHJpY3MgYXMgV29ya2VyU3RhcnR1cE1ldHJpY3MpO1xuXG4gICAgICAvLyBEaXNwbGF5IHdvcmtlciBzdGFydHVwIG1ldHJpYyBhcyBzdGFuZGFsb25lIGVudHJ5IChkZWR1cGxpY2F0ZWQpXG4gICAgICBpZiAoIXdhcm5Pbmx5KSB7XG4gICAgICAgIGNvbnN0IHdvcmtlclN0YXJ0dXBNZXRyaWMgPSBtZXRyaWNzIGFzIFdvcmtlclN0YXJ0dXBNZXRyaWNzO1xuICAgICAgICBjb25zdCB3b3JrZXJLZXkgPSBgJHt3b3JrZXJTdGFydHVwTWV0cmljLndvcmtlclR5cGV9LSR7d29ya2VyU3RhcnR1cE1ldHJpYy5yb3V0ZX1gO1xuICAgICAgICBcbiAgICAgICAgLy8gT25seSBsb2cgaWYgd2UgaGF2ZW4ndCBzZWVuIHRoaXMgd29ya2VyIHR5cGUgZm9yIHRoaXMgcm91dGUgYmVmb3JlXG4gICAgICAgIGlmICghbG9nZ2VkV29ya2VyU3RhcnR1cHMuaGFzKHdvcmtlcktleSkpIHtcbiAgICAgICAgICBsb2dnZWRXb3JrZXJTdGFydHVwcy5hZGQod29ya2VyS2V5KTtcbiAgICAgICAgICBjb25zdCBzdGFydHVwVGltZSA9IGZvcm1hdFRpbWUod29ya2VyU3RhcnR1cE1ldHJpYy5zdGFydHVwVGltZSk7XG4gICAgICAgICAgY29uc3Qgd29ya2VyVHlwZSA9IHdvcmtlclN0YXJ0dXBNZXRyaWMud29ya2VyVHlwZTtcbiAgICAgICAgICBpbmZvKFxuICAgICAgICAgICAgYFxceDFiWzM1bSR7d29ya2VyVHlwZS50b1VwcGVyQ2FzZSgpfS13b3JrZXIgc3RhcnRlZCBpbiBcXHgxYlswbSAke3N0YXJ0dXBUaW1lfSAoaW5pdGlhbCByb3V0ZTogJHtyb3V0ZX0pYFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybjsgLy8gRG9uJ3QgcHJvY2VzcyB3b3JrZXIgc3RhcnR1cCBtZXRyaWNzIGZvciByZW5kZXJpbmcgY2hlY2tzXG4gICAgfSBlbHNlIGlmIChtZXRyaWNzLnR5cGUgPT09IFwibW9kdWxlLXJlc29sdXRpb25cIikge1xuICAgICAgLy8gU3RvcmUgbW9kdWxlIHJlc29sdXRpb24gbWV0cmljcyBzZXBhcmF0ZWx5XG4gICAgICBwYWdlTWV0cmljcy5tb2R1bGVSZXNvbHV0aW9uTWV0cmljcy5wdXNoKFxuICAgICAgICBtZXRyaWNzIGFzIE1vZHVsZVJlc29sdXRpb25NZXRyaWNzXG4gICAgICApO1xuXG4gICAgICAvLyBEaXNwbGF5IG1vZHVsZSByZXNvbHV0aW9uIG1ldHJpYyBhcyBzdGFuZGFsb25lIGVudHJ5XG4gICAgICBpZiAobWV0cmljcy50eXBlID09PSBcIm1vZHVsZS1yZXNvbHV0aW9uXCIgJiYgXCJyZXNvbHV0aW9uVGltZVwiIGluIG1ldHJpY3MgJiYgbWV0cmljcy5yZXNvbHV0aW9uVGltZSA+IG1heFRpbWUpIHtcbiAgICAgICAgY29uc3QgbW9kdWxlUmVzb2x1dGlvbk1ldHJpYyA9IG1ldHJpY3MgYXMgTW9kdWxlUmVzb2x1dGlvbk1ldHJpY3M7XG4gICAgICAgIGNvbnN0IHJlc29sdXRpb25UaW1lID0gZm9ybWF0VGltZShcbiAgICAgICAgICBtb2R1bGVSZXNvbHV0aW9uTWV0cmljLnJlc29sdXRpb25UaW1lXG4gICAgICAgICk7XG4gICAgICAgIHdhcm4oXG4gICAgICAgICAgYCR7bW9kdWxlUmVzb2x1dGlvbk1ldHJpYy53b3JrZXJUeXBlfSB3b3JrZXIgdG9vayAke3Jlc29sdXRpb25UaW1lfSBmb3Igcm91dGUgJHtyb3V0ZX1gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICByZXR1cm47IC8vIERvbid0IHByb2Nlc3MgbW9kdWxlIHJlc29sdXRpb24gbWV0cmljcyBmb3IgcmVuZGVyaW5nIGNoZWNrc1xuICAgIH1cblxuICAgIC8vIE9ubHkgcHJvY2VzcyBSZW5kZXJNZXRyaWNzIGZyb20gaGVyZSBvblxuICAgIGNvbnN0IHJlbmRlck1ldHJpY3MgPSBtZXRyaWNzIGFzIFJlbmRlck1ldHJpY3M7XG5cbiAgICAvLyBDaGVjayBmb3IgYmFja3ByZXNzdXJlIGZpcnN0IChtb3JlIGNyaXRpY2FsKVxuICAgIGlmIChyZW5kZXJNZXRyaWNzLnN0cmVhbU1ldHJpY3MuYmFja3ByZXNzdXJlQ291bnQgPiBtYXhCYWNrcHJlc3N1cmUpIHtcbiAgICAgIHdhcm4oXG4gICAgICAgIGBCYWNrcHJlc3N1cmUgZGV0ZWN0ZWQgb24gJHtyb3V0ZX0gKCR7cmVuZGVyTWV0cmljcy50eXBlfSk6ICR7cmVuZGVyTWV0cmljcy5zdHJlYW1NZXRyaWNzLmJhY2twcmVzc3VyZUNvdW50fSBvY2N1cnJlbmNlc2BcbiAgICAgICk7XG4gICAgfVxuICAgIC8vIENoZWNrIGZvciBzbG93IHByb2Nlc3NpbmdcbiAgICAvLyBDYWxjdWxhdGUgdG90YWwgd29ya2VyIHN0YXJ0dXAgdGltZSBmb3IgdGhpcyByb3V0ZVxuICAgIGNvbnN0IHRvdGFsV29ya2VyU3RhcnR1cFRpbWUgPSBwYWdlTWV0cmljcy53b3JrZXJTdGFydHVwTWV0cmljcy5yZWR1Y2UoXG4gICAgICAodG90YWwsIHN0YXJ0dXApID0+IHRvdGFsICsgc3RhcnR1cC5zdGFydHVwVGltZSxcbiAgICAgIDBcbiAgICApO1xuXG4gICAgLy8gQ2FsY3VsYXRlIHRvdGFsIG1vZHVsZSByZXNvbHV0aW9uIHRpbWUgZm9yIHRoaXMgcm91dGVcbiAgICBjb25zdCB0b3RhbE1vZHVsZVJlc29sdXRpb25UaW1lID1cbiAgICAgIHBhZ2VNZXRyaWNzLm1vZHVsZVJlc29sdXRpb25NZXRyaWNzLnJlZHVjZShcbiAgICAgICAgKHRvdGFsLCByZXNvbHV0aW9uKSA9PiB0b3RhbCArIHJlc29sdXRpb24ucmVzb2x1dGlvblRpbWUsXG4gICAgICAgIDBcbiAgICAgICk7XG5cbiAgICAvLyBTdWJ0cmFjdCB3b3JrZXIgc3RhcnR1cCBhbmQgbW9kdWxlIHJlc29sdXRpb24gdGltZSBmcm9tIHByb2Nlc3NpbmcgdGltZSBmb3IgdGhlIGZpcnN0IHBhZ2VcbiAgICBjb25zdCBhY3R1YWxQcm9jZXNzaW5nVGltZSA9XG4gICAgICByZW5kZXJNZXRyaWNzLnByb2Nlc3NpbmdUaW1lIC1cbiAgICAgIHRvdGFsV29ya2VyU3RhcnR1cFRpbWUgLVxuICAgICAgdG90YWxNb2R1bGVSZXNvbHV0aW9uVGltZTtcblxuICAgIGlmIChhY3R1YWxQcm9jZXNzaW5nVGltZSA+IG1heFRpbWUpIHtcbiAgICAgIGNvbnN0IHN0YXJ0dXBUaW1lTXNnID1cbiAgICAgICAgdG90YWxXb3JrZXJTdGFydHVwVGltZSA+IDBcbiAgICAgICAgICA/IGAgKHdvcmtlciBzdGFydHVwOiAke2Zvcm1hdFRpbWUodG90YWxXb3JrZXJTdGFydHVwVGltZSl9KWBcbiAgICAgICAgICA6IFwiXCI7XG4gICAgICBjb25zdCByZXNvbHV0aW9uVGltZU1zZyA9XG4gICAgICAgIHRvdGFsTW9kdWxlUmVzb2x1dGlvblRpbWUgPiAwXG4gICAgICAgICAgPyBgIChtb2R1bGUgcmVzb2x1dGlvbjogJHtmb3JtYXRUaW1lKHRvdGFsTW9kdWxlUmVzb2x1dGlvblRpbWUpfSlgXG4gICAgICAgICAgOiBcIlwiO1xuXG4gICAgICB3YXJuKFxuICAgICAgICBgSXQgdG9vayAke2FjdHVhbFByb2Nlc3NpbmdUaW1lfW1zIHRvIHJlbmRlciAke3JvdXRlfSAoJHtyZW5kZXJNZXRyaWNzLnR5cGV9KSR7c3RhcnR1cFRpbWVNc2d9JHtyZXNvbHV0aW9uVGltZU1zZ31gXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIENoZWNrIGlmIHdlIGhhdmUgYWxsIG1ldHJpY3MgZm9yIHRoaXMgcGFnZVxuICAgIGNvbnN0IGhhc0FsbE1ldHJpY3MgPVxuICAgICAgcGFnZU1ldHJpY3MubWV0cmljcy5yc2NGdWxsICYmXG4gICAgICBwYWdlTWV0cmljcy5tZXRyaWNzLnJzY0hlYWRsZXNzICYmXG4gICAgICBwYWdlTWV0cmljcy5tZXRyaWNzLmh0bWw7XG4gICAgaWYgKGhhc0FsbE1ldHJpY3MgJiYgIXdhcm5Pbmx5KSB7XG4gICAgICAvLyBHZXQgdGhlIGFjdHVhbCBmaWxlIG5hbWUgYW5kIG91dHB1dCBwYXRoIGZyb20gdGhlIG1ldHJpY3NcbiAgICAgIGNvbnN0IGh0bWxNZXRyaWNzID0gcGFnZU1ldHJpY3MubWV0cmljcy5odG1sITtcbiAgICAgIGNvbnN0IHJzY01ldHJpY3MgPSBwYWdlTWV0cmljcy5tZXRyaWNzLnJzY0hlYWRsZXNzITtcblxuICAgICAgLy8gSGVscGVyIGZ1bmN0aW9uIHRvIGZvcm1hdCBmaWxlIG91dHB1dFxuICAgICAgY29uc3QgZm9ybWF0RmlsZU91dHB1dCA9IChtZXRyaWNzOiBSZW5kZXJNZXRyaWNzKSA9PiB7XG4gICAgICAgIC8vIFNraXAgaWYgZmlsZS1yZWxhdGVkIHByb3BlcnRpZXMgYXJlIG5vdCBhdmFpbGFibGVcbiAgICAgICAgaWYgKCFtZXRyaWNzLmZpbGVTaXplKSB7XG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBmaWxlU2l6ZSA9IGZvcm1hdEZpbGVTaXplKG1ldHJpY3MuZmlsZVNpemUpO1xuICAgICAgICBjb25zdCBwcm9jZXNzaW5nVGltZSA9IGZvcm1hdFRpbWUobWV0cmljcy5wcm9jZXNzaW5nVGltZSk7XG5cbiAgICAgICAgLy8gVXNlIHN0cnVjdHVyZWQgZGF0YSBmb3IgY29sb3Jpbmc6IGJhc2VEaXIgKGdyYXkpLCByb3V0ZVBhdGggKHllbGxvdyksIGZpbGVuYW1lIChjeWFuKVxuICAgICAgICBjb25zdCBpc1Jvb3RSb3V0ZSA9IG1ldHJpY3Mucm91dGUgPT09IFwiL1wiO1xuICAgICAgICBjb25zdCBiYXNlRGlyRGlzcGxheSA9IGBcXHgxYlsybSR7bWV0cmljcy5iYXNlRGlyfVxceDFiWzBtYDtcbiAgICAgICAgY29uc3Qgcm91dGVEaXNwbGF5ID0gaXNSb290Um91dGVcbiAgICAgICAgICA/IFwiXCJcbiAgICAgICAgICA6IGBcXHgxYlszM20vJHttZXRyaWNzLnJvdXRlUGF0aH1cXHgxYlswbWA7XG4gICAgICAgIGNvbnN0IGNvbG9yZWRQYXRoID0gYCR7YmFzZURpckRpc3BsYXl9JHtyb3V0ZURpc3BsYXl9XFx4MWJbMzZtLyR7bWV0cmljcy5maWxlTmFtZX1cXHgxYlswbWA7XG5cbiAgICAgICAgcmV0dXJuIGAke2NvbG9yZWRQYXRofSBcXHgxYlsxbSR7ZmlsZVNpemV9XFx4MWJbMG0gXFx4MWJbOTBtJHtwcm9jZXNzaW5nVGltZX1cXHgxYlswbWA7XG4gICAgICB9O1xuXG4gICAgICAvLyBTaG93IEhUTUwgYW5kIFJTQyBmaWxlc1xuICAgICAgY29uc3QgaHRtbE91dHB1dCA9IGZvcm1hdEZpbGVPdXRwdXQoaHRtbE1ldHJpY3MpO1xuICAgICAgY29uc3QgcnNjT3V0cHV0ID0gZm9ybWF0RmlsZU91dHB1dChyc2NNZXRyaWNzKTtcblxuICAgICAgaWYgKHR5cGVvZiBodG1sT3V0cHV0ID09PSBcInN0cmluZ1wiKSBpbmZvKGh0bWxPdXRwdXQpO1xuICAgICAgaWYgKHR5cGVvZiByc2NPdXRwdXQgPT09IFwic3RyaW5nXCIpIGluZm8ocnNjT3V0cHV0KTtcblxuICAgICAgLy8gQ2xlYW4gdXBcbiAgICAgIHBhZ2VNZXRyaWNzTWFwLmRlbGV0ZShyb3V0ZSk7XG4gICAgfVxuICB9O1xufVxuIl0sIm5hbWVzIjpbIm1ldHJpY3MiXSwi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