@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/api.cjs CHANGED
@@ -36,6 +36,7 @@ __export(api_exports, {
36
36
  API_ROUTE_METHODS: () => API_ROUTE_METHODS,
37
37
  DELETE: () => DELETE,
38
38
  EndpointFailure: () => EndpointFailure,
39
+ FARM_API_ROUTE_META_SYMBOL: () => FARM_API_ROUTE_META_SYMBOL,
39
40
  FARM_API_ROUTE_REF_SYMBOL: () => FARM_API_ROUTE_REF_SYMBOL,
40
41
  GET: () => GET,
41
42
  HEAD: () => HEAD,
@@ -47,12 +48,20 @@ __export(api_exports, {
47
48
  createEndpoint: () => createEndpoint,
48
49
  createServerAPIClient: () => createServerAPIClient,
49
50
  farmApiPlugin: () => farmApiPlugin,
51
+ getAPIRouteRefMetadata: () => getAPIRouteRefMetadata,
50
52
  invokeAPIRouteEndpoint: () => invokeAPIRouteEndpoint,
51
53
  isAPIRouteRef: () => isAPIRouteRef,
52
54
  isEndpointFailure: () => isEndpointFailure,
55
+ isFarmAPIStream: () => isFarmAPIStream,
56
+ isJSONStreamResponse: () => isJSONStreamResponse,
57
+ isMultipartSchema: () => isMultipartSchema,
53
58
  isWebResponse: () => isWebResponse,
59
+ jsonStream: () => jsonStream,
54
60
  matchAPIRoute: () => matchAPIRoute,
55
- normalizeRouteResponse: () => normalizeRouteResponse
61
+ multipart: () => multipart,
62
+ normalizeRouteResponse: () => normalizeRouteResponse,
63
+ readJSONStream: () => readJSONStream,
64
+ toFormData: () => toFormData
56
65
  });
57
66
  module.exports = __toCommonJS(api_exports);
58
67
 
@@ -180,7 +189,8 @@ var FARM_CACHE_INVALIDATION_STATE = /* @__PURE__ */ Symbol.for("farm.cacheInvali
180
189
  var globalState = globalThis;
181
190
  function getFarmCacheInvalidationState() {
182
191
  return globalState[FARM_CACHE_INVALIDATION_STATE] ?? (globalState[FARM_CACHE_INVALIDATION_STATE] = {
183
- listeners: /* @__PURE__ */ new Set()
192
+ listeners: /* @__PURE__ */ new Set(),
193
+ taskListeners: /* @__PURE__ */ new Set()
184
194
  });
185
195
  }
186
196
  __name(getFarmCacheInvalidationState, "getFarmCacheInvalidationState");
@@ -191,6 +201,12 @@ function notifyFarmCacheInvalidation(key) {
191
201
  }
192
202
  }
193
203
  __name(notifyFarmCacheInvalidation, "notifyFarmCacheInvalidation");
204
+ function notifyFarmCacheTask(task) {
205
+ for (const listener of getFarmCacheInvalidationState().taskListeners) {
206
+ listener(task);
207
+ }
208
+ }
209
+ __name(notifyFarmCacheTask, "notifyFarmCacheTask");
194
210
  function applyFarmCacheInvalidations(keys) {
195
211
  if (!Array.isArray(keys)) return;
196
212
  for (const key of keys) {
@@ -236,11 +252,51 @@ __name(_setFarmI18nSnapshotResolver, "_setFarmI18nSnapshotResolver");
236
252
 
237
253
  // src/cache.ts
238
254
  var _FarmDataCache = class _FarmDataCache {
239
- constructor() {
255
+ constructor(config = {}) {
240
256
  this.entries = /* @__PURE__ */ new Map();
241
257
  this.inflight = /* @__PURE__ */ new Map();
242
258
  this.invalidatedTagVersions = /* @__PURE__ */ new Map();
243
259
  this.version = 0;
260
+ this.namespace = "farm";
261
+ this.local = true;
262
+ this.lease = {
263
+ enabled: true,
264
+ ttlMs: 1e4,
265
+ waitTimeoutMs: 1e4,
266
+ pollIntervalMs: 25
267
+ };
268
+ this.configure(config);
269
+ }
270
+ configure(config = {}) {
271
+ this.adapter = config.adapter;
272
+ this.namespace = normalizeCacheNamespace(config.namespace || "farm");
273
+ this.local = !config.adapter;
274
+ this.lease = config.lease === false ? { ...this.lease, enabled: false } : {
275
+ enabled: true,
276
+ ttlMs: normalizePositiveDuration(config.lease?.ttlMs, 1e4, "cache.lease.ttlMs"),
277
+ waitTimeoutMs: normalizePositiveDuration(
278
+ config.lease?.waitTimeoutMs,
279
+ 1e4,
280
+ "cache.lease.waitTimeoutMs"
281
+ ),
282
+ pollIntervalMs: normalizePositiveDuration(
283
+ config.lease?.pollIntervalMs,
284
+ 25,
285
+ "cache.lease.pollIntervalMs"
286
+ )
287
+ };
288
+ if (!this.local) {
289
+ this.entries.clear();
290
+ this.inflight.clear();
291
+ this.invalidatedTagVersions.clear();
292
+ this.version = 0;
293
+ }
294
+ }
295
+ get adapterName() {
296
+ return this.adapter?.name || (this.adapter ? "custom" : "memory");
297
+ }
298
+ get hasAdapter() {
299
+ return this.adapter !== void 0;
244
300
  }
245
301
  get size() {
246
302
  return this.entries.size;
@@ -276,6 +332,45 @@ var _FarmDataCache = class _FarmDataCache {
276
332
  });
277
333
  return this.toPublicEntry(entry);
278
334
  }
335
+ async getEntryAsync(key, options = {}) {
336
+ if (this.local) {
337
+ const localEntry = this.getEntry(key, options);
338
+ if (localEntry) return localEntry;
339
+ }
340
+ if (!this.adapter) {
341
+ return this.local ? void 0 : this.getEntry(key, options);
342
+ }
343
+ const entry = await this.adapter.get(this.createAdapterKey(key));
344
+ if (!entry) {
345
+ emitFarmEvent({ type: "cache.miss", key });
346
+ return void 0;
347
+ }
348
+ assertFarmCacheEntry(entry, key);
349
+ const stale = await this.isAdapterEntryStale(entry, options.now);
350
+ if (stale) {
351
+ emitFarmEvent({
352
+ type: "cache.stale",
353
+ key,
354
+ tags: [...entry.tags],
355
+ revalidate: entry.revalidate
356
+ });
357
+ if (!options.allowStale) {
358
+ emitFarmEvent({ type: "cache.miss", key, reason: "stale" });
359
+ return void 0;
360
+ }
361
+ }
362
+ emitFarmEvent({
363
+ type: "cache.hit",
364
+ key,
365
+ tags: [...entry.tags],
366
+ revalidate: entry.revalidate,
367
+ stale
368
+ });
369
+ if (this.local && !stale) {
370
+ this.hydrateLocalEntry(entry);
371
+ }
372
+ return { ...entry, key };
373
+ }
279
374
  set(key, value, options = {}) {
280
375
  const tags = /* @__PURE__ */ new Set();
281
376
  for (const tag of options.tags ?? []) {
@@ -288,6 +383,7 @@ var _FarmDataCache = class _FarmDataCache {
288
383
  key,
289
384
  value,
290
385
  tags,
386
+ tagVersions: void 0,
291
387
  createdAt: options.createdAt ?? Date.now(),
292
388
  createdVersion: ++this.version,
293
389
  revalidate: normalizeRevalidate(options.revalidate)
@@ -301,11 +397,45 @@ var _FarmDataCache = class _FarmDataCache {
301
397
  });
302
398
  return this.toPublicEntry(entry);
303
399
  }
400
+ async setAsync(key, value, options = {}, tagVersions) {
401
+ const tags = normalizeCacheOptionsTags(options);
402
+ const capturedVersions = tagVersions ?? await this.getAdapterTagVersions(Array.from(tags.values()));
403
+ const entry = {
404
+ key,
405
+ value,
406
+ tags: Array.from(tags),
407
+ tagVersions: capturedVersions,
408
+ createdAt: options.createdAt ?? Date.now(),
409
+ createdVersion: ++this.version,
410
+ revalidate: normalizeRevalidate(options.revalidate)
411
+ };
412
+ if (this.local) {
413
+ this.hydrateLocalEntry(entry);
414
+ }
415
+ if (this.adapter) {
416
+ await this.adapter.set(this.createAdapterKey(key), entry);
417
+ }
418
+ emitFarmEvent({
419
+ type: "cache.set",
420
+ key,
421
+ tags: [...entry.tags],
422
+ revalidate: entry.revalidate
423
+ });
424
+ return entry;
425
+ }
304
426
  delete(key) {
305
427
  const deleted = this.entries.delete(key);
306
428
  emitFarmEvent({ type: "cache.delete", key, deleted });
307
429
  return deleted;
308
430
  }
431
+ async deleteAsync(key) {
432
+ const deleted = this.entries.delete(key);
433
+ if (this.adapter) {
434
+ await this.adapter.delete(this.createAdapterKey(key));
435
+ }
436
+ emitFarmEvent({ type: "cache.delete", key, deleted: this.adapter ? true : deleted });
437
+ return this.adapter ? true : deleted;
438
+ }
309
439
  clear() {
310
440
  const count = this.entries.size;
311
441
  this.entries.clear();
@@ -314,6 +444,10 @@ var _FarmDataCache = class _FarmDataCache {
314
444
  this.version = 0;
315
445
  emitFarmEvent({ type: "cache.clear", count });
316
446
  }
447
+ async clearAsync() {
448
+ this.clear();
449
+ await this.adapter?.clear?.();
450
+ }
317
451
  isStale(entry, now = Date.now()) {
318
452
  if (typeof entry.revalidate === "number" && entry.revalidate > 0 && now - entry.createdAt >= entry.revalidate * 1e3) {
319
453
  return true;
@@ -326,6 +460,12 @@ var _FarmDataCache = class _FarmDataCache {
326
460
  }
327
461
  return false;
328
462
  }
463
+ async isStaleAsync(entry, now = Date.now()) {
464
+ if (this.adapter) {
465
+ return this.isAdapterEntryStale(entry, now);
466
+ }
467
+ return this.isStale(entry, now);
468
+ }
329
469
  revalidateTag(tag, options = {}) {
330
470
  const normalized = normalizeCacheTag(tag);
331
471
  const count = this.invalidateTag(normalized);
@@ -334,6 +474,15 @@ var _FarmDataCache = class _FarmDataCache {
334
474
  );
335
475
  return count;
336
476
  }
477
+ async revalidateTagAsync(tag, options = {}) {
478
+ const normalized = normalizeCacheTag(tag);
479
+ const count = this.invalidateTag(normalized);
480
+ await this.adapter?.invalidateTags?.([this.createAdapterTag(normalized)]);
481
+ emitFarmEvent(
482
+ options.source === "updateTag" ? { type: "cache.updateTag", tag: normalized, count } : { type: "cache.revalidateTag", tag: normalized, profile: options.profile, count }
483
+ );
484
+ return count;
485
+ }
337
486
  revalidatePath(routePath) {
338
487
  const normalizedPath = normalizeRevalidatePath(routePath);
339
488
  const pathTag = createPathCacheTag(normalizedPath);
@@ -350,8 +499,25 @@ var _FarmDataCache = class _FarmDataCache {
350
499
  }
351
500
  return count;
352
501
  }
502
+ async revalidatePathAsync(routePath) {
503
+ const normalizedPath = normalizeRevalidatePath(routePath);
504
+ const pathTag = createPathCacheTag(normalizedPath);
505
+ const pprCount = this.countEntriesForTags([pathTag, "ppr"]);
506
+ const count = this.invalidateTag(pathTag);
507
+ await this.adapter?.invalidateTags?.([this.createAdapterTag(pathTag)]);
508
+ emitFarmEvent({ type: "cache.revalidatePath", path: normalizedPath, count });
509
+ if (pprCount > 0) {
510
+ emitFarmEvent({
511
+ type: "ppr.shell.invalidated",
512
+ route: normalizedPath,
513
+ reason: "revalidatePath",
514
+ count: pprCount
515
+ });
516
+ }
517
+ return count;
518
+ }
353
519
  async getOrSet(key, producer, options = {}) {
354
- const cached = this.getEntry(key);
520
+ const cached = await this.getEntryAsync(key);
355
521
  if (cached) {
356
522
  return cached.value;
357
523
  }
@@ -360,10 +526,8 @@ var _FarmDataCache = class _FarmDataCache {
360
526
  emitFarmEvent({ type: "cache.dedupe", key });
361
527
  return inflight;
362
528
  }
363
- const promise = Promise.resolve().then(producer).then((value) => {
364
- this.set(key, value, options);
365
- return value;
366
- }).catch((error) => {
529
+ const tags = Array.from(normalizeCacheOptionsTags(options));
530
+ const promise = this.fillCacheEntry(key, producer, options, tags).catch((error) => {
367
531
  emitFarmEvent({ type: "cache.error", key, operation: "set", error });
368
532
  throw error;
369
533
  }).finally(() => {
@@ -372,6 +536,40 @@ var _FarmDataCache = class _FarmDataCache {
372
536
  this.inflight.set(key, promise);
373
537
  return promise;
374
538
  }
539
+ async fillCacheEntry(key, producer, options, tags) {
540
+ const leaseKey = `${this.namespace}:lease:${key}`;
541
+ let leaseToken;
542
+ if (this.adapter?.acquireLease && this.adapter.releaseLease && this.lease.enabled) {
543
+ leaseToken = await this.adapter.acquireLease(leaseKey, this.lease.ttlMs);
544
+ if (!leaseToken) {
545
+ const shared = await this.waitForAdapterEntry(key);
546
+ if (shared) {
547
+ emitFarmEvent({ type: "cache.dedupe", key });
548
+ return shared.value;
549
+ }
550
+ leaseToken = await this.adapter.acquireLease(leaseKey, this.lease.ttlMs);
551
+ }
552
+ }
553
+ try {
554
+ const initialTagVersions = await this.getAdapterTagVersions(tags);
555
+ const value = await producer();
556
+ await this.setAsync(key, value, options, initialTagVersions);
557
+ return value;
558
+ } finally {
559
+ if (leaseToken && this.adapter?.releaseLease) {
560
+ await this.adapter.releaseLease(leaseKey, leaseToken);
561
+ }
562
+ }
563
+ }
564
+ async waitForAdapterEntry(key) {
565
+ const deadline = Date.now() + this.lease.waitTimeoutMs;
566
+ while (Date.now() < deadline) {
567
+ await delay(this.lease.pollIntervalMs);
568
+ const entry = await this.getEntryAsync(key);
569
+ if (entry) return entry;
570
+ }
571
+ return void 0;
572
+ }
375
573
  countEntriesForTag(tag) {
376
574
  let count = 0;
377
575
  for (const entry of this.entries.values()) {
@@ -399,11 +597,53 @@ var _FarmDataCache = class _FarmDataCache {
399
597
  key: entry.key,
400
598
  value: entry.value,
401
599
  tags: Array.from(entry.tags),
600
+ tagVersions: entry.tagVersions,
402
601
  createdAt: entry.createdAt,
403
602
  createdVersion: entry.createdVersion,
404
603
  revalidate: entry.revalidate
405
604
  };
406
605
  }
606
+ hydrateLocalEntry(entry) {
607
+ this.entries.set(entry.key, {
608
+ key: entry.key,
609
+ value: entry.value,
610
+ tags: new Set(entry.tags.map(normalizeCacheTag)),
611
+ tagVersions: entry.tagVersions,
612
+ createdAt: entry.createdAt,
613
+ createdVersion: entry.createdVersion ?? ++this.version,
614
+ revalidate: normalizeRevalidate(entry.revalidate)
615
+ });
616
+ }
617
+ createAdapterKey(key) {
618
+ return `${this.namespace}:entry:${key}`;
619
+ }
620
+ createAdapterTag(tag) {
621
+ return `${this.namespace}:tag:${tag}`;
622
+ }
623
+ async getAdapterTagVersions(tags) {
624
+ if (!this.adapter?.getTagVersions || tags.length === 0) return {};
625
+ const normalized = tags.map(normalizeCacheTag);
626
+ const physicalTags = normalized.map((tag) => this.createAdapterTag(tag));
627
+ const versions = await this.adapter.getTagVersions(physicalTags);
628
+ return Object.fromEntries(
629
+ normalized.map((tag, index) => [
630
+ tag,
631
+ normalizeAdapterVersion(versions[physicalTags[index]])
632
+ ])
633
+ );
634
+ }
635
+ async isAdapterEntryStale(entry, now = Date.now()) {
636
+ if (typeof entry.revalidate === "number" && entry.revalidate > 0 && now - entry.createdAt >= entry.revalidate * 1e3) {
637
+ return true;
638
+ }
639
+ const currentVersions = await this.getAdapterTagVersions(entry.tags);
640
+ for (const tag of entry.tags) {
641
+ if (normalizeAdapterVersion(currentVersions[tag]) > normalizeAdapterVersion(entry.tagVersions?.[tag])) {
642
+ return true;
643
+ }
644
+ }
645
+ return false;
646
+ }
407
647
  };
408
648
  __name(_FarmDataCache, "FarmDataCache");
409
649
  var FarmDataCache = _FarmDataCache;
@@ -416,16 +656,52 @@ function getFarmDataCache() {
416
656
  return sharedFarmDataCache;
417
657
  }
418
658
  __name(getFarmDataCache, "getFarmDataCache");
659
+ function updateTag(tag) {
660
+ const cache = getFarmDataCache();
661
+ if (cache.hasAdapter) {
662
+ const task = cache.revalidateTagAsync(tag, { source: "updateTag" }).then(() => void 0);
663
+ notifyFarmCacheTask(task);
664
+ return task;
665
+ }
666
+ cache.revalidateTag(tag, { source: "updateTag" });
667
+ }
668
+ __name(updateTag, "updateTag");
419
669
  function revalidatePath(routePath) {
420
- getFarmDataCache().revalidatePath(routePath);
670
+ const cache = getFarmDataCache();
671
+ if (cache.hasAdapter) {
672
+ const task = cache.revalidatePathAsync(routePath).then(() => void 0);
673
+ notifyFarmCacheTask(task);
674
+ return task;
675
+ }
676
+ cache.revalidatePath(routePath);
421
677
  }
422
678
  __name(revalidatePath, "revalidatePath");
423
679
  function invalidate(key) {
424
680
  const clientKey = createRouteDataCacheKey(key);
425
- getFarmDataCache().revalidateTag(createRouteDataCacheTag(key), { source: "updateTag" });
681
+ const task = updateTag(createRouteDataCacheTag(key));
426
682
  notifyFarmCacheInvalidation(clientKey);
683
+ return task;
427
684
  }
428
685
  __name(invalidate, "invalidate");
686
+ async function applyFarmCacheInvalidationTargets(targets) {
687
+ if (!Array.isArray(targets)) {
688
+ throw new TypeError("Cache invalidations must resolve to an array of targets.");
689
+ }
690
+ const clientKeys = [];
691
+ for (const target of targets) {
692
+ assertFarmCacheInvalidationTarget(target);
693
+ if ("key" in target) {
694
+ await invalidate(target.key);
695
+ clientKeys.push(createRouteDataCacheKey(target.key));
696
+ } else if ("path" in target) {
697
+ await revalidatePath(target.path);
698
+ } else {
699
+ await updateTag(target.tag);
700
+ }
701
+ }
702
+ return Array.from(new Set(clientKeys));
703
+ }
704
+ __name(applyFarmCacheInvalidationTargets, "applyFarmCacheInvalidationTargets");
429
705
  function createPathCacheTag(routePath) {
430
706
  return `path:${normalizeRevalidatePath(routePath)}`;
431
707
  }
@@ -486,6 +762,67 @@ function normalizeCacheTag(tag) {
486
762
  return normalized;
487
763
  }
488
764
  __name(normalizeCacheTag, "normalizeCacheTag");
765
+ function normalizeCacheNamespace(namespace) {
766
+ if (typeof namespace !== "string") {
767
+ throw new TypeError("Cache namespace must be a string.");
768
+ }
769
+ const normalized = namespace.trim().replace(/:+$/g, "");
770
+ if (!normalized) {
771
+ throw new Error("Cache namespace cannot be empty.");
772
+ }
773
+ return normalized;
774
+ }
775
+ __name(normalizeCacheNamespace, "normalizeCacheNamespace");
776
+ function normalizeAdapterVersion(value) {
777
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
778
+ }
779
+ __name(normalizeAdapterVersion, "normalizeAdapterVersion");
780
+ function normalizePositiveDuration(value, fallback, name) {
781
+ if (value === void 0) return fallback;
782
+ if (!Number.isFinite(value) || value <= 0) {
783
+ throw new TypeError(`${name} must be a positive number of milliseconds.`);
784
+ }
785
+ return Math.floor(value);
786
+ }
787
+ __name(normalizePositiveDuration, "normalizePositiveDuration");
788
+ function delay(ms) {
789
+ return new Promise((resolve) => setTimeout(resolve, ms));
790
+ }
791
+ __name(delay, "delay");
792
+ function normalizeCacheOptionsTags(options) {
793
+ const tags = /* @__PURE__ */ new Set();
794
+ for (const tag of options.tags ?? []) {
795
+ tags.add(normalizeCacheTag(tag));
796
+ }
797
+ for (const routePath of options.paths ?? []) {
798
+ tags.add(createPathCacheTag(routePath));
799
+ }
800
+ return tags;
801
+ }
802
+ __name(normalizeCacheOptionsTags, "normalizeCacheOptionsTags");
803
+ function assertFarmCacheEntry(entry, expectedKey) {
804
+ if (!entry || typeof entry !== "object" || entry.key !== expectedKey || !Array.isArray(entry.tags) || typeof entry.createdAt !== "number") {
805
+ throw new TypeError(
806
+ `Cache adapter returned an invalid entry for ${JSON.stringify(expectedKey)}.`
807
+ );
808
+ }
809
+ }
810
+ __name(assertFarmCacheEntry, "assertFarmCacheEntry");
811
+ function assertFarmCacheInvalidationTarget(target) {
812
+ if (!target || typeof target !== "object") {
813
+ throw new TypeError("Cache invalidation targets must be { key }, { path }, or { tag }.");
814
+ }
815
+ if ("key" in target) {
816
+ const key = target.key;
817
+ if (typeof key === "string" || Array.isArray(key)) return;
818
+ } else if ("path" in target && typeof target.path === "string") {
819
+ return;
820
+ } else if ("tag" in target && typeof target.tag === "string") {
821
+ return;
822
+ }
823
+ throw new TypeError("Cache invalidation targets must contain a string/array key, path, or tag.");
824
+ }
825
+ __name(assertFarmCacheInvalidationTarget, "assertFarmCacheInvalidationTarget");
489
826
  function getFunctionCacheIdentity(fn) {
490
827
  if (fn.name) {
491
828
  return `name:${fn.name}`;
@@ -540,6 +877,179 @@ function stableSerialize(value, seen = /* @__PURE__ */ new WeakSet()) {
540
877
  }
541
878
  __name(stableSerialize, "stableSerialize");
542
879
 
880
+ // src/api/transport.ts
881
+ function multipart(schema) {
882
+ if (!Object.isExtensible(schema) && !isMultipartSchema(schema)) {
883
+ throw new TypeError("multipart() requires an extensible schema object");
884
+ }
885
+ if (!isMultipartSchema(schema)) {
886
+ Object.defineProperty(schema, "__farmMultipartSchema", {
887
+ value: true,
888
+ configurable: false,
889
+ enumerable: false,
890
+ writable: false
891
+ });
892
+ }
893
+ return schema;
894
+ }
895
+ __name(multipart, "multipart");
896
+ function isMultipartSchema(value) {
897
+ return typeof value === "object" && value !== null && value.__farmMultipartSchema === true && typeof value.parse === "function";
898
+ }
899
+ __name(isMultipartSchema, "isMultipartSchema");
900
+ function toFormData(values) {
901
+ const formData = new FormData();
902
+ for (const [key, value] of Object.entries(values)) {
903
+ if (isUnsafeFormKey(key)) continue;
904
+ if (Array.isArray(value)) {
905
+ for (const entry of value) appendFormValue(formData, key, entry);
906
+ continue;
907
+ }
908
+ appendFormValue(formData, key, value);
909
+ }
910
+ return formData;
911
+ }
912
+ __name(toFormData, "toFormData");
913
+ function jsonStream(source, init = {}) {
914
+ const iterator = toAsyncIterator(source);
915
+ const encoder = new TextEncoder();
916
+ let finished = false;
917
+ const body = new ReadableStream(
918
+ {
919
+ async pull(controller) {
920
+ if (finished) return;
921
+ try {
922
+ const next = await iterator.next();
923
+ if (next.done) {
924
+ finished = true;
925
+ controller.close();
926
+ return;
927
+ }
928
+ controller.enqueue(encoder.encode(`${JSON.stringify(next.value)}
929
+ `));
930
+ } catch (error) {
931
+ finished = true;
932
+ controller.error(error);
933
+ }
934
+ },
935
+ async cancel(reason) {
936
+ finished = true;
937
+ await iterator.return?.(reason);
938
+ }
939
+ },
940
+ {
941
+ // Do not read the next application event until the response consumer
942
+ // requests another chunk.
943
+ highWaterMark: 0
944
+ }
945
+ );
946
+ const headers = new Headers(init.headers);
947
+ if (!headers.has("content-type")) {
948
+ headers.set("content-type", "application/x-ndjson; charset=utf-8");
949
+ }
950
+ headers.set("cache-control", headers.get("cache-control") ?? "no-store");
951
+ return new Response(body, {
952
+ ...init,
953
+ headers
954
+ });
955
+ }
956
+ __name(jsonStream, "jsonStream");
957
+ function isJSONStreamResponse(response) {
958
+ const contentType = response.headers?.get?.("content-type")?.toLowerCase() ?? "";
959
+ return contentType.includes("application/x-ndjson") || contentType.includes("application/ndjson");
960
+ }
961
+ __name(isJSONStreamResponse, "isJSONStreamResponse");
962
+ function readJSONStream(response) {
963
+ if (!response.body) {
964
+ throw new TypeError("Cannot read a JSON stream response without a body");
965
+ }
966
+ const reader = response.body.getReader();
967
+ const decoder = new TextDecoder();
968
+ let buffer = "";
969
+ let completed = false;
970
+ let claimed = false;
971
+ const iterator = {
972
+ async next() {
973
+ while (true) {
974
+ const lineEnd = buffer.indexOf("\n");
975
+ if (lineEnd >= 0) {
976
+ const line = buffer.slice(0, lineEnd).trim();
977
+ buffer = buffer.slice(lineEnd + 1);
978
+ if (!line) continue;
979
+ return { done: false, value: JSON.parse(line) };
980
+ }
981
+ if (completed) {
982
+ const line = buffer.trim();
983
+ buffer = "";
984
+ if (!line) return { done: true, value: void 0 };
985
+ return { done: false, value: JSON.parse(line) };
986
+ }
987
+ const chunk = await reader.read();
988
+ completed = chunk.done;
989
+ buffer += decoder.decode(chunk.value, { stream: !chunk.done });
990
+ }
991
+ },
992
+ async return() {
993
+ completed = true;
994
+ buffer = "";
995
+ await reader.cancel();
996
+ return { done: true, value: void 0 };
997
+ }
998
+ };
999
+ return {
1000
+ response,
1001
+ async cancel(reason) {
1002
+ completed = true;
1003
+ buffer = "";
1004
+ await reader.cancel(reason);
1005
+ },
1006
+ [Symbol.asyncIterator]() {
1007
+ if (claimed) {
1008
+ throw new TypeError("Farm API streams can only be consumed once");
1009
+ }
1010
+ claimed = true;
1011
+ return iterator;
1012
+ }
1013
+ };
1014
+ }
1015
+ __name(readJSONStream, "readJSONStream");
1016
+ function isFarmAPIStream(value) {
1017
+ return typeof value === "object" && value !== null && "response" in value && typeof value.cancel === "function" && typeof value[Symbol.asyncIterator] === "function";
1018
+ }
1019
+ __name(isFarmAPIStream, "isFarmAPIStream");
1020
+ function appendFormValue(formData, key, value) {
1021
+ if (value === void 0) return;
1022
+ if (value === null) {
1023
+ formData.append(key, "");
1024
+ return;
1025
+ }
1026
+ if (value instanceof Blob) {
1027
+ formData.append(key, value);
1028
+ return;
1029
+ }
1030
+ if (value instanceof Date) {
1031
+ formData.append(key, value.toISOString());
1032
+ return;
1033
+ }
1034
+ formData.append(key, String(value));
1035
+ }
1036
+ __name(appendFormValue, "appendFormValue");
1037
+ function isUnsafeFormKey(key) {
1038
+ return key === "__proto__" || key === "constructor" || key === "prototype";
1039
+ }
1040
+ __name(isUnsafeFormKey, "isUnsafeFormKey");
1041
+ function toAsyncIterator(source) {
1042
+ if (Symbol.asyncIterator in Object(source)) {
1043
+ return source[Symbol.asyncIterator]();
1044
+ }
1045
+ const iterator = source[Symbol.iterator]();
1046
+ return {
1047
+ next: /* @__PURE__ */ __name(async () => iterator.next(), "next"),
1048
+ return: iterator.return ? async (value) => iterator.return(value) : void 0
1049
+ };
1050
+ }
1051
+ __name(toAsyncIterator, "toAsyncIterator");
1052
+
543
1053
  // src/api/endpoint.ts
544
1054
  var _EndpointFailure = class _EndpointFailure extends Error {
545
1055
  constructor(code, data, options) {
@@ -607,6 +1117,7 @@ function createEndpoint(pathOrOptions, optionsOrHandler, maybeHandler) {
607
1117
  endpoint.__errors = errors;
608
1118
  endpoint.__types = {
609
1119
  body: options.body,
1120
+ inputBody: isMultipartSchema(options.body) ? "form-data" : options.body,
610
1121
  query: options.query,
611
1122
  headers: options.headers,
612
1123
  response: null,
@@ -725,37 +1236,12 @@ async function applyEndpointInvalidations(declaration, context, result) {
725
1236
  const targets = typeof declaration === "function" ? await declaration(context) : declaration;
726
1237
  if (!Array.isArray(targets)) {
727
1238
  throw new TypeError(
728
- "Endpoint invalidates must resolve to an array of { key } or { path } targets"
1239
+ "Endpoint invalidates must resolve to an array of { key }, { path }, or { tag } targets"
729
1240
  );
730
1241
  }
731
- const clientKeys = [];
732
- for (const target of targets) {
733
- assertEndpointInvalidationTarget(target);
734
- if ("key" in target) {
735
- invalidate(target.key);
736
- clientKeys.push(createRouteDataCacheKey(target.key));
737
- } else {
738
- revalidatePath(target.path);
739
- }
740
- }
741
- return Array.from(new Set(clientKeys));
1242
+ return applyFarmCacheInvalidationTargets(targets);
742
1243
  }
743
1244
  __name(applyEndpointInvalidations, "applyEndpointInvalidations");
744
- function assertEndpointInvalidationTarget(target) {
745
- if (!target || typeof target !== "object") {
746
- throw new TypeError("Endpoint invalidation targets must be { key } or { path } objects");
747
- }
748
- if ("key" in target) {
749
- const key = target.key;
750
- if (typeof key === "string" || Array.isArray(key)) return;
751
- } else if ("path" in target && typeof target.path === "string") {
752
- return;
753
- }
754
- throw new TypeError(
755
- "Endpoint invalidation targets must contain a string/array key or a path string"
756
- );
757
- }
758
- __name(assertEndpointInvalidationTarget, "assertEndpointInvalidationTarget");
759
1245
  function createInitialEndpointContext(value) {
760
1246
  if (value === void 0 || value === null) return EMPTY_ENDPOINT_CONTEXT;
761
1247
  if (!isPlainEndpointContext(value)) {
@@ -1248,7 +1734,7 @@ async function invokeAPIRouteEndpointInContext(endpoint, request, params) {
1248
1734
  });
1249
1735
  let body = void 0;
1250
1736
  if (request.method.toUpperCase() !== "GET" && request.method.toUpperCase() !== "HEAD") {
1251
- body = await readJSONBody(request);
1737
+ body = await readRequestBody(request);
1252
1738
  }
1253
1739
  const headers = Object.fromEntries(request.headers.entries());
1254
1740
  const types = endpoint.__types || {};
@@ -1352,17 +1838,50 @@ function isFarmContextHandler(endpoint) {
1352
1838
  return firstParameter === "ctx" || firstParameter === "context" || firstParameter.startsWith("{");
1353
1839
  }
1354
1840
  __name(isFarmContextHandler, "isFarmContextHandler");
1355
- async function readJSONBody(request) {
1841
+ async function readRequestBody(request) {
1842
+ const contentType = request.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
1356
1843
  try {
1844
+ if (contentType === "multipart/form-data") {
1845
+ return formDataToObject(await request.clone().formData());
1846
+ }
1357
1847
  const text = await request.clone().text();
1358
- if (text) {
1848
+ if (!text) return void 0;
1849
+ if (contentType === "application/x-www-form-urlencoded") {
1850
+ return searchParamsToObject(new URLSearchParams(text));
1851
+ }
1852
+ if (contentType === "application/json" || contentType?.endsWith("+json")) {
1359
1853
  return JSON.parse(text);
1360
1854
  }
1855
+ return JSON.parse(text);
1361
1856
  } catch {
1362
1857
  }
1363
1858
  return void 0;
1364
1859
  }
1365
- __name(readJSONBody, "readJSONBody");
1860
+ __name(readRequestBody, "readRequestBody");
1861
+ function formDataToObject(formData) {
1862
+ return entriesToObject(formData.entries());
1863
+ }
1864
+ __name(formDataToObject, "formDataToObject");
1865
+ function searchParamsToObject(searchParams) {
1866
+ return entriesToObject(searchParams.entries());
1867
+ }
1868
+ __name(searchParamsToObject, "searchParamsToObject");
1869
+ function entriesToObject(entries) {
1870
+ const output = /* @__PURE__ */ Object.create(null);
1871
+ for (const [key, value] of entries) {
1872
+ if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
1873
+ const current = output[key];
1874
+ if (current === void 0) {
1875
+ output[key] = value;
1876
+ } else if (Array.isArray(current)) {
1877
+ current.push(value);
1878
+ } else {
1879
+ output[key] = [current, value];
1880
+ }
1881
+ }
1882
+ return output;
1883
+ }
1884
+ __name(entriesToObject, "entriesToObject");
1366
1885
  function validateInput(schema, value, error) {
1367
1886
  if (!schema || typeof schema.parse !== "function") {
1368
1887
  return value;
@@ -2474,6 +2993,7 @@ __name(normalizeFarmClientCacheKey, "normalizeFarmClientCacheKey");
2474
2993
 
2475
2994
  // src/api/client.ts
2476
2995
  var FARM_API_ROUTE_REF_SYMBOL = /* @__PURE__ */ Symbol.for("farm.api.route-ref");
2996
+ var FARM_API_ROUTE_META_SYMBOL = /* @__PURE__ */ Symbol.for("farm.api.route-meta");
2477
2997
  var _APIClientError = class _APIClientError extends Error {
2478
2998
  constructor(code, data, options) {
2479
2999
  super(options.message);
@@ -2511,16 +3031,22 @@ function createAPIClient(options = {}) {
2511
3031
  }
2512
3032
  });
2513
3033
  }
3034
+ const headers = {
3035
+ "Content-Type": "application/json",
3036
+ ...options.headers,
3037
+ ...requestOptions.headers
3038
+ };
2514
3039
  const fetchOptions = {
2515
3040
  method: requestOptions.method || "GET",
2516
- headers: {
2517
- "Content-Type": "application/json",
2518
- ...options.headers,
2519
- ...requestOptions.headers
2520
- }
3041
+ headers
2521
3042
  };
2522
- if (requestOptions.body) {
2523
- fetchOptions.body = JSON.stringify(requestOptions.body);
3043
+ if (requestOptions.body !== void 0) {
3044
+ if (isFormData(requestOptions.body)) {
3045
+ deleteHeader(headers, "content-type");
3046
+ fetchOptions.body = requestOptions.body;
3047
+ } else {
3048
+ fetchOptions.body = JSON.stringify(requestOptions.body);
3049
+ }
2524
3050
  }
2525
3051
  const response = await fetch(url.toString(), fetchOptions);
2526
3052
  applyFarmCacheInvalidations(
@@ -2528,7 +3054,7 @@ function createAPIClient(options = {}) {
2528
3054
  );
2529
3055
  let data = void 0;
2530
3056
  if (response.status !== 204 && response.status !== 205) {
2531
- data = await response.json();
3057
+ data = isJSONStreamResponse(response) ? readJSONStream(response) : await response.json();
2532
3058
  }
2533
3059
  return { response, data };
2534
3060
  }, "fetchClient");
@@ -2674,16 +3200,16 @@ function createAPIClient(options = {}) {
2674
3200
  }
2675
3201
  }
2676
3202
  attempt += 1;
2677
- const delay = typeof clientOptions?.retry?.delay === "function" ? clientOptions.retry.delay(attempt) : clientOptions?.retry?.delay ?? 0;
2678
- if (delay > 0) {
2679
- await new Promise((resolve) => setTimeout(resolve, delay));
3203
+ const delay2 = typeof clientOptions?.retry?.delay === "function" ? clientOptions.retry.delay(attempt) : clientOptions?.retry?.delay ?? 0;
3204
+ if (delay2 > 0) {
3205
+ await new Promise((resolve) => setTimeout(resolve, delay2));
2680
3206
  }
2681
3207
  }
2682
3208
  })();
2683
3209
  inflightState.set(cacheKey, { promise, startedAt: now });
2684
3210
  try {
2685
3211
  const result2 = await promise;
2686
- if (!result2.error && isCacheEnabled) {
3212
+ if (!result2.error && isCacheEnabled && !isFarmAPIStream(result2.data)) {
2687
3213
  const updatedAt = Date.now();
2688
3214
  cacheState.set(cacheKey, {
2689
3215
  data: result2.data,
@@ -2756,10 +3282,17 @@ function createAPIClient(options = {}) {
2756
3282
  clientOptions?.onSettled?.(result.data, result.error);
2757
3283
  return result;
2758
3284
  }, "request");
2759
- return createNestedProxy([], request, routeMeta, baseURL, rootAliases);
3285
+ return createNestedProxy(
3286
+ [],
3287
+ request,
3288
+ routeMeta,
3289
+ baseURL,
3290
+ options.baseURL === void 0,
3291
+ rootAliases
3292
+ );
2760
3293
  }
2761
3294
  __name(createAPIClient, "createAPIClient");
2762
- function createNestedProxy(path4, client, routeMeta, baseURL, rootAliases) {
3295
+ function createNestedProxy(path4, client, routeMeta, baseURL, sameOrigin, rootAliases) {
2763
3296
  const target = /* @__PURE__ */ __name(() => {
2764
3297
  }, "target");
2765
3298
  const proxy = new Proxy(target, {
@@ -2768,13 +3301,29 @@ function createNestedProxy(path4, client, routeMeta, baseURL, rootAliases) {
2768
3301
  if (prop === FARM_API_ROUTE_REF_SYMBOL) {
2769
3302
  return path4.length > 0;
2770
3303
  }
3304
+ if (prop === FARM_API_ROUTE_META_SYMBOL) {
3305
+ const metadata = resolveRouteMeta({ path: path4, baseURL });
3306
+ return Object.freeze({
3307
+ path: metadata.routePath,
3308
+ method: metadata.method,
3309
+ baseURL,
3310
+ sameOrigin
3311
+ });
3312
+ }
2771
3313
  if (path4.length === 0 && typeof prop === "string" && rootAliases && prop in rootAliases) {
2772
3314
  return rootAliases[prop];
2773
3315
  }
2774
3316
  if (typeof prop !== "string") {
2775
3317
  return Reflect.get(_target, prop);
2776
3318
  }
2777
- return createNestedProxy([...path4, prop], client, routeMeta, baseURL, rootAliases);
3319
+ return createNestedProxy(
3320
+ [...path4, prop],
3321
+ client,
3322
+ routeMeta,
3323
+ baseURL,
3324
+ sameOrigin,
3325
+ rootAliases
3326
+ );
2778
3327
  },
2779
3328
  // When calling as a function
2780
3329
  apply(_target, _thisArg, args) {
@@ -2800,6 +3349,22 @@ function isAPIRouteRef(value) {
2800
3349
  return typeof value === "function" && value[FARM_API_ROUTE_REF_SYMBOL] === true;
2801
3350
  }
2802
3351
  __name(isAPIRouteRef, "isAPIRouteRef");
3352
+ function getAPIRouteRefMetadata(value) {
3353
+ if (!isAPIRouteRef(value)) return null;
3354
+ const metadata = value[FARM_API_ROUTE_META_SYMBOL];
3355
+ if (!metadata || typeof metadata !== "object") return null;
3356
+ const candidate = metadata;
3357
+ if (typeof candidate.path !== "string" || typeof candidate.method !== "string" || typeof candidate.baseURL !== "string" || typeof candidate.sameOrigin !== "boolean") {
3358
+ return null;
3359
+ }
3360
+ return {
3361
+ path: candidate.path,
3362
+ method: candidate.method,
3363
+ baseURL: candidate.baseURL,
3364
+ sameOrigin: candidate.sameOrigin
3365
+ };
3366
+ }
3367
+ __name(getAPIRouteRefMetadata, "getAPIRouteRefMetadata");
2803
3368
  function createServerAPIClient(endpoints, options = {}) {
2804
3369
  if (options.integrations === false || Object.prototype.hasOwnProperty.call(endpoints, "integrations")) {
2805
3370
  return endpoints;
@@ -2904,6 +3469,17 @@ function normalizeError(error) {
2904
3469
  return normalized;
2905
3470
  }
2906
3471
  __name(normalizeError, "normalizeError");
3472
+ function isFormData(value) {
3473
+ return typeof value === "object" && value !== null && (typeof FormData !== "undefined" && value instanceof FormData || Object.prototype.toString.call(value) === "[object FormData]" && typeof value.entries === "function");
3474
+ }
3475
+ __name(isFormData, "isFormData");
3476
+ function deleteHeader(headers, name) {
3477
+ const normalized = name.toLowerCase();
3478
+ for (const key of Object.keys(headers)) {
3479
+ if (key.toLowerCase() === normalized) delete headers[key];
3480
+ }
3481
+ }
3482
+ __name(deleteHeader, "deleteHeader");
2907
3483
  function createResponseError2(response, data) {
2908
3484
  const expected = readEndpointErrorEnvelope(data);
2909
3485
  if (expected) {
@@ -3494,6 +4070,7 @@ __name(farmApiPlugin, "farmApiPlugin");
3494
4070
  API_ROUTE_METHODS,
3495
4071
  DELETE,
3496
4072
  EndpointFailure,
4073
+ FARM_API_ROUTE_META_SYMBOL,
3497
4074
  FARM_API_ROUTE_REF_SYMBOL,
3498
4075
  GET,
3499
4076
  HEAD,
@@ -3505,11 +4082,19 @@ __name(farmApiPlugin, "farmApiPlugin");
3505
4082
  createEndpoint,
3506
4083
  createServerAPIClient,
3507
4084
  farmApiPlugin,
4085
+ getAPIRouteRefMetadata,
3508
4086
  invokeAPIRouteEndpoint,
3509
4087
  isAPIRouteRef,
3510
4088
  isEndpointFailure,
4089
+ isFarmAPIStream,
4090
+ isJSONStreamResponse,
4091
+ isMultipartSchema,
3511
4092
  isWebResponse,
4093
+ jsonStream,
3512
4094
  matchAPIRoute,
3513
- normalizeRouteResponse
4095
+ multipart,
4096
+ normalizeRouteResponse,
4097
+ readJSONStream,
4098
+ toFormData
3514
4099
  });
3515
4100
  //# sourceMappingURL=api.cjs.map