@farm.js/core 0.1.0-beta.3 → 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 (192) hide show
  1. package/dist/agent-runtime.d.mts +2 -1
  2. package/dist/agent-runtime.d.ts +2 -1
  3. package/dist/api/route-manager.cjs +313 -10
  4. package/dist/api/route-manager.cjs.map +1 -1
  5. package/dist/api/route-manager.d.mts +3 -2
  6. package/dist/api/route-manager.d.ts +3 -2
  7. package/dist/api/route-manager.mjs +6 -5
  8. package/dist/api/runtime.cjs +313 -10
  9. package/dist/api/runtime.cjs.map +1 -1
  10. package/dist/api/runtime.d.mts +2 -1
  11. package/dist/api/runtime.d.ts +2 -1
  12. package/dist/api/runtime.mjs +4 -3
  13. package/dist/api.cjs +642 -57
  14. package/dist/api.cjs.map +1 -1
  15. package/dist/api.d.mts +3 -2
  16. package/dist/api.d.ts +3 -2
  17. package/dist/api.mjs +29 -9
  18. package/dist/{app-DOKxo-LH.d.ts → app-BjN-da13.d.ts} +38 -3
  19. package/dist/{app-BB3Iu3xh.d.mts → app-CakAr8Be.d.mts} +38 -3
  20. package/dist/app-markdown.d.mts +2 -1
  21. package/dist/app-markdown.d.ts +2 -1
  22. package/dist/cache.cjs +395 -12
  23. package/dist/cache.cjs.map +1 -1
  24. package/dist/cache.d.mts +100 -6
  25. package/dist/cache.d.ts +100 -6
  26. package/dist/cache.mjs +8 -2
  27. package/dist/{chunk-XUBZ7JI4.mjs → chunk-2CUKEMVR.mjs} +187 -16
  28. package/dist/chunk-2CUKEMVR.mjs.map +1 -0
  29. package/dist/{chunk-5QH4IKY3.mjs → chunk-3U3ZUQAQ.mjs} +2 -2
  30. package/dist/{chunk-6WXJ54TC.mjs → chunk-65A7QIKI.mjs} +5 -5
  31. package/dist/{chunk-6WXJ54TC.mjs.map → chunk-65A7QIKI.mjs.map} +1 -1
  32. package/dist/{chunk-OHC6VCDI.mjs → chunk-AJWRO5WE.mjs} +521 -42
  33. package/dist/chunk-AJWRO5WE.mjs.map +1 -0
  34. package/dist/chunk-ALCLXXTY.mjs +187 -0
  35. package/dist/chunk-ALCLXXTY.mjs.map +1 -0
  36. package/dist/{chunk-XJSHJN4M.mjs → chunk-AOBXKNS5.mjs} +593 -49
  37. package/dist/chunk-AOBXKNS5.mjs.map +1 -0
  38. package/dist/{chunk-CSU4KJJF.mjs → chunk-C2ROET2V.mjs} +2 -2
  39. package/dist/{chunk-BIOIOWXZ.mjs → chunk-HNIQFZKB.mjs} +2 -2
  40. package/dist/{chunk-G5I34UA6.mjs → chunk-JDEOUK5V.mjs} +4 -4
  41. package/dist/{chunk-T543TMFY.mjs → chunk-NM3CRAAL.mjs} +3 -2
  42. package/dist/chunk-NM3CRAAL.mjs.map +1 -0
  43. package/dist/{chunk-LWMGIEJA.mjs → chunk-PFE6GMNE.mjs} +47 -37
  44. package/dist/chunk-PFE6GMNE.mjs.map +1 -0
  45. package/dist/{chunk-6VS6CKAV.mjs → chunk-QM746KUO.mjs} +8 -1
  46. package/dist/chunk-QM746KUO.mjs.map +1 -0
  47. package/dist/{chunk-SHRJG6OG.mjs → chunk-RBRLLZL5.mjs} +18 -3
  48. package/dist/chunk-RBRLLZL5.mjs.map +1 -0
  49. package/dist/{chunk-MH6FKW2I.mjs → chunk-SADGIRS2.mjs} +3 -3
  50. package/dist/{chunk-NRRFGX45.mjs → chunk-TQAEEJB4.mjs} +3 -3
  51. package/dist/{chunk-45LKHSHJ.mjs → chunk-UB5UOSHB.mjs} +24 -12
  52. package/dist/chunk-UB5UOSHB.mjs.map +1 -0
  53. package/dist/chunk-V3XURYJO.mjs +756 -0
  54. package/dist/chunk-V3XURYJO.mjs.map +1 -0
  55. package/dist/{chunk-5FW6PQ3J.mjs → chunk-VVKWFZAH.mjs} +41 -16
  56. package/dist/chunk-VVKWFZAH.mjs.map +1 -0
  57. package/dist/{chunk-HZYXGV4K.mjs → chunk-VY2UYN5R.mjs} +24 -4
  58. package/dist/chunk-VY2UYN5R.mjs.map +1 -0
  59. package/dist/{chunk-C33RALN7.mjs → chunk-W2CRQFF6.mjs} +79 -15
  60. package/dist/chunk-W2CRQFF6.mjs.map +1 -0
  61. package/dist/{chunk-JNYVN7YP.mjs → chunk-W4UIVMVI.mjs} +2 -2
  62. package/dist/{chunk-JNYVN7YP.mjs.map → chunk-W4UIVMVI.mjs.map} +1 -1
  63. package/dist/{chunk-LG3YINQN.mjs → chunk-Z5CQMP54.mjs} +3 -3
  64. package/dist/{client-DiViK9yK.d.mts → client-BT1mFQas.d.mts} +23 -4
  65. package/dist/{client-DpEBJbts.d.ts → client-Nn0q4eO4.d.ts} +23 -4
  66. package/dist/{client-plugins-CTnsZz_A.d.ts → client-plugins-Cw4qUGsw.d.ts} +6 -0
  67. package/dist/{client-plugins-Cnr0D3kk.d.mts → client-plugins-DQQ1adXM.d.mts} +6 -0
  68. package/dist/client-plugins.d.mts +2 -1
  69. package/dist/client-plugins.d.ts +2 -1
  70. package/dist/client.cjs +665 -82
  71. package/dist/client.cjs.map +1 -1
  72. package/dist/client.d.mts +70 -4
  73. package/dist/client.d.ts +70 -4
  74. package/dist/client.mjs +10 -7
  75. package/dist/config.d.mts +2 -1
  76. package/dist/config.d.ts +2 -1
  77. package/dist/{devtools-HE4FTUDN.mjs → devtools-LVC3VB5P.mjs} +4 -4
  78. package/dist/docs.cjs +11 -1
  79. package/dist/docs.cjs.map +1 -1
  80. package/dist/docs.mjs +4 -4
  81. package/dist/index.cjs +2112 -197
  82. package/dist/index.cjs.map +1 -1
  83. package/dist/index.d.mts +12 -11
  84. package/dist/index.d.ts +12 -11
  85. package/dist/index.mjs +49 -21
  86. package/dist/index.mjs.map +1 -1
  87. package/dist/integrations.d.mts +2 -1
  88. package/dist/integrations.d.ts +2 -1
  89. package/dist/internal/build-runtime.cjs +1455 -90
  90. package/dist/internal/build-runtime.cjs.map +1 -1
  91. package/dist/internal/build-runtime.d.mts +4 -3
  92. package/dist/internal/build-runtime.d.ts +4 -3
  93. package/dist/internal/build-runtime.mjs +15 -14
  94. package/dist/internal/config-runtime.cjs +12 -1
  95. package/dist/internal/config-runtime.cjs.map +1 -1
  96. package/dist/internal/config-runtime.d.mts +3 -2
  97. package/dist/internal/config-runtime.d.ts +3 -2
  98. package/dist/internal/config-runtime.mjs +3 -3
  99. package/dist/internal/production-runtime.cjs +282 -6
  100. package/dist/internal/production-runtime.cjs.map +1 -1
  101. package/dist/internal/production-runtime.d.mts +4 -4
  102. package/dist/internal/production-runtime.d.ts +4 -4
  103. package/dist/internal/production-runtime.mjs +4 -2
  104. package/dist/{metadata-eoVmHoyv.d.ts → metadata-BAPg_Nmo.d.ts} +1 -1
  105. package/dist/{metadata-Dp8AdvsB.d.mts → metadata-_6i9oFG3.d.mts} +1 -1
  106. package/dist/middleware.d.mts +4 -3
  107. package/dist/middleware.d.ts +4 -3
  108. package/dist/navigation.cjs +40 -15
  109. package/dist/navigation.cjs.map +1 -1
  110. package/dist/navigation.mjs +2 -2
  111. package/dist/plugin.cjs +913 -53
  112. package/dist/plugin.cjs.map +1 -1
  113. package/dist/plugin.d.mts +2 -1
  114. package/dist/plugin.d.ts +2 -1
  115. package/dist/plugin.mjs +11 -10
  116. package/dist/{production-runtime-BqTnUTai.d.ts → production-runtime-BoJDc5mc.d.ts} +1 -1
  117. package/dist/{production-runtime-DtDdG9fc.d.mts → production-runtime-DPfgMV9Y.d.mts} +1 -1
  118. package/dist/routes.cjs +276 -6
  119. package/dist/routes.cjs.map +1 -1
  120. package/dist/routes.d.mts +1 -1
  121. package/dist/routes.d.ts +1 -1
  122. package/dist/routes.mjs +3 -3
  123. package/dist/{runtime-C1B7pSGT.d.mts → runtime-9nQjVM7X.d.mts} +8 -9
  124. package/dist/{runtime-CdPHt0bv.d.ts → runtime-DgeS2skB.d.ts} +8 -9
  125. package/dist/server-action-security.cjs +28 -10
  126. package/dist/server-action-security.cjs.map +1 -1
  127. package/dist/server-action-security.d.mts +2 -1
  128. package/dist/server-action-security.d.ts +2 -1
  129. package/dist/server-action-security.mjs +2 -2
  130. package/dist/server-fn-client.d.mts +1 -0
  131. package/dist/server-fn-client.d.ts +1 -0
  132. package/dist/server-fn.cjs +785 -3
  133. package/dist/server-fn.cjs.map +1 -1
  134. package/dist/server-fn.d.mts +10 -1
  135. package/dist/server-fn.d.ts +10 -1
  136. package/dist/server-fn.mjs +6 -3
  137. package/dist/server-plugins.d.mts +3 -2
  138. package/dist/server-plugins.d.ts +3 -2
  139. package/dist/server-query-client.cjs +278 -7
  140. package/dist/server-query-client.cjs.map +1 -1
  141. package/dist/server-query-client.mjs +4 -4
  142. package/dist/server-query.cjs +381 -10
  143. package/dist/server-query.cjs.map +1 -1
  144. package/dist/server-query.mjs +5 -5
  145. package/dist/server.cjs +1086 -76
  146. package/dist/server.cjs.map +1 -1
  147. package/dist/server.d.mts +8 -7
  148. package/dist/server.d.ts +8 -7
  149. package/dist/server.mjs +31 -16
  150. package/dist/server.mjs.map +1 -1
  151. package/dist/testing.cjs +341 -20
  152. package/dist/testing.cjs.map +1 -1
  153. package/dist/testing.d.mts +3 -2
  154. package/dist/testing.d.ts +3 -2
  155. package/dist/testing.mjs +7 -6
  156. package/dist/testing.mjs.map +1 -1
  157. package/dist/transport-BmbGTXA5.d.mts +49 -0
  158. package/dist/transport-BmbGTXA5.d.ts +49 -0
  159. package/dist/{utils-8USa5BiY.d.mts → utils-CHXlMDkg.d.mts} +1 -1
  160. package/dist/{utils-DKJb6K6G.d.ts → utils-Drsyz1Vj.d.ts} +1 -1
  161. package/dist/version.cjs +1 -1
  162. package/dist/version.cjs.map +1 -1
  163. package/dist/version.mjs +1 -1
  164. package/dist/vite.cjs +914 -54
  165. package/dist/vite.cjs.map +1 -1
  166. package/dist/vite.d.mts +2 -1
  167. package/dist/vite.d.ts +2 -1
  168. package/dist/vite.mjs +11 -10
  169. package/package.json +1 -1
  170. package/types/api.d.ts +44 -0
  171. package/types/client.d.ts +85 -4
  172. package/dist/chunk-45LKHSHJ.mjs.map +0 -1
  173. package/dist/chunk-5FW6PQ3J.mjs.map +0 -1
  174. package/dist/chunk-6VS6CKAV.mjs.map +0 -1
  175. package/dist/chunk-C33RALN7.mjs.map +0 -1
  176. package/dist/chunk-GZWT6VI5.mjs +0 -382
  177. package/dist/chunk-GZWT6VI5.mjs.map +0 -1
  178. package/dist/chunk-HZYXGV4K.mjs.map +0 -1
  179. package/dist/chunk-LWMGIEJA.mjs.map +0 -1
  180. package/dist/chunk-OHC6VCDI.mjs.map +0 -1
  181. package/dist/chunk-SHRJG6OG.mjs.map +0 -1
  182. package/dist/chunk-T543TMFY.mjs.map +0 -1
  183. package/dist/chunk-XJSHJN4M.mjs.map +0 -1
  184. package/dist/chunk-XUBZ7JI4.mjs.map +0 -1
  185. /package/dist/{chunk-5QH4IKY3.mjs.map → chunk-3U3ZUQAQ.mjs.map} +0 -0
  186. /package/dist/{chunk-CSU4KJJF.mjs.map → chunk-C2ROET2V.mjs.map} +0 -0
  187. /package/dist/{chunk-BIOIOWXZ.mjs.map → chunk-HNIQFZKB.mjs.map} +0 -0
  188. /package/dist/{chunk-G5I34UA6.mjs.map → chunk-JDEOUK5V.mjs.map} +0 -0
  189. /package/dist/{chunk-MH6FKW2I.mjs.map → chunk-SADGIRS2.mjs.map} +0 -0
  190. /package/dist/{chunk-NRRFGX45.mjs.map → chunk-TQAEEJB4.mjs.map} +0 -0
  191. /package/dist/{chunk-LG3YINQN.mjs.map → chunk-Z5CQMP54.mjs.map} +0 -0
  192. /package/dist/{devtools-HE4FTUDN.mjs.map → devtools-LVC3VB5P.mjs.map} +0 -0
package/dist/testing.cjs CHANGED
@@ -161,7 +161,8 @@ var FARM_CACHE_INVALIDATION_STATE = /* @__PURE__ */ Symbol.for("farm.cacheInvali
161
161
  var globalState = globalThis;
162
162
  function getFarmCacheInvalidationState() {
163
163
  return globalState[FARM_CACHE_INVALIDATION_STATE] ?? (globalState[FARM_CACHE_INVALIDATION_STATE] = {
164
- listeners: /* @__PURE__ */ new Set()
164
+ listeners: /* @__PURE__ */ new Set(),
165
+ taskListeners: /* @__PURE__ */ new Set()
165
166
  });
166
167
  }
167
168
  __name(getFarmCacheInvalidationState, "getFarmCacheInvalidationState");
@@ -191,6 +192,12 @@ function subscribeFarmCacheInvalidation(listener) {
191
192
  return () => state.listeners.delete(listener);
192
193
  }
193
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");
194
201
 
195
202
  // src/i18n/bridge.ts
196
203
  var FARM_I18N_SNAPSHOT_RESOLVER = /* @__PURE__ */ Symbol.for("farm.i18n.snapshotResolver");
@@ -201,11 +208,51 @@ __name(_setFarmI18nSnapshotResolver, "_setFarmI18nSnapshotResolver");
201
208
 
202
209
  // src/cache.ts
203
210
  var _FarmDataCache = class _FarmDataCache {
204
- constructor() {
211
+ constructor(config = {}) {
205
212
  this.entries = /* @__PURE__ */ new Map();
206
213
  this.inflight = /* @__PURE__ */ new Map();
207
214
  this.invalidatedTagVersions = /* @__PURE__ */ new Map();
208
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;
209
256
  }
210
257
  get size() {
211
258
  return this.entries.size;
@@ -241,6 +288,45 @@ var _FarmDataCache = class _FarmDataCache {
241
288
  });
242
289
  return this.toPublicEntry(entry);
243
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
+ }
244
330
  set(key, value, options = {}) {
245
331
  const tags = /* @__PURE__ */ new Set();
246
332
  for (const tag of options.tags ?? []) {
@@ -253,6 +339,7 @@ var _FarmDataCache = class _FarmDataCache {
253
339
  key,
254
340
  value,
255
341
  tags,
342
+ tagVersions: void 0,
256
343
  createdAt: options.createdAt ?? Date.now(),
257
344
  createdVersion: ++this.version,
258
345
  revalidate: normalizeRevalidate(options.revalidate)
@@ -266,11 +353,45 @@ var _FarmDataCache = class _FarmDataCache {
266
353
  });
267
354
  return this.toPublicEntry(entry);
268
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
+ }
269
382
  delete(key) {
270
383
  const deleted = this.entries.delete(key);
271
384
  emitFarmEvent({ type: "cache.delete", key, deleted });
272
385
  return deleted;
273
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
+ }
274
395
  clear() {
275
396
  const count = this.entries.size;
276
397
  this.entries.clear();
@@ -279,6 +400,10 @@ var _FarmDataCache = class _FarmDataCache {
279
400
  this.version = 0;
280
401
  emitFarmEvent({ type: "cache.clear", count });
281
402
  }
403
+ async clearAsync() {
404
+ this.clear();
405
+ await this.adapter?.clear?.();
406
+ }
282
407
  isStale(entry, now = Date.now()) {
283
408
  if (typeof entry.revalidate === "number" && entry.revalidate > 0 && now - entry.createdAt >= entry.revalidate * 1e3) {
284
409
  return true;
@@ -291,6 +416,12 @@ var _FarmDataCache = class _FarmDataCache {
291
416
  }
292
417
  return false;
293
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
+ }
294
425
  revalidateTag(tag, options = {}) {
295
426
  const normalized = normalizeCacheTag(tag);
296
427
  const count = this.invalidateTag(normalized);
@@ -299,6 +430,15 @@ var _FarmDataCache = class _FarmDataCache {
299
430
  );
300
431
  return count;
301
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
+ }
302
442
  revalidatePath(routePath) {
303
443
  const normalizedPath = normalizeRevalidatePath(routePath);
304
444
  const pathTag = createPathCacheTag(normalizedPath);
@@ -315,8 +455,25 @@ var _FarmDataCache = class _FarmDataCache {
315
455
  }
316
456
  return count;
317
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
+ }
318
475
  async getOrSet(key, producer, options = {}) {
319
- const cached = this.getEntry(key);
476
+ const cached = await this.getEntryAsync(key);
320
477
  if (cached) {
321
478
  return cached.value;
322
479
  }
@@ -325,10 +482,8 @@ var _FarmDataCache = class _FarmDataCache {
325
482
  emitFarmEvent({ type: "cache.dedupe", key });
326
483
  return inflight;
327
484
  }
328
- const promise = Promise.resolve().then(producer).then((value) => {
329
- this.set(key, value, options);
330
- return value;
331
- }).catch((error) => {
485
+ const tags = Array.from(normalizeCacheOptionsTags(options));
486
+ const promise = this.fillCacheEntry(key, producer, options, tags).catch((error) => {
332
487
  emitFarmEvent({ type: "cache.error", key, operation: "set", error });
333
488
  throw error;
334
489
  }).finally(() => {
@@ -337,6 +492,40 @@ var _FarmDataCache = class _FarmDataCache {
337
492
  this.inflight.set(key, promise);
338
493
  return promise;
339
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
+ }
340
529
  countEntriesForTag(tag) {
341
530
  let count = 0;
342
531
  for (const entry of this.entries.values()) {
@@ -364,11 +553,53 @@ var _FarmDataCache = class _FarmDataCache {
364
553
  key: entry.key,
365
554
  value: entry.value,
366
555
  tags: Array.from(entry.tags),
556
+ tagVersions: entry.tagVersions,
367
557
  createdAt: entry.createdAt,
368
558
  createdVersion: entry.createdVersion,
369
559
  revalidate: entry.revalidate
370
560
  };
371
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
+ }
372
603
  };
373
604
  __name(_FarmDataCache, "FarmDataCache");
374
605
  var FarmDataCache = _FarmDataCache;
@@ -441,6 +672,52 @@ function normalizeCacheTag(tag) {
441
672
  return normalized;
442
673
  }
443
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");
444
721
  function getFunctionCacheIdentity(fn) {
445
722
  if (fn.name) {
446
723
  return `name:${fn.name}`;
@@ -1281,7 +1558,7 @@ async function invokeAPIRouteEndpointInContext(endpoint, request, params) {
1281
1558
  });
1282
1559
  let body = void 0;
1283
1560
  if (request.method.toUpperCase() !== "GET" && request.method.toUpperCase() !== "HEAD") {
1284
- body = await readJSONBody(request);
1561
+ body = await readRequestBody(request);
1285
1562
  }
1286
1563
  const headers = Object.fromEntries(request.headers.entries());
1287
1564
  const types = endpoint.__types || {};
@@ -1385,17 +1662,50 @@ function isFarmContextHandler(endpoint) {
1385
1662
  return firstParameter === "ctx" || firstParameter === "context" || firstParameter.startsWith("{");
1386
1663
  }
1387
1664
  __name(isFarmContextHandler, "isFarmContextHandler");
1388
- async function readJSONBody(request) {
1665
+ async function readRequestBody(request) {
1666
+ const contentType = request.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
1389
1667
  try {
1668
+ if (contentType === "multipart/form-data") {
1669
+ return formDataToObject(await request.clone().formData());
1670
+ }
1390
1671
  const text = await request.clone().text();
1391
- 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")) {
1392
1677
  return JSON.parse(text);
1393
1678
  }
1679
+ return JSON.parse(text);
1394
1680
  } catch {
1395
1681
  }
1396
1682
  return void 0;
1397
1683
  }
1398
- __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");
1399
1709
  function validateInput(schema, value, error) {
1400
1710
  if (!schema || typeof schema.parse !== "function") {
1401
1711
  return value;
@@ -1649,16 +1959,24 @@ __name(createSearchParams2, "createSearchParams");
1649
1959
  // src/server-action-security.ts
1650
1960
  var import_node_async_hooks3 = require("async_hooks");
1651
1961
  var SERVER_ACTION_STORAGE_KEY = /* @__PURE__ */ Symbol.for("farm.serverActionStorage");
1652
- function runWithServerActionRequest(request, callback) {
1962
+ async function runWithServerActionRequest(request, callback) {
1653
1963
  throwIfAborted(request.signal);
1654
- return getServerActionStorage().run(
1655
- {
1656
- request,
1657
- signal: request.signal,
1658
- invalidations: /* @__PURE__ */ new Set()
1659
- },
1660
- callback
1661
- );
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
+ });
1662
1980
  }
1663
1981
  __name(runWithServerActionRequest, "runWithServerActionRequest");
1664
1982
  function getServerActionExecutionContext() {
@@ -1668,6 +1986,9 @@ __name(getServerActionExecutionContext, "getServerActionExecutionContext");
1668
1986
  subscribeFarmCacheInvalidation((key) => {
1669
1987
  getServerActionExecutionContext()?.invalidations.add(key);
1670
1988
  });
1989
+ subscribeFarmCacheTask((task) => {
1990
+ getServerActionExecutionContext()?.cacheTasks.add(task);
1991
+ });
1671
1992
  function getServerActionStorage() {
1672
1993
  const globalState2 = globalThis;
1673
1994
  if (!globalState2[SERVER_ACTION_STORAGE_KEY]) {