vite-plugin-react-server
Version:
Vite plugin for React Server Components (RSC)
261 lines (258 loc) • 30.4 kB
JavaScript
/**
* vite-plugin-react-server
* Copyright (c) Nico Brinkkemper
* MIT License
*/
import { join } from 'node:path';
import { mkdirSync, createWriteStream } from 'node:fs';
import { PassThrough, Transform } from 'node:stream';
import { getNodeEnv } from '../config/getNodeEnv.js';
import { handleError } from '../error/handleError.js';
class ContentCollectorStream extends Transform {
chunks = [];
_isFinished = false;
_onAllChunksCollected;
constructor(options = {}) {
super({
...options,
objectMode: false
});
}
_transform(chunk, _encoding, callback) {
if (this._isFinished) {
callback();
return;
}
const buffer = Buffer.from(chunk);
this.chunks.push(buffer);
this.push(chunk);
callback();
}
_flush(callback) {
this._isFinished = true;
if (this._onAllChunksCollected) {
this._onAllChunksCollected();
}
callback();
}
getAllChunks() {
return this.chunks;
}
getContent() {
return Buffer.concat(this.chunks).toString("utf8");
}
hasContent() {
return this.chunks.length > 0;
}
onAllChunksCollected(callback) {
if (this._isFinished) {
callback();
} else {
this._onAllChunksCollected = callback;
}
}
}
const fileWriter = function _fileWriter(stream, fileType, options, signal) {
if (!stream) {
throw new Error(`Missing stream for route: ${options.route}`);
}
const isStreamWrapper = stream.pipe && typeof stream.pipe === "function";
const routePath = options.route === "/" ? "" : options.route.replace(/^\//, "");
const baseDir = join(options.build.outDir, options.build.static);
const outputPath = join(
baseDir,
routePath,
fileType === "html" ? options.build.htmlOutputPath : options.build.rscOutputPath
);
try {
mkdirSync(join(baseDir, routePath), { recursive: true });
} catch (error) {
const panicError = handleError({
error,
logger: options.logger,
mode: getNodeEnv(),
panicThreshold: options.panicThreshold,
critical: false});
if (panicError != null) {
throw panicError;
}
}
if (options.verbose) {
options.logger?.info(
`[fileWriter] Starting file write for ${fileType} on route ${options.route}`
);
}
if (signal?.aborted) {
const abortReason = signal?.reason || new Error("File write aborted");
throw abortReason;
}
const contentCollector = new ContentCollectorStream({
highWaterMark: 64 * 1024
// 64KB buffer
});
const writeStream = createWriteStream(outputPath, {
highWaterMark: 64 * 1024
// 64KB buffer
});
let sourceStream;
if (isStreamWrapper) {
sourceStream = new PassThrough();
try {
stream.pipe(sourceStream);
} catch (error) {
throw new Error(`Failed to pipe stream wrapper: ${error}`);
}
} else {
sourceStream = stream;
}
if (options.onEvent) {
try {
options.onEvent({
type: "file.write",
data: {
path: outputPath,
route: options.route,
fileType,
stream: contentCollector,
onComplete: () => new Promise((resolveComplete) => {
resolveComplete();
})
}
});
} catch (error) {
if (options.onEvent) {
options.onEvent({
type: "route.error",
data: {
error,
route: options.route,
panicThreshold: options.panicThreshold
}
});
}
throw error;
}
}
return new Promise((resolve, reject) => {
const abortHandler = () => {
writeStream.destroy();
contentCollector.destroy();
sourceStream.destroy?.();
const abortReason = signal?.reason || new Error("File write aborted");
reject(abortReason);
};
if (signal) {
signal.addEventListener("abort", abortHandler);
}
sourceStream.pipe(contentCollector).pipe(writeStream);
const handleError2 = (error) => {
if (signal) {
signal.removeEventListener("abort", abortHandler);
}
if (options.verbose) {
options.logger?.error(
`[fileWriter] Error writing ${fileType} file for route ${options.route}: ${error.message}`
);
}
reject(error);
};
sourceStream.on("error", handleError2);
contentCollector.on("error", handleError2);
writeStream.on("error", handleError2);
writeStream.on("finish", () => {
if (signal) {
signal.removeEventListener("abort", abortHandler);
}
if (options.verbose) {
options.logger?.info(
`[fileWriter] Completed file write for ${fileType} on route ${options.route}`
);
}
contentCollector.onAllChunksCollected(() => {
if (options.onEvent) {
if (contentCollector.hasContent()) {
const content = contentCollector.getContent();
const chunks = contentCollector.getAllChunks();
if (options.verbose) {
options.logger?.info(
`[fileWriter:${fileType}] Emitting file.write.done with content length: ${content.length} bytes, chunks: ${chunks.length}`
);
if (content.length > 0) {
options.logger?.info(
`[fileWriter:${fileType}] Content preview: ${content.substring(0, 200)}...`
);
}
}
const fileName = fileType === "html" ? options.build.htmlOutputPath : options.build.rscOutputPath;
try {
options.onEvent({
type: "file.write.done",
data: {
route: options.route,
fileType,
content,
chunks: chunks.length,
path: outputPath,
fileName,
baseDir,
routePath
}
});
} catch (error) {
if (options.onEvent) {
options.onEvent({
type: "route.error",
data: {
error,
route: options.route,
panicThreshold: options.panicThreshold
}
});
}
reject(error);
return;
}
} else {
if (options.verbose) {
options.logger?.warn(
`[fileWriter] No content chunks collected for ${fileType} file: ${outputPath}. This may be normal for empty files.`
);
}
const fileName = fileType === "html" ? options.build.htmlOutputPath : options.build.rscOutputPath;
try {
options.onEvent({
type: "file.write.done",
data: {
route: options.route,
fileType,
content: "",
chunks: 0,
path: outputPath,
fileName,
baseDir,
routePath
}
});
} catch (error) {
if (options.onEvent) {
options.onEvent({
type: "route.error",
data: {
error,
route: options.route,
panicThreshold: options.panicThreshold
}
});
}
reject(error);
return;
}
}
}
resolve();
});
});
});
};
export { fileWriter };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZVdyaXRlci5qcyIsInNvdXJjZXMiOlsiLi4vLi4vLi4vcGx1Z2luL3JlYWN0LXN0YXRpYy9maWxlV3JpdGVyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogZmlsZVdyaXRlci50c1xuICpcbiAqIFBVUlBPU0U6IEhhbmRsZXMgZmlsZSB3cml0aW5nIG9wZXJhdGlvbnMgZm9yIFJlYWN0IFNlcnZlciBDb21wb25lbnRzIChSU0MpIHJlbmRlcmluZ1xuICpcbiAqIFRoaXMgbW9kdWxlOlxuICogMS4gV3JpdGVzIEhUTUwgYW5kIFJTQyBmaWxlcyB0byB0aGUgZmlsZXN5c3RlbSB1c2luZyBzdHJlYW1zXG4gKiAyLiBDcmVhdGVzIG5lY2Vzc2FyeSBkaXJlY3Rvcmllc1xuICogMy4gSGFuZGxlcyBmaWxlIHBhdGggY29uc3RydWN0aW9uXG4gKiA0LiBQcm92aWRlcyBhIGNsZWFuIGludGVyZmFjZSBmb3IgZmlsZSBvcGVyYXRpb25zXG4gKi9cbmltcG9ydCB7IGpvaW4gfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgeyBjcmVhdGVXcml0ZVN0cmVhbSwgbWtkaXJTeW5jIH0gZnJvbSBcIm5vZGU6ZnNcIjtcbmltcG9ydCB7IFRyYW5zZm9ybSwgUGFzc1Rocm91Z2ggfSBmcm9tIFwibm9kZTpzdHJlYW1cIjtcbmltcG9ydCB0eXBlIHsgRmlsZVdyaXRlckZuIH0gZnJvbSBcIi4vdHlwZXMuanNcIjtcbmltcG9ydCB7IGdldE5vZGVFbnYgfSBmcm9tIFwiLi4vY29uZmlnL2dldE5vZGVFbnYuanNcIjtcbmltcG9ydCB7IGhhbmRsZUVycm9yIH0gZnJvbSBcIi4uL2Vycm9yL2hhbmRsZUVycm9yLmpzXCI7XG5cbi8qKlxuICogQSByb2J1c3QgY29udGVudCBjb2xsZWN0aW5nIHRyYW5zZm9ybSBzdHJlYW0gdGhhdCBoYW5kbGVzIHJhY2UgY29uZGl0aW9uc1xuICovXG5jbGFzcyBDb250ZW50Q29sbGVjdG9yU3RyZWFtIGV4dGVuZHMgVHJhbnNmb3JtIHtcbiAgcHJpdmF0ZSBjaHVua3M6IEJ1ZmZlcltdID0gW107XG4gIHByaXZhdGUgX2lzRmluaXNoZWQgPSBmYWxzZTtcbiAgcHJpdmF0ZSBfb25BbGxDaHVua3NDb2xsZWN0ZWQ/OiAoKSA9PiB2b2lkO1xuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IGFueSA9IHt9KSB7XG4gICAgc3VwZXIoe1xuICAgICAgLi4ub3B0aW9ucyxcbiAgICAgIG9iamVjdE1vZGU6IGZhbHNlLFxuICAgIH0pO1xuICB9XG5cbiAgX3RyYW5zZm9ybShjaHVuazogYW55LCBfZW5jb2Rpbmc6IGFueSwgY2FsbGJhY2s6IGFueSkge1xuICAgIGlmICh0aGlzLl9pc0ZpbmlzaGVkKSB7XG4gICAgICBjYWxsYmFjaygpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGJ1ZmZlciA9IEJ1ZmZlci5mcm9tKGNodW5rKTtcbiAgICB0aGlzLmNodW5rcy5wdXNoKGJ1ZmZlcik7XG4gICAgdGhpcy5wdXNoKGNodW5rKTtcbiAgICBjYWxsYmFjaygpO1xuICB9XG5cbiAgX2ZsdXNoKGNhbGxiYWNrOiBhbnkpIHtcbiAgICB0aGlzLl9pc0ZpbmlzaGVkID0gdHJ1ZTtcbiAgICBpZiAodGhpcy5fb25BbGxDaHVua3NDb2xsZWN0ZWQpIHtcbiAgICAgIHRoaXMuX29uQWxsQ2h1bmtzQ29sbGVjdGVkKCk7XG4gICAgfVxuICAgIGNhbGxiYWNrKCk7XG4gIH1cblxuICBnZXRBbGxDaHVua3MoKTogQnVmZmVyW10ge1xuICAgIHJldHVybiB0aGlzLmNodW5rcztcbiAgfVxuXG4gIGdldENvbnRlbnQoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gQnVmZmVyLmNvbmNhdCh0aGlzLmNodW5rcykudG9TdHJpbmcoJ3V0ZjgnKTtcbiAgfVxuXG4gIGhhc0NvbnRlbnQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuY2h1bmtzLmxlbmd0aCA+IDA7XG4gIH1cblxuICBvbkFsbENodW5rc0NvbGxlY3RlZChjYWxsYmFjazogKCkgPT4gdm9pZCkge1xuICAgIGlmICh0aGlzLl9pc0ZpbmlzaGVkKSB7XG4gICAgICAvLyBBbHJlYWR5IGZpbmlzaGVkLCBjYWxsIGltbWVkaWF0ZWx5XG4gICAgICBjYWxsYmFjaygpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9vbkFsbENodW5rc0NvbGxlY3RlZCA9IGNhbGxiYWNrO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFdyaXRlcyBIVE1MIGFuZCBSU0MgZmlsZXMgZm9yIGEgcm91dGUgdXNpbmcgc3RyZWFtc1xuICpcbiAqIEBwYXJhbSBzdHJlYW0gVGhlIHJlYWRhYmxlIHN0cmVhbSBjb250YWluaW5nIHRoZSBjb250ZW50XG4gKiBAcGFyYW0gZmlsZVR5cGUgVGhlIHR5cGUgb2YgZmlsZSBiZWluZyB3cml0dGVuIChcImh0bWxcIiBvciBcInJzY1wiKVxuICogQHBhcmFtIG9wdGlvbnMgVGhlIGZpbGUgd3JpdGVyIG9wdGlvbnNcbiAqIEBwYXJhbSBzaWduYWwgT3B0aW9uYWwgQWJvcnRTaWduYWwgdG8gY2FuY2VsIHRoZSBmaWxlIHdyaXRlIG9wZXJhdGlvblxuICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgZmlsZSBpcyB3cml0dGVuXG4gKi9cbmV4cG9ydCBjb25zdCBmaWxlV3JpdGVyOiBGaWxlV3JpdGVyRm4gPSBmdW5jdGlvbiBfZmlsZVdyaXRlcihcbiAgc3RyZWFtLFxuICBmaWxlVHlwZSxcbiAgb3B0aW9ucyxcbiAgc2lnbmFsXG4pIHtcbiAgLy8gVmFsaWRhdGUgc3RyZWFtIG9yIHN0cmVhbSB3cmFwcGVyXG4gIGlmICghc3RyZWFtKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBNaXNzaW5nIHN0cmVhbSBmb3Igcm91dGU6ICR7b3B0aW9ucy5yb3V0ZX1gKTtcbiAgfVxuXG4gIC8vIEhhbmRsZSBzdHJlYW0gd3JhcHBlciBvYmplY3RzIChmcm9tIHJlbmRlclBhZ2Uuc2VydmVyLnRzKVxuICBjb25zdCBpc1N0cmVhbVdyYXBwZXIgPVxuICAgIChzdHJlYW0gYXMgYW55KS5waXBlICYmIHR5cGVvZiAoc3RyZWFtIGFzIGFueSkucGlwZSA9PT0gXCJmdW5jdGlvblwiO1xuXG4gIC8vIFJlbW92ZSBsZWFkaW5nIHNsYXNoIGZyb20gcm91dGUgZm9yIGZpbGUgcGF0aCBjb25zdHJ1Y3Rpb25cbiAgY29uc3Qgcm91dGVQYXRoID1cbiAgICBvcHRpb25zLnJvdXRlID09PSBcIi9cIiA/IFwiXCIgOiBvcHRpb25zLnJvdXRlLnJlcGxhY2UoL15cXC8vLCBcIlwiKTtcbiAgY29uc3QgYmFzZURpciA9IGpvaW4ob3B0aW9ucy5idWlsZC5vdXREaXIsIG9wdGlvbnMuYnVpbGQuc3RhdGljKTtcbiAgY29uc3Qgb3V0cHV0UGF0aCA9IGpvaW4oXG4gICAgYmFzZURpcixcbiAgICByb3V0ZVBhdGgsXG4gICAgZmlsZVR5cGUgPT09IFwiaHRtbFwiXG4gICAgICA/IG9wdGlvbnMuYnVpbGQuaHRtbE91dHB1dFBhdGhcbiAgICAgIDogb3B0aW9ucy5idWlsZC5yc2NPdXRwdXRQYXRoXG4gICk7XG5cbiAgLy8gRW5zdXJlIGRpcmVjdG9yeSBleGlzdHNcbiAgdHJ5IHtcbiAgICBta2RpclN5bmMoam9pbihiYXNlRGlyLCByb3V0ZVBhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBjb25zdCBwYW5pY0Vycm9yID0gaGFuZGxlRXJyb3Ioe1xuICAgICAgZXJyb3IsXG4gICAgICBsb2dnZXI6IG9wdGlvbnMubG9nZ2VyLFxuICAgICAgbW9kZTogZ2V0Tm9kZUVudigpLFxuICAgICAgcGFuaWNUaHJlc2hvbGQ6IG9wdGlvbnMucGFuaWNUaHJlc2hvbGQsXG4gICAgICBjcml0aWNhbDogZmFsc2UsXG4gICAgICBjb250ZXh0OiBcImZpbGVXcml0ZXJcIixcbiAgICB9KTtcbiAgICBpZiAocGFuaWNFcnJvciAhPSBudWxsKSB7XG4gICAgICB0aHJvdyBwYW5pY0Vycm9yO1xuICAgIH1cbiAgfVxuXG4gIGlmIChvcHRpb25zLnZlcmJvc2UpIHtcbiAgICBvcHRpb25zLmxvZ2dlcj8uaW5mbyhcbiAgICAgIGBbZmlsZVdyaXRlcl0gU3RhcnRpbmcgZmlsZSB3cml0ZSBmb3IgJHtmaWxlVHlwZX0gb24gcm91dGUgJHtvcHRpb25zLnJvdXRlfWBcbiAgICApO1xuICB9XG5cbiAgLy8gSGFuZGxlIGFib3J0IHNpZ25hbCBlYXJseVxuICBpZiAoc2lnbmFsPy5hYm9ydGVkKSB7XG4gICAgY29uc3QgYWJvcnRSZWFzb24gPSBzaWduYWw/LnJlYXNvbiB8fCBuZXcgRXJyb3IoXCJGaWxlIHdyaXRlIGFib3J0ZWRcIik7XG4gICAgdGhyb3cgYWJvcnRSZWFzb247XG4gIH1cblxuICAvLyBDcmVhdGUgc3RyZWFtcyB3aXRoIHByb3BlciBlcnJvciBoYW5kbGluZ1xuICBjb25zdCBjb250ZW50Q29sbGVjdG9yID0gbmV3IENvbnRlbnRDb2xsZWN0b3JTdHJlYW0oe1xuICAgIGhpZ2hXYXRlck1hcms6IDY0ICogMTAyNCwgLy8gNjRLQiBidWZmZXJcbiAgfSk7XG5cbiAgY29uc3Qgd3JpdGVTdHJlYW0gPSBjcmVhdGVXcml0ZVN0cmVhbShvdXRwdXRQYXRoLCB7XG4gICAgaGlnaFdhdGVyTWFyazogNjQgKiAxMDI0LCAvLyA2NEtCIGJ1ZmZlclxuICB9KTtcblxuICAvLyBDcmVhdGUgYSByb2J1c3Qgc291cmNlIHN0cmVhbSB0aGF0IGhhbmRsZXMgd3JhcHBlcnMgcHJvcGVybHlcbiAgbGV0IHNvdXJjZVN0cmVhbTogYW55O1xuICBpZiAoaXNTdHJlYW1XcmFwcGVyKSB7XG4gICAgLy8gQ3JlYXRlIGEgUGFzc1Rocm91Z2ggc3RyZWFtIHRvIG5vcm1hbGl6ZSB0aGUgd3JhcHBlclxuICAgIHNvdXJjZVN0cmVhbSA9IG5ldyBQYXNzVGhyb3VnaCgpO1xuICAgIHRyeSB7XG4gICAgICAoc3RyZWFtIGFzIGFueSkucGlwZShzb3VyY2VTdHJlYW0pO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBwaXBlIHN0cmVhbSB3cmFwcGVyOiAke2Vycm9yfWApO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBzb3VyY2VTdHJlYW0gPSBzdHJlYW07XG4gIH1cblxuICAvLyBFbWl0IGZpbGUud3JpdGUgZXZlbnQgaWYgb25FdmVudCBpcyBwcm92aWRlZFxuICBpZiAob3B0aW9ucy5vbkV2ZW50KSB7XG4gICAgdHJ5IHtcbiAgICAgIG9wdGlvbnMub25FdmVudCh7XG4gICAgICAgIHR5cGU6IFwiZmlsZS53cml0ZVwiLFxuICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgcGF0aDogb3V0cHV0UGF0aCxcbiAgICAgICAgICByb3V0ZTogb3B0aW9ucy5yb3V0ZSxcbiAgICAgICAgICBmaWxlVHlwZSxcbiAgICAgICAgICBzdHJlYW06IGNvbnRlbnRDb2xsZWN0b3IsXG4gICAgICAgICAgb25Db21wbGV0ZTogKCkgPT5cbiAgICAgICAgICAgIG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlQ29tcGxldGUpID0+IHtcbiAgICAgICAgICAgICAgcmVzb2x2ZUNvbXBsZXRlKCk7XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAvLyBGb3IgZmlsZS53cml0ZSBldmVudHMsIHdlIG5lZWQgdG8gZW1pdCBhIHJvdXRlLmVycm9yIGV2ZW50XG4gICAgICBpZiAob3B0aW9ucy5vbkV2ZW50KSB7XG4gICAgICAgIG9wdGlvbnMub25FdmVudCh7XG4gICAgICAgICAgdHlwZTogXCJyb3V0ZS5lcnJvclwiLFxuICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgIGVycm9yOiBlcnJvcixcbiAgICAgICAgICAgIHJvdXRlOiBvcHRpb25zLnJvdXRlLFxuICAgICAgICAgICAgcGFuaWNUaHJlc2hvbGQ6IG9wdGlvbnMucGFuaWNUaHJlc2hvbGRcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAvLyBIYW5kbGUgYWJvcnQgc2lnbmFsXG4gICAgY29uc3QgYWJvcnRIYW5kbGVyID0gKCkgPT4ge1xuICAgICAgd3JpdGVTdHJlYW0uZGVzdHJveSgpO1xuICAgICAgY29udGVudENvbGxlY3Rvci5kZXN0cm95KCk7XG4gICAgICBzb3VyY2VTdHJlYW0uZGVzdHJveT8uKCk7XG4gICAgICBjb25zdCBhYm9ydFJlYXNvbiA9IHNpZ25hbD8ucmVhc29uIHx8IG5ldyBFcnJvcihcIkZpbGUgd3JpdGUgYWJvcnRlZFwiKTtcbiAgICAgIHJlamVjdChhYm9ydFJlYXNvbik7XG4gICAgfTtcblxuICAgIGlmIChzaWduYWwpIHtcbiAgICAgIHNpZ25hbC5hZGRFdmVudExpc3RlbmVyKFwiYWJvcnRcIiwgYWJvcnRIYW5kbGVyKTtcbiAgICB9XG5cbiAgICAvLyBTZXQgdXAgdGhlIHN0cmVhbSBwaXBlbGluZSBtYW51YWxseSBmb3IgYmV0dGVyIGNvbnRyb2xcbiAgICBzb3VyY2VTdHJlYW0ucGlwZShjb250ZW50Q29sbGVjdG9yKS5waXBlKHdyaXRlU3RyZWFtKTtcblxuICAgIC8vIEhhbmRsZSBlcnJvcnMgZnJvbSBhbnkgcGFydCBvZiB0aGUgcGlwZWxpbmVcbiAgICBjb25zdCBoYW5kbGVFcnJvciA9IChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgIGlmIChzaWduYWwpIHtcbiAgICAgICAgc2lnbmFsLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJhYm9ydFwiLCBhYm9ydEhhbmRsZXIpO1xuICAgICAgfVxuICAgICAgaWYgKG9wdGlvbnMudmVyYm9zZSkge1xuICAgICAgICBvcHRpb25zLmxvZ2dlcj8uZXJyb3IoXG4gICAgICAgICAgYFtmaWxlV3JpdGVyXSBFcnJvciB3cml0aW5nICR7ZmlsZVR5cGV9IGZpbGUgZm9yIHJvdXRlICR7b3B0aW9ucy5yb3V0ZX06ICR7ZXJyb3IubWVzc2FnZX1gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICByZWplY3QoZXJyb3IpO1xuICAgIH07XG5cbiAgICBzb3VyY2VTdHJlYW0ub24oJ2Vycm9yJywgaGFuZGxlRXJyb3IpO1xuICAgIGNvbnRlbnRDb2xsZWN0b3Iub24oJ2Vycm9yJywgaGFuZGxlRXJyb3IpO1xuICAgIHdyaXRlU3RyZWFtLm9uKCdlcnJvcicsIGhhbmRsZUVycm9yKTtcblxuICAgIC8vIEhhbmRsZSBzdWNjZXNzZnVsIGNvbXBsZXRpb25cbiAgICB3cml0ZVN0cmVhbS5vbihcImZpbmlzaFwiLCAoKSA9PiB7XG4gICAgICBpZiAoc2lnbmFsKSB7XG4gICAgICAgIHNpZ25hbC5yZW1vdmVFdmVudExpc3RlbmVyKFwiYWJvcnRcIiwgYWJvcnRIYW5kbGVyKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdGlvbnMudmVyYm9zZSkge1xuICAgICAgICBvcHRpb25zLmxvZ2dlcj8uaW5mbyhcbiAgICAgICAgICBgW2ZpbGVXcml0ZXJdIENvbXBsZXRlZCBmaWxlIHdyaXRlIGZvciAke2ZpbGVUeXBlfSBvbiByb3V0ZSAke29wdGlvbnMucm91dGV9YFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICAvLyBXYWl0IGZvciBjb250ZW50IGNvbGxlY3RvciB0byBmaW5pc2ggcHJvY2Vzc2luZyBhbGwgY2h1bmtzXG4gICAgICBjb250ZW50Q29sbGVjdG9yLm9uQWxsQ2h1bmtzQ29sbGVjdGVkKCgpID0+IHtcbiAgICAgICAgLy8gRW1pdCBmaWxlLndyaXRlLmRvbmUgZXZlbnQgaWYgb25FdmVudCBpcyBwcm92aWRlZFxuICAgICAgICBpZiAob3B0aW9ucy5vbkV2ZW50KSB7XG4gICAgICAgICAgaWYgKGNvbnRlbnRDb2xsZWN0b3IuaGFzQ29udGVudCgpKSB7XG4gICAgICAgICAgICBjb25zdCBjb250ZW50ID0gY29udGVudENvbGxlY3Rvci5nZXRDb250ZW50KCk7XG4gICAgICAgICAgICBjb25zdCBjaHVua3MgPSBjb250ZW50Q29sbGVjdG9yLmdldEFsbENodW5rcygpO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICBpZiAob3B0aW9ucy52ZXJib3NlKSB7XG4gICAgICAgICAgICAgIG9wdGlvbnMubG9nZ2VyPy5pbmZvKFxuICAgICAgICAgICAgICAgIGBbZmlsZVdyaXRlcjoke2ZpbGVUeXBlfV0gRW1pdHRpbmcgZmlsZS53cml0ZS5kb25lIHdpdGggY29udGVudCBsZW5ndGg6ICR7Y29udGVudC5sZW5ndGh9IGJ5dGVzLCBjaHVua3M6ICR7Y2h1bmtzLmxlbmd0aH1gXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIGlmIChjb250ZW50Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBvcHRpb25zLmxvZ2dlcj8uaW5mbyhcbiAgICAgICAgICAgICAgICAgIGBbZmlsZVdyaXRlcjoke2ZpbGVUeXBlfV0gQ29udGVudCBwcmV2aWV3OiAke2NvbnRlbnQuc3Vic3RyaW5nKDAsIDIwMCl9Li4uYFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXh0cmFjdCBmaWxlIG5hbWUgZnJvbSB0aGUgb3V0cHV0IHBhdGhcbiAgICAgICAgICAgIGNvbnN0IGZpbGVOYW1lID1cbiAgICAgICAgICAgICAgZmlsZVR5cGUgPT09IFwiaHRtbFwiXG4gICAgICAgICAgICAgICAgPyBvcHRpb25zLmJ1aWxkLmh0bWxPdXRwdXRQYXRoXG4gICAgICAgICAgICAgICAgOiBvcHRpb25zLmJ1aWxkLnJzY091dHB1dFBhdGg7XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIG9wdGlvbnMub25FdmVudCh7XG4gICAgICAgICAgICAgICAgdHlwZTogXCJmaWxlLndyaXRlLmRvbmVcIixcbiAgICAgICAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICAgICAgICByb3V0ZTogb3B0aW9ucy5yb3V0ZSxcbiAgICAgICAgICAgICAgICAgIGZpbGVUeXBlLFxuICAgICAgICAgICAgICAgICAgY29udGVudCxcbiAgICAgICAgICAgICAgICAgIGNodW5rczogY2h1bmtzLmxlbmd0aCxcbiAgICAgICAgICAgICAgICAgIHBhdGg6IG91dHB1dFBhdGgsXG4gICAgICAgICAgICAgICAgICBmaWxlTmFtZSxcbiAgICAgICAgICAgICAgICAgIGJhc2VEaXI6IGJhc2VEaXIsXG4gICAgICAgICAgICAgICAgICByb3V0ZVBhdGg6IHJvdXRlUGF0aCxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgIC8vIEZvciBmaWxlLndyaXRlLmRvbmUgZXZlbnRzLCB3ZSBuZWVkIHRvIGVtaXQgYSByb3V0ZS5lcnJvciBldmVudFxuICAgICAgICAgICAgICBpZiAob3B0aW9ucy5vbkV2ZW50KSB7XG4gICAgICAgICAgICAgICAgb3B0aW9ucy5vbkV2ZW50KHtcbiAgICAgICAgICAgICAgICAgIHR5cGU6IFwicm91dGUuZXJyb3JcIixcbiAgICAgICAgICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3I6IGVycm9yLFxuICAgICAgICAgICAgICAgICAgICByb3V0ZTogb3B0aW9ucy5yb3V0ZSxcbiAgICAgICAgICAgICAgICAgICAgcGFuaWNUaHJlc2hvbGQ6IG9wdGlvbnMucGFuaWNUaHJlc2hvbGRcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEluc3RlYWQgb2YgcmVqZWN0aW5nLCBsZXQncyBiZSBtb3JlIGxlbmllbnQgYWJvdXQgZW1wdHkgY29udGVudFxuICAgICAgICAgICAgLy8gVGhpcyBjYW4gaGFwcGVuIGxlZ2l0aW1hdGVseSB3aXRoIGVtcHR5IGZpbGVzIG9yIGZhc3QgYnVpbGRzXG4gICAgICAgICAgICBpZiAob3B0aW9ucy52ZXJib3NlKSB7XG4gICAgICAgICAgICAgIG9wdGlvbnMubG9nZ2VyPy53YXJuKFxuICAgICAgICAgICAgICAgIGBbZmlsZVdyaXRlcl0gTm8gY29udGVudCBjaHVua3MgY29sbGVjdGVkIGZvciAke2ZpbGVUeXBlfSBmaWxlOiAke291dHB1dFBhdGh9LiBUaGlzIG1heSBiZSBub3JtYWwgZm9yIGVtcHR5IGZpbGVzLmBcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIFxuICAgICAgICAgICAgLy8gU3RpbGwgZW1pdCB0aGUgZG9uZSBldmVudCwgYnV0IHdpdGggZW1wdHkgY29udGVudFxuICAgICAgICAgICAgY29uc3QgZmlsZU5hbWUgPVxuICAgICAgICAgICAgICBmaWxlVHlwZSA9PT0gXCJodG1sXCJcbiAgICAgICAgICAgICAgICA/IG9wdGlvbnMuYnVpbGQuaHRtbE91dHB1dFBhdGhcbiAgICAgICAgICAgICAgICA6IG9wdGlvbnMuYnVpbGQucnNjT3V0cHV0UGF0aDtcblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgb3B0aW9ucy5vbkV2ZW50KHtcbiAgICAgICAgICAgICAgICB0eXBlOiBcImZpbGUud3JpdGUuZG9uZVwiLFxuICAgICAgICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgICAgICAgIHJvdXRlOiBvcHRpb25zLnJvdXRlLFxuICAgICAgICAgICAgICAgICAgZmlsZVR5cGUsXG4gICAgICAgICAgICAgICAgICBjb250ZW50OiBcIlwiLFxuICAgICAgICAgICAgICAgICAgY2h1bmtzOiAwLFxuICAgICAgICAgICAgICAgICAgcGF0aDogb3V0cHV0UGF0aCxcbiAgICAgICAgICAgICAgICAgIGZpbGVOYW1lLFxuICAgICAgICAgICAgICAgICAgYmFzZURpcjogYmFzZURpcixcbiAgICAgICAgICAgICAgICAgIHJvdXRlUGF0aDogcm91dGVQYXRoLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgaWYgKG9wdGlvbnMub25FdmVudCkge1xuICAgICAgICAgICAgICAgIG9wdGlvbnMub25FdmVudCh7XG4gICAgICAgICAgICAgICAgICB0eXBlOiBcInJvdXRlLmVycm9yXCIsXG4gICAgICAgICAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yOiBlcnJvcixcbiAgICAgICAgICAgICAgICAgICAgcm91dGU6IG9wdGlvbnMucm91dGUsXG4gICAgICAgICAgICAgICAgICAgIHBhbmljVGhyZXNob2xkOiBvcHRpb25zLnBhbmljVGhyZXNob2xkXG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJlc29sdmUoKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcbn07XG4iXSwibmFtZXMiOlsiaGFuZGxlRXJyb3IiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7O0FBcUJBLE1BQU0sK0JBQStCLFNBQVUsQ0FBQTtBQUFBLEVBQ3JDLFNBQW1CLEVBQUM7QUFBQSxFQUNwQixXQUFjLEdBQUEsS0FBQTtBQUFBLEVBQ2QscUJBQUE7QUFBQSxFQUVSLFdBQUEsQ0FBWSxPQUFlLEdBQUEsRUFBSSxFQUFBO0FBQzdCLElBQU0sS0FBQSxDQUFBO0FBQUEsTUFDSixHQUFHLE9BQUE7QUFBQSxNQUNILFVBQVksRUFBQTtBQUFBLEtBQ2IsQ0FBQTtBQUFBO0FBQ0gsRUFFQSxVQUFBLENBQVcsS0FBWSxFQUFB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