@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/vite.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 {
@@ -104,9 +129,8 @@ function readServerEnvKey(server, key) {
104
129
  function readRuntimeServerEnv(env2) {
105
130
  const state = env2[FARM_ENV_RUNTIME_SYMBOL];
106
131
  if (!state) return;
107
- const source = getProcessEnv();
108
132
  for (const [key, type] of Object.entries(state.pending)) {
109
- const raw = source[key];
133
+ const raw = readFarmEnvironmentValue(key);
110
134
  if (raw === void 0) continue;
111
135
  env2.server[key] = coerceRuntimeEnvValue(raw, type);
112
136
  delete state.pending[key];
@@ -137,6 +161,22 @@ function coerceRuntimeEnvValue(raw, type) {
137
161
  }
138
162
  return raw;
139
163
  }
164
+ function isSameEnvValue(left, right) {
165
+ if (Object.is(left, right)) return true;
166
+ if (Array.isArray(left) || Array.isArray(right)) {
167
+ return Array.isArray(left) && Array.isArray(right) && left.length === right.length && left.every((item, index) => isSameEnvValue(item, right[index]));
168
+ }
169
+ if (!isPlainObject(left) || !isPlainObject(right)) return false;
170
+ const keys = Object.keys(left);
171
+ return keys.length === Object.keys(right).length && keys.every(
172
+ (key) => Object.prototype.hasOwnProperty.call(right, key) && isSameEnvValue(left[key], right[key])
173
+ );
174
+ }
175
+ function isPlainObject(value) {
176
+ if (!value || typeof value !== "object") return false;
177
+ const prototype = Object.getPrototypeOf(value);
178
+ return prototype === Object.prototype || prototype === null;
179
+ }
140
180
  function prepareEnv(env2) {
141
181
  const normalized = normalizeResolvedEnv(env2);
142
182
  const runtime3 = env2.runtime?.server;
@@ -212,6 +252,7 @@ var FARM_ENV_SYMBOL, FARM_ENV_RUNTIME_SYMBOL, farmEnvGlobal, currentEnv, env, pu
212
252
  var init_env = __esm({
213
253
  "src/env.ts"() {
214
254
  "use strict";
255
+ init_runtime_env();
215
256
  FARM_ENV_SYMBOL = /* @__PURE__ */ Symbol.for("farm.env");
216
257
  FARM_ENV_RUNTIME_SYMBOL = /* @__PURE__ */ Symbol.for("farm.env.runtime");
217
258
  farmEnvGlobal = globalThis;
@@ -225,6 +266,8 @@ var init_env = __esm({
225
266
  __name(readRuntimeServerEnv, "readRuntimeServerEnv");
226
267
  __name(getRuntimeEnvType, "getRuntimeEnvType");
227
268
  __name(coerceRuntimeEnvValue, "coerceRuntimeEnvValue");
269
+ __name(isSameEnvValue, "isSameEnvValue");
270
+ __name(isPlainObject, "isPlainObject");
228
271
  __name(prepareEnv, "prepareEnv");
229
272
  __name(assertServerEnvAccess, "assertServerEnvAccess");
230
273
  __name(getInitialEnv, "getInitialEnv");
@@ -358,8 +401,16 @@ async function createMarkdownMirrorResponse(options) {
358
401
  if (!hasMarkdownExtension) {
359
402
  headersOut.set("Vary", "Accept");
360
403
  }
404
+ for (const token of pageResponse.headers.get("vary")?.split(",") ?? []) {
405
+ const name2 = token.trim();
406
+ if (name2 && name2.toLowerCase() !== "accept") appendHeaderToken(headersOut, "Vary", name2);
407
+ }
408
+ const pageCacheControl = pageResponse.headers.get("cache-control");
361
409
  const cache = target.route?.cache ?? options.config?.cache ?? false;
362
- headersOut.set("Cache-Control", createMarkdownCacheHeader(cache));
410
+ headersOut.set(
411
+ "Cache-Control",
412
+ pageCacheControl && isPrivateCacheControl(pageCacheControl) ? pageCacheControl : createMarkdownCacheHeader(cache)
413
+ );
363
414
  return new Response(options.request.method === "HEAD" ? null : markdown, {
364
415
  status: pageResponse.status,
365
416
  headers: headersOut
@@ -510,6 +561,17 @@ function isFarmMarkdownMirrorExposed(config, pathname) {
510
561
  function matchesFarmMarkdownRoutePattern(pattern, pathname) {
511
562
  return routeMatches(pattern, pathname);
512
563
  }
564
+ function appendHeaderToken(headers, name2, token) {
565
+ const current = headers.get(name2);
566
+ if (!current) {
567
+ headers.set(name2, token);
568
+ return;
569
+ }
570
+ const tokens = current.split(",").map((value) => value.trim().toLowerCase());
571
+ if (!tokens.includes(token.toLowerCase())) {
572
+ headers.set(name2, `${current}, ${token}`);
573
+ }
574
+ }
513
575
  function findExposedMarkdownRoute(config, pathname) {
514
576
  if (config.expose === true) {
515
577
  return null;
@@ -541,6 +603,12 @@ function isHtmlResponse(response) {
541
603
  const contentType = response.headers.get("content-type") ?? "";
542
604
  return contentType.includes("text/html");
543
605
  }
606
+ function isPrivateCacheControl(value) {
607
+ return value.split(",").some((directive) => {
608
+ const name2 = directive.split("=", 1)[0].trim().toLowerCase();
609
+ return name2 === "private" || name2 === "no-store";
610
+ });
611
+ }
544
612
  function createMarkdownCacheHeader(cache) {
545
613
  if (cache === false || cache <= 0) {
546
614
  return "no-store";
@@ -693,9 +761,11 @@ var init_markdown = __esm({
693
761
  __name(getFarmMarkdownAlternatePath, "getFarmMarkdownAlternatePath");
694
762
  __name(isFarmMarkdownMirrorExposed, "isFarmMarkdownMirrorExposed");
695
763
  __name(matchesFarmMarkdownRoutePattern, "matchesFarmMarkdownRoutePattern");
764
+ __name(appendHeaderToken, "appendHeaderToken");
696
765
  __name(findExposedMarkdownRoute, "findExposedMarkdownRoute");
697
766
  __name(routeMatches, "routeMatches");
698
767
  __name(isHtmlResponse, "isHtmlResponse");
768
+ __name(isPrivateCacheControl, "isPrivateCacheControl");
699
769
  __name(createMarkdownCacheHeader, "createMarkdownCacheHeader");
700
770
  __name(extractHtmlTitle, "extractHtmlTitle");
701
771
  __name(extractHtmlBody, "extractHtmlBody");
@@ -1399,29 +1469,6 @@ var init_secret_compare = __esm({
1399
1469
  }
1400
1470
  });
1401
1471
 
1402
- // src/utils/runtime-env.ts
1403
- function getFarmRuntimeBindings() {
1404
- const runtimeBindings = globalThis.__env__;
1405
- return runtimeBindings && typeof runtimeBindings === "object" ? runtimeBindings : void 0;
1406
- }
1407
- function readFarmEnvironmentValue(name2) {
1408
- const runtimeValue = getFarmRuntimeBindings()?.[name2];
1409
- if (typeof runtimeValue === "string") return runtimeValue;
1410
- return typeof process !== "undefined" ? process.env?.[name2] : void 0;
1411
- }
1412
- function isFarmDeployedRuntime() {
1413
- if (getFarmRuntimeBindings()) return true;
1414
- return readFarmEnvironmentValue("NODE_ENV") === "production";
1415
- }
1416
- var init_runtime_env = __esm({
1417
- "src/utils/runtime-env.ts"() {
1418
- "use strict";
1419
- __name(getFarmRuntimeBindings, "getFarmRuntimeBindings");
1420
- __name(readFarmEnvironmentValue, "readFarmEnvironmentValue");
1421
- __name(isFarmDeployedRuntime, "isFarmDeployedRuntime");
1422
- }
1423
- });
1424
-
1425
1472
  // src/utils/decode.ts
1426
1473
  function decodeRouteSegment(segment) {
1427
1474
  try {
@@ -4676,7 +4723,7 @@ function mergeFarmLayerConfig(base, override) {
4676
4723
  output[key] = mergeConfigListResolvers(output[key], value);
4677
4724
  continue;
4678
4725
  }
4679
- if (isPlainObject(output[key]) && isPlainObject(value)) {
4726
+ if (isPlainObject2(output[key]) && isPlainObject2(value)) {
4680
4727
  output[key] = mergePlainObjects(output[key], value);
4681
4728
  continue;
4682
4729
  }
@@ -4688,7 +4735,7 @@ function mergePlainObjects(base, override) {
4688
4735
  const output = { ...base };
4689
4736
  for (const [key, value] of Object.entries(override)) {
4690
4737
  if (value === void 0) continue;
4691
- output[key] = isPlainObject(output[key]) && isPlainObject(value) ? mergePlainObjects(output[key], value) : value;
4738
+ output[key] = isPlainObject2(output[key]) && isPlainObject2(value) ? mergePlainObjects(output[key], value) : value;
4692
4739
  }
4693
4740
  return output;
4694
4741
  }
@@ -4703,7 +4750,7 @@ function toArray(value) {
4703
4750
  if (value === void 0 || value === null) return [];
4704
4751
  return Array.isArray(value) ? value : [value];
4705
4752
  }
4706
- function isPlainObject(value) {
4753
+ function isPlainObject2(value) {
4707
4754
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
4708
4755
  const prototype = Object.getPrototypeOf(value);
4709
4756
  return prototype === Object.prototype || prototype === null;
@@ -4780,7 +4827,7 @@ var init_layers = __esm({
4780
4827
  __name(mergeConfigListResolvers, "mergeConfigListResolvers");
4781
4828
  __name(resolveConfigList, "resolveConfigList");
4782
4829
  __name(toArray, "toArray");
4783
- __name(isPlainObject, "isPlainObject");
4830
+ __name(isPlainObject2, "isPlainObject");
4784
4831
  __name(isPathLayerSource, "isPathLayerSource");
4785
4832
  __name(normalizeRealPath, "normalizeRealPath");
4786
4833
  }
@@ -5565,6 +5612,8 @@ var init_cache = __esm({
5565
5612
  constructor(config = {}) {
5566
5613
  this.entries = /* @__PURE__ */ new Map();
5567
5614
  this.inflight = /* @__PURE__ */ new Map();
5615
+ /** Local entries by tag, so tag counts and pruning never scan unrelated entries. */
5616
+ this.entriesByTag = /* @__PURE__ */ new Map();
5568
5617
  this.invalidatedTagVersions = /* @__PURE__ */ new Map();
5569
5618
  this.activeGenerations = /* @__PURE__ */ new Set();
5570
5619
  this.version = 0;
@@ -5583,6 +5632,7 @@ var init_cache = __esm({
5583
5632
  configure(config = {}) {
5584
5633
  this.generation++;
5585
5634
  this.entries.clear();
5635
+ this.entriesByTag.clear();
5586
5636
  this.inflight.clear();
5587
5637
  this.invalidatedTagVersions.clear();
5588
5638
  this.activeGenerations.clear();
@@ -5749,14 +5799,12 @@ var init_cache = __esm({
5749
5799
  return entry;
5750
5800
  }
5751
5801
  delete(key) {
5752
- const deleted = this.entries.delete(key);
5753
- if (deleted) this.pruneInvalidatedTagVersions();
5802
+ const deleted = this.deleteLocalEntry(key);
5754
5803
  emitFarmEvent({ type: "cache.delete", key, deleted });
5755
5804
  return deleted;
5756
5805
  }
5757
5806
  async deleteAsync(key) {
5758
- const deleted = this.entries.delete(key);
5759
- if (deleted) this.pruneInvalidatedTagVersions();
5807
+ const deleted = this.deleteLocalEntry(key);
5760
5808
  if (this.adapter) {
5761
5809
  await this.adapter.delete(this.createAdapterKey(key));
5762
5810
  }
@@ -5767,6 +5815,7 @@ var init_cache = __esm({
5767
5815
  const count = this.entries.size;
5768
5816
  this.generation++;
5769
5817
  this.entries.clear();
5818
+ this.entriesByTag.clear();
5770
5819
  this.inflight.clear();
5771
5820
  this.invalidatedTagVersions.clear();
5772
5821
  this.activeGenerations.clear();
@@ -5852,23 +5901,32 @@ var init_cache = __esm({
5852
5901
  return cached.value;
5853
5902
  }
5854
5903
  const inflight = this.inflight.get(key);
5855
- if (inflight) {
5904
+ if (inflight && !this.wasInvalidatedSince(inflight.tags, inflight.startVersion)) {
5856
5905
  emitFarmEvent({ type: "cache.dedupe", key });
5857
- return inflight;
5906
+ return inflight.promise;
5858
5907
  }
5859
5908
  const tags = Array.from(normalizeCacheOptionsTags(options));
5860
5909
  const generation = this.generation;
5910
+ const startVersion = this.version;
5861
5911
  const promise = this.fillCacheEntry(key, producer, options, tags, generation).catch((error) => {
5862
5912
  emitFarmEvent({ type: "cache.error", key, operation: "set", error });
5863
5913
  throw error;
5864
5914
  }).finally(() => {
5865
- if (this.inflight.get(key) === promise) {
5915
+ if (this.inflight.get(key)?.promise === promise) {
5866
5916
  this.inflight.delete(key);
5867
5917
  }
5868
5918
  });
5869
- this.inflight.set(key, promise);
5919
+ this.inflight.set(key, { promise, tags, startVersion });
5870
5920
  return promise;
5871
5921
  }
5922
+ /** A fill that started before one of its tags was invalidated cannot satisfy later readers. */
5923
+ wasInvalidatedSince(tags, version2) {
5924
+ for (const tag of tags) {
5925
+ const invalidatedVersion = this.invalidatedTagVersions.get(tag);
5926
+ if (invalidatedVersion !== void 0 && invalidatedVersion > version2) return true;
5927
+ }
5928
+ return false;
5929
+ }
5872
5930
  async fillCacheEntry(key, producer, options, tags, generation) {
5873
5931
  const adapter = this.adapter;
5874
5932
  const namespace = this.namespace;
@@ -5909,7 +5967,7 @@ var init_cache = __esm({
5909
5967
  return value;
5910
5968
  } finally {
5911
5969
  this.activeGenerations.delete(activeGeneration);
5912
- this.pruneInvalidatedTagVersions();
5970
+ this.pruneInvalidatedTagVersions(activeGeneration.tags);
5913
5971
  if (leaseToken && adapter?.releaseLease) {
5914
5972
  try {
5915
5973
  await adapter.releaseLease(leaseKey, leaseToken);
@@ -5954,18 +6012,9 @@ var init_cache = __esm({
5954
6012
  }
5955
6013
  return void 0;
5956
6014
  }
5957
- countEntriesForTag(tag) {
5958
- let count = 0;
5959
- for (const entry of this.entries.values()) {
5960
- if (entry.tags.has(tag)) {
5961
- count++;
5962
- }
5963
- }
5964
- return count;
5965
- }
5966
6015
  countEntriesForTags(tags) {
5967
6016
  let count = 0;
5968
- for (const entry of this.entries.values()) {
6017
+ for (const entry of this.entriesByTag.get(tags[0]) ?? []) {
5969
6018
  if (tags.every((tag) => entry.tags.has(tag))) {
5970
6019
  count++;
5971
6020
  }
@@ -5973,10 +6022,10 @@ var init_cache = __esm({
5973
6022
  return count;
5974
6023
  }
5975
6024
  invalidateTag(normalizedTag) {
5976
- const count = this.countEntriesForTag(normalizedTag);
6025
+ const count = this.entriesByTag.get(normalizedTag)?.size ?? 0;
5977
6026
  this.invalidatedTagVersions.delete(normalizedTag);
5978
6027
  this.invalidatedTagVersions.set(normalizedTag, ++this.version);
5979
- this.pruneInvalidatedTagVersions();
6028
+ this.pruneInvalidatedTagVersions([normalizedTag]);
5980
6029
  return count;
5981
6030
  }
5982
6031
  toPublicEntry(entry) {
@@ -6006,19 +6055,51 @@ var init_cache = __esm({
6006
6055
  this.entries.set(key, entry);
6007
6056
  }
6008
6057
  storeLocalEntry(entry) {
6009
- this.entries.delete(entry.key);
6058
+ const removed = [];
6059
+ const replaced = this.detachLocalEntry(entry.key);
6060
+ if (replaced) removed.push(replaced);
6010
6061
  this.entries.set(entry.key, entry);
6062
+ for (const tag of entry.tags) {
6063
+ let tagged = this.entriesByTag.get(tag);
6064
+ if (!tagged) this.entriesByTag.set(tag, tagged = /* @__PURE__ */ new Set());
6065
+ tagged.add(entry);
6066
+ }
6011
6067
  while (this.entries.size > this.maxEntries) {
6012
6068
  const oldestKey = this.entries.keys().next().value;
6013
6069
  if (oldestKey === void 0) break;
6014
- this.entries.delete(oldestKey);
6070
+ removed.push(this.detachLocalEntry(oldestKey));
6015
6071
  }
6016
- this.pruneInvalidatedTagVersions();
6072
+ for (const removedEntry of removed) this.pruneInvalidatedTagVersions(removedEntry.tags);
6073
+ }
6074
+ deleteLocalEntry(key) {
6075
+ const entry = this.detachLocalEntry(key);
6076
+ if (!entry) return false;
6077
+ this.pruneInvalidatedTagVersions(entry.tags);
6078
+ return true;
6017
6079
  }
6018
- pruneInvalidatedTagVersions() {
6019
- tags: for (const [tag, invalidatedVersion] of this.invalidatedTagVersions) {
6020
- for (const entry of this.entries.values()) {
6021
- if (entry.tags.has(tag) && entry.createdVersion < invalidatedVersion) continue tags;
6080
+ detachLocalEntry(key) {
6081
+ const entry = this.entries.get(key);
6082
+ if (!entry) return void 0;
6083
+ this.entries.delete(key);
6084
+ for (const tag of entry.tags) {
6085
+ const tagged = this.entriesByTag.get(tag);
6086
+ if (!tagged) continue;
6087
+ tagged.delete(entry);
6088
+ if (tagged.size === 0) this.entriesByTag.delete(tag);
6089
+ }
6090
+ return entry;
6091
+ }
6092
+ /**
6093
+ * Drop invalidation versions that no local entry or active fill can be stale against.
6094
+ * Callers pass only the tags whose dependents just changed, so the cost is bounded by
6095
+ * the entries sharing those tags rather than by the whole cache.
6096
+ */
6097
+ pruneInvalidatedTagVersions(tags) {
6098
+ tags: for (const tag of tags) {
6099
+ const invalidatedVersion = this.invalidatedTagVersions.get(tag);
6100
+ if (invalidatedVersion === void 0) continue;
6101
+ for (const entry of this.entriesByTag.get(tag) ?? []) {
6102
+ if (entry.createdVersion < invalidatedVersion) continue tags;
6022
6103
  }
6023
6104
  for (const generation of this.activeGenerations) {
6024
6105
  if (generation.tags.has(tag) && generation.createdVersion < invalidatedVersion)
@@ -6413,6 +6494,7 @@ function createProgrammaticPageComponent(route, rendererRuntime) {
6413
6494
  }
6414
6495
  return rendererRuntime.createElement(...args);
6415
6496
  }, "createElement");
6497
+ const markFunctionComponent = /* @__PURE__ */ __name((component) => rendererRuntime?.markFunctionComponent?.(component) ?? component, "markFunctionComponent");
6416
6498
  const Component = route.component;
6417
6499
  if (route.pending) {
6418
6500
  const PendingComponent = route.pending;
@@ -6434,7 +6516,9 @@ function createProgrammaticPageComponent(route, rendererRuntime) {
6434
6516
  throw error;
6435
6517
  }
6436
6518
  }, "FarmProgrammaticPageContent");
6437
- const PageContent = FarmProgrammaticPageContent2;
6519
+ const PageContent = markFunctionComponent(
6520
+ FarmProgrammaticPageContent2
6521
+ );
6438
6522
  const FarmProgrammaticPage = /* @__PURE__ */ __name(function FarmProgrammaticPage2(props) {
6439
6523
  return createElement2(
6440
6524
  rendererRuntime.Suspense,
@@ -6444,7 +6528,7 @@ function createProgrammaticPageComponent(route, rendererRuntime) {
6444
6528
  createElement2(PageContent, props)
6445
6529
  );
6446
6530
  }, "FarmProgrammaticPage");
6447
- return FarmProgrammaticPage;
6531
+ return markFunctionComponent(FarmProgrammaticPage);
6448
6532
  }
6449
6533
  const FarmProgrammaticPageContent = /* @__PURE__ */ __name(async function FarmProgrammaticPageContent2(props) {
6450
6534
  try {
@@ -6463,7 +6547,7 @@ function createProgrammaticPageComponent(route, rendererRuntime) {
6463
6547
  throw error;
6464
6548
  }
6465
6549
  }, "FarmProgrammaticPageContent");
6466
- return FarmProgrammaticPageContent;
6550
+ return markFunctionComponent(FarmProgrammaticPageContent);
6467
6551
  }
6468
6552
  function readProgrammaticRouteProps(route, props, resources) {
6469
6553
  if (isProgrammaticRoutePropsResolved(props)) {
@@ -13561,6 +13645,7 @@ function createFarmDocsHandler(docs, options) {
13561
13645
  if (!isFarmDocsRequest(docs, request2)) return null;
13562
13646
  const page2 = loadPage(contentDir, docs, request2);
13563
13647
  if (!page2) return null;
13648
+ const negotiatesAccept = !requestUrl.pathname.endsWith(".md");
13564
13649
  if (shouldReturnMarkdown(request2)) {
13565
13650
  const origin = new URL(request2.url).origin;
13566
13651
  return omitFarmDocsHeadBody(
@@ -13575,7 +13660,8 @@ function createFarmDocsHandler(docs, options) {
13575
13660
  status: 200,
13576
13661
  headers: {
13577
13662
  "Content-Type": "text/markdown; charset=utf-8",
13578
- "Cache-Control": "public, max-age=60"
13663
+ "Cache-Control": "public, max-age=60",
13664
+ ...negotiatesAccept ? { Vary: "Accept" } : {}
13579
13665
  }
13580
13666
  }
13581
13667
  )
@@ -13605,6 +13691,7 @@ function createFarmDocsHandler(docs, options) {
13605
13691
  headers: {
13606
13692
  "Content-Type": "text/html; charset=utf-8",
13607
13693
  "Cache-Control": "public, s-maxage=60, stale-while-revalidate=300",
13694
+ Vary: "Accept",
13608
13695
  ...fontPreloadHeader ? { Link: fontPreloadHeader } : {}
13609
13696
  }
13610
13697
  }
@@ -19564,7 +19651,7 @@ function resolveImportedModule(importerPath, specifier, root) {
19564
19651
  return { path: resolveImportedModuleSourcePath(importerPath, specifier, root), local: true };
19565
19652
  }
19566
19653
  const aliased = resolveProjectAliasSourcePath(specifier, root);
19567
- if (aliased !== void 0) return { path: aliased, local: true };
19654
+ if (aliased) return { path: aliased, local: true };
19568
19655
  return { path: resolvePackageModuleSourcePath(importerPath, specifier, root), local: false };
19569
19656
  }
19570
19657
  __name(resolveImportedModule, "resolveImportedModule");
@@ -19580,11 +19667,12 @@ function resolveProjectAliasSourcePath(specifier, root) {
19580
19667
  if (!match || alias.prefix.length > match.alias.prefix.length) match = { alias, captured };
19581
19668
  }
19582
19669
  if (!match) return void 0;
19583
- return resolveSourceCandidate(
19670
+ const resolved = resolveSourceCandidate(
19584
19671
  match.alias.targets.map(
19585
19672
  (target) => import_path4.default.normalize(match.alias.wildcard ? target.replace("*", match.captured) : target)
19586
19673
  )
19587
19674
  );
19675
+ return resolved && /\.d\.[cm]?ts$/.test(resolved) ? null : resolved;
19588
19676
  }
19589
19677
  __name(resolveProjectAliasSourcePath, "resolveProjectAliasSourcePath");
19590
19678
  function matchProjectImportAlias(alias, specifier) {
@@ -19991,6 +20079,7 @@ __name(readAltText, "readAltText");
19991
20079
  // src/routing/route-manager.ts
19992
20080
  init_route_runtime();
19993
20081
  init_routing();
20082
+ init_base_path();
19994
20083
 
19995
20084
  // src/redirect-query.ts
19996
20085
  function appendFarmRedirectQuery(destination, search) {
@@ -21067,7 +21156,7 @@ var _RouteManager = class _RouteManager {
21067
21156
  }
21068
21157
  toRoutePathname(pathname) {
21069
21158
  const i18n = this.getI18nConfig();
21070
- return i18n ? stripFarmLocaleFromPathname(pathname, i18n) : pathname;
21159
+ return i18n ? stripFarmLocaleFromPathname(pathname, i18n) : stripFarmBasePath(pathname, this.config.basePath);
21071
21160
  }
21072
21161
  localizeRedirectDestination(destination, locale) {
21073
21162
  if (!locale || !destination.startsWith("/") || destination.startsWith("//")) {
@@ -22256,7 +22345,7 @@ async function readFarmI18nCatalogs(config) {
22256
22345
  }
22257
22346
  __name(readFarmI18nCatalogs, "readFarmI18nCatalogs");
22258
22347
  function flattenFarmI18nCatalog(input, source = "i18n catalog") {
22259
- if (!isPlainObject2(input)) {
22348
+ if (!isPlainObject3(input)) {
22260
22349
  throw new Error(`${source} must contain a JSON object at its root.`);
22261
22350
  }
22262
22351
  const output = {};
@@ -22270,7 +22359,7 @@ function flattenFarmI18nCatalog(input, source = "i18n catalog") {
22270
22359
  output[key] = value;
22271
22360
  return;
22272
22361
  }
22273
- if (!isPlainObject2(value)) {
22362
+ if (!isPlainObject3(value)) {
22274
22363
  const key = segments.join(".") || "<root>";
22275
22364
  throw new Error(`${source} message "${key}" must be a string or nested object.`);
22276
22365
  }
@@ -22370,10 +22459,10 @@ function sameSignature(expected, actual) {
22370
22459
  return JSON.stringify(expectedEntries) === JSON.stringify(actualEntries);
22371
22460
  }
22372
22461
  __name(sameSignature, "sameSignature");
22373
- function isPlainObject2(value) {
22462
+ function isPlainObject3(value) {
22374
22463
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
22375
22464
  }
22376
- __name(isPlainObject2, "isPlainObject");
22465
+ __name(isPlainObject3, "isPlainObject");
22377
22466
  function messageOf(error) {
22378
22467
  return error instanceof Error ? error.message : String(error);
22379
22468
  }
@@ -25176,7 +25265,7 @@ _setFarmThemeServerSnapshotResolver(() => {
25176
25265
  });
25177
25266
 
25178
25267
  // package.json
25179
- var version = "0.1.16";
25268
+ var version = "0.1.17";
25180
25269
 
25181
25270
  // src/version.ts
25182
25271
  var FARM_VERSION = version;
@@ -25466,7 +25555,7 @@ function createPPRRefreshScript() {
25466
25555
  __name(createPPRRefreshScript, "createPPRRefreshScript");
25467
25556
  function createPreHydrationClickQueueScript() {
25468
25557
  const selector = JSON.stringify(FARM_ISLAND_REPLAYABLE_SELECTOR);
25469
- 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>`;
25558
+ 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>`;
25470
25559
  }
25471
25560
  __name(createPreHydrationClickQueueScript, "createPreHydrationClickQueueScript");
25472
25561
  function createDocumentFooter(options) {
@@ -28826,7 +28915,7 @@ function createEndpoint(pathOrOptions, optionsOrHandler, maybeHandler) {
28826
28915
  wrappedHandler
28827
28916
  );
28828
28917
  endpoint.__path = path39 || void 0;
28829
- endpoint.__method = options.method || "GET";
28918
+ endpoint.__method = options.method || (path39 ? "GET" : void 0);
28830
28919
  endpoint.__autoPath = !path39;
28831
28920
  endpoint.__handler = wrappedHandler;
28832
28921
  endpoint.__farmInvoke = (ctx) => runEndpointMiddleware(middleware, ctx, handler, error, options.invalidates);
@@ -30414,7 +30503,7 @@ function parseColonParam(segment) {
30414
30503
  };
30415
30504
  }
30416
30505
  __name(parseColonParam, "parseColonParam");
30417
- function compilePathPattern(pattern) {
30506
+ function compilePathPattern(pattern, trailingSlash = false) {
30418
30507
  const params = [];
30419
30508
  const segments = pattern.split("/").filter(Boolean);
30420
30509
  if (segments.length === 0) {
@@ -30450,11 +30539,18 @@ function compilePathPattern(pattern) {
30450
30539
  });
30451
30540
  return {
30452
30541
  kind: "path",
30453
- regex: new RegExp(`^${parts.join("")}$`),
30542
+ regex: new RegExp(`^${parts.join("")}${trailingSlash ? "/?" : ""}$`),
30454
30543
  params
30455
30544
  };
30456
30545
  }
30457
30546
  __name(compilePathPattern, "compilePathPattern");
30547
+ function compileMatcherPattern(pattern) {
30548
+ if (typeof pattern === "string" && pattern !== "*" && !pattern.endsWith("(.*)")) {
30549
+ return compilePathPattern(pattern, true);
30550
+ }
30551
+ return compilePattern(pattern);
30552
+ }
30553
+ __name(compileMatcherPattern, "compileMatcherPattern");
30458
30554
  function compilePattern(pattern) {
30459
30555
  if (pattern instanceof RegExp) {
30460
30556
  return { kind: "regexp", regex: pattern };
@@ -30474,7 +30570,7 @@ __name(compilePattern, "compilePattern");
30474
30570
  function compileMiddlewareConfig(config) {
30475
30571
  const compiled = {
30476
30572
  matcher: config.matcher ? toMatcherList(config.matcher).map(
30477
- (matcher) => typeof matcher === "function" ? matcher : compilePattern(matcher)
30573
+ (matcher) => typeof matcher === "function" ? matcher : compileMatcherPattern(matcher)
30478
30574
  ) : void 0,
30479
30575
  exclude: config.exclude?.map(compilePattern)
30480
30576
  };
@@ -31740,6 +31836,7 @@ __name(collectLegacyTypeArtifacts, "collectLegacyTypeArtifacts");
31740
31836
  // src/vite.ts
31741
31837
  init_routes_shared();
31742
31838
  init_markdown();
31839
+ init_base_path();
31743
31840
  init_llms_txt();
31744
31841
  init_agent_crawlers();
31745
31842
  init_response();
@@ -33466,8 +33563,8 @@ function farmPlugin(options = {}, initialPluginManager) {
33466
33563
  }, "emitPluginError");
33467
33564
  farmApp = new FarmApp(
33468
33565
  {
33469
- root: server.config.root,
33470
- ...options
33566
+ ...options,
33567
+ root: resolveDevelopmentRoot(options.root, server.config.root)
33471
33568
  },
33472
33569
  server
33473
33570
  );
@@ -34054,7 +34151,8 @@ window.__FARM_MANIFEST__ = ${inlineValue({
34054
34151
  () => middlewareManager.execute(req, res)
34055
34152
  );
34056
34153
  }, "runAppMiddlewareForContentRoute");
34057
- if (openAPIManager && options.openapi?.specRoute && requestPathname === options.openapi.specRoute) {
34154
+ const openAPIRequestPathname = openAPIManager ? stripFarmBasePath(requestPathname, farmConfig.basePath) : requestPathname;
34155
+ if (openAPIManager && options.openapi?.specRoute && openAPIRequestPathname === options.openapi.specRoute) {
34058
34156
  if (await runAppMiddlewareForContentRoute()) return;
34059
34157
  if (requestMethod !== "GET" && requestMethod !== "HEAD") {
34060
34158
  res.statusCode = 405;
@@ -34071,7 +34169,7 @@ window.__FARM_MANIFEST__ = ${inlineValue({
34071
34169
  res.end(requestMethod === "HEAD" ? void 0 : body);
34072
34170
  return;
34073
34171
  }
34074
- if (openAPIManager && requestPathname === options.openapi?.route) {
34172
+ if (openAPIManager && openAPIRequestPathname === options.openapi?.route) {
34075
34173
  if (await runAppMiddlewareForContentRoute()) return;
34076
34174
  const docsHandler = openAPIManager.getDocsRouteHandler(parsedRequestUrl.origin);
34077
34175
  return docsHandler(req, res);
@@ -34549,6 +34647,21 @@ window.__FARM_MANIFEST__ = ${inlineValue({
34549
34647
  headers: request2.headers,
34550
34648
  signal: request2.signal
34551
34649
  });
34650
+ let middlewareMap = /* @__PURE__ */ new Map();
34651
+ let middlewareContext = /* @__PURE__ */ new Map();
34652
+ if (middlewareManager?.hasMiddleware()) {
34653
+ const targetNodeRequest = createPageDataMiddlewareRequest(req, targetRequestUrl);
34654
+ const handled = await runFarmMiddlewareWithNavigation(
34655
+ farmApp.getServerRenderer(),
34656
+ targetRequest,
34657
+ targetNodeRequest,
34658
+ res,
34659
+ () => middlewareManager.execute(targetNodeRequest, res)
34660
+ );
34661
+ if (handled) return;
34662
+ middlewareMap = targetNodeRequest.__FARM_MIDDLEWARE_DATA__ ?? middlewareMap;
34663
+ middlewareContext = targetNodeRequest.__FARM_MIDDLEWARE_CONTEXT__ ?? middlewareContext;
34664
+ }
34552
34665
  await farmApp.getServerRenderer().runWithRequestContext(targetRequest, async () => {
34553
34666
  const routeManager3 = farmApp.getRouteManager();
34554
34667
  if (pm) {
@@ -34622,7 +34735,8 @@ window.__FARM_MANIFEST__ = ${inlineValue({
34622
34735
  {
34623
34736
  params,
34624
34737
  searchParams: Promise.resolve(searchParams),
34625
- path: targetUrl.pathname
34738
+ path: targetUrl.pathname,
34739
+ middleware: middlewareMap.size > 0 ? { data: middlewareMap } : void 0
34626
34740
  },
34627
34741
  routeContext
34628
34742
  ),
@@ -34710,27 +34824,34 @@ window.__FARM_MANIFEST__ = ${inlineValue({
34710
34824
  parseFarmLayoutChainHeader(request2.headers.get("x-farm-layout-chain")),
34711
34825
  destinationLayoutPatterns
34712
34826
  );
34713
- const fragmentHtml = await farmApp.getServerRenderer().renderNavigationFragment({
34714
- PageComponent: routeModule.default,
34715
- LoadingComponent: loadingModule?.default,
34716
- pageProps: routeProps,
34717
- params,
34718
- layouts: layouts.map((layout2, index) => ({
34719
- pattern: layout2.pattern,
34720
- module: layoutModules[index]
34721
- })),
34722
- layoutStartIndex,
34723
- slots: routeSlots.map((slot) => ({
34724
- name: slot.name,
34725
- ownerPattern: slot.ownerPattern,
34726
- containerId: slot.containerId,
34727
- module: slot.renderModule,
34728
- props: slot.props
34729
- })),
34730
- pageShouldHydrate: shouldHydrate,
34731
- layoutShouldHydrate: shouldHydrateLayout,
34732
- islandStrategy: hydrationIslandStrategy
34733
- });
34827
+ const renderer = farmApp.getServerRenderer();
34828
+ const fragmentHtml = await _runWithMiddlewareData(
34829
+ middlewareMap,
34830
+ () => _runWithMiddlewareContext(
34831
+ middlewareContext,
34832
+ () => renderer.renderNavigationFragment({
34833
+ PageComponent: routeModule.default,
34834
+ LoadingComponent: loadingModule?.default,
34835
+ pageProps: routeProps,
34836
+ params,
34837
+ layouts: layouts.map((layout2, index) => ({
34838
+ pattern: layout2.pattern,
34839
+ module: layoutModules[index]
34840
+ })),
34841
+ layoutStartIndex,
34842
+ slots: routeSlots.map((slot) => ({
34843
+ name: slot.name,
34844
+ ownerPattern: slot.ownerPattern,
34845
+ containerId: slot.containerId,
34846
+ module: slot.renderModule,
34847
+ props: slot.props
34848
+ })),
34849
+ pageShouldHydrate: shouldHydrate,
34850
+ layoutShouldHydrate: shouldHydrateLayout,
34851
+ islandStrategy: hydrationIslandStrategy
34852
+ })
34853
+ )
34854
+ );
34734
34855
  const pageData = {
34735
34856
  props: {
34736
34857
  params: routeProps.params,
@@ -34740,7 +34861,9 @@ window.__FARM_MANIFEST__ = ${inlineValue({
34740
34861
  ...routeProps.__farmCanonicalPath ? {
34741
34862
  __farmCanonicalPath: routeProps.__farmCanonicalPath
34742
34863
  } : {},
34743
- ...routeProps.__farmRoutePropsResolved ? { __farmRoutePropsResolved: true } : {}
34864
+ ...routeProps.__farmRoutePropsResolved ? { __farmRoutePropsResolved: true } : {},
34865
+ // The same serialized shape a full load embeds in __FARM_PROPS__.
34866
+ ...middlewareMap.size > 0 ? { middleware: { data: Object.fromEntries(middlewareMap) } } : {}
34744
34867
  },
34745
34868
  canonicalPath: routeProps.__farmCanonicalPath,
34746
34869
  modulePath: toUrlPath(route.modulePath),
@@ -35490,6 +35613,26 @@ function runFarmMiddlewareWithNavigation(renderer, middlewareRequest, req, res,
35490
35613
  });
35491
35614
  }
35492
35615
  __name(runFarmMiddlewareWithNavigation, "runFarmMiddlewareWithNavigation");
35616
+ function createPageDataMiddlewareRequest(req, target) {
35617
+ const targetNodeRequest = Object.create(req);
35618
+ targetNodeRequest.url = `${target.pathname}${target.search}`;
35619
+ targetNodeRequest.originalUrl = targetNodeRequest.url;
35620
+ targetNodeRequest.method = "GET";
35621
+ return targetNodeRequest;
35622
+ }
35623
+ __name(createPageDataMiddlewareRequest, "createPageDataMiddlewareRequest");
35624
+ function resolveDevelopmentRoot(farmRoot, viteRoot) {
35625
+ if (!farmRoot) return viteRoot;
35626
+ if (path38.resolve(farmRoot) === path38.resolve(viteRoot)) return farmRoot;
35627
+ try {
35628
+ if (fs14.realpathSync(farmRoot) === fs14.realpathSync(viteRoot)) {
35629
+ return path38.resolve(viteRoot);
35630
+ }
35631
+ } catch {
35632
+ }
35633
+ return farmRoot;
35634
+ }
35635
+ __name(resolveDevelopmentRoot, "resolveDevelopmentRoot");
35493
35636
  function isFarmClientVirtualId(id) {
35494
35637
  const pathname = id.split("?", 1)[0];
35495
35638
  return pathname === "/@farm/client" || pathname === "/@farm/client.js";
@@ -35505,16 +35648,18 @@ function generateProgrammaticRouteModule(moduleId, root, renderer = REACT_RENDER
35505
35648
  return generateProgrammaticApiRouteModule(parsed.routePath, routeFile);
35506
35649
  }
35507
35650
  return `
35508
- import {
35509
- createElement as __farmCreateElement,
35510
- Suspense as __farmSuspense,
35511
- } from ${JSON.stringify(renderer.server)};
35651
+ import * as __farmRendererRuntime from ${JSON.stringify(renderer.server)};
35512
35652
  import {
35513
35653
  createLayoutModuleFromProgrammaticLayout as __farmCreateLayoutRouteModule,
35514
35654
  createRouteModuleFromProgrammaticPage as __farmCreatePageRouteModule,
35515
35655
  } from "@farm.js/core/routes";
35516
35656
  import * as __farmRoutesModule from ${JSON.stringify(routeFile)};
35517
35657
 
35658
+ const __farmCreateElement = __farmRendererRuntime.createElement;
35659
+ const __farmSuspense = __farmRendererRuntime.Suspense;
35660
+ // Optional hook: only renderers that need it export markFunctionComponent.
35661
+ const __farmMarkFunctionComponent = Reflect.get(__farmRendererRuntime, "markFunctionComponent");
35662
+
35518
35663
  const __farmIsRouteDefinition = (value) => (
35519
35664
  value &&
35520
35665
  typeof value === "object" &&
@@ -35568,6 +35713,7 @@ const __farmRouteModule = __farmRoute.kind === "layout"
35568
35713
  : __farmCreatePageRouteModule(__farmRoute, {
35569
35714
  createElement: __farmCreateElement,
35570
35715
  Suspense: __farmSuspense,
35716
+ markFunctionComponent: __farmMarkFunctionComponent,
35571
35717
  });
35572
35718
 
35573
35719
  export const metadata = __farmRouteModule.metadata;
@@ -37177,6 +37323,11 @@ async function hydrate() {
37177
37323
  pendingPageHydrationController = hydrationController;
37178
37324
  await hydrateFarmIsolatedClientBoundaries(rootContainer, hydrationController.signal);
37179
37325
  if (hydrationController.signal.aborted) return;
37326
+ // The rest of the document is static server HTML with nothing to hydrate, so
37327
+ // stop holding its clicks and submits once the load-strategy islands are live.
37328
+ // Deferred islands capture their own interactions, and held targets outside an
37329
+ // island are not replayed into DOM no client code owns.
37330
+ markFarmHydrated();
37180
37331
  return;
37181
37332
  }` : ""}
37182
37333
  if (!shouldHydrate) {