@farm.js/core 0.1.16 → 0.1.17

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 (180) hide show
  1. package/dist/agent-runtime.d.mts +3 -3
  2. package/dist/agent-runtime.d.ts +3 -3
  3. package/dist/api/client.cjs +62 -28
  4. package/dist/api/client.d.mts +3 -3
  5. package/dist/api/client.d.ts +3 -3
  6. package/dist/api/client.mjs +3 -3
  7. package/dist/api/route-manager.cjs +69 -32
  8. package/dist/api/route-manager.d.mts +3 -3
  9. package/dist/api/route-manager.d.ts +3 -3
  10. package/dist/api/route-manager.mjs +5 -5
  11. package/dist/api/runtime.cjs +65 -29
  12. package/dist/api/runtime.d.mts +3 -3
  13. package/dist/api/runtime.d.ts +3 -3
  14. package/dist/api/runtime.mjs +6 -3
  15. package/dist/{api-client-B-n3pm_Q.d.mts → api-client-Cx54IR5g.d.mts} +2 -2
  16. package/dist/{api-client-C0_NZEBl.d.ts → api-client-DykpaKcY.d.ts} +2 -2
  17. package/dist/api.cjs +106 -33
  18. package/dist/api.d.mts +5 -5
  19. package/dist/api.d.ts +5 -5
  20. package/dist/api.mjs +8 -8
  21. package/dist/{app-AyjEsCBq.d.ts → app-BHY_10Lm.d.ts} +3 -3
  22. package/dist/{app-CYPHeOo_.d.mts → app-BMk0do23.d.mts} +3 -3
  23. package/dist/app-markdown.d.mts +4 -4
  24. package/dist/app-markdown.d.ts +4 -4
  25. package/dist/app-markdown.mjs +3 -3
  26. package/dist/cache.cjs +62 -28
  27. package/dist/cache.d.mts +11 -1
  28. package/dist/cache.d.ts +11 -1
  29. package/dist/cache.mjs +1 -1
  30. package/dist/{chunk-7HDZYYS4.mjs → chunk-4OOBRCJX.mjs} +27 -5
  31. package/dist/{chunk-NHHKW2T6.mjs → chunk-56DAX2BE.mjs} +170 -52
  32. package/dist/{chunk-B76DT5Y6.mjs → chunk-57J3Y7Y3.mjs} +1 -1
  33. package/dist/{chunk-MOQNHLTS.mjs → chunk-5QOEPUYE.mjs} +5 -2
  34. package/dist/{chunk-HKLRP3BN.mjs → chunk-5SPPCN5J.mjs} +1 -1
  35. package/dist/{chunk-LUC2FAGW.mjs → chunk-6VQIKZZO.mjs} +1 -1
  36. package/dist/{chunk-7ZWL7XOU.mjs → chunk-76DG3LF3.mjs} +1 -1
  37. package/dist/{chunk-EWDK36MM.mjs → chunk-A72YEUZ3.mjs} +1 -1
  38. package/dist/{chunk-ZHOIQC6U.mjs → chunk-ATERBVHQ.mjs} +2 -2
  39. package/dist/{chunk-27JNCYEK.mjs → chunk-EN7WTEAY.mjs} +2 -2
  40. package/dist/{chunk-IGO2HEV7.mjs → chunk-F6SJAKFJ.mjs} +62 -28
  41. package/dist/{chunk-GSDIZACQ.mjs → chunk-FG5H2VCJ.mjs} +2 -2
  42. package/dist/{chunk-LZK5CXDW.mjs → chunk-KLSSO6YD.mjs} +2 -2
  43. package/dist/{chunk-KUO3GBPK.mjs → chunk-L6V3P73N.mjs} +1 -1
  44. package/dist/{chunk-TYVVIQ5M.mjs → chunk-MVIWBEJF.mjs} +32 -25
  45. package/dist/{chunk-KTGFMHET.mjs → chunk-N6UROPT7.mjs} +1 -1
  46. package/dist/{chunk-NDD2YVGU.mjs → chunk-NRVGEI5I.mjs} +10 -3
  47. package/dist/{chunk-IXTEENRS.mjs → chunk-QGVJVSNX.mjs} +5 -5
  48. package/dist/{chunk-6SCB2MXB.mjs → chunk-SXHV42UQ.mjs} +16 -1
  49. package/dist/{chunk-OWTIOHON.mjs → chunk-SYGGPS4A.mjs} +2 -2
  50. package/dist/{chunk-NC333MFA.mjs → chunk-TSWW5BVH.mjs} +7 -4
  51. package/dist/{chunk-LK6FGAQR.mjs → chunk-UDBJCUPA.mjs} +7 -4
  52. package/dist/{chunk-NUD6XBMO.mjs → chunk-UTBVHYS3.mjs} +2 -2
  53. package/dist/{chunk-76MNRHTS.mjs → chunk-UUYF3CHN.mjs} +2 -2
  54. package/dist/{chunk-VVTREAG5.mjs → chunk-WD4YXVLV.mjs} +11 -3
  55. package/dist/{chunk-UQZPTIML.mjs → chunk-WD5PNSOB.mjs} +2 -2
  56. package/dist/{chunk-DPZUDPVJ.mjs → chunk-XP777LRD.mjs} +1 -1
  57. package/dist/{chunk-KATQ6I56.mjs → chunk-XWAYMDLB.mjs} +1 -1
  58. package/dist/{chunk-IL5RWYK7.mjs → chunk-YD4J4XCI.mjs} +1 -1
  59. package/dist/{chunk-Q3MDL7TM.mjs → chunk-ZCNJKLA2.mjs} +30 -11
  60. package/dist/{client-plugins-CqVtZi5X.d.ts → client-plugins-C089bQhN.d.ts} +2 -2
  61. package/dist/{client-plugins-CIPRtSsW.d.mts → client-plugins-JXXmZliS.d.mts} +2 -2
  62. package/dist/client-plugins.d.mts +3 -3
  63. package/dist/client-plugins.d.ts +3 -3
  64. package/dist/client.cjs +62 -28
  65. package/dist/client.d.mts +8 -8
  66. package/dist/client.d.ts +8 -8
  67. package/dist/client.mjs +6 -6
  68. package/dist/config.d.mts +3 -3
  69. package/dist/config.d.ts +3 -3
  70. package/dist/cron.mjs +2 -2
  71. package/dist/{devtools-IU7LKZOH.mjs → devtools-UFVTMQX5.mjs} +7 -7
  72. package/dist/docs.cjs +18 -10
  73. package/dist/docs.mjs +9 -9
  74. package/dist/{endpoint-kSAxE52R.d.ts → endpoint-1zA994xL.d.ts} +1 -1
  75. package/dist/{endpoint-Bu3XgeMK.d.mts → endpoint-DAc96i93.d.mts} +1 -1
  76. package/dist/env.cjs +39 -5
  77. package/dist/env.d.mts +5 -3
  78. package/dist/env.d.ts +5 -3
  79. package/dist/env.mjs +2 -1
  80. package/dist/index.cjs +311 -93
  81. package/dist/index.d.mts +14 -14
  82. package/dist/index.d.ts +14 -14
  83. package/dist/index.mjs +34 -34
  84. package/dist/integrations.d.mts +3 -3
  85. package/dist/integrations.d.ts +3 -3
  86. package/dist/internal/app-markdown-runtime.d.mts +3 -3
  87. package/dist/internal/app-markdown-runtime.d.ts +3 -3
  88. package/dist/internal/app-markdown-runtime.mjs +2 -2
  89. package/dist/internal/build-runtime.cjs +342 -121
  90. package/dist/internal/build-runtime.d.mts +5 -5
  91. package/dist/internal/build-runtime.d.ts +5 -5
  92. package/dist/internal/build-runtime.mjs +23 -23
  93. package/dist/internal/cli-runtime.cjs +77 -31
  94. package/dist/internal/cli-runtime.mjs +13 -13
  95. package/dist/internal/client-error-overlay.cjs +1 -1
  96. package/dist/internal/client-error-overlay.mjs +1 -1
  97. package/dist/internal/compression-runtime.d.mts +3 -3
  98. package/dist/internal/compression-runtime.d.ts +3 -3
  99. package/dist/internal/config-runtime.cjs +14 -2
  100. package/dist/internal/config-runtime.d.mts +4 -4
  101. package/dist/internal/config-runtime.d.ts +4 -4
  102. package/dist/internal/config-runtime.mjs +7 -7
  103. package/dist/internal/product-telemetry-runtime.cjs +1 -1
  104. package/dist/internal/product-telemetry-runtime.mjs +1 -1
  105. package/dist/internal/production-runtime.cjs +101 -41
  106. package/dist/internal/production-runtime.d.mts +9 -9
  107. package/dist/internal/production-runtime.d.ts +9 -9
  108. package/dist/internal/production-runtime.mjs +6 -6
  109. package/dist/markdown.cjs +16 -1
  110. package/dist/markdown.mjs +1 -1
  111. package/dist/{metadata-8g__AMPM.d.ts → metadata-BcNJP4fq.d.ts} +1 -1
  112. package/dist/{metadata-OMX6wFNf.d.mts → metadata-C1Z9vLbb.d.mts} +1 -1
  113. package/dist/middleware.cjs +10 -3
  114. package/dist/middleware.d.mts +5 -5
  115. package/dist/middleware.d.ts +5 -5
  116. package/dist/middleware.mjs +4 -4
  117. package/dist/{nitro-3N4ZXRYM.mjs → nitro-CVZ36JM5.mjs} +4 -4
  118. package/dist/plugin.cjs +256 -105
  119. package/dist/plugin.d.mts +3 -3
  120. package/dist/plugin.d.ts +3 -3
  121. package/dist/plugin.mjs +19 -19
  122. package/dist/{production-runtime-W3M0eNDV.d.mts → production-runtime-jcrTlRTb.d.mts} +1 -1
  123. package/dist/{production-runtime-BJh7o6Cr.d.ts → production-runtime-oKmC0WU-.d.ts} +1 -1
  124. package/dist/{render-plan-io7pvDNc.d.mts → render-plan-BLIfc4jt.d.mts} +1 -1
  125. package/dist/{render-plan-Be4ZGTJP.d.ts → render-plan-DOB9cV-h.d.ts} +1 -1
  126. package/dist/renderer-client.cjs +62 -28
  127. package/dist/renderer-client.d.mts +5 -5
  128. package/dist/renderer-client.d.ts +5 -5
  129. package/dist/renderer-client.mjs +3 -3
  130. package/dist/{request-DZkHYQ89.d.mts → request-Cr53NRHr.d.mts} +1 -1
  131. package/dist/{request-G8JhKr4F.d.ts → request-Dt2gNuQD.d.ts} +1 -1
  132. package/dist/request.d.mts +4 -4
  133. package/dist/request.d.ts +4 -4
  134. package/dist/{route-C_eLaFTZ.d.mts → route-B0XrsrFk.d.mts} +1 -1
  135. package/dist/{route-BxNJT447.d.ts → route-DOEpbyWZ.d.ts} +1 -1
  136. package/dist/{route-rendering-BcLLPJgN.d.ts → route-rendering-CWYd8Mv1.d.ts} +1 -1
  137. package/dist/{route-rendering-CbAKr1TY.d.mts → route-rendering-CeFBEAoZ.d.mts} +1 -1
  138. package/dist/routes.cjs +68 -31
  139. package/dist/routes.d.mts +4 -4
  140. package/dist/routes.d.ts +4 -4
  141. package/dist/routes.mjs +2 -2
  142. package/dist/server-fn-client.d.mts +3 -3
  143. package/dist/server-fn-client.d.ts +3 -3
  144. package/dist/server-fn.cjs +72 -30
  145. package/dist/server-fn.d.mts +1 -1
  146. package/dist/server-fn.d.ts +1 -1
  147. package/dist/server-fn.mjs +2 -2
  148. package/dist/server-plugins.d.mts +4 -4
  149. package/dist/server-plugins.d.ts +4 -4
  150. package/dist/server-query-client.cjs +62 -28
  151. package/dist/server-query-client.d.mts +1 -1
  152. package/dist/server-query-client.d.ts +1 -1
  153. package/dist/server-query-client.mjs +4 -4
  154. package/dist/server-query.cjs +72 -30
  155. package/dist/server-query.d.mts +1 -1
  156. package/dist/server-query.d.ts +1 -1
  157. package/dist/server-query.mjs +3 -3
  158. package/dist/server.cjs +239 -80
  159. package/dist/server.d.mts +9 -9
  160. package/dist/server.d.ts +9 -9
  161. package/dist/server.mjs +22 -22
  162. package/dist/{spa-router-BcS_4nqm.d.mts → spa-router-CQWiYGxS.d.mts} +2 -2
  163. package/dist/{spa-router-BzFBUJkn.d.ts → spa-router-Wjiw-8hB.d.ts} +2 -2
  164. package/dist/testing.cjs +73 -32
  165. package/dist/testing.d.mts +3 -3
  166. package/dist/testing.d.ts +3 -3
  167. package/dist/testing.mjs +11 -7
  168. package/dist/{utils-C4yrAhNc.d.ts → utils-B0XJmG_b.d.ts} +1 -1
  169. package/dist/{utils-5kQP1mFR.d.mts → utils-uUxF0K0P.d.mts} +1 -1
  170. package/dist/version.cjs +1 -1
  171. package/dist/version.mjs +1 -1
  172. package/dist/vite.cjs +260 -109
  173. package/dist/vite.d.mts +3 -3
  174. package/dist/vite.d.ts +3 -3
  175. package/dist/vite.mjs +19 -19
  176. package/dist/workflows.mjs +2 -2
  177. package/package.json +2 -2
  178. package/dist/{chunk-VO5SCWF5.mjs → chunk-BNGS6KJ6.mjs} +0 -0
  179. package/dist/{chunk-MUUZJLCI.mjs → chunk-EGJDUF4Q.mjs} +3 -3
  180. package/dist/{chunk-4L7SZOHZ.mjs → chunk-YHOCRI4H.mjs} +3 -3
package/dist/plugin.cjs CHANGED
@@ -31,16 +31,41 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
31
31
  ));
32
32
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
33
33
 
34
+ // src/utils/runtime-env.ts
35
+ function getFarmRuntimeBindings() {
36
+ const runtimeBindings = globalThis.__env__;
37
+ return runtimeBindings && typeof runtimeBindings === "object" ? runtimeBindings : void 0;
38
+ }
39
+ function readFarmEnvironmentValue(name2) {
40
+ const runtimeValue = getFarmRuntimeBindings()?.[name2];
41
+ if (typeof runtimeValue === "string") return runtimeValue;
42
+ return typeof process !== "undefined" ? process.env?.[name2] : void 0;
43
+ }
44
+ function isFarmDeployedRuntime() {
45
+ if (getFarmRuntimeBindings()) return true;
46
+ return readFarmEnvironmentValue("NODE_ENV") === "production";
47
+ }
48
+ var init_runtime_env = __esm({
49
+ "src/utils/runtime-env.ts"() {
50
+ "use strict";
51
+ __name(getFarmRuntimeBindings, "getFarmRuntimeBindings");
52
+ __name(readFarmEnvironmentValue, "readFarmEnvironmentValue");
53
+ __name(isFarmDeployedRuntime, "isFarmDeployedRuntime");
54
+ }
55
+ });
56
+
34
57
  // src/env.ts
35
58
  function createBundledEnv(env2, source = getProcessEnv()) {
36
59
  const resolved = normalizeResolvedEnv(env2 ?? {});
37
60
  const server = {};
38
61
  const runtime3 = {};
39
62
  for (const [key, value] of Object.entries(resolved.server)) {
40
- if (source[key] === void 0) {
41
- server[key] = value;
63
+ const raw = source[key];
64
+ const type = getRuntimeEnvType(value);
65
+ if (raw !== void 0 && isSameEnvValue(coerceRuntimeEnvValue(raw, type), value)) {
66
+ runtime3[key] = type;
42
67
  } else {
43
- runtime3[key] = getRuntimeEnvType(value);
68
+ server[key] = value;
44
69
  }
45
70
  }
46
71
  return {
@@ -109,9 +134,8 @@ function readServerEnvKey(server, key) {
109
134
  function readRuntimeServerEnv(env2) {
110
135
  const state = env2[FARM_ENV_RUNTIME_SYMBOL];
111
136
  if (!state) return;
112
- const source = getProcessEnv();
113
137
  for (const [key, type] of Object.entries(state.pending)) {
114
- const raw = source[key];
138
+ const raw = readFarmEnvironmentValue(key);
115
139
  if (raw === void 0) continue;
116
140
  env2.server[key] = coerceRuntimeEnvValue(raw, type);
117
141
  delete state.pending[key];
@@ -142,6 +166,22 @@ function coerceRuntimeEnvValue(raw, type) {
142
166
  }
143
167
  return raw;
144
168
  }
169
+ function isSameEnvValue(left, right) {
170
+ if (Object.is(left, right)) return true;
171
+ if (Array.isArray(left) || Array.isArray(right)) {
172
+ return Array.isArray(left) && Array.isArray(right) && left.length === right.length && left.every((item, index) => isSameEnvValue(item, right[index]));
173
+ }
174
+ if (!isPlainObject(left) || !isPlainObject(right)) return false;
175
+ const keys = Object.keys(left);
176
+ return keys.length === Object.keys(right).length && keys.every(
177
+ (key) => Object.prototype.hasOwnProperty.call(right, key) && isSameEnvValue(left[key], right[key])
178
+ );
179
+ }
180
+ function isPlainObject(value) {
181
+ if (!value || typeof value !== "object") return false;
182
+ const prototype = Object.getPrototypeOf(value);
183
+ return prototype === Object.prototype || prototype === null;
184
+ }
145
185
  function prepareEnv(env2) {
146
186
  const normalized = normalizeResolvedEnv(env2);
147
187
  const runtime3 = env2.runtime?.server;
@@ -217,6 +257,7 @@ var FARM_ENV_SYMBOL, FARM_ENV_RUNTIME_SYMBOL, farmEnvGlobal, currentEnv, env, pu
217
257
  var init_env = __esm({
218
258
  "src/env.ts"() {
219
259
  "use strict";
260
+ init_runtime_env();
220
261
  FARM_ENV_SYMBOL = /* @__PURE__ */ Symbol.for("farm.env");
221
262
  FARM_ENV_RUNTIME_SYMBOL = /* @__PURE__ */ Symbol.for("farm.env.runtime");
222
263
  farmEnvGlobal = globalThis;
@@ -231,6 +272,8 @@ var init_env = __esm({
231
272
  __name(readRuntimeServerEnv, "readRuntimeServerEnv");
232
273
  __name(getRuntimeEnvType, "getRuntimeEnvType");
233
274
  __name(coerceRuntimeEnvValue, "coerceRuntimeEnvValue");
275
+ __name(isSameEnvValue, "isSameEnvValue");
276
+ __name(isPlainObject, "isPlainObject");
234
277
  __name(prepareEnv, "prepareEnv");
235
278
  __name(assertServerEnvAccess, "assertServerEnvAccess");
236
279
  __name(getInitialEnv, "getInitialEnv");
@@ -711,8 +754,16 @@ async function createMarkdownMirrorResponse(options) {
711
754
  if (!hasMarkdownExtension) {
712
755
  headersOut.set("Vary", "Accept");
713
756
  }
757
+ for (const token of pageResponse.headers.get("vary")?.split(",") ?? []) {
758
+ const name2 = token.trim();
759
+ if (name2 && name2.toLowerCase() !== "accept") appendHeaderToken(headersOut, "Vary", name2);
760
+ }
761
+ const pageCacheControl = pageResponse.headers.get("cache-control");
714
762
  const cache = target.route?.cache ?? options.config?.cache ?? false;
715
- headersOut.set("Cache-Control", createMarkdownCacheHeader(cache));
763
+ headersOut.set(
764
+ "Cache-Control",
765
+ pageCacheControl && isPrivateCacheControl(pageCacheControl) ? pageCacheControl : createMarkdownCacheHeader(cache)
766
+ );
716
767
  return new Response(options.request.method === "HEAD" ? null : markdown, {
717
768
  status: pageResponse.status,
718
769
  headers: headersOut
@@ -863,6 +914,17 @@ function isFarmMarkdownMirrorExposed(config, pathname) {
863
914
  function matchesFarmMarkdownRoutePattern(pattern, pathname) {
864
915
  return routeMatches(pattern, pathname);
865
916
  }
917
+ function appendHeaderToken(headers, name2, token) {
918
+ const current = headers.get(name2);
919
+ if (!current) {
920
+ headers.set(name2, token);
921
+ return;
922
+ }
923
+ const tokens = current.split(",").map((value) => value.trim().toLowerCase());
924
+ if (!tokens.includes(token.toLowerCase())) {
925
+ headers.set(name2, `${current}, ${token}`);
926
+ }
927
+ }
866
928
  function findExposedMarkdownRoute(config, pathname) {
867
929
  if (config.expose === true) {
868
930
  return null;
@@ -894,6 +956,12 @@ function isHtmlResponse(response) {
894
956
  const contentType = response.headers.get("content-type") ?? "";
895
957
  return contentType.includes("text/html");
896
958
  }
959
+ function isPrivateCacheControl(value) {
960
+ return value.split(",").some((directive) => {
961
+ const name2 = directive.split("=", 1)[0].trim().toLowerCase();
962
+ return name2 === "private" || name2 === "no-store";
963
+ });
964
+ }
897
965
  function createMarkdownCacheHeader(cache) {
898
966
  if (cache === false || cache <= 0) {
899
967
  return "no-store";
@@ -1046,9 +1114,11 @@ var init_markdown = __esm({
1046
1114
  __name(getFarmMarkdownAlternatePath, "getFarmMarkdownAlternatePath");
1047
1115
  __name(isFarmMarkdownMirrorExposed, "isFarmMarkdownMirrorExposed");
1048
1116
  __name(matchesFarmMarkdownRoutePattern, "matchesFarmMarkdownRoutePattern");
1117
+ __name(appendHeaderToken, "appendHeaderToken");
1049
1118
  __name(findExposedMarkdownRoute, "findExposedMarkdownRoute");
1050
1119
  __name(routeMatches, "routeMatches");
1051
1120
  __name(isHtmlResponse, "isHtmlResponse");
1121
+ __name(isPrivateCacheControl, "isPrivateCacheControl");
1052
1122
  __name(createMarkdownCacheHeader, "createMarkdownCacheHeader");
1053
1123
  __name(extractHtmlTitle, "extractHtmlTitle");
1054
1124
  __name(extractHtmlBody, "extractHtmlBody");
@@ -1667,29 +1737,6 @@ var init_secret_compare = __esm({
1667
1737
  }
1668
1738
  });
1669
1739
 
1670
- // src/utils/runtime-env.ts
1671
- function getFarmRuntimeBindings() {
1672
- const runtimeBindings = globalThis.__env__;
1673
- return runtimeBindings && typeof runtimeBindings === "object" ? runtimeBindings : void 0;
1674
- }
1675
- function readFarmEnvironmentValue(name2) {
1676
- const runtimeValue = getFarmRuntimeBindings()?.[name2];
1677
- if (typeof runtimeValue === "string") return runtimeValue;
1678
- return typeof process !== "undefined" ? process.env?.[name2] : void 0;
1679
- }
1680
- function isFarmDeployedRuntime() {
1681
- if (getFarmRuntimeBindings()) return true;
1682
- return readFarmEnvironmentValue("NODE_ENV") === "production";
1683
- }
1684
- var init_runtime_env = __esm({
1685
- "src/utils/runtime-env.ts"() {
1686
- "use strict";
1687
- __name(getFarmRuntimeBindings, "getFarmRuntimeBindings");
1688
- __name(readFarmEnvironmentValue, "readFarmEnvironmentValue");
1689
- __name(isFarmDeployedRuntime, "isFarmDeployedRuntime");
1690
- }
1691
- });
1692
-
1693
1740
  // src/utils/decode.ts
1694
1741
  function decodeRouteSegment(segment) {
1695
1742
  try {
@@ -5321,6 +5368,8 @@ var init_cache = __esm({
5321
5368
  constructor(config = {}) {
5322
5369
  this.entries = /* @__PURE__ */ new Map();
5323
5370
  this.inflight = /* @__PURE__ */ new Map();
5371
+ /** Local entries by tag, so tag counts and pruning never scan unrelated entries. */
5372
+ this.entriesByTag = /* @__PURE__ */ new Map();
5324
5373
  this.invalidatedTagVersions = /* @__PURE__ */ new Map();
5325
5374
  this.activeGenerations = /* @__PURE__ */ new Set();
5326
5375
  this.version = 0;
@@ -5339,6 +5388,7 @@ var init_cache = __esm({
5339
5388
  configure(config = {}) {
5340
5389
  this.generation++;
5341
5390
  this.entries.clear();
5391
+ this.entriesByTag.clear();
5342
5392
  this.inflight.clear();
5343
5393
  this.invalidatedTagVersions.clear();
5344
5394
  this.activeGenerations.clear();
@@ -5505,14 +5555,12 @@ var init_cache = __esm({
5505
5555
  return entry;
5506
5556
  }
5507
5557
  delete(key) {
5508
- const deleted = this.entries.delete(key);
5509
- if (deleted) this.pruneInvalidatedTagVersions();
5558
+ const deleted = this.deleteLocalEntry(key);
5510
5559
  emitFarmEvent({ type: "cache.delete", key, deleted });
5511
5560
  return deleted;
5512
5561
  }
5513
5562
  async deleteAsync(key) {
5514
- const deleted = this.entries.delete(key);
5515
- if (deleted) this.pruneInvalidatedTagVersions();
5563
+ const deleted = this.deleteLocalEntry(key);
5516
5564
  if (this.adapter) {
5517
5565
  await this.adapter.delete(this.createAdapterKey(key));
5518
5566
  }
@@ -5523,6 +5571,7 @@ var init_cache = __esm({
5523
5571
  const count = this.entries.size;
5524
5572
  this.generation++;
5525
5573
  this.entries.clear();
5574
+ this.entriesByTag.clear();
5526
5575
  this.inflight.clear();
5527
5576
  this.invalidatedTagVersions.clear();
5528
5577
  this.activeGenerations.clear();
@@ -5608,23 +5657,32 @@ var init_cache = __esm({
5608
5657
  return cached.value;
5609
5658
  }
5610
5659
  const inflight = this.inflight.get(key);
5611
- if (inflight) {
5660
+ if (inflight && !this.wasInvalidatedSince(inflight.tags, inflight.startVersion)) {
5612
5661
  emitFarmEvent({ type: "cache.dedupe", key });
5613
- return inflight;
5662
+ return inflight.promise;
5614
5663
  }
5615
5664
  const tags = Array.from(normalizeCacheOptionsTags(options));
5616
5665
  const generation = this.generation;
5666
+ const startVersion = this.version;
5617
5667
  const promise = this.fillCacheEntry(key, producer, options, tags, generation).catch((error) => {
5618
5668
  emitFarmEvent({ type: "cache.error", key, operation: "set", error });
5619
5669
  throw error;
5620
5670
  }).finally(() => {
5621
- if (this.inflight.get(key) === promise) {
5671
+ if (this.inflight.get(key)?.promise === promise) {
5622
5672
  this.inflight.delete(key);
5623
5673
  }
5624
5674
  });
5625
- this.inflight.set(key, promise);
5675
+ this.inflight.set(key, { promise, tags, startVersion });
5626
5676
  return promise;
5627
5677
  }
5678
+ /** A fill that started before one of its tags was invalidated cannot satisfy later readers. */
5679
+ wasInvalidatedSince(tags, version2) {
5680
+ for (const tag of tags) {
5681
+ const invalidatedVersion = this.invalidatedTagVersions.get(tag);
5682
+ if (invalidatedVersion !== void 0 && invalidatedVersion > version2) return true;
5683
+ }
5684
+ return false;
5685
+ }
5628
5686
  async fillCacheEntry(key, producer, options, tags, generation) {
5629
5687
  const adapter = this.adapter;
5630
5688
  const namespace = this.namespace;
@@ -5665,7 +5723,7 @@ var init_cache = __esm({
5665
5723
  return value;
5666
5724
  } finally {
5667
5725
  this.activeGenerations.delete(activeGeneration);
5668
- this.pruneInvalidatedTagVersions();
5726
+ this.pruneInvalidatedTagVersions(activeGeneration.tags);
5669
5727
  if (leaseToken && adapter?.releaseLease) {
5670
5728
  try {
5671
5729
  await adapter.releaseLease(leaseKey, leaseToken);
@@ -5710,18 +5768,9 @@ var init_cache = __esm({
5710
5768
  }
5711
5769
  return void 0;
5712
5770
  }
5713
- countEntriesForTag(tag) {
5714
- let count = 0;
5715
- for (const entry of this.entries.values()) {
5716
- if (entry.tags.has(tag)) {
5717
- count++;
5718
- }
5719
- }
5720
- return count;
5721
- }
5722
5771
  countEntriesForTags(tags) {
5723
5772
  let count = 0;
5724
- for (const entry of this.entries.values()) {
5773
+ for (const entry of this.entriesByTag.get(tags[0]) ?? []) {
5725
5774
  if (tags.every((tag) => entry.tags.has(tag))) {
5726
5775
  count++;
5727
5776
  }
@@ -5729,10 +5778,10 @@ var init_cache = __esm({
5729
5778
  return count;
5730
5779
  }
5731
5780
  invalidateTag(normalizedTag) {
5732
- const count = this.countEntriesForTag(normalizedTag);
5781
+ const count = this.entriesByTag.get(normalizedTag)?.size ?? 0;
5733
5782
  this.invalidatedTagVersions.delete(normalizedTag);
5734
5783
  this.invalidatedTagVersions.set(normalizedTag, ++this.version);
5735
- this.pruneInvalidatedTagVersions();
5784
+ this.pruneInvalidatedTagVersions([normalizedTag]);
5736
5785
  return count;
5737
5786
  }
5738
5787
  toPublicEntry(entry) {
@@ -5762,19 +5811,51 @@ var init_cache = __esm({
5762
5811
  this.entries.set(key, entry);
5763
5812
  }
5764
5813
  storeLocalEntry(entry) {
5765
- this.entries.delete(entry.key);
5814
+ const removed = [];
5815
+ const replaced = this.detachLocalEntry(entry.key);
5816
+ if (replaced) removed.push(replaced);
5766
5817
  this.entries.set(entry.key, entry);
5818
+ for (const tag of entry.tags) {
5819
+ let tagged = this.entriesByTag.get(tag);
5820
+ if (!tagged) this.entriesByTag.set(tag, tagged = /* @__PURE__ */ new Set());
5821
+ tagged.add(entry);
5822
+ }
5767
5823
  while (this.entries.size > this.maxEntries) {
5768
5824
  const oldestKey = this.entries.keys().next().value;
5769
5825
  if (oldestKey === void 0) break;
5770
- this.entries.delete(oldestKey);
5826
+ removed.push(this.detachLocalEntry(oldestKey));
5771
5827
  }
5772
- this.pruneInvalidatedTagVersions();
5828
+ for (const removedEntry of removed) this.pruneInvalidatedTagVersions(removedEntry.tags);
5773
5829
  }
5774
- pruneInvalidatedTagVersions() {
5775
- tags: for (const [tag, invalidatedVersion] of this.invalidatedTagVersions) {
5776
- for (const entry of this.entries.values()) {
5777
- if (entry.tags.has(tag) && entry.createdVersion < invalidatedVersion) continue tags;
5830
+ deleteLocalEntry(key) {
5831
+ const entry = this.detachLocalEntry(key);
5832
+ if (!entry) return false;
5833
+ this.pruneInvalidatedTagVersions(entry.tags);
5834
+ return true;
5835
+ }
5836
+ detachLocalEntry(key) {
5837
+ const entry = this.entries.get(key);
5838
+ if (!entry) return void 0;
5839
+ this.entries.delete(key);
5840
+ for (const tag of entry.tags) {
5841
+ const tagged = this.entriesByTag.get(tag);
5842
+ if (!tagged) continue;
5843
+ tagged.delete(entry);
5844
+ if (tagged.size === 0) this.entriesByTag.delete(tag);
5845
+ }
5846
+ return entry;
5847
+ }
5848
+ /**
5849
+ * Drop invalidation versions that no local entry or active fill can be stale against.
5850
+ * Callers pass only the tags whose dependents just changed, so the cost is bounded by
5851
+ * the entries sharing those tags rather than by the whole cache.
5852
+ */
5853
+ pruneInvalidatedTagVersions(tags) {
5854
+ tags: for (const tag of tags) {
5855
+ const invalidatedVersion = this.invalidatedTagVersions.get(tag);
5856
+ if (invalidatedVersion === void 0) continue;
5857
+ for (const entry of this.entriesByTag.get(tag) ?? []) {
5858
+ if (entry.createdVersion < invalidatedVersion) continue tags;
5778
5859
  }
5779
5860
  for (const generation of this.activeGenerations) {
5780
5861
  if (generation.tags.has(tag) && generation.createdVersion < invalidatedVersion)
@@ -6169,6 +6250,7 @@ function createProgrammaticPageComponent(route, rendererRuntime) {
6169
6250
  }
6170
6251
  return rendererRuntime.createElement(...args);
6171
6252
  }, "createElement");
6253
+ const markFunctionComponent = /* @__PURE__ */ __name((component) => rendererRuntime?.markFunctionComponent?.(component) ?? component, "markFunctionComponent");
6172
6254
  const Component = route.component;
6173
6255
  if (route.pending) {
6174
6256
  const PendingComponent = route.pending;
@@ -6190,7 +6272,9 @@ function createProgrammaticPageComponent(route, rendererRuntime) {
6190
6272
  throw error;
6191
6273
  }
6192
6274
  }, "FarmProgrammaticPageContent");
6193
- const PageContent = FarmProgrammaticPageContent2;
6275
+ const PageContent = markFunctionComponent(
6276
+ FarmProgrammaticPageContent2
6277
+ );
6194
6278
  const FarmProgrammaticPage = /* @__PURE__ */ __name(function FarmProgrammaticPage2(props) {
6195
6279
  return createElement2(
6196
6280
  rendererRuntime.Suspense,
@@ -6200,7 +6284,7 @@ function createProgrammaticPageComponent(route, rendererRuntime) {
6200
6284
  createElement2(PageContent, props)
6201
6285
  );
6202
6286
  }, "FarmProgrammaticPage");
6203
- return FarmProgrammaticPage;
6287
+ return markFunctionComponent(FarmProgrammaticPage);
6204
6288
  }
6205
6289
  const FarmProgrammaticPageContent = /* @__PURE__ */ __name(async function FarmProgrammaticPageContent2(props) {
6206
6290
  try {
@@ -6219,7 +6303,7 @@ function createProgrammaticPageComponent(route, rendererRuntime) {
6219
6303
  throw error;
6220
6304
  }
6221
6305
  }, "FarmProgrammaticPageContent");
6222
- return FarmProgrammaticPageContent;
6306
+ return markFunctionComponent(FarmProgrammaticPageContent);
6223
6307
  }
6224
6308
  function readProgrammaticRouteProps(route, props, resources) {
6225
6309
  if (isProgrammaticRoutePropsResolved(props)) {
@@ -13122,6 +13206,7 @@ function createFarmDocsHandler(docs, options) {
13122
13206
  if (!isFarmDocsRequest(docs, request2)) return null;
13123
13207
  const page2 = loadPage(contentDir, docs, request2);
13124
13208
  if (!page2) return null;
13209
+ const negotiatesAccept = !requestUrl.pathname.endsWith(".md");
13125
13210
  if (shouldReturnMarkdown(request2)) {
13126
13211
  const origin = new URL(request2.url).origin;
13127
13212
  return omitFarmDocsHeadBody(
@@ -13136,7 +13221,8 @@ function createFarmDocsHandler(docs, options) {
13136
13221
  status: 200,
13137
13222
  headers: {
13138
13223
  "Content-Type": "text/markdown; charset=utf-8",
13139
- "Cache-Control": "public, max-age=60"
13224
+ "Cache-Control": "public, max-age=60",
13225
+ ...negotiatesAccept ? { Vary: "Accept" } : {}
13140
13226
  }
13141
13227
  }
13142
13228
  )
@@ -13166,6 +13252,7 @@ function createFarmDocsHandler(docs, options) {
13166
13252
  headers: {
13167
13253
  "Content-Type": "text/html; charset=utf-8",
13168
13254
  "Cache-Control": "public, s-maxage=60, stale-while-revalidate=300",
13255
+ Vary: "Accept",
13169
13256
  ...fontPreloadHeader ? { Link: fontPreloadHeader } : {}
13170
13257
  }
13171
13258
  }
@@ -19363,7 +19450,7 @@ function resolveImportedModule(importerPath, specifier, root) {
19363
19450
  return { path: resolveImportedModuleSourcePath(importerPath, specifier, root), local: true };
19364
19451
  }
19365
19452
  const aliased = resolveProjectAliasSourcePath(specifier, root);
19366
- if (aliased !== void 0) return { path: aliased, local: true };
19453
+ if (aliased) return { path: aliased, local: true };
19367
19454
  return { path: resolvePackageModuleSourcePath(importerPath, specifier, root), local: false };
19368
19455
  }
19369
19456
  __name(resolveImportedModule, "resolveImportedModule");
@@ -19379,11 +19466,12 @@ function resolveProjectAliasSourcePath(specifier, root) {
19379
19466
  if (!match || alias.prefix.length > match.alias.prefix.length) match = { alias, captured };
19380
19467
  }
19381
19468
  if (!match) return void 0;
19382
- return resolveSourceCandidate(
19469
+ const resolved = resolveSourceCandidate(
19383
19470
  match.alias.targets.map(
19384
19471
  (target) => import_path4.default.normalize(match.alias.wildcard ? target.replace("*", match.captured) : target)
19385
19472
  )
19386
19473
  );
19474
+ return resolved && /\.d\.[cm]?ts$/.test(resolved) ? null : resolved;
19387
19475
  }
19388
19476
  __name(resolveProjectAliasSourcePath, "resolveProjectAliasSourcePath");
19389
19477
  function matchProjectImportAlias(alias, specifier) {
@@ -19790,6 +19878,7 @@ __name(readAltText, "readAltText");
19790
19878
  // src/routing/route-manager.ts
19791
19879
  init_route_runtime();
19792
19880
  init_routing();
19881
+ init_base_path();
19793
19882
 
19794
19883
  // src/redirect-query.ts
19795
19884
  function appendFarmRedirectQuery(destination, search) {
@@ -20866,7 +20955,7 @@ var _RouteManager = class _RouteManager {
20866
20955
  }
20867
20956
  toRoutePathname(pathname) {
20868
20957
  const i18n = this.getI18nConfig();
20869
- return i18n ? stripFarmLocaleFromPathname(pathname, i18n) : pathname;
20958
+ return i18n ? stripFarmLocaleFromPathname(pathname, i18n) : stripFarmBasePath(pathname, this.config.basePath);
20870
20959
  }
20871
20960
  localizeRedirectDestination(destination, locale) {
20872
20961
  if (!locale || !destination.startsWith("/") || destination.startsWith("//")) {
@@ -22055,7 +22144,7 @@ async function readFarmI18nCatalogs(config) {
22055
22144
  }
22056
22145
  __name(readFarmI18nCatalogs, "readFarmI18nCatalogs");
22057
22146
  function flattenFarmI18nCatalog(input, source = "i18n catalog") {
22058
- if (!isPlainObject(input)) {
22147
+ if (!isPlainObject2(input)) {
22059
22148
  throw new Error(`${source} must contain a JSON object at its root.`);
22060
22149
  }
22061
22150
  const output = {};
@@ -22069,7 +22158,7 @@ function flattenFarmI18nCatalog(input, source = "i18n catalog") {
22069
22158
  output[key] = value;
22070
22159
  return;
22071
22160
  }
22072
- if (!isPlainObject(value)) {
22161
+ if (!isPlainObject2(value)) {
22073
22162
  const key = segments.join(".") || "<root>";
22074
22163
  throw new Error(`${source} message "${key}" must be a string or nested object.`);
22075
22164
  }
@@ -22169,10 +22258,10 @@ function sameSignature(expected, actual) {
22169
22258
  return JSON.stringify(expectedEntries) === JSON.stringify(actualEntries);
22170
22259
  }
22171
22260
  __name(sameSignature, "sameSignature");
22172
- function isPlainObject(value) {
22261
+ function isPlainObject2(value) {
22173
22262
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
22174
22263
  }
22175
- __name(isPlainObject, "isPlainObject");
22264
+ __name(isPlainObject2, "isPlainObject");
22176
22265
  function messageOf(error) {
22177
22266
  return error instanceof Error ? error.message : String(error);
22178
22267
  }
@@ -24975,7 +25064,7 @@ _setFarmThemeServerSnapshotResolver(() => {
24975
25064
  });
24976
25065
 
24977
25066
  // package.json
24978
- var version = "0.1.16";
25067
+ var version = "0.1.17";
24979
25068
 
24980
25069
  // src/version.ts
24981
25070
  var FARM_VERSION = version;
@@ -25265,7 +25354,7 @@ function createPPRRefreshScript() {
25265
25354
  __name(createPPRRefreshScript, "createPPRRefreshScript");
25266
25355
  function createPreHydrationClickQueueScript() {
25267
25356
  const selector = JSON.stringify(FARM_ISLAND_REPLAYABLE_SELECTOR);
25268
- return `<script>(function(){if(window.__FARM_PREHYDRATION_CLICK_QUEUE__)return;var queue=[];window.__FARM_PREHYDRATION_CLICK_QUEUE__=queue;window.__FARM_HYDRATED__=false;document.documentElement.dataset.farmHydrated="false";function isModified(event){return !!(event.metaKey||event.altKey||event.ctrlKey||event.shiftKey)}function inHydrated(node){return !!(node&&node.closest&&node.closest('[data-farm-island-hydrated="true"]'))}function closestQueuedTarget(target){while(target&&target!==document.documentElement){if(target.matches&&target.matches(${selector}))return target;target=target.parentElement}return null}function announce(target,kind){document.dispatchEvent(new CustomEvent("farm:island-interaction",{detail:{target:target,kind:kind||null}}))}function hold(event,target,kind){if(queue.some(function(item){return item.target===target}))return;queue.push({target:target,kind:kind,createdAt:Date.now()});announce(target,kind);event.preventDefault();event.stopImmediatePropagation()}document.addEventListener("click",function(event){if(window.__FARM_HYDRATED__)return;if(event.defaultPrevented||event.button!==0||isModified(event))return;var target=closestQueuedTarget(event.target);if(!target||target.closest&&target.closest("a[href]")||inHydrated(target))return;hold(event,target,"click")},true);document.addEventListener("submit",function(event){if(window.__FARM_HYDRATED__)return;if(event.defaultPrevented)return;var form=event.target;if(!form||form.nodeName!=="FORM"||inHydrated(form))return;hold(event,form,"submit")},true);function observe(event){if(window.__FARM_HYDRATED__)return;var target=event.target;if(!(target&&target.closest)||inHydrated(target))return;announce(target,null)}document.addEventListener("pointerdown",observe,true);document.addEventListener("focusin",observe,true);})();</script>`;
25357
+ return `<script>(function(){if(window.__FARM_PREHYDRATION_CLICK_QUEUE__)return;var queue=[];window.__FARM_PREHYDRATION_CLICK_QUEUE__=queue;window.__FARM_HYDRATED__=false;document.documentElement.dataset.farmHydrated="false";function isModified(event){return !!(event.metaKey||event.altKey||event.ctrlKey||event.shiftKey)}function inHydrated(node){return !!(node&&node.closest&&node.closest('[data-farm-island-hydrated="true"]'))}function closestQueuedTarget(target){while(target&&target!==document.documentElement){if(target.matches&&target.matches(${selector}))return target;target=target.parentElement}return null}function announce(target,kind){document.dispatchEvent(new CustomEvent("farm:island-interaction",{detail:{target:target,kind:kind||null}}))}function hold(event,target,kind){if(!queue.some(function(item){return item.target===target})){queue.push({target:target,kind:kind,createdAt:Date.now()});announce(target,kind)}event.preventDefault();event.stopImmediatePropagation()}document.addEventListener("click",function(event){if(window.__FARM_HYDRATED__)return;if(event.defaultPrevented||event.button!==0||isModified(event))return;var target=closestQueuedTarget(event.target);if(!target||target.closest&&target.closest("a[href]")||inHydrated(target))return;hold(event,target,"click")},true);document.addEventListener("submit",function(event){if(window.__FARM_HYDRATED__)return;if(event.defaultPrevented)return;var form=event.target;if(!form||form.nodeName!=="FORM"||inHydrated(form))return;hold(event,form,"submit")},true);function observe(event){if(window.__FARM_HYDRATED__)return;var target=event.target;if(!(target&&target.closest)||inHydrated(target))return;announce(target,null)}document.addEventListener("pointerdown",observe,true);document.addEventListener("focusin",observe,true);})();</script>`;
25269
25358
  }
25270
25359
  __name(createPreHydrationClickQueueScript, "createPreHydrationClickQueueScript");
25271
25360
  function createDocumentFooter(options) {
@@ -28332,7 +28421,7 @@ function createEndpoint(pathOrOptions, optionsOrHandler, maybeHandler) {
28332
28421
  wrappedHandler
28333
28422
  );
28334
28423
  endpoint.__path = path39 || void 0;
28335
- endpoint.__method = options.method || "GET";
28424
+ endpoint.__method = options.method || (path39 ? "GET" : void 0);
28336
28425
  endpoint.__autoPath = !path39;
28337
28426
  endpoint.__handler = wrappedHandler;
28338
28427
  endpoint.__farmInvoke = (ctx) => runEndpointMiddleware(middleware, ctx, handler, error, options.invalidates);
@@ -29920,7 +30009,7 @@ function parseColonParam(segment) {
29920
30009
  };
29921
30010
  }
29922
30011
  __name(parseColonParam, "parseColonParam");
29923
- function compilePathPattern(pattern) {
30012
+ function compilePathPattern(pattern, trailingSlash = false) {
29924
30013
  const params = [];
29925
30014
  const segments = pattern.split("/").filter(Boolean);
29926
30015
  if (segments.length === 0) {
@@ -29956,11 +30045,18 @@ function compilePathPattern(pattern) {
29956
30045
  });
29957
30046
  return {
29958
30047
  kind: "path",
29959
- regex: new RegExp(`^${parts.join("")}$`),
30048
+ regex: new RegExp(`^${parts.join("")}${trailingSlash ? "/?" : ""}$`),
29960
30049
  params
29961
30050
  };
29962
30051
  }
29963
30052
  __name(compilePathPattern, "compilePathPattern");
30053
+ function compileMatcherPattern(pattern) {
30054
+ if (typeof pattern === "string" && pattern !== "*" && !pattern.endsWith("(.*)")) {
30055
+ return compilePathPattern(pattern, true);
30056
+ }
30057
+ return compilePattern(pattern);
30058
+ }
30059
+ __name(compileMatcherPattern, "compileMatcherPattern");
29964
30060
  function compilePattern(pattern) {
29965
30061
  if (pattern instanceof RegExp) {
29966
30062
  return { kind: "regexp", regex: pattern };
@@ -29980,7 +30076,7 @@ __name(compilePattern, "compilePattern");
29980
30076
  function compileMiddlewareConfig(config) {
29981
30077
  const compiled = {
29982
30078
  matcher: config.matcher ? toMatcherList(config.matcher).map(
29983
- (matcher) => typeof matcher === "function" ? matcher : compilePattern(matcher)
30079
+ (matcher) => typeof matcher === "function" ? matcher : compileMatcherPattern(matcher)
29984
30080
  ) : void 0,
29985
30081
  exclude: config.exclude?.map(compilePattern)
29986
30082
  };
@@ -31246,6 +31342,7 @@ __name(collectLegacyTypeArtifacts, "collectLegacyTypeArtifacts");
31246
31342
  // src/vite.ts
31247
31343
  init_routes_shared();
31248
31344
  init_markdown();
31345
+ init_base_path();
31249
31346
  init_llms_txt();
31250
31347
  init_agent_crawlers();
31251
31348
  init_response();
@@ -32529,8 +32626,8 @@ function farmPlugin(options = {}, initialPluginManager) {
32529
32626
  }, "emitPluginError");
32530
32627
  farmApp = new FarmApp(
32531
32628
  {
32532
- root: server.config.root,
32533
- ...options
32629
+ ...options,
32630
+ root: resolveDevelopmentRoot(options.root, server.config.root)
32534
32631
  },
32535
32632
  server
32536
32633
  );
@@ -33117,7 +33214,8 @@ window.__FARM_MANIFEST__ = ${inlineValue({
33117
33214
  () => middlewareManager.execute(req, res)
33118
33215
  );
33119
33216
  }, "runAppMiddlewareForContentRoute");
33120
- if (openAPIManager && options.openapi?.specRoute && requestPathname === options.openapi.specRoute) {
33217
+ const openAPIRequestPathname = openAPIManager ? stripFarmBasePath(requestPathname, farmConfig.basePath) : requestPathname;
33218
+ if (openAPIManager && options.openapi?.specRoute && openAPIRequestPathname === options.openapi.specRoute) {
33121
33219
  if (await runAppMiddlewareForContentRoute()) return;
33122
33220
  if (requestMethod !== "GET" && requestMethod !== "HEAD") {
33123
33221
  res.statusCode = 405;
@@ -33134,7 +33232,7 @@ window.__FARM_MANIFEST__ = ${inlineValue({
33134
33232
  res.end(requestMethod === "HEAD" ? void 0 : body);
33135
33233
  return;
33136
33234
  }
33137
- if (openAPIManager && requestPathname === options.openapi?.route) {
33235
+ if (openAPIManager && openAPIRequestPathname === options.openapi?.route) {
33138
33236
  if (await runAppMiddlewareForContentRoute()) return;
33139
33237
  const docsHandler = openAPIManager.getDocsRouteHandler(parsedRequestUrl.origin);
33140
33238
  return docsHandler(req, res);
@@ -33612,6 +33710,21 @@ window.__FARM_MANIFEST__ = ${inlineValue({
33612
33710
  headers: request2.headers,
33613
33711
  signal: request2.signal
33614
33712
  });
33713
+ let middlewareMap = /* @__PURE__ */ new Map();
33714
+ let middlewareContext = /* @__PURE__ */ new Map();
33715
+ if (middlewareManager?.hasMiddleware()) {
33716
+ const targetNodeRequest = createPageDataMiddlewareRequest(req, targetRequestUrl);
33717
+ const handled = await runFarmMiddlewareWithNavigation(
33718
+ farmApp.getServerRenderer(),
33719
+ targetRequest,
33720
+ targetNodeRequest,
33721
+ res,
33722
+ () => middlewareManager.execute(targetNodeRequest, res)
33723
+ );
33724
+ if (handled) return;
33725
+ middlewareMap = targetNodeRequest.__FARM_MIDDLEWARE_DATA__ ?? middlewareMap;
33726
+ middlewareContext = targetNodeRequest.__FARM_MIDDLEWARE_CONTEXT__ ?? middlewareContext;
33727
+ }
33615
33728
  await farmApp.getServerRenderer().runWithRequestContext(targetRequest, async () => {
33616
33729
  const routeManager3 = farmApp.getRouteManager();
33617
33730
  if (pm) {
@@ -33685,7 +33798,8 @@ window.__FARM_MANIFEST__ = ${inlineValue({
33685
33798
  {
33686
33799
  params,
33687
33800
  searchParams: Promise.resolve(searchParams),
33688
- path: targetUrl.pathname
33801
+ path: targetUrl.pathname,
33802
+ middleware: middlewareMap.size > 0 ? { data: middlewareMap } : void 0
33689
33803
  },
33690
33804
  routeContext
33691
33805
  ),
@@ -33773,27 +33887,34 @@ window.__FARM_MANIFEST__ = ${inlineValue({
33773
33887
  parseFarmLayoutChainHeader(request2.headers.get("x-farm-layout-chain")),
33774
33888
  destinationLayoutPatterns
33775
33889
  );
33776
- const fragmentHtml = await farmApp.getServerRenderer().renderNavigationFragment({
33777
- PageComponent: routeModule.default,
33778
- LoadingComponent: loadingModule?.default,
33779
- pageProps: routeProps,
33780
- params,
33781
- layouts: layouts.map((layout2, index) => ({
33782
- pattern: layout2.pattern,
33783
- module: layoutModules[index]
33784
- })),
33785
- layoutStartIndex,
33786
- slots: routeSlots.map((slot) => ({
33787
- name: slot.name,
33788
- ownerPattern: slot.ownerPattern,
33789
- containerId: slot.containerId,
33790
- module: slot.renderModule,
33791
- props: slot.props
33792
- })),
33793
- pageShouldHydrate: shouldHydrate,
33794
- layoutShouldHydrate: shouldHydrateLayout,
33795
- islandStrategy: hydrationIslandStrategy
33796
- });
33890
+ const renderer = farmApp.getServerRenderer();
33891
+ const fragmentHtml = await _runWithMiddlewareData(
33892
+ middlewareMap,
33893
+ () => _runWithMiddlewareContext(
33894
+ middlewareContext,
33895
+ () => renderer.renderNavigationFragment({
33896
+ PageComponent: routeModule.default,
33897
+ LoadingComponent: loadingModule?.default,
33898
+ pageProps: routeProps,
33899
+ params,
33900
+ layouts: layouts.map((layout2, index) => ({
33901
+ pattern: layout2.pattern,
33902
+ module: layoutModules[index]
33903
+ })),
33904
+ layoutStartIndex,
33905
+ slots: routeSlots.map((slot) => ({
33906
+ name: slot.name,
33907
+ ownerPattern: slot.ownerPattern,
33908
+ containerId: slot.containerId,
33909
+ module: slot.renderModule,
33910
+ props: slot.props
33911
+ })),
33912
+ pageShouldHydrate: shouldHydrate,
33913
+ layoutShouldHydrate: shouldHydrateLayout,
33914
+ islandStrategy: hydrationIslandStrategy
33915
+ })
33916
+ )
33917
+ );
33797
33918
  const pageData = {
33798
33919
  props: {
33799
33920
  params: routeProps.params,
@@ -33803,7 +33924,9 @@ window.__FARM_MANIFEST__ = ${inlineValue({
33803
33924
  ...routeProps.__farmCanonicalPath ? {
33804
33925
  __farmCanonicalPath: routeProps.__farmCanonicalPath
33805
33926
  } : {},
33806
- ...routeProps.__farmRoutePropsResolved ? { __farmRoutePropsResolved: true } : {}
33927
+ ...routeProps.__farmRoutePropsResolved ? { __farmRoutePropsResolved: true } : {},
33928
+ // The same serialized shape a full load embeds in __FARM_PROPS__.
33929
+ ...middlewareMap.size > 0 ? { middleware: { data: Object.fromEntries(middlewareMap) } } : {}
33807
33930
  },
33808
33931
  canonicalPath: routeProps.__farmCanonicalPath,
33809
33932
  modulePath: toUrlPath(route.modulePath),
@@ -34553,6 +34676,26 @@ function runFarmMiddlewareWithNavigation(renderer, middlewareRequest, req, res,
34553
34676
  });
34554
34677
  }
34555
34678
  __name(runFarmMiddlewareWithNavigation, "runFarmMiddlewareWithNavigation");
34679
+ function createPageDataMiddlewareRequest(req, target) {
34680
+ const targetNodeRequest = Object.create(req);
34681
+ targetNodeRequest.url = `${target.pathname}${target.search}`;
34682
+ targetNodeRequest.originalUrl = targetNodeRequest.url;
34683
+ targetNodeRequest.method = "GET";
34684
+ return targetNodeRequest;
34685
+ }
34686
+ __name(createPageDataMiddlewareRequest, "createPageDataMiddlewareRequest");
34687
+ function resolveDevelopmentRoot(farmRoot, viteRoot) {
34688
+ if (!farmRoot) return viteRoot;
34689
+ if (path38.resolve(farmRoot) === path38.resolve(viteRoot)) return farmRoot;
34690
+ try {
34691
+ if (fs14.realpathSync(farmRoot) === fs14.realpathSync(viteRoot)) {
34692
+ return path38.resolve(viteRoot);
34693
+ }
34694
+ } catch {
34695
+ }
34696
+ return farmRoot;
34697
+ }
34698
+ __name(resolveDevelopmentRoot, "resolveDevelopmentRoot");
34556
34699
  function isFarmClientVirtualId(id) {
34557
34700
  const pathname = id.split("?", 1)[0];
34558
34701
  return pathname === "/@farm/client" || pathname === "/@farm/client.js";
@@ -34568,16 +34711,18 @@ function generateProgrammaticRouteModule(moduleId, root, renderer = REACT_RENDER
34568
34711
  return generateProgrammaticApiRouteModule(parsed.routePath, routeFile);
34569
34712
  }
34570
34713
  return `
34571
- import {
34572
- createElement as __farmCreateElement,
34573
- Suspense as __farmSuspense,
34574
- } from ${JSON.stringify(renderer.server)};
34714
+ import * as __farmRendererRuntime from ${JSON.stringify(renderer.server)};
34575
34715
  import {
34576
34716
  createLayoutModuleFromProgrammaticLayout as __farmCreateLayoutRouteModule,
34577
34717
  createRouteModuleFromProgrammaticPage as __farmCreatePageRouteModule,
34578
34718
  } from "@farm.js/core/routes";
34579
34719
  import * as __farmRoutesModule from ${JSON.stringify(routeFile)};
34580
34720
 
34721
+ const __farmCreateElement = __farmRendererRuntime.createElement;
34722
+ const __farmSuspense = __farmRendererRuntime.Suspense;
34723
+ // Optional hook: only renderers that need it export markFunctionComponent.
34724
+ const __farmMarkFunctionComponent = Reflect.get(__farmRendererRuntime, "markFunctionComponent");
34725
+
34581
34726
  const __farmIsRouteDefinition = (value) => (
34582
34727
  value &&
34583
34728
  typeof value === "object" &&
@@ -34631,6 +34776,7 @@ const __farmRouteModule = __farmRoute.kind === "layout"
34631
34776
  : __farmCreatePageRouteModule(__farmRoute, {
34632
34777
  createElement: __farmCreateElement,
34633
34778
  Suspense: __farmSuspense,
34779
+ markFunctionComponent: __farmMarkFunctionComponent,
34634
34780
  });
34635
34781
 
34636
34782
  export const metadata = __farmRouteModule.metadata;
@@ -36240,6 +36386,11 @@ async function hydrate() {
36240
36386
  pendingPageHydrationController = hydrationController;
36241
36387
  await hydrateFarmIsolatedClientBoundaries(rootContainer, hydrationController.signal);
36242
36388
  if (hydrationController.signal.aborted) return;
36389
+ // The rest of the document is static server HTML with nothing to hydrate, so
36390
+ // stop holding its clicks and submits once the load-strategy islands are live.
36391
+ // Deferred islands capture their own interactions, and held targets outside an
36392
+ // island are not replayed into DOM no client code owns.
36393
+ markFarmHydrated();
36243
36394
  return;
36244
36395
  }` : ""}
36245
36396
  if (!shouldHydrate) {