@farm.js/core 0.1.44 → 0.1.46

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 (191) hide show
  1. package/dist/{agent-mcp-EnzWYv_X.d.ts → agent-mcp-BtK_KZ1m.d.ts} +2 -2
  2. package/dist/{agent-mcp-CWI-awqd.d.mts → agent-mcp-Cc-ypyNi.d.mts} +2 -2
  3. package/dist/agent-runtime.d.mts +10 -10
  4. package/dist/agent-runtime.d.ts +10 -10
  5. package/dist/api/client.d.mts +3 -3
  6. package/dist/api/client.d.ts +3 -3
  7. package/dist/api/route-manager.d.mts +16 -16
  8. package/dist/api/route-manager.d.ts +16 -16
  9. package/dist/api/runtime.d.mts +12 -12
  10. package/dist/api/runtime.d.ts +12 -12
  11. package/dist/{api-client-Dk9QOLwr.d.mts → api-client-CFdv-Xgh.d.mts} +3 -3
  12. package/dist/{api-client-BJv9mTbO.d.ts → api-client-CvI5oOBE.d.ts} +3 -3
  13. package/dist/api.d.mts +17 -17
  14. package/dist/api.d.ts +17 -17
  15. package/dist/{app-DG3dE8v5.d.mts → app-2SBLAaNq.d.mts} +8 -8
  16. package/dist/{app-CAN_2Cqo.d.ts → app-BlXGEpdA.d.ts} +8 -8
  17. package/dist/{app-manifest-DazjgQya.d.ts → app-manifest-D1Tgp8ya.d.ts} +1 -1
  18. package/dist/{app-manifest-8x5VjZ0L.d.mts → app-manifest-nZHIvS3a.d.mts} +1 -1
  19. package/dist/app-markdown.d.mts +11 -11
  20. package/dist/app-markdown.d.ts +11 -11
  21. package/dist/{base-path-BU16ETmo.d.mts → base-path-leyrqXbX.d.mts} +1 -1
  22. package/dist/{base-path-BU16ETmo.d.ts → base-path-leyrqXbX.d.ts} +1 -1
  23. package/dist/{chunk-YFLBG2W3.mjs → chunk-4GRLJURM.mjs} +1 -1
  24. package/dist/{chunk-GA6JM4L6.cjs → chunk-A7XJHKRK.cjs} +43 -43
  25. package/dist/{chunk-T44ECMEP.cjs → chunk-DQNWI2PV.cjs} +6 -6
  26. package/dist/{chunk-5GBL2LKD.cjs → chunk-E6Z63WDR.cjs} +237 -135
  27. package/dist/{chunk-3YJMBQ27.cjs → chunk-F6KWRHF5.cjs} +1 -1
  28. package/dist/{chunk-AI3WVJNP.cjs → chunk-HDFNAUSG.cjs} +50 -50
  29. package/dist/{chunk-R4J2UOV4.mjs → chunk-HNGR7CTG.mjs} +1 -1
  30. package/dist/{chunk-2MKTHHEU.mjs → chunk-JBL546U4.mjs} +3 -3
  31. package/dist/{chunk-QGFKXYC7.mjs → chunk-KLDBRGD5.mjs} +2 -2
  32. package/dist/{chunk-XUHIRBXY.mjs → chunk-TUGIZGTH.mjs} +1 -1
  33. package/dist/{chunk-ERA5RP3L.mjs → chunk-YLPEGQDE.mjs} +175 -73
  34. package/dist/{chunk-XPSGGECF.cjs → chunk-ZM6U54TC.cjs} +2 -2
  35. package/dist/{client-plugins-nQ0tYt4l.d.mts → client-plugins-DEmIQo5R.d.mts} +1438 -1438
  36. package/dist/{client-plugins-BGS0wqzc.d.ts → client-plugins-br48Hpmk.d.ts} +1438 -1438
  37. package/dist/client-plugins.d.mts +10 -10
  38. package/dist/client-plugins.d.ts +10 -10
  39. package/dist/client.d.mts +17 -17
  40. package/dist/client.d.ts +17 -17
  41. package/dist/config.d.mts +10 -10
  42. package/dist/config.d.ts +10 -10
  43. package/dist/docs.d.mts +11 -11
  44. package/dist/docs.d.ts +11 -11
  45. package/dist/{endpoint-BOE0IAaG.d.ts → endpoint-BgHn0lhl.d.ts} +1 -1
  46. package/dist/{endpoint-DGZRZHux.d.mts → endpoint-BkMSCRf6.d.mts} +1 -1
  47. package/dist/environment/vite.d.mts +1 -1
  48. package/dist/environment/vite.d.ts +1 -1
  49. package/dist/i18n/client.d.mts +2 -2
  50. package/dist/i18n/client.d.ts +2 -2
  51. package/dist/i18n/index.d.mts +3 -3
  52. package/dist/i18n/index.d.ts +3 -3
  53. package/dist/i18n/server.d.mts +5 -5
  54. package/dist/i18n/server.d.ts +5 -5
  55. package/dist/image/server.d.mts +1 -1
  56. package/dist/image/server.d.ts +1 -1
  57. package/dist/image/sharp.d.mts +1 -1
  58. package/dist/image/sharp.d.ts +1 -1
  59. package/dist/{image-config-BpH1q5R8.d.ts → image-config-CeDgNyX4.d.mts} +1 -1
  60. package/dist/{image-config-BpH1q5R8.d.mts → image-config-CeDgNyX4.d.ts} +1 -1
  61. package/dist/image.d.mts +1 -1
  62. package/dist/image.d.ts +1 -1
  63. package/dist/{index-BJJfLxJo.d.mts → index-Cl3akY5U.d.mts} +2 -2
  64. package/dist/{index-Cy26isrh.d.ts → index-CyD9Rfso.d.ts} +2 -2
  65. package/dist/{index-CwoOP-MW.d.ts → index-MocnSP3a.d.ts} +2 -2
  66. package/dist/{index-y1jgR74U.d.mts → index-_nhUt_dh.d.mts} +2 -2
  67. package/dist/index.cjs +6 -6
  68. package/dist/index.d.mts +32 -32
  69. package/dist/index.d.ts +32 -32
  70. package/dist/index.mjs +5 -5
  71. package/dist/{instrumentation-runtime-CE06JLHZ.d.mts → instrumentation-runtime-CX9Zh-16.d.mts} +1 -1
  72. package/dist/{instrumentation-runtime-CE06JLHZ.d.ts → instrumentation-runtime-CX9Zh-16.d.ts} +1 -1
  73. package/dist/instrumentation.d.mts +2 -2
  74. package/dist/instrumentation.d.ts +2 -2
  75. package/dist/integrations.d.mts +10 -10
  76. package/dist/integrations.d.ts +10 -10
  77. package/dist/internal/app-markdown-runtime.d.mts +11 -11
  78. package/dist/internal/app-markdown-runtime.d.ts +11 -11
  79. package/dist/internal/build-runtime.cjs +6 -6
  80. package/dist/internal/build-runtime.d.mts +12 -12
  81. package/dist/internal/build-runtime.d.ts +12 -12
  82. package/dist/internal/build-runtime.mjs +5 -5
  83. package/dist/internal/client-error-overlay.cjs +4 -4
  84. package/dist/internal/client-error-overlay.mjs +1 -1
  85. package/dist/internal/client-runtime.d.mts +1 -1
  86. package/dist/internal/client-runtime.d.ts +1 -1
  87. package/dist/internal/compression-runtime.d.mts +10 -10
  88. package/dist/internal/compression-runtime.d.ts +10 -10
  89. package/dist/internal/config-runtime.d.mts +11 -11
  90. package/dist/internal/config-runtime.d.ts +11 -11
  91. package/dist/internal/form-actions.d.mts +1 -1
  92. package/dist/internal/form-actions.d.ts +1 -1
  93. package/dist/internal/islx-client.d.mts +4 -0
  94. package/dist/internal/islx-client.d.ts +4 -0
  95. package/dist/internal/product-telemetry-runtime.cjs +2 -2
  96. package/dist/internal/product-telemetry-runtime.mjs +1 -1
  97. package/dist/internal/production-runtime.cjs +4 -4
  98. package/dist/internal/production-runtime.d.mts +25 -25
  99. package/dist/internal/production-runtime.d.ts +25 -25
  100. package/dist/internal/production-runtime.mjs +3 -3
  101. package/dist/{layers-CM5i6T7z.d.mts → layers-D9fbe-rz.d.mts} +1 -1
  102. package/dist/{layers-CM5i6T7z.d.ts → layers-D9fbe-rz.d.ts} +1 -1
  103. package/dist/markdown.d.mts +10 -10
  104. package/dist/markdown.d.ts +10 -10
  105. package/dist/middleware.d.mts +12 -12
  106. package/dist/middleware.d.ts +12 -12
  107. package/dist/navigation.d.mts +13 -13
  108. package/dist/navigation.d.ts +13 -13
  109. package/dist/{observability-CoXunYhS.d.mts → observability-B2363jB6.d.mts} +1 -1
  110. package/dist/{observability-CoXunYhS.d.ts → observability-B2363jB6.d.ts} +1 -1
  111. package/dist/observability.d.mts +1 -1
  112. package/dist/observability.d.ts +1 -1
  113. package/dist/og.d.mts +0 -5
  114. package/dist/og.d.ts +0 -5
  115. package/dist/plugin.cjs +5 -5
  116. package/dist/plugin.d.mts +12 -12
  117. package/dist/plugin.d.ts +12 -12
  118. package/dist/plugin.mjs +4 -4
  119. package/dist/{production-runtime-ClFA_1KQ.d.mts → production-runtime-BEbIyIUe.d.mts} +4 -4
  120. package/dist/{production-runtime-BVMDgHrA.d.ts → production-runtime-DsHjccVI.d.ts} +4 -4
  121. package/dist/{ssg-XnMHCyEc.d.ts → programmatic-routes-client-DlMKstmL.d.ts} +57 -57
  122. package/dist/{ssg-ByrOVYdM.d.mts → programmatic-routes-client-Dqr6tHND.d.mts} +57 -57
  123. package/dist/{render-plan-CoSovy_O.d.mts → render-plan-Bu6XOxNg.d.mts} +1 -1
  124. package/dist/{render-plan-y2DefWf8.d.ts → render-plan-MefW_fLC.d.ts} +1 -1
  125. package/dist/renderer/react/server.d.mts +1 -1
  126. package/dist/renderer/react/server.d.ts +1 -1
  127. package/dist/renderer-client.d.mts +12 -12
  128. package/dist/renderer-client.d.ts +12 -12
  129. package/dist/{request-cNM09Q7e.d.mts → request-BBe1B8Bk.d.mts} +1 -1
  130. package/dist/{request-aG5Wovm5.d.ts → request-CMsRJQK3.d.ts} +1 -1
  131. package/dist/request.d.mts +11 -11
  132. package/dist/request.d.ts +11 -11
  133. package/dist/{resolver-khasx3fU.d.mts → resolver-C2G-3Tm6.d.mts} +1 -1
  134. package/dist/{resolver-DadfRL6F.d.ts → resolver-DC57A4vz.d.ts} +1 -1
  135. package/dist/{integration-api-DWyMmvrR.d.mts → route-2_yXC6gv.d.mts} +100 -100
  136. package/dist/{integration-api-BuPHMeKz.d.ts → route-DFhZj6jN.d.ts} +100 -100
  137. package/dist/{route-pattern-W-SsJGSp.d.mts → route-pattern-CVsVbq5n.d.mts} +1 -1
  138. package/dist/{route-pattern-W-SsJGSp.d.ts → route-pattern-CVsVbq5n.d.ts} +1 -1
  139. package/dist/{route-rendering-EyInfsjI.d.mts → route-rendering-DTLNruPw.d.ts} +1 -1
  140. package/dist/{route-rendering-B3uQmCWX.d.ts → route-rendering-Do8tuYgh.d.mts} +1 -1
  141. package/dist/{router-DNUf-Bg1.d.ts → router-BJreOZ-k.d.ts} +2 -2
  142. package/dist/{router-Devibh4r.d.mts → router-o2mZB9Y4.d.mts} +2 -2
  143. package/dist/routes.d.mts +11 -11
  144. package/dist/routes.d.ts +11 -11
  145. package/dist/{runtime-BgDQzBiu.d.ts → runtime-B9HmxiZc.d.ts} +2 -2
  146. package/dist/{runtime-CV2UCV-5.d.mts → runtime-CCxTmGuf.d.mts} +2 -2
  147. package/dist/{runtime-CLr9P5kn.d.ts → runtime-Cp5YZNz4.d.mts} +5 -5
  148. package/dist/{runtime-9KZb8AI5.d.mts → runtime-Da57KD8F.d.ts} +5 -5
  149. package/dist/server-action-security.d.mts +1 -1
  150. package/dist/server-action-security.d.ts +1 -1
  151. package/dist/server-fn-client.d.mts +4 -4
  152. package/dist/server-fn-client.d.ts +4 -4
  153. package/dist/{server-fn-error-DDh14a0V.d.mts → server-fn-error-DrcH9cc1.d.mts} +1 -1
  154. package/dist/{server-fn-error-DDh14a0V.d.ts → server-fn-error-DrcH9cc1.d.ts} +1 -1
  155. package/dist/server-fn.d.mts +3 -3
  156. package/dist/server-fn.d.ts +3 -3
  157. package/dist/server-plugins.d.mts +11 -11
  158. package/dist/server-plugins.d.ts +11 -11
  159. package/dist/server-query-client.d.mts +2 -2
  160. package/dist/server-query-client.d.ts +2 -2
  161. package/dist/server-query.d.mts +2 -2
  162. package/dist/server-query.d.ts +2 -2
  163. package/dist/server.cjs +14 -14
  164. package/dist/server.d.mts +20 -20
  165. package/dist/server.d.ts +20 -20
  166. package/dist/server.mjs +4 -4
  167. package/dist/{spa-router-Ds6R_oe-.d.ts → spa-router-CN2vc0GY.d.ts} +4 -4
  168. package/dist/{spa-router-BIxh4IY-.d.mts → spa-router-COZLIB7k.d.mts} +4 -4
  169. package/dist/storage.d.mts +3 -3
  170. package/dist/storage.d.ts +3 -3
  171. package/dist/testing.d.mts +12 -12
  172. package/dist/testing.d.ts +12 -12
  173. package/dist/theme/server.d.mts +1 -1
  174. package/dist/theme/server.d.ts +1 -1
  175. package/dist/{types-CnH8DOqo.d.mts → types--Wh02r5_.d.mts} +1 -1
  176. package/dist/{types-CnH8DOqo.d.ts → types--Wh02r5_.d.ts} +1 -1
  177. package/dist/{types-Cc8l9IqS.d.ts → types-BnIqOn9w.d.mts} +1 -1
  178. package/dist/{types-Cc8l9IqS.d.mts → types-BnIqOn9w.d.ts} +1 -1
  179. package/dist/{utils-BN70ueSN.d.ts → utils-BAtVIHfw.d.mts} +2 -2
  180. package/dist/{utils-BrjR5xRs.d.mts → utils-Y8MZrj4b.d.ts} +2 -2
  181. package/dist/version.cjs +2 -2
  182. package/dist/version.mjs +1 -1
  183. package/dist/vite.cjs +5 -5
  184. package/dist/vite.d.mts +14 -14
  185. package/dist/vite.d.ts +14 -14
  186. package/dist/vite.mjs +4 -4
  187. package/dist/{workflows-IWP1ddBm.d.mts → workflows-Df1C_7OG.d.mts} +1 -1
  188. package/dist/{workflows-IWP1ddBm.d.ts → workflows-Df1C_7OG.d.ts} +1 -1
  189. package/dist/workflows.d.mts +1 -1
  190. package/dist/workflows.d.ts +1 -1
  191. package/package.json +2 -2
@@ -11,7 +11,7 @@ import {
11
11
  import {
12
12
  generateNativeMCPPluginSource,
13
13
  layoutsCanCoverSamePage
14
- } from "./chunk-XUHIRBXY.mjs";
14
+ } from "./chunk-TUGIZGTH.mjs";
15
15
  import {
16
16
  assertFarmDocsAdapterServesNoGuardedPages,
17
17
  compileFarmDocsAdapterEdgeManifest,
@@ -82,7 +82,7 @@ import {
82
82
  resolveFarmIsolatedClientHydrationMode,
83
83
  resolveFarmNotFoundComponentPath,
84
84
  usesFarmServerTree
85
- } from "./chunk-QGFKXYC7.mjs";
85
+ } from "./chunk-KLDBRGD5.mjs";
86
86
  import {
87
87
  PluginManager
88
88
  } from "./chunk-FGH3ZXTP.mjs";
@@ -109,7 +109,7 @@ import {
109
109
  resolveFarmAppManifestInput,
110
110
  routeBoundaryCoversDirectory,
111
111
  stripRouteGroups
112
- } from "./chunk-YFLBG2W3.mjs";
112
+ } from "./chunk-4GRLJURM.mjs";
113
113
  import {
114
114
  farmPluginMayAffectRuntimePath
115
115
  } from "./chunk-Y5RG6B7S.mjs";
@@ -224,7 +224,7 @@ import {
224
224
  } from "./chunk-BTHHUD7Q.mjs";
225
225
  import {
226
226
  FARM_VERSION
227
- } from "./chunk-R4J2UOV4.mjs";
227
+ } from "./chunk-HNGR7CTG.mjs";
228
228
  import {
229
229
  getFarmPresetRuntime
230
230
  } from "./chunk-2A3EQHXX.mjs";
@@ -7019,6 +7019,73 @@ function createFarmDocumentStream(contentStream, prefix, suffix, onComplete) {
7019
7019
  });
7020
7020
  }
7021
7021
 
7022
+ // Streams a layout's own <html> document. React's output is held until the opening <body>, so
7023
+ // Farm's head assets go into the document's head (openDocument); the body then streams through.
7024
+ // The closing </body></html> React writes with its shell is held back: Suspense content React
7025
+ // streams later belongs inside the body, before Farm's footer (closeDocument) and the closing tags.
7026
+ function createFarmFullDocumentStream(contentStream, openDocument, closeDocument, onComplete) {
7027
+ const encoder = new TextEncoder();
7028
+ const decoder = new TextDecoder();
7029
+ const reader = contentStream.getReader();
7030
+ // The footer renders after the handler returned, outside its async scope.
7031
+ const cspNonce = _resolveCurrentCspNonce();
7032
+ let opening = "";
7033
+ let opened = false;
7034
+ let rootOpened = false;
7035
+ let closing = false;
7036
+ return new ReadableStream({
7037
+ async pull(controller) {
7038
+ try {
7039
+ for (;;) {
7040
+ const result = await reader.read();
7041
+ let text = result.done ? decoder.decode() : decoder.decode(result.value, { stream: true });
7042
+ if (!opened) {
7043
+ opening += text;
7044
+ if (!result.done && !/<body\\b[^>]*>/i.test(opening)) continue;
7045
+ opened = true;
7046
+ text = opening;
7047
+ opening = "";
7048
+ const closeAt = text.search(/<\\/body>/i);
7049
+ const head = closeAt >= 0 ? text.slice(0, closeAt) : text;
7050
+ const rest = closeAt >= 0 ? text.slice(closeAt) : "";
7051
+ // ensureFarmDocumentRoot opens #root unless the layout's body already does.
7052
+ rootOpened = !/<body\\b[^>]*>\\s*<div\\b[^>]*\\sid=["']root["']/i.test(head);
7053
+ text = openDocument(head) + rest;
7054
+ }
7055
+ if (!closing) {
7056
+ const closeAt = text.search(/<\\/body>/i);
7057
+ if (closeAt >= 0) {
7058
+ closing = true;
7059
+ // Drop the closing tags and Farm's wrapper divs around the document; keep what React
7060
+ // wrote after them.
7061
+ text = text.slice(0, closeAt) +
7062
+ text.slice(closeAt).replace(/^<\\/body>\\s*(?:<\\/html>)?(?:\\s*<\\/div>)*/i, "");
7063
+ }
7064
+ }
7065
+ if (result.done) {
7066
+ const footer = await _runWithFarmCspNonce(cspNonce, function() {
7067
+ return closeDocument(rootOpened);
7068
+ });
7069
+ controller.enqueue(encoder.encode(text + footer + "</body>\\n</html>"));
7070
+ if (onComplete) onComplete();
7071
+ controller.close();
7072
+ return;
7073
+ }
7074
+ if (text) {
7075
+ controller.enqueue(encoder.encode(text));
7076
+ return;
7077
+ }
7078
+ }
7079
+ } catch (error) {
7080
+ controller.error(error);
7081
+ }
7082
+ },
7083
+ cancel(reason) {
7084
+ return reader.cancel(reason);
7085
+ },
7086
+ });
7087
+ }
7088
+
7022
7089
  function stripFarmDocumentWrappers(markup) {
7023
7090
  return peelFarmDocumentPrefix(markup).inner;
7024
7091
  }
@@ -9305,15 +9372,60 @@ ${hasServerRuntimeIntegrations ? `
9305
9372
  const initialHtml = html !== undefined ? html : renderedPage.shellHtml || "";
9306
9373
  const hasFullDocument = opensFarmFullDocument(initialHtml);
9307
9374
 
9308
- // Stream a suspended body as soon as React's shell is ready. Full-document
9309
- // layouts, localized documents, and cacheable PPR shells still use the
9310
- // buffered path because they require whole-document transformation, and so
9311
- // does the anonymous check behind a page's Markdown source: there, a
9312
- // redirect() under a loading boundary must still decide the status.
9375
+ const rendererHead = renderedPage.head || "";
9376
+ const rendererHasTitle = /<title[\\s>]/i.test(rendererHead);
9377
+ // First <title> wins: the fallback framework title yields to a
9378
+ // renderer-emitted one; explicit metadata titles still come first.
9379
+ const suppressDefaultTitle =
9380
+ !renderedMetadata.hasExplicitTitle && rendererHasTitle;
9381
+ // A layout's own <html> document with Farm's head assets merged in and the #root the client
9382
+ // hydrates opening its body: the whole document, or a streamed one's opening.
9383
+ const composeFarmFullDocument = function(markup) {
9384
+ let composed = addFarmFallbackIcon(
9385
+ ensureFarmDocumentRoot(ensureFarmDocumentHead(markup)),
9386
+ hasFavicon,
9387
+ );
9388
+ composed = composed
9389
+ // Inject CSS link after opening head tag or first meta tag
9390
+ .replace(/<head([^>]*)>/i, function(match, attrs) { return '<head' + attrs + '>\\n <link rel="stylesheet" href="/__farm_client_css_href__">' + renderFarmClientModulePreloads(composed, route.clientModule); })
9391
+ .replace(/<\\/head>/i, () => renderFarmRendererHydrationScript() + '\\n</head>')
9392
+ // Explicit metadata wins over renderer and layout titles. Without
9393
+ // explicit metadata, a renderer title wins over the layout title.
9394
+ .replace(/<head([^>]*)>([\\s\\S]*?)<\\/head>/i, (match, attrs, headContent) => {
9395
+ const hasAuthoritativeTitle = renderedMetadata.hasExplicitTitle || rendererHasTitle;
9396
+ let nextHeadContent = hasAuthoritativeTitle
9397
+ ? headContent.replace(/<title\\b[^>]*>[\\s\\S]*?<\\/title>\\s*/gi, "")
9398
+ : headContent;
9399
+ if (renderedMetadata.hasExplicitTitle) {
9400
+ nextHeadContent += "\\n <title>" + title + "</title>";
9401
+ }
9402
+ if (metaTags) nextHeadContent += metaTags;
9403
+ // Renderer-emitted head markup (e.g. <svelte:head>). Function
9404
+ // replacement below keeps $-sequences literal.
9405
+ const effectiveRendererHead = renderedMetadata.hasExplicitTitle
9406
+ ? rendererHead.replace(/<title\\b[^>]*>[\\s\\S]*?<\\/title>\\s*/gi, "")
9407
+ : rendererHead;
9408
+ if (effectiveRendererHead) nextHeadContent += "\\n " + effectiveRendererHead;
9409
+ return nextHeadContent === headContent
9410
+ ? match
9411
+ : "<head" + attrs + ">" + nextHeadContent + "\\n</head>";
9412
+ });
9413
+ // Last, so the charset (and the viewport, unless the layout wrote one) open the head.
9414
+ composed = ensureFarmDocumentMeta(composed, viewportTags);
9415
+ if (!composed.trim().startsWith('<!DOCTYPE')) {
9416
+ composed = '<!DOCTYPE html>\\n' + composed;
9417
+ }
9418
+ return composed;
9419
+ };
9420
+
9421
+ // Stream a suspended body as soon as React's shell is ready, a layout's own <html> document
9422
+ // included. Localized documents and cacheable PPR shells still use the buffered path
9423
+ // because they require whole-document transformation, and so does the anonymous check
9424
+ // behind a page's Markdown source: there, a redirect() under a loading boundary must still
9425
+ // decide the status.
9313
9426
  if (
9314
9427
  pageStatus === 200 &&
9315
9428
  renderedPage.stream &&
9316
- !hasFullDocument &&
9317
9429
  !farmI18nSnapshot &&
9318
9430
  !pprCacheKey &&
9319
9431
  !_isFarmMarkdownPageCheck(request.headers.get(FARM_MARKDOWN_PAGE_CHECK_HEADER))
@@ -9323,6 +9435,15 @@ ${hasServerRuntimeIntegrations ? `
9323
9435
  farmResolvedRuntimeConfig.basePath,
9324
9436
  getFarmTheme(request)
9325
9437
  );
9438
+ // The page's client data and entry, after its content.
9439
+ const farmClientScripts = function() {
9440
+ return ' ' + renderFarmClientBootstrapScript(
9441
+ pageProps.__farmCanonicalPath,
9442
+ routeSlotPayload,
9443
+ clientPageProps
9444
+ ) + '\\n' +
9445
+ ' ' + renderFarmClientEntryScript() + '\\n';
9446
+ };
9326
9447
  const streamPrefix = '<!DOCTYPE html>\\n<html lang="en">\\n<head>\\n' +
9327
9448
  farmThemeDocument.head + '\\n' +
9328
9449
  ' <meta charset="utf-8">\\n' +
@@ -9333,32 +9454,22 @@ ${hasServerRuntimeIntegrations ? `
9333
9454
  ' <link rel="modulepreload" href="/__farm_client_js_src__">' + renderFarmClientModulePreloads(null, route.clientModule) + '\\n' +
9334
9455
  renderFarmRendererHydrationScript() + '\\n' +
9335
9456
  '</head>\\n<body>\\n <div id="root">';
9336
- const streamSuffix = '</div>\\n' +
9337
- ' ' + renderFarmClientBootstrapScript(
9338
- pageProps.__farmCanonicalPath,
9339
- routeSlotPayload,
9340
- clientPageProps
9341
- ) + '\\n' +
9342
- ' ' + renderFarmClientEntryScript() + '\\n' +
9343
- '</body>\\n</html>';
9457
+ const streamSuffix = '</div>\\n' + farmClientScripts() + '</body>\\n</html>';
9344
9458
  const themedStreamPrefix = streamPrefix.replace(
9345
9459
  '<html lang="en">',
9346
9460
  () => '<html lang="en"' + farmThemeDocument.attributes + '>'
9347
9461
  );
9348
- const streamedDocument = createFarmDocumentStream(
9349
- renderedPage.stream,
9350
- themedStreamPrefix,
9351
- async function() {
9462
+ const lateNavigationRecovery = async function() {
9352
9463
  // A redirect()/notFound() after the 200 shell went out can only
9353
9464
  // be recovered in the document.
9354
9465
  const lateNavigationError = renderedPage.streamErrors.find(function(error) {
9355
9466
  return isFarmRedirectError(error) || isFarmNotFoundError(error);
9356
9467
  });
9357
- if (!lateNavigationError) return streamSuffix;
9468
+ if (!lateNavigationError) return "";
9358
9469
  if (isFarmRedirectError(lateNavigationError)) {
9359
9470
  return createLateRedirectRecovery(
9360
9471
  getFarmRedirectError(lateNavigationError).url
9361
- ) + streamSuffix;
9472
+ );
9362
9473
  }
9363
9474
  try {
9364
9475
  return createLateNotFoundRecovery(
@@ -9366,7 +9477,7 @@ ${hasServerRuntimeIntegrations ? `
9366
9477
  wrapWithFarmIntegrationProviders(createFarmNotFoundElement(pathname)),
9367
9478
  getFarmRendererRenderOptions()
9368
9479
  )
9369
- ) + streamSuffix;
9480
+ );
9370
9481
  } catch (error) {
9371
9482
  // The layouts are already in the shell; a not-found page that
9372
9483
  // needs their context cannot render alone, so use Farm's.
@@ -9376,10 +9487,10 @@ ${hasServerRuntimeIntegrations ? `
9376
9487
  React.createElement(FarmDefault404Page),
9377
9488
  getFarmRendererRenderOptions()
9378
9489
  )
9379
- ) + streamSuffix;
9490
+ );
9380
9491
  }
9381
- },
9382
- function() {
9492
+ };
9493
+ const onStreamComplete = function() {
9383
9494
  if (pprBypassReason === "refresh") {
9384
9495
  emitFarmEvent({
9385
9496
  type: "ppr.refresh.complete",
@@ -9394,8 +9505,41 @@ ${hasServerRuntimeIntegrations ? `
9394
9505
  status: pageStatus,
9395
9506
  durationMs: Date.now() - requestStartTime,
9396
9507
  });
9397
- }
9398
- );
9508
+ };
9509
+ const streamedDocument = hasFullDocument
9510
+ ? createFarmFullDocumentStream(
9511
+ renderedPage.stream,
9512
+ function(opening) {
9513
+ // Farm's wrappers and the head elements React hoisted ahead of the layout's <html>.
9514
+ const peeled = peelFarmDocumentPrefix(opening);
9515
+ const start = opening.search(/<!doctype|<html[\\s>]/i);
9516
+ return applyFarmThemeDocument(
9517
+ composeFarmFullDocument(
9518
+ restoreFarmHoistedHead(opening.slice(Math.max(start, 0)), peeled.hoisted)
9519
+ // The client entry arrives last: fetch it while the body streams.
9520
+ ).replace(/<\\/head>/i, function() {
9521
+ return ' <link rel="modulepreload" href="/__farm_client_js_src__">\\n</head>';
9522
+ }),
9523
+ farmThemeConfig,
9524
+ farmResolvedRuntimeConfig.basePath,
9525
+ getFarmTheme(request)
9526
+ );
9527
+ },
9528
+ async function(rootOpened) {
9529
+ return (await lateNavigationRecovery()) +
9530
+ (rootOpened ? '</div>\\n' : '') +
9531
+ farmClientScripts();
9532
+ },
9533
+ onStreamComplete
9534
+ )
9535
+ : createFarmDocumentStream(
9536
+ renderedPage.stream,
9537
+ themedStreamPrefix,
9538
+ async function() {
9539
+ return (await lateNavigationRecovery()) + streamSuffix;
9540
+ },
9541
+ onStreamComplete
9542
+ );
9399
9543
  return applyProductionMiddlewareHeaders(farmOwnedResponse(streamedDocument, {
9400
9544
  status: pageStatus,
9401
9545
  headers: { ...responseHeaders, "x-farm-preload-streaming": "1" },
@@ -9409,44 +9553,10 @@ ${hasServerRuntimeIntegrations ? `
9409
9553
  }
9410
9554
  }
9411
9555
 
9412
- const rendererHead = renderedPage.head || "";
9413
- const rendererHasTitle = /<title[\\s>]/i.test(rendererHead);
9414
- // First <title> wins: the fallback framework title yields to a
9415
- // renderer-emitted one; explicit metadata titles still come first.
9416
- const suppressDefaultTitle =
9417
- !renderedMetadata.hasExplicitTitle && rendererHasTitle;
9418
9556
  let fullHtml;
9419
9557
  if (hasFullDocument) {
9420
9558
  // Layout provides full HTML structure - inject CSS and client script
9421
- html = addFarmFallbackIcon(
9422
- ensureFarmDocumentRoot(ensureFarmDocumentHead(extractFarmFullDocument(html) || html)),
9423
- hasFavicon,
9424
- );
9425
- fullHtml = html
9426
- // Inject CSS link after opening head tag or first meta tag
9427
- .replace(/<head([^>]*)>/i, function(match, attrs) { return '<head' + attrs + '>\\n <link rel="stylesheet" href="/__farm_client_css_href__">' + renderFarmClientModulePreloads(html, route.clientModule); })
9428
- .replace(/<\\/head>/i, () => renderFarmRendererHydrationScript() + '\\n</head>')
9429
- // Explicit metadata wins over renderer and layout titles. Without
9430
- // explicit metadata, a renderer title wins over the layout title.
9431
- .replace(/<head([^>]*)>([\\s\\S]*?)<\\/head>/i, (match, attrs, headContent) => {
9432
- const hasAuthoritativeTitle = renderedMetadata.hasExplicitTitle || rendererHasTitle;
9433
- let nextHeadContent = hasAuthoritativeTitle
9434
- ? headContent.replace(/<title\\b[^>]*>[\\s\\S]*?<\\/title>\\s*/gi, "")
9435
- : headContent;
9436
- if (renderedMetadata.hasExplicitTitle) {
9437
- nextHeadContent += "\\n <title>" + title + "</title>";
9438
- }
9439
- if (metaTags) nextHeadContent += metaTags;
9440
- // Renderer-emitted head markup (e.g. <svelte:head>). Function
9441
- // replacement below keeps $-sequences literal.
9442
- const effectiveRendererHead = renderedMetadata.hasExplicitTitle
9443
- ? rendererHead.replace(/<title\\b[^>]*>[\\s\\S]*?<\\/title>\\s*/gi, "")
9444
- : rendererHead;
9445
- if (effectiveRendererHead) nextHeadContent += "\\n " + effectiveRendererHead;
9446
- return nextHeadContent === headContent
9447
- ? match
9448
- : "<head" + attrs + ">" + nextHeadContent + "\\n</head>";
9449
- })
9559
+ fullHtml = composeFarmFullDocument(extractFarmFullDocument(html) || html)
9450
9560
  // Inject client script before closing body tag. Function replacement:
9451
9561
  // serialized page props may contain $-sequences ($&, $', $$) that a
9452
9562
  // string replacement would expand into surrounding document markup,
@@ -9460,14 +9570,6 @@ ${hasServerRuntimeIntegrations ? `
9460
9570
  ) + '\\n' +
9461
9571
  ' ' + renderFarmClientEntryScript() + '\\n</body>',
9462
9572
  );
9463
-
9464
- // Last, so the charset (and the viewport, unless the layout wrote one) open the head.
9465
- fullHtml = ensureFarmDocumentMeta(fullHtml, viewportTags);
9466
-
9467
- // Add DOCTYPE if not present
9468
- if (!fullHtml.trim().startsWith('<!DOCTYPE')) {
9469
- fullHtml = '<!DOCTYPE html>\\n' + fullHtml;
9470
- }
9471
9573
  } else {
9472
9574
  // No layout with full document - wrap in HTML structure
9473
9575
  fullHtml = \`<!DOCTYPE html>
@@ -45,7 +45,7 @@ var _chunkKNBBQHO2cjs = require('./chunk-KNBBQHO2.cjs');
45
45
  var _chunk5NAVKJCZcjs = require('./chunk-5NAVKJCZ.cjs');
46
46
 
47
47
 
48
- var _chunk3YJMBQ27cjs = require('./chunk-3YJMBQ27.cjs');
48
+ var _chunkF6KWRHF5cjs = require('./chunk-F6KWRHF5.cjs');
49
49
 
50
50
 
51
51
  var _chunkBIDYX3SLcjs = require('./chunk-BIDYX3SL.cjs');
@@ -1051,7 +1051,7 @@ function createFarmAppManifest(input) {
1051
1051
  return {
1052
1052
  schemaVersion: 1,
1053
1053
  app: app ? {
1054
- ...app.version ? { farm: _chunk3YJMBQ27cjs.FARM_VERSION } : {},
1054
+ ...app.version ? { farm: _chunkF6KWRHF5cjs.FARM_VERSION } : {},
1055
1055
  ...app.renderer ? { renderer: input.renderer } : {},
1056
1056
  basePath: input.basePath,
1057
1057
  ...app.build ? { build: input.build } : {}