@farm.js/core 0.1.36 → 0.1.38

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 (272) hide show
  1. package/dist/{agent-mcp-BVExL8rZ.d.mts → agent-mcp-BwKlpnc7.d.mts} +1 -1
  2. package/dist/{agent-mcp-luzfXK-P.d.ts → agent-mcp-De1imoMS.d.ts} +1 -1
  3. package/dist/{agent-mcp-handler-SJAHFSPI.cjs → agent-mcp-handler-MRGP3WJ3.cjs} +5 -5
  4. package/dist/{agent-mcp-handler-LPJ2CADR.mjs → agent-mcp-handler-OLRMZONF.mjs} +4 -4
  5. package/dist/agent-runtime.cjs +3 -3
  6. package/dist/agent-runtime.d.mts +1 -1
  7. package/dist/agent-runtime.d.ts +1 -1
  8. package/dist/agent-runtime.mjs +2 -2
  9. package/dist/api/client.cjs +3 -3
  10. package/dist/api/client.mjs +2 -2
  11. package/dist/api/route-manager.cjs +6 -6
  12. package/dist/api/route-manager.d.mts +3 -3
  13. package/dist/api/route-manager.d.ts +3 -3
  14. package/dist/api/route-manager.mjs +5 -5
  15. package/dist/api/runtime.cjs +4 -4
  16. package/dist/api/runtime.d.mts +2 -2
  17. package/dist/api/runtime.d.ts +2 -2
  18. package/dist/api/runtime.mjs +3 -3
  19. package/dist/api.cjs +9 -8
  20. package/dist/api.d.mts +3 -3
  21. package/dist/api.d.ts +3 -3
  22. package/dist/api.mjs +8 -7
  23. package/dist/{app-BukwkFIu.d.mts → app-CFZt-srr.d.mts} +21 -3
  24. package/dist/{app-Yfa2dsFy.d.ts → app-kT_QXTdx.d.ts} +21 -3
  25. package/dist/app-markdown.cjs +6 -4
  26. package/dist/app-markdown.d.mts +3 -3
  27. package/dist/app-markdown.d.ts +3 -3
  28. package/dist/app-markdown.mjs +5 -3
  29. package/dist/{chunk-ADEA7PN3.cjs → chunk-2DD4JMQC.cjs} +113 -22
  30. package/dist/chunk-2ZYGC6SS.cjs +576 -0
  31. package/dist/{chunk-JZVADIOD.cjs → chunk-34UCJRQO.cjs} +2 -2
  32. package/dist/{chunk-D2BB47NB.cjs → chunk-3LOLJTFV.cjs} +6 -6
  33. package/dist/{chunk-KXWRO25S.cjs → chunk-472NCAZ7.cjs} +3 -3
  34. package/dist/chunk-4E5QXOCL.cjs +109 -0
  35. package/dist/{chunk-Z2HLU4IX.cjs → chunk-4GWRFP22.cjs} +23 -2
  36. package/dist/{chunk-VQLJWDVW.cjs → chunk-4IE345DM.cjs} +37 -19
  37. package/dist/{chunk-O6WAEAX3.mjs → chunk-5BWWFHR2.mjs} +70 -15
  38. package/dist/{chunk-JNUWCDTF.cjs → chunk-5D2JIPLH.cjs} +2 -2
  39. package/dist/{chunk-BO36SELV.cjs → chunk-5OKBARDN.cjs} +2 -2
  40. package/dist/{chunk-AO6RYU5N.cjs → chunk-5PWXMJOH.cjs} +30 -22
  41. package/dist/{chunk-AHGECQEW.mjs → chunk-666CKENS.mjs} +1 -1
  42. package/dist/chunk-6BK3K2GB.mjs +318 -0
  43. package/dist/{chunk-O6I6VWKK.mjs → chunk-6HB6V3R7.mjs} +1 -1
  44. package/dist/{chunk-UXFQ3UDA.cjs → chunk-6XWDE2P2.cjs} +61 -4
  45. package/dist/{chunk-VILIPRS6.mjs → chunk-7FPTZLKH.mjs} +1 -1
  46. package/dist/{chunk-SC2WYWPF.mjs → chunk-7PEP3BUT.mjs} +3 -3
  47. package/dist/{chunk-4E5AEDKY.mjs → chunk-A3EAIURZ.mjs} +25 -7
  48. package/dist/{chunk-YDQZGSDS.mjs → chunk-ARC7I3O2.mjs} +1 -1
  49. package/dist/{chunk-LSZAVSGY.mjs → chunk-B6G5CKMC.mjs} +101 -10
  50. package/dist/{chunk-3KZS4SUS.mjs → chunk-BZHXGVMA.mjs} +1 -1
  51. package/dist/{chunk-KN7K4VQN.mjs → chunk-CNNOLE4O.mjs} +1 -1
  52. package/dist/{chunk-4GLOOWKE.mjs → chunk-CQMVIOYP.mjs} +1 -1
  53. package/dist/{chunk-2ELDTQRN.mjs → chunk-CUM5NYL5.mjs} +1 -1
  54. package/dist/{chunk-HITLGIAO.cjs → chunk-CY2ZQ5C6.cjs} +7 -6
  55. package/dist/{chunk-PZNL3WEG.mjs → chunk-DMEPTZTI.mjs} +22 -11
  56. package/dist/{chunk-QORUJDIV.mjs → chunk-DRLKAXDM.mjs} +2 -2
  57. package/dist/{chunk-DQQOKWYA.cjs → chunk-EIPC3FDA.cjs} +12 -4
  58. package/dist/{chunk-HOXTWRGB.mjs → chunk-EKF7KDFD.mjs} +5 -2
  59. package/dist/{chunk-42NHY7HW.cjs → chunk-EKN7NSZO.cjs} +62 -14
  60. package/dist/{chunk-YKX5BK66.cjs → chunk-EMO6K4YY.cjs} +7 -7
  61. package/dist/{chunk-6SJ2KJTA.mjs → chunk-EPYU2EBL.mjs} +1 -1
  62. package/dist/{chunk-D227TIEN.cjs → chunk-FWE7LEQC.cjs} +13 -13
  63. package/dist/{chunk-PTZ2TVNE.cjs → chunk-H5CLOUZS.cjs} +5 -5
  64. package/dist/{chunk-DTSROJ5J.mjs → chunk-HD5CF3OE.mjs} +1 -1
  65. package/dist/{chunk-35GKZR22.mjs → chunk-HXRYZWTA.mjs} +1 -1
  66. package/dist/{chunk-JG6DJF5A.mjs → chunk-HZFM2LWQ.mjs} +22 -1
  67. package/dist/{chunk-MKYBIIAQ.mjs → chunk-IBUQWVYA.mjs} +17 -1
  68. package/dist/{chunk-F2SE2VDO.mjs → chunk-IHQIOZLC.mjs} +1 -1
  69. package/dist/{chunk-W7LF2J2S.mjs → chunk-INL3THCU.mjs} +1 -1
  70. package/dist/{chunk-WZ77PUAM.mjs → chunk-IVLZZZEI.mjs} +1 -1
  71. package/dist/{chunk-ENLZ4R3Y.mjs → chunk-J7K2NZD6.mjs} +7 -6
  72. package/dist/{chunk-BPOF5U4N.mjs → chunk-JCKYH4LG.mjs} +10 -7
  73. package/dist/{chunk-77GNHH2Z.cjs → chunk-JCYYXBAJ.cjs} +3 -3
  74. package/dist/{chunk-C4SPBWFM.cjs → chunk-JEZO6VUR.cjs} +10 -1
  75. package/dist/{chunk-ZWM5KGAA.cjs → chunk-KCQBAKIY.cjs} +23 -20
  76. package/dist/{chunk-OTC5BDGO.mjs → chunk-KHKLMNI5.mjs} +12 -7
  77. package/dist/{chunk-DZ5ZVB2K.cjs → chunk-KKSTAEMY.cjs} +1 -1
  78. package/dist/{chunk-N2NAS2AM.cjs → chunk-L4DD7ODZ.cjs} +2 -2
  79. package/dist/{chunk-YSCV4SJF.cjs → chunk-L5H2GSUC.cjs} +4 -4
  80. package/dist/{chunk-OO7GXVSR.mjs → chunk-LI2F57NI.mjs} +1 -1
  81. package/dist/{chunk-NRSN7G7E.mjs → chunk-MLY2RP5R.mjs} +10 -2
  82. package/dist/{chunk-BPMATOP2.cjs → chunk-N32CC42M.cjs} +25 -20
  83. package/dist/{chunk-FNO7A7CM.cjs → chunk-NBBEQLOK.cjs} +34 -16
  84. package/dist/{chunk-XCMCS4DA.mjs → chunk-ND2CWPOD.mjs} +2 -2
  85. package/dist/{chunk-GQRWBCWK.mjs → chunk-OAHTRMIC.mjs} +13 -5
  86. package/dist/{chunk-35WV46VL.mjs → chunk-OCIEZME4.mjs} +876 -685
  87. package/dist/{chunk-UH6QN5NL.mjs → chunk-P664ZVTV.mjs} +2 -2
  88. package/dist/{chunk-TE2G5ION.cjs → chunk-PGZDEPTM.cjs} +88 -33
  89. package/dist/{chunk-FDR64H6B.mjs → chunk-POSPE3IO.mjs} +59 -2
  90. package/dist/{chunk-UVW64BCB.cjs → chunk-Q3NXS4MU.cjs} +16 -14
  91. package/dist/{chunk-4WCZJQUO.mjs → chunk-QFW2IH5E.mjs} +57 -9
  92. package/dist/{chunk-5SJWVY6R.mjs → chunk-QHSH7IH4.mjs} +9 -0
  93. package/dist/chunk-QRKIMN7T.mjs +48 -0
  94. package/dist/chunk-QTXBII4Z.cjs +632 -0
  95. package/dist/{chunk-CI6E3UOH.cjs → chunk-RG4A6LB2.cjs} +7 -7
  96. package/dist/{chunk-BJPBQNIE.cjs → chunk-RW63BOV7.cjs} +2 -2
  97. package/dist/{chunk-FO427P6I.cjs → chunk-RWFLWR5J.cjs} +10 -10
  98. package/dist/{chunk-FFFW3OQ7.cjs → chunk-S6FJO323.cjs} +2 -2
  99. package/dist/{chunk-EUV4YR3V.cjs → chunk-SGBJ247Q.cjs} +18 -2
  100. package/dist/chunk-SGBZPZUW.mjs +75 -0
  101. package/dist/{chunk-2NNMOPDN.mjs → chunk-SKVTP5PR.mjs} +4 -1
  102. package/dist/{chunk-2YTDKNH3.cjs → chunk-TGFQVLLF.cjs} +956 -765
  103. package/dist/{chunk-IHNIDL6H.cjs → chunk-TO4GJ56K.cjs} +22 -11
  104. package/dist/{chunk-276VJSM6.mjs → chunk-TUBTR2OP.mjs} +250 -118
  105. package/dist/{chunk-GQ3Z3IZI.cjs → chunk-TYJALEHQ.cjs} +18 -18
  106. package/dist/chunk-TYMMBFN2.mjs +109 -0
  107. package/dist/chunk-U6QLDL3G.mjs +576 -0
  108. package/dist/{chunk-U4KT7QP3.cjs → chunk-ULASELLA.cjs} +26 -1
  109. package/dist/chunk-UXHS27O6.cjs +75 -0
  110. package/dist/{chunk-WWIKMBRN.mjs → chunk-VNGH5MLF.mjs} +17 -1
  111. package/dist/{chunk-EZDQRNQ7.mjs → chunk-VT4WFRHA.mjs} +23 -5
  112. package/dist/{chunk-CBJJH36A.cjs → chunk-VU6AAZVY.cjs} +20 -4
  113. package/dist/{chunk-27ZWSI3W.cjs → chunk-VXEEATVD.cjs} +2 -2
  114. package/dist/{chunk-EWET4D2Y.mjs → chunk-W36M2BQ4.mjs} +3 -3
  115. package/dist/{chunk-4WQ6PGSJ.cjs → chunk-WEW2JVA4.cjs} +4 -4
  116. package/dist/{chunk-4E5WBPEG.mjs → chunk-WFRT7JPX.mjs} +8 -533
  117. package/dist/{chunk-T4OGRVNS.mjs → chunk-WLL43JMO.mjs} +2 -2
  118. package/dist/chunk-WW46B6HA.cjs +318 -0
  119. package/dist/{chunk-TKSCR644.cjs → chunk-WXJLNP33.cjs} +2 -2
  120. package/dist/{chunk-S6VYG6XU.cjs → chunk-XKG2BLFN.cjs} +2 -2
  121. package/dist/{chunk-4NU4GGTC.cjs → chunk-XKVVMZP5.cjs} +6 -3
  122. package/dist/{chunk-NMHWYWDR.cjs → chunk-YR2VBEMO.cjs} +658 -526
  123. package/dist/{chunk-OHLSEQ57.mjs → chunk-ZJD2PN6Z.mjs} +10 -8
  124. package/dist/{chunk-3BU22U3M.cjs → chunk-ZXH4TS3F.cjs} +5 -2
  125. package/dist/{client-plugins-r1mOtSC1.d.ts → client-plugins-BvlNhGEB.d.ts} +54 -7
  126. package/dist/{client-plugins-C3mK9Pol.d.mts → client-plugins-DUrIYX9B.d.mts} +54 -7
  127. package/dist/client-plugins.d.mts +1 -1
  128. package/dist/client-plugins.d.ts +1 -1
  129. package/dist/client.cjs +8 -8
  130. package/dist/client.d.mts +5 -5
  131. package/dist/client.d.ts +5 -5
  132. package/dist/client.mjs +7 -7
  133. package/dist/config.d.mts +1 -1
  134. package/dist/config.d.ts +1 -1
  135. package/dist/{devtools-ERIKFEXX.mjs → devtools-JYJNOLPQ.mjs} +8 -6
  136. package/dist/{devtools-JZJJY5CK.cjs → devtools-VQWJANJV.cjs} +9 -7
  137. package/dist/docs.cjs +12 -10
  138. package/dist/docs.d.mts +20 -2
  139. package/dist/docs.d.ts +20 -2
  140. package/dist/docs.mjs +11 -9
  141. package/dist/headers.cjs +6 -4
  142. package/dist/headers.d.mts +11 -1
  143. package/dist/headers.d.ts +11 -1
  144. package/dist/headers.mjs +5 -3
  145. package/dist/i18n/client.cjs +11 -11
  146. package/dist/i18n/client.mjs +3 -3
  147. package/dist/index.cjs +62 -46
  148. package/dist/index.d.mts +16 -16
  149. package/dist/index.d.ts +16 -16
  150. package/dist/index.mjs +62 -46
  151. package/dist/integrations.cjs +5 -3
  152. package/dist/integrations.d.mts +1 -1
  153. package/dist/integrations.d.ts +1 -1
  154. package/dist/integrations.mjs +4 -2
  155. package/dist/internal/app-markdown-runtime.cjs +5 -3
  156. package/dist/internal/app-markdown-runtime.d.mts +19 -5
  157. package/dist/internal/app-markdown-runtime.d.ts +19 -5
  158. package/dist/internal/app-markdown-runtime.mjs +4 -2
  159. package/dist/internal/build-runtime.cjs +33 -30
  160. package/dist/internal/build-runtime.d.mts +3 -3
  161. package/dist/internal/build-runtime.d.ts +3 -3
  162. package/dist/internal/build-runtime.mjs +32 -29
  163. package/dist/internal/cli-runtime.cjs +14 -12
  164. package/dist/internal/cli-runtime.mjs +13 -11
  165. package/dist/internal/client-error-overlay.cjs +4 -4
  166. package/dist/internal/client-error-overlay.mjs +1 -1
  167. package/dist/internal/client-runtime.cjs +2 -2
  168. package/dist/internal/client-runtime.mjs +1 -1
  169. package/dist/internal/compression-runtime.d.mts +1 -1
  170. package/dist/internal/compression-runtime.d.ts +1 -1
  171. package/dist/internal/config-runtime.cjs +9 -7
  172. package/dist/internal/config-runtime.d.mts +2 -2
  173. package/dist/internal/config-runtime.d.ts +2 -2
  174. package/dist/internal/config-runtime.mjs +8 -6
  175. package/dist/internal/docs-precompiled-runtime.cjs +19 -13
  176. package/dist/internal/docs-precompiled-runtime.d.mts +5 -0
  177. package/dist/internal/docs-precompiled-runtime.d.ts +5 -0
  178. package/dist/internal/docs-precompiled-runtime.mjs +14 -8
  179. package/dist/internal/infra-analytics-runtime.cjs +5 -5
  180. package/dist/internal/infra-analytics-runtime.mjs +3 -3
  181. package/dist/internal/product-telemetry-runtime.cjs +2 -2
  182. package/dist/internal/product-telemetry-runtime.mjs +1 -1
  183. package/dist/internal/production-node-env.cjs +6 -2
  184. package/dist/internal/production-node-env.d.mts +10 -1
  185. package/dist/internal/production-node-env.d.ts +10 -1
  186. package/dist/internal/production-node-env.mjs +5 -1
  187. package/dist/internal/production-runtime.cjs +39 -54
  188. package/dist/internal/production-runtime.d.mts +51 -11
  189. package/dist/internal/production-runtime.d.ts +51 -11
  190. package/dist/internal/production-runtime.mjs +39 -54
  191. package/dist/markdown.cjs +8 -2
  192. package/dist/markdown.d.mts +1 -1
  193. package/dist/markdown.d.ts +1 -1
  194. package/dist/markdown.mjs +7 -1
  195. package/dist/middleware.cjs +10 -8
  196. package/dist/middleware.d.mts +27 -5
  197. package/dist/middleware.d.ts +27 -5
  198. package/dist/middleware.mjs +10 -8
  199. package/dist/navigation.cjs +7 -7
  200. package/dist/navigation.d.mts +4 -4
  201. package/dist/navigation.d.ts +4 -4
  202. package/dist/navigation.mjs +6 -6
  203. package/dist/plugin.cjs +25 -23
  204. package/dist/plugin.d.mts +1 -1
  205. package/dist/plugin.d.ts +1 -1
  206. package/dist/plugin.mjs +24 -22
  207. package/dist/{production-runtime-CCeVZXst.d.mts → production-runtime-BQ4_WLwQ.d.mts} +1 -1
  208. package/dist/{production-runtime-DPnsggY3.d.ts → production-runtime-D2aMyzjr.d.ts} +1 -1
  209. package/dist/query/client.cjs +9 -9
  210. package/dist/query/client.mjs +4 -4
  211. package/dist/{render-plan-Cw4f5E_R.d.ts → render-plan-25p4hrj4.d.ts} +1 -1
  212. package/dist/{render-plan-BuGaPFe6.d.mts → render-plan-DtkXMN8D.d.mts} +1 -1
  213. package/dist/renderer-client.cjs +12 -12
  214. package/dist/renderer-client.d.mts +3 -3
  215. package/dist/renderer-client.d.ts +3 -3
  216. package/dist/renderer-client.mjs +4 -4
  217. package/dist/renderer.d.mts +13 -4
  218. package/dist/renderer.d.ts +13 -4
  219. package/dist/{request-CsGARcAw.d.mts → request-DgCkIdcn.d.mts} +4 -2
  220. package/dist/{request-Bkg-hERy.d.ts → request-jF4jwx8f.d.ts} +4 -2
  221. package/dist/request.cjs +3 -3
  222. package/dist/request.d.mts +2 -2
  223. package/dist/request.d.ts +2 -2
  224. package/dist/request.mjs +2 -2
  225. package/dist/{route-rendering-BUZMH_64.d.ts → route-rendering-Bji6S6a_.d.ts} +1 -1
  226. package/dist/{route-rendering-f11yh5dp.d.mts → route-rendering-CSBF78Ya.d.mts} +1 -1
  227. package/dist/{router-Cp6yRE8A.d.mts → router-B09Ui3Qm.d.mts} +1 -1
  228. package/dist/{router-B8CR9GbD.d.ts → router-CPB9cXtG.d.ts} +1 -1
  229. package/dist/routes.cjs +2 -2
  230. package/dist/routes.d.mts +1 -1
  231. package/dist/routes.d.ts +1 -1
  232. package/dist/routes.mjs +1 -1
  233. package/dist/{runtime-CAEv36S_.d.mts → runtime-CM6E6yuI.d.mts} +1 -1
  234. package/dist/{runtime-CQVsT330.d.ts → runtime-EDMwLdjv.d.ts} +1 -1
  235. package/dist/server-fn.cjs +3 -3
  236. package/dist/server-fn.mjs +2 -2
  237. package/dist/server-plugins.cjs +5 -5
  238. package/dist/server-plugins.d.mts +2 -2
  239. package/dist/server-plugins.d.ts +2 -2
  240. package/dist/server-plugins.mjs +4 -4
  241. package/dist/server-query.cjs +4 -4
  242. package/dist/server-query.mjs +3 -3
  243. package/dist/server.cjs +51 -49
  244. package/dist/server.d.mts +7 -7
  245. package/dist/server.d.ts +7 -7
  246. package/dist/server.mjs +29 -27
  247. package/dist/{spa-router-BuciWGCZ.d.ts → spa-router-B_N8XgVu.d.ts} +2 -2
  248. package/dist/{spa-router-DwbqGkGj.d.mts → spa-router-Cgimzfbi.d.mts} +2 -2
  249. package/dist/testing.cjs +8 -8
  250. package/dist/testing.d.mts +1 -1
  251. package/dist/testing.d.ts +1 -1
  252. package/dist/testing.mjs +6 -6
  253. package/dist/theme/server.cjs +4 -4
  254. package/dist/theme/server.mjs +3 -3
  255. package/dist/{utils-CaoWKtYM.d.ts → utils-BNxAKAuT.d.ts} +1 -1
  256. package/dist/{utils-B9V0S_yL.d.mts → utils-DZciYXYl.d.mts} +1 -1
  257. package/dist/version.cjs +2 -2
  258. package/dist/version.mjs +1 -1
  259. package/dist/vite.cjs +25 -23
  260. package/dist/vite.d.mts +1 -1
  261. package/dist/vite.d.ts +1 -1
  262. package/dist/vite.mjs +24 -22
  263. package/package.json +1 -1
  264. package/types/middleware.d.ts +5 -1
  265. package/dist/chunk-655RLQQL.mjs +0 -43
  266. package/dist/chunk-FXEF4PPL.mjs +0 -47
  267. package/dist/chunk-IZY3V5XW.mjs +0 -23
  268. package/dist/chunk-MRMI32SN.cjs +0 -1157
  269. package/dist/chunk-MT763TDW.cjs +0 -43
  270. package/dist/chunk-XD32KALF.cjs +0 -47
  271. /package/dist/{chunk-SJNMVDDF.cjs → chunk-FUCSUGDM.cjs} +0 -0
  272. /package/dist/{chunk-UDNPLXW7.mjs → chunk-MYIZXDZA.mjs} +0 -0
@@ -2,25 +2,32 @@ import {
2
2
  loadFarmProductionVite
3
3
  } from "./chunk-S3FNNQHR.mjs";
4
4
  import {
5
+ FARM_NODE_ENV_MODULE_FILE,
6
+ FARM_NODE_ENV_MODULE_SOURCE,
7
+ createFarmNodeServerEntry,
5
8
  withProductionNodeEnv
6
- } from "./chunk-655RLQQL.mjs";
9
+ } from "./chunk-6BK3K2GB.mjs";
7
10
  import {
8
- generateNativeMCPPluginSource
9
- } from "./chunk-FXEF4PPL.mjs";
11
+ generateNativeMCPPluginSource,
12
+ layoutsCanCoverSamePage
13
+ } from "./chunk-TYMMBFN2.mjs";
10
14
  import {
15
+ assertFarmDocsAdapterServesNoGuardedPages,
11
16
  compileFarmDocsAdapterEdgeManifest,
12
- createFarmDocsAPIHandler
13
- } from "./chunk-4E5AEDKY.mjs";
17
+ createFarmDocsAPIHandler,
18
+ hasFarmDocsRuntimeAdapter
19
+ } from "./chunk-A3EAIURZ.mjs";
14
20
  import {
15
21
  FARM_DOCS_LAST_MODIFIED_MANIFEST,
16
22
  createFarmDocsHandler,
17
23
  createFarmDocsLastModifiedManifest,
18
24
  discoverFarmDocsPages,
25
+ getFarmDocsMarkdownPath,
19
26
  getFarmDocsRouteTypeEntries,
20
27
  loadFarmDocsPage,
21
28
  resolveFarmDocsContentDir,
22
29
  toFarmDocsMarkdownPage
23
- } from "./chunk-O6WAEAX3.mjs";
30
+ } from "./chunk-5BWWFHR2.mjs";
24
31
  import {
25
32
  generateFarmDocsSearchClientRuntime,
26
33
  isFarmDocsSearchEnabled,
@@ -28,7 +35,7 @@ import {
28
35
  } from "./chunk-UP4CW6WP.mjs";
29
36
  import {
30
37
  FARM_PRERENDER_ENV
31
- } from "./chunk-3KZS4SUS.mjs";
38
+ } from "./chunk-BZHXGVMA.mjs";
32
39
  import {
33
40
  loadFarmDocsEngine
34
41
  } from "./chunk-2VQKKQ6D.mjs";
@@ -37,7 +44,7 @@ import {
37
44
  getDeployTargetForPreset,
38
45
  hasCustomFarmRouteContext,
39
46
  resolveDeployOutputPath
40
- } from "./chunk-OHLSEQ57.mjs";
47
+ } from "./chunk-ZJD2PN6Z.mjs";
41
48
  import {
42
49
  resolveFarmInstrumentationFile
43
50
  } from "./chunk-ZZSRYEYU.mjs";
@@ -76,30 +83,34 @@ import {
76
83
  resolveFarmIsolatedClientHydrationMode,
77
84
  resolveFarmNotFoundComponentPath,
78
85
  usesFarmServerTree
79
- } from "./chunk-276VJSM6.mjs";
86
+ } from "./chunk-TUBTR2OP.mjs";
80
87
  import {
81
88
  findRequestBoundSourceBlockers,
82
89
  generateFarmTypeArtifacts,
83
90
  parseRouteRenderingDirective,
84
91
  resolveRouteRenderingConfigFromFile
85
- } from "./chunk-4GLOOWKE.mjs";
92
+ } from "./chunk-CQMVIOYP.mjs";
86
93
  import {
87
94
  FARM_API_CATALOG_PATH,
88
95
  FARM_APP_MANIFEST_LEGACY_PATH,
89
96
  FARM_APP_MANIFEST_PATH,
90
97
  HOISTED_HEAD_ELEMENT,
98
+ appMiddlewareMayHandlePath,
99
+ configMiddlewareMayHandlePath,
100
+ farmPathGuardCoversPage,
91
101
  getRouteDirectoryDepth,
92
102
  getRouteGroupScope,
103
+ hasFarmMiddlewareConfig,
93
104
  resolveFarmApiCatalogInput,
94
105
  resolveFarmAppManifestInput,
95
106
  routeBoundaryCoversDirectory,
96
107
  stripRouteGroups
97
- } from "./chunk-LSZAVSGY.mjs";
108
+ } from "./chunk-B6G5CKMC.mjs";
98
109
  import {
99
110
  FARM_DEFAULT_MCP_PATH,
100
111
  createFarmDefaultMCPServer,
101
112
  farmConfigMountsMCP
102
- } from "./chunk-UH6QN5NL.mjs";
113
+ } from "./chunk-P664ZVTV.mjs";
103
114
  import {
104
115
  isFarmPreviewDeploymentEnvironment
105
116
  } from "./chunk-BOYNDCZL.mjs";
@@ -109,7 +120,7 @@ import {
109
120
  import {
110
121
  generateFarmDocsAdapterClientRuntime,
111
122
  getFarmDocsAdapterConfigModule
112
- } from "./chunk-ENLZ4R3Y.mjs";
123
+ } from "./chunk-J7K2NZD6.mjs";
113
124
  import {
114
125
  resolveFarmDocsFontAssets,
115
126
  toFarmDocsPublicFontAssets
@@ -130,8 +141,9 @@ import {
130
141
  resolveFarmRendererAppSetup
131
142
  } from "./chunk-DAATZTKJ.mjs";
132
143
  import {
133
- applyFarmCspHashesToHtml
134
- } from "./chunk-4E5WBPEG.mjs";
144
+ applyFarmCspHashesToHtml,
145
+ createFarmCspNonce
146
+ } from "./chunk-U6QLDL3G.mjs";
135
147
  import {
136
148
  applyFarmCronVercelCrons,
137
149
  createFarmCronCloudflareConfig,
@@ -143,14 +155,14 @@ import {
143
155
  } from "./chunk-4OOBRCJX.mjs";
144
156
  import {
145
157
  isFarmMarkdownPageFile
146
- } from "./chunk-4WCZJQUO.mjs";
158
+ } from "./chunk-QFW2IH5E.mjs";
147
159
  import {
148
160
  resolveFarmMdxComponentsModulePath,
149
161
  resolveMdxConfig
150
162
  } from "./chunk-FA2W42OV.mjs";
151
163
  import {
152
164
  getFarmMarkdownAlternatePath
153
- } from "./chunk-WWIKMBRN.mjs";
165
+ } from "./chunk-VNGH5MLF.mjs";
154
166
  import {
155
167
  applyFarmWorkflowVercelCrons,
156
168
  prepareFarmWorkflowsForNitro
@@ -159,20 +171,15 @@ import {
159
171
  FARM_INTEGRATION_API_BASE_PATH_KEY,
160
172
  getFarmIntegrationPluginServerRuntime,
161
173
  getIntegrationProviders
162
- } from "./chunk-MKYBIIAQ.mjs";
174
+ } from "./chunk-IBUQWVYA.mjs";
163
175
  import {
164
176
  appendMiddlewareDirectory,
165
177
  appendMiddlewareRoutePath,
166
178
  compareMiddlewareRouteLocations
167
- } from "./chunk-BPOF5U4N.mjs";
168
- import {
169
- compileMiddlewareConfig,
170
- matchesCompiledMiddlewareConfig,
171
- matchesMiddlewareRoute
172
- } from "./chunk-JG6DJF5A.mjs";
179
+ } from "./chunk-JCKYH4LG.mjs";
173
180
  import {
174
181
  APIRouteManager
175
- } from "./chunk-T4OGRVNS.mjs";
182
+ } from "./chunk-WLL43JMO.mjs";
176
183
  import {
177
184
  readFarmI18nCatalogs
178
185
  } from "./chunk-QCFBDFRS.mjs";
@@ -199,10 +206,13 @@ import {
199
206
  } from "./chunk-BTHHUD7Q.mjs";
200
207
  import {
201
208
  FARM_VERSION
202
- } from "./chunk-OO7GXVSR.mjs";
209
+ } from "./chunk-LI2F57NI.mjs";
203
210
  import {
204
211
  getFarmPresetRuntime
205
212
  } from "./chunk-2A3EQHXX.mjs";
213
+ import {
214
+ _runWithFarmCspNonce
215
+ } from "./chunk-POSPE3IO.mjs";
206
216
  import {
207
217
  compareRoutePatternSpecificity
208
218
  } from "./chunk-55YI3RRB.mjs";
@@ -211,7 +221,7 @@ import {
211
221
  } from "./chunk-LPEX4YW6.mjs";
212
222
 
213
223
  // src/build/index.ts
214
- import path7 from "path";
224
+ import path9 from "path";
215
225
  import { existsSync as existsSync3 } from "fs";
216
226
 
217
227
  // src/nitro/client-css-href.ts
@@ -219,15 +229,15 @@ import path from "path";
219
229
  var FARM_CLIENT_CSS_HREF_PLACEHOLDER = "/__farm_client_css_href__";
220
230
  var FARM_CLIENT_JS_SRC_PLACEHOLDER = "/__farm_client_js_src__";
221
231
  async function hashAndCopy(sourcePath, destinationDir, hashedName) {
222
- const fs = await import("fs/promises");
232
+ const fs3 = await import("fs/promises");
223
233
  try {
224
- const bytes = await fs.readFile(sourcePath);
234
+ const bytes = await fs3.readFile(sourcePath);
225
235
  if (bytes.length === 0) return null;
226
236
  const { createHash } = await import("crypto");
227
237
  const hash = createHash("sha256").update(bytes).digest("hex").slice(0, 8);
228
238
  const name = hashedName(hash);
229
- await fs.mkdir(destinationDir, { recursive: true });
230
- await fs.writeFile(path.join(destinationDir, name), bytes);
239
+ await fs3.mkdir(destinationDir, { recursive: true });
240
+ await fs3.writeFile(path.join(destinationDir, name), bytes);
231
241
  return name;
232
242
  } catch {
233
243
  return null;
@@ -244,9 +254,9 @@ async function resolveHashedClientCssHref(clientOutputDir) {
244
254
  }
245
255
  __name(resolveHashedClientCssHref, "resolveHashedClientCssHref");
246
256
  async function findFingerprintedClientEntry(clientOutputDir) {
247
- const fs = await import("fs/promises");
257
+ const fs3 = await import("fs/promises");
248
258
  try {
249
- const entries = await fs.readdir(clientOutputDir);
259
+ const entries = await fs3.readdir(clientOutputDir);
250
260
  return entries.find((name) => /^farm-client-h[0-9a-f]+\.js$/.test(name)) ?? null;
251
261
  } catch {
252
262
  return null;
@@ -256,17 +266,17 @@ __name(findFingerprintedClientEntry, "findFingerprintedClientEntry");
256
266
  async function resolveHashedClientJsSrc(clientOutputDir) {
257
267
  const entryName = await findFingerprintedClientEntry(clientOutputDir);
258
268
  if (!entryName) return "/farm-client.js";
259
- const fs = await import("fs/promises");
269
+ const fs3 = await import("fs/promises");
260
270
  const shim = `export * from "./${entryName}";
261
271
  `;
262
- await fs.writeFile(path.join(clientOutputDir, "farm-client.js"), shim);
272
+ await fs3.writeFile(path.join(clientOutputDir, "farm-client.js"), shim);
263
273
  return `/${entryName}`;
264
274
  }
265
275
  __name(resolveHashedClientJsSrc, "resolveHashedClientJsSrc");
266
276
 
267
277
  // src/nitro/universal-build.ts
268
278
  import os from "os";
269
- import path6 from "path";
279
+ import path8 from "path";
270
280
  import { constants as fsConstants, existsSync as existsSync2, readFileSync, realpathSync, statSync } from "fs";
271
281
  import { fileURLToPath } from "url";
272
282
  import { builtinModules, createRequire } from "module";
@@ -342,18 +352,21 @@ async function compileFarmDocsManifest(docs, options) {
342
352
  clientEntry: options.clientEntry,
343
353
  fontAssets: options.fontAssets,
344
354
  fontStylesheetHref: options.fontStylesheetHref,
345
- globalStylesheetHref: options.globalStylesheetHref
355
+ globalStylesheetHref: options.globalStylesheetHref,
356
+ isPathGuarded: options.isPathGuarded
346
357
  });
347
358
  const apiHandler = createFarmDocsAPIHandler({
348
359
  rootDir: options.root,
349
360
  srcDir: options.srcDir,
350
- docs
361
+ docs,
362
+ isPathGuarded: options.isPathGuarded
351
363
  });
364
+ const publicPages = pages.filter((page) => !options.isPathGuarded?.(page.href));
352
365
  const routes = {};
353
366
  const apiMarkdown = {};
354
367
  for (const page of pages) {
355
368
  const htmlResponse = await addHandlerRoute(routes, page.href, handler, absolutePaths);
356
- const markdownPath = page.href === "/" ? "/.md" : `${page.href}.md`;
369
+ const markdownPath = getFarmDocsMarkdownPath(page.href);
357
370
  await addHandlerRoute(routes, markdownPath, handler, absolutePaths);
358
371
  if (htmlResponse) {
359
372
  const socialImagePath = findSocialImagePath(await htmlResponse.text());
@@ -361,6 +374,7 @@ async function compileFarmDocsManifest(docs, options) {
361
374
  await addHandlerRoute(routes, socialImagePath, handler, absolutePaths);
362
375
  }
363
376
  }
377
+ if (options.isPathGuarded?.(page.href)) continue;
364
378
  const apiResponse = await apiHandler(
365
379
  new Request(
366
380
  `${FARM_DOCS_COMPILED_ORIGIN}/api/docs?format=markdown&path=${encodeURIComponent(page.slug)}`
@@ -435,7 +449,7 @@ async function compileFarmDocsManifest(docs, options) {
435
449
  empty: await compileResponse(emptyResponse, absolutePaths),
436
450
  post: await compileResponse(postResponse, absolutePaths),
437
451
  search: {
438
- pages: pages.map((page) => ({
452
+ pages: publicPages.map((page) => ({
439
453
  ...toFarmDocsMarkdownPage(page),
440
454
  sourcePath: `farm-docs:${page.slug || "index"}`
441
455
  })),
@@ -448,11 +462,179 @@ async function compileFarmDocsManifest(docs, options) {
448
462
  }
449
463
  __name(compileFarmDocsManifest, "compileFarmDocsManifest");
450
464
 
451
- // src/route-runtime-manifest.ts
465
+ // src/nitro/client-module-preloads.ts
466
+ import fs from "fs/promises";
452
467
  import path3 from "path";
468
+ var FARM_CLIENT_MODULE_PRELOADS_PLACEHOLDER = "__farm_client_module_preloads__";
469
+ var FARM_CLIENT_MODULE_PRELOADS_FILE = "client-module-preloads.json";
470
+ function collectFarmClientModulePreloads(bundle, options) {
471
+ const chunks = Object.values(bundle).filter(
472
+ (output) => output.type === "chunk"
473
+ );
474
+ const entry = chunks.find((chunk) => chunk.isEntry && chunk.name === options.entryName);
475
+ if (!entry) return null;
476
+ const byFile = new Map(chunks.map((chunk) => [chunk.fileName, chunk]));
477
+ const files = [];
478
+ const indexOf = /* @__PURE__ */ new Map();
479
+ const index = /* @__PURE__ */ __name((fileName) => {
480
+ let value = indexOf.get(fileName);
481
+ if (value === void 0) {
482
+ value = files.push(fileName) - 1;
483
+ indexOf.set(fileName, value);
484
+ }
485
+ return value;
486
+ }, "index");
487
+ const staticImports = /* @__PURE__ */ __name((chunk, loaded, into) => {
488
+ for (const fileName of chunk.imports ?? []) {
489
+ const imported = byFile.get(fileName);
490
+ if (loaded.has(fileName) || !imported) continue;
491
+ loaded.add(fileName);
492
+ into.push(fileName);
493
+ staticImports(imported, loaded, into);
494
+ }
495
+ return into;
496
+ }, "staticImports");
497
+ const entryFiles = staticImports(entry, /* @__PURE__ */ new Set([entry.fileName]), []);
498
+ const entryLoaded = /* @__PURE__ */ new Set([entry.fileName, ...entryFiles]);
499
+ const modules = {};
500
+ for (const chunk of chunks) {
501
+ if (!chunk.isDynamicEntry || !chunk.facadeModuleId || entryLoaded.has(chunk.fileName)) {
502
+ continue;
503
+ }
504
+ const moduleId = chunk.facadeModuleId.split("?")[0];
505
+ if (!path3.isAbsolute(moduleId)) continue;
506
+ const loaded = /* @__PURE__ */ new Set([...entryLoaded, chunk.fileName]);
507
+ modules[toViteModuleId(moduleId, options.root)] = [
508
+ chunk.fileName,
509
+ ...staticImports(chunk, loaded, [])
510
+ ].map(index);
511
+ }
512
+ return { files, entry: entryFiles.map(index), modules };
513
+ }
514
+ __name(collectFarmClientModulePreloads, "collectFarmClientModulePreloads");
515
+ function createFarmClientModulePreloadPlugin(options) {
516
+ return {
517
+ name: "farm-client-module-preloads",
518
+ async generateBundle(_output, bundle) {
519
+ await fs.mkdir(options.buildDir, { recursive: true });
520
+ await fs.writeFile(
521
+ path3.join(options.buildDir, FARM_CLIENT_MODULE_PRELOADS_FILE),
522
+ JSON.stringify(collectFarmClientModulePreloads(bundle, options))
523
+ );
524
+ }
525
+ };
526
+ }
527
+ __name(createFarmClientModulePreloadPlugin, "createFarmClientModulePreloadPlugin");
528
+ async function readFarmClientModulePreloads(buildDir) {
529
+ try {
530
+ return JSON.parse(
531
+ await fs.readFile(path3.join(buildDir, FARM_CLIENT_MODULE_PRELOADS_FILE), "utf8")
532
+ );
533
+ } catch {
534
+ return null;
535
+ }
536
+ }
537
+ __name(readFarmClientModulePreloads, "readFarmClientModulePreloads");
538
+ function encodeFarmClientModulePreloads(manifest) {
539
+ return JSON.stringify(JSON.stringify(manifest)).slice(1, -1).replace(/'/g, "\\u0027").replace(/`/g, "\\u0060").replace(/\$/g, "\\u0024").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
540
+ }
541
+ __name(encodeFarmClientModulePreloads, "encodeFarmClientModulePreloads");
542
+
543
+ // src/docs/module-preloads.ts
544
+ import fs2 from "fs/promises";
545
+ import path4 from "path";
546
+ var FARM_DOCS_MODULE_PRELOADS_PLACEHOLDER = "__farm_docs_module_preloads__";
547
+ var FARM_DOCS_MODULE_PRELOADS_FILE = "docs-module-preloads.json";
548
+ function normalizeModuleId(id) {
549
+ return id.split("?")[0].replace(/\\/g, "/");
550
+ }
551
+ __name(normalizeModuleId, "normalizeModuleId");
552
+ function collectFarmDocsModulePreloads(bundle, options) {
553
+ const chunks = Object.values(bundle).filter(
554
+ (output) => output.type === "chunk"
555
+ );
556
+ const byFile = new Map(chunks.map((chunk) => [chunk.fileName, chunk]));
557
+ const byModule = new Map(
558
+ chunks.filter((chunk) => chunk.facadeModuleId).map((chunk) => [normalizeModuleId(chunk.facadeModuleId), chunk])
559
+ );
560
+ const withStaticImports = /* @__PURE__ */ __name((fileName, into) => {
561
+ if (into.has(fileName) || !byFile.has(fileName)) return into;
562
+ into.add(fileName);
563
+ for (const imported of byFile.get(fileName).imports ?? []) withStaticImports(imported, into);
564
+ return into;
565
+ }, "withStaticImports");
566
+ const runtimeChunks = options.runtimeModuleIds.map((id) => byModule.get(normalizeModuleId(id))).filter((chunk) => Boolean(chunk));
567
+ const entry = chunks.find((chunk) => chunk.isEntry && chunk.name === options.entryName);
568
+ if (!entry || runtimeChunks.length === 0) return null;
569
+ const runtime = withStaticImports(entry.fileName, /* @__PURE__ */ new Set());
570
+ for (const chunk of runtimeChunks) withStaticImports(chunk.fileName, runtime);
571
+ const files = [];
572
+ const indexOf = /* @__PURE__ */ new Map();
573
+ const index = /* @__PURE__ */ __name((fileName) => {
574
+ let value = indexOf.get(fileName);
575
+ if (value === void 0) {
576
+ value = files.push(fileName) - 1;
577
+ indexOf.set(fileName, value);
578
+ }
579
+ return value;
580
+ }, "index");
581
+ const pages = {};
582
+ const root = normalizeModuleId(path4.resolve(options.root));
583
+ for (const [moduleId, chunk] of byModule) {
584
+ if (!/\.mdx?$/.test(moduleId) || !moduleId.startsWith(`${root}/`)) continue;
585
+ const own = [...withStaticImports(chunk.fileName, /* @__PURE__ */ new Set())].filter(
586
+ (fileName) => !runtime.has(fileName)
587
+ );
588
+ pages[moduleId.slice(root.length)] = own.map(index);
589
+ }
590
+ return { files, runtime: [...runtime].map(index), pages };
591
+ }
592
+ __name(collectFarmDocsModulePreloads, "collectFarmDocsModulePreloads");
593
+ function createFarmDocsModulePreloadPlugin(options) {
594
+ let runtimeModuleIds = [];
595
+ return {
596
+ name: "farm-docs-module-preloads",
597
+ async buildStart() {
598
+ const resolved = await Promise.all(
599
+ options.modules.map((specifier) => this.resolve(specifier, options.importer))
600
+ );
601
+ runtimeModuleIds = resolved.filter((value) => value !== null).map((value) => value.id);
602
+ },
603
+ async generateBundle(_output, bundle) {
604
+ const manifest = collectFarmDocsModulePreloads(bundle, {
605
+ root: options.root,
606
+ entryName: options.entryName,
607
+ runtimeModuleIds
608
+ });
609
+ await fs2.mkdir(options.buildDir, { recursive: true });
610
+ await fs2.writeFile(
611
+ path4.join(options.buildDir, FARM_DOCS_MODULE_PRELOADS_FILE),
612
+ JSON.stringify(manifest)
613
+ );
614
+ }
615
+ };
616
+ }
617
+ __name(createFarmDocsModulePreloadPlugin, "createFarmDocsModulePreloadPlugin");
618
+ async function readFarmDocsModulePreloads(buildDir) {
619
+ try {
620
+ return JSON.parse(
621
+ await fs2.readFile(path4.join(buildDir, FARM_DOCS_MODULE_PRELOADS_FILE), "utf8")
622
+ );
623
+ } catch {
624
+ return null;
625
+ }
626
+ }
627
+ __name(readFarmDocsModulePreloads, "readFarmDocsModulePreloads");
628
+ function encodeFarmDocsModulePreloads(manifest) {
629
+ return JSON.stringify(JSON.stringify(manifest)).slice(1, -1).replace(/'/g, "\\u0027").replace(/`/g, "\\u0060").replace(/\$/g, "\\u0024").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
630
+ }
631
+ __name(encodeFarmDocsModulePreloads, "encodeFarmDocsModulePreloads");
632
+
633
+ // src/route-runtime-manifest.ts
634
+ import path5 from "path";
453
635
  var FARM_ROUTE_RUNTIME_MANIFEST = "route-runtime-manifest.json";
454
636
  async function createFarmRouteRuntimeManifest(options) {
455
- const root = path3.resolve(options.root || options.config.root || process.cwd());
637
+ const root = path5.resolve(options.root || options.config.root || process.cwd());
456
638
  const routes = [];
457
639
  for (const [pattern, entry] of options.routeManager.getRoutes()) {
458
640
  const routeModule = await options.routeManager.loadRouteModule(entry.modulePath);
@@ -522,10 +704,10 @@ async function createFarmRouteRuntimeManifest(options) {
522
704
  }
523
705
  __name(createFarmRouteRuntimeManifest, "createFarmRouteRuntimeManifest");
524
706
  async function writeFarmRouteRuntimeManifest(directory, manifest) {
525
- const fs = await import("fs/promises");
526
- const manifestPath = path3.join(directory, FARM_ROUTE_RUNTIME_MANIFEST);
527
- await fs.mkdir(directory, { recursive: true });
528
- await fs.writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}
707
+ const fs3 = await import("fs/promises");
708
+ const manifestPath = path5.join(directory, FARM_ROUTE_RUNTIME_MANIFEST);
709
+ await fs3.mkdir(directory, { recursive: true });
710
+ await fs3.writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}
529
711
  `);
530
712
  return manifestPath;
531
713
  }
@@ -563,14 +745,14 @@ function normalizeManifestSource(root, modulePath) {
563
745
  const queryIndex = modulePath.indexOf("?");
564
746
  const filePath = queryIndex === -1 ? modulePath : modulePath.slice(0, queryIndex);
565
747
  const query = queryIndex === -1 ? "" : modulePath.slice(queryIndex);
566
- const relativePath = path3.isAbsolute(filePath) ? path3.relative(root, filePath) : filePath;
748
+ const relativePath = path5.isAbsolute(filePath) ? path5.relative(root, filePath) : filePath;
567
749
  return `${relativePath.replace(/\\/g, "/")}${query}`;
568
750
  }
569
751
  __name(normalizeManifestSource, "normalizeManifestSource");
570
752
 
571
753
  // src/nitro/vercel-route-runtime.ts
572
- import path4 from "path";
573
- async function createFarmVercelRouteRuntimeFunctions(outputDir, manifest, fs, basePath = "/") {
754
+ import path6 from "path";
755
+ async function createFarmVercelRouteRuntimeFunctions(outputDir, manifest, fs3, basePath = "/") {
574
756
  const dynamicRoutes = manifest.routes.filter(
575
757
  (route) => route.rendering === "dynamic" && route.runtime !== "edge"
576
758
  );
@@ -589,8 +771,8 @@ async function createFarmVercelRouteRuntimeFunctions(outputDir, manifest, fs, ba
589
771
  group.routes.push(route);
590
772
  groups.set(key, group);
591
773
  }
592
- const functionsDir = path4.join(outputDir, "functions");
593
- const baseFunctionDir = path4.join(functionsDir, "__nitro.func");
774
+ const functionsDir = path6.join(outputDir, "functions");
775
+ const baseFunctionDir = path6.join(functionsDir, "__nitro.func");
594
776
  const destinations = /* @__PURE__ */ new Map();
595
777
  let groupIndex = 0;
596
778
  for (const [key, group] of groups) {
@@ -600,9 +782,9 @@ async function createFarmVercelRouteRuntimeFunctions(outputDir, manifest, fs, ba
600
782
  }
601
783
  groupIndex += 1;
602
784
  const functionName = `__farm_runtime_${groupIndex}`;
603
- const functionDir = path4.join(functionsDir, `${functionName}.func`);
604
- await fs.cp(baseFunctionDir, functionDir, { recursive: true, force: true });
605
- await configureVercelFunction(functionDir, group.config, fs);
785
+ const functionDir = path6.join(functionsDir, `${functionName}.func`);
786
+ await fs3.cp(baseFunctionDir, functionDir, { recursive: true, force: true });
787
+ await configureVercelFunction(functionDir, group.config, fs3);
606
788
  destinations.set(key, `/${functionName}`);
607
789
  }
608
790
  const routes = [];
@@ -651,15 +833,15 @@ function farmRoutePatternToVercelSource(pattern, basePath = "/") {
651
833
  return source === "/" ? normalizedBasePath : `${normalizedBasePath}${source}`;
652
834
  }
653
835
  __name(farmRoutePatternToVercelSource, "farmRoutePatternToVercelSource");
654
- async function configureVercelFunction(functionDir, config, fs) {
655
- const configPath = path4.join(functionDir, ".vc-config.json");
656
- const current = JSON.parse(await fs.readFile(configPath, "utf8"));
836
+ async function configureVercelFunction(functionDir, config, fs3) {
837
+ const configPath = path6.join(functionDir, ".vc-config.json");
838
+ const current = JSON.parse(await fs3.readFile(configPath, "utf8"));
657
839
  const next = {
658
840
  ...current,
659
841
  ...config.regions?.length ? { regions: config.regions } : {},
660
842
  ...config.maxDuration ? { maxDuration: config.maxDuration } : {}
661
843
  };
662
- await fs.writeFile(configPath, `${JSON.stringify(next, null, 2)}
844
+ await fs3.writeFile(configPath, `${JSON.stringify(next, null, 2)}
663
845
  `);
664
846
  }
665
847
  __name(configureVercelFunction, "configureVercelFunction");
@@ -736,10 +918,10 @@ __name(buildFarmVercelRoutes, "buildFarmVercelRoutes");
736
918
 
737
919
  // src/nitro/netlify-entry.ts
738
920
  import { existsSync } from "fs";
739
- import path5 from "path";
921
+ import path7 from "path";
740
922
  function resolveNitroNetlifyEntry(nitroRuntimeEntry) {
741
- const entry = path5.join(
742
- path5.dirname(nitroRuntimeEntry),
923
+ const entry = path7.join(
924
+ path7.dirname(nitroRuntimeEntry),
743
925
  "..",
744
926
  "presets",
745
927
  "netlify",
@@ -751,7 +933,7 @@ function resolveNitroNetlifyEntry(nitroRuntimeEntry) {
751
933
  `[Farm.js] Could not find Nitro's Netlify function entry at ${entry}. Farm wraps it so private responses are never cached by Netlify's CDN; reinstall dependencies or report the installed Nitro version.`
752
934
  );
753
935
  }
754
- return entry.split(path5.sep).join("/");
936
+ return entry.split(path7.sep).join("/");
755
937
  }
756
938
  __name(resolveNitroNetlifyEntry, "resolveNitroNetlifyEntry");
757
939
  function createFarmNetlifyEntry(options) {
@@ -759,15 +941,32 @@ function createFarmNetlifyEntry(options) {
759
941
  import nitroNetlifyHandler from ${JSON.stringify(options.nitroNetlifyEntry)};
760
942
 
761
943
  const PRIVATE_CACHE_DIRECTIVE = /(?:^|,)\\s*(?:private|no-store)\\s*(?:[,=]|$)/i;
944
+ const CREDENTIAL_VARY = /(?:^|,)\\s*(?:\\*|cookie|authorization)\\s*(?:,|$)/i;
945
+ // What Nitro's entry sets when the response has no Cache-Control of its own.
946
+ const NITRO_DEFAULT_CACHE_CONTROL = "public, max-age=0, must-revalidate";
947
+
948
+ function isSharedCacheable(request, response) {
949
+ return (
950
+ response.status === 200 &&
951
+ !request.headers.has("cookie") &&
952
+ !request.headers.has("authorization") &&
953
+ !response.headers.has("set-cookie") &&
954
+ !PRIVATE_CACHE_DIRECTIVE.test(response.headers.get("cache-control") || "") &&
955
+ !CREDENTIAL_VARY.test(response.headers.get("vary") || "")
956
+ );
957
+ }
762
958
 
763
959
  export default async function farmNetlifyHandler(request, context) {
764
960
  const response = await nitroNetlifyHandler(request, context);
765
961
  if (
766
962
  response &&
767
963
  response.headers.has("netlify-cdn-cache-control") &&
768
- PRIVATE_CACHE_DIRECTIVE.test(response.headers.get("cache-control") || "")
964
+ !isSharedCacheable(request, response)
769
965
  ) {
770
966
  response.headers.delete("netlify-cdn-cache-control");
967
+ if (response.headers.get("cache-control") === NITRO_DEFAULT_CACHE_CONTROL) {
968
+ response.headers.set("cache-control", "private, no-store");
969
+ }
771
970
  }
772
971
  return response;
773
972
  }
@@ -775,278 +974,6 @@ export default async function farmNetlifyHandler(request, context) {
775
974
  }
776
975
  __name(createFarmNetlifyEntry, "createFarmNetlifyEntry");
777
976
 
778
- // src/nitro/node-server-entry.ts
779
- var FARM_NODE_ENV_MODULE_FILE = "farm-node-env.mjs";
780
- var FARM_NODE_ENV_MODULE_SOURCE = `if (!process.env.NODE_ENV) process.env.NODE_ENV = "production";
781
- `;
782
- function createFarmNodeServerEntry(options) {
783
- const serverConfig = JSON.stringify(options.server);
784
- const nitroEntryImport = `./${options.nitroEntryFile.replace(/^\.\//, "")}`;
785
- return `
786
- import "./${FARM_NODE_ENV_MODULE_FILE}";
787
- import "#nitro/virtual/polyfills";
788
- import { NodeRequest, serve } from ${JSON.stringify(options.nodeAdapterModule)};
789
- import wsAdapter from ${JSON.stringify(options.websocketAdapterModule)};
790
- import { resolveWebsocketHooks, useNitroApp, useNitroHooks } from "#nitro/runtime/app";
791
- import { useRuntimeConfig } from "#nitro/runtime/runtime-config";
792
- import { trapUnhandledErrors } from "#nitro/runtime/error/hooks";
793
- import { setupCloseHooks } from "#nitro/runtime/shutdown";
794
- import { startScheduleRunner } from "#nitro/runtime/task";
795
- import { tracingSrvxPlugins } from "#nitro/virtual/tracing";
796
- import { farmProductionLifecycle } from ${JSON.stringify(nitroEntryImport)};
797
-
798
- const farmServerConfig = ${serverConfig};
799
- if (!process.env.NITRO_SHUTDOWN_TIMEOUT) {
800
- process.env.NITRO_SHUTDOWN_TIMEOUT = String(farmServerConfig.gracefulShutdownTimeout);
801
- }
802
- const shutdownConfig = {
803
- disabled: Boolean(process.env.NITRO_SHUTDOWN_DISABLED),
804
- signals: (process.env.NITRO_SHUTDOWN_SIGNALS || "SIGTERM SIGINT")
805
- .split(" ")
806
- .map((signal) => signal.trim())
807
- .filter(Boolean),
808
- timeout: Number.parseInt(process.env.NITRO_SHUTDOWN_TIMEOUT || "", 10) || 30000,
809
- forceExit: !process.env.NITRO_SHUTDOWN_NO_FORCE_EXIT,
810
- };
811
-
812
- const nitroApp = useNitroApp();
813
- useNitroHooks().hook("close", async () => {
814
- try {
815
- await farmProductionLifecycle.close("production-server-closed");
816
- } catch (error) {
817
- process.exitCode = 1;
818
- throw error;
819
- }
820
- });
821
-
822
- let startupSignal;
823
- let resolveStartupSignal;
824
- const startupSignalPromise = new Promise((resolve) => {
825
- resolveStartupSignal = resolve;
826
- });
827
- const startupSignalListeners = new Map();
828
- if (!shutdownConfig.disabled) {
829
- for (const signal of shutdownConfig.signals) {
830
- const listener = (receivedSignal) => {
831
- if (!startupSignal) {
832
- startupSignal = receivedSignal;
833
- resolveStartupSignal(receivedSignal);
834
- }
835
- farmProductionLifecycle.beginDrain(receivedSignal);
836
- };
837
- startupSignalListeners.set(signal, listener);
838
- process.once(signal, listener);
839
- }
840
- }
841
-
842
- try {
843
- await Promise.race([
844
- Promise.resolve().then(() => farmProductionLifecycle.start()),
845
- startupSignalPromise,
846
- ]);
847
- } catch (error) {
848
- await farmProductionLifecycle.close("production-start-failed").catch((closeError) => {
849
- console.error("[Farm] Runtime cleanup after startup failure failed:", closeError);
850
- });
851
- throw error;
852
- } finally {
853
- for (const [signal, listener] of startupSignalListeners) {
854
- process.removeListener(signal, listener);
855
- }
856
- }
857
-
858
- if (startupSignal) {
859
- let startupCloseTimer;
860
- const startupCloseCompleted = await Promise.race([
861
- Promise.resolve()
862
- .then(() => farmProductionLifecycle.close(startupSignal))
863
- .then(
864
- () => true,
865
- (error) => {
866
- console.error("[Farm] Runtime shutdown during startup failed:", error);
867
- process.exitCode = 1;
868
- return true;
869
- },
870
- ),
871
- new Promise((resolve) => {
872
- startupCloseTimer = setTimeout(() => resolve(false), farmServerConfig.gracefulShutdownTimeout);
873
- }),
874
- ]);
875
- clearTimeout(startupCloseTimer);
876
- if (!startupCloseCompleted) {
877
- console.warn("[Farm] Runtime startup did not settle before shutdown; forcing cleanup");
878
- let forcedCloseTimer;
879
- const forcedCloseCompleted = await Promise.race([
880
- Promise.resolve()
881
- .then(() => farmProductionLifecycle.forceClose(startupSignal))
882
- .then(
883
- () => true,
884
- (error) => {
885
- console.error("[Farm] Forced runtime shutdown during startup failed:", error);
886
- process.exitCode = 1;
887
- return true;
888
- },
889
- ),
890
- new Promise((resolve) => {
891
- forcedCloseTimer = setTimeout(
892
- () => resolve(false),
893
- farmServerConfig.gracefulShutdownTimeout,
894
- );
895
- }),
896
- ]);
897
- clearTimeout(forcedCloseTimer);
898
- if (!forcedCloseCompleted) {
899
- console.error("[Farm] Forced runtime shutdown during startup timed out");
900
- process.exitCode = 1;
901
- }
902
- }
903
- process.exit(process.exitCode || 0);
904
- }
905
-
906
- const cert = process.env.NITRO_SSL_CERT;
907
- const key = process.env.NITRO_SSL_KEY;
908
- const configuredPort = Number(process.env.NITRO_PORT || process.env.PORT);
909
- const port = Number.isFinite(configuredPort) && configuredPort > 0 ? configuredPort : 3000;
910
- const host = process.env.NITRO_HOST || process.env.HOST;
911
- const socketPath = process.env.NITRO_UNIX_SOCKET;
912
- const server = serve({
913
- manual: true,
914
- silent: true,
915
- gracefulShutdown: false,
916
- port,
917
- hostname: host,
918
- node: socketPath ? { path: socketPath } : undefined,
919
- tls: cert && key ? { cert, key } : undefined,
920
- fetch: nitroApp.fetch,
921
- plugins: [...tracingSrvxPlugins],
922
- });
923
- const nodeServer = server.node?.server;
924
- if (!nodeServer) throw new Error("[Farm] Nitro did not create a Node server");
925
-
926
- nodeServer.headersTimeout = farmServerConfig.headersTimeout;
927
- nodeServer.requestTimeout = farmServerConfig.requestTimeout;
928
- nodeServer.keepAliveTimeout = farmServerConfig.keepAliveTimeout;
929
-
930
- let isShuttingDown = false;
931
- nodeServer.on("request", (_request, response) => {
932
- response.once("finish", () => {
933
- if (isShuttingDown) nodeServer.closeIdleConnections?.();
934
- });
935
- });
936
-
937
- if (import.meta._websocket) {
938
- const { handleUpgrade } = wsAdapter({ resolve: resolveWebsocketHooks });
939
- nodeServer.on("upgrade", (request, socket, head) => {
940
- handleUpgrade(
941
- request,
942
- socket,
943
- head,
944
- new NodeRequest({ req: request, upgrade: { socket, head } }),
945
- );
946
- });
947
- }
948
-
949
- setupCloseHooks(server);
950
- trapUnhandledErrors();
951
-
952
- let shutdownPromise;
953
- async function shutdown(signal) {
954
- isShuttingDown = true;
955
- farmProductionLifecycle.beginDrain(signal);
956
-
957
- const gracefulClose = server.close().then(
958
- () => true,
959
- (error) => {
960
- console.error("[Farm] Runtime shutdown failed:", error);
961
- process.exitCode = 1;
962
- return true;
963
- },
964
- );
965
- nodeServer.closeIdleConnections?.();
966
- let gracefulTimer;
967
- const gracefullyClosed = await Promise.race([
968
- gracefulClose,
969
- new Promise((resolve) => {
970
- gracefulTimer = setTimeout(() => resolve(false), shutdownConfig.timeout);
971
- }),
972
- ]);
973
- clearTimeout(gracefulTimer);
974
-
975
- if (!gracefullyClosed) {
976
- console.warn("[Farm] Graceful shutdown timed out; forcing cleanup");
977
- void server.close(true).catch((error) => {
978
- console.error("[Farm] Forced server shutdown failed:", error);
979
- process.exitCode = 1;
980
- });
981
-
982
- let forceTimer;
983
- const forceClosed = await Promise.race([
984
- Promise.resolve()
985
- .then(() => farmProductionLifecycle.forceClose("production-server-closed"))
986
- .then(
987
- () => true,
988
- (error) => {
989
- console.error("[Farm] Forced runtime shutdown failed:", error);
990
- process.exitCode = 1;
991
- return true;
992
- },
993
- ),
994
- new Promise((resolve) => {
995
- forceTimer = setTimeout(() => resolve(false), shutdownConfig.timeout);
996
- }),
997
- ]);
998
- clearTimeout(forceTimer);
999
- if (!forceClosed) {
1000
- console.error("[Farm] Forced runtime shutdown timed out");
1001
- process.exitCode = 1;
1002
- }
1003
- }
1004
-
1005
- if (shutdownConfig.forceExit) process.exit(process.exitCode || 0);
1006
- }
1007
-
1008
- if (!shutdownConfig.disabled) {
1009
- for (const signal of shutdownConfig.signals) {
1010
- process.once(signal, (receivedSignal) => {
1011
- shutdownPromise ||= shutdown(receivedSignal);
1012
- });
1013
- }
1014
- }
1015
-
1016
- try {
1017
- await server.serve();
1018
- const protocol = cert && key ? "https" : "http";
1019
- const addressInfo = nodeServer.address();
1020
- if (typeof addressInfo === "string") {
1021
- console.log(\`Listening on unix socket \${addressInfo}\`);
1022
- } else if (addressInfo) {
1023
- const configuredBaseURL = useRuntimeConfig().app.baseURL || "";
1024
- const baseURL = configuredBaseURL.endsWith("/")
1025
- ? configuredBaseURL.slice(0, -1)
1026
- : configuredBaseURL;
1027
- const address = addressInfo.family === "IPv6"
1028
- ? \`[\${addressInfo.address}]\`
1029
- : addressInfo.address;
1030
- console.log(\`Listening on \${protocol}://\${address}:\${addressInfo.port}\${baseURL}\`);
1031
- }
1032
- } catch (error) {
1033
- console.error(error);
1034
- process.exitCode = 1;
1035
- await farmProductionLifecycle.close("production-listen-error").catch((closeError) => {
1036
- console.error("[Farm] Runtime cleanup after listen failure failed:", closeError);
1037
- });
1038
- throw error;
1039
- }
1040
-
1041
- if (import.meta._tasks) {
1042
- startScheduleRunner({ waitUntil: server.waitUntil });
1043
- }
1044
-
1045
- export default {};
1046
- `.trim();
1047
- }
1048
- __name(createFarmNodeServerEntry, "createFarmNodeServerEntry");
1049
-
1050
977
  // src/nitro/universal-build.ts
1051
978
  function preloadFarmNitroBuilder() {
1052
979
  return import("nitro/builder").then(
@@ -1056,18 +983,18 @@ function preloadFarmNitroBuilder() {
1056
983
  }
1057
984
  __name(preloadFarmNitroBuilder, "preloadFarmNitroBuilder");
1058
985
  var _filename = typeof import.meta.url !== "undefined" ? fileURLToPath(import.meta.url) : "";
1059
- var _dirname = path6.dirname(_filename);
986
+ var _dirname = path8.dirname(_filename);
1060
987
  function findFarmCoreRoot(from) {
1061
- let dir = path6.dirname(from);
1062
- while (dir !== path6.dirname(dir)) {
1063
- const manifest = path6.join(dir, "package.json");
988
+ let dir = path8.dirname(from);
989
+ while (dir !== path8.dirname(dir)) {
990
+ const manifest = path8.join(dir, "package.json");
1064
991
  if (existsSync2(manifest)) {
1065
992
  try {
1066
993
  if (JSON.parse(readFileSync(manifest, "utf8")).name === "@farm.js/core") return dir;
1067
994
  } catch {
1068
995
  }
1069
996
  }
1070
- dir = path6.dirname(dir);
997
+ dir = path8.dirname(dir);
1071
998
  }
1072
999
  return null;
1073
1000
  }
@@ -1079,16 +1006,16 @@ function toModulePath(file) {
1079
1006
  }
1080
1007
  __name(toModulePath, "toModulePath");
1081
1008
  function findInstalledPackageDir(name, from) {
1082
- for (let dir = from; ; dir = path6.dirname(dir)) {
1083
- const candidate = path6.join(dir, "node_modules", name);
1084
- if (existsSync2(path6.join(candidate, "package.json"))) {
1009
+ for (let dir = from; ; dir = path8.dirname(dir)) {
1010
+ const candidate = path8.join(dir, "node_modules", name);
1011
+ if (existsSync2(path8.join(candidate, "package.json"))) {
1085
1012
  try {
1086
1013
  return realpathSync(candidate);
1087
1014
  } catch {
1088
1015
  return null;
1089
1016
  }
1090
1017
  }
1091
- if (dir === path6.dirname(dir)) return null;
1018
+ if (dir === path8.dirname(dir)) return null;
1092
1019
  }
1093
1020
  }
1094
1021
  __name(findInstalledPackageDir, "findInstalledPackageDir");
@@ -1100,7 +1027,7 @@ function collectFarmDependencyDirs(root) {
1100
1027
  seen.add(dir);
1101
1028
  let manifest;
1102
1029
  try {
1103
- manifest = JSON.parse(readFileSync(path6.join(dir, "package.json"), "utf8"));
1030
+ manifest = JSON.parse(readFileSync(path8.join(dir, "package.json"), "utf8"));
1104
1031
  } catch {
1105
1032
  return;
1106
1033
  }
@@ -1111,7 +1038,7 @@ function collectFarmDependencyDirs(root) {
1111
1038
  if (farmCoreRoot) visit(realpathSync(farmCoreRoot));
1112
1039
  queue.push({ name: "@farm.js/core", from: root });
1113
1040
  try {
1114
- const manifest = JSON.parse(readFileSync(path6.join(root, "package.json"), "utf8"));
1041
+ const manifest = JSON.parse(readFileSync(path8.join(root, "package.json"), "utf8"));
1115
1042
  for (const field of ["dependencies", "devDependencies"]) {
1116
1043
  for (const name of Object.keys(manifest[field] ?? {})) {
1117
1044
  if (name.startsWith("@farm.js/")) queue.push({ name, from: root });
@@ -1178,15 +1105,15 @@ var FARM_SSR_PACKAGE_IMPORT = "#farm-ssr-entry";
1178
1105
  var FARM_SSR_OUTPUT_DIR = "farm-ssr";
1179
1106
  var FARM_CLIENT_BUILD_TARGET = ["es2020", "edge88", "firefox78", "chrome87", "safari14"];
1180
1107
  function resolveNitroRuntimeDependency(root, specifier) {
1181
- return createRequire(resolveNitroPackageEntry(root)).resolve(specifier).split(path6.sep).join("/");
1108
+ return createRequire(resolveNitroPackageEntry(root)).resolve(specifier).split(path8.sep).join("/");
1182
1109
  }
1183
1110
  __name(resolveNitroRuntimeDependency, "resolveNitroRuntimeDependency");
1184
1111
  function resolveNitroInternalRuntimeAliases(root) {
1185
- const runtimeDir = path6.dirname(resolveNitroPackageEntry(root));
1112
+ const runtimeDir = path8.dirname(resolveNitroPackageEntry(root));
1186
1113
  return Object.fromEntries(
1187
1114
  ["app", "error/hooks", "runtime-config", "shutdown", "task"].map((moduleName) => [
1188
1115
  `#nitro/runtime/${moduleName}`,
1189
- path6.join(runtimeDir, "internal", `${moduleName}.mjs`).split(path6.sep).join("/")
1116
+ path8.join(runtimeDir, "internal", `${moduleName}.mjs`).split(path8.sep).join("/")
1190
1117
  ])
1191
1118
  );
1192
1119
  }
@@ -1197,7 +1124,7 @@ function createPrerenderRuntimeResolverPlugin(root, resolveNitroEntry = resolveN
1197
1124
  name: "farm-prerender-runtime-resolver",
1198
1125
  async resolveId(id, _importer, options) {
1199
1126
  if (options.custom?.farmPrerenderRuntimeResolve) return null;
1200
- if (id.startsWith("\0") || id.startsWith(".") || id.startsWith("#") || id.startsWith("virtual:") || path6.isAbsolute(id) || NODE_BUILTIN_MODULES.has(id)) {
1127
+ if (id.startsWith("\0") || id.startsWith(".") || id.startsWith("#") || id.startsWith("virtual:") || path8.isAbsolute(id) || NODE_BUILTIN_MODULES.has(id)) {
1201
1128
  return null;
1202
1129
  }
1203
1130
  if (nitroEntry === void 0) {
@@ -1218,7 +1145,7 @@ function createPrerenderRuntimeResolverPlugin(root, resolveNitroEntry = resolveN
1218
1145
  }
1219
1146
  __name(createPrerenderRuntimeResolverPlugin, "createPrerenderRuntimeResolverPlugin");
1220
1147
  function resolveNitroPackageEntry(root) {
1221
- const projectRequire = createRequire(path6.join(root, "package.json"));
1148
+ const projectRequire = createRequire(path8.join(root, "package.json"));
1222
1149
  let runtimeRequire = projectRequire;
1223
1150
  try {
1224
1151
  runtimeRequire = createRequire(projectRequire.resolve("@farm.js/core"));
@@ -1293,7 +1220,7 @@ function createFarmReactWebServerAlias(hasEdgeBuild) {
1293
1220
  __name(createFarmReactWebServerAlias, "createFarmReactWebServerAlias");
1294
1221
  function hasReactDomEdgeServerBuild(root) {
1295
1222
  try {
1296
- createRequire(path6.join(root, "package.json")).resolve("react-dom/server.edge");
1223
+ createRequire(path8.join(root, "package.json")).resolve("react-dom/server.edge");
1297
1224
  return true;
1298
1225
  } catch {
1299
1226
  return false;
@@ -1351,7 +1278,7 @@ function createMetadataImageWasmPlugin() {
1351
1278
  return null;
1352
1279
  }
1353
1280
  const requestPath = source.slice(0, -"?module".length);
1354
- const resolvedPath = path6.isAbsolute(requestPath) ? requestPath : path6.resolve(path6.dirname(importer.split("?", 1)[0]), requestPath);
1281
+ const resolvedPath = path8.isAbsolute(requestPath) ? requestPath : path8.resolve(path8.dirname(importer.split("?", 1)[0]), requestPath);
1355
1282
  return `${FARM_METADATA_IMAGE_WASM_PREFIX}${resolvedPath}`;
1356
1283
  },
1357
1284
  load(id) {
@@ -1377,11 +1304,11 @@ function collectSSRExternalPackages(ssrBundle) {
1377
1304
  for (const importId of [...output.imports, ...output.dynamicImports]) {
1378
1305
  const normalizedImportId = importId.replace(/\\/g, "/");
1379
1306
  const normalizedId = normalizedImportId.replace(/^\.\//, "");
1380
- const resolvedRelativeId = normalizedImportId.startsWith("./") || normalizedImportId.startsWith("../") ? path6.posix.normalize(path6.posix.join(path6.posix.dirname(fileName), normalizedImportId)) : null;
1307
+ const resolvedRelativeId = normalizedImportId.startsWith("./") || normalizedImportId.startsWith("../") ? path8.posix.normalize(path8.posix.join(path8.posix.dirname(fileName), normalizedImportId)) : null;
1381
1308
  if (emittedFiles.has(normalizedId) || resolvedRelativeId !== null && emittedFiles.has(resolvedRelativeId) || NODE_BUILTIN_MODULES.has(importId) || importId.startsWith("node:")) {
1382
1309
  continue;
1383
1310
  }
1384
- if (path6.isAbsolute(importId) || /^[A-Za-z]:[\\/]/.test(importId) || importId.startsWith("#") || importId.startsWith("\0")) {
1311
+ if (path8.isAbsolute(importId) || /^[A-Za-z]:[\\/]/.test(importId) || importId.startsWith("#") || importId.startsWith("\0")) {
1385
1312
  externalPackages.add(importId);
1386
1313
  continue;
1387
1314
  }
@@ -1394,15 +1321,15 @@ function collectSSRExternalPackages(ssrBundle) {
1394
1321
  }
1395
1322
  __name(collectSSRExternalPackages, "collectSSRExternalPackages");
1396
1323
  function createExternalSSRBundlePlugin(nitroEntryPath, ssrOutputDir, ssrEntryFile) {
1397
- const resolvedNitroEntry = path6.resolve(nitroEntryPath);
1398
- const resolvedSSREntry = path6.resolve(ssrOutputDir, ssrEntryFile);
1324
+ const resolvedNitroEntry = path8.resolve(nitroEntryPath);
1325
+ const resolvedSSREntry = path8.resolve(ssrOutputDir, ssrEntryFile);
1399
1326
  return {
1400
1327
  name: "farm-externalize-prebuilt-ssr",
1401
1328
  resolveId(source, importer) {
1402
- if (!importer || path6.resolve(importer) !== resolvedNitroEntry) {
1329
+ if (!importer || path8.resolve(importer) !== resolvedNitroEntry) {
1403
1330
  return null;
1404
1331
  }
1405
- const resolvedImport = path6.resolve(path6.dirname(importer), source);
1332
+ const resolvedImport = path8.resolve(path8.dirname(importer), source);
1406
1333
  if (resolvedImport !== resolvedSSREntry) return null;
1407
1334
  return { id: FARM_SSR_PACKAGE_IMPORT, external: true };
1408
1335
  }
@@ -1530,13 +1457,13 @@ function resolveBuildDocsContentDir(config, root) {
1530
1457
  if (!config.docs?.enabled) return null;
1531
1458
  const configuredContentDir = config.docs.contentDir || config.docs.config.contentDir;
1532
1459
  if (typeof configuredContentDir === "string" && configuredContentDir.trim()) {
1533
- const contentDir = path6.isAbsolute(configuredContentDir) ? configuredContentDir : path6.join(root, configuredContentDir);
1460
+ const contentDir = path8.isAbsolute(configuredContentDir) ? configuredContentDir : path8.join(root, configuredContentDir);
1534
1461
  return existsSync2(contentDir) ? contentDir : null;
1535
1462
  }
1536
1463
  const entryDir = config.docs.config.entry || trimSlashes(config.docs.entry) || "docs";
1537
- const appDocsDir = path6.join(root, config.srcDir || "src", "app", entryDir);
1464
+ const appDocsDir = path8.join(root, config.srcDir || "src", "app", entryDir);
1538
1465
  if (existsSync2(appDocsDir)) return appDocsDir;
1539
- const rootDocsDir = path6.join(root, entryDir);
1466
+ const rootDocsDir = path8.join(root, entryDir);
1540
1467
  return existsSync2(rootDocsDir) ? rootDocsDir : null;
1541
1468
  }
1542
1469
  __name(resolveBuildDocsContentDir, "resolveBuildDocsContentDir");
@@ -1554,7 +1481,7 @@ function hasProjectPostcssConfig(root) {
1554
1481
  ".postcssrc.mjs",
1555
1482
  ".postcssrc.ts"
1556
1483
  ];
1557
- const projectRequire = createRequire(path6.join(root, "package.json"));
1484
+ const projectRequire = createRequire(path8.join(root, "package.json"));
1558
1485
  return candidates.some((file) => {
1559
1486
  try {
1560
1487
  projectRequire.resolve(`./${file}`);
@@ -1566,7 +1493,7 @@ function hasProjectPostcssConfig(root) {
1566
1493
  }
1567
1494
  __name(hasProjectPostcssConfig, "hasProjectPostcssConfig");
1568
1495
  async function findFarmConfigPath(root) {
1569
- const fs = await import("fs/promises");
1496
+ const fs3 = await import("fs/promises");
1570
1497
  const candidates = [
1571
1498
  "farm.config.ts",
1572
1499
  "farm.config.mts",
@@ -1578,9 +1505,9 @@ async function findFarmConfigPath(root) {
1578
1505
  "config.mjs"
1579
1506
  ];
1580
1507
  for (const candidate of candidates) {
1581
- const resolvedPath = path6.join(root, candidate);
1508
+ const resolvedPath = path8.join(root, candidate);
1582
1509
  try {
1583
- await fs.access(resolvedPath);
1510
+ await fs3.access(resolvedPath);
1584
1511
  return resolvedPath;
1585
1512
  } catch {
1586
1513
  }
@@ -1588,15 +1515,6 @@ async function findFarmConfigPath(root) {
1588
1515
  return null;
1589
1516
  }
1590
1517
  __name(findFarmConfigPath, "findFarmConfigPath");
1591
- function hasFarmMiddlewareConfig(config) {
1592
- if (!config) return false;
1593
- if (Array.isArray(config)) return config.length > 0;
1594
- const configRecord = config;
1595
- return Boolean(
1596
- configRecord.matcher || configRecord.exclude || configRecord.runtime || configRecord.handler || Array.isArray(configRecord.handlers) && configRecord.handlers.length > 0
1597
- );
1598
- }
1599
- __name(hasFarmMiddlewareConfig, "hasFarmMiddlewareConfig");
1600
1518
  function hasFarmServerRuntimePlugins(config) {
1601
1519
  return (config.plugins || []).some((plugin) => {
1602
1520
  if (getFarmIntegrationPluginServerRuntime(plugin) === false) return false;
@@ -1617,13 +1535,13 @@ function farmServerRuntimePluginsMayHandlePath(config, pathname) {
1617
1535
  }
1618
1536
  __name(farmServerRuntimePluginsMayHandlePath, "farmServerRuntimePluginsMayHandlePath");
1619
1537
  async function discoverMiddlewareRoutes(appDir) {
1620
- const fs = await import("fs/promises");
1538
+ const fs3 = await import("fs/promises");
1621
1539
  const appDirs = Array.isArray(appDir) ? [...appDir] : [appDir];
1622
1540
  const routes = /* @__PURE__ */ new Map();
1623
1541
  async function walk(dir, routePath, directory, discovered) {
1624
1542
  let entries;
1625
1543
  try {
1626
- entries = await fs.readdir(dir, { withFileTypes: true });
1544
+ entries = await fs3.readdir(dir, { withFileTypes: true });
1627
1545
  } catch {
1628
1546
  return;
1629
1547
  }
@@ -1634,7 +1552,7 @@ async function discoverMiddlewareRoutes(appDir) {
1634
1552
  discovered.push({
1635
1553
  path: routePath,
1636
1554
  directory,
1637
- filePath: path6.join(dir, middlewareFile.name)
1555
+ filePath: path8.join(dir, middlewareFile.name)
1638
1556
  });
1639
1557
  }
1640
1558
  for (const entry of entries) {
@@ -1642,7 +1560,7 @@ async function discoverMiddlewareRoutes(appDir) {
1642
1560
  continue;
1643
1561
  }
1644
1562
  await walk(
1645
- path6.join(dir, entry.name),
1563
+ path8.join(dir, entry.name),
1646
1564
  appendMiddlewareRoutePath(routePath, entry.name),
1647
1565
  appendMiddlewareDirectory(directory, entry.name),
1648
1566
  discovered
@@ -1719,21 +1637,21 @@ async function buildUniversal(config, routeManager, apiRouteManager, serverRende
1719
1637
  })
1720
1638
  );
1721
1639
  logger.info(`\u{1F4CB} Found ${pageRoutes.length} page routes`);
1722
- const fs = await import("fs/promises");
1640
+ const fs3 = await import("fs/promises");
1723
1641
  const layoutRoutes = [];
1724
- const appDir = path6.join(root, srcDir, "app");
1642
+ const appDir = path8.join(root, srcDir, "app");
1725
1643
  async function findLayoutsForClient(dir, routePrefix = "/") {
1726
1644
  try {
1727
- const entries = await fs.readdir(dir, { withFileTypes: true });
1645
+ const entries = await fs3.readdir(dir, { withFileTypes: true });
1728
1646
  for (const entry of entries) {
1729
1647
  if (entry.isFile() && entry.name.match(/^layout\.(tsx?|jsx?|vue|svelte)$/)) {
1730
1648
  layoutRoutes.push({
1731
1649
  pattern: routePrefix,
1732
- modulePath: path6.join(dir, entry.name)
1650
+ modulePath: path8.join(dir, entry.name)
1733
1651
  });
1734
1652
  } else if (entry.isDirectory() && !entry.name.startsWith(".") && !entry.name.startsWith("_")) {
1735
1653
  const childPrefix = routePrefix === "/" ? `/${entry.name}` : `${routePrefix}/${entry.name}`;
1736
- await findLayoutsForClient(path6.join(dir, entry.name), childPrefix);
1654
+ await findLayoutsForClient(path8.join(dir, entry.name), childPrefix);
1737
1655
  }
1738
1656
  }
1739
1657
  } catch {
@@ -1750,7 +1668,7 @@ async function buildUniversal(config, routeManager, apiRouteManager, serverRende
1750
1668
  logger.info(`\u{1F4CB} Found ${pageRoutes.length} page routes and ${layoutRoutes.length} layouts`);
1751
1669
  const isolatedClientBoundaryModules = routeManager.getIsolatedClientBoundaryModules(root);
1752
1670
  const hydrationPlanCache = /* @__PURE__ */ new Map();
1753
- const clientOutputDir = path6.join(root, distDir, "client");
1671
+ const clientOutputDir = path8.join(root, distDir, "client");
1754
1672
  const [productionViteResult] = await productionViteResultPromise;
1755
1673
  if (productionViteResult.status === "rejected") {
1756
1674
  await routeRuntimeManifestResultPromise;
@@ -1859,10 +1777,10 @@ async function buildUniversal(config, routeManager, apiRouteManager, serverRende
1859
1777
  lifecyclePluginManager
1860
1778
  );
1861
1779
  const runtimeManifestPath = await writeFarmRouteRuntimeManifest(
1862
- path6.join(root, distDir),
1780
+ path8.join(root, distDir),
1863
1781
  routeRuntimeManifest
1864
1782
  );
1865
- logger.info(`\u{1F4CB} Route runtime manifest: ${path6.relative(root, runtimeManifestPath)}`);
1783
+ logger.info(`\u{1F4CB} Route runtime manifest: ${path8.relative(root, runtimeManifestPath)}`);
1866
1784
  } catch (error) {
1867
1785
  if (lifecyclePluginManager) {
1868
1786
  await lifecyclePluginManager.runHookParallel("onError", {
@@ -1882,50 +1800,50 @@ async function buildUniversal(config, routeManager, apiRouteManager, serverRende
1882
1800
  }
1883
1801
  __name(buildUniversal, "buildUniversal");
1884
1802
  async function writeSSRAssetsToClient(bundle, outputDir) {
1885
- const fs = await import("fs/promises");
1803
+ const fs3 = await import("fs/promises");
1886
1804
  for (const [fileName, output] of Object.entries(bundle)) {
1887
1805
  if (output.type !== "asset") continue;
1888
1806
  if (fileName === "farm-fonts.css") {
1889
1807
  await mergeBuiltFontCss(outputDir, output.source);
1890
1808
  continue;
1891
1809
  }
1892
- const filePath = path6.join(outputDir, fileName);
1893
- await fs.mkdir(path6.dirname(filePath), { recursive: true });
1894
- await fs.writeFile(filePath, output.source);
1810
+ const filePath = path8.join(outputDir, fileName);
1811
+ await fs3.mkdir(path8.dirname(filePath), { recursive: true });
1812
+ await fs3.writeFile(filePath, output.source);
1895
1813
  }
1896
1814
  }
1897
1815
  __name(writeSSRAssetsToClient, "writeSSRAssetsToClient");
1898
1816
  async function copyFarmDocsFontAssetsToClient(root, outputDir) {
1899
- const fs = await import("fs/promises");
1817
+ const fs3 = await import("fs/promises");
1900
1818
  await Promise.all(
1901
1819
  resolveFarmDocsFontAssets(root).map(async ({ sourcePath, url }) => {
1902
- const targetPath = path6.join(outputDir, url.replace(/^\/+/, ""));
1903
- await fs.mkdir(path6.dirname(targetPath), { recursive: true });
1904
- await fs.copyFile(sourcePath, targetPath);
1820
+ const targetPath = path8.join(outputDir, url.replace(/^\/+/, ""));
1821
+ await fs3.mkdir(path8.dirname(targetPath), { recursive: true });
1822
+ await fs3.copyFile(sourcePath, targetPath);
1905
1823
  })
1906
1824
  );
1907
1825
  }
1908
1826
  __name(copyFarmDocsFontAssetsToClient, "copyFarmDocsFontAssetsToClient");
1909
1827
  async function mergeBuiltFontCss(outputDir, fontCssSource) {
1910
- const fs = await import("fs/promises");
1911
- const fontCssPath = path6.join(outputDir, "farm-fonts.css");
1828
+ const fs3 = await import("fs/promises");
1829
+ const fontCssPath = path8.join(outputDir, "farm-fonts.css");
1912
1830
  let fontCss = fontCssSource;
1913
1831
  if (fontCss === void 0) {
1914
1832
  try {
1915
- fontCss = await fs.readFile(fontCssPath);
1833
+ fontCss = await fs3.readFile(fontCssPath);
1916
1834
  } catch {
1917
1835
  return;
1918
1836
  }
1919
1837
  }
1920
- const clientCssPath = path6.join(outputDir, "farm-client.css");
1838
+ const clientCssPath = path8.join(outputDir, "farm-client.css");
1921
1839
  let clientCss = "";
1922
1840
  try {
1923
- clientCss = await fs.readFile(clientCssPath, "utf8");
1841
+ clientCss = await fs3.readFile(clientCssPath, "utf8");
1924
1842
  } catch {
1925
1843
  }
1926
1844
  const normalizedFontCss = typeof fontCss === "string" ? fontCss : Buffer.from(fontCss).toString("utf8");
1927
- await fs.writeFile(fontCssPath, normalizedFontCss);
1928
- await fs.writeFile(clientCssPath, mergeFarmFontCss(clientCss, normalizedFontCss));
1845
+ await fs3.writeFile(fontCssPath, normalizedFontCss);
1846
+ await fs3.writeFile(clientCssPath, mergeFarmFontCss(clientCss, normalizedFontCss));
1929
1847
  }
1930
1848
  __name(mergeBuiltFontCss, "mergeBuiltFontCss");
1931
1849
  var _IncompleteClientBuildOutputError = class _IncompleteClientBuildOutputError extends Error {
@@ -1937,28 +1855,28 @@ var _IncompleteClientBuildOutputError = class _IncompleteClientBuildOutputError
1937
1855
  __name(_IncompleteClientBuildOutputError, "IncompleteClientBuildOutputError");
1938
1856
  var IncompleteClientBuildOutputError = _IncompleteClientBuildOutputError;
1939
1857
  async function validateClientBuildOutput(root, srcDir, outputDir) {
1940
- const fs = await import("fs/promises");
1858
+ const fs3 = await import("fs/promises");
1941
1859
  const fingerprinted = await findFingerprintedClientEntry(outputDir);
1942
- const clientEntryPath = path6.join(outputDir, fingerprinted ?? "farm-client.js");
1860
+ const clientEntryPath = path8.join(outputDir, fingerprinted ?? "farm-client.js");
1943
1861
  let clientEntrySize = 0;
1944
1862
  try {
1945
- const clientEntry = await fs.stat(clientEntryPath);
1863
+ const clientEntry = await fs3.stat(clientEntryPath);
1946
1864
  if (clientEntry.isFile()) clientEntrySize = clientEntry.size;
1947
1865
  } catch {
1948
1866
  }
1949
1867
  if (clientEntrySize === 0) {
1950
1868
  throw new IncompleteClientBuildOutputError("farm-client.js is missing or empty");
1951
1869
  }
1952
- const clientCssPath = path6.join(outputDir, "farm-client.css");
1953
- const globalsCssPath = path6.join(root, srcDir, "app", "globals.css");
1870
+ const clientCssPath = path8.join(outputDir, "farm-client.css");
1871
+ const globalsCssPath = path8.join(root, srcDir, "app", "globals.css");
1954
1872
  let expectsCss = false;
1955
1873
  try {
1956
- const globalsCss = await fs.readFile(globalsCssPath, "utf8");
1874
+ const globalsCss = await fs3.readFile(globalsCssPath, "utf8");
1957
1875
  expectsCss = globalsCss.replace(/\/\*[\s\S]*?\*\//g, "").trim().length > 0;
1958
1876
  } catch {
1959
1877
  }
1960
1878
  try {
1961
- const clientCss = await fs.stat(clientCssPath);
1879
+ const clientCss = await fs3.stat(clientCssPath);
1962
1880
  if (expectsCss && (!clientCss.isFile() || clientCss.size === 0)) {
1963
1881
  throw new IncompleteClientBuildOutputError("farm-client.css is empty");
1964
1882
  }
@@ -1967,12 +1885,12 @@ async function validateClientBuildOutput(root, srcDir, outputDir) {
1967
1885
  if (expectsCss) {
1968
1886
  throw new IncompleteClientBuildOutputError("farm-client.css is missing");
1969
1887
  }
1970
- await fs.writeFile(clientCssPath, "");
1888
+ await fs3.writeFile(clientCssPath, "");
1971
1889
  }
1972
1890
  }
1973
1891
  __name(validateClientBuildOutput, "validateClientBuildOutput");
1974
1892
  function getCachedClientModuleHydrationPlan(modulePath, root, mode, cache, options = {}) {
1975
- const key = `${path6.resolve(root)}\0${mode}\0${options.asyncOwnerIslands === true}\0${path6.resolve(modulePath)}`;
1893
+ const key = `${path8.resolve(root)}\0${mode}\0${options.asyncOwnerIslands === true}\0${path8.resolve(modulePath)}`;
1976
1894
  let plan = cache.get(key);
1977
1895
  if (!plan) {
1978
1896
  plan = getClientModuleHydrationPlan(modulePath, root, mode, options);
@@ -1985,7 +1903,7 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
1985
1903
  const viteBuild = productionVite.build;
1986
1904
  const { farmPlugin, farmServerOnlyEntriesPlugin } = await import("./vite.mjs");
1987
1905
  const { PluginManager: PluginManager2 } = await import("./plugin.mjs");
1988
- const fs = await import("fs/promises");
1906
+ const fs3 = await import("fs/promises");
1989
1907
  const pluginManager = new PluginManager2({
1990
1908
  config,
1991
1909
  isDev: false,
@@ -2211,10 +2129,10 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2211
2129
  logger.info(
2212
2130
  `\u{1F4F1} Total hydratable routes detected: ${clientPages.length} pages, ${clientLayouts.filter((layout) => layout.shouldHydrate || layout.hasIsolatedClientBoundaries).length} layouts, and ${clientRouteSlots.length} slots`
2213
2131
  );
2214
- const clientEntryRoot = path6.join(root, ".farm", "tmp");
2215
- await fs.mkdir(clientEntryRoot, { recursive: true });
2216
- const clientEntryDir = await fs.mkdtemp(path6.join(clientEntryRoot, "client-entry-"));
2217
- const clientEntryPath = path6.join(clientEntryDir, "farm-client-entry.tsx");
2132
+ const clientEntryRoot = path8.join(root, ".farm", "tmp");
2133
+ await fs3.mkdir(clientEntryRoot, { recursive: true });
2134
+ const clientEntryDir = await fs3.mkdtemp(path8.join(clientEntryRoot, "client-entry-"));
2135
+ const clientEntryPath = path8.join(clientEntryDir, "farm-client-entry.tsx");
2218
2136
  const clientHydrationCode = generateClientHydrationEntry(
2219
2137
  clientPages,
2220
2138
  clientLayouts,
@@ -2235,7 +2153,7 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2235
2153
  generateClientCachePersistenceCode(resolveFarmClientCacheAdapterEntry(root, config.cache)),
2236
2154
  adapterOwnsDocsRuntime ? getFarmDocsAdapterConfigModule(config.docs) : void 0
2237
2155
  );
2238
- await fs.writeFile(clientEntryPath, clientHydrationCode);
2156
+ await fs3.writeFile(clientEntryPath, clientHydrationCode);
2239
2157
  const hasScopedPostcssConfig = hasProjectPostcssConfig(root);
2240
2158
  let postcssSearchPath;
2241
2159
  let tailwindVitePlugin = void 0;
@@ -2246,8 +2164,8 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2246
2164
  if (hasScopedPostcssConfig) {
2247
2165
  logger.info("\u{1F4E6} Using project PostCSS/Tailwind configuration");
2248
2166
  } else {
2249
- const postcssConfigPath = path6.join(clientEntryDir, "postcss.config.cjs");
2250
- await fs.writeFile(postcssConfigPath, "module.exports = { plugins: [] };\n");
2167
+ const postcssConfigPath = path8.join(clientEntryDir, "postcss.config.cjs");
2168
+ await fs3.writeFile(postcssConfigPath, "module.exports = { plugins: [] };\n");
2251
2169
  postcssSearchPath = clientEntryDir;
2252
2170
  tailwindVitePlugin = await loadTailwindVitePlugin({
2253
2171
  builder: productionVite.builder,
@@ -2319,6 +2237,23 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2319
2237
  },
2320
2238
  plugins: [
2321
2239
  createFarmThemeCssPlugin(config.theme, config.basePath),
2240
+ createFarmClientModulePreloadPlugin({
2241
+ root,
2242
+ buildDir: path8.dirname(outputDir),
2243
+ entryName: "farm-client"
2244
+ }),
2245
+ ...adapterOwnsDocsRuntime ? [
2246
+ createFarmDocsModulePreloadPlugin({
2247
+ root,
2248
+ buildDir: path8.dirname(outputDir),
2249
+ importer: clientEntryPath,
2250
+ entryName: "farm-client",
2251
+ modules: [
2252
+ config.docs.adapter.react,
2253
+ getFarmDocsAdapterConfigModule(config.docs)
2254
+ ].filter((specifier) => Boolean(specifier))
2255
+ })
2256
+ ] : [],
2322
2257
  ...tailwindVitePlugin ? [tailwindVitePlugin] : [],
2323
2258
  ...rendererVitePlugins,
2324
2259
  ...config.vite.plugins || [],
@@ -2400,7 +2335,7 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2400
2335
  await validateClientBuildOutput(root, srcDir, outputDir);
2401
2336
  } finally {
2402
2337
  try {
2403
- await fs.rm(clientEntryDir, { recursive: true, force: true });
2338
+ await fs3.rm(clientEntryDir, { recursive: true, force: true });
2404
2339
  } catch {
2405
2340
  }
2406
2341
  }
@@ -2408,12 +2343,12 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2408
2343
  __name(buildClient, "buildClient");
2409
2344
  function toBakedMarkdownSourcePath(root, filePath) {
2410
2345
  if (!filePath) return "";
2411
- if (!path6.isAbsolute(filePath)) return filePath.split(path6.sep).join("/");
2412
- const relative = path6.relative(root, filePath);
2413
- if (!relative || relative.startsWith("..") || path6.isAbsolute(relative)) {
2414
- return path6.basename(filePath);
2346
+ if (!path8.isAbsolute(filePath)) return filePath.split(path8.sep).join("/");
2347
+ const relative = path8.relative(root, filePath);
2348
+ if (!relative || relative.startsWith("..") || path8.isAbsolute(relative)) {
2349
+ return path8.basename(filePath);
2415
2350
  }
2416
- return relative.split(path6.sep).join("/");
2351
+ return relative.split(path8.sep).join("/");
2417
2352
  }
2418
2353
  __name(toBakedMarkdownSourcePath, "toBakedMarkdownSourcePath");
2419
2354
  function generateUniversalRouterStateRuntime() {
@@ -3170,19 +3105,21 @@ __farmConfigureApp(__farmAppSetup);` : `import React, { createRoot, hydrateRoot
3170
3105
  root,
3171
3106
  renderer.componentExtensions ?? []
3172
3107
  );
3173
- const globalsCssPath = path6.join(root, srcDir, "app", "globals.css");
3108
+ const globalsCssPath = path8.join(root, srcDir, "app", "globals.css");
3174
3109
  const cssImport = existsSync2(globalsCssPath) ? `import ${JSON.stringify(toImportPath(globalsCssPath))};` : "";
3175
3110
  const layoutImportStatements = [];
3176
3111
  const layoutRegistrations = [];
3112
+ const hydratingLayoutPatterns = layoutRoutes.filter((layout) => layout.shouldHydrate).map((layout) => layout.pattern);
3177
3113
  layoutRoutes.forEach((layout, index) => {
3178
3114
  const relativePath = toImportPath(layout.modulePath);
3179
- if (!layout.hasIsolatedClientBoundaries) {
3115
+ const rendersOnClient = !layout.hasIsolatedClientBoundaries && hydratingLayoutPatterns.some((pattern) => layoutsCanCoverSamePage(layout.pattern, pattern));
3116
+ if (rendersOnClient) {
3180
3117
  layoutImportStatements.push(`import Layout${index} from "${relativePath}";`);
3181
3118
  }
3182
3119
  const groupScope = getRouteGroupScope(layout.pattern);
3183
3120
  const groupFields = groupScope ? `, urlPattern: ${JSON.stringify(stripRouteGroups(layout.pattern))}, groupScope: ${JSON.stringify(groupScope)}` : "";
3184
3121
  layoutRegistrations.push(
3185
- ` { pattern: ${JSON.stringify(layout.pattern)}${groupFields}, Component: ${layout.hasIsolatedClientBoundaries ? "null" : `Layout${index}`}, shouldHydrate: ${JSON.stringify(layout.shouldHydrate)}, islandStrategy: ${JSON.stringify(layout.islandStrategy)} }`
3122
+ ` { pattern: ${JSON.stringify(layout.pattern)}${groupFields}, Component: ${rendersOnClient ? `Layout${index}` : "null"}, shouldHydrate: ${JSON.stringify(layout.shouldHydrate)}, islandStrategy: ${JSON.stringify(layout.islandStrategy)} }`
3186
3123
  );
3187
3124
  });
3188
3125
  const layoutImports = layoutImportStatements.join("\n");
@@ -4642,7 +4579,7 @@ async function buildSSRInMemory(productionVite, config, root, routeManager, apiR
4642
4579
  const viteBuild = productionVite.build;
4643
4580
  const { farmPlugin, farmServerOnlyEntriesPlugin } = await import("./vite.mjs");
4644
4581
  const { PluginManager: PluginManager2 } = await import("./plugin.mjs");
4645
- const fs = await import("fs/promises");
4582
+ const fs3 = await import("fs/promises");
4646
4583
  const pluginManager = new PluginManager2({
4647
4584
  config,
4648
4585
  isDev: false,
@@ -4657,9 +4594,9 @@ async function buildSSRInMemory(productionVite, config, root, routeManager, apiR
4657
4594
  buildLifetime: rendererBuildLifetime
4658
4595
  });
4659
4596
  if (!hasScopedPostcssConfig) {
4660
- postcssConfigDir = await fs.mkdtemp(path6.join(os.tmpdir(), "farm-postcss-"));
4661
- await fs.writeFile(
4662
- path6.join(postcssConfigDir, "postcss.config.cjs"),
4597
+ postcssConfigDir = await fs3.mkdtemp(path8.join(os.tmpdir(), "farm-postcss-"));
4598
+ await fs3.writeFile(
4599
+ path8.join(postcssConfigDir, "postcss.config.cjs"),
4663
4600
  "module.exports = { plugins: [] };\n"
4664
4601
  );
4665
4602
  tailwindVitePlugin = await loadTailwindVitePlugin({
@@ -4684,7 +4621,7 @@ async function buildSSRInMemory(productionVite, config, root, routeManager, apiR
4684
4621
  fileName: entry.fileName,
4685
4622
  sourceType: "static",
4686
4623
  staticInfo: entry.staticInfo,
4687
- data: (await fs.readFile(entry.modulePath)).toString("base64")
4624
+ data: (await fs3.readFile(entry.modulePath)).toString("base64")
4688
4625
  });
4689
4626
  continue;
4690
4627
  }
@@ -4791,20 +4728,39 @@ async function buildSSRInMemory(productionVite, config, root, routeManager, apiR
4791
4728
  const hasConfiguredRuntimePlugins = Boolean(
4792
4729
  hasRuntimeConfigModule && (config.plugins || []).length > 0
4793
4730
  );
4794
- const farmDocsPrecompiledManifest = config.docs?.enabled && getFarmPresetRuntime(preset) === "edge" ? config.docs.adapter?.server ? await compileFarmDocsAdapterEdgeManifest(config.docs, {
4795
- root,
4796
- srcDir: config.srcDir,
4797
- clientEntry: FARM_CLIENT_JS_SRC_PLACEHOLDER,
4798
- fontStylesheetHref: "/farm-fonts.css",
4799
- globalStylesheetHref: "/assets/globals.css"
4800
- }) : await compileFarmDocsManifest(config.docs, {
4801
- root,
4802
- srcDir: config.srcDir,
4803
- clientEntry: FARM_CLIENT_JS_SRC_PLACEHOLDER,
4804
- fontAssets: toFarmDocsPublicFontAssets(resolveFarmDocsFontAssets(root)),
4805
- fontStylesheetHref: "/farm-fonts.css",
4806
- globalStylesheetHref: "/assets/globals.css"
4807
- }) : null;
4731
+ if (hasFarmDocsRuntimeAdapter(config.docs)) {
4732
+ const adapterGuardedPaths = new Set(getFarmDocsGuardedPaths(config, middlewareRoutes));
4733
+ assertFarmDocsAdapterServesNoGuardedPages(
4734
+ config.docs,
4735
+ { root, srcDir: config.srcDir },
4736
+ (pathname) => adapterGuardedPaths.has(pathname)
4737
+ );
4738
+ }
4739
+ const farmDocsCspNonceMarker = createFarmCspNonce(config.security);
4740
+ const farmDocsPrecompiledManifest = config.docs?.enabled && getFarmPresetRuntime(preset) === "edge" ? await _runWithFarmCspNonce(
4741
+ farmDocsCspNonceMarker,
4742
+ async () => config.docs.adapter?.server ? await compileFarmDocsAdapterEdgeManifest(config.docs, {
4743
+ root,
4744
+ srcDir: config.srcDir,
4745
+ clientEntry: FARM_CLIENT_JS_SRC_PLACEHOLDER,
4746
+ fontStylesheetHref: "/farm-fonts.css",
4747
+ globalStylesheetHref: "/assets/globals.css"
4748
+ }) : await (async () => {
4749
+ const guardedPaths = new Set(getFarmDocsGuardedPaths(config, middlewareRoutes));
4750
+ return compileFarmDocsManifest(config.docs, {
4751
+ root,
4752
+ srcDir: config.srcDir,
4753
+ clientEntry: FARM_CLIENT_JS_SRC_PLACEHOLDER,
4754
+ fontAssets: toFarmDocsPublicFontAssets(resolveFarmDocsFontAssets(root)),
4755
+ fontStylesheetHref: "/farm-fonts.css",
4756
+ globalStylesheetHref: "/assets/globals.css",
4757
+ isPathGuarded: /* @__PURE__ */ __name((pathname) => guardedPaths.has(pathname), "isPathGuarded")
4758
+ });
4759
+ })()
4760
+ ) : null;
4761
+ if (farmDocsPrecompiledManifest && farmDocsCspNonceMarker) {
4762
+ farmDocsPrecompiledManifest.cspNonceMarker = farmDocsCspNonceMarker;
4763
+ }
4808
4764
  const virtualEntryCode = generateVirtualEntryCode(
4809
4765
  apiRoutes,
4810
4766
  pageRoutes,
@@ -5000,7 +4956,7 @@ async function buildSSRInMemory(productionVite, config, root, routeManager, apiR
5000
4956
  } finally {
5001
4957
  if (postcssConfigDir) {
5002
4958
  try {
5003
- await fs.rm(postcssConfigDir, { recursive: true, force: true });
4959
+ await fs3.rm(postcssConfigDir, { recursive: true, force: true });
5004
4960
  } catch {
5005
4961
  }
5006
4962
  }
@@ -5014,7 +4970,7 @@ async function buildSSRInMemory(productionVite, config, root, routeManager, apiR
5014
4970
  __name(buildSSRInMemory, "buildSSRInMemory");
5015
4971
  function readFarmAppPackageIdentity(root) {
5016
4972
  try {
5017
- return JSON.parse(readFileSync(path6.join(root, "package.json"), "utf8"));
4973
+ return JSON.parse(readFileSync(path8.join(root, "package.json"), "utf8"));
5018
4974
  } catch {
5019
4975
  return {};
5020
4976
  }
@@ -5034,6 +4990,19 @@ function readFarmPageLastModified(pageRoutes) {
5034
4990
  return lastModified;
5035
4991
  }
5036
4992
  __name(readFarmPageLastModified, "readFarmPageLastModified");
4993
+ function getFarmDocsGuardedPaths(config, middlewareRoutes) {
4994
+ if (!config.docs?.enabled) return [];
4995
+ const contentDir = resolveFarmDocsContentDir(config.docs, {
4996
+ root: config.root,
4997
+ srcDir: config.srcDir
4998
+ });
4999
+ const guards = {
5000
+ config: { middleware: config.middleware, integrations: config.integrations },
5001
+ middlewareRoutes
5002
+ };
5003
+ return discoverFarmDocsPages(contentDir, config.docs).flatMap((page) => [page.href, getFarmDocsMarkdownPath(page.href)]).filter((pathname) => farmPathGuardCoversPage(guards, pathname));
5004
+ }
5005
+ __name(getFarmDocsGuardedPaths, "getFarmDocsGuardedPaths");
5037
5006
  function getFarmAppOwnedDocsEnginePaths(agent, applicationMetadataRoutes) {
5038
5007
  const llmsTxt = agent?.llmsTxt;
5039
5008
  const ownedByFile = /* @__PURE__ */ __name((kind) => applicationMetadataRoutes.some(
@@ -5582,7 +5551,8 @@ function renderFarmRouteServerTree(element) { return element; }`;
5582
5551
  pattern: ${JSON.stringify(route.pattern)},${route.directory ? `
5583
5552
  directory: ${JSON.stringify(route.directory)},` : ""}
5584
5553
  module: ${varName},
5585
- shouldHydrate: ${JSON.stringify(clientMetadata.shouldHydrate)},
5554
+ shouldHydrate: ${JSON.stringify(clientMetadata.shouldHydrate)},${clientMetadata.shouldHydrate ? `
5555
+ clientModule: ${JSON.stringify(toViteModuleId(route.modulePath, config.root))},` : ""}
5586
5556
  islandStrategy: ${JSON.stringify(clientMetadata.islandStrategy)},${usesFarmServerTree(clientMetadata) ? "\n serverTree: true," : ""}${renderingDirective ? `
5587
5557
  rendering: ${JSON.stringify(renderingDirective)},` : ""}
5588
5558
  ${route.source !== void 0 ? `markdownSource: {
@@ -5703,7 +5673,9 @@ function renderFarmRouteServerTree(element) { return element; }`;
5703
5673
  const productionRuntimeImport = `import {
5704
5674
  _getRequestReadCount,
5705
5675
  _runWithAfterRequest,
5676
+ _resolveCurrentCspNonce,
5706
5677
  _runWithCurrentRequest,
5678
+ _runWithFarmCspNonce,
5707
5679
  _runWithAPIRequestRuntime,
5708
5680
  _runWithMiddlewareContext,
5709
5681
  _runWithMiddlewareData,
@@ -5713,6 +5685,8 @@ function renderFarmRouteServerTree(element) { return element; }`;
5713
5685
  appendFarmRedirectQuery,
5714
5686
  applyFarmBasePath,
5715
5687
  applyFarmCspNonceToResponse,
5688
+ createFarmCspNonce,
5689
+ stampFarmCspNonce,
5716
5690
  applyFarmPreviewRobotsTag,
5717
5691
  applyFarmThemeDocument,
5718
5692
  appendFarmLinkHeader,
@@ -5734,6 +5708,7 @@ function renderFarmRouteServerTree(element) { return element; }`;
5734
5708
  createFarmAiCatalogResponse,
5735
5709
  createFarmApiCatalogResponse,
5736
5710
  createFarmAppManifestResponse,
5711
+ farmPathGuardCoversEndpoint,
5737
5712
  collectFarmLlmsTxtPages,
5738
5713
  createFarmDefaultLlmsTxt,
5739
5714
  createFarmLlmsMarkdownReader,
@@ -5807,9 +5782,9 @@ import * as farmDocsConfigModule from ${toVirtualEntryImportSpecifier(docsConfig
5807
5782
  import { dirname as farmDocsDirname, join as farmDocsJoin } from "node:path";
5808
5783
  import { fileURLToPath as farmDocsFileURLToPath } from "node:url";` : "";
5809
5784
  const markdownHandlerImport = config.md?.enabled ? `import { applyMarkdownNegotiationHeaders, createMarkdownMirrorResponse, getFarmMarkdownAlternatePath } from "@farm.js/core/markdown";` : "";
5810
- const appMarkdownImport = hasMarkdownPages ? `import { createFarmMarkdownRouteModule, createFarmMarkdownSourceResponse, isFarmMarkdownPublicSourceResponse } from "@farm.js/core/internal/app-markdown-runtime";` : "const createFarmMarkdownSourceResponse = null;\nconst isFarmMarkdownPublicSourceResponse = null;";
5811
- const markdownErrorImport = `import { FARM_MARKDOWN_CONTENT_TYPE, createFarmMarkdownErrorBody, farmRequestWantsMarkdown } from "@farm.js/core/markdown";`;
5812
- const mdxComponentsPath = typeof config.mdx?.components === "string" ? path6.isAbsolute(config.mdx.components) ? config.mdx.components : path6.join(config.root, config.mdx.components) : null;
5785
+ const appMarkdownImport = hasMarkdownPages ? `import { FARM_MARKDOWN_ANONYMOUS_CLIENT_ADDRESS, createFarmMarkdownRouteModule, createFarmMarkdownSourceResponse, isFarmMarkdownPublicSourceResponse } from "@farm.js/core/internal/app-markdown-runtime";` : "const createFarmMarkdownSourceResponse = null;\nconst isFarmMarkdownPublicSourceResponse = null;";
5786
+ const markdownErrorImport = `import { FARM_MARKDOWN_CONTENT_TYPE, FARM_MARKDOWN_PAGE_CHECK_HEADER, _isFarmMarkdownPageCheck, createFarmMarkdownErrorBody, farmRequestWantsMarkdown } from "@farm.js/core/markdown";`;
5787
+ const mdxComponentsPath = typeof config.mdx?.components === "string" ? path8.isAbsolute(config.mdx.components) ? config.mdx.components : path8.join(config.root, config.mdx.components) : null;
5813
5788
  const mdxComponentsImport = mdxComponentsPath ? `import * as FarmMdxComponentsModule from ${toVirtualEntryImportSpecifier(mdxComponentsPath)};` : "";
5814
5789
  const layerConfigPaths = (config.layers || []).map((layer) => layer.configFile).filter((configFile) => Boolean(configFile)).filter((configFile) => configFile !== configModulePath);
5815
5790
  const layerConfigImports = layerConfigPaths.map(
@@ -6213,12 +6188,41 @@ const farmDocsBundledContentDir = ${config.docs?.enabled && !hasPrecompiledDocs
6213
6188
  })()` : "null"};
6214
6189
  const farmDocsResolvedConfig = ${generateFarmDocsRuntimeConfigExpression(config.docs, hasPrecompiledDocs)};
6215
6190
  const farmDocsRuntimeRoot = ${hasPrecompiledDocs ? '"."' : `farmDocsBundledContentDir || ${JSON.stringify(config.root)}`};
6191
+ // Docs pages a path-specific guard covers, decided at build time. The docs API and the
6192
+ // root llms/sitemap files answer anyone, so they leave these pages out.
6193
+ const farmDocsGuardedPaths = ${JSON.stringify(
6194
+ hasPrecompiledDocs ? [] : getFarmDocsGuardedPaths(config, middlewareRoutes)
6195
+ )};
6196
+ const farmDocsGuardedPathSet = new Set(farmDocsGuardedPaths);
6197
+ const isFarmDocsPathGuarded = (pathname) => farmDocsGuardedPathSet.has(pathname);
6216
6198
  globalThis.__FARM_DOCS_RUNTIME_CONFIG__ = {
6217
6199
  root: farmDocsRuntimeRoot,
6218
6200
  srcDir: ${JSON.stringify(config.srcDir)},
6219
6201
  docs: farmDocsResolvedConfig,
6202
+ guardedPaths: farmDocsGuardedPaths,
6220
6203
  };
6221
6204
  const farmDocsPrecompiledRuntime = ${hasPrecompiledDocs ? `createFarmDocsPrecompiledRuntime(${JSON.stringify(farmDocsPrecompiledManifest)})` : "null"};
6205
+ // Filled in from the client build once it has finished (see buildNitroUniversal).
6206
+ const farmDocsModulePreloads = (() => {
6207
+ try {
6208
+ return JSON.parse("${FARM_DOCS_MODULE_PRELOADS_PLACEHOLDER}");
6209
+ } catch {
6210
+ return null;
6211
+ }
6212
+ })();
6213
+ // Paths the adapter matches against a page's source path the way the browser
6214
+ // finds the page's module.
6215
+ const farmDocsModulePreloadPaths = farmDocsModulePreloads
6216
+ ? {
6217
+ runtime: farmDocsModulePreloads.runtime.map((index) => "/" + farmDocsModulePreloads.files[index]),
6218
+ pages: Object.fromEntries(
6219
+ Object.entries(farmDocsModulePreloads.pages).map(([sourcePath, indexes]) => [
6220
+ sourcePath,
6221
+ indexes.map((index) => "/" + farmDocsModulePreloads.files[index]),
6222
+ ]),
6223
+ ),
6224
+ }
6225
+ : undefined;
6222
6226
  const farmDocsHandler = ${config.docs?.enabled ? hasPrecompiledDocs ? "farmDocsPrecompiledRuntime.handleDocsRequest" : adapterOwnsDocsRuntime ? `createFarmDocsAdapterRuntimeHandler({
6223
6227
  ${docsConfigModulePath ? "...(farmDocsConfigModule.default || farmDocsConfigModule),\n ...farmDocsResolvedConfig.configOverrides," : "...farmDocsResolvedConfig.config,"}
6224
6228
  entry: farmDocsResolvedConfig.config?.entry || String(farmDocsResolvedConfig.entry || "/docs").replace(/^\\/+|\\/+$/g, "") || "docs",
@@ -6229,6 +6233,9 @@ const farmDocsHandler = ${config.docs?.enabled ? hasPrecompiledDocs ? "farmDocsP
6229
6233
  // A production build's content cannot change, so the adapter reads its
6230
6234
  // navigation once instead of scanning the content directory per request.
6231
6235
  immutableContent: true,
6236
+ // List the chunks a page needs, so the browser fetches them alongside the
6237
+ // client entry instead of discovering them one import at a time.
6238
+ modulePreloads: farmDocsModulePreloadPaths,
6232
6239
  clientEntry: "/__farm_client_js_src__",
6233
6240
  // Font CSS is merged into the client stylesheet; farm-fonts.css only exists when the
6234
6241
  // app has fonts, so linking it separately 404'd for apps without them.
@@ -6251,18 +6258,30 @@ const farmDocsHandler = ${config.docs?.enabled ? hasPrecompiledDocs ? "farmDocsP
6251
6258
  ),
6252
6259
  fontStylesheetHref: "/farm-fonts.css",
6253
6260
  globalStylesheetHref: "/assets/globals.css",
6261
+ isPathGuarded: isFarmDocsPathGuarded,
6254
6262
  })` : "null"};
6255
- const farmDocsAPIHandler = ${config.docs?.enabled ? hasPrecompiledDocs ? "farmDocsPrecompiledRuntime.handleAPIRequest" : adapterOwnsDocsRuntime ? "null" : `createFarmDocsAPIHandler({ rootDir: farmDocsRuntimeRoot, srcDir: ${JSON.stringify(config.srcDir)}, docs: farmDocsResolvedConfig })` : "null"};
6263
+ const farmDocsAPIHandler = ${config.docs?.enabled ? hasPrecompiledDocs ? "farmDocsPrecompiledRuntime.handleAPIRequest" : adapterOwnsDocsRuntime ? "null" : `createFarmDocsAPIHandler({ rootDir: farmDocsRuntimeRoot, srcDir: ${JSON.stringify(config.srcDir)}, docs: farmDocsResolvedConfig, isPathGuarded: isFarmDocsPathGuarded })` : "null"};
6256
6264
 
6257
6265
  // API routes bundled at build time
6258
6266
  const apiRoutes = ${apiRoutes.length > 0 ? "mergePluginAPIRoutes(" : ""}[${apiRegistrations.join(",")}
6259
- ]${apiRoutes.length > 0 ? `, configuredPlugins, ${JSON.stringify(apiRoutes.map(({ path: path8, methods }) => ({ path: path8, methods })))}, { bodySizeLimit: ${JSON.stringify(config.server.bodySizeLimit)}, dispatch: dispatchFarmPluginAPIRequest })` : ""};
6267
+ ]${apiRoutes.length > 0 ? `, configuredPlugins, ${JSON.stringify(apiRoutes.map(({ path: path10, methods }) => ({ path: path10, methods })))}, { bodySizeLimit: ${JSON.stringify(config.server.bodySizeLimit)}, dispatch: dispatchFarmPluginAPIRequest })` : ""};
6260
6268
  // A plugin calling an app endpoint (an MCP tool, say) goes through the whole
6261
6269
  // pipeline, so the endpoint's middleware and integration guards run for it.
6262
6270
  function dispatchFarmPluginAPIRequest(request) {
6263
6271
  const url = new URL(request.url);
6264
6272
  url.pathname = applyFarmBasePath(url.pathname);
6265
- return handleFarmRequest(url.href === request.url ? request : new Request(url, request));
6273
+ return fetchFarmInnerRequest(url.href === request.url ? request : new Request(url, request));
6274
+ }
6275
+ // A request the app makes to itself (a Markdown page check, a plugin's endpoint call) enters
6276
+ // through this module's outer \`fetch\`, as a direct request does: plugin runtime hooks run and
6277
+ // it gets its own request context, so \`cookies()\` and \`headers()\` are its own, never the
6278
+ // caller's. It asks for an identity body: the caller reads it, and the outer response is
6279
+ // compressed once.
6280
+ function fetchFarmInnerRequest(request, context) {
6281
+ if (!request.headers.has("accept-encoding")) return fetch(request, context);
6282
+ const headers = new Headers(request.headers);
6283
+ headers.delete("accept-encoding");
6284
+ return fetch(new Request(request, { headers }), context);
6266
6285
  }
6267
6286
  const farmLocalAPIBasePath = ${JSON.stringify(resolveFarmAPIServerBasePath(config.api))};
6268
6287
  const farmOpenAPIReference = ${JSON.stringify(openAPIReference)};
@@ -6274,7 +6293,17 @@ ${config.agent?.apiCatalog ? `const farmApiCatalogInput = ${JSON.stringify(resol
6274
6293
  webmcpTools: config.plugins.some(({ name }) => name === "farm:webmcp") ? collectFarmWebMCPTools(config.root, config.srcDir) : []
6275
6294
  })
6276
6295
  )};
6277
- ${servesDefaultMCP ? "farmAppManifestInput.defaultMCP = getFarmDefaultMCPServer;\n" : ""}` : ""}
6296
+ ${servesDefaultMCP ? "farmAppManifestInput.defaultMCP = getFarmDefaultMCPServer;\n" : ""}// A guard written for an MCP server's path keeps its tools out of the public view.
6297
+ farmAppManifestInput.guardCoversPath = (path) =>
6298
+ farmPathGuardCoversEndpoint(
6299
+ {
6300
+ config: { middleware: farmMiddlewareConfig, integrations: serverRuntimeIntegrations },
6301
+ middlewareRoutes: fileMiddlewareModules,
6302
+ },
6303
+ path,
6304
+ farmLocalAPIBasePath,
6305
+ );
6306
+ ` : ""}
6278
6307
  function isFarmLocalAPIPathname(pathname) {
6279
6308
  return farmLocalAPIBasePath !== "/" &&
6280
6309
  (pathname === farmLocalAPIBasePath ||
@@ -6374,15 +6403,26 @@ function renderFarmClientBootstrapScript(canonicalPath, selectedRouteSlots, page
6374
6403
  }
6375
6404
  return '<script id="__farm_route_slots_data__" type="application/json">' +
6376
6405
  serializedRouteSlots +
6377
- '</script><script>' + source + '</script>';
6406
+ '</script>' + stampFarmCspNonce('<script>' + source + '</script>');
6378
6407
  }
6379
6408
 
6380
6409
  function renderFarmRendererHydrationScript() {
6381
6410
  return typeof ReactDOMServer.generateHydrationScript === "function"
6382
- ? ReactDOMServer.generateHydrationScript()
6411
+ ? stampFarmCspNonce(ReactDOMServer.generateHydrationScript())
6383
6412
  : "";
6384
6413
  }
6385
6414
 
6415
+ function renderFarmClientEntryScript() {
6416
+ return stampFarmCspNonce('<script type="module" src="/__farm_client_js_src__"></script>');
6417
+ }
6418
+
6419
+ // Renderer options for the response being rendered: its CSP nonce, which the
6420
+ // renderer puts on the inline scripts it emits.
6421
+ function getFarmRendererRenderOptions() {
6422
+ const nonce = _resolveCurrentCspNonce();
6423
+ return nonce ? { nonce } : undefined;
6424
+ }
6425
+
6386
6426
  function escapeFarmHtmlAttribute(value) {
6387
6427
  return String(value)
6388
6428
  .replace(/&/g, "&amp;")
@@ -6424,6 +6464,7 @@ async function renderFarmElement(ReactDOMServer, element, routeKey) {
6424
6464
  if (farmRendererStreamingCapabilities.web &&
6425
6465
  typeof ReactDOMServer.renderToReadableStream === "function") {
6426
6466
  const stream = await ReactDOMServer.renderToReadableStream(element, {
6467
+ nonce: _resolveCurrentCspNonce(),
6427
6468
  onError(error) {
6428
6469
  // redirect()/notFound() are control flow, not render failures: the
6429
6470
  // request handler must still receive them to map the response status,
@@ -6556,6 +6597,7 @@ async function renderFarmElement(ReactDOMServer, element, routeKey) {
6556
6597
  },
6557
6598
  };
6558
6599
  pipeableStream = ReactDOMServer.renderToPipeableStream(element, {
6600
+ nonce: _resolveCurrentCspNonce(),
6559
6601
  onShellReady() {
6560
6602
  try {
6561
6603
  pipeableStream.pipe(destination);
@@ -6618,7 +6660,10 @@ async function renderFarmElement(ReactDOMServer, element, routeKey) {
6618
6660
  }
6619
6661
 
6620
6662
  if (ReactDOMServer.renderToStringWithHead) {
6621
- const rendered = await ReactDOMServer.renderToStringWithHead(element);
6663
+ const rendered = await ReactDOMServer.renderToStringWithHead(
6664
+ element,
6665
+ getFarmRendererRenderOptions(),
6666
+ );
6622
6667
  return {
6623
6668
  html: rendered.html,
6624
6669
  head: rendered.head || "",
@@ -6626,7 +6671,7 @@ async function renderFarmElement(ReactDOMServer, element, routeKey) {
6626
6671
  streamErrors,
6627
6672
  };
6628
6673
  }
6629
- const html = await ReactDOMServer.renderToString(element);
6674
+ const html = await ReactDOMServer.renderToString(element, getFarmRendererRenderOptions());
6630
6675
  return { html, head: "", shellHtml: html, streamErrors };
6631
6676
  }
6632
6677
 
@@ -6665,7 +6710,7 @@ function renderFarmElementSync(ReactDOMServer, element, routeKey) {
6665
6710
  if (typeof ReactDOMServer.renderToString !== "function") return undefined;
6666
6711
  let html;
6667
6712
  try {
6668
- html = ReactDOMServer.renderToString(element);
6713
+ html = ReactDOMServer.renderToString(element, getFarmRendererRenderOptions());
6669
6714
  } catch {
6670
6715
  html = undefined;
6671
6716
  }
@@ -6680,6 +6725,8 @@ function renderFarmElementSync(ReactDOMServer, element, routeKey) {
6680
6725
  function createFarmDocumentStream(contentStream, prefix, suffix, onComplete) {
6681
6726
  const encoder = new TextEncoder();
6682
6727
  const reader = contentStream.getReader();
6728
+ // The suffix renders after the handler returned, outside its async scope.
6729
+ const cspNonce = _resolveCurrentCspNonce();
6683
6730
  return new ReadableStream({
6684
6731
  start(controller) {
6685
6732
  controller.enqueue(encoder.encode(prefix));
@@ -6688,7 +6735,9 @@ function createFarmDocumentStream(contentStream, prefix, suffix, onComplete) {
6688
6735
  try {
6689
6736
  const result = await reader.read();
6690
6737
  if (result.done) {
6691
- const tail = typeof suffix === "function" ? await suffix() : suffix;
6738
+ const tail = typeof suffix === "function"
6739
+ ? await _runWithFarmCspNonce(cspNonce, suffix)
6740
+ : suffix;
6692
6741
  controller.enqueue(encoder.encode(tail));
6693
6742
  if (onComplete) onComplete();
6694
6743
  controller.close();
@@ -6810,18 +6859,18 @@ function createFarmErrorDocument(html, title) {
6810
6859
  ' <meta name="viewport" content="width=device-width, initial-scale=1">\\n' +
6811
6860
  ' <link rel="icon" href="data:,">\\n' +
6812
6861
  ' <title>' + escapedTitle + '</title>\\n' +
6813
- ' <link rel="stylesheet" href="/__farm_client_css_href__">\\n' +
6862
+ ' <link rel="stylesheet" href="/__farm_client_css_href__">' + renderFarmClientModulePreloads(html) + '\\n' +
6814
6863
  renderFarmRendererHydrationScript() + '\\n' +
6815
6864
  '</head>\\n<body>\\n' +
6816
6865
  ' <div id="root">' + html + '</div>\\n' +
6817
6866
  ' ' + renderFarmClientBootstrapScript() + '\\n' +
6818
- ' <script type="module" src="/__farm_client_js_src__"></script>\\n' +
6867
+ ' ' + renderFarmClientEntryScript() + '\\n' +
6819
6868
  '</body>\\n</html>';
6820
6869
  }
6821
6870
 
6822
6871
  let fullHtml = ensureFarmDocumentRoot(ensureFarmDocumentHead(fullDocument));
6823
6872
  fullHtml = fullHtml
6824
- .replace(/<head([^>]*)>/i, '<head$1>\\n <link rel="stylesheet" href="/__farm_client_css_href__">')
6873
+ .replace(/<head([^>]*)>/i, function(match, attrs) { return '<head' + attrs + '>\\n <link rel="stylesheet" href="/__farm_client_css_href__">' + renderFarmClientModulePreloads(fullDocument); })
6825
6874
  // Function replacements: dynamic markup may contain $-sequences ($&, $', $$)
6826
6875
  // that a string replacement would expand, corrupting the document.
6827
6876
  .replace(/<\\/head>/i, function() { return renderFarmRendererHydrationScript() + '\\n</head>'; })
@@ -6834,7 +6883,7 @@ function createFarmErrorDocument(html, title) {
6834
6883
  /<\\/body>/i,
6835
6884
  function() {
6836
6885
  return ' ' + renderFarmClientBootstrapScript() + '\\n' +
6837
- ' <script type="module" src="/__farm_client_js_src__"></script>\\n</body>';
6886
+ ' ' + renderFarmClientEntryScript() + '\\n</body>';
6838
6887
  },
6839
6888
  );
6840
6889
  return fullHtml.trim().startsWith("<!DOCTYPE")
@@ -6842,6 +6891,53 @@ function createFarmErrorDocument(html, title) {
6842
6891
  : "<!DOCTYPE html>\\n" + fullHtml;
6843
6892
  }
6844
6893
 
6894
+ // The client modules a page needs before it hydrates, filled in from the client
6895
+ // build once it has finished (see buildNitroUniversal).
6896
+ const farmClientModulePreloads = (() => {
6897
+ try {
6898
+ return JSON.parse("${FARM_CLIENT_MODULE_PRELOADS_PLACEHOLDER}");
6899
+ } catch {
6900
+ return null;
6901
+ }
6902
+ })();
6903
+ const farmClientEntryPreloadTags = farmClientModulePreloads
6904
+ ? farmClientModulePreloads.entry.map(renderFarmClientModulePreload).join("")
6905
+ : "";
6906
+ // The client modules a document's markup loads: its islands' boundaries and the
6907
+ // client references of its server tree.
6908
+ const FARM_CLIENT_MODULE_REFERENCE_PATTERN = /data-farm-client-boundary="([^"]+)"|"r":"(\\/[^"]+)"/g;
6909
+
6910
+ function renderFarmClientModulePreload(index) {
6911
+ return '\\n <link rel="modulepreload" href="/' +
6912
+ escapeFarmHtmlAttribute(farmClientModulePreloads.files[index]) +
6913
+ '" fetchpriority="low">';
6914
+ }
6915
+
6916
+ // The modulepreload links for a document: the entry's static imports, then the
6917
+ // modules its hydrating page and its markup load.
6918
+ function renderFarmClientModulePreloads(markup, pageModule) {
6919
+ // A nonce policy blocks parser-inserted links without the nonce, and the
6920
+ // response filter manages nonces on script elements only, so CSP nonce mode
6921
+ // keeps the documents it had.
6922
+ if (!farmClientModulePreloads || (farmSecurityConfig.csp && farmSecurityConfig.csp.nonce)) return "";
6923
+ const modules = farmClientModulePreloads.modules;
6924
+ const listed = new Set();
6925
+ let tags = farmClientEntryPreloadTags;
6926
+ const add = (moduleId) => {
6927
+ if (!moduleId || !Object.prototype.hasOwnProperty.call(modules, moduleId)) return;
6928
+ for (const index of modules[moduleId]) {
6929
+ if (listed.has(index)) continue;
6930
+ listed.add(index);
6931
+ tags += renderFarmClientModulePreload(index);
6932
+ }
6933
+ };
6934
+ add(pageModule);
6935
+ if (typeof markup === "string") {
6936
+ for (const match of markup.matchAll(FARM_CLIENT_MODULE_REFERENCE_PATTERN)) add(match[1] || match[2]);
6937
+ }
6938
+ return tags;
6939
+ }
6940
+
6845
6941
  // The origin hreflang alternates resolve against when the route sets no
6846
6942
  // metadataBase. Forwarded authority counts only under server.trustProxy, the
6847
6943
  // same rule the development server applies.
@@ -6874,7 +6970,7 @@ function applyFarmI18nDocument(html, requestPath, snapshot, request, metadata) {
6874
6970
  });
6875
6971
  const runtimeMarkup =
6876
6972
  renderFarmI18nAlternateLinks(requestPath, snapshot, request, metadata) +
6877
- '<script>window.__FARM_I18N__ = ' + serializeFarmInlineValue(snapshot) + ';</script>';
6973
+ stampFarmCspNonce('<script>window.__FARM_I18N__ = ' + serializeFarmInlineValue(snapshot) + ';</script>');
6878
6974
  nextHtml = nextHtml.replace(/<head([^>]*)>/i, function(_match, attributes) {
6879
6975
  // Function replacement: runtimeMarkup may contain $-sequences ($&, $', $$).
6880
6976
  return '<head' + attributes + '>' + runtimeMarkup;
@@ -6944,6 +7040,26 @@ function hasPrivateFarmRequestHeaders(request, farmLocaleResolution) {
6944
7040
  );
6945
7041
  }
6946
7042
 
7043
+ // A docs response a guard let this visitor read is theirs, as for pages: one for a
7044
+ // request with credentials, or with middleware request data, never fills a shared cache.
7045
+ // Middleware headers cannot do this, since they never replace a response's own.
7046
+ function withFarmDocsRequestCache(response, request, farmLocaleResolution, middlewareData, middlewareContext) {
7047
+ if (
7048
+ !hasPrivateFarmRequestHeaders(request, farmLocaleResolution) &&
7049
+ !middlewareData?.size &&
7050
+ !middlewareContext?.size
7051
+ ) {
7052
+ return response;
7053
+ }
7054
+ const headers = new Headers(response.headers);
7055
+ headers.set("Cache-Control", "private, no-store");
7056
+ return farmOwnedResponse(response.body, {
7057
+ status: response.status,
7058
+ statusText: response.statusText,
7059
+ headers,
7060
+ });
7061
+ }
7062
+
6947
7063
  ${generateRuntimePathMatcherSource()}
6948
7064
 
6949
7065
  function getMatchingErrorBoundary(pathname) {
@@ -7174,6 +7290,27 @@ function createFarmAgentRobotsResponse(request) {
7174
7290
  );
7175
7291
  }
7176
7292
  ` : ""}
7293
+ // Static pages a path-specific guard covers (non-root middleware.ts, a config or
7294
+ // integration middleware matcher naming the path), decided at build time.
7295
+ // sitemap.xml, llms.txt and the default MCP server never list them, nor a page behind
7296
+ // a route guard.
7297
+ const farmAgentGuardedPages = new Set(${JSON.stringify(
7298
+ pageRoutes.map((route) => route.pattern).filter(
7299
+ (pattern) => !pattern.includes("[") && farmPathGuardCoversPage(
7300
+ {
7301
+ config: { middleware: config.middleware, integrations: config.integrations },
7302
+ middlewareRoutes
7303
+ },
7304
+ pattern
7305
+ )
7306
+ )
7307
+ )});
7308
+ function getFarmAgentListedPageRoutes() {
7309
+ return pageRoutes.filter(
7310
+ (route) =>
7311
+ !farmAgentGuardedPages.has(route.pattern) && !(route.module && route.module.__farmRouteGuard),
7312
+ );
7313
+ }
7177
7314
  ${servesAgentSitemap ? `// sitemap.xml from agent.sitemap, built the same way as in development. Each page's
7178
7315
  // lastmod is its file's modification time, read at build time.
7179
7316
  const farmAgentSitemapConfig = ${JSON.stringify(config.agent.sitemap)};
@@ -7183,7 +7320,7 @@ function createFarmAgentSitemapResponse(request) {
7183
7320
  return createFarmMetadataRouteResponse(
7184
7321
  "sitemap",
7185
7322
  createFarmDefaultSitemap(
7186
- pageRoutes.map((route) => ({
7323
+ getFarmAgentListedPageRoutes().map((route) => ({
7187
7324
  pattern: route.pattern,
7188
7325
  module: route.module,
7189
7326
  lastModified: farmAgentSitemapLastModified[route.pattern],
@@ -7222,7 +7359,7 @@ async function handleFarmDefaultMCP(request) {
7222
7359
  basePath: ${JSON.stringify(config.basePath)},
7223
7360
  listPages: () =>
7224
7361
  collectFarmDefaultMCPPages(
7225
- pageRoutes.map((route) => ({ pattern: route.pattern, module: route.module })),
7362
+ getFarmAgentListedPageRoutes().map((route) => ({ pattern: route.pattern, module: route.module })),
7226
7363
  { origin, basePath: ${JSON.stringify(config.basePath)}, markdown: farmMarkdownConfig },
7227
7364
  ),
7228
7365
  // A fresh request through this handler, so the caller's cookies never shape a page.
@@ -7234,13 +7371,15 @@ async function handleFarmDefaultMCP(request) {
7234
7371
  },
7235
7372
  });
7236
7373
  }
7237
- const farmDefaultMCPReadMarkdown = createFarmLlmsMarkdownReader((page) => handleFarmRequest(page));
7374
+ // \`fetch\` is this module's outer request entry: plugin runtime hooks run and the page
7375
+ // gets its own request context, as for a direct request.
7376
+ const farmDefaultMCPReadMarkdown = createFarmLlmsMarkdownReader((page) => fetch(page));
7238
7377
  ` : ""}
7239
7378
  // Static pages and root metadata for llms.txt, built the same way as in development.
7240
7379
  function createFarmLlmsTxtContext(request, full) {
7241
7380
  const origin = new URL(request.url).origin;
7242
7381
  const pages = collectFarmLlmsTxtPages(
7243
- pageRoutes.map((route) => ({ pattern: route.pattern, metadata: route.module && route.module.metadata })),
7382
+ getFarmAgentListedPageRoutes().map((route) => ({ pattern: route.pattern, metadata: route.module && route.module.metadata })),
7244
7383
  {
7245
7384
  origin,
7246
7385
  markdown: farmMarkdownConfig,
@@ -7261,14 +7400,15 @@ function createFarmLlmsTxtContext(request, full) {
7261
7400
  apiServerBasePath: farmLocalAPIBasePath,${servesDefaultMCP ? "\n defaultMCP: getFarmDefaultMCPServer," : ""}
7262
7401
  }),` : ""}
7263
7402
  }),
7264
- // llms-full.txt reads each page's .md mirror through this same handler,
7265
- // with a fresh request so the caller's cookies never shape its content.
7266
- // HEAD discards the body, so it reads nothing.
7403
+ // llms-full.txt reads each page's .md mirror through this module's outer
7404
+ // request entry, so plugin runtime hooks run and each read has a fresh request
7405
+ // context: the caller's cookies never shape its content. HEAD discards the
7406
+ // body, so it reads nothing.
7267
7407
  ...(full
7268
7408
  ? {
7269
7409
  markdown: request.method.toUpperCase() === "HEAD"
7270
7410
  ? async () => null
7271
- : createFarmLlmsMarkdownReader((page) => handleFarmRequest(page)),
7411
+ : createFarmLlmsMarkdownReader((page) => fetch(page)),
7272
7412
  }
7273
7413
  : {}),
7274
7414
  };
@@ -7716,7 +7856,7 @@ ${config.docs?.enabled ? `async function wrapFarmDocsResponseWithLayouts(request
7716
7856
  if (!html.includes('src="/__farm_client_js_src__"')) {
7717
7857
  html = html.replace(
7718
7858
  /<[/]body>/i,
7719
- ' <script type="module" src="/__farm_client_js_src__"></script>\\n</body>',
7859
+ function() { return ' ' + renderFarmClientEntryScript() + '\\n</body>'; },
7720
7860
  );
7721
7861
  }
7722
7862
  if (!html.includes('window._$HY')) {
@@ -7753,6 +7893,9 @@ function resolvePPRConfig(route) {
7753
7893
  }
7754
7894
 
7755
7895
  function getPPRShellBypassReason(request, middlewareData, middlewareContext) {
7896
+ // A shared shell would carry one response's nonce to every visitor, where
7897
+ // the nonce filter strips it and Farm's scripts stop running.
7898
+ if (farmSecurityConfig.csp && farmSecurityConfig.csp.nonce) return "csp-nonce";
7756
7899
  const method = request.method.toUpperCase();
7757
7900
  if (method !== "GET" && method !== "HEAD") return "method";
7758
7901
  if (request.headers.get("cookie")) return "cookie";
@@ -8030,11 +8173,17 @@ async function handleFarmRequestInContext(
8030
8173
  const docsResponse = await farmDocsHandler(cloneFarmRequestWithContext(request));
8031
8174
  if (docsResponse) {
8032
8175
  if (!docsResponse.headers.get("content-type")?.toLowerCase().includes("text/html")) {
8033
- return applyProductionMiddlewareHeaders(docsResponse, middlewareHeaders);
8176
+ return applyProductionMiddlewareHeaders(
8177
+ withFarmDocsRequestCache(docsResponse, request, farmLocaleResolution, middlewareData, middlewareContext),
8178
+ middlewareHeaders,
8179
+ );
8034
8180
  }
8035
- const wrappedDocsResponse = await wrapFarmDocsResponseWithLayouts(
8181
+ const wrappedDocsResponse = withFarmDocsRequestCache(
8182
+ await wrapFarmDocsResponseWithLayouts(request, docsResponse),
8036
8183
  request,
8037
- docsResponse,
8184
+ farmLocaleResolution,
8185
+ middlewareData,
8186
+ middlewareContext,
8038
8187
  );
8039
8188
  const docsHeaders = new Headers(wrappedDocsResponse.headers);
8040
8189
  docsHeaders.set("x-farm-preload-buffered", "1");
@@ -8058,7 +8207,13 @@ async function handleFarmRequestInContext(
8058
8207
  const match = matchPageRoute(getFarmRoutePathname(targetPathname));
8059
8208
  return match?.route?.markdownSource || null;
8060
8209
  },
8061
- renderPage: (targetRequest) => handleFarmRequest(targetRequest, adapterContext),
8210
+ clientAddress: adapterContext?.clientAddress,
8211
+ // An anonymous visitor's request: guards never see the caller's address.
8212
+ renderPage: (targetRequest) =>
8213
+ fetchFarmInnerRequest(targetRequest, {
8214
+ ...adapterContext,
8215
+ clientAddress: FARM_MARKDOWN_ANONYMOUS_CLIENT_ADDRESS,
8216
+ }),
8062
8217
  });
8063
8218
  if (markdownSourceResponse) {
8064
8219
  return isFarmMarkdownPublicSourceResponse(markdownSourceResponse)
@@ -8078,7 +8233,7 @@ async function handleFarmRequestInContext(
8078
8233
  config: farmMarkdownConfig,
8079
8234
  routeExists: (targetPathname) =>
8080
8235
  Boolean(matchPageRoute(getFarmRoutePathname(targetPathname))),
8081
- renderPage: (targetRequest) => handleFarmRequest(targetRequest, adapterContext),
8236
+ renderPage: (targetRequest) => fetchFarmInnerRequest(targetRequest, adapterContext),
8082
8237
  apiServerBasePath: farmLocalAPIBasePath,
8083
8238
  });
8084
8239
  if (markdownResponse) {
@@ -8129,7 +8284,7 @@ async function handleFarmRequestInContext(
8129
8284
  ) {
8130
8285
  const method = request.method.toUpperCase();
8131
8286
  const response = method === "GET" || method === "HEAD"
8132
- ? farmOwnedResponse(method === "HEAD" ? null : farmOpenAPIReference.html, {
8287
+ ? farmOwnedResponse(method === "HEAD" ? null : stampFarmCspNonce(farmOpenAPIReference.html), {
8133
8288
  status: 200,
8134
8289
  headers: {
8135
8290
  "Content-Type": "text/html; charset=utf-8",
@@ -8249,7 +8404,10 @@ async function handleFarmRequestInContext(
8249
8404
  ${config.docs?.enabled ? `if (farmDocsAPIHandler && isFarmDocsAPIRequest(pathname)) {
8250
8405
  const docsAPIResponse = await farmDocsAPIHandler(cloneFarmRequestWithContext(request));
8251
8406
  if (docsAPIResponse) {
8252
- return applyProductionMiddlewareHeaders(docsAPIResponse, middlewareHeaders);
8407
+ return applyProductionMiddlewareHeaders(
8408
+ withFarmDocsRequestCache(docsAPIResponse, request, farmLocaleResolution, middlewareData, middlewareContext),
8409
+ middlewareHeaders,
8410
+ );
8253
8411
  }
8254
8412
  }` : ""}
8255
8413
 
@@ -8763,13 +8921,16 @@ async function handleFarmRequestInContext(
8763
8921
 
8764
8922
  // Stream a suspended body as soon as React's shell is ready. Full-document
8765
8923
  // layouts, localized documents, and cacheable PPR shells still use the
8766
- // buffered path because they require whole-document transformation.
8924
+ // buffered path because they require whole-document transformation, and so
8925
+ // does the anonymous check behind a page's Markdown source: there, a
8926
+ // redirect() under a loading boundary must still decide the status.
8767
8927
  if (
8768
8928
  pageStatus === 200 &&
8769
8929
  renderedPage.stream &&
8770
8930
  !hasFullDocument &&
8771
8931
  !farmI18nSnapshot &&
8772
- !pprCacheKey
8932
+ !pprCacheKey &&
8933
+ !_isFarmMarkdownPageCheck(request.headers.get(FARM_MARKDOWN_PAGE_CHECK_HEADER))
8773
8934
  ) {
8774
8935
  const farmThemeDocument = createFarmThemeDocumentParts(
8775
8936
  farmThemeConfig,
@@ -8783,7 +8944,7 @@ async function handleFarmRequestInContext(
8783
8944
  (hasFavicon ? '' : ' <link rel="icon" href="data:,">\\n') +
8784
8945
  ' <title>' + title + '</title>' + metaTags + '\\n' +
8785
8946
  ' <link rel="stylesheet" href="/__farm_client_css_href__">\\n' +
8786
- ' <link rel="modulepreload" href="/__farm_client_js_src__">\\n' +
8947
+ ' <link rel="modulepreload" href="/__farm_client_js_src__">' + renderFarmClientModulePreloads(null, route.clientModule) + '\\n' +
8787
8948
  renderFarmRendererHydrationScript() + '\\n' +
8788
8949
  '</head>\\n<body>\\n <div id="root">';
8789
8950
  const streamSuffix = '</div>\\n' +
@@ -8792,7 +8953,7 @@ async function handleFarmRequestInContext(
8792
8953
  routeSlotPayload,
8793
8954
  clientPageProps
8794
8955
  ) + '\\n' +
8795
- ' <script type="module" src="/__farm_client_js_src__"></script>\\n' +
8956
+ ' ' + renderFarmClientEntryScript() + '\\n' +
8796
8957
  '</body>\\n</html>';
8797
8958
  const themedStreamPrefix = streamPrefix.replace(
8798
8959
  '<html lang="en">',
@@ -8816,7 +8977,8 @@ async function handleFarmRequestInContext(
8816
8977
  try {
8817
8978
  return createLateNotFoundRecovery(
8818
8979
  await ReactDOMServer.renderToString(
8819
- wrapWithFarmIntegrationProviders(createFarmNotFoundElement(pathname))
8980
+ wrapWithFarmIntegrationProviders(createFarmNotFoundElement(pathname)),
8981
+ getFarmRendererRenderOptions()
8820
8982
  )
8821
8983
  ) + streamSuffix;
8822
8984
  } catch (error) {
@@ -8824,7 +8986,10 @@ async function handleFarmRequestInContext(
8824
8986
  // needs their context cannot render alone, so use Farm's.
8825
8987
  console.warn("not-found page could not render outside its layout, using Farm's:", error);
8826
8988
  return createLateNotFoundRecovery(
8827
- await ReactDOMServer.renderToString(React.createElement(FarmDefault404Page))
8989
+ await ReactDOMServer.renderToString(
8990
+ React.createElement(FarmDefault404Page),
8991
+ getFarmRendererRenderOptions()
8992
+ )
8828
8993
  ) + streamSuffix;
8829
8994
  }
8830
8995
  },
@@ -8873,7 +9038,7 @@ async function handleFarmRequestInContext(
8873
9038
  );
8874
9039
  fullHtml = html
8875
9040
  // Inject CSS link after opening head tag or first meta tag
8876
- .replace(/<head([^>]*)>/i, '<head$1>\\n <link rel="stylesheet" href="/__farm_client_css_href__">')
9041
+ .replace(/<head([^>]*)>/i, function(match, attrs) { return '<head' + attrs + '>\\n <link rel="stylesheet" href="/__farm_client_css_href__">' + renderFarmClientModulePreloads(html, route.clientModule); })
8877
9042
  .replace(/<\\/head>/i, () => renderFarmRendererHydrationScript() + '\\n</head>')
8878
9043
  // Explicit metadata wins over renderer and layout titles. Without
8879
9044
  // explicit metadata, a renderer title wins over the layout title.
@@ -8907,7 +9072,7 @@ async function handleFarmRequestInContext(
8907
9072
  routeSlotPayload,
8908
9073
  clientPageProps
8909
9074
  ) + '\\n' +
8910
- ' <script type="module" src="/__farm_client_js_src__"></script>\\n</body>',
9075
+ ' ' + renderFarmClientEntryScript() + '\\n</body>',
8911
9076
  );
8912
9077
 
8913
9078
  // Last, so the charset (and the viewport, unless the layout wrote one) open the head.
@@ -8926,13 +9091,13 @@ async function handleFarmRequestInContext(
8926
9091
  \${viewportTags}
8927
9092
  \${hasFavicon ? "" : '<link rel="icon" href="data:,">'}
8928
9093
  \${suppressDefaultTitle ? "" : "<title>" + title + "</title>"}\${metaTags}\${rendererHead ? "\\n " + rendererHead : ""}
8929
- <link rel="stylesheet" href="/__farm_client_css_href__">
9094
+ <link rel="stylesheet" href="/__farm_client_css_href__">\${renderFarmClientModulePreloads(html, route.clientModule)}
8930
9095
  \${renderFarmRendererHydrationScript()}
8931
9096
  </head>
8932
9097
  <body>
8933
9098
  <div id="root">\${html}</div>
8934
9099
  \${renderFarmClientBootstrapScript(pageProps.__farmCanonicalPath, routeSlotPayload, clientPageProps)}
8935
- <script type="module" src="/__farm_client_js_src__"></script>
9100
+ \${renderFarmClientEntryScript()}
8936
9101
  </body>
8937
9102
  </html>\`;
8938
9103
  }
@@ -9104,14 +9269,14 @@ async function handleFarmRequestInContext(
9104
9269
  }
9105
9270
  }
9106
9271
 
9107
- const fallbackHtml = createDefaultErrorMarkup({
9272
+ const fallbackHtml = stampFarmCspNonce(createDefaultErrorMarkup({
9108
9273
  statusCode: errorStatus,
9109
9274
  statusText: errorStatusText,
9110
9275
  requestPath: pathname,
9111
9276
  method: request.method,
9112
9277
  development: false,
9113
9278
  mode: "production",
9114
- });
9279
+ }));
9115
9280
  const fallbackDocument = applyFarmThemeDocument(
9116
9281
  applyFarmI18nDocument(
9117
9282
  createFarmErrorDocument(
@@ -9198,7 +9363,7 @@ ${servesDefaultMCP ? `
9198
9363
  }
9199
9364
  notFoundElement = wrapWithFarmIntegrationProviders(notFoundElement);
9200
9365
 
9201
- const html = await ReactDOMServer.renderToString(notFoundElement);
9366
+ const html = await ReactDOMServer.renderToString(notFoundElement, getFarmRendererRenderOptions());
9202
9367
  // The layouts' and the not-found page's metadata, as the development renderer uses it.
9203
9368
  const notFoundMetadata = renderMetadataHead(
9204
9369
  await resolveFarmNotFoundMetadata(
@@ -9223,12 +9388,12 @@ ${servesDefaultMCP ? `
9223
9388
  "<head" + attrs + ">" +
9224
9389
  headContent.replace(/<title\\b[^>]*>[\\s\\S]*?<\\/title>\\s*/gi, "") +
9225
9390
  "\\n <title>" + notFoundMetadata.title + "</title>" + notFoundMetadata.tags + "\\n</head>")
9226
- .replace(/<head([^>]*)>/i, '<head$1>\\n <link rel="stylesheet" href="/__farm_client_css_href__">')
9391
+ .replace(/<head([^>]*)>/i, function(match, attrs) { return '<head' + attrs + '>\\n <link rel="stylesheet" href="/__farm_client_css_href__">' + renderFarmClientModulePreloads(fullDocument); })
9227
9392
  .replace(/<\\/head>/i, () => renderFarmRendererHydrationScript() + '\\n</head>')
9228
9393
  .replace(
9229
9394
  /<\\/body>/i,
9230
9395
  () => ' ' + renderFarmClientBootstrapScript() + '\\n' +
9231
- ' <script type="module" src="/__farm_client_js_src__"></script>\\n</body>',
9396
+ ' ' + renderFarmClientEntryScript() + '\\n</body>',
9232
9397
  );
9233
9398
  fullHtml = ensureFarmDocumentMeta(fullHtml, notFoundMetadata.viewport);
9234
9399
  if (!fullHtml.trim().startsWith('<!DOCTYPE')) {
@@ -9241,14 +9406,14 @@ ${servesDefaultMCP ? `
9241
9406
  <meta charset="UTF-8">
9242
9407
  \${notFoundMetadata.viewport}
9243
9408
  \${notFoundMetadata.hasFavicon ? "" : '<link rel="icon" href="data:,">'}
9244
- <link rel="stylesheet" href="/__farm_client_css_href__">
9409
+ <link rel="stylesheet" href="/__farm_client_css_href__">\${renderFarmClientModulePreloads(html)}
9245
9410
  <title>\${notFoundMetadata.title}</title>\${notFoundMetadata.tags}
9246
9411
  \${renderFarmRendererHydrationScript()}
9247
9412
  </head>
9248
9413
  <body>
9249
9414
  <div id="root">\${html}</div>
9250
9415
  \${renderFarmClientBootstrapScript()}
9251
- <script type="module" src="/__farm_client_js_src__"></script>
9416
+ \${renderFarmClientEntryScript()}
9252
9417
  </body>
9253
9418
  </html>\`;
9254
9419
  }
@@ -9382,6 +9547,9 @@ async function handleFarmFetch(request, context) {
9382
9547
  () =>
9383
9548
  runWithFarmRequestSpan(request, async () => {
9384
9549
  const runtimeOptions = farmPluginRuntime ? getFarmPluginRequestOptions(request) : null;
9550
+ // Created before rendering so only scripts Farm, the renderer, or the
9551
+ // app (through getCspNonce()) give it carry the response nonce.
9552
+ const cspNonce = createFarmCspNonce(farmSecurityConfig);
9385
9553
  const prepareResponse = async (runtimeRequest, responsePromise) => {
9386
9554
  const response = await responsePromise;
9387
9555
  // Headers need the path eagerly; preload reporting needs it only for
@@ -9393,6 +9561,7 @@ async function handleFarmFetch(request, context) {
9393
9561
  applyFarmCspNonceToResponse(
9394
9562
  applyConfiguredResponseHeaders(response, routePathname),
9395
9563
  farmSecurityConfig,
9564
+ cspNonce,
9396
9565
  ),
9397
9566
  routePathname,
9398
9567
  runtimeRequest,
@@ -9425,7 +9594,7 @@ async function handleFarmFetch(request, context) {
9425
9594
  : ` : ""}prepareResponse(request, handleFarmRequest(request, context));
9426
9595
 
9427
9596
  const response = await _runWithCurrentRequest(request, () =>
9428
- _runWithAfterRequest(request, runRequest, context),
9597
+ _runWithFarmCspNonce(cspNonce, () => _runWithAfterRequest(request, runRequest, context)),
9429
9598
  );
9430
9599
  return ${hasCompressionRuntime && !hasPluginRuntime ? "compressFarmResponse(request, response, getFarmOwnedBufferedHtml(response), farmLazyBufferedHtml.has(response))" : "response"};
9431
9600
  }),
@@ -9500,26 +9669,6 @@ function middlewarePatternMatches(pattern, pathname) {
9500
9669
  return new RegExp(`^${expression}/?$`).test(pathname);
9501
9670
  }
9502
9671
  __name(middlewarePatternMatches, "middlewarePatternMatches");
9503
- function configMiddlewareMayHandlePath(config, pathname) {
9504
- if (!hasFarmMiddlewareConfig(config)) return false;
9505
- const entries = Array.isArray(config) ? config : [config];
9506
- return entries.some((entry) => {
9507
- if (!entry.matcher && !entry.exclude) return true;
9508
- const matchers = entry.matcher ? (Array.isArray(entry.matcher) ? entry.matcher : [entry.matcher]).map(
9509
- (matcher) => (
9510
- // A request-aware matcher cannot be proven safe at build time.
9511
- typeof matcher === "function" ? () => true : matcher
9512
- )
9513
- ) : void 0;
9514
- const compiled = compileMiddlewareConfig({ matcher: matchers, exclude: entry.exclude });
9515
- return matchesCompiledMiddlewareConfig(pathname, compiled, {}).matched;
9516
- });
9517
- }
9518
- __name(configMiddlewareMayHandlePath, "configMiddlewareMayHandlePath");
9519
- function appMiddlewareMayHandlePath(middlewareRoutes, pathname) {
9520
- return middlewareRoutes.some((route) => matchesMiddlewareRoute(pathname, route).matched);
9521
- }
9522
- __name(appMiddlewareMayHandlePath, "appMiddlewareMayHandlePath");
9523
9672
  function routePatternSpecificity(pattern) {
9524
9673
  return pattern.split("/").filter(Boolean).reduce((score, segment) => {
9525
9674
  if (segment === "**" || segment.startsWith("[[...")) return score + 1;
@@ -9575,7 +9724,7 @@ function getPhysicalPrerenderBypassReason(options) {
9575
9724
  }
9576
9725
  __name(getPhysicalPrerenderBypassReason, "getPhysicalPrerenderBypassReason");
9577
9726
  async function buildNitroUniversal(config, routeManager, apiRouteManager, serverRenderer, preset, root, distDir, ssrBundle, ssrEntryFile, clientOutputDir, routeRuntimeManifest, configuredHeaderRoutes, nitroBuilderResultPromise, pluginManager) {
9578
- const [fs, nitroBuilderResult] = await Promise.all([
9727
+ const [fs3, nitroBuilderResult] = await Promise.all([
9579
9728
  import("fs/promises"),
9580
9729
  nitroBuilderResultPromise
9581
9730
  ]);
@@ -9584,8 +9733,8 @@ async function buildNitroUniversal(config, routeManager, apiRouteManager, server
9584
9733
  const isVercel = preset === "vercel" || preset === "vercel-edge";
9585
9734
  const isCloudflareWorker = preset === "cloudflare-module";
9586
9735
  const outputDir = resolveDeployOutputPath(root, config.deploy.outputDir);
9587
- const runtimeServerOutputDir = isVercel ? path6.join(outputDir, "functions", "__nitro.func") : path6.join(outputDir, "server");
9588
- const ssrOutputDir = path6.join(root, distDir, "ssr");
9736
+ const runtimeServerOutputDir = isVercel ? path8.join(outputDir, "functions", "__nitro.func") : path8.join(outputDir, "server");
9737
+ const ssrOutputDir = path8.join(root, distDir, "ssr");
9589
9738
  const imageRuntime = resolveImageRuntime(config, preset);
9590
9739
  const hasGeneratedMetadataImages = Array.from(routeManager.getMetadataImages().values()).some(
9591
9740
  (image) => image.sourceType === "module"
@@ -9654,12 +9803,22 @@ async function buildNitroUniversal(config, routeManager, apiRouteManager, server
9654
9803
  }
9655
9804
  const scheduledTasks = mergeScheduledTasks(farmWorkflows.scheduledTasks, farmCron.scheduledTasks);
9656
9805
  const cloudflareCronConfig = createFarmCronCloudflareConfig(farmCron.jobs);
9657
- const [clientCssHref, clientJsSrc] = await Promise.all([
9806
+ const [clientCssHref, clientJsSrc, docsModulePreloads, clientModulePreloads] = await Promise.all([
9658
9807
  resolveHashedClientCssHref(clientOutputDir),
9659
- resolveHashedClientJsSrc(clientOutputDir)
9808
+ resolveHashedClientJsSrc(clientOutputDir),
9809
+ readFarmDocsModulePreloads(path8.join(root, distDir)),
9810
+ readFarmClientModulePreloads(path8.join(root, distDir))
9660
9811
  ]);
9812
+ const encodedDocsModulePreloads = encodeFarmDocsModulePreloads(docsModulePreloads);
9813
+ const encodedClientModulePreloads = encodeFarmClientModulePreloads(clientModulePreloads);
9661
9814
  for (const output of Object.values(ssrBundle)) {
9662
9815
  if (output.type !== "chunk") continue;
9816
+ if (output.code.includes(FARM_DOCS_MODULE_PRELOADS_PLACEHOLDER)) {
9817
+ output.code = output.code.split(FARM_DOCS_MODULE_PRELOADS_PLACEHOLDER).join(encodedDocsModulePreloads);
9818
+ }
9819
+ if (output.code.includes(FARM_CLIENT_MODULE_PRELOADS_PLACEHOLDER)) {
9820
+ output.code = output.code.split(FARM_CLIENT_MODULE_PRELOADS_PLACEHOLDER).join(encodedClientModulePreloads);
9821
+ }
9663
9822
  if (output.code.includes(FARM_CLIENT_CSS_HREF_PLACEHOLDER)) {
9664
9823
  output.code = output.code.split(FARM_CLIENT_CSS_HREF_PLACEHOLDER).join(clientCssHref);
9665
9824
  }
@@ -9667,13 +9826,13 @@ async function buildNitroUniversal(config, routeManager, apiRouteManager, server
9667
9826
  output.code = output.code.split(FARM_CLIENT_JS_SRC_PLACEHOLDER).join(clientJsSrc);
9668
9827
  }
9669
9828
  }
9670
- await fs.mkdir(ssrOutputDir, { recursive: true });
9829
+ await fs3.mkdir(ssrOutputDir, { recursive: true });
9671
9830
  for (const [fileName, output] of Object.entries(ssrBundle)) {
9672
- const filePath = path6.join(ssrOutputDir, fileName);
9673
- await fs.mkdir(path6.dirname(filePath), { recursive: true });
9674
- await fs.writeFile(filePath, output.type === "chunk" ? output.code : output.source);
9831
+ const filePath = path8.join(ssrOutputDir, fileName);
9832
+ await fs3.mkdir(path8.dirname(filePath), { recursive: true });
9833
+ await fs3.writeFile(filePath, output.type === "chunk" ? output.code : output.source);
9675
9834
  }
9676
- const nitroEntryPath = path6.join(ssrOutputDir, "nitro-entry.mjs");
9835
+ const nitroEntryPath = path8.join(ssrOutputDir, "nitro-entry.mjs");
9677
9836
  const nodeAdapterModule = preset === "node-server" ? resolveNitroRuntimeDependency(root, "srvx/node") : null;
9678
9837
  const nitroEntryCode = `
9679
9838
  // Farm.js Nitro Entry
@@ -9825,26 +9984,26 @@ function toFarmNodeResponse(request, response) {
9825
9984
  })
9826
9985
  }` : ""}
9827
9986
  `.trim();
9828
- await fs.writeFile(nitroEntryPath, nitroEntryCode);
9829
- const farmNodeServerEntryPath = preset === "node-server" ? path6.join(ssrOutputDir, "farm-node-server-entry.mjs") : null;
9987
+ await fs3.writeFile(nitroEntryPath, nitroEntryCode);
9988
+ const farmNodeServerEntryPath = preset === "node-server" ? path8.join(ssrOutputDir, "farm-node-server-entry.mjs") : null;
9830
9989
  if (farmNodeServerEntryPath && nodeAdapterModule) {
9831
- await fs.writeFile(
9832
- path6.join(ssrOutputDir, FARM_NODE_ENV_MODULE_FILE),
9990
+ await fs3.writeFile(
9991
+ path8.join(ssrOutputDir, FARM_NODE_ENV_MODULE_FILE),
9833
9992
  FARM_NODE_ENV_MODULE_SOURCE
9834
9993
  );
9835
- await fs.writeFile(
9994
+ await fs3.writeFile(
9836
9995
  farmNodeServerEntryPath,
9837
9996
  createFarmNodeServerEntry({
9838
- nitroEntryFile: path6.basename(nitroEntryPath),
9997
+ nitroEntryFile: path8.basename(nitroEntryPath),
9839
9998
  nodeAdapterModule,
9840
9999
  server: config.server,
9841
10000
  websocketAdapterModule: resolveNitroRuntimeDependency(root, "crossws/adapters/node")
9842
10001
  })
9843
10002
  );
9844
10003
  }
9845
- const farmNetlifyEntryPath = preset === "netlify" ? path6.join(ssrOutputDir, "farm-netlify-entry.mjs") : null;
10004
+ const farmNetlifyEntryPath = preset === "netlify" ? path8.join(ssrOutputDir, "farm-netlify-entry.mjs") : null;
9846
10005
  if (farmNetlifyEntryPath) {
9847
- await fs.writeFile(
10006
+ await fs3.writeFile(
9848
10007
  farmNetlifyEntryPath,
9849
10008
  createFarmNetlifyEntry({
9850
10009
  nitroNetlifyEntry: resolveNitroNetlifyEntry(resolveNitroPackageEntry(root))
@@ -9884,7 +10043,7 @@ function toFarmNodeResponse(request, response) {
9884
10043
  // `src` directory), as Nitro handlers outside Farm's aliases.
9885
10044
  serverDir: false,
9886
10045
  serverEntry: false,
9887
- buildDir: path6.join(root, distDir, ".nitro"),
10046
+ buildDir: path8.join(root, distDir, ".nitro"),
9888
10047
  alias: resolveNitroInternalRuntimeAliases(root),
9889
10048
  compatibilityDate: "2024-12-01",
9890
10049
  output: resolveFarmNitroOutputConfig(preset, outputDir),
@@ -9960,7 +10119,7 @@ function toFarmNodeResponse(request, response) {
9960
10119
  if (pluginManager) {
9961
10120
  nitroConfig = await pluginManager.runHookSerial("beforeNitroBuild", nitroConfig);
9962
10121
  }
9963
- const expectedServerDir = path6.join(outputDir, "server");
10122
+ const expectedServerDir = path8.join(outputDir, "server");
9964
10123
  const customRollupKeys = Object.keys(nitroConfig.rollupConfig || {}).filter(
9965
10124
  (key) => key !== "external" && key !== "plugins"
9966
10125
  );
@@ -9973,9 +10132,9 @@ function toFarmNodeResponse(request, response) {
9973
10132
  snapshotSSRRebundleOptions(nitroConfig)
9974
10133
  );
9975
10134
  const requestedBuilder = nitroConfig.builder ?? process.env.NITRO_BUILDER;
9976
- const canReusePrebuiltSSR = isPrebuiltSSRCandidate && nitroConfig.preset === "node-server" && (requestedBuilder === void 0 || requestedBuilder === "rollup" || requestedBuilder === "rolldown") && nitroConfig.sourcemap === false && !hasCustomOxcOptions && !hasLateBuildMutationConfig && !hasUnsupportedSSRRebundleOverrides && nitroConfig.rollupConfig?.external === nitroRollupExternal && !hasRollupPlugins(nitroConfig.rollupConfig?.plugins) && customRollupKeys.length === 0 && path6.resolve(nitroConfig.output?.serverDir || "") === path6.resolve(expectedServerDir) && Boolean(
10135
+ const canReusePrebuiltSSR = isPrebuiltSSRCandidate && nitroConfig.preset === "node-server" && (requestedBuilder === void 0 || requestedBuilder === "rollup" || requestedBuilder === "rolldown") && nitroConfig.sourcemap === false && !hasCustomOxcOptions && !hasLateBuildMutationConfig && !hasUnsupportedSSRRebundleOverrides && nitroConfig.rollupConfig?.external === nitroRollupExternal && !hasRollupPlugins(nitroConfig.rollupConfig?.plugins) && customRollupKeys.length === 0 && path8.resolve(nitroConfig.output?.serverDir || "") === path8.resolve(expectedServerDir) && Boolean(
9977
10136
  nitroConfig.handlers?.some(
9978
- (handler) => path6.resolve(handler?.handler || "") === nitroEntryPath
10137
+ (handler) => path8.resolve(handler?.handler || "") === nitroEntryPath
9979
10138
  )
9980
10139
  );
9981
10140
  const selectRolldownBuilder = canReusePrebuiltSSR && requestedBuilder === void 0 && await canUseRolldownBuilder();
@@ -10062,14 +10221,14 @@ function toFarmNodeResponse(request, response) {
10062
10221
  });
10063
10222
  }
10064
10223
  prerenderer.hooks.hook("compiled", async () => {
10065
- const prerenderServerDir = path6.join(outputDir, "server");
10224
+ const prerenderServerDir = path8.join(outputDir, "server");
10066
10225
  await copyPrebuiltSSRBundle(
10067
10226
  ssrBundle,
10068
- path6.join(prerenderServerDir, FARM_SSR_OUTPUT_DIR),
10227
+ path8.join(prerenderServerDir, FARM_SSR_OUTPUT_DIR),
10069
10228
  null,
10070
- fs
10229
+ fs3
10071
10230
  );
10072
- await registerPrebuiltSSRPackageImport(prerenderServerDir, ssrEntryFile, fs);
10231
+ await registerPrebuiltSSRPackageImport(prerenderServerDir, ssrEntryFile, fs3);
10073
10232
  });
10074
10233
  });
10075
10234
  }
@@ -10100,7 +10259,7 @@ function toFarmNodeResponse(request, response) {
10100
10259
  else process.env[FARM_PRERENDER_ENV] = previousPrerender;
10101
10260
  }
10102
10261
  }
10103
- const sharpRuntimeStagePromise = imageRuntime === "node" ? stageSharpRuntime(config, root, distDir, fs, preset) : Promise.resolve(null);
10262
+ const sharpRuntimeStagePromise = imageRuntime === "node" ? stageSharpRuntime(config, root, distDir, fs3, preset) : Promise.resolve(null);
10104
10263
  const prebuiltSSRFilesPromise = canReusePrebuiltSSR ? prepareSSRBundleFiles(
10105
10264
  ssrBundle,
10106
10265
  shouldMinify ? { keepNames: keepServerNames, target: "node18" } : null
@@ -10113,7 +10272,7 @@ function toFarmNodeResponse(request, response) {
10113
10272
  await nitroInstance.close();
10114
10273
  if (nitroBuildResult.status === "rejected") {
10115
10274
  if (sharpRuntimeStageResult.status === "fulfilled" && sharpRuntimeStageResult.value) {
10116
- await fs.rm(sharpRuntimeStageResult.value.stageDir, {
10275
+ await fs3.rm(sharpRuntimeStageResult.value.stageDir, {
10117
10276
  recursive: true,
10118
10277
  force: true
10119
10278
  });
@@ -10126,20 +10285,20 @@ function toFarmNodeResponse(request, response) {
10126
10285
  if (prebuiltSSRFilesResult.status === "rejected") {
10127
10286
  throw prebuiltSSRFilesResult.reason;
10128
10287
  }
10129
- const stagedSharpRuntime = sharpRuntimeStageResult.value ?? (imageRuntime === "node" ? await stageSharpRuntime(config, root, distDir, fs, preset) : null);
10288
+ const stagedSharpRuntime = sharpRuntimeStageResult.value ?? (imageRuntime === "node" ? await stageSharpRuntime(config, root, distDir, fs3, preset) : null);
10130
10289
  const runtimeCopyPromise = (async () => {
10131
10290
  if (stagedSharpRuntime) {
10132
- await installStagedSharpRuntime(stagedSharpRuntime, runtimeServerOutputDir, fs);
10291
+ await installStagedSharpRuntime(stagedSharpRuntime, runtimeServerOutputDir, fs3);
10133
10292
  }
10134
10293
  if (useExternalMetadataImageRuntime) {
10135
- await copyMetadataImageRuntime(root, runtimeServerOutputDir, fs);
10294
+ await copyMetadataImageRuntime(root, runtimeServerOutputDir, fs3);
10136
10295
  }
10137
10296
  })();
10138
10297
  const copyResults = await Promise.allSettled([
10139
10298
  prebuiltSSRFilesResult.value ? writeSSRBundleFiles(
10140
10299
  prebuiltSSRFilesResult.value,
10141
- path6.join(outputDir, "server", FARM_SSR_OUTPUT_DIR),
10142
- fs
10300
+ path8.join(outputDir, "server", FARM_SSR_OUTPUT_DIR),
10301
+ fs3
10143
10302
  ) : Promise.resolve(),
10144
10303
  runtimeCopyPromise
10145
10304
  ]);
@@ -10148,7 +10307,7 @@ function toFarmNodeResponse(request, response) {
10148
10307
  );
10149
10308
  if (failedCopy) throw failedCopy.reason;
10150
10309
  if (canReusePrebuiltSSR) {
10151
- await registerPrebuiltSSRPackageImport(path6.join(outputDir, "server"), ssrEntryFile, fs);
10310
+ await registerPrebuiltSSRPackageImport(path8.join(outputDir, "server"), ssrEntryFile, fs3);
10152
10311
  logger.info("\u26A1 Reused Farm's prebuilt SSR bundle for the Node output");
10153
10312
  }
10154
10313
  if (useRolldownBuilder) {
@@ -10163,7 +10322,7 @@ function toFarmNodeResponse(request, response) {
10163
10322
  });
10164
10323
  }
10165
10324
  if (isVercel) {
10166
- await postProcessVercelOutput(root, outputDir, fs, config, farmWorkflows, routeRuntimeManifest);
10325
+ await postProcessVercelOutput(root, outputDir, fs3, config, farmWorkflows, routeRuntimeManifest);
10167
10326
  }
10168
10327
  logger.success(`\u2705 Nitro build completed with preset: ${preset}`);
10169
10328
  }
@@ -10173,11 +10332,11 @@ function resolveFarmNitroOutputConfig(preset, outputDir) {
10173
10332
  return {
10174
10333
  dir: outputDir,
10175
10334
  ...preset === "node-server" ? {
10176
- serverDir: path6.join(outputDir, "server"),
10177
- publicDir: path6.join(outputDir, "public")
10335
+ serverDir: path8.join(outputDir, "server"),
10336
+ publicDir: path8.join(outputDir, "public")
10178
10337
  } : isVercel ? {
10179
- serverDir: path6.join(outputDir, "functions", "__nitro.func"),
10180
- publicDir: path6.join(outputDir, "static")
10338
+ serverDir: path8.join(outputDir, "functions", "__nitro.func"),
10339
+ publicDir: path8.join(outputDir, "static")
10181
10340
  } : {}
10182
10341
  };
10183
10342
  }
@@ -10191,24 +10350,24 @@ function prepareSSRBundleFiles(ssrBundle, minifyOptions) {
10191
10350
  );
10192
10351
  }
10193
10352
  __name(prepareSSRBundleFiles, "prepareSSRBundleFiles");
10194
- async function writeSSRBundleFiles(files, targetDir, fs) {
10195
- await fs.rm(targetDir, { recursive: true, force: true });
10353
+ async function writeSSRBundleFiles(files, targetDir, fs3) {
10354
+ await fs3.rm(targetDir, { recursive: true, force: true });
10196
10355
  await Promise.all(
10197
10356
  files.map(async ({ fileName, contents }) => {
10198
- const targetPath = path6.join(targetDir, fileName);
10199
- await fs.mkdir(path6.dirname(targetPath), { recursive: true });
10200
- await fs.writeFile(targetPath, contents);
10357
+ const targetPath = path8.join(targetDir, fileName);
10358
+ await fs3.mkdir(path8.dirname(targetPath), { recursive: true });
10359
+ await fs3.writeFile(targetPath, contents);
10201
10360
  })
10202
10361
  );
10203
10362
  }
10204
10363
  __name(writeSSRBundleFiles, "writeSSRBundleFiles");
10205
- async function copyPrebuiltSSRBundle(ssrBundle, targetDir, minifyOptions, fs) {
10206
- await writeSSRBundleFiles(await prepareSSRBundleFiles(ssrBundle, minifyOptions), targetDir, fs);
10364
+ async function copyPrebuiltSSRBundle(ssrBundle, targetDir, minifyOptions, fs3) {
10365
+ await writeSSRBundleFiles(await prepareSSRBundleFiles(ssrBundle, minifyOptions), targetDir, fs3);
10207
10366
  }
10208
10367
  __name(copyPrebuiltSSRBundle, "copyPrebuiltSSRBundle");
10209
- async function registerPrebuiltSSRPackageImport(serverDir, ssrEntryFile, fs) {
10210
- const packagePath = path6.join(serverDir, "package.json");
10211
- const packageJSON = await fs.readFile(packagePath, "utf8").then((contents) => JSON.parse(contents)).catch((error) => {
10368
+ async function registerPrebuiltSSRPackageImport(serverDir, ssrEntryFile, fs3) {
10369
+ const packagePath = path8.join(serverDir, "package.json");
10370
+ const packageJSON = await fs3.readFile(packagePath, "utf8").then((contents) => JSON.parse(contents)).catch((error) => {
10212
10371
  if (error.code === "ENOENT") return { type: "module" };
10213
10372
  throw error;
10214
10373
  });
@@ -10218,14 +10377,14 @@ async function registerPrebuiltSSRPackageImport(serverDir, ssrEntryFile, fs) {
10218
10377
  ...existingImports,
10219
10378
  [FARM_SSR_PACKAGE_IMPORT]: `./${outputEntry}`
10220
10379
  };
10221
- await fs.mkdir(serverDir, { recursive: true });
10222
- await fs.writeFile(packagePath, `${JSON.stringify(packageJSON, null, 2)}
10380
+ await fs3.mkdir(serverDir, { recursive: true });
10381
+ await fs3.writeFile(packagePath, `${JSON.stringify(packageJSON, null, 2)}
10223
10382
  `);
10224
10383
  }
10225
10384
  __name(registerPrebuiltSSRPackageImport, "registerPrebuiltSSRPackageImport");
10226
- async function moveVercelOutputPath(src, dest, fs) {
10385
+ async function moveVercelOutputPath(src, dest, fs3) {
10227
10386
  try {
10228
- await fs.rename(src, dest);
10387
+ await fs3.rename(src, dest);
10229
10388
  return;
10230
10389
  } catch (error) {
10231
10390
  const code = error?.code;
@@ -10233,39 +10392,39 @@ async function moveVercelOutputPath(src, dest, fs) {
10233
10392
  throw error;
10234
10393
  }
10235
10394
  }
10236
- await fs.cp(src, dest, { recursive: true, force: true });
10237
- await fs.rm(src, { recursive: true, force: true });
10395
+ await fs3.cp(src, dest, { recursive: true, force: true });
10396
+ await fs3.rm(src, { recursive: true, force: true });
10238
10397
  }
10239
10398
  __name(moveVercelOutputPath, "moveVercelOutputPath");
10240
- async function postProcessVercelOutput(root, outputDir, fs, config, farmWorkflows, routeRuntimeManifest) {
10241
- const serverDir = path6.join(outputDir, "server");
10242
- const functionsDir = path6.join(outputDir, "functions");
10243
- const nitroFuncDir = path6.join(functionsDir, "__nitro.func");
10244
- const staticDir = path6.join(outputDir, "static");
10245
- const publicDir = path6.join(outputDir, "public");
10246
- await fs.mkdir(nitroFuncDir, { recursive: true });
10247
- const serverContents = await fs.readdir(serverDir).catch((error) => {
10399
+ async function postProcessVercelOutput(root, outputDir, fs3, config, farmWorkflows, routeRuntimeManifest) {
10400
+ const serverDir = path8.join(outputDir, "server");
10401
+ const functionsDir = path8.join(outputDir, "functions");
10402
+ const nitroFuncDir = path8.join(functionsDir, "__nitro.func");
10403
+ const staticDir = path8.join(outputDir, "static");
10404
+ const publicDir = path8.join(outputDir, "public");
10405
+ await fs3.mkdir(nitroFuncDir, { recursive: true });
10406
+ const serverContents = await fs3.readdir(serverDir).catch((error) => {
10248
10407
  if (error.code === "ENOENT") return [];
10249
10408
  throw error;
10250
10409
  });
10251
10410
  for (const file of serverContents) {
10252
- await moveVercelOutputPath(path6.join(serverDir, file), path6.join(nitroFuncDir, file), fs);
10411
+ await moveVercelOutputPath(path8.join(serverDir, file), path8.join(nitroFuncDir, file), fs3);
10253
10412
  }
10254
- if (serverContents.length > 0) await fs.rm(serverDir, { recursive: true, force: true });
10413
+ if (serverContents.length > 0) await fs3.rm(serverDir, { recursive: true, force: true });
10255
10414
  try {
10256
- await moveVercelOutputPath(publicDir, staticDir, fs);
10415
+ await moveVercelOutputPath(publicDir, staticDir, fs3);
10257
10416
  } catch (error) {
10258
10417
  if (error?.code !== "ENOENT") throw error;
10259
10418
  }
10260
- await copyFarmDocsContentForVercel(config, root, nitroFuncDir, fs);
10261
- await copyPrismaClientForVercel(root, nitroFuncDir, fs);
10262
- const configPath = path6.join(outputDir, "config.json");
10263
- const configContent = await fs.readFile(configPath, "utf-8");
10419
+ await copyFarmDocsContentForVercel(config, root, nitroFuncDir, fs3);
10420
+ await copyPrismaClientForVercel(root, nitroFuncDir, fs3);
10421
+ const configPath = path8.join(outputDir, "config.json");
10422
+ const configContent = await fs3.readFile(configPath, "utf-8");
10264
10423
  const vercelConfig = JSON.parse(configContent);
10265
10424
  const runtimeRoutes = await createFarmVercelRouteRuntimeFunctions(
10266
10425
  outputDir,
10267
10426
  routeRuntimeManifest,
10268
- fs,
10427
+ fs3,
10269
10428
  config.basePath
10270
10429
  );
10271
10430
  vercelConfig.routes = buildFarmVercelRoutes({
@@ -10280,29 +10439,29 @@ async function postProcessVercelOutput(root, outputDir, fs, config, farmWorkflow
10280
10439
  vercelConfigWithWorkflowCrons,
10281
10440
  config.cron.jobs
10282
10441
  );
10283
- await fs.writeFile(configPath, JSON.stringify(vercelConfigWithCrons, null, 2));
10442
+ await fs3.writeFile(configPath, JSON.stringify(vercelConfigWithCrons, null, 2));
10284
10443
  logger.info("\u2705 Post-processed Vercel output for Build Output API v3");
10285
10444
  }
10286
10445
  __name(postProcessVercelOutput, "postProcessVercelOutput");
10287
- async function copyFarmDocsContentForVercel(config, root, nitroFuncDir, fs) {
10446
+ async function copyFarmDocsContentForVercel(config, root, nitroFuncDir, fs3) {
10288
10447
  const docsContentDir = resolveBuildDocsContentDir(config, root);
10289
10448
  if (!docsContentDir) return;
10290
- const bundledContentDir = path6.join(nitroFuncDir, "farm-docs-content");
10449
+ const bundledContentDir = path8.join(nitroFuncDir, "farm-docs-content");
10291
10450
  const lastModifiedManifest = createFarmDocsLastModifiedManifest(docsContentDir, {
10292
10451
  fallback: "now"
10293
10452
  });
10294
- await fs.rm(bundledContentDir, { recursive: true, force: true });
10295
- await fs.mkdir(path6.dirname(bundledContentDir), { recursive: true });
10296
- await fs.cp(docsContentDir, bundledContentDir, {
10453
+ await fs3.rm(bundledContentDir, { recursive: true, force: true });
10454
+ await fs3.mkdir(path8.dirname(bundledContentDir), { recursive: true });
10455
+ await fs3.cp(docsContentDir, bundledContentDir, {
10297
10456
  recursive: true,
10298
10457
  force: true
10299
10458
  });
10300
- await fs.writeFile(
10301
- path6.join(bundledContentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST),
10459
+ await fs3.writeFile(
10460
+ path8.join(bundledContentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST),
10302
10461
  `${JSON.stringify(lastModifiedManifest, null, 2)}
10303
10462
  `
10304
10463
  );
10305
- logger.info(`\u{1F4DA} Bundled docs content for Vercel: ${path6.relative(root, docsContentDir)}`);
10464
+ logger.info(`\u{1F4DA} Bundled docs content for Vercel: ${path8.relative(root, docsContentDir)}`);
10306
10465
  }
10307
10466
  __name(copyFarmDocsContentForVercel, "copyFarmDocsContentForVercel");
10308
10467
  function resolveServerFunctionPlatform(preset) {
@@ -10321,9 +10480,9 @@ function platformFieldAllows(field, value) {
10321
10480
  return allowed.length === 0 || allowed.includes(value);
10322
10481
  }
10323
10482
  __name(platformFieldAllows, "platformFieldAllows");
10324
- async function stageSharpRuntime(config, root, distDir, fs, preset) {
10483
+ async function stageSharpRuntime(config, root, distDir, fs3, preset) {
10325
10484
  const functionPlatform = resolveServerFunctionPlatform(preset);
10326
- const projectRequire = createRequire(path6.join(root, "package.json"));
10485
+ const projectRequire = createRequire(path8.join(root, "package.json"));
10327
10486
  let sharpRequire = projectRequire;
10328
10487
  if (!resolvePackageJson(projectRequire, "sharp")) {
10329
10488
  try {
@@ -10333,10 +10492,10 @@ async function stageSharpRuntime(config, root, distDir, fs, preset) {
10333
10492
  }
10334
10493
  const copiedPackages = /* @__PURE__ */ new Map();
10335
10494
  const packageCopies = /* @__PURE__ */ new Map();
10336
- const stageRoot = path6.join(root, distDir, "tmp");
10337
- await fs.mkdir(stageRoot, { recursive: true });
10338
- const stageDir = await fs.mkdtemp(path6.join(stageRoot, "sharp-runtime-"));
10339
- const targetNodeModules = path6.join(stageDir, "node_modules");
10495
+ const stageRoot = path8.join(root, distDir, "tmp");
10496
+ await fs3.mkdir(stageRoot, { recursive: true });
10497
+ const stageDir = await fs3.mkdtemp(path8.join(stageRoot, "sharp-runtime-"));
10498
+ const targetNodeModules = path8.join(stageDir, "node_modules");
10340
10499
  function copyPackage(packageName, parentRequire) {
10341
10500
  const activeCopy = packageCopies.get(packageName);
10342
10501
  if (activeCopy) return activeCopy;
@@ -10348,19 +10507,19 @@ async function stageSharpRuntime(config, root, distDir, fs, preset) {
10348
10507
  async function copyPackageOnce(packageName, parentRequire) {
10349
10508
  const packageJsonPath = resolvePackageJson(parentRequire, packageName);
10350
10509
  if (!packageJsonPath) return;
10351
- const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf8"));
10510
+ const packageJson = JSON.parse(await fs3.readFile(packageJsonPath, "utf8"));
10352
10511
  if (functionPlatform && !packageSupportsPlatform(packageJson, functionPlatform)) return;
10353
- const packageDir = path6.dirname(packageJsonPath);
10354
- const targetDir = path6.join(targetNodeModules, ...packageName.split("/"));
10512
+ const packageDir = path8.dirname(packageJsonPath);
10513
+ const targetDir = path8.join(targetNodeModules, ...packageName.split("/"));
10355
10514
  copiedPackages.set(packageName, String(packageJson.version || "*"));
10356
- await fs.mkdir(path6.dirname(targetDir), { recursive: true });
10515
+ await fs3.mkdir(path8.dirname(targetDir), { recursive: true });
10357
10516
  const packageRequire = createRequire(packageJsonPath);
10358
10517
  const dependencies = {
10359
10518
  ...packageJson.dependencies,
10360
10519
  ...packageJson.optionalDependencies
10361
10520
  };
10362
10521
  await settleAllOrThrow([
10363
- fs.cp(packageDir, targetDir, {
10522
+ fs3.cp(packageDir, targetDir, {
10364
10523
  recursive: true,
10365
10524
  force: true,
10366
10525
  dereference: true,
@@ -10378,7 +10537,7 @@ async function stageSharpRuntime(config, root, distDir, fs, preset) {
10378
10537
  throw new Error(`Farm image optimization requires sharp. ${SHARP_INSTALL_HINT}`);
10379
10538
  }
10380
10539
  } catch (error) {
10381
- await fs.rm(stageDir, { recursive: true, force: true });
10540
+ await fs3.rm(stageDir, { recursive: true, force: true });
10382
10541
  throw error;
10383
10542
  }
10384
10543
  return {
@@ -10389,19 +10548,19 @@ async function stageSharpRuntime(config, root, distDir, fs, preset) {
10389
10548
  };
10390
10549
  }
10391
10550
  __name(stageSharpRuntime, "stageSharpRuntime");
10392
- async function installStagedSharpRuntime(staged, nitroFuncDir, fs) {
10393
- const stagedNodeModules = path6.join(staged.stageDir, "node_modules");
10394
- const targetNodeModules = path6.join(nitroFuncDir, "node_modules");
10551
+ async function installStagedSharpRuntime(staged, nitroFuncDir, fs3) {
10552
+ const stagedNodeModules = path8.join(staged.stageDir, "node_modules");
10553
+ const targetNodeModules = path8.join(nitroFuncDir, "node_modules");
10395
10554
  try {
10396
- await mergeStagedDirectory(stagedNodeModules, targetNodeModules, fs);
10397
- const functionPackage = await readNitroOutputPackage(nitroFuncDir, fs);
10555
+ await mergeStagedDirectory(stagedNodeModules, targetNodeModules, fs3);
10556
+ const functionPackage = await readNitroOutputPackage(nitroFuncDir, fs3);
10398
10557
  functionPackage.dependencies = {
10399
10558
  ...functionPackage.dependencies,
10400
10559
  ...staged.dependencies
10401
10560
  };
10402
- await writeNitroOutputPackage(nitroFuncDir, functionPackage, fs);
10561
+ await writeNitroOutputPackage(nitroFuncDir, functionPackage, fs3);
10403
10562
  } finally {
10404
- await fs.rm(staged.stageDir, { recursive: true, force: true });
10563
+ await fs3.rm(staged.stageDir, { recursive: true, force: true });
10405
10564
  }
10406
10565
  logger.info(
10407
10566
  `\u{1F5BC}\uFE0F Bundled Sharp image runtime (${Object.keys(staged.dependencies).length} packages)`
@@ -10416,15 +10575,15 @@ async function settleAllOrThrow(operations) {
10416
10575
  if (failure) throw failure.reason;
10417
10576
  }
10418
10577
  __name(settleAllOrThrow, "settleAllOrThrow");
10419
- async function mergeStagedDirectory(sourceDir, targetDir, fs) {
10420
- await fs.mkdir(targetDir, { recursive: true });
10421
- const entries = await fs.readdir(sourceDir, { withFileTypes: true });
10578
+ async function mergeStagedDirectory(sourceDir, targetDir, fs3) {
10579
+ await fs3.mkdir(targetDir, { recursive: true });
10580
+ const entries = await fs3.readdir(sourceDir, { withFileTypes: true });
10422
10581
  await settleAllOrThrow(
10423
10582
  entries.map(async (entry) => {
10424
- const sourcePath = path6.join(sourceDir, entry.name);
10425
- const targetPath = path6.join(targetDir, entry.name);
10583
+ const sourcePath = path8.join(sourceDir, entry.name);
10584
+ const targetPath = path8.join(targetDir, entry.name);
10426
10585
  try {
10427
- await fs.rename(sourcePath, targetPath);
10586
+ await fs3.rename(sourcePath, targetPath);
10428
10587
  return;
10429
10588
  } catch (error) {
10430
10589
  const code = error.code;
@@ -10433,16 +10592,16 @@ async function mergeStagedDirectory(sourceDir, targetDir, fs) {
10433
10592
  }
10434
10593
  }
10435
10594
  if (entry.isDirectory()) {
10436
- await mergeStagedDirectory(sourcePath, targetPath, fs);
10437
- await fs.rm(sourcePath, { recursive: true, force: true });
10595
+ await mergeStagedDirectory(sourcePath, targetPath, fs3);
10596
+ await fs3.rm(sourcePath, { recursive: true, force: true });
10438
10597
  return;
10439
10598
  }
10440
- await fs.cp(sourcePath, targetPath, {
10599
+ await fs3.cp(sourcePath, targetPath, {
10441
10600
  force: true,
10442
10601
  dereference: true,
10443
10602
  mode: fsConstants.COPYFILE_FICLONE
10444
10603
  });
10445
- await fs.rm(sourcePath, { force: true });
10604
+ await fs3.rm(sourcePath, { force: true });
10446
10605
  })
10447
10606
  );
10448
10607
  }
@@ -10450,14 +10609,14 @@ __name(mergeStagedDirectory, "mergeStagedDirectory");
10450
10609
  function assertMetadataImageRuntimeInstalled(root, metadataImageRoutes) {
10451
10610
  const generated = metadataImageRoutes.find((image) => image.sourceType === "module");
10452
10611
  if (!generated || resolveMetadataImageRuntimePackageJson(root)) return;
10453
- const file = generated.modulePath ? toPosixPath(path6.relative(root, generated.modulePath)) : "";
10612
+ const file = generated.modulePath ? toPosixPath(path8.relative(root, generated.modulePath)) : "";
10454
10613
  throw new Error(
10455
10614
  `${file || "A generated metadata image"} renders with @vercel/og, which is not installed. ${VERCEL_OG_INSTALL_HINT}`
10456
10615
  );
10457
10616
  }
10458
10617
  __name(assertMetadataImageRuntimeInstalled, "assertMetadataImageRuntimeInstalled");
10459
10618
  function resolveMetadataImageRuntimePackageJson(root) {
10460
- const projectRequire = createRequire(path6.join(root, "package.json"));
10619
+ const projectRequire = createRequire(path8.join(root, "package.json"));
10461
10620
  const packageJsonPath = resolvePackageJson(projectRequire, "@vercel/og");
10462
10621
  if (packageJsonPath) return packageJsonPath;
10463
10622
  try {
@@ -10467,40 +10626,40 @@ function resolveMetadataImageRuntimePackageJson(root) {
10467
10626
  }
10468
10627
  }
10469
10628
  __name(resolveMetadataImageRuntimePackageJson, "resolveMetadataImageRuntimePackageJson");
10470
- async function copyMetadataImageRuntime(root, nitroFuncDir, fs) {
10629
+ async function copyMetadataImageRuntime(root, nitroFuncDir, fs3) {
10471
10630
  const packageJsonPath = resolveMetadataImageRuntimePackageJson(root);
10472
10631
  if (!packageJsonPath) return;
10473
- const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf8"));
10474
- const packageDir = path6.dirname(packageJsonPath);
10475
- const targetDir = path6.join(nitroFuncDir, "node_modules", "@vercel", "og");
10476
- await fs.mkdir(path6.dirname(targetDir), { recursive: true });
10477
- await fs.cp(packageDir, targetDir, {
10632
+ const packageJson = JSON.parse(await fs3.readFile(packageJsonPath, "utf8"));
10633
+ const packageDir = path8.dirname(packageJsonPath);
10634
+ const targetDir = path8.join(nitroFuncDir, "node_modules", "@vercel", "og");
10635
+ await fs3.mkdir(path8.dirname(targetDir), { recursive: true });
10636
+ await fs3.cp(packageDir, targetDir, {
10478
10637
  recursive: true,
10479
10638
  force: true,
10480
10639
  dereference: true,
10481
10640
  mode: fsConstants.COPYFILE_FICLONE
10482
10641
  });
10483
- const functionPackage = await readNitroOutputPackage(nitroFuncDir, fs);
10642
+ const functionPackage = await readNitroOutputPackage(nitroFuncDir, fs3);
10484
10643
  functionPackage.dependencies = {
10485
10644
  ...functionPackage.dependencies,
10486
10645
  "@vercel/og": String(packageJson.version || "0.11.1")
10487
10646
  };
10488
- await writeNitroOutputPackage(nitroFuncDir, functionPackage, fs);
10647
+ await writeNitroOutputPackage(nitroFuncDir, functionPackage, fs3);
10489
10648
  logger.info("\u{1F5BC}\uFE0F Bundled generated metadata image runtime");
10490
10649
  }
10491
10650
  __name(copyMetadataImageRuntime, "copyMetadataImageRuntime");
10492
- async function readNitroOutputPackage(outputDir, fs) {
10493
- const packagePath = path6.join(outputDir, "package.json");
10494
- return fs.readFile(packagePath, "utf8").then((contents) => JSON.parse(contents)).catch((error) => {
10651
+ async function readNitroOutputPackage(outputDir, fs3) {
10652
+ const packagePath = path8.join(outputDir, "package.json");
10653
+ return fs3.readFile(packagePath, "utf8").then((contents) => JSON.parse(contents)).catch((error) => {
10495
10654
  if (error.code === "ENOENT") return {};
10496
10655
  throw error;
10497
10656
  });
10498
10657
  }
10499
10658
  __name(readNitroOutputPackage, "readNitroOutputPackage");
10500
- async function writeNitroOutputPackage(outputDir, packageJson, fs) {
10501
- await fs.mkdir(outputDir, { recursive: true });
10502
- await fs.writeFile(
10503
- path6.join(outputDir, "package.json"),
10659
+ async function writeNitroOutputPackage(outputDir, packageJson, fs3) {
10660
+ await fs3.mkdir(outputDir, { recursive: true });
10661
+ await fs3.writeFile(
10662
+ path8.join(outputDir, "package.json"),
10504
10663
  `${JSON.stringify(packageJson, null, 2)}
10505
10664
  `
10506
10665
  );
@@ -10517,9 +10676,9 @@ function resolvePackageJson(parentRequire, packageName) {
10517
10676
  }
10518
10677
  }
10519
10678
  try {
10520
- let directory = path6.dirname(metadataModule ?? parentRequire.resolve(packageName));
10521
- while (directory !== path6.dirname(directory)) {
10522
- const candidate = path6.join(directory, "package.json");
10679
+ let directory = path8.dirname(metadataModule ?? parentRequire.resolve(packageName));
10680
+ while (directory !== path8.dirname(directory)) {
10681
+ const candidate = path8.join(directory, "package.json");
10523
10682
  if (existsSync2(candidate)) {
10524
10683
  try {
10525
10684
  const manifest = JSON.parse(readFileSync(candidate, "utf8"));
@@ -10527,55 +10686,79 @@ function resolvePackageJson(parentRequire, packageName) {
10527
10686
  } catch {
10528
10687
  }
10529
10688
  }
10530
- if (path6.basename(directory) === "node_modules") break;
10531
- directory = path6.dirname(directory);
10689
+ if (path8.basename(directory) === "node_modules") break;
10690
+ directory = path8.dirname(directory);
10532
10691
  }
10533
10692
  } catch {
10534
10693
  }
10535
10694
  return null;
10536
10695
  }
10537
10696
  __name(resolvePackageJson, "resolvePackageJson");
10538
- async function copyPrismaClientForVercel(root, nitroFuncDir, fs) {
10539
- const projectRequire = createRequire(path6.join(root, "package.json"));
10697
+ async function copyPrismaClientForVercel(root, nitroFuncDir, fs3) {
10698
+ const projectRequire = createRequire(path8.join(root, "package.json"));
10540
10699
  let prismaClientDir;
10541
10700
  try {
10542
- prismaClientDir = path6.dirname(projectRequire.resolve("@prisma/client/default.js"));
10701
+ prismaClientDir = path8.dirname(projectRequire.resolve("@prisma/client/default.js"));
10543
10702
  } catch {
10544
10703
  return;
10545
10704
  }
10546
- const generatedClientDir = path6.join(prismaClientDir, "..", "..", ".prisma", "client");
10705
+ const generatedClientDir = path8.join(prismaClientDir, "..", "..", ".prisma", "client");
10547
10706
  try {
10548
- await fs.access(generatedClientDir);
10707
+ await fs3.access(generatedClientDir);
10549
10708
  } catch {
10550
10709
  return;
10551
10710
  }
10552
- const targetNodeModules = path6.join(nitroFuncDir, "node_modules");
10553
- const targetPrismaScopeDir = path6.join(targetNodeModules, "@prisma");
10554
- const targetGeneratedDir = path6.join(targetNodeModules, ".prisma", "client");
10555
- const targetClientDir = path6.join(targetPrismaScopeDir, "client");
10556
- await fs.mkdir(targetPrismaScopeDir, { recursive: true });
10557
- await fs.cp(prismaClientDir, targetClientDir, {
10711
+ const targetNodeModules = path8.join(nitroFuncDir, "node_modules");
10712
+ const targetPrismaScopeDir = path8.join(targetNodeModules, "@prisma");
10713
+ const targetGeneratedDir = path8.join(targetNodeModules, ".prisma", "client");
10714
+ const targetClientDir = path8.join(targetPrismaScopeDir, "client");
10715
+ await fs3.mkdir(targetPrismaScopeDir, { recursive: true });
10716
+ await fs3.cp(prismaClientDir, targetClientDir, {
10558
10717
  recursive: true,
10559
10718
  force: true
10560
10719
  });
10561
- await fs.cp(generatedClientDir, targetGeneratedDir, {
10720
+ await fs3.cp(generatedClientDir, targetGeneratedDir, {
10562
10721
  recursive: true,
10563
10722
  force: true
10564
10723
  });
10565
- const clientPackagePath = path6.join(prismaClientDir, "package.json");
10724
+ const clientPackagePath = path8.join(prismaClientDir, "package.json");
10566
10725
  const [functionPackage, clientPackageContent] = await Promise.all([
10567
- readNitroOutputPackage(nitroFuncDir, fs),
10568
- fs.readFile(clientPackagePath, "utf-8")
10726
+ readNitroOutputPackage(nitroFuncDir, fs3),
10727
+ fs3.readFile(clientPackagePath, "utf-8")
10569
10728
  ]);
10570
10729
  const clientPackage = JSON.parse(clientPackageContent);
10571
10730
  functionPackage.dependencies = {
10572
10731
  ...functionPackage.dependencies,
10573
10732
  "@prisma/client": clientPackage.version
10574
10733
  };
10575
- await writeNitroOutputPackage(nitroFuncDir, functionPackage, fs);
10734
+ await writeNitroOutputPackage(nitroFuncDir, functionPackage, fs3);
10576
10735
  }
10577
10736
  __name(copyPrismaClientForVercel, "copyPrismaClientForVercel");
10578
10737
 
10738
+ // src/build/project-module-runner.ts
10739
+ async function createFarmProjectModuleSsrEnvironment() {
10740
+ const vite = await import("vite");
10741
+ const { ModuleRunner, createNodeImportMeta } = await import("vite/module-runner");
10742
+ return {
10743
+ dev: {
10744
+ createEnvironment(name, config) {
10745
+ return vite.createRunnableDevEnvironment(name, config, {
10746
+ runner: /* @__PURE__ */ __name((environment) => new ModuleRunner({
10747
+ transport: {
10748
+ ...vite.createServerModuleRunnerTransport({ channel: environment.hot }),
10749
+ timeout: 0
10750
+ },
10751
+ hmr: false,
10752
+ createImportMeta: createNodeImportMeta,
10753
+ sourcemapInterceptor: "node"
10754
+ }), "runner")
10755
+ });
10756
+ }
10757
+ }
10758
+ };
10759
+ }
10760
+ __name(createFarmProjectModuleSsrEnvironment, "createFarmProjectModuleSsrEnvironment");
10761
+
10579
10762
  // src/build/index.ts
10580
10763
  async function build(config, options = {}) {
10581
10764
  return withProductionNodeEnv(() => buildWithProductionNodeEnv(config, options));
@@ -10721,9 +10904,9 @@ async function buildWithProductionNodeEnv(inputConfig, options) {
10721
10904
  } else {
10722
10905
  const { build: legacyViteBuild } = await import("vite");
10723
10906
  logger.info("\u{1F4E6} Building client bundle...");
10724
- await buildClient2(legacyViteBuild, config, root, srcDir, path7.join(root, distDir, "client"));
10907
+ await buildClient2(legacyViteBuild, config, root, srcDir, path9.join(root, distDir, "client"));
10725
10908
  logger.info("\u{1F4E6} Building SSR bundle...");
10726
- await buildSSR(legacyViteBuild, config, root, srcDir, path7.join(root, distDir, "server"));
10909
+ await buildSSR(legacyViteBuild, config, root, srcDir, path9.join(root, distDir, "server"));
10727
10910
  logger.info(`\u{1F680} Building server with Nitro (preset: ${preset})...`);
10728
10911
  await buildNitro(
10729
10912
  config,
@@ -10836,6 +11019,14 @@ async function createProjectModuleServer(createViteServer, config, root, buildLi
10836
11019
  optimizeDeps: {
10837
11020
  ...viteConfig.optimizeDeps,
10838
11021
  noDiscovery: true
11022
+ },
11023
+ // An app or plugin that brings its own SSR environment keeps it.
11024
+ environments: viteConfig.environments?.ssr?.dev?.createEnvironment ? viteConfig.environments : {
11025
+ ...viteConfig.environments,
11026
+ ssr: {
11027
+ ...viteConfig.environments?.ssr,
11028
+ ...await createFarmProjectModuleSsrEnvironment()
11029
+ }
10839
11030
  }
10840
11031
  });
10841
11032
  }
@@ -10903,12 +11094,12 @@ async function buildSSR(viteBuild, config, root, srcDir, outputDir) {
10903
11094
  }
10904
11095
  __name(buildSSR, "buildSSR");
10905
11096
  function resolveLegacyPageEntry(config, root, srcDir) {
10906
- const appDir = path7.join(root, srcDir, "app");
11097
+ const appDir = path9.join(root, srcDir, "app");
10907
11098
  for (const extension of getFarmRendererComponentExtensions(config.renderer)) {
10908
- const candidate = path7.join(appDir, `page${extension}`);
11099
+ const candidate = path9.join(appDir, `page${extension}`);
10909
11100
  if (existsSync3(candidate)) return candidate;
10910
11101
  }
10911
- return path7.join(appDir, "page.tsx");
11102
+ return path9.join(appDir, "page.tsx");
10912
11103
  }
10913
11104
  __name(resolveLegacyPageEntry, "resolveLegacyPageEntry");
10914
11105
  async function buildNitro(config, routeManager, apiRouteManager, serverRenderer, preset, root, distDir, pluginManager) {
@@ -10927,23 +11118,23 @@ async function buildNitro(config, routeManager, apiRouteManager, serverRenderer,
10927
11118
  nitroConfig = await pluginManager.runHookSerial("beforeNitroBuild", nitroConfig);
10928
11119
  }
10929
11120
  const outputDir = resolveDeployOutputPath(root, config.deploy.outputDir);
10930
- const serverOutputDir = path7.join(outputDir, "server");
10931
- const publicOutputDir = path7.join(outputDir, "public");
11121
+ const serverOutputDir = path9.join(outputDir, "server");
11122
+ const publicOutputDir = path9.join(outputDir, "public");
10932
11123
  const { mkdir, cp } = await import("fs/promises");
10933
11124
  await mkdir(serverOutputDir, { recursive: true });
10934
11125
  await mkdir(publicOutputDir, { recursive: true });
10935
- const clientDir = path7.join(root, distDir, "client");
11126
+ const clientDir = path9.join(root, distDir, "client");
10936
11127
  try {
10937
11128
  await mkdir(publicOutputDir, { recursive: true });
10938
11129
  await cp(clientDir, publicOutputDir, { recursive: true });
10939
11130
  logger.info("\u{1F4E6} Copied client assets to public directory");
10940
- const manifestPath = path7.join(publicOutputDir, "farm-client-manifest.json");
10941
- const assetsDir = path7.join(publicOutputDir, "assets");
11131
+ const manifestPath = path9.join(publicOutputDir, "farm-client-manifest.json");
11132
+ const assetsDir = path9.join(publicOutputDir, "assets");
10942
11133
  const manifestExists = await import("fs/promises").then(
10943
- (fs) => fs.access(manifestPath).then(() => true).catch(() => false)
11134
+ (fs3) => fs3.access(manifestPath).then(() => true).catch(() => false)
10944
11135
  );
10945
11136
  const assetsExist = await import("fs/promises").then(
10946
- (fs) => fs.access(assetsDir).then(() => true).catch(() => false)
11137
+ (fs3) => fs3.access(assetsDir).then(() => true).catch(() => false)
10947
11138
  );
10948
11139
  if (manifestExists && assetsExist) {
10949
11140
  logger.info("\u2705 Verified client assets are present");
@@ -10954,8 +11145,8 @@ async function buildNitro(config, routeManager, apiRouteManager, serverRenderer,
10954
11145
  logger.error(`\u274C Failed to copy client assets: ${error}`);
10955
11146
  throw error;
10956
11147
  }
10957
- const serverDir = path7.join(root, distDir, "server");
10958
- const nitroServerDir = path7.join(root, distDir, ".nitro", "server", "farm");
11148
+ const serverDir = path9.join(root, distDir, "server");
11149
+ const nitroServerDir = path9.join(root, distDir, ".nitro", "server", "farm");
10959
11150
  try {
10960
11151
  await mkdir(nitroServerDir, { recursive: true });
10961
11152
  await cp(serverDir, nitroServerDir, { recursive: true });
@@ -10964,7 +11155,7 @@ async function buildNitro(config, routeManager, apiRouteManager, serverRenderer,
10964
11155
  logger.warn(`Could not copy SSR bundles: ${error}`);
10965
11156
  }
10966
11157
  const nitro = await createNitro(nitroConfig);
10967
- const registryPath = path7.join(root, distDir, ".nitro", "server", "farm-registry.ts");
11158
+ const registryPath = path9.join(root, distDir, ".nitro", "server", "farm-registry.ts");
10968
11159
  try {
10969
11160
  const { farmRegistry } = await import(
10970
11161
  /* @vite-ignore */
@@ -10981,7 +11172,7 @@ async function buildNitro(config, routeManager, apiRouteManager, serverRenderer,
10981
11172
  }
10982
11173
  farmRegistry.routePaths = routePaths;
10983
11174
  try {
10984
- const clientManifestPath = path7.join(root, distDir, "client", "farm-client-manifest.json");
11175
+ const clientManifestPath = path9.join(root, distDir, "client", "farm-client-manifest.json");
10985
11176
  const { readFile } = await import("fs/promises");
10986
11177
  const manifestContent = await readFile(clientManifestPath, "utf-8");
10987
11178
  farmRegistry.clientManifest = JSON.parse(manifestContent);