vinext 0.0.28 → 0.0.30

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 (173) hide show
  1. package/dist/build/report.d.ts +117 -0
  2. package/dist/build/report.d.ts.map +1 -0
  3. package/dist/build/report.js +303 -0
  4. package/dist/build/report.js.map +1 -0
  5. package/dist/check.d.ts.map +1 -1
  6. package/dist/check.js +11 -7
  7. package/dist/check.js.map +1 -1
  8. package/dist/cli.js +106 -9
  9. package/dist/cli.js.map +1 -1
  10. package/dist/cloudflare/kv-cache-handler.d.ts.map +1 -1
  11. package/dist/cloudflare/kv-cache-handler.js +58 -42
  12. package/dist/cloudflare/kv-cache-handler.js.map +1 -1
  13. package/dist/cloudflare/tpr.d.ts +10 -0
  14. package/dist/cloudflare/tpr.d.ts.map +1 -1
  15. package/dist/cloudflare/tpr.js +36 -41
  16. package/dist/cloudflare/tpr.js.map +1 -1
  17. package/dist/config/next-config.d.ts.map +1 -1
  18. package/dist/config/next-config.js +16 -0
  19. package/dist/config/next-config.js.map +1 -1
  20. package/dist/entries/app-rsc-entry.d.ts +1 -1
  21. package/dist/entries/app-rsc-entry.d.ts.map +1 -1
  22. package/dist/entries/app-rsc-entry.js +225 -186
  23. package/dist/entries/app-rsc-entry.js.map +1 -1
  24. package/dist/entries/pages-server-entry.d.ts.map +1 -1
  25. package/dist/entries/pages-server-entry.js +192 -91
  26. package/dist/entries/pages-server-entry.js.map +1 -1
  27. package/dist/index.d.ts +17 -0
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +121 -40
  30. package/dist/index.js.map +1 -1
  31. package/dist/routing/app-router.d.ts +2 -0
  32. package/dist/routing/app-router.d.ts.map +1 -1
  33. package/dist/routing/app-router.js +131 -104
  34. package/dist/routing/app-router.js.map +1 -1
  35. package/dist/routing/pages-router.d.ts.map +1 -1
  36. package/dist/routing/pages-router.js +17 -57
  37. package/dist/routing/pages-router.js.map +1 -1
  38. package/dist/routing/route-trie.d.ts +57 -0
  39. package/dist/routing/route-trie.d.ts.map +1 -0
  40. package/dist/routing/route-trie.js +160 -0
  41. package/dist/routing/route-trie.js.map +1 -0
  42. package/dist/routing/route-validation.d.ts.map +1 -1
  43. package/dist/routing/route-validation.js +13 -1
  44. package/dist/routing/route-validation.js.map +1 -1
  45. package/dist/routing/utils.d.ts +19 -0
  46. package/dist/routing/utils.d.ts.map +1 -1
  47. package/dist/routing/utils.js +47 -0
  48. package/dist/routing/utils.js.map +1 -1
  49. package/dist/server/api-handler.d.ts.map +1 -1
  50. package/dist/server/api-handler.js +28 -13
  51. package/dist/server/api-handler.js.map +1 -1
  52. package/dist/server/app-router-entry.js +1 -1
  53. package/dist/server/app-router-entry.js.map +1 -1
  54. package/dist/server/dev-server.d.ts +2 -1
  55. package/dist/server/dev-server.d.ts.map +1 -1
  56. package/dist/server/dev-server.js +167 -115
  57. package/dist/server/dev-server.js.map +1 -1
  58. package/dist/server/image-optimization.d.ts.map +1 -1
  59. package/dist/server/image-optimization.js +24 -12
  60. package/dist/server/image-optimization.js.map +1 -1
  61. package/dist/server/instrumentation.d.ts.map +1 -1
  62. package/dist/server/instrumentation.js +17 -8
  63. package/dist/server/instrumentation.js.map +1 -1
  64. package/dist/server/isr-cache.d.ts.map +1 -1
  65. package/dist/server/isr-cache.js +8 -3
  66. package/dist/server/isr-cache.js.map +1 -1
  67. package/dist/server/metadata-routes.d.ts.map +1 -1
  68. package/dist/server/metadata-routes.js +56 -18
  69. package/dist/server/metadata-routes.js.map +1 -1
  70. package/dist/server/middleware-codegen.d.ts +10 -0
  71. package/dist/server/middleware-codegen.d.ts.map +1 -1
  72. package/dist/server/middleware-codegen.js +76 -4
  73. package/dist/server/middleware-codegen.js.map +1 -1
  74. package/dist/server/middleware.d.ts.map +1 -1
  75. package/dist/server/middleware.js +52 -7
  76. package/dist/server/middleware.js.map +1 -1
  77. package/dist/server/pages-i18n.d.ts +50 -0
  78. package/dist/server/pages-i18n.d.ts.map +1 -0
  79. package/dist/server/pages-i18n.js +152 -0
  80. package/dist/server/pages-i18n.js.map +1 -0
  81. package/dist/server/prod-server.d.ts +8 -2
  82. package/dist/server/prod-server.d.ts.map +1 -1
  83. package/dist/server/prod-server.js +60 -20
  84. package/dist/server/prod-server.js.map +1 -1
  85. package/dist/shims/cache-runtime.d.ts +3 -0
  86. package/dist/shims/cache-runtime.d.ts.map +1 -1
  87. package/dist/shims/cache-runtime.js +22 -5
  88. package/dist/shims/cache-runtime.js.map +1 -1
  89. package/dist/shims/cache.d.ts +3 -0
  90. package/dist/shims/cache.d.ts.map +1 -1
  91. package/dist/shims/cache.js +21 -12
  92. package/dist/shims/cache.js.map +1 -1
  93. package/dist/shims/constants.d.ts.map +1 -1
  94. package/dist/shims/constants.js +0 -1
  95. package/dist/shims/constants.js.map +1 -1
  96. package/dist/shims/fetch-cache.d.ts +14 -0
  97. package/dist/shims/fetch-cache.d.ts.map +1 -1
  98. package/dist/shims/fetch-cache.js +102 -37
  99. package/dist/shims/fetch-cache.js.map +1 -1
  100. package/dist/shims/head-state.d.ts +4 -0
  101. package/dist/shims/head-state.d.ts.map +1 -1
  102. package/dist/shims/head-state.js +14 -11
  103. package/dist/shims/head-state.js.map +1 -1
  104. package/dist/shims/head.d.ts +4 -2
  105. package/dist/shims/head.d.ts.map +1 -1
  106. package/dist/shims/head.js +162 -52
  107. package/dist/shims/head.js.map +1 -1
  108. package/dist/shims/headers.d.ts +8 -1
  109. package/dist/shims/headers.d.ts.map +1 -1
  110. package/dist/shims/headers.js +23 -34
  111. package/dist/shims/headers.js.map +1 -1
  112. package/dist/shims/i18n-context.d.ts +27 -0
  113. package/dist/shims/i18n-context.d.ts.map +1 -0
  114. package/dist/shims/i18n-context.js +57 -0
  115. package/dist/shims/i18n-context.js.map +1 -0
  116. package/dist/shims/i18n-state.d.ts +20 -0
  117. package/dist/shims/i18n-state.d.ts.map +1 -0
  118. package/dist/shims/i18n-state.js +53 -0
  119. package/dist/shims/i18n-state.js.map +1 -0
  120. package/dist/shims/image.d.ts +2 -0
  121. package/dist/shims/image.d.ts.map +1 -1
  122. package/dist/shims/image.js +14 -6
  123. package/dist/shims/image.js.map +1 -1
  124. package/dist/shims/internal/utils.d.ts +1 -0
  125. package/dist/shims/internal/utils.d.ts.map +1 -1
  126. package/dist/shims/internal/utils.js.map +1 -1
  127. package/dist/shims/link.d.ts.map +1 -1
  128. package/dist/shims/link.js +38 -54
  129. package/dist/shims/link.js.map +1 -1
  130. package/dist/shims/metadata.d.ts +78 -22
  131. package/dist/shims/metadata.d.ts.map +1 -1
  132. package/dist/shims/metadata.js +96 -28
  133. package/dist/shims/metadata.js.map +1 -1
  134. package/dist/shims/navigation-state.d.ts +14 -0
  135. package/dist/shims/navigation-state.d.ts.map +1 -1
  136. package/dist/shims/navigation-state.js +33 -15
  137. package/dist/shims/navigation-state.js.map +1 -1
  138. package/dist/shims/navigation.d.ts +2 -0
  139. package/dist/shims/navigation.d.ts.map +1 -1
  140. package/dist/shims/navigation.js +80 -51
  141. package/dist/shims/navigation.js.map +1 -1
  142. package/dist/shims/request-context.d.ts.map +1 -1
  143. package/dist/shims/request-context.js +9 -0
  144. package/dist/shims/request-context.js.map +1 -1
  145. package/dist/shims/request-state-types.d.ts +11 -0
  146. package/dist/shims/request-state-types.d.ts.map +1 -0
  147. package/dist/shims/request-state-types.js +2 -0
  148. package/dist/shims/request-state-types.js.map +1 -0
  149. package/dist/shims/router-state.d.ts +11 -0
  150. package/dist/shims/router-state.d.ts.map +1 -1
  151. package/dist/shims/router-state.js +10 -8
  152. package/dist/shims/router-state.js.map +1 -1
  153. package/dist/shims/router.d.ts +4 -0
  154. package/dist/shims/router.d.ts.map +1 -1
  155. package/dist/shims/router.js +130 -40
  156. package/dist/shims/router.js.map +1 -1
  157. package/dist/shims/server.d.ts +8 -1
  158. package/dist/shims/server.d.ts.map +1 -1
  159. package/dist/shims/server.js +52 -6
  160. package/dist/shims/server.js.map +1 -1
  161. package/dist/shims/unified-request-context.d.ts +66 -0
  162. package/dist/shims/unified-request-context.d.ts.map +1 -0
  163. package/dist/shims/unified-request-context.js +116 -0
  164. package/dist/shims/unified-request-context.js.map +1 -0
  165. package/dist/shims/url-utils.d.ts +20 -6
  166. package/dist/shims/url-utils.d.ts.map +1 -1
  167. package/dist/shims/url-utils.js +79 -0
  168. package/dist/shims/url-utils.js.map +1 -1
  169. package/dist/utils/domain-locale.d.ts +18 -0
  170. package/dist/utils/domain-locale.d.ts.map +1 -0
  171. package/dist/utils/domain-locale.js +64 -0
  172. package/dist/utils/domain-locale.js.map +1 -0
  173. package/package.json +2 -2
@@ -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;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"}
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;AAuBnE;;;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,CAioCjB"}
@@ -11,10 +11,12 @@ import path from "node:path";
11
11
  import { fileURLToPath } from "node:url";
12
12
  import { pagesRouter, apiRouter } from "../routing/pages-router.js";
13
13
  import { isProxyFile } from "../server/middleware.js";
14
- import { generateSafeRegExpCode, generateMiddlewareMatcherCode, generateNormalizePathCode, } from "../server/middleware-codegen.js";
14
+ import { generateSafeRegExpCode, generateMiddlewareMatcherCode, generateNormalizePathCode, generateRouteMatchNormalizationCode, } 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
17
  const _requestContextShimPath = fileURLToPath(new URL("../shims/request-context.js", import.meta.url)).replace(/\\/g, "/");
18
+ const _routeTriePath = fileURLToPath(new URL("../routing/route-trie.js", import.meta.url)).replace(/\\/g, "/");
19
+ const _pagesI18nPath = fileURLToPath(new URL("../server/pages-i18n.js", import.meta.url)).replace(/\\/g, "/");
18
20
  /**
19
21
  * Generate the virtual SSR server entry module.
20
22
  * This is the entry point for `vite build --ssr`.
@@ -43,12 +45,10 @@ export async function generateServerEntry(pagesDir, nextConfig, fileMatcher, mid
43
45
  // Check for _app and _document
44
46
  const appFilePath = findFileWithExts(pagesDir, "_app", fileMatcher);
45
47
  const docFilePath = findFileWithExts(pagesDir, "_document", fileMatcher);
46
- const hasApp = appFilePath !== null;
47
- const hasDoc = docFilePath !== null;
48
- const appImportCode = hasApp
48
+ const appImportCode = appFilePath !== null
49
49
  ? `import { default as AppComponent } from ${JSON.stringify(appFilePath.replace(/\\/g, "/"))};`
50
50
  : `const AppComponent = null;`;
51
- const docImportCode = hasDoc
51
+ const docImportCode = docFilePath !== null
52
52
  ? `import { default as DocumentComponent } from ${JSON.stringify(docFilePath.replace(/\\/g, "/"))};`
53
53
  : `const DocumentComponent = null;`;
54
54
  // Serialize i18n config for embedding in the server entry
@@ -57,6 +57,7 @@ export async function generateServerEntry(pagesDir, nextConfig, fileMatcher, mid
57
57
  locales: nextConfig.i18n.locales,
58
58
  defaultLocale: nextConfig.i18n.defaultLocale,
59
59
  localeDetection: nextConfig.i18n.localeDetection,
60
+ domains: nextConfig.i18n.domains,
60
61
  })
61
62
  : "null";
62
63
  // Embed the resolved build ID at build time
@@ -115,6 +116,7 @@ import { NextRequest, NextFetchEvent } from "next/server";`
115
116
  ? `
116
117
  // --- Middleware support (generated from middleware-codegen.ts) ---
117
118
  ${generateNormalizePathCode("es5")}
119
+ ${generateRouteMatchNormalizationCode("es5")}
118
120
  ${generateSafeRegExpCode("es5")}
119
121
  ${generateMiddlewareMatcherCode("es5")}
120
122
 
@@ -141,7 +143,7 @@ async function _runMiddleware(request) {
141
143
  // Normalize pathname before matching to prevent path-confusion bypasses
142
144
  // (percent-encoding like /%61dmin, double slashes like /dashboard//settings).
143
145
  var decodedPathname;
144
- try { decodedPathname = decodeURIComponent(url.pathname); } catch (e) {
146
+ try { decodedPathname = __normalizePathnameForRouteMatchStrict(url.pathname); } catch (e) {
145
147
  return { continue: false, response: new Response("Bad Request", { status: 400 }) };
146
148
  }
147
149
  var normalizedPathname = __normalizePath(decodedPathname);
@@ -221,18 +223,24 @@ import { renderToReadableStream } from "react-dom/server.edge";
221
223
  import { resetSSRHead, getSSRHeadHTML } from "next/head";
222
224
  import { flushPreloads } from "next/dynamic";
223
225
  import { setSSRContext, wrapWithRouterContext } from "next/router";
224
- import { getCacheHandler } from "next/cache";
225
- import { runWithFetchCache } from "vinext/fetch-cache";
226
- import { _runWithCacheState } from "next/cache";
226
+ import { getCacheHandler, _runWithCacheState } from "next/cache";
227
227
  import { runWithPrivateCache } from "vinext/cache-runtime";
228
- import { runWithRouterState } from "vinext/router-state";
228
+ import { ensureFetchPatch, runWithFetchCache } from "vinext/fetch-cache";
229
+ import { runWithRequestContext as _runWithUnifiedCtx, createRequestContext as _createUnifiedCtx } from "vinext/unified-request-context";
230
+ import "vinext/router-state";
231
+ import { runWithServerInsertedHTMLState } from "vinext/navigation-state";
229
232
  import { runWithHeadState } from "vinext/head-state";
233
+ import "vinext/i18n-state";
234
+ import { setI18nContext } from "vinext/i18n-context";
230
235
  import { safeJsonStringify } from "vinext/html";
231
236
  import { decode as decodeQueryString } from "node:querystring";
232
237
  import { getSSRFontLinks as _getSSRFontLinks, getSSRFontStyles as _getSSRFontStylesGoogle, getSSRFontPreloads as _getSSRFontPreloadsGoogle } from "next/font/google";
233
238
  import { getSSRFontStyles as _getSSRFontStylesLocal, getSSRFontPreloads as _getSSRFontPreloadsLocal } from "next/font/local";
234
239
  import { parseCookies } from ${JSON.stringify(path.resolve(__dirname, "../config/config-matchers.js").replace(/\\/g, "/"))};
235
240
  import { runWithExecutionContext as _runWithExecutionContext, getRequestExecutionContext as _getRequestExecutionContext } from ${JSON.stringify(_requestContextShimPath)};
241
+ import { buildRouteTrie as _buildRouteTrie, trieMatch as _trieMatch } from ${JSON.stringify(_routeTriePath)};
242
+ import { reportRequestError as _reportRequestError } from "vinext/instrumentation";
243
+ import { resolvePagesI18nRequest } from ${JSON.stringify(_pagesI18nPath)};
236
244
  ${instrumentationImportCode}
237
245
  ${middlewareImportCode}
238
246
 
@@ -302,12 +310,37 @@ function isrCacheKey(router, pathname) {
302
310
  return prefix + ":__hash:" + fnv1a64(normalized);
303
311
  }
304
312
 
313
+ function getMediaType(contentType) {
314
+ var type = (contentType || "text/plain").split(";")[0];
315
+ type = type && type.trim().toLowerCase();
316
+ return type || "text/plain";
317
+ }
318
+
319
+ function isJsonMediaType(mediaType) {
320
+ return mediaType === "application/json" || mediaType === "application/ld+json";
321
+ }
322
+
305
323
  async function renderToStringAsync(element) {
306
324
  const stream = await renderToReadableStream(element);
307
325
  await stream.allReady;
308
326
  return new Response(stream).text();
309
327
  }
310
328
 
329
+ async function renderIsrPassToStringAsync(element) {
330
+ // The cache-fill render is a second render pass for the same request.
331
+ // Reset render-scoped state so it cannot leak from the streamed response
332
+ // render or affect async work that is still draining from that stream.
333
+ // Keep request identity state (pathname/query/locale/executionContext)
334
+ // intact: this second pass still belongs to the same request.
335
+ return await runWithServerInsertedHTMLState(() =>
336
+ runWithHeadState(() =>
337
+ _runWithCacheState(() =>
338
+ runWithPrivateCache(() => runWithFetchCache(async () => renderToStringAsync(element))),
339
+ ),
340
+ ),
341
+ );
342
+ }
343
+
311
344
  ${pageImports.join("\n")}
312
345
  ${apiImports.join("\n")}
313
346
 
@@ -317,10 +350,12 @@ ${docImportCode}
317
350
  const pageRoutes = [
318
351
  ${pageRouteEntries.join(",\n")}
319
352
  ];
353
+ const _pageRouteTrie = _buildRouteTrie(pageRoutes);
320
354
 
321
355
  const apiRoutes = [
322
356
  ${apiRouteEntries.join(",\n")}
323
357
  ];
358
+ const _apiRouteTrie = _buildRouteTrie(apiRoutes);
324
359
 
325
360
  function matchRoute(url, routes) {
326
361
  const pathname = url.split("?")[0];
@@ -328,40 +363,8 @@ function matchRoute(url, routes) {
328
363
  // NOTE: Do NOT decodeURIComponent here. The pathname is already decoded at
329
364
  // the entry point. Decoding again would create a double-decode vector.
330
365
  const urlParts = normalizedUrl.split("/").filter(Boolean);
331
- for (const route of routes) {
332
- const params = matchPattern(urlParts, route.patternParts);
333
- if (params !== null) return { route, params };
334
- }
335
- return null;
336
- }
337
-
338
- function matchPattern(urlParts, patternParts) {
339
- const params = Object.create(null);
340
- for (let i = 0; i < patternParts.length; i++) {
341
- const pp = patternParts[i];
342
- if (pp.endsWith("+")) {
343
- if (i !== patternParts.length - 1) return null;
344
- const paramName = pp.slice(1, -1);
345
- const remaining = urlParts.slice(i);
346
- if (remaining.length === 0) return null;
347
- params[paramName] = remaining;
348
- return params;
349
- }
350
- if (pp.endsWith("*")) {
351
- if (i !== patternParts.length - 1) return null;
352
- const paramName = pp.slice(1, -1);
353
- params[paramName] = urlParts.slice(i);
354
- return params;
355
- }
356
- if (pp.startsWith(":")) {
357
- if (i >= urlParts.length) return null;
358
- params[pp.slice(1)] = urlParts[i];
359
- continue;
360
- }
361
- if (i >= urlParts.length || urlParts[i] !== pp) return null;
362
- }
363
- if (urlParts.length !== patternParts.length) return null;
364
- return params;
366
+ const trie = routes === pageRoutes ? _pageRouteTrie : _apiRouteTrie;
367
+ return _trieMatch(trie, urlParts);
365
368
  }
366
369
 
367
370
  function parseQuery(url) {
@@ -667,23 +670,25 @@ export async function renderPage(request, url, manifest, ctx) {
667
670
  }
668
671
 
669
672
  async function _renderPage(request, url, manifest) {
670
- const localeInfo = extractLocale(url);
673
+ const localeInfo = i18nConfig
674
+ ? resolvePagesI18nRequest(
675
+ url,
676
+ i18nConfig,
677
+ request.headers,
678
+ new URL(request.url).hostname,
679
+ vinextConfig.basePath,
680
+ vinextConfig.trailingSlash,
681
+ )
682
+ : { locale: undefined, url, hadPrefix: false, domainLocale: undefined, redirectUrl: undefined };
671
683
  const locale = localeInfo.locale;
672
684
  const routeUrl = localeInfo.url;
673
- const cookieHeader = request.headers.get("cookie") || "";
685
+ const currentDefaultLocale = i18nConfig
686
+ ? (localeInfo.domainLocale ? localeInfo.domainLocale.defaultLocale : i18nConfig.defaultLocale)
687
+ : undefined;
688
+ const domainLocales = i18nConfig ? i18nConfig.domains : undefined;
674
689
 
675
- // i18n redirect: check NEXT_LOCALE cookie first, then Accept-Language
676
- if (i18nConfig && !localeInfo.hadPrefix) {
677
- const cookieLocale = parseCookieLocaleFromHeader(cookieHeader);
678
- if (cookieLocale && cookieLocale !== i18nConfig.defaultLocale) {
679
- return new Response(null, { status: 307, headers: { Location: "/" + cookieLocale + routeUrl } });
680
- }
681
- if (!cookieLocale && i18nConfig.localeDetection !== false) {
682
- const detected = detectLocaleFromHeaders(request.headers);
683
- if (detected && detected !== i18nConfig.defaultLocale) {
684
- return new Response(null, { status: 307, headers: { Location: "/" + detected + routeUrl } });
685
- }
686
- }
690
+ if (localeInfo.redirectUrl) {
691
+ return new Response(null, { status: 307, headers: { Location: localeInfo.redirectUrl } });
687
692
  }
688
693
 
689
694
  const match = matchRoute(routeUrl, pageRoutes);
@@ -693,12 +698,12 @@ async function _renderPage(request, url, manifest) {
693
698
  }
694
699
 
695
700
  const { route, params } = match;
696
- return runWithRouterState(() =>
697
- runWithHeadState(() =>
698
- _runWithCacheState(() =>
699
- runWithPrivateCache(() =>
700
- runWithFetchCache(async () => {
701
- try {
701
+ const __uCtx = _createUnifiedCtx({
702
+ executionContext: _getRequestExecutionContext(),
703
+ });
704
+ return _runWithUnifiedCtx(__uCtx, async () => {
705
+ ensureFetchPatch();
706
+ try {
702
707
  if (typeof setSSRContext === "function") {
703
708
  setSSRContext({
704
709
  pathname: patternToNextFormat(route.pattern),
@@ -706,14 +711,19 @@ async function _renderPage(request, url, manifest) {
706
711
  asPath: routeUrl,
707
712
  locale: locale,
708
713
  locales: i18nConfig ? i18nConfig.locales : undefined,
709
- defaultLocale: i18nConfig ? i18nConfig.defaultLocale : undefined,
714
+ defaultLocale: currentDefaultLocale,
715
+ domainLocales: domainLocales,
710
716
  });
711
717
  }
712
718
 
713
719
  if (i18nConfig) {
714
- globalThis.__VINEXT_LOCALE__ = locale;
715
- globalThis.__VINEXT_LOCALES__ = i18nConfig.locales;
716
- globalThis.__VINEXT_DEFAULT_LOCALE__ = i18nConfig.defaultLocale;
720
+ setI18nContext({
721
+ locale: locale,
722
+ locales: i18nConfig.locales,
723
+ defaultLocale: currentDefaultLocale,
724
+ domainLocales: domainLocales,
725
+ hostname: new URL(request.url).hostname,
726
+ });
717
727
  }
718
728
 
719
729
  const pageModule = route.module;
@@ -726,7 +736,7 @@ async function _renderPage(request, url, manifest) {
726
736
  if (typeof pageModule.getStaticPaths === "function" && route.isDynamic) {
727
737
  const pathsResult = await pageModule.getStaticPaths({
728
738
  locales: i18nConfig ? i18nConfig.locales : [],
729
- defaultLocale: i18nConfig ? i18nConfig.defaultLocale : "",
739
+ defaultLocale: currentDefaultLocale || "",
730
740
  });
731
741
  const fallback = pathsResult && pathsResult.fallback !== undefined ? pathsResult.fallback : false;
732
742
 
@@ -759,7 +769,7 @@ async function _renderPage(request, url, manifest) {
759
769
  resolvedUrl: routeUrl,
760
770
  locale: locale,
761
771
  locales: i18nConfig ? i18nConfig.locales : undefined,
762
- defaultLocale: i18nConfig ? i18nConfig.defaultLocale : undefined,
772
+ defaultLocale: currentDefaultLocale,
763
773
  };
764
774
  const result = await pageModule.getServerSideProps(ctx);
765
775
  // If gSSP called res.end() directly (short-circuit), return that response.
@@ -808,10 +818,89 @@ async function _renderPage(request, url, manifest) {
808
818
 
809
819
  if (cached && cached.isStale && cached.value.value && cached.value.value.kind === "PAGES") {
810
820
  triggerBackgroundRegeneration(cacheKey, async function() {
811
- const freshResult = await pageModule.getStaticProps({ params });
812
- if (freshResult && freshResult.props && typeof freshResult.revalidate === "number" && freshResult.revalidate > 0) {
813
- await isrSet(cacheKey, { kind: "PAGES", html: cached.value.value.html, pageData: freshResult.props, headers: undefined, status: undefined }, freshResult.revalidate);
814
- }
821
+ var revalCtx = _createUnifiedCtx({
822
+ executionContext: _getRequestExecutionContext(),
823
+ });
824
+ return _runWithUnifiedCtx(revalCtx, async () => {
825
+ ensureFetchPatch();
826
+ var freshResult = await pageModule.getStaticProps({
827
+ params: params,
828
+ locale: locale,
829
+ locales: i18nConfig ? i18nConfig.locales : undefined,
830
+ defaultLocale: currentDefaultLocale,
831
+ });
832
+ if (freshResult && freshResult.props && typeof freshResult.revalidate === "number" && freshResult.revalidate > 0) {
833
+ var _fp = freshResult.props;
834
+ if (typeof setSSRContext === "function") {
835
+ setSSRContext({
836
+ pathname: patternToNextFormat(route.pattern),
837
+ query: { ...params, ...parseQuery(routeUrl) },
838
+ asPath: routeUrl,
839
+ locale: locale,
840
+ locales: i18nConfig ? i18nConfig.locales : undefined,
841
+ defaultLocale: currentDefaultLocale,
842
+ domainLocales: domainLocales,
843
+ });
844
+ }
845
+ if (i18nConfig) {
846
+ setI18nContext({
847
+ locale: locale,
848
+ locales: i18nConfig.locales,
849
+ defaultLocale: currentDefaultLocale,
850
+ domainLocales: domainLocales,
851
+ hostname: new URL(request.url).hostname,
852
+ });
853
+ }
854
+ // Re-render the page with fresh props inside fresh render sub-scopes
855
+ // so head/cache state cannot leak across passes.
856
+ var _el = AppComponent
857
+ ? React.createElement(AppComponent, { Component: PageComponent, pageProps: _fp })
858
+ : React.createElement(PageComponent, _fp);
859
+ _el = wrapWithRouterContext(_el);
860
+ var _freshBody = await renderIsrPassToStringAsync(_el);
861
+ // Rebuild __NEXT_DATA__ with fresh props
862
+ var _regenPayload = {
863
+ props: { pageProps: _fp }, page: patternToNextFormat(route.pattern),
864
+ query: params, buildId: buildId, isFallback: false,
865
+ };
866
+ if (i18nConfig) {
867
+ _regenPayload.locale = locale;
868
+ _regenPayload.locales = i18nConfig.locales;
869
+ _regenPayload.defaultLocale = currentDefaultLocale;
870
+ _regenPayload.domainLocales = domainLocales;
871
+ }
872
+ var _lGlobals = i18nConfig
873
+ ? ";window.__VINEXT_LOCALE__=" + safeJsonStringify(locale) +
874
+ ";window.__VINEXT_LOCALES__=" + safeJsonStringify(i18nConfig.locales) +
875
+ ";window.__VINEXT_DEFAULT_LOCALE__=" + safeJsonStringify(currentDefaultLocale)
876
+ : "";
877
+ var _freshNDS = "<script>window.__NEXT_DATA__ = " + safeJsonStringify(_regenPayload) + _lGlobals + "</script>";
878
+ // Reconstruct ISR HTML preserving the document shell from the
879
+ // cached entry (head, fonts, assets, custom _document markup).
880
+ var _cachedStr = cached.value.value.html;
881
+ var _btag = '<div id="__next">';
882
+ var _bstart = _cachedStr.indexOf(_btag);
883
+ var _bodyStart = _bstart >= 0 ? _bstart + _btag.length : -1;
884
+ // Locate __NEXT_DATA__ script to split body from suffix
885
+ var _ndMarker = '<script>window.__NEXT_DATA__';
886
+ var _ndStart = _cachedStr.indexOf(_ndMarker);
887
+ var _freshHtml;
888
+ if (_bodyStart >= 0 && _ndStart >= 0) {
889
+ // Region between body start and __NEXT_DATA__ contains:
890
+ // BODY_HTML + </div> + optional gap (custom _document content)
891
+ var _region = _cachedStr.slice(_bodyStart, _ndStart);
892
+ var _lastClose = _region.lastIndexOf('</div>');
893
+ var _gap = _lastClose >= 0 ? _region.slice(_lastClose + 6) : '';
894
+ // Tail: everything after the old __NEXT_DATA__ </script>
895
+ var _ndEnd = _cachedStr.indexOf('</script>', _ndStart) + 9;
896
+ var _tail = _cachedStr.slice(_ndEnd);
897
+ _freshHtml = _cachedStr.slice(0, _bodyStart) + _freshBody + '</div>' + _gap + _freshNDS + _tail;
898
+ } else {
899
+ _freshHtml = '<!DOCTYPE html>\\n<html>\\n<head>\\n</head>\\n<body>\\n <div id="__next">' + _freshBody + '</div>\\n ' + _freshNDS + '\\n</body>\\n</html>';
900
+ }
901
+ await isrSet(cacheKey, { kind: "PAGES", html: _freshHtml, pageData: _fp, headers: undefined, status: undefined }, freshResult.revalidate);
902
+ }
903
+ });
815
904
  });
816
905
  var _staleHeaders = {
817
906
  "Content-Type": "text/html", "X-Vinext-Cache": "STALE",
@@ -825,7 +914,7 @@ async function _renderPage(request, url, manifest) {
825
914
  params,
826
915
  locale: locale,
827
916
  locales: i18nConfig ? i18nConfig.locales : undefined,
828
- defaultLocale: i18nConfig ? i18nConfig.defaultLocale : undefined,
917
+ defaultLocale: currentDefaultLocale,
829
918
  };
830
919
  const result = await pageModule.getStaticProps(ctx);
831
920
  if (result && result.props) pageProps = result.props;
@@ -878,12 +967,13 @@ async function _renderPage(request, url, manifest) {
878
967
  if (i18nConfig) {
879
968
  nextDataPayload.locale = locale;
880
969
  nextDataPayload.locales = i18nConfig.locales;
881
- nextDataPayload.defaultLocale = i18nConfig.defaultLocale;
970
+ nextDataPayload.defaultLocale = currentDefaultLocale;
971
+ nextDataPayload.domainLocales = domainLocales;
882
972
  }
883
973
  const localeGlobals = i18nConfig
884
974
  ? ";window.__VINEXT_LOCALE__=" + safeJsonStringify(locale) +
885
975
  ";window.__VINEXT_LOCALES__=" + safeJsonStringify(i18nConfig.locales) +
886
- ";window.__VINEXT_DEFAULT_LOCALE__=" + safeJsonStringify(i18nConfig.defaultLocale)
976
+ ";window.__VINEXT_DEFAULT_LOCALE__=" + safeJsonStringify(currentDefaultLocale)
887
977
  : "";
888
978
  const nextDataScript = "<script>window.__NEXT_DATA__ = " + safeJsonStringify(nextDataPayload) + localeGlobals + "</script>";
889
979
 
@@ -946,7 +1036,7 @@ async function _renderPage(request, url, manifest) {
946
1036
  isrElement = React.createElement(PageComponent, pageProps);
947
1037
  }
948
1038
  isrElement = wrapWithRouterContext(isrElement);
949
- var isrHtml = await renderToStringAsync(isrElement);
1039
+ var isrHtml = await renderIsrPassToStringAsync(isrElement);
950
1040
  var fullHtml = shellPrefix + isrHtml + shellSuffix;
951
1041
  var isrPathname = url.split("?")[0];
952
1042
  var _cacheKey = isrCacheKey("pages", isrPathname);
@@ -980,15 +1070,16 @@ async function _renderPage(request, url, manifest) {
980
1070
  responseHeaders.set("Link", _fontLinkHeader);
981
1071
  }
982
1072
  return new Response(compositeStream, { status: finalStatus, headers: responseHeaders });
983
- } catch (e) {
1073
+ } catch (e) {
984
1074
  console.error("[vinext] SSR error:", e);
1075
+ _reportRequestError(
1076
+ e instanceof Error ? e : new Error(String(e)),
1077
+ { path: url, method: request.method, headers: Object.fromEntries(request.headers.entries()) },
1078
+ { routerKind: "Pages Router", routePath: route.pattern, routeType: "render" },
1079
+ ).catch(() => { /* ignore reporting errors */ });
985
1080
  return new Response("Internal Server Error", { status: 500 });
986
- }
987
- }) // end runWithFetchCache
988
- ) // end runWithPrivateCache
989
- ) // end _runWithCacheState
990
- ) // end runWithHeadState
991
- ); // end runWithRouterState
1081
+ }
1082
+ });
992
1083
  }
993
1084
 
994
1085
  export async function handleApiRoute(request, url) {
@@ -1026,15 +1117,20 @@ export async function handleApiRoute(request, url) {
1026
1117
  }
1027
1118
  try {
1028
1119
  let body;
1029
- const ct = request.headers.get("content-type") || "";
1120
+ const mediaType = getMediaType(request.headers.get("content-type"));
1030
1121
  let rawBody;
1031
1122
  try { rawBody = await readBodyWithLimit(request, 1 * 1024 * 1024); }
1032
1123
  catch { return new Response("Request body too large", { status: 413 }); }
1033
1124
  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")) {
1125
+ body = isJsonMediaType(mediaType)
1126
+ ? {}
1127
+ : mediaType === "application/x-www-form-urlencoded"
1128
+ ? decodeQueryString(rawBody)
1129
+ : undefined;
1130
+ } else if (isJsonMediaType(mediaType)) {
1131
+ try { body = JSON.parse(rawBody); }
1132
+ catch { throw new ApiBodyParseError("Invalid JSON", 400); }
1133
+ } else if (mediaType === "application/x-www-form-urlencoded") {
1038
1134
  body = decodeQueryString(rawBody);
1039
1135
  } else {
1040
1136
  body = rawBody;
@@ -1048,9 +1144,14 @@ export async function handleApiRoute(request, url) {
1048
1144
  return await responsePromise;
1049
1145
  } catch (e) {
1050
1146
  if (e instanceof ApiBodyParseError) {
1051
- return new Response(e.message, { status: e.statusCode });
1147
+ return new Response(e.message, { status: e.statusCode, statusText: e.message });
1052
1148
  }
1053
1149
  console.error("[vinext] API error:", e);
1150
+ _reportRequestError(
1151
+ e instanceof Error ? e : new Error(String(e)),
1152
+ { path: url, method: request.method, headers: Object.fromEntries(request.headers.entries()) },
1153
+ { routerKind: "Pages Router", routePath: route.pattern, routeType: "route" },
1154
+ );
1054
1155
  return new Response("Internal Server Error", { status: 500 });
1055
1156
  }
1056
1157
  }