@commercetools/sdk-client-v2 1.0.2 → 1.3.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.
@@ -30,13 +30,104 @@ function validate(funcName, request, options = {
30
30
  if (!options.allowedMethods.includes(request.method)) throw new Error(`The "${funcName}" Request object requires a valid method. See https://commercetools.github.io/nodejs/sdk/Glossary.html#clientrequest`);
31
31
  }
32
32
 
33
+ let _options;
34
+
33
35
  function compose(...funcs) {
34
36
  funcs = funcs.filter(func => typeof func === 'function');
35
37
  if (funcs.length === 1) return funcs[0];
36
38
  return funcs.reduce((a, b) => (...args) => a(b(...args)));
37
39
  }
38
40
 
41
+ function process$1(request, fn, processOpt) {
42
+ validate('process', request, {
43
+ allowedMethods: ['GET']
44
+ });
45
+ 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
46
+
47
+ const opt = {
48
+ total: Number.POSITIVE_INFINITY,
49
+ accumulate: true,
50
+ ...processOpt
51
+ };
52
+ return new Promise((resolve, reject) => {
53
+ let _path,
54
+ _queryString = '';
55
+
56
+ if (request && request.uri) {
57
+ const [path, queryString] = request.uri.split('?');
58
+ _path = path;
59
+ _queryString = queryString;
60
+ }
61
+
62
+ const requestQuery = { ...qs.parse(_queryString)
63
+ };
64
+ const query = {
65
+ // defaults
66
+ limit: 20,
67
+ // merge given query params
68
+ ...requestQuery
69
+ };
70
+ let hasFirstPageBeenProcessed = false;
71
+ let itemsToGet = opt.total;
72
+
73
+ const processPage = async (lastId, acc = []) => {
74
+ // Use the lesser value between limit and itemsToGet in query
75
+ const limit = query.limit < itemsToGet ? query.limit : itemsToGet;
76
+ const originalQueryString = qs.stringify({ ...query,
77
+ limit
78
+ });
79
+ const enhancedQuery = {
80
+ sort: 'id asc',
81
+ withTotal: false,
82
+ ...(lastId ? {
83
+ where: `id > "${lastId}"`
84
+ } : {})
85
+ };
86
+ const enhancedQueryString = qs.stringify(enhancedQuery);
87
+ const enhancedRequest = { ...request,
88
+ uri: `${_path}?${enhancedQueryString}&${originalQueryString}`
89
+ };
90
+
91
+ try {
92
+ const payload = await createClient(_options).execute(enhancedRequest);
93
+ const {
94
+ results,
95
+ count: resultsLength
96
+ } = payload.body;
97
+
98
+ if (!resultsLength && hasFirstPageBeenProcessed) {
99
+ return resolve(acc || []);
100
+ }
101
+
102
+ const result = await Promise.resolve(fn(payload));
103
+ let accumulated;
104
+ hasFirstPageBeenProcessed = true;
105
+ if (opt.accumulate) accumulated = acc.concat(result || []);
106
+ itemsToGet -= resultsLength; // If there are no more items to get, it means the total number
107
+ // of items in the original request have been fetched so we
108
+ // resolve the promise.
109
+ // Also, if we get less results in a page then the limit set it
110
+ // means that there are no more pages and that we can finally
111
+ // resolve the promise.
112
+
113
+ if (resultsLength < query.limit || !itemsToGet) {
114
+ return resolve(accumulated || []);
115
+ }
116
+
117
+ const last = results[resultsLength - 1];
118
+ const newLastId = last && last.id;
119
+ processPage(newLastId, accumulated);
120
+ } catch (error) {
121
+ reject(error);
122
+ }
123
+ }; // Start iterating through pages
124
+
125
+
126
+ processPage();
127
+ });
128
+ }
39
129
  function createClient(options) {
130
+ _options = options;
40
131
  if (!options) throw new Error('Missing required options');
41
132
  if (options.middlewares && !Array.isArray(options.middlewares)) throw new Error('Middlewares should be an array');
42
133
  if (!options.middlewares || !Array.isArray(options.middlewares) || !options.middlewares.length) throw new Error('You need to provide at least one middleware');
@@ -44,6 +135,8 @@ function createClient(options) {
44
135
  /**
45
136
  * Given a request object,
46
137
  */
138
+ process: process$1,
139
+
47
140
  execute(request) {
48
141
  validate('exec', request);
49
142
  return new Promise((resolve, reject) => {
@@ -72,95 +165,6 @@ function createClient(options) {
72
165
  error: undefined
73
166
  });
74
167
  });
75
- },
76
-
77
- process(request, fn, processOpt) {
78
- validate('process', request, {
79
- allowedMethods: ['GET']
80
- });
81
- 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
82
-
83
- const opt = {
84
- total: Number.POSITIVE_INFINITY,
85
- accumulate: true,
86
- ...processOpt
87
- };
88
- return new Promise((resolve, reject) => {
89
- let _path,
90
- _queryString = '';
91
-
92
- if (request && request.uri) {
93
- const [path, queryString] = request.uri.split('?');
94
- _path = path;
95
- _queryString = queryString;
96
- }
97
-
98
- const requestQuery = { ...qs.parse(_queryString)
99
- };
100
- const query = {
101
- // defaults
102
- limit: 20,
103
- // merge given query params
104
- ...requestQuery
105
- };
106
- let hasFirstPageBeenProcessed = false;
107
- let itemsToGet = opt.total;
108
-
109
- const processPage = async (lastId, acc = []) => {
110
- // Use the lesser value between limit and itemsToGet in query
111
- const limit = query.limit < itemsToGet ? query.limit : itemsToGet;
112
- const originalQueryString = qs.stringify({ ...query,
113
- limit
114
- });
115
- const enhancedQuery = {
116
- sort: 'id asc',
117
- withTotal: false,
118
- ...(lastId ? {
119
- where: `id > "${lastId}"`
120
- } : {})
121
- };
122
- const enhancedQueryString = qs.stringify(enhancedQuery);
123
- const enhancedRequest = { ...request,
124
- uri: `${_path}?${enhancedQueryString}&${originalQueryString}`
125
- };
126
-
127
- try {
128
- const payload = await this.execute(enhancedRequest);
129
- const {
130
- results,
131
- count: resultsLength
132
- } = payload.body;
133
-
134
- if (!resultsLength && hasFirstPageBeenProcessed) {
135
- return resolve(acc || []);
136
- }
137
-
138
- const result = await Promise.resolve(fn(payload));
139
- let accumulated;
140
- hasFirstPageBeenProcessed = true;
141
- if (opt.accumulate) accumulated = acc.concat(result || []);
142
- itemsToGet -= resultsLength; // If there are no more items to get, it means the total number
143
- // of items in the original request have been fetched so we
144
- // resolve the promise.
145
- // Also, if we get less results in a page then the limit set it
146
- // means that there are no more pages and that we can finally
147
- // resolve the promise.
148
-
149
- if (resultsLength < query.limit || !itemsToGet) {
150
- return resolve(accumulated || []);
151
- }
152
-
153
- const last = results[resultsLength - 1];
154
- const newLastId = last && last.id;
155
- processPage(newLastId, accumulated);
156
- } catch (error) {
157
- reject(error);
158
- }
159
- }; // Start iterating through pages
160
-
161
-
162
- processPage();
163
- });
164
168
  }
165
169
 
166
170
  };
@@ -740,7 +744,8 @@ function createHttpMiddleware({
740
744
  maxRetries = 10,
741
745
  backoff = true,
742
746
  retryDelay = 200,
743
- maxDelay = Infinity
747
+ maxDelay = Infinity,
748
+ retryCodes = [503]
744
749
  } = {},
745
750
  fetch: fetcher,
746
751
  getAbortController
@@ -758,20 +763,29 @@ function createHttpMiddleware({
758
763
  fetchFunction = fetch;
759
764
  }
760
765
 
766
+ if (!Array.isArray(retryCodes)) {
767
+ throw new Error('`retryCodes` option must be an array of retry status (error) codes.');
768
+ }
769
+
761
770
  return next => (request, response) => {
762
771
  let abortController;
763
772
  if (timeout || getAbortController) abortController = (getAbortController ? getAbortController() : null) || new AbortController();
764
773
  const url = host.replace(/\/$/, '') + request.uri;
765
- const body = typeof request.body === 'string' || Buffer.isBuffer(request.body) ? request.body : // NOTE: `stringify` of `null` gives the String('null')
766
- JSON.stringify(request.body || undefined);
767
774
  const requestHeader = { ...request.headers
768
- };
775
+ }; // Unset the content-type header if explicitly asked to (passing `null` as value).
769
776
 
770
- if (!Object.prototype.hasOwnProperty.call(requestHeader, 'Content-Type')) {
771
- requestHeader['Content-Type'] = 'application/json';
777
+ if (requestHeader['Content-Type'] === null) {
778
+ delete requestHeader['Content-Type'];
772
779
  }
773
780
 
774
- if (body) {
781
+ if (!Object.prototype.hasOwnProperty.call(requestHeader, 'Content-Type') || !Object.prototype.hasOwnProperty.call(requestHeader, 'content-type')) {
782
+ requestHeader['Content-Type'] = 'application/json';
783
+ } // Ensure body is a string if content type is application/json
784
+
785
+
786
+ const body = requestHeader['Content-Type'] === 'application/json' && typeof request.body === 'string' || Buffer.isBuffer(request.body) ? request.body : JSON.stringify(request.body || undefined);
787
+
788
+ if (body && (typeof body === 'string' || Buffer.isBuffer(body))) {
775
789
  requestHeader['Content-Length'] = Buffer.byteLength(body).toString();
776
790
  }
777
791
 
@@ -840,15 +854,25 @@ function createHttpMiddleware({
840
854
  next(request, parsedResponse);
841
855
  });
842
856
  return;
843
- }
844
-
845
- if (res.status === 503 && enableRetry) if (retryCount < maxRetries) {
846
- setTimeout(executeFetch, calcDelayDuration(retryCount, retryDelay, maxRetries, backoff, maxDelay));
847
- retryCount += 1;
848
- return;
849
- } // Server responded with an error. Try to parse it as JSON, then
857
+ } // if (res.status === 503 && enableRetry)
858
+ // if (retryCount < maxRetries) {
859
+ // setTimeout(
860
+ // executeFetch,
861
+ // calcDelayDuration(
862
+ // retryCount,
863
+ // retryDelay,
864
+ // maxRetries,
865
+ // backoff,
866
+ // maxDelay
867
+ // )
868
+ // )
869
+ // retryCount += 1
870
+ // return
871
+ // }
872
+ // Server responded with an error. Try to parse it as JSON, then
850
873
  // return a proper error type with all necessary meta information.
851
874
 
875
+
852
876
  res.text().then(text => {
853
877
  // Try to parse the error response as JSON
854
878
  let parsed;
@@ -872,6 +896,15 @@ function createHttpMiddleware({
872
896
  body: parsed
873
897
  })
874
898
  });
899
+
900
+ if (enableRetry && (retryCodes.indexOf(error.statusCode) !== -1 || (retryCodes === null || retryCodes === void 0 ? void 0 : retryCodes.indexOf(error.message)) !== -1)) {
901
+ if (retryCount < maxRetries) {
902
+ setTimeout(executeFetch, calcDelayDuration(retryCount, retryDelay, maxRetries, backoff, maxDelay));
903
+ retryCount += 1;
904
+ return;
905
+ }
906
+ }
907
+
875
908
  maskAuthData(error.originalRequest, maskSensitiveHeaderData); // Let the final resolver to reject the promise
876
909
 
877
910
  const parsedResponse = { ...response,
@@ -973,7 +1006,7 @@ function createQueueMiddleware({
973
1006
 
974
1007
  var packageJson = {
975
1008
  name: "@commercetools/sdk-client-v2",
976
- version: "1.0.2",
1009
+ version: "1.3.0",
977
1010
  description: "commercetools TypeScript SDK client.",
978
1011
  keywords: [
979
1012
  "commercetools",
@@ -1020,10 +1053,10 @@ var packageJson = {
1020
1053
  devDependencies: {
1021
1054
  "abort-controller": "3.0.0",
1022
1055
  "common-tags": "1.8.2",
1023
- dotenv: "10.0.0",
1024
- jest: "27.3.1",
1056
+ dotenv: "16.0.0",
1057
+ jest: "27.4.7",
1025
1058
  nock: "12.0.3",
1026
- "organize-imports-cli": "0.8.0"
1059
+ "organize-imports-cli": "0.9.0"
1027
1060
  },
1028
1061
  scripts: {
1029
1062
  organize_imports: "find src -type f -name '*.ts' | xargs organize-imports-cli",
@@ -1064,12 +1097,14 @@ function createUserAgent(options) {
1064
1097
  let contactInfo = null;
1065
1098
  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
1066
1099
 
1067
- const systemInfo = getSystemInfo();
1068
- return [baseInfo, systemInfo, libraryInfo, contactInfo].filter(Boolean).join(' ');
1100
+ const systemInfo = getSystemInfo(); // customName
1101
+
1102
+ const customAgent = options.customAgent || '';
1103
+ return [baseInfo, systemInfo, libraryInfo, contactInfo, customAgent].filter(Boolean).join(' ');
1069
1104
  }
1070
1105
 
1071
- function createUserAgentMiddleware() {
1072
- const userAgent = createUserAgent({
1106
+ function createUserAgentMiddleware(options) {
1107
+ const userAgent = createUserAgent({ ...options,
1073
1108
  name: `commercetools-sdk-javascript-v2/${packageJson.version}`
1074
1109
  });
1075
1110
  return next => (request, response) => {
@@ -1210,8 +1245,8 @@ class ClientBuilder {
1210
1245
  return this;
1211
1246
  }
1212
1247
 
1213
- withUserAgentMiddleware() {
1214
- this.userAgentMiddleware = createUserAgentMiddleware();
1248
+ withUserAgentMiddleware(options) {
1249
+ this.userAgentMiddleware = createUserAgentMiddleware(options);
1215
1250
  return this;
1216
1251
  }
1217
1252
 
@@ -1251,4 +1286,4 @@ class ClientBuilder {
1251
1286
 
1252
1287
  }
1253
1288
 
1254
- export { ClientBuilder, createAuthMiddlewareForAnonymousSessionFlow$1 as createAuthForAnonymousSessionFlow, createAuthMiddlewareForClientCredentialsFlow$1 as createAuthForClientCredentialsFlow, createAuthMiddlewareForPasswordFlow$1 as createAuthForPasswordFlow, createAuthMiddlewareForRefreshTokenFlow$1 as createAuthForRefreshTokenFlow, createAuthMiddlewareWithExistingToken$1 as createAuthWithExistingToken, createClient, createCorrelationIdMiddleware, createHttpMiddleware as createHttpClient, createLoggerMiddleware, createQueueMiddleware, createUserAgentMiddleware, getErrorByCode };
1289
+ export { ClientBuilder, process$1 as Process, createAuthMiddlewareForAnonymousSessionFlow$1 as createAuthForAnonymousSessionFlow, createAuthMiddlewareForClientCredentialsFlow$1 as createAuthForClientCredentialsFlow, createAuthMiddlewareForPasswordFlow$1 as createAuthForPasswordFlow, createAuthMiddlewareForRefreshTokenFlow$1 as createAuthForRefreshTokenFlow, createAuthMiddlewareWithExistingToken$1 as createAuthWithExistingToken, createClient, createCorrelationIdMiddleware, createHttpMiddleware as createHttpClient, createLoggerMiddleware, createQueueMiddleware, createUserAgentMiddleware, getErrorByCode };