vinext 0.0.26 → 0.0.28

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 (227) hide show
  1. package/README.md +89 -85
  2. package/dist/build/static-export.d.ts +1 -1
  3. package/dist/build/static-export.d.ts.map +1 -1
  4. package/dist/build/static-export.js +5 -9
  5. package/dist/build/static-export.js.map +1 -1
  6. package/dist/check.d.ts.map +1 -1
  7. package/dist/check.js +152 -48
  8. package/dist/check.js.map +1 -1
  9. package/dist/cli.js +10 -11
  10. package/dist/cli.js.map +1 -1
  11. package/dist/cloudflare/kv-cache-handler.d.ts +43 -1
  12. package/dist/cloudflare/kv-cache-handler.d.ts.map +1 -1
  13. package/dist/cloudflare/kv-cache-handler.js +135 -44
  14. package/dist/cloudflare/kv-cache-handler.js.map +1 -1
  15. package/dist/cloudflare/tpr.d.ts.map +1 -1
  16. package/dist/cloudflare/tpr.js +15 -4
  17. package/dist/cloudflare/tpr.js.map +1 -1
  18. package/dist/config/config-matchers.d.ts +28 -0
  19. package/dist/config/config-matchers.d.ts.map +1 -1
  20. package/dist/config/config-matchers.js +353 -79
  21. package/dist/config/config-matchers.js.map +1 -1
  22. package/dist/config/dotenv.d.ts.map +1 -1
  23. package/dist/config/dotenv.js +1 -6
  24. package/dist/config/dotenv.js.map +1 -1
  25. package/dist/config/next-config.d.ts +7 -0
  26. package/dist/config/next-config.d.ts.map +1 -1
  27. package/dist/config/next-config.js +44 -19
  28. package/dist/config/next-config.js.map +1 -1
  29. package/dist/deploy.d.ts +1 -1
  30. package/dist/deploy.d.ts.map +1 -1
  31. package/dist/deploy.js +81 -48
  32. package/dist/deploy.js.map +1 -1
  33. package/dist/entries/app-rsc-entry.d.ts +3 -1
  34. package/dist/entries/app-rsc-entry.d.ts.map +1 -1
  35. package/dist/entries/app-rsc-entry.js +584 -113
  36. package/dist/entries/app-rsc-entry.js.map +1 -1
  37. package/dist/entries/pages-client-entry.d.ts.map +1 -1
  38. package/dist/entries/pages-client-entry.js +5 -3
  39. package/dist/entries/pages-client-entry.js.map +1 -1
  40. package/dist/entries/pages-server-entry.d.ts.map +1 -1
  41. package/dist/entries/pages-server-entry.js +100 -32
  42. package/dist/entries/pages-server-entry.js.map +1 -1
  43. package/dist/index.d.ts +24 -8
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +327 -154
  46. package/dist/index.js.map +1 -1
  47. package/dist/init.d.ts.map +1 -1
  48. package/dist/init.js +6 -5
  49. package/dist/init.js.map +1 -1
  50. package/dist/plugins/client-reference-dedup.d.ts +19 -0
  51. package/dist/plugins/client-reference-dedup.d.ts.map +1 -0
  52. package/dist/plugins/client-reference-dedup.js +96 -0
  53. package/dist/plugins/client-reference-dedup.js.map +1 -0
  54. package/dist/routing/app-router.d.ts +2 -0
  55. package/dist/routing/app-router.d.ts.map +1 -1
  56. package/dist/routing/app-router.js +70 -107
  57. package/dist/routing/app-router.js.map +1 -1
  58. package/dist/routing/file-matcher.d.ts.map +1 -1
  59. package/dist/routing/file-matcher.js.map +1 -1
  60. package/dist/routing/pages-router.d.ts +3 -1
  61. package/dist/routing/pages-router.d.ts.map +1 -1
  62. package/dist/routing/pages-router.js +33 -18
  63. package/dist/routing/pages-router.js.map +1 -1
  64. package/dist/routing/route-validation.d.ts +8 -0
  65. package/dist/routing/route-validation.d.ts.map +1 -0
  66. package/dist/routing/route-validation.js +124 -0
  67. package/dist/routing/route-validation.js.map +1 -0
  68. package/dist/routing/utils.d.ts.map +1 -1
  69. package/dist/routing/utils.js.map +1 -1
  70. package/dist/server/api-handler.d.ts.map +1 -1
  71. package/dist/server/api-handler.js +31 -9
  72. package/dist/server/api-handler.js.map +1 -1
  73. package/dist/server/app-router-entry.d.ts +3 -2
  74. package/dist/server/app-router-entry.d.ts.map +1 -1
  75. package/dist/server/app-router-entry.js +8 -4
  76. package/dist/server/app-router-entry.js.map +1 -1
  77. package/dist/server/dev-module-runner.d.ts.map +1 -1
  78. package/dist/server/dev-module-runner.js +1 -1
  79. package/dist/server/dev-module-runner.js.map +1 -1
  80. package/dist/server/dev-origin-check.d.ts.map +1 -1
  81. package/dist/server/dev-origin-check.js.map +1 -1
  82. package/dist/server/dev-server.d.ts.map +1 -1
  83. package/dist/server/dev-server.js +39 -21
  84. package/dist/server/dev-server.js.map +1 -1
  85. package/dist/server/image-optimization.d.ts.map +1 -1
  86. package/dist/server/image-optimization.js.map +1 -1
  87. package/dist/server/instrumentation.js +1 -1
  88. package/dist/server/instrumentation.js.map +1 -1
  89. package/dist/server/isr-cache.d.ts +5 -1
  90. package/dist/server/isr-cache.d.ts.map +1 -1
  91. package/dist/server/isr-cache.js +13 -3
  92. package/dist/server/isr-cache.js.map +1 -1
  93. package/dist/server/metadata-routes.d.ts +8 -2
  94. package/dist/server/metadata-routes.d.ts.map +1 -1
  95. package/dist/server/metadata-routes.js +78 -45
  96. package/dist/server/metadata-routes.js.map +1 -1
  97. package/dist/server/middleware-codegen.d.ts +1 -1
  98. package/dist/server/middleware-codegen.d.ts.map +1 -1
  99. package/dist/server/middleware-codegen.js +177 -22
  100. package/dist/server/middleware-codegen.js.map +1 -1
  101. package/dist/server/middleware-request-headers.d.ts +9 -0
  102. package/dist/server/middleware-request-headers.d.ts.map +1 -0
  103. package/dist/server/middleware-request-headers.js +77 -0
  104. package/dist/server/middleware-request-headers.js.map +1 -0
  105. package/dist/server/middleware.d.ts +9 -8
  106. package/dist/server/middleware.d.ts.map +1 -1
  107. package/dist/server/middleware.js +112 -32
  108. package/dist/server/middleware.js.map +1 -1
  109. package/dist/server/normalize-path.js.map +1 -1
  110. package/dist/server/prod-server.d.ts +1 -1
  111. package/dist/server/prod-server.d.ts.map +1 -1
  112. package/dist/server/prod-server.js +127 -82
  113. package/dist/server/prod-server.js.map +1 -1
  114. package/dist/server/request-pipeline.d.ts +2 -1
  115. package/dist/server/request-pipeline.d.ts.map +1 -1
  116. package/dist/server/request-pipeline.js +5 -7
  117. package/dist/server/request-pipeline.js.map +1 -1
  118. package/dist/shims/cache-runtime.d.ts.map +1 -1
  119. package/dist/shims/cache-runtime.js +21 -16
  120. package/dist/shims/cache-runtime.js.map +1 -1
  121. package/dist/shims/cache.d.ts +2 -0
  122. package/dist/shims/cache.d.ts.map +1 -1
  123. package/dist/shims/cache.js +38 -25
  124. package/dist/shims/cache.js.map +1 -1
  125. package/dist/shims/constants.d.ts.map +1 -1
  126. package/dist/shims/constants.js +1 -6
  127. package/dist/shims/constants.js.map +1 -1
  128. package/dist/shims/dynamic.d.ts.map +1 -1
  129. package/dist/shims/dynamic.js +1 -1
  130. package/dist/shims/dynamic.js.map +1 -1
  131. package/dist/shims/error-boundary.d.ts.map +1 -1
  132. package/dist/shims/error-boundary.js +2 -3
  133. package/dist/shims/error-boundary.js.map +1 -1
  134. package/dist/shims/error.d.ts.map +1 -1
  135. package/dist/shims/error.js +1 -3
  136. package/dist/shims/error.js.map +1 -1
  137. package/dist/shims/fetch-cache.d.ts.map +1 -1
  138. package/dist/shims/fetch-cache.js +57 -30
  139. package/dist/shims/fetch-cache.js.map +1 -1
  140. package/dist/shims/font-google-base.d.ts.map +1 -1
  141. package/dist/shims/font-google-base.js +16 -4
  142. package/dist/shims/font-google-base.js.map +1 -1
  143. package/dist/shims/font-google.d.ts +1 -1
  144. package/dist/shims/font-google.d.ts.map +1 -1
  145. package/dist/shims/font-google.generated.d.ts.map +1 -1
  146. package/dist/shims/font-google.generated.js +412 -206
  147. package/dist/shims/font-google.generated.js.map +1 -1
  148. package/dist/shims/font-google.js +1 -1
  149. package/dist/shims/font-google.js.map +1 -1
  150. package/dist/shims/font-local.d.ts.map +1 -1
  151. package/dist/shims/font-local.js +13 -3
  152. package/dist/shims/font-local.js.map +1 -1
  153. package/dist/shims/form.d.ts.map +1 -1
  154. package/dist/shims/form.js +105 -10
  155. package/dist/shims/form.js.map +1 -1
  156. package/dist/shims/head.d.ts.map +1 -1
  157. package/dist/shims/head.js +10 -8
  158. package/dist/shims/head.js.map +1 -1
  159. package/dist/shims/headers.d.ts +34 -8
  160. package/dist/shims/headers.d.ts.map +1 -1
  161. package/dist/shims/headers.js +268 -53
  162. package/dist/shims/headers.js.map +1 -1
  163. package/dist/shims/image.d.ts.map +1 -1
  164. package/dist/shims/image.js +35 -8
  165. package/dist/shims/image.js.map +1 -1
  166. package/dist/shims/internal/parse-cookie-header.d.ts +12 -0
  167. package/dist/shims/internal/parse-cookie-header.d.ts.map +1 -0
  168. package/dist/shims/internal/parse-cookie-header.js +32 -0
  169. package/dist/shims/internal/parse-cookie-header.js.map +1 -0
  170. package/dist/shims/legacy-image.d.ts.map +1 -1
  171. package/dist/shims/legacy-image.js +1 -1
  172. package/dist/shims/legacy-image.js.map +1 -1
  173. package/dist/shims/link.d.ts +2 -1
  174. package/dist/shims/link.d.ts.map +1 -1
  175. package/dist/shims/link.js +37 -17
  176. package/dist/shims/link.js.map +1 -1
  177. package/dist/shims/metadata.d.ts +12 -2
  178. package/dist/shims/metadata.d.ts.map +1 -1
  179. package/dist/shims/metadata.js +10 -8
  180. package/dist/shims/metadata.js.map +1 -1
  181. package/dist/shims/navigation-state.d.ts.map +1 -1
  182. package/dist/shims/navigation-state.js +3 -2
  183. package/dist/shims/navigation-state.js.map +1 -1
  184. package/dist/shims/navigation.d.ts +3 -7
  185. package/dist/shims/navigation.d.ts.map +1 -1
  186. package/dist/shims/navigation.js +46 -29
  187. package/dist/shims/navigation.js.map +1 -1
  188. package/dist/shims/readonly-url-search-params.d.ts +11 -0
  189. package/dist/shims/readonly-url-search-params.d.ts.map +1 -0
  190. package/dist/shims/readonly-url-search-params.js +24 -0
  191. package/dist/shims/readonly-url-search-params.js.map +1 -0
  192. package/dist/shims/request-context.d.ts +50 -0
  193. package/dist/shims/request-context.d.ts.map +1 -0
  194. package/dist/shims/request-context.js +59 -0
  195. package/dist/shims/request-context.js.map +1 -0
  196. package/dist/shims/router-state.d.ts.map +1 -1
  197. package/dist/shims/router-state.js +2 -1
  198. package/dist/shims/router-state.js.map +1 -1
  199. package/dist/shims/router.d.ts +4 -3
  200. package/dist/shims/router.d.ts.map +1 -1
  201. package/dist/shims/router.js +59 -53
  202. package/dist/shims/router.js.map +1 -1
  203. package/dist/shims/script.d.ts.map +1 -1
  204. package/dist/shims/script.js.map +1 -1
  205. package/dist/shims/server.d.ts +14 -1
  206. package/dist/shims/server.d.ts.map +1 -1
  207. package/dist/shims/server.js +107 -47
  208. package/dist/shims/server.js.map +1 -1
  209. package/dist/shims/url-utils.d.ts.map +1 -1
  210. package/dist/shims/url-utils.js +1 -3
  211. package/dist/shims/url-utils.js.map +1 -1
  212. package/dist/utils/base-path.d.ts +17 -0
  213. package/dist/utils/base-path.d.ts.map +1 -0
  214. package/dist/utils/base-path.js +25 -0
  215. package/dist/utils/base-path.js.map +1 -0
  216. package/dist/utils/manifest-paths.d.ts +4 -0
  217. package/dist/utils/manifest-paths.d.ts.map +1 -0
  218. package/dist/utils/manifest-paths.js +20 -0
  219. package/dist/utils/manifest-paths.js.map +1 -0
  220. package/dist/utils/project.d.ts.map +1 -1
  221. package/dist/utils/project.js +2 -4
  222. package/dist/utils/project.js.map +1 -1
  223. package/dist/utils/query.d.ts +9 -0
  224. package/dist/utils/query.d.ts.map +1 -1
  225. package/dist/utils/query.js +59 -7
  226. package/dist/utils/query.js.map +1 -1
  227. package/package.json +47 -33
@@ -1 +1 @@
1
- {"version":3,"file":"pages-client-entry.d.ts","sourceRoot":"","sources":["../../src/entries/pages-client-entry.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAGnE,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,kBAAkB,EAC9B,WAAW,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,GACrD,OAAO,CAAC,MAAM,CAAC,CAmFjB"}
1
+ {"version":3,"file":"pages-client-entry.d.ts","sourceRoot":"","sources":["../../src/entries/pages-client-entry.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAGnE,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,kBAAkB,EAC9B,WAAW,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,GACrD,OAAO,CAAC,MAAM,CAAC,CAuFjB"}
@@ -9,7 +9,7 @@
9
9
  *
10
10
  * Extracted from index.ts.
11
11
  */
12
- import { pagesRouter, patternToNextFormat as pagesPatternToNextFormat } from "../routing/pages-router.js";
12
+ import { pagesRouter, patternToNextFormat as pagesPatternToNextFormat, } from "../routing/pages-router.js";
13
13
  import { findFileWithExts } from "./pages-entry-helpers.js";
14
14
  export async function generateClientEntry(pagesDir, nextConfig, fileMatcher) {
15
15
  const pageRoutes = await pagesRouter(pagesDir, nextConfig?.pageExtensions, fileMatcher);
@@ -61,7 +61,8 @@ async function hydrate() {
61
61
  }
62
62
 
63
63
  let element;
64
- ${hasApp ? `
64
+ ${hasApp
65
+ ? `
65
66
  try {
66
67
  const appModule = await import(${JSON.stringify(appFileBase)});
67
68
  const AppComponent = appModule.default;
@@ -70,7 +71,8 @@ async function hydrate() {
70
71
  } catch {
71
72
  element = React.createElement(PageComponent, pageProps);
72
73
  }
73
- ` : `
74
+ `
75
+ : `
74
76
  element = React.createElement(PageComponent, pageProps);
75
77
  `}
76
78
 
@@ -1 +1 @@
1
- {"version":3,"file":"pages-client-entry.js","sourceRoot":"","sources":["../../src/entries/pages-client-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,WAAW,EAAE,mBAAmB,IAAI,wBAAwB,EAAc,MAAM,4BAA4B,CAAC;AAGtH,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAgB,EAChB,UAA8B,EAC9B,WAAsD;IAEtD,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC;IAExF,MAAM,WAAW,GAAG,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;IACpE,MAAM,MAAM,GAAG,WAAW,KAAK,IAAI,CAAC;IAEpC,kDAAkD;IAClD,oEAAoE;IACpE,wEAAwE;IACxE,MAAM,aAAa,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAQ,EAAE,EAAE;QAChD,MAAM,OAAO,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC/C,MAAM,iBAAiB,GAAG,wBAAwB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAC9D,0EAA0E;QAC1E,qDAAqD;QACrD,iCAAiC;QACjC,OAAO,KAAK,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,kBAAkB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC;IAC5F,CAAC,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,WAAW,EAAE,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAErD,OAAO;;;;;;;;;EASP,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;IAyBvB,MAAM,CAAC,CAAC,CAAC;;qCAEwB,IAAI,CAAC,SAAS,CAAC,WAAY,CAAC;;;;;;;GAO9D,CAAC,CAAC,CAAC;;GAEH;;;;;;;;;;;;;;;;;CAiBF,CAAC;AACF,CAAC","sourcesContent":["/**\n * Pages Router client hydration entry generator.\n *\n * Generates the virtual client entry module (`virtual:vinext-client-entry`).\n * This is the entry point for `vite build` (client bundle). It maps route\n * patterns to dynamic imports of page modules so Vite code-splits each page\n * into its own chunk. At runtime it reads __NEXT_DATA__ to determine which\n * page to hydrate.\n *\n * Extracted from index.ts.\n */\nimport { pagesRouter, patternToNextFormat as pagesPatternToNextFormat, type Route } from \"../routing/pages-router.js\";\nimport { createValidFileMatcher } from \"../routing/file-matcher.js\";\nimport { type ResolvedNextConfig } from \"../config/next-config.js\";\nimport { findFileWithExts } from \"./pages-entry-helpers.js\";\n\nexport async function generateClientEntry(\n pagesDir: string,\n nextConfig: ResolvedNextConfig,\n fileMatcher: ReturnType<typeof createValidFileMatcher>,\n): Promise<string> {\n const pageRoutes = await pagesRouter(pagesDir, nextConfig?.pageExtensions, fileMatcher);\n\n const appFilePath = findFileWithExts(pagesDir, \"_app\", fileMatcher);\n const hasApp = appFilePath !== null;\n\n // Build a map of route pattern -> dynamic import.\n // Keys must use Next.js bracket format (e.g. \"/user/[id]\") to match\n // __NEXT_DATA__.page which is set via patternToNextFormat() during SSR.\n const loaderEntries = pageRoutes.map((r: Route) => {\n const absPath = r.filePath.replace(/\\\\/g, \"/\");\n const nextFormatPattern = pagesPatternToNextFormat(r.pattern);\n // JSON.stringify safely escapes quotes, backslashes, and special chars in\n // both the route pattern and the absolute file path.\n // lgtm[js/bad-code-sanitization]\n return ` ${JSON.stringify(nextFormatPattern)}: () => import(${JSON.stringify(absPath)})`;\n });\n\n const appFileBase = appFilePath?.replace(/\\\\/g, \"/\");\n\n return `\nimport React from \"react\";\nimport { hydrateRoot } from \"react-dom/client\";\n// Eagerly import the router shim so its module-level popstate listener is\n// registered. Without this, browser back/forward buttons do nothing because\n// navigateClient() is never invoked on history changes.\nimport \"next/router\";\n\nconst pageLoaders = {\n${loaderEntries.join(\",\\n\")}\n};\n\nasync function hydrate() {\n const nextData = window.__NEXT_DATA__;\n if (!nextData) {\n console.error(\"[vinext] No __NEXT_DATA__ found\");\n return;\n }\n\n const { pageProps } = nextData.props;\n const loader = pageLoaders[nextData.page];\n if (!loader) {\n console.error(\"[vinext] No page loader for route:\", nextData.page);\n return;\n }\n\n const pageModule = await loader();\n const PageComponent = pageModule.default;\n if (!PageComponent) {\n console.error(\"[vinext] Page module has no default export\");\n return;\n }\n\n let element;\n ${hasApp ? `\n try {\n const appModule = await import(${JSON.stringify(appFileBase!)});\n const AppComponent = appModule.default;\n window.__VINEXT_APP__ = AppComponent;\n element = React.createElement(AppComponent, { Component: PageComponent, pageProps });\n } catch {\n element = React.createElement(PageComponent, pageProps);\n }\n ` : `\n element = React.createElement(PageComponent, pageProps);\n `}\n\n // Wrap with RouterContext.Provider so next/compat/router works during hydration\n const { wrapWithRouterContext } = await import(\"next/router\");\n element = wrapWithRouterContext(element);\n\n const container = document.getElementById(\"__next\");\n if (!container) {\n console.error(\"[vinext] No #__next element found\");\n return;\n }\n\n const root = hydrateRoot(container, element);\n window.__VINEXT_ROOT__ = root;\n}\n\nhydrate();\n`;\n}\n"]}
1
+ {"version":3,"file":"pages-client-entry.js","sourceRoot":"","sources":["../../src/entries/pages-client-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EACL,WAAW,EACX,mBAAmB,IAAI,wBAAwB,GAEhD,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAgB,EAChB,UAA8B,EAC9B,WAAsD;IAEtD,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC;IAExF,MAAM,WAAW,GAAG,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;IACpE,MAAM,MAAM,GAAG,WAAW,KAAK,IAAI,CAAC;IAEpC,kDAAkD;IAClD,oEAAoE;IACpE,wEAAwE;IACxE,MAAM,aAAa,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAQ,EAAE,EAAE;QAChD,MAAM,OAAO,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC/C,MAAM,iBAAiB,GAAG,wBAAwB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAC9D,0EAA0E;QAC1E,qDAAqD;QACrD,iCAAiC;QACjC,OAAO,KAAK,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,kBAAkB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC;IAC5F,CAAC,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,WAAW,EAAE,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAErD,OAAO;;;;;;;;;EASP,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;IA0BvB,MAAM;QACJ,CAAC,CAAC;;qCAE6B,IAAI,CAAC,SAAS,CAAC,WAAY,CAAC;;;;;;;GAO9D;QACG,CAAC,CAAC;;GAGN;;;;;;;;;;;;;;;;;CAiBD,CAAC;AACF,CAAC","sourcesContent":["/**\n * Pages Router client hydration entry generator.\n *\n * Generates the virtual client entry module (`virtual:vinext-client-entry`).\n * This is the entry point for `vite build` (client bundle). It maps route\n * patterns to dynamic imports of page modules so Vite code-splits each page\n * into its own chunk. At runtime it reads __NEXT_DATA__ to determine which\n * page to hydrate.\n *\n * Extracted from index.ts.\n */\nimport {\n pagesRouter,\n patternToNextFormat as pagesPatternToNextFormat,\n type Route,\n} from \"../routing/pages-router.js\";\nimport { createValidFileMatcher } from \"../routing/file-matcher.js\";\nimport { type ResolvedNextConfig } from \"../config/next-config.js\";\nimport { findFileWithExts } from \"./pages-entry-helpers.js\";\n\nexport async function generateClientEntry(\n pagesDir: string,\n nextConfig: ResolvedNextConfig,\n fileMatcher: ReturnType<typeof createValidFileMatcher>,\n): Promise<string> {\n const pageRoutes = await pagesRouter(pagesDir, nextConfig?.pageExtensions, fileMatcher);\n\n const appFilePath = findFileWithExts(pagesDir, \"_app\", fileMatcher);\n const hasApp = appFilePath !== null;\n\n // Build a map of route pattern -> dynamic import.\n // Keys must use Next.js bracket format (e.g. \"/user/[id]\") to match\n // __NEXT_DATA__.page which is set via patternToNextFormat() during SSR.\n const loaderEntries = pageRoutes.map((r: Route) => {\n const absPath = r.filePath.replace(/\\\\/g, \"/\");\n const nextFormatPattern = pagesPatternToNextFormat(r.pattern);\n // JSON.stringify safely escapes quotes, backslashes, and special chars in\n // both the route pattern and the absolute file path.\n // lgtm[js/bad-code-sanitization]\n return ` ${JSON.stringify(nextFormatPattern)}: () => import(${JSON.stringify(absPath)})`;\n });\n\n const appFileBase = appFilePath?.replace(/\\\\/g, \"/\");\n\n return `\nimport React from \"react\";\nimport { hydrateRoot } from \"react-dom/client\";\n// Eagerly import the router shim so its module-level popstate listener is\n// registered. Without this, browser back/forward buttons do nothing because\n// navigateClient() is never invoked on history changes.\nimport \"next/router\";\n\nconst pageLoaders = {\n${loaderEntries.join(\",\\n\")}\n};\n\nasync function hydrate() {\n const nextData = window.__NEXT_DATA__;\n if (!nextData) {\n console.error(\"[vinext] No __NEXT_DATA__ found\");\n return;\n }\n\n const { pageProps } = nextData.props;\n const loader = pageLoaders[nextData.page];\n if (!loader) {\n console.error(\"[vinext] No page loader for route:\", nextData.page);\n return;\n }\n\n const pageModule = await loader();\n const PageComponent = pageModule.default;\n if (!PageComponent) {\n console.error(\"[vinext] Page module has no default export\");\n return;\n }\n\n let element;\n ${\n hasApp\n ? `\n try {\n const appModule = await import(${JSON.stringify(appFileBase!)});\n const AppComponent = appModule.default;\n window.__VINEXT_APP__ = AppComponent;\n element = React.createElement(AppComponent, { Component: PageComponent, pageProps });\n } catch {\n element = React.createElement(PageComponent, pageProps);\n }\n `\n : `\n element = React.createElement(PageComponent, pageProps);\n `\n }\n\n // Wrap with RouterContext.Provider so next/compat/router works during hydration\n const { wrapWithRouterContext } = await import(\"next/router\");\n element = wrapWithRouterContext(element);\n\n const container = document.getElementById(\"__next\");\n if (!container) {\n console.error(\"[vinext] No #__next element found\");\n return;\n }\n\n const root = hydrateRoot(container, element);\n window.__VINEXT_ROOT__ = root;\n}\n\nhydrate();\n`;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"pages-server-entry.d.ts","sourceRoot":"","sources":["../../src/entries/pages-server-entry.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAWnE;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,kBAAkB,EAC9B,WAAW,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,EACtD,cAAc,EAAE,MAAM,GAAG,IAAI,EAC7B,mBAAmB,EAAE,MAAM,GAAG,IAAI,GACjC,OAAO,CAAC,MAAM,CAAC,CAy9BjB"}
1
+ {"version":3,"file":"pages-server-entry.d.ts","sourceRoot":"","sources":["../../src/entries/pages-server-entry.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAcnE;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,kBAAkB,EAC9B,WAAW,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,EACtD,cAAc,EAAE,MAAM,GAAG,IAAI,EAC7B,mBAAmB,EAAE,MAAM,GAAG,IAAI,GACjC,OAAO,CAAC,MAAM,CAAC,CA6hCjB"}
@@ -14,6 +14,7 @@ import { isProxyFile } from "../server/middleware.js";
14
14
  import { generateSafeRegExpCode, generateMiddlewareMatcherCode, generateNormalizePathCode, } from "../server/middleware-codegen.js";
15
15
  import { findFileWithExts } from "./pages-entry-helpers.js";
16
16
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
17
+ const _requestContextShimPath = fileURLToPath(new URL("../shims/request-context.js", import.meta.url)).replace(/\\/g, "/");
17
18
  /**
18
19
  * Generate the virtual SSR server entry module.
19
20
  * This is the entry point for `vite build --ssr`.
@@ -34,10 +35,10 @@ export async function generateServerEntry(pagesDir, nextConfig, fileMatcher, mid
34
35
  // Build the route table — include filePath for SSR manifest lookup
35
36
  const pageRouteEntries = pageRoutes.map((r, i) => {
36
37
  const absPath = r.filePath.replace(/\\/g, "/");
37
- return ` { pattern: ${JSON.stringify(r.pattern)}, isDynamic: ${r.isDynamic}, params: ${JSON.stringify(r.params)}, module: page_${i}, filePath: ${JSON.stringify(absPath)} }`;
38
+ return ` { pattern: ${JSON.stringify(r.pattern)}, patternParts: ${JSON.stringify(r.patternParts)}, isDynamic: ${r.isDynamic}, params: ${JSON.stringify(r.params)}, module: page_${i}, filePath: ${JSON.stringify(absPath)} }`;
38
39
  });
39
40
  const apiRouteEntries = apiRoutes.map((r, i) => {
40
- return ` { pattern: ${JSON.stringify(r.pattern)}, isDynamic: ${r.isDynamic}, params: ${JSON.stringify(r.params)}, module: api_${i} }`;
41
+ return ` { pattern: ${JSON.stringify(r.pattern)}, patternParts: ${JSON.stringify(r.patternParts)}, isDynamic: ${r.isDynamic}, params: ${JSON.stringify(r.params)}, module: api_${i} }`;
41
42
  });
42
43
  // Check for _app and _document
43
44
  const appFilePath = findFileWithExts(pagesDir, "_app", fileMatcher);
@@ -58,6 +59,8 @@ export async function generateServerEntry(pagesDir, nextConfig, fileMatcher, mid
58
59
  localeDetection: nextConfig.i18n.localeDetection,
59
60
  })
60
61
  : "null";
62
+ // Embed the resolved build ID at build time
63
+ const buildIdJson = JSON.stringify(nextConfig?.buildId ?? null);
61
64
  // Serialize the full resolved config for the production server.
62
65
  // This embeds redirects, rewrites, headers, basePath, trailingSlash
63
66
  // so prod-server.ts can apply them without loading next.config.js at runtime.
@@ -116,6 +119,11 @@ ${generateSafeRegExpCode("es5")}
116
119
  ${generateMiddlewareMatcherCode("es5")}
117
120
 
118
121
  export async function runMiddleware(request, ctx) {
122
+ if (ctx) return _runWithExecutionContext(ctx, () => _runMiddleware(request));
123
+ return _runMiddleware(request);
124
+ }
125
+
126
+ async function _runMiddleware(request) {
119
127
  var isProxy = ${middlewarePath ? JSON.stringify(isProxyFile(middlewarePath)) : "false"};
120
128
  var middlewareFn = isProxy
121
129
  ? (middlewareModule.proxy ?? middlewareModule.default)
@@ -138,7 +146,7 @@ export async function runMiddleware(request, ctx) {
138
146
  }
139
147
  var normalizedPathname = __normalizePath(decodedPathname);
140
148
 
141
- if (!matchesMiddleware(normalizedPathname, matcher)) return { continue: true };
149
+ if (!matchesMiddleware(normalizedPathname, matcher, request, i18nConfig)) return { continue: true };
142
150
 
143
151
  // Construct a new Request with the decoded + normalized pathname so middleware
144
152
  // always sees the same canonical path that the router uses.
@@ -156,7 +164,8 @@ export async function runMiddleware(request, ctx) {
156
164
  console.error("[vinext] Middleware error:", e);
157
165
  return { continue: false, response: new Response("Internal Server Error", { status: 500 }) };
158
166
  }
159
- if (ctx && typeof ctx.waitUntil === "function") { ctx.waitUntil(fetchEvent.drainWaitUntil()); } else { fetchEvent.drainWaitUntil(); }
167
+ var _mwCtx = _getRequestExecutionContext();
168
+ if (_mwCtx && typeof _mwCtx.waitUntil === "function") { _mwCtx.waitUntil(fetchEvent.drainWaitUntil()); } else { fetchEvent.drainWaitUntil(); }
160
169
 
161
170
  if (!response) return { continue: true };
162
171
 
@@ -168,6 +177,7 @@ export async function runMiddleware(request, ctx) {
168
177
  // from the final client response.
169
178
  if (
170
179
  !key.startsWith("x-middleware-") ||
180
+ key === "x-middleware-override-headers" ||
171
181
  key.startsWith("x-middleware-request-")
172
182
  ) rHeaders.append(key, value);
173
183
  }
@@ -189,7 +199,7 @@ export async function runMiddleware(request, ctx) {
189
199
  if (rewriteUrl) {
190
200
  var rwHeaders = new Headers();
191
201
  for (var [k, v] of response.headers) {
192
- if (!k.startsWith("x-middleware-") || k.startsWith("x-middleware-request-")) rwHeaders.append(k, v);
202
+ if (!k.startsWith("x-middleware-") || k === "x-middleware-override-headers" || k.startsWith("x-middleware-request-")) rwHeaders.append(k, v);
193
203
  }
194
204
  var rewritePath;
195
205
  try { var parsed = new URL(rewriteUrl, request.url); rewritePath = parsed.pathname + parsed.search; }
@@ -218,9 +228,11 @@ import { runWithPrivateCache } from "vinext/cache-runtime";
218
228
  import { runWithRouterState } from "vinext/router-state";
219
229
  import { runWithHeadState } from "vinext/head-state";
220
230
  import { safeJsonStringify } from "vinext/html";
231
+ import { decode as decodeQueryString } from "node:querystring";
221
232
  import { getSSRFontLinks as _getSSRFontLinks, getSSRFontStyles as _getSSRFontStylesGoogle, getSSRFontPreloads as _getSSRFontPreloadsGoogle } from "next/font/google";
222
233
  import { getSSRFontStyles as _getSSRFontStylesLocal, getSSRFontPreloads as _getSSRFontPreloadsLocal } from "next/font/local";
223
234
  import { parseCookies } from ${JSON.stringify(path.resolve(__dirname, "../config/config-matchers.js").replace(/\\/g, "/"))};
235
+ import { runWithExecutionContext as _runWithExecutionContext, getRequestExecutionContext as _getRequestExecutionContext } from ${JSON.stringify(_requestContextShimPath)};
224
236
  ${instrumentationImportCode}
225
237
  ${middlewareImportCode}
226
238
 
@@ -229,9 +241,20 @@ ${instrumentationInitCode}
229
241
  // i18n config (embedded at build time)
230
242
  const i18nConfig = ${i18nConfigJson};
231
243
 
244
+ // Build ID (embedded at build time)
245
+ const buildId = ${buildIdJson};
246
+
232
247
  // Full resolved config for production server (embedded at build time)
233
248
  export const vinextConfig = ${vinextConfigJson};
234
249
 
250
+ class ApiBodyParseError extends Error {
251
+ constructor(message, statusCode) {
252
+ super(message);
253
+ this.statusCode = statusCode;
254
+ this.name = "ApiBodyParseError";
255
+ }
256
+ }
257
+
235
258
  // ISR cache helpers (inlined for the server entry)
236
259
  async function isrGet(key) {
237
260
  const handler = getCacheHandler();
@@ -250,6 +273,33 @@ function triggerBackgroundRegeneration(key, renderFn) {
250
273
  .catch((err) => console.error("[vinext] ISR regen failed for " + key + ":", err))
251
274
  .finally(() => pendingRegenerations.delete(key));
252
275
  pendingRegenerations.set(key, promise);
276
+ // Register with the Workers ExecutionContext so the isolate is kept alive
277
+ // until the regeneration finishes, even after the Response has been sent.
278
+ const ctx = _getRequestExecutionContext();
279
+ if (ctx && typeof ctx.waitUntil === "function") ctx.waitUntil(promise);
280
+ }
281
+
282
+ function fnv1a64(input) {
283
+ let h1 = 0x811c9dc5;
284
+ for (let i = 0; i < input.length; i++) {
285
+ h1 ^= input.charCodeAt(i);
286
+ h1 = (h1 * 0x01000193) >>> 0;
287
+ }
288
+ let h2 = 0x050c5d1f;
289
+ for (let i = 0; i < input.length; i++) {
290
+ h2 ^= input.charCodeAt(i);
291
+ h2 = (h2 * 0x01000193) >>> 0;
292
+ }
293
+ return h1.toString(36) + h2.toString(36);
294
+ }
295
+ // Keep prefix construction and hashing logic in sync with isrCacheKey() in server/isr-cache.ts.
296
+ // buildId is a top-level const in the generated entry (see "const buildId = ..." above).
297
+ function isrCacheKey(router, pathname) {
298
+ const normalized = pathname === "/" ? "/" : pathname.replace(/\\/$/, "");
299
+ const prefix = buildId ? router + ":" + buildId : router;
300
+ const key = prefix + ":" + normalized;
301
+ if (key.length <= 200) return key;
302
+ return prefix + ":__hash:" + fnv1a64(normalized);
253
303
  }
254
304
 
255
305
  async function renderToStringAsync(element) {
@@ -277,20 +327,20 @@ function matchRoute(url, routes) {
277
327
  let normalizedUrl = pathname === "/" ? "/" : pathname.replace(/\\/$/, "");
278
328
  // NOTE: Do NOT decodeURIComponent here. The pathname is already decoded at
279
329
  // the entry point. Decoding again would create a double-decode vector.
330
+ const urlParts = normalizedUrl.split("/").filter(Boolean);
280
331
  for (const route of routes) {
281
- const params = matchPattern(normalizedUrl, route.pattern);
332
+ const params = matchPattern(urlParts, route.patternParts);
282
333
  if (params !== null) return { route, params };
283
334
  }
284
335
  return null;
285
336
  }
286
337
 
287
- function matchPattern(url, pattern) {
288
- const urlParts = url.split("/").filter(Boolean);
289
- const patternParts = pattern.split("/").filter(Boolean);
338
+ function matchPattern(urlParts, patternParts) {
290
339
  const params = Object.create(null);
291
340
  for (let i = 0; i < patternParts.length; i++) {
292
341
  const pp = patternParts[i];
293
342
  if (pp.endsWith("+")) {
343
+ if (i !== patternParts.length - 1) return null;
294
344
  const paramName = pp.slice(1, -1);
295
345
  const remaining = urlParts.slice(i);
296
346
  if (remaining.length === 0) return null;
@@ -298,6 +348,7 @@ function matchPattern(url, pattern) {
298
348
  return params;
299
349
  }
300
350
  if (pp.endsWith("*")) {
351
+ if (i !== patternParts.length - 1) return null;
301
352
  const paramName = pp.slice(1, -1);
302
353
  params[paramName] = urlParts.slice(i);
303
354
  return params;
@@ -558,8 +609,16 @@ function createReqRes(request, url, query, body) {
558
609
  res.end(JSON.stringify(data));
559
610
  },
560
611
  send: function(data) {
561
- if (typeof data === "object" && data !== null) { res.json(data); }
562
- else { if (!resHeaders["content-type"]) resHeaders["content-type"] = "text/plain"; res.end(String(data)); }
612
+ if (Buffer.isBuffer(data)) {
613
+ if (!resHeaders["content-type"]) resHeaders["content-type"] = "application/octet-stream";
614
+ resHeaders["content-length"] = String(data.length);
615
+ res.end(data);
616
+ } else if (typeof data === "object" && data !== null) {
617
+ res.json(data);
618
+ } else {
619
+ if (!resHeaders["content-type"]) resHeaders["content-type"] = "text/plain";
620
+ res.end(String(data));
621
+ }
563
622
  },
564
623
  redirect: function(statusOrUrl, url2) {
565
624
  if (typeof statusOrUrl === "string") { res.writeHead(307, { Location: statusOrUrl }); }
@@ -602,7 +661,12 @@ async function readBodyWithLimit(request, maxBytes) {
602
661
  return chunks.join("");
603
662
  }
604
663
 
605
- export async function renderPage(request, url, manifest) {
664
+ export async function renderPage(request, url, manifest, ctx) {
665
+ if (ctx) return _runWithExecutionContext(ctx, () => _renderPage(request, url, manifest));
666
+ return _renderPage(request, url, manifest);
667
+ }
668
+
669
+ async function _renderPage(request, url, manifest) {
606
670
  const localeInfo = extractLocale(url);
607
671
  const locale = localeInfo.locale;
608
672
  const routeUrl = localeInfo.url;
@@ -637,7 +701,7 @@ export async function renderPage(request, url, manifest) {
637
701
  try {
638
702
  if (typeof setSSRContext === "function") {
639
703
  setSSRContext({
640
- pathname: routeUrl.split("?")[0],
704
+ pathname: patternToNextFormat(route.pattern),
641
705
  query: { ...params, ...parseQuery(routeUrl) },
642
706
  asPath: routeUrl,
643
707
  locale: locale,
@@ -730,7 +794,7 @@ export async function renderPage(request, url, manifest) {
730
794
  let isrRevalidateSeconds = null;
731
795
  if (typeof pageModule.getStaticProps === "function") {
732
796
  const pathname = routeUrl.split("?")[0];
733
- const cacheKey = "pages:" + (pathname === "/" ? "/" : pathname.replace(/\\/$/, ""));
797
+ const cacheKey = isrCacheKey("pages", pathname);
734
798
  const cached = await isrGet(cacheKey);
735
799
 
736
800
  if (cached && !cached.isStale && cached.value.value && cached.value.value.kind === "PAGES") {
@@ -809,7 +873,7 @@ export async function renderPage(request, url, manifest) {
809
873
  const pageModuleIds = route.filePath ? [route.filePath] : [];
810
874
  const assetTags = collectAssetTags(manifest, pageModuleIds);
811
875
  const nextDataPayload = {
812
- props: { pageProps }, page: patternToNextFormat(route.pattern), query: params, isFallback: false,
876
+ props: { pageProps }, page: patternToNextFormat(route.pattern), query: params, buildId, isFallback: false,
813
877
  };
814
878
  if (i18nConfig) {
815
879
  nextDataPayload.locale = locale;
@@ -885,8 +949,8 @@ export async function renderPage(request, url, manifest) {
885
949
  var isrHtml = await renderToStringAsync(isrElement);
886
950
  var fullHtml = shellPrefix + isrHtml + shellSuffix;
887
951
  var isrPathname = url.split("?")[0];
888
- var isrCacheKey = "pages:" + (isrPathname === "/" ? "/" : isrPathname.replace(/\\/$/, ""));
889
- await isrSet(isrCacheKey, { kind: "PAGES", html: fullHtml, pageData: pageProps, headers: undefined, status: undefined }, isrRevalidateSeconds);
952
+ var _cacheKey = isrCacheKey("pages", isrPathname);
953
+ await isrSet(_cacheKey, { kind: "PAGES", html: fullHtml, pageData: pageProps, headers: undefined, status: undefined }, isrRevalidateSeconds);
890
954
  }
891
955
 
892
956
  // Merge headers/status/cookies set by getServerSideProps on the res object.
@@ -960,28 +1024,32 @@ export async function handleApiRoute(request, url) {
960
1024
  if (contentLength > 1 * 1024 * 1024) {
961
1025
  return new Response("Request body too large", { status: 413 });
962
1026
  }
963
- let body;
964
- const ct = request.headers.get("content-type") || "";
965
- let rawBody;
966
- try { rawBody = await readBodyWithLimit(request, 1 * 1024 * 1024); }
967
- catch { return new Response("Request body too large", { status: 413 }); }
968
- if (!rawBody) {
969
- body = undefined;
970
- } else if (ct.includes("application/json")) {
971
- try { body = JSON.parse(rawBody); } catch { body = rawBody; }
972
- } else {
973
- body = rawBody;
974
- }
975
-
976
- const { req, res, responsePromise } = createReqRes(request, url, query, body);
977
-
978
1027
  try {
1028
+ let body;
1029
+ const ct = request.headers.get("content-type") || "";
1030
+ let rawBody;
1031
+ try { rawBody = await readBodyWithLimit(request, 1 * 1024 * 1024); }
1032
+ catch { return new Response("Request body too large", { status: 413 }); }
1033
+ if (!rawBody) {
1034
+ body = undefined;
1035
+ } else if (ct.includes("application/json")) {
1036
+ try { body = JSON.parse(rawBody); } catch { throw new ApiBodyParseError("Invalid JSON", 400); }
1037
+ } else if (ct.includes("application/x-www-form-urlencoded")) {
1038
+ body = decodeQueryString(rawBody);
1039
+ } else {
1040
+ body = rawBody;
1041
+ }
1042
+
1043
+ const { req, res, responsePromise } = createReqRes(request, url, query, body);
979
1044
  await handler(req, res);
980
1045
  // If handler didn't call res.end(), end it now.
981
1046
  // The end() method is idempotent — safe to call twice.
982
1047
  res.end();
983
1048
  return await responsePromise;
984
1049
  } catch (e) {
1050
+ if (e instanceof ApiBodyParseError) {
1051
+ return new Response(e.message, { status: e.statusCode });
1052
+ }
985
1053
  console.error("[vinext] API error:", e);
986
1054
  return new Response("Internal Server Error", { status: 500 });
987
1055
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pages-server-entry.js","sourceRoot":"","sources":["../../src/entries/pages-server-entry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pages Router server entry generator.\n *\n * Generates the virtual SSR server entry module (`virtual:vinext-server-entry`).\n * This is the entry point for `vite build --ssr`. It handles SSR, API routes,\n * middleware, ISR, and i18n for the Pages Router.\n *\n * Extracted from index.ts.\n */\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { pagesRouter, apiRouter, type Route } from \"../routing/pages-router.js\";\nimport { createValidFileMatcher } from \"../routing/file-matcher.js\";\nimport { type ResolvedNextConfig } from \"../config/next-config.js\";\nimport { isProxyFile } from \"../server/middleware.js\";\nimport {\n generateSafeRegExpCode,\n generateMiddlewareMatcherCode,\n generateNormalizePathCode,\n} from \"../server/middleware-codegen.js\";\nimport { findFileWithExts } from \"./pages-entry-helpers.js\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\n/**\n * Generate the virtual SSR server entry module.\n * This is the entry point for `vite build --ssr`.\n */\nexport async function generateServerEntry(\n pagesDir: string,\n nextConfig: ResolvedNextConfig,\n fileMatcher: ReturnType<typeof createValidFileMatcher>,\n middlewarePath: string | null,\n instrumentationPath: string | null,\n): Promise<string> {\n const pageRoutes = await pagesRouter(pagesDir, nextConfig?.pageExtensions, fileMatcher);\n const apiRoutes = await apiRouter(pagesDir, nextConfig?.pageExtensions, fileMatcher);\n\n // Generate import statements using absolute paths since virtual\n // modules don't have a real file location for relative resolution.\n const pageImports = pageRoutes.map((r: Route, i: number) => {\n const absPath = r.filePath.replace(/\\\\/g, \"/\");\n return `import * as page_${i} from ${JSON.stringify(absPath)};`;\n });\n\n const apiImports = apiRoutes.map((r: Route, i: number) => {\n const absPath = r.filePath.replace(/\\\\/g, \"/\");\n return `import * as api_${i} from ${JSON.stringify(absPath)};`;\n });\n\n // Build the route table — include filePath for SSR manifest lookup\n const pageRouteEntries = pageRoutes.map((r: Route, i: number) => {\n const absPath = r.filePath.replace(/\\\\/g, \"/\");\n return ` { pattern: ${JSON.stringify(r.pattern)}, isDynamic: ${r.isDynamic}, params: ${JSON.stringify(r.params)}, module: page_${i}, filePath: ${JSON.stringify(absPath)} }`;\n });\n\n const apiRouteEntries = apiRoutes.map((r: Route, i: number) => {\n return ` { pattern: ${JSON.stringify(r.pattern)}, isDynamic: ${r.isDynamic}, params: ${JSON.stringify(r.params)}, module: api_${i} }`;\n });\n\n // Check for _app and _document\n const appFilePath = findFileWithExts(pagesDir, \"_app\", fileMatcher);\n const docFilePath = findFileWithExts(pagesDir, \"_document\", fileMatcher);\n const hasApp = appFilePath !== null;\n const hasDoc = docFilePath !== null;\n\n const appImportCode = hasApp\n ? `import { default as AppComponent } from ${JSON.stringify(appFilePath!.replace(/\\\\/g, \"/\"))};`\n : `const AppComponent = null;`;\n\n const docImportCode = hasDoc\n ? `import { default as DocumentComponent } from ${JSON.stringify(docFilePath!.replace(/\\\\/g, \"/\"))};`\n : `const DocumentComponent = null;`;\n\n // Serialize i18n config for embedding in the server entry\n const i18nConfigJson = nextConfig?.i18n\n ? JSON.stringify({\n locales: nextConfig.i18n.locales,\n defaultLocale: nextConfig.i18n.defaultLocale,\n localeDetection: nextConfig.i18n.localeDetection,\n })\n : \"null\";\n\n // Serialize the full resolved config for the production server.\n // This embeds redirects, rewrites, headers, basePath, trailingSlash\n // so prod-server.ts can apply them without loading next.config.js at runtime.\n const vinextConfigJson = JSON.stringify({\n basePath: nextConfig?.basePath ?? \"\",\n trailingSlash: nextConfig?.trailingSlash ?? false,\n redirects: nextConfig?.redirects ?? [],\n rewrites: nextConfig?.rewrites ?? { beforeFiles: [], afterFiles: [], fallback: [] },\n headers: nextConfig?.headers ?? [],\n i18n: nextConfig?.i18n ?? null,\n images: {\n deviceSizes: nextConfig?.images?.deviceSizes,\n imageSizes: nextConfig?.images?.imageSizes,\n dangerouslyAllowSVG: nextConfig?.images?.dangerouslyAllowSVG,\n contentDispositionType: nextConfig?.images?.contentDispositionType,\n contentSecurityPolicy: nextConfig?.images?.contentSecurityPolicy,\n },\n });\n\n // Generate instrumentation code if instrumentation.ts exists.\n // For production (Cloudflare Workers), instrumentation.ts is bundled into the\n // Worker and register() is called as a top-level await at module evaluation time —\n // before any request is handled. This mirrors App Router behavior (generateRscEntry)\n // and matches Next.js semantics: register() runs once on startup in the process\n // that handles requests.\n //\n // The onRequestError handler is stored on globalThis so it is visible across\n // all code within the Worker (same global scope).\n const instrumentationImportCode = instrumentationPath\n ? `import * as _instrumentation from ${JSON.stringify(instrumentationPath.replace(/\\\\/g, \"/\"))};`\n : \"\";\n\n const instrumentationInitCode = instrumentationPath\n ? `// Run instrumentation register() once at module evaluation time — before any\n// requests are handled. Matches Next.js semantics: register() is called once\n// on startup in the process that handles requests.\nif (typeof _instrumentation.register === \"function\") {\n await _instrumentation.register();\n}\n// Store the onRequestError handler on globalThis so it is visible to all\n// code within the Worker (same global scope).\nif (typeof _instrumentation.onRequestError === \"function\") {\n globalThis.__VINEXT_onRequestErrorHandler__ = _instrumentation.onRequestError;\n}`\n : \"\";\n\n // Generate middleware code if middleware.ts exists\n const middlewareImportCode = middlewarePath\n ? `import * as middlewareModule from ${JSON.stringify(middlewarePath.replace(/\\\\/g, \"/\"))};\nimport { NextRequest, NextFetchEvent } from \"next/server\";`\n : \"\";\n\n // The matcher config is read from the middleware module at import time.\n // We inline the matching + execution logic so the prod server can call it.\n const middlewareExportCode = middlewarePath\n ? `\n// --- Middleware support (generated from middleware-codegen.ts) ---\n${generateNormalizePathCode(\"es5\")}\n${generateSafeRegExpCode(\"es5\")}\n${generateMiddlewareMatcherCode(\"es5\")}\n\nexport async function runMiddleware(request, ctx) {\n var isProxy = ${middlewarePath ? JSON.stringify(isProxyFile(middlewarePath)) : \"false\"};\n var middlewareFn = isProxy\n ? (middlewareModule.proxy ?? middlewareModule.default)\n : (middlewareModule.middleware ?? middlewareModule.default);\n if (typeof middlewareFn !== \"function\") {\n var fileType = isProxy ? \"Proxy\" : \"Middleware\";\n var expectedExport = isProxy ? \"proxy\" : \"middleware\";\n throw new Error(\"The \" + fileType + \" file must export a function named \\`\" + expectedExport + \"\\` or a \\`default\\` function.\");\n }\n\n var config = middlewareModule.config;\n var matcher = config && config.matcher;\n var url = new URL(request.url);\n\n // Normalize pathname before matching to prevent path-confusion bypasses\n // (percent-encoding like /%61dmin, double slashes like /dashboard//settings).\n var decodedPathname;\n try { decodedPathname = decodeURIComponent(url.pathname); } catch (e) {\n return { continue: false, response: new Response(\"Bad Request\", { status: 400 }) };\n }\n var normalizedPathname = __normalizePath(decodedPathname);\n\n if (!matchesMiddleware(normalizedPathname, matcher)) return { continue: true };\n\n // Construct a new Request with the decoded + normalized pathname so middleware\n // always sees the same canonical path that the router uses.\n var mwRequest = request;\n if (normalizedPathname !== url.pathname) {\n var mwUrl = new URL(url);\n mwUrl.pathname = normalizedPathname;\n mwRequest = new Request(mwUrl, request);\n }\n var nextRequest = mwRequest instanceof NextRequest ? mwRequest : new NextRequest(mwRequest);\n var fetchEvent = new NextFetchEvent({ page: normalizedPathname });\n var response;\n try { response = await middlewareFn(nextRequest, fetchEvent); }\n catch (e) {\n console.error(\"[vinext] Middleware error:\", e);\n return { continue: false, response: new Response(\"Internal Server Error\", { status: 500 }) };\n }\n if (ctx && typeof ctx.waitUntil === \"function\") { ctx.waitUntil(fetchEvent.drainWaitUntil()); } else { fetchEvent.drainWaitUntil(); }\n\n if (!response) return { continue: true };\n\n if (response.headers.get(\"x-middleware-next\") === \"1\") {\n var rHeaders = new Headers();\n for (var [key, value] of response.headers) {\n // Keep x-middleware-request-* headers so the production server can\n // apply middleware-request header overrides before stripping internals\n // from the final client response.\n if (\n !key.startsWith(\"x-middleware-\") ||\n key.startsWith(\"x-middleware-request-\")\n ) rHeaders.append(key, value);\n }\n return { continue: true, responseHeaders: rHeaders };\n }\n\n if (response.status >= 300 && response.status < 400) {\n var location = response.headers.get(\"Location\") || response.headers.get(\"location\");\n if (location) {\n var rdHeaders = new Headers();\n for (var [rk, rv] of response.headers) {\n if (!rk.startsWith(\"x-middleware-\") && rk.toLowerCase() !== \"location\") rdHeaders.append(rk, rv);\n }\n return { continue: false, redirectUrl: location, redirectStatus: response.status, responseHeaders: rdHeaders };\n }\n }\n\n var rewriteUrl = response.headers.get(\"x-middleware-rewrite\");\n if (rewriteUrl) {\n var rwHeaders = new Headers();\n for (var [k, v] of response.headers) {\n if (!k.startsWith(\"x-middleware-\") || k.startsWith(\"x-middleware-request-\")) rwHeaders.append(k, v);\n }\n var rewritePath;\n try { var parsed = new URL(rewriteUrl, request.url); rewritePath = parsed.pathname + parsed.search; }\n catch { rewritePath = rewriteUrl; }\n return { continue: true, rewriteUrl: rewritePath, rewriteStatus: response.status !== 200 ? response.status : undefined, responseHeaders: rwHeaders };\n }\n\n return { continue: false, response: response };\n}\n`\n : `\nexport async function runMiddleware() { return { continue: true }; }\n`;\n\n // The server entry is a self-contained module that uses Web-standard APIs\n // (Request/Response, renderToReadableStream) so it runs on Cloudflare Workers.\n return `\nimport React from \"react\";\nimport { renderToReadableStream } from \"react-dom/server.edge\";\nimport { resetSSRHead, getSSRHeadHTML } from \"next/head\";\nimport { flushPreloads } from \"next/dynamic\";\nimport { setSSRContext, wrapWithRouterContext } from \"next/router\";\nimport { getCacheHandler } from \"next/cache\";\nimport { runWithFetchCache } from \"vinext/fetch-cache\";\nimport { _runWithCacheState } from \"next/cache\";\nimport { runWithPrivateCache } from \"vinext/cache-runtime\";\nimport { runWithRouterState } from \"vinext/router-state\";\nimport { runWithHeadState } from \"vinext/head-state\";\nimport { safeJsonStringify } from \"vinext/html\";\nimport { getSSRFontLinks as _getSSRFontLinks, getSSRFontStyles as _getSSRFontStylesGoogle, getSSRFontPreloads as _getSSRFontPreloadsGoogle } from \"next/font/google\";\nimport { getSSRFontStyles as _getSSRFontStylesLocal, getSSRFontPreloads as _getSSRFontPreloadsLocal } from \"next/font/local\";\nimport { parseCookies } from ${JSON.stringify(path.resolve(__dirname, \"../config/config-matchers.js\").replace(/\\\\/g, \"/\"))};\n${instrumentationImportCode}\n${middlewareImportCode}\n\n${instrumentationInitCode}\n\n// i18n config (embedded at build time)\nconst i18nConfig = ${i18nConfigJson};\n\n// Full resolved config for production server (embedded at build time)\nexport const vinextConfig = ${vinextConfigJson};\n\n// ISR cache helpers (inlined for the server entry)\nasync function isrGet(key) {\n const handler = getCacheHandler();\n const result = await handler.get(key);\n if (!result || !result.value) return null;\n return { value: result, isStale: result.cacheState === \"stale\" };\n}\nasync function isrSet(key, data, revalidateSeconds, tags) {\n const handler = getCacheHandler();\n await handler.set(key, data, { revalidate: revalidateSeconds, tags: tags || [] });\n}\nconst pendingRegenerations = new Map();\nfunction triggerBackgroundRegeneration(key, renderFn) {\n if (pendingRegenerations.has(key)) return;\n const promise = renderFn()\n .catch((err) => console.error(\"[vinext] ISR regen failed for \" + key + \":\", err))\n .finally(() => pendingRegenerations.delete(key));\n pendingRegenerations.set(key, promise);\n}\n\nasync function renderToStringAsync(element) {\n const stream = await renderToReadableStream(element);\n await stream.allReady;\n return new Response(stream).text();\n}\n\n${pageImports.join(\"\\n\")}\n${apiImports.join(\"\\n\")}\n\n${appImportCode}\n${docImportCode}\n\nconst pageRoutes = [\n${pageRouteEntries.join(\",\\n\")}\n];\n\nconst apiRoutes = [\n${apiRouteEntries.join(\",\\n\")}\n];\n\nfunction matchRoute(url, routes) {\n const pathname = url.split(\"?\")[0];\n let normalizedUrl = pathname === \"/\" ? \"/\" : pathname.replace(/\\\\/$/, \"\");\n // NOTE: Do NOT decodeURIComponent here. The pathname is already decoded at\n // the entry point. Decoding again would create a double-decode vector.\n for (const route of routes) {\n const params = matchPattern(normalizedUrl, route.pattern);\n if (params !== null) return { route, params };\n }\n return null;\n}\n\nfunction matchPattern(url, pattern) {\n const urlParts = url.split(\"/\").filter(Boolean);\n const patternParts = pattern.split(\"/\").filter(Boolean);\n const params = Object.create(null);\n for (let i = 0; i < patternParts.length; i++) {\n const pp = patternParts[i];\n if (pp.endsWith(\"+\")) {\n const paramName = pp.slice(1, -1);\n const remaining = urlParts.slice(i);\n if (remaining.length === 0) return null;\n params[paramName] = remaining;\n return params;\n }\n if (pp.endsWith(\"*\")) {\n const paramName = pp.slice(1, -1);\n params[paramName] = urlParts.slice(i);\n return params;\n }\n if (pp.startsWith(\":\")) {\n if (i >= urlParts.length) return null;\n params[pp.slice(1)] = urlParts[i];\n continue;\n }\n if (i >= urlParts.length || urlParts[i] !== pp) return null;\n }\n if (urlParts.length !== patternParts.length) return null;\n return params;\n}\n\nfunction parseQuery(url) {\n const qs = url.split(\"?\")[1];\n if (!qs) return {};\n const p = new URLSearchParams(qs);\n const q = {};\n for (const [k, v] of p) {\n if (k in q) {\n q[k] = Array.isArray(q[k]) ? q[k].concat(v) : [q[k], v];\n } else {\n q[k] = v;\n }\n }\n return q;\n}\n\nfunction patternToNextFormat(pattern) {\n return pattern\n .replace(/:([\\\\w]+)\\\\*/g, \"[[...$1]]\")\n .replace(/:([\\\\w]+)\\\\+/g, \"[...$1]\")\n .replace(/:([\\\\w]+)/g, \"[$1]\");\n}\n\nfunction collectAssetTags(manifest, moduleIds) {\n // Fall back to embedded manifest (set by vinext:cloudflare-build for Workers)\n const m = (manifest && Object.keys(manifest).length > 0)\n ? manifest\n : (typeof globalThis !== \"undefined\" && globalThis.__VINEXT_SSR_MANIFEST__) || null;\n const tags = [];\n const seen = new Set();\n\n // Load the set of lazy chunk filenames (only reachable via dynamic imports).\n // These should NOT get <link rel=\"modulepreload\"> or <script type=\"module\">\n // tags — they are fetched on demand when the dynamic import() executes (e.g.\n // chunks behind React.lazy() or next/dynamic boundaries).\n var lazyChunks = (typeof globalThis !== \"undefined\" && globalThis.__VINEXT_LAZY_CHUNKS__) || null;\n var lazySet = lazyChunks && lazyChunks.length > 0 ? new Set(lazyChunks) : null;\n\n // Inject the client entry script if embedded by vinext:cloudflare-build\n if (typeof globalThis !== \"undefined\" && globalThis.__VINEXT_CLIENT_ENTRY__) {\n const entry = globalThis.__VINEXT_CLIENT_ENTRY__;\n seen.add(entry);\n tags.push('<link rel=\"modulepreload\" href=\"/' + entry + '\" />');\n tags.push('<script type=\"module\" src=\"/' + entry + '\" crossorigin></script>');\n }\n if (m) {\n // Always inject shared chunks (framework, vinext runtime, entry) and\n // page-specific chunks. The manifest maps module file paths to their\n // associated JS/CSS assets.\n //\n // For page-specific injection, the module IDs may be absolute paths\n // while the manifest uses relative paths. Try both the original ID\n // and a suffix match to find the correct manifest entry.\n var allFiles = [];\n\n if (moduleIds && moduleIds.length > 0) {\n // Collect assets for the requested page modules\n for (var mi = 0; mi < moduleIds.length; mi++) {\n var id = moduleIds[mi];\n var files = m[id];\n if (!files) {\n // Absolute path didn't match — try matching by suffix.\n // Manifest keys are relative (e.g. \"pages/about.tsx\") while\n // moduleIds may be absolute (e.g. \"/home/.../pages/about.tsx\").\n for (var mk in m) {\n if (id.endsWith(\"/\" + mk) || id === mk) {\n files = m[mk];\n break;\n }\n }\n }\n if (files) {\n for (var fi = 0; fi < files.length; fi++) allFiles.push(files[fi]);\n }\n }\n\n // Also inject shared chunks that every page needs: framework,\n // vinext runtime, and the entry bootstrap. These are identified\n // by scanning all manifest values for chunk filenames containing\n // known prefixes.\n for (var key in m) {\n var vals = m[key];\n if (!vals) continue;\n for (var vi = 0; vi < vals.length; vi++) {\n var file = vals[vi];\n var basename = file.split(\"/\").pop() || \"\";\n if (\n basename.startsWith(\"framework-\") ||\n basename.startsWith(\"vinext-\") ||\n basename.includes(\"vinext-client-entry\") ||\n basename.includes(\"vinext-app-browser-entry\")\n ) {\n allFiles.push(file);\n }\n }\n }\n } else {\n // No specific modules — include all assets from manifest\n for (var akey in m) {\n var avals = m[akey];\n if (avals) {\n for (var ai = 0; ai < avals.length; ai++) allFiles.push(avals[ai]);\n }\n }\n }\n\n for (var ti = 0; ti < allFiles.length; ti++) {\n var tf = allFiles[ti];\n // Normalize: Vite's SSR manifest values include a leading '/'\n // (from base path), but we prepend '/' ourselves when building\n // href/src attributes. Strip any existing leading slash to avoid\n // producing protocol-relative URLs like \"//assets/chunk.js\".\n // This also ensures consistent keys for the seen-set dedup and\n // lazySet.has() checks (which use values without leading slash).\n if (tf.charAt(0) === '/') tf = tf.slice(1);\n if (seen.has(tf)) continue;\n seen.add(tf);\n if (tf.endsWith(\".css\")) {\n tags.push('<link rel=\"stylesheet\" href=\"/' + tf + '\" />');\n } else if (tf.endsWith(\".js\")) {\n // Skip lazy chunks — they are behind dynamic import() boundaries\n // (React.lazy, next/dynamic) and should only be fetched on demand.\n if (lazySet && lazySet.has(tf)) continue;\n tags.push('<link rel=\"modulepreload\" href=\"/' + tf + '\" />');\n tags.push('<script type=\"module\" src=\"/' + tf + '\" crossorigin></script>');\n }\n }\n }\n return tags.join(\"\\\\n \");\n}\n\n// i18n helpers\nfunction extractLocale(url) {\n if (!i18nConfig) return { locale: undefined, url, hadPrefix: false };\n const pathname = url.split(\"?\")[0];\n const parts = pathname.split(\"/\").filter(Boolean);\n const query = url.includes(\"?\") ? url.slice(url.indexOf(\"?\")) : \"\";\n if (parts.length > 0 && i18nConfig.locales.includes(parts[0])) {\n const locale = parts[0];\n const rest = \"/\" + parts.slice(1).join(\"/\");\n return { locale, url: (rest || \"/\") + query, hadPrefix: true };\n }\n return { locale: i18nConfig.defaultLocale, url, hadPrefix: false };\n}\n\nfunction detectLocaleFromHeaders(headers) {\n if (!i18nConfig) return null;\n const acceptLang = headers.get(\"accept-language\");\n if (!acceptLang) return null;\n const langs = acceptLang.split(\",\").map(function(part) {\n const pieces = part.trim().split(\";\");\n const q = pieces[1] ? parseFloat(pieces[1].replace(\"q=\", \"\")) : 1;\n return { lang: pieces[0].trim().toLowerCase(), q: q };\n }).sort(function(a, b) { return b.q - a.q; });\n for (let k = 0; k < langs.length; k++) {\n const lang = langs[k].lang;\n for (let j = 0; j < i18nConfig.locales.length; j++) {\n if (i18nConfig.locales[j].toLowerCase() === lang) return i18nConfig.locales[j];\n }\n const prefix = lang.split(\"-\")[0];\n for (let j = 0; j < i18nConfig.locales.length; j++) {\n const loc = i18nConfig.locales[j].toLowerCase();\n if (loc === prefix || loc.startsWith(prefix + \"-\")) return i18nConfig.locales[j];\n }\n }\n return null;\n}\n\nfunction parseCookieLocaleFromHeader(cookieHeader) {\n if (!i18nConfig || !cookieHeader) return null;\n const match = cookieHeader.match(/(?:^|;\\\\s*)NEXT_LOCALE=([^;]*)/);\n if (!match) return null;\n var value;\n try { value = decodeURIComponent(match[1].trim()); } catch (e) { return null; }\n if (i18nConfig.locales.indexOf(value) !== -1) return value;\n return null;\n}\n\n// Lightweight req/res facade for getServerSideProps and API routes.\n// Next.js pages expect ctx.req/ctx.res with Node-like shapes.\nfunction createReqRes(request, url, query, body) {\n const headersObj = {};\n for (const [k, v] of request.headers) headersObj[k.toLowerCase()] = v;\n\n const req = {\n method: request.method,\n url: url,\n headers: headersObj,\n query: query,\n body: body,\n cookies: parseCookies(request.headers.get(\"cookie\")),\n };\n\n let resStatusCode = 200;\n const resHeaders = {};\n // set-cookie needs array support (multiple Set-Cookie headers are common)\n const setCookieHeaders = [];\n let resBody = null;\n let ended = false;\n let resolveResponse;\n const responsePromise = new Promise(function(r) { resolveResponse = r; });\n\n const res = {\n get statusCode() { return resStatusCode; },\n set statusCode(code) { resStatusCode = code; },\n writeHead: function(code, headers) {\n resStatusCode = code;\n if (headers) {\n for (const [k, v] of Object.entries(headers)) {\n if (k.toLowerCase() === \"set-cookie\") {\n if (Array.isArray(v)) { for (const c of v) setCookieHeaders.push(c); }\n else { setCookieHeaders.push(v); }\n } else {\n resHeaders[k] = v;\n }\n }\n }\n return res;\n },\n setHeader: function(name, value) {\n if (name.toLowerCase() === \"set-cookie\") {\n if (Array.isArray(value)) { for (const c of value) setCookieHeaders.push(c); }\n else { setCookieHeaders.push(value); }\n } else {\n resHeaders[name.toLowerCase()] = value;\n }\n return res;\n },\n getHeader: function(name) {\n if (name.toLowerCase() === \"set-cookie\") return setCookieHeaders.length > 0 ? setCookieHeaders : undefined;\n return resHeaders[name.toLowerCase()];\n },\n end: function(data) {\n if (ended) return;\n ended = true;\n if (data !== undefined && data !== null) resBody = data;\n const h = new Headers(resHeaders);\n for (const c of setCookieHeaders) h.append(\"set-cookie\", c);\n resolveResponse(new Response(resBody, { status: resStatusCode, headers: h }));\n },\n status: function(code) { resStatusCode = code; return res; },\n json: function(data) {\n resHeaders[\"content-type\"] = \"application/json\";\n res.end(JSON.stringify(data));\n },\n send: function(data) {\n if (typeof data === \"object\" && data !== null) { res.json(data); }\n else { if (!resHeaders[\"content-type\"]) resHeaders[\"content-type\"] = \"text/plain\"; res.end(String(data)); }\n },\n redirect: function(statusOrUrl, url2) {\n if (typeof statusOrUrl === \"string\") { res.writeHead(307, { Location: statusOrUrl }); }\n else { res.writeHead(statusOrUrl, { Location: url2 }); }\n res.end();\n },\n getHeaders: function() {\n var h = Object.assign({}, resHeaders);\n if (setCookieHeaders.length > 0) h[\"set-cookie\"] = setCookieHeaders;\n return h;\n },\n get headersSent() { return ended; },\n };\n\n return { req, res, responsePromise };\n}\n\n/**\n * Read request body as text with a size limit.\n * Throws if the body exceeds maxBytes. This prevents DoS via chunked\n * transfer encoding where Content-Length is absent or spoofed.\n */\nasync function readBodyWithLimit(request, maxBytes) {\n if (!request.body) return \"\";\n var reader = request.body.getReader();\n var decoder = new TextDecoder();\n var chunks = [];\n var totalSize = 0;\n for (;;) {\n var result = await reader.read();\n if (result.done) break;\n totalSize += result.value.byteLength;\n if (totalSize > maxBytes) {\n reader.cancel();\n throw new Error(\"Request body too large\");\n }\n chunks.push(decoder.decode(result.value, { stream: true }));\n }\n chunks.push(decoder.decode());\n return chunks.join(\"\");\n}\n\nexport async function renderPage(request, url, manifest) {\n const localeInfo = extractLocale(url);\n const locale = localeInfo.locale;\n const routeUrl = localeInfo.url;\n const cookieHeader = request.headers.get(\"cookie\") || \"\";\n\n // i18n redirect: check NEXT_LOCALE cookie first, then Accept-Language\n if (i18nConfig && !localeInfo.hadPrefix) {\n const cookieLocale = parseCookieLocaleFromHeader(cookieHeader);\n if (cookieLocale && cookieLocale !== i18nConfig.defaultLocale) {\n return new Response(null, { status: 307, headers: { Location: \"/\" + cookieLocale + routeUrl } });\n }\n if (!cookieLocale && i18nConfig.localeDetection !== false) {\n const detected = detectLocaleFromHeaders(request.headers);\n if (detected && detected !== i18nConfig.defaultLocale) {\n return new Response(null, { status: 307, headers: { Location: \"/\" + detected + routeUrl } });\n }\n }\n }\n\n const match = matchRoute(routeUrl, pageRoutes);\n if (!match) {\n return new Response(\"<!DOCTYPE html><html><body><h1>404 - Page not found</h1></body></html>\",\n { status: 404, headers: { \"Content-Type\": \"text/html\" } });\n }\n\n const { route, params } = match;\n return runWithRouterState(() =>\n runWithHeadState(() =>\n _runWithCacheState(() =>\n runWithPrivateCache(() =>\n runWithFetchCache(async () => {\n try {\n if (typeof setSSRContext === \"function\") {\n setSSRContext({\n pathname: routeUrl.split(\"?\")[0],\n query: { ...params, ...parseQuery(routeUrl) },\n asPath: routeUrl,\n locale: locale,\n locales: i18nConfig ? i18nConfig.locales : undefined,\n defaultLocale: i18nConfig ? i18nConfig.defaultLocale : undefined,\n });\n }\n\n if (i18nConfig) {\n globalThis.__VINEXT_LOCALE__ = locale;\n globalThis.__VINEXT_LOCALES__ = i18nConfig.locales;\n globalThis.__VINEXT_DEFAULT_LOCALE__ = i18nConfig.defaultLocale;\n }\n\n const pageModule = route.module;\n const PageComponent = pageModule.default;\n if (!PageComponent) {\n return new Response(\"Page has no default export\", { status: 500 });\n }\n\n // Handle getStaticPaths for dynamic routes\n if (typeof pageModule.getStaticPaths === \"function\" && route.isDynamic) {\n const pathsResult = await pageModule.getStaticPaths({\n locales: i18nConfig ? i18nConfig.locales : [],\n defaultLocale: i18nConfig ? i18nConfig.defaultLocale : \"\",\n });\n const fallback = pathsResult && pathsResult.fallback !== undefined ? pathsResult.fallback : false;\n\n if (fallback === false) {\n const paths = pathsResult && pathsResult.paths ? pathsResult.paths : [];\n const isValidPath = paths.some(function(p) {\n return Object.entries(p.params).every(function(entry) {\n var key = entry[0], val = entry[1];\n var actual = params[key];\n if (Array.isArray(val)) {\n return Array.isArray(actual) && val.join(\"/\") === actual.join(\"/\");\n }\n return String(val) === String(actual);\n });\n });\n if (!isValidPath) {\n return new Response(\"<!DOCTYPE html><html><body><h1>404 - Page not found</h1></body></html>\",\n { status: 404, headers: { \"Content-Type\": \"text/html\" } });\n }\n }\n }\n\n let pageProps = {};\n var gsspRes = null;\n if (typeof pageModule.getServerSideProps === \"function\") {\n const { req, res, responsePromise } = createReqRes(request, routeUrl, parseQuery(routeUrl), undefined);\n const ctx = {\n params, req, res,\n query: parseQuery(routeUrl),\n resolvedUrl: routeUrl,\n locale: locale,\n locales: i18nConfig ? i18nConfig.locales : undefined,\n defaultLocale: i18nConfig ? i18nConfig.defaultLocale : undefined,\n };\n const result = await pageModule.getServerSideProps(ctx);\n // If gSSP called res.end() directly (short-circuit), return that response.\n if (res.headersSent) {\n return await responsePromise;\n }\n if (result && result.props) pageProps = result.props;\n if (result && result.redirect) {\n var gsspStatus = result.redirect.statusCode != null ? result.redirect.statusCode : (result.redirect.permanent ? 308 : 307);\n return new Response(null, { status: gsspStatus, headers: { Location: sanitizeDestinationLocal(result.redirect.destination) } });\n }\n if (result && result.notFound) {\n return new Response(\"404\", { status: 404 });\n }\n // Preserve the res object so headers/status/cookies set by gSSP\n // can be merged into the final HTML response.\n gsspRes = res;\n }\n // Build font Link header early so it's available for ISR cached responses too.\n // Font preloads are module-level state populated at import time and persist across requests.\n var _fontLinkHeader = \"\";\n var _allFp = [];\n try {\n var _fpGoogle = typeof _getSSRFontPreloadsGoogle === \"function\" ? _getSSRFontPreloadsGoogle() : [];\n var _fpLocal = typeof _getSSRFontPreloadsLocal === \"function\" ? _getSSRFontPreloadsLocal() : [];\n _allFp = _fpGoogle.concat(_fpLocal);\n if (_allFp.length > 0) {\n _fontLinkHeader = _allFp.map(function(p) { return \"<\" + p.href + \">; rel=preload; as=font; type=\" + p.type + \"; crossorigin\"; }).join(\", \");\n }\n } catch (e) { /* font preloads not available */ }\n\n let isrRevalidateSeconds = null;\n if (typeof pageModule.getStaticProps === \"function\") {\n const pathname = routeUrl.split(\"?\")[0];\n const cacheKey = \"pages:\" + (pathname === \"/\" ? \"/\" : pathname.replace(/\\\\/$/, \"\"));\n const cached = await isrGet(cacheKey);\n\n if (cached && !cached.isStale && cached.value.value && cached.value.value.kind === \"PAGES\") {\n var _hitHeaders = {\n \"Content-Type\": \"text/html\", \"X-Vinext-Cache\": \"HIT\",\n \"Cache-Control\": \"s-maxage=\" + (cached.value.value.revalidate || 60) + \", stale-while-revalidate\",\n };\n if (_fontLinkHeader) _hitHeaders[\"Link\"] = _fontLinkHeader;\n return new Response(cached.value.value.html, { status: 200, headers: _hitHeaders });\n }\n\n if (cached && cached.isStale && cached.value.value && cached.value.value.kind === \"PAGES\") {\n triggerBackgroundRegeneration(cacheKey, async function() {\n const freshResult = await pageModule.getStaticProps({ params });\n if (freshResult && freshResult.props && typeof freshResult.revalidate === \"number\" && freshResult.revalidate > 0) {\n await isrSet(cacheKey, { kind: \"PAGES\", html: cached.value.value.html, pageData: freshResult.props, headers: undefined, status: undefined }, freshResult.revalidate);\n }\n });\n var _staleHeaders = {\n \"Content-Type\": \"text/html\", \"X-Vinext-Cache\": \"STALE\",\n \"Cache-Control\": \"s-maxage=0, stale-while-revalidate\",\n };\n if (_fontLinkHeader) _staleHeaders[\"Link\"] = _fontLinkHeader;\n return new Response(cached.value.value.html, { status: 200, headers: _staleHeaders });\n }\n\n const ctx = {\n params,\n locale: locale,\n locales: i18nConfig ? i18nConfig.locales : undefined,\n defaultLocale: i18nConfig ? i18nConfig.defaultLocale : undefined,\n };\n const result = await pageModule.getStaticProps(ctx);\n if (result && result.props) pageProps = result.props;\n if (result && result.redirect) {\n var gspStatus = result.redirect.statusCode != null ? result.redirect.statusCode : (result.redirect.permanent ? 308 : 307);\n return new Response(null, { status: gspStatus, headers: { Location: sanitizeDestinationLocal(result.redirect.destination) } });\n }\n if (result && result.notFound) {\n return new Response(\"404\", { status: 404 });\n }\n if (typeof result.revalidate === \"number\" && result.revalidate > 0) {\n isrRevalidateSeconds = result.revalidate;\n }\n }\n\n let element;\n if (AppComponent) {\n element = React.createElement(AppComponent, { Component: PageComponent, pageProps });\n } else {\n element = React.createElement(PageComponent, pageProps);\n }\n element = wrapWithRouterContext(element);\n\n if (typeof resetSSRHead === \"function\") resetSSRHead();\n if (typeof flushPreloads === \"function\") await flushPreloads();\n\n const ssrHeadHTML = typeof getSSRHeadHTML === \"function\" ? getSSRHeadHTML() : \"\";\n\n // Collect SSR font data (Google Font links, font preloads, font-face styles)\n var fontHeadHTML = \"\";\n function _escAttr(s) { return s.replace(/&/g, \"&amp;\").replace(/\"/g, \"&quot;\"); }\n try {\n var fontLinks = typeof _getSSRFontLinks === \"function\" ? _getSSRFontLinks() : [];\n for (var fl of fontLinks) { fontHeadHTML += '<link rel=\"stylesheet\" href=\"' + _escAttr(fl) + '\" />\\\\n '; }\n } catch (e) { /* next/font/google not used */ }\n // Emit <link rel=\"preload\"> for all font files (reuse _allFp collected earlier for Link header)\n for (var fp of _allFp) { fontHeadHTML += '<link rel=\"preload\" href=\"' + _escAttr(fp.href) + '\" as=\"font\" type=\"' + _escAttr(fp.type) + '\" crossorigin />\\\\n '; }\n try {\n var allFontStyles = [];\n if (typeof _getSSRFontStylesGoogle === \"function\") allFontStyles.push(..._getSSRFontStylesGoogle());\n if (typeof _getSSRFontStylesLocal === \"function\") allFontStyles.push(..._getSSRFontStylesLocal());\n if (allFontStyles.length > 0) { fontHeadHTML += '<style data-vinext-fonts>' + allFontStyles.join(\"\\\\n\") + '</style>\\\\n '; }\n } catch (e) { /* font styles not available */ }\n\n const pageModuleIds = route.filePath ? [route.filePath] : [];\n const assetTags = collectAssetTags(manifest, pageModuleIds);\n const nextDataPayload = {\n props: { pageProps }, page: patternToNextFormat(route.pattern), query: params, isFallback: false,\n };\n if (i18nConfig) {\n nextDataPayload.locale = locale;\n nextDataPayload.locales = i18nConfig.locales;\n nextDataPayload.defaultLocale = i18nConfig.defaultLocale;\n }\n const localeGlobals = i18nConfig\n ? \";window.__VINEXT_LOCALE__=\" + safeJsonStringify(locale) +\n \";window.__VINEXT_LOCALES__=\" + safeJsonStringify(i18nConfig.locales) +\n \";window.__VINEXT_DEFAULT_LOCALE__=\" + safeJsonStringify(i18nConfig.defaultLocale)\n : \"\";\n const nextDataScript = \"<script>window.__NEXT_DATA__ = \" + safeJsonStringify(nextDataPayload) + localeGlobals + \"</script>\";\n\n // Build the document shell with a placeholder for the streamed body\n var BODY_MARKER = \"<!--VINEXT_STREAM_BODY-->\";\n var shellHtml;\n if (DocumentComponent) {\n const docElement = React.createElement(DocumentComponent);\n shellHtml = await renderToStringAsync(docElement);\n shellHtml = shellHtml.replace(\"__NEXT_MAIN__\", BODY_MARKER);\n if (ssrHeadHTML || assetTags || fontHeadHTML) {\n shellHtml = shellHtml.replace(\"</head>\", \" \" + fontHeadHTML + ssrHeadHTML + \"\\\\n \" + assetTags + \"\\\\n</head>\");\n }\n shellHtml = shellHtml.replace(\"<!-- __NEXT_SCRIPTS__ -->\", nextDataScript);\n if (!shellHtml.includes(\"__NEXT_DATA__\")) {\n shellHtml = shellHtml.replace(\"</body>\", \" \" + nextDataScript + \"\\\\n</body>\");\n }\n } else {\n shellHtml = \"<!DOCTYPE html>\\\\n<html>\\\\n<head>\\\\n <meta charset=\\\\\"utf-8\\\\\" />\\\\n <meta name=\\\\\"viewport\\\\\" content=\\\\\"width=device-width, initial-scale=1\\\\\" />\\\\n \" + fontHeadHTML + ssrHeadHTML + \"\\\\n \" + assetTags + \"\\\\n</head>\\\\n<body>\\\\n <div id=\\\\\"__next\\\\\">\" + BODY_MARKER + \"</div>\\\\n \" + nextDataScript + \"\\\\n</body>\\\\n</html>\";\n }\n\n if (typeof setSSRContext === \"function\") setSSRContext(null);\n\n // Split the shell at the body marker\n var markerIdx = shellHtml.indexOf(BODY_MARKER);\n var shellPrefix = shellHtml.slice(0, markerIdx);\n var shellSuffix = shellHtml.slice(markerIdx + BODY_MARKER.length);\n\n // Start the React body stream — progressive SSR (no allReady wait)\n var bodyStream = await renderToReadableStream(element);\n var encoder = new TextEncoder();\n\n // Create a composite stream: prefix + body + suffix\n var compositeStream = new ReadableStream({\n async start(controller) {\n controller.enqueue(encoder.encode(shellPrefix));\n var reader = bodyStream.getReader();\n try {\n for (;;) {\n var chunk = await reader.read();\n if (chunk.done) break;\n controller.enqueue(chunk.value);\n }\n } finally {\n reader.releaseLock();\n }\n controller.enqueue(encoder.encode(shellSuffix));\n controller.close();\n }\n });\n\n // Cache the rendered HTML for ISR (needs the full string — re-render synchronously)\n if (isrRevalidateSeconds !== null && isrRevalidateSeconds > 0) {\n // Tee the stream so we can cache and respond simultaneously would be ideal,\n // but ISR responses are rare on first hit. Re-render to get complete HTML for cache.\n var isrElement;\n if (AppComponent) {\n isrElement = React.createElement(AppComponent, { Component: PageComponent, pageProps });\n } else {\n isrElement = React.createElement(PageComponent, pageProps);\n }\n isrElement = wrapWithRouterContext(isrElement);\n var isrHtml = await renderToStringAsync(isrElement);\n var fullHtml = shellPrefix + isrHtml + shellSuffix;\n var isrPathname = url.split(\"?\")[0];\n var isrCacheKey = \"pages:\" + (isrPathname === \"/\" ? \"/\" : isrPathname.replace(/\\\\/$/, \"\"));\n await isrSet(isrCacheKey, { kind: \"PAGES\", html: fullHtml, pageData: pageProps, headers: undefined, status: undefined }, isrRevalidateSeconds);\n }\n\n // Merge headers/status/cookies set by getServerSideProps on the res object.\n // gSSP commonly uses res.setHeader(\"Set-Cookie\", ...) or res.status(304).\n var finalStatus = 200;\n const responseHeaders = new Headers({ \"Content-Type\": \"text/html\" });\n if (gsspRes) {\n finalStatus = gsspRes.statusCode;\n var gsspHeaders = gsspRes.getHeaders();\n for (var hk of Object.keys(gsspHeaders)) {\n var hv = gsspHeaders[hk];\n if (hk === \"set-cookie\" && Array.isArray(hv)) {\n for (var sc of hv) responseHeaders.append(\"set-cookie\", sc);\n } else if (hv != null) {\n responseHeaders.set(hk, String(hv));\n }\n }\n // Ensure Content-Type stays text/html (gSSP shouldn't override it for page renders)\n responseHeaders.set(\"Content-Type\", \"text/html\");\n }\n if (isrRevalidateSeconds) {\n responseHeaders.set(\"Cache-Control\", \"s-maxage=\" + isrRevalidateSeconds + \", stale-while-revalidate\");\n responseHeaders.set(\"X-Vinext-Cache\", \"MISS\");\n }\n // Set HTTP Link header for font preloading\n if (_fontLinkHeader) {\n responseHeaders.set(\"Link\", _fontLinkHeader);\n }\n return new Response(compositeStream, { status: finalStatus, headers: responseHeaders });\n } catch (e) {\n console.error(\"[vinext] SSR error:\", e);\n return new Response(\"Internal Server Error\", { status: 500 });\n }\n }) // end runWithFetchCache\n ) // end runWithPrivateCache\n ) // end _runWithCacheState\n ) // end runWithHeadState\n ); // end runWithRouterState\n}\n\nexport async function handleApiRoute(request, url) {\n const match = matchRoute(url, apiRoutes);\n if (!match) {\n return new Response(\"404 - API route not found\", { status: 404 });\n }\n\n const { route, params } = match;\n const handler = route.module.default;\n if (typeof handler !== \"function\") {\n return new Response(\"API route does not export a default function\", { status: 500 });\n }\n\n const query = { ...params };\n const qs = url.split(\"?\")[1];\n if (qs) {\n for (const [k, v] of new URLSearchParams(qs)) {\n if (k in query) {\n // Multi-value: promote to array (Next.js returns string[] for duplicate keys)\n query[k] = Array.isArray(query[k]) ? query[k].concat(v) : [query[k], v];\n } else {\n query[k] = v;\n }\n }\n }\n\n // Parse request body (enforce 1MB limit to prevent memory exhaustion,\n // matching Next.js default bodyParser sizeLimit).\n // Check Content-Length first as a fast path, then enforce on the actual\n // stream to prevent bypasses via chunked transfer encoding.\n const contentLength = parseInt(request.headers.get(\"content-length\") || \"0\", 10);\n if (contentLength > 1 * 1024 * 1024) {\n return new Response(\"Request body too large\", { status: 413 });\n }\n let body;\n const ct = request.headers.get(\"content-type\") || \"\";\n let rawBody;\n try { rawBody = await readBodyWithLimit(request, 1 * 1024 * 1024); }\n catch { return new Response(\"Request body too large\", { status: 413 }); }\n if (!rawBody) {\n body = undefined;\n } else if (ct.includes(\"application/json\")) {\n try { body = JSON.parse(rawBody); } catch { body = rawBody; }\n } else {\n body = rawBody;\n }\n\n const { req, res, responsePromise } = createReqRes(request, url, query, body);\n\n try {\n await handler(req, res);\n // If handler didn't call res.end(), end it now.\n // The end() method is idempotent — safe to call twice.\n res.end();\n return await responsePromise;\n } catch (e) {\n console.error(\"[vinext] API error:\", e);\n return new Response(\"Internal Server Error\", { status: 500 });\n }\n}\n\n${middlewareExportCode}\n`;\n}\n"]}
1
+ {"version":3,"file":"pages-server-entry.js","sourceRoot":"","sources":["../../src/entries/pages-server-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAc,MAAM,4BAA4B,CAAC;AAGhF,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EACL,sBAAsB,EACtB,6BAA6B,EAC7B,yBAAyB,GAC1B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,MAAM,uBAAuB,GAAG,aAAa,CAC3C,IAAI,GAAG,CAAC,6BAA6B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CACxD,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAEtB;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAgB,EAChB,UAA8B,EAC9B,WAAsD,EACtD,cAA6B,EAC7B,mBAAkC;IAElC,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC;IACxF,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,QAAQ,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC;IAErF,gEAAgE;IAChE,mEAAmE;IACnE,MAAM,WAAW,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAQ,EAAE,CAAS,EAAE,EAAE;QACzD,MAAM,OAAO,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC/C,OAAO,oBAAoB,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAQ,EAAE,CAAS,EAAE,EAAE;QACvD,MAAM,OAAO,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC/C,OAAO,mBAAmB,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,mEAAmE;IACnE,MAAM,gBAAgB,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAQ,EAAE,CAAS,EAAE,EAAE;QAC9D,MAAM,OAAO,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC/C,OAAO,gBAAgB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,mBAAmB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC,SAAS,aAAa,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,eAAe,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC;IACjO,CAAC,CAAC,CAAC;IAEH,MAAM,eAAe,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAQ,EAAE,CAAS,EAAE,EAAE;QAC5D,OAAO,gBAAgB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,mBAAmB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC,SAAS,aAAa,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC;IAC1L,CAAC,CAAC,CAAC;IAEH,+BAA+B;IAC/B,MAAM,WAAW,GAAG,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;IACpE,MAAM,WAAW,GAAG,gBAAgB,CAAC,QAAQ,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;IACzE,MAAM,MAAM,GAAG,WAAW,KAAK,IAAI,CAAC;IACpC,MAAM,MAAM,GAAG,WAAW,KAAK,IAAI,CAAC;IAEpC,MAAM,aAAa,GAAG,MAAM;QAC1B,CAAC,CAAC,2CAA2C,IAAI,CAAC,SAAS,CAAC,WAAY,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,GAAG;QAChG,CAAC,CAAC,4BAA4B,CAAC;IAEjC,MAAM,aAAa,GAAG,MAAM;QAC1B,CAAC,CAAC,gDAAgD,IAAI,CAAC,SAAS,CAAC,WAAY,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,GAAG;QACrG,CAAC,CAAC,iCAAiC,CAAC;IAEtC,0DAA0D;IAC1D,MAAM,cAAc,GAAG,UAAU,EAAE,IAAI;QACrC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;YACb,OAAO,EAAE,UAAU,CAAC,IAAI,CAAC,OAAO;YAChC,aAAa,EAAE,UAAU,CAAC,IAAI,CAAC,aAAa;YAC5C,eAAe,EAAE,UAAU,CAAC,IAAI,CAAC,eAAe;SACjD,CAAC;QACJ,CAAC,CAAC,MAAM,CAAC;IAEX,4CAA4C;IAC5C,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,OAAO,IAAI,IAAI,CAAC,CAAC;IAEhE,gEAAgE;IAChE,oEAAoE;IACpE,8EAA8E;IAC9E,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC;QACtC,QAAQ,EAAE,UAAU,EAAE,QAAQ,IAAI,EAAE;QACpC,aAAa,EAAE,UAAU,EAAE,aAAa,IAAI,KAAK;QACjD,SAAS,EAAE,UAAU,EAAE,SAAS,IAAI,EAAE;QACtC,QAAQ,EAAE,UAAU,EAAE,QAAQ,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QACnF,OAAO,EAAE,UAAU,EAAE,OAAO,IAAI,EAAE;QAClC,IAAI,EAAE,UAAU,EAAE,IAAI,IAAI,IAAI;QAC9B,MAAM,EAAE;YACN,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW;YAC5C,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU;YAC1C,mBAAmB,EAAE,UAAU,EAAE,MAAM,EAAE,mBAAmB;YAC5D,sBAAsB,EAAE,UAAU,EAAE,MAAM,EAAE,sBAAsB;YAClE,qBAAqB,EAAE,UAAU,EAAE,MAAM,EAAE,qBAAqB;SACjE;KACF,CAAC,CAAC;IAEH,8DAA8D;IAC9D,8EAA8E;IAC9E,mFAAmF;IACnF,qFAAqF;IACrF,gFAAgF;IAChF,yBAAyB;IACzB,EAAE;IACF,6EAA6E;IAC7E,kDAAkD;IAClD,MAAM,yBAAyB,GAAG,mBAAmB;QACnD,CAAC,CAAC,qCAAqC,IAAI,CAAC,SAAS,CAAC,mBAAmB,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,GAAG;QACjG,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,uBAAuB,GAAG,mBAAmB;QACjD,CAAC,CAAC;;;;;;;;;;EAUJ;QACE,CAAC,CAAC,EAAE,CAAC;IAEP,mDAAmD;IACnD,MAAM,oBAAoB,GAAG,cAAc;QACzC,CAAC,CAAC,qCAAqC,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;2DAClC;QACvD,CAAC,CAAC,EAAE,CAAC;IAEP,wEAAwE;IACxE,2EAA2E;IAC3E,MAAM,oBAAoB,GAAG,cAAc;QACzC,CAAC,CAAC;;EAEJ,yBAAyB,CAAC,KAAK,CAAC;EAChC,sBAAsB,CAAC,KAAK,CAAC;EAC7B,6BAA6B,CAAC,KAAK,CAAC;;;;;;;;kBAQpB,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqFvF;QACG,CAAC,CAAC;;CAEL,CAAC;IAEA,0EAA0E;IAC1E,+EAA+E;IAC/E,OAAO;;;;;;;;;;;;;;;;+BAgBsB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,8BAA8B,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;iIACO,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC;EACtK,yBAAyB;EACzB,oBAAoB;;EAEpB,uBAAuB;;;qBAGJ,cAAc;;;kBAGjB,WAAW;;;8BAGC,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+D5C,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;EACtB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;;EAErB,aAAa;EACb,aAAa;;;EAGb,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC;;;;EAI5B,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAguB3B,oBAAoB;CACrB,CAAC;AACF,CAAC","sourcesContent":["/**\n * Pages Router server entry generator.\n *\n * Generates the virtual SSR server entry module (`virtual:vinext-server-entry`).\n * This is the entry point for `vite build --ssr`. It handles SSR, API routes,\n * middleware, ISR, and i18n for the Pages Router.\n *\n * Extracted from index.ts.\n */\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { pagesRouter, apiRouter, type Route } from \"../routing/pages-router.js\";\nimport { createValidFileMatcher } from \"../routing/file-matcher.js\";\nimport { type ResolvedNextConfig } from \"../config/next-config.js\";\nimport { isProxyFile } from \"../server/middleware.js\";\nimport {\n generateSafeRegExpCode,\n generateMiddlewareMatcherCode,\n generateNormalizePathCode,\n} from \"../server/middleware-codegen.js\";\nimport { findFileWithExts } from \"./pages-entry-helpers.js\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst _requestContextShimPath = fileURLToPath(\n new URL(\"../shims/request-context.js\", import.meta.url),\n).replace(/\\\\/g, \"/\");\n\n/**\n * Generate the virtual SSR server entry module.\n * This is the entry point for `vite build --ssr`.\n */\nexport async function generateServerEntry(\n pagesDir: string,\n nextConfig: ResolvedNextConfig,\n fileMatcher: ReturnType<typeof createValidFileMatcher>,\n middlewarePath: string | null,\n instrumentationPath: string | null,\n): Promise<string> {\n const pageRoutes = await pagesRouter(pagesDir, nextConfig?.pageExtensions, fileMatcher);\n const apiRoutes = await apiRouter(pagesDir, nextConfig?.pageExtensions, fileMatcher);\n\n // Generate import statements using absolute paths since virtual\n // modules don't have a real file location for relative resolution.\n const pageImports = pageRoutes.map((r: Route, i: number) => {\n const absPath = r.filePath.replace(/\\\\/g, \"/\");\n return `import * as page_${i} from ${JSON.stringify(absPath)};`;\n });\n\n const apiImports = apiRoutes.map((r: Route, i: number) => {\n const absPath = r.filePath.replace(/\\\\/g, \"/\");\n return `import * as api_${i} from ${JSON.stringify(absPath)};`;\n });\n\n // Build the route table — include filePath for SSR manifest lookup\n const pageRouteEntries = pageRoutes.map((r: Route, i: number) => {\n const absPath = r.filePath.replace(/\\\\/g, \"/\");\n return ` { pattern: ${JSON.stringify(r.pattern)}, patternParts: ${JSON.stringify(r.patternParts)}, isDynamic: ${r.isDynamic}, params: ${JSON.stringify(r.params)}, module: page_${i}, filePath: ${JSON.stringify(absPath)} }`;\n });\n\n const apiRouteEntries = apiRoutes.map((r: Route, i: number) => {\n return ` { pattern: ${JSON.stringify(r.pattern)}, patternParts: ${JSON.stringify(r.patternParts)}, isDynamic: ${r.isDynamic}, params: ${JSON.stringify(r.params)}, module: api_${i} }`;\n });\n\n // Check for _app and _document\n const appFilePath = findFileWithExts(pagesDir, \"_app\", fileMatcher);\n const docFilePath = findFileWithExts(pagesDir, \"_document\", fileMatcher);\n const hasApp = appFilePath !== null;\n const hasDoc = docFilePath !== null;\n\n const appImportCode = hasApp\n ? `import { default as AppComponent } from ${JSON.stringify(appFilePath!.replace(/\\\\/g, \"/\"))};`\n : `const AppComponent = null;`;\n\n const docImportCode = hasDoc\n ? `import { default as DocumentComponent } from ${JSON.stringify(docFilePath!.replace(/\\\\/g, \"/\"))};`\n : `const DocumentComponent = null;`;\n\n // Serialize i18n config for embedding in the server entry\n const i18nConfigJson = nextConfig?.i18n\n ? JSON.stringify({\n locales: nextConfig.i18n.locales,\n defaultLocale: nextConfig.i18n.defaultLocale,\n localeDetection: nextConfig.i18n.localeDetection,\n })\n : \"null\";\n\n // Embed the resolved build ID at build time\n const buildIdJson = JSON.stringify(nextConfig?.buildId ?? null);\n\n // Serialize the full resolved config for the production server.\n // This embeds redirects, rewrites, headers, basePath, trailingSlash\n // so prod-server.ts can apply them without loading next.config.js at runtime.\n const vinextConfigJson = JSON.stringify({\n basePath: nextConfig?.basePath ?? \"\",\n trailingSlash: nextConfig?.trailingSlash ?? false,\n redirects: nextConfig?.redirects ?? [],\n rewrites: nextConfig?.rewrites ?? { beforeFiles: [], afterFiles: [], fallback: [] },\n headers: nextConfig?.headers ?? [],\n i18n: nextConfig?.i18n ?? null,\n images: {\n deviceSizes: nextConfig?.images?.deviceSizes,\n imageSizes: nextConfig?.images?.imageSizes,\n dangerouslyAllowSVG: nextConfig?.images?.dangerouslyAllowSVG,\n contentDispositionType: nextConfig?.images?.contentDispositionType,\n contentSecurityPolicy: nextConfig?.images?.contentSecurityPolicy,\n },\n });\n\n // Generate instrumentation code if instrumentation.ts exists.\n // For production (Cloudflare Workers), instrumentation.ts is bundled into the\n // Worker and register() is called as a top-level await at module evaluation time —\n // before any request is handled. This mirrors App Router behavior (generateRscEntry)\n // and matches Next.js semantics: register() runs once on startup in the process\n // that handles requests.\n //\n // The onRequestError handler is stored on globalThis so it is visible across\n // all code within the Worker (same global scope).\n const instrumentationImportCode = instrumentationPath\n ? `import * as _instrumentation from ${JSON.stringify(instrumentationPath.replace(/\\\\/g, \"/\"))};`\n : \"\";\n\n const instrumentationInitCode = instrumentationPath\n ? `// Run instrumentation register() once at module evaluation time — before any\n// requests are handled. Matches Next.js semantics: register() is called once\n// on startup in the process that handles requests.\nif (typeof _instrumentation.register === \"function\") {\n await _instrumentation.register();\n}\n// Store the onRequestError handler on globalThis so it is visible to all\n// code within the Worker (same global scope).\nif (typeof _instrumentation.onRequestError === \"function\") {\n globalThis.__VINEXT_onRequestErrorHandler__ = _instrumentation.onRequestError;\n}`\n : \"\";\n\n // Generate middleware code if middleware.ts exists\n const middlewareImportCode = middlewarePath\n ? `import * as middlewareModule from ${JSON.stringify(middlewarePath.replace(/\\\\/g, \"/\"))};\nimport { NextRequest, NextFetchEvent } from \"next/server\";`\n : \"\";\n\n // The matcher config is read from the middleware module at import time.\n // We inline the matching + execution logic so the prod server can call it.\n const middlewareExportCode = middlewarePath\n ? `\n// --- Middleware support (generated from middleware-codegen.ts) ---\n${generateNormalizePathCode(\"es5\")}\n${generateSafeRegExpCode(\"es5\")}\n${generateMiddlewareMatcherCode(\"es5\")}\n\nexport async function runMiddleware(request, ctx) {\n if (ctx) return _runWithExecutionContext(ctx, () => _runMiddleware(request));\n return _runMiddleware(request);\n}\n\nasync function _runMiddleware(request) {\n var isProxy = ${middlewarePath ? JSON.stringify(isProxyFile(middlewarePath)) : \"false\"};\n var middlewareFn = isProxy\n ? (middlewareModule.proxy ?? middlewareModule.default)\n : (middlewareModule.middleware ?? middlewareModule.default);\n if (typeof middlewareFn !== \"function\") {\n var fileType = isProxy ? \"Proxy\" : \"Middleware\";\n var expectedExport = isProxy ? \"proxy\" : \"middleware\";\n throw new Error(\"The \" + fileType + \" file must export a function named \\`\" + expectedExport + \"\\` or a \\`default\\` function.\");\n }\n\n var config = middlewareModule.config;\n var matcher = config && config.matcher;\n var url = new URL(request.url);\n\n // Normalize pathname before matching to prevent path-confusion bypasses\n // (percent-encoding like /%61dmin, double slashes like /dashboard//settings).\n var decodedPathname;\n try { decodedPathname = decodeURIComponent(url.pathname); } catch (e) {\n return { continue: false, response: new Response(\"Bad Request\", { status: 400 }) };\n }\n var normalizedPathname = __normalizePath(decodedPathname);\n\n if (!matchesMiddleware(normalizedPathname, matcher, request, i18nConfig)) return { continue: true };\n\n // Construct a new Request with the decoded + normalized pathname so middleware\n // always sees the same canonical path that the router uses.\n var mwRequest = request;\n if (normalizedPathname !== url.pathname) {\n var mwUrl = new URL(url);\n mwUrl.pathname = normalizedPathname;\n mwRequest = new Request(mwUrl, request);\n }\n var nextRequest = mwRequest instanceof NextRequest ? mwRequest : new NextRequest(mwRequest);\n var fetchEvent = new NextFetchEvent({ page: normalizedPathname });\n var response;\n try { response = await middlewareFn(nextRequest, fetchEvent); }\n catch (e) {\n console.error(\"[vinext] Middleware error:\", e);\n return { continue: false, response: new Response(\"Internal Server Error\", { status: 500 }) };\n }\n var _mwCtx = _getRequestExecutionContext();\n if (_mwCtx && typeof _mwCtx.waitUntil === \"function\") { _mwCtx.waitUntil(fetchEvent.drainWaitUntil()); } else { fetchEvent.drainWaitUntil(); }\n\n if (!response) return { continue: true };\n\n if (response.headers.get(\"x-middleware-next\") === \"1\") {\n var rHeaders = new Headers();\n for (var [key, value] of response.headers) {\n // Keep x-middleware-request-* headers so the production server can\n // apply middleware-request header overrides before stripping internals\n // from the final client response.\n if (\n !key.startsWith(\"x-middleware-\") ||\n key === \"x-middleware-override-headers\" ||\n key.startsWith(\"x-middleware-request-\")\n ) rHeaders.append(key, value);\n }\n return { continue: true, responseHeaders: rHeaders };\n }\n\n if (response.status >= 300 && response.status < 400) {\n var location = response.headers.get(\"Location\") || response.headers.get(\"location\");\n if (location) {\n var rdHeaders = new Headers();\n for (var [rk, rv] of response.headers) {\n if (!rk.startsWith(\"x-middleware-\") && rk.toLowerCase() !== \"location\") rdHeaders.append(rk, rv);\n }\n return { continue: false, redirectUrl: location, redirectStatus: response.status, responseHeaders: rdHeaders };\n }\n }\n\n var rewriteUrl = response.headers.get(\"x-middleware-rewrite\");\n if (rewriteUrl) {\n var rwHeaders = new Headers();\n for (var [k, v] of response.headers) {\n if (!k.startsWith(\"x-middleware-\") || k === \"x-middleware-override-headers\" || k.startsWith(\"x-middleware-request-\")) rwHeaders.append(k, v);\n }\n var rewritePath;\n try { var parsed = new URL(rewriteUrl, request.url); rewritePath = parsed.pathname + parsed.search; }\n catch { rewritePath = rewriteUrl; }\n return { continue: true, rewriteUrl: rewritePath, rewriteStatus: response.status !== 200 ? response.status : undefined, responseHeaders: rwHeaders };\n }\n\n return { continue: false, response: response };\n}\n`\n : `\nexport async function runMiddleware() { return { continue: true }; }\n`;\n\n // The server entry is a self-contained module that uses Web-standard APIs\n // (Request/Response, renderToReadableStream) so it runs on Cloudflare Workers.\n return `\nimport React from \"react\";\nimport { renderToReadableStream } from \"react-dom/server.edge\";\nimport { resetSSRHead, getSSRHeadHTML } from \"next/head\";\nimport { flushPreloads } from \"next/dynamic\";\nimport { setSSRContext, wrapWithRouterContext } from \"next/router\";\nimport { getCacheHandler } from \"next/cache\";\nimport { runWithFetchCache } from \"vinext/fetch-cache\";\nimport { _runWithCacheState } from \"next/cache\";\nimport { runWithPrivateCache } from \"vinext/cache-runtime\";\nimport { runWithRouterState } from \"vinext/router-state\";\nimport { runWithHeadState } from \"vinext/head-state\";\nimport { safeJsonStringify } from \"vinext/html\";\nimport { decode as decodeQueryString } from \"node:querystring\";\nimport { getSSRFontLinks as _getSSRFontLinks, getSSRFontStyles as _getSSRFontStylesGoogle, getSSRFontPreloads as _getSSRFontPreloadsGoogle } from \"next/font/google\";\nimport { getSSRFontStyles as _getSSRFontStylesLocal, getSSRFontPreloads as _getSSRFontPreloadsLocal } from \"next/font/local\";\nimport { parseCookies } from ${JSON.stringify(path.resolve(__dirname, \"../config/config-matchers.js\").replace(/\\\\/g, \"/\"))};\nimport { runWithExecutionContext as _runWithExecutionContext, getRequestExecutionContext as _getRequestExecutionContext } from ${JSON.stringify(_requestContextShimPath)};\n${instrumentationImportCode}\n${middlewareImportCode}\n\n${instrumentationInitCode}\n\n// i18n config (embedded at build time)\nconst i18nConfig = ${i18nConfigJson};\n\n// Build ID (embedded at build time)\nconst buildId = ${buildIdJson};\n\n// Full resolved config for production server (embedded at build time)\nexport const vinextConfig = ${vinextConfigJson};\n\nclass ApiBodyParseError extends Error {\n constructor(message, statusCode) {\n super(message);\n this.statusCode = statusCode;\n this.name = \"ApiBodyParseError\";\n }\n}\n\n// ISR cache helpers (inlined for the server entry)\nasync function isrGet(key) {\n const handler = getCacheHandler();\n const result = await handler.get(key);\n if (!result || !result.value) return null;\n return { value: result, isStale: result.cacheState === \"stale\" };\n}\nasync function isrSet(key, data, revalidateSeconds, tags) {\n const handler = getCacheHandler();\n await handler.set(key, data, { revalidate: revalidateSeconds, tags: tags || [] });\n}\nconst pendingRegenerations = new Map();\nfunction triggerBackgroundRegeneration(key, renderFn) {\n if (pendingRegenerations.has(key)) return;\n const promise = renderFn()\n .catch((err) => console.error(\"[vinext] ISR regen failed for \" + key + \":\", err))\n .finally(() => pendingRegenerations.delete(key));\n pendingRegenerations.set(key, promise);\n // Register with the Workers ExecutionContext so the isolate is kept alive\n // until the regeneration finishes, even after the Response has been sent.\n const ctx = _getRequestExecutionContext();\n if (ctx && typeof ctx.waitUntil === \"function\") ctx.waitUntil(promise);\n}\n\nfunction fnv1a64(input) {\n let h1 = 0x811c9dc5;\n for (let i = 0; i < input.length; i++) {\n h1 ^= input.charCodeAt(i);\n h1 = (h1 * 0x01000193) >>> 0;\n }\n let h2 = 0x050c5d1f;\n for (let i = 0; i < input.length; i++) {\n h2 ^= input.charCodeAt(i);\n h2 = (h2 * 0x01000193) >>> 0;\n }\n return h1.toString(36) + h2.toString(36);\n}\n// Keep prefix construction and hashing logic in sync with isrCacheKey() in server/isr-cache.ts.\n// buildId is a top-level const in the generated entry (see \"const buildId = ...\" above).\nfunction isrCacheKey(router, pathname) {\n const normalized = pathname === \"/\" ? \"/\" : pathname.replace(/\\\\/$/, \"\");\n const prefix = buildId ? router + \":\" + buildId : router;\n const key = prefix + \":\" + normalized;\n if (key.length <= 200) return key;\n return prefix + \":__hash:\" + fnv1a64(normalized);\n}\n\nasync function renderToStringAsync(element) {\n const stream = await renderToReadableStream(element);\n await stream.allReady;\n return new Response(stream).text();\n}\n\n${pageImports.join(\"\\n\")}\n${apiImports.join(\"\\n\")}\n\n${appImportCode}\n${docImportCode}\n\nconst pageRoutes = [\n${pageRouteEntries.join(\",\\n\")}\n];\n\nconst apiRoutes = [\n${apiRouteEntries.join(\",\\n\")}\n];\n\nfunction matchRoute(url, routes) {\n const pathname = url.split(\"?\")[0];\n let normalizedUrl = pathname === \"/\" ? \"/\" : pathname.replace(/\\\\/$/, \"\");\n // NOTE: Do NOT decodeURIComponent here. The pathname is already decoded at\n // the entry point. Decoding again would create a double-decode vector.\n const urlParts = normalizedUrl.split(\"/\").filter(Boolean);\n for (const route of routes) {\n const params = matchPattern(urlParts, route.patternParts);\n if (params !== null) return { route, params };\n }\n return null;\n}\n\nfunction matchPattern(urlParts, patternParts) {\n const params = Object.create(null);\n for (let i = 0; i < patternParts.length; i++) {\n const pp = patternParts[i];\n if (pp.endsWith(\"+\")) {\n if (i !== patternParts.length - 1) return null;\n const paramName = pp.slice(1, -1);\n const remaining = urlParts.slice(i);\n if (remaining.length === 0) return null;\n params[paramName] = remaining;\n return params;\n }\n if (pp.endsWith(\"*\")) {\n if (i !== patternParts.length - 1) return null;\n const paramName = pp.slice(1, -1);\n params[paramName] = urlParts.slice(i);\n return params;\n }\n if (pp.startsWith(\":\")) {\n if (i >= urlParts.length) return null;\n params[pp.slice(1)] = urlParts[i];\n continue;\n }\n if (i >= urlParts.length || urlParts[i] !== pp) return null;\n }\n if (urlParts.length !== patternParts.length) return null;\n return params;\n}\n\nfunction parseQuery(url) {\n const qs = url.split(\"?\")[1];\n if (!qs) return {};\n const p = new URLSearchParams(qs);\n const q = {};\n for (const [k, v] of p) {\n if (k in q) {\n q[k] = Array.isArray(q[k]) ? q[k].concat(v) : [q[k], v];\n } else {\n q[k] = v;\n }\n }\n return q;\n}\n\nfunction patternToNextFormat(pattern) {\n return pattern\n .replace(/:([\\\\w]+)\\\\*/g, \"[[...$1]]\")\n .replace(/:([\\\\w]+)\\\\+/g, \"[...$1]\")\n .replace(/:([\\\\w]+)/g, \"[$1]\");\n}\n\nfunction collectAssetTags(manifest, moduleIds) {\n // Fall back to embedded manifest (set by vinext:cloudflare-build for Workers)\n const m = (manifest && Object.keys(manifest).length > 0)\n ? manifest\n : (typeof globalThis !== \"undefined\" && globalThis.__VINEXT_SSR_MANIFEST__) || null;\n const tags = [];\n const seen = new Set();\n\n // Load the set of lazy chunk filenames (only reachable via dynamic imports).\n // These should NOT get <link rel=\"modulepreload\"> or <script type=\"module\">\n // tags — they are fetched on demand when the dynamic import() executes (e.g.\n // chunks behind React.lazy() or next/dynamic boundaries).\n var lazyChunks = (typeof globalThis !== \"undefined\" && globalThis.__VINEXT_LAZY_CHUNKS__) || null;\n var lazySet = lazyChunks && lazyChunks.length > 0 ? new Set(lazyChunks) : null;\n\n // Inject the client entry script if embedded by vinext:cloudflare-build\n if (typeof globalThis !== \"undefined\" && globalThis.__VINEXT_CLIENT_ENTRY__) {\n const entry = globalThis.__VINEXT_CLIENT_ENTRY__;\n seen.add(entry);\n tags.push('<link rel=\"modulepreload\" href=\"/' + entry + '\" />');\n tags.push('<script type=\"module\" src=\"/' + entry + '\" crossorigin></script>');\n }\n if (m) {\n // Always inject shared chunks (framework, vinext runtime, entry) and\n // page-specific chunks. The manifest maps module file paths to their\n // associated JS/CSS assets.\n //\n // For page-specific injection, the module IDs may be absolute paths\n // while the manifest uses relative paths. Try both the original ID\n // and a suffix match to find the correct manifest entry.\n var allFiles = [];\n\n if (moduleIds && moduleIds.length > 0) {\n // Collect assets for the requested page modules\n for (var mi = 0; mi < moduleIds.length; mi++) {\n var id = moduleIds[mi];\n var files = m[id];\n if (!files) {\n // Absolute path didn't match — try matching by suffix.\n // Manifest keys are relative (e.g. \"pages/about.tsx\") while\n // moduleIds may be absolute (e.g. \"/home/.../pages/about.tsx\").\n for (var mk in m) {\n if (id.endsWith(\"/\" + mk) || id === mk) {\n files = m[mk];\n break;\n }\n }\n }\n if (files) {\n for (var fi = 0; fi < files.length; fi++) allFiles.push(files[fi]);\n }\n }\n\n // Also inject shared chunks that every page needs: framework,\n // vinext runtime, and the entry bootstrap. These are identified\n // by scanning all manifest values for chunk filenames containing\n // known prefixes.\n for (var key in m) {\n var vals = m[key];\n if (!vals) continue;\n for (var vi = 0; vi < vals.length; vi++) {\n var file = vals[vi];\n var basename = file.split(\"/\").pop() || \"\";\n if (\n basename.startsWith(\"framework-\") ||\n basename.startsWith(\"vinext-\") ||\n basename.includes(\"vinext-client-entry\") ||\n basename.includes(\"vinext-app-browser-entry\")\n ) {\n allFiles.push(file);\n }\n }\n }\n } else {\n // No specific modules — include all assets from manifest\n for (var akey in m) {\n var avals = m[akey];\n if (avals) {\n for (var ai = 0; ai < avals.length; ai++) allFiles.push(avals[ai]);\n }\n }\n }\n\n for (var ti = 0; ti < allFiles.length; ti++) {\n var tf = allFiles[ti];\n // Normalize: Vite's SSR manifest values include a leading '/'\n // (from base path), but we prepend '/' ourselves when building\n // href/src attributes. Strip any existing leading slash to avoid\n // producing protocol-relative URLs like \"//assets/chunk.js\".\n // This also ensures consistent keys for the seen-set dedup and\n // lazySet.has() checks (which use values without leading slash).\n if (tf.charAt(0) === '/') tf = tf.slice(1);\n if (seen.has(tf)) continue;\n seen.add(tf);\n if (tf.endsWith(\".css\")) {\n tags.push('<link rel=\"stylesheet\" href=\"/' + tf + '\" />');\n } else if (tf.endsWith(\".js\")) {\n // Skip lazy chunks — they are behind dynamic import() boundaries\n // (React.lazy, next/dynamic) and should only be fetched on demand.\n if (lazySet && lazySet.has(tf)) continue;\n tags.push('<link rel=\"modulepreload\" href=\"/' + tf + '\" />');\n tags.push('<script type=\"module\" src=\"/' + tf + '\" crossorigin></script>');\n }\n }\n }\n return tags.join(\"\\\\n \");\n}\n\n// i18n helpers\nfunction extractLocale(url) {\n if (!i18nConfig) return { locale: undefined, url, hadPrefix: false };\n const pathname = url.split(\"?\")[0];\n const parts = pathname.split(\"/\").filter(Boolean);\n const query = url.includes(\"?\") ? url.slice(url.indexOf(\"?\")) : \"\";\n if (parts.length > 0 && i18nConfig.locales.includes(parts[0])) {\n const locale = parts[0];\n const rest = \"/\" + parts.slice(1).join(\"/\");\n return { locale, url: (rest || \"/\") + query, hadPrefix: true };\n }\n return { locale: i18nConfig.defaultLocale, url, hadPrefix: false };\n}\n\nfunction detectLocaleFromHeaders(headers) {\n if (!i18nConfig) return null;\n const acceptLang = headers.get(\"accept-language\");\n if (!acceptLang) return null;\n const langs = acceptLang.split(\",\").map(function(part) {\n const pieces = part.trim().split(\";\");\n const q = pieces[1] ? parseFloat(pieces[1].replace(\"q=\", \"\")) : 1;\n return { lang: pieces[0].trim().toLowerCase(), q: q };\n }).sort(function(a, b) { return b.q - a.q; });\n for (let k = 0; k < langs.length; k++) {\n const lang = langs[k].lang;\n for (let j = 0; j < i18nConfig.locales.length; j++) {\n if (i18nConfig.locales[j].toLowerCase() === lang) return i18nConfig.locales[j];\n }\n const prefix = lang.split(\"-\")[0];\n for (let j = 0; j < i18nConfig.locales.length; j++) {\n const loc = i18nConfig.locales[j].toLowerCase();\n if (loc === prefix || loc.startsWith(prefix + \"-\")) return i18nConfig.locales[j];\n }\n }\n return null;\n}\n\nfunction parseCookieLocaleFromHeader(cookieHeader) {\n if (!i18nConfig || !cookieHeader) return null;\n const match = cookieHeader.match(/(?:^|;\\\\s*)NEXT_LOCALE=([^;]*)/);\n if (!match) return null;\n var value;\n try { value = decodeURIComponent(match[1].trim()); } catch (e) { return null; }\n if (i18nConfig.locales.indexOf(value) !== -1) return value;\n return null;\n}\n\n// Lightweight req/res facade for getServerSideProps and API routes.\n// Next.js pages expect ctx.req/ctx.res with Node-like shapes.\nfunction createReqRes(request, url, query, body) {\n const headersObj = {};\n for (const [k, v] of request.headers) headersObj[k.toLowerCase()] = v;\n\n const req = {\n method: request.method,\n url: url,\n headers: headersObj,\n query: query,\n body: body,\n cookies: parseCookies(request.headers.get(\"cookie\")),\n };\n\n let resStatusCode = 200;\n const resHeaders = {};\n // set-cookie needs array support (multiple Set-Cookie headers are common)\n const setCookieHeaders = [];\n let resBody = null;\n let ended = false;\n let resolveResponse;\n const responsePromise = new Promise(function(r) { resolveResponse = r; });\n\n const res = {\n get statusCode() { return resStatusCode; },\n set statusCode(code) { resStatusCode = code; },\n writeHead: function(code, headers) {\n resStatusCode = code;\n if (headers) {\n for (const [k, v] of Object.entries(headers)) {\n if (k.toLowerCase() === \"set-cookie\") {\n if (Array.isArray(v)) { for (const c of v) setCookieHeaders.push(c); }\n else { setCookieHeaders.push(v); }\n } else {\n resHeaders[k] = v;\n }\n }\n }\n return res;\n },\n setHeader: function(name, value) {\n if (name.toLowerCase() === \"set-cookie\") {\n if (Array.isArray(value)) { for (const c of value) setCookieHeaders.push(c); }\n else { setCookieHeaders.push(value); }\n } else {\n resHeaders[name.toLowerCase()] = value;\n }\n return res;\n },\n getHeader: function(name) {\n if (name.toLowerCase() === \"set-cookie\") return setCookieHeaders.length > 0 ? setCookieHeaders : undefined;\n return resHeaders[name.toLowerCase()];\n },\n end: function(data) {\n if (ended) return;\n ended = true;\n if (data !== undefined && data !== null) resBody = data;\n const h = new Headers(resHeaders);\n for (const c of setCookieHeaders) h.append(\"set-cookie\", c);\n resolveResponse(new Response(resBody, { status: resStatusCode, headers: h }));\n },\n status: function(code) { resStatusCode = code; return res; },\n json: function(data) {\n resHeaders[\"content-type\"] = \"application/json\";\n res.end(JSON.stringify(data));\n },\n send: function(data) {\n if (Buffer.isBuffer(data)) {\n if (!resHeaders[\"content-type\"]) resHeaders[\"content-type\"] = \"application/octet-stream\";\n resHeaders[\"content-length\"] = String(data.length);\n res.end(data);\n } else if (typeof data === \"object\" && data !== null) {\n res.json(data);\n } else {\n if (!resHeaders[\"content-type\"]) resHeaders[\"content-type\"] = \"text/plain\";\n res.end(String(data));\n }\n },\n redirect: function(statusOrUrl, url2) {\n if (typeof statusOrUrl === \"string\") { res.writeHead(307, { Location: statusOrUrl }); }\n else { res.writeHead(statusOrUrl, { Location: url2 }); }\n res.end();\n },\n getHeaders: function() {\n var h = Object.assign({}, resHeaders);\n if (setCookieHeaders.length > 0) h[\"set-cookie\"] = setCookieHeaders;\n return h;\n },\n get headersSent() { return ended; },\n };\n\n return { req, res, responsePromise };\n}\n\n/**\n * Read request body as text with a size limit.\n * Throws if the body exceeds maxBytes. This prevents DoS via chunked\n * transfer encoding where Content-Length is absent or spoofed.\n */\nasync function readBodyWithLimit(request, maxBytes) {\n if (!request.body) return \"\";\n var reader = request.body.getReader();\n var decoder = new TextDecoder();\n var chunks = [];\n var totalSize = 0;\n for (;;) {\n var result = await reader.read();\n if (result.done) break;\n totalSize += result.value.byteLength;\n if (totalSize > maxBytes) {\n reader.cancel();\n throw new Error(\"Request body too large\");\n }\n chunks.push(decoder.decode(result.value, { stream: true }));\n }\n chunks.push(decoder.decode());\n return chunks.join(\"\");\n}\n\nexport async function renderPage(request, url, manifest, ctx) {\n if (ctx) return _runWithExecutionContext(ctx, () => _renderPage(request, url, manifest));\n return _renderPage(request, url, manifest);\n}\n\nasync function _renderPage(request, url, manifest) {\n const localeInfo = extractLocale(url);\n const locale = localeInfo.locale;\n const routeUrl = localeInfo.url;\n const cookieHeader = request.headers.get(\"cookie\") || \"\";\n\n // i18n redirect: check NEXT_LOCALE cookie first, then Accept-Language\n if (i18nConfig && !localeInfo.hadPrefix) {\n const cookieLocale = parseCookieLocaleFromHeader(cookieHeader);\n if (cookieLocale && cookieLocale !== i18nConfig.defaultLocale) {\n return new Response(null, { status: 307, headers: { Location: \"/\" + cookieLocale + routeUrl } });\n }\n if (!cookieLocale && i18nConfig.localeDetection !== false) {\n const detected = detectLocaleFromHeaders(request.headers);\n if (detected && detected !== i18nConfig.defaultLocale) {\n return new Response(null, { status: 307, headers: { Location: \"/\" + detected + routeUrl } });\n }\n }\n }\n\n const match = matchRoute(routeUrl, pageRoutes);\n if (!match) {\n return new Response(\"<!DOCTYPE html><html><body><h1>404 - Page not found</h1></body></html>\",\n { status: 404, headers: { \"Content-Type\": \"text/html\" } });\n }\n\n const { route, params } = match;\n return runWithRouterState(() =>\n runWithHeadState(() =>\n _runWithCacheState(() =>\n runWithPrivateCache(() =>\n runWithFetchCache(async () => {\n try {\n if (typeof setSSRContext === \"function\") {\n setSSRContext({\n pathname: patternToNextFormat(route.pattern),\n query: { ...params, ...parseQuery(routeUrl) },\n asPath: routeUrl,\n locale: locale,\n locales: i18nConfig ? i18nConfig.locales : undefined,\n defaultLocale: i18nConfig ? i18nConfig.defaultLocale : undefined,\n });\n }\n\n if (i18nConfig) {\n globalThis.__VINEXT_LOCALE__ = locale;\n globalThis.__VINEXT_LOCALES__ = i18nConfig.locales;\n globalThis.__VINEXT_DEFAULT_LOCALE__ = i18nConfig.defaultLocale;\n }\n\n const pageModule = route.module;\n const PageComponent = pageModule.default;\n if (!PageComponent) {\n return new Response(\"Page has no default export\", { status: 500 });\n }\n\n // Handle getStaticPaths for dynamic routes\n if (typeof pageModule.getStaticPaths === \"function\" && route.isDynamic) {\n const pathsResult = await pageModule.getStaticPaths({\n locales: i18nConfig ? i18nConfig.locales : [],\n defaultLocale: i18nConfig ? i18nConfig.defaultLocale : \"\",\n });\n const fallback = pathsResult && pathsResult.fallback !== undefined ? pathsResult.fallback : false;\n\n if (fallback === false) {\n const paths = pathsResult && pathsResult.paths ? pathsResult.paths : [];\n const isValidPath = paths.some(function(p) {\n return Object.entries(p.params).every(function(entry) {\n var key = entry[0], val = entry[1];\n var actual = params[key];\n if (Array.isArray(val)) {\n return Array.isArray(actual) && val.join(\"/\") === actual.join(\"/\");\n }\n return String(val) === String(actual);\n });\n });\n if (!isValidPath) {\n return new Response(\"<!DOCTYPE html><html><body><h1>404 - Page not found</h1></body></html>\",\n { status: 404, headers: { \"Content-Type\": \"text/html\" } });\n }\n }\n }\n\n let pageProps = {};\n var gsspRes = null;\n if (typeof pageModule.getServerSideProps === \"function\") {\n const { req, res, responsePromise } = createReqRes(request, routeUrl, parseQuery(routeUrl), undefined);\n const ctx = {\n params, req, res,\n query: parseQuery(routeUrl),\n resolvedUrl: routeUrl,\n locale: locale,\n locales: i18nConfig ? i18nConfig.locales : undefined,\n defaultLocale: i18nConfig ? i18nConfig.defaultLocale : undefined,\n };\n const result = await pageModule.getServerSideProps(ctx);\n // If gSSP called res.end() directly (short-circuit), return that response.\n if (res.headersSent) {\n return await responsePromise;\n }\n if (result && result.props) pageProps = result.props;\n if (result && result.redirect) {\n var gsspStatus = result.redirect.statusCode != null ? result.redirect.statusCode : (result.redirect.permanent ? 308 : 307);\n return new Response(null, { status: gsspStatus, headers: { Location: sanitizeDestinationLocal(result.redirect.destination) } });\n }\n if (result && result.notFound) {\n return new Response(\"404\", { status: 404 });\n }\n // Preserve the res object so headers/status/cookies set by gSSP\n // can be merged into the final HTML response.\n gsspRes = res;\n }\n // Build font Link header early so it's available for ISR cached responses too.\n // Font preloads are module-level state populated at import time and persist across requests.\n var _fontLinkHeader = \"\";\n var _allFp = [];\n try {\n var _fpGoogle = typeof _getSSRFontPreloadsGoogle === \"function\" ? _getSSRFontPreloadsGoogle() : [];\n var _fpLocal = typeof _getSSRFontPreloadsLocal === \"function\" ? _getSSRFontPreloadsLocal() : [];\n _allFp = _fpGoogle.concat(_fpLocal);\n if (_allFp.length > 0) {\n _fontLinkHeader = _allFp.map(function(p) { return \"<\" + p.href + \">; rel=preload; as=font; type=\" + p.type + \"; crossorigin\"; }).join(\", \");\n }\n } catch (e) { /* font preloads not available */ }\n\n let isrRevalidateSeconds = null;\n if (typeof pageModule.getStaticProps === \"function\") {\n const pathname = routeUrl.split(\"?\")[0];\n const cacheKey = isrCacheKey(\"pages\", pathname);\n const cached = await isrGet(cacheKey);\n\n if (cached && !cached.isStale && cached.value.value && cached.value.value.kind === \"PAGES\") {\n var _hitHeaders = {\n \"Content-Type\": \"text/html\", \"X-Vinext-Cache\": \"HIT\",\n \"Cache-Control\": \"s-maxage=\" + (cached.value.value.revalidate || 60) + \", stale-while-revalidate\",\n };\n if (_fontLinkHeader) _hitHeaders[\"Link\"] = _fontLinkHeader;\n return new Response(cached.value.value.html, { status: 200, headers: _hitHeaders });\n }\n\n if (cached && cached.isStale && cached.value.value && cached.value.value.kind === \"PAGES\") {\n triggerBackgroundRegeneration(cacheKey, async function() {\n const freshResult = await pageModule.getStaticProps({ params });\n if (freshResult && freshResult.props && typeof freshResult.revalidate === \"number\" && freshResult.revalidate > 0) {\n await isrSet(cacheKey, { kind: \"PAGES\", html: cached.value.value.html, pageData: freshResult.props, headers: undefined, status: undefined }, freshResult.revalidate);\n }\n });\n var _staleHeaders = {\n \"Content-Type\": \"text/html\", \"X-Vinext-Cache\": \"STALE\",\n \"Cache-Control\": \"s-maxage=0, stale-while-revalidate\",\n };\n if (_fontLinkHeader) _staleHeaders[\"Link\"] = _fontLinkHeader;\n return new Response(cached.value.value.html, { status: 200, headers: _staleHeaders });\n }\n\n const ctx = {\n params,\n locale: locale,\n locales: i18nConfig ? i18nConfig.locales : undefined,\n defaultLocale: i18nConfig ? i18nConfig.defaultLocale : undefined,\n };\n const result = await pageModule.getStaticProps(ctx);\n if (result && result.props) pageProps = result.props;\n if (result && result.redirect) {\n var gspStatus = result.redirect.statusCode != null ? result.redirect.statusCode : (result.redirect.permanent ? 308 : 307);\n return new Response(null, { status: gspStatus, headers: { Location: sanitizeDestinationLocal(result.redirect.destination) } });\n }\n if (result && result.notFound) {\n return new Response(\"404\", { status: 404 });\n }\n if (typeof result.revalidate === \"number\" && result.revalidate > 0) {\n isrRevalidateSeconds = result.revalidate;\n }\n }\n\n let element;\n if (AppComponent) {\n element = React.createElement(AppComponent, { Component: PageComponent, pageProps });\n } else {\n element = React.createElement(PageComponent, pageProps);\n }\n element = wrapWithRouterContext(element);\n\n if (typeof resetSSRHead === \"function\") resetSSRHead();\n if (typeof flushPreloads === \"function\") await flushPreloads();\n\n const ssrHeadHTML = typeof getSSRHeadHTML === \"function\" ? getSSRHeadHTML() : \"\";\n\n // Collect SSR font data (Google Font links, font preloads, font-face styles)\n var fontHeadHTML = \"\";\n function _escAttr(s) { return s.replace(/&/g, \"&amp;\").replace(/\"/g, \"&quot;\"); }\n try {\n var fontLinks = typeof _getSSRFontLinks === \"function\" ? _getSSRFontLinks() : [];\n for (var fl of fontLinks) { fontHeadHTML += '<link rel=\"stylesheet\" href=\"' + _escAttr(fl) + '\" />\\\\n '; }\n } catch (e) { /* next/font/google not used */ }\n // Emit <link rel=\"preload\"> for all font files (reuse _allFp collected earlier for Link header)\n for (var fp of _allFp) { fontHeadHTML += '<link rel=\"preload\" href=\"' + _escAttr(fp.href) + '\" as=\"font\" type=\"' + _escAttr(fp.type) + '\" crossorigin />\\\\n '; }\n try {\n var allFontStyles = [];\n if (typeof _getSSRFontStylesGoogle === \"function\") allFontStyles.push(..._getSSRFontStylesGoogle());\n if (typeof _getSSRFontStylesLocal === \"function\") allFontStyles.push(..._getSSRFontStylesLocal());\n if (allFontStyles.length > 0) { fontHeadHTML += '<style data-vinext-fonts>' + allFontStyles.join(\"\\\\n\") + '</style>\\\\n '; }\n } catch (e) { /* font styles not available */ }\n\n const pageModuleIds = route.filePath ? [route.filePath] : [];\n const assetTags = collectAssetTags(manifest, pageModuleIds);\n const nextDataPayload = {\n props: { pageProps }, page: patternToNextFormat(route.pattern), query: params, buildId, isFallback: false,\n };\n if (i18nConfig) {\n nextDataPayload.locale = locale;\n nextDataPayload.locales = i18nConfig.locales;\n nextDataPayload.defaultLocale = i18nConfig.defaultLocale;\n }\n const localeGlobals = i18nConfig\n ? \";window.__VINEXT_LOCALE__=\" + safeJsonStringify(locale) +\n \";window.__VINEXT_LOCALES__=\" + safeJsonStringify(i18nConfig.locales) +\n \";window.__VINEXT_DEFAULT_LOCALE__=\" + safeJsonStringify(i18nConfig.defaultLocale)\n : \"\";\n const nextDataScript = \"<script>window.__NEXT_DATA__ = \" + safeJsonStringify(nextDataPayload) + localeGlobals + \"</script>\";\n\n // Build the document shell with a placeholder for the streamed body\n var BODY_MARKER = \"<!--VINEXT_STREAM_BODY-->\";\n var shellHtml;\n if (DocumentComponent) {\n const docElement = React.createElement(DocumentComponent);\n shellHtml = await renderToStringAsync(docElement);\n shellHtml = shellHtml.replace(\"__NEXT_MAIN__\", BODY_MARKER);\n if (ssrHeadHTML || assetTags || fontHeadHTML) {\n shellHtml = shellHtml.replace(\"</head>\", \" \" + fontHeadHTML + ssrHeadHTML + \"\\\\n \" + assetTags + \"\\\\n</head>\");\n }\n shellHtml = shellHtml.replace(\"<!-- __NEXT_SCRIPTS__ -->\", nextDataScript);\n if (!shellHtml.includes(\"__NEXT_DATA__\")) {\n shellHtml = shellHtml.replace(\"</body>\", \" \" + nextDataScript + \"\\\\n</body>\");\n }\n } else {\n shellHtml = \"<!DOCTYPE html>\\\\n<html>\\\\n<head>\\\\n <meta charset=\\\\\"utf-8\\\\\" />\\\\n <meta name=\\\\\"viewport\\\\\" content=\\\\\"width=device-width, initial-scale=1\\\\\" />\\\\n \" + fontHeadHTML + ssrHeadHTML + \"\\\\n \" + assetTags + \"\\\\n</head>\\\\n<body>\\\\n <div id=\\\\\"__next\\\\\">\" + BODY_MARKER + \"</div>\\\\n \" + nextDataScript + \"\\\\n</body>\\\\n</html>\";\n }\n\n if (typeof setSSRContext === \"function\") setSSRContext(null);\n\n // Split the shell at the body marker\n var markerIdx = shellHtml.indexOf(BODY_MARKER);\n var shellPrefix = shellHtml.slice(0, markerIdx);\n var shellSuffix = shellHtml.slice(markerIdx + BODY_MARKER.length);\n\n // Start the React body stream — progressive SSR (no allReady wait)\n var bodyStream = await renderToReadableStream(element);\n var encoder = new TextEncoder();\n\n // Create a composite stream: prefix + body + suffix\n var compositeStream = new ReadableStream({\n async start(controller) {\n controller.enqueue(encoder.encode(shellPrefix));\n var reader = bodyStream.getReader();\n try {\n for (;;) {\n var chunk = await reader.read();\n if (chunk.done) break;\n controller.enqueue(chunk.value);\n }\n } finally {\n reader.releaseLock();\n }\n controller.enqueue(encoder.encode(shellSuffix));\n controller.close();\n }\n });\n\n // Cache the rendered HTML for ISR (needs the full string — re-render synchronously)\n if (isrRevalidateSeconds !== null && isrRevalidateSeconds > 0) {\n // Tee the stream so we can cache and respond simultaneously would be ideal,\n // but ISR responses are rare on first hit. Re-render to get complete HTML for cache.\n var isrElement;\n if (AppComponent) {\n isrElement = React.createElement(AppComponent, { Component: PageComponent, pageProps });\n } else {\n isrElement = React.createElement(PageComponent, pageProps);\n }\n isrElement = wrapWithRouterContext(isrElement);\n var isrHtml = await renderToStringAsync(isrElement);\n var fullHtml = shellPrefix + isrHtml + shellSuffix;\n var isrPathname = url.split(\"?\")[0];\n var _cacheKey = isrCacheKey(\"pages\", isrPathname);\n await isrSet(_cacheKey, { kind: \"PAGES\", html: fullHtml, pageData: pageProps, headers: undefined, status: undefined }, isrRevalidateSeconds);\n }\n\n // Merge headers/status/cookies set by getServerSideProps on the res object.\n // gSSP commonly uses res.setHeader(\"Set-Cookie\", ...) or res.status(304).\n var finalStatus = 200;\n const responseHeaders = new Headers({ \"Content-Type\": \"text/html\" });\n if (gsspRes) {\n finalStatus = gsspRes.statusCode;\n var gsspHeaders = gsspRes.getHeaders();\n for (var hk of Object.keys(gsspHeaders)) {\n var hv = gsspHeaders[hk];\n if (hk === \"set-cookie\" && Array.isArray(hv)) {\n for (var sc of hv) responseHeaders.append(\"set-cookie\", sc);\n } else if (hv != null) {\n responseHeaders.set(hk, String(hv));\n }\n }\n // Ensure Content-Type stays text/html (gSSP shouldn't override it for page renders)\n responseHeaders.set(\"Content-Type\", \"text/html\");\n }\n if (isrRevalidateSeconds) {\n responseHeaders.set(\"Cache-Control\", \"s-maxage=\" + isrRevalidateSeconds + \", stale-while-revalidate\");\n responseHeaders.set(\"X-Vinext-Cache\", \"MISS\");\n }\n // Set HTTP Link header for font preloading\n if (_fontLinkHeader) {\n responseHeaders.set(\"Link\", _fontLinkHeader);\n }\n return new Response(compositeStream, { status: finalStatus, headers: responseHeaders });\n } catch (e) {\n console.error(\"[vinext] SSR error:\", e);\n return new Response(\"Internal Server Error\", { status: 500 });\n }\n }) // end runWithFetchCache\n ) // end runWithPrivateCache\n ) // end _runWithCacheState\n ) // end runWithHeadState\n ); // end runWithRouterState\n}\n\nexport async function handleApiRoute(request, url) {\n const match = matchRoute(url, apiRoutes);\n if (!match) {\n return new Response(\"404 - API route not found\", { status: 404 });\n }\n\n const { route, params } = match;\n const handler = route.module.default;\n if (typeof handler !== \"function\") {\n return new Response(\"API route does not export a default function\", { status: 500 });\n }\n\n const query = { ...params };\n const qs = url.split(\"?\")[1];\n if (qs) {\n for (const [k, v] of new URLSearchParams(qs)) {\n if (k in query) {\n // Multi-value: promote to array (Next.js returns string[] for duplicate keys)\n query[k] = Array.isArray(query[k]) ? query[k].concat(v) : [query[k], v];\n } else {\n query[k] = v;\n }\n }\n }\n\n // Parse request body (enforce 1MB limit to prevent memory exhaustion,\n // matching Next.js default bodyParser sizeLimit).\n // Check Content-Length first as a fast path, then enforce on the actual\n // stream to prevent bypasses via chunked transfer encoding.\n const contentLength = parseInt(request.headers.get(\"content-length\") || \"0\", 10);\n if (contentLength > 1 * 1024 * 1024) {\n return new Response(\"Request body too large\", { status: 413 });\n }\n try {\n let body;\n const ct = request.headers.get(\"content-type\") || \"\";\n let rawBody;\n try { rawBody = await readBodyWithLimit(request, 1 * 1024 * 1024); }\n catch { return new Response(\"Request body too large\", { status: 413 }); }\n if (!rawBody) {\n body = undefined;\n } else if (ct.includes(\"application/json\")) {\n try { body = JSON.parse(rawBody); } catch { throw new ApiBodyParseError(\"Invalid JSON\", 400); }\n } else if (ct.includes(\"application/x-www-form-urlencoded\")) {\n body = decodeQueryString(rawBody);\n } else {\n body = rawBody;\n }\n\n const { req, res, responsePromise } = createReqRes(request, url, query, body);\n await handler(req, res);\n // If handler didn't call res.end(), end it now.\n // The end() method is idempotent — safe to call twice.\n res.end();\n return await responsePromise;\n } catch (e) {\n if (e instanceof ApiBodyParseError) {\n return new Response(e.message, { status: e.statusCode });\n }\n console.error(\"[vinext] API error:\", e);\n return new Response(\"Internal Server Error\", { status: 500 });\n }\n}\n\n${middlewareExportCode}\n`;\n}\n"]}