@commercetools/ts-client 2.0.0 → 2.0.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @commercetools/ts-client
2
2
 
3
+ ## 2.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#767](https://github.com/commercetools/commercetools-sdk-typescript/pull/767) [`d82a9e0`](https://github.com/commercetools/commercetools-sdk-typescript/commit/d82a9e0e6666e076183172a9229ffcda8e28905a) Thanks [@ajimae](https://github.com/ajimae)! - Fix issues with request state not being reset back to default on error when fetching token.
8
+
3
9
  ## 2.0.0
4
10
 
5
11
  ### Major Changes
@@ -121,10 +121,11 @@ function createError({
121
121
  return new HttpError(statusCode, errorMessage, rest);
122
122
  }
123
123
 
124
- function predicate(retryCodes, response) {
125
- return !
126
- // retryCodes.includes(response?.error?.message) ||
127
- [503, ...retryCodes].includes(response?.status || response?.statusCode);
124
+ function hasResponseRetryCode(retryCodes, response) {
125
+ return (
126
+ // retryCodes.includes(response?.error?.message) ||
127
+ [503, ...retryCodes].includes(response?.status || response?.statusCode)
128
+ );
128
129
  }
129
130
  async function executeHttpClientRequest(fetcher, config) {
130
131
  async function sendRequest() {
@@ -151,14 +152,17 @@ async function executor(request) {
151
152
  const data = await executeHttpClientRequest(async options => {
152
153
  const {
153
154
  enableRetry,
154
- retryConfig
155
+ retryConfig,
156
+ abortController
155
157
  } = rest;
156
158
  const {
157
159
  retryCodes = [],
158
160
  maxDelay = Infinity,
159
161
  maxRetries = 3,
160
162
  backoff = true,
161
- retryDelay = 200
163
+ retryDelay = 200,
164
+ // If set to true reinitialize the abort controller when the timeout is reached and apply the retry config
165
+ retryOnAbort = true
162
166
  } = retryConfig || {};
163
167
  let result,
164
168
  data,
@@ -184,15 +188,41 @@ async function executor(request) {
184
188
  });
185
189
  }
186
190
  async function executeWithRetry() {
191
+ const executeWithTryCatch = async (retryCodes, retryWhenAborted) => {
192
+ let _response = {};
193
+ try {
194
+ _response = await execute();
195
+ if (_response.status > 299 && hasResponseRetryCode(retryCodes, _response)) return {
196
+ _response,
197
+ shouldRetry: true
198
+ };
199
+ } catch (e) {
200
+ if (e.name.includes('AbortError') && retryWhenAborted) {
201
+ return {
202
+ _response: e,
203
+ shouldRetry: true
204
+ };
205
+ } else {
206
+ throw e;
207
+ }
208
+ }
209
+ return {
210
+ _response,
211
+ shouldRetry: false
212
+ };
213
+ };
214
+ const retryWhenAborted = retryOnAbort || !abortController || !abortController.signal;
187
215
  // first attempt
188
- let _response = await execute();
189
- if (predicate(retryCodes, _response)) return _response;
190
-
216
+ let {
217
+ _response,
218
+ shouldRetry
219
+ } = await executeWithTryCatch(retryCodes, retryWhenAborted);
191
220
  // retry attempts
192
- while (enableRetry && retryCount < maxRetries) {
221
+ while (enableRetry && shouldRetry && retryCount < maxRetries) {
193
222
  retryCount++;
194
- _response = await execute();
195
- if (predicate(retryCodes, _response)) return _response;
223
+ const execution = await executeWithTryCatch(retryCodes, retryWhenAborted);
224
+ _response = execution._response;
225
+ shouldRetry = execution.shouldRetry;
196
226
 
197
227
  // delay next execution
198
228
  const timer = calculateRetryDelay({
@@ -432,7 +462,6 @@ function createUserAgent(options) {
432
462
  function validateHttpOptions(options) {
433
463
  if (!options.host) throw new Error('Request `host` or `url` is missing or invalid, please pass in a valid host e.g `host: http://a-valid-host-url`');
434
464
  if (!options.httpClient && typeof options.httpClient !== 'function') throw new Error('An `httpClient` is not available, please pass in a `fetch` or `axios` instance as an option or have them globally available.');
435
- if (options.timeout && !options.getAbortController) throw new Error('`AbortController` is not available. Please pass in `getAbortController` as an option or have AbortController globally available when using timeout.');
436
465
  }
437
466
 
438
467
  /**
@@ -638,7 +667,10 @@ async function executeRequest$1(options) {
638
667
  * and there's either no token or the token is expired
639
668
  */
640
669
  if (tokenCacheObject && tokenCacheObject.refreshToken && (!tokenCacheObject.token || tokenCacheObject.token && Date.now() > tokenCacheObject.expirationTime)) {
641
- if (!userOption) throw new Error('Missing required options.');
670
+ if (!userOption) {
671
+ requestState.set(false);
672
+ throw new Error('Missing required options.');
673
+ }
642
674
  const opt = {
643
675
  ...buildRequestForRefreshTokenFlow({
644
676
  ...userOption,
@@ -711,8 +743,10 @@ async function executeRequest$1(options) {
711
743
  const error = new Error(response.data.message ? response.data.message : JSON.stringify(response.data));
712
744
  /**
713
745
  * reject the error immediately
714
- * and free up the middleware chain
746
+ * and free up the middleware chain and
747
+ * release the requestState by setting it to false
715
748
  */
749
+ requestState.set(false);
716
750
  request.reject({
717
751
  ...request,
718
752
  headers: {
@@ -727,6 +761,10 @@ async function executeRequest$1(options) {
727
761
  }
728
762
  });
729
763
  } catch (error) {
764
+ /**
765
+ * on error release the state by setting it to false
766
+ */
767
+ requestState.set(false);
730
768
  return {
731
769
  ...request,
732
770
  headers: {
@@ -1224,7 +1262,7 @@ function createQueueMiddleware$1({
1224
1262
 
1225
1263
  var packageJson = {
1226
1264
  name: "@commercetools/ts-client",
1227
- version: "2.0.0",
1265
+ version: "2.0.1",
1228
1266
  engines: {
1229
1267
  node: ">=14"
1230
1268
  },
@@ -1260,7 +1298,7 @@ var packageJson = {
1260
1298
  "abort-controller": "3.0.0",
1261
1299
  buffer: "^6.0.3",
1262
1300
  "node-fetch": "^2.6.1",
1263
- uuid: "9.0.1"
1301
+ uuid: "10.0.0"
1264
1302
  },
1265
1303
  files: [
1266
1304
  "dist",
@@ -112,10 +112,11 @@ function createError({
112
112
  return new HttpError(statusCode, errorMessage, rest);
113
113
  }
114
114
 
115
- function predicate(retryCodes, response) {
116
- return !
117
- // retryCodes.includes(response?.error?.message) ||
118
- [503, ...retryCodes].includes(response?.status || response?.statusCode);
115
+ function hasResponseRetryCode(retryCodes, response) {
116
+ return (
117
+ // retryCodes.includes(response?.error?.message) ||
118
+ [503, ...retryCodes].includes(response?.status || response?.statusCode)
119
+ );
119
120
  }
120
121
  async function executeHttpClientRequest(fetcher, config) {
121
122
  async function sendRequest() {
@@ -142,14 +143,17 @@ async function executor(request) {
142
143
  const data = await executeHttpClientRequest(async options => {
143
144
  const {
144
145
  enableRetry,
145
- retryConfig
146
+ retryConfig,
147
+ abortController
146
148
  } = rest;
147
149
  const {
148
150
  retryCodes = [],
149
151
  maxDelay = Infinity,
150
152
  maxRetries = 3,
151
153
  backoff = true,
152
- retryDelay = 200
154
+ retryDelay = 200,
155
+ // If set to true reinitialize the abort controller when the timeout is reached and apply the retry config
156
+ retryOnAbort = true
153
157
  } = retryConfig || {};
154
158
  let result,
155
159
  data,
@@ -175,15 +179,41 @@ async function executor(request) {
175
179
  });
176
180
  }
177
181
  async function executeWithRetry() {
182
+ const executeWithTryCatch = async (retryCodes, retryWhenAborted) => {
183
+ let _response = {};
184
+ try {
185
+ _response = await execute();
186
+ if (_response.status > 299 && hasResponseRetryCode(retryCodes, _response)) return {
187
+ _response,
188
+ shouldRetry: true
189
+ };
190
+ } catch (e) {
191
+ if (e.name.includes('AbortError') && retryWhenAborted) {
192
+ return {
193
+ _response: e,
194
+ shouldRetry: true
195
+ };
196
+ } else {
197
+ throw e;
198
+ }
199
+ }
200
+ return {
201
+ _response,
202
+ shouldRetry: false
203
+ };
204
+ };
205
+ const retryWhenAborted = retryOnAbort || !abortController || !abortController.signal;
178
206
  // first attempt
179
- let _response = await execute();
180
- if (predicate(retryCodes, _response)) return _response;
181
-
207
+ let {
208
+ _response,
209
+ shouldRetry
210
+ } = await executeWithTryCatch(retryCodes, retryWhenAborted);
182
211
  // retry attempts
183
- while (enableRetry && retryCount < maxRetries) {
212
+ while (enableRetry && shouldRetry && retryCount < maxRetries) {
184
213
  retryCount++;
185
- _response = await execute();
186
- if (predicate(retryCodes, _response)) return _response;
214
+ const execution = await executeWithTryCatch(retryCodes, retryWhenAborted);
215
+ _response = execution._response;
216
+ shouldRetry = execution.shouldRetry;
187
217
 
188
218
  // delay next execution
189
219
  const timer = calculateRetryDelay({
@@ -423,7 +453,6 @@ function createUserAgent(options) {
423
453
  function validateHttpOptions(options) {
424
454
  if (!options.host) throw new Error('Request `host` or `url` is missing or invalid, please pass in a valid host e.g `host: http://a-valid-host-url`');
425
455
  if (!options.httpClient && typeof options.httpClient !== 'function') throw new Error('An `httpClient` is not available, please pass in a `fetch` or `axios` instance as an option or have them globally available.');
426
- if (options.timeout && !options.getAbortController) throw new Error('`AbortController` is not available. Please pass in `getAbortController` as an option or have AbortController globally available when using timeout.');
427
456
  }
428
457
 
429
458
  /**
@@ -629,7 +658,10 @@ async function executeRequest$1(options) {
629
658
  * and there's either no token or the token is expired
630
659
  */
631
660
  if (tokenCacheObject && tokenCacheObject.refreshToken && (!tokenCacheObject.token || tokenCacheObject.token && Date.now() > tokenCacheObject.expirationTime)) {
632
- if (!userOption) throw new Error('Missing required options.');
661
+ if (!userOption) {
662
+ requestState.set(false);
663
+ throw new Error('Missing required options.');
664
+ }
633
665
  const opt = {
634
666
  ...buildRequestForRefreshTokenFlow({
635
667
  ...userOption,
@@ -702,8 +734,10 @@ async function executeRequest$1(options) {
702
734
  const error = new Error(response.data.message ? response.data.message : JSON.stringify(response.data));
703
735
  /**
704
736
  * reject the error immediately
705
- * and free up the middleware chain
737
+ * and free up the middleware chain and
738
+ * release the requestState by setting it to false
706
739
  */
740
+ requestState.set(false);
707
741
  request.reject({
708
742
  ...request,
709
743
  headers: {
@@ -718,6 +752,10 @@ async function executeRequest$1(options) {
718
752
  }
719
753
  });
720
754
  } catch (error) {
755
+ /**
756
+ * on error release the state by setting it to false
757
+ */
758
+ requestState.set(false);
721
759
  return {
722
760
  ...request,
723
761
  headers: {
@@ -1215,7 +1253,7 @@ function createQueueMiddleware$1({
1215
1253
 
1216
1254
  var packageJson = {
1217
1255
  name: "@commercetools/ts-client",
1218
- version: "2.0.0",
1256
+ version: "2.0.1",
1219
1257
  engines: {
1220
1258
  node: ">=14"
1221
1259
  },
@@ -1251,7 +1289,7 @@ var packageJson = {
1251
1289
  "abort-controller": "3.0.0",
1252
1290
  buffer: "^6.0.3",
1253
1291
  "node-fetch": "^2.6.1",
1254
- uuid: "9.0.1"
1292
+ uuid: "10.0.0"
1255
1293
  },
1256
1294
  files: [
1257
1295
  "dist",
@@ -121,10 +121,11 @@ function createError({
121
121
  return new HttpError(statusCode, errorMessage, rest);
122
122
  }
123
123
 
124
- function predicate(retryCodes, response) {
125
- return !
126
- // retryCodes.includes(response?.error?.message) ||
127
- [503, ...retryCodes].includes(response?.status || response?.statusCode);
124
+ function hasResponseRetryCode(retryCodes, response) {
125
+ return (
126
+ // retryCodes.includes(response?.error?.message) ||
127
+ [503, ...retryCodes].includes(response?.status || response?.statusCode)
128
+ );
128
129
  }
129
130
  async function executeHttpClientRequest(fetcher, config) {
130
131
  async function sendRequest() {
@@ -151,14 +152,17 @@ async function executor(request) {
151
152
  const data = await executeHttpClientRequest(async options => {
152
153
  const {
153
154
  enableRetry,
154
- retryConfig
155
+ retryConfig,
156
+ abortController
155
157
  } = rest;
156
158
  const {
157
159
  retryCodes = [],
158
160
  maxDelay = Infinity,
159
161
  maxRetries = 3,
160
162
  backoff = true,
161
- retryDelay = 200
163
+ retryDelay = 200,
164
+ // If set to true reinitialize the abort controller when the timeout is reached and apply the retry config
165
+ retryOnAbort = true
162
166
  } = retryConfig || {};
163
167
  let result,
164
168
  data,
@@ -184,15 +188,41 @@ async function executor(request) {
184
188
  });
185
189
  }
186
190
  async function executeWithRetry() {
191
+ const executeWithTryCatch = async (retryCodes, retryWhenAborted) => {
192
+ let _response = {};
193
+ try {
194
+ _response = await execute();
195
+ if (_response.status > 299 && hasResponseRetryCode(retryCodes, _response)) return {
196
+ _response,
197
+ shouldRetry: true
198
+ };
199
+ } catch (e) {
200
+ if (e.name.includes('AbortError') && retryWhenAborted) {
201
+ return {
202
+ _response: e,
203
+ shouldRetry: true
204
+ };
205
+ } else {
206
+ throw e;
207
+ }
208
+ }
209
+ return {
210
+ _response,
211
+ shouldRetry: false
212
+ };
213
+ };
214
+ const retryWhenAborted = retryOnAbort || !abortController || !abortController.signal;
187
215
  // first attempt
188
- let _response = await execute();
189
- if (predicate(retryCodes, _response)) return _response;
190
-
216
+ let {
217
+ _response,
218
+ shouldRetry
219
+ } = await executeWithTryCatch(retryCodes, retryWhenAborted);
191
220
  // retry attempts
192
- while (enableRetry && retryCount < maxRetries) {
221
+ while (enableRetry && shouldRetry && retryCount < maxRetries) {
193
222
  retryCount++;
194
- _response = await execute();
195
- if (predicate(retryCodes, _response)) return _response;
223
+ const execution = await executeWithTryCatch(retryCodes, retryWhenAborted);
224
+ _response = execution._response;
225
+ shouldRetry = execution.shouldRetry;
196
226
 
197
227
  // delay next execution
198
228
  const timer = calculateRetryDelay({
@@ -432,7 +462,6 @@ function createUserAgent(options) {
432
462
  function validateHttpOptions(options) {
433
463
  if (!options.host) throw new Error('Request `host` or `url` is missing or invalid, please pass in a valid host e.g `host: http://a-valid-host-url`');
434
464
  if (!options.httpClient && typeof options.httpClient !== 'function') throw new Error('An `httpClient` is not available, please pass in a `fetch` or `axios` instance as an option or have them globally available.');
435
- if (options.timeout && !options.getAbortController) throw new Error('`AbortController` is not available. Please pass in `getAbortController` as an option or have AbortController globally available when using timeout.');
436
465
  }
437
466
 
438
467
  /**
@@ -638,7 +667,10 @@ async function executeRequest$1(options) {
638
667
  * and there's either no token or the token is expired
639
668
  */
640
669
  if (tokenCacheObject && tokenCacheObject.refreshToken && (!tokenCacheObject.token || tokenCacheObject.token && Date.now() > tokenCacheObject.expirationTime)) {
641
- if (!userOption) throw new Error('Missing required options.');
670
+ if (!userOption) {
671
+ requestState.set(false);
672
+ throw new Error('Missing required options.');
673
+ }
642
674
  const opt = {
643
675
  ...buildRequestForRefreshTokenFlow({
644
676
  ...userOption,
@@ -711,8 +743,10 @@ async function executeRequest$1(options) {
711
743
  const error = new Error(response.data.message ? response.data.message : JSON.stringify(response.data));
712
744
  /**
713
745
  * reject the error immediately
714
- * and free up the middleware chain
746
+ * and free up the middleware chain and
747
+ * release the requestState by setting it to false
715
748
  */
749
+ requestState.set(false);
716
750
  request.reject({
717
751
  ...request,
718
752
  headers: {
@@ -727,6 +761,10 @@ async function executeRequest$1(options) {
727
761
  }
728
762
  });
729
763
  } catch (error) {
764
+ /**
765
+ * on error release the state by setting it to false
766
+ */
767
+ requestState.set(false);
730
768
  return {
731
769
  ...request,
732
770
  headers: {
@@ -1224,7 +1262,7 @@ function createQueueMiddleware$1({
1224
1262
 
1225
1263
  var packageJson = {
1226
1264
  name: "@commercetools/ts-client",
1227
- version: "2.0.0",
1265
+ version: "2.0.1",
1228
1266
  engines: {
1229
1267
  node: ">=14"
1230
1268
  },
@@ -1260,7 +1298,7 @@ var packageJson = {
1260
1298
  "abort-controller": "3.0.0",
1261
1299
  buffer: "^6.0.3",
1262
1300
  "node-fetch": "^2.6.1",
1263
- uuid: "9.0.1"
1301
+ uuid: "10.0.0"
1264
1302
  },
1265
1303
  files: [
1266
1304
  "dist",
@@ -121,10 +121,11 @@ function createError({
121
121
  return new HttpError(statusCode, errorMessage, rest);
122
122
  }
123
123
 
124
- function predicate(retryCodes, response) {
125
- return !
126
- // retryCodes.includes(response?.error?.message) ||
127
- [503, ...retryCodes].includes(response?.status || response?.statusCode);
124
+ function hasResponseRetryCode(retryCodes, response) {
125
+ return (
126
+ // retryCodes.includes(response?.error?.message) ||
127
+ [503, ...retryCodes].includes(response?.status || response?.statusCode)
128
+ );
128
129
  }
129
130
  async function executeHttpClientRequest(fetcher, config) {
130
131
  async function sendRequest() {
@@ -151,14 +152,17 @@ async function executor(request) {
151
152
  const data = await executeHttpClientRequest(async options => {
152
153
  const {
153
154
  enableRetry,
154
- retryConfig
155
+ retryConfig,
156
+ abortController
155
157
  } = rest;
156
158
  const {
157
159
  retryCodes = [],
158
160
  maxDelay = Infinity,
159
161
  maxRetries = 3,
160
162
  backoff = true,
161
- retryDelay = 200
163
+ retryDelay = 200,
164
+ // If set to true reinitialize the abort controller when the timeout is reached and apply the retry config
165
+ retryOnAbort = true
162
166
  } = retryConfig || {};
163
167
  let result,
164
168
  data,
@@ -184,15 +188,41 @@ async function executor(request) {
184
188
  });
185
189
  }
186
190
  async function executeWithRetry() {
191
+ const executeWithTryCatch = async (retryCodes, retryWhenAborted) => {
192
+ let _response = {};
193
+ try {
194
+ _response = await execute();
195
+ if (_response.status > 299 && hasResponseRetryCode(retryCodes, _response)) return {
196
+ _response,
197
+ shouldRetry: true
198
+ };
199
+ } catch (e) {
200
+ if (e.name.includes('AbortError') && retryWhenAborted) {
201
+ return {
202
+ _response: e,
203
+ shouldRetry: true
204
+ };
205
+ } else {
206
+ throw e;
207
+ }
208
+ }
209
+ return {
210
+ _response,
211
+ shouldRetry: false
212
+ };
213
+ };
214
+ const retryWhenAborted = retryOnAbort || !abortController || !abortController.signal;
187
215
  // first attempt
188
- let _response = await execute();
189
- if (predicate(retryCodes, _response)) return _response;
190
-
216
+ let {
217
+ _response,
218
+ shouldRetry
219
+ } = await executeWithTryCatch(retryCodes, retryWhenAborted);
191
220
  // retry attempts
192
- while (enableRetry && retryCount < maxRetries) {
221
+ while (enableRetry && shouldRetry && retryCount < maxRetries) {
193
222
  retryCount++;
194
- _response = await execute();
195
- if (predicate(retryCodes, _response)) return _response;
223
+ const execution = await executeWithTryCatch(retryCodes, retryWhenAborted);
224
+ _response = execution._response;
225
+ shouldRetry = execution.shouldRetry;
196
226
 
197
227
  // delay next execution
198
228
  const timer = calculateRetryDelay({
@@ -432,7 +462,6 @@ function createUserAgent(options) {
432
462
  function validateHttpOptions(options) {
433
463
  if (!options.host) throw new Error('Request `host` or `url` is missing or invalid, please pass in a valid host e.g `host: http://a-valid-host-url`');
434
464
  if (!options.httpClient && typeof options.httpClient !== 'function') throw new Error('An `httpClient` is not available, please pass in a `fetch` or `axios` instance as an option or have them globally available.');
435
- if (options.timeout && !options.getAbortController) throw new Error('`AbortController` is not available. Please pass in `getAbortController` as an option or have AbortController globally available when using timeout.');
436
465
  }
437
466
 
438
467
  /**
@@ -638,7 +667,10 @@ async function executeRequest$1(options) {
638
667
  * and there's either no token or the token is expired
639
668
  */
640
669
  if (tokenCacheObject && tokenCacheObject.refreshToken && (!tokenCacheObject.token || tokenCacheObject.token && Date.now() > tokenCacheObject.expirationTime)) {
641
- if (!userOption) throw new Error('Missing required options.');
670
+ if (!userOption) {
671
+ requestState.set(false);
672
+ throw new Error('Missing required options.');
673
+ }
642
674
  const opt = {
643
675
  ...buildRequestForRefreshTokenFlow({
644
676
  ...userOption,
@@ -711,8 +743,10 @@ async function executeRequest$1(options) {
711
743
  const error = new Error(response.data.message ? response.data.message : JSON.stringify(response.data));
712
744
  /**
713
745
  * reject the error immediately
714
- * and free up the middleware chain
746
+ * and free up the middleware chain and
747
+ * release the requestState by setting it to false
715
748
  */
749
+ requestState.set(false);
716
750
  request.reject({
717
751
  ...request,
718
752
  headers: {
@@ -727,6 +761,10 @@ async function executeRequest$1(options) {
727
761
  }
728
762
  });
729
763
  } catch (error) {
764
+ /**
765
+ * on error release the state by setting it to false
766
+ */
767
+ requestState.set(false);
730
768
  return {
731
769
  ...request,
732
770
  headers: {
@@ -1224,7 +1262,7 @@ function createQueueMiddleware$1({
1224
1262
 
1225
1263
  var packageJson = {
1226
1264
  name: "@commercetools/ts-client",
1227
- version: "2.0.0",
1265
+ version: "2.0.1",
1228
1266
  engines: {
1229
1267
  node: ">=14"
1230
1268
  },
@@ -1260,7 +1298,7 @@ var packageJson = {
1260
1298
  "abort-controller": "3.0.0",
1261
1299
  buffer: "^6.0.3",
1262
1300
  "node-fetch": "^2.6.1",
1263
- uuid: "9.0.1"
1301
+ uuid: "10.0.0"
1264
1302
  },
1265
1303
  files: [
1266
1304
  "dist",
@@ -112,10 +112,11 @@ function createError({
112
112
  return new HttpError(statusCode, errorMessage, rest);
113
113
  }
114
114
 
115
- function predicate(retryCodes, response) {
116
- return !
117
- // retryCodes.includes(response?.error?.message) ||
118
- [503, ...retryCodes].includes(response?.status || response?.statusCode);
115
+ function hasResponseRetryCode(retryCodes, response) {
116
+ return (
117
+ // retryCodes.includes(response?.error?.message) ||
118
+ [503, ...retryCodes].includes(response?.status || response?.statusCode)
119
+ );
119
120
  }
120
121
  async function executeHttpClientRequest(fetcher, config) {
121
122
  async function sendRequest() {
@@ -142,14 +143,17 @@ async function executor(request) {
142
143
  const data = await executeHttpClientRequest(async options => {
143
144
  const {
144
145
  enableRetry,
145
- retryConfig
146
+ retryConfig,
147
+ abortController
146
148
  } = rest;
147
149
  const {
148
150
  retryCodes = [],
149
151
  maxDelay = Infinity,
150
152
  maxRetries = 3,
151
153
  backoff = true,
152
- retryDelay = 200
154
+ retryDelay = 200,
155
+ // If set to true reinitialize the abort controller when the timeout is reached and apply the retry config
156
+ retryOnAbort = true
153
157
  } = retryConfig || {};
154
158
  let result,
155
159
  data,
@@ -175,15 +179,41 @@ async function executor(request) {
175
179
  });
176
180
  }
177
181
  async function executeWithRetry() {
182
+ const executeWithTryCatch = async (retryCodes, retryWhenAborted) => {
183
+ let _response = {};
184
+ try {
185
+ _response = await execute();
186
+ if (_response.status > 299 && hasResponseRetryCode(retryCodes, _response)) return {
187
+ _response,
188
+ shouldRetry: true
189
+ };
190
+ } catch (e) {
191
+ if (e.name.includes('AbortError') && retryWhenAborted) {
192
+ return {
193
+ _response: e,
194
+ shouldRetry: true
195
+ };
196
+ } else {
197
+ throw e;
198
+ }
199
+ }
200
+ return {
201
+ _response,
202
+ shouldRetry: false
203
+ };
204
+ };
205
+ const retryWhenAborted = retryOnAbort || !abortController || !abortController.signal;
178
206
  // first attempt
179
- let _response = await execute();
180
- if (predicate(retryCodes, _response)) return _response;
181
-
207
+ let {
208
+ _response,
209
+ shouldRetry
210
+ } = await executeWithTryCatch(retryCodes, retryWhenAborted);
182
211
  // retry attempts
183
- while (enableRetry && retryCount < maxRetries) {
212
+ while (enableRetry && shouldRetry && retryCount < maxRetries) {
184
213
  retryCount++;
185
- _response = await execute();
186
- if (predicate(retryCodes, _response)) return _response;
214
+ const execution = await executeWithTryCatch(retryCodes, retryWhenAborted);
215
+ _response = execution._response;
216
+ shouldRetry = execution.shouldRetry;
187
217
 
188
218
  // delay next execution
189
219
  const timer = calculateRetryDelay({
@@ -423,7 +453,6 @@ function createUserAgent(options) {
423
453
  function validateHttpOptions(options) {
424
454
  if (!options.host) throw new Error('Request `host` or `url` is missing or invalid, please pass in a valid host e.g `host: http://a-valid-host-url`');
425
455
  if (!options.httpClient && typeof options.httpClient !== 'function') throw new Error('An `httpClient` is not available, please pass in a `fetch` or `axios` instance as an option or have them globally available.');
426
- if (options.timeout && !options.getAbortController) throw new Error('`AbortController` is not available. Please pass in `getAbortController` as an option or have AbortController globally available when using timeout.');
427
456
  }
428
457
 
429
458
  /**
@@ -629,7 +658,10 @@ async function executeRequest$1(options) {
629
658
  * and there's either no token or the token is expired
630
659
  */
631
660
  if (tokenCacheObject && tokenCacheObject.refreshToken && (!tokenCacheObject.token || tokenCacheObject.token && Date.now() > tokenCacheObject.expirationTime)) {
632
- if (!userOption) throw new Error('Missing required options.');
661
+ if (!userOption) {
662
+ requestState.set(false);
663
+ throw new Error('Missing required options.');
664
+ }
633
665
  const opt = {
634
666
  ...buildRequestForRefreshTokenFlow({
635
667
  ...userOption,
@@ -702,8 +734,10 @@ async function executeRequest$1(options) {
702
734
  const error = new Error(response.data.message ? response.data.message : JSON.stringify(response.data));
703
735
  /**
704
736
  * reject the error immediately
705
- * and free up the middleware chain
737
+ * and free up the middleware chain and
738
+ * release the requestState by setting it to false
706
739
  */
740
+ requestState.set(false);
707
741
  request.reject({
708
742
  ...request,
709
743
  headers: {
@@ -718,6 +752,10 @@ async function executeRequest$1(options) {
718
752
  }
719
753
  });
720
754
  } catch (error) {
755
+ /**
756
+ * on error release the state by setting it to false
757
+ */
758
+ requestState.set(false);
721
759
  return {
722
760
  ...request,
723
761
  headers: {
@@ -1215,7 +1253,7 @@ function createQueueMiddleware$1({
1215
1253
 
1216
1254
  var packageJson = {
1217
1255
  name: "@commercetools/ts-client",
1218
- version: "2.0.0",
1256
+ version: "2.0.1",
1219
1257
  engines: {
1220
1258
  node: ">=14"
1221
1259
  },
@@ -1251,7 +1289,7 @@ var packageJson = {
1251
1289
  "abort-controller": "3.0.0",
1252
1290
  buffer: "^6.0.3",
1253
1291
  "node-fetch": "^2.6.1",
1254
- uuid: "9.0.1"
1292
+ uuid: "10.0.0"
1255
1293
  },
1256
1294
  files: [
1257
1295
  "dist",
@@ -222,7 +222,7 @@ export type HttpMiddlewareOptions = {
222
222
  retryConfig?: RetryOptions
223
223
  httpClient: Function
224
224
  getAbortController?: () => AbortController
225
- httpClientOptions?: object
225
+ httpClientOptions?: object // will be passed as a second argument to your httpClient function for configuration
226
226
  }
227
227
 
228
228
  export type RetryOptions = RetryMiddlewareOptions
@@ -242,6 +242,7 @@ export type RetryMiddlewareOptions = {
242
242
  maxRetries?: number
243
243
  retryDelay?: number
244
244
  maxDelay?: typeof Infinity
245
+ retryOnAbort?: boolean
245
246
  retryCodes?: Array<number | string>
246
247
  }
247
248
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commercetools/ts-client",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "engines": {
5
5
  "node": ">=14"
6
6
  },
@@ -36,7 +36,7 @@
36
36
  "abort-controller": "3.0.0",
37
37
  "buffer": "^6.0.3",
38
38
  "node-fetch": "^2.6.1",
39
- "uuid": "9.0.1"
39
+ "uuid": "10.0.0"
40
40
  },
41
41
  "files": ["dist", "CHANGELOG.md"],
42
42
  "author": "Chukwuemeka Ajima <meeky.ae@gmail.com>",