@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/server.cjs CHANGED
@@ -152,8 +152,16 @@ async function createMarkdownMirrorResponse(options) {
152
152
  if (!hasMarkdownExtension) {
153
153
  headersOut.set("Vary", "Accept");
154
154
  }
155
+ for (const token of pageResponse.headers.get("vary")?.split(",") ?? []) {
156
+ const name2 = token.trim();
157
+ if (name2 && name2.toLowerCase() !== "accept") appendHeaderToken(headersOut, "Vary", name2);
158
+ }
159
+ const pageCacheControl = pageResponse.headers.get("cache-control");
155
160
  const cache = target.route?.cache ?? options.config?.cache ?? false;
156
- headersOut.set("Cache-Control", createMarkdownCacheHeader(cache));
161
+ headersOut.set(
162
+ "Cache-Control",
163
+ pageCacheControl && isPrivateCacheControl(pageCacheControl) ? pageCacheControl : createMarkdownCacheHeader(cache)
164
+ );
157
165
  return new Response(options.request.method === "HEAD" ? null : markdown, {
158
166
  status: pageResponse.status,
159
167
  headers: headersOut
@@ -304,6 +312,17 @@ function isFarmMarkdownMirrorExposed(config, pathname) {
304
312
  function matchesFarmMarkdownRoutePattern(pattern, pathname) {
305
313
  return routeMatches(pattern, pathname);
306
314
  }
315
+ function appendHeaderToken(headers, name2, token) {
316
+ const current = headers.get(name2);
317
+ if (!current) {
318
+ headers.set(name2, token);
319
+ return;
320
+ }
321
+ const tokens = current.split(",").map((value) => value.trim().toLowerCase());
322
+ if (!tokens.includes(token.toLowerCase())) {
323
+ headers.set(name2, `${current}, ${token}`);
324
+ }
325
+ }
307
326
  function findExposedMarkdownRoute(config, pathname) {
308
327
  if (config.expose === true) {
309
328
  return null;
@@ -335,6 +354,12 @@ function isHtmlResponse(response) {
335
354
  const contentType = response.headers.get("content-type") ?? "";
336
355
  return contentType.includes("text/html");
337
356
  }
357
+ function isPrivateCacheControl(value) {
358
+ return value.split(",").some((directive) => {
359
+ const name2 = directive.split("=", 1)[0].trim().toLowerCase();
360
+ return name2 === "private" || name2 === "no-store";
361
+ });
362
+ }
338
363
  function createMarkdownCacheHeader(cache) {
339
364
  if (cache === false || cache <= 0) {
340
365
  return "no-store";
@@ -487,9 +512,11 @@ var init_markdown = __esm({
487
512
  __name(getFarmMarkdownAlternatePath, "getFarmMarkdownAlternatePath");
488
513
  __name(isFarmMarkdownMirrorExposed, "isFarmMarkdownMirrorExposed");
489
514
  __name(matchesFarmMarkdownRoutePattern, "matchesFarmMarkdownRoutePattern");
515
+ __name(appendHeaderToken, "appendHeaderToken");
490
516
  __name(findExposedMarkdownRoute, "findExposedMarkdownRoute");
491
517
  __name(routeMatches, "routeMatches");
492
518
  __name(isHtmlResponse, "isHtmlResponse");
519
+ __name(isPrivateCacheControl, "isPrivateCacheControl");
493
520
  __name(createMarkdownCacheHeader, "createMarkdownCacheHeader");
494
521
  __name(extractHtmlTitle, "extractHtmlTitle");
495
522
  __name(extractHtmlBody, "extractHtmlBody");
@@ -6149,6 +6176,8 @@ var init_cache = __esm({
6149
6176
  constructor(config = {}) {
6150
6177
  this.entries = /* @__PURE__ */ new Map();
6151
6178
  this.inflight = /* @__PURE__ */ new Map();
6179
+ /** Local entries by tag, so tag counts and pruning never scan unrelated entries. */
6180
+ this.entriesByTag = /* @__PURE__ */ new Map();
6152
6181
  this.invalidatedTagVersions = /* @__PURE__ */ new Map();
6153
6182
  this.activeGenerations = /* @__PURE__ */ new Set();
6154
6183
  this.version = 0;
@@ -6167,6 +6196,7 @@ var init_cache = __esm({
6167
6196
  configure(config = {}) {
6168
6197
  this.generation++;
6169
6198
  this.entries.clear();
6199
+ this.entriesByTag.clear();
6170
6200
  this.inflight.clear();
6171
6201
  this.invalidatedTagVersions.clear();
6172
6202
  this.activeGenerations.clear();
@@ -6333,14 +6363,12 @@ var init_cache = __esm({
6333
6363
  return entry;
6334
6364
  }
6335
6365
  delete(key) {
6336
- const deleted = this.entries.delete(key);
6337
- if (deleted) this.pruneInvalidatedTagVersions();
6366
+ const deleted = this.deleteLocalEntry(key);
6338
6367
  emitFarmEvent({ type: "cache.delete", key, deleted });
6339
6368
  return deleted;
6340
6369
  }
6341
6370
  async deleteAsync(key) {
6342
- const deleted = this.entries.delete(key);
6343
- if (deleted) this.pruneInvalidatedTagVersions();
6371
+ const deleted = this.deleteLocalEntry(key);
6344
6372
  if (this.adapter) {
6345
6373
  await this.adapter.delete(this.createAdapterKey(key));
6346
6374
  }
@@ -6351,6 +6379,7 @@ var init_cache = __esm({
6351
6379
  const count = this.entries.size;
6352
6380
  this.generation++;
6353
6381
  this.entries.clear();
6382
+ this.entriesByTag.clear();
6354
6383
  this.inflight.clear();
6355
6384
  this.invalidatedTagVersions.clear();
6356
6385
  this.activeGenerations.clear();
@@ -6436,23 +6465,32 @@ var init_cache = __esm({
6436
6465
  return cached.value;
6437
6466
  }
6438
6467
  const inflight = this.inflight.get(key);
6439
- if (inflight) {
6468
+ if (inflight && !this.wasInvalidatedSince(inflight.tags, inflight.startVersion)) {
6440
6469
  emitFarmEvent({ type: "cache.dedupe", key });
6441
- return inflight;
6470
+ return inflight.promise;
6442
6471
  }
6443
6472
  const tags = Array.from(normalizeCacheOptionsTags(options));
6444
6473
  const generation = this.generation;
6474
+ const startVersion = this.version;
6445
6475
  const promise = this.fillCacheEntry(key, producer, options, tags, generation).catch((error) => {
6446
6476
  emitFarmEvent({ type: "cache.error", key, operation: "set", error });
6447
6477
  throw error;
6448
6478
  }).finally(() => {
6449
- if (this.inflight.get(key) === promise) {
6479
+ if (this.inflight.get(key)?.promise === promise) {
6450
6480
  this.inflight.delete(key);
6451
6481
  }
6452
6482
  });
6453
- this.inflight.set(key, promise);
6483
+ this.inflight.set(key, { promise, tags, startVersion });
6454
6484
  return promise;
6455
6485
  }
6486
+ /** A fill that started before one of its tags was invalidated cannot satisfy later readers. */
6487
+ wasInvalidatedSince(tags, version2) {
6488
+ for (const tag of tags) {
6489
+ const invalidatedVersion = this.invalidatedTagVersions.get(tag);
6490
+ if (invalidatedVersion !== void 0 && invalidatedVersion > version2) return true;
6491
+ }
6492
+ return false;
6493
+ }
6456
6494
  async fillCacheEntry(key, producer, options, tags, generation) {
6457
6495
  const adapter = this.adapter;
6458
6496
  const namespace = this.namespace;
@@ -6493,7 +6531,7 @@ var init_cache = __esm({
6493
6531
  return value;
6494
6532
  } finally {
6495
6533
  this.activeGenerations.delete(activeGeneration);
6496
- this.pruneInvalidatedTagVersions();
6534
+ this.pruneInvalidatedTagVersions(activeGeneration.tags);
6497
6535
  if (leaseToken && adapter?.releaseLease) {
6498
6536
  try {
6499
6537
  await adapter.releaseLease(leaseKey, leaseToken);
@@ -6538,18 +6576,9 @@ var init_cache = __esm({
6538
6576
  }
6539
6577
  return void 0;
6540
6578
  }
6541
- countEntriesForTag(tag) {
6542
- let count = 0;
6543
- for (const entry of this.entries.values()) {
6544
- if (entry.tags.has(tag)) {
6545
- count++;
6546
- }
6547
- }
6548
- return count;
6549
- }
6550
6579
  countEntriesForTags(tags) {
6551
6580
  let count = 0;
6552
- for (const entry of this.entries.values()) {
6581
+ for (const entry of this.entriesByTag.get(tags[0]) ?? []) {
6553
6582
  if (tags.every((tag) => entry.tags.has(tag))) {
6554
6583
  count++;
6555
6584
  }
@@ -6557,10 +6586,10 @@ var init_cache = __esm({
6557
6586
  return count;
6558
6587
  }
6559
6588
  invalidateTag(normalizedTag) {
6560
- const count = this.countEntriesForTag(normalizedTag);
6589
+ const count = this.entriesByTag.get(normalizedTag)?.size ?? 0;
6561
6590
  this.invalidatedTagVersions.delete(normalizedTag);
6562
6591
  this.invalidatedTagVersions.set(normalizedTag, ++this.version);
6563
- this.pruneInvalidatedTagVersions();
6592
+ this.pruneInvalidatedTagVersions([normalizedTag]);
6564
6593
  return count;
6565
6594
  }
6566
6595
  toPublicEntry(entry) {
@@ -6590,19 +6619,51 @@ var init_cache = __esm({
6590
6619
  this.entries.set(key, entry);
6591
6620
  }
6592
6621
  storeLocalEntry(entry) {
6593
- this.entries.delete(entry.key);
6622
+ const removed = [];
6623
+ const replaced = this.detachLocalEntry(entry.key);
6624
+ if (replaced) removed.push(replaced);
6594
6625
  this.entries.set(entry.key, entry);
6626
+ for (const tag of entry.tags) {
6627
+ let tagged = this.entriesByTag.get(tag);
6628
+ if (!tagged) this.entriesByTag.set(tag, tagged = /* @__PURE__ */ new Set());
6629
+ tagged.add(entry);
6630
+ }
6595
6631
  while (this.entries.size > this.maxEntries) {
6596
6632
  const oldestKey = this.entries.keys().next().value;
6597
6633
  if (oldestKey === void 0) break;
6598
- this.entries.delete(oldestKey);
6634
+ removed.push(this.detachLocalEntry(oldestKey));
6635
+ }
6636
+ for (const removedEntry of removed) this.pruneInvalidatedTagVersions(removedEntry.tags);
6637
+ }
6638
+ deleteLocalEntry(key) {
6639
+ const entry = this.detachLocalEntry(key);
6640
+ if (!entry) return false;
6641
+ this.pruneInvalidatedTagVersions(entry.tags);
6642
+ return true;
6643
+ }
6644
+ detachLocalEntry(key) {
6645
+ const entry = this.entries.get(key);
6646
+ if (!entry) return void 0;
6647
+ this.entries.delete(key);
6648
+ for (const tag of entry.tags) {
6649
+ const tagged = this.entriesByTag.get(tag);
6650
+ if (!tagged) continue;
6651
+ tagged.delete(entry);
6652
+ if (tagged.size === 0) this.entriesByTag.delete(tag);
6599
6653
  }
6600
- this.pruneInvalidatedTagVersions();
6654
+ return entry;
6601
6655
  }
6602
- pruneInvalidatedTagVersions() {
6603
- tags: for (const [tag, invalidatedVersion] of this.invalidatedTagVersions) {
6604
- for (const entry of this.entries.values()) {
6605
- if (entry.tags.has(tag) && entry.createdVersion < invalidatedVersion) continue tags;
6656
+ /**
6657
+ * Drop invalidation versions that no local entry or active fill can be stale against.
6658
+ * Callers pass only the tags whose dependents just changed, so the cost is bounded by
6659
+ * the entries sharing those tags rather than by the whole cache.
6660
+ */
6661
+ pruneInvalidatedTagVersions(tags) {
6662
+ tags: for (const tag of tags) {
6663
+ const invalidatedVersion = this.invalidatedTagVersions.get(tag);
6664
+ if (invalidatedVersion === void 0) continue;
6665
+ for (const entry of this.entriesByTag.get(tag) ?? []) {
6666
+ if (entry.createdVersion < invalidatedVersion) continue tags;
6606
6667
  }
6607
6668
  for (const generation of this.activeGenerations) {
6608
6669
  if (generation.tags.has(tag) && generation.createdVersion < invalidatedVersion)
@@ -7000,6 +7061,7 @@ function createProgrammaticPageComponent(route, rendererRuntime) {
7000
7061
  }
7001
7062
  return rendererRuntime.createElement(...args);
7002
7063
  }, "createElement");
7064
+ const markFunctionComponent = /* @__PURE__ */ __name((component) => rendererRuntime?.markFunctionComponent?.(component) ?? component, "markFunctionComponent");
7003
7065
  const Component = route.component;
7004
7066
  if (route.pending) {
7005
7067
  const PendingComponent = route.pending;
@@ -7021,7 +7083,9 @@ function createProgrammaticPageComponent(route, rendererRuntime) {
7021
7083
  throw error;
7022
7084
  }
7023
7085
  }, "FarmProgrammaticPageContent");
7024
- const PageContent = FarmProgrammaticPageContent2;
7086
+ const PageContent = markFunctionComponent(
7087
+ FarmProgrammaticPageContent2
7088
+ );
7025
7089
  const FarmProgrammaticPage = /* @__PURE__ */ __name(function FarmProgrammaticPage2(props) {
7026
7090
  return createElement2(
7027
7091
  rendererRuntime.Suspense,
@@ -7031,7 +7095,7 @@ function createProgrammaticPageComponent(route, rendererRuntime) {
7031
7095
  createElement2(PageContent, props)
7032
7096
  );
7033
7097
  }, "FarmProgrammaticPage");
7034
- return FarmProgrammaticPage;
7098
+ return markFunctionComponent(FarmProgrammaticPage);
7035
7099
  }
7036
7100
  const FarmProgrammaticPageContent = /* @__PURE__ */ __name(async function FarmProgrammaticPageContent2(props) {
7037
7101
  try {
@@ -7050,7 +7114,7 @@ function createProgrammaticPageComponent(route, rendererRuntime) {
7050
7114
  throw error;
7051
7115
  }
7052
7116
  }, "FarmProgrammaticPageContent");
7053
- return FarmProgrammaticPageContent;
7117
+ return markFunctionComponent(FarmProgrammaticPageContent);
7054
7118
  }
7055
7119
  function readProgrammaticRouteProps(route, props, resources) {
7056
7120
  if (isProgrammaticRoutePropsResolved(props)) {
@@ -11971,14 +12035,35 @@ function resolveEnv(config, source = getProcessEnv()) {
11971
12035
  };
11972
12036
  return resolved;
11973
12037
  }
12038
+ function createBundledEnv(env2, source = getProcessEnv()) {
12039
+ const resolved = normalizeResolvedEnv(env2 ?? {});
12040
+ const server = {};
12041
+ const runtime3 = {};
12042
+ for (const [key, value] of Object.entries(resolved.server)) {
12043
+ const raw = source[key];
12044
+ const type = getRuntimeEnvType(value);
12045
+ if (raw !== void 0 && isSameEnvValue(coerceRuntimeEnvValue(raw, type), value)) {
12046
+ runtime3[key] = type;
12047
+ } else {
12048
+ server[key] = value;
12049
+ }
12050
+ }
12051
+ return {
12052
+ server,
12053
+ public: resolved.public,
12054
+ ...Object.keys(runtime3).length > 0 ? { runtime: { server: runtime3 } } : {}
12055
+ };
12056
+ }
11974
12057
  function setEnv(env2) {
11975
- currentEnv = normalizeResolvedEnv(env2);
12058
+ currentEnv = prepareEnv(env2);
11976
12059
  if (typeof window === "undefined") {
11977
12060
  farmEnvGlobal[FARM_ENV_SYMBOL] = currentEnv;
11978
12061
  }
11979
12062
  }
11980
12063
  function getResolvedEnv() {
11981
- return getCurrentEnv();
12064
+ const env2 = getCurrentEnv();
12065
+ if (typeof window === "undefined") readRuntimeServerEnv(env2);
12066
+ return env2;
11982
12067
  }
11983
12068
  function resolveEnvScope(shape, source, scope) {
11984
12069
  if (!shape) {
@@ -12013,7 +12098,7 @@ function createEnvProxy(scope) {
12013
12098
  return void 0;
12014
12099
  }
12015
12100
  const env2 = getEnvScope(scope);
12016
- return env2[property];
12101
+ return scope === "server" ? readServerEnvKey(env2, property) : env2[property];
12017
12102
  },
12018
12103
  ownKeys() {
12019
12104
  return Reflect.ownKeys(getEnvScope(scope));
@@ -12036,10 +12121,90 @@ function createEnvProxy(scope) {
12036
12121
  );
12037
12122
  }
12038
12123
  function getEnvScope(scope) {
12124
+ const env2 = getCurrentEnv();
12039
12125
  if (scope === "server") {
12040
12126
  assertServerEnvAccess();
12127
+ readRuntimeServerEnv(env2);
12128
+ }
12129
+ return env2[scope] || {};
12130
+ }
12131
+ function readServerEnvKey(server, key) {
12132
+ const value = server[key];
12133
+ if (value === void 0) {
12134
+ const state = getCurrentEnv()[FARM_ENV_RUNTIME_SYMBOL];
12135
+ if (state && key in state.pending && !state.warned.has(key)) {
12136
+ state.warned.add(key);
12137
+ console.warn(
12138
+ `[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.`
12139
+ );
12140
+ }
12141
+ }
12142
+ return value;
12143
+ }
12144
+ function readRuntimeServerEnv(env2) {
12145
+ const state = env2[FARM_ENV_RUNTIME_SYMBOL];
12146
+ if (!state) return;
12147
+ for (const [key, type] of Object.entries(state.pending)) {
12148
+ const raw = readFarmEnvironmentValue(key);
12149
+ if (raw === void 0) continue;
12150
+ env2.server[key] = coerceRuntimeEnvValue(raw, type);
12151
+ delete state.pending[key];
12152
+ }
12153
+ }
12154
+ function getRuntimeEnvType(value) {
12155
+ if (typeof value === "number") return "number";
12156
+ if (typeof value === "boolean") return "boolean";
12157
+ if (value !== null && typeof value === "object" && !(value instanceof Date)) return "json";
12158
+ return "string";
12159
+ }
12160
+ function coerceRuntimeEnvValue(raw, type) {
12161
+ if (type === "number") {
12162
+ const value = Number(raw);
12163
+ return raw.trim() !== "" && Number.isFinite(value) ? value : raw;
12164
+ }
12165
+ if (type === "boolean") {
12166
+ if (/^(true|1)$/i.test(raw.trim())) return true;
12167
+ if (/^(false|0|)$/i.test(raw.trim())) return false;
12168
+ return raw;
12169
+ }
12170
+ if (type === "json") {
12171
+ try {
12172
+ return JSON.parse(raw);
12173
+ } catch {
12174
+ return raw;
12175
+ }
12176
+ }
12177
+ return raw;
12178
+ }
12179
+ function isSameEnvValue(left, right) {
12180
+ if (Object.is(left, right)) return true;
12181
+ if (Array.isArray(left) || Array.isArray(right)) {
12182
+ return Array.isArray(left) && Array.isArray(right) && left.length === right.length && left.every((item, index) => isSameEnvValue(item, right[index]));
12041
12183
  }
12042
- return getCurrentEnv()[scope] || {};
12184
+ if (!isPlainObject3(left) || !isPlainObject3(right)) return false;
12185
+ const keys = Object.keys(left);
12186
+ return keys.length === Object.keys(right).length && keys.every(
12187
+ (key) => Object.prototype.hasOwnProperty.call(right, key) && isSameEnvValue(left[key], right[key])
12188
+ );
12189
+ }
12190
+ function isPlainObject3(value) {
12191
+ if (!value || typeof value !== "object") return false;
12192
+ const prototype = Object.getPrototypeOf(value);
12193
+ return prototype === Object.prototype || prototype === null;
12194
+ }
12195
+ function prepareEnv(env2) {
12196
+ const normalized = normalizeResolvedEnv(env2);
12197
+ const runtime3 = env2.runtime?.server;
12198
+ if (!isRecord4(runtime3) || Object.keys(runtime3).length === 0) return normalized;
12199
+ const prepared = { server: { ...normalized.server }, public: normalized.public };
12200
+ Object.defineProperty(prepared, FARM_ENV_RUNTIME_SYMBOL, {
12201
+ value: {
12202
+ pending: { ...runtime3 },
12203
+ warned: /* @__PURE__ */ new Set()
12204
+ },
12205
+ enumerable: false
12206
+ });
12207
+ return prepared;
12043
12208
  }
12044
12209
  function assertServerEnvAccess() {
12045
12210
  if (typeof window !== "undefined") {
@@ -12068,7 +12233,7 @@ function getCurrentEnv() {
12068
12233
  function getInjectedEnv() {
12069
12234
  try {
12070
12235
  if (typeof __FARM_ENV__ !== "undefined" && __FARM_ENV__) {
12071
- return normalizeResolvedEnv(__FARM_ENV__);
12236
+ return prepareEnv(__FARM_ENV__);
12072
12237
  }
12073
12238
  } catch {
12074
12239
  }
@@ -12098,14 +12263,17 @@ function getProcessEnv() {
12098
12263
  }
12099
12264
  return {};
12100
12265
  }
12101
- var FARM_ENV_SYMBOL, farmEnvGlobal, currentEnv, env, publicEnv;
12266
+ var FARM_ENV_SYMBOL, FARM_ENV_RUNTIME_SYMBOL, farmEnvGlobal, currentEnv, env, publicEnv;
12102
12267
  var init_env = __esm({
12103
12268
  "src/env.ts"() {
12104
12269
  "use strict";
12270
+ init_runtime_env();
12105
12271
  FARM_ENV_SYMBOL = /* @__PURE__ */ Symbol.for("farm.env");
12272
+ FARM_ENV_RUNTIME_SYMBOL = /* @__PURE__ */ Symbol.for("farm.env.runtime");
12106
12273
  farmEnvGlobal = globalThis;
12107
12274
  currentEnv = getInitialEnv();
12108
12275
  __name(resolveEnv, "resolveEnv");
12276
+ __name(createBundledEnv, "createBundledEnv");
12109
12277
  __name(setEnv, "setEnv");
12110
12278
  __name(getResolvedEnv, "getResolvedEnv");
12111
12279
  env = createEnvProxy("server");
@@ -12114,6 +12282,13 @@ var init_env = __esm({
12114
12282
  __name(parseEnvValue, "parseEnvValue");
12115
12283
  __name(createEnvProxy, "createEnvProxy");
12116
12284
  __name(getEnvScope, "getEnvScope");
12285
+ __name(readServerEnvKey, "readServerEnvKey");
12286
+ __name(readRuntimeServerEnv, "readRuntimeServerEnv");
12287
+ __name(getRuntimeEnvType, "getRuntimeEnvType");
12288
+ __name(coerceRuntimeEnvValue, "coerceRuntimeEnvValue");
12289
+ __name(isSameEnvValue, "isSameEnvValue");
12290
+ __name(isPlainObject3, "isPlainObject");
12291
+ __name(prepareEnv, "prepareEnv");
12117
12292
  __name(assertServerEnvAccess, "assertServerEnvAccess");
12118
12293
  __name(getInitialEnv, "getInitialEnv");
12119
12294
  __name(getCurrentEnv, "getCurrentEnv");
@@ -17390,6 +17565,7 @@ function createFarmDocsHandler(docs, options) {
17390
17565
  if (!isFarmDocsRequest(docs, request2)) return null;
17391
17566
  const page2 = loadPage(contentDir, docs, request2);
17392
17567
  if (!page2) return null;
17568
+ const negotiatesAccept = !requestUrl.pathname.endsWith(".md");
17393
17569
  if (shouldReturnMarkdown(request2)) {
17394
17570
  const origin = new URL(request2.url).origin;
17395
17571
  return omitFarmDocsHeadBody(
@@ -17404,7 +17580,8 @@ function createFarmDocsHandler(docs, options) {
17404
17580
  status: 200,
17405
17581
  headers: {
17406
17582
  "Content-Type": "text/markdown; charset=utf-8",
17407
- "Cache-Control": "public, max-age=60"
17583
+ "Cache-Control": "public, max-age=60",
17584
+ ...negotiatesAccept ? { Vary: "Accept" } : {}
17408
17585
  }
17409
17586
  }
17410
17587
  )
@@ -17434,6 +17611,7 @@ function createFarmDocsHandler(docs, options) {
17434
17611
  headers: {
17435
17612
  "Content-Type": "text/html; charset=utf-8",
17436
17613
  "Cache-Control": "public, s-maxage=60, stale-while-revalidate=300",
17614
+ Vary: "Accept",
17437
17615
  ...fontPreloadHeader ? { Link: fontPreloadHeader } : {}
17438
17616
  }
17439
17617
  }
@@ -24043,7 +24221,7 @@ function resolveImportedModule(importerPath, specifier, root) {
24043
24221
  return { path: resolveImportedModuleSourcePath(importerPath, specifier, root), local: true };
24044
24222
  }
24045
24223
  const aliased = resolveProjectAliasSourcePath(specifier, root);
24046
- if (aliased !== void 0) return { path: aliased, local: true };
24224
+ if (aliased) return { path: aliased, local: true };
24047
24225
  return { path: resolvePackageModuleSourcePath(importerPath, specifier, root), local: false };
24048
24226
  }
24049
24227
  __name(resolveImportedModule, "resolveImportedModule");
@@ -24059,11 +24237,12 @@ function resolveProjectAliasSourcePath(specifier, root) {
24059
24237
  if (!match || alias.prefix.length > match.alias.prefix.length) match = { alias, captured };
24060
24238
  }
24061
24239
  if (!match) return void 0;
24062
- return resolveSourceCandidate(
24240
+ const resolved = resolveSourceCandidate(
24063
24241
  match.alias.targets.map(
24064
24242
  (target) => import_path4.default.normalize(match.alias.wildcard ? target.replace("*", match.captured) : target)
24065
24243
  )
24066
24244
  );
24245
+ return resolved && /\.d\.[cm]?ts$/.test(resolved) ? null : resolved;
24067
24246
  }
24068
24247
  __name(resolveProjectAliasSourcePath, "resolveProjectAliasSourcePath");
24069
24248
  function matchProjectImportAlias(alias, specifier) {
@@ -24470,6 +24649,7 @@ __name(readAltText, "readAltText");
24470
24649
  // src/routing/route-manager.ts
24471
24650
  init_route_runtime();
24472
24651
  init_routing();
24652
+ init_base_path();
24473
24653
 
24474
24654
  // src/redirect-query.ts
24475
24655
  function appendFarmRedirectQuery(destination, search) {
@@ -25546,7 +25726,7 @@ var _RouteManager = class _RouteManager {
25546
25726
  }
25547
25727
  toRoutePathname(pathname) {
25548
25728
  const i18n = this.getI18nConfig();
25549
- return i18n ? stripFarmLocaleFromPathname(pathname, i18n) : pathname;
25729
+ return i18n ? stripFarmLocaleFromPathname(pathname, i18n) : stripFarmBasePath(pathname, this.config.basePath);
25550
25730
  }
25551
25731
  localizeRedirectDestination(destination, locale) {
25552
25732
  if (!locale || !destination.startsWith("/") || destination.startsWith("//")) {
@@ -29669,7 +29849,7 @@ _setFarmThemeServerSnapshotResolver(() => {
29669
29849
  });
29670
29850
 
29671
29851
  // package.json
29672
- var version = "0.1.15";
29852
+ var version = "0.1.17";
29673
29853
 
29674
29854
  // src/version.ts
29675
29855
  var FARM_VERSION = version;
@@ -29959,7 +30139,7 @@ function createPPRRefreshScript() {
29959
30139
  __name(createPPRRefreshScript, "createPPRRefreshScript");
29960
30140
  function createPreHydrationClickQueueScript() {
29961
30141
  const selector = JSON.stringify(FARM_ISLAND_REPLAYABLE_SELECTOR);
29962
- 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>`;
30142
+ 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>`;
29963
30143
  }
29964
30144
  __name(createPreHydrationClickQueueScript, "createPreHydrationClickQueueScript");
29965
30145
  function createDocumentFooter(options) {
@@ -32638,6 +32818,7 @@ function createFarmApp(config, viteServer) {
32638
32818
  __name(createFarmApp, "createFarmApp");
32639
32819
 
32640
32820
  // src/vite.ts
32821
+ init_env();
32641
32822
  init_utils();
32642
32823
 
32643
32824
  // src/plugin.ts
@@ -34049,7 +34230,7 @@ function createEndpoint(pathOrOptions, optionsOrHandler, maybeHandler) {
34049
34230
  wrappedHandler
34050
34231
  );
34051
34232
  endpoint.__path = path41 || void 0;
34052
- endpoint.__method = options.method || "GET";
34233
+ endpoint.__method = options.method || (path41 ? "GET" : void 0);
34053
34234
  endpoint.__autoPath = !path41;
34054
34235
  endpoint.__handler = wrappedHandler;
34055
34236
  endpoint.__farmInvoke = (ctx) => runEndpointMiddleware(middleware, ctx, handler, error, options.invalidates);
@@ -35637,7 +35818,7 @@ function parseColonParam(segment) {
35637
35818
  };
35638
35819
  }
35639
35820
  __name(parseColonParam, "parseColonParam");
35640
- function compilePathPattern(pattern) {
35821
+ function compilePathPattern(pattern, trailingSlash = false) {
35641
35822
  const params = [];
35642
35823
  const segments = pattern.split("/").filter(Boolean);
35643
35824
  if (segments.length === 0) {
@@ -35673,11 +35854,18 @@ function compilePathPattern(pattern) {
35673
35854
  });
35674
35855
  return {
35675
35856
  kind: "path",
35676
- regex: new RegExp(`^${parts.join("")}$`),
35857
+ regex: new RegExp(`^${parts.join("")}${trailingSlash ? "/?" : ""}$`),
35677
35858
  params
35678
35859
  };
35679
35860
  }
35680
35861
  __name(compilePathPattern, "compilePathPattern");
35862
+ function compileMatcherPattern(pattern) {
35863
+ if (typeof pattern === "string" && pattern !== "*" && !pattern.endsWith("(.*)")) {
35864
+ return compilePathPattern(pattern, true);
35865
+ }
35866
+ return compilePattern(pattern);
35867
+ }
35868
+ __name(compileMatcherPattern, "compileMatcherPattern");
35681
35869
  function compilePattern(pattern) {
35682
35870
  if (pattern instanceof RegExp) {
35683
35871
  return { kind: "regexp", regex: pattern };
@@ -35697,7 +35885,7 @@ __name(compilePattern, "compilePattern");
35697
35885
  function compileMiddlewareConfig(config) {
35698
35886
  const compiled = {
35699
35887
  matcher: config.matcher ? toMatcherList(config.matcher).map(
35700
- (matcher) => typeof matcher === "function" ? matcher : compilePattern(matcher)
35888
+ (matcher) => typeof matcher === "function" ? matcher : compileMatcherPattern(matcher)
35701
35889
  ) : void 0,
35702
35890
  exclude: config.exclude?.map(compilePattern)
35703
35891
  };
@@ -36948,6 +37136,7 @@ __name(collectLegacyTypeArtifacts, "collectLegacyTypeArtifacts");
36948
37136
  // src/vite.ts
36949
37137
  init_routes_shared();
36950
37138
  init_markdown();
37139
+ init_base_path();
36951
37140
  init_llms_txt();
36952
37141
  init_agent_crawlers();
36953
37142
  init_response();
@@ -38600,7 +38789,7 @@ function getEnvDefines(config, configEnv) {
38600
38789
  )
38601
38790
  };
38602
38791
  if (configEnv?.isSsrBuild) {
38603
- defines.__FARM_ENV__ = JSON.stringify(getFullEnvDefine(config));
38792
+ defines.__FARM_ENV__ = JSON.stringify(createBundledEnv(getFullEnvDefine(config)));
38604
38793
  }
38605
38794
  return defines;
38606
38795
  }
@@ -38877,8 +39066,8 @@ function farmPlugin(options = {}, initialPluginManager) {
38877
39066
  }, "emitPluginError");
38878
39067
  farmApp = new FarmApp(
38879
39068
  {
38880
- root: server.config.root,
38881
- ...options
39069
+ ...options,
39070
+ root: resolveDevelopmentRoot(options.root, server.config.root)
38882
39071
  },
38883
39072
  server
38884
39073
  );
@@ -39465,7 +39654,8 @@ window.__FARM_MANIFEST__ = ${inlineValue({
39465
39654
  () => middlewareManager.execute(req, res)
39466
39655
  );
39467
39656
  }, "runAppMiddlewareForContentRoute");
39468
- if (openAPIManager && options.openapi?.specRoute && requestPathname === options.openapi.specRoute) {
39657
+ const openAPIRequestPathname = openAPIManager ? stripFarmBasePath(requestPathname, farmConfig.basePath) : requestPathname;
39658
+ if (openAPIManager && options.openapi?.specRoute && openAPIRequestPathname === options.openapi.specRoute) {
39469
39659
  if (await runAppMiddlewareForContentRoute()) return;
39470
39660
  if (requestMethod !== "GET" && requestMethod !== "HEAD") {
39471
39661
  res.statusCode = 405;
@@ -39482,7 +39672,7 @@ window.__FARM_MANIFEST__ = ${inlineValue({
39482
39672
  res.end(requestMethod === "HEAD" ? void 0 : body);
39483
39673
  return;
39484
39674
  }
39485
- if (openAPIManager && requestPathname === options.openapi?.route) {
39675
+ if (openAPIManager && openAPIRequestPathname === options.openapi?.route) {
39486
39676
  if (await runAppMiddlewareForContentRoute()) return;
39487
39677
  const docsHandler = openAPIManager.getDocsRouteHandler(parsedRequestUrl.origin);
39488
39678
  return docsHandler(req, res);
@@ -39960,6 +40150,21 @@ window.__FARM_MANIFEST__ = ${inlineValue({
39960
40150
  headers: request2.headers,
39961
40151
  signal: request2.signal
39962
40152
  });
40153
+ let middlewareMap = /* @__PURE__ */ new Map();
40154
+ let middlewareContext = /* @__PURE__ */ new Map();
40155
+ if (middlewareManager?.hasMiddleware()) {
40156
+ const targetNodeRequest = createPageDataMiddlewareRequest(req, targetRequestUrl);
40157
+ const handled = await runFarmMiddlewareWithNavigation(
40158
+ farmApp.getServerRenderer(),
40159
+ targetRequest,
40160
+ targetNodeRequest,
40161
+ res,
40162
+ () => middlewareManager.execute(targetNodeRequest, res)
40163
+ );
40164
+ if (handled) return;
40165
+ middlewareMap = targetNodeRequest.__FARM_MIDDLEWARE_DATA__ ?? middlewareMap;
40166
+ middlewareContext = targetNodeRequest.__FARM_MIDDLEWARE_CONTEXT__ ?? middlewareContext;
40167
+ }
39963
40168
  await farmApp.getServerRenderer().runWithRequestContext(targetRequest, async () => {
39964
40169
  const routeManager3 = farmApp.getRouteManager();
39965
40170
  if (pm) {
@@ -40033,7 +40238,8 @@ window.__FARM_MANIFEST__ = ${inlineValue({
40033
40238
  {
40034
40239
  params,
40035
40240
  searchParams: Promise.resolve(searchParams),
40036
- path: targetUrl.pathname
40241
+ path: targetUrl.pathname,
40242
+ middleware: middlewareMap.size > 0 ? { data: middlewareMap } : void 0
40037
40243
  },
40038
40244
  routeContext
40039
40245
  ),
@@ -40121,27 +40327,34 @@ window.__FARM_MANIFEST__ = ${inlineValue({
40121
40327
  parseFarmLayoutChainHeader(request2.headers.get("x-farm-layout-chain")),
40122
40328
  destinationLayoutPatterns
40123
40329
  );
40124
- const fragmentHtml = await farmApp.getServerRenderer().renderNavigationFragment({
40125
- PageComponent: routeModule.default,
40126
- LoadingComponent: loadingModule?.default,
40127
- pageProps: routeProps,
40128
- params,
40129
- layouts: layouts.map((layout2, index) => ({
40130
- pattern: layout2.pattern,
40131
- module: layoutModules[index]
40132
- })),
40133
- layoutStartIndex,
40134
- slots: routeSlots.map((slot) => ({
40135
- name: slot.name,
40136
- ownerPattern: slot.ownerPattern,
40137
- containerId: slot.containerId,
40138
- module: slot.renderModule,
40139
- props: slot.props
40140
- })),
40141
- pageShouldHydrate: shouldHydrate,
40142
- layoutShouldHydrate: shouldHydrateLayout,
40143
- islandStrategy: hydrationIslandStrategy
40144
- });
40330
+ const renderer = farmApp.getServerRenderer();
40331
+ const fragmentHtml = await _runWithMiddlewareData(
40332
+ middlewareMap,
40333
+ () => _runWithMiddlewareContext(
40334
+ middlewareContext,
40335
+ () => renderer.renderNavigationFragment({
40336
+ PageComponent: routeModule.default,
40337
+ LoadingComponent: loadingModule?.default,
40338
+ pageProps: routeProps,
40339
+ params,
40340
+ layouts: layouts.map((layout2, index) => ({
40341
+ pattern: layout2.pattern,
40342
+ module: layoutModules[index]
40343
+ })),
40344
+ layoutStartIndex,
40345
+ slots: routeSlots.map((slot) => ({
40346
+ name: slot.name,
40347
+ ownerPattern: slot.ownerPattern,
40348
+ containerId: slot.containerId,
40349
+ module: slot.renderModule,
40350
+ props: slot.props
40351
+ })),
40352
+ pageShouldHydrate: shouldHydrate,
40353
+ layoutShouldHydrate: shouldHydrateLayout,
40354
+ islandStrategy: hydrationIslandStrategy
40355
+ })
40356
+ )
40357
+ );
40145
40358
  const pageData = {
40146
40359
  props: {
40147
40360
  params: routeProps.params,
@@ -40151,7 +40364,9 @@ window.__FARM_MANIFEST__ = ${inlineValue({
40151
40364
  ...routeProps.__farmCanonicalPath ? {
40152
40365
  __farmCanonicalPath: routeProps.__farmCanonicalPath
40153
40366
  } : {},
40154
- ...routeProps.__farmRoutePropsResolved ? { __farmRoutePropsResolved: true } : {}
40367
+ ...routeProps.__farmRoutePropsResolved ? { __farmRoutePropsResolved: true } : {},
40368
+ // The same serialized shape a full load embeds in __FARM_PROPS__.
40369
+ ...middlewareMap.size > 0 ? { middleware: { data: Object.fromEntries(middlewareMap) } } : {}
40155
40370
  },
40156
40371
  canonicalPath: routeProps.__farmCanonicalPath,
40157
40372
  modulePath: toUrlPath(route.modulePath),
@@ -40901,6 +41116,26 @@ function runFarmMiddlewareWithNavigation(renderer, middlewareRequest, req, res,
40901
41116
  });
40902
41117
  }
40903
41118
  __name(runFarmMiddlewareWithNavigation, "runFarmMiddlewareWithNavigation");
41119
+ function createPageDataMiddlewareRequest(req, target) {
41120
+ const targetNodeRequest = Object.create(req);
41121
+ targetNodeRequest.url = `${target.pathname}${target.search}`;
41122
+ targetNodeRequest.originalUrl = targetNodeRequest.url;
41123
+ targetNodeRequest.method = "GET";
41124
+ return targetNodeRequest;
41125
+ }
41126
+ __name(createPageDataMiddlewareRequest, "createPageDataMiddlewareRequest");
41127
+ function resolveDevelopmentRoot(farmRoot, viteRoot) {
41128
+ if (!farmRoot) return viteRoot;
41129
+ if (path38.resolve(farmRoot) === path38.resolve(viteRoot)) return farmRoot;
41130
+ try {
41131
+ if (fs14.realpathSync(farmRoot) === fs14.realpathSync(viteRoot)) {
41132
+ return path38.resolve(viteRoot);
41133
+ }
41134
+ } catch {
41135
+ }
41136
+ return farmRoot;
41137
+ }
41138
+ __name(resolveDevelopmentRoot, "resolveDevelopmentRoot");
40904
41139
  function isFarmClientVirtualId(id) {
40905
41140
  const pathname = id.split("?", 1)[0];
40906
41141
  return pathname === "/@farm/client" || pathname === "/@farm/client.js";
@@ -40916,16 +41151,18 @@ function generateProgrammaticRouteModule(moduleId, root, renderer = REACT_RENDER
40916
41151
  return generateProgrammaticApiRouteModule(parsed.routePath, routeFile);
40917
41152
  }
40918
41153
  return `
40919
- import {
40920
- createElement as __farmCreateElement,
40921
- Suspense as __farmSuspense,
40922
- } from ${JSON.stringify(renderer.server)};
41154
+ import * as __farmRendererRuntime from ${JSON.stringify(renderer.server)};
40923
41155
  import {
40924
41156
  createLayoutModuleFromProgrammaticLayout as __farmCreateLayoutRouteModule,
40925
41157
  createRouteModuleFromProgrammaticPage as __farmCreatePageRouteModule,
40926
41158
  } from "@farm.js/core/routes";
40927
41159
  import * as __farmRoutesModule from ${JSON.stringify(routeFile)};
40928
41160
 
41161
+ const __farmCreateElement = __farmRendererRuntime.createElement;
41162
+ const __farmSuspense = __farmRendererRuntime.Suspense;
41163
+ // Optional hook: only renderers that need it export markFunctionComponent.
41164
+ const __farmMarkFunctionComponent = Reflect.get(__farmRendererRuntime, "markFunctionComponent");
41165
+
40929
41166
  const __farmIsRouteDefinition = (value) => (
40930
41167
  value &&
40931
41168
  typeof value === "object" &&
@@ -40979,6 +41216,7 @@ const __farmRouteModule = __farmRoute.kind === "layout"
40979
41216
  : __farmCreatePageRouteModule(__farmRoute, {
40980
41217
  createElement: __farmCreateElement,
40981
41218
  Suspense: __farmSuspense,
41219
+ markFunctionComponent: __farmMarkFunctionComponent,
40982
41220
  });
40983
41221
 
40984
41222
  export const metadata = __farmRouteModule.metadata;
@@ -42588,6 +42826,11 @@ async function hydrate() {
42588
42826
  pendingPageHydrationController = hydrationController;
42589
42827
  await hydrateFarmIsolatedClientBoundaries(rootContainer, hydrationController.signal);
42590
42828
  if (hydrationController.signal.aborted) return;
42829
+ // The rest of the document is static server HTML with nothing to hydrate, so
42830
+ // stop holding its clicks and submits once the load-strategy islands are live.
42831
+ // Deferred islands capture their own interactions, and held targets outside an
42832
+ // island are not replayed into DOM no client code owns.
42833
+ markFarmHydrated();
42591
42834
  return;
42592
42835
  }` : ""}
42593
42836
  if (!shouldHydrate) {
@@ -43031,8 +43274,46 @@ init_server_action_security();
43031
43274
  init_server_action_security();
43032
43275
  init_cache();
43033
43276
  init_server_fn_error();
43277
+ init_navigation_errors();
43034
43278
  init_server_fn_error();
43035
43279
  var FARM_SERVER_FN_SYMBOL = /* @__PURE__ */ Symbol.for("farm.server-fn");
43280
+ var FARM_SERVER_FUNCTION_DESCRIPTOR = /* @__PURE__ */ Symbol.for("farm.server-function.descriptor");
43281
+ var _ServerFnInputError = class _ServerFnInputError extends Error {
43282
+ constructor(cause) {
43283
+ super("Server function input is invalid");
43284
+ this.cause = cause;
43285
+ }
43286
+ };
43287
+ __name(_ServerFnInputError, "ServerFnInputError");
43288
+ var ServerFnInputError = _ServerFnInputError;
43289
+ function createServerFunctionDescriptor(kind, options, run) {
43290
+ return Object.freeze({
43291
+ kind,
43292
+ input: options.input,
43293
+ output: options.output,
43294
+ mcp: options.mcp === void 0 ? void 0 : Object.freeze({ ...options.mcp }),
43295
+ run
43296
+ });
43297
+ }
43298
+ __name(createServerFunctionDescriptor, "createServerFunctionDescriptor");
43299
+ function _attachServerFunctionDescriptor(target, descriptor) {
43300
+ Object.defineProperty(target, FARM_SERVER_FUNCTION_DESCRIPTOR, {
43301
+ value: descriptor,
43302
+ enumerable: false
43303
+ });
43304
+ }
43305
+ __name(_attachServerFunctionDescriptor, "_attachServerFunctionDescriptor");
43306
+ function getServerFunctionRunner(value) {
43307
+ if (typeof value !== "function") return void 0;
43308
+ return value[FARM_SERVER_FUNCTION_DESCRIPTOR];
43309
+ }
43310
+ __name(getServerFunctionRunner, "getServerFunctionRunner");
43311
+ function _runServerFunctionForCaller(value, input) {
43312
+ const runner = getServerFunctionRunner(value);
43313
+ if (!runner) throw new TypeError("Expected a function created with createServerFn");
43314
+ return runner.run(input);
43315
+ }
43316
+ __name(_runServerFunctionForCaller, "_runServerFunctionForCaller");
43036
43317
  var UNSAFE_FORM_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
43037
43318
  function createServerFn(options) {
43038
43319
  if (!options || typeof options.handler !== "function") {
@@ -43041,10 +43322,15 @@ function createServerFn(options) {
43041
43322
  const middleware = resolveServerFnMiddleware(options.middleware);
43042
43323
  const errors = normalizeServerFnErrors(options.errors);
43043
43324
  const error = createServerFnErrorHandler(errors);
43044
- const serverFn = /* @__PURE__ */ __name(async (value) => {
43325
+ const run = /* @__PURE__ */ __name(async (value, labelInputErrors) => {
43045
43326
  const formData = isFormData(value) ? value : void 0;
43046
43327
  const rawInput = formData ? formDataToObject2(formData) : value;
43047
- const input = await _parseServerFnSchema(options.input, rawInput, "input");
43328
+ let input;
43329
+ try {
43330
+ input = await _parseServerFnSchema(options.input, rawInput, "input");
43331
+ } catch (cause) {
43332
+ throw labelInputErrors && isSchemaValidationFailure(cause) ? new ServerFnInputError(cause) : cause;
43333
+ }
43048
43334
  const executionContext = getServerActionExecutionContext();
43049
43335
  const request2 = executionContext?.request ?? _resolveCurrentRequest();
43050
43336
  const signal = executionContext?.signal ?? request2?.signal ?? getServerActionSignal();
@@ -43070,7 +43356,8 @@ function createServerFn(options) {
43070
43356
  await applyFarmCacheInvalidationTargets(declaration);
43071
43357
  }
43072
43358
  return parsedResult;
43073
- }, "serverFn");
43359
+ }, "run");
43360
+ const serverFn = /* @__PURE__ */ __name((value) => run(value, false), "serverFn");
43074
43361
  Object.defineProperties(serverFn, {
43075
43362
  [FARM_SERVER_FN_SYMBOL]: {
43076
43363
  value: true,
@@ -43101,6 +43388,10 @@ function createServerFn(options) {
43101
43388
  enumerable: false
43102
43389
  }
43103
43390
  });
43391
+ _attachServerFunctionDescriptor(
43392
+ serverFn,
43393
+ createServerFunctionDescriptor("action", options, (value) => run(value, true))
43394
+ );
43104
43395
  return serverFn;
43105
43396
  }
43106
43397
  __name(createServerFn, "createServerFn");
@@ -43258,9 +43549,17 @@ async function _parseServerFnSchema(schema, value, contract, owner = "createServ
43258
43549
  throw new TypeError(`${owner} ${contract} must provide parse, parseAsync, or safeParse`);
43259
43550
  }
43260
43551
  __name(_parseServerFnSchema, "_parseServerFnSchema");
43552
+ var schemaValidationFailures = /* @__PURE__ */ new WeakSet();
43553
+ function isSchemaValidationFailure(error) {
43554
+ if (!error || typeof error !== "object") return false;
43555
+ return schemaValidationFailures.has(error) || Array.isArray(error.issues);
43556
+ }
43557
+ __name(isSchemaValidationFailure, "isSchemaValidationFailure");
43261
43558
  function unwrapSafeParseResult(result) {
43262
43559
  if (result && typeof result === "object" && "success" in result && result.success === false) {
43263
- throw result.error;
43560
+ const error = result.error;
43561
+ if (error && typeof error === "object") schemaValidationFailures.add(error);
43562
+ throw error;
43264
43563
  }
43265
43564
  if (result && typeof result === "object" && "success" in result && result.success === true) {
43266
43565
  return result.data;
@@ -43377,6 +43676,16 @@ function createServerQuery(options) {
43377
43676
  enumerable: false
43378
43677
  }
43379
43678
  });
43679
+ _attachServerFunctionDescriptor(
43680
+ query,
43681
+ createServerFunctionDescriptor("query", options, async (value) => {
43682
+ const result = await _runServerFunctionForCaller(
43683
+ execute,
43684
+ value
43685
+ );
43686
+ return result.data;
43687
+ })
43688
+ );
43380
43689
  return query;
43381
43690
  }
43382
43691
  __name(createServerQuery, "createServerQuery");