UNPKG

vite-plugin-react-server

Version:
261 lines (258 loc) 30.4 kB
/** * 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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