@farm.js/core 0.1.0-beta.1 → 0.1.0-beta.4

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 (254) hide show
  1. package/README.md +1 -1
  2. package/dist/agent-runtime.d.mts +2 -1
  3. package/dist/agent-runtime.d.ts +2 -1
  4. package/dist/api/route-manager.cjs +410 -15
  5. package/dist/api/route-manager.cjs.map +1 -1
  6. package/dist/api/route-manager.d.mts +4 -2
  7. package/dist/api/route-manager.d.ts +4 -2
  8. package/dist/api/route-manager.mjs +9 -8
  9. package/dist/api/runtime.cjs +748 -9
  10. package/dist/api/runtime.cjs.map +1 -1
  11. package/dist/api/runtime.d.mts +3 -16
  12. package/dist/api/runtime.d.ts +3 -16
  13. package/dist/api/runtime.mjs +8 -1
  14. package/dist/api.cjs +1243 -342
  15. package/dist/api.cjs.map +1 -1
  16. package/dist/api.d.mts +5 -147
  17. package/dist/api.d.ts +5 -147
  18. package/dist/api.mjs +51 -21
  19. package/dist/{app-CFRNJXP1.d.ts → app-BjN-da13.d.ts} +38 -3
  20. package/dist/{app-BiX4qb-d.d.mts → app-CakAr8Be.d.mts} +38 -3
  21. package/dist/app-markdown.cjs +1 -1
  22. package/dist/app-markdown.cjs.map +1 -1
  23. package/dist/app-markdown.d.mts +2 -1
  24. package/dist/app-markdown.d.ts +2 -1
  25. package/dist/app-markdown.mjs +1 -1
  26. package/dist/cache.cjs +414 -12
  27. package/dist/cache.cjs.map +1 -1
  28. package/dist/cache.d.mts +120 -6
  29. package/dist/cache.d.ts +120 -6
  30. package/dist/cache.mjs +11 -3
  31. package/dist/{chunk-Y7A27276.mjs → chunk-2CUKEMVR.mjs} +349 -15
  32. package/dist/chunk-2CUKEMVR.mjs.map +1 -0
  33. package/dist/{chunk-QF4PHCMA.mjs → chunk-2ED5Q2GH.mjs} +3 -3
  34. package/dist/chunk-2ED5Q2GH.mjs.map +1 -0
  35. package/dist/{chunk-GZP5W4K3.mjs → chunk-32W4QEJP.mjs} +1 -1
  36. package/dist/chunk-32W4QEJP.mjs.map +1 -0
  37. package/dist/{chunk-TRORP7E4.mjs → chunk-3U3ZUQAQ.mjs} +2 -2
  38. package/dist/{chunk-25D7G34K.mjs → chunk-65A7QIKI.mjs} +5 -5
  39. package/dist/{chunk-25D7G34K.mjs.map → chunk-65A7QIKI.mjs.map} +1 -1
  40. package/dist/{chunk-G3B5BRDY.mjs → chunk-AJWRO5WE.mjs} +539 -61
  41. package/dist/chunk-AJWRO5WE.mjs.map +1 -0
  42. package/dist/chunk-ALCLXXTY.mjs +187 -0
  43. package/dist/chunk-ALCLXXTY.mjs.map +1 -0
  44. package/dist/{chunk-CHFHNEMO.mjs → chunk-AOBXKNS5.mjs} +627 -84
  45. package/dist/chunk-AOBXKNS5.mjs.map +1 -0
  46. package/dist/{chunk-B6N4ZB2H.mjs → chunk-C2ROET2V.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-QM6VV26B.mjs → chunk-GQVGIUSN.mjs} +3 -3
  52. package/dist/{chunk-QM6VV26B.mjs.map → chunk-GQVGIUSN.mjs.map} +1 -1
  53. package/dist/{chunk-UREJA4GZ.mjs → chunk-GXASWWJU.mjs} +1 -1
  54. package/dist/{chunk-UREJA4GZ.mjs.map → chunk-GXASWWJU.mjs.map} +1 -1
  55. package/dist/{chunk-3QJO55ZF.mjs → chunk-HNIQFZKB.mjs} +5 -3
  56. package/dist/{chunk-3QJO55ZF.mjs.map → chunk-HNIQFZKB.mjs.map} +1 -1
  57. package/dist/{chunk-PRNYWD7K.mjs → chunk-JDEOUK5V.mjs} +67 -239
  58. package/dist/chunk-JDEOUK5V.mjs.map +1 -0
  59. package/dist/{chunk-O3HADRW6.mjs → chunk-MIUW47JX.mjs} +2 -2
  60. package/dist/{chunk-O3HADRW6.mjs.map → chunk-MIUW47JX.mjs.map} +1 -1
  61. package/dist/{chunk-UHE2TTLK.mjs → chunk-NM3CRAAL.mjs} +9 -8
  62. package/dist/chunk-NM3CRAAL.mjs.map +1 -0
  63. package/dist/chunk-PFE6GMNE.mjs +603 -0
  64. package/dist/chunk-PFE6GMNE.mjs.map +1 -0
  65. package/dist/{chunk-S2XHZS7W.mjs → chunk-QGQX7SFC.mjs} +2 -2
  66. package/dist/chunk-QGQX7SFC.mjs.map +1 -0
  67. package/dist/{chunk-RKI6TN3A.mjs → chunk-QM746KUO.mjs} +9 -2
  68. package/dist/chunk-QM746KUO.mjs.map +1 -0
  69. package/dist/chunk-RBRLLZL5.mjs +81 -0
  70. package/dist/chunk-RBRLLZL5.mjs.map +1 -0
  71. package/dist/{chunk-HXP3ZSPC.mjs → chunk-SADGIRS2.mjs} +3 -3
  72. package/dist/{chunk-6XDUHOEM.mjs → chunk-TQAEEJB4.mjs} +3 -3
  73. package/dist/{chunk-AGS7UJ52.mjs → chunk-UB5UOSHB.mjs} +24 -12
  74. package/dist/chunk-UB5UOSHB.mjs.map +1 -0
  75. package/dist/{chunk-SXZTEK3V.mjs → chunk-UXUAWNO5.mjs} +2 -2
  76. package/dist/chunk-V3XURYJO.mjs +756 -0
  77. package/dist/chunk-V3XURYJO.mjs.map +1 -0
  78. package/dist/{chunk-TU4YJICB.mjs → chunk-VVKWFZAH.mjs} +41 -16
  79. package/dist/chunk-VVKWFZAH.mjs.map +1 -0
  80. package/dist/{chunk-JLWMCADZ.mjs → chunk-VY2UYN5R.mjs} +24 -4
  81. package/dist/chunk-VY2UYN5R.mjs.map +1 -0
  82. package/dist/{chunk-QFQRHRZS.mjs → chunk-W2CRQFF6.mjs} +151 -23
  83. package/dist/chunk-W2CRQFF6.mjs.map +1 -0
  84. package/dist/chunk-W4UIVMVI.mjs +10 -0
  85. package/dist/chunk-W4UIVMVI.mjs.map +1 -0
  86. package/dist/{chunk-Y2OJJD7R.mjs → chunk-XIVV5IWN.mjs} +7 -9
  87. package/dist/chunk-XIVV5IWN.mjs.map +1 -0
  88. package/dist/{chunk-OYXO65LI.mjs → chunk-YW7OBE6Q.mjs} +4 -4
  89. package/dist/chunk-YW7OBE6Q.mjs.map +1 -0
  90. package/dist/{chunk-YHU7SS6L.mjs → chunk-Z5CQMP54.mjs} +11 -11
  91. package/dist/{chunk-SOU3Q3ZA.mjs → chunk-ZZ57EH5Z.mjs} +1 -1
  92. package/dist/chunk-ZZ57EH5Z.mjs.map +1 -0
  93. package/dist/{client-D_yUjVhe.d.mts → client-BT1mFQas.d.mts} +55 -10
  94. package/dist/{client-Dkc03WP8.d.ts → client-Nn0q4eO4.d.ts} +55 -10
  95. package/dist/{client-plugins-BZnpeTGA.d.ts → client-plugins-Cw4qUGsw.d.ts} +7 -0
  96. package/dist/{client-plugins-g4bzuCmo.d.mts → client-plugins-DQQ1adXM.d.mts} +7 -0
  97. package/dist/client-plugins.d.mts +2 -1
  98. package/dist/client-plugins.d.ts +2 -1
  99. package/dist/client.cjs +922 -91
  100. package/dist/client.cjs.map +1 -1
  101. package/dist/client.d.mts +121 -3
  102. package/dist/client.d.ts +121 -3
  103. package/dist/client.mjs +23 -16
  104. package/dist/config.d.mts +2 -1
  105. package/dist/config.d.ts +2 -1
  106. package/dist/cron.cjs.map +1 -1
  107. package/dist/cron.mjs +1 -1
  108. package/dist/{devtools-AE4RVXCM.mjs → devtools-LVC3VB5P.mjs} +10 -10
  109. package/dist/{devtools-client-6WPY2AQU.mjs → devtools-client-3XRTBND5.mjs} +2 -11
  110. package/dist/devtools-client-3XRTBND5.mjs.map +1 -0
  111. package/dist/docs.cjs +14 -2
  112. package/dist/docs.cjs.map +1 -1
  113. package/dist/docs.mjs +10 -10
  114. package/dist/i18n/server.cjs +2 -2
  115. package/dist/i18n/server.cjs.map +1 -1
  116. package/dist/i18n/server.mjs +1 -1
  117. package/dist/index.cjs +2852 -463
  118. package/dist/index.cjs.map +1 -1
  119. package/dist/index.d.mts +13 -12
  120. package/dist/index.d.ts +13 -12
  121. package/dist/index.mjs +152 -109
  122. package/dist/index.mjs.map +1 -1
  123. package/dist/integrations.d.mts +2 -1
  124. package/dist/integrations.d.ts +2 -1
  125. package/dist/internal/build-runtime.cjs +1616 -149
  126. package/dist/internal/build-runtime.cjs.map +1 -1
  127. package/dist/internal/build-runtime.d.mts +4 -3
  128. package/dist/internal/build-runtime.d.ts +4 -3
  129. package/dist/internal/build-runtime.mjs +27 -25
  130. package/dist/internal/client-runtime.cjs.map +1 -1
  131. package/dist/internal/client-runtime.mjs +1 -1
  132. package/dist/internal/config-runtime.cjs +13 -2
  133. package/dist/internal/config-runtime.cjs.map +1 -1
  134. package/dist/internal/config-runtime.d.mts +3 -2
  135. package/dist/internal/config-runtime.d.ts +3 -2
  136. package/dist/internal/config-runtime.mjs +9 -9
  137. package/dist/internal/production-runtime.cjs +285 -9
  138. package/dist/internal/production-runtime.cjs.map +1 -1
  139. package/dist/internal/production-runtime.d.mts +4 -4
  140. package/dist/internal/production-runtime.d.ts +4 -4
  141. package/dist/internal/production-runtime.mjs +10 -8
  142. package/dist/{metadata-DAXRaOHx.d.ts → metadata-BAPg_Nmo.d.ts} +1 -1
  143. package/dist/{metadata-C9NZxMDW.d.mts → metadata-_6i9oFG3.d.mts} +1 -1
  144. package/dist/middleware.cjs +2 -2
  145. package/dist/middleware.cjs.map +1 -1
  146. package/dist/middleware.d.mts +4 -3
  147. package/dist/middleware.d.ts +4 -3
  148. package/dist/middleware.mjs +3 -3
  149. package/dist/navigation.cjs +40 -15
  150. package/dist/navigation.cjs.map +1 -1
  151. package/dist/navigation.mjs +3 -3
  152. package/dist/{nitro-KME62MWG.mjs → nitro-QO5LV6QK.mjs} +11 -13
  153. package/dist/{nitro-KME62MWG.mjs.map → nitro-QO5LV6QK.mjs.map} +1 -1
  154. package/dist/plugin.cjs +1032 -92
  155. package/dist/plugin.cjs.map +1 -1
  156. package/dist/plugin.d.mts +2 -1
  157. package/dist/plugin.d.ts +2 -1
  158. package/dist/plugin.mjs +23 -21
  159. package/dist/{production-runtime-DRkCHUvJ.d.ts → production-runtime-BoJDc5mc.d.ts} +1 -1
  160. package/dist/{production-runtime-flrjp_nC.d.mts → production-runtime-DPfgMV9Y.d.mts} +1 -1
  161. package/dist/routes.cjs +276 -6
  162. package/dist/routes.cjs.map +1 -1
  163. package/dist/routes.d.mts +1 -1
  164. package/dist/routes.d.ts +1 -1
  165. package/dist/routes.mjs +4 -4
  166. package/dist/runtime-9nQjVM7X.d.mts +206 -0
  167. package/dist/runtime-DgeS2skB.d.ts +206 -0
  168. package/dist/server-action-security.cjs +28 -10
  169. package/dist/server-action-security.cjs.map +1 -1
  170. package/dist/server-action-security.d.mts +2 -1
  171. package/dist/server-action-security.d.ts +2 -1
  172. package/dist/server-action-security.mjs +2 -2
  173. package/dist/server-fn-client.cjs.map +1 -1
  174. package/dist/server-fn-client.d.mts +1 -0
  175. package/dist/server-fn-client.d.ts +1 -0
  176. package/dist/server-fn-client.mjs +1 -1
  177. package/dist/server-fn.cjs +785 -3
  178. package/dist/server-fn.cjs.map +1 -1
  179. package/dist/server-fn.d.mts +10 -1
  180. package/dist/server-fn.d.ts +10 -1
  181. package/dist/server-fn.mjs +6 -3
  182. package/dist/server-plugins.d.mts +3 -2
  183. package/dist/server-plugins.d.ts +3 -2
  184. package/dist/server-query-client.cjs +278 -7
  185. package/dist/server-query-client.cjs.map +1 -1
  186. package/dist/server-query-client.mjs +4 -4
  187. package/dist/server-query.cjs +381 -10
  188. package/dist/server-query.cjs.map +1 -1
  189. package/dist/server-query.mjs +5 -5
  190. package/dist/server.cjs +1233 -118
  191. package/dist/server.cjs.map +1 -1
  192. package/dist/server.d.mts +8 -7
  193. package/dist/server.d.ts +8 -7
  194. package/dist/server.mjs +53 -33
  195. package/dist/server.mjs.map +1 -1
  196. package/dist/testing.cjs +436 -25
  197. package/dist/testing.cjs.map +1 -1
  198. package/dist/testing.d.mts +4 -3
  199. package/dist/testing.d.ts +4 -3
  200. package/dist/testing.mjs +19 -18
  201. package/dist/testing.mjs.map +1 -1
  202. package/dist/transport-BmbGTXA5.d.mts +49 -0
  203. package/dist/transport-BmbGTXA5.d.ts +49 -0
  204. package/dist/{utils-DOXXivjL.d.mts → utils-CHXlMDkg.d.mts} +1 -1
  205. package/dist/{utils-DA1yo54_.d.ts → utils-Drsyz1Vj.d.ts} +1 -1
  206. package/dist/version.cjs +36 -0
  207. package/dist/version.cjs.map +1 -0
  208. package/dist/version.d.mts +3 -0
  209. package/dist/version.d.ts +3 -0
  210. package/dist/version.mjs +8 -0
  211. package/dist/version.mjs.map +1 -0
  212. package/dist/vite.cjs +1039 -93
  213. package/dist/vite.cjs.map +1 -1
  214. package/dist/vite.d.mts +2 -1
  215. package/dist/vite.d.ts +2 -1
  216. package/dist/vite.mjs +23 -21
  217. package/dist/workflows.cjs +6 -8
  218. package/dist/workflows.cjs.map +1 -1
  219. package/dist/workflows.mjs +1 -1
  220. package/package.json +12 -5
  221. package/types/api.d.ts +44 -0
  222. package/types/client.d.ts +220 -16
  223. package/dist/chunk-4PTK6KT4.mjs +0 -364
  224. package/dist/chunk-4PTK6KT4.mjs.map +0 -1
  225. package/dist/chunk-AGS7UJ52.mjs.map +0 -1
  226. package/dist/chunk-CHFHNEMO.mjs.map +0 -1
  227. package/dist/chunk-EVGBEZDF.mjs +0 -215
  228. package/dist/chunk-EVGBEZDF.mjs.map +0 -1
  229. package/dist/chunk-G3B5BRDY.mjs.map +0 -1
  230. package/dist/chunk-GZP5W4K3.mjs.map +0 -1
  231. package/dist/chunk-JLWMCADZ.mjs.map +0 -1
  232. package/dist/chunk-JN3UU635.mjs.map +0 -1
  233. package/dist/chunk-OYXO65LI.mjs.map +0 -1
  234. package/dist/chunk-PRNYWD7K.mjs.map +0 -1
  235. package/dist/chunk-QF4PHCMA.mjs.map +0 -1
  236. package/dist/chunk-QFQRHRZS.mjs.map +0 -1
  237. package/dist/chunk-RKI6TN3A.mjs.map +0 -1
  238. package/dist/chunk-S2XHZS7W.mjs.map +0 -1
  239. package/dist/chunk-SOU3Q3ZA.mjs.map +0 -1
  240. package/dist/chunk-TU4YJICB.mjs.map +0 -1
  241. package/dist/chunk-TXCFGOHW.mjs +0 -42
  242. package/dist/chunk-TXCFGOHW.mjs.map +0 -1
  243. package/dist/chunk-UHE2TTLK.mjs.map +0 -1
  244. package/dist/chunk-Y2OJJD7R.mjs.map +0 -1
  245. package/dist/chunk-Y7A27276.mjs.map +0 -1
  246. package/dist/chunk-ZJQNATYV.mjs.map +0 -1
  247. package/dist/devtools-client-6WPY2AQU.mjs.map +0 -1
  248. /package/dist/{chunk-TRORP7E4.mjs.map → chunk-3U3ZUQAQ.mjs.map} +0 -0
  249. /package/dist/{chunk-B6N4ZB2H.mjs.map → chunk-C2ROET2V.mjs.map} +0 -0
  250. /package/dist/{chunk-HXP3ZSPC.mjs.map → chunk-SADGIRS2.mjs.map} +0 -0
  251. /package/dist/{chunk-6XDUHOEM.mjs.map → chunk-TQAEEJB4.mjs.map} +0 -0
  252. /package/dist/{chunk-SXZTEK3V.mjs.map → chunk-UXUAWNO5.mjs.map} +0 -0
  253. /package/dist/{chunk-YHU7SS6L.mjs.map → chunk-Z5CQMP54.mjs.map} +0 -0
  254. /package/dist/{devtools-AE4RVXCM.mjs.map → devtools-LVC3VB5P.mjs.map} +0 -0
package/dist/testing.cjs CHANGED
@@ -156,20 +156,48 @@ function formatError(error) {
156
156
  __name(formatError, "formatError");
157
157
 
158
158
  // src/cache-invalidation.ts
159
+ var FARM_CACHE_INVALIDATION_HEADER = "x-farm-cache-invalidations";
159
160
  var FARM_CACHE_INVALIDATION_STATE = /* @__PURE__ */ Symbol.for("farm.cacheInvalidationState");
160
161
  var globalState = globalThis;
161
162
  function getFarmCacheInvalidationState() {
162
163
  return globalState[FARM_CACHE_INVALIDATION_STATE] ?? (globalState[FARM_CACHE_INVALIDATION_STATE] = {
163
- listeners: /* @__PURE__ */ new Set()
164
+ listeners: /* @__PURE__ */ new Set(),
165
+ taskListeners: /* @__PURE__ */ new Set()
164
166
  });
165
167
  }
166
168
  __name(getFarmCacheInvalidationState, "getFarmCacheInvalidationState");
169
+ function encodeFarmCacheInvalidations(keys) {
170
+ const normalized = Array.from(
171
+ new Set(keys.filter((key) => typeof key === "string" && key.length > 0))
172
+ );
173
+ if (normalized.length === 0) return null;
174
+ return encodeURIComponent(JSON.stringify(normalized));
175
+ }
176
+ __name(encodeFarmCacheInvalidations, "encodeFarmCacheInvalidations");
177
+ function decodeFarmCacheInvalidations(value) {
178
+ if (!value) return [];
179
+ try {
180
+ const parsed = JSON.parse(decodeURIComponent(value));
181
+ return Array.isArray(parsed) ? Array.from(
182
+ new Set(parsed.filter((key) => typeof key === "string" && key.length > 0))
183
+ ) : [];
184
+ } catch {
185
+ return [];
186
+ }
187
+ }
188
+ __name(decodeFarmCacheInvalidations, "decodeFarmCacheInvalidations");
167
189
  function subscribeFarmCacheInvalidation(listener) {
168
190
  const state = getFarmCacheInvalidationState();
169
191
  state.listeners.add(listener);
170
192
  return () => state.listeners.delete(listener);
171
193
  }
172
194
  __name(subscribeFarmCacheInvalidation, "subscribeFarmCacheInvalidation");
195
+ function subscribeFarmCacheTask(listener) {
196
+ const state = getFarmCacheInvalidationState();
197
+ state.taskListeners.add(listener);
198
+ return () => state.taskListeners.delete(listener);
199
+ }
200
+ __name(subscribeFarmCacheTask, "subscribeFarmCacheTask");
173
201
 
174
202
  // src/i18n/bridge.ts
175
203
  var FARM_I18N_SNAPSHOT_RESOLVER = /* @__PURE__ */ Symbol.for("farm.i18n.snapshotResolver");
@@ -180,11 +208,51 @@ __name(_setFarmI18nSnapshotResolver, "_setFarmI18nSnapshotResolver");
180
208
 
181
209
  // src/cache.ts
182
210
  var _FarmDataCache = class _FarmDataCache {
183
- constructor() {
211
+ constructor(config = {}) {
184
212
  this.entries = /* @__PURE__ */ new Map();
185
213
  this.inflight = /* @__PURE__ */ new Map();
186
214
  this.invalidatedTagVersions = /* @__PURE__ */ new Map();
187
215
  this.version = 0;
216
+ this.namespace = "farm";
217
+ this.local = true;
218
+ this.lease = {
219
+ enabled: true,
220
+ ttlMs: 1e4,
221
+ waitTimeoutMs: 1e4,
222
+ pollIntervalMs: 25
223
+ };
224
+ this.configure(config);
225
+ }
226
+ configure(config = {}) {
227
+ this.adapter = config.adapter;
228
+ this.namespace = normalizeCacheNamespace(config.namespace || "farm");
229
+ this.local = !config.adapter;
230
+ this.lease = config.lease === false ? { ...this.lease, enabled: false } : {
231
+ enabled: true,
232
+ ttlMs: normalizePositiveDuration(config.lease?.ttlMs, 1e4, "cache.lease.ttlMs"),
233
+ waitTimeoutMs: normalizePositiveDuration(
234
+ config.lease?.waitTimeoutMs,
235
+ 1e4,
236
+ "cache.lease.waitTimeoutMs"
237
+ ),
238
+ pollIntervalMs: normalizePositiveDuration(
239
+ config.lease?.pollIntervalMs,
240
+ 25,
241
+ "cache.lease.pollIntervalMs"
242
+ )
243
+ };
244
+ if (!this.local) {
245
+ this.entries.clear();
246
+ this.inflight.clear();
247
+ this.invalidatedTagVersions.clear();
248
+ this.version = 0;
249
+ }
250
+ }
251
+ get adapterName() {
252
+ return this.adapter?.name || (this.adapter ? "custom" : "memory");
253
+ }
254
+ get hasAdapter() {
255
+ return this.adapter !== void 0;
188
256
  }
189
257
  get size() {
190
258
  return this.entries.size;
@@ -220,6 +288,45 @@ var _FarmDataCache = class _FarmDataCache {
220
288
  });
221
289
  return this.toPublicEntry(entry);
222
290
  }
291
+ async getEntryAsync(key, options = {}) {
292
+ if (this.local) {
293
+ const localEntry = this.getEntry(key, options);
294
+ if (localEntry) return localEntry;
295
+ }
296
+ if (!this.adapter) {
297
+ return this.local ? void 0 : this.getEntry(key, options);
298
+ }
299
+ const entry = await this.adapter.get(this.createAdapterKey(key));
300
+ if (!entry) {
301
+ emitFarmEvent({ type: "cache.miss", key });
302
+ return void 0;
303
+ }
304
+ assertFarmCacheEntry(entry, key);
305
+ const stale = await this.isAdapterEntryStale(entry, options.now);
306
+ if (stale) {
307
+ emitFarmEvent({
308
+ type: "cache.stale",
309
+ key,
310
+ tags: [...entry.tags],
311
+ revalidate: entry.revalidate
312
+ });
313
+ if (!options.allowStale) {
314
+ emitFarmEvent({ type: "cache.miss", key, reason: "stale" });
315
+ return void 0;
316
+ }
317
+ }
318
+ emitFarmEvent({
319
+ type: "cache.hit",
320
+ key,
321
+ tags: [...entry.tags],
322
+ revalidate: entry.revalidate,
323
+ stale
324
+ });
325
+ if (this.local && !stale) {
326
+ this.hydrateLocalEntry(entry);
327
+ }
328
+ return { ...entry, key };
329
+ }
223
330
  set(key, value, options = {}) {
224
331
  const tags = /* @__PURE__ */ new Set();
225
332
  for (const tag of options.tags ?? []) {
@@ -232,6 +339,7 @@ var _FarmDataCache = class _FarmDataCache {
232
339
  key,
233
340
  value,
234
341
  tags,
342
+ tagVersions: void 0,
235
343
  createdAt: options.createdAt ?? Date.now(),
236
344
  createdVersion: ++this.version,
237
345
  revalidate: normalizeRevalidate(options.revalidate)
@@ -245,11 +353,45 @@ var _FarmDataCache = class _FarmDataCache {
245
353
  });
246
354
  return this.toPublicEntry(entry);
247
355
  }
356
+ async setAsync(key, value, options = {}, tagVersions) {
357
+ const tags = normalizeCacheOptionsTags(options);
358
+ const capturedVersions = tagVersions ?? await this.getAdapterTagVersions(Array.from(tags.values()));
359
+ const entry = {
360
+ key,
361
+ value,
362
+ tags: Array.from(tags),
363
+ tagVersions: capturedVersions,
364
+ createdAt: options.createdAt ?? Date.now(),
365
+ createdVersion: ++this.version,
366
+ revalidate: normalizeRevalidate(options.revalidate)
367
+ };
368
+ if (this.local) {
369
+ this.hydrateLocalEntry(entry);
370
+ }
371
+ if (this.adapter) {
372
+ await this.adapter.set(this.createAdapterKey(key), entry);
373
+ }
374
+ emitFarmEvent({
375
+ type: "cache.set",
376
+ key,
377
+ tags: [...entry.tags],
378
+ revalidate: entry.revalidate
379
+ });
380
+ return entry;
381
+ }
248
382
  delete(key) {
249
383
  const deleted = this.entries.delete(key);
250
384
  emitFarmEvent({ type: "cache.delete", key, deleted });
251
385
  return deleted;
252
386
  }
387
+ async deleteAsync(key) {
388
+ const deleted = this.entries.delete(key);
389
+ if (this.adapter) {
390
+ await this.adapter.delete(this.createAdapterKey(key));
391
+ }
392
+ emitFarmEvent({ type: "cache.delete", key, deleted: this.adapter ? true : deleted });
393
+ return this.adapter ? true : deleted;
394
+ }
253
395
  clear() {
254
396
  const count = this.entries.size;
255
397
  this.entries.clear();
@@ -258,6 +400,10 @@ var _FarmDataCache = class _FarmDataCache {
258
400
  this.version = 0;
259
401
  emitFarmEvent({ type: "cache.clear", count });
260
402
  }
403
+ async clearAsync() {
404
+ this.clear();
405
+ await this.adapter?.clear?.();
406
+ }
261
407
  isStale(entry, now = Date.now()) {
262
408
  if (typeof entry.revalidate === "number" && entry.revalidate > 0 && now - entry.createdAt >= entry.revalidate * 1e3) {
263
409
  return true;
@@ -270,6 +416,12 @@ var _FarmDataCache = class _FarmDataCache {
270
416
  }
271
417
  return false;
272
418
  }
419
+ async isStaleAsync(entry, now = Date.now()) {
420
+ if (this.adapter) {
421
+ return this.isAdapterEntryStale(entry, now);
422
+ }
423
+ return this.isStale(entry, now);
424
+ }
273
425
  revalidateTag(tag, options = {}) {
274
426
  const normalized = normalizeCacheTag(tag);
275
427
  const count = this.invalidateTag(normalized);
@@ -278,6 +430,15 @@ var _FarmDataCache = class _FarmDataCache {
278
430
  );
279
431
  return count;
280
432
  }
433
+ async revalidateTagAsync(tag, options = {}) {
434
+ const normalized = normalizeCacheTag(tag);
435
+ const count = this.invalidateTag(normalized);
436
+ await this.adapter?.invalidateTags?.([this.createAdapterTag(normalized)]);
437
+ emitFarmEvent(
438
+ options.source === "updateTag" ? { type: "cache.updateTag", tag: normalized, count } : { type: "cache.revalidateTag", tag: normalized, profile: options.profile, count }
439
+ );
440
+ return count;
441
+ }
281
442
  revalidatePath(routePath) {
282
443
  const normalizedPath = normalizeRevalidatePath(routePath);
283
444
  const pathTag = createPathCacheTag(normalizedPath);
@@ -294,8 +455,25 @@ var _FarmDataCache = class _FarmDataCache {
294
455
  }
295
456
  return count;
296
457
  }
458
+ async revalidatePathAsync(routePath) {
459
+ const normalizedPath = normalizeRevalidatePath(routePath);
460
+ const pathTag = createPathCacheTag(normalizedPath);
461
+ const pprCount = this.countEntriesForTags([pathTag, "ppr"]);
462
+ const count = this.invalidateTag(pathTag);
463
+ await this.adapter?.invalidateTags?.([this.createAdapterTag(pathTag)]);
464
+ emitFarmEvent({ type: "cache.revalidatePath", path: normalizedPath, count });
465
+ if (pprCount > 0) {
466
+ emitFarmEvent({
467
+ type: "ppr.shell.invalidated",
468
+ route: normalizedPath,
469
+ reason: "revalidatePath",
470
+ count: pprCount
471
+ });
472
+ }
473
+ return count;
474
+ }
297
475
  async getOrSet(key, producer, options = {}) {
298
- const cached = this.getEntry(key);
476
+ const cached = await this.getEntryAsync(key);
299
477
  if (cached) {
300
478
  return cached.value;
301
479
  }
@@ -304,10 +482,8 @@ var _FarmDataCache = class _FarmDataCache {
304
482
  emitFarmEvent({ type: "cache.dedupe", key });
305
483
  return inflight;
306
484
  }
307
- const promise = Promise.resolve().then(producer).then((value) => {
308
- this.set(key, value, options);
309
- return value;
310
- }).catch((error) => {
485
+ const tags = Array.from(normalizeCacheOptionsTags(options));
486
+ const promise = this.fillCacheEntry(key, producer, options, tags).catch((error) => {
311
487
  emitFarmEvent({ type: "cache.error", key, operation: "set", error });
312
488
  throw error;
313
489
  }).finally(() => {
@@ -316,6 +492,40 @@ var _FarmDataCache = class _FarmDataCache {
316
492
  this.inflight.set(key, promise);
317
493
  return promise;
318
494
  }
495
+ async fillCacheEntry(key, producer, options, tags) {
496
+ const leaseKey = `${this.namespace}:lease:${key}`;
497
+ let leaseToken;
498
+ if (this.adapter?.acquireLease && this.adapter.releaseLease && this.lease.enabled) {
499
+ leaseToken = await this.adapter.acquireLease(leaseKey, this.lease.ttlMs);
500
+ if (!leaseToken) {
501
+ const shared = await this.waitForAdapterEntry(key);
502
+ if (shared) {
503
+ emitFarmEvent({ type: "cache.dedupe", key });
504
+ return shared.value;
505
+ }
506
+ leaseToken = await this.adapter.acquireLease(leaseKey, this.lease.ttlMs);
507
+ }
508
+ }
509
+ try {
510
+ const initialTagVersions = await this.getAdapterTagVersions(tags);
511
+ const value = await producer();
512
+ await this.setAsync(key, value, options, initialTagVersions);
513
+ return value;
514
+ } finally {
515
+ if (leaseToken && this.adapter?.releaseLease) {
516
+ await this.adapter.releaseLease(leaseKey, leaseToken);
517
+ }
518
+ }
519
+ }
520
+ async waitForAdapterEntry(key) {
521
+ const deadline = Date.now() + this.lease.waitTimeoutMs;
522
+ while (Date.now() < deadline) {
523
+ await delay(this.lease.pollIntervalMs);
524
+ const entry = await this.getEntryAsync(key);
525
+ if (entry) return entry;
526
+ }
527
+ return void 0;
528
+ }
319
529
  countEntriesForTag(tag) {
320
530
  let count = 0;
321
531
  for (const entry of this.entries.values()) {
@@ -343,11 +553,53 @@ var _FarmDataCache = class _FarmDataCache {
343
553
  key: entry.key,
344
554
  value: entry.value,
345
555
  tags: Array.from(entry.tags),
556
+ tagVersions: entry.tagVersions,
346
557
  createdAt: entry.createdAt,
347
558
  createdVersion: entry.createdVersion,
348
559
  revalidate: entry.revalidate
349
560
  };
350
561
  }
562
+ hydrateLocalEntry(entry) {
563
+ this.entries.set(entry.key, {
564
+ key: entry.key,
565
+ value: entry.value,
566
+ tags: new Set(entry.tags.map(normalizeCacheTag)),
567
+ tagVersions: entry.tagVersions,
568
+ createdAt: entry.createdAt,
569
+ createdVersion: entry.createdVersion ?? ++this.version,
570
+ revalidate: normalizeRevalidate(entry.revalidate)
571
+ });
572
+ }
573
+ createAdapterKey(key) {
574
+ return `${this.namespace}:entry:${key}`;
575
+ }
576
+ createAdapterTag(tag) {
577
+ return `${this.namespace}:tag:${tag}`;
578
+ }
579
+ async getAdapterTagVersions(tags) {
580
+ if (!this.adapter?.getTagVersions || tags.length === 0) return {};
581
+ const normalized = tags.map(normalizeCacheTag);
582
+ const physicalTags = normalized.map((tag) => this.createAdapterTag(tag));
583
+ const versions = await this.adapter.getTagVersions(physicalTags);
584
+ return Object.fromEntries(
585
+ normalized.map((tag, index) => [
586
+ tag,
587
+ normalizeAdapterVersion(versions[physicalTags[index]])
588
+ ])
589
+ );
590
+ }
591
+ async isAdapterEntryStale(entry, now = Date.now()) {
592
+ if (typeof entry.revalidate === "number" && entry.revalidate > 0 && now - entry.createdAt >= entry.revalidate * 1e3) {
593
+ return true;
594
+ }
595
+ const currentVersions = await this.getAdapterTagVersions(entry.tags);
596
+ for (const tag of entry.tags) {
597
+ if (normalizeAdapterVersion(currentVersions[tag]) > normalizeAdapterVersion(entry.tagVersions?.[tag])) {
598
+ return true;
599
+ }
600
+ }
601
+ return false;
602
+ }
351
603
  };
352
604
  __name(_FarmDataCache, "FarmDataCache");
353
605
  var FarmDataCache = _FarmDataCache;
@@ -420,6 +672,52 @@ function normalizeCacheTag(tag) {
420
672
  return normalized;
421
673
  }
422
674
  __name(normalizeCacheTag, "normalizeCacheTag");
675
+ function normalizeCacheNamespace(namespace) {
676
+ if (typeof namespace !== "string") {
677
+ throw new TypeError("Cache namespace must be a string.");
678
+ }
679
+ const normalized = namespace.trim().replace(/:+$/g, "");
680
+ if (!normalized) {
681
+ throw new Error("Cache namespace cannot be empty.");
682
+ }
683
+ return normalized;
684
+ }
685
+ __name(normalizeCacheNamespace, "normalizeCacheNamespace");
686
+ function normalizeAdapterVersion(value) {
687
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
688
+ }
689
+ __name(normalizeAdapterVersion, "normalizeAdapterVersion");
690
+ function normalizePositiveDuration(value, fallback, name) {
691
+ if (value === void 0) return fallback;
692
+ if (!Number.isFinite(value) || value <= 0) {
693
+ throw new TypeError(`${name} must be a positive number of milliseconds.`);
694
+ }
695
+ return Math.floor(value);
696
+ }
697
+ __name(normalizePositiveDuration, "normalizePositiveDuration");
698
+ function delay(ms) {
699
+ return new Promise((resolve) => setTimeout(resolve, ms));
700
+ }
701
+ __name(delay, "delay");
702
+ function normalizeCacheOptionsTags(options) {
703
+ const tags = /* @__PURE__ */ new Set();
704
+ for (const tag of options.tags ?? []) {
705
+ tags.add(normalizeCacheTag(tag));
706
+ }
707
+ for (const routePath of options.paths ?? []) {
708
+ tags.add(createPathCacheTag(routePath));
709
+ }
710
+ return tags;
711
+ }
712
+ __name(normalizeCacheOptionsTags, "normalizeCacheOptionsTags");
713
+ function assertFarmCacheEntry(entry, expectedKey) {
714
+ if (!entry || typeof entry !== "object" || entry.key !== expectedKey || !Array.isArray(entry.tags) || typeof entry.createdAt !== "number") {
715
+ throw new TypeError(
716
+ `Cache adapter returned an invalid entry for ${JSON.stringify(expectedKey)}.`
717
+ );
718
+ }
719
+ }
720
+ __name(assertFarmCacheEntry, "assertFarmCacheEntry");
423
721
  function getFunctionCacheIdentity(fn) {
424
722
  if (fn.name) {
425
723
  return `name:${fn.name}`;
@@ -1196,6 +1494,26 @@ async function _runWithCurrentRequest(request, fn) {
1196
1494
  }
1197
1495
  __name(_runWithCurrentRequest, "_runWithCurrentRequest");
1198
1496
 
1497
+ // src/api/endpoint.ts
1498
+ var import_better_call = require("better-call");
1499
+ var _EndpointFailure = class _EndpointFailure extends Error {
1500
+ constructor(code, data, options) {
1501
+ super(options.message);
1502
+ this.name = "EndpointFailure";
1503
+ this.code = code;
1504
+ this.data = data;
1505
+ this.status = options.status;
1506
+ }
1507
+ };
1508
+ __name(_EndpointFailure, "EndpointFailure");
1509
+ var EndpointFailure = _EndpointFailure;
1510
+ function isEndpointFailure(value) {
1511
+ return value instanceof EndpointFailure;
1512
+ }
1513
+ __name(isEndpointFailure, "isEndpointFailure");
1514
+ var EMPTY_ENDPOINT_MIDDLEWARE = Object.freeze([]);
1515
+ var EMPTY_ENDPOINT_CONTEXT = Object.freeze(/* @__PURE__ */ Object.create(null));
1516
+
1199
1517
  // src/api/runtime.ts
1200
1518
  function matchAPIRoute(routes, pathname) {
1201
1519
  const exactRoute = routes.get(pathname);
@@ -1228,10 +1546,10 @@ __name(invokeAPIRouteEndpoint, "invokeAPIRouteEndpoint");
1228
1546
  async function invokeAPIRouteEndpointInContext(endpoint, request, params) {
1229
1547
  const farmHandler = endpoint.__handler || (isFarmContextHandler(endpoint) ? endpoint : null);
1230
1548
  if (!farmHandler) {
1231
- const result2 = await endpoint(request, {
1549
+ const result = await endpoint(request, {
1232
1550
  params: Promise.resolve(params)
1233
1551
  });
1234
- return normalizeRouteResponse(result2);
1552
+ return normalizeRouteResponse(result);
1235
1553
  }
1236
1554
  const url = new URL(request.url);
1237
1555
  const query = {};
@@ -1240,7 +1558,7 @@ async function invokeAPIRouteEndpointInContext(endpoint, request, params) {
1240
1558
  });
1241
1559
  let body = void 0;
1242
1560
  if (request.method.toUpperCase() !== "GET" && request.method.toUpperCase() !== "HEAD") {
1243
- body = await readJSONBody(request);
1561
+ body = await readRequestBody(request);
1244
1562
  }
1245
1563
  const headers = Object.fromEntries(request.headers.entries());
1246
1564
  const types = endpoint.__types || {};
@@ -1256,15 +1574,30 @@ async function invokeAPIRouteEndpointInContext(endpoint, request, params) {
1256
1574
  if (headersValidation instanceof Response) {
1257
1575
  return headersValidation;
1258
1576
  }
1259
- const result = await farmHandler({
1577
+ const handlerContext = {
1260
1578
  query: queryValidation,
1261
1579
  body: bodyValidation,
1262
1580
  headers: headersValidation,
1263
1581
  request,
1264
1582
  context: {},
1265
1583
  params
1266
- });
1267
- return normalizeRouteResponse(result);
1584
+ };
1585
+ let execution;
1586
+ try {
1587
+ execution = typeof endpoint.__farmInvoke === "function" ? await endpoint.__farmInvoke(handlerContext) : {
1588
+ result: await farmHandler(handlerContext),
1589
+ context: handlerContext.context,
1590
+ handlerExecuted: true,
1591
+ invalidations: []
1592
+ };
1593
+ } catch (error) {
1594
+ if (isEndpointFailure(error)) {
1595
+ return createEndpointFailureResponse(error);
1596
+ }
1597
+ throw error;
1598
+ }
1599
+ const response = normalizeRouteResponse(execution.result);
1600
+ return attachEndpointInvalidations(response, execution.invalidations);
1268
1601
  }
1269
1602
  __name(invokeAPIRouteEndpointInContext, "invokeAPIRouteEndpointInContext");
1270
1603
  function normalizeRouteResponse(result) {
@@ -1284,6 +1617,40 @@ function isWebResponse(value) {
1284
1617
  return value instanceof Response || typeof value === "object" && value !== null && "headers" in value && "status" in value && typeof value.arrayBuffer === "function";
1285
1618
  }
1286
1619
  __name(isWebResponse, "isWebResponse");
1620
+ function attachEndpointInvalidations(response, keys) {
1621
+ const existing = decodeFarmCacheInvalidations(
1622
+ response.headers.get(FARM_CACHE_INVALIDATION_HEADER)
1623
+ );
1624
+ const encoded = encodeFarmCacheInvalidations([...existing, ...keys]);
1625
+ if (!encoded) return response;
1626
+ const headers = new Headers(response.headers);
1627
+ headers.set(FARM_CACHE_INVALIDATION_HEADER, encoded);
1628
+ return new Response(response.body, {
1629
+ status: response.status,
1630
+ statusText: response.statusText,
1631
+ headers
1632
+ });
1633
+ }
1634
+ __name(attachEndpointInvalidations, "attachEndpointInvalidations");
1635
+ function createEndpointFailureResponse(failure) {
1636
+ return new Response(
1637
+ JSON.stringify({
1638
+ error: {
1639
+ code: failure.code,
1640
+ message: failure.message,
1641
+ data: failure.data
1642
+ }
1643
+ }),
1644
+ {
1645
+ status: failure.status,
1646
+ headers: {
1647
+ "cache-control": "no-store",
1648
+ "content-type": "application/json"
1649
+ }
1650
+ }
1651
+ );
1652
+ }
1653
+ __name(createEndpointFailureResponse, "createEndpointFailureResponse");
1287
1654
  function isFarmContextHandler(endpoint) {
1288
1655
  if (typeof endpoint !== "function") {
1289
1656
  return false;
@@ -1295,17 +1662,50 @@ function isFarmContextHandler(endpoint) {
1295
1662
  return firstParameter === "ctx" || firstParameter === "context" || firstParameter.startsWith("{");
1296
1663
  }
1297
1664
  __name(isFarmContextHandler, "isFarmContextHandler");
1298
- async function readJSONBody(request) {
1665
+ async function readRequestBody(request) {
1666
+ const contentType = request.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
1299
1667
  try {
1668
+ if (contentType === "multipart/form-data") {
1669
+ return formDataToObject(await request.clone().formData());
1670
+ }
1300
1671
  const text = await request.clone().text();
1301
- if (text) {
1672
+ if (!text) return void 0;
1673
+ if (contentType === "application/x-www-form-urlencoded") {
1674
+ return searchParamsToObject(new URLSearchParams(text));
1675
+ }
1676
+ if (contentType === "application/json" || contentType?.endsWith("+json")) {
1302
1677
  return JSON.parse(text);
1303
1678
  }
1679
+ return JSON.parse(text);
1304
1680
  } catch {
1305
1681
  }
1306
1682
  return void 0;
1307
1683
  }
1308
- __name(readJSONBody, "readJSONBody");
1684
+ __name(readRequestBody, "readRequestBody");
1685
+ function formDataToObject(formData) {
1686
+ return entriesToObject(formData.entries());
1687
+ }
1688
+ __name(formDataToObject, "formDataToObject");
1689
+ function searchParamsToObject(searchParams) {
1690
+ return entriesToObject(searchParams.entries());
1691
+ }
1692
+ __name(searchParamsToObject, "searchParamsToObject");
1693
+ function entriesToObject(entries) {
1694
+ const output = /* @__PURE__ */ Object.create(null);
1695
+ for (const [key, value] of entries) {
1696
+ if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
1697
+ const current = output[key];
1698
+ if (current === void 0) {
1699
+ output[key] = value;
1700
+ } else if (Array.isArray(current)) {
1701
+ current.push(value);
1702
+ } else {
1703
+ output[key] = [current, value];
1704
+ }
1705
+ }
1706
+ return output;
1707
+ }
1708
+ __name(entriesToObject, "entriesToObject");
1309
1709
  function validateInput(schema, value, error) {
1310
1710
  if (!schema || typeof schema.parse !== "function") {
1311
1711
  return value;
@@ -1559,16 +1959,24 @@ __name(createSearchParams2, "createSearchParams");
1559
1959
  // src/server-action-security.ts
1560
1960
  var import_node_async_hooks3 = require("async_hooks");
1561
1961
  var SERVER_ACTION_STORAGE_KEY = /* @__PURE__ */ Symbol.for("farm.serverActionStorage");
1562
- function runWithServerActionRequest(request, callback) {
1962
+ async function runWithServerActionRequest(request, callback) {
1563
1963
  throwIfAborted(request.signal);
1564
- return getServerActionStorage().run(
1565
- {
1566
- request,
1567
- signal: request.signal,
1568
- invalidations: /* @__PURE__ */ new Set()
1569
- },
1570
- callback
1571
- );
1964
+ const context = {
1965
+ request,
1966
+ signal: request.signal,
1967
+ invalidations: /* @__PURE__ */ new Set(),
1968
+ cacheTasks: /* @__PURE__ */ new Set()
1969
+ };
1970
+ return getServerActionStorage().run(context, async () => {
1971
+ try {
1972
+ const result = await callback();
1973
+ await Promise.all(context.cacheTasks);
1974
+ return result;
1975
+ } catch (error) {
1976
+ await Promise.allSettled(context.cacheTasks);
1977
+ throw error;
1978
+ }
1979
+ });
1572
1980
  }
1573
1981
  __name(runWithServerActionRequest, "runWithServerActionRequest");
1574
1982
  function getServerActionExecutionContext() {
@@ -1578,6 +1986,9 @@ __name(getServerActionExecutionContext, "getServerActionExecutionContext");
1578
1986
  subscribeFarmCacheInvalidation((key) => {
1579
1987
  getServerActionExecutionContext()?.invalidations.add(key);
1580
1988
  });
1989
+ subscribeFarmCacheTask((task) => {
1990
+ getServerActionExecutionContext()?.cacheTasks.add(task);
1991
+ });
1581
1992
  function getServerActionStorage() {
1582
1993
  const globalState2 = globalThis;
1583
1994
  if (!globalState2[SERVER_ACTION_STORAGE_KEY]) {