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