@commercetools/ts-client 2.0.4 → 2.1.0-alpha.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @commercetools/ts-client
2
2
 
3
+ ## 2.0.5
4
+
5
+ ### Patch Changes
6
+
7
+ - [#807](https://github.com/commercetools/commercetools-sdk-typescript/pull/807) [`dfbe4ce`](https://github.com/commercetools/commercetools-sdk-typescript/commit/dfbe4cec72156668055cd73a05d03abc59749168) Thanks [@ajimae](https://github.com/ajimae)! - Fix concurrency issues in TypeScript v3 SDK
8
+
3
9
  ## 2.0.4
4
10
 
5
11
  ### Patch Changes
@@ -5,7 +5,6 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var fetch$1 = require('node-fetch');
6
6
  var uuid = require('uuid');
7
7
  var _ = require('buffer/');
8
- var asyncMutex = require('async-mutex');
9
8
  var AbortController = require('abort-controller');
10
9
 
11
10
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
@@ -193,7 +192,7 @@ async function executor(request) {
193
192
  let _response = {};
194
193
  try {
195
194
  _response = await execute();
196
- if (_response.status > 299 && hasResponseRetryCode(retryCodes, _response)) return {
195
+ if (_response.status > 399 && hasResponseRetryCode(retryCodes, _response)) return {
197
196
  _response,
198
197
  shouldRetry: true
199
198
  };
@@ -456,6 +455,18 @@ function createUserAgent(options) {
456
455
  return [baseInfo, systemInfo, libraryInfo, contactInfo, customAgent].filter(Boolean).join(' ');
457
456
  }
458
457
 
458
+ function responseCache() {
459
+ let val;
460
+ return {
461
+ set(response) {
462
+ val = response;
463
+ },
464
+ get() {
465
+ return val;
466
+ }
467
+ };
468
+ }
469
+
459
470
  /**
460
471
  * validate some essential http options
461
472
  * @param options
@@ -623,6 +634,7 @@ async function executeRequest$1(options) {
623
634
  tokenCache,
624
635
  tokenCacheKey,
625
636
  userOption,
637
+ tokenCacheObject,
626
638
  next
627
639
  } = options;
628
640
  let url = options.url;
@@ -630,20 +642,26 @@ async function executeRequest$1(options) {
630
642
  let basicAuth = options.basicAuth;
631
643
 
632
644
  // get the pending object from option
633
- let pendingTasks = options.pendingTasks;
645
+ // let pendingTasks: Array<Task> = options.pendingTasks
646
+
634
647
  if (!httpClient || typeof 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.');
635
648
 
636
649
  /**
637
650
  * If there is a token in the tokenCache, and it's not
638
651
  * expired, append the token in the `Authorization` header.
639
652
  */
640
- const tokenCacheObject = tokenCache.get(tokenCacheKey);
641
- if (tokenCacheObject && tokenCacheObject.token && Date.now() < tokenCacheObject.expirationTime) {
642
- const requestWithAuth = mergeAuthHeader(tokenCacheObject.token, request);
643
- return {
644
- ...requestWithAuth
645
- };
646
- }
653
+ // const tokenCacheObject = tokenCache.get(tokenCacheKey)
654
+
655
+ // if (
656
+ // tokenCacheObject && tokenCacheObject.token
657
+ // && Date.now() < tokenCacheObject.expirationTime
658
+ // ) {
659
+ // return next(
660
+ // mergeAuthHeader(
661
+ // tokenCacheObject.token, request
662
+ // )
663
+ // );
664
+ // }
647
665
 
648
666
  /**
649
667
  * Keep pending tasks until a token is fetched
@@ -651,10 +669,7 @@ async function executeRequest$1(options) {
651
669
  * unexpected behaviour in a context in which the next function uses global vars
652
670
  * or Promises to capture the token to hand it to other libraries, e.g. Apollo
653
671
  */
654
- pendingTasks.push({
655
- request,
656
- next
657
- });
672
+ // pendingTasks.push({ request, next })
658
673
 
659
674
  /**
660
675
  * use refreshToken flow if there is refresh-token
@@ -712,30 +727,35 @@ async function executeRequest$1(options) {
712
727
  * Freeze and copy pending queue, reset
713
728
  * original one for accepting new pending tasks
714
729
  */
715
- const requestQueue = pendingTasks.slice();
730
+ // const requestQueue = pendingTasks.slice()
716
731
 
717
- // reset pendingTask queue
718
- pendingTasks = [];
719
- if (requestQueue.length === 1) {
720
- return mergeAuthHeader(token, requestQueue.pop().request);
721
- }
732
+ // // reset pendingTask queue
733
+ // pendingTasks = []
722
734
 
723
- // execute all pending tasks if any
724
- for (let i = 0; i < requestQueue.length; i++) {
725
- const task = requestQueue[i];
726
- const requestWithAuth = mergeAuthHeader(token, task.request);
735
+ // if (requestQueue.length === 1) {
736
+ // return mergeAuthHeader(token, requestQueue.pop().request)
737
+ // }
727
738
 
728
- // execute task
729
- task.next(requestWithAuth);
730
- }
731
- return;
739
+ // // execute all pending tasks if any
740
+ // for (let i = 0; i < pendingTasks.length; i++) {
741
+ // const task: Task = pendingTasks[i];
742
+ // const requestWithAuth = mergeAuthHeader(token, task.request)
743
+
744
+ // // execute task
745
+ // // task.next(requestWithAuth)
746
+
747
+ // pendingTasks[i].request = requestWithAuth;
748
+ // }
749
+
750
+ // return pendingTasks;
751
+ return Promise.resolve(true);
732
752
  }
733
753
  const error = new Error(response.data.message ? response.data.message : JSON.stringify(response.data));
734
754
  /**
735
755
  * reject the error immediately
736
756
  * and free up the middleware chain
737
757
  */
738
- request.reject({
758
+ return request.reject({
739
759
  ...request,
740
760
  headers: {
741
761
  ...request.headers
@@ -749,7 +769,7 @@ async function executeRequest$1(options) {
749
769
  }
750
770
  });
751
771
  } catch (error) {
752
- return {
772
+ request.reject({
753
773
  ...request,
754
774
  headers: {
755
775
  ...request.headers
@@ -763,17 +783,19 @@ async function executeRequest$1(options) {
763
783
  body: response
764
784
  }
765
785
  }
766
- };
786
+ });
767
787
  }
768
788
  }
769
789
 
770
790
  function createAuthMiddlewareForAnonymousSessionFlow$1(options) {
771
- const pendingTasks = [];
772
- const requestState = store(false);
791
+ // const pendingTasks: Array<Task> = []
792
+ // const requestState = new Mutex()
773
793
  const tokenCache = options.tokenCache || store({
774
794
  token: '',
775
795
  expirationTime: -1
776
796
  });
797
+ let tokenCacheObject;
798
+ let tokenFetchPromise = null;
777
799
  const tokenCacheKey = buildTokenCacheKey(options);
778
800
  return next => {
779
801
  return async request => {
@@ -782,13 +804,17 @@ function createAuthMiddlewareForAnonymousSessionFlow$1(options) {
782
804
  // move on
783
805
  return next(request);
784
806
  }
807
+ tokenCacheObject = tokenCache.get(tokenCacheKey);
808
+ if (tokenCacheObject && tokenCacheObject.token && Date.now() < tokenCacheObject.expirationTime) {
809
+ return next(mergeAuthHeader(tokenCacheObject.token, request));
810
+ }
785
811
 
786
812
  // prepare request options
787
813
  const requestOptions = {
814
+ // requestState,
815
+ // pendingTasks,
788
816
  request,
789
- requestState,
790
817
  tokenCache,
791
- pendingTasks,
792
818
  tokenCacheKey,
793
819
  httpClient: options.httpClient || fetch__default["default"],
794
820
  ...buildRequestForAnonymousSessionFlow(options),
@@ -796,22 +822,34 @@ function createAuthMiddlewareForAnonymousSessionFlow$1(options) {
796
822
  next
797
823
  };
798
824
 
799
- // make request to coco
800
- const requestWithAuth = await executeRequest$1(requestOptions);
801
- if (requestWithAuth) {
802
- return next(requestWithAuth);
825
+ // If a token is already being fetched, wait for it to finish
826
+ if (tokenFetchPromise) {
827
+ await tokenFetchPromise;
828
+ } else {
829
+ // Otherwise, fetch the token and let others wait for this process to complete
830
+ tokenFetchPromise = executeRequest$1(requestOptions);
831
+ await tokenFetchPromise;
832
+ tokenFetchPromise = null;
833
+ }
834
+
835
+ // Now the token is present in the tokenCache
836
+ tokenCacheObject = tokenCache.get(tokenCacheKey);
837
+ if (tokenCacheObject && tokenCacheObject.token && Date.now() < tokenCacheObject.expirationTime) {
838
+ return next(mergeAuthHeader(tokenCacheObject.token, request));
803
839
  }
804
840
  };
805
841
  };
806
842
  }
807
843
 
808
844
  function createAuthMiddlewareForClientCredentialsFlow$1(options) {
809
- const requestState = new asyncMutex.Mutex();
810
- const pendingTasks = [];
845
+ // const requestState = new Mutex()
846
+ // const pendingTasks: Array<Task> = []
811
847
  const tokenCache = options.tokenCache || store({
812
848
  token: '',
813
849
  expirationTime: -1
814
850
  });
851
+ let tokenCacheObject;
852
+ let tokenFetchPromise = null;
815
853
  const tokenCacheKey = buildTokenCacheKey(options);
816
854
  return next => {
817
855
  return async request => {
@@ -820,30 +858,38 @@ function createAuthMiddlewareForClientCredentialsFlow$1(options) {
820
858
  // move on
821
859
  return next(request);
822
860
  }
861
+ tokenCacheObject = tokenCache.get(tokenCacheKey);
862
+ if (tokenCacheObject && tokenCacheObject.token && Date.now() < tokenCacheObject.expirationTime) {
863
+ return next(mergeAuthHeader(tokenCacheObject.token, request));
864
+ }
823
865
 
824
866
  // prepare request options
825
867
  const requestOptions = {
868
+ // requestState,
869
+ // pendingTasks,
826
870
  request,
827
- requestState,
828
871
  tokenCache,
829
- pendingTasks,
830
872
  tokenCacheKey,
873
+ tokenCacheObject,
831
874
  httpClient: options.httpClient || fetch__default["default"],
832
875
  ...buildRequestForClientCredentialsFlow(options),
833
876
  next
834
877
  };
835
878
 
836
- // make request to coco
837
- let requestWithAuth;
838
- try {
839
- await requestState.acquire();
840
- requestWithAuth = await executeRequest$1(requestOptions);
841
- } finally {
842
- requestState.release();
879
+ // If a token is already being fetched, wait for it to finish
880
+ if (tokenFetchPromise) {
881
+ await tokenFetchPromise;
882
+ } else {
883
+ // Otherwise, fetch the token and let others wait for this process to complete
884
+ tokenFetchPromise = executeRequest$1(requestOptions);
885
+ await tokenFetchPromise;
886
+ tokenFetchPromise = null;
843
887
  }
844
- if (requestWithAuth) {
845
- // make the request and inject the token into the header
846
- return next(requestWithAuth);
888
+
889
+ // Now the token is present in the tokenCache
890
+ tokenCacheObject = tokenCache.get(tokenCacheKey);
891
+ if (tokenCacheObject && tokenCacheObject.token && Date.now() < tokenCacheObject.expirationTime) {
892
+ return next(mergeAuthHeader(tokenCacheObject.token, request));
847
893
  }
848
894
  };
849
895
  };
@@ -880,8 +926,8 @@ function createAuthMiddlewareForPasswordFlow$1(options) {
880
926
  token: '',
881
927
  expirationTime: -1
882
928
  });
883
- const pendingTasks = [];
884
- const requestState = store(false);
929
+ let tokenCacheObject;
930
+ let tokenFetchPromise = null;
885
931
  const tokenCacheKey = buildTokenCacheKey(options);
886
932
  return next => {
887
933
  return async request => {
@@ -889,10 +935,10 @@ function createAuthMiddlewareForPasswordFlow$1(options) {
889
935
  return next(request);
890
936
  }
891
937
  const requestOptions = {
938
+ // requestState,
939
+ // pendingTasks,
892
940
  request,
893
- requestState,
894
941
  tokenCache,
895
- pendingTasks,
896
942
  tokenCacheKey,
897
943
  httpClient: options.httpClient || fetch__default["default"],
898
944
  ...buildRequestForPasswordFlow(options),
@@ -900,10 +946,20 @@ function createAuthMiddlewareForPasswordFlow$1(options) {
900
946
  next
901
947
  };
902
948
 
903
- // make request to coco
904
- const requestWithAuth = await executeRequest$1(requestOptions);
905
- if (requestWithAuth) {
906
- return next(requestWithAuth);
949
+ // If a token is already being fetched, wait for it to finish
950
+ if (tokenFetchPromise) {
951
+ await tokenFetchPromise;
952
+ } else {
953
+ // Otherwise, fetch the token and let others wait for this process to complete
954
+ tokenFetchPromise = executeRequest$1(requestOptions);
955
+ await tokenFetchPromise;
956
+ tokenFetchPromise = null;
957
+ }
958
+
959
+ // Now the token is present in the tokenCache
960
+ tokenCacheObject = tokenCache.get(tokenCacheKey);
961
+ if (tokenCacheObject && tokenCacheObject.token && Date.now() < tokenCacheObject.expirationTime) {
962
+ return next(mergeAuthHeader(tokenCacheObject.token, request));
907
963
  }
908
964
  };
909
965
  };
@@ -914,8 +970,13 @@ function createAuthMiddlewareForRefreshTokenFlow$1(options) {
914
970
  token: '',
915
971
  tokenCacheKey: null
916
972
  });
917
- const pendingTasks = [];
918
- const requestState = store(false);
973
+
974
+ // const pendingTasks: Array<Task> = []
975
+ // const requestState = new Mutex()
976
+
977
+ let tokenCacheObject;
978
+ let tokenFetchPromise = null;
979
+ const tokenCacheKey = buildTokenCacheKey(options);
919
980
  return next => {
920
981
  return async request => {
921
982
  if (request.headers && (request.headers.Authorization || request.headers.authorization)) {
@@ -924,19 +985,29 @@ function createAuthMiddlewareForRefreshTokenFlow$1(options) {
924
985
 
925
986
  // prepare request options
926
987
  const requestOptions = {
988
+ // pendingTasks,
989
+ // requestState,
927
990
  request,
928
- requestState,
929
991
  tokenCache,
930
- pendingTasks,
931
992
  httpClient: options.httpClient || fetch,
932
993
  ...buildRequestForRefreshTokenFlow(options),
933
994
  next
934
995
  };
935
996
 
936
- // make request to coco
937
- const requestWithAuth = await executeRequest$1(requestOptions);
938
- if (requestWithAuth) {
939
- return next(requestWithAuth);
997
+ // If a token is already being fetched, wait for it to finish
998
+ if (tokenFetchPromise) {
999
+ await tokenFetchPromise;
1000
+ } else {
1001
+ // Otherwise, fetch the token and let others wait for this process to complete
1002
+ tokenFetchPromise = executeRequest$1(requestOptions);
1003
+ await tokenFetchPromise;
1004
+ tokenFetchPromise = null;
1005
+ }
1006
+
1007
+ // Now the token is present in the tokenCache
1008
+ tokenCacheObject = tokenCache.get(tokenCacheKey);
1009
+ if (tokenCacheObject && tokenCacheObject.token && Date.now() < tokenCacheObject.expirationTime) {
1010
+ return next(mergeAuthHeader(tokenCacheObject.token, request));
940
1011
  }
941
1012
  };
942
1013
  };
@@ -945,6 +1016,7 @@ function createAuthMiddlewareForRefreshTokenFlow$1(options) {
945
1016
  function createConcurrentModificationMiddleware$1(modifierFunction) {
946
1017
  return next => {
947
1018
  return async request => {
1019
+ request['concurrent'] = true;
948
1020
  const response = await next(request);
949
1021
  if (response.statusCode == 409) {
950
1022
  /**
@@ -952,7 +1024,7 @@ function createConcurrentModificationMiddleware$1(modifierFunction) {
952
1024
  * from the error body and update
953
1025
  * request with the currentVersion
954
1026
  */
955
- const version = response.error.body?.errors?.[0]?.currentVersion;
1027
+ const version = response.error?.body?.errors?.[0]?.currentVersion;
956
1028
 
957
1029
  // update the resource version here
958
1030
  if (version) {
@@ -967,10 +1039,18 @@ function createConcurrentModificationMiddleware$1(modifierFunction) {
967
1039
  version
968
1040
  };
969
1041
  }
970
- return next(request);
1042
+ return next({
1043
+ ...request,
1044
+ response
1045
+ });
971
1046
  }
972
1047
  }
973
- return response;
1048
+ request.continue = true;
1049
+ delete request['concurrent'];
1050
+ return next({
1051
+ ...request,
1052
+ response
1053
+ });
974
1054
  };
975
1055
  };
976
1056
  }
@@ -1009,12 +1089,20 @@ function createErrorMiddleware(options) {
1009
1089
  };
1010
1090
  }
1011
1091
 
1092
+ let result;
1093
+ const cache = responseCache();
1012
1094
  async function executeRequest({
1013
1095
  url,
1014
1096
  httpClient,
1015
1097
  clientOptions
1016
1098
  }) {
1017
1099
  let timer;
1100
+
1101
+ // don't make further api calls
1102
+ if (clientOptions.request['continue']) {
1103
+ delete clientOptions.request['continue'];
1104
+ return cache.get();
1105
+ }
1018
1106
  const {
1019
1107
  timeout,
1020
1108
  request,
@@ -1041,19 +1129,22 @@ async function executeRequest({
1041
1129
  }
1042
1130
  if (response.statusCode >= 200 && response.statusCode < 300) {
1043
1131
  if (clientOptions.method == 'HEAD') {
1044
- return {
1132
+ const _result = {
1045
1133
  body: null,
1046
1134
  statusCode: response.statusCode,
1047
1135
  retryCount: response.retryCount,
1048
1136
  headers: getHeaders(response.headers)
1049
1137
  };
1138
+ cache.set(_result);
1139
+ return _result;
1050
1140
  }
1051
- return {
1141
+ result = {
1052
1142
  body: response.data,
1053
1143
  statusCode: response.statusCode,
1054
1144
  retryCount: response.retryCount,
1055
1145
  headers: getHeaders(response.headers)
1056
1146
  };
1147
+ return result;
1057
1148
  }
1058
1149
  const error = createError({
1059
1150
  message: response?.data?.message || response?.message,
@@ -1073,17 +1164,18 @@ async function executeRequest({
1073
1164
  * handle non-ok (error) response
1074
1165
  * build error body
1075
1166
  */
1076
- return {
1167
+ result = {
1077
1168
  body: response.data,
1078
1169
  code: response.statusCode,
1079
1170
  statusCode: response.statusCode,
1080
1171
  headers: getHeaders(response.headers),
1081
1172
  error
1082
1173
  };
1174
+ return result;
1083
1175
  } catch (e) {
1084
1176
  // We know that this is a network error
1085
1177
  const headers = includeResponseHeaders ? getHeaders(e.response?.headers) : null;
1086
- const statusCode = e.response?.status || e.response?.data0 || 0;
1178
+ const statusCode = e.response?.status || e.response?.data || 0;
1087
1179
  const message = e.response?.data?.message;
1088
1180
  const error = createError({
1089
1181
  statusCode,
@@ -1099,11 +1191,16 @@ async function executeRequest({
1099
1191
  uri: request.uri
1100
1192
  })
1101
1193
  });
1102
- return {
1194
+ result = {
1103
1195
  body: error,
1104
1196
  error
1105
1197
  };
1198
+ return result;
1106
1199
  } finally {
1200
+ /**
1201
+ * finally cache the response
1202
+ */
1203
+ cache.set(result);
1107
1204
  clearTimeout(timer);
1108
1205
  }
1109
1206
  }
@@ -1179,6 +1276,9 @@ function createHttpMiddleware$1(options) {
1179
1276
  clientOptions,
1180
1277
  httpClient
1181
1278
  });
1279
+ if (request['concurrent']) {
1280
+ return response;
1281
+ }
1182
1282
  const responseWithRequest = {
1183
1283
  ...request,
1184
1284
  includeOriginalRequest,
@@ -1252,7 +1352,7 @@ function createQueueMiddleware$1({
1252
1352
 
1253
1353
  var packageJson = {
1254
1354
  name: "@commercetools/ts-client",
1255
- version: "2.0.4",
1355
+ version: "2.1.0-alpha.0",
1256
1356
  engines: {
1257
1357
  node: ">=14"
1258
1358
  },
@@ -1286,14 +1386,16 @@ var packageJson = {
1286
1386
  },
1287
1387
  dependencies: {
1288
1388
  "abort-controller": "3.0.0",
1289
- "async-mutex": "^0.5.0",
1290
1389
  buffer: "^6.0.3",
1291
1390
  "node-fetch": "^2.6.1",
1292
1391
  uuid: "10.0.0"
1293
1392
  },
1294
1393
  files: [
1295
1394
  "dist",
1296
- "CHANGELOG.md"
1395
+ "CHANGELOG.md",
1396
+ "LICENSE",
1397
+ "README.md",
1398
+ "package.json"
1297
1399
  ],
1298
1400
  author: "Chukwuemeka Ajima <meeky.ae@gmail.com>",
1299
1401
  main: "dist/commercetools-ts-client.cjs.js",
@@ -1448,7 +1550,6 @@ function process$1(request, fn, processOpt) {
1448
1550
  function createClient(middlewares) {
1449
1551
  _options = middlewares;
1450
1552
  validateClient(middlewares);
1451
- let _maskSensitiveHeaderData = false;
1452
1553
  const resolver = {
1453
1554
  async resolve(rs) {
1454
1555
  const {
@@ -1461,20 +1562,25 @@ function createClient(middlewares) {
1461
1562
  retryCount,
1462
1563
  ...rest
1463
1564
  } = response;
1464
- _maskSensitiveHeaderData = maskSensitiveHeaderData;
1565
+ // _maskSensitiveHeaderData = maskSensitiveHeaderData
1566
+
1465
1567
  const res = {
1466
1568
  body: null,
1467
1569
  error: null,
1468
1570
  reject: rs.reject,
1469
1571
  resolve: rs.resolve,
1470
1572
  ...rest,
1471
- ...(includeOriginalRequest ? {
1472
- originalRequest: request
1473
- } : {}),
1474
1573
  ...(response?.retryCount ? {
1475
1574
  retryCount: response.retryCount
1575
+ } : {}),
1576
+ ...(includeOriginalRequest ? {
1577
+ originalRequest: maskSensitiveHeaderData ? maskAuthData(request) : request
1476
1578
  } : {})
1477
1579
  };
1580
+ if (res.error) {
1581
+ rs.reject(res.error);
1582
+ }
1583
+ rs.resolve(res);
1478
1584
  return res;
1479
1585
  }
1480
1586
  };
@@ -1483,18 +1589,12 @@ function createClient(middlewares) {
1483
1589
  process: process$1,
1484
1590
  execute(request) {
1485
1591
  validate('exec', request);
1486
- return new Promise((resolve, reject) => {
1487
- dispatch({
1592
+ return new Promise(async (resolve, reject) => {
1593
+ return dispatch({
1488
1594
  reject,
1489
1595
  resolve,
1490
1596
  ...request
1491
- }).then(res => {
1492
- if (res.error) return reject(res.error);
1493
- if (res.originalRequest && _maskSensitiveHeaderData) {
1494
- res.originalRequest = maskAuthData(res.originalRequest);
1495
- }
1496
- resolve(res);
1497
- }).catch(reject);
1597
+ });
1498
1598
  });
1499
1599
  }
1500
1600
  };