UNPKG

vite-plugin-react-server

Version:
92 lines (89 loc) 12.4 kB
/** * vite-plugin-react-server * Copyright (c) Nico Brinkkemper * MIT License */ import { createStreamMetrics } from '../metrics/createStreamMetrics.js'; import { handleError } from '../error/handleError.js'; import { getNodeEnv } from '../config/getNodeEnv.js'; import { createLogger } from 'vite'; function validateRscStreamOptions(options, context) { if (!options.route) { throw new Error(`${context}: Route is required for RSC stream creation`); } if (!options.pagePath) { throw new Error(`${context}: pagePath is required for RSC stream creation`); } } function createBaseRscStreamResult(rscStream, pipe, abort, metrics, id) { return { id, rscStream, pipe, abort, metrics }; } function handleRscStreamError(error, options, context) { const panicError = handleError({ error, logger: options.logger, mode: getNodeEnv(), panicThreshold: options.panicThreshold || "none", context: `${context} for route ${options.route}` }); if (panicError != null) { throw panicError; } throw error; } function createRscStreamMetrics() { const metrics = createStreamMetrics(); metrics.startTime = performance.now(); return metrics; } function setupRscStreamEventHandlers(stream, metrics, options) { const { route, verbose = false, logger = createLogger() } = options; stream.on("data", (chunk) => { if (verbose) { logger.info( `[createRscStream:${route}] Received data chunk: ${chunk.length} bytes` ); } metrics.chunks++; metrics.bytes += chunk.length; }); stream.on("end", () => { if (verbose) { logger.info(`[createRscStream:${route}] Stream ended`); } metrics.duration = performance.now() - metrics.startTime; metrics.endTime = performance.now(); }); stream.on("error", (error) => { logger.error(`[createRscStream:${route}] Stream error: ${error}`); }); stream.on("drain", () => { if (verbose) { logger.info( `[createRscStream:${route}] Stream drain - backpressure resolved` ); } }); const originalWrite = stream.write.bind(stream); stream.write = function(chunk, encoding, callback) { const result = originalWrite(chunk, encoding, callback); if (!result) { metrics.backpressureCount++; if (verbose) { logger.warn(`[createRscStream:${route}] Backpressure detected`); } } return result; }; return () => { stream.removeAllListeners(); }; } export { createBaseRscStreamResult, createRscStreamMetrics, handleRscStreamError, setupRscStreamEventHandlers, validateRscStreamOptions }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlUnNjU3RyZWFtLnV0aWxzLmpzIiwic291cmNlcyI6WyIuLi8uLi8uLi9wbHVnaW4vc3RyZWFtL2NyZWF0ZVJzY1N0cmVhbS51dGlscy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjcmVhdGVTdHJlYW1NZXRyaWNzIH0gZnJvbSBcIi4uL2hlbHBlcnMvbWV0cmljcy5qc1wiO1xuaW1wb3J0IHsgaGFuZGxlRXJyb3IgfSBmcm9tIFwiLi4vZXJyb3IvaGFuZGxlRXJyb3IuanNcIjtcbmltcG9ydCB7IGdldE5vZGVFbnYgfSBmcm9tIFwiLi4vY29uZmlnL2dldE5vZGVFbnYuanNcIjtcbmltcG9ydCB0eXBlIHtcbiAgQ2xpZW50UnNjU3RyZWFtT3B0aW9ucyxcbiAgU2VydmVyUnNjU3RyZWFtT3B0aW9ucyxcbiAgQmFzZVJzY1N0cmVhbVJlc3VsdCxcbn0gZnJvbSBcIi4vY3JlYXRlUnNjU3RyZWFtLnR5cGVzLmpzXCI7XG5pbXBvcnQgdHlwZSB7IFBhc3NUaHJvdWdoIH0gZnJvbSBcIm5vZGU6c3RyZWFtXCI7XG5pbXBvcnQgeyBjcmVhdGVMb2dnZXIsIHR5cGUgTG9nZ2VyIH0gZnJvbSBcInZpdGVcIjtcblxuLyoqXG4gKiBWYWxpZGF0ZXMgY29tbW9uIFJTQyBzdHJlYW0gb3B0aW9uc1xuICpcbiAqIEBwYXJhbSBvcHRpb25zIC0gUlNDIHN0cmVhbSBvcHRpb25zIHRvIHZhbGlkYXRlXG4gKiBAcGFyYW0gY29udGV4dCAtIENvbnRleHQgZm9yIGVycm9yIG1lc3NhZ2VzXG4gKiBAdGhyb3dzIEVycm9yIGlmIHZhbGlkYXRpb24gZmFpbHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlUnNjU3RyZWFtT3B0aW9ucyhcbiAgb3B0aW9uczogQ2xpZW50UnNjU3RyZWFtT3B0aW9ucyB8IFNlcnZlclJzY1N0cmVhbU9wdGlvbnMsXG4gIGNvbnRleHQ6IHN0cmluZ1xuKTogdm9pZCB7XG4gIGlmICghb3B0aW9ucy5yb3V0ZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgJHtjb250ZXh0fTogUm91dGUgaXMgcmVxdWlyZWQgZm9yIFJTQyBzdHJlYW0gY3JlYXRpb25gKTtcbiAgfVxuXG4gIGlmICghb3B0aW9ucy5wYWdlUGF0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgJHtjb250ZXh0fTogcGFnZVBhdGggaXMgcmVxdWlyZWQgZm9yIFJTQyBzdHJlYW0gY3JlYXRpb25gKTtcbiAgfVxufVxuXG4vKipcbiAqIENyZWF0ZXMgY29tbW9uIFJTQyBzdHJlYW0gcmVzdWx0IHN0cnVjdHVyZVxuICpcbiAqIEBwYXJhbSByc2NTdHJlYW0gLSBUaGUgUlNDIHN0cmVhbVxuICogQHBhcmFtIGVsZW1lbnRzIC0gUmVhY3QgZWxlbWVudHNcbiAqIEBwYXJhbSBwaXBlIC0gUGlwZSBmdW5jdGlvblxuICogQHBhcmFtIGFib3J0IC0gQWJvcnQgZnVuY3Rpb25cbiAqIEBwYXJhbSBtZXRyaWNzIC0gU3RyZWFtIG1ldHJpY3NcbiAqIEByZXR1cm5zIEJhc2UgUlNDIHN0cmVhbSByZXN1bHRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUJhc2VSc2NTdHJlYW1SZXN1bHQoXG4gIHJzY1N0cmVhbTogUGFzc1Rocm91Z2gsXG4gIHBpcGU6IDxXcml0YWJsZSBleHRlbmRzIE5vZGVKUy5Xcml0YWJsZVN0cmVhbT4oXG4gICAgZGVzdGluYXRpb246IFdyaXRhYmxlXG4gICkgPT4gV3JpdGFibGUsXG4gIGFib3J0OiAocmVhc29uPzogdW5rbm93bikgPT4gdm9pZCxcbiAgbWV0cmljczogUmV0dXJuVHlwZTx0eXBlb2YgY3JlYXRlU3RyZWFtTWV0cmljcz4sXG4gIGlkOiBzdHJpbmdcbik6IEJhc2VSc2NTdHJlYW1SZXN1bHQge1xuICByZXR1cm4ge1xuICAgIGlkLFxuICAgIHJzY1N0cmVhbSxcbiAgICBwaXBlLFxuICAgIGFib3J0LFxuICAgIG1ldHJpY3MsXG4gIH07XG59XG5cbi8qKlxuICogSGFuZGxlcyBSU0Mgc3RyZWFtIGVycm9ycyB3aXRoIGNvbnNpc3RlbnQgZXJyb3IgaGFuZGxpbmdcbiAqXG4gKiBAcGFyYW0gZXJyb3IgLSBUaGUgZXJyb3IgdGhhdCBvY2N1cnJlZFxuICogQHBhcmFtIG9wdGlvbnMgLSBSU0Mgc3RyZWFtIG9wdGlvbnMgZm9yIGNvbnRleHRcbiAqIEBwYXJhbSBjb250ZXh0IC0gQWRkaXRpb25hbCBjb250ZXh0IGZvciBlcnJvciBoYW5kbGluZ1xuICogQHRocm93cyBFcnJvciBpZiBwYW5pYyB0aHJlc2hvbGQgaXMgbWV0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYW5kbGVSc2NTdHJlYW1FcnJvcihcbiAgZXJyb3I6IHVua25vd24sXG4gIG9wdGlvbnM6IENsaWVudFJzY1N0cmVhbU9wdGlvbnMgfCBTZXJ2ZXJSc2NTdHJlYW1PcHRpb25zLFxuICBjb250ZXh0OiBzdHJpbmdcbik6IHZvaWQge1xuICBjb25zdCBwYW5pY0Vycm9yID0gaGFuZGxlRXJyb3Ioe1xuICAgIGVycm9yLFxuICAgIGxvZ2dlcjogKG9wdGlvbnMgYXMgYW55KS5sb2dnZXIsXG4gICAgbW9kZTogZ2V0Tm9kZUVudigpLFxuICAgIHBhbmljVGhyZXNob2xkOiBvcHRpb25zLnBhbmljVGhyZXNob2xkIHx8IFwibm9uZVwiLFxuICAgIGNvbnRleHQ6IGAke2NvbnRleHR9IGZvciByb3V0ZSAke29wdGlvbnMucm91dGV9YCxcbiAgfSk7XG5cbiAgaWYgKHBhbmljRXJyb3IgIT0gbnVsbCkge1xuICAgIHRocm93IHBhbmljRXJyb3I7XG4gIH1cblxuICB0aHJvdyBlcnJvcjtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIHN0cmVhbSBtZXRyaWNzIHdpdGggY29tbW9uIHNldHVwXG4gKlxuICogQHBhcmFtIHJvdXRlIC0gUm91dGUgZm9yIGxvZ2dpbmcgY29udGV4dFxuICogQHBhcmFtIHZlcmJvc2UgLSBXaGV0aGVyIHRvIGVuYWJsZSB2ZXJib3NlIGxvZ2dpbmdcbiAqIEByZXR1cm5zIFN0cmVhbSBtZXRyaWNzIGluc3RhbmNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVSc2NTdHJlYW1NZXRyaWNzKCk6IFJldHVyblR5cGU8dHlwZW9mIGNyZWF0ZVN0cmVhbU1ldHJpY3M+IHtcbiAgY29uc3QgbWV0cmljcyA9IGNyZWF0ZVN0cmVhbU1ldHJpY3MoKTtcbiAgbWV0cmljcy5zdGFydFRpbWUgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgcmV0dXJuIG1ldHJpY3M7XG59XG5cbi8qKlxuICogU2V0cyB1cCBjb21tb24gc3RyZWFtIGV2ZW50IGhhbmRsZXJzIGZvciBtZXRyaWNzIGNvbGxlY3Rpb25cbiAqXG4gKiBAcGFyYW0gc3RyZWFtIC0gVGhlIHN0cmVhbSB0byBtb25pdG9yXG4gKiBAcGFyYW0gbWV0cmljcyAtIE1ldHJpY3MgdG8gdXBkYXRlXG4gKiBAcGFyYW0gb3B0aW9ucyAtIENvbmZpZ3VyYXRpb24gb3B0aW9uc1xuICogQHJldHVybnMgQ2xlYW51cCBmdW5jdGlvblxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0dXBSc2NTdHJlYW1FdmVudEhhbmRsZXJzKFxuICBzdHJlYW06IFBhc3NUaHJvdWdoLFxuICBtZXRyaWNzOiBSZXR1cm5UeXBlPHR5cGVvZiBjcmVhdGVTdHJlYW1NZXRyaWNzPixcbiAgb3B0aW9uczoge1xuICAgIHJvdXRlOiBzdHJpbmc7XG4gICAgdmVyYm9zZT86IGJvb2xlYW47XG4gICAgbG9nZ2VyPzogTG9nZ2VyO1xuICB9XG4pOiAoKSA9PiB2b2lkIHtcbiAgY29uc3QgeyByb3V0ZSwgdmVyYm9zZSA9IGZhbHNlLCBsb2dnZXIgPSBjcmVhdGVMb2dnZXIoKSB9ID0gb3B0aW9ucztcblxuICBzdHJlYW0ub24oXCJkYXRhXCIsIChjaHVuazogQnVmZmVyKSA9PiB7XG4gICAgaWYgKHZlcmJvc2UpIHtcbiAgICAgIGxvZ2dlci5pbmZvKFxuICAgICAgICBgW2NyZWF0ZVJzY1N0cmVhbToke3JvdXRlfV0gUmVjZWl2ZWQgZGF0YSBjaHVuazogJHtjaHVuay5sZW5ndGh9IGJ5dGVzYFxuICAgICAgKTtcbiAgICB9XG4gICAgbWV0cmljcy5jaHVua3MrKztcbiAgICBtZXRyaWNzLmJ5dGVzICs9IGNodW5rLmxlbmd0aDtcbiAgfSk7XG5cbiAgc3RyZWFtLm9uKFwiZW5kXCIsICgpID0+IHtcbiAgICBpZiAodmVyYm9zZSkge1xuICAgICAgbG9nZ2VyLmluZm8oYFtjcmVhdGVSc2NTdHJlYW06JHtyb3V0ZX1dIFN0cmVhbSBlbmRlZGApO1xuICAgIH1cbiAgICBtZXRyaWNzLmR1cmF0aW9uID0gcGVyZm9ybWFuY2Uubm93KCkgLSBtZXRyaWNzLnN0YXJ0VGltZTtcbiAgICBtZXRyaWNzLmVuZFRpbWUgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgfSk7XG5cbiAgc3RyZWFtLm9uKFwiZXJyb3JcIiwgKGVycm9yOiB1bmtub3duKSA9PiB7XG4gICAgbG9nZ2VyLmVycm9yKGBbY3JlYXRlUnNjU3RyZWFtOiR7cm91dGV9XSBTdHJlYW0gZXJyb3I6ICR7ZXJyb3J9YCk7XG4gIH0pO1xuXG4gIHN0cmVhbS5vbihcImRyYWluXCIsICgpID0+IHtcbiAgICBpZiAodmVyYm9zZSkge1xuICAgICAgbG9nZ2VyLmluZm8oXG4gICAgICAgIGBbY3JlYXRlUnNjU3RyZWFtOiR7cm91dGV9XSBTdHJlYW0gZHJhaW4gLSBiYWNrcHJlc3N1cmUgcmVzb2x2ZWRgXG4gICAgICApO1xuICAgIH1cbiAgfSk7XG5cbiAgLy8gVHJhY2sgYmFja3ByZXNzdXJlIHdoZW4gd3JpdGUgYnVmZmVyIGlzIGZ1bGxcbiAgY29uc3Qgb3JpZ2luYWxXcml0ZSA9IHN0cmVhbS53cml0ZS5iaW5kKHN0cmVhbSk7XG4gIHN0cmVhbS53cml0ZSA9IGZ1bmN0aW9uIChcbiAgICBjaHVuazogYW55LFxuICAgIGVuY29kaW5nPzogQnVmZmVyRW5jb2RpbmcgfCAoKGVycm9yOiBFcnJvciB8IG51bGwgfCB1bmRlZmluZWQpID0+IHZvaWQpLFxuICAgIGNhbGxiYWNrPzogKGVycm9yOiBFcnJvciB8IG51bGwgfCB1bmRlZmluZWQpID0+IHZvaWRcbiAgKSB7XG4gICAgY29uc3QgcmVzdWx0ID0gb3JpZ2luYWxXcml0ZShjaHVuaywgZW5jb2RpbmcgYXMgYW55LCBjYWxsYmFjayk7XG4gICAgaWYgKCFyZXN1bHQpIHtcbiAgICAgIG1ldHJpY3MuYmFja3ByZXNzdXJlQ291bnQrKztcbiAgICAgIGlmICh2ZXJib3NlKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKGBbY3JlYXRlUnNjU3RyZWFtOiR7cm91dGV9XSBCYWNrcHJlc3N1cmUgZGV0ZWN0ZWRgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICByZXR1cm4gKCkgPT4ge1xuICAgIC8vIE5vIGNsZWFudXAgbmVlZGVkIHNpbmNlIHdlIHJlbW92ZWQgdGhlIHRpbWVvdXRcbiAgICBzdHJlYW0ucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gIH07XG59XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztBQWtCTyxTQUFTLHdCQUFBLENBQ2QsU0FDQSxPQUNNLEVBQUE7QUFDTixFQUFJLElBQUEsQ0FBQyxRQUFRLEtBQU8sRUFBQTtBQUNsQixJQUFBLE1BQU0sSUFBSSxLQUFBLENBQU0sQ0FBRyxFQUFBLE9BQU8sQ0FBNkMsMkNBQUEsQ0FBQSxDQUFBO0FBQUE7QUFHekUsRUFBSSxJQUFBLENBQUMsUUFBUSxRQUFVLEVBQUE7QUFDckIsSUFBQSxNQUFNLElBQUksS0FBQSxDQUFNLENBQUcsRUFBQSxPQUFPLENBQWdELDhDQUFBLENBQUEsQ0FBQTtBQUFBO0FBRTlFO0FBWU8sU0FBUyx5QkFDZCxDQUFBLFNBQUEsRUFDQSxJQUdBLEVBQUEsS0FBQSxFQUNBLFNBQ0EsRUFDcUIsRUFBQTtBQUNyQixFQUFPLE9BQUE7QUFBQSxJQUNMLEVBQUE7QUFBQSxJQUNBLFNBQUE7QUFBQSxJQUNBLElBQUE7QUFBQSxJQUNBLEtBQUE7QUFBQSxJQUNBO0FBQUEsR0FDRjtBQUNGO0FBVU8sU0FBUyxvQkFBQSxDQUNkLEtBQ0EsRUFBQSxPQUFBLEVBQ0EsT0FDTSxFQUFBO0FBQ04sRUFBQSxNQUFNLGFB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