mbt-api-client 1.0.4 → 1.1.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.cts CHANGED
@@ -1,917 +1,83 @@
1
1
  import * as react from 'react';
2
2
  import { AxiosRequestConfig, AxiosInstance } from 'axios';
3
3
 
4
- /**
5
- * Модуль управления обновлением токенов
6
- *
7
- * Реализует механизм обновления JWT токенов с очередью запросов.
8
- * Предотвращает множественные одновременные запросы на обновление токена,
9
- * когда несколько параллельных API-запросов получают ошибку 401.
10
- *
11
- * @example
12
- * ```typescript
13
- * // Создание менеджера с кастомными функциями
14
- * const tokenManager = createTokenRefreshManager({
15
- * refreshTokenFn: async () => {
16
- * const response = await fetch('/api/auth/refresh');
17
- * const data = await response.json();
18
- * return { ok: true, accessToken: data.accessToken };
19
- * },
20
- * onNavigateToLogin: () => router.push('/login'),
21
- * });
22
- *
23
- * // Использование с RTK Query или другими клиентами
24
- * if (response.status === 401) {
25
- * const newToken = await tokenManager.handle401();
26
- * // Повторить запрос с новым токеном
27
- * }
28
- * ```
29
- *
30
- * @module token-refresh
31
- */
32
- /**
33
- * Конфигурация менеджера обновления токенов
34
- *
35
- * @example
36
- * ```typescript
37
- * const config: TokenRefreshConfig = {
38
- * refreshTokenFn: async () => {
39
- * // Ваша логика обновления токена
40
- * return { ok: true, accessToken: 'new-token' };
41
- * },
42
- * onNavigateToLogin: () => window.location.href = '/login',
43
- * getAccessToken: () => localStorage.getItem('accessToken'),
44
- * getRefreshToken: () => localStorage.getItem('refreshToken'),
45
- * setTokens: (access, refresh) => {
46
- * localStorage.setItem('accessToken', access);
47
- * if (refresh) localStorage.setItem('refreshToken', refresh);
48
- * },
49
- * clearTokens: () => {
50
- * localStorage.removeItem('accessToken');
51
- * localStorage.removeItem('refreshToken');
52
- * },
53
- * };
54
- * ```
55
- */
56
4
  interface TokenRefreshConfig {
57
- /**
58
- * Функция для выполнения запроса на обновление токена
59
- *
60
- * Должна вернуть объект с `ok: true` и новым `accessToken` при успехе,
61
- * или `ok: false` при ошибке.
62
- *
63
- * @returns Промис с результатом обновления токена
64
- *
65
- * @example
66
- * ```typescript
67
- * refreshTokenFn: async () => {
68
- * try {
69
- * const response = await axios.post('/auth/refresh-token', {}, {
70
- * headers: { Authorization: `Bearer ${refreshToken}` }
71
- * });
72
- * return {
73
- * ok: true,
74
- * accessToken: response.data.accessToken,
75
- * refreshToken: response.data.refreshToken,
76
- * };
77
- * } catch {
78
- * return { ok: false };
79
- * }
80
- * }
81
- * ```
82
- */
83
5
  refreshTokenFn: () => Promise<TokenRefreshResult>;
84
- /**
85
- * Колбэк для перенаправления на страницу логина
86
- *
87
- * Вызывается когда:
88
- * - Токен невалиден (message: 'Invalid token')
89
- * - Обновление токена не удалось
90
- * - Refresh token истёк
91
- *
92
- * @default Очищает localStorage и редиректит на '#/login'
93
- *
94
- * @example
95
- * ```typescript
96
- * onNavigateToLogin: () => {
97
- * // Для React Router
98
- * navigate('/login');
99
- * // Или для Next.js
100
- * router.push('/login');
101
- * }
102
- * ```
103
- */
104
6
  onNavigateToLogin?: () => void;
105
- /**
106
- * Функция получения текущего access токена
107
- *
108
- * @default () => localStorage.getItem('accessToken')
109
- *
110
- * @example
111
- * ```typescript
112
- * // Для хранения в Redux
113
- * getAccessToken: () => store.getState().auth.accessToken
114
- * ```
115
- */
116
7
  getAccessToken?: () => string | null;
117
- /**
118
- * Функция получения текущего refresh токена
119
- *
120
- * @default () => localStorage.getItem('refreshToken')
121
- */
122
8
  getRefreshToken?: () => string | null;
123
- /**
124
- * Функция сохранения новых токенов после обновления
125
- *
126
- * @param accessToken - Новый access токен
127
- * @param refreshToken - Новый refresh токен (опционально)
128
- *
129
- * @default Сохраняет в localStorage
130
- *
131
- * @example
132
- * ```typescript
133
- * // Для хранения в Redux
134
- * setTokens: (access, refresh) => {
135
- * store.dispatch(setAuthTokens({ accessToken: access, refreshToken: refresh }));
136
- * }
137
- * ```
138
- */
139
9
  setTokens?: (accessToken: string, refreshToken?: string) => void;
140
- /**
141
- * Функция очистки токенов (при выходе или ошибке авторизации)
142
- *
143
- * @default Удаляет 'accessToken' и 'refreshToken' из localStorage
144
- */
145
10
  clearTokens?: () => void;
146
11
  }
147
- /**
148
- * Результат операции обновления токена
149
- *
150
- * @example
151
- * ```typescript
152
- * // Успешное обновление
153
- * const success: TokenRefreshResult = {
154
- * ok: true,
155
- * accessToken: 'eyJhbGciOiJIUzI1...',
156
- * refreshToken: 'dGhpcyBpcyBhIHJl...',
157
- * };
158
- *
159
- * // Ошибка обновления
160
- * const failure: TokenRefreshResult = { ok: false };
161
- * ```
162
- */
163
12
  interface TokenRefreshResult {
164
- /**
165
- * Успешность операции обновления
166
- *
167
- * `true` - токен успешно обновлён
168
- * `false` - ошибка обновления (пользователь будет перенаправлен на логин)
169
- */
170
13
  ok: boolean;
171
- /**
172
- * Новый access токен (только при `ok: true`)
173
- */
174
14
  accessToken?: string;
175
- /**
176
- * Новый refresh токен (опционально, только при `ok: true`)
177
- */
178
15
  refreshToken?: string;
179
16
  }
180
- /**
181
- * Менеджер обновления токенов с очередью запросов
182
- *
183
- * Решает проблему одновременного обновления токена при множественных
184
- * параллельных запросах, получивших 401 ошибку.
185
- *
186
- * **Как это работает:**
187
- * 1. Первый запрос с 401 инициирует обновление токена
188
- * 2. Последующие запросы с 401 добавляются в очередь ожидания
189
- * 3. После успешного обновления все запросы в очереди получают новый токен
190
- * 4. При ошибке обновления все запросы получают ошибку
191
- *
192
- * @example
193
- * ```typescript
194
- * // Создание менеджера
195
- * const tokenManager = new TokenRefreshManager({
196
- * refreshTokenFn: async () => {
197
- * const res = await fetch('/api/refresh');
198
- * const data = await res.json();
199
- * return { ok: true, accessToken: data.token };
200
- * },
201
- * });
202
- *
203
- * // Использование в axios interceptor
204
- * axios.interceptors.response.use(
205
- * response => response,
206
- * async error => {
207
- * if (error.response?.status === 401) {
208
- * const newToken = await tokenManager.handle401();
209
- * if (newToken) {
210
- * error.config.headers.Authorization = `Bearer ${newToken}`;
211
- * return axios(error.config);
212
- * }
213
- * }
214
- * return Promise.reject(error);
215
- * }
216
- * );
217
- * ```
218
- */
219
17
  declare class TokenRefreshManager {
220
18
  private isRefreshing;
221
19
  private refreshPromise;
222
20
  private queuedRequests;
223
21
  private config;
224
- /**
225
- * Создаёт новый экземпляр TokenRefreshManager
226
- *
227
- * @param config - Конфигурация менеджера
228
- *
229
- * @example
230
- * ```typescript
231
- * const manager = new TokenRefreshManager({
232
- * refreshTokenFn: myRefreshFunction,
233
- * onNavigateToLogin: () => router.push('/login'),
234
- * });
235
- * ```
236
- */
237
22
  constructor(config: TokenRefreshConfig);
238
- /**
239
- * Получает текущий access токен
240
- *
241
- * @returns Access токен или null, если токен отсутствует
242
- *
243
- * @example
244
- * ```typescript
245
- * const token = manager.getAccessToken();
246
- * if (token) {
247
- * headers.Authorization = `Bearer ${token}`;
248
- * }
249
- * ```
250
- */
251
23
  getAccessToken(): string | null;
252
- /**
253
- * Получает текущий refresh токен
254
- *
255
- * @returns Refresh токен или null, если токен отсутствует
256
- */
257
24
  getRefreshToken(): string | null;
258
- /**
259
- * Проверяет, идёт ли в данный момент процесс обновления токена
260
- *
261
- * Используйте для определения, нужно ли ставить запрос в очередь
262
- * или инициировать новое обновление.
263
- *
264
- * @returns `true` если обновление в процессе, `false` если нет
265
- *
266
- * @example
267
- * ```typescript
268
- * if (manager.isRefreshInProgress()) {
269
- * // Ждём завершения текущего обновления
270
- * const newToken = await manager.waitForTokenRefresh();
271
- * } else {
272
- * // Инициируем новое обновление
273
- * await manager.refreshToken();
274
- * }
275
- * ```
276
- */
277
25
  isRefreshInProgress(): boolean;
278
- /**
279
- * Добавляет запрос в очередь ожидания обновления токена
280
- *
281
- * Возвращает промис, который разрешится с новым токеном после
282
- * успешного обновления или будет отклонён при ошибке.
283
- *
284
- * @returns Промис с новым access токеном
285
- *
286
- * @example
287
- * ```typescript
288
- * // В response interceptor при множественных 401
289
- * if (manager.isRefreshInProgress()) {
290
- * try {
291
- * const newToken = await manager.waitForTokenRefresh();
292
- * // Повторить запрос с новым токеном
293
- * } catch {
294
- * // Обновление не удалось
295
- * }
296
- * }
297
- * ```
298
- */
299
26
  waitForTokenRefresh(): Promise<string>;
300
- /**
301
- * Выполняет обновление токена
302
- *
303
- * Если обновление уже в процессе, вернёт существующий промис.
304
- * После обновления уведомляет все запросы в очереди.
305
- *
306
- * @returns Промис с результатом обновления
307
- *
308
- * @example
309
- * ```typescript
310
- * const result = await manager.refreshToken();
311
- * if (result.ok) {
312
- * console.log('Новый токен:', result.accessToken);
313
- * } else {
314
- * console.log('Ошибка обновления токена');
315
- * }
316
- * ```
317
- */
318
27
  refreshToken(): Promise<TokenRefreshResult>;
319
- /**
320
- * Обрабатывает ошибку 401 — либо обновляет токен, либо перенаправляет на логин
321
- *
322
- * Основной метод для использования в interceptors. Автоматически:
323
- * - Перенаправляет на логин при невалидном токене
324
- * - Ставит запрос в очередь, если обновление уже идёт
325
- * - Инициирует обновление, если ещё не запущено
326
- *
327
- * @param isInvalidToken - Если true, токен считается невалидным и будет выполнен переход на логин
328
- * @returns Промис с новым access токеном или null при ошибке
329
- *
330
- * @example
331
- * ```typescript
332
- * // В axios response interceptor
333
- * if (error.response?.status === 401) {
334
- * const isInvalid = error.response.data?.message === 'Invalid token';
335
- * const newToken = await manager.handle401(isInvalid);
336
- *
337
- * if (newToken) {
338
- * // Повторить запрос с новым токеном
339
- * error.config.headers.Authorization = `Bearer ${newToken}`;
340
- * return axios(error.config);
341
- * }
342
- * // newToken === null означает переход на логин
343
- * }
344
- * ```
345
- */
346
28
  handle401(isInvalidToken?: boolean): Promise<string | null>;
347
- /**
348
- * Принудительно перенаправляет на страницу логина
349
- *
350
- * Вызывает колбэк onNavigateToLogin из конфигурации.
351
- *
352
- * @example
353
- * ```typescript
354
- * // При необходимости принудительного выхода
355
- * manager.navigateToLogin();
356
- * ```
357
- */
358
29
  navigateToLogin(): void;
359
- /**
360
- * Сбрасывает внутреннее состояние менеджера
361
- *
362
- * Полезно для тестирования или при необходимости
363
- * принудительно сбросить очередь запросов.
364
- *
365
- * @example
366
- * ```typescript
367
- * // В тестах
368
- * beforeEach(() => {
369
- * manager.reset();
370
- * });
371
- * ```
372
- */
373
30
  reset(): void;
374
31
  private performRefresh;
375
32
  private notifyQueueSuccess;
376
33
  private notifyQueueFailure;
377
34
  }
378
- /**
379
- * Создаёт новый экземпляр TokenRefreshManager
380
- *
381
- * Фабричная функция для создания менеджера обновления токенов.
382
- * Предпочтительный способ создания вместо прямого вызова конструктора.
383
- *
384
- * @param config - Конфигурация менеджера
385
- * @returns Новый экземпляр TokenRefreshManager
386
- *
387
- * @example
388
- * ```typescript
389
- * import { createTokenRefreshManager } from 'mbt-api-client';
390
- *
391
- * const tokenManager = createTokenRefreshManager({
392
- * refreshTokenFn: async () => {
393
- * const response = await fetch('/api/auth/refresh', {
394
- * method: 'POST',
395
- * headers: {
396
- * Authorization: `Bearer ${localStorage.getItem('refreshToken')}`,
397
- * },
398
- * });
399
- *
400
- * if (!response.ok) {
401
- * return { ok: false };
402
- * }
403
- *
404
- * const data = await response.json();
405
- * return {
406
- * ok: true,
407
- * accessToken: data.accessToken,
408
- * refreshToken: data.refreshToken,
409
- * };
410
- * },
411
- * onNavigateToLogin: () => {
412
- * window.location.href = '/login';
413
- * },
414
- * });
415
- *
416
- * // Использование
417
- * const newToken = await tokenManager.handle401();
418
- * ```
419
- */
420
35
  declare const createTokenRefreshManager: (config: TokenRefreshConfig) => TokenRefreshManager;
421
36
 
422
- /**
423
- * URL-адреса микросервисов API
424
- *
425
- * @example
426
- * ```typescript
427
- * const urls: ApiClientUrls = {
428
- * authService: 'https://auth.example.com',
429
- * userProgressService: 'https://progress.example.com',
430
- * recommendationService: 'https://rec.example.com',
431
- * partnerManager: 'https://partners.example.com',
432
- * puzzleController: 'https://puzzles.example.com',
433
- * monolith: 'https://api.example.com',
434
- * };
435
- * ```
436
- */
437
37
  interface ApiClientUrls {
438
- /** URL сервиса авторизации (логин, регистрация, refresh токенов) */
439
38
  authService: string;
440
- /** URL сервиса прогресса пользователя */
441
39
  userProgressService: string;
442
- /** URL сервиса рекомендаций */
443
40
  recommendationService: string;
444
- /** URL сервиса управления партнёрами */
445
41
  partnerManager: string;
446
- /** URL сервиса управления приключениями */
447
42
  adventureManager: string;
448
- /** URL сервиса агрегации данных для клиента */
449
43
  bff: string;
450
- /** URL контроллера пазлов/задач */
451
44
  puzzleController: string;
452
- /** URL контроллера микромодов */
453
45
  micromodeController: string;
454
- /** URL сервиса управления пользователями */
455
46
  userManager: string;
456
- /** URL основного монолитного сервиса */
457
47
  monolith: string;
458
48
  }
459
- /**
460
- * Конфигурация API клиента
461
- *
462
- * @example
463
- * ```typescript
464
- * const config: ApiClientConfig = {
465
- * urls: {
466
- * authService: 'https://auth.example.com',
467
- * userProgressService: 'https://progress.example.com',
468
- * // ... остальные URL
469
- * },
470
- * onNavigateToLogin: () => {
471
- * // Для React Router
472
- * navigate('/login');
473
- * },
474
- * timeout: 15000,
475
- * decodeJwt: (token) => {
476
- * // Кастомный декодер JWT
477
- * return jwtDecode(token);
478
- * },
479
- * };
480
- * ```
481
- */
482
49
  interface ApiClientConfig {
483
- /**
484
- * URL-адреса микросервисов
485
- */
486
50
  urls: ApiClientUrls;
487
- /**
488
- * Колбэк для перенаправления на страницу логина
489
- *
490
- * Вызывается при:
491
- * - Ошибке 401 с невалидным токеном
492
- * - Ошибке 403 (доступ запрещён)
493
- * - Неудачном обновлении токена
494
- *
495
- * @default Очищает localStorage и редиректит на '#/login'
496
- *
497
- * @example
498
- * ```typescript
499
- * // React Router
500
- * onNavigateToLogin: () => navigate('/login')
501
- *
502
- * // Next.js
503
- * onNavigateToLogin: () => router.push('/login')
504
- *
505
- * // Vanilla JS
506
- * onNavigateToLogin: () => { window.location.href = '/login' }
507
- * ```
508
- */
509
51
  onNavigateToLogin?: () => void;
510
- /**
511
- * Таймаут запросов в миллисекундах
512
- *
513
- * @default 10000 (10 секунд)
514
- */
515
52
  timeout?: number;
516
- /**
517
- * Функция декодирования JWT токена для извлечения userId
518
- *
519
- * Используется для добавления заголовка X-User-Id к запросам.
520
- * Если не указана, используется встроенный base64 декодер.
521
- *
522
- * @param token - JWT токен для декодирования
523
- * @returns Объект с userId или null при ошибке декодирования
524
- *
525
- * @default Встроенный base64 декодер
526
- *
527
- * @example
528
- * ```typescript
529
- * // С библиотекой jwt-decode
530
- * import { jwtDecode } from 'jwt-decode';
531
- *
532
- * decodeJwt: (token) => {
533
- * try {
534
- * return jwtDecode<{ userId: string }>(token);
535
- * } catch {
536
- * return null;
537
- * }
538
- * }
539
- * ```
540
- */
541
53
  decodeJwt?: (token: string) => {
542
54
  userId?: string;
543
55
  } | null;
544
56
  }
545
- /**
546
- * Обёртка над axios для выполнения HTTP-запросов
547
- *
548
- * Предоставляет типизированные методы для всех HTTP-операций.
549
- * Автоматически извлекает `data` из ответа axios.
550
- *
551
- * @example
552
- * ```typescript
553
- * interface User {
554
- * id: string;
555
- * name: string;
556
- * email: string;
557
- * }
558
- *
559
- * // GET запрос с типизацией
560
- * const user = await apiService.get<User>('/users/me');
561
- * console.log(user.name);
562
- *
563
- * // POST запрос
564
- * const newUser = await apiService.post<User>('/users', {
565
- * name: 'John',
566
- * email: 'john@example.com',
567
- * });
568
- *
569
- * // С дополнительными параметрами axios
570
- * const data = await apiService.get<Data>('/endpoint', {
571
- * params: { page: 1, limit: 10 },
572
- * headers: { 'X-Custom-Header': 'value' },
573
- * });
574
- * ```
575
- */
576
57
  interface ApiService {
577
- /**
578
- * Выполняет GET-запрос
579
- *
580
- * Автоматически добавляет cache-buster параметр `_t` для предотвращения кэширования.
581
- *
582
- * @typeParam T - Тип данных ответа
583
- * @param url - URL эндпоинта (относительно baseURL сервиса)
584
- * @param config - Дополнительные параметры axios (headers, params и т.д.)
585
- * @returns Промис с данными ответа
586
- *
587
- * @example
588
- * ```typescript
589
- * // Простой GET
590
- * const users = await service.get<User[]>('/users');
591
- *
592
- * // С query параметрами
593
- * const filtered = await service.get<User[]>('/users', {
594
- * params: { role: 'admin', active: true }
595
- * });
596
- * ```
597
- */
598
58
  get: <T>(url: string, config?: AxiosRequestConfig) => Promise<T>;
599
- /**
600
- * Выполняет POST-запрос
601
- *
602
- * @typeParam T - Тип данных ответа
603
- * @param url - URL эндпоинта (относительно baseURL сервиса)
604
- * @param data - Тело запроса (будет сериализовано в JSON)
605
- * @param config - Дополнительные параметры axios
606
- * @returns Промис с данными ответа
607
- *
608
- * @example
609
- * ```typescript
610
- * const newUser = await service.post<User>('/users', {
611
- * name: 'John Doe',
612
- * email: 'john@example.com',
613
- * });
614
- * ```
615
- */
616
59
  post: <T>(url: string, data?: unknown, config?: AxiosRequestConfig) => Promise<T>;
617
- /**
618
- * Выполняет PUT-запрос
619
- *
620
- * @typeParam T - Тип данных ответа
621
- * @param url - URL эндпоинта
622
- * @param data - Тело запроса для обновления
623
- * @param config - Дополнительные параметры axios
624
- * @returns Промис с данными ответа
625
- *
626
- * @example
627
- * ```typescript
628
- * const updated = await service.put<User>('/users/123', {
629
- * name: 'Jane Doe',
630
- * });
631
- * ```
632
- */
633
60
  put: <T>(url: string, data?: unknown, config?: AxiosRequestConfig) => Promise<T>;
634
- /**
635
- * Выполняет PATCH-запрос
636
- *
637
- * @typeParam T - Тип данных ответа
638
- * @param url - URL эндпоинта
639
- * @param data - Тело запроса для частичного обновления
640
- * @param config - Дополнительные параметры axios
641
- * @returns Промис с данными ответа
642
- *
643
- * @example
644
- * ```typescript
645
- * const updated = await service.patch<User>('/users/123', {
646
- * name: 'Jane Doe',
647
- * });
648
- * ```
649
- */
650
61
  patch: <T>(url: string, data?: unknown, config?: AxiosRequestConfig) => Promise<T>;
651
- /**
652
- * Выполняет DELETE-запрос
653
- *
654
- * @typeParam T - Тип данных ответа
655
- * @param url - URL эндпоинта
656
- * @param config - Дополнительные параметры axios
657
- * @returns Промис с данными ответа
658
- *
659
- * @example
660
- * ```typescript
661
- * await service.delete<void>('/users/123');
662
- * ```
663
- */
664
62
  delete: <T>(url: string, config?: AxiosRequestConfig) => Promise<T>;
665
- /**
666
- * Доступ к нативному экземпляру axios
667
- *
668
- * Используйте для добавления кастомных interceptors или
669
- * выполнения нестандартных запросов.
670
- *
671
- * @example
672
- * ```typescript
673
- * // Добавление кастомного interceptor
674
- * service.axiosInstance.interceptors.request.use(config => {
675
- * config.headers['X-Request-Id'] = generateId();
676
- * return config;
677
- * });
678
- * ```
679
- */
680
63
  axiosInstance: AxiosInstance;
681
64
  }
682
- /**
683
- * Главный объект API клиента
684
- *
685
- * Содержит настроенные сервисы для каждого микросервиса
686
- * и менеджер обновления токенов.
687
- *
688
- * @example
689
- * ```typescript
690
- * const apiClient = createApiClient({ urls: {...} });
691
- *
692
- * // Использование сервисов
693
- * const user = await apiClient.userProgressService.get('/me');
694
- * const puzzles = await apiClient.puzzleController.get('/puzzles');
695
- *
696
- * // Работа с токенами
697
- * const currentToken = apiClient.tokenRefreshManager.getAccessToken();
698
- * ```
699
- */
700
65
  interface ApiClient {
701
- /**
702
- * Сервис авторизации
703
- *
704
- * Используется для логина, регистрации, обновления токенов.
705
- */
706
66
  authService: ApiService;
707
- /**
708
- * Сервис прогресса пользователя
709
- *
710
- * Используется для получения и обновления прогресса обучения.
711
- */
712
67
  userProgressService: ApiService;
713
- /**
714
- * Сервис рекомендаций
715
- *
716
- * Используется для получения персонализированных рекомендаций.
717
- */
718
68
  recommendationService: ApiService;
719
- /**
720
- * Сервис управления партнёрами
721
- */
722
69
  partnerManager: ApiService;
723
- /**
724
- * Сервис управления приключениями
725
- */
726
70
  adventureManager: ApiService;
727
- /**
728
- * Сервис агрегации данных для клиента
729
- */
730
71
  bff: ApiService;
731
- /**
732
- * Контроллер пазлов/задач
733
- *
734
- * Используется для работы с учебными задачами и пазлами.
735
- */
736
72
  puzzleController: ApiService;
737
- /**
738
- * Контроллер микромодов
739
- */
740
73
  micromodeController: ApiService;
741
- /**
742
- * Сервис управления пользователями
743
- */
744
74
  userManager: ApiService;
745
- /**
746
- * Основной монолитный сервис
747
- *
748
- * Используется для запросов, не выделенных в отдельные микросервисы.
749
- */
750
75
  monolith: ApiService;
751
- /**
752
- * Менеджер обновления токенов
753
- *
754
- * Предоставляет доступ к функциям работы с токенами.
755
- * Можно использовать с RTK Query или другими HTTP-клиентами.
756
- *
757
- * @example
758
- * ```typescript
759
- * // Получение текущего токена
760
- * const token = apiClient.tokenRefreshManager.getAccessToken();
761
- *
762
- * // Обработка 401 в кастомном клиенте
763
- * if (response.status === 401) {
764
- * const newToken = await apiClient.tokenRefreshManager.handle401();
765
- * }
766
- * ```
767
- */
768
76
  tokenRefreshManager: TokenRefreshManager;
769
77
  }
770
- /**
771
- * Создаёт настроенный API клиент
772
- *
773
- * Фабричная функция, которая создаёт полностью настроенный API клиент
774
- * с поддержкой автоматического обновления токенов, обработкой ошибок
775
- * авторизации и типизированными методами запросов.
776
- *
777
- * **Особенности:**
778
- * - Автоматическое добавление Authorization заголовка
779
- * - Автоматическое обновление токена при 401 ошибке
780
- * - Очередь запросов при одновременном обновлении токена
781
- * - Добавление X-User-Id заголовка из JWT
782
- * - Cache-busting для GET запросов
783
- *
784
- * @param config - Конфигурация клиента
785
- * @returns Настроенный API клиент
786
- *
787
- * @example
788
- * ```typescript
789
- * import { createApiClient } from 'mbt-api-client';
790
- *
791
- * const apiClient = createApiClient({
792
- * urls: {
793
- * authService: 'https://auth.example.com',
794
- * userProgressService: 'https://progress.example.com',
795
- * recommendationService: 'https://rec.example.com',
796
- * partnerManager: 'https://partners.example.com',
797
- * puzzleController: 'https://puzzles.example.com',
798
- * monolith: 'https://api.example.com',
799
- * },
800
- * onNavigateToLogin: () => {
801
- * // Очистка состояния и редирект
802
- * store.dispatch(logout());
803
- * navigate('/login');
804
- * },
805
- * timeout: 15000, // 15 секунд
806
- * });
807
- *
808
- * // Использование
809
- * try {
810
- * const user = await apiClient.userProgressService.get<User>('/me');
811
- * console.log('Пользователь:', user);
812
- * } catch (error) {
813
- * console.error('Ошибка:', error);
814
- * }
815
- * ```
816
- */
817
78
  declare const createApiClient: (config: ApiClientConfig) => ApiClient;
818
- /**
819
- * React Context для API клиента
820
- *
821
- * Используется внутри ApiClientProvider для передачи клиента
822
- * через дерево компонентов.
823
- *
824
- * @example
825
- * ```typescript
826
- * // Для кастомных случаев (обычно используйте ApiClientProvider)
827
- * <ApiClientContext.Provider value={apiClient}>
828
- * <App />
829
- * </ApiClientContext.Provider>
830
- * ```
831
- */
832
79
  declare const ApiClientContext: react.Context<ApiClient | null>;
833
- /**
834
- * React хук для доступа к API клиенту
835
- *
836
- * Получает API клиент из контекста. Должен использоваться внутри
837
- * компонента, обёрнутого в ApiClientProvider.
838
- *
839
- * @returns API клиент с типизированными сервисами
840
- * @throws Error если используется вне ApiClientProvider
841
- *
842
- * @example
843
- * ```typescript
844
- * import { useApiClient } from 'mbt-api-client';
845
- *
846
- * function UserProfile() {
847
- * const { userProgressService } = useApiClient();
848
- * const [user, setUser] = useState<User | null>(null);
849
- *
850
- * useEffect(() => {
851
- * userProgressService.get<User>('/me')
852
- * .then(setUser)
853
- * .catch(console.error);
854
- * }, []);
855
- *
856
- * return <div>{user?.name}</div>;
857
- * }
858
- *
859
- * // С деструктуризацией нескольких сервисов
860
- * function Dashboard() {
861
- * const {
862
- * userProgressService,
863
- * recommendationService,
864
- * puzzleController,
865
- * } = useApiClient();
866
- *
867
- * // Параллельные запросы
868
- * const [progress, recommendations, puzzles] = await Promise.all([
869
- * userProgressService.get('/progress'),
870
- * recommendationService.get('/for-me'),
871
- * puzzleController.get('/puzzles'),
872
- * ]);
873
- * }
874
- * ```
875
- */
876
80
  declare const useApiClient: () => ApiClient;
877
- /**
878
- * React Provider для API клиента
879
- *
880
- * Оборачивает приложение для предоставления доступа к API клиенту
881
- * через хук useApiClient.
882
- *
883
- * @example
884
- * ```typescript
885
- * import { createApiClient, ApiClientProvider } from 'mbt-api-client';
886
- *
887
- * // Создание клиента (обычно в отдельном файле)
888
- * const apiClient = createApiClient({
889
- * urls: { ... },
890
- * });
891
- *
892
- * // В корне приложения
893
- * function App() {
894
- * return (
895
- * <ApiClientProvider value={apiClient}>
896
- * <Router>
897
- * <Routes />
898
- * </Router>
899
- * </ApiClientProvider>
900
- * );
901
- * }
902
- *
903
- * // С React Query
904
- * function App() {
905
- * return (
906
- * <QueryClientProvider client={queryClient}>
907
- * <ApiClientProvider value={apiClient}>
908
- * <Routes />
909
- * </ApiClientProvider>
910
- * </QueryClientProvider>
911
- * );
912
- * }
913
- * ```
914
- */
915
81
  declare const ApiClientProvider: react.Provider<ApiClient | null>;
916
82
 
917
83
  export { type ApiClient, type ApiClientConfig, ApiClientContext, ApiClientProvider, type ApiClientUrls, type ApiService, type TokenRefreshConfig, TokenRefreshManager, type TokenRefreshResult, createApiClient, createTokenRefreshManager, useApiClient };