@farm.js/core 0.1.31 → 0.1.35

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 (352) hide show
  1. package/README.md +1 -1
  2. package/dist/agent-runtime.cjs +70 -15
  3. package/dist/agent-runtime.d.mts +4 -5
  4. package/dist/agent-runtime.d.ts +4 -5
  5. package/dist/agent-runtime.mjs +59 -4
  6. package/dist/api/route-manager.cjs +17 -14
  7. package/dist/api/route-manager.d.mts +6 -7
  8. package/dist/api/route-manager.d.ts +6 -7
  9. package/dist/api/route-manager.mjs +16 -13
  10. package/dist/api/runtime.cjs +12 -8
  11. package/dist/api/runtime.d.mts +4 -5
  12. package/dist/api/runtime.d.ts +4 -5
  13. package/dist/api/runtime.mjs +12 -8
  14. package/dist/api.cjs +20 -17
  15. package/dist/api.d.mts +7 -8
  16. package/dist/api.d.ts +7 -8
  17. package/dist/api.mjs +19 -16
  18. package/dist/{app-sUJ3jnTZ.d.ts → app-BXB3JZYc.d.ts} +38 -12
  19. package/dist/{app-DAuUTIZf.d.mts → app-D_j9AAVL.d.mts} +38 -12
  20. package/dist/app-markdown.cjs +8 -6
  21. package/dist/app-markdown.d.mts +6 -7
  22. package/dist/app-markdown.d.ts +6 -7
  23. package/dist/app-markdown.mjs +7 -5
  24. package/dist/cache.cjs +2 -2
  25. package/dist/cache.d.mts +10 -1
  26. package/dist/cache.d.ts +10 -1
  27. package/dist/cache.mjs +1 -1
  28. package/dist/{chunk-BXFWA23T.mjs → chunk-22LTEMGQ.mjs} +3 -3
  29. package/dist/{chunk-YZTASLPQ.cjs → chunk-27ZWSI3W.cjs} +2 -2
  30. package/dist/{chunk-WBIH66JK.mjs → chunk-2ELDTQRN.mjs} +5 -2
  31. package/dist/{chunk-K7CELQLK.cjs → chunk-2F2ER724.cjs} +54 -29
  32. package/dist/{chunk-O3DTUAX2.mjs → chunk-2G2NNLE2.mjs} +6 -77
  33. package/dist/{chunk-NRVGEI5I.mjs → chunk-2NNMOPDN.mjs} +4 -210
  34. package/dist/{chunk-CTV2TTNP.cjs → chunk-3BHT4WMP.cjs} +16 -87
  35. package/dist/chunk-3BU22U3M.cjs +237 -0
  36. package/dist/{chunk-MM5D6VLP.mjs → chunk-3KZS4SUS.mjs} +33 -14
  37. package/dist/{chunk-VA62MHFV.mjs → chunk-3PXS2MHU.mjs} +1 -1
  38. package/dist/chunk-3SDFA7UF.cjs +701 -0
  39. package/dist/{chunk-4IEPYMHF.mjs → chunk-3UEVPCGW.mjs} +1 -1
  40. package/dist/{chunk-MXDTKXO6.cjs → chunk-3UH7MRCP.cjs} +73 -26
  41. package/dist/{chunk-7QOCTYBS.mjs → chunk-4JHOT46A.mjs} +37 -1
  42. package/dist/{chunk-6L6DQR5W.mjs → chunk-4KU5Q7C2.mjs} +917 -305
  43. package/dist/{chunk-3FCFQP5V.cjs → chunk-4MMGO7YW.cjs} +25 -25
  44. package/dist/{chunk-5HGR3W6O.mjs → chunk-5SJWVY6R.mjs} +8 -0
  45. package/dist/{chunk-KZLND3D2.cjs → chunk-62XKI4Z3.cjs} +7 -5
  46. package/dist/{chunk-FJZ3DQLK.mjs → chunk-6DU6UFUE.mjs} +13 -12
  47. package/dist/{chunk-TEN4FIZU.mjs → chunk-6ETPZTJI.mjs} +513 -3
  48. package/dist/{chunk-VUMAE7NC.mjs → chunk-6TJOML4E.mjs} +92 -31
  49. package/dist/{chunk-3ATMYLLJ.mjs → chunk-6WCPV6G2.mjs} +1 -1
  50. package/dist/{chunk-FYRBX5IY.cjs → chunk-73MC7ZL6.cjs} +2 -2
  51. package/dist/chunk-75RZHGLS.cjs +135 -0
  52. package/dist/{chunk-QZRVZSPN.cjs → chunk-77GNHH2Z.cjs} +3 -3
  53. package/dist/{chunk-FXUUWYAX.cjs → chunk-7GLPRTTF.cjs} +12 -2
  54. package/dist/{chunk-A777V5WU.cjs → chunk-7L5V3KQO.cjs} +2 -2
  55. package/dist/{chunk-4ZQQL4IU.mjs → chunk-AHGECQEW.mjs} +1 -1
  56. package/dist/{chunk-RG3ZOTG5.cjs → chunk-AI7QMY7O.cjs} +10 -3
  57. package/dist/{chunk-YMCXWPWK.mjs → chunk-BCMSYSN2.mjs} +4 -1
  58. package/dist/{chunk-I6XDAKWQ.mjs → chunk-BTHHUD7Q.mjs} +14 -0
  59. package/dist/{chunk-LI2LMOLR.mjs → chunk-C35ZBVRD.mjs} +12 -3
  60. package/dist/chunk-C4SPBWFM.cjs +26 -0
  61. package/dist/{chunk-YQVSHTMR.mjs → chunk-CP6X4AEU.mjs} +1 -1
  62. package/dist/{chunk-QZCT2CQ4.mjs → chunk-CXEN47J3.mjs} +64 -2
  63. package/dist/{chunk-WNLBF77X.cjs → chunk-D227TIEN.cjs} +28 -16
  64. package/dist/{chunk-ROUTX2E5.cjs → chunk-DBNKI4NF.cjs} +12 -3
  65. package/dist/{chunk-J3LOGE4T.cjs → chunk-DQQOKWYA.cjs} +5 -5
  66. package/dist/chunk-E5GNDG5F.mjs +701 -0
  67. package/dist/{chunk-X7KZBF63.cjs → chunk-EFCQPQMG.cjs} +40 -4
  68. package/dist/{chunk-K3F2E6GS.cjs → chunk-EJQT6KZN.cjs} +2 -2
  69. package/dist/{chunk-3LUF2PE2.cjs → chunk-EK4QAEFZ.cjs} +67 -5
  70. package/dist/{chunk-VVBO3QH7.mjs → chunk-ENLZ4R3Y.mjs} +10 -1
  71. package/dist/{chunk-KJ2TIHZZ.cjs → chunk-EUV4YR3V.cjs} +3 -2
  72. package/dist/{chunk-E76XC6ZG.mjs → chunk-EZDQRNQ7.mjs} +2 -2
  73. package/dist/{chunk-TOVMYGYW.mjs → chunk-F2SE2VDO.mjs} +1 -1
  74. package/dist/{chunk-MNUGPHLN.mjs → chunk-F6Z3Y5KL.mjs} +5 -3
  75. package/dist/{chunk-DFLLARUK.cjs → chunk-F7JZENPF.cjs} +35 -34
  76. package/dist/{chunk-BSPQVJ4A.mjs → chunk-FDR64H6B.mjs} +13 -0
  77. package/dist/{chunk-5OVTOKGH.cjs → chunk-FFFW3OQ7.cjs} +2 -2
  78. package/dist/{chunk-D4JE5NNV.cjs → chunk-FNO7A7CM.cjs} +5 -5
  79. package/dist/{chunk-Z5HIWVDP.cjs → chunk-FTFYRMQQ.cjs} +80 -91
  80. package/dist/chunk-FZ6YYU2W.mjs +65 -0
  81. package/dist/{chunk-X7WVQMIB.mjs → chunk-G5RT7EXW.mjs} +11 -5
  82. package/dist/{chunk-IXUY2F5U.mjs → chunk-GCXWJJKH.mjs} +4 -7
  83. package/dist/{chunk-ES4B2IXW.cjs → chunk-GFHLGIYC.cjs} +8 -8
  84. package/dist/{chunk-SORB3MAR.cjs → chunk-GQ3Z3IZI.cjs} +17 -17
  85. package/dist/{chunk-75WGQVQA.cjs → chunk-HITLGIAO.cjs} +10 -1
  86. package/dist/{chunk-HBTUGXHS.cjs → chunk-HLJ6MBUZ.cjs} +7 -4
  87. package/dist/{chunk-JLCQGPXE.mjs → chunk-HMIJDL7S.mjs} +51 -62
  88. package/dist/{chunk-F6XEGFHO.mjs → chunk-HUMR6LSU.mjs} +11 -1
  89. package/dist/{chunk-IMB4PIAR.cjs → chunk-ICUQICNC.cjs} +1441 -828
  90. package/dist/{chunk-ZCU4NZ3M.cjs → chunk-IE7XCHH3.cjs} +4 -4
  91. package/dist/{chunk-I26CZYPV.cjs → chunk-IHNIDL6H.cjs} +50 -7
  92. package/dist/{chunk-2FQHH5SC.mjs → chunk-IHNMMXHV.mjs} +49 -24
  93. package/dist/{chunk-YVGAEAA5.cjs → chunk-IPXLADVO.cjs} +522 -12
  94. package/dist/{chunk-VHJGDMCG.cjs → chunk-IWZKTWHZ.cjs} +2 -2
  95. package/dist/chunk-JG6DJF5A.mjs +238 -0
  96. package/dist/{chunk-KROWKCUH.cjs → chunk-JGLC4TO3.cjs} +8 -1
  97. package/dist/{chunk-5TISYEQF.mjs → chunk-JM5XPKWH.mjs} +10 -3
  98. package/dist/{chunk-BJJATPEC.mjs → chunk-KN7K4VQN.mjs} +1 -1
  99. package/dist/{chunk-WPYFSQKK.cjs → chunk-KNBBQHO2.cjs} +15 -1
  100. package/dist/{chunk-XWAWFQFS.cjs → chunk-KXWRO25S.cjs} +7 -4
  101. package/dist/chunk-LSKZMJMP.cjs +65 -0
  102. package/dist/{chunk-2N5PX3LS.mjs → chunk-LYV44OIR.mjs} +7 -1
  103. package/dist/chunk-M7MKQXAF.cjs +87 -0
  104. package/dist/{chunk-IV6CQY7O.mjs → chunk-MSSFIQGM.mjs} +63 -13
  105. package/dist/{chunk-KH7BN726.cjs → chunk-N4UOK6ZI.cjs} +8 -2
  106. package/dist/{chunk-JNGIWIY6.mjs → chunk-NPC7VWJE.mjs} +2 -2
  107. package/dist/chunk-NRDBW4MP.mjs +45 -0
  108. package/dist/{chunk-ILWLPEVO.mjs → chunk-NRSN7G7E.mjs} +2 -2
  109. package/dist/chunk-OFZUJMCU.mjs +601 -0
  110. package/dist/{chunk-L4DVIHOC.mjs → chunk-OKZUAXHF.mjs} +1 -1
  111. package/dist/{chunk-EM6SBQKM.cjs → chunk-OMVAU7NT.cjs} +27 -2
  112. package/dist/{chunk-AHAJGAYD.mjs → chunk-PDOCJ6RY.mjs} +2 -2
  113. package/dist/{chunk-IFI5FXEZ.cjs → chunk-PFQKNERH.cjs} +562 -251
  114. package/dist/{chunk-S5GDHOE4.mjs → chunk-PZNL3WEG.mjs} +48 -5
  115. package/dist/{chunk-GZYH4OER.mjs → chunk-Q3VLETLE.mjs} +2 -2
  116. package/dist/{chunk-WG2KHOMN.mjs → chunk-QAU5JD57.mjs} +571 -260
  117. package/dist/{chunk-FV45CKBC.mjs → chunk-QCFBDFRS.mjs} +1 -1
  118. package/dist/{chunk-75BRBIFP.cjs → chunk-QCVE2OCI.cjs} +5 -8
  119. package/dist/{chunk-6ZCMSZ5U.mjs → chunk-QE6VAKLT.mjs} +1 -1
  120. package/dist/{chunk-QG5HNS7P.mjs → chunk-QORUJDIV.mjs} +2 -2
  121. package/dist/chunk-RHAZ22ZN.mjs +87 -0
  122. package/dist/{chunk-CUMINO7Z.cjs → chunk-RU3M2FIK.cjs} +18 -14
  123. package/dist/{chunk-DGXN3L4D.mjs → chunk-SAZVVAJH.mjs} +5 -5
  124. package/dist/{chunk-MKMBQSNQ.mjs → chunk-SC2WYWPF.mjs} +3 -3
  125. package/dist/{chunk-QCFFHV5H.mjs → chunk-SMHH4VDG.mjs} +1 -1
  126. package/dist/{chunk-UAFSBWNT.mjs → chunk-SOMHP6GF.mjs} +63 -16
  127. package/dist/{chunk-ND224OE2.cjs → chunk-TKSCR644.cjs} +34 -15
  128. package/dist/{chunk-4V7GIE2U.mjs → chunk-UAORZ7QA.mjs} +3 -3
  129. package/dist/{chunk-IQXFRNY2.cjs → chunk-UFDAAQFX.cjs} +2 -2
  130. package/dist/{chunk-6VYZOPOT.mjs → chunk-UJD4PHYB.mjs} +15 -11
  131. package/dist/{chunk-ZHVYQL3H.cjs → chunk-ULAWS2PA.cjs} +97 -36
  132. package/dist/{chunk-5ZSWG4UX.cjs → chunk-UXFQ3UDA.cjs} +14 -1
  133. package/dist/{chunk-MPEYMSCF.cjs → chunk-VFQT3LAO.cjs} +5 -5
  134. package/dist/{chunk-2FXWWUE5.cjs → chunk-VZJR7UTG.cjs} +6 -6
  135. package/dist/{chunk-2AKFKCHA.mjs → chunk-W7LF2J2S.mjs} +1 -1
  136. package/dist/chunk-WWFTAUFG.cjs +45 -0
  137. package/dist/{chunk-JBC2FKRW.mjs → chunk-WWIKMBRN.mjs} +2 -1
  138. package/dist/{chunk-75DYEVXI.cjs → chunk-X6W5FFH6.cjs} +11 -11
  139. package/dist/{chunk-EXLKRR4U.cjs → chunk-XBML5KMG.cjs} +12 -12
  140. package/dist/{chunk-PZNCMPJF.cjs → chunk-XCACDAZZ.cjs} +18 -12
  141. package/dist/{chunk-JATSG2ZO.mjs → chunk-XCMCS4DA.mjs} +15 -3
  142. package/dist/{chunk-UJ2C4ICS.cjs → chunk-XJXBIP67.cjs} +4 -4
  143. package/dist/{chunk-XF7Q24PF.mjs → chunk-Y7RKTKYI.mjs} +25 -0
  144. package/dist/{chunk-VYZSOYR4.cjs → chunk-YC6V7PWE.cjs} +1 -1
  145. package/dist/{chunk-F6OHXPWR.mjs → chunk-YFILVET3.mjs} +8 -1
  146. package/dist/{chunk-JLRDISQL.cjs → chunk-YKX5BK66.cjs} +7 -7
  147. package/dist/{chunk-DYEJQTDN.cjs → chunk-YSCV4SJF.cjs} +4 -4
  148. package/dist/chunk-YSLWRWWP.cjs +601 -0
  149. package/dist/{chunk-5LJCOSKT.mjs → chunk-YULD7ICZ.mjs} +1 -1
  150. package/dist/{chunk-2SDO73HK.cjs → chunk-YWN746US.cjs} +64 -14
  151. package/dist/chunk-Z2HLU4IX.cjs +238 -0
  152. package/dist/chunk-ZLAT2CWY.mjs +135 -0
  153. package/dist/{chunk-T5CERMEH.cjs → chunk-ZXGAFZDO.cjs} +2 -2
  154. package/dist/{client-plugins-BX2ptm4H.d.mts → client-plugins-CvIslxWi.d.mts} +232 -8
  155. package/dist/{client-plugins-BmxM5KW_.d.ts → client-plugins-HIyulDym.d.ts} +232 -8
  156. package/dist/client-plugins.d.mts +4 -5
  157. package/dist/client-plugins.d.ts +4 -5
  158. package/dist/client.cjs +10 -10
  159. package/dist/client.d.mts +8 -9
  160. package/dist/client.d.ts +8 -9
  161. package/dist/client.mjs +9 -9
  162. package/dist/config.d.mts +4 -5
  163. package/dist/config.d.ts +4 -5
  164. package/dist/{devtools-EWRDHCD5.cjs → devtools-EAUY43BS.cjs} +14 -12
  165. package/dist/{devtools-BPBCYOU6.mjs → devtools-EE5RIBTH.mjs} +13 -11
  166. package/dist/docs.cjs +17 -15
  167. package/dist/docs.d.mts +46 -4
  168. package/dist/docs.d.ts +46 -4
  169. package/dist/docs.mjs +16 -14
  170. package/dist/environment/vite.cjs +2 -2
  171. package/dist/environment/vite.mjs +1 -1
  172. package/dist/headers.cjs +4 -4
  173. package/dist/headers.mjs +3 -3
  174. package/dist/i18n/client.cjs +14 -13
  175. package/dist/i18n/client.d.mts +2 -2
  176. package/dist/i18n/client.d.ts +2 -2
  177. package/dist/i18n/client.mjs +5 -4
  178. package/dist/i18n/index.cjs +3 -2
  179. package/dist/i18n/index.d.mts +3 -3
  180. package/dist/i18n/index.d.ts +3 -3
  181. package/dist/i18n/index.mjs +2 -1
  182. package/dist/i18n/server.cjs +6 -5
  183. package/dist/i18n/server.d.mts +5 -5
  184. package/dist/i18n/server.d.ts +5 -5
  185. package/dist/i18n/server.mjs +5 -4
  186. package/dist/image/server.cjs +3 -3
  187. package/dist/image/server.mjs +2 -2
  188. package/dist/image/sharp.cjs +10 -10
  189. package/dist/image/sharp.mjs +2 -2
  190. package/dist/{index-a-8Z5kZU.d.mts → index-BJJfLxJo.d.mts} +2 -2
  191. package/dist/{index-BWVfxIsO.d.ts → index-CwoOP-MW.d.ts} +2 -2
  192. package/dist/index.cjs +75 -60
  193. package/dist/index.d.mts +21 -22
  194. package/dist/index.d.ts +21 -22
  195. package/dist/index.mjs +79 -64
  196. package/dist/integrations.cjs +7 -4
  197. package/dist/integrations.d.mts +4 -5
  198. package/dist/integrations.d.ts +4 -5
  199. package/dist/integrations.mjs +8 -5
  200. package/dist/internal/app-markdown-runtime.cjs +7 -5
  201. package/dist/internal/app-markdown-runtime.d.mts +17 -7
  202. package/dist/internal/app-markdown-runtime.d.ts +17 -7
  203. package/dist/internal/app-markdown-runtime.mjs +6 -4
  204. package/dist/internal/build-runtime.cjs +44 -41
  205. package/dist/internal/build-runtime.d.mts +6 -7
  206. package/dist/internal/build-runtime.d.ts +6 -7
  207. package/dist/internal/build-runtime.mjs +43 -40
  208. package/dist/internal/cli-runtime.cjs +23 -20
  209. package/dist/internal/cli-runtime.mjs +22 -19
  210. package/dist/internal/client-error-overlay.cjs +6 -6
  211. package/dist/internal/client-error-overlay.mjs +2 -2
  212. package/dist/internal/client-runtime.cjs +5 -3
  213. package/dist/internal/client-runtime.d.mts +9 -1
  214. package/dist/internal/client-runtime.d.ts +9 -1
  215. package/dist/internal/client-runtime.mjs +4 -2
  216. package/dist/internal/compression-runtime.d.mts +4 -5
  217. package/dist/internal/compression-runtime.d.ts +4 -5
  218. package/dist/internal/config-runtime.cjs +14 -12
  219. package/dist/internal/config-runtime.d.mts +5 -6
  220. package/dist/internal/config-runtime.d.ts +5 -6
  221. package/dist/internal/config-runtime.mjs +13 -11
  222. package/dist/internal/infra-analytics-runtime.cjs +4 -4
  223. package/dist/internal/infra-analytics-runtime.mjs +2 -2
  224. package/dist/internal/isolated-boundary.cjs +3 -2
  225. package/dist/internal/isolated-boundary.d.mts +1 -0
  226. package/dist/internal/isolated-boundary.d.ts +1 -0
  227. package/dist/internal/isolated-boundary.mjs +2 -1
  228. package/dist/internal/metadata-image-runtime.cjs +3 -3
  229. package/dist/internal/metadata-image-runtime.mjs +2 -2
  230. package/dist/internal/product-telemetry-runtime.cjs +2 -2
  231. package/dist/internal/product-telemetry-runtime.mjs +1 -1
  232. package/dist/internal/production-runtime.cjs +61 -31
  233. package/dist/internal/production-runtime.d.mts +165 -18
  234. package/dist/internal/production-runtime.d.ts +165 -18
  235. package/dist/internal/production-runtime.mjs +57 -27
  236. package/dist/internal/request-cookies.cjs +4 -2
  237. package/dist/internal/request-cookies.d.mts +9 -1
  238. package/dist/internal/request-cookies.d.ts +9 -1
  239. package/dist/internal/request-cookies.mjs +3 -1
  240. package/dist/internal/server-tree.cjs +12 -0
  241. package/dist/internal/server-tree.d.mts +27 -0
  242. package/dist/internal/server-tree.d.ts +27 -0
  243. package/dist/internal/server-tree.mjs +12 -0
  244. package/dist/markdown.cjs +4 -4
  245. package/dist/markdown.d.mts +4 -5
  246. package/dist/markdown.d.ts +4 -5
  247. package/dist/markdown.mjs +3 -3
  248. package/dist/{metadata-DsEaK7mQ.d.mts → metadata-BnLDsUOS.d.ts} +16 -2
  249. package/dist/{metadata-fwZ3gfG6.d.ts → metadata-WGpBYcGn.d.mts} +16 -2
  250. package/dist/middleware.cjs +18 -8
  251. package/dist/middleware.d.mts +27 -9
  252. package/dist/middleware.d.ts +27 -9
  253. package/dist/middleware.mjs +18 -8
  254. package/dist/navigation.cjs +7 -7
  255. package/dist/navigation.d.mts +7 -8
  256. package/dist/navigation.d.ts +7 -8
  257. package/dist/navigation.mjs +6 -6
  258. package/dist/{nitro-NAKCRVHX.mjs → nitro-MXRDCXWZ.mjs} +5 -5
  259. package/dist/{nitro-VYDZGYFY.cjs → nitro-OVPLKPE2.cjs} +7 -7
  260. package/dist/{observability-BupkiN0m.d.mts → observability-CoXunYhS.d.mts} +4 -3
  261. package/dist/{observability-BupkiN0m.d.ts → observability-CoXunYhS.d.ts} +4 -3
  262. package/dist/observability.d.mts +1 -1
  263. package/dist/observability.d.ts +1 -1
  264. package/dist/plugin.cjs +39 -36
  265. package/dist/plugin.d.mts +4 -5
  266. package/dist/plugin.d.ts +4 -5
  267. package/dist/plugin.mjs +38 -35
  268. package/dist/{production-runtime-Baqgwtvc.d.mts → production-runtime-0sRnuYc-.d.mts} +11 -4
  269. package/dist/{production-runtime-DNkpFnmg.d.ts → production-runtime-Crq6CJ-2.d.ts} +11 -4
  270. package/dist/query/client.cjs +8 -8
  271. package/dist/query/client.mjs +4 -4
  272. package/dist/{render-plan-rkIK9wd9.d.ts → render-plan-8ozZh2Qv.d.ts} +1 -1
  273. package/dist/{render-plan-DhwQnmmX.d.mts → render-plan-gs9GGPzw.d.mts} +1 -1
  274. package/dist/renderer/react/server.cjs +10 -4
  275. package/dist/renderer/react/server.d.mts +2 -1
  276. package/dist/renderer/react/server.d.ts +2 -1
  277. package/dist/renderer/react/server.mjs +7 -1
  278. package/dist/renderer-client.cjs +40 -20
  279. package/dist/renderer-client.d.mts +6 -7
  280. package/dist/renderer-client.d.ts +6 -7
  281. package/dist/renderer-client.mjs +29 -9
  282. package/dist/renderer.d.mts +2 -0
  283. package/dist/renderer.d.ts +2 -0
  284. package/dist/{request-BcY4RYPC.d.ts → request-B5G8rLBH.d.ts} +7 -2
  285. package/dist/{request-CFy1BltJ.d.mts → request-fkhiynXe.d.mts} +7 -2
  286. package/dist/request.cjs +2 -2
  287. package/dist/request.d.mts +5 -6
  288. package/dist/request.d.ts +5 -6
  289. package/dist/request.mjs +1 -1
  290. package/dist/{resolver-PPEeiJ6M.d.ts → resolver-DadfRL6F.d.ts} +1 -1
  291. package/dist/{resolver-DhW0CqZN.d.mts → resolver-khasx3fU.d.mts} +1 -1
  292. package/dist/{route-rendering-BkS0TBlB.d.mts → route-rendering-CLnS7AZj.d.mts} +1 -1
  293. package/dist/{route-rendering-D4XpMjam.d.ts → route-rendering-lS5nUMua.d.ts} +1 -1
  294. package/dist/{router-Cq7BcZxg.d.ts → router-4iuiYnOW.d.ts} +1 -1
  295. package/dist/{router-C4zPlC3V.d.mts → router-ifU8Dui1.d.mts} +1 -1
  296. package/dist/routes.cjs +3 -3
  297. package/dist/routes.d.mts +4 -5
  298. package/dist/routes.d.ts +4 -5
  299. package/dist/routes.mjs +2 -2
  300. package/dist/{runtime-BirxPwbZ.d.ts → runtime-BgDQzBiu.d.ts} +2 -2
  301. package/dist/{runtime-AOJge4vQ.d.mts → runtime-CV2UCV-5.d.mts} +2 -2
  302. package/dist/server-action-security.cjs +3 -3
  303. package/dist/server-action-security.mjs +2 -2
  304. package/dist/server-fn.cjs +5 -5
  305. package/dist/server-fn.mjs +4 -4
  306. package/dist/server-plugins.cjs +4 -4
  307. package/dist/server-plugins.d.mts +5 -6
  308. package/dist/server-plugins.d.ts +5 -6
  309. package/dist/server-plugins.mjs +3 -3
  310. package/dist/server-query-client.cjs +3 -3
  311. package/dist/server-query-client.mjs +2 -2
  312. package/dist/server-query.cjs +6 -6
  313. package/dist/server-query.mjs +5 -5
  314. package/dist/server.cjs +66 -63
  315. package/dist/server.d.mts +13 -14
  316. package/dist/server.d.ts +13 -14
  317. package/dist/server.mjs +43 -40
  318. package/dist/{spa-router-DzPZH-AO.d.mts → spa-router-Bq7VCOwx.d.mts} +3 -3
  319. package/dist/{spa-router-B1HI3X9k.d.ts → spa-router-DaJk5Re4.d.ts} +3 -3
  320. package/dist/testing.cjs +22 -20
  321. package/dist/testing.d.mts +4 -5
  322. package/dist/testing.d.ts +4 -5
  323. package/dist/testing.mjs +18 -16
  324. package/dist/theme/server.cjs +4 -3
  325. package/dist/theme/server.mjs +3 -2
  326. package/dist/{types-Z0aotQ8w.d.mts → types-CnH8DOqo.d.mts} +1 -1
  327. package/dist/{types-Z0aotQ8w.d.ts → types-CnH8DOqo.d.ts} +1 -1
  328. package/dist/{utils-DMD1Hzta.d.ts → utils-BXLmFsVR.d.ts} +1 -1
  329. package/dist/{utils-CEBktlBG.d.mts → utils-XJn0c9bj.d.mts} +1 -1
  330. package/dist/version.cjs +2 -2
  331. package/dist/version.mjs +1 -1
  332. package/dist/vite.cjs +39 -36
  333. package/dist/vite.d.mts +4 -5
  334. package/dist/vite.d.ts +4 -5
  335. package/dist/vite.mjs +38 -35
  336. package/dist/{workflows-CR9ex-gz.d.ts → workflows-jZ4BcdoZ.d.mts} +1 -1
  337. package/dist/{workflows-CR9ex-gz.d.mts → workflows-jZ4BcdoZ.d.ts} +1 -1
  338. package/dist/workflows.cjs +3 -3
  339. package/dist/workflows.d.mts +1 -1
  340. package/dist/workflows.d.ts +1 -1
  341. package/dist/workflows.mjs +2 -2
  342. package/package.json +10 -2
  343. package/dist/chunk-22GUSVNJ.cjs +0 -351
  344. package/dist/chunk-5MKEDGLD.cjs +0 -53
  345. package/dist/chunk-O6XNAMBV.mjs +0 -53
  346. package/dist/chunk-SWN467MP.cjs +0 -18
  347. package/dist/chunk-XGC343EY.cjs +0 -443
  348. package/dist/chunk-ZSH2Y4LN.mjs +0 -351
  349. package/dist/types-DFbjpjXX.d.mts +0 -105
  350. package/dist/types-DFbjpjXX.d.ts +0 -105
  351. /package/dist/{chunk-SUIBNSNO.cjs → chunk-SJNMVDDF.cjs} +0 -0
  352. /package/dist/{chunk-LNZ7JZUS.mjs → chunk-UDNPLXW7.mjs} +0 -0
@@ -10,7 +10,7 @@ import {
10
10
  import {
11
11
  compileFarmDocsAdapterEdgeManifest,
12
12
  createFarmDocsAPIHandler
13
- } from "./chunk-UAFSBWNT.mjs";
13
+ } from "./chunk-SOMHP6GF.mjs";
14
14
  import {
15
15
  FARM_DOCS_LAST_MODIFIED_MANIFEST,
16
16
  createFarmDocsHandler,
@@ -20,7 +20,7 @@ import {
20
20
  loadFarmDocsPage,
21
21
  resolveFarmDocsContentDir,
22
22
  toFarmDocsMarkdownPage
23
- } from "./chunk-AHAJGAYD.mjs";
23
+ } from "./chunk-PDOCJ6RY.mjs";
24
24
  import {
25
25
  generateFarmDocsSearchClientRuntime,
26
26
  isFarmDocsSearchEnabled,
@@ -28,7 +28,7 @@ import {
28
28
  } from "./chunk-UP4CW6WP.mjs";
29
29
  import {
30
30
  FARM_PRERENDER_ENV
31
- } from "./chunk-MM5D6VLP.mjs";
31
+ } from "./chunk-3KZS4SUS.mjs";
32
32
  import {
33
33
  loadFarmDocsEngine
34
34
  } from "./chunk-2VQKKQ6D.mjs";
@@ -37,7 +37,7 @@ import {
37
37
  getDeployTargetForPreset,
38
38
  hasCustomFarmRouteContext,
39
39
  resolveDeployOutputPath
40
- } from "./chunk-FJZ3DQLK.mjs";
40
+ } from "./chunk-6DU6UFUE.mjs";
41
41
  import {
42
42
  resolveFarmInstrumentationFile
43
43
  } from "./chunk-ZZSRYEYU.mjs";
@@ -47,15 +47,16 @@ import {
47
47
  import {
48
48
  DEFAULT_NOT_FOUND_STYLES,
49
49
  FARM_LAYOUT_ELEMENT_CLIENT_SOURCE,
50
- HOISTED_HEAD_ELEMENT,
51
50
  PluginManager,
52
51
  SHARP_INSTALL_HINT,
52
+ collectFarmWebMCPTools,
53
53
  createFarmApp,
54
54
  createFarmSourceAlias,
55
55
  createFarmThemeCssPlugin,
56
56
  createMarkdownPageHydrationPlanner,
57
57
  describeSuppressedAsyncHydration,
58
58
  enforceFarmIsolatedHydrationRouteBudget,
59
+ farmDocsClientConfigPlugin,
59
60
  farmFontImportsPlugin,
60
61
  farmPluginMayAffectRuntimePath,
61
62
  generateClientCachePersistenceCode,
@@ -69,31 +70,40 @@ import {
69
70
  mergeFarmFontCss,
70
71
  mergeFarmProductionViteConfig,
71
72
  mergeFarmViteConfig,
73
+ resolveFarmAppPackages,
72
74
  resolveFarmClientCacheAdapterEntry,
73
75
  resolveFarmImageProviderForRuntime,
74
76
  resolveFarmIsolatedClientHydrationMode,
75
- resolveFarmNotFoundComponentPath
76
- } from "./chunk-6L6DQR5W.mjs";
77
+ resolveFarmNotFoundComponentPath,
78
+ usesFarmServerTree
79
+ } from "./chunk-4KU5Q7C2.mjs";
77
80
  import {
78
81
  findRequestBoundSourceBlockers,
79
82
  generateFarmTypeArtifacts,
80
83
  parseRouteRenderingDirective,
81
84
  resolveRouteRenderingConfigFromFile
82
- } from "./chunk-O3DTUAX2.mjs";
85
+ } from "./chunk-2G2NNLE2.mjs";
83
86
  import {
84
87
  FARM_API_CATALOG_PATH,
85
- resolveFarmApiCatalogInput
86
- } from "./chunk-TEN4FIZU.mjs";
88
+ FARM_APP_MANIFEST_PATH,
89
+ HOISTED_HEAD_ELEMENT,
90
+ getRouteDirectoryDepth,
91
+ getRouteGroupScope,
92
+ resolveFarmApiCatalogInput,
93
+ resolveFarmAppManifestInput,
94
+ routeBoundaryCoversDirectory,
95
+ stripRouteGroups
96
+ } from "./chunk-6ETPZTJI.mjs";
87
97
  import {
88
98
  isFarmPreviewDeploymentEnvironment
89
99
  } from "./chunk-BOYNDCZL.mjs";
90
100
  import {
91
101
  farmEnvironmentFunctionsPlugin
92
- } from "./chunk-ZSH2Y4LN.mjs";
102
+ } from "./chunk-E5GNDG5F.mjs";
93
103
  import {
94
104
  generateFarmDocsAdapterClientRuntime,
95
105
  getFarmDocsAdapterConfigModule
96
- } from "./chunk-VVBO3QH7.mjs";
106
+ } from "./chunk-ENLZ4R3Y.mjs";
97
107
  import {
98
108
  resolveFarmDocsFontAssets,
99
109
  toFarmDocsPublicFontAssets
@@ -115,7 +125,7 @@ import {
115
125
  } from "./chunk-DAATZTKJ.mjs";
116
126
  import {
117
127
  applyFarmCspHashesToHtml
118
- } from "./chunk-6VYZOPOT.mjs";
128
+ } from "./chunk-UJD4PHYB.mjs";
119
129
  import {
120
130
  applyFarmCronVercelCrons,
121
131
  createFarmCronCloudflareConfig,
@@ -127,38 +137,41 @@ import {
127
137
  } from "./chunk-4OOBRCJX.mjs";
128
138
  import {
129
139
  isFarmMarkdownPageFile
130
- } from "./chunk-7QOCTYBS.mjs";
140
+ } from "./chunk-4JHOT46A.mjs";
131
141
  import {
132
142
  resolveFarmMdxComponentsModulePath,
133
143
  resolveMdxConfig
134
144
  } from "./chunk-FA2W42OV.mjs";
135
145
  import {
136
146
  getFarmMarkdownAlternatePath
137
- } from "./chunk-JBC2FKRW.mjs";
147
+ } from "./chunk-WWIKMBRN.mjs";
138
148
  import {
139
149
  applyFarmWorkflowVercelCrons,
140
150
  prepareFarmWorkflowsForNitro
141
- } from "./chunk-3ATMYLLJ.mjs";
151
+ } from "./chunk-6WCPV6G2.mjs";
142
152
  import {
143
153
  getFarmIntegrationPluginServerRuntime,
144
154
  getIntegrationProviders
145
- } from "./chunk-JLCQGPXE.mjs";
155
+ } from "./chunk-HMIJDL7S.mjs";
146
156
  import {
147
- appendMiddlewareRoutePath
148
- } from "./chunk-VUMAE7NC.mjs";
157
+ appendMiddlewareDirectory,
158
+ appendMiddlewareRoutePath,
159
+ compareMiddlewareRouteLocations
160
+ } from "./chunk-6TJOML4E.mjs";
161
+ import {
162
+ compileMiddlewareConfig,
163
+ matchesCompiledMiddlewareConfig,
164
+ matchesMiddlewareRoute
165
+ } from "./chunk-JG6DJF5A.mjs";
149
166
  import {
150
167
  APIRouteManager
151
- } from "./chunk-BXFWA23T.mjs";
168
+ } from "./chunk-22LTEMGQ.mjs";
152
169
  import {
153
170
  readFarmI18nCatalogs
154
- } from "./chunk-FV45CKBC.mjs";
171
+ } from "./chunk-QCFBDFRS.mjs";
155
172
  import {
156
173
  VERCEL_OG_INSTALL_HINT
157
174
  } from "./chunk-YOZYCI6Z.mjs";
158
- import {
159
- resolveFarmAPIServerBasePath,
160
- resolveFarmAPIServerRoutePath
161
- } from "./chunk-I6XDAKWQ.mjs";
162
175
  import {
163
176
  createFarmRouteRuntimeKey,
164
177
  getFarmRouteRuntimeConfig,
@@ -173,6 +186,10 @@ import {
173
186
  toPosixPath,
174
187
  toViteModuleId
175
188
  } from "./chunk-KI3MESHB.mjs";
189
+ import {
190
+ resolveFarmAPIServerBasePath,
191
+ resolveFarmAPIServerRoutePath
192
+ } from "./chunk-BTHHUD7Q.mjs";
176
193
  import {
177
194
  getFarmPresetRuntime
178
195
  } from "./chunk-2A3EQHXX.mjs";
@@ -184,8 +201,8 @@ import {
184
201
  } from "./chunk-LPEX4YW6.mjs";
185
202
 
186
203
  // src/build/index.ts
187
- import path6 from "path";
188
- import { existsSync as existsSync2 } from "fs";
204
+ import path7 from "path";
205
+ import { existsSync as existsSync3 } from "fs";
189
206
 
190
207
  // src/nitro/client-css-href.ts
191
208
  import path from "path";
@@ -239,8 +256,8 @@ __name(resolveHashedClientJsSrc, "resolveHashedClientJsSrc");
239
256
 
240
257
  // src/nitro/universal-build.ts
241
258
  import os from "os";
242
- import path5 from "path";
243
- import { constants as fsConstants, existsSync, readFileSync, realpathSync } from "fs";
259
+ import path6 from "path";
260
+ import { constants as fsConstants, existsSync as existsSync2, readFileSync, realpathSync } from "fs";
244
261
  import { fileURLToPath } from "url";
245
262
  import { builtinModules, createRequire } from "module";
246
263
  import { isDeepStrictEqual } from "util";
@@ -707,6 +724,47 @@ function buildFarmVercelRoutes(options) {
707
724
  }
708
725
  __name(buildFarmVercelRoutes, "buildFarmVercelRoutes");
709
726
 
727
+ // src/nitro/netlify-entry.ts
728
+ import { existsSync } from "fs";
729
+ import path5 from "path";
730
+ function resolveNitroNetlifyEntry(nitroRuntimeEntry) {
731
+ const entry = path5.join(
732
+ path5.dirname(nitroRuntimeEntry),
733
+ "..",
734
+ "presets",
735
+ "netlify",
736
+ "runtime",
737
+ "netlify.mjs"
738
+ );
739
+ if (!existsSync(entry)) {
740
+ throw new Error(
741
+ `[Farm.js] Could not find Nitro's Netlify function entry at ${entry}. Farm wraps it so private responses are never cached by Netlify's CDN; reinstall dependencies or report the installed Nitro version.`
742
+ );
743
+ }
744
+ return entry.split(path5.sep).join("/");
745
+ }
746
+ __name(resolveNitroNetlifyEntry, "resolveNitroNetlifyEntry");
747
+ function createFarmNetlifyEntry(options) {
748
+ return `
749
+ import nitroNetlifyHandler from ${JSON.stringify(options.nitroNetlifyEntry)};
750
+
751
+ const PRIVATE_CACHE_DIRECTIVE = /(?:^|,)\\s*(?:private|no-store)\\s*(?:[,=]|$)/i;
752
+
753
+ export default async function farmNetlifyHandler(request, context) {
754
+ const response = await nitroNetlifyHandler(request, context);
755
+ if (
756
+ response &&
757
+ response.headers.has("netlify-cdn-cache-control") &&
758
+ PRIVATE_CACHE_DIRECTIVE.test(response.headers.get("cache-control") || "")
759
+ ) {
760
+ response.headers.delete("netlify-cdn-cache-control");
761
+ }
762
+ return response;
763
+ }
764
+ `.trim();
765
+ }
766
+ __name(createFarmNetlifyEntry, "createFarmNetlifyEntry");
767
+
710
768
  // src/nitro/node-server-entry.ts
711
769
  function createFarmNodeServerEntry(options) {
712
770
  const serverConfig = JSON.stringify(options.server);
@@ -984,18 +1042,18 @@ function preloadFarmNitroBuilder() {
984
1042
  }
985
1043
  __name(preloadFarmNitroBuilder, "preloadFarmNitroBuilder");
986
1044
  var _filename = typeof import.meta.url !== "undefined" ? fileURLToPath(import.meta.url) : "";
987
- var _dirname = path5.dirname(_filename);
1045
+ var _dirname = path6.dirname(_filename);
988
1046
  function findFarmCoreRoot(from) {
989
- let dir = path5.dirname(from);
990
- while (dir !== path5.dirname(dir)) {
991
- const manifest = path5.join(dir, "package.json");
992
- if (existsSync(manifest)) {
1047
+ let dir = path6.dirname(from);
1048
+ while (dir !== path6.dirname(dir)) {
1049
+ const manifest = path6.join(dir, "package.json");
1050
+ if (existsSync2(manifest)) {
993
1051
  try {
994
1052
  if (JSON.parse(readFileSync(manifest, "utf8")).name === "@farm.js/core") return dir;
995
1053
  } catch {
996
1054
  }
997
1055
  }
998
- dir = path5.dirname(dir);
1056
+ dir = path6.dirname(dir);
999
1057
  }
1000
1058
  return null;
1001
1059
  }
@@ -1007,16 +1065,16 @@ function toModulePath(file) {
1007
1065
  }
1008
1066
  __name(toModulePath, "toModulePath");
1009
1067
  function findInstalledPackageDir(name, from) {
1010
- for (let dir = from; ; dir = path5.dirname(dir)) {
1011
- const candidate = path5.join(dir, "node_modules", name);
1012
- if (existsSync(path5.join(candidate, "package.json"))) {
1068
+ for (let dir = from; ; dir = path6.dirname(dir)) {
1069
+ const candidate = path6.join(dir, "node_modules", name);
1070
+ if (existsSync2(path6.join(candidate, "package.json"))) {
1013
1071
  try {
1014
1072
  return realpathSync(candidate);
1015
1073
  } catch {
1016
1074
  return null;
1017
1075
  }
1018
1076
  }
1019
- if (dir === path5.dirname(dir)) return null;
1077
+ if (dir === path6.dirname(dir)) return null;
1020
1078
  }
1021
1079
  }
1022
1080
  __name(findInstalledPackageDir, "findInstalledPackageDir");
@@ -1028,7 +1086,7 @@ function collectFarmDependencyDirs(root) {
1028
1086
  seen.add(dir);
1029
1087
  let manifest;
1030
1088
  try {
1031
- manifest = JSON.parse(readFileSync(path5.join(dir, "package.json"), "utf8"));
1089
+ manifest = JSON.parse(readFileSync(path6.join(dir, "package.json"), "utf8"));
1032
1090
  } catch {
1033
1091
  return;
1034
1092
  }
@@ -1039,7 +1097,7 @@ function collectFarmDependencyDirs(root) {
1039
1097
  if (farmCoreRoot) visit(realpathSync(farmCoreRoot));
1040
1098
  queue.push({ name: "@farm.js/core", from: root });
1041
1099
  try {
1042
- const manifest = JSON.parse(readFileSync(path5.join(root, "package.json"), "utf8"));
1100
+ const manifest = JSON.parse(readFileSync(path6.join(root, "package.json"), "utf8"));
1043
1101
  for (const field of ["dependencies", "devDependencies"]) {
1044
1102
  for (const name of Object.keys(manifest[field] ?? {})) {
1045
1103
  if (name.startsWith("@farm.js/")) queue.push({ name, from: root });
@@ -1106,15 +1164,15 @@ var FARM_SSR_PACKAGE_IMPORT = "#farm-ssr-entry";
1106
1164
  var FARM_SSR_OUTPUT_DIR = "farm-ssr";
1107
1165
  var FARM_CLIENT_BUILD_TARGET = ["es2020", "edge88", "firefox78", "chrome87", "safari14"];
1108
1166
  function resolveNitroRuntimeDependency(root, specifier) {
1109
- return createRequire(resolveNitroPackageEntry(root)).resolve(specifier).split(path5.sep).join("/");
1167
+ return createRequire(resolveNitroPackageEntry(root)).resolve(specifier).split(path6.sep).join("/");
1110
1168
  }
1111
1169
  __name(resolveNitroRuntimeDependency, "resolveNitroRuntimeDependency");
1112
1170
  function resolveNitroInternalRuntimeAliases(root) {
1113
- const runtimeDir = path5.dirname(resolveNitroPackageEntry(root));
1171
+ const runtimeDir = path6.dirname(resolveNitroPackageEntry(root));
1114
1172
  return Object.fromEntries(
1115
1173
  ["app", "error/hooks", "runtime-config", "shutdown", "task"].map((moduleName) => [
1116
1174
  `#nitro/runtime/${moduleName}`,
1117
- path5.join(runtimeDir, "internal", `${moduleName}.mjs`).split(path5.sep).join("/")
1175
+ path6.join(runtimeDir, "internal", `${moduleName}.mjs`).split(path6.sep).join("/")
1118
1176
  ])
1119
1177
  );
1120
1178
  }
@@ -1125,7 +1183,7 @@ function createPrerenderRuntimeResolverPlugin(root, resolveNitroEntry = resolveN
1125
1183
  name: "farm-prerender-runtime-resolver",
1126
1184
  async resolveId(id, _importer, options) {
1127
1185
  if (options.custom?.farmPrerenderRuntimeResolve) return null;
1128
- if (id.startsWith("\0") || id.startsWith(".") || id.startsWith("#") || id.startsWith("virtual:") || path5.isAbsolute(id) || NODE_BUILTIN_MODULES.has(id)) {
1186
+ if (id.startsWith("\0") || id.startsWith(".") || id.startsWith("#") || id.startsWith("virtual:") || path6.isAbsolute(id) || NODE_BUILTIN_MODULES.has(id)) {
1129
1187
  return null;
1130
1188
  }
1131
1189
  if (nitroEntry === void 0) {
@@ -1146,7 +1204,7 @@ function createPrerenderRuntimeResolverPlugin(root, resolveNitroEntry = resolveN
1146
1204
  }
1147
1205
  __name(createPrerenderRuntimeResolverPlugin, "createPrerenderRuntimeResolverPlugin");
1148
1206
  function resolveNitroPackageEntry(root) {
1149
- const projectRequire = createRequire(path5.join(root, "package.json"));
1207
+ const projectRequire = createRequire(path6.join(root, "package.json"));
1150
1208
  let runtimeRequire = projectRequire;
1151
1209
  try {
1152
1210
  runtimeRequire = createRequire(projectRequire.resolve("@farm.js/core"));
@@ -1221,7 +1279,7 @@ function createFarmReactWebServerAlias(hasEdgeBuild) {
1221
1279
  __name(createFarmReactWebServerAlias, "createFarmReactWebServerAlias");
1222
1280
  function hasReactDomEdgeServerBuild(root) {
1223
1281
  try {
1224
- createRequire(path5.join(root, "package.json")).resolve("react-dom/server.edge");
1282
+ createRequire(path6.join(root, "package.json")).resolve("react-dom/server.edge");
1225
1283
  return true;
1226
1284
  } catch {
1227
1285
  return false;
@@ -1279,7 +1337,7 @@ function createMetadataImageWasmPlugin() {
1279
1337
  return null;
1280
1338
  }
1281
1339
  const requestPath = source.slice(0, -"?module".length);
1282
- const resolvedPath = path5.isAbsolute(requestPath) ? requestPath : path5.resolve(path5.dirname(importer.split("?", 1)[0]), requestPath);
1340
+ const resolvedPath = path6.isAbsolute(requestPath) ? requestPath : path6.resolve(path6.dirname(importer.split("?", 1)[0]), requestPath);
1283
1341
  return `${FARM_METADATA_IMAGE_WASM_PREFIX}${resolvedPath}`;
1284
1342
  },
1285
1343
  load(id) {
@@ -1305,11 +1363,11 @@ function collectSSRExternalPackages(ssrBundle) {
1305
1363
  for (const importId of [...output.imports, ...output.dynamicImports]) {
1306
1364
  const normalizedImportId = importId.replace(/\\/g, "/");
1307
1365
  const normalizedId = normalizedImportId.replace(/^\.\//, "");
1308
- const resolvedRelativeId = normalizedImportId.startsWith("./") || normalizedImportId.startsWith("../") ? path5.posix.normalize(path5.posix.join(path5.posix.dirname(fileName), normalizedImportId)) : null;
1366
+ const resolvedRelativeId = normalizedImportId.startsWith("./") || normalizedImportId.startsWith("../") ? path6.posix.normalize(path6.posix.join(path6.posix.dirname(fileName), normalizedImportId)) : null;
1309
1367
  if (emittedFiles.has(normalizedId) || resolvedRelativeId !== null && emittedFiles.has(resolvedRelativeId) || NODE_BUILTIN_MODULES.has(importId) || importId.startsWith("node:")) {
1310
1368
  continue;
1311
1369
  }
1312
- if (path5.isAbsolute(importId) || /^[A-Za-z]:[\\/]/.test(importId) || importId.startsWith("#") || importId.startsWith("\0")) {
1370
+ if (path6.isAbsolute(importId) || /^[A-Za-z]:[\\/]/.test(importId) || importId.startsWith("#") || importId.startsWith("\0")) {
1313
1371
  externalPackages.add(importId);
1314
1372
  continue;
1315
1373
  }
@@ -1322,15 +1380,15 @@ function collectSSRExternalPackages(ssrBundle) {
1322
1380
  }
1323
1381
  __name(collectSSRExternalPackages, "collectSSRExternalPackages");
1324
1382
  function createExternalSSRBundlePlugin(nitroEntryPath, ssrOutputDir, ssrEntryFile) {
1325
- const resolvedNitroEntry = path5.resolve(nitroEntryPath);
1326
- const resolvedSSREntry = path5.resolve(ssrOutputDir, ssrEntryFile);
1383
+ const resolvedNitroEntry = path6.resolve(nitroEntryPath);
1384
+ const resolvedSSREntry = path6.resolve(ssrOutputDir, ssrEntryFile);
1327
1385
  return {
1328
1386
  name: "farm-externalize-prebuilt-ssr",
1329
1387
  resolveId(source, importer) {
1330
- if (!importer || path5.resolve(importer) !== resolvedNitroEntry) {
1388
+ if (!importer || path6.resolve(importer) !== resolvedNitroEntry) {
1331
1389
  return null;
1332
1390
  }
1333
- const resolvedImport = path5.resolve(path5.dirname(importer), source);
1391
+ const resolvedImport = path6.resolve(path6.dirname(importer), source);
1334
1392
  if (resolvedImport !== resolvedSSREntry) return null;
1335
1393
  return { id: FARM_SSR_PACKAGE_IMPORT, external: true };
1336
1394
  }
@@ -1344,6 +1402,11 @@ function hasRollupPlugins(plugins) {
1344
1402
  return Boolean(plugins);
1345
1403
  }
1346
1404
  __name(hasRollupPlugins, "hasRollupPlugins");
1405
+ function hasFarmServerCacheConfig(cache) {
1406
+ if (!cache || typeof cache !== "object") return false;
1407
+ return cache.adapter !== void 0 || cache.namespace !== void 0 || cache.maxEntries !== void 0 || cache.lease !== void 0;
1408
+ }
1409
+ __name(hasFarmServerCacheConfig, "hasFarmServerCacheConfig");
1347
1410
  function hasFarmRuntimeConfigModule(config, configModulePath) {
1348
1411
  return Boolean(configModulePath || (config.layers || []).some((layer) => layer.configFile));
1349
1412
  }
@@ -1453,14 +1516,14 @@ function resolveBuildDocsContentDir(config, root) {
1453
1516
  if (!config.docs?.enabled) return null;
1454
1517
  const configuredContentDir = config.docs.contentDir || config.docs.config.contentDir;
1455
1518
  if (typeof configuredContentDir === "string" && configuredContentDir.trim()) {
1456
- const contentDir = path5.isAbsolute(configuredContentDir) ? configuredContentDir : path5.join(root, configuredContentDir);
1457
- return existsSync(contentDir) ? contentDir : null;
1519
+ const contentDir = path6.isAbsolute(configuredContentDir) ? configuredContentDir : path6.join(root, configuredContentDir);
1520
+ return existsSync2(contentDir) ? contentDir : null;
1458
1521
  }
1459
1522
  const entryDir = config.docs.config.entry || trimSlashes(config.docs.entry) || "docs";
1460
- const appDocsDir = path5.join(root, config.srcDir || "src", "app", entryDir);
1461
- if (existsSync(appDocsDir)) return appDocsDir;
1462
- const rootDocsDir = path5.join(root, entryDir);
1463
- return existsSync(rootDocsDir) ? rootDocsDir : null;
1523
+ const appDocsDir = path6.join(root, config.srcDir || "src", "app", entryDir);
1524
+ if (existsSync2(appDocsDir)) return appDocsDir;
1525
+ const rootDocsDir = path6.join(root, entryDir);
1526
+ return existsSync2(rootDocsDir) ? rootDocsDir : null;
1464
1527
  }
1465
1528
  __name(resolveBuildDocsContentDir, "resolveBuildDocsContentDir");
1466
1529
  function hasProjectPostcssConfig(root) {
@@ -1477,7 +1540,7 @@ function hasProjectPostcssConfig(root) {
1477
1540
  ".postcssrc.mjs",
1478
1541
  ".postcssrc.ts"
1479
1542
  ];
1480
- const projectRequire = createRequire(path5.join(root, "package.json"));
1543
+ const projectRequire = createRequire(path6.join(root, "package.json"));
1481
1544
  return candidates.some((file) => {
1482
1545
  try {
1483
1546
  projectRequire.resolve(`./${file}`);
@@ -1501,7 +1564,7 @@ async function findFarmConfigPath(root) {
1501
1564
  "config.mjs"
1502
1565
  ];
1503
1566
  for (const candidate of candidates) {
1504
- const resolvedPath = path5.join(root, candidate);
1567
+ const resolvedPath = path6.join(root, candidate);
1505
1568
  try {
1506
1569
  await fs.access(resolvedPath);
1507
1570
  return resolvedPath;
@@ -1543,7 +1606,7 @@ async function discoverMiddlewareRoutes(appDir) {
1543
1606
  const fs = await import("fs/promises");
1544
1607
  const appDirs = Array.isArray(appDir) ? [...appDir] : [appDir];
1545
1608
  const routes = /* @__PURE__ */ new Map();
1546
- async function walk(dir, routePath, discovered) {
1609
+ async function walk(dir, routePath, directory, discovered) {
1547
1610
  let entries;
1548
1611
  try {
1549
1612
  entries = await fs.readdir(dir, { withFileTypes: true });
@@ -1556,30 +1619,31 @@ async function discoverMiddlewareRoutes(appDir) {
1556
1619
  if (middlewareFile) {
1557
1620
  discovered.push({
1558
1621
  path: routePath,
1559
- filePath: path5.join(dir, middlewareFile.name)
1622
+ directory,
1623
+ filePath: path6.join(dir, middlewareFile.name)
1560
1624
  });
1561
1625
  }
1562
1626
  for (const entry of entries) {
1563
- if (!entry.isDirectory() || entry.name.startsWith(".") || entry.name.startsWith("_")) {
1627
+ if (!entry.isDirectory() || entry.name.startsWith(".")) {
1564
1628
  continue;
1565
1629
  }
1566
- const childRoutePath = appendMiddlewareRoutePath(routePath, entry.name);
1567
- await walk(path5.join(dir, entry.name), childRoutePath, discovered);
1630
+ await walk(
1631
+ path6.join(dir, entry.name),
1632
+ appendMiddlewareRoutePath(routePath, entry.name),
1633
+ appendMiddlewareDirectory(directory, entry.name),
1634
+ discovered
1635
+ );
1568
1636
  }
1569
1637
  }
1570
1638
  __name(walk, "walk");
1571
1639
  for (const sourceAppDir of appDirs) {
1572
1640
  const discovered = [];
1573
- await walk(sourceAppDir, "/", discovered);
1641
+ await walk(sourceAppDir, "/", "", discovered);
1574
1642
  for (const route of discovered) {
1575
- routes.set(route.path, route);
1643
+ routes.set(route.directory, route);
1576
1644
  }
1577
1645
  }
1578
- return Array.from(routes.values()).sort((a, b) => {
1579
- const depthA = a.path.split("/").filter(Boolean).length;
1580
- const depthB = b.path.split("/").filter(Boolean).length;
1581
- return depthA - depthB || a.path.localeCompare(b.path);
1582
- });
1646
+ return Array.from(routes.values()).sort(compareMiddlewareRouteLocations).map(({ path: routePath, filePath }) => ({ path: routePath, filePath }));
1583
1647
  }
1584
1648
  __name(discoverMiddlewareRoutes, "discoverMiddlewareRoutes");
1585
1649
  function assertFarmDocsRuntimeSupported(config, preset) {
@@ -1619,6 +1683,7 @@ async function buildUniversal(config, routeManager, apiRouteManager, serverRende
1619
1683
  const markdownSourcePath = entry.markdownSourcePath || (isFarmMarkdownPageFile(entry.modulePath) ? entry.modulePath : void 0);
1620
1684
  pageRoutes.push({
1621
1685
  pattern,
1686
+ ...entry.directory ? { directory: entry.directory } : {},
1622
1687
  modulePath: entry.modulePath,
1623
1688
  ...markdownSourcePath ? {
1624
1689
  source: readFileSync(markdownSourcePath, "utf8"),
@@ -1631,6 +1696,7 @@ async function buildUniversal(config, routeManager, apiRouteManager, serverRende
1631
1696
  (entry) => ({
1632
1697
  name: entry.name,
1633
1698
  ownerPattern: entry.ownerPattern,
1699
+ ...entry.ownerDirectory ? { ownerDirectory: entry.ownerDirectory } : {},
1634
1700
  pattern: entry.pattern,
1635
1701
  modulePath: entry.modulePath,
1636
1702
  containerId: entry.containerId,
@@ -1641,7 +1707,7 @@ async function buildUniversal(config, routeManager, apiRouteManager, serverRende
1641
1707
  logger.info(`\u{1F4CB} Found ${pageRoutes.length} page routes`);
1642
1708
  const fs = await import("fs/promises");
1643
1709
  const layoutRoutes = [];
1644
- const appDir = path5.join(root, srcDir, "app");
1710
+ const appDir = path6.join(root, srcDir, "app");
1645
1711
  async function findLayoutsForClient(dir, routePrefix = "/") {
1646
1712
  try {
1647
1713
  const entries = await fs.readdir(dir, { withFileTypes: true });
@@ -1649,11 +1715,11 @@ async function buildUniversal(config, routeManager, apiRouteManager, serverRende
1649
1715
  if (entry.isFile() && entry.name.match(/^layout\.(tsx?|jsx?|vue|svelte)$/)) {
1650
1716
  layoutRoutes.push({
1651
1717
  pattern: routePrefix,
1652
- modulePath: path5.join(dir, entry.name)
1718
+ modulePath: path6.join(dir, entry.name)
1653
1719
  });
1654
1720
  } else if (entry.isDirectory() && !entry.name.startsWith(".") && !entry.name.startsWith("_")) {
1655
1721
  const childPrefix = routePrefix === "/" ? `/${entry.name}` : `${routePrefix}/${entry.name}`;
1656
- await findLayoutsForClient(path5.join(dir, entry.name), childPrefix);
1722
+ await findLayoutsForClient(path6.join(dir, entry.name), childPrefix);
1657
1723
  }
1658
1724
  }
1659
1725
  } catch {
@@ -1670,7 +1736,7 @@ async function buildUniversal(config, routeManager, apiRouteManager, serverRende
1670
1736
  logger.info(`\u{1F4CB} Found ${pageRoutes.length} page routes and ${layoutRoutes.length} layouts`);
1671
1737
  const isolatedClientBoundaryModules = routeManager.getIsolatedClientBoundaryModules(root);
1672
1738
  const hydrationPlanCache = /* @__PURE__ */ new Map();
1673
- const clientOutputDir = path5.join(root, distDir, "client");
1739
+ const clientOutputDir = path6.join(root, distDir, "client");
1674
1740
  const [productionViteResult] = await productionViteResultPromise;
1675
1741
  if (productionViteResult.status === "rejected") {
1676
1742
  await routeRuntimeManifestResultPromise;
@@ -1779,10 +1845,10 @@ async function buildUniversal(config, routeManager, apiRouteManager, serverRende
1779
1845
  lifecyclePluginManager
1780
1846
  );
1781
1847
  const runtimeManifestPath = await writeFarmRouteRuntimeManifest(
1782
- path5.join(root, distDir),
1848
+ path6.join(root, distDir),
1783
1849
  routeRuntimeManifest
1784
1850
  );
1785
- logger.info(`\u{1F4CB} Route runtime manifest: ${path5.relative(root, runtimeManifestPath)}`);
1851
+ logger.info(`\u{1F4CB} Route runtime manifest: ${path6.relative(root, runtimeManifestPath)}`);
1786
1852
  } catch (error) {
1787
1853
  if (lifecyclePluginManager) {
1788
1854
  await lifecyclePluginManager.runHookParallel("onError", {
@@ -1809,8 +1875,8 @@ async function writeSSRAssetsToClient(bundle, outputDir) {
1809
1875
  await mergeBuiltFontCss(outputDir, output.source);
1810
1876
  continue;
1811
1877
  }
1812
- const filePath = path5.join(outputDir, fileName);
1813
- await fs.mkdir(path5.dirname(filePath), { recursive: true });
1878
+ const filePath = path6.join(outputDir, fileName);
1879
+ await fs.mkdir(path6.dirname(filePath), { recursive: true });
1814
1880
  await fs.writeFile(filePath, output.source);
1815
1881
  }
1816
1882
  }
@@ -1819,8 +1885,8 @@ async function copyFarmDocsFontAssetsToClient(root, outputDir) {
1819
1885
  const fs = await import("fs/promises");
1820
1886
  await Promise.all(
1821
1887
  resolveFarmDocsFontAssets(root).map(async ({ sourcePath, url }) => {
1822
- const targetPath = path5.join(outputDir, url.replace(/^\/+/, ""));
1823
- await fs.mkdir(path5.dirname(targetPath), { recursive: true });
1888
+ const targetPath = path6.join(outputDir, url.replace(/^\/+/, ""));
1889
+ await fs.mkdir(path6.dirname(targetPath), { recursive: true });
1824
1890
  await fs.copyFile(sourcePath, targetPath);
1825
1891
  })
1826
1892
  );
@@ -1828,7 +1894,7 @@ async function copyFarmDocsFontAssetsToClient(root, outputDir) {
1828
1894
  __name(copyFarmDocsFontAssetsToClient, "copyFarmDocsFontAssetsToClient");
1829
1895
  async function mergeBuiltFontCss(outputDir, fontCssSource) {
1830
1896
  const fs = await import("fs/promises");
1831
- const fontCssPath = path5.join(outputDir, "farm-fonts.css");
1897
+ const fontCssPath = path6.join(outputDir, "farm-fonts.css");
1832
1898
  let fontCss = fontCssSource;
1833
1899
  if (fontCss === void 0) {
1834
1900
  try {
@@ -1837,7 +1903,7 @@ async function mergeBuiltFontCss(outputDir, fontCssSource) {
1837
1903
  return;
1838
1904
  }
1839
1905
  }
1840
- const clientCssPath = path5.join(outputDir, "farm-client.css");
1906
+ const clientCssPath = path6.join(outputDir, "farm-client.css");
1841
1907
  let clientCss = "";
1842
1908
  try {
1843
1909
  clientCss = await fs.readFile(clientCssPath, "utf8");
@@ -1859,7 +1925,7 @@ var IncompleteClientBuildOutputError = _IncompleteClientBuildOutputError;
1859
1925
  async function validateClientBuildOutput(root, srcDir, outputDir) {
1860
1926
  const fs = await import("fs/promises");
1861
1927
  const fingerprinted = await findFingerprintedClientEntry(outputDir);
1862
- const clientEntryPath = path5.join(outputDir, fingerprinted ?? "farm-client.js");
1928
+ const clientEntryPath = path6.join(outputDir, fingerprinted ?? "farm-client.js");
1863
1929
  let clientEntrySize = 0;
1864
1930
  try {
1865
1931
  const clientEntry = await fs.stat(clientEntryPath);
@@ -1869,8 +1935,8 @@ async function validateClientBuildOutput(root, srcDir, outputDir) {
1869
1935
  if (clientEntrySize === 0) {
1870
1936
  throw new IncompleteClientBuildOutputError("farm-client.js is missing or empty");
1871
1937
  }
1872
- const clientCssPath = path5.join(outputDir, "farm-client.css");
1873
- const globalsCssPath = path5.join(root, srcDir, "app", "globals.css");
1938
+ const clientCssPath = path6.join(outputDir, "farm-client.css");
1939
+ const globalsCssPath = path6.join(root, srcDir, "app", "globals.css");
1874
1940
  let expectsCss = false;
1875
1941
  try {
1876
1942
  const globalsCss = await fs.readFile(globalsCssPath, "utf8");
@@ -1892,7 +1958,7 @@ async function validateClientBuildOutput(root, srcDir, outputDir) {
1892
1958
  }
1893
1959
  __name(validateClientBuildOutput, "validateClientBuildOutput");
1894
1960
  function getCachedClientModuleHydrationPlan(modulePath, root, mode, cache, options = {}) {
1895
- const key = `${path5.resolve(root)}\0${mode}\0${options.asyncOwnerIslands === true}\0${path5.resolve(modulePath)}`;
1961
+ const key = `${path6.resolve(root)}\0${mode}\0${options.asyncOwnerIslands === true}\0${path6.resolve(modulePath)}`;
1896
1962
  let plan = cache.get(key);
1897
1963
  if (!plan) {
1898
1964
  plan = getClientModuleHydrationPlan(modulePath, root, mode, options);
@@ -1978,7 +2044,8 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
1978
2044
  };
1979
2045
  }
1980
2046
  });
1981
- const layoutAppliesToRoute = /* @__PURE__ */ __name((layoutPattern, routePattern) => layoutPattern === "/" || routePattern === layoutPattern || routePattern.startsWith(`${layoutPattern}/`), "layoutAppliesToRoute");
2047
+ const layoutAppliesToRoute = routeBoundaryCoversDirectory;
2048
+ const routeDirectory = /* @__PURE__ */ __name((route) => route.directory ?? route.pattern, "routeDirectory");
1982
2049
  const adapterOwnsDocsRuntime = Boolean(
1983
2050
  isReactRenderer(config.renderer) && config.docs?.enabled && config.docs.adapter?.server && config.docs.adapter.react
1984
2051
  );
@@ -2012,8 +2079,8 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2012
2079
  })),
2013
2080
  [
2014
2081
  ...routePlans.map(({ route, metadata }) => ({
2015
- pattern: route.pattern,
2016
- depth: route.pattern.split("/").filter(Boolean).length,
2082
+ pattern: routeDirectory(route),
2083
+ depth: getRouteDirectoryDepth(routeDirectory(route)),
2017
2084
  metadata
2018
2085
  })),
2019
2086
  ...syntheticDocsPatterns.map((pattern) => ({
@@ -2034,7 +2101,7 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2034
2101
  layoutAppliesToRoute
2035
2102
  );
2036
2103
  for (const layout of clientLayouts) {
2037
- const matchesBuiltRoute = pageRoutes.some((route) => layoutAppliesToRoute(layout.pattern, route.pattern)) || Boolean(adapterDocsEntry && layoutAppliesToRoute(layout.pattern, adapterDocsEntry));
2104
+ const matchesBuiltRoute = pageRoutes.some((route) => layoutAppliesToRoute(layout.pattern, routeDirectory(route))) || Boolean(adapterDocsEntry && layoutAppliesToRoute(layout.pattern, adapterDocsEntry));
2038
2105
  if (matchesBuiltRoute && layout.suppressedAsyncHydration) {
2039
2106
  logger.warn(`\u26A0\uFE0F ${describeSuppressedAsyncHydration(layout.pattern, layout.fallbackReason)}`);
2040
2107
  }
@@ -2056,7 +2123,7 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2056
2123
  if (isAdapterDocsRoute(route.pattern)) continue;
2057
2124
  try {
2058
2125
  const applicableClientLayouts = clientLayouts.filter(
2059
- (layout) => (layout.shouldHydrate || layout.hasIsolatedClientBoundaries) && layoutAppliesToRoute(layout.pattern, route.pattern)
2126
+ (layout) => (layout.shouldHydrate || layout.hasIsolatedClientBoundaries) && layoutAppliesToRoute(layout.pattern, routeDirectory(route))
2060
2127
  );
2061
2128
  if (metadata.suppressedAsyncHydration) {
2062
2129
  logger.warn(
@@ -2083,7 +2150,9 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2083
2150
  isolatedBoundaries: [
2084
2151
  ...metadata.hasIsolatedClientBoundaries ? metadata.isolatedBoundaries : [],
2085
2152
  ...applicableClientLayouts.filter((layout) => layout.hasIsolatedClientBoundaries).flatMap((layout) => layout.isolatedBoundaries)
2086
- ]
2153
+ ],
2154
+ // The server renders a server tree only below a hydrating layout.
2155
+ ...usesFarmServerTree(metadata) && applicableClientLayouts.some((layout) => layout.shouldHydrate) ? { serverTree: true } : {}
2087
2156
  });
2088
2157
  logger.info(`\u{1F4F1} Found hydratable route: ${route.pattern} -> ${route.modulePath}`);
2089
2158
  }
@@ -2128,10 +2197,10 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2128
2197
  logger.info(
2129
2198
  `\u{1F4F1} Total hydratable routes detected: ${clientPages.length} pages, ${clientLayouts.filter((layout) => layout.shouldHydrate || layout.hasIsolatedClientBoundaries).length} layouts, and ${clientRouteSlots.length} slots`
2130
2199
  );
2131
- const clientEntryRoot = path5.join(root, ".farm", "tmp");
2200
+ const clientEntryRoot = path6.join(root, ".farm", "tmp");
2132
2201
  await fs.mkdir(clientEntryRoot, { recursive: true });
2133
- const clientEntryDir = await fs.mkdtemp(path5.join(clientEntryRoot, "client-entry-"));
2134
- const clientEntryPath = path5.join(clientEntryDir, "farm-client-entry.tsx");
2202
+ const clientEntryDir = await fs.mkdtemp(path6.join(clientEntryRoot, "client-entry-"));
2203
+ const clientEntryPath = path6.join(clientEntryDir, "farm-client-entry.tsx");
2135
2204
  const clientHydrationCode = generateClientHydrationEntry(
2136
2205
  clientPages,
2137
2206
  clientLayouts,
@@ -2163,7 +2232,7 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2163
2232
  if (hasScopedPostcssConfig) {
2164
2233
  logger.info("\u{1F4E6} Using project PostCSS/Tailwind configuration");
2165
2234
  } else {
2166
- const postcssConfigPath = path5.join(clientEntryDir, "postcss.config.cjs");
2235
+ const postcssConfigPath = path6.join(clientEntryDir, "postcss.config.cjs");
2167
2236
  await fs.writeFile(postcssConfigPath, "module.exports = { plugins: [] };\n");
2168
2237
  postcssSearchPath = clientEntryDir;
2169
2238
  tailwindVitePlugin = await loadTailwindVitePlugin({
@@ -2240,6 +2309,9 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2240
2309
  ...rendererVitePlugins,
2241
2310
  ...config.vite.plugins || [],
2242
2311
  farmServerOnlyEntriesPlugin(),
2312
+ farmDocsClientConfigPlugin(
2313
+ adapterOwnsDocsRuntime ? getFarmDocsAdapterConfigModule(config.docs) : void 0
2314
+ ),
2243
2315
  // Plugin to redirect @farm.js/core imports to client-only exports
2244
2316
  {
2245
2317
  name: "farm-client-only-imports",
@@ -2322,12 +2394,12 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2322
2394
  __name(buildClient, "buildClient");
2323
2395
  function toBakedMarkdownSourcePath(root, filePath) {
2324
2396
  if (!filePath) return "";
2325
- if (!path5.isAbsolute(filePath)) return filePath.split(path5.sep).join("/");
2326
- const relative = path5.relative(root, filePath);
2327
- if (!relative || relative.startsWith("..") || path5.isAbsolute(relative)) {
2328
- return path5.basename(filePath);
2397
+ if (!path6.isAbsolute(filePath)) return filePath.split(path6.sep).join("/");
2398
+ const relative = path6.relative(root, filePath);
2399
+ if (!relative || relative.startsWith("..") || path6.isAbsolute(relative)) {
2400
+ return path6.basename(filePath);
2329
2401
  }
2330
- return relative.split(path5.sep).join("/");
2402
+ return relative.split(path6.sep).join("/");
2331
2403
  }
2332
2404
  __name(toBakedMarkdownSourcePath, "toBakedMarkdownSourcePath");
2333
2405
  function generateUniversalRouterStateRuntime() {
@@ -3084,8 +3156,8 @@ __farmConfigureApp(__farmAppSetup);` : `import React, { createRoot, hydrateRoot
3084
3156
  root,
3085
3157
  renderer.componentExtensions ?? []
3086
3158
  );
3087
- const globalsCssPath = path5.join(root, srcDir, "app", "globals.css");
3088
- const cssImport = existsSync(globalsCssPath) ? `import ${JSON.stringify(toImportPath(globalsCssPath))};` : "";
3159
+ const globalsCssPath = path6.join(root, srcDir, "app", "globals.css");
3160
+ const cssImport = existsSync2(globalsCssPath) ? `import ${JSON.stringify(toImportPath(globalsCssPath))};` : "";
3089
3161
  const layoutImportStatements = [];
3090
3162
  const layoutRegistrations = [];
3091
3163
  layoutRoutes.forEach((layout, index) => {
@@ -3093,8 +3165,10 @@ __farmConfigureApp(__farmAppSetup);` : `import React, { createRoot, hydrateRoot
3093
3165
  if (!layout.hasIsolatedClientBoundaries) {
3094
3166
  layoutImportStatements.push(`import Layout${index} from "${relativePath}";`);
3095
3167
  }
3168
+ const groupScope = getRouteGroupScope(layout.pattern);
3169
+ const groupFields = groupScope ? `, urlPattern: ${JSON.stringify(stripRouteGroups(layout.pattern))}, groupScope: ${JSON.stringify(groupScope)}` : "";
3096
3170
  layoutRegistrations.push(
3097
- ` { pattern: ${JSON.stringify(layout.pattern)}, Component: ${layout.hasIsolatedClientBoundaries ? "null" : `Layout${index}`}, shouldHydrate: ${JSON.stringify(layout.shouldHydrate)}, islandStrategy: ${JSON.stringify(layout.islandStrategy)} }`
3171
+ ` { pattern: ${JSON.stringify(layout.pattern)}${groupFields}, Component: ${layout.hasIsolatedClientBoundaries ? "null" : `Layout${index}`}, shouldHydrate: ${JSON.stringify(layout.shouldHydrate)}, islandStrategy: ${JSON.stringify(layout.islandStrategy)} }`
3098
3172
  );
3099
3173
  });
3100
3174
  const layoutImports = layoutImportStatements.join("\n");
@@ -3151,7 +3225,7 @@ function isFarmDocsPath() {
3151
3225
  // Farm.js Client Runtime (no client components)
3152
3226
  ${cssImport}
3153
3227
  ${layoutImports}
3154
- import { createClientCancellation, createClientPluginManager, getHashTargetElement, installChunkErrorRecovery, isFarmExternalNavigationURL, reconcileFarmDocumentHead, setFarmBasePath, setFarmTrailingSlashPreference, stripFarmBasePath } from "@farm.js/core/internal/client-runtime";
3228
+ import { createClientCancellation, createClientPluginManager, getHashTargetElement, installChunkErrorRecovery, isFarmBlockedNavigationURL, isFarmExternalNavigationURL, reconcileFarmDocumentHead, setFarmBasePath, setFarmTrailingSlashPreference, stripFarmBasePath } from "@farm.js/core/internal/client-runtime";
3155
3229
  import { createFarmDeploymentMismatchError, createFarmDeploymentRequestHeaders, isFarmDeploymentMismatchResponse } from "@farm.js/core/deployment";
3156
3230
  ${clientPluginEntry.imports}
3157
3231
  ${clientCachePersistence.imports}
@@ -3175,6 +3249,7 @@ ${generateUniversalRouterStateProperties()}
3175
3249
 
3176
3250
  navigate: async function(href, options = {}) {
3177
3251
  const url = new URL(href, window.location.href);
3252
+ if (isFarmBlockedNavigationURL(url)) return;
3178
3253
  if (isFarmExternalNavigationURL(url, window.location.origin)) {
3179
3254
  this.cancelActiveNavigation();
3180
3255
  if (options.replace || options.action === "replace") window.location.replace(href);
@@ -3438,7 +3513,8 @@ document.addEventListener("click", function(e) {
3438
3513
  }
3439
3514
  const load = page.pageShouldHydrate ? `() => import(${JSON.stringify(toImportPath(page.modulePath))}).then((module) => module.default)` : "null";
3440
3515
  routeEntries.push(` {
3441
- pattern: ${JSON.stringify(page.pattern)},
3516
+ pattern: ${JSON.stringify(page.pattern)},${page.directory ? `
3517
+ directory: ${JSON.stringify(page.directory)},` : ""}
3442
3518
  pageShouldHydrate: ${JSON.stringify(page.pageShouldHydrate)},
3443
3519
  ${page.hasIsolatedClientBoundaries ? "hasIsolatedClientBoundaries: true," : ""}
3444
3520
  islandStrategy: ${JSON.stringify(page.islandStrategy)},
@@ -3447,20 +3523,22 @@ document.addEventListener("click", function(e) {
3447
3523
  }`);
3448
3524
  });
3449
3525
  const isolatedHydrationEnabled = isolatedBoundaryModules.size > 0;
3450
- const isolatedHydrationImport = isolatedHydrationEnabled ? `import { createFarmIsolatedHydrationRuntime, createFarmServerPageBoundary, wrapFarmIsolatedClientGraph } from "@farm.js/core/internal/isolated-boundary";` : "";
3526
+ const serverTreeEnabled = isolatedHydrationEnabled && clientPages.some((page) => page.serverTree);
3527
+ const isolatedHydrationImport = isolatedHydrationEnabled ? `import { createFarmIsolatedHydrationRuntime, createFarmServerPageBoundary, wrapFarmIsolatedClientGraph } from "@farm.js/core/internal/isolated-boundary";${serverTreeEnabled ? '\nimport { createFarmServerTreeElement } from "@farm.js/core/internal/server-tree";' : ""}` : "";
3451
3528
  const isolatedHydrationRuntime = isolatedHydrationEnabled ? `const farmIsolatedBoundaryLoaders = {
3452
3529
  ${Array.from(isolatedBoundaryModules.entries()).map(
3453
3530
  ([reference, modulePath]) => ` ${JSON.stringify(reference)}: () => import(${JSON.stringify(modulePath)}),`
3454
3531
  ).join("\n")}
3455
3532
  };
3533
+ async function loadFarmIsolatedBoundary(reference) {
3534
+ const loader = farmIsolatedBoundaryLoaders[reference];
3535
+ if (!loader) throw new Error("isolated client boundary loader was not found: " + reference);
3536
+ return loader();
3537
+ }
3456
3538
  const farmIsolatedHydrationRuntime = createFarmIsolatedHydrationRuntime({
3457
3539
  ReactRuntime: React,
3458
3540
  hydrateRoot,
3459
- load: async function(reference) {
3460
- const loader = farmIsolatedBoundaryLoaders[reference];
3461
- if (!loader) throw new Error("isolated client boundary loader was not found: " + reference);
3462
- return loader();
3463
- },
3541
+ load: loadFarmIsolatedBoundary,
3464
3542
  schedule: scheduleFarmIslandHydration,
3465
3543
  wrap: wrapWithIntegrationProviders,
3466
3544
  });
@@ -3474,7 +3552,21 @@ function disposeFarmIsolatedClientBoundaries(scope) {
3474
3552
 
3475
3553
  async function hydrateFarmIsolatedClientBoundaries(scope = document, signal) {
3476
3554
  await farmIsolatedHydrationRuntime.hydrate(scope, signal);
3477
- }` : "";
3555
+ }
3556
+ ${serverTreeEnabled ? `
3557
+ // A server-tree page (an async page below a hydrating layout) rebuilds in the layout's root.
3558
+ async function createFarmServerTreePageElement(source, pathname) {
3559
+ try {
3560
+ return await createFarmServerTreeElement(React, source, {
3561
+ load: loadFarmIsolatedBoundary,
3562
+ ServerHtml: FarmServerPage,
3563
+ key: pathname,
3564
+ });
3565
+ } catch (error) {
3566
+ console.warn("[Farm.js] Could not rebuild the server tree of " + pathname + "; its server HTML was kept.", error);
3567
+ return null;
3568
+ }
3569
+ }` : "async function createFarmServerTreePageElement() { return null; }"}` : `async function createFarmServerTreePageElement() { return null; }`;
3478
3570
  const routeClientGraphRuntime = isolatedHydrationEnabled ? `function wrapFarmRouteClientGraph(element) {
3479
3571
  return wrapFarmIsolatedClientGraph(React, element);
3480
3572
  }` : `function wrapFarmRouteClientGraph(element) { return element; }`;
@@ -3498,7 +3590,7 @@ ${layoutImports}
3498
3590
  ${rendererClientImports}
3499
3591
  ${isolatedHydrationImport}
3500
3592
  ${providerClientCode.imports}
3501
- import { createClientCancellation, createClientPluginManager, getHashTargetElement, installChunkErrorRecovery, isFarmExternalNavigationURL, reconcileFarmDocumentHead, scheduleFarmIslandHydration, searchParamsToObject, setFarmBasePath, setFarmTrailingSlashPreference, stripFarmBasePath } from "@farm.js/core/internal/client-runtime";
3593
+ import { createClientCancellation, createClientPluginManager, getHashTargetElement, installChunkErrorRecovery, isFarmBlockedNavigationURL, isFarmExternalNavigationURL, reconcileFarmDocumentHead, scheduleFarmIslandHydration, searchParamsToObject, setFarmBasePath, setFarmTrailingSlashPreference, stripFarmBasePath } from "@farm.js/core/internal/client-runtime";
3502
3594
  import { createFarmDeploymentMismatchError, createFarmDeploymentRequestHeaders, isFarmDeploymentMismatchResponse } from "@farm.js/core/deployment";
3503
3595
  import { createFarmRouter, isFarmRouteActive, matchFarmRoute } from "@farm.js/core/router";
3504
3596
  ${clientPluginEntry.imports}
@@ -3541,11 +3633,24 @@ ${layoutRegistrations.join(",\n")}
3541
3633
  function getApplicableLayouts(pathname) {
3542
3634
  const applicable = [];
3543
3635
  const normalizedPath = getFarmRoutePathname(pathname).replace(/\\/$/, '') || '/';
3636
+ let directory;
3544
3637
 
3545
3638
  for (const layout of layoutRoutes) {
3546
- if (layout.pattern === '/' || isFarmRouteActive(layout.pattern, normalizedPath, { exact: false })) {
3547
- applicable.push(layout);
3639
+ // Route groups add no URL segment: match the layout's URL, then keep a
3640
+ // grouped layout to the pages inside its group directory.
3641
+ const urlPattern = layout.urlPattern || layout.pattern;
3642
+ if (urlPattern !== '/' && !isFarmRouteActive(urlPattern, normalizedPath, { exact: false })) continue;
3643
+ if (layout.groupScope) {
3644
+ if (directory === undefined) {
3645
+ const matched = matchRoute(pathname);
3646
+ directory = matched ? matched.route.directory || matched.route.pattern : null;
3647
+ }
3648
+ if (
3649
+ typeof directory !== 'string' ||
3650
+ (directory !== layout.groupScope && !directory.startsWith(layout.groupScope + '/'))
3651
+ ) continue;
3548
3652
  }
3653
+ applicable.push(layout);
3549
3654
  }
3550
3655
 
3551
3656
  // Sort by depth (root first)
@@ -3614,7 +3719,17 @@ async function loadRouteComponent(route) {
3614
3719
  return route.Component;
3615
3720
  }
3616
3721
 
3617
- async function createMatchedHydrationRoute(matched, pathname, searchParams, serverHtml) {
3722
+ // The props the server rendered this document with, as the page receives them:
3723
+ // middleware data arrives as a plain object and is a Map again here.
3724
+ function reviveServerPageProps(serverProps) {
3725
+ if (!serverProps || typeof serverProps !== "object") return {};
3726
+ const middleware = serverProps.middleware;
3727
+ return middleware && middleware.data && !(middleware.data instanceof Map)
3728
+ ? { ...serverProps, middleware: { ...middleware, data: new Map(Object.entries(middleware.data)) } }
3729
+ : serverProps;
3730
+ }
3731
+
3732
+ async function createMatchedHydrationRoute(matched, pathname, searchParams, serverHtml, serverProps) {
3618
3733
  const hydrateLayouts = hasHydratableLayout(pathname);
3619
3734
  const params = matched.params;
3620
3735
  let pageElement = null;
@@ -3622,22 +3737,43 @@ async function createMatchedHydrationRoute(matched, pathname, searchParams, serv
3622
3737
  if (matched.route.pageShouldHydrate) {
3623
3738
  const Component = await loadRouteComponent(matched.route);
3624
3739
  if (!Component) return null;
3625
- if (typeof Component === "function" && Component.constructor && Component.constructor.name === "AsyncFunction") {
3740
+ // A programmatic page whose guard and data run only on the server renders
3741
+ // from the props the server resolved for this document. Without them (a
3742
+ // rejected guard, deferred data) its server-rendered HTML is kept.
3743
+ if (Component.__farmServerProps === true) {
3744
+ if (!serverProps || serverProps.__farmRoutePropsResolved !== true) return null;
3745
+ const props = {
3746
+ ...reviveServerPageProps(serverProps),
3747
+ searchParams: Promise.resolve(serverProps.search ?? searchParams),
3748
+ };
3749
+ pageElement = React.createElement(Component, props);
3750
+ } else if (typeof Component === "function" && Component.constructor && Component.constructor.name === "AsyncFunction") {
3626
3751
  console.warn(
3627
3752
  "[Farm.js] Skipping hydration for " + pathname +
3628
3753
  ": async server components cannot run in the browser. Server-rendered HTML is preserved."
3629
3754
  );
3630
3755
  return null;
3756
+ } else {
3757
+ // Keep what the server rendered with, such as middleware data, so the
3758
+ // first render matches the HTML. A navigation passes the fetched document's props.
3759
+ const props = {
3760
+ ...reviveServerPageProps(serverProps),
3761
+ params: params,
3762
+ searchParams: Promise.resolve(searchParams),
3763
+ };
3764
+ pageElement = React.createElement(Component, props);
3631
3765
  }
3632
- const props = { params: params, searchParams: Promise.resolve(searchParams) };
3633
- pageElement = React.createElement(Component, props);
3634
3766
  } else if (hydrateLayouts) {
3635
3767
  const serverPage = document.getElementById("__farm_page__");
3636
- pageElement = createLayoutPageBoundary(
3637
- matched.route,
3638
- null,
3639
- typeof serverHtml === "string" ? serverHtml : serverPage ? serverPage.innerHTML : "",
3640
- );
3768
+ const pageSource = typeof serverHtml === "string" ? serverHtml : serverPage;
3769
+ const serverTree = pageSource ? await createFarmServerTreePageElement(pageSource, pathname) : null;
3770
+ pageElement = serverTree
3771
+ ? createLayoutPageBoundary(matched.route, serverTree)
3772
+ : createLayoutPageBoundary(
3773
+ matched.route,
3774
+ null,
3775
+ typeof serverHtml === "string" ? serverHtml : serverPage ? serverPage.innerHTML : "",
3776
+ );
3641
3777
  }
3642
3778
 
3643
3779
  if (!pageElement) return null;
@@ -3701,6 +3837,32 @@ function findClientRouteSlot(slot) {
3701
3837
  });
3702
3838
  }
3703
3839
 
3840
+ /**
3841
+ * The page props a fetched document embeds in its bootstrap script, which a
3842
+ * client navigation does not execute. The JSON ends at the first statement
3843
+ * boundary where it parses, so the separator inside a string cannot cut it.
3844
+ */
3845
+ function readPagePropsPayload(doc) {
3846
+ const prefix = "window.__FARM_PROPS__=";
3847
+ const separator = ";window.__FARM_INTEGRATION_API_MANIFEST__=";
3848
+ for (const script of doc.querySelectorAll("script:not([src])")) {
3849
+ const source = script.textContent || "";
3850
+ if (!source.startsWith(prefix)) continue;
3851
+ for (
3852
+ let end = source.indexOf(separator, prefix.length);
3853
+ end !== -1;
3854
+ end = source.indexOf(separator, end + 1)
3855
+ ) {
3856
+ try {
3857
+ return JSON.parse(source.slice(prefix.length, end));
3858
+ } catch {
3859
+ // The separator was inside a string value; try the next one.
3860
+ }
3861
+ }
3862
+ }
3863
+ return undefined;
3864
+ }
3865
+
3704
3866
  function readRouteSlotPayload(doc) {
3705
3867
  const script = doc.getElementById("__farm_route_slots_data__");
3706
3868
  if (!script?.textContent) return [];
@@ -3897,6 +4059,8 @@ async function hydrate() {
3897
4059
  matched,
3898
4060
  pathname,
3899
4061
  searchParams,
4062
+ undefined,
4063
+ window.__FARM_PROPS__,
3900
4064
  );
3901
4065
  if (!routeState) return;
3902
4066
  const shouldHydrate = !isHydrated && Boolean(container.innerHTML.trim());
@@ -4011,6 +4175,7 @@ ${generateUniversalRouterStateProperties()}
4011
4175
 
4012
4176
  navigate: async function(href, options = {}) {
4013
4177
  const url = new URL(href, window.location.href);
4178
+ if (isFarmBlockedNavigationURL(url)) return;
4014
4179
  if (isFarmExternalNavigationURL(url, window.location.origin)) {
4015
4180
  this.cancelActiveNavigation();
4016
4181
  if (options.replace || options.action === "replace") window.location.replace(href);
@@ -4243,6 +4408,7 @@ ${generateUniversalRouterStateProperties()}
4243
4408
  if (isFarmLocaleDocumentChange(doc)) return false;
4244
4409
  if (doc.getElementById("nd-docs-layout")) return false;
4245
4410
  const nextRouteSlots = readRouteSlotPayload(doc);
4411
+ const nextPageProps = readPagePropsPayload(doc);
4246
4412
  const isNavigationCurrent = () =>
4247
4413
  this.isCurrentNavigation(navigation, clientNavigation);
4248
4414
 
@@ -4273,6 +4439,7 @@ ${generateUniversalRouterStateProperties()}
4273
4439
  newPathname,
4274
4440
  searchParams,
4275
4441
  nextPage ? nextPage.innerHTML : "",
4442
+ nextPageProps,
4276
4443
  );
4277
4444
  if (!isNavigationCurrent()) return false;
4278
4445
  if (routeState) {
@@ -4308,6 +4475,8 @@ ${generateUniversalRouterStateProperties()}
4308
4475
  matched,
4309
4476
  newPathname,
4310
4477
  searchParams,
4478
+ undefined,
4479
+ nextPageProps,
4311
4480
  );
4312
4481
  if (!isNavigationCurrent()) return false;
4313
4482
  if (routeState) {
@@ -4474,9 +4643,9 @@ async function buildSSRInMemory(productionVite, config, root, routeManager, apiR
4474
4643
  buildLifetime: rendererBuildLifetime
4475
4644
  });
4476
4645
  if (!hasScopedPostcssConfig) {
4477
- postcssConfigDir = await fs.mkdtemp(path5.join(os.tmpdir(), "farm-postcss-"));
4646
+ postcssConfigDir = await fs.mkdtemp(path6.join(os.tmpdir(), "farm-postcss-"));
4478
4647
  await fs.writeFile(
4479
- path5.join(postcssConfigDir, "postcss.config.cjs"),
4648
+ path6.join(postcssConfigDir, "postcss.config.cjs"),
4480
4649
  "module.exports = { plugins: [] };\n"
4481
4650
  );
4482
4651
  tailwindVitePlugin = await loadTailwindVitePlugin({
@@ -4601,7 +4770,8 @@ async function buildSSRInMemory(productionVite, config, root, routeManager, apiR
4601
4770
  const hasRouteContextConfig = hasCustomFarmRouteContext(config);
4602
4771
  const hasServerRuntimePlugins = hasFarmServerRuntimePlugins(config);
4603
4772
  const hasPluginRoutes = hasFarmPluginRoutes(config);
4604
- const configModulePath = hasServerRuntimeIntegrations || hasObservabilityHandler || hasMdxComponentConfig || hasMiddlewareConfig || hasRouteContextConfig || hasServerRuntimePlugins || hasPluginRoutes || hasIntegrationProviders ? await findFarmConfigPath(root) : null;
4773
+ const hasServerCacheConfig = hasFarmServerCacheConfig(config.cache);
4774
+ const configModulePath = hasServerRuntimeIntegrations || hasObservabilityHandler || hasMdxComponentConfig || hasMiddlewareConfig || hasRouteContextConfig || hasServerRuntimePlugins || hasPluginRoutes || hasServerCacheConfig || hasIntegrationProviders ? await findFarmConfigPath(root) : null;
4605
4775
  const hasRuntimeConfigModule = hasFarmRuntimeConfigModule(config, configModulePath);
4606
4776
  const hasRuntimeIntegrationConfig = hasRuntimeConfigModule && hasAnyConfiguredIntegrations;
4607
4777
  const hasConfiguredRuntimePlugins = Boolean(
@@ -5191,6 +5361,7 @@ function generateVirtualEntryCode(apiRoutes, pageRoutes, layoutRoutes, routeSlot
5191
5361
  const servesAgentRobotsTxt = Boolean(config.agent?.crawlers?.enabled) && !applicationMetadataRoutes.some(
5192
5362
  (metadata) => metadata.kind === "robots" && metadata.pattern === "/"
5193
5363
  );
5364
+ const servesAiCatalog = config.agent?.aiCatalog !== false;
5194
5365
  const hasPluginRuntime = hasRuntimeIntegrationConfig || hasServerRuntimePlugins;
5195
5366
  const hasInfraAnalyticsRuntime = config.analytics !== false && resolveFarmInstrumentationRuntime(preset) === "nodejs";
5196
5367
  const hasPrecompiledDocs = Boolean(farmDocsPrecompiledManifest);
@@ -5205,7 +5376,7 @@ function generateVirtualEntryCode(apiRoutes, pageRoutes, layoutRoutes, routeSlot
5205
5376
  );
5206
5377
  const hasReactSyncRender = isReactRenderer(config.renderer);
5207
5378
  const rendererServerImports = isReactRenderer(config.renderer) ? `import * as React from "react";
5208
- import * as ReactDOMServer from "react-dom/server";${hasIsolatedClientGraphRuntime ? '\nimport { isolateFarmServerPageGraph, wrapFarmIsolatedClientGraph } from "@farm.js/core/internal/isolated-boundary";' : ""}` : `import React, * as ReactDOMServer from ${JSON.stringify(config.renderer.server)};${generateFarmRendererAppSetupServerCode(config)}`;
5379
+ import * as ReactDOMServer from "react-dom/server";${hasIsolatedClientGraphRuntime ? '\nimport { isolateFarmServerPageGraph, wrapFarmIsolatedClientGraph } from "@farm.js/core/internal/isolated-boundary";\nimport { renderFarmServerTreePage } from "@farm.js/core/internal/server-tree";' : ""}` : `import React, * as ReactDOMServer from ${JSON.stringify(config.renderer.server)};${generateFarmRendererAppSetupServerCode(config)}`;
5209
5380
  const routeClientGraphServerRuntime = hasIsolatedClientGraphRuntime ? `function wrapFarmRouteClientGraph(element) {
5210
5381
  return wrapFarmIsolatedClientGraph(React, element);
5211
5382
  }
@@ -5214,9 +5385,17 @@ import * as ReactDOMServer from "react-dom/server";${hasIsolatedClientGraphRunti
5214
5385
  // components render as their own islands instead of joining the layout's React tree.
5215
5386
  function isolateFarmRouteServerPage(element) {
5216
5387
  return isolateFarmServerPageGraph(React, element);
5388
+ }
5389
+
5390
+ // An async page below a hydrating layout renders as a serialized tree the browser rebuilds in
5391
+ // the layout's React root, so its client components read the layout's context.
5392
+ function renderFarmRouteServerTree(element) {
5393
+ return renderFarmServerTreePage(React, element, { isolate: isolateFarmRouteServerPage });
5217
5394
  }` : `function wrapFarmRouteClientGraph(element) { return element; }
5218
5395
 
5219
- function isolateFarmRouteServerPage(element) { return element; }`;
5396
+ function isolateFarmRouteServerPage(element) { return element; }
5397
+
5398
+ function renderFarmRouteServerTree(element) { return element; }`;
5220
5399
  const hasGeneratedMetadataImages = metadataImageRoutes.some(
5221
5400
  (image) => image.sourceType === "module"
5222
5401
  );
@@ -5262,7 +5441,6 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5262
5441
  config.renderer,
5263
5442
  Boolean(unsupportedIntegrationProvider)
5264
5443
  );
5265
- const layoutAppliesToRoute = /* @__PURE__ */ __name((layoutPattern, routePattern) => layoutPattern === "/" || routePattern === layoutPattern || routePattern.startsWith(`${layoutPattern}/`), "layoutAppliesToRoute");
5266
5444
  const layoutHydrationPlans = layoutRoutes.map((layout) => ({
5267
5445
  ...layout,
5268
5446
  hydration: getCachedClientModuleHydrationPlan(
@@ -5298,11 +5476,12 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5298
5476
  metadata: layout.hydration
5299
5477
  })),
5300
5478
  pageRoutes.map((route) => ({
5301
- pattern: route.pattern,
5302
- depth: route.pattern.split("/").filter(Boolean).length,
5479
+ // Compared by directory so a grouped layout applies only inside its group.
5480
+ pattern: route.directory ?? route.pattern,
5481
+ depth: getRouteDirectoryDepth(route.directory ?? route.pattern),
5303
5482
  metadata: pageHydrationPlans.get(route.modulePath)
5304
5483
  })),
5305
- layoutAppliesToRoute
5484
+ routeBoundaryCoversDirectory
5306
5485
  );
5307
5486
  const providerServerImports = [
5308
5487
  providerServerModules.hasClerkProvider ? `import { ClerkProvider as FarmClerkProvider } from "@clerk/react";` : "",
@@ -5335,7 +5514,8 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5335
5514
  if (isFarmMarkdownPageFile(route.modulePath)) {
5336
5515
  pageRegistrations.push(`
5337
5516
  {
5338
- pattern: ${JSON.stringify(route.pattern)},
5517
+ pattern: ${JSON.stringify(route.pattern)},${route.directory ? `
5518
+ directory: ${JSON.stringify(route.directory)},` : ""}
5339
5519
  module: createFarmMarkdownRouteModule({
5340
5520
  source: ${JSON.stringify(route.source ?? "")},
5341
5521
  filePath: ${JSON.stringify(toBakedMarkdownSourcePath(config.root, route.modulePath))},
@@ -5358,10 +5538,11 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5358
5538
  const renderingDirective = parseRouteRenderingDirectiveFromDisk(route.modulePath);
5359
5539
  pageRegistrations.push(`
5360
5540
  {
5361
- pattern: ${JSON.stringify(route.pattern)},
5541
+ pattern: ${JSON.stringify(route.pattern)},${route.directory ? `
5542
+ directory: ${JSON.stringify(route.directory)},` : ""}
5362
5543
  module: ${varName},
5363
5544
  shouldHydrate: ${JSON.stringify(clientMetadata.shouldHydrate)},
5364
- islandStrategy: ${JSON.stringify(clientMetadata.islandStrategy)},${renderingDirective ? `
5545
+ islandStrategy: ${JSON.stringify(clientMetadata.islandStrategy)},${usesFarmServerTree(clientMetadata) ? "\n serverTree: true," : ""}${renderingDirective ? `
5365
5546
  rendering: ${JSON.stringify(renderingDirective)},` : ""}
5366
5547
  ${route.source !== void 0 ? `markdownSource: {
5367
5548
  source: ${JSON.stringify(route.source)},
@@ -5402,7 +5583,8 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5402
5583
  routeSlotRegistrations.push(`
5403
5584
  {
5404
5585
  name: ${JSON.stringify(slot.name)},
5405
- ownerPattern: ${JSON.stringify(slot.ownerPattern)},
5586
+ ownerPattern: ${JSON.stringify(slot.ownerPattern)},${slot.ownerDirectory ? `
5587
+ ownerDirectory: ${JSON.stringify(slot.ownerDirectory)},` : ""}
5406
5588
  pattern: ${JSON.stringify(slot.pattern)},
5407
5589
  containerId: ${JSON.stringify(slot.containerId)},
5408
5590
  interception: ${JSON.stringify(slot.interception)},
@@ -5417,9 +5599,12 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5417
5599
  errorImports.push(
5418
5600
  `import * as ${varName} from ${toVirtualEntryImportSpecifier(errorRoute.modulePath)};`
5419
5601
  );
5602
+ const groupScope = getRouteGroupScope(errorRoute.pattern);
5420
5603
  errorRegistrations.push(`
5421
5604
  {
5422
- pattern: ${JSON.stringify(errorRoute.pattern)},
5605
+ pattern: ${JSON.stringify(stripRouteGroups(errorRoute.pattern))},${groupScope ? `
5606
+ groupScope: ${JSON.stringify(groupScope)},
5607
+ directoryDepth: ${getRouteDirectoryDepth(errorRoute.pattern)},` : ""}
5423
5608
  module: ${varName},
5424
5609
  }`);
5425
5610
  });
@@ -5475,6 +5660,7 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5475
5660
  const notFoundImport = notFoundPath ? `import * as CustomNotFound from ${toVirtualEntryImportSpecifier(notFoundPath)};` : "";
5476
5661
  const apiRouteHelpersImport = apiRoutes.length > 0 ? `import { mergePluginAPIRoutes, getAllowedAPIRouteMethods, invokeAPIRouteEndpoint, createStaticAPIRouteMatcherAtBasePath, resolveAPIRouteEndpoint } from "@farm.js/core/api/runtime";` : "";
5477
5662
  const productionRuntimeImport = `import {
5663
+ _getRequestReadCount,
5478
5664
  _runWithAfterRequest,
5479
5665
  _runWithCurrentRequest,
5480
5666
  _runWithAPIRequestRuntime,
@@ -5496,13 +5682,18 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5496
5682
  createDefaultErrorMarkup,
5497
5683
  createFarmInstrumentationLifecycle,
5498
5684
  createFarmLayoutSelector,
5685
+ isInFarmRouteGroupScope,
5499
5686
  createFarmCacheKey,
5500
5687
  createFarmMetadataRouteResponse,
5501
5688
  createFarmAgentRobots,
5689
+ createFarmAiCatalogResponse,
5502
5690
  createFarmApiCatalogResponse,
5691
+ createFarmAppManifestResponse,
5503
5692
  collectFarmLlmsTxtPages,
5504
5693
  createFarmDefaultLlmsTxt,
5505
5694
  createFarmLlmsMarkdownReader,
5695
+ listFarmMCPLlmsTxtLinks,
5696
+ registerFarmMCPServer,
5506
5697
  renderFarmLlmsFullTxt,
5507
5698
  createFarmLlmsFullRenderer,
5508
5699
  createFarmThemeDocumentParts,
@@ -5523,6 +5714,9 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5523
5714
  mergeRouteRenderingDirectiveConfig,
5524
5715
  manageFarmLinkHeaderPreloads,
5525
5716
  mergeMetadata,
5717
+ mergeModuleViewport,
5718
+ ensureFarmDocumentMeta,
5719
+ renderViewportHead,
5526
5720
  matchesFarmIfNoneMatch,
5527
5721
  normalizeRevalidatePath,
5528
5722
  reportFarmPreloadWarnings,
@@ -5568,9 +5762,9 @@ import * as farmDocsConfigModule from ${toVirtualEntryImportSpecifier(docsConfig
5568
5762
  import { dirname as farmDocsDirname, join as farmDocsJoin } from "node:path";
5569
5763
  import { fileURLToPath as farmDocsFileURLToPath } from "node:url";` : "";
5570
5764
  const markdownHandlerImport = config.md?.enabled ? `import { applyMarkdownNegotiationHeaders, createMarkdownMirrorResponse, getFarmMarkdownAlternatePath } from "@farm.js/core/markdown";` : "";
5571
- const appMarkdownImport = hasMarkdownPages ? `import { createFarmMarkdownRouteModule, createFarmMarkdownSourceResponse } from "@farm.js/core/internal/app-markdown-runtime";` : "const createFarmMarkdownSourceResponse = null;";
5765
+ const appMarkdownImport = hasMarkdownPages ? `import { createFarmMarkdownRouteModule, createFarmMarkdownSourceResponse, isFarmMarkdownPublicSourceResponse } from "@farm.js/core/internal/app-markdown-runtime";` : "const createFarmMarkdownSourceResponse = null;\nconst isFarmMarkdownPublicSourceResponse = null;";
5572
5766
  const markdownErrorImport = `import { FARM_MARKDOWN_CONTENT_TYPE, createFarmMarkdownErrorBody, farmRequestWantsMarkdown } from "@farm.js/core/markdown";`;
5573
- const mdxComponentsPath = typeof config.mdx?.components === "string" ? path5.isAbsolute(config.mdx.components) ? config.mdx.components : path5.join(config.root, config.mdx.components) : null;
5767
+ const mdxComponentsPath = typeof config.mdx?.components === "string" ? path6.isAbsolute(config.mdx.components) ? config.mdx.components : path6.join(config.root, config.mdx.components) : null;
5574
5768
  const mdxComponentsImport = mdxComponentsPath ? `import * as FarmMdxComponentsModule from ${toVirtualEntryImportSpecifier(mdxComponentsPath)};` : "";
5575
5769
  const layerConfigPaths = (config.layers || []).map((layer) => layer.configFile).filter((configFile) => Boolean(configFile)).filter((configFile) => configFile !== configModulePath);
5576
5770
  const layerConfigImports = layerConfigPaths.map(
@@ -5998,6 +6192,8 @@ const farmDocsHandler = ${config.docs?.enabled ? hasPrecompiledDocs ? "farmDocsP
5998
6192
  getApplicableLayouts(getFarmRoutePathname(pathname)).map((layout) => layout.module),
5999
6193
  ),
6000
6194
  loadReactModule: async () => FarmDocsAdapterReact,
6195
+ // Lists the docs MCP endpoint in /.well-known/ai-catalog.json for the server's lifetime.
6196
+ registerMCPServer: registerFarmMCPServer,
6001
6197
  })` : `createFarmDocsHandler(farmDocsResolvedConfig, {
6002
6198
  root: farmDocsRuntimeRoot,
6003
6199
  srcDir: ${JSON.stringify(config.srcDir)},
@@ -6014,10 +6210,17 @@ const farmDocsAPIHandler = ${config.docs?.enabled ? hasPrecompiledDocs ? "farmDo
6014
6210
 
6015
6211
  // API routes bundled at build time
6016
6212
  const apiRoutes = ${apiRoutes.length > 0 ? "mergePluginAPIRoutes(" : ""}[${apiRegistrations.join(",")}
6017
- ]${apiRoutes.length > 0 ? `, configuredPlugins, ${JSON.stringify(apiRoutes.map(({ path: path7, methods }) => ({ path: path7, methods })))}, { bodySizeLimit: ${JSON.stringify(config.server.bodySizeLimit)} })` : ""};
6213
+ ]${apiRoutes.length > 0 ? `, configuredPlugins, ${JSON.stringify(apiRoutes.map(({ path: path8, methods }) => ({ path: path8, methods })))}, { bodySizeLimit: ${JSON.stringify(config.server.bodySizeLimit)} })` : ""};
6018
6214
  const farmLocalAPIBasePath = ${JSON.stringify(resolveFarmAPIServerBasePath(config.api))};
6019
6215
  const farmOpenAPIReference = ${JSON.stringify(openAPIReference)};
6020
6216
  ${config.agent?.apiCatalog ? `const farmApiCatalogInput = ${JSON.stringify(resolveFarmApiCatalogInput(config))};
6217
+ ` : ""}${config.analytics !== false ? `const farmAppManifestInput = ${JSON.stringify(
6218
+ resolveFarmAppManifestInput(config, {
6219
+ build: config.deploymentId,
6220
+ packages: resolveFarmAppPackages(config.root),
6221
+ webmcpTools: config.plugins.some(({ name }) => name === "farm:webmcp") ? collectFarmWebMCPTools(config.root, config.srcDir) : []
6222
+ })
6223
+ )};
6021
6224
  ` : ""}
6022
6225
  function isFarmLocalAPIPathname(pathname) {
6023
6226
  return farmLocalAPIBasePath !== "/" &&
@@ -6043,7 +6246,7 @@ for (const route of pageRoutes) {
6043
6246
  // Layout routes bundled at build time (sorted by depth, root first)
6044
6247
  const layoutRoutes = [${layoutRegistrations.join(",")}
6045
6248
  ];
6046
- const selectApplicableLayouts = createFarmLayoutSelector(layoutRoutes);
6249
+ const selectApplicableLayouts = createFarmLayoutSelector(layoutRoutes, getMatchedPageDirectory);
6047
6250
 
6048
6251
  const routeSlots = [${routeSlotRegistrations.join(",")}
6049
6252
  ];
@@ -6086,9 +6289,12 @@ function getFarmI18nSnapshot() {
6086
6289
  return ${config.i18n.enabled ? "getFarmI18nClientSnapshot()" : "undefined"};
6087
6290
  }
6088
6291
 
6292
+ // The locale step strips farmI18nConfig.basePath itself. Stripping it first as
6293
+ // well removed it twice, so /console/console/secret served /secret while
6294
+ // middleware and integration guards, which strip it once, saw /console/secret.
6089
6295
  function getFarmRoutePathname(pathname) {
6090
6296
  return farmI18nRuntime
6091
- ? stripFarmLocaleFromPathname(stripFarmBasePath(pathname), farmI18nConfig)
6297
+ ? stripFarmLocaleFromPathname(pathname, farmI18nConfig)
6092
6298
  : stripFarmBasePath(pathname);
6093
6299
  }
6094
6300
 
@@ -6689,6 +6895,7 @@ ${generateRuntimePathMatcherSource()}
6689
6895
  function getMatchingErrorBoundary(pathname) {
6690
6896
  const pathSegments = splitRuntimePath(pathname);
6691
6897
  let bestMatch = null;
6898
+ let directory;
6692
6899
 
6693
6900
  for (const errorRoute of errorRoutes) {
6694
6901
  const patternDepth = splitRuntimePath(errorRoute.pattern).length;
@@ -6698,9 +6905,18 @@ function getMatchingErrorBoundary(pathname) {
6698
6905
  : "/" + pathSegments.slice(0, patternDepth).join("/");
6699
6906
  const params = matchRuntimePathPattern(errorRoute.pattern, candidatePath);
6700
6907
  if (params === null) continue;
6908
+ if (errorRoute.groupScope) {
6909
+ if (directory === undefined) directory = getMatchedPageDirectory(pathname);
6910
+ if (!isInFarmRouteGroupScope(directory, errorRoute.groupScope)) continue;
6911
+ }
6701
6912
 
6702
- if (!bestMatch || patternDepth > bestMatch.depth) {
6703
- bestMatch = { route: errorRoute, params, depth: patternDepth };
6913
+ const directoryDepth = errorRoute.directoryDepth ?? patternDepth;
6914
+ if (
6915
+ !bestMatch ||
6916
+ patternDepth > bestMatch.depth ||
6917
+ (patternDepth === bestMatch.depth && directoryDepth > bestMatch.directoryDepth)
6918
+ ) {
6919
+ bestMatch = { route: errorRoute, params, depth: patternDepth, directoryDepth };
6704
6920
  }
6705
6921
  }
6706
6922
 
@@ -6924,6 +7140,10 @@ function createFarmLlmsTxtContext(request, full) {
6924
7140
  pages,
6925
7141
  config: farmLlmsTxtConfig,
6926
7142
  rootMetadata: rootLayout && rootLayout.module && rootLayout.module.metadata,
7143
+ ${servesAiCatalog ? `mcp: listFarmMCPLlmsTxtLinks(origin, {
7144
+ basePath: ${JSON.stringify(config.basePath)},
7145
+ apiServerBasePath: farmLocalAPIBasePath,
7146
+ }),` : ""}
6927
7147
  }),
6928
7148
  // llms-full.txt reads each page's .md mirror through this same handler,
6929
7149
  // with a fresh request so the caller's cookies never shape its content.
@@ -7030,6 +7250,7 @@ const farmMiddlewareRunner = ${hasMiddlewareRuntime ? `createProductionMiddlewar
7030
7250
  modules: fileMiddlewareModules,
7031
7251
  i18n: farmI18nConfig,
7032
7252
  server: farmServerConfig,
7253
+ apiBasePath: farmLocalAPIBasePath,
7033
7254
  })` : "null"};
7034
7255
 
7035
7256
  ${apiHandlerCode}
@@ -7272,11 +7493,18 @@ function getFarmPluginRequestOptions(request) {
7272
7493
  return { kind: "request", route };
7273
7494
  }
7274
7495
 
7496
+ /** The directory of the page a pathname selects, or null; route groups confine layouts to it. */
7497
+ function getMatchedPageDirectory(pathname) {
7498
+ const match = matchPageRoute(pathname);
7499
+ return match ? match.route.directory || match.route.pattern : null;
7500
+ }
7501
+
7275
7502
  /**
7276
- * Get applicable layouts for a page path (from root to most specific)
7503
+ * Get applicable layouts for a page path (from root to most specific). Pass the
7504
+ * selected page's directory when it is known, or null when no page applies.
7277
7505
  */
7278
- function getApplicableLayouts(pathname) {
7279
- const applicable = selectApplicableLayouts(pathname);
7506
+ function getApplicableLayouts(pathname, directory) {
7507
+ const applicable = selectApplicableLayouts(pathname, directory);
7280
7508
  // buildSSRInMemory already emits these immutable descriptors in stable depth
7281
7509
  // order. Filtering preserves that order, including equal-depth ties.
7282
7510
  return applicable;
@@ -7450,6 +7678,12 @@ function getPPRHeaders(status, config) {
7450
7678
  return headers;
7451
7679
  }
7452
7680
 
7681
+ function hasFarmUnserializableRouteData(data) {
7682
+ const isPromise = (value) => Boolean(value) && typeof value.then === "function";
7683
+ if (isPromise(data)) return true;
7684
+ return Boolean(data) && typeof data === "object" && Object.values(data).some(isPromise);
7685
+ }
7686
+
7453
7687
  function getRouteSharedCacheControl(route, pprCanCache) {
7454
7688
  if (!route || !route.module) {
7455
7689
  return null;
@@ -7631,6 +7865,20 @@ async function handleFarmRequestInContext(
7631
7865
  const middlewareHeaders = ${hasServerRuntimeIntegrations ? "withFarmIntegrationSetCookies(undefined, farmIntegrationSetCookies)" : "undefined"};
7632
7866
  `}
7633
7867
 
7868
+ ${servesAiCatalog ? `
7869
+ // agent.aiCatalog: the AI catalog of MCP servers and each server's card. Cards
7870
+ // live below the MCP endpoint, so this answers before the docs runtime and the
7871
+ // API routes, as in dev.
7872
+ const farmAiCatalogResponse = createFarmAiCatalogResponse(
7873
+ request,
7874
+ { basePath: ${JSON.stringify(config.basePath)}, apiServerBasePath: farmLocalAPIBasePath },
7875
+ url,
7876
+ );
7877
+ if (farmAiCatalogResponse) {
7878
+ return applyProductionMiddlewareHeaders(farmAiCatalogResponse, middlewareHeaders);
7879
+ }
7880
+ ` : ""}
7881
+
7634
7882
  ${config.docs?.enabled ? `
7635
7883
  // Docs responses are served after app middleware so route guards and
7636
7884
  // middleware headers apply to the docs engine like any other page content.
@@ -7662,7 +7910,8 @@ async function handleFarmRequestInContext(
7662
7910
 
7663
7911
  ${hasMarkdownPages ? `
7664
7912
  // The raw markdown source of a page route is the page's content in another
7665
- // representation; middleware guarding the route must run before serving it.
7913
+ // representation; it is only served for a page an anonymous visitor may open,
7914
+ // which renderPage asks the app with the page's own path.
7666
7915
  const markdownSourceResponse = await createFarmMarkdownSourceResponse?.({
7667
7916
  request: cloneFarmRequestWithContext(request),
7668
7917
  config: farmMdxConfig,
@@ -7670,9 +7919,12 @@ async function handleFarmRequestInContext(
7670
7919
  const match = matchPageRoute(getFarmRoutePathname(targetPathname));
7671
7920
  return match?.route?.markdownSource || null;
7672
7921
  },
7922
+ renderPage: (targetRequest) => handleFarmRequest(targetRequest, adapterContext),
7673
7923
  });
7674
7924
  if (markdownSourceResponse) {
7675
- return applyProductionMiddlewareHeaders(markdownSourceResponse, middlewareHeaders);
7925
+ return isFarmMarkdownPublicSourceResponse(markdownSourceResponse)
7926
+ ? markdownSourceResponse
7927
+ : applyProductionMiddlewareHeaders(markdownSourceResponse, middlewareHeaders);
7676
7928
  }
7677
7929
  ` : ""}
7678
7930
 
@@ -7775,6 +8027,17 @@ async function handleFarmRequestInContext(
7775
8027
  return applyProductionMiddlewareHeaders(applicationMetadataResponse, middlewareHeaders);
7776
8028
  }
7777
8029
  ` : ""}
8030
+ ${config.analytics !== false ? `
8031
+ // /.well-known/farmjs: the app's manifest, only for a request Farm Infra signed.
8032
+ if (normalizeRuntimePath(routePathname) === ${JSON.stringify(FARM_APP_MANIFEST_PATH)}) {
8033
+ const farmAppManifest = await createFarmAppManifestResponse(request, farmAppManifestInput, {
8034
+ development: false,
8035
+ });
8036
+ if (farmAppManifest) {
8037
+ return applyProductionMiddlewareHeaders(farmAppManifest, middlewareHeaders);
8038
+ }
8039
+ }
8040
+ ` : ""}
7778
8041
  ${config.agent?.apiCatalog ? `
7779
8042
  // agent.apiCatalog: list the OpenAPI and MCP surfaces at the RFC 9727 path.
7780
8043
  if (normalizeRuntimePath(routePathname) === ${JSON.stringify(FARM_API_CATALOG_PATH)}) {
@@ -7913,13 +8176,19 @@ async function handleFarmRequestInContext(
7913
8176
  emitFarmEvent({ type: "ppr.shell.miss", route: pathname, key: pprCacheKey });
7914
8177
  }
7915
8178
 
8179
+ // Reads from here on belong to the page render, not to middleware.
8180
+ const requestReadsBeforeRender = _getRequestReadCount();
8181
+
7916
8182
  // Get the page component and metadata
7917
8183
  let PageComponent = route.module.default;
7918
8184
  let pageStatus = 200;
7919
8185
  const pageMetadata = route.module.metadata || {};
7920
8186
 
7921
8187
  // Get applicable layouts for this page
7922
- const applicableLayouts = getApplicableLayouts(routePathname);
8188
+ const applicableLayouts = getApplicableLayouts(
8189
+ routePathname,
8190
+ route.directory || route.pattern,
8191
+ );
7923
8192
  const shouldHydrateLayout = applicableLayouts.some(
7924
8193
  (layout) => layout.shouldHydrate === true,
7925
8194
  );
@@ -7972,6 +8241,10 @@ async function handleFarmRequestInContext(
7972
8241
  });
7973
8242
  }
7974
8243
  let pageProps;
8244
+ // A rejected guard or loader renders the route's notFound/error
8245
+ // component, and the route's generateMetadata must not run for it:
8246
+ // it would describe the resource the caller was refused.
8247
+ let routeStateRejected = false;
7975
8248
  try {
7976
8249
  // Resolve top-level route state before starting the HTTP stream so
7977
8250
  // redirects, notFound(), and failures keep their real status. Route
@@ -8006,6 +8279,7 @@ async function handleFarmRequestInContext(
8006
8279
  } catch (routeStateError) {
8007
8280
  if (isFarmRedirectError(routeStateError)) throw routeStateError;
8008
8281
 
8282
+ routeStateRejected = true;
8009
8283
  const routeComponents = route.module.__farmRouteComponents;
8010
8284
  const routeStateProps = {
8011
8285
  ...rawPageProps,
@@ -8095,7 +8369,9 @@ async function handleFarmRequestInContext(
8095
8369
  ...(pageProps.__farmCanonicalPath
8096
8370
  ? { __farmCanonicalPath: pageProps.__farmCanonicalPath }
8097
8371
  : {}),
8098
- ...(pageProps.__farmRoutePropsResolved
8372
+ // Deferred values do not survive JSON, so the browser cannot render
8373
+ // a page from these props while one is still in flight.
8374
+ ...(pageProps.__farmRoutePropsResolved && !hasFarmUnserializableRouteData(pageProps.data)
8099
8375
  ? { __farmRoutePropsResolved: true }
8100
8376
  : {}),
8101
8377
  path: pathname,
@@ -8145,7 +8421,9 @@ async function handleFarmRequestInContext(
8145
8421
  if (route.shouldHydrate && !shouldHydrateLayout) {
8146
8422
  pageElement = wrapFarmRouteClientGraph(pageElement);
8147
8423
  } else if (shouldHydrateLayout && !route.shouldHydrate) {
8148
- pageElement = isolateFarmRouteServerPage(pageElement);
8424
+ pageElement = route.serverTree
8425
+ ? await renderFarmRouteServerTree(pageElement)
8426
+ : isolateFarmRouteServerPage(pageElement);
8149
8427
  }
8150
8428
 
8151
8429
  pageElement = React.createElement(
@@ -8172,7 +8450,7 @@ async function handleFarmRequestInContext(
8172
8450
  if (LayoutComponent) {
8173
8451
  const slotProps = {};
8174
8452
  for (const slot of renderedRouteSlots) {
8175
- if (slot.ownerPattern !== layout.pattern) continue;
8453
+ if ((slot.ownerDirectory || slot.ownerPattern) !== layout.pattern) continue;
8176
8454
  slotProps[slot.name] = React.createElement(
8177
8455
  "div",
8178
8456
  {
@@ -8217,7 +8495,7 @@ async function handleFarmRequestInContext(
8217
8495
  // the request's resolved Suspense content. Until the production runtime
8218
8496
  // can persist and resume the partial shell itself, buffer streamed PPR
8219
8497
  // responses for late status errors but do not cache their dynamic HTML.
8220
- const shouldCachePPRShell = Boolean(pprCacheKey && !renderedPage.stream);
8498
+ let shouldCachePPRShell = Boolean(pprCacheKey && !renderedPage.stream);
8221
8499
  if (!shouldCachePPRShell && pprCacheKey) {
8222
8500
  pprCanCache = false;
8223
8501
  emitFarmEvent({
@@ -8239,14 +8517,22 @@ async function handleFarmRequestInContext(
8239
8517
  await layout.module.generateMetadata({ params: pageProps.params }),
8240
8518
  );
8241
8519
  }
8520
+ mergedMetadata = await mergeModuleViewport(mergedMetadata, layout.module, {
8521
+ params: pageProps.params,
8522
+ });
8242
8523
  }
8243
8524
  mergedMetadata = mergeMetadata(mergedMetadata, pageMetadata);
8244
- if (typeof route.module.generateMetadata === "function") {
8525
+ if (!routeStateRejected && typeof route.module.generateMetadata === "function") {
8245
8526
  mergedMetadata = mergeMetadata(
8246
8527
  mergedMetadata,
8247
8528
  await route.module.generateMetadata(pageProps),
8248
8529
  );
8249
8530
  }
8531
+ mergedMetadata = await mergeModuleViewport(
8532
+ mergedMetadata,
8533
+ routeStateRejected ? { viewport: route.module.viewport } : route.module,
8534
+ pageProps,
8535
+ );
8250
8536
 
8251
8537
  if (!mergedMetadata.manifest) {
8252
8538
  const manifestMatch = getMatchingApplicationMetadataRoute(routePathname, "manifest");
@@ -8275,10 +8561,22 @@ async function handleFarmRequestInContext(
8275
8561
  getFarmMarkdownAlternatePath(farmMarkdownConfig, pathname),
8276
8562
  );` : ""}
8277
8563
 
8564
+ // headers(), cookies(), or getCurrentRequest() read during the render,
8565
+ // in the page, a layout, metadata, or anything they import, makes this
8566
+ // HTML one visitor's: never a shared PPR shell or CDN response.
8567
+ const renderReadRequest = _getRequestReadCount() !== requestReadsBeforeRender;
8568
+ if (renderReadRequest && shouldCachePPRShell) {
8569
+ shouldCachePPRShell = false;
8570
+ pprCanCache = false;
8571
+ emitFarmEvent({ type: "ppr.shell.bypass", route: pathname, reason: "request-read" });
8572
+ emitFarmEvent({ type: "cache.bypass", route: pathname, reason: "request-read" });
8573
+ }
8574
+
8278
8575
  const renderedMetadata = renderMetadataHead(mergedMetadata, { pathname, jsonLd: ${JSON.stringify(config.agent?.jsonLd ?? false)} });
8279
8576
  const title = renderedMetadata.title;
8280
8577
  const metaTags = renderedMetadata.tags;
8281
8578
  const hasFavicon = renderedMetadata.hasFavicon;
8579
+ const viewportTags = renderedMetadata.viewport;
8282
8580
 
8283
8581
  const hasPrivateRequestHeaders = hasPrivateFarmRequestHeaders(
8284
8582
  request,
@@ -8286,6 +8584,7 @@ async function handleFarmRequestInContext(
8286
8584
  );
8287
8585
  const hasRequestScopedRender = Boolean(
8288
8586
  pageStatus >= 400 ||
8587
+ renderReadRequest ||
8289
8588
  request.headers.get("x-farm-intercept-from") ||
8290
8589
  hasPrivateRequestHeaders ||
8291
8590
  hasConfiguredRouteContext ||
@@ -8329,7 +8628,7 @@ async function handleFarmRequestInContext(
8329
8628
  const streamPrefix = '<!DOCTYPE html>\\n<html lang="en">\\n<head>\\n' +
8330
8629
  farmThemeDocument.head + '\\n' +
8331
8630
  ' <meta charset="utf-8">\\n' +
8332
- ' <meta name="viewport" content="width=device-width, initial-scale=1">\\n' +
8631
+ ' ' + viewportTags + '\\n' +
8333
8632
  (hasFavicon ? '' : ' <link rel="icon" href="data:,">\\n') +
8334
8633
  ' <title>' + title + '</title>' + metaTags + '\\n' +
8335
8634
  ' <link rel="stylesheet" href="/__farm_client_css_href__">\\n' +
@@ -8460,6 +8759,9 @@ async function handleFarmRequestInContext(
8460
8759
  ' <script type="module" src="/__farm_client_js_src__"></script>\\n</body>',
8461
8760
  );
8462
8761
 
8762
+ // Last, so the charset (and the viewport, unless the layout wrote one) open the head.
8763
+ fullHtml = ensureFarmDocumentMeta(fullHtml, viewportTags);
8764
+
8463
8765
  // Add DOCTYPE if not present
8464
8766
  if (!fullHtml.trim().startsWith('<!DOCTYPE')) {
8465
8767
  fullHtml = '<!DOCTYPE html>\\n' + fullHtml;
@@ -8470,7 +8772,7 @@ async function handleFarmRequestInContext(
8470
8772
  <html lang="en">
8471
8773
  <head>
8472
8774
  <meta charset="utf-8">
8473
- <meta name="viewport" content="width=device-width, initial-scale=1">
8775
+ \${viewportTags}
8474
8776
  \${hasFavicon ? "" : '<link rel="icon" href="data:,">'}
8475
8777
  \${suppressDefaultTitle ? "" : "<title>" + title + "</title>"}\${metaTags}\${rendererHead ? "\\n " + rendererHead : ""}
8476
8778
  <link rel="stylesheet" href="/__farm_client_css_href__">
@@ -8720,7 +9022,8 @@ async function handleFarmRequestInContext(
8720
9022
  try {
8721
9023
  // Wrap 404 page with root layout if available
8722
9024
  let notFoundElement = createFarmNotFoundElement(pathname);
8723
- const applicableLayouts = getApplicableLayouts("/");
9025
+ // No page matched, so a layout inside a route group cannot apply.
9026
+ const applicableLayouts = getApplicableLayouts("/", null);
8724
9027
 
8725
9028
  // Wrap with layouts (from innermost to outermost)
8726
9029
  for (let i = applicableLayouts.length - 1; i >= 0; i--) {
@@ -8764,6 +9067,7 @@ async function handleFarmRequestInContext(
8764
9067
  () => ' ' + renderFarmClientBootstrapScript() + '\\n' +
8765
9068
  ' <script type="module" src="/__farm_client_js_src__"></script>\\n</body>',
8766
9069
  );
9070
+ fullHtml = ensureFarmDocumentMeta(fullHtml, notFoundMetadata.viewport);
8767
9071
  if (!fullHtml.trim().startsWith('<!DOCTYPE')) {
8768
9072
  fullHtml = '<!DOCTYPE html>\\n' + fullHtml;
8769
9073
  }
@@ -8772,7 +9076,7 @@ async function handleFarmRequestInContext(
8772
9076
  <html lang="en">
8773
9077
  <head>
8774
9078
  <meta charset="UTF-8">
8775
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
9079
+ \${notFoundMetadata.viewport}
8776
9080
  \${notFoundMetadata.hasFavicon ? "" : '<link rel="icon" href="data:,">'}
8777
9081
  <link rel="stylesheet" href="/__farm_client_css_href__">
8778
9082
  <title>\${notFoundMetadata.title}</title>\${notFoundMetadata.tags}
@@ -9037,23 +9341,20 @@ function configMiddlewareMayHandlePath(config, pathname) {
9037
9341
  if (!hasFarmMiddlewareConfig(config)) return false;
9038
9342
  const entries = Array.isArray(config) ? config : [config];
9039
9343
  return entries.some((entry) => {
9040
- if (entry.exclude?.some((pattern) => middlewarePatternMatches(pattern, pathname))) {
9041
- return false;
9042
- }
9043
- if (!entry.matcher) return true;
9044
- const matchers = Array.isArray(entry.matcher) ? entry.matcher : [entry.matcher];
9045
- return matchers.some((matcher) => {
9046
- if (typeof matcher === "function") return true;
9047
- return (typeof matcher === "string" || matcher instanceof RegExp) && middlewarePatternMatches(matcher, pathname);
9048
- });
9344
+ if (!entry.matcher && !entry.exclude) return true;
9345
+ const matchers = entry.matcher ? (Array.isArray(entry.matcher) ? entry.matcher : [entry.matcher]).map(
9346
+ (matcher) => (
9347
+ // A request-aware matcher cannot be proven safe at build time.
9348
+ typeof matcher === "function" ? () => true : matcher
9349
+ )
9350
+ ) : void 0;
9351
+ const compiled = compileMiddlewareConfig({ matcher: matchers, exclude: entry.exclude });
9352
+ return matchesCompiledMiddlewareConfig(pathname, compiled, {}).matched;
9049
9353
  });
9050
9354
  }
9051
9355
  __name(configMiddlewareMayHandlePath, "configMiddlewareMayHandlePath");
9052
9356
  function appMiddlewareMayHandlePath(middlewareRoutes, pathname) {
9053
- return middlewareRoutes.some((route) => {
9054
- if (route.path === "/") return true;
9055
- return middlewarePatternMatches(route.path, pathname) || middlewarePatternMatches(`${route.path}/**`, pathname);
9056
- });
9357
+ return middlewareRoutes.some((route) => matchesMiddlewareRoute(pathname, route).matched);
9057
9358
  }
9058
9359
  __name(appMiddlewareMayHandlePath, "appMiddlewareMayHandlePath");
9059
9360
  function routePatternSpecificity(pattern) {
@@ -9120,8 +9421,8 @@ async function buildNitroUniversal(config, routeManager, apiRouteManager, server
9120
9421
  const isVercel = preset === "vercel" || preset === "vercel-edge";
9121
9422
  const isCloudflareWorker = preset === "cloudflare-module";
9122
9423
  const outputDir = resolveDeployOutputPath(root, config.deploy.outputDir);
9123
- const runtimeServerOutputDir = isVercel ? path5.join(outputDir, "functions", "__nitro.func") : path5.join(outputDir, "server");
9124
- const ssrOutputDir = path5.join(root, distDir, "ssr");
9424
+ const runtimeServerOutputDir = isVercel ? path6.join(outputDir, "functions", "__nitro.func") : path6.join(outputDir, "server");
9425
+ const ssrOutputDir = path6.join(root, distDir, "ssr");
9125
9426
  const imageRuntime = resolveImageRuntime(config, preset);
9126
9427
  const hasGeneratedMetadataImages = Array.from(routeManager.getMetadataImages().values()).some(
9127
9428
  (image) => image.sourceType === "module"
@@ -9205,11 +9506,11 @@ async function buildNitroUniversal(config, routeManager, apiRouteManager, server
9205
9506
  }
9206
9507
  await fs.mkdir(ssrOutputDir, { recursive: true });
9207
9508
  for (const [fileName, output] of Object.entries(ssrBundle)) {
9208
- const filePath = path5.join(ssrOutputDir, fileName);
9209
- await fs.mkdir(path5.dirname(filePath), { recursive: true });
9509
+ const filePath = path6.join(ssrOutputDir, fileName);
9510
+ await fs.mkdir(path6.dirname(filePath), { recursive: true });
9210
9511
  await fs.writeFile(filePath, output.type === "chunk" ? output.code : output.source);
9211
9512
  }
9212
- const nitroEntryPath = path5.join(ssrOutputDir, "nitro-entry.mjs");
9513
+ const nitroEntryPath = path6.join(ssrOutputDir, "nitro-entry.mjs");
9213
9514
  const nodeAdapterModule = preset === "node-server" ? resolveNitroRuntimeDependency(root, "srvx/node") : null;
9214
9515
  const nitroEntryCode = `
9215
9516
  // Farm.js Nitro Entry
@@ -9362,18 +9663,27 @@ function toFarmNodeResponse(request, response) {
9362
9663
  }` : ""}
9363
9664
  `.trim();
9364
9665
  await fs.writeFile(nitroEntryPath, nitroEntryCode);
9365
- const farmNodeServerEntryPath = preset === "node-server" ? path5.join(ssrOutputDir, "farm-node-server-entry.mjs") : null;
9666
+ const farmNodeServerEntryPath = preset === "node-server" ? path6.join(ssrOutputDir, "farm-node-server-entry.mjs") : null;
9366
9667
  if (farmNodeServerEntryPath && nodeAdapterModule) {
9367
9668
  await fs.writeFile(
9368
9669
  farmNodeServerEntryPath,
9369
9670
  createFarmNodeServerEntry({
9370
- nitroEntryFile: path5.basename(nitroEntryPath),
9671
+ nitroEntryFile: path6.basename(nitroEntryPath),
9371
9672
  nodeAdapterModule,
9372
9673
  server: config.server,
9373
9674
  websocketAdapterModule: resolveNitroRuntimeDependency(root, "crossws/adapters/node")
9374
9675
  })
9375
9676
  );
9376
9677
  }
9678
+ const farmNetlifyEntryPath = preset === "netlify" ? path6.join(ssrOutputDir, "farm-netlify-entry.mjs") : null;
9679
+ if (farmNetlifyEntryPath) {
9680
+ await fs.writeFile(
9681
+ farmNetlifyEntryPath,
9682
+ createFarmNetlifyEntry({
9683
+ nitroNetlifyEntry: resolveNitroNetlifyEntry(resolveNitroPackageEntry(root))
9684
+ })
9685
+ );
9686
+ }
9377
9687
  const prebuiltSSRPlugin = createExternalSSRBundlePlugin(
9378
9688
  nitroEntryPath,
9379
9689
  ssrOutputDir,
@@ -9399,6 +9709,7 @@ function toFarmNodeResponse(request, response) {
9399
9709
  let nitroConfig = {
9400
9710
  preset,
9401
9711
  ...farmNodeServerEntryPath ? { entry: farmNodeServerEntryPath } : {},
9712
+ ...farmNetlifyEntryPath ? { entry: farmNetlifyEntryPath } : {},
9402
9713
  rootDir: root,
9403
9714
  // Farm registers every handler, task, and plugin explicitly. Scanning the
9404
9715
  // project root would bundle an app's own `middleware/`, `api/`, `routes/`,
@@ -9406,7 +9717,7 @@ function toFarmNodeResponse(request, response) {
9406
9717
  // `src` directory), as Nitro handlers outside Farm's aliases.
9407
9718
  serverDir: false,
9408
9719
  serverEntry: false,
9409
- buildDir: path5.join(root, distDir, ".nitro"),
9720
+ buildDir: path6.join(root, distDir, ".nitro"),
9410
9721
  alias: resolveNitroInternalRuntimeAliases(root),
9411
9722
  compatibilityDate: "2024-12-01",
9412
9723
  output: resolveFarmNitroOutputConfig(preset, outputDir),
@@ -9482,7 +9793,7 @@ function toFarmNodeResponse(request, response) {
9482
9793
  if (pluginManager) {
9483
9794
  nitroConfig = await pluginManager.runHookSerial("beforeNitroBuild", nitroConfig);
9484
9795
  }
9485
- const expectedServerDir = path5.join(outputDir, "server");
9796
+ const expectedServerDir = path6.join(outputDir, "server");
9486
9797
  const customRollupKeys = Object.keys(nitroConfig.rollupConfig || {}).filter(
9487
9798
  (key) => key !== "external" && key !== "plugins"
9488
9799
  );
@@ -9495,9 +9806,9 @@ function toFarmNodeResponse(request, response) {
9495
9806
  snapshotSSRRebundleOptions(nitroConfig)
9496
9807
  );
9497
9808
  const requestedBuilder = nitroConfig.builder ?? process.env.NITRO_BUILDER;
9498
- const canReusePrebuiltSSR = isPrebuiltSSRCandidate && nitroConfig.preset === "node-server" && (requestedBuilder === void 0 || requestedBuilder === "rollup" || requestedBuilder === "rolldown") && nitroConfig.sourcemap === false && !hasCustomOxcOptions && !hasLateBuildMutationConfig && !hasUnsupportedSSRRebundleOverrides && nitroConfig.rollupConfig?.external === nitroRollupExternal && !hasRollupPlugins(nitroConfig.rollupConfig?.plugins) && customRollupKeys.length === 0 && path5.resolve(nitroConfig.output?.serverDir || "") === path5.resolve(expectedServerDir) && Boolean(
9809
+ const canReusePrebuiltSSR = isPrebuiltSSRCandidate && nitroConfig.preset === "node-server" && (requestedBuilder === void 0 || requestedBuilder === "rollup" || requestedBuilder === "rolldown") && nitroConfig.sourcemap === false && !hasCustomOxcOptions && !hasLateBuildMutationConfig && !hasUnsupportedSSRRebundleOverrides && nitroConfig.rollupConfig?.external === nitroRollupExternal && !hasRollupPlugins(nitroConfig.rollupConfig?.plugins) && customRollupKeys.length === 0 && path6.resolve(nitroConfig.output?.serverDir || "") === path6.resolve(expectedServerDir) && Boolean(
9499
9810
  nitroConfig.handlers?.some(
9500
- (handler) => path5.resolve(handler?.handler || "") === nitroEntryPath
9811
+ (handler) => path6.resolve(handler?.handler || "") === nitroEntryPath
9501
9812
  )
9502
9813
  );
9503
9814
  const selectRolldownBuilder = canReusePrebuiltSSR && requestedBuilder === void 0 && await canUseRolldownBuilder();
@@ -9558,7 +9869,7 @@ function toFarmNodeResponse(request, response) {
9558
9869
  nitroInstance.routing.sync();
9559
9870
  });
9560
9871
  }
9561
- if (farmNodeServerEntryPath) {
9872
+ if (farmNodeServerEntryPath || farmNetlifyEntryPath) {
9562
9873
  nitroInstance.hooks.hook("prerender:config", (prerendererConfig) => {
9563
9874
  delete prerendererConfig.entry;
9564
9875
  });
@@ -9584,10 +9895,10 @@ function toFarmNodeResponse(request, response) {
9584
9895
  });
9585
9896
  }
9586
9897
  prerenderer.hooks.hook("compiled", async () => {
9587
- const prerenderServerDir = path5.join(outputDir, "server");
9898
+ const prerenderServerDir = path6.join(outputDir, "server");
9588
9899
  await copyPrebuiltSSRBundle(
9589
9900
  ssrBundle,
9590
- path5.join(prerenderServerDir, FARM_SSR_OUTPUT_DIR),
9901
+ path6.join(prerenderServerDir, FARM_SSR_OUTPUT_DIR),
9591
9902
  null,
9592
9903
  fs
9593
9904
  );
@@ -9660,7 +9971,7 @@ function toFarmNodeResponse(request, response) {
9660
9971
  const copyResults = await Promise.allSettled([
9661
9972
  prebuiltSSRFilesResult.value ? writeSSRBundleFiles(
9662
9973
  prebuiltSSRFilesResult.value,
9663
- path5.join(outputDir, "server", FARM_SSR_OUTPUT_DIR),
9974
+ path6.join(outputDir, "server", FARM_SSR_OUTPUT_DIR),
9664
9975
  fs
9665
9976
  ) : Promise.resolve(),
9666
9977
  runtimeCopyPromise
@@ -9670,7 +9981,7 @@ function toFarmNodeResponse(request, response) {
9670
9981
  );
9671
9982
  if (failedCopy) throw failedCopy.reason;
9672
9983
  if (canReusePrebuiltSSR) {
9673
- await registerPrebuiltSSRPackageImport(path5.join(outputDir, "server"), ssrEntryFile, fs);
9984
+ await registerPrebuiltSSRPackageImport(path6.join(outputDir, "server"), ssrEntryFile, fs);
9674
9985
  logger.info("\u26A1 Reused Farm's prebuilt SSR bundle for the Node output");
9675
9986
  }
9676
9987
  if (useRolldownBuilder) {
@@ -9695,11 +10006,11 @@ function resolveFarmNitroOutputConfig(preset, outputDir) {
9695
10006
  return {
9696
10007
  dir: outputDir,
9697
10008
  ...preset === "node-server" ? {
9698
- serverDir: path5.join(outputDir, "server"),
9699
- publicDir: path5.join(outputDir, "public")
10009
+ serverDir: path6.join(outputDir, "server"),
10010
+ publicDir: path6.join(outputDir, "public")
9700
10011
  } : isVercel ? {
9701
- serverDir: path5.join(outputDir, "functions", "__nitro.func"),
9702
- publicDir: path5.join(outputDir, "static")
10012
+ serverDir: path6.join(outputDir, "functions", "__nitro.func"),
10013
+ publicDir: path6.join(outputDir, "static")
9703
10014
  } : {}
9704
10015
  };
9705
10016
  }
@@ -9717,8 +10028,8 @@ async function writeSSRBundleFiles(files, targetDir, fs) {
9717
10028
  await fs.rm(targetDir, { recursive: true, force: true });
9718
10029
  await Promise.all(
9719
10030
  files.map(async ({ fileName, contents }) => {
9720
- const targetPath = path5.join(targetDir, fileName);
9721
- await fs.mkdir(path5.dirname(targetPath), { recursive: true });
10031
+ const targetPath = path6.join(targetDir, fileName);
10032
+ await fs.mkdir(path6.dirname(targetPath), { recursive: true });
9722
10033
  await fs.writeFile(targetPath, contents);
9723
10034
  })
9724
10035
  );
@@ -9729,7 +10040,7 @@ async function copyPrebuiltSSRBundle(ssrBundle, targetDir, minifyOptions, fs) {
9729
10040
  }
9730
10041
  __name(copyPrebuiltSSRBundle, "copyPrebuiltSSRBundle");
9731
10042
  async function registerPrebuiltSSRPackageImport(serverDir, ssrEntryFile, fs) {
9732
- const packagePath = path5.join(serverDir, "package.json");
10043
+ const packagePath = path6.join(serverDir, "package.json");
9733
10044
  const packageJSON = await fs.readFile(packagePath, "utf8").then((contents) => JSON.parse(contents)).catch((error) => {
9734
10045
  if (error.code === "ENOENT") return { type: "module" };
9735
10046
  throw error;
@@ -9760,18 +10071,18 @@ async function moveVercelOutputPath(src, dest, fs) {
9760
10071
  }
9761
10072
  __name(moveVercelOutputPath, "moveVercelOutputPath");
9762
10073
  async function postProcessVercelOutput(root, outputDir, fs, config, farmWorkflows, routeRuntimeManifest) {
9763
- const serverDir = path5.join(outputDir, "server");
9764
- const functionsDir = path5.join(outputDir, "functions");
9765
- const nitroFuncDir = path5.join(functionsDir, "__nitro.func");
9766
- const staticDir = path5.join(outputDir, "static");
9767
- const publicDir = path5.join(outputDir, "public");
10074
+ const serverDir = path6.join(outputDir, "server");
10075
+ const functionsDir = path6.join(outputDir, "functions");
10076
+ const nitroFuncDir = path6.join(functionsDir, "__nitro.func");
10077
+ const staticDir = path6.join(outputDir, "static");
10078
+ const publicDir = path6.join(outputDir, "public");
9768
10079
  await fs.mkdir(nitroFuncDir, { recursive: true });
9769
10080
  const serverContents = await fs.readdir(serverDir).catch((error) => {
9770
10081
  if (error.code === "ENOENT") return [];
9771
10082
  throw error;
9772
10083
  });
9773
10084
  for (const file of serverContents) {
9774
- await moveVercelOutputPath(path5.join(serverDir, file), path5.join(nitroFuncDir, file), fs);
10085
+ await moveVercelOutputPath(path6.join(serverDir, file), path6.join(nitroFuncDir, file), fs);
9775
10086
  }
9776
10087
  if (serverContents.length > 0) await fs.rm(serverDir, { recursive: true, force: true });
9777
10088
  try {
@@ -9781,7 +10092,7 @@ async function postProcessVercelOutput(root, outputDir, fs, config, farmWorkflow
9781
10092
  }
9782
10093
  await copyFarmDocsContentForVercel(config, root, nitroFuncDir, fs);
9783
10094
  await copyPrismaClientForVercel(root, nitroFuncDir, fs);
9784
- const configPath = path5.join(outputDir, "config.json");
10095
+ const configPath = path6.join(outputDir, "config.json");
9785
10096
  const configContent = await fs.readFile(configPath, "utf-8");
9786
10097
  const vercelConfig = JSON.parse(configContent);
9787
10098
  const runtimeRoutes = await createFarmVercelRouteRuntimeFunctions(
@@ -9809,22 +10120,22 @@ __name(postProcessVercelOutput, "postProcessVercelOutput");
9809
10120
  async function copyFarmDocsContentForVercel(config, root, nitroFuncDir, fs) {
9810
10121
  const docsContentDir = resolveBuildDocsContentDir(config, root);
9811
10122
  if (!docsContentDir) return;
9812
- const bundledContentDir = path5.join(nitroFuncDir, "farm-docs-content");
10123
+ const bundledContentDir = path6.join(nitroFuncDir, "farm-docs-content");
9813
10124
  const lastModifiedManifest = createFarmDocsLastModifiedManifest(docsContentDir, {
9814
10125
  fallback: "now"
9815
10126
  });
9816
10127
  await fs.rm(bundledContentDir, { recursive: true, force: true });
9817
- await fs.mkdir(path5.dirname(bundledContentDir), { recursive: true });
10128
+ await fs.mkdir(path6.dirname(bundledContentDir), { recursive: true });
9818
10129
  await fs.cp(docsContentDir, bundledContentDir, {
9819
10130
  recursive: true,
9820
10131
  force: true
9821
10132
  });
9822
10133
  await fs.writeFile(
9823
- path5.join(bundledContentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST),
10134
+ path6.join(bundledContentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST),
9824
10135
  `${JSON.stringify(lastModifiedManifest, null, 2)}
9825
10136
  `
9826
10137
  );
9827
- logger.info(`\u{1F4DA} Bundled docs content for Vercel: ${path5.relative(root, docsContentDir)}`);
10138
+ logger.info(`\u{1F4DA} Bundled docs content for Vercel: ${path6.relative(root, docsContentDir)}`);
9828
10139
  }
9829
10140
  __name(copyFarmDocsContentForVercel, "copyFarmDocsContentForVercel");
9830
10141
  function resolveServerFunctionPlatform(preset) {
@@ -9845,7 +10156,7 @@ function platformFieldAllows(field, value) {
9845
10156
  __name(platformFieldAllows, "platformFieldAllows");
9846
10157
  async function stageSharpRuntime(config, root, distDir, fs, preset) {
9847
10158
  const functionPlatform = resolveServerFunctionPlatform(preset);
9848
- const projectRequire = createRequire(path5.join(root, "package.json"));
10159
+ const projectRequire = createRequire(path6.join(root, "package.json"));
9849
10160
  let sharpRequire = projectRequire;
9850
10161
  if (!resolvePackageJson(projectRequire, "sharp")) {
9851
10162
  try {
@@ -9855,10 +10166,10 @@ async function stageSharpRuntime(config, root, distDir, fs, preset) {
9855
10166
  }
9856
10167
  const copiedPackages = /* @__PURE__ */ new Map();
9857
10168
  const packageCopies = /* @__PURE__ */ new Map();
9858
- const stageRoot = path5.join(root, distDir, "tmp");
10169
+ const stageRoot = path6.join(root, distDir, "tmp");
9859
10170
  await fs.mkdir(stageRoot, { recursive: true });
9860
- const stageDir = await fs.mkdtemp(path5.join(stageRoot, "sharp-runtime-"));
9861
- const targetNodeModules = path5.join(stageDir, "node_modules");
10171
+ const stageDir = await fs.mkdtemp(path6.join(stageRoot, "sharp-runtime-"));
10172
+ const targetNodeModules = path6.join(stageDir, "node_modules");
9862
10173
  function copyPackage(packageName, parentRequire) {
9863
10174
  const activeCopy = packageCopies.get(packageName);
9864
10175
  if (activeCopy) return activeCopy;
@@ -9872,10 +10183,10 @@ async function stageSharpRuntime(config, root, distDir, fs, preset) {
9872
10183
  if (!packageJsonPath) return;
9873
10184
  const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf8"));
9874
10185
  if (functionPlatform && !packageSupportsPlatform(packageJson, functionPlatform)) return;
9875
- const packageDir = path5.dirname(packageJsonPath);
9876
- const targetDir = path5.join(targetNodeModules, ...packageName.split("/"));
10186
+ const packageDir = path6.dirname(packageJsonPath);
10187
+ const targetDir = path6.join(targetNodeModules, ...packageName.split("/"));
9877
10188
  copiedPackages.set(packageName, String(packageJson.version || "*"));
9878
- await fs.mkdir(path5.dirname(targetDir), { recursive: true });
10189
+ await fs.mkdir(path6.dirname(targetDir), { recursive: true });
9879
10190
  const packageRequire = createRequire(packageJsonPath);
9880
10191
  const dependencies = {
9881
10192
  ...packageJson.dependencies,
@@ -9912,8 +10223,8 @@ async function stageSharpRuntime(config, root, distDir, fs, preset) {
9912
10223
  }
9913
10224
  __name(stageSharpRuntime, "stageSharpRuntime");
9914
10225
  async function installStagedSharpRuntime(staged, nitroFuncDir, fs) {
9915
- const stagedNodeModules = path5.join(staged.stageDir, "node_modules");
9916
- const targetNodeModules = path5.join(nitroFuncDir, "node_modules");
10226
+ const stagedNodeModules = path6.join(staged.stageDir, "node_modules");
10227
+ const targetNodeModules = path6.join(nitroFuncDir, "node_modules");
9917
10228
  try {
9918
10229
  await mergeStagedDirectory(stagedNodeModules, targetNodeModules, fs);
9919
10230
  const functionPackage = await readNitroOutputPackage(nitroFuncDir, fs);
@@ -9943,8 +10254,8 @@ async function mergeStagedDirectory(sourceDir, targetDir, fs) {
9943
10254
  const entries = await fs.readdir(sourceDir, { withFileTypes: true });
9944
10255
  await settleAllOrThrow(
9945
10256
  entries.map(async (entry) => {
9946
- const sourcePath = path5.join(sourceDir, entry.name);
9947
- const targetPath = path5.join(targetDir, entry.name);
10257
+ const sourcePath = path6.join(sourceDir, entry.name);
10258
+ const targetPath = path6.join(targetDir, entry.name);
9948
10259
  try {
9949
10260
  await fs.rename(sourcePath, targetPath);
9950
10261
  return;
@@ -9972,14 +10283,14 @@ __name(mergeStagedDirectory, "mergeStagedDirectory");
9972
10283
  function assertMetadataImageRuntimeInstalled(root, metadataImageRoutes) {
9973
10284
  const generated = metadataImageRoutes.find((image) => image.sourceType === "module");
9974
10285
  if (!generated || resolveMetadataImageRuntimePackageJson(root)) return;
9975
- const file = generated.modulePath ? toPosixPath(path5.relative(root, generated.modulePath)) : "";
10286
+ const file = generated.modulePath ? toPosixPath(path6.relative(root, generated.modulePath)) : "";
9976
10287
  throw new Error(
9977
10288
  `${file || "A generated metadata image"} renders with @vercel/og, which is not installed. ${VERCEL_OG_INSTALL_HINT}`
9978
10289
  );
9979
10290
  }
9980
10291
  __name(assertMetadataImageRuntimeInstalled, "assertMetadataImageRuntimeInstalled");
9981
10292
  function resolveMetadataImageRuntimePackageJson(root) {
9982
- const projectRequire = createRequire(path5.join(root, "package.json"));
10293
+ const projectRequire = createRequire(path6.join(root, "package.json"));
9983
10294
  const packageJsonPath = resolvePackageJson(projectRequire, "@vercel/og");
9984
10295
  if (packageJsonPath) return packageJsonPath;
9985
10296
  try {
@@ -9993,9 +10304,9 @@ async function copyMetadataImageRuntime(root, nitroFuncDir, fs) {
9993
10304
  const packageJsonPath = resolveMetadataImageRuntimePackageJson(root);
9994
10305
  if (!packageJsonPath) return;
9995
10306
  const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf8"));
9996
- const packageDir = path5.dirname(packageJsonPath);
9997
- const targetDir = path5.join(nitroFuncDir, "node_modules", "@vercel", "og");
9998
- await fs.mkdir(path5.dirname(targetDir), { recursive: true });
10307
+ const packageDir = path6.dirname(packageJsonPath);
10308
+ const targetDir = path6.join(nitroFuncDir, "node_modules", "@vercel", "og");
10309
+ await fs.mkdir(path6.dirname(targetDir), { recursive: true });
9999
10310
  await fs.cp(packageDir, targetDir, {
10000
10311
  recursive: true,
10001
10312
  force: true,
@@ -10012,7 +10323,7 @@ async function copyMetadataImageRuntime(root, nitroFuncDir, fs) {
10012
10323
  }
10013
10324
  __name(copyMetadataImageRuntime, "copyMetadataImageRuntime");
10014
10325
  async function readNitroOutputPackage(outputDir, fs) {
10015
- const packagePath = path5.join(outputDir, "package.json");
10326
+ const packagePath = path6.join(outputDir, "package.json");
10016
10327
  return fs.readFile(packagePath, "utf8").then((contents) => JSON.parse(contents)).catch((error) => {
10017
10328
  if (error.code === "ENOENT") return {};
10018
10329
  throw error;
@@ -10022,7 +10333,7 @@ __name(readNitroOutputPackage, "readNitroOutputPackage");
10022
10333
  async function writeNitroOutputPackage(outputDir, packageJson, fs) {
10023
10334
  await fs.mkdir(outputDir, { recursive: true });
10024
10335
  await fs.writeFile(
10025
- path5.join(outputDir, "package.json"),
10336
+ path6.join(outputDir, "package.json"),
10026
10337
  `${JSON.stringify(packageJson, null, 2)}
10027
10338
  `
10028
10339
  );
@@ -10039,18 +10350,18 @@ function resolvePackageJson(parentRequire, packageName) {
10039
10350
  }
10040
10351
  }
10041
10352
  try {
10042
- let directory = path5.dirname(metadataModule ?? parentRequire.resolve(packageName));
10043
- while (directory !== path5.dirname(directory)) {
10044
- const candidate = path5.join(directory, "package.json");
10045
- if (existsSync(candidate)) {
10353
+ let directory = path6.dirname(metadataModule ?? parentRequire.resolve(packageName));
10354
+ while (directory !== path6.dirname(directory)) {
10355
+ const candidate = path6.join(directory, "package.json");
10356
+ if (existsSync2(candidate)) {
10046
10357
  try {
10047
10358
  const manifest = JSON.parse(readFileSync(candidate, "utf8"));
10048
10359
  if (manifest.name === packageName) return candidate;
10049
10360
  } catch {
10050
10361
  }
10051
10362
  }
10052
- if (path5.basename(directory) === "node_modules") break;
10053
- directory = path5.dirname(directory);
10363
+ if (path6.basename(directory) === "node_modules") break;
10364
+ directory = path6.dirname(directory);
10054
10365
  }
10055
10366
  } catch {
10056
10367
  }
@@ -10058,23 +10369,23 @@ function resolvePackageJson(parentRequire, packageName) {
10058
10369
  }
10059
10370
  __name(resolvePackageJson, "resolvePackageJson");
10060
10371
  async function copyPrismaClientForVercel(root, nitroFuncDir, fs) {
10061
- const projectRequire = createRequire(path5.join(root, "package.json"));
10372
+ const projectRequire = createRequire(path6.join(root, "package.json"));
10062
10373
  let prismaClientDir;
10063
10374
  try {
10064
- prismaClientDir = path5.dirname(projectRequire.resolve("@prisma/client/default.js"));
10375
+ prismaClientDir = path6.dirname(projectRequire.resolve("@prisma/client/default.js"));
10065
10376
  } catch {
10066
10377
  return;
10067
10378
  }
10068
- const generatedClientDir = path5.join(prismaClientDir, "..", "..", ".prisma", "client");
10379
+ const generatedClientDir = path6.join(prismaClientDir, "..", "..", ".prisma", "client");
10069
10380
  try {
10070
10381
  await fs.access(generatedClientDir);
10071
10382
  } catch {
10072
10383
  return;
10073
10384
  }
10074
- const targetNodeModules = path5.join(nitroFuncDir, "node_modules");
10075
- const targetPrismaScopeDir = path5.join(targetNodeModules, "@prisma");
10076
- const targetGeneratedDir = path5.join(targetNodeModules, ".prisma", "client");
10077
- const targetClientDir = path5.join(targetPrismaScopeDir, "client");
10385
+ const targetNodeModules = path6.join(nitroFuncDir, "node_modules");
10386
+ const targetPrismaScopeDir = path6.join(targetNodeModules, "@prisma");
10387
+ const targetGeneratedDir = path6.join(targetNodeModules, ".prisma", "client");
10388
+ const targetClientDir = path6.join(targetPrismaScopeDir, "client");
10078
10389
  await fs.mkdir(targetPrismaScopeDir, { recursive: true });
10079
10390
  await fs.cp(prismaClientDir, targetClientDir, {
10080
10391
  recursive: true,
@@ -10084,7 +10395,7 @@ async function copyPrismaClientForVercel(root, nitroFuncDir, fs) {
10084
10395
  recursive: true,
10085
10396
  force: true
10086
10397
  });
10087
- const clientPackagePath = path5.join(prismaClientDir, "package.json");
10398
+ const clientPackagePath = path6.join(prismaClientDir, "package.json");
10088
10399
  const [functionPackage, clientPackageContent] = await Promise.all([
10089
10400
  readNitroOutputPackage(nitroFuncDir, fs),
10090
10401
  fs.readFile(clientPackagePath, "utf-8")
@@ -10243,9 +10554,9 @@ async function buildWithProductionNodeEnv(inputConfig, options) {
10243
10554
  } else {
10244
10555
  const { build: legacyViteBuild } = await import("vite");
10245
10556
  logger.info("\u{1F4E6} Building client bundle...");
10246
- await buildClient2(legacyViteBuild, config, root, srcDir, path6.join(root, distDir, "client"));
10557
+ await buildClient2(legacyViteBuild, config, root, srcDir, path7.join(root, distDir, "client"));
10247
10558
  logger.info("\u{1F4E6} Building SSR bundle...");
10248
- await buildSSR(legacyViteBuild, config, root, srcDir, path6.join(root, distDir, "server"));
10559
+ await buildSSR(legacyViteBuild, config, root, srcDir, path7.join(root, distDir, "server"));
10249
10560
  logger.info(`\u{1F680} Building server with Nitro (preset: ${preset})...`);
10250
10561
  await buildNitro(
10251
10562
  config,
@@ -10425,17 +10736,17 @@ async function buildSSR(viteBuild, config, root, srcDir, outputDir) {
10425
10736
  }
10426
10737
  __name(buildSSR, "buildSSR");
10427
10738
  function resolveLegacyPageEntry(config, root, srcDir) {
10428
- const appDir = path6.join(root, srcDir, "app");
10739
+ const appDir = path7.join(root, srcDir, "app");
10429
10740
  for (const extension of getFarmRendererComponentExtensions(config.renderer)) {
10430
- const candidate = path6.join(appDir, `page${extension}`);
10431
- if (existsSync2(candidate)) return candidate;
10741
+ const candidate = path7.join(appDir, `page${extension}`);
10742
+ if (existsSync3(candidate)) return candidate;
10432
10743
  }
10433
- return path6.join(appDir, "page.tsx");
10744
+ return path7.join(appDir, "page.tsx");
10434
10745
  }
10435
10746
  __name(resolveLegacyPageEntry, "resolveLegacyPageEntry");
10436
10747
  async function buildNitro(config, routeManager, apiRouteManager, serverRenderer, preset, root, distDir, pluginManager) {
10437
10748
  const [{ createNitroConfig }, { createNitro, build: nitroBuild }] = await Promise.all([
10438
- import("./nitro-NAKCRVHX.mjs"),
10749
+ import("./nitro-MXRDCXWZ.mjs"),
10439
10750
  import("nitro/builder")
10440
10751
  ]);
10441
10752
  let nitroConfig = await createNitroConfig(
@@ -10449,18 +10760,18 @@ async function buildNitro(config, routeManager, apiRouteManager, serverRenderer,
10449
10760
  nitroConfig = await pluginManager.runHookSerial("beforeNitroBuild", nitroConfig);
10450
10761
  }
10451
10762
  const outputDir = resolveDeployOutputPath(root, config.deploy.outputDir);
10452
- const serverOutputDir = path6.join(outputDir, "server");
10453
- const publicOutputDir = path6.join(outputDir, "public");
10763
+ const serverOutputDir = path7.join(outputDir, "server");
10764
+ const publicOutputDir = path7.join(outputDir, "public");
10454
10765
  const { mkdir, cp } = await import("fs/promises");
10455
10766
  await mkdir(serverOutputDir, { recursive: true });
10456
10767
  await mkdir(publicOutputDir, { recursive: true });
10457
- const clientDir = path6.join(root, distDir, "client");
10768
+ const clientDir = path7.join(root, distDir, "client");
10458
10769
  try {
10459
10770
  await mkdir(publicOutputDir, { recursive: true });
10460
10771
  await cp(clientDir, publicOutputDir, { recursive: true });
10461
10772
  logger.info("\u{1F4E6} Copied client assets to public directory");
10462
- const manifestPath = path6.join(publicOutputDir, "farm-client-manifest.json");
10463
- const assetsDir = path6.join(publicOutputDir, "assets");
10773
+ const manifestPath = path7.join(publicOutputDir, "farm-client-manifest.json");
10774
+ const assetsDir = path7.join(publicOutputDir, "assets");
10464
10775
  const manifestExists = await import("fs/promises").then(
10465
10776
  (fs) => fs.access(manifestPath).then(() => true).catch(() => false)
10466
10777
  );
@@ -10476,8 +10787,8 @@ async function buildNitro(config, routeManager, apiRouteManager, serverRenderer,
10476
10787
  logger.error(`\u274C Failed to copy client assets: ${error}`);
10477
10788
  throw error;
10478
10789
  }
10479
- const serverDir = path6.join(root, distDir, "server");
10480
- const nitroServerDir = path6.join(root, distDir, ".nitro", "server", "farm");
10790
+ const serverDir = path7.join(root, distDir, "server");
10791
+ const nitroServerDir = path7.join(root, distDir, ".nitro", "server", "farm");
10481
10792
  try {
10482
10793
  await mkdir(nitroServerDir, { recursive: true });
10483
10794
  await cp(serverDir, nitroServerDir, { recursive: true });
@@ -10486,7 +10797,7 @@ async function buildNitro(config, routeManager, apiRouteManager, serverRenderer,
10486
10797
  logger.warn(`Could not copy SSR bundles: ${error}`);
10487
10798
  }
10488
10799
  const nitro = await createNitro(nitroConfig);
10489
- const registryPath = path6.join(root, distDir, ".nitro", "server", "farm-registry.ts");
10800
+ const registryPath = path7.join(root, distDir, ".nitro", "server", "farm-registry.ts");
10490
10801
  try {
10491
10802
  const { farmRegistry } = await import(
10492
10803
  /* @vite-ignore */
@@ -10503,7 +10814,7 @@ async function buildNitro(config, routeManager, apiRouteManager, serverRenderer,
10503
10814
  }
10504
10815
  farmRegistry.routePaths = routePaths;
10505
10816
  try {
10506
- const clientManifestPath = path6.join(root, distDir, "client", "farm-client-manifest.json");
10817
+ const clientManifestPath = path7.join(root, distDir, "client", "farm-client-manifest.json");
10507
10818
  const { readFile } = await import("fs/promises");
10508
10819
  const manifestContent = await readFile(clientManifestPath, "utf-8");
10509
10820
  farmRegistry.clientManifest = JSON.parse(manifestContent);