@farm.js/core 0.1.34 → 0.1.36

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 (282) hide show
  1. package/dist/agent-mcp-BVExL8rZ.d.mts +109 -0
  2. package/dist/agent-mcp-handler-LPJ2CADR.mjs +19 -0
  3. package/dist/agent-mcp-handler-SJAHFSPI.cjs +19 -0
  4. package/dist/agent-mcp-luzfXK-P.d.ts +109 -0
  5. package/dist/agent-runtime.cjs +5 -3
  6. package/dist/agent-runtime.d.mts +4 -5
  7. package/dist/agent-runtime.d.ts +4 -5
  8. package/dist/agent-runtime.mjs +4 -2
  9. package/dist/api/route-manager.cjs +7 -7
  10. package/dist/api/route-manager.d.mts +15 -10
  11. package/dist/api/route-manager.d.ts +15 -10
  12. package/dist/api/route-manager.mjs +6 -6
  13. package/dist/api/runtime.cjs +7 -5
  14. package/dist/api/runtime.d.mts +7 -66
  15. package/dist/api/runtime.d.ts +7 -66
  16. package/dist/api/runtime.mjs +7 -5
  17. package/dist/api.cjs +9 -9
  18. package/dist/api.d.mts +8 -9
  19. package/dist/api.d.ts +8 -9
  20. package/dist/api.mjs +8 -8
  21. package/dist/{app-q4rmZlXK.d.mts → app-BukwkFIu.d.mts} +52 -12
  22. package/dist/{app-DgotYGbq.d.ts → app-Yfa2dsFy.d.ts} +52 -12
  23. package/dist/app-markdown.cjs +6 -6
  24. package/dist/app-markdown.d.mts +5 -6
  25. package/dist/app-markdown.d.ts +5 -6
  26. package/dist/app-markdown.mjs +5 -5
  27. package/dist/{chunk-XV5DJTBX.mjs → chunk-276VJSM6.mjs} +627 -260
  28. package/dist/{chunk-36MK5YCW.cjs → chunk-2YTDKNH3.cjs} +547 -240
  29. package/dist/{chunk-VHANUNEG.mjs → chunk-35GKZR22.mjs} +2 -2
  30. package/dist/{chunk-LR5QSC2P.mjs → chunk-35WV46VL.mjs} +399 -92
  31. package/dist/{chunk-UX5S4JEO.cjs → chunk-42NHY7HW.cjs} +57 -7
  32. package/dist/{chunk-U4PTAHW3.mjs → chunk-4E5AEDKY.mjs} +7 -11
  33. package/dist/{chunk-NGVORZVZ.mjs → chunk-4E5WBPEG.mjs} +73 -351
  34. package/dist/{chunk-AQZFOP7S.mjs → chunk-4GLOOWKE.mjs} +5 -5
  35. package/dist/{chunk-7BT4H4P7.cjs → chunk-4NU4GGTC.cjs} +2 -2
  36. package/dist/{chunk-AGC75XAE.mjs → chunk-4WCZJQUO.mjs} +55 -5
  37. package/dist/chunk-4WQ6PGSJ.cjs +367 -0
  38. package/dist/{chunk-QCFFHV5H.mjs → chunk-4WVJLURN.mjs} +1 -1
  39. package/dist/chunk-6SJ2KJTA.mjs +314 -0
  40. package/dist/chunk-75RZHGLS.cjs +135 -0
  41. package/dist/{chunk-P64MIF5B.cjs → chunk-ADEA7PN3.cjs} +483 -60
  42. package/dist/{chunk-YQVSHTMR.mjs → chunk-AJQTP4OO.mjs} +1 -1
  43. package/dist/{chunk-TA5G2HWD.cjs → chunk-AO6RYU5N.cjs} +31 -28
  44. package/dist/{chunk-MOKLYNHV.cjs → chunk-BO36SELV.cjs} +6 -6
  45. package/dist/{chunk-7Y6ZNFPX.mjs → chunk-BPOF5U4N.mjs} +17 -7
  46. package/dist/{chunk-JHWOVJ3M.mjs → chunk-BUGNQIHC.mjs} +5 -0
  47. package/dist/{chunk-TDFPACVX.cjs → chunk-CBJJH36A.cjs} +50 -25
  48. package/dist/{chunk-VKNHTSAP.cjs → chunk-CGBDNNSM.cjs} +2 -2
  49. package/dist/chunk-CI6E3UOH.cjs +314 -0
  50. package/dist/{chunk-QZCT2CQ4.mjs → chunk-CXEN47J3.mjs} +64 -2
  51. package/dist/{chunk-ATK2R4CH.cjs → chunk-D227TIEN.cjs} +14 -4
  52. package/dist/{chunk-QGYRXFU2.cjs → chunk-D2BB47NB.cjs} +8 -8
  53. package/dist/chunk-DTSROJ5J.mjs +367 -0
  54. package/dist/{chunk-ODBZYBAB.cjs → chunk-DZ5ZVB2K.cjs} +1 -1
  55. package/dist/{chunk-ROUTX2E5.cjs → chunk-ECKF2BAM.cjs} +18 -5
  56. package/dist/{chunk-3LUF2PE2.cjs → chunk-EK4QAEFZ.cjs} +67 -5
  57. package/dist/{chunk-VVBO3QH7.mjs → chunk-ENLZ4R3Y.mjs} +10 -1
  58. package/dist/{chunk-XXJU7FCC.cjs → chunk-EUV4YR3V.cjs} +2 -2
  59. package/dist/{chunk-HR5KPHC2.mjs → chunk-EWET4D2Y.mjs} +1 -1
  60. package/dist/{chunk-PXKIEXZD.mjs → chunk-F5QO4FNE.mjs} +1 -1
  61. package/dist/{chunk-MIDIZJZC.cjs → chunk-FO427P6I.cjs} +22 -12
  62. package/dist/{chunk-AWC4VUZL.cjs → chunk-GQ3Z3IZI.cjs} +14 -14
  63. package/dist/{chunk-JDPAKVS4.mjs → chunk-GQRWBCWK.mjs} +8 -5
  64. package/dist/{chunk-75WGQVQA.cjs → chunk-HITLGIAO.cjs} +10 -1
  65. package/dist/{chunk-WNNYOOIB.mjs → chunk-HOXTWRGB.mjs} +1 -1
  66. package/dist/{chunk-KROWKCUH.cjs → chunk-JGLC4TO3.cjs} +8 -1
  67. package/dist/{chunk-QJ3J6MZT.cjs → chunk-JNUWCDTF.cjs} +8 -8
  68. package/dist/{chunk-BTAG7LI7.cjs → chunk-JZVADIOD.cjs} +2 -2
  69. package/dist/{chunk-EM6SBQKM.cjs → chunk-KIIMAWOJ.cjs} +37 -2
  70. package/dist/{chunk-43FMW62B.mjs → chunk-KMTGADN3.mjs} +28 -0
  71. package/dist/{chunk-GOABMOX3.mjs → chunk-LSZAVSGY.mjs} +468 -45
  72. package/dist/{chunk-2NQQ5H5G.cjs → chunk-M7MKQXAF.cjs} +2 -1
  73. package/dist/{chunk-GNSDTTWZ.mjs → chunk-MKYBIIAQ.mjs} +30 -5
  74. package/dist/{chunk-ZHPHJPQP.cjs → chunk-MRMI32SN.cjs} +88 -366
  75. package/dist/{chunk-7M52YUMY.cjs → chunk-N2NAS2AM.cjs} +2 -2
  76. package/dist/{chunk-SJVKK4JE.cjs → chunk-NMHWYWDR.cjs} +1144 -777
  77. package/dist/chunk-NRDBW4MP.mjs +45 -0
  78. package/dist/{chunk-657WJNRY.mjs → chunk-O6I6VWKK.mjs} +20 -5
  79. package/dist/{chunk-O27L4YAA.mjs → chunk-O6WAEAX3.mjs} +2 -2
  80. package/dist/chunk-OFZUJMCU.mjs +601 -0
  81. package/dist/{chunk-ZKP7C2B6.mjs → chunk-OHLSEQ57.mjs} +22 -13
  82. package/dist/{chunk-X242HVD5.mjs → chunk-OO7GXVSR.mjs} +1 -1
  83. package/dist/chunk-PTZ2TVNE.cjs +178 -0
  84. package/dist/{chunk-3ATMYLLJ.mjs → chunk-Q2KB32T4.mjs} +1 -1
  85. package/dist/{chunk-LHODW25H.mjs → chunk-QORUJDIV.mjs} +2 -2
  86. package/dist/{chunk-UBO4SGH4.mjs → chunk-RHAZ22ZN.mjs} +2 -1
  87. package/dist/{chunk-G26MUMKL.cjs → chunk-S6VYG6XU.cjs} +23 -8
  88. package/dist/{chunk-6VVL3MHY.mjs → chunk-SC2WYWPF.mjs} +1 -1
  89. package/dist/{chunk-MPEYMSCF.cjs → chunk-SDOTRX3V.cjs} +5 -5
  90. package/dist/{chunk-BMWDEBXO.cjs → chunk-SHLXACIO.cjs} +31 -3
  91. package/dist/{chunk-LMJ7VRHZ.mjs → chunk-T4OGRVNS.mjs} +13 -3
  92. package/dist/{chunk-T5CERMEH.cjs → chunk-T5OJPTVN.cjs} +2 -2
  93. package/dist/{chunk-Z2YLTERK.cjs → chunk-TE2G5ION.cjs} +6 -6
  94. package/dist/chunk-UH6QN5NL.mjs +178 -0
  95. package/dist/{chunk-PQDFUSXD.cjs → chunk-UVW64BCB.cjs} +44 -35
  96. package/dist/{chunk-VCCUOMQN.mjs → chunk-VILIPRS6.mjs} +1 -1
  97. package/dist/{chunk-A5FGU2WU.cjs → chunk-VQLJWDVW.cjs} +19 -23
  98. package/dist/{chunk-VPTDD5XF.cjs → chunk-WBKEZXWE.cjs} +5 -0
  99. package/dist/{chunk-K3F2E6GS.cjs → chunk-WC5UV2HQ.cjs} +2 -2
  100. package/dist/chunk-WWFTAUFG.cjs +45 -0
  101. package/dist/{chunk-ZUSJDQ2Q.mjs → chunk-WWIKMBRN.mjs} +1 -1
  102. package/dist/{chunk-3VSKDFAT.mjs → chunk-WZ77PUAM.mjs} +1 -1
  103. package/dist/{chunk-CLJYVZAD.mjs → chunk-XCMCS4DA.mjs} +11 -1
  104. package/dist/{chunk-F6OHXPWR.mjs → chunk-YFILVET3.mjs} +8 -1
  105. package/dist/{chunk-DZ4DTRJ5.cjs → chunk-YKX5BK66.cjs} +7 -7
  106. package/dist/chunk-YSLWRWWP.cjs +601 -0
  107. package/dist/{chunk-LI2LMOLR.mjs → chunk-YWMZUGIS.mjs} +18 -5
  108. package/dist/chunk-ZLAT2CWY.mjs +135 -0
  109. package/dist/{chunk-XF7Q24PF.mjs → chunk-ZMMBIVQM.mjs} +35 -0
  110. package/dist/{chunk-U74I55WB.cjs → chunk-ZWM5KGAA.cjs} +19 -9
  111. package/dist/{client-plugins-CLObcuCq.d.mts → client-plugins-C3mK9Pol.d.mts} +300 -7
  112. package/dist/{client-plugins-DZjHC4Mi.d.ts → client-plugins-r1mOtSC1.d.ts} +300 -7
  113. package/dist/client-plugins.d.mts +4 -5
  114. package/dist/client-plugins.d.ts +4 -5
  115. package/dist/client.cjs +5 -5
  116. package/dist/client.d.mts +8 -9
  117. package/dist/client.d.ts +8 -9
  118. package/dist/client.mjs +4 -4
  119. package/dist/config.d.mts +4 -5
  120. package/dist/config.d.ts +4 -5
  121. package/dist/{devtools-RNXCTS4R.mjs → devtools-ERIKFEXX.mjs} +11 -10
  122. package/dist/{devtools-HU6Y2MNV.cjs → devtools-JZJJY5CK.cjs} +12 -11
  123. package/dist/docs.cjs +15 -14
  124. package/dist/docs.d.mts +41 -4
  125. package/dist/docs.d.ts +41 -4
  126. package/dist/docs.mjs +14 -13
  127. package/dist/i18n/client.d.mts +2 -2
  128. package/dist/i18n/client.d.ts +2 -2
  129. package/dist/i18n/index.d.mts +3 -3
  130. package/dist/i18n/index.d.ts +3 -3
  131. package/dist/i18n/server.d.mts +5 -5
  132. package/dist/i18n/server.d.ts +5 -5
  133. package/dist/image/server.cjs +3 -3
  134. package/dist/image/server.mjs +2 -2
  135. package/dist/image/sharp.cjs +10 -10
  136. package/dist/image/sharp.mjs +2 -2
  137. package/dist/{index-a-8Z5kZU.d.mts → index-BJJfLxJo.d.mts} +2 -2
  138. package/dist/{index-BWVfxIsO.d.ts → index-CwoOP-MW.d.ts} +2 -2
  139. package/dist/index.cjs +51 -44
  140. package/dist/index.d.mts +20 -21
  141. package/dist/index.d.ts +20 -21
  142. package/dist/index.mjs +50 -43
  143. package/dist/integrations.cjs +7 -3
  144. package/dist/integrations.d.mts +4 -5
  145. package/dist/integrations.d.ts +4 -5
  146. package/dist/integrations.mjs +6 -2
  147. package/dist/internal/app-markdown-runtime.cjs +5 -5
  148. package/dist/internal/app-markdown-runtime.d.mts +5 -6
  149. package/dist/internal/app-markdown-runtime.d.ts +5 -6
  150. package/dist/internal/app-markdown-runtime.mjs +4 -4
  151. package/dist/internal/build-runtime.cjs +32 -30
  152. package/dist/internal/build-runtime.d.mts +6 -7
  153. package/dist/internal/build-runtime.d.ts +6 -7
  154. package/dist/internal/build-runtime.mjs +31 -29
  155. package/dist/internal/cli-runtime.cjs +17 -16
  156. package/dist/internal/cli-runtime.mjs +16 -15
  157. package/dist/internal/client-error-overlay.cjs +6 -6
  158. package/dist/internal/client-error-overlay.mjs +2 -2
  159. package/dist/internal/client-runtime.cjs +2 -2
  160. package/dist/internal/client-runtime.mjs +1 -1
  161. package/dist/internal/compression-runtime.d.mts +4 -5
  162. package/dist/internal/compression-runtime.d.ts +4 -5
  163. package/dist/internal/config-runtime.cjs +12 -11
  164. package/dist/internal/config-runtime.d.mts +5 -6
  165. package/dist/internal/config-runtime.d.ts +5 -6
  166. package/dist/internal/config-runtime.mjs +11 -10
  167. package/dist/internal/isolated-boundary.cjs +3 -2
  168. package/dist/internal/isolated-boundary.d.mts +1 -1
  169. package/dist/internal/isolated-boundary.d.ts +1 -1
  170. package/dist/internal/isolated-boundary.mjs +2 -1
  171. package/dist/internal/metadata-image-runtime.cjs +3 -3
  172. package/dist/internal/metadata-image-runtime.mjs +2 -2
  173. package/dist/internal/product-telemetry-runtime.cjs +2 -2
  174. package/dist/internal/product-telemetry-runtime.mjs +1 -1
  175. package/dist/internal/production-runtime.cjs +63 -25
  176. package/dist/internal/production-runtime.d.mts +117 -37
  177. package/dist/internal/production-runtime.d.ts +117 -37
  178. package/dist/internal/production-runtime.mjs +65 -27
  179. package/dist/internal/server-tree.cjs +12 -0
  180. package/dist/internal/server-tree.d.mts +27 -0
  181. package/dist/internal/server-tree.d.ts +27 -0
  182. package/dist/internal/server-tree.mjs +12 -0
  183. package/dist/{layers-BRQF5ETU.mjs → layers-UTB43B7A.mjs} +1 -1
  184. package/dist/layers-VUWIOFEO.cjs +18 -0
  185. package/dist/markdown.cjs +4 -4
  186. package/dist/markdown.d.mts +4 -5
  187. package/dist/markdown.d.ts +4 -5
  188. package/dist/markdown.mjs +3 -3
  189. package/dist/middleware.cjs +7 -7
  190. package/dist/middleware.d.mts +6 -7
  191. package/dist/middleware.d.ts +6 -7
  192. package/dist/middleware.mjs +6 -6
  193. package/dist/navigation.cjs +5 -5
  194. package/dist/navigation.d.mts +7 -8
  195. package/dist/navigation.d.ts +7 -8
  196. package/dist/navigation.mjs +4 -4
  197. package/dist/{nitro-HSAQFXSS.cjs → nitro-7F65EZZS.cjs} +3 -3
  198. package/dist/{nitro-4XGPNIK4.mjs → nitro-MPZJGPXK.mjs} +2 -2
  199. package/dist/{observability-BupkiN0m.d.mts → observability-CoXunYhS.d.mts} +4 -3
  200. package/dist/{observability-BupkiN0m.d.ts → observability-CoXunYhS.d.ts} +4 -3
  201. package/dist/observability.d.mts +1 -1
  202. package/dist/observability.d.ts +1 -1
  203. package/dist/plugin.cjs +28 -26
  204. package/dist/plugin.d.mts +4 -5
  205. package/dist/plugin.d.ts +4 -5
  206. package/dist/plugin.mjs +27 -25
  207. package/dist/{production-runtime-CysZl3EV.d.mts → production-runtime-CCeVZXst.d.mts} +4 -4
  208. package/dist/{production-runtime-BU5ETAK9.d.ts → production-runtime-DPnsggY3.d.ts} +4 -4
  209. package/dist/query/client.cjs +6 -6
  210. package/dist/query/client.mjs +2 -2
  211. package/dist/{render-plan-CKr4ltOd.d.mts → render-plan-BuGaPFe6.d.mts} +1 -1
  212. package/dist/{render-plan-D72O1qm4.d.ts → render-plan-Cw4f5E_R.d.ts} +1 -1
  213. package/dist/renderer/react/server.cjs +10 -4
  214. package/dist/renderer/react/server.d.mts +2 -1
  215. package/dist/renderer/react/server.d.ts +2 -1
  216. package/dist/renderer/react/server.mjs +7 -1
  217. package/dist/renderer-client.cjs +5 -5
  218. package/dist/renderer-client.d.mts +6 -7
  219. package/dist/renderer-client.d.ts +6 -7
  220. package/dist/renderer-client.mjs +2 -2
  221. package/dist/renderer.d.mts +2 -0
  222. package/dist/renderer.d.ts +2 -0
  223. package/dist/{request-DbyOYI2j.d.ts → request-Bkg-hERy.d.ts} +1 -1
  224. package/dist/{request-Be83WafN.d.mts → request-CsGARcAw.d.mts} +1 -1
  225. package/dist/request.d.mts +5 -6
  226. package/dist/request.d.ts +5 -6
  227. package/dist/{resolver-PPEeiJ6M.d.ts → resolver-DadfRL6F.d.ts} +1 -1
  228. package/dist/{resolver-DhW0CqZN.d.mts → resolver-khasx3fU.d.mts} +1 -1
  229. package/dist/{route-rendering-CtVMpV-k.d.ts → route-rendering-BUZMH_64.d.ts} +1 -1
  230. package/dist/{route-rendering-BG56SzvJ.d.mts → route-rendering-f11yh5dp.d.mts} +1 -1
  231. package/dist/{router-D94-SDlW.d.ts → router-B8CR9GbD.d.ts} +1 -1
  232. package/dist/{router-ALUvm8gC.d.mts → router-Cp6yRE8A.d.mts} +1 -1
  233. package/dist/routes.d.mts +4 -5
  234. package/dist/routes.d.ts +4 -5
  235. package/dist/{runtime-BirxPwbZ.d.ts → runtime-BgDQzBiu.d.ts} +2 -2
  236. package/dist/runtime-CAEv36S_.d.mts +69 -0
  237. package/dist/runtime-CQVsT330.d.ts +69 -0
  238. package/dist/{runtime-AOJge4vQ.d.mts → runtime-CV2UCV-5.d.mts} +2 -2
  239. package/dist/server-action-security.cjs +3 -3
  240. package/dist/server-action-security.mjs +2 -2
  241. package/dist/server-fn.cjs +4 -4
  242. package/dist/server-fn.mjs +3 -3
  243. package/dist/server-plugins.d.mts +5 -6
  244. package/dist/server-plugins.d.ts +5 -6
  245. package/dist/server-query.cjs +5 -5
  246. package/dist/server-query.mjs +4 -4
  247. package/dist/server.cjs +47 -45
  248. package/dist/server.d.mts +13 -14
  249. package/dist/server.d.ts +13 -14
  250. package/dist/server.mjs +30 -28
  251. package/dist/{spa-router-CxK3USIz.d.ts → spa-router-BuciWGCZ.d.ts} +3 -3
  252. package/dist/{spa-router-DbxNRKOB.d.mts → spa-router-DwbqGkGj.d.mts} +3 -3
  253. package/dist/testing.cjs +9 -9
  254. package/dist/testing.d.mts +4 -5
  255. package/dist/testing.d.ts +4 -5
  256. package/dist/testing.mjs +7 -7
  257. package/dist/{types-Z0aotQ8w.d.mts → types-CnH8DOqo.d.mts} +1 -1
  258. package/dist/{types-Z0aotQ8w.d.ts → types-CnH8DOqo.d.ts} +1 -1
  259. package/dist/{utils-4wVRcpOw.d.mts → utils-B9V0S_yL.d.mts} +1 -1
  260. package/dist/{utils-311Y8eoK.d.ts → utils-CaoWKtYM.d.ts} +1 -1
  261. package/dist/version.cjs +2 -2
  262. package/dist/version.mjs +1 -1
  263. package/dist/vite.cjs +28 -26
  264. package/dist/vite.d.mts +4 -5
  265. package/dist/vite.d.ts +4 -5
  266. package/dist/vite.mjs +27 -25
  267. package/dist/{workflows-CR9ex-gz.d.ts → workflows-jZ4BcdoZ.d.mts} +1 -1
  268. package/dist/{workflows-CR9ex-gz.d.mts → workflows-jZ4BcdoZ.d.ts} +1 -1
  269. package/dist/workflows.cjs +3 -3
  270. package/dist/workflows.d.mts +1 -1
  271. package/dist/workflows.d.ts +1 -1
  272. package/dist/workflows.mjs +2 -2
  273. package/package.json +9 -1
  274. package/dist/chunk-M64YUMA4.cjs +0 -58
  275. package/dist/chunk-QLQ32WC4.mjs +0 -58
  276. package/dist/layers-4PNE2HOY.cjs +0 -18
  277. package/dist/metadata-2HSU2i_w.d.mts +0 -52
  278. package/dist/metadata-Cjs8JMRM.d.ts +0 -52
  279. package/dist/types-DFbjpjXX.d.mts +0 -105
  280. package/dist/types-DFbjpjXX.d.ts +0 -105
  281. package/dist/{chunk-2F2ER724.cjs → chunk-BPMATOP2.cjs} +2 -2
  282. package/dist/{chunk-IHNMMXHV.mjs → chunk-OTC5BDGO.mjs} +3 -3
@@ -10,7 +10,7 @@ import {
10
10
  import {
11
11
  compileFarmDocsAdapterEdgeManifest,
12
12
  createFarmDocsAPIHandler
13
- } from "./chunk-U4PTAHW3.mjs";
13
+ } from "./chunk-4E5AEDKY.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-O27L4YAA.mjs";
23
+ } from "./chunk-O6WAEAX3.mjs";
24
24
  import {
25
25
  generateFarmDocsSearchClientRuntime,
26
26
  isFarmDocsSearchEnabled,
@@ -37,7 +37,7 @@ import {
37
37
  getDeployTargetForPreset,
38
38
  hasCustomFarmRouteContext,
39
39
  resolveDeployOutputPath
40
- } from "./chunk-ZKP7C2B6.mjs";
40
+ } from "./chunk-OHLSEQ57.mjs";
41
41
  import {
42
42
  resolveFarmInstrumentationFile
43
43
  } from "./chunk-ZZSRYEYU.mjs";
@@ -47,7 +47,6 @@ 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,
53
52
  collectFarmWebMCPTools,
@@ -57,6 +56,7 @@ import {
57
56
  createMarkdownPageHydrationPlanner,
58
57
  describeSuppressedAsyncHydration,
59
58
  enforceFarmIsolatedHydrationRouteBudget,
59
+ farmDocsClientConfigPlugin,
60
60
  farmFontImportsPlugin,
61
61
  farmPluginMayAffectRuntimePath,
62
62
  generateClientCachePersistenceCode,
@@ -74,20 +74,32 @@ import {
74
74
  resolveFarmClientCacheAdapterEntry,
75
75
  resolveFarmImageProviderForRuntime,
76
76
  resolveFarmIsolatedClientHydrationMode,
77
- resolveFarmNotFoundComponentPath
78
- } from "./chunk-XV5DJTBX.mjs";
77
+ resolveFarmNotFoundComponentPath,
78
+ usesFarmServerTree
79
+ } from "./chunk-276VJSM6.mjs";
79
80
  import {
80
81
  findRequestBoundSourceBlockers,
81
82
  generateFarmTypeArtifacts,
82
83
  parseRouteRenderingDirective,
83
84
  resolveRouteRenderingConfigFromFile
84
- } from "./chunk-AQZFOP7S.mjs";
85
+ } from "./chunk-4GLOOWKE.mjs";
85
86
  import {
86
87
  FARM_API_CATALOG_PATH,
88
+ FARM_APP_MANIFEST_LEGACY_PATH,
87
89
  FARM_APP_MANIFEST_PATH,
90
+ HOISTED_HEAD_ELEMENT,
91
+ getRouteDirectoryDepth,
92
+ getRouteGroupScope,
88
93
  resolveFarmApiCatalogInput,
89
- resolveFarmAppManifestInput
90
- } from "./chunk-GOABMOX3.mjs";
94
+ resolveFarmAppManifestInput,
95
+ routeBoundaryCoversDirectory,
96
+ stripRouteGroups
97
+ } from "./chunk-LSZAVSGY.mjs";
98
+ import {
99
+ FARM_DEFAULT_MCP_PATH,
100
+ createFarmDefaultMCPServer,
101
+ farmConfigMountsMCP
102
+ } from "./chunk-UH6QN5NL.mjs";
91
103
  import {
92
104
  isFarmPreviewDeploymentEnvironment
93
105
  } from "./chunk-BOYNDCZL.mjs";
@@ -97,7 +109,7 @@ import {
97
109
  import {
98
110
  generateFarmDocsAdapterClientRuntime,
99
111
  getFarmDocsAdapterConfigModule
100
- } from "./chunk-VVBO3QH7.mjs";
112
+ } from "./chunk-ENLZ4R3Y.mjs";
101
113
  import {
102
114
  resolveFarmDocsFontAssets,
103
115
  toFarmDocsPublicFontAssets
@@ -107,7 +119,7 @@ import {
107
119
  } from "./chunk-GHFS7RUB.mjs";
108
120
  import {
109
121
  getFarmAppDirectories
110
- } from "./chunk-JHWOVJ3M.mjs";
122
+ } from "./chunk-BUGNQIHC.mjs";
111
123
  import {
112
124
  REACT_RENDERER,
113
125
  getFarmRendererCapabilities,
@@ -119,7 +131,7 @@ import {
119
131
  } from "./chunk-DAATZTKJ.mjs";
120
132
  import {
121
133
  applyFarmCspHashesToHtml
122
- } from "./chunk-NGVORZVZ.mjs";
134
+ } from "./chunk-4E5WBPEG.mjs";
123
135
  import {
124
136
  applyFarmCronVercelCrons,
125
137
  createFarmCronCloudflareConfig,
@@ -131,27 +143,28 @@ import {
131
143
  } from "./chunk-4OOBRCJX.mjs";
132
144
  import {
133
145
  isFarmMarkdownPageFile
134
- } from "./chunk-AGC75XAE.mjs";
146
+ } from "./chunk-4WCZJQUO.mjs";
135
147
  import {
136
148
  resolveFarmMdxComponentsModulePath,
137
149
  resolveMdxConfig
138
150
  } from "./chunk-FA2W42OV.mjs";
139
151
  import {
140
152
  getFarmMarkdownAlternatePath
141
- } from "./chunk-ZUSJDQ2Q.mjs";
153
+ } from "./chunk-WWIKMBRN.mjs";
142
154
  import {
143
155
  applyFarmWorkflowVercelCrons,
144
156
  prepareFarmWorkflowsForNitro
145
- } from "./chunk-3ATMYLLJ.mjs";
157
+ } from "./chunk-Q2KB32T4.mjs";
146
158
  import {
159
+ FARM_INTEGRATION_API_BASE_PATH_KEY,
147
160
  getFarmIntegrationPluginServerRuntime,
148
161
  getIntegrationProviders
149
- } from "./chunk-GNSDTTWZ.mjs";
162
+ } from "./chunk-MKYBIIAQ.mjs";
150
163
  import {
151
164
  appendMiddlewareDirectory,
152
165
  appendMiddlewareRoutePath,
153
166
  compareMiddlewareRouteLocations
154
- } from "./chunk-7Y6ZNFPX.mjs";
167
+ } from "./chunk-BPOF5U4N.mjs";
155
168
  import {
156
169
  compileMiddlewareConfig,
157
170
  matchesCompiledMiddlewareConfig,
@@ -159,7 +172,7 @@ import {
159
172
  } from "./chunk-JG6DJF5A.mjs";
160
173
  import {
161
174
  APIRouteManager
162
- } from "./chunk-LMJ7VRHZ.mjs";
175
+ } from "./chunk-T4OGRVNS.mjs";
163
176
  import {
164
177
  readFarmI18nCatalogs
165
178
  } from "./chunk-QCFBDFRS.mjs";
@@ -184,6 +197,9 @@ import {
184
197
  resolveFarmAPIServerBasePath,
185
198
  resolveFarmAPIServerRoutePath
186
199
  } from "./chunk-BTHHUD7Q.mjs";
200
+ import {
201
+ FARM_VERSION
202
+ } from "./chunk-OO7GXVSR.mjs";
187
203
  import {
188
204
  getFarmPresetRuntime
189
205
  } from "./chunk-2A3EQHXX.mjs";
@@ -251,7 +267,7 @@ __name(resolveHashedClientJsSrc, "resolveHashedClientJsSrc");
251
267
  // src/nitro/universal-build.ts
252
268
  import os from "os";
253
269
  import path6 from "path";
254
- import { constants as fsConstants, existsSync as existsSync2, readFileSync, realpathSync } from "fs";
270
+ import { constants as fsConstants, existsSync as existsSync2, readFileSync, realpathSync, statSync } from "fs";
255
271
  import { fileURLToPath } from "url";
256
272
  import { builtinModules, createRequire } from "module";
257
273
  import { isDeepStrictEqual } from "util";
@@ -760,10 +776,14 @@ export default async function farmNetlifyHandler(request, context) {
760
776
  __name(createFarmNetlifyEntry, "createFarmNetlifyEntry");
761
777
 
762
778
  // src/nitro/node-server-entry.ts
779
+ var FARM_NODE_ENV_MODULE_FILE = "farm-node-env.mjs";
780
+ var FARM_NODE_ENV_MODULE_SOURCE = `if (!process.env.NODE_ENV) process.env.NODE_ENV = "production";
781
+ `;
763
782
  function createFarmNodeServerEntry(options) {
764
783
  const serverConfig = JSON.stringify(options.server);
765
784
  const nitroEntryImport = `./${options.nitroEntryFile.replace(/^\.\//, "")}`;
766
785
  return `
786
+ import "./${FARM_NODE_ENV_MODULE_FILE}";
767
787
  import "#nitro/virtual/polyfills";
768
788
  import { NodeRequest, serve } from ${JSON.stringify(options.nodeAdapterModule)};
769
789
  import wsAdapter from ${JSON.stringify(options.websocketAdapterModule)};
@@ -1618,7 +1638,7 @@ async function discoverMiddlewareRoutes(appDir) {
1618
1638
  });
1619
1639
  }
1620
1640
  for (const entry of entries) {
1621
- if (!entry.isDirectory() || entry.name.startsWith(".") || entry.name.startsWith("_")) {
1641
+ if (!entry.isDirectory() || entry.name.startsWith(".")) {
1622
1642
  continue;
1623
1643
  }
1624
1644
  await walk(
@@ -1677,6 +1697,7 @@ async function buildUniversal(config, routeManager, apiRouteManager, serverRende
1677
1697
  const markdownSourcePath = entry.markdownSourcePath || (isFarmMarkdownPageFile(entry.modulePath) ? entry.modulePath : void 0);
1678
1698
  pageRoutes.push({
1679
1699
  pattern,
1700
+ ...entry.directory ? { directory: entry.directory } : {},
1680
1701
  modulePath: entry.modulePath,
1681
1702
  ...markdownSourcePath ? {
1682
1703
  source: readFileSync(markdownSourcePath, "utf8"),
@@ -1689,6 +1710,7 @@ async function buildUniversal(config, routeManager, apiRouteManager, serverRende
1689
1710
  (entry) => ({
1690
1711
  name: entry.name,
1691
1712
  ownerPattern: entry.ownerPattern,
1713
+ ...entry.ownerDirectory ? { ownerDirectory: entry.ownerDirectory } : {},
1692
1714
  pattern: entry.pattern,
1693
1715
  modulePath: entry.modulePath,
1694
1716
  containerId: entry.containerId,
@@ -2036,7 +2058,8 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2036
2058
  };
2037
2059
  }
2038
2060
  });
2039
- const layoutAppliesToRoute = /* @__PURE__ */ __name((layoutPattern, routePattern) => layoutPattern === "/" || routePattern === layoutPattern || routePattern.startsWith(`${layoutPattern}/`), "layoutAppliesToRoute");
2061
+ const layoutAppliesToRoute = routeBoundaryCoversDirectory;
2062
+ const routeDirectory = /* @__PURE__ */ __name((route) => route.directory ?? route.pattern, "routeDirectory");
2040
2063
  const adapterOwnsDocsRuntime = Boolean(
2041
2064
  isReactRenderer(config.renderer) && config.docs?.enabled && config.docs.adapter?.server && config.docs.adapter.react
2042
2065
  );
@@ -2070,8 +2093,8 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2070
2093
  })),
2071
2094
  [
2072
2095
  ...routePlans.map(({ route, metadata }) => ({
2073
- pattern: route.pattern,
2074
- depth: route.pattern.split("/").filter(Boolean).length,
2096
+ pattern: routeDirectory(route),
2097
+ depth: getRouteDirectoryDepth(routeDirectory(route)),
2075
2098
  metadata
2076
2099
  })),
2077
2100
  ...syntheticDocsPatterns.map((pattern) => ({
@@ -2092,7 +2115,7 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2092
2115
  layoutAppliesToRoute
2093
2116
  );
2094
2117
  for (const layout of clientLayouts) {
2095
- const matchesBuiltRoute = pageRoutes.some((route) => layoutAppliesToRoute(layout.pattern, route.pattern)) || Boolean(adapterDocsEntry && layoutAppliesToRoute(layout.pattern, adapterDocsEntry));
2118
+ const matchesBuiltRoute = pageRoutes.some((route) => layoutAppliesToRoute(layout.pattern, routeDirectory(route))) || Boolean(adapterDocsEntry && layoutAppliesToRoute(layout.pattern, adapterDocsEntry));
2096
2119
  if (matchesBuiltRoute && layout.suppressedAsyncHydration) {
2097
2120
  logger.warn(`\u26A0\uFE0F ${describeSuppressedAsyncHydration(layout.pattern, layout.fallbackReason)}`);
2098
2121
  }
@@ -2114,7 +2137,7 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2114
2137
  if (isAdapterDocsRoute(route.pattern)) continue;
2115
2138
  try {
2116
2139
  const applicableClientLayouts = clientLayouts.filter(
2117
- (layout) => (layout.shouldHydrate || layout.hasIsolatedClientBoundaries) && layoutAppliesToRoute(layout.pattern, route.pattern)
2140
+ (layout) => (layout.shouldHydrate || layout.hasIsolatedClientBoundaries) && layoutAppliesToRoute(layout.pattern, routeDirectory(route))
2118
2141
  );
2119
2142
  if (metadata.suppressedAsyncHydration) {
2120
2143
  logger.warn(
@@ -2141,7 +2164,9 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2141
2164
  isolatedBoundaries: [
2142
2165
  ...metadata.hasIsolatedClientBoundaries ? metadata.isolatedBoundaries : [],
2143
2166
  ...applicableClientLayouts.filter((layout) => layout.hasIsolatedClientBoundaries).flatMap((layout) => layout.isolatedBoundaries)
2144
- ]
2167
+ ],
2168
+ // The server renders a server tree only below a hydrating layout.
2169
+ ...usesFarmServerTree(metadata) && applicableClientLayouts.some((layout) => layout.shouldHydrate) ? { serverTree: true } : {}
2145
2170
  });
2146
2171
  logger.info(`\u{1F4F1} Found hydratable route: ${route.pattern} -> ${route.modulePath}`);
2147
2172
  }
@@ -2298,6 +2323,9 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2298
2323
  ...rendererVitePlugins,
2299
2324
  ...config.vite.plugins || [],
2300
2325
  farmServerOnlyEntriesPlugin(),
2326
+ farmDocsClientConfigPlugin(
2327
+ adapterOwnsDocsRuntime ? getFarmDocsAdapterConfigModule(config.docs) : void 0
2328
+ ),
2301
2329
  // Plugin to redirect @farm.js/core imports to client-only exports
2302
2330
  {
2303
2331
  name: "farm-client-only-imports",
@@ -3151,8 +3179,10 @@ __farmConfigureApp(__farmAppSetup);` : `import React, { createRoot, hydrateRoot
3151
3179
  if (!layout.hasIsolatedClientBoundaries) {
3152
3180
  layoutImportStatements.push(`import Layout${index} from "${relativePath}";`);
3153
3181
  }
3182
+ const groupScope = getRouteGroupScope(layout.pattern);
3183
+ const groupFields = groupScope ? `, urlPattern: ${JSON.stringify(stripRouteGroups(layout.pattern))}, groupScope: ${JSON.stringify(groupScope)}` : "";
3154
3184
  layoutRegistrations.push(
3155
- ` { pattern: ${JSON.stringify(layout.pattern)}, Component: ${layout.hasIsolatedClientBoundaries ? "null" : `Layout${index}`}, shouldHydrate: ${JSON.stringify(layout.shouldHydrate)}, islandStrategy: ${JSON.stringify(layout.islandStrategy)} }`
3185
+ ` { pattern: ${JSON.stringify(layout.pattern)}${groupFields}, Component: ${layout.hasIsolatedClientBoundaries ? "null" : `Layout${index}`}, shouldHydrate: ${JSON.stringify(layout.shouldHydrate)}, islandStrategy: ${JSON.stringify(layout.islandStrategy)} }`
3156
3186
  );
3157
3187
  });
3158
3188
  const layoutImports = layoutImportStatements.join("\n");
@@ -3497,7 +3527,8 @@ document.addEventListener("click", function(e) {
3497
3527
  }
3498
3528
  const load = page.pageShouldHydrate ? `() => import(${JSON.stringify(toImportPath(page.modulePath))}).then((module) => module.default)` : "null";
3499
3529
  routeEntries.push(` {
3500
- pattern: ${JSON.stringify(page.pattern)},
3530
+ pattern: ${JSON.stringify(page.pattern)},${page.directory ? `
3531
+ directory: ${JSON.stringify(page.directory)},` : ""}
3501
3532
  pageShouldHydrate: ${JSON.stringify(page.pageShouldHydrate)},
3502
3533
  ${page.hasIsolatedClientBoundaries ? "hasIsolatedClientBoundaries: true," : ""}
3503
3534
  islandStrategy: ${JSON.stringify(page.islandStrategy)},
@@ -3506,20 +3537,22 @@ document.addEventListener("click", function(e) {
3506
3537
  }`);
3507
3538
  });
3508
3539
  const isolatedHydrationEnabled = isolatedBoundaryModules.size > 0;
3509
- const isolatedHydrationImport = isolatedHydrationEnabled ? `import { createFarmIsolatedHydrationRuntime, createFarmServerPageBoundary, wrapFarmIsolatedClientGraph } from "@farm.js/core/internal/isolated-boundary";` : "";
3540
+ const serverTreeEnabled = isolatedHydrationEnabled && clientPages.some((page) => page.serverTree);
3541
+ const isolatedHydrationImport = isolatedHydrationEnabled ? `import { createFarmIsolatedHydrationRuntime, createFarmServerPageBoundary, wrapFarmIsolatedClientGraph } from "@farm.js/core/internal/isolated-boundary";${serverTreeEnabled ? '\nimport { createFarmServerTreeElement } from "@farm.js/core/internal/server-tree";' : ""}` : "";
3510
3542
  const isolatedHydrationRuntime = isolatedHydrationEnabled ? `const farmIsolatedBoundaryLoaders = {
3511
3543
  ${Array.from(isolatedBoundaryModules.entries()).map(
3512
3544
  ([reference, modulePath]) => ` ${JSON.stringify(reference)}: () => import(${JSON.stringify(modulePath)}),`
3513
3545
  ).join("\n")}
3514
3546
  };
3547
+ async function loadFarmIsolatedBoundary(reference) {
3548
+ const loader = farmIsolatedBoundaryLoaders[reference];
3549
+ if (!loader) throw new Error("isolated client boundary loader was not found: " + reference);
3550
+ return loader();
3551
+ }
3515
3552
  const farmIsolatedHydrationRuntime = createFarmIsolatedHydrationRuntime({
3516
3553
  ReactRuntime: React,
3517
3554
  hydrateRoot,
3518
- load: async function(reference) {
3519
- const loader = farmIsolatedBoundaryLoaders[reference];
3520
- if (!loader) throw new Error("isolated client boundary loader was not found: " + reference);
3521
- return loader();
3522
- },
3555
+ load: loadFarmIsolatedBoundary,
3523
3556
  schedule: scheduleFarmIslandHydration,
3524
3557
  wrap: wrapWithIntegrationProviders,
3525
3558
  });
@@ -3533,7 +3566,21 @@ function disposeFarmIsolatedClientBoundaries(scope) {
3533
3566
 
3534
3567
  async function hydrateFarmIsolatedClientBoundaries(scope = document, signal) {
3535
3568
  await farmIsolatedHydrationRuntime.hydrate(scope, signal);
3536
- }` : "";
3569
+ }
3570
+ ${serverTreeEnabled ? `
3571
+ // A server-tree page (an async page below a hydrating layout) rebuilds in the layout's root.
3572
+ async function createFarmServerTreePageElement(source, pathname) {
3573
+ try {
3574
+ return await createFarmServerTreeElement(React, source, {
3575
+ load: loadFarmIsolatedBoundary,
3576
+ ServerHtml: FarmServerPage,
3577
+ key: pathname,
3578
+ });
3579
+ } catch (error) {
3580
+ console.warn("[Farm.js] Could not rebuild the server tree of " + pathname + "; its server HTML was kept.", error);
3581
+ return null;
3582
+ }
3583
+ }` : "async function createFarmServerTreePageElement() { return null; }"}` : `async function createFarmServerTreePageElement() { return null; }`;
3537
3584
  const routeClientGraphRuntime = isolatedHydrationEnabled ? `function wrapFarmRouteClientGraph(element) {
3538
3585
  return wrapFarmIsolatedClientGraph(React, element);
3539
3586
  }` : `function wrapFarmRouteClientGraph(element) { return element; }`;
@@ -3600,11 +3647,24 @@ ${layoutRegistrations.join(",\n")}
3600
3647
  function getApplicableLayouts(pathname) {
3601
3648
  const applicable = [];
3602
3649
  const normalizedPath = getFarmRoutePathname(pathname).replace(/\\/$/, '') || '/';
3650
+ let directory;
3603
3651
 
3604
3652
  for (const layout of layoutRoutes) {
3605
- if (layout.pattern === '/' || isFarmRouteActive(layout.pattern, normalizedPath, { exact: false })) {
3606
- applicable.push(layout);
3653
+ // Route groups add no URL segment: match the layout's URL, then keep a
3654
+ // grouped layout to the pages inside its group directory.
3655
+ const urlPattern = layout.urlPattern || layout.pattern;
3656
+ if (urlPattern !== '/' && !isFarmRouteActive(urlPattern, normalizedPath, { exact: false })) continue;
3657
+ if (layout.groupScope) {
3658
+ if (directory === undefined) {
3659
+ const matched = matchRoute(pathname);
3660
+ directory = matched ? matched.route.directory || matched.route.pattern : null;
3661
+ }
3662
+ if (
3663
+ typeof directory !== 'string' ||
3664
+ (directory !== layout.groupScope && !directory.startsWith(layout.groupScope + '/'))
3665
+ ) continue;
3607
3666
  }
3667
+ applicable.push(layout);
3608
3668
  }
3609
3669
 
3610
3670
  // Sort by depth (root first)
@@ -3673,6 +3733,16 @@ async function loadRouteComponent(route) {
3673
3733
  return route.Component;
3674
3734
  }
3675
3735
 
3736
+ // The props the server rendered this document with, as the page receives them:
3737
+ // middleware data arrives as a plain object and is a Map again here.
3738
+ function reviveServerPageProps(serverProps) {
3739
+ if (!serverProps || typeof serverProps !== "object") return {};
3740
+ const middleware = serverProps.middleware;
3741
+ return middleware && middleware.data && !(middleware.data instanceof Map)
3742
+ ? { ...serverProps, middleware: { ...middleware, data: new Map(Object.entries(middleware.data)) } }
3743
+ : serverProps;
3744
+ }
3745
+
3676
3746
  async function createMatchedHydrationRoute(matched, pathname, searchParams, serverHtml, serverProps) {
3677
3747
  const hydrateLayouts = hasHydratableLayout(pathname);
3678
3748
  const params = matched.params;
@@ -3686,12 +3756,8 @@ async function createMatchedHydrationRoute(matched, pathname, searchParams, serv
3686
3756
  // rejected guard, deferred data) its server-rendered HTML is kept.
3687
3757
  if (Component.__farmServerProps === true) {
3688
3758
  if (!serverProps || serverProps.__farmRoutePropsResolved !== true) return null;
3689
- const middleware = serverProps.middleware;
3690
3759
  const props = {
3691
- ...serverProps,
3692
- ...(middleware && middleware.data && !(middleware.data instanceof Map)
3693
- ? { middleware: { ...middleware, data: new Map(Object.entries(middleware.data)) } }
3694
- : {}),
3760
+ ...reviveServerPageProps(serverProps),
3695
3761
  searchParams: Promise.resolve(serverProps.search ?? searchParams),
3696
3762
  };
3697
3763
  pageElement = React.createElement(Component, props);
@@ -3702,16 +3768,26 @@ async function createMatchedHydrationRoute(matched, pathname, searchParams, serv
3702
3768
  );
3703
3769
  return null;
3704
3770
  } else {
3705
- const props = { params: params, searchParams: Promise.resolve(searchParams) };
3771
+ // Keep what the server rendered with, such as middleware data, so the
3772
+ // first render matches the HTML. A navigation passes the fetched document's props.
3773
+ const props = {
3774
+ ...reviveServerPageProps(serverProps),
3775
+ params: params,
3776
+ searchParams: Promise.resolve(searchParams),
3777
+ };
3706
3778
  pageElement = React.createElement(Component, props);
3707
3779
  }
3708
3780
  } else if (hydrateLayouts) {
3709
3781
  const serverPage = document.getElementById("__farm_page__");
3710
- pageElement = createLayoutPageBoundary(
3711
- matched.route,
3712
- null,
3713
- typeof serverHtml === "string" ? serverHtml : serverPage ? serverPage.innerHTML : "",
3714
- );
3782
+ const pageSource = typeof serverHtml === "string" ? serverHtml : serverPage;
3783
+ const serverTree = pageSource ? await createFarmServerTreePageElement(pageSource, pathname) : null;
3784
+ pageElement = serverTree
3785
+ ? createLayoutPageBoundary(matched.route, serverTree)
3786
+ : createLayoutPageBoundary(
3787
+ matched.route,
3788
+ null,
3789
+ typeof serverHtml === "string" ? serverHtml : serverPage ? serverPage.innerHTML : "",
3790
+ );
3715
3791
  }
3716
3792
 
3717
3793
  if (!pageElement) return null;
@@ -4936,6 +5012,28 @@ async function buildSSRInMemory(productionVite, config, root, routeManager, apiR
4936
5012
  };
4937
5013
  }
4938
5014
  __name(buildSSRInMemory, "buildSSRInMemory");
5015
+ function readFarmAppPackageIdentity(root) {
5016
+ try {
5017
+ return JSON.parse(readFileSync(path6.join(root, "package.json"), "utf8"));
5018
+ } catch {
5019
+ return {};
5020
+ }
5021
+ }
5022
+ __name(readFarmAppPackageIdentity, "readFarmAppPackageIdentity");
5023
+ function readFarmPageLastModified(pageRoutes) {
5024
+ const lastModified = {};
5025
+ for (const route of pageRoutes) {
5026
+ if (route.pattern.includes("[")) continue;
5027
+ try {
5028
+ lastModified[route.pattern] = statSync(
5029
+ route.markdownSourcePath ?? route.modulePath
5030
+ ).mtime.toISOString();
5031
+ } catch {
5032
+ }
5033
+ }
5034
+ return lastModified;
5035
+ }
5036
+ __name(readFarmPageLastModified, "readFarmPageLastModified");
4939
5037
  function getFarmAppOwnedDocsEnginePaths(agent, applicationMetadataRoutes) {
4940
5038
  const llmsTxt = agent?.llmsTxt;
4941
5039
  const ownedByFile = /* @__PURE__ */ __name((kind) => applicationMetadataRoutes.some(
@@ -4944,7 +5042,7 @@ function getFarmAppOwnedDocsEnginePaths(agent, applicationMetadataRoutes) {
4944
5042
  return [
4945
5043
  ...llmsTxt?.enabled || ownedByFile("llms") ? ["/llms.txt"] : [],
4946
5044
  ...llmsTxt?.enabled && llmsTxt.full || ownedByFile("llms-full") ? ["/llms-full.txt"] : [],
4947
- ...ownedByFile("sitemap") ? ["/sitemap.xml"] : [],
5045
+ ...agent?.sitemap?.enabled || ownedByFile("sitemap") ? ["/sitemap.xml"] : [],
4948
5046
  ...agent?.crawlers?.enabled || ownedByFile("robots") ? ["/robots.txt"] : []
4949
5047
  ];
4950
5048
  }
@@ -5010,7 +5108,7 @@ function matchLocalIntegrationRequest(request) {
5010
5108
  });` : "return null;"}
5011
5109
  }
5012
5110
 
5013
- async function handleIntegrationRequest(request) {
5111
+ async function handleIntegrationRequest(request, ranMiddleware) {
5014
5112
  ${options.hasServerRuntimeIntegrations ? `return dispatchIntegrationRequests(
5015
5113
  serverRuntimeIntegrations,
5016
5114
  {
@@ -5019,6 +5117,7 @@ async function handleIntegrationRequest(request) {
5019
5117
  isProd: true,
5020
5118
  },
5021
5119
  request,
5120
+ { ranMiddleware },
5022
5121
  );` : `return { response: null, setCookies: [] };`}
5023
5122
  }
5024
5123
 
@@ -5299,6 +5398,11 @@ function generateVirtualEntryCode(apiRoutes, pageRoutes, layoutRoutes, routeSlot
5299
5398
  const servesAgentRobotsTxt = Boolean(config.agent?.crawlers?.enabled) && !applicationMetadataRoutes.some(
5300
5399
  (metadata) => metadata.kind === "robots" && metadata.pattern === "/"
5301
5400
  );
5401
+ const servesAgentSitemap = Boolean(config.agent?.sitemap?.enabled) && !applicationMetadataRoutes.some(
5402
+ (metadata) => metadata.kind === "sitemap" && metadata.pattern === "/"
5403
+ );
5404
+ const servesDefaultMCP = config.agent?.mcp === true && !farmConfigMountsMCP(config) && !apiRoutes.some((route) => route.path === "/api/mcp");
5405
+ const servesAiCatalog = config.agent?.aiCatalog !== false;
5302
5406
  const hasPluginRuntime = hasRuntimeIntegrationConfig || hasServerRuntimePlugins;
5303
5407
  const hasInfraAnalyticsRuntime = config.analytics !== false && resolveFarmInstrumentationRuntime(preset) === "nodejs";
5304
5408
  const hasPrecompiledDocs = Boolean(farmDocsPrecompiledManifest);
@@ -5313,7 +5417,7 @@ function generateVirtualEntryCode(apiRoutes, pageRoutes, layoutRoutes, routeSlot
5313
5417
  );
5314
5418
  const hasReactSyncRender = isReactRenderer(config.renderer);
5315
5419
  const rendererServerImports = isReactRenderer(config.renderer) ? `import * as React from "react";
5316
- 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)}`;
5420
+ 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)}`;
5317
5421
  const routeClientGraphServerRuntime = hasIsolatedClientGraphRuntime ? `function wrapFarmRouteClientGraph(element) {
5318
5422
  return wrapFarmIsolatedClientGraph(React, element);
5319
5423
  }
@@ -5322,9 +5426,17 @@ import * as ReactDOMServer from "react-dom/server";${hasIsolatedClientGraphRunti
5322
5426
  // components render as their own islands instead of joining the layout's React tree.
5323
5427
  function isolateFarmRouteServerPage(element) {
5324
5428
  return isolateFarmServerPageGraph(React, element);
5429
+ }
5430
+
5431
+ // An async page below a hydrating layout renders as a serialized tree the browser rebuilds in
5432
+ // the layout's React root, so its client components read the layout's context.
5433
+ function renderFarmRouteServerTree(element) {
5434
+ return renderFarmServerTreePage(React, element, { isolate: isolateFarmRouteServerPage });
5325
5435
  }` : `function wrapFarmRouteClientGraph(element) { return element; }
5326
5436
 
5327
- function isolateFarmRouteServerPage(element) { return element; }`;
5437
+ function isolateFarmRouteServerPage(element) { return element; }
5438
+
5439
+ function renderFarmRouteServerTree(element) { return element; }`;
5328
5440
  const hasGeneratedMetadataImages = metadataImageRoutes.some(
5329
5441
  (image) => image.sourceType === "module"
5330
5442
  );
@@ -5370,7 +5482,6 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5370
5482
  config.renderer,
5371
5483
  Boolean(unsupportedIntegrationProvider)
5372
5484
  );
5373
- const layoutAppliesToRoute = /* @__PURE__ */ __name((layoutPattern, routePattern) => layoutPattern === "/" || routePattern === layoutPattern || routePattern.startsWith(`${layoutPattern}/`), "layoutAppliesToRoute");
5374
5485
  const layoutHydrationPlans = layoutRoutes.map((layout) => ({
5375
5486
  ...layout,
5376
5487
  hydration: getCachedClientModuleHydrationPlan(
@@ -5406,11 +5517,12 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5406
5517
  metadata: layout.hydration
5407
5518
  })),
5408
5519
  pageRoutes.map((route) => ({
5409
- pattern: route.pattern,
5410
- depth: route.pattern.split("/").filter(Boolean).length,
5520
+ // Compared by directory so a grouped layout applies only inside its group.
5521
+ pattern: route.directory ?? route.pattern,
5522
+ depth: getRouteDirectoryDepth(route.directory ?? route.pattern),
5411
5523
  metadata: pageHydrationPlans.get(route.modulePath)
5412
5524
  })),
5413
- layoutAppliesToRoute
5525
+ routeBoundaryCoversDirectory
5414
5526
  );
5415
5527
  const providerServerImports = [
5416
5528
  providerServerModules.hasClerkProvider ? `import { ClerkProvider as FarmClerkProvider } from "@clerk/react";` : "",
@@ -5443,7 +5555,8 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5443
5555
  if (isFarmMarkdownPageFile(route.modulePath)) {
5444
5556
  pageRegistrations.push(`
5445
5557
  {
5446
- pattern: ${JSON.stringify(route.pattern)},
5558
+ pattern: ${JSON.stringify(route.pattern)},${route.directory ? `
5559
+ directory: ${JSON.stringify(route.directory)},` : ""}
5447
5560
  module: createFarmMarkdownRouteModule({
5448
5561
  source: ${JSON.stringify(route.source ?? "")},
5449
5562
  filePath: ${JSON.stringify(toBakedMarkdownSourcePath(config.root, route.modulePath))},
@@ -5466,10 +5579,11 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5466
5579
  const renderingDirective = parseRouteRenderingDirectiveFromDisk(route.modulePath);
5467
5580
  pageRegistrations.push(`
5468
5581
  {
5469
- pattern: ${JSON.stringify(route.pattern)},
5582
+ pattern: ${JSON.stringify(route.pattern)},${route.directory ? `
5583
+ directory: ${JSON.stringify(route.directory)},` : ""}
5470
5584
  module: ${varName},
5471
5585
  shouldHydrate: ${JSON.stringify(clientMetadata.shouldHydrate)},
5472
- islandStrategy: ${JSON.stringify(clientMetadata.islandStrategy)},${renderingDirective ? `
5586
+ islandStrategy: ${JSON.stringify(clientMetadata.islandStrategy)},${usesFarmServerTree(clientMetadata) ? "\n serverTree: true," : ""}${renderingDirective ? `
5473
5587
  rendering: ${JSON.stringify(renderingDirective)},` : ""}
5474
5588
  ${route.source !== void 0 ? `markdownSource: {
5475
5589
  source: ${JSON.stringify(route.source)},
@@ -5510,7 +5624,8 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5510
5624
  routeSlotRegistrations.push(`
5511
5625
  {
5512
5626
  name: ${JSON.stringify(slot.name)},
5513
- ownerPattern: ${JSON.stringify(slot.ownerPattern)},
5627
+ ownerPattern: ${JSON.stringify(slot.ownerPattern)},${slot.ownerDirectory ? `
5628
+ ownerDirectory: ${JSON.stringify(slot.ownerDirectory)},` : ""}
5514
5629
  pattern: ${JSON.stringify(slot.pattern)},
5515
5630
  containerId: ${JSON.stringify(slot.containerId)},
5516
5631
  interception: ${JSON.stringify(slot.interception)},
@@ -5525,9 +5640,12 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5525
5640
  errorImports.push(
5526
5641
  `import * as ${varName} from ${toVirtualEntryImportSpecifier(errorRoute.modulePath)};`
5527
5642
  );
5643
+ const groupScope = getRouteGroupScope(errorRoute.pattern);
5528
5644
  errorRegistrations.push(`
5529
5645
  {
5530
- pattern: ${JSON.stringify(errorRoute.pattern)},
5646
+ pattern: ${JSON.stringify(stripRouteGroups(errorRoute.pattern))},${groupScope ? `
5647
+ groupScope: ${JSON.stringify(groupScope)},
5648
+ directoryDepth: ${getRouteDirectoryDepth(errorRoute.pattern)},` : ""}
5531
5649
  module: ${varName},
5532
5650
  }`);
5533
5651
  });
@@ -5605,14 +5723,22 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5605
5723
  createDefaultErrorMarkup,
5606
5724
  createFarmInstrumentationLifecycle,
5607
5725
  createFarmLayoutSelector,
5726
+ isInFarmRouteGroupScope,
5608
5727
  createFarmCacheKey,
5609
5728
  createFarmMetadataRouteResponse,
5610
5729
  createFarmAgentRobots,
5730
+ createFarmDefaultSitemap,
5731
+ collectFarmDefaultMCPPages,
5732
+ resolveFarmDefaultMCPServer,
5733
+ handleFarmDefaultMCPRequest,
5734
+ createFarmAiCatalogResponse,
5611
5735
  createFarmApiCatalogResponse,
5612
5736
  createFarmAppManifestResponse,
5613
5737
  collectFarmLlmsTxtPages,
5614
5738
  createFarmDefaultLlmsTxt,
5615
5739
  createFarmLlmsMarkdownReader,
5740
+ listFarmMCPLlmsTxtLinks,
5741
+ registerFarmMCPServer,
5616
5742
  renderFarmLlmsFullTxt,
5617
5743
  createFarmLlmsFullRenderer,
5618
5744
  createFarmThemeDocumentParts,
@@ -5633,6 +5759,9 @@ function isolateFarmRouteServerPage(element) { return element; }`;
5633
5759
  mergeRouteRenderingDirectiveConfig,
5634
5760
  manageFarmLinkHeaderPreloads,
5635
5761
  mergeMetadata,
5762
+ mergeModuleViewport,
5763
+ ensureFarmDocumentMeta,
5764
+ renderViewportHead,
5636
5765
  matchesFarmIfNoneMatch,
5637
5766
  normalizeRevalidatePath,
5638
5767
  reportFarmPreloadWarnings,
@@ -5978,6 +6107,7 @@ const serverRuntimeIntegrations = Object.fromEntries(
5978
6107
  );
5979
6108
  const integrationRuntimeConfig = Object.assign({}, ...farmRuntimeConfigs, {
5980
6109
  integrations: configuredIntegrations,
6110
+ ${JSON.stringify(FARM_INTEGRATION_API_BASE_PATH_KEY)}: ${JSON.stringify(resolveFarmAPIServerBasePath(config.api))},
5981
6111
  });
5982
6112
  const farmInfraAnalytics = ${hasInfraAnalyticsRuntime ? hasPluginRuntime ? "createFarmInfraAnalyticsPlugin()" : "createFarmInfraAnalyticsRecorder()" : "null"};
5983
6113
  const configuredPlugins = [
@@ -6108,6 +6238,8 @@ const farmDocsHandler = ${config.docs?.enabled ? hasPrecompiledDocs ? "farmDocsP
6108
6238
  getApplicableLayouts(getFarmRoutePathname(pathname)).map((layout) => layout.module),
6109
6239
  ),
6110
6240
  loadReactModule: async () => FarmDocsAdapterReact,
6241
+ // Lists the docs MCP endpoint in /.well-known/ai-catalog.json for the server's lifetime.
6242
+ registerMCPServer: registerFarmMCPServer,
6111
6243
  })` : `createFarmDocsHandler(farmDocsResolvedConfig, {
6112
6244
  root: farmDocsRuntimeRoot,
6113
6245
  srcDir: ${JSON.stringify(config.srcDir)},
@@ -6124,18 +6256,25 @@ const farmDocsAPIHandler = ${config.docs?.enabled ? hasPrecompiledDocs ? "farmDo
6124
6256
 
6125
6257
  // API routes bundled at build time
6126
6258
  const apiRoutes = ${apiRoutes.length > 0 ? "mergePluginAPIRoutes(" : ""}[${apiRegistrations.join(",")}
6127
- ]${apiRoutes.length > 0 ? `, configuredPlugins, ${JSON.stringify(apiRoutes.map(({ path: path8, methods }) => ({ path: path8, methods })))}, { bodySizeLimit: ${JSON.stringify(config.server.bodySizeLimit)} })` : ""};
6259
+ ]${apiRoutes.length > 0 ? `, configuredPlugins, ${JSON.stringify(apiRoutes.map(({ path: path8, methods }) => ({ path: path8, methods })))}, { bodySizeLimit: ${JSON.stringify(config.server.bodySizeLimit)}, dispatch: dispatchFarmPluginAPIRequest })` : ""};
6260
+ // A plugin calling an app endpoint (an MCP tool, say) goes through the whole
6261
+ // pipeline, so the endpoint's middleware and integration guards run for it.
6262
+ function dispatchFarmPluginAPIRequest(request) {
6263
+ const url = new URL(request.url);
6264
+ url.pathname = applyFarmBasePath(url.pathname);
6265
+ return handleFarmRequest(url.href === request.url ? request : new Request(url, request));
6266
+ }
6128
6267
  const farmLocalAPIBasePath = ${JSON.stringify(resolveFarmAPIServerBasePath(config.api))};
6129
6268
  const farmOpenAPIReference = ${JSON.stringify(openAPIReference)};
6130
6269
  ${config.agent?.apiCatalog ? `const farmApiCatalogInput = ${JSON.stringify(resolveFarmApiCatalogInput(config))};
6131
- ` : ""}${config.analytics !== false ? `const farmAppManifestInput = ${JSON.stringify(
6270
+ ` : ""}${config.agent?.manifest !== false ? `const farmAppManifestInput = ${JSON.stringify(
6132
6271
  resolveFarmAppManifestInput(config, {
6133
6272
  build: config.deploymentId,
6134
6273
  packages: resolveFarmAppPackages(config.root),
6135
6274
  webmcpTools: config.plugins.some(({ name }) => name === "farm:webmcp") ? collectFarmWebMCPTools(config.root, config.srcDir) : []
6136
6275
  })
6137
6276
  )};
6138
- ` : ""}
6277
+ ${servesDefaultMCP ? "farmAppManifestInput.defaultMCP = getFarmDefaultMCPServer;\n" : ""}` : ""}
6139
6278
  function isFarmLocalAPIPathname(pathname) {
6140
6279
  return farmLocalAPIBasePath !== "/" &&
6141
6280
  (pathname === farmLocalAPIBasePath ||
@@ -6160,7 +6299,7 @@ for (const route of pageRoutes) {
6160
6299
  // Layout routes bundled at build time (sorted by depth, root first)
6161
6300
  const layoutRoutes = [${layoutRegistrations.join(",")}
6162
6301
  ];
6163
- const selectApplicableLayouts = createFarmLayoutSelector(layoutRoutes);
6302
+ const selectApplicableLayouts = createFarmLayoutSelector(layoutRoutes, getMatchedPageDirectory);
6164
6303
 
6165
6304
  const routeSlots = [${routeSlotRegistrations.join(",")}
6166
6305
  ];
@@ -6642,7 +6781,8 @@ function ensureFarmDocumentHead(markup) {
6642
6781
  }
6643
6782
 
6644
6783
  function ensureFarmDocumentRoot(markup) {
6645
- if (/\\sid=["']root["']/i.test(markup)) return markup;
6784
+ // Only a #root that opens the body is the container; page content can have id="root" too.
6785
+ if (/<body\\b[^>]*>\\s*<div\\b[^>]*\\sid=["']root["']/i.test(markup)) return markup;
6646
6786
  return markup
6647
6787
  .replace(/<body\\b([^>]*)>/i, function(_match, attributes) {
6648
6788
  return "<body" + attributes + '><div id="root">';
@@ -6809,6 +6949,7 @@ ${generateRuntimePathMatcherSource()}
6809
6949
  function getMatchingErrorBoundary(pathname) {
6810
6950
  const pathSegments = splitRuntimePath(pathname);
6811
6951
  let bestMatch = null;
6952
+ let directory;
6812
6953
 
6813
6954
  for (const errorRoute of errorRoutes) {
6814
6955
  const patternDepth = splitRuntimePath(errorRoute.pattern).length;
@@ -6818,9 +6959,18 @@ function getMatchingErrorBoundary(pathname) {
6818
6959
  : "/" + pathSegments.slice(0, patternDepth).join("/");
6819
6960
  const params = matchRuntimePathPattern(errorRoute.pattern, candidatePath);
6820
6961
  if (params === null) continue;
6962
+ if (errorRoute.groupScope) {
6963
+ if (directory === undefined) directory = getMatchedPageDirectory(pathname);
6964
+ if (!isInFarmRouteGroupScope(directory, errorRoute.groupScope)) continue;
6965
+ }
6821
6966
 
6822
- if (!bestMatch || patternDepth > bestMatch.depth) {
6823
- bestMatch = { route: errorRoute, params, depth: patternDepth };
6967
+ const directoryDepth = errorRoute.directoryDepth ?? patternDepth;
6968
+ if (
6969
+ !bestMatch ||
6970
+ patternDepth > bestMatch.depth ||
6971
+ (patternDepth === bestMatch.depth && directoryDepth > bestMatch.directoryDepth)
6972
+ ) {
6973
+ bestMatch = { route: errorRoute, params, depth: patternDepth, directoryDepth };
6824
6974
  }
6825
6975
  }
6826
6976
 
@@ -7011,7 +7161,7 @@ function createFarmAgentRobotsResponse(request) {
7011
7161
  "robots",
7012
7162
  createFarmAgentRobots({
7013
7163
  crawlers: farmAgentCrawlers,
7014
- sitemapPath: ${applicationMetadataRoutes.some(
7164
+ sitemapPath: ${servesAgentSitemap || applicationMetadataRoutes.some(
7015
7165
  (metadata) => metadata.kind === "sitemap" && metadata.pattern === "/"
7016
7166
  ) ? JSON.stringify("/sitemap.xml") : "undefined"},
7017
7167
  metadataBase: rootLayout && rootLayout.module && rootLayout.module.metadata
@@ -7024,6 +7174,68 @@ function createFarmAgentRobotsResponse(request) {
7024
7174
  );
7025
7175
  }
7026
7176
  ` : ""}
7177
+ ${servesAgentSitemap ? `// sitemap.xml from agent.sitemap, built the same way as in development. Each page's
7178
+ // lastmod is its file's modification time, read at build time.
7179
+ const farmAgentSitemapConfig = ${JSON.stringify(config.agent.sitemap)};
7180
+ const farmAgentSitemapLastModified = ${JSON.stringify(readFarmPageLastModified(pageRoutes))};
7181
+ function createFarmAgentSitemapResponse(request) {
7182
+ const rootLayout = layoutRoutes.find((layout) => layout.pattern === "/");
7183
+ return createFarmMetadataRouteResponse(
7184
+ "sitemap",
7185
+ createFarmDefaultSitemap(
7186
+ pageRoutes.map((route) => ({
7187
+ pattern: route.pattern,
7188
+ module: route.module,
7189
+ lastModified: farmAgentSitemapLastModified[route.pattern],
7190
+ })),
7191
+ {
7192
+ origin: new URL(request.url).origin,
7193
+ config: farmAgentSitemapConfig,
7194
+ metadataBase: rootLayout && rootLayout.module && rootLayout.module.metadata
7195
+ ? rootLayout.module.metadata.metadataBase
7196
+ : undefined,
7197
+ basePath: ${JSON.stringify(config.basePath)},
7198
+ },
7199
+ ),
7200
+ {},
7201
+ { method: request.method },
7202
+ );
7203
+ }
7204
+ ` : ""}
7205
+ ${servesDefaultMCP ? `// agent.mcp: the default read-only MCP server at /mcp, as in development. It steps
7206
+ // aside for a page route that answers /mcp and for any MCP server published or
7207
+ // registered at runtime, such as the docs engine's.
7208
+ const farmDefaultMCPServer = ${JSON.stringify(
7209
+ createFarmDefaultMCPServer(readFarmAppPackageIdentity(config.root), FARM_VERSION)
7210
+ )};
7211
+ let farmDefaultMCPRouteFree;
7212
+ function getFarmDefaultMCPServer() {
7213
+ if (farmDefaultMCPRouteFree === undefined) {
7214
+ farmDefaultMCPRouteFree = !matchPageRoute(${JSON.stringify(FARM_DEFAULT_MCP_PATH)});
7215
+ }
7216
+ return farmDefaultMCPRouteFree ? resolveFarmDefaultMCPServer(farmDefaultMCPServer) : undefined;
7217
+ }
7218
+ async function handleFarmDefaultMCP(request) {
7219
+ const origin = new URL(request.url).origin;
7220
+ return handleFarmDefaultMCPRequest(request, {
7221
+ server: getFarmDefaultMCPServer(),
7222
+ basePath: ${JSON.stringify(config.basePath)},
7223
+ listPages: () =>
7224
+ collectFarmDefaultMCPPages(
7225
+ pageRoutes.map((route) => ({ pattern: route.pattern, module: route.module })),
7226
+ { origin, basePath: ${JSON.stringify(config.basePath)}, markdown: farmMarkdownConfig },
7227
+ ),
7228
+ // A fresh request through this handler, so the caller's cookies never shape a page.
7229
+ // The handler sees paths below the base path, as the server passes them in.
7230
+ readMarkdown: (url) => {
7231
+ const page = new URL(url);
7232
+ page.pathname = stripFarmBasePath(page.pathname);
7233
+ return farmDefaultMCPReadMarkdown(page.href);
7234
+ },
7235
+ });
7236
+ }
7237
+ const farmDefaultMCPReadMarkdown = createFarmLlmsMarkdownReader((page) => handleFarmRequest(page));
7238
+ ` : ""}
7027
7239
  // Static pages and root metadata for llms.txt, built the same way as in development.
7028
7240
  function createFarmLlmsTxtContext(request, full) {
7029
7241
  const origin = new URL(request.url).origin;
@@ -7044,6 +7256,10 @@ function createFarmLlmsTxtContext(request, full) {
7044
7256
  pages,
7045
7257
  config: farmLlmsTxtConfig,
7046
7258
  rootMetadata: rootLayout && rootLayout.module && rootLayout.module.metadata,
7259
+ ${servesAiCatalog ? `mcp: listFarmMCPLlmsTxtLinks(origin, {
7260
+ basePath: ${JSON.stringify(config.basePath)},
7261
+ apiServerBasePath: farmLocalAPIBasePath,${servesDefaultMCP ? "\n defaultMCP: getFarmDefaultMCPServer," : ""}
7262
+ }),` : ""}
7047
7263
  }),
7048
7264
  // llms-full.txt reads each page's .md mirror through this same handler,
7049
7265
  // with a fresh request so the caller's cookies never shape its content.
@@ -7393,11 +7609,18 @@ function getFarmPluginRequestOptions(request) {
7393
7609
  return { kind: "request", route };
7394
7610
  }
7395
7611
 
7612
+ /** The directory of the page a pathname selects, or null; route groups confine layouts to it. */
7613
+ function getMatchedPageDirectory(pathname) {
7614
+ const match = matchPageRoute(pathname);
7615
+ return match ? match.route.directory || match.route.pattern : null;
7616
+ }
7617
+
7396
7618
  /**
7397
- * Get applicable layouts for a page path (from root to most specific)
7619
+ * Get applicable layouts for a page path (from root to most specific). Pass the
7620
+ * selected page's directory when it is known, or null when no page applies.
7398
7621
  */
7399
- function getApplicableLayouts(pathname) {
7400
- const applicable = selectApplicableLayouts(pathname);
7622
+ function getApplicableLayouts(pathname, directory) {
7623
+ const applicable = selectApplicableLayouts(pathname, directory);
7401
7624
  // buildSSRInMemory already emits these immutable descriptors in stable depth
7402
7625
  // order. Filtering preserves that order, including equal-depth ties.
7403
7626
  return applicable;
@@ -7716,7 +7939,11 @@ async function handleFarmRequestInContext(
7716
7939
  }
7717
7940
 
7718
7941
  ${hasServerRuntimeIntegrations ? `
7719
- const integrationDispatch = await handleIntegrationRequest(cloneFarmRequestWithContext(request));
7942
+ const farmIntegrationRanMiddleware = new Set();
7943
+ const integrationDispatch = await handleIntegrationRequest(
7944
+ cloneFarmRequestWithContext(request),
7945
+ farmIntegrationRanMiddleware,
7946
+ );
7720
7947
  if (integrationDispatch.response) {
7721
7948
  return integrationDispatch.response;
7722
7949
  }
@@ -7724,7 +7951,7 @@ async function handleFarmRequestInContext(
7724
7951
  // its rotated Set-Cookie values back here. They belong on whatever response
7725
7952
  // the page or API handler produces, so they ride the same deferred-header
7726
7953
  // channel the file middleware runner already uses.
7727
- const farmIntegrationSetCookies = integrationDispatch.setCookies;
7954
+ let farmIntegrationSetCookies = integrationDispatch.setCookies;
7728
7955
  ` : ""}
7729
7956
 
7730
7957
  ${hasMiddlewareRuntime ? `
@@ -7735,7 +7962,23 @@ async function handleFarmRequestInContext(
7735
7962
  if (middlewareResult.response) {
7736
7963
  return middlewareResult.response;
7737
7964
  }
7738
- request = middlewareResult.request;
7965
+ request = middlewareResult.request;${hasServerRuntimeIntegrations ? `
7966
+ // A ctx.rewrite() target is guarded as a direct request for it is: integration
7967
+ // guards (protectedRoutes) and routes see the rewritten URL, as in dev. Guards
7968
+ // that already ran for the original URL are skipped, so each runs once.
7969
+ if (request.url !== url.href) {
7970
+ const rewrittenDispatch = await handleIntegrationRequest(
7971
+ cloneFarmRequestWithContext(request),
7972
+ farmIntegrationRanMiddleware,
7973
+ );
7974
+ farmIntegrationSetCookies = [...farmIntegrationSetCookies, ...rewrittenDispatch.setCookies];
7975
+ if (rewrittenDispatch.response) {
7976
+ return applyProductionMiddlewareHeaders(
7977
+ rewrittenDispatch.response,
7978
+ withFarmIntegrationSetCookies(middlewareResult.headers, integrationDispatch.setCookies),
7979
+ );
7980
+ }
7981
+ }` : ""}
7739
7982
  const middlewareData = middlewareResult.data;
7740
7983
  const middlewareContext = middlewareResult.context;
7741
7984
  const middlewareHeaders = ${hasServerRuntimeIntegrations ? "withFarmIntegrationSetCookies(middlewareResult.headers, farmIntegrationSetCookies)" : "middlewareResult.headers"};
@@ -7758,6 +8001,23 @@ async function handleFarmRequestInContext(
7758
8001
  const middlewareHeaders = ${hasServerRuntimeIntegrations ? "withFarmIntegrationSetCookies(undefined, farmIntegrationSetCookies)" : "undefined"};
7759
8002
  `}
7760
8003
 
8004
+ ${servesAiCatalog ? `
8005
+ // agent.aiCatalog: the AI catalog of MCP servers and each server's card. Cards
8006
+ // live below the MCP endpoint, so this answers before the docs runtime and the
8007
+ // API routes, as in dev.
8008
+ const farmAiCatalogResponse = createFarmAiCatalogResponse(
8009
+ request,
8010
+ {
8011
+ basePath: ${JSON.stringify(config.basePath)},
8012
+ apiServerBasePath: farmLocalAPIBasePath,${servesDefaultMCP ? "\n defaultMCP: getFarmDefaultMCPServer," : ""}
8013
+ },
8014
+ url,
8015
+ );
8016
+ if (farmAiCatalogResponse) {
8017
+ return applyProductionMiddlewareHeaders(farmAiCatalogResponse, middlewareHeaders);
8018
+ }
8019
+ ` : ""}
8020
+
7761
8021
  ${config.docs?.enabled ? `
7762
8022
  // Docs responses are served after app middleware so route guards and
7763
8023
  // middleware headers apply to the docs engine like any other page content.
@@ -7906,15 +8166,18 @@ async function handleFarmRequestInContext(
7906
8166
  return applyProductionMiddlewareHeaders(applicationMetadataResponse, middlewareHeaders);
7907
8167
  }
7908
8168
  ` : ""}
7909
- ${config.analytics !== false ? `
7910
- // /.well-known/farmjs: the app's manifest, only for a request Farm Infra signed.
7911
- if (normalizeRuntimePath(routePathname) === ${JSON.stringify(FARM_APP_MANIFEST_PATH)}) {
7912
- const farmAppManifest = await createFarmAppManifestResponse(request, farmAppManifestInput, {
7913
- development: false,
7914
- });
7915
- if (farmAppManifest) {
7916
- return applyProductionMiddlewareHeaders(farmAppManifest, middlewareHeaders);
7917
- }
8169
+ ${config.agent?.manifest !== false ? `
8170
+ // agent.manifest: /.well-known/farmjs.json (and 0.1.34's /.well-known/farmjs), the app's
8171
+ // public manifest; Farm Infra's signed request gets the full view.
8172
+ if (
8173
+ [${JSON.stringify(FARM_APP_MANIFEST_PATH)}, ${JSON.stringify(FARM_APP_MANIFEST_LEGACY_PATH)}].includes(
8174
+ normalizeRuntimePath(routePathname),
8175
+ )
8176
+ ) {
8177
+ return applyProductionMiddlewareHeaders(
8178
+ await createFarmAppManifestResponse(request, farmAppManifestInput),
8179
+ middlewareHeaders,
8180
+ );
7918
8181
  }
7919
8182
  ` : ""}
7920
8183
  ${config.agent?.apiCatalog ? `
@@ -7935,6 +8198,15 @@ async function handleFarmRequestInContext(
7935
8198
  );
7936
8199
  }
7937
8200
  ` : ""}
8201
+ ${servesAgentSitemap ? `
8202
+ // agent.sitemap with no sitemap.ts: serve the generated file.
8203
+ if (normalizeRuntimePath(routePathname) === "/sitemap.xml") {
8204
+ return applyProductionMiddlewareHeaders(
8205
+ createFarmAgentSitemapResponse(request),
8206
+ middlewareHeaders,
8207
+ );
8208
+ }
8209
+ ` : ""}
7938
8210
  ${config.agent?.llmsTxt?.enabled ? `
7939
8211
  // agent.llmsTxt with no llms.ts or llms-full.ts: serve the generated files.
7940
8212
  const farmGeneratedLlmsKind = normalizeRuntimePath(routePathname) === "/llms.txt"
@@ -8064,7 +8336,10 @@ async function handleFarmRequestInContext(
8064
8336
  const pageMetadata = route.module.metadata || {};
8065
8337
 
8066
8338
  // Get applicable layouts for this page
8067
- const applicableLayouts = getApplicableLayouts(routePathname);
8339
+ const applicableLayouts = getApplicableLayouts(
8340
+ routePathname,
8341
+ route.directory || route.pattern,
8342
+ );
8068
8343
  const shouldHydrateLayout = applicableLayouts.some(
8069
8344
  (layout) => layout.shouldHydrate === true,
8070
8345
  );
@@ -8297,7 +8572,9 @@ async function handleFarmRequestInContext(
8297
8572
  if (route.shouldHydrate && !shouldHydrateLayout) {
8298
8573
  pageElement = wrapFarmRouteClientGraph(pageElement);
8299
8574
  } else if (shouldHydrateLayout && !route.shouldHydrate) {
8300
- pageElement = isolateFarmRouteServerPage(pageElement);
8575
+ pageElement = route.serverTree
8576
+ ? await renderFarmRouteServerTree(pageElement)
8577
+ : isolateFarmRouteServerPage(pageElement);
8301
8578
  }
8302
8579
 
8303
8580
  pageElement = React.createElement(
@@ -8324,7 +8601,7 @@ async function handleFarmRequestInContext(
8324
8601
  if (LayoutComponent) {
8325
8602
  const slotProps = {};
8326
8603
  for (const slot of renderedRouteSlots) {
8327
- if (slot.ownerPattern !== layout.pattern) continue;
8604
+ if ((slot.ownerDirectory || slot.ownerPattern) !== layout.pattern) continue;
8328
8605
  slotProps[slot.name] = React.createElement(
8329
8606
  "div",
8330
8607
  {
@@ -8391,6 +8668,9 @@ async function handleFarmRequestInContext(
8391
8668
  await layout.module.generateMetadata({ params: pageProps.params }),
8392
8669
  );
8393
8670
  }
8671
+ mergedMetadata = await mergeModuleViewport(mergedMetadata, layout.module, {
8672
+ params: pageProps.params,
8673
+ });
8394
8674
  }
8395
8675
  mergedMetadata = mergeMetadata(mergedMetadata, pageMetadata);
8396
8676
  if (!routeStateRejected && typeof route.module.generateMetadata === "function") {
@@ -8399,6 +8679,11 @@ async function handleFarmRequestInContext(
8399
8679
  await route.module.generateMetadata(pageProps),
8400
8680
  );
8401
8681
  }
8682
+ mergedMetadata = await mergeModuleViewport(
8683
+ mergedMetadata,
8684
+ routeStateRejected ? { viewport: route.module.viewport } : route.module,
8685
+ pageProps,
8686
+ );
8402
8687
 
8403
8688
  if (!mergedMetadata.manifest) {
8404
8689
  const manifestMatch = getMatchingApplicationMetadataRoute(routePathname, "manifest");
@@ -8442,6 +8727,7 @@ async function handleFarmRequestInContext(
8442
8727
  const title = renderedMetadata.title;
8443
8728
  const metaTags = renderedMetadata.tags;
8444
8729
  const hasFavicon = renderedMetadata.hasFavicon;
8730
+ const viewportTags = renderedMetadata.viewport;
8445
8731
 
8446
8732
  const hasPrivateRequestHeaders = hasPrivateFarmRequestHeaders(
8447
8733
  request,
@@ -8493,7 +8779,7 @@ async function handleFarmRequestInContext(
8493
8779
  const streamPrefix = '<!DOCTYPE html>\\n<html lang="en">\\n<head>\\n' +
8494
8780
  farmThemeDocument.head + '\\n' +
8495
8781
  ' <meta charset="utf-8">\\n' +
8496
- ' <meta name="viewport" content="width=device-width, initial-scale=1">\\n' +
8782
+ ' ' + viewportTags + '\\n' +
8497
8783
  (hasFavicon ? '' : ' <link rel="icon" href="data:,">\\n') +
8498
8784
  ' <title>' + title + '</title>' + metaTags + '\\n' +
8499
8785
  ' <link rel="stylesheet" href="/__farm_client_css_href__">\\n' +
@@ -8624,6 +8910,9 @@ async function handleFarmRequestInContext(
8624
8910
  ' <script type="module" src="/__farm_client_js_src__"></script>\\n</body>',
8625
8911
  );
8626
8912
 
8913
+ // Last, so the charset (and the viewport, unless the layout wrote one) open the head.
8914
+ fullHtml = ensureFarmDocumentMeta(fullHtml, viewportTags);
8915
+
8627
8916
  // Add DOCTYPE if not present
8628
8917
  if (!fullHtml.trim().startsWith('<!DOCTYPE')) {
8629
8918
  fullHtml = '<!DOCTYPE html>\\n' + fullHtml;
@@ -8634,7 +8923,7 @@ async function handleFarmRequestInContext(
8634
8923
  <html lang="en">
8635
8924
  <head>
8636
8925
  <meta charset="utf-8">
8637
- <meta name="viewport" content="width=device-width, initial-scale=1">
8926
+ \${viewportTags}
8638
8927
  \${hasFavicon ? "" : '<link rel="icon" href="data:,">'}
8639
8928
  \${suppressDefaultTitle ? "" : "<title>" + title + "</title>"}\${metaTags}\${rendererHead ? "\\n " + rendererHead : ""}
8640
8929
  <link rel="stylesheet" href="/__farm_client_css_href__">
@@ -8851,6 +9140,18 @@ async function handleFarmRequestInContext(
8851
9140
  }
8852
9141
  }
8853
9142
 
9143
+ ${servesDefaultMCP ? `
9144
+ // agent.mcp: no app route answered /mcp, so the default read-only server may.
9145
+ if (
9146
+ normalizeRuntimePath(routePathname) === ${JSON.stringify(FARM_DEFAULT_MCP_PATH)} &&
9147
+ getFarmDefaultMCPServer()
9148
+ ) {
9149
+ return applyProductionMiddlewareHeaders(
9150
+ await handleFarmDefaultMCP(request),
9151
+ middlewareHeaders,
9152
+ );
9153
+ }
9154
+ ` : ""}
8854
9155
  // 404 fallback - render proper HTML page
8855
9156
  return renderFarmNotFoundResponse();
8856
9157
 
@@ -8884,7 +9185,8 @@ async function handleFarmRequestInContext(
8884
9185
  try {
8885
9186
  // Wrap 404 page with root layout if available
8886
9187
  let notFoundElement = createFarmNotFoundElement(pathname);
8887
- const applicableLayouts = getApplicableLayouts("/");
9188
+ // No page matched, so a layout inside a route group cannot apply.
9189
+ const applicableLayouts = getApplicableLayouts("/", null);
8888
9190
 
8889
9191
  // Wrap with layouts (from innermost to outermost)
8890
9192
  for (let i = applicableLayouts.length - 1; i >= 0; i--) {
@@ -8928,6 +9230,7 @@ async function handleFarmRequestInContext(
8928
9230
  () => ' ' + renderFarmClientBootstrapScript() + '\\n' +
8929
9231
  ' <script type="module" src="/__farm_client_js_src__"></script>\\n</body>',
8930
9232
  );
9233
+ fullHtml = ensureFarmDocumentMeta(fullHtml, notFoundMetadata.viewport);
8931
9234
  if (!fullHtml.trim().startsWith('<!DOCTYPE')) {
8932
9235
  fullHtml = '<!DOCTYPE html>\\n' + fullHtml;
8933
9236
  }
@@ -8936,7 +9239,7 @@ async function handleFarmRequestInContext(
8936
9239
  <html lang="en">
8937
9240
  <head>
8938
9241
  <meta charset="UTF-8">
8939
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
9242
+ \${notFoundMetadata.viewport}
8940
9243
  \${notFoundMetadata.hasFavicon ? "" : '<link rel="icon" href="data:,">'}
8941
9244
  <link rel="stylesheet" href="/__farm_client_css_href__">
8942
9245
  <title>\${notFoundMetadata.title}</title>\${notFoundMetadata.tags}
@@ -9525,6 +9828,10 @@ function toFarmNodeResponse(request, response) {
9525
9828
  await fs.writeFile(nitroEntryPath, nitroEntryCode);
9526
9829
  const farmNodeServerEntryPath = preset === "node-server" ? path6.join(ssrOutputDir, "farm-node-server-entry.mjs") : null;
9527
9830
  if (farmNodeServerEntryPath && nodeAdapterModule) {
9831
+ await fs.writeFile(
9832
+ path6.join(ssrOutputDir, FARM_NODE_ENV_MODULE_FILE),
9833
+ FARM_NODE_ENV_MODULE_SOURCE
9834
+ );
9528
9835
  await fs.writeFile(
9529
9836
  farmNodeServerEntryPath,
9530
9837
  createFarmNodeServerEntry({
@@ -10606,7 +10913,7 @@ function resolveLegacyPageEntry(config, root, srcDir) {
10606
10913
  __name(resolveLegacyPageEntry, "resolveLegacyPageEntry");
10607
10914
  async function buildNitro(config, routeManager, apiRouteManager, serverRenderer, preset, root, distDir, pluginManager) {
10608
10915
  const [{ createNitroConfig }, { createNitro, build: nitroBuild }] = await Promise.all([
10609
- import("./nitro-4XGPNIK4.mjs"),
10916
+ import("./nitro-MPZJGPXK.mjs"),
10610
10917
  import("nitro/builder")
10611
10918
  ]);
10612
10919
  let nitroConfig = await createNitroConfig(