@farm.js/core 0.1.16 → 0.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/dist/agent-runtime.d.mts +3 -3
  2. package/dist/agent-runtime.d.ts +3 -3
  3. package/dist/api/client.cjs +62 -28
  4. package/dist/api/client.d.mts +3 -3
  5. package/dist/api/client.d.ts +3 -3
  6. package/dist/api/client.mjs +3 -3
  7. package/dist/api/route-manager.cjs +69 -32
  8. package/dist/api/route-manager.d.mts +3 -3
  9. package/dist/api/route-manager.d.ts +3 -3
  10. package/dist/api/route-manager.mjs +5 -5
  11. package/dist/api/runtime.cjs +65 -29
  12. package/dist/api/runtime.d.mts +3 -3
  13. package/dist/api/runtime.d.ts +3 -3
  14. package/dist/api/runtime.mjs +6 -3
  15. package/dist/{api-client-B-n3pm_Q.d.mts → api-client-Cx54IR5g.d.mts} +2 -2
  16. package/dist/{api-client-C0_NZEBl.d.ts → api-client-DykpaKcY.d.ts} +2 -2
  17. package/dist/api.cjs +106 -33
  18. package/dist/api.d.mts +5 -5
  19. package/dist/api.d.ts +5 -5
  20. package/dist/api.mjs +8 -8
  21. package/dist/{app-AyjEsCBq.d.ts → app-BHY_10Lm.d.ts} +3 -3
  22. package/dist/{app-CYPHeOo_.d.mts → app-BMk0do23.d.mts} +3 -3
  23. package/dist/app-markdown.d.mts +4 -4
  24. package/dist/app-markdown.d.ts +4 -4
  25. package/dist/app-markdown.mjs +3 -3
  26. package/dist/cache.cjs +62 -28
  27. package/dist/cache.d.mts +11 -1
  28. package/dist/cache.d.ts +11 -1
  29. package/dist/cache.mjs +1 -1
  30. package/dist/{chunk-7HDZYYS4.mjs → chunk-4OOBRCJX.mjs} +27 -5
  31. package/dist/{chunk-NHHKW2T6.mjs → chunk-56DAX2BE.mjs} +170 -52
  32. package/dist/{chunk-B76DT5Y6.mjs → chunk-57J3Y7Y3.mjs} +1 -1
  33. package/dist/{chunk-MOQNHLTS.mjs → chunk-5QOEPUYE.mjs} +5 -2
  34. package/dist/{chunk-HKLRP3BN.mjs → chunk-5SPPCN5J.mjs} +1 -1
  35. package/dist/{chunk-LUC2FAGW.mjs → chunk-6VQIKZZO.mjs} +1 -1
  36. package/dist/{chunk-7ZWL7XOU.mjs → chunk-76DG3LF3.mjs} +1 -1
  37. package/dist/{chunk-EWDK36MM.mjs → chunk-A72YEUZ3.mjs} +1 -1
  38. package/dist/{chunk-ZHOIQC6U.mjs → chunk-ATERBVHQ.mjs} +2 -2
  39. package/dist/{chunk-27JNCYEK.mjs → chunk-EN7WTEAY.mjs} +2 -2
  40. package/dist/{chunk-IGO2HEV7.mjs → chunk-F6SJAKFJ.mjs} +62 -28
  41. package/dist/{chunk-GSDIZACQ.mjs → chunk-FG5H2VCJ.mjs} +2 -2
  42. package/dist/{chunk-LZK5CXDW.mjs → chunk-KLSSO6YD.mjs} +2 -2
  43. package/dist/{chunk-KUO3GBPK.mjs → chunk-L6V3P73N.mjs} +1 -1
  44. package/dist/{chunk-TYVVIQ5M.mjs → chunk-MVIWBEJF.mjs} +32 -25
  45. package/dist/{chunk-KTGFMHET.mjs → chunk-N6UROPT7.mjs} +1 -1
  46. package/dist/{chunk-NDD2YVGU.mjs → chunk-NRVGEI5I.mjs} +10 -3
  47. package/dist/{chunk-IXTEENRS.mjs → chunk-QGVJVSNX.mjs} +5 -5
  48. package/dist/{chunk-6SCB2MXB.mjs → chunk-SXHV42UQ.mjs} +16 -1
  49. package/dist/{chunk-OWTIOHON.mjs → chunk-SYGGPS4A.mjs} +2 -2
  50. package/dist/{chunk-NC333MFA.mjs → chunk-TSWW5BVH.mjs} +7 -4
  51. package/dist/{chunk-LK6FGAQR.mjs → chunk-UDBJCUPA.mjs} +7 -4
  52. package/dist/{chunk-NUD6XBMO.mjs → chunk-UTBVHYS3.mjs} +2 -2
  53. package/dist/{chunk-76MNRHTS.mjs → chunk-UUYF3CHN.mjs} +2 -2
  54. package/dist/{chunk-VVTREAG5.mjs → chunk-WD4YXVLV.mjs} +11 -3
  55. package/dist/{chunk-UQZPTIML.mjs → chunk-WD5PNSOB.mjs} +2 -2
  56. package/dist/{chunk-DPZUDPVJ.mjs → chunk-XP777LRD.mjs} +1 -1
  57. package/dist/{chunk-KATQ6I56.mjs → chunk-XWAYMDLB.mjs} +1 -1
  58. package/dist/{chunk-IL5RWYK7.mjs → chunk-YD4J4XCI.mjs} +1 -1
  59. package/dist/{chunk-Q3MDL7TM.mjs → chunk-ZCNJKLA2.mjs} +30 -11
  60. package/dist/{client-plugins-CqVtZi5X.d.ts → client-plugins-C089bQhN.d.ts} +2 -2
  61. package/dist/{client-plugins-CIPRtSsW.d.mts → client-plugins-JXXmZliS.d.mts} +2 -2
  62. package/dist/client-plugins.d.mts +3 -3
  63. package/dist/client-plugins.d.ts +3 -3
  64. package/dist/client.cjs +62 -28
  65. package/dist/client.d.mts +8 -8
  66. package/dist/client.d.ts +8 -8
  67. package/dist/client.mjs +6 -6
  68. package/dist/config.d.mts +3 -3
  69. package/dist/config.d.ts +3 -3
  70. package/dist/cron.mjs +2 -2
  71. package/dist/{devtools-IU7LKZOH.mjs → devtools-UFVTMQX5.mjs} +7 -7
  72. package/dist/docs.cjs +18 -10
  73. package/dist/docs.mjs +9 -9
  74. package/dist/{endpoint-kSAxE52R.d.ts → endpoint-1zA994xL.d.ts} +1 -1
  75. package/dist/{endpoint-Bu3XgeMK.d.mts → endpoint-DAc96i93.d.mts} +1 -1
  76. package/dist/env.cjs +39 -5
  77. package/dist/env.d.mts +5 -3
  78. package/dist/env.d.ts +5 -3
  79. package/dist/env.mjs +2 -1
  80. package/dist/index.cjs +311 -93
  81. package/dist/index.d.mts +14 -14
  82. package/dist/index.d.ts +14 -14
  83. package/dist/index.mjs +34 -34
  84. package/dist/integrations.d.mts +3 -3
  85. package/dist/integrations.d.ts +3 -3
  86. package/dist/internal/app-markdown-runtime.d.mts +3 -3
  87. package/dist/internal/app-markdown-runtime.d.ts +3 -3
  88. package/dist/internal/app-markdown-runtime.mjs +2 -2
  89. package/dist/internal/build-runtime.cjs +342 -121
  90. package/dist/internal/build-runtime.d.mts +5 -5
  91. package/dist/internal/build-runtime.d.ts +5 -5
  92. package/dist/internal/build-runtime.mjs +23 -23
  93. package/dist/internal/cli-runtime.cjs +77 -31
  94. package/dist/internal/cli-runtime.mjs +13 -13
  95. package/dist/internal/client-error-overlay.cjs +1 -1
  96. package/dist/internal/client-error-overlay.mjs +1 -1
  97. package/dist/internal/compression-runtime.d.mts +3 -3
  98. package/dist/internal/compression-runtime.d.ts +3 -3
  99. package/dist/internal/config-runtime.cjs +14 -2
  100. package/dist/internal/config-runtime.d.mts +4 -4
  101. package/dist/internal/config-runtime.d.ts +4 -4
  102. package/dist/internal/config-runtime.mjs +7 -7
  103. package/dist/internal/product-telemetry-runtime.cjs +1 -1
  104. package/dist/internal/product-telemetry-runtime.mjs +1 -1
  105. package/dist/internal/production-runtime.cjs +101 -41
  106. package/dist/internal/production-runtime.d.mts +9 -9
  107. package/dist/internal/production-runtime.d.ts +9 -9
  108. package/dist/internal/production-runtime.mjs +6 -6
  109. package/dist/markdown.cjs +16 -1
  110. package/dist/markdown.mjs +1 -1
  111. package/dist/{metadata-8g__AMPM.d.ts → metadata-BcNJP4fq.d.ts} +1 -1
  112. package/dist/{metadata-OMX6wFNf.d.mts → metadata-C1Z9vLbb.d.mts} +1 -1
  113. package/dist/middleware.cjs +10 -3
  114. package/dist/middleware.d.mts +5 -5
  115. package/dist/middleware.d.ts +5 -5
  116. package/dist/middleware.mjs +4 -4
  117. package/dist/{nitro-3N4ZXRYM.mjs → nitro-CVZ36JM5.mjs} +4 -4
  118. package/dist/plugin.cjs +256 -105
  119. package/dist/plugin.d.mts +3 -3
  120. package/dist/plugin.d.ts +3 -3
  121. package/dist/plugin.mjs +19 -19
  122. package/dist/{production-runtime-W3M0eNDV.d.mts → production-runtime-jcrTlRTb.d.mts} +1 -1
  123. package/dist/{production-runtime-BJh7o6Cr.d.ts → production-runtime-oKmC0WU-.d.ts} +1 -1
  124. package/dist/{render-plan-io7pvDNc.d.mts → render-plan-BLIfc4jt.d.mts} +1 -1
  125. package/dist/{render-plan-Be4ZGTJP.d.ts → render-plan-DOB9cV-h.d.ts} +1 -1
  126. package/dist/renderer-client.cjs +62 -28
  127. package/dist/renderer-client.d.mts +5 -5
  128. package/dist/renderer-client.d.ts +5 -5
  129. package/dist/renderer-client.mjs +3 -3
  130. package/dist/{request-DZkHYQ89.d.mts → request-Cr53NRHr.d.mts} +1 -1
  131. package/dist/{request-G8JhKr4F.d.ts → request-Dt2gNuQD.d.ts} +1 -1
  132. package/dist/request.d.mts +4 -4
  133. package/dist/request.d.ts +4 -4
  134. package/dist/{route-C_eLaFTZ.d.mts → route-B0XrsrFk.d.mts} +1 -1
  135. package/dist/{route-BxNJT447.d.ts → route-DOEpbyWZ.d.ts} +1 -1
  136. package/dist/{route-rendering-BcLLPJgN.d.ts → route-rendering-CWYd8Mv1.d.ts} +1 -1
  137. package/dist/{route-rendering-CbAKr1TY.d.mts → route-rendering-CeFBEAoZ.d.mts} +1 -1
  138. package/dist/routes.cjs +68 -31
  139. package/dist/routes.d.mts +4 -4
  140. package/dist/routes.d.ts +4 -4
  141. package/dist/routes.mjs +2 -2
  142. package/dist/server-fn-client.d.mts +3 -3
  143. package/dist/server-fn-client.d.ts +3 -3
  144. package/dist/server-fn.cjs +72 -30
  145. package/dist/server-fn.d.mts +1 -1
  146. package/dist/server-fn.d.ts +1 -1
  147. package/dist/server-fn.mjs +2 -2
  148. package/dist/server-plugins.d.mts +4 -4
  149. package/dist/server-plugins.d.ts +4 -4
  150. package/dist/server-query-client.cjs +62 -28
  151. package/dist/server-query-client.d.mts +1 -1
  152. package/dist/server-query-client.d.ts +1 -1
  153. package/dist/server-query-client.mjs +4 -4
  154. package/dist/server-query.cjs +72 -30
  155. package/dist/server-query.d.mts +1 -1
  156. package/dist/server-query.d.ts +1 -1
  157. package/dist/server-query.mjs +3 -3
  158. package/dist/server.cjs +239 -80
  159. package/dist/server.d.mts +9 -9
  160. package/dist/server.d.ts +9 -9
  161. package/dist/server.mjs +22 -22
  162. package/dist/{spa-router-BcS_4nqm.d.mts → spa-router-CQWiYGxS.d.mts} +2 -2
  163. package/dist/{spa-router-BzFBUJkn.d.ts → spa-router-Wjiw-8hB.d.ts} +2 -2
  164. package/dist/testing.cjs +73 -32
  165. package/dist/testing.d.mts +3 -3
  166. package/dist/testing.d.ts +3 -3
  167. package/dist/testing.mjs +11 -7
  168. package/dist/{utils-C4yrAhNc.d.ts → utils-B0XJmG_b.d.ts} +1 -1
  169. package/dist/{utils-5kQP1mFR.d.mts → utils-uUxF0K0P.d.mts} +1 -1
  170. package/dist/version.cjs +1 -1
  171. package/dist/version.mjs +1 -1
  172. package/dist/vite.cjs +260 -109
  173. package/dist/vite.d.mts +3 -3
  174. package/dist/vite.d.ts +3 -3
  175. package/dist/vite.mjs +19 -19
  176. package/dist/workflows.mjs +2 -2
  177. package/package.json +2 -2
  178. package/dist/{chunk-VO5SCWF5.mjs → chunk-BNGS6KJ6.mjs} +0 -0
  179. package/dist/{chunk-MUUZJLCI.mjs → chunk-EGJDUF4Q.mjs} +3 -3
  180. package/dist/{chunk-4L7SZOHZ.mjs → chunk-YHOCRI4H.mjs} +3 -3
package/dist/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));
6599
6635
  }
6600
- this.pruneInvalidatedTagVersions();
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);
6653
+ }
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)) {
@@ -11976,10 +12040,12 @@ function createBundledEnv(env2, source = getProcessEnv()) {
11976
12040
  const server = {};
11977
12041
  const runtime3 = {};
11978
12042
  for (const [key, value] of Object.entries(resolved.server)) {
11979
- if (source[key] === void 0) {
11980
- server[key] = value;
12043
+ const raw = source[key];
12044
+ const type = getRuntimeEnvType(value);
12045
+ if (raw !== void 0 && isSameEnvValue(coerceRuntimeEnvValue(raw, type), value)) {
12046
+ runtime3[key] = type;
11981
12047
  } else {
11982
- runtime3[key] = getRuntimeEnvType(value);
12048
+ server[key] = value;
11983
12049
  }
11984
12050
  }
11985
12051
  return {
@@ -12078,9 +12144,8 @@ function readServerEnvKey(server, key) {
12078
12144
  function readRuntimeServerEnv(env2) {
12079
12145
  const state = env2[FARM_ENV_RUNTIME_SYMBOL];
12080
12146
  if (!state) return;
12081
- const source = getProcessEnv();
12082
12147
  for (const [key, type] of Object.entries(state.pending)) {
12083
- const raw = source[key];
12148
+ const raw = readFarmEnvironmentValue(key);
12084
12149
  if (raw === void 0) continue;
12085
12150
  env2.server[key] = coerceRuntimeEnvValue(raw, type);
12086
12151
  delete state.pending[key];
@@ -12111,6 +12176,22 @@ function coerceRuntimeEnvValue(raw, type) {
12111
12176
  }
12112
12177
  return raw;
12113
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]));
12183
+ }
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
+ }
12114
12195
  function prepareEnv(env2) {
12115
12196
  const normalized = normalizeResolvedEnv(env2);
12116
12197
  const runtime3 = env2.runtime?.server;
@@ -12186,6 +12267,7 @@ var FARM_ENV_SYMBOL, FARM_ENV_RUNTIME_SYMBOL, farmEnvGlobal, currentEnv, env, pu
12186
12267
  var init_env = __esm({
12187
12268
  "src/env.ts"() {
12188
12269
  "use strict";
12270
+ init_runtime_env();
12189
12271
  FARM_ENV_SYMBOL = /* @__PURE__ */ Symbol.for("farm.env");
12190
12272
  FARM_ENV_RUNTIME_SYMBOL = /* @__PURE__ */ Symbol.for("farm.env.runtime");
12191
12273
  farmEnvGlobal = globalThis;
@@ -12204,6 +12286,8 @@ var init_env = __esm({
12204
12286
  __name(readRuntimeServerEnv, "readRuntimeServerEnv");
12205
12287
  __name(getRuntimeEnvType, "getRuntimeEnvType");
12206
12288
  __name(coerceRuntimeEnvValue, "coerceRuntimeEnvValue");
12289
+ __name(isSameEnvValue, "isSameEnvValue");
12290
+ __name(isPlainObject3, "isPlainObject");
12207
12291
  __name(prepareEnv, "prepareEnv");
12208
12292
  __name(assertServerEnvAccess, "assertServerEnvAccess");
12209
12293
  __name(getInitialEnv, "getInitialEnv");
@@ -17481,6 +17565,7 @@ function createFarmDocsHandler(docs, options) {
17481
17565
  if (!isFarmDocsRequest(docs, request2)) return null;
17482
17566
  const page2 = loadPage(contentDir, docs, request2);
17483
17567
  if (!page2) return null;
17568
+ const negotiatesAccept = !requestUrl.pathname.endsWith(".md");
17484
17569
  if (shouldReturnMarkdown(request2)) {
17485
17570
  const origin = new URL(request2.url).origin;
17486
17571
  return omitFarmDocsHeadBody(
@@ -17495,7 +17580,8 @@ function createFarmDocsHandler(docs, options) {
17495
17580
  status: 200,
17496
17581
  headers: {
17497
17582
  "Content-Type": "text/markdown; charset=utf-8",
17498
- "Cache-Control": "public, max-age=60"
17583
+ "Cache-Control": "public, max-age=60",
17584
+ ...negotiatesAccept ? { Vary: "Accept" } : {}
17499
17585
  }
17500
17586
  }
17501
17587
  )
@@ -17525,6 +17611,7 @@ function createFarmDocsHandler(docs, options) {
17525
17611
  headers: {
17526
17612
  "Content-Type": "text/html; charset=utf-8",
17527
17613
  "Cache-Control": "public, s-maxage=60, stale-while-revalidate=300",
17614
+ Vary: "Accept",
17528
17615
  ...fontPreloadHeader ? { Link: fontPreloadHeader } : {}
17529
17616
  }
17530
17617
  }
@@ -24134,7 +24221,7 @@ function resolveImportedModule(importerPath, specifier, root) {
24134
24221
  return { path: resolveImportedModuleSourcePath(importerPath, specifier, root), local: true };
24135
24222
  }
24136
24223
  const aliased = resolveProjectAliasSourcePath(specifier, root);
24137
- if (aliased !== void 0) return { path: aliased, local: true };
24224
+ if (aliased) return { path: aliased, local: true };
24138
24225
  return { path: resolvePackageModuleSourcePath(importerPath, specifier, root), local: false };
24139
24226
  }
24140
24227
  __name(resolveImportedModule, "resolveImportedModule");
@@ -24150,11 +24237,12 @@ function resolveProjectAliasSourcePath(specifier, root) {
24150
24237
  if (!match || alias.prefix.length > match.alias.prefix.length) match = { alias, captured };
24151
24238
  }
24152
24239
  if (!match) return void 0;
24153
- return resolveSourceCandidate(
24240
+ const resolved = resolveSourceCandidate(
24154
24241
  match.alias.targets.map(
24155
24242
  (target) => import_path4.default.normalize(match.alias.wildcard ? target.replace("*", match.captured) : target)
24156
24243
  )
24157
24244
  );
24245
+ return resolved && /\.d\.[cm]?ts$/.test(resolved) ? null : resolved;
24158
24246
  }
24159
24247
  __name(resolveProjectAliasSourcePath, "resolveProjectAliasSourcePath");
24160
24248
  function matchProjectImportAlias(alias, specifier) {
@@ -24561,6 +24649,7 @@ __name(readAltText, "readAltText");
24561
24649
  // src/routing/route-manager.ts
24562
24650
  init_route_runtime();
24563
24651
  init_routing();
24652
+ init_base_path();
24564
24653
 
24565
24654
  // src/redirect-query.ts
24566
24655
  function appendFarmRedirectQuery(destination, search) {
@@ -25637,7 +25726,7 @@ var _RouteManager = class _RouteManager {
25637
25726
  }
25638
25727
  toRoutePathname(pathname) {
25639
25728
  const i18n = this.getI18nConfig();
25640
- return i18n ? stripFarmLocaleFromPathname(pathname, i18n) : pathname;
25729
+ return i18n ? stripFarmLocaleFromPathname(pathname, i18n) : stripFarmBasePath(pathname, this.config.basePath);
25641
25730
  }
25642
25731
  localizeRedirectDestination(destination, locale) {
25643
25732
  if (!locale || !destination.startsWith("/") || destination.startsWith("//")) {
@@ -29760,7 +29849,7 @@ _setFarmThemeServerSnapshotResolver(() => {
29760
29849
  });
29761
29850
 
29762
29851
  // package.json
29763
- var version = "0.1.16";
29852
+ var version = "0.1.17";
29764
29853
 
29765
29854
  // src/version.ts
29766
29855
  var FARM_VERSION = version;
@@ -30050,7 +30139,7 @@ function createPPRRefreshScript() {
30050
30139
  __name(createPPRRefreshScript, "createPPRRefreshScript");
30051
30140
  function createPreHydrationClickQueueScript() {
30052
30141
  const selector = JSON.stringify(FARM_ISLAND_REPLAYABLE_SELECTOR);
30053
- 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>`;
30054
30143
  }
30055
30144
  __name(createPreHydrationClickQueueScript, "createPreHydrationClickQueueScript");
30056
30145
  function createDocumentFooter(options) {
@@ -34141,7 +34230,7 @@ function createEndpoint(pathOrOptions, optionsOrHandler, maybeHandler) {
34141
34230
  wrappedHandler
34142
34231
  );
34143
34232
  endpoint.__path = path41 || void 0;
34144
- endpoint.__method = options.method || "GET";
34233
+ endpoint.__method = options.method || (path41 ? "GET" : void 0);
34145
34234
  endpoint.__autoPath = !path41;
34146
34235
  endpoint.__handler = wrappedHandler;
34147
34236
  endpoint.__farmInvoke = (ctx) => runEndpointMiddleware(middleware, ctx, handler, error, options.invalidates);
@@ -35729,7 +35818,7 @@ function parseColonParam(segment) {
35729
35818
  };
35730
35819
  }
35731
35820
  __name(parseColonParam, "parseColonParam");
35732
- function compilePathPattern(pattern) {
35821
+ function compilePathPattern(pattern, trailingSlash = false) {
35733
35822
  const params = [];
35734
35823
  const segments = pattern.split("/").filter(Boolean);
35735
35824
  if (segments.length === 0) {
@@ -35765,11 +35854,18 @@ function compilePathPattern(pattern) {
35765
35854
  });
35766
35855
  return {
35767
35856
  kind: "path",
35768
- regex: new RegExp(`^${parts.join("")}$`),
35857
+ regex: new RegExp(`^${parts.join("")}${trailingSlash ? "/?" : ""}$`),
35769
35858
  params
35770
35859
  };
35771
35860
  }
35772
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");
35773
35869
  function compilePattern(pattern) {
35774
35870
  if (pattern instanceof RegExp) {
35775
35871
  return { kind: "regexp", regex: pattern };
@@ -35789,7 +35885,7 @@ __name(compilePattern, "compilePattern");
35789
35885
  function compileMiddlewareConfig(config) {
35790
35886
  const compiled = {
35791
35887
  matcher: config.matcher ? toMatcherList(config.matcher).map(
35792
- (matcher) => typeof matcher === "function" ? matcher : compilePattern(matcher)
35888
+ (matcher) => typeof matcher === "function" ? matcher : compileMatcherPattern(matcher)
35793
35889
  ) : void 0,
35794
35890
  exclude: config.exclude?.map(compilePattern)
35795
35891
  };
@@ -37040,6 +37136,7 @@ __name(collectLegacyTypeArtifacts, "collectLegacyTypeArtifacts");
37040
37136
  // src/vite.ts
37041
37137
  init_routes_shared();
37042
37138
  init_markdown();
37139
+ init_base_path();
37043
37140
  init_llms_txt();
37044
37141
  init_agent_crawlers();
37045
37142
  init_response();
@@ -38969,8 +39066,8 @@ function farmPlugin(options = {}, initialPluginManager) {
38969
39066
  }, "emitPluginError");
38970
39067
  farmApp = new FarmApp(
38971
39068
  {
38972
- root: server.config.root,
38973
- ...options
39069
+ ...options,
39070
+ root: resolveDevelopmentRoot(options.root, server.config.root)
38974
39071
  },
38975
39072
  server
38976
39073
  );
@@ -39557,7 +39654,8 @@ window.__FARM_MANIFEST__ = ${inlineValue({
39557
39654
  () => middlewareManager.execute(req, res)
39558
39655
  );
39559
39656
  }, "runAppMiddlewareForContentRoute");
39560
- 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) {
39561
39659
  if (await runAppMiddlewareForContentRoute()) return;
39562
39660
  if (requestMethod !== "GET" && requestMethod !== "HEAD") {
39563
39661
  res.statusCode = 405;
@@ -39574,7 +39672,7 @@ window.__FARM_MANIFEST__ = ${inlineValue({
39574
39672
  res.end(requestMethod === "HEAD" ? void 0 : body);
39575
39673
  return;
39576
39674
  }
39577
- if (openAPIManager && requestPathname === options.openapi?.route) {
39675
+ if (openAPIManager && openAPIRequestPathname === options.openapi?.route) {
39578
39676
  if (await runAppMiddlewareForContentRoute()) return;
39579
39677
  const docsHandler = openAPIManager.getDocsRouteHandler(parsedRequestUrl.origin);
39580
39678
  return docsHandler(req, res);
@@ -40052,6 +40150,21 @@ window.__FARM_MANIFEST__ = ${inlineValue({
40052
40150
  headers: request2.headers,
40053
40151
  signal: request2.signal
40054
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
+ }
40055
40168
  await farmApp.getServerRenderer().runWithRequestContext(targetRequest, async () => {
40056
40169
  const routeManager3 = farmApp.getRouteManager();
40057
40170
  if (pm) {
@@ -40125,7 +40238,8 @@ window.__FARM_MANIFEST__ = ${inlineValue({
40125
40238
  {
40126
40239
  params,
40127
40240
  searchParams: Promise.resolve(searchParams),
40128
- path: targetUrl.pathname
40241
+ path: targetUrl.pathname,
40242
+ middleware: middlewareMap.size > 0 ? { data: middlewareMap } : void 0
40129
40243
  },
40130
40244
  routeContext
40131
40245
  ),
@@ -40213,27 +40327,34 @@ window.__FARM_MANIFEST__ = ${inlineValue({
40213
40327
  parseFarmLayoutChainHeader(request2.headers.get("x-farm-layout-chain")),
40214
40328
  destinationLayoutPatterns
40215
40329
  );
40216
- const fragmentHtml = await farmApp.getServerRenderer().renderNavigationFragment({
40217
- PageComponent: routeModule.default,
40218
- LoadingComponent: loadingModule?.default,
40219
- pageProps: routeProps,
40220
- params,
40221
- layouts: layouts.map((layout2, index) => ({
40222
- pattern: layout2.pattern,
40223
- module: layoutModules[index]
40224
- })),
40225
- layoutStartIndex,
40226
- slots: routeSlots.map((slot) => ({
40227
- name: slot.name,
40228
- ownerPattern: slot.ownerPattern,
40229
- containerId: slot.containerId,
40230
- module: slot.renderModule,
40231
- props: slot.props
40232
- })),
40233
- pageShouldHydrate: shouldHydrate,
40234
- layoutShouldHydrate: shouldHydrateLayout,
40235
- islandStrategy: hydrationIslandStrategy
40236
- });
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
+ );
40237
40358
  const pageData = {
40238
40359
  props: {
40239
40360
  params: routeProps.params,
@@ -40243,7 +40364,9 @@ window.__FARM_MANIFEST__ = ${inlineValue({
40243
40364
  ...routeProps.__farmCanonicalPath ? {
40244
40365
  __farmCanonicalPath: routeProps.__farmCanonicalPath
40245
40366
  } : {},
40246
- ...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) } } : {}
40247
40370
  },
40248
40371
  canonicalPath: routeProps.__farmCanonicalPath,
40249
40372
  modulePath: toUrlPath(route.modulePath),
@@ -40993,6 +41116,26 @@ function runFarmMiddlewareWithNavigation(renderer, middlewareRequest, req, res,
40993
41116
  });
40994
41117
  }
40995
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");
40996
41139
  function isFarmClientVirtualId(id) {
40997
41140
  const pathname = id.split("?", 1)[0];
40998
41141
  return pathname === "/@farm/client" || pathname === "/@farm/client.js";
@@ -41008,16 +41151,18 @@ function generateProgrammaticRouteModule(moduleId, root, renderer = REACT_RENDER
41008
41151
  return generateProgrammaticApiRouteModule(parsed.routePath, routeFile);
41009
41152
  }
41010
41153
  return `
41011
- import {
41012
- createElement as __farmCreateElement,
41013
- Suspense as __farmSuspense,
41014
- } from ${JSON.stringify(renderer.server)};
41154
+ import * as __farmRendererRuntime from ${JSON.stringify(renderer.server)};
41015
41155
  import {
41016
41156
  createLayoutModuleFromProgrammaticLayout as __farmCreateLayoutRouteModule,
41017
41157
  createRouteModuleFromProgrammaticPage as __farmCreatePageRouteModule,
41018
41158
  } from "@farm.js/core/routes";
41019
41159
  import * as __farmRoutesModule from ${JSON.stringify(routeFile)};
41020
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
+
41021
41166
  const __farmIsRouteDefinition = (value) => (
41022
41167
  value &&
41023
41168
  typeof value === "object" &&
@@ -41071,6 +41216,7 @@ const __farmRouteModule = __farmRoute.kind === "layout"
41071
41216
  : __farmCreatePageRouteModule(__farmRoute, {
41072
41217
  createElement: __farmCreateElement,
41073
41218
  Suspense: __farmSuspense,
41219
+ markFunctionComponent: __farmMarkFunctionComponent,
41074
41220
  });
41075
41221
 
41076
41222
  export const metadata = __farmRouteModule.metadata;
@@ -42680,6 +42826,11 @@ async function hydrate() {
42680
42826
  pendingPageHydrationController = hydrationController;
42681
42827
  await hydrateFarmIsolatedClientBoundaries(rootContainer, hydrationController.signal);
42682
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();
42683
42834
  return;
42684
42835
  }` : ""}
42685
42836
  if (!shouldHydrate) {
@@ -43178,7 +43329,7 @@ function createServerFn(options) {
43178
43329
  try {
43179
43330
  input = await _parseServerFnSchema(options.input, rawInput, "input");
43180
43331
  } catch (cause) {
43181
- throw labelInputErrors ? new ServerFnInputError(cause) : cause;
43332
+ throw labelInputErrors && isSchemaValidationFailure(cause) ? new ServerFnInputError(cause) : cause;
43182
43333
  }
43183
43334
  const executionContext = getServerActionExecutionContext();
43184
43335
  const request2 = executionContext?.request ?? _resolveCurrentRequest();
@@ -43398,9 +43549,17 @@ async function _parseServerFnSchema(schema, value, contract, owner = "createServ
43398
43549
  throw new TypeError(`${owner} ${contract} must provide parse, parseAsync, or safeParse`);
43399
43550
  }
43400
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");
43401
43558
  function unwrapSafeParseResult(result) {
43402
43559
  if (result && typeof result === "object" && "success" in result && result.success === false) {
43403
- throw result.error;
43560
+ const error = result.error;
43561
+ if (error && typeof error === "object") schemaValidationFailures.add(error);
43562
+ throw error;
43404
43563
  }
43405
43564
  if (result && typeof result === "object" && "success" in result && result.success === true) {
43406
43565
  return result.data;