@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
@@ -31,6 +31,29 @@ 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 resolveEnv(config, source = getProcessEnv()) {
36
59
  const resolved = {
@@ -44,10 +67,12 @@ function createBundledEnv(env2, source = getProcessEnv()) {
44
67
  const server = {};
45
68
  const runtime3 = {};
46
69
  for (const [key, value] of Object.entries(resolved.server)) {
47
- if (source[key] === void 0) {
48
- server[key] = value;
70
+ const raw = source[key];
71
+ const type = getRuntimeEnvType(value);
72
+ if (raw !== void 0 && isSameEnvValue(coerceRuntimeEnvValue(raw, type), value)) {
73
+ runtime3[key] = type;
49
74
  } else {
50
- runtime3[key] = getRuntimeEnvType(value);
75
+ server[key] = value;
51
76
  }
52
77
  }
53
78
  return {
@@ -146,9 +171,8 @@ function readServerEnvKey(server, key) {
146
171
  function readRuntimeServerEnv(env2) {
147
172
  const state = env2[FARM_ENV_RUNTIME_SYMBOL];
148
173
  if (!state) return;
149
- const source = getProcessEnv();
150
174
  for (const [key, type] of Object.entries(state.pending)) {
151
- const raw = source[key];
175
+ const raw = readFarmEnvironmentValue(key);
152
176
  if (raw === void 0) continue;
153
177
  env2.server[key] = coerceRuntimeEnvValue(raw, type);
154
178
  delete state.pending[key];
@@ -179,6 +203,22 @@ function coerceRuntimeEnvValue(raw, type) {
179
203
  }
180
204
  return raw;
181
205
  }
206
+ function isSameEnvValue(left, right) {
207
+ if (Object.is(left, right)) return true;
208
+ if (Array.isArray(left) || Array.isArray(right)) {
209
+ return Array.isArray(left) && Array.isArray(right) && left.length === right.length && left.every((item, index) => isSameEnvValue(item, right[index]));
210
+ }
211
+ if (!isPlainObject(left) || !isPlainObject(right)) return false;
212
+ const keys = Object.keys(left);
213
+ return keys.length === Object.keys(right).length && keys.every(
214
+ (key) => Object.prototype.hasOwnProperty.call(right, key) && isSameEnvValue(left[key], right[key])
215
+ );
216
+ }
217
+ function isPlainObject(value) {
218
+ if (!value || typeof value !== "object") return false;
219
+ const prototype = Object.getPrototypeOf(value);
220
+ return prototype === Object.prototype || prototype === null;
221
+ }
182
222
  function prepareEnv(env2) {
183
223
  const normalized = normalizeResolvedEnv(env2);
184
224
  const runtime3 = env2.runtime?.server;
@@ -254,6 +294,7 @@ var FARM_ENV_SYMBOL, FARM_ENV_RUNTIME_SYMBOL, farmEnvGlobal, currentEnv, env, pu
254
294
  var init_env = __esm({
255
295
  "src/env.ts"() {
256
296
  "use strict";
297
+ init_runtime_env();
257
298
  FARM_ENV_SYMBOL = /* @__PURE__ */ Symbol.for("farm.env");
258
299
  FARM_ENV_RUNTIME_SYMBOL = /* @__PURE__ */ Symbol.for("farm.env.runtime");
259
300
  farmEnvGlobal = globalThis;
@@ -272,6 +313,8 @@ var init_env = __esm({
272
313
  __name(readRuntimeServerEnv, "readRuntimeServerEnv");
273
314
  __name(getRuntimeEnvType, "getRuntimeEnvType");
274
315
  __name(coerceRuntimeEnvValue, "coerceRuntimeEnvValue");
316
+ __name(isSameEnvValue, "isSameEnvValue");
317
+ __name(isPlainObject, "isPlainObject");
275
318
  __name(prepareEnv, "prepareEnv");
276
319
  __name(assertServerEnvAccess, "assertServerEnvAccess");
277
320
  __name(getInitialEnv, "getInitialEnv");
@@ -4354,8 +4397,16 @@ async function createMarkdownMirrorResponse(options) {
4354
4397
  if (!hasMarkdownExtension) {
4355
4398
  headersOut.set("Vary", "Accept");
4356
4399
  }
4400
+ for (const token of pageResponse.headers.get("vary")?.split(",") ?? []) {
4401
+ const name2 = token.trim();
4402
+ if (name2 && name2.toLowerCase() !== "accept") appendHeaderToken(headersOut, "Vary", name2);
4403
+ }
4404
+ const pageCacheControl = pageResponse.headers.get("cache-control");
4357
4405
  const cache = target.route?.cache ?? options.config?.cache ?? false;
4358
- headersOut.set("Cache-Control", createMarkdownCacheHeader(cache));
4406
+ headersOut.set(
4407
+ "Cache-Control",
4408
+ pageCacheControl && isPrivateCacheControl(pageCacheControl) ? pageCacheControl : createMarkdownCacheHeader(cache)
4409
+ );
4359
4410
  return new Response(options.request.method === "HEAD" ? null : markdown, {
4360
4411
  status: pageResponse.status,
4361
4412
  headers: headersOut
@@ -4506,6 +4557,17 @@ function isFarmMarkdownMirrorExposed(config, pathname) {
4506
4557
  function matchesFarmMarkdownRoutePattern(pattern, pathname) {
4507
4558
  return routeMatches(pattern, pathname);
4508
4559
  }
4560
+ function appendHeaderToken(headers, name2, token) {
4561
+ const current = headers.get(name2);
4562
+ if (!current) {
4563
+ headers.set(name2, token);
4564
+ return;
4565
+ }
4566
+ const tokens = current.split(",").map((value) => value.trim().toLowerCase());
4567
+ if (!tokens.includes(token.toLowerCase())) {
4568
+ headers.set(name2, `${current}, ${token}`);
4569
+ }
4570
+ }
4509
4571
  function findExposedMarkdownRoute(config, pathname) {
4510
4572
  if (config.expose === true) {
4511
4573
  return null;
@@ -4537,6 +4599,12 @@ function isHtmlResponse(response) {
4537
4599
  const contentType = response.headers.get("content-type") ?? "";
4538
4600
  return contentType.includes("text/html");
4539
4601
  }
4602
+ function isPrivateCacheControl(value) {
4603
+ return value.split(",").some((directive) => {
4604
+ const name2 = directive.split("=", 1)[0].trim().toLowerCase();
4605
+ return name2 === "private" || name2 === "no-store";
4606
+ });
4607
+ }
4540
4608
  function createMarkdownCacheHeader(cache) {
4541
4609
  if (cache === false || cache <= 0) {
4542
4610
  return "no-store";
@@ -4689,9 +4757,11 @@ var init_markdown = __esm({
4689
4757
  __name(getFarmMarkdownAlternatePath, "getFarmMarkdownAlternatePath");
4690
4758
  __name(isFarmMarkdownMirrorExposed, "isFarmMarkdownMirrorExposed");
4691
4759
  __name(matchesFarmMarkdownRoutePattern, "matchesFarmMarkdownRoutePattern");
4760
+ __name(appendHeaderToken, "appendHeaderToken");
4692
4761
  __name(findExposedMarkdownRoute, "findExposedMarkdownRoute");
4693
4762
  __name(routeMatches, "routeMatches");
4694
4763
  __name(isHtmlResponse, "isHtmlResponse");
4764
+ __name(isPrivateCacheControl, "isPrivateCacheControl");
4695
4765
  __name(createMarkdownCacheHeader, "createMarkdownCacheHeader");
4696
4766
  __name(extractHtmlTitle, "extractHtmlTitle");
4697
4767
  __name(extractHtmlBody, "extractHtmlBody");
@@ -4767,29 +4837,6 @@ var init_secret_compare = __esm({
4767
4837
  }
4768
4838
  });
4769
4839
 
4770
- // src/utils/runtime-env.ts
4771
- function getFarmRuntimeBindings() {
4772
- const runtimeBindings = globalThis.__env__;
4773
- return runtimeBindings && typeof runtimeBindings === "object" ? runtimeBindings : void 0;
4774
- }
4775
- function readFarmEnvironmentValue(name2) {
4776
- const runtimeValue = getFarmRuntimeBindings()?.[name2];
4777
- if (typeof runtimeValue === "string") return runtimeValue;
4778
- return typeof process !== "undefined" ? process.env?.[name2] : void 0;
4779
- }
4780
- function isFarmDeployedRuntime() {
4781
- if (getFarmRuntimeBindings()) return true;
4782
- return readFarmEnvironmentValue("NODE_ENV") === "production";
4783
- }
4784
- var init_runtime_env = __esm({
4785
- "src/utils/runtime-env.ts"() {
4786
- "use strict";
4787
- __name(getFarmRuntimeBindings, "getFarmRuntimeBindings");
4788
- __name(readFarmEnvironmentValue, "readFarmEnvironmentValue");
4789
- __name(isFarmDeployedRuntime, "isFarmDeployedRuntime");
4790
- }
4791
- });
4792
-
4793
4840
  // src/utils.ts
4794
4841
  function parseRoutePath(filePath) {
4795
4842
  const segments = [];
@@ -6871,7 +6918,7 @@ function mergeFarmLayerConfig(base, override) {
6871
6918
  output[key] = mergeConfigListResolvers(output[key], value);
6872
6919
  continue;
6873
6920
  }
6874
- if (isPlainObject(output[key]) && isPlainObject(value)) {
6921
+ if (isPlainObject2(output[key]) && isPlainObject2(value)) {
6875
6922
  output[key] = mergePlainObjects(output[key], value);
6876
6923
  continue;
6877
6924
  }
@@ -6883,7 +6930,7 @@ function mergePlainObjects(base, override) {
6883
6930
  const output = { ...base };
6884
6931
  for (const [key, value] of Object.entries(override)) {
6885
6932
  if (value === void 0) continue;
6886
- output[key] = isPlainObject(output[key]) && isPlainObject(value) ? mergePlainObjects(output[key], value) : value;
6933
+ output[key] = isPlainObject2(output[key]) && isPlainObject2(value) ? mergePlainObjects(output[key], value) : value;
6887
6934
  }
6888
6935
  return output;
6889
6936
  }
@@ -6898,7 +6945,7 @@ function toArray(value) {
6898
6945
  if (value === void 0 || value === null) return [];
6899
6946
  return Array.isArray(value) ? value : [value];
6900
6947
  }
6901
- function isPlainObject(value) {
6948
+ function isPlainObject2(value) {
6902
6949
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
6903
6950
  const prototype = Object.getPrototypeOf(value);
6904
6951
  return prototype === Object.prototype || prototype === null;
@@ -6975,7 +7022,7 @@ var init_layers = __esm({
6975
7022
  __name(mergeConfigListResolvers, "mergeConfigListResolvers");
6976
7023
  __name(resolveConfigList, "resolveConfigList");
6977
7024
  __name(toArray, "toArray");
6978
- __name(isPlainObject, "isPlainObject");
7025
+ __name(isPlainObject2, "isPlainObject");
6979
7026
  __name(isPathLayerSource, "isPathLayerSource");
6980
7027
  __name(normalizeRealPath, "normalizeRealPath");
6981
7028
  }
@@ -12057,6 +12104,8 @@ var init_cache = __esm({
12057
12104
  constructor(config = {}) {
12058
12105
  this.entries = /* @__PURE__ */ new Map();
12059
12106
  this.inflight = /* @__PURE__ */ new Map();
12107
+ /** Local entries by tag, so tag counts and pruning never scan unrelated entries. */
12108
+ this.entriesByTag = /* @__PURE__ */ new Map();
12060
12109
  this.invalidatedTagVersions = /* @__PURE__ */ new Map();
12061
12110
  this.activeGenerations = /* @__PURE__ */ new Set();
12062
12111
  this.version = 0;
@@ -12075,6 +12124,7 @@ var init_cache = __esm({
12075
12124
  configure(config = {}) {
12076
12125
  this.generation++;
12077
12126
  this.entries.clear();
12127
+ this.entriesByTag.clear();
12078
12128
  this.inflight.clear();
12079
12129
  this.invalidatedTagVersions.clear();
12080
12130
  this.activeGenerations.clear();
@@ -12241,14 +12291,12 @@ var init_cache = __esm({
12241
12291
  return entry;
12242
12292
  }
12243
12293
  delete(key) {
12244
- const deleted = this.entries.delete(key);
12245
- if (deleted) this.pruneInvalidatedTagVersions();
12294
+ const deleted = this.deleteLocalEntry(key);
12246
12295
  emitFarmEvent({ type: "cache.delete", key, deleted });
12247
12296
  return deleted;
12248
12297
  }
12249
12298
  async deleteAsync(key) {
12250
- const deleted = this.entries.delete(key);
12251
- if (deleted) this.pruneInvalidatedTagVersions();
12299
+ const deleted = this.deleteLocalEntry(key);
12252
12300
  if (this.adapter) {
12253
12301
  await this.adapter.delete(this.createAdapterKey(key));
12254
12302
  }
@@ -12259,6 +12307,7 @@ var init_cache = __esm({
12259
12307
  const count = this.entries.size;
12260
12308
  this.generation++;
12261
12309
  this.entries.clear();
12310
+ this.entriesByTag.clear();
12262
12311
  this.inflight.clear();
12263
12312
  this.invalidatedTagVersions.clear();
12264
12313
  this.activeGenerations.clear();
@@ -12344,23 +12393,32 @@ var init_cache = __esm({
12344
12393
  return cached.value;
12345
12394
  }
12346
12395
  const inflight = this.inflight.get(key);
12347
- if (inflight) {
12396
+ if (inflight && !this.wasInvalidatedSince(inflight.tags, inflight.startVersion)) {
12348
12397
  emitFarmEvent({ type: "cache.dedupe", key });
12349
- return inflight;
12398
+ return inflight.promise;
12350
12399
  }
12351
12400
  const tags = Array.from(normalizeCacheOptionsTags(options));
12352
12401
  const generation = this.generation;
12402
+ const startVersion = this.version;
12353
12403
  const promise = this.fillCacheEntry(key, producer, options, tags, generation).catch((error) => {
12354
12404
  emitFarmEvent({ type: "cache.error", key, operation: "set", error });
12355
12405
  throw error;
12356
12406
  }).finally(() => {
12357
- if (this.inflight.get(key) === promise) {
12407
+ if (this.inflight.get(key)?.promise === promise) {
12358
12408
  this.inflight.delete(key);
12359
12409
  }
12360
12410
  });
12361
- this.inflight.set(key, promise);
12411
+ this.inflight.set(key, { promise, tags, startVersion });
12362
12412
  return promise;
12363
12413
  }
12414
+ /** A fill that started before one of its tags was invalidated cannot satisfy later readers. */
12415
+ wasInvalidatedSince(tags, version2) {
12416
+ for (const tag of tags) {
12417
+ const invalidatedVersion = this.invalidatedTagVersions.get(tag);
12418
+ if (invalidatedVersion !== void 0 && invalidatedVersion > version2) return true;
12419
+ }
12420
+ return false;
12421
+ }
12364
12422
  async fillCacheEntry(key, producer, options, tags, generation) {
12365
12423
  const adapter = this.adapter;
12366
12424
  const namespace = this.namespace;
@@ -12401,7 +12459,7 @@ var init_cache = __esm({
12401
12459
  return value;
12402
12460
  } finally {
12403
12461
  this.activeGenerations.delete(activeGeneration);
12404
- this.pruneInvalidatedTagVersions();
12462
+ this.pruneInvalidatedTagVersions(activeGeneration.tags);
12405
12463
  if (leaseToken && adapter?.releaseLease) {
12406
12464
  try {
12407
12465
  await adapter.releaseLease(leaseKey, leaseToken);
@@ -12446,18 +12504,9 @@ var init_cache = __esm({
12446
12504
  }
12447
12505
  return void 0;
12448
12506
  }
12449
- countEntriesForTag(tag) {
12450
- let count = 0;
12451
- for (const entry of this.entries.values()) {
12452
- if (entry.tags.has(tag)) {
12453
- count++;
12454
- }
12455
- }
12456
- return count;
12457
- }
12458
12507
  countEntriesForTags(tags) {
12459
12508
  let count = 0;
12460
- for (const entry of this.entries.values()) {
12509
+ for (const entry of this.entriesByTag.get(tags[0]) ?? []) {
12461
12510
  if (tags.every((tag) => entry.tags.has(tag))) {
12462
12511
  count++;
12463
12512
  }
@@ -12465,10 +12514,10 @@ var init_cache = __esm({
12465
12514
  return count;
12466
12515
  }
12467
12516
  invalidateTag(normalizedTag) {
12468
- const count = this.countEntriesForTag(normalizedTag);
12517
+ const count = this.entriesByTag.get(normalizedTag)?.size ?? 0;
12469
12518
  this.invalidatedTagVersions.delete(normalizedTag);
12470
12519
  this.invalidatedTagVersions.set(normalizedTag, ++this.version);
12471
- this.pruneInvalidatedTagVersions();
12520
+ this.pruneInvalidatedTagVersions([normalizedTag]);
12472
12521
  return count;
12473
12522
  }
12474
12523
  toPublicEntry(entry) {
@@ -12498,19 +12547,51 @@ var init_cache = __esm({
12498
12547
  this.entries.set(key, entry);
12499
12548
  }
12500
12549
  storeLocalEntry(entry) {
12501
- this.entries.delete(entry.key);
12550
+ const removed = [];
12551
+ const replaced = this.detachLocalEntry(entry.key);
12552
+ if (replaced) removed.push(replaced);
12502
12553
  this.entries.set(entry.key, entry);
12554
+ for (const tag of entry.tags) {
12555
+ let tagged = this.entriesByTag.get(tag);
12556
+ if (!tagged) this.entriesByTag.set(tag, tagged = /* @__PURE__ */ new Set());
12557
+ tagged.add(entry);
12558
+ }
12503
12559
  while (this.entries.size > this.maxEntries) {
12504
12560
  const oldestKey = this.entries.keys().next().value;
12505
12561
  if (oldestKey === void 0) break;
12506
- this.entries.delete(oldestKey);
12562
+ removed.push(this.detachLocalEntry(oldestKey));
12507
12563
  }
12508
- this.pruneInvalidatedTagVersions();
12564
+ for (const removedEntry of removed) this.pruneInvalidatedTagVersions(removedEntry.tags);
12509
12565
  }
12510
- pruneInvalidatedTagVersions() {
12511
- tags: for (const [tag, invalidatedVersion] of this.invalidatedTagVersions) {
12512
- for (const entry of this.entries.values()) {
12513
- if (entry.tags.has(tag) && entry.createdVersion < invalidatedVersion) continue tags;
12566
+ deleteLocalEntry(key) {
12567
+ const entry = this.detachLocalEntry(key);
12568
+ if (!entry) return false;
12569
+ this.pruneInvalidatedTagVersions(entry.tags);
12570
+ return true;
12571
+ }
12572
+ detachLocalEntry(key) {
12573
+ const entry = this.entries.get(key);
12574
+ if (!entry) return void 0;
12575
+ this.entries.delete(key);
12576
+ for (const tag of entry.tags) {
12577
+ const tagged = this.entriesByTag.get(tag);
12578
+ if (!tagged) continue;
12579
+ tagged.delete(entry);
12580
+ if (tagged.size === 0) this.entriesByTag.delete(tag);
12581
+ }
12582
+ return entry;
12583
+ }
12584
+ /**
12585
+ * Drop invalidation versions that no local entry or active fill can be stale against.
12586
+ * Callers pass only the tags whose dependents just changed, so the cost is bounded by
12587
+ * the entries sharing those tags rather than by the whole cache.
12588
+ */
12589
+ pruneInvalidatedTagVersions(tags) {
12590
+ tags: for (const tag of tags) {
12591
+ const invalidatedVersion = this.invalidatedTagVersions.get(tag);
12592
+ if (invalidatedVersion === void 0) continue;
12593
+ for (const entry of this.entriesByTag.get(tag) ?? []) {
12594
+ if (entry.createdVersion < invalidatedVersion) continue tags;
12514
12595
  }
12515
12596
  for (const generation of this.activeGenerations) {
12516
12597
  if (generation.tags.has(tag) && generation.createdVersion < invalidatedVersion)
@@ -12905,6 +12986,7 @@ function createProgrammaticPageComponent(route, rendererRuntime) {
12905
12986
  }
12906
12987
  return rendererRuntime.createElement(...args);
12907
12988
  }, "createElement");
12989
+ const markFunctionComponent = /* @__PURE__ */ __name((component) => rendererRuntime?.markFunctionComponent?.(component) ?? component, "markFunctionComponent");
12908
12990
  const Component = route.component;
12909
12991
  if (route.pending) {
12910
12992
  const PendingComponent = route.pending;
@@ -12926,7 +13008,9 @@ function createProgrammaticPageComponent(route, rendererRuntime) {
12926
13008
  throw error;
12927
13009
  }
12928
13010
  }, "FarmProgrammaticPageContent");
12929
- const PageContent = FarmProgrammaticPageContent2;
13011
+ const PageContent = markFunctionComponent(
13012
+ FarmProgrammaticPageContent2
13013
+ );
12930
13014
  const FarmProgrammaticPage = /* @__PURE__ */ __name(function FarmProgrammaticPage2(props) {
12931
13015
  return createElement2(
12932
13016
  rendererRuntime.Suspense,
@@ -12936,7 +13020,7 @@ function createProgrammaticPageComponent(route, rendererRuntime) {
12936
13020
  createElement2(PageContent, props)
12937
13021
  );
12938
13022
  }, "FarmProgrammaticPage");
12939
- return FarmProgrammaticPage;
13023
+ return markFunctionComponent(FarmProgrammaticPage);
12940
13024
  }
12941
13025
  const FarmProgrammaticPageContent = /* @__PURE__ */ __name(async function FarmProgrammaticPageContent2(props) {
12942
13026
  try {
@@ -12955,7 +13039,7 @@ function createProgrammaticPageComponent(route, rendererRuntime) {
12955
13039
  throw error;
12956
13040
  }
12957
13041
  }, "FarmProgrammaticPageContent");
12958
- return FarmProgrammaticPageContent;
13042
+ return markFunctionComponent(FarmProgrammaticPageContent);
12959
13043
  }
12960
13044
  function readProgrammaticRouteProps(route, props, resources) {
12961
13045
  if (isProgrammaticRoutePropsResolved(props)) {
@@ -14615,7 +14699,7 @@ function resolveImportedModule(importerPath, specifier, root) {
14615
14699
  return { path: resolveImportedModuleSourcePath(importerPath, specifier, root), local: true };
14616
14700
  }
14617
14701
  const aliased = resolveProjectAliasSourcePath(specifier, root);
14618
- if (aliased !== void 0) return { path: aliased, local: true };
14702
+ if (aliased) return { path: aliased, local: true };
14619
14703
  return { path: resolvePackageModuleSourcePath(importerPath, specifier, root), local: false };
14620
14704
  }
14621
14705
  function resolveProjectAliasSourcePath(specifier, root) {
@@ -14628,11 +14712,12 @@ function resolveProjectAliasSourcePath(specifier, root) {
14628
14712
  if (!match || alias.prefix.length > match.alias.prefix.length) match = { alias, captured };
14629
14713
  }
14630
14714
  if (!match) return void 0;
14631
- return resolveSourceCandidate(
14715
+ const resolved = resolveSourceCandidate(
14632
14716
  match.alias.targets.map(
14633
14717
  (target) => import_path5.default.normalize(match.alias.wildcard ? target.replace("*", match.captured) : target)
14634
14718
  )
14635
14719
  );
14720
+ return resolved && /\.d\.[cm]?ts$/.test(resolved) ? null : resolved;
14636
14721
  }
14637
14722
  function matchProjectImportAlias(alias, specifier) {
14638
14723
  if (!alias.wildcard) return specifier === alias.prefix ? "" : null;
@@ -15352,6 +15437,7 @@ var init_route_manager = __esm({
15352
15437
  init_static_metadata_image();
15353
15438
  init_route_runtime();
15354
15439
  init_routing();
15440
+ init_base_path();
15355
15441
  init_redirect_query();
15356
15442
  init_route_slots();
15357
15443
  init_renderer();
@@ -16333,7 +16419,7 @@ var init_route_manager = __esm({
16333
16419
  }
16334
16420
  toRoutePathname(pathname) {
16335
16421
  const i18n = this.getI18nConfig();
16336
- return i18n ? stripFarmLocaleFromPathname(pathname, i18n) : pathname;
16422
+ return i18n ? stripFarmLocaleFromPathname(pathname, i18n) : stripFarmBasePath(pathname, this.config.basePath);
16337
16423
  }
16338
16424
  localizeRedirectDestination(destination, locale) {
16339
16425
  if (!locale || !destination.startsWith("/") || destination.startsWith("//")) {
@@ -17454,7 +17540,7 @@ async function readFarmI18nCatalogs(config) {
17454
17540
  return { catalogs, signatures };
17455
17541
  }
17456
17542
  function flattenFarmI18nCatalog(input, source = "i18n catalog") {
17457
- if (!isPlainObject2(input)) {
17543
+ if (!isPlainObject3(input)) {
17458
17544
  throw new Error(`${source} must contain a JSON object at its root.`);
17459
17545
  }
17460
17546
  const output = {};
@@ -17468,7 +17554,7 @@ function flattenFarmI18nCatalog(input, source = "i18n catalog") {
17468
17554
  output[key] = value;
17469
17555
  return;
17470
17556
  }
17471
- if (!isPlainObject2(value)) {
17557
+ if (!isPlainObject3(value)) {
17472
17558
  const key = segments.join(".") || "<root>";
17473
17559
  throw new Error(`${source} message "${key}" must be a string or nested object.`);
17474
17560
  }
@@ -17562,7 +17648,7 @@ function sameSignature(expected, actual) {
17562
17648
  const actualEntries = Object.entries(actual).sort(([a], [b]) => a.localeCompare(b));
17563
17649
  return JSON.stringify(expectedEntries) === JSON.stringify(actualEntries);
17564
17650
  }
17565
- function isPlainObject2(value) {
17651
+ function isPlainObject3(value) {
17566
17652
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
17567
17653
  }
17568
17654
  function messageOf(error) {
@@ -17582,7 +17668,7 @@ var init_catalog = __esm({
17582
17668
  __name(collectArguments, "collectArguments");
17583
17669
  __name(addArgument, "addArgument");
17584
17670
  __name(sameSignature, "sameSignature");
17585
- __name(isPlainObject2, "isPlainObject");
17671
+ __name(isPlainObject3, "isPlainObject");
17586
17672
  __name(messageOf, "messageOf");
17587
17673
  }
17588
17674
  });
@@ -20478,7 +20564,7 @@ var init_server3 = __esm({
20478
20564
  var version;
20479
20565
  var init_package = __esm({
20480
20566
  "package.json"() {
20481
- version = "0.1.16";
20567
+ version = "0.1.17";
20482
20568
  }
20483
20569
  });
20484
20570
 
@@ -20906,7 +20992,7 @@ function createPPRRefreshScript() {
20906
20992
  }
20907
20993
  function createPreHydrationClickQueueScript() {
20908
20994
  const selector = JSON.stringify(FARM_ISLAND_REPLAYABLE_SELECTOR);
20909
- 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>`;
20995
+ 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>`;
20910
20996
  }
20911
20997
  function createDocumentFooter(options) {
20912
20998
  return `</div>
@@ -23744,7 +23830,7 @@ function createEndpoint(pathOrOptions, optionsOrHandler, maybeHandler) {
23744
23830
  wrappedHandler
23745
23831
  );
23746
23832
  endpoint.__path = path47 || void 0;
23747
- endpoint.__method = options.method || "GET";
23833
+ endpoint.__method = options.method || (path47 ? "GET" : void 0);
23748
23834
  endpoint.__autoPath = !path47;
23749
23835
  endpoint.__handler = wrappedHandler;
23750
23836
  endpoint.__farmInvoke = (ctx) => runEndpointMiddleware(middleware, ctx, handler, error, options.invalidates);
@@ -24547,6 +24633,7 @@ var init_runtime2 = __esm({
24547
24633
  init_response_body();
24548
24634
  init_route_shape();
24549
24635
  init_route_schema();
24636
+ init_endpoint();
24550
24637
  init_plugin_route_runtime();
24551
24638
  init_route_pattern2();
24552
24639
  init_route_pattern2();
@@ -27808,6 +27895,7 @@ function createFarmDocsHandler(docs, options) {
27808
27895
  if (!isFarmDocsRequest(docs, request2)) return null;
27809
27896
  const page2 = loadPage(contentDir, docs, request2);
27810
27897
  if (!page2) return null;
27898
+ const negotiatesAccept = !requestUrl.pathname.endsWith(".md");
27811
27899
  if (shouldReturnMarkdown(request2)) {
27812
27900
  const origin = new URL(request2.url).origin;
27813
27901
  return omitFarmDocsHeadBody(
@@ -27822,7 +27910,8 @@ function createFarmDocsHandler(docs, options) {
27822
27910
  status: 200,
27823
27911
  headers: {
27824
27912
  "Content-Type": "text/markdown; charset=utf-8",
27825
- "Cache-Control": "public, max-age=60"
27913
+ "Cache-Control": "public, max-age=60",
27914
+ ...negotiatesAccept ? { Vary: "Accept" } : {}
27826
27915
  }
27827
27916
  }
27828
27917
  )
@@ -27852,6 +27941,7 @@ function createFarmDocsHandler(docs, options) {
27852
27941
  headers: {
27853
27942
  "Content-Type": "text/html; charset=utf-8",
27854
27943
  "Cache-Control": "public, s-maxage=60, stale-while-revalidate=300",
27944
+ Vary: "Accept",
27855
27945
  ...fontPreloadHeader ? { Link: fontPreloadHeader } : {}
27856
27946
  }
27857
27947
  }
@@ -28796,6 +28886,66 @@ function mergeFarmViteConfig(farmConfig, userConfig = {}) {
28796
28886
  }
28797
28887
  };
28798
28888
  }
28889
+ function mergeExternal(farmValue, userValue) {
28890
+ if (farmValue === void 0) return userValue;
28891
+ if (userValue === void 0) return farmValue;
28892
+ if (farmValue === true || userValue === true) return true;
28893
+ return Array.from(/* @__PURE__ */ new Set([...farmValue, ...userValue]));
28894
+ }
28895
+ function mergeFarmProductionViteConfig(farmConfig, userConfig = {}) {
28896
+ const {
28897
+ plugins: _plugins,
28898
+ root: _root,
28899
+ base: _base,
28900
+ mode: _mode,
28901
+ appType: _appType,
28902
+ publicDir: _publicDir,
28903
+ build: userBuild = {},
28904
+ css: userCss,
28905
+ define: userDefine,
28906
+ esbuild: userEsbuild,
28907
+ ...shared2
28908
+ } = userConfig;
28909
+ const {
28910
+ outDir: _outDir,
28911
+ emptyOutDir: _emptyOutDir,
28912
+ ssr: _ssr,
28913
+ ssrEmitAssets: _ssrEmitAssets,
28914
+ write: _write,
28915
+ lib: _lib,
28916
+ watch: _watch,
28917
+ rollupOptions: userRollupOptions,
28918
+ rolldownOptions: userRolldownOptions,
28919
+ ...userBuildOptions
28920
+ } = userBuild;
28921
+ const {
28922
+ input: _input,
28923
+ output: _output,
28924
+ ...userBundlerOptions
28925
+ } = {
28926
+ ...userRollupOptions,
28927
+ ...userRolldownOptions
28928
+ };
28929
+ const merged = mergeFarmViteConfig(farmConfig, shared2);
28930
+ return {
28931
+ ...merged,
28932
+ build: {
28933
+ ...userBuildOptions,
28934
+ ...farmConfig.build,
28935
+ rollupOptions: {
28936
+ ...userBundlerOptions,
28937
+ ...farmConfig.build?.rollupOptions
28938
+ }
28939
+ },
28940
+ css: farmConfig.css || userCss ? { ...farmConfig.css, ...userCss } : void 0,
28941
+ define: farmConfig.define || userDefine ? { ...userDefine, ...farmConfig.define } : void 0,
28942
+ esbuild: typeof userEsbuild === "object" && farmConfig.esbuild !== false ? { ...userEsbuild, ...farmConfig.esbuild } : farmConfig.esbuild ?? userEsbuild,
28943
+ ssr: {
28944
+ ...merged.ssr,
28945
+ external: mergeExternal(farmConfig.ssr?.external, userConfig.ssr?.external)
28946
+ }
28947
+ };
28948
+ }
28799
28949
  var import_node_path21, FARM_CLIENT_ENTRY_PATTERN, FARM_CLIENT_OPTIMIZE_DEPS_INCLUDE;
28800
28950
  var init_vite_config = __esm({
28801
28951
  "src/server/vite-config.ts"() {
@@ -28824,6 +28974,8 @@ var init_vite_config = __esm({
28824
28974
  __name(mergeNoExternal, "mergeNoExternal");
28825
28975
  __name(mergeAlias, "mergeAlias");
28826
28976
  __name(mergeFarmViteConfig, "mergeFarmViteConfig");
28977
+ __name(mergeExternal, "mergeExternal");
28978
+ __name(mergeFarmProductionViteConfig, "mergeFarmProductionViteConfig");
28827
28979
  }
28828
28980
  });
28829
28981
 
@@ -30446,7 +30598,7 @@ function parseColonParam(segment) {
30446
30598
  modifier
30447
30599
  };
30448
30600
  }
30449
- function compilePathPattern(pattern) {
30601
+ function compilePathPattern(pattern, trailingSlash = false) {
30450
30602
  const params = [];
30451
30603
  const segments = pattern.split("/").filter(Boolean);
30452
30604
  if (segments.length === 0) {
@@ -30482,10 +30634,16 @@ function compilePathPattern(pattern) {
30482
30634
  });
30483
30635
  return {
30484
30636
  kind: "path",
30485
- regex: new RegExp(`^${parts.join("")}$`),
30637
+ regex: new RegExp(`^${parts.join("")}${trailingSlash ? "/?" : ""}$`),
30486
30638
  params
30487
30639
  };
30488
30640
  }
30641
+ function compileMatcherPattern(pattern) {
30642
+ if (typeof pattern === "string" && pattern !== "*" && !pattern.endsWith("(.*)")) {
30643
+ return compilePathPattern(pattern, true);
30644
+ }
30645
+ return compilePattern(pattern);
30646
+ }
30489
30647
  function compilePattern(pattern) {
30490
30648
  if (pattern instanceof RegExp) {
30491
30649
  return { kind: "regexp", regex: pattern };
@@ -30504,7 +30662,7 @@ function compilePattern(pattern) {
30504
30662
  function compileMiddlewareConfig(config) {
30505
30663
  const compiled = {
30506
30664
  matcher: config.matcher ? toMatcherList(config.matcher).map(
30507
- (matcher) => typeof matcher === "function" ? matcher : compilePattern(matcher)
30665
+ (matcher) => typeof matcher === "function" ? matcher : compileMatcherPattern(matcher)
30508
30666
  ) : void 0,
30509
30667
  exclude: config.exclude?.map(compilePattern)
30510
30668
  };
@@ -30592,6 +30750,7 @@ var init_matcher = __esm({
30592
30750
  __name(escapeRegex, "escapeRegex");
30593
30751
  __name(parseColonParam, "parseColonParam");
30594
30752
  __name(compilePathPattern, "compilePathPattern");
30753
+ __name(compileMatcherPattern, "compileMatcherPattern");
30595
30754
  __name(compilePattern, "compilePattern");
30596
30755
  __name(compileMiddlewareConfig, "compileMiddlewareConfig");
30597
30756
  __name(matchPattern, "matchPattern");
@@ -36825,8 +36984,8 @@ function farmPlugin(options = {}, initialPluginManager) {
36825
36984
  }, "emitPluginError");
36826
36985
  farmApp = new FarmApp(
36827
36986
  {
36828
- root: server.config.root,
36829
- ...options
36987
+ ...options,
36988
+ root: resolveDevelopmentRoot(options.root, server.config.root)
36830
36989
  },
36831
36990
  server
36832
36991
  );
@@ -37413,7 +37572,8 @@ window.__FARM_MANIFEST__ = ${inlineValue({
37413
37572
  () => middlewareManager.execute(req, res)
37414
37573
  );
37415
37574
  }, "runAppMiddlewareForContentRoute");
37416
- if (openAPIManager && options.openapi?.specRoute && requestPathname === options.openapi.specRoute) {
37575
+ const openAPIRequestPathname = openAPIManager ? stripFarmBasePath(requestPathname, farmConfig.basePath) : requestPathname;
37576
+ if (openAPIManager && options.openapi?.specRoute && openAPIRequestPathname === options.openapi.specRoute) {
37417
37577
  if (await runAppMiddlewareForContentRoute()) return;
37418
37578
  if (requestMethod !== "GET" && requestMethod !== "HEAD") {
37419
37579
  res.statusCode = 405;
@@ -37430,7 +37590,7 @@ window.__FARM_MANIFEST__ = ${inlineValue({
37430
37590
  res.end(requestMethod === "HEAD" ? void 0 : body);
37431
37591
  return;
37432
37592
  }
37433
- if (openAPIManager && requestPathname === options.openapi?.route) {
37593
+ if (openAPIManager && openAPIRequestPathname === options.openapi?.route) {
37434
37594
  if (await runAppMiddlewareForContentRoute()) return;
37435
37595
  const docsHandler = openAPIManager.getDocsRouteHandler(parsedRequestUrl.origin);
37436
37596
  return docsHandler(req, res);
@@ -37908,6 +38068,21 @@ window.__FARM_MANIFEST__ = ${inlineValue({
37908
38068
  headers: request2.headers,
37909
38069
  signal: request2.signal
37910
38070
  });
38071
+ let middlewareMap = /* @__PURE__ */ new Map();
38072
+ let middlewareContext = /* @__PURE__ */ new Map();
38073
+ if (middlewareManager?.hasMiddleware()) {
38074
+ const targetNodeRequest = createPageDataMiddlewareRequest(req, targetRequestUrl);
38075
+ const handled = await runFarmMiddlewareWithNavigation(
38076
+ farmApp.getServerRenderer(),
38077
+ targetRequest,
38078
+ targetNodeRequest,
38079
+ res,
38080
+ () => middlewareManager.execute(targetNodeRequest, res)
38081
+ );
38082
+ if (handled) return;
38083
+ middlewareMap = targetNodeRequest.__FARM_MIDDLEWARE_DATA__ ?? middlewareMap;
38084
+ middlewareContext = targetNodeRequest.__FARM_MIDDLEWARE_CONTEXT__ ?? middlewareContext;
38085
+ }
37911
38086
  await farmApp.getServerRenderer().runWithRequestContext(targetRequest, async () => {
37912
38087
  const routeManager3 = farmApp.getRouteManager();
37913
38088
  if (pm) {
@@ -37981,7 +38156,8 @@ window.__FARM_MANIFEST__ = ${inlineValue({
37981
38156
  {
37982
38157
  params,
37983
38158
  searchParams: Promise.resolve(searchParams),
37984
- path: targetUrl.pathname
38159
+ path: targetUrl.pathname,
38160
+ middleware: middlewareMap.size > 0 ? { data: middlewareMap } : void 0
37985
38161
  },
37986
38162
  routeContext
37987
38163
  ),
@@ -38069,27 +38245,34 @@ window.__FARM_MANIFEST__ = ${inlineValue({
38069
38245
  parseFarmLayoutChainHeader(request2.headers.get("x-farm-layout-chain")),
38070
38246
  destinationLayoutPatterns
38071
38247
  );
38072
- const fragmentHtml = await farmApp.getServerRenderer().renderNavigationFragment({
38073
- PageComponent: routeModule.default,
38074
- LoadingComponent: loadingModule?.default,
38075
- pageProps: routeProps,
38076
- params,
38077
- layouts: layouts.map((layout2, index) => ({
38078
- pattern: layout2.pattern,
38079
- module: layoutModules[index]
38080
- })),
38081
- layoutStartIndex,
38082
- slots: routeSlots.map((slot) => ({
38083
- name: slot.name,
38084
- ownerPattern: slot.ownerPattern,
38085
- containerId: slot.containerId,
38086
- module: slot.renderModule,
38087
- props: slot.props
38088
- })),
38089
- pageShouldHydrate: shouldHydrate,
38090
- layoutShouldHydrate: shouldHydrateLayout,
38091
- islandStrategy: hydrationIslandStrategy
38092
- });
38248
+ const renderer = farmApp.getServerRenderer();
38249
+ const fragmentHtml = await _runWithMiddlewareData(
38250
+ middlewareMap,
38251
+ () => _runWithMiddlewareContext(
38252
+ middlewareContext,
38253
+ () => renderer.renderNavigationFragment({
38254
+ PageComponent: routeModule.default,
38255
+ LoadingComponent: loadingModule?.default,
38256
+ pageProps: routeProps,
38257
+ params,
38258
+ layouts: layouts.map((layout2, index) => ({
38259
+ pattern: layout2.pattern,
38260
+ module: layoutModules[index]
38261
+ })),
38262
+ layoutStartIndex,
38263
+ slots: routeSlots.map((slot) => ({
38264
+ name: slot.name,
38265
+ ownerPattern: slot.ownerPattern,
38266
+ containerId: slot.containerId,
38267
+ module: slot.renderModule,
38268
+ props: slot.props
38269
+ })),
38270
+ pageShouldHydrate: shouldHydrate,
38271
+ layoutShouldHydrate: shouldHydrateLayout,
38272
+ islandStrategy: hydrationIslandStrategy
38273
+ })
38274
+ )
38275
+ );
38093
38276
  const pageData = {
38094
38277
  props: {
38095
38278
  params: routeProps.params,
@@ -38099,7 +38282,9 @@ window.__FARM_MANIFEST__ = ${inlineValue({
38099
38282
  ...routeProps.__farmCanonicalPath ? {
38100
38283
  __farmCanonicalPath: routeProps.__farmCanonicalPath
38101
38284
  } : {},
38102
- ...routeProps.__farmRoutePropsResolved ? { __farmRoutePropsResolved: true } : {}
38285
+ ...routeProps.__farmRoutePropsResolved ? { __farmRoutePropsResolved: true } : {},
38286
+ // The same serialized shape a full load embeds in __FARM_PROPS__.
38287
+ ...middlewareMap.size > 0 ? { middleware: { data: Object.fromEntries(middlewareMap) } } : {}
38103
38288
  },
38104
38289
  canonicalPath: routeProps.__farmCanonicalPath,
38105
38290
  modulePath: toUrlPath(route.modulePath),
@@ -38847,6 +39032,24 @@ function runFarmMiddlewareWithNavigation(renderer, middlewareRequest, req, res,
38847
39032
  }
38848
39033
  });
38849
39034
  }
39035
+ function createPageDataMiddlewareRequest(req, target) {
39036
+ const targetNodeRequest = Object.create(req);
39037
+ targetNodeRequest.url = `${target.pathname}${target.search}`;
39038
+ targetNodeRequest.originalUrl = targetNodeRequest.url;
39039
+ targetNodeRequest.method = "GET";
39040
+ return targetNodeRequest;
39041
+ }
39042
+ function resolveDevelopmentRoot(farmRoot, viteRoot) {
39043
+ if (!farmRoot) return viteRoot;
39044
+ if (path43.resolve(farmRoot) === path43.resolve(viteRoot)) return farmRoot;
39045
+ try {
39046
+ if (fs15.realpathSync(farmRoot) === fs15.realpathSync(viteRoot)) {
39047
+ return path43.resolve(viteRoot);
39048
+ }
39049
+ } catch {
39050
+ }
39051
+ return farmRoot;
39052
+ }
38850
39053
  function isFarmClientVirtualId(id) {
38851
39054
  const pathname = id.split("?", 1)[0];
38852
39055
  return pathname === "/@farm/client" || pathname === "/@farm/client.js";
@@ -38861,16 +39064,18 @@ function generateProgrammaticRouteModule(moduleId, root, renderer = REACT_RENDER
38861
39064
  return generateProgrammaticApiRouteModule(parsed.routePath, routeFile);
38862
39065
  }
38863
39066
  return `
38864
- import {
38865
- createElement as __farmCreateElement,
38866
- Suspense as __farmSuspense,
38867
- } from ${JSON.stringify(renderer.server)};
39067
+ import * as __farmRendererRuntime from ${JSON.stringify(renderer.server)};
38868
39068
  import {
38869
39069
  createLayoutModuleFromProgrammaticLayout as __farmCreateLayoutRouteModule,
38870
39070
  createRouteModuleFromProgrammaticPage as __farmCreatePageRouteModule,
38871
39071
  } from "@farm.js/core/routes";
38872
39072
  import * as __farmRoutesModule from ${JSON.stringify(routeFile)};
38873
39073
 
39074
+ const __farmCreateElement = __farmRendererRuntime.createElement;
39075
+ const __farmSuspense = __farmRendererRuntime.Suspense;
39076
+ // Optional hook: only renderers that need it export markFunctionComponent.
39077
+ const __farmMarkFunctionComponent = Reflect.get(__farmRendererRuntime, "markFunctionComponent");
39078
+
38874
39079
  const __farmIsRouteDefinition = (value) => (
38875
39080
  value &&
38876
39081
  typeof value === "object" &&
@@ -38924,6 +39129,7 @@ const __farmRouteModule = __farmRoute.kind === "layout"
38924
39129
  : __farmCreatePageRouteModule(__farmRoute, {
38925
39130
  createElement: __farmCreateElement,
38926
39131
  Suspense: __farmSuspense,
39132
+ markFunctionComponent: __farmMarkFunctionComponent,
38927
39133
  });
38928
39134
 
38929
39135
  export const metadata = __farmRouteModule.metadata;
@@ -40528,6 +40734,11 @@ async function hydrate() {
40528
40734
  pendingPageHydrationController = hydrationController;
40529
40735
  await hydrateFarmIsolatedClientBoundaries(rootContainer, hydrationController.signal);
40530
40736
  if (hydrationController.signal.aborted) return;
40737
+ // The rest of the document is static server HTML with nothing to hydrate, so
40738
+ // stop holding its clicks and submits once the load-strategy islands are live.
40739
+ // Deferred islands capture their own interactions, and held targets outside an
40740
+ // island are not replayed into DOM no client code owns.
40741
+ markFarmHydrated();
40531
40742
  return;
40532
40743
  }` : ""}
40533
40744
  if (!shouldHydrate) {
@@ -40969,9 +41180,11 @@ var init_vite2 = __esm({
40969
41180
  init_server_path();
40970
41181
  init_runtime2();
40971
41182
  init_manager();
41183
+ init_server();
40972
41184
  init_type_artifacts();
40973
41185
  init_routes_shared();
40974
41186
  init_markdown();
41187
+ init_base_path();
40975
41188
  init_llms_txt();
40976
41189
  init_agent_crawlers();
40977
41190
  init_app_markdown();
@@ -41109,6 +41322,8 @@ async function mountFarmDocsSearch() {
41109
41322
  __name(hasViteAlias, "hasViteAlias");
41110
41323
  __name(farmPlugin, "farmPlugin");
41111
41324
  __name(runFarmMiddlewareWithNavigation, "runFarmMiddlewareWithNavigation");
41325
+ __name(createPageDataMiddlewareRequest, "createPageDataMiddlewareRequest");
41326
+ __name(resolveDevelopmentRoot, "resolveDevelopmentRoot");
41112
41327
  __name(isFarmClientVirtualId, "isFarmClientVirtualId");
41113
41328
  __name(generateProgrammaticRouteModule, "generateProgrammaticRouteModule");
41114
41329
  __name(generateProgrammaticApiRouteModule, "generateProgrammaticApiRouteModule");
@@ -43888,7 +44103,7 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
43888
44103
  }
43889
44104
  }
43890
44105
  try {
43891
- await viteBuild({
44106
+ const clientViteConfig = {
43892
44107
  root,
43893
44108
  // Vite otherwise falls back to <root>/public, silently dropping every
43894
44109
  // asset in a custom config.publicDir from the production client output.
@@ -44024,7 +44239,8 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
44024
44239
  "@farm.js/core/headers"
44025
44240
  ]
44026
44241
  }
44027
- });
44242
+ };
44243
+ await viteBuild(mergeFarmProductionViteConfig(clientViteConfig, config.vite));
44028
44244
  await mergeBuiltFontCss(outputDir);
44029
44245
  await validateClientBuildOutput(root, srcDir, outputDir);
44030
44246
  } finally {
@@ -46370,7 +46586,7 @@ async function buildSSRInMemory(productionVite, config, root, routeManager, apiR
46370
46586
  "react-dom/server"
46371
46587
  ];
46372
46588
  try {
46373
- await viteBuild({
46589
+ const serverViteConfig = {
46374
46590
  root,
46375
46591
  build: {
46376
46592
  target: "esnext",
@@ -46531,7 +46747,8 @@ async function buildSSRInMemory(productionVite, config, root, routeManager, apiR
46531
46747
  // Route modules and the renderer adapter must share one runtime instance.
46532
46748
  dedupe: [...config.renderer.dedupe || []]
46533
46749
  }
46534
- });
46750
+ };
46751
+ await viteBuild(mergeFarmProductionViteConfig(serverViteConfig, config.vite));
46535
46752
  } finally {
46536
46753
  if (postcssConfigDir) {
46537
46754
  try {
@@ -48739,7 +48956,7 @@ function hasLocalRequestRoute(request, routePathname) {
48739
48956
  const pathname = new URL(request.url).pathname;
48740
48957
  if (
48741
48958
  farmOpenAPIReference &&
48742
- normalizeRuntimePath(pathname) === normalizeRuntimePath(farmOpenAPIReference.route)
48959
+ normalizeRuntimePath(stripFarmBasePath(pathname)) === normalizeRuntimePath(farmOpenAPIReference.route)
48743
48960
  ) {
48744
48961
  return true;
48745
48962
  }
@@ -48775,7 +48992,7 @@ function getFarmPluginRequestOptions(request) {
48775
48992
  const route = { pathname };
48776
48993
  if (
48777
48994
  farmOpenAPIReference &&
48778
- normalizeRuntimePath(pathname) === normalizeRuntimePath(farmOpenAPIReference.route)
48995
+ normalizeRuntimePath(stripFarmBasePath(pathname)) === normalizeRuntimePath(farmOpenAPIReference.route)
48779
48996
  ) {
48780
48997
  return {
48781
48998
  kind: "docs",
@@ -49104,9 +49321,10 @@ async function handleFarmRequest(request, adapterContext) {
49104
49321
  )` : "handleFarmRequestInContext(request, null, false, Date.now(), adapterContext, requestUrl)"};
49105
49322
  ${config.md?.enabled ? `const pathname = getFarmRoutePathname(requestUrl.pathname);
49106
49323
  if (matchPageRoute(pathname)) {
49324
+ // The Link header advertises the public .md URL, like the head alternate.
49107
49325
  return applyMarkdownNegotiationHeaders(response, {
49108
49326
  config: farmMarkdownConfig,
49109
- pathname,
49327
+ pathname: requestUrl.pathname,
49110
49328
  });
49111
49329
  }` : ""}
49112
49330
  return response;
@@ -49294,7 +49512,7 @@ async function handleFarmRequestInContext(
49294
49512
  if (
49295
49513
  farmOpenAPIReference &&
49296
49514
  farmOpenAPIReference.specRoute &&
49297
- normalizeRuntimePath(pathname) === normalizeRuntimePath(farmOpenAPIReference.specRoute)
49515
+ normalizeRuntimePath(stripFarmBasePath(pathname)) === normalizeRuntimePath(farmOpenAPIReference.specRoute)
49298
49516
  ) {
49299
49517
  const method = request.method.toUpperCase();
49300
49518
  const specResponse = method === "GET" || method === "HEAD"
@@ -49318,7 +49536,7 @@ async function handleFarmRequestInContext(
49318
49536
 
49319
49537
  if (
49320
49538
  farmOpenAPIReference &&
49321
- normalizeRuntimePath(pathname) === normalizeRuntimePath(farmOpenAPIReference.route)
49539
+ normalizeRuntimePath(stripFarmBasePath(pathname)) === normalizeRuntimePath(farmOpenAPIReference.route)
49322
49540
  ) {
49323
49541
  const method = request.method.toUpperCase();
49324
49542
  const response = method === "GET" || method === "HEAD"
@@ -49856,12 +50074,15 @@ async function handleFarmRequestInContext(
49856
50074
  const sharedCacheControl = getRouteSharedCacheControl(route, pprCanCache);
49857
50075
  const responseHeaders = {
49858
50076
  "Content-Type": "text/html; charset=utf-8",
49859
- "Cache-Control": renderedPage.stream || hasRequestScopedRender || !sharedCacheControl
49860
- ? "private, no-store"
49861
- : sharedCacheControl,
50077
+ "Cache-Control": sharedCacheControl,
49862
50078
  ...(farmFontPreloadHeader ? { "Link": farmFontPreloadHeader } : {}),
49863
50079
  ...(pprConfig.enabled ? getPPRHeaders(pprCanCache ? "miss" : "bypass", pprConfig) : {}),
49864
50080
  };
50081
+ // An error status or a request-scoped render is never shareable, even when
50082
+ // the PPR shell headers would otherwise grant a shared max-age.
50083
+ if (renderedPage.stream || hasRequestScopedRender || !sharedCacheControl) {
50084
+ responseHeaders["Cache-Control"] = "private, no-store";
50085
+ }
49865
50086
  const farmI18nSnapshot = getFarmI18nSnapshot();
49866
50087
  let html = renderedPage.html;
49867
50088