@farm.js/core 0.1.15 → 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 +5 -2
  2. package/dist/agent-runtime.d.ts +5 -2
  3. package/dist/api/client.cjs +62 -28
  4. package/dist/api/client.d.mts +3 -2
  5. package/dist/api/client.d.ts +3 -2
  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 +5 -2
  9. package/dist/api/route-manager.d.ts +5 -2
  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 -2
  13. package/dist/api/runtime.d.ts +3 -2
  14. package/dist/api/runtime.mjs +6 -3
  15. package/dist/{api-client-C8d7BZNp.d.mts → api-client-Cx54IR5g.d.mts} +2 -1
  16. package/dist/{api-client-BWrEbxfO.d.ts → api-client-DykpaKcY.d.ts} +2 -1
  17. package/dist/api.cjs +106 -33
  18. package/dist/api.d.mts +7 -4
  19. package/dist/api.d.ts +7 -4
  20. package/dist/api.mjs +8 -8
  21. package/dist/{app-wIYse61b.d.ts → app-BHY_10Lm.d.ts} +3 -3
  22. package/dist/{app-B3nVSjen.d.mts → app-BMk0do23.d.mts} +3 -3
  23. package/dist/app-markdown.d.mts +6 -3
  24. package/dist/app-markdown.d.ts +6 -3
  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-FOGLGRDS.mjs → chunk-4OOBRCJX.mjs} +122 -8
  31. package/dist/{chunk-JRF3C33L.mjs → chunk-56DAX2BE.mjs} +172 -53
  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-FBHGHMOA.mjs → chunk-MVIWBEJF.mjs} +37 -27
  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-GNTPTTLA.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-NJ47VORC.mjs → chunk-UTBVHYS3.mjs} +2 -2
  53. package/dist/{chunk-76MNRHTS.mjs → chunk-UUYF3CHN.mjs} +2 -2
  54. package/dist/{chunk-S3QW3BIS.mjs → chunk-WD4YXVLV.mjs} +99 -6
  55. package/dist/{chunk-W7IVHTOP.mjs → chunk-WD5PNSOB.mjs} +16 -3
  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-UE75PB52.mjs → chunk-YD4J4XCI.mjs} +1 -1
  59. package/dist/{chunk-Q3MDL7TM.mjs → chunk-ZCNJKLA2.mjs} +30 -11
  60. package/dist/{client-plugins-CslwYp3E.d.ts → client-plugins-C089bQhN.d.ts} +16 -4
  61. package/dist/{client-plugins-C1EgdoJM.d.mts → client-plugins-JXXmZliS.d.mts} +16 -4
  62. package/dist/client-plugins.d.mts +5 -2
  63. package/dist/client-plugins.d.ts +5 -2
  64. package/dist/client.cjs +62 -28
  65. package/dist/client.d.mts +8 -7
  66. package/dist/client.d.ts +8 -7
  67. package/dist/client.mjs +6 -6
  68. package/dist/config.d.mts +5 -2
  69. package/dist/config.d.ts +5 -2
  70. package/dist/cron.mjs +2 -2
  71. package/dist/{devtools-PCGEBRSC.mjs → devtools-UFVTMQX5.mjs} +7 -7
  72. package/dist/docs.cjs +83 -4
  73. package/dist/docs.mjs +9 -9
  74. package/dist/{route-CHBaW55F.d.ts → endpoint-1zA994xL.d.ts} +3 -128
  75. package/dist/{route-C6UClI1z.d.mts → endpoint-DAc96i93.d.mts} +3 -128
  76. package/dist/env.cjs +135 -8
  77. package/dist/env.d.mts +22 -2
  78. package/dist/env.d.ts +22 -2
  79. package/dist/env.mjs +4 -1
  80. package/dist/index.cjs +516 -105
  81. package/dist/index.d.mts +16 -15
  82. package/dist/index.d.ts +16 -15
  83. package/dist/index.mjs +46 -34
  84. package/dist/integrations.d.mts +5 -2
  85. package/dist/integrations.d.ts +5 -2
  86. package/dist/internal/app-markdown-runtime.d.mts +5 -2
  87. package/dist/internal/app-markdown-runtime.d.ts +5 -2
  88. package/dist/internal/app-markdown-runtime.mjs +2 -2
  89. package/dist/internal/build-runtime.cjs +600 -284
  90. package/dist/internal/build-runtime.d.mts +7 -4
  91. package/dist/internal/build-runtime.d.ts +7 -4
  92. package/dist/internal/build-runtime.mjs +23 -23
  93. package/dist/internal/cli-runtime.cjs +143 -33
  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 +5 -2
  98. package/dist/internal/compression-runtime.d.ts +5 -2
  99. package/dist/internal/config-runtime.cjs +80 -4
  100. package/dist/internal/config-runtime.d.mts +6 -3
  101. package/dist/internal/config-runtime.d.ts +6 -3
  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 +11 -8
  107. package/dist/internal/production-runtime.d.ts +11 -8
  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-BsUcOEXg.d.ts → metadata-BcNJP4fq.d.ts} +1 -1
  112. package/dist/{metadata-B1bxCPUY.d.mts → metadata-C1Z9vLbb.d.mts} +1 -1
  113. package/dist/middleware.cjs +10 -3
  114. package/dist/middleware.d.mts +7 -4
  115. package/dist/middleware.d.ts +7 -4
  116. package/dist/middleware.mjs +4 -4
  117. package/dist/{nitro-ICBP5APY.mjs → nitro-CVZ36JM5.mjs} +8 -5
  118. package/dist/plugin.cjs +358 -106
  119. package/dist/plugin.d.mts +5 -2
  120. package/dist/plugin.d.ts +5 -2
  121. package/dist/plugin.mjs +19 -19
  122. package/dist/{production-runtime-BDllolVh.d.mts → production-runtime-jcrTlRTb.d.mts} +1 -1
  123. package/dist/{production-runtime-CsNn2-zx.d.ts → production-runtime-oKmC0WU-.d.ts} +1 -1
  124. package/dist/{render-plan-CNUlzylR.d.mts → render-plan-BLIfc4jt.d.mts} +1 -1
  125. package/dist/{render-plan-EG4hNFjy.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 -4
  128. package/dist/renderer-client.d.ts +5 -4
  129. package/dist/renderer-client.mjs +3 -3
  130. package/dist/{request-Blh_f7Z3.d.mts → request-Cr53NRHr.d.mts} +1 -1
  131. package/dist/{request-DsVSQVfD.d.ts → request-Dt2gNuQD.d.ts} +1 -1
  132. package/dist/request.d.mts +6 -3
  133. package/dist/request.d.ts +6 -3
  134. package/dist/route-B0XrsrFk.d.mts +128 -0
  135. package/dist/route-DOEpbyWZ.d.ts +128 -0
  136. package/dist/{route-rendering-hUETRCbM.d.ts → route-rendering-CWYd8Mv1.d.ts} +1 -1
  137. package/dist/{route-rendering-LT4XSoQK.d.mts → route-rendering-CeFBEAoZ.d.mts} +1 -1
  138. package/dist/routes.cjs +68 -31
  139. package/dist/routes.d.mts +5 -3
  140. package/dist/routes.d.ts +5 -3
  141. package/dist/routes.mjs +2 -2
  142. package/dist/server-fn-client.d.mts +3 -2
  143. package/dist/server-fn-client.d.ts +3 -2
  144. package/dist/server-fn.cjs +212 -32
  145. package/dist/server-fn.d.mts +72 -1
  146. package/dist/server-fn.d.ts +72 -1
  147. package/dist/server-fn.mjs +13 -2
  148. package/dist/server-plugins.d.mts +6 -3
  149. package/dist/server-plugins.d.ts +6 -3
  150. package/dist/server-query-client.cjs +62 -28
  151. package/dist/server-query-client.d.mts +1 -0
  152. package/dist/server-query-client.d.ts +1 -0
  153. package/dist/server-query-client.mjs +4 -4
  154. package/dist/server-query.cjs +131 -32
  155. package/dist/server-query.d.mts +6 -1
  156. package/dist/server-query.d.ts +6 -1
  157. package/dist/server-query.mjs +4 -3
  158. package/dist/server.cjs +393 -84
  159. package/dist/server.d.mts +9 -8
  160. package/dist/server.d.ts +9 -8
  161. package/dist/server.mjs +22 -22
  162. package/dist/{spa-router-csKR9Ebj.d.mts → spa-router-CQWiYGxS.d.mts} +2 -2
  163. package/dist/{spa-router-Y_2FSJQK.d.ts → spa-router-Wjiw-8hB.d.ts} +2 -2
  164. package/dist/testing.cjs +73 -32
  165. package/dist/testing.d.mts +5 -3
  166. package/dist/testing.d.ts +5 -3
  167. package/dist/testing.mjs +11 -7
  168. package/dist/{utils-jISOE9SD.d.ts → utils-B0XJmG_b.d.ts} +1 -1
  169. package/dist/{utils-DR2wfZAn.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 +500 -252
  173. package/dist/vite.d.mts +5 -2
  174. package/dist/vite.d.ts +5 -2
  175. package/dist/vite.mjs +19 -19
  176. package/dist/workflows.mjs +2 -2
  177. package/package.json +2 -2
  178. package/dist/{chunk-VO5SCWF5.mjs → chunk-BNGS6KJ6.mjs} +0 -0
  179. package/dist/{chunk-MUUZJLCI.mjs → chunk-EGJDUF4Q.mjs} +3 -3
  180. package/dist/{chunk-4L7SZOHZ.mjs → chunk-YHOCRI4H.mjs} +3 -3
package/dist/plugin.cjs CHANGED
@@ -31,9 +31,53 @@ 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
58
+ function createBundledEnv(env2, source = getProcessEnv()) {
59
+ const resolved = normalizeResolvedEnv(env2 ?? {});
60
+ const server = {};
61
+ const runtime3 = {};
62
+ for (const [key, value] of Object.entries(resolved.server)) {
63
+ const raw = source[key];
64
+ const type = getRuntimeEnvType(value);
65
+ if (raw !== void 0 && isSameEnvValue(coerceRuntimeEnvValue(raw, type), value)) {
66
+ runtime3[key] = type;
67
+ } else {
68
+ server[key] = value;
69
+ }
70
+ }
71
+ return {
72
+ server,
73
+ public: resolved.public,
74
+ ...Object.keys(runtime3).length > 0 ? { runtime: { server: runtime3 } } : {}
75
+ };
76
+ }
35
77
  function getResolvedEnv() {
36
- return getCurrentEnv();
78
+ const env2 = getCurrentEnv();
79
+ if (typeof window === "undefined") readRuntimeServerEnv(env2);
80
+ return env2;
37
81
  }
38
82
  function createEnvProxy(scope) {
39
83
  return new Proxy(
@@ -44,7 +88,7 @@ function createEnvProxy(scope) {
44
88
  return void 0;
45
89
  }
46
90
  const env2 = getEnvScope(scope);
47
- return env2[property];
91
+ return scope === "server" ? readServerEnvKey(env2, property) : env2[property];
48
92
  },
49
93
  ownKeys() {
50
94
  return Reflect.ownKeys(getEnvScope(scope));
@@ -67,10 +111,90 @@ function createEnvProxy(scope) {
67
111
  );
68
112
  }
69
113
  function getEnvScope(scope) {
114
+ const env2 = getCurrentEnv();
70
115
  if (scope === "server") {
71
116
  assertServerEnvAccess();
117
+ readRuntimeServerEnv(env2);
72
118
  }
73
- return getCurrentEnv()[scope] || {};
119
+ return env2[scope] || {};
120
+ }
121
+ function readServerEnvKey(server, key) {
122
+ const value = server[key];
123
+ if (value === void 0) {
124
+ const state = getCurrentEnv()[FARM_ENV_RUNTIME_SYMBOL];
125
+ if (state && key in state.pending && !state.warned.has(key)) {
126
+ state.warned.add(key);
127
+ console.warn(
128
+ `[Farm] Server env "${key}" was set when this app was built but is not set where the server runs, so it reads as undefined. Farm reads server env at runtime and does not store it in the build output; set "${key}" in the server's environment.`
129
+ );
130
+ }
131
+ }
132
+ return value;
133
+ }
134
+ function readRuntimeServerEnv(env2) {
135
+ const state = env2[FARM_ENV_RUNTIME_SYMBOL];
136
+ if (!state) return;
137
+ for (const [key, type] of Object.entries(state.pending)) {
138
+ const raw = readFarmEnvironmentValue(key);
139
+ if (raw === void 0) continue;
140
+ env2.server[key] = coerceRuntimeEnvValue(raw, type);
141
+ delete state.pending[key];
142
+ }
143
+ }
144
+ function getRuntimeEnvType(value) {
145
+ if (typeof value === "number") return "number";
146
+ if (typeof value === "boolean") return "boolean";
147
+ if (value !== null && typeof value === "object" && !(value instanceof Date)) return "json";
148
+ return "string";
149
+ }
150
+ function coerceRuntimeEnvValue(raw, type) {
151
+ if (type === "number") {
152
+ const value = Number(raw);
153
+ return raw.trim() !== "" && Number.isFinite(value) ? value : raw;
154
+ }
155
+ if (type === "boolean") {
156
+ if (/^(true|1)$/i.test(raw.trim())) return true;
157
+ if (/^(false|0|)$/i.test(raw.trim())) return false;
158
+ return raw;
159
+ }
160
+ if (type === "json") {
161
+ try {
162
+ return JSON.parse(raw);
163
+ } catch {
164
+ return raw;
165
+ }
166
+ }
167
+ return raw;
168
+ }
169
+ function isSameEnvValue(left, right) {
170
+ if (Object.is(left, right)) return true;
171
+ if (Array.isArray(left) || Array.isArray(right)) {
172
+ return Array.isArray(left) && Array.isArray(right) && left.length === right.length && left.every((item, index) => isSameEnvValue(item, right[index]));
173
+ }
174
+ if (!isPlainObject(left) || !isPlainObject(right)) return false;
175
+ const keys = Object.keys(left);
176
+ return keys.length === Object.keys(right).length && keys.every(
177
+ (key) => Object.prototype.hasOwnProperty.call(right, key) && isSameEnvValue(left[key], right[key])
178
+ );
179
+ }
180
+ function isPlainObject(value) {
181
+ if (!value || typeof value !== "object") return false;
182
+ const prototype = Object.getPrototypeOf(value);
183
+ return prototype === Object.prototype || prototype === null;
184
+ }
185
+ function prepareEnv(env2) {
186
+ const normalized = normalizeResolvedEnv(env2);
187
+ const runtime3 = env2.runtime?.server;
188
+ if (!isRecord(runtime3) || Object.keys(runtime3).length === 0) return normalized;
189
+ const prepared = { server: { ...normalized.server }, public: normalized.public };
190
+ Object.defineProperty(prepared, FARM_ENV_RUNTIME_SYMBOL, {
191
+ value: {
192
+ pending: { ...runtime3 },
193
+ warned: /* @__PURE__ */ new Set()
194
+ },
195
+ enumerable: false
196
+ });
197
+ return prepared;
74
198
  }
75
199
  function assertServerEnvAccess() {
76
200
  if (typeof window !== "undefined") {
@@ -99,7 +223,7 @@ function getCurrentEnv() {
99
223
  function getInjectedEnv() {
100
224
  try {
101
225
  if (typeof __FARM_ENV__ !== "undefined" && __FARM_ENV__) {
102
- return normalizeResolvedEnv(__FARM_ENV__);
226
+ return prepareEnv(__FARM_ENV__);
103
227
  }
104
228
  } catch {
105
229
  }
@@ -123,18 +247,34 @@ function normalizeResolvedEnv(env2) {
123
247
  function isRecord(value) {
124
248
  return !!value && typeof value === "object" && !Array.isArray(value);
125
249
  }
126
- var FARM_ENV_SYMBOL, farmEnvGlobal, currentEnv, env, publicEnv;
250
+ function getProcessEnv() {
251
+ if (typeof process !== "undefined" && process.env) {
252
+ return process.env;
253
+ }
254
+ return {};
255
+ }
256
+ var FARM_ENV_SYMBOL, FARM_ENV_RUNTIME_SYMBOL, farmEnvGlobal, currentEnv, env, publicEnv;
127
257
  var init_env = __esm({
128
258
  "src/env.ts"() {
129
259
  "use strict";
260
+ init_runtime_env();
130
261
  FARM_ENV_SYMBOL = /* @__PURE__ */ Symbol.for("farm.env");
262
+ FARM_ENV_RUNTIME_SYMBOL = /* @__PURE__ */ Symbol.for("farm.env.runtime");
131
263
  farmEnvGlobal = globalThis;
132
264
  currentEnv = getInitialEnv();
265
+ __name(createBundledEnv, "createBundledEnv");
133
266
  __name(getResolvedEnv, "getResolvedEnv");
134
267
  env = createEnvProxy("server");
135
268
  publicEnv = createEnvProxy("public");
136
269
  __name(createEnvProxy, "createEnvProxy");
137
270
  __name(getEnvScope, "getEnvScope");
271
+ __name(readServerEnvKey, "readServerEnvKey");
272
+ __name(readRuntimeServerEnv, "readRuntimeServerEnv");
273
+ __name(getRuntimeEnvType, "getRuntimeEnvType");
274
+ __name(coerceRuntimeEnvValue, "coerceRuntimeEnvValue");
275
+ __name(isSameEnvValue, "isSameEnvValue");
276
+ __name(isPlainObject, "isPlainObject");
277
+ __name(prepareEnv, "prepareEnv");
138
278
  __name(assertServerEnvAccess, "assertServerEnvAccess");
139
279
  __name(getInitialEnv, "getInitialEnv");
140
280
  __name(getCurrentEnv, "getCurrentEnv");
@@ -142,6 +282,7 @@ var init_env = __esm({
142
282
  __name(getInjectedPublicEnv, "getInjectedPublicEnv");
143
283
  __name(normalizeResolvedEnv, "normalizeResolvedEnv");
144
284
  __name(isRecord, "isRecord");
285
+ __name(getProcessEnv, "getProcessEnv");
145
286
  }
146
287
  });
147
288
 
@@ -613,8 +754,16 @@ async function createMarkdownMirrorResponse(options) {
613
754
  if (!hasMarkdownExtension) {
614
755
  headersOut.set("Vary", "Accept");
615
756
  }
757
+ for (const token of pageResponse.headers.get("vary")?.split(",") ?? []) {
758
+ const name2 = token.trim();
759
+ if (name2 && name2.toLowerCase() !== "accept") appendHeaderToken(headersOut, "Vary", name2);
760
+ }
761
+ const pageCacheControl = pageResponse.headers.get("cache-control");
616
762
  const cache = target.route?.cache ?? options.config?.cache ?? false;
617
- headersOut.set("Cache-Control", createMarkdownCacheHeader(cache));
763
+ headersOut.set(
764
+ "Cache-Control",
765
+ pageCacheControl && isPrivateCacheControl(pageCacheControl) ? pageCacheControl : createMarkdownCacheHeader(cache)
766
+ );
618
767
  return new Response(options.request.method === "HEAD" ? null : markdown, {
619
768
  status: pageResponse.status,
620
769
  headers: headersOut
@@ -765,6 +914,17 @@ function isFarmMarkdownMirrorExposed(config, pathname) {
765
914
  function matchesFarmMarkdownRoutePattern(pattern, pathname) {
766
915
  return routeMatches(pattern, pathname);
767
916
  }
917
+ function appendHeaderToken(headers, name2, token) {
918
+ const current = headers.get(name2);
919
+ if (!current) {
920
+ headers.set(name2, token);
921
+ return;
922
+ }
923
+ const tokens = current.split(",").map((value) => value.trim().toLowerCase());
924
+ if (!tokens.includes(token.toLowerCase())) {
925
+ headers.set(name2, `${current}, ${token}`);
926
+ }
927
+ }
768
928
  function findExposedMarkdownRoute(config, pathname) {
769
929
  if (config.expose === true) {
770
930
  return null;
@@ -796,6 +956,12 @@ function isHtmlResponse(response) {
796
956
  const contentType = response.headers.get("content-type") ?? "";
797
957
  return contentType.includes("text/html");
798
958
  }
959
+ function isPrivateCacheControl(value) {
960
+ return value.split(",").some((directive) => {
961
+ const name2 = directive.split("=", 1)[0].trim().toLowerCase();
962
+ return name2 === "private" || name2 === "no-store";
963
+ });
964
+ }
799
965
  function createMarkdownCacheHeader(cache) {
800
966
  if (cache === false || cache <= 0) {
801
967
  return "no-store";
@@ -948,9 +1114,11 @@ var init_markdown = __esm({
948
1114
  __name(getFarmMarkdownAlternatePath, "getFarmMarkdownAlternatePath");
949
1115
  __name(isFarmMarkdownMirrorExposed, "isFarmMarkdownMirrorExposed");
950
1116
  __name(matchesFarmMarkdownRoutePattern, "matchesFarmMarkdownRoutePattern");
1117
+ __name(appendHeaderToken, "appendHeaderToken");
951
1118
  __name(findExposedMarkdownRoute, "findExposedMarkdownRoute");
952
1119
  __name(routeMatches, "routeMatches");
953
1120
  __name(isHtmlResponse, "isHtmlResponse");
1121
+ __name(isPrivateCacheControl, "isPrivateCacheControl");
954
1122
  __name(createMarkdownCacheHeader, "createMarkdownCacheHeader");
955
1123
  __name(extractHtmlTitle, "extractHtmlTitle");
956
1124
  __name(extractHtmlBody, "extractHtmlBody");
@@ -1569,29 +1737,6 @@ var init_secret_compare = __esm({
1569
1737
  }
1570
1738
  });
1571
1739
 
1572
- // src/utils/runtime-env.ts
1573
- function getFarmRuntimeBindings() {
1574
- const runtimeBindings = globalThis.__env__;
1575
- return runtimeBindings && typeof runtimeBindings === "object" ? runtimeBindings : void 0;
1576
- }
1577
- function readFarmEnvironmentValue(name2) {
1578
- const runtimeValue = getFarmRuntimeBindings()?.[name2];
1579
- if (typeof runtimeValue === "string") return runtimeValue;
1580
- return typeof process !== "undefined" ? process.env?.[name2] : void 0;
1581
- }
1582
- function isFarmDeployedRuntime() {
1583
- if (getFarmRuntimeBindings()) return true;
1584
- return readFarmEnvironmentValue("NODE_ENV") === "production";
1585
- }
1586
- var init_runtime_env = __esm({
1587
- "src/utils/runtime-env.ts"() {
1588
- "use strict";
1589
- __name(getFarmRuntimeBindings, "getFarmRuntimeBindings");
1590
- __name(readFarmEnvironmentValue, "readFarmEnvironmentValue");
1591
- __name(isFarmDeployedRuntime, "isFarmDeployedRuntime");
1592
- }
1593
- });
1594
-
1595
1740
  // src/utils/decode.ts
1596
1741
  function decodeRouteSegment(segment) {
1597
1742
  try {
@@ -5223,6 +5368,8 @@ var init_cache = __esm({
5223
5368
  constructor(config = {}) {
5224
5369
  this.entries = /* @__PURE__ */ new Map();
5225
5370
  this.inflight = /* @__PURE__ */ new Map();
5371
+ /** Local entries by tag, so tag counts and pruning never scan unrelated entries. */
5372
+ this.entriesByTag = /* @__PURE__ */ new Map();
5226
5373
  this.invalidatedTagVersions = /* @__PURE__ */ new Map();
5227
5374
  this.activeGenerations = /* @__PURE__ */ new Set();
5228
5375
  this.version = 0;
@@ -5241,6 +5388,7 @@ var init_cache = __esm({
5241
5388
  configure(config = {}) {
5242
5389
  this.generation++;
5243
5390
  this.entries.clear();
5391
+ this.entriesByTag.clear();
5244
5392
  this.inflight.clear();
5245
5393
  this.invalidatedTagVersions.clear();
5246
5394
  this.activeGenerations.clear();
@@ -5407,14 +5555,12 @@ var init_cache = __esm({
5407
5555
  return entry;
5408
5556
  }
5409
5557
  delete(key) {
5410
- const deleted = this.entries.delete(key);
5411
- if (deleted) this.pruneInvalidatedTagVersions();
5558
+ const deleted = this.deleteLocalEntry(key);
5412
5559
  emitFarmEvent({ type: "cache.delete", key, deleted });
5413
5560
  return deleted;
5414
5561
  }
5415
5562
  async deleteAsync(key) {
5416
- const deleted = this.entries.delete(key);
5417
- if (deleted) this.pruneInvalidatedTagVersions();
5563
+ const deleted = this.deleteLocalEntry(key);
5418
5564
  if (this.adapter) {
5419
5565
  await this.adapter.delete(this.createAdapterKey(key));
5420
5566
  }
@@ -5425,6 +5571,7 @@ var init_cache = __esm({
5425
5571
  const count = this.entries.size;
5426
5572
  this.generation++;
5427
5573
  this.entries.clear();
5574
+ this.entriesByTag.clear();
5428
5575
  this.inflight.clear();
5429
5576
  this.invalidatedTagVersions.clear();
5430
5577
  this.activeGenerations.clear();
@@ -5510,23 +5657,32 @@ var init_cache = __esm({
5510
5657
  return cached.value;
5511
5658
  }
5512
5659
  const inflight = this.inflight.get(key);
5513
- if (inflight) {
5660
+ if (inflight && !this.wasInvalidatedSince(inflight.tags, inflight.startVersion)) {
5514
5661
  emitFarmEvent({ type: "cache.dedupe", key });
5515
- return inflight;
5662
+ return inflight.promise;
5516
5663
  }
5517
5664
  const tags = Array.from(normalizeCacheOptionsTags(options));
5518
5665
  const generation = this.generation;
5666
+ const startVersion = this.version;
5519
5667
  const promise = this.fillCacheEntry(key, producer, options, tags, generation).catch((error) => {
5520
5668
  emitFarmEvent({ type: "cache.error", key, operation: "set", error });
5521
5669
  throw error;
5522
5670
  }).finally(() => {
5523
- if (this.inflight.get(key) === promise) {
5671
+ if (this.inflight.get(key)?.promise === promise) {
5524
5672
  this.inflight.delete(key);
5525
5673
  }
5526
5674
  });
5527
- this.inflight.set(key, promise);
5675
+ this.inflight.set(key, { promise, tags, startVersion });
5528
5676
  return promise;
5529
5677
  }
5678
+ /** A fill that started before one of its tags was invalidated cannot satisfy later readers. */
5679
+ wasInvalidatedSince(tags, version2) {
5680
+ for (const tag of tags) {
5681
+ const invalidatedVersion = this.invalidatedTagVersions.get(tag);
5682
+ if (invalidatedVersion !== void 0 && invalidatedVersion > version2) return true;
5683
+ }
5684
+ return false;
5685
+ }
5530
5686
  async fillCacheEntry(key, producer, options, tags, generation) {
5531
5687
  const adapter = this.adapter;
5532
5688
  const namespace = this.namespace;
@@ -5567,7 +5723,7 @@ var init_cache = __esm({
5567
5723
  return value;
5568
5724
  } finally {
5569
5725
  this.activeGenerations.delete(activeGeneration);
5570
- this.pruneInvalidatedTagVersions();
5726
+ this.pruneInvalidatedTagVersions(activeGeneration.tags);
5571
5727
  if (leaseToken && adapter?.releaseLease) {
5572
5728
  try {
5573
5729
  await adapter.releaseLease(leaseKey, leaseToken);
@@ -5612,18 +5768,9 @@ var init_cache = __esm({
5612
5768
  }
5613
5769
  return void 0;
5614
5770
  }
5615
- countEntriesForTag(tag) {
5616
- let count = 0;
5617
- for (const entry of this.entries.values()) {
5618
- if (entry.tags.has(tag)) {
5619
- count++;
5620
- }
5621
- }
5622
- return count;
5623
- }
5624
5771
  countEntriesForTags(tags) {
5625
5772
  let count = 0;
5626
- for (const entry of this.entries.values()) {
5773
+ for (const entry of this.entriesByTag.get(tags[0]) ?? []) {
5627
5774
  if (tags.every((tag) => entry.tags.has(tag))) {
5628
5775
  count++;
5629
5776
  }
@@ -5631,10 +5778,10 @@ var init_cache = __esm({
5631
5778
  return count;
5632
5779
  }
5633
5780
  invalidateTag(normalizedTag) {
5634
- const count = this.countEntriesForTag(normalizedTag);
5781
+ const count = this.entriesByTag.get(normalizedTag)?.size ?? 0;
5635
5782
  this.invalidatedTagVersions.delete(normalizedTag);
5636
5783
  this.invalidatedTagVersions.set(normalizedTag, ++this.version);
5637
- this.pruneInvalidatedTagVersions();
5784
+ this.pruneInvalidatedTagVersions([normalizedTag]);
5638
5785
  return count;
5639
5786
  }
5640
5787
  toPublicEntry(entry) {
@@ -5664,19 +5811,51 @@ var init_cache = __esm({
5664
5811
  this.entries.set(key, entry);
5665
5812
  }
5666
5813
  storeLocalEntry(entry) {
5667
- this.entries.delete(entry.key);
5814
+ const removed = [];
5815
+ const replaced = this.detachLocalEntry(entry.key);
5816
+ if (replaced) removed.push(replaced);
5668
5817
  this.entries.set(entry.key, entry);
5818
+ for (const tag of entry.tags) {
5819
+ let tagged = this.entriesByTag.get(tag);
5820
+ if (!tagged) this.entriesByTag.set(tag, tagged = /* @__PURE__ */ new Set());
5821
+ tagged.add(entry);
5822
+ }
5669
5823
  while (this.entries.size > this.maxEntries) {
5670
5824
  const oldestKey = this.entries.keys().next().value;
5671
5825
  if (oldestKey === void 0) break;
5672
- this.entries.delete(oldestKey);
5826
+ removed.push(this.detachLocalEntry(oldestKey));
5673
5827
  }
5674
- this.pruneInvalidatedTagVersions();
5828
+ for (const removedEntry of removed) this.pruneInvalidatedTagVersions(removedEntry.tags);
5829
+ }
5830
+ deleteLocalEntry(key) {
5831
+ const entry = this.detachLocalEntry(key);
5832
+ if (!entry) return false;
5833
+ this.pruneInvalidatedTagVersions(entry.tags);
5834
+ return true;
5835
+ }
5836
+ detachLocalEntry(key) {
5837
+ const entry = this.entries.get(key);
5838
+ if (!entry) return void 0;
5839
+ this.entries.delete(key);
5840
+ for (const tag of entry.tags) {
5841
+ const tagged = this.entriesByTag.get(tag);
5842
+ if (!tagged) continue;
5843
+ tagged.delete(entry);
5844
+ if (tagged.size === 0) this.entriesByTag.delete(tag);
5845
+ }
5846
+ return entry;
5675
5847
  }
5676
- pruneInvalidatedTagVersions() {
5677
- tags: for (const [tag, invalidatedVersion] of this.invalidatedTagVersions) {
5678
- for (const entry of this.entries.values()) {
5679
- if (entry.tags.has(tag) && entry.createdVersion < invalidatedVersion) continue tags;
5848
+ /**
5849
+ * Drop invalidation versions that no local entry or active fill can be stale against.
5850
+ * Callers pass only the tags whose dependents just changed, so the cost is bounded by
5851
+ * the entries sharing those tags rather than by the whole cache.
5852
+ */
5853
+ pruneInvalidatedTagVersions(tags) {
5854
+ tags: for (const tag of tags) {
5855
+ const invalidatedVersion = this.invalidatedTagVersions.get(tag);
5856
+ if (invalidatedVersion === void 0) continue;
5857
+ for (const entry of this.entriesByTag.get(tag) ?? []) {
5858
+ if (entry.createdVersion < invalidatedVersion) continue tags;
5680
5859
  }
5681
5860
  for (const generation of this.activeGenerations) {
5682
5861
  if (generation.tags.has(tag) && generation.createdVersion < invalidatedVersion)
@@ -6071,6 +6250,7 @@ function createProgrammaticPageComponent(route, rendererRuntime) {
6071
6250
  }
6072
6251
  return rendererRuntime.createElement(...args);
6073
6252
  }, "createElement");
6253
+ const markFunctionComponent = /* @__PURE__ */ __name((component) => rendererRuntime?.markFunctionComponent?.(component) ?? component, "markFunctionComponent");
6074
6254
  const Component = route.component;
6075
6255
  if (route.pending) {
6076
6256
  const PendingComponent = route.pending;
@@ -6092,7 +6272,9 @@ function createProgrammaticPageComponent(route, rendererRuntime) {
6092
6272
  throw error;
6093
6273
  }
6094
6274
  }, "FarmProgrammaticPageContent");
6095
- const PageContent = FarmProgrammaticPageContent2;
6275
+ const PageContent = markFunctionComponent(
6276
+ FarmProgrammaticPageContent2
6277
+ );
6096
6278
  const FarmProgrammaticPage = /* @__PURE__ */ __name(function FarmProgrammaticPage2(props) {
6097
6279
  return createElement2(
6098
6280
  rendererRuntime.Suspense,
@@ -6102,7 +6284,7 @@ function createProgrammaticPageComponent(route, rendererRuntime) {
6102
6284
  createElement2(PageContent, props)
6103
6285
  );
6104
6286
  }, "FarmProgrammaticPage");
6105
- return FarmProgrammaticPage;
6287
+ return markFunctionComponent(FarmProgrammaticPage);
6106
6288
  }
6107
6289
  const FarmProgrammaticPageContent = /* @__PURE__ */ __name(async function FarmProgrammaticPageContent2(props) {
6108
6290
  try {
@@ -6121,7 +6303,7 @@ function createProgrammaticPageComponent(route, rendererRuntime) {
6121
6303
  throw error;
6122
6304
  }
6123
6305
  }, "FarmProgrammaticPageContent");
6124
- return FarmProgrammaticPageContent;
6306
+ return markFunctionComponent(FarmProgrammaticPageContent);
6125
6307
  }
6126
6308
  function readProgrammaticRouteProps(route, props, resources) {
6127
6309
  if (isProgrammaticRoutePropsResolved(props)) {
@@ -13024,6 +13206,7 @@ function createFarmDocsHandler(docs, options) {
13024
13206
  if (!isFarmDocsRequest(docs, request2)) return null;
13025
13207
  const page2 = loadPage(contentDir, docs, request2);
13026
13208
  if (!page2) return null;
13209
+ const negotiatesAccept = !requestUrl.pathname.endsWith(".md");
13027
13210
  if (shouldReturnMarkdown(request2)) {
13028
13211
  const origin = new URL(request2.url).origin;
13029
13212
  return omitFarmDocsHeadBody(
@@ -13038,7 +13221,8 @@ function createFarmDocsHandler(docs, options) {
13038
13221
  status: 200,
13039
13222
  headers: {
13040
13223
  "Content-Type": "text/markdown; charset=utf-8",
13041
- "Cache-Control": "public, max-age=60"
13224
+ "Cache-Control": "public, max-age=60",
13225
+ ...negotiatesAccept ? { Vary: "Accept" } : {}
13042
13226
  }
13043
13227
  }
13044
13228
  )
@@ -13068,6 +13252,7 @@ function createFarmDocsHandler(docs, options) {
13068
13252
  headers: {
13069
13253
  "Content-Type": "text/html; charset=utf-8",
13070
13254
  "Cache-Control": "public, s-maxage=60, stale-while-revalidate=300",
13255
+ Vary: "Accept",
13071
13256
  ...fontPreloadHeader ? { Link: fontPreloadHeader } : {}
13072
13257
  }
13073
13258
  }
@@ -17249,6 +17434,9 @@ function normalizeRuntimeEndpointRequestPath(pathname) {
17249
17434
  }
17250
17435
  __name(normalizeRuntimeEndpointRequestPath, "normalizeRuntimeEndpointRequestPath");
17251
17436
 
17437
+ // src/vite.ts
17438
+ init_env();
17439
+
17252
17440
  // src/app.ts
17253
17441
  init_app_markdown_config();
17254
17442
  init_markdown();
@@ -19262,7 +19450,7 @@ function resolveImportedModule(importerPath, specifier, root) {
19262
19450
  return { path: resolveImportedModuleSourcePath(importerPath, specifier, root), local: true };
19263
19451
  }
19264
19452
  const aliased = resolveProjectAliasSourcePath(specifier, root);
19265
- if (aliased !== void 0) return { path: aliased, local: true };
19453
+ if (aliased) return { path: aliased, local: true };
19266
19454
  return { path: resolvePackageModuleSourcePath(importerPath, specifier, root), local: false };
19267
19455
  }
19268
19456
  __name(resolveImportedModule, "resolveImportedModule");
@@ -19278,11 +19466,12 @@ function resolveProjectAliasSourcePath(specifier, root) {
19278
19466
  if (!match || alias.prefix.length > match.alias.prefix.length) match = { alias, captured };
19279
19467
  }
19280
19468
  if (!match) return void 0;
19281
- return resolveSourceCandidate(
19469
+ const resolved = resolveSourceCandidate(
19282
19470
  match.alias.targets.map(
19283
19471
  (target) => import_path4.default.normalize(match.alias.wildcard ? target.replace("*", match.captured) : target)
19284
19472
  )
19285
19473
  );
19474
+ return resolved && /\.d\.[cm]?ts$/.test(resolved) ? null : resolved;
19286
19475
  }
19287
19476
  __name(resolveProjectAliasSourcePath, "resolveProjectAliasSourcePath");
19288
19477
  function matchProjectImportAlias(alias, specifier) {
@@ -19689,6 +19878,7 @@ __name(readAltText, "readAltText");
19689
19878
  // src/routing/route-manager.ts
19690
19879
  init_route_runtime();
19691
19880
  init_routing();
19881
+ init_base_path();
19692
19882
 
19693
19883
  // src/redirect-query.ts
19694
19884
  function appendFarmRedirectQuery(destination, search) {
@@ -20765,7 +20955,7 @@ var _RouteManager = class _RouteManager {
20765
20955
  }
20766
20956
  toRoutePathname(pathname) {
20767
20957
  const i18n = this.getI18nConfig();
20768
- return i18n ? stripFarmLocaleFromPathname(pathname, i18n) : pathname;
20958
+ return i18n ? stripFarmLocaleFromPathname(pathname, i18n) : stripFarmBasePath(pathname, this.config.basePath);
20769
20959
  }
20770
20960
  localizeRedirectDestination(destination, locale) {
20771
20961
  if (!locale || !destination.startsWith("/") || destination.startsWith("//")) {
@@ -21954,7 +22144,7 @@ async function readFarmI18nCatalogs(config) {
21954
22144
  }
21955
22145
  __name(readFarmI18nCatalogs, "readFarmI18nCatalogs");
21956
22146
  function flattenFarmI18nCatalog(input, source = "i18n catalog") {
21957
- if (!isPlainObject(input)) {
22147
+ if (!isPlainObject2(input)) {
21958
22148
  throw new Error(`${source} must contain a JSON object at its root.`);
21959
22149
  }
21960
22150
  const output = {};
@@ -21968,7 +22158,7 @@ function flattenFarmI18nCatalog(input, source = "i18n catalog") {
21968
22158
  output[key] = value;
21969
22159
  return;
21970
22160
  }
21971
- if (!isPlainObject(value)) {
22161
+ if (!isPlainObject2(value)) {
21972
22162
  const key = segments.join(".") || "<root>";
21973
22163
  throw new Error(`${source} message "${key}" must be a string or nested object.`);
21974
22164
  }
@@ -22068,10 +22258,10 @@ function sameSignature(expected, actual) {
22068
22258
  return JSON.stringify(expectedEntries) === JSON.stringify(actualEntries);
22069
22259
  }
22070
22260
  __name(sameSignature, "sameSignature");
22071
- function isPlainObject(value) {
22261
+ function isPlainObject2(value) {
22072
22262
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
22073
22263
  }
22074
- __name(isPlainObject, "isPlainObject");
22264
+ __name(isPlainObject2, "isPlainObject");
22075
22265
  function messageOf(error) {
22076
22266
  return error instanceof Error ? error.message : String(error);
22077
22267
  }
@@ -24874,7 +25064,7 @@ _setFarmThemeServerSnapshotResolver(() => {
24874
25064
  });
24875
25065
 
24876
25066
  // package.json
24877
- var version = "0.1.15";
25067
+ var version = "0.1.17";
24878
25068
 
24879
25069
  // src/version.ts
24880
25070
  var FARM_VERSION = version;
@@ -25164,7 +25354,7 @@ function createPPRRefreshScript() {
25164
25354
  __name(createPPRRefreshScript, "createPPRRefreshScript");
25165
25355
  function createPreHydrationClickQueueScript() {
25166
25356
  const selector = JSON.stringify(FARM_ISLAND_REPLAYABLE_SELECTOR);
25167
- return `<script>(function(){if(window.__FARM_PREHYDRATION_CLICK_QUEUE__)return;var queue=[];window.__FARM_PREHYDRATION_CLICK_QUEUE__=queue;window.__FARM_HYDRATED__=false;document.documentElement.dataset.farmHydrated="false";function isModified(event){return !!(event.metaKey||event.altKey||event.ctrlKey||event.shiftKey)}function inHydrated(node){return !!(node&&node.closest&&node.closest('[data-farm-island-hydrated="true"]'))}function closestQueuedTarget(target){while(target&&target!==document.documentElement){if(target.matches&&target.matches(${selector}))return target;target=target.parentElement}return null}function announce(target,kind){document.dispatchEvent(new CustomEvent("farm:island-interaction",{detail:{target:target,kind:kind||null}}))}function hold(event,target,kind){if(queue.some(function(item){return item.target===target}))return;queue.push({target:target,kind:kind,createdAt:Date.now()});announce(target,kind);event.preventDefault();event.stopImmediatePropagation()}document.addEventListener("click",function(event){if(window.__FARM_HYDRATED__)return;if(event.defaultPrevented||event.button!==0||isModified(event))return;var target=closestQueuedTarget(event.target);if(!target||target.closest&&target.closest("a[href]")||inHydrated(target))return;hold(event,target,"click")},true);document.addEventListener("submit",function(event){if(window.__FARM_HYDRATED__)return;if(event.defaultPrevented)return;var form=event.target;if(!form||form.nodeName!=="FORM"||inHydrated(form))return;hold(event,form,"submit")},true);function observe(event){if(window.__FARM_HYDRATED__)return;var target=event.target;if(!(target&&target.closest)||inHydrated(target))return;announce(target,null)}document.addEventListener("pointerdown",observe,true);document.addEventListener("focusin",observe,true);})();</script>`;
25357
+ return `<script>(function(){if(window.__FARM_PREHYDRATION_CLICK_QUEUE__)return;var queue=[];window.__FARM_PREHYDRATION_CLICK_QUEUE__=queue;window.__FARM_HYDRATED__=false;document.documentElement.dataset.farmHydrated="false";function isModified(event){return !!(event.metaKey||event.altKey||event.ctrlKey||event.shiftKey)}function inHydrated(node){return !!(node&&node.closest&&node.closest('[data-farm-island-hydrated="true"]'))}function closestQueuedTarget(target){while(target&&target!==document.documentElement){if(target.matches&&target.matches(${selector}))return target;target=target.parentElement}return null}function announce(target,kind){document.dispatchEvent(new CustomEvent("farm:island-interaction",{detail:{target:target,kind:kind||null}}))}function hold(event,target,kind){if(!queue.some(function(item){return item.target===target})){queue.push({target:target,kind:kind,createdAt:Date.now()});announce(target,kind)}event.preventDefault();event.stopImmediatePropagation()}document.addEventListener("click",function(event){if(window.__FARM_HYDRATED__)return;if(event.defaultPrevented||event.button!==0||isModified(event))return;var target=closestQueuedTarget(event.target);if(!target||target.closest&&target.closest("a[href]")||inHydrated(target))return;hold(event,target,"click")},true);document.addEventListener("submit",function(event){if(window.__FARM_HYDRATED__)return;if(event.defaultPrevented)return;var form=event.target;if(!form||form.nodeName!=="FORM"||inHydrated(form))return;hold(event,form,"submit")},true);function observe(event){if(window.__FARM_HYDRATED__)return;var target=event.target;if(!(target&&target.closest)||inHydrated(target))return;announce(target,null)}document.addEventListener("pointerdown",observe,true);document.addEventListener("focusin",observe,true);})();</script>`;
25168
25358
  }
25169
25359
  __name(createPreHydrationClickQueueScript, "createPreHydrationClickQueueScript");
25170
25360
  function createDocumentFooter(options) {
@@ -28231,7 +28421,7 @@ function createEndpoint(pathOrOptions, optionsOrHandler, maybeHandler) {
28231
28421
  wrappedHandler
28232
28422
  );
28233
28423
  endpoint.__path = path39 || void 0;
28234
- endpoint.__method = options.method || "GET";
28424
+ endpoint.__method = options.method || (path39 ? "GET" : void 0);
28235
28425
  endpoint.__autoPath = !path39;
28236
28426
  endpoint.__handler = wrappedHandler;
28237
28427
  endpoint.__farmInvoke = (ctx) => runEndpointMiddleware(middleware, ctx, handler, error, options.invalidates);
@@ -29819,7 +30009,7 @@ function parseColonParam(segment) {
29819
30009
  };
29820
30010
  }
29821
30011
  __name(parseColonParam, "parseColonParam");
29822
- function compilePathPattern(pattern) {
30012
+ function compilePathPattern(pattern, trailingSlash = false) {
29823
30013
  const params = [];
29824
30014
  const segments = pattern.split("/").filter(Boolean);
29825
30015
  if (segments.length === 0) {
@@ -29855,11 +30045,18 @@ function compilePathPattern(pattern) {
29855
30045
  });
29856
30046
  return {
29857
30047
  kind: "path",
29858
- regex: new RegExp(`^${parts.join("")}$`),
30048
+ regex: new RegExp(`^${parts.join("")}${trailingSlash ? "/?" : ""}$`),
29859
30049
  params
29860
30050
  };
29861
30051
  }
29862
30052
  __name(compilePathPattern, "compilePathPattern");
30053
+ function compileMatcherPattern(pattern) {
30054
+ if (typeof pattern === "string" && pattern !== "*" && !pattern.endsWith("(.*)")) {
30055
+ return compilePathPattern(pattern, true);
30056
+ }
30057
+ return compilePattern(pattern);
30058
+ }
30059
+ __name(compileMatcherPattern, "compileMatcherPattern");
29863
30060
  function compilePattern(pattern) {
29864
30061
  if (pattern instanceof RegExp) {
29865
30062
  return { kind: "regexp", regex: pattern };
@@ -29879,7 +30076,7 @@ __name(compilePattern, "compilePattern");
29879
30076
  function compileMiddlewareConfig(config) {
29880
30077
  const compiled = {
29881
30078
  matcher: config.matcher ? toMatcherList(config.matcher).map(
29882
- (matcher) => typeof matcher === "function" ? matcher : compilePattern(matcher)
30079
+ (matcher) => typeof matcher === "function" ? matcher : compileMatcherPattern(matcher)
29883
30080
  ) : void 0,
29884
30081
  exclude: config.exclude?.map(compilePattern)
29885
30082
  };
@@ -31145,6 +31342,7 @@ __name(collectLegacyTypeArtifacts, "collectLegacyTypeArtifacts");
31145
31342
  // src/vite.ts
31146
31343
  init_routes_shared();
31147
31344
  init_markdown();
31345
+ init_base_path();
31148
31346
  init_llms_txt();
31149
31347
  init_agent_crawlers();
31150
31348
  init_response();
@@ -32151,7 +32349,7 @@ function getEnvDefines(config, configEnv) {
32151
32349
  )
32152
32350
  };
32153
32351
  if (configEnv?.isSsrBuild) {
32154
- defines.__FARM_ENV__ = JSON.stringify(getFullEnvDefine(config));
32352
+ defines.__FARM_ENV__ = JSON.stringify(createBundledEnv(getFullEnvDefine(config)));
32155
32353
  }
32156
32354
  return defines;
32157
32355
  }
@@ -32428,8 +32626,8 @@ function farmPlugin(options = {}, initialPluginManager) {
32428
32626
  }, "emitPluginError");
32429
32627
  farmApp = new FarmApp(
32430
32628
  {
32431
- root: server.config.root,
32432
- ...options
32629
+ ...options,
32630
+ root: resolveDevelopmentRoot(options.root, server.config.root)
32433
32631
  },
32434
32632
  server
32435
32633
  );
@@ -33016,7 +33214,8 @@ window.__FARM_MANIFEST__ = ${inlineValue({
33016
33214
  () => middlewareManager.execute(req, res)
33017
33215
  );
33018
33216
  }, "runAppMiddlewareForContentRoute");
33019
- if (openAPIManager && options.openapi?.specRoute && requestPathname === options.openapi.specRoute) {
33217
+ const openAPIRequestPathname = openAPIManager ? stripFarmBasePath(requestPathname, farmConfig.basePath) : requestPathname;
33218
+ if (openAPIManager && options.openapi?.specRoute && openAPIRequestPathname === options.openapi.specRoute) {
33020
33219
  if (await runAppMiddlewareForContentRoute()) return;
33021
33220
  if (requestMethod !== "GET" && requestMethod !== "HEAD") {
33022
33221
  res.statusCode = 405;
@@ -33033,7 +33232,7 @@ window.__FARM_MANIFEST__ = ${inlineValue({
33033
33232
  res.end(requestMethod === "HEAD" ? void 0 : body);
33034
33233
  return;
33035
33234
  }
33036
- if (openAPIManager && requestPathname === options.openapi?.route) {
33235
+ if (openAPIManager && openAPIRequestPathname === options.openapi?.route) {
33037
33236
  if (await runAppMiddlewareForContentRoute()) return;
33038
33237
  const docsHandler = openAPIManager.getDocsRouteHandler(parsedRequestUrl.origin);
33039
33238
  return docsHandler(req, res);
@@ -33511,6 +33710,21 @@ window.__FARM_MANIFEST__ = ${inlineValue({
33511
33710
  headers: request2.headers,
33512
33711
  signal: request2.signal
33513
33712
  });
33713
+ let middlewareMap = /* @__PURE__ */ new Map();
33714
+ let middlewareContext = /* @__PURE__ */ new Map();
33715
+ if (middlewareManager?.hasMiddleware()) {
33716
+ const targetNodeRequest = createPageDataMiddlewareRequest(req, targetRequestUrl);
33717
+ const handled = await runFarmMiddlewareWithNavigation(
33718
+ farmApp.getServerRenderer(),
33719
+ targetRequest,
33720
+ targetNodeRequest,
33721
+ res,
33722
+ () => middlewareManager.execute(targetNodeRequest, res)
33723
+ );
33724
+ if (handled) return;
33725
+ middlewareMap = targetNodeRequest.__FARM_MIDDLEWARE_DATA__ ?? middlewareMap;
33726
+ middlewareContext = targetNodeRequest.__FARM_MIDDLEWARE_CONTEXT__ ?? middlewareContext;
33727
+ }
33514
33728
  await farmApp.getServerRenderer().runWithRequestContext(targetRequest, async () => {
33515
33729
  const routeManager3 = farmApp.getRouteManager();
33516
33730
  if (pm) {
@@ -33584,7 +33798,8 @@ window.__FARM_MANIFEST__ = ${inlineValue({
33584
33798
  {
33585
33799
  params,
33586
33800
  searchParams: Promise.resolve(searchParams),
33587
- path: targetUrl.pathname
33801
+ path: targetUrl.pathname,
33802
+ middleware: middlewareMap.size > 0 ? { data: middlewareMap } : void 0
33588
33803
  },
33589
33804
  routeContext
33590
33805
  ),
@@ -33672,27 +33887,34 @@ window.__FARM_MANIFEST__ = ${inlineValue({
33672
33887
  parseFarmLayoutChainHeader(request2.headers.get("x-farm-layout-chain")),
33673
33888
  destinationLayoutPatterns
33674
33889
  );
33675
- const fragmentHtml = await farmApp.getServerRenderer().renderNavigationFragment({
33676
- PageComponent: routeModule.default,
33677
- LoadingComponent: loadingModule?.default,
33678
- pageProps: routeProps,
33679
- params,
33680
- layouts: layouts.map((layout2, index) => ({
33681
- pattern: layout2.pattern,
33682
- module: layoutModules[index]
33683
- })),
33684
- layoutStartIndex,
33685
- slots: routeSlots.map((slot) => ({
33686
- name: slot.name,
33687
- ownerPattern: slot.ownerPattern,
33688
- containerId: slot.containerId,
33689
- module: slot.renderModule,
33690
- props: slot.props
33691
- })),
33692
- pageShouldHydrate: shouldHydrate,
33693
- layoutShouldHydrate: shouldHydrateLayout,
33694
- islandStrategy: hydrationIslandStrategy
33695
- });
33890
+ const renderer = farmApp.getServerRenderer();
33891
+ const fragmentHtml = await _runWithMiddlewareData(
33892
+ middlewareMap,
33893
+ () => _runWithMiddlewareContext(
33894
+ middlewareContext,
33895
+ () => renderer.renderNavigationFragment({
33896
+ PageComponent: routeModule.default,
33897
+ LoadingComponent: loadingModule?.default,
33898
+ pageProps: routeProps,
33899
+ params,
33900
+ layouts: layouts.map((layout2, index) => ({
33901
+ pattern: layout2.pattern,
33902
+ module: layoutModules[index]
33903
+ })),
33904
+ layoutStartIndex,
33905
+ slots: routeSlots.map((slot) => ({
33906
+ name: slot.name,
33907
+ ownerPattern: slot.ownerPattern,
33908
+ containerId: slot.containerId,
33909
+ module: slot.renderModule,
33910
+ props: slot.props
33911
+ })),
33912
+ pageShouldHydrate: shouldHydrate,
33913
+ layoutShouldHydrate: shouldHydrateLayout,
33914
+ islandStrategy: hydrationIslandStrategy
33915
+ })
33916
+ )
33917
+ );
33696
33918
  const pageData = {
33697
33919
  props: {
33698
33920
  params: routeProps.params,
@@ -33702,7 +33924,9 @@ window.__FARM_MANIFEST__ = ${inlineValue({
33702
33924
  ...routeProps.__farmCanonicalPath ? {
33703
33925
  __farmCanonicalPath: routeProps.__farmCanonicalPath
33704
33926
  } : {},
33705
- ...routeProps.__farmRoutePropsResolved ? { __farmRoutePropsResolved: true } : {}
33927
+ ...routeProps.__farmRoutePropsResolved ? { __farmRoutePropsResolved: true } : {},
33928
+ // The same serialized shape a full load embeds in __FARM_PROPS__.
33929
+ ...middlewareMap.size > 0 ? { middleware: { data: Object.fromEntries(middlewareMap) } } : {}
33706
33930
  },
33707
33931
  canonicalPath: routeProps.__farmCanonicalPath,
33708
33932
  modulePath: toUrlPath(route.modulePath),
@@ -34452,6 +34676,26 @@ function runFarmMiddlewareWithNavigation(renderer, middlewareRequest, req, res,
34452
34676
  });
34453
34677
  }
34454
34678
  __name(runFarmMiddlewareWithNavigation, "runFarmMiddlewareWithNavigation");
34679
+ function createPageDataMiddlewareRequest(req, target) {
34680
+ const targetNodeRequest = Object.create(req);
34681
+ targetNodeRequest.url = `${target.pathname}${target.search}`;
34682
+ targetNodeRequest.originalUrl = targetNodeRequest.url;
34683
+ targetNodeRequest.method = "GET";
34684
+ return targetNodeRequest;
34685
+ }
34686
+ __name(createPageDataMiddlewareRequest, "createPageDataMiddlewareRequest");
34687
+ function resolveDevelopmentRoot(farmRoot, viteRoot) {
34688
+ if (!farmRoot) return viteRoot;
34689
+ if (path38.resolve(farmRoot) === path38.resolve(viteRoot)) return farmRoot;
34690
+ try {
34691
+ if (fs14.realpathSync(farmRoot) === fs14.realpathSync(viteRoot)) {
34692
+ return path38.resolve(viteRoot);
34693
+ }
34694
+ } catch {
34695
+ }
34696
+ return farmRoot;
34697
+ }
34698
+ __name(resolveDevelopmentRoot, "resolveDevelopmentRoot");
34455
34699
  function isFarmClientVirtualId(id) {
34456
34700
  const pathname = id.split("?", 1)[0];
34457
34701
  return pathname === "/@farm/client" || pathname === "/@farm/client.js";
@@ -34467,16 +34711,18 @@ function generateProgrammaticRouteModule(moduleId, root, renderer = REACT_RENDER
34467
34711
  return generateProgrammaticApiRouteModule(parsed.routePath, routeFile);
34468
34712
  }
34469
34713
  return `
34470
- import {
34471
- createElement as __farmCreateElement,
34472
- Suspense as __farmSuspense,
34473
- } from ${JSON.stringify(renderer.server)};
34714
+ import * as __farmRendererRuntime from ${JSON.stringify(renderer.server)};
34474
34715
  import {
34475
34716
  createLayoutModuleFromProgrammaticLayout as __farmCreateLayoutRouteModule,
34476
34717
  createRouteModuleFromProgrammaticPage as __farmCreatePageRouteModule,
34477
34718
  } from "@farm.js/core/routes";
34478
34719
  import * as __farmRoutesModule from ${JSON.stringify(routeFile)};
34479
34720
 
34721
+ const __farmCreateElement = __farmRendererRuntime.createElement;
34722
+ const __farmSuspense = __farmRendererRuntime.Suspense;
34723
+ // Optional hook: only renderers that need it export markFunctionComponent.
34724
+ const __farmMarkFunctionComponent = Reflect.get(__farmRendererRuntime, "markFunctionComponent");
34725
+
34480
34726
  const __farmIsRouteDefinition = (value) => (
34481
34727
  value &&
34482
34728
  typeof value === "object" &&
@@ -34530,6 +34776,7 @@ const __farmRouteModule = __farmRoute.kind === "layout"
34530
34776
  : __farmCreatePageRouteModule(__farmRoute, {
34531
34777
  createElement: __farmCreateElement,
34532
34778
  Suspense: __farmSuspense,
34779
+ markFunctionComponent: __farmMarkFunctionComponent,
34533
34780
  });
34534
34781
 
34535
34782
  export const metadata = __farmRouteModule.metadata;
@@ -36139,6 +36386,11 @@ async function hydrate() {
36139
36386
  pendingPageHydrationController = hydrationController;
36140
36387
  await hydrateFarmIsolatedClientBoundaries(rootContainer, hydrationController.signal);
36141
36388
  if (hydrationController.signal.aborted) return;
36389
+ // The rest of the document is static server HTML with nothing to hydrate, so
36390
+ // stop holding its clicks and submits once the load-strategy islands are live.
36391
+ // Deferred islands capture their own interactions, and held targets outside an
36392
+ // island are not replayed into DOM no client code owns.
36393
+ markFarmHydrated();
36142
36394
  return;
36143
36395
  }` : ""}
36144
36396
  if (!shouldHydrate) {