vinext 0.0.33 → 0.0.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/deploy.js +52 -4
  2. package/dist/deploy.js.map +1 -1
  3. package/dist/entries/app-rsc-entry.js +278 -740
  4. package/dist/entries/app-rsc-entry.js.map +1 -1
  5. package/dist/entries/pages-server-entry.js +8 -1
  6. package/dist/entries/pages-server-entry.js.map +1 -1
  7. package/dist/index.js +299 -22
  8. package/dist/index.js.map +1 -1
  9. package/dist/server/app-browser-entry.js +2 -3
  10. package/dist/server/app-browser-entry.js.map +1 -1
  11. package/dist/server/app-page-boundary-render.d.ts +63 -0
  12. package/dist/server/app-page-boundary-render.js +182 -0
  13. package/dist/server/app-page-boundary-render.js.map +1 -0
  14. package/dist/server/app-page-boundary.d.ts +57 -0
  15. package/dist/server/app-page-boundary.js +60 -0
  16. package/dist/server/app-page-boundary.js.map +1 -0
  17. package/dist/server/app-page-execution.d.ts +46 -0
  18. package/dist/server/app-page-execution.js +109 -0
  19. package/dist/server/app-page-execution.js.map +1 -0
  20. package/dist/server/app-page-probe.d.ts +17 -0
  21. package/dist/server/app-page-probe.js +35 -0
  22. package/dist/server/app-page-probe.js.map +1 -0
  23. package/dist/server/app-page-render.d.ts +59 -0
  24. package/dist/server/app-page-render.js +174 -0
  25. package/dist/server/app-page-render.js.map +1 -0
  26. package/dist/server/app-page-request.d.ts +58 -0
  27. package/dist/server/app-page-request.js +79 -0
  28. package/dist/server/app-page-request.js.map +1 -0
  29. package/dist/server/app-page-stream.d.ts +55 -0
  30. package/dist/server/app-page-stream.js +65 -0
  31. package/dist/server/app-page-stream.js.map +1 -0
  32. package/dist/server/app-ssr-stream.js +1 -1
  33. package/dist/server/app-ssr-stream.js.map +1 -1
  34. package/dist/server/prod-server.d.ts +13 -1
  35. package/dist/server/prod-server.js +113 -19
  36. package/dist/server/prod-server.js.map +1 -1
  37. package/dist/server/worker-utils.d.ts +0 -6
  38. package/dist/server/worker-utils.js +41 -5
  39. package/dist/server/worker-utils.js.map +1 -1
  40. package/dist/shims/error-boundary.js +1 -1
  41. package/dist/shims/font-google-base.js +1 -1
  42. package/dist/shims/font-google-base.js.map +1 -1
  43. package/dist/shims/font-google.d.ts +2 -3
  44. package/dist/shims/font-google.js +2 -3
  45. package/package.json +1 -1
  46. package/dist/shims/font-google.generated.d.ts +0 -1929
  47. package/dist/shims/font-google.generated.js +0 -1929
  48. package/dist/shims/font-google.generated.js.map +0 -1
@@ -0,0 +1,55 @@
1
+ import { AppPageFontPreload } from "./app-page-execution.js";
2
+
3
+ //#region src/server/app-page-stream.d.ts
4
+ interface AppPageFontData {
5
+ links: string[];
6
+ preloads: readonly AppPageFontPreload[];
7
+ styles: string[];
8
+ }
9
+ interface CreateAppPageFontDataOptions {
10
+ getLinks: () => string[];
11
+ getPreloads: () => AppPageFontPreload[];
12
+ getStyles: () => string[];
13
+ }
14
+ interface AppPageSsrHandler {
15
+ handleSsr: (rscStream: ReadableStream<Uint8Array>, navigationContext: unknown, fontData: AppPageFontData) => Promise<ReadableStream<Uint8Array>>;
16
+ }
17
+ interface RenderAppPageHtmlStreamOptions {
18
+ fontData: AppPageFontData;
19
+ navigationContext: unknown;
20
+ rscStream: ReadableStream<Uint8Array>;
21
+ ssrHandler: AppPageSsrHandler;
22
+ }
23
+ interface RenderAppPageHtmlResponseOptions extends RenderAppPageHtmlStreamOptions {
24
+ clearRequestContext: () => void;
25
+ fontLinkHeader?: string;
26
+ status: number;
27
+ }
28
+ interface AppPageHtmlStreamRecoveryResult {
29
+ htmlStream: ReadableStream<Uint8Array> | null;
30
+ response: Response | null;
31
+ }
32
+ interface RenderAppPageHtmlStreamWithRecoveryOptions<TSpecialError> {
33
+ onShellRendered?: () => void;
34
+ renderErrorBoundaryResponse: (error: unknown) => Promise<Response | null>;
35
+ renderHtmlStream: () => Promise<ReadableStream<Uint8Array>>;
36
+ renderSpecialErrorResponse: (specialError: TSpecialError) => Promise<Response>;
37
+ resolveSpecialError: (error: unknown) => TSpecialError | null;
38
+ }
39
+ interface AppPageRscErrorTracker {
40
+ getCapturedError: () => unknown;
41
+ onRenderError: (error: unknown, requestInfo: unknown, errorContext: unknown) => unknown;
42
+ }
43
+ interface ShouldRerenderAppPageWithGlobalErrorOptions {
44
+ capturedError: unknown;
45
+ hasLocalBoundary: boolean;
46
+ }
47
+ declare function createAppPageFontData(options: CreateAppPageFontDataOptions): AppPageFontData;
48
+ declare function renderAppPageHtmlStream(options: RenderAppPageHtmlStreamOptions): Promise<ReadableStream<Uint8Array>>;
49
+ declare function renderAppPageHtmlResponse(options: RenderAppPageHtmlResponseOptions): Promise<Response>;
50
+ declare function renderAppPageHtmlStreamWithRecovery<TSpecialError>(options: RenderAppPageHtmlStreamWithRecoveryOptions<TSpecialError>): Promise<AppPageHtmlStreamRecoveryResult>;
51
+ declare function createAppPageRscErrorTracker(baseOnError: (error: unknown, requestInfo: unknown, errorContext: unknown) => unknown): AppPageRscErrorTracker;
52
+ declare function shouldRerenderAppPageWithGlobalError(options: ShouldRerenderAppPageWithGlobalErrorOptions): boolean;
53
+ //#endregion
54
+ export { AppPageFontData, AppPageHtmlStreamRecoveryResult, AppPageRscErrorTracker, AppPageSsrHandler, CreateAppPageFontDataOptions, RenderAppPageHtmlResponseOptions, RenderAppPageHtmlStreamOptions, RenderAppPageHtmlStreamWithRecoveryOptions, ShouldRerenderAppPageWithGlobalErrorOptions, createAppPageFontData, createAppPageRscErrorTracker, renderAppPageHtmlResponse, renderAppPageHtmlStream, renderAppPageHtmlStreamWithRecovery, shouldRerenderAppPageWithGlobalError };
55
+ //# sourceMappingURL=app-page-stream.d.ts.map
@@ -0,0 +1,65 @@
1
+ //#region src/server/app-page-stream.ts
2
+ function createAppPageFontData(options) {
3
+ return {
4
+ links: options.getLinks(),
5
+ preloads: options.getPreloads(),
6
+ styles: options.getStyles()
7
+ };
8
+ }
9
+ async function renderAppPageHtmlStream(options) {
10
+ return options.ssrHandler.handleSsr(options.rscStream, options.navigationContext, options.fontData);
11
+ }
12
+ async function renderAppPageHtmlResponse(options) {
13
+ const htmlStream = await renderAppPageHtmlStream(options);
14
+ options.clearRequestContext();
15
+ const headers = {
16
+ "Content-Type": "text/html; charset=utf-8",
17
+ Vary: "RSC, Accept"
18
+ };
19
+ if (options.fontLinkHeader) headers.Link = options.fontLinkHeader;
20
+ return new Response(htmlStream, {
21
+ status: options.status,
22
+ headers
23
+ });
24
+ }
25
+ async function renderAppPageHtmlStreamWithRecovery(options) {
26
+ try {
27
+ const htmlStream = await options.renderHtmlStream();
28
+ options.onShellRendered?.();
29
+ return {
30
+ htmlStream,
31
+ response: null
32
+ };
33
+ } catch (error) {
34
+ const specialError = options.resolveSpecialError(error);
35
+ if (specialError) return {
36
+ htmlStream: null,
37
+ response: await options.renderSpecialErrorResponse(specialError)
38
+ };
39
+ const boundaryResponse = await options.renderErrorBoundaryResponse(error);
40
+ if (boundaryResponse) return {
41
+ htmlStream: null,
42
+ response: boundaryResponse
43
+ };
44
+ throw error;
45
+ }
46
+ }
47
+ function createAppPageRscErrorTracker(baseOnError) {
48
+ let capturedError = null;
49
+ return {
50
+ getCapturedError() {
51
+ return capturedError;
52
+ },
53
+ onRenderError(error, requestInfo, errorContext) {
54
+ if (!(error && typeof error === "object" && "digest" in error)) capturedError = error;
55
+ return baseOnError(error, requestInfo, errorContext);
56
+ }
57
+ };
58
+ }
59
+ function shouldRerenderAppPageWithGlobalError(options) {
60
+ return Boolean(options.capturedError) && !options.hasLocalBoundary;
61
+ }
62
+ //#endregion
63
+ export { createAppPageFontData, createAppPageRscErrorTracker, renderAppPageHtmlResponse, renderAppPageHtmlStream, renderAppPageHtmlStreamWithRecovery, shouldRerenderAppPageWithGlobalError };
64
+
65
+ //# sourceMappingURL=app-page-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-page-stream.js","names":[],"sources":["../../src/server/app-page-stream.ts"],"sourcesContent":["import type { AppPageFontPreload } from \"./app-page-execution.js\";\n\nexport interface AppPageFontData {\n links: string[];\n preloads: readonly AppPageFontPreload[];\n styles: string[];\n}\n\nexport interface CreateAppPageFontDataOptions {\n getLinks: () => string[];\n getPreloads: () => AppPageFontPreload[];\n getStyles: () => string[];\n}\n\nexport interface AppPageSsrHandler {\n handleSsr: (\n rscStream: ReadableStream<Uint8Array>,\n navigationContext: unknown,\n fontData: AppPageFontData,\n ) => Promise<ReadableStream<Uint8Array>>;\n}\n\nexport interface RenderAppPageHtmlStreamOptions {\n fontData: AppPageFontData;\n navigationContext: unknown;\n rscStream: ReadableStream<Uint8Array>;\n ssrHandler: AppPageSsrHandler;\n}\n\nexport interface RenderAppPageHtmlResponseOptions extends RenderAppPageHtmlStreamOptions {\n clearRequestContext: () => void;\n fontLinkHeader?: string;\n status: number;\n}\n\nexport interface AppPageHtmlStreamRecoveryResult {\n htmlStream: ReadableStream<Uint8Array> | null;\n response: Response | null;\n}\n\nexport interface RenderAppPageHtmlStreamWithRecoveryOptions<TSpecialError> {\n onShellRendered?: () => void;\n renderErrorBoundaryResponse: (error: unknown) => Promise<Response | null>;\n renderHtmlStream: () => Promise<ReadableStream<Uint8Array>>;\n renderSpecialErrorResponse: (specialError: TSpecialError) => Promise<Response>;\n resolveSpecialError: (error: unknown) => TSpecialError | null;\n}\n\nexport interface AppPageRscErrorTracker {\n getCapturedError: () => unknown;\n onRenderError: (error: unknown, requestInfo: unknown, errorContext: unknown) => unknown;\n}\n\nexport interface ShouldRerenderAppPageWithGlobalErrorOptions {\n capturedError: unknown;\n hasLocalBoundary: boolean;\n}\n\nexport function createAppPageFontData(options: CreateAppPageFontDataOptions): AppPageFontData {\n return {\n links: options.getLinks(),\n preloads: options.getPreloads(),\n styles: options.getStyles(),\n };\n}\n\nexport async function renderAppPageHtmlStream(\n options: RenderAppPageHtmlStreamOptions,\n): Promise<ReadableStream<Uint8Array>> {\n return options.ssrHandler.handleSsr(\n options.rscStream,\n options.navigationContext,\n options.fontData,\n );\n}\n\nexport async function renderAppPageHtmlResponse(\n options: RenderAppPageHtmlResponseOptions,\n): Promise<Response> {\n const htmlStream = await renderAppPageHtmlStream(options);\n options.clearRequestContext();\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"text/html; charset=utf-8\",\n Vary: \"RSC, Accept\",\n };\n\n if (options.fontLinkHeader) {\n headers.Link = options.fontLinkHeader;\n }\n\n return new Response(htmlStream, {\n status: options.status,\n headers,\n });\n}\n\nexport async function renderAppPageHtmlStreamWithRecovery<TSpecialError>(\n options: RenderAppPageHtmlStreamWithRecoveryOptions<TSpecialError>,\n): Promise<AppPageHtmlStreamRecoveryResult> {\n try {\n const htmlStream = await options.renderHtmlStream();\n options.onShellRendered?.();\n return {\n htmlStream,\n response: null,\n };\n } catch (error) {\n const specialError = options.resolveSpecialError(error);\n if (specialError) {\n return {\n htmlStream: null,\n response: await options.renderSpecialErrorResponse(specialError),\n };\n }\n\n const boundaryResponse = await options.renderErrorBoundaryResponse(error);\n if (boundaryResponse) {\n return {\n htmlStream: null,\n response: boundaryResponse,\n };\n }\n\n throw error;\n }\n}\n\nexport function createAppPageRscErrorTracker(\n baseOnError: (error: unknown, requestInfo: unknown, errorContext: unknown) => unknown,\n): AppPageRscErrorTracker {\n let capturedError: unknown = null;\n\n return {\n getCapturedError() {\n return capturedError;\n },\n onRenderError(error, requestInfo, errorContext) {\n if (!(error && typeof error === \"object\" && \"digest\" in error)) {\n capturedError = error;\n }\n return baseOnError(error, requestInfo, errorContext);\n },\n };\n}\n\nexport function shouldRerenderAppPageWithGlobalError(\n options: ShouldRerenderAppPageWithGlobalErrorOptions,\n): boolean {\n return Boolean(options.capturedError) && !options.hasLocalBoundary;\n}\n"],"mappings":";AA0DA,SAAgB,sBAAsB,SAAwD;AAC5F,QAAO;EACL,OAAO,QAAQ,UAAU;EACzB,UAAU,QAAQ,aAAa;EAC/B,QAAQ,QAAQ,WAAW;EAC5B;;AAGH,eAAsB,wBACpB,SACqC;AACrC,QAAO,QAAQ,WAAW,UACxB,QAAQ,WACR,QAAQ,mBACR,QAAQ,SACT;;AAGH,eAAsB,0BACpB,SACmB;CACnB,MAAM,aAAa,MAAM,wBAAwB,QAAQ;AACzD,SAAQ,qBAAqB;CAE7B,MAAM,UAAkC;EACtC,gBAAgB;EAChB,MAAM;EACP;AAED,KAAI,QAAQ,eACV,SAAQ,OAAO,QAAQ;AAGzB,QAAO,IAAI,SAAS,YAAY;EAC9B,QAAQ,QAAQ;EAChB;EACD,CAAC;;AAGJ,eAAsB,oCACpB,SAC0C;AAC1C,KAAI;EACF,MAAM,aAAa,MAAM,QAAQ,kBAAkB;AACnD,UAAQ,mBAAmB;AAC3B,SAAO;GACL;GACA,UAAU;GACX;UACM,OAAO;EACd,MAAM,eAAe,QAAQ,oBAAoB,MAAM;AACvD,MAAI,aACF,QAAO;GACL,YAAY;GACZ,UAAU,MAAM,QAAQ,2BAA2B,aAAa;GACjE;EAGH,MAAM,mBAAmB,MAAM,QAAQ,4BAA4B,MAAM;AACzE,MAAI,iBACF,QAAO;GACL,YAAY;GACZ,UAAU;GACX;AAGH,QAAM;;;AAIV,SAAgB,6BACd,aACwB;CACxB,IAAI,gBAAyB;AAE7B,QAAO;EACL,mBAAmB;AACjB,UAAO;;EAET,cAAc,OAAO,aAAa,cAAc;AAC9C,OAAI,EAAE,SAAS,OAAO,UAAU,YAAY,YAAY,OACtD,iBAAgB;AAElB,UAAO,YAAY,OAAO,aAAa,aAAa;;EAEvD;;AAGH,SAAgB,qCACd,SACS;AACT,QAAO,QAAQ,QAAQ,cAAc,IAAI,CAAC,QAAQ"}
@@ -6,7 +6,7 @@ import { safeJsonStringify } from "./html.js";
6
6
  * the HTML spec requires as="style" for <link rel="preload">.
7
7
  */
8
8
  function fixFlightHints(text) {
9
- return text.replace(/(\d+:HL\[.*?),"stylesheet"(\]|,)/g, "$1,\"style\"$2");
9
+ return text.replace(/(\d*:HL\[.*?),"stylesheet"(\]|,)/g, "$1,\"style\"$2");
10
10
  }
11
11
  /**
12
12
  * Create a helper that progressively embeds RSC chunks as inline <script> tags.
@@ -1 +1 @@
1
- {"version":3,"file":"app-ssr-stream.js","names":[],"sources":["../../src/server/app-ssr-stream.ts"],"sourcesContent":["import { safeJsonStringify } from \"./html.js\";\n\nexport interface RscEmbedTransform {\n flush(): string;\n finalize(): Promise<string>;\n}\n\n/**\n * Fix invalid preload \"as\" values in RSC Flight hint lines before they reach\n * the client. React Flight emits HL hints with as=\"stylesheet\" for CSS, but\n * the HTML spec requires as=\"style\" for <link rel=\"preload\">.\n */\nexport function fixFlightHints(text: string): string {\n return text.replace(/(\\d+:HL\\[.*?),\"stylesheet\"(\\]|,)/g, '$1,\"style\"$2');\n}\n\n/**\n * Create a helper that progressively embeds RSC chunks as inline <script> tags.\n * The browser entry turns the embedded text chunks back into Uint8Array data.\n */\nexport function createRscEmbedTransform(\n embedStream: ReadableStream<Uint8Array>,\n): RscEmbedTransform {\n const reader = embedStream.getReader();\n const decoder = new TextDecoder();\n let pendingChunks: string[] = [];\n let reading = false;\n\n async function pumpReader(): Promise<void> {\n if (reading) return;\n reading = true;\n try {\n while (true) {\n const result = await reader.read();\n if (result.done) break;\n const text = decoder.decode(result.value, { stream: true });\n // The RSC entry already fixes HL hints at the source. Keep this second\n // pass as defense in depth for any embed stream that bypasses that\n // wrapper; the rewrite is idempotent, so double-application is safe.\n pendingChunks.push(fixFlightHints(text));\n }\n } catch (error) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\"[vinext] RSC embed stream read error:\", error);\n }\n } finally {\n reading = false;\n }\n }\n\n const pumpPromise = pumpReader();\n\n return {\n flush(): string {\n if (pendingChunks.length === 0) return \"\";\n\n const chunks = pendingChunks;\n pendingChunks = [];\n\n let scripts = \"\";\n for (const chunk of chunks) {\n scripts +=\n \"<script>self.__VINEXT_RSC_CHUNKS__=self.__VINEXT_RSC_CHUNKS__||[];self.__VINEXT_RSC_CHUNKS__.push(\" +\n safeJsonStringify(chunk) +\n \")</script>\";\n }\n return scripts;\n },\n\n async finalize(): Promise<string> {\n await pumpPromise;\n let scripts = this.flush();\n scripts += \"<script>self.__VINEXT_RSC_DONE__=true</script>\";\n return scripts;\n },\n };\n}\n\n/**\n * Fix invalid preload \"as\" values in server-rendered HTML.\n * React Fizz emits <link rel=\"preload\" as=\"stylesheet\"> for CSS, but the\n * HTML spec requires as=\"style\" for <link rel=\"preload\">.\n */\nexport function fixPreloadAs(html: string): string {\n return html.replace(/<link(?=[^>]*\\srel=\"preload\")[^>]*>/g, (tag) => {\n return tag.replace(' as=\"stylesheet\"', ' as=\"style\"');\n });\n}\n\n/**\n * Create the tick-buffered HTML transform that injects RSC scripts between\n * React Fizz flush cycles without corrupting split HTML chunks.\n */\nexport function createTickBufferedTransform(\n rscEmbed: RscEmbedTransform,\n injectHTML = \"\",\n): TransformStream<Uint8Array, Uint8Array> {\n const decoder = new TextDecoder();\n const encoder = new TextEncoder();\n let injected = false;\n let buffered: string[] = [];\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const flushBuffered = (controller: TransformStreamDefaultController<Uint8Array>): void => {\n for (const chunk of buffered) {\n if (!injected) {\n const headEnd = chunk.indexOf(\"</head>\");\n if (headEnd !== -1) {\n const before = chunk.slice(0, headEnd);\n const after = chunk.slice(headEnd);\n controller.enqueue(encoder.encode(before + injectHTML + after));\n injected = true;\n continue;\n }\n }\n controller.enqueue(encoder.encode(chunk));\n }\n buffered = [];\n };\n\n return new TransformStream<Uint8Array, Uint8Array>({\n transform(chunk, controller) {\n buffered.push(fixPreloadAs(decoder.decode(chunk, { stream: true })));\n\n if (timeoutId !== null) return;\n\n timeoutId = setTimeout(() => {\n flushBuffered(controller);\n\n const rscScripts = rscEmbed.flush();\n if (rscScripts) {\n controller.enqueue(encoder.encode(rscScripts));\n }\n\n timeoutId = null;\n }, 0);\n },\n\n async flush(controller) {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n flushBuffered(controller);\n\n if (!injected && injectHTML) {\n controller.enqueue(encoder.encode(injectHTML));\n }\n\n const finalScripts = await rscEmbed.finalize();\n if (finalScripts) {\n controller.enqueue(encoder.encode(finalScripts));\n }\n },\n });\n}\n"],"mappings":";;;;;;;AAYA,SAAgB,eAAe,MAAsB;AACnD,QAAO,KAAK,QAAQ,qCAAqC,iBAAe;;;;;;AAO1E,SAAgB,wBACd,aACmB;CACnB,MAAM,SAAS,YAAY,WAAW;CACtC,MAAM,UAAU,IAAI,aAAa;CACjC,IAAI,gBAA0B,EAAE;CAChC,IAAI,UAAU;CAEd,eAAe,aAA4B;AACzC,MAAI,QAAS;AACb,YAAU;AACV,MAAI;AACF,UAAO,MAAM;IACX,MAAM,SAAS,MAAM,OAAO,MAAM;AAClC,QAAI,OAAO,KAAM;IACjB,MAAM,OAAO,QAAQ,OAAO,OAAO,OAAO,EAAE,QAAQ,MAAM,CAAC;AAI3D,kBAAc,KAAK,eAAe,KAAK,CAAC;;WAEnC,OAAO;AACd,OAAI,QAAQ,IAAI,aAAa,aAC3B,SAAQ,KAAK,yCAAyC,MAAM;YAEtD;AACR,aAAU;;;CAId,MAAM,cAAc,YAAY;AAEhC,QAAO;EACL,QAAgB;AACd,OAAI,cAAc,WAAW,EAAG,QAAO;GAEvC,MAAM,SAAS;AACf,mBAAgB,EAAE;GAElB,IAAI,UAAU;AACd,QAAK,MAAM,SAAS,OAClB,YACE,uGACA,kBAAkB,MAAM,GACxB;AAEJ,UAAO;;EAGT,MAAM,WAA4B;AAChC,SAAM;GACN,IAAI,UAAU,KAAK,OAAO;AAC1B,cAAW;AACX,UAAO;;EAEV;;;;;;;AAQH,SAAgB,aAAa,MAAsB;AACjD,QAAO,KAAK,QAAQ,yCAAyC,QAAQ;AACnE,SAAO,IAAI,QAAQ,sBAAoB,gBAAc;GACrD;;;;;;AAOJ,SAAgB,4BACd,UACA,aAAa,IAC4B;CACzC,MAAM,UAAU,IAAI,aAAa;CACjC,MAAM,UAAU,IAAI,aAAa;CACjC,IAAI,WAAW;CACf,IAAI,WAAqB,EAAE;CAC3B,IAAI,YAAkD;CAEtD,MAAM,iBAAiB,eAAmE;AACxF,OAAK,MAAM,SAAS,UAAU;AAC5B,OAAI,CAAC,UAAU;IACb,MAAM,UAAU,MAAM,QAAQ,UAAU;AACxC,QAAI,YAAY,IAAI;KAClB,MAAM,SAAS,MAAM,MAAM,GAAG,QAAQ;KACtC,MAAM,QAAQ,MAAM,MAAM,QAAQ;AAClC,gBAAW,QAAQ,QAAQ,OAAO,SAAS,aAAa,MAAM,CAAC;AAC/D,gBAAW;AACX;;;AAGJ,cAAW,QAAQ,QAAQ,OAAO,MAAM,CAAC;;AAE3C,aAAW,EAAE;;AAGf,QAAO,IAAI,gBAAwC;EACjD,UAAU,OAAO,YAAY;AAC3B,YAAS,KAAK,aAAa,QAAQ,OAAO,OAAO,EAAE,QAAQ,MAAM,CAAC,CAAC,CAAC;AAEpE,OAAI,cAAc,KAAM;AAExB,eAAY,iBAAiB;AAC3B,kBAAc,WAAW;IAEzB,MAAM,aAAa,SAAS,OAAO;AACnC,QAAI,WACF,YAAW,QAAQ,QAAQ,OAAO,WAAW,CAAC;AAGhD,gBAAY;MACX,EAAE;;EAGP,MAAM,MAAM,YAAY;AACtB,OAAI,cAAc,MAAM;AACtB,iBAAa,UAAU;AACvB,gBAAY;;AAGd,iBAAc,WAAW;AAEzB,OAAI,CAAC,YAAY,WACf,YAAW,QAAQ,QAAQ,OAAO,WAAW,CAAC;GAGhD,MAAM,eAAe,MAAM,SAAS,UAAU;AAC9C,OAAI,aACF,YAAW,QAAQ,QAAQ,OAAO,aAAa,CAAC;;EAGrD,CAAC"}
1
+ {"version":3,"file":"app-ssr-stream.js","names":[],"sources":["../../src/server/app-ssr-stream.ts"],"sourcesContent":["import { safeJsonStringify } from \"./html.js\";\n\nexport interface RscEmbedTransform {\n flush(): string;\n finalize(): Promise<string>;\n}\n\n/**\n * Fix invalid preload \"as\" values in RSC Flight hint lines before they reach\n * the client. React Flight emits HL hints with as=\"stylesheet\" for CSS, but\n * the HTML spec requires as=\"style\" for <link rel=\"preload\">.\n */\nexport function fixFlightHints(text: string): string {\n return text.replace(/(\\d*:HL\\[.*?),\"stylesheet\"(\\]|,)/g, '$1,\"style\"$2');\n}\n\n/**\n * Create a helper that progressively embeds RSC chunks as inline <script> tags.\n * The browser entry turns the embedded text chunks back into Uint8Array data.\n */\nexport function createRscEmbedTransform(\n embedStream: ReadableStream<Uint8Array>,\n): RscEmbedTransform {\n const reader = embedStream.getReader();\n const decoder = new TextDecoder();\n let pendingChunks: string[] = [];\n let reading = false;\n\n async function pumpReader(): Promise<void> {\n if (reading) return;\n reading = true;\n try {\n while (true) {\n const result = await reader.read();\n if (result.done) break;\n const text = decoder.decode(result.value, { stream: true });\n // The RSC entry already fixes HL hints at the source. Keep this second\n // pass as defense in depth for any embed stream that bypasses that\n // wrapper; the rewrite is idempotent, so double-application is safe.\n pendingChunks.push(fixFlightHints(text));\n }\n } catch (error) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\"[vinext] RSC embed stream read error:\", error);\n }\n } finally {\n reading = false;\n }\n }\n\n const pumpPromise = pumpReader();\n\n return {\n flush(): string {\n if (pendingChunks.length === 0) return \"\";\n\n const chunks = pendingChunks;\n pendingChunks = [];\n\n let scripts = \"\";\n for (const chunk of chunks) {\n scripts +=\n \"<script>self.__VINEXT_RSC_CHUNKS__=self.__VINEXT_RSC_CHUNKS__||[];self.__VINEXT_RSC_CHUNKS__.push(\" +\n safeJsonStringify(chunk) +\n \")</script>\";\n }\n return scripts;\n },\n\n async finalize(): Promise<string> {\n await pumpPromise;\n let scripts = this.flush();\n scripts += \"<script>self.__VINEXT_RSC_DONE__=true</script>\";\n return scripts;\n },\n };\n}\n\n/**\n * Fix invalid preload \"as\" values in server-rendered HTML.\n * React Fizz emits <link rel=\"preload\" as=\"stylesheet\"> for CSS, but the\n * HTML spec requires as=\"style\" for <link rel=\"preload\">.\n */\nexport function fixPreloadAs(html: string): string {\n return html.replace(/<link(?=[^>]*\\srel=\"preload\")[^>]*>/g, (tag) => {\n return tag.replace(' as=\"stylesheet\"', ' as=\"style\"');\n });\n}\n\n/**\n * Create the tick-buffered HTML transform that injects RSC scripts between\n * React Fizz flush cycles without corrupting split HTML chunks.\n */\nexport function createTickBufferedTransform(\n rscEmbed: RscEmbedTransform,\n injectHTML = \"\",\n): TransformStream<Uint8Array, Uint8Array> {\n const decoder = new TextDecoder();\n const encoder = new TextEncoder();\n let injected = false;\n let buffered: string[] = [];\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const flushBuffered = (controller: TransformStreamDefaultController<Uint8Array>): void => {\n for (const chunk of buffered) {\n if (!injected) {\n const headEnd = chunk.indexOf(\"</head>\");\n if (headEnd !== -1) {\n const before = chunk.slice(0, headEnd);\n const after = chunk.slice(headEnd);\n controller.enqueue(encoder.encode(before + injectHTML + after));\n injected = true;\n continue;\n }\n }\n controller.enqueue(encoder.encode(chunk));\n }\n buffered = [];\n };\n\n return new TransformStream<Uint8Array, Uint8Array>({\n transform(chunk, controller) {\n buffered.push(fixPreloadAs(decoder.decode(chunk, { stream: true })));\n\n if (timeoutId !== null) return;\n\n timeoutId = setTimeout(() => {\n flushBuffered(controller);\n\n const rscScripts = rscEmbed.flush();\n if (rscScripts) {\n controller.enqueue(encoder.encode(rscScripts));\n }\n\n timeoutId = null;\n }, 0);\n },\n\n async flush(controller) {\n if (timeoutId !== null) {\n clearTimeout(timeoutId);\n timeoutId = null;\n }\n\n flushBuffered(controller);\n\n if (!injected && injectHTML) {\n controller.enqueue(encoder.encode(injectHTML));\n }\n\n const finalScripts = await rscEmbed.finalize();\n if (finalScripts) {\n controller.enqueue(encoder.encode(finalScripts));\n }\n },\n });\n}\n"],"mappings":";;;;;;;AAYA,SAAgB,eAAe,MAAsB;AACnD,QAAO,KAAK,QAAQ,qCAAqC,iBAAe;;;;;;AAO1E,SAAgB,wBACd,aACmB;CACnB,MAAM,SAAS,YAAY,WAAW;CACtC,MAAM,UAAU,IAAI,aAAa;CACjC,IAAI,gBAA0B,EAAE;CAChC,IAAI,UAAU;CAEd,eAAe,aAA4B;AACzC,MAAI,QAAS;AACb,YAAU;AACV,MAAI;AACF,UAAO,MAAM;IACX,MAAM,SAAS,MAAM,OAAO,MAAM;AAClC,QAAI,OAAO,KAAM;IACjB,MAAM,OAAO,QAAQ,OAAO,OAAO,OAAO,EAAE,QAAQ,MAAM,CAAC;AAI3D,kBAAc,KAAK,eAAe,KAAK,CAAC;;WAEnC,OAAO;AACd,OAAI,QAAQ,IAAI,aAAa,aAC3B,SAAQ,KAAK,yCAAyC,MAAM;YAEtD;AACR,aAAU;;;CAId,MAAM,cAAc,YAAY;AAEhC,QAAO;EACL,QAAgB;AACd,OAAI,cAAc,WAAW,EAAG,QAAO;GAEvC,MAAM,SAAS;AACf,mBAAgB,EAAE;GAElB,IAAI,UAAU;AACd,QAAK,MAAM,SAAS,OAClB,YACE,uGACA,kBAAkB,MAAM,GACxB;AAEJ,UAAO;;EAGT,MAAM,WAA4B;AAChC,SAAM;GACN,IAAI,UAAU,KAAK,OAAO;AAC1B,cAAW;AACX,UAAO;;EAEV;;;;;;;AAQH,SAAgB,aAAa,MAAsB;AACjD,QAAO,KAAK,QAAQ,yCAAyC,QAAQ;AACnE,SAAO,IAAI,QAAQ,sBAAoB,gBAAc;GACrD;;;;;;AAOJ,SAAgB,4BACd,UACA,aAAa,IAC4B;CACzC,MAAM,UAAU,IAAI,aAAa;CACjC,MAAM,UAAU,IAAI,aAAa;CACjC,IAAI,WAAW;CACf,IAAI,WAAqB,EAAE;CAC3B,IAAI,YAAkD;CAEtD,MAAM,iBAAiB,eAAmE;AACxF,OAAK,MAAM,SAAS,UAAU;AAC5B,OAAI,CAAC,UAAU;IACb,MAAM,UAAU,MAAM,QAAQ,UAAU;AACxC,QAAI,YAAY,IAAI;KAClB,MAAM,SAAS,MAAM,MAAM,GAAG,QAAQ;KACtC,MAAM,QAAQ,MAAM,MAAM,QAAQ;AAClC,gBAAW,QAAQ,QAAQ,OAAO,SAAS,aAAa,MAAM,CAAC;AAC/D,gBAAW;AACX;;;AAGJ,cAAW,QAAQ,QAAQ,OAAO,MAAM,CAAC;;AAE3C,aAAW,EAAE;;AAGf,QAAO,IAAI,gBAAwC;EACjD,UAAU,OAAO,YAAY;AAC3B,YAAS,KAAK,aAAa,QAAQ,OAAO,OAAO,EAAE,QAAQ,MAAM,CAAC,CAAC,CAAC;AAEpE,OAAI,cAAc,KAAM;AAExB,eAAY,iBAAiB;AAC3B,kBAAc,WAAW;IAEzB,MAAM,aAAa,SAAS,OAAO;AACnC,QAAI,WACF,YAAW,QAAQ,QAAQ,OAAO,WAAW,CAAC;AAGhD,gBAAY;MACX,EAAE;;EAGP,MAAM,MAAM,YAAY;AACtB,OAAI,cAAc,MAAM;AACtB,iBAAa,UAAU;AACvB,gBAAY;;AAGd,iBAAc,WAAW;AAEzB,OAAI,CAAC,YAAY,WACf,YAAW,QAAQ,QAAQ,OAAO,WAAW,CAAC;GAGhD,MAAM,eAAe,MAAM,SAAS,UAAU;AAC9C,OAAI,aACF,YAAW,QAAQ,QAAQ,OAAO,aAAa,CAAC;;EAGrD,CAAC"}
@@ -27,6 +27,13 @@ declare function negotiateEncoding(req: IncomingMessage): "br" | "gzip" | "defla
27
27
  * to preserve multiple Set-Cookie values instead of flattening them.
28
28
  */
29
29
  declare function mergeResponseHeaders(middlewareHeaders: Record<string, string | string[]>, response: Response): Record<string, string | string[]>;
30
+ /**
31
+ * Merge middleware/config headers and an optional status override into a new
32
+ * Web Response while preserving the original body stream when allowed.
33
+ * Keep this in sync with server/worker-utils.ts and the generated copy in
34
+ * deploy.ts.
35
+ */
36
+ declare function mergeWebResponse(middlewareHeaders: Record<string, string | string[]>, response: Response, statusOverride?: number): Response;
30
37
  /**
31
38
  * Send a compressed response if the content type is compressible and the
32
39
  * client supports compression. Otherwise send uncompressed.
@@ -63,6 +70,11 @@ declare const trustProxy: boolean;
63
70
  * the result here so the downstream RSC handler doesn't re-normalize).
64
71
  */
65
72
  declare function nodeToWebRequest(req: IncomingMessage, urlOverride?: string): Request;
73
+ /**
74
+ * Stream a Web Response back to a Node.js ServerResponse.
75
+ * Supports streaming compression for SSR responses.
76
+ */
77
+ declare function sendWebResponse(webResponse: Response, req: IncomingMessage, res: ServerResponse, compress: boolean): Promise<void>;
66
78
  /**
67
79
  * Start the production server.
68
80
  *
@@ -74,5 +86,5 @@ declare function startProdServer(options?: ProdServerOptions): Promise<{
74
86
  port: number;
75
87
  }>;
76
88
  //#endregion
77
- export { COMPRESSIBLE_TYPES, COMPRESS_THRESHOLD, ProdServerOptions, mergeResponseHeaders, negotiateEncoding, nodeToWebRequest, resolveHost, sendCompressed, startProdServer, trustProxy, trustedHosts };
89
+ export { COMPRESSIBLE_TYPES, COMPRESS_THRESHOLD, ProdServerOptions, mergeResponseHeaders, mergeWebResponse, negotiateEncoding, nodeToWebRequest, resolveHost, sendCompressed, sendWebResponse, startProdServer, trustProxy, trustedHosts };
78
90
  //# sourceMappingURL=prod-server.d.ts.map
@@ -75,11 +75,20 @@ function negotiateEncoding(req) {
75
75
  /**
76
76
  * Create a compression stream for the given encoding.
77
77
  */
78
- function createCompressor(encoding) {
78
+ function createCompressor(encoding, mode = "default") {
79
79
  switch (encoding) {
80
- case "br": return zlib.createBrotliCompress({ params: { [zlib.constants.BROTLI_PARAM_QUALITY]: 4 } });
81
- case "gzip": return zlib.createGzip({ level: 6 });
82
- case "deflate": return zlib.createDeflate({ level: 6 });
80
+ case "br": return zlib.createBrotliCompress({
81
+ ...mode === "streaming" ? { flush: zlib.constants.BROTLI_OPERATION_FLUSH } : {},
82
+ params: { [zlib.constants.BROTLI_PARAM_QUALITY]: 4 }
83
+ });
84
+ case "gzip": return zlib.createGzip({
85
+ level: 6,
86
+ ...mode === "streaming" ? { flush: zlib.constants.Z_SYNC_FLUSH } : {}
87
+ });
88
+ case "deflate": return zlib.createDeflate({
89
+ level: 6,
90
+ ...mode === "streaming" ? { flush: zlib.constants.Z_SYNC_FLUSH } : {}
91
+ });
83
92
  }
84
93
  }
85
94
  /**
@@ -100,6 +109,79 @@ function mergeResponseHeaders(middlewareHeaders, response) {
100
109
  }
101
110
  return merged;
102
111
  }
112
+ function toWebHeaders(headersRecord) {
113
+ const headers = new Headers();
114
+ for (const [key, value] of Object.entries(headersRecord)) if (Array.isArray(value)) for (const item of value) headers.append(key, item);
115
+ else headers.set(key, value);
116
+ return headers;
117
+ }
118
+ const NO_BODY_RESPONSE_STATUSES = new Set([
119
+ 204,
120
+ 205,
121
+ 304
122
+ ]);
123
+ function hasHeader(headersRecord, name) {
124
+ const target = name.toLowerCase();
125
+ return Object.keys(headersRecord).some((key) => key.toLowerCase() === target);
126
+ }
127
+ function omitHeadersCaseInsensitive(headersRecord, names) {
128
+ const targets = new Set(names.map((name) => name.toLowerCase()));
129
+ const filtered = {};
130
+ for (const [key, value] of Object.entries(headersRecord)) {
131
+ if (targets.has(key.toLowerCase())) continue;
132
+ filtered[key] = value;
133
+ }
134
+ return filtered;
135
+ }
136
+ function stripHeaders(headersRecord, names) {
137
+ const targets = new Set(names.map((name) => name.toLowerCase()));
138
+ for (const key of Object.keys(headersRecord)) if (targets.has(key.toLowerCase())) delete headersRecord[key];
139
+ }
140
+ function isNoBodyResponseStatus(status) {
141
+ return NO_BODY_RESPONSE_STATUSES.has(status);
142
+ }
143
+ function cancelResponseBody(response) {
144
+ const body = response.body;
145
+ if (!body || body.locked) return;
146
+ body.cancel().catch(() => {});
147
+ }
148
+ function isVinextStreamedHtmlResponse(response) {
149
+ return response.__vinextStreamedHtmlResponse === true;
150
+ }
151
+ /**
152
+ * Merge middleware/config headers and an optional status override into a new
153
+ * Web Response while preserving the original body stream when allowed.
154
+ * Keep this in sync with server/worker-utils.ts and the generated copy in
155
+ * deploy.ts.
156
+ */
157
+ function mergeWebResponse(middlewareHeaders, response, statusOverride) {
158
+ const filteredMiddlewareHeaders = omitHeadersCaseInsensitive(middlewareHeaders, ["content-length"]);
159
+ const status = statusOverride ?? response.status;
160
+ const mergedHeaders = mergeResponseHeaders(filteredMiddlewareHeaders, response);
161
+ const shouldDropBody = isNoBodyResponseStatus(status);
162
+ const shouldStripStreamLength = isVinextStreamedHtmlResponse(response) && hasHeader(mergedHeaders, "content-length");
163
+ if (!Object.keys(filteredMiddlewareHeaders).length && statusOverride === void 0 && !shouldDropBody && !shouldStripStreamLength) return response;
164
+ if (shouldDropBody) {
165
+ cancelResponseBody(response);
166
+ stripHeaders(mergedHeaders, [
167
+ "content-encoding",
168
+ "content-length",
169
+ "content-type",
170
+ "transfer-encoding"
171
+ ]);
172
+ return new Response(null, {
173
+ status,
174
+ statusText: status === response.status ? response.statusText : void 0,
175
+ headers: toWebHeaders(mergedHeaders)
176
+ });
177
+ }
178
+ if (shouldStripStreamLength) stripHeaders(mergedHeaders, ["content-length"]);
179
+ return new Response(response.body, {
180
+ status,
181
+ statusText: status === response.status ? response.statusText : void 0,
182
+ headers: toWebHeaders(mergedHeaders)
183
+ });
184
+ }
103
185
  /**
104
186
  * Send a compressed response if the content type is compressible and the
105
187
  * client supports compression. Otherwise send uncompressed.
@@ -108,6 +190,7 @@ function sendCompressed(req, res, body, contentType, statusCode, extraHeaders =
108
190
  const buf = typeof body === "string" ? Buffer.from(body) : body;
109
191
  const baseType = contentType.split(";")[0].trim();
110
192
  const encoding = compress ? negotiateEncoding(req) : null;
193
+ const headersWithoutBodyHeaders = omitHeadersCaseInsensitive(extraHeaders, ["content-length", "content-type"]);
111
194
  const writeHead = (headers) => {
112
195
  if (statusText) res.writeHead(statusCode, statusText, headers);
113
196
  else res.writeHead(statusCode, headers);
@@ -120,7 +203,7 @@ function sendCompressed(req, res, body, contentType, statusCode, extraHeaders =
120
203
  if (existingVary) varyValue = existingVary.toLowerCase().includes("accept-encoding") ? existingVary : existingVary + ", Accept-Encoding";
121
204
  else varyValue = "Accept-Encoding";
122
205
  writeHead({
123
- ...extraHeaders,
206
+ ...headersWithoutBodyHeaders,
124
207
  "Content-Type": contentType,
125
208
  "Content-Encoding": encoding,
126
209
  Vary: varyValue
@@ -128,9 +211,8 @@ function sendCompressed(req, res, body, contentType, statusCode, extraHeaders =
128
211
  compressor.end(buf);
129
212
  pipeline(compressor, res, () => {});
130
213
  } else {
131
- const { "content-length": _cl, "Content-Length": _CL, ...headersWithoutLength } = extraHeaders;
132
214
  writeHead({
133
- ...headersWithoutLength,
215
+ ...headersWithoutBodyHeaders,
134
216
  "Content-Type": contentType,
135
217
  "Content-Length": String(buf.length)
136
218
  });
@@ -308,11 +390,12 @@ async function sendWebResponse(webResponse, req, res, compress) {
308
390
  }
309
391
  writeHead(nodeHeaders);
310
392
  if (req.method === "HEAD") {
393
+ cancelResponseBody(webResponse);
311
394
  res.end();
312
395
  return;
313
396
  }
314
397
  const nodeStream = Readable.fromWeb(webResponse.body);
315
- if (shouldCompress) pipeline(nodeStream, createCompressor(encoding), res, () => {});
398
+ if (shouldCompress) pipeline(nodeStream, createCompressor(encoding, "streaming"), res, () => {});
316
399
  else pipeline(nodeStream, res, () => {});
317
400
  }
318
401
  /**
@@ -698,11 +781,16 @@ async function startPagesRouterServer(options) {
698
781
  let response;
699
782
  if (typeof handleApi === "function") response = await handleApi(webRequest, resolvedUrl);
700
783
  else response = new Response("404 - API route not found", { status: 404 });
701
- const responseBody = Buffer.from(await response.arrayBuffer());
702
- const ct = response.headers.get("content-type") ?? "application/octet-stream";
703
- const responseHeaders = mergeResponseHeaders(middlewareHeaders, response);
704
- const finalStatus = middlewareRewriteStatus ?? response.status;
705
- sendCompressed(req, res, responseBody, ct, finalStatus, responseHeaders, compress, finalStatus === response.status ? response.statusText || void 0 : void 0);
784
+ const mergedResponse = mergeWebResponse(middlewareHeaders, response, middlewareRewriteStatus);
785
+ if (!mergedResponse.body) {
786
+ await sendWebResponse(mergedResponse, req, res, compress);
787
+ return;
788
+ }
789
+ const responseBody = Buffer.from(await mergedResponse.arrayBuffer());
790
+ const ct = mergedResponse.headers.get("content-type") ?? "application/octet-stream";
791
+ const responseHeaders = mergeResponseHeaders({}, mergedResponse);
792
+ const finalStatusText = mergedResponse.statusText || void 0;
793
+ sendCompressed(req, res, responseBody, ct, mergedResponse.status, responseHeaders, compress, finalStatusText);
706
794
  return;
707
795
  }
708
796
  if (configRewrites.afterFiles?.length) {
@@ -735,11 +823,17 @@ async function startPagesRouterServer(options) {
735
823
  res.end("404 - Not found");
736
824
  return;
737
825
  }
738
- const responseBody = Buffer.from(await response.arrayBuffer());
739
- const ct = response.headers.get("content-type") ?? "text/html";
740
- const responseHeaders = mergeResponseHeaders(middlewareHeaders, response);
741
- const finalStatus = middlewareRewriteStatus ?? response.status;
742
- sendCompressed(req, res, responseBody, ct, finalStatus, responseHeaders, compress, finalStatus === response.status ? response.statusText || void 0 : void 0);
826
+ const shouldStreamPagesResponse = isVinextStreamedHtmlResponse(response);
827
+ const mergedResponse = mergeWebResponse(middlewareHeaders, response, middlewareRewriteStatus);
828
+ if (shouldStreamPagesResponse || !mergedResponse.body) {
829
+ await sendWebResponse(mergedResponse, req, res, compress);
830
+ return;
831
+ }
832
+ const responseBody = Buffer.from(await mergedResponse.arrayBuffer());
833
+ const ct = mergedResponse.headers.get("content-type") ?? "text/html";
834
+ const responseHeaders = mergeResponseHeaders({}, mergedResponse);
835
+ const finalStatusText = mergedResponse.statusText || void 0;
836
+ sendCompressed(req, res, responseBody, ct, mergedResponse.status, responseHeaders, compress, finalStatusText);
743
837
  } catch (e) {
744
838
  console.error("[vinext] Server error:", e);
745
839
  if (!res.headersSent) {
@@ -763,6 +857,6 @@ async function startPagesRouterServer(options) {
763
857
  };
764
858
  }
765
859
  //#endregion
766
- export { COMPRESSIBLE_TYPES, COMPRESS_THRESHOLD, mergeResponseHeaders, negotiateEncoding, nodeToWebRequest, resolveHost, sendCompressed, startProdServer, trustProxy, trustedHosts };
860
+ export { COMPRESSIBLE_TYPES, COMPRESS_THRESHOLD, mergeResponseHeaders, mergeWebResponse, negotiateEncoding, nodeToWebRequest, resolveHost, sendCompressed, sendWebResponse, startProdServer, trustProxy, trustedHosts };
767
861
 
768
862
  //# sourceMappingURL=prod-server.js.map