@extrahorizon/javascript-sdk 8.14.2-dev-207-77c1c66 → 8.14.2-dev-211-13941b3
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/CHANGELOG.md +7 -0
- package/build/index.cjs.js +29 -14
- package/build/index.mjs +29 -14
- package/build/types/version.d.ts +1 -1
- package/build/version.d.ts +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [8.14.2]
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- OAuth2 token refreshes are now shared between parallel requests, no longer invalidating each other
|
|
12
|
+
- Response transformations are no longer applied twice to retried requests
|
|
13
|
+
- Retry handling no longer masks internally generated errors as `TypeError: Cannot destructure property 'retry' of 'config' as it is undefined`
|
|
14
|
+
|
|
8
15
|
## [8.14.1]
|
|
9
16
|
|
|
10
17
|
### Fixed
|
package/build/index.cjs.js
CHANGED
|
@@ -1752,11 +1752,13 @@ function typeReceivedError(error) {
|
|
|
1752
1752
|
}
|
|
1753
1753
|
|
|
1754
1754
|
const retryInterceptor = (axios) => async (error) => {
|
|
1755
|
+
if (!error || !error.isAxiosError || !error.config) {
|
|
1756
|
+
throw error;
|
|
1757
|
+
}
|
|
1755
1758
|
const { config } = error;
|
|
1756
1759
|
const { retry } = config;
|
|
1757
1760
|
// tries includes the initial try. So 5 tries equals 4 retries
|
|
1758
|
-
if ((
|
|
1759
|
-
(retry === null || retry === void 0 ? void 0 : retry.tries) > (retry === null || retry === void 0 ? void 0 : retry.current) &&
|
|
1761
|
+
if ((retry === null || retry === void 0 ? void 0 : retry.tries) > (retry === null || retry === void 0 ? void 0 : retry.current) &&
|
|
1760
1762
|
(retry === null || retry === void 0 ? void 0 : retry.retryCondition(error))) {
|
|
1761
1763
|
await delay(retry.retryTimeInMs);
|
|
1762
1764
|
return axios({
|
|
@@ -2235,11 +2237,11 @@ function createOAuth1HttpClient(http, options) {
|
|
|
2235
2237
|
{}),
|
|
2236
2238
|
},
|
|
2237
2239
|
}));
|
|
2238
|
-
httpWithAuth.interceptors.response.use(null, retryInterceptor(httpWithAuth));
|
|
2239
|
-
httpWithAuth.interceptors.response.use(null, typeReceivedErrorsInterceptor);
|
|
2240
2240
|
httpWithAuth.interceptors.response.use(camelizeResponseData);
|
|
2241
2241
|
httpWithAuth.interceptors.response.use(transformResponseData);
|
|
2242
2242
|
httpWithAuth.interceptors.response.use(transformKeysResponseData);
|
|
2243
|
+
httpWithAuth.interceptors.response.use(null, retryInterceptor(httpWithAuth));
|
|
2244
|
+
httpWithAuth.interceptors.response.use(null, typeReceivedErrorsInterceptor);
|
|
2243
2245
|
async function authenticate(data) {
|
|
2244
2246
|
// If the user has passed in a token/tokenSecret combination.
|
|
2245
2247
|
// Validate it against /users/me on the unauthenticated Axios client unless skipTokenCheck is true
|
|
@@ -2390,6 +2392,7 @@ function btoa(input) {
|
|
|
2390
2392
|
const TOKEN_ENDPOINT = `${AUTH_BASE}/oauth2/tokens`;
|
|
2391
2393
|
function createOAuth2HttpClient(http, options) {
|
|
2392
2394
|
let tokenData;
|
|
2395
|
+
let refreshingTokensPromise = null;
|
|
2393
2396
|
if ('refreshToken' in options && 'accessToken' in options) {
|
|
2394
2397
|
tokenData = {
|
|
2395
2398
|
refreshToken: options.refreshToken,
|
|
@@ -2443,7 +2446,7 @@ function createOAuth2HttpClient(http, options) {
|
|
|
2443
2446
|
// Refresh 10 seconds before the token is about to expire.
|
|
2444
2447
|
// This is to prevent being just too late with a refresh of the token due to latencies
|
|
2445
2448
|
if (Date.now() > expireTime - 10 * 1000) {
|
|
2446
|
-
await
|
|
2449
|
+
await refreshTokens();
|
|
2447
2450
|
}
|
|
2448
2451
|
}
|
|
2449
2452
|
return {
|
|
@@ -2454,6 +2457,9 @@ function createOAuth2HttpClient(http, options) {
|
|
|
2454
2457
|
},
|
|
2455
2458
|
};
|
|
2456
2459
|
});
|
|
2460
|
+
httpWithAuth.interceptors.response.use(camelizeResponseData);
|
|
2461
|
+
httpWithAuth.interceptors.response.use(transformResponseData);
|
|
2462
|
+
httpWithAuth.interceptors.response.use(transformKeysResponseData);
|
|
2457
2463
|
httpWithAuth.interceptors.response.use(null, retryInterceptor(httpWithAuth));
|
|
2458
2464
|
// If we receive a expired/unknown access token error, refresh the tokens
|
|
2459
2465
|
httpWithAuth.interceptors.response.use(null, async (error) => {
|
|
@@ -2467,15 +2473,12 @@ function createOAuth2HttpClient(http, options) {
|
|
|
2467
2473
|
[118, 117].includes((_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.code) &&
|
|
2468
2474
|
!originalRequest.isRetryWithRefreshedTokens) {
|
|
2469
2475
|
originalRequest.isRetryWithRefreshedTokens = true;
|
|
2470
|
-
await
|
|
2476
|
+
await refreshTokens();
|
|
2471
2477
|
return httpWithAuth(originalRequest);
|
|
2472
2478
|
}
|
|
2473
2479
|
throw error;
|
|
2474
2480
|
});
|
|
2475
2481
|
httpWithAuth.interceptors.response.use(null, typeReceivedErrorsInterceptor);
|
|
2476
|
-
httpWithAuth.interceptors.response.use(camelizeResponseData);
|
|
2477
|
-
httpWithAuth.interceptors.response.use(transformResponseData);
|
|
2478
|
-
httpWithAuth.interceptors.response.use(transformKeysResponseData);
|
|
2479
2482
|
/**
|
|
2480
2483
|
* - Adds a creationTimestamp to the token
|
|
2481
2484
|
* - Notifies the user
|
|
@@ -2508,6 +2511,18 @@ function createOAuth2HttpClient(http, options) {
|
|
|
2508
2511
|
{});
|
|
2509
2512
|
return await dateAndSetTokenData(tokenResult.data);
|
|
2510
2513
|
}
|
|
2514
|
+
async function refreshTokens() {
|
|
2515
|
+
if (refreshingTokensPromise) {
|
|
2516
|
+
return refreshingTokensPromise;
|
|
2517
|
+
}
|
|
2518
|
+
refreshingTokensPromise = authenticate({ refreshToken: tokenData.refreshToken });
|
|
2519
|
+
try {
|
|
2520
|
+
return await refreshingTokensPromise;
|
|
2521
|
+
}
|
|
2522
|
+
finally {
|
|
2523
|
+
refreshingTokensPromise = null;
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2511
2526
|
async function confirmMfa({ token, methodId, code, }) {
|
|
2512
2527
|
const tokenResult = await http.post(TOKEN_ENDPOINT, {
|
|
2513
2528
|
...clientCredentials,
|
|
@@ -2629,11 +2644,11 @@ function createProxyHttpClient(http, options) {
|
|
|
2629
2644
|
return Promise.reject(error);
|
|
2630
2645
|
});
|
|
2631
2646
|
}
|
|
2632
|
-
httpWithAuth.interceptors.response.use(null, retryInterceptor(httpWithAuth));
|
|
2633
|
-
httpWithAuth.interceptors.response.use(null, typeReceivedErrorsInterceptor);
|
|
2634
2647
|
httpWithAuth.interceptors.response.use(camelizeResponseData);
|
|
2635
2648
|
httpWithAuth.interceptors.response.use(transformResponseData);
|
|
2636
2649
|
httpWithAuth.interceptors.response.use(transformKeysResponseData);
|
|
2650
|
+
httpWithAuth.interceptors.response.use(null, retryInterceptor(httpWithAuth));
|
|
2651
|
+
httpWithAuth.interceptors.response.use(null, typeReceivedErrorsInterceptor);
|
|
2637
2652
|
async function logout() {
|
|
2638
2653
|
try {
|
|
2639
2654
|
await httpWithAuth.post('/logout');
|
|
@@ -2694,11 +2709,11 @@ function createHttpClient({ packageVersion, host, requestLogger, responseLogger,
|
|
|
2694
2709
|
return Promise.reject(error);
|
|
2695
2710
|
});
|
|
2696
2711
|
}
|
|
2697
|
-
http.interceptors.response.use(null, retryInterceptor(http));
|
|
2698
|
-
http.interceptors.response.use(null, typeReceivedErrorsInterceptor);
|
|
2699
2712
|
http.interceptors.response.use(camelizeResponseData);
|
|
2700
2713
|
http.interceptors.response.use(transformResponseData);
|
|
2701
2714
|
http.interceptors.response.use(transformKeysResponseData);
|
|
2715
|
+
http.interceptors.response.use(null, retryInterceptor(http));
|
|
2716
|
+
http.interceptors.response.use(null, typeReceivedErrorsInterceptor);
|
|
2702
2717
|
return http;
|
|
2703
2718
|
}
|
|
2704
2719
|
|
|
@@ -5768,7 +5783,7 @@ const templatesV2Service = (httpWithAuth) => {
|
|
|
5768
5783
|
};
|
|
5769
5784
|
};
|
|
5770
5785
|
|
|
5771
|
-
const version = '8.14.2-dev-
|
|
5786
|
+
const version = '8.14.2-dev-211-13941b3';
|
|
5772
5787
|
|
|
5773
5788
|
/**
|
|
5774
5789
|
* Create ExtraHorizon client.
|
package/build/index.mjs
CHANGED
|
@@ -1722,11 +1722,13 @@ function typeReceivedError(error) {
|
|
|
1722
1722
|
}
|
|
1723
1723
|
|
|
1724
1724
|
const retryInterceptor = (axios) => async (error) => {
|
|
1725
|
+
if (!error || !error.isAxiosError || !error.config) {
|
|
1726
|
+
throw error;
|
|
1727
|
+
}
|
|
1725
1728
|
const { config } = error;
|
|
1726
1729
|
const { retry } = config;
|
|
1727
1730
|
// tries includes the initial try. So 5 tries equals 4 retries
|
|
1728
|
-
if ((
|
|
1729
|
-
(retry === null || retry === void 0 ? void 0 : retry.tries) > (retry === null || retry === void 0 ? void 0 : retry.current) &&
|
|
1731
|
+
if ((retry === null || retry === void 0 ? void 0 : retry.tries) > (retry === null || retry === void 0 ? void 0 : retry.current) &&
|
|
1730
1732
|
(retry === null || retry === void 0 ? void 0 : retry.retryCondition(error))) {
|
|
1731
1733
|
await delay(retry.retryTimeInMs);
|
|
1732
1734
|
return axios({
|
|
@@ -2205,11 +2207,11 @@ function createOAuth1HttpClient(http, options) {
|
|
|
2205
2207
|
{}),
|
|
2206
2208
|
},
|
|
2207
2209
|
}));
|
|
2208
|
-
httpWithAuth.interceptors.response.use(null, retryInterceptor(httpWithAuth));
|
|
2209
|
-
httpWithAuth.interceptors.response.use(null, typeReceivedErrorsInterceptor);
|
|
2210
2210
|
httpWithAuth.interceptors.response.use(camelizeResponseData);
|
|
2211
2211
|
httpWithAuth.interceptors.response.use(transformResponseData);
|
|
2212
2212
|
httpWithAuth.interceptors.response.use(transformKeysResponseData);
|
|
2213
|
+
httpWithAuth.interceptors.response.use(null, retryInterceptor(httpWithAuth));
|
|
2214
|
+
httpWithAuth.interceptors.response.use(null, typeReceivedErrorsInterceptor);
|
|
2213
2215
|
async function authenticate(data) {
|
|
2214
2216
|
// If the user has passed in a token/tokenSecret combination.
|
|
2215
2217
|
// Validate it against /users/me on the unauthenticated Axios client unless skipTokenCheck is true
|
|
@@ -2360,6 +2362,7 @@ function btoa(input) {
|
|
|
2360
2362
|
const TOKEN_ENDPOINT = `${AUTH_BASE}/oauth2/tokens`;
|
|
2361
2363
|
function createOAuth2HttpClient(http, options) {
|
|
2362
2364
|
let tokenData;
|
|
2365
|
+
let refreshingTokensPromise = null;
|
|
2363
2366
|
if ('refreshToken' in options && 'accessToken' in options) {
|
|
2364
2367
|
tokenData = {
|
|
2365
2368
|
refreshToken: options.refreshToken,
|
|
@@ -2413,7 +2416,7 @@ function createOAuth2HttpClient(http, options) {
|
|
|
2413
2416
|
// Refresh 10 seconds before the token is about to expire.
|
|
2414
2417
|
// This is to prevent being just too late with a refresh of the token due to latencies
|
|
2415
2418
|
if (Date.now() > expireTime - 10 * 1000) {
|
|
2416
|
-
await
|
|
2419
|
+
await refreshTokens();
|
|
2417
2420
|
}
|
|
2418
2421
|
}
|
|
2419
2422
|
return {
|
|
@@ -2424,6 +2427,9 @@ function createOAuth2HttpClient(http, options) {
|
|
|
2424
2427
|
},
|
|
2425
2428
|
};
|
|
2426
2429
|
});
|
|
2430
|
+
httpWithAuth.interceptors.response.use(camelizeResponseData);
|
|
2431
|
+
httpWithAuth.interceptors.response.use(transformResponseData);
|
|
2432
|
+
httpWithAuth.interceptors.response.use(transformKeysResponseData);
|
|
2427
2433
|
httpWithAuth.interceptors.response.use(null, retryInterceptor(httpWithAuth));
|
|
2428
2434
|
// If we receive a expired/unknown access token error, refresh the tokens
|
|
2429
2435
|
httpWithAuth.interceptors.response.use(null, async (error) => {
|
|
@@ -2437,15 +2443,12 @@ function createOAuth2HttpClient(http, options) {
|
|
|
2437
2443
|
[118, 117].includes((_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.code) &&
|
|
2438
2444
|
!originalRequest.isRetryWithRefreshedTokens) {
|
|
2439
2445
|
originalRequest.isRetryWithRefreshedTokens = true;
|
|
2440
|
-
await
|
|
2446
|
+
await refreshTokens();
|
|
2441
2447
|
return httpWithAuth(originalRequest);
|
|
2442
2448
|
}
|
|
2443
2449
|
throw error;
|
|
2444
2450
|
});
|
|
2445
2451
|
httpWithAuth.interceptors.response.use(null, typeReceivedErrorsInterceptor);
|
|
2446
|
-
httpWithAuth.interceptors.response.use(camelizeResponseData);
|
|
2447
|
-
httpWithAuth.interceptors.response.use(transformResponseData);
|
|
2448
|
-
httpWithAuth.interceptors.response.use(transformKeysResponseData);
|
|
2449
2452
|
/**
|
|
2450
2453
|
* - Adds a creationTimestamp to the token
|
|
2451
2454
|
* - Notifies the user
|
|
@@ -2478,6 +2481,18 @@ function createOAuth2HttpClient(http, options) {
|
|
|
2478
2481
|
{});
|
|
2479
2482
|
return await dateAndSetTokenData(tokenResult.data);
|
|
2480
2483
|
}
|
|
2484
|
+
async function refreshTokens() {
|
|
2485
|
+
if (refreshingTokensPromise) {
|
|
2486
|
+
return refreshingTokensPromise;
|
|
2487
|
+
}
|
|
2488
|
+
refreshingTokensPromise = authenticate({ refreshToken: tokenData.refreshToken });
|
|
2489
|
+
try {
|
|
2490
|
+
return await refreshingTokensPromise;
|
|
2491
|
+
}
|
|
2492
|
+
finally {
|
|
2493
|
+
refreshingTokensPromise = null;
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2481
2496
|
async function confirmMfa({ token, methodId, code, }) {
|
|
2482
2497
|
const tokenResult = await http.post(TOKEN_ENDPOINT, {
|
|
2483
2498
|
...clientCredentials,
|
|
@@ -2599,11 +2614,11 @@ function createProxyHttpClient(http, options) {
|
|
|
2599
2614
|
return Promise.reject(error);
|
|
2600
2615
|
});
|
|
2601
2616
|
}
|
|
2602
|
-
httpWithAuth.interceptors.response.use(null, retryInterceptor(httpWithAuth));
|
|
2603
|
-
httpWithAuth.interceptors.response.use(null, typeReceivedErrorsInterceptor);
|
|
2604
2617
|
httpWithAuth.interceptors.response.use(camelizeResponseData);
|
|
2605
2618
|
httpWithAuth.interceptors.response.use(transformResponseData);
|
|
2606
2619
|
httpWithAuth.interceptors.response.use(transformKeysResponseData);
|
|
2620
|
+
httpWithAuth.interceptors.response.use(null, retryInterceptor(httpWithAuth));
|
|
2621
|
+
httpWithAuth.interceptors.response.use(null, typeReceivedErrorsInterceptor);
|
|
2607
2622
|
async function logout() {
|
|
2608
2623
|
try {
|
|
2609
2624
|
await httpWithAuth.post('/logout');
|
|
@@ -2664,11 +2679,11 @@ function createHttpClient({ packageVersion, host, requestLogger, responseLogger,
|
|
|
2664
2679
|
return Promise.reject(error);
|
|
2665
2680
|
});
|
|
2666
2681
|
}
|
|
2667
|
-
http.interceptors.response.use(null, retryInterceptor(http));
|
|
2668
|
-
http.interceptors.response.use(null, typeReceivedErrorsInterceptor);
|
|
2669
2682
|
http.interceptors.response.use(camelizeResponseData);
|
|
2670
2683
|
http.interceptors.response.use(transformResponseData);
|
|
2671
2684
|
http.interceptors.response.use(transformKeysResponseData);
|
|
2685
|
+
http.interceptors.response.use(null, retryInterceptor(http));
|
|
2686
|
+
http.interceptors.response.use(null, typeReceivedErrorsInterceptor);
|
|
2672
2687
|
return http;
|
|
2673
2688
|
}
|
|
2674
2689
|
|
|
@@ -5738,7 +5753,7 @@ const templatesV2Service = (httpWithAuth) => {
|
|
|
5738
5753
|
};
|
|
5739
5754
|
};
|
|
5740
5755
|
|
|
5741
|
-
const version = '8.14.2-dev-
|
|
5756
|
+
const version = '8.14.2-dev-211-13941b3';
|
|
5742
5757
|
|
|
5743
5758
|
/**
|
|
5744
5759
|
* Create ExtraHorizon client.
|
package/build/types/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "8.14.2-dev-
|
|
1
|
+
export declare const version = "8.14.2-dev-211-13941b3";
|
package/build/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "8.14.2-dev-
|
|
1
|
+
export declare const version = "8.14.2-dev-211-13941b3";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@extrahorizon/javascript-sdk",
|
|
3
|
-
"version": "8.14.2-dev-
|
|
3
|
+
"version": "8.14.2-dev-211-13941b3",
|
|
4
4
|
"description": "This package serves as a JavaScript wrapper around all Extra Horizon cloud services.",
|
|
5
5
|
"main": "build/index.cjs.js",
|
|
6
6
|
"types": "build/types/index.d.ts",
|