@pushwoosh/http-client 1.4.2 → 1.5.0

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/README.md CHANGED
@@ -1,234 +1,304 @@
1
1
  # Pushwoosh / Micro Frontends / Http Client
2
2
  Этот пакет является частью микрофронтендовой архитектуры
3
3
  <br/>
4
- За основу взят проект [Single SPA](https://single-spa.js.org)
5
- <br/>
6
- Предназначен для выполнения запросов к API
7
-
8
- ## Термины
9
- [Аутентификация](https://auth0.com/docs/authentication) - процесс подтверждения личности пользователя
10
-
11
- [Авторизация](https://auth0.com/docs/authorization) - процесс проверки доступа к защищенным ресурсам
12
-
13
- [Клиент](https://www.rfc-editor.org/rfc/rfc6749.html#section-1.1) - приложение запрашивающее защищенные ресурсы от имени пользователя
14
-
15
- [Сервер авторизации](https://www.rfc-editor.org/rfc/rfc6749.html#section-1.1) - сервер, выдающий токены доступа клиенту после успешной аутентификации владельца ресурса и получение авторизации
4
+ Предназначен для выполнения запросов к API с использованием OAuth2 протокола
16
5
 
17
6
  ## Установка
18
- 1. Сгенерировать ключи для запуска сервера в режиме HTTPS. ([Confluence](https://confluence.corp.pushwoosh.com/display/FD/HTTPS+on+localhost))
7
+ 1. Сгенерировать ключи для запуска сервера в режиме
8
+ HTTPS ([Confluence](https://confluence.corp.pushwoosh.com/display/FD/HTTPS+on+localhost))
19
9
  2. Выполнить `npm ci`
20
10
 
21
11
  ## Запуск разработки
22
- 1. Скопировать файл `.env.example` в `.env`. Удалить из него комментарии к переменным
12
+ 1. Скопировать файл `.env.example` в `.env`
23
13
  2. Выполнить `npm start`
24
14
 
25
- ## Работа с библиотекой
26
- Библиотека собирается в формате UMD.
27
- <br/>
28
- В первую очередь предназначена для загрузки с помощью SystemJS.
15
+ ## Использование
16
+ Работу с Http Client можно разделить на несколько условных частей:
17
+
18
+ 1. Создание экземпляра
19
+ 2. Авторизация (этот шаг может быть пропущен)
20
+ 3. Выполнение запросов
21
+ 4. Обработка ответов
22
+ 5. Обработка ошибок
29
23
 
30
- ### Создание экземпляра HttpClient
31
- При создании экземпляра класса HttpClient необходимо указать следующие параметры:
24
+ ### Создание экземпляра
25
+ Первым делом нужно создать экземпляр HttpClient
32
26
 
33
27
  ```typescript
34
- import { HttpClient } from '@pushwoosh/http-client';
28
+ const httpClient = new HttpClient(history, config);
29
+ ```
35
30
 
36
- const httpClient = new HttpClient({
37
- errorMiddleware: (error: unknown): Promise<never> | never => {
38
- // какие-то действия над ошибками
39
- },
31
+ Где:
32
+ <br/>
33
+ <strong>history</strong> - API для работы с навигацией
34
+ <br/>
35
+ <strong>config</strong> - конфигурация Http Client
36
+ <br/>
37
+ <strong>config.defaultResponseMiddleware</strong> - обработчик ответа от сервера по умолчанию (см. раздел обработка ответов от сервера)
38
+ <br/>
39
+ <strong>config.defaultErrorMiddleware</strong> - обработчик ошибок по умолчанию (см. раздел обработка ошибок)
40
+
41
+ ```typescript
42
+ import { createBrowserHistory } from 'history';
43
+ import { defaultErrorMiddleware, defaultResponseMiddleware, HttpClient } from '@pushwoosh/http-client';
44
+
45
+ // создаем API для работы с навигацией
46
+ const history = createBrowserHistory();
47
+
48
+ // формируем конфигурацию Http Client
49
+ const config = {
50
+ // обязательное поле: описывает адреса для выполнения внутренних запросов HttpClient к серверу авторизации
51
+ // для более подробной инфорации смотри https://www.rfc-editor.org/rfc/rfc6749.html#section-1.1 - authorization server
40
52
  urls: {
41
- authorize: 'https://sso.pushwoosh.com/authorize', // адрес старта сеанса
42
- token: 'https://sso.pushwoosh.com/token', // адрес для получения или обновления пары токенов для авторизации в приватных API
43
- logout: 'https://sso.pushwoosh.com/logout', // адрес для завершения сеанса
53
+ // обязательное поле: адрес для получения authorization code и authorization state
54
+ // для более подробноей информации смотри https://www.rfc-editor.org/rfc/rfc6749.html#section-4.1.1
55
+ authorize: 'https://sso.pushwoosh.com/authorize',
56
+ // обязательное поле: адрес для получения access token и refresh token
57
+ token: 'https://sso.pushwoosh.com/token',
58
+ // обязательное поле: адрес для завершения сессии
59
+ logout: 'https://sso.pushwoosh.com/logout',
44
60
  },
45
- clientId: 'APP_FRONT', // уникальный идентификатор клиента (связан с доменом)
61
+ // обязательное поле: идентификатор клиента, свзязан с сервером SSO, зависит от домена на котором работает HttpClient
62
+ // для более подробной инфорации смотри https://www.rfc-editor.org/rfc/rfc6749.html#section-1.1 - client
63
+ clientId: 'APP_FRONT',
64
+ // обязательное поле: область ограничений на работу с защищенными ресурсами
65
+ // для более подробной инфорации смотри https://www.rfc-editor.org/rfc/rfc6749.html#section-1.1 - resource server
66
+ scope: 'cp-pushwoosh customer-journey',
67
+ // обязательное поле: параметры куки для сохранения authorization state и url before authorize
46
68
  cookie: {
47
- domain: '.pushwoosh.com', // на какой домен будут выписываться cookies
69
+ // обязательное поле: определяет домен на котором будут доступны куки
70
+ domain: '.pushwoosh.com',
71
+ // определяет время жизни кук
72
+ expires: 300,
73
+ // определяет путь, где будут доступны куки
74
+ path: '/',
75
+ // определяет будут ли передаваться куки только по https протоколу
76
+ secure: true,
77
+ // определяет при каких условиях куки будут отправлятся на сервер при выполнении кроссдоменных запросов
78
+ sameSite: 'none',
48
79
  },
49
- })
80
+ // обязательное поле: бызовый обработчик ответов от сервера
81
+ basicResponseMiddleware: defaultResponseMiddleware,
82
+ // обязательное поле: базовый обработчик ошибкок при выполнении запросов
83
+ basicErrorMiddleware: defaultErrorMiddleware,
84
+ };
50
85
  ```
51
86
 
52
- ### Инициализация экземпляра HttpClient
53
- Экземпляр класса HttpClient необходимо инициализировать, для получения информации аутентифицирован ли пользователь на клиенте
87
+ ### Авторизация
88
+ Этот шаг может быть пропущен, если access token получается другим способом.
89
+ <br/>
90
+ Если требуется произвести авторизацию клиента с помощью SSO, то нам нужно выполнить 2 действия:
91
+ <br/>
92
+
93
+ 1. Получить Basic Authorization путем перехода на сервер авторизации и возвращения обратно с authorization code и authorization state
94
+ ```typescript
95
+ await httpClient.login();
96
+ ```
97
+ 2. Получить Bearer Authorization путем выполнения запроса к серверу авторизации и получения access token и refresh token с помощью authorization code
98
+ ```typescript
99
+ const introspect = await httpClient.authorize(authorization);
100
+ ```
54
101
 
102
+ Полный пример выполнения авторизации клиента:
55
103
  ```typescript
56
- const introspect = await httpClient.initialize(authorizationCode, authorizationState);
104
+ // получаем authorization code и authorization state из строки браузера
105
+ const query = parse(window.location.search.slice(1));
106
+ const authorizationCode = typeof query.code === 'string' ? query.code : null;
107
+ const authorizationState = typeof query.state === 'string' ? query.state : null;
108
+ const authorization = authorizationCode && authorizationState
109
+ ? { code: authorizationCode, state: authorizationState }
110
+ : null;
111
+
112
+ // выполняем авторизацию
113
+ if (authorization) {
114
+ const introspect = await httpClient.authorize(authorization);
115
+ if (!introspect) {
116
+ await httpClient.login();
117
+ return;
118
+ }
119
+ }
57
120
  ```
58
121
 
59
- `authorizationCode` - это код авторизации переданный со стороны `сервера авторизации`
60
-
61
- `authorizationState` - это случайная строка, сгенерированная и сохраненная клиентом перед началом сеанса, возвращается вместе с `authorizationCode`
62
-
63
- `introspect` - это данные о текущем сеансе (идентификатор пользователя, идентификатор аккаунта и т.п.), которые зашиты в `access token`
64
-
65
- ### Начать сеанс
66
- Выполнить аутентификацию пользователя на клиенте
67
-
122
+ ### Выполнение запросов:
123
+ Для выполнения запросов можно использовать следующий метод:
68
124
  ```typescript
69
- await httpClient.login();
70
- ```
125
+ import { defaultErrorMiddleware } from './http-client.utilities';
71
126
 
72
- ### Завершить сеанс
73
- Завершить сеанс клиента
127
+ type Result = {
128
+ readonly data1: string;
129
+ readonly data2: number;
130
+ };
74
131
 
75
- ```typescript
76
- await httpClient.logout();
77
- ```
132
+ type Params = {
133
+ readonly param1: string;
134
+ readonly param2: number;
135
+ }
78
136
 
79
- ### Выполнение запросов
137
+ type Query = {
138
+ readonly query1: string;
139
+ readonly query2: number;
140
+ }
80
141
 
81
- #### Базовая конфигурация:
142
+ type Body = {
143
+ readonly body1: string;
144
+ readonly body2: number;
145
+ }
82
146
 
83
- Запрос:
84
- ```
85
- curl 'https://app.pushwoosh.com/entrypoint/XXXXX-XXXXX?query1=0' \
86
- -H 'accept: application/json, text/plain, */*' \
87
- -H 'content-type: application/json' \
88
- --data-raw '{"body1":true}' \
147
+ const url = '/entrypoint/:param1/:param2';
148
+ const method = Method.POST;
149
+ const options = {
150
+ // определяет заголовки, которые будут отправлены вместе с запросом
151
+ headers: {
152
+ 'Some-Header': 'Some-Value',
153
+ },
154
+ // параметры для заполнения адреса запроса
155
+ params: {
156
+ param1: 'value-param',
157
+ param2: 1,
158
+ },
159
+ // параметры запроса
160
+ query: {
161
+ query1: 'value-query',
162
+ query2: 2,
163
+ },
164
+ // тело запроса
165
+ body: {
166
+ body1: 'value-body',
167
+ body2: 3,
168
+ },
169
+ // обязательное поле: определяет требуется ли передавать данные об авторизации
170
+ withAuthorization: true,
171
+ // определяет требуется ли отправлять заголовки в кроссдоменных запросах
172
+ withCredentials: false,
173
+ // определяет какой обработчик ответа будет использован (см. разедл обработка ответа от сервера)
174
+ responseMiddleware: defaultResponseMiddleware,
175
+ // определяет какой обработчик ошибок будет использован (см. разедл обработка ошибок)
176
+ errorMiddleware: defaultErrorMiddleware,
177
+ };
178
+
179
+ const { data1, data2 } = await httpClient.request<Method.POST, Result, Params, Query, Body>(url, method, options);
89
180
  ```
90
- Можно выполнить следующей конструкцией:
181
+
182
+ Он эквивалентен следующему запросу:
91
183
  ```
92
- try {
93
- const response = httpClient.request<'POST', { param1: string }, { query1: number }, { body1: boolean }, { result1: string, result2: number, result3: boolean }>('/entrypoint/:param1', {
94
- method: 'POST',
95
- params: {
96
- param1: 'XXXXX-XXXXX',
97
- },
98
- query: {
99
- query1: 0,
100
- },
101
- body: {
102
- body1: true,
103
- },
104
- withAuthorization: false,
105
- withCredentials: false,
106
- });
107
- } catch (error: unknown) {
108
- // TODO: error capture
109
- }
184
+ curl -XPOST 'https://pushwoosh.com/entrypoint/value-param/1?query1=value-query&query2=2' -H "Some-Header: Some-Value" -H "Authorization: Bearer ..." -d '{
185
+ "body1": "value-body",
186
+ "body2": 3
187
+ }'
110
188
  ```
111
189
 
112
- `method` - тип запроса (`GET`, `POST`, `PUT`, `PATCH`, `DELETE`)
113
-
114
- `params` - параметры, которые будут подставлены в шаблон `URL`
115
-
116
- `query` - параметры, которые будут преобразованы к `Query String`
117
-
118
- `body` - параметры, которые будут преобразованы к `Request Payload` (недоступен для `GET`)
119
-
120
- `withAuthorization` - передавать заголовок `Authorization` в заголовке
121
-
122
- `withCredentials` - передавать идентификационные данные в кросс доменных запросах
123
-
124
- `response` - ответ от сервера:
190
+ Также существуют упрощенные варианты запросов:
125
191
 
192
+ ##### GET
126
193
  ```typescript
127
- type Response<R extends Result> = | ResponseFailure | ResponseSuccess<R>;
194
+ const result = httpClient.get<Result, Params, Query>(url, options);
128
195
  ```
129
196
 
130
- #### GET, POST, PUT, UPDATE, DELETE запросы
131
- Все запросы имеют упрощенную структуру с указанием типа запроса:
132
-
133
- ```
134
- curl 'https://app.pushwoosh.com/entrypoint' \
135
- -H 'accept: application/json, text/plain, */*' \
136
- -H 'authorization: Bearer SOME-ACCESS-TOKEN' \
137
- ```
138
- Можно выполнить следующей конструкцией:
197
+ ##### POST
139
198
  ```typescript
140
- try {
141
- const result = httpClient.get<never, never, { some: string }>('/entrypoint', {
142
- withAuthorization: true,
143
- responseMiddleware: (response: Response<{some: string}>): { some: string } => {
144
- // если стандартный middleware для разбора ответа от сервера не подходит
145
- // например когда ответ от сервера всегда 200, а коды ошибок зашиты в самом ответе.
146
- // {
147
- // status: 200,
148
- // message: 'Ok',
149
- // result: {
150
- // status: 200,
151
- // message: 'Ok',
152
- // response: {
153
- // some: 'some-string',
154
- // },
155
- // },
156
- // }
157
- const jsonResponse = httpClient.baseResponseMiddleware(response);
158
- if (jsonResponse.status !== 200) {
159
- // map jsonResponse error to HttpClient error and throw it.
160
- }
161
-
162
- return jsonResponse.result;
163
- },
164
- });
165
- } catch (error: unknown) {
166
- // TODO: error capture
167
- }
199
+ const result = httpClient.post<Result, Params, Query, Body>(url, options);
168
200
  ```
169
- В данном примере приходит сразу `result`, а если http запрос вернул `response.status` >= `400`, то произойдет выброс исключения.
170
-
171
- ## Обработка ошибок:
172
201
 
202
+ ##### PUT
173
203
  ```typescript
174
- import { ForbiddenError, HttpClient, NotFoundError, UnauthorizedError } from './http-client.errors';
175
-
176
- try {
177
- const result = httpClient.get<never, never, never>('/entrypoint', {
178
- withAuthorization: true,
179
- });
180
- } catch (error: unknown) {
181
- if (error instanceof UnauthorizedError) {
182
- // TODO: Если не авторизован...
183
- }
184
-
185
- if (error instanceof ForbiddenError) {
186
- // TODO: Если запрещено выполнять запрос...
187
- }
204
+ const result = httpClient.put<Result, Params, Query, Body>(url, options);
205
+ ```
188
206
 
189
- if (error instanceof NotFoundError) {
190
- // TODO: Если сервер ничего не нашел...
191
- }
207
+ ##### PATCH
208
+ ```typescript
209
+ const result = httpClient.patch<Result, Params, Query, Body>(url, options);
210
+ ```
192
211
 
193
- // TODO: error capture
194
- }
212
+ ##### DELETE
213
+ ```typescript
214
+ const result = httpClient.delete<Result, Params, Query, Body>(url, options);
195
215
  ```
196
216
 
197
- ### Родительский класс для ошибок
198
- `HttpClientError` - Класс описывает ошибку связанную с HttpClient.
217
+ ### Обработка ответов от сервера
218
+ Так как ответ от сервера не стандартизирован, то при обращении к разным эндпоинтам может потребоваться своя валидация и парсинг.
199
219
  <br/>
200
- HttpClientError класс является наследником Error.
220
+ Для этого в каждом запросе можно указать свой обработчик запроса.
201
221
  <br/>
202
- <b>Никогда не выбрасывается как исключение. От нее наследуются все остальные ошибки!</b>
203
-
204
- Каждая ошибка имеет свой класс:
205
-
206
- #### Ошибки связанные с самим модулем:
207
- `InternalError` - Класс описывающий внутреннюю ошибку HttpClient
208
-
209
- #### Ошибки связанные с ответами от сервера:
210
- `BadRequestError` - Класс описывающий ошибку "Плохой запрос"
211
-
212
- `UnauthorizedError` - Класс описывающий ошибку "Не авторизовано"
213
-
214
- `ForbiddenError` - Класс описывающий ошибку "Запрещено"
215
-
216
- `NotFoundError` - Класс описывающий ошибку "Не найден"
217
-
218
- `MethodNotAllowedError` - Класс описывающий ошибку "Метод не доступен"
219
-
220
- `UnsupportedMediaTypeError` - Класс описывающий ошибку "Медиа формат не поддерживается сервером"
222
+ Например, если ответ от сервера всегда 200, а внутри него лежит JSON с данными, то можно поступить следующим образом:
221
223
 
222
- `UnprocessableEntityError` - Класс описывающий ошибку "Сервер не может обработать запрос"
223
-
224
- #### Ошибки связанные с работой сервера:
225
- `InternalServerError` - Класс описывающий ошибку "Внутренняя ошибка сервера"
224
+ ```typescript
225
+ type Result = {
226
+ readonly data1: string;
227
+ readonly data2: number;
228
+ };
229
+
230
+ type JSONResponse = {
231
+ readonly result: Result;
232
+ readonly code: number;
233
+ readonly message: string;
234
+ };
235
+
236
+ const { data1, data2 } = await httpClient.post<Result, never, never, never>('/entrypoint', {
237
+ withAuthorization: true,
238
+ responseMiddleware: (response) => {
239
+ const jsonResponse = defaultResponseMiddleware<JSONResponse>(response);
240
+ if (jsonResponse.code !== 200) {
241
+ switch (jsonResponse.code) {
242
+ case 210:
243
+ case 401:
244
+ throw new UnauthorizedError(jsonResponse.message, response.details);
245
+ default:
246
+ throw new UntiledError(jsonResponse.message, jsonResponse.code, response.details);
247
+ }
248
+ }
226
249
 
227
- `BadGatewayError` - Класс описывающий ошибку "Плохой шлюз"
250
+ return jsonResponse.result;
251
+ },
252
+ });
253
+ ```
228
254
 
229
- `ServiceUnavailableError` - Класс описывающий ошибку "Сервис недоступен"
255
+ При обработке ответа от сервера очень важно корректно указывать ошибки, так как:
256
+ 1. Если при обработке ответа от сервера будет кинуто исключение UnauthorizedError, то HttpClient попробует обновить access token м выполнить запрос повторно
257
+ 2. Настраивается глобальный обработчик ошибок, который при возникновении тех или иных ситуаций их обрабатывает
230
258
 
231
- `GatewayTimeoutError` - Класс описывающий ошибку "Вышло время ожидания ответа"
259
+ ### Обработка ошибок
260
+ Если в момент выполнения запроса происходит ошибка, то в первую очередь ее пробует обработать basicErrorMiddleware (если для конкретного запроса он не заменен на свой обработчик ошибок)
261
+ ```typescript
262
+ import { ForbiddenError, HttpClientError, UnauthorizedError } from './http-client.errors';
263
+
264
+ const httpClient = new HttpClient(history, {
265
+ basicErrorMiddleware: async (error: unknown): Promise<never> => {
266
+ // если клиент не авторизован и пытается выполнить запрос к приватным данным, то пробуем его авторизовать
267
+ if (error instanceof UnauthorizedError) {
268
+ await httpClient.logout();
269
+ await httpClient.login();
270
+ }
271
+
272
+ throw error;
273
+ },
274
+ });
275
+ ```
232
276
 
233
- #### Остальные:
234
- `UnknownServerError` - Класс описывает ошибку связанную с запросами к серверу, но для которой не подходит ни один из вариантов выше.
277
+ Если ошибка попадает под список обрабатываемых, то Http Client ее обработает сам, если нет, она продолжит всплытие и ее можно будет обработать на месте.
278
+
279
+ #### Ошибки:
280
+
281
+ Все ошибки наследуются от родительского класса HttpClientError. Существуют следующие ошибки:
282
+
283
+ 1. HttpClientError:
284
+ 1. LogicError - ошибка в логике самого Http Client
285
+ 2. ClassifiedError - категоризированная ошибка, никогда не используется как отдельный экземпляр, от нее наследуются все остальные ошибки.
286
+ 1. UntiledError - ошибка не попавшая ни под одну из категорий ниже
287
+ 2. BadRequestError - некорректный запрос (сервер не может обработать запрос из-за некорректного синтаксиса)
288
+ 3. UnauthorizedError - не авторизован / некорректная авторизация
289
+ 4. ForbiddenError - запрещено для выполнения (permissions)
290
+ 5. NotFoundError - не найдено
291
+ 6. MethodNotAllowedError - не доступно для выполнения (restrictions)
292
+ 7. PayloadTooLargeError - слишком большой запрос
293
+ 8. UnsupportedMediaTypeError - неподдерживаемое тип медиа
294
+ 9. UnprocessableEntityError - сервер понял запрос, но не смог его обработать из-за логических ошибок
295
+ 10. TooManyRequestsError - слишком много запросов
296
+ 11. InternalServerError
297
+ 12. NotImplementedError
298
+ 13. BadGatewayError
299
+ 14. ServiceUnavailableError
300
+ 15. GatewayTimeoutError
301
+
302
+ Нужно понимать, что API поддерживают не все из приведенных выше ошибок или наоборот ошибок может не хватать
303
+ <br/>
304
+ Тут нужно придерживаться именно логики вызова этих ошибок и приводить разношерстный API к единому виду обработки
@@ -0,0 +1,24 @@
1
+ module.exports = (api) => {
2
+ api.cache.using(() => process.env.NODE_ENV);
3
+
4
+ return {
5
+ presets: [
6
+ [
7
+ '@babel/preset-env',
8
+ {
9
+ modules: false,
10
+ corejs: 3,
11
+ useBuiltIns: 'entry',
12
+ },
13
+ ],
14
+ ],
15
+ plugins: [
16
+ [
17
+ '@babel/plugin-transform-runtime',
18
+ {
19
+ corejs: 3,
20
+ },
21
+ ],
22
+ ],
23
+ };
24
+ };
package/jest.config.js ADDED
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ preset: 'ts-jest',
3
+ };
package/package.json CHANGED
@@ -1,74 +1,68 @@
1
1
  {
2
2
  "name": "@pushwoosh/http-client",
3
- "version": "1.4.2",
4
- "license": "MIT",
5
3
  "main": "./dist/index.js",
6
4
  "types": "./dist/index.d.ts",
7
- "files": [
8
- "dist"
9
- ],
10
5
  "scripts": {
11
6
  "start": "npm run development",
12
7
  "build": "npm run production",
13
8
  "development": "cross-env NODE_ENV=development webpack-dev-server --config webpack.development.config.js",
14
9
  "production": "cross-env NODE_ENV=production webpack --config webpack.production.config.js",
15
- "check": "npm run check:lint && npm run check:types && npm run check:tests",
16
- "check:lint": "echo \"Run check:lint\" && eslint .",
10
+ "check": "npm run check:lint && npm run check:tests && npm run check:types",
11
+ "check:lint": "echo \"Run check:lint\" && eslint",
17
12
  "check:tests": "echo \"Run check:tests\" && jest --passWithNoTests",
18
13
  "check:types": "echo \"Run check:types\" && tsc --project tsconfig.json --noEmit"
19
14
  },
20
15
  "pre-commit": "check",
21
16
  "dependencies": {
22
- "@babel/runtime-corejs3": "^7.16.5",
23
- "core-js": "^3.20.0",
17
+ "@babel/runtime-corejs3": "^7.17.2",
18
+ "axios": "^0.25.0",
19
+ "core-js": "^3.21.0",
24
20
  "js-cookie": "^3.0.1",
25
21
  "jwt-decode": "^3.1.2",
26
22
  "path-to-regexp": "^6.2.0",
27
23
  "qs": "^6.10.3"
28
24
  },
29
25
  "devDependencies": {
30
- "@babel/core": "^7.16.5",
31
- "@babel/plugin-transform-runtime": "^7.16.5",
32
- "@babel/preset-env": "^7.16.5",
33
- "@types/jest": "^26.0.24",
26
+ "@babel/core": "^7.17.2",
27
+ "@babel/plugin-transform-runtime": "^7.17.0",
28
+ "@babel/preset-env": "^7.16.11",
29
+ "@types/jest": "^27.4.0",
34
30
  "@types/webpack-env": "^1.16.3",
35
- "@typescript-eslint/eslint-plugin": "^4.33.0",
36
- "@typescript-eslint/parser": "^4.33.0",
31
+ "@typescript-eslint/eslint-plugin": "^5.11.0",
32
+ "@typescript-eslint/parser": "^5.11.0",
37
33
  "babel-loader": "^8.2.3",
38
- "clean-webpack-plugin": "^3.0.0",
34
+ "clean-webpack-plugin": "^4.0.0",
39
35
  "cross-env": "^7.0.3",
40
- "dotenv": "^10.0.0",
41
- "eslint": "^7.32.0",
42
- "eslint-config-airbnb": "^18.2.1",
43
- "eslint-config-airbnb-typescript": "^14.0.2",
44
- "eslint-import-resolver-alias": "^1.1.2",
45
- "eslint-plugin-compat": "^4.0.0",
46
- "eslint-plugin-import": "^2.25.3",
36
+ "dotenv": "^16.0.0",
37
+ "eslint": "^8.8.0",
38
+ "eslint-config-airbnb": "^19.0.4",
39
+ "eslint-config-airbnb-typescript": "^16.1.0",
40
+ "eslint-plugin-compat": "^4.0.2",
41
+ "eslint-plugin-import": "^2.25.4",
47
42
  "eslint-plugin-jsx-a11y": "^6.5.1",
48
- "eslint-plugin-react": "^7.27.1",
43
+ "eslint-plugin-react": "^7.28.0",
49
44
  "eslint-plugin-react-hooks": "^4.3.0",
50
- "jest": "^26.6.3",
45
+ "jest": "^27.5.1",
51
46
  "pre-commit": "^1.2.2",
52
- "terser-webpack-plugin": "^4.2.3",
53
- "ts-jest": "^26.5.6",
54
- "ts-loader": "^8.3.0",
55
- "typescript": "^4.5.4",
56
- "unused-files-webpack-plugin": "^3.4.0",
57
- "webpack": "^4.46.0",
58
- "webpack-cli": "^3.3.12",
59
- "webpack-dev-server": "^3.11.3",
47
+ "terser-webpack-plugin": "^5.3.1",
48
+ "ts-jest": "^27.1.3",
49
+ "ts-loader": "^9.2.6",
50
+ "typescript": "^4.5.5",
51
+ "webpack": "^5.68.0",
52
+ "webpack-cli": "^4.9.2",
53
+ "webpack-dev-server": "^4.7.4",
60
54
  "webpack-merge": "^5.8.0"
61
55
  },
62
56
  "peerDependencies": {
63
- "@types/history": "^4.7.10",
57
+ "@types/history": "^4.7.11",
64
58
  "@types/js-cookie": "^3.0.1",
65
59
  "@types/qs": "^6.9.7",
66
- "axios": "^0.24.0",
67
60
  "history": "^4.10.1",
68
61
  "tslib": "^2.3.1"
69
62
  },
70
63
  "engines": {
71
- "node": ">= 16",
72
- "npm": ">= 7"
73
- }
64
+ "node": ">=16.0.0",
65
+ "npm": ">=7.0.0"
66
+ },
67
+ "version": "1.5.0"
74
68
  }