@farm.js/core 0.1.41 → 0.1.43

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 (237) hide show
  1. package/dist/{agent-mcp-BOqIxJLI.d.mts → agent-mcp-3KDz4hr9.d.mts} +1 -1
  2. package/dist/{agent-mcp-D0eZKfci.d.ts → agent-mcp-6yRebHk7.d.ts} +1 -1
  3. package/dist/agent-runtime.d.mts +1 -1
  4. package/dist/agent-runtime.d.ts +1 -1
  5. package/dist/api/route-manager.d.mts +3 -3
  6. package/dist/api/route-manager.d.ts +3 -3
  7. package/dist/api/runtime.d.mts +2 -2
  8. package/dist/api/runtime.d.ts +2 -2
  9. package/dist/api.cjs +2 -2
  10. package/dist/api.d.mts +8 -3
  11. package/dist/api.d.ts +8 -3
  12. package/dist/api.mjs +1 -1
  13. package/dist/{app-DM8e1z3G.d.ts → app-8Db1zR-2.d.ts} +8 -4
  14. package/dist/{app-CzTSMJaf.d.mts → app-DlTWv4cn.d.mts} +8 -4
  15. package/dist/app-manifest-TRzS7ZZ9.d.mts +120 -0
  16. package/dist/app-manifest-cO2jkG1F.d.ts +120 -0
  17. package/dist/app-markdown.d.mts +2 -2
  18. package/dist/app-markdown.d.ts +2 -2
  19. package/dist/{chunk-ECKF2BAM.cjs → chunk-2GVF3C2F.cjs} +255 -42
  20. package/dist/chunk-2NXO5SBY.mjs +57 -0
  21. package/dist/chunk-3BROEWFY.cjs +39 -0
  22. package/dist/{chunk-ENOBPDKZ.mjs → chunk-4MRQ5OKQ.mjs} +14 -9
  23. package/dist/{chunk-R65GCA6A.mjs → chunk-4OCEMK72.mjs} +260 -49
  24. package/dist/{chunk-6PKXK4TY.mjs → chunk-53ZV6K65.mjs} +1 -1
  25. package/dist/{chunk-LYIZHJTK.cjs → chunk-5LPHJZSI.cjs} +14 -14
  26. package/dist/chunk-5NIWBWDD.mjs +97 -0
  27. package/dist/{chunk-NRDBW4MP.mjs → chunk-7IQQIPRZ.mjs} +10 -0
  28. package/dist/{chunk-FJGIVDA5.mjs → chunk-7SCCY6SI.mjs} +80 -177
  29. package/dist/chunk-APDGOKKE.cjs +148 -0
  30. package/dist/chunk-AZBSVLRM.cjs +132 -0
  31. package/dist/{chunk-PN676AZF.cjs → chunk-BKPXWRTT.cjs} +6 -6
  32. package/dist/chunk-CEDPEDNW.cjs +98 -0
  33. package/dist/chunk-D5RFPV2H.mjs +148 -0
  34. package/dist/{chunk-BYQVROIP.mjs → chunk-DMRPN25V.mjs} +69 -0
  35. package/dist/{chunk-724JLMS4.mjs → chunk-F646BZ4Y.mjs} +4 -2
  36. package/dist/{chunk-C5KVWHIH.cjs → chunk-G2Z5DGMS.cjs} +5 -3
  37. package/dist/{chunk-L6HYACBE.cjs → chunk-GVNCWSQV.cjs} +145 -127
  38. package/dist/{chunk-24SP5TGU.mjs → chunk-H4LXPWI2.mjs} +2 -2
  39. package/dist/chunk-H7BLEEAE.cjs +57 -0
  40. package/dist/{chunk-JOTUZIM4.cjs → chunk-HUMEHX24.cjs} +2 -2
  41. package/dist/{chunk-BD3D7EZV.cjs → chunk-IXFOBGLQ.cjs} +9 -3
  42. package/dist/{chunk-3TB5QGUW.cjs → chunk-JAXDRRRC.cjs} +70 -1
  43. package/dist/{chunk-32TZ3QTP.cjs → chunk-JDJAPCR2.cjs} +421 -210
  44. package/dist/{chunk-MHN4UR5U.cjs → chunk-KFZZFZ7J.cjs} +7 -7
  45. package/dist/chunk-LRJRXXQZ.cjs +109 -0
  46. package/dist/{chunk-EX4MKHXN.cjs → chunk-LVABUXLA.cjs} +22 -17
  47. package/dist/{chunk-HCSVR4YZ.mjs → chunk-M3BXTWJM.mjs} +18 -0
  48. package/dist/{chunk-PYHPXPSW.mjs → chunk-NXO75WY4.mjs} +1 -1
  49. package/dist/{chunk-BGGWKZ2V.mjs → chunk-OYSGGV6O.mjs} +137 -167
  50. package/dist/{chunk-JR4QCLJY.cjs → chunk-PDU4P2IC.cjs} +19 -1
  51. package/dist/chunk-PJEHUSHA.mjs +229 -0
  52. package/dist/chunk-QGH2RQVF.mjs +132 -0
  53. package/dist/{chunk-YWMZUGIS.mjs → chunk-R3ZFQJEF.mjs} +247 -34
  54. package/dist/{chunk-ROQ4C4LJ.cjs → chunk-RACQTC7K.cjs} +274 -371
  55. package/dist/{chunk-WSOBCAYO.cjs → chunk-RQYTOFQM.cjs} +23 -23
  56. package/dist/chunk-S34OBRMZ.mjs +109 -0
  57. package/dist/{chunk-TS4JHGUJ.mjs → chunk-S3ZEMCE6.mjs} +9 -3
  58. package/dist/{chunk-WWFTAUFG.cjs → chunk-SBH2JLLF.cjs} +12 -2
  59. package/dist/{chunk-YSLWRWWP.cjs → chunk-SKK6UF5P.cjs} +200 -46
  60. package/dist/chunk-T7J7E63D.cjs +144 -0
  61. package/dist/{chunk-SVPGWJZF.mjs → chunk-TESO7EFU.mjs} +125 -107
  62. package/dist/{chunk-OQ4YXWH4.cjs → chunk-VIVQERJ5.cjs} +320 -351
  63. package/dist/{chunk-JIYYX7WU.mjs → chunk-VLXNGUKO.mjs} +1 -1
  64. package/dist/{chunk-OFZUJMCU.mjs → chunk-WPJQN64R.mjs} +195 -41
  65. package/dist/chunk-XARSG2TG.mjs +144 -0
  66. package/dist/chunk-XUGFRFD2.mjs +39 -0
  67. package/dist/{chunk-EH3464KF.cjs → chunk-YBDSTNMH.cjs} +1 -1
  68. package/dist/{chunk-VLPII2JJ.mjs → chunk-YGZH4T2X.mjs} +1 -1
  69. package/dist/chunk-YKUEJ3MG.cjs +229 -0
  70. package/dist/{chunk-4C7KTKX7.mjs → chunk-ZYWJIPKQ.mjs} +1 -1
  71. package/dist/{client-plugins-CkYwvDJ0.d.mts → client-plugins-Cv0OJtnM.d.mts} +98 -7
  72. package/dist/{client-plugins-DfeKd0sD.d.ts → client-plugins-kwQuZcWq.d.ts} +98 -7
  73. package/dist/client-plugins.d.mts +1 -1
  74. package/dist/client-plugins.d.ts +1 -1
  75. package/dist/client.cjs +4 -3
  76. package/dist/client.d.mts +5 -5
  77. package/dist/client.d.ts +5 -5
  78. package/dist/client.mjs +3 -2
  79. package/dist/config.d.mts +1 -1
  80. package/dist/config.d.ts +1 -1
  81. package/dist/{devtools-N3QLRIQU.mjs → devtools-M22FEFPK.mjs} +4 -4
  82. package/dist/{devtools-2YHAJYH6.cjs → devtools-MLB3JJMC.cjs} +5 -5
  83. package/dist/docs.cjs +6 -6
  84. package/dist/docs.d.mts +2 -2
  85. package/dist/docs.d.ts +2 -2
  86. package/dist/docs.mjs +5 -5
  87. package/dist/index-CQOp8EmB.d.mts +48 -0
  88. package/dist/index-DAl0QTZS.d.ts +48 -0
  89. package/dist/index.cjs +41 -24
  90. package/dist/index.d.mts +15 -14
  91. package/dist/index.d.ts +15 -14
  92. package/dist/index.mjs +46 -29
  93. package/dist/integrations.d.mts +1 -1
  94. package/dist/integrations.d.ts +1 -1
  95. package/dist/internal/app-markdown-runtime.d.mts +2 -2
  96. package/dist/internal/app-markdown-runtime.d.ts +2 -2
  97. package/dist/internal/build-runtime.cjs +29 -15
  98. package/dist/internal/build-runtime.d.mts +12 -16
  99. package/dist/internal/build-runtime.d.ts +12 -16
  100. package/dist/internal/build-runtime.mjs +28 -14
  101. package/dist/internal/cli-runtime.cjs +23 -11
  102. package/dist/internal/cli-runtime.mjs +23 -11
  103. package/dist/internal/client-error-overlay.cjs +4 -4
  104. package/dist/internal/client-error-overlay.mjs +1 -1
  105. package/dist/internal/client-runtime.cjs +5 -1
  106. package/dist/internal/client-runtime.d.mts +1 -0
  107. package/dist/internal/client-runtime.d.ts +1 -0
  108. package/dist/internal/client-runtime.mjs +4 -0
  109. package/dist/internal/compression-runtime.d.mts +1 -1
  110. package/dist/internal/compression-runtime.d.ts +1 -1
  111. package/dist/internal/config-runtime.cjs +5 -5
  112. package/dist/internal/config-runtime.d.mts +2 -2
  113. package/dist/internal/config-runtime.d.ts +2 -2
  114. package/dist/internal/config-runtime.mjs +4 -4
  115. package/dist/internal/form-actions-client.cjs +18 -0
  116. package/dist/internal/form-actions-client.d.mts +5 -0
  117. package/dist/internal/form-actions-client.d.ts +5 -0
  118. package/dist/internal/form-actions-client.mjs +18 -0
  119. package/dist/internal/form-actions.cjs +18 -0
  120. package/dist/internal/form-actions.d.mts +14 -0
  121. package/dist/internal/form-actions.d.ts +14 -0
  122. package/dist/internal/form-actions.mjs +18 -0
  123. package/dist/internal/island-codec.cjs +22 -0
  124. package/dist/internal/island-codec.d.mts +29 -0
  125. package/dist/internal/island-codec.d.ts +29 -0
  126. package/dist/internal/island-codec.mjs +22 -0
  127. package/dist/internal/island-value-store.cjs +13 -0
  128. package/dist/internal/island-value-store.d.mts +6 -0
  129. package/dist/internal/island-value-store.d.ts +6 -0
  130. package/dist/internal/island-value-store.mjs +13 -0
  131. package/dist/internal/islands-runtime.cjs +77 -0
  132. package/dist/internal/islands-runtime.d.mts +57 -0
  133. package/dist/internal/islands-runtime.d.ts +57 -0
  134. package/dist/internal/islands-runtime.mjs +77 -0
  135. package/dist/internal/islands-server.cjs +19 -0
  136. package/dist/internal/islands-server.d.mts +3 -0
  137. package/dist/internal/islands-server.d.ts +3 -0
  138. package/dist/internal/islands-server.mjs +19 -0
  139. package/dist/internal/islx-client.cjs +5 -0
  140. package/dist/internal/islx-client.d.mts +2 -0
  141. package/dist/internal/islx-client.d.ts +2 -0
  142. package/dist/internal/islx-client.mjs +3 -0
  143. package/dist/internal/islx-react.cjs +4 -0
  144. package/dist/internal/islx-react.d.mts +1 -0
  145. package/dist/internal/islx-react.d.ts +1 -0
  146. package/dist/internal/islx-react.mjs +2 -0
  147. package/dist/internal/islx-server.cjs +5 -0
  148. package/dist/internal/islx-server.d.mts +2 -0
  149. package/dist/internal/islx-server.d.ts +2 -0
  150. package/dist/internal/islx-server.mjs +3 -0
  151. package/dist/internal/isolated-boundary.cjs +4 -3
  152. package/dist/internal/isolated-boundary.d.mts +13 -1
  153. package/dist/internal/isolated-boundary.d.ts +13 -1
  154. package/dist/internal/isolated-boundary.mjs +3 -2
  155. package/dist/internal/product-telemetry-runtime.cjs +2 -2
  156. package/dist/internal/product-telemetry-runtime.mjs +1 -1
  157. package/dist/internal/production-runtime.cjs +24 -7
  158. package/dist/internal/production-runtime.d.mts +20 -127
  159. package/dist/internal/production-runtime.d.ts +20 -127
  160. package/dist/internal/production-runtime.mjs +24 -7
  161. package/dist/internal/server-tree.cjs +6 -3
  162. package/dist/internal/server-tree.d.mts +25 -2
  163. package/dist/internal/server-tree.d.ts +25 -2
  164. package/dist/internal/server-tree.mjs +7 -4
  165. package/dist/island-value-protocol-BRayRghM.d.mts +12 -0
  166. package/dist/island-value-protocol-BRayRghM.d.ts +12 -0
  167. package/dist/markdown.d.mts +1 -1
  168. package/dist/markdown.d.ts +1 -1
  169. package/dist/middleware.d.mts +3 -3
  170. package/dist/middleware.d.ts +3 -3
  171. package/dist/navigation.cjs +5 -4
  172. package/dist/navigation.d.mts +4 -4
  173. package/dist/navigation.d.ts +4 -4
  174. package/dist/navigation.mjs +4 -3
  175. package/dist/og.d.mts +5 -0
  176. package/dist/og.d.ts +5 -0
  177. package/dist/plugin.cjs +18 -12
  178. package/dist/plugin.d.mts +3 -3
  179. package/dist/plugin.d.ts +3 -3
  180. package/dist/plugin.mjs +17 -11
  181. package/dist/{production-runtime-DFC7pgbp.d.ts → production-runtime-5nArjFpn.d.ts} +1 -1
  182. package/dist/{production-runtime-BTkXQdYy.d.mts → production-runtime-BzsF2z5F.d.mts} +1 -1
  183. package/dist/query/client.cjs +6 -5
  184. package/dist/query/client.mjs +2 -1
  185. package/dist/{render-plan-5rFeWmk7.d.mts → render-plan-B9yQorV4.d.mts} +4 -2
  186. package/dist/{render-plan-BoAK9xFC.d.ts → render-plan-fg6E_HvL.d.ts} +4 -2
  187. package/dist/renderer/react/server.cjs +7 -6
  188. package/dist/renderer/react/server.d.mts +3 -1
  189. package/dist/renderer/react/server.d.ts +3 -1
  190. package/dist/renderer/react/server.mjs +5 -4
  191. package/dist/renderer-client.cjs +5 -4
  192. package/dist/renderer-client.d.mts +3 -3
  193. package/dist/renderer-client.d.ts +3 -3
  194. package/dist/renderer-client.mjs +2 -1
  195. package/dist/renderer.d.mts +3 -1
  196. package/dist/renderer.d.ts +3 -1
  197. package/dist/{request-BxBWigtl.d.mts → request-C4j_g-BH.d.mts} +1 -1
  198. package/dist/{request-fciwmd3n.d.ts → request-gz8vFK0n.d.ts} +1 -1
  199. package/dist/request.d.mts +2 -2
  200. package/dist/request.d.ts +2 -2
  201. package/dist/{route-rendering-BLZT0IP0.d.ts → route-rendering-DamyKVi3.d.ts} +1 -1
  202. package/dist/{route-rendering-BCM1QzEf.d.mts → route-rendering-iTTOwz1f.d.mts} +1 -1
  203. package/dist/{router-DyZJWc1_.d.mts → router-EoSzHlos.d.mts} +1 -1
  204. package/dist/{router-CkheNX3-.d.ts → router-OVjDqVo8.d.ts} +1 -1
  205. package/dist/routes.d.mts +1 -1
  206. package/dist/routes.d.ts +1 -1
  207. package/dist/rsc-pipeline-LK4K5JFK.mjs +77 -0
  208. package/dist/rsc-pipeline-YCDRJME4.cjs +77 -0
  209. package/dist/{runtime-DfU4sKa5.d.ts → runtime-CwiuozLd.d.ts} +1 -1
  210. package/dist/{runtime-wexvUN5J.d.mts → runtime-DDH4tiuF.d.mts} +1 -1
  211. package/dist/{schema-dev-notice-5JPE67AI.cjs → schema-dev-notice-77ZL23PL.cjs} +4 -4
  212. package/dist/{schema-dev-notice-WLPZ6WKU.mjs → schema-dev-notice-BLXOS6U2.mjs} +2 -2
  213. package/dist/server-plugins.d.mts +2 -2
  214. package/dist/server-plugins.d.ts +2 -2
  215. package/dist/server.cjs +56 -38
  216. package/dist/server.d.mts +15 -10
  217. package/dist/server.d.ts +15 -10
  218. package/dist/server.mjs +36 -18
  219. package/dist/{spa-router-DgsMXqfX.d.mts → spa-router-Br4qFCWf.d.mts} +8 -3
  220. package/dist/{spa-router-CcejECnG.d.ts → spa-router-BsWUKH73.d.ts} +8 -3
  221. package/dist/{ssg-1FGaFISl.d.ts → ssg-Csy2vwpi.d.ts} +2 -2
  222. package/dist/{ssg-Bg4bMMhM.d.mts → ssg-Donyfcxy.d.mts} +2 -2
  223. package/dist/testing.d.mts +1 -1
  224. package/dist/testing.d.ts +1 -1
  225. package/dist/{utils-Dxbh6Hgj.d.ts → utils-Luk72LXC.d.ts} +1 -1
  226. package/dist/{utils-8wtTYiH4.d.mts → utils-d_k1ZZw0.d.mts} +1 -1
  227. package/dist/version.cjs +2 -2
  228. package/dist/version.mjs +1 -1
  229. package/dist/vite.cjs +18 -12
  230. package/dist/vite.d.mts +6 -4
  231. package/dist/vite.d.ts +6 -4
  232. package/dist/vite.mjs +17 -11
  233. package/package.json +53 -1
  234. package/dist/{chunk-35WS7P2V.mjs → chunk-26CXZR6L.mjs} +3 -3
  235. package/dist/{chunk-QEILRWVV.cjs → chunk-3XEMGDBF.cjs} +2 -2
  236. package/dist/{chunk-BPOTSHDO.cjs → chunk-IOAUK4OI.cjs} +2 -2
  237. package/dist/{chunk-BYR3RQPB.mjs → chunk-T76H22WI.mjs} +4 -4
@@ -11,13 +11,13 @@ import {
11
11
  import {
12
12
  generateNativeMCPPluginSource,
13
13
  layoutsCanCoverSamePage
14
- } from "./chunk-4C7KTKX7.mjs";
14
+ } from "./chunk-ZYWJIPKQ.mjs";
15
15
  import {
16
16
  assertFarmDocsAdapterServesNoGuardedPages,
17
17
  compileFarmDocsAdapterEdgeManifest,
18
18
  createFarmDocsAPIHandler,
19
19
  hasFarmDocsRuntimeAdapter
20
- } from "./chunk-PYHPXPSW.mjs";
20
+ } from "./chunk-NXO75WY4.mjs";
21
21
  import {
22
22
  FARM_DOCS_LAST_MODIFIED_MANIFEST,
23
23
  createFarmDocsHandler,
@@ -45,7 +45,7 @@ import {
45
45
  getDeployTargetForPreset,
46
46
  hasCustomFarmRouteContext,
47
47
  resolveDeployOutputPath
48
- } from "./chunk-ENOBPDKZ.mjs";
48
+ } from "./chunk-4MRQ5OKQ.mjs";
49
49
  import {
50
50
  resolveFarmInstrumentationFile
51
51
  } from "./chunk-ZZSRYEYU.mjs";
@@ -72,7 +72,6 @@ import {
72
72
  getClientModuleHydrationPlan,
73
73
  getClientModuleMetadata,
74
74
  getFarmClientHydrationPlanOptions,
75
- loadTailwindVitePlugin,
76
75
  mergeFarmFontCss,
77
76
  mergeFarmProductionViteConfig,
78
77
  mergeFarmViteConfig,
@@ -83,15 +82,18 @@ import {
83
82
  resolveFarmIsolatedClientHydrationMode,
84
83
  resolveFarmNotFoundComponentPath,
85
84
  usesFarmServerTree
86
- } from "./chunk-FJGIVDA5.mjs";
85
+ } from "./chunk-7SCCY6SI.mjs";
87
86
  import {
88
87
  PluginManager
89
88
  } from "./chunk-FGH3ZXTP.mjs";
89
+ import {
90
+ loadTailwindVitePlugin
91
+ } from "./chunk-S34OBRMZ.mjs";
90
92
  import {
91
93
  generateFarmTypeArtifacts,
92
94
  readRouteRenderingDirectiveFromFile,
93
95
  resolveRouteRenderingConfigFromFile
94
- } from "./chunk-35WS7P2V.mjs";
96
+ } from "./chunk-26CXZR6L.mjs";
95
97
  import {
96
98
  FARM_API_CATALOG_PATH,
97
99
  FARM_APP_MANIFEST_LEGACY_PATH,
@@ -107,15 +109,15 @@ import {
107
109
  resolveFarmAppManifestInput,
108
110
  routeBoundaryCoversDirectory,
109
111
  stripRouteGroups
110
- } from "./chunk-SVPGWJZF.mjs";
112
+ } from "./chunk-TESO7EFU.mjs";
113
+ import {
114
+ farmPluginMayAffectRuntimePath
115
+ } from "./chunk-Y5RG6B7S.mjs";
111
116
  import {
112
117
  FARM_DEFAULT_MCP_PATH,
113
118
  createFarmDefaultMCPServer,
114
119
  farmConfigMountsMCP
115
120
  } from "./chunk-4ZZNPK25.mjs";
116
- import {
117
- farmPluginMayAffectRuntimePath
118
- } from "./chunk-Y5RG6B7S.mjs";
119
121
  import {
120
122
  isFarmPreviewDeploymentEnvironment
121
123
  } from "./chunk-BOYNDCZL.mjs";
@@ -130,6 +132,9 @@ import {
130
132
  resolveFarmDocsFontAssets,
131
133
  toFarmDocsPublicFontAssets
132
134
  } from "./chunk-TVGP4BBZ.mjs";
135
+ import {
136
+ resolveFarmServerComponentsMode
137
+ } from "./chunk-M3BXTWJM.mjs";
133
138
  import {
134
139
  routeRulesToNitroRouteRules
135
140
  } from "./chunk-GHFS7RUB.mjs";
@@ -155,6 +160,9 @@ import {
155
160
  mergeScheduledTasks,
156
161
  prepareFarmCronForNitro
157
162
  } from "./chunk-YHOCRI4H.mjs";
163
+ import {
164
+ resolveServerActionsConfig
165
+ } from "./chunk-WMHG64DA.mjs";
158
166
  import {
159
167
  createBundledEnv
160
168
  } from "./chunk-4OOBRCJX.mjs";
@@ -214,7 +222,7 @@ import {
214
222
  } from "./chunk-BTHHUD7Q.mjs";
215
223
  import {
216
224
  FARM_VERSION
217
- } from "./chunk-VLPII2JJ.mjs";
225
+ } from "./chunk-YGZH4T2X.mjs";
218
226
  import {
219
227
  getFarmPresetRuntime
220
228
  } from "./chunk-2A3EQHXX.mjs";
@@ -232,6 +240,9 @@ import {
232
240
  import path10 from "path";
233
241
  import { existsSync as existsSync3 } from "fs";
234
242
 
243
+ // src/nitro/universal-build.ts
244
+ import { randomBytes } from "crypto";
245
+
235
246
  // src/nitro/client-css-href.ts
236
247
  import path from "path";
237
248
  var FARM_CLIENT_CSS_HREF_PLACEHOLDER = "/__farm_client_css_href__";
@@ -1998,7 +2009,7 @@ async function validateClientBuildOutput(root, srcDir, outputDir) {
1998
2009
  }
1999
2010
  __name(validateClientBuildOutput, "validateClientBuildOutput");
2000
2011
  function getCachedClientModuleHydrationPlan(modulePath, root, mode, cache, options = {}) {
2001
- const key = `${path9.resolve(root)}\0${mode}\0${options.asyncOwnerIslands === true}\0${path9.resolve(modulePath)}`;
2012
+ const key = `${path9.resolve(root)}\0${mode}\0${options.asyncOwnerIslands === true}\0${options.serverOwners === true}\0${path9.resolve(modulePath)}`;
2002
2013
  let plan = cache.get(key);
2003
2014
  if (!plan) {
2004
2015
  plan = getClientModuleHydrationPlan(modulePath, root, mode, options);
@@ -2025,7 +2036,7 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2025
2036
  const unsupportedIntegrationProvider = integrationProviders.find(
2026
2037
  (provider) => provider.supportsIsolatedHydration !== true
2027
2038
  );
2028
- if (config.experimental?.isolatedClientHydration === "enabled" && config.experimental?.serverComponents !== true && unsupportedIntegrationProvider) {
2039
+ if (config.experimental?.isolatedClientHydration === "enabled" && resolveFarmServerComponentsMode(config.experimental?.serverComponents) !== "rsc" && unsupportedIntegrationProvider) {
2029
2040
  logger.warn(
2030
2041
  `[Farm.js] isolated hydration kept route-wide because integration provider "${unsupportedIntegrationProvider.name}" does not declare supportsIsolatedHydration: true.`
2031
2042
  );
@@ -2033,7 +2044,7 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2033
2044
  const isolatedMode = resolveFarmIsolatedClientHydrationMode(
2034
2045
  config.experimental?.isolatedClientHydration,
2035
2046
  {
2036
- serverComponents: config.experimental?.serverComponents === true,
2047
+ serverComponents: resolveFarmServerComponentsMode(config.experimental?.serverComponents) === "rsc",
2037
2048
  hasUnsupportedIntegrationProvider: Boolean(unsupportedIntegrationProvider)
2038
2049
  }
2039
2050
  );
@@ -2041,6 +2052,10 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2041
2052
  config.renderer,
2042
2053
  Boolean(unsupportedIntegrationProvider)
2043
2054
  );
2055
+ const pagePlanOptions = {
2056
+ ...planOptions,
2057
+ serverOwners: resolveFarmServerComponentsMode(config.experimental?.serverComponents) === "islands"
2058
+ };
2044
2059
  const clientLayouts = layoutRoutes.map((layout) => {
2045
2060
  try {
2046
2061
  const metadata = getCachedClientModuleHydrationPlan(
@@ -2108,7 +2123,7 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2108
2123
  root,
2109
2124
  isolatedMode,
2110
2125
  hydrationPlanCache,
2111
- planOptions
2126
+ pagePlanOptions
2112
2127
  )
2113
2128
  }));
2114
2129
  enforceFarmIsolatedHydrationRouteBudget(
@@ -2259,7 +2274,8 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
2259
2274
  getIntegrationProviders(config.integrations),
2260
2275
  config.basePath,
2261
2276
  generateClientCachePersistenceCode(resolveFarmClientCacheAdapterEntry(root, config.cache)),
2262
- adapterOwnsDocsRuntime ? getFarmDocsAdapterConfigModule(config.docs) : void 0
2277
+ adapterOwnsDocsRuntime ? getFarmDocsAdapterConfigModule(config.docs) : void 0,
2278
+ resolveFarmServerComponentsMode(config.experimental?.serverComponents) === "islands"
2263
2279
  );
2264
2280
  await fs4.writeFile(clientEntryPath, clientHydrationCode);
2265
2281
  const hasScopedPostcssConfig = hasProjectPostcssConfig(root);
@@ -2974,13 +2990,17 @@ function generateUniversalRouterStateProperties() {
2974
2990
 
2975
2991
  clearPrefetchedPath: function(url) {
2976
2992
  const interceptionPrefix = url + "\\nintercept:";
2993
+ const partialPrefix = url + "\\npartial:";
2994
+ const matches = function(key) {
2995
+ return key === url || key.startsWith(interceptionPrefix) || key.startsWith(partialPrefix);
2996
+ };
2977
2997
  for (const key of this.prefetchCache.keys()) {
2978
- if (key === url || key.startsWith(interceptionPrefix)) {
2998
+ if (matches(key)) {
2979
2999
  this.prefetchCache.delete(key);
2980
3000
  }
2981
3001
  }
2982
3002
  for (const [key, pending] of this.pendingPrefetches) {
2983
- if (key === url || key.startsWith(interceptionPrefix)) {
3003
+ if (matches(key)) {
2984
3004
  pending.valid = false;
2985
3005
  this.pendingPrefetches.delete(key);
2986
3006
  }
@@ -2994,9 +3014,18 @@ function generateUniversalRouterStateProperties() {
2994
3014
  this.pendingPrefetches.clear();
2995
3015
  },
2996
3016
 
2997
- fetchPrefetchedDocument: async function(url, interceptFrom, fresh, recover, signal, cacheResult = true) {
3017
+ // Islands mode: a partial response (layouts kept, or only the page's payload) suits the page
3018
+ // that asked for it, so the cache keys it by what that page told the server.
3019
+ prefetchRequest: function(url, interceptFrom, layoutChain = true) {
3020
+ const base = interceptFrom ? url + "\\nintercept:" + interceptFrom : url;
3021
+ const partial = layoutChain && this.partialNavigationHeaders ? this.partialNavigationHeaders() : {};
3022
+ const identity = Object.keys(partial).length ? JSON.stringify(partial) : "";
3023
+ return { cacheKey: identity ? base + "\\npartial:" + identity : base, headers: partial };
3024
+ },
3025
+
3026
+ fetchPrefetchedDocument: async function(url, interceptFrom, fresh, recover, signal, cacheResult = true, layoutChain = true) {
2998
3027
  signal?.throwIfAborted();
2999
- const cacheKey = interceptFrom ? url + "\\nintercept:" + interceptFrom : url;
3028
+ const { cacheKey, headers: partialHeaders } = this.prefetchRequest(url, interceptFrom, layoutChain);
3000
3029
  if (fresh) this.clearPrefetchedPath(url);
3001
3030
  const cached = fresh ? undefined : this.readFreshPrefetch(cacheKey);
3002
3031
  if (cached !== undefined) return cached;
@@ -3028,6 +3057,10 @@ function generateUniversalRouterStateProperties() {
3028
3057
  const response = await fetchFarmNavigationDocument(url, {
3029
3058
  "Accept": "text/html",
3030
3059
  ...(interceptFrom ? { "X-Farm-Intercept-From": interceptFrom } : {}),
3060
+ // Islands mode: the server leaves out island values this browser holds, and the
3061
+ // layouts it shows.
3062
+ ...getFarmIslandValueHeaders(),
3063
+ ...partialHeaders,
3031
3064
  }, recover, signal);
3032
3065
  if (!response.ok) throw new Error("Failed to fetch page");
3033
3066
  const html = await response.text();
@@ -3185,6 +3218,25 @@ function generateUniversalRouterStateProperties() {
3185
3218
  `.trim();
3186
3219
  }
3187
3220
  __name(generateUniversalRouterStateProperties, "generateUniversalRouterStateProperties");
3221
+ var FARM_SEGMENT_NAVIGATION_SERVER_RUNTIME = `
3222
+ function getFarmLayoutKey(pattern, params) {
3223
+ return pattern.replace(/\\[\\[?\\.\\.\\.([^\\]]+)\\]?\\]|\\[([^\\]]+)\\]/g, function(match, rest, name) {
3224
+ const value = params ? params[rest || name] : undefined;
3225
+ if (Array.isArray(value)) return value.map(encodeURIComponent).join("/");
3226
+ return value === undefined ? "" : encodeURIComponent(String(value));
3227
+ });
3228
+ }
3229
+
3230
+ function countFarmKeptLayouts(request, layouts, params) {
3231
+ const chain = parseFarmLayoutChainHeader(request.headers.get("f-layouts"));
3232
+ if (chain.length === 0) return 0;
3233
+ const keys = layouts.map(function(layout) { return getFarmLayoutKey(layout.pattern, params); });
3234
+ if (chain[0] === keys[0]) return getSharedLayoutPrefixLength(chain, keys);
3235
+ // A root layout that renders the document itself leaves no boundary in the page, so the
3236
+ // browser's chain starts at the next layout.
3237
+ return keys.length > 1 ? 1 + getSharedLayoutPrefixLength(chain, keys.slice(1)) : 0;
3238
+ }
3239
+ `;
3188
3240
  function generateClientHydrationEntry(clientPages, layoutRoutes, clientRouteSlots, root, srcDir, docsSearchEnabled, docsSearchModuleId, docsEntryPath, docsAdapterReact, i18nConfig = {
3189
3241
  enabled: false,
3190
3242
  basePath: "/",
@@ -3203,7 +3255,7 @@ function generateClientHydrationEntry(clientPages, layoutRoutes, clientRouteSlot
3203
3255
  secure: false
3204
3256
  },
3205
3257
  direction: {}
3206
- }, plugins = [], renderer = REACT_RENDERER, publicRuntimeConfig = void 0, trailingSlash = false, integrationProviders = [], basePath = "/", clientCachePersistence = { imports: "", init: "" }, docsConfigModule) {
3258
+ }, plugins = [], renderer = REACT_RENDERER, publicRuntimeConfig = void 0, trailingSlash = false, integrationProviders = [], basePath = "/", clientCachePersistence = { imports: "", init: "" }, docsConfigModule, islandValues = false) {
3207
3259
  const toImportPath = /* @__PURE__ */ __name((targetPath) => targetPath.replace(/\\/g, "/"), "toImportPath");
3208
3260
  const clientPluginEntry = generateFarmClientPluginEntryCode(
3209
3261
  plugins,
@@ -3292,7 +3344,7 @@ function isFarmDocsPath() {
3292
3344
  // Farm.js Client Runtime (no client components)
3293
3345
  ${cssImport}
3294
3346
  ${layoutImports}
3295
- import { createClientCancellation, createClientPluginManager, getHashTargetElement, installChunkErrorRecovery, isFarmBlockedNavigationURL, isFarmExternalNavigationURL, reconcileFarmDocumentHead, setFarmBasePath, setFarmTrailingSlashPreference, stripFarmBasePath } from "@farm.js/core/internal/client-runtime";
3347
+ import { createClientCancellation, createClientPluginManager, getFarmIslandValueHeaders, getHashTargetElement, installChunkErrorRecovery, isFarmBlockedNavigationURL, isFarmExternalNavigationURL, reconcileFarmDocumentHead, setFarmBasePath, setFarmTrailingSlashPreference, stripFarmBasePath } from "@farm.js/core/internal/client-runtime";
3296
3348
  import { createFarmDeploymentMismatchError, createFarmDeploymentRequestHeaders, isFarmDeploymentMismatchResponse } from "@farm.js/core/deployment";
3297
3349
  ${clientPluginEntry.imports}
3298
3350
  ${clientCachePersistence.imports}
@@ -3591,7 +3643,7 @@ document.addEventListener("click", function(e) {
3591
3643
  });
3592
3644
  const isolatedHydrationEnabled = isolatedBoundaryModules.size > 0;
3593
3645
  const serverTreeEnabled = isolatedHydrationEnabled && clientPages.some((page) => page.serverTree);
3594
- const isolatedHydrationImport = isolatedHydrationEnabled ? `import { createFarmIsolatedHydrationRuntime, createFarmServerPageBoundary, wrapFarmIsolatedClientGraph } from "@farm.js/core/internal/isolated-boundary";${serverTreeEnabled ? '\nimport { createFarmServerTreeElement } from "@farm.js/core/internal/server-tree";' : ""}` : "";
3646
+ const isolatedHydrationImport = isolatedHydrationEnabled ? `${islandValues ? 'import { createFarmIsolatedHydrationRuntime, createFarmServerPageBoundary, wrapFarmIsolatedClientGraph, createFarmServerTreeElement } from "@farm.js/core/internal/islands-runtime";' : 'import { createFarmIsolatedHydrationRuntime, createFarmServerPageBoundary, wrapFarmIsolatedClientGraph } from "@farm.js/core/internal/isolated-boundary";'}${serverTreeEnabled && !islandValues ? '\nimport { createFarmServerTreeElement } from "@farm.js/core/internal/server-tree";' : ""}` : "";
3595
3647
  const isolatedHydrationRuntime = isolatedHydrationEnabled ? `const farmIsolatedBoundaryLoaders = {
3596
3648
  ${Array.from(isolatedBoundaryModules.entries()).map(
3597
3649
  ([reference, modulePath]) => ` ${JSON.stringify(reference)}: () => import(${JSON.stringify(modulePath)}),`
@@ -3657,7 +3709,7 @@ ${layoutImports}
3657
3709
  ${rendererClientImports}
3658
3710
  ${isolatedHydrationImport}
3659
3711
  ${providerClientCode.imports}
3660
- import { createClientCancellation, createClientPluginManager, getHashTargetElement, installChunkErrorRecovery, isFarmBlockedNavigationURL, isFarmExternalNavigationURL, reconcileFarmDocumentHead, scheduleFarmIslandHydration, searchParamsToObject, setFarmBasePath, setFarmTrailingSlashPreference, stripFarmBasePath } from "@farm.js/core/internal/client-runtime";
3712
+ import { createClientCancellation, createClientPluginManager, getFarmIslandValueHeaders, getHashTargetElement, installChunkErrorRecovery, isFarmBlockedNavigationURL, isFarmExternalNavigationURL, reconcileFarmDocumentHead, scheduleFarmIslandHydration, searchParamsToObject, setFarmBasePath, setFarmTrailingSlashPreference, stripFarmBasePath } from "@farm.js/core/internal/client-runtime";
3661
3713
  import { createFarmDeploymentMismatchError, createFarmDeploymentRequestHeaders, isFarmDeploymentMismatchResponse } from "@farm.js/core/deployment";
3662
3714
  import { createFarmRouter, isFarmRouteActive, matchFarmRoute } from "@farm.js/core/router";
3663
3715
  ${clientPluginEntry.imports}
@@ -3834,6 +3886,10 @@ async function createMatchedHydrationRoute(matched, pathname, searchParams, serv
3834
3886
  const serverPage = document.getElementById("__farm_page__");
3835
3887
  const pageSource = typeof serverHtml === "string" ? serverHtml : serverPage;
3836
3888
  const serverTree = pageSource ? await createFarmServerTreePageElement(pageSource, pathname) : null;
3889
+ // A payload-only page (islands mode) has no HTML to fall back to: fetch the whole document.
3890
+ if (!serverTree && typeof serverHtml === "string" && serverHtml.includes('<script type="f/tree" partial')) {
3891
+ return null;
3892
+ }
3837
3893
  pageElement = serverTree
3838
3894
  ? createLayoutPageBoundary(matched.route, serverTree)
3839
3895
  : createLayoutPageBoundary(
@@ -4161,7 +4217,7 @@ async function hydrate() {
4161
4217
  });
4162
4218
  ${isolatedHydrationEnabled ? `const isolatedHydration =
4163
4219
  !hasHydratableLayout(pathname) &&
4164
- document.querySelector('farm-client-boundary[data-farm-client-boundary]')
4220
+ document.querySelector('f-island[src]')
4165
4221
  ? hydrateFarmIsolatedClientBoundaries(document, hydrationController.signal)
4166
4222
  : Promise.resolve();
4167
4223
  await Promise.all([pageHydration, isolatedHydration]);` : "await pageHydration;"}
@@ -4172,20 +4228,41 @@ async function hydrate() {
4172
4228
  }
4173
4229
  }
4174
4230
 
4231
+ // A layout boundary is the same layout when its key matches: islands mode keys it by pattern and
4232
+ // params, so a layout whose params change renders again. Other modes compare patterns.
4233
+ function getLayoutIdentity(boundary) {
4234
+ return boundary.getAttribute("data-farm-layout-key") || boundary.getAttribute("data-farm-layout-pattern");
4235
+ }
4236
+
4175
4237
  function findLayoutBoundary(root, pattern) {
4176
4238
  const boundaries = root?.querySelectorAll?.('[data-farm-layout-boundary="true"]') || [];
4177
4239
  for (const boundary of boundaries) {
4178
- if (boundary.getAttribute("data-farm-layout-pattern") === pattern) return boundary;
4240
+ if (getLayoutIdentity(boundary) === pattern) return boundary;
4179
4241
  }
4180
4242
  return null;
4181
4243
  }
4182
4244
 
4183
4245
  function getLayoutPatterns(root) {
4184
4246
  return Array.from(root?.querySelectorAll?.('[data-farm-layout-boundary="true"]') || [])
4185
- .map(function(element) { return element.getAttribute("data-farm-layout-pattern"); })
4247
+ .map(getLayoutIdentity)
4186
4248
  .filter(Boolean);
4187
4249
  }
4188
4250
 
4251
+ ${islandValues ? `// A segment response leaves out the layouts the browser said it shows. It fits this page only if
4252
+ // the page still shows each of them, at the same depth.
4253
+ function fitsSegmentResponse(currentRoot, nextRoot) {
4254
+ const nextBoundaries = Array.from(nextRoot.querySelectorAll('[data-farm-layout-boundary="true"]'));
4255
+ const lastKept = nextBoundaries.map(function(boundary) {
4256
+ return boundary.getAttribute("data-farm-layout-kept") === "true";
4257
+ }).lastIndexOf(true);
4258
+ if (lastKept === -1) return true;
4259
+ const current = getLayoutPatterns(currentRoot);
4260
+ for (let index = 0; index <= lastKept; index++) {
4261
+ if (current[index] !== getLayoutIdentity(nextBoundaries[index])) return false;
4262
+ }
4263
+ return true;
4264
+ }` : ""}
4265
+
4189
4266
  function activateNavigationScripts(root) {
4190
4267
  for (const script of Array.from(root?.querySelectorAll?.("script") || [])) {
4191
4268
  const freshScript = document.createElement("script");
@@ -4197,7 +4274,7 @@ function activateNavigationScripts(root) {
4197
4274
  }
4198
4275
  }
4199
4276
 
4200
- function replaceSharedLayoutBoundary(currentRoot, nextRoot) {
4277
+ function replaceSharedLayoutBoundary(currentRoot, nextRoot, refresh = false) {
4201
4278
  const currentPatterns = getLayoutPatterns(currentRoot);
4202
4279
  const nextPatterns = getLayoutPatterns(nextRoot);
4203
4280
  let sharedCount = 0;
@@ -4218,7 +4295,9 @@ function replaceSharedLayoutBoundary(currentRoot, nextRoot) {
4218
4295
  : nextRoot.querySelector("#__farm_page__");
4219
4296
 
4220
4297
  if (!currentTarget || !nextTarget) return false;
4221
- ${isolatedHydrationEnabled ? "disposeFarmIsolatedClientBoundaries(currentTarget);" : ""}
4298
+ ${isolatedHydrationEnabled ? `${islandValues ? `// A refresh keeps the islands still on the page, with their state and new props.
4299
+ if (refresh) farmIsolatedHydrationRuntime.carryOver(currentTarget, nextTarget);
4300
+ ` : ""}disposeFarmIsolatedClientBoundaries(currentTarget);` : ""}
4222
4301
  currentTarget.replaceWith(nextTarget);
4223
4302
  activateNavigationScripts(nextTarget);
4224
4303
  if (nextTreeRoot && nextTreeRoot !== nextTarget) nextTreeRoot.remove();
@@ -4239,7 +4318,17 @@ function replaceSharedLayoutBoundary(currentRoot, nextRoot) {
4239
4318
  const spaRouter = {
4240
4319
  ${generateUniversalRouterStateProperties()}
4241
4320
  prefetchCache: new Map(),
4242
-
4321
+ ${islandValues ? ` // Islands mode: navigations name the layouts on screen, and say when this page renders the
4322
+ // next one in its own React root; the server leaves out what the browser keeps or rebuilds.
4323
+ partialNavigationHeaders: function() {
4324
+ const root = document.getElementById("root") || document.body;
4325
+ const layouts = getLayoutPatterns(root);
4326
+ return {
4327
+ ...(layouts.length ? { "F-Layouts": JSON.stringify(layouts) } : {}),
4328
+ ...(reactRoot && reactRootContainer === root ? { "F-Render": "tree" } : {}),
4329
+ };
4330
+ },
4331
+ ` : ""}
4243
4332
  navigate: async function(href, options = {}) {
4244
4333
  const url = new URL(href, window.location.href);
4245
4334
  if (isFarmBlockedNavigationURL(url)) return;
@@ -4294,6 +4383,8 @@ ${generateUniversalRouterStateProperties()}
4294
4383
  cancelPendingPageHydration();
4295
4384
  this.saveScrollPosition(window.location.pathname + window.location.search);
4296
4385
  const navigation = this.startNavigation(from, url, action);
4386
+ // A refresh keeps the islands still on the page (islands mode).
4387
+ navigation.refresh = options.refresh === true;
4297
4388
  let clientNavigation;
4298
4389
 
4299
4390
  try {
@@ -4396,26 +4487,48 @@ ${generateUniversalRouterStateProperties()}
4396
4487
  this.currentPath = to;
4397
4488
  });
4398
4489
  } else {
4490
+ // A refresh renders every layout again; other navigations keep the ones on screen.
4399
4491
  const html = await this.fetchPage(
4400
4492
  url.pathname + url.search,
4401
4493
  undefined,
4402
4494
  options.refresh === true,
4403
4495
  true,
4404
4496
  navigation.controller.signal,
4497
+ options.refresh !== true,
4405
4498
  );
4406
4499
  if (!this.isCurrentNavigation(navigation, clientNavigation)) return;
4407
4500
  await farmClientRuntime.markNavigationLoaded(clientNavigation, html);
4408
4501
  if (!this.isCurrentNavigation(navigation, clientNavigation)) return;
4409
4502
  await this.runViewTransition(options.viewTransition, async () => {
4410
4503
  if (!this.isCurrentNavigation(navigation, clientNavigation)) return;
4411
- const swapped = await this.swapContent(
4504
+ let swapped = await this.swapContent(
4412
4505
  html,
4413
4506
  url.pathname + url.search,
4414
4507
  navigation,
4415
4508
  clientNavigation,
4416
4509
  );
4417
4510
  if (!this.isCurrentNavigation(navigation, clientNavigation)) return;
4418
- if (!swapped) {
4511
+ if (swapped === "segment-mismatch") {
4512
+ // The page changed since this segment was requested (a prefetch, a later
4513
+ // navigation): fetch the whole document instead.
4514
+ const documentHtml = await this.fetchPage(
4515
+ url.pathname + url.search,
4516
+ undefined,
4517
+ true,
4518
+ true,
4519
+ navigation.controller.signal,
4520
+ false,
4521
+ );
4522
+ if (!this.isCurrentNavigation(navigation, clientNavigation)) return;
4523
+ swapped = await this.swapContent(
4524
+ documentHtml,
4525
+ url.pathname + url.search,
4526
+ navigation,
4527
+ clientNavigation,
4528
+ );
4529
+ if (!this.isCurrentNavigation(navigation, clientNavigation)) return;
4530
+ }
4531
+ if (!swapped || swapped === "segment-mismatch") {
4419
4532
  throw new Error("Farm could not swap the target document");
4420
4533
  }
4421
4534
  this.writeHistoryEntry(action, url.pathname + url.search, options.state, url);
@@ -4465,8 +4578,8 @@ ${generateUniversalRouterStateProperties()}
4465
4578
  });
4466
4579
  },
4467
4580
 
4468
- fetchPage: async function(url, interceptFrom, fresh = false, recover = true, signal) {
4469
- return this.fetchPrefetchedDocument(url, interceptFrom, fresh, recover, signal);
4581
+ fetchPage: async function(url, interceptFrom, fresh = false, recover = true, signal, layoutChain = true) {
4582
+ return this.fetchPrefetchedDocument(url, interceptFrom, fresh, recover, signal, true, layoutChain);
4470
4583
  },
4471
4584
 
4472
4585
  swapContent: async function(html, targetPath, navigation, clientNavigation) {
@@ -4487,6 +4600,14 @@ ${generateUniversalRouterStateProperties()}
4487
4600
  // whole document (and remounting every isolated client boundary).
4488
4601
  const newRoot = doc.getElementById("root") || doc.body;
4489
4602
  const currentRoot = document.getElementById("root") || document.body;
4603
+ ${islandValues ? `const isSegment = Boolean(newRoot?.querySelector('[data-farm-layout-kept="true"]'));
4604
+ // A segment needs this page's kept layouts in place, outside a React-owned root.
4605
+ if (
4606
+ isSegment &&
4607
+ (!currentRoot || reactRootContainer === currentRoot || !fitsSegmentResponse(currentRoot, newRoot))
4608
+ ) {
4609
+ return "segment-mismatch";
4610
+ }` : ""}
4490
4611
  if (!newRoot || !currentRoot) {
4491
4612
  if (!isNavigationCurrent()) return false;
4492
4613
  return this.swapDocument(doc);
@@ -4517,13 +4638,16 @@ ${generateUniversalRouterStateProperties()}
4517
4638
  }
4518
4639
  }
4519
4640
 
4641
+ ${islandValues ? `// A payload-only page renders only in a React root that rebuilds it.
4642
+ if (nextPage?.querySelector('script[type="f/tree"][partial]')) return "segment-mismatch";` : ""}
4520
4643
  const rootWasReactOwned = reactRootContainer === currentRoot;
4521
4644
  resetReactRoot();
4522
4645
  resetRouteSlotRoots();
4523
4646
  const replacedSharedBoundary = rootWasReactOwned
4524
4647
  ? null
4525
- : replaceSharedLayoutBoundary(currentRoot, newRoot);
4648
+ : replaceSharedLayoutBoundary(currentRoot, newRoot, navigation?.refresh === true);
4526
4649
  let isolatedHydrationScope = replacedSharedBoundary || currentRoot;
4650
+ ${islandValues ? 'if (!replacedSharedBoundary && isSegment) return "segment-mismatch";' : ""}
4527
4651
  if (!replacedSharedBoundary) {
4528
4652
  ${isolatedHydrationEnabled ? "disposeFarmIsolatedClientBoundaries(currentRoot);" : ""}
4529
4653
  currentRoot.innerHTML = newRoot.innerHTML;
@@ -4606,7 +4730,7 @@ ${generateUniversalRouterStateProperties()}
4606
4730
  // navigation (double fetch per prefetched link) and sent
4607
4731
  // X-Farm-Intercept-From, which bypasses the shared cache server-side.
4608
4732
  const pathname = url.pathname + url.search;
4609
- if (this.readFreshPrefetch(pathname) !== undefined) return;
4733
+ if (this.readFreshPrefetch(this.prefetchRequest(pathname).cacheKey) !== undefined) return;
4610
4734
 
4611
4735
  return this.fetchPage(pathname, undefined, false, false)
4612
4736
  .catch(function(error) {
@@ -5478,6 +5602,7 @@ ReactDOMServer.configureApp(__farmAppSetup);`;
5478
5602
  }
5479
5603
  __name(generateFarmRendererAppSetupServerCode, "generateFarmRendererAppSetupServerCode");
5480
5604
  function generateVirtualEntryCode(apiRoutes, pageRoutes, layoutRoutes, routeSlots, errorRoutes, metadataImageRoutes, applicationMetadataRoutes, middlewareRoutes, redirectRoutes, configuredRewriteRoutes, configuredHeaderRoutes, openAPIReference, notFoundPath, instrumentationPath, config, farmDocsPrecompiledManifest, configModulePath, hasServerRuntimeIntegrations, hasRuntimeIntegrationConfig, hasConfiguredRuntimePlugins, hasServerRuntimePlugins, preset, i18nCatalogs, isolatedClientBoundaryModules, hydrationPlanCache) {
5605
+ const farmIslandsMode = resolveFarmServerComponentsMode(config.experimental?.serverComponents) === "islands";
5481
5606
  const hasCompressionRuntime = config.compress && resolveFarmInstrumentationRuntime(preset) === "nodejs";
5482
5607
  const servesAgentRobotsTxt = Boolean(config.agent?.crawlers?.enabled) && !applicationMetadataRoutes.some(
5483
5608
  (metadata) => metadata.kind === "robots" && metadata.pattern === "/"
@@ -5501,7 +5626,7 @@ function generateVirtualEntryCode(apiRoutes, pageRoutes, layoutRoutes, routeSlot
5501
5626
  );
5502
5627
  const hasReactSyncRender = isReactRenderer(config.renderer);
5503
5628
  const rendererServerImports = isReactRenderer(config.renderer) ? `import * as React from "react";
5504
- import * as ReactDOMServer from "react-dom/server";${hasIsolatedClientGraphRuntime ? '\nimport { isolateFarmServerPageGraph, wrapFarmIsolatedClientGraph } from "@farm.js/core/internal/isolated-boundary";\nimport { renderFarmServerTreePage } from "@farm.js/core/internal/server-tree";' : ""}` : `import React, * as ReactDOMServer from ${JSON.stringify(config.renderer.server)};${generateFarmRendererAppSetupServerCode(config)}`;
5629
+ import * as ReactDOMServer from "react-dom/server";${hasIsolatedClientGraphRuntime ? farmIslandsMode ? '\nimport { isolateFarmServerPageGraph, wrapFarmIsolatedClientGraph, renderFarmServerTreePage } from "@farm.js/core/internal/islands-runtime";' : '\nimport { isolateFarmServerPageGraph, wrapFarmIsolatedClientGraph } from "@farm.js/core/internal/isolated-boundary";\nimport { renderFarmServerTreePage } from "@farm.js/core/internal/server-tree";' : ""}` : `import React, * as ReactDOMServer from ${JSON.stringify(config.renderer.server)};${generateFarmRendererAppSetupServerCode(config)}`;
5505
5630
  const routeClientGraphServerRuntime = hasIsolatedClientGraphRuntime ? `function wrapFarmRouteClientGraph(element) {
5506
5631
  return wrapFarmIsolatedClientGraph(React, element);
5507
5632
  }
@@ -5514,13 +5639,16 @@ function isolateFarmRouteServerPage(element) {
5514
5639
 
5515
5640
  // An async page below a hydrating layout renders as a serialized tree the browser rebuilds in
5516
5641
  // the layout's React root, so its client components read the layout's context.
5517
- function renderFarmRouteServerTree(element) {
5518
- return renderFarmServerTreePage(React, element, { isolate: isolateFarmRouteServerPage });
5642
+ function renderFarmRouteServerTree(element, extra) {
5643
+ return renderFarmServerTreePage(React, element, {
5644
+ isolate: isolateFarmRouteServerPage,${farmIslandsMode ? "\n values: true," : ""}
5645
+ ...extra,
5646
+ });
5519
5647
  }` : `function wrapFarmRouteClientGraph(element) { return element; }
5520
5648
 
5521
5649
  function isolateFarmRouteServerPage(element) { return element; }
5522
5650
 
5523
- function renderFarmRouteServerTree(element) { return element; }`;
5651
+ function renderFarmRouteServerTree(element, extra) { return element; }`;
5524
5652
  const hasGeneratedMetadataImages = metadataImageRoutes.some(
5525
5653
  (image) => image.sourceType === "module"
5526
5654
  );
@@ -5558,7 +5686,7 @@ function renderFarmRouteServerTree(element) { return element; }`;
5558
5686
  const isolatedHydrationMode = resolveFarmIsolatedClientHydrationMode(
5559
5687
  config.experimental?.isolatedClientHydration,
5560
5688
  {
5561
- serverComponents: config.experimental?.serverComponents === true,
5689
+ serverComponents: resolveFarmServerComponentsMode(config.experimental?.serverComponents) === "rsc",
5562
5690
  hasUnsupportedIntegrationProvider: Boolean(unsupportedIntegrationProvider)
5563
5691
  }
5564
5692
  );
@@ -5566,6 +5694,10 @@ function renderFarmRouteServerTree(element) { return element; }`;
5566
5694
  config.renderer,
5567
5695
  Boolean(unsupportedIntegrationProvider)
5568
5696
  );
5697
+ const pageHydrationPlanOptions = {
5698
+ ...hydrationPlanOptions,
5699
+ serverOwners: resolveFarmServerComponentsMode(config.experimental?.serverComponents) === "islands"
5700
+ };
5569
5701
  const layoutHydrationPlans = layoutRoutes.map((layout) => ({
5570
5702
  ...layout,
5571
5703
  hydration: getCachedClientModuleHydrationPlan(
@@ -5590,7 +5722,7 @@ function renderFarmRouteServerTree(element) { return element; }`;
5590
5722
  config.root,
5591
5723
  isolatedHydrationMode,
5592
5724
  hydrationPlanCache,
5593
- hydrationPlanOptions
5725
+ pageHydrationPlanOptions
5594
5726
  )
5595
5727
  ])
5596
5728
  );
@@ -5876,7 +6008,14 @@ function renderFarmRouteServerTree(element) { return element; }`;
5876
6008
  withFarmRouteContext,
5877
6009
  createLateNotFoundRecovery,
5878
6010
  createLateRedirectRecovery,${hasFarmServerStorageConfig(config.storage) ? "\n _registerFarmStorageModules,\n disposeFarmStorage,\n initFarmStorage," : ""}
5879
- } from "@farm.js/core/internal/production-runtime";`;
6011
+ } from "@farm.js/core/internal/production-runtime";${farmIslandsMode ? `
6012
+ import { getSharedLayoutPrefixLength, handleFarmFormActionRequest, ignoreFarmHeldValues, installFarmIslandValues, parseFarmLayoutChainHeader } from "@farm.js/core/internal/production-runtime";
6013
+ import { installFarmIslandsServer } from "@farm.js/core/internal/islands-server";
6014
+ installFarmIslandsServer();
6015
+ const farmFormActionsConfig = ${JSON.stringify(resolveServerActionsConfig(config.serverActions))};
6016
+ installFarmIslandValues();
6017
+ ${islandsActionKeyCode()}
6018
+ ${FARM_SEGMENT_NAVIGATION_SERVER_RUNTIME}` : ""}`;
5880
6019
  const productionSiteTelemetryImport = config.telemetry ? `import { createFarmProductionSiteReporter } from "@farm.js/core/internal/product-telemetry-runtime";` : "";
5881
6020
  const metadataImageRuntimeImport = hasGeneratedMetadataImages ? `import { createFarmMetadataImageResponse } from "@farm.js/core/internal/metadata-image-runtime";` : "";
5882
6021
  const pluginRuntimeImport = hasPluginRuntime ? `import { PluginManager } from "@farm.js/core/plugin";` : "";
@@ -7029,7 +7168,7 @@ const farmClientEntryPreloadTags = farmClientModulePreloads
7029
7168
  : "";
7030
7169
  // The client modules a document's markup loads: its islands' boundaries and the
7031
7170
  // client references of its server tree.
7032
- const FARM_CLIENT_MODULE_REFERENCE_PATTERN = /data-farm-client-boundary="([^"]+)"|"r":"(\\/[^"]+)"/g;
7171
+ const FARM_CLIENT_MODULE_REFERENCE_PATTERN = /<f-island src="([^"]+)"|"r":"(\\/[^"]+)"/g;
7033
7172
 
7034
7173
  function renderFarmClientModulePreload(index) {
7035
7174
  return '\\n <link rel="modulepreload" href="/' +
@@ -8502,7 +8641,7 @@ ${hasServerRuntimeIntegrations ? `
8502
8641
  ` : ""}
8503
8642
  ${config.agent?.manifest !== false ? `
8504
8643
  // agent.manifest: /.well-known/farmjs.json (and 0.1.34's /.well-known/farmjs), the app's
8505
- // public manifest; Farm Infra's signed request gets the full view.
8644
+ // public manifest, the same document for every request.
8506
8645
  if (
8507
8646
  [${JSON.stringify(FARM_APP_MANIFEST_PATH)}, ${JSON.stringify(FARM_APP_MANIFEST_LEGACY_PATH)}].includes(
8508
8647
  normalizeRuntimePath(routePathname),
@@ -8601,6 +8740,11 @@ ${hasServerRuntimeIntegrations ? `
8601
8740
  // Handle page routes (SSR)
8602
8741
  emitFarmEvent({ type: "render.start", route: pathname, pathname });
8603
8742
  const matchedRoute = matchPageRoute(routePathname);
8743
+ ${farmIslandsMode ? `// Islands mode: a form or client component posting a server action to this page.
8744
+ if (matchedRoute && request.method === "POST") {
8745
+ const actionResponse = await handleFarmFormActionRequest(request, farmFormActionsConfig);
8746
+ if (actionResponse) return applyProductionMiddlewareHeaders(actionResponse, middlewareHeaders);
8747
+ }` : ""}
8604
8748
  if (matchedRoute) {
8605
8749
  const trailingSlashLocation = resolveFarmTrailingSlashRedirect(
8606
8750
  url,
@@ -8619,6 +8763,21 @@ ${hasServerRuntimeIntegrations ? `
8619
8763
  emitFarmEvent({ type: "route.matched", pathname, route: route.pattern, params });
8620
8764
 
8621
8765
  try {
8766
+ ${farmIslandsMode ? `// Islands mode: the layouts the navigating browser keeps, decided before the shell cache
8767
+ // so a PPR route caches each segment under its own key. A static page, a layout that
8768
+ // hydrates as a root, or a route slot always renders whole.
8769
+ const farmSegmentLayouts = getApplicableLayouts(
8770
+ routePathname,
8771
+ route.directory || route.pattern,
8772
+ );
8773
+ const farmKeptLayoutCount =
8774
+ resolveRouteRenderingView(route).ssg ||
8775
+ farmSegmentLayouts.some((layout) => layout.shouldHydrate === true) ||
8776
+ matchRouteSlots(routePathname, request.headers.get("x-farm-intercept-from")).length > 0
8777
+ ? 0
8778
+ : countFarmKeptLayouts(request, farmSegmentLayouts, params);
8779
+ // The root layout always renders, so keeping one layout keeps nothing.
8780
+ const farmKeptLayouts = farmKeptLayoutCount > 1 ? farmKeptLayoutCount : 0;` : `const farmKeptLayouts = 0;`}
8622
8781
  const pprConfig = resolvePPRConfig(route);
8623
8782
  const pprBypassReason = pprConfig.enabled
8624
8783
  ? getPPRShellBypassReason(request, middlewareData, middlewareContext)
@@ -8631,7 +8790,7 @@ ${hasServerRuntimeIntegrations ? `
8631
8790
  farmLocaleResolution && farmI18nConfig.routing !== "none"
8632
8791
  ? resolveFarmI18nAlternateOrigin(request)
8633
8792
  : ""
8634
- )
8793
+ ) + (farmKeptLayouts ? ":segment:" + farmKeptLayouts : "")
8635
8794
  : null;
8636
8795
  if (pprConfig.enabled && pprBypassReason) {
8637
8796
  emitFarmEvent({ type: "ppr.shell.bypass", route: pathname, reason: pprBypassReason });
@@ -8658,6 +8817,10 @@ ${hasServerRuntimeIntegrations ? `
8658
8817
  "x-farm-preload-buffered": getFarmBufferedPreloadMarker(cachedPPRShell),
8659
8818
  ...(farmFontPreloadHeader ? { "Link": farmFontPreloadHeader } : {}),
8660
8819
  ...getPPRHeaders("hit", pprConfig),
8820
+ // A segment is one navigation's answer, never a CDN entry: some CDNs ignore Vary.
8821
+ ...(farmKeptLayouts
8822
+ ? { "Cache-Control": "private, no-store", "Vary": "F-Layouts" }
8823
+ : {}),
8661
8824
  },
8662
8825
  }), middlewareHeaders), cachedPPRShell);
8663
8826
  }
@@ -8884,6 +9047,21 @@ ${hasServerRuntimeIntegrations ? `
8884
9047
  };
8885
9048
  });
8886
9049
 
9050
+ ${farmIslandsMode ? `// Islands mode: a route a shared cache may store (a PPR shell, a static page) renders
9051
+ // whole for every request, so a cache hit stays a hit. Other routes leave out what the
9052
+ // navigating browser keeps: the layouts it shows and the values it holds.
9053
+ const farmSharedCacheableRoute = Boolean(getRouteSharedCacheControl(route, pprCanCache));
9054
+ if (farmSharedCacheableRoute) ignoreFarmHeldValues();
9055
+ const farmLayoutKeyOf = getFarmLayoutKey;
9056
+ // A navigation the browser renders in its layout's React root rebuilds a server-tree page
9057
+ // from its payload, so the page's rendered HTML would go unused.
9058
+ const farmPayloadOnlyNavigation =
9059
+ !farmSharedCacheableRoute &&
9060
+ shouldHydrateLayout &&
9061
+ route.serverTree === true &&
9062
+ !route.shouldHydrate &&
9063
+ request.headers.get("f-render") === "tree";` : `const farmLayoutKeyOf = null;
9064
+ const farmPayloadOnlyNavigation = false;`}
8887
9065
  const renderPageElement = async () => {
8888
9066
  // First, render the page content
8889
9067
  let pageElement;
@@ -8910,7 +9088,10 @@ ${hasServerRuntimeIntegrations ? `
8910
9088
  pageElement = wrapFarmRouteClientGraph(pageElement);
8911
9089
  } else if (shouldHydrateLayout && !route.shouldHydrate) {
8912
9090
  pageElement = route.serverTree
8913
- ? await renderFarmRouteServerTree(pageElement)
9091
+ ? await renderFarmRouteServerTree(
9092
+ pageElement,
9093
+ farmPayloadOnlyNavigation ? { payloadOnly: true } : undefined,
9094
+ )
8914
9095
  : isolateFarmRouteServerPage(pageElement);
8915
9096
  }
8916
9097
 
@@ -8935,6 +9116,22 @@ ${hasServerRuntimeIntegrations ? `
8935
9116
  for (let i = applicableLayouts.length - 1; i >= 0; i--) {
8936
9117
  const layout = applicableLayouts[i];
8937
9118
  const LayoutComponent = layout.module.default;
9119
+ // Islands mode: a layout the browser keeps sends only its boundary, so the client
9120
+ // knows where the rest goes. The root layout always renders: it may own the document.
9121
+ if (LayoutComponent && i > 0 && i < farmKeptLayouts) {
9122
+ wrappedElement = React.createElement(
9123
+ "div",
9124
+ {
9125
+ "data-farm-layout-boundary": "true",
9126
+ "data-farm-layout-pattern": layout.pattern,
9127
+ "data-farm-layout-key": farmLayoutKeyOf(layout.pattern, params),
9128
+ "data-farm-layout-kept": "true",
9129
+ style: { display: "contents" },
9130
+ },
9131
+ wrappedElement,
9132
+ );
9133
+ continue;
9134
+ }
8938
9135
  if (LayoutComponent) {
8939
9136
  const slotProps = {};
8940
9137
  for (const slot of renderedRouteSlots) {
@@ -8961,6 +9158,9 @@ ${hasServerRuntimeIntegrations ? `
8961
9158
  {
8962
9159
  "data-farm-layout-boundary": "true",
8963
9160
  "data-farm-layout-pattern": layout.pattern,
9161
+ "data-farm-layout-key": farmLayoutKeyOf
9162
+ ? farmLayoutKeyOf(layout.pattern, params)
9163
+ : undefined,
8964
9164
  style: { display: "contents" },
8965
9165
  },
8966
9166
  wrappedElement,
@@ -9071,7 +9271,7 @@ ${hasServerRuntimeIntegrations ? `
9071
9271
  farmLocaleResolution,
9072
9272
  );
9073
9273
  const hasRequestScopedRender = Boolean(
9074
- pageStatus >= 400 ||
9274
+ pageStatus >= 400 ||${farmIslandsMode ? "\n farmKeptLayouts > 0 ||\n farmPayloadOnlyNavigation ||" : ""}
9075
9275
  renderReadRequest ||
9076
9276
  request.headers.get("x-farm-intercept-from") ||
9077
9277
  hasPrivateRequestHeaders ||
@@ -9091,7 +9291,12 @@ ${hasServerRuntimeIntegrations ? `
9091
9291
  if (renderedPage.stream || hasRequestScopedRender || !sharedCacheControl) {
9092
9292
  responseHeaders["Cache-Control"] = "private, no-store";
9093
9293
  }
9094
- const farmI18nSnapshot = getFarmI18nSnapshot();
9294
+ const farmI18nSnapshot = getFarmI18nSnapshot();${farmIslandsMode ? `
9295
+ // Islands mode: a navigation that names the values it holds, or the layouts it shows,
9296
+ // gets HTML without them.
9297
+ responseHeaders["Vary"] = farmSharedCacheableRoute
9298
+ ? "F-Layouts"
9299
+ : "F-Values, F-Layouts, F-Render";` : ""}
9095
9300
  let html = renderedPage.html;
9096
9301
 
9097
9302
  // Check if the layout already rendered a full HTML document
@@ -11003,6 +11208,12 @@ async function copyPrismaClientForVercel(root, nitroFuncDir, fs4) {
11003
11208
  await writeNitroOutputPackage(nitroFuncDir, functionPackage, fs4);
11004
11209
  }
11005
11210
  __name(copyPrismaClientForVercel, "copyPrismaClientForVercel");
11211
+ function islandsActionKeyCode() {
11212
+ const key = randomBytes(32).toString("base64url");
11213
+ return `import { setBuildDefaults as __farmIslxBuildDefaults } from "@farm.js/core/internal/islx-server";
11214
+ __farmIslxBuildDefaults({ key: ${JSON.stringify(key)} });`;
11215
+ }
11216
+ __name(islandsActionKeyCode, "islandsActionKeyCode");
11006
11217
 
11007
11218
  // src/build/project-module-runner.ts
11008
11219
  async function createFarmProjectModuleSsrEnvironment() {