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