@pushwoosh/http-client 2.12.0 → 2.13.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.
@@ -0,0 +1,524 @@
1
+ import Cookies from 'js-cookie';
2
+ import { jwtDecode } from 'jwt-decode';
3
+ import { LogicError, UnauthorizedError, UnprocessableEntityError } from './http-client.errors';
4
+ import { updatePath } from './http-client.helpers';
5
+ import { Method } from './http-client.types';
6
+ export class HttpClient {
7
+ /**
8
+ * Cookie name used to save the authorization state
9
+ * For more information see https://www.rfc-editor.org/rfc/rfc6749.html#section-4.1.1
10
+ */
11
+ static AUTHORIZATION_STATE_COOKIE_NAME = '__PW_AUTHORIZATION_STATE';
12
+ static AUTHORIZATION_STATE_SESSION_KEY = '__PW_SESSION_AUTHORIZATION_STATE';
13
+ static URL_BEFORE_AUTHORIZATION_SESSION_KEY = '__PW_SESSION_URL_BEFORE_AUTHORIZATION';
14
+ /**
15
+ * Cookie name used to save the page address before authorization
16
+ */
17
+ static URL_BEFORE_AUTHORIZATION_COOKIE_NAME = '__PW_URL_BEFORE_AUTHORIZATION';
18
+ /**
19
+ * Base URL for requests
20
+ */
21
+ baseURL;
22
+ /**
23
+ * API for working with navigation
24
+ */
25
+ history;
26
+ /**
27
+ * Http Client configuration
28
+ */
29
+ config;
30
+ /**
31
+ * Access token used to access protected resources
32
+ * For more information see https://www.rfc-editor.org/rfc/rfc6749.html#section-1.4
33
+ */
34
+ accessToken;
35
+ /**
36
+ * Refresh token used to refresh the access token.
37
+ * For more information see https://www.rfc-editor.org/rfc/rfc6749.html#section-1.5
38
+ */
39
+ refreshToken;
40
+ /**
41
+ * Is token refresh in progress
42
+ */
43
+ isRefreshing;
44
+ /**
45
+ * Email or username of the logged in user.
46
+ * Taken from jwt (claims).
47
+ */
48
+ userName;
49
+ /**
50
+ * Account ID under which the user is logged in.
51
+ * Taken from jwt (claims).
52
+ */
53
+ accountID;
54
+ /**
55
+ * Create an instance of the class
56
+ *
57
+ * @param history - API for working with navigation
58
+ * @param config - Http Client configuration
59
+ */
60
+ constructor(history, config) {
61
+ const {
62
+ baseURL
63
+ } = config;
64
+ this.baseURL = baseURL;
65
+ this.history = history;
66
+ this.config = config;
67
+ this.accessToken = null;
68
+ this.refreshToken = null;
69
+ this.isRefreshing = false;
70
+ this.userName = '';
71
+ this.accountID = '';
72
+ }
73
+ /**
74
+ * Check for authorization
75
+ *
76
+ * @param details - request details to protected resources
77
+ */
78
+ checkAuthorization = async details => {
79
+ // if the token refresh process is in progress, wait 100 ms and try to check the authorization again
80
+ if (this.isRefreshing) {
81
+ await new Promise(resolve => {
82
+ setTimeout(resolve, 100);
83
+ });
84
+ await this.checkAuthorization(details);
85
+ return;
86
+ }
87
+ // if there is no access token, then the client is definitely not authorized
88
+ if (!this.accessToken) {
89
+ throw new UnauthorizedError('Unauthorized!', details);
90
+ }
91
+ // if the token lifetime has expired, you need to try to update it using the refresh token
92
+ const currentTime = new Date().getTime() / 1000;
93
+ const introspect = jwtDecode(this.accessToken);
94
+ const isTokenExpired = introspect.expired_at < currentTime;
95
+ if (isTokenExpired) {
96
+ await this.updateTokenByRefreshToken(details);
97
+ await this.checkAuthorization(details);
98
+ }
99
+ };
100
+ /**
101
+ * Update access token
102
+ * For more information see:
103
+ * https://www.rfc-editor.org/rfc/rfc6749.html#section-4.1.3
104
+ * https://www.rfc-editor.org/rfc/rfc6749.html#section-6
105
+ *
106
+ * @param query - query parameters involved in the update
107
+ */
108
+ updateToken = async query => {
109
+ // client identification is done using the header
110
+ const clientIdInBase64 = btoa(`${this.config.clientId}:`);
111
+ const authorizationHeader = `Basic ${clientIdInBase64}`;
112
+ try {
113
+ this.isRefreshing = true;
114
+ const tokens = await this.post(this.config.urls.token, {
115
+ headers: {
116
+ Authorization: authorizationHeader
117
+ },
118
+ query,
119
+ withAuthorization: false,
120
+ withCredentials: true
121
+ });
122
+ this.accessToken = tokens.access_token;
123
+ this.refreshToken = tokens.refresh_token;
124
+ this.isRefreshing = false;
125
+ } catch (error) {
126
+ this.accessToken = null;
127
+ this.refreshToken = null;
128
+ this.isRefreshing = false;
129
+ throw error;
130
+ }
131
+ };
132
+ /**
133
+ * Update access token using authorization code
134
+ * For more information see: https://www.rfc-editor.org/rfc/rfc6749.html#section-4.1.3
135
+ *
136
+ * @param authorizationCode - authorization code received from the authorization server
137
+ */
138
+ updateTokenByAuthorizationCode = async authorizationCode => {
139
+ await this.updateToken({
140
+ grant_type: 'authorization_code',
141
+ code: authorizationCode,
142
+ redirect_uri: `${window.location.origin}${window.location.pathname}`
143
+ });
144
+ };
145
+ /**
146
+ * Update access token using refresh token
147
+ * For more information see: https://www.rfc-editor.org/rfc/rfc6749.html#section-6
148
+ *
149
+ * @param details - request details to protected resources
150
+ */
151
+ updateTokenByRefreshToken = async details => {
152
+ if (!this.refreshToken) {
153
+ this.accessToken = null;
154
+ throw new UnauthorizedError('Unauthorized!', details);
155
+ }
156
+ await this.updateToken({
157
+ grant_type: 'refresh_token',
158
+ refresh_token: this.refreshToken,
159
+ username: this.userName,
160
+ account_id: this.accountID
161
+ });
162
+ };
163
+ /**
164
+ * Process response from fetch request
165
+ *
166
+ * @param response - fetch response
167
+ * @param details - request details
168
+ * @param responseMiddleware - middleware to process response
169
+ */
170
+ processFetchResponse = async (response, details, responseMiddleware) => {
171
+ let data;
172
+ if (response.headers.get('Content-Type')?.includes('application/json')) {
173
+ data = await response.json().catch(() => ({}));
174
+ } else {
175
+ data = await response.text().then(str => {
176
+ try {
177
+ return JSON.parse(str);
178
+ } catch {
179
+ return str;
180
+ }
181
+ }).catch(() => '');
182
+ }
183
+ return responseMiddleware({
184
+ result: data,
185
+ status: response.status,
186
+ message: response.statusText,
187
+ details
188
+ });
189
+ };
190
+ /**
191
+ * Build fetch request URL, headers, and options from the given parameters.
192
+ * Shared by both `request()` and `stream()`.
193
+ */
194
+ buildFetchRequest = async (url, method, options) => {
195
+ // Initialize fetch request
196
+ let fetchUrl = url;
197
+ // Apply base URL if present
198
+ if (this.baseURL && !fetchUrl.startsWith('http')) {
199
+ fetchUrl = `${this.baseURL}${fetchUrl.startsWith('/') ? '' : '/'}${fetchUrl}`;
200
+ }
201
+ // Apply URL parameters
202
+ if (options.params) {
203
+ fetchUrl = updatePath(fetchUrl, options.params);
204
+ }
205
+ // Apply query parameters
206
+ if (options.query) {
207
+ const queryParams = options.query;
208
+ let queryString;
209
+ if (typeof queryParams === 'string') {
210
+ queryString = queryParams;
211
+ } else if (queryParams instanceof URLSearchParams) {
212
+ queryString = queryParams.toString();
213
+ } else {
214
+ queryString = new URLSearchParams(queryParams).toString();
215
+ }
216
+ fetchUrl = `${fetchUrl}${fetchUrl.includes('?') ? '&' : '?'}${queryString}`;
217
+ }
218
+ // Initialize request headers
219
+ const headers = options.headers || {};
220
+ const headersInit = {};
221
+ // Convert headers object to proper format
222
+ Object.entries(headers).forEach(([key, value]) => {
223
+ headersInit[key] = String(value);
224
+ });
225
+ // Add authorization header if needed
226
+ if (options.withAuthorization) {
227
+ await this.checkAuthorization(null);
228
+ headersInit.Authorization = `Bearer ${this.accessToken}`;
229
+ }
230
+ // Initialize request options
231
+ const fetchOptions = {
232
+ method,
233
+ headers: headersInit,
234
+ credentials: options.withCredentials ? 'include' : 'same-origin',
235
+ signal: options.signal
236
+ };
237
+ // Add body if needed
238
+ if (options.body !== undefined) {
239
+ if (options.body instanceof FormData) {
240
+ fetchOptions.body = options.body;
241
+ } else {
242
+ headersInit['Content-Type'] = 'application/json';
243
+ if (method !== Method.GET) {
244
+ fetchOptions.body = JSON.stringify(options.body);
245
+ }
246
+ }
247
+ }
248
+ return {
249
+ fetchUrl,
250
+ fetchOptions,
251
+ headersInit
252
+ };
253
+ };
254
+ /**
255
+ * Make a request
256
+ *
257
+ * @param url - request address
258
+ * @param method - request method
259
+ * @param options - request configuration
260
+ */
261
+ request = async (url, method, options) => {
262
+ const {
263
+ basicErrorMiddleware,
264
+ basicResponseMiddleware
265
+ } = this.config;
266
+ const {
267
+ errorMiddleware = basicErrorMiddleware,
268
+ responseMiddleware = basicResponseMiddleware
269
+ } = options;
270
+ // form request details
271
+ const details = {
272
+ url,
273
+ method,
274
+ headers: options.headers,
275
+ params: options.params,
276
+ query: options.query,
277
+ body: options.body,
278
+ withCredentials: options.withCredentials,
279
+ withAuthorization: options.withAuthorization
280
+ };
281
+ // the cast is needed only because RequestOptions is a conditional type over
282
+ // generics that are still unresolved here
283
+ const {
284
+ fetchUrl,
285
+ fetchOptions,
286
+ headersInit
287
+ } = await this.buildFetchRequest(url, method, options);
288
+ // the request can be made twice if an UnauthorizedError occurred,
289
+ // to have the opportunity to automatically update the access token using the refresh token
290
+ try {
291
+ const response = await fetch(fetchUrl, fetchOptions);
292
+ return await this.processFetchResponse(response, details, responseMiddleware);
293
+ } catch (firstError) {
294
+ // if the error that occurred during the first request is not Unauthorized, then pass it further
295
+ if (!(firstError instanceof UnauthorizedError)) {
296
+ await errorMiddleware(firstError);
297
+ // if for some reason an exception is not thrown in errorMiddleware, we do it for it
298
+ throw firstError;
299
+ }
300
+ // second attempt to make the request, but now with token update
301
+ try {
302
+ if (options.withAuthorization) {
303
+ await this.updateTokenByRefreshToken(details);
304
+ await this.checkAuthorization(details);
305
+ headersInit.Authorization = `Bearer ${this.accessToken}`;
306
+ }
307
+ const response = await fetch(fetchUrl, fetchOptions);
308
+ return await this.processFetchResponse(response, details, responseMiddleware);
309
+ } catch (secondError) {
310
+ await errorMiddleware(secondError);
311
+ // if for some reason an exception is not thrown in errorMiddleware, we do it for it
312
+ throw secondError;
313
+ }
314
+ }
315
+ };
316
+ /**
317
+ * Make a streaming request that returns the raw Response.
318
+ * Use this for NDJSON, SSE, or other streaming protocols where
319
+ * you need access to response.body (ReadableStream).
320
+ *
321
+ * @param url - request address
322
+ * @param method - request method
323
+ * @param options - stream request configuration
324
+ */
325
+ stream = async (url, method, options) => {
326
+ const {
327
+ basicErrorMiddleware
328
+ } = this.config;
329
+ const {
330
+ errorMiddleware = basicErrorMiddleware
331
+ } = options;
332
+ const {
333
+ fetchUrl,
334
+ fetchOptions,
335
+ headersInit
336
+ } = await this.buildFetchRequest(url, method, options);
337
+ const details = {
338
+ url,
339
+ method,
340
+ params: options.params,
341
+ query: options.query,
342
+ body: options.body,
343
+ withCredentials: options.withCredentials,
344
+ withAuthorization: options.withAuthorization
345
+ };
346
+ const {
347
+ basicResponseMiddleware
348
+ } = this.config;
349
+ try {
350
+ const response = await fetch(fetchUrl, fetchOptions);
351
+ if (!response.ok) {
352
+ // Delegate to processFetchResponse to get proper typed errors (BadRequestError, etc.)
353
+ await this.processFetchResponse(response, details, basicResponseMiddleware);
354
+ }
355
+ return response;
356
+ } catch (firstError) {
357
+ if (!(firstError instanceof UnauthorizedError)) {
358
+ await errorMiddleware(firstError);
359
+ throw firstError;
360
+ }
361
+ // Retry with token refresh
362
+ try {
363
+ if (options.withAuthorization) {
364
+ await this.updateTokenByRefreshToken(details);
365
+ await this.checkAuthorization(details);
366
+ headersInit.Authorization = `Bearer ${this.accessToken}`;
367
+ }
368
+ const response = await fetch(fetchUrl, fetchOptions);
369
+ if (!response.ok) {
370
+ await this.processFetchResponse(response, details, basicResponseMiddleware);
371
+ }
372
+ return response;
373
+ } catch (secondError) {
374
+ await errorMiddleware(secondError);
375
+ throw secondError;
376
+ }
377
+ }
378
+ };
379
+ /**
380
+ * Perform GET request
381
+ *
382
+ * @param url - request address
383
+ * @param options - GET request configuration
384
+ */
385
+ get = (url, options) => this.request(url, Method.GET, options);
386
+ /**
387
+ * Perform POST request
388
+ *
389
+ * @param url - request address
390
+ * @param options - POST request configuration
391
+ */
392
+ post = (url, options) => this.request(url, Method.POST, options);
393
+ /**
394
+ * Perform PUT request
395
+ *
396
+ * @param url - request address
397
+ * @param options - PUT request configuration
398
+ */
399
+ put = (url, options) => this.request(url, Method.PUT, options);
400
+ /**
401
+ * Perform PATCH request
402
+ *
403
+ * @param url - request address
404
+ * @param options - PATCH request configuration
405
+ */
406
+ patch = (url, options) => this.request(url, Method.PATCH, options);
407
+ /**
408
+ * Perform DELETE request
409
+ *
410
+ * @param url - request address
411
+ * @param options - DELETE request configuration
412
+ */
413
+ delete = (url, options) => this.request(url, Method.DELETE, options);
414
+ /**
415
+ * Address to return to once authorization completes
416
+ */
417
+ static resolveUrlBeforeAuthorization() {
418
+ const stored = sessionStorage.getItem(HttpClient.URL_BEFORE_AUTHORIZATION_SESSION_KEY);
419
+ // SSO can bounce the browser back to `origin + pathname` to re-issue /authorize, and by then
420
+ // the query string is already gone: reuse the stored address, but only for that same page
421
+ if (stored && HttpClient.isCurrentDocument(stored)) {
422
+ return stored;
423
+ }
424
+ return window.location.href;
425
+ }
426
+ /**
427
+ * Does the URL address the page the browser is on right now, query and hash aside
428
+ */
429
+ static isCurrentDocument(url) {
430
+ try {
431
+ const parsed = new URL(url);
432
+ return parsed.origin === window.location.origin && parsed.pathname === window.location.pathname;
433
+ } catch {
434
+ return false;
435
+ }
436
+ }
437
+ /**
438
+ * Perform the first step of client authorization
439
+ * For more information see https://www.rfc-editor.org/rfc/rfc6749.html#section-4.1.1
440
+ */
441
+ login = async () => {
442
+ const newAuthorizationState = Math.random().toString().slice(2, 12);
443
+ // Store in sessionStorage (per-tab)
444
+ sessionStorage.setItem(HttpClient.AUTHORIZATION_STATE_SESSION_KEY, newAuthorizationState);
445
+ const urlBeforeAuthorization = HttpClient.resolveUrlBeforeAuthorization();
446
+ sessionStorage.setItem(HttpClient.URL_BEFORE_AUTHORIZATION_SESSION_KEY, urlBeforeAuthorization);
447
+ // Also store in cookie as fallback for cross-domain scenarios
448
+ Cookies.set(HttpClient.AUTHORIZATION_STATE_COOKIE_NAME, newAuthorizationState);
449
+ // URL in cookie - it gets overwritten by other tabs!!!
450
+ Cookies.set(HttpClient.URL_BEFORE_AUTHORIZATION_COOKIE_NAME, urlBeforeAuthorization);
451
+ const searchParams = new URLSearchParams({
452
+ response_type: 'code',
453
+ client_id: this.config.clientId,
454
+ redirect_uri: `${window.location.origin}${window.location.pathname}`,
455
+ state: newAuthorizationState
456
+ });
457
+ window.location.href = `${this.config.urls.authorize}?${searchParams.toString()}`;
458
+ };
459
+ /**
460
+ * Perform the second step of client authorization
461
+ * For more information see https://www.rfc-editor.org/rfc/rfc6749.html#section-4.1.3
462
+ *
463
+ * @param authorization - client authorization data on the server
464
+ */
465
+ authorize = async authorization => {
466
+ // Try sessionStorage first (per-tab), then fallback to cookie
467
+ const storedAuthorizationState = sessionStorage.getItem(HttpClient.AUTHORIZATION_STATE_SESSION_KEY) || Cookies.get(HttpClient.AUTHORIZATION_STATE_COOKIE_NAME);
468
+ // Read from sessionStorage first (per-tab), then cookie
469
+ const storedAuthorizationUrl = sessionStorage.getItem(HttpClient.URL_BEFORE_AUTHORIZATION_SESSION_KEY) || Cookies.get(HttpClient.URL_BEFORE_AUTHORIZATION_COOKIE_NAME);
470
+ // Clean up
471
+ sessionStorage.removeItem(HttpClient.AUTHORIZATION_STATE_SESSION_KEY);
472
+ sessionStorage.removeItem(HttpClient.URL_BEFORE_AUTHORIZATION_SESSION_KEY);
473
+ Cookies.remove(HttpClient.AUTHORIZATION_STATE_COOKIE_NAME);
474
+ Cookies.remove(HttpClient.URL_BEFORE_AUTHORIZATION_COOKIE_NAME);
475
+ if (storedAuthorizationUrl) {
476
+ const url = new URL(storedAuthorizationUrl);
477
+ this.history.replace({
478
+ pathname: url.pathname,
479
+ search: url.search,
480
+ hash: url.hash
481
+ });
482
+ }
483
+ if (storedAuthorizationState !== authorization.state) {
484
+ throw new UnprocessableEntityError('Stored authorization state and received authorization state are not equal!');
485
+ }
486
+ await this.updateTokenByAuthorizationCode(authorization.code);
487
+ if (!this.accessToken) {
488
+ throw new LogicError('Access token is null after tokens update!');
489
+ }
490
+ const introspect = jwtDecode(this.accessToken);
491
+ this.userName = introspect.username;
492
+ this.accountID = introspect.account_id.toString();
493
+ return introspect;
494
+ };
495
+ /**
496
+ * End the session
497
+ */
498
+ logout = async () => {
499
+ this.accessToken = null;
500
+ this.refreshToken = null;
501
+ await this.get(this.config.urls.logout, {
502
+ withAuthorization: false,
503
+ withCredentials: true
504
+ });
505
+ };
506
+ /**
507
+ * Get access token
508
+ */
509
+ getAccessToken = async () => {
510
+ await this.checkAuthorization(null);
511
+ if (!this.accessToken) {
512
+ throw new LogicError('Access token is null after authorization check!');
513
+ }
514
+ return this.accessToken;
515
+ };
516
+ /**
517
+ * Manually set the access token
518
+ *
519
+ * @param accessToken - access token
520
+ */
521
+ setAccessToken = accessToken => {
522
+ this.accessToken = accessToken;
523
+ };
524
+ }
@@ -96,4 +96,3 @@ export type StreamOptions = FetchRequestOptions & {
96
96
  readonly errorMiddleware?: (error: unknown) => Promise<never> | never;
97
97
  };
98
98
  export {};
99
- //# sourceMappingURL=http-client.types.d.ts.map
@@ -0,0 +1,8 @@
1
+ export var Method;
2
+ (function (Method) {
3
+ Method["GET"] = "GET";
4
+ Method["POST"] = "POST";
5
+ Method["PUT"] = "PUT";
6
+ Method["PATCH"] = "PATCH";
7
+ Method["DELETE"] = "DELETE";
8
+ })(Method || (Method = {}));
@@ -17,4 +17,3 @@ export declare function defaultResponseMiddleware<R extends Result>(response: Re
17
17
  * @param error - error.
18
18
  */
19
19
  export declare function defaultErrorMiddleware(error: unknown): never;
20
- //# sourceMappingURL=http-client.utilities.d.ts.map
@@ -0,0 +1,63 @@
1
+ import { BadGatewayError, BadRequestError, ForbiddenError, GatewayTimeoutError, InternalServerError, MethodNotAllowedError, NotFoundError, NotImplementedError, PayloadTooLargeError, ServiceUnavailableError, TooManyRequestsError, UnauthorizedError, UnprocessableEntityError, UnsupportedMediaTypeError, UntiledError } from './http-client.errors';
2
+ /**
3
+ * Check if the request was successful.
4
+ *
5
+ * @param response - response from the server.
6
+ */
7
+ export function checkIsResponseSuccess(response) {
8
+ return response.status >= 200 && response.status < 300;
9
+ }
10
+ /**
11
+ * Default server response handler.
12
+ *
13
+ * @param response - response from the server.
14
+ */
15
+ export function defaultResponseMiddleware(response) {
16
+ if (checkIsResponseSuccess(response)) {
17
+ return response.result;
18
+ }
19
+ // The response may contain an empty string as message, for example from nginx.
20
+ // In errors we expect undefined as an empty value to replace it with status.
21
+ // Therefore, we leave undefined as the last value in the logical operator when response.message is empty.
22
+ const message = response.result?.message || response.message || undefined;
23
+ switch (response.status) {
24
+ case 400:
25
+ throw new BadRequestError(message, response.details);
26
+ case 401:
27
+ throw new UnauthorizedError(message, response.details);
28
+ case 403:
29
+ throw new ForbiddenError(message, response.details);
30
+ case 404:
31
+ throw new NotFoundError(message, response.details);
32
+ case 405:
33
+ throw new MethodNotAllowedError(message, response.details);
34
+ case 413:
35
+ throw new PayloadTooLargeError(message, response.details);
36
+ case 415:
37
+ throw new UnsupportedMediaTypeError(message, response.details);
38
+ case 422:
39
+ throw new UnprocessableEntityError(message, response.details);
40
+ case 429:
41
+ throw new TooManyRequestsError(message, response.details);
42
+ case 500:
43
+ throw new InternalServerError(message, response.details);
44
+ case 501:
45
+ throw new NotImplementedError(message, response.details);
46
+ case 502:
47
+ throw new BadGatewayError(message, response.details);
48
+ case 503:
49
+ throw new ServiceUnavailableError(message, response.details);
50
+ case 504:
51
+ throw new GatewayTimeoutError(message, response.details);
52
+ default:
53
+ throw new UntiledError(message || 'Untiled Error!', response.status, response.details);
54
+ }
55
+ }
56
+ /**
57
+ * Default error handler.
58
+ *
59
+ * @param error - error.
60
+ */
61
+ export function defaultErrorMiddleware(error) {
62
+ throw error;
63
+ }
@@ -2,4 +2,3 @@ export * from './http-client.errors';
2
2
  export * from './http-client.main';
3
3
  export * from './http-client.types';
4
4
  export * from './http-client.utilities';
5
- //# sourceMappingURL=index.d.ts.map
package/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export * from './http-client.errors';
2
+ export * from './http-client.main';
3
+ export * from './http-client.types';
4
+ export * from './http-client.utilities';
package/package.json CHANGED
@@ -1,24 +1,24 @@
1
1
  {
2
2
  "name": "@pushwoosh/http-client",
3
- "version": "2.12.0",
3
+ "version": "2.13.1",
4
4
  "description": "HTTP client with OAuth2 for Pushwoosh micro-frontends",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://gitlab.corp.pushwoosh.com/frontend/frontend-monorepo.git",
8
8
  "directory": "packages/http-client"
9
9
  },
10
- "main": "./dist/index.mjs",
11
- "module": "./dist/index.mjs",
12
- "types": "./dist/index.d.ts",
10
+ "main": "index.js",
11
+ "module": "index.js",
12
+ "types": "index.d.ts",
13
+ "sideEffects": false,
13
14
  "publishConfig": {
14
- "access": "public"
15
+ "access": "public",
16
+ "directory": "dist"
15
17
  },
16
- "files": [
17
- "dist"
18
- ],
19
18
  "pushwoosh": {
20
19
  "cdn": {
21
20
  "path": "http-client",
21
+ "dir": "cdn-dist",
22
22
  "importMap": [
23
23
  "@frontend/http-client",
24
24
  "@pushwoosh/http-client"
@@ -31,7 +31,7 @@
31
31
  "path-to-regexp": "^6.2.0"
32
32
  },
33
33
  "devDependencies": {
34
- "@pushwoosh/frontend-builder-engine": "^4.0.0",
34
+ "@pushwoosh/frontend-builder-engine": "^5.5.0",
35
35
  "@types/history": "^4.7.11",
36
36
  "@types/js-cookie": "^3.0.1",
37
37
  "typescript": "^6.0.3"
@@ -40,13 +40,11 @@
40
40
  "node": ">= 24"
41
41
  },
42
42
  "scripts": {
43
- "clean": "rm -rf dist",
44
- "build": "pnpm run clean && pnpm run build:types && `pushwoosh-engine app:command:build`",
45
- "build:types": "tsc --project tsconfig.json",
43
+ "build": "pushwoosh-engine lib:build && `pushwoosh-engine app:command:build`",
46
44
  "analyze": "`pushwoosh-engine app:command:analyze`",
47
45
  "check": "pnpm run check:lint && pnpm run check:types",
48
46
  "check:lint": "echo \"Run check:lint\" && NODE_ENV=production eslint ./src",
49
47
  "check:lint-fix": "echo \"Run check:lint\" && NODE_ENV=production eslint ./src --fix",
50
- "check:types": "echo \"Run check:types\" && tsc --project tsconfig.json --skipLibCheck --emitDeclarationOnly false --noEmit"
48
+ "check:types": "echo \"Run check:types\" && pushwoosh-engine lib:check-types"
51
49
  }
52
50
  }