@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
@@ -4,7 +4,7 @@ import {
4
4
  matchSSGPage,
5
5
  resolveRouteRenderingConfig,
6
6
  resolveRouteRenderingConfigFromFile
7
- } from "./chunk-AQZFOP7S.mjs";
7
+ } from "./chunk-4GLOOWKE.mjs";
8
8
  import {
9
9
  collectSchemaExtensions,
10
10
  declareSchemaTables,
@@ -15,29 +15,51 @@ import {
15
15
  } from "./chunk-ZMSZZXOR.mjs";
16
16
  import {
17
17
  FARM_API_CATALOG_PATH,
18
- FARM_APP_MANIFEST_PATH,
18
+ FARM_INFRA_SIGNATURE_HEADER,
19
+ classifyFarmDocumentPrefix,
20
+ composeFarmFullDocument,
19
21
  createDefaultErrorMarkup,
22
+ createFarmAiCatalogResponse,
20
23
  createFarmApiCatalogResponse,
21
24
  createFarmAppManifestResponse,
22
25
  createFarmMetadataRouteResponse,
23
26
  createFarmThemeDocumentParts,
24
27
  createLateNotFoundRecovery,
25
28
  createLateRedirectRecovery,
29
+ createRouteDirectoryPattern,
30
+ extractFarmFullDocument,
31
+ formatRouteSegment,
26
32
  getDefaultErrorStatusText,
33
+ getRouteDirectoryDepth,
34
+ getRouteGroupScope,
35
+ isFarmAppManifestPath,
36
+ isInRouteGroupScope,
37
+ listFarmMCPLlmsTxtLinks,
38
+ removeFarmDocumentTitles,
27
39
  renderFarmLocaleAlternateLinks,
28
40
  resolveDefaultErrorStatus,
29
41
  resolveFarmApiCatalogInput,
30
- resolveFarmAppManifestInput
31
- } from "./chunk-GOABMOX3.mjs";
42
+ resolveFarmAppManifestInput,
43
+ routeBoundaryCoversDirectory,
44
+ stripRouteGroups
45
+ } from "./chunk-LSZAVSGY.mjs";
46
+ import {
47
+ FARM_DEFAULT_MCP_PATH,
48
+ collectFarmDefaultMCPPages,
49
+ createFarmDefaultMCPServer,
50
+ farmConfigMountsMCP,
51
+ isFarmDefaultMCPPathname,
52
+ resolveFarmDefaultMCPServer
53
+ } from "./chunk-UH6QN5NL.mjs";
32
54
  import {
33
55
  isFarmPreviewDeploymentEnvironment
34
56
  } from "./chunk-BOYNDCZL.mjs";
35
57
  import {
36
58
  createFarmMetadataImageResponse
37
- } from "./chunk-YQVSHTMR.mjs";
59
+ } from "./chunk-AJQTP4OO.mjs";
38
60
  import {
39
61
  createFarmImageHandler
40
- } from "./chunk-PXKIEXZD.mjs";
62
+ } from "./chunk-F5QO4FNE.mjs";
41
63
  import {
42
64
  FARM_ISLAND_REPLAYABLE_SELECTOR,
43
65
  isFarmIslandStrategy
@@ -54,8 +76,9 @@ import {
54
76
  } from "./chunk-2ELDTQRN.mjs";
55
77
  import {
56
78
  generateFarmDocsAdapterClientRuntime,
57
- getFarmDocsAdapterConfigModule
58
- } from "./chunk-VVBO3QH7.mjs";
79
+ getFarmDocsAdapterConfigModule,
80
+ isSecretDocsConfigKey
81
+ } from "./chunk-ENLZ4R3Y.mjs";
59
82
  import {
60
83
  resolveFarmDocsFontAssets,
61
84
  toFarmDocsPublicFontAssets
@@ -79,7 +102,7 @@ import {
79
102
  getFarmAppDirectories,
80
103
  getFarmLayerAliases,
81
104
  getFarmSourceRoots
82
- } from "./chunk-JHWOVJ3M.mjs";
105
+ } from "./chunk-BUGNQIHC.mjs";
83
106
  import {
84
107
  REACT_RENDERER,
85
108
  assertFarmRendererStreamingRuntime,
@@ -97,19 +120,23 @@ import {
97
120
  import {
98
121
  FARM_PREVIEW_ROBOTS_TAG,
99
122
  addFarmCspNonceToScriptTags,
100
- collectFarmLlmsTxtPages,
101
123
  createFarmAgentRobots,
102
124
  createFarmCspNonce,
103
125
  createFarmCspNonceRewriter,
104
- createFarmDefaultLlmsTxt,
105
- createFarmLlmsMarkdownReader,
126
+ createFarmDefaultSitemap,
106
127
  getFarmSecurityHeader,
107
- renderFarmLlmsFullTxt,
108
128
  resolveFarmAgentCrawlers,
109
- resolveFarmLlmsTxtConfig,
129
+ resolveFarmAgentSitemap,
110
130
  resolveFarmPerformanceConfig,
111
131
  resolveFarmSecurityConfig
112
- } from "./chunk-NGVORZVZ.mjs";
132
+ } from "./chunk-4E5WBPEG.mjs";
133
+ import {
134
+ collectFarmLlmsTxtPages,
135
+ createFarmDefaultLlmsTxt,
136
+ createFarmLlmsMarkdownReader,
137
+ renderFarmLlmsFullTxt,
138
+ resolveFarmLlmsTxtConfig
139
+ } from "./chunk-DTSROJ5J.mjs";
113
140
  import {
114
141
  getPublicFarmImageConfig,
115
142
  resolveFarmImageConfig
@@ -119,7 +146,7 @@ import {
119
146
  } from "./chunk-YHOCRI4H.mjs";
120
147
  import {
121
148
  resolveServerActionsConfig
122
- } from "./chunk-QCFFHV5H.mjs";
149
+ } from "./chunk-4WVJLURN.mjs";
123
150
  import {
124
151
  createBundledEnv,
125
152
  getResolvedEnv
@@ -127,12 +154,12 @@ import {
127
154
  import {
128
155
  createFarmMarkdownRouteModuleFromFile,
129
156
  loadFarmMdxComponents
130
- } from "./chunk-3VSKDFAT.mjs";
157
+ } from "./chunk-WZ77PUAM.mjs";
131
158
  import {
132
159
  createFarmMarkdownSourceResponse,
133
160
  isFarmMarkdownPageFile,
134
161
  normalizeFarmMarkdownRoutePath
135
- } from "./chunk-AGC75XAE.mjs";
162
+ } from "./chunk-4WCZJQUO.mjs";
136
163
  import {
137
164
  resolveFarmMdxComponentsModulePath,
138
165
  resolveMdxConfig
@@ -146,10 +173,10 @@ import {
146
173
  getFarmMarkdownMirrorPath,
147
174
  resolveMarkdownConfig,
148
175
  resolveMarkdownMirrorTarget
149
- } from "./chunk-ZUSJDQ2Q.mjs";
176
+ } from "./chunk-WWIKMBRN.mjs";
150
177
  import {
151
178
  resolveWorkflowsConfig
152
- } from "./chunk-3ATMYLLJ.mjs";
179
+ } from "./chunk-Q2KB32T4.mjs";
153
180
  import {
154
181
  initStorage
155
182
  } from "./chunk-UWPLULNK.mjs";
@@ -169,14 +196,14 @@ import {
169
196
  getRegisteredIntegrationAPIManifest,
170
197
  isFarmIntegrationProviderComponentReference,
171
198
  matchIntegrationRoute
172
- } from "./chunk-GNSDTTWZ.mjs";
199
+ } from "./chunk-MKYBIIAQ.mjs";
173
200
  import {
174
201
  MiddlewareManager
175
- } from "./chunk-7Y6ZNFPX.mjs";
202
+ } from "./chunk-BPOF5U4N.mjs";
176
203
  import {
177
204
  createRouteSlotContainerId,
178
205
  parseRouteSlotFile
179
- } from "./chunk-UBO4SGH4.mjs";
206
+ } from "./chunk-RHAZ22ZN.mjs";
180
207
  import {
181
208
  _clearCurrentMiddlewareContext,
182
209
  _clearCurrentMiddlewareData,
@@ -191,7 +218,7 @@ import {
191
218
  } from "./chunk-IOEH4VWN.mjs";
192
219
  import {
193
220
  APIRouteManager
194
- } from "./chunk-LMJ7VRHZ.mjs";
221
+ } from "./chunk-T4OGRVNS.mjs";
195
222
  import {
196
223
  findProgrammaticRouteFiles,
197
224
  loadProgrammaticRouteManifests
@@ -210,7 +237,10 @@ import {
210
237
  } from "./chunk-YOZYCI6Z.mjs";
211
238
  import {
212
239
  isFarmAPIPathname
213
- } from "./chunk-657WJNRY.mjs";
240
+ } from "./chunk-O6I6VWKK.mjs";
241
+ import {
242
+ registerFarmMCPServer
243
+ } from "./chunk-ZLAT2CWY.mjs";
214
244
  import {
215
245
  createProgrammaticRouteModuleId,
216
246
  getProgrammaticRouteSearchClientOptions,
@@ -235,6 +265,7 @@ import {
235
265
  clearRequestContext,
236
266
  copyRequestContext,
237
267
  createFarmNodeRequestAbortSignal,
268
+ createFarmNodeRequestBodyStream,
238
269
  createFarmRequestBodyErrorResponse,
239
270
  deleteRequestContext,
240
271
  getRequestContext,
@@ -244,15 +275,16 @@ import {
244
275
  readNodeRequestBody,
245
276
  resolveFarmServerConfig,
246
277
  setRequestContext
247
- } from "./chunk-XF7Q24PF.mjs";
278
+ } from "./chunk-ZMMBIVQM.mjs";
248
279
  import {
249
280
  createCliColors
250
281
  } from "./chunk-I2BHUNBU.mjs";
251
282
  import {
252
283
  invalidateFailedFarmDevModules,
284
+ invalidateFarmDevDependents,
253
285
  loadFarmDevModule,
254
286
  toFileModuleUrl
255
- } from "./chunk-43FMW62B.mjs";
287
+ } from "./chunk-KMTGADN3.mjs";
256
288
  import {
257
289
  isFarmI18nCatalogFile,
258
290
  resolveFarmI18nConfig,
@@ -276,9 +308,6 @@ import {
276
308
  import {
277
309
  searchParamsToObject
278
310
  } from "./chunk-QVKYGNVM.mjs";
279
- import {
280
- resolveFarmAPIServerBasePath
281
- } from "./chunk-BTHHUD7Q.mjs";
282
311
  import {
283
312
  configureFarmObservability,
284
313
  emitFarmEvent,
@@ -288,9 +317,12 @@ import {
288
317
  applyWebResponseHeaders,
289
318
  sendWebResponse
290
319
  } from "./chunk-Z2RZJZIZ.mjs";
320
+ import {
321
+ resolveFarmAPIServerBasePath
322
+ } from "./chunk-BTHHUD7Q.mjs";
291
323
  import {
292
324
  FARM_VERSION
293
- } from "./chunk-X242HVD5.mjs";
325
+ } from "./chunk-OO7GXVSR.mjs";
294
326
  import {
295
327
  resolveFarmTrailingSlashRedirect,
296
328
  setFarmTrailingSlashPreference
@@ -307,9 +339,11 @@ import {
307
339
  addMetadataImageReference,
308
340
  addMetadataMarkdownAlternate,
309
341
  mergeMetadata,
342
+ mergeModuleViewport,
310
343
  renderMetadataHead,
344
+ renderViewportHead,
311
345
  resolveFarmNotFoundMetadata
312
- } from "./chunk-QZCT2CQ4.mjs";
346
+ } from "./chunk-CXEN47J3.mjs";
313
347
  import {
314
348
  FARM_DEPLOYMENT_ID_HEADER,
315
349
  createFarmDeploymentCookie,
@@ -339,6 +373,7 @@ import {
339
373
  _getRequestReadCount,
340
374
  _runWithCurrentRequest,
341
375
  createWebRequestFromFarmRequest,
376
+ getCurrentRequestOrNull,
342
377
  resolveFarmRequestURL
343
378
  } from "./chunk-FDR64H6B.mjs";
344
379
  import {
@@ -752,6 +787,26 @@ function parseClientModuleMetadata(content, inspectIslandExport) {
752
787
  };
753
788
  }
754
789
  __name(parseClientModuleMetadata, "parseClientModuleMetadata");
790
+ var DEFAULT_REEXPORT = /export\s*\{\s*default(?:\s+as\s+default)?\s*\}\s*from\s*(["'])([^"']+)\1/;
791
+ function resolveDefaultReexport(ownerPath, content, root) {
792
+ const match = content ? DEFAULT_REEXPORT.exec(content) : null;
793
+ if (!match) return null;
794
+ const imported = resolveImportedModule(ownerPath, match[2], root);
795
+ return imported.local ? imported.path : null;
796
+ }
797
+ __name(resolveDefaultReexport, "resolveDefaultReexport");
798
+ function resolveOwnerSourcePath(resolvedPath, root) {
799
+ const seen = /* @__PURE__ */ new Set();
800
+ let current = resolvedPath;
801
+ while (current && !seen.has(current)) {
802
+ seen.add(current);
803
+ const target = resolveDefaultReexport(current, readIfExists(current), root);
804
+ if (!target) return current;
805
+ current = target;
806
+ }
807
+ return current;
808
+ }
809
+ __name(resolveOwnerSourcePath, "resolveOwnerSourcePath");
755
810
  function getClientModuleMetadata(modulePath, root) {
756
811
  const resolvedPath = resolveModuleSourcePath(modulePath, root);
757
812
  return inspectClientModuleMetadata(resolvedPath, root, /* @__PURE__ */ new Set(), true);
@@ -773,7 +828,7 @@ function getClientModuleHydrationPlan(modulePath, root, mode = "off", options =
773
828
  }), "emptyPlan");
774
829
  const asyncOwner = metadata.suppressedAsyncHydration === true && options.asyncOwnerIslands === true;
775
830
  if (mode === "off" && !asyncOwner) return emptyPlan();
776
- const resolvedPath = resolveModuleSourcePath(modulePath, root);
831
+ const resolvedPath = resolveOwnerSourcePath(resolveModuleSourcePath(modulePath, root), root);
777
832
  const content = readIfExists(resolvedPath ?? "");
778
833
  const parsed = parseClientModuleMetadata(content, true);
779
834
  if (!resolvedPath) return emptyPlan("the owner source could not be resolved");
@@ -785,6 +840,7 @@ function getClientModuleHydrationPlan(modulePath, root, mode = "off", options =
785
840
  }
786
841
  const inspection = collectIsolatedClientBoundaries(resolvedPath, root, {
787
842
  allowDynamicCardinality: asyncOwner,
843
+ allowElementProps: asyncOwner,
788
844
  staticPackageBoundaries: asyncOwner
789
845
  });
790
846
  if (inspection.boundaries.length === 0) {
@@ -827,6 +883,10 @@ function getClientModuleHydrationPlan(modulePath, root, mode = "off", options =
827
883
  return plan;
828
884
  }
829
885
  __name(getClientModuleHydrationPlan, "getClientModuleHydrationPlan");
886
+ function usesFarmServerTree(plan) {
887
+ return plan?.asyncOwnerIslands === true && plan.isolatedBoundaries.length > 0 && plan.isolatedBoundaries.every((boundary) => boundary.islandStrategy === "load");
888
+ }
889
+ __name(usesFarmServerTree, "usesFarmServerTree");
830
890
  function getMarkdownPageHydrationPlan(componentsModulePath, root, mode = "off", options = {}) {
831
891
  const plan = {
832
892
  isClientComponent: false,
@@ -1278,7 +1338,7 @@ function collectIsolatedClientBoundaries(ownerPath, root, options = {}) {
1278
1338
  fallbackReason = `the client boundary imported from ${specifier} renders inside <${container}>, where the HTML parser relocates its hydration marker`;
1279
1339
  return 0;
1280
1340
  }
1281
- if (passesElementValuedProps(content, localBindings)) {
1341
+ if (!options.allowElementProps && passesElementValuedProps(content, localBindings)) {
1282
1342
  fallbackReason = `the client boundary imported from ${specifier} receives React elements, which cannot cross the boundary as serialized props`;
1283
1343
  return 0;
1284
1344
  }
@@ -1314,6 +1374,10 @@ function inspectClientModuleMetadata(resolvedPath, root, visited, inspectIslandE
1314
1374
  }
1315
1375
  visited.add(resolvedPath);
1316
1376
  const content = readIfExists(resolvedPath);
1377
+ if (inspectIslandExport) {
1378
+ const target = resolveDefaultReexport(resolvedPath, content, root);
1379
+ if (target) return inspectClientModuleMetadata(target, root, visited, true);
1380
+ }
1317
1381
  const parsed = parseClientModuleMetadata(content, inspectIslandExport);
1318
1382
  if (parsed.isClientComponent) {
1319
1383
  return {
@@ -1323,10 +1387,12 @@ function inspectClientModuleMetadata(resolvedPath, root, visited, inspectIslandE
1323
1387
  };
1324
1388
  }
1325
1389
  let importsClientBoundary = false;
1390
+ let importsAsyncOwner = false;
1326
1391
  let importedIslandStrategy = null;
1327
1392
  for (const specifier of getImportSpecifiers(content)) {
1328
1393
  const imported = resolveImportedModule(resolvedPath, specifier, root);
1329
1394
  const importedMetadata = imported.local ? inspectClientModuleMetadata(imported.path, root, visited, false) : inspectPackageClientBoundary(imported.path, root, visited);
1395
+ if (importedMetadata.suppressedAsyncHydration) importsAsyncOwner = true;
1330
1396
  if (importedMetadata.isClientComponent || importedMetadata.shouldHydrate) {
1331
1397
  importsClientBoundary = true;
1332
1398
  if (importedIslandStrategy === null) {
@@ -1337,7 +1403,7 @@ function inspectClientModuleMetadata(resolvedPath, root, visited, inspectIslandE
1337
1403
  }
1338
1404
  }
1339
1405
  const shouldHydrate = parsed.hasHydrateExport || importsClientBoundary;
1340
- if (shouldHydrate && hasAsyncDefaultExport(content)) {
1406
+ if (shouldHydrate && hasAsyncDefaultExport(content) || importsAsyncOwner) {
1341
1407
  return {
1342
1408
  isClientComponent: false,
1343
1409
  shouldHydrate: false,
@@ -1895,6 +1961,10 @@ async function readAltText(filePath) {
1895
1961
  __name(readAltText, "readAltText");
1896
1962
 
1897
1963
  // src/routing/route-manager.ts
1964
+ function getRouteEntryDirectory(entry) {
1965
+ return entry.directory ?? entry.pattern;
1966
+ }
1967
+ __name(getRouteEntryDirectory, "getRouteEntryDirectory");
1898
1968
  function shouldSuggestStaticRenderingForI18n(i18n) {
1899
1969
  return !i18n || i18n.routing === "prefix-always" || i18n.routing === "prefix-except-default" && i18n.detection.every((signal) => signal === "url");
1900
1970
  }
@@ -1972,8 +2042,8 @@ var _RouteManager = class _RouteManager {
1972
2042
  )
1973
2043
  );
1974
2044
  this.orderedLayouts = Array.from(this.layouts.values()).sort(
1975
- (left, right) => left.route.segments.length - right.route.segments.length
1976
- );
2045
+ (left, right) => getRouteDirectoryDepth(left.pattern) - getRouteDirectoryDepth(right.pattern)
2046
+ ).map((entry) => ({ entry, groupScope: getRouteGroupScope(entry.pattern) }));
1977
2047
  for (const slot of this.routeSlots.values()) {
1978
2048
  if (!this.routeSlotOwnerSegments.has(slot.ownerPattern)) {
1979
2049
  this.routeSlotOwnerSegments.set(
@@ -2008,7 +2078,7 @@ var _RouteManager = class _RouteManager {
2008
2078
  break;
2009
2079
  }
2010
2080
  }
2011
- const layouts = this.findMatchingLayouts(normalizedPath, pathParts);
2081
+ const layouts = this.findMatchingLayouts(pathParts, matchedRoute);
2012
2082
  const slots = this.findMatchingRouteSlots(normalizedPath, pathParts, options.interceptFrom);
2013
2083
  return {
2014
2084
  route: matchedRoute,
@@ -2039,7 +2109,7 @@ var _RouteManager = class _RouteManager {
2039
2109
  throw new Error(`Cannot resolve runtime configuration for unknown route "${pattern}"`);
2040
2110
  }
2041
2111
  const inherited = resolveFarmRouteRuleRuntimeConfig(pattern, this.config.routeRules);
2042
- const layouts = this.findMatchingLayouts(pattern);
2112
+ const layouts = this.findMatchingLayouts(splitRoutePath(pattern), routeEntry);
2043
2113
  const layoutConfigs = [];
2044
2114
  for (const layout of layouts) {
2045
2115
  const layoutModule = await this.loadLayoutModule(layout.modulePath);
@@ -2106,16 +2176,19 @@ var _RouteManager = class _RouteManager {
2106
2176
  return null;
2107
2177
  }
2108
2178
  /**
2109
- * Return the nearest matching loading boundary for a pathname.
2179
+ * Return the nearest matching loading boundary for a pathname. Pass the page
2180
+ * `matchRoute` selected when it is known (`null` for none); otherwise the page is
2181
+ * matched only if a boundary inside a route group needs it.
2110
2182
  */
2111
- getMatchingLoading(pathname) {
2112
- return this.findNearestBoundary(this.toRoutePathname(pathname), this.loadings);
2183
+ getMatchingLoading(pathname, route) {
2184
+ return this.findNearestBoundary(this.toRoutePathname(pathname), this.loadings, route);
2113
2185
  }
2114
2186
  /**
2115
- * Return the nearest matching error boundary for a pathname.
2187
+ * Return the nearest matching error boundary for a pathname. `route` works as it
2188
+ * does for `getMatchingLoading`.
2116
2189
  */
2117
- getMatchingError(pathname) {
2118
- return this.findNearestBoundary(this.toRoutePathname(pathname), this.errors);
2190
+ getMatchingError(pathname, route) {
2191
+ return this.findNearestBoundary(this.toRoutePathname(pathname), this.errors, route);
2119
2192
  }
2120
2193
  matchMetadataImage(pathname) {
2121
2194
  const routePathname = this.toRoutePathname(pathname);
@@ -2283,15 +2356,15 @@ var _RouteManager = class _RouteManager {
2283
2356
  enforceFarmIsolatedHydrationRouteBudget(
2284
2357
  layoutEntries.map(({ entry, metadata }) => ({
2285
2358
  pattern: entry.pattern,
2286
- depth: entry.route.segments.length,
2359
+ depth: getRouteDirectoryDepth(entry.pattern),
2287
2360
  metadata
2288
2361
  })),
2289
2362
  routeEntries.map(({ entry, metadata }) => ({
2290
- pattern: entry.pattern,
2291
- depth: entry.route.segments.length,
2363
+ pattern: getRouteEntryDirectory(entry),
2364
+ depth: getRouteDirectoryDepth(getRouteEntryDirectory(entry)),
2292
2365
  metadata
2293
2366
  })),
2294
- (layoutPattern, routePattern) => layoutPattern === "/" || routePattern === layoutPattern || routePattern.startsWith(`${layoutPattern.replace(/\/$/, "")}/`)
2367
+ routeBoundaryCoversDirectory
2295
2368
  );
2296
2369
  for (const { entry, metadata } of [...layoutEntries, ...routeEntries]) {
2297
2370
  if (!metadata.costGuardExceeded) continue;
@@ -2310,10 +2383,11 @@ var _RouteManager = class _RouteManager {
2310
2383
  const routes = routeEntries.map(({ entry, metadata }) => {
2311
2384
  const programmaticPage = this.programmaticPages.get(entry.modulePath);
2312
2385
  const layoutShouldHydrate = layoutEntries.some(
2313
- ({ entry: layout, metadata: layoutMetadata }) => layoutMetadata.shouldHydrate && (layout.pattern === "/" || entry.pattern === layout.pattern || entry.pattern.startsWith(`${layout.pattern.replace(/\/$/, "")}/`))
2386
+ ({ entry: layout, metadata: layoutMetadata }) => layoutMetadata.shouldHydrate && routeBoundaryCoversDirectory(layout.pattern, getRouteEntryDirectory(entry))
2314
2387
  );
2315
2388
  return {
2316
2389
  pattern: entry.pattern,
2390
+ ...entry.directory ? { directory: entry.directory } : {},
2317
2391
  modulePath: toUrlPath(entry.modulePath),
2318
2392
  shouldHydrate: metadata.shouldHydrate,
2319
2393
  isClientComponent: metadata.isClientComponent,
@@ -2325,6 +2399,7 @@ var _RouteManager = class _RouteManager {
2325
2399
  modulePath: toUrlPath(boundary.modulePath)
2326
2400
  }))
2327
2401
  } : {},
2402
+ ...usesFarmServerTree(metadata) ? { serverTree: true } : {},
2328
2403
  renderPlan: createFarmRouteRenderPlan({
2329
2404
  pageShouldHydrate: metadata.shouldHydrate,
2330
2405
  layoutShouldHydrate,
@@ -2483,13 +2558,7 @@ var _RouteManager = class _RouteManager {
2483
2558
  */
2484
2559
  createRoutePattern(route) {
2485
2560
  if (route.segments.length === 0) return "/";
2486
- return "/" + route.segments.map((segment) => {
2487
- if (!segment.isDynamic) return segment.segment;
2488
- if (segment.isCatchAll) {
2489
- return segment.isOptional ? `[[...${segment.segment}]]` : `[...${segment.segment}]`;
2490
- }
2491
- return `[${segment.segment}]`;
2492
- }).join("/");
2561
+ return "/" + route.segments.map(formatRouteSegment).join("/");
2493
2562
  }
2494
2563
  registerPageRoute(entry) {
2495
2564
  assertUniqueRouteParameters(entry.pattern);
@@ -2570,6 +2639,7 @@ var _RouteManager = class _RouteManager {
2570
2639
  markdownSourcePath: path3.join(appDir, markdownFile)
2571
2640
  } : {},
2572
2641
  pattern,
2642
+ ...getPageDirectoryField(group.route, pattern),
2573
2643
  source: "file",
2574
2644
  sourceRoot: source.root
2575
2645
  });
@@ -2582,7 +2652,7 @@ var _RouteManager = class _RouteManager {
2582
2652
  for (const file of files) {
2583
2653
  const route = parseRoutePath(file);
2584
2654
  const modulePath = path3.join(appDir, file);
2585
- const pattern = this.createRoutePattern(route);
2655
+ const pattern = createRouteDirectoryPattern(route);
2586
2656
  const existing = target.get(pattern);
2587
2657
  if (existing?.sourceRoot === source.root) {
2588
2658
  throw new Error(
@@ -2604,6 +2674,7 @@ var _RouteManager = class _RouteManager {
2604
2674
  const modulePath = path3.join(appDir, file);
2605
2675
  const pattern = this.createRoutePattern(slot.route);
2606
2676
  const ownerPattern = this.createRoutePattern(slot.ownerRoute);
2677
+ const ownerDirectory = createRouteDirectoryPattern(slot.ownerRoute);
2607
2678
  const key = `${ownerPattern}:${slot.name}:${slot.interception ? "intercept" : "slot"}:${slot.fallback ? "default" : pattern}`;
2608
2679
  const existing = this.routeSlots.get(key);
2609
2680
  if (existing?.sourceRoot === source.root) {
@@ -2619,6 +2690,7 @@ var _RouteManager = class _RouteManager {
2619
2690
  sourceRoot: source.root,
2620
2691
  name: slot.name,
2621
2692
  ownerPattern,
2693
+ ...ownerDirectory === ownerPattern ? {} : { ownerDirectory },
2622
2694
  interception: slot.interception,
2623
2695
  fallback: slot.fallback,
2624
2696
  containerId: createRouteSlotContainerId(slot.name, ownerPattern)
@@ -2700,13 +2772,14 @@ var _RouteManager = class _RouteManager {
2700
2772
  route,
2701
2773
  modulePath,
2702
2774
  pattern,
2775
+ ...getPageDirectoryField(route, pattern),
2703
2776
  source: "programmatic",
2704
2777
  sourceRoot: source.root
2705
2778
  });
2706
2779
  }
2707
2780
  if (definition.kind === "layout") {
2708
2781
  const route = parseProgrammaticRoutePath(definition.path, "layout");
2709
- const pattern = this.createRoutePattern(route);
2782
+ const pattern = createRouteDirectoryPattern(route);
2710
2783
  const existing = this.layouts.get(pattern);
2711
2784
  if (existing?.sourceRoot === source.root) {
2712
2785
  throw new Error(
@@ -2746,17 +2819,26 @@ var _RouteManager = class _RouteManager {
2746
2819
  );
2747
2820
  }
2748
2821
  /**
2749
- * Find all layouts that should wrap a given path
2822
+ * Find all layouts that should wrap a given path. A layout inside a route group
2823
+ * wraps only the pages in that group, so it needs the selected page.
2750
2824
  */
2751
- findMatchingLayouts(pathname, pathnameParts = splitRoutePath(pathname)) {
2825
+ findMatchingLayouts(pathnameParts, route) {
2752
2826
  const matchingLayouts = [];
2753
- for (const layoutEntry of this.orderedLayouts) {
2754
- if (matchRoutePrefixParts(pathnameParts, layoutEntry.route.segments)) {
2755
- matchingLayouts.push(layoutEntry);
2827
+ for (const { entry, groupScope } of this.orderedLayouts) {
2828
+ if (!matchRoutePrefixParts(pathnameParts, entry.route.segments)) continue;
2829
+ if (groupScope !== null && !isInRouteGroupScope(route && getRouteEntryDirectory(route), groupScope)) {
2830
+ continue;
2756
2831
  }
2832
+ matchingLayouts.push(entry);
2757
2833
  }
2758
2834
  return matchingLayouts;
2759
2835
  }
2836
+ matchPageRoute(pathnameParts) {
2837
+ for (const routeEntry of this.routes.values()) {
2838
+ if (matchRouteParts(pathnameParts, routeEntry.route.segments).matches) return routeEntry;
2839
+ }
2840
+ return null;
2841
+ }
2760
2842
  findMatchingRouteSlots(pathname, pathnameParts, interceptFrom) {
2761
2843
  const groups = /* @__PURE__ */ new Map();
2762
2844
  for (const entry of this.routeSlots.values()) {
@@ -2786,6 +2868,7 @@ var _RouteManager = class _RouteManager {
2786
2868
  matches.push({
2787
2869
  name: selected.entry.name,
2788
2870
  ownerPattern: selected.entry.ownerPattern,
2871
+ ...selected.entry.ownerDirectory ? { ownerDirectory: selected.entry.ownerDirectory } : {},
2789
2872
  containerId: selected.entry.containerId,
2790
2873
  interception: selected.entry.interception,
2791
2874
  fallback: false,
@@ -2799,6 +2882,7 @@ var _RouteManager = class _RouteManager {
2799
2882
  matches.push({
2800
2883
  name: fallback.name,
2801
2884
  ownerPattern: fallback.ownerPattern,
2885
+ ...fallback.ownerDirectory ? { ownerDirectory: fallback.ownerDirectory } : {},
2802
2886
  containerId: fallback.containerId,
2803
2887
  interception: false,
2804
2888
  fallback: true,
@@ -2817,12 +2901,20 @@ var _RouteManager = class _RouteManager {
2817
2901
  const patternSegments = this.routeSlotOwnerSegments.get(pattern) ?? parseRoutePath(`${pattern}/page.tsx`).segments;
2818
2902
  return matchRoutePrefixParts(pathnameParts, patternSegments);
2819
2903
  }
2820
- findNearestBoundary(pathname, boundaries) {
2904
+ findNearestBoundary(pathname, boundaries, route) {
2821
2905
  const normalizedPath = pathname === "/" ? "/" : pathname.replace(/\/$/, "");
2822
2906
  let bestMatch = null;
2907
+ let page = route;
2823
2908
  for (const boundaryEntry of boundaries.values()) {
2824
2909
  if (!matchRoutePrefix(normalizedPath, boundaryEntry.route.segments)) continue;
2825
- if (!bestMatch || boundaryEntry.route.segments.length > bestMatch.route.segments.length) {
2910
+ const groupScope = getRouteGroupScope(boundaryEntry.pattern);
2911
+ if (groupScope !== null) {
2912
+ if (page === void 0) page = this.matchPageRoute(splitRoutePath(normalizedPath));
2913
+ if (!isInRouteGroupScope(page && getRouteEntryDirectory(page), groupScope)) continue;
2914
+ }
2915
+ const depth = boundaryEntry.route.segments.length;
2916
+ const bestDepth = bestMatch?.route.segments.length ?? -1;
2917
+ if (!bestMatch || depth > bestDepth || depth === bestDepth && getRouteDirectoryDepth(boundaryEntry.pattern) > getRouteDirectoryDepth(bestMatch.pattern)) {
2826
2918
  bestMatch = boundaryEntry;
2827
2919
  }
2828
2920
  }
@@ -2937,6 +3029,11 @@ var _RouteManager = class _RouteManager {
2937
3029
  };
2938
3030
  __name(_RouteManager, "RouteManager");
2939
3031
  var RouteManager = _RouteManager;
3032
+ function getPageDirectoryField(route, pattern) {
3033
+ const directory = createRouteDirectoryPattern(route);
3034
+ return directory === pattern ? {} : { directory };
3035
+ }
3036
+ __name(getPageDirectoryField, "getPageDirectoryField");
2940
3037
  function interpolateRedirectDestination(destination, params) {
2941
3038
  let result = destination;
2942
3039
  for (const [key, value] of Object.entries(params)) {
@@ -3054,112 +3151,6 @@ function collectDevStylesheetUrls(modules, alreadyLinked = ALREADY_LINKED) {
3054
3151
  }
3055
3152
  __name(collectDevStylesheetUrls, "collectDevStylesheetUrls");
3056
3153
 
3057
- // src/server/full-document.ts
3058
- var CONTENTS_WRAPPER = /^<div\b[^>]*style="display\s*:\s*contents"[^>]*>/i;
3059
- var HOISTED_HEAD_ELEMENT = /^(?:<(?:meta|link|base)\b[^>]*>|<title\b[^>]*>[\s\S]*?<\/title>|<script\b[^>]*\basync\b[^>]*><\/script>|<style\b[^>]*\bdata-precedence\b[^>]*>[\s\S]*?<\/style>)/i;
3060
- function peelDocumentPrefix(markup) {
3061
- let inner = markup.replace(/^\s+/, "");
3062
- let hoisted = "";
3063
- let match;
3064
- while (match = CONTENTS_WRAPPER.exec(inner) ?? HOISTED_HEAD_ELEMENT.exec(inner)) {
3065
- if (!/^<div/i.test(match[0])) hoisted += match[0];
3066
- inner = inner.slice(match[0].length).replace(/^\s+/, "");
3067
- }
3068
- return { inner, hoisted };
3069
- }
3070
- __name(peelDocumentPrefix, "peelDocumentPrefix");
3071
- function restoreHoistedHead(document, hoisted) {
3072
- if (!hoisted) return document;
3073
- if (/<head[\s>]/i.test(document)) {
3074
- return document.replace(/<head\b[^>]*>/i, (open) => open + hoisted);
3075
- }
3076
- return document.replace(/<html\b[^>]*>/i, (open) => `${open}<head>${hoisted}</head>`);
3077
- }
3078
- __name(restoreHoistedHead, "restoreHoistedHead");
3079
- function extractFarmFullDocument(markup) {
3080
- const { inner, hoisted } = peelDocumentPrefix(markup);
3081
- if (!/^<!doctype/i.test(inner) && !/^<html[\s>]/i.test(inner)) return null;
3082
- const start = markup.search(/<!doctype|<html[\s>]/i);
3083
- const lower = markup.toLowerCase();
3084
- let closeIndex = lower.lastIndexOf("</html>");
3085
- if (lower.length !== markup.length) {
3086
- closeIndex = -1;
3087
- const closing = /<\/html>/gi;
3088
- let match;
3089
- while (match = closing.exec(markup)) closeIndex = match.index;
3090
- }
3091
- if (start < 0 || closeIndex < 0) return null;
3092
- const closeEnd = closeIndex + "</html>".length;
3093
- let document = markup.slice(start, closeEnd);
3094
- const streamedTail = markup.slice(closeEnd).replace(/^(?:\s*<\/div>)+/i, "").trim();
3095
- if (streamedTail) {
3096
- document = document.replace(/<\/body>/i, () => `${streamedTail}</body>`);
3097
- }
3098
- return restoreHoistedHead(document, hoisted);
3099
- }
3100
- __name(extractFarmFullDocument, "extractFarmFullDocument");
3101
- function classifyFarmDocumentPrefix(markup) {
3102
- const { inner } = peelDocumentPrefix(markup);
3103
- if (/^<!doctype/i.test(inner) || /^<html[\s>]/i.test(inner)) return "document";
3104
- return inner === "" ? "pending" : "fragment";
3105
- }
3106
- __name(classifyFarmDocumentPrefix, "classifyFarmDocumentPrefix");
3107
- function ensureFarmDocumentHead(markup) {
3108
- if (/<head[\s>]/i.test(markup)) return markup;
3109
- return markup.replace(/<html([^>]*)>/i, (_match, attributes) => {
3110
- return `<html${attributes}><head></head>`;
3111
- });
3112
- }
3113
- __name(ensureFarmDocumentHead, "ensureFarmDocumentHead");
3114
- function ensureFarmDocumentRoot(markup) {
3115
- if (/\sid=["']root["']/i.test(markup)) return markup;
3116
- return markup.replace(
3117
- /<body\b([^>]*)>/i,
3118
- (_match, attributes) => `<body${attributes}><div id="root">`
3119
- ).replace(/<\/body>/i, () => "</div></body>");
3120
- }
3121
- __name(ensureFarmDocumentRoot, "ensureFarmDocumentRoot");
3122
- function hasFarmDocumentIcon(markup) {
3123
- return /<link\b[^>]*\brel=["']?(?:shortcut )?icon\b/i.test(markup);
3124
- }
3125
- __name(hasFarmDocumentIcon, "hasFarmDocumentIcon");
3126
- function removeFarmDocumentTitles(markup) {
3127
- return markup.replace(/<title\b[^>]*>[\s\S]*?<\/title>\s*/gi, "");
3128
- }
3129
- __name(removeFarmDocumentTitles, "removeFarmDocumentTitles");
3130
- function composeFarmFullDocument(documentHtml, assets) {
3131
- let html = ensureFarmDocumentHead(documentHtml);
3132
- if (assets.htmlAttributes) {
3133
- html = html.replace(/<html\b([^>]*)>/i, (_match, attrs) => {
3134
- let nextAttributes = attrs;
3135
- for (const name of assets.replaceHtmlAttributes ?? []) {
3136
- const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3137
- nextAttributes = nextAttributes.replace(
3138
- new RegExp("\\s+" + escapedName + `=(?:"[^"]*"|'[^']*'|[^\\s>]+)`, "gi"),
3139
- ""
3140
- );
3141
- }
3142
- return `<html${nextAttributes}${assets.htmlAttributes}>`;
3143
- });
3144
- }
3145
- html = ensureFarmDocumentRoot(html);
3146
- const headAssets = [
3147
- assets.fallbackIcon && !hasFarmDocumentIcon(html) ? '<link rel="icon" href="data:,">' : "",
3148
- assets.headAssets
3149
- ].filter(Boolean).join("\n ");
3150
- if (headAssets) {
3151
- html = html.replace(/<\/head>/i, () => ` ${headAssets}
3152
- </head>`);
3153
- }
3154
- if (assets.bodyFooter) {
3155
- html = html.replace(/<\/body>/i, () => ` ${assets.bodyFooter}
3156
- </body>`);
3157
- }
3158
- return /^\s*<!doctype/i.test(html) ? html : `<!DOCTYPE html>
3159
- ${html}`;
3160
- }
3161
- __name(composeFarmFullDocument, "composeFarmFullDocument");
3162
-
3163
3154
  // src/server/renderer.ts
3164
3155
  import { Readable, Writable } from "stream";
3165
3156
 
@@ -4831,6 +4822,16 @@ function createRouteStateProps(input) {
4831
4822
  };
4832
4823
  }
4833
4824
  __name(createRouteStateProps, "createRouteStateProps");
4825
+ function readAppPackageIdentity(root) {
4826
+ try {
4827
+ return JSON.parse(
4828
+ fs5.readFileSync(path9.join(root || process.cwd(), "package.json"), "utf8")
4829
+ );
4830
+ } catch {
4831
+ return {};
4832
+ }
4833
+ }
4834
+ __name(readAppPackageIdentity, "readAppPackageIdentity");
4834
4835
  var _ServerRenderer = class _ServerRenderer {
4835
4836
  constructor(config, routeManager, i18nRuntime, viteServer) {
4836
4837
  this.ssgManifest = [];
@@ -5028,7 +5029,7 @@ var _ServerRenderer = class _ServerRenderer {
5028
5029
  if (input.pageShouldHydrate && !input.layoutShouldHydrate) {
5029
5030
  element = this.wrapClientGraph(element);
5030
5031
  } else if (input.layoutShouldHydrate && !input.pageShouldHydrate && this.rendererRuntime.isolateServerPageGraph) {
5031
- element = this.rendererRuntime.isolateServerPageGraph(element);
5032
+ element = input.serverTree && this.rendererRuntime.renderServerTreePage ? await this.rendererRuntime.renderServerTreePage(element) : this.rendererRuntime.isolateServerPageGraph(element);
5032
5033
  }
5033
5034
  element = this.createPageBoundary(element, {
5034
5035
  pageShouldHydrate: input.pageShouldHydrate,
@@ -5045,7 +5046,9 @@ var _ServerRenderer = class _ServerRenderer {
5045
5046
  if (!LayoutComponent) continue;
5046
5047
  const slotProps = {};
5047
5048
  for (const slot of input.slots || []) {
5048
- if (slot.ownerPattern !== layout.pattern || !slot.module.default) continue;
5049
+ if ((slot.ownerDirectory ?? slot.ownerPattern) !== layout.pattern || !slot.module.default) {
5050
+ continue;
5051
+ }
5049
5052
  let slotElement = this.rendererRuntime.createElement(slot.module.default, slot.props);
5050
5053
  slotElement = this.wrapClientGraph(slotElement);
5051
5054
  slotProps[slot.name] = this.rendererRuntime.createElement(
@@ -5412,6 +5415,11 @@ var _ServerRenderer = class _ServerRenderer {
5412
5415
  completeRender(res.statusCode || 200, pathname);
5413
5416
  return;
5414
5417
  }
5418
+ if (pathname === "/sitemap.xml" && this.getAgentSitemap().enabled) {
5419
+ await this.renderGeneratedSitemap(req, res);
5420
+ completeRender(res.statusCode || 200, pathname);
5421
+ return;
5422
+ }
5415
5423
  const metadataImageMatch = this.routeManager.matchMetadataImage(pathname);
5416
5424
  if (metadataImageMatch) {
5417
5425
  await this.renderMetadataImage(req, res, {
@@ -5449,6 +5457,11 @@ var _ServerRenderer = class _ServerRenderer {
5449
5457
  layouts = match.layouts;
5450
5458
  routeSlots = match.slots ?? [];
5451
5459
  if (!route) {
5460
+ if (isFarmDefaultMCPPathname(pathname) && this.getDefaultMCPServer()) {
5461
+ await this.renderDefaultMCP(req, res);
5462
+ completeRender(res.statusCode || 200, pathname);
5463
+ return;
5464
+ }
5452
5465
  emitFarmEvent({ type: "route.notFound", pathname });
5453
5466
  await this.render404(req, res);
5454
5467
  completeRender(404);
@@ -5460,8 +5473,8 @@ var _ServerRenderer = class _ServerRenderer {
5460
5473
  route: route.pattern,
5461
5474
  params
5462
5475
  });
5463
- const loadingBoundaryEntry = this.routeManager.getMatchingLoading(pathname);
5464
- errorBoundaryEntry = this.routeManager.getMatchingError(pathname);
5476
+ const loadingBoundaryEntry = this.routeManager.getMatchingLoading(pathname, route);
5477
+ errorBoundaryEntry = this.routeManager.getMatchingError(pathname, route);
5465
5478
  middlewareMap = toMiddlewareMap(req.__FARM_MIDDLEWARE_DATA__);
5466
5479
  middlewareContext = toMiddlewareMap(req.__FARM_MIDDLEWARE_CONTEXT__);
5467
5480
  pluginExposedContext = getRequestContextSnapshot(req, {
@@ -5788,7 +5801,7 @@ var _ServerRenderer = class _ServerRenderer {
5788
5801
  if ((isClientComponent || shouldHydrate) && !shouldHydrateLayout) {
5789
5802
  pageElement = this.wrapClientGraph(pageElement);
5790
5803
  } else if (shouldHydrateLayout && !(isClientComponent || shouldHydrate) && this.rendererRuntime.isolateServerPageGraph) {
5791
- pageElement = this.rendererRuntime.isolateServerPageGraph(pageElement);
5804
+ pageElement = routeManifestEntry?.serverTree === true && this.rendererRuntime.renderServerTreePage ? await this.rendererRuntime.renderServerTreePage(pageElement) : this.rendererRuntime.isolateServerPageGraph(pageElement);
5792
5805
  }
5793
5806
  pageElement = this.createPageBoundary(pageElement, {
5794
5807
  pageShouldHydrate: isClientComponent || shouldHydrate,
@@ -5802,7 +5815,7 @@ var _ServerRenderer = class _ServerRenderer {
5802
5815
  const LayoutComponent = layoutModule.default;
5803
5816
  const slotProps = {};
5804
5817
  for (const slot of renderedRouteSlots) {
5805
- if (slot.ownerPattern !== layoutEntry.pattern) continue;
5818
+ if ((slot.ownerDirectory ?? slot.ownerPattern) !== layoutEntry.pattern) continue;
5806
5819
  let slotElement = this.rendererRuntime.createElement(
5807
5820
  slot.module.default,
5808
5821
  slot.props
@@ -6053,6 +6066,9 @@ var _ServerRenderer = class _ServerRenderer {
6053
6066
  })
6054
6067
  );
6055
6068
  }
6069
+ metadata = await mergeModuleViewport(metadata, layoutModule, {
6070
+ params: options.pageProps.params
6071
+ });
6056
6072
  }
6057
6073
  metadata = mergeMetadata(metadata, options.routeModule.metadata);
6058
6074
  if (!options.skipGeneratedRouteMetadata && typeof options.routeModule.generateMetadata === "function") {
@@ -6061,6 +6077,11 @@ var _ServerRenderer = class _ServerRenderer {
6061
6077
  await options.routeModule.generateMetadata(options.pageProps)
6062
6078
  );
6063
6079
  }
6080
+ metadata = await mergeModuleViewport(
6081
+ metadata,
6082
+ options.skipGeneratedRouteMetadata ? { viewport: options.routeModule.viewport } : options.routeModule,
6083
+ options.pageProps
6084
+ );
6064
6085
  if (!metadata.manifest) {
6065
6086
  const manifestMatch = this.routeManager.getMatchingMetadataRoute(
6066
6087
  options.pathname,
@@ -6225,7 +6246,7 @@ var _ServerRenderer = class _ServerRenderer {
6225
6246
  /** `/robots.txt` from `agent.crawlers` when no robots.ts owns it. */
6226
6247
  async renderGeneratedRobotsTxt(req, res) {
6227
6248
  try {
6228
- const sitemapPath = this.routeManager.matchMetadataRoute("/sitemap.xml")?.metadata.kind === "sitemap" ? "/sitemap.xml" : void 0;
6249
+ const sitemapPath = this.routeManager.matchMetadataRoute("/sitemap.xml")?.metadata.kind === "sitemap" || this.getAgentSitemap().enabled ? "/sitemap.xml" : void 0;
6229
6250
  const rootLayout = this.routeManager.getLayouts().get("/");
6230
6251
  const rootMetadata = sitemapPath && rootLayout ? (await this.routeManager.loadLayoutModule(rootLayout.modulePath)).metadata : void 0;
6231
6252
  const robots = createFarmAgentRobots({
@@ -6249,6 +6270,112 @@ var _ServerRenderer = class _ServerRenderer {
6249
6270
  );
6250
6271
  }
6251
6272
  }
6273
+ getAgentSitemap() {
6274
+ return resolveFarmAgentSitemap(this.config.agent?.sitemap);
6275
+ }
6276
+ /** `/sitemap.xml` from `agent.sitemap` when no sitemap.ts owns it. */
6277
+ async renderGeneratedSitemap(req, res) {
6278
+ try {
6279
+ const request2 = createWebRequestFromFarmRequest(req, {
6280
+ trustProxy: this.config.server?.trustProxy
6281
+ });
6282
+ const sources = await Promise.all(
6283
+ [...this.routeManager.getRoutes()].filter(([pattern]) => !pattern.includes("[")).map(async ([pattern, route]) => {
6284
+ const [module, stat] = await Promise.all([
6285
+ this.routeManager.loadRouteModule(route.modulePath).catch((error) => {
6286
+ logger.warn(`Could not read metadata for ${pattern} in sitemap.xml: ${error}`);
6287
+ return void 0;
6288
+ }),
6289
+ fs5.promises.stat(route.modulePath).catch(() => void 0)
6290
+ ]);
6291
+ return { pattern, module, lastModified: stat?.mtime.toISOString() };
6292
+ })
6293
+ );
6294
+ const rootLayout = this.routeManager.getLayouts().get("/");
6295
+ const rootMetadata = rootLayout ? (await this.routeManager.loadLayoutModule(rootLayout.modulePath)).metadata : void 0;
6296
+ const sitemap = createFarmDefaultSitemap(sources, {
6297
+ origin: new URL(request2.url).origin,
6298
+ config: this.getAgentSitemap(),
6299
+ metadataBase: rootMetadata?.metadataBase,
6300
+ basePath: this.config.basePath
6301
+ });
6302
+ await sendWebResponse(
6303
+ res,
6304
+ createFarmMetadataRouteResponse("sitemap", sitemap, {}, { method: req.method })
6305
+ );
6306
+ } catch (error) {
6307
+ logger.error(`Generated sitemap.xml failed: ${error}`);
6308
+ await sendWebResponse(
6309
+ res,
6310
+ new Response("Internal Server Error", {
6311
+ status: 500,
6312
+ headers: { "Content-Type": "text/plain; charset=utf-8" }
6313
+ })
6314
+ );
6315
+ }
6316
+ }
6317
+ /** Lets the default MCP server see the app's API routes, which the dev server owns. */
6318
+ setAPIRouteLookup(exists) {
6319
+ this.apiRouteExists = exists;
6320
+ }
6321
+ /**
6322
+ * The default read-only MCP server (`agent.mcp`), or undefined when the app has an MCP
6323
+ * server of its own: a route that answers /mcp, an API route at /api/mcp, `@farm.js/mcp`,
6324
+ * or a registered server such as the docs engine's. Production applies the same rules.
6325
+ */
6326
+ getDefaultMCPServer() {
6327
+ if (this.config.agent?.mcp !== true || farmConfigMountsMCP(this.config)) return void 0;
6328
+ if (this.apiRouteExists?.("/api/mcp")) return void 0;
6329
+ if (this.routeManager.matchRoute(FARM_DEFAULT_MCP_PATH).route) return void 0;
6330
+ this.defaultMCPServer ?? (this.defaultMCPServer = createFarmDefaultMCPServer(
6331
+ readAppPackageIdentity(this.config.root),
6332
+ FARM_VERSION
6333
+ ));
6334
+ return resolveFarmDefaultMCPServer(this.defaultMCPServer);
6335
+ }
6336
+ async renderDefaultMCP(req, res) {
6337
+ const server = this.getDefaultMCPServer();
6338
+ const request2 = getCurrentRequestOrNull() ?? createWebRequestFromFarmRequest(req, { trustProxy: this.config.server?.trustProxy });
6339
+ try {
6340
+ const { handleFarmDefaultMCPRequest } = await import("./agent-mcp-handler-LPJ2CADR.mjs");
6341
+ const origin = new URL(request2.url).origin;
6342
+ const response = await handleFarmDefaultMCPRequest(request2, {
6343
+ server,
6344
+ basePath: this.config.basePath,
6345
+ listPages: /* @__PURE__ */ __name(async () => {
6346
+ const sources = await Promise.all(
6347
+ [...this.routeManager.getRoutes()].filter(([pattern]) => !pattern.includes("[")).map(async ([pattern, route]) => ({
6348
+ pattern,
6349
+ // The page itself surfaces a load error. Without its module a guard cannot
6350
+ // be ruled out, so the page is left out.
6351
+ module: await this.routeManager.loadRouteModule(route.modulePath).catch(() => ({ __farmRouteGuard: true }))
6352
+ }))
6353
+ );
6354
+ return collectFarmDefaultMCPPages(sources, {
6355
+ origin,
6356
+ basePath: this.config.basePath,
6357
+ markdown: resolveMarkdownConfig(this.config.md)
6358
+ });
6359
+ }, "listPages"),
6360
+ // Pages are read through this server's own socket, with no cookies, as llms-full.txt does.
6361
+ readMarkdown: this.createDevMarkdownReader(req)
6362
+ });
6363
+ await sendWebResponse(res, response);
6364
+ } catch (error) {
6365
+ logger.error(`Default MCP server failed: ${error}`);
6366
+ await sendWebResponse(
6367
+ res,
6368
+ new Response(
6369
+ JSON.stringify({
6370
+ jsonrpc: "2.0",
6371
+ id: null,
6372
+ error: { code: -32603, message: "Internal error." }
6373
+ }),
6374
+ { status: 500, headers: { "Content-Type": "application/json" } }
6375
+ )
6376
+ );
6377
+ }
6378
+ }
6252
6379
  /** Same inputs the production server gives llms.txt: static pages and root metadata. */
6253
6380
  async createLlmsTxtContext(request2, options = {}) {
6254
6381
  const config = resolveFarmLlmsTxtConfig(this.config.agent?.llmsTxt);
@@ -6278,7 +6405,21 @@ var _ServerRenderer = class _ServerRenderer {
6278
6405
  });
6279
6406
  return {
6280
6407
  pages,
6281
- defaults: createFarmDefaultLlmsTxt({ origin, pages, config, rootMetadata }),
6408
+ defaults: createFarmDefaultLlmsTxt({
6409
+ origin,
6410
+ pages,
6411
+ config,
6412
+ rootMetadata,
6413
+ mcp: this.config.agent?.aiCatalog === false ? [] : listFarmMCPLlmsTxtLinks(origin, {
6414
+ basePath: this.config.basePath,
6415
+ apiServerBasePath: resolveFarmAPIServerBasePath(
6416
+ normalizeFarmAPIConfig(
6417
+ this.config.api
6418
+ )
6419
+ ),
6420
+ defaultMCP: /* @__PURE__ */ __name(() => this.getDefaultMCPServer(), "defaultMCP")
6421
+ })
6422
+ }),
6282
6423
  ...options.full ? { markdown: this.createDevMarkdownReader(options.req) } : {}
6283
6424
  };
6284
6425
  }
@@ -6540,7 +6681,8 @@ window.__FARM_I18N__ = ${getFarmI18nClientSnapshot() ? serializeInlineValue(getF
6540
6681
  title,
6541
6682
  tags: metaTags,
6542
6683
  hasFavicon,
6543
- hasExplicitTitle
6684
+ hasExplicitTitle,
6685
+ viewport: viewportTags
6544
6686
  } = renderMetadataHead(req.__FARM_METADATA__, {
6545
6687
  pathname: getFarmMetadataPathname(req),
6546
6688
  jsonLd: this.config.agent?.jsonLd
@@ -6566,6 +6708,7 @@ window.__FARM_I18N__ = ${getFarmI18nClientSnapshot() ? serializeInlineValue(getF
6566
6708
  const effectiveRendererHead = hasExplicitTitle ? removeFarmDocumentTitles(rendererHead) : rendererHead;
6567
6709
  html = composeFarmFullDocument(documentHtml, {
6568
6710
  fallbackIcon: !hasFavicon,
6711
+ viewport: viewportTags,
6569
6712
  htmlAttributes: `${i18nSnapshot ? ` lang="${escapeHtmlAttribute2(i18nSnapshot.locale)}" dir="${escapeHtmlAttribute2(i18nSnapshot.direction)}"` : ""}${themeDocument.attributes}`,
6570
6713
  replaceHtmlAttributes: [
6571
6714
  ...i18nSnapshot ? ["lang", "dir"] : [],
@@ -6593,7 +6736,7 @@ window.__FARM_I18N__ = ${getFarmI18nClientSnapshot() ? serializeInlineValue(getF
6593
6736
  <head>
6594
6737
  ${themeDocument.head}
6595
6738
  <meta charset="utf-8">
6596
- <meta name="viewport" content="width=device-width, initial-scale=1">
6739
+ ${viewportTags}
6597
6740
  <meta name="farm-deployment-id" content="${escapeHtmlAttribute2(deploymentId)}">
6598
6741
  ${hasFavicon ? "" : '<link rel="icon" href="data:,">'}
6599
6742
  ${documentTitleTag}${metaTags}${alternateTags}${rendererHead ? `
@@ -6778,7 +6921,8 @@ window.__FARM_I18N__ = ${getFarmI18nClientSnapshot() ? serializeInlineValue(getF
6778
6921
  const {
6779
6922
  title,
6780
6923
  tags: metaTags,
6781
- hasFavicon
6924
+ hasFavicon,
6925
+ viewport: viewportTags
6782
6926
  } = renderMetadataHead(req.__FARM_METADATA__, {
6783
6927
  pathname: getFarmMetadataPathname(req),
6784
6928
  jsonLd: this.config.agent?.jsonLd
@@ -6827,7 +6971,7 @@ window.__FARM_I18N__ = ${getFarmI18nClientSnapshot() ? serializeInlineValue(getF
6827
6971
  <head>
6828
6972
  ${themeDocument.head}
6829
6973
  <meta charset="utf-8">
6830
- <meta name="viewport" content="width=device-width, initial-scale=1">
6974
+ ${viewportTags}
6831
6975
  <meta name="farm-deployment-id" content="${escapeHtmlAttribute2(deploymentId)}">
6832
6976
  ${hasFavicon ? "" : '<link rel="icon" href="data:,">'}
6833
6977
  <title>${title}</title>${metaTags}${i18nAlternateTags}
@@ -7202,12 +7346,14 @@ ${i18nSnapshot ? `window.__FARM_I18N__ = ${serializeInlineValue(i18nSnapshot)};`
7202
7346
  getTheme()
7203
7347
  );
7204
7348
  const rendererHydrationScript = this.rendererRuntime.generateHydrationScript?.() || "";
7349
+ const viewportTags = renderViewportHead(alternates.metadata?.viewport);
7205
7350
  const fullDocument = extractFarmFullDocument(content);
7206
7351
  if (fullDocument) {
7207
7352
  return composeFarmFullDocument(
7208
7353
  metadataHead ? removeFarmDocumentTitles(fullDocument) : fullDocument,
7209
7354
  {
7210
7355
  fallbackIcon: !metadataHead,
7356
+ viewport: viewportTags,
7211
7357
  htmlAttributes: `${i18nSnapshot ? ` lang="${escapeHtmlAttribute2(i18nSnapshot.locale)}" dir="${escapeHtmlAttribute2(i18nSnapshot.direction)}"` : ""}${themeDocument.attributes}`,
7212
7358
  replaceHtmlAttributes: [
7213
7359
  ...i18nSnapshot ? ["lang", "dir"] : [],
@@ -7234,7 +7380,7 @@ ${i18nSnapshot ? `window.__FARM_I18N__ = ${serializeInlineValue(i18nSnapshot)};`
7234
7380
  <head>
7235
7381
  ${themeDocument.head}
7236
7382
  <meta charset="utf-8">
7237
- <meta name="viewport" content="width=device-width, initial-scale=1">
7383
+ ${viewportTags}
7238
7384
  <meta name="farm-deployment-id" content="${escapeHtmlAttribute2(this.getDeploymentId())}">
7239
7385
  ${metadataHead ?? '<link rel="icon" href="data:,">\n <title>Farm.js App</title>'}${alternateLinks}
7240
7386
  ${fontHead}
@@ -7662,8 +7808,8 @@ __name(validateSchemaSteps, "validateSchemaSteps");
7662
7808
  var _FarmPluginOptionsError = class _FarmPluginOptionsError extends TypeError {
7663
7809
  constructor(issues) {
7664
7810
  const lines = issues.map((issue) => {
7665
- const path21 = formatIssuePath(issue.path);
7666
- return ` - ${path21 ? `${path21}: ` : ""}${issue.message}`;
7811
+ const path22 = formatIssuePath(issue.path);
7812
+ return ` - ${path22 ? `${path22}: ` : ""}${issue.message}`;
7667
7813
  });
7668
7814
  super(`Invalid plugin options:
7669
7815
  ${lines.join("\n")}`);
@@ -7673,9 +7819,9 @@ ${lines.join("\n")}`);
7673
7819
  };
7674
7820
  __name(_FarmPluginOptionsError, "FarmPluginOptionsError");
7675
7821
  var FarmPluginOptionsError = _FarmPluginOptionsError;
7676
- function formatIssuePath(path21) {
7677
- if (!path21?.length) return "";
7678
- return path21.map((segment) => {
7822
+ function formatIssuePath(path22) {
7823
+ if (!path22?.length) return "";
7824
+ return path22.map((segment) => {
7679
7825
  const key = typeof segment === "object" && segment !== null ? segment.key : segment;
7680
7826
  return typeof key === "symbol" ? key.toString() : String(key);
7681
7827
  }).join(".");
@@ -7911,23 +8057,23 @@ var _PluginManager = class _PluginManager {
7911
8057
  `Farm plugin "${plugin.name}" runtime.endpoints must contain endpoint objects`
7912
8058
  );
7913
8059
  }
7914
- const path21 = normalizeFarmPluginRuntimeEndpointPath(
8060
+ const path22 = normalizeFarmPluginRuntimeEndpointPath(
7915
8061
  endpoint.path,
7916
8062
  `Farm plugin "${plugin.name}" runtime endpoint`
7917
8063
  );
7918
8064
  if (typeof endpoint.handler !== "function") {
7919
8065
  throw new TypeError(
7920
- `Farm plugin "${plugin.name}" runtime endpoint ${path21} requires a handler`
8066
+ `Farm plugin "${plugin.name}" runtime endpoint ${path22} requires a handler`
7921
8067
  );
7922
8068
  }
7923
- const owner = owners.get(path21);
8069
+ const owner = owners.get(path22);
7924
8070
  if (owner) {
7925
8071
  throw new Error(
7926
- `Farm plugin runtime endpoint ${path21} from "${plugin.name}" conflicts with "${owner}"`
8072
+ `Farm plugin runtime endpoint ${path22} from "${plugin.name}" conflicts with "${owner}"`
7927
8073
  );
7928
8074
  }
7929
- owners.set(path21, plugin.name);
7930
- endpoints.push({ plugin, endpoint, path: path21 });
8075
+ owners.set(path22, plugin.name);
8076
+ endpoints.push({ plugin, endpoint, path: path22 });
7931
8077
  }
7932
8078
  }
7933
8079
  this.runtimeEndpoints = endpoints;
@@ -9267,7 +9413,7 @@ var SOURCE_QUERY_FLAGS = ["raw", "inline", "url"];
9267
9413
  var MODULE_EXTENSION = /\.(?:[cm]?[jt]sx?|vue|svelte|astro|mdx?|css|scss|sass|less|styl|stylus|pcss|postcss|sss)$/i;
9268
9414
  var ASSET_EXTENSION = /\.(?:apng|bmp|png|jpe?g|jfif|pjpeg|pjp|gif|svg|ico|webp|avif|cur|jxl|mp4|webm|ogg|mp3|wav|flac|aac|opus|mov|m4a|vtt|woff2?|eot|ttf|otf|webmanifest|pdf|txt|wasm)$/i;
9269
9415
  var INTERNAL_PREFIXES = ["/@vite/", "/@farm/", "/@react-refresh", "/__vite_ping"];
9270
- var DEVELOPER_ONLY_PREFIXES = ["/__farm/devtools", "/__open-in-editor"];
9416
+ var DEVELOPER_ONLY_PREFIXES = ["/__farm/devtools", "/__open-in-editor", "/__mf_runner__"];
9271
9417
  function createFarmDevPreviewGuard(server, options) {
9272
9418
  return /* @__PURE__ */ __name(async function farmDevPreviewGuard(req, res, next) {
9273
9419
  if (!isFarmPreviewTunnelRequest(req.headers)) return next();
@@ -9360,7 +9506,7 @@ __name(isInside, "isInside");
9360
9506
 
9361
9507
  // src/vite.ts
9362
9508
  import * as fs11 from "fs";
9363
- import * as path20 from "path";
9509
+ import * as path21 from "path";
9364
9510
  import { pathToFileURL as pathToFileURL3 } from "url";
9365
9511
 
9366
9512
  // src/dev-static.ts
@@ -9810,6 +9956,87 @@ function mergeFarmProductionViteConfig(farmConfig, userConfig = {}) {
9810
9956
  }
9811
9957
  __name(mergeFarmProductionViteConfig, "mergeFarmProductionViteConfig");
9812
9958
 
9959
+ // src/docs/client-config.ts
9960
+ import { realpathSync } from "fs";
9961
+ import { createRequire as createRequire3 } from "module";
9962
+ import path20 from "path";
9963
+ var parseAst2;
9964
+ function propertyKeyName(property2) {
9965
+ if (property2.computed) return void 0;
9966
+ const key = property2.key;
9967
+ if (key.type === "Identifier") return key.name;
9968
+ if (key.type === "Literal" && typeof key.value === "string") return key.value;
9969
+ return void 0;
9970
+ }
9971
+ __name(propertyKeyName, "propertyKeyName");
9972
+ function redactFarmDocsClientConfig(code, filename) {
9973
+ parseAst2 ?? (parseAst2 = createRequire3(typeof __filename === "string" ? __filename : import.meta.url)(
9974
+ "rolldown/parseAst"
9975
+ ).parseAst);
9976
+ const extension = path20.extname(filename);
9977
+ const program = parseAst2(code, {
9978
+ lang: extension === ".tsx" || extension === ".jsx" ? "tsx" : "ts"
9979
+ });
9980
+ const edits = [];
9981
+ const visit = /* @__PURE__ */ __name((node) => {
9982
+ if (Array.isArray(node)) {
9983
+ for (const child of node) visit(child);
9984
+ return;
9985
+ }
9986
+ if (!node || typeof node !== "object") return;
9987
+ const current = node;
9988
+ if (current.type === "Property") {
9989
+ const name = propertyKeyName(current);
9990
+ const valueType = current.value?.type;
9991
+ const credential = name !== void 0 && (name.toLowerCase() === "headers" || isSecretDocsConfigKey(name) && valueType !== "ObjectExpression" && valueType !== "ArrayExpression");
9992
+ if (name && credential) {
9993
+ edits.push(
9994
+ current.shorthand || current.method || current.kind !== "init" ? { start: current.start, end: current.end, text: `${JSON.stringify(name)}: undefined` } : {
9995
+ start: current.value.start,
9996
+ end: current.value.end,
9997
+ text: "undefined"
9998
+ }
9999
+ );
10000
+ return;
10001
+ }
10002
+ }
10003
+ for (const [key, value] of Object.entries(current)) {
10004
+ if (key !== "start" && key !== "end" && value && typeof value === "object") visit(value);
10005
+ }
10006
+ }, "visit");
10007
+ visit(program);
10008
+ if (edits.length === 0) return null;
10009
+ let redacted = code;
10010
+ for (const edit of edits.sort((left, right) => right.start - left.start)) {
10011
+ redacted = redacted.slice(0, edit.start) + edit.text + redacted.slice(edit.end);
10012
+ }
10013
+ return redacted;
10014
+ }
10015
+ __name(redactFarmDocsClientConfig, "redactFarmDocsClientConfig");
10016
+ function isFarmDocsClientConfigModule(id, configModule) {
10017
+ if (!configModule) return false;
10018
+ const file = id.split("?")[0].replace(/\\/g, "/");
10019
+ if (file === configModule) return true;
10020
+ try {
10021
+ return file === realpathSync(configModule).replace(/\\/g, "/");
10022
+ } catch {
10023
+ return false;
10024
+ }
10025
+ }
10026
+ __name(isFarmDocsClientConfigModule, "isFarmDocsClientConfigModule");
10027
+ function farmDocsClientConfigPlugin(configModule) {
10028
+ return {
10029
+ name: "farm:docs-client-config",
10030
+ enforce: "pre",
10031
+ transform(code, id, options) {
10032
+ if (options?.ssr || !isFarmDocsClientConfigModule(id, configModule)) return null;
10033
+ const redacted = redactFarmDocsClientConfig(code, id.split("?")[0]);
10034
+ return redacted === null ? null : { code: redacted, map: null };
10035
+ }
10036
+ };
10037
+ }
10038
+ __name(farmDocsClientConfigPlugin, "farmDocsClientConfigPlugin");
10039
+
9813
10040
  // src/theme/vite.ts
9814
10041
  var FARM_DARK_VARIANT = '@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));';
9815
10042
  function createFarmThemeCssPlugin(input, basePath = "/") {
@@ -9884,7 +10111,12 @@ function farmLlmsTxtGeneratedPaths(config) {
9884
10111
  __name(farmLlmsTxtGeneratedPaths, "farmLlmsTxtGeneratedPaths");
9885
10112
  function farmAgentGeneratedPaths(config) {
9886
10113
  const crawlers = resolveFarmAgentCrawlers(config.agent?.crawlers);
9887
- return [...farmLlmsTxtGeneratedPaths(config), ...crawlers.enabled ? ["/robots.txt"] : []];
10114
+ const sitemap = resolveFarmAgentSitemap(config.agent?.sitemap);
10115
+ return [
10116
+ ...farmLlmsTxtGeneratedPaths(config),
10117
+ ...sitemap.enabled ? ["/sitemap.xml"] : [],
10118
+ ...crawlers.enabled ? ["/robots.txt"] : []
10119
+ ];
9888
10120
  }
9889
10121
  __name(farmAgentGeneratedPaths, "farmAgentGeneratedPaths");
9890
10122
  var ALL_TYPE_ARTIFACTS = {
@@ -9929,7 +10161,7 @@ function loadFarmWorkflowsDevRuntime() {
9929
10161
  }
9930
10162
  __name(loadFarmWorkflowsDevRuntime, "loadFarmWorkflowsDevRuntime");
9931
10163
  function loadFarmDevtoolsSnapshotRuntime() {
9932
- return import("./devtools-RNXCTS4R.mjs");
10164
+ return import("./devtools-ERIKFEXX.mjs");
9933
10165
  }
9934
10166
  __name(loadFarmDevtoolsSnapshotRuntime, "loadFarmDevtoolsSnapshotRuntime");
9935
10167
  function loadFarmDevtoolsUIRuntime() {
@@ -10352,7 +10584,7 @@ function fileContainsProgrammaticPageRoute(file) {
10352
10584
  __name(fileContainsProgrammaticPageRoute, "fileContainsProgrammaticPageRoute");
10353
10585
  function rewriteEarlySsrRelativeImports(options) {
10354
10586
  const cleanId = options.id.split("?", 1)[0];
10355
- if (!path20.isAbsolute(cleanId) || cleanId.replace(/\\/g, "/").includes("/node_modules/")) {
10587
+ if (!path21.isAbsolute(cleanId) || cleanId.replace(/\\/g, "/").includes("/node_modules/")) {
10356
10588
  return null;
10357
10589
  }
10358
10590
  const replacements = [];
@@ -10372,7 +10604,7 @@ function rewriteEarlySsrRelativeImports(options) {
10372
10604
  const suffixIndex = source.value.search(/[?#]/);
10373
10605
  const sourcePath = suffixIndex === -1 ? source.value : source.value.slice(0, suffixIndex);
10374
10606
  const suffix = suffixIndex === -1 ? "" : source.value.slice(suffixIndex);
10375
- const resolvedPath = path20.resolve(path20.dirname(cleanId), sourcePath);
10607
+ const resolvedPath = path21.resolve(path21.dirname(cleanId), sourcePath);
10376
10608
  replacements.push({
10377
10609
  start: source.start,
10378
10610
  end: source.end,
@@ -10540,6 +10772,11 @@ function farmPlugin(options = {}, initialPluginManager) {
10540
10772
  let refreshRouteDiscovery = null;
10541
10773
  let workflowHandler = null;
10542
10774
  let isBuild = false;
10775
+ const docsMCPServerDisposers = /* @__PURE__ */ new Set();
10776
+ const releaseDocsMCPServers = /* @__PURE__ */ __name(() => {
10777
+ for (const dispose of docsMCPServerDisposers) dispose();
10778
+ docsMCPServerDisposers.clear();
10779
+ }, "releaseDocsMCPServers");
10543
10780
  const logUpdate = /* @__PURE__ */ __name((tag, message) => {
10544
10781
  const pc = createCliColors();
10545
10782
  const log = [
@@ -10570,7 +10807,7 @@ function farmPlugin(options = {}, initialPluginManager) {
10570
10807
  },
10571
10808
  server: {
10572
10809
  fs: {
10573
- ...layerRoots.length ? { allow: [path20.resolve(options.root || process.cwd()), ...layerRoots] } : {},
10810
+ ...layerRoots.length ? { allow: [path21.resolve(options.root || process.cwd()), ...layerRoots] } : {},
10574
10811
  deny: getFarmDevFsDeny(userConfig.server?.fs?.deny, options)
10575
10812
  }
10576
10813
  }
@@ -10646,7 +10883,7 @@ function farmPlugin(options = {}, initialPluginManager) {
10646
10883
  });
10647
10884
  }
10648
10885
  const sourceRoots = getFarmSourceRoots(farmConfig);
10649
- server.watcher.add(sourceRoots.map((source) => path20.join(source.root, source.srcDir)));
10886
+ server.watcher.add(sourceRoots.map((source) => path21.join(source.root, source.srcDir)));
10650
10887
  if (farmConfig.i18n.enabled) {
10651
10888
  server.watcher.add(
10652
10889
  farmConfig.i18n.locales.map(
@@ -10661,7 +10898,7 @@ function farmPlugin(options = {}, initialPluginManager) {
10661
10898
  ...farmDocsDevRuntime?.getFarmDocsRouteTypeEntries(farmConfig.docs) ?? []
10662
10899
  ], "getExtraRouteTypes");
10663
10900
  const appDirSlugs = sourceRoots.map(
10664
- (source) => path20.join(source.root, source.srcDir, "app").replace(/\\/g, "/")
10901
+ (source) => path21.join(source.root, source.srcDir, "app").replace(/\\/g, "/")
10665
10902
  );
10666
10903
  const generateTypeArtifacts = /* @__PURE__ */ __name(async (reason, selection = ALL_TYPE_ARTIFACTS, log = false) => {
10667
10904
  try {
@@ -10702,7 +10939,7 @@ function farmPlugin(options = {}, initialPluginManager) {
10702
10939
  }, "generateTypeArtifacts");
10703
10940
  await generateTypeArtifacts("startup");
10704
10941
  const srcDirSlugs = sourceRoots.map(
10705
- (source) => path20.join(source.root, source.srcDir).replace(/\\/g, "/")
10942
+ (source) => path21.join(source.root, source.srcDir).replace(/\\/g, "/")
10706
10943
  );
10707
10944
  const layerConfigFiles = new Set(
10708
10945
  farmConfig.layers.map((layer) => layer.configFile?.replace(/\\/g, "/")).filter((file) => Boolean(file))
@@ -10836,12 +11073,20 @@ function farmPlugin(options = {}, initialPluginManager) {
10836
11073
  plugins: farmConfig.plugins,
10837
11074
  i18n: farmApp.getI18nRuntime(),
10838
11075
  bodySizeLimit: serverConfig.bodySizeLimit,
10839
- basePath: apiServerBasePath
11076
+ basePath: apiServerBasePath,
11077
+ // A plugin calling an app endpoint (an MCP tool, say) goes back through this server,
11078
+ // so the endpoint's middleware and integration guards run for it, as in production.
11079
+ dispatch: /* @__PURE__ */ __name((request2) => {
11080
+ const url = new URL(request2.url);
11081
+ url.pathname = applyFarmBasePath(url.pathname, farmConfig.basePath);
11082
+ return fetch(new Request(url, request2), { redirect: "manual" });
11083
+ }, "dispatch")
10840
11084
  });
10841
11085
  await apiRouteManager.discoverRoutes();
11086
+ farmApp.getServerRenderer().setAPIRouteLookup((routePath) => apiRouteManager.getRoutes().has(routePath));
10842
11087
  let discoveredWorkflows = [];
10843
11088
  const hasWorkflowDirectory = workflowConfig.enabled && workflowConfig.dirs.some(
10844
- (dir) => fs11.existsSync(path20.isAbsolute(dir) ? dir : path20.join(farmConfig.root, dir))
11089
+ (dir) => fs11.existsSync(path21.isAbsolute(dir) ? dir : path21.join(farmConfig.root, dir))
10845
11090
  );
10846
11091
  if (hasWorkflowDirectory) {
10847
11092
  const { createFarmWorkflowRequestHandler, discoverFarmWorkflows } = await loadFarmWorkflowsDevRuntime();
@@ -10919,6 +11164,7 @@ function farmPlugin(options = {}, initialPluginManager) {
10919
11164
  );
10920
11165
  return resolveFarmLayoutFonts(layoutModules);
10921
11166
  }, "resolveDocsLayoutFonts");
11167
+ releaseDocsMCPServers();
10922
11168
  const farmDocsHandler = farmDocsDevRuntime ? farmDocsDevRuntime.hasFarmDocsRuntimeAdapter(farmConfig.docs) ? await farmDocsDevRuntime.createFarmDocsAdapterHandler(farmConfig.docs, {
10923
11169
  root: farmConfig.root,
10924
11170
  srcDir: farmConfig.srcDir,
@@ -10938,7 +11184,15 @@ function farmPlugin(options = {}, initialPluginManager) {
10938
11184
  );
10939
11185
  }
10940
11186
  return loadFarmDevModule(server, resolved?.id ?? specifier);
10941
- }, "loadModule")
11187
+ }, "loadModule"),
11188
+ registerMCPServer: /* @__PURE__ */ __name((mcpServer) => {
11189
+ const dispose = registerFarmMCPServer(mcpServer);
11190
+ docsMCPServerDisposers.add(dispose);
11191
+ return () => {
11192
+ docsMCPServerDisposers.delete(dispose);
11193
+ dispose();
11194
+ };
11195
+ }, "registerMCPServer")
10942
11196
  }) : farmDocsDevRuntime.createFarmDocsHandler(farmConfig.docs, {
10943
11197
  root: farmConfig.root,
10944
11198
  srcDir: farmConfig.srcDir,
@@ -11232,22 +11486,30 @@ window.__FARM_MANIFEST__ = ${inlineValue({
11232
11486
  const docsHandler = openAPIManager.getDocsRouteHandler(parsedRequestUrl.origin);
11233
11487
  return docsHandler(req, res);
11234
11488
  }
11235
- if (stripFarmBasePath(requestPathname, farmConfig.basePath) === FARM_APP_MANIFEST_PATH) {
11489
+ if (options.agent?.manifest !== false && isFarmAppManifestPath(stripFarmBasePath(requestPathname, farmConfig.basePath))) {
11490
+ if (await runAppMiddlewareForContentRoute()) return;
11236
11491
  farmAppPackages ?? (farmAppPackages = resolveFarmAppPackages(farmConfig.root ?? process.cwd()));
11492
+ const header = /* @__PURE__ */ __name((name) => String(req.headers[name] ?? ""), "header");
11237
11493
  const manifest = await createFarmAppManifestResponse(
11238
- new Request(parsedRequestUrl, { method: requestMethod }),
11239
- resolveFarmAppManifestInput(farmConfig, {
11240
- build: "development",
11241
- packages: farmAppPackages,
11242
- // Read again on each request; unchanged files come from a cache.
11243
- webmcpTools: farmConfig.plugins?.some(({ name }) => name === "farm:webmcp") ? collectFarmWebMCPTools(farmConfig.root ?? process.cwd(), farmConfig.srcDir) : []
11494
+ new Request(parsedRequestUrl, {
11495
+ method: requestMethod,
11496
+ headers: {
11497
+ "if-none-match": header("if-none-match"),
11498
+ [FARM_INFRA_SIGNATURE_HEADER]: header(FARM_INFRA_SIGNATURE_HEADER)
11499
+ }
11244
11500
  }),
11245
- { development: true }
11501
+ {
11502
+ ...resolveFarmAppManifestInput(farmConfig, {
11503
+ build: "development",
11504
+ packages: farmAppPackages,
11505
+ // Read again on each request; unchanged files come from a cache.
11506
+ webmcpTools: farmConfig.plugins?.some(({ name }) => name === "farm:webmcp") ? collectFarmWebMCPTools(farmConfig.root ?? process.cwd(), farmConfig.srcDir) : []
11507
+ }),
11508
+ defaultMCP: /* @__PURE__ */ __name(() => farmApp.getServerRenderer().getDefaultMCPServer(), "defaultMCP")
11509
+ }
11246
11510
  );
11247
- if (manifest) {
11248
- await sendWebResponse(res, manifest);
11249
- return;
11250
- }
11511
+ await sendWebResponse(res, manifest);
11512
+ return;
11251
11513
  }
11252
11514
  if (options.agent?.apiCatalog && stripFarmBasePath(requestPathname, farmConfig.basePath) === FARM_API_CATALOG_PATH) {
11253
11515
  if (await runAppMiddlewareForContentRoute()) return;
@@ -11263,6 +11525,27 @@ window.__FARM_MANIFEST__ = ${inlineValue({
11263
11525
  );
11264
11526
  return;
11265
11527
  }
11528
+ if (options.agent?.aiCatalog !== false) {
11529
+ const aiCatalog = createFarmAiCatalogResponse(
11530
+ new Request(parsedRequestUrl, {
11531
+ method: requestMethod,
11532
+ headers: {
11533
+ "user-agent": String(req.headers["user-agent"] ?? ""),
11534
+ "if-none-match": String(req.headers["if-none-match"] ?? "")
11535
+ }
11536
+ }),
11537
+ {
11538
+ basePath: farmConfig.basePath,
11539
+ apiServerBasePath,
11540
+ defaultMCP: /* @__PURE__ */ __name(() => farmApp.getServerRenderer().getDefaultMCPServer(), "defaultMCP")
11541
+ }
11542
+ );
11543
+ if (aiCatalog) {
11544
+ if (await runAppMiddlewareForContentRoute()) return;
11545
+ await sendWebResponse(res, aiCatalog);
11546
+ return;
11547
+ }
11548
+ }
11266
11549
  const docsHeaders = new Headers();
11267
11550
  for (const [key, value] of Object.entries(req.headers)) {
11268
11551
  if (value) {
@@ -11280,7 +11563,8 @@ window.__FARM_MANIFEST__ = ${inlineValue({
11280
11563
  method: requestMethod,
11281
11564
  headers: docsHeaders
11282
11565
  });
11283
- const docsResponse = await farmDocsHandler(docsRequest.clone());
11566
+ const docsBodyInit = requestMethod === "GET" || requestMethod === "HEAD" ? {} : { body: createFarmNodeRequestBodyStream(req), duplex: "half" };
11567
+ const docsResponse = await farmDocsHandler(new Request(docsRequest, docsBodyInit));
11284
11568
  if (docsResponse) {
11285
11569
  if (await runAppMiddlewareForContentRoute()) return;
11286
11570
  await sendWebResponse(
@@ -11800,7 +12084,10 @@ window.__FARM_MANIFEST__ = ${inlineValue({
11800
12084
  return;
11801
12085
  }
11802
12086
  const routeModule = await routeManager3.loadRouteModule(route.modulePath);
11803
- const loadingBoundary = routeManager3.getMatchingLoading(targetRequestUrl.pathname);
12087
+ const loadingBoundary = routeManager3.getMatchingLoading(
12088
+ targetRequestUrl.pathname,
12089
+ route
12090
+ );
11804
12091
  const loadingModule = loadingBoundary ? await routeManager3.loadRouteModule(loadingBoundary.modulePath) : null;
11805
12092
  const navigationManifest = routeManager3.generateClientManifest(server.config.root);
11806
12093
  const moduleMetadata = navigationManifest.routes.find((entry) => entry.pattern === route.pattern) ?? getClientModuleMetadata(route.modulePath, server.config.root);
@@ -11854,6 +12141,9 @@ window.__FARM_MANIFEST__ = ${inlineValue({
11854
12141
  await layoutModule.generateMetadata({ params: routeProps.params })
11855
12142
  );
11856
12143
  }
12144
+ mergedMetadata = await mergeModuleViewport(mergedMetadata, layoutModule, {
12145
+ params: routeProps.params
12146
+ });
11857
12147
  }
11858
12148
  mergedMetadata = mergeMetadata(mergedMetadata, routeModule.metadata);
11859
12149
  if (typeof routeModule.generateMetadata === "function") {
@@ -11862,6 +12152,7 @@ window.__FARM_MANIFEST__ = ${inlineValue({
11862
12152
  await routeModule.generateMetadata(routeProps)
11863
12153
  );
11864
12154
  }
12155
+ mergedMetadata = await mergeModuleViewport(mergedMetadata, routeModule, routeProps);
11865
12156
  mergedMetadata = addMetadataMarkdownAlternate(
11866
12157
  mergedMetadata,
11867
12158
  getFarmMarkdownAlternatePath(farmApp.getConfig().md, targetRequestUrl.pathname)
@@ -11893,6 +12184,7 @@ window.__FARM_MANIFEST__ = ${inlineValue({
11893
12184
  return {
11894
12185
  name: slot.name,
11895
12186
  ownerPattern: slot.ownerPattern,
12187
+ ...slot.ownerDirectory ? { ownerDirectory: slot.ownerDirectory } : {},
11896
12188
  containerId: slot.containerId,
11897
12189
  interception: slot.interception,
11898
12190
  fallback: slot.fallback,
@@ -11945,13 +12237,15 @@ window.__FARM_MANIFEST__ = ${inlineValue({
11945
12237
  slots: routeSlots.map((slot) => ({
11946
12238
  name: slot.name,
11947
12239
  ownerPattern: slot.ownerPattern,
12240
+ ownerDirectory: slot.ownerDirectory,
11948
12241
  containerId: slot.containerId,
11949
12242
  module: slot.renderModule,
11950
12243
  props: slot.props
11951
12244
  })),
11952
12245
  pageShouldHydrate: shouldHydrate,
11953
12246
  layoutShouldHydrate: shouldHydrateLayout,
11954
- islandStrategy: hydrationIslandStrategy
12247
+ islandStrategy: hydrationIslandStrategy,
12248
+ serverTree: "serverTree" in moduleMetadata && moduleMetadata.serverTree === true
11955
12249
  })
11956
12250
  )
11957
12251
  );
@@ -12302,6 +12596,7 @@ export const getManifest = () => ({
12302
12596
  fullManifest.routes[route.pattern] = {
12303
12597
  modulePath: route.modulePath,
12304
12598
  pattern: route.pattern,
12599
+ ...route.directory ? { directory: route.directory } : {},
12305
12600
  segments: route.segments,
12306
12601
  search: route.search,
12307
12602
  isClientComponent: route.isClientComponent,
@@ -12314,9 +12609,11 @@ export const getManifest = () => ({
12314
12609
  };
12315
12610
  }
12316
12611
  for (const layout of manifest.layouts) {
12612
+ const groupScope = getRouteGroupScope(layout.pattern);
12317
12613
  fullManifest.layouts[layout.pattern] = {
12318
12614
  modulePath: layout.modulePath,
12319
12615
  pattern: layout.pattern,
12616
+ ...groupScope ? { urlPattern: stripRouteGroups(layout.pattern), groupScope } : {},
12320
12617
  shouldHydrate: layout.shouldHydrate,
12321
12618
  islandStrategy: layout.islandStrategy,
12322
12619
  preloads: [layout.modulePath],
@@ -12340,6 +12637,13 @@ export const manifest = getManifest();
12340
12637
  }
12341
12638
  },
12342
12639
  async transform(code, id, transformOptions) {
12640
+ if (!transformOptions?.ssr) {
12641
+ const docsConfigModule = getFarmDocsAdapterConfigModule(farmApp?.getConfig()?.docs);
12642
+ if (isFarmDocsClientConfigModule(id, docsConfigModule)) {
12643
+ const redacted = redactFarmDocsClientConfig(code, id.split("?")[0]);
12644
+ if (redacted !== null) return { code: redacted, map: null };
12645
+ }
12646
+ }
12343
12647
  if (!transformOptions?.ssr) {
12344
12648
  const currentConfig = farmApp?.getConfig() ?? options;
12345
12649
  if (currentConfig.experimental?.serverActions !== true || !serverFnTransformActive) {
@@ -12396,7 +12700,7 @@ export const manifest = getManifest();
12396
12700
  const root = currentConfig.root || server?.config.root || process.cwd();
12397
12701
  const cleanId = id.split("?", 1)[0];
12398
12702
  const selectedIsolatedModules = options.isolatedClientBoundaryModules ?? farmApp?.getRouteManager().getIsolatedClientBoundaryModules(root);
12399
- const selectedForIsolatedHydration = selectedIsolatedModules?.has(path20.resolve(cleanId)) === true;
12703
+ const selectedForIsolatedHydration = selectedIsolatedModules?.has(path21.resolve(cleanId)) === true;
12400
12704
  if (isReactRenderer(resolveFarmRenderer(currentConfig.renderer)) && selectedForIsolatedHydration && isIsolatableClientBoundarySource(clientBoundarySource)) {
12401
12705
  isolatedModuleReference = toViteModuleId(cleanId, root);
12402
12706
  const transformedBoundary = transformIsolatedClientBoundaryModule({
@@ -12476,6 +12780,7 @@ if (import.meta.hot) {
12476
12780
  });
12477
12781
  },
12478
12782
  async closeBundle() {
12783
+ if (!isBuild) releaseDocsMCPServers();
12479
12784
  if (!farmApp || !isBuild) return;
12480
12785
  try {
12481
12786
  const routeManager = farmApp.getRouteManager();
@@ -12487,8 +12792,8 @@ if (import.meta.hot) {
12487
12792
  }
12488
12793
  logger.info(`Found ${ssgPages.length} SSG pages, ${ssrRoutes.length} SSR routes`);
12489
12794
  logger.info("Pre-rendering SSG pages...");
12490
- const outDir = path20.join(server?.config.root || process.cwd(), options.outDir || "dist");
12491
- const clientDir = path20.join(outDir, "client");
12795
+ const outDir = path21.join(server?.config.root || process.cwd(), options.outDir || "dist");
12796
+ const clientDir = path21.join(outDir, "client");
12492
12797
  for (const page of ssgPages) {
12493
12798
  try {
12494
12799
  const staticRequest = new Request(new URL(page.urlPath, "http://farm.static"));
@@ -12540,8 +12845,8 @@ if (import.meta.hot) {
12540
12845
  <script type="module" src="/assets/client.js"></script>
12541
12846
  </body>
12542
12847
  </html>`;
12543
- const outputPath = page.urlPath === "/" ? path20.join(clientDir, "index.html") : path20.join(clientDir, page.urlPath + ".html");
12544
- fs11.mkdirSync(path20.dirname(outputPath), { recursive: true });
12848
+ const outputPath = page.urlPath === "/" ? path21.join(clientDir, "index.html") : path21.join(clientDir, page.urlPath + ".html");
12849
+ fs11.mkdirSync(path21.dirname(outputPath), { recursive: true });
12545
12850
  fs11.writeFileSync(outputPath, fullHtml);
12546
12851
  const revalidateInfo = page.revalidate ? ` (revalidate: ${page.revalidate}s)` : "";
12547
12852
  logger.success(` \u2713 ${page.urlPath}${revalidateInfo}`);
@@ -12550,7 +12855,7 @@ if (import.meta.hot) {
12550
12855
  logger.error(` \u2717 ${page.urlPath}: ${error}`);
12551
12856
  }
12552
12857
  }
12553
- const manifestPath = path20.join(outDir, "__ssg_manifest.json");
12858
+ const manifestPath = path21.join(outDir, "__ssg_manifest.json");
12554
12859
  fs11.writeFileSync(
12555
12860
  manifestPath,
12556
12861
  JSON.stringify(
@@ -12594,9 +12899,9 @@ if (import.meta.hot) {
12594
12899
  server2.ws.send({ type: "full-reload", path: "*" });
12595
12900
  return [];
12596
12901
  }
12597
- const currentSrcRoot = currentFarmConfig ? getFarmSourceRoots(currentFarmConfig).map((source) => path20.join(source.root, source.srcDir).replace(/\\/g, "/")).find((sourceRoot) => normalizedFile.startsWith(`${sourceRoot}/`)) || null : null;
12902
+ const currentSrcRoot = currentFarmConfig ? getFarmSourceRoots(currentFarmConfig).map((source) => path21.join(source.root, source.srcDir).replace(/\\/g, "/")).find((sourceRoot) => normalizedFile.startsWith(`${sourceRoot}/`)) || null : null;
12598
12903
  if (currentSrcRoot && normalizedFile.startsWith(`${currentSrcRoot}/`) && isProgrammaticRoutesFileName(normalizedFile)) {
12599
- logUpdate("PAGE", `updated ${path20.basename(file)}`);
12904
+ logUpdate("PAGE", `updated ${path21.basename(file)}`);
12600
12905
  for (const mod of modules) {
12601
12906
  server2.moduleGraph.invalidateModule(mod);
12602
12907
  }
@@ -12620,6 +12925,9 @@ if (import.meta.hot) {
12620
12925
  });
12621
12926
  return [];
12622
12927
  }
12928
+ if (apiRouteManager && invalidateFarmDevDependents(server2, file, apiRouteManager.getSourceFiles()).length > 0) {
12929
+ await refreshRouteDiscovery?.(`updated ${file}`);
12930
+ }
12623
12931
  const isolatedHydrationMode = currentFarmConfig?.experimental?.isolatedClientHydration;
12624
12932
  const planRouteManager = farmApp?.getRouteManager();
12625
12933
  const isHydrationPlanSource = currentSrcRoot !== null && normalizedFile.startsWith(`${currentSrcRoot}/`) && /\.[cm]?[jt]sx?$/.test(normalizedFile);
@@ -12727,10 +13035,10 @@ function createPageDataMiddlewareRequest(req, target) {
12727
13035
  __name(createPageDataMiddlewareRequest, "createPageDataMiddlewareRequest");
12728
13036
  function resolveDevelopmentRoot(farmRoot, viteRoot) {
12729
13037
  if (!farmRoot) return viteRoot;
12730
- if (path20.resolve(farmRoot) === path20.resolve(viteRoot)) return farmRoot;
13038
+ if (path21.resolve(farmRoot) === path21.resolve(viteRoot)) return farmRoot;
12731
13039
  try {
12732
13040
  if (fs11.realpathSync(farmRoot) === fs11.realpathSync(viteRoot)) {
12733
- return path20.resolve(viteRoot);
13041
+ return path21.resolve(viteRoot);
12734
13042
  }
12735
13043
  } catch {
12736
13044
  }
@@ -13095,7 +13403,8 @@ function generateClientCode(integrationProviders = [], documentNavigationMatcher
13095
13403
  import { hydrateRoot, createRoot } from 'react-dom/client'` : appSetupPath ? `import React, { hydrateRoot, createRoot, configureApp as __farmConfigureApp } from ${JSON.stringify(renderer.client)}
13096
13404
  import __farmAppSetup from ${JSON.stringify(toViteModuleId(appSetupPath, root))}
13097
13405
  __farmConfigureApp(__farmAppSetup)` : `import React, { hydrateRoot, createRoot } from ${JSON.stringify(renderer.client)}`;
13098
- const isolatedHydrationImport = isolatedHydrationEnabled ? `import { createFarmIsolatedHydrationRuntime, createFarmServerPageBoundary, wrapFarmIsolatedClientGraph } from '@farm.js/core/internal/isolated-boundary'` : "";
13406
+ const isolatedHydrationImport = isolatedHydrationEnabled ? `import { createFarmIsolatedHydrationRuntime, createFarmServerPageBoundary, wrapFarmIsolatedClientGraph } from '@farm.js/core/internal/isolated-boundary'
13407
+ import { createFarmServerTreeElement } from '@farm.js/core/internal/server-tree'` : "";
13099
13408
  const docsAdapterImportBlock = generateFarmDocsAdapterClientRuntime(
13100
13409
  docsAdapterReact,
13101
13410
  docsConfigModule
@@ -13117,7 +13426,21 @@ function disposeFarmIsolatedClientBoundaries(scope) {
13117
13426
 
13118
13427
  async function hydrateFarmIsolatedClientBoundaries(scope = document, signal) {
13119
13428
  await farmIsolatedHydrationRuntime.hydrate(scope, signal);
13120
- }` : "";
13429
+ }
13430
+
13431
+ // A server-tree page (an async page below a hydrating layout) rebuilds in the layout's root.
13432
+ async function createFarmServerTreePageElement(source, pathname) {
13433
+ try {
13434
+ return await createFarmServerTreeElement(React, source, {
13435
+ load: (reference) => import(/* @vite-ignore */ reference),
13436
+ ServerHtml: FarmServerPage,
13437
+ key: pathname,
13438
+ });
13439
+ } catch (error) {
13440
+ console.warn('[Farm.js] Could not rebuild the server tree of ' + pathname + '; its server HTML was kept.', error);
13441
+ return null;
13442
+ }
13443
+ }` : `async function createFarmServerTreePageElement() { return null; }`;
13121
13444
  return `
13122
13445
  ${rendererClientImports}
13123
13446
  ${isolatedHydrationImport}
@@ -13258,14 +13581,29 @@ function findLayouts(pathname) {
13258
13581
  const manifest = getManifest();
13259
13582
  const layouts = Object.values(manifest.layouts);
13260
13583
  const matchingLayouts = [];
13584
+ let directory;
13261
13585
 
13262
13586
  for (const layout of layouts) {
13263
- if (layout.pattern === '/' || isFarmRouteActive(layout.pattern, pathname, { exact: false })) {
13264
- matchingLayouts.push(layout);
13587
+ // Route groups add no URL segment: match the layout's URL, then keep a
13588
+ // grouped layout to the pages inside its group directory.
13589
+ const urlPattern = layout.urlPattern || layout.pattern;
13590
+ if (urlPattern !== '/' && !isFarmRouteActive(urlPattern, pathname, { exact: false })) continue;
13591
+ if (layout.groupScope) {
13592
+ if (directory === undefined) {
13593
+ const route = findRoute(pathname)?.route;
13594
+ directory = route ? route.directory || route.pattern : null;
13595
+ }
13596
+ if (
13597
+ typeof directory !== 'string' ||
13598
+ (directory !== layout.groupScope && !directory.startsWith(layout.groupScope + '/'))
13599
+ ) continue;
13265
13600
  }
13601
+ matchingLayouts.push(layout);
13266
13602
  }
13267
13603
 
13268
- return matchingLayouts.sort((a, b) => a.pattern.length - b.pattern.length);
13604
+ return matchingLayouts.sort(
13605
+ (a, b) => a.pattern.split('/').filter(Boolean).length - b.pattern.split('/').filter(Boolean).length,
13606
+ );
13269
13607
  }
13270
13608
 
13271
13609
  // ====== SPA ROUTER ======
@@ -14047,14 +14385,23 @@ async function tryHydrateImportedPage(
14047
14385
  } else if (layoutShouldHydrate) {
14048
14386
  currentPageProps = existingProps || { params };
14049
14387
  const serverPage = document.getElementById('__farm_page__');
14050
- pageElement = createLayoutPageBoundary(
14051
- false,
14052
- islandStrategy,
14053
- null,
14054
- typeof hydrationOptions.serverHtml === 'string'
14055
- ? hydrationOptions.serverHtml
14056
- : serverPage ? serverPage.innerHTML : '',
14057
- );
14388
+ const pageSource = typeof hydrationOptions.serverHtml === 'string'
14389
+ ? hydrationOptions.serverHtml
14390
+ : serverPage;
14391
+ const serverTree = pageSource
14392
+ ? await createFarmServerTreePageElement(pageSource, window.location.pathname)
14393
+ : null;
14394
+ if (signal?.aborted || !container?.isConnected) return false;
14395
+ pageElement = serverTree
14396
+ ? createLayoutPageBoundary(false, islandStrategy, serverTree)
14397
+ : createLayoutPageBoundary(
14398
+ false,
14399
+ islandStrategy,
14400
+ null,
14401
+ typeof hydrationOptions.serverHtml === 'string'
14402
+ ? hydrationOptions.serverHtml
14403
+ : serverPage ? serverPage.innerHTML : '',
14404
+ );
14058
14405
  }
14059
14406
  if (signal?.aborted || !container?.isConnected || !pageElement) return false;
14060
14407
 
@@ -14240,6 +14587,8 @@ async function renderPage(pageData) {
14240
14587
  loadingModulePath: pageData.loadingModulePath,
14241
14588
  };
14242
14589
  const params = pageData.props?.params || {};
14590
+ // Page data carries middleware data as JSON, the way a full load embeds it.
14591
+ const pageProps = pageData.props ? normalizeServerProps(pageData.props) : pageData.props;
14243
14592
  const nextLayoutPatterns = Array.isArray(pageData.fragment?.layoutPatterns)
14244
14593
  ? pageData.fragment.layoutPatterns
14245
14594
  : [];
@@ -14256,6 +14605,20 @@ async function renderPage(pageData) {
14256
14605
  let fragmentHtml = pageData.fragment?.html;
14257
14606
  let layoutPatterns = nextLayoutPatterns;
14258
14607
 
14608
+ // The fragment leaves out the layouts both routes share. When React owns the
14609
+ // current layouts and will not keep rendering them, the swap below replaces the
14610
+ // whole container, so a fragment without its outer layouts would drop them.
14611
+ // Load the complete route for that swap instead.
14612
+ if (
14613
+ typeof fragmentHtml === 'string' &&
14614
+ activeLayoutShouldHydrate &&
14615
+ !(route.layoutShouldHydrate && (appRoot || reactRoot)) &&
14616
+ nextLayoutPatterns.length > 0 &&
14617
+ !findLayoutBoundary(parseNavigationFragment(fragmentHtml), nextLayoutPatterns[0])
14618
+ ) {
14619
+ fragmentHtml = undefined;
14620
+ }
14621
+
14259
14622
  if (typeof fragmentHtml !== 'string') {
14260
14623
  const deploymentId = window.__FARM_DEPLOYMENT_ID__;
14261
14624
  const response = await fetch(path, {
@@ -14296,7 +14659,7 @@ async function renderPage(pageData) {
14296
14659
  params,
14297
14660
  layouts,
14298
14661
  false,
14299
- pageData.props,
14662
+ pageProps,
14300
14663
  null,
14301
14664
  {
14302
14665
  pageShouldHydrate,
@@ -14342,7 +14705,7 @@ async function renderPage(pageData) {
14342
14705
  params,
14343
14706
  layouts,
14344
14707
  true,
14345
- pageData.props,
14708
+ pageProps,
14346
14709
  hydrationController.signal,
14347
14710
  {
14348
14711
  pageShouldHydrate,
@@ -14456,17 +14819,20 @@ async function hydrate() {
14456
14819
  return
14457
14820
  }
14458
14821
 
14459
- // Get props - either from server-injected props or by matching the current URL
14460
- if (!pageProps || !pageProps.params || Object.keys(pageProps.params).length === 0) {
14461
- // Extract params from URL using manifest route matching (fallback)
14822
+ // Use the server-injected props. A document that carries no params (a route
14823
+ // without any, or generated HTML) takes them from the current URL, keeping
14824
+ // what the server rendered with, such as middleware data.
14825
+ if (!pageProps.params || Object.keys(pageProps.params).length === 0) {
14462
14826
  const pathname = window.location.pathname;
14463
14827
  const foundRoute = findRoute(pathname);
14464
- pageProps = normalizeServerProps({
14465
- params: foundRoute?.params || {},
14466
- search: getCurrentSearchParams(),
14467
- searchParams: getCurrentSearchParams(),
14828
+ const search = getCurrentSearchParams();
14829
+ pageProps = {
14830
+ search,
14831
+ searchParams: search,
14468
14832
  path: pathname,
14469
- });
14833
+ ...pageProps,
14834
+ params: foundRoute?.params || {},
14835
+ };
14470
14836
  }
14471
14837
  currentPageProps = pageProps;
14472
14838
 
@@ -14659,9 +15025,9 @@ function generateClientManifest(bundle) {
14659
15025
  __name(generateClientManifest, "generateClientManifest");
14660
15026
  async function defineConfig(config = {}) {
14661
15027
  const tailwindVitePlugin = await loadTailwindVitePlugin();
14662
- const appRoot = path20.resolve(config.root || process.cwd());
15028
+ const appRoot = path21.resolve(config.root || process.cwd());
14663
15029
  if (config.extends?.length) {
14664
- const { config: layeredConfig } = await import("./layers-BRQF5ETU.mjs").then(
15030
+ const { config: layeredConfig } = await import("./layers-UTB43B7A.mjs").then(
14665
15031
  ({ resolveFarmLayers }) => resolveFarmLayers(config, {
14666
15032
  root: appRoot,
14667
15033
  mode: process.env.NODE_ENV === "production" ? "production" : "development"
@@ -14882,10 +15248,10 @@ export {
14882
15248
  resolveFarmIsolatedClientHydrationMode,
14883
15249
  getClientModuleMetadata,
14884
15250
  getClientModuleHydrationPlan,
15251
+ usesFarmServerTree,
14885
15252
  createMarkdownPageHydrationPlanner,
14886
15253
  enforceFarmIsolatedHydrationRouteBudget,
14887
15254
  RouteManager,
14888
- HOISTED_HEAD_ELEMENT,
14889
15255
  resolveFarmNotFoundComponentPath,
14890
15256
  farmFontImportsPlugin,
14891
15257
  mergeFarmFontCss,
@@ -14911,6 +15277,7 @@ export {
14911
15277
  createFarmSourceAlias,
14912
15278
  mergeFarmViteConfig,
14913
15279
  mergeFarmProductionViteConfig,
15280
+ farmDocsClientConfigPlugin,
14914
15281
  createFarmThemeCssPlugin,
14915
15282
  farmI18nClientBridgePlugin,
14916
15283
  farmServerOnlyEntriesPlugin,