@krymskyimaksym/react-api-client 2.0.0-beta.0 → 2.0.0-beta.2

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/index.js CHANGED
@@ -36,6 +36,52 @@ var ApiError = class _ApiError extends Error {
36
36
  Object.setPrototypeOf(this, _ApiError.prototype);
37
37
  }
38
38
  };
39
+ var isObject = (v) => typeof v === "object" && v !== null;
40
+ function toApiError(thrown) {
41
+ if (thrown instanceof ApiError) return thrown;
42
+ if (isObject(thrown) && "response" in thrown && isObject(thrown.response)) {
43
+ const r = thrown.response;
44
+ const status = typeof r.status === "number" ? r.status : 0;
45
+ const data = isObject(r.data) ? r.data : void 0;
46
+ const message = (data && typeof data.message === "string" ? data.message : void 0) ?? (thrown instanceof Error ? thrown.message : void 0) ?? `HTTP ${status}`;
47
+ return new ApiError({
48
+ message,
49
+ status,
50
+ code: data && typeof data.code === "string" ? data.code : void 0,
51
+ errors: data?.errors,
52
+ isNetworkError: status === 0,
53
+ isUnauthorized: status === 401,
54
+ isValidationError: status === 422 || data?.errors !== void 0,
55
+ raw: r.data ?? thrown
56
+ });
57
+ }
58
+ if (thrown instanceof Error) {
59
+ return new ApiError({
60
+ message: thrown.message,
61
+ status: 0,
62
+ isNetworkError: true,
63
+ raw: thrown
64
+ });
65
+ }
66
+ return new ApiError({
67
+ message: "Unknown error",
68
+ status: 0,
69
+ raw: thrown
70
+ });
71
+ }
72
+ function businessErrorToApiError(response) {
73
+ if (!isObject(response)) {
74
+ return new ApiError({ message: "Request failed", status: 200, raw: response });
75
+ }
76
+ return new ApiError({
77
+ message: typeof response.message === "string" ? response.message : "Request failed",
78
+ status: 200,
79
+ code: typeof response.code === "string" ? response.code : void 0,
80
+ errors: response.errors,
81
+ isValidationError: response.errors !== void 0,
82
+ raw: response
83
+ });
84
+ }
39
85
 
40
86
  // src/utils.ts
41
87
  function buildEndpoint(endpoint, params) {
@@ -44,7 +90,7 @@ function buildEndpoint(endpoint, params) {
44
90
  }
45
91
  return endpoint;
46
92
  }
47
- async function executeRequest(endpoint, fetchConfig, params) {
93
+ async function executeRequest(endpoint, fetchConfig, params, signal) {
48
94
  const url = buildEndpoint(endpoint, params);
49
95
  const config = getConfig();
50
96
  try {
@@ -55,7 +101,8 @@ async function executeRequest(endpoint, fetchConfig, params) {
55
101
  params: {
56
102
  ...requestConfig.requestParams,
57
103
  ...params
58
- }
104
+ },
105
+ signal
59
106
  });
60
107
  } else {
61
108
  response = await config.httpClient.request(url, {
@@ -63,38 +110,29 @@ async function executeRequest(endpoint, fetchConfig, params) {
63
110
  data: {
64
111
  ...requestConfig.requestParams,
65
112
  ...params
66
- }
113
+ },
114
+ signal
67
115
  });
68
116
  }
69
117
  const hasExplicitStatus = response && typeof response === "object" && "status" in response && typeof response.status === "boolean";
70
118
  if (config.throwOnError && hasExplicitStatus && response.status === false) {
71
- const body = response;
72
- throw new ApiError({
73
- message: body.message ?? "Request failed",
74
- status: 200,
75
- errors: body.errors,
76
- raw: response
77
- });
119
+ throw businessErrorToApiError(response);
78
120
  }
79
121
  return { ...response, status: true };
80
122
  } catch (e) {
81
- if (e instanceof ApiError) throw e;
123
+ if (e instanceof ApiError) {
124
+ if (e.status === 401 && config.onUnauthorized) {
125
+ await config.onUnauthorized();
126
+ }
127
+ throw e;
128
+ }
82
129
  const error = e;
83
130
  const httpStatus = error.response?.status;
84
131
  if (httpStatus === 401 && config.onUnauthorized) {
85
132
  await config.onUnauthorized();
86
133
  }
87
134
  if (config.throwOnError) {
88
- const data = error.response?.data;
89
- const isNetwork = httpStatus === void 0;
90
- throw new ApiError({
91
- message: data?.message ?? (e instanceof Error ? e.message : void 0) ?? (isNetwork ? "Network error" : "Request error"),
92
- status: httpStatus ?? 0,
93
- code: data?.code,
94
- errors: data,
95
- isNetworkError: isNetwork,
96
- raw: e
97
- });
135
+ throw toApiError(e);
98
136
  }
99
137
  if (error.response?.data) {
100
138
  return {
@@ -117,6 +155,21 @@ function handleResponse(result, onSuccess, onError) {
117
155
  }
118
156
  }
119
157
 
158
+ // src/logger.ts
159
+ function getLogger() {
160
+ if (!isConfigured()) return void 0;
161
+ return getConfig().logger;
162
+ }
163
+ function callLogger(method, ...args) {
164
+ const logger = getLogger();
165
+ const fn = logger?.[method];
166
+ if (!fn) return;
167
+ try {
168
+ fn(...args);
169
+ } catch {
170
+ }
171
+ }
172
+
120
173
  // src/query/focus-manager.ts
121
174
  var FocusManager = class {
122
175
  constructor() {
@@ -255,6 +308,21 @@ var DEFAULT_STALE_TIME = 0;
255
308
  var QueryCache = class {
256
309
  constructor() {
257
310
  this.entries = /* @__PURE__ */ new Map();
311
+ this.globalListeners = /* @__PURE__ */ new Set();
312
+ }
313
+ /**
314
+ * Подписка на любое изменение кэша: setData, invalidate, remove,
315
+ * успешный/ошибочный fetch. Используется persistQueryClient и
316
+ * devtools-подобными адаптерами. Не дублирует `subscribe(key, ...)`.
317
+ */
318
+ subscribeAll(listener) {
319
+ this.globalListeners.add(listener);
320
+ return () => {
321
+ this.globalListeners.delete(listener);
322
+ };
323
+ }
324
+ notifyGlobal() {
325
+ for (const listener of this.globalListeners) listener();
258
326
  }
259
327
  ensureEntry(key, staleTime, gcTime) {
260
328
  const hash = hashQueryKey(key);
@@ -271,7 +339,9 @@ var QueryCache = class {
271
339
  },
272
340
  subscribers: /* @__PURE__ */ new Set(),
273
341
  inflight: null,
342
+ inflightController: null,
274
343
  gcTimer: null,
344
+ lastQueryFn: null,
275
345
  staleTime: staleTime ?? DEFAULT_STALE_TIME,
276
346
  gcTime: gcTime ?? DEFAULT_GC_TIME
277
347
  };
@@ -319,6 +389,7 @@ var QueryCache = class {
319
389
  }
320
390
  notify(entry) {
321
391
  for (const listener of entry.subscribers) listener();
392
+ this.notifyGlobal();
322
393
  }
323
394
  scheduleGc(entry) {
324
395
  if (entry.gcTimer) clearTimeout(entry.gcTimer);
@@ -341,18 +412,21 @@ var QueryCache = class {
341
412
  const gcTime = options.gcTime ?? DEFAULT_GC_TIME;
342
413
  const entry = this.ensureEntry(key, staleTime, gcTime);
343
414
  const isFresh = entry.state.status === "success" && !entry.state.isStale && Date.now() - entry.state.updatedAt < staleTime;
415
+ entry.lastQueryFn = queryFn;
344
416
  if (!options.force && isFresh && entry.state.data !== void 0) {
345
417
  return entry.state.data;
346
418
  }
347
419
  if (entry.inflight) return entry.inflight;
348
420
  entry.state = { ...entry.state, status: "loading", error: null };
349
421
  this.notify(entry);
422
+ const controller = new AbortController();
350
423
  const token = Symbol("inflight");
351
424
  entry.inflightToken = token;
425
+ entry.inflightController = controller;
352
426
  const isCurrent = () => entry.inflightToken === token;
353
427
  const myPromise = (async () => {
354
428
  try {
355
- const data = await queryFn();
429
+ const data = await queryFn({ signal: controller.signal });
356
430
  if (!isCurrent()) return data;
357
431
  entry.state = {
358
432
  data,
@@ -373,7 +447,10 @@ var QueryCache = class {
373
447
  this.notify(entry);
374
448
  throw err;
375
449
  } finally {
376
- if (isCurrent()) entry.inflight = null;
450
+ if (isCurrent()) {
451
+ entry.inflight = null;
452
+ entry.inflightController = null;
453
+ }
377
454
  }
378
455
  })();
379
456
  entry.inflight = myPromise;
@@ -395,6 +472,26 @@ var QueryCache = class {
395
472
  }
396
473
  return invalidated;
397
474
  }
475
+ /**
476
+ * Перезапускает все записи, матчинг predicate, у которых сохранён
477
+ * `lastQueryFn` (т.е. их хоть раз кто-то загрузил через `fetch`).
478
+ * Возвращает promise, который резолвится когда все запросы завершились.
479
+ * Ошибки отдельных запросов проглатываются — общий promise успешный.
480
+ */
481
+ refetchQueries(predicate) {
482
+ const match = typeof predicate === "function" ? predicate : (k) => matchQueryKey(predicate, k);
483
+ const promises = [];
484
+ for (const entry of this.entries.values()) {
485
+ if (!match(entry.key)) continue;
486
+ if (!entry.lastQueryFn) continue;
487
+ promises.push(
488
+ this.fetch(entry.key, entry.lastQueryFn, { force: true }).catch(
489
+ () => void 0
490
+ )
491
+ );
492
+ }
493
+ return Promise.all(promises).then(() => void 0);
494
+ }
398
495
  /**
399
496
  * Отменяет «привязку» inflight-промиса к ключу. Сам HTTP-запрос
400
497
  * продолжит исполняться (executeRequest не использует AbortSignal),
@@ -405,6 +502,8 @@ var QueryCache = class {
405
502
  const match = typeof predicate === "function" ? predicate : (k) => matchQueryKey(predicate, k);
406
503
  for (const entry of this.entries.values()) {
407
504
  if (match(entry.key) && entry.inflight) {
505
+ entry.inflightController?.abort();
506
+ entry.inflightController = null;
408
507
  entry.inflight = null;
409
508
  entry.inflightToken = void 0;
410
509
  if (entry.state.status === "loading") {
@@ -420,12 +519,28 @@ var QueryCache = class {
420
519
  */
421
520
  remove(predicate) {
422
521
  const match = typeof predicate === "function" ? predicate : (k) => matchQueryKey(predicate, k);
522
+ let removed = false;
423
523
  for (const [hash, entry] of [...this.entries]) {
424
524
  if (match(entry.key)) {
425
525
  if (entry.gcTimer) clearTimeout(entry.gcTimer);
426
526
  this.entries.delete(hash);
527
+ removed = true;
427
528
  }
428
529
  }
530
+ if (removed) this.notifyGlobal();
531
+ }
532
+ /**
533
+ * Количество inflight-запросов в кэше, опционально отфильтрованных
534
+ * по predicate. Используется `useIsFetching()` для глобального
535
+ * индикатора загрузки.
536
+ */
537
+ countFetching(predicate) {
538
+ const match = !predicate ? () => true : typeof predicate === "function" ? predicate : (k) => matchQueryKey(predicate, k);
539
+ let n = 0;
540
+ for (const entry of this.entries.values()) {
541
+ if (entry.state.status === "loading" && match(entry.key)) n++;
542
+ }
543
+ return n;
429
544
  }
430
545
  /** Только для тестов / DevTools. */
431
546
  _debugEntries() {
@@ -484,7 +599,8 @@ var QueryClient = class {
484
599
  return this.cache.fetch(key, queryFn, options);
485
600
  }
486
601
  invalidateQueries(predicate) {
487
- this.cache.invalidate(predicate);
602
+ const hashes = this.cache.invalidate(predicate);
603
+ if (hashes.length > 0) callLogger("onInvalidate", hashes);
488
604
  }
489
605
  removeQueries(predicate) {
490
606
  this.cache.remove(predicate);
@@ -492,6 +608,19 @@ var QueryClient = class {
492
608
  cancelQueries(predicate) {
493
609
  this.cache.cancelQueries(predicate);
494
610
  }
611
+ refetchQueries(predicate) {
612
+ return this.cache.refetchQueries(predicate);
613
+ }
614
+ /**
615
+ * Кладёт запрос в кэш, не пробрасывая ошибки. Подходит для оптимистичной
616
+ * подгрузки следующего экрана при наведении / долгом тапе.
617
+ */
618
+ prefetchQuery(key, queryFn, options) {
619
+ return this.cache.fetch(key, queryFn, options).then(
620
+ () => void 0,
621
+ () => void 0
622
+ );
623
+ }
495
624
  };
496
625
  var globalClient = null;
497
626
  function getQueryClient() {
@@ -530,27 +659,37 @@ function createUseFetch(endpoint, fetchConfig) {
530
659
  }, [customKey ? hashQueryKey(customKey) : null, serializedParams]);
531
660
  const client = getQueryClient();
532
661
  const cache = client.cache;
533
- const queryFn = react.useCallback(() => {
534
- const parsedParams = serializedParams ? JSON.parse(serializedParams) : void 0;
535
- return executeRequest(endpoint, fetchConfig, parsedParams);
536
- }, [serializedParams]);
662
+ const queryFn = react.useCallback(
663
+ ({ signal }) => {
664
+ const parsedParams = serializedParams ? JSON.parse(serializedParams) : void 0;
665
+ return executeRequest(endpoint, fetchConfig, parsedParams, signal);
666
+ },
667
+ [serializedParams]
668
+ );
537
669
  const initialState = cache.getState(queryKey);
538
670
  const [, forceRender] = react.useState(0);
539
671
  const rerender = react.useCallback(() => forceRender((v) => v + 1), []);
540
672
  react.useEffect(() => {
541
- if (!enabled) return;
542
673
  const unsub = cache.subscribe(queryKey, rerender);
543
- return unsub;
544
- }, [cache, enabled, hashQueryKey(queryKey), rerender]);
674
+ return () => {
675
+ unsub();
676
+ const state2 = cache._debugEntries().get(hashQueryKey(queryKey));
677
+ if (state2 && state2.subscribers.size === 0 && state2.inflight) {
678
+ cache.cancelQueries(queryKey);
679
+ }
680
+ };
681
+ }, [cache, hashQueryKey(queryKey), rerender]);
545
682
  const lastNotifiedRef = react.useRef({});
546
683
  const runFetch = react.useCallback(
547
684
  async (force) => {
685
+ callLogger("onFetchStart", queryKey);
548
686
  try {
549
687
  const data = await cache.fetch(queryKey, queryFn, {
550
688
  staleTime,
551
689
  gcTime,
552
690
  force
553
691
  });
692
+ callLogger("onFetchSuccess", queryKey, data);
554
693
  if (lastNotifiedRef.current.success !== data) {
555
694
  lastNotifiedRef.current.success = data;
556
695
  handleResponse(
@@ -560,6 +699,7 @@ function createUseFetch(endpoint, fetchConfig) {
560
699
  );
561
700
  }
562
701
  } catch (err) {
702
+ callLogger("onFetchError", queryKey, err);
563
703
  const e = err;
564
704
  const hash = `${e.name}:${e.message}`;
565
705
  if (lastNotifiedRef.current.errorHash !== hash) {
@@ -643,6 +783,47 @@ function createUseFetch(endpoint, fetchConfig) {
643
783
  };
644
784
  };
645
785
  }
786
+
787
+ // src/query/mutation-counter.ts
788
+ var MutationCounter = class {
789
+ constructor() {
790
+ this.active = /* @__PURE__ */ new Map();
791
+ this.listeners = /* @__PURE__ */ new Set();
792
+ }
793
+ start(scope) {
794
+ const id = Symbol("mutation");
795
+ this.active.set(id, scope);
796
+ this.notify();
797
+ return id;
798
+ }
799
+ stop(id) {
800
+ if (this.active.delete(id)) this.notify();
801
+ }
802
+ count(predicate) {
803
+ if (!predicate) return this.active.size;
804
+ let n = 0;
805
+ for (const scope of this.active.values()) {
806
+ if (typeof predicate === "function") {
807
+ if (predicate(scope)) n++;
808
+ } else {
809
+ if (scope && matchQueryKey(predicate, scope)) n++;
810
+ }
811
+ }
812
+ return n;
813
+ }
814
+ subscribe(listener) {
815
+ this.listeners.add(listener);
816
+ return () => {
817
+ this.listeners.delete(listener);
818
+ };
819
+ }
820
+ notify() {
821
+ for (const l of this.listeners) l();
822
+ }
823
+ };
824
+ var mutationCounter = new MutationCounter();
825
+
826
+ // src/hooks/use-mutation.ts
646
827
  function createUseMutation(endpoint, fetchConfig) {
647
828
  return (options = {}) => {
648
829
  const {
@@ -669,10 +850,21 @@ function createUseMutation(endpoint, fetchConfig) {
669
850
  (vars, result) => {
670
851
  if (!invalidateKeys) return;
671
852
  const client = getQueryClient();
672
- const keys = typeof invalidateKeys === "function" ? invalidateKeys(vars, result) : invalidateKeys;
673
- if (keys.length === 0) return;
853
+ if (Array.isArray(invalidateKeys)) {
854
+ if (invalidateKeys.length === 0) return;
855
+ client.invalidateQueries(
856
+ (k) => invalidateKeys.some((prefix) => matchQueryKey(prefix, k))
857
+ );
858
+ return;
859
+ }
860
+ const out = invalidateKeys(vars, result);
861
+ if (typeof out === "function") {
862
+ client.invalidateQueries(out);
863
+ return;
864
+ }
865
+ if (out.length === 0) return;
674
866
  client.invalidateQueries(
675
- (k) => keys.some((prefix) => matchQueryKey(prefix, k))
867
+ (k) => out.some((prefix) => matchQueryKey(prefix, k))
676
868
  );
677
869
  },
678
870
  [invalidateKeys]
@@ -683,6 +875,10 @@ function createUseMutation(endpoint, fetchConfig) {
683
875
  setIsSuccess(false);
684
876
  setIsError(false);
685
877
  setError(null);
878
+ const scope = Array.isArray(invalidateKeys) && invalidateKeys.length > 0 ? invalidateKeys[0] : void 0;
879
+ const mutationId = mutationCounter.start(scope);
880
+ const endpointId = buildEndpoint(endpoint, variables);
881
+ callLogger("onMutationStart", endpointId, variables);
686
882
  let context;
687
883
  try {
688
884
  if (onMutate) {
@@ -693,6 +889,7 @@ function createUseMutation(endpoint, fetchConfig) {
693
889
  setData(result);
694
890
  if (result.status) {
695
891
  setIsSuccess(true);
892
+ callLogger("onMutationSuccess", endpointId, variables, result);
696
893
  if (setQueryData) {
697
894
  setQueryData(getQueryClient(), variables, result);
698
895
  }
@@ -704,6 +901,7 @@ function createUseMutation(endpoint, fetchConfig) {
704
901
  const err = new Error(result.message ?? "Mutation failed");
705
902
  setIsError(true);
706
903
  setError(err);
904
+ callLogger("onMutationError", endpointId, variables, err);
707
905
  if (onError) {
708
906
  await onError(err, variables, context);
709
907
  }
@@ -717,6 +915,7 @@ function createUseMutation(endpoint, fetchConfig) {
717
915
  setError(error2);
718
916
  setIsError(true);
719
917
  setIsSuccess(false);
918
+ callLogger("onMutationError", endpointId, variables, error2);
720
919
  if (onError) {
721
920
  await onError(error2, variables, context);
722
921
  }
@@ -725,6 +924,7 @@ function createUseMutation(endpoint, fetchConfig) {
725
924
  }
726
925
  throw error2;
727
926
  } finally {
927
+ mutationCounter.stop(mutationId);
728
928
  setIsLoading(false);
729
929
  }
730
930
  },
@@ -801,14 +1001,14 @@ function createUsePaginate(endpoint, fetchConfig, options) {
801
1001
  [keyPrefix, limit]
802
1002
  );
803
1003
  const pageQueryFn = react.useCallback(
804
- (page) => () => {
1004
+ (page) => ({ signal }) => {
805
1005
  const parsedParams = serializedParams ? JSON.parse(serializedParams) : {};
806
1006
  const requestParams = {
807
1007
  ...parsedParams,
808
1008
  page,
809
1009
  limit
810
1010
  };
811
- return executeRequest(endpoint, fetchConfig, requestParams);
1011
+ return executeRequest(endpoint, fetchConfig, requestParams, signal);
812
1012
  },
813
1013
  [serializedParams, limit]
814
1014
  );
@@ -927,6 +1127,33 @@ function createUsePaginate(endpoint, fetchConfig, options) {
927
1127
  };
928
1128
  };
929
1129
  }
1130
+ function useIsFetching(predicate) {
1131
+ const client = getQueryClient();
1132
+ const get = react.useCallback(
1133
+ () => client.cache.countFetching(predicate),
1134
+ [client.cache, predicate]
1135
+ );
1136
+ const [count, setCount] = react.useState(get);
1137
+ react.useEffect(() => {
1138
+ setCount(get());
1139
+ const unsub = client.cache.subscribeAll(() => setCount(get()));
1140
+ return unsub;
1141
+ }, [client.cache, get]);
1142
+ return count;
1143
+ }
1144
+ function useIsMutating(predicate) {
1145
+ const get = react.useCallback(
1146
+ () => mutationCounter.count(predicate),
1147
+ [predicate]
1148
+ );
1149
+ const [count, setCount] = react.useState(get);
1150
+ react.useEffect(() => {
1151
+ setCount(get());
1152
+ const unsub = mutationCounter.subscribe(() => setCount(get()));
1153
+ return unsub;
1154
+ }, [get]);
1155
+ return count;
1156
+ }
930
1157
 
931
1158
  // src/query/persist.ts
932
1159
  function persistQueryClient(options) {
@@ -939,19 +1166,26 @@ function persistQueryClient(options) {
939
1166
  maxAge,
940
1167
  version
941
1168
  } = options;
942
- let timer = null;
1169
+ let pendingTimer = null;
943
1170
  let lastSerialized = null;
1171
+ let unsubscribed = false;
944
1172
  const persist = async () => {
945
1173
  const state = client.cache.dehydrate(allowList);
946
- if (state.queries.length === 0) {
947
- return;
948
- }
1174
+ if (state.queries.length === 0) return;
949
1175
  const snap = { version, savedAt: Date.now(), state };
950
1176
  const serialized = JSON.stringify(snap);
951
1177
  if (serialized === lastSerialized) return;
952
1178
  lastSerialized = serialized;
953
1179
  await storage.setItem(storageKey, serialized);
954
1180
  };
1181
+ const scheduleWrite = () => {
1182
+ if (unsubscribed) return;
1183
+ if (pendingTimer) return;
1184
+ pendingTimer = setTimeout(() => {
1185
+ pendingTimer = null;
1186
+ void persist();
1187
+ }, throttleMs);
1188
+ };
955
1189
  const restore = async () => {
956
1190
  const raw = await storage.getItem(storageKey);
957
1191
  if (!raw) return;
@@ -970,15 +1204,17 @@ function persistQueryClient(options) {
970
1204
  await storage.removeItem(storageKey);
971
1205
  }
972
1206
  };
973
- timer = setInterval(() => {
974
- void persist();
975
- }, throttleMs);
1207
+ const unsubscribeFromCache = client.cache.subscribeAll(scheduleWrite);
976
1208
  return {
977
1209
  restore,
978
1210
  persist,
979
1211
  unsubscribe: () => {
980
- if (timer) clearInterval(timer);
981
- timer = null;
1212
+ unsubscribed = true;
1213
+ unsubscribeFromCache();
1214
+ if (pendingTimer) {
1215
+ clearTimeout(pendingTimer);
1216
+ pendingTimer = null;
1217
+ }
982
1218
  }
983
1219
  };
984
1220
  }
@@ -1085,6 +1321,7 @@ exports.QueryCache = QueryCache;
1085
1321
  exports.QueryClient = QueryClient;
1086
1322
  exports.apiMutation = apiMutation;
1087
1323
  exports.apiPaginate = apiPaginate;
1324
+ exports.businessErrorToApiError = businessErrorToApiError;
1088
1325
  exports.configureApiClient = configureApiClient;
1089
1326
  exports.default = index_default;
1090
1327
  exports.focusManager = focusManager;
@@ -1099,6 +1336,9 @@ exports.onlineManager = onlineManager;
1099
1336
  exports.persistQueryClient = persistQueryClient;
1100
1337
  exports.setQueryClient = setQueryClient;
1101
1338
  exports.summarizeCache = summarizeCache;
1339
+ exports.toApiError = toApiError;
1340
+ exports.useIsFetching = useIsFetching;
1341
+ exports.useIsMutating = useIsMutating;
1102
1342
  exports.useQueryClient = useQueryClient;
1103
1343
  //# sourceMappingURL=index.js.map
1104
1344
  //# sourceMappingURL=index.js.map