@farm.js/core 0.1.0-beta.1 → 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/api.cjs CHANGED
@@ -31,9 +31,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  // src/api/index.ts
32
32
  var api_exports = {};
33
33
  __export(api_exports, {
34
+ APIClientError: () => APIClientError,
34
35
  APIRouteManager: () => APIRouteManager,
35
36
  API_ROUTE_METHODS: () => API_ROUTE_METHODS,
36
37
  DELETE: () => DELETE,
38
+ EndpointFailure: () => EndpointFailure,
39
+ FARM_API_ROUTE_REF_SYMBOL: () => FARM_API_ROUTE_REF_SYMBOL,
37
40
  GET: () => GET,
38
41
  HEAD: () => HEAD,
39
42
  OPTIONS: () => OPTIONS,
@@ -45,6 +48,8 @@ __export(api_exports, {
45
48
  createServerAPIClient: () => createServerAPIClient,
46
49
  farmApiPlugin: () => farmApiPlugin,
47
50
  invokeAPIRouteEndpoint: () => invokeAPIRouteEndpoint,
51
+ isAPIRouteRef: () => isAPIRouteRef,
52
+ isEndpointFailure: () => isEndpointFailure,
48
53
  isWebResponse: () => isWebResponse,
49
54
  matchAPIRoute: () => matchAPIRoute,
50
55
  normalizeRouteResponse: () => normalizeRouteResponse
@@ -53,197 +58,6 @@ module.exports = __toCommonJS(api_exports);
53
58
 
54
59
  // src/api/endpoint.ts
55
60
  var import_better_call = require("better-call");
56
- function createEndpoint(pathOrOptions, optionsOrHandler, maybeHandler) {
57
- let path4;
58
- let options;
59
- let handler;
60
- if (typeof pathOrOptions === "string") {
61
- path4 = pathOrOptions;
62
- options = optionsOrHandler;
63
- handler = maybeHandler;
64
- } else {
65
- path4 = "";
66
- options = pathOrOptions;
67
- handler = optionsOrHandler;
68
- }
69
- if (typeof handler !== "function") {
70
- throw new TypeError("createEndpoint requires a handler function");
71
- }
72
- const middleware = normalizeEndpointMiddleware(options.middleware);
73
- const wrappedHandler = /* @__PURE__ */ __name(((ctx) => runEndpointMiddleware(middleware, ctx, handler)), "wrappedHandler");
74
- const { middleware: _middleware, ...betterCallOptions } = options;
75
- const endpoint = (0, import_better_call.createEndpoint)(
76
- path4 || "/__farm_auto_path__",
77
- betterCallOptions,
78
- wrappedHandler
79
- );
80
- endpoint.__path = path4 || void 0;
81
- endpoint.__method = options.method || "GET";
82
- endpoint.__autoPath = !path4;
83
- endpoint.__handler = wrappedHandler;
84
- endpoint.__middleware = middleware;
85
- endpoint.__sourceHandler = handler;
86
- endpoint.__types = {
87
- body: options.body,
88
- query: options.query,
89
- headers: options.headers,
90
- response: null
91
- };
92
- return endpoint;
93
- }
94
- __name(createEndpoint, "createEndpoint");
95
- var EMPTY_ENDPOINT_MIDDLEWARE = Object.freeze([]);
96
- var EMPTY_ENDPOINT_CONTEXT = Object.freeze(/* @__PURE__ */ Object.create(null));
97
- var UNSAFE_ENDPOINT_CONTEXT_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
98
- function normalizeEndpointMiddleware(middleware) {
99
- if (middleware === void 0) return EMPTY_ENDPOINT_MIDDLEWARE;
100
- if (!Array.isArray(middleware)) {
101
- throw new TypeError("createEndpoint middleware must be an array of functions");
102
- }
103
- const normalized = [...middleware];
104
- for (const entry of normalized) {
105
- if (typeof entry !== "function") {
106
- throw new TypeError("createEndpoint middleware entries must be functions");
107
- }
108
- }
109
- return Object.freeze(normalized);
110
- }
111
- __name(normalizeEndpointMiddleware, "normalizeEndpointMiddleware");
112
- async function runEndpointMiddleware(middleware, handlerContext, handler) {
113
- let context = createInitialEndpointContext(handlerContext.context);
114
- for (let index = 0; index < middleware.length; index++) {
115
- const result = await middleware[index]({ ...handlerContext, context });
116
- if (isEndpointResponse(result)) return result;
117
- if (result === false) return forbiddenEndpointResponse();
118
- if (result === true) continue;
119
- if (!isPlainEndpointContext(result)) {
120
- throw new TypeError(
121
- `Endpoint middleware ${index + 1} must return an object, true, false, or a Response`
122
- );
123
- }
124
- context = mergeEndpointContext(context, result, index);
125
- }
126
- return handler({ ...handlerContext, context });
127
- }
128
- __name(runEndpointMiddleware, "runEndpointMiddleware");
129
- function createInitialEndpointContext(value) {
130
- if (value === void 0 || value === null) return EMPTY_ENDPOINT_CONTEXT;
131
- if (!isPlainEndpointContext(value)) {
132
- throw new TypeError("Endpoint context must be a plain object");
133
- }
134
- return mergeEndpointContext(EMPTY_ENDPOINT_CONTEXT, value);
135
- }
136
- __name(createInitialEndpointContext, "createInitialEndpointContext");
137
- function mergeEndpointContext(current, added, middlewareIndex) {
138
- const next = Object.assign(/* @__PURE__ */ Object.create(null), current);
139
- for (const key of Reflect.ownKeys(added)) {
140
- if (!Object.prototype.propertyIsEnumerable.call(added, key)) continue;
141
- if (typeof key === "string" && UNSAFE_ENDPOINT_CONTEXT_KEYS.has(key)) {
142
- throw new TypeError(`Endpoint middleware cannot provide the unsafe context key "${key}"`);
143
- }
144
- if (Object.prototype.hasOwnProperty.call(current, key)) {
145
- const source = middlewareIndex === void 0 ? "Endpoint context" : `Endpoint middleware ${middlewareIndex + 1}`;
146
- throw new TypeError(`${source} cannot replace the existing context key "${String(key)}"`);
147
- }
148
- next[key] = added[key];
149
- }
150
- return Object.freeze(next);
151
- }
152
- __name(mergeEndpointContext, "mergeEndpointContext");
153
- function isPlainEndpointContext(value) {
154
- if (!value || typeof value !== "object" || Array.isArray(value)) return false;
155
- const prototype = Object.getPrototypeOf(value);
156
- return prototype === Object.prototype || prototype === null;
157
- }
158
- __name(isPlainEndpointContext, "isPlainEndpointContext");
159
- function isEndpointResponse(value) {
160
- return value instanceof Response || typeof value === "object" && value !== null && "headers" in value && "status" in value && typeof value.arrayBuffer === "function";
161
- }
162
- __name(isEndpointResponse, "isEndpointResponse");
163
- function forbiddenEndpointResponse() {
164
- return new Response(JSON.stringify({ error: "Forbidden" }), {
165
- status: 403,
166
- headers: { "Content-Type": "application/json" }
167
- });
168
- }
169
- __name(forbiddenEndpointResponse, "forbiddenEndpointResponse");
170
- function GET(...args) {
171
- if (args.length === 1) {
172
- return createEndpoint("", { method: "GET" }, args[0]);
173
- }
174
- return createEndpoint("", { ...args[0], method: "GET" }, args[1]);
175
- }
176
- __name(GET, "GET");
177
- function HEAD(...args) {
178
- if (args.length === 1) {
179
- return createEndpoint("", { method: "HEAD" }, args[0]);
180
- }
181
- return createEndpoint("", { ...args[0], method: "HEAD" }, args[1]);
182
- }
183
- __name(HEAD, "HEAD");
184
- function POST(...args) {
185
- if (args.length === 1) {
186
- return createEndpoint("", { method: "POST" }, args[0]);
187
- }
188
- return createEndpoint("", { ...args[0], method: "POST" }, args[1]);
189
- }
190
- __name(POST, "POST");
191
- function PUT(...args) {
192
- if (args.length === 1) {
193
- return createEndpoint("", { method: "PUT" }, args[0]);
194
- }
195
- return createEndpoint("", { ...args[0], method: "PUT" }, args[1]);
196
- }
197
- __name(PUT, "PUT");
198
- function DELETE(...args) {
199
- if (args.length === 1) {
200
- return createEndpoint("", { method: "DELETE" }, args[0]);
201
- }
202
- return createEndpoint("", { ...args[0], method: "DELETE" }, args[1]);
203
- }
204
- __name(DELETE, "DELETE");
205
- function PATCH(...args) {
206
- if (args.length === 1) {
207
- return createEndpoint("", { method: "PATCH" }, args[0]);
208
- }
209
- return createEndpoint("", { ...args[0], method: "PATCH" }, args[1]);
210
- }
211
- __name(PATCH, "PATCH");
212
- function OPTIONS(...args) {
213
- if (args.length === 1) {
214
- return createEndpoint("", { method: "OPTIONS" }, args[0]);
215
- }
216
- return createEndpoint("", { ...args[0], method: "OPTIONS" }, args[1]);
217
- }
218
- __name(OPTIONS, "OPTIONS");
219
-
220
- // src/api/route-manager.ts
221
- var fs = __toESM(require("fs"));
222
- var path3 = __toESM(require("path"));
223
-
224
- // src/utils.ts
225
- var import_path = __toESM(require("path"));
226
- function toViteModuleId(filePath, root) {
227
- if (!import_path.default.isAbsolute(filePath)) return filePath;
228
- const relativePath = import_path.default.relative(root, filePath);
229
- if (relativePath && !relativePath.startsWith("..") && !import_path.default.isAbsolute(relativePath)) {
230
- return `/${relativePath.split(import_path.default.sep).join("/")}`;
231
- }
232
- const normalizedPath = filePath.replace(/\\/g, "/");
233
- return normalizedPath.startsWith("/") ? `/@fs${normalizedPath}` : `/@fs/${normalizedPath}`;
234
- }
235
- __name(toViteModuleId, "toViteModuleId");
236
- var logger = {
237
- info: /* @__PURE__ */ __name((message) => console.log(`[info] ${message}`), "info"),
238
- success: /* @__PURE__ */ __name((message) => console.log(`[success] ${message}`), "success"),
239
- warn: /* @__PURE__ */ __name((message) => console.warn(`\u26A0\uFE0F ${message}`), "warn"),
240
- error: /* @__PURE__ */ __name((message) => console.error(`\u274C ${message}`), "error"),
241
- ready: /* @__PURE__ */ __name((message) => console.log(`${message}`), "ready"),
242
- event: /* @__PURE__ */ __name((message) => console.log(` ${message}`), "event")
243
- };
244
-
245
- // src/routes.ts
246
- var import_react = require("react");
247
61
 
248
62
  // src/observability.ts
249
63
  var runtimeHandlers = /* @__PURE__ */ new Set();
@@ -361,6 +175,7 @@ function formatError(error) {
361
175
  __name(formatError, "formatError");
362
176
 
363
177
  // src/cache-invalidation.ts
178
+ var FARM_CACHE_INVALIDATION_HEADER = "x-farm-cache-invalidations";
364
179
  var FARM_CACHE_INVALIDATION_STATE = /* @__PURE__ */ Symbol.for("farm.cacheInvalidationState");
365
180
  var globalState = globalThis;
366
181
  function getFarmCacheInvalidationState() {
@@ -369,6 +184,42 @@ function getFarmCacheInvalidationState() {
369
184
  });
370
185
  }
371
186
  __name(getFarmCacheInvalidationState, "getFarmCacheInvalidationState");
187
+ function notifyFarmCacheInvalidation(key) {
188
+ if (typeof key !== "string" || key.length === 0) return;
189
+ for (const listener of getFarmCacheInvalidationState().listeners) {
190
+ listener(key);
191
+ }
192
+ }
193
+ __name(notifyFarmCacheInvalidation, "notifyFarmCacheInvalidation");
194
+ function applyFarmCacheInvalidations(keys) {
195
+ if (!Array.isArray(keys)) return;
196
+ for (const key of keys) {
197
+ if (typeof key === "string") {
198
+ notifyFarmCacheInvalidation(key);
199
+ }
200
+ }
201
+ }
202
+ __name(applyFarmCacheInvalidations, "applyFarmCacheInvalidations");
203
+ function encodeFarmCacheInvalidations(keys) {
204
+ const normalized = Array.from(
205
+ new Set(keys.filter((key) => typeof key === "string" && key.length > 0))
206
+ );
207
+ if (normalized.length === 0) return null;
208
+ return encodeURIComponent(JSON.stringify(normalized));
209
+ }
210
+ __name(encodeFarmCacheInvalidations, "encodeFarmCacheInvalidations");
211
+ function decodeFarmCacheInvalidations(value) {
212
+ if (!value) return [];
213
+ try {
214
+ const parsed = JSON.parse(decodeURIComponent(value));
215
+ return Array.isArray(parsed) ? Array.from(
216
+ new Set(parsed.filter((key) => typeof key === "string" && key.length > 0))
217
+ ) : [];
218
+ } catch {
219
+ return [];
220
+ }
221
+ }
222
+ __name(decodeFarmCacheInvalidations, "decodeFarmCacheInvalidations");
372
223
  function subscribeFarmCacheInvalidation(listener) {
373
224
  const state = getFarmCacheInvalidationState();
374
225
  state.listeners.add(listener);
@@ -561,10 +412,28 @@ var farmDataCacheGlobal = globalThis;
561
412
  var sharedFarmDataCache = farmDataCacheGlobal[FARM_DATA_CACHE_SYMBOL] ?? (farmDataCacheGlobal[FARM_DATA_CACHE_SYMBOL] = new FarmDataCache());
562
413
  var functionIds = /* @__PURE__ */ new WeakMap();
563
414
  var nextFunctionId = 0;
415
+ function getFarmDataCache() {
416
+ return sharedFarmDataCache;
417
+ }
418
+ __name(getFarmDataCache, "getFarmDataCache");
419
+ function revalidatePath(routePath) {
420
+ getFarmDataCache().revalidatePath(routePath);
421
+ }
422
+ __name(revalidatePath, "revalidatePath");
423
+ function invalidate(key) {
424
+ const clientKey = createRouteDataCacheKey(key);
425
+ getFarmDataCache().revalidateTag(createRouteDataCacheTag(key), { source: "updateTag" });
426
+ notifyFarmCacheInvalidation(clientKey);
427
+ }
428
+ __name(invalidate, "invalidate");
564
429
  function createPathCacheTag(routePath) {
565
430
  return `path:${normalizeRevalidatePath(routePath)}`;
566
431
  }
567
432
  __name(createPathCacheTag, "createPathCacheTag");
433
+ function createRouteDataCacheTag(key) {
434
+ return `route-data:${createRouteDataCacheKey(key)}`;
435
+ }
436
+ __name(createRouteDataCacheTag, "createRouteDataCacheTag");
568
437
  function createRouteDataCacheKey(key) {
569
438
  return createFarmCacheKey(Array.isArray(key) ? key : [key]);
570
439
  }
@@ -671,6 +540,341 @@ function stableSerialize(value, seen = /* @__PURE__ */ new WeakSet()) {
671
540
  }
672
541
  __name(stableSerialize, "stableSerialize");
673
542
 
543
+ // src/api/endpoint.ts
544
+ var _EndpointFailure = class _EndpointFailure extends Error {
545
+ constructor(code, data, options) {
546
+ super(options.message);
547
+ this.name = "EndpointFailure";
548
+ this.code = code;
549
+ this.data = data;
550
+ this.status = options.status;
551
+ }
552
+ };
553
+ __name(_EndpointFailure, "EndpointFailure");
554
+ var EndpointFailure = _EndpointFailure;
555
+ function isEndpointFailure(value) {
556
+ return value instanceof EndpointFailure;
557
+ }
558
+ __name(isEndpointFailure, "isEndpointFailure");
559
+ function createEndpoint(pathOrOptions, optionsOrHandler, maybeHandler) {
560
+ let path4;
561
+ let options;
562
+ let handler;
563
+ if (typeof pathOrOptions === "string") {
564
+ path4 = pathOrOptions;
565
+ options = optionsOrHandler;
566
+ handler = maybeHandler;
567
+ } else {
568
+ path4 = "";
569
+ options = pathOrOptions;
570
+ handler = optionsOrHandler;
571
+ }
572
+ if (typeof handler !== "function") {
573
+ throw new TypeError("createEndpoint requires a handler function");
574
+ }
575
+ const middleware = normalizeEndpointMiddleware(options.middleware);
576
+ const errors = normalizeEndpointErrors(options.errors);
577
+ const fail = createEndpointFail(errors);
578
+ const wrappedHandler = /* @__PURE__ */ __name((async (ctx) => {
579
+ const execution = await runEndpointMiddleware(
580
+ middleware,
581
+ ctx,
582
+ handler,
583
+ fail,
584
+ options.invalidates
585
+ );
586
+ return execution.result;
587
+ }), "wrappedHandler");
588
+ const {
589
+ middleware: _middleware,
590
+ errors: _errors,
591
+ invalidates: _invalidates,
592
+ ...betterCallOptions
593
+ } = options;
594
+ const endpoint = (0, import_better_call.createEndpoint)(
595
+ path4 || "/__farm_auto_path__",
596
+ betterCallOptions,
597
+ wrappedHandler
598
+ );
599
+ endpoint.__path = path4 || void 0;
600
+ endpoint.__method = options.method || "GET";
601
+ endpoint.__autoPath = !path4;
602
+ endpoint.__handler = wrappedHandler;
603
+ endpoint.__farmInvoke = (ctx) => runEndpointMiddleware(middleware, ctx, handler, fail, options.invalidates);
604
+ endpoint.__middleware = middleware;
605
+ endpoint.__sourceHandler = handler;
606
+ endpoint.__invalidates = options.invalidates;
607
+ endpoint.__errors = errors;
608
+ endpoint.__types = {
609
+ body: options.body,
610
+ query: options.query,
611
+ headers: options.headers,
612
+ response: null,
613
+ errors
614
+ };
615
+ return endpoint;
616
+ }
617
+ __name(createEndpoint, "createEndpoint");
618
+ var EMPTY_ENDPOINT_MIDDLEWARE = Object.freeze([]);
619
+ var EMPTY_ENDPOINT_CONTEXT = Object.freeze(/* @__PURE__ */ Object.create(null));
620
+ var UNSAFE_ENDPOINT_CONTEXT_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
621
+ function normalizeEndpointErrors(definitions) {
622
+ if (definitions === void 0) return Object.freeze({});
623
+ if (!isPlainEndpointContext(definitions)) {
624
+ throw new TypeError("createEndpoint errors must be an object");
625
+ }
626
+ const normalized = /* @__PURE__ */ Object.create(null);
627
+ for (const [code, definition] of Object.entries(definitions)) {
628
+ if (!code.trim()) {
629
+ throw new TypeError("Endpoint error codes cannot be empty");
630
+ }
631
+ if (!definition || typeof definition !== "object") {
632
+ throw new TypeError(`Endpoint error "${code}" must be an object`);
633
+ }
634
+ if (!Number.isInteger(definition.status) || definition.status < 400 || definition.status > 599) {
635
+ throw new TypeError(`Endpoint error "${code}" status must be an integer between 400 and 599`);
636
+ }
637
+ if (!definition.schema || typeof definition.schema.parse !== "function") {
638
+ throw new TypeError(`Endpoint error "${code}" requires a schema with parse()`);
639
+ }
640
+ if (definition.message !== void 0 && typeof definition.message !== "string") {
641
+ throw new TypeError(`Endpoint error "${code}" message must be a string`);
642
+ }
643
+ normalized[code] = Object.freeze({ ...definition });
644
+ }
645
+ return Object.freeze(normalized);
646
+ }
647
+ __name(normalizeEndpointErrors, "normalizeEndpointErrors");
648
+ function createEndpointFail(definitions) {
649
+ return ((code, data) => {
650
+ const definition = definitions[code];
651
+ if (!definition) {
652
+ throw new TypeError(`Endpoint error "${code}" is not declared`);
653
+ }
654
+ const parsed = definition.schema.parse(data);
655
+ throw new EndpointFailure(code, parsed, {
656
+ status: definition.status,
657
+ message: definition.message ?? "Request failed"
658
+ });
659
+ });
660
+ }
661
+ __name(createEndpointFail, "createEndpointFail");
662
+ function normalizeEndpointMiddleware(middleware) {
663
+ if (middleware === void 0) return EMPTY_ENDPOINT_MIDDLEWARE;
664
+ if (!Array.isArray(middleware)) {
665
+ throw new TypeError("createEndpoint middleware must be an array of functions");
666
+ }
667
+ const normalized = [...middleware];
668
+ for (const entry of normalized) {
669
+ if (typeof entry !== "function") {
670
+ throw new TypeError("createEndpoint middleware entries must be functions");
671
+ }
672
+ }
673
+ return Object.freeze(normalized);
674
+ }
675
+ __name(normalizeEndpointMiddleware, "normalizeEndpointMiddleware");
676
+ async function runEndpointMiddleware(middleware, handlerContext, handler, fail, invalidations) {
677
+ let context = createInitialEndpointContext(handlerContext.context);
678
+ for (let index = 0; index < middleware.length; index++) {
679
+ const result2 = await middleware[index]({ ...handlerContext, context });
680
+ if (isEndpointResponse(result2)) {
681
+ return {
682
+ result: result2,
683
+ context,
684
+ handlerExecuted: false,
685
+ invalidations: []
686
+ };
687
+ }
688
+ if (result2 === false) {
689
+ return {
690
+ result: forbiddenEndpointResponse(),
691
+ context,
692
+ handlerExecuted: false,
693
+ invalidations: []
694
+ };
695
+ }
696
+ if (result2 === true) continue;
697
+ if (!isPlainEndpointContext(result2)) {
698
+ throw new TypeError(
699
+ `Endpoint middleware ${index + 1} must return an object, true, false, or a Response`
700
+ );
701
+ }
702
+ context = mergeEndpointContext(context, result2, index);
703
+ }
704
+ const result = await handler({ ...handlerContext, context, fail });
705
+ return {
706
+ result,
707
+ context,
708
+ handlerExecuted: true,
709
+ invalidations: await applyEndpointInvalidations(
710
+ invalidations,
711
+ {
712
+ ...handlerContext,
713
+ context,
714
+ result
715
+ },
716
+ result
717
+ )
718
+ };
719
+ }
720
+ __name(runEndpointMiddleware, "runEndpointMiddleware");
721
+ async function applyEndpointInvalidations(declaration, context, result) {
722
+ if (!declaration || isEndpointResponse(result) && result.status >= 400) {
723
+ return [];
724
+ }
725
+ const targets = typeof declaration === "function" ? await declaration(context) : declaration;
726
+ if (!Array.isArray(targets)) {
727
+ throw new TypeError(
728
+ "Endpoint invalidates must resolve to an array of { key } or { path } targets"
729
+ );
730
+ }
731
+ const clientKeys = [];
732
+ for (const target of targets) {
733
+ assertEndpointInvalidationTarget(target);
734
+ if ("key" in target) {
735
+ invalidate(target.key);
736
+ clientKeys.push(createRouteDataCacheKey(target.key));
737
+ } else {
738
+ revalidatePath(target.path);
739
+ }
740
+ }
741
+ return Array.from(new Set(clientKeys));
742
+ }
743
+ __name(applyEndpointInvalidations, "applyEndpointInvalidations");
744
+ function assertEndpointInvalidationTarget(target) {
745
+ if (!target || typeof target !== "object") {
746
+ throw new TypeError("Endpoint invalidation targets must be { key } or { path } objects");
747
+ }
748
+ if ("key" in target) {
749
+ const key = target.key;
750
+ if (typeof key === "string" || Array.isArray(key)) return;
751
+ } else if ("path" in target && typeof target.path === "string") {
752
+ return;
753
+ }
754
+ throw new TypeError(
755
+ "Endpoint invalidation targets must contain a string/array key or a path string"
756
+ );
757
+ }
758
+ __name(assertEndpointInvalidationTarget, "assertEndpointInvalidationTarget");
759
+ function createInitialEndpointContext(value) {
760
+ if (value === void 0 || value === null) return EMPTY_ENDPOINT_CONTEXT;
761
+ if (!isPlainEndpointContext(value)) {
762
+ throw new TypeError("Endpoint context must be a plain object");
763
+ }
764
+ return mergeEndpointContext(EMPTY_ENDPOINT_CONTEXT, value);
765
+ }
766
+ __name(createInitialEndpointContext, "createInitialEndpointContext");
767
+ function mergeEndpointContext(current, added, middlewareIndex) {
768
+ const next = Object.assign(/* @__PURE__ */ Object.create(null), current);
769
+ for (const key of Reflect.ownKeys(added)) {
770
+ if (!Object.prototype.propertyIsEnumerable.call(added, key)) continue;
771
+ if (typeof key === "string" && UNSAFE_ENDPOINT_CONTEXT_KEYS.has(key)) {
772
+ throw new TypeError(`Endpoint middleware cannot provide the unsafe context key "${key}"`);
773
+ }
774
+ if (Object.prototype.hasOwnProperty.call(current, key)) {
775
+ const source = middlewareIndex === void 0 ? "Endpoint context" : `Endpoint middleware ${middlewareIndex + 1}`;
776
+ throw new TypeError(`${source} cannot replace the existing context key "${String(key)}"`);
777
+ }
778
+ next[key] = added[key];
779
+ }
780
+ return Object.freeze(next);
781
+ }
782
+ __name(mergeEndpointContext, "mergeEndpointContext");
783
+ function isPlainEndpointContext(value) {
784
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
785
+ const prototype = Object.getPrototypeOf(value);
786
+ return prototype === Object.prototype || prototype === null;
787
+ }
788
+ __name(isPlainEndpointContext, "isPlainEndpointContext");
789
+ function isEndpointResponse(value) {
790
+ return value instanceof Response || typeof value === "object" && value !== null && "headers" in value && "status" in value && typeof value.arrayBuffer === "function";
791
+ }
792
+ __name(isEndpointResponse, "isEndpointResponse");
793
+ function forbiddenEndpointResponse() {
794
+ return new Response(JSON.stringify({ error: "Forbidden" }), {
795
+ status: 403,
796
+ headers: { "Content-Type": "application/json" }
797
+ });
798
+ }
799
+ __name(forbiddenEndpointResponse, "forbiddenEndpointResponse");
800
+ function GET(...args) {
801
+ if (args.length === 1) {
802
+ return createEndpoint("", { method: "GET" }, args[0]);
803
+ }
804
+ return createEndpoint("", { ...args[0], method: "GET" }, args[1]);
805
+ }
806
+ __name(GET, "GET");
807
+ function HEAD(...args) {
808
+ if (args.length === 1) {
809
+ return createEndpoint("", { method: "HEAD" }, args[0]);
810
+ }
811
+ return createEndpoint("", { ...args[0], method: "HEAD" }, args[1]);
812
+ }
813
+ __name(HEAD, "HEAD");
814
+ function POST(...args) {
815
+ if (args.length === 1) {
816
+ return createEndpoint("", { method: "POST" }, args[0]);
817
+ }
818
+ return createEndpoint("", { ...args[0], method: "POST" }, args[1]);
819
+ }
820
+ __name(POST, "POST");
821
+ function PUT(...args) {
822
+ if (args.length === 1) {
823
+ return createEndpoint("", { method: "PUT" }, args[0]);
824
+ }
825
+ return createEndpoint("", { ...args[0], method: "PUT" }, args[1]);
826
+ }
827
+ __name(PUT, "PUT");
828
+ function DELETE(...args) {
829
+ if (args.length === 1) {
830
+ return createEndpoint("", { method: "DELETE" }, args[0]);
831
+ }
832
+ return createEndpoint("", { ...args[0], method: "DELETE" }, args[1]);
833
+ }
834
+ __name(DELETE, "DELETE");
835
+ function PATCH(...args) {
836
+ if (args.length === 1) {
837
+ return createEndpoint("", { method: "PATCH" }, args[0]);
838
+ }
839
+ return createEndpoint("", { ...args[0], method: "PATCH" }, args[1]);
840
+ }
841
+ __name(PATCH, "PATCH");
842
+ function OPTIONS(...args) {
843
+ if (args.length === 1) {
844
+ return createEndpoint("", { method: "OPTIONS" }, args[0]);
845
+ }
846
+ return createEndpoint("", { ...args[0], method: "OPTIONS" }, args[1]);
847
+ }
848
+ __name(OPTIONS, "OPTIONS");
849
+
850
+ // src/api/route-manager.ts
851
+ var fs = __toESM(require("fs"));
852
+ var path3 = __toESM(require("path"));
853
+
854
+ // src/utils.ts
855
+ var import_path = __toESM(require("path"));
856
+ function toViteModuleId(filePath, root) {
857
+ if (!import_path.default.isAbsolute(filePath)) return filePath;
858
+ const relativePath = import_path.default.relative(root, filePath);
859
+ if (relativePath && !relativePath.startsWith("..") && !import_path.default.isAbsolute(relativePath)) {
860
+ return `/${relativePath.split(import_path.default.sep).join("/")}`;
861
+ }
862
+ const normalizedPath = filePath.replace(/\\/g, "/");
863
+ return normalizedPath.startsWith("/") ? `/@fs${normalizedPath}` : `/@fs/${normalizedPath}`;
864
+ }
865
+ __name(toViteModuleId, "toViteModuleId");
866
+ var logger = {
867
+ info: /* @__PURE__ */ __name((message) => console.log(`[info] ${message}`), "info"),
868
+ success: /* @__PURE__ */ __name((message) => console.log(`[success] ${message}`), "success"),
869
+ warn: /* @__PURE__ */ __name((message) => console.warn(`\u26A0\uFE0F ${message}`), "warn"),
870
+ error: /* @__PURE__ */ __name((message) => console.error(`\u274C ${message}`), "error"),
871
+ ready: /* @__PURE__ */ __name((message) => console.log(`${message}`), "ready"),
872
+ event: /* @__PURE__ */ __name((message) => console.log(` ${message}`), "event")
873
+ };
874
+
875
+ // src/routes.ts
876
+ var import_react = require("react");
877
+
674
878
  // src/route-runtime.ts
675
879
  function normalizeFarmRouteRuntimeConfig(value, source = "Route configuration") {
676
880
  if (!value) return {};
@@ -1032,10 +1236,10 @@ __name(invokeAPIRouteEndpoint, "invokeAPIRouteEndpoint");
1032
1236
  async function invokeAPIRouteEndpointInContext(endpoint, request, params) {
1033
1237
  const farmHandler = endpoint.__handler || (isFarmContextHandler(endpoint) ? endpoint : null);
1034
1238
  if (!farmHandler) {
1035
- const result2 = await endpoint(request, {
1239
+ const result = await endpoint(request, {
1036
1240
  params: Promise.resolve(params)
1037
1241
  });
1038
- return normalizeRouteResponse(result2);
1242
+ return normalizeRouteResponse(result);
1039
1243
  }
1040
1244
  const url = new URL(request.url);
1041
1245
  const query = {};
@@ -1060,15 +1264,30 @@ async function invokeAPIRouteEndpointInContext(endpoint, request, params) {
1060
1264
  if (headersValidation instanceof Response) {
1061
1265
  return headersValidation;
1062
1266
  }
1063
- const result = await farmHandler({
1267
+ const handlerContext = {
1064
1268
  query: queryValidation,
1065
1269
  body: bodyValidation,
1066
1270
  headers: headersValidation,
1067
1271
  request,
1068
1272
  context: {},
1069
1273
  params
1070
- });
1071
- return normalizeRouteResponse(result);
1274
+ };
1275
+ let execution;
1276
+ try {
1277
+ execution = typeof endpoint.__farmInvoke === "function" ? await endpoint.__farmInvoke(handlerContext) : {
1278
+ result: await farmHandler(handlerContext),
1279
+ context: handlerContext.context,
1280
+ handlerExecuted: true,
1281
+ invalidations: []
1282
+ };
1283
+ } catch (error) {
1284
+ if (isEndpointFailure(error)) {
1285
+ return createEndpointFailureResponse(error);
1286
+ }
1287
+ throw error;
1288
+ }
1289
+ const response = normalizeRouteResponse(execution.result);
1290
+ return attachEndpointInvalidations(response, execution.invalidations);
1072
1291
  }
1073
1292
  __name(invokeAPIRouteEndpointInContext, "invokeAPIRouteEndpointInContext");
1074
1293
  function normalizeRouteResponse(result) {
@@ -1088,6 +1307,40 @@ function isWebResponse(value) {
1088
1307
  return value instanceof Response || typeof value === "object" && value !== null && "headers" in value && "status" in value && typeof value.arrayBuffer === "function";
1089
1308
  }
1090
1309
  __name(isWebResponse, "isWebResponse");
1310
+ function attachEndpointInvalidations(response, keys) {
1311
+ const existing = decodeFarmCacheInvalidations(
1312
+ response.headers.get(FARM_CACHE_INVALIDATION_HEADER)
1313
+ );
1314
+ const encoded = encodeFarmCacheInvalidations([...existing, ...keys]);
1315
+ if (!encoded) return response;
1316
+ const headers = new Headers(response.headers);
1317
+ headers.set(FARM_CACHE_INVALIDATION_HEADER, encoded);
1318
+ return new Response(response.body, {
1319
+ status: response.status,
1320
+ statusText: response.statusText,
1321
+ headers
1322
+ });
1323
+ }
1324
+ __name(attachEndpointInvalidations, "attachEndpointInvalidations");
1325
+ function createEndpointFailureResponse(failure) {
1326
+ return new Response(
1327
+ JSON.stringify({
1328
+ error: {
1329
+ code: failure.code,
1330
+ message: failure.message,
1331
+ data: failure.data
1332
+ }
1333
+ }),
1334
+ {
1335
+ status: failure.status,
1336
+ headers: {
1337
+ "cache-control": "no-store",
1338
+ "content-type": "application/json"
1339
+ }
1340
+ }
1341
+ );
1342
+ }
1343
+ __name(createEndpointFailureResponse, "createEndpointFailureResponse");
1091
1344
  function isFarmContextHandler(endpoint) {
1092
1345
  if (typeof endpoint !== "function") {
1093
1346
  return false;
@@ -1569,7 +1822,7 @@ function mergeIntegrationClientData(...values) {
1569
1822
  continue;
1570
1823
  }
1571
1824
  merged = {
1572
- ...merged || {},
1825
+ ...merged,
1573
1826
  ...data
1574
1827
  };
1575
1828
  }
@@ -2220,6 +2473,19 @@ function normalizeFarmClientCacheKey(key) {
2220
2473
  __name(normalizeFarmClientCacheKey, "normalizeFarmClientCacheKey");
2221
2474
 
2222
2475
  // src/api/client.ts
2476
+ var FARM_API_ROUTE_REF_SYMBOL = /* @__PURE__ */ Symbol.for("farm.api.route-ref");
2477
+ var _APIClientError = class _APIClientError extends Error {
2478
+ constructor(code, data, options) {
2479
+ super(options.message);
2480
+ this.name = "APIClientError";
2481
+ this.code = code;
2482
+ this.data = data;
2483
+ this.status = options.status;
2484
+ this.response = options.response;
2485
+ }
2486
+ };
2487
+ __name(_APIClientError, "APIClientError");
2488
+ var APIClientError = _APIClientError;
2223
2489
  function createAPIClient(options = {}) {
2224
2490
  options ?? (options = {});
2225
2491
  const baseURL = options.baseURL || (typeof window !== "undefined" ? window.location.origin : "http://localhost:3000");
@@ -2257,6 +2523,9 @@ function createAPIClient(options = {}) {
2257
2523
  fetchOptions.body = JSON.stringify(requestOptions.body);
2258
2524
  }
2259
2525
  const response = await fetch(url.toString(), fetchOptions);
2526
+ applyFarmCacheInvalidations(
2527
+ decodeFarmCacheInvalidations(response.headers?.get?.(FARM_CACHE_INVALIDATION_HEADER))
2528
+ );
2260
2529
  let data = void 0;
2261
2530
  if (response.status !== 204 && response.status !== 205) {
2262
2531
  data = await response.json();
@@ -2496,9 +2765,15 @@ function createNestedProxy(path4, client, routeMeta, baseURL, rootAliases) {
2496
2765
  const proxy = new Proxy(target, {
2497
2766
  // When accessing a property (api.hello)
2498
2767
  get(_target, prop) {
2768
+ if (prop === FARM_API_ROUTE_REF_SYMBOL) {
2769
+ return path4.length > 0;
2770
+ }
2499
2771
  if (path4.length === 0 && typeof prop === "string" && rootAliases && prop in rootAliases) {
2500
2772
  return rootAliases[prop];
2501
2773
  }
2774
+ if (typeof prop !== "string") {
2775
+ return Reflect.get(_target, prop);
2776
+ }
2502
2777
  return createNestedProxy([...path4, prop], client, routeMeta, baseURL, rootAliases);
2503
2778
  },
2504
2779
  // When calling as a function
@@ -2521,6 +2796,10 @@ function createNestedProxy(path4, client, routeMeta, baseURL, rootAliases) {
2521
2796
  return proxy;
2522
2797
  }
2523
2798
  __name(createNestedProxy, "createNestedProxy");
2799
+ function isAPIRouteRef(value) {
2800
+ return typeof value === "function" && value[FARM_API_ROUTE_REF_SYMBOL] === true;
2801
+ }
2802
+ __name(isAPIRouteRef, "isAPIRouteRef");
2524
2803
  function createServerAPIClient(endpoints, options = {}) {
2525
2804
  if (options.integrations === false || Object.prototype.hasOwnProperty.call(endpoints, "integrations")) {
2526
2805
  return endpoints;
@@ -2587,7 +2866,10 @@ function resolveTargetKey(routeMeta, target, input, baseURL = "http://localhost:
2587
2866
  }
2588
2867
  if (Array.isArray(target)) {
2589
2868
  const [route, routeInput] = target;
2590
- return resolveTargetKey(routeMeta, route, routeInput, baseURL);
2869
+ if (typeof route === "function") {
2870
+ return resolveTargetKey(routeMeta, route, routeInput, baseURL);
2871
+ }
2872
+ return normalizeFarmClientCacheKey(target);
2591
2873
  }
2592
2874
  if ("key" in target) return normalizeFarmClientCacheKey(target.key);
2593
2875
  if ("path" in target) {
@@ -2613,18 +2895,45 @@ function resolveRouteMeta(meta) {
2613
2895
  }
2614
2896
  __name(resolveRouteMeta, "resolveRouteMeta");
2615
2897
  function normalizeError(error) {
2616
- if (error instanceof Error) return error;
2617
- return new Error(typeof error === "string" ? error : "Unknown error");
2898
+ if (error instanceof APIClientError) return error;
2899
+ const normalized = new APIClientError("network_error", void 0, {
2900
+ status: 0,
2901
+ message: error instanceof Error ? error.message : typeof error === "string" ? error : "Network request failed"
2902
+ });
2903
+ normalized.cause = error;
2904
+ return normalized;
2618
2905
  }
2619
2906
  __name(normalizeError, "normalizeError");
2620
2907
  function createResponseError2(response, data) {
2621
- const error = new Error(`HTTP ${response.status}: ${response.statusText}`);
2622
- error.status = response.status;
2623
- error.response = response;
2624
- error.data = data;
2625
- return error;
2908
+ const expected = readEndpointErrorEnvelope(data);
2909
+ if (expected) {
2910
+ return new APIClientError(expected.code, expected.data, {
2911
+ status: response.status,
2912
+ message: expected.message,
2913
+ response
2914
+ });
2915
+ }
2916
+ return new APIClientError("http_error", data, {
2917
+ status: response.status,
2918
+ message: `HTTP ${response.status}: ${response.statusText}`,
2919
+ response
2920
+ });
2626
2921
  }
2627
2922
  __name(createResponseError2, "createResponseError");
2923
+ function readEndpointErrorEnvelope(data) {
2924
+ if (!data || typeof data !== "object") return null;
2925
+ const error = data.error;
2926
+ if (!error || typeof error !== "object") return null;
2927
+ const code = error.code;
2928
+ const message = error.message;
2929
+ if (typeof code !== "string" || typeof message !== "string") return null;
2930
+ return {
2931
+ code,
2932
+ message,
2933
+ data: error.data
2934
+ };
2935
+ }
2936
+ __name(readEndpointErrorEnvelope, "readEndpointErrorEnvelope");
2628
2937
 
2629
2938
  // src/server/response.ts
2630
2939
  var import_node_events = require("events");
@@ -2996,69 +3305,71 @@ function farmApiPlugin(options = {}) {
2996
3305
  waitForDiscovery: /* @__PURE__ */ __name(() => discoveryPromise, "waitForDiscovery")
2997
3306
  };
2998
3307
  return () => {
2999
- server.middlewares.use(_withAfterNodeMiddleware(async (req, res, next) => {
3000
- const url = req.url || "/";
3001
- const pathname = url.split("?")[0];
3002
- const method = req.method || "GET";
3003
- if (discoveryPromise && !discoveryComplete) {
3004
- await discoveryPromise;
3005
- }
3006
- if (!matchAPIRoute(apiRoutesCache, pathname)) {
3007
- return next();
3008
- }
3009
- if (!apiRouterHandler) {
3010
- return next();
3011
- }
3012
- const startTime = Date.now();
3013
- try {
3014
- const farmMiddleware = server.__farmMiddleware__;
3015
- if (farmMiddleware) {
3016
- await farmMiddleware.waitForDiscovery?.();
3017
- const middlewareData = /* @__PURE__ */ new Map();
3018
- const handled = await farmMiddleware.execute(req, res, pathname, middlewareData);
3019
- if (handled) {
3020
- const duration2 = Date.now() - startTime;
3021
- logResponse(method, pathname, res.statusCode || 200, duration2);
3022
- return;
3023
- }
3308
+ server.middlewares.use(
3309
+ _withAfterNodeMiddleware(async (req, res, next) => {
3310
+ const url = req.url || "/";
3311
+ const pathname = url.split("?")[0];
3312
+ const method = req.method || "GET";
3313
+ if (discoveryPromise && !discoveryComplete) {
3314
+ await discoveryPromise;
3024
3315
  }
3025
- const fullUrl = `http://${req.headers.host || "localhost:3000"}${url}`;
3026
- const headers = new Headers();
3027
- for (const [key, value] of Object.entries(req.headers)) {
3028
- if (value) {
3029
- headers.set(key, Array.isArray(value) ? value.join(", ") : value);
3030
- }
3316
+ if (!matchAPIRoute(apiRoutesCache, pathname)) {
3317
+ return next();
3031
3318
  }
3032
- let body;
3033
- if (method !== "GET" && method !== "HEAD") {
3034
- body = await new Promise((resolve) => {
3035
- let data = "";
3036
- req.on("data", (chunk) => {
3037
- data += chunk;
3038
- });
3039
- req.on("end", () => {
3040
- resolve(data);
3319
+ if (!apiRouterHandler) {
3320
+ return next();
3321
+ }
3322
+ const startTime = Date.now();
3323
+ try {
3324
+ const farmMiddleware = server.__farmMiddleware__;
3325
+ if (farmMiddleware) {
3326
+ await farmMiddleware.waitForDiscovery?.();
3327
+ const middlewareData = /* @__PURE__ */ new Map();
3328
+ const handled = await farmMiddleware.execute(req, res, pathname, middlewareData);
3329
+ if (handled) {
3330
+ const duration2 = Date.now() - startTime;
3331
+ logResponse(method, pathname, res.statusCode || 200, duration2);
3332
+ return;
3333
+ }
3334
+ }
3335
+ const fullUrl = `http://${req.headers.host || "localhost:3000"}${url}`;
3336
+ const headers = new Headers();
3337
+ for (const [key, value] of Object.entries(req.headers)) {
3338
+ if (value) {
3339
+ headers.set(key, Array.isArray(value) ? value.join(", ") : value);
3340
+ }
3341
+ }
3342
+ let body;
3343
+ if (method !== "GET" && method !== "HEAD") {
3344
+ body = await new Promise((resolve) => {
3345
+ let data = "";
3346
+ req.on("data", (chunk) => {
3347
+ data += chunk;
3348
+ });
3349
+ req.on("end", () => {
3350
+ resolve(data);
3351
+ });
3041
3352
  });
3353
+ }
3354
+ const request = new Request(fullUrl, {
3355
+ method,
3356
+ headers,
3357
+ body: body || void 0
3042
3358
  });
3359
+ const response = await apiRouterHandler(request);
3360
+ const duration = Date.now() - startTime;
3361
+ logResponse(method, pathname, response.status, duration);
3362
+ await sendWebResponse(res, response);
3363
+ } catch (error) {
3364
+ const duration = Date.now() - startTime;
3365
+ logResponse(method, pathname, 500, duration);
3366
+ console.error("[FARM] API error:", error);
3367
+ res.statusCode = 500;
3368
+ res.setHeader("Content-Type", "application/json");
3369
+ res.end(JSON.stringify({ error: "Internal server error" }));
3043
3370
  }
3044
- const request = new Request(fullUrl, {
3045
- method,
3046
- headers,
3047
- body: body || void 0
3048
- });
3049
- const response = await apiRouterHandler(request);
3050
- const duration = Date.now() - startTime;
3051
- logResponse(method, pathname, response.status, duration);
3052
- await sendWebResponse(res, response);
3053
- } catch (error) {
3054
- const duration = Date.now() - startTime;
3055
- logResponse(method, pathname, 500, duration);
3056
- console.error("[FARM] API error:", error);
3057
- res.statusCode = 500;
3058
- res.setHeader("Content-Type", "application/json");
3059
- res.end(JSON.stringify({ error: "Internal server error" }));
3060
- }
3061
- }));
3371
+ })
3372
+ );
3062
3373
  };
3063
3374
  },
3064
3375
  async handleHotUpdate({ file, server, modules }) {
@@ -3178,9 +3489,12 @@ function farmApiPlugin(options = {}) {
3178
3489
  __name(farmApiPlugin, "farmApiPlugin");
3179
3490
  // Annotate the CommonJS export names for ESM import in node:
3180
3491
  0 && (module.exports = {
3492
+ APIClientError,
3181
3493
  APIRouteManager,
3182
3494
  API_ROUTE_METHODS,
3183
3495
  DELETE,
3496
+ EndpointFailure,
3497
+ FARM_API_ROUTE_REF_SYMBOL,
3184
3498
  GET,
3185
3499
  HEAD,
3186
3500
  OPTIONS,
@@ -3192,6 +3506,8 @@ __name(farmApiPlugin, "farmApiPlugin");
3192
3506
  createServerAPIClient,
3193
3507
  farmApiPlugin,
3194
3508
  invokeAPIRouteEndpoint,
3509
+ isAPIRouteRef,
3510
+ isEndpointFailure,
3195
3511
  isWebResponse,
3196
3512
  matchAPIRoute,
3197
3513
  normalizeRouteResponse