@extrahorizon/javascript-sdk 8.14.2-dev-207-77c1c66 → 8.14.2-feat-209-291dd31

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 CHANGED
@@ -5,6 +5,12 @@ 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
12
+ - Response transformations are no longer applied twice to retried requests
13
+
8
14
  ## [8.14.1]
9
15
 
10
16
  ### Fixed
@@ -2235,11 +2235,11 @@ function createOAuth1HttpClient(http, options) {
2235
2235
  {}),
2236
2236
  },
2237
2237
  }));
2238
- httpWithAuth.interceptors.response.use(null, retryInterceptor(httpWithAuth));
2239
- httpWithAuth.interceptors.response.use(null, typeReceivedErrorsInterceptor);
2240
2238
  httpWithAuth.interceptors.response.use(camelizeResponseData);
2241
2239
  httpWithAuth.interceptors.response.use(transformResponseData);
2242
2240
  httpWithAuth.interceptors.response.use(transformKeysResponseData);
2241
+ httpWithAuth.interceptors.response.use(null, retryInterceptor(httpWithAuth));
2242
+ httpWithAuth.interceptors.response.use(null, typeReceivedErrorsInterceptor);
2243
2243
  async function authenticate(data) {
2244
2244
  // If the user has passed in a token/tokenSecret combination.
2245
2245
  // Validate it against /users/me on the unauthenticated Axios client unless skipTokenCheck is true
@@ -2390,6 +2390,7 @@ function btoa(input) {
2390
2390
  const TOKEN_ENDPOINT = `${AUTH_BASE}/oauth2/tokens`;
2391
2391
  function createOAuth2HttpClient(http, options) {
2392
2392
  let tokenData;
2393
+ let refreshingTokensPromise = null;
2393
2394
  if ('refreshToken' in options && 'accessToken' in options) {
2394
2395
  tokenData = {
2395
2396
  refreshToken: options.refreshToken,
@@ -2443,7 +2444,7 @@ function createOAuth2HttpClient(http, options) {
2443
2444
  // Refresh 10 seconds before the token is about to expire.
2444
2445
  // This is to prevent being just too late with a refresh of the token due to latencies
2445
2446
  if (Date.now() > expireTime - 10 * 1000) {
2446
- await authenticate({ refreshToken: tokenData.refreshToken });
2447
+ await refreshTokens();
2447
2448
  }
2448
2449
  }
2449
2450
  return {
@@ -2454,6 +2455,9 @@ function createOAuth2HttpClient(http, options) {
2454
2455
  },
2455
2456
  };
2456
2457
  });
2458
+ httpWithAuth.interceptors.response.use(camelizeResponseData);
2459
+ httpWithAuth.interceptors.response.use(transformResponseData);
2460
+ httpWithAuth.interceptors.response.use(transformKeysResponseData);
2457
2461
  httpWithAuth.interceptors.response.use(null, retryInterceptor(httpWithAuth));
2458
2462
  // If we receive a expired/unknown access token error, refresh the tokens
2459
2463
  httpWithAuth.interceptors.response.use(null, async (error) => {
@@ -2467,15 +2471,12 @@ function createOAuth2HttpClient(http, options) {
2467
2471
  [118, 117].includes((_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.code) &&
2468
2472
  !originalRequest.isRetryWithRefreshedTokens) {
2469
2473
  originalRequest.isRetryWithRefreshedTokens = true;
2470
- await authenticate({ refreshToken: tokenData.refreshToken });
2474
+ await refreshTokens();
2471
2475
  return httpWithAuth(originalRequest);
2472
2476
  }
2473
2477
  throw error;
2474
2478
  });
2475
2479
  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
2480
  /**
2480
2481
  * - Adds a creationTimestamp to the token
2481
2482
  * - Notifies the user
@@ -2508,6 +2509,18 @@ function createOAuth2HttpClient(http, options) {
2508
2509
  {});
2509
2510
  return await dateAndSetTokenData(tokenResult.data);
2510
2511
  }
2512
+ async function refreshTokens() {
2513
+ if (refreshingTokensPromise) {
2514
+ return refreshingTokensPromise;
2515
+ }
2516
+ refreshingTokensPromise = authenticate({ refreshToken: tokenData.refreshToken });
2517
+ try {
2518
+ return await refreshingTokensPromise;
2519
+ }
2520
+ finally {
2521
+ refreshingTokensPromise = null;
2522
+ }
2523
+ }
2511
2524
  async function confirmMfa({ token, methodId, code, }) {
2512
2525
  const tokenResult = await http.post(TOKEN_ENDPOINT, {
2513
2526
  ...clientCredentials,
@@ -2629,11 +2642,11 @@ function createProxyHttpClient(http, options) {
2629
2642
  return Promise.reject(error);
2630
2643
  });
2631
2644
  }
2632
- httpWithAuth.interceptors.response.use(null, retryInterceptor(httpWithAuth));
2633
- httpWithAuth.interceptors.response.use(null, typeReceivedErrorsInterceptor);
2634
2645
  httpWithAuth.interceptors.response.use(camelizeResponseData);
2635
2646
  httpWithAuth.interceptors.response.use(transformResponseData);
2636
2647
  httpWithAuth.interceptors.response.use(transformKeysResponseData);
2648
+ httpWithAuth.interceptors.response.use(null, retryInterceptor(httpWithAuth));
2649
+ httpWithAuth.interceptors.response.use(null, typeReceivedErrorsInterceptor);
2637
2650
  async function logout() {
2638
2651
  try {
2639
2652
  await httpWithAuth.post('/logout');
@@ -2694,11 +2707,11 @@ function createHttpClient({ packageVersion, host, requestLogger, responseLogger,
2694
2707
  return Promise.reject(error);
2695
2708
  });
2696
2709
  }
2697
- http.interceptors.response.use(null, retryInterceptor(http));
2698
- http.interceptors.response.use(null, typeReceivedErrorsInterceptor);
2699
2710
  http.interceptors.response.use(camelizeResponseData);
2700
2711
  http.interceptors.response.use(transformResponseData);
2701
2712
  http.interceptors.response.use(transformKeysResponseData);
2713
+ http.interceptors.response.use(null, retryInterceptor(http));
2714
+ http.interceptors.response.use(null, typeReceivedErrorsInterceptor);
2702
2715
  return http;
2703
2716
  }
2704
2717
 
@@ -5768,7 +5781,7 @@ const templatesV2Service = (httpWithAuth) => {
5768
5781
  };
5769
5782
  };
5770
5783
 
5771
- const version = '8.14.2-dev-207-77c1c66';
5784
+ const version = '8.14.2-feat-209-291dd31';
5772
5785
 
5773
5786
  /**
5774
5787
  * Create ExtraHorizon client.
package/build/index.mjs CHANGED
@@ -2205,11 +2205,11 @@ function createOAuth1HttpClient(http, options) {
2205
2205
  {}),
2206
2206
  },
2207
2207
  }));
2208
- httpWithAuth.interceptors.response.use(null, retryInterceptor(httpWithAuth));
2209
- httpWithAuth.interceptors.response.use(null, typeReceivedErrorsInterceptor);
2210
2208
  httpWithAuth.interceptors.response.use(camelizeResponseData);
2211
2209
  httpWithAuth.interceptors.response.use(transformResponseData);
2212
2210
  httpWithAuth.interceptors.response.use(transformKeysResponseData);
2211
+ httpWithAuth.interceptors.response.use(null, retryInterceptor(httpWithAuth));
2212
+ httpWithAuth.interceptors.response.use(null, typeReceivedErrorsInterceptor);
2213
2213
  async function authenticate(data) {
2214
2214
  // If the user has passed in a token/tokenSecret combination.
2215
2215
  // Validate it against /users/me on the unauthenticated Axios client unless skipTokenCheck is true
@@ -2360,6 +2360,7 @@ function btoa(input) {
2360
2360
  const TOKEN_ENDPOINT = `${AUTH_BASE}/oauth2/tokens`;
2361
2361
  function createOAuth2HttpClient(http, options) {
2362
2362
  let tokenData;
2363
+ let refreshingTokensPromise = null;
2363
2364
  if ('refreshToken' in options && 'accessToken' in options) {
2364
2365
  tokenData = {
2365
2366
  refreshToken: options.refreshToken,
@@ -2413,7 +2414,7 @@ function createOAuth2HttpClient(http, options) {
2413
2414
  // Refresh 10 seconds before the token is about to expire.
2414
2415
  // This is to prevent being just too late with a refresh of the token due to latencies
2415
2416
  if (Date.now() > expireTime - 10 * 1000) {
2416
- await authenticate({ refreshToken: tokenData.refreshToken });
2417
+ await refreshTokens();
2417
2418
  }
2418
2419
  }
2419
2420
  return {
@@ -2424,6 +2425,9 @@ function createOAuth2HttpClient(http, options) {
2424
2425
  },
2425
2426
  };
2426
2427
  });
2428
+ httpWithAuth.interceptors.response.use(camelizeResponseData);
2429
+ httpWithAuth.interceptors.response.use(transformResponseData);
2430
+ httpWithAuth.interceptors.response.use(transformKeysResponseData);
2427
2431
  httpWithAuth.interceptors.response.use(null, retryInterceptor(httpWithAuth));
2428
2432
  // If we receive a expired/unknown access token error, refresh the tokens
2429
2433
  httpWithAuth.interceptors.response.use(null, async (error) => {
@@ -2437,15 +2441,12 @@ function createOAuth2HttpClient(http, options) {
2437
2441
  [118, 117].includes((_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.code) &&
2438
2442
  !originalRequest.isRetryWithRefreshedTokens) {
2439
2443
  originalRequest.isRetryWithRefreshedTokens = true;
2440
- await authenticate({ refreshToken: tokenData.refreshToken });
2444
+ await refreshTokens();
2441
2445
  return httpWithAuth(originalRequest);
2442
2446
  }
2443
2447
  throw error;
2444
2448
  });
2445
2449
  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
2450
  /**
2450
2451
  * - Adds a creationTimestamp to the token
2451
2452
  * - Notifies the user
@@ -2478,6 +2479,18 @@ function createOAuth2HttpClient(http, options) {
2478
2479
  {});
2479
2480
  return await dateAndSetTokenData(tokenResult.data);
2480
2481
  }
2482
+ async function refreshTokens() {
2483
+ if (refreshingTokensPromise) {
2484
+ return refreshingTokensPromise;
2485
+ }
2486
+ refreshingTokensPromise = authenticate({ refreshToken: tokenData.refreshToken });
2487
+ try {
2488
+ return await refreshingTokensPromise;
2489
+ }
2490
+ finally {
2491
+ refreshingTokensPromise = null;
2492
+ }
2493
+ }
2481
2494
  async function confirmMfa({ token, methodId, code, }) {
2482
2495
  const tokenResult = await http.post(TOKEN_ENDPOINT, {
2483
2496
  ...clientCredentials,
@@ -2599,11 +2612,11 @@ function createProxyHttpClient(http, options) {
2599
2612
  return Promise.reject(error);
2600
2613
  });
2601
2614
  }
2602
- httpWithAuth.interceptors.response.use(null, retryInterceptor(httpWithAuth));
2603
- httpWithAuth.interceptors.response.use(null, typeReceivedErrorsInterceptor);
2604
2615
  httpWithAuth.interceptors.response.use(camelizeResponseData);
2605
2616
  httpWithAuth.interceptors.response.use(transformResponseData);
2606
2617
  httpWithAuth.interceptors.response.use(transformKeysResponseData);
2618
+ httpWithAuth.interceptors.response.use(null, retryInterceptor(httpWithAuth));
2619
+ httpWithAuth.interceptors.response.use(null, typeReceivedErrorsInterceptor);
2607
2620
  async function logout() {
2608
2621
  try {
2609
2622
  await httpWithAuth.post('/logout');
@@ -2664,11 +2677,11 @@ function createHttpClient({ packageVersion, host, requestLogger, responseLogger,
2664
2677
  return Promise.reject(error);
2665
2678
  });
2666
2679
  }
2667
- http.interceptors.response.use(null, retryInterceptor(http));
2668
- http.interceptors.response.use(null, typeReceivedErrorsInterceptor);
2669
2680
  http.interceptors.response.use(camelizeResponseData);
2670
2681
  http.interceptors.response.use(transformResponseData);
2671
2682
  http.interceptors.response.use(transformKeysResponseData);
2683
+ http.interceptors.response.use(null, retryInterceptor(http));
2684
+ http.interceptors.response.use(null, typeReceivedErrorsInterceptor);
2672
2685
  return http;
2673
2686
  }
2674
2687
 
@@ -5738,7 +5751,7 @@ const templatesV2Service = (httpWithAuth) => {
5738
5751
  };
5739
5752
  };
5740
5753
 
5741
- const version = '8.14.2-dev-207-77c1c66';
5754
+ const version = '8.14.2-feat-209-291dd31';
5742
5755
 
5743
5756
  /**
5744
5757
  * Create ExtraHorizon client.
@@ -1 +1 @@
1
- export declare const version = "8.14.2-dev-207-77c1c66";
1
+ export declare const version = "8.14.2-feat-209-291dd31";
@@ -1 +1 @@
1
- export declare const version = "8.14.2-dev-207-77c1c66";
1
+ export declare const version = "8.14.2-feat-209-291dd31";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@extrahorizon/javascript-sdk",
3
- "version": "8.14.2-dev-207-77c1c66",
3
+ "version": "8.14.2-feat-209-291dd31",
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",