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