@commercetools/sdk-client-v2 2.0.2 → 2.1.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.
@@ -22,7 +22,6 @@ function _defineProperty(obj, key, value) {
22
22
  } else {
23
23
  obj[key] = value;
24
24
  }
25
-
26
25
  return obj;
27
26
  }
28
27
 
@@ -31,7 +30,6 @@ var METHODS = ['ACL', 'BIND', 'CHECKOUT', 'CONNECT', 'COPY', 'DELETE', 'GET', 'H
31
30
  /**
32
31
  * @throws {Error}
33
32
  */
34
-
35
33
  function validate(funcName, request, options = {
36
34
  allowedMethods: METHODS
37
35
  }) {
@@ -41,19 +39,18 @@ function validate(funcName, request, options = {
41
39
  }
42
40
 
43
41
  let _options;
44
-
45
42
  function compose(...funcs) {
46
43
  funcs = funcs.filter(func => typeof func === 'function');
47
44
  if (funcs.length === 1) return funcs[0];
48
45
  return funcs.reduce((a, b) => (...args) => a(b(...args)));
49
46
  }
50
-
51
47
  function process$1(request, fn, processOpt) {
52
48
  validate('process', request, {
53
49
  allowedMethods: ['GET']
54
50
  });
55
- if (typeof fn !== 'function') throw new Error('The "process" function accepts a "Function" as a second argument that returns a Promise. See https://commercetools.github.io/nodejs/sdk/api/sdkClient.html#processrequest-processfn-options'); // Set default process options
51
+ if (typeof fn !== 'function') throw new Error('The "process" function accepts a "Function" as a second argument that returns a Promise. See https://commercetools.github.io/nodejs/sdk/api/sdkClient.html#processrequest-processfn-options');
56
52
 
53
+ // Set default process options
57
54
  const opt = {
58
55
  total: Number.POSITIVE_INFINITY,
59
56
  accumulate: true,
@@ -61,15 +58,14 @@ function process$1(request, fn, processOpt) {
61
58
  };
62
59
  return new Promise((resolve, reject) => {
63
60
  let _path,
64
- _queryString = '';
65
-
61
+ _queryString = '';
66
62
  if (request && request.uri) {
67
63
  const [path, queryString] = request.uri.split('?');
68
64
  _path = path;
69
65
  _queryString = queryString;
70
66
  }
71
-
72
- const requestQuery = { ...qs__default["default"].parse(_queryString)
67
+ const requestQuery = {
68
+ ...qs__default["default"].parse(_queryString)
73
69
  };
74
70
  const query = {
75
71
  // defaults
@@ -79,11 +75,11 @@ function process$1(request, fn, processOpt) {
79
75
  };
80
76
  let hasFirstPageBeenProcessed = false;
81
77
  let itemsToGet = opt.total;
82
-
83
78
  const processPage = async (lastId, acc = []) => {
84
79
  // Use the lesser value between limit and itemsToGet in query
85
80
  const limit = query.limit < itemsToGet ? query.limit : itemsToGet;
86
- const originalQueryString = qs__default["default"].stringify({ ...query,
81
+ const originalQueryString = qs__default["default"].stringify({
82
+ ...query,
87
83
  limit
88
84
  });
89
85
  const enhancedQuery = {
@@ -94,45 +90,42 @@ function process$1(request, fn, processOpt) {
94
90
  } : {})
95
91
  };
96
92
  const enhancedQueryString = qs__default["default"].stringify(enhancedQuery);
97
- const enhancedRequest = { ...request,
93
+ const enhancedRequest = {
94
+ ...request,
98
95
  uri: `${_path}?${enhancedQueryString}&${originalQueryString}`
99
96
  };
100
-
101
97
  try {
102
98
  const payload = await createClient(_options).execute(enhancedRequest);
103
99
  const {
104
100
  results,
105
101
  count: resultsLength
106
102
  } = payload.body;
107
-
108
103
  if (!resultsLength && hasFirstPageBeenProcessed) {
109
104
  return resolve(acc || []);
110
105
  }
111
-
112
106
  const result = await Promise.resolve(fn(payload));
113
107
  let accumulated;
114
108
  hasFirstPageBeenProcessed = true;
115
109
  if (opt.accumulate) accumulated = acc.concat(result || []);
116
- itemsToGet -= resultsLength; // If there are no more items to get, it means the total number
110
+ itemsToGet -= resultsLength;
111
+ // If there are no more items to get, it means the total number
117
112
  // of items in the original request have been fetched so we
118
113
  // resolve the promise.
119
114
  // Also, if we get less results in a page then the limit set it
120
115
  // means that there are no more pages and that we can finally
121
116
  // resolve the promise.
122
-
123
117
  if (resultsLength < query.limit || !itemsToGet) {
124
118
  return resolve(accumulated || []);
125
119
  }
126
-
127
120
  const last = results[resultsLength - 1];
128
121
  const newLastId = last && last.id;
129
122
  processPage(newLastId, accumulated);
130
123
  } catch (error) {
131
124
  reject(error);
132
125
  }
133
- }; // Start iterating through pages
134
-
126
+ };
135
127
 
128
+ // Start iterating through pages
136
129
  processPage();
137
130
  });
138
131
  }
@@ -146,7 +139,6 @@ function createClient(options) {
146
139
  * Given a request object,
147
140
  */
148
141
  process: process$1,
149
-
150
142
  execute(request) {
151
143
  validate('exec', request);
152
144
  return new Promise((resolve, reject) => {
@@ -165,9 +157,9 @@ function createClient(options) {
165
157
  rs.resolve(resObj);
166
158
  }
167
159
  };
168
-
169
160
  const dispatch = compose(...options.middlewares)(resolver);
170
- dispatch(request, // Initial response shape
161
+ dispatch(request,
162
+ // Initial response shape
171
163
  {
172
164
  resolve,
173
165
  reject,
@@ -176,14 +168,12 @@ function createClient(options) {
176
168
  });
177
169
  });
178
170
  }
179
-
180
171
  };
181
172
  }
182
173
 
183
174
  // POST https://{host}/oauth/token?grant_type=client_credentials&scope={scope}
184
175
  // Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
185
176
  const Buffer$1 = require('buffer/').Buffer;
186
-
187
177
  function buildRequestForClientCredentialsFlow(options) {
188
178
  if (!options) throw new Error('Missing required options');
189
179
  if (!options.host) throw new Error('Missing required option (host)');
@@ -195,9 +185,9 @@ function buildRequestForClientCredentialsFlow(options) {
195
185
  } = options.credentials;
196
186
  if (!(clientId && clientSecret)) throw new Error('Missing required credentials (clientId, clientSecret)');
197
187
  const scope = options.scopes ? options.scopes.join(' ') : undefined;
198
- const basicAuth = Buffer$1.from(`${clientId}:${clientSecret}`).toString('base64'); // This is mostly useful for internal testing purposes to be able to check
188
+ const basicAuth = Buffer$1.from(`${clientId}:${clientSecret}`).toString('base64');
189
+ // This is mostly useful for internal testing purposes to be able to check
199
190
  // other oauth endpoints.
200
-
201
191
  const oauthUri = options.oauthUri || '/oauth/token';
202
192
  const url = options.host.replace(/\/$/, '') + oauthUri;
203
193
  const body = `grant_type=client_credentials${scope ? `&scope=${scope}` : ''}`;
@@ -231,10 +221,9 @@ function buildRequestForPasswordFlow(options) {
231
221
  * This is mostly useful for internal testing purposes to be able to check
232
222
  * other oauth endpoints.
233
223
  */
234
-
235
224
  const oauthUri = options.oauthUri || `/oauth/${pKey}/customers/token`;
236
- const url = options.host.replace(/\/$/, '') + oauthUri; // encode username and password as requested by the system
237
-
225
+ const url = options.host.replace(/\/$/, '') + oauthUri;
226
+ // encode username and password as requested by the system
238
227
  const body = `grant_type=password&username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}${scopeStr}`;
239
228
  return {
240
229
  basicAuth,
@@ -253,9 +242,9 @@ function buildRequestForRefreshTokenFlow(options) {
253
242
  clientSecret
254
243
  } = options.credentials;
255
244
  if (!(clientId && clientSecret)) throw new Error('Missing required credentials (clientId, clientSecret)');
256
- const basicAuth = Buffer$1.from(`${clientId}:${clientSecret}`).toString('base64'); // This is mostly useful for internal testing purposes to be able to check
245
+ const basicAuth = Buffer$1.from(`${clientId}:${clientSecret}`).toString('base64');
246
+ // This is mostly useful for internal testing purposes to be able to check
257
247
  // other oauth endpoints.
258
-
259
248
  const oauthUri = options.oauthUri || '/oauth/token';
260
249
  const url = options.host.replace(/\/$/, '') + oauthUri;
261
250
  const body = `grant_type=refresh_token&refresh_token=${encodeURIComponent(options.refreshToken)}`;
@@ -272,25 +261,26 @@ function buildRequestForAnonymousSessionFlow(options) {
272
261
  options.oauthUri = options.oauthUri || `/oauth/${pKey}/anonymous/token`;
273
262
  const result = buildRequestForClientCredentialsFlow(options);
274
263
  if (options.credentials.anonymousId) result.body += `&anonymous_id=${options.credentials.anonymousId}`;
275
- return { ...result
264
+ return {
265
+ ...result
276
266
  };
277
267
  }
278
268
 
279
269
  const Buffer = require('buffer/').Buffer;
280
-
281
270
  function mergeAuthHeader(token, req) {
282
- return { ...req,
283
- headers: { ...req.headers,
271
+ return {
272
+ ...req,
273
+ headers: {
274
+ ...req.headers,
284
275
  Authorization: `Bearer ${token}`
285
276
  }
286
277
  };
287
278
  }
288
-
289
279
  function calculateExpirationTime(expiresIn) {
290
- return Date.now() + // Add a gap of 5 minutes before expiration time.
280
+ return Date.now() +
281
+ // Add a gap of 5 minutes before expiration time.
291
282
  expiresIn * 1000 - 5 * 60 * 1000;
292
283
  }
293
-
294
284
  async function executeRequest({
295
285
  fetcher,
296
286
  url,
@@ -312,27 +302,28 @@ async function executeRequest({
312
302
  },
313
303
  body
314
304
  });
315
-
316
305
  if (_res.ok) {
317
306
  const {
318
307
  access_token: token,
319
308
  expires_in: expiresIn,
320
309
  refresh_token: refreshToken
321
310
  } = await _res.json();
322
- const expirationTime = calculateExpirationTime(expiresIn); // cache new generated token
311
+ const expirationTime = calculateExpirationTime(expiresIn);
323
312
 
313
+ // cache new generated token
324
314
  tokenCache.set({
325
315
  token,
326
316
  expirationTime,
327
317
  refreshToken
328
- }, tokenCacheKey); // Dispatch all pending requests
318
+ }, tokenCacheKey);
329
319
 
320
+ // Dispatch all pending requests
330
321
  requestState.set(false);
322
+
331
323
  /**
332
324
  * Freeze and copy pending queue, reset original one for accepting
333
325
  * new pending tasks
334
326
  */
335
-
336
327
  const executionQueue = pendingTasks.slice();
337
328
  pendingTasks = [];
338
329
  executionQueue.forEach(task => {
@@ -342,31 +333,28 @@ async function executeRequest({
342
333
  * console.log('test', cache, pendingTasks)
343
334
  * Continue by calling the task's own next function
344
335
  */
345
-
346
336
  task.next(requestWithAuth, task.response);
347
337
  });
348
338
  return;
349
- } // Handle error response
350
-
339
+ }
351
340
 
341
+ // Handle error response
352
342
  let parsed;
353
343
  const text = await _res.text();
354
-
355
344
  try {
356
345
  parsed = JSON.parse(text);
357
346
  } catch (error) {
358
347
  /* noop */
359
348
  }
360
-
361
349
  const error = new Error(parsed ? parsed.message : text);
362
350
  if (parsed) error.body = parsed;
351
+
363
352
  /**
364
353
  * to notify that token is either fetched or failed
365
354
  * in the below case token failed to be fetched
366
355
  * and reset requestState to false
367
356
  * so requestState could be shared between multi authMiddlewareBase functions
368
357
  */
369
-
370
358
  requestState.set(false);
371
359
  response.reject(error);
372
360
  } catch (error) {
@@ -380,7 +368,6 @@ async function executeRequest({
380
368
  if (response && typeof response.reject === 'function') response.reject(error);
381
369
  }
382
370
  }
383
-
384
371
  function authMiddlewareBase({
385
372
  request,
386
373
  response,
@@ -394,50 +381,50 @@ function authMiddlewareBase({
394
381
  fetch: fetcher
395
382
  }, next, userOptions) {
396
383
  if (!fetcher && typeof fetch === 'undefined') throw new Error('`fetch` is not available. Please pass in `fetch` as an option or have it globally available.');
397
- if (!fetcher) fetcher = fetch; // Check if there is already a `Authorization` header in the request.
384
+ if (!fetcher) fetcher = fetch;
385
+ // Check if there is already a `Authorization` header in the request.
398
386
  // If so, then go directly to the next middleware.
399
-
400
387
  if (request.headers && request.headers.authorization || request.headers && request.headers.Authorization) {
401
388
  next(request, response);
402
389
  return;
403
- } // If there was a token in the tokenCache, and it's not expired, append
390
+ }
391
+ // If there was a token in the tokenCache, and it's not expired, append
404
392
  // the token in the `Authorization` header.
405
-
406
-
407
393
  const tokenObj = tokenCache.get(tokenCacheKey);
408
-
409
394
  if (tokenObj && tokenObj.token && Date.now() < tokenObj.expirationTime) {
410
395
  const requestWithAuth = mergeAuthHeader(tokenObj.token, request);
411
396
  next(requestWithAuth, response);
412
397
  return;
413
398
  }
399
+
414
400
  /**
415
401
  * Keep pending tasks until a token is fetched
416
402
  * Save next function as well, to call it once the token has been fetched, which prevents
417
403
  * unexpected behaviour in a context in which the next function uses global vars
418
404
  * or Promises to capture the token to hand it to other libraries, e.g. Apollo
419
405
  */
420
-
421
-
422
406
  pendingTasks.push({
423
407
  request,
424
408
  response,
425
409
  next
426
- }); // If a token is currently being fetched, just wait ;)
410
+ });
427
411
 
428
- if (requestState.get()) return; // Mark that a token is being fetched
412
+ // If a token is currently being fetched, just wait ;)
413
+ if (requestState.get()) return;
429
414
 
415
+ // Mark that a token is being fetched
430
416
  requestState.set(true);
417
+
431
418
  /**
432
419
  * If there was a refreshToken in the tokenCache, and there was an expired
433
420
  * token or no token in the tokenCache, use the refreshToken flow
434
421
  */
435
-
436
422
  if (tokenObj && tokenObj.refreshToken && (!tokenObj.token || tokenObj.token && Date.now() > tokenObj.expirationTime)) {
437
423
  if (!userOptions) throw new Error('Missing required options');
438
424
  executeRequest({
439
425
  fetcher,
440
- ...buildRequestForRefreshTokenFlow({ ...userOptions,
426
+ ...buildRequestForRefreshTokenFlow({
427
+ ...userOptions,
441
428
  refreshToken: tokenObj.refreshToken
442
429
  }),
443
430
  tokenCacheKey,
@@ -447,9 +434,9 @@ function authMiddlewareBase({
447
434
  response
448
435
  });
449
436
  return;
450
- } // Token and refreshToken are not present or invalid. Request a new token...
451
-
437
+ }
452
438
 
439
+ // Token and refreshToken are not present or invalid. Request a new token...
453
440
  executeRequest({
454
441
  fetcher,
455
442
  url,
@@ -466,16 +453,18 @@ function authMiddlewareBase({
466
453
  function store(initVal) {
467
454
  let value = initVal;
468
455
  return {
469
- get: () => value,
470
- set: val => {
456
+ get: TokenCacheOption => value,
457
+ set: (val, TokenCacheOption) => {
471
458
  value = val;
472
- return value;
473
459
  }
474
460
  };
475
461
  }
476
462
 
477
463
  function createAuthMiddlewareForAnonymousSessionFlow$1(options) {
478
- const tokenCache = options.tokenCache || store({});
464
+ const tokenCache = options.tokenCache || store({
465
+ token: '',
466
+ expirationTime: -1
467
+ });
479
468
  const pendingTasks = [];
480
469
  const requestState = store(false);
481
470
  return next => (request, response) => {
@@ -485,7 +474,6 @@ function createAuthMiddlewareForAnonymousSessionFlow$1(options) {
485
474
  next(request, response);
486
475
  return;
487
476
  }
488
-
489
477
  const params = {
490
478
  request,
491
479
  response,
@@ -521,7 +509,6 @@ function createAuthMiddlewareForClientCredentialsFlow$1(options) {
521
509
  next(request, response);
522
510
  return;
523
511
  }
524
-
525
512
  const params = {
526
513
  request,
527
514
  response,
@@ -540,17 +527,18 @@ function createAuthMiddlewareWithExistingToken$1(authorization = '', options = {
540
527
  return next => (request, response) => {
541
528
  if (typeof authorization !== 'string') throw new Error('authorization must be a string');
542
529
  const force = options.force === undefined ? true : options.force;
530
+
543
531
  /** The request will not be modified if:
544
532
  * 1. no argument is passed
545
533
  * 2. force is false and authorization header exists
546
534
  */
547
-
548
535
  if (!authorization || (request.headers && request.headers.authorization || request.headers && request.headers.Authorization) && force === false) {
549
536
  return next(request, response);
550
537
  }
551
-
552
- const requestWithAuth = { ...request,
553
- headers: { ...request.headers,
538
+ const requestWithAuth = {
539
+ ...request,
540
+ headers: {
541
+ ...request.headers,
554
542
  Authorization: authorization
555
543
  }
556
544
  };
@@ -569,7 +557,6 @@ function createAuthMiddlewareForPasswordFlow$1(options) {
569
557
  next(request, response);
570
558
  return;
571
559
  }
572
-
573
560
  const params = {
574
561
  request,
575
562
  response,
@@ -584,7 +571,10 @@ function createAuthMiddlewareForPasswordFlow$1(options) {
584
571
  }
585
572
 
586
573
  function createAuthMiddlewareForRefreshTokenFlow$1(options) {
587
- const tokenCache = options.tokenCache || store({});
574
+ const tokenCache = options.tokenCache || store({
575
+ token: '',
576
+ expirationTime: -1
577
+ });
588
578
  const pendingTasks = [];
589
579
  const requestState = store(false);
590
580
  return next => (request, response) => {
@@ -594,7 +584,6 @@ function createAuthMiddlewareForRefreshTokenFlow$1(options) {
594
584
  next(request, response);
595
585
  return;
596
586
  }
597
-
598
587
  const params = {
599
588
  request,
600
589
  response,
@@ -619,8 +608,10 @@ var authMiddlewares = /*#__PURE__*/Object.freeze({
619
608
 
620
609
  function createCorrelationIdMiddleware(options) {
621
610
  return next => (request, response) => {
622
- const nextRequest = { ...request,
623
- headers: { ...request.headers,
611
+ const nextRequest = {
612
+ ...request,
613
+ headers: {
614
+ ...request.headers,
624
615
  'X-Correlation-ID': options.generate()
625
616
  }
626
617
  };
@@ -636,16 +627,11 @@ function defineError(statusCode, message, meta = {}) {
636
627
  this.constructor.prototype.__proto__ = Error.prototype;
637
628
  if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
638
629
  }
639
-
640
630
  function NetworkError(...args) {
641
- defineError.call(this, 0
642
- /* special code to indicate network errors */
643
- , ...args);
631
+ defineError.call(this, 0 /* special code to indicate network errors */, ...args);
644
632
  }
645
633
  function HttpError(...args) {
646
- defineError.call(this,
647
- /* code will be passed as arg */
648
- ...args);
634
+ defineError.call(this, /* code will be passed as arg */...args);
649
635
  }
650
636
  function BadRequest(...args) {
651
637
  defineError.call(this, 400, ...args);
@@ -672,39 +658,34 @@ function getErrorByCode(code) {
672
658
  switch (code) {
673
659
  case 0:
674
660
  return NetworkError;
675
-
676
661
  case 400:
677
662
  return BadRequest;
678
-
679
663
  case 401:
680
664
  return Unauthorized;
681
-
682
665
  case 403:
683
666
  return Forbidden;
684
-
685
667
  case 404:
686
668
  return NotFound;
687
-
688
669
  case 409:
689
670
  return ConcurrentModification;
690
-
691
671
  case 500:
692
672
  return InternalServerError;
693
-
694
673
  case 503:
695
674
  return ServiceUnavailable;
696
-
697
675
  default:
698
676
  return undefined;
699
677
  }
700
678
  }
701
679
 
702
680
  function parseHeaders(headers) {
703
- if (headers.raw) // node-fetch
704
- return headers.raw(); // Tmp fix for Firefox until it supports iterables
681
+ if (headers.raw)
682
+ // node-fetch
683
+ return headers.raw();
705
684
 
706
- if (!headers.forEach) return {}; // whatwg-fetch
685
+ // Tmp fix for Firefox until it supports iterables
686
+ if (!headers.forEach) return {};
707
687
 
688
+ // whatwg-fetch
708
689
  const map = {};
709
690
  headers.forEach((value, name) => {
710
691
  map[name] = value;
@@ -712,10 +693,10 @@ function parseHeaders(headers) {
712
693
  return map;
713
694
  }
714
695
 
696
+ // performs a proper buffer check
715
697
  function isBuffer(obj) {
716
698
  return obj != null && obj.constructor != null && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj);
717
699
  }
718
-
719
700
  function createError({
720
701
  statusCode,
721
702
  message,
@@ -726,23 +707,21 @@ function createError({
726
707
  const ResponseError = getErrorByCode(statusCode);
727
708
  if (ResponseError) return new ResponseError(errorMessage, rest);
728
709
  return new HttpError(statusCode, errorMessage, rest);
729
- } // calculates the delay duration exponentially
730
- // More info about the algorithm use here https://goo.gl/Xk8h5f
731
-
710
+ }
732
711
 
712
+ // calculates the delay duration exponentially
713
+ // More info about the algorithm use here https://goo.gl/Xk8h5f
733
714
  function calcDelayDuration(retryCount, retryDelay, maxRetries, backoff, maxDelay) {
734
715
  if (backoff) return retryCount !== 0 // do not increase if it's the first retry
735
716
  ? Math.min(Math.round((Math.random() + 1) * retryDelay * 2 ** retryCount), maxDelay) : retryDelay;
736
717
  return retryDelay;
737
718
  }
738
-
739
719
  function maskAuthData(request, maskSensitiveHeaderData) {
740
720
  if (maskSensitiveHeaderData) {
741
721
  if (request && request.headers && request.headers.authorization) request.headers.authorization = 'Bearer ********';
742
722
  if (request && request.headers && request.headers.Authorization) request.headers.Authorization = 'Bearer ********';
743
723
  }
744
724
  }
745
-
746
725
  function createHttpMiddleware({
747
726
  host,
748
727
  credentialsMode,
@@ -758,6 +737,8 @@ function createHttpMiddleware({
758
737
  backoff = true,
759
738
  retryDelay = 200,
760
739
  maxDelay = Infinity,
740
+ // If set to true reinitialize the abort controller when the timeout is reached and apply the retry config
741
+ retryOnAbort = false,
761
742
  retryCodes = [503]
762
743
  } = {},
763
744
  fetch: fetcher,
@@ -767,7 +748,6 @@ function createHttpMiddleware({
767
748
  if (!fetcher) throw new Error('`fetch` is not available. Please pass in `fetch` as an option or have it globally available.');
768
749
  if (timeout && !getAbortController) throw new Error('`AbortController` is not available. Please pass in `getAbortController` as an option or have AbortController globally available when using timeout.');
769
750
  let fetchFunction;
770
-
771
751
  if (fetcher) {
772
752
  fetchFunction = fetcher;
773
753
  } else {
@@ -776,71 +756,65 @@ function createHttpMiddleware({
776
756
  // For reference of this pattern: https://github.com/apollographql/apollo-link/blob/498b413a5b5199b0758ce898b3bb55451f57a2fa/packages/apollo-link-http/src/httpLink.ts#L49
777
757
  fetchFunction = fetch;
778
758
  }
779
-
780
759
  if (!Array.isArray(retryCodes)) {
781
760
  throw new Error('`retryCodes` option must be an array of retry status (error) codes.');
782
761
  }
783
-
784
762
  return next => (request, response) => {
785
- let abortController;
786
- if (timeout || getAbortController) abortController = (getAbortController ? getAbortController() : null) || new AbortController();
787
763
  const url = host.replace(/\/$/, '') + request.uri;
788
- const requestHeader = { ...request.headers
789
- }; // Unset the content-type header if explicitly asked to (passing `null` as value).
764
+ const requestHeader = {
765
+ ...request.headers
766
+ };
790
767
 
768
+ // Unset the content-type header if explicitly asked to (passing `null` as value).
791
769
  if (requestHeader['Content-Type'] === null) {
792
770
  delete requestHeader['Content-Type'];
793
771
  }
794
-
795
772
  if (!(Object.prototype.hasOwnProperty.call(requestHeader, 'Content-Type') || Object.prototype.hasOwnProperty.call(requestHeader, 'content-type'))) {
796
773
  requestHeader['Content-Type'] = 'application/json';
797
- } // Ensure body is a string if content type is application/json
798
-
774
+ }
799
775
 
776
+ // Ensure body is a string if content type is application/json
800
777
  const body = ['application/json', 'application/graphql'].indexOf(requestHeader['Content-Type']) > -1 && typeof request.body === 'string' || isBuffer(request.body) ? request.body : JSON.stringify(request.body || undefined);
801
-
802
778
  if (body && (typeof body === 'string' || isBuffer(body))) {
803
779
  requestHeader['Content-Length'] = _.Buffer.byteLength(body).toString();
804
780
  }
805
-
806
781
  const fetchOptions = {
807
782
  method: request.method,
808
783
  headers: requestHeader
809
784
  };
810
-
811
785
  if (credentialsMode) {
812
786
  fetchOptions.credentialsMode = credentialsMode;
813
787
  }
814
-
815
- if (abortController) {
816
- fetchOptions.signal = abortController.signal;
817
- }
818
-
819
788
  if (body) {
820
789
  fetchOptions.body = body;
821
790
  }
822
-
823
- let retryCount = 0; // wrap in a fn so we can retry if error occur
824
-
791
+ let retryCount = 0;
792
+ // wrap in a fn so we can retry if error occur
825
793
  function executeFetch() {
826
794
  // Kick off timer for abortController directly before fetch.
827
795
  let timer;
828
- if (timeout) timer = setTimeout(() => {
829
- abortController.abort();
830
- }, timeout);
796
+ let abortController;
797
+ if (timeout) {
798
+ // Initialize the abort controller in case we do a retry on an aborted request to rest the signal
799
+ abortController = (getAbortController ? getAbortController() : null) || new AbortController();
800
+ fetchOptions.signal = abortController.signal;
801
+ // Set the timer
802
+ timer = setTimeout(() => {
803
+ abortController.abort();
804
+ }, timeout);
805
+ }
831
806
  fetchFunction(url, fetchOptions).then(res => {
832
807
  if (res.ok) {
833
808
  if (fetchOptions.method === 'HEAD') {
834
- next(request, { ...response,
809
+ next(request, {
810
+ ...response,
835
811
  statusCode: res.status
836
812
  });
837
813
  return;
838
814
  }
839
-
840
815
  res.text().then(result => {
841
816
  // Try to parse the response as JSON
842
817
  let parsed;
843
-
844
818
  try {
845
819
  parsed = result.length > 0 ? JSON.parse(result) : {};
846
820
  } catch (err) {
@@ -849,39 +823,35 @@ function createHttpMiddleware({
849
823
  retryCount += 1;
850
824
  return;
851
825
  }
852
-
853
826
  parsed = result;
854
827
  }
855
-
856
- const parsedResponse = { ...response,
828
+ const parsedResponse = {
829
+ ...response,
857
830
  body: parsed,
858
831
  statusCode: res.status
859
832
  };
860
833
  if (includeResponseHeaders) parsedResponse.headers = parseHeaders(res.headers);
861
-
862
834
  if (includeOriginalRequest) {
863
- parsedResponse.request = { ...fetchOptions
835
+ parsedResponse.request = {
836
+ ...fetchOptions
864
837
  };
865
838
  maskAuthData(parsedResponse.request, maskSensitiveHeaderData);
866
839
  }
867
-
868
840
  next(request, parsedResponse);
869
841
  });
870
842
  return;
871
- } // Server responded with an error. Try to parse it as JSON, then
872
- // return a proper error type with all necessary meta information.
873
-
843
+ }
874
844
 
845
+ // Server responded with an error. Try to parse it as JSON, then
846
+ // return a proper error type with all necessary meta information.
875
847
  res.text().then(text => {
876
848
  // Try to parse the error response as JSON
877
849
  let parsed;
878
-
879
850
  try {
880
851
  parsed = JSON.parse(text);
881
852
  } catch (error) {
882
853
  parsed = text;
883
854
  }
884
-
885
855
  const error = createError({
886
856
  statusCode: res.status,
887
857
  ...(includeRequestInErrorResponse ? {
@@ -897,7 +867,6 @@ function createHttpMiddleware({
897
867
  body: parsed
898
868
  })
899
869
  });
900
-
901
870
  if (enableRetry && (retryCodes.indexOf(error.statusCode) !== -1 || (retryCodes === null || retryCodes === void 0 ? void 0 : retryCodes.indexOf(error.message)) !== -1)) {
902
871
  if (retryCount < maxRetries) {
903
872
  setTimeout(executeFetch, calcDelayDuration(retryCount, retryDelay, maxRetries, backoff, maxDelay));
@@ -905,29 +874,35 @@ function createHttpMiddleware({
905
874
  return;
906
875
  }
907
876
  }
908
-
909
- maskAuthData(error.originalRequest, maskSensitiveHeaderData); // Let the final resolver to reject the promise
910
-
911
- const parsedResponse = { ...response,
877
+ maskAuthData(error.originalRequest, maskSensitiveHeaderData);
878
+ // Let the final resolver to reject the promise
879
+ const parsedResponse = {
880
+ ...response,
912
881
  error,
913
882
  statusCode: res.status
914
883
  };
915
884
  next(request, parsedResponse);
916
885
  });
917
- }, // We know that this is a "network" error thrown by the `fetch` library
886
+ },
887
+ // We know that this is a "network" error thrown by the `fetch` library
918
888
  e => {
919
- if (enableRetry) if (retryCount < maxRetries) {
920
- setTimeout(executeFetch, calcDelayDuration(retryCount, retryDelay, maxRetries, backoff, maxDelay));
921
- retryCount += 1;
922
- return;
889
+ // Retry when enabled and either the request was not aborted or retryOnAbort is enabled
890
+ if (enableRetry && (retryOnAbort || !abortController || !abortController.signal)) {
891
+ if (retryCount < maxRetries) {
892
+ setTimeout(executeFetch, calcDelayDuration(retryCount, retryDelay, maxRetries, backoff, maxDelay));
893
+ retryCount += 1;
894
+ return;
895
+ }
923
896
  }
924
- const error = new NetworkError(e.message, { ...(includeRequestInErrorResponse ? {
897
+ const error = new NetworkError(e.message, {
898
+ ...(includeRequestInErrorResponse ? {
925
899
  originalRequest: request
926
900
  } : {}),
927
901
  retryCount
928
902
  });
929
903
  maskAuthData(error.originalRequest, maskSensitiveHeaderData);
930
- next(request, { ...response,
904
+ next(request, {
905
+ ...response,
931
906
  error,
932
907
  statusCode: 0
933
908
  });
@@ -935,7 +910,6 @@ function createHttpMiddleware({
935
910
  clearTimeout(timer);
936
911
  });
937
912
  }
938
-
939
913
  executeFetch();
940
914
  };
941
915
  }
@@ -962,42 +936,41 @@ function createQueueMiddleware({
962
936
  }) {
963
937
  const queue = [];
964
938
  let runningCount = 0;
965
-
966
939
  const dequeue = next => {
967
940
  // We assume here that this task has been completed
968
- runningCount -= 1; // Check if there are any other pending tasks and execute them
941
+ runningCount -= 1;
969
942
 
943
+ // Check if there are any other pending tasks and execute them
970
944
  if (queue.length && runningCount <= concurrency) {
971
945
  const nextTask = queue.shift();
972
946
  runningCount += 1;
973
947
  next(nextTask.request, nextTask.response);
974
948
  }
975
949
  };
976
-
977
950
  return next => (request, response) => {
978
951
  // Override response `resolve` and `reject` to know when the request has
979
952
  // been completed and therefore trigger a pending task in the queue.
980
- const patchedResponse = { ...response,
981
-
953
+ const patchedResponse = {
954
+ ...response,
982
955
  resolve(data) {
983
956
  // Resolve original promise
984
957
  response.resolve(data);
985
958
  dequeue(next);
986
959
  },
987
-
988
960
  reject(error) {
989
961
  // Reject original promise
990
962
  response.reject(error);
991
963
  dequeue(next);
992
964
  }
965
+ };
993
966
 
994
- }; // Add task to the queue
995
-
967
+ // Add task to the queue
996
968
  queue.push({
997
969
  request,
998
970
  response: patchedResponse
999
- }); // If possible, run the task straight away
971
+ });
1000
972
 
973
+ // If possible, run the task straight away
1001
974
  if (runningCount < concurrency) {
1002
975
  const nextTask = queue.shift();
1003
976
  runningCount += 1;
@@ -1008,7 +981,7 @@ function createQueueMiddleware({
1008
981
 
1009
982
  var packageJson = {
1010
983
  name: "@commercetools/sdk-client-v2",
1011
- version: "2.0.2",
984
+ version: "2.1.0",
1012
985
  engines: {
1013
986
  node: ">=14"
1014
987
  },
@@ -1060,7 +1033,7 @@ var packageJson = {
1060
1033
  "abort-controller": "3.0.0",
1061
1034
  "common-tags": "1.8.2",
1062
1035
  dotenv: "16.0.3",
1063
- jest: "29.2.1",
1036
+ jest: "29.3.0",
1064
1037
  nock: "12.0.3",
1065
1038
  "organize-imports-cli": "0.10.0"
1066
1039
  },
@@ -1080,10 +1053,8 @@ var packageJson = {
1080
1053
  the specific test.
1081
1054
  */
1082
1055
  const isBrowser = () => typeof window !== 'undefined' && window.document && window.document.nodeType === 9;
1083
-
1084
1056
  function getSystemInfo() {
1085
1057
  var _process;
1086
-
1087
1058
  if (isBrowser()) return window.navigator.userAgent;
1088
1059
  const nodeVersion = ((_process = process) === null || _process === void 0 ? void 0 : _process.version.slice(1)) || '12'; // temporary fix for rn environment
1089
1060
  // const platformInfo = `(${process.platform}; ${process.arch})`
@@ -1091,31 +1062,38 @@ function getSystemInfo() {
1091
1062
 
1092
1063
  return `node.js/${nodeVersion}`;
1093
1064
  }
1094
-
1095
1065
  function createUserAgent(options) {
1096
- if (!options || Object.keys(options).length === 0 || !{}.hasOwnProperty.call(options, 'name')) throw new Error('Missing required option `name`'); // Main info
1066
+ if (!options || Object.keys(options).length === 0 || !{}.hasOwnProperty.call(options, 'name')) throw new Error('Missing required option `name`');
1097
1067
 
1098
- const baseInfo = options.version ? `${options.name}/${options.version}` : options.name; // Library info
1068
+ // Main info
1069
+ const baseInfo = options.version ? `${options.name}/${options.version}` : options.name;
1099
1070
 
1071
+ // Library info
1100
1072
  let libraryInfo = null;
1101
- if (options.libraryName && !options.libraryVersion) libraryInfo = options.libraryName;else if (options.libraryName && options.libraryVersion) libraryInfo = `${options.libraryName}/${options.libraryVersion}`; // Contact info
1073
+ if (options.libraryName && !options.libraryVersion) libraryInfo = options.libraryName;else if (options.libraryName && options.libraryVersion) libraryInfo = `${options.libraryName}/${options.libraryVersion}`;
1102
1074
 
1075
+ // Contact info
1103
1076
  let contactInfo = null;
1104
- if (options.contactUrl && !options.contactEmail) contactInfo = `(+${options.contactUrl})`;else if (!options.contactUrl && options.contactEmail) contactInfo = `(+${options.contactEmail})`;else if (options.contactUrl && options.contactEmail) contactInfo = `(+${options.contactUrl}; +${options.contactEmail})`; // System info
1077
+ if (options.contactUrl && !options.contactEmail) contactInfo = `(+${options.contactUrl})`;else if (!options.contactUrl && options.contactEmail) contactInfo = `(+${options.contactEmail})`;else if (options.contactUrl && options.contactEmail) contactInfo = `(+${options.contactUrl}; +${options.contactEmail})`;
1105
1078
 
1106
- const systemInfo = getSystemInfo(); // customName
1079
+ // System info
1080
+ const systemInfo = getSystemInfo();
1107
1081
 
1082
+ // customName
1108
1083
  const customAgent = options.customAgent || '';
1109
1084
  return [baseInfo, systemInfo, libraryInfo, contactInfo, customAgent].filter(Boolean).join(' ');
1110
1085
  }
1111
1086
 
1112
1087
  function createUserAgentMiddleware(options) {
1113
- const userAgent = createUserAgent({ ...options,
1088
+ const userAgent = createUserAgent({
1089
+ ...options,
1114
1090
  name: `commercetools-sdk-javascript-v2/${packageJson.version}`
1115
1091
  });
1116
1092
  return next => (request, response) => {
1117
- const requestWithUserAgent = { ...request,
1118
- headers: { ...request.headers,
1093
+ const requestWithUserAgent = {
1094
+ ...request,
1095
+ headers: {
1096
+ ...request.headers,
1119
1097
  'User-Agent': userAgent
1120
1098
  }
1121
1099
  };
@@ -1133,27 +1111,18 @@ const {
1133
1111
  class ClientBuilder {
1134
1112
  constructor() {
1135
1113
  _defineProperty(this, "projectKey", void 0);
1136
-
1137
1114
  _defineProperty(this, "authMiddleware", void 0);
1138
-
1139
1115
  _defineProperty(this, "httpMiddleware", void 0);
1140
-
1141
1116
  _defineProperty(this, "userAgentMiddleware", void 0);
1142
-
1143
1117
  _defineProperty(this, "correlationIdMiddleware", void 0);
1144
-
1145
1118
  _defineProperty(this, "loggerMiddleware", void 0);
1146
-
1147
1119
  _defineProperty(this, "queueMiddleware", void 0);
1148
-
1149
1120
  _defineProperty(this, "middlewares", []);
1150
1121
  }
1151
-
1152
1122
  withProjectKey(key) {
1153
1123
  this.projectKey = key;
1154
1124
  return this;
1155
1125
  }
1156
-
1157
1126
  defaultClient(baseUri, credentials, oauthUri, projectKey) {
1158
1127
  return this.withClientCredentialsFlow({
1159
1128
  host: oauthUri,
@@ -1164,17 +1133,14 @@ class ClientBuilder {
1164
1133
  fetch: fetch__default["default"]
1165
1134
  }).withLoggerMiddleware();
1166
1135
  }
1167
-
1168
1136
  withAuthMiddleware(authMiddleware) {
1169
1137
  this.authMiddleware = authMiddleware;
1170
1138
  return this;
1171
1139
  }
1172
-
1173
1140
  withMiddleware(middleware) {
1174
1141
  this.middlewares.push(middleware);
1175
1142
  return this;
1176
1143
  }
1177
-
1178
1144
  withClientCredentialsFlow(options) {
1179
1145
  return this.withAuthMiddleware(createAuthMiddlewareForClientCredentialsFlow({
1180
1146
  host: options.host || 'https://auth.europe-west1.gcp.commercetools.com',
@@ -1189,7 +1155,6 @@ class ClientBuilder {
1189
1155
  ...options
1190
1156
  }));
1191
1157
  }
1192
-
1193
1158
  withPasswordFlow(options) {
1194
1159
  return this.withAuthMiddleware(createAuthMiddlewareForPasswordFlow({
1195
1160
  host: options.host || 'https://auth.europe-west1.gcp.commercetools.com',
@@ -1206,7 +1171,6 @@ class ClientBuilder {
1206
1171
  ...options
1207
1172
  }));
1208
1173
  }
1209
-
1210
1174
  withAnonymousSessionFlow(options) {
1211
1175
  return this.withAuthMiddleware(createAuthMiddlewareForAnonymousSessionFlow({
1212
1176
  host: options.host || 'https://auth.europe-west1.gcp.commercetools.com',
@@ -1220,7 +1184,6 @@ class ClientBuilder {
1220
1184
  ...options
1221
1185
  }));
1222
1186
  }
1223
-
1224
1187
  withRefreshTokenFlow(options) {
1225
1188
  return this.withAuthMiddleware(createAuthMiddlewareForRefreshTokenFlow({
1226
1189
  host: options.host || 'https://auth.europe-west1.gcp.commercetools.com',
@@ -1234,14 +1197,12 @@ class ClientBuilder {
1234
1197
  ...options
1235
1198
  }));
1236
1199
  }
1237
-
1238
1200
  withExistingTokenFlow(authorization, options) {
1239
1201
  return this.withAuthMiddleware(createAuthMiddlewareWithExistingToken(authorization, {
1240
1202
  force: options.force || true,
1241
1203
  ...options
1242
1204
  }));
1243
1205
  }
1244
-
1245
1206
  withHttpMiddleware(options) {
1246
1207
  this.httpMiddleware = createHttpMiddleware({
1247
1208
  host: options.host || 'https://api.europe-west1.gcp.commercetools.com',
@@ -1250,12 +1211,10 @@ class ClientBuilder {
1250
1211
  });
1251
1212
  return this;
1252
1213
  }
1253
-
1254
1214
  withUserAgentMiddleware(options) {
1255
1215
  this.userAgentMiddleware = createUserAgentMiddleware(options);
1256
1216
  return this;
1257
1217
  }
1258
-
1259
1218
  withQueueMiddleware(options) {
1260
1219
  this.queueMiddleware = createQueueMiddleware({
1261
1220
  concurrency: options.concurrency || 20,
@@ -1263,12 +1222,10 @@ class ClientBuilder {
1263
1222
  });
1264
1223
  return this;
1265
1224
  }
1266
-
1267
1225
  withLoggerMiddleware() {
1268
1226
  this.loggerMiddleware = createLoggerMiddleware();
1269
1227
  return this;
1270
1228
  }
1271
-
1272
1229
  withCorrelationIdMiddleware(options) {
1273
1230
  this.correlationIdMiddleware = createCorrelationIdMiddleware({
1274
1231
  generate: options.generate || null,
@@ -1276,7 +1233,6 @@ class ClientBuilder {
1276
1233
  });
1277
1234
  return this;
1278
1235
  }
1279
-
1280
1236
  build() {
1281
1237
  const middlewares = this.middlewares.slice();
1282
1238
  if (this.correlationIdMiddleware) middlewares.push(this.correlationIdMiddleware);
@@ -1289,7 +1245,6 @@ class ClientBuilder {
1289
1245
  middlewares
1290
1246
  });
1291
1247
  }
1292
-
1293
1248
  }
1294
1249
 
1295
1250
  exports.ClientBuilder = ClientBuilder;