@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/index.cjs CHANGED
@@ -7285,8 +7285,16 @@ async function createMarkdownMirrorResponse(options) {
7285
7285
  if (!hasMarkdownExtension) {
7286
7286
  headersOut.set("Vary", "Accept");
7287
7287
  }
7288
+ for (const token of pageResponse.headers.get("vary")?.split(",") ?? []) {
7289
+ const name2 = token.trim();
7290
+ if (name2 && name2.toLowerCase() !== "accept") appendHeaderToken(headersOut, "Vary", name2);
7291
+ }
7292
+ const pageCacheControl = pageResponse.headers.get("cache-control");
7288
7293
  const cache = target.route?.cache ?? options.config?.cache ?? false;
7289
- headersOut.set("Cache-Control", createMarkdownCacheHeader(cache));
7294
+ headersOut.set(
7295
+ "Cache-Control",
7296
+ pageCacheControl && isPrivateCacheControl(pageCacheControl) ? pageCacheControl : createMarkdownCacheHeader(cache)
7297
+ );
7290
7298
  return new Response(options.request.method === "HEAD" ? null : markdown, {
7291
7299
  status: pageResponse.status,
7292
7300
  headers: headersOut
@@ -7496,6 +7504,12 @@ function isHtmlResponse(response) {
7496
7504
  const contentType = response.headers.get("content-type") ?? "";
7497
7505
  return contentType.includes("text/html");
7498
7506
  }
7507
+ function isPrivateCacheControl(value) {
7508
+ return value.split(",").some((directive) => {
7509
+ const name2 = directive.split("=", 1)[0].trim().toLowerCase();
7510
+ return name2 === "private" || name2 === "no-store";
7511
+ });
7512
+ }
7499
7513
  function createMarkdownCacheHeader(cache) {
7500
7514
  if (cache === false || cache <= 0) {
7501
7515
  return "no-store";
@@ -7653,6 +7667,7 @@ var init_markdown = __esm({
7653
7667
  __name(findExposedMarkdownRoute, "findExposedMarkdownRoute");
7654
7668
  __name(routeMatches, "routeMatches");
7655
7669
  __name(isHtmlResponse, "isHtmlResponse");
7670
+ __name(isPrivateCacheControl, "isPrivateCacheControl");
7656
7671
  __name(createMarkdownCacheHeader, "createMarkdownCacheHeader");
7657
7672
  __name(extractHtmlTitle, "extractHtmlTitle");
7658
7673
  __name(extractHtmlBody, "extractHtmlBody");
@@ -12543,6 +12558,8 @@ var init_cache = __esm({
12543
12558
  constructor(config = {}) {
12544
12559
  this.entries = /* @__PURE__ */ new Map();
12545
12560
  this.inflight = /* @__PURE__ */ new Map();
12561
+ /** Local entries by tag, so tag counts and pruning never scan unrelated entries. */
12562
+ this.entriesByTag = /* @__PURE__ */ new Map();
12546
12563
  this.invalidatedTagVersions = /* @__PURE__ */ new Map();
12547
12564
  this.activeGenerations = /* @__PURE__ */ new Set();
12548
12565
  this.version = 0;
@@ -12561,6 +12578,7 @@ var init_cache = __esm({
12561
12578
  configure(config = {}) {
12562
12579
  this.generation++;
12563
12580
  this.entries.clear();
12581
+ this.entriesByTag.clear();
12564
12582
  this.inflight.clear();
12565
12583
  this.invalidatedTagVersions.clear();
12566
12584
  this.activeGenerations.clear();
@@ -12727,14 +12745,12 @@ var init_cache = __esm({
12727
12745
  return entry;
12728
12746
  }
12729
12747
  delete(key) {
12730
- const deleted = this.entries.delete(key);
12731
- if (deleted) this.pruneInvalidatedTagVersions();
12748
+ const deleted = this.deleteLocalEntry(key);
12732
12749
  emitFarmEvent({ type: "cache.delete", key, deleted });
12733
12750
  return deleted;
12734
12751
  }
12735
12752
  async deleteAsync(key) {
12736
- const deleted = this.entries.delete(key);
12737
- if (deleted) this.pruneInvalidatedTagVersions();
12753
+ const deleted = this.deleteLocalEntry(key);
12738
12754
  if (this.adapter) {
12739
12755
  await this.adapter.delete(this.createAdapterKey(key));
12740
12756
  }
@@ -12745,6 +12761,7 @@ var init_cache = __esm({
12745
12761
  const count = this.entries.size;
12746
12762
  this.generation++;
12747
12763
  this.entries.clear();
12764
+ this.entriesByTag.clear();
12748
12765
  this.inflight.clear();
12749
12766
  this.invalidatedTagVersions.clear();
12750
12767
  this.activeGenerations.clear();
@@ -12830,23 +12847,32 @@ var init_cache = __esm({
12830
12847
  return cached.value;
12831
12848
  }
12832
12849
  const inflight = this.inflight.get(key);
12833
- if (inflight) {
12850
+ if (inflight && !this.wasInvalidatedSince(inflight.tags, inflight.startVersion)) {
12834
12851
  emitFarmEvent({ type: "cache.dedupe", key });
12835
- return inflight;
12852
+ return inflight.promise;
12836
12853
  }
12837
12854
  const tags = Array.from(normalizeCacheOptionsTags(options));
12838
12855
  const generation = this.generation;
12856
+ const startVersion = this.version;
12839
12857
  const promise = this.fillCacheEntry(key, producer, options, tags, generation).catch((error) => {
12840
12858
  emitFarmEvent({ type: "cache.error", key, operation: "set", error });
12841
12859
  throw error;
12842
12860
  }).finally(() => {
12843
- if (this.inflight.get(key) === promise) {
12861
+ if (this.inflight.get(key)?.promise === promise) {
12844
12862
  this.inflight.delete(key);
12845
12863
  }
12846
12864
  });
12847
- this.inflight.set(key, promise);
12865
+ this.inflight.set(key, { promise, tags, startVersion });
12848
12866
  return promise;
12849
12867
  }
12868
+ /** A fill that started before one of its tags was invalidated cannot satisfy later readers. */
12869
+ wasInvalidatedSince(tags, version2) {
12870
+ for (const tag of tags) {
12871
+ const invalidatedVersion = this.invalidatedTagVersions.get(tag);
12872
+ if (invalidatedVersion !== void 0 && invalidatedVersion > version2) return true;
12873
+ }
12874
+ return false;
12875
+ }
12850
12876
  async fillCacheEntry(key, producer, options, tags, generation) {
12851
12877
  const adapter = this.adapter;
12852
12878
  const namespace = this.namespace;
@@ -12887,7 +12913,7 @@ var init_cache = __esm({
12887
12913
  return value;
12888
12914
  } finally {
12889
12915
  this.activeGenerations.delete(activeGeneration);
12890
- this.pruneInvalidatedTagVersions();
12916
+ this.pruneInvalidatedTagVersions(activeGeneration.tags);
12891
12917
  if (leaseToken && adapter?.releaseLease) {
12892
12918
  try {
12893
12919
  await adapter.releaseLease(leaseKey, leaseToken);
@@ -12932,18 +12958,9 @@ var init_cache = __esm({
12932
12958
  }
12933
12959
  return void 0;
12934
12960
  }
12935
- countEntriesForTag(tag) {
12936
- let count = 0;
12937
- for (const entry of this.entries.values()) {
12938
- if (entry.tags.has(tag)) {
12939
- count++;
12940
- }
12941
- }
12942
- return count;
12943
- }
12944
12961
  countEntriesForTags(tags) {
12945
12962
  let count = 0;
12946
- for (const entry of this.entries.values()) {
12963
+ for (const entry of this.entriesByTag.get(tags[0]) ?? []) {
12947
12964
  if (tags.every((tag) => entry.tags.has(tag))) {
12948
12965
  count++;
12949
12966
  }
@@ -12951,10 +12968,10 @@ var init_cache = __esm({
12951
12968
  return count;
12952
12969
  }
12953
12970
  invalidateTag(normalizedTag) {
12954
- const count = this.countEntriesForTag(normalizedTag);
12971
+ const count = this.entriesByTag.get(normalizedTag)?.size ?? 0;
12955
12972
  this.invalidatedTagVersions.delete(normalizedTag);
12956
12973
  this.invalidatedTagVersions.set(normalizedTag, ++this.version);
12957
- this.pruneInvalidatedTagVersions();
12974
+ this.pruneInvalidatedTagVersions([normalizedTag]);
12958
12975
  return count;
12959
12976
  }
12960
12977
  toPublicEntry(entry) {
@@ -12984,19 +13001,51 @@ var init_cache = __esm({
12984
13001
  this.entries.set(key, entry);
12985
13002
  }
12986
13003
  storeLocalEntry(entry) {
12987
- this.entries.delete(entry.key);
13004
+ const removed = [];
13005
+ const replaced = this.detachLocalEntry(entry.key);
13006
+ if (replaced) removed.push(replaced);
12988
13007
  this.entries.set(entry.key, entry);
13008
+ for (const tag of entry.tags) {
13009
+ let tagged = this.entriesByTag.get(tag);
13010
+ if (!tagged) this.entriesByTag.set(tag, tagged = /* @__PURE__ */ new Set());
13011
+ tagged.add(entry);
13012
+ }
12989
13013
  while (this.entries.size > this.maxEntries) {
12990
13014
  const oldestKey = this.entries.keys().next().value;
12991
13015
  if (oldestKey === void 0) break;
12992
- this.entries.delete(oldestKey);
13016
+ removed.push(this.detachLocalEntry(oldestKey));
13017
+ }
13018
+ for (const removedEntry of removed) this.pruneInvalidatedTagVersions(removedEntry.tags);
13019
+ }
13020
+ deleteLocalEntry(key) {
13021
+ const entry = this.detachLocalEntry(key);
13022
+ if (!entry) return false;
13023
+ this.pruneInvalidatedTagVersions(entry.tags);
13024
+ return true;
13025
+ }
13026
+ detachLocalEntry(key) {
13027
+ const entry = this.entries.get(key);
13028
+ if (!entry) return void 0;
13029
+ this.entries.delete(key);
13030
+ for (const tag of entry.tags) {
13031
+ const tagged = this.entriesByTag.get(tag);
13032
+ if (!tagged) continue;
13033
+ tagged.delete(entry);
13034
+ if (tagged.size === 0) this.entriesByTag.delete(tag);
12993
13035
  }
12994
- this.pruneInvalidatedTagVersions();
13036
+ return entry;
12995
13037
  }
12996
- pruneInvalidatedTagVersions() {
12997
- tags: for (const [tag, invalidatedVersion] of this.invalidatedTagVersions) {
12998
- for (const entry of this.entries.values()) {
12999
- if (entry.tags.has(tag) && entry.createdVersion < invalidatedVersion) continue tags;
13038
+ /**
13039
+ * Drop invalidation versions that no local entry or active fill can be stale against.
13040
+ * Callers pass only the tags whose dependents just changed, so the cost is bounded by
13041
+ * the entries sharing those tags rather than by the whole cache.
13042
+ */
13043
+ pruneInvalidatedTagVersions(tags) {
13044
+ tags: for (const tag of tags) {
13045
+ const invalidatedVersion = this.invalidatedTagVersions.get(tag);
13046
+ if (invalidatedVersion === void 0) continue;
13047
+ for (const entry of this.entriesByTag.get(tag) ?? []) {
13048
+ if (entry.createdVersion < invalidatedVersion) continue tags;
13000
13049
  }
13001
13050
  for (const generation of this.activeGenerations) {
13002
13051
  if (generation.tags.has(tag) && generation.createdVersion < invalidatedVersion)
@@ -13394,6 +13443,7 @@ function createProgrammaticPageComponent(route2, rendererRuntime) {
13394
13443
  }
13395
13444
  return rendererRuntime.createElement(...args);
13396
13445
  }, "createElement");
13446
+ const markFunctionComponent = /* @__PURE__ */ __name((component) => rendererRuntime?.markFunctionComponent?.(component) ?? component, "markFunctionComponent");
13397
13447
  const Component = route2.component;
13398
13448
  if (route2.pending) {
13399
13449
  const PendingComponent = route2.pending;
@@ -13415,7 +13465,9 @@ function createProgrammaticPageComponent(route2, rendererRuntime) {
13415
13465
  throw error;
13416
13466
  }
13417
13467
  }, "FarmProgrammaticPageContent");
13418
- const PageContent = FarmProgrammaticPageContent2;
13468
+ const PageContent = markFunctionComponent(
13469
+ FarmProgrammaticPageContent2
13470
+ );
13419
13471
  const FarmProgrammaticPage = /* @__PURE__ */ __name(function FarmProgrammaticPage2(props) {
13420
13472
  return createElement4(
13421
13473
  rendererRuntime.Suspense,
@@ -13425,7 +13477,7 @@ function createProgrammaticPageComponent(route2, rendererRuntime) {
13425
13477
  createElement4(PageContent, props)
13426
13478
  );
13427
13479
  }, "FarmProgrammaticPage");
13428
- return FarmProgrammaticPage;
13480
+ return markFunctionComponent(FarmProgrammaticPage);
13429
13481
  }
13430
13482
  const FarmProgrammaticPageContent = /* @__PURE__ */ __name(async function FarmProgrammaticPageContent2(props) {
13431
13483
  try {
@@ -13444,7 +13496,7 @@ function createProgrammaticPageComponent(route2, rendererRuntime) {
13444
13496
  throw error;
13445
13497
  }
13446
13498
  }, "FarmProgrammaticPageContent");
13447
- return FarmProgrammaticPageContent;
13499
+ return markFunctionComponent(FarmProgrammaticPageContent);
13448
13500
  }
13449
13501
  function readProgrammaticRouteProps(route2, props, resources) {
13450
13502
  if (isProgrammaticRoutePropsResolved(props)) {
@@ -15104,7 +15156,7 @@ function resolveImportedModule(importerPath, specifier, root) {
15104
15156
  return { path: resolveImportedModuleSourcePath(importerPath, specifier, root), local: true };
15105
15157
  }
15106
15158
  const aliased = resolveProjectAliasSourcePath(specifier, root);
15107
- if (aliased !== void 0) return { path: aliased, local: true };
15159
+ if (aliased) return { path: aliased, local: true };
15108
15160
  return { path: resolvePackageModuleSourcePath(importerPath, specifier, root), local: false };
15109
15161
  }
15110
15162
  function resolveProjectAliasSourcePath(specifier, root) {
@@ -15117,11 +15169,12 @@ function resolveProjectAliasSourcePath(specifier, root) {
15117
15169
  if (!match || alias.prefix.length > match.alias.prefix.length) match = { alias, captured };
15118
15170
  }
15119
15171
  if (!match) return void 0;
15120
- return resolveSourceCandidate(
15172
+ const resolved = resolveSourceCandidate(
15121
15173
  match.alias.targets.map(
15122
15174
  (target) => import_path4.default.normalize(match.alias.wildcard ? target.replace("*", match.captured) : target)
15123
15175
  )
15124
15176
  );
15177
+ return resolved && /\.d\.[cm]?ts$/.test(resolved) ? null : resolved;
15125
15178
  }
15126
15179
  function matchProjectImportAlias(alias, specifier) {
15127
15180
  if (!alias.wildcard) return specifier === alias.prefix ? "" : null;
@@ -15841,6 +15894,7 @@ var init_route_manager = __esm({
15841
15894
  init_static_metadata_image();
15842
15895
  init_route_runtime();
15843
15896
  init_routing();
15897
+ init_base_path();
15844
15898
  init_redirect_query();
15845
15899
  init_route_slots();
15846
15900
  init_renderer();
@@ -16822,7 +16876,7 @@ var init_route_manager = __esm({
16822
16876
  }
16823
16877
  toRoutePathname(pathname) {
16824
16878
  const i18n = this.getI18nConfig();
16825
- return i18n ? stripFarmLocaleFromPathname(pathname, i18n) : pathname;
16879
+ return i18n ? stripFarmLocaleFromPathname(pathname, i18n) : stripFarmBasePath(pathname, this.config.basePath);
16826
16880
  }
16827
16881
  localizeRedirectDestination(destination, locale) {
16828
16882
  if (!locale || !destination.startsWith("/") || destination.startsWith("//")) {
@@ -22038,7 +22092,7 @@ var init_server3 = __esm({
22038
22092
  var version;
22039
22093
  var init_package = __esm({
22040
22094
  "package.json"() {
22041
- version = "0.1.16";
22095
+ version = "0.1.17";
22042
22096
  }
22043
22097
  });
22044
22098
 
@@ -22947,7 +23001,7 @@ function createPPRRefreshScript() {
22947
23001
  }
22948
23002
  function createPreHydrationClickQueueScript() {
22949
23003
  const selector = JSON.stringify(FARM_ISLAND_REPLAYABLE_SELECTOR);
22950
- 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>`;
23004
+ 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>`;
22951
23005
  }
22952
23006
  function createDocumentFooter(options) {
22953
23007
  return `</div>
@@ -26378,10 +26432,12 @@ function createBundledEnv(env2, source = getProcessEnv()) {
26378
26432
  const server = {};
26379
26433
  const runtime3 = {};
26380
26434
  for (const [key, value] of Object.entries(resolved.server)) {
26381
- if (source[key] === void 0) {
26382
- server[key] = value;
26435
+ const raw = source[key];
26436
+ const type = getRuntimeEnvType(value);
26437
+ if (raw !== void 0 && isSameEnvValue(coerceRuntimeEnvValue(raw, type), value)) {
26438
+ runtime3[key] = type;
26383
26439
  } else {
26384
- runtime3[key] = getRuntimeEnvType(value);
26440
+ server[key] = value;
26385
26441
  }
26386
26442
  }
26387
26443
  return {
@@ -26493,9 +26549,8 @@ function readServerEnvKey(server, key) {
26493
26549
  function readRuntimeServerEnv(env2) {
26494
26550
  const state = env2[FARM_ENV_RUNTIME_SYMBOL];
26495
26551
  if (!state) return;
26496
- const source = getProcessEnv();
26497
26552
  for (const [key, type] of Object.entries(state.pending)) {
26498
- const raw = source[key];
26553
+ const raw = readFarmEnvironmentValue(key);
26499
26554
  if (raw === void 0) continue;
26500
26555
  env2.server[key] = coerceRuntimeEnvValue(raw, type);
26501
26556
  delete state.pending[key];
@@ -26526,6 +26581,22 @@ function coerceRuntimeEnvValue(raw, type) {
26526
26581
  }
26527
26582
  return raw;
26528
26583
  }
26584
+ function isSameEnvValue(left, right) {
26585
+ if (Object.is(left, right)) return true;
26586
+ if (Array.isArray(left) || Array.isArray(right)) {
26587
+ return Array.isArray(left) && Array.isArray(right) && left.length === right.length && left.every((item, index) => isSameEnvValue(item, right[index]));
26588
+ }
26589
+ if (!isPlainObject3(left) || !isPlainObject3(right)) return false;
26590
+ const keys = Object.keys(left);
26591
+ return keys.length === Object.keys(right).length && keys.every(
26592
+ (key) => Object.prototype.hasOwnProperty.call(right, key) && isSameEnvValue(left[key], right[key])
26593
+ );
26594
+ }
26595
+ function isPlainObject3(value) {
26596
+ if (!value || typeof value !== "object") return false;
26597
+ const prototype = Object.getPrototypeOf(value);
26598
+ return prototype === Object.prototype || prototype === null;
26599
+ }
26529
26600
  function prepareEnv(env2) {
26530
26601
  const normalized = normalizeResolvedEnv(env2);
26531
26602
  const runtime3 = env2.runtime?.server;
@@ -26601,6 +26672,7 @@ var FARM_ENV_SYMBOL, FARM_ENV_RUNTIME_SYMBOL, farmEnvGlobal, currentEnv, env, se
26601
26672
  var init_env = __esm({
26602
26673
  "src/env.ts"() {
26603
26674
  "use strict";
26675
+ init_runtime_env();
26604
26676
  FARM_ENV_SYMBOL = /* @__PURE__ */ Symbol.for("farm.env");
26605
26677
  FARM_ENV_RUNTIME_SYMBOL = /* @__PURE__ */ Symbol.for("farm.env.runtime");
26606
26678
  farmEnvGlobal = globalThis;
@@ -26622,6 +26694,8 @@ var init_env = __esm({
26622
26694
  __name(readRuntimeServerEnv, "readRuntimeServerEnv");
26623
26695
  __name(getRuntimeEnvType, "getRuntimeEnvType");
26624
26696
  __name(coerceRuntimeEnvValue, "coerceRuntimeEnvValue");
26697
+ __name(isSameEnvValue, "isSameEnvValue");
26698
+ __name(isPlainObject3, "isPlainObject");
26625
26699
  __name(prepareEnv, "prepareEnv");
26626
26700
  __name(assertServerEnvAccess, "assertServerEnvAccess");
26627
26701
  __name(getInitialEnv, "getInitialEnv");
@@ -27533,7 +27607,7 @@ function createEndpoint(pathOrOptions, optionsOrHandler, maybeHandler) {
27533
27607
  wrappedHandler
27534
27608
  );
27535
27609
  endpoint2.__path = path48 || void 0;
27536
- endpoint2.__method = options.method || "GET";
27610
+ endpoint2.__method = options.method || (path48 ? "GET" : void 0);
27537
27611
  endpoint2.__autoPath = !path48;
27538
27612
  endpoint2.__handler = wrappedHandler;
27539
27613
  endpoint2.__farmInvoke = (ctx) => runEndpointMiddleware(middleware2, ctx, handler, error, options.invalidates);
@@ -28392,6 +28466,7 @@ var init_runtime2 = __esm({
28392
28466
  init_response_body();
28393
28467
  init_route_shape();
28394
28468
  init_route_schema();
28469
+ init_endpoint();
28395
28470
  init_plugin_route_runtime();
28396
28471
  init_route_pattern2();
28397
28472
  init_route_pattern2();
@@ -29300,7 +29375,7 @@ function parseColonParam(segment) {
29300
29375
  modifier
29301
29376
  };
29302
29377
  }
29303
- function compilePathPattern(pattern) {
29378
+ function compilePathPattern(pattern, trailingSlash = false) {
29304
29379
  const params = [];
29305
29380
  const segments = pattern.split("/").filter(Boolean);
29306
29381
  if (segments.length === 0) {
@@ -29336,10 +29411,16 @@ function compilePathPattern(pattern) {
29336
29411
  });
29337
29412
  return {
29338
29413
  kind: "path",
29339
- regex: new RegExp(`^${parts.join("")}$`),
29414
+ regex: new RegExp(`^${parts.join("")}${trailingSlash ? "/?" : ""}$`),
29340
29415
  params
29341
29416
  };
29342
29417
  }
29418
+ function compileMatcherPattern(pattern) {
29419
+ if (typeof pattern === "string" && pattern !== "*" && !pattern.endsWith("(.*)")) {
29420
+ return compilePathPattern(pattern, true);
29421
+ }
29422
+ return compilePattern(pattern);
29423
+ }
29343
29424
  function compilePattern(pattern) {
29344
29425
  if (pattern instanceof RegExp) {
29345
29426
  return { kind: "regexp", regex: pattern };
@@ -29358,7 +29439,7 @@ function compilePattern(pattern) {
29358
29439
  function compileMiddlewareConfig(config) {
29359
29440
  const compiled = {
29360
29441
  matcher: config.matcher ? toMatcherList(config.matcher).map(
29361
- (matcher) => typeof matcher === "function" ? matcher : compilePattern(matcher)
29442
+ (matcher) => typeof matcher === "function" ? matcher : compileMatcherPattern(matcher)
29362
29443
  ) : void 0,
29363
29444
  exclude: config.exclude?.map(compilePattern)
29364
29445
  };
@@ -29446,6 +29527,7 @@ var init_matcher = __esm({
29446
29527
  __name(escapeRegex, "escapeRegex");
29447
29528
  __name(parseColonParam, "parseColonParam");
29448
29529
  __name(compilePathPattern, "compilePathPattern");
29530
+ __name(compileMatcherPattern, "compileMatcherPattern");
29449
29531
  __name(compilePattern, "compilePattern");
29450
29532
  __name(compileMiddlewareConfig, "compileMiddlewareConfig");
29451
29533
  __name(matchPattern, "matchPattern");
@@ -32728,6 +32810,66 @@ function mergeFarmViteConfig(farmConfig, userConfig = {}) {
32728
32810
  }
32729
32811
  };
32730
32812
  }
32813
+ function mergeExternal(farmValue, userValue) {
32814
+ if (farmValue === void 0) return userValue;
32815
+ if (userValue === void 0) return farmValue;
32816
+ if (farmValue === true || userValue === true) return true;
32817
+ return Array.from(/* @__PURE__ */ new Set([...farmValue, ...userValue]));
32818
+ }
32819
+ function mergeFarmProductionViteConfig(farmConfig, userConfig = {}) {
32820
+ const {
32821
+ plugins: _plugins,
32822
+ root: _root,
32823
+ base: _base,
32824
+ mode: _mode,
32825
+ appType: _appType,
32826
+ publicDir: _publicDir,
32827
+ build: userBuild = {},
32828
+ css: userCss,
32829
+ define: userDefine,
32830
+ esbuild: userEsbuild,
32831
+ ...shared2
32832
+ } = userConfig;
32833
+ const {
32834
+ outDir: _outDir,
32835
+ emptyOutDir: _emptyOutDir,
32836
+ ssr: _ssr,
32837
+ ssrEmitAssets: _ssrEmitAssets,
32838
+ write: _write,
32839
+ lib: _lib,
32840
+ watch: _watch,
32841
+ rollupOptions: userRollupOptions,
32842
+ rolldownOptions: userRolldownOptions,
32843
+ ...userBuildOptions
32844
+ } = userBuild;
32845
+ const {
32846
+ input: _input,
32847
+ output: _output,
32848
+ ...userBundlerOptions
32849
+ } = {
32850
+ ...userRollupOptions,
32851
+ ...userRolldownOptions
32852
+ };
32853
+ const merged = mergeFarmViteConfig(farmConfig, shared2);
32854
+ return {
32855
+ ...merged,
32856
+ build: {
32857
+ ...userBuildOptions,
32858
+ ...farmConfig.build,
32859
+ rollupOptions: {
32860
+ ...userBundlerOptions,
32861
+ ...farmConfig.build?.rollupOptions
32862
+ }
32863
+ },
32864
+ css: farmConfig.css || userCss ? { ...farmConfig.css, ...userCss } : void 0,
32865
+ define: farmConfig.define || userDefine ? { ...userDefine, ...farmConfig.define } : void 0,
32866
+ esbuild: typeof userEsbuild === "object" && farmConfig.esbuild !== false ? { ...userEsbuild, ...farmConfig.esbuild } : farmConfig.esbuild ?? userEsbuild,
32867
+ ssr: {
32868
+ ...merged.ssr,
32869
+ external: mergeExternal(farmConfig.ssr?.external, userConfig.ssr?.external)
32870
+ }
32871
+ };
32872
+ }
32731
32873
  var import_node_path16, FARM_CLIENT_ENTRY_PATTERN, FARM_CLIENT_OPTIMIZE_DEPS_INCLUDE;
32732
32874
  var init_vite_config = __esm({
32733
32875
  "src/server/vite-config.ts"() {
@@ -32756,6 +32898,8 @@ var init_vite_config = __esm({
32756
32898
  __name(mergeNoExternal, "mergeNoExternal");
32757
32899
  __name(mergeAlias, "mergeAlias");
32758
32900
  __name(mergeFarmViteConfig, "mergeFarmViteConfig");
32901
+ __name(mergeExternal, "mergeExternal");
32902
+ __name(mergeFarmProductionViteConfig, "mergeFarmProductionViteConfig");
32759
32903
  }
32760
32904
  });
32761
32905
 
@@ -34975,6 +35119,7 @@ function createFarmDocsHandler(docs, options) {
34975
35119
  if (!isFarmDocsRequest(docs, request2)) return null;
34976
35120
  const page2 = loadPage(contentDir, docs, request2);
34977
35121
  if (!page2) return null;
35122
+ const negotiatesAccept = !requestUrl.pathname.endsWith(".md");
34978
35123
  if (shouldReturnMarkdown(request2)) {
34979
35124
  const origin = new URL(request2.url).origin;
34980
35125
  return omitFarmDocsHeadBody(
@@ -34989,7 +35134,8 @@ function createFarmDocsHandler(docs, options) {
34989
35134
  status: 200,
34990
35135
  headers: {
34991
35136
  "Content-Type": "text/markdown; charset=utf-8",
34992
- "Cache-Control": "public, max-age=60"
35137
+ "Cache-Control": "public, max-age=60",
35138
+ ...negotiatesAccept ? { Vary: "Accept" } : {}
34993
35139
  }
34994
35140
  }
34995
35141
  )
@@ -35019,6 +35165,7 @@ function createFarmDocsHandler(docs, options) {
35019
35165
  headers: {
35020
35166
  "Content-Type": "text/html; charset=utf-8",
35021
35167
  "Cache-Control": "public, s-maxage=60, stale-while-revalidate=300",
35168
+ Vary: "Accept",
35022
35169
  ...fontPreloadHeader ? { Link: fontPreloadHeader } : {}
35023
35170
  }
35024
35171
  }
@@ -40152,8 +40299,8 @@ function farmPlugin(options = {}, initialPluginManager) {
40152
40299
  }, "emitPluginError");
40153
40300
  farmApp = new FarmApp(
40154
40301
  {
40155
- root: server.config.root,
40156
- ...options
40302
+ ...options,
40303
+ root: resolveDevelopmentRoot(options.root, server.config.root)
40157
40304
  },
40158
40305
  server
40159
40306
  );
@@ -40740,7 +40887,8 @@ window.__FARM_MANIFEST__ = ${inlineValue({
40740
40887
  () => middlewareManager.execute(req, res)
40741
40888
  );
40742
40889
  }, "runAppMiddlewareForContentRoute");
40743
- if (openAPIManager && options.openapi?.specRoute && requestPathname === options.openapi.specRoute) {
40890
+ const openAPIRequestPathname = openAPIManager ? stripFarmBasePath(requestPathname, farmConfig.basePath) : requestPathname;
40891
+ if (openAPIManager && options.openapi?.specRoute && openAPIRequestPathname === options.openapi.specRoute) {
40744
40892
  if (await runAppMiddlewareForContentRoute()) return;
40745
40893
  if (requestMethod !== "GET" && requestMethod !== "HEAD") {
40746
40894
  res.statusCode = 405;
@@ -40757,7 +40905,7 @@ window.__FARM_MANIFEST__ = ${inlineValue({
40757
40905
  res.end(requestMethod === "HEAD" ? void 0 : body);
40758
40906
  return;
40759
40907
  }
40760
- if (openAPIManager && requestPathname === options.openapi?.route) {
40908
+ if (openAPIManager && openAPIRequestPathname === options.openapi?.route) {
40761
40909
  if (await runAppMiddlewareForContentRoute()) return;
40762
40910
  const docsHandler = openAPIManager.getDocsRouteHandler(parsedRequestUrl.origin);
40763
40911
  return docsHandler(req, res);
@@ -41235,6 +41383,21 @@ window.__FARM_MANIFEST__ = ${inlineValue({
41235
41383
  headers: request2.headers,
41236
41384
  signal: request2.signal
41237
41385
  });
41386
+ let middlewareMap = /* @__PURE__ */ new Map();
41387
+ let middlewareContext = /* @__PURE__ */ new Map();
41388
+ if (middlewareManager?.hasMiddleware()) {
41389
+ const targetNodeRequest = createPageDataMiddlewareRequest(req, targetRequestUrl);
41390
+ const handled = await runFarmMiddlewareWithNavigation(
41391
+ farmApp.getServerRenderer(),
41392
+ targetRequest,
41393
+ targetNodeRequest,
41394
+ res,
41395
+ () => middlewareManager.execute(targetNodeRequest, res)
41396
+ );
41397
+ if (handled) return;
41398
+ middlewareMap = targetNodeRequest.__FARM_MIDDLEWARE_DATA__ ?? middlewareMap;
41399
+ middlewareContext = targetNodeRequest.__FARM_MIDDLEWARE_CONTEXT__ ?? middlewareContext;
41400
+ }
41238
41401
  await farmApp.getServerRenderer().runWithRequestContext(targetRequest, async () => {
41239
41402
  const routeManager3 = farmApp.getRouteManager();
41240
41403
  if (pm) {
@@ -41308,7 +41471,8 @@ window.__FARM_MANIFEST__ = ${inlineValue({
41308
41471
  {
41309
41472
  params,
41310
41473
  searchParams: Promise.resolve(searchParams),
41311
- path: targetUrl.pathname
41474
+ path: targetUrl.pathname,
41475
+ middleware: middlewareMap.size > 0 ? { data: middlewareMap } : void 0
41312
41476
  },
41313
41477
  routeContext
41314
41478
  ),
@@ -41396,27 +41560,34 @@ window.__FARM_MANIFEST__ = ${inlineValue({
41396
41560
  parseFarmLayoutChainHeader(request2.headers.get("x-farm-layout-chain")),
41397
41561
  destinationLayoutPatterns
41398
41562
  );
41399
- const fragmentHtml = await farmApp.getServerRenderer().renderNavigationFragment({
41400
- PageComponent: routeModule.default,
41401
- LoadingComponent: loadingModule?.default,
41402
- pageProps: routeProps,
41403
- params,
41404
- layouts: layouts.map((layout2, index) => ({
41405
- pattern: layout2.pattern,
41406
- module: layoutModules[index]
41407
- })),
41408
- layoutStartIndex,
41409
- slots: routeSlots.map((slot) => ({
41410
- name: slot.name,
41411
- ownerPattern: slot.ownerPattern,
41412
- containerId: slot.containerId,
41413
- module: slot.renderModule,
41414
- props: slot.props
41415
- })),
41416
- pageShouldHydrate: shouldHydrate,
41417
- layoutShouldHydrate: shouldHydrateLayout,
41418
- islandStrategy: hydrationIslandStrategy
41419
- });
41563
+ const renderer = farmApp.getServerRenderer();
41564
+ const fragmentHtml = await _runWithMiddlewareData(
41565
+ middlewareMap,
41566
+ () => _runWithMiddlewareContext(
41567
+ middlewareContext,
41568
+ () => renderer.renderNavigationFragment({
41569
+ PageComponent: routeModule.default,
41570
+ LoadingComponent: loadingModule?.default,
41571
+ pageProps: routeProps,
41572
+ params,
41573
+ layouts: layouts.map((layout2, index) => ({
41574
+ pattern: layout2.pattern,
41575
+ module: layoutModules[index]
41576
+ })),
41577
+ layoutStartIndex,
41578
+ slots: routeSlots.map((slot) => ({
41579
+ name: slot.name,
41580
+ ownerPattern: slot.ownerPattern,
41581
+ containerId: slot.containerId,
41582
+ module: slot.renderModule,
41583
+ props: slot.props
41584
+ })),
41585
+ pageShouldHydrate: shouldHydrate,
41586
+ layoutShouldHydrate: shouldHydrateLayout,
41587
+ islandStrategy: hydrationIslandStrategy
41588
+ })
41589
+ )
41590
+ );
41420
41591
  const pageData = {
41421
41592
  props: {
41422
41593
  params: routeProps.params,
@@ -41426,7 +41597,9 @@ window.__FARM_MANIFEST__ = ${inlineValue({
41426
41597
  ...routeProps.__farmCanonicalPath ? {
41427
41598
  __farmCanonicalPath: routeProps.__farmCanonicalPath
41428
41599
  } : {},
41429
- ...routeProps.__farmRoutePropsResolved ? { __farmRoutePropsResolved: true } : {}
41600
+ ...routeProps.__farmRoutePropsResolved ? { __farmRoutePropsResolved: true } : {},
41601
+ // The same serialized shape a full load embeds in __FARM_PROPS__.
41602
+ ...middlewareMap.size > 0 ? { middleware: { data: Object.fromEntries(middlewareMap) } } : {}
41430
41603
  },
41431
41604
  canonicalPath: routeProps.__farmCanonicalPath,
41432
41605
  modulePath: toUrlPath(route2.modulePath),
@@ -42174,6 +42347,24 @@ function runFarmMiddlewareWithNavigation(renderer, middlewareRequest, req, res,
42174
42347
  }
42175
42348
  });
42176
42349
  }
42350
+ function createPageDataMiddlewareRequest(req, target) {
42351
+ const targetNodeRequest = Object.create(req);
42352
+ targetNodeRequest.url = `${target.pathname}${target.search}`;
42353
+ targetNodeRequest.originalUrl = targetNodeRequest.url;
42354
+ targetNodeRequest.method = "GET";
42355
+ return targetNodeRequest;
42356
+ }
42357
+ function resolveDevelopmentRoot(farmRoot, viteRoot) {
42358
+ if (!farmRoot) return viteRoot;
42359
+ if (path38.resolve(farmRoot) === path38.resolve(viteRoot)) return farmRoot;
42360
+ try {
42361
+ if (fs14.realpathSync(farmRoot) === fs14.realpathSync(viteRoot)) {
42362
+ return path38.resolve(viteRoot);
42363
+ }
42364
+ } catch {
42365
+ }
42366
+ return farmRoot;
42367
+ }
42177
42368
  function isFarmClientVirtualId(id) {
42178
42369
  const pathname = id.split("?", 1)[0];
42179
42370
  return pathname === "/@farm/client" || pathname === "/@farm/client.js";
@@ -42188,16 +42379,18 @@ function generateProgrammaticRouteModule(moduleId, root, renderer = REACT_RENDER
42188
42379
  return generateProgrammaticApiRouteModule(parsed.routePath, routeFile);
42189
42380
  }
42190
42381
  return `
42191
- import {
42192
- createElement as __farmCreateElement,
42193
- Suspense as __farmSuspense,
42194
- } from ${JSON.stringify(renderer.server)};
42382
+ import * as __farmRendererRuntime from ${JSON.stringify(renderer.server)};
42195
42383
  import {
42196
42384
  createLayoutModuleFromProgrammaticLayout as __farmCreateLayoutRouteModule,
42197
42385
  createRouteModuleFromProgrammaticPage as __farmCreatePageRouteModule,
42198
42386
  } from "@farm.js/core/routes";
42199
42387
  import * as __farmRoutesModule from ${JSON.stringify(routeFile)};
42200
42388
 
42389
+ const __farmCreateElement = __farmRendererRuntime.createElement;
42390
+ const __farmSuspense = __farmRendererRuntime.Suspense;
42391
+ // Optional hook: only renderers that need it export markFunctionComponent.
42392
+ const __farmMarkFunctionComponent = Reflect.get(__farmRendererRuntime, "markFunctionComponent");
42393
+
42201
42394
  const __farmIsRouteDefinition = (value) => (
42202
42395
  value &&
42203
42396
  typeof value === "object" &&
@@ -42251,6 +42444,7 @@ const __farmRouteModule = __farmRoute.kind === "layout"
42251
42444
  : __farmCreatePageRouteModule(__farmRoute, {
42252
42445
  createElement: __farmCreateElement,
42253
42446
  Suspense: __farmSuspense,
42447
+ markFunctionComponent: __farmMarkFunctionComponent,
42254
42448
  });
42255
42449
 
42256
42450
  export const metadata = __farmRouteModule.metadata;
@@ -43855,6 +44049,11 @@ async function hydrate() {
43855
44049
  pendingPageHydrationController = hydrationController;
43856
44050
  await hydrateFarmIsolatedClientBoundaries(rootContainer, hydrationController.signal);
43857
44051
  if (hydrationController.signal.aborted) return;
44052
+ // The rest of the document is static server HTML with nothing to hydrate, so
44053
+ // stop holding its clicks and submits once the load-strategy islands are live.
44054
+ // Deferred islands capture their own interactions, and held targets outside an
44055
+ // island are not replayed into DOM no client code owns.
44056
+ markFarmHydrated();
43858
44057
  return;
43859
44058
  }` : ""}
43860
44059
  if (!shouldHydrate) {
@@ -44296,9 +44495,11 @@ var init_vite2 = __esm({
44296
44495
  init_server_path();
44297
44496
  init_runtime2();
44298
44497
  init_manager();
44498
+ init_server();
44299
44499
  init_type_artifacts();
44300
44500
  init_routes_shared();
44301
44501
  init_markdown();
44502
+ init_base_path();
44302
44503
  init_llms_txt();
44303
44504
  init_agent_crawlers();
44304
44505
  init_app_markdown();
@@ -44436,6 +44637,8 @@ async function mountFarmDocsSearch() {
44436
44637
  __name(hasViteAlias, "hasViteAlias");
44437
44638
  __name(farmPlugin, "farmPlugin");
44438
44639
  __name(runFarmMiddlewareWithNavigation, "runFarmMiddlewareWithNavigation");
44640
+ __name(createPageDataMiddlewareRequest, "createPageDataMiddlewareRequest");
44641
+ __name(resolveDevelopmentRoot, "resolveDevelopmentRoot");
44439
44642
  __name(isFarmClientVirtualId, "isFarmClientVirtualId");
44440
44643
  __name(generateProgrammaticRouteModule, "generateProgrammaticRouteModule");
44441
44644
  __name(generateProgrammaticApiRouteModule, "generateProgrammaticApiRouteModule");
@@ -50576,6 +50779,7 @@ init_transport();
50576
50779
  init_route_manager2();
50577
50780
  init_runtime2();
50578
50781
  init_response();
50782
+ init_request();
50579
50783
  init_route_files();
50580
50784
  init_after();
50581
50785
  init_server_context();
@@ -50932,7 +51136,7 @@ function farmApiPlugin(options = {}) {
50932
51136
  if (currentPathname !== pathname && !matchAPIRouteAtBasePath(apiRoutesCache, currentPathname, basePath)) {
50933
51137
  return next();
50934
51138
  }
50935
- const fullUrl = `http://${req.headers.host || "localhost:3000"}${currentUrl}`;
51139
+ const fullUrl = resolveFarmRequestURL(req);
50936
51140
  const headers2 = new Headers();
50937
51141
  for (const [key, value] of Object.entries(req.headers)) {
50938
51142
  if (value) {
@@ -52990,7 +53194,7 @@ function createServerFn(options) {
52990
53194
  try {
52991
53195
  input = await _parseServerFnSchema(options.input, rawInput, "input");
52992
53196
  } catch (cause) {
52993
- throw labelInputErrors ? new ServerFnInputError(cause) : cause;
53197
+ throw labelInputErrors && isSchemaValidationFailure(cause) ? new ServerFnInputError(cause) : cause;
52994
53198
  }
52995
53199
  const executionContext = getServerActionExecutionContext();
52996
53200
  const request2 = executionContext?.request ?? _resolveCurrentRequest();
@@ -53210,9 +53414,17 @@ async function _parseServerFnSchema(schema, value, contract, owner = "createServ
53210
53414
  throw new TypeError(`${owner} ${contract} must provide parse, parseAsync, or safeParse`);
53211
53415
  }
53212
53416
  __name(_parseServerFnSchema, "_parseServerFnSchema");
53417
+ var schemaValidationFailures = /* @__PURE__ */ new WeakSet();
53418
+ function isSchemaValidationFailure(error) {
53419
+ if (!error || typeof error !== "object") return false;
53420
+ return schemaValidationFailures.has(error) || Array.isArray(error.issues);
53421
+ }
53422
+ __name(isSchemaValidationFailure, "isSchemaValidationFailure");
53213
53423
  function unwrapSafeParseResult(result) {
53214
53424
  if (result && typeof result === "object" && "success" in result && result.success === false) {
53215
- throw result.error;
53425
+ const error = result.error;
53426
+ if (error && typeof error === "object") schemaValidationFailures.add(error);
53427
+ throw error;
53216
53428
  }
53217
53429
  if (result && typeof result === "object" && "success" in result && result.success === true) {
53218
53430
  return result.data;
@@ -56094,7 +56306,7 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
56094
56306
  }
56095
56307
  }
56096
56308
  try {
56097
- await viteBuild({
56309
+ const clientViteConfig = {
56098
56310
  root,
56099
56311
  // Vite otherwise falls back to <root>/public, silently dropping every
56100
56312
  // asset in a custom config.publicDir from the production client output.
@@ -56230,7 +56442,8 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
56230
56442
  "@farm.js/core/headers"
56231
56443
  ]
56232
56444
  }
56233
- });
56445
+ };
56446
+ await viteBuild(mergeFarmProductionViteConfig(clientViteConfig, config.vite));
56234
56447
  await mergeBuiltFontCss(outputDir);
56235
56448
  await validateClientBuildOutput(root, srcDir, outputDir);
56236
56449
  } finally {
@@ -58576,7 +58789,7 @@ async function buildSSRInMemory(productionVite, config, root, routeManager, apiR
58576
58789
  "react-dom/server"
58577
58790
  ];
58578
58791
  try {
58579
- await viteBuild({
58792
+ const serverViteConfig = {
58580
58793
  root,
58581
58794
  build: {
58582
58795
  target: "esnext",
@@ -58737,7 +58950,8 @@ async function buildSSRInMemory(productionVite, config, root, routeManager, apiR
58737
58950
  // Route modules and the renderer adapter must share one runtime instance.
58738
58951
  dedupe: [...config.renderer.dedupe || []]
58739
58952
  }
58740
- });
58953
+ };
58954
+ await viteBuild(mergeFarmProductionViteConfig(serverViteConfig, config.vite));
58741
58955
  } finally {
58742
58956
  if (postcssConfigDir) {
58743
58957
  try {
@@ -60945,7 +61159,7 @@ function hasLocalRequestRoute(request, routePathname) {
60945
61159
  const pathname = new URL(request.url).pathname;
60946
61160
  if (
60947
61161
  farmOpenAPIReference &&
60948
- normalizeRuntimePath(pathname) === normalizeRuntimePath(farmOpenAPIReference.route)
61162
+ normalizeRuntimePath(stripFarmBasePath(pathname)) === normalizeRuntimePath(farmOpenAPIReference.route)
60949
61163
  ) {
60950
61164
  return true;
60951
61165
  }
@@ -60981,7 +61195,7 @@ function getFarmPluginRequestOptions(request) {
60981
61195
  const route = { pathname };
60982
61196
  if (
60983
61197
  farmOpenAPIReference &&
60984
- normalizeRuntimePath(pathname) === normalizeRuntimePath(farmOpenAPIReference.route)
61198
+ normalizeRuntimePath(stripFarmBasePath(pathname)) === normalizeRuntimePath(farmOpenAPIReference.route)
60985
61199
  ) {
60986
61200
  return {
60987
61201
  kind: "docs",
@@ -61310,9 +61524,10 @@ async function handleFarmRequest(request, adapterContext) {
61310
61524
  )` : "handleFarmRequestInContext(request, null, false, Date.now(), adapterContext, requestUrl)"};
61311
61525
  ${config.md?.enabled ? `const pathname = getFarmRoutePathname(requestUrl.pathname);
61312
61526
  if (matchPageRoute(pathname)) {
61527
+ // The Link header advertises the public .md URL, like the head alternate.
61313
61528
  return applyMarkdownNegotiationHeaders(response, {
61314
61529
  config: farmMarkdownConfig,
61315
- pathname,
61530
+ pathname: requestUrl.pathname,
61316
61531
  });
61317
61532
  }` : ""}
61318
61533
  return response;
@@ -61500,7 +61715,7 @@ async function handleFarmRequestInContext(
61500
61715
  if (
61501
61716
  farmOpenAPIReference &&
61502
61717
  farmOpenAPIReference.specRoute &&
61503
- normalizeRuntimePath(pathname) === normalizeRuntimePath(farmOpenAPIReference.specRoute)
61718
+ normalizeRuntimePath(stripFarmBasePath(pathname)) === normalizeRuntimePath(farmOpenAPIReference.specRoute)
61504
61719
  ) {
61505
61720
  const method = request.method.toUpperCase();
61506
61721
  const specResponse = method === "GET" || method === "HEAD"
@@ -61524,7 +61739,7 @@ async function handleFarmRequestInContext(
61524
61739
 
61525
61740
  if (
61526
61741
  farmOpenAPIReference &&
61527
- normalizeRuntimePath(pathname) === normalizeRuntimePath(farmOpenAPIReference.route)
61742
+ normalizeRuntimePath(stripFarmBasePath(pathname)) === normalizeRuntimePath(farmOpenAPIReference.route)
61528
61743
  ) {
61529
61744
  const method = request.method.toUpperCase();
61530
61745
  const response = method === "GET" || method === "HEAD"
@@ -62062,12 +62277,15 @@ async function handleFarmRequestInContext(
62062
62277
  const sharedCacheControl = getRouteSharedCacheControl(route, pprCanCache);
62063
62278
  const responseHeaders = {
62064
62279
  "Content-Type": "text/html; charset=utf-8",
62065
- "Cache-Control": renderedPage.stream || hasRequestScopedRender || !sharedCacheControl
62066
- ? "private, no-store"
62067
- : sharedCacheControl,
62280
+ "Cache-Control": sharedCacheControl,
62068
62281
  ...(farmFontPreloadHeader ? { "Link": farmFontPreloadHeader } : {}),
62069
62282
  ...(pprConfig.enabled ? getPPRHeaders(pprCanCache ? "miss" : "bypass", pprConfig) : {}),
62070
62283
  };
62284
+ // An error status or a request-scoped render is never shareable, even when
62285
+ // the PPR shell headers would otherwise grant a shared max-age.
62286
+ if (renderedPage.stream || hasRequestScopedRender || !sharedCacheControl) {
62287
+ responseHeaders["Cache-Control"] = "private, no-store";
62288
+ }
62071
62289
  const farmI18nSnapshot = getFarmI18nSnapshot();
62072
62290
  let html = renderedPage.html;
62073
62291