vinext 0.0.46 → 0.0.48

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 (351) hide show
  1. package/README.md +8 -6
  2. package/dist/build/layout-classification.js +3 -1
  3. package/dist/build/layout-classification.js.map +1 -1
  4. package/dist/build/prerender.d.ts +2 -1
  5. package/dist/build/prerender.js +80 -24
  6. package/dist/build/prerender.js.map +1 -1
  7. package/dist/build/report.d.ts +9 -5
  8. package/dist/build/report.js +17 -7
  9. package/dist/build/report.js.map +1 -1
  10. package/dist/build/route-classification-injector.d.ts +35 -0
  11. package/dist/build/route-classification-injector.js +61 -0
  12. package/dist/build/route-classification-injector.js.map +1 -0
  13. package/dist/build/route-classification-manifest.d.ts +1 -1
  14. package/dist/build/run-prerender.d.ts +5 -0
  15. package/dist/build/run-prerender.js +4 -1
  16. package/dist/build/run-prerender.js.map +1 -1
  17. package/dist/build/server-manifest.js +2 -7
  18. package/dist/build/server-manifest.js.map +1 -1
  19. package/dist/build/standalone.js +3 -5
  20. package/dist/build/standalone.js.map +1 -1
  21. package/dist/build/static-export.d.ts +1 -1
  22. package/dist/check.js +45 -29
  23. package/dist/check.js.map +1 -1
  24. package/dist/cli-args.d.ts +33 -0
  25. package/dist/cli-args.js +121 -0
  26. package/dist/cli-args.js.map +1 -0
  27. package/dist/cli.js +11 -20
  28. package/dist/cli.js.map +1 -1
  29. package/dist/cloudflare/kv-cache-handler.js +29 -9
  30. package/dist/cloudflare/kv-cache-handler.js.map +1 -1
  31. package/dist/config/config-matchers.js +46 -37
  32. package/dist/config/config-matchers.js.map +1 -1
  33. package/dist/config/next-config.d.ts +4 -2
  34. package/dist/config/next-config.js +3 -0
  35. package/dist/config/next-config.js.map +1 -1
  36. package/dist/deploy.d.ts +18 -2
  37. package/dist/deploy.js +47 -4
  38. package/dist/deploy.js.map +1 -1
  39. package/dist/entries/app-rsc-entry.d.ts +4 -3
  40. package/dist/entries/app-rsc-entry.js +379 -858
  41. package/dist/entries/app-rsc-entry.js.map +1 -1
  42. package/dist/entries/app-rsc-manifest.d.ts +1 -1
  43. package/dist/entries/app-rsc-manifest.js +6 -1
  44. package/dist/entries/app-rsc-manifest.js.map +1 -1
  45. package/dist/entries/pages-client-entry.js +3 -2
  46. package/dist/entries/pages-client-entry.js.map +1 -1
  47. package/dist/entries/pages-server-entry.js +19 -61
  48. package/dist/entries/pages-server-entry.js.map +1 -1
  49. package/dist/entries/runtime-entry-module.d.ts +12 -3
  50. package/dist/entries/runtime-entry-module.js +15 -4
  51. package/dist/entries/runtime-entry-module.js.map +1 -1
  52. package/dist/index.js +40 -58
  53. package/dist/index.js.map +1 -1
  54. package/dist/plugins/fonts.js +54 -32
  55. package/dist/plugins/fonts.js.map +1 -1
  56. package/dist/plugins/og-assets.js +15 -16
  57. package/dist/plugins/og-assets.js.map +1 -1
  58. package/dist/plugins/rsc-client-shim-excludes.d.ts +2 -1
  59. package/dist/plugins/rsc-client-shim-excludes.js +11 -1
  60. package/dist/plugins/rsc-client-shim-excludes.js.map +1 -1
  61. package/dist/routing/app-route-graph.d.ts +195 -0
  62. package/dist/routing/app-route-graph.js +1022 -0
  63. package/dist/routing/app-route-graph.js.map +1 -0
  64. package/dist/routing/app-router.d.ts +14 -88
  65. package/dist/routing/app-router.js +21 -712
  66. package/dist/routing/app-router.js.map +1 -1
  67. package/dist/routing/file-matcher.d.ts +3 -1
  68. package/dist/routing/file-matcher.js +6 -1
  69. package/dist/routing/file-matcher.js.map +1 -1
  70. package/dist/routing/pages-router.js +10 -19
  71. package/dist/routing/pages-router.js.map +1 -1
  72. package/dist/routing/route-matching.d.ts +28 -0
  73. package/dist/routing/route-matching.js +44 -0
  74. package/dist/routing/route-matching.js.map +1 -0
  75. package/dist/routing/route-pattern.js +4 -1
  76. package/dist/routing/route-pattern.js.map +1 -1
  77. package/dist/routing/route-trie.d.ts +8 -0
  78. package/dist/routing/route-trie.js +12 -1
  79. package/dist/routing/route-trie.js.map +1 -1
  80. package/dist/routing/route-validation.js +3 -4
  81. package/dist/routing/route-validation.js.map +1 -1
  82. package/dist/routing/utils.d.ts +8 -1
  83. package/dist/routing/utils.js +25 -2
  84. package/dist/routing/utils.js.map +1 -1
  85. package/dist/server/app-browser-entry.js +145 -294
  86. package/dist/server/app-browser-entry.js.map +1 -1
  87. package/dist/server/app-browser-error.d.ts +3 -4
  88. package/dist/server/app-browser-error.js +8 -4
  89. package/dist/server/app-browser-error.js.map +1 -1
  90. package/dist/server/app-browser-navigation-controller.d.ts +75 -0
  91. package/dist/server/app-browser-navigation-controller.js +290 -0
  92. package/dist/server/app-browser-navigation-controller.js.map +1 -0
  93. package/dist/server/app-browser-state.d.ts +33 -15
  94. package/dist/server/app-browser-state.js +52 -59
  95. package/dist/server/app-browser-state.js.map +1 -1
  96. package/dist/server/app-browser-visible-commit.d.ts +68 -0
  97. package/dist/server/app-browser-visible-commit.js +182 -0
  98. package/dist/server/app-browser-visible-commit.js.map +1 -0
  99. package/dist/server/app-client-reference-preloader.d.ts +15 -0
  100. package/dist/server/app-client-reference-preloader.js +46 -0
  101. package/dist/server/app-client-reference-preloader.js.map +1 -0
  102. package/dist/server/app-elements-wire.d.ts +130 -0
  103. package/dist/server/app-elements-wire.js +205 -0
  104. package/dist/server/app-elements-wire.js.map +1 -0
  105. package/dist/server/app-elements.d.ts +2 -84
  106. package/dist/server/app-elements.js +4 -107
  107. package/dist/server/app-elements.js.map +1 -1
  108. package/dist/server/app-fallback-renderer.d.ts +57 -0
  109. package/dist/server/app-fallback-renderer.js +79 -0
  110. package/dist/server/app-fallback-renderer.js.map +1 -0
  111. package/dist/server/app-hook-warning-suppression.d.ts +7 -0
  112. package/dist/server/app-hook-warning-suppression.js +12 -0
  113. package/dist/server/app-hook-warning-suppression.js.map +1 -0
  114. package/dist/server/app-middleware.d.ts +2 -1
  115. package/dist/server/app-middleware.js +34 -11
  116. package/dist/server/app-middleware.js.map +1 -1
  117. package/dist/server/app-mounted-slots-header.d.ts +17 -0
  118. package/dist/server/app-mounted-slots-header.js +21 -0
  119. package/dist/server/app-mounted-slots-header.js.map +1 -0
  120. package/dist/server/app-page-boundary-render.d.ts +3 -3
  121. package/dist/server/app-page-boundary-render.js +8 -5
  122. package/dist/server/app-page-boundary-render.js.map +1 -1
  123. package/dist/server/app-page-boundary.js +2 -1
  124. package/dist/server/app-page-boundary.js.map +1 -1
  125. package/dist/server/app-page-cache.d.ts +19 -4
  126. package/dist/server/app-page-cache.js +60 -22
  127. package/dist/server/app-page-cache.js.map +1 -1
  128. package/dist/server/app-page-dispatch.d.ts +9 -5
  129. package/dist/server/app-page-dispatch.js +41 -17
  130. package/dist/server/app-page-dispatch.js.map +1 -1
  131. package/dist/server/app-page-element-builder.d.ts +61 -0
  132. package/dist/server/app-page-element-builder.js +142 -0
  133. package/dist/server/app-page-element-builder.js.map +1 -0
  134. package/dist/server/app-page-execution.d.ts +23 -5
  135. package/dist/server/app-page-execution.js +39 -24
  136. package/dist/server/app-page-execution.js.map +1 -1
  137. package/dist/server/app-page-head.js +2 -1
  138. package/dist/server/app-page-head.js.map +1 -1
  139. package/dist/server/app-page-method.js +2 -5
  140. package/dist/server/app-page-method.js.map +1 -1
  141. package/dist/server/app-page-params.d.ts +2 -1
  142. package/dist/server/app-page-params.js +3 -3
  143. package/dist/server/app-page-params.js.map +1 -1
  144. package/dist/server/app-page-probe.d.ts +1 -1
  145. package/dist/server/app-page-probe.js +5 -1
  146. package/dist/server/app-page-probe.js.map +1 -1
  147. package/dist/server/app-page-render.d.ts +6 -2
  148. package/dist/server/app-page-render.js +118 -30
  149. package/dist/server/app-page-render.js.map +1 -1
  150. package/dist/server/app-page-request.d.ts +19 -5
  151. package/dist/server/app-page-request.js +49 -7
  152. package/dist/server/app-page-request.js.map +1 -1
  153. package/dist/server/app-page-response.d.ts +1 -0
  154. package/dist/server/app-page-response.js +6 -9
  155. package/dist/server/app-page-response.js.map +1 -1
  156. package/dist/server/app-page-route-wiring.d.ts +20 -4
  157. package/dist/server/app-page-route-wiring.js +15 -12
  158. package/dist/server/app-page-route-wiring.js.map +1 -1
  159. package/dist/server/app-page-stream.d.ts +7 -0
  160. package/dist/server/app-page-stream.js +9 -2
  161. package/dist/server/app-page-stream.js.map +1 -1
  162. package/dist/server/app-post-middleware-context.d.ts +16 -0
  163. package/dist/server/app-post-middleware-context.js +28 -0
  164. package/dist/server/app-post-middleware-context.js.map +1 -0
  165. package/dist/server/app-prerender-endpoints.js +3 -2
  166. package/dist/server/app-prerender-endpoints.js.map +1 -1
  167. package/dist/server/app-request-context.d.ts +22 -0
  168. package/dist/server/app-request-context.js +30 -0
  169. package/dist/server/app-request-context.js.map +1 -0
  170. package/dist/server/app-route-handler-cache.d.ts +1 -0
  171. package/dist/server/app-route-handler-cache.js +7 -2
  172. package/dist/server/app-route-handler-cache.js.map +1 -1
  173. package/dist/server/app-route-handler-dispatch.d.ts +1 -0
  174. package/dist/server/app-route-handler-dispatch.js +8 -5
  175. package/dist/server/app-route-handler-dispatch.js.map +1 -1
  176. package/dist/server/app-route-handler-execution.d.ts +2 -1
  177. package/dist/server/app-route-handler-execution.js +2 -2
  178. package/dist/server/app-route-handler-execution.js.map +1 -1
  179. package/dist/server/app-route-handler-policy.js +13 -13
  180. package/dist/server/app-route-handler-policy.js.map +1 -1
  181. package/dist/server/app-route-handler-response.d.ts +4 -2
  182. package/dist/server/app-route-handler-response.js +9 -7
  183. package/dist/server/app-route-handler-response.js.map +1 -1
  184. package/dist/server/app-route-handler-runtime.d.ts +9 -1
  185. package/dist/server/app-route-handler-runtime.js +11 -1
  186. package/dist/server/app-route-handler-runtime.js.map +1 -1
  187. package/dist/server/app-router-entry.js +9 -4
  188. package/dist/server/app-router-entry.js.map +1 -1
  189. package/dist/server/app-rsc-cache-busting.d.ts +34 -0
  190. package/dist/server/app-rsc-cache-busting.js +137 -0
  191. package/dist/server/app-rsc-cache-busting.js.map +1 -0
  192. package/dist/server/app-rsc-error-handler.d.ts +21 -0
  193. package/dist/server/app-rsc-error-handler.js +30 -0
  194. package/dist/server/app-rsc-error-handler.js.map +1 -0
  195. package/dist/server/app-rsc-handler.d.ts +117 -0
  196. package/dist/server/app-rsc-handler.js +271 -0
  197. package/dist/server/app-rsc-handler.js.map +1 -0
  198. package/dist/server/app-rsc-request-normalization.d.ts +42 -0
  199. package/dist/server/app-rsc-request-normalization.js +67 -0
  200. package/dist/server/app-rsc-request-normalization.js.map +1 -0
  201. package/dist/server/app-rsc-response-finalizer.d.ts +30 -0
  202. package/dist/server/app-rsc-response-finalizer.js +38 -0
  203. package/dist/server/app-rsc-response-finalizer.js.map +1 -0
  204. package/dist/server/app-rsc-route-matching.js +8 -4
  205. package/dist/server/app-rsc-route-matching.js.map +1 -1
  206. package/dist/server/app-segment-config.d.ts +33 -0
  207. package/dist/server/app-segment-config.js +90 -0
  208. package/dist/server/app-segment-config.js.map +1 -0
  209. package/dist/server/app-server-action-execution.d.ts +2 -0
  210. package/dist/server/app-server-action-execution.js +45 -51
  211. package/dist/server/app-server-action-execution.js.map +1 -1
  212. package/dist/server/app-ssr-entry.js +21 -20
  213. package/dist/server/app-ssr-entry.js.map +1 -1
  214. package/dist/server/artifact-compatibility.d.ts +44 -0
  215. package/dist/server/artifact-compatibility.js +82 -0
  216. package/dist/server/artifact-compatibility.js.map +1 -0
  217. package/dist/server/cache-control.d.ts +24 -0
  218. package/dist/server/cache-control.js +33 -0
  219. package/dist/server/cache-control.js.map +1 -0
  220. package/dist/server/cache-proof.d.ts +200 -0
  221. package/dist/server/cache-proof.js +342 -0
  222. package/dist/server/cache-proof.js.map +1 -0
  223. package/dist/server/dev-error-overlay-store.d.ts +23 -0
  224. package/dist/server/dev-error-overlay-store.js +67 -0
  225. package/dist/server/dev-error-overlay-store.js.map +1 -0
  226. package/dist/server/dev-error-overlay.d.ts +15 -0
  227. package/dist/server/dev-error-overlay.js +548 -0
  228. package/dist/server/dev-error-overlay.js.map +1 -0
  229. package/dist/server/dev-origin-check.js +8 -4
  230. package/dist/server/dev-origin-check.js.map +1 -1
  231. package/dist/server/dev-server.js +1 -6
  232. package/dist/server/dev-server.js.map +1 -1
  233. package/dist/server/http-error-responses.d.ts +67 -0
  234. package/dist/server/http-error-responses.js +77 -0
  235. package/dist/server/http-error-responses.js.map +1 -0
  236. package/dist/server/image-optimization.js +2 -1
  237. package/dist/server/image-optimization.js.map +1 -1
  238. package/dist/server/instrumentation-runtime.d.ts +44 -0
  239. package/dist/server/instrumentation-runtime.js +29 -0
  240. package/dist/server/instrumentation-runtime.js.map +1 -0
  241. package/dist/server/isr-cache.d.ts +2 -7
  242. package/dist/server/isr-cache.js +7 -10
  243. package/dist/server/isr-cache.js.map +1 -1
  244. package/dist/server/metadata-route-response.js +6 -5
  245. package/dist/server/metadata-route-response.js.map +1 -1
  246. package/dist/server/metadata-routes.d.ts +1 -0
  247. package/dist/server/metadata-routes.js +6 -0
  248. package/dist/server/metadata-routes.js.map +1 -1
  249. package/dist/server/middleware-matcher.js +2 -2
  250. package/dist/server/middleware-matcher.js.map +1 -1
  251. package/dist/server/middleware-response-headers.js +21 -0
  252. package/dist/server/middleware-response-headers.js.map +1 -1
  253. package/dist/server/middleware-runtime.js +3 -3
  254. package/dist/server/middleware-runtime.js.map +1 -1
  255. package/dist/server/navigation-trace.d.ts +33 -0
  256. package/dist/server/navigation-trace.js +35 -0
  257. package/dist/server/navigation-trace.js.map +1 -0
  258. package/dist/server/next-error-digest.d.ts +44 -0
  259. package/dist/server/next-error-digest.js +40 -0
  260. package/dist/server/next-error-digest.js.map +1 -0
  261. package/dist/server/pages-api-route.js +2 -1
  262. package/dist/server/pages-api-route.js.map +1 -1
  263. package/dist/server/pages-node-compat.js +4 -16
  264. package/dist/server/pages-node-compat.js.map +1 -1
  265. package/dist/server/pages-page-data.d.ts +2 -1
  266. package/dist/server/pages-page-data.js +6 -5
  267. package/dist/server/pages-page-data.js.map +1 -1
  268. package/dist/server/pages-page-response.d.ts +3 -8
  269. package/dist/server/pages-page-response.js +46 -15
  270. package/dist/server/pages-page-response.js.map +1 -1
  271. package/dist/server/prod-server.d.ts +6 -0
  272. package/dist/server/prod-server.js +28 -21
  273. package/dist/server/prod-server.js.map +1 -1
  274. package/dist/server/request-pipeline.d.ts +42 -1
  275. package/dist/server/request-pipeline.js +97 -17
  276. package/dist/server/request-pipeline.js.map +1 -1
  277. package/dist/server/rsc-stream-hints.d.ts +3 -1
  278. package/dist/server/rsc-stream-hints.js +4 -1
  279. package/dist/server/rsc-stream-hints.js.map +1 -1
  280. package/dist/server/seed-cache.js +19 -8
  281. package/dist/server/seed-cache.js.map +1 -1
  282. package/dist/shims/cache-runtime.d.ts +2 -2
  283. package/dist/shims/cache-runtime.js +31 -17
  284. package/dist/shims/cache-runtime.js.map +1 -1
  285. package/dist/shims/cache.d.ts +15 -3
  286. package/dist/shims/cache.js +45 -20
  287. package/dist/shims/cache.js.map +1 -1
  288. package/dist/shims/error-boundary.d.ts +17 -1
  289. package/dist/shims/error-boundary.js +31 -1
  290. package/dist/shims/error-boundary.js.map +1 -1
  291. package/dist/shims/fetch-cache.d.ts +4 -1
  292. package/dist/shims/fetch-cache.js +57 -16
  293. package/dist/shims/fetch-cache.js.map +1 -1
  294. package/dist/shims/head-state.js +2 -3
  295. package/dist/shims/head-state.js.map +1 -1
  296. package/dist/shims/headers.js +4 -44
  297. package/dist/shims/headers.js.map +1 -1
  298. package/dist/shims/i18n-state.js +2 -3
  299. package/dist/shims/i18n-state.js.map +1 -1
  300. package/dist/shims/image.js +93 -5
  301. package/dist/shims/image.js.map +1 -1
  302. package/dist/shims/internal/als-registry.d.ts +15 -0
  303. package/dist/shims/internal/als-registry.js +55 -0
  304. package/dist/shims/internal/als-registry.js.map +1 -0
  305. package/dist/shims/internal/cookie-serialize.d.ts +46 -0
  306. package/dist/shims/internal/cookie-serialize.js +51 -0
  307. package/dist/shims/internal/cookie-serialize.js.map +1 -0
  308. package/dist/shims/link.js +31 -26
  309. package/dist/shims/link.js.map +1 -1
  310. package/dist/shims/metadata.d.ts +26 -1
  311. package/dist/shims/metadata.js +94 -4
  312. package/dist/shims/metadata.js.map +1 -1
  313. package/dist/shims/navigation-state.js +2 -3
  314. package/dist/shims/navigation-state.js.map +1 -1
  315. package/dist/shims/navigation.d.ts +2 -7
  316. package/dist/shims/navigation.js +44 -36
  317. package/dist/shims/navigation.js.map +1 -1
  318. package/dist/shims/request-context.js +2 -4
  319. package/dist/shims/request-context.js.map +1 -1
  320. package/dist/shims/request-state-types.d.ts +1 -1
  321. package/dist/shims/router-state.js +2 -3
  322. package/dist/shims/router-state.js.map +1 -1
  323. package/dist/shims/router.js +2 -2
  324. package/dist/shims/router.js.map +1 -1
  325. package/dist/shims/server.js +5 -30
  326. package/dist/shims/server.js.map +1 -1
  327. package/dist/shims/slot.d.ts +1 -1
  328. package/dist/shims/slot.js +5 -4
  329. package/dist/shims/slot.js.map +1 -1
  330. package/dist/shims/thenable-params.d.ts +5 -2
  331. package/dist/shims/thenable-params.js +26 -6
  332. package/dist/shims/thenable-params.js.map +1 -1
  333. package/dist/shims/unified-request-context.d.ts +1 -1
  334. package/dist/shims/unified-request-context.js +3 -14
  335. package/dist/shims/unified-request-context.js.map +1 -1
  336. package/dist/shims/use-merged-ref.d.ts +7 -0
  337. package/dist/shims/use-merged-ref.js +40 -0
  338. package/dist/shims/use-merged-ref.js.map +1 -0
  339. package/dist/utils/base-path.d.ts +7 -1
  340. package/dist/utils/base-path.js +12 -1
  341. package/dist/utils/base-path.js.map +1 -1
  342. package/dist/utils/cache-control-metadata.d.ts +6 -0
  343. package/dist/utils/cache-control-metadata.js +16 -0
  344. package/dist/utils/cache-control-metadata.js.map +1 -0
  345. package/dist/utils/safe-json-file.d.ts +18 -0
  346. package/dist/utils/safe-json-file.js +25 -0
  347. package/dist/utils/safe-json-file.js.map +1 -0
  348. package/dist/utils/text-stream.d.ts +29 -0
  349. package/dist/utils/text-stream.js +66 -0
  350. package/dist/utils/text-stream.js.map +1 -0
  351. package/package.json +5 -5
@@ -1,26 +1,30 @@
1
+ import { normalizePathnameForRouteMatch } from "../routing/utils.js";
1
2
  import { buildRouteTrie, trieMatch } from "../routing/route-trie.js";
2
3
  import { matchRoutePattern } from "../routing/route-pattern.js";
3
4
  //#region src/server/app-rsc-route-matching.ts
4
5
  function createRouteParams() {
5
6
  return Object.create(null);
6
7
  }
8
+ function appRscPathnameParts(pathname) {
9
+ const pathOnly = pathname.split("?")[0];
10
+ return normalizePathnameForRouteMatch(pathOnly === "/" ? "/" : pathOnly.replace(/\/$/, "")).split("/").filter(Boolean);
11
+ }
7
12
  function createAppRscRouteMatcher(routes) {
8
13
  const routeTrie = buildRouteTrie(routes);
9
14
  const interceptLookup = createInterceptLookup(routes);
10
15
  return {
11
16
  matchRoute(url) {
12
- const pathname = url.split("?")[0];
13
- return trieMatch(routeTrie, (pathname === "/" ? "/" : pathname.replace(/\/$/, "")).split("/").filter(Boolean));
17
+ return trieMatch(routeTrie, appRscPathnameParts(url));
14
18
  },
15
19
  findIntercept(pathname, sourcePathname = null) {
16
- const urlParts = pathname.split("/").filter(Boolean);
20
+ const urlParts = appRscPathnameParts(pathname);
17
21
  for (const entry of interceptLookup) {
18
22
  const params = matchAppRscRoutePattern(urlParts, entry.targetPatternParts);
19
23
  if (params !== null) {
20
24
  let sourceParams = createRouteParams();
21
25
  if (sourcePathname !== null) {
22
26
  const sourceRoute = routes[entry.sourceRouteIndex];
23
- const sourceParts = sourcePathname.split("/").filter(Boolean);
27
+ const sourceParts = appRscPathnameParts(sourcePathname);
24
28
  const matchedSourceParams = sourceRoute ? matchAppRscRoutePattern(sourceParts, sourceRoute.patternParts) : null;
25
29
  if (matchedSourceParams !== null) sourceParams = matchedSourceParams;
26
30
  }
@@ -1 +1 @@
1
- {"version":3,"file":"app-rsc-route-matching.js","names":[],"sources":["../../src/server/app-rsc-route-matching.ts"],"sourcesContent":["import { buildRouteTrie, trieMatch } from \"../routing/route-trie.js\";\nimport { matchRoutePattern, type RoutePatternParams } from \"../routing/route-pattern.js\";\n\ntype AppRscRouteParams = RoutePatternParams;\n\ntype AppRscInterceptForMatching = {\n targetPattern: string;\n interceptLayouts: readonly unknown[];\n page: unknown;\n params: readonly string[];\n};\n\ntype AppRscSlotForMatching = {\n intercepts?: readonly AppRscInterceptForMatching[];\n};\n\ntype AppRscRouteForMatching = {\n patternParts: string[];\n slots?: Record<string, AppRscSlotForMatching>;\n};\n\ntype AppRscInterceptMatch = AppRscInterceptLookupEntry & {\n matchedParams: AppRscRouteParams;\n};\n\ntype AppRscInterceptLookupEntry = {\n sourceRouteIndex: number;\n slotKey: string;\n targetPattern: string;\n targetPatternParts: string[];\n interceptLayouts: readonly unknown[];\n page: unknown;\n params: readonly string[];\n};\n\nfunction createRouteParams(): AppRscRouteParams {\n return Object.create(null);\n}\n\nexport function createAppRscRouteMatcher<Route extends AppRscRouteForMatching>(\n routes: Route[],\n): {\n matchRoute(url: string): { route: Route; params: AppRscRouteParams } | null;\n findIntercept(pathname: string, sourcePathname?: string | null): AppRscInterceptMatch | null;\n} {\n const routeTrie = buildRouteTrie(routes);\n const interceptLookup = createInterceptLookup(routes);\n\n return {\n matchRoute(url) {\n const pathname = url.split(\"?\")[0];\n const normalizedUrl = pathname === \"/\" ? \"/\" : pathname.replace(/\\/$/, \"\");\n // The request entry point owns decoding. Matching here preserves the\n // already-normalized segment bytes so middleware and routing stay aligned.\n const urlParts = normalizedUrl.split(\"/\").filter(Boolean);\n return trieMatch(routeTrie, urlParts);\n },\n findIntercept(pathname, sourcePathname = null) {\n const urlParts = pathname.split(\"/\").filter(Boolean);\n for (const entry of interceptLookup) {\n const params = matchAppRscRoutePattern(urlParts, entry.targetPatternParts);\n if (params !== null) {\n let sourceParams = createRouteParams();\n if (sourcePathname !== null) {\n const sourceRoute = routes[entry.sourceRouteIndex];\n const sourceParts = sourcePathname.split(\"/\").filter(Boolean);\n const matchedSourceParams = sourceRoute\n ? matchAppRscRoutePattern(sourceParts, sourceRoute.patternParts)\n : null;\n if (matchedSourceParams !== null) {\n sourceParams = matchedSourceParams;\n }\n }\n return { ...entry, matchedParams: mergeMatchedParams(sourceParams, params) };\n }\n }\n return null;\n },\n };\n}\n\nfunction createInterceptLookup<Route extends AppRscRouteForMatching>(\n routes: Route[],\n): AppRscInterceptLookupEntry[] {\n const interceptLookup: AppRscInterceptLookupEntry[] = [];\n for (let routeIndex = 0; routeIndex < routes.length; routeIndex++) {\n const route = routes[routeIndex];\n if (!route.slots) continue;\n for (const [slotKey, slotModule] of Object.entries(route.slots)) {\n if (!slotModule.intercepts) continue;\n for (const intercept of slotModule.intercepts) {\n interceptLookup.push({\n sourceRouteIndex: routeIndex,\n slotKey,\n targetPattern: intercept.targetPattern,\n targetPatternParts: intercept.targetPattern.split(\"/\").filter(Boolean),\n interceptLayouts: intercept.interceptLayouts,\n page: intercept.page,\n params: intercept.params,\n });\n }\n }\n }\n return interceptLookup;\n}\n\nexport function matchAppRscRoutePattern(\n urlParts: string[],\n patternParts: string[],\n): AppRscRouteParams | null {\n return matchRoutePattern(urlParts, patternParts);\n}\n\nfunction mergeMatchedParams(\n sourceParams: AppRscRouteParams,\n targetParams: AppRscRouteParams,\n): AppRscRouteParams {\n return Object.assign(createRouteParams(), sourceParams, targetParams);\n}\n"],"mappings":";;;AAmCA,SAAS,oBAAuC;AAC9C,QAAO,OAAO,OAAO,KAAK;;AAG5B,SAAgB,yBACd,QAIA;CACA,MAAM,YAAY,eAAe,OAAO;CACxC,MAAM,kBAAkB,sBAAsB,OAAO;AAErD,QAAO;EACL,WAAW,KAAK;GACd,MAAM,WAAW,IAAI,MAAM,IAAI,CAAC;AAKhC,UAAO,UAAU,YAJK,aAAa,MAAM,MAAM,SAAS,QAAQ,OAAO,GAAG,EAG3C,MAAM,IAAI,CAAC,OAAO,QAAQ,CACpB;;EAEvC,cAAc,UAAU,iBAAiB,MAAM;GAC7C,MAAM,WAAW,SAAS,MAAM,IAAI,CAAC,OAAO,QAAQ;AACpD,QAAK,MAAM,SAAS,iBAAiB;IACnC,MAAM,SAAS,wBAAwB,UAAU,MAAM,mBAAmB;AAC1E,QAAI,WAAW,MAAM;KACnB,IAAI,eAAe,mBAAmB;AACtC,SAAI,mBAAmB,MAAM;MAC3B,MAAM,cAAc,OAAO,MAAM;MACjC,MAAM,cAAc,eAAe,MAAM,IAAI,CAAC,OAAO,QAAQ;MAC7D,MAAM,sBAAsB,cACxB,wBAAwB,aAAa,YAAY,aAAa,GAC9D;AACJ,UAAI,wBAAwB,KAC1B,gBAAe;;AAGnB,YAAO;MAAE,GAAG;MAAO,eAAe,mBAAmB,cAAc,OAAO;MAAE;;;AAGhF,UAAO;;EAEV;;AAGH,SAAS,sBACP,QAC8B;CAC9B,MAAM,kBAAgD,EAAE;AACxD,MAAK,IAAI,aAAa,GAAG,aAAa,OAAO,QAAQ,cAAc;EACjE,MAAM,QAAQ,OAAO;AACrB,MAAI,CAAC,MAAM,MAAO;AAClB,OAAK,MAAM,CAAC,SAAS,eAAe,OAAO,QAAQ,MAAM,MAAM,EAAE;AAC/D,OAAI,CAAC,WAAW,WAAY;AAC5B,QAAK,MAAM,aAAa,WAAW,WACjC,iBAAgB,KAAK;IACnB,kBAAkB;IAClB;IACA,eAAe,UAAU;IACzB,oBAAoB,UAAU,cAAc,MAAM,IAAI,CAAC,OAAO,QAAQ;IACtE,kBAAkB,UAAU;IAC5B,MAAM,UAAU;IAChB,QAAQ,UAAU;IACnB,CAAC;;;AAIR,QAAO;;AAGT,SAAgB,wBACd,UACA,cAC0B;AAC1B,QAAO,kBAAkB,UAAU,aAAa;;AAGlD,SAAS,mBACP,cACA,cACmB;AACnB,QAAO,OAAO,OAAO,mBAAmB,EAAE,cAAc,aAAa"}
1
+ {"version":3,"file":"app-rsc-route-matching.js","names":[],"sources":["../../src/server/app-rsc-route-matching.ts"],"sourcesContent":["import { buildRouteTrie, trieMatch } from \"../routing/route-trie.js\";\nimport { matchRoutePattern, type RoutePatternParams } from \"../routing/route-pattern.js\";\nimport { normalizePathnameForRouteMatch } from \"../routing/utils.js\";\n\ntype AppRscRouteParams = RoutePatternParams;\n\ntype AppRscInterceptForMatching = {\n targetPattern: string;\n interceptLayouts: readonly unknown[];\n page: unknown;\n params: readonly string[];\n};\n\ntype AppRscSlotForMatching = {\n intercepts?: readonly AppRscInterceptForMatching[];\n};\n\ntype AppRscRouteForMatching = {\n patternParts: string[];\n slots?: Record<string, AppRscSlotForMatching>;\n};\n\ntype AppRscInterceptMatch = AppRscInterceptLookupEntry & {\n matchedParams: AppRscRouteParams;\n};\n\ntype AppRscInterceptLookupEntry = {\n sourceRouteIndex: number;\n slotKey: string;\n targetPattern: string;\n targetPatternParts: string[];\n interceptLayouts: readonly unknown[];\n page: unknown;\n params: readonly string[];\n};\n\nfunction createRouteParams(): AppRscRouteParams {\n return Object.create(null);\n}\n\nfunction appRscPathnameParts(pathname: string): string[] {\n const pathOnly = pathname.split(\"?\")[0];\n const normalized = pathOnly === \"/\" ? \"/\" : pathOnly.replace(/\\/$/, \"\");\n return normalizePathnameForRouteMatch(normalized).split(\"/\").filter(Boolean);\n}\n\nexport function createAppRscRouteMatcher<Route extends AppRscRouteForMatching>(\n routes: Route[],\n): {\n matchRoute(url: string): { route: Route; params: AppRscRouteParams } | null;\n findIntercept(pathname: string, sourcePathname?: string | null): AppRscInterceptMatch | null;\n} {\n const routeTrie = buildRouteTrie(routes);\n const interceptLookup = createInterceptLookup(routes);\n\n return {\n matchRoute(url) {\n return trieMatch(routeTrie, appRscPathnameParts(url));\n },\n findIntercept(pathname, sourcePathname = null) {\n const urlParts = appRscPathnameParts(pathname);\n for (const entry of interceptLookup) {\n const params = matchAppRscRoutePattern(urlParts, entry.targetPatternParts);\n if (params !== null) {\n let sourceParams = createRouteParams();\n if (sourcePathname !== null) {\n const sourceRoute = routes[entry.sourceRouteIndex];\n const sourceParts = appRscPathnameParts(sourcePathname);\n const matchedSourceParams = sourceRoute\n ? matchAppRscRoutePattern(sourceParts, sourceRoute.patternParts)\n : null;\n if (matchedSourceParams !== null) {\n sourceParams = matchedSourceParams;\n }\n }\n return { ...entry, matchedParams: mergeMatchedParams(sourceParams, params) };\n }\n }\n return null;\n },\n };\n}\n\nfunction createInterceptLookup<Route extends AppRscRouteForMatching>(\n routes: Route[],\n): AppRscInterceptLookupEntry[] {\n const interceptLookup: AppRscInterceptLookupEntry[] = [];\n for (let routeIndex = 0; routeIndex < routes.length; routeIndex++) {\n const route = routes[routeIndex];\n if (!route.slots) continue;\n for (const [slotKey, slotModule] of Object.entries(route.slots)) {\n if (!slotModule.intercepts) continue;\n for (const intercept of slotModule.intercepts) {\n interceptLookup.push({\n sourceRouteIndex: routeIndex,\n slotKey,\n targetPattern: intercept.targetPattern,\n targetPatternParts: intercept.targetPattern.split(\"/\").filter(Boolean),\n interceptLayouts: intercept.interceptLayouts,\n page: intercept.page,\n params: intercept.params,\n });\n }\n }\n }\n return interceptLookup;\n}\n\nexport function matchAppRscRoutePattern(\n urlParts: string[],\n patternParts: string[],\n): AppRscRouteParams | null {\n return matchRoutePattern(urlParts, patternParts);\n}\n\nfunction mergeMatchedParams(\n sourceParams: AppRscRouteParams,\n targetParams: AppRscRouteParams,\n): AppRscRouteParams {\n return Object.assign(createRouteParams(), sourceParams, targetParams);\n}\n"],"mappings":";;;;AAoCA,SAAS,oBAAuC;AAC9C,QAAO,OAAO,OAAO,KAAK;;AAG5B,SAAS,oBAAoB,UAA4B;CACvD,MAAM,WAAW,SAAS,MAAM,IAAI,CAAC;AAErC,QAAO,+BADY,aAAa,MAAM,MAAM,SAAS,QAAQ,OAAO,GAAG,CACtB,CAAC,MAAM,IAAI,CAAC,OAAO,QAAQ;;AAG9E,SAAgB,yBACd,QAIA;CACA,MAAM,YAAY,eAAe,OAAO;CACxC,MAAM,kBAAkB,sBAAsB,OAAO;AAErD,QAAO;EACL,WAAW,KAAK;AACd,UAAO,UAAU,WAAW,oBAAoB,IAAI,CAAC;;EAEvD,cAAc,UAAU,iBAAiB,MAAM;GAC7C,MAAM,WAAW,oBAAoB,SAAS;AAC9C,QAAK,MAAM,SAAS,iBAAiB;IACnC,MAAM,SAAS,wBAAwB,UAAU,MAAM,mBAAmB;AAC1E,QAAI,WAAW,MAAM;KACnB,IAAI,eAAe,mBAAmB;AACtC,SAAI,mBAAmB,MAAM;MAC3B,MAAM,cAAc,OAAO,MAAM;MACjC,MAAM,cAAc,oBAAoB,eAAe;MACvD,MAAM,sBAAsB,cACxB,wBAAwB,aAAa,YAAY,aAAa,GAC9D;AACJ,UAAI,wBAAwB,KAC1B,gBAAe;;AAGnB,YAAO;MAAE,GAAG;MAAO,eAAe,mBAAmB,cAAc,OAAO;MAAE;;;AAGhF,UAAO;;EAEV;;AAGH,SAAS,sBACP,QAC8B;CAC9B,MAAM,kBAAgD,EAAE;AACxD,MAAK,IAAI,aAAa,GAAG,aAAa,OAAO,QAAQ,cAAc;EACjE,MAAM,QAAQ,OAAO;AACrB,MAAI,CAAC,MAAM,MAAO;AAClB,OAAK,MAAM,CAAC,SAAS,eAAe,OAAO,QAAQ,MAAM,MAAM,EAAE;AAC/D,OAAI,CAAC,WAAW,WAAY;AAC5B,QAAK,MAAM,aAAa,WAAW,WACjC,iBAAgB,KAAK;IACnB,kBAAkB;IAClB;IACA,eAAe,UAAU;IACzB,oBAAoB,UAAU,cAAc,MAAM,IAAI,CAAC,OAAO,QAAQ;IACtE,kBAAkB,UAAU;IAC5B,MAAM,UAAU;IAChB,QAAQ,UAAU;IACnB,CAAC;;;AAIR,QAAO;;AAGT,SAAgB,wBACd,UACA,cAC0B;AAC1B,QAAO,kBAAkB,UAAU,aAAa;;AAGlD,SAAS,mBACP,cACA,cACmB;AACnB,QAAO,OAAO,OAAO,mBAAmB,EAAE,cAAc,aAAa"}
@@ -0,0 +1,33 @@
1
+ import { FetchCacheMode } from "../shims/fetch-cache.js";
2
+
3
+ //#region src/server/app-segment-config.d.ts
4
+ type AppRouteSegmentDynamic = "auto" | "error" | "force-dynamic" | "force-static";
5
+ type AppRouteSegmentConfigModule = {
6
+ dynamic?: unknown;
7
+ dynamicParams?: unknown;
8
+ fetchCache?: unknown;
9
+ revalidate?: unknown;
10
+ };
11
+ type EffectiveAppPageSegmentConfig = {
12
+ dynamicConfig?: AppRouteSegmentDynamic;
13
+ dynamicParamsConfig?: boolean;
14
+ fetchCache?: FetchCacheMode;
15
+ revalidateSeconds: number | null;
16
+ };
17
+ type ResolveAppPageSegmentConfigOptions = {
18
+ layouts?: readonly (AppRouteSegmentConfigModule | null | undefined)[];
19
+ page?: AppRouteSegmentConfigModule | null;
20
+ };
21
+ /**
22
+ * Resolve the route segment config that applies to an App page route.
23
+ *
24
+ * Next.js collects config from every segment in the loader tree and reduces it
25
+ * into the effective route config. The generated vinext entry already knows
26
+ * the concrete layout/page modules for a route, so it should only describe
27
+ * those modules and delegate the behavior to this helper.
28
+ */
29
+ declare function resolveAppPageSegmentConfig(options: ResolveAppPageSegmentConfigOptions): EffectiveAppPageSegmentConfig;
30
+ declare function resolveAppPageFetchCacheMode(options: ResolveAppPageSegmentConfigOptions): FetchCacheMode | null;
31
+ //#endregion
32
+ export { resolveAppPageFetchCacheMode, resolveAppPageSegmentConfig };
33
+ //# sourceMappingURL=app-segment-config.d.ts.map
@@ -0,0 +1,90 @@
1
+ //#region src/server/app-segment-config.ts
2
+ const DYNAMIC_VALUES = new Set([
3
+ "auto",
4
+ "error",
5
+ "force-dynamic",
6
+ "force-static"
7
+ ]);
8
+ const FETCH_CACHE_VALUES = new Set([
9
+ "auto",
10
+ "default-cache",
11
+ "default-no-store",
12
+ "force-cache",
13
+ "force-no-store",
14
+ "only-cache",
15
+ "only-no-store"
16
+ ]);
17
+ function isRouteSegmentDynamic(value) {
18
+ return DYNAMIC_VALUES.has(value);
19
+ }
20
+ function isRouteSegmentFetchCache(value) {
21
+ return FETCH_CACHE_VALUES.has(value);
22
+ }
23
+ function resolveRevalidateSeconds(current, value) {
24
+ if (value === false) {
25
+ if (current === null) return Infinity;
26
+ return current === Infinity ? Infinity : current;
27
+ }
28
+ if (typeof value !== "number") return current;
29
+ if (current === null) return value;
30
+ return value < current ? value : current;
31
+ }
32
+ function isCacheFetchCacheMode(value) {
33
+ return value === "default-cache" || value === "force-cache" || value === "only-cache";
34
+ }
35
+ function describeFetchCacheConflict(value) {
36
+ return `Route segment config has incompatible fetchCache values including "${value}".`;
37
+ }
38
+ /**
39
+ * Resolve the route segment config that applies to an App page route.
40
+ *
41
+ * Next.js collects config from every segment in the loader tree and reduces it
42
+ * into the effective route config. The generated vinext entry already knows
43
+ * the concrete layout/page modules for a route, so it should only describe
44
+ * those modules and delegate the behavior to this helper.
45
+ */
46
+ function resolveAppPageSegmentConfig(options) {
47
+ const segments = [...options.layouts ?? [], options.page];
48
+ const config = { revalidateSeconds: null };
49
+ let hasForceCache = false;
50
+ let hasForceNoStore = false;
51
+ let hasOnlyCache = false;
52
+ let hasOnlyNoStore = false;
53
+ let hasParentDefaultNoStore = false;
54
+ for (const segment of segments) {
55
+ if (!segment) continue;
56
+ if (isRouteSegmentDynamic(segment.dynamic)) config.dynamicConfig = segment.dynamic;
57
+ if (segment.dynamicParams === false) config.dynamicParamsConfig = false;
58
+ else if (segment.dynamicParams === true && config.dynamicParamsConfig !== false) config.dynamicParamsConfig = true;
59
+ if (isRouteSegmentFetchCache(segment.fetchCache)) {
60
+ const fetchCache = segment.fetchCache;
61
+ if (hasParentDefaultNoStore && (fetchCache === "auto" || isCacheFetchCacheMode(fetchCache))) throw new Error(describeFetchCacheConflict(fetchCache));
62
+ if (fetchCache === "force-cache") hasForceCache = true;
63
+ if (fetchCache === "force-no-store") hasForceNoStore = true;
64
+ if (fetchCache === "only-cache") hasOnlyCache = true;
65
+ if (fetchCache === "only-no-store") hasOnlyNoStore = true;
66
+ if ((hasForceCache || hasOnlyCache) && (hasForceNoStore || hasOnlyNoStore)) throw new Error(describeFetchCacheConflict(fetchCache));
67
+ if (fetchCache === "default-no-store") hasParentDefaultNoStore = true;
68
+ if (hasForceCache) config.fetchCache = "force-cache";
69
+ else if (hasForceNoStore) config.fetchCache = "force-no-store";
70
+ else if (hasOnlyCache) config.fetchCache = "only-cache";
71
+ else if (hasOnlyNoStore) config.fetchCache = "only-no-store";
72
+ else config.fetchCache = fetchCache;
73
+ }
74
+ config.revalidateSeconds = resolveRevalidateSeconds(config.revalidateSeconds, segment.revalidate);
75
+ }
76
+ if (config.dynamicConfig === "force-dynamic") config.revalidateSeconds = 0;
77
+ if (config.fetchCache === void 0) {
78
+ if (config.dynamicConfig === "force-dynamic") config.fetchCache = "force-no-store";
79
+ else if (config.dynamicConfig === "error") config.fetchCache = "only-cache";
80
+ }
81
+ if (config.dynamicParamsConfig === void 0 && (config.dynamicConfig === "error" || config.dynamicConfig === "force-static")) config.dynamicParamsConfig = false;
82
+ return config;
83
+ }
84
+ function resolveAppPageFetchCacheMode(options) {
85
+ return resolveAppPageSegmentConfig(options).fetchCache ?? null;
86
+ }
87
+ //#endregion
88
+ export { resolveAppPageFetchCacheMode, resolveAppPageSegmentConfig };
89
+
90
+ //# sourceMappingURL=app-segment-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-segment-config.js","names":[],"sources":["../../src/server/app-segment-config.ts"],"sourcesContent":["import type { FetchCacheMode } from \"vinext/shims/fetch-cache\";\n\ntype AppRouteSegmentDynamic = \"auto\" | \"error\" | \"force-dynamic\" | \"force-static\";\n\ntype AppRouteSegmentConfigModule = {\n dynamic?: unknown;\n dynamicParams?: unknown;\n fetchCache?: unknown;\n revalidate?: unknown;\n};\n\ntype EffectiveAppPageSegmentConfig = {\n dynamicConfig?: AppRouteSegmentDynamic;\n dynamicParamsConfig?: boolean;\n fetchCache?: FetchCacheMode;\n revalidateSeconds: number | null;\n};\n\ntype ResolveAppPageSegmentConfigOptions = {\n layouts?: readonly (AppRouteSegmentConfigModule | null | undefined)[];\n page?: AppRouteSegmentConfigModule | null;\n};\n\nconst DYNAMIC_VALUES = new Set<unknown>([\"auto\", \"error\", \"force-dynamic\", \"force-static\"]);\nconst FETCH_CACHE_VALUES = new Set<unknown>([\n \"auto\",\n \"default-cache\",\n \"default-no-store\",\n \"force-cache\",\n \"force-no-store\",\n \"only-cache\",\n \"only-no-store\",\n]);\n\nfunction isRouteSegmentDynamic(value: unknown): value is AppRouteSegmentDynamic {\n return DYNAMIC_VALUES.has(value);\n}\n\nfunction isRouteSegmentFetchCache(value: unknown): value is FetchCacheMode {\n return FETCH_CACHE_VALUES.has(value);\n}\n\nfunction resolveRevalidateSeconds(current: number | null, value: unknown): number | null {\n // revalidate = false means \"cache indefinitely\" in Next.js segment config.\n // Represent it as Infinity so downstream code can distinguish \"never\n // revalidate\" (Infinity) from \"no config / unset\" (null).\n if (value === false) {\n if (current === null) return Infinity;\n // Shortest-wins: any finite interval is shorter than Infinity.\n return current === Infinity ? Infinity : current;\n }\n\n if (typeof value !== \"number\") {\n return current;\n }\n\n if (current === null) {\n return value;\n }\n\n return value < current ? value : current;\n}\n\nfunction isCacheFetchCacheMode(value: FetchCacheMode): boolean {\n return value === \"default-cache\" || value === \"force-cache\" || value === \"only-cache\";\n}\n\nfunction describeFetchCacheConflict(value: FetchCacheMode): string {\n return `Route segment config has incompatible fetchCache values including \"${value}\".`;\n}\n\n/**\n * Resolve the route segment config that applies to an App page route.\n *\n * Next.js collects config from every segment in the loader tree and reduces it\n * into the effective route config. The generated vinext entry already knows\n * the concrete layout/page modules for a route, so it should only describe\n * those modules and delegate the behavior to this helper.\n */\nexport function resolveAppPageSegmentConfig(\n options: ResolveAppPageSegmentConfigOptions,\n): EffectiveAppPageSegmentConfig {\n const segments = [...(options.layouts ?? []), options.page];\n // Reduction strategies differ by field:\n // - dynamic: child segments override parents.\n // - dynamicParams: false is sticky across the route tree.\n // - fetchCache: force/only modes take route-level precedence and reject conflicts.\n // - revalidate: the shortest numeric interval wins.\n const config: EffectiveAppPageSegmentConfig = {\n revalidateSeconds: null,\n };\n let hasForceCache = false;\n let hasForceNoStore = false;\n let hasOnlyCache = false;\n let hasOnlyNoStore = false;\n let hasParentDefaultNoStore = false;\n\n for (const segment of segments) {\n if (!segment) continue;\n\n if (isRouteSegmentDynamic(segment.dynamic)) {\n config.dynamicConfig = segment.dynamic;\n }\n\n if (segment.dynamicParams === false) {\n config.dynamicParamsConfig = false;\n } else if (segment.dynamicParams === true && config.dynamicParamsConfig !== false) {\n config.dynamicParamsConfig = true;\n }\n\n if (isRouteSegmentFetchCache(segment.fetchCache)) {\n const fetchCache = segment.fetchCache;\n\n if (hasParentDefaultNoStore && (fetchCache === \"auto\" || isCacheFetchCacheMode(fetchCache))) {\n throw new Error(describeFetchCacheConflict(fetchCache));\n }\n\n if (fetchCache === \"force-cache\") hasForceCache = true;\n if (fetchCache === \"force-no-store\") hasForceNoStore = true;\n if (fetchCache === \"only-cache\") hasOnlyCache = true;\n if (fetchCache === \"only-no-store\") hasOnlyNoStore = true;\n\n const hasCacheEnforcer = hasForceCache || hasOnlyCache;\n const hasNoStoreEnforcer = hasForceNoStore || hasOnlyNoStore;\n if (hasCacheEnforcer && hasNoStoreEnforcer) {\n throw new Error(describeFetchCacheConflict(fetchCache));\n }\n\n if (fetchCache === \"default-no-store\") {\n hasParentDefaultNoStore = true;\n }\n\n if (hasForceCache) {\n config.fetchCache = \"force-cache\";\n } else if (hasForceNoStore) {\n config.fetchCache = \"force-no-store\";\n } else if (hasOnlyCache) {\n config.fetchCache = \"only-cache\";\n } else if (hasOnlyNoStore) {\n config.fetchCache = \"only-no-store\";\n } else {\n config.fetchCache = fetchCache;\n }\n }\n\n config.revalidateSeconds = resolveRevalidateSeconds(\n config.revalidateSeconds,\n segment.revalidate,\n );\n }\n\n if (config.dynamicConfig === \"force-dynamic\") {\n config.revalidateSeconds = 0;\n }\n\n // Top-level dynamic modes supply fetchCache defaults unless a segment does.\n if (config.fetchCache === undefined) {\n if (config.dynamicConfig === \"force-dynamic\") {\n config.fetchCache = \"force-no-store\";\n } else if (config.dynamicConfig === \"error\") {\n config.fetchCache = \"only-cache\";\n }\n }\n\n // Static-only dynamic modes change the default, but explicit dynamicParams wins.\n if (\n config.dynamicParamsConfig === undefined &&\n (config.dynamicConfig === \"error\" || config.dynamicConfig === \"force-static\")\n ) {\n config.dynamicParamsConfig = false;\n }\n\n return config;\n}\n\nexport function resolveAppPageFetchCacheMode(\n options: ResolveAppPageSegmentConfigOptions,\n): FetchCacheMode | null {\n return resolveAppPageSegmentConfig(options).fetchCache ?? null;\n}\n"],"mappings":";AAuBA,MAAM,iBAAiB,IAAI,IAAa;CAAC;CAAQ;CAAS;CAAiB;CAAe,CAAC;AAC3F,MAAM,qBAAqB,IAAI,IAAa;CAC1C;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,SAAS,sBAAsB,OAAiD;AAC9E,QAAO,eAAe,IAAI,MAAM;;AAGlC,SAAS,yBAAyB,OAAyC;AACzE,QAAO,mBAAmB,IAAI,MAAM;;AAGtC,SAAS,yBAAyB,SAAwB,OAA+B;AAIvF,KAAI,UAAU,OAAO;AACnB,MAAI,YAAY,KAAM,QAAO;AAE7B,SAAO,YAAY,WAAW,WAAW;;AAG3C,KAAI,OAAO,UAAU,SACnB,QAAO;AAGT,KAAI,YAAY,KACd,QAAO;AAGT,QAAO,QAAQ,UAAU,QAAQ;;AAGnC,SAAS,sBAAsB,OAAgC;AAC7D,QAAO,UAAU,mBAAmB,UAAU,iBAAiB,UAAU;;AAG3E,SAAS,2BAA2B,OAA+B;AACjE,QAAO,sEAAsE,MAAM;;;;;;;;;;AAWrF,SAAgB,4BACd,SAC+B;CAC/B,MAAM,WAAW,CAAC,GAAI,QAAQ,WAAW,EAAE,EAAG,QAAQ,KAAK;CAM3D,MAAM,SAAwC,EAC5C,mBAAmB,MACpB;CACD,IAAI,gBAAgB;CACpB,IAAI,kBAAkB;CACtB,IAAI,eAAe;CACnB,IAAI,iBAAiB;CACrB,IAAI,0BAA0B;AAE9B,MAAK,MAAM,WAAW,UAAU;AAC9B,MAAI,CAAC,QAAS;AAEd,MAAI,sBAAsB,QAAQ,QAAQ,CACxC,QAAO,gBAAgB,QAAQ;AAGjC,MAAI,QAAQ,kBAAkB,MAC5B,QAAO,sBAAsB;WACpB,QAAQ,kBAAkB,QAAQ,OAAO,wBAAwB,MAC1E,QAAO,sBAAsB;AAG/B,MAAI,yBAAyB,QAAQ,WAAW,EAAE;GAChD,MAAM,aAAa,QAAQ;AAE3B,OAAI,4BAA4B,eAAe,UAAU,sBAAsB,WAAW,EACxF,OAAM,IAAI,MAAM,2BAA2B,WAAW,CAAC;AAGzD,OAAI,eAAe,cAAe,iBAAgB;AAClD,OAAI,eAAe,iBAAkB,mBAAkB;AACvD,OAAI,eAAe,aAAc,gBAAe;AAChD,OAAI,eAAe,gBAAiB,kBAAiB;AAIrD,QAFyB,iBAAiB,kBACf,mBAAmB,gBAE5C,OAAM,IAAI,MAAM,2BAA2B,WAAW,CAAC;AAGzD,OAAI,eAAe,mBACjB,2BAA0B;AAG5B,OAAI,cACF,QAAO,aAAa;YACX,gBACT,QAAO,aAAa;YACX,aACT,QAAO,aAAa;YACX,eACT,QAAO,aAAa;OAEpB,QAAO,aAAa;;AAIxB,SAAO,oBAAoB,yBACzB,OAAO,mBACP,QAAQ,WACT;;AAGH,KAAI,OAAO,kBAAkB,gBAC3B,QAAO,oBAAoB;AAI7B,KAAI,OAAO,eAAe,KAAA;MACpB,OAAO,kBAAkB,gBAC3B,QAAO,aAAa;WACX,OAAO,kBAAkB,QAClC,QAAO,aAAa;;AAKxB,KACE,OAAO,wBAAwB,KAAA,MAC9B,OAAO,kBAAkB,WAAW,OAAO,kBAAkB,gBAE9D,QAAO,sBAAsB;AAG/B,QAAO;;AAGT,SAAgB,6BACd,SACuB;AACvB,QAAO,4BAA4B,QAAQ,CAAC,cAAc"}
@@ -1,3 +1,4 @@
1
+ import { FetchCacheMode } from "../shims/fetch-cache.js";
1
2
  import { HeadersAccessPhase } from "../shims/headers.js";
2
3
 
3
4
  //#region src/server/app-server-action-execution.d.ts
@@ -99,6 +100,7 @@ type HandleServerActionRscRequestOptions<TElement, TRoute extends AppServerActio
99
100
  readFormDataWithLimit: ReadFormDataWithLimit;
100
101
  renderToReadableStream: (model: AppServerActionRscModel<TElement>, options: RenderServerActionRscStreamOptions<TTemporaryReferences>) => BodyInit | null | Promise<BodyInit | null>;
101
102
  reportRequestError: AppServerActionErrorReporter;
103
+ resolveRouteFetchCacheMode?: (route: TRoute) => FetchCacheMode | null;
102
104
  request: Request;
103
105
  sanitizeErrorForClient: (error: unknown) => unknown;
104
106
  searchParams: URLSearchParams;
@@ -1,8 +1,18 @@
1
+ import { internalServerErrorResponse, payloadTooLargeResponse } from "./http-error-responses.js";
1
2
  import { validateCsrfOrigin, validateServerActionPayload } from "./request-pipeline.js";
3
+ import { setCurrentFetchCacheMode } from "../shims/fetch-cache.js";
4
+ import { VINEXT_RSC_VARY_HEADER } from "./app-rsc-cache-busting.js";
2
5
  import { createServerActionNotFoundResponse, getServerActionNotFoundMessage, isServerActionNotFoundError } from "./server-action-not-found.js";
3
6
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
7
+ import { readStreamAsTextWithLimit } from "../utils/text-stream.js";
8
+ import { getNextErrorDigest, parseNextHttpErrorDigest, parseNextRedirectDigest } from "./next-error-digest.js";
4
9
  import { resolveAppPageActionRerenderTarget } from "./app-page-request.js";
5
10
  //#region src/server/app-server-action-execution.ts
11
+ /**
12
+ * Matches Next.js' server action argument cap to prevent stack overflow in
13
+ * Function.prototype.apply when decoding hostile action payloads.
14
+ */
15
+ const SERVER_ACTION_ARGS_LIMIT = 1e3;
6
16
  function isRequestBodyTooLarge(error) {
7
17
  return error instanceof Error && error.message === "Request body too large";
8
18
  }
@@ -15,24 +25,14 @@ function normalizeError(error) {
15
25
  function getServerActionFailureMessage(error) {
16
26
  return error instanceof Error && error.message ? error.message : String(error);
17
27
  }
28
+ function validateServerActionArgs(args) {
29
+ if (args.length > SERVER_ACTION_ARGS_LIMIT) throw new Error(`Server Action arguments list is too long (${args.length}). Maximum allowed is ${SERVER_ACTION_ARGS_LIMIT}.`);
30
+ }
18
31
  async function readActionBodyWithLimit(request, maxBytes) {
19
32
  if (!request.body) return "";
20
- const reader = request.body.getReader();
21
- const decoder = new TextDecoder();
22
- const chunks = [];
23
- let totalSize = 0;
24
- for (;;) {
25
- const result = await reader.read();
26
- if (result.done) break;
27
- totalSize += result.value.byteLength;
28
- if (totalSize > maxBytes) {
29
- await reader.cancel();
30
- throw new Error("Request body too large");
31
- }
32
- chunks.push(decoder.decode(result.value, { stream: true }));
33
- }
34
- chunks.push(decoder.decode());
35
- return chunks.join("");
33
+ return readStreamAsTextWithLimit(request.body, maxBytes, () => {
34
+ throw new Error("Request body too large");
35
+ });
36
36
  }
37
37
  async function readActionFormDataWithLimit(request, maxBytes) {
38
38
  if (!request.body) return new FormData();
@@ -57,46 +57,38 @@ async function readActionFormDataWithLimit(request, maxBytes) {
57
57
  }
58
58
  return new Response(combined, { headers: { "Content-Type": request.headers.get("content-type") || "" } }).formData();
59
59
  }
60
- function getErrorDigest(error) {
61
- if (!error || typeof error !== "object" || !("digest" in error)) return null;
62
- return String(error.digest);
63
- }
64
60
  function getActionControlResponse(error) {
65
- const digest = getErrorDigest(error);
61
+ const digest = getNextErrorDigest(error);
66
62
  if (!digest) return null;
67
- if (digest.startsWith("NEXT_REDIRECT;")) {
68
- const encodedUrl = digest.split(";")[2];
69
- if (!encodedUrl) return null;
70
- return {
71
- kind: "redirect",
72
- url: decodeURIComponent(encodedUrl)
73
- };
74
- }
75
- if (digest === "NEXT_NOT_FOUND" || digest.startsWith("NEXT_HTTP_ERROR_FALLBACK;")) {
76
- const statusCode = digest === "NEXT_NOT_FOUND" ? 404 : parseInt(digest.split(";")[1], 10);
77
- if (!Number.isInteger(statusCode)) return null;
63
+ const redirect = parseNextRedirectDigest(digest);
64
+ if (redirect) return {
65
+ kind: "redirect",
66
+ url: redirect.url
67
+ };
68
+ const httpError = parseNextHttpErrorDigest(digest);
69
+ if (httpError) {
70
+ if (!Number.isInteger(httpError.status)) return null;
78
71
  return {
79
72
  kind: "status",
80
- statusCode
73
+ statusCode: httpError.status
81
74
  };
82
75
  }
83
76
  return null;
84
77
  }
85
78
  function getActionRedirect(error) {
86
- const digest = getErrorDigest(error);
87
- if (!digest?.startsWith("NEXT_REDIRECT;")) return null;
88
- const parts = digest.split(";");
89
- const encodedUrl = parts[2];
90
- if (!encodedUrl) return null;
79
+ const digest = getNextErrorDigest(error);
80
+ if (!digest) return null;
81
+ const redirect = parseNextRedirectDigest(digest);
82
+ if (!redirect) return null;
91
83
  return {
92
- status: parts[3] ? parseInt(parts[3], 10) : 307,
93
- type: parts[1] || "push",
94
- url: decodeURIComponent(encodedUrl)
84
+ status: redirect.status,
85
+ type: redirect.type,
86
+ url: redirect.url
95
87
  };
96
88
  }
97
89
  function isActionHttpFallback(error) {
98
- const digest = getErrorDigest(error);
99
- return digest === "NEXT_NOT_FOUND" || digest?.startsWith("NEXT_HTTP_ERROR_FALLBACK;") === true;
90
+ const digest = getNextErrorDigest(error);
91
+ return digest !== null && parseNextHttpErrorDigest(digest) !== null;
100
92
  }
101
93
  function createServerActionErrorResponse(error, options) {
102
94
  options.getAndClearPendingCookies();
@@ -111,7 +103,7 @@ function createServerActionErrorResponse(error, options) {
111
103
  routeType: "action"
112
104
  });
113
105
  options.clearRequestContext();
114
- return new Response(process.env.NODE_ENV === "production" ? "Internal Server Error" : "Server action failed: " + getServerActionFailureMessage(error), { status: 500 });
106
+ return internalServerErrorResponse(process.env.NODE_ENV === "production" ? void 0 : "Server action failed: " + getServerActionFailureMessage(error));
115
107
  }
116
108
  function createActionNotFoundResponse(actionId, options) {
117
109
  options.getAndClearPendingCookies();
@@ -128,7 +120,7 @@ async function handleProgressiveServerActionRequest(options) {
128
120
  if (csrfResponse) return csrfResponse;
129
121
  if (parseInt(options.request.headers.get("content-length") || "0", 10) > options.maxActionBodySize) {
130
122
  options.clearRequestContext();
131
- return new Response("Payload Too Large", { status: 413 });
123
+ return payloadTooLargeResponse();
132
124
  }
133
125
  try {
134
126
  let body;
@@ -137,7 +129,7 @@ async function handleProgressiveServerActionRequest(options) {
137
129
  } catch (error) {
138
130
  if (isRequestBodyTooLarge(error)) {
139
131
  options.clearRequestContext();
140
- return new Response("Payload Too Large", { status: 413 });
132
+ return payloadTooLargeResponse();
141
133
  }
142
134
  throw error;
143
135
  }
@@ -188,7 +180,7 @@ async function handleProgressiveServerActionRequest(options) {
188
180
  routeType: "action"
189
181
  });
190
182
  options.clearRequestContext();
191
- return new Response(process.env.NODE_ENV === "production" ? "Internal Server Error" : "Server action failed: " + getServerActionFailureMessage(error), { status: 500 });
183
+ return internalServerErrorResponse(process.env.NODE_ENV === "production" ? void 0 : "Server action failed: " + getServerActionFailureMessage(error));
192
184
  }
193
185
  }
194
186
  async function handleServerActionRscRequest(options) {
@@ -197,7 +189,7 @@ async function handleServerActionRscRequest(options) {
197
189
  if (csrfResponse) return csrfResponse;
198
190
  if (parseInt(options.request.headers.get("content-length") || "0", 10) > options.maxActionBodySize) {
199
191
  options.clearRequestContext();
200
- return new Response("Payload Too Large", { status: 413 });
192
+ return payloadTooLargeResponse();
201
193
  }
202
194
  try {
203
195
  let body;
@@ -206,7 +198,7 @@ async function handleServerActionRscRequest(options) {
206
198
  } catch (error) {
207
199
  if (isRequestBodyTooLarge(error)) {
208
200
  options.clearRequestContext();
209
- return new Response("Payload Too Large", { status: 413 });
201
+ return payloadTooLargeResponse();
210
202
  }
211
203
  throw error;
212
204
  }
@@ -236,6 +228,7 @@ async function handleServerActionRscRequest(options) {
236
228
  const previousHeadersPhase = options.setHeadersAccessPhase("action");
237
229
  try {
238
230
  try {
231
+ validateServerActionArgs(args);
239
232
  returnValue = {
240
233
  ok: true,
241
234
  data: await action.apply(null, args)
@@ -267,7 +260,7 @@ async function handleServerActionRscRequest(options) {
267
260
  options.clearRequestContext();
268
261
  const redirectHeaders = new Headers({
269
262
  "Content-Type": "text/x-component; charset=utf-8",
270
- Vary: "RSC, Accept"
263
+ Vary: VINEXT_RSC_VARY_HEADER
271
264
  });
272
265
  mergeMiddlewareResponseHeaders(redirectHeaders, options.middlewareHeaders);
273
266
  redirectHeaders.set("x-action-redirect", actionRedirect.url);
@@ -300,6 +293,7 @@ async function handleServerActionRscRequest(options) {
300
293
  searchParams: options.searchParams,
301
294
  params: actionRerenderTarget.navigationParams
302
295
  });
296
+ setCurrentFetchCacheMode(options.resolveRouteFetchCacheMode?.(actionRerenderTarget.route) ?? null);
303
297
  element = options.buildPageElement({
304
298
  cleanPathname: options.cleanPathname,
305
299
  interceptOpts: actionRerenderTarget.interceptOpts,
@@ -327,7 +321,7 @@ async function handleServerActionRscRequest(options) {
327
321
  const actionDraftCookie = options.getDraftModeCookieHeader();
328
322
  const actionHeaders = new Headers({
329
323
  "Content-Type": "text/x-component; charset=utf-8",
330
- Vary: "RSC, Accept"
324
+ Vary: VINEXT_RSC_VARY_HEADER
331
325
  });
332
326
  mergeMiddlewareResponseHeaders(actionHeaders, options.middlewareHeaders);
333
327
  const actionResponse = new Response(rscStream, {
@@ -1 +1 @@
1
- {"version":3,"file":"app-server-action-execution.js","names":[],"sources":["../../src/server/app-server-action-execution.ts"],"sourcesContent":["import type { HeadersAccessPhase } from \"vinext/shims/headers\";\nimport { resolveAppPageActionRerenderTarget } from \"./app-page-request.js\";\nimport { mergeMiddlewareResponseHeaders } from \"./middleware-response-headers.js\";\nimport { validateCsrfOrigin, validateServerActionPayload } from \"./request-pipeline.js\";\nimport {\n createServerActionNotFoundResponse,\n getServerActionNotFoundMessage,\n isServerActionNotFoundError,\n} from \"./server-action-not-found.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>;\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 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};\n\ntype AppServerActionRscModel<TElement> = {\n returnValue: AppServerActionReturnValue;\n root: TElement;\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 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 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\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\nexport async function readActionBodyWithLimit(request: Request, maxBytes: number): Promise<string> {\n if (!request.body) return \"\";\n\n const reader = request.body.getReader();\n const decoder = new TextDecoder();\n const chunks: string[] = [];\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(decoder.decode(result.value, { stream: true }));\n }\n\n chunks.push(decoder.decode());\n return chunks.join(\"\");\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 getErrorDigest(error: unknown): string | null {\n if (!error || typeof error !== \"object\" || !(\"digest\" in error)) {\n return null;\n }\n\n return String(error.digest);\n}\n\nfunction getActionControlResponse(error: unknown): ActionControlResponse | null {\n const digest = getErrorDigest(error);\n if (!digest) return null;\n\n if (digest.startsWith(\"NEXT_REDIRECT;\")) {\n const parts = digest.split(\";\");\n const encodedUrl = parts[2];\n if (!encodedUrl) {\n return null;\n }\n\n return {\n kind: \"redirect\",\n url: decodeURIComponent(encodedUrl),\n };\n }\n\n if (digest === \"NEXT_NOT_FOUND\" || digest.startsWith(\"NEXT_HTTP_ERROR_FALLBACK;\")) {\n const statusCode = digest === \"NEXT_NOT_FOUND\" ? 404 : parseInt(digest.split(\";\")[1], 10);\n if (!Number.isInteger(statusCode)) {\n return null;\n }\n\n return {\n kind: \"status\",\n statusCode,\n };\n }\n\n return null;\n}\n\nfunction getActionRedirect(error: unknown): AppServerActionRedirect | null {\n const digest = getErrorDigest(error);\n if (!digest?.startsWith(\"NEXT_REDIRECT;\")) {\n return null;\n }\n\n const parts = digest.split(\";\");\n const encodedUrl = parts[2];\n if (!encodedUrl) {\n return null;\n }\n\n return {\n status: parts[3] ? parseInt(parts[3], 10) : 307,\n type: parts[1] || \"push\",\n url: decodeURIComponent(encodedUrl),\n };\n}\n\nfunction isActionHttpFallback(error: unknown): boolean {\n const digest = getErrorDigest(error);\n return digest === \"NEXT_NOT_FOUND\" || digest?.startsWith(\"NEXT_HTTP_ERROR_FALLBACK;\") === true;\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 new Response(\n process.env.NODE_ENV === \"production\"\n ? \"Internal Server Error\"\n : \"Server action failed: \" + getServerActionFailureMessage(error),\n { status: 500 },\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 | 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 new Response(\"Payload Too Large\", { status: 413 });\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 new Response(\"Payload Too Large\", { status: 413 });\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 (typeof action !== \"function\") {\n return null;\n }\n\n let actionControlResponse: ActionControlResponse | null = null;\n const previousHeadersPhase = options.setHeadersAccessPhase(\"action\");\n try {\n 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 // Next.js decodes form state and re-renders after a successful MPA action.\n // vinext currently supports the redirect/error status cases; successful\n // non-redirect actions intentionally fall through to the page render.\n return null;\n }\n\n const actionPendingCookies = options.getAndClearPendingCookies();\n const actionDraftCookie = options.getDraftModeCookieHeader();\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\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 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 new Response(\n process.env.NODE_ENV === \"production\"\n ? \"Internal Server Error\"\n : \"Server action failed: \" + getServerActionFailureMessage(error),\n { status: 500 },\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 new Response(\"Payload Too Large\", { status: 413 });\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 new Response(\"Payload Too Large\", { status: 413 });\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 const previousHeadersPhase = options.setHeadersAccessPhase(\"action\");\n try {\n try {\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 if (isActionHttpFallback(error)) {\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 } finally {\n options.setHeadersAccessPhase(previousHeadersPhase);\n }\n\n if (actionRedirect) {\n const actionPendingCookies = options.getAndClearPendingCookies();\n const actionDraftCookie = options.getDraftModeCookieHeader();\n options.clearRequestContext();\n const redirectHeaders = new Headers({\n \"Content-Type\": \"text/x-component; charset=utf-8\",\n Vary: \"RSC, Accept\",\n });\n mergeMiddlewareResponseHeaders(redirectHeaders, options.middlewareHeaders);\n redirectHeaders.set(\"x-action-redirect\", actionRedirect.url);\n redirectHeaders.set(\"x-action-redirect-type\", actionRedirect.type);\n redirectHeaders.set(\"x-action-redirect-status\", 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 return new Response(\"\", { status: 200, headers: redirectHeaders });\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 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 });\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 actionPendingCookies = options.getAndClearPendingCookies();\n const actionDraftCookie = options.getDraftModeCookieHeader();\n\n const actionHeaders = new Headers({\n \"Content-Type\": \"text/x-component; charset=utf-8\",\n Vary: \"RSC, Accept\",\n });\n mergeMiddlewareResponseHeaders(actionHeaders, options.middlewareHeaders);\n const actionResponse = new Response(rscStream, {\n status: options.middlewareStatus ?? 200,\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 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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"}
1
+ {"version":3,"file":"app-server-action-execution.js","names":[],"sources":["../../src/server/app-server-action-execution.ts"],"sourcesContent":["import type { HeadersAccessPhase } from \"vinext/shims/headers\";\nimport { type FetchCacheMode, setCurrentFetchCacheMode } from \"vinext/shims/fetch-cache\";\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 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>;\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 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};\n\ntype AppServerActionRscModel<TElement> = {\n returnValue: AppServerActionReturnValue;\n root: TElement;\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 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;\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,\n url: redirect.url,\n };\n}\n\nfunction isActionHttpFallback(error: unknown): boolean {\n const digest = getNextErrorDigest(error);\n return digest !== null && parseNextHttpErrorDigest(digest) !== null;\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 | 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 (typeof action !== \"function\") {\n return null;\n }\n\n let actionControlResponse: ActionControlResponse | null = null;\n const previousHeadersPhase = options.setHeadersAccessPhase(\"action\");\n try {\n 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 // Next.js decodes form state and re-renders after a successful MPA action.\n // vinext currently supports the redirect/error status cases; successful\n // non-redirect actions intentionally fall through to the page render.\n return null;\n }\n\n const actionPendingCookies = options.getAndClearPendingCookies();\n const actionDraftCookie = options.getDraftModeCookieHeader();\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\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 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 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 if (isActionHttpFallback(error)) {\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 } finally {\n options.setHeadersAccessPhase(previousHeadersPhase);\n }\n\n if (actionRedirect) {\n const actionPendingCookies = options.getAndClearPendingCookies();\n const actionDraftCookie = options.getDraftModeCookieHeader();\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(\"x-action-redirect\", actionRedirect.url);\n redirectHeaders.set(\"x-action-redirect-type\", actionRedirect.type);\n redirectHeaders.set(\"x-action-redirect-status\", 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 return new Response(\"\", { status: 200, headers: redirectHeaders });\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 });\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 actionPendingCookies = options.getAndClearPendingCookies();\n const actionDraftCookie = options.getDraftModeCookieHeader();\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 const actionResponse = new Response(rscStream, {\n status: options.middlewareStatus ?? 200,\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 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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"}