@farm.js/core 0.1.0-beta.0 → 0.1.0-beta.3

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 (230) hide show
  1. package/README.md +1 -1
  2. package/dist/agent-runtime.d.mts +1 -1
  3. package/dist/agent-runtime.d.ts +1 -1
  4. package/dist/api/route-manager.cjs +97 -5
  5. package/dist/api/route-manager.cjs.map +1 -1
  6. package/dist/api/route-manager.d.mts +3 -2
  7. package/dist/api/route-manager.d.ts +3 -2
  8. package/dist/api/route-manager.mjs +8 -8
  9. package/dist/api/runtime.cjs +441 -5
  10. package/dist/api/runtime.cjs.map +1 -1
  11. package/dist/api/runtime.d.mts +2 -16
  12. package/dist/api/runtime.d.ts +2 -16
  13. package/dist/api/runtime.mjs +7 -1
  14. package/dist/api.cjs +579 -263
  15. package/dist/api.cjs.map +1 -1
  16. package/dist/api.d.mts +4 -147
  17. package/dist/api.d.ts +4 -147
  18. package/dist/api.mjs +30 -20
  19. package/dist/{app-BiX4qb-d.d.mts → app-BB3Iu3xh.d.mts} +2 -2
  20. package/dist/{app-CFRNJXP1.d.ts → app-DOKxo-LH.d.ts} +2 -2
  21. package/dist/app-markdown.cjs +1 -1
  22. package/dist/app-markdown.cjs.map +1 -1
  23. package/dist/app-markdown.d.mts +1 -1
  24. package/dist/app-markdown.d.ts +1 -1
  25. package/dist/app-markdown.mjs +1 -1
  26. package/dist/cache.cjs +19 -0
  27. package/dist/cache.cjs.map +1 -1
  28. package/dist/cache.d.mts +21 -1
  29. package/dist/cache.d.ts +21 -1
  30. package/dist/cache.mjs +5 -3
  31. package/dist/{chunk-QF4PHCMA.mjs → chunk-2ED5Q2GH.mjs} +3 -3
  32. package/dist/chunk-2ED5Q2GH.mjs.map +1 -0
  33. package/dist/{chunk-GZP5W4K3.mjs → chunk-32W4QEJP.mjs} +1 -1
  34. package/dist/chunk-32W4QEJP.mjs.map +1 -0
  35. package/dist/{chunk-AGS7UJ52.mjs → chunk-45LKHSHJ.mjs} +2 -2
  36. package/dist/{chunk-TU4YJICB.mjs → chunk-5FW6PQ3J.mjs} +1 -1
  37. package/dist/{chunk-TU4YJICB.mjs.map → chunk-5FW6PQ3J.mjs.map} +1 -1
  38. package/dist/{chunk-TRORP7E4.mjs → chunk-5QH4IKY3.mjs} +2 -2
  39. package/dist/{chunk-RKI6TN3A.mjs → chunk-6VS6CKAV.mjs} +2 -2
  40. package/dist/chunk-6VS6CKAV.mjs.map +1 -0
  41. package/dist/{chunk-25D7G34K.mjs → chunk-6WXJ54TC.mjs} +4 -4
  42. package/dist/{chunk-3QJO55ZF.mjs → chunk-BIOIOWXZ.mjs} +5 -3
  43. package/dist/{chunk-3QJO55ZF.mjs.map → chunk-BIOIOWXZ.mjs.map} +1 -1
  44. package/dist/{chunk-QFQRHRZS.mjs → chunk-C33RALN7.mjs} +75 -11
  45. package/dist/chunk-C33RALN7.mjs.map +1 -0
  46. package/dist/{chunk-B6N4ZB2H.mjs → chunk-CSU4KJJF.mjs} +3 -3
  47. package/dist/{chunk-JN3UU635.mjs → chunk-EJ7T4TPB.mjs} +2 -2
  48. package/dist/chunk-EJ7T4TPB.mjs.map +1 -0
  49. package/dist/{chunk-ZJQNATYV.mjs → chunk-FRPWCMMG.mjs} +3 -3
  50. package/dist/chunk-FRPWCMMG.mjs.map +1 -0
  51. package/dist/{chunk-PRNYWD7K.mjs → chunk-G5I34UA6.mjs} +67 -239
  52. package/dist/chunk-G5I34UA6.mjs.map +1 -0
  53. package/dist/{chunk-QM6VV26B.mjs → chunk-GQVGIUSN.mjs} +3 -3
  54. package/dist/{chunk-QM6VV26B.mjs.map → chunk-GQVGIUSN.mjs.map} +1 -1
  55. package/dist/{chunk-UREJA4GZ.mjs → chunk-GXASWWJU.mjs} +1 -1
  56. package/dist/{chunk-UREJA4GZ.mjs.map → chunk-GXASWWJU.mjs.map} +1 -1
  57. package/dist/{chunk-4PTK6KT4.mjs → chunk-GZWT6VI5.mjs} +22 -4
  58. package/dist/chunk-GZWT6VI5.mjs.map +1 -0
  59. package/dist/{chunk-JLWMCADZ.mjs → chunk-HZYXGV4K.mjs} +2 -2
  60. package/dist/chunk-JNYVN7YP.mjs +10 -0
  61. package/dist/chunk-JNYVN7YP.mjs.map +1 -0
  62. package/dist/{chunk-YHU7SS6L.mjs → chunk-LG3YINQN.mjs} +11 -11
  63. package/dist/chunk-LWMGIEJA.mjs +593 -0
  64. package/dist/chunk-LWMGIEJA.mjs.map +1 -0
  65. package/dist/{chunk-HXP3ZSPC.mjs → chunk-MH6FKW2I.mjs} +3 -3
  66. package/dist/{chunk-O3HADRW6.mjs → chunk-MIUW47JX.mjs} +2 -2
  67. package/dist/{chunk-O3HADRW6.mjs.map → chunk-MIUW47JX.mjs.map} +1 -1
  68. package/dist/{chunk-6XDUHOEM.mjs → chunk-NRRFGX45.mjs} +3 -3
  69. package/dist/{chunk-G3B5BRDY.mjs → chunk-OHC6VCDI.mjs} +24 -25
  70. package/dist/{chunk-G3B5BRDY.mjs.map → chunk-OHC6VCDI.mjs.map} +1 -1
  71. package/dist/{chunk-S2XHZS7W.mjs → chunk-QGQX7SFC.mjs} +2 -2
  72. package/dist/chunk-QGQX7SFC.mjs.map +1 -0
  73. package/dist/{chunk-TXCFGOHW.mjs → chunk-SHRJG6OG.mjs} +25 -1
  74. package/dist/chunk-SHRJG6OG.mjs.map +1 -0
  75. package/dist/{chunk-UHE2TTLK.mjs → chunk-T543TMFY.mjs} +8 -8
  76. package/dist/chunk-T543TMFY.mjs.map +1 -0
  77. package/dist/{chunk-SXZTEK3V.mjs → chunk-UXUAWNO5.mjs} +2 -2
  78. package/dist/{chunk-Y2OJJD7R.mjs → chunk-XIVV5IWN.mjs} +7 -9
  79. package/dist/chunk-XIVV5IWN.mjs.map +1 -0
  80. package/dist/{chunk-CHFHNEMO.mjs → chunk-XJSHJN4M.mjs} +41 -42
  81. package/dist/chunk-XJSHJN4M.mjs.map +1 -0
  82. package/dist/{chunk-Y7A27276.mjs → chunk-XUBZ7JI4.mjs} +178 -15
  83. package/dist/chunk-XUBZ7JI4.mjs.map +1 -0
  84. package/dist/{chunk-OYXO65LI.mjs → chunk-YW7OBE6Q.mjs} +4 -4
  85. package/dist/chunk-YW7OBE6Q.mjs.map +1 -0
  86. package/dist/{chunk-SOU3Q3ZA.mjs → chunk-ZZ57EH5Z.mjs} +1 -1
  87. package/dist/chunk-ZZ57EH5Z.mjs.map +1 -0
  88. package/dist/{client-D_yUjVhe.d.mts → client-DiViK9yK.d.mts} +33 -7
  89. package/dist/{client-Dkc03WP8.d.ts → client-DpEBJbts.d.ts} +33 -7
  90. package/dist/{client-plugins-BZnpeTGA.d.ts → client-plugins-CTnsZz_A.d.ts} +1 -0
  91. package/dist/{client-plugins-g4bzuCmo.d.mts → client-plugins-Cnr0D3kk.d.mts} +1 -0
  92. package/dist/client-plugins.d.mts +1 -1
  93. package/dist/client-plugins.d.ts +1 -1
  94. package/dist/client.cjs +302 -54
  95. package/dist/client.cjs.map +1 -1
  96. package/dist/client.d.mts +54 -2
  97. package/dist/client.d.ts +54 -2
  98. package/dist/client.mjs +20 -16
  99. package/dist/config.d.mts +1 -1
  100. package/dist/config.d.ts +1 -1
  101. package/dist/cron.cjs.map +1 -1
  102. package/dist/cron.mjs +1 -1
  103. package/dist/{devtools-AE4RVXCM.mjs → devtools-HE4FTUDN.mjs} +10 -10
  104. package/dist/{devtools-client-6WPY2AQU.mjs → devtools-client-3XRTBND5.mjs} +2 -11
  105. package/dist/devtools-client-3XRTBND5.mjs.map +1 -0
  106. package/dist/docs.cjs +3 -1
  107. package/dist/docs.cjs.map +1 -1
  108. package/dist/docs.mjs +10 -10
  109. package/dist/i18n/server.cjs +2 -2
  110. package/dist/i18n/server.cjs.map +1 -1
  111. package/dist/i18n/server.mjs +1 -1
  112. package/dist/index.cjs +791 -317
  113. package/dist/index.cjs.map +1 -1
  114. package/dist/index.d.mts +11 -11
  115. package/dist/index.d.ts +11 -11
  116. package/dist/index.mjs +125 -110
  117. package/dist/index.mjs.map +1 -1
  118. package/dist/integrations.d.mts +1 -1
  119. package/dist/integrations.d.ts +1 -1
  120. package/dist/internal/build-runtime.cjs +162 -60
  121. package/dist/internal/build-runtime.cjs.map +1 -1
  122. package/dist/internal/build-runtime.d.mts +3 -3
  123. package/dist/internal/build-runtime.d.ts +3 -3
  124. package/dist/internal/build-runtime.mjs +26 -25
  125. package/dist/internal/client-runtime.cjs.map +1 -1
  126. package/dist/internal/client-runtime.mjs +1 -1
  127. package/dist/internal/config-runtime.cjs +1 -1
  128. package/dist/internal/config-runtime.cjs.map +1 -1
  129. package/dist/internal/config-runtime.d.mts +2 -2
  130. package/dist/internal/config-runtime.d.ts +2 -2
  131. package/dist/internal/config-runtime.mjs +9 -9
  132. package/dist/internal/production-runtime.cjs +3 -3
  133. package/dist/internal/production-runtime.cjs.map +1 -1
  134. package/dist/internal/production-runtime.d.mts +3 -3
  135. package/dist/internal/production-runtime.d.ts +3 -3
  136. package/dist/internal/production-runtime.mjs +8 -8
  137. package/dist/{metadata-C9NZxMDW.d.mts → metadata-Dp8AdvsB.d.mts} +1 -1
  138. package/dist/{metadata-DAXRaOHx.d.ts → metadata-eoVmHoyv.d.ts} +1 -1
  139. package/dist/middleware.cjs +2 -2
  140. package/dist/middleware.cjs.map +1 -1
  141. package/dist/middleware.d.mts +3 -3
  142. package/dist/middleware.d.ts +3 -3
  143. package/dist/middleware.mjs +3 -3
  144. package/dist/navigation.cjs.map +1 -1
  145. package/dist/navigation.mjs +3 -3
  146. package/dist/{nitro-KME62MWG.mjs → nitro-QO5LV6QK.mjs} +11 -13
  147. package/dist/{nitro-KME62MWG.mjs.map → nitro-QO5LV6QK.mjs.map} +1 -1
  148. package/dist/plugin.cjs +119 -39
  149. package/dist/plugin.cjs.map +1 -1
  150. package/dist/plugin.d.mts +1 -1
  151. package/dist/plugin.d.ts +1 -1
  152. package/dist/plugin.mjs +22 -21
  153. package/dist/{production-runtime-DRkCHUvJ.d.ts → production-runtime-BqTnUTai.d.ts} +1 -1
  154. package/dist/{production-runtime-flrjp_nC.d.mts → production-runtime-DtDdG9fc.d.mts} +1 -1
  155. package/dist/routes.cjs.map +1 -1
  156. package/dist/routes.d.mts +1 -1
  157. package/dist/routes.d.ts +1 -1
  158. package/dist/routes.mjs +4 -4
  159. package/dist/runtime-C1B7pSGT.d.mts +207 -0
  160. package/dist/runtime-CdPHt0bv.d.ts +207 -0
  161. package/dist/server-action-security.cjs.map +1 -1
  162. package/dist/server-action-security.mjs +2 -2
  163. package/dist/server-fn-client.cjs.map +1 -1
  164. package/dist/server-fn-client.mjs +1 -1
  165. package/dist/server-fn.cjs.map +1 -1
  166. package/dist/server-fn.mjs +3 -3
  167. package/dist/server-plugins.d.mts +2 -2
  168. package/dist/server-plugins.d.ts +2 -2
  169. package/dist/server-query-client.cjs.map +1 -1
  170. package/dist/server-query-client.mjs +4 -4
  171. package/dist/server-query.cjs.map +1 -1
  172. package/dist/server-query.mjs +5 -5
  173. package/dist/server.cjs +148 -43
  174. package/dist/server.cjs.map +1 -1
  175. package/dist/server.d.mts +6 -6
  176. package/dist/server.d.ts +6 -6
  177. package/dist/server.mjs +36 -31
  178. package/dist/server.mjs.map +1 -1
  179. package/dist/testing.cjs +95 -5
  180. package/dist/testing.cjs.map +1 -1
  181. package/dist/testing.d.mts +3 -3
  182. package/dist/testing.d.ts +3 -3
  183. package/dist/testing.mjs +18 -18
  184. package/dist/{utils-DOXXivjL.d.mts → utils-8USa5BiY.d.mts} +1 -1
  185. package/dist/{utils-DA1yo54_.d.ts → utils-DKJb6K6G.d.ts} +1 -1
  186. package/dist/version.cjs +36 -0
  187. package/dist/version.cjs.map +1 -0
  188. package/dist/version.d.mts +3 -0
  189. package/dist/version.d.ts +3 -0
  190. package/dist/version.mjs +8 -0
  191. package/dist/version.mjs.map +1 -0
  192. package/dist/vite.cjs +126 -40
  193. package/dist/vite.cjs.map +1 -1
  194. package/dist/vite.d.mts +1 -1
  195. package/dist/vite.d.ts +1 -1
  196. package/dist/vite.mjs +22 -21
  197. package/dist/workflows.cjs +6 -8
  198. package/dist/workflows.cjs.map +1 -1
  199. package/dist/workflows.mjs +1 -1
  200. package/package.json +12 -5
  201. package/types/client.d.ts +136 -13
  202. package/dist/chunk-4PTK6KT4.mjs.map +0 -1
  203. package/dist/chunk-CHFHNEMO.mjs.map +0 -1
  204. package/dist/chunk-EVGBEZDF.mjs +0 -215
  205. package/dist/chunk-EVGBEZDF.mjs.map +0 -1
  206. package/dist/chunk-GZP5W4K3.mjs.map +0 -1
  207. package/dist/chunk-JN3UU635.mjs.map +0 -1
  208. package/dist/chunk-OYXO65LI.mjs.map +0 -1
  209. package/dist/chunk-PRNYWD7K.mjs.map +0 -1
  210. package/dist/chunk-QF4PHCMA.mjs.map +0 -1
  211. package/dist/chunk-QFQRHRZS.mjs.map +0 -1
  212. package/dist/chunk-RKI6TN3A.mjs.map +0 -1
  213. package/dist/chunk-S2XHZS7W.mjs.map +0 -1
  214. package/dist/chunk-SOU3Q3ZA.mjs.map +0 -1
  215. package/dist/chunk-TXCFGOHW.mjs.map +0 -1
  216. package/dist/chunk-UHE2TTLK.mjs.map +0 -1
  217. package/dist/chunk-Y2OJJD7R.mjs.map +0 -1
  218. package/dist/chunk-Y7A27276.mjs.map +0 -1
  219. package/dist/chunk-ZJQNATYV.mjs.map +0 -1
  220. package/dist/devtools-client-6WPY2AQU.mjs.map +0 -1
  221. /package/dist/{chunk-AGS7UJ52.mjs.map → chunk-45LKHSHJ.mjs.map} +0 -0
  222. /package/dist/{chunk-TRORP7E4.mjs.map → chunk-5QH4IKY3.mjs.map} +0 -0
  223. /package/dist/{chunk-25D7G34K.mjs.map → chunk-6WXJ54TC.mjs.map} +0 -0
  224. /package/dist/{chunk-B6N4ZB2H.mjs.map → chunk-CSU4KJJF.mjs.map} +0 -0
  225. /package/dist/{chunk-JLWMCADZ.mjs.map → chunk-HZYXGV4K.mjs.map} +0 -0
  226. /package/dist/{chunk-YHU7SS6L.mjs.map → chunk-LG3YINQN.mjs.map} +0 -0
  227. /package/dist/{chunk-HXP3ZSPC.mjs.map → chunk-MH6FKW2I.mjs.map} +0 -0
  228. /package/dist/{chunk-6XDUHOEM.mjs.map → chunk-NRRFGX45.mjs.map} +0 -0
  229. /package/dist/{chunk-SXZTEK3V.mjs.map → chunk-UXUAWNO5.mjs.map} +0 -0
  230. /package/dist/{devtools-AE4RVXCM.mjs.map → devtools-HE4FTUDN.mjs.map} +0 -0
package/dist/index.cjs CHANGED
@@ -3052,7 +3052,7 @@ function createFarmMarkdownRouteModule(input) {
3052
3052
  ...props,
3053
3053
  components: {
3054
3054
  ...components,
3055
- ...props?.components || {}
3055
+ ...props?.components
3056
3056
  }
3057
3057
  })
3058
3058
  );
@@ -3569,7 +3569,11 @@ async function prepareFarmWorkflowsForNitro(config) {
3569
3569
  };
3570
3570
  }
3571
3571
  const handlerPath = path28.join(generatedDir, "http-handler.mjs");
3572
- await fs9.writeFile(handlerPath, createNitroWorkflowHTTPHandler(workflowConfig, workflows), "utf8");
3572
+ await fs9.writeFile(
3573
+ handlerPath,
3574
+ createNitroWorkflowHTTPHandler(workflowConfig, workflows),
3575
+ "utf8"
3576
+ );
3573
3577
  const manifestPath = path28.join(generatedDir, "manifest.json");
3574
3578
  await fs9.writeFile(
3575
3579
  manifestPath,
@@ -3643,13 +3647,7 @@ function normalizeSchedule(schedule) {
3643
3647
  return (Array.isArray(schedule) ? schedule : [schedule]).map((value) => value.trim()).filter(Boolean);
3644
3648
  }
3645
3649
  function resolveWorkflowDefinition(module2) {
3646
- const candidates = [
3647
- module2.default,
3648
- module2.workflow,
3649
- module2.cron,
3650
- module2.task,
3651
- module2.job
3652
- ];
3650
+ const candidates = [module2.default, module2.workflow, module2.cron, module2.task, module2.job];
3653
3651
  for (const candidate of candidates) {
3654
3652
  if (candidate && typeof candidate === "object" && typeof candidate.run === "function") {
3655
3653
  return candidate;
@@ -4562,8 +4560,8 @@ function compareFarmRouteRuleSpecificity(left, right) {
4562
4560
  }
4563
4561
  function getFarmRouteRuleSpecificity(pattern) {
4564
4562
  return normalizeRoutePattern(pattern).split("/").filter(Boolean).reduce((score, segment) => {
4565
- if (segment === "**" || /^\[\[\.\.\./.test(segment)) return score + 1;
4566
- if (segment === "*" || /^\[\.\.\./.test(segment)) return score + 10;
4563
+ if (segment === "**" || segment.startsWith("[[...")) return score + 1;
4564
+ if (segment === "*" || segment.startsWith("[...")) return score + 10;
4567
4565
  if (/^\[.+\]$/.test(segment) || /^:.+$/.test(segment)) return score + 50;
4568
4566
  return score + 100;
4569
4567
  }, 0);
@@ -4625,7 +4623,7 @@ function routeRulesToHeaders(routeRules) {
4625
4623
  for (const [source, rule] of Object.entries(routeRules)) {
4626
4624
  const headers2 = {
4627
4625
  ...normalizeCorsHeaders(rule.cors),
4628
- ...rule.headers || {}
4626
+ ...rule.headers
4629
4627
  };
4630
4628
  const entries = Object.entries(headers2);
4631
4629
  if (entries.length === 0) continue;
@@ -4655,7 +4653,7 @@ function routeRulesToNitroRouteRules(routeRules) {
4655
4653
  nitroRule.cors = true;
4656
4654
  nitroRule.headers = {
4657
4655
  ...normalizeCorsHeaders(rule.cors),
4658
- ...rule.headers || {}
4656
+ ...rule.headers
4659
4657
  };
4660
4658
  }
4661
4659
  delete nitroRule.render;
@@ -4724,20 +4722,41 @@ function applyFarmCacheInvalidations(keys) {
4724
4722
  }
4725
4723
  }
4726
4724
  }
4725
+ function encodeFarmCacheInvalidations(keys) {
4726
+ const normalized = Array.from(
4727
+ new Set(keys.filter((key) => typeof key === "string" && key.length > 0))
4728
+ );
4729
+ if (normalized.length === 0) return null;
4730
+ return encodeURIComponent(JSON.stringify(normalized));
4731
+ }
4732
+ function decodeFarmCacheInvalidations(value) {
4733
+ if (!value) return [];
4734
+ try {
4735
+ const parsed = JSON.parse(decodeURIComponent(value));
4736
+ return Array.isArray(parsed) ? Array.from(
4737
+ new Set(parsed.filter((key) => typeof key === "string" && key.length > 0))
4738
+ ) : [];
4739
+ } catch {
4740
+ return [];
4741
+ }
4742
+ }
4727
4743
  function subscribeFarmCacheInvalidation(listener) {
4728
4744
  const state = getFarmCacheInvalidationState();
4729
4745
  state.listeners.add(listener);
4730
4746
  return () => state.listeners.delete(listener);
4731
4747
  }
4732
- var FARM_CACHE_INVALIDATION_STATE, globalState;
4748
+ var FARM_CACHE_INVALIDATION_HEADER, FARM_CACHE_INVALIDATION_STATE, globalState;
4733
4749
  var init_cache_invalidation = __esm({
4734
4750
  "src/cache-invalidation.ts"() {
4735
4751
  "use strict";
4752
+ FARM_CACHE_INVALIDATION_HEADER = "x-farm-cache-invalidations";
4736
4753
  FARM_CACHE_INVALIDATION_STATE = /* @__PURE__ */ Symbol.for("farm.cacheInvalidationState");
4737
4754
  globalState = globalThis;
4738
4755
  __name(getFarmCacheInvalidationState, "getFarmCacheInvalidationState");
4739
4756
  __name(notifyFarmCacheInvalidation, "notifyFarmCacheInvalidation");
4740
4757
  __name(applyFarmCacheInvalidations, "applyFarmCacheInvalidations");
4758
+ __name(encodeFarmCacheInvalidations, "encodeFarmCacheInvalidations");
4759
+ __name(decodeFarmCacheInvalidations, "decodeFarmCacheInvalidations");
4741
4760
  __name(subscribeFarmCacheInvalidation, "subscribeFarmCacheInvalidation");
4742
4761
  }
4743
4762
  });
@@ -6196,6 +6215,22 @@ var init_bridge = __esm({
6196
6215
  });
6197
6216
 
6198
6217
  // src/cache.ts
6218
+ function defineCacheKey() {
6219
+ return (factory) => {
6220
+ if (typeof factory !== "function") {
6221
+ throw new TypeError("defineCacheKey expects a key factory function.");
6222
+ }
6223
+ return ((...args) => {
6224
+ const key = factory(...args);
6225
+ if (typeof key !== "string" && !Array.isArray(key)) {
6226
+ throw new TypeError(
6227
+ "A defined cache key factory must return a string or structured array."
6228
+ );
6229
+ }
6230
+ return key;
6231
+ });
6232
+ };
6233
+ }
6199
6234
  function getFarmDataCache() {
6200
6235
  return sharedFarmDataCache;
6201
6236
  }
@@ -6344,6 +6379,7 @@ var init_cache = __esm({
6344
6379
  init_cache_invalidation();
6345
6380
  init_bridge();
6346
6381
  init_cache_invalidation();
6382
+ __name(defineCacheKey, "defineCacheKey");
6347
6383
  _FarmDataCache = class _FarmDataCache {
6348
6384
  constructor() {
6349
6385
  this.entries = /* @__PURE__ */ new Map();
@@ -10138,7 +10174,7 @@ function mergeMetadata(base, next) {
10138
10174
  }
10139
10175
  function addMetadataImageReference(metadata, reference) {
10140
10176
  if (reference.kind === "opengraph") {
10141
- const openGraph = { ...metadata.openGraph || {} };
10177
+ const openGraph = { ...metadata.openGraph };
10142
10178
  if (!hasMetadataImages(openGraph.images) && !hasMetadataImages(openGraph.image)) {
10143
10179
  openGraph.images = [
10144
10180
  {
@@ -10155,7 +10191,7 @@ function addMetadataImageReference(metadata, reference) {
10155
10191
  openGraph
10156
10192
  };
10157
10193
  }
10158
- const twitter = { ...metadata.twitter || {} };
10194
+ const twitter = { ...metadata.twitter };
10159
10195
  if (!hasMetadataImages(twitter.images)) {
10160
10196
  twitter.images = [reference.href];
10161
10197
  twitter.card = twitter.card || "summary_large_image";
@@ -10906,8 +10942,8 @@ var init_runtime = __esm({
10906
10942
  cookie: this.config.cookie,
10907
10943
  direction: getFarmLocaleDirection(resolution.locale, this.config.direction),
10908
10944
  messages: {
10909
- ...this.catalogs[this.config.fallbackLocale] || {},
10910
- ...this.catalogs[resolution.locale] || {}
10945
+ ...this.catalogs[this.config.fallbackLocale],
10946
+ ...this.catalogs[resolution.locale]
10911
10947
  }
10912
10948
  };
10913
10949
  }
@@ -12466,11 +12502,7 @@ var init_app = __esm({
12466
12502
  _setDefaultFarmI18nRuntime(this.i18nRuntime);
12467
12503
  this.viteServer = viteServer;
12468
12504
  this.routeManager = new RouteManager(this.config, viteServer);
12469
- this.serverRenderer = new ServerRenderer(
12470
- this.config,
12471
- this.routeManager,
12472
- this.i18nRuntime
12473
- );
12505
+ this.serverRenderer = new ServerRenderer(this.config, this.routeManager, this.i18nRuntime);
12474
12506
  }
12475
12507
  async initialize() {
12476
12508
  if (process.env.FARM_VERBOSE) {
@@ -13106,6 +13138,321 @@ var init_hmr = __esm({
13106
13138
  }
13107
13139
  });
13108
13140
 
13141
+ // src/api/endpoint.ts
13142
+ function isEndpointFailure(value) {
13143
+ return value instanceof EndpointFailure;
13144
+ }
13145
+ function createEndpoint(pathOrOptions, optionsOrHandler, maybeHandler) {
13146
+ let path28;
13147
+ let options;
13148
+ let handler;
13149
+ if (typeof pathOrOptions === "string") {
13150
+ path28 = pathOrOptions;
13151
+ options = optionsOrHandler;
13152
+ handler = maybeHandler;
13153
+ } else {
13154
+ path28 = "";
13155
+ options = pathOrOptions;
13156
+ handler = optionsOrHandler;
13157
+ }
13158
+ if (typeof handler !== "function") {
13159
+ throw new TypeError("createEndpoint requires a handler function");
13160
+ }
13161
+ const middleware2 = normalizeEndpointMiddleware(options.middleware);
13162
+ const errors = normalizeEndpointErrors(options.errors);
13163
+ const fail = createEndpointFail(errors);
13164
+ const wrappedHandler = /* @__PURE__ */ __name((async (ctx) => {
13165
+ const execution = await runEndpointMiddleware(
13166
+ middleware2,
13167
+ ctx,
13168
+ handler,
13169
+ fail,
13170
+ options.invalidates
13171
+ );
13172
+ return execution.result;
13173
+ }), "wrappedHandler");
13174
+ const {
13175
+ middleware: _middleware,
13176
+ errors: _errors,
13177
+ invalidates: _invalidates,
13178
+ ...betterCallOptions
13179
+ } = options;
13180
+ const endpoint2 = (0, import_better_call.createEndpoint)(
13181
+ path28 || "/__farm_auto_path__",
13182
+ betterCallOptions,
13183
+ wrappedHandler
13184
+ );
13185
+ endpoint2.__path = path28 || void 0;
13186
+ endpoint2.__method = options.method || "GET";
13187
+ endpoint2.__autoPath = !path28;
13188
+ endpoint2.__handler = wrappedHandler;
13189
+ endpoint2.__farmInvoke = (ctx) => runEndpointMiddleware(middleware2, ctx, handler, fail, options.invalidates);
13190
+ endpoint2.__middleware = middleware2;
13191
+ endpoint2.__sourceHandler = handler;
13192
+ endpoint2.__invalidates = options.invalidates;
13193
+ endpoint2.__errors = errors;
13194
+ endpoint2.__types = {
13195
+ body: options.body,
13196
+ query: options.query,
13197
+ headers: options.headers,
13198
+ response: null,
13199
+ errors
13200
+ };
13201
+ return endpoint2;
13202
+ }
13203
+ function normalizeEndpointErrors(definitions) {
13204
+ if (definitions === void 0) return Object.freeze({});
13205
+ if (!isPlainEndpointContext(definitions)) {
13206
+ throw new TypeError("createEndpoint errors must be an object");
13207
+ }
13208
+ const normalized = /* @__PURE__ */ Object.create(null);
13209
+ for (const [code, definition] of Object.entries(definitions)) {
13210
+ if (!code.trim()) {
13211
+ throw new TypeError("Endpoint error codes cannot be empty");
13212
+ }
13213
+ if (!definition || typeof definition !== "object") {
13214
+ throw new TypeError(`Endpoint error "${code}" must be an object`);
13215
+ }
13216
+ if (!Number.isInteger(definition.status) || definition.status < 400 || definition.status > 599) {
13217
+ throw new TypeError(`Endpoint error "${code}" status must be an integer between 400 and 599`);
13218
+ }
13219
+ if (!definition.schema || typeof definition.schema.parse !== "function") {
13220
+ throw new TypeError(`Endpoint error "${code}" requires a schema with parse()`);
13221
+ }
13222
+ if (definition.message !== void 0 && typeof definition.message !== "string") {
13223
+ throw new TypeError(`Endpoint error "${code}" message must be a string`);
13224
+ }
13225
+ normalized[code] = Object.freeze({ ...definition });
13226
+ }
13227
+ return Object.freeze(normalized);
13228
+ }
13229
+ function createEndpointFail(definitions) {
13230
+ return ((code, data) => {
13231
+ const definition = definitions[code];
13232
+ if (!definition) {
13233
+ throw new TypeError(`Endpoint error "${code}" is not declared`);
13234
+ }
13235
+ const parsed = definition.schema.parse(data);
13236
+ throw new EndpointFailure(code, parsed, {
13237
+ status: definition.status,
13238
+ message: definition.message ?? "Request failed"
13239
+ });
13240
+ });
13241
+ }
13242
+ function normalizeEndpointMiddleware(middleware2) {
13243
+ if (middleware2 === void 0) return EMPTY_ENDPOINT_MIDDLEWARE;
13244
+ if (!Array.isArray(middleware2)) {
13245
+ throw new TypeError("createEndpoint middleware must be an array of functions");
13246
+ }
13247
+ const normalized = [...middleware2];
13248
+ for (const entry of normalized) {
13249
+ if (typeof entry !== "function") {
13250
+ throw new TypeError("createEndpoint middleware entries must be functions");
13251
+ }
13252
+ }
13253
+ return Object.freeze(normalized);
13254
+ }
13255
+ async function runEndpointMiddleware(middleware2, handlerContext, handler, fail, invalidations) {
13256
+ let context = createInitialEndpointContext(handlerContext.context);
13257
+ for (let index = 0; index < middleware2.length; index++) {
13258
+ const result2 = await middleware2[index]({ ...handlerContext, context });
13259
+ if (isEndpointResponse(result2)) {
13260
+ return {
13261
+ result: result2,
13262
+ context,
13263
+ handlerExecuted: false,
13264
+ invalidations: []
13265
+ };
13266
+ }
13267
+ if (result2 === false) {
13268
+ return {
13269
+ result: forbiddenEndpointResponse(),
13270
+ context,
13271
+ handlerExecuted: false,
13272
+ invalidations: []
13273
+ };
13274
+ }
13275
+ if (result2 === true) continue;
13276
+ if (!isPlainEndpointContext(result2)) {
13277
+ throw new TypeError(
13278
+ `Endpoint middleware ${index + 1} must return an object, true, false, or a Response`
13279
+ );
13280
+ }
13281
+ context = mergeEndpointContext(context, result2, index);
13282
+ }
13283
+ const result = await handler({ ...handlerContext, context, fail });
13284
+ return {
13285
+ result,
13286
+ context,
13287
+ handlerExecuted: true,
13288
+ invalidations: await applyEndpointInvalidations(
13289
+ invalidations,
13290
+ {
13291
+ ...handlerContext,
13292
+ context,
13293
+ result
13294
+ },
13295
+ result
13296
+ )
13297
+ };
13298
+ }
13299
+ async function applyEndpointInvalidations(declaration, context, result) {
13300
+ if (!declaration || isEndpointResponse(result) && result.status >= 400) {
13301
+ return [];
13302
+ }
13303
+ const targets = typeof declaration === "function" ? await declaration(context) : declaration;
13304
+ if (!Array.isArray(targets)) {
13305
+ throw new TypeError(
13306
+ "Endpoint invalidates must resolve to an array of { key } or { path } targets"
13307
+ );
13308
+ }
13309
+ const clientKeys = [];
13310
+ for (const target of targets) {
13311
+ assertEndpointInvalidationTarget(target);
13312
+ if ("key" in target) {
13313
+ invalidate(target.key);
13314
+ clientKeys.push(createRouteDataCacheKey(target.key));
13315
+ } else {
13316
+ revalidatePath(target.path);
13317
+ }
13318
+ }
13319
+ return Array.from(new Set(clientKeys));
13320
+ }
13321
+ function assertEndpointInvalidationTarget(target) {
13322
+ if (!target || typeof target !== "object") {
13323
+ throw new TypeError("Endpoint invalidation targets must be { key } or { path } objects");
13324
+ }
13325
+ if ("key" in target) {
13326
+ const key = target.key;
13327
+ if (typeof key === "string" || Array.isArray(key)) return;
13328
+ } else if ("path" in target && typeof target.path === "string") {
13329
+ return;
13330
+ }
13331
+ throw new TypeError(
13332
+ "Endpoint invalidation targets must contain a string/array key or a path string"
13333
+ );
13334
+ }
13335
+ function createInitialEndpointContext(value) {
13336
+ if (value === void 0 || value === null) return EMPTY_ENDPOINT_CONTEXT;
13337
+ if (!isPlainEndpointContext(value)) {
13338
+ throw new TypeError("Endpoint context must be a plain object");
13339
+ }
13340
+ return mergeEndpointContext(EMPTY_ENDPOINT_CONTEXT, value);
13341
+ }
13342
+ function mergeEndpointContext(current, added, middlewareIndex) {
13343
+ const next = Object.assign(/* @__PURE__ */ Object.create(null), current);
13344
+ for (const key of Reflect.ownKeys(added)) {
13345
+ if (!Object.prototype.propertyIsEnumerable.call(added, key)) continue;
13346
+ if (typeof key === "string" && UNSAFE_ENDPOINT_CONTEXT_KEYS.has(key)) {
13347
+ throw new TypeError(`Endpoint middleware cannot provide the unsafe context key "${key}"`);
13348
+ }
13349
+ if (Object.prototype.hasOwnProperty.call(current, key)) {
13350
+ const source = middlewareIndex === void 0 ? "Endpoint context" : `Endpoint middleware ${middlewareIndex + 1}`;
13351
+ throw new TypeError(`${source} cannot replace the existing context key "${String(key)}"`);
13352
+ }
13353
+ next[key] = added[key];
13354
+ }
13355
+ return Object.freeze(next);
13356
+ }
13357
+ function isPlainEndpointContext(value) {
13358
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
13359
+ const prototype = Object.getPrototypeOf(value);
13360
+ return prototype === Object.prototype || prototype === null;
13361
+ }
13362
+ function isEndpointResponse(value) {
13363
+ return value instanceof Response || typeof value === "object" && value !== null && "headers" in value && "status" in value && typeof value.arrayBuffer === "function";
13364
+ }
13365
+ function forbiddenEndpointResponse() {
13366
+ return new Response(JSON.stringify({ error: "Forbidden" }), {
13367
+ status: 403,
13368
+ headers: { "Content-Type": "application/json" }
13369
+ });
13370
+ }
13371
+ function GET(...args) {
13372
+ if (args.length === 1) {
13373
+ return createEndpoint("", { method: "GET" }, args[0]);
13374
+ }
13375
+ return createEndpoint("", { ...args[0], method: "GET" }, args[1]);
13376
+ }
13377
+ function HEAD(...args) {
13378
+ if (args.length === 1) {
13379
+ return createEndpoint("", { method: "HEAD" }, args[0]);
13380
+ }
13381
+ return createEndpoint("", { ...args[0], method: "HEAD" }, args[1]);
13382
+ }
13383
+ function POST(...args) {
13384
+ if (args.length === 1) {
13385
+ return createEndpoint("", { method: "POST" }, args[0]);
13386
+ }
13387
+ return createEndpoint("", { ...args[0], method: "POST" }, args[1]);
13388
+ }
13389
+ function PUT(...args) {
13390
+ if (args.length === 1) {
13391
+ return createEndpoint("", { method: "PUT" }, args[0]);
13392
+ }
13393
+ return createEndpoint("", { ...args[0], method: "PUT" }, args[1]);
13394
+ }
13395
+ function DELETE(...args) {
13396
+ if (args.length === 1) {
13397
+ return createEndpoint("", { method: "DELETE" }, args[0]);
13398
+ }
13399
+ return createEndpoint("", { ...args[0], method: "DELETE" }, args[1]);
13400
+ }
13401
+ function PATCH(...args) {
13402
+ if (args.length === 1) {
13403
+ return createEndpoint("", { method: "PATCH" }, args[0]);
13404
+ }
13405
+ return createEndpoint("", { ...args[0], method: "PATCH" }, args[1]);
13406
+ }
13407
+ function OPTIONS(...args) {
13408
+ if (args.length === 1) {
13409
+ return createEndpoint("", { method: "OPTIONS" }, args[0]);
13410
+ }
13411
+ return createEndpoint("", { ...args[0], method: "OPTIONS" }, args[1]);
13412
+ }
13413
+ var import_better_call, _EndpointFailure, EndpointFailure, EMPTY_ENDPOINT_MIDDLEWARE, EMPTY_ENDPOINT_CONTEXT, UNSAFE_ENDPOINT_CONTEXT_KEYS;
13414
+ var init_endpoint = __esm({
13415
+ "src/api/endpoint.ts"() {
13416
+ "use strict";
13417
+ import_better_call = require("better-call");
13418
+ init_cache();
13419
+ _EndpointFailure = class _EndpointFailure extends Error {
13420
+ constructor(code, data, options) {
13421
+ super(options.message);
13422
+ this.name = "EndpointFailure";
13423
+ this.code = code;
13424
+ this.data = data;
13425
+ this.status = options.status;
13426
+ }
13427
+ };
13428
+ __name(_EndpointFailure, "EndpointFailure");
13429
+ EndpointFailure = _EndpointFailure;
13430
+ __name(isEndpointFailure, "isEndpointFailure");
13431
+ __name(createEndpoint, "createEndpoint");
13432
+ EMPTY_ENDPOINT_MIDDLEWARE = Object.freeze([]);
13433
+ EMPTY_ENDPOINT_CONTEXT = Object.freeze(/* @__PURE__ */ Object.create(null));
13434
+ UNSAFE_ENDPOINT_CONTEXT_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
13435
+ __name(normalizeEndpointErrors, "normalizeEndpointErrors");
13436
+ __name(createEndpointFail, "createEndpointFail");
13437
+ __name(normalizeEndpointMiddleware, "normalizeEndpointMiddleware");
13438
+ __name(runEndpointMiddleware, "runEndpointMiddleware");
13439
+ __name(applyEndpointInvalidations, "applyEndpointInvalidations");
13440
+ __name(assertEndpointInvalidationTarget, "assertEndpointInvalidationTarget");
13441
+ __name(createInitialEndpointContext, "createInitialEndpointContext");
13442
+ __name(mergeEndpointContext, "mergeEndpointContext");
13443
+ __name(isPlainEndpointContext, "isPlainEndpointContext");
13444
+ __name(isEndpointResponse, "isEndpointResponse");
13445
+ __name(forbiddenEndpointResponse, "forbiddenEndpointResponse");
13446
+ __name(GET, "GET");
13447
+ __name(HEAD, "HEAD");
13448
+ __name(POST, "POST");
13449
+ __name(PUT, "PUT");
13450
+ __name(DELETE, "DELETE");
13451
+ __name(PATCH, "PATCH");
13452
+ __name(OPTIONS, "OPTIONS");
13453
+ }
13454
+ });
13455
+
13109
13456
  // src/api/runtime.ts
13110
13457
  function matchAPIRoute(routes, pathname) {
13111
13458
  const exactRoute = routes.get(pathname);
@@ -13136,10 +13483,10 @@ async function invokeAPIRouteEndpoint(endpoint2, request, params = {}) {
13136
13483
  async function invokeAPIRouteEndpointInContext(endpoint2, request, params) {
13137
13484
  const farmHandler = endpoint2.__handler || (isFarmContextHandler(endpoint2) ? endpoint2 : null);
13138
13485
  if (!farmHandler) {
13139
- const result2 = await endpoint2(request, {
13486
+ const result = await endpoint2(request, {
13140
13487
  params: Promise.resolve(params)
13141
13488
  });
13142
- return normalizeRouteResponse(result2);
13489
+ return normalizeRouteResponse(result);
13143
13490
  }
13144
13491
  const url = new URL(request.url);
13145
13492
  const query = {};
@@ -13164,15 +13511,30 @@ async function invokeAPIRouteEndpointInContext(endpoint2, request, params) {
13164
13511
  if (headersValidation instanceof Response) {
13165
13512
  return headersValidation;
13166
13513
  }
13167
- const result = await farmHandler({
13514
+ const handlerContext = {
13168
13515
  query: queryValidation,
13169
13516
  body: bodyValidation,
13170
13517
  headers: headersValidation,
13171
13518
  request,
13172
13519
  context: {},
13173
13520
  params
13174
- });
13175
- return normalizeRouteResponse(result);
13521
+ };
13522
+ let execution;
13523
+ try {
13524
+ execution = typeof endpoint2.__farmInvoke === "function" ? await endpoint2.__farmInvoke(handlerContext) : {
13525
+ result: await farmHandler(handlerContext),
13526
+ context: handlerContext.context,
13527
+ handlerExecuted: true,
13528
+ invalidations: []
13529
+ };
13530
+ } catch (error) {
13531
+ if (isEndpointFailure(error)) {
13532
+ return createEndpointFailureResponse(error);
13533
+ }
13534
+ throw error;
13535
+ }
13536
+ const response = normalizeRouteResponse(execution.result);
13537
+ return attachEndpointInvalidations(response, execution.invalidations);
13176
13538
  }
13177
13539
  function normalizeRouteResponse(result) {
13178
13540
  if (isWebResponse2(result)) {
@@ -13189,6 +13551,38 @@ function normalizeRouteResponse(result) {
13189
13551
  function isWebResponse2(value) {
13190
13552
  return value instanceof Response || typeof value === "object" && value !== null && "headers" in value && "status" in value && typeof value.arrayBuffer === "function";
13191
13553
  }
13554
+ function attachEndpointInvalidations(response, keys) {
13555
+ const existing = decodeFarmCacheInvalidations(
13556
+ response.headers.get(FARM_CACHE_INVALIDATION_HEADER)
13557
+ );
13558
+ const encoded = encodeFarmCacheInvalidations([...existing, ...keys]);
13559
+ if (!encoded) return response;
13560
+ const headers2 = new Headers(response.headers);
13561
+ headers2.set(FARM_CACHE_INVALIDATION_HEADER, encoded);
13562
+ return new Response(response.body, {
13563
+ status: response.status,
13564
+ statusText: response.statusText,
13565
+ headers: headers2
13566
+ });
13567
+ }
13568
+ function createEndpointFailureResponse(failure) {
13569
+ return new Response(
13570
+ JSON.stringify({
13571
+ error: {
13572
+ code: failure.code,
13573
+ message: failure.message,
13574
+ data: failure.data
13575
+ }
13576
+ }),
13577
+ {
13578
+ status: failure.status,
13579
+ headers: {
13580
+ "cache-control": "no-store",
13581
+ "content-type": "application/json"
13582
+ }
13583
+ }
13584
+ );
13585
+ }
13192
13586
  function isFarmContextHandler(endpoint2) {
13193
13587
  if (typeof endpoint2 !== "function") {
13194
13588
  return false;
@@ -13297,11 +13691,15 @@ var init_runtime2 = __esm({
13297
13691
  "src/api/runtime.ts"() {
13298
13692
  "use strict";
13299
13693
  init_request();
13694
+ init_cache_invalidation();
13695
+ init_endpoint();
13300
13696
  __name(matchAPIRoute, "matchAPIRoute");
13301
13697
  __name(invokeAPIRouteEndpoint, "invokeAPIRouteEndpoint");
13302
13698
  __name(invokeAPIRouteEndpointInContext, "invokeAPIRouteEndpointInContext");
13303
13699
  __name(normalizeRouteResponse, "normalizeRouteResponse");
13304
13700
  __name(isWebResponse2, "isWebResponse");
13701
+ __name(attachEndpointInvalidations, "attachEndpointInvalidations");
13702
+ __name(createEndpointFailureResponse, "createEndpointFailureResponse");
13305
13703
  __name(isFarmContextHandler, "isFarmContextHandler");
13306
13704
  __name(readJSONBody, "readJSONBody");
13307
13705
  __name(validateInput, "validateInput");
@@ -14262,7 +14660,7 @@ var init_manager = __esm({
14262
14660
  if (!nestedMatch.matched) {
14263
14661
  return { matched: false };
14264
14662
  }
14265
- const params = { ...nestedMatch.params || {} };
14663
+ const params = { ...nestedMatch.params };
14266
14664
  delete params.__farmRest;
14267
14665
  return {
14268
14666
  matched: true,
@@ -15414,6 +15812,24 @@ var init_environment_vite = __esm({
15414
15812
  }
15415
15813
  });
15416
15814
 
15815
+ // package.json
15816
+ var version;
15817
+ var init_package = __esm({
15818
+ "package.json"() {
15819
+ version = "0.1.0-beta.3";
15820
+ }
15821
+ });
15822
+
15823
+ // src/version.ts
15824
+ var FARM_VERSION;
15825
+ var init_version = __esm({
15826
+ "src/version.ts"() {
15827
+ "use strict";
15828
+ init_package();
15829
+ FARM_VERSION = version;
15830
+ }
15831
+ });
15832
+
15417
15833
  // src/after.ts
15418
15834
  function getAfterStorage() {
15419
15835
  const runtime = globalThis;
@@ -16187,7 +16603,9 @@ function readManifest(contentDir) {
16187
16603
  const manifestPath = import_node_path7.default.join(contentDir, FARM_DOCS_LAST_MODIFIED_MANIFEST);
16188
16604
  if (!(0, import_node_fs5.existsSync)(manifestPath)) return null;
16189
16605
  try {
16190
- const parsed = JSON.parse((0, import_node_fs5.readFileSync)(manifestPath, "utf8"));
16606
+ const parsed = JSON.parse(
16607
+ (0, import_node_fs5.readFileSync)(manifestPath, "utf8")
16608
+ );
16191
16609
  if (parsed.version !== 1 || !parsed.pages || typeof parsed.pages !== "object") return null;
16192
16610
  const pages = Object.fromEntries(
16193
16611
  Object.entries(parsed.pages).filter(
@@ -22558,16 +22976,7 @@ __export(devtools_client_exports, {
22558
22976
  function parseShortcut(shortcut) {
22559
22977
  const tokens = shortcut.toLowerCase().split("+").map((token) => token.trim()).filter(Boolean);
22560
22978
  const key = tokens.find(
22561
- (token) => ![
22562
- "alt",
22563
- "ctrl",
22564
- "control",
22565
- "meta",
22566
- "cmd",
22567
- "command",
22568
- "mod",
22569
- "shift"
22570
- ].includes(token)
22979
+ (token) => !["alt", "ctrl", "control", "meta", "cmd", "command", "mod", "shift"].includes(token)
22571
22980
  );
22572
22981
  if (!key) {
22573
22982
  return null;
@@ -22998,7 +23407,7 @@ function isResolvedEnvScope(value) {
22998
23407
  );
22999
23408
  }
23000
23409
  function isPotentialProgrammaticRouteSourceFile(normalizedFile, srcDirSlug) {
23001
- return normalizedFile.startsWith(`${srcDirSlug}/`) && /\.(ts|tsx|js|jsx)$/.test(normalizedFile) && !/\.d\.ts$/.test(normalizedFile) && !normalizedFile.endsWith("/farm-routes.d.ts") && !normalizedFile.endsWith("/farm-env.d.ts") && !normalizedFile.endsWith("/lib/api.generated.ts");
23410
+ return normalizedFile.startsWith(`${srcDirSlug}/`) && /\.(ts|tsx|js|jsx)$/.test(normalizedFile) && !normalizedFile.endsWith(".d.ts") && !normalizedFile.endsWith("/farm-routes.d.ts") && !normalizedFile.endsWith("/farm-env.d.ts") && !normalizedFile.endsWith("/lib/api.generated.ts");
23002
23411
  }
23003
23412
  function fileContainsProgrammaticPageRoute(file) {
23004
23413
  if (!fs7.existsSync(file)) {
@@ -26109,7 +26518,7 @@ async function defineConfig2(config = {}) {
26109
26518
  const isExposed = hostConfig === true || hostConfig === "0.0.0.0";
26110
26519
  console.log("");
26111
26520
  console.log(
26112
- ` ${pc.bold(pc.green("Farm.js"))} ${pc.dim("v1.0.0")} ${pc.dim(`ready in ${elapsed}ms`)}`
26521
+ ` ${pc.bold(pc.green("Farm.js"))} ${pc.dim(`v${FARM_VERSION}`)} ${pc.dim(`ready in ${elapsed}ms`)}`
26113
26522
  );
26114
26523
  console.log("");
26115
26524
  console.log(
@@ -26233,6 +26642,7 @@ var init_vite = __esm({
26233
26642
  path21 = __toESM(require("path"));
26234
26643
  init_layers();
26235
26644
  init_environment_vite();
26645
+ init_version();
26236
26646
  init_deferred();
26237
26647
  init_after();
26238
26648
  init_deployment();
@@ -27448,14 +27858,12 @@ export default defineEventHandler(async (event: H3Event) => {
27448
27858
  ...preset === "cloudflare-module" && cloudflareCronConfig ? {
27449
27859
  cloudflare: cloudflareCronConfig
27450
27860
  } : {},
27451
- handlers: [
27452
- ...farmWorkflows.handlerPath ? [
27453
- {
27454
- route: `${config.workflows.route}/**`,
27455
- handler: farmWorkflows.handlerPath
27456
- }
27457
- ] : []
27458
- ],
27861
+ handlers: farmWorkflows.handlerPath ? [
27862
+ {
27863
+ route: `${config.workflows.route}/**`,
27864
+ handler: farmWorkflows.handlerPath
27865
+ }
27866
+ ] : [],
27459
27867
  // Route rules for Vercel
27460
27868
  routeRules: {
27461
27869
  "/api/**": {
@@ -27601,6 +28009,7 @@ var init_nitro = __esm({
27601
28009
  // src/index.ts
27602
28010
  var src_exports = {};
27603
28011
  __export(src_exports, {
28012
+ APIClientError: () => APIClientError,
27604
28013
  APIRouteManager: () => APIRouteManager,
27605
28014
  APITypeGenerator: () => APITypeGenerator,
27606
28015
  API_ROUTE_METHODS: () => API_ROUTE_METHODS,
@@ -27613,6 +28022,8 @@ __export(src_exports, {
27613
28022
  DELETE: () => DELETE,
27614
28023
  DeferredDataError: () => DeferredDataError,
27615
28024
  DocsRoute: () => DocsRoute,
28025
+ EndpointFailure: () => EndpointFailure,
28026
+ FARM_API_ROUTE_REF_SYMBOL: () => FARM_API_ROUTE_REF_SYMBOL,
27616
28027
  FARM_CRON_MANIFEST: () => FARM_CRON_MANIFEST,
27617
28028
  FARM_DEFERRED_BRAND: () => FARM_DEFERRED_BRAND,
27618
28029
  FARM_DEFERRED_CONTENT_TYPE: () => FARM_DEFERRED_CONTENT_TYPE,
@@ -27739,6 +28150,7 @@ __export(src_exports, {
27739
28150
  cronRoute: () => cronRoute,
27740
28151
  databaseStorage: () => databaseStorage,
27741
28152
  defer: () => defer,
28153
+ defineCacheKey: () => defineCacheKey,
27742
28154
  defineConfig: () => defineConfig,
27743
28155
  defineCron: () => defineCron,
27744
28156
  defineFarmConfig: () => defineFarmConfig,
@@ -27825,9 +28237,11 @@ __export(src_exports, {
27825
28237
  invalidate: () => invalidate,
27826
28238
  invalidateRouteData: () => invalidateRouteData,
27827
28239
  invokeAPIRouteEndpoint: () => invokeAPIRouteEndpoint,
28240
+ isAPIRouteRef: () => isAPIRouteRef,
27828
28241
  isChunkLoadError: () => isChunkLoadError,
27829
28242
  isCronRequestAuthorized: () => isCronRequestAuthorized,
27830
28243
  isDeferred: () => isDeferred,
28244
+ isEndpointFailure: () => isEndpointFailure,
27831
28245
  isFarmDeploymentMismatchResponse: () => isFarmDeploymentMismatchResponse,
27832
28246
  isFarmDocsAPIRequest: () => isFarmDocsAPIRequest,
27833
28247
  isFarmDocsRequest: () => isFarmDocsRequest,
@@ -27946,6 +28360,7 @@ __export(src_exports, {
27946
28360
  updateTag: () => updateTag,
27947
28361
  upstashStorage: () => upstashStorage,
27948
28362
  useBlocker: () => useBlocker,
28363
+ useMutation: () => useMutation,
27949
28364
  useNavigation: () => useNavigation,
27950
28365
  usePageState: () => usePageState,
27951
28366
  usePathname: () => usePathname,
@@ -28181,173 +28596,8 @@ function createLoggerPlugin({
28181
28596
  }
28182
28597
  __name(createLoggerPlugin, "createLoggerPlugin");
28183
28598
 
28184
- // src/api/endpoint.ts
28185
- var import_better_call = require("better-call");
28186
- function createEndpoint(pathOrOptions, optionsOrHandler, maybeHandler) {
28187
- let path28;
28188
- let options;
28189
- let handler;
28190
- if (typeof pathOrOptions === "string") {
28191
- path28 = pathOrOptions;
28192
- options = optionsOrHandler;
28193
- handler = maybeHandler;
28194
- } else {
28195
- path28 = "";
28196
- options = pathOrOptions;
28197
- handler = optionsOrHandler;
28198
- }
28199
- if (typeof handler !== "function") {
28200
- throw new TypeError("createEndpoint requires a handler function");
28201
- }
28202
- const middleware2 = normalizeEndpointMiddleware(options.middleware);
28203
- const wrappedHandler = /* @__PURE__ */ __name(((ctx) => runEndpointMiddleware(middleware2, ctx, handler)), "wrappedHandler");
28204
- const { middleware: _middleware, ...betterCallOptions } = options;
28205
- const endpoint2 = (0, import_better_call.createEndpoint)(
28206
- path28 || "/__farm_auto_path__",
28207
- betterCallOptions,
28208
- wrappedHandler
28209
- );
28210
- endpoint2.__path = path28 || void 0;
28211
- endpoint2.__method = options.method || "GET";
28212
- endpoint2.__autoPath = !path28;
28213
- endpoint2.__handler = wrappedHandler;
28214
- endpoint2.__middleware = middleware2;
28215
- endpoint2.__sourceHandler = handler;
28216
- endpoint2.__types = {
28217
- body: options.body,
28218
- query: options.query,
28219
- headers: options.headers,
28220
- response: null
28221
- };
28222
- return endpoint2;
28223
- }
28224
- __name(createEndpoint, "createEndpoint");
28225
- var EMPTY_ENDPOINT_MIDDLEWARE = Object.freeze([]);
28226
- var EMPTY_ENDPOINT_CONTEXT = Object.freeze(/* @__PURE__ */ Object.create(null));
28227
- var UNSAFE_ENDPOINT_CONTEXT_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
28228
- function normalizeEndpointMiddleware(middleware2) {
28229
- if (middleware2 === void 0) return EMPTY_ENDPOINT_MIDDLEWARE;
28230
- if (!Array.isArray(middleware2)) {
28231
- throw new TypeError("createEndpoint middleware must be an array of functions");
28232
- }
28233
- const normalized = [...middleware2];
28234
- for (const entry of normalized) {
28235
- if (typeof entry !== "function") {
28236
- throw new TypeError("createEndpoint middleware entries must be functions");
28237
- }
28238
- }
28239
- return Object.freeze(normalized);
28240
- }
28241
- __name(normalizeEndpointMiddleware, "normalizeEndpointMiddleware");
28242
- async function runEndpointMiddleware(middleware2, handlerContext, handler) {
28243
- let context = createInitialEndpointContext(handlerContext.context);
28244
- for (let index = 0; index < middleware2.length; index++) {
28245
- const result = await middleware2[index]({ ...handlerContext, context });
28246
- if (isEndpointResponse(result)) return result;
28247
- if (result === false) return forbiddenEndpointResponse();
28248
- if (result === true) continue;
28249
- if (!isPlainEndpointContext(result)) {
28250
- throw new TypeError(
28251
- `Endpoint middleware ${index + 1} must return an object, true, false, or a Response`
28252
- );
28253
- }
28254
- context = mergeEndpointContext(context, result, index);
28255
- }
28256
- return handler({ ...handlerContext, context });
28257
- }
28258
- __name(runEndpointMiddleware, "runEndpointMiddleware");
28259
- function createInitialEndpointContext(value) {
28260
- if (value === void 0 || value === null) return EMPTY_ENDPOINT_CONTEXT;
28261
- if (!isPlainEndpointContext(value)) {
28262
- throw new TypeError("Endpoint context must be a plain object");
28263
- }
28264
- return mergeEndpointContext(EMPTY_ENDPOINT_CONTEXT, value);
28265
- }
28266
- __name(createInitialEndpointContext, "createInitialEndpointContext");
28267
- function mergeEndpointContext(current, added, middlewareIndex) {
28268
- const next = Object.assign(/* @__PURE__ */ Object.create(null), current);
28269
- for (const key of Reflect.ownKeys(added)) {
28270
- if (!Object.prototype.propertyIsEnumerable.call(added, key)) continue;
28271
- if (typeof key === "string" && UNSAFE_ENDPOINT_CONTEXT_KEYS.has(key)) {
28272
- throw new TypeError(`Endpoint middleware cannot provide the unsafe context key "${key}"`);
28273
- }
28274
- if (Object.prototype.hasOwnProperty.call(current, key)) {
28275
- const source = middlewareIndex === void 0 ? "Endpoint context" : `Endpoint middleware ${middlewareIndex + 1}`;
28276
- throw new TypeError(`${source} cannot replace the existing context key "${String(key)}"`);
28277
- }
28278
- next[key] = added[key];
28279
- }
28280
- return Object.freeze(next);
28281
- }
28282
- __name(mergeEndpointContext, "mergeEndpointContext");
28283
- function isPlainEndpointContext(value) {
28284
- if (!value || typeof value !== "object" || Array.isArray(value)) return false;
28285
- const prototype = Object.getPrototypeOf(value);
28286
- return prototype === Object.prototype || prototype === null;
28287
- }
28288
- __name(isPlainEndpointContext, "isPlainEndpointContext");
28289
- function isEndpointResponse(value) {
28290
- return value instanceof Response || typeof value === "object" && value !== null && "headers" in value && "status" in value && typeof value.arrayBuffer === "function";
28291
- }
28292
- __name(isEndpointResponse, "isEndpointResponse");
28293
- function forbiddenEndpointResponse() {
28294
- return new Response(JSON.stringify({ error: "Forbidden" }), {
28295
- status: 403,
28296
- headers: { "Content-Type": "application/json" }
28297
- });
28298
- }
28299
- __name(forbiddenEndpointResponse, "forbiddenEndpointResponse");
28300
- function GET(...args) {
28301
- if (args.length === 1) {
28302
- return createEndpoint("", { method: "GET" }, args[0]);
28303
- }
28304
- return createEndpoint("", { ...args[0], method: "GET" }, args[1]);
28305
- }
28306
- __name(GET, "GET");
28307
- function HEAD(...args) {
28308
- if (args.length === 1) {
28309
- return createEndpoint("", { method: "HEAD" }, args[0]);
28310
- }
28311
- return createEndpoint("", { ...args[0], method: "HEAD" }, args[1]);
28312
- }
28313
- __name(HEAD, "HEAD");
28314
- function POST(...args) {
28315
- if (args.length === 1) {
28316
- return createEndpoint("", { method: "POST" }, args[0]);
28317
- }
28318
- return createEndpoint("", { ...args[0], method: "POST" }, args[1]);
28319
- }
28320
- __name(POST, "POST");
28321
- function PUT(...args) {
28322
- if (args.length === 1) {
28323
- return createEndpoint("", { method: "PUT" }, args[0]);
28324
- }
28325
- return createEndpoint("", { ...args[0], method: "PUT" }, args[1]);
28326
- }
28327
- __name(PUT, "PUT");
28328
- function DELETE(...args) {
28329
- if (args.length === 1) {
28330
- return createEndpoint("", { method: "DELETE" }, args[0]);
28331
- }
28332
- return createEndpoint("", { ...args[0], method: "DELETE" }, args[1]);
28333
- }
28334
- __name(DELETE, "DELETE");
28335
- function PATCH(...args) {
28336
- if (args.length === 1) {
28337
- return createEndpoint("", { method: "PATCH" }, args[0]);
28338
- }
28339
- return createEndpoint("", { ...args[0], method: "PATCH" }, args[1]);
28340
- }
28341
- __name(PATCH, "PATCH");
28342
- function OPTIONS(...args) {
28343
- if (args.length === 1) {
28344
- return createEndpoint("", { method: "OPTIONS" }, args[0]);
28345
- }
28346
- return createEndpoint("", { ...args[0], method: "OPTIONS" }, args[1]);
28347
- }
28348
- __name(OPTIONS, "OPTIONS");
28349
-
28350
28599
  // src/api/index.ts
28600
+ init_endpoint();
28351
28601
  init_route_manager2();
28352
28602
 
28353
28603
  // src/integration-client.ts
@@ -28459,7 +28709,7 @@ function mergeIntegrationClientData(...values) {
28459
28709
  continue;
28460
28710
  }
28461
28711
  merged = {
28462
- ...merged || {},
28712
+ ...merged,
28463
28713
  ...data
28464
28714
  };
28465
28715
  }
@@ -29289,6 +29539,20 @@ function normalizeFarmClientCacheKey(key) {
29289
29539
  __name(normalizeFarmClientCacheKey, "normalizeFarmClientCacheKey");
29290
29540
 
29291
29541
  // src/api/client.ts
29542
+ init_cache_invalidation();
29543
+ var FARM_API_ROUTE_REF_SYMBOL = /* @__PURE__ */ Symbol.for("farm.api.route-ref");
29544
+ var _APIClientError = class _APIClientError extends Error {
29545
+ constructor(code, data, options) {
29546
+ super(options.message);
29547
+ this.name = "APIClientError";
29548
+ this.code = code;
29549
+ this.data = data;
29550
+ this.status = options.status;
29551
+ this.response = options.response;
29552
+ }
29553
+ };
29554
+ __name(_APIClientError, "APIClientError");
29555
+ var APIClientError = _APIClientError;
29292
29556
  function createAPIClient(options = {}) {
29293
29557
  options ?? (options = {});
29294
29558
  const baseURL = options.baseURL || (typeof window !== "undefined" ? window.location.origin : "http://localhost:3000");
@@ -29326,6 +29590,9 @@ function createAPIClient(options = {}) {
29326
29590
  fetchOptions.body = JSON.stringify(requestOptions.body);
29327
29591
  }
29328
29592
  const response = await fetch(url.toString(), fetchOptions);
29593
+ applyFarmCacheInvalidations(
29594
+ decodeFarmCacheInvalidations(response.headers?.get?.(FARM_CACHE_INVALIDATION_HEADER))
29595
+ );
29329
29596
  let data = void 0;
29330
29597
  if (response.status !== 204 && response.status !== 205) {
29331
29598
  data = await response.json();
@@ -29565,9 +29832,15 @@ function createNestedProxy(path28, client, routeMeta, baseURL, rootAliases) {
29565
29832
  const proxy = new Proxy(target, {
29566
29833
  // When accessing a property (api.hello)
29567
29834
  get(_target, prop) {
29835
+ if (prop === FARM_API_ROUTE_REF_SYMBOL) {
29836
+ return path28.length > 0;
29837
+ }
29568
29838
  if (path28.length === 0 && typeof prop === "string" && rootAliases && prop in rootAliases) {
29569
29839
  return rootAliases[prop];
29570
29840
  }
29841
+ if (typeof prop !== "string") {
29842
+ return Reflect.get(_target, prop);
29843
+ }
29571
29844
  return createNestedProxy([...path28, prop], client, routeMeta, baseURL, rootAliases);
29572
29845
  },
29573
29846
  // When calling as a function
@@ -29590,6 +29863,10 @@ function createNestedProxy(path28, client, routeMeta, baseURL, rootAliases) {
29590
29863
  return proxy;
29591
29864
  }
29592
29865
  __name(createNestedProxy, "createNestedProxy");
29866
+ function isAPIRouteRef(value) {
29867
+ return typeof value === "function" && value[FARM_API_ROUTE_REF_SYMBOL] === true;
29868
+ }
29869
+ __name(isAPIRouteRef, "isAPIRouteRef");
29593
29870
  function createServerAPIClient(endpoints, options = {}) {
29594
29871
  if (options.integrations === false || Object.prototype.hasOwnProperty.call(endpoints, "integrations")) {
29595
29872
  return endpoints;
@@ -29656,7 +29933,10 @@ function resolveTargetKey(routeMeta, target, input, baseURL = "http://localhost:
29656
29933
  }
29657
29934
  if (Array.isArray(target)) {
29658
29935
  const [route2, routeInput] = target;
29659
- return resolveTargetKey(routeMeta, route2, routeInput, baseURL);
29936
+ if (typeof route2 === "function") {
29937
+ return resolveTargetKey(routeMeta, route2, routeInput, baseURL);
29938
+ }
29939
+ return normalizeFarmClientCacheKey(target);
29660
29940
  }
29661
29941
  if ("key" in target) return normalizeFarmClientCacheKey(target.key);
29662
29942
  if ("path" in target) {
@@ -29682,18 +29962,45 @@ function resolveRouteMeta(meta) {
29682
29962
  }
29683
29963
  __name(resolveRouteMeta, "resolveRouteMeta");
29684
29964
  function normalizeError(error) {
29685
- if (error instanceof Error) return error;
29686
- return new Error(typeof error === "string" ? error : "Unknown error");
29965
+ if (error instanceof APIClientError) return error;
29966
+ const normalized = new APIClientError("network_error", void 0, {
29967
+ status: 0,
29968
+ message: error instanceof Error ? error.message : typeof error === "string" ? error : "Network request failed"
29969
+ });
29970
+ normalized.cause = error;
29971
+ return normalized;
29687
29972
  }
29688
29973
  __name(normalizeError, "normalizeError");
29689
29974
  function createResponseError2(response, data) {
29690
- const error = new Error(`HTTP ${response.status}: ${response.statusText}`);
29691
- error.status = response.status;
29692
- error.response = response;
29693
- error.data = data;
29694
- return error;
29975
+ const expected = readEndpointErrorEnvelope(data);
29976
+ if (expected) {
29977
+ return new APIClientError(expected.code, expected.data, {
29978
+ status: response.status,
29979
+ message: expected.message,
29980
+ response
29981
+ });
29982
+ }
29983
+ return new APIClientError("http_error", data, {
29984
+ status: response.status,
29985
+ message: `HTTP ${response.status}: ${response.statusText}`,
29986
+ response
29987
+ });
29695
29988
  }
29696
29989
  __name(createResponseError2, "createResponseError");
29990
+ function readEndpointErrorEnvelope(data) {
29991
+ if (!data || typeof data !== "object") return null;
29992
+ const error = data.error;
29993
+ if (!error || typeof error !== "object") return null;
29994
+ const code = error.code;
29995
+ const message = error.message;
29996
+ if (typeof code !== "string" || typeof message !== "string") return null;
29997
+ return {
29998
+ code,
29999
+ message,
30000
+ data: error.data
30001
+ };
30002
+ }
30003
+ __name(readEndpointErrorEnvelope, "readEndpointErrorEnvelope");
29697
30004
 
29698
30005
  // src/api/vite-plugin.ts
29699
30006
  init_route_manager2();
@@ -29915,69 +30222,71 @@ function farmApiPlugin(options = {}) {
29915
30222
  waitForDiscovery: /* @__PURE__ */ __name(() => discoveryPromise, "waitForDiscovery")
29916
30223
  };
29917
30224
  return () => {
29918
- server.middlewares.use(_withAfterNodeMiddleware(async (req, res, next) => {
29919
- const url = req.url || "/";
29920
- const pathname = url.split("?")[0];
29921
- const method = req.method || "GET";
29922
- if (discoveryPromise && !discoveryComplete) {
29923
- await discoveryPromise;
29924
- }
29925
- if (!matchAPIRoute(apiRoutesCache, pathname)) {
29926
- return next();
29927
- }
29928
- if (!apiRouterHandler) {
29929
- return next();
29930
- }
29931
- const startTime = Date.now();
29932
- try {
29933
- const farmMiddleware = server.__farmMiddleware__;
29934
- if (farmMiddleware) {
29935
- await farmMiddleware.waitForDiscovery?.();
29936
- const middlewareData = /* @__PURE__ */ new Map();
29937
- const handled = await farmMiddleware.execute(req, res, pathname, middlewareData);
29938
- if (handled) {
29939
- const duration2 = Date.now() - startTime;
29940
- logResponse(method, pathname, res.statusCode || 200, duration2);
29941
- return;
29942
- }
30225
+ server.middlewares.use(
30226
+ _withAfterNodeMiddleware(async (req, res, next) => {
30227
+ const url = req.url || "/";
30228
+ const pathname = url.split("?")[0];
30229
+ const method = req.method || "GET";
30230
+ if (discoveryPromise && !discoveryComplete) {
30231
+ await discoveryPromise;
29943
30232
  }
29944
- const fullUrl = `http://${req.headers.host || "localhost:3000"}${url}`;
29945
- const headers2 = new Headers();
29946
- for (const [key, value] of Object.entries(req.headers)) {
29947
- if (value) {
29948
- headers2.set(key, Array.isArray(value) ? value.join(", ") : value);
29949
- }
30233
+ if (!matchAPIRoute(apiRoutesCache, pathname)) {
30234
+ return next();
29950
30235
  }
29951
- let body;
29952
- if (method !== "GET" && method !== "HEAD") {
29953
- body = await new Promise((resolve5) => {
29954
- let data = "";
29955
- req.on("data", (chunk) => {
29956
- data += chunk;
29957
- });
29958
- req.on("end", () => {
29959
- resolve5(data);
30236
+ if (!apiRouterHandler) {
30237
+ return next();
30238
+ }
30239
+ const startTime = Date.now();
30240
+ try {
30241
+ const farmMiddleware = server.__farmMiddleware__;
30242
+ if (farmMiddleware) {
30243
+ await farmMiddleware.waitForDiscovery?.();
30244
+ const middlewareData = /* @__PURE__ */ new Map();
30245
+ const handled = await farmMiddleware.execute(req, res, pathname, middlewareData);
30246
+ if (handled) {
30247
+ const duration2 = Date.now() - startTime;
30248
+ logResponse(method, pathname, res.statusCode || 200, duration2);
30249
+ return;
30250
+ }
30251
+ }
30252
+ const fullUrl = `http://${req.headers.host || "localhost:3000"}${url}`;
30253
+ const headers2 = new Headers();
30254
+ for (const [key, value] of Object.entries(req.headers)) {
30255
+ if (value) {
30256
+ headers2.set(key, Array.isArray(value) ? value.join(", ") : value);
30257
+ }
30258
+ }
30259
+ let body;
30260
+ if (method !== "GET" && method !== "HEAD") {
30261
+ body = await new Promise((resolve5) => {
30262
+ let data = "";
30263
+ req.on("data", (chunk) => {
30264
+ data += chunk;
30265
+ });
30266
+ req.on("end", () => {
30267
+ resolve5(data);
30268
+ });
29960
30269
  });
30270
+ }
30271
+ const request = new Request(fullUrl, {
30272
+ method,
30273
+ headers: headers2,
30274
+ body: body || void 0
29961
30275
  });
30276
+ const response = await apiRouterHandler(request);
30277
+ const duration = Date.now() - startTime;
30278
+ logResponse(method, pathname, response.status, duration);
30279
+ await sendWebResponse(res, response);
30280
+ } catch (error) {
30281
+ const duration = Date.now() - startTime;
30282
+ logResponse(method, pathname, 500, duration);
30283
+ console.error("[FARM] API error:", error);
30284
+ res.statusCode = 500;
30285
+ res.setHeader("Content-Type", "application/json");
30286
+ res.end(JSON.stringify({ error: "Internal server error" }));
29962
30287
  }
29963
- const request = new Request(fullUrl, {
29964
- method,
29965
- headers: headers2,
29966
- body: body || void 0
29967
- });
29968
- const response = await apiRouterHandler(request);
29969
- const duration = Date.now() - startTime;
29970
- logResponse(method, pathname, response.status, duration);
29971
- await sendWebResponse(res, response);
29972
- } catch (error) {
29973
- const duration = Date.now() - startTime;
29974
- logResponse(method, pathname, 500, duration);
29975
- console.error("[FARM] API error:", error);
29976
- res.statusCode = 500;
29977
- res.setHeader("Content-Type", "application/json");
29978
- res.end(JSON.stringify({ error: "Internal server error" }));
29979
- }
29980
- }));
30288
+ })
30289
+ );
29981
30290
  };
29982
30291
  },
29983
30292
  async handleHotUpdate({ file, server, modules }) {
@@ -31026,7 +31335,7 @@ function matchRoutePath2(pathname, middlewarePath) {
31026
31335
  if (!nestedMatch.matched) {
31027
31336
  return { matched: false };
31028
31337
  }
31029
- const params = { ...nestedMatch.params || {} };
31338
+ const params = { ...nestedMatch.params };
31030
31339
  delete params.__farmRest;
31031
31340
  return {
31032
31341
  matched: true,
@@ -32330,8 +32639,8 @@ function compareRuntimeRoutes(left, right) {
32330
32639
  __name(compareRuntimeRoutes, "compareRuntimeRoutes");
32331
32640
  function getPatternSpecificity(pattern) {
32332
32641
  return normalizePattern(pattern).split("/").filter(Boolean).reduce((score, segment) => {
32333
- if (segment === "**" || /^\[\[\.\.\./.test(segment)) return score + 1;
32334
- if (segment === "*" || /^\[\.\.\./.test(segment)) return score + 10;
32642
+ if (segment === "**" || segment.startsWith("[[...")) return score + 1;
32643
+ if (segment === "*" || segment.startsWith("[...")) return score + 10;
32335
32644
  if (/^\[.+\]$/.test(segment)) return score + 50;
32336
32645
  return score + 100;
32337
32646
  }, 0);
@@ -36969,9 +37278,8 @@ async function buildNitroUniversal(config, routeManager, apiRouteManager, server
36969
37278
  const nitroEntryPath = import_path12.default.join(ssrOutputDir, "nitro-entry.mjs");
36970
37279
  const nitroEntryCode = `
36971
37280
  // Farm.js Nitro Entry
36972
- // This file imports h3 and the SSR handler, wrapping it for Nitro
37281
+ // This file adapts Farm's Web fetch handler to Nitro's event handler contract.
36973
37282
 
36974
- import { defineEventHandler } from 'h3'
36975
37283
  import handler from './${ssrEntryFile}'
36976
37284
 
36977
37285
  function mergeVaryHeaders(target, source) {
@@ -37009,8 +37317,8 @@ function createResponseFinishedHook(event) {
37009
37317
  }
37010
37318
  }
37011
37319
 
37012
- // Export the wrapped handler for Nitro
37013
- export default defineEventHandler(async (event) => {
37320
+ // Export the event handler for Nitro
37321
+ export default async function farmNitroEventHandler(event) {
37014
37322
  const response = await handler.fetch(event.req, {
37015
37323
  waitUntil: (promise) => event.waitUntil(promise),
37016
37324
  onResponseFinished: createResponseFinishedHook(event),
@@ -37021,7 +37329,7 @@ export default defineEventHandler(async (event) => {
37021
37329
  const farmVary = response.headers.get('Vary')
37022
37330
  if (farmVary) mergeVaryHeaders(event.res.headers, farmVary)
37023
37331
  return response
37024
- })
37332
+ }
37025
37333
  `.trim();
37026
37334
  await fs9.writeFile(nitroEntryPath, nitroEntryCode);
37027
37335
  const prebuiltSSRPlugin = createExternalSSRBundlePlugin(
@@ -37439,8 +37747,8 @@ async function copySharpRuntime(config, root, nitroFuncDir, fs9) {
37439
37747
  await fs9.mkdir(import_path12.default.dirname(targetDir), { recursive: true });
37440
37748
  const packageRequire = (0, import_module3.createRequire)(packageJsonPath);
37441
37749
  const dependencies = {
37442
- ...packageJson.dependencies || {},
37443
- ...packageJson.optionalDependencies || {}
37750
+ ...packageJson.dependencies,
37751
+ ...packageJson.optionalDependencies
37444
37752
  };
37445
37753
  await Promise.all([
37446
37754
  fs9.cp(packageDir, targetDir, {
@@ -37533,7 +37841,7 @@ init_environment_vite();
37533
37841
  // src/server/vite-config.ts
37534
37842
  function mergeNoExternal(farmValue, userValue) {
37535
37843
  if (farmValue === true || userValue === true) return true;
37536
- const normalize = /* @__PURE__ */ __name((value) => value == null ? [] : Array.isArray(value) ? value : [value], "normalize");
37844
+ const normalize = /* @__PURE__ */ __name((value) => value == null || value === true ? [] : Array.isArray(value) ? value : [value], "normalize");
37537
37845
  return Array.from(/* @__PURE__ */ new Set([...normalize(farmValue), ...normalize(userValue)]));
37538
37846
  }
37539
37847
  __name(mergeNoExternal, "mergeNoExternal");
@@ -37933,11 +38241,170 @@ async function buildNitro(config, routeManager, apiRouteManager, serverRenderer,
37933
38241
  }
37934
38242
  __name(buildNitro, "buildNitro");
37935
38243
 
38244
+ // src/mutation-client.ts
38245
+ var import_react9 = require("react");
38246
+ function useMutation(target, options = {}) {
38247
+ const initialData = options.initialData ?? null;
38248
+ const optionsRef = (0, import_react9.useRef)(options);
38249
+ const targetRef = (0, import_react9.useRef)(target);
38250
+ const requestIdRef = (0, import_react9.useRef)(0);
38251
+ const initialState = {
38252
+ pendingCount: 0,
38253
+ status: "idle",
38254
+ data: initialData,
38255
+ error: null,
38256
+ variables: void 0
38257
+ };
38258
+ const stateRef = (0, import_react9.useRef)(initialState);
38259
+ const [state, setState] = (0, import_react9.useState)(initialState);
38260
+ optionsRef.current = options;
38261
+ targetRef.current = target;
38262
+ const setMutationState = (0, import_react9.useCallback)(
38263
+ (value) => {
38264
+ setState((current) => {
38265
+ const next = typeof value === "function" ? value(current) : value;
38266
+ stateRef.current = next;
38267
+ return next;
38268
+ });
38269
+ },
38270
+ []
38271
+ );
38272
+ const mutateAsync = (0, import_react9.useCallback)(
38273
+ async (variables) => {
38274
+ const requestId = ++requestIdRef.current;
38275
+ const currentOptions = optionsRef.current;
38276
+ const previousData = stateRef.current.data;
38277
+ const optimisticData = currentOptions.optimistic?.({
38278
+ variables,
38279
+ current: previousData
38280
+ });
38281
+ const hasOptimisticData = optimisticData !== void 0;
38282
+ setMutationState((current) => ({
38283
+ pendingCount: current.pendingCount + 1,
38284
+ status: "pending",
38285
+ data: hasOptimisticData ? optimisticData : currentOptions.resetOnMutate === false ? current.data : null,
38286
+ error: null,
38287
+ variables
38288
+ }));
38289
+ try {
38290
+ const mutationTarget = targetRef.current;
38291
+ const rawResult = isAPIRouteRef(mutationTarget) ? await mutationTarget(variables, currentOptions.request) : await mutationTarget(variables);
38292
+ const data = unwrapMutationResult(rawResult, isAPIRouteRef(mutationTarget));
38293
+ const isLatestRequest = requestId === requestIdRef.current;
38294
+ setMutationState((current) => {
38295
+ const pendingCount = Math.max(0, current.pendingCount - 1);
38296
+ if (!isLatestRequest) {
38297
+ return {
38298
+ ...current,
38299
+ pendingCount,
38300
+ status: pendingCount > 0 ? "pending" : current.status
38301
+ };
38302
+ }
38303
+ return {
38304
+ pendingCount,
38305
+ status: "success",
38306
+ data,
38307
+ error: null,
38308
+ variables
38309
+ };
38310
+ });
38311
+ if (isLatestRequest) {
38312
+ currentOptions.onSuccess?.(data, variables);
38313
+ currentOptions.onSettled?.(data, null, variables);
38314
+ }
38315
+ return data;
38316
+ } catch (cause) {
38317
+ const error = normalizeMutationError(cause);
38318
+ const isLatestRequest = requestId === requestIdRef.current;
38319
+ setMutationState((current) => {
38320
+ const pendingCount = Math.max(0, current.pendingCount - 1);
38321
+ if (!isLatestRequest) {
38322
+ return {
38323
+ ...current,
38324
+ pendingCount,
38325
+ status: pendingCount > 0 ? "pending" : current.status
38326
+ };
38327
+ }
38328
+ return {
38329
+ pendingCount,
38330
+ status: "error",
38331
+ data: hasOptimisticData && currentOptions.rollbackOnError ? previousData : currentOptions.resetOnMutate === false ? current.data : null,
38332
+ error,
38333
+ variables
38334
+ };
38335
+ });
38336
+ if (isLatestRequest) {
38337
+ currentOptions.onError?.(error, variables);
38338
+ currentOptions.onSettled?.(null, error, variables);
38339
+ }
38340
+ throw error;
38341
+ }
38342
+ },
38343
+ [setMutationState]
38344
+ );
38345
+ const mutate = (0, import_react9.useCallback)(
38346
+ (variables) => {
38347
+ void mutateAsync(variables).catch(() => {
38348
+ });
38349
+ },
38350
+ [mutateAsync]
38351
+ );
38352
+ const reset = (0, import_react9.useCallback)(() => {
38353
+ requestIdRef.current += 1;
38354
+ setMutationState({
38355
+ pendingCount: 0,
38356
+ status: "idle",
38357
+ data: optionsRef.current.initialData ?? null,
38358
+ error: null,
38359
+ variables: void 0
38360
+ });
38361
+ }, [setMutationState]);
38362
+ return (0, import_react9.useMemo)(
38363
+ () => ({
38364
+ pending: state.pendingCount > 0,
38365
+ status: state.status,
38366
+ data: state.data,
38367
+ error: state.error,
38368
+ variables: state.variables,
38369
+ mutate,
38370
+ mutateAsync,
38371
+ reset
38372
+ }),
38373
+ [
38374
+ mutate,
38375
+ mutateAsync,
38376
+ reset,
38377
+ state.data,
38378
+ state.error,
38379
+ state.pendingCount,
38380
+ state.status,
38381
+ state.variables
38382
+ ]
38383
+ );
38384
+ }
38385
+ __name(useMutation, "useMutation");
38386
+ function unwrapMutationResult(result, apiRoute) {
38387
+ if (!apiRoute) return result;
38388
+ const apiResult = result;
38389
+ if (apiResult.error) {
38390
+ throw apiResult.error;
38391
+ }
38392
+ return apiResult.data;
38393
+ }
38394
+ __name(unwrapMutationResult, "unwrapMutationResult");
38395
+ function normalizeMutationError(error) {
38396
+ if (error instanceof Error) return error;
38397
+ const normalized = new Error(typeof error === "string" ? error : "Mutation failed");
38398
+ normalized.cause = error;
38399
+ return normalized;
38400
+ }
38401
+ __name(normalizeMutationError, "normalizeMutationError");
38402
+
37936
38403
  // src/client.ts
37937
38404
  init_integration_api();
37938
38405
 
37939
38406
  // src/store.ts
37940
- var import_react9 = require("react");
38407
+ var import_react10 = require("react");
37941
38408
  var RESERVED_STORE_KEYS = /* @__PURE__ */ new Set([
37942
38409
  "use",
37943
38410
  "get",
@@ -38069,20 +38536,20 @@ function createStore(initialState, extend) {
38069
38536
  }
38070
38537
  return lastSlice;
38071
38538
  }, "getSnapshot");
38072
- return (0, import_react9.useSyncExternalStore)(
38539
+ return (0, import_react10.useSyncExternalStore)(
38073
38540
  (notify) => addSubscription(keys, () => notify()),
38074
38541
  getSnapshot,
38075
38542
  getSnapshot
38076
38543
  );
38077
38544
  }
38078
38545
  if (typeof keyOrKeys === "string") {
38079
- return (0, import_react9.useSyncExternalStore)(
38546
+ return (0, import_react10.useSyncExternalStore)(
38080
38547
  (notify) => addSubscription([keyOrKeys], () => notify()),
38081
38548
  () => state[keyOrKeys],
38082
38549
  () => state[keyOrKeys]
38083
38550
  );
38084
38551
  }
38085
- return (0, import_react9.useSyncExternalStore)(
38552
+ return (0, import_react10.useSyncExternalStore)(
38086
38553
  (notify) => addSubscription(null, () => notify()),
38087
38554
  () => state,
38088
38555
  () => state
@@ -38134,7 +38601,7 @@ function createStore(initialState, extend) {
38134
38601
  __name(createStore, "createStore");
38135
38602
 
38136
38603
  // src/client/link.tsx
38137
- var import_react10 = require("react");
38604
+ var import_react11 = require("react");
38138
38605
  init_router();
38139
38606
  init_client_runtime();
38140
38607
  var import_jsx_runtime4 = require("react/jsx-runtime");
@@ -38196,9 +38663,9 @@ function LinkInner({
38196
38663
  onTouchStart,
38197
38664
  ...props
38198
38665
  }, ref) {
38199
- const elementRef = (0, import_react10.useRef)(null);
38200
- const intentTimeoutRef = (0, import_react10.useRef)(null);
38201
- const hasPrefetched = (0, import_react10.useRef)(false);
38666
+ const elementRef = (0, import_react11.useRef)(null);
38667
+ const intentTimeoutRef = (0, import_react11.useRef)(null);
38668
+ const hasPrefetched = (0, import_react11.useRef)(false);
38202
38669
  const { intent, viewport, render } = normalizePrefetch(prefetch2);
38203
38670
  const baseHref = resolveLinkHref(href, params, {
38204
38671
  query,
@@ -38207,17 +38674,17 @@ function LinkInner({
38207
38674
  });
38208
38675
  const resolvedHref = localizeActiveFarmHref(baseHref, locale);
38209
38676
  const isExternal = isExternalUrl(resolvedHref);
38210
- const doPrefetch = (0, import_react10.useCallback)(() => {
38677
+ const doPrefetch = (0, import_react11.useCallback)(() => {
38211
38678
  if (isExternal || hasPrefetched.current) return;
38212
38679
  const router = getRouter2();
38213
38680
  if (!router) return;
38214
38681
  hasPrefetched.current = true;
38215
38682
  router.prefetch(resolvedHref);
38216
38683
  }, [resolvedHref, isExternal]);
38217
- (0, import_react10.useEffect)(() => {
38684
+ (0, import_react11.useEffect)(() => {
38218
38685
  hasPrefetched.current = false;
38219
38686
  }, [resolvedHref]);
38220
- (0, import_react10.useEffect)(() => {
38687
+ (0, import_react11.useEffect)(() => {
38221
38688
  const element = elementRef.current;
38222
38689
  if (!element || isExternal) return;
38223
38690
  const router = getRouter2();
@@ -38227,7 +38694,7 @@ function LinkInner({
38227
38694
  return () => router.unobserveForPrefetch(element);
38228
38695
  }
38229
38696
  }, [resolvedHref, viewport, isExternal]);
38230
- (0, import_react10.useEffect)(() => {
38697
+ (0, import_react11.useEffect)(() => {
38231
38698
  if (!render || isExternal) return;
38232
38699
  let cancelled = false;
38233
38700
  let timeoutId = null;
@@ -38249,7 +38716,7 @@ function LinkInner({
38249
38716
  }
38250
38717
  };
38251
38718
  }, [render, isExternal, resolvedHref]);
38252
- (0, import_react10.useEffect)(() => {
38719
+ (0, import_react11.useEffect)(() => {
38253
38720
  return () => {
38254
38721
  if (intentTimeoutRef.current) {
38255
38722
  clearTimeout(intentTimeoutRef.current);
@@ -38257,13 +38724,13 @@ function LinkInner({
38257
38724
  }
38258
38725
  };
38259
38726
  }, []);
38260
- const cancelIntent = (0, import_react10.useCallback)(() => {
38727
+ const cancelIntent = (0, import_react11.useCallback)(() => {
38261
38728
  if (intentTimeoutRef.current) {
38262
38729
  clearTimeout(intentTimeoutRef.current);
38263
38730
  intentTimeoutRef.current = null;
38264
38731
  }
38265
38732
  }, []);
38266
- const scheduleIntentPrefetch = (0, import_react10.useCallback)(() => {
38733
+ const scheduleIntentPrefetch = (0, import_react11.useCallback)(() => {
38267
38734
  if (isExternal || !intent || hasPrefetched.current) return;
38268
38735
  cancelIntent();
38269
38736
  intentTimeoutRef.current = setTimeout(() => {
@@ -38271,42 +38738,42 @@ function LinkInner({
38271
38738
  doPrefetch();
38272
38739
  }, prefetchDelay);
38273
38740
  }, [intent, isExternal, prefetchDelay, doPrefetch, cancelIntent]);
38274
- const handleMouseEnter = (0, import_react10.useCallback)(
38741
+ const handleMouseEnter = (0, import_react11.useCallback)(
38275
38742
  (event) => {
38276
38743
  onMouseEnter?.(event);
38277
38744
  scheduleIntentPrefetch();
38278
38745
  },
38279
38746
  [onMouseEnter, scheduleIntentPrefetch]
38280
38747
  );
38281
- const handleMouseLeave = (0, import_react10.useCallback)(
38748
+ const handleMouseLeave = (0, import_react11.useCallback)(
38282
38749
  (event) => {
38283
38750
  onMouseLeave?.(event);
38284
38751
  cancelIntent();
38285
38752
  },
38286
38753
  [onMouseLeave, cancelIntent]
38287
38754
  );
38288
- const handleTouchStart = (0, import_react10.useCallback)(
38755
+ const handleTouchStart = (0, import_react11.useCallback)(
38289
38756
  (event) => {
38290
38757
  onTouchStart?.(event);
38291
38758
  scheduleIntentPrefetch();
38292
38759
  },
38293
38760
  [onTouchStart, scheduleIntentPrefetch]
38294
38761
  );
38295
- const handleFocus = (0, import_react10.useCallback)(
38762
+ const handleFocus = (0, import_react11.useCallback)(
38296
38763
  (event) => {
38297
38764
  onFocus?.(event);
38298
38765
  scheduleIntentPrefetch();
38299
38766
  },
38300
38767
  [onFocus, scheduleIntentPrefetch]
38301
38768
  );
38302
- const handleBlur = (0, import_react10.useCallback)(
38769
+ const handleBlur = (0, import_react11.useCallback)(
38303
38770
  (event) => {
38304
38771
  onBlur?.(event);
38305
38772
  cancelIntent();
38306
38773
  },
38307
38774
  [onBlur, cancelIntent]
38308
38775
  );
38309
- const handleClick = (0, import_react10.useCallback)(
38776
+ const handleClick = (0, import_react11.useCallback)(
38310
38777
  (event) => {
38311
38778
  onClick?.(event);
38312
38779
  if (event.defaultPrevented) return;
@@ -38331,7 +38798,7 @@ function LinkInner({
38331
38798
  },
38332
38799
  [resolvedHref, replace, scroll, viewTransition, target, isExternal, onClick]
38333
38800
  );
38334
- const setRefs = (0, import_react10.useCallback)(
38801
+ const setRefs = (0, import_react11.useCallback)(
38335
38802
  (node) => {
38336
38803
  elementRef.current = node;
38337
38804
  if (typeof ref === "function") ref(node);
@@ -38360,7 +38827,7 @@ function LinkInner({
38360
38827
  );
38361
38828
  }
38362
38829
  __name(LinkInner, "LinkInner");
38363
- var LinkWithRef = (0, import_react10.forwardRef)(LinkInner);
38830
+ var LinkWithRef = (0, import_react11.forwardRef)(LinkInner);
38364
38831
  LinkWithRef.displayName = "Link";
38365
38832
  var Link = LinkWithRef;
38366
38833
  function resolveLinkHref(href, params, options) {
@@ -39072,6 +39539,7 @@ function decodeCookiePart(value) {
39072
39539
  __name(decodeCookiePart, "decodeCookiePart");
39073
39540
  // Annotate the CommonJS export names for ESM import in node:
39074
39541
  0 && (module.exports = {
39542
+ APIClientError,
39075
39543
  APIRouteManager,
39076
39544
  APITypeGenerator,
39077
39545
  API_ROUTE_METHODS,
@@ -39084,6 +39552,8 @@ __name(decodeCookiePart, "decodeCookiePart");
39084
39552
  DELETE,
39085
39553
  DeferredDataError,
39086
39554
  DocsRoute,
39555
+ EndpointFailure,
39556
+ FARM_API_ROUTE_REF_SYMBOL,
39087
39557
  FARM_CRON_MANIFEST,
39088
39558
  FARM_DEFERRED_BRAND,
39089
39559
  FARM_DEFERRED_CONTENT_TYPE,
@@ -39210,6 +39680,7 @@ __name(decodeCookiePart, "decodeCookiePart");
39210
39680
  cronRoute,
39211
39681
  databaseStorage,
39212
39682
  defer,
39683
+ defineCacheKey,
39213
39684
  defineConfig,
39214
39685
  defineCron,
39215
39686
  defineFarmConfig,
@@ -39296,9 +39767,11 @@ __name(decodeCookiePart, "decodeCookiePart");
39296
39767
  invalidate,
39297
39768
  invalidateRouteData,
39298
39769
  invokeAPIRouteEndpoint,
39770
+ isAPIRouteRef,
39299
39771
  isChunkLoadError,
39300
39772
  isCronRequestAuthorized,
39301
39773
  isDeferred,
39774
+ isEndpointFailure,
39302
39775
  isFarmDeploymentMismatchResponse,
39303
39776
  isFarmDocsAPIRequest,
39304
39777
  isFarmDocsRequest,
@@ -39417,6 +39890,7 @@ __name(decodeCookiePart, "decodeCookiePart");
39417
39890
  updateTag,
39418
39891
  upstashStorage,
39419
39892
  useBlocker,
39893
+ useMutation,
39420
39894
  useNavigation,
39421
39895
  usePageState,
39422
39896
  usePathname,