@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.
- package/dist/agent-runtime.d.mts +2 -1
- package/dist/agent-runtime.d.ts +2 -1
- package/dist/api/route-manager.cjs +313 -10
- package/dist/api/route-manager.cjs.map +1 -1
- package/dist/api/route-manager.d.mts +3 -2
- package/dist/api/route-manager.d.ts +3 -2
- package/dist/api/route-manager.mjs +6 -5
- package/dist/api/runtime.cjs +313 -10
- package/dist/api/runtime.cjs.map +1 -1
- package/dist/api/runtime.d.mts +2 -1
- package/dist/api/runtime.d.ts +2 -1
- package/dist/api/runtime.mjs +4 -3
- package/dist/api.cjs +642 -57
- package/dist/api.cjs.map +1 -1
- package/dist/api.d.mts +3 -2
- package/dist/api.d.ts +3 -2
- package/dist/api.mjs +29 -9
- package/dist/{app-DOKxo-LH.d.ts → app-BjN-da13.d.ts} +38 -3
- package/dist/{app-BB3Iu3xh.d.mts → app-CakAr8Be.d.mts} +38 -3
- package/dist/app-markdown.d.mts +2 -1
- package/dist/app-markdown.d.ts +2 -1
- package/dist/cache.cjs +395 -12
- package/dist/cache.cjs.map +1 -1
- package/dist/cache.d.mts +100 -6
- package/dist/cache.d.ts +100 -6
- package/dist/cache.mjs +8 -2
- package/dist/{chunk-XUBZ7JI4.mjs → chunk-2CUKEMVR.mjs} +187 -16
- package/dist/chunk-2CUKEMVR.mjs.map +1 -0
- package/dist/{chunk-5QH4IKY3.mjs → chunk-3U3ZUQAQ.mjs} +2 -2
- package/dist/{chunk-6WXJ54TC.mjs → chunk-65A7QIKI.mjs} +5 -5
- package/dist/{chunk-6WXJ54TC.mjs.map → chunk-65A7QIKI.mjs.map} +1 -1
- package/dist/{chunk-OHC6VCDI.mjs → chunk-AJWRO5WE.mjs} +521 -42
- package/dist/chunk-AJWRO5WE.mjs.map +1 -0
- package/dist/chunk-ALCLXXTY.mjs +187 -0
- package/dist/chunk-ALCLXXTY.mjs.map +1 -0
- package/dist/{chunk-XJSHJN4M.mjs → chunk-AOBXKNS5.mjs} +593 -49
- package/dist/chunk-AOBXKNS5.mjs.map +1 -0
- package/dist/{chunk-CSU4KJJF.mjs → chunk-C2ROET2V.mjs} +2 -2
- package/dist/{chunk-BIOIOWXZ.mjs → chunk-HNIQFZKB.mjs} +2 -2
- package/dist/{chunk-G5I34UA6.mjs → chunk-JDEOUK5V.mjs} +4 -4
- package/dist/{chunk-T543TMFY.mjs → chunk-NM3CRAAL.mjs} +3 -2
- package/dist/chunk-NM3CRAAL.mjs.map +1 -0
- package/dist/{chunk-LWMGIEJA.mjs → chunk-PFE6GMNE.mjs} +47 -37
- package/dist/chunk-PFE6GMNE.mjs.map +1 -0
- package/dist/{chunk-6VS6CKAV.mjs → chunk-QM746KUO.mjs} +8 -1
- package/dist/chunk-QM746KUO.mjs.map +1 -0
- package/dist/{chunk-SHRJG6OG.mjs → chunk-RBRLLZL5.mjs} +18 -3
- package/dist/chunk-RBRLLZL5.mjs.map +1 -0
- package/dist/{chunk-MH6FKW2I.mjs → chunk-SADGIRS2.mjs} +3 -3
- package/dist/{chunk-NRRFGX45.mjs → chunk-TQAEEJB4.mjs} +3 -3
- package/dist/{chunk-45LKHSHJ.mjs → chunk-UB5UOSHB.mjs} +24 -12
- package/dist/chunk-UB5UOSHB.mjs.map +1 -0
- package/dist/chunk-V3XURYJO.mjs +756 -0
- package/dist/chunk-V3XURYJO.mjs.map +1 -0
- package/dist/{chunk-5FW6PQ3J.mjs → chunk-VVKWFZAH.mjs} +41 -16
- package/dist/chunk-VVKWFZAH.mjs.map +1 -0
- package/dist/{chunk-HZYXGV4K.mjs → chunk-VY2UYN5R.mjs} +24 -4
- package/dist/chunk-VY2UYN5R.mjs.map +1 -0
- package/dist/{chunk-C33RALN7.mjs → chunk-W2CRQFF6.mjs} +79 -15
- package/dist/chunk-W2CRQFF6.mjs.map +1 -0
- package/dist/{chunk-JNYVN7YP.mjs → chunk-W4UIVMVI.mjs} +2 -2
- package/dist/{chunk-JNYVN7YP.mjs.map → chunk-W4UIVMVI.mjs.map} +1 -1
- package/dist/{chunk-LG3YINQN.mjs → chunk-Z5CQMP54.mjs} +3 -3
- package/dist/{client-DiViK9yK.d.mts → client-BT1mFQas.d.mts} +23 -4
- package/dist/{client-DpEBJbts.d.ts → client-Nn0q4eO4.d.ts} +23 -4
- package/dist/{client-plugins-CTnsZz_A.d.ts → client-plugins-Cw4qUGsw.d.ts} +6 -0
- package/dist/{client-plugins-Cnr0D3kk.d.mts → client-plugins-DQQ1adXM.d.mts} +6 -0
- package/dist/client-plugins.d.mts +2 -1
- package/dist/client-plugins.d.ts +2 -1
- package/dist/client.cjs +665 -82
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.mts +70 -4
- package/dist/client.d.ts +70 -4
- package/dist/client.mjs +10 -7
- package/dist/config.d.mts +2 -1
- package/dist/config.d.ts +2 -1
- package/dist/{devtools-HE4FTUDN.mjs → devtools-LVC3VB5P.mjs} +4 -4
- package/dist/docs.cjs +11 -1
- package/dist/docs.cjs.map +1 -1
- package/dist/docs.mjs +4 -4
- package/dist/index.cjs +2112 -197
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +12 -11
- package/dist/index.d.ts +12 -11
- package/dist/index.mjs +49 -21
- package/dist/index.mjs.map +1 -1
- package/dist/integrations.d.mts +2 -1
- package/dist/integrations.d.ts +2 -1
- package/dist/internal/build-runtime.cjs +1455 -90
- package/dist/internal/build-runtime.cjs.map +1 -1
- package/dist/internal/build-runtime.d.mts +4 -3
- package/dist/internal/build-runtime.d.ts +4 -3
- package/dist/internal/build-runtime.mjs +15 -14
- package/dist/internal/config-runtime.cjs +12 -1
- package/dist/internal/config-runtime.cjs.map +1 -1
- package/dist/internal/config-runtime.d.mts +3 -2
- package/dist/internal/config-runtime.d.ts +3 -2
- package/dist/internal/config-runtime.mjs +3 -3
- package/dist/internal/production-runtime.cjs +282 -6
- package/dist/internal/production-runtime.cjs.map +1 -1
- package/dist/internal/production-runtime.d.mts +4 -4
- package/dist/internal/production-runtime.d.ts +4 -4
- package/dist/internal/production-runtime.mjs +4 -2
- package/dist/{metadata-eoVmHoyv.d.ts → metadata-BAPg_Nmo.d.ts} +1 -1
- package/dist/{metadata-Dp8AdvsB.d.mts → metadata-_6i9oFG3.d.mts} +1 -1
- package/dist/middleware.d.mts +4 -3
- package/dist/middleware.d.ts +4 -3
- package/dist/navigation.cjs +40 -15
- package/dist/navigation.cjs.map +1 -1
- package/dist/navigation.mjs +2 -2
- package/dist/plugin.cjs +913 -53
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.mts +2 -1
- package/dist/plugin.d.ts +2 -1
- package/dist/plugin.mjs +11 -10
- package/dist/{production-runtime-BqTnUTai.d.ts → production-runtime-BoJDc5mc.d.ts} +1 -1
- package/dist/{production-runtime-DtDdG9fc.d.mts → production-runtime-DPfgMV9Y.d.mts} +1 -1
- package/dist/routes.cjs +276 -6
- package/dist/routes.cjs.map +1 -1
- package/dist/routes.d.mts +1 -1
- package/dist/routes.d.ts +1 -1
- package/dist/routes.mjs +3 -3
- package/dist/{runtime-C1B7pSGT.d.mts → runtime-9nQjVM7X.d.mts} +8 -9
- package/dist/{runtime-CdPHt0bv.d.ts → runtime-DgeS2skB.d.ts} +8 -9
- package/dist/server-action-security.cjs +28 -10
- package/dist/server-action-security.cjs.map +1 -1
- package/dist/server-action-security.d.mts +2 -1
- package/dist/server-action-security.d.ts +2 -1
- package/dist/server-action-security.mjs +2 -2
- package/dist/server-fn-client.d.mts +1 -0
- package/dist/server-fn-client.d.ts +1 -0
- package/dist/server-fn.cjs +785 -3
- package/dist/server-fn.cjs.map +1 -1
- package/dist/server-fn.d.mts +10 -1
- package/dist/server-fn.d.ts +10 -1
- package/dist/server-fn.mjs +6 -3
- package/dist/server-plugins.d.mts +3 -2
- package/dist/server-plugins.d.ts +3 -2
- package/dist/server-query-client.cjs +278 -7
- package/dist/server-query-client.cjs.map +1 -1
- package/dist/server-query-client.mjs +4 -4
- package/dist/server-query.cjs +381 -10
- package/dist/server-query.cjs.map +1 -1
- package/dist/server-query.mjs +5 -5
- package/dist/server.cjs +1086 -76
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.mts +8 -7
- package/dist/server.d.ts +8 -7
- package/dist/server.mjs +31 -16
- package/dist/server.mjs.map +1 -1
- package/dist/testing.cjs +341 -20
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.mts +3 -2
- package/dist/testing.d.ts +3 -2
- package/dist/testing.mjs +7 -6
- package/dist/testing.mjs.map +1 -1
- package/dist/transport-BmbGTXA5.d.mts +49 -0
- package/dist/transport-BmbGTXA5.d.ts +49 -0
- package/dist/{utils-8USa5BiY.d.mts → utils-CHXlMDkg.d.mts} +1 -1
- package/dist/{utils-DKJb6K6G.d.ts → utils-Drsyz1Vj.d.ts} +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.cjs.map +1 -1
- package/dist/version.mjs +1 -1
- package/dist/vite.cjs +914 -54
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.d.mts +2 -1
- package/dist/vite.d.ts +2 -1
- package/dist/vite.mjs +11 -10
- package/package.json +1 -1
- package/types/api.d.ts +44 -0
- package/types/client.d.ts +85 -4
- package/dist/chunk-45LKHSHJ.mjs.map +0 -1
- package/dist/chunk-5FW6PQ3J.mjs.map +0 -1
- package/dist/chunk-6VS6CKAV.mjs.map +0 -1
- package/dist/chunk-C33RALN7.mjs.map +0 -1
- package/dist/chunk-GZWT6VI5.mjs +0 -382
- package/dist/chunk-GZWT6VI5.mjs.map +0 -1
- package/dist/chunk-HZYXGV4K.mjs.map +0 -1
- package/dist/chunk-LWMGIEJA.mjs.map +0 -1
- package/dist/chunk-OHC6VCDI.mjs.map +0 -1
- package/dist/chunk-SHRJG6OG.mjs.map +0 -1
- package/dist/chunk-T543TMFY.mjs.map +0 -1
- package/dist/chunk-XJSHJN4M.mjs.map +0 -1
- package/dist/chunk-XUBZ7JI4.mjs.map +0 -1
- /package/dist/{chunk-5QH4IKY3.mjs.map → chunk-3U3ZUQAQ.mjs.map} +0 -0
- /package/dist/{chunk-CSU4KJJF.mjs.map → chunk-C2ROET2V.mjs.map} +0 -0
- /package/dist/{chunk-BIOIOWXZ.mjs.map → chunk-HNIQFZKB.mjs.map} +0 -0
- /package/dist/{chunk-G5I34UA6.mjs.map → chunk-JDEOUK5V.mjs.map} +0 -0
- /package/dist/{chunk-MH6FKW2I.mjs.map → chunk-SADGIRS2.mjs.map} +0 -0
- /package/dist/{chunk-NRRFGX45.mjs.map → chunk-TQAEEJB4.mjs.map} +0 -0
- /package/dist/{chunk-LG3YINQN.mjs.map → chunk-Z5CQMP54.mjs.map} +0 -0
- /package/dist/{devtools-HE4FTUDN.mjs.map → devtools-LVC3VB5P.mjs.map} +0 -0
package/dist/client.cjs
CHANGED
|
@@ -64,6 +64,7 @@ __export(client_exports, {
|
|
|
64
64
|
readPageState: () => readPageState,
|
|
65
65
|
replaceState: () => replaceState,
|
|
66
66
|
useBlocker: () => useBlocker,
|
|
67
|
+
useFetcher: () => useFetcher,
|
|
67
68
|
useMutation: () => useMutation,
|
|
68
69
|
useNavigation: () => useNavigation,
|
|
69
70
|
usePageState: () => usePageState,
|
|
@@ -988,7 +989,8 @@ var FARM_CACHE_INVALIDATION_STATE = /* @__PURE__ */ Symbol.for("farm.cacheInvali
|
|
|
988
989
|
var globalState = globalThis;
|
|
989
990
|
function getFarmCacheInvalidationState() {
|
|
990
991
|
return globalState[FARM_CACHE_INVALIDATION_STATE] ?? (globalState[FARM_CACHE_INVALIDATION_STATE] = {
|
|
991
|
-
listeners: /* @__PURE__ */ new Set()
|
|
992
|
+
listeners: /* @__PURE__ */ new Set(),
|
|
993
|
+
taskListeners: /* @__PURE__ */ new Set()
|
|
992
994
|
});
|
|
993
995
|
}
|
|
994
996
|
__name(getFarmCacheInvalidationState, "getFarmCacheInvalidationState");
|
|
@@ -1039,11 +1041,51 @@ __name(getActiveFarmI18nSnapshot, "getActiveFarmI18nSnapshot");
|
|
|
1039
1041
|
|
|
1040
1042
|
// src/cache.ts
|
|
1041
1043
|
var _FarmDataCache = class _FarmDataCache {
|
|
1042
|
-
constructor() {
|
|
1044
|
+
constructor(config = {}) {
|
|
1043
1045
|
this.entries = /* @__PURE__ */ new Map();
|
|
1044
1046
|
this.inflight = /* @__PURE__ */ new Map();
|
|
1045
1047
|
this.invalidatedTagVersions = /* @__PURE__ */ new Map();
|
|
1046
1048
|
this.version = 0;
|
|
1049
|
+
this.namespace = "farm";
|
|
1050
|
+
this.local = true;
|
|
1051
|
+
this.lease = {
|
|
1052
|
+
enabled: true,
|
|
1053
|
+
ttlMs: 1e4,
|
|
1054
|
+
waitTimeoutMs: 1e4,
|
|
1055
|
+
pollIntervalMs: 25
|
|
1056
|
+
};
|
|
1057
|
+
this.configure(config);
|
|
1058
|
+
}
|
|
1059
|
+
configure(config = {}) {
|
|
1060
|
+
this.adapter = config.adapter;
|
|
1061
|
+
this.namespace = normalizeCacheNamespace(config.namespace || "farm");
|
|
1062
|
+
this.local = !config.adapter;
|
|
1063
|
+
this.lease = config.lease === false ? { ...this.lease, enabled: false } : {
|
|
1064
|
+
enabled: true,
|
|
1065
|
+
ttlMs: normalizePositiveDuration(config.lease?.ttlMs, 1e4, "cache.lease.ttlMs"),
|
|
1066
|
+
waitTimeoutMs: normalizePositiveDuration(
|
|
1067
|
+
config.lease?.waitTimeoutMs,
|
|
1068
|
+
1e4,
|
|
1069
|
+
"cache.lease.waitTimeoutMs"
|
|
1070
|
+
),
|
|
1071
|
+
pollIntervalMs: normalizePositiveDuration(
|
|
1072
|
+
config.lease?.pollIntervalMs,
|
|
1073
|
+
25,
|
|
1074
|
+
"cache.lease.pollIntervalMs"
|
|
1075
|
+
)
|
|
1076
|
+
};
|
|
1077
|
+
if (!this.local) {
|
|
1078
|
+
this.entries.clear();
|
|
1079
|
+
this.inflight.clear();
|
|
1080
|
+
this.invalidatedTagVersions.clear();
|
|
1081
|
+
this.version = 0;
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
get adapterName() {
|
|
1085
|
+
return this.adapter?.name || (this.adapter ? "custom" : "memory");
|
|
1086
|
+
}
|
|
1087
|
+
get hasAdapter() {
|
|
1088
|
+
return this.adapter !== void 0;
|
|
1047
1089
|
}
|
|
1048
1090
|
get size() {
|
|
1049
1091
|
return this.entries.size;
|
|
@@ -1079,6 +1121,45 @@ var _FarmDataCache = class _FarmDataCache {
|
|
|
1079
1121
|
});
|
|
1080
1122
|
return this.toPublicEntry(entry);
|
|
1081
1123
|
}
|
|
1124
|
+
async getEntryAsync(key, options = {}) {
|
|
1125
|
+
if (this.local) {
|
|
1126
|
+
const localEntry = this.getEntry(key, options);
|
|
1127
|
+
if (localEntry) return localEntry;
|
|
1128
|
+
}
|
|
1129
|
+
if (!this.adapter) {
|
|
1130
|
+
return this.local ? void 0 : this.getEntry(key, options);
|
|
1131
|
+
}
|
|
1132
|
+
const entry = await this.adapter.get(this.createAdapterKey(key));
|
|
1133
|
+
if (!entry) {
|
|
1134
|
+
emitFarmEvent({ type: "cache.miss", key });
|
|
1135
|
+
return void 0;
|
|
1136
|
+
}
|
|
1137
|
+
assertFarmCacheEntry(entry, key);
|
|
1138
|
+
const stale = await this.isAdapterEntryStale(entry, options.now);
|
|
1139
|
+
if (stale) {
|
|
1140
|
+
emitFarmEvent({
|
|
1141
|
+
type: "cache.stale",
|
|
1142
|
+
key,
|
|
1143
|
+
tags: [...entry.tags],
|
|
1144
|
+
revalidate: entry.revalidate
|
|
1145
|
+
});
|
|
1146
|
+
if (!options.allowStale) {
|
|
1147
|
+
emitFarmEvent({ type: "cache.miss", key, reason: "stale" });
|
|
1148
|
+
return void 0;
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
emitFarmEvent({
|
|
1152
|
+
type: "cache.hit",
|
|
1153
|
+
key,
|
|
1154
|
+
tags: [...entry.tags],
|
|
1155
|
+
revalidate: entry.revalidate,
|
|
1156
|
+
stale
|
|
1157
|
+
});
|
|
1158
|
+
if (this.local && !stale) {
|
|
1159
|
+
this.hydrateLocalEntry(entry);
|
|
1160
|
+
}
|
|
1161
|
+
return { ...entry, key };
|
|
1162
|
+
}
|
|
1082
1163
|
set(key, value, options = {}) {
|
|
1083
1164
|
const tags = /* @__PURE__ */ new Set();
|
|
1084
1165
|
for (const tag of options.tags ?? []) {
|
|
@@ -1091,6 +1172,7 @@ var _FarmDataCache = class _FarmDataCache {
|
|
|
1091
1172
|
key,
|
|
1092
1173
|
value,
|
|
1093
1174
|
tags,
|
|
1175
|
+
tagVersions: void 0,
|
|
1094
1176
|
createdAt: options.createdAt ?? Date.now(),
|
|
1095
1177
|
createdVersion: ++this.version,
|
|
1096
1178
|
revalidate: normalizeRevalidate(options.revalidate)
|
|
@@ -1104,11 +1186,45 @@ var _FarmDataCache = class _FarmDataCache {
|
|
|
1104
1186
|
});
|
|
1105
1187
|
return this.toPublicEntry(entry);
|
|
1106
1188
|
}
|
|
1189
|
+
async setAsync(key, value, options = {}, tagVersions) {
|
|
1190
|
+
const tags = normalizeCacheOptionsTags(options);
|
|
1191
|
+
const capturedVersions = tagVersions ?? await this.getAdapterTagVersions(Array.from(tags.values()));
|
|
1192
|
+
const entry = {
|
|
1193
|
+
key,
|
|
1194
|
+
value,
|
|
1195
|
+
tags: Array.from(tags),
|
|
1196
|
+
tagVersions: capturedVersions,
|
|
1197
|
+
createdAt: options.createdAt ?? Date.now(),
|
|
1198
|
+
createdVersion: ++this.version,
|
|
1199
|
+
revalidate: normalizeRevalidate(options.revalidate)
|
|
1200
|
+
};
|
|
1201
|
+
if (this.local) {
|
|
1202
|
+
this.hydrateLocalEntry(entry);
|
|
1203
|
+
}
|
|
1204
|
+
if (this.adapter) {
|
|
1205
|
+
await this.adapter.set(this.createAdapterKey(key), entry);
|
|
1206
|
+
}
|
|
1207
|
+
emitFarmEvent({
|
|
1208
|
+
type: "cache.set",
|
|
1209
|
+
key,
|
|
1210
|
+
tags: [...entry.tags],
|
|
1211
|
+
revalidate: entry.revalidate
|
|
1212
|
+
});
|
|
1213
|
+
return entry;
|
|
1214
|
+
}
|
|
1107
1215
|
delete(key) {
|
|
1108
1216
|
const deleted = this.entries.delete(key);
|
|
1109
1217
|
emitFarmEvent({ type: "cache.delete", key, deleted });
|
|
1110
1218
|
return deleted;
|
|
1111
1219
|
}
|
|
1220
|
+
async deleteAsync(key) {
|
|
1221
|
+
const deleted = this.entries.delete(key);
|
|
1222
|
+
if (this.adapter) {
|
|
1223
|
+
await this.adapter.delete(this.createAdapterKey(key));
|
|
1224
|
+
}
|
|
1225
|
+
emitFarmEvent({ type: "cache.delete", key, deleted: this.adapter ? true : deleted });
|
|
1226
|
+
return this.adapter ? true : deleted;
|
|
1227
|
+
}
|
|
1112
1228
|
clear() {
|
|
1113
1229
|
const count = this.entries.size;
|
|
1114
1230
|
this.entries.clear();
|
|
@@ -1117,6 +1233,10 @@ var _FarmDataCache = class _FarmDataCache {
|
|
|
1117
1233
|
this.version = 0;
|
|
1118
1234
|
emitFarmEvent({ type: "cache.clear", count });
|
|
1119
1235
|
}
|
|
1236
|
+
async clearAsync() {
|
|
1237
|
+
this.clear();
|
|
1238
|
+
await this.adapter?.clear?.();
|
|
1239
|
+
}
|
|
1120
1240
|
isStale(entry, now2 = Date.now()) {
|
|
1121
1241
|
if (typeof entry.revalidate === "number" && entry.revalidate > 0 && now2 - entry.createdAt >= entry.revalidate * 1e3) {
|
|
1122
1242
|
return true;
|
|
@@ -1129,6 +1249,12 @@ var _FarmDataCache = class _FarmDataCache {
|
|
|
1129
1249
|
}
|
|
1130
1250
|
return false;
|
|
1131
1251
|
}
|
|
1252
|
+
async isStaleAsync(entry, now2 = Date.now()) {
|
|
1253
|
+
if (this.adapter) {
|
|
1254
|
+
return this.isAdapterEntryStale(entry, now2);
|
|
1255
|
+
}
|
|
1256
|
+
return this.isStale(entry, now2);
|
|
1257
|
+
}
|
|
1132
1258
|
revalidateTag(tag, options = {}) {
|
|
1133
1259
|
const normalized = normalizeCacheTag(tag);
|
|
1134
1260
|
const count = this.invalidateTag(normalized);
|
|
@@ -1137,6 +1263,15 @@ var _FarmDataCache = class _FarmDataCache {
|
|
|
1137
1263
|
);
|
|
1138
1264
|
return count;
|
|
1139
1265
|
}
|
|
1266
|
+
async revalidateTagAsync(tag, options = {}) {
|
|
1267
|
+
const normalized = normalizeCacheTag(tag);
|
|
1268
|
+
const count = this.invalidateTag(normalized);
|
|
1269
|
+
await this.adapter?.invalidateTags?.([this.createAdapterTag(normalized)]);
|
|
1270
|
+
emitFarmEvent(
|
|
1271
|
+
options.source === "updateTag" ? { type: "cache.updateTag", tag: normalized, count } : { type: "cache.revalidateTag", tag: normalized, profile: options.profile, count }
|
|
1272
|
+
);
|
|
1273
|
+
return count;
|
|
1274
|
+
}
|
|
1140
1275
|
revalidatePath(routePath) {
|
|
1141
1276
|
const normalizedPath = normalizeRevalidatePath(routePath);
|
|
1142
1277
|
const pathTag = createPathCacheTag(normalizedPath);
|
|
@@ -1153,8 +1288,25 @@ var _FarmDataCache = class _FarmDataCache {
|
|
|
1153
1288
|
}
|
|
1154
1289
|
return count;
|
|
1155
1290
|
}
|
|
1291
|
+
async revalidatePathAsync(routePath) {
|
|
1292
|
+
const normalizedPath = normalizeRevalidatePath(routePath);
|
|
1293
|
+
const pathTag = createPathCacheTag(normalizedPath);
|
|
1294
|
+
const pprCount = this.countEntriesForTags([pathTag, "ppr"]);
|
|
1295
|
+
const count = this.invalidateTag(pathTag);
|
|
1296
|
+
await this.adapter?.invalidateTags?.([this.createAdapterTag(pathTag)]);
|
|
1297
|
+
emitFarmEvent({ type: "cache.revalidatePath", path: normalizedPath, count });
|
|
1298
|
+
if (pprCount > 0) {
|
|
1299
|
+
emitFarmEvent({
|
|
1300
|
+
type: "ppr.shell.invalidated",
|
|
1301
|
+
route: normalizedPath,
|
|
1302
|
+
reason: "revalidatePath",
|
|
1303
|
+
count: pprCount
|
|
1304
|
+
});
|
|
1305
|
+
}
|
|
1306
|
+
return count;
|
|
1307
|
+
}
|
|
1156
1308
|
async getOrSet(key, producer, options = {}) {
|
|
1157
|
-
const cached = this.
|
|
1309
|
+
const cached = await this.getEntryAsync(key);
|
|
1158
1310
|
if (cached) {
|
|
1159
1311
|
return cached.value;
|
|
1160
1312
|
}
|
|
@@ -1163,10 +1315,8 @@ var _FarmDataCache = class _FarmDataCache {
|
|
|
1163
1315
|
emitFarmEvent({ type: "cache.dedupe", key });
|
|
1164
1316
|
return inflight;
|
|
1165
1317
|
}
|
|
1166
|
-
const
|
|
1167
|
-
|
|
1168
|
-
return value;
|
|
1169
|
-
}).catch((error) => {
|
|
1318
|
+
const tags = Array.from(normalizeCacheOptionsTags(options));
|
|
1319
|
+
const promise = this.fillCacheEntry(key, producer, options, tags).catch((error) => {
|
|
1170
1320
|
emitFarmEvent({ type: "cache.error", key, operation: "set", error });
|
|
1171
1321
|
throw error;
|
|
1172
1322
|
}).finally(() => {
|
|
@@ -1175,6 +1325,40 @@ var _FarmDataCache = class _FarmDataCache {
|
|
|
1175
1325
|
this.inflight.set(key, promise);
|
|
1176
1326
|
return promise;
|
|
1177
1327
|
}
|
|
1328
|
+
async fillCacheEntry(key, producer, options, tags) {
|
|
1329
|
+
const leaseKey = `${this.namespace}:lease:${key}`;
|
|
1330
|
+
let leaseToken;
|
|
1331
|
+
if (this.adapter?.acquireLease && this.adapter.releaseLease && this.lease.enabled) {
|
|
1332
|
+
leaseToken = await this.adapter.acquireLease(leaseKey, this.lease.ttlMs);
|
|
1333
|
+
if (!leaseToken) {
|
|
1334
|
+
const shared = await this.waitForAdapterEntry(key);
|
|
1335
|
+
if (shared) {
|
|
1336
|
+
emitFarmEvent({ type: "cache.dedupe", key });
|
|
1337
|
+
return shared.value;
|
|
1338
|
+
}
|
|
1339
|
+
leaseToken = await this.adapter.acquireLease(leaseKey, this.lease.ttlMs);
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
try {
|
|
1343
|
+
const initialTagVersions = await this.getAdapterTagVersions(tags);
|
|
1344
|
+
const value = await producer();
|
|
1345
|
+
await this.setAsync(key, value, options, initialTagVersions);
|
|
1346
|
+
return value;
|
|
1347
|
+
} finally {
|
|
1348
|
+
if (leaseToken && this.adapter?.releaseLease) {
|
|
1349
|
+
await this.adapter.releaseLease(leaseKey, leaseToken);
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
async waitForAdapterEntry(key) {
|
|
1354
|
+
const deadline = Date.now() + this.lease.waitTimeoutMs;
|
|
1355
|
+
while (Date.now() < deadline) {
|
|
1356
|
+
await delay(this.lease.pollIntervalMs);
|
|
1357
|
+
const entry = await this.getEntryAsync(key);
|
|
1358
|
+
if (entry) return entry;
|
|
1359
|
+
}
|
|
1360
|
+
return void 0;
|
|
1361
|
+
}
|
|
1178
1362
|
countEntriesForTag(tag) {
|
|
1179
1363
|
let count = 0;
|
|
1180
1364
|
for (const entry of this.entries.values()) {
|
|
@@ -1202,11 +1386,53 @@ var _FarmDataCache = class _FarmDataCache {
|
|
|
1202
1386
|
key: entry.key,
|
|
1203
1387
|
value: entry.value,
|
|
1204
1388
|
tags: Array.from(entry.tags),
|
|
1389
|
+
tagVersions: entry.tagVersions,
|
|
1205
1390
|
createdAt: entry.createdAt,
|
|
1206
1391
|
createdVersion: entry.createdVersion,
|
|
1207
1392
|
revalidate: entry.revalidate
|
|
1208
1393
|
};
|
|
1209
1394
|
}
|
|
1395
|
+
hydrateLocalEntry(entry) {
|
|
1396
|
+
this.entries.set(entry.key, {
|
|
1397
|
+
key: entry.key,
|
|
1398
|
+
value: entry.value,
|
|
1399
|
+
tags: new Set(entry.tags.map(normalizeCacheTag)),
|
|
1400
|
+
tagVersions: entry.tagVersions,
|
|
1401
|
+
createdAt: entry.createdAt,
|
|
1402
|
+
createdVersion: entry.createdVersion ?? ++this.version,
|
|
1403
|
+
revalidate: normalizeRevalidate(entry.revalidate)
|
|
1404
|
+
});
|
|
1405
|
+
}
|
|
1406
|
+
createAdapterKey(key) {
|
|
1407
|
+
return `${this.namespace}:entry:${key}`;
|
|
1408
|
+
}
|
|
1409
|
+
createAdapterTag(tag) {
|
|
1410
|
+
return `${this.namespace}:tag:${tag}`;
|
|
1411
|
+
}
|
|
1412
|
+
async getAdapterTagVersions(tags) {
|
|
1413
|
+
if (!this.adapter?.getTagVersions || tags.length === 0) return {};
|
|
1414
|
+
const normalized = tags.map(normalizeCacheTag);
|
|
1415
|
+
const physicalTags = normalized.map((tag) => this.createAdapterTag(tag));
|
|
1416
|
+
const versions = await this.adapter.getTagVersions(physicalTags);
|
|
1417
|
+
return Object.fromEntries(
|
|
1418
|
+
normalized.map((tag, index) => [
|
|
1419
|
+
tag,
|
|
1420
|
+
normalizeAdapterVersion(versions[physicalTags[index]])
|
|
1421
|
+
])
|
|
1422
|
+
);
|
|
1423
|
+
}
|
|
1424
|
+
async isAdapterEntryStale(entry, now2 = Date.now()) {
|
|
1425
|
+
if (typeof entry.revalidate === "number" && entry.revalidate > 0 && now2 - entry.createdAt >= entry.revalidate * 1e3) {
|
|
1426
|
+
return true;
|
|
1427
|
+
}
|
|
1428
|
+
const currentVersions = await this.getAdapterTagVersions(entry.tags);
|
|
1429
|
+
for (const tag of entry.tags) {
|
|
1430
|
+
if (normalizeAdapterVersion(currentVersions[tag]) > normalizeAdapterVersion(entry.tagVersions?.[tag])) {
|
|
1431
|
+
return true;
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
return false;
|
|
1435
|
+
}
|
|
1210
1436
|
};
|
|
1211
1437
|
__name(_FarmDataCache, "FarmDataCache");
|
|
1212
1438
|
var FarmDataCache = _FarmDataCache;
|
|
@@ -1271,6 +1497,52 @@ function normalizeCacheTag(tag) {
|
|
|
1271
1497
|
return normalized;
|
|
1272
1498
|
}
|
|
1273
1499
|
__name(normalizeCacheTag, "normalizeCacheTag");
|
|
1500
|
+
function normalizeCacheNamespace(namespace) {
|
|
1501
|
+
if (typeof namespace !== "string") {
|
|
1502
|
+
throw new TypeError("Cache namespace must be a string.");
|
|
1503
|
+
}
|
|
1504
|
+
const normalized = namespace.trim().replace(/:+$/g, "");
|
|
1505
|
+
if (!normalized) {
|
|
1506
|
+
throw new Error("Cache namespace cannot be empty.");
|
|
1507
|
+
}
|
|
1508
|
+
return normalized;
|
|
1509
|
+
}
|
|
1510
|
+
__name(normalizeCacheNamespace, "normalizeCacheNamespace");
|
|
1511
|
+
function normalizeAdapterVersion(value) {
|
|
1512
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
|
|
1513
|
+
}
|
|
1514
|
+
__name(normalizeAdapterVersion, "normalizeAdapterVersion");
|
|
1515
|
+
function normalizePositiveDuration(value, fallback, name) {
|
|
1516
|
+
if (value === void 0) return fallback;
|
|
1517
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
1518
|
+
throw new TypeError(`${name} must be a positive number of milliseconds.`);
|
|
1519
|
+
}
|
|
1520
|
+
return Math.floor(value);
|
|
1521
|
+
}
|
|
1522
|
+
__name(normalizePositiveDuration, "normalizePositiveDuration");
|
|
1523
|
+
function delay(ms) {
|
|
1524
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1525
|
+
}
|
|
1526
|
+
__name(delay, "delay");
|
|
1527
|
+
function normalizeCacheOptionsTags(options) {
|
|
1528
|
+
const tags = /* @__PURE__ */ new Set();
|
|
1529
|
+
for (const tag of options.tags ?? []) {
|
|
1530
|
+
tags.add(normalizeCacheTag(tag));
|
|
1531
|
+
}
|
|
1532
|
+
for (const routePath of options.paths ?? []) {
|
|
1533
|
+
tags.add(createPathCacheTag(routePath));
|
|
1534
|
+
}
|
|
1535
|
+
return tags;
|
|
1536
|
+
}
|
|
1537
|
+
__name(normalizeCacheOptionsTags, "normalizeCacheOptionsTags");
|
|
1538
|
+
function assertFarmCacheEntry(entry, expectedKey) {
|
|
1539
|
+
if (!entry || typeof entry !== "object" || entry.key !== expectedKey || !Array.isArray(entry.tags) || typeof entry.createdAt !== "number") {
|
|
1540
|
+
throw new TypeError(
|
|
1541
|
+
`Cache adapter returned an invalid entry for ${JSON.stringify(expectedKey)}.`
|
|
1542
|
+
);
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
__name(assertFarmCacheEntry, "assertFarmCacheEntry");
|
|
1274
1546
|
function getFunctionCacheIdentity(fn) {
|
|
1275
1547
|
if (fn.name) {
|
|
1276
1548
|
return `name:${fn.name}`;
|
|
@@ -1467,8 +1739,74 @@ function normalizeFarmClientCacheKey(key) {
|
|
|
1467
1739
|
}
|
|
1468
1740
|
__name(normalizeFarmClientCacheKey, "normalizeFarmClientCacheKey");
|
|
1469
1741
|
|
|
1742
|
+
// src/api/transport.ts
|
|
1743
|
+
function isJSONStreamResponse(response) {
|
|
1744
|
+
const contentType = response.headers?.get?.("content-type")?.toLowerCase() ?? "";
|
|
1745
|
+
return contentType.includes("application/x-ndjson") || contentType.includes("application/ndjson");
|
|
1746
|
+
}
|
|
1747
|
+
__name(isJSONStreamResponse, "isJSONStreamResponse");
|
|
1748
|
+
function readJSONStream(response) {
|
|
1749
|
+
if (!response.body) {
|
|
1750
|
+
throw new TypeError("Cannot read a JSON stream response without a body");
|
|
1751
|
+
}
|
|
1752
|
+
const reader = response.body.getReader();
|
|
1753
|
+
const decoder = new TextDecoder();
|
|
1754
|
+
let buffer = "";
|
|
1755
|
+
let completed = false;
|
|
1756
|
+
let claimed = false;
|
|
1757
|
+
const iterator = {
|
|
1758
|
+
async next() {
|
|
1759
|
+
while (true) {
|
|
1760
|
+
const lineEnd = buffer.indexOf("\n");
|
|
1761
|
+
if (lineEnd >= 0) {
|
|
1762
|
+
const line = buffer.slice(0, lineEnd).trim();
|
|
1763
|
+
buffer = buffer.slice(lineEnd + 1);
|
|
1764
|
+
if (!line) continue;
|
|
1765
|
+
return { done: false, value: JSON.parse(line) };
|
|
1766
|
+
}
|
|
1767
|
+
if (completed) {
|
|
1768
|
+
const line = buffer.trim();
|
|
1769
|
+
buffer = "";
|
|
1770
|
+
if (!line) return { done: true, value: void 0 };
|
|
1771
|
+
return { done: false, value: JSON.parse(line) };
|
|
1772
|
+
}
|
|
1773
|
+
const chunk = await reader.read();
|
|
1774
|
+
completed = chunk.done;
|
|
1775
|
+
buffer += decoder.decode(chunk.value, { stream: !chunk.done });
|
|
1776
|
+
}
|
|
1777
|
+
},
|
|
1778
|
+
async return() {
|
|
1779
|
+
completed = true;
|
|
1780
|
+
buffer = "";
|
|
1781
|
+
await reader.cancel();
|
|
1782
|
+
return { done: true, value: void 0 };
|
|
1783
|
+
}
|
|
1784
|
+
};
|
|
1785
|
+
return {
|
|
1786
|
+
response,
|
|
1787
|
+
async cancel(reason) {
|
|
1788
|
+
completed = true;
|
|
1789
|
+
buffer = "";
|
|
1790
|
+
await reader.cancel(reason);
|
|
1791
|
+
},
|
|
1792
|
+
[Symbol.asyncIterator]() {
|
|
1793
|
+
if (claimed) {
|
|
1794
|
+
throw new TypeError("Farm API streams can only be consumed once");
|
|
1795
|
+
}
|
|
1796
|
+
claimed = true;
|
|
1797
|
+
return iterator;
|
|
1798
|
+
}
|
|
1799
|
+
};
|
|
1800
|
+
}
|
|
1801
|
+
__name(readJSONStream, "readJSONStream");
|
|
1802
|
+
function isFarmAPIStream(value) {
|
|
1803
|
+
return typeof value === "object" && value !== null && "response" in value && typeof value.cancel === "function" && typeof value[Symbol.asyncIterator] === "function";
|
|
1804
|
+
}
|
|
1805
|
+
__name(isFarmAPIStream, "isFarmAPIStream");
|
|
1806
|
+
|
|
1470
1807
|
// src/api/client.ts
|
|
1471
1808
|
var FARM_API_ROUTE_REF_SYMBOL = /* @__PURE__ */ Symbol.for("farm.api.route-ref");
|
|
1809
|
+
var FARM_API_ROUTE_META_SYMBOL = /* @__PURE__ */ Symbol.for("farm.api.route-meta");
|
|
1472
1810
|
var _APIClientError = class _APIClientError extends Error {
|
|
1473
1811
|
constructor(code, data, options) {
|
|
1474
1812
|
super(options.message);
|
|
@@ -1506,16 +1844,22 @@ function createAPIClient(options = {}) {
|
|
|
1506
1844
|
}
|
|
1507
1845
|
});
|
|
1508
1846
|
}
|
|
1847
|
+
const headers = {
|
|
1848
|
+
"Content-Type": "application/json",
|
|
1849
|
+
...options.headers,
|
|
1850
|
+
...requestOptions.headers
|
|
1851
|
+
};
|
|
1509
1852
|
const fetchOptions = {
|
|
1510
1853
|
method: requestOptions.method || "GET",
|
|
1511
|
-
headers
|
|
1512
|
-
"Content-Type": "application/json",
|
|
1513
|
-
...options.headers,
|
|
1514
|
-
...requestOptions.headers
|
|
1515
|
-
}
|
|
1854
|
+
headers
|
|
1516
1855
|
};
|
|
1517
|
-
if (requestOptions.body) {
|
|
1518
|
-
|
|
1856
|
+
if (requestOptions.body !== void 0) {
|
|
1857
|
+
if (isFormData(requestOptions.body)) {
|
|
1858
|
+
deleteHeader(headers, "content-type");
|
|
1859
|
+
fetchOptions.body = requestOptions.body;
|
|
1860
|
+
} else {
|
|
1861
|
+
fetchOptions.body = JSON.stringify(requestOptions.body);
|
|
1862
|
+
}
|
|
1519
1863
|
}
|
|
1520
1864
|
const response = await fetch(url.toString(), fetchOptions);
|
|
1521
1865
|
applyFarmCacheInvalidations(
|
|
@@ -1523,7 +1867,7 @@ function createAPIClient(options = {}) {
|
|
|
1523
1867
|
);
|
|
1524
1868
|
let data = void 0;
|
|
1525
1869
|
if (response.status !== 204 && response.status !== 205) {
|
|
1526
|
-
data = await response.json();
|
|
1870
|
+
data = isJSONStreamResponse(response) ? readJSONStream(response) : await response.json();
|
|
1527
1871
|
}
|
|
1528
1872
|
return { response, data };
|
|
1529
1873
|
}, "fetchClient");
|
|
@@ -1669,16 +2013,16 @@ function createAPIClient(options = {}) {
|
|
|
1669
2013
|
}
|
|
1670
2014
|
}
|
|
1671
2015
|
attempt += 1;
|
|
1672
|
-
const
|
|
1673
|
-
if (
|
|
1674
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
2016
|
+
const delay2 = typeof clientOptions?.retry?.delay === "function" ? clientOptions.retry.delay(attempt) : clientOptions?.retry?.delay ?? 0;
|
|
2017
|
+
if (delay2 > 0) {
|
|
2018
|
+
await new Promise((resolve) => setTimeout(resolve, delay2));
|
|
1675
2019
|
}
|
|
1676
2020
|
}
|
|
1677
2021
|
})();
|
|
1678
2022
|
inflightState.set(cacheKey, { promise, startedAt: now2 });
|
|
1679
2023
|
try {
|
|
1680
2024
|
const result2 = await promise;
|
|
1681
|
-
if (!result2.error && isCacheEnabled) {
|
|
2025
|
+
if (!result2.error && isCacheEnabled && !isFarmAPIStream(result2.data)) {
|
|
1682
2026
|
const updatedAt = Date.now();
|
|
1683
2027
|
cacheState.set(cacheKey, {
|
|
1684
2028
|
data: result2.data,
|
|
@@ -1751,10 +2095,17 @@ function createAPIClient(options = {}) {
|
|
|
1751
2095
|
clientOptions?.onSettled?.(result.data, result.error);
|
|
1752
2096
|
return result;
|
|
1753
2097
|
}, "request");
|
|
1754
|
-
return createNestedProxy(
|
|
2098
|
+
return createNestedProxy(
|
|
2099
|
+
[],
|
|
2100
|
+
request,
|
|
2101
|
+
routeMeta,
|
|
2102
|
+
baseURL,
|
|
2103
|
+
options.baseURL === void 0,
|
|
2104
|
+
rootAliases
|
|
2105
|
+
);
|
|
1755
2106
|
}
|
|
1756
2107
|
__name(createAPIClient, "createAPIClient");
|
|
1757
|
-
function createNestedProxy(path, client, routeMeta, baseURL, rootAliases) {
|
|
2108
|
+
function createNestedProxy(path, client, routeMeta, baseURL, sameOrigin, rootAliases) {
|
|
1758
2109
|
const target = /* @__PURE__ */ __name(() => {
|
|
1759
2110
|
}, "target");
|
|
1760
2111
|
const proxy = new Proxy(target, {
|
|
@@ -1763,13 +2114,29 @@ function createNestedProxy(path, client, routeMeta, baseURL, rootAliases) {
|
|
|
1763
2114
|
if (prop === FARM_API_ROUTE_REF_SYMBOL) {
|
|
1764
2115
|
return path.length > 0;
|
|
1765
2116
|
}
|
|
2117
|
+
if (prop === FARM_API_ROUTE_META_SYMBOL) {
|
|
2118
|
+
const metadata = resolveRouteMeta({ path, baseURL });
|
|
2119
|
+
return Object.freeze({
|
|
2120
|
+
path: metadata.routePath,
|
|
2121
|
+
method: metadata.method,
|
|
2122
|
+
baseURL,
|
|
2123
|
+
sameOrigin
|
|
2124
|
+
});
|
|
2125
|
+
}
|
|
1766
2126
|
if (path.length === 0 && typeof prop === "string" && rootAliases && prop in rootAliases) {
|
|
1767
2127
|
return rootAliases[prop];
|
|
1768
2128
|
}
|
|
1769
2129
|
if (typeof prop !== "string") {
|
|
1770
2130
|
return Reflect.get(_target, prop);
|
|
1771
2131
|
}
|
|
1772
|
-
return createNestedProxy(
|
|
2132
|
+
return createNestedProxy(
|
|
2133
|
+
[...path, prop],
|
|
2134
|
+
client,
|
|
2135
|
+
routeMeta,
|
|
2136
|
+
baseURL,
|
|
2137
|
+
sameOrigin,
|
|
2138
|
+
rootAliases
|
|
2139
|
+
);
|
|
1773
2140
|
},
|
|
1774
2141
|
// When calling as a function
|
|
1775
2142
|
apply(_target, _thisArg, args) {
|
|
@@ -1795,6 +2162,22 @@ function isAPIRouteRef(value) {
|
|
|
1795
2162
|
return typeof value === "function" && value[FARM_API_ROUTE_REF_SYMBOL] === true;
|
|
1796
2163
|
}
|
|
1797
2164
|
__name(isAPIRouteRef, "isAPIRouteRef");
|
|
2165
|
+
function getAPIRouteRefMetadata(value) {
|
|
2166
|
+
if (!isAPIRouteRef(value)) return null;
|
|
2167
|
+
const metadata = value[FARM_API_ROUTE_META_SYMBOL];
|
|
2168
|
+
if (!metadata || typeof metadata !== "object") return null;
|
|
2169
|
+
const candidate = metadata;
|
|
2170
|
+
if (typeof candidate.path !== "string" || typeof candidate.method !== "string" || typeof candidate.baseURL !== "string" || typeof candidate.sameOrigin !== "boolean") {
|
|
2171
|
+
return null;
|
|
2172
|
+
}
|
|
2173
|
+
return {
|
|
2174
|
+
path: candidate.path,
|
|
2175
|
+
method: candidate.method,
|
|
2176
|
+
baseURL: candidate.baseURL,
|
|
2177
|
+
sameOrigin: candidate.sameOrigin
|
|
2178
|
+
};
|
|
2179
|
+
}
|
|
2180
|
+
__name(getAPIRouteRefMetadata, "getAPIRouteRefMetadata");
|
|
1798
2181
|
function createServerAPIClient(endpoints, options = {}) {
|
|
1799
2182
|
if (options.integrations === false || Object.prototype.hasOwnProperty.call(endpoints, "integrations")) {
|
|
1800
2183
|
return endpoints;
|
|
@@ -1899,6 +2282,17 @@ function normalizeError(error) {
|
|
|
1899
2282
|
return normalized;
|
|
1900
2283
|
}
|
|
1901
2284
|
__name(normalizeError, "normalizeError");
|
|
2285
|
+
function isFormData(value) {
|
|
2286
|
+
return typeof value === "object" && value !== null && (typeof FormData !== "undefined" && value instanceof FormData || Object.prototype.toString.call(value) === "[object FormData]" && typeof value.entries === "function");
|
|
2287
|
+
}
|
|
2288
|
+
__name(isFormData, "isFormData");
|
|
2289
|
+
function deleteHeader(headers, name) {
|
|
2290
|
+
const normalized = name.toLowerCase();
|
|
2291
|
+
for (const key of Object.keys(headers)) {
|
|
2292
|
+
if (key.toLowerCase() === normalized) delete headers[key];
|
|
2293
|
+
}
|
|
2294
|
+
}
|
|
2295
|
+
__name(deleteHeader, "deleteHeader");
|
|
1902
2296
|
function createResponseError2(response, data) {
|
|
1903
2297
|
const expected = readEndpointErrorEnvelope(data);
|
|
1904
2298
|
if (expected) {
|
|
@@ -2089,8 +2483,171 @@ function normalizeMutationError(error) {
|
|
|
2089
2483
|
}
|
|
2090
2484
|
__name(normalizeMutationError, "normalizeMutationError");
|
|
2091
2485
|
|
|
2092
|
-
// src/
|
|
2486
|
+
// src/fetcher-client.tsx
|
|
2093
2487
|
var import_react2 = require("react");
|
|
2488
|
+
var formDataContexts = /* @__PURE__ */ new WeakMap();
|
|
2489
|
+
function useFetcher(target, options = {}) {
|
|
2490
|
+
const targetRef = (0, import_react2.useRef)(target);
|
|
2491
|
+
const optionsRef = (0, import_react2.useRef)(options);
|
|
2492
|
+
const submissionIdRef = (0, import_react2.useRef)(0);
|
|
2493
|
+
const [formData, setFormData] = (0, import_react2.useState)(null);
|
|
2494
|
+
const mutation = useMutation(target, options);
|
|
2495
|
+
targetRef.current = target;
|
|
2496
|
+
optionsRef.current = options;
|
|
2497
|
+
const submitAsync = (0, import_react2.useCallback)(
|
|
2498
|
+
async (input) => {
|
|
2499
|
+
const submissionId = ++submissionIdRef.current;
|
|
2500
|
+
const submittedFormData = isFormData2(input) ? input : null;
|
|
2501
|
+
setFormData(submittedFormData);
|
|
2502
|
+
try {
|
|
2503
|
+
const variables = submittedFormData ? mapFetcherFormData(targetRef.current, submittedFormData, optionsRef.current) : input;
|
|
2504
|
+
return await mutation.mutateAsync(variables);
|
|
2505
|
+
} finally {
|
|
2506
|
+
if (submissionId === submissionIdRef.current) {
|
|
2507
|
+
setFormData(null);
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2510
|
+
},
|
|
2511
|
+
[mutation.mutateAsync]
|
|
2512
|
+
);
|
|
2513
|
+
const submit = (0, import_react2.useCallback)(
|
|
2514
|
+
(input) => {
|
|
2515
|
+
void submitAsync(input).catch(() => {
|
|
2516
|
+
});
|
|
2517
|
+
},
|
|
2518
|
+
[submitAsync]
|
|
2519
|
+
);
|
|
2520
|
+
const Form = (0, import_react2.useMemo)(() => {
|
|
2521
|
+
const FetcherForm = /* @__PURE__ */ __name(({ action, method, encType, onSubmit, ...props }) => {
|
|
2522
|
+
const targetValue = targetRef.current;
|
|
2523
|
+
const metadata = getAPIRouteRefMetadata(targetValue);
|
|
2524
|
+
const nativeAction = action ?? resolveFetcherFormAction(targetValue, metadata);
|
|
2525
|
+
const nativeMethod = method ?? (metadata && (metadata.method === "GET" || metadata.method === "POST") ? metadata.method.toLowerCase() : metadata ? "post" : void 0);
|
|
2526
|
+
const functionAction = typeof nativeAction === "function";
|
|
2527
|
+
const handleSubmit = /* @__PURE__ */ __name((event) => {
|
|
2528
|
+
onSubmit?.(event);
|
|
2529
|
+
if (event.defaultPrevented) return;
|
|
2530
|
+
event.preventDefault();
|
|
2531
|
+
const submitter = getSubmitter(event);
|
|
2532
|
+
const nextFormData = createSubmitterFormData(event.currentTarget, submitter);
|
|
2533
|
+
formDataContexts.set(nextFormData, {
|
|
2534
|
+
form: event.currentTarget,
|
|
2535
|
+
submitter
|
|
2536
|
+
});
|
|
2537
|
+
void submitAsync(nextFormData).catch(() => {
|
|
2538
|
+
});
|
|
2539
|
+
}, "handleSubmit");
|
|
2540
|
+
return (0, import_react2.createElement)("form", {
|
|
2541
|
+
...props,
|
|
2542
|
+
action: nativeAction,
|
|
2543
|
+
method: functionAction ? void 0 : nativeMethod,
|
|
2544
|
+
encType: functionAction ? void 0 : encType,
|
|
2545
|
+
onSubmit: handleSubmit
|
|
2546
|
+
});
|
|
2547
|
+
}, "FetcherForm");
|
|
2548
|
+
FetcherForm.displayName = "FetcherForm";
|
|
2549
|
+
return FetcherForm;
|
|
2550
|
+
}, [submitAsync]);
|
|
2551
|
+
const reset = (0, import_react2.useCallback)(() => {
|
|
2552
|
+
submissionIdRef.current += 1;
|
|
2553
|
+
setFormData(null);
|
|
2554
|
+
mutation.reset();
|
|
2555
|
+
}, [mutation.reset]);
|
|
2556
|
+
return (0, import_react2.useMemo)(
|
|
2557
|
+
() => ({
|
|
2558
|
+
state: mutation.pending ? "submitting" : "idle",
|
|
2559
|
+
status: mutation.status,
|
|
2560
|
+
pending: mutation.pending,
|
|
2561
|
+
data: mutation.data,
|
|
2562
|
+
error: mutation.error,
|
|
2563
|
+
variables: mutation.variables,
|
|
2564
|
+
formData,
|
|
2565
|
+
submit,
|
|
2566
|
+
submitAsync,
|
|
2567
|
+
Form,
|
|
2568
|
+
reset
|
|
2569
|
+
}),
|
|
2570
|
+
[
|
|
2571
|
+
Form,
|
|
2572
|
+
formData,
|
|
2573
|
+
mutation.data,
|
|
2574
|
+
mutation.error,
|
|
2575
|
+
mutation.pending,
|
|
2576
|
+
mutation.status,
|
|
2577
|
+
mutation.variables,
|
|
2578
|
+
reset,
|
|
2579
|
+
submit,
|
|
2580
|
+
submitAsync
|
|
2581
|
+
]
|
|
2582
|
+
);
|
|
2583
|
+
}
|
|
2584
|
+
__name(useFetcher, "useFetcher");
|
|
2585
|
+
function mapFetcherFormData(target, formData, options) {
|
|
2586
|
+
const context = formDataContexts.get(formData) ?? { form: null, submitter: null };
|
|
2587
|
+
if (options.mapFormData) {
|
|
2588
|
+
return options.mapFormData(formData, context);
|
|
2589
|
+
}
|
|
2590
|
+
if (!isAPIRouteRef(target)) {
|
|
2591
|
+
return formData;
|
|
2592
|
+
}
|
|
2593
|
+
const values = formDataToObject(formData);
|
|
2594
|
+
const method = getAPIRouteRefMetadata(target)?.method;
|
|
2595
|
+
return method === "GET" || method === "HEAD" ? { query: values } : { body: values };
|
|
2596
|
+
}
|
|
2597
|
+
__name(mapFetcherFormData, "mapFetcherFormData");
|
|
2598
|
+
function resolveFetcherFormAction(target, metadata) {
|
|
2599
|
+
if (!metadata) return isProgressiveFormAction(target) ? target : void 0;
|
|
2600
|
+
if (metadata.sameOrigin) return metadata.path;
|
|
2601
|
+
return new URL(metadata.path, metadata.baseURL).href;
|
|
2602
|
+
}
|
|
2603
|
+
__name(resolveFetcherFormAction, "resolveFetcherFormAction");
|
|
2604
|
+
function formDataToObject(formData) {
|
|
2605
|
+
const output = /* @__PURE__ */ Object.create(null);
|
|
2606
|
+
for (const [key, value] of formData.entries()) {
|
|
2607
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
|
|
2608
|
+
const current = output[key];
|
|
2609
|
+
if (current === void 0) {
|
|
2610
|
+
output[key] = value;
|
|
2611
|
+
} else if (Array.isArray(current)) {
|
|
2612
|
+
current.push(value);
|
|
2613
|
+
} else {
|
|
2614
|
+
output[key] = [current, value];
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
return output;
|
|
2618
|
+
}
|
|
2619
|
+
__name(formDataToObject, "formDataToObject");
|
|
2620
|
+
function createSubmitterFormData(form, submitter) {
|
|
2621
|
+
try {
|
|
2622
|
+
return new FormData(form, submitter);
|
|
2623
|
+
} catch {
|
|
2624
|
+
const formData = new FormData(form);
|
|
2625
|
+
const candidate = submitter;
|
|
2626
|
+
if (candidate && !candidate.disabled && candidate.name) {
|
|
2627
|
+
formData.append(candidate.name, candidate.value ?? "");
|
|
2628
|
+
}
|
|
2629
|
+
return formData;
|
|
2630
|
+
}
|
|
2631
|
+
}
|
|
2632
|
+
__name(createSubmitterFormData, "createSubmitterFormData");
|
|
2633
|
+
function getSubmitter(event) {
|
|
2634
|
+
const nativeEvent = event.nativeEvent;
|
|
2635
|
+
return nativeEvent.submitter instanceof HTMLElement ? nativeEvent.submitter : null;
|
|
2636
|
+
}
|
|
2637
|
+
__name(getSubmitter, "getSubmitter");
|
|
2638
|
+
function isProgressiveFormAction(target) {
|
|
2639
|
+
const candidate = target;
|
|
2640
|
+
return candidate.__farmServerFn === true || typeof candidate.$$FORM_ACTION === "function" || candidate.$$typeof === /* @__PURE__ */ Symbol.for("react.server.reference");
|
|
2641
|
+
}
|
|
2642
|
+
__name(isProgressiveFormAction, "isProgressiveFormAction");
|
|
2643
|
+
function isFormData2(value) {
|
|
2644
|
+
if (!value || typeof value !== "object") return false;
|
|
2645
|
+
return typeof FormData !== "undefined" && value instanceof FormData || Object.prototype.toString.call(value) === "[object FormData]" && typeof value.entries === "function";
|
|
2646
|
+
}
|
|
2647
|
+
__name(isFormData2, "isFormData");
|
|
2648
|
+
|
|
2649
|
+
// src/server-query-client.ts
|
|
2650
|
+
var import_react3 = require("react");
|
|
2094
2651
|
var FARM_SERVER_QUERY_CLIENT_STATE = /* @__PURE__ */ Symbol.for("farm.serverQueryClientState");
|
|
2095
2652
|
var serverQueryClientGlobal = globalThis;
|
|
2096
2653
|
var serverQueryClientState = serverQueryClientGlobal[FARM_SERVER_QUERY_CLIENT_STATE] ?? (serverQueryClientGlobal[FARM_SERVER_QUERY_CLIENT_STATE] = {
|
|
@@ -2122,25 +2679,25 @@ __name(prefetchServerQuery, "prefetchServerQuery");
|
|
|
2122
2679
|
function useServerQuery(query, input, options = {}) {
|
|
2123
2680
|
const cache = getFarmClientDataCache();
|
|
2124
2681
|
const key = createServerQueryCallKey(query, input);
|
|
2125
|
-
const inputRef = (0,
|
|
2126
|
-
const optionsRef = (0,
|
|
2127
|
-
const mountedKeyRef = (0,
|
|
2682
|
+
const inputRef = (0, import_react3.useRef)(input);
|
|
2683
|
+
const optionsRef = (0, import_react3.useRef)(options);
|
|
2684
|
+
const mountedKeyRef = (0, import_react3.useRef)();
|
|
2128
2685
|
inputRef.current = input;
|
|
2129
2686
|
optionsRef.current = options;
|
|
2130
|
-
const subscribe = (0,
|
|
2687
|
+
const subscribe = (0, import_react3.useCallback)(
|
|
2131
2688
|
(listener) => cache.subscribe(key, listener),
|
|
2132
2689
|
[cache, key]
|
|
2133
2690
|
);
|
|
2134
|
-
const getSnapshot = (0,
|
|
2135
|
-
const entry = (0,
|
|
2136
|
-
const run = (0,
|
|
2691
|
+
const getSnapshot = (0, import_react3.useCallback)(() => cache.get(key), [cache, key]);
|
|
2692
|
+
const entry = (0, import_react3.useSyncExternalStore)(subscribe, getSnapshot, () => void 0);
|
|
2693
|
+
const run = (0, import_react3.useCallback)(
|
|
2137
2694
|
(force = false) => fetchServerQuery(query, inputRef.current, {
|
|
2138
2695
|
...optionsRef.current,
|
|
2139
2696
|
force
|
|
2140
2697
|
}),
|
|
2141
2698
|
[query]
|
|
2142
2699
|
);
|
|
2143
|
-
(0,
|
|
2700
|
+
(0, import_react3.useEffect)(() => {
|
|
2144
2701
|
if (options.enabled === false) return;
|
|
2145
2702
|
const firstReadForKey = mountedKeyRef.current !== key;
|
|
2146
2703
|
if (firstReadForKey) mountedKeyRef.current = key;
|
|
@@ -2148,7 +2705,7 @@ function useServerQuery(query, input, options = {}) {
|
|
|
2148
2705
|
void run().catch(() => void 0);
|
|
2149
2706
|
}
|
|
2150
2707
|
}, [cache, entry, key, options.enabled, run]);
|
|
2151
|
-
(0,
|
|
2708
|
+
(0, import_react3.useEffect)(() => {
|
|
2152
2709
|
if (options.enabled === false || typeof window === "undefined") return;
|
|
2153
2710
|
const refreshIfStale = /* @__PURE__ */ __name(() => {
|
|
2154
2711
|
if (cache.isStale(key)) void run().catch(() => void 0);
|
|
@@ -2461,7 +3018,7 @@ var api = {
|
|
|
2461
3018
|
var endpoint = api;
|
|
2462
3019
|
|
|
2463
3020
|
// src/store.ts
|
|
2464
|
-
var
|
|
3021
|
+
var import_react4 = require("react");
|
|
2465
3022
|
var RESERVED_STORE_KEYS = /* @__PURE__ */ new Set([
|
|
2466
3023
|
"use",
|
|
2467
3024
|
"get",
|
|
@@ -2593,20 +3150,20 @@ function createStore(initialState, extend) {
|
|
|
2593
3150
|
}
|
|
2594
3151
|
return lastSlice;
|
|
2595
3152
|
}, "getSnapshot");
|
|
2596
|
-
return (0,
|
|
3153
|
+
return (0, import_react4.useSyncExternalStore)(
|
|
2597
3154
|
(notify) => addSubscription(keys, () => notify()),
|
|
2598
3155
|
getSnapshot,
|
|
2599
3156
|
getSnapshot
|
|
2600
3157
|
);
|
|
2601
3158
|
}
|
|
2602
3159
|
if (typeof keyOrKeys === "string") {
|
|
2603
|
-
return (0,
|
|
3160
|
+
return (0, import_react4.useSyncExternalStore)(
|
|
2604
3161
|
(notify) => addSubscription([keyOrKeys], () => notify()),
|
|
2605
3162
|
() => state[keyOrKeys],
|
|
2606
3163
|
() => state[keyOrKeys]
|
|
2607
3164
|
);
|
|
2608
3165
|
}
|
|
2609
|
-
return (0,
|
|
3166
|
+
return (0, import_react4.useSyncExternalStore)(
|
|
2610
3167
|
(notify) => addSubscription(null, () => notify()),
|
|
2611
3168
|
() => state,
|
|
2612
3169
|
() => state
|
|
@@ -2658,7 +3215,7 @@ function createStore(initialState, extend) {
|
|
|
2658
3215
|
__name(createStore, "createStore");
|
|
2659
3216
|
|
|
2660
3217
|
// src/client/link.tsx
|
|
2661
|
-
var
|
|
3218
|
+
var import_react5 = require("react");
|
|
2662
3219
|
|
|
2663
3220
|
// src/router.ts
|
|
2664
3221
|
function createFarmRouter(routes) {
|
|
@@ -3058,9 +3615,9 @@ function LinkInner({
|
|
|
3058
3615
|
onTouchStart,
|
|
3059
3616
|
...props
|
|
3060
3617
|
}, ref) {
|
|
3061
|
-
const elementRef = (0,
|
|
3062
|
-
const intentTimeoutRef = (0,
|
|
3063
|
-
const hasPrefetched = (0,
|
|
3618
|
+
const elementRef = (0, import_react5.useRef)(null);
|
|
3619
|
+
const intentTimeoutRef = (0, import_react5.useRef)(null);
|
|
3620
|
+
const hasPrefetched = (0, import_react5.useRef)(false);
|
|
3064
3621
|
const { intent, viewport, render } = normalizePrefetch(prefetch2);
|
|
3065
3622
|
const baseHref = resolveLinkHref(href, params, {
|
|
3066
3623
|
query,
|
|
@@ -3069,17 +3626,17 @@ function LinkInner({
|
|
|
3069
3626
|
});
|
|
3070
3627
|
const resolvedHref = localizeActiveFarmHref(baseHref, locale);
|
|
3071
3628
|
const isExternal = isExternalUrl(resolvedHref);
|
|
3072
|
-
const doPrefetch = (0,
|
|
3629
|
+
const doPrefetch = (0, import_react5.useCallback)(() => {
|
|
3073
3630
|
if (isExternal || hasPrefetched.current) return;
|
|
3074
3631
|
const router = getRouter();
|
|
3075
3632
|
if (!router) return;
|
|
3076
3633
|
hasPrefetched.current = true;
|
|
3077
3634
|
router.prefetch(resolvedHref);
|
|
3078
3635
|
}, [resolvedHref, isExternal]);
|
|
3079
|
-
(0,
|
|
3636
|
+
(0, import_react5.useEffect)(() => {
|
|
3080
3637
|
hasPrefetched.current = false;
|
|
3081
3638
|
}, [resolvedHref]);
|
|
3082
|
-
(0,
|
|
3639
|
+
(0, import_react5.useEffect)(() => {
|
|
3083
3640
|
const element = elementRef.current;
|
|
3084
3641
|
if (!element || isExternal) return;
|
|
3085
3642
|
const router = getRouter();
|
|
@@ -3089,7 +3646,7 @@ function LinkInner({
|
|
|
3089
3646
|
return () => router.unobserveForPrefetch(element);
|
|
3090
3647
|
}
|
|
3091
3648
|
}, [resolvedHref, viewport, isExternal]);
|
|
3092
|
-
(0,
|
|
3649
|
+
(0, import_react5.useEffect)(() => {
|
|
3093
3650
|
if (!render || isExternal) return;
|
|
3094
3651
|
let cancelled = false;
|
|
3095
3652
|
let timeoutId = null;
|
|
@@ -3111,7 +3668,7 @@ function LinkInner({
|
|
|
3111
3668
|
}
|
|
3112
3669
|
};
|
|
3113
3670
|
}, [render, isExternal, resolvedHref]);
|
|
3114
|
-
(0,
|
|
3671
|
+
(0, import_react5.useEffect)(() => {
|
|
3115
3672
|
return () => {
|
|
3116
3673
|
if (intentTimeoutRef.current) {
|
|
3117
3674
|
clearTimeout(intentTimeoutRef.current);
|
|
@@ -3119,13 +3676,13 @@ function LinkInner({
|
|
|
3119
3676
|
}
|
|
3120
3677
|
};
|
|
3121
3678
|
}, []);
|
|
3122
|
-
const cancelIntent = (0,
|
|
3679
|
+
const cancelIntent = (0, import_react5.useCallback)(() => {
|
|
3123
3680
|
if (intentTimeoutRef.current) {
|
|
3124
3681
|
clearTimeout(intentTimeoutRef.current);
|
|
3125
3682
|
intentTimeoutRef.current = null;
|
|
3126
3683
|
}
|
|
3127
3684
|
}, []);
|
|
3128
|
-
const scheduleIntentPrefetch = (0,
|
|
3685
|
+
const scheduleIntentPrefetch = (0, import_react5.useCallback)(() => {
|
|
3129
3686
|
if (isExternal || !intent || hasPrefetched.current) return;
|
|
3130
3687
|
cancelIntent();
|
|
3131
3688
|
intentTimeoutRef.current = setTimeout(() => {
|
|
@@ -3133,42 +3690,42 @@ function LinkInner({
|
|
|
3133
3690
|
doPrefetch();
|
|
3134
3691
|
}, prefetchDelay);
|
|
3135
3692
|
}, [intent, isExternal, prefetchDelay, doPrefetch, cancelIntent]);
|
|
3136
|
-
const handleMouseEnter = (0,
|
|
3693
|
+
const handleMouseEnter = (0, import_react5.useCallback)(
|
|
3137
3694
|
(event) => {
|
|
3138
3695
|
onMouseEnter?.(event);
|
|
3139
3696
|
scheduleIntentPrefetch();
|
|
3140
3697
|
},
|
|
3141
3698
|
[onMouseEnter, scheduleIntentPrefetch]
|
|
3142
3699
|
);
|
|
3143
|
-
const handleMouseLeave = (0,
|
|
3700
|
+
const handleMouseLeave = (0, import_react5.useCallback)(
|
|
3144
3701
|
(event) => {
|
|
3145
3702
|
onMouseLeave?.(event);
|
|
3146
3703
|
cancelIntent();
|
|
3147
3704
|
},
|
|
3148
3705
|
[onMouseLeave, cancelIntent]
|
|
3149
3706
|
);
|
|
3150
|
-
const handleTouchStart = (0,
|
|
3707
|
+
const handleTouchStart = (0, import_react5.useCallback)(
|
|
3151
3708
|
(event) => {
|
|
3152
3709
|
onTouchStart?.(event);
|
|
3153
3710
|
scheduleIntentPrefetch();
|
|
3154
3711
|
},
|
|
3155
3712
|
[onTouchStart, scheduleIntentPrefetch]
|
|
3156
3713
|
);
|
|
3157
|
-
const handleFocus = (0,
|
|
3714
|
+
const handleFocus = (0, import_react5.useCallback)(
|
|
3158
3715
|
(event) => {
|
|
3159
3716
|
onFocus?.(event);
|
|
3160
3717
|
scheduleIntentPrefetch();
|
|
3161
3718
|
},
|
|
3162
3719
|
[onFocus, scheduleIntentPrefetch]
|
|
3163
3720
|
);
|
|
3164
|
-
const handleBlur = (0,
|
|
3721
|
+
const handleBlur = (0, import_react5.useCallback)(
|
|
3165
3722
|
(event) => {
|
|
3166
3723
|
onBlur?.(event);
|
|
3167
3724
|
cancelIntent();
|
|
3168
3725
|
},
|
|
3169
3726
|
[onBlur, cancelIntent]
|
|
3170
3727
|
);
|
|
3171
|
-
const handleClick = (0,
|
|
3728
|
+
const handleClick = (0, import_react5.useCallback)(
|
|
3172
3729
|
(event) => {
|
|
3173
3730
|
onClick?.(event);
|
|
3174
3731
|
if (event.defaultPrevented) return;
|
|
@@ -3193,7 +3750,7 @@ function LinkInner({
|
|
|
3193
3750
|
},
|
|
3194
3751
|
[resolvedHref, replace, scroll, viewTransition, target, isExternal, onClick]
|
|
3195
3752
|
);
|
|
3196
|
-
const setRefs = (0,
|
|
3753
|
+
const setRefs = (0, import_react5.useCallback)(
|
|
3197
3754
|
(node) => {
|
|
3198
3755
|
elementRef.current = node;
|
|
3199
3756
|
if (typeof ref === "function") ref(node);
|
|
@@ -3222,7 +3779,7 @@ function LinkInner({
|
|
|
3222
3779
|
);
|
|
3223
3780
|
}
|
|
3224
3781
|
__name(LinkInner, "LinkInner");
|
|
3225
|
-
var LinkWithRef = (0,
|
|
3782
|
+
var LinkWithRef = (0, import_react5.forwardRef)(LinkInner);
|
|
3226
3783
|
LinkWithRef.displayName = "Link";
|
|
3227
3784
|
var Link = LinkWithRef;
|
|
3228
3785
|
function resolveLinkHref(href, params, options) {
|
|
@@ -3323,7 +3880,7 @@ function matchManifestRoute(pathname, route2) {
|
|
|
3323
3880
|
__name(matchManifestRoute, "matchManifestRoute");
|
|
3324
3881
|
|
|
3325
3882
|
// src/client/router.ts
|
|
3326
|
-
var
|
|
3883
|
+
var import_react6 = require("react");
|
|
3327
3884
|
|
|
3328
3885
|
// src/deferred.ts
|
|
3329
3886
|
var FARM_DEFERRED_CONTENT_TYPE = "application/x-farm-deferred+json";
|
|
@@ -3542,6 +4099,7 @@ __name(createFarmDeploymentMismatchError, "createFarmDeploymentMismatchError");
|
|
|
3542
4099
|
|
|
3543
4100
|
// src/client/spa-router.ts
|
|
3544
4101
|
var FARM_PAGE_STATE_KEY = "__farmPageState";
|
|
4102
|
+
var FARM_INTERCEPT_FROM_KEY = "__farmInterceptFrom";
|
|
3545
4103
|
var IDLE_NAVIGATION_STATE = {
|
|
3546
4104
|
state: "idle",
|
|
3547
4105
|
pending: false,
|
|
@@ -3612,7 +4170,11 @@ var _SPARouter = class _SPARouter {
|
|
|
3612
4170
|
return;
|
|
3613
4171
|
}
|
|
3614
4172
|
const from = window.location.pathname + window.location.search;
|
|
3615
|
-
if (await this.shouldBlockNavigation({
|
|
4173
|
+
if (await this.shouldBlockNavigation({
|
|
4174
|
+
from,
|
|
4175
|
+
to: fullPath,
|
|
4176
|
+
action: replace ? "replace" : "push"
|
|
4177
|
+
})) {
|
|
3616
4178
|
return;
|
|
3617
4179
|
}
|
|
3618
4180
|
if (this.options.scrollRestoration) {
|
|
@@ -3630,11 +4192,11 @@ var _SPARouter = class _SPARouter {
|
|
|
3630
4192
|
to: url,
|
|
3631
4193
|
action: replace ? "replace" : "push"
|
|
3632
4194
|
});
|
|
3633
|
-
const pageData = await this.fetchPageData(fullPath);
|
|
4195
|
+
const pageData = await this.fetchPageData(fullPath, true, from);
|
|
3634
4196
|
if (clientNavigation) {
|
|
3635
4197
|
await this.clientPlugins?.markNavigationLoaded(clientNavigation, pageData);
|
|
3636
4198
|
}
|
|
3637
|
-
if (pageData.isClientComponent === false) {
|
|
4199
|
+
if (pageData.isClientComponent === false && !pageData.interception) {
|
|
3638
4200
|
this.finishNavigation();
|
|
3639
4201
|
window.location.assign(pageData.canonicalPath || fullPath);
|
|
3640
4202
|
return;
|
|
@@ -3672,11 +4234,12 @@ var _SPARouter = class _SPARouter {
|
|
|
3672
4234
|
if (isFarmLocaleChangeHref(href)) return;
|
|
3673
4235
|
const url = new URL(href, window.location.origin);
|
|
3674
4236
|
const fullPath = url.pathname + url.search;
|
|
4237
|
+
const interceptFrom = window.location.pathname + window.location.search;
|
|
3675
4238
|
if (this.prefetchingUrls.has(fullPath)) return;
|
|
3676
|
-
if (this.isCached(fullPath)) return;
|
|
4239
|
+
if (this.isCached(fullPath, interceptFrom)) return;
|
|
3677
4240
|
this.prefetchingUrls.add(fullPath);
|
|
3678
4241
|
try {
|
|
3679
|
-
await this.fetchPageData(fullPath, false);
|
|
4242
|
+
await this.fetchPageData(fullPath, false, interceptFrom);
|
|
3680
4243
|
} catch (error) {
|
|
3681
4244
|
console.warn("[Farm.js] Prefetch failed:", href, error);
|
|
3682
4245
|
} finally {
|
|
@@ -3751,7 +4314,12 @@ var _SPARouter = class _SPARouter {
|
|
|
3751
4314
|
}
|
|
3752
4315
|
async commitNavigation(options) {
|
|
3753
4316
|
const historyPath = options.pageData.canonicalPath || options.fullPath;
|
|
3754
|
-
const historyState = createHistoryState(
|
|
4317
|
+
const historyState = createHistoryState(
|
|
4318
|
+
historyPath,
|
|
4319
|
+
options.state,
|
|
4320
|
+
void 0,
|
|
4321
|
+
options.pageData.interception?.from ?? null
|
|
4322
|
+
);
|
|
3755
4323
|
if (options.replace) {
|
|
3756
4324
|
window.history.replaceState(historyState, "", historyPath);
|
|
3757
4325
|
} else {
|
|
@@ -3806,15 +4374,17 @@ var _SPARouter = class _SPARouter {
|
|
|
3806
4374
|
/**
|
|
3807
4375
|
* Fetch page data from cache or server
|
|
3808
4376
|
*/
|
|
3809
|
-
async fetchPageData(path, recover = true) {
|
|
3810
|
-
const
|
|
4377
|
+
async fetchPageData(path, recover = true, interceptFrom) {
|
|
4378
|
+
const cacheKey = getPageDataCacheKey(path, interceptFrom);
|
|
4379
|
+
const cached = this.cache.get(cacheKey);
|
|
3811
4380
|
if (cached && Date.now() - cached.timestamp < this.options.cacheMaxAge) {
|
|
3812
4381
|
return cached.data;
|
|
3813
4382
|
}
|
|
3814
4383
|
const response = await fetch(`/__farm/page-data?path=${encodeURIComponent(path)}`, {
|
|
3815
4384
|
headers: createFarmDeploymentRequestHeaders(this.options.deploymentId, {
|
|
3816
4385
|
Accept: "application/x-farm-deferred+json, application/json",
|
|
3817
|
-
"X-Farm-SPA": "1"
|
|
4386
|
+
"X-Farm-SPA": "1",
|
|
4387
|
+
...interceptFrom ? { "X-Farm-Intercept-From": interceptFrom } : {}
|
|
3818
4388
|
})
|
|
3819
4389
|
});
|
|
3820
4390
|
if (isFarmDeploymentMismatchResponse(response, this.options.deploymentId)) {
|
|
@@ -3832,7 +4402,7 @@ var _SPARouter = class _SPARouter {
|
|
|
3832
4402
|
throw new Error(`Failed to fetch page data: ${response.status}`);
|
|
3833
4403
|
}
|
|
3834
4404
|
const data = await readDeferredDataResponse(response);
|
|
3835
|
-
this.cache.set(
|
|
4405
|
+
this.cache.set(cacheKey, {
|
|
3836
4406
|
data,
|
|
3837
4407
|
timestamp: Date.now()
|
|
3838
4408
|
});
|
|
@@ -3863,7 +4433,8 @@ var _SPARouter = class _SPARouter {
|
|
|
3863
4433
|
to: window.location.href,
|
|
3864
4434
|
action: "pop"
|
|
3865
4435
|
});
|
|
3866
|
-
const
|
|
4436
|
+
const interceptFrom = typeof event.state?.[FARM_INTERCEPT_FROM_KEY] === "string" ? event.state[FARM_INTERCEPT_FROM_KEY] : void 0;
|
|
4437
|
+
const pageData = await this.fetchPageData(path, true, interceptFrom);
|
|
3867
4438
|
if (clientNavigation) {
|
|
3868
4439
|
await this.clientPlugins?.markNavigationLoaded(clientNavigation, pageData);
|
|
3869
4440
|
}
|
|
@@ -3894,8 +4465,8 @@ var _SPARouter = class _SPARouter {
|
|
|
3894
4465
|
/**
|
|
3895
4466
|
* Check if URL is cached
|
|
3896
4467
|
*/
|
|
3897
|
-
isCached(path) {
|
|
3898
|
-
const cached = this.cache.get(path);
|
|
4468
|
+
isCached(path, interceptFrom) {
|
|
4469
|
+
const cached = this.cache.get(getPageDataCacheKey(path, interceptFrom));
|
|
3899
4470
|
return cached !== void 0 && Date.now() - cached.timestamp < this.options.cacheMaxAge;
|
|
3900
4471
|
}
|
|
3901
4472
|
/**
|
|
@@ -4051,15 +4622,26 @@ function readPageState() {
|
|
|
4051
4622
|
return state[FARM_PAGE_STATE_KEY] ?? null;
|
|
4052
4623
|
}
|
|
4053
4624
|
__name(readPageState, "readPageState");
|
|
4054
|
-
function createHistoryState(path, pageState, currentState) {
|
|
4625
|
+
function createHistoryState(path, pageState, currentState, interceptFrom) {
|
|
4055
4626
|
const base = currentState && typeof currentState === "object" ? { ...currentState } : {};
|
|
4056
|
-
|
|
4627
|
+
const nextState = {
|
|
4057
4628
|
...base,
|
|
4058
4629
|
path,
|
|
4059
4630
|
[FARM_PAGE_STATE_KEY]: pageState
|
|
4060
4631
|
};
|
|
4632
|
+
if (interceptFrom === null) {
|
|
4633
|
+
delete nextState[FARM_INTERCEPT_FROM_KEY];
|
|
4634
|
+
} else if (interceptFrom) {
|
|
4635
|
+
nextState[FARM_INTERCEPT_FROM_KEY] = interceptFrom;
|
|
4636
|
+
}
|
|
4637
|
+
return nextState;
|
|
4061
4638
|
}
|
|
4062
4639
|
__name(createHistoryState, "createHistoryState");
|
|
4640
|
+
function getPageDataCacheKey(path, interceptFrom) {
|
|
4641
|
+
return interceptFrom ? `${path}
|
|
4642
|
+
intercept:${interceptFrom}` : path;
|
|
4643
|
+
}
|
|
4644
|
+
__name(getPageDataCacheKey, "getPageDataCacheKey");
|
|
4063
4645
|
function createNavigationLocation(url) {
|
|
4064
4646
|
return {
|
|
4065
4647
|
href: url.href,
|
|
@@ -4079,14 +4661,14 @@ function useRouter(options = {}) {
|
|
|
4079
4661
|
const basePath = options.basePath || "";
|
|
4080
4662
|
const routes = options.routes;
|
|
4081
4663
|
const routeKey = routes?.map((route2) => typeof route2 === "string" ? route2 : route2.path).join("\n") || "";
|
|
4082
|
-
const routeMatcher = (0,
|
|
4664
|
+
const routeMatcher = (0, import_react6.useMemo)(
|
|
4083
4665
|
() => routeKey ? createFarmRouter(routeKey.split("\n")) : null,
|
|
4084
4666
|
[routeKey]
|
|
4085
4667
|
);
|
|
4086
|
-
const [state, setState] = (0,
|
|
4668
|
+
const [state, setState] = (0, import_react6.useState)(() => {
|
|
4087
4669
|
return readRouterState(basePath, routeMatcher);
|
|
4088
4670
|
});
|
|
4089
|
-
(0,
|
|
4671
|
+
(0, import_react6.useEffect)(() => {
|
|
4090
4672
|
if (typeof window === "undefined") return;
|
|
4091
4673
|
const handlePopState = /* @__PURE__ */ __name(() => {
|
|
4092
4674
|
setState(readRouterState(basePath, routeMatcher));
|
|
@@ -4137,8 +4719,8 @@ function useRouter(options = {}) {
|
|
|
4137
4719
|
}
|
|
4138
4720
|
__name(useRouter, "useRouter");
|
|
4139
4721
|
function usePageState() {
|
|
4140
|
-
const [state, setState] = (0,
|
|
4141
|
-
(0,
|
|
4722
|
+
const [state, setState] = (0, import_react6.useState)(() => readPageState());
|
|
4723
|
+
(0, import_react6.useEffect)(() => {
|
|
4142
4724
|
if (typeof window === "undefined") return;
|
|
4143
4725
|
const handlePopState = /* @__PURE__ */ __name(() => {
|
|
4144
4726
|
setState(readPageState());
|
|
@@ -4151,10 +4733,10 @@ function usePageState() {
|
|
|
4151
4733
|
}
|
|
4152
4734
|
__name(usePageState, "usePageState");
|
|
4153
4735
|
function useNavigation() {
|
|
4154
|
-
const [state, setState] = (0,
|
|
4736
|
+
const [state, setState] = (0, import_react6.useState)(
|
|
4155
4737
|
() => getRouter2().getNavigationState()
|
|
4156
4738
|
);
|
|
4157
|
-
(0,
|
|
4739
|
+
(0, import_react6.useEffect)(() => {
|
|
4158
4740
|
if (typeof window === "undefined") return;
|
|
4159
4741
|
return getRouter2().subscribeNavigation(setState);
|
|
4160
4742
|
}, []);
|
|
@@ -4162,10 +4744,10 @@ function useNavigation() {
|
|
|
4162
4744
|
}
|
|
4163
4745
|
__name(useNavigation, "useNavigation");
|
|
4164
4746
|
function useBlocker(options) {
|
|
4165
|
-
const optionsRef = (0,
|
|
4747
|
+
const optionsRef = (0, import_react6.useRef)(options);
|
|
4166
4748
|
optionsRef.current = options;
|
|
4167
4749
|
const active = Boolean(options.when);
|
|
4168
|
-
(0,
|
|
4750
|
+
(0, import_react6.useEffect)(() => {
|
|
4169
4751
|
if (typeof window === "undefined" || !active) {
|
|
4170
4752
|
return;
|
|
4171
4753
|
}
|
|
@@ -4186,8 +4768,8 @@ function useBlocker(options) {
|
|
|
4186
4768
|
}
|
|
4187
4769
|
__name(useBlocker, "useBlocker");
|
|
4188
4770
|
function useScrollRestoration(key) {
|
|
4189
|
-
const ref = (0,
|
|
4190
|
-
(0,
|
|
4771
|
+
const ref = (0, import_react6.useRef)(null);
|
|
4772
|
+
(0, import_react6.useEffect)(() => {
|
|
4191
4773
|
const element = ref.current;
|
|
4192
4774
|
if (!element) return;
|
|
4193
4775
|
return getRouter2().registerScrollElement(key, element);
|
|
@@ -4809,6 +5391,7 @@ __name(isObject, "isObject");
|
|
|
4809
5391
|
readPageState,
|
|
4810
5392
|
replaceState,
|
|
4811
5393
|
useBlocker,
|
|
5394
|
+
useFetcher,
|
|
4812
5395
|
useMutation,
|
|
4813
5396
|
useNavigation,
|
|
4814
5397
|
usePageState,
|