@krymskyimaksym/react-api-client 1.0.0 → 2.0.0-beta.1
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.d.mts +406 -9
- package/dist/index.d.ts +406 -9
- package/dist/index.js +917 -147
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +902 -149
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,151 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
type QueryKey = readonly unknown[];
|
|
5
|
+
/**
|
|
6
|
+
* Стабильная сериализация ключа кэша.
|
|
7
|
+
* - Объекты сериализуются с сортировкой ключей.
|
|
8
|
+
* - Массивы сохраняют порядок.
|
|
9
|
+
* - Функции и symbol — недопустимы (как в TanStack Query), кидаем.
|
|
10
|
+
* - undefined в массиве становится null, в объекте — поле пропускается.
|
|
11
|
+
*
|
|
12
|
+
* Пример: ['orders', { sort: 'date', dir: 'asc' }] и
|
|
13
|
+
* ['orders', { dir: 'asc', sort: 'date' }] дают одинаковый hash.
|
|
14
|
+
*/
|
|
15
|
+
declare function hashQueryKey(key: QueryKey): string;
|
|
16
|
+
/**
|
|
17
|
+
* Проверяет, начинается ли `key` с `prefix`.
|
|
18
|
+
* Используется для invalidateQueries по префиксу: ['orders'] матчит
|
|
19
|
+
* и ['orders', 'manager'], и ['orders', 960].
|
|
20
|
+
*/
|
|
21
|
+
declare function matchQueryKey(prefix: QueryKey, key: QueryKey): boolean;
|
|
22
|
+
|
|
23
|
+
type QueryStatus = 'idle' | 'loading' | 'success' | 'error';
|
|
24
|
+
type QueryState<T> = {
|
|
25
|
+
data: T | undefined;
|
|
26
|
+
error: Error | null;
|
|
27
|
+
status: QueryStatus;
|
|
28
|
+
updatedAt: number;
|
|
29
|
+
isStale: boolean;
|
|
30
|
+
};
|
|
31
|
+
type Listener$2 = () => void;
|
|
32
|
+
type QueryEntry<T> = {
|
|
33
|
+
key: QueryKey;
|
|
34
|
+
state: QueryState<T>;
|
|
35
|
+
subscribers: Set<Listener$2>;
|
|
36
|
+
inflight: Promise<T> | null;
|
|
37
|
+
inflightController: AbortController | null;
|
|
38
|
+
gcTimer: ReturnType<typeof setTimeout> | null;
|
|
39
|
+
staleTime: number;
|
|
40
|
+
gcTime: number;
|
|
41
|
+
};
|
|
42
|
+
type QueryFnContext = {
|
|
43
|
+
signal: AbortSignal;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* queryFn принимает контекст с AbortSignal. Если HTTP-клиент его
|
|
47
|
+
* использует — отмена будет реальной; если игнорирует — поведение
|
|
48
|
+
* деградирует до текущего (запрос идёт до конца, но кэш игнорирует результат).
|
|
49
|
+
*
|
|
50
|
+
* Для обратной совместимости старая сигнатура `() => Promise<T>` тоже
|
|
51
|
+
* принимается — пакет просто не передаст signal внутрь.
|
|
52
|
+
*/
|
|
53
|
+
type QueryFn<T> = (ctx: QueryFnContext) => Promise<T>;
|
|
54
|
+
type FetchOptions = {
|
|
55
|
+
staleTime?: number;
|
|
56
|
+
gcTime?: number;
|
|
57
|
+
/** Если true — игнорируем staleTime и форсим запрос */
|
|
58
|
+
force?: boolean;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* In-memory кэш запросов с подпиской по ключу, dedupe inflight-промисов
|
|
62
|
+
* и сборкой мусора через gcTime.
|
|
63
|
+
*/
|
|
64
|
+
declare class QueryCache {
|
|
65
|
+
private entries;
|
|
66
|
+
private globalListeners;
|
|
67
|
+
/**
|
|
68
|
+
* Подписка на любое изменение кэша: setData, invalidate, remove,
|
|
69
|
+
* успешный/ошибочный fetch. Используется persistQueryClient и
|
|
70
|
+
* devtools-подобными адаптерами. Не дублирует `subscribe(key, ...)`.
|
|
71
|
+
*/
|
|
72
|
+
subscribeAll(listener: Listener$2): () => void;
|
|
73
|
+
private notifyGlobal;
|
|
74
|
+
private ensureEntry;
|
|
75
|
+
getState<T>(key: QueryKey): QueryState<T> | undefined;
|
|
76
|
+
getData<T>(key: QueryKey): T | undefined;
|
|
77
|
+
setData<T>(key: QueryKey, updater: T | ((prev: T | undefined) => T)): void;
|
|
78
|
+
/**
|
|
79
|
+
* Подписка на изменения ключа. Возвращает unsubscribe.
|
|
80
|
+
* Подписка останавливает GC таймер; отписка — запускает его обратно.
|
|
81
|
+
*/
|
|
82
|
+
subscribe(key: QueryKey, listener: Listener$2): () => void;
|
|
83
|
+
private notify;
|
|
84
|
+
private scheduleGc;
|
|
85
|
+
/**
|
|
86
|
+
* Запускает или присоединяется к inflight-запросу.
|
|
87
|
+
* Если данные свежие (не stale) и не force — отдаёт кэш без запроса.
|
|
88
|
+
*/
|
|
89
|
+
fetch<T>(key: QueryKey, queryFn: QueryFn<T>, options?: FetchOptions): Promise<T>;
|
|
90
|
+
/**
|
|
91
|
+
* Помечает запись как stale. Сами по себе данные не удаляются.
|
|
92
|
+
* Если есть подписчики — они получат уведомление, чтобы инициировать refetch.
|
|
93
|
+
*/
|
|
94
|
+
invalidate(predicate: QueryKey | ((key: QueryKey) => boolean)): string[];
|
|
95
|
+
/**
|
|
96
|
+
* Отменяет «привязку» inflight-промиса к ключу. Сам HTTP-запрос
|
|
97
|
+
* продолжит исполняться (executeRequest не использует AbortSignal),
|
|
98
|
+
* но его результат больше не попадёт в кэш и не уведомит подписчиков.
|
|
99
|
+
* Полезно при размонтировании / при переключении страниц.
|
|
100
|
+
*/
|
|
101
|
+
cancelQueries(predicate: QueryKey | ((key: QueryKey) => boolean)): void;
|
|
102
|
+
/**
|
|
103
|
+
* Полностью удаляет записи (даже с активными подписчиками).
|
|
104
|
+
* Используется редко — обычно достаточно invalidate.
|
|
105
|
+
*/
|
|
106
|
+
remove(predicate: QueryKey | ((key: QueryKey) => boolean)): void;
|
|
107
|
+
/** Только для тестов / DevTools. */
|
|
108
|
+
_debugEntries(): ReadonlyMap<string, QueryEntry<unknown>>;
|
|
109
|
+
/**
|
|
110
|
+
* Сериализует записи со статусом success — для persistence.
|
|
111
|
+
* inflight / loading / error не сохраняются, чтобы не гидратировать
|
|
112
|
+
* приложение в полу-загруженном состоянии.
|
|
113
|
+
*/
|
|
114
|
+
dehydrate(filter?: (key: QueryKey) => boolean): DehydratedState;
|
|
115
|
+
hydrate(state: DehydratedState): void;
|
|
116
|
+
}
|
|
117
|
+
type DehydratedQuery = {
|
|
118
|
+
key: unknown[];
|
|
119
|
+
data: unknown;
|
|
120
|
+
updatedAt: number;
|
|
121
|
+
};
|
|
122
|
+
type DehydratedState = {
|
|
123
|
+
queries: DehydratedQuery[];
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Высокоуровневый фасад над QueryCache: единый объект, который удобно
|
|
128
|
+
* прокидывать через Provider и дергать из push-handler'ов / эффектов.
|
|
129
|
+
*
|
|
130
|
+
* Сами queryFn-ы здесь не регистрируются — refetchQueries требует, чтобы
|
|
131
|
+
* либо подписчик сам перезапустил запрос (через subscribe), либо чтобы
|
|
132
|
+
* вызвали fetchQuery с queryFn вручную. Это намеренно: хук React сам
|
|
133
|
+
* знает, как собрать свой queryFn из endpoint/params.
|
|
134
|
+
*/
|
|
135
|
+
declare class QueryClient {
|
|
136
|
+
readonly cache: QueryCache;
|
|
137
|
+
constructor(cache?: QueryCache);
|
|
138
|
+
getQueryData<T>(key: QueryKey): T | undefined;
|
|
139
|
+
setQueryData<T>(key: QueryKey, updater: T | ((prev: T | undefined) => T)): void;
|
|
140
|
+
fetchQuery<T>(key: QueryKey, queryFn: QueryFn<T>, options?: FetchOptions): Promise<T>;
|
|
141
|
+
invalidateQueries(predicate: QueryKey | ((key: QueryKey) => boolean)): void;
|
|
142
|
+
removeQueries(predicate: QueryKey | ((key: QueryKey) => boolean)): void;
|
|
143
|
+
cancelQueries(predicate: QueryKey | ((key: QueryKey) => boolean)): void;
|
|
144
|
+
}
|
|
145
|
+
/** Singleton-доступ для тех мест, где Provider недоступен (push-handler и т.п.). */
|
|
146
|
+
declare function getQueryClient(): QueryClient;
|
|
147
|
+
declare function setQueryClient(client: QueryClient): void;
|
|
148
|
+
|
|
1
149
|
type RequestConfig = {
|
|
2
150
|
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
3
151
|
requestParams?: Record<string, string>;
|
|
@@ -7,9 +155,40 @@ type ResponseWrapper<DataType, ErrorsType = unknown> = {
|
|
|
7
155
|
message?: string;
|
|
8
156
|
errors?: ErrorsType;
|
|
9
157
|
} & DataType;
|
|
10
|
-
type UseFetchOptions<T> = {
|
|
158
|
+
type UseFetchOptions<T, TSelected = T> = {
|
|
159
|
+
/**
|
|
160
|
+
* При `false`:
|
|
161
|
+
* - запрос НЕ инициируется (ни на mount, ни на focus/reconnect/poll);
|
|
162
|
+
* - но хук **подписан на ключ кэша** и перерисуется, если данные
|
|
163
|
+
* обновит другой источник (другой `useFetch` с тем же ключом,
|
|
164
|
+
* `setQueryData` / `invalidateQueries`, мутация, push-handler).
|
|
165
|
+
*
|
|
166
|
+
* То есть `enabled: false` превращает хук в read-only слушателя.
|
|
167
|
+
* Если нужно полностью «потушить» хук — просто не вызывай его.
|
|
168
|
+
*
|
|
169
|
+
* По умолчанию `true`.
|
|
170
|
+
*/
|
|
11
171
|
enabled?: boolean;
|
|
12
172
|
refetchOnMount?: boolean;
|
|
173
|
+
/** Refetch при возврате на экран / в браузерное окно. */
|
|
174
|
+
refetchOnFocus?: boolean;
|
|
175
|
+
/** Refetch при возврате приложения в активное состояние (RN AppState). */
|
|
176
|
+
refetchOnAppActive?: boolean;
|
|
177
|
+
/** Refetch при восстановлении сетевого соединения (offline → online). */
|
|
178
|
+
refetchOnReconnect?: boolean;
|
|
179
|
+
/** Время свежести данных в ms. Пока не истечёт — повторный mount берёт из кэша без сети. */
|
|
180
|
+
staleTime?: number;
|
|
181
|
+
/** Сколько держать запись в кэше после ухода последнего подписчика. По умолчанию 5 мин. */
|
|
182
|
+
gcTime?: number;
|
|
183
|
+
/** Интервал поллинга в ms. Поллинг автоматически останавливается, если экран не виден. */
|
|
184
|
+
pollingInterval?: number;
|
|
185
|
+
/**
|
|
186
|
+
* Кастомный queryKey. По умолчанию собирается как
|
|
187
|
+
* `['__endpoint__', endpointString, params]`.
|
|
188
|
+
*/
|
|
189
|
+
queryKey?: readonly unknown[];
|
|
190
|
+
/** Селектор результата — пересчитывается мемоизированно. */
|
|
191
|
+
select?: (data: T) => TSelected;
|
|
13
192
|
onSuccess?: (data: T) => void;
|
|
14
193
|
onError?: (error: Error) => void;
|
|
15
194
|
};
|
|
@@ -24,6 +203,16 @@ type UsePaginateOptions<T> = {
|
|
|
24
203
|
enabled?: boolean;
|
|
25
204
|
initialPage?: number;
|
|
26
205
|
initialLimit?: number;
|
|
206
|
+
/** ms — пока страница свежая, повторный mount берёт её из кэша. */
|
|
207
|
+
staleTime?: number;
|
|
208
|
+
gcTime?: number;
|
|
209
|
+
/**
|
|
210
|
+
* Если true — при смене страницы (или params) предыдущие данные остаются
|
|
211
|
+
* на экране до прихода новых. Полезно для плавной пагинации.
|
|
212
|
+
*/
|
|
213
|
+
keepPreviousData?: boolean;
|
|
214
|
+
/** Кастомный префикс ключа кэша. По умолчанию — endpoint + serialized params. */
|
|
215
|
+
queryKey?: readonly unknown[];
|
|
27
216
|
onSuccess?: (data: T) => void;
|
|
28
217
|
onError?: (error: Error) => void;
|
|
29
218
|
};
|
|
@@ -36,17 +225,39 @@ type UsePaginateResult<TData extends unknown[]> = {
|
|
|
36
225
|
hasPreviousPage: boolean;
|
|
37
226
|
isLoading: boolean;
|
|
38
227
|
isFetchingNextPage: boolean;
|
|
228
|
+
/** true если данные показываются из предыдущей страницы (keepPreviousData). */
|
|
229
|
+
isPlaceholderData: boolean;
|
|
39
230
|
error: Error | null;
|
|
40
231
|
fetchNextPage: () => Promise<void>;
|
|
41
232
|
fetchPreviousPage: () => Promise<void>;
|
|
233
|
+
/** Префетчит следующую страницу в кэш, не меняя UI. */
|
|
234
|
+
prefetchNextPage: () => Promise<void>;
|
|
42
235
|
refetch: () => Promise<void>;
|
|
43
236
|
reset: () => void;
|
|
44
237
|
};
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
238
|
+
|
|
239
|
+
type UseMutationOptions<TData, TVariables, TContext = unknown> = {
|
|
240
|
+
/**
|
|
241
|
+
* Вызывается ДО запроса. Может вернуть context — он попадёт в onError
|
|
242
|
+
* (для rollback) и в onSettled. Используется для optimistic updates:
|
|
243
|
+
* сохранить снепшот → применить оптимистичный setQueryData → в onError
|
|
244
|
+
* вернуть снепшот обратно.
|
|
245
|
+
*/
|
|
246
|
+
onMutate?: (variables: TVariables) => void | TContext | Promise<void | TContext>;
|
|
247
|
+
onSuccess?: (data: TData, variables: TVariables, context: TContext | undefined) => void | Promise<void>;
|
|
248
|
+
onError?: (error: Error, variables: TVariables, context: TContext | undefined) => void | Promise<void>;
|
|
249
|
+
onSettled?: (data: TData | null, error: Error | null, variables: TVariables, context: TContext | undefined) => void | Promise<void>;
|
|
250
|
+
/**
|
|
251
|
+
* Ключи кэша, которые надо инвалидировать после успеха.
|
|
252
|
+
* Может быть массивом ключей или функцией, считающей их по vars/data.
|
|
253
|
+
* Каждый ключ матчится по префиксу (см. matchQueryKey).
|
|
254
|
+
*/
|
|
255
|
+
invalidateKeys?: QueryKey[] | ((vars: TVariables, data: TData) => QueryKey[]);
|
|
256
|
+
/**
|
|
257
|
+
* Точечно патчит кэш после успеха — до invalidate. Удобно для
|
|
258
|
+
* «сервер вернул свежий объект, положим его прямо в ['orders', id]».
|
|
259
|
+
*/
|
|
260
|
+
setQueryData?: (client: QueryClient, variables: TVariables, data: TData) => void;
|
|
50
261
|
};
|
|
51
262
|
type UseMutationResult<TData, TVariables> = {
|
|
52
263
|
data: TData | null;
|
|
@@ -61,23 +272,33 @@ type UseMutationResult<TData, TVariables> = {
|
|
|
61
272
|
interface IHttpClient {
|
|
62
273
|
get<T>(url: string, config?: {
|
|
63
274
|
params?: Record<string, unknown>;
|
|
275
|
+
signal?: AbortSignal;
|
|
64
276
|
}): Promise<T>;
|
|
65
277
|
request<T>(url: string, config: {
|
|
66
278
|
method?: string;
|
|
67
279
|
data?: Record<string, unknown>;
|
|
280
|
+
signal?: AbortSignal;
|
|
68
281
|
}): Promise<T>;
|
|
69
282
|
}
|
|
70
283
|
type ApiClientConfig = {
|
|
71
284
|
httpClient: IHttpClient;
|
|
72
285
|
onUnauthorized?: () => void | Promise<void>;
|
|
286
|
+
/**
|
|
287
|
+
* Когда true — любая ошибка (HTTP >= 400, сеть, тело с `{ status: false }`)
|
|
288
|
+
* приводит к `throw new ApiError(...)`. По умолчанию false — пакет
|
|
289
|
+
* сохраняет старое поведение (ошибки приходят как `{ status: false }`).
|
|
290
|
+
* Включать только после того, как все вызовы `await *.mutate()` /
|
|
291
|
+
* `await *.fetch()` обёрнуты в try/catch.
|
|
292
|
+
*/
|
|
293
|
+
throwOnError?: boolean;
|
|
73
294
|
};
|
|
74
295
|
type ApiClientReturn<ResponseType, RequestParamsType, ErrorResponseType = unknown> = {
|
|
75
296
|
fetch: (params?: RequestParamsType) => Promise<ResponseWrapper<ResponseType, ErrorResponseType>>;
|
|
76
|
-
useFetch: (params?: RequestParamsType, options?: UseFetchOptions<ResponseWrapper<ResponseType, ErrorResponseType
|
|
297
|
+
useFetch: <TSelected = ResponseWrapper<ResponseType, ErrorResponseType>>(params?: RequestParamsType, options?: UseFetchOptions<ResponseWrapper<ResponseType, ErrorResponseType>, TSelected>) => UseFetchResult<TSelected>;
|
|
77
298
|
};
|
|
78
299
|
type ApiMutationReturn<ResponseType, RequestParamsType, ErrorResponseType = unknown> = {
|
|
79
300
|
mutate: (params?: RequestParamsType) => Promise<ResponseWrapper<ResponseType, ErrorResponseType>>;
|
|
80
|
-
useMutation: (options?: UseMutationOptions<ResponseWrapper<ResponseType, ErrorResponseType>, RequestParamsType>) => UseMutationResult<ResponseWrapper<ResponseType, ErrorResponseType>, RequestParamsType>;
|
|
301
|
+
useMutation: <TContext = unknown>(options?: UseMutationOptions<ResponseWrapper<ResponseType, ErrorResponseType>, RequestParamsType, TContext>) => UseMutationResult<ResponseWrapper<ResponseType, ErrorResponseType>, RequestParamsType>;
|
|
81
302
|
};
|
|
82
303
|
type ApiPaginateReturn<ResponseType, RequestParamsType, DataArrayType extends unknown[], ErrorResponseType = unknown> = {
|
|
83
304
|
usePaginate: (params?: Omit<RequestParamsType, 'page' | 'limit'>, options?: UsePaginateOptions<ResponseWrapper<ResponseType, ErrorResponseType>>) => UsePaginateResult<DataArrayType>;
|
|
@@ -107,6 +328,182 @@ declare function getConfig(): ApiClientConfig;
|
|
|
107
328
|
*/
|
|
108
329
|
declare function isConfigured(): boolean;
|
|
109
330
|
|
|
331
|
+
/**
|
|
332
|
+
* Унифицированная ошибка API. Кидается из `executeRequest` (а значит,
|
|
333
|
+
* из `fetch`/`mutate`/хуков) только когда в `configureApiClient` включён
|
|
334
|
+
* `throwOnError: true`. По умолчанию поведение пакета не меняется —
|
|
335
|
+
* ошибки приходят как `{ status: false }` (см. CHANGELOG, Фаза 3.5).
|
|
336
|
+
*/
|
|
337
|
+
type ApiErrorInit<E = unknown> = {
|
|
338
|
+
message: string;
|
|
339
|
+
status: number;
|
|
340
|
+
code?: string;
|
|
341
|
+
errors?: E;
|
|
342
|
+
isNetworkError?: boolean;
|
|
343
|
+
isUnauthorized?: boolean;
|
|
344
|
+
isValidationError?: boolean;
|
|
345
|
+
raw?: unknown;
|
|
346
|
+
};
|
|
347
|
+
declare class ApiError<E = unknown> extends Error {
|
|
348
|
+
readonly status: number;
|
|
349
|
+
readonly code?: string;
|
|
350
|
+
readonly errors?: E;
|
|
351
|
+
readonly isNetworkError: boolean;
|
|
352
|
+
readonly isUnauthorized: boolean;
|
|
353
|
+
readonly isValidationError: boolean;
|
|
354
|
+
readonly raw: unknown;
|
|
355
|
+
constructor(init: ApiErrorInit<E>);
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Конвертация произвольного throw'нутого значения в `ApiError`.
|
|
359
|
+
* Покрывает 4 кейса:
|
|
360
|
+
* - `ApiError` → passthrough
|
|
361
|
+
* - axios-like `{ response: { status, data } }` → ApiError с полями из data
|
|
362
|
+
* - `Error` (сетевая ошибка, таймаут) → ApiError(isNetworkError, status: 0)
|
|
363
|
+
* - неизвестный объект → ApiError(message: 'Unknown error', status: 0)
|
|
364
|
+
*/
|
|
365
|
+
declare function toApiError(thrown: unknown): ApiError;
|
|
366
|
+
/**
|
|
367
|
+
* Для 2xx ответа, в теле которого Laravel-style `{ status: false }`.
|
|
368
|
+
* Возвращает ApiError(status: 200, ...). Вызывается из executeRequest
|
|
369
|
+
* только при `throwOnError: true`.
|
|
370
|
+
*/
|
|
371
|
+
declare function businessErrorToApiError(response: unknown): ApiError;
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Storage-адаптер. Совместим с AsyncStorage и expo-secure-store:
|
|
375
|
+
* { getItem(key): Promise<string|null>, setItem(key, value): Promise<void>,
|
|
376
|
+
* removeItem(key): Promise<void> }.
|
|
377
|
+
*/
|
|
378
|
+
interface PersistStorage {
|
|
379
|
+
getItem(key: string): Promise<string | null>;
|
|
380
|
+
setItem(key: string, value: string): Promise<void>;
|
|
381
|
+
removeItem(key: string): Promise<void>;
|
|
382
|
+
}
|
|
383
|
+
type PersistOptions = {
|
|
384
|
+
client: QueryClient;
|
|
385
|
+
storage: PersistStorage;
|
|
386
|
+
/** Ключ в storage. По умолчанию 'react-api-client:cache'. */
|
|
387
|
+
storageKey?: string;
|
|
388
|
+
/** Дросселирование записи (ms). По умолчанию 1000. */
|
|
389
|
+
throttleMs?: number;
|
|
390
|
+
/** Фильтр ключей: что вообще сохранять. По умолчанию — всё. */
|
|
391
|
+
allowList?: (key: QueryKey) => boolean;
|
|
392
|
+
/** Максимальный возраст сохранённого снэпшота (ms). Старее — выбрасываем. */
|
|
393
|
+
maxAge?: number;
|
|
394
|
+
/**
|
|
395
|
+
* Версия снэпшота. При несовпадении — снэпшот игнорируется и удаляется.
|
|
396
|
+
* Поднимай при изменении формата данных в кэше.
|
|
397
|
+
*/
|
|
398
|
+
version?: string | number;
|
|
399
|
+
};
|
|
400
|
+
/**
|
|
401
|
+
* Подключает QueryClient к persistent storage.
|
|
402
|
+
*
|
|
403
|
+
* С версии 2.0.0 — подписан на `cache.subscribeAll`, поэтому
|
|
404
|
+
* автоматически сохраняет состояние через `throttleMs` после любого
|
|
405
|
+
* изменения (setData, успешный fetch, invalidate, remove). Ручной
|
|
406
|
+
* `persist()` остаётся доступным для критичных моментов (logout,
|
|
407
|
+
* shutdown), но в обычном потоке не нужен.
|
|
408
|
+
*
|
|
409
|
+
* Возвращает:
|
|
410
|
+
* - `restore()` — гидратирует кэш из storage. Вызывать на старте.
|
|
411
|
+
* - `persist()` — форс-запись текущего состояния.
|
|
412
|
+
* - `unsubscribe()` — отключить авто-сохранение.
|
|
413
|
+
*/
|
|
414
|
+
declare function persistQueryClient(options: PersistOptions): {
|
|
415
|
+
restore: () => Promise<void>;
|
|
416
|
+
persist: () => Promise<void>;
|
|
417
|
+
unsubscribe: () => void;
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
type CacheEntrySnapshot = {
|
|
421
|
+
key: QueryKey;
|
|
422
|
+
hash: string;
|
|
423
|
+
status: QueryStatus;
|
|
424
|
+
isStale: boolean;
|
|
425
|
+
updatedAt: number;
|
|
426
|
+
hasData: boolean;
|
|
427
|
+
subscribers: number;
|
|
428
|
+
hasInflight: boolean;
|
|
429
|
+
errorMessage: string | null;
|
|
430
|
+
};
|
|
431
|
+
/**
|
|
432
|
+
* Снимок состояния всего кэша — без приватных полей и без данных.
|
|
433
|
+
* Удобно выводить в debug-экране или логировать.
|
|
434
|
+
*/
|
|
435
|
+
declare function inspectCache(cache: QueryCache): CacheEntrySnapshot[];
|
|
436
|
+
/** «invalidate all» — пометить весь кэш как stale. */
|
|
437
|
+
declare function invalidateAll(client: QueryClient): void;
|
|
438
|
+
/** Краткая сводка для логов: сколько записей, активных подписчиков, inflight. */
|
|
439
|
+
declare function summarizeCache(cache: QueryCache): {
|
|
440
|
+
total: number;
|
|
441
|
+
withSubscribers: number;
|
|
442
|
+
inflight: number;
|
|
443
|
+
stale: number;
|
|
444
|
+
byStatus: Record<QueryStatus, number>;
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Глобальный менеджер «фокуса» приложения.
|
|
449
|
+
* - В вебе автоматически подключается к window focus/visibilitychange.
|
|
450
|
+
* - В React Native интеграцию ставит сам потребитель через
|
|
451
|
+
* `focusManager.setFocused(state === 'active')` из AppState.
|
|
452
|
+
*
|
|
453
|
+
* Подписчики (useFetch с refetchOnFocus / refetchOnAppActive) получают
|
|
454
|
+
* уведомление при переходе в focused == true.
|
|
455
|
+
*/
|
|
456
|
+
type Listener$1 = (focused: boolean) => void;
|
|
457
|
+
declare class FocusManager {
|
|
458
|
+
private focused;
|
|
459
|
+
private listeners;
|
|
460
|
+
private cleanup;
|
|
461
|
+
subscribe(listener: Listener$1): () => void;
|
|
462
|
+
isFocused(): boolean;
|
|
463
|
+
setFocused(focused: boolean): void;
|
|
464
|
+
private setupBrowserListeners;
|
|
465
|
+
private teardownBrowserListeners;
|
|
466
|
+
}
|
|
467
|
+
declare const focusManager: FocusManager;
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Глобальный менеджер сетевого статуса.
|
|
471
|
+
* - В браузере подключается к window online/offline.
|
|
472
|
+
* - В React Native интеграция — через NetInfo (опционально):
|
|
473
|
+
* `NetInfo.addEventListener(s => onlineManager.setOnline(!!s.isConnected))`.
|
|
474
|
+
* Жёсткой зависимости от NetInfo нет — без него по умолчанию online: true.
|
|
475
|
+
*
|
|
476
|
+
* Подписчики (useFetch с refetchOnReconnect) получают уведомление при
|
|
477
|
+
* переходе offline → online.
|
|
478
|
+
*/
|
|
479
|
+
type Listener = (online: boolean) => void;
|
|
480
|
+
declare class OnlineManager {
|
|
481
|
+
private online;
|
|
482
|
+
private listeners;
|
|
483
|
+
private cleanup;
|
|
484
|
+
subscribe(listener: Listener): () => void;
|
|
485
|
+
isOnline(): boolean;
|
|
486
|
+
setOnline(online: boolean): void;
|
|
487
|
+
private setupBrowserListeners;
|
|
488
|
+
private teardownBrowserListeners;
|
|
489
|
+
}
|
|
490
|
+
declare const onlineManager: OnlineManager;
|
|
491
|
+
|
|
492
|
+
type ApiClientProviderProps = {
|
|
493
|
+
client?: QueryClient;
|
|
494
|
+
children: ReactNode;
|
|
495
|
+
};
|
|
496
|
+
/**
|
|
497
|
+
* Корневой Provider пакета. Создаёт (или принимает) QueryClient и кладёт
|
|
498
|
+
* его в React Context. Хуки достают клиент через useQueryClient().
|
|
499
|
+
*
|
|
500
|
+
* Также синхронизирует переданный client с singleton'ом
|
|
501
|
+
* getQueryClient() — чтобы push-handler'ы вне React-дерева могли дергать
|
|
502
|
+
* `getQueryClient().invalidateQueries(...)`.
|
|
503
|
+
*/
|
|
504
|
+
declare function ApiClientProvider({ client, children, }: ApiClientProviderProps): react.FunctionComponentElement<react.ProviderProps<QueryClient | null>>;
|
|
505
|
+
declare function useQueryClient(): QueryClient;
|
|
506
|
+
|
|
110
507
|
/**
|
|
111
508
|
* Creates an API client for GET requests
|
|
112
509
|
* @param endpoint - URL string or function that generates URL from params
|
|
@@ -149,4 +546,4 @@ declare function apiPaginate<ResponseType extends {
|
|
|
149
546
|
totalExtractor?: (response: ResponseType) => number;
|
|
150
547
|
}): ApiPaginateReturn<ResponseType, RequestParamsType, TData, ErrorResponseType>;
|
|
151
548
|
|
|
152
|
-
export { type ApiClientConfig, type IHttpClient, type ResponseWrapper, type UseFetchOptions, type UseFetchResult, type UseMutationOptions, type UseMutationResult, type UsePaginateOptions, type UsePaginateResult, apiMutation, apiPaginate, configureApiClient, apiClient as default, getConfig, isConfigured };
|
|
549
|
+
export { type ApiClientConfig, ApiClientProvider, type ApiClientProviderProps, ApiError, type ApiErrorInit, type CacheEntrySnapshot, type DehydratedQuery, type DehydratedState, type FetchOptions, type IHttpClient, type PersistOptions, type PersistStorage, QueryCache, QueryClient, type QueryFn, type QueryKey, type QueryState, type QueryStatus, type ResponseWrapper, type UseFetchOptions, type UseFetchResult, type UseMutationOptions, type UseMutationResult, type UsePaginateOptions, type UsePaginateResult, apiMutation, apiPaginate, businessErrorToApiError, configureApiClient, apiClient as default, focusManager, getConfig, getQueryClient, hashQueryKey, inspectCache, invalidateAll, isConfigured, matchQueryKey, onlineManager, persistQueryClient, setQueryClient, summarizeCache, toApiError, useQueryClient };
|