@commercetools/ts-client 1.0.0 → 1.1.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.
Files changed (49) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +55 -0
  3. package/dist/commercetools-ts-client.browser.cjs.js +1155 -1141
  4. package/dist/commercetools-ts-client.browser.esm.js +1155 -1140
  5. package/dist/commercetools-ts-client.cjs.d.ts +1 -0
  6. package/dist/commercetools-ts-client.cjs.d.ts.map +1 -0
  7. package/dist/commercetools-ts-client.cjs.dev.js +1155 -1141
  8. package/dist/commercetools-ts-client.cjs.prod.js +1155 -1141
  9. package/dist/commercetools-ts-client.esm.js +1155 -1140
  10. package/dist/declarations/src/client/builder.d.ts +1 -1
  11. package/dist/declarations/src/client/client.d.ts +1 -1
  12. package/dist/declarations/src/client/index.d.ts +2 -3
  13. package/dist/declarations/src/index.d.ts +3 -12
  14. package/dist/declarations/src/middleware/auth-middleware/anonymous-session-flow.d.ts +1 -1
  15. package/dist/declarations/src/middleware/auth-middleware/client-credentials-flow.d.ts +1 -1
  16. package/dist/declarations/src/middleware/auth-middleware/existing-token-flow.d.ts +1 -1
  17. package/dist/declarations/src/middleware/auth-middleware/index.d.ts +5 -5
  18. package/dist/declarations/src/middleware/auth-middleware/password-flow.d.ts +1 -1
  19. package/dist/declarations/src/middleware/auth-middleware/refresh-token-flow.d.ts +1 -1
  20. package/dist/declarations/src/middleware/create-concurrent-modification-middleware.d.ts +1 -1
  21. package/dist/declarations/src/middleware/create-correlation-id-middleware.d.ts +1 -1
  22. package/dist/declarations/src/middleware/create-error-middleware.d.ts +1 -1
  23. package/dist/declarations/src/middleware/create-http-middleware.d.ts +1 -1
  24. package/dist/declarations/src/middleware/create-logger-middleware.d.ts +1 -1
  25. package/dist/declarations/src/middleware/create-queue-middleware.d.ts +1 -1
  26. package/dist/declarations/src/middleware/create-user-agent-middleware.d.ts +1 -1
  27. package/dist/declarations/src/middleware/index.d.ts +8 -8
  28. package/dist/declarations/src/types/types.d.ts +1 -1
  29. package/package.json +4 -4
  30. package/dist/declarations/src/middleware/auth-middleware/auth-request-builder.d.ts +0 -24
  31. package/dist/declarations/src/middleware/auth-middleware/auth-request-executor.d.ts +0 -2
  32. package/dist/declarations/src/utils/constants.d.ts +0 -5
  33. package/dist/declarations/src/utils/createError.d.ts +0 -8
  34. package/dist/declarations/src/utils/errors.d.ts +0 -10
  35. package/dist/declarations/src/utils/executor.d.ts +0 -2
  36. package/dist/declarations/src/utils/generateID.d.ts +0 -1
  37. package/dist/declarations/src/utils/headers.d.ts +0 -2
  38. package/dist/declarations/src/utils/index.d.ts +0 -17
  39. package/dist/declarations/src/utils/isBuffer.d.ts +0 -1
  40. package/dist/declarations/src/utils/maskAuthData.d.ts +0 -2
  41. package/dist/declarations/src/utils/mergeAuthHeader.d.ts +0 -2
  42. package/dist/declarations/src/utils/methods.d.ts +0 -2
  43. package/dist/declarations/src/utils/retryDelay.d.ts +0 -8
  44. package/dist/declarations/src/utils/sleep.d.ts +0 -1
  45. package/dist/declarations/src/utils/tokenCacheKey.d.ts +0 -2
  46. package/dist/declarations/src/utils/tokenExpirationTime.d.ts +0 -1
  47. package/dist/declarations/src/utils/tokenStore.d.ts +0 -2
  48. package/dist/declarations/src/utils/userAgent.d.ts +0 -2
  49. package/dist/declarations/src/utils/validate.d.ts +0 -25
@@ -1,165 +1,121 @@
1
- import qs from 'querystring';
2
- import crytpo from 'crypto';
3
1
  import fetch$1 from 'node-fetch';
2
+ import { v4 } from 'uuid';
4
3
  import { Buffer } from 'buffer/';
5
4
  import AbortController from 'abort-controller';
6
5
 
6
+ function toPrimitive(t, r) {
7
+ if ("object" != typeof t || !t) return t;
8
+ var e = t[Symbol.toPrimitive];
9
+ if (void 0 !== e) {
10
+ var i = e.call(t, r || "default");
11
+ if ("object" != typeof i) return i;
12
+ throw new TypeError("@@toPrimitive must return a primitive value.");
13
+ }
14
+ return ("string" === r ? String : Number)(t);
15
+ }
16
+
17
+ function toPropertyKey(t) {
18
+ var i = toPrimitive(t, "string");
19
+ return "symbol" == typeof i ? i : String(i);
20
+ }
21
+
22
+ function _defineProperty(obj, key, value) {
23
+ key = toPropertyKey(key);
24
+ if (key in obj) {
25
+ Object.defineProperty(obj, key, {
26
+ value: value,
27
+ enumerable: true,
28
+ configurable: true,
29
+ writable: true
30
+ });
31
+ } else {
32
+ obj[key] = value;
33
+ }
34
+ return obj;
35
+ }
36
+
7
37
  const HEADERS_CONTENT_TYPES = ['application/json', 'application/graphql'];
8
38
  const CONCURRENCT_REQUEST = 20;
9
39
  const CTP_API_URL = 'https://api.europe-west1.gcp.commercetools.com';
10
40
  const CTP_AUTH_URL = 'https://auth.europe-west1.gcp.commercetools.com';
11
41
  const DEFAULT_HEADERS = ['content-type', 'access-control-allow-origin', 'access-control-allow-headers', 'access-control-allow-methods', 'access-control-expose-headers', 'access-control-max-ag', 'x-correlation-id', 'server-timing', 'date', 'server', 'transfer-encoding', 'access-control-max-age', 'content-encoding', 'x-envoy-upstream-service-time', 'via', 'alt-svc', 'connection'];
12
42
 
13
- function parse(headers) {
14
- return DEFAULT_HEADERS.reduce((result, key) => {
15
- let val = headers[key] ? headers[key] : typeof headers.get == 'function' ? headers.get(key) : null;
16
- if (val) result[key] = val;
17
- return result;
18
- }, {});
43
+ function DefineError(statusCode, message, meta = {}) {
44
+ // eslint-disable-next-line no-multi-assign
45
+ this.status = this.statusCode = this.code = statusCode;
46
+ this.message = message;
47
+ Object.assign(this, meta);
48
+ this.name = this.constructor.name;
49
+ // eslint-disable-next-line no-proto
50
+ this.constructor.prototype.__proto__ = Error.prototype;
51
+ if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
19
52
  }
20
- function getHeaders(headers) {
21
- if (!headers) return null;
22
-
23
- // node-fetch
24
- if (headers.raw && typeof headers.raw == 'function') return headers.raw();
25
-
26
- // Tmp fix for Firefox until it supports iterables
27
- if (!headers.forEach) return parse(headers);
28
- return headers.forEach((value, name) => value);
53
+ function NetworkError(...args) {
54
+ DefineError.call(this, 0, ...args);
29
55
  }
30
-
31
- function isBuffer(obj) {
32
- return obj != null && obj.constructor != null && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj);
56
+ function HttpError(...args) {
57
+ DefineError.call(this, ...args);
33
58
  }
34
-
35
- function calculateRetryDelay({
36
- retryCount,
37
- retryDelay,
38
- // maxRetries,
39
- backoff,
40
- maxDelay
41
- }) {
42
- if (backoff) {
43
- return retryCount !== 0 // do not increase if it's the first retry
44
- ? Math.min(Math.round((Math.random() + 1) * retryDelay * 2 ** retryCount), maxDelay) : retryDelay;
45
- }
46
- return retryDelay;
59
+ function BadRequest(...args) {
60
+ DefineError.call(this, 400, ...args);
47
61
  }
48
-
49
- // TODO: Polyfill crypto for browsers
50
- function generateID() {
51
- return crytpo.randomBytes(32).toString('base64').replace(/[\/\-=+]/gi, '');
62
+ function Unauthorized(...args) {
63
+ DefineError.call(this, 401, ...args);
52
64
  }
53
-
54
- // import { validateUserAgentOptions } from '../utils'
55
-
56
- /*
57
- This is the easiest way, for this use case, to detect if we're running in
58
- Node.js or in a browser environment. In other cases, this won't be even a
59
- problem as Rollup will provide the correct polyfill in the bundle.
60
- The main advantage by doing it this way is that it allows to easily test
61
- the code running in both environments, by overriding `global.window` in
62
- the specific test.
63
- */
64
- const isBrowser = () => window.document && window.document.nodeType === 9;
65
- function getSystemInfo() {
66
- var _process;
67
- if (isBrowser()) return window.navigator.userAgent;
68
- const nodeVersion = ((_process = process) === null || _process === void 0 ? void 0 : _process.version.slice(1)) || 'unknow'; // unknow environment like React Native etc
69
- const platformInfo = `(${process.platform}; ${process.arch})`;
70
-
71
- // return `node.js/${nodeVersion}`
72
- return `node.js/${nodeVersion} ${platformInfo}`;
65
+ function Forbidden(...args) {
66
+ DefineError.call(this, 403, ...args);
73
67
  }
74
- function createUserAgent(options) {
75
- let libraryInfo = null;
76
- let contactInfo = null;
77
-
78
- // validateUserAgentOptions(options)
79
- if (!options) {
80
- throw new Error('Missing required option `name`');
81
- }
82
-
83
- // Main info
84
- const baseInfo = options.version ? `${options.name}/${options.version}` : options.name;
85
-
86
- // Library info
87
- if (options.libraryName && !options.libraryVersion) {
88
- libraryInfo = options.libraryName;
89
- } else if (options.libraryName && options.libraryVersion) {
90
- libraryInfo = `${options.libraryName}/${options.libraryVersion}`;
91
- }
92
-
93
- // Contact info
94
- if (options.contactUrl && !options.contactEmail) {
95
- contactInfo = `(+${options.contactUrl})`;
96
- } else if (!options.contactUrl && options.contactEmail) {
97
- contactInfo = `(+${options.contactEmail})`;
98
- } else if (options.contactUrl && options.contactEmail) {
99
- contactInfo = `(+${options.contactUrl}; +${options.contactEmail})`;
100
- }
101
-
102
- // System info
103
- const systemInfo = getSystemInfo();
104
-
105
- // customName
106
- const customAgent = options.customAgent || '';
107
- return [baseInfo, systemInfo, libraryInfo, contactInfo, customAgent].filter(Boolean).join(' ');
68
+ function NotFound(...args) {
69
+ DefineError.call(this, 404, ...args);
108
70
  }
109
-
110
- function maskAuthData(request) {
111
- const _request = Object.assign({}, request);
112
- if (_request !== null && _request !== void 0 && _request.headers) {
113
- if (_request.headers.Authorization) {
114
- _request.headers['Authorization'] = 'Bearer ********';
115
- }
116
- if (_request.headers.authorization) {
117
- _request.headers['authorization'] = 'Bearer ********';
118
- }
119
- }
120
- return _request;
71
+ function ConcurrentModification(...args) {
72
+ DefineError.call(this, 409, ...args);
121
73
  }
122
-
123
- function calculateExpirationTime(expiresIn) {
124
- return Date.now() +
125
- // Add a gap of 5 minutes before expiration time.
126
- expiresIn * 1000 - 5 * 60 * 1000;
74
+ function InternalServerError(...args) {
75
+ DefineError.call(this, 500, ...args);
127
76
  }
128
-
129
- function buildTokenCacheKey(options) {
130
- var _options$credentials;
131
- if (!(options !== null && options !== void 0 && (_options$credentials = options.credentials) !== null && _options$credentials !== void 0 && _options$credentials.clientId) || !options.projectKey || !options.host) throw new Error('Missing required options.');
132
- return {
133
- clientId: options.credentials.clientId,
134
- host: options.host,
135
- projectKey: options.projectKey
136
- };
77
+ function ServiceUnavailable(...args) {
78
+ DefineError.call(this, 503, ...args);
137
79
  }
138
-
139
- function store(initVal) {
140
- let value = initVal;
141
- return {
142
- get: TokenCacheOption => value,
143
- set: (val, TokenCacheOption) => {
144
- value = val;
145
- }
146
- };
80
+ function getErrorByCode(code) {
81
+ switch (code) {
82
+ case 0:
83
+ return NetworkError;
84
+ case 400:
85
+ return BadRequest;
86
+ case 401:
87
+ return Unauthorized;
88
+ case 403:
89
+ return Forbidden;
90
+ case 404:
91
+ return NotFound;
92
+ case 409:
93
+ return ConcurrentModification;
94
+ case 500:
95
+ return InternalServerError;
96
+ case 503:
97
+ return ServiceUnavailable;
98
+ default:
99
+ return undefined;
100
+ }
147
101
  }
148
102
 
149
- function mergeAuthHeader(token, req) {
150
- return {
151
- ...req,
152
- headers: {
153
- ...req.headers,
154
- Authorization: `Bearer ${token}`
155
- }
156
- };
103
+ function createError({
104
+ statusCode,
105
+ message,
106
+ ...rest
107
+ }) {
108
+ let errorMessage = message || 'Unexpected non-JSON error response';
109
+ if (statusCode === 404) errorMessage = `URI not found: ${rest.originalRequest?.uri || rest.uri}`;
110
+ const ResponseError = getErrorByCode(statusCode);
111
+ if (ResponseError) return new ResponseError(errorMessage, rest);
112
+ return new HttpError(statusCode, errorMessage, rest);
157
113
  }
158
114
 
159
115
  function predicate(retryCodes, response) {
160
116
  return !
161
117
  // retryCodes.includes(response?.error?.message) ||
162
- [503, ...retryCodes].includes((response === null || response === void 0 ? void 0 : response.status) || (response === null || response === void 0 ? void 0 : response.statusCode));
118
+ [503, ...retryCodes].includes(response?.status || response?.statusCode);
163
119
  }
164
120
  async function executeHttpClientRequest(fetcher, config) {
165
121
  async function sendRequest() {
@@ -270,85 +226,184 @@ async function executor(request) {
270
226
  return data;
271
227
  }
272
228
 
273
- function sleep(ms) {
274
- return new Promise(resolve => {
275
- setTimeout(resolve, ms);
276
- });
229
+ function generateID() {
230
+ return v4();
277
231
  }
278
232
 
279
- var METHODS = ['ACL', 'BIND', 'CHECKOUT', 'CONNECT', 'COPY', 'DELETE', 'GET', 'HEAD', 'LINK', 'LOCK', 'M-SEARCH', 'MERGE', 'MKACTIVITY', 'MKCALENDAR', 'MKCOL', 'MOVE', 'NOTIFY', 'OPTIONS', 'PATCH', 'POST', 'PROPFIND', 'PROPPATCH', 'PURGE', 'PUT', 'REBIND', 'REPORT', 'SEARCH', 'SOURCE', 'SUBSCRIBE', 'TRACE', 'UNBIND', 'UNLINK', 'UNLOCK', 'UNSUBSCRIBE'];
280
-
281
- function DefineError(statusCode, message, meta = {}) {
282
- // eslint-disable-next-line no-multi-assign
283
- this.status = this.statusCode = this.code = statusCode;
284
- this.message = message;
285
- Object.assign(this, meta);
286
- this.name = this.constructor.name;
287
- // eslint-disable-next-line no-proto
288
- this.constructor.prototype.__proto__ = Error.prototype;
289
- if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
290
- }
291
- function NetworkError(...args) {
292
- DefineError.call(this, 0, ...args);
233
+ function parse(headers) {
234
+ return DEFAULT_HEADERS.reduce((result, key) => {
235
+ let val = headers[key] ? headers[key] : typeof headers.get == 'function' ? headers.get(key) : null;
236
+ if (val) result[key] = val;
237
+ return result;
238
+ }, {});
293
239
  }
294
- function HttpError(...args) {
295
- DefineError.call(this, ...args);
240
+ function getHeaders(headers) {
241
+ if (!headers) return null;
242
+
243
+ // node-fetch
244
+ if (headers.raw && typeof headers.raw == 'function') return headers.raw();
245
+
246
+ // Tmp fix for Firefox until it supports iterables
247
+ if (!headers.forEach) return parse(headers);
248
+ return headers.forEach((value, name) => value);
296
249
  }
297
- function BadRequest(...args) {
298
- DefineError.call(this, 400, ...args);
250
+
251
+ function isBuffer(obj) {
252
+ return obj != null && obj.constructor != null && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj);
299
253
  }
300
- function Unauthorized(...args) {
301
- DefineError.call(this, 401, ...args);
254
+
255
+ function maskAuthData(request) {
256
+ const _request = Object.assign({}, request);
257
+ if (_request?.headers) {
258
+ if (_request.headers.Authorization) {
259
+ _request.headers['Authorization'] = 'Bearer ********';
260
+ }
261
+ if (_request.headers.authorization) {
262
+ _request.headers['authorization'] = 'Bearer ********';
263
+ }
264
+ }
265
+ return _request;
302
266
  }
303
- function Forbidden(...args) {
304
- DefineError.call(this, 403, ...args);
267
+
268
+ function mergeAuthHeader(token, req) {
269
+ return {
270
+ ...req,
271
+ headers: {
272
+ ...req.headers,
273
+ Authorization: `Bearer ${token}`
274
+ }
275
+ };
305
276
  }
306
- function NotFound(...args) {
307
- DefineError.call(this, 404, ...args);
277
+
278
+ var METHODS = ['ACL', 'BIND', 'CHECKOUT', 'CONNECT', 'COPY', 'DELETE', 'GET', 'HEAD', 'LINK', 'LOCK', 'M-SEARCH', 'MERGE', 'MKACTIVITY', 'MKCALENDAR', 'MKCOL', 'MOVE', 'NOTIFY', 'OPTIONS', 'PATCH', 'POST', 'PROPFIND', 'PROPPATCH', 'PURGE', 'PUT', 'REBIND', 'REPORT', 'SEARCH', 'SOURCE', 'SUBSCRIBE', 'TRACE', 'UNBIND', 'UNLINK', 'UNLOCK', 'UNSUBSCRIBE'];
279
+
280
+ function calculateRetryDelay({
281
+ retryCount,
282
+ retryDelay,
283
+ // maxRetries,
284
+ backoff,
285
+ maxDelay
286
+ }) {
287
+ if (backoff) {
288
+ return retryCount !== 0 // do not increase if it's the first retry
289
+ ? Math.min(Math.round((Math.random() + 1) * retryDelay * 2 ** retryCount), maxDelay) : retryDelay;
290
+ }
291
+ return retryDelay;
308
292
  }
309
- function ConcurrentModification(...args) {
310
- DefineError.call(this, 409, ...args);
293
+
294
+ function sleep(ms) {
295
+ return new Promise(resolve => {
296
+ setTimeout(resolve, ms);
297
+ });
311
298
  }
312
- function InternalServerError(...args) {
313
- DefineError.call(this, 500, ...args);
299
+
300
+ function buildTokenCacheKey(options) {
301
+ if (!options?.credentials?.clientId || !options.projectKey || !options.host) throw new Error('Missing required options.');
302
+ return {
303
+ clientId: options.credentials.clientId,
304
+ host: options.host,
305
+ projectKey: options.projectKey
306
+ };
314
307
  }
315
- function ServiceUnavailable(...args) {
316
- DefineError.call(this, 503, ...args);
308
+
309
+ function calculateExpirationTime(expiresIn) {
310
+ return Date.now() +
311
+ // Add a gap of 5 minutes before expiration time.
312
+ expiresIn * 1000 - 5 * 60 * 1000;
317
313
  }
318
- function getErrorByCode(code) {
319
- switch (code) {
320
- case 0:
321
- return NetworkError;
322
- case 400:
323
- return BadRequest;
324
- case 401:
325
- return Unauthorized;
326
- case 403:
327
- return Forbidden;
328
- case 404:
329
- return NotFound;
330
- case 409:
331
- return ConcurrentModification;
332
- case 500:
333
- return InternalServerError;
334
- case 503:
335
- return ServiceUnavailable;
336
- default:
337
- return undefined;
314
+
315
+ function store(initVal) {
316
+ let value = initVal;
317
+ return {
318
+ get: TokenCacheOption => value,
319
+ set: (val, TokenCacheOption) => {
320
+ value = val;
321
+ }
322
+ };
323
+ }
324
+
325
+ function urlParser(url) {
326
+ const object = {};
327
+ const data = new URLSearchParams(url);
328
+ for (let x of data.keys()) {
329
+ if (data.getAll(x).length > 1) {
330
+ object[x] = data.getAll(x);
331
+ } else {
332
+ object[x] = data.get(x);
333
+ }
334
+ }
335
+ return object;
336
+ }
337
+ function urlStringifier(object) {
338
+ const params = new URLSearchParams(object);
339
+ for (const [key, value] of Object.entries(object)) {
340
+ if (Array.isArray(value)) {
341
+ params.delete(key);
342
+ value.filter(Boolean).forEach(v => params.append(key, v));
343
+ }
338
344
  }
345
+ return params.toString();
346
+ }
347
+ function parseURLString(url, parser = urlParser) {
348
+ return parser(url);
349
+ }
350
+ function stringifyURLString(object, stringifier = urlStringifier) {
351
+ return urlStringifier(object);
339
352
  }
340
353
 
341
- function createError({
342
- statusCode,
343
- message,
344
- ...rest
345
- }) {
346
- var _rest$originalRequest;
347
- let errorMessage = message || 'Unexpected non-JSON error response';
348
- if (statusCode === 404) errorMessage = `URI not found: ${((_rest$originalRequest = rest.originalRequest) === null || _rest$originalRequest === void 0 ? void 0 : _rest$originalRequest.uri) || rest.uri}`;
349
- const ResponseError = getErrorByCode(statusCode);
350
- if (ResponseError) return new ResponseError(errorMessage, rest);
351
- return new HttpError(statusCode, errorMessage, rest);
354
+ // import { validateUserAgentOptions } from '../utils'
355
+
356
+ /*
357
+ This is the easiest way, for this use case, to detect if we're running in
358
+ Node.js or in a browser environment. In other cases, this won't be even a
359
+ problem as Rollup will provide the correct polyfill in the bundle.
360
+ The main advantage by doing it this way is that it allows to easily test
361
+ the code running in both environments, by overriding `global.window` in
362
+ the specific test.
363
+ */
364
+ const isBrowser = () => window.document && window.document.nodeType === 9;
365
+ function getSystemInfo() {
366
+ if (isBrowser()) return window.navigator.userAgent;
367
+ const nodeVersion = process?.version.slice(1) || 'unknow'; // unknow environment like React Native etc
368
+ const platformInfo = `(${process.platform}; ${process.arch})`;
369
+
370
+ // return `node.js/${nodeVersion}`
371
+ return `node.js/${nodeVersion} ${platformInfo}`;
372
+ }
373
+ function createUserAgent(options) {
374
+ let libraryInfo = null;
375
+ let contactInfo = null;
376
+
377
+ // validateUserAgentOptions(options)
378
+ if (!options) {
379
+ throw new Error('Missing required option `name`');
380
+ }
381
+
382
+ // Main info
383
+ const baseInfo = options.version ? `${options.name}/${options.version}` : options.name;
384
+
385
+ // Library info
386
+ if (options.libraryName && !options.libraryVersion) {
387
+ libraryInfo = options.libraryName;
388
+ } else if (options.libraryName && options.libraryVersion) {
389
+ libraryInfo = `${options.libraryName}/${options.libraryVersion}`;
390
+ }
391
+
392
+ // Contact info
393
+ if (options.contactUrl && !options.contactEmail) {
394
+ contactInfo = `(+${options.contactUrl})`;
395
+ } else if (!options.contactUrl && options.contactEmail) {
396
+ contactInfo = `(+${options.contactEmail})`;
397
+ } else if (options.contactUrl && options.contactEmail) {
398
+ contactInfo = `(+${options.contactUrl}; +${options.contactEmail})`;
399
+ }
400
+
401
+ // System info
402
+ const systemInfo = getSystemInfo();
403
+
404
+ // customName
405
+ const customAgent = options.customAgent || '';
406
+ return [baseInfo, systemInfo, libraryInfo, contactInfo, customAgent].filter(Boolean).join(' ');
352
407
  }
353
408
 
354
409
  /**
@@ -395,1055 +450,1015 @@ function validate(funcName, request, options = {
395
450
  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`);
396
451
  }
397
452
 
398
- function compose({
399
- middlewares
400
- }) {
401
- if (middlewares.length === 1) return middlewares[0];
402
- const _middlewares = middlewares.slice();
403
- return _middlewares.reduce((ac, cv) => (...args) => ac(cv.apply(null, args)));
453
+ /**
454
+ *
455
+ * @param {AuthMiddlewareOptions} options
456
+ * @returns { IBuiltRequestParams } *
457
+ */
458
+ function buildRequestForClientCredentialsFlow(options) {
459
+ // Validate options
460
+ if (!options) throw new Error('Missing required options');
461
+ if (!options.host) throw new Error('Missing required option (host)');
462
+ if (!options.projectKey) throw new Error('Missing required option (projectKey)');
463
+ if (!options.credentials) throw new Error('Missing required option (credentials)');
464
+ const {
465
+ clientId,
466
+ clientSecret
467
+ } = options.credentials || {};
468
+ if (!(clientId && clientSecret)) throw new Error('Missing required credentials (clientId, clientSecret)');
469
+ const scope = options.scopes ? options.scopes.join(' ') : undefined;
470
+ const basicAuth = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
471
+ // This is mostly useful for internal testing purposes to be able to check
472
+ // other oauth endpoints.
473
+ const oauthUri = options.oauthUri || '/oauth/token';
474
+ const url = options.host.replace(/\/$/, '') + oauthUri;
475
+ const body = `grant_type=client_credentials${scope ? `&scope=${scope}` : ''}`;
476
+ return {
477
+ url,
478
+ body,
479
+ basicAuth
480
+ };
404
481
  }
405
482
 
406
- // process batch requests
407
- let _options;
408
- function process$1(request, fn, processOpt) {
409
- validate('process', request, {
410
- allowedMethods: ['GET']
411
- });
412
- 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');
483
+ /**
484
+ *
485
+ * @param {AuthMiddlewareOptions} options
486
+ * @returns {IBuiltRequestParams} *
487
+ */
488
+ function buildRequestForAnonymousSessionFlow(options) {
489
+ if (!options) throw new Error('Missing required options');
490
+ if (!options.projectKey) throw new Error('Missing required option (projectKey)');
491
+ const projectKey = options.projectKey;
492
+ options.oauthUri = options.oauthUri || `/oauth/${projectKey}/anonymous/token`;
493
+ const result = buildRequestForClientCredentialsFlow(options);
494
+ if (options.credentials.anonymousId) result.body += `&anonymous_id=${options.credentials.anonymousId}`;
495
+ return {
496
+ ...result
497
+ };
498
+ }
413
499
 
414
- // Set default process options
415
- const opt = {
416
- total: Number.POSITIVE_INFINITY,
417
- accumulate: true,
418
- ...processOpt
500
+ /**
501
+ *
502
+ * @param {RefreshAuthMiddlewareOptions} options
503
+ * @returns {IBuiltRequestParams}
504
+ */
505
+ function buildRequestForRefreshTokenFlow(options) {
506
+ if (!options) throw new Error('Missing required options');
507
+ if (!options.host) throw new Error('Missing required option (host)');
508
+ if (!options.projectKey) throw new Error('Missing required option (projectKey)');
509
+ if (!options.credentials) throw new Error('Missing required option (credentials)');
510
+ if (!options.refreshToken) throw new Error('Missing required option (refreshToken)');
511
+ const {
512
+ clientId,
513
+ clientSecret
514
+ } = options.credentials;
515
+ if (!(clientId && clientSecret)) throw new Error('Missing required credentials (clientId, clientSecret)');
516
+ const basicAuth = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
517
+ // This is mostly useful for internal testing purposes to be able to check
518
+ // other oauth endpoints.
519
+ const oauthUri = options.oauthUri || '/oauth/token';
520
+ const url = options.host.replace(/\/$/, '') + oauthUri;
521
+ const body = `grant_type=refresh_token&refresh_token=${encodeURIComponent(options.refreshToken)}`;
522
+ return {
523
+ basicAuth,
524
+ url,
525
+ body
419
526
  };
420
- return new Promise((resolve, reject) => {
421
- let _path,
422
- _queryString = '';
423
- if (request && request.uri) {
424
- const [path, queryString] = request.uri.split('?');
425
- _path = path;
426
- _queryString = queryString;
427
- }
428
- const requestQuery = {
429
- ...qs.parse(_queryString)
430
- };
431
- const query = {
432
- // defaults
433
- limit: 20,
434
- // merge given query params
435
- ...requestQuery
436
- };
437
- let itemsToGet = opt.total;
438
- let hasFirstPageBeenProcessed = false;
439
- const processPage = async (lastId, acc = []) => {
440
- // Use the lesser value between limit and itemsToGet in query
441
- const limit = query.limit < itemsToGet ? query.limit : itemsToGet;
442
- const originalQueryString = qs.stringify({
443
- ...query,
444
- limit
445
- });
446
- const enhancedQuery = {
447
- sort: 'id asc',
448
- withTotal: false,
449
- ...(lastId ? {
450
- where: `id > "${lastId}"`
451
- } : {})
452
- };
453
- const enhancedQueryString = qs.stringify(enhancedQuery);
454
- const enhancedRequest = {
455
- ...request,
456
- uri: `${_path}?${enhancedQueryString}&${originalQueryString}`
457
- };
458
- try {
459
- const payload = await createClient(_options).execute(enhancedRequest);
460
- const {
461
- results,
462
- count: resultsLength
463
- } = (payload === null || payload === void 0 ? void 0 : payload.body) || {};
464
- if (!resultsLength && hasFirstPageBeenProcessed) {
465
- return resolve(acc || []);
466
- }
467
- const result = await Promise.resolve(fn(payload));
468
- let accumulated;
469
- hasFirstPageBeenProcessed = true;
470
- if (opt.accumulate) accumulated = acc.concat(result || []);
471
- itemsToGet -= resultsLength;
472
- // If there are no more items to get, it means the total number
473
- // of items in the original request have been fetched so we
474
- // resolve the promise.
475
- // Also, if we get less results in a page then the limit set it
476
- // means that there are no more pages and that we can finally
477
- // resolve the promise.
478
- if (resultsLength < query.limit || !itemsToGet) {
479
- return resolve(accumulated || []);
480
- }
481
- const last = results[resultsLength - 1];
482
- const newLastId = last && last.id;
483
- processPage(newLastId, accumulated);
484
- } catch (error) {
485
- reject(error);
486
- }
487
- };
488
-
489
- // Start iterating through pages
490
- processPage();
491
- });
492
- }
493
- function createClient(middlewares) {
494
- _options = middlewares;
495
- validateClient(middlewares);
496
- const resolver = {
497
- async resolve(rs) {
498
- const {
499
- response,
500
- includeOriginalRequest,
501
- maskSensitiveHeaderData,
502
- ...request
503
- } = rs;
504
- const {
505
- retryCount,
506
- ...rest
507
- } = response;
508
- const res = {
509
- body: null,
510
- error: null,
511
- reject: rs.reject,
512
- resolve: rs.resolve,
513
- ...rest,
514
- ...(includeOriginalRequest ? {
515
- originalRequest: maskSensitiveHeaderData ? maskAuthData(request) : request
516
- } : {}),
517
- ...(response !== null && response !== void 0 && response.retryCount ? {
518
- retryCount: response.retryCount
519
- } : {})
520
- };
521
- if (res.error) {
522
- res.reject(res.error);
523
- return res;
524
- }
525
- res.resolve(res);
526
- return res;
527
- }
528
- };
529
- const dispatch = compose(middlewares)(resolver.resolve);
530
- return {
531
- process: process$1,
532
- execute(request) {
533
- validate('exec', request);
534
- return new Promise((resolve, reject) => {
535
- return dispatch({
536
- reject,
537
- resolve,
538
- ...request
539
- });
540
- });
541
- }
542
- };
543
- }
544
-
545
- function _toPrimitive(input, hint) {
546
- if (typeof input !== "object" || input === null) return input;
547
- var prim = input[Symbol.toPrimitive];
548
- if (prim !== undefined) {
549
- var res = prim.call(input, hint || "default");
550
- if (typeof res !== "object") return res;
551
- throw new TypeError("@@toPrimitive must return a primitive value.");
552
- }
553
- return (hint === "string" ? String : Number)(input);
554
527
  }
555
528
 
556
- function _toPropertyKey(arg) {
557
- var key = _toPrimitive(arg, "string");
558
- return typeof key === "symbol" ? key : String(key);
559
- }
529
+ /**
530
+ * @param {PasswordAuthMiddlewareOptions} options
531
+ * @returns {IBuiltRequestParams}
532
+ */
533
+ function buildRequestForPasswordFlow(options) {
534
+ if (!options) throw new Error('Missing required options');
535
+ if (!options.host) throw new Error('Missing required option (host)');
536
+ if (!options.projectKey) throw new Error('Missing required option (projectKey)');
537
+ if (!options.credentials) throw new Error('Missing required option (credentials)');
538
+ const {
539
+ clientId,
540
+ clientSecret,
541
+ user
542
+ } = options.credentials;
543
+ const projectKey = options.projectKey;
544
+ if (!(clientId && clientSecret && user)) throw new Error('Missing required credentials (clientId, clientSecret, user)');
545
+ const {
546
+ username,
547
+ password
548
+ } = user;
549
+ if (!(username && password)) throw new Error('Missing required user credentials (username, password)');
550
+ const scope = (options.scopes || []).join(' ');
551
+ const scopeStr = scope ? `&scope=${scope}` : '';
552
+ const basicAuth = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
560
553
 
561
- function _defineProperty(obj, key, value) {
562
- key = _toPropertyKey(key);
563
- if (key in obj) {
564
- Object.defineProperty(obj, key, {
565
- value: value,
566
- enumerable: true,
567
- configurable: true,
568
- writable: true
569
- });
570
- } else {
571
- obj[key] = value;
572
- }
573
- return obj;
574
- }
554
+ /**
555
+ * This is mostly useful for internal testing purposes to be able to check
556
+ * other oauth endpoints.
557
+ */
558
+ const oauthUri = options.oauthUri || `/oauth/${projectKey}/customers/token`;
559
+ const url = options.host.replace(/\/$/, '') + oauthUri;
575
560
 
576
- function createCorrelationIdMiddleware$1(options) {
577
- return next => request => {
578
- const nextRequest = {
579
- ...request,
580
- headers: {
581
- ...request.headers,
582
- 'X-Correlation-ID': options.generate && typeof options.generate == 'function' ? options.generate() : generateID()
583
- }
584
- };
585
- return next(nextRequest);
561
+ // encode username and password as requested by the system
562
+ const body = `grant_type=password&username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}${scopeStr}`;
563
+ return {
564
+ basicAuth,
565
+ url,
566
+ body
586
567
  };
587
568
  }
588
569
 
589
- async function executeRequest$1({
590
- url,
591
- httpClient,
592
- clientOptions
593
- }) {
594
- let timer;
570
+ async function executeRequest$1(options) {
595
571
  const {
596
- timeout,
597
572
  request,
598
- abortController,
599
- maskSensitiveHeaderData,
600
- includeRequestInErrorResponse
601
- } = clientOptions;
602
- try {
603
- var _response$data, _response$data2;
604
- if (timeout) timer = setTimeout(() => {
605
- abortController.abort();
606
- }, timeout);
607
- const response = await executor({
608
- url,
609
- ...clientOptions,
610
- httpClient,
611
- method: clientOptions.method,
612
- ...(clientOptions.body ? {
613
- body: clientOptions.body
614
- } : {})
615
- });
616
- if (response.statusCode >= 200 && response.statusCode < 300) {
617
- if (clientOptions.method == 'HEAD') {
618
- return {
619
- body: null,
620
- statusCode: response.statusCode,
621
- retryCount: response.retryCount,
622
- headers: getHeaders(response.headers)
623
- };
624
- }
625
- return {
626
- body: response.data,
627
- statusCode: response.statusCode,
628
- retryCount: response.retryCount,
629
- headers: getHeaders(response.headers)
630
- };
631
- }
632
- const error = createError({
633
- message: (response === null || response === void 0 ? void 0 : (_response$data = response.data) === null || _response$data === void 0 ? void 0 : _response$data.message) || (response === null || response === void 0 ? void 0 : response.message),
634
- statusCode: response.statusCode || (response === null || response === void 0 ? void 0 : (_response$data2 = response.data) === null || _response$data2 === void 0 ? void 0 : _response$data2.statusCode),
635
- headers: getHeaders(response.headers),
636
- method: clientOptions.method,
637
- body: response.data,
638
- retryCount: response.retryCount,
639
- ...(includeRequestInErrorResponse ? {
640
- originalRequest: maskSensitiveHeaderData ? maskAuthData(request) : request
641
- } : {
642
- uri: request.uri
643
- })
644
- });
573
+ httpClient,
574
+ tokenCache,
575
+ tokenCacheKey,
576
+ requestState,
577
+ userOption,
578
+ next
579
+ } = options;
580
+ let url = options.url;
581
+ let body = options.body;
582
+ let basicAuth = options.basicAuth;
645
583
 
646
- /**
647
- * handle non-ok (error) response
648
- * build error body
649
- */
650
- return {
651
- body: response.data,
652
- code: response.statusCode,
653
- statusCode: response.statusCode,
654
- headers: getHeaders(response.headers),
655
- error
656
- };
657
- } catch (e) {
658
- var _e$response, _e$response2, _e$response3, _e$response4, _e$response4$data, _e$response5, _e$response6;
659
- // We know that this is a network error
660
- const headers = getHeaders((_e$response = e.response) === null || _e$response === void 0 ? void 0 : _e$response.headers);
661
- const statusCode = ((_e$response2 = e.response) === null || _e$response2 === void 0 ? void 0 : _e$response2.status) || ((_e$response3 = e.response) === null || _e$response3 === void 0 ? void 0 : _e$response3.data0) || 0;
662
- const message = (_e$response4 = e.response) === null || _e$response4 === void 0 ? void 0 : (_e$response4$data = _e$response4.data) === null || _e$response4$data === void 0 ? void 0 : _e$response4$data.message;
663
- const error = createError({
664
- statusCode,
665
- code: statusCode,
666
- status: statusCode,
667
- message: message || e.message,
668
- headers,
669
- body: ((_e$response5 = e.response) === null || _e$response5 === void 0 ? void 0 : _e$response5.data) || e,
670
- error: (_e$response6 = e.response) === null || _e$response6 === void 0 ? void 0 : _e$response6.data,
671
- ...(includeRequestInErrorResponse ? {
672
- originalRequest: maskSensitiveHeaderData ? maskAuthData(request) : request
673
- } : {
674
- uri: request.uri
675
- })
676
- });
584
+ // get the pending object from option
585
+ let pendingTasks = options.pendingTasks;
586
+ 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.');
587
+
588
+ /**
589
+ * If there is a token in the tokenCache, and it's not
590
+ * expired, append the token in the `Authorization` header.
591
+ */
592
+ const tokenCacheObject = tokenCache.get(tokenCacheKey);
593
+ if (tokenCacheObject && tokenCacheObject.token && Date.now() < tokenCacheObject.expirationTime) {
594
+ const requestWithAuth = mergeAuthHeader(tokenCacheObject.token, request);
677
595
  return {
678
- body: error,
679
- error
596
+ ...requestWithAuth
680
597
  };
681
- } finally {
682
- clearTimeout(timer);
683
598
  }
684
- }
685
- function createHttpMiddleware$1(options) {
686
- // validate response
687
- validateHttpOptions(options);
688
- const {
689
- host,
690
- credentialsMode,
691
- httpClient,
692
- timeout,
693
- enableRetry,
694
- retryConfig,
695
- getAbortController,
696
- includeOriginalRequest,
697
- includeRequestInErrorResponse,
698
- maskSensitiveHeaderData,
699
- httpClientOptions
700
- } = options;
701
- return next => {
702
- return async request => {
703
- let abortController;
704
- if (timeout || getAbortController) abortController = (getAbortController ? getAbortController() : null) || new AbortController();
705
- const url = host.replace(/\/$/, '') + request.uri;
706
- const requestHeader = {
707
- ...request.headers
708
- };
709
599
 
710
- // validate header
711
- if (!(Object.prototype.hasOwnProperty.call(requestHeader, 'Content-Type') || Object.prototype.hasOwnProperty.call(requestHeader, 'content-type'))) {
712
- requestHeader['Content-Type'] = 'application/json';
713
- }
600
+ /**
601
+ * Keep pending tasks until a token is fetched
602
+ * Save next function as well, to call it once the token has been fetched, which prevents
603
+ * unexpected behaviour in a context in which the next function uses global vars
604
+ * or Promises to capture the token to hand it to other libraries, e.g. Apollo
605
+ */
606
+ pendingTasks.push({
607
+ request,
608
+ next
609
+ });
714
610
 
715
- // Unset the content-type header if explicitly asked to (passing `null` as value).
716
- if (requestHeader['Content-Type'] === null) {
717
- delete requestHeader['Content-Type'];
718
- }
611
+ // if a token is currently being fetched, then wait
612
+ if (requestState.get()) return;
719
613
 
720
- // Ensure body is a string if content type is application/{json|graphql}
721
- const body = HEADERS_CONTENT_TYPES.indexOf(requestHeader['Content-Type']) > -1 && typeof request.body === 'string' || isBuffer(request.body) ? request.body : JSON.stringify(request.body || undefined);
722
- if (body && (typeof body === 'string' || isBuffer(body))) {
723
- requestHeader['Content-Length'] = Buffer.byteLength(body).toString();
724
- }
725
- const clientOptions = {
726
- enableRetry,
727
- retryConfig,
728
- request: request,
729
- method: request.method,
730
- headers: requestHeader,
731
- includeRequestInErrorResponse,
732
- maskSensitiveHeaderData,
733
- ...httpClientOptions
734
- };
735
- if (credentialsMode) {
736
- clientOptions.credentialsMode = credentialsMode;
737
- }
738
- if (abortController) {
739
- clientOptions.signal = abortController.signal;
740
- }
741
- if (timeout) {
742
- clientOptions.timeout = timeout;
743
- clientOptions.abortController = abortController;
744
- }
745
- if (body) {
746
- clientOptions.body = body;
747
- }
614
+ // signal that a token is being fetched
615
+ requestState.set(true);
616
+
617
+ /**
618
+ * use refreshToken flow if there is refresh-token
619
+ * and there's either no token or the token is expired
620
+ */
621
+ if (tokenCacheObject && tokenCacheObject.refreshToken && (!tokenCacheObject.token || tokenCacheObject.token && Date.now() > tokenCacheObject.expirationTime)) {
622
+ if (!userOption) throw new Error('Missing required options.');
623
+ const opt = {
624
+ ...buildRequestForRefreshTokenFlow({
625
+ ...userOption,
626
+ refreshToken: tokenCacheObject.refreshToken
627
+ })
628
+ };
629
+
630
+ // reassign values
631
+ url = opt.url;
632
+ body = opt.body;
633
+ basicAuth = opt.basicAuth;
634
+ }
635
+
636
+ // request a new token
637
+ let response;
638
+ try {
639
+ response = await executor({
640
+ url,
641
+ method: 'POST',
642
+ headers: {
643
+ Authorization: `Basic ${basicAuth}`,
644
+ 'Content-Type': 'application/x-www-form-urlencoded',
645
+ 'Conent-Length': Buffer.byteLength(body).toString()
646
+ },
647
+ httpClient,
648
+ body
649
+ });
650
+ if (response.statusCode >= 200 && response.statusCode < 300) {
651
+ const {
652
+ access_token: token,
653
+ expires_in: expiresIn,
654
+ refresh_token: refreshToken
655
+ } = response?.data;
748
656
 
749
- // get result from executed request
750
- const response = await executeRequest$1({
751
- url,
752
- clientOptions,
753
- httpClient
657
+ // calculate token expiration time
658
+ const expirationTime = calculateExpirationTime(expiresIn);
659
+
660
+ // cache new generated token, refreshToken and expiration time
661
+ tokenCache.set({
662
+ token,
663
+ expirationTime,
664
+ refreshToken
754
665
  });
755
- const responseWithRequest = {
756
- ...request,
757
- includeOriginalRequest,
758
- maskSensitiveHeaderData,
759
- response
760
- };
761
- return next(responseWithRequest);
762
- };
763
- };
764
- }
765
666
 
766
- function createQueueMiddleware$1({
767
- concurrency = 20
768
- }) {
769
- let runningCount = 0;
770
- const queue = [];
771
- const dequeue = next => {
772
- runningCount--;
773
- if (queue.length && runningCount <= concurrency) {
774
- const nextTask = queue.shift();
775
- runningCount++;
776
- return next(nextTask.request);
777
- }
778
- };
779
- const enqueue = ({
780
- request
781
- }) => queue.push({
782
- request
783
- });
784
- return next => request => {
785
- // wrap and override resolve and reject functions
786
- const patchedRequest = {
787
- ...request,
788
- resolve(data) {
789
- request.resolve(data);
790
- dequeue(next);
791
- },
792
- reject(error) {
793
- request.reject(error);
794
- dequeue(next);
795
- }
796
- };
667
+ // signal that a token fetch is complete
668
+ requestState.set(false);
797
669
 
798
- // enqueue requests
799
- enqueue({
800
- request: patchedRequest
801
- });
802
- if (runningCount < concurrency) {
803
- runningCount++;
804
- const nextTask = queue.shift();
805
- return next(nextTask.request);
806
- }
807
- };
808
- }
670
+ /**
671
+ * Freeze and copy pending queue, reset
672
+ * original one for accepting new pending tasks
673
+ */
674
+ const requestQueue = pendingTasks.slice();
809
675
 
810
- // error, info, success
811
- function createLoggerMiddleware$1(options) {
812
- return next => {
813
- return async request => {
814
- let response = await next(request);
815
- const originalResponse = Object.assign({}, response);
816
- const {
817
- loggerFn = console.log,
818
- // logLevel = 'ERROR',
819
- maskSensitiveHeaderData = true,
820
- includeOriginalRequest = true,
821
- includeResponseHeaders = true
822
- // includeRequestInErrorResponse
823
- } = options || {};
824
- if (includeOriginalRequest && maskSensitiveHeaderData) {
825
- maskAuthData(response.request);
826
- }
827
- if (!includeOriginalRequest) {
828
- const {
829
- request,
830
- ...rest
831
- } = response;
832
- response = rest;
833
- }
834
- if (!includeResponseHeaders) {
835
- const {
836
- headers,
837
- ...rest
838
- } = response;
839
- response = rest;
840
- }
841
- if (loggerFn && typeof loggerFn == 'function') {
842
- loggerFn(response);
843
- // return originalResponse
676
+ // reset pendingTask queue
677
+ pendingTasks = [];
678
+ if (requestQueue.length === 1) {
679
+ return mergeAuthHeader(token, requestQueue.pop().request);
844
680
  }
845
681
 
846
- // console.log({ Response: response })
847
- return originalResponse;
848
- };
849
- };
850
- }
851
-
852
- var packageJson = {
853
- name: "@commercetools/ts-client",
854
- version: "1.0.0",
855
- engines: {
856
- node: ">=14"
857
- },
858
- description: "commercetools Composable Commerce TypeScript SDK client.",
859
- keywords: [
860
- "commercetools",
861
- "composable commerce",
862
- "sdk",
863
- "typescript",
864
- "client",
865
- "middleware",
866
- "http",
867
- "oauth",
868
- "auth"
869
- ],
870
- homepage: "https://github.com/commercetools/commercetools-sdk-typescript",
871
- license: "MIT",
872
- directories: {
873
- lib: "lib",
874
- test: "test"
875
- },
876
- publishConfig: {
877
- access: "public"
878
- },
879
- repository: {
880
- type: "git",
881
- url: "git+https://github.com/commercetools/commercetools-sdk-typescript.git"
882
- },
883
- bugs: {
884
- url: "https://github.com/commercetools/commercetools-sdk-typescript/issues"
885
- },
886
- dependencies: {
887
- "abort-controller": "3.0.0",
888
- buffer: "^6.0.3",
889
- "node-fetch": "^2.6.1",
890
- querystring: "^0.2.1"
891
- },
892
- files: [
893
- "dist",
894
- "CHANGELOG.md"
895
- ],
896
- author: "Chukwuemeka Ajima <meeky.ae@gmail.com>",
897
- main: "dist/commercetools-ts-client.cjs.js",
898
- module: "dist/commercetools-ts-client.esm.js",
899
- browser: {
900
- "./dist/commercetools-ts-client.cjs.js": "./dist/commercetools-ts-client.browser.cjs.js",
901
- "./dist/commercetools-ts-client.esm.js": "./dist/commercetools-ts-client.browser.esm.js"
902
- },
903
- devDependencies: {
904
- "common-tags": "1.8.2",
905
- dotenv: "16.0.3",
906
- jest: "29.5.0",
907
- nock: "12.0.3",
908
- "organize-imports-cli": "0.10.0"
909
- },
910
- scripts: {
911
- organize_imports: "find src -type f -name '*.ts' | xargs organize-imports-cli",
912
- postbuild: "yarn organize_imports",
913
- post_process_generate: "yarn organize_imports"
914
- }
915
- };
682
+ // execute all pending tasks if any
683
+ for (let i = 0; i < requestQueue.length; i++) {
684
+ const task = requestQueue[i];
685
+ const requestWithAuth = mergeAuthHeader(token, task.request);
916
686
 
917
- function createUserAgentMiddleware$1(options) {
918
- return next => async request => {
919
- const userAgent = createUserAgent({
920
- ...options,
921
- name: `commercetools-sdk-javascript-v3/${packageJson.version}`
687
+ // execute task
688
+ task.next(requestWithAuth);
689
+ }
690
+ return;
691
+ }
692
+ const error = new Error(response.data.message ? response.data.message : JSON.stringify(response.data));
693
+ /**
694
+ * reject the error immediately
695
+ * and free up the middleware chain
696
+ */
697
+ request.reject({
698
+ ...request,
699
+ headers: {
700
+ ...request.headers
701
+ },
702
+ response: {
703
+ statusCode: response.statusCode || response.data.statusCode,
704
+ error: {
705
+ error,
706
+ body: response
707
+ }
708
+ }
922
709
  });
923
- const requestWithUserAgent = {
710
+ } catch (error) {
711
+ return {
924
712
  ...request,
925
713
  headers: {
926
- ...request.headers,
927
- 'User-Agent': userAgent
714
+ ...request.headers
715
+ },
716
+ response: {
717
+ body: null,
718
+ statusCode: error.statusCode || 0,
719
+ error: {
720
+ ...response,
721
+ error,
722
+ body: response
723
+ }
928
724
  }
929
725
  };
930
- return next(requestWithUserAgent);
931
- };
726
+ }
932
727
  }
933
728
 
934
- function createConcurrentModificationMiddleware$1() {
729
+ function createAuthMiddlewareForAnonymousSessionFlow$1(options) {
730
+ const pendingTasks = [];
731
+ const requestState = store(false);
732
+ const tokenCache = options.tokenCache || store({
733
+ token: '',
734
+ expirationTime: -1
735
+ });
736
+ const tokenCacheKey = buildTokenCacheKey(options);
935
737
  return next => {
936
738
  return async request => {
937
- const response = await next(request);
938
- if (response.statusCode == 409) {
939
- var _response$error, _response$error$body, _response$error$body$, _response$error$body$2;
940
- /**
941
- * extract the currentVersion
942
- * from the error body and update
943
- * request with the currentVersion
944
- */
945
- const version = (_response$error = response.error) === null || _response$error === void 0 ? void 0 : (_response$error$body = _response$error.body) === null || _response$error$body === void 0 ? void 0 : (_response$error$body$ = _response$error$body.errors) === null || _response$error$body$ === void 0 ? void 0 : (_response$error$body$2 = _response$error$body$[0]) === null || _response$error$body$2 === void 0 ? void 0 : _response$error$body$2.currentVersion;
739
+ // if here is a token in the header, then move on to the next middleware
740
+ if (request.headers && (request.headers.Authorization || request.headers.authorization)) {
741
+ // move on
742
+ return next(request);
743
+ }
744
+
745
+ // prepare request options
746
+ const requestOptions = {
747
+ request,
748
+ requestState,
749
+ tokenCache,
750
+ pendingTasks,
751
+ tokenCacheKey,
752
+ httpClient: options.httpClient || fetch$1,
753
+ ...buildRequestForAnonymousSessionFlow(options),
754
+ userOption: options,
755
+ next
756
+ };
946
757
 
947
- // update the resource version here
948
- if (version) {
949
- request.body = typeof request.body == 'string' ? {
950
- ...JSON.parse(request.body),
951
- version
952
- } : {
953
- ...request.body,
954
- version
955
- };
956
- return next(request);
957
- }
758
+ // make request to coco
759
+ const requestWithAuth = await executeRequest$1(requestOptions);
760
+ if (requestWithAuth) {
761
+ return next(requestWithAuth);
958
762
  }
959
- return response;
960
763
  };
961
764
  };
962
765
  }
963
766
 
964
- function createErrorMiddleware$1(options) {
965
- return next => async request => {
966
- const response = await next(request);
967
- if (response.error) {
968
- const {
969
- error
970
- } = response;
971
- return {
972
- ...response,
973
- statusCode: error.statusCode || 0,
974
- headers: error.headers || getHeaders({}),
975
- error: {
976
- ...error,
977
- body: error.data || error
978
- }
767
+ function createAuthMiddlewareForClientCredentialsFlow$1(options) {
768
+ const requestState = store(false);
769
+ const pendingTasks = [];
770
+ const tokenCache = options.tokenCache || store({
771
+ token: '',
772
+ expirationTime: -1
773
+ });
774
+ const tokenCacheKey = buildTokenCacheKey(options);
775
+ return next => {
776
+ return async request => {
777
+ // if here is a token in the header, then move on to the next middleware
778
+ if (request.headers && (request.headers.Authorization || request.headers.authorization)) {
779
+ // move on
780
+ return next(request);
781
+ }
782
+
783
+ // prepare request options
784
+ const requestOptions = {
785
+ request,
786
+ requestState,
787
+ tokenCache,
788
+ pendingTasks,
789
+ tokenCacheKey,
790
+ httpClient: options.httpClient || fetch$1,
791
+ ...buildRequestForClientCredentialsFlow(options),
792
+ next
979
793
  };
980
- }
981
- return response;
982
- };
983
- }
984
794
 
985
- /**
986
- *
987
- * @param {AuthMiddlewareOptions} options
988
- * @returns { IBuiltRequestParams } *
989
- */
990
- function buildRequestForClientCredentialsFlow(options) {
991
- // Validate options
992
- if (!options) throw new Error('Missing required options');
993
- if (!options.host) throw new Error('Missing required option (host)');
994
- if (!options.projectKey) throw new Error('Missing required option (projectKey)');
995
- if (!options.credentials) throw new Error('Missing required option (credentials)');
996
- const {
997
- clientId,
998
- clientSecret
999
- } = options.credentials || {};
1000
- if (!(clientId && clientSecret)) throw new Error('Missing required credentials (clientId, clientSecret)');
1001
- const scope = options.scopes ? options.scopes.join(' ') : undefined;
1002
- const basicAuth = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
1003
- // This is mostly useful for internal testing purposes to be able to check
1004
- // other oauth endpoints.
1005
- const oauthUri = options.oauthUri || '/oauth/token';
1006
- const url = options.host.replace(/\/$/, '') + oauthUri;
1007
- const body = `grant_type=client_credentials${scope ? `&scope=${scope}` : ''}`;
1008
- return {
1009
- url,
1010
- body,
1011
- basicAuth
795
+ // make request to coco
796
+ const requestWithAuth = await executeRequest$1(requestOptions);
797
+ if (requestWithAuth) {
798
+ // make the request and inject the token into the header
799
+ return next(requestWithAuth);
800
+ }
801
+ };
1012
802
  };
1013
803
  }
1014
804
 
1015
- /**
1016
- *
1017
- * @param {AuthMiddlewareOptions} options
1018
- * @returns {IBuiltRequestParams} *
1019
- */
1020
- function buildRequestForAnonymousSessionFlow(options) {
1021
- if (!options) throw new Error('Missing required options');
1022
- if (!options.projectKey) throw new Error('Missing required option (projectKey)');
1023
- const projectKey = options.projectKey;
1024
- options.oauthUri = options.oauthUri || `/oauth/${projectKey}/anonymous/token`;
1025
- const result = buildRequestForClientCredentialsFlow(options);
1026
- if (options.credentials.anonymousId) result.body += `&anonymous_id=${options.credentials.anonymousId}`;
1027
- return {
1028
- ...result
1029
- };
1030
- }
805
+ function createAuthMiddlewareForExistingTokenFlow$1(authorization, options) {
806
+ return next => {
807
+ return async request => {
808
+ if (typeof authorization !== 'string') throw new Error('authorization must be a string');
809
+ const isForce = options?.force === undefined ? true : options.force;
1031
810
 
1032
- /**
1033
- *
1034
- * @param {RefreshAuthMiddlewareOptions} options
1035
- * @returns {IBuiltRequestParams}
1036
- */
1037
- function buildRequestForRefreshTokenFlow(options) {
1038
- if (!options) throw new Error('Missing required options');
1039
- if (!options.host) throw new Error('Missing required option (host)');
1040
- if (!options.projectKey) throw new Error('Missing required option (projectKey)');
1041
- if (!options.credentials) throw new Error('Missing required option (credentials)');
1042
- if (!options.refreshToken) throw new Error('Missing required option (refreshToken)');
1043
- const {
1044
- clientId,
1045
- clientSecret
1046
- } = options.credentials;
1047
- if (!(clientId && clientSecret)) throw new Error('Missing required credentials (clientId, clientSecret)');
1048
- const basicAuth = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
1049
- // This is mostly useful for internal testing purposes to be able to check
1050
- // other oauth endpoints.
1051
- const oauthUri = options.oauthUri || '/oauth/token';
1052
- const url = options.host.replace(/\/$/, '') + oauthUri;
1053
- const body = `grant_type=refresh_token&refresh_token=${encodeURIComponent(options.refreshToken)}`;
1054
- return {
1055
- basicAuth,
1056
- url,
1057
- body
811
+ /**
812
+ * The request will not be modified if:
813
+ * 1. no argument is passed
814
+ * 2. force is false and authorization header exists
815
+ */
816
+ if (!authorization || request.headers && (request.headers.Authorization || request.headers.authorization) && isForce === false) {
817
+ return next(request);
818
+ }
819
+ const requestWithAuth = {
820
+ ...request,
821
+ headers: {
822
+ ...request.headers,
823
+ Authorization: authorization
824
+ }
825
+ };
826
+ return next(requestWithAuth);
827
+ };
1058
828
  };
1059
829
  }
1060
830
 
1061
- /**
1062
- * @param {PasswordAuthMiddlewareOptions} options
1063
- * @returns {IBuiltRequestParams}
1064
- */
1065
- function buildRequestForPasswordFlow(options) {
1066
- if (!options) throw new Error('Missing required options');
1067
- if (!options.host) throw new Error('Missing required option (host)');
1068
- if (!options.projectKey) throw new Error('Missing required option (projectKey)');
1069
- if (!options.credentials) throw new Error('Missing required option (credentials)');
1070
- const {
1071
- clientId,
1072
- clientSecret,
1073
- user
1074
- } = options.credentials;
1075
- const projectKey = options.projectKey;
1076
- if (!(clientId && clientSecret && user)) throw new Error('Missing required credentials (clientId, clientSecret, user)');
1077
- const {
1078
- username,
1079
- password
1080
- } = user;
1081
- if (!(username && password)) throw new Error('Missing required user credentials (username, password)');
1082
- const scope = (options.scopes || []).join(' ');
1083
- const scopeStr = scope ? `&scope=${scope}` : '';
1084
- const basicAuth = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
1085
-
1086
- /**
1087
- * This is mostly useful for internal testing purposes to be able to check
1088
- * other oauth endpoints.
1089
- */
1090
- const oauthUri = options.oauthUri || `/oauth/${projectKey}/customers/token`;
1091
- const url = options.host.replace(/\/$/, '') + oauthUri;
831
+ function createAuthMiddlewareForPasswordFlow$1(options) {
832
+ const tokenCache = options.tokenCache || store({
833
+ token: '',
834
+ expirationTime: -1
835
+ });
836
+ const pendingTasks = [];
837
+ const requestState = store(false);
838
+ const tokenCacheKey = buildTokenCacheKey(options);
839
+ return next => {
840
+ return async request => {
841
+ if (request.headers && (request.headers.Authorization || request.headers.authorization)) {
842
+ return next(request);
843
+ }
844
+ const requestOptions = {
845
+ request,
846
+ requestState,
847
+ tokenCache,
848
+ pendingTasks,
849
+ tokenCacheKey,
850
+ httpClient: options.httpClient || fetch$1,
851
+ ...buildRequestForPasswordFlow(options),
852
+ userOption: options,
853
+ next
854
+ };
1092
855
 
1093
- // encode username and password as requested by the system
1094
- const body = `grant_type=password&username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}${scopeStr}`;
1095
- return {
1096
- basicAuth,
1097
- url,
1098
- body
856
+ // make request to coco
857
+ const requestWithAuth = await executeRequest$1(requestOptions);
858
+ if (requestWithAuth) {
859
+ return next(requestWithAuth);
860
+ }
861
+ };
1099
862
  };
1100
863
  }
1101
864
 
1102
- async function executeRequest(options) {
1103
- const {
1104
- request,
1105
- httpClient,
1106
- tokenCache,
1107
- tokenCacheKey,
1108
- requestState,
1109
- userOption,
1110
- next
1111
- } = options;
1112
- let url = options.url;
1113
- let body = options.body;
1114
- let basicAuth = options.basicAuth;
865
+ function createAuthMiddlewareForRefreshTokenFlow$1(options) {
866
+ const tokenCache = options.tokenCache || store({
867
+ token: '',
868
+ tokenCacheKey: null
869
+ });
870
+ const pendingTasks = [];
871
+ const requestState = store(false);
872
+ return next => {
873
+ return async request => {
874
+ if (request.headers && (request.headers.Authorization || request.headers.authorization)) {
875
+ return next(request);
876
+ }
1115
877
 
1116
- // get the pending object from option
1117
- let pendingTasks = options.pendingTasks;
1118
- 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.');
878
+ // prepare request options
879
+ const requestOptions = {
880
+ request,
881
+ requestState,
882
+ tokenCache,
883
+ pendingTasks,
884
+ httpClient: options.httpClient || fetch,
885
+ ...buildRequestForRefreshTokenFlow(options),
886
+ next
887
+ };
1119
888
 
1120
- /**
1121
- * If there is a token in the tokenCache, and it's not
1122
- * expired, append the token in the `Authorization` header.
1123
- */
1124
- const tokenCacheObject = tokenCache.get(tokenCacheKey);
1125
- if (tokenCacheObject && tokenCacheObject.token && Date.now() < tokenCacheObject.expirationTime) {
1126
- const requestWithAuth = mergeAuthHeader(tokenCacheObject.token, request);
1127
- return {
1128
- ...requestWithAuth
889
+ // make request to coco
890
+ const requestWithAuth = await executeRequest$1(requestOptions);
891
+ if (requestWithAuth) {
892
+ return next(requestWithAuth);
893
+ }
1129
894
  };
1130
- }
1131
-
1132
- /**
1133
- * Keep pending tasks until a token is fetched
1134
- * Save next function as well, to call it once the token has been fetched, which prevents
1135
- * unexpected behaviour in a context in which the next function uses global vars
1136
- * or Promises to capture the token to hand it to other libraries, e.g. Apollo
1137
- */
1138
- pendingTasks.push({
1139
- request,
1140
- next
1141
- });
895
+ };
896
+ }
1142
897
 
1143
- // if a token is currently being fetched, then wait
1144
- if (requestState.get()) return;
898
+ function createConcurrentModificationMiddleware$1() {
899
+ return next => {
900
+ return async request => {
901
+ const response = await next(request);
902
+ if (response.statusCode == 409) {
903
+ /**
904
+ * extract the currentVersion
905
+ * from the error body and update
906
+ * request with the currentVersion
907
+ */
908
+ const version = response.error.body?.errors?.[0]?.currentVersion;
1145
909
 
1146
- // signal that a token is being fetched
1147
- requestState.set(true);
910
+ // update the resource version here
911
+ if (version) {
912
+ request.body = typeof request.body == 'string' ? {
913
+ ...JSON.parse(request.body),
914
+ version
915
+ } : {
916
+ ...request.body,
917
+ version
918
+ };
919
+ return next(request);
920
+ }
921
+ }
922
+ return response;
923
+ };
924
+ };
925
+ }
1148
926
 
1149
- /**
1150
- * use refreshToken flow if there is refresh-token
1151
- * and there's either no token or the token is expired
1152
- */
1153
- if (tokenCacheObject && tokenCacheObject.refreshToken && (!tokenCacheObject.token || tokenCacheObject.token && Date.now() > tokenCacheObject.expirationTime)) {
1154
- if (!userOption) throw new Error('Missing required options.');
1155
- const opt = {
1156
- ...buildRequestForRefreshTokenFlow({
1157
- ...userOption,
1158
- refreshToken: tokenCacheObject.refreshToken
1159
- })
927
+ function createCorrelationIdMiddleware$1(options) {
928
+ return next => request => {
929
+ const nextRequest = {
930
+ ...request,
931
+ headers: {
932
+ ...request.headers,
933
+ 'X-Correlation-ID': options.generate && typeof options.generate == 'function' ? options.generate() : generateID()
934
+ }
1160
935
  };
936
+ return next(nextRequest);
937
+ };
938
+ }
1161
939
 
1162
- // reassign values
1163
- url = opt.url;
1164
- body = opt.body;
1165
- basicAuth = opt.basicAuth;
1166
- }
940
+ function createErrorMiddleware$1(options) {
941
+ return next => async request => {
942
+ const response = await next(request);
943
+ if (response.error) {
944
+ const {
945
+ error
946
+ } = response;
947
+ return {
948
+ ...response,
949
+ statusCode: error.statusCode || 0,
950
+ headers: error.headers || getHeaders({}),
951
+ error: {
952
+ ...error,
953
+ body: error.data || error
954
+ }
955
+ };
956
+ }
957
+ return response;
958
+ };
959
+ }
1167
960
 
1168
- // request a new token
1169
- let response;
961
+ async function executeRequest({
962
+ url,
963
+ httpClient,
964
+ clientOptions
965
+ }) {
966
+ let timer;
967
+ const {
968
+ timeout,
969
+ request,
970
+ abortController,
971
+ maskSensitiveHeaderData,
972
+ includeRequestInErrorResponse
973
+ } = clientOptions;
1170
974
  try {
1171
- response = await executor({
975
+ if (timeout) timer = setTimeout(() => {
976
+ abortController.abort();
977
+ }, timeout);
978
+ const response = await executor({
1172
979
  url,
1173
- method: 'POST',
1174
- headers: {
1175
- Authorization: `Basic ${basicAuth}`,
1176
- 'Content-Type': 'application/x-www-form-urlencoded',
1177
- 'Conent-Length': Buffer.byteLength(body).toString()
1178
- },
980
+ ...clientOptions,
1179
981
  httpClient,
1180
- body
982
+ method: clientOptions.method,
983
+ ...(clientOptions.body ? {
984
+ body: clientOptions.body
985
+ } : {})
1181
986
  });
1182
987
  if (response.statusCode >= 200 && response.statusCode < 300) {
1183
- var _response;
1184
- const {
1185
- access_token: token,
1186
- expires_in: expiresIn,
1187
- refresh_token: refreshToken
1188
- } = (_response = response) === null || _response === void 0 ? void 0 : _response.data;
1189
-
1190
- // calculate token expiration time
1191
- const expirationTime = calculateExpirationTime(expiresIn);
1192
-
1193
- // cache new generated token, refreshToken and expiration time
1194
- tokenCache.set({
1195
- token,
1196
- expirationTime,
1197
- refreshToken
1198
- });
988
+ if (clientOptions.method == 'HEAD') {
989
+ return {
990
+ body: null,
991
+ statusCode: response.statusCode,
992
+ retryCount: response.retryCount,
993
+ headers: getHeaders(response.headers)
994
+ };
995
+ }
996
+ return {
997
+ body: response.data,
998
+ statusCode: response.statusCode,
999
+ retryCount: response.retryCount,
1000
+ headers: getHeaders(response.headers)
1001
+ };
1002
+ }
1003
+ const error = createError({
1004
+ message: response?.data?.message || response?.message,
1005
+ statusCode: response.statusCode || response?.data?.statusCode,
1006
+ headers: getHeaders(response.headers),
1007
+ method: clientOptions.method,
1008
+ body: response.data,
1009
+ retryCount: response.retryCount,
1010
+ ...(includeRequestInErrorResponse ? {
1011
+ originalRequest: maskSensitiveHeaderData ? maskAuthData(request) : request
1012
+ } : {
1013
+ uri: request.uri
1014
+ })
1015
+ });
1199
1016
 
1200
- // signal that a token fetch is complete
1201
- requestState.set(false);
1017
+ /**
1018
+ * handle non-ok (error) response
1019
+ * build error body
1020
+ */
1021
+ return {
1022
+ body: response.data,
1023
+ code: response.statusCode,
1024
+ statusCode: response.statusCode,
1025
+ headers: getHeaders(response.headers),
1026
+ error
1027
+ };
1028
+ } catch (e) {
1029
+ // We know that this is a network error
1030
+ const headers = getHeaders(e.response?.headers);
1031
+ const statusCode = e.response?.status || e.response?.data0 || 0;
1032
+ const message = e.response?.data?.message;
1033
+ const error = createError({
1034
+ statusCode,
1035
+ code: statusCode,
1036
+ status: statusCode,
1037
+ message: message || e.message,
1038
+ headers,
1039
+ body: e.response?.data || e,
1040
+ error: e.response?.data,
1041
+ ...(includeRequestInErrorResponse ? {
1042
+ originalRequest: maskSensitiveHeaderData ? maskAuthData(request) : request
1043
+ } : {
1044
+ uri: request.uri
1045
+ })
1046
+ });
1047
+ return {
1048
+ body: error,
1049
+ error
1050
+ };
1051
+ } finally {
1052
+ clearTimeout(timer);
1053
+ }
1054
+ }
1055
+ function createHttpMiddleware$1(options) {
1056
+ // validate response
1057
+ validateHttpOptions(options);
1058
+ const {
1059
+ host,
1060
+ credentialsMode,
1061
+ httpClient,
1062
+ timeout,
1063
+ enableRetry,
1064
+ retryConfig,
1065
+ getAbortController,
1066
+ includeOriginalRequest,
1067
+ includeRequestInErrorResponse,
1068
+ maskSensitiveHeaderData,
1069
+ httpClientOptions
1070
+ } = options;
1071
+ return next => {
1072
+ return async request => {
1073
+ let abortController;
1074
+ if (timeout || getAbortController) abortController = (getAbortController ? getAbortController() : null) || new AbortController();
1075
+ const url = host.replace(/\/$/, '') + request.uri;
1076
+ const requestHeader = {
1077
+ ...request.headers
1078
+ };
1202
1079
 
1203
- /**
1204
- * Freeze and copy pending queue, reset
1205
- * original one for accepting new pending tasks
1206
- */
1207
- const requestQueue = pendingTasks.slice();
1080
+ // validate header
1081
+ if (!(Object.prototype.hasOwnProperty.call(requestHeader, 'Content-Type') || Object.prototype.hasOwnProperty.call(requestHeader, 'content-type'))) {
1082
+ requestHeader['Content-Type'] = 'application/json';
1083
+ }
1208
1084
 
1209
- // reset pendingTask queue
1210
- pendingTasks = [];
1211
- if (requestQueue.length === 1) {
1212
- return mergeAuthHeader(token, requestQueue.pop().request);
1085
+ // Unset the content-type header if explicitly asked to (passing `null` as value).
1086
+ if (requestHeader['Content-Type'] === null) {
1087
+ delete requestHeader['Content-Type'];
1213
1088
  }
1214
1089
 
1215
- // execute all pending tasks if any
1216
- for (let i = 0; i < requestQueue.length; i++) {
1217
- const task = requestQueue[i];
1218
- const requestWithAuth = mergeAuthHeader(token, task.request);
1219
-
1220
- // execute task
1221
- task.next(requestWithAuth);
1090
+ // Ensure body is a string if content type is application/{json|graphql}
1091
+ const body = HEADERS_CONTENT_TYPES.indexOf(requestHeader['Content-Type']) > -1 && typeof request.body === 'string' || isBuffer(request.body) ? request.body : JSON.stringify(request.body || undefined);
1092
+ if (body && (typeof body === 'string' || isBuffer(body))) {
1093
+ requestHeader['Content-Length'] = Buffer.byteLength(body).toString();
1222
1094
  }
1223
- return;
1224
- }
1225
- const error = new Error(response.data.message ? response.data.message : JSON.stringify(response.data));
1226
- /**
1227
- * reject the error immediately
1228
- * and free up the middleware chain
1229
- */
1230
- request.reject({
1231
- ...request,
1232
- headers: {
1233
- ...request.headers
1234
- },
1235
- response: {
1236
- statusCode: response.statusCode || response.data.statusCode,
1237
- error: {
1238
- error,
1239
- body: response
1240
- }
1095
+ const clientOptions = {
1096
+ enableRetry,
1097
+ retryConfig,
1098
+ request: request,
1099
+ method: request.method,
1100
+ headers: requestHeader,
1101
+ includeRequestInErrorResponse,
1102
+ maskSensitiveHeaderData,
1103
+ ...httpClientOptions
1104
+ };
1105
+ if (credentialsMode) {
1106
+ clientOptions.credentialsMode = credentialsMode;
1241
1107
  }
1242
- });
1243
- } catch (error) {
1244
- return {
1245
- ...request,
1246
- headers: {
1247
- ...request.headers
1248
- },
1249
- response: {
1250
- body: null,
1251
- statusCode: error.statusCode || 0,
1252
- error: {
1253
- ...response,
1254
- error,
1255
- body: response
1256
- }
1108
+ if (abortController) {
1109
+ clientOptions.signal = abortController.signal;
1110
+ }
1111
+ if (timeout) {
1112
+ clientOptions.timeout = timeout;
1113
+ clientOptions.abortController = abortController;
1114
+ }
1115
+ if (body) {
1116
+ clientOptions.body = body;
1257
1117
  }
1118
+
1119
+ // get result from executed request
1120
+ const response = await executeRequest({
1121
+ url,
1122
+ clientOptions,
1123
+ httpClient
1124
+ });
1125
+ const responseWithRequest = {
1126
+ ...request,
1127
+ includeOriginalRequest,
1128
+ maskSensitiveHeaderData,
1129
+ response
1130
+ };
1131
+ return next(responseWithRequest);
1258
1132
  };
1259
- }
1133
+ };
1260
1134
  }
1261
1135
 
1262
- function createAuthMiddlewareForPasswordFlow$1(options) {
1263
- const tokenCache = options.tokenCache || store({
1264
- token: '',
1265
- expirationTime: -1
1266
- });
1267
- const pendingTasks = [];
1268
- const requestState = store(false);
1269
- const tokenCacheKey = buildTokenCacheKey(options);
1136
+ // error, info, success
1137
+ function createLoggerMiddleware$1(options) {
1270
1138
  return next => {
1271
1139
  return async request => {
1272
- if (request.headers && (request.headers.Authorization || request.headers.authorization)) {
1273
- return next(request);
1140
+ let response = await next(request);
1141
+ const originalResponse = Object.assign({}, response);
1142
+ const {
1143
+ loggerFn = console.log,
1144
+ // logLevel = 'ERROR',
1145
+ maskSensitiveHeaderData = true,
1146
+ includeOriginalRequest = true,
1147
+ includeResponseHeaders = true
1148
+ // includeRequestInErrorResponse
1149
+ } = options || {};
1150
+ if (includeOriginalRequest && maskSensitiveHeaderData) {
1151
+ maskAuthData(response.request);
1274
1152
  }
1275
- const requestOptions = {
1276
- request,
1277
- requestState,
1278
- tokenCache,
1279
- pendingTasks,
1280
- tokenCacheKey,
1281
- httpClient: options.httpClient || fetch$1,
1282
- ...buildRequestForPasswordFlow(options),
1283
- userOption: options,
1284
- next
1285
- };
1286
-
1287
- // make request to coco
1288
- const requestWithAuth = await executeRequest(requestOptions);
1289
- if (requestWithAuth) {
1290
- return next(requestWithAuth);
1153
+ if (!includeOriginalRequest) {
1154
+ const {
1155
+ request,
1156
+ ...rest
1157
+ } = response;
1158
+ response = rest;
1159
+ }
1160
+ if (!includeResponseHeaders) {
1161
+ const {
1162
+ headers,
1163
+ ...rest
1164
+ } = response;
1165
+ response = rest;
1166
+ }
1167
+ if (loggerFn && typeof loggerFn == 'function') {
1168
+ loggerFn(response);
1169
+ // return originalResponse
1291
1170
  }
1171
+
1172
+ // console.log({ Response: response })
1173
+ return originalResponse;
1292
1174
  };
1293
1175
  };
1294
1176
  }
1295
1177
 
1296
- function createAuthMiddlewareForAnonymousSessionFlow$1(options) {
1297
- const pendingTasks = [];
1298
- const requestState = store(false);
1299
- const tokenCache = options.tokenCache || store({
1300
- token: '',
1301
- expirationTime: -1
1178
+ function createQueueMiddleware$1({
1179
+ concurrency = 20
1180
+ }) {
1181
+ let runningCount = 0;
1182
+ const queue = [];
1183
+ const dequeue = next => {
1184
+ runningCount--;
1185
+ if (queue.length && runningCount <= concurrency) {
1186
+ const nextTask = queue.shift();
1187
+ runningCount++;
1188
+ return next(nextTask.request);
1189
+ }
1190
+ };
1191
+ const enqueue = ({
1192
+ request
1193
+ }) => queue.push({
1194
+ request
1302
1195
  });
1303
- const tokenCacheKey = buildTokenCacheKey(options);
1304
- return next => {
1305
- return async request => {
1306
- // if here is a token in the header, then move on to the next middleware
1307
- if (request.headers && (request.headers.Authorization || request.headers.authorization)) {
1308
- // move on
1309
- return next(request);
1196
+ return next => request => {
1197
+ // wrap and override resolve and reject functions
1198
+ const patchedRequest = {
1199
+ ...request,
1200
+ resolve(data) {
1201
+ request.resolve(data);
1202
+ dequeue(next);
1203
+ },
1204
+ reject(error) {
1205
+ request.reject(error);
1206
+ dequeue(next);
1310
1207
  }
1208
+ };
1311
1209
 
1312
- // prepare request options
1313
- const requestOptions = {
1314
- request,
1315
- requestState,
1316
- tokenCache,
1317
- pendingTasks,
1318
- tokenCacheKey,
1319
- httpClient: options.httpClient || fetch$1,
1320
- ...buildRequestForAnonymousSessionFlow(options),
1321
- userOption: options,
1322
- next
1323
- };
1210
+ // enqueue requests
1211
+ enqueue({
1212
+ request: patchedRequest
1213
+ });
1214
+ if (runningCount < concurrency) {
1215
+ runningCount++;
1216
+ const nextTask = queue.shift();
1217
+ return next(nextTask.request);
1218
+ }
1219
+ };
1220
+ }
1221
+
1222
+ var packageJson = {
1223
+ name: "@commercetools/ts-client",
1224
+ version: "1.1.1",
1225
+ engines: {
1226
+ node: ">=14"
1227
+ },
1228
+ description: "commercetools Composable Commerce TypeScript SDK client.",
1229
+ keywords: [
1230
+ "commercetools",
1231
+ "composable commerce",
1232
+ "sdk",
1233
+ "typescript",
1234
+ "client",
1235
+ "middleware",
1236
+ "http",
1237
+ "oauth",
1238
+ "auth"
1239
+ ],
1240
+ homepage: "https://github.com/commercetools/commercetools-sdk-typescript",
1241
+ license: "MIT",
1242
+ directories: {
1243
+ lib: "lib",
1244
+ test: "test"
1245
+ },
1246
+ publishConfig: {
1247
+ access: "public"
1248
+ },
1249
+ repository: {
1250
+ type: "git",
1251
+ url: "git+https://github.com/commercetools/commercetools-sdk-typescript.git"
1252
+ },
1253
+ bugs: {
1254
+ url: "https://github.com/commercetools/commercetools-sdk-typescript/issues"
1255
+ },
1256
+ dependencies: {
1257
+ "abort-controller": "3.0.0",
1258
+ buffer: "^6.0.3",
1259
+ "node-fetch": "^2.6.1",
1260
+ uuid: "9.0.0"
1261
+ },
1262
+ files: [
1263
+ "dist",
1264
+ "CHANGELOG.md"
1265
+ ],
1266
+ author: "Chukwuemeka Ajima <meeky.ae@gmail.com>",
1267
+ main: "dist/commercetools-ts-client.cjs.js",
1268
+ module: "dist/commercetools-ts-client.esm.js",
1269
+ browser: {
1270
+ "./dist/commercetools-ts-client.cjs.js": "./dist/commercetools-ts-client.browser.cjs.js",
1271
+ "./dist/commercetools-ts-client.esm.js": "./dist/commercetools-ts-client.browser.esm.js"
1272
+ },
1273
+ devDependencies: {
1274
+ "common-tags": "1.8.2",
1275
+ dotenv: "16.3.1",
1276
+ jest: "29.6.2",
1277
+ nock: "12.0.3",
1278
+ "organize-imports-cli": "0.10.0"
1279
+ },
1280
+ scripts: {
1281
+ organize_imports: "find src -type f -name '*.ts' | xargs organize-imports-cli",
1282
+ postbuild: "yarn organize_imports",
1283
+ post_process_generate: "yarn organize_imports"
1284
+ }
1285
+ };
1324
1286
 
1325
- // make request to coco
1326
- const requestWithAuth = await executeRequest(requestOptions);
1327
- if (requestWithAuth) {
1328
- return next(requestWithAuth);
1287
+ function createUserAgentMiddleware$1(options) {
1288
+ return next => async request => {
1289
+ const userAgent = createUserAgent({
1290
+ ...options,
1291
+ name: `commercetools-sdk-javascript-v3/${packageJson.version}`
1292
+ });
1293
+ const requestWithUserAgent = {
1294
+ ...request,
1295
+ headers: {
1296
+ ...request.headers,
1297
+ 'User-Agent': userAgent
1329
1298
  }
1330
1299
  };
1300
+ return next(requestWithUserAgent);
1331
1301
  };
1332
1302
  }
1333
1303
 
1334
- function createAuthMiddlewareForClientCredentialsFlow$1(options) {
1335
- const requestState = store(false);
1336
- const pendingTasks = [];
1337
- const tokenCache = options.tokenCache || store({
1338
- token: '',
1339
- expirationTime: -1
1340
- });
1341
- const tokenCacheKey = buildTokenCacheKey(options);
1342
- return next => {
1343
- return async request => {
1344
- // if here is a token in the header, then move on to the next middleware
1345
- if (request.headers && (request.headers.Authorization || request.headers.authorization)) {
1346
- // move on
1347
- return next(request);
1348
- }
1349
-
1350
- // prepare request options
1351
- const requestOptions = {
1352
- request,
1353
- requestState,
1354
- tokenCache,
1355
- pendingTasks,
1356
- tokenCacheKey,
1357
- httpClient: options.httpClient || fetch$1,
1358
- ...buildRequestForClientCredentialsFlow(options),
1359
- next
1360
- };
1304
+ var middleware = /*#__PURE__*/Object.freeze({
1305
+ __proto__: null,
1306
+ createAuthMiddlewareForAnonymousSessionFlow: createAuthMiddlewareForAnonymousSessionFlow$1,
1307
+ createAuthMiddlewareForClientCredentialsFlow: createAuthMiddlewareForClientCredentialsFlow$1,
1308
+ createAuthMiddlewareForExistingTokenFlow: createAuthMiddlewareForExistingTokenFlow$1,
1309
+ createAuthMiddlewareForPasswordFlow: createAuthMiddlewareForPasswordFlow$1,
1310
+ createAuthMiddlewareForRefreshTokenFlow: createAuthMiddlewareForRefreshTokenFlow$1,
1311
+ createConcurrentModificationMiddleware: createConcurrentModificationMiddleware$1,
1312
+ createCorrelationIdMiddleware: createCorrelationIdMiddleware$1,
1313
+ createErrorMiddleware: createErrorMiddleware$1,
1314
+ createHttpMiddleware: createHttpMiddleware$1,
1315
+ createLoggerMiddleware: createLoggerMiddleware$1,
1316
+ createQueueMiddleware: createQueueMiddleware$1,
1317
+ createUserAgentMiddleware: createUserAgentMiddleware$1
1318
+ });
1361
1319
 
1362
- // make request to coco
1363
- const requestWithAuth = await executeRequest(requestOptions);
1364
- if (requestWithAuth) {
1365
- // make the request and inject the token into the header
1366
- return next(requestWithAuth);
1367
- }
1368
- };
1369
- };
1320
+ function compose({
1321
+ middlewares
1322
+ }) {
1323
+ if (middlewares.length === 1) return middlewares[0];
1324
+ const _middlewares = middlewares.slice();
1325
+ return _middlewares.reduce((ac, cv) => (...args) => ac(cv.apply(null, args)));
1370
1326
  }
1371
1327
 
1372
- function createAuthMiddlewareForRefreshTokenFlow$1(options) {
1373
- const tokenCache = options.tokenCache || store({
1374
- token: '',
1375
- tokenCacheKey: null
1328
+ // process batch requests
1329
+ let _options;
1330
+ function process$1(request, fn, processOpt) {
1331
+ validate('process', request, {
1332
+ allowedMethods: ['GET']
1376
1333
  });
1377
- const pendingTasks = [];
1378
- const requestState = store(false);
1379
- return next => {
1380
- return async request => {
1381
- if (request.headers && (request.headers.Authorization || request.headers.authorization)) {
1382
- return next(request);
1383
- }
1334
+ 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');
1384
1335
 
1385
- // prepare request options
1386
- const requestOptions = {
1387
- request,
1388
- requestState,
1389
- tokenCache,
1390
- pendingTasks,
1391
- httpClient: options.httpClient || fetch,
1392
- ...buildRequestForRefreshTokenFlow(options),
1393
- next
1336
+ // Set default process options
1337
+ const opt = {
1338
+ total: Number.POSITIVE_INFINITY,
1339
+ accumulate: true,
1340
+ ...processOpt
1341
+ };
1342
+ return new Promise((resolve, reject) => {
1343
+ let _path,
1344
+ _queryString = '';
1345
+ if (request && request.uri) {
1346
+ const [path, queryString] = request.uri.split('?');
1347
+ _path = path;
1348
+ _queryString = queryString;
1349
+ }
1350
+ const requestQuery = {
1351
+ ...parseURLString(_queryString)
1352
+ };
1353
+ const query = {
1354
+ // defaults
1355
+ limit: 20,
1356
+ // merge given query params
1357
+ ...requestQuery
1358
+ };
1359
+ let itemsToGet = opt.total;
1360
+ let hasFirstPageBeenProcessed = false;
1361
+ const processPage = async (lastId, acc = []) => {
1362
+ // Use the lesser value between limit and itemsToGet in query
1363
+ const limit = query.limit < itemsToGet ? query.limit : itemsToGet;
1364
+ const originalQueryString = stringifyURLString({
1365
+ ...query,
1366
+ limit
1367
+ });
1368
+ const enhancedQuery = {
1369
+ sort: 'id asc',
1370
+ withTotal: false,
1371
+ ...(lastId ? {
1372
+ where: `id > "${lastId}"`
1373
+ } : {})
1394
1374
  };
1395
-
1396
- // make request to coco
1397
- const requestWithAuth = await executeRequest(requestOptions);
1398
- if (requestWithAuth) {
1399
- return next(requestWithAuth);
1375
+ const enhancedQueryString = stringifyURLString(enhancedQuery);
1376
+ const enhancedRequest = {
1377
+ ...request,
1378
+ uri: `${_path}?${enhancedQueryString}&${originalQueryString}`
1379
+ };
1380
+ try {
1381
+ const payload = await createClient(_options).execute(enhancedRequest);
1382
+ const {
1383
+ results,
1384
+ count: resultsLength
1385
+ } = payload?.body || {};
1386
+ if (!resultsLength && hasFirstPageBeenProcessed) {
1387
+ return resolve(acc || []);
1388
+ }
1389
+ const result = await Promise.resolve(fn(payload));
1390
+ let accumulated;
1391
+ hasFirstPageBeenProcessed = true;
1392
+ if (opt.accumulate) accumulated = acc.concat(result || []);
1393
+ itemsToGet -= resultsLength;
1394
+ // If there are no more items to get, it means the total number
1395
+ // of items in the original request have been fetched so we
1396
+ // resolve the promise.
1397
+ // Also, if we get less results in a page then the limit set it
1398
+ // means that there are no more pages and that we can finally
1399
+ // resolve the promise.
1400
+ if (resultsLength < query.limit || !itemsToGet) {
1401
+ return resolve(accumulated || []);
1402
+ }
1403
+ const last = results[resultsLength - 1];
1404
+ const newLastId = last && last.id;
1405
+ processPage(newLastId, accumulated);
1406
+ } catch (error) {
1407
+ reject(error);
1400
1408
  }
1401
1409
  };
1402
- };
1403
- }
1404
-
1405
- function createAuthMiddlewareForExistingTokenFlow$1(authorization, options) {
1406
- return next => {
1407
- return async request => {
1408
- if (typeof authorization !== 'string') throw new Error('authorization must be a string');
1409
- const isForce = (options === null || options === void 0 ? void 0 : options.force) === undefined ? true : options.force;
1410
1410
 
1411
- /**
1412
- * The request will not be modified if:
1413
- * 1. no argument is passed
1414
- * 2. force is false and authorization header exists
1415
- */
1416
- if (!authorization || request.headers && (request.headers.Authorization || request.headers.authorization) && isForce === false) {
1417
- return next(request);
1418
- }
1419
- const requestWithAuth = {
1420
- ...request,
1421
- headers: {
1422
- ...request.headers,
1423
- Authorization: authorization
1424
- }
1411
+ // Start iterating through pages
1412
+ processPage();
1413
+ });
1414
+ }
1415
+ function createClient(middlewares) {
1416
+ _options = middlewares;
1417
+ validateClient(middlewares);
1418
+ const resolver = {
1419
+ async resolve(rs) {
1420
+ const {
1421
+ response,
1422
+ includeOriginalRequest,
1423
+ maskSensitiveHeaderData,
1424
+ ...request
1425
+ } = rs;
1426
+ const {
1427
+ retryCount,
1428
+ ...rest
1429
+ } = response;
1430
+ const res = {
1431
+ body: null,
1432
+ error: null,
1433
+ reject: rs.reject,
1434
+ resolve: rs.resolve,
1435
+ ...rest,
1436
+ ...(includeOriginalRequest ? {
1437
+ originalRequest: maskSensitiveHeaderData ? maskAuthData(request) : request
1438
+ } : {}),
1439
+ ...(response?.retryCount ? {
1440
+ retryCount: response.retryCount
1441
+ } : {})
1425
1442
  };
1426
- return next(requestWithAuth);
1427
- };
1443
+ return res;
1444
+ }
1445
+ };
1446
+ const dispatch = compose(middlewares)(resolver.resolve);
1447
+ return {
1448
+ process: process$1,
1449
+ execute(request) {
1450
+ validate('exec', request);
1451
+ return new Promise((resolve, reject) => {
1452
+ dispatch({
1453
+ reject,
1454
+ resolve,
1455
+ ...request
1456
+ }).then(resolve).catch(reject);
1457
+ });
1458
+ }
1428
1459
  };
1429
1460
  }
1430
1461
 
1431
- var middleware = /*#__PURE__*/Object.freeze({
1432
- __proto__: null,
1433
- createCorrelationIdMiddleware: createCorrelationIdMiddleware$1,
1434
- createHttpMiddleware: createHttpMiddleware$1,
1435
- createQueueMiddleware: createQueueMiddleware$1,
1436
- createLoggerMiddleware: createLoggerMiddleware$1,
1437
- createUserAgentMiddleware: createUserAgentMiddleware$1,
1438
- createConcurrentModificationMiddleware: createConcurrentModificationMiddleware$1,
1439
- createErrorMiddleware: createErrorMiddleware$1,
1440
- createAuthMiddlewareForPasswordFlow: createAuthMiddlewareForPasswordFlow$1,
1441
- createAuthMiddlewareForClientCredentialsFlow: createAuthMiddlewareForClientCredentialsFlow$1,
1442
- createAuthMiddlewareForAnonymousSessionFlow: createAuthMiddlewareForAnonymousSessionFlow$1,
1443
- createAuthMiddlewareForExistingTokenFlow: createAuthMiddlewareForExistingTokenFlow$1,
1444
- createAuthMiddlewareForRefreshTokenFlow: createAuthMiddlewareForRefreshTokenFlow$1
1445
- });
1446
-
1447
1462
  const {
1448
1463
  createAuthMiddlewareForPasswordFlow,
1449
1464
  createAuthMiddlewareForAnonymousSessionFlow,
@@ -1582,7 +1597,7 @@ class ClientBuilder {
1582
1597
  }
1583
1598
  withCorrelationIdMiddleware(options) {
1584
1599
  this.correlationIdMiddleware = createCorrelationIdMiddleware({
1585
- generate: options === null || options === void 0 ? void 0 : options.generate,
1600
+ generate: options?.generate,
1586
1601
  ...options
1587
1602
  });
1588
1603
  return this;
@@ -1617,4 +1632,4 @@ class ClientBuilder {
1617
1632
  }
1618
1633
  }
1619
1634
 
1620
- export { ClientBuilder, process$1 as Process, createAuthMiddlewareForAnonymousSessionFlow$1 as createAuthMiddlewareForAnonymousSessionFlow, createAuthMiddlewareForClientCredentialsFlow$1 as createAuthMiddlewareForClientCredentialsFlow, createAuthMiddlewareForExistingTokenFlow$1 as createAuthMiddlewareForExistingTokenFlow, createAuthMiddlewareForPasswordFlow$1 as createAuthMiddlewareForPasswordFlow, createAuthMiddlewareForRefreshTokenFlow$1 as createAuthMiddlewareForRefreshTokenFlow, createClient, createCorrelationIdMiddleware$1 as createCorrelationIdMiddleware, createHttpMiddleware$1 as createHttpMiddleware, createLoggerMiddleware$1 as createLoggerMiddleware, createQueueMiddleware$1 as createQueueMiddleware, createUserAgentMiddleware$1 as createUserAgentMiddleware };
1635
+ export { ClientBuilder, process$1 as Process, createAuthMiddlewareForAnonymousSessionFlow$1 as createAuthMiddlewareForAnonymousSessionFlow, createAuthMiddlewareForClientCredentialsFlow$1 as createAuthMiddlewareForClientCredentialsFlow, createAuthMiddlewareForExistingTokenFlow$1 as createAuthMiddlewareForExistingTokenFlow, createAuthMiddlewareForPasswordFlow$1 as createAuthMiddlewareForPasswordFlow, createAuthMiddlewareForRefreshTokenFlow$1 as createAuthMiddlewareForRefreshTokenFlow, createClient, createConcurrentModificationMiddleware$1 as createConcurrentModificationMiddleware, createCorrelationIdMiddleware$1 as createCorrelationIdMiddleware, createHttpMiddleware$1 as createHttpMiddleware, createLoggerMiddleware$1 as createLoggerMiddleware, createQueueMiddleware$1 as createQueueMiddleware, createUserAgentMiddleware$1 as createUserAgentMiddleware };