@commercetools/ts-client 1.0.0 → 1.1.0

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