@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
@@ -146,24 +146,84 @@ var FARM_CACHE_INVALIDATION_STATE = /* @__PURE__ */ Symbol.for("farm.cacheInvali
146
146
  var globalState = globalThis;
147
147
  function getFarmCacheInvalidationState() {
148
148
  return globalState[FARM_CACHE_INVALIDATION_STATE] ?? (globalState[FARM_CACHE_INVALIDATION_STATE] = {
149
- listeners: /* @__PURE__ */ new Set()
149
+ listeners: /* @__PURE__ */ new Set(),
150
+ taskListeners: /* @__PURE__ */ new Set()
150
151
  });
151
152
  }
152
153
  __name(getFarmCacheInvalidationState, "getFarmCacheInvalidationState");
154
+ function notifyFarmCacheInvalidation(key) {
155
+ if (typeof key !== "string" || key.length === 0) return;
156
+ for (const listener of getFarmCacheInvalidationState().listeners) {
157
+ listener(key);
158
+ }
159
+ }
160
+ __name(notifyFarmCacheInvalidation, "notifyFarmCacheInvalidation");
161
+ function notifyFarmCacheTask(task) {
162
+ for (const listener of getFarmCacheInvalidationState().taskListeners) {
163
+ listener(task);
164
+ }
165
+ }
166
+ __name(notifyFarmCacheTask, "notifyFarmCacheTask");
153
167
  function subscribeFarmCacheInvalidation(listener) {
154
168
  const state = getFarmCacheInvalidationState();
155
169
  state.listeners.add(listener);
156
170
  return () => state.listeners.delete(listener);
157
171
  }
158
172
  __name(subscribeFarmCacheInvalidation, "subscribeFarmCacheInvalidation");
173
+ function subscribeFarmCacheTask(listener) {
174
+ const state = getFarmCacheInvalidationState();
175
+ state.taskListeners.add(listener);
176
+ return () => state.taskListeners.delete(listener);
177
+ }
178
+ __name(subscribeFarmCacheTask, "subscribeFarmCacheTask");
159
179
 
160
180
  // src/cache.ts
161
181
  var _FarmDataCache = class _FarmDataCache {
162
- constructor() {
182
+ constructor(config = {}) {
163
183
  this.entries = /* @__PURE__ */ new Map();
164
184
  this.inflight = /* @__PURE__ */ new Map();
165
185
  this.invalidatedTagVersions = /* @__PURE__ */ new Map();
166
186
  this.version = 0;
187
+ this.namespace = "farm";
188
+ this.local = true;
189
+ this.lease = {
190
+ enabled: true,
191
+ ttlMs: 1e4,
192
+ waitTimeoutMs: 1e4,
193
+ pollIntervalMs: 25
194
+ };
195
+ this.configure(config);
196
+ }
197
+ configure(config = {}) {
198
+ this.adapter = config.adapter;
199
+ this.namespace = normalizeCacheNamespace(config.namespace || "farm");
200
+ this.local = !config.adapter;
201
+ this.lease = config.lease === false ? { ...this.lease, enabled: false } : {
202
+ enabled: true,
203
+ ttlMs: normalizePositiveDuration(config.lease?.ttlMs, 1e4, "cache.lease.ttlMs"),
204
+ waitTimeoutMs: normalizePositiveDuration(
205
+ config.lease?.waitTimeoutMs,
206
+ 1e4,
207
+ "cache.lease.waitTimeoutMs"
208
+ ),
209
+ pollIntervalMs: normalizePositiveDuration(
210
+ config.lease?.pollIntervalMs,
211
+ 25,
212
+ "cache.lease.pollIntervalMs"
213
+ )
214
+ };
215
+ if (!this.local) {
216
+ this.entries.clear();
217
+ this.inflight.clear();
218
+ this.invalidatedTagVersions.clear();
219
+ this.version = 0;
220
+ }
221
+ }
222
+ get adapterName() {
223
+ return this.adapter?.name || (this.adapter ? "custom" : "memory");
224
+ }
225
+ get hasAdapter() {
226
+ return this.adapter !== void 0;
167
227
  }
168
228
  get size() {
169
229
  return this.entries.size;
@@ -199,6 +259,45 @@ var _FarmDataCache = class _FarmDataCache {
199
259
  });
200
260
  return this.toPublicEntry(entry);
201
261
  }
262
+ async getEntryAsync(key, options = {}) {
263
+ if (this.local) {
264
+ const localEntry = this.getEntry(key, options);
265
+ if (localEntry) return localEntry;
266
+ }
267
+ if (!this.adapter) {
268
+ return this.local ? void 0 : this.getEntry(key, options);
269
+ }
270
+ const entry = await this.adapter.get(this.createAdapterKey(key));
271
+ if (!entry) {
272
+ emitFarmEvent({ type: "cache.miss", key });
273
+ return void 0;
274
+ }
275
+ assertFarmCacheEntry(entry, key);
276
+ const stale = await this.isAdapterEntryStale(entry, options.now);
277
+ if (stale) {
278
+ emitFarmEvent({
279
+ type: "cache.stale",
280
+ key,
281
+ tags: [...entry.tags],
282
+ revalidate: entry.revalidate
283
+ });
284
+ if (!options.allowStale) {
285
+ emitFarmEvent({ type: "cache.miss", key, reason: "stale" });
286
+ return void 0;
287
+ }
288
+ }
289
+ emitFarmEvent({
290
+ type: "cache.hit",
291
+ key,
292
+ tags: [...entry.tags],
293
+ revalidate: entry.revalidate,
294
+ stale
295
+ });
296
+ if (this.local && !stale) {
297
+ this.hydrateLocalEntry(entry);
298
+ }
299
+ return { ...entry, key };
300
+ }
202
301
  set(key, value, options = {}) {
203
302
  const tags = /* @__PURE__ */ new Set();
204
303
  for (const tag of options.tags ?? []) {
@@ -211,6 +310,7 @@ var _FarmDataCache = class _FarmDataCache {
211
310
  key,
212
311
  value,
213
312
  tags,
313
+ tagVersions: void 0,
214
314
  createdAt: options.createdAt ?? Date.now(),
215
315
  createdVersion: ++this.version,
216
316
  revalidate: normalizeRevalidate(options.revalidate)
@@ -224,11 +324,45 @@ var _FarmDataCache = class _FarmDataCache {
224
324
  });
225
325
  return this.toPublicEntry(entry);
226
326
  }
327
+ async setAsync(key, value, options = {}, tagVersions) {
328
+ const tags = normalizeCacheOptionsTags(options);
329
+ const capturedVersions = tagVersions ?? await this.getAdapterTagVersions(Array.from(tags.values()));
330
+ const entry = {
331
+ key,
332
+ value,
333
+ tags: Array.from(tags),
334
+ tagVersions: capturedVersions,
335
+ createdAt: options.createdAt ?? Date.now(),
336
+ createdVersion: ++this.version,
337
+ revalidate: normalizeRevalidate(options.revalidate)
338
+ };
339
+ if (this.local) {
340
+ this.hydrateLocalEntry(entry);
341
+ }
342
+ if (this.adapter) {
343
+ await this.adapter.set(this.createAdapterKey(key), entry);
344
+ }
345
+ emitFarmEvent({
346
+ type: "cache.set",
347
+ key,
348
+ tags: [...entry.tags],
349
+ revalidate: entry.revalidate
350
+ });
351
+ return entry;
352
+ }
227
353
  delete(key) {
228
354
  const deleted = this.entries.delete(key);
229
355
  emitFarmEvent({ type: "cache.delete", key, deleted });
230
356
  return deleted;
231
357
  }
358
+ async deleteAsync(key) {
359
+ const deleted = this.entries.delete(key);
360
+ if (this.adapter) {
361
+ await this.adapter.delete(this.createAdapterKey(key));
362
+ }
363
+ emitFarmEvent({ type: "cache.delete", key, deleted: this.adapter ? true : deleted });
364
+ return this.adapter ? true : deleted;
365
+ }
232
366
  clear() {
233
367
  const count = this.entries.size;
234
368
  this.entries.clear();
@@ -237,6 +371,10 @@ var _FarmDataCache = class _FarmDataCache {
237
371
  this.version = 0;
238
372
  emitFarmEvent({ type: "cache.clear", count });
239
373
  }
374
+ async clearAsync() {
375
+ this.clear();
376
+ await this.adapter?.clear?.();
377
+ }
240
378
  isStale(entry, now = Date.now()) {
241
379
  if (typeof entry.revalidate === "number" && entry.revalidate > 0 && now - entry.createdAt >= entry.revalidate * 1e3) {
242
380
  return true;
@@ -249,6 +387,12 @@ var _FarmDataCache = class _FarmDataCache {
249
387
  }
250
388
  return false;
251
389
  }
390
+ async isStaleAsync(entry, now = Date.now()) {
391
+ if (this.adapter) {
392
+ return this.isAdapterEntryStale(entry, now);
393
+ }
394
+ return this.isStale(entry, now);
395
+ }
252
396
  revalidateTag(tag, options = {}) {
253
397
  const normalized = normalizeCacheTag(tag);
254
398
  const count = this.invalidateTag(normalized);
@@ -257,6 +401,15 @@ var _FarmDataCache = class _FarmDataCache {
257
401
  );
258
402
  return count;
259
403
  }
404
+ async revalidateTagAsync(tag, options = {}) {
405
+ const normalized = normalizeCacheTag(tag);
406
+ const count = this.invalidateTag(normalized);
407
+ await this.adapter?.invalidateTags?.([this.createAdapterTag(normalized)]);
408
+ emitFarmEvent(
409
+ options.source === "updateTag" ? { type: "cache.updateTag", tag: normalized, count } : { type: "cache.revalidateTag", tag: normalized, profile: options.profile, count }
410
+ );
411
+ return count;
412
+ }
260
413
  revalidatePath(routePath) {
261
414
  const normalizedPath = normalizeRevalidatePath(routePath);
262
415
  const pathTag = createPathCacheTag(normalizedPath);
@@ -273,8 +426,25 @@ var _FarmDataCache = class _FarmDataCache {
273
426
  }
274
427
  return count;
275
428
  }
429
+ async revalidatePathAsync(routePath) {
430
+ const normalizedPath = normalizeRevalidatePath(routePath);
431
+ const pathTag = createPathCacheTag(normalizedPath);
432
+ const pprCount = this.countEntriesForTags([pathTag, "ppr"]);
433
+ const count = this.invalidateTag(pathTag);
434
+ await this.adapter?.invalidateTags?.([this.createAdapterTag(pathTag)]);
435
+ emitFarmEvent({ type: "cache.revalidatePath", path: normalizedPath, count });
436
+ if (pprCount > 0) {
437
+ emitFarmEvent({
438
+ type: "ppr.shell.invalidated",
439
+ route: normalizedPath,
440
+ reason: "revalidatePath",
441
+ count: pprCount
442
+ });
443
+ }
444
+ return count;
445
+ }
276
446
  async getOrSet(key, producer, options = {}) {
277
- const cached = this.getEntry(key);
447
+ const cached = await this.getEntryAsync(key);
278
448
  if (cached) {
279
449
  return cached.value;
280
450
  }
@@ -283,10 +453,8 @@ var _FarmDataCache = class _FarmDataCache {
283
453
  emitFarmEvent({ type: "cache.dedupe", key });
284
454
  return inflight;
285
455
  }
286
- const promise = Promise.resolve().then(producer).then((value) => {
287
- this.set(key, value, options);
288
- return value;
289
- }).catch((error) => {
456
+ const tags = Array.from(normalizeCacheOptionsTags(options));
457
+ const promise = this.fillCacheEntry(key, producer, options, tags).catch((error) => {
290
458
  emitFarmEvent({ type: "cache.error", key, operation: "set", error });
291
459
  throw error;
292
460
  }).finally(() => {
@@ -295,6 +463,40 @@ var _FarmDataCache = class _FarmDataCache {
295
463
  this.inflight.set(key, promise);
296
464
  return promise;
297
465
  }
466
+ async fillCacheEntry(key, producer, options, tags) {
467
+ const leaseKey = `${this.namespace}:lease:${key}`;
468
+ let leaseToken;
469
+ if (this.adapter?.acquireLease && this.adapter.releaseLease && this.lease.enabled) {
470
+ leaseToken = await this.adapter.acquireLease(leaseKey, this.lease.ttlMs);
471
+ if (!leaseToken) {
472
+ const shared = await this.waitForAdapterEntry(key);
473
+ if (shared) {
474
+ emitFarmEvent({ type: "cache.dedupe", key });
475
+ return shared.value;
476
+ }
477
+ leaseToken = await this.adapter.acquireLease(leaseKey, this.lease.ttlMs);
478
+ }
479
+ }
480
+ try {
481
+ const initialTagVersions = await this.getAdapterTagVersions(tags);
482
+ const value = await producer();
483
+ await this.setAsync(key, value, options, initialTagVersions);
484
+ return value;
485
+ } finally {
486
+ if (leaseToken && this.adapter?.releaseLease) {
487
+ await this.adapter.releaseLease(leaseKey, leaseToken);
488
+ }
489
+ }
490
+ }
491
+ async waitForAdapterEntry(key) {
492
+ const deadline = Date.now() + this.lease.waitTimeoutMs;
493
+ while (Date.now() < deadline) {
494
+ await delay(this.lease.pollIntervalMs);
495
+ const entry = await this.getEntryAsync(key);
496
+ if (entry) return entry;
497
+ }
498
+ return void 0;
499
+ }
298
500
  countEntriesForTag(tag) {
299
501
  let count = 0;
300
502
  for (const entry of this.entries.values()) {
@@ -322,11 +524,53 @@ var _FarmDataCache = class _FarmDataCache {
322
524
  key: entry.key,
323
525
  value: entry.value,
324
526
  tags: Array.from(entry.tags),
527
+ tagVersions: entry.tagVersions,
325
528
  createdAt: entry.createdAt,
326
529
  createdVersion: entry.createdVersion,
327
530
  revalidate: entry.revalidate
328
531
  };
329
532
  }
533
+ hydrateLocalEntry(entry) {
534
+ this.entries.set(entry.key, {
535
+ key: entry.key,
536
+ value: entry.value,
537
+ tags: new Set(entry.tags.map(normalizeCacheTag)),
538
+ tagVersions: entry.tagVersions,
539
+ createdAt: entry.createdAt,
540
+ createdVersion: entry.createdVersion ?? ++this.version,
541
+ revalidate: normalizeRevalidate(entry.revalidate)
542
+ });
543
+ }
544
+ createAdapterKey(key) {
545
+ return `${this.namespace}:entry:${key}`;
546
+ }
547
+ createAdapterTag(tag) {
548
+ return `${this.namespace}:tag:${tag}`;
549
+ }
550
+ async getAdapterTagVersions(tags) {
551
+ if (!this.adapter?.getTagVersions || tags.length === 0) return {};
552
+ const normalized = tags.map(normalizeCacheTag);
553
+ const physicalTags = normalized.map((tag) => this.createAdapterTag(tag));
554
+ const versions = await this.adapter.getTagVersions(physicalTags);
555
+ return Object.fromEntries(
556
+ normalized.map((tag, index) => [
557
+ tag,
558
+ normalizeAdapterVersion(versions[physicalTags[index]])
559
+ ])
560
+ );
561
+ }
562
+ async isAdapterEntryStale(entry, now = Date.now()) {
563
+ if (typeof entry.revalidate === "number" && entry.revalidate > 0 && now - entry.createdAt >= entry.revalidate * 1e3) {
564
+ return true;
565
+ }
566
+ const currentVersions = await this.getAdapterTagVersions(entry.tags);
567
+ for (const tag of entry.tags) {
568
+ if (normalizeAdapterVersion(currentVersions[tag]) > normalizeAdapterVersion(entry.tagVersions?.[tag])) {
569
+ return true;
570
+ }
571
+ }
572
+ return false;
573
+ }
330
574
  };
331
575
  __name(_FarmDataCache, "FarmDataCache");
332
576
  var FarmDataCache = _FarmDataCache;
@@ -339,6 +583,52 @@ function getFarmDataCache() {
339
583
  return sharedFarmDataCache;
340
584
  }
341
585
  __name(getFarmDataCache, "getFarmDataCache");
586
+ function updateTag(tag) {
587
+ const cache = getFarmDataCache();
588
+ if (cache.hasAdapter) {
589
+ const task = cache.revalidateTagAsync(tag, { source: "updateTag" }).then(() => void 0);
590
+ notifyFarmCacheTask(task);
591
+ return task;
592
+ }
593
+ cache.revalidateTag(tag, { source: "updateTag" });
594
+ }
595
+ __name(updateTag, "updateTag");
596
+ function revalidatePath(routePath) {
597
+ const cache = getFarmDataCache();
598
+ if (cache.hasAdapter) {
599
+ const task = cache.revalidatePathAsync(routePath).then(() => void 0);
600
+ notifyFarmCacheTask(task);
601
+ return task;
602
+ }
603
+ cache.revalidatePath(routePath);
604
+ }
605
+ __name(revalidatePath, "revalidatePath");
606
+ function invalidate(key) {
607
+ const clientKey = createRouteDataCacheKey(key);
608
+ const task = updateTag(createRouteDataCacheTag(key));
609
+ notifyFarmCacheInvalidation(clientKey);
610
+ return task;
611
+ }
612
+ __name(invalidate, "invalidate");
613
+ async function applyFarmCacheInvalidationTargets(targets) {
614
+ if (!Array.isArray(targets)) {
615
+ throw new TypeError("Cache invalidations must resolve to an array of targets.");
616
+ }
617
+ const clientKeys = [];
618
+ for (const target of targets) {
619
+ assertFarmCacheInvalidationTarget(target);
620
+ if ("key" in target) {
621
+ await invalidate(target.key);
622
+ clientKeys.push(createRouteDataCacheKey(target.key));
623
+ } else if ("path" in target) {
624
+ await revalidatePath(target.path);
625
+ } else {
626
+ await updateTag(target.tag);
627
+ }
628
+ }
629
+ return Array.from(new Set(clientKeys));
630
+ }
631
+ __name(applyFarmCacheInvalidationTargets, "applyFarmCacheInvalidationTargets");
342
632
  function createPathCacheTag(routePath) {
343
633
  return `path:${normalizeRevalidatePath(routePath)}`;
344
634
  }
@@ -399,6 +689,67 @@ function normalizeCacheTag(tag) {
399
689
  return normalized;
400
690
  }
401
691
  __name(normalizeCacheTag, "normalizeCacheTag");
692
+ function normalizeCacheNamespace(namespace) {
693
+ if (typeof namespace !== "string") {
694
+ throw new TypeError("Cache namespace must be a string.");
695
+ }
696
+ const normalized = namespace.trim().replace(/:+$/g, "");
697
+ if (!normalized) {
698
+ throw new Error("Cache namespace cannot be empty.");
699
+ }
700
+ return normalized;
701
+ }
702
+ __name(normalizeCacheNamespace, "normalizeCacheNamespace");
703
+ function normalizeAdapterVersion(value) {
704
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
705
+ }
706
+ __name(normalizeAdapterVersion, "normalizeAdapterVersion");
707
+ function normalizePositiveDuration(value, fallback, name) {
708
+ if (value === void 0) return fallback;
709
+ if (!Number.isFinite(value) || value <= 0) {
710
+ throw new TypeError(`${name} must be a positive number of milliseconds.`);
711
+ }
712
+ return Math.floor(value);
713
+ }
714
+ __name(normalizePositiveDuration, "normalizePositiveDuration");
715
+ function delay(ms) {
716
+ return new Promise((resolve) => setTimeout(resolve, ms));
717
+ }
718
+ __name(delay, "delay");
719
+ function normalizeCacheOptionsTags(options) {
720
+ const tags = /* @__PURE__ */ new Set();
721
+ for (const tag of options.tags ?? []) {
722
+ tags.add(normalizeCacheTag(tag));
723
+ }
724
+ for (const routePath of options.paths ?? []) {
725
+ tags.add(createPathCacheTag(routePath));
726
+ }
727
+ return tags;
728
+ }
729
+ __name(normalizeCacheOptionsTags, "normalizeCacheOptionsTags");
730
+ function assertFarmCacheEntry(entry, expectedKey) {
731
+ if (!entry || typeof entry !== "object" || entry.key !== expectedKey || !Array.isArray(entry.tags) || typeof entry.createdAt !== "number") {
732
+ throw new TypeError(
733
+ `Cache adapter returned an invalid entry for ${JSON.stringify(expectedKey)}.`
734
+ );
735
+ }
736
+ }
737
+ __name(assertFarmCacheEntry, "assertFarmCacheEntry");
738
+ function assertFarmCacheInvalidationTarget(target) {
739
+ if (!target || typeof target !== "object") {
740
+ throw new TypeError("Cache invalidation targets must be { key }, { path }, or { tag }.");
741
+ }
742
+ if ("key" in target) {
743
+ const key = target.key;
744
+ if (typeof key === "string" || Array.isArray(key)) return;
745
+ } else if ("path" in target && typeof target.path === "string") {
746
+ return;
747
+ } else if ("tag" in target && typeof target.tag === "string") {
748
+ return;
749
+ }
750
+ throw new TypeError("Cache invalidation targets must contain a string/array key, path, or tag.");
751
+ }
752
+ __name(assertFarmCacheInvalidationTarget, "assertFarmCacheInvalidationTarget");
402
753
  function getFunctionCacheIdentity(fn) {
403
754
  if (fn.name) {
404
755
  return `name:${fn.name}`;
@@ -468,6 +819,9 @@ __name(getServerActionSignal, "getServerActionSignal");
468
819
  subscribeFarmCacheInvalidation((key) => {
469
820
  getServerActionExecutionContext()?.invalidations.add(key);
470
821
  });
822
+ subscribeFarmCacheTask((task) => {
823
+ getServerActionExecutionContext()?.cacheTasks.add(task);
824
+ });
471
825
  function getServerActionStorage() {
472
826
  const globalState2 = globalThis;
473
827
  if (!globalState2[SERVER_ACTION_STORAGE_KEY]) {
@@ -518,8 +872,21 @@ function createServerFn(options) {
518
872
  request,
519
873
  signal
520
874
  };
521
- const result = await runServerFnMiddleware(middleware, handlerContext, options.handler);
522
- return _parseServerFnSchema(options.output, result, "output");
875
+ let resolvedContext = Object.freeze(/* @__PURE__ */ Object.create(null));
876
+ const result = await runServerFnMiddleware(middleware, handlerContext, async (context) => {
877
+ resolvedContext = context.context;
878
+ return options.handler(context);
879
+ });
880
+ const parsedResult = await _parseServerFnSchema(options.output, result, "output");
881
+ if (options.invalidates) {
882
+ const declaration = typeof options.invalidates === "function" ? await options.invalidates({
883
+ ...handlerContext,
884
+ context: resolvedContext,
885
+ result: parsedResult
886
+ }) : options.invalidates;
887
+ await applyFarmCacheInvalidationTargets(declaration);
888
+ }
889
+ return parsedResult;
523
890
  }, "serverFn");
524
891
  Object.defineProperties(serverFn, {
525
892
  [FARM_SERVER_FN_SYMBOL]: {
@@ -541,6 +908,10 @@ function createServerFn(options) {
541
908
  __farmServerFnMiddleware: {
542
909
  value: middleware,
543
910
  enumerable: false
911
+ },
912
+ __farmServerFnInvalidates: {
913
+ value: options.invalidates,
914
+ enumerable: false
544
915
  }
545
916
  });
546
917
  return serverFn;
@@ -715,7 +1086,7 @@ function createServerQuery(options) {
715
1086
  tags: [createRouteDataCacheTag(routeKey)],
716
1087
  revalidate: staleTime === false ? false : Math.max(1, Math.ceil(staleTime / 1e3))
717
1088
  });
718
- updatedAt = cache.getEntry(cacheKey, { allowStale: true })?.createdAt ?? Date.now();
1089
+ updatedAt = (await cache.getEntryAsync(cacheKey, { allowStale: true }))?.createdAt ?? Date.now();
719
1090
  }
720
1091
  return createFarmServerQueryResult(data, {
721
1092
  key: clientKey,