@farm.js/core 0.1.51-beta.2 → 0.1.60

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 (321) hide show
  1. package/dist/{agent-mcp-handler-WWCC4GLG.mjs → agent-mcp-handler-7QMX2LUY.mjs} +7 -7
  2. package/dist/agent-mcp-handler-OV4WRFBL.cjs +18 -0
  3. package/dist/{agent-mcp.d-Z5DuwrqW.d.mts → agent-mcp.d-C-2S9bnP.d.mts} +1 -1
  4. package/dist/{agent-mcp.d-CR5Ov83o.d.ts → agent-mcp.d-SIoCUP1I.d.ts} +1 -1
  5. package/dist/agent-runtime.cjs +5 -5
  6. package/dist/agent-runtime.d.mts +2 -2
  7. package/dist/agent-runtime.d.ts +2 -2
  8. package/dist/agent-runtime.mjs +4 -4
  9. package/dist/{analyzer-Z6TNEAET.mjs → analyzer-22BEYV7S.mjs} +126 -12
  10. package/dist/{analyzer-T76CN3S7.cjs → analyzer-LCSI3NSH.cjs} +132 -18
  11. package/dist/api/client.cjs +5 -4
  12. package/dist/api/client.d.mts +1 -1
  13. package/dist/api/client.d.ts +1 -1
  14. package/dist/api/client.mjs +3 -2
  15. package/dist/api/client.native.cjs +45 -0
  16. package/dist/api/client.native.d.mts +23 -0
  17. package/dist/api/client.native.d.ts +23 -0
  18. package/dist/api/client.native.mjs +45 -0
  19. package/dist/api/route-manager.cjs +7 -7
  20. package/dist/api/route-manager.d.mts +4 -4
  21. package/dist/api/route-manager.d.ts +4 -4
  22. package/dist/api/route-manager.mjs +6 -6
  23. package/dist/api/runtime.cjs +5 -5
  24. package/dist/api/runtime.d.mts +3 -3
  25. package/dist/api/runtime.d.ts +3 -3
  26. package/dist/api/runtime.mjs +4 -4
  27. package/dist/{api-client.d-CeA6tNA6.d.mts → api-client.d-BNLXNCXJ.d.mts} +1 -1
  28. package/dist/{api-client.d-BWcqZciH.d.ts → api-client.d-ddQBNGtu.d.ts} +1 -1
  29. package/dist/api.cjs +11 -11
  30. package/dist/api.d.mts +5 -5
  31. package/dist/api.d.ts +5 -5
  32. package/dist/api.mjs +10 -10
  33. package/dist/{app-manifest.d-CAHkOBFa.d.mts → app-manifest.d-DrSAHskY.d.mts} +1 -1
  34. package/dist/{app-manifest.d-DiWr_Jfx.d.ts → app-manifest.d-Tb3CJpL4.d.ts} +1 -1
  35. package/dist/app-markdown.cjs +7 -7
  36. package/dist/app-markdown.d.mts +3 -3
  37. package/dist/app-markdown.d.ts +3 -3
  38. package/dist/app-markdown.mjs +6 -6
  39. package/dist/{app.d-DmapqkbV.d.ts → app.d-CmWlYpZJ.d.ts} +9 -4
  40. package/dist/{app.d-BfgJCsTQ.d.mts → app.d-D6QQM_kk.d.mts} +9 -4
  41. package/dist/{chunk-SN5VSO3Q.mjs → chunk-25T5VXOE.mjs} +7 -9
  42. package/dist/{chunk-GUJTVM36.cjs → chunk-2FRLSDBT.cjs} +1 -1
  43. package/dist/{chunk-LM2YOGDK.mjs → chunk-2I6PUKWJ.mjs} +1 -1
  44. package/dist/{chunk-EIMK7D2D.mjs → chunk-2KTYMMWT.mjs} +34 -4
  45. package/dist/{chunk-B5BBTPJQ.cjs → chunk-2OF5RPVU.cjs} +14 -14
  46. package/dist/chunk-37PYUEK5.mjs +533 -0
  47. package/dist/chunk-3HLQTOVU.cjs +6 -0
  48. package/dist/{chunk-VSLM6BHX.cjs → chunk-3OJNNCDL.cjs} +9 -9
  49. package/dist/{chunk-X3JNB2TB.mjs → chunk-3PX4AIXO.mjs} +36 -5
  50. package/dist/{chunk-UQHIWZZ6.cjs → chunk-3TL3AH25.cjs} +12 -6
  51. package/dist/chunk-3YMLUNL2.cjs +251 -0
  52. package/dist/chunk-4JTQPOKO.cjs +137 -0
  53. package/dist/{chunk-QXPSWMUD.cjs → chunk-4P23B7DU.cjs} +5 -5
  54. package/dist/{chunk-YVJV7Q2X.mjs → chunk-55U5QIXQ.mjs} +1 -1
  55. package/dist/{chunk-5N7QAGEA.cjs → chunk-5JNUYGNF.cjs} +37 -7
  56. package/dist/{chunk-NJLTQR5P.cjs → chunk-6BJJYOFL.cjs} +7 -7
  57. package/dist/chunk-6UUH4N4J.mjs +251 -0
  58. package/dist/{chunk-2NHOYYUT.mjs → chunk-7H45IJWO.mjs} +2 -2
  59. package/dist/{chunk-NN3MOPSI.mjs → chunk-A2MN5PQJ.mjs} +7 -7
  60. package/dist/{chunk-KY32FWK7.mjs → chunk-BHJAYPYU.mjs} +2 -2
  61. package/dist/{chunk-VAHBCI6X.mjs → chunk-BQWBHWEW.mjs} +26 -1
  62. package/dist/{chunk-KJMWAUKE.mjs → chunk-C7GJDVN4.mjs} +1 -1
  63. package/dist/{chunk-OYNNA4DD.cjs → chunk-CBKRS3M4.cjs} +9 -9
  64. package/dist/{chunk-I2DQGS56.cjs → chunk-CBOEJ5Z4.cjs} +39 -41
  65. package/dist/{chunk-BOVGCUDZ.cjs → chunk-CI4UNQHO.cjs} +2 -2
  66. package/dist/{chunk-S5AQ7CAC.cjs → chunk-CNNBFGL5.cjs} +39 -14
  67. package/dist/chunk-D2X5MUF5.cjs +1457 -0
  68. package/dist/{chunk-LEIXUFJN.cjs → chunk-D4MRNBVF.cjs} +10 -9
  69. package/dist/{chunk-2KVDHNQS.mjs → chunk-D7LTCK3U.mjs} +2 -2
  70. package/dist/{chunk-J3LBO2O4.cjs → chunk-DPJ66FSI.cjs} +22 -22
  71. package/dist/{chunk-NYQSC4DX.cjs → chunk-DZPR2W6U.cjs} +5 -5
  72. package/dist/{chunk-GW4YUIHW.mjs → chunk-E72UD6ME.mjs} +1 -1
  73. package/dist/chunk-EFZGB7JC.cjs +114 -0
  74. package/dist/{chunk-XXXRRVY6.mjs → chunk-EGVC4LIG.mjs} +5 -5
  75. package/dist/{chunk-72NBDVWQ.mjs → chunk-EXUONJYV.mjs} +3 -3
  76. package/dist/{chunk-VS7EHLLW.mjs → chunk-EZ34EHQP.mjs} +1 -1
  77. package/dist/{chunk-FM2UEKS2.mjs → chunk-F6Y7ZAPQ.mjs} +2 -2
  78. package/dist/{chunk-LMFJCXDD.mjs → chunk-FN5UEC7I.mjs} +1 -1
  79. package/dist/{chunk-E6LTONL4.mjs → chunk-FORSVMEJ.mjs} +2 -2
  80. package/dist/{chunk-6CYQQQGR.mjs → chunk-HPWB57PZ.mjs} +1 -1
  81. package/dist/{chunk-Y2G5SJFB.mjs → chunk-IFHPDLIS.mjs} +1 -1
  82. package/dist/{chunk-GNJIYJMS.cjs → chunk-IFXSBJPN.cjs} +16 -16
  83. package/dist/{chunk-74Z5KX4A.mjs → chunk-ILMTRGBG.mjs} +309 -56
  84. package/dist/{chunk-NXBHYO7S.cjs → chunk-JBK7UJOI.cjs} +14 -11
  85. package/dist/chunk-JI5D7MXY.mjs +137 -0
  86. package/dist/{chunk-QXJADAQB.cjs → chunk-JIBEFLQ7.cjs} +6 -2
  87. package/dist/{chunk-LZ4SB57H.mjs → chunk-JPIUGDK4.mjs} +1 -1
  88. package/dist/{chunk-Y3N5BFRJ.mjs → chunk-JSDV2NUN.mjs} +1 -1
  89. package/dist/{chunk-IRSS4HS4.mjs → chunk-K3RU5MOR.mjs} +1 -1
  90. package/dist/chunk-KPOMS5RO.cjs +237 -0
  91. package/dist/{chunk-LAZK6UV7.mjs → chunk-KVW2M6PI.mjs} +1 -1
  92. package/dist/{chunk-5IONBVJY.cjs → chunk-LB3DPQP6.cjs} +22 -22
  93. package/dist/{chunk-CZ35L6PL.mjs → chunk-LJVNMGE3.mjs} +10 -4
  94. package/dist/chunk-LLZSYFOM.mjs +6 -0
  95. package/dist/{chunk-X2AMN2WV.cjs → chunk-LQNW3ABP.cjs} +10 -10
  96. package/dist/{chunk-6ONBZGVH.cjs → chunk-LRB5OVRT.cjs} +3 -3
  97. package/dist/{chunk-WJFFPXCV.cjs → chunk-LT4VAF5Z.cjs} +12 -10
  98. package/dist/{chunk-F6TLUMH7.mjs → chunk-M53MIIXY.mjs} +1 -1
  99. package/dist/{chunk-HIFIG6HL.cjs → chunk-MEQN6DDA.cjs} +5 -5
  100. package/dist/{chunk-XLRLSTJ6.cjs → chunk-MGKW5XZE.cjs} +7 -7
  101. package/dist/{chunk-B3GZAQSC.cjs → chunk-MHLNWRCJ.cjs} +3 -3
  102. package/dist/{chunk-5ENW27SL.mjs → chunk-MMK4MZUN.mjs} +1 -1
  103. package/dist/{chunk-DTU4PX7V.cjs → chunk-MTWXOEI4.cjs} +927 -629
  104. package/dist/chunk-NHD7BAKD.mjs +1457 -0
  105. package/dist/{chunk-NPQLMP7M.cjs → chunk-NQJDO7K7.cjs} +32 -31
  106. package/dist/{chunk-76GHW3WI.cjs → chunk-O27PLNQZ.cjs} +10 -10
  107. package/dist/{chunk-PIHKO25G.mjs → chunk-OM7WILES.mjs} +1 -1
  108. package/dist/{chunk-7UPCJDB5.mjs → chunk-PCXIJKPM.mjs} +8 -8
  109. package/dist/{chunk-IWFV5ZED.cjs → chunk-PMJSG4JS.cjs} +1 -1
  110. package/dist/{chunk-JATTVAHA.cjs → chunk-PRFNLQSP.cjs} +4 -4
  111. package/dist/{chunk-SBABQKPT.cjs → chunk-QAS7KE7J.cjs} +7 -7
  112. package/dist/chunk-QGOZLGVP.mjs +0 -0
  113. package/dist/{chunk-VQJYGZNX.cjs → chunk-QMNWKQL4.cjs} +1 -1
  114. package/dist/{chunk-XB24LZWI.cjs → chunk-QRX4JRBO.cjs} +3 -3
  115. package/dist/{chunk-LNM57D3H.cjs → chunk-R53QDV6T.cjs} +4 -4
  116. package/dist/{chunk-SUV6YO4Q.cjs → chunk-RAWWCDCT.cjs} +5 -5
  117. package/dist/{chunk-LJDIFIJ2.mjs → chunk-RPUJHJHE.mjs} +4 -4
  118. package/dist/{chunk-G2KTRMWA.mjs → chunk-RSEAX5MW.mjs} +4 -0
  119. package/dist/chunk-SJRCWF4Z.mjs +237 -0
  120. package/dist/{chunk-IBSAYAWB.mjs → chunk-SX7EECTS.mjs} +8 -5
  121. package/dist/{chunk-KBRZAYI7.mjs → chunk-T4TBK5NY.mjs} +2 -2
  122. package/dist/{chunk-4SSRBCBR.mjs → chunk-T7I62A4C.mjs} +619 -321
  123. package/dist/{chunk-E36C43IX.cjs → chunk-U4BJKNIR.cjs} +6 -6
  124. package/dist/{chunk-YU42A5MA.cjs → chunk-UDJY2ZGY.cjs} +533 -280
  125. package/dist/{chunk-SHS6KXOZ.mjs → chunk-UR25Z5Z6.mjs} +1 -1
  126. package/dist/{chunk-WZW6LEHM.cjs → chunk-UYSTTPYJ.cjs} +1590 -1019
  127. package/dist/{chunk-KRRZJ77U.mjs → chunk-UZZ6IEQP.mjs} +3 -3
  128. package/dist/{chunk-EKJYE4Y7.cjs → chunk-VGG74PSU.cjs} +25 -25
  129. package/dist/{chunk-CTM4SPB3.mjs → chunk-VPTWKOCY.mjs} +20 -19
  130. package/dist/{chunk-UN6N623E.mjs → chunk-VQJHT2ND.mjs} +2 -2
  131. package/dist/{chunk-SJ23LJ3N.cjs → chunk-VVTJTMGQ.cjs} +3 -3
  132. package/dist/{chunk-KHXAJ2KA.cjs → chunk-W2RZ73IU.cjs} +12 -12
  133. package/dist/{chunk-JWI5PUO2.mjs → chunk-W2ZXMMHA.mjs} +2 -1
  134. package/dist/{chunk-BLD5GVCG.mjs → chunk-W6QLRQ3V.mjs} +1 -1
  135. package/dist/{chunk-AV26KHTG.mjs → chunk-X2CZTWQA.mjs} +2 -2
  136. package/dist/chunk-XPIPMWY3.cjs +1 -0
  137. package/dist/chunk-XTG73QZA.cjs +533 -0
  138. package/dist/{chunk-XPMC4E2G.cjs → chunk-XVSBALOY.cjs} +3 -3
  139. package/dist/{chunk-XYL4HSVC.cjs → chunk-YI6FKTTN.cjs} +38 -7
  140. package/dist/{chunk-N77JBPLC.mjs → chunk-YSXTNSXS.mjs} +10 -8
  141. package/dist/{chunk-EHB77D5U.cjs → chunk-ZDAEHG2O.cjs} +3 -3
  142. package/dist/{chunk-PMKUU273.mjs → chunk-ZFUKPWFC.mjs} +1226 -655
  143. package/dist/{chunk-E73PGHSR.mjs → chunk-ZMHAFH4R.mjs} +8 -8
  144. package/dist/{chunk-ZOWNWHK6.cjs → chunk-ZNH6NR3H.cjs} +2 -2
  145. package/dist/chunk-ZNXTU4YH.mjs +114 -0
  146. package/dist/{chunk-PFV2KPDZ.cjs → chunk-ZOYKJBP5.cjs} +3 -3
  147. package/dist/{chunk-CECUDGXQ.cjs → chunk-ZP32GNJQ.cjs} +13 -13
  148. package/dist/{chunk-72D2NX77.mjs → chunk-ZZ2QKCKW.mjs} +1 -1
  149. package/dist/{client-plugins.d-Bx3FXpqm.d.mts → client-plugins.d-CgQQ-EAv.d.mts} +25 -4
  150. package/dist/{client-plugins.d-TiLbS5j4.d.ts → client-plugins.d-vXrbcfJ1.d.ts} +25 -4
  151. package/dist/client-plugins.d.mts +2 -2
  152. package/dist/client-plugins.d.ts +2 -2
  153. package/dist/client.cjs +9 -9
  154. package/dist/client.d.mts +9 -9
  155. package/dist/client.d.ts +9 -9
  156. package/dist/client.mjs +9 -9
  157. package/dist/{config.d-iRPI16ku.d.mts → config.d-DqZkLwef.d.mts} +146 -1
  158. package/dist/{config.d-iRPI16ku.d.ts → config.d-DqZkLwef.d.ts} +146 -1
  159. package/dist/config.d.mts +2 -2
  160. package/dist/config.d.ts +2 -2
  161. package/dist/cron.cjs +3 -3
  162. package/dist/cron.d.mts +10 -0
  163. package/dist/cron.d.ts +10 -0
  164. package/dist/cron.mjs +2 -2
  165. package/dist/desktop.d.mts +3 -3
  166. package/dist/desktop.d.ts +3 -3
  167. package/dist/{devtools-UQLDAOEI.mjs → devtools-KQZ6SRCJ.mjs} +16 -16
  168. package/dist/{devtools-6XWCZIGO.cjs → devtools-UF6JYHUN.cjs} +18 -18
  169. package/dist/docs.cjs +19 -19
  170. package/dist/docs.d.mts +3 -3
  171. package/dist/docs.d.ts +3 -3
  172. package/dist/docs.mjs +18 -18
  173. package/dist/index.cjs +99 -95
  174. package/dist/{index.d-yueUNipJ.d.ts → index.d-DlCELfhf.d.ts} +1 -1
  175. package/dist/{index.d-YxJ2AiDF.d.mts → index.d-Dmfb7Kb_.d.mts} +1 -1
  176. package/dist/index.d.mts +18 -18
  177. package/dist/index.d.ts +18 -18
  178. package/dist/index.mjs +139 -135
  179. package/dist/integrations.cjs +5 -5
  180. package/dist/integrations.d.mts +2 -2
  181. package/dist/integrations.d.ts +2 -2
  182. package/dist/integrations.mjs +4 -4
  183. package/dist/internal/app-markdown-runtime.cjs +6 -6
  184. package/dist/internal/app-markdown-runtime.d.mts +3 -3
  185. package/dist/internal/app-markdown-runtime.d.ts +3 -3
  186. package/dist/internal/app-markdown-runtime.mjs +5 -5
  187. package/dist/internal/build-runtime.cjs +52 -50
  188. package/dist/internal/build-runtime.d.mts +4 -4
  189. package/dist/internal/build-runtime.d.ts +4 -4
  190. package/dist/internal/build-runtime.mjs +51 -49
  191. package/dist/internal/cli-runtime.cjs +28 -28
  192. package/dist/internal/cli-runtime.mjs +28 -28
  193. package/dist/internal/client-error-overlay.cjs +4 -4
  194. package/dist/internal/client-error-overlay.mjs +1 -1
  195. package/dist/internal/client-runtime.cjs +20 -15
  196. package/dist/internal/client-runtime.d.mts +5 -5
  197. package/dist/internal/client-runtime.d.ts +5 -5
  198. package/dist/internal/client-runtime.mjs +8 -3
  199. package/dist/internal/compression-runtime.d.mts +2 -2
  200. package/dist/internal/compression-runtime.d.ts +2 -2
  201. package/dist/internal/config-runtime.cjs +18 -18
  202. package/dist/internal/config-runtime.d.mts +119 -7
  203. package/dist/internal/config-runtime.d.ts +119 -7
  204. package/dist/internal/config-runtime.mjs +17 -17
  205. package/dist/internal/infra-analytics-runtime.cjs +11 -11
  206. package/dist/internal/infra-analytics-runtime.mjs +9 -9
  207. package/dist/internal/islands-boot.cjs +211 -0
  208. package/dist/internal/islands-boot.d.mts +8 -0
  209. package/dist/internal/islands-boot.d.ts +8 -0
  210. package/dist/internal/islands-boot.mjs +211 -0
  211. package/dist/internal/product-telemetry-runtime.cjs +2 -2
  212. package/dist/internal/product-telemetry-runtime.mjs +1 -1
  213. package/dist/internal/production-runtime.cjs +42 -28
  214. package/dist/internal/production-runtime.d.mts +50 -12
  215. package/dist/internal/production-runtime.d.ts +50 -12
  216. package/dist/internal/production-runtime.mjs +52 -38
  217. package/dist/markdown.cjs +7 -5
  218. package/dist/markdown.d.mts +2 -2
  219. package/dist/markdown.d.ts +2 -2
  220. package/dist/markdown.mjs +6 -4
  221. package/dist/middleware.cjs +10 -10
  222. package/dist/middleware.d.mts +4 -4
  223. package/dist/middleware.d.ts +4 -4
  224. package/dist/middleware.mjs +9 -9
  225. package/dist/mobile.d.mts +43 -5
  226. package/dist/mobile.d.ts +43 -5
  227. package/dist/modules-VHD7BELU.mjs +13 -0
  228. package/dist/modules-WT5D3AWY.cjs +13 -0
  229. package/dist/native-specs-BD7HOTMJ.mjs +15 -0
  230. package/dist/native-specs-IQQRJOOW.cjs +15 -0
  231. package/dist/native-tree-6G5O53O3.cjs +27 -0
  232. package/dist/native-tree-VWNW2MQ2.mjs +27 -0
  233. package/dist/native.cjs +87 -0
  234. package/dist/native.d.mts +72 -0
  235. package/dist/native.d.ts +72 -0
  236. package/dist/native.mjs +87 -0
  237. package/dist/{navigation-delegate.d-HnDXhlyP.d.mts → navigation-delegate.d-CnOTWOyi.d.mts} +1 -1
  238. package/dist/{navigation-delegate.d-BY1e_Xrh.d.ts → navigation-delegate.d-JXx40JzR.d.ts} +1 -1
  239. package/dist/navigation.cjs +5 -5
  240. package/dist/navigation.d.mts +5 -5
  241. package/dist/navigation.d.ts +5 -5
  242. package/dist/navigation.mjs +4 -4
  243. package/dist/{nitro-R444AF3O.mjs → nitro-FLN6DRGJ.mjs} +7 -7
  244. package/dist/{nitro-CK7M4RMY.cjs → nitro-HXAZZQKY.cjs} +12 -12
  245. package/dist/plugin.cjs +43 -42
  246. package/dist/plugin.d.mts +5 -4
  247. package/dist/plugin.d.ts +5 -4
  248. package/dist/plugin.mjs +42 -41
  249. package/dist/port-C6GBH4C6.cjs +419 -0
  250. package/dist/port-WOOQ3V56.mjs +419 -0
  251. package/dist/{production-runtime.d-BpJUDzP8.d.mts → production-runtime.d-CP5s6RuY.d.mts} +1 -1
  252. package/dist/{production-runtime.d-lMjvE9cf.d.ts → production-runtime.d-N-cE3pmy.d.ts} +1 -1
  253. package/dist/{programmatic-routes-client.d-BlFp5hv4.d.ts → programmatic-routes-client.d-CLG2N1yH.d.ts} +2 -2
  254. package/dist/{programmatic-routes-client.d-6CGQ3TCk.d.mts → programmatic-routes-client.d-CPbNqtIi.d.mts} +2 -2
  255. package/dist/query/client.cjs +6 -6
  256. package/dist/query/client.mjs +2 -2
  257. package/dist/{render-plan.d-DhP0mTHF.d.ts → render-plan.d-B9lAP3uX.d.ts} +1 -1
  258. package/dist/{render-plan.d-BH9edqKs.d.mts → render-plan.d-DZ-qjjdG.d.mts} +1 -1
  259. package/dist/renderer/react/server.cjs +2 -2
  260. package/dist/renderer/react/server.mjs +3 -3
  261. package/dist/renderer-client.cjs +6 -6
  262. package/dist/renderer-client.d.mts +5 -5
  263. package/dist/renderer-client.d.ts +5 -5
  264. package/dist/renderer-client.mjs +2 -2
  265. package/dist/{request.d-BVZrsR1v.d.ts → request.d-BiicaNxb.d.ts} +1 -1
  266. package/dist/{request.d-DJFRdKi8.d.mts → request.d-DV0oeUit.d.mts} +1 -1
  267. package/dist/request.d.mts +3 -3
  268. package/dist/request.d.ts +3 -3
  269. package/dist/{route-rendering.d-Bpmw7PED.d.mts → route-rendering.d-BrIKA51A.d.mts} +1 -1
  270. package/dist/{route-rendering.d-B00JtK_-.d.ts → route-rendering.d-Iss0C7GR.d.ts} +1 -1
  271. package/dist/{router.d-Bd1x9XxQ.d.ts → router.d-DjGn_al7.d.ts} +1 -1
  272. package/dist/{router.d-e0jQ3jQ-.d.mts → router.d-mNTbOGV_.d.mts} +1 -1
  273. package/dist/{routes.d-D96Dq9lz.d.ts → routes.d-BKSjHuH9.d.ts} +27 -4
  274. package/dist/{routes.d-Cmv8TgVq.d.mts → routes.d-qd8Qf4LG.d.mts} +27 -4
  275. package/dist/routes.d.mts +2 -2
  276. package/dist/routes.d.ts +2 -2
  277. package/dist/{rsc-pipeline-DX4OC5FN.cjs → rsc-pipeline-SVLBTY7H.cjs} +21 -21
  278. package/dist/{rsc-pipeline-ZQ4CTVEG.mjs → rsc-pipeline-WBLBDQXA.mjs} +20 -20
  279. package/dist/{runtime-NQ3EDSA7.cjs → runtime-DGUOWSMF.cjs} +307 -48
  280. package/dist/{runtime-NPDRDV6R.mjs → runtime-HFZTVNFF.mjs} +298 -39
  281. package/dist/{runtime.d-CgB3IJDq.d.mts → runtime.d-BNVbojF1.d.mts} +1 -1
  282. package/dist/{runtime.d-D-td-RR3.d.ts → runtime.d-Bm_4hP5T.d.ts} +1 -1
  283. package/dist/{schema-dev-notice-F6QYSOAI.mjs → schema-dev-notice-JMXEQWIQ.mjs} +3 -3
  284. package/dist/{schema-dev-notice-UU7DMZEU.cjs → schema-dev-notice-PLBFDTOF.cjs} +6 -6
  285. package/dist/server-fn-client.d.mts +1 -1
  286. package/dist/server-fn-client.d.ts +1 -1
  287. package/dist/server-plugins.cjs +1 -1
  288. package/dist/server-plugins.d.mts +3 -3
  289. package/dist/server-plugins.d.ts +3 -3
  290. package/dist/server-plugins.mjs +1 -1
  291. package/dist/server.cjs +82 -81
  292. package/dist/server.d.mts +12 -11
  293. package/dist/server.d.ts +12 -11
  294. package/dist/server.mjs +65 -64
  295. package/dist/session-2Q72D4QV.cjs +23 -0
  296. package/dist/{session-IGEDQ5PY.mjs → session-QZXZOPR2.mjs} +2 -2
  297. package/dist/shell-render.d-CG6bPiiA.d.mts +41 -0
  298. package/dist/shell-render.d-CG6bPiiA.d.ts +41 -0
  299. package/dist/{spa-router.d-CO01mVOM.d.ts → spa-router.d-DAtnNoBe.d.ts} +11 -2
  300. package/dist/{spa-router.d-BWDhS0FK.d.mts → spa-router.d-DHDoXxDE.d.mts} +11 -2
  301. package/dist/testing.cjs +7 -7
  302. package/dist/testing.d.mts +2 -2
  303. package/dist/testing.d.ts +2 -2
  304. package/dist/testing.mjs +6 -6
  305. package/dist/{utils.d-B77__yh8.d.ts → utils.d-DwZ-KLSB.d.ts} +7 -1
  306. package/dist/{utils.d-DRDazhCA.d.mts → utils.d-uKZcKJk4.d.mts} +7 -1
  307. package/dist/version.cjs +2 -2
  308. package/dist/version.mjs +1 -1
  309. package/dist/vite.cjs +43 -42
  310. package/dist/vite.d.mts +17 -6
  311. package/dist/vite.d.ts +17 -6
  312. package/dist/vite.mjs +42 -41
  313. package/dist/workflows.cjs +3 -3
  314. package/dist/workflows.mjs +2 -2
  315. package/package.json +17 -3
  316. package/dist/agent-mcp-handler-RT3COCEL.cjs +0 -18
  317. package/dist/session-AAU7RNRO.cjs +0 -23
  318. package/dist/{chunk-7FVVQEVL.cjs → chunk-4BS3HSY7.cjs} +2 -2
  319. package/dist/{chunk-N7JQXQAV.cjs → chunk-5OJVKXFV.cjs} +2 -2
  320. package/dist/{chunk-WSDKXV4E.mjs → chunk-72KABRWN.mjs} +4 -4
  321. package/dist/{chunk-C3BOESDW.mjs → chunk-B4CWYGCG.mjs} +3 -3
@@ -5,7 +5,7 @@ import {
5
5
  collectSSGPages,
6
6
  matchSSGPage,
7
7
  resolveRouteRenderingConfigFromFile
8
- } from "./chunk-CZ35L6PL.mjs";
8
+ } from "./chunk-LJVNMGE3.mjs";
9
9
  import {
10
10
  classifyFarmDocumentPrefix,
11
11
  composeFarmFullDocument,
@@ -24,16 +24,21 @@ import {
24
24
  getFarmServerTreeLayoutPatterns,
25
25
  getRouteDirectoryDepth,
26
26
  getRouteGroupScope,
27
+ getSharedLayoutPrefixLength,
27
28
  isInRouteGroupScope,
28
29
  openFarmStreamedDocument,
30
+ parseFarmLayoutChainHeader,
29
31
  removeFarmDocumentTitles,
30
32
  renderFarmLocaleAlternateLinks,
31
33
  resolveDefaultErrorStatus,
32
34
  routeBoundaryCoversDirectory
33
- } from "./chunk-7UPCJDB5.mjs";
35
+ } from "./chunk-PCXIJKPM.mjs";
36
+ import {
37
+ handleFarmFormActionRequest
38
+ } from "./chunk-Z5A6CNV2.mjs";
34
39
  import {
35
40
  listFarmMCPLlmsTxtLinks
36
- } from "./chunk-E73PGHSR.mjs";
41
+ } from "./chunk-ZMHAFH4R.mjs";
37
42
  import {
38
43
  FARM_DEFAULT_MCP_PATH,
39
44
  collectFarmDefaultMCPPages,
@@ -41,7 +46,7 @@ import {
41
46
  farmConfigMountsMCP,
42
47
  isFarmDefaultMCPPathname,
43
48
  resolveFarmDefaultMCPServer
44
- } from "./chunk-KRRZJ77U.mjs";
49
+ } from "./chunk-UZZ6IEQP.mjs";
45
50
  import {
46
51
  createFarmMetadataImageResponse
47
52
  } from "./chunk-OZK2DS44.mjs";
@@ -49,9 +54,6 @@ import {
49
54
  installFarmIslandValues,
50
55
  uninstallFarmIslandValues
51
56
  } from "./chunk-A4PWGL46.mjs";
52
- import {
53
- handleFarmFormActionRequest
54
- } from "./chunk-Z5A6CNV2.mjs";
55
57
  import {
56
58
  FARM_ISLAND_REPLAYABLE_SELECTOR,
57
59
  isFarmIslandStrategy
@@ -61,17 +63,6 @@ import {
61
63
  mergeProgrammaticClientRoutes,
62
64
  resolveProgrammaticClientRoutes
63
65
  } from "./chunk-ZQ5BDNKW.mjs";
64
- import {
65
- createFarmMarkdownRouteModuleFromFile,
66
- loadFarmMdxComponents
67
- } from "./chunk-YVJV7Q2X.mjs";
68
- import {
69
- isFarmMarkdownPageFile
70
- } from "./chunk-GW4YUIHW.mjs";
71
- import {
72
- _setDefaultFarmThemeConfig,
73
- getTheme
74
- } from "./chunk-EMDGXYUD.mjs";
75
66
  import {
76
67
  isSecretDocsConfigKey
77
68
  } from "./chunk-EJCVG25Z.mjs";
@@ -105,14 +96,7 @@ import {
105
96
  resolveFarmAgentCrawlers,
106
97
  resolveFarmAgentSitemap,
107
98
  resolveFarmPerformanceConfig
108
- } from "./chunk-KBRZAYI7.mjs";
109
- import {
110
- collectFarmLlmsTxtPages,
111
- createFarmDefaultLlmsTxt,
112
- createFarmLlmsMarkdownReader,
113
- renderFarmLlmsFullTxt,
114
- resolveFarmLlmsTxtConfig
115
- } from "./chunk-LAZK6UV7.mjs";
99
+ } from "./chunk-T4TBK5NY.mjs";
116
100
  import {
117
101
  createFarmCspNonce,
118
102
  createFarmCspNonceRewriter,
@@ -122,37 +106,55 @@ import {
122
106
  stampFarmCspNonce
123
107
  } from "./chunk-22W4FNTG.mjs";
124
108
  import {
125
- resolveFarmImageConfig
126
- } from "./chunk-2NGZFOKG.mjs";
109
+ collectFarmLlmsTxtPages,
110
+ createFarmDefaultLlmsTxt,
111
+ createFarmLlmsMarkdownReader,
112
+ renderFarmLlmsFullTxt,
113
+ resolveFarmLlmsTxtConfig
114
+ } from "./chunk-KVW2M6PI.mjs";
127
115
  import {
128
116
  getFarmAppDirectories,
129
117
  getFarmSourceRoots
130
118
  } from "./chunk-52Y3C3HG.mjs";
119
+ import {
120
+ resolveFarmImageConfig
121
+ } from "./chunk-2NGZFOKG.mjs";
122
+ import {
123
+ createFarmMarkdownRouteModuleFromFile,
124
+ loadFarmMdxComponents
125
+ } from "./chunk-55U5QIXQ.mjs";
126
+ import {
127
+ isFarmMarkdownPageFile
128
+ } from "./chunk-E72UD6ME.mjs";
131
129
  import {
132
130
  resolveFarmMdxComponentsModulePath,
133
131
  resolveMdxConfig
134
132
  } from "./chunk-UIJOLBUL.mjs";
133
+ import {
134
+ FARM_MARKDOWN_CONTENT_TYPE,
135
+ FARM_MARKDOWN_PAGE_CHECK_HEADER,
136
+ _isFarmMarkdownPageCheck,
137
+ createFarmMarkdownErrorBody,
138
+ farmRequestWantsMarkdown,
139
+ getFarmMarkdownAlternatePath,
140
+ resolveMarkdownConfig
141
+ } from "./chunk-YSXTNSXS.mjs";
135
142
  import {
136
143
  resolveWorkflowsConfig
137
- } from "./chunk-LZ4SB57H.mjs";
144
+ } from "./chunk-JPIUGDK4.mjs";
138
145
  import {
139
146
  resolveCronConfig
140
- } from "./chunk-X3JNB2TB.mjs";
147
+ } from "./chunk-3PX4AIXO.mjs";
141
148
  import {
142
149
  resolveServerActionsConfig
143
150
  } from "./chunk-FSQMN2MQ.mjs";
151
+ import {
152
+ _setDefaultFarmThemeConfig,
153
+ getTheme
154
+ } from "./chunk-EMDGXYUD.mjs";
144
155
  import {
145
156
  resolveFarmThemeConfig
146
157
  } from "./chunk-YWPNIYUP.mjs";
147
- import {
148
- FARM_MARKDOWN_CONTENT_TYPE,
149
- FARM_MARKDOWN_PAGE_CHECK_HEADER,
150
- _isFarmMarkdownPageCheck,
151
- createFarmMarkdownErrorBody,
152
- farmRequestWantsMarkdown,
153
- getFarmMarkdownAlternatePath,
154
- resolveMarkdownConfig
155
- } from "./chunk-N77JBPLC.mjs";
156
158
  import {
157
159
  initStorage
158
160
  } from "./chunk-TJVUTGED.mjs";
@@ -164,11 +166,11 @@ import {
164
166
  getIntegrationProviders,
165
167
  getRegisteredIntegrationAPIManifest,
166
168
  isFarmIntegrationProviderComponentReference
167
- } from "./chunk-Y2G5SJFB.mjs";
169
+ } from "./chunk-IFHPDLIS.mjs";
168
170
  import {
169
171
  createRouteSlotContainerId,
170
172
  parseRouteSlotFile
171
- } from "./chunk-IRSS4HS4.mjs";
173
+ } from "./chunk-K3RU5MOR.mjs";
172
174
  import {
173
175
  _clearCurrentMiddlewareContext,
174
176
  _clearCurrentMiddlewareData,
@@ -230,7 +232,7 @@ import {
230
232
  splitRoutePath,
231
233
  toRootRelativeUrlPath,
232
234
  toViteModuleId
233
- } from "./chunk-Y3N5BFRJ.mjs";
235
+ } from "./chunk-JSDV2NUN.mjs";
234
236
  import {
235
237
  createFarmSearchParams,
236
238
  searchParamsToObject
@@ -242,6 +244,9 @@ import {
242
244
  import {
243
245
  sendWebResponse
244
246
  } from "./chunk-CO6UYM2D.mjs";
247
+ import {
248
+ resolveFarmAPIServerBasePath
249
+ } from "./chunk-2I6PUKWJ.mjs";
245
250
  import {
246
251
  matchesFarmIfNoneMatch,
247
252
  resolveFarmServerConfig
@@ -249,19 +254,16 @@ import {
249
254
  import {
250
255
  getRequestContextSnapshot
251
256
  } from "./chunk-D2LCAV6L.mjs";
252
- import {
253
- resolveFarmAPIServerBasePath
254
- } from "./chunk-LM2YOGDK.mjs";
255
257
  import {
256
258
  FARM_VERSION
257
- } from "./chunk-6CYQQQGR.mjs";
259
+ } from "./chunk-HPWB57PZ.mjs";
258
260
  import {
259
261
  resolveFarmTrailingSlashRedirect,
260
262
  setFarmTrailingSlashPreference
261
263
  } from "./chunk-RFKTJTWZ.mjs";
262
264
  import {
263
265
  normalizeFarmAPIConfig
264
- } from "./chunk-BLD5GVCG.mjs";
266
+ } from "./chunk-W6QLRQ3V.mjs";
265
267
  import {
266
268
  createFarmLocaleCookie,
267
269
  getFarmLocaleVaryHeaders
@@ -326,15 +328,240 @@ import {
326
328
  } from "./chunk-AYP2YFVN.mjs";
327
329
 
328
330
  // src/utils/client-component.ts
331
+ import fs2 from "fs";
332
+ import path2 from "path";
333
+ import { fileURLToPath } from "url";
334
+
335
+ // src/utils/package-client-boundary-cache.ts
336
+ import { AsyncLocalStorage } from "async_hooks";
329
337
  import fs from "fs";
330
338
  import path from "path";
331
- import { fileURLToPath } from "url";
339
+ var SCHEMA_VERSION = 1;
340
+ var NODE_MODULES_SEGMENT = `${path.sep}node_modules${path.sep}`;
341
+ var PackageInspectionTrace = class {
342
+ constructor() {
343
+ this.files = /* @__PURE__ */ new Set();
344
+ this.stops = /* @__PURE__ */ new Set();
345
+ this.fileStamps = [];
346
+ this.directoryStamps = /* @__PURE__ */ new Map();
347
+ }
348
+ visit(file) {
349
+ this.files.add(file);
350
+ const directory = path.dirname(file);
351
+ if (!this.directoryStamps.has(directory)) {
352
+ this.directoryStamps.set(directory, stampPackagePath(directory, "directory"));
353
+ }
354
+ this.fileStamps.push(stampPackagePath(file, "file"));
355
+ }
356
+ /** The inspection reached `file` after it was already visited. */
357
+ stop(file) {
358
+ if (!this.files.has(file)) this.stops.add(file);
359
+ }
360
+ toEntry(result) {
361
+ const entry = {
362
+ result: { ...result },
363
+ files: Array.from(this.files),
364
+ stops: Array.from(this.stops)
365
+ };
366
+ const files = this.fileStamps.filter((stamp) => stamp !== void 0);
367
+ const directories = Array.from(this.directoryStamps.values()).filter(
368
+ (stamp) => stamp !== void 0
369
+ );
370
+ if (files.length === this.fileStamps.length && directories.length === this.directoryStamps.size) {
371
+ entry.stamps = { files, directories };
372
+ }
373
+ return entry;
374
+ }
375
+ };
376
+ function stampPackagePath(target, kind) {
377
+ if (!`${target}${path.sep}`.includes(NODE_MODULES_SEGMENT)) return void 0;
378
+ try {
379
+ const stat = fs.statSync(target, { throwIfNoEntry: false });
380
+ if (!stat || (kind === "file" ? !stat.isFile() : !stat.isDirectory())) return void 0;
381
+ return [target, stat.size, stat.mtimeMs, stat.ctimeMs];
382
+ } catch {
383
+ return void 0;
384
+ }
385
+ }
386
+ var PackageClientBoundaryCache = class {
387
+ constructor() {
388
+ this.entries = /* @__PURE__ */ new Map();
389
+ this.stored = /* @__PURE__ */ new Map();
390
+ this.storedPaths = [];
391
+ this.unchangedPaths = /* @__PURE__ */ new Map();
392
+ this.dirty = false;
393
+ }
394
+ load(file) {
395
+ this.file = file;
396
+ const stored = readStoredCache(file);
397
+ if (!stored) {
398
+ this.dirty = true;
399
+ return;
400
+ }
401
+ this.storedPaths = stored.paths;
402
+ this.stored = new Map(Object.entries(stored.entries));
403
+ }
404
+ /** An inspection of `key` that applies to `visited`. */
405
+ find(key, visited) {
406
+ let entries = this.entries.get(key);
407
+ const stored = this.stored.get(key);
408
+ if (stored) {
409
+ this.stored.delete(key);
410
+ entries ?? (entries = []);
411
+ this.entries.set(key, entries);
412
+ for (const entry of stored) {
413
+ const restored = this.restore(entry);
414
+ if (restored) entries.push(restored);
415
+ else this.dirty = true;
416
+ }
417
+ }
418
+ return entries?.find(
419
+ (entry) => entry.stops.every((file) => visited.has(file)) && !entry.files.some((file) => visited.has(file))
420
+ );
421
+ }
422
+ add(key, entry) {
423
+ const entries = this.entries.get(key);
424
+ if (entries) entries.push(entry);
425
+ else this.entries.set(key, [entry]);
426
+ if (entry.stamps) this.dirty = true;
427
+ }
428
+ async persist() {
429
+ const file = this.file;
430
+ if (!file || !this.dirty && this.stored.size === 0) return;
431
+ const paths = [];
432
+ const pathIndexes = /* @__PURE__ */ new Map();
433
+ const indexOf = (stamp) => {
434
+ let index = pathIndexes.get(stamp[0]);
435
+ if (index === void 0) {
436
+ index = paths.push(stamp) - 1;
437
+ pathIndexes.set(stamp[0], index);
438
+ }
439
+ return index;
440
+ };
441
+ const entries = {};
442
+ for (const [key, variants] of this.entries) {
443
+ const persisted = variants.flatMap(
444
+ ({ result, stops, stamps }) => stamps ? [
445
+ {
446
+ result,
447
+ files: stamps.files.map(indexOf),
448
+ directories: stamps.directories.map(indexOf),
449
+ stops
450
+ }
451
+ ] : []
452
+ );
453
+ if (persisted.length > 0) entries[key] = persisted;
454
+ }
455
+ const contents = JSON.stringify({
456
+ schema: SCHEMA_VERSION,
457
+ farm: FARM_VERSION,
458
+ paths,
459
+ entries
460
+ });
461
+ const temporary = `${file}.${process.pid}.${Date.now()}.tmp`;
462
+ try {
463
+ await fs.promises.mkdir(path.dirname(file), { recursive: true });
464
+ await fs.promises.writeFile(temporary, contents);
465
+ await fs.promises.rename(temporary, file);
466
+ } catch {
467
+ await fs.promises.rm(temporary, { force: true }).catch(() => {
468
+ });
469
+ }
470
+ }
471
+ restore(entry) {
472
+ const files = this.restoreStamps(entry.files, "file");
473
+ const directories = this.restoreStamps(entry.directories, "directory");
474
+ if (!files || !directories) return void 0;
475
+ return {
476
+ result: entry.result,
477
+ files: files.map(([file]) => file),
478
+ stops: entry.stops,
479
+ stamps: { files, directories }
480
+ };
481
+ }
482
+ restoreStamps(indexes, kind) {
483
+ const stamps = [];
484
+ for (const index of indexes) {
485
+ const stamp = this.storedPaths[index];
486
+ let unchanged = this.unchangedPaths.get(index);
487
+ if (unchanged === void 0) {
488
+ const current = stampPackagePath(stamp[0], kind);
489
+ unchanged = current !== void 0 && current[1] === stamp[1] && current[2] === stamp[2] && current[3] === stamp[3];
490
+ this.unchangedPaths.set(index, unchanged);
491
+ }
492
+ if (!unchanged) return void 0;
493
+ stamps.push(stamp);
494
+ }
495
+ return stamps;
496
+ }
497
+ };
498
+ function readStoredCache(file) {
499
+ let value;
500
+ try {
501
+ value = JSON.parse(fs.readFileSync(file, "utf8"));
502
+ } catch {
503
+ return null;
504
+ }
505
+ if (!isRecord(value) || value.schema !== SCHEMA_VERSION || value.farm !== FARM_VERSION) {
506
+ return null;
507
+ }
508
+ const { paths, entries } = value;
509
+ if (!Array.isArray(paths) || !paths.every(isPathStamp) || !isRecord(entries)) return null;
510
+ const valid = {};
511
+ for (const [key, variants] of Object.entries(entries)) {
512
+ if (!Array.isArray(variants)) continue;
513
+ const usable = variants.filter((entry) => isStoredEntry(entry, paths.length));
514
+ if (usable.length > 0) valid[key] = usable;
515
+ }
516
+ return { schema: SCHEMA_VERSION, farm: FARM_VERSION, paths, entries: valid };
517
+ }
518
+ function isRecord(value) {
519
+ return typeof value === "object" && value !== null && !Array.isArray(value);
520
+ }
521
+ function isPathStamp(value) {
522
+ return Array.isArray(value) && value.length === 4 && typeof value[0] === "string" && path.isAbsolute(value[0]) && value.slice(1).every((part) => typeof part === "number" && Number.isFinite(part));
523
+ }
524
+ function isPathIndexList(value, pathCount) {
525
+ return Array.isArray(value) && value.length > 0 && value.every((index) => Number.isSafeInteger(index) && index >= 0 && index < pathCount);
526
+ }
527
+ function isStoredEntry(value, pathCount) {
528
+ if (!isRecord(value) || !isRecord(value.result)) return false;
529
+ const { isClientComponent, shouldHydrate, islandStrategy } = value.result;
530
+ return isPathIndexList(value.files, pathCount) && isPathIndexList(value.directories, pathCount) && Array.isArray(value.stops) && value.stops.every((file) => typeof file === "string" && path.isAbsolute(file)) && typeof isClientComponent === "boolean" && typeof shouldHydrate === "boolean" && (islandStrategy === null || isFarmIslandStrategy(islandStrategy)) && Object.keys(value.result).length === 3;
531
+ }
532
+ var STORAGE_KEY = /* @__PURE__ */ Symbol.for("@farm.js/core/package-client-boundary-cache");
533
+ function getStorage() {
534
+ const runtime = globalThis;
535
+ const existing = runtime[STORAGE_KEY];
536
+ if (existing instanceof AsyncLocalStorage) {
537
+ return existing;
538
+ }
539
+ const storage = new AsyncLocalStorage();
540
+ runtime[STORAGE_KEY] = storage;
541
+ return storage;
542
+ }
543
+ function getPackageClientBoundaryCache() {
544
+ return getStorage().getStore();
545
+ }
546
+ async function withPackageClientBoundaryCache(operation) {
547
+ const cache2 = new PackageClientBoundaryCache();
548
+ try {
549
+ return await getStorage().run(cache2, operation);
550
+ } finally {
551
+ await cache2.persist();
552
+ }
553
+ }
554
+ function usePackageClientBoundaryCacheFile(file) {
555
+ getPackageClientBoundaryCache()?.load(file);
556
+ }
557
+
558
+ // src/utils/client-component.ts
332
559
  function readIfExists(filePath) {
333
560
  try {
334
- if (!filePath || !fs.existsSync(filePath)) {
561
+ if (!filePath || !fs2.existsSync(filePath)) {
335
562
  return null;
336
563
  }
337
- return fs.readFileSync(filePath, "utf-8");
564
+ return fs2.readFileSync(filePath, "utf-8");
338
565
  } catch {
339
566
  return null;
340
567
  }
@@ -353,21 +580,21 @@ function resolveModuleSourcePath(modulePath, root) {
353
580
  }
354
581
  if (modulePath.startsWith("/@fs/")) {
355
582
  const fsPath = withoutQuery.slice("/@fs/".length);
356
- candidates.add(path.normalize(/^[A-Za-z]:/.test(fsPath) ? fsPath : `/${fsPath}`));
583
+ candidates.add(path2.normalize(/^[A-Za-z]:/.test(fsPath) ? fsPath : `/${fsPath}`));
357
584
  }
358
585
  }
359
586
  if (root && modulePath) {
360
587
  const normalized = withoutQuery.replace(/^\/+/, "");
361
- candidates.add(path.join(root, normalized));
362
- candidates.add(path.resolve(root, normalized));
588
+ candidates.add(path2.join(root, normalized));
589
+ candidates.add(path2.resolve(root, normalized));
363
590
  }
364
591
  if (withoutQuery?.startsWith("/src/")) {
365
592
  const normalized = withoutQuery.replace(/^\/+/, "");
366
- candidates.add(path.join(process.cwd(), normalized));
367
- candidates.add(path.resolve(process.cwd(), normalized));
593
+ candidates.add(path2.join(process.cwd(), normalized));
594
+ candidates.add(path2.resolve(process.cwd(), normalized));
368
595
  }
369
596
  for (const candidate of candidates) {
370
- if (fs.existsSync(candidate)) {
597
+ if (fs2.existsSync(candidate)) {
371
598
  return candidate;
372
599
  }
373
600
  }
@@ -384,8 +611,8 @@ var FARM_ISOLATED_HYDRATION_MAX_BOUNDARIES = 4;
384
611
  function isolatedHydrationBoundaryLimit() {
385
612
  const benchmarkRoot = process.env.FARM_INTERNAL_ISOLATED_HYDRATION_BENCHMARK_ROOT;
386
613
  const benchmarkLimit = Number(process.env.FARM_INTERNAL_ISOLATED_HYDRATION_BENCHMARK_LIMIT);
387
- const resolvedBenchmarkRoot = benchmarkRoot ? path.resolve(benchmarkRoot) : null;
388
- const isBenchmarkFixture = process.env.FARM_INTERNAL_BENCHMARK === "isolated-hydration" && resolvedBenchmarkRoot !== null && (process.cwd() === resolvedBenchmarkRoot || process.cwd().startsWith(`${resolvedBenchmarkRoot}${path.sep}`));
614
+ const resolvedBenchmarkRoot = benchmarkRoot ? path2.resolve(benchmarkRoot) : null;
615
+ const isBenchmarkFixture = process.env.FARM_INTERNAL_BENCHMARK === "isolated-hydration" && resolvedBenchmarkRoot !== null && (process.cwd() === resolvedBenchmarkRoot || process.cwd().startsWith(`${resolvedBenchmarkRoot}${path2.sep}`));
389
616
  return isBenchmarkFixture && Number.isSafeInteger(benchmarkLimit) && benchmarkLimit > FARM_ISOLATED_HYDRATION_MAX_BOUNDARIES ? benchmarkLimit : FARM_ISOLATED_HYDRATION_MAX_BOUNDARIES;
390
617
  }
391
618
  var RESOLVABLE_SOURCE_EXTENSIONS = [
@@ -707,6 +934,41 @@ function resolveOwnerSourcePath(resolvedPath, root) {
707
934
  }
708
935
  return current;
709
936
  }
937
+ function collectFarmRenderedClientModules(modulePath, root) {
938
+ const resolvedPath = resolveOwnerSourcePath(resolveModuleSourcePath(modulePath, root), root);
939
+ if (!resolvedPath) return null;
940
+ if (hasUseClientDirective(readIfExists(resolvedPath))) return [resolvedPath];
941
+ const collected = collectIsolatedClientBoundaries(resolvedPath, root, {
942
+ allowDynamicCardinality: true,
943
+ allowElementProps: true
944
+ });
945
+ if (collected.fallbackReason || collected.costGuardExceeded) return null;
946
+ return collected.boundaries.map((boundary) => boundary.modulePath);
947
+ }
948
+ var SERVER_MODULE_SOURCE = /\.[cm]?[jt]sx?$/;
949
+ var STYLESHEET_SOURCE = /\.(?:css|scss|sass|less|styl|stylus|pcss|postcss)$/;
950
+ function collectFarmServerStylesheets(modulePaths, root) {
951
+ const stylesheets = /* @__PURE__ */ new Set();
952
+ const visited = /* @__PURE__ */ new Set();
953
+ const visit = (file) => {
954
+ if (visited.has(file) || !SERVER_MODULE_SOURCE.test(file)) return;
955
+ visited.add(file);
956
+ const content = readIfExists(file);
957
+ if (!content || hasUseClientDirective(content)) return;
958
+ for (const specifier of getImportSpecifiers(content)) {
959
+ if (specifier.includes("?")) continue;
960
+ const imported = resolveImportedModule(file, specifier, root);
961
+ if (!imported.path) continue;
962
+ if (STYLESHEET_SOURCE.test(imported.path)) stylesheets.add(imported.path);
963
+ else if (imported.local) visit(imported.path);
964
+ }
965
+ };
966
+ for (const modulePath of modulePaths) {
967
+ const resolved = resolveOwnerSourcePath(resolveModuleSourcePath(modulePath, root), root);
968
+ if (resolved) visit(resolved);
969
+ }
970
+ return [...stylesheets];
971
+ }
710
972
  function getClientModuleMetadata(modulePath, root) {
711
973
  const resolvedPath = resolveModuleSourcePath(modulePath, root);
712
974
  return inspectClientModuleMetadata(resolvedPath, root, /* @__PURE__ */ new Set(), true);
@@ -721,7 +983,8 @@ function getClientModuleHydrationPlan(modulePath, root, mode = "off", options =
721
983
  if (!resolvedPath || owner.isClientComponent || owner.hasHydrateExport) return plan;
722
984
  const layout = collectIsolatedClientBoundaries(resolvedPath, root, {
723
985
  allowDynamicCardinality: true,
724
- allowElementProps: true
986
+ allowElementProps: true,
987
+ staticPackageLeaves: true
725
988
  });
726
989
  const routeWide = {
727
990
  ...plan,
@@ -739,7 +1002,16 @@ function getClientModuleHydrationPlan(modulePath, root, mode = "off", options =
739
1002
  islandsError: layout.fallbackHint ? `${layout.fallbackReason}. ${layout.fallbackHint}` : layout.fallbackReason
740
1003
  };
741
1004
  }
742
- return { ...routeWide, serverTreeLayout: true, isolatedBoundaries: layout.boundaries };
1005
+ const staticPackages = layout.staticPackages.length > 0 ? { staticPackageBoundaries: layout.staticPackages } : {};
1006
+ if (layout.boundaries.length === 0) {
1007
+ return { ...routeWide, shouldHydrate: false, islandStrategy: null, ...staticPackages };
1008
+ }
1009
+ return {
1010
+ ...routeWide,
1011
+ serverTreeLayout: true,
1012
+ isolatedBoundaries: layout.boundaries,
1013
+ ...staticPackages
1014
+ };
743
1015
  }
744
1016
  function planClientModuleHydration(modulePath, root, mode, options) {
745
1017
  const metadata = getClientModuleMetadata(modulePath, root);
@@ -770,7 +1042,8 @@ function planClientModuleHydration(modulePath, root, mode, options) {
770
1042
  const inspection = collectIsolatedClientBoundaries(resolvedPath, root, {
771
1043
  allowDynamicCardinality: asyncOwner,
772
1044
  allowElementProps: asyncOwner,
773
- staticPackageBoundaries: asyncOwner
1045
+ staticPackageBoundaries: asyncOwner,
1046
+ staticPackageLeaves: options.serverTreeLayouts === true && options.asyncOwnerIslands === true
774
1047
  });
775
1048
  if (inspection.fallbackReason && asyncOwner && options.serverOwners === true) {
776
1049
  return {
@@ -814,9 +1087,9 @@ function planClientModuleHydration(modulePath, root, mode, options) {
814
1087
  if (asyncOwner) {
815
1088
  delete plan.suppressedAsyncHydration;
816
1089
  plan.asyncOwnerIslands = true;
817
- if (inspection.staticPackages.length > 0)
818
- plan.staticPackageBoundaries = inspection.staticPackages;
819
1090
  }
1091
+ if (inspection.staticPackages.length > 0)
1092
+ plan.staticPackageBoundaries = inspection.staticPackages;
820
1093
  return plan;
821
1094
  }
822
1095
  function usesFarmServerTree(plan) {
@@ -879,10 +1152,10 @@ function restoreRouteWideHydration(metadata, fallbackReason) {
879
1152
  metadata.fallbackReason = fallbackReason;
880
1153
  }
881
1154
  }
882
- function enforceFarmIsolatedHydrationRouteBudget(layouts, routes, layoutAppliesToRoute) {
1155
+ function enforceFarmIsolatedHydrationRouteBudget(layouts, routes, layoutAppliesToRoute, options = {}) {
883
1156
  const boundaryLimit = isolatedHydrationBoundaryLimit();
884
1157
  const sortedLayouts = [...layouts].sort((left, right) => left.depth - right.depth);
885
- for (const route of routes) {
1158
+ for (const route of options.serverOwners ? [] : routes) {
886
1159
  if (route.metadata.mode !== "enabled") continue;
887
1160
  const applicableLayouts = sortedLayouts.filter(
888
1161
  (layout) => layoutAppliesToRoute(layout.pattern, route.pattern)
@@ -1189,6 +1462,25 @@ function passesElementValuedProps(content, localBindings) {
1189
1462
  }
1190
1463
  return false;
1191
1464
  }
1465
+ function rendersOnlyLeafElements(content, localBindings) {
1466
+ if (!content) return false;
1467
+ const names = new Set(localBindings);
1468
+ const tokens = tokenizeModuleSource(content);
1469
+ for (let index = 0; index < tokens.length - 1; index++) {
1470
+ if (tokens[index].value !== "<" || !names.has(tokens[index + 1].value)) continue;
1471
+ let braceDepth = 0;
1472
+ let cursor = index + 2;
1473
+ for (; cursor < tokens.length; cursor++) {
1474
+ const value = tokens[cursor].value;
1475
+ if (value === "{") braceDepth++;
1476
+ else if (value === "}") braceDepth--;
1477
+ else if (value === "<" && braceDepth > 0) return false;
1478
+ else if (value === ">" && braceDepth === 0) break;
1479
+ }
1480
+ if (cursor >= tokens.length || tokens[cursor - 1]?.value !== "/") return false;
1481
+ }
1482
+ return true;
1483
+ }
1192
1484
  function hasDynamicJsxCardinality(content, localBindings) {
1193
1485
  if (!content || localBindings.length === 0) return false;
1194
1486
  const clientBindings = new Set(localBindings);
@@ -1225,7 +1517,7 @@ function collectIsolatedClientBoundaries(ownerPath, root, options = {}) {
1225
1517
  let fallbackReason;
1226
1518
  let fallbackHint;
1227
1519
  let costGuardExceeded = false;
1228
- const projectRoot = root ? path.resolve(root) : void 0;
1520
+ const projectRoot = root ? path2.resolve(root) : void 0;
1229
1521
  const visit = (moduleSourcePath) => {
1230
1522
  if (fallbackReason) return 0;
1231
1523
  const cached = estimates.get(moduleSourcePath);
@@ -1235,7 +1527,7 @@ function collectIsolatedClientBoundaries(ownerPath, root, options = {}) {
1235
1527
  const content = readIfExists(moduleSourcePath);
1236
1528
  const parsed = parseClientModuleMetadata(content, false);
1237
1529
  if (parsed.isClientComponent) {
1238
- if (projectRoot && !path.resolve(moduleSourcePath).startsWith(`${projectRoot}${path.sep}`)) {
1530
+ if (projectRoot && !path2.resolve(moduleSourcePath).startsWith(`${projectRoot}${path2.sep}`)) {
1239
1531
  fallbackReason = `client boundary ${moduleSourcePath} is outside the application root`;
1240
1532
  fallbackHint = "Move the component into the application, or publish it as a package (package client components render as static HTML)";
1241
1533
  return 0;
@@ -1267,7 +1559,7 @@ function collectIsolatedClientBoundaries(ownerPath, root, options = {}) {
1267
1559
  if (!imported.local) {
1268
1560
  const packageMetadata = inspectPackageClientBoundary(importedPath, root, /* @__PURE__ */ new Set());
1269
1561
  if (packageMetadata.shouldHydrate) {
1270
- if (options.staticPackageBoundaries) {
1562
+ if (options.staticPackageBoundaries || options.staticPackageLeaves && rendersOnlyLeafElements(content, importedBindings.get(specifier) ?? [])) {
1271
1563
  staticPackages.add(specifier);
1272
1564
  continue;
1273
1565
  }
@@ -1368,7 +1660,24 @@ function inspectClientModuleMetadata(resolvedPath, root, visited, inspectIslandE
1368
1660
  };
1369
1661
  }
1370
1662
  function inspectPackageClientBoundary(resolvedPath, root, visited) {
1663
+ const cache2 = getPackageClientBoundaryCache();
1664
+ if (!cache2 || !resolvedPath || visited.has(resolvedPath)) {
1665
+ return traversePackageClientBoundary(resolvedPath, root, visited);
1666
+ }
1667
+ const key = `${root ?? ""}\0${resolvedPath}`;
1668
+ const cached = cache2.find(key, visited);
1669
+ if (cached) {
1670
+ for (const file of cached.files) visited.add(file);
1671
+ return { ...cached.result };
1672
+ }
1673
+ const trace = new PackageInspectionTrace();
1674
+ const result = traversePackageClientBoundary(resolvedPath, root, visited, trace);
1675
+ cache2.add(key, trace.toEntry(result));
1676
+ return result;
1677
+ }
1678
+ function traversePackageClientBoundary(resolvedPath, root, visited, trace) {
1371
1679
  if (!resolvedPath || visited.has(resolvedPath)) {
1680
+ if (resolvedPath) trace?.stop(resolvedPath);
1372
1681
  return {
1373
1682
  isClientComponent: false,
1374
1683
  shouldHydrate: false,
@@ -1376,6 +1685,7 @@ function inspectPackageClientBoundary(resolvedPath, root, visited) {
1376
1685
  };
1377
1686
  }
1378
1687
  visited.add(resolvedPath);
1688
+ trace?.visit(resolvedPath);
1379
1689
  const content = readIfExists(resolvedPath);
1380
1690
  const parsed = parseClientModuleMetadata(content, false);
1381
1691
  let importsClientBoundary = false;
@@ -1383,7 +1693,7 @@ function inspectPackageClientBoundary(resolvedPath, root, visited) {
1383
1693
  for (const specifier of getImportSpecifiers(content)) {
1384
1694
  if (!specifier.startsWith(".") && !specifier.startsWith("/")) continue;
1385
1695
  const importedPath = resolveImportedModuleSourcePath(resolvedPath, specifier, root);
1386
- const importedMetadata = inspectPackageClientBoundary(importedPath, root, visited);
1696
+ const importedMetadata = traversePackageClientBoundary(importedPath, root, visited, trace);
1387
1697
  if (!importedMetadata.shouldHydrate) continue;
1388
1698
  importsClientBoundary = true;
1389
1699
  if (importedIslandStrategy === null) {
@@ -1482,7 +1792,7 @@ var ALIAS_IMPORT = /^(?:@\/|~\/|#)/;
1482
1792
  function warnUnresolvedAliasImport(importerPath, specifier, root) {
1483
1793
  if (!ALIAS_IMPORT.test(specifier) || warnedUnresolvedAliasImports.has(specifier)) return;
1484
1794
  warnedUnresolvedAliasImports.add(specifier);
1485
- const importer = root ? path.relative(root, importerPath) : importerPath;
1795
+ const importer = root ? path2.relative(root, importerPath) : importerPath;
1486
1796
  logger.warn(
1487
1797
  `Could not resolve "${specifier}" (imported by ${importer}) while checking which pages need client JavaScript. If it holds client components, they will not hydrate. Map the alias in tsconfig.json "paths" or package.json "imports".`
1488
1798
  );
@@ -1491,7 +1801,7 @@ var projectImportAliasCache = /* @__PURE__ */ new Map();
1491
1801
  var PROJECT_ALIAS_FILES = ["tsconfig.json", "jsconfig.json", "package.json"];
1492
1802
  function resolveProjectAliasSourcePath(specifier, root) {
1493
1803
  if (!root) return void 0;
1494
- const projectRoot = path.resolve(root);
1804
+ const projectRoot = path2.resolve(root);
1495
1805
  let match;
1496
1806
  for (const alias of getProjectImportAliases(projectRoot)) {
1497
1807
  const captured = matchProjectImportAlias(alias, specifier);
@@ -1501,7 +1811,7 @@ function resolveProjectAliasSourcePath(specifier, root) {
1501
1811
  if (!match) return void 0;
1502
1812
  const resolved = resolveSourceCandidate(
1503
1813
  match.alias.targets.map(
1504
- (target) => path.normalize(match.alias.wildcard ? target.replace("*", match.captured) : target)
1814
+ (target) => path2.normalize(match.alias.wildcard ? target.replace("*", match.captured) : target)
1505
1815
  )
1506
1816
  );
1507
1817
  return resolved && /\.d\.[cm]?ts$/.test(resolved) ? null : resolved;
@@ -1516,7 +1826,7 @@ function matchProjectImportAlias(alias, specifier) {
1516
1826
  function getProjectImportAliases(projectRoot) {
1517
1827
  const stamp = PROJECT_ALIAS_FILES.map((file) => {
1518
1828
  try {
1519
- return String(fs.statSync(path.join(projectRoot, file)).mtimeMs);
1829
+ return String(fs2.statSync(path2.join(projectRoot, file)).mtimeMs);
1520
1830
  } catch {
1521
1831
  return "-";
1522
1832
  }
@@ -1534,7 +1844,7 @@ function getProjectImportAliases(projectRoot) {
1534
1844
  prefix: "@/",
1535
1845
  suffix: "",
1536
1846
  wildcard: true,
1537
- targets: [path.join(projectRoot, sourceDir, "*")]
1847
+ targets: [path2.join(projectRoot, sourceDir, "*")]
1538
1848
  });
1539
1849
  }
1540
1850
  projectImportAliasCache.set(projectRoot, { stamp: cacheStamp, aliases });
@@ -1542,8 +1852,8 @@ function getProjectImportAliases(projectRoot) {
1542
1852
  }
1543
1853
  function readTsconfigPathAliases(projectRoot) {
1544
1854
  for (const name of ["tsconfig.json", "jsconfig.json"]) {
1545
- const configPath = path.join(projectRoot, name);
1546
- if (!fs.existsSync(configPath)) continue;
1855
+ const configPath = path2.join(projectRoot, name);
1856
+ if (!fs2.existsSync(configPath)) continue;
1547
1857
  const resolved = readTsconfigPaths(configPath, /* @__PURE__ */ new Set());
1548
1858
  if (!resolved?.paths) return [];
1549
1859
  const base = resolved.baseUrl ?? resolved.pathsDirectory;
@@ -1555,7 +1865,7 @@ function readTsconfigPathAliases(projectRoot) {
1555
1865
  prefix: wildcardIndex === -1 ? pattern : pattern.slice(0, wildcardIndex),
1556
1866
  suffix: wildcardIndex === -1 ? "" : pattern.slice(wildcardIndex + 1),
1557
1867
  wildcard: wildcardIndex !== -1,
1558
- targets: targets.filter((target) => typeof target === "string").map((target) => path.resolve(base, target))
1868
+ targets: targets.filter((target) => typeof target === "string").map((target) => path2.resolve(base, target))
1559
1869
  }
1560
1870
  ];
1561
1871
  });
@@ -1567,27 +1877,27 @@ function readTsconfigPaths(configPath, visited) {
1567
1877
  visited.add(configPath);
1568
1878
  const config = readJsonWithComments(configPath);
1569
1879
  if (!config) return null;
1570
- const directory = path.dirname(configPath);
1880
+ const directory = path2.dirname(configPath);
1571
1881
  const parents = (Array.isArray(config.extends) ? config.extends : [config.extends]).filter(
1572
1882
  (parent) => typeof parent === "string" && parent.startsWith(".")
1573
1883
  );
1574
1884
  let inherited = null;
1575
1885
  for (const parent of parents) {
1576
- const parentPath = path.resolve(
1886
+ const parentPath = path2.resolve(
1577
1887
  directory,
1578
1888
  parent.endsWith(".json") ? parent : `${parent}.json`
1579
1889
  );
1580
1890
  inherited = readTsconfigPaths(parentPath, visited) ?? inherited;
1581
1891
  }
1582
1892
  const options = config.compilerOptions ?? {};
1583
- const baseUrl = typeof options.baseUrl === "string" ? path.resolve(directory, options.baseUrl) : inherited?.baseUrl;
1893
+ const baseUrl = typeof options.baseUrl === "string" ? path2.resolve(directory, options.baseUrl) : inherited?.baseUrl;
1584
1894
  if (options.paths && typeof options.paths === "object") {
1585
1895
  return { paths: options.paths, pathsDirectory: directory, baseUrl };
1586
1896
  }
1587
1897
  return inherited ? { ...inherited, baseUrl } : { pathsDirectory: directory, baseUrl };
1588
1898
  }
1589
1899
  function readPackageImportAliases(projectRoot) {
1590
- const imports = readPackageJson(path.join(projectRoot, "package.json"))?.imports;
1900
+ const imports = readPackageJson(path2.join(projectRoot, "package.json"))?.imports;
1591
1901
  if (!imports || typeof imports !== "object") return [];
1592
1902
  return Object.entries(imports).flatMap(([pattern, value]) => {
1593
1903
  const target = resolveConditionalExportTarget(value);
@@ -1598,7 +1908,7 @@ function readPackageImportAliases(projectRoot) {
1598
1908
  prefix: wildcardIndex === -1 ? pattern : pattern.slice(0, wildcardIndex),
1599
1909
  suffix: wildcardIndex === -1 ? "" : pattern.slice(wildcardIndex + 1),
1600
1910
  wildcard: wildcardIndex !== -1,
1601
- targets: [path.resolve(projectRoot, target)]
1911
+ targets: [path2.resolve(projectRoot, target)]
1602
1912
  }
1603
1913
  ];
1604
1914
  });
@@ -1606,7 +1916,7 @@ function readPackageImportAliases(projectRoot) {
1606
1916
  function readJsonWithComments(filePath) {
1607
1917
  let source;
1608
1918
  try {
1609
- source = fs.readFileSync(filePath, "utf8");
1919
+ source = fs2.readFileSync(filePath, "utf8");
1610
1920
  } catch {
1611
1921
  return null;
1612
1922
  }
@@ -1644,7 +1954,7 @@ function resolveImportedModuleSourcePath(importerPath, specifier, root) {
1644
1954
  return resolvePackageModuleSourcePath(importerPath, specifier, root);
1645
1955
  }
1646
1956
  const candidates = /* @__PURE__ */ new Set();
1647
- const basePath = specifier.startsWith(".") ? path.resolve(path.dirname(importerPath), specifier) : root ? path.resolve(root, specifier.replace(/^\/+/, "")) : path.resolve(specifier);
1957
+ const basePath = specifier.startsWith(".") ? path2.resolve(path2.dirname(importerPath), specifier) : root ? path2.resolve(root, specifier.replace(/^\/+/, "")) : path2.resolve(specifier);
1648
1958
  candidates.add(basePath);
1649
1959
  return resolveSourceCandidate(candidates);
1650
1960
  }
@@ -1654,45 +1964,45 @@ function resolvePackageModuleSourcePath(importerPath, specifier, root) {
1654
1964
  const packageSubpath = packageParts.slice(packageName.startsWith("@") ? 2 : 1).join("/");
1655
1965
  const packageDirectory = findPackageDirectory(importerPath, packageName, root);
1656
1966
  if (!packageDirectory) return null;
1657
- const packageJsonPath = path.join(packageDirectory, "package.json");
1967
+ const packageJsonPath = path2.join(packageDirectory, "package.json");
1658
1968
  const packageJson = readPackageJson(packageJsonPath);
1659
1969
  const exportKey = packageSubpath ? `./${packageSubpath}` : ".";
1660
1970
  const exportTarget = resolvePackageExport(packageJson?.exports, exportKey);
1661
1971
  const candidates = /* @__PURE__ */ new Set();
1662
1972
  if (exportTarget?.startsWith("./")) {
1663
- candidates.add(path.resolve(packageDirectory, exportTarget));
1973
+ candidates.add(path2.resolve(packageDirectory, exportTarget));
1664
1974
  }
1665
1975
  if (packageSubpath) {
1666
- candidates.add(path.join(packageDirectory, packageSubpath));
1976
+ candidates.add(path2.join(packageDirectory, packageSubpath));
1667
1977
  } else {
1668
1978
  for (const entry of [packageJson?.browser, packageJson?.module, packageJson?.main]) {
1669
- if (typeof entry === "string") candidates.add(path.resolve(packageDirectory, entry));
1979
+ if (typeof entry === "string") candidates.add(path2.resolve(packageDirectory, entry));
1670
1980
  }
1671
- candidates.add(path.join(packageDirectory, "index"));
1981
+ candidates.add(path2.join(packageDirectory, "index"));
1672
1982
  }
1673
1983
  return resolveSourceCandidate(candidates);
1674
1984
  }
1675
1985
  function findPackageDirectory(importerPath, packageName, root) {
1676
1986
  const searchRoots = /* @__PURE__ */ new Set();
1677
- let current = path.dirname(importerPath);
1987
+ let current = path2.dirname(importerPath);
1678
1988
  while (true) {
1679
1989
  searchRoots.add(current);
1680
- const parent = path.dirname(current);
1990
+ const parent = path2.dirname(current);
1681
1991
  if (parent === current) break;
1682
1992
  current = parent;
1683
1993
  }
1684
1994
  if (root) {
1685
- current = path.resolve(root);
1995
+ current = path2.resolve(root);
1686
1996
  while (true) {
1687
1997
  searchRoots.add(current);
1688
- const parent = path.dirname(current);
1998
+ const parent = path2.dirname(current);
1689
1999
  if (parent === current) break;
1690
2000
  current = parent;
1691
2001
  }
1692
2002
  }
1693
2003
  for (const searchRoot of searchRoots) {
1694
- const packageDirectory = path.join(searchRoot, "node_modules", packageName);
1695
- if (fs.existsSync(path.join(packageDirectory, "package.json"))) {
2004
+ const packageDirectory = path2.join(searchRoot, "node_modules", packageName);
2005
+ if (fs2.existsSync(path2.join(packageDirectory, "package.json"))) {
1696
2006
  return packageDirectory;
1697
2007
  }
1698
2008
  }
@@ -1700,7 +2010,7 @@ function findPackageDirectory(importerPath, packageName, root) {
1700
2010
  }
1701
2011
  function readPackageJson(packageJsonPath) {
1702
2012
  try {
1703
- return JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
2013
+ return JSON.parse(fs2.readFileSync(packageJsonPath, "utf8"));
1704
2014
  } catch {
1705
2015
  return null;
1706
2016
  }
@@ -1758,11 +2068,11 @@ function resolveSourceCandidate(candidates) {
1758
2068
  for (const candidate of candidates) {
1759
2069
  const paths = [candidate];
1760
2070
  for (const extension of RESOLVABLE_SOURCE_EXTENSIONS) {
1761
- paths.push(`${candidate}${extension}`, path.join(candidate, `index${extension}`));
2071
+ paths.push(`${candidate}${extension}`, path2.join(candidate, `index${extension}`));
1762
2072
  }
1763
2073
  for (const sourcePath of paths) {
1764
2074
  try {
1765
- if (fs.statSync(sourcePath).isFile()) return sourcePath;
2075
+ if (fs2.statSync(sourcePath).isFile()) return sourcePath;
1766
2076
  } catch {
1767
2077
  }
1768
2078
  }
@@ -1772,12 +2082,12 @@ function resolveSourceCandidate(candidates) {
1772
2082
 
1773
2083
  // src/routing/route-manager.ts
1774
2084
  import { realpathSync } from "fs";
1775
- import path3 from "path";
2085
+ import path4 from "path";
1776
2086
 
1777
2087
  // src/static-metadata-image.ts
1778
2088
  import { createHash } from "crypto";
1779
2089
  import { readFile } from "fs/promises";
1780
- import path2 from "path";
2090
+ import path3 from "path";
1781
2091
  import { imageSize } from "image-size";
1782
2092
  var STATIC_METADATA_IMAGE_EXTENSIONS = ["png", "jpg", "jpeg", "gif", "webp"];
1783
2093
  var CONTENT_TYPES = {
@@ -1818,13 +2128,13 @@ async function inspectStaticMetadataImage(filePath) {
1818
2128
  };
1819
2129
  }
1820
2130
  function getStaticMetadataImageAltPath(filePath) {
1821
- return path2.join(
1822
- path2.dirname(filePath),
1823
- `${path2.basename(filePath, path2.extname(filePath))}.alt.txt`
2131
+ return path3.join(
2132
+ path3.dirname(filePath),
2133
+ `${path3.basename(filePath, path3.extname(filePath))}.alt.txt`
1824
2134
  );
1825
2135
  }
1826
2136
  function getStaticMetadataImageExtension(filePath) {
1827
- const extension = path2.extname(filePath).slice(1).toLowerCase();
2137
+ const extension = path3.extname(filePath).slice(1).toLowerCase();
1828
2138
  return STATIC_METADATA_IMAGE_EXTENSIONS.includes(extension) ? extension : null;
1829
2139
  }
1830
2140
  async function readAltText(filePath) {
@@ -2152,14 +2462,14 @@ var RouteManager = class {
2152
2462
  * Requests still fetch route data, but never inspect component source.
2153
2463
  */
2154
2464
  generateClientManifest(projectRoot = this.config.root) {
2155
- const normalizedProjectRoot = path3.resolve(projectRoot);
2465
+ const normalizedProjectRoot = path4.resolve(projectRoot);
2156
2466
  if (this.clientManifestCache?.projectRoot === normalizedProjectRoot) {
2157
2467
  return this.clientManifestCache.manifest;
2158
2468
  }
2159
2469
  const toUrlPath = (absolutePath) => {
2160
2470
  const rootRelative = toRootRelativeUrlPath(absolutePath, normalizedProjectRoot);
2161
2471
  if (rootRelative !== void 0) return rootRelative;
2162
- if (path3.isAbsolute(absolutePath)) {
2472
+ if (path4.isAbsolute(absolutePath)) {
2163
2473
  const normalized = absolutePath.replace(/\\/g, "/");
2164
2474
  return normalized.startsWith("/") ? `/@fs${normalized}` : `/@fs/${normalized}`;
2165
2475
  }
@@ -2229,7 +2539,7 @@ var RouteManager = class {
2229
2539
  for (const { entry, metadata } of [...layoutEntries, ...routeEntries]) {
2230
2540
  if (isFarmMarkdownPageFile(entry.modulePath) || !metadata.staticPackageBoundaries) continue;
2231
2541
  logger.info(
2232
- `[Farm.js] ${entry.pattern} is async, so it renders client components from ${metadata.staticPackageBoundaries.join(", ")} as static HTML: package client components cannot be isolated yet.`
2542
+ `[Farm.js] ${entry.pattern} renders client components from ${metadata.staticPackageBoundaries.join(", ")} as static HTML: package client components cannot be isolated yet.`
2233
2543
  );
2234
2544
  }
2235
2545
  enforceFarmIsolatedHydrationRouteBudget(
@@ -2243,7 +2553,8 @@ var RouteManager = class {
2243
2553
  depth: getRouteDirectoryDepth(getRouteEntryDirectory(entry)),
2244
2554
  metadata
2245
2555
  })),
2246
- routeBoundaryCoversDirectory
2556
+ routeBoundaryCoversDirectory,
2557
+ { serverOwners: islandsMode }
2247
2558
  );
2248
2559
  for (const { entry, metadata } of [...layoutEntries, ...routeEntries]) {
2249
2560
  if (!metadata.costGuardExceeded) continue;
@@ -2338,7 +2649,7 @@ var RouteManager = class {
2338
2649
  for (const { metadata } of [...layoutEntries, ...routeEntries]) {
2339
2650
  if (!metadata.hasIsolatedClientBoundaries && !metadata.serverTreeLayout) continue;
2340
2651
  for (const boundary of metadata.isolatedBoundaries) {
2341
- isolatedClientBoundaryModules.add(path3.resolve(boundary.modulePath));
2652
+ isolatedClientBoundaryModules.add(path4.resolve(boundary.modulePath));
2342
2653
  }
2343
2654
  }
2344
2655
  const islandsErrors = [
@@ -2389,7 +2700,7 @@ var RouteManager = class {
2389
2700
  }
2390
2701
  /** @internal Client modules selected by the compiled hydration ownership plan. */
2391
2702
  getIsolatedClientBoundaryModules(projectRoot = this.config.root) {
2392
- const normalizedProjectRoot = path3.resolve(projectRoot);
2703
+ const normalizedProjectRoot = path4.resolve(projectRoot);
2393
2704
  this.generateClientManifest(normalizedProjectRoot);
2394
2705
  return this.clientManifestCache?.isolatedClientBoundaryModules ?? /* @__PURE__ */ new Set();
2395
2706
  }
@@ -2398,7 +2709,7 @@ var RouteManager = class {
2398
2709
  * such a page whole would ship its server code to the browser, so it stays static instead.
2399
2710
  */
2400
2711
  getIslandsErrors(projectRoot = this.config.root) {
2401
- this.generateClientManifest(path3.resolve(projectRoot));
2712
+ this.generateClientManifest(path4.resolve(projectRoot));
2402
2713
  return this.clientManifestCache?.islandsErrors ?? [];
2403
2714
  }
2404
2715
  /**
@@ -2529,19 +2840,19 @@ var RouteManager = class {
2529
2840
  const markdownFiles = group.files.filter(isFarmMarkdownPageFile);
2530
2841
  if (componentFiles.length > 1) {
2531
2842
  throw new Error(
2532
- `Duplicate page route "${pattern}". Found ${componentFiles.map((file) => path3.join(appDir, file)).join(" and ")}.`
2843
+ `Duplicate page route "${pattern}". Found ${componentFiles.map((file) => path4.join(appDir, file)).join(" and ")}.`
2533
2844
  );
2534
2845
  }
2535
2846
  if (markdownFiles.length > 1) {
2536
2847
  throw new Error(
2537
- `Duplicate markdown representation for page route "${pattern}". Found ${markdownFiles.map((file) => path3.join(appDir, file)).join(" and ")}.`
2848
+ `Duplicate markdown representation for page route "${pattern}". Found ${markdownFiles.map((file) => path4.join(appDir, file)).join(" and ")}.`
2538
2849
  );
2539
2850
  }
2540
2851
  const componentFile = componentFiles[0];
2541
2852
  const markdownFile = markdownFiles[0];
2542
2853
  const primaryFile = componentFile || markdownFile;
2543
2854
  if (!primaryFile) continue;
2544
- const modulePath = path3.join(appDir, primaryFile);
2855
+ const modulePath = path4.join(appDir, primaryFile);
2545
2856
  const existing = this.routes.get(pattern);
2546
2857
  if (existing?.sourceRoot === source.root) {
2547
2858
  throw new Error(
@@ -2552,7 +2863,7 @@ var RouteManager = class {
2552
2863
  route: group.route,
2553
2864
  modulePath,
2554
2865
  ...markdownFile ? {
2555
- markdownSourcePath: path3.join(appDir, markdownFile)
2866
+ markdownSourcePath: path4.join(appDir, markdownFile)
2556
2867
  } : {},
2557
2868
  pattern,
2558
2869
  ...getPageDirectoryField(group.route, pattern),
@@ -2567,7 +2878,7 @@ var RouteManager = class {
2567
2878
  ]) {
2568
2879
  for (const file of files) {
2569
2880
  const route = parseRoutePath(file);
2570
- const modulePath = path3.join(appDir, file);
2881
+ const modulePath = path4.join(appDir, file);
2571
2882
  const pattern = createRouteDirectoryPattern(route);
2572
2883
  const existing = target.get(pattern);
2573
2884
  if (existing?.sourceRoot === source.root) {
@@ -2587,7 +2898,7 @@ var RouteManager = class {
2587
2898
  for (const file of [...pageFiles, ...slotDefaultFiles]) {
2588
2899
  const slot = parseRouteSlotFile(file);
2589
2900
  if (!slot) continue;
2590
- const modulePath = path3.join(appDir, file);
2901
+ const modulePath = path4.join(appDir, file);
2591
2902
  const pattern = this.createRoutePattern(slot.route);
2592
2903
  const ownerPattern = this.createRoutePattern(slot.ownerRoute);
2593
2904
  const ownerDirectory = createRouteDirectoryPattern(slot.ownerRoute);
@@ -2613,11 +2924,11 @@ var RouteManager = class {
2613
2924
  });
2614
2925
  }
2615
2926
  for (const file of metadataImageFiles) {
2616
- const fileBase = path3.basename(file, path3.extname(file));
2927
+ const fileBase = path4.basename(file, path4.extname(file));
2617
2928
  const kind = fileBase === "twitter-image" ? "twitter" : "opengraph";
2618
2929
  const fileName = kind === "twitter" ? "twitter-image" : "opengraph-image";
2619
2930
  const route = parseRoutePath(file);
2620
- const modulePath = path3.join(appDir, file);
2931
+ const modulePath = path4.join(appDir, file);
2621
2932
  const pattern = this.createRoutePattern(route);
2622
2933
  const key = `${kind}:${pattern}`;
2623
2934
  const existing = this.metadataImages.get(key);
@@ -2642,11 +2953,11 @@ var RouteManager = class {
2642
2953
  }
2643
2954
  for (const file of metadataRouteFiles) {
2644
2955
  const descriptor = getApplicationMetadataRouteDescriptor(
2645
- path3.basename(file, path3.extname(file))
2956
+ path4.basename(file, path4.extname(file))
2646
2957
  );
2647
2958
  if (!descriptor) continue;
2648
2959
  const route = parseRoutePath(file);
2649
- const modulePath = path3.join(appDir, file);
2960
+ const modulePath = path4.join(appDir, file);
2650
2961
  const pattern = this.createRoutePattern(route);
2651
2962
  const key = `${descriptor.kind}:${pattern}`;
2652
2963
  const existing = this.metadataRoutes.get(key);
@@ -3057,26 +3368,27 @@ function toRealPath(filePath) {
3057
3368
  }
3058
3369
 
3059
3370
  // src/server/dev-styles.ts
3060
- import * as fs2 from "fs";
3061
- import * as path4 from "path";
3371
+ import * as fs3 from "fs";
3372
+ import * as path5 from "path";
3062
3373
  function resolveDevGlobalStylesheetHref(root, srcDir = "src") {
3063
- const file = path4.join(root, srcDir, "app", "globals.css");
3064
- if (!fs2.existsSync(file)) return void 0;
3065
- return `/${path4.relative(root, file).split(path4.sep).join("/")}`;
3374
+ const file = path5.join(root, srcDir, "app", "globals.css");
3375
+ if (!fs3.existsSync(file)) return void 0;
3376
+ return `/${path5.relative(root, file).split(path5.sep).join("/")}`;
3066
3377
  }
3067
3378
  var STYLE_EXTENSIONS = /\.(css|scss|sass|less|styl|stylus)(?:$|\?)/;
3068
3379
  var ALREADY_LINKED = "/src/app/globals.css";
3069
- function collectDevStylesheetUrls(modules, alreadyLinked = ALREADY_LINKED) {
3380
+ function collectDevStylesheetUrls(modules, alreadyLinked = ALREADY_LINKED, options = {}) {
3070
3381
  const seen = /* @__PURE__ */ new Set();
3071
3382
  for (const mod of modules) {
3072
3383
  const id = mod.id ?? mod.file ?? "";
3073
3384
  if (!STYLE_EXTENSIONS.test(id)) continue;
3074
- if (id.includes(".module.")) continue;
3385
+ const cssModule = id.includes(".module.");
3386
+ if (cssModule && !options.cssModules) continue;
3075
3387
  const url = mod.url;
3076
3388
  if (!url || !url.startsWith("/")) continue;
3077
3389
  const bare = url.split("?")[0];
3078
3390
  if (bare === alreadyLinked) continue;
3079
- seen.add(bare);
3391
+ seen.add(cssModule ? `${bare}?direct` : bare);
3080
3392
  }
3081
3393
  return [...seen].sort();
3082
3394
  }
@@ -3085,7 +3397,7 @@ function collectDevStylesheetUrls(modules, alreadyLinked = ALREADY_LINKED) {
3085
3397
  import { createHash as createHash2, timingSafeEqual } from "crypto";
3086
3398
  import { existsSync as existsSync2 } from "fs";
3087
3399
  import { readFile as readFile2 } from "fs/promises";
3088
- import path5 from "path";
3400
+ import path6 from "path";
3089
3401
  import { createRequire } from "module";
3090
3402
  import { pathToFileURL } from "url";
3091
3403
  var FONT_IMPORTS = /* @__PURE__ */ new Set(["@farm.js/core", "@farm.js/core/font"]);
@@ -3442,7 +3754,7 @@ ${FONT_SECTION_END}
3442
3754
  return resource;
3443
3755
  }
3444
3756
  const bytes2 = await fetchRemoteFont(url, input.integrity);
3445
- return this.createSelfHostedResource(bytes2, extension, path5.basename(url.pathname));
3757
+ return this.createSelfHostedResource(bytes2, extension, path6.basename(url.pathname));
3446
3758
  }
3447
3759
  if (input.source.startsWith("/")) {
3448
3760
  return this.createPublicResource(input.moduleId, input.source);
@@ -3465,8 +3777,8 @@ ${FONT_SECTION_END}
3465
3777
  }
3466
3778
  return this.createSelfHostedResource(
3467
3779
  bytes,
3468
- path5.extname(resolvedPath),
3469
- path5.basename(resolvedPath)
3780
+ path6.extname(resolvedPath),
3781
+ path6.basename(resolvedPath)
3470
3782
  );
3471
3783
  }
3472
3784
  async createPublicResource(moduleId, source) {
@@ -3477,7 +3789,7 @@ ${FONT_SECTION_END}
3477
3789
  );
3478
3790
  }
3479
3791
  const publicPath = normalizePublicFontPath(source, moduleId);
3480
- const resolvedPath = path5.resolve(this.publicDir, `.${publicPath}`);
3792
+ const resolvedPath = path6.resolve(this.publicDir, `.${publicPath}`);
3481
3793
  if (!isPathInside(this.publicDir, resolvedPath)) {
3482
3794
  throw fontError(moduleId, `public font path must stay inside publicDir`);
3483
3795
  }
@@ -3493,7 +3805,7 @@ ${FONT_SECTION_END}
3493
3805
  `could not read ${JSON.stringify(source)} from publicDir: ${error.message}`
3494
3806
  );
3495
3807
  }
3496
- const extension = path5.extname(resolvedPath).toLowerCase();
3808
+ const extension = path6.extname(resolvedPath).toLowerCase();
3497
3809
  const hash = createHash2("sha256").update(bytes).digest("hex").slice(0, 12);
3498
3810
  const resource = {
3499
3811
  extension,
@@ -3508,7 +3820,7 @@ ${FONT_SECTION_END}
3508
3820
  createSelfHostedResource(bytes, extension, fileName) {
3509
3821
  const normalizedExtension = extension.toLowerCase();
3510
3822
  const hash = createHash2("sha256").update(bytes).digest("hex").slice(0, 12);
3511
- const baseName = sanitizeFileName(path5.basename(fileName, extension)) || "font";
3823
+ const baseName = sanitizeFileName(path6.basename(fileName, extension)) || "font";
3512
3824
  const outputFileName = `assets/fonts/${baseName}-h${hash}${normalizedExtension}`;
3513
3825
  const key = `${hash}${normalizedExtension}`;
3514
3826
  const existing = this.resources.get(key);
@@ -3861,24 +4173,24 @@ function verifyIntegrity(bytes, integrity) {
3861
4173
  if (!matches) throw new Error("downloaded font did not match its integrity value");
3862
4174
  }
3863
4175
  function resolveLocalFontPath(source, importer, root) {
3864
- if (source.startsWith(".")) return path5.resolve(path5.dirname(importer), source);
3865
- if (path5.isAbsolute(source)) {
4176
+ if (source.startsWith(".")) return path6.resolve(path6.dirname(importer), source);
4177
+ if (path6.isAbsolute(source)) {
3866
4178
  return source;
3867
4179
  }
3868
4180
  try {
3869
4181
  return createRequire(pathToFileURL(importer)).resolve(source);
3870
4182
  } catch {
3871
4183
  const segments = source.replace(/\\/g, "/").split("/");
3872
- if (segments.includes("..")) return path5.resolve(root, source);
3873
- let current = path5.dirname(importer);
3874
- const filesystemRoot = path5.parse(current).root;
4184
+ if (segments.includes("..")) return path6.resolve(root, source);
4185
+ let current = path6.dirname(importer);
4186
+ const filesystemRoot = path6.parse(current).root;
3875
4187
  while (true) {
3876
- const candidate = path5.join(current, "node_modules", ...segments);
4188
+ const candidate = path6.join(current, "node_modules", ...segments);
3877
4189
  if (existsSync2(candidate)) return candidate;
3878
4190
  if (current === filesystemRoot) break;
3879
- current = path5.dirname(current);
4191
+ current = path6.dirname(current);
3880
4192
  }
3881
- return path5.resolve(root, "node_modules", ...segments);
4193
+ return path6.resolve(root, "node_modules", ...segments);
3882
4194
  }
3883
4195
  }
3884
4196
  function replaceFontSection(css, section) {
@@ -3911,11 +4223,11 @@ function getGlobalMap(key) {
3911
4223
  return created;
3912
4224
  }
3913
4225
  function normalizeRoot(root) {
3914
- return path5.resolve(root).replace(/\\/g, "/");
4226
+ return path6.resolve(root).replace(/\\/g, "/");
3915
4227
  }
3916
4228
  function normalizePublicDir(root, publicDir) {
3917
4229
  if (publicDir === false || publicDir === "") return false;
3918
- return path5.resolve(root, publicDir || "public");
4230
+ return path6.resolve(root, publicDir || "public");
3919
4231
  }
3920
4232
  function normalizePublicFontPath(source, moduleId) {
3921
4233
  if (source.includes("?") || source.includes("#")) {
@@ -3924,8 +4236,8 @@ function normalizePublicFontPath(source, moduleId) {
3924
4236
  return `/${source.replace(/\\/g, "/").replace(/^\/+/, "")}`;
3925
4237
  }
3926
4238
  function isPathInside(parent, child) {
3927
- const relative3 = path5.relative(parent, child);
3928
- return relative3 === "" || !relative3.startsWith("..") && !path5.isAbsolute(relative3);
4239
+ const relative3 = path6.relative(parent, child);
4240
+ return relative3 === "" || !relative3.startsWith("..") && !path6.isAbsolute(relative3);
3929
4241
  }
3930
4242
  function normalizeBasePath(value) {
3931
4243
  if (!value || value === "/") return "/";
@@ -3935,7 +4247,7 @@ function joinBasePath(basePath, value) {
3935
4247
  return basePath === "/" ? value : `${basePath.replace(/\/$/, "")}${value}`;
3936
4248
  }
3937
4249
  function extensionFromPath(pathname) {
3938
- const extension = path5.extname(pathname).toLowerCase();
4250
+ const extension = path6.extname(pathname).toLowerCase();
3939
4251
  if (!FONT_EXTENSION_RE.test(extension)) {
3940
4252
  throw new Error(`[Farm fonts] Remote font URL must end in .woff2, .woff, .ttf, or .otf`);
3941
4253
  }
@@ -4075,7 +4387,7 @@ function fontError(id, message) {
4075
4387
  }
4076
4388
 
4077
4389
  // src/integration-provider-build.ts
4078
- import path6 from "path";
4390
+ import path7 from "path";
4079
4391
  function isRendererCompiledComponent(moduleId, rendererComponentExtensions) {
4080
4392
  const lowered = moduleId.toLowerCase();
4081
4393
  return rendererComponentExtensions.some((extension) => lowered.endsWith(extension.toLowerCase()));
@@ -4177,76 +4489,473 @@ function generateFarmIntegrationProviderServerModules(providers, root, rendererC
4177
4489
  }
4178
4490
  function resolveProviderModule(moduleId, root) {
4179
4491
  if (!moduleId.startsWith(".")) return moduleId;
4180
- return toViteModuleId(path6.resolve(root, moduleId), root);
4492
+ return toViteModuleId(path7.resolve(root, moduleId), root);
4181
4493
  }
4182
4494
 
4183
- // src/server/renderer.ts
4184
- import * as fs5 from "fs";
4185
- import * as https from "https";
4186
- import { isIP } from "net";
4187
- import * as path9 from "path";
4188
- import * as tls from "tls";
4189
- import { Readable, Writable } from "stream";
4190
-
4191
- // src/not-found.ts
4192
- import fs3 from "fs";
4193
- import path7 from "path";
4194
- function resolveFarmNotFoundComponentPath(config, appDirs) {
4195
- const extensions = getFarmRendererComponentExtensions(config.renderer);
4196
- const configuredPath = config.notFound?.component?.trim();
4197
- if (configuredPath) {
4198
- const componentPath = path7.isAbsolute(configuredPath) ? path7.normalize(configuredPath) : path7.resolve(config.root, configuredPath);
4199
- if (!extensions.some((extension) => componentPath.endsWith(extension))) {
4200
- throw new Error(
4201
- `notFound.component must use one of the configured renderer extensions: ${extensions.join(", ")}`
4202
- );
4495
+ // src/island-inference.ts
4496
+ import fs4 from "fs";
4497
+ import path8 from "path";
4498
+ import { inferStrategy } from "@farm.js/islx/compiler";
4499
+ import { parseAst } from "rolldown/parseAst";
4500
+ var PARSE_LANGS = /* @__PURE__ */ new Map([
4501
+ [".tsx", "tsx"],
4502
+ [".ts", "ts"],
4503
+ [".jsx", "jsx"],
4504
+ [".js", "jsx"],
4505
+ [".mjs", "js"]
4506
+ ]);
4507
+ function parseFarmIslandSource(file, code) {
4508
+ const lang = PARSE_LANGS.get(path8.extname(file));
4509
+ if (!lang) throw new Error(`${path8.basename(file)} is not a script module`);
4510
+ return parseAst(code, { lang });
4511
+ }
4512
+ function modifiedAt(file) {
4513
+ try {
4514
+ return fs4.statSync(file).mtimeMs;
4515
+ } catch {
4516
+ return -1;
4517
+ }
4518
+ }
4519
+ var inferences = /* @__PURE__ */ new Map();
4520
+ function inferFarmIslandStrategy(filePath, root) {
4521
+ const file = path8.resolve(filePath);
4522
+ const cached = inferences.get(file);
4523
+ if (cached && cached.stamps.every(([read, stamp]) => modifiedAt(read) === stamp)) {
4524
+ return cached.result;
4525
+ }
4526
+ let code;
4527
+ try {
4528
+ code = fs4.readFileSync(file, "utf8");
4529
+ } catch {
4530
+ return { strategy: null, files: [file], reason: `${path8.basename(file)} could not be read` };
4531
+ }
4532
+ const result = inferStrategy(file, code, {
4533
+ parse: parseFarmIslandSource,
4534
+ resolve: (specifier, importer) => {
4535
+ const resolved = resolveImportedModule(importer, specifier, root);
4536
+ return resolved.local ? resolved.path : null;
4203
4537
  }
4204
- if (!fs3.existsSync(componentPath) || !fs3.statSync(componentPath).isFile()) {
4205
- throw new Error(`notFound.component was not found: ${componentPath}`);
4538
+ });
4539
+ inferences.set(file, {
4540
+ stamps: result.files.map((read) => [read, modifiedAt(read)]),
4541
+ result
4542
+ });
4543
+ return result;
4544
+ }
4545
+ function inferFarmRouteRootStrategy(owners, root) {
4546
+ const files = [];
4547
+ const modules = [];
4548
+ for (const owner of owners) {
4549
+ const rendered = collectFarmRenderedClientModules(owner, root);
4550
+ if (!rendered) {
4551
+ return {
4552
+ strategy: null,
4553
+ files,
4554
+ reason: `${path8.basename(owner)}: its client components could not be listed`
4555
+ };
4206
4556
  }
4207
- return componentPath;
4557
+ modules.push(...rendered);
4208
4558
  }
4209
- let discoveredPath = null;
4210
- for (const appDir of appDirs) {
4211
- for (const extension of extensions) {
4212
- const candidate = path7.join(appDir, `not-found${extension}`);
4213
- if (fs3.existsSync(candidate) && fs3.statSync(candidate).isFile()) {
4214
- discoveredPath = candidate;
4215
- break;
4216
- }
4559
+ for (const module of modules) {
4560
+ let source = null;
4561
+ try {
4562
+ source = fs4.readFileSync(module, "utf8");
4563
+ } catch {
4217
4564
  }
4565
+ if (getIslandStrategyExport(source) !== null) return { strategy: null, files, declared: true };
4218
4566
  }
4219
- return discoveredPath;
4220
- }
4221
-
4222
- // src/components/not-found-styles.ts
4223
- var DEFAULT_NOT_FOUND_STYLES = `
4224
- body {
4225
- margin: 0;
4567
+ for (const module of modules) {
4568
+ const result = inferFarmIslandStrategy(module, root);
4569
+ files.push(...result.files);
4570
+ if (!result.strategy) return { strategy: null, files, reason: result.reason };
4571
+ }
4572
+ return { strategy: "interaction", files };
4226
4573
  }
4227
-
4228
- .farm-default-not-found {
4229
- --farm-not-found-bg: #fafafa;
4230
- --farm-not-found-fg: #171717;
4231
- --farm-not-found-muted: #737373;
4232
- --farm-not-found-line: rgba(0, 0, 0, 0.16);
4233
- --farm-not-found-button-fg: #ffffff;
4234
- min-height: 100vh;
4235
- min-height: 100svh;
4236
- display: grid;
4237
- place-items: center;
4238
- padding: 24px;
4239
- color: var(--farm-not-found-fg);
4240
- background: var(--farm-not-found-bg);
4241
- font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
4242
- color-scheme: light;
4574
+ function resolveFarmRouteRootStrategy(route, page, layouts, root, islandsMode) {
4575
+ const directory = route.directory ?? route.pattern;
4576
+ const onRoute = layouts.filter(
4577
+ (layout) => routeBoundaryCoversDirectory(layout.pattern, directory)
4578
+ );
4579
+ const declared = [
4580
+ ...page.islandStrategy ? [page.islandStrategy] : [],
4581
+ ...onRoute.flatMap(
4582
+ (layout) => (layout.shouldHydrate || layout.hasIsolatedClientBoundaries) && layout.islandStrategy ? [layout.islandStrategy] : []
4583
+ )
4584
+ ];
4585
+ const combined = declared.every((strategy) => strategy === declared[0]) ? declared[0] ?? "load" : "load";
4586
+ const layoutHydrates = onRoute.some((layout) => layout.shouldHydrate);
4587
+ if (!islandsMode || !page.shouldHydrate && !layoutHydrates) return combined;
4588
+ const owners = [
4589
+ route.modulePath,
4590
+ ...layoutHydrates ? onRoute.map((layout) => layout.modulePath) : []
4591
+ ];
4592
+ const inference = inferFarmRouteRootStrategy(owners, root);
4593
+ if (inference.declared) return combined;
4594
+ return inference.strategy ?? "load";
4243
4595
  }
4244
4596
 
4245
- .farm-default-not-found,
4246
- .farm-default-not-found * {
4247
- box-sizing: border-box;
4597
+ // src/client-plugin-build.ts
4598
+ import fs5 from "fs";
4599
+ import path9 from "path";
4600
+ var CLIENT_KEYS = [
4601
+ "public",
4602
+ "setup",
4603
+ "hydration",
4604
+ "navigation",
4605
+ "error",
4606
+ "performance",
4607
+ "close"
4608
+ ];
4609
+ var HYDRATION_KEYS = ["before", "after"];
4610
+ var NAVIGATION_KEYS = ["before", "loaded", "resolved", "rendered", "error"];
4611
+ var MOBILE_SHELL_CLIENT_IMPORT = 'import { farmMobileShellClient as __farmMobileShellClient } from "@farm.js/core/internal/client-runtime";';
4612
+ var MOBILE_SHELL_CLIENT_REGISTRATION = ` {
4613
+ name: "farm:mobile-shell",
4614
+ enforce: "pre",
4615
+ definition: __farmMobileShellClient,
4616
+ }`;
4617
+ var APP_CLIENT_EXTENSIONS = ["ts", "tsx", "js", "jsx", "mts", "mjs"];
4618
+ function resolveFarmAppClientEntry(root = process.cwd(), srcDir = "src") {
4619
+ const sourceRoot = path9.resolve(root, srcDir);
4620
+ for (const extension of APP_CLIENT_EXTENSIONS) {
4621
+ const candidate = path9.join(sourceRoot, `client.${extension}`);
4622
+ if (fs5.existsSync(candidate) && fs5.statSync(candidate).isFile()) return candidate;
4623
+ }
4624
+ return void 0;
4248
4625
  }
4249
-
4626
+ function resolveFarmClientPlugins(plugins, _root) {
4627
+ if (!plugins?.length) return [];
4628
+ return plugins.flatMap((plugin) => {
4629
+ if (!plugin.client) return [];
4630
+ assertClientLifecycle(plugin.client, plugin.name);
4631
+ assertPublicData(plugin.client.public, plugin.name);
4632
+ return [
4633
+ {
4634
+ name: plugin.name,
4635
+ version: plugin.version,
4636
+ enforce: plugin.enforce,
4637
+ definition: plugin.client,
4638
+ publicData: plugin.client.public
4639
+ }
4640
+ ];
4641
+ });
4642
+ }
4643
+ function generateFarmClientPluginEntryCode(plugins, root, srcDir = "src", appPublicData, platform = resolveFarmPlatform()) {
4644
+ const resolved = resolveFarmClientPlugins(plugins, root);
4645
+ const appClientEntry = root ? resolveFarmAppClientEntry(root, srcDir) : void 0;
4646
+ const appImport = appClientEntry ? `import farmAppClientDefinition from ${JSON.stringify(appClientEntry.replace(/\\/g, "/"))};` : "";
4647
+ const mobileShell = platform === "mobile";
4648
+ const imports = mobileShell ? [MOBILE_SHELL_CLIENT_IMPORT, appImport].filter(Boolean).join("\n") : appImport;
4649
+ const serializedPlugins = mobileShell ? [MOBILE_SHELL_CLIENT_REGISTRATION] : [];
4650
+ serializedPlugins.push(
4651
+ ...resolved.map(
4652
+ (plugin) => ` {
4653
+ name: ${JSON.stringify(plugin.name)},
4654
+ version: ${serializeOptionalString(plugin.version)},
4655
+ enforce: ${serializeOptionalString(plugin.enforce)},
4656
+ definition: ${serializeClientLifecycle(plugin.definition, plugin.name)},
4657
+ public: ${serializePublicData(plugin.publicData)},
4658
+ }`
4659
+ )
4660
+ );
4661
+ if (appClientEntry) {
4662
+ assertPublicData(appPublicData, "farm:app-client");
4663
+ serializedPlugins.push(` {
4664
+ name: "farm:app-client",
4665
+ enforce: "post",
4666
+ definition: farmAppClientDefinition,
4667
+ public: ${serializePublicData(appPublicData)},
4668
+ }`);
4669
+ }
4670
+ const registrations = `[
4671
+ ${serializedPlugins.join(",\n")}
4672
+ ]`;
4673
+ return { imports, registrations, plugins: resolved };
4674
+ }
4675
+ function assertClientLifecycle(client, pluginName) {
4676
+ assertLifecycleObject(client, pluginName, "client", CLIENT_KEYS);
4677
+ assertHook(client.setup, pluginName, "client.setup");
4678
+ assertHook(client.error, pluginName, "client.error");
4679
+ assertHook(client.performance, pluginName, "client.performance");
4680
+ assertHook(client.close, pluginName, "client.close");
4681
+ if (client.hydration !== void 0) {
4682
+ assertLifecycleObject(client.hydration, pluginName, "client.hydration", HYDRATION_KEYS);
4683
+ assertHook(client.hydration.before, pluginName, "client.hydration.before");
4684
+ assertHook(client.hydration.after, pluginName, "client.hydration.after");
4685
+ }
4686
+ if (client.navigation !== void 0) {
4687
+ assertLifecycleObject(client.navigation, pluginName, "client.navigation", NAVIGATION_KEYS);
4688
+ for (const key of NAVIGATION_KEYS) {
4689
+ assertHook(client.navigation[key], pluginName, `client.navigation.${key}`);
4690
+ }
4691
+ }
4692
+ }
4693
+ function assertLifecycleObject(value, pluginName, location, allowedKeys) {
4694
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
4695
+ throw new TypeError(`Client plugin "${pluginName}" ${location} must be an object`);
4696
+ }
4697
+ const prototype = Object.getPrototypeOf(value);
4698
+ if (prototype !== Object.prototype && prototype !== null) {
4699
+ throw new TypeError(`Client plugin "${pluginName}" ${location} must be a plain object`);
4700
+ }
4701
+ for (const key of Reflect.ownKeys(value)) {
4702
+ if (typeof key === "symbol") {
4703
+ throw new TypeError(`Client plugin "${pluginName}" ${location} cannot contain symbol keys`);
4704
+ }
4705
+ if (!allowedKeys.includes(key)) {
4706
+ throw new TypeError(`Client plugin "${pluginName}" has an unknown ${location}.${key} option`);
4707
+ }
4708
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
4709
+ if (!descriptor?.enumerable) {
4710
+ throw new TypeError(`Client plugin "${pluginName}" ${location}.${key} must be enumerable`);
4711
+ }
4712
+ if (!("value" in descriptor)) {
4713
+ throw new TypeError(`Client plugin "${pluginName}" ${location}.${key} cannot be an accessor`);
4714
+ }
4715
+ }
4716
+ }
4717
+ function assertHook(value, pluginName, location) {
4718
+ if (value === void 0) return;
4719
+ if (typeof value !== "function") {
4720
+ throw new TypeError(`Client plugin "${pluginName}" ${location} must be a function`);
4721
+ }
4722
+ functionSource(value, pluginName, location);
4723
+ }
4724
+ function serializeClientLifecycle(definition, pluginName) {
4725
+ const fields = [];
4726
+ pushHook(fields, "setup", definition.setup, pluginName, "client.setup", 2);
4727
+ pushHookGroup(fields, "hydration", definition.hydration, HYDRATION_KEYS, pluginName, 2);
4728
+ pushHookGroup(fields, "navigation", definition.navigation, NAVIGATION_KEYS, pluginName, 2);
4729
+ pushHook(fields, "error", definition.error, pluginName, "client.error", 2);
4730
+ pushHook(fields, "performance", definition.performance, pluginName, "client.performance", 2);
4731
+ pushHook(fields, "close", definition.close, pluginName, "client.close", 2);
4732
+ return fields.length ? `{
4733
+ ${fields.join(",\n")}
4734
+ }` : "{}";
4735
+ }
4736
+ function pushHookGroup(fields, groupName, group, keys, pluginName, indent) {
4737
+ if (!group) return;
4738
+ const hooks = [];
4739
+ for (const key of keys) {
4740
+ pushHook(hooks, key, group[key], pluginName, `client.${groupName}.${key}`, indent + 2);
4741
+ }
4742
+ fields.push(
4743
+ `${" ".repeat(indent)}${JSON.stringify(groupName)}: {
4744
+ ${hooks.join(",\n")}
4745
+ ${" ".repeat(indent)}}`
4746
+ );
4747
+ }
4748
+ function pushHook(fields, key, hook, pluginName, location, indent) {
4749
+ if (hook === void 0) return;
4750
+ fields.push(
4751
+ `${" ".repeat(indent)}${JSON.stringify(key)}: ${functionSource(hook, pluginName, location)}`
4752
+ );
4753
+ }
4754
+ function functionSource(value, pluginName, location) {
4755
+ if (typeof value !== "function") {
4756
+ throw new TypeError(`Client plugin "${pluginName}" ${location} must be a function`);
4757
+ }
4758
+ const source = Function.prototype.toString.call(value).trim();
4759
+ if (!source || source.includes("[native code]")) {
4760
+ throw new TypeError(
4761
+ `Client plugin "${pluginName}" ${location} must be authored inline and cannot be native or bound`
4762
+ );
4763
+ }
4764
+ if (/^(?:async\s+)?function(?:\s*\*)?(?:\s+|\()/.test(source)) {
4765
+ return `(${source})`;
4766
+ }
4767
+ const method = source.match(/^(async\s+)?(\*\s*)?[$A-Z_a-z][$\w]*\s*(\([\s\S]*)$/);
4768
+ if (method) {
4769
+ const asyncPrefix = method[1] ?? "";
4770
+ const generator = method[2] ? "*" : "";
4771
+ return `(${asyncPrefix}function${generator}${method[3]})`;
4772
+ }
4773
+ if (source.includes("=>")) return `(${source})`;
4774
+ throw new TypeError(
4775
+ `Client plugin "${pluginName}" ${location} must use a function, method, or arrow function`
4776
+ );
4777
+ }
4778
+ function assertPublicData(value, pluginName) {
4779
+ if (value === void 0) return;
4780
+ const seen = /* @__PURE__ */ new WeakSet();
4781
+ const visit = (current, pathSegments) => {
4782
+ if (current === null || typeof current === "string" || typeof current === "boolean") {
4783
+ return;
4784
+ }
4785
+ if (typeof current === "number") {
4786
+ if (Number.isFinite(current)) return;
4787
+ throwPublicDataError(pluginName, pathSegments, "must be a finite number");
4788
+ }
4789
+ if (typeof current !== "object") {
4790
+ throwPublicDataError(pluginName, pathSegments, `cannot contain ${typeof current} values`);
4791
+ }
4792
+ if (seen.has(current)) {
4793
+ throwPublicDataError(pluginName, pathSegments, "cannot contain circular references");
4794
+ }
4795
+ seen.add(current);
4796
+ if (Array.isArray(current)) {
4797
+ for (let index = 0; index < current.length; index += 1) {
4798
+ if (!Object.prototype.hasOwnProperty.call(current, index)) {
4799
+ throwPublicDataError(
4800
+ pluginName,
4801
+ [...pathSegments, String(index)],
4802
+ "cannot contain sparse array slots"
4803
+ );
4804
+ }
4805
+ visit(current[index], [...pathSegments, String(index)]);
4806
+ }
4807
+ for (const key of Reflect.ownKeys(current)) {
4808
+ if (key === "length" || typeof key === "string" && isArrayIndex(key)) continue;
4809
+ throwPublicDataError(
4810
+ pluginName,
4811
+ pathSegments,
4812
+ typeof key === "symbol" ? "cannot contain symbol keys" : `cannot contain non-index array property ${key}`
4813
+ );
4814
+ }
4815
+ seen.delete(current);
4816
+ return;
4817
+ }
4818
+ const prototype = Object.getPrototypeOf(current);
4819
+ if (prototype !== Object.prototype && prototype !== null) {
4820
+ throwPublicDataError(pluginName, pathSegments, "must contain only plain objects and arrays");
4821
+ }
4822
+ for (const key of Reflect.ownKeys(current)) {
4823
+ if (typeof key === "symbol") {
4824
+ throwPublicDataError(pluginName, pathSegments, "cannot contain symbol keys");
4825
+ }
4826
+ const descriptor = Object.getOwnPropertyDescriptor(current, key);
4827
+ if (!descriptor?.enumerable) {
4828
+ throwPublicDataError(
4829
+ pluginName,
4830
+ [...pathSegments, key],
4831
+ "cannot contain non-enumerable properties"
4832
+ );
4833
+ }
4834
+ if (!("value" in descriptor)) {
4835
+ throwPublicDataError(
4836
+ pluginName,
4837
+ [...pathSegments, key],
4838
+ "cannot contain accessor properties"
4839
+ );
4840
+ }
4841
+ visit(descriptor.value, [...pathSegments, key]);
4842
+ }
4843
+ seen.delete(current);
4844
+ };
4845
+ visit(value, []);
4846
+ }
4847
+ function throwPublicDataError(pluginName, pathSegments, message) {
4848
+ const location = pathSegments.length ? ` at client.public.${pathSegments.join(".")}` : "";
4849
+ throw new TypeError(`Client plugin "${pluginName}"${location} ${message}`);
4850
+ }
4851
+ function serializePublicData(value) {
4852
+ if (value === void 0) return "undefined";
4853
+ return `JSON.parse(${JSON.stringify(JSON.stringify(value))})`;
4854
+ }
4855
+ function serializeOptionalString(value) {
4856
+ return value === void 0 ? "undefined" : JSON.stringify(value);
4857
+ }
4858
+ function isArrayIndex(key) {
4859
+ const value = Number(key);
4860
+ return Number.isInteger(value) && value >= 0 && value < 4294967295 && String(value) === key;
4861
+ }
4862
+
4863
+ // src/server/renderer.ts
4864
+ import * as fs8 from "fs";
4865
+ import * as https from "https";
4866
+ import { isIP } from "net";
4867
+ import * as path12 from "path";
4868
+ import * as tls from "tls";
4869
+ import { Readable, Writable } from "stream";
4870
+
4871
+ // src/not-found.ts
4872
+ import fs6 from "fs";
4873
+ import path10 from "path";
4874
+ function resolveFarmNotFoundComponentPath(config, appDirs) {
4875
+ const extensions = getFarmRendererComponentExtensions(config.renderer);
4876
+ const configuredPath = config.notFound?.component?.trim();
4877
+ if (configuredPath) {
4878
+ const componentPath = path10.isAbsolute(configuredPath) ? path10.normalize(configuredPath) : path10.resolve(config.root, configuredPath);
4879
+ if (!extensions.some((extension) => componentPath.endsWith(extension))) {
4880
+ throw new Error(
4881
+ `notFound.component must use one of the configured renderer extensions: ${extensions.join(", ")}`
4882
+ );
4883
+ }
4884
+ if (!fs6.existsSync(componentPath) || !fs6.statSync(componentPath).isFile()) {
4885
+ throw new Error(`notFound.component was not found: ${componentPath}`);
4886
+ }
4887
+ return componentPath;
4888
+ }
4889
+ let discoveredPath = null;
4890
+ for (const appDir of appDirs) {
4891
+ for (const extension of extensions) {
4892
+ const candidate = path10.join(appDir, `not-found${extension}`);
4893
+ if (fs6.existsSync(candidate) && fs6.statSync(candidate).isFile()) {
4894
+ discoveredPath = candidate;
4895
+ break;
4896
+ }
4897
+ }
4898
+ }
4899
+ return discoveredPath;
4900
+ }
4901
+
4902
+ // src/navigation/segment-navigation.ts
4903
+ function getFarmLayoutKey(pattern, params) {
4904
+ return pattern.replace(
4905
+ /\[\[?\.\.\.([^\]]+)\]?\]|\[([^\]]+)\]/g,
4906
+ (_match, rest, name) => {
4907
+ const value = params ? params[rest || name] : void 0;
4908
+ if (Array.isArray(value)) return value.map(encodeURIComponent).join("/");
4909
+ return value === void 0 ? "" : encodeURIComponent(String(value));
4910
+ }
4911
+ );
4912
+ }
4913
+ function countFarmKeptLayouts(layoutsHeader, layouts, params) {
4914
+ const chain = parseFarmLayoutChainHeader(layoutsHeader ?? null);
4915
+ if (chain.length === 0) return 0;
4916
+ const keys = layouts.map((layout) => getFarmLayoutKey(layout.pattern, params));
4917
+ if (chain[0] === keys[0]) return getSharedLayoutPrefixLength(chain, keys);
4918
+ return keys.length > 1 ? 1 + getSharedLayoutPrefixLength(chain, keys.slice(1)) : 0;
4919
+ }
4920
+ function createFarmFlushToken() {
4921
+ const bytes = new Uint8Array(16);
4922
+ globalThis.crypto.getRandomValues(bytes);
4923
+ let token = "";
4924
+ for (const byte of bytes) token += byte.toString(16).padStart(2, "0");
4925
+ return token;
4926
+ }
4927
+ function farmFlushMarker(token) {
4928
+ return `<!--farm-flush:${token}-->`;
4929
+ }
4930
+
4931
+ // src/components/not-found-styles.ts
4932
+ var DEFAULT_NOT_FOUND_STYLES = `
4933
+ body {
4934
+ margin: 0;
4935
+ }
4936
+
4937
+ .farm-default-not-found {
4938
+ --farm-not-found-bg: #fafafa;
4939
+ --farm-not-found-fg: #171717;
4940
+ --farm-not-found-muted: #737373;
4941
+ --farm-not-found-line: rgba(0, 0, 0, 0.16);
4942
+ --farm-not-found-button-fg: #ffffff;
4943
+ min-height: 100vh;
4944
+ min-height: 100svh;
4945
+ display: grid;
4946
+ place-items: center;
4947
+ padding: 24px;
4948
+ color: var(--farm-not-found-fg);
4949
+ background: var(--farm-not-found-bg);
4950
+ font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
4951
+ color-scheme: light;
4952
+ }
4953
+
4954
+ .farm-default-not-found,
4955
+ .farm-default-not-found * {
4956
+ box-sizing: border-box;
4957
+ }
4958
+
4250
4959
  .farm-default-not-found__content {
4251
4960
  width: min(100%, 280px);
4252
4961
  display: flex;
@@ -4377,8 +5086,8 @@ body {
4377
5086
  import { pathToFileURL as pathToFileURL2 } from "url";
4378
5087
 
4379
5088
  // src/server/error-diagnostics.ts
4380
- import * as fs4 from "fs";
4381
- import * as path8 from "path";
5089
+ import * as fs7 from "fs";
5090
+ import * as path11 from "path";
4382
5091
  import { fileURLToPath as fileURLToPath2 } from "url";
4383
5092
  var SECRET_VALUE_PATTERN = /\b(api[_-]?key|access[_-]?token|auth[_-]?token|client[_-]?secret|secret[_-]?key|token|password|secret)\s*[:=]\s*([^\s,;]+)/gi;
4384
5093
  var BEARER_PATTERN = /\b(Bearer\s+)[A-Za-z0-9._~+/=-]+/gi;
@@ -4386,8 +5095,8 @@ function redactErrorText(value) {
4386
5095
  return value.replace(BEARER_PATTERN, "$1[REDACTED]").replace(SECRET_VALUE_PATTERN, "$1=[REDACTED]");
4387
5096
  }
4388
5097
  function isPathInsideRoot(root, filePath) {
4389
- const relative3 = path8.relative(root, filePath);
4390
- return relative3 === "" || !relative3.startsWith("..") && !path8.isAbsolute(relative3);
5098
+ const relative3 = path11.relative(root, filePath);
5099
+ return relative3 === "" || !relative3.startsWith("..") && !path11.isAbsolute(relative3);
4391
5100
  }
4392
5101
  function normalizeStackPath(value) {
4393
5102
  const withoutQuery = value.replace(/[?#].*$/, "");
@@ -4404,13 +5113,13 @@ function findStackLocation(stack, root) {
4404
5113
  );
4405
5114
  if (!match) continue;
4406
5115
  const candidate = normalizeStackPath(match[1]);
4407
- if (!candidate || candidate.includes(`${path8.sep}node_modules${path8.sep}`)) continue;
4408
- const absolutePath = path8.resolve(candidate);
4409
- if (!isPathInsideRoot(root, absolutePath) || !fs4.existsSync(absolutePath)) continue;
4410
- const relativePath = path8.relative(root, absolutePath).split(path8.sep).join("/");
5116
+ if (!candidate || candidate.includes(`${path11.sep}node_modules${path11.sep}`)) continue;
5117
+ const absolutePath = path11.resolve(candidate);
5118
+ if (!isPathInsideRoot(root, absolutePath) || !fs7.existsSync(absolutePath)) continue;
5119
+ const relativePath = path11.relative(root, absolutePath).split(path11.sep).join("/");
4411
5120
  return {
4412
5121
  absolutePath,
4413
- displayPath: relativePath || path8.basename(absolutePath),
5122
+ displayPath: relativePath || path11.basename(absolutePath),
4414
5123
  line: Number(match[2]),
4415
5124
  column: Number(match[3])
4416
5125
  };
@@ -4419,7 +5128,7 @@ function findStackLocation(stack, root) {
4419
5128
  }
4420
5129
  function createSourceFrame(location) {
4421
5130
  try {
4422
- const sourceLines = fs4.readFileSync(location.absolutePath, "utf8").split(/\r?\n/);
5131
+ const sourceLines = fs7.readFileSync(location.absolutePath, "utf8").split(/\r?\n/);
4423
5132
  if (location.line < 1 || location.line > sourceLines.length) return void 0;
4424
5133
  const start = Math.max(1, location.line - 2);
4425
5134
  const end = Math.min(sourceLines.length, location.line + 2);
@@ -4442,13 +5151,13 @@ function createSourceFrame(location) {
4442
5151
  }
4443
5152
  }
4444
5153
  function sanitizeStack(stack, root) {
4445
- const normalizedRoot = path8.resolve(root);
5154
+ const normalizedRoot = path11.resolve(root);
4446
5155
  return redactErrorText(stack).split(normalizedRoot).join("<project>").replace(/<project>[^\s)]*/g, (segment) => segment.split("\\").join("/")).split("\n").filter((line, index) => index === 0 || !line.includes("node:internal")).slice(0, 14).join("\n");
4447
5156
  }
4448
5157
  function createDefaultErrorDiagnostics(error, root) {
4449
5158
  const normalizedError = error instanceof Error ? error : new Error(typeof error === "string" ? error : "Unknown server rendering error");
4450
5159
  const rawStack = normalizedError.stack || `${normalizedError.name}: ${normalizedError.message}`;
4451
- const location = findStackLocation(rawStack, path8.resolve(root));
5160
+ const location = findStackLocation(rawStack, path11.resolve(root));
4452
5161
  return {
4453
5162
  name: redactErrorText(normalizedError.name || "Error"),
4454
5163
  message: redactErrorText(normalizedError.message || "Unknown server rendering error"),
@@ -4457,6 +5166,13 @@ function createDefaultErrorDiagnostics(error, root) {
4457
5166
  };
4458
5167
  }
4459
5168
 
5169
+ // src/islands-client-boot.ts
5170
+ function canBootFarmIslandsClient(config) {
5171
+ const docs = config.docs;
5172
+ const docsEnabled = docs === true || typeof docs === "object" && docs !== null && docs.enabled !== false;
5173
+ return resolveFarmServerComponentsMode(config.experimental?.serverComponents) === "islands" && !docsEnabled && resolveFarmClientPlugins(config.plugins, config.root).length === 0 && !resolveFarmAppClientEntry(config.root, config.srcDir || "src");
5174
+ }
5175
+
4460
5176
  // src/server/renderer.ts
4461
5177
  var islands;
4462
5178
  function withFarmIslandsRenders(runtime, islandsRuntime) {
@@ -4563,6 +5279,10 @@ function appendResponseHeader(res, name, value) {
4563
5279
  res.setHeader(name, [String(current), value]);
4564
5280
  }
4565
5281
  }
5282
+ function requestHeader(req, name) {
5283
+ const value = req.headers?.[name];
5284
+ return Array.isArray(value) ? value[0] : value;
5285
+ }
4566
5286
  function appendResponseVary(res, value) {
4567
5287
  const current = res.getHeader("Vary");
4568
5288
  const values = new Set(
@@ -4589,6 +5309,10 @@ function rendererRenderOptions() {
4589
5309
  return nonce ? { nonce } : void 0;
4590
5310
  }
4591
5311
  var FARM_DEV_EARLY_CLIENT_SCRIPT = `<script type="module" async src="/@farm/client.js"></script>`;
5312
+ function createFarmDevBootScript(root, strategy) {
5313
+ const rootAttributes = root ? ` data-farm-root="${root}" data-farm-root-strategy="${escapeHtmlAttribute2(strategy ?? "load")}"` : "";
5314
+ return `<script type="module" async src="/@farm/client-boot.js" data-farm-runtime="/@farm/client.js"${rootAttributes}></script>`;
5315
+ }
4592
5316
  function createDocumentFooter(options) {
4593
5317
  return `${options.closeRoot === false ? "" : "</div>"}
4594
5318
  ${options.suspenseRevealFallback}
@@ -4702,7 +5426,7 @@ function createRouteStateProps(input) {
4702
5426
  function readAppPackageIdentity(root) {
4703
5427
  try {
4704
5428
  return JSON.parse(
4705
- fs5.readFileSync(path9.join(root || process.cwd(), "package.json"), "utf8")
5429
+ fs8.readFileSync(path12.join(root || process.cwd(), "package.json"), "utf8")
4706
5430
  );
4707
5431
  } catch {
4708
5432
  return {};
@@ -4814,7 +5538,8 @@ var ServerRenderer = class {
4814
5538
  if (!graph) return [];
4815
5539
  return collectDevStylesheetUrls(
4816
5540
  graph.idToModuleMap.values(),
4817
- this.devGlobalStylesheetHref() ?? void 0
5541
+ this.devGlobalStylesheetHref() ?? void 0,
5542
+ { cssModules: this.islandValues() }
4818
5543
  );
4819
5544
  }
4820
5545
  collectDevStyleLinks() {
@@ -4822,12 +5547,19 @@ var ServerRenderer = class {
4822
5547
  (href) => `<link rel="stylesheet" href="${escapeHtmlAttribute2(href)}">`
4823
5548
  );
4824
5549
  }
4825
- createLayoutBoundary(pattern, layoutElement) {
5550
+ /**
5551
+ * A layout's boundary. Islands mode keys it (the pattern with its params, as the production
5552
+ * server does), so a navigation can name the layouts the browser shows; a layout the browser
5553
+ * keeps is sent as its boundary alone (`kept`).
5554
+ */
5555
+ createLayoutBoundary(pattern, layoutElement, segment) {
4826
5556
  return this.rendererRuntime.createElement(
4827
5557
  "div",
4828
5558
  {
4829
5559
  "data-farm-layout-boundary": "true",
4830
5560
  "data-farm-layout-pattern": pattern,
5561
+ ...segment ? { "data-farm-layout-key": segment.key } : {},
5562
+ ...segment?.kept ? { "data-farm-layout-kept": "true" } : {},
4831
5563
  style: { display: "contents" }
4832
5564
  },
4833
5565
  layoutElement
@@ -5001,10 +5733,10 @@ var ServerRenderer = class {
5001
5733
  * Load SSG manifest from build output
5002
5734
  */
5003
5735
  loadSSGManifest() {
5004
- const manifestPath = path9.join(this.config.root, this.config.outDir, "__ssg_manifest.json");
5736
+ const manifestPath = path12.join(this.config.root, this.config.outDir, "__ssg_manifest.json");
5005
5737
  let content;
5006
5738
  try {
5007
- content = fs5.readFileSync(manifestPath, "utf-8");
5739
+ content = fs8.readFileSync(manifestPath, "utf-8");
5008
5740
  } catch (error) {
5009
5741
  if (error.code === "ENOENT") {
5010
5742
  return;
@@ -5223,10 +5955,10 @@ var ServerRenderer = class {
5223
5955
  return true;
5224
5956
  }
5225
5957
  try {
5226
- const htmlPath = page.urlPath === "/" ? path9.join(this.config.root, this.config.outDir, "client", "index.html") : path9.join(this.config.root, this.config.outDir, "client", page.urlPath + ".html");
5227
- if (fs5.existsSync(htmlPath)) {
5228
- const stat = fs5.statSync(htmlPath);
5229
- const html = fs5.readFileSync(htmlPath, "utf-8");
5958
+ const htmlPath = page.urlPath === "/" ? path12.join(this.config.root, this.config.outDir, "client", "index.html") : path12.join(this.config.root, this.config.outDir, "client", page.urlPath + ".html");
5959
+ if (fs8.existsSync(htmlPath)) {
5960
+ const stat = fs8.statSync(htmlPath);
5961
+ const html = fs8.readFileSync(htmlPath, "utf-8");
5230
5962
  await this.cacheSSGPage(page, html, {
5231
5963
  document: true,
5232
5964
  createdAt: stat.mtimeMs
@@ -5476,7 +6208,10 @@ var ServerRenderer = class {
5476
6208
  { experimentalPPR: this.config.experimental?.ppr === true }
5477
6209
  );
5478
6210
  const pprBypassReason = renderingConfig.ppr ? this.getPPRShellBypassReason(req, middlewareMap, middlewareContext, pluginExposedContext) : void 0;
5479
- const canCachePPRShell = renderingConfig.ppr && !pprBypassReason;
6211
+ const islandsNavigationRequest = Boolean(
6212
+ islands && this.islandValues() && (requestHeader(req, "f-layouts") || requestHeader(req, "f-stream"))
6213
+ );
6214
+ const canCachePPRShell = renderingConfig.ppr && !pprBypassReason && !islandsNavigationRequest;
5480
6215
  const pprI18nSnapshot = canCachePPRShell ? getFarmI18nClientSnapshot() : void 0;
5481
6216
  const pprShellOptions = canCachePPRShell ? {
5482
6217
  pathname,
@@ -5650,9 +6385,19 @@ var ServerRenderer = class {
5650
6385
  (metadata) => metadata.shouldHydrate && metadata.islandStrategy ? [metadata.islandStrategy] : []
5651
6386
  )
5652
6387
  ];
5653
- const hydrationIslandStrategy = hydrationStrategies.every(
5654
- (strategy) => strategy === hydrationStrategies[0]
5655
- ) ? hydrationStrategies[0] ?? "load" : "load";
6388
+ const hydrationIslandStrategy = this.islandValues() ? resolveFarmRouteRootStrategy(
6389
+ route,
6390
+ { shouldHydrate, islandStrategy: moduleMetadata.islandStrategy ?? null },
6391
+ layouts.map((layout, index) => ({
6392
+ pattern: layout.pattern,
6393
+ modulePath: layout.modulePath,
6394
+ shouldHydrate: layoutHydrationMetadata[index]?.shouldHydrate === true,
6395
+ hasIsolatedClientBoundaries: layoutHydrationMetadata[index]?.hasIsolatedClientBoundaries === true,
6396
+ islandStrategy: layoutHydrationMetadata[index]?.islandStrategy ?? null
6397
+ })),
6398
+ this.config.root || process.cwd(),
6399
+ true
6400
+ ) : hydrationStrategies.every((strategy) => strategy === hydrationStrategies[0]) ? hydrationStrategies[0] ?? "load" : "load";
5656
6401
  const hasHydratableRouteSlots = renderedRouteSlots.some(
5657
6402
  (slot) => slot.isClientComponent || slot.shouldHydrate
5658
6403
  );
@@ -5749,11 +6494,22 @@ var ServerRenderer = class {
5749
6494
  layoutShouldHydrate: shouldHydrateLayout,
5750
6495
  islandStrategy: hydrationIslandStrategy
5751
6496
  });
6497
+ const islandsSegments = Boolean(islands && this.islandValues());
6498
+ const keptLayoutCount = islandsSegments && !renderingConfig.ssg && !shouldHydrateLayout && renderedRouteSlots.length === 0 ? countFarmKeptLayouts(requestHeader(req, "f-layouts"), layouts, params) : 0;
6499
+ const keptLayouts = keptLayoutCount > 1 ? keptLayoutCount : 0;
5752
6500
  let wrappedElement = pageElement;
5753
6501
  for (let i = layoutModules.length - 1; i >= 0; i--) {
5754
6502
  const layoutModule = layoutModules[i];
5755
6503
  const layoutEntry = layouts[i];
5756
6504
  const LayoutComponent = layoutModule.default;
6505
+ const segment = islandsSegments && !shouldHydrateLayout ? { key: getFarmLayoutKey(layoutEntry.pattern, params) } : void 0;
6506
+ if (LayoutComponent && i > 0 && i < keptLayouts) {
6507
+ wrappedElement = this.createLayoutBoundary(layoutEntry.pattern, wrappedElement, {
6508
+ key: segment.key,
6509
+ kept: true
6510
+ });
6511
+ continue;
6512
+ }
5757
6513
  const slotProps = {};
5758
6514
  for (const slot of renderedRouteSlots) {
5759
6515
  if ((slot.ownerDirectory ?? slot.ownerPattern) !== layoutEntry.pattern) continue;
@@ -5783,7 +6539,11 @@ var ServerRenderer = class {
5783
6539
  params,
5784
6540
  ...slotProps
5785
6541
  });
5786
- wrappedElement = this.createLayoutBoundary(layoutEntry.pattern, wrappedElement);
6542
+ wrappedElement = this.createLayoutBoundary(
6543
+ layoutEntry.pattern,
6544
+ wrappedElement,
6545
+ segment
6546
+ );
5787
6547
  }
5788
6548
  if (shouldHydrateLayout) {
5789
6549
  wrappedElement = this.wrapClientGraph(wrappedElement);
@@ -5961,11 +6721,11 @@ var ServerRenderer = class {
5961
6721
  if (isFarmIntegrationProviderComponentReference(provider.component)) {
5962
6722
  providerSourceModule = provider.component.module;
5963
6723
  const providerModuleId = provider.component.module.startsWith(".") ? toViteModuleId(
5964
- path9.resolve(this.config.root, provider.component.module),
6724
+ path12.resolve(this.config.root, provider.component.module),
5965
6725
  this.config.root
5966
6726
  ) : provider.component.module;
5967
6727
  const providerModule = this.viteServer ? await loadFarmDevModule(this.viteServer, providerModuleId) : await importRuntimeModule(
5968
- provider.component.module.startsWith(".") ? pathToFileURL2(path9.resolve(this.config.root, provider.component.module)).href : provider.component.module
6728
+ provider.component.module.startsWith(".") ? pathToFileURL2(path12.resolve(this.config.root, provider.component.module)).href : provider.component.module
5969
6729
  );
5970
6730
  ProviderComponent = providerModule[provider.component.export || "default"];
5971
6731
  } else if (typeof provider.component === "function") {
@@ -6232,7 +6992,7 @@ var ServerRenderer = class {
6232
6992
  logger.warn(`Could not read metadata for ${pattern} in sitemap.xml: ${error}`);
6233
6993
  return void 0;
6234
6994
  }),
6235
- fs5.promises.stat(route.modulePath).catch(() => void 0)
6995
+ fs8.promises.stat(route.modulePath).catch(() => void 0)
6236
6996
  ]);
6237
6997
  return { pattern, module, lastModified: stat?.mtime.toISOString() };
6238
6998
  })
@@ -6298,7 +7058,7 @@ var ServerRenderer = class {
6298
7058
  const server = this.getDefaultMCPServer();
6299
7059
  const request2 = getCurrentRequestOrNull() ?? createWebRequestFromFarmRequest(req, { trustProxy: this.config.server?.trustProxy });
6300
7060
  try {
6301
- const { handleFarmDefaultMCPRequest } = await import("./agent-mcp-handler-WWCC4GLG.mjs");
7061
+ const { handleFarmDefaultMCPRequest } = await import("./agent-mcp-handler-7QMX2LUY.mjs");
6302
7062
  const origin = new URL(request2.url).origin;
6303
7063
  const response = await handleFarmDefaultMCPRequest(request2, {
6304
7064
  server,
@@ -6483,7 +7243,7 @@ var ServerRenderer = class {
6483
7243
  res.end();
6484
7244
  return;
6485
7245
  }
6486
- res.write(await fs5.promises.readFile(image.modulePath));
7246
+ res.write(await fs8.promises.readFile(image.modulePath));
6487
7247
  res.end();
6488
7248
  }
6489
7249
  async renderRouteErrorBoundary(req, res, options) {
@@ -6805,6 +7565,18 @@ window.__FARM_I18N__ = ${getFarmI18nClientSnapshot() ? serializeInlineValue(getF
6805
7565
  for (const [key, value] of Object.entries(options.responseHeaders || {})) {
6806
7566
  res.setHeader(key, value);
6807
7567
  }
7568
+ const islandsMode = Boolean(islands && this.islandValues());
7569
+ const flushToken = islandsMode && requestHeader(req, "f-stream") === "flush" ? createFarmFlushToken() : "";
7570
+ const flushMarker = flushToken ? Buffer.from(farmFlushMarker(flushToken)) : void 0;
7571
+ if (islandsMode) {
7572
+ for (const name of ["F-Values", "F-Layouts", "F-Render", "F-Stream"]) {
7573
+ appendResponseVary(res, name);
7574
+ }
7575
+ if (requestHeader(req, "f-layouts") || flushToken) {
7576
+ res.setHeader("Cache-Control", "private, no-store");
7577
+ }
7578
+ if (flushToken) res.setHeader("F-Flush", flushToken);
7579
+ }
6808
7580
  const htmlParts = [];
6809
7581
  const findStaticShellBoundary = this.rendererRuntime.findStaticShellBoundary;
6810
7582
  const staticShellParts = options.captureStaticShell && findStaticShellBoundary ? [] : void 0;
@@ -6900,7 +7672,11 @@ window.__FARM_MANIFEST__ = ${JSON.stringify(clientManifest)};
6900
7672
  window.__FARM_INTEGRATION_API_MANIFEST__ = ${JSON.stringify(getRegisteredIntegrationAPIManifest())};
6901
7673
  window.__FARM_I18N__ = ${getFarmI18nClientSnapshot() ? serializeInlineValue(getFarmI18nClientSnapshot()) : "null"};
6902
7674
  </script>`;
6903
- const hydrationClickQueueScript = isClientComponent || req.__FARM_SHOULD_HYDRATE__ === true || req.__FARM_HAS_HYDRATABLE_ROUTE_SLOTS__ === true ? createPreHydrationClickQueueScript() : "";
7675
+ const islandsOnlyPage = this.islandValues() && req.__FARM_PAGE_SHOULD_HYDRATE__ !== true && req.__FARM_LAYOUT_SHOULD_HYDRATE__ !== true && req.__FARM_HAS_HYDRATABLE_ROUTE_SLOTS__ !== true;
7676
+ const rootStrategy = req.__FARM_ISLAND_STRATEGY__;
7677
+ const waitingRoot = this.islandValues() && !islandsOnlyPage && req.__FARM_HAS_HYDRATABLE_ROUTE_SLOTS__ !== true && rootStrategy !== void 0 && rootStrategy !== "load" ? req.__FARM_LAYOUT_SHOULD_HYDRATE__ === true ? "root" : "__farm_page__" : null;
7678
+ const bootClient = (islandsOnlyPage || waitingRoot !== null) && !staticShellParts && canBootFarmIslandsClient(this.config);
7679
+ const hydrationClickQueueScript = !islandsOnlyPage && !bootClient && (isClientComponent || req.__FARM_SHOULD_HYDRATE__ === true || req.__FARM_HAS_HYDRATABLE_ROUTE_SLOTS__ === true) ? createPreHydrationClickQueueScript() : "";
6904
7680
  const {
6905
7681
  title,
6906
7682
  tags: metaTags,
@@ -6931,6 +7707,7 @@ window.__FARM_I18N__ = ${getFarmI18nClientSnapshot() ? serializeInlineValue(getF
6931
7707
  const filterDocumentHTML = (html) => cspNonce ? filterFarmCspNonces(html, cspNonce) : html;
6932
7708
  const createLateNavigationRecovery = (navigationError) => this.createLateNavigationRecoveryHTML(req, navigationError);
6933
7709
  const earlyClient = this.islandValues();
7710
+ const earlyClientScript = bootClient ? createFarmDevBootScript(waitingRoot, rootStrategy) : FARM_DEV_EARLY_CLIENT_SCRIPT;
6934
7711
  const { pipe, abort } = renderToPipeableStream(streamRoot, {
6935
7712
  nonce: cspNonce,
6936
7713
  onShellReady() {
@@ -6969,7 +7746,7 @@ window.__FARM_I18N__ = ${getFarmI18nClientSnapshot() ? serializeInlineValue(getF
6969
7746
  ${hydrationClickQueueScript}
6970
7747
  </head>
6971
7748
  <body class="">${earlyClient ? `
6972
- ${FARM_DEV_EARLY_CLIENT_SCRIPT}` : ""}
7749
+ ${earlyClientScript}` : ""}
6973
7750
  <div id="root">`;
6974
7751
  const securedShell = streamDocument ? "" : stampDocumentHTML(shell);
6975
7752
  if (securedShell) {
@@ -6981,7 +7758,7 @@ window.__FARM_I18N__ = ${getFarmI18nClientSnapshot() ? serializeInlineValue(getF
6981
7758
  html: document.html.replace(
6982
7759
  /<body\b[^>]*>/i,
6983
7760
  (open) => `${open}
6984
- ${stampDocumentHTML(FARM_DEV_EARLY_CLIENT_SCRIPT)}`
7761
+ ${stampDocumentHTML(earlyClientScript)}`
6985
7762
  )
6986
7763
  } : document;
6987
7764
  const documentTransform = streamDocument ? createFarmStreamedDocumentTransform(
@@ -7054,6 +7831,14 @@ window.__FARM_I18N__ = ${getFarmI18nClientSnapshot() ? serializeInlineValue(getF
7054
7831
  };
7055
7832
  const writableStream = new Writable({
7056
7833
  write(chunk, encoding, callback) {
7834
+ if (flushMarker && chunk === flushMarker) {
7835
+ const marker = documentTransform ? documentTransform.write(flushMarker.toString()) : flushMarker;
7836
+ res.write(marker, () => {
7837
+ if (typeof res.flush === "function") res.flush();
7838
+ callback();
7839
+ });
7840
+ return;
7841
+ }
7057
7842
  if (firstChunk && process.env.FARM_VERBOSE) {
7058
7843
  console.log(`[FARM STREAM] first pipe chunk at ${Date.now() - streamStartTime}ms`);
7059
7844
  firstChunk = false;
@@ -7149,6 +7934,7 @@ window.__FARM_I18N__ = ${getFarmI18nClientSnapshot() ? serializeInlineValue(getF
7149
7934
  if (typeof res.flush === "function") {
7150
7935
  res.flush();
7151
7936
  }
7937
+ if (flushMarker) writableStream.flush = () => writableStream.write(flushMarker);
7152
7938
  pipe(writableStream);
7153
7939
  },
7154
7940
  onShellError(error) {
@@ -7278,13 +8064,13 @@ window.__FARM_I18N__ = ${getFarmI18nClientSnapshot() ? serializeInlineValue(getF
7278
8064
  res.end(createFarmMarkdownErrorBody(404, pathname, this.config.basePath || "/"));
7279
8065
  return;
7280
8066
  }
7281
- const appDir = path9.join(this.config.root, this.config.srcDir, "app");
8067
+ const appDir = path12.join(this.config.root, this.config.srcDir, "app");
7282
8068
  const notFoundExtensions = getFarmRendererComponentExtensions(this.config.renderer);
7283
8069
  let layoutModule = null;
7284
8070
  try {
7285
8071
  for (const ext of notFoundExtensions) {
7286
- const layoutPath = path9.join(appDir, `layout${ext}`);
7287
- if (fs5.existsSync(layoutPath)) {
8072
+ const layoutPath = path12.join(appDir, `layout${ext}`);
8073
+ if (fs8.existsSync(layoutPath)) {
7288
8074
  layoutModule = await this.routeManager.loadLayoutModule(layoutPath);
7289
8075
  break;
7290
8076
  }
@@ -7497,7 +8283,7 @@ ${clientScript}
7497
8283
  };
7498
8284
 
7499
8285
  // src/app.ts
7500
- import path10 from "path";
8286
+ import path13 from "path";
7501
8287
  var defaultDocsConfig = {
7502
8288
  enabled: false,
7503
8289
  entry: "/docs",
@@ -7637,7 +8423,7 @@ var FarmApp = class {
7637
8423
  }
7638
8424
  const componentExtensions = getFarmRendererComponentExtensions(this.config.renderer);
7639
8425
  const rootLayoutPaths = appDirs.flatMap(
7640
- (appDir) => componentExtensions.map((extension) => path10.join(appDir, `layout${extension}`))
8426
+ (appDir) => componentExtensions.map((extension) => path13.join(appDir, `layout${extension}`))
7641
8427
  );
7642
8428
  const hasRootLayout = await Promise.all(rootLayoutPaths.map((p) => fileExists(p))).then(
7643
8429
  (results) => results.some(Boolean)
@@ -7701,13 +8487,13 @@ function resolveFarmImageServerRuntime(images, preset) {
7701
8487
  }
7702
8488
 
7703
8489
  // src/app-manifest-packages.ts
7704
- import fs6 from "fs";
7705
- import path11 from "path";
8490
+ import fs9 from "fs";
8491
+ import path14 from "path";
7706
8492
  var FARM_PACKAGE = /^@(?:farm\.js|farming-labs)\/[a-z0-9._-]+$/;
7707
8493
  function resolveFarmAppPackages(root) {
7708
8494
  let manifest;
7709
8495
  try {
7710
- manifest = JSON.parse(fs6.readFileSync(path11.join(root, "package.json"), "utf8"));
8496
+ manifest = JSON.parse(fs9.readFileSync(path14.join(root, "package.json"), "utf8"));
7711
8497
  } catch {
7712
8498
  return {};
7713
8499
  }
@@ -7722,13 +8508,13 @@ function resolveFarmAppPackages(root) {
7722
8508
  for (let dir = root; ; ) {
7723
8509
  try {
7724
8510
  const { version } = JSON.parse(
7725
- fs6.readFileSync(path11.join(dir, "node_modules", name, "package.json"), "utf8")
8511
+ fs9.readFileSync(path14.join(dir, "node_modules", name, "package.json"), "utf8")
7726
8512
  );
7727
8513
  if (typeof version === "string" && /^[0-9A-Za-z.+-]{1,64}$/.test(version))
7728
8514
  versions[name] = version;
7729
8515
  break;
7730
8516
  } catch {
7731
- const parent = path11.dirname(dir);
8517
+ const parent = path14.dirname(dir);
7732
8518
  if (parent === dir) break;
7733
8519
  dir = parent;
7734
8520
  }
@@ -7738,9 +8524,9 @@ function resolveFarmAppPackages(root) {
7738
8524
  }
7739
8525
 
7740
8526
  // src/app-manifest-webmcp.ts
7741
- import fs7 from "fs";
8527
+ import fs10 from "fs";
7742
8528
  import { createRequire as createRequire2 } from "module";
7743
- import path12 from "path";
8529
+ import path15 from "path";
7744
8530
  import { globSync } from "tinyglobby";
7745
8531
  var WEBMCP_CLIENT = "@farm.js/webmcp/client";
7746
8532
  var DEFINERS = /* @__PURE__ */ new Set(["defineWebMCPTool", "registerWebMCPTool", "registerWebMCPTools"]);
@@ -7758,7 +8544,7 @@ var LANGS = {
7758
8544
  cjs: "jsx",
7759
8545
  jsx: "jsx"
7760
8546
  };
7761
- var parseAst;
8547
+ var parseAst2;
7762
8548
  function staticValue(node) {
7763
8549
  if (!node) return NOT_STATIC;
7764
8550
  switch (node.type) {
@@ -7790,407 +8576,141 @@ function staticValue(node) {
7790
8576
  if (value === NOT_STATIC) return NOT_STATIC;
7791
8577
  object[key] = value;
7792
8578
  }
7793
- return object;
7794
- }
7795
- case "TSAsExpression":
7796
- case "TSSatisfiesExpression":
7797
- case "TSNonNullExpression":
7798
- case "ParenthesizedExpression":
7799
- return staticValue(node.expression);
7800
- default:
7801
- return NOT_STATIC;
7802
- }
7803
- }
7804
- function property(object, name) {
7805
- return object.properties.find(
7806
- (entry) => entry.type === "Property" && !entry.computed && (entry.key.name === name || entry.key.value === name)
7807
- )?.value;
7808
- }
7809
- function toolFromObject(object) {
7810
- const name = staticValue(property(object, "name"));
7811
- if (typeof name !== "string" || !/^[A-Za-z0-9_.-]{1,128}$/.test(name)) return null;
7812
- const text = (key) => {
7813
- const value = staticValue(property(object, key));
7814
- return typeof value === "string" && value.length <= 2e3 ? value : void 0;
7815
- };
7816
- const annotations = staticValue(property(object, "annotations"));
7817
- const hints = annotations && typeof annotations === "object" && !Array.isArray(annotations) ? Object.fromEntries(
7818
- HINTS.filter(
7819
- (hint) => typeof annotations[hint] === "boolean"
7820
- ).map((hint) => [hint, annotations[hint]])
7821
- ) : {};
7822
- const schemaNode = property(object, "inputSchema");
7823
- const schema = staticValue(schemaNode);
7824
- const literal = schema !== NOT_STATIC && schema !== null && typeof schema === "object" && !Array.isArray(schema) && Buffer.byteLength(JSON.stringify(schema)) <= MAX_SCHEMA_BYTES;
7825
- const title = text("title");
7826
- const description = text("description");
7827
- return {
7828
- name,
7829
- ...title ? { title } : {},
7830
- ...description ? { description } : {},
7831
- ...hints,
7832
- ...literal ? { inputSchema: schema } : {},
7833
- inputSchemaSource: literal ? "literal" : schemaNode ? "computed" : "none"
7834
- };
7835
- }
7836
- function findFarmWebMCPTools(code, filename = "module.tsx") {
7837
- if (!code.includes(WEBMCP_CLIENT)) return [];
7838
- const lang = LANGS[path12.extname(filename).slice(1)] ?? "tsx";
7839
- parseAst ?? (parseAst = createRequire2(typeof __filename === "string" ? __filename : import.meta.url)(
7840
- "rolldown/parseAst"
7841
- ).parseAst);
7842
- let program;
7843
- try {
7844
- program = parseAst(code, { lang });
7845
- } catch {
7846
- return [];
7847
- }
7848
- const locals = /* @__PURE__ */ new Map();
7849
- for (const statement of program.body) {
7850
- if (statement.type !== "ImportDeclaration" || statement.source.value !== WEBMCP_CLIENT)
7851
- continue;
7852
- for (const specifier of statement.specifiers) {
7853
- const imported = specifier.imported?.name ?? specifier.imported?.value;
7854
- if (specifier.type === "ImportSpecifier" && DEFINERS.has(imported))
7855
- locals.set(specifier.local.name, imported);
7856
- }
7857
- }
7858
- if (!locals.size) return [];
7859
- const found = [];
7860
- const visit = (node) => {
7861
- if (!node || typeof node !== "object") return;
7862
- if (Array.isArray(node)) return node.forEach(visit);
7863
- const current = node;
7864
- if (current.type === "CallExpression" && current.callee.type === "Identifier") {
7865
- const definer = locals.get(current.callee.name);
7866
- const [argument] = current.arguments;
7867
- if (definer && argument) {
7868
- const objects = definer === "registerWebMCPTools" ? argument.type === "ArrayExpression" ? argument.elements.filter(
7869
- (element) => element?.type === "ObjectExpression"
7870
- ) : [] : argument.type === "ObjectExpression" ? [argument] : [];
7871
- for (const object of objects) {
7872
- const tool = toolFromObject(object);
7873
- if (tool) found.push({ start: object.start, tool });
7874
- }
7875
- }
7876
- }
7877
- for (const [key, value] of Object.entries(current))
7878
- if (key !== "type" && value && typeof value === "object") visit(value);
7879
- };
7880
- visit(program.body);
7881
- return found.sort((a, b) => a.start - b.start).map(({ tool }) => tool);
7882
- }
7883
- var cache = /* @__PURE__ */ new Map();
7884
- function collectFarmWebMCPTools(root, srcDir = "src") {
7885
- const base = path12.resolve(root, srcDir);
7886
- let files;
7887
- try {
7888
- files = globSync("**/*.{ts,tsx,js,jsx,mts,mjs,cts,cjs}", {
7889
- cwd: base,
7890
- absolute: true,
7891
- expandDirectories: false,
7892
- ignore: ["**/node_modules/**", "**/*.d.ts", "**/*.{test,spec}.*", "**/__tests__/**"]
7893
- });
7894
- } catch {
7895
- return [];
7896
- }
7897
- const seen = /* @__PURE__ */ new Set();
7898
- const tools = [];
7899
- for (const file of files.sort()) {
7900
- let mtimeMs;
7901
- try {
7902
- mtimeMs = fs7.statSync(file).mtimeMs;
7903
- } catch {
7904
- continue;
7905
- }
7906
- let entry = cache.get(file);
7907
- if (!entry || entry.mtimeMs !== mtimeMs) {
7908
- let code = "";
7909
- try {
7910
- code = fs7.readFileSync(file, "utf8");
7911
- } catch {
7912
- }
7913
- entry = { mtimeMs, tools: findFarmWebMCPTools(code, file) };
7914
- cache.set(file, entry);
7915
- }
7916
- for (const tool of entry.tools) {
7917
- if (seen.has(tool.name) || tools.length >= MAX_TOOLS) continue;
7918
- seen.add(tool.name);
7919
- tools.push(tool);
7920
- }
7921
- }
7922
- return tools;
7923
- }
7924
-
7925
- // src/client-plugin-build.ts
7926
- import fs8 from "fs";
7927
- import path13 from "path";
7928
- var CLIENT_KEYS = [
7929
- "public",
7930
- "setup",
7931
- "hydration",
7932
- "navigation",
7933
- "error",
7934
- "performance",
7935
- "close"
7936
- ];
7937
- var HYDRATION_KEYS = ["before", "after"];
7938
- var NAVIGATION_KEYS = ["before", "loaded", "resolved", "rendered", "error"];
7939
- var MOBILE_SHELL_CLIENT_IMPORT = 'import { farmMobileShellClient as __farmMobileShellClient } from "@farm.js/core/internal/client-runtime";';
7940
- var MOBILE_SHELL_CLIENT_REGISTRATION = ` {
7941
- name: "farm:mobile-shell",
7942
- enforce: "pre",
7943
- definition: __farmMobileShellClient,
7944
- }`;
7945
- var APP_CLIENT_EXTENSIONS = ["ts", "tsx", "js", "jsx", "mts", "mjs"];
7946
- function resolveFarmAppClientEntry(root = process.cwd(), srcDir = "src") {
7947
- const sourceRoot = path13.resolve(root, srcDir);
7948
- for (const extension of APP_CLIENT_EXTENSIONS) {
7949
- const candidate = path13.join(sourceRoot, `client.${extension}`);
7950
- if (fs8.existsSync(candidate) && fs8.statSync(candidate).isFile()) return candidate;
7951
- }
7952
- return void 0;
7953
- }
7954
- function resolveFarmClientPlugins(plugins, _root) {
7955
- if (!plugins?.length) return [];
7956
- return plugins.flatMap((plugin) => {
7957
- if (!plugin.client) return [];
7958
- assertClientLifecycle(plugin.client, plugin.name);
7959
- assertPublicData(plugin.client.public, plugin.name);
7960
- return [
7961
- {
7962
- name: plugin.name,
7963
- version: plugin.version,
7964
- enforce: plugin.enforce,
7965
- definition: plugin.client,
7966
- publicData: plugin.client.public
7967
- }
7968
- ];
7969
- });
7970
- }
7971
- function generateFarmClientPluginEntryCode(plugins, root, srcDir = "src", appPublicData) {
7972
- const resolved = resolveFarmClientPlugins(plugins, root);
7973
- const appClientEntry = root ? resolveFarmAppClientEntry(root, srcDir) : void 0;
7974
- const appImport = appClientEntry ? `import farmAppClientDefinition from ${JSON.stringify(appClientEntry.replace(/\\/g, "/"))};` : "";
7975
- const mobileShell = resolveFarmPlatform() === "mobile";
7976
- const imports = mobileShell ? [MOBILE_SHELL_CLIENT_IMPORT, appImport].filter(Boolean).join("\n") : appImport;
7977
- const serializedPlugins = mobileShell ? [MOBILE_SHELL_CLIENT_REGISTRATION] : [];
7978
- serializedPlugins.push(
7979
- ...resolved.map(
7980
- (plugin) => ` {
7981
- name: ${JSON.stringify(plugin.name)},
7982
- version: ${serializeOptionalString(plugin.version)},
7983
- enforce: ${serializeOptionalString(plugin.enforce)},
7984
- definition: ${serializeClientLifecycle(plugin.definition, plugin.name)},
7985
- public: ${serializePublicData(plugin.publicData)},
7986
- }`
7987
- )
7988
- );
7989
- if (appClientEntry) {
7990
- assertPublicData(appPublicData, "farm:app-client");
7991
- serializedPlugins.push(` {
7992
- name: "farm:app-client",
7993
- enforce: "post",
7994
- definition: farmAppClientDefinition,
7995
- public: ${serializePublicData(appPublicData)},
7996
- }`);
7997
- }
7998
- const registrations = `[
7999
- ${serializedPlugins.join(",\n")}
8000
- ]`;
8001
- return { imports, registrations, plugins: resolved };
8002
- }
8003
- function assertClientLifecycle(client, pluginName) {
8004
- assertLifecycleObject(client, pluginName, "client", CLIENT_KEYS);
8005
- assertHook(client.setup, pluginName, "client.setup");
8006
- assertHook(client.error, pluginName, "client.error");
8007
- assertHook(client.performance, pluginName, "client.performance");
8008
- assertHook(client.close, pluginName, "client.close");
8009
- if (client.hydration !== void 0) {
8010
- assertLifecycleObject(client.hydration, pluginName, "client.hydration", HYDRATION_KEYS);
8011
- assertHook(client.hydration.before, pluginName, "client.hydration.before");
8012
- assertHook(client.hydration.after, pluginName, "client.hydration.after");
8013
- }
8014
- if (client.navigation !== void 0) {
8015
- assertLifecycleObject(client.navigation, pluginName, "client.navigation", NAVIGATION_KEYS);
8016
- for (const key of NAVIGATION_KEYS) {
8017
- assertHook(client.navigation[key], pluginName, `client.navigation.${key}`);
8018
- }
8019
- }
8020
- }
8021
- function assertLifecycleObject(value, pluginName, location, allowedKeys) {
8022
- if (!value || typeof value !== "object" || Array.isArray(value)) {
8023
- throw new TypeError(`Client plugin "${pluginName}" ${location} must be an object`);
8024
- }
8025
- const prototype = Object.getPrototypeOf(value);
8026
- if (prototype !== Object.prototype && prototype !== null) {
8027
- throw new TypeError(`Client plugin "${pluginName}" ${location} must be a plain object`);
8028
- }
8029
- for (const key of Reflect.ownKeys(value)) {
8030
- if (typeof key === "symbol") {
8031
- throw new TypeError(`Client plugin "${pluginName}" ${location} cannot contain symbol keys`);
8032
- }
8033
- if (!allowedKeys.includes(key)) {
8034
- throw new TypeError(`Client plugin "${pluginName}" has an unknown ${location}.${key} option`);
8035
- }
8036
- const descriptor = Object.getOwnPropertyDescriptor(value, key);
8037
- if (!descriptor?.enumerable) {
8038
- throw new TypeError(`Client plugin "${pluginName}" ${location}.${key} must be enumerable`);
8039
- }
8040
- if (!("value" in descriptor)) {
8041
- throw new TypeError(`Client plugin "${pluginName}" ${location}.${key} cannot be an accessor`);
8042
- }
8043
- }
8044
- }
8045
- function assertHook(value, pluginName, location) {
8046
- if (value === void 0) return;
8047
- if (typeof value !== "function") {
8048
- throw new TypeError(`Client plugin "${pluginName}" ${location} must be a function`);
8579
+ return object;
8580
+ }
8581
+ case "TSAsExpression":
8582
+ case "TSSatisfiesExpression":
8583
+ case "TSNonNullExpression":
8584
+ case "ParenthesizedExpression":
8585
+ return staticValue(node.expression);
8586
+ default:
8587
+ return NOT_STATIC;
8049
8588
  }
8050
- functionSource(value, pluginName, location);
8051
- }
8052
- function serializeClientLifecycle(definition, pluginName) {
8053
- const fields = [];
8054
- pushHook(fields, "setup", definition.setup, pluginName, "client.setup", 2);
8055
- pushHookGroup(fields, "hydration", definition.hydration, HYDRATION_KEYS, pluginName, 2);
8056
- pushHookGroup(fields, "navigation", definition.navigation, NAVIGATION_KEYS, pluginName, 2);
8057
- pushHook(fields, "error", definition.error, pluginName, "client.error", 2);
8058
- pushHook(fields, "performance", definition.performance, pluginName, "client.performance", 2);
8059
- pushHook(fields, "close", definition.close, pluginName, "client.close", 2);
8060
- return fields.length ? `{
8061
- ${fields.join(",\n")}
8062
- }` : "{}";
8063
8589
  }
8064
- function pushHookGroup(fields, groupName, group, keys, pluginName, indent) {
8065
- if (!group) return;
8066
- const hooks = [];
8067
- for (const key of keys) {
8068
- pushHook(hooks, key, group[key], pluginName, `client.${groupName}.${key}`, indent + 2);
8069
- }
8070
- fields.push(
8071
- `${" ".repeat(indent)}${JSON.stringify(groupName)}: {
8072
- ${hooks.join(",\n")}
8073
- ${" ".repeat(indent)}}`
8074
- );
8590
+ function property(object, name) {
8591
+ return object.properties.find(
8592
+ (entry) => entry.type === "Property" && !entry.computed && (entry.key.name === name || entry.key.value === name)
8593
+ )?.value;
8075
8594
  }
8076
- function pushHook(fields, key, hook, pluginName, location, indent) {
8077
- if (hook === void 0) return;
8078
- fields.push(
8079
- `${" ".repeat(indent)}${JSON.stringify(key)}: ${functionSource(hook, pluginName, location)}`
8080
- );
8595
+ function toolFromObject(object) {
8596
+ const name = staticValue(property(object, "name"));
8597
+ if (typeof name !== "string" || !/^[A-Za-z0-9_.-]{1,128}$/.test(name)) return null;
8598
+ const text = (key) => {
8599
+ const value = staticValue(property(object, key));
8600
+ return typeof value === "string" && value.length <= 2e3 ? value : void 0;
8601
+ };
8602
+ const annotations = staticValue(property(object, "annotations"));
8603
+ const hints = annotations && typeof annotations === "object" && !Array.isArray(annotations) ? Object.fromEntries(
8604
+ HINTS.filter(
8605
+ (hint) => typeof annotations[hint] === "boolean"
8606
+ ).map((hint) => [hint, annotations[hint]])
8607
+ ) : {};
8608
+ const schemaNode = property(object, "inputSchema");
8609
+ const schema = staticValue(schemaNode);
8610
+ const literal = schema !== NOT_STATIC && schema !== null && typeof schema === "object" && !Array.isArray(schema) && Buffer.byteLength(JSON.stringify(schema)) <= MAX_SCHEMA_BYTES;
8611
+ const title = text("title");
8612
+ const description = text("description");
8613
+ return {
8614
+ name,
8615
+ ...title ? { title } : {},
8616
+ ...description ? { description } : {},
8617
+ ...hints,
8618
+ ...literal ? { inputSchema: schema } : {},
8619
+ inputSchemaSource: literal ? "literal" : schemaNode ? "computed" : "none"
8620
+ };
8081
8621
  }
8082
- function functionSource(value, pluginName, location) {
8083
- if (typeof value !== "function") {
8084
- throw new TypeError(`Client plugin "${pluginName}" ${location} must be a function`);
8085
- }
8086
- const source = Function.prototype.toString.call(value).trim();
8087
- if (!source || source.includes("[native code]")) {
8088
- throw new TypeError(
8089
- `Client plugin "${pluginName}" ${location} must be authored inline and cannot be native or bound`
8090
- );
8091
- }
8092
- if (/^(?:async\s+)?function(?:\s*\*)?(?:\s+|\()/.test(source)) {
8093
- return `(${source})`;
8094
- }
8095
- const method = source.match(/^(async\s+)?(\*\s*)?[$A-Z_a-z][$\w]*\s*(\([\s\S]*)$/);
8096
- if (method) {
8097
- const asyncPrefix = method[1] ?? "";
8098
- const generator = method[2] ? "*" : "";
8099
- return `(${asyncPrefix}function${generator}${method[3]})`;
8622
+ function findFarmWebMCPTools(code, filename = "module.tsx") {
8623
+ if (!code.includes(WEBMCP_CLIENT)) return [];
8624
+ const lang = LANGS[path15.extname(filename).slice(1)] ?? "tsx";
8625
+ parseAst2 ?? (parseAst2 = createRequire2(typeof __filename === "string" ? __filename : import.meta.url)(
8626
+ "rolldown/parseAst"
8627
+ ).parseAst);
8628
+ let program;
8629
+ try {
8630
+ program = parseAst2(code, { lang });
8631
+ } catch {
8632
+ return [];
8100
8633
  }
8101
- if (source.includes("=>")) return `(${source})`;
8102
- throw new TypeError(
8103
- `Client plugin "${pluginName}" ${location} must use a function, method, or arrow function`
8104
- );
8105
- }
8106
- function assertPublicData(value, pluginName) {
8107
- if (value === void 0) return;
8108
- const seen = /* @__PURE__ */ new WeakSet();
8109
- const visit = (current, pathSegments) => {
8110
- if (current === null || typeof current === "string" || typeof current === "boolean") {
8111
- return;
8112
- }
8113
- if (typeof current === "number") {
8114
- if (Number.isFinite(current)) return;
8115
- throwPublicDataError(pluginName, pathSegments, "must be a finite number");
8116
- }
8117
- if (typeof current !== "object") {
8118
- throwPublicDataError(pluginName, pathSegments, `cannot contain ${typeof current} values`);
8119
- }
8120
- if (seen.has(current)) {
8121
- throwPublicDataError(pluginName, pathSegments, "cannot contain circular references");
8634
+ const locals = /* @__PURE__ */ new Map();
8635
+ for (const statement of program.body) {
8636
+ if (statement.type !== "ImportDeclaration" || statement.source.value !== WEBMCP_CLIENT)
8637
+ continue;
8638
+ for (const specifier of statement.specifiers) {
8639
+ const imported = specifier.imported?.name ?? specifier.imported?.value;
8640
+ if (specifier.type === "ImportSpecifier" && DEFINERS.has(imported))
8641
+ locals.set(specifier.local.name, imported);
8122
8642
  }
8123
- seen.add(current);
8124
- if (Array.isArray(current)) {
8125
- for (let index = 0; index < current.length; index += 1) {
8126
- if (!Object.prototype.hasOwnProperty.call(current, index)) {
8127
- throwPublicDataError(
8128
- pluginName,
8129
- [...pathSegments, String(index)],
8130
- "cannot contain sparse array slots"
8131
- );
8643
+ }
8644
+ if (!locals.size) return [];
8645
+ const found = [];
8646
+ const visit = (node) => {
8647
+ if (!node || typeof node !== "object") return;
8648
+ if (Array.isArray(node)) return node.forEach(visit);
8649
+ const current = node;
8650
+ if (current.type === "CallExpression" && current.callee.type === "Identifier") {
8651
+ const definer = locals.get(current.callee.name);
8652
+ const [argument] = current.arguments;
8653
+ if (definer && argument) {
8654
+ const objects = definer === "registerWebMCPTools" ? argument.type === "ArrayExpression" ? argument.elements.filter(
8655
+ (element) => element?.type === "ObjectExpression"
8656
+ ) : [] : argument.type === "ObjectExpression" ? [argument] : [];
8657
+ for (const object of objects) {
8658
+ const tool = toolFromObject(object);
8659
+ if (tool) found.push({ start: object.start, tool });
8132
8660
  }
8133
- visit(current[index], [...pathSegments, String(index)]);
8134
- }
8135
- for (const key of Reflect.ownKeys(current)) {
8136
- if (key === "length" || typeof key === "string" && isArrayIndex(key)) continue;
8137
- throwPublicDataError(
8138
- pluginName,
8139
- pathSegments,
8140
- typeof key === "symbol" ? "cannot contain symbol keys" : `cannot contain non-index array property ${key}`
8141
- );
8142
8661
  }
8143
- seen.delete(current);
8144
- return;
8145
8662
  }
8146
- const prototype = Object.getPrototypeOf(current);
8147
- if (prototype !== Object.prototype && prototype !== null) {
8148
- throwPublicDataError(pluginName, pathSegments, "must contain only plain objects and arrays");
8663
+ for (const [key, value] of Object.entries(current))
8664
+ if (key !== "type" && value && typeof value === "object") visit(value);
8665
+ };
8666
+ visit(program.body);
8667
+ return found.sort((a, b) => a.start - b.start).map(({ tool }) => tool);
8668
+ }
8669
+ var cache = /* @__PURE__ */ new Map();
8670
+ function collectFarmWebMCPTools(root, srcDir = "src") {
8671
+ const base = path15.resolve(root, srcDir);
8672
+ let files;
8673
+ try {
8674
+ files = globSync("**/*.{ts,tsx,js,jsx,mts,mjs,cts,cjs}", {
8675
+ cwd: base,
8676
+ absolute: true,
8677
+ expandDirectories: false,
8678
+ ignore: ["**/node_modules/**", "**/*.d.ts", "**/*.{test,spec}.*", "**/__tests__/**"]
8679
+ });
8680
+ } catch {
8681
+ return [];
8682
+ }
8683
+ const seen = /* @__PURE__ */ new Set();
8684
+ const tools = [];
8685
+ for (const file of files.sort()) {
8686
+ let mtimeMs;
8687
+ try {
8688
+ mtimeMs = fs10.statSync(file).mtimeMs;
8689
+ } catch {
8690
+ continue;
8149
8691
  }
8150
- for (const key of Reflect.ownKeys(current)) {
8151
- if (typeof key === "symbol") {
8152
- throwPublicDataError(pluginName, pathSegments, "cannot contain symbol keys");
8153
- }
8154
- const descriptor = Object.getOwnPropertyDescriptor(current, key);
8155
- if (!descriptor?.enumerable) {
8156
- throwPublicDataError(
8157
- pluginName,
8158
- [...pathSegments, key],
8159
- "cannot contain non-enumerable properties"
8160
- );
8161
- }
8162
- if (!("value" in descriptor)) {
8163
- throwPublicDataError(
8164
- pluginName,
8165
- [...pathSegments, key],
8166
- "cannot contain accessor properties"
8167
- );
8692
+ let entry = cache.get(file);
8693
+ if (!entry || entry.mtimeMs !== mtimeMs) {
8694
+ let code = "";
8695
+ try {
8696
+ code = fs10.readFileSync(file, "utf8");
8697
+ } catch {
8168
8698
  }
8169
- visit(descriptor.value, [...pathSegments, key]);
8699
+ entry = { mtimeMs, tools: findFarmWebMCPTools(code, file) };
8700
+ cache.set(file, entry);
8170
8701
  }
8171
- seen.delete(current);
8172
- };
8173
- visit(value, []);
8174
- }
8175
- function throwPublicDataError(pluginName, pathSegments, message) {
8176
- const location = pathSegments.length ? ` at client.public.${pathSegments.join(".")}` : "";
8177
- throw new TypeError(`Client plugin "${pluginName}"${location} ${message}`);
8178
- }
8179
- function serializePublicData(value) {
8180
- if (value === void 0) return "undefined";
8181
- return `JSON.parse(${JSON.stringify(JSON.stringify(value))})`;
8182
- }
8183
- function serializeOptionalString(value) {
8184
- return value === void 0 ? "undefined" : JSON.stringify(value);
8185
- }
8186
- function isArrayIndex(key) {
8187
- const value = Number(key);
8188
- return Number.isInteger(value) && value >= 0 && value < 4294967295 && String(value) === key;
8702
+ for (const tool of entry.tools) {
8703
+ if (seen.has(tool.name) || tools.length >= MAX_TOOLS) continue;
8704
+ seen.add(tool.name);
8705
+ tools.push(tool);
8706
+ }
8707
+ }
8708
+ return tools;
8189
8709
  }
8190
8710
 
8191
8711
  // src/client-cache-persistence-build.ts
8192
- import fs9 from "fs";
8193
- import path14 from "path";
8712
+ import fs11 from "fs";
8713
+ import path16 from "path";
8194
8714
  var ADAPTER_EXTENSIONS = ["ts", "tsx", "js", "jsx", "mts", "mjs"];
8195
8715
  function resolveFarmClientCacheAdapterEntry(root, cache2) {
8196
8716
  const client = cache2?.client;
@@ -8201,7 +8721,7 @@ function resolveFarmClientCacheAdapterEntry(root, cache2) {
8201
8721
  'cache.client.adapter must be a module path string, for example "./src/cache-adapter".'
8202
8722
  );
8203
8723
  }
8204
- const resolved = path14.resolve(root, adapter);
8724
+ const resolved = path16.resolve(root, adapter);
8205
8725
  const found = resolveAdapterFile(resolved);
8206
8726
  if (!found) {
8207
8727
  throw new Error(
@@ -8214,10 +8734,10 @@ function resolveFarmClientCacheAdapterEntry(root, cache2) {
8214
8734
  return { importPath: found.replace(/\\/g, "/"), options };
8215
8735
  }
8216
8736
  function resolveAdapterFile(resolved) {
8217
- if (fs9.existsSync(resolved) && fs9.statSync(resolved).isFile()) return resolved;
8737
+ if (fs11.existsSync(resolved) && fs11.statSync(resolved).isFile()) return resolved;
8218
8738
  for (const extension of ADAPTER_EXTENSIONS) {
8219
8739
  const candidate = `${resolved}.${extension}`;
8220
- if (fs9.existsSync(candidate) && fs9.statSync(candidate).isFile()) return candidate;
8740
+ if (fs11.existsSync(candidate) && fs11.statSync(candidate).isFile()) return candidate;
8221
8741
  }
8222
8742
  return void 0;
8223
8743
  }
@@ -8380,11 +8900,55 @@ async function buildFarmTreeLayouts(layouts, params, source, options) {
8380
8900
  }
8381
8901
  `;
8382
8902
 
8903
+ // src/client/navigation-stream-client.ts
8904
+ var FARM_NAVIGATION_STREAM_READER_SOURCE = `// Reads a streamed navigation (F-Stream) up to the end of React's shell. \`next\` then resolves
8905
+ // with each later flush as it ends, and null at the end; a document without a marker is all shell.
8906
+ // The marker carries the random token the server sent in the F-Flush header, so page content
8907
+ // cannot forge a boundary; a response without a valid token is all shell.
8908
+ async function readFarmNavigationStream(body, flushToken) {
8909
+ const reader = body.getReader();
8910
+ const decoder = new TextDecoder();
8911
+ const marker = typeof flushToken === "string" && /^[0-9a-f]{32}$/.test(flushToken)
8912
+ ? "<!--farm-flush:" + flushToken + "-->"
8913
+ : "";
8914
+ let text = "";
8915
+ let done = false;
8916
+ const next = async function() {
8917
+ for (;;) {
8918
+ const at = marker ? text.indexOf(marker) : -1;
8919
+ if (at !== -1) {
8920
+ const flush = text.slice(0, at);
8921
+ text = text.slice(at + marker.length);
8922
+ return flush;
8923
+ }
8924
+ if (done) {
8925
+ const flush = text;
8926
+ text = "";
8927
+ return flush ? flush : null;
8928
+ }
8929
+ const result = await reader.read();
8930
+ if (result.done) {
8931
+ done = true;
8932
+ text += decoder.decode();
8933
+ } else {
8934
+ text += decoder.decode(result.value, { stream: true });
8935
+ }
8936
+ }
8937
+ };
8938
+ const shell = await next();
8939
+ if (done && !text) return { shell: shell || "" };
8940
+ return {
8941
+ shell: shell,
8942
+ next: next,
8943
+ cancel: function() { reader.cancel().catch(function() {}); },
8944
+ };
8945
+ }`;
8946
+
8383
8947
  // src/docs/client-config.ts
8384
8948
  import { realpathSync as realpathSync2 } from "fs";
8385
8949
  import { createRequire as createRequire3 } from "module";
8386
- import path15 from "path";
8387
- var parseAst2;
8950
+ import path17 from "path";
8951
+ var parseAst3;
8388
8952
  function propertyKeyName(property2) {
8389
8953
  if (property2.computed) return void 0;
8390
8954
  const key = property2.key;
@@ -8393,11 +8957,11 @@ function propertyKeyName(property2) {
8393
8957
  return void 0;
8394
8958
  }
8395
8959
  function redactFarmDocsClientConfig(code, filename) {
8396
- parseAst2 ?? (parseAst2 = createRequire3(typeof __filename === "string" ? __filename : import.meta.url)(
8960
+ parseAst3 ?? (parseAst3 = createRequire3(typeof __filename === "string" ? __filename : import.meta.url)(
8397
8961
  "rolldown/parseAst"
8398
8962
  ).parseAst);
8399
- const extension = path15.extname(filename);
8400
- const program = parseAst2(code, {
8963
+ const extension = path17.extname(filename);
8964
+ const program = parseAst3(code, {
8401
8965
  lang: extension === ".tsx" || extension === ".jsx" ? "tsx" : "ts"
8402
8966
  });
8403
8967
  const edits = [];
@@ -8458,7 +9022,7 @@ function farmDocsClientConfigPlugin(configModule) {
8458
9022
  }
8459
9023
 
8460
9024
  // src/server/vite-config.ts
8461
- import path16 from "path";
9025
+ import path18 from "path";
8462
9026
  var FARM_CLIENT_ENTRY_PATTERN = "**/{page,layout,loading,error,not-found,default}.{js,jsx,ts,tsx}";
8463
9027
  var FARM_CLIENT_OPTIMIZE_DEPS_INCLUDE = [
8464
9028
  "react",
@@ -8485,9 +9049,9 @@ function getFarmClientOptimizeDepsInclude(renderer) {
8485
9049
  );
8486
9050
  }
8487
9051
  function createFarmClientOptimizeDepsEntries(projectRoot, appDirectories) {
8488
- const resolvedProjectRoot = path16.resolve(projectRoot);
9052
+ const resolvedProjectRoot = path18.resolve(projectRoot);
8489
9053
  return appDirectories.map((appDirectory) => {
8490
- const relativeAppDirectory = path16.relative(resolvedProjectRoot, path16.resolve(appDirectory)).replace(/\\/g, "/");
9054
+ const relativeAppDirectory = path18.relative(resolvedProjectRoot, path18.resolve(appDirectory)).replace(/\\/g, "/");
8491
9055
  const prefix = relativeAppDirectory || ".";
8492
9056
  return `${prefix}/${FARM_CLIENT_ENTRY_PATTERN}`;
8493
9057
  });
@@ -8509,7 +9073,7 @@ function createFarmClientOptimizeDepsConfig(entries, renderer) {
8509
9073
  }
8510
9074
  function createFarmSourceAlias(projectRoot, srcDir = "src") {
8511
9075
  return {
8512
- "@": path16.resolve(projectRoot, srcDir)
9076
+ "@": path18.resolve(projectRoot, srcDir)
8513
9077
  };
8514
9078
  }
8515
9079
  function mergeNoExternal(farmValue, userValue) {
@@ -8657,6 +9221,8 @@ ${FARM_DARK_VARIANT}
8657
9221
  }
8658
9222
 
8659
9223
  export {
9224
+ withPackageClientBoundaryCache,
9225
+ usePackageClientBoundaryCacheFile,
8660
9226
  resolveModuleSourcePath,
8661
9227
  getFarmClientHydrationPlanOptions,
8662
9228
  describeSuppressedAsyncHydration,
@@ -8664,6 +9230,7 @@ export {
8664
9230
  hasUseClientDirective,
8665
9231
  getIslandStrategyExport,
8666
9232
  stripUseClientDirective,
9233
+ collectFarmServerStylesheets,
8667
9234
  getClientModuleMetadata,
8668
9235
  getClientModuleHydrationPlan,
8669
9236
  usesFarmServerTree,
@@ -8678,6 +9245,10 @@ export {
8678
9245
  DEFAULT_NOT_FOUND_STYLES,
8679
9246
  generateFarmIntegrationProviderClientCode,
8680
9247
  generateFarmIntegrationProviderServerModules,
9248
+ inferFarmIslandStrategy,
9249
+ resolveFarmRouteRootStrategy,
9250
+ generateFarmClientPluginEntryCode,
9251
+ canBootFarmIslandsClient,
8681
9252
  ServerRenderer,
8682
9253
  FarmApp,
8683
9254
  createFarmApp,
@@ -8686,11 +9257,11 @@ export {
8686
9257
  resolveFarmImageServerRuntime,
8687
9258
  resolveFarmAppPackages,
8688
9259
  collectFarmWebMCPTools,
8689
- generateFarmClientPluginEntryCode,
8690
9260
  resolveFarmClientCacheAdapterEntry,
8691
9261
  generateClientCachePersistenceCode,
8692
9262
  FARM_LAYOUT_ELEMENT_CLIENT_SOURCE,
8693
9263
  FARM_SERVER_TREE_LAYOUT_CLIENT_SOURCE,
9264
+ FARM_NAVIGATION_STREAM_READER_SOURCE,
8694
9265
  redactFarmDocsClientConfig,
8695
9266
  isFarmDocsClientConfigModule,
8696
9267
  farmDocsClientConfigPlugin,