vinext 0.0.50 → 0.0.51

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 (309) hide show
  1. package/dist/build/google-fonts/fallback-metrics-data.js +14031 -0
  2. package/dist/build/google-fonts/fallback-metrics-data.js.map +1 -0
  3. package/dist/build/google-fonts/fallback-metrics.d.ts +13 -0
  4. package/dist/build/google-fonts/fallback-metrics.js +46 -0
  5. package/dist/build/google-fonts/fallback-metrics.js.map +1 -0
  6. package/dist/build/precompress.d.ts +13 -2
  7. package/dist/build/precompress.js +12 -3
  8. package/dist/build/precompress.js.map +1 -1
  9. package/dist/build/prerender.d.ts +1 -1
  10. package/dist/build/prerender.js +44 -14
  11. package/dist/build/prerender.js.map +1 -1
  12. package/dist/build/report.d.ts +5 -4
  13. package/dist/build/report.js +196 -348
  14. package/dist/build/report.js.map +1 -1
  15. package/dist/check.js +1 -0
  16. package/dist/check.js.map +1 -1
  17. package/dist/cli.js +60 -3
  18. package/dist/cli.js.map +1 -1
  19. package/dist/client/window-next.d.ts +3 -1
  20. package/dist/client/window-next.js.map +1 -1
  21. package/dist/config/dotenv.d.ts +11 -1
  22. package/dist/config/dotenv.js.map +1 -1
  23. package/dist/config/next-config.d.ts +87 -3
  24. package/dist/config/next-config.js +222 -6
  25. package/dist/config/next-config.js.map +1 -1
  26. package/dist/config/tsconfig-paths.d.ts +13 -0
  27. package/dist/config/tsconfig-paths.js +117 -0
  28. package/dist/config/tsconfig-paths.js.map +1 -0
  29. package/dist/deploy.js +3 -2
  30. package/dist/deploy.js.map +1 -1
  31. package/dist/entries/app-browser-entry.d.ts +2 -2
  32. package/dist/entries/app-browser-entry.js +26 -1
  33. package/dist/entries/app-browser-entry.js.map +1 -1
  34. package/dist/entries/app-rsc-entry.d.ts +19 -1
  35. package/dist/entries/app-rsc-entry.js +38 -12
  36. package/dist/entries/app-rsc-entry.js.map +1 -1
  37. package/dist/entries/app-rsc-manifest.d.ts +9 -0
  38. package/dist/entries/app-rsc-manifest.js +4 -1
  39. package/dist/entries/app-rsc-manifest.js.map +1 -1
  40. package/dist/entries/pages-client-entry.js +3 -5
  41. package/dist/entries/pages-client-entry.js.map +1 -1
  42. package/dist/entries/pages-server-entry.js +19 -1
  43. package/dist/entries/pages-server-entry.js.map +1 -1
  44. package/dist/index.js +130 -37
  45. package/dist/index.js.map +1 -1
  46. package/dist/plugins/client-reference-dedup.d.ts +15 -2
  47. package/dist/plugins/client-reference-dedup.js +138 -16
  48. package/dist/plugins/client-reference-dedup.js.map +1 -1
  49. package/dist/plugins/fonts.d.ts +2 -2
  50. package/dist/plugins/fonts.js +15 -6
  51. package/dist/plugins/fonts.js.map +1 -1
  52. package/dist/plugins/sass.d.ts +34 -0
  53. package/dist/plugins/sass.js +22 -0
  54. package/dist/plugins/sass.js.map +1 -0
  55. package/dist/routing/app-route-graph.d.ts +31 -2
  56. package/dist/routing/app-route-graph.js +82 -10
  57. package/dist/routing/app-route-graph.js.map +1 -1
  58. package/dist/routing/route-pattern.d.ts +56 -1
  59. package/dist/routing/route-pattern.js +60 -1
  60. package/dist/routing/route-pattern.js.map +1 -1
  61. package/dist/server/app-browser-action-result.d.ts +27 -2
  62. package/dist/server/app-browser-action-result.js +63 -2
  63. package/dist/server/app-browser-action-result.js.map +1 -1
  64. package/dist/server/app-browser-entry.js +262 -108
  65. package/dist/server/app-browser-entry.js.map +1 -1
  66. package/dist/server/app-browser-hydration.d.ts +13 -1
  67. package/dist/server/app-browser-hydration.js +9 -1
  68. package/dist/server/app-browser-hydration.js.map +1 -1
  69. package/dist/server/app-browser-navigation-controller.d.ts +14 -1
  70. package/dist/server/app-browser-navigation-controller.js +28 -9
  71. package/dist/server/app-browser-navigation-controller.js.map +1 -1
  72. package/dist/server/app-browser-popstate.d.ts +16 -0
  73. package/dist/server/app-browser-popstate.js +17 -0
  74. package/dist/server/app-browser-popstate.js.map +1 -0
  75. package/dist/server/app-browser-rsc-redirect.d.ts +28 -0
  76. package/dist/server/app-browser-rsc-redirect.js +37 -0
  77. package/dist/server/app-browser-rsc-redirect.js.map +1 -0
  78. package/dist/server/app-browser-state.d.ts +11 -7
  79. package/dist/server/app-browser-state.js +45 -27
  80. package/dist/server/app-browser-state.js.map +1 -1
  81. package/dist/server/app-browser-stream.d.ts +5 -4
  82. package/dist/server/app-browser-stream.js +5 -6
  83. package/dist/server/app-browser-stream.js.map +1 -1
  84. package/dist/server/app-browser-visible-commit.d.ts +5 -0
  85. package/dist/server/app-browser-visible-commit.js +38 -5
  86. package/dist/server/app-browser-visible-commit.js.map +1 -1
  87. package/dist/server/app-elements-wire.d.ts +38 -6
  88. package/dist/server/app-elements-wire.js +106 -6
  89. package/dist/server/app-elements-wire.js.map +1 -1
  90. package/dist/server/app-elements.d.ts +2 -2
  91. package/dist/server/app-elements.js +2 -2
  92. package/dist/server/app-elements.js.map +1 -1
  93. package/dist/server/app-fallback-renderer.d.ts +10 -1
  94. package/dist/server/app-fallback-renderer.js +37 -1
  95. package/dist/server/app-fallback-renderer.js.map +1 -1
  96. package/dist/server/app-history-state.d.ts +26 -0
  97. package/dist/server/app-history-state.js +53 -0
  98. package/dist/server/app-history-state.js.map +1 -0
  99. package/dist/server/app-page-boundary-render.d.ts +10 -1
  100. package/dist/server/app-page-boundary-render.js +13 -6
  101. package/dist/server/app-page-boundary-render.js.map +1 -1
  102. package/dist/server/app-page-boundary.js +3 -2
  103. package/dist/server/app-page-boundary.js.map +1 -1
  104. package/dist/server/app-page-cache.d.ts +13 -0
  105. package/dist/server/app-page-cache.js +25 -8
  106. package/dist/server/app-page-cache.js.map +1 -1
  107. package/dist/server/app-page-dispatch.d.ts +5 -0
  108. package/dist/server/app-page-dispatch.js +68 -11
  109. package/dist/server/app-page-dispatch.js.map +1 -1
  110. package/dist/server/app-page-element-builder.d.ts +7 -0
  111. package/dist/server/app-page-element-builder.js +32 -4
  112. package/dist/server/app-page-element-builder.js.map +1 -1
  113. package/dist/server/app-page-execution.js +2 -3
  114. package/dist/server/app-page-execution.js.map +1 -1
  115. package/dist/server/app-page-head.d.ts +7 -0
  116. package/dist/server/app-page-head.js +2 -1
  117. package/dist/server/app-page-head.js.map +1 -1
  118. package/dist/server/app-page-probe.d.ts +23 -1
  119. package/dist/server/app-page-probe.js +29 -1
  120. package/dist/server/app-page-probe.js.map +1 -1
  121. package/dist/server/app-page-render-observation.d.ts +35 -0
  122. package/dist/server/app-page-render-observation.js +68 -0
  123. package/dist/server/app-page-render-observation.js.map +1 -0
  124. package/dist/server/app-page-render.d.ts +5 -1
  125. package/dist/server/app-page-render.js +79 -3
  126. package/dist/server/app-page-render.js.map +1 -1
  127. package/dist/server/app-page-request.d.ts +1 -0
  128. package/dist/server/app-page-request.js.map +1 -1
  129. package/dist/server/app-page-response.js +3 -2
  130. package/dist/server/app-page-response.js.map +1 -1
  131. package/dist/server/app-page-route-wiring.d.ts +3 -1
  132. package/dist/server/app-page-route-wiring.js +42 -14
  133. package/dist/server/app-page-route-wiring.js.map +1 -1
  134. package/dist/server/app-page-stream.d.ts +2 -0
  135. package/dist/server/app-page-stream.js +1 -0
  136. package/dist/server/app-page-stream.js.map +1 -1
  137. package/dist/server/app-router-entry.js +1 -13
  138. package/dist/server/app-router-entry.js.map +1 -1
  139. package/dist/server/app-rsc-cache-busting.d.ts +19 -1
  140. package/dist/server/app-rsc-cache-busting.js +36 -1
  141. package/dist/server/app-rsc-cache-busting.js.map +1 -1
  142. package/dist/server/app-rsc-embedded-chunks.d.ts +9 -0
  143. package/dist/server/app-rsc-embedded-chunks.js +34 -0
  144. package/dist/server/app-rsc-embedded-chunks.js.map +1 -0
  145. package/dist/server/app-rsc-errors.d.ts +4 -1
  146. package/dist/server/app-rsc-errors.js +1 -1
  147. package/dist/server/app-rsc-errors.js.map +1 -1
  148. package/dist/server/app-rsc-handler.d.ts +12 -4
  149. package/dist/server/app-rsc-handler.js +6 -1
  150. package/dist/server/app-rsc-handler.js.map +1 -1
  151. package/dist/server/app-rsc-route-matching.d.ts +23 -0
  152. package/dist/server/app-rsc-route-matching.js +45 -23
  153. package/dist/server/app-rsc-route-matching.js.map +1 -1
  154. package/dist/server/app-server-action-execution.d.ts +35 -3
  155. package/dist/server/app-server-action-execution.js +87 -33
  156. package/dist/server/app-server-action-execution.js.map +1 -1
  157. package/dist/server/app-ssr-entry.d.ts +1 -0
  158. package/dist/server/app-ssr-entry.js +37 -13
  159. package/dist/server/app-ssr-entry.js.map +1 -1
  160. package/dist/server/app-ssr-error-meta.d.ts +14 -0
  161. package/dist/server/app-ssr-error-meta.js +50 -0
  162. package/dist/server/app-ssr-error-meta.js.map +1 -0
  163. package/dist/server/app-ssr-stream.d.ts +1 -1
  164. package/dist/server/app-ssr-stream.js +9 -12
  165. package/dist/server/app-ssr-stream.js.map +1 -1
  166. package/dist/server/artifact-compatibility.d.ts +12 -2
  167. package/dist/server/artifact-compatibility.js +12 -8
  168. package/dist/server/artifact-compatibility.js.map +1 -1
  169. package/dist/server/cache-proof.d.ts +124 -5
  170. package/dist/server/cache-proof.js +416 -18
  171. package/dist/server/cache-proof.js.map +1 -1
  172. package/dist/server/dev-lockfile.d.ts +110 -0
  173. package/dist/server/dev-lockfile.js +180 -0
  174. package/dist/server/dev-lockfile.js.map +1 -0
  175. package/dist/server/dev-server.js +15 -5
  176. package/dist/server/dev-server.js.map +1 -1
  177. package/dist/server/file-based-metadata.d.ts +13 -0
  178. package/dist/server/file-based-metadata.js +49 -2
  179. package/dist/server/file-based-metadata.js.map +1 -1
  180. package/dist/server/headers.d.ts +3 -1
  181. package/dist/server/headers.js +5 -2
  182. package/dist/server/headers.js.map +1 -1
  183. package/dist/server/html.js +1 -1
  184. package/dist/server/html.js.map +1 -1
  185. package/dist/server/http-error-responses.d.ts +10 -0
  186. package/dist/server/http-error-responses.js +11 -1
  187. package/dist/server/http-error-responses.js.map +1 -1
  188. package/dist/server/isr-cache.d.ts +2 -1
  189. package/dist/server/isr-cache.js +4 -2
  190. package/dist/server/isr-cache.js.map +1 -1
  191. package/dist/server/metadata-route-response.js +22 -5
  192. package/dist/server/metadata-route-response.js.map +1 -1
  193. package/dist/server/metadata-routes.js +27 -8
  194. package/dist/server/metadata-routes.js.map +1 -1
  195. package/dist/server/middleware-runtime.js +1 -0
  196. package/dist/server/middleware-runtime.js.map +1 -1
  197. package/dist/server/middleware.d.ts +12 -0
  198. package/dist/server/middleware.js +12 -0
  199. package/dist/server/middleware.js.map +1 -1
  200. package/dist/server/navigation-planner.d.ts +19 -5
  201. package/dist/server/navigation-planner.js +278 -17
  202. package/dist/server/navigation-planner.js.map +1 -1
  203. package/dist/server/navigation-trace.d.ts +8 -1
  204. package/dist/server/navigation-trace.js +7 -0
  205. package/dist/server/navigation-trace.js.map +1 -1
  206. package/dist/server/normalize-path.d.ts +2 -1
  207. package/dist/server/normalize-path.js +4 -1
  208. package/dist/server/normalize-path.js.map +1 -1
  209. package/dist/server/pages-api-route.js +1 -0
  210. package/dist/server/pages-api-route.js.map +1 -1
  211. package/dist/server/pages-page-data.d.ts +3 -2
  212. package/dist/server/pages-page-data.js +22 -3
  213. package/dist/server/pages-page-data.js.map +1 -1
  214. package/dist/server/pages-page-response.js +1 -1
  215. package/dist/server/prod-server.d.ts +28 -1
  216. package/dist/server/prod-server.js +62 -9
  217. package/dist/server/prod-server.js.map +1 -1
  218. package/dist/server/server-action-not-found.d.ts +16 -3
  219. package/dist/server/server-action-not-found.js +19 -1
  220. package/dist/server/server-action-not-found.js.map +1 -1
  221. package/dist/server/server-globals.d.ts +5 -0
  222. package/dist/server/server-globals.js +37 -0
  223. package/dist/server/server-globals.js.map +1 -0
  224. package/dist/server/static-file-cache.js +1 -1
  225. package/dist/server/static-file-cache.js.map +1 -1
  226. package/dist/shims/cache-runtime.d.ts +19 -2
  227. package/dist/shims/cache-runtime.js +67 -11
  228. package/dist/shims/cache-runtime.js.map +1 -1
  229. package/dist/shims/cache.d.ts +5 -18
  230. package/dist/shims/cache.js +2 -0
  231. package/dist/shims/cache.js.map +1 -1
  232. package/dist/shims/error-boundary.js +6 -8
  233. package/dist/shims/error-boundary.js.map +1 -1
  234. package/dist/shims/error.d.ts +18 -1
  235. package/dist/shims/error.js +56 -1
  236. package/dist/shims/error.js.map +1 -1
  237. package/dist/shims/fetch-cache.d.ts +4 -1
  238. package/dist/shims/fetch-cache.js +40 -5
  239. package/dist/shims/fetch-cache.js.map +1 -1
  240. package/dist/shims/font-google-base.d.ts +22 -8
  241. package/dist/shims/font-google-base.js +41 -71
  242. package/dist/shims/font-google-base.js.map +1 -1
  243. package/dist/shims/font-local.d.ts +3 -20
  244. package/dist/shims/font-local.js +23 -75
  245. package/dist/shims/font-local.js.map +1 -1
  246. package/dist/shims/font-utils.d.ts +51 -0
  247. package/dist/shims/font-utils.js +97 -0
  248. package/dist/shims/font-utils.js.map +1 -0
  249. package/dist/shims/hash-scroll.d.ts +7 -0
  250. package/dist/shims/hash-scroll.js +30 -0
  251. package/dist/shims/hash-scroll.js.map +1 -0
  252. package/dist/shims/headers.d.ts +8 -11
  253. package/dist/shims/headers.js +22 -2
  254. package/dist/shims/headers.js.map +1 -1
  255. package/dist/shims/image.d.ts +1 -0
  256. package/dist/shims/image.js +144 -78
  257. package/dist/shims/image.js.map +1 -1
  258. package/dist/shims/internal/app-router-context.d.ts +6 -6
  259. package/dist/shims/internal/app-router-context.js +17 -6
  260. package/dist/shims/internal/app-router-context.js.map +1 -1
  261. package/dist/shims/link-prefetch.d.ts +9 -1
  262. package/dist/shims/link-prefetch.js +11 -6
  263. package/dist/shims/link-prefetch.js.map +1 -1
  264. package/dist/shims/link.d.ts +12 -2
  265. package/dist/shims/link.js +78 -32
  266. package/dist/shims/link.js.map +1 -1
  267. package/dist/shims/metadata.d.ts +16 -30
  268. package/dist/shims/metadata.js +87 -28
  269. package/dist/shims/metadata.js.map +1 -1
  270. package/dist/shims/navigation.d.ts +158 -17
  271. package/dist/shims/navigation.js +324 -74
  272. package/dist/shims/navigation.js.map +1 -1
  273. package/dist/shims/navigation.react-server.d.ts +3 -2
  274. package/dist/shims/navigation.react-server.js +5 -2
  275. package/dist/shims/navigation.react-server.js.map +1 -1
  276. package/dist/shims/pages-router-runtime.d.ts +7 -0
  277. package/dist/shims/pages-router-runtime.js +16 -0
  278. package/dist/shims/pages-router-runtime.js.map +1 -0
  279. package/dist/shims/router.d.ts +32 -6
  280. package/dist/shims/router.js +197 -242
  281. package/dist/shims/router.js.map +1 -1
  282. package/dist/shims/script.js +110 -32
  283. package/dist/shims/script.js.map +1 -1
  284. package/dist/shims/server.js +2 -1
  285. package/dist/shims/server.js.map +1 -1
  286. package/dist/shims/slot.d.ts +1 -0
  287. package/dist/shims/slot.js +41 -1
  288. package/dist/shims/slot.js.map +1 -1
  289. package/dist/shims/unified-request-context.js +2 -0
  290. package/dist/shims/unified-request-context.js.map +1 -1
  291. package/dist/shims/unrecognized-action-error.d.ts +35 -0
  292. package/dist/shims/unrecognized-action-error.js +41 -0
  293. package/dist/shims/unrecognized-action-error.js.map +1 -0
  294. package/dist/shims/url-utils.d.ts +21 -1
  295. package/dist/shims/url-utils.js +67 -3
  296. package/dist/shims/url-utils.js.map +1 -1
  297. package/dist/utils/asset-prefix.d.ts +69 -0
  298. package/dist/utils/asset-prefix.js +91 -0
  299. package/dist/utils/asset-prefix.js.map +1 -0
  300. package/dist/utils/base-path.d.ts +7 -1
  301. package/dist/utils/base-path.js +10 -1
  302. package/dist/utils/base-path.js.map +1 -1
  303. package/dist/utils/navigation-signal.d.ts +1 -2
  304. package/dist/utils/navigation-signal.js +1 -1
  305. package/dist/utils/navigation-signal.js.map +1 -1
  306. package/dist/utils/sorted-array.d.ts +9 -0
  307. package/dist/utils/sorted-array.js +22 -0
  308. package/dist/utils/sorted-array.js.map +1 -0
  309. package/package.json +3 -3
@@ -1,13 +1,15 @@
1
+ import { addBasePathToPathname, hasBasePath } from "../utils/base-path.js";
1
2
  import { ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER } from "./headers.js";
3
+ import { isExternalUrl } from "../config/config-matchers.js";
2
4
  import { internalServerErrorResponse, payloadTooLargeResponse } from "./http-error-responses.js";
3
5
  import { validateCsrfOrigin, validateServerActionPayload } from "./request-pipeline.js";
4
6
  import { getAndClearActionRevalidationKind } from "../shims/cache.js";
5
7
  import { APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI } from "./app-rsc-render-mode.js";
6
8
  import { setCurrentFetchCacheMode } from "../shims/fetch-cache.js";
7
- import { VINEXT_RSC_VARY_HEADER } from "./app-rsc-cache-busting.js";
8
- import { readStreamAsTextWithLimit } from "../utils/text-stream.js";
9
+ import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
9
10
  import { createServerActionNotFoundResponse, getServerActionNotFoundMessage, isServerActionNotFoundError } from "./server-action-not-found.js";
10
11
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
12
+ import { readStreamAsTextWithLimit } from "../utils/text-stream.js";
11
13
  import { getNextErrorDigest, parseNextHttpErrorDigest, parseNextRedirectDigest } from "./next-error-digest.js";
12
14
  import { resolveAppPageActionRerenderTarget } from "./app-page-request.js";
13
15
  //#region src/server/app-server-action-execution.ts
@@ -71,24 +73,6 @@ async function readActionFormDataWithLimit(request, maxBytes) {
71
73
  }
72
74
  return new Response(combined, { headers: { "Content-Type": request.headers.get("content-type") || "" } }).formData();
73
75
  }
74
- function getActionControlResponse(error) {
75
- const digest = getNextErrorDigest(error);
76
- if (!digest) return null;
77
- const redirect = parseNextRedirectDigest(digest);
78
- if (redirect) return {
79
- kind: "redirect",
80
- url: redirect.url
81
- };
82
- const httpError = parseNextHttpErrorDigest(digest);
83
- if (httpError) {
84
- if (!Number.isInteger(httpError.status)) return null;
85
- return {
86
- kind: "status",
87
- statusCode: httpError.status
88
- };
89
- }
90
- return null;
91
- }
92
76
  function getActionRedirect(error) {
93
77
  const digest = getNextErrorDigest(error);
94
78
  if (!digest) return null;
@@ -100,6 +84,41 @@ function getActionRedirect(error) {
100
84
  url: redirect.url
101
85
  };
102
86
  }
87
+ /**
88
+ * Prepend the configured next.config `basePath` to a server-action redirect
89
+ * target before it goes on the wire.
90
+ *
91
+ * `redirect("/foo")` called from a server action mounted at `/base/...` must
92
+ * land the browser at `/base/foo`, mirroring how Next.js threads basePath
93
+ * through `addPathPrefix(getURLFromRedirectError(err), basePath)` in
94
+ * `app-render.tsx` for SSR redirects and in `action-handler.ts` for action
95
+ * redirects.
96
+ *
97
+ * Idempotent and external-aware:
98
+ * - Empty basePath → returned unchanged.
99
+ * - External URLs (`http://`, `https://`, `data:`, protocol-relative `//`)
100
+ * are returned unchanged because the framework does not own those routes.
101
+ * - Targets that already start with the configured basePath are returned
102
+ * unchanged so this helper can be applied at any layer without risk of
103
+ * double-prefixing (`/base/base/foo`).
104
+ *
105
+ * Exported for tests. Used by both the progressive (no-JS form POST) and
106
+ * RSC (`ACTION_REDIRECT_HEADER`) action redirect paths below.
107
+ *
108
+ * @see https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/action-handler.ts
109
+ */
110
+ function applyActionRedirectBasePath(url, basePath) {
111
+ if (!basePath) return url;
112
+ if (isExternalUrl(url)) return url;
113
+ if (hasBasePath(url, basePath)) return url;
114
+ if (!url.startsWith("/")) return url;
115
+ const queryIndex = url.indexOf("?");
116
+ const hashIndex = url.indexOf("#");
117
+ const splitAt = queryIndex === -1 ? hashIndex : hashIndex === -1 ? queryIndex : Math.min(queryIndex, hashIndex);
118
+ const pathname = splitAt === -1 ? url : url.slice(0, splitAt);
119
+ const suffix = splitAt === -1 ? "" : url.slice(splitAt);
120
+ return `${addBasePathToPathname(pathname, basePath)}${suffix}`;
121
+ }
103
122
  function getActionHttpFallbackStatus(error) {
104
123
  const digest = getNextErrorDigest(error);
105
124
  if (!digest) return null;
@@ -133,6 +152,10 @@ function isProgressiveServerActionRequest(request, contentType, actionId) {
133
152
  }
134
153
  async function handleProgressiveServerActionRequest(options) {
135
154
  if (!isProgressiveServerActionRequest(options.request, options.contentType, options.actionId)) return null;
155
+ if (options.request.headers.get("x-action-forwarded")) return createActionNotFoundResponse(null, {
156
+ clearRequestContext: options.clearRequestContext,
157
+ getAndClearPendingCookies: options.getAndClearPendingCookies
158
+ });
136
159
  const csrfResponse = validateCsrfOrigin(options.request, options.allowedOrigins);
137
160
  if (csrfResponse) return csrfResponse;
138
161
  if (parseInt(options.request.headers.get("content-length") || "0", 10) > options.maxActionBodySize) {
@@ -157,19 +180,42 @@ async function handleProgressiveServerActionRequest(options) {
157
180
  }
158
181
  const action = await options.decodeAction(body);
159
182
  if (!isAppServerActionFunction(action)) return null;
160
- let actionControlResponse = null;
183
+ let actionRedirect = null;
184
+ let actionError = void 0;
185
+ let actionFailed = false;
161
186
  let actionResult;
162
187
  const previousHeadersPhase = options.setHeadersAccessPhase("action");
163
188
  try {
164
189
  actionResult = await action();
165
190
  } catch (error) {
166
- actionControlResponse = getActionControlResponse(error);
167
- if (!actionControlResponse) throw error;
191
+ actionRedirect = getActionRedirect(error);
192
+ if (!actionRedirect) {
193
+ actionError = error;
194
+ actionFailed = true;
195
+ if (!(getActionHttpFallbackStatus(error) !== null || isServerActionNotFoundError(error, null))) {
196
+ console.error("[vinext] Server action error:", error);
197
+ options.reportRequestError(normalizeError(error), {
198
+ path: options.cleanPathname,
199
+ method: options.request.method,
200
+ headers: Object.fromEntries(options.request.headers.entries())
201
+ }, {
202
+ routerKind: "App Router",
203
+ routePath: options.cleanPathname,
204
+ routeType: "action"
205
+ });
206
+ }
207
+ }
168
208
  } finally {
169
209
  options.setHeadersAccessPhase(previousHeadersPhase);
170
210
  }
171
- if (!actionControlResponse) {
211
+ if (!actionRedirect) {
172
212
  getAndClearActionRevalidationKind();
213
+ if (actionFailed) return {
214
+ kind: "form-state",
215
+ formState: null,
216
+ actionError,
217
+ actionFailed
218
+ };
173
219
  return {
174
220
  kind: "form-state",
175
221
  formState: await options.decodeFormState(actionResult, body) ?? null
@@ -180,13 +226,14 @@ async function handleProgressiveServerActionRequest(options) {
180
226
  const actionRevalidationKind = resolveActionRevalidationKind(actionPendingCookies.length > 0 || Boolean(actionDraftCookie));
181
227
  options.clearRequestContext();
182
228
  const headers = new Headers();
183
- if (actionControlResponse.kind === "redirect") headers.set("Location", new URL(actionControlResponse.url, options.request.url).toString());
229
+ const prefixedRedirectUrl = applyActionRedirectBasePath(actionRedirect.url, options.basePath ?? "");
230
+ headers.set("Location", new URL(prefixedRedirectUrl, options.request.url).toString());
184
231
  mergeMiddlewareResponseHeaders(headers, options.middlewareHeaders);
185
232
  for (const cookie of actionPendingCookies) headers.append("Set-Cookie", cookie);
186
233
  if (actionDraftCookie) headers.append("Set-Cookie", actionDraftCookie);
187
234
  setActionRevalidatedHeader(headers, actionRevalidationKind);
188
235
  return new Response(null, {
189
- status: actionControlResponse.kind === "redirect" ? 303 : actionControlResponse.statusCode,
236
+ status: 303,
190
237
  headers
191
238
  });
192
239
  } catch (error) {
@@ -196,7 +243,7 @@ async function handleProgressiveServerActionRequest(options) {
196
243
  });
197
244
  getAndClearActionRevalidationKind();
198
245
  options.getAndClearPendingCookies();
199
- console.error("[vinext] Server action error:", error);
246
+ console.error("[vinext] Server action payload parsing error:", error);
200
247
  options.reportRequestError(normalizeError(error), {
201
248
  path: options.cleanPathname,
202
249
  method: options.request.method,
@@ -207,11 +254,15 @@ async function handleProgressiveServerActionRequest(options) {
207
254
  routeType: "action"
208
255
  });
209
256
  options.clearRequestContext();
210
- return internalServerErrorResponse(process.env.NODE_ENV === "production" ? void 0 : "Server action failed: " + getServerActionFailureMessage(error));
257
+ return internalServerErrorResponse(process.env.NODE_ENV === "production" ? void 0 : "Server action parsing failed: " + getServerActionFailureMessage(error));
211
258
  }
212
259
  }
213
260
  async function handleServerActionRscRequest(options) {
214
261
  if (options.request.method.toUpperCase() !== "POST" || !options.actionId) return null;
262
+ if (options.request.headers.get("x-action-forwarded")) return createActionNotFoundResponse(options.actionId, {
263
+ clearRequestContext: options.clearRequestContext,
264
+ getAndClearPendingCookies: options.getAndClearPendingCookies
265
+ });
215
266
  const csrfResponse = validateCsrfOrigin(options.request, options.allowedOrigins);
216
267
  if (csrfResponse) return csrfResponse;
217
268
  if (parseInt(options.request.headers.get("content-length") || "0", 10) > options.maxActionBodySize) {
@@ -293,11 +344,12 @@ async function handleServerActionRscRequest(options) {
293
344
  const actionRevalidationKind = resolveActionRevalidationKind(actionPendingCookies.length > 0 || Boolean(actionDraftCookie));
294
345
  options.clearRequestContext();
295
346
  const redirectHeaders = new Headers({
296
- "Content-Type": "text/x-component; charset=utf-8",
347
+ "Content-Type": VINEXT_RSC_CONTENT_TYPE,
297
348
  Vary: VINEXT_RSC_VARY_HEADER
298
349
  });
299
350
  mergeMiddlewareResponseHeaders(redirectHeaders, options.middlewareHeaders);
300
- redirectHeaders.set(ACTION_REDIRECT_HEADER, actionRedirect.url);
351
+ applyRscCompatibilityIdHeader(redirectHeaders);
352
+ redirectHeaders.set(ACTION_REDIRECT_HEADER, applyActionRedirectBasePath(actionRedirect.url, options.basePath ?? ""));
301
353
  redirectHeaders.set(ACTION_REDIRECT_TYPE_HEADER, actionRedirect.type);
302
354
  redirectHeaders.set(ACTION_REDIRECT_STATUS_HEADER, String(actionRedirect.status));
303
355
  for (const cookie of actionPendingCookies) redirectHeaders.append("Set-Cookie", cookie);
@@ -319,10 +371,11 @@ async function handleServerActionRscRequest(options) {
319
371
  });
320
372
  options.clearRequestContext();
321
373
  const actionHeaders = new Headers({
322
- "Content-Type": "text/x-component; charset=utf-8",
374
+ "Content-Type": VINEXT_RSC_CONTENT_TYPE,
323
375
  Vary: VINEXT_RSC_VARY_HEADER
324
376
  });
325
377
  mergeMiddlewareResponseHeaders(actionHeaders, options.middlewareHeaders);
378
+ applyRscCompatibilityIdHeader(actionHeaders);
326
379
  return new Response(rscStream, {
327
380
  status: options.middlewareStatus ?? actionStatus,
328
381
  headers: actionHeaders
@@ -374,10 +427,11 @@ async function handleServerActionRscRequest(options) {
374
427
  onError: onRenderError
375
428
  });
376
429
  const actionHeaders = new Headers({
377
- "Content-Type": "text/x-component; charset=utf-8",
430
+ "Content-Type": VINEXT_RSC_CONTENT_TYPE,
378
431
  Vary: VINEXT_RSC_VARY_HEADER
379
432
  });
380
433
  mergeMiddlewareResponseHeaders(actionHeaders, options.middlewareHeaders);
434
+ applyRscCompatibilityIdHeader(actionHeaders);
381
435
  setActionRevalidatedHeader(actionHeaders, actionRevalidationKind);
382
436
  const actionResponse = new Response(rscStream, {
383
437
  status: options.middlewareStatus ?? actionStatus,
@@ -400,6 +454,6 @@ async function handleServerActionRscRequest(options) {
400
454
  }
401
455
  }
402
456
  //#endregion
403
- export { handleProgressiveServerActionRequest, handleServerActionRscRequest, isProgressiveServerActionRequest, readActionBodyWithLimit, readActionFormDataWithLimit };
457
+ export { applyActionRedirectBasePath, handleProgressiveServerActionRequest, handleServerActionRscRequest, isProgressiveServerActionRequest, readActionBodyWithLimit, readActionFormDataWithLimit };
404
458
 
405
459
  //# sourceMappingURL=app-server-action-execution.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"app-server-action-execution.js","names":[],"sources":["../../src/server/app-server-action-execution.ts"],"sourcesContent":["import { getAndClearActionRevalidationKind, type ActionRevalidationKind } from \"vinext/shims/cache\";\nimport type { HeadersAccessPhase } from \"vinext/shims/headers\";\nimport { type FetchCacheMode, setCurrentFetchCacheMode } from \"vinext/shims/fetch-cache\";\nimport type { ReactFormState } from \"react-dom/client\";\nimport {\n ACTION_REDIRECT_HEADER,\n ACTION_REDIRECT_STATUS_HEADER,\n ACTION_REDIRECT_TYPE_HEADER,\n ACTION_REVALIDATED_HEADER,\n} from \"./headers.js\";\nimport { VINEXT_RSC_VARY_HEADER } from \"./app-rsc-cache-busting.js\";\nimport { resolveAppPageActionRerenderTarget } from \"./app-page-request.js\";\nimport { mergeMiddlewareResponseHeaders } from \"./middleware-response-headers.js\";\nimport {\n APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI,\n type AppRscRenderMode,\n} from \"./app-rsc-render-mode.js\";\nimport {\n getNextErrorDigest,\n parseNextHttpErrorDigest,\n parseNextRedirectDigest,\n} from \"./next-error-digest.js\";\nimport { validateCsrfOrigin, validateServerActionPayload } from \"./request-pipeline.js\";\nimport { readStreamAsTextWithLimit } from \"../utils/text-stream.js\";\nimport {\n createServerActionNotFoundResponse,\n getServerActionNotFoundMessage,\n isServerActionNotFoundError,\n} from \"./server-action-not-found.js\";\nimport { internalServerErrorResponse, payloadTooLargeResponse } from \"./http-error-responses.js\";\n\ntype AppPageParams = Record<string, string | string[]>;\n\ntype AppServerActionErrorReporter = (\n error: Error,\n request: { path: string; method: string; headers: Record<string, string> },\n route: { routerKind: \"App Router\"; routePath: string; routeType: \"action\" },\n) => void;\n\ntype AppServerActionDecoder = (body: FormData) => Promise<unknown>;\ntype AppServerActionFormStateDecoder = (\n actionResult: unknown,\n body: FormData,\n) => Promise<ReactFormState | undefined>;\n\ntype ReadFormDataWithLimit = (request: Request, maxBytes: number) => Promise<FormData>;\n\ntype ReadBodyWithLimit = (request: Request, maxBytes: number) => Promise<string>;\n\ntype AppServerActionFunction = (...args: unknown[]) => unknown;\n\ntype AppServerActionReturnValue =\n | {\n data: unknown;\n ok: true;\n }\n | {\n data: unknown;\n ok: false;\n };\n\ntype AppServerActionRedirect = {\n status: number;\n type: string;\n url: string;\n};\n\ntype AppServerActionRoute = {\n pattern: string;\n};\n\ntype ProgressiveServerActionResult = {\n formState: ReactFormState | null;\n kind: \"form-state\";\n};\n\ntype AppServerActionMatch<TRoute extends AppServerActionRoute> = {\n params: AppPageParams;\n route: TRoute;\n};\n\ntype AppServerActionIntercept<TPage = unknown> = {\n matchedParams: AppPageParams;\n page: TPage;\n slotKey: string;\n sourceRouteIndex: number;\n};\n\ntype BuildServerActionPageElementOptions<TRoute extends AppServerActionRoute, TInterceptOpts> = {\n cleanPathname: string;\n interceptOpts: TInterceptOpts | undefined;\n isRscRequest: boolean;\n mountedSlotsHeader: string | null;\n params: AppPageParams;\n request: Request;\n route: TRoute;\n searchParams: URLSearchParams;\n renderMode: AppRscRenderMode;\n};\n\ntype AppServerActionRscModel<TElement> = {\n /**\n * Omitted when the action did not invalidate page data. This mirrors Next.js'\n * empty Flight payload for non-revalidating fetch actions: the client resolves\n * the action value without committing a visible router update.\n */\n root?: TElement;\n returnValue: AppServerActionReturnValue;\n};\n\ntype RenderServerActionRscStreamOptions<TTemporaryReferences> = {\n onError: (error: unknown) => unknown;\n temporaryReferences: TTemporaryReferences;\n};\n\ntype DecodeServerActionReplyOptions<TTemporaryReferences> = {\n temporaryReferences: TTemporaryReferences;\n};\n\nexport type HandleProgressiveServerActionRequestOptions = {\n actionId: string | null;\n allowedOrigins: string[];\n cleanPathname: string;\n clearRequestContext: () => void;\n contentType: string;\n decodeAction: AppServerActionDecoder;\n decodeFormState: AppServerActionFormStateDecoder;\n getAndClearPendingCookies: () => string[];\n getDraftModeCookieHeader: () => string | null | undefined;\n maxActionBodySize: number;\n middlewareHeaders: Headers | null;\n readFormDataWithLimit: ReadFormDataWithLimit;\n reportRequestError: AppServerActionErrorReporter;\n request: Request;\n setHeadersAccessPhase: (phase: HeadersAccessPhase) => HeadersAccessPhase;\n};\n\nexport type HandleServerActionRscRequestOptions<\n TElement,\n TRoute extends AppServerActionRoute,\n TInterceptOpts,\n TTemporaryReferences,\n TPage = unknown,\n> = {\n actionId: string | null;\n allowedOrigins: string[];\n buildPageElement: (\n options: BuildServerActionPageElementOptions<TRoute, TInterceptOpts>,\n ) => TElement;\n cleanPathname: string;\n clearRequestContext: () => void;\n contentType: string;\n createNotFoundElement: (routeId: string) => TElement;\n createPayloadRouteId: (pathname: string, interceptionContext: string | null) => string;\n createRscOnErrorHandler: (\n request: Request,\n pathname: string,\n pattern: string,\n ) => (error: unknown) => unknown;\n createTemporaryReferenceSet: () => TTemporaryReferences;\n decodeReply: (\n body: string | FormData,\n options: DecodeServerActionReplyOptions<TTemporaryReferences>,\n ) => Promise<unknown[]> | unknown[];\n findIntercept: (pathname: string) => AppServerActionIntercept<TPage> | null;\n getAndClearPendingCookies: () => string[];\n getDraftModeCookieHeader: () => string | null | undefined;\n getRouteParamNames: (route: TRoute) => readonly string[];\n getSourceRoute: (sourceRouteIndex: number) => TRoute | undefined;\n isRscRequest: boolean;\n loadServerAction: (actionId: string) => Promise<unknown>;\n matchRoute: (pathname: string) => AppServerActionMatch<TRoute> | null;\n maxActionBodySize: number;\n middlewareHeaders: Headers | null;\n middlewareStatus: number | null | undefined;\n mountedSlotsHeader: string | null;\n readBodyWithLimit: ReadBodyWithLimit;\n readFormDataWithLimit: ReadFormDataWithLimit;\n renderToReadableStream: (\n model: AppServerActionRscModel<TElement>,\n options: RenderServerActionRscStreamOptions<TTemporaryReferences>,\n ) => BodyInit | null | Promise<BodyInit | null>;\n reportRequestError: AppServerActionErrorReporter;\n resolveRouteFetchCacheMode?: (route: TRoute) => FetchCacheMode | null;\n request: Request;\n sanitizeErrorForClient: (error: unknown) => unknown;\n searchParams: URLSearchParams;\n setHeadersAccessPhase: (phase: HeadersAccessPhase) => HeadersAccessPhase;\n setNavigationContext: (context: {\n params: AppPageParams;\n pathname: string;\n searchParams: URLSearchParams;\n }) => void;\n toInterceptOpts: (intercept: AppServerActionIntercept<TPage>) => TInterceptOpts;\n};\n\ntype ActionControlResponse =\n | {\n kind: \"redirect\";\n url: string;\n }\n | {\n kind: \"status\";\n statusCode: number;\n };\n\n/**\n * Matches Next.js' server action argument cap to prevent stack overflow in\n * Function.prototype.apply when decoding hostile action payloads.\n */\nconst SERVER_ACTION_ARGS_LIMIT = 1000;\nconst ACTION_DID_NOT_REVALIDATE = 0 satisfies ActionRevalidationKind;\nconst ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC = 1 satisfies ActionRevalidationKind;\n\nfunction setActionRevalidatedHeader(headers: Headers, kind: ActionRevalidationKind): void {\n if (kind === ACTION_DID_NOT_REVALIDATE) return;\n headers.set(ACTION_REVALIDATED_HEADER, JSON.stringify(kind));\n}\n\nfunction resolveActionRevalidationKind(hasModifiedCookies: boolean): ActionRevalidationKind {\n const revalidationKind = getAndClearActionRevalidationKind();\n // Cookie mutations are a hard override to STATIC_AND_DYNAMIC: any cookie\n // change can invalidate downstream cached payloads regardless of what\n // (if anything) the action explicitly revalidated, so we always emit the\n // strongest kind. STATIC_AND_DYNAMIC is also the lowest numeric value, so\n // this matches the max-precedence semantics in markActionRevalidation.\n if (hasModifiedCookies) return ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC;\n return revalidationKind;\n}\n\nfunction isRequestBodyTooLarge(error: unknown): boolean {\n return error instanceof Error && error.message === \"Request body too large\";\n}\n\nfunction isAppServerActionFunction(action: unknown): action is AppServerActionFunction {\n return typeof action === \"function\";\n}\n\nfunction normalizeError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n\nfunction getServerActionFailureMessage(error: unknown): string {\n return error instanceof Error && error.message ? error.message : String(error);\n}\n\nfunction validateServerActionArgs(args: readonly unknown[]): void {\n if (args.length > SERVER_ACTION_ARGS_LIMIT) {\n throw new Error(\n `Server Action arguments list is too long (${args.length}). Maximum allowed is ${SERVER_ACTION_ARGS_LIMIT}.`,\n );\n }\n}\n\nexport async function readActionBodyWithLimit(request: Request, maxBytes: number): Promise<string> {\n if (!request.body) return \"\";\n return readStreamAsTextWithLimit(request.body, maxBytes, () => {\n throw new Error(\"Request body too large\");\n });\n}\n\nexport async function readActionFormDataWithLimit(\n request: Request,\n maxBytes: number,\n): Promise<FormData> {\n if (!request.body) return new FormData();\n\n const reader = request.body.getReader();\n const chunks: Uint8Array[] = [];\n let totalSize = 0;\n\n for (;;) {\n const result = await reader.read();\n if (result.done) break;\n\n totalSize += result.value.byteLength;\n if (totalSize > maxBytes) {\n await reader.cancel();\n throw new Error(\"Request body too large\");\n }\n chunks.push(result.value);\n }\n\n const combined = new Uint8Array(totalSize);\n let offset = 0;\n for (const chunk of chunks) {\n combined.set(chunk, offset);\n offset += chunk.byteLength;\n }\n\n return new Response(combined, {\n headers: { \"Content-Type\": request.headers.get(\"content-type\") || \"\" },\n }).formData();\n}\n\nfunction getActionControlResponse(error: unknown): ActionControlResponse | null {\n const digest = getNextErrorDigest(error);\n if (!digest) return null;\n\n const redirect = parseNextRedirectDigest(digest);\n if (redirect) {\n return {\n kind: \"redirect\",\n url: redirect.url,\n };\n }\n\n const httpError = parseNextHttpErrorDigest(digest);\n if (httpError) {\n if (!Number.isInteger(httpError.status)) {\n return null;\n }\n\n return {\n kind: \"status\",\n statusCode: httpError.status,\n };\n }\n\n return null;\n}\n\nfunction getActionRedirect(error: unknown): AppServerActionRedirect | null {\n const digest = getNextErrorDigest(error);\n if (!digest) return null;\n\n const redirect = parseNextRedirectDigest(digest);\n if (!redirect) return null;\n\n return {\n status: redirect.status,\n type: redirect.type ?? \"push\",\n url: redirect.url,\n };\n}\n\nfunction getActionHttpFallbackStatus(error: unknown): number | null {\n const digest = getNextErrorDigest(error);\n if (!digest) return null;\n\n const httpError = parseNextHttpErrorDigest(digest);\n if (!httpError || !Number.isInteger(httpError.status)) return null;\n\n return httpError.status;\n}\n\nfunction createServerActionErrorResponse(\n error: unknown,\n options: {\n cleanPathname: string;\n clearRequestContext: () => void;\n getAndClearPendingCookies: () => string[];\n reportRequestError: AppServerActionErrorReporter;\n request: Request;\n },\n): Response {\n options.getAndClearPendingCookies();\n console.error(\"[vinext] Server action error:\", error);\n options.reportRequestError(\n normalizeError(error),\n {\n path: options.cleanPathname,\n method: options.request.method,\n headers: Object.fromEntries(options.request.headers.entries()),\n },\n { routerKind: \"App Router\", routePath: options.cleanPathname, routeType: \"action\" },\n );\n options.clearRequestContext();\n return internalServerErrorResponse(\n process.env.NODE_ENV === \"production\"\n ? undefined\n : \"Server action failed: \" + getServerActionFailureMessage(error),\n );\n}\n\nfunction createActionNotFoundResponse(\n actionId: string | null,\n options: {\n clearRequestContext: () => void;\n getAndClearPendingCookies: () => string[];\n },\n): Response {\n options.getAndClearPendingCookies();\n console.warn(getServerActionNotFoundMessage(actionId));\n options.clearRequestContext();\n return createServerActionNotFoundResponse();\n}\n\nexport function isProgressiveServerActionRequest(\n request: Pick<Request, \"method\">,\n contentType: string,\n actionId: string | null,\n): boolean {\n return (\n request.method.toUpperCase() === \"POST\" &&\n contentType.startsWith(\"multipart/form-data\") &&\n !actionId\n );\n}\n\nexport async function handleProgressiveServerActionRequest(\n options: HandleProgressiveServerActionRequestOptions,\n): Promise<Response | ProgressiveServerActionResult | null> {\n if (!isProgressiveServerActionRequest(options.request, options.contentType, options.actionId)) {\n return null;\n }\n\n const csrfResponse = validateCsrfOrigin(options.request, options.allowedOrigins);\n if (csrfResponse) {\n return csrfResponse;\n }\n\n const contentLength = parseInt(options.request.headers.get(\"content-length\") || \"0\", 10);\n if (contentLength > options.maxActionBodySize) {\n options.clearRequestContext();\n return payloadTooLargeResponse();\n }\n\n try {\n let body: FormData;\n try {\n // Progressive submissions can still fall through to a regular page render when\n // the multipart body is not an action payload. Read a clone so that fallback\n // code can still consume the original request body.\n body = await options.readFormDataWithLimit(\n options.request.clone(),\n options.maxActionBodySize,\n );\n } catch (error) {\n if (isRequestBodyTooLarge(error)) {\n options.clearRequestContext();\n return payloadTooLargeResponse();\n }\n throw error;\n }\n\n const payloadResponse = await validateServerActionPayload(body);\n if (payloadResponse) {\n options.clearRequestContext();\n return payloadResponse;\n }\n\n const action = await options.decodeAction(body);\n if (!isAppServerActionFunction(action)) {\n return null;\n }\n\n let actionControlResponse: ActionControlResponse | null = null;\n let actionResult: unknown;\n const previousHeadersPhase = options.setHeadersAccessPhase(\"action\");\n try {\n actionResult = await action();\n } catch (error) {\n actionControlResponse = getActionControlResponse(error);\n if (!actionControlResponse) {\n throw error;\n }\n } finally {\n options.setHeadersAccessPhase(previousHeadersPhase);\n }\n\n if (!actionControlResponse) {\n getAndClearActionRevalidationKind();\n const formState = await options.decodeFormState(actionResult, body);\n return { kind: \"form-state\", formState: formState ?? null };\n }\n\n const actionPendingCookies = options.getAndClearPendingCookies();\n const actionDraftCookie = options.getDraftModeCookieHeader();\n const actionRevalidationKind = resolveActionRevalidationKind(\n actionPendingCookies.length > 0 || Boolean(actionDraftCookie),\n );\n options.clearRequestContext();\n\n const headers = new Headers();\n if (actionControlResponse.kind === \"redirect\") {\n headers.set(\"Location\", new URL(actionControlResponse.url, options.request.url).toString());\n }\n mergeMiddlewareResponseHeaders(headers, options.middlewareHeaders);\n for (const cookie of actionPendingCookies) {\n headers.append(\"Set-Cookie\", cookie);\n }\n if (actionDraftCookie) {\n headers.append(\"Set-Cookie\", actionDraftCookie);\n }\n setActionRevalidatedHeader(headers, actionRevalidationKind);\n\n return new Response(null, {\n status: actionControlResponse.kind === \"redirect\" ? 303 : actionControlResponse.statusCode,\n headers,\n });\n } catch (error) {\n if (isServerActionNotFoundError(error, null)) {\n return createActionNotFoundResponse(null, {\n clearRequestContext: options.clearRequestContext,\n getAndClearPendingCookies: options.getAndClearPendingCookies,\n });\n }\n\n getAndClearActionRevalidationKind();\n options.getAndClearPendingCookies();\n // Next.js rethrows generic MPA action errors into its page render path.\n // vinext does not yet implement that form-state render path, so unexpected\n // action failures remain request failures here.\n console.error(\"[vinext] Server action error:\", error);\n options.reportRequestError(\n normalizeError(error),\n {\n path: options.cleanPathname,\n method: options.request.method,\n headers: Object.fromEntries(options.request.headers.entries()),\n },\n { routerKind: \"App Router\", routePath: options.cleanPathname, routeType: \"action\" },\n );\n options.clearRequestContext();\n return internalServerErrorResponse(\n process.env.NODE_ENV === \"production\"\n ? undefined\n : \"Server action failed: \" + getServerActionFailureMessage(error),\n );\n }\n}\n\nexport async function handleServerActionRscRequest<\n TElement,\n TRoute extends AppServerActionRoute,\n TInterceptOpts,\n TTemporaryReferences,\n TPage = unknown,\n>(\n options: HandleServerActionRscRequestOptions<\n TElement,\n TRoute,\n TInterceptOpts,\n TTemporaryReferences,\n TPage\n >,\n): Promise<Response | null> {\n if (options.request.method.toUpperCase() !== \"POST\" || !options.actionId) {\n return null;\n }\n\n const csrfResponse = validateCsrfOrigin(options.request, options.allowedOrigins);\n if (csrfResponse) return csrfResponse;\n\n const contentLength = parseInt(options.request.headers.get(\"content-length\") || \"0\", 10);\n if (contentLength > options.maxActionBodySize) {\n options.clearRequestContext();\n return payloadTooLargeResponse();\n }\n\n try {\n let body: string | FormData;\n try {\n body = options.contentType.startsWith(\"multipart/form-data\")\n ? await options.readFormDataWithLimit(options.request, options.maxActionBodySize)\n : await options.readBodyWithLimit(options.request, options.maxActionBodySize);\n } catch (error) {\n if (isRequestBodyTooLarge(error)) {\n options.clearRequestContext();\n return payloadTooLargeResponse();\n }\n throw error;\n }\n\n const payloadResponse = await validateServerActionPayload(body);\n if (payloadResponse) {\n options.clearRequestContext();\n return payloadResponse;\n }\n\n let action: unknown;\n try {\n action = await options.loadServerAction(options.actionId);\n } catch (error) {\n if (isServerActionNotFoundError(error, options.actionId)) {\n return createActionNotFoundResponse(options.actionId, {\n clearRequestContext: options.clearRequestContext,\n getAndClearPendingCookies: options.getAndClearPendingCookies,\n });\n }\n\n throw error;\n }\n\n if (!isAppServerActionFunction(action)) {\n return createActionNotFoundResponse(options.actionId, {\n clearRequestContext: options.clearRequestContext,\n getAndClearPendingCookies: options.getAndClearPendingCookies,\n });\n }\n\n const temporaryReferences = options.createTemporaryReferenceSet();\n const args = await options.decodeReply(body, { temporaryReferences });\n let returnValue: AppServerActionReturnValue;\n let actionRedirect: AppServerActionRedirect | null = null;\n let actionStatus = 200;\n const previousHeadersPhase = options.setHeadersAccessPhase(\"action\");\n try {\n try {\n validateServerActionArgs(args);\n const data = await action.apply(null, args);\n returnValue = { ok: true, data };\n } catch (error) {\n actionRedirect = getActionRedirect(error);\n if (actionRedirect) {\n returnValue = { ok: true, data: undefined };\n } else {\n const httpFallbackStatus = getActionHttpFallbackStatus(error);\n if (httpFallbackStatus !== null) {\n actionStatus = httpFallbackStatus;\n returnValue = { ok: false, data: error };\n } else {\n console.error(\"[vinext] Server action error:\", error);\n returnValue = { ok: false, data: options.sanitizeErrorForClient(error) };\n }\n }\n }\n } finally {\n options.setHeadersAccessPhase(previousHeadersPhase);\n }\n\n if (actionRedirect) {\n const actionPendingCookies = options.getAndClearPendingCookies();\n const actionDraftCookie = options.getDraftModeCookieHeader();\n const actionRevalidationKind = resolveActionRevalidationKind(\n actionPendingCookies.length > 0 || Boolean(actionDraftCookie),\n );\n options.clearRequestContext();\n const redirectHeaders = new Headers({\n \"Content-Type\": \"text/x-component; charset=utf-8\",\n Vary: VINEXT_RSC_VARY_HEADER,\n });\n mergeMiddlewareResponseHeaders(redirectHeaders, options.middlewareHeaders);\n redirectHeaders.set(ACTION_REDIRECT_HEADER, actionRedirect.url);\n redirectHeaders.set(ACTION_REDIRECT_TYPE_HEADER, actionRedirect.type);\n redirectHeaders.set(ACTION_REDIRECT_STATUS_HEADER, String(actionRedirect.status));\n for (const cookie of actionPendingCookies) {\n redirectHeaders.append(\"Set-Cookie\", cookie);\n }\n if (actionDraftCookie) redirectHeaders.append(\"Set-Cookie\", actionDraftCookie);\n setActionRevalidatedHeader(redirectHeaders, actionRevalidationKind);\n return new Response(\"\", { status: 200, headers: redirectHeaders });\n }\n\n const actionPendingCookies = options.getAndClearPendingCookies();\n const actionDraftCookie = options.getDraftModeCookieHeader();\n const actionRevalidationKind = resolveActionRevalidationKind(\n actionPendingCookies.length > 0 || Boolean(actionDraftCookie),\n );\n\n const shouldSkipPageRendering = actionRevalidationKind === ACTION_DID_NOT_REVALIDATE;\n if (shouldSkipPageRendering) {\n const onRenderError = options.createRscOnErrorHandler(\n options.request,\n options.cleanPathname,\n options.cleanPathname,\n );\n const rscStream = await options.renderToReadableStream(\n { returnValue },\n { temporaryReferences, onError: onRenderError },\n );\n\n options.clearRequestContext();\n\n const actionHeaders = new Headers({\n \"Content-Type\": \"text/x-component; charset=utf-8\",\n Vary: VINEXT_RSC_VARY_HEADER,\n });\n mergeMiddlewareResponseHeaders(actionHeaders, options.middlewareHeaders);\n\n return new Response(rscStream, {\n status: options.middlewareStatus ?? actionStatus,\n headers: actionHeaders,\n });\n }\n\n const match = options.matchRoute(options.cleanPathname);\n let element: TElement;\n let errorPattern = match ? match.route.pattern : options.cleanPathname;\n if (match) {\n const { route: actionRoute, params: actionParams } = match;\n const actionRerenderTarget = resolveAppPageActionRerenderTarget({\n cleanPathname: options.cleanPathname,\n currentParams: actionParams,\n currentRoute: actionRoute,\n findIntercept: options.findIntercept,\n getRouteParamNames: options.getRouteParamNames,\n getSourceRoute: options.getSourceRoute,\n isRscRequest: options.isRscRequest,\n toInterceptOpts: options.toInterceptOpts,\n });\n\n options.setNavigationContext({\n pathname: options.cleanPathname,\n searchParams: options.searchParams,\n params: actionRerenderTarget.navigationParams,\n });\n setCurrentFetchCacheMode(\n options.resolveRouteFetchCacheMode?.(actionRerenderTarget.route) ?? null,\n );\n element = options.buildPageElement({\n cleanPathname: options.cleanPathname,\n interceptOpts: actionRerenderTarget.interceptOpts,\n isRscRequest: options.isRscRequest,\n mountedSlotsHeader: options.mountedSlotsHeader,\n params: actionRerenderTarget.params,\n request: options.request,\n route: actionRerenderTarget.route,\n searchParams: options.searchParams,\n renderMode: APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI,\n });\n errorPattern = actionRerenderTarget.route.pattern;\n } else {\n const actionRouteId = options.createPayloadRouteId(options.cleanPathname, null);\n element = options.createNotFoundElement(actionRouteId);\n }\n\n const onRenderError = options.createRscOnErrorHandler(\n options.request,\n options.cleanPathname,\n errorPattern,\n );\n const rscStream = await options.renderToReadableStream(\n { root: element, returnValue },\n { temporaryReferences, onError: onRenderError },\n );\n\n const actionHeaders = new Headers({\n \"Content-Type\": \"text/x-component; charset=utf-8\",\n Vary: VINEXT_RSC_VARY_HEADER,\n });\n mergeMiddlewareResponseHeaders(actionHeaders, options.middlewareHeaders);\n setActionRevalidatedHeader(actionHeaders, actionRevalidationKind);\n const actionResponse = new Response(rscStream, {\n status: options.middlewareStatus ?? actionStatus,\n headers: actionHeaders,\n });\n if (actionPendingCookies.length > 0 || actionDraftCookie) {\n for (const cookie of actionPendingCookies) {\n actionResponse.headers.append(\"Set-Cookie\", cookie);\n }\n if (actionDraftCookie) actionResponse.headers.append(\"Set-Cookie\", actionDraftCookie);\n }\n return actionResponse;\n } catch (error) {\n getAndClearActionRevalidationKind();\n return createServerActionErrorResponse(error, {\n cleanPathname: options.cleanPathname,\n clearRequestContext: options.clearRequestContext,\n getAndClearPendingCookies: options.getAndClearPendingCookies,\n reportRequestError: options.reportRequestError,\n request: options.request,\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAkNA,MAAM,2BAA2B;AACjC,MAAM,4BAA4B;AAClC,MAAM,2CAA2C;AAEjD,SAAS,2BAA2B,SAAkB,MAAoC;CACxF,IAAI,SAAS,2BAA2B;CACxC,QAAQ,IAAI,2BAA2B,KAAK,UAAU,KAAK,CAAC;;AAG9D,SAAS,8BAA8B,oBAAqD;CAC1F,MAAM,mBAAmB,mCAAmC;CAM5D,IAAI,oBAAoB,OAAO;CAC/B,OAAO;;AAGT,SAAS,sBAAsB,OAAyB;CACtD,OAAO,iBAAiB,SAAS,MAAM,YAAY;;AAGrD,SAAS,0BAA0B,QAAoD;CACrF,OAAO,OAAO,WAAW;;AAG3B,SAAS,eAAe,OAAuB;CAC7C,OAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,MAAM,CAAC;;AAGlE,SAAS,8BAA8B,OAAwB;CAC7D,OAAO,iBAAiB,SAAS,MAAM,UAAU,MAAM,UAAU,OAAO,MAAM;;AAGhF,SAAS,yBAAyB,MAAgC;CAChE,IAAI,KAAK,SAAS,0BAChB,MAAM,IAAI,MACR,6CAA6C,KAAK,OAAO,wBAAwB,yBAAyB,GAC3G;;AAIL,eAAsB,wBAAwB,SAAkB,UAAmC;CACjG,IAAI,CAAC,QAAQ,MAAM,OAAO;CAC1B,OAAO,0BAA0B,QAAQ,MAAM,gBAAgB;EAC7D,MAAM,IAAI,MAAM,yBAAyB;GACzC;;AAGJ,eAAsB,4BACpB,SACA,UACmB;CACnB,IAAI,CAAC,QAAQ,MAAM,OAAO,IAAI,UAAU;CAExC,MAAM,SAAS,QAAQ,KAAK,WAAW;CACvC,MAAM,SAAuB,EAAE;CAC/B,IAAI,YAAY;CAEhB,SAAS;EACP,MAAM,SAAS,MAAM,OAAO,MAAM;EAClC,IAAI,OAAO,MAAM;EAEjB,aAAa,OAAO,MAAM;EAC1B,IAAI,YAAY,UAAU;GACxB,MAAM,OAAO,QAAQ;GACrB,MAAM,IAAI,MAAM,yBAAyB;;EAE3C,OAAO,KAAK,OAAO,MAAM;;CAG3B,MAAM,WAAW,IAAI,WAAW,UAAU;CAC1C,IAAI,SAAS;CACb,KAAK,MAAM,SAAS,QAAQ;EAC1B,SAAS,IAAI,OAAO,OAAO;EAC3B,UAAU,MAAM;;CAGlB,OAAO,IAAI,SAAS,UAAU,EAC5B,SAAS,EAAE,gBAAgB,QAAQ,QAAQ,IAAI,eAAe,IAAI,IAAI,EACvE,CAAC,CAAC,UAAU;;AAGf,SAAS,yBAAyB,OAA8C;CAC9E,MAAM,SAAS,mBAAmB,MAAM;CACxC,IAAI,CAAC,QAAQ,OAAO;CAEpB,MAAM,WAAW,wBAAwB,OAAO;CAChD,IAAI,UACF,OAAO;EACL,MAAM;EACN,KAAK,SAAS;EACf;CAGH,MAAM,YAAY,yBAAyB,OAAO;CAClD,IAAI,WAAW;EACb,IAAI,CAAC,OAAO,UAAU,UAAU,OAAO,EACrC,OAAO;EAGT,OAAO;GACL,MAAM;GACN,YAAY,UAAU;GACvB;;CAGH,OAAO;;AAGT,SAAS,kBAAkB,OAAgD;CACzE,MAAM,SAAS,mBAAmB,MAAM;CACxC,IAAI,CAAC,QAAQ,OAAO;CAEpB,MAAM,WAAW,wBAAwB,OAAO;CAChD,IAAI,CAAC,UAAU,OAAO;CAEtB,OAAO;EACL,QAAQ,SAAS;EACjB,MAAM,SAAS,QAAQ;EACvB,KAAK,SAAS;EACf;;AAGH,SAAS,4BAA4B,OAA+B;CAClE,MAAM,SAAS,mBAAmB,MAAM;CACxC,IAAI,CAAC,QAAQ,OAAO;CAEpB,MAAM,YAAY,yBAAyB,OAAO;CAClD,IAAI,CAAC,aAAa,CAAC,OAAO,UAAU,UAAU,OAAO,EAAE,OAAO;CAE9D,OAAO,UAAU;;AAGnB,SAAS,gCACP,OACA,SAOU;CACV,QAAQ,2BAA2B;CACnC,QAAQ,MAAM,iCAAiC,MAAM;CACrD,QAAQ,mBACN,eAAe,MAAM,EACrB;EACE,MAAM,QAAQ;EACd,QAAQ,QAAQ,QAAQ;EACxB,SAAS,OAAO,YAAY,QAAQ,QAAQ,QAAQ,SAAS,CAAC;EAC/D,EACD;EAAE,YAAY;EAAc,WAAW,QAAQ;EAAe,WAAW;EAAU,CACpF;CACD,QAAQ,qBAAqB;CAC7B,OAAO,4BACL,QAAQ,IAAI,aAAa,eACrB,KAAA,IACA,2BAA2B,8BAA8B,MAAM,CACpE;;AAGH,SAAS,6BACP,UACA,SAIU;CACV,QAAQ,2BAA2B;CACnC,QAAQ,KAAK,+BAA+B,SAAS,CAAC;CACtD,QAAQ,qBAAqB;CAC7B,OAAO,oCAAoC;;AAG7C,SAAgB,iCACd,SACA,aACA,UACS;CACT,OACE,QAAQ,OAAO,aAAa,KAAK,UACjC,YAAY,WAAW,sBAAsB,IAC7C,CAAC;;AAIL,eAAsB,qCACpB,SAC0D;CAC1D,IAAI,CAAC,iCAAiC,QAAQ,SAAS,QAAQ,aAAa,QAAQ,SAAS,EAC3F,OAAO;CAGT,MAAM,eAAe,mBAAmB,QAAQ,SAAS,QAAQ,eAAe;CAChF,IAAI,cACF,OAAO;CAIT,IADsB,SAAS,QAAQ,QAAQ,QAAQ,IAAI,iBAAiB,IAAI,KAAK,GACpE,GAAG,QAAQ,mBAAmB;EAC7C,QAAQ,qBAAqB;EAC7B,OAAO,yBAAyB;;CAGlC,IAAI;EACF,IAAI;EACJ,IAAI;GAIF,OAAO,MAAM,QAAQ,sBACnB,QAAQ,QAAQ,OAAO,EACvB,QAAQ,kBACT;WACM,OAAO;GACd,IAAI,sBAAsB,MAAM,EAAE;IAChC,QAAQ,qBAAqB;IAC7B,OAAO,yBAAyB;;GAElC,MAAM;;EAGR,MAAM,kBAAkB,MAAM,4BAA4B,KAAK;EAC/D,IAAI,iBAAiB;GACnB,QAAQ,qBAAqB;GAC7B,OAAO;;EAGT,MAAM,SAAS,MAAM,QAAQ,aAAa,KAAK;EAC/C,IAAI,CAAC,0BAA0B,OAAO,EACpC,OAAO;EAGT,IAAI,wBAAsD;EAC1D,IAAI;EACJ,MAAM,uBAAuB,QAAQ,sBAAsB,SAAS;EACpE,IAAI;GACF,eAAe,MAAM,QAAQ;WACtB,OAAO;GACd,wBAAwB,yBAAyB,MAAM;GACvD,IAAI,CAAC,uBACH,MAAM;YAEA;GACR,QAAQ,sBAAsB,qBAAqB;;EAGrD,IAAI,CAAC,uBAAuB;GAC1B,mCAAmC;GAEnC,OAAO;IAAE,MAAM;IAAc,WAAW,MADhB,QAAQ,gBAAgB,cAAc,KAAK,IACd;IAAM;;EAG7D,MAAM,uBAAuB,QAAQ,2BAA2B;EAChE,MAAM,oBAAoB,QAAQ,0BAA0B;EAC5D,MAAM,yBAAyB,8BAC7B,qBAAqB,SAAS,KAAK,QAAQ,kBAAkB,CAC9D;EACD,QAAQ,qBAAqB;EAE7B,MAAM,UAAU,IAAI,SAAS;EAC7B,IAAI,sBAAsB,SAAS,YACjC,QAAQ,IAAI,YAAY,IAAI,IAAI,sBAAsB,KAAK,QAAQ,QAAQ,IAAI,CAAC,UAAU,CAAC;EAE7F,+BAA+B,SAAS,QAAQ,kBAAkB;EAClE,KAAK,MAAM,UAAU,sBACnB,QAAQ,OAAO,cAAc,OAAO;EAEtC,IAAI,mBACF,QAAQ,OAAO,cAAc,kBAAkB;EAEjD,2BAA2B,SAAS,uBAAuB;EAE3D,OAAO,IAAI,SAAS,MAAM;GACxB,QAAQ,sBAAsB,SAAS,aAAa,MAAM,sBAAsB;GAChF;GACD,CAAC;UACK,OAAO;EACd,IAAI,4BAA4B,OAAO,KAAK,EAC1C,OAAO,6BAA6B,MAAM;GACxC,qBAAqB,QAAQ;GAC7B,2BAA2B,QAAQ;GACpC,CAAC;EAGJ,mCAAmC;EACnC,QAAQ,2BAA2B;EAInC,QAAQ,MAAM,iCAAiC,MAAM;EACrD,QAAQ,mBACN,eAAe,MAAM,EACrB;GACE,MAAM,QAAQ;GACd,QAAQ,QAAQ,QAAQ;GACxB,SAAS,OAAO,YAAY,QAAQ,QAAQ,QAAQ,SAAS,CAAC;GAC/D,EACD;GAAE,YAAY;GAAc,WAAW,QAAQ;GAAe,WAAW;GAAU,CACpF;EACD,QAAQ,qBAAqB;EAC7B,OAAO,4BACL,QAAQ,IAAI,aAAa,eACrB,KAAA,IACA,2BAA2B,8BAA8B,MAAM,CACpE;;;AAIL,eAAsB,6BAOpB,SAO0B;CAC1B,IAAI,QAAQ,QAAQ,OAAO,aAAa,KAAK,UAAU,CAAC,QAAQ,UAC9D,OAAO;CAGT,MAAM,eAAe,mBAAmB,QAAQ,SAAS,QAAQ,eAAe;CAChF,IAAI,cAAc,OAAO;CAGzB,IADsB,SAAS,QAAQ,QAAQ,QAAQ,IAAI,iBAAiB,IAAI,KAAK,GACpE,GAAG,QAAQ,mBAAmB;EAC7C,QAAQ,qBAAqB;EAC7B,OAAO,yBAAyB;;CAGlC,IAAI;EACF,IAAI;EACJ,IAAI;GACF,OAAO,QAAQ,YAAY,WAAW,sBAAsB,GACxD,MAAM,QAAQ,sBAAsB,QAAQ,SAAS,QAAQ,kBAAkB,GAC/E,MAAM,QAAQ,kBAAkB,QAAQ,SAAS,QAAQ,kBAAkB;WACxE,OAAO;GACd,IAAI,sBAAsB,MAAM,EAAE;IAChC,QAAQ,qBAAqB;IAC7B,OAAO,yBAAyB;;GAElC,MAAM;;EAGR,MAAM,kBAAkB,MAAM,4BAA4B,KAAK;EAC/D,IAAI,iBAAiB;GACnB,QAAQ,qBAAqB;GAC7B,OAAO;;EAGT,IAAI;EACJ,IAAI;GACF,SAAS,MAAM,QAAQ,iBAAiB,QAAQ,SAAS;WAClD,OAAO;GACd,IAAI,4BAA4B,OAAO,QAAQ,SAAS,EACtD,OAAO,6BAA6B,QAAQ,UAAU;IACpD,qBAAqB,QAAQ;IAC7B,2BAA2B,QAAQ;IACpC,CAAC;GAGJ,MAAM;;EAGR,IAAI,CAAC,0BAA0B,OAAO,EACpC,OAAO,6BAA6B,QAAQ,UAAU;GACpD,qBAAqB,QAAQ;GAC7B,2BAA2B,QAAQ;GACpC,CAAC;EAGJ,MAAM,sBAAsB,QAAQ,6BAA6B;EACjE,MAAM,OAAO,MAAM,QAAQ,YAAY,MAAM,EAAE,qBAAqB,CAAC;EACrE,IAAI;EACJ,IAAI,iBAAiD;EACrD,IAAI,eAAe;EACnB,MAAM,uBAAuB,QAAQ,sBAAsB,SAAS;EACpE,IAAI;GACF,IAAI;IACF,yBAAyB,KAAK;IAE9B,cAAc;KAAE,IAAI;KAAM,MAAA,MADP,OAAO,MAAM,MAAM,KAAK;KACX;YACzB,OAAO;IACd,iBAAiB,kBAAkB,MAAM;IACzC,IAAI,gBACF,cAAc;KAAE,IAAI;KAAM,MAAM,KAAA;KAAW;SACtC;KACL,MAAM,qBAAqB,4BAA4B,MAAM;KAC7D,IAAI,uBAAuB,MAAM;MAC/B,eAAe;MACf,cAAc;OAAE,IAAI;OAAO,MAAM;OAAO;YACnC;MACL,QAAQ,MAAM,iCAAiC,MAAM;MACrD,cAAc;OAAE,IAAI;OAAO,MAAM,QAAQ,uBAAuB,MAAM;OAAE;;;;YAItE;GACR,QAAQ,sBAAsB,qBAAqB;;EAGrD,IAAI,gBAAgB;GAClB,MAAM,uBAAuB,QAAQ,2BAA2B;GAChE,MAAM,oBAAoB,QAAQ,0BAA0B;GAC5D,MAAM,yBAAyB,8BAC7B,qBAAqB,SAAS,KAAK,QAAQ,kBAAkB,CAC9D;GACD,QAAQ,qBAAqB;GAC7B,MAAM,kBAAkB,IAAI,QAAQ;IAClC,gBAAgB;IAChB,MAAM;IACP,CAAC;GACF,+BAA+B,iBAAiB,QAAQ,kBAAkB;GAC1E,gBAAgB,IAAI,wBAAwB,eAAe,IAAI;GAC/D,gBAAgB,IAAI,6BAA6B,eAAe,KAAK;GACrE,gBAAgB,IAAI,+BAA+B,OAAO,eAAe,OAAO,CAAC;GACjF,KAAK,MAAM,UAAU,sBACnB,gBAAgB,OAAO,cAAc,OAAO;GAE9C,IAAI,mBAAmB,gBAAgB,OAAO,cAAc,kBAAkB;GAC9E,2BAA2B,iBAAiB,uBAAuB;GACnE,OAAO,IAAI,SAAS,IAAI;IAAE,QAAQ;IAAK,SAAS;IAAiB,CAAC;;EAGpE,MAAM,uBAAuB,QAAQ,2BAA2B;EAChE,MAAM,oBAAoB,QAAQ,0BAA0B;EAC5D,MAAM,yBAAyB,8BAC7B,qBAAqB,SAAS,KAAK,QAAQ,kBAAkB,CAC9D;EAGD,IADgC,2BAA2B,2BAC9B;GAC3B,MAAM,gBAAgB,QAAQ,wBAC5B,QAAQ,SACR,QAAQ,eACR,QAAQ,cACT;GACD,MAAM,YAAY,MAAM,QAAQ,uBAC9B,EAAE,aAAa,EACf;IAAE;IAAqB,SAAS;IAAe,CAChD;GAED,QAAQ,qBAAqB;GAE7B,MAAM,gBAAgB,IAAI,QAAQ;IAChC,gBAAgB;IAChB,MAAM;IACP,CAAC;GACF,+BAA+B,eAAe,QAAQ,kBAAkB;GAExE,OAAO,IAAI,SAAS,WAAW;IAC7B,QAAQ,QAAQ,oBAAoB;IACpC,SAAS;IACV,CAAC;;EAGJ,MAAM,QAAQ,QAAQ,WAAW,QAAQ,cAAc;EACvD,IAAI;EACJ,IAAI,eAAe,QAAQ,MAAM,MAAM,UAAU,QAAQ;EACzD,IAAI,OAAO;GACT,MAAM,EAAE,OAAO,aAAa,QAAQ,iBAAiB;GACrD,MAAM,uBAAuB,mCAAmC;IAC9D,eAAe,QAAQ;IACvB,eAAe;IACf,cAAc;IACd,eAAe,QAAQ;IACvB,oBAAoB,QAAQ;IAC5B,gBAAgB,QAAQ;IACxB,cAAc,QAAQ;IACtB,iBAAiB,QAAQ;IAC1B,CAAC;GAEF,QAAQ,qBAAqB;IAC3B,UAAU,QAAQ;IAClB,cAAc,QAAQ;IACtB,QAAQ,qBAAqB;IAC9B,CAAC;GACF,yBACE,QAAQ,6BAA6B,qBAAqB,MAAM,IAAI,KACrE;GACD,UAAU,QAAQ,iBAAiB;IACjC,eAAe,QAAQ;IACvB,eAAe,qBAAqB;IACpC,cAAc,QAAQ;IACtB,oBAAoB,QAAQ;IAC5B,QAAQ,qBAAqB;IAC7B,SAAS,QAAQ;IACjB,OAAO,qBAAqB;IAC5B,cAAc,QAAQ;IACtB,YAAY;IACb,CAAC;GACF,eAAe,qBAAqB,MAAM;SACrC;GACL,MAAM,gBAAgB,QAAQ,qBAAqB,QAAQ,eAAe,KAAK;GAC/E,UAAU,QAAQ,sBAAsB,cAAc;;EAGxD,MAAM,gBAAgB,QAAQ,wBAC5B,QAAQ,SACR,QAAQ,eACR,aACD;EACD,MAAM,YAAY,MAAM,QAAQ,uBAC9B;GAAE,MAAM;GAAS;GAAa,EAC9B;GAAE;GAAqB,SAAS;GAAe,CAChD;EAED,MAAM,gBAAgB,IAAI,QAAQ;GAChC,gBAAgB;GAChB,MAAM;GACP,CAAC;EACF,+BAA+B,eAAe,QAAQ,kBAAkB;EACxE,2BAA2B,eAAe,uBAAuB;EACjE,MAAM,iBAAiB,IAAI,SAAS,WAAW;GAC7C,QAAQ,QAAQ,oBAAoB;GACpC,SAAS;GACV,CAAC;EACF,IAAI,qBAAqB,SAAS,KAAK,mBAAmB;GACxD,KAAK,MAAM,UAAU,sBACnB,eAAe,QAAQ,OAAO,cAAc,OAAO;GAErD,IAAI,mBAAmB,eAAe,QAAQ,OAAO,cAAc,kBAAkB;;EAEvF,OAAO;UACA,OAAO;EACd,mCAAmC;EACnC,OAAO,gCAAgC,OAAO;GAC5C,eAAe,QAAQ;GACvB,qBAAqB,QAAQ;GAC7B,2BAA2B,QAAQ;GACnC,oBAAoB,QAAQ;GAC5B,SAAS,QAAQ;GAClB,CAAC"}
1
+ {"version":3,"file":"app-server-action-execution.js","names":[],"sources":["../../src/server/app-server-action-execution.ts"],"sourcesContent":["import { getAndClearActionRevalidationKind, type ActionRevalidationKind } from \"vinext/shims/cache\";\nimport type { HeadersAccessPhase } from \"vinext/shims/headers\";\nimport { type FetchCacheMode, setCurrentFetchCacheMode } from \"vinext/shims/fetch-cache\";\nimport type { ReactFormState } from \"react-dom/client\";\nimport { isExternalUrl } from \"../config/config-matchers.js\";\nimport { addBasePathToPathname, hasBasePath } from \"../utils/base-path.js\";\nimport {\n ACTION_FORWARDED_HEADER,\n ACTION_REDIRECT_HEADER,\n ACTION_REDIRECT_STATUS_HEADER,\n ACTION_REDIRECT_TYPE_HEADER,\n ACTION_REVALIDATED_HEADER,\n} from \"./headers.js\";\nimport {\n VINEXT_RSC_CONTENT_TYPE,\n VINEXT_RSC_VARY_HEADER,\n applyRscCompatibilityIdHeader,\n} from \"./app-rsc-cache-busting.js\";\nimport { resolveAppPageActionRerenderTarget } from \"./app-page-request.js\";\nimport { mergeMiddlewareResponseHeaders } from \"./middleware-response-headers.js\";\nimport {\n APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI,\n type AppRscRenderMode,\n} from \"./app-rsc-render-mode.js\";\nimport {\n getNextErrorDigest,\n parseNextHttpErrorDigest,\n parseNextRedirectDigest,\n} from \"./next-error-digest.js\";\nimport { validateCsrfOrigin, validateServerActionPayload } from \"./request-pipeline.js\";\nimport { readStreamAsTextWithLimit } from \"../utils/text-stream.js\";\nimport {\n createServerActionNotFoundResponse,\n getServerActionNotFoundMessage,\n isServerActionNotFoundError,\n} from \"./server-action-not-found.js\";\nimport { internalServerErrorResponse, payloadTooLargeResponse } from \"./http-error-responses.js\";\n\ntype AppPageParams = Record<string, string | string[]>;\n\ntype AppServerActionErrorReporter = (\n error: Error,\n request: { path: string; method: string; headers: Record<string, string> },\n route: { routerKind: \"App Router\"; routePath: string; routeType: \"action\" },\n) => void;\n\ntype AppServerActionDecoder = (body: FormData) => Promise<unknown>;\ntype AppServerActionFormStateDecoder = (\n actionResult: unknown,\n body: FormData,\n) => Promise<ReactFormState | undefined>;\n\ntype ReadFormDataWithLimit = (request: Request, maxBytes: number) => Promise<FormData>;\n\ntype ReadBodyWithLimit = (request: Request, maxBytes: number) => Promise<string>;\n\ntype AppServerActionFunction = (...args: unknown[]) => unknown;\n\ntype AppServerActionReturnValue =\n | {\n data: unknown;\n ok: true;\n }\n | {\n data: unknown;\n ok: false;\n };\n\ntype AppServerActionRedirect = {\n status: number;\n type: string;\n url: string;\n};\n\ntype AppServerActionRoute = {\n pattern: string;\n};\n\ntype ProgressiveServerActionResult =\n | {\n formState: ReactFormState | null;\n kind: \"form-state\";\n }\n | {\n actionError: unknown;\n actionFailed: true;\n formState: null;\n kind: \"form-state\";\n };\n\ntype AppServerActionMatch<TRoute extends AppServerActionRoute> = {\n params: AppPageParams;\n route: TRoute;\n};\n\ntype AppServerActionIntercept<TPage = unknown> = {\n matchedParams: AppPageParams;\n page: TPage;\n slotId?: string | null;\n slotKey: string;\n sourceRouteIndex: number;\n};\n\ntype BuildServerActionPageElementOptions<TRoute extends AppServerActionRoute, TInterceptOpts> = {\n cleanPathname: string;\n interceptOpts: TInterceptOpts | undefined;\n isRscRequest: boolean;\n mountedSlotsHeader: string | null;\n params: AppPageParams;\n request: Request;\n route: TRoute;\n searchParams: URLSearchParams;\n renderMode: AppRscRenderMode;\n};\n\ntype AppServerActionRscModel<TElement> = {\n /**\n * Omitted when the action did not invalidate page data. This mirrors Next.js'\n * empty Flight payload for non-revalidating fetch actions: the client resolves\n * the action value without committing a visible router update.\n */\n root?: TElement;\n returnValue: AppServerActionReturnValue;\n};\n\ntype RenderServerActionRscStreamOptions<TTemporaryReferences> = {\n onError: (error: unknown) => unknown;\n temporaryReferences: TTemporaryReferences;\n};\n\ntype DecodeServerActionReplyOptions<TTemporaryReferences> = {\n temporaryReferences: TTemporaryReferences;\n};\n\nexport type HandleProgressiveServerActionRequestOptions = {\n actionId: string | null;\n allowedOrigins: string[];\n /** Configured next.config `basePath`. Prefixed onto progressive Location targets. */\n basePath?: string;\n cleanPathname: string;\n clearRequestContext: () => void;\n contentType: string;\n decodeAction: AppServerActionDecoder;\n decodeFormState: AppServerActionFormStateDecoder;\n getAndClearPendingCookies: () => string[];\n getDraftModeCookieHeader: () => string | null | undefined;\n maxActionBodySize: number;\n middlewareHeaders: Headers | null;\n readFormDataWithLimit: ReadFormDataWithLimit;\n reportRequestError: AppServerActionErrorReporter;\n request: Request;\n setHeadersAccessPhase: (phase: HeadersAccessPhase) => HeadersAccessPhase;\n};\n\nexport type HandleServerActionRscRequestOptions<\n TElement,\n TRoute extends AppServerActionRoute,\n TInterceptOpts,\n TTemporaryReferences,\n TPage = unknown,\n> = {\n actionId: string | null;\n allowedOrigins: string[];\n /** Configured next.config `basePath`. Prefixed onto ACTION_REDIRECT_HEADER targets. */\n basePath?: string;\n buildPageElement: (\n options: BuildServerActionPageElementOptions<TRoute, TInterceptOpts>,\n ) => TElement;\n cleanPathname: string;\n clearRequestContext: () => void;\n contentType: string;\n createNotFoundElement: (routeId: string) => TElement;\n createPayloadRouteId: (pathname: string, interceptionContext: string | null) => string;\n createRscOnErrorHandler: (\n request: Request,\n pathname: string,\n pattern: string,\n ) => (error: unknown) => unknown;\n createTemporaryReferenceSet: () => TTemporaryReferences;\n decodeReply: (\n body: string | FormData,\n options: DecodeServerActionReplyOptions<TTemporaryReferences>,\n ) => Promise<unknown[]> | unknown[];\n findIntercept: (pathname: string) => AppServerActionIntercept<TPage> | null;\n getAndClearPendingCookies: () => string[];\n getDraftModeCookieHeader: () => string | null | undefined;\n getRouteParamNames: (route: TRoute) => readonly string[];\n getSourceRoute: (sourceRouteIndex: number) => TRoute | undefined;\n isRscRequest: boolean;\n loadServerAction: (actionId: string) => Promise<unknown>;\n matchRoute: (pathname: string) => AppServerActionMatch<TRoute> | null;\n maxActionBodySize: number;\n middlewareHeaders: Headers | null;\n middlewareStatus: number | null | undefined;\n mountedSlotsHeader: string | null;\n readBodyWithLimit: ReadBodyWithLimit;\n readFormDataWithLimit: ReadFormDataWithLimit;\n renderToReadableStream: (\n model: AppServerActionRscModel<TElement>,\n options: RenderServerActionRscStreamOptions<TTemporaryReferences>,\n ) => BodyInit | null | Promise<BodyInit | null>;\n reportRequestError: AppServerActionErrorReporter;\n resolveRouteFetchCacheMode?: (route: TRoute) => FetchCacheMode | null;\n request: Request;\n sanitizeErrorForClient: (error: unknown) => unknown;\n searchParams: URLSearchParams;\n setHeadersAccessPhase: (phase: HeadersAccessPhase) => HeadersAccessPhase;\n setNavigationContext: (context: {\n params: AppPageParams;\n pathname: string;\n searchParams: URLSearchParams;\n }) => void;\n toInterceptOpts: (intercept: AppServerActionIntercept<TPage>) => TInterceptOpts;\n};\n\n/**\n * Matches Next.js' server action argument cap to prevent stack overflow in\n * Function.prototype.apply when decoding hostile action payloads.\n */\nconst SERVER_ACTION_ARGS_LIMIT = 1000;\nconst ACTION_DID_NOT_REVALIDATE = 0 satisfies ActionRevalidationKind;\nconst ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC = 1 satisfies ActionRevalidationKind;\n\nfunction setActionRevalidatedHeader(headers: Headers, kind: ActionRevalidationKind): void {\n if (kind === ACTION_DID_NOT_REVALIDATE) return;\n headers.set(ACTION_REVALIDATED_HEADER, JSON.stringify(kind));\n}\n\nfunction resolveActionRevalidationKind(hasModifiedCookies: boolean): ActionRevalidationKind {\n const revalidationKind = getAndClearActionRevalidationKind();\n // Cookie mutations are a hard override to STATIC_AND_DYNAMIC: any cookie\n // change can invalidate downstream cached payloads regardless of what\n // (if anything) the action explicitly revalidated, so we always emit the\n // strongest kind. STATIC_AND_DYNAMIC is also the lowest numeric value, so\n // this matches the max-precedence semantics in markActionRevalidation.\n if (hasModifiedCookies) return ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC;\n return revalidationKind;\n}\n\nfunction isRequestBodyTooLarge(error: unknown): boolean {\n return error instanceof Error && error.message === \"Request body too large\";\n}\n\nfunction isAppServerActionFunction(action: unknown): action is AppServerActionFunction {\n return typeof action === \"function\";\n}\n\nfunction normalizeError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n\nfunction getServerActionFailureMessage(error: unknown): string {\n return error instanceof Error && error.message ? error.message : String(error);\n}\n\nfunction validateServerActionArgs(args: readonly unknown[]): void {\n if (args.length > SERVER_ACTION_ARGS_LIMIT) {\n throw new Error(\n `Server Action arguments list is too long (${args.length}). Maximum allowed is ${SERVER_ACTION_ARGS_LIMIT}.`,\n );\n }\n}\n\nexport async function readActionBodyWithLimit(request: Request, maxBytes: number): Promise<string> {\n if (!request.body) return \"\";\n return readStreamAsTextWithLimit(request.body, maxBytes, () => {\n throw new Error(\"Request body too large\");\n });\n}\n\nexport async function readActionFormDataWithLimit(\n request: Request,\n maxBytes: number,\n): Promise<FormData> {\n if (!request.body) return new FormData();\n\n const reader = request.body.getReader();\n const chunks: Uint8Array[] = [];\n let totalSize = 0;\n\n for (;;) {\n const result = await reader.read();\n if (result.done) break;\n\n totalSize += result.value.byteLength;\n if (totalSize > maxBytes) {\n await reader.cancel();\n throw new Error(\"Request body too large\");\n }\n chunks.push(result.value);\n }\n\n const combined = new Uint8Array(totalSize);\n let offset = 0;\n for (const chunk of chunks) {\n combined.set(chunk, offset);\n offset += chunk.byteLength;\n }\n\n return new Response(combined, {\n headers: { \"Content-Type\": request.headers.get(\"content-type\") || \"\" },\n }).formData();\n}\n\nfunction getActionRedirect(error: unknown): AppServerActionRedirect | null {\n const digest = getNextErrorDigest(error);\n if (!digest) return null;\n\n const redirect = parseNextRedirectDigest(digest);\n if (!redirect) return null;\n\n return {\n status: redirect.status,\n type: redirect.type ?? \"push\",\n url: redirect.url,\n };\n}\n\n/**\n * Prepend the configured next.config `basePath` to a server-action redirect\n * target before it goes on the wire.\n *\n * `redirect(\"/foo\")` called from a server action mounted at `/base/...` must\n * land the browser at `/base/foo`, mirroring how Next.js threads basePath\n * through `addPathPrefix(getURLFromRedirectError(err), basePath)` in\n * `app-render.tsx` for SSR redirects and in `action-handler.ts` for action\n * redirects.\n *\n * Idempotent and external-aware:\n * - Empty basePath → returned unchanged.\n * - External URLs (`http://`, `https://`, `data:`, protocol-relative `//`)\n * are returned unchanged because the framework does not own those routes.\n * - Targets that already start with the configured basePath are returned\n * unchanged so this helper can be applied at any layer without risk of\n * double-prefixing (`/base/base/foo`).\n *\n * Exported for tests. Used by both the progressive (no-JS form POST) and\n * RSC (`ACTION_REDIRECT_HEADER`) action redirect paths below.\n *\n * @see https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/action-handler.ts\n */\nexport function applyActionRedirectBasePath(url: string, basePath: string): string {\n if (!basePath) return url;\n if (isExternalUrl(url)) return url;\n // Pathnames that already include basePath are returned as-is.\n if (hasBasePath(url, basePath)) return url;\n // Relative or hash/query-only targets cannot be prefixed safely without an\n // origin; leave them to the caller's URL resolution.\n if (!url.startsWith(\"/\")) return url;\n // Split off optional query+hash so addBasePathToPathname only operates on\n // the path. We must accept hash too because Next.js redirect targets may\n // contain \"#anchor\".\n const queryIndex = url.indexOf(\"?\");\n const hashIndex = url.indexOf(\"#\");\n const splitAt =\n queryIndex === -1 ? hashIndex : hashIndex === -1 ? queryIndex : Math.min(queryIndex, hashIndex);\n const pathname = splitAt === -1 ? url : url.slice(0, splitAt);\n const suffix = splitAt === -1 ? \"\" : url.slice(splitAt);\n return `${addBasePathToPathname(pathname, basePath)}${suffix}`;\n}\n\nfunction getActionHttpFallbackStatus(error: unknown): number | null {\n const digest = getNextErrorDigest(error);\n if (!digest) return null;\n\n const httpError = parseNextHttpErrorDigest(digest);\n if (!httpError || !Number.isInteger(httpError.status)) return null;\n\n return httpError.status;\n}\n\nfunction createServerActionErrorResponse(\n error: unknown,\n options: {\n cleanPathname: string;\n clearRequestContext: () => void;\n getAndClearPendingCookies: () => string[];\n reportRequestError: AppServerActionErrorReporter;\n request: Request;\n },\n): Response {\n options.getAndClearPendingCookies();\n console.error(\"[vinext] Server action error:\", error);\n options.reportRequestError(\n normalizeError(error),\n {\n path: options.cleanPathname,\n method: options.request.method,\n headers: Object.fromEntries(options.request.headers.entries()),\n },\n { routerKind: \"App Router\", routePath: options.cleanPathname, routeType: \"action\" },\n );\n options.clearRequestContext();\n return internalServerErrorResponse(\n process.env.NODE_ENV === \"production\"\n ? undefined\n : \"Server action failed: \" + getServerActionFailureMessage(error),\n );\n}\n\nfunction createActionNotFoundResponse(\n actionId: string | null,\n options: {\n clearRequestContext: () => void;\n getAndClearPendingCookies: () => string[];\n },\n): Response {\n options.getAndClearPendingCookies();\n console.warn(getServerActionNotFoundMessage(actionId));\n options.clearRequestContext();\n return createServerActionNotFoundResponse();\n}\n\nexport function isProgressiveServerActionRequest(\n request: Pick<Request, \"method\">,\n contentType: string,\n actionId: string | null,\n): boolean {\n return (\n request.method.toUpperCase() === \"POST\" &&\n contentType.startsWith(\"multipart/form-data\") &&\n !actionId\n );\n}\n\nexport async function handleProgressiveServerActionRequest(\n options: HandleProgressiveServerActionRequestOptions,\n): Promise<Response | ProgressiveServerActionResult | null> {\n if (!isProgressiveServerActionRequest(options.request, options.contentType, options.actionId)) {\n return null;\n }\n\n // Defensive guard: prevent infinite forwarding loops. See handleServerActionRscRequest.\n if (options.request.headers.get(ACTION_FORWARDED_HEADER)) {\n return createActionNotFoundResponse(null, {\n clearRequestContext: options.clearRequestContext,\n getAndClearPendingCookies: options.getAndClearPendingCookies,\n });\n }\n\n const csrfResponse = validateCsrfOrigin(options.request, options.allowedOrigins);\n if (csrfResponse) {\n return csrfResponse;\n }\n\n const contentLength = parseInt(options.request.headers.get(\"content-length\") || \"0\", 10);\n if (contentLength > options.maxActionBodySize) {\n options.clearRequestContext();\n return payloadTooLargeResponse();\n }\n\n try {\n let body: FormData;\n try {\n // Progressive submissions can still fall through to a regular page render when\n // the multipart body is not an action payload. Read a clone so that fallback\n // code can still consume the original request body.\n body = await options.readFormDataWithLimit(\n options.request.clone(),\n options.maxActionBodySize,\n );\n } catch (error) {\n if (isRequestBodyTooLarge(error)) {\n options.clearRequestContext();\n return payloadTooLargeResponse();\n }\n throw error;\n }\n\n const payloadResponse = await validateServerActionPayload(body);\n if (payloadResponse) {\n options.clearRequestContext();\n return payloadResponse;\n }\n\n const action = await options.decodeAction(body);\n if (!isAppServerActionFunction(action)) {\n return null;\n }\n\n let actionRedirect: AppServerActionRedirect | null = null;\n let actionError: unknown = undefined;\n let actionFailed = false;\n let actionResult: unknown;\n const previousHeadersPhase = options.setHeadersAccessPhase(\"action\");\n try {\n actionResult = await action();\n } catch (error) {\n actionRedirect = getActionRedirect(error);\n if (!actionRedirect) {\n actionError = error;\n actionFailed = true;\n const isControlFlow =\n getActionHttpFallbackStatus(error) !== null || isServerActionNotFoundError(error, null);\n if (!isControlFlow) {\n console.error(\"[vinext] Server action error:\", error);\n options.reportRequestError(\n normalizeError(error),\n {\n path: options.cleanPathname,\n method: options.request.method,\n headers: Object.fromEntries(options.request.headers.entries()),\n },\n { routerKind: \"App Router\", routePath: options.cleanPathname, routeType: \"action\" },\n );\n }\n }\n } finally {\n options.setHeadersAccessPhase(previousHeadersPhase);\n }\n\n if (!actionRedirect) {\n getAndClearActionRevalidationKind();\n if (actionFailed) {\n return { kind: \"form-state\", formState: null, actionError, actionFailed };\n }\n\n const formState = await options.decodeFormState(actionResult, body);\n return { kind: \"form-state\", formState: formState ?? null };\n }\n\n const actionPendingCookies = options.getAndClearPendingCookies();\n const actionDraftCookie = options.getDraftModeCookieHeader();\n const actionRevalidationKind = resolveActionRevalidationKind(\n actionPendingCookies.length > 0 || Boolean(actionDraftCookie),\n );\n options.clearRequestContext();\n\n const headers = new Headers();\n // Prefix the configured basePath onto the redirect target before it\n // becomes an absolute Location URL. Mirrors Next.js, which threads\n // basePath through `addPathPrefix(...)` for server-action redirects.\n const prefixedRedirectUrl = applyActionRedirectBasePath(\n actionRedirect.url,\n options.basePath ?? \"\",\n );\n headers.set(\"Location\", new URL(prefixedRedirectUrl, options.request.url).toString());\n mergeMiddlewareResponseHeaders(headers, options.middlewareHeaders);\n for (const cookie of actionPendingCookies) {\n headers.append(\"Set-Cookie\", cookie);\n }\n if (actionDraftCookie) {\n headers.append(\"Set-Cookie\", actionDraftCookie);\n }\n setActionRevalidatedHeader(headers, actionRevalidationKind);\n\n return new Response(null, {\n status: 303,\n headers,\n });\n } catch (error) {\n if (isServerActionNotFoundError(error, null)) {\n return createActionNotFoundResponse(null, {\n clearRequestContext: options.clearRequestContext,\n getAndClearPendingCookies: options.getAndClearPendingCookies,\n });\n }\n\n getAndClearActionRevalidationKind();\n options.getAndClearPendingCookies();\n console.error(\"[vinext] Server action payload parsing error:\", error);\n options.reportRequestError(\n normalizeError(error),\n {\n path: options.cleanPathname,\n method: options.request.method,\n headers: Object.fromEntries(options.request.headers.entries()),\n },\n { routerKind: \"App Router\", routePath: options.cleanPathname, routeType: \"action\" },\n );\n options.clearRequestContext();\n return internalServerErrorResponse(\n process.env.NODE_ENV === \"production\"\n ? undefined\n : \"Server action parsing failed: \" + getServerActionFailureMessage(error),\n );\n }\n}\n\nexport async function handleServerActionRscRequest<\n TElement,\n TRoute extends AppServerActionRoute,\n TInterceptOpts,\n TTemporaryReferences,\n TPage = unknown,\n>(\n options: HandleServerActionRscRequestOptions<\n TElement,\n TRoute,\n TInterceptOpts,\n TTemporaryReferences,\n TPage\n >,\n): Promise<Response | null> {\n if (options.request.method.toUpperCase() !== \"POST\" || !options.actionId) {\n return null;\n }\n\n // Defensive guard: if this request has already been forwarded between workers,\n // do not attempt to process it again. Prevents infinite forwarding loops when\n // middleware rewrites action POSTs. Matches Next.js behavior:\n // https://github.com/vercel/next.js/commit/20892dd44e1321c13f755f051e48c3cadd75204b\n if (options.request.headers.get(ACTION_FORWARDED_HEADER)) {\n return createActionNotFoundResponse(options.actionId, {\n clearRequestContext: options.clearRequestContext,\n getAndClearPendingCookies: options.getAndClearPendingCookies,\n });\n }\n\n const csrfResponse = validateCsrfOrigin(options.request, options.allowedOrigins);\n if (csrfResponse) return csrfResponse;\n\n const contentLength = parseInt(options.request.headers.get(\"content-length\") || \"0\", 10);\n if (contentLength > options.maxActionBodySize) {\n options.clearRequestContext();\n return payloadTooLargeResponse();\n }\n\n try {\n let body: string | FormData;\n try {\n body = options.contentType.startsWith(\"multipart/form-data\")\n ? await options.readFormDataWithLimit(options.request, options.maxActionBodySize)\n : await options.readBodyWithLimit(options.request, options.maxActionBodySize);\n } catch (error) {\n if (isRequestBodyTooLarge(error)) {\n options.clearRequestContext();\n return payloadTooLargeResponse();\n }\n throw error;\n }\n\n const payloadResponse = await validateServerActionPayload(body);\n if (payloadResponse) {\n options.clearRequestContext();\n return payloadResponse;\n }\n\n let action: unknown;\n try {\n action = await options.loadServerAction(options.actionId);\n } catch (error) {\n if (isServerActionNotFoundError(error, options.actionId)) {\n return createActionNotFoundResponse(options.actionId, {\n clearRequestContext: options.clearRequestContext,\n getAndClearPendingCookies: options.getAndClearPendingCookies,\n });\n }\n\n throw error;\n }\n\n if (!isAppServerActionFunction(action)) {\n return createActionNotFoundResponse(options.actionId, {\n clearRequestContext: options.clearRequestContext,\n getAndClearPendingCookies: options.getAndClearPendingCookies,\n });\n }\n\n const temporaryReferences = options.createTemporaryReferenceSet();\n const args = await options.decodeReply(body, { temporaryReferences });\n let returnValue: AppServerActionReturnValue;\n let actionRedirect: AppServerActionRedirect | null = null;\n let actionStatus = 200;\n const previousHeadersPhase = options.setHeadersAccessPhase(\"action\");\n try {\n try {\n validateServerActionArgs(args);\n const data = await action.apply(null, args);\n returnValue = { ok: true, data };\n } catch (error) {\n actionRedirect = getActionRedirect(error);\n if (actionRedirect) {\n returnValue = { ok: true, data: undefined };\n } else {\n const httpFallbackStatus = getActionHttpFallbackStatus(error);\n if (httpFallbackStatus !== null) {\n actionStatus = httpFallbackStatus;\n returnValue = { ok: false, data: error };\n } else {\n console.error(\"[vinext] Server action error:\", error);\n returnValue = { ok: false, data: options.sanitizeErrorForClient(error) };\n }\n }\n }\n } finally {\n options.setHeadersAccessPhase(previousHeadersPhase);\n }\n\n if (actionRedirect) {\n const actionPendingCookies = options.getAndClearPendingCookies();\n const actionDraftCookie = options.getDraftModeCookieHeader();\n const actionRevalidationKind = resolveActionRevalidationKind(\n actionPendingCookies.length > 0 || Boolean(actionDraftCookie),\n );\n options.clearRequestContext();\n const redirectHeaders = new Headers({\n \"Content-Type\": VINEXT_RSC_CONTENT_TYPE,\n Vary: VINEXT_RSC_VARY_HEADER,\n });\n mergeMiddlewareResponseHeaders(redirectHeaders, options.middlewareHeaders);\n applyRscCompatibilityIdHeader(redirectHeaders);\n // Prefix basePath onto the redirect target. The client-side handler in\n // app-browser-entry reads ACTION_REDIRECT_HEADER and calls\n // window.location.assign/replace verbatim, so the value must already\n // be a basePath-prefixed URL.\n redirectHeaders.set(\n ACTION_REDIRECT_HEADER,\n applyActionRedirectBasePath(actionRedirect.url, options.basePath ?? \"\"),\n );\n redirectHeaders.set(ACTION_REDIRECT_TYPE_HEADER, actionRedirect.type);\n redirectHeaders.set(ACTION_REDIRECT_STATUS_HEADER, String(actionRedirect.status));\n for (const cookie of actionPendingCookies) {\n redirectHeaders.append(\"Set-Cookie\", cookie);\n }\n if (actionDraftCookie) redirectHeaders.append(\"Set-Cookie\", actionDraftCookie);\n setActionRevalidatedHeader(redirectHeaders, actionRevalidationKind);\n return new Response(\"\", { status: 200, headers: redirectHeaders });\n }\n\n const actionPendingCookies = options.getAndClearPendingCookies();\n const actionDraftCookie = options.getDraftModeCookieHeader();\n const actionRevalidationKind = resolveActionRevalidationKind(\n actionPendingCookies.length > 0 || Boolean(actionDraftCookie),\n );\n\n const shouldSkipPageRendering = actionRevalidationKind === ACTION_DID_NOT_REVALIDATE;\n if (shouldSkipPageRendering) {\n const onRenderError = options.createRscOnErrorHandler(\n options.request,\n options.cleanPathname,\n options.cleanPathname,\n );\n const rscStream = await options.renderToReadableStream(\n { returnValue },\n { temporaryReferences, onError: onRenderError },\n );\n\n options.clearRequestContext();\n\n const actionHeaders = new Headers({\n \"Content-Type\": VINEXT_RSC_CONTENT_TYPE,\n Vary: VINEXT_RSC_VARY_HEADER,\n });\n mergeMiddlewareResponseHeaders(actionHeaders, options.middlewareHeaders);\n applyRscCompatibilityIdHeader(actionHeaders);\n\n return new Response(rscStream, {\n status: options.middlewareStatus ?? actionStatus,\n headers: actionHeaders,\n });\n }\n\n const match = options.matchRoute(options.cleanPathname);\n let element: TElement;\n let errorPattern = match ? match.route.pattern : options.cleanPathname;\n if (match) {\n const { route: actionRoute, params: actionParams } = match;\n const actionRerenderTarget = resolveAppPageActionRerenderTarget({\n cleanPathname: options.cleanPathname,\n currentParams: actionParams,\n currentRoute: actionRoute,\n findIntercept: options.findIntercept,\n getRouteParamNames: options.getRouteParamNames,\n getSourceRoute: options.getSourceRoute,\n isRscRequest: options.isRscRequest,\n toInterceptOpts: options.toInterceptOpts,\n });\n\n options.setNavigationContext({\n pathname: options.cleanPathname,\n searchParams: options.searchParams,\n params: actionRerenderTarget.navigationParams,\n });\n setCurrentFetchCacheMode(\n options.resolveRouteFetchCacheMode?.(actionRerenderTarget.route) ?? null,\n );\n element = options.buildPageElement({\n cleanPathname: options.cleanPathname,\n interceptOpts: actionRerenderTarget.interceptOpts,\n isRscRequest: options.isRscRequest,\n mountedSlotsHeader: options.mountedSlotsHeader,\n params: actionRerenderTarget.params,\n request: options.request,\n route: actionRerenderTarget.route,\n searchParams: options.searchParams,\n renderMode: APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI,\n });\n errorPattern = actionRerenderTarget.route.pattern;\n } else {\n const actionRouteId = options.createPayloadRouteId(options.cleanPathname, null);\n element = options.createNotFoundElement(actionRouteId);\n }\n\n const onRenderError = options.createRscOnErrorHandler(\n options.request,\n options.cleanPathname,\n errorPattern,\n );\n const rscStream = await options.renderToReadableStream(\n { root: element, returnValue },\n { temporaryReferences, onError: onRenderError },\n );\n\n const actionHeaders = new Headers({\n \"Content-Type\": VINEXT_RSC_CONTENT_TYPE,\n Vary: VINEXT_RSC_VARY_HEADER,\n });\n mergeMiddlewareResponseHeaders(actionHeaders, options.middlewareHeaders);\n applyRscCompatibilityIdHeader(actionHeaders);\n setActionRevalidatedHeader(actionHeaders, actionRevalidationKind);\n const actionResponse = new Response(rscStream, {\n status: options.middlewareStatus ?? actionStatus,\n headers: actionHeaders,\n });\n if (actionPendingCookies.length > 0 || actionDraftCookie) {\n for (const cookie of actionPendingCookies) {\n actionResponse.headers.append(\"Set-Cookie\", cookie);\n }\n if (actionDraftCookie) actionResponse.headers.append(\"Set-Cookie\", actionDraftCookie);\n }\n return actionResponse;\n } catch (error) {\n getAndClearActionRevalidationKind();\n return createServerActionErrorResponse(error, {\n cleanPathname: options.cleanPathname,\n clearRequestContext: options.clearRequestContext,\n getAndClearPendingCookies: options.getAndClearPendingCookies,\n reportRequestError: options.reportRequestError,\n request: options.request,\n });\n }\n}\n"],"mappings":"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"}
@@ -21,6 +21,7 @@ declare function handleSsr(rscStream: ReadableStream<Uint8Array>, navContext: Na
21
21
  value: Promise<ArrayBuffer> | null;
22
22
  };
23
23
  formState?: ReactFormState | null;
24
+ basePath?: string;
24
25
  /** When true, wait for the full React tree (including Suspense boundaries)
25
26
  * to resolve before returning the HTML stream. Used for static prerender
26
27
  * and ISR cache writes to avoid caching fallback content. */
@@ -1,8 +1,10 @@
1
+ import "./server-globals.js";
1
2
  import { notFoundResponse } from "./http-error-responses.js";
2
3
  import { isOpenRedirectShaped } from "./request-pipeline.js";
3
4
  import { AppElementsWire } from "./app-elements-wire.js";
4
5
  import "./app-elements.js";
5
- import { ServerInsertedHTMLContext, clearServerInsertedHTML, renderServerInsertedHTML, setNavigationContext, useServerInsertedHTML } from "../shims/navigation.js";
6
+ import { AppRouterContext } from "../shims/internal/app-router-context.js";
7
+ import { ServerInsertedHTMLContext, appRouterInstance, clearServerInsertedHTML, renderServerInsertedHTML, setNavigationContext, useServerInsertedHTML } from "../shims/navigation.js";
6
8
  import { runWithNavigationContext } from "../shims/navigation-state.js";
7
9
  import { withScriptNonce } from "../shims/script-nonce-context.js";
8
10
  import { createInlineScriptTag, createNonceAttribute, escapeHtmlAttr, safeJsonStringify } from "./html.js";
@@ -11,6 +13,7 @@ import { RSC_FORM_STATE_GLOBAL } from "./app-browser-hydration.js";
11
13
  import { createClientReferencePreloader } from "./app-client-reference-preloader.js";
12
14
  import { deferUntilStreamConsumed } from "./app-page-stream.js";
13
15
  import { createRscEmbedTransform, createTickBufferedTransform } from "./app-ssr-stream.js";
16
+ import { createSsrErrorMetaRenderer } from "./app-ssr-error-meta.js";
14
17
  import { Fragment, createElement, use } from "react";
15
18
  import { renderToReadableStream, renderToStaticMarkup } from "react-dom/server.edge";
16
19
  import { createFromReadableStream } from "@vitejs/plugin-rsc/ssr";
@@ -53,20 +56,37 @@ function renderFontHtml(fontData, nonce) {
53
56
  if (fontData.styles && fontData.styles.length > 0) fontHTML += `<style data-vinext-fonts${nonceAttr}>${fontData.styles.join("\n")}</style>\n`;
54
57
  return fontHTML;
55
58
  }
56
- function extractModulePreloadHtml(bootstrapScriptContent, nonce) {
57
- if (!bootstrapScriptContent) return "";
58
- const match = bootstrapScriptContent.match(/import\("([^"]+)"\)/);
59
- if (!match?.[1]) return "";
60
- return `<link rel="modulepreload"${createNonceAttribute(nonce)} href="${escapeHtmlAttr(match[1])}" />\n`;
59
+ /**
60
+ * Extract the bootstrap module URL from the `import("...")` string that
61
+ * `import.meta.viteRsc.loadBootstrapScriptContent("index")` returns.
62
+ *
63
+ * The plugin-rsc helper returns the bootstrap as an inline call so we can
64
+ * inject it via `bootstrapScriptContent`. We instead pass the URL to
65
+ * React's `bootstrapModules` option so a real
66
+ * `<script type="module" src="…">` tag ends up in the streamed HTML —
67
+ * this exposes the URL to anything that reads `script.attribs.src` (e.g.
68
+ * the Next.js asset-prefix fixture test). The same URL also feeds the
69
+ * `<link rel="modulepreload">` we emit ahead of the bootstrap.
70
+ *
71
+ * Returns `undefined` when the helper produced no URL (older plugin-rsc
72
+ * versions, or a custom client entry that disables bootstrap content).
73
+ */
74
+ function extractBootstrapModuleUrl(bootstrapScriptContent) {
75
+ if (!bootstrapScriptContent) return void 0;
76
+ return bootstrapScriptContent.match(/import\(["']([^"']+)["']\)/)?.[1] ?? void 0;
61
77
  }
62
- function buildHeadInjectionHtml(navContext, bootstrapScriptContent, formState, insertedHTML, fontHTML, scriptNonce) {
78
+ function buildModulePreloadHtml(bootstrapModuleUrl, nonce) {
79
+ if (!bootstrapModuleUrl) return "";
80
+ return `<link rel="modulepreload"${createNonceAttribute(nonce)} href="${escapeHtmlAttr(bootstrapModuleUrl)}" />\n`;
81
+ }
82
+ function buildHeadInjectionHtml(navContext, bootstrapModuleUrl, formState, insertedHTML, fontHTML, scriptNonce) {
63
83
  const paramsScript = createInlineScriptTag("self.__VINEXT_RSC_PARAMS__=" + safeJsonStringify(navContext?.params ?? {}), scriptNonce);
64
84
  const navScript = createInlineScriptTag("self.__VINEXT_RSC_NAV__=" + safeJsonStringify({
65
85
  pathname: navContext?.pathname ?? "/",
66
86
  searchParams: navContext?.searchParams ? [...navContext.searchParams.entries()] : []
67
87
  }), scriptNonce);
68
88
  const formStateScript = formState === null ? "" : createInlineScriptTag("self[" + safeJsonStringify(RSC_FORM_STATE_GLOBAL) + "]=" + safeJsonStringify(formState), scriptNonce);
69
- return paramsScript + navScript + formStateScript + extractModulePreloadHtml(bootstrapScriptContent, scriptNonce) + insertedHTML + fontHTML;
89
+ return paramsScript + navScript + formStateScript + buildModulePreloadHtml(bootstrapModuleUrl, scriptNonce) + insertedHTML + fontHTML;
70
90
  }
71
91
  async function handleSsr(rscStream, navContext, fontData, options) {
72
92
  return runWithNavigationContext(async () => {
@@ -97,14 +117,17 @@ async function handleSsr(rscStream, navContext, fontData, options) {
97
117
  const metadata = AppElementsWire.readMetadata(elements);
98
118
  return createElement(ElementsContext.Provider, { value: elements }, createElement(Slot, { id: metadata.routeId }));
99
119
  }
100
- const root = createElement(VinextFlightRoot);
120
+ const flightRootElement = createElement(VinextFlightRoot);
121
+ const root = AppRouterContext ? createElement(AppRouterContext.Provider, { value: appRouterInstance }, flightRootElement) : flightRootElement;
101
122
  const ssrRoot = withScriptNonce(ServerInsertedHTMLContext ? createElement(ServerInsertedHTMLContext.Provider, { value: useServerInsertedHTML }, root) : root, options?.scriptNonce);
102
- const bootstrapScriptContent = await import.meta.viteRsc.loadBootstrapScriptContent("index");
123
+ const bootstrapModuleUrl = extractBootstrapModuleUrl(await import.meta.viteRsc.loadBootstrapScriptContent("index"));
124
+ const errorMetaRenderer = createSsrErrorMetaRenderer({ basePath: options?.basePath });
103
125
  const htmlStream = await renderToReadableStream(ssrRoot, {
104
- bootstrapScriptContent,
126
+ bootstrapModules: bootstrapModuleUrl ? [bootstrapModuleUrl] : void 0,
105
127
  formState: options?.formState ?? null,
106
128
  nonce: options?.scriptNonce,
107
129
  onError(error) {
130
+ errorMetaRenderer.capture(error);
108
131
  if (error && typeof error === "object" && "digest" in error) return String(error.digest);
109
132
  if (process.env.NODE_ENV === "production" && error) return ssrErrorDigest(getErrorMessage(error) + (error instanceof Error ? error.stack ?? "" : ""));
110
133
  }
@@ -114,9 +137,10 @@ async function handleSsr(rscStream, navContext, fontData, options) {
114
137
  let didInjectHeadHTML = false;
115
138
  const getInsertedHTML = () => {
116
139
  const insertedHTML = renderInsertedHtml(renderServerInsertedHTML());
117
- if (didInjectHeadHTML) return insertedHTML;
140
+ const errorMetaHTML = errorMetaRenderer.flush();
141
+ if (didInjectHeadHTML) return insertedHTML + errorMetaHTML;
118
142
  didInjectHeadHTML = true;
119
- return buildHeadInjectionHtml(navContext, bootstrapScriptContent, options?.formState ?? null, insertedHTML, fontHTML, options?.scriptNonce);
143
+ return buildHeadInjectionHtml(navContext, bootstrapModuleUrl, options?.formState ?? null, insertedHTML + errorMetaHTML, fontHTML, options?.scriptNonce);
120
144
  };
121
145
  return deferUntilStreamConsumed(htmlStream.pipeThrough(createTickBufferedTransform(rscEmbed, getInsertedHTML)), cleanup);
122
146
  } catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"app-ssr-entry.js","names":["createReactElement"],"sources":["../../src/server/app-ssr-entry.ts"],"sourcesContent":["/// <reference types=\"@vitejs/plugin-rsc/types\" />\n\nimport type { ReactNode } from \"react\";\nimport type { ReactFormState } from \"react-dom/client\";\nimport { Fragment, createElement as createReactElement, use } from \"react\";\nimport { createFromReadableStream } from \"@vitejs/plugin-rsc/ssr\";\nimport { renderToReadableStream, renderToStaticMarkup } from \"react-dom/server.edge\";\nimport clientReferences from \"virtual:vite-rsc/client-references\";\nimport type { NavigationContext } from \"vinext/shims/navigation\";\nimport {\n ServerInsertedHTMLContext,\n clearServerInsertedHTML,\n renderServerInsertedHTML,\n setNavigationContext,\n useServerInsertedHTML,\n} from \"vinext/shims/navigation\";\nimport { runWithNavigationContext } from \"vinext/shims/navigation-state\";\nimport { isOpenRedirectShaped } from \"./request-pipeline.js\";\nimport { notFoundResponse } from \"./http-error-responses.js\";\nimport { withScriptNonce } from \"vinext/shims/script-nonce-context\";\nimport {\n createInlineScriptTag,\n createNonceAttribute,\n escapeHtmlAttr,\n safeJsonStringify,\n} from \"./html.js\";\nimport { createRscEmbedTransform, createTickBufferedTransform } from \"./app-ssr-stream.js\";\nimport { deferUntilStreamConsumed } from \"./app-page-stream.js\";\nimport { AppElementsWire, type AppWireElements } from \"./app-elements.js\";\nimport { ElementsContext, Slot } from \"vinext/shims/slot\";\nimport { createClientReferencePreloader } from \"./app-client-reference-preloader.js\";\nimport { RSC_FORM_STATE_GLOBAL } from \"./app-browser-hydration.js\";\n\nexport type FontPreload = {\n href: string;\n type: string;\n};\n\nexport type FontData = {\n links?: string[];\n styles?: string[];\n preloads?: FontPreload[];\n};\n\nconst clientReferencePreloader = createClientReferencePreloader({\n getReferences() {\n return clientReferences;\n },\n getClientRequire() {\n return globalThis.__vite_rsc_client_require__;\n },\n onPreloadError(id, error) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\"[vinext] failed to preload client ref:\", id, error);\n }\n },\n});\n\nfunction ssrErrorDigest(input: string): string {\n let hash = 5381;\n for (let i = input.length - 1; i >= 0; i--) {\n hash = (hash * 33) ^ input.charCodeAt(i);\n }\n return (hash >>> 0).toString();\n}\n\nfunction getErrorMessage(error: unknown): string {\n if (error instanceof Error) return error.message;\n if (typeof error === \"string\") return error;\n return Object.prototype.toString.call(error);\n}\n\nfunction renderInsertedHtml(insertedElements: readonly unknown[]): string {\n let insertedHTML = \"\";\n\n for (const element of insertedElements) {\n try {\n insertedHTML += renderToStaticMarkup(\n createReactElement(Fragment, null, element as ReactNode),\n );\n } catch {\n // Ignore individual callback failures so the rest of the page can render.\n }\n }\n\n return insertedHTML;\n}\n\nfunction renderFontHtml(fontData?: FontData, nonce?: string): string {\n if (!fontData) return \"\";\n\n let fontHTML = \"\";\n const nonceAttr = createNonceAttribute(nonce);\n\n for (const url of fontData.links ?? []) {\n fontHTML += `<link rel=\"stylesheet\"${nonceAttr} href=\"${escapeHtmlAttr(url)}\" />\\n`;\n }\n\n for (const preload of fontData.preloads ?? []) {\n fontHTML += `<link rel=\"preload\"${nonceAttr} href=\"${escapeHtmlAttr(preload.href)}\" as=\"font\" type=\"${escapeHtmlAttr(preload.type)}\" crossorigin />\\n`;\n }\n\n if (fontData.styles && fontData.styles.length > 0) {\n fontHTML += `<style data-vinext-fonts${nonceAttr}>${fontData.styles.join(\"\\n\")}</style>\\n`;\n }\n\n return fontHTML;\n}\n\nfunction extractModulePreloadHtml(bootstrapScriptContent?: string, nonce?: string): string {\n if (!bootstrapScriptContent) return \"\";\n\n const match = bootstrapScriptContent.match(/import\\(\"([^\"]+)\"\\)/);\n if (!match?.[1]) return \"\";\n\n return `<link rel=\"modulepreload\"${createNonceAttribute(nonce)} href=\"${escapeHtmlAttr(match[1])}\" />\\n`;\n}\n\nfunction buildHeadInjectionHtml(\n navContext: NavigationContext | null,\n bootstrapScriptContent: string | undefined,\n formState: ReactFormState | null,\n insertedHTML: string,\n fontHTML: string,\n scriptNonce?: string,\n): string {\n const paramsScript = createInlineScriptTag(\n \"self.__VINEXT_RSC_PARAMS__=\" + safeJsonStringify(navContext?.params ?? {}),\n scriptNonce,\n );\n const navPayload = {\n pathname: navContext?.pathname ?? \"/\",\n searchParams: navContext?.searchParams ? [...navContext.searchParams.entries()] : [],\n };\n const navScript = createInlineScriptTag(\n \"self.__VINEXT_RSC_NAV__=\" + safeJsonStringify(navPayload),\n scriptNonce,\n );\n const formStateScript =\n formState === null\n ? \"\"\n : createInlineScriptTag(\n \"self[\" + safeJsonStringify(RSC_FORM_STATE_GLOBAL) + \"]=\" + safeJsonStringify(formState),\n scriptNonce,\n );\n\n return (\n paramsScript +\n navScript +\n formStateScript +\n extractModulePreloadHtml(bootstrapScriptContent, scriptNonce) +\n insertedHTML +\n fontHTML\n );\n}\n\nexport async function handleSsr(\n rscStream: ReadableStream<Uint8Array>,\n navContext: NavigationContext | null,\n fontData?: FontData,\n options?: {\n scriptNonce?: string;\n /** Pre-split side stream for embed+capture fusion. When provided,\n * rscStream is fed directly to createFromReadableStream (no internal tee).\n * The embed transform accumulates raw bytes. */\n sideStream?: ReadableStream<Uint8Array>;\n /** Out-parameter: filled with accumulated raw RSC bytes when sideStream is consumed. */\n capturedRscDataRef?: { value: Promise<ArrayBuffer> | null };\n formState?: ReactFormState | null;\n /** When true, wait for the full React tree (including Suspense boundaries)\n * to resolve before returning the HTML stream. Used for static prerender\n * and ISR cache writes to avoid caching fallback content. */\n waitForAllReady?: boolean;\n },\n): Promise<ReadableStream<Uint8Array>> {\n return runWithNavigationContext(async () => {\n await clientReferencePreloader.preload();\n\n if (navContext) {\n setNavigationContext(navContext);\n }\n\n clearServerInsertedHTML();\n\n const cleanup = (): void => {\n setNavigationContext(null);\n clearServerInsertedHTML();\n };\n\n try {\n // Fused tee path (#981): caller pre-split the stream. No internal tee needed.\n // sideStream carries both the embed transform and raw byte accumulation.\n // rscStream is used directly for createFromReadableStream (SSR).\n let ssrStream: ReadableStream<Uint8Array>;\n let rscEmbed;\n\n if (options?.sideStream) {\n ssrStream = rscStream;\n rscEmbed = createRscEmbedTransform(options.sideStream, options?.scriptNonce);\n if (options.capturedRscDataRef) {\n options.capturedRscDataRef.value = rscEmbed.getRawBuffer();\n }\n } else {\n const [s1, s2] = rscStream.tee();\n ssrStream = s1;\n rscEmbed = createRscEmbedTransform(s2, options?.scriptNonce);\n }\n\n let flightRoot: PromiseLike<AppWireElements> | null = null;\n\n function VinextFlightRoot(): ReactNode {\n if (!flightRoot) {\n flightRoot = createFromReadableStream<AppWireElements>(ssrStream);\n }\n const wireElements = use(flightRoot);\n const elements = AppElementsWire.decode(wireElements);\n const metadata = AppElementsWire.readMetadata(elements);\n return createReactElement(\n ElementsContext.Provider,\n { value: elements },\n createReactElement(Slot, { id: metadata.routeId }),\n );\n }\n\n const root = createReactElement(VinextFlightRoot);\n const ssrTree = ServerInsertedHTMLContext\n ? createReactElement(\n ServerInsertedHTMLContext.Provider,\n { value: useServerInsertedHTML },\n root,\n )\n : root;\n const ssrRoot = withScriptNonce(ssrTree, options?.scriptNonce);\n\n const bootstrapScriptContent = await import.meta.viteRsc.loadBootstrapScriptContent(\"index\");\n\n const htmlStream = await renderToReadableStream(ssrRoot, {\n bootstrapScriptContent,\n formState: options?.formState ?? null,\n nonce: options?.scriptNonce,\n onError(error) {\n if (error && typeof error === \"object\" && \"digest\" in error) {\n return String(error.digest);\n }\n\n if (process.env.NODE_ENV === \"production\" && error) {\n const message = getErrorMessage(error);\n const stack = error instanceof Error ? (error.stack ?? \"\") : \"\";\n return ssrErrorDigest(message + stack);\n }\n\n return undefined;\n },\n });\n\n // When producing static output (prerender / ISR cache writes), wait for\n // the full React tree to resolve before emitting bytes. This prevents\n // Suspense fallback content from being serialized to the cache.\n // Matches Next.js waitForAllReady forkpoint in renderToNodeFizzStream.\n if (options?.waitForAllReady === true) {\n await htmlStream.allReady;\n }\n\n const fontHTML = renderFontHtml(fontData, options?.scriptNonce);\n let didInjectHeadHTML = false;\n const getInsertedHTML = (): string => {\n const insertedHTML = renderInsertedHtml(renderServerInsertedHTML());\n if (didInjectHeadHTML) return insertedHTML;\n\n didInjectHeadHTML = true;\n return buildHeadInjectionHtml(\n navContext,\n bootstrapScriptContent,\n options?.formState ?? null,\n insertedHTML,\n fontHTML,\n options?.scriptNonce,\n );\n };\n\n return deferUntilStreamConsumed(\n htmlStream.pipeThrough(createTickBufferedTransform(rscEmbed, getInsertedHTML)),\n cleanup,\n );\n } catch (error) {\n cleanup();\n throw error;\n }\n }) as Promise<ReadableStream<Uint8Array>>;\n}\n\nexport default {\n async fetch(request: Request): Promise<Response> {\n const url = new URL(request.url);\n // Block protocol-relative URL open redirects (including percent-encoded\n // variants like /%5Cevil.com/). See request-pipeline.ts for details.\n if (isOpenRedirectShaped(url.pathname)) {\n return notFoundResponse();\n }\n\n const rscModule = await import.meta.viteRsc.loadModule<{\n default(request: Request): Promise<Response | string | null | undefined>;\n }>(\"rsc\", \"index\");\n const result = await rscModule.default(request);\n\n if (result instanceof Response) {\n return result;\n }\n\n if (result == null) {\n return notFoundResponse();\n }\n\n return new Response(String(result), { status: 200 });\n },\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"app-ssr-entry.js","names":["createReactElement"],"sources":["../../src/server/app-ssr-entry.ts"],"sourcesContent":["/// <reference types=\"@vitejs/plugin-rsc/types\" />\n\nimport \"./server-globals.js\";\nimport type { ReactNode } from \"react\";\nimport type { ReactFormState } from \"react-dom/client\";\nimport { Fragment, createElement as createReactElement, use } from \"react\";\nimport { createFromReadableStream } from \"@vitejs/plugin-rsc/ssr\";\nimport { renderToReadableStream, renderToStaticMarkup } from \"react-dom/server.edge\";\nimport clientReferences from \"virtual:vite-rsc/client-references\";\nimport type { NavigationContext } from \"vinext/shims/navigation\";\nimport {\n ServerInsertedHTMLContext,\n appRouterInstance,\n clearServerInsertedHTML,\n renderServerInsertedHTML,\n setNavigationContext,\n useServerInsertedHTML,\n} from \"vinext/shims/navigation\";\nimport { runWithNavigationContext } from \"vinext/shims/navigation-state\";\nimport { isOpenRedirectShaped } from \"./request-pipeline.js\";\nimport { notFoundResponse } from \"./http-error-responses.js\";\nimport { withScriptNonce } from \"vinext/shims/script-nonce-context\";\nimport {\n createInlineScriptTag,\n createNonceAttribute,\n escapeHtmlAttr,\n safeJsonStringify,\n} from \"./html.js\";\nimport { createRscEmbedTransform, createTickBufferedTransform } from \"./app-ssr-stream.js\";\nimport { deferUntilStreamConsumed } from \"./app-page-stream.js\";\nimport { createSsrErrorMetaRenderer } from \"./app-ssr-error-meta.js\";\nimport { AppElementsWire, type AppWireElements } from \"./app-elements.js\";\nimport { ElementsContext, Slot } from \"vinext/shims/slot\";\nimport { AppRouterContext } from \"vinext/shims/internal/app-router-context\";\nimport { createClientReferencePreloader } from \"./app-client-reference-preloader.js\";\nimport { RSC_FORM_STATE_GLOBAL } from \"./app-browser-hydration.js\";\n\nexport type FontPreload = {\n href: string;\n type: string;\n};\n\nexport type FontData = {\n links?: string[];\n styles?: string[];\n preloads?: FontPreload[];\n};\n\nconst clientReferencePreloader = createClientReferencePreloader({\n getReferences() {\n return clientReferences;\n },\n getClientRequire() {\n return globalThis.__vite_rsc_client_require__;\n },\n onPreloadError(id, error) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\"[vinext] failed to preload client ref:\", id, error);\n }\n },\n});\n\nfunction ssrErrorDigest(input: string): string {\n let hash = 5381;\n for (let i = input.length - 1; i >= 0; i--) {\n hash = (hash * 33) ^ input.charCodeAt(i);\n }\n return (hash >>> 0).toString();\n}\n\nfunction getErrorMessage(error: unknown): string {\n if (error instanceof Error) return error.message;\n if (typeof error === \"string\") return error;\n return Object.prototype.toString.call(error);\n}\n\nfunction renderInsertedHtml(insertedElements: readonly unknown[]): string {\n let insertedHTML = \"\";\n\n for (const element of insertedElements) {\n try {\n insertedHTML += renderToStaticMarkup(\n createReactElement(Fragment, null, element as ReactNode),\n );\n } catch {\n // Ignore individual callback failures so the rest of the page can render.\n }\n }\n\n return insertedHTML;\n}\n\nfunction renderFontHtml(fontData?: FontData, nonce?: string): string {\n if (!fontData) return \"\";\n\n let fontHTML = \"\";\n const nonceAttr = createNonceAttribute(nonce);\n\n for (const url of fontData.links ?? []) {\n fontHTML += `<link rel=\"stylesheet\"${nonceAttr} href=\"${escapeHtmlAttr(url)}\" />\\n`;\n }\n\n for (const preload of fontData.preloads ?? []) {\n fontHTML += `<link rel=\"preload\"${nonceAttr} href=\"${escapeHtmlAttr(preload.href)}\" as=\"font\" type=\"${escapeHtmlAttr(preload.type)}\" crossorigin />\\n`;\n }\n\n if (fontData.styles && fontData.styles.length > 0) {\n fontHTML += `<style data-vinext-fonts${nonceAttr}>${fontData.styles.join(\"\\n\")}</style>\\n`;\n }\n\n return fontHTML;\n}\n\n/**\n * Extract the bootstrap module URL from the `import(\"...\")` string that\n * `import.meta.viteRsc.loadBootstrapScriptContent(\"index\")` returns.\n *\n * The plugin-rsc helper returns the bootstrap as an inline call so we can\n * inject it via `bootstrapScriptContent`. We instead pass the URL to\n * React's `bootstrapModules` option so a real\n * `<script type=\"module\" src=\"…\">` tag ends up in the streamed HTML —\n * this exposes the URL to anything that reads `script.attribs.src` (e.g.\n * the Next.js asset-prefix fixture test). The same URL also feeds the\n * `<link rel=\"modulepreload\">` we emit ahead of the bootstrap.\n *\n * Returns `undefined` when the helper produced no URL (older plugin-rsc\n * versions, or a custom client entry that disables bootstrap content).\n */\nfunction extractBootstrapModuleUrl(bootstrapScriptContent?: string): string | undefined {\n if (!bootstrapScriptContent) return undefined;\n // Accept either quote style — plugin-rsc currently emits double quotes\n // (`import(\"…\")`) but a future version could switch to single quotes,\n // and there's no public contract documenting which is used.\n const match = bootstrapScriptContent.match(/import\\([\"']([^\"']+)[\"']\\)/);\n return match?.[1] ?? undefined;\n}\n\nfunction buildModulePreloadHtml(bootstrapModuleUrl?: string, nonce?: string): string {\n if (!bootstrapModuleUrl) return \"\";\n return `<link rel=\"modulepreload\"${createNonceAttribute(nonce)} href=\"${escapeHtmlAttr(bootstrapModuleUrl)}\" />\\n`;\n}\n\nfunction buildHeadInjectionHtml(\n navContext: NavigationContext | null,\n bootstrapModuleUrl: string | undefined,\n formState: ReactFormState | null,\n insertedHTML: string,\n fontHTML: string,\n scriptNonce?: string,\n): string {\n const paramsScript = createInlineScriptTag(\n \"self.__VINEXT_RSC_PARAMS__=\" + safeJsonStringify(navContext?.params ?? {}),\n scriptNonce,\n );\n const navPayload = {\n pathname: navContext?.pathname ?? \"/\",\n searchParams: navContext?.searchParams ? [...navContext.searchParams.entries()] : [],\n };\n const navScript = createInlineScriptTag(\n \"self.__VINEXT_RSC_NAV__=\" + safeJsonStringify(navPayload),\n scriptNonce,\n );\n const formStateScript =\n formState === null\n ? \"\"\n : createInlineScriptTag(\n \"self[\" + safeJsonStringify(RSC_FORM_STATE_GLOBAL) + \"]=\" + safeJsonStringify(formState),\n scriptNonce,\n );\n\n return (\n paramsScript +\n navScript +\n formStateScript +\n buildModulePreloadHtml(bootstrapModuleUrl, scriptNonce) +\n insertedHTML +\n fontHTML\n );\n}\n\nexport async function handleSsr(\n rscStream: ReadableStream<Uint8Array>,\n navContext: NavigationContext | null,\n fontData?: FontData,\n options?: {\n scriptNonce?: string;\n /** Pre-split side stream for embed+capture fusion. When provided,\n * rscStream is fed directly to createFromReadableStream (no internal tee).\n * The embed transform accumulates raw bytes. */\n sideStream?: ReadableStream<Uint8Array>;\n /** Out-parameter: filled with accumulated raw RSC bytes when sideStream is consumed. */\n capturedRscDataRef?: { value: Promise<ArrayBuffer> | null };\n formState?: ReactFormState | null;\n basePath?: string;\n /** When true, wait for the full React tree (including Suspense boundaries)\n * to resolve before returning the HTML stream. Used for static prerender\n * and ISR cache writes to avoid caching fallback content. */\n waitForAllReady?: boolean;\n },\n): Promise<ReadableStream<Uint8Array>> {\n return runWithNavigationContext(async () => {\n await clientReferencePreloader.preload();\n\n if (navContext) {\n setNavigationContext(navContext);\n }\n\n clearServerInsertedHTML();\n\n const cleanup = (): void => {\n setNavigationContext(null);\n clearServerInsertedHTML();\n };\n\n try {\n // Fused tee path (#981): caller pre-split the stream. No internal tee needed.\n // sideStream carries both the embed transform and raw byte accumulation.\n // rscStream is used directly for createFromReadableStream (SSR).\n let ssrStream: ReadableStream<Uint8Array>;\n let rscEmbed;\n\n if (options?.sideStream) {\n ssrStream = rscStream;\n rscEmbed = createRscEmbedTransform(options.sideStream, options?.scriptNonce);\n if (options.capturedRscDataRef) {\n options.capturedRscDataRef.value = rscEmbed.getRawBuffer();\n }\n } else {\n const [s1, s2] = rscStream.tee();\n ssrStream = s1;\n rscEmbed = createRscEmbedTransform(s2, options?.scriptNonce);\n }\n\n let flightRoot: PromiseLike<AppWireElements> | null = null;\n\n function VinextFlightRoot(): ReactNode {\n if (!flightRoot) {\n flightRoot = createFromReadableStream<AppWireElements>(ssrStream);\n }\n const wireElements = use(flightRoot);\n const elements = AppElementsWire.decode(wireElements);\n const metadata = AppElementsWire.readMetadata(elements);\n return createReactElement(\n ElementsContext.Provider,\n { value: elements },\n createReactElement(Slot, { id: metadata.routeId }),\n );\n }\n\n const flightRootElement = createReactElement(VinextFlightRoot);\n const root = AppRouterContext\n ? createReactElement(\n AppRouterContext.Provider,\n { value: appRouterInstance },\n flightRootElement,\n )\n : flightRootElement;\n const ssrTree = ServerInsertedHTMLContext\n ? createReactElement(\n ServerInsertedHTMLContext.Provider,\n { value: useServerInsertedHTML },\n root,\n )\n : root;\n const ssrRoot = withScriptNonce(ssrTree, options?.scriptNonce);\n\n // plugin-rsc returns the bootstrap as `import(\"<url>\")` so callers can\n // inject it via `bootstrapScriptContent`. We hand the URL to React's\n // `bootstrapModules` option instead so the streamed HTML contains a\n // real `<script type=\"module\" src=\"<url>\">` tag — exposing the URL\n // to anything that inspects `script.attribs.src` (e.g. the Next.js\n // asset-prefix fixture test \"bundles should return 200 on served\n // assetPrefix\"). Mirrors Next.js's app-render path which passes\n // `bootstrapScripts: [{ src }]` for the same reason; we use\n // `bootstrapModules` because vinext's chunks are native ES modules\n // (Vite output) so a `type=\"module\"` tag is the correct loader.\n //\n // In dev, `<url>` is a Vite dev URL like\n // `/@id/__x00__virtual:vinext-app-browser-entry`; the browser fetches\n // it as a module from the dev server. In prod it's the hashed bundle\n // URL (e.g. `/_next/static/index-abc123.js`, optionally prefixed by\n // `assetPrefix`). Both are valid `<script type=\"module\" src=…>` targets.\n const bootstrapScriptContent = await import.meta.viteRsc.loadBootstrapScriptContent(\"index\");\n const bootstrapModuleUrl = extractBootstrapModuleUrl(bootstrapScriptContent);\n const errorMetaRenderer = createSsrErrorMetaRenderer({\n basePath: options?.basePath,\n });\n\n const htmlStream = await renderToReadableStream(ssrRoot, {\n // `bootstrapScriptContent` was previously how vinext injected the\n // dynamic-import call. `bootstrapModules` performs the same work\n // natively (and exposes the URL in the DOM), so passing both would\n // load the bootstrap module twice.\n //\n // CSP implications of using `bootstrapModules` instead of inline\n // `bootstrapScriptContent`:\n // - Apps no longer need `script-src 'unsafe-inline'` to load the\n // bootstrap (improvement — inline imports required `'unsafe-inline'`).\n // - Apps that restrict script sources need `'self'` for the\n // common case, or the CDN origin when `assetPrefix` is an\n // absolute URL like `https://cdn.example.com`.\n // - React still applies `nonce` to the emitted\n // `<script type=\"module\" src=…>` tag, so nonce-based CSP\n // (`script-src 'nonce-…' 'strict-dynamic'`) keeps working.\n bootstrapModules: bootstrapModuleUrl ? [bootstrapModuleUrl] : undefined,\n formState: options?.formState ?? null,\n nonce: options?.scriptNonce,\n onError(error) {\n errorMetaRenderer.capture(error);\n\n if (error && typeof error === \"object\" && \"digest\" in error) {\n return String(error.digest);\n }\n\n if (process.env.NODE_ENV === \"production\" && error) {\n const message = getErrorMessage(error);\n const stack = error instanceof Error ? (error.stack ?? \"\") : \"\";\n return ssrErrorDigest(message + stack);\n }\n\n return undefined;\n },\n });\n\n // When producing static output (prerender / ISR cache writes), wait for\n // the full React tree to resolve before emitting bytes. This prevents\n // Suspense fallback content from being serialized to the cache.\n // Matches Next.js waitForAllReady forkpoint in renderToNodeFizzStream.\n if (options?.waitForAllReady === true) {\n await htmlStream.allReady;\n }\n\n const fontHTML = renderFontHtml(fontData, options?.scriptNonce);\n let didInjectHeadHTML = false;\n const getInsertedHTML = (): string => {\n const insertedHTML = renderInsertedHtml(renderServerInsertedHTML());\n const errorMetaHTML = errorMetaRenderer.flush();\n if (didInjectHeadHTML) return insertedHTML + errorMetaHTML;\n\n didInjectHeadHTML = true;\n return buildHeadInjectionHtml(\n navContext,\n bootstrapModuleUrl,\n options?.formState ?? null,\n insertedHTML + errorMetaHTML,\n fontHTML,\n options?.scriptNonce,\n );\n };\n\n return deferUntilStreamConsumed(\n htmlStream.pipeThrough(createTickBufferedTransform(rscEmbed, getInsertedHTML)),\n cleanup,\n );\n } catch (error) {\n cleanup();\n throw error;\n }\n }) as Promise<ReadableStream<Uint8Array>>;\n}\n\nexport default {\n async fetch(request: Request): Promise<Response> {\n const url = new URL(request.url);\n // Block protocol-relative URL open redirects (including percent-encoded\n // variants like /%5Cevil.com/). See request-pipeline.ts for details.\n if (isOpenRedirectShaped(url.pathname)) {\n return notFoundResponse();\n }\n\n const rscModule = await import.meta.viteRsc.loadModule<{\n default(request: Request): Promise<Response | string | null | undefined>;\n }>(\"rsc\", \"index\");\n const result = await rscModule.default(request);\n\n if (result instanceof Response) {\n return result;\n }\n\n if (result == null) {\n return notFoundResponse();\n }\n\n return new Response(String(result), { status: 200 });\n },\n};\n"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ //#region src/server/app-ssr-error-meta.d.ts
2
+ type SsrErrorMetaRenderOptions = {
3
+ basePath?: string;
4
+ nodeEnv?: string;
5
+ };
6
+ type SsrErrorMetaRenderer = {
7
+ capture: (error: unknown) => void;
8
+ flush: () => string;
9
+ };
10
+ declare function renderSsrErrorMetaTags(errors: readonly unknown[], options?: SsrErrorMetaRenderOptions): string;
11
+ declare function createSsrErrorMetaRenderer(options?: SsrErrorMetaRenderOptions): SsrErrorMetaRenderer;
12
+ //#endregion
13
+ export { createSsrErrorMetaRenderer, renderSsrErrorMetaTags };
14
+ //# sourceMappingURL=app-ssr-error-meta.d.ts.map