@uploadcare/upload-client 2.0.0-alpha.6 → 2.0.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/README.md +35 -10
- package/dist/index.browser.cjs +209 -150
- package/dist/index.browser.js +244 -189
- package/dist/index.cjs +214 -150
- package/dist/index.js +247 -192
- package/dist/types.d.ts +155 -92
- package/package.json +33 -27
- package/CHANGELOG.md +0 -243
package/dist/index.browser.js
CHANGED
|
@@ -1,36 +1,9 @@
|
|
|
1
|
-
/*globals self, window */
|
|
2
|
-
|
|
3
|
-
/*eslint-disable @mysticatea/prettier */
|
|
4
|
-
const { AbortController, AbortSignal } =
|
|
5
|
-
typeof self !== "undefined" ? self :
|
|
6
|
-
typeof window !== "undefined" ? window :
|
|
7
|
-
/* otherwise */ undefined;
|
|
8
|
-
|
|
9
|
-
/*
|
|
10
|
-
Settings for future support:
|
|
11
|
-
parallelDirectUploads: 10,
|
|
12
|
-
*/
|
|
13
|
-
const defaultSettings = {
|
|
14
|
-
baseCDN: 'https://ucarecdn.com',
|
|
15
|
-
baseURL: 'https://upload.uploadcare.com',
|
|
16
|
-
maxContentLength: 50 * 1024 * 1024,
|
|
17
|
-
retryThrottledRequestMaxTimes: 1,
|
|
18
|
-
multipartMinFileSize: 25 * 1024 * 1024,
|
|
19
|
-
multipartChunkSize: 5 * 1024 * 1024,
|
|
20
|
-
multipartMinLastPartSize: 1024 * 1024,
|
|
21
|
-
maxConcurrentRequests: 4,
|
|
22
|
-
multipartMaxAttempts: 3,
|
|
23
|
-
pollingTimeoutMilliseconds: 10000,
|
|
24
|
-
pusherKey: '79ae88bd931ea68464d9'
|
|
25
|
-
};
|
|
26
|
-
const defaultContentType = 'application/octet-stream';
|
|
27
|
-
const defaultFilename = 'original';
|
|
28
|
-
|
|
29
1
|
class UploadClientError extends Error {
|
|
30
|
-
constructor(message, request, response, headers) {
|
|
2
|
+
constructor(message, code, request, response, headers) {
|
|
31
3
|
super();
|
|
32
4
|
this.name = 'UploadClientError';
|
|
33
5
|
this.message = message;
|
|
6
|
+
this.code = code;
|
|
34
7
|
this.request = request;
|
|
35
8
|
this.response = response;
|
|
36
9
|
this.headers = headers;
|
|
@@ -60,7 +33,7 @@ const request = ({ method, url, data, headers = {}, signal, onProgress }) => new
|
|
|
60
33
|
let aborted = false;
|
|
61
34
|
xhr.open(requestMethod, url);
|
|
62
35
|
if (headers) {
|
|
63
|
-
Object.entries(headers).forEach(entry => {
|
|
36
|
+
Object.entries(headers).forEach((entry) => {
|
|
64
37
|
const [key, value] = entry;
|
|
65
38
|
typeof value !== 'undefined' &&
|
|
66
39
|
!Array.isArray(value) &&
|
|
@@ -132,18 +105,25 @@ const request = ({ method, url, data, headers = {}, signal, onProgress }) => new
|
|
|
132
105
|
}
|
|
133
106
|
});
|
|
134
107
|
|
|
108
|
+
function identity(obj) {
|
|
109
|
+
return obj;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const transformFile = identity;
|
|
135
113
|
var getFormData = () => new FormData();
|
|
136
114
|
|
|
115
|
+
const isFileTuple = (tuple) => tuple[0] === 'file';
|
|
137
116
|
function buildFormData(body) {
|
|
138
117
|
const formData = getFormData();
|
|
139
|
-
const isTriple = (tuple) => tuple[0] === 'file';
|
|
140
118
|
for (const tuple of body) {
|
|
141
119
|
if (Array.isArray(tuple[1])) {
|
|
142
120
|
// refactor this
|
|
143
|
-
tuple[1].forEach(val => val && formData.append(tuple[0] + '[]', `${val}`));
|
|
121
|
+
tuple[1].forEach((val) => val && formData.append(tuple[0] + '[]', `${val}`));
|
|
144
122
|
}
|
|
145
|
-
else if (
|
|
146
|
-
|
|
123
|
+
else if (isFileTuple(tuple)) {
|
|
124
|
+
const name = tuple[2];
|
|
125
|
+
const file = transformFile(tuple[1]); // lgtm[js/superfluous-trailing-arguments]
|
|
126
|
+
formData.append(tuple[0], file, name);
|
|
147
127
|
}
|
|
148
128
|
else if (tuple[1] != null) {
|
|
149
129
|
formData.append(tuple[0], `${tuple[1]}`);
|
|
@@ -155,9 +135,9 @@ function buildFormData(body) {
|
|
|
155
135
|
const serializePair = (key, value) => typeof value !== 'undefined' ? `${key}=${encodeURIComponent(value)}` : null;
|
|
156
136
|
const createQuery = (query) => Object.entries(query)
|
|
157
137
|
.reduce((params, [key, value]) => params.concat(Array.isArray(value)
|
|
158
|
-
? value.map(value => serializePair(`${key}[]`, value))
|
|
138
|
+
? value.map((value) => serializePair(`${key}[]`, value))
|
|
159
139
|
: serializePair(key, value)), [])
|
|
160
|
-
.filter(x => !!x)
|
|
140
|
+
.filter((x) => !!x)
|
|
161
141
|
.join('&');
|
|
162
142
|
const getUrl = (base, path, query) => [
|
|
163
143
|
base,
|
|
@@ -168,15 +148,52 @@ const getUrl = (base, path, query) => [
|
|
|
168
148
|
.filter(Boolean)
|
|
169
149
|
.join('');
|
|
170
150
|
|
|
171
|
-
|
|
151
|
+
/*
|
|
152
|
+
Settings for future support:
|
|
153
|
+
parallelDirectUploads: 10,
|
|
154
|
+
*/
|
|
155
|
+
const defaultSettings = {
|
|
156
|
+
baseCDN: 'https://ucarecdn.com',
|
|
157
|
+
baseURL: 'https://upload.uploadcare.com',
|
|
158
|
+
maxContentLength: 50 * 1024 * 1024,
|
|
159
|
+
retryThrottledRequestMaxTimes: 1,
|
|
160
|
+
multipartMinFileSize: 25 * 1024 * 1024,
|
|
161
|
+
multipartChunkSize: 5 * 1024 * 1024,
|
|
162
|
+
multipartMinLastPartSize: 1024 * 1024,
|
|
163
|
+
maxConcurrentRequests: 4,
|
|
164
|
+
multipartMaxAttempts: 3,
|
|
165
|
+
pollingTimeoutMilliseconds: 10000,
|
|
166
|
+
pusherKey: '79ae88bd931ea68464d9'
|
|
167
|
+
};
|
|
168
|
+
const defaultContentType = 'application/octet-stream';
|
|
169
|
+
const defaultFilename = 'original';
|
|
170
|
+
|
|
171
|
+
var version = '2.0.0';
|
|
172
172
|
|
|
173
173
|
/**
|
|
174
174
|
* Returns User Agent based on version and settings.
|
|
175
175
|
*/
|
|
176
|
-
function getUserAgent({ publicKey = '', integration = '' } = {}) {
|
|
177
|
-
const
|
|
178
|
-
const
|
|
179
|
-
|
|
176
|
+
function getUserAgent({ userAgent, publicKey = '', integration = '' } = {}) {
|
|
177
|
+
const libraryName = 'UploadcareUploadClient';
|
|
178
|
+
const libraryVersion = version;
|
|
179
|
+
const languageName = 'JavaScript';
|
|
180
|
+
if (typeof userAgent === 'string') {
|
|
181
|
+
return userAgent;
|
|
182
|
+
}
|
|
183
|
+
if (typeof userAgent === 'function') {
|
|
184
|
+
return userAgent({
|
|
185
|
+
publicKey,
|
|
186
|
+
libraryName,
|
|
187
|
+
libraryVersion,
|
|
188
|
+
languageName,
|
|
189
|
+
integration
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
const mainInfo = [libraryName, libraryVersion, publicKey]
|
|
193
|
+
.filter(Boolean)
|
|
194
|
+
.join('/');
|
|
195
|
+
const additionInfo = [languageName, integration].filter(Boolean).join('; ');
|
|
196
|
+
return `${mainInfo} (${additionInfo})`;
|
|
180
197
|
}
|
|
181
198
|
|
|
182
199
|
const SEPARATOR = /\W|_/g;
|
|
@@ -210,7 +227,7 @@ function camelizeKeys(source) {
|
|
|
210
227
|
*
|
|
211
228
|
* @param {number} ms Timeout in milliseconds.
|
|
212
229
|
*/
|
|
213
|
-
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
230
|
+
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
214
231
|
|
|
215
232
|
const defaultOptions = {
|
|
216
233
|
factor: 2,
|
|
@@ -232,7 +249,7 @@ function retrier(fn, options = defaultOptions) {
|
|
|
232
249
|
return runAttempt(fn);
|
|
233
250
|
}
|
|
234
251
|
|
|
235
|
-
const REQUEST_WAS_THROTTLED_CODE =
|
|
252
|
+
const REQUEST_WAS_THROTTLED_CODE = 'RequestThrottledError';
|
|
236
253
|
const DEFAULT_RETRY_AFTER_TIMEOUT = 15000;
|
|
237
254
|
function getTimeoutFromThrottledRequest(error) {
|
|
238
255
|
const { headers } = error || {};
|
|
@@ -242,9 +259,8 @@ function getTimeoutFromThrottledRequest(error) {
|
|
|
242
259
|
}
|
|
243
260
|
function retryIfThrottled(fn, retryThrottledMaxTimes) {
|
|
244
261
|
return retrier(({ attempt, retry }) => fn().catch((error) => {
|
|
245
|
-
var _a;
|
|
246
262
|
if ('response' in error &&
|
|
247
|
-
(
|
|
263
|
+
(error === null || error === void 0 ? void 0 : error.code) === REQUEST_WAS_THROTTLED_CODE &&
|
|
248
264
|
attempt < retryThrottledMaxTimes) {
|
|
249
265
|
return retry(getTimeoutFromThrottledRequest(error));
|
|
250
266
|
}
|
|
@@ -256,7 +272,7 @@ function retryIfThrottled(fn, retryThrottledMaxTimes) {
|
|
|
256
272
|
* Performs file uploading request to Uploadcare Upload API.
|
|
257
273
|
* Can be canceled and has progress.
|
|
258
274
|
*/
|
|
259
|
-
function base(file, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source = 'local', integration, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
275
|
+
function base(file, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
260
276
|
return retryIfThrottled(() => {
|
|
261
277
|
var _a;
|
|
262
278
|
return request({
|
|
@@ -265,7 +281,7 @@ function base(file, { publicKey, fileName, baseURL = defaultSettings.baseURL, se
|
|
|
265
281
|
jsonerrors: 1
|
|
266
282
|
}),
|
|
267
283
|
headers: {
|
|
268
|
-
'X-UC-User-Agent': getUserAgent({ publicKey, integration })
|
|
284
|
+
'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
|
|
269
285
|
},
|
|
270
286
|
data: buildFormData([
|
|
271
287
|
['file', file, (_a = fileName !== null && fileName !== void 0 ? fileName : file.name) !== null && _a !== void 0 ? _a : defaultFilename],
|
|
@@ -283,7 +299,7 @@ function base(file, { publicKey, fileName, baseURL = defaultSettings.baseURL, se
|
|
|
283
299
|
}).then(({ data, headers, request }) => {
|
|
284
300
|
const response = camelizeKeys(JSON.parse(data));
|
|
285
301
|
if ('error' in response) {
|
|
286
|
-
throw new UploadClientError(
|
|
302
|
+
throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
|
|
287
303
|
}
|
|
288
304
|
else {
|
|
289
305
|
return response;
|
|
@@ -292,34 +308,6 @@ function base(file, { publicKey, fileName, baseURL = defaultSettings.baseURL, se
|
|
|
292
308
|
}, retryThrottledRequestMaxTimes);
|
|
293
309
|
}
|
|
294
310
|
|
|
295
|
-
/**
|
|
296
|
-
* Returns a JSON dictionary holding file info.
|
|
297
|
-
*/
|
|
298
|
-
/* eslint @typescript-eslint/camelcase: [2, {allow: ["pub_key", "file_id"]}] */
|
|
299
|
-
function info(uuid, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
300
|
-
return retryIfThrottled(() => request({
|
|
301
|
-
method: 'GET',
|
|
302
|
-
headers: {
|
|
303
|
-
'X-UC-User-Agent': getUserAgent({ publicKey, integration })
|
|
304
|
-
},
|
|
305
|
-
url: getUrl(baseURL, '/info/', {
|
|
306
|
-
jsonerrors: 1,
|
|
307
|
-
pub_key: publicKey,
|
|
308
|
-
file_id: uuid,
|
|
309
|
-
source
|
|
310
|
-
}),
|
|
311
|
-
signal
|
|
312
|
-
}).then(({ data, headers, request }) => {
|
|
313
|
-
const response = camelizeKeys(JSON.parse(data));
|
|
314
|
-
if ('error' in response) {
|
|
315
|
-
throw new UploadClientError(`[${response.error.statusCode}] ${response.error.content}`, request, response.error, headers);
|
|
316
|
-
}
|
|
317
|
-
else {
|
|
318
|
-
return response;
|
|
319
|
-
}
|
|
320
|
-
}), retryThrottledRequestMaxTimes);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
311
|
var TypeEnum;
|
|
324
312
|
(function (TypeEnum) {
|
|
325
313
|
TypeEnum["Token"] = "token";
|
|
@@ -328,12 +316,11 @@ var TypeEnum;
|
|
|
328
316
|
/**
|
|
329
317
|
* Uploading files from URL.
|
|
330
318
|
*/
|
|
331
|
-
|
|
332
|
-
function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, store, fileName, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, source = 'url', signal, integration, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
319
|
+
function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, store, fileName, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, source = 'url', signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
333
320
|
return retryIfThrottled(() => request({
|
|
334
321
|
method: 'POST',
|
|
335
322
|
headers: {
|
|
336
|
-
'X-UC-User-Agent': getUserAgent({ publicKey, integration })
|
|
323
|
+
'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
|
|
337
324
|
},
|
|
338
325
|
url: getUrl(baseURL, '/from_url/', {
|
|
339
326
|
jsonerrors: 1,
|
|
@@ -351,7 +338,7 @@ function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, stor
|
|
|
351
338
|
}).then(({ data, headers, request }) => {
|
|
352
339
|
const response = camelizeKeys(JSON.parse(data));
|
|
353
340
|
if ('error' in response) {
|
|
354
|
-
throw new UploadClientError(
|
|
341
|
+
throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
|
|
355
342
|
}
|
|
356
343
|
else {
|
|
357
344
|
return response;
|
|
@@ -373,11 +360,17 @@ const isErrorResponse = (response) => {
|
|
|
373
360
|
/**
|
|
374
361
|
* Checking upload status and working with file tokens.
|
|
375
362
|
*/
|
|
376
|
-
function fromUrlStatus(token, { publicKey, baseURL = defaultSettings.baseURL, signal, integration, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes } = {}) {
|
|
363
|
+
function fromUrlStatus(token, { publicKey, baseURL = defaultSettings.baseURL, signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes } = {}) {
|
|
377
364
|
return retryIfThrottled(() => request({
|
|
378
365
|
method: 'GET',
|
|
379
366
|
headers: publicKey
|
|
380
|
-
? {
|
|
367
|
+
? {
|
|
368
|
+
'X-UC-User-Agent': getUserAgent({
|
|
369
|
+
publicKey,
|
|
370
|
+
integration,
|
|
371
|
+
userAgent
|
|
372
|
+
})
|
|
373
|
+
}
|
|
381
374
|
: undefined,
|
|
382
375
|
url: getUrl(baseURL, '/from_url/status/', {
|
|
383
376
|
jsonerrors: 1,
|
|
@@ -387,7 +380,7 @@ function fromUrlStatus(token, { publicKey, baseURL = defaultSettings.baseURL, si
|
|
|
387
380
|
}).then(({ data, headers, request }) => {
|
|
388
381
|
const response = camelizeKeys(JSON.parse(data));
|
|
389
382
|
if ('error' in response && !isErrorResponse(response)) {
|
|
390
|
-
throw new UploadClientError(
|
|
383
|
+
throw new UploadClientError(response.error.content, undefined, request, response, headers);
|
|
391
384
|
}
|
|
392
385
|
else {
|
|
393
386
|
return response;
|
|
@@ -398,12 +391,11 @@ function fromUrlStatus(token, { publicKey, baseURL = defaultSettings.baseURL, si
|
|
|
398
391
|
/**
|
|
399
392
|
* Create files group.
|
|
400
393
|
*/
|
|
401
|
-
|
|
402
|
-
function group(uuids, { publicKey, baseURL = defaultSettings.baseURL, jsonpCallback, secureSignature, secureExpire, signal, source, integration, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
394
|
+
function group(uuids, { publicKey, baseURL = defaultSettings.baseURL, jsonpCallback, secureSignature, secureExpire, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
403
395
|
return retryIfThrottled(() => request({
|
|
404
396
|
method: 'POST',
|
|
405
397
|
headers: {
|
|
406
|
-
'X-UC-User-Agent': getUserAgent({ publicKey, integration })
|
|
398
|
+
'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
|
|
407
399
|
},
|
|
408
400
|
url: getUrl(baseURL, '/group/', {
|
|
409
401
|
jsonerrors: 1,
|
|
@@ -418,7 +410,7 @@ function group(uuids, { publicKey, baseURL = defaultSettings.baseURL, jsonpCallb
|
|
|
418
410
|
}).then(({ data, headers, request }) => {
|
|
419
411
|
const response = camelizeKeys(JSON.parse(data));
|
|
420
412
|
if ('error' in response) {
|
|
421
|
-
throw new UploadClientError(
|
|
413
|
+
throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
|
|
422
414
|
}
|
|
423
415
|
else {
|
|
424
416
|
return response;
|
|
@@ -429,12 +421,11 @@ function group(uuids, { publicKey, baseURL = defaultSettings.baseURL, jsonpCallb
|
|
|
429
421
|
/**
|
|
430
422
|
* Get info about group.
|
|
431
423
|
*/
|
|
432
|
-
|
|
433
|
-
function groupInfo(id, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
424
|
+
function groupInfo(id, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
434
425
|
return retryIfThrottled(() => request({
|
|
435
426
|
method: 'GET',
|
|
436
427
|
headers: {
|
|
437
|
-
'X-UC-User-Agent': getUserAgent({ publicKey, integration })
|
|
428
|
+
'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
|
|
438
429
|
},
|
|
439
430
|
url: getUrl(baseURL, '/group/info/', {
|
|
440
431
|
jsonerrors: 1,
|
|
@@ -446,7 +437,7 @@ function groupInfo(id, { publicKey, baseURL = defaultSettings.baseURL, signal, s
|
|
|
446
437
|
}).then(({ data, headers, request }) => {
|
|
447
438
|
const response = camelizeKeys(JSON.parse(data));
|
|
448
439
|
if ('error' in response) {
|
|
449
|
-
throw new UploadClientError(
|
|
440
|
+
throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
|
|
450
441
|
}
|
|
451
442
|
else {
|
|
452
443
|
return response;
|
|
@@ -455,62 +446,62 @@ function groupInfo(id, { publicKey, baseURL = defaultSettings.baseURL, signal, s
|
|
|
455
446
|
}
|
|
456
447
|
|
|
457
448
|
/**
|
|
458
|
-
*
|
|
449
|
+
* Returns a JSON dictionary holding file info.
|
|
459
450
|
*/
|
|
460
|
-
function
|
|
451
|
+
function info(uuid, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
461
452
|
return retryIfThrottled(() => request({
|
|
462
|
-
method: '
|
|
463
|
-
url: getUrl(baseURL, '/multipart/start/', { jsonerrors: 1 }),
|
|
453
|
+
method: 'GET',
|
|
464
454
|
headers: {
|
|
465
|
-
'X-UC-User-Agent': getUserAgent({ publicKey, integration })
|
|
455
|
+
'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
|
|
466
456
|
},
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
['UPLOADCARE_PUB_KEY', publicKey],
|
|
474
|
-
['signature', secureSignature],
|
|
475
|
-
['expire', secureExpire],
|
|
476
|
-
['source', source]
|
|
477
|
-
]),
|
|
457
|
+
url: getUrl(baseURL, '/info/', {
|
|
458
|
+
jsonerrors: 1,
|
|
459
|
+
pub_key: publicKey,
|
|
460
|
+
file_id: uuid,
|
|
461
|
+
source
|
|
462
|
+
}),
|
|
478
463
|
signal
|
|
479
464
|
}).then(({ data, headers, request }) => {
|
|
480
465
|
const response = camelizeKeys(JSON.parse(data));
|
|
481
466
|
if ('error' in response) {
|
|
482
|
-
throw new UploadClientError(
|
|
467
|
+
throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
|
|
483
468
|
}
|
|
484
469
|
else {
|
|
485
|
-
// convert to array
|
|
486
|
-
response.parts = Object.keys(response.parts).map(key => response.parts[key]);
|
|
487
470
|
return response;
|
|
488
471
|
}
|
|
489
472
|
}), retryThrottledRequestMaxTimes);
|
|
490
473
|
}
|
|
491
474
|
|
|
492
475
|
/**
|
|
493
|
-
*
|
|
476
|
+
* Start multipart uploading.
|
|
494
477
|
*/
|
|
495
|
-
function
|
|
478
|
+
function multipartStart(size, { publicKey, contentType, fileName, multipartChunkSize = defaultSettings.multipartChunkSize, baseURL = '', secureSignature, secureExpire, store, signal, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
496
479
|
return retryIfThrottled(() => request({
|
|
497
480
|
method: 'POST',
|
|
498
|
-
url: getUrl(baseURL, '/multipart/
|
|
481
|
+
url: getUrl(baseURL, '/multipart/start/', { jsonerrors: 1 }),
|
|
499
482
|
headers: {
|
|
500
|
-
'X-UC-User-Agent': getUserAgent({ publicKey, integration })
|
|
483
|
+
'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
|
|
501
484
|
},
|
|
502
485
|
data: buildFormData([
|
|
503
|
-
['
|
|
486
|
+
['filename', fileName !== null && fileName !== void 0 ? fileName : defaultFilename],
|
|
487
|
+
['size', size],
|
|
488
|
+
['content_type', contentType !== null && contentType !== void 0 ? contentType : defaultContentType],
|
|
489
|
+
['part_size', multipartChunkSize],
|
|
490
|
+
['UPLOADCARE_STORE', store ? '' : 'auto'],
|
|
504
491
|
['UPLOADCARE_PUB_KEY', publicKey],
|
|
492
|
+
['signature', secureSignature],
|
|
493
|
+
['expire', secureExpire],
|
|
505
494
|
['source', source]
|
|
506
495
|
]),
|
|
507
496
|
signal
|
|
508
497
|
}).then(({ data, headers, request }) => {
|
|
509
498
|
const response = camelizeKeys(JSON.parse(data));
|
|
510
499
|
if ('error' in response) {
|
|
511
|
-
throw new UploadClientError(
|
|
500
|
+
throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
|
|
512
501
|
}
|
|
513
502
|
else {
|
|
503
|
+
// convert to array
|
|
504
|
+
response.parts = Object.keys(response.parts).map((key) => response.parts[key]);
|
|
514
505
|
return response;
|
|
515
506
|
}
|
|
516
507
|
}), retryThrottledRequestMaxTimes);
|
|
@@ -519,20 +510,15 @@ function multipartComplete(uuid, { publicKey, baseURL = defaultSettings.baseURL,
|
|
|
519
510
|
/**
|
|
520
511
|
* Complete multipart uploading.
|
|
521
512
|
*/
|
|
522
|
-
function multipartUpload(part, url, {
|
|
513
|
+
function multipartUpload(part, url, { signal, onProgress }) {
|
|
523
514
|
return request({
|
|
524
515
|
method: 'PUT',
|
|
525
516
|
url,
|
|
526
|
-
headers: {
|
|
527
|
-
'X-UC-User-Agent': publicKey
|
|
528
|
-
? getUserAgent({ publicKey, integration })
|
|
529
|
-
: undefined
|
|
530
|
-
},
|
|
531
517
|
data: part,
|
|
532
518
|
onProgress,
|
|
533
519
|
signal
|
|
534
520
|
})
|
|
535
|
-
.then(result => {
|
|
521
|
+
.then((result) => {
|
|
536
522
|
// hack for node ¯\_(ツ)_/¯
|
|
537
523
|
if (onProgress)
|
|
538
524
|
onProgress({ value: 1 });
|
|
@@ -541,12 +527,40 @@ function multipartUpload(part, url, { publicKey, signal, onProgress, integration
|
|
|
541
527
|
.then(({ status }) => ({ code: status }));
|
|
542
528
|
}
|
|
543
529
|
|
|
530
|
+
/**
|
|
531
|
+
* Complete multipart uploading.
|
|
532
|
+
*/
|
|
533
|
+
function multipartComplete(uuid, { publicKey, baseURL = defaultSettings.baseURL, source = 'local', signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
534
|
+
return retryIfThrottled(() => request({
|
|
535
|
+
method: 'POST',
|
|
536
|
+
url: getUrl(baseURL, '/multipart/complete/', { jsonerrors: 1 }),
|
|
537
|
+
headers: {
|
|
538
|
+
'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
|
|
539
|
+
},
|
|
540
|
+
data: buildFormData([
|
|
541
|
+
['uuid', uuid],
|
|
542
|
+
['UPLOADCARE_PUB_KEY', publicKey],
|
|
543
|
+
['source', source]
|
|
544
|
+
]),
|
|
545
|
+
signal
|
|
546
|
+
}).then(({ data, headers, request }) => {
|
|
547
|
+
const response = camelizeKeys(JSON.parse(data));
|
|
548
|
+
if ('error' in response) {
|
|
549
|
+
throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
|
|
550
|
+
}
|
|
551
|
+
else {
|
|
552
|
+
return response;
|
|
553
|
+
}
|
|
554
|
+
}), retryThrottledRequestMaxTimes);
|
|
555
|
+
}
|
|
556
|
+
|
|
544
557
|
class UploadcareFile {
|
|
545
558
|
constructor(fileInfo, { baseCDN, defaultEffects, fileName }) {
|
|
546
559
|
this.name = null;
|
|
547
560
|
this.size = null;
|
|
548
561
|
this.isStored = null;
|
|
549
562
|
this.isImage = null;
|
|
563
|
+
this.mimeType = null;
|
|
550
564
|
this.cdnUrl = null;
|
|
551
565
|
this.cdnUrlModifiers = null;
|
|
552
566
|
this.originalUrl = null;
|
|
@@ -565,6 +579,7 @@ class UploadcareFile {
|
|
|
565
579
|
this.size = fileInfo.size;
|
|
566
580
|
this.isStored = fileInfo.isStored;
|
|
567
581
|
this.isImage = fileInfo.isImage;
|
|
582
|
+
this.mimeType = fileInfo.mimeType;
|
|
568
583
|
this.cdnUrl = cdnUrl;
|
|
569
584
|
this.cdnUrlModifiers = cdnUrlModifiers;
|
|
570
585
|
this.originalUrl = originalUrl;
|
|
@@ -584,7 +599,7 @@ const poll = ({ check, interval = DEFAULT_INTERVAL, signal }) => new Promise((re
|
|
|
584
599
|
const tick = () => {
|
|
585
600
|
try {
|
|
586
601
|
Promise.resolve(check(signal))
|
|
587
|
-
.then(result => {
|
|
602
|
+
.then((result) => {
|
|
588
603
|
if (result) {
|
|
589
604
|
resolve(result);
|
|
590
605
|
}
|
|
@@ -592,7 +607,7 @@ const poll = ({ check, interval = DEFAULT_INTERVAL, signal }) => new Promise((re
|
|
|
592
607
|
timeoutId = setTimeout(tick, interval);
|
|
593
608
|
}
|
|
594
609
|
})
|
|
595
|
-
.catch(error => reject(error));
|
|
610
|
+
.catch((error) => reject(error));
|
|
596
611
|
}
|
|
597
612
|
catch (error) {
|
|
598
613
|
reject(error);
|
|
@@ -601,16 +616,17 @@ const poll = ({ check, interval = DEFAULT_INTERVAL, signal }) => new Promise((re
|
|
|
601
616
|
timeoutId = setTimeout(tick, 0);
|
|
602
617
|
});
|
|
603
618
|
|
|
604
|
-
function isReadyPoll({ file, publicKey, baseURL, source, integration, retryThrottledRequestMaxTimes, signal, onProgress }) {
|
|
619
|
+
function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent, retryThrottledRequestMaxTimes, signal, onProgress }) {
|
|
605
620
|
return poll({
|
|
606
|
-
check: signal => info(file, {
|
|
621
|
+
check: (signal) => info(file, {
|
|
607
622
|
publicKey,
|
|
608
623
|
baseURL,
|
|
609
624
|
signal,
|
|
610
625
|
source,
|
|
611
626
|
integration,
|
|
627
|
+
userAgent,
|
|
612
628
|
retryThrottledRequestMaxTimes
|
|
613
|
-
}).then(response => {
|
|
629
|
+
}).then((response) => {
|
|
614
630
|
if (response.isReady) {
|
|
615
631
|
return response;
|
|
616
632
|
}
|
|
@@ -621,7 +637,7 @@ function isReadyPoll({ file, publicKey, baseURL, source, integration, retryThrot
|
|
|
621
637
|
});
|
|
622
638
|
}
|
|
623
639
|
|
|
624
|
-
const uploadFromObject = (file, { publicKey, fileName, baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, retryThrottledRequestMaxTimes, baseCDN }) => {
|
|
640
|
+
const uploadFromObject = (file, { publicKey, fileName, baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, baseCDN }) => {
|
|
625
641
|
return base(file, {
|
|
626
642
|
publicKey,
|
|
627
643
|
fileName,
|
|
@@ -633,6 +649,7 @@ const uploadFromObject = (file, { publicKey, fileName, baseURL, secureSignature,
|
|
|
633
649
|
onProgress,
|
|
634
650
|
source,
|
|
635
651
|
integration,
|
|
652
|
+
userAgent,
|
|
636
653
|
retryThrottledRequestMaxTimes
|
|
637
654
|
})
|
|
638
655
|
.then(({ file }) => {
|
|
@@ -642,14 +659,23 @@ const uploadFromObject = (file, { publicKey, fileName, baseURL, secureSignature,
|
|
|
642
659
|
baseURL,
|
|
643
660
|
source,
|
|
644
661
|
integration,
|
|
662
|
+
userAgent,
|
|
645
663
|
retryThrottledRequestMaxTimes,
|
|
646
664
|
onProgress,
|
|
647
665
|
signal
|
|
648
666
|
});
|
|
649
667
|
})
|
|
650
|
-
.then(fileInfo => new UploadcareFile(fileInfo, { baseCDN }));
|
|
668
|
+
.then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN }));
|
|
651
669
|
};
|
|
652
670
|
|
|
671
|
+
/*globals self, window */
|
|
672
|
+
|
|
673
|
+
/*eslint-disable @mysticatea/prettier */
|
|
674
|
+
const { AbortController, AbortSignal } =
|
|
675
|
+
typeof self !== "undefined" ? self :
|
|
676
|
+
typeof window !== "undefined" ? window :
|
|
677
|
+
/* otherwise */ undefined;
|
|
678
|
+
|
|
653
679
|
const race = (fns, { signal } = {}) => {
|
|
654
680
|
let lastError = null;
|
|
655
681
|
let winnerIndex = null;
|
|
@@ -659,21 +685,21 @@ const race = (fns, { signal } = {}) => {
|
|
|
659
685
|
controllers.forEach((controller, index) => index !== i && controller.abort());
|
|
660
686
|
};
|
|
661
687
|
onCancel(signal, () => {
|
|
662
|
-
controllers.forEach(controller => controller.abort());
|
|
688
|
+
controllers.forEach((controller) => controller.abort());
|
|
663
689
|
});
|
|
664
690
|
return Promise.all(fns.map((fn, i) => {
|
|
665
691
|
const stopRace = createStopRaceCallback(i);
|
|
666
692
|
return Promise.resolve()
|
|
667
693
|
.then(() => fn({ stopRace, signal: controllers[i].signal }))
|
|
668
|
-
.then(result => {
|
|
694
|
+
.then((result) => {
|
|
669
695
|
stopRace();
|
|
670
696
|
return result;
|
|
671
697
|
})
|
|
672
|
-
.catch(error => {
|
|
698
|
+
.catch((error) => {
|
|
673
699
|
lastError = error;
|
|
674
700
|
return null;
|
|
675
701
|
});
|
|
676
|
-
})).then(results => {
|
|
702
|
+
})).then((results) => {
|
|
677
703
|
if (winnerIndex === null) {
|
|
678
704
|
throw lastError;
|
|
679
705
|
}
|
|
@@ -691,7 +717,7 @@ class Events {
|
|
|
691
717
|
}
|
|
692
718
|
emit(event, data) {
|
|
693
719
|
var _a;
|
|
694
|
-
(_a = this.events[event]) === null || _a === void 0 ? void 0 : _a.forEach(fn => fn(data));
|
|
720
|
+
(_a = this.events[event]) === null || _a === void 0 ? void 0 : _a.forEach((fn) => fn(data));
|
|
695
721
|
}
|
|
696
722
|
on(event, callback) {
|
|
697
723
|
this.events[event] = this.events[event] || [];
|
|
@@ -699,7 +725,7 @@ class Events {
|
|
|
699
725
|
}
|
|
700
726
|
off(event, callback) {
|
|
701
727
|
if (callback) {
|
|
702
|
-
this.events[event] = this.events[event].filter(fn => fn !== callback);
|
|
728
|
+
this.events[event] = this.events[event].filter((fn) => fn !== callback);
|
|
703
729
|
}
|
|
704
730
|
else {
|
|
705
731
|
this.events[event] = [];
|
|
@@ -732,16 +758,16 @@ class Pusher {
|
|
|
732
758
|
if (!this.isConnected && !this.ws) {
|
|
733
759
|
const pusherUrl = `wss://ws.pusherapp.com/app/${this.key}?protocol=5&client=js&version=1.12.2`;
|
|
734
760
|
this.ws = new WebSocket(pusherUrl);
|
|
735
|
-
this.ws.addEventListener('error', error => {
|
|
761
|
+
this.ws.addEventListener('error', (error) => {
|
|
736
762
|
this.emmitter.emit('error', new Error(error.message));
|
|
737
763
|
});
|
|
738
764
|
this.emmitter.on('connected', () => {
|
|
739
765
|
this.isConnected = true;
|
|
740
|
-
this.queue.forEach(message => this.send(message.event, message.data));
|
|
766
|
+
this.queue.forEach((message) => this.send(message.event, message.data));
|
|
741
767
|
this.queue = [];
|
|
742
768
|
});
|
|
743
|
-
this.ws.addEventListener('message', e => {
|
|
744
|
-
const data = JSON.parse(e.data);
|
|
769
|
+
this.ws.addEventListener('message', (e) => {
|
|
770
|
+
const data = JSON.parse(e.data.toString());
|
|
745
771
|
switch (data.event) {
|
|
746
772
|
case 'pusher:connection_established': {
|
|
747
773
|
this.emmitter.emit('connected', undefined);
|
|
@@ -809,7 +835,7 @@ class Pusher {
|
|
|
809
835
|
this.send(message.event, message.data);
|
|
810
836
|
}
|
|
811
837
|
else {
|
|
812
|
-
this.queue = this.queue.filter(msg => msg.data.channel !== channel);
|
|
838
|
+
this.queue = this.queue.filter((msg) => msg.data.channel !== channel);
|
|
813
839
|
}
|
|
814
840
|
if (this.subscribers === 0) {
|
|
815
841
|
this.disconnect();
|
|
@@ -833,18 +859,19 @@ const preconnect = (key) => {
|
|
|
833
859
|
getPusher(key).connect();
|
|
834
860
|
};
|
|
835
861
|
|
|
836
|
-
function pollStrategy({ token, publicKey, baseURL, integration, retryThrottledRequestMaxTimes, onProgress, signal }) {
|
|
862
|
+
function pollStrategy({ token, publicKey, baseURL, integration, userAgent, retryThrottledRequestMaxTimes, onProgress, signal }) {
|
|
837
863
|
return poll({
|
|
838
|
-
check: signal => fromUrlStatus(token, {
|
|
864
|
+
check: (signal) => fromUrlStatus(token, {
|
|
839
865
|
publicKey,
|
|
840
866
|
baseURL,
|
|
841
867
|
integration,
|
|
868
|
+
userAgent,
|
|
842
869
|
retryThrottledRequestMaxTimes,
|
|
843
870
|
signal
|
|
844
|
-
}).then(response => {
|
|
871
|
+
}).then((response) => {
|
|
845
872
|
switch (response.status) {
|
|
846
873
|
case Status.Error: {
|
|
847
|
-
return new UploadClientError(response.error);
|
|
874
|
+
return new UploadClientError(response.error, response.errorCode);
|
|
848
875
|
}
|
|
849
876
|
case Status.Waiting: {
|
|
850
877
|
return false;
|
|
@@ -870,7 +897,7 @@ function pollStrategy({ token, publicKey, baseURL, integration, retryThrottledRe
|
|
|
870
897
|
signal
|
|
871
898
|
});
|
|
872
899
|
}
|
|
873
|
-
const pushStrategy = ({ token, pusherKey, signal,
|
|
900
|
+
const pushStrategy = ({ token, pusherKey, signal, onProgress }) => new Promise((resolve, reject) => {
|
|
874
901
|
const pusher = getPusher(pusherKey);
|
|
875
902
|
const unsubErrorHandler = pusher.onError(reject);
|
|
876
903
|
const destroy = () => {
|
|
@@ -879,10 +906,9 @@ const pushStrategy = ({ token, pusherKey, signal, stopRace, onProgress }) => new
|
|
|
879
906
|
};
|
|
880
907
|
onCancel(signal, () => {
|
|
881
908
|
destroy();
|
|
882
|
-
reject(cancelError('
|
|
909
|
+
reject(cancelError('pusher cancelled'));
|
|
883
910
|
});
|
|
884
|
-
pusher.subscribe(token, result => {
|
|
885
|
-
stopRace();
|
|
911
|
+
pusher.subscribe(token, (result) => {
|
|
886
912
|
switch (result.status) {
|
|
887
913
|
case Status.Progress: {
|
|
888
914
|
if (onProgress) {
|
|
@@ -899,12 +925,12 @@ const pushStrategy = ({ token, pusherKey, signal, stopRace, onProgress }) => new
|
|
|
899
925
|
}
|
|
900
926
|
case Status.Error: {
|
|
901
927
|
destroy();
|
|
902
|
-
reject(new UploadClientError(result.msg));
|
|
928
|
+
reject(new UploadClientError(result.msg, result.error_code));
|
|
903
929
|
}
|
|
904
930
|
}
|
|
905
931
|
});
|
|
906
932
|
});
|
|
907
|
-
const uploadFromUrl = (sourceUrl, { publicKey, fileName, baseURL, baseCDN, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, store, signal, onProgress, source, integration, retryThrottledRequestMaxTimes, pusherKey = defaultSettings.pusherKey }) => Promise.resolve(preconnect(pusherKey))
|
|
933
|
+
const uploadFromUrl = (sourceUrl, { publicKey, fileName, baseURL, baseCDN, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, pusherKey = defaultSettings.pusherKey }) => Promise.resolve(preconnect(pusherKey))
|
|
908
934
|
.then(() => fromUrl(sourceUrl, {
|
|
909
935
|
publicKey,
|
|
910
936
|
fileName,
|
|
@@ -917,9 +943,15 @@ const uploadFromUrl = (sourceUrl, { publicKey, fileName, baseURL, baseCDN, check
|
|
|
917
943
|
signal,
|
|
918
944
|
source,
|
|
919
945
|
integration,
|
|
946
|
+
userAgent,
|
|
920
947
|
retryThrottledRequestMaxTimes
|
|
921
948
|
}))
|
|
922
|
-
.
|
|
949
|
+
.catch((error) => {
|
|
950
|
+
const pusher = getPusher(pusherKey);
|
|
951
|
+
pusher === null || pusher === void 0 ? void 0 : pusher.disconnect();
|
|
952
|
+
return Promise.reject(error);
|
|
953
|
+
})
|
|
954
|
+
.then((urlResponse) => {
|
|
923
955
|
if (urlResponse.type === TypeEnum.FileInfo) {
|
|
924
956
|
return urlResponse;
|
|
925
957
|
}
|
|
@@ -930,47 +962,49 @@ const uploadFromUrl = (sourceUrl, { publicKey, fileName, baseURL, baseCDN, check
|
|
|
930
962
|
publicKey,
|
|
931
963
|
baseURL,
|
|
932
964
|
integration,
|
|
965
|
+
userAgent,
|
|
933
966
|
retryThrottledRequestMaxTimes,
|
|
934
967
|
onProgress,
|
|
935
968
|
signal
|
|
936
969
|
}),
|
|
937
|
-
({
|
|
970
|
+
({ signal }) => pushStrategy({
|
|
938
971
|
token: urlResponse.token,
|
|
939
972
|
pusherKey,
|
|
940
|
-
stopRace,
|
|
941
973
|
signal,
|
|
942
974
|
onProgress
|
|
943
975
|
})
|
|
944
976
|
], { signal });
|
|
945
977
|
}
|
|
946
978
|
})
|
|
947
|
-
.then(result => {
|
|
979
|
+
.then((result) => {
|
|
948
980
|
if (result instanceof UploadClientError)
|
|
949
981
|
throw result;
|
|
950
982
|
return result;
|
|
951
983
|
})
|
|
952
|
-
.then(result => isReadyPoll({
|
|
984
|
+
.then((result) => isReadyPoll({
|
|
953
985
|
file: result.uuid,
|
|
954
986
|
publicKey,
|
|
955
987
|
baseURL,
|
|
956
988
|
integration,
|
|
989
|
+
userAgent,
|
|
957
990
|
retryThrottledRequestMaxTimes,
|
|
958
991
|
onProgress,
|
|
959
992
|
signal
|
|
960
993
|
}))
|
|
961
|
-
.then(fileInfo => new UploadcareFile(fileInfo, { baseCDN }));
|
|
994
|
+
.then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN }));
|
|
962
995
|
|
|
963
|
-
const uploadFromUploaded = (uuid, { publicKey, fileName, baseURL, signal, onProgress, source, integration, retryThrottledRequestMaxTimes, baseCDN }) => {
|
|
996
|
+
const uploadFromUploaded = (uuid, { publicKey, fileName, baseURL, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, baseCDN }) => {
|
|
964
997
|
return info(uuid, {
|
|
965
998
|
publicKey,
|
|
966
999
|
baseURL,
|
|
967
1000
|
signal,
|
|
968
1001
|
source,
|
|
969
1002
|
integration,
|
|
1003
|
+
userAgent,
|
|
970
1004
|
retryThrottledRequestMaxTimes
|
|
971
1005
|
})
|
|
972
|
-
.then(fileInfo => new UploadcareFile(fileInfo, { baseCDN, fileName }))
|
|
973
|
-
.then(result => {
|
|
1006
|
+
.then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN, fileName }))
|
|
1007
|
+
.then((result) => {
|
|
974
1008
|
// hack for node ¯\_(ツ)_/¯
|
|
975
1009
|
if (onProgress)
|
|
976
1010
|
onProgress({ value: 1 });
|
|
@@ -1019,6 +1053,16 @@ const isMultipart = (fileSize, multipartMinFileSize = defaultSettings.multipartM
|
|
|
1019
1053
|
return fileSize >= multipartMinFileSize;
|
|
1020
1054
|
};
|
|
1021
1055
|
|
|
1056
|
+
const sliceChunk = (file, index, fileSize, chunkSize) => {
|
|
1057
|
+
const start = chunkSize * index;
|
|
1058
|
+
const end = Math.min(start + chunkSize, fileSize);
|
|
1059
|
+
return file.slice(start, end);
|
|
1060
|
+
};
|
|
1061
|
+
|
|
1062
|
+
function prepareChunks(file, fileSize, chunkSize) {
|
|
1063
|
+
return (index) => sliceChunk(file, index, fileSize, chunkSize);
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1022
1066
|
const runWithConcurrency = (concurrency, tasks) => {
|
|
1023
1067
|
return new Promise((resolve, reject) => {
|
|
1024
1068
|
const results = [];
|
|
@@ -1042,7 +1086,7 @@ const runWithConcurrency = (concurrency, tasks) => {
|
|
|
1042
1086
|
resolve(results);
|
|
1043
1087
|
}
|
|
1044
1088
|
})
|
|
1045
|
-
.catch(error => {
|
|
1089
|
+
.catch((error) => {
|
|
1046
1090
|
rejected = true;
|
|
1047
1091
|
reject(error);
|
|
1048
1092
|
});
|
|
@@ -1054,23 +1098,18 @@ const runWithConcurrency = (concurrency, tasks) => {
|
|
|
1054
1098
|
});
|
|
1055
1099
|
};
|
|
1056
1100
|
|
|
1057
|
-
const getChunk = (file, index, fileSize, chunkSize) => {
|
|
1058
|
-
const start = chunkSize * index;
|
|
1059
|
-
const end = Math.min(start + chunkSize, fileSize);
|
|
1060
|
-
return file.slice(start, end);
|
|
1061
|
-
};
|
|
1062
1101
|
const uploadPartWithRetry = (chunk, url, { publicKey, onProgress, signal, integration, multipartMaxAttempts }) => retrier(({ attempt, retry }) => multipartUpload(chunk, url, {
|
|
1063
1102
|
publicKey,
|
|
1064
1103
|
onProgress,
|
|
1065
1104
|
signal,
|
|
1066
1105
|
integration
|
|
1067
|
-
}).catch(error => {
|
|
1106
|
+
}).catch((error) => {
|
|
1068
1107
|
if (attempt < multipartMaxAttempts) {
|
|
1069
1108
|
return retry();
|
|
1070
1109
|
}
|
|
1071
1110
|
throw error;
|
|
1072
1111
|
}));
|
|
1073
|
-
const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, retryThrottledRequestMaxTimes, contentType, multipartChunkSize = defaultSettings.multipartChunkSize, maxConcurrentRequests = defaultSettings.maxConcurrentRequests, multipartMaxAttempts = defaultSettings.multipartMaxAttempts, baseCDN }) => {
|
|
1112
|
+
const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, contentType, multipartChunkSize = defaultSettings.multipartChunkSize, maxConcurrentRequests = defaultSettings.maxConcurrentRequests, multipartMaxAttempts = defaultSettings.multipartMaxAttempts, baseCDN }) => {
|
|
1074
1113
|
const size = fileSize || getFileSize(file);
|
|
1075
1114
|
let progressValues;
|
|
1076
1115
|
const createProgressHandler = (size, index) => {
|
|
@@ -1096,26 +1135,31 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
|
|
|
1096
1135
|
signal,
|
|
1097
1136
|
source,
|
|
1098
1137
|
integration,
|
|
1138
|
+
userAgent,
|
|
1099
1139
|
retryThrottledRequestMaxTimes
|
|
1100
1140
|
})
|
|
1101
|
-
.then(({ uuid, parts }) =>
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1141
|
+
.then(({ uuid, parts }) => {
|
|
1142
|
+
const getChunk = prepareChunks(file, size, multipartChunkSize);
|
|
1143
|
+
return Promise.all([
|
|
1144
|
+
uuid,
|
|
1145
|
+
runWithConcurrency(maxConcurrentRequests, parts.map((url, index) => () => uploadPartWithRetry(getChunk(index), url, {
|
|
1146
|
+
publicKey,
|
|
1147
|
+
onProgress: createProgressHandler(parts.length, index),
|
|
1148
|
+
signal,
|
|
1149
|
+
integration,
|
|
1150
|
+
multipartMaxAttempts
|
|
1151
|
+
})))
|
|
1152
|
+
]);
|
|
1153
|
+
})
|
|
1111
1154
|
.then(([uuid]) => multipartComplete(uuid, {
|
|
1112
1155
|
publicKey,
|
|
1113
1156
|
baseURL,
|
|
1114
1157
|
source,
|
|
1115
1158
|
integration,
|
|
1159
|
+
userAgent,
|
|
1116
1160
|
retryThrottledRequestMaxTimes
|
|
1117
1161
|
}))
|
|
1118
|
-
.then(fileInfo => {
|
|
1162
|
+
.then((fileInfo) => {
|
|
1119
1163
|
if (fileInfo.isReady) {
|
|
1120
1164
|
return fileInfo;
|
|
1121
1165
|
}
|
|
@@ -1126,19 +1170,20 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
|
|
|
1126
1170
|
baseURL,
|
|
1127
1171
|
source,
|
|
1128
1172
|
integration,
|
|
1173
|
+
userAgent,
|
|
1129
1174
|
retryThrottledRequestMaxTimes,
|
|
1130
1175
|
onProgress,
|
|
1131
1176
|
signal
|
|
1132
1177
|
});
|
|
1133
1178
|
}
|
|
1134
1179
|
})
|
|
1135
|
-
.then(fileInfo => new UploadcareFile(fileInfo, { baseCDN }));
|
|
1180
|
+
.then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN }));
|
|
1136
1181
|
};
|
|
1137
1182
|
|
|
1138
1183
|
/**
|
|
1139
1184
|
* Uploads file from provided data.
|
|
1140
1185
|
*/
|
|
1141
|
-
function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, retryThrottledRequestMaxTimes, contentType, multipartChunkSize
|
|
1186
|
+
function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, contentType, multipartChunkSize, multipartMaxAttempts, maxConcurrentRequests, baseCDN = defaultSettings.baseCDN, checkForUrlDuplicates, saveUrlForRecurrentUploads, pusherKey }) {
|
|
1142
1187
|
if (isFileData(data)) {
|
|
1143
1188
|
const fileSize = getFileSize(data);
|
|
1144
1189
|
if (isMultipart(fileSize)) {
|
|
@@ -1146,6 +1191,7 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
|
|
|
1146
1191
|
publicKey,
|
|
1147
1192
|
contentType,
|
|
1148
1193
|
multipartChunkSize,
|
|
1194
|
+
multipartMaxAttempts,
|
|
1149
1195
|
fileName,
|
|
1150
1196
|
baseURL,
|
|
1151
1197
|
secureSignature,
|
|
@@ -1155,6 +1201,8 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
|
|
|
1155
1201
|
onProgress,
|
|
1156
1202
|
source,
|
|
1157
1203
|
integration,
|
|
1204
|
+
userAgent,
|
|
1205
|
+
maxConcurrentRequests,
|
|
1158
1206
|
retryThrottledRequestMaxTimes,
|
|
1159
1207
|
baseCDN
|
|
1160
1208
|
});
|
|
@@ -1170,6 +1218,7 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
|
|
|
1170
1218
|
onProgress,
|
|
1171
1219
|
source,
|
|
1172
1220
|
integration,
|
|
1221
|
+
userAgent,
|
|
1173
1222
|
retryThrottledRequestMaxTimes,
|
|
1174
1223
|
baseCDN
|
|
1175
1224
|
});
|
|
@@ -1179,6 +1228,9 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
|
|
|
1179
1228
|
publicKey,
|
|
1180
1229
|
fileName,
|
|
1181
1230
|
baseURL,
|
|
1231
|
+
baseCDN,
|
|
1232
|
+
checkForUrlDuplicates,
|
|
1233
|
+
saveUrlForRecurrentUploads,
|
|
1182
1234
|
secureSignature,
|
|
1183
1235
|
secureExpire,
|
|
1184
1236
|
store,
|
|
@@ -1186,8 +1238,9 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
|
|
|
1186
1238
|
onProgress,
|
|
1187
1239
|
source,
|
|
1188
1240
|
integration,
|
|
1241
|
+
userAgent,
|
|
1189
1242
|
retryThrottledRequestMaxTimes,
|
|
1190
|
-
|
|
1243
|
+
pusherKey
|
|
1191
1244
|
});
|
|
1192
1245
|
}
|
|
1193
1246
|
if (isUuid(data)) {
|
|
@@ -1199,6 +1252,7 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
|
|
|
1199
1252
|
onProgress,
|
|
1200
1253
|
source,
|
|
1201
1254
|
integration,
|
|
1255
|
+
userAgent,
|
|
1202
1256
|
retryThrottledRequestMaxTimes,
|
|
1203
1257
|
baseCDN
|
|
1204
1258
|
});
|
|
@@ -1213,8 +1267,7 @@ class UploadcareGroup {
|
|
|
1213
1267
|
this.filesCount = groupInfo.filesCount;
|
|
1214
1268
|
this.totalSize = Object.values(groupInfo.files).reduce((acc, file) => acc + file.size, 0);
|
|
1215
1269
|
this.isStored = !!groupInfo.datetimeStored;
|
|
1216
|
-
this.isImage = !!Object.values(groupInfo.files).filter(file => file.isImage)
|
|
1217
|
-
.length;
|
|
1270
|
+
this.isImage = !!Object.values(groupInfo.files).filter((file) => file.isImage).length;
|
|
1218
1271
|
this.cdnUrl = groupInfo.cdnUrl;
|
|
1219
1272
|
this.files = files;
|
|
1220
1273
|
this.createdAt = groupInfo.datetimeCreated;
|
|
@@ -1256,7 +1309,7 @@ const isUrlArray = (data) => {
|
|
|
1256
1309
|
return true;
|
|
1257
1310
|
};
|
|
1258
1311
|
|
|
1259
|
-
function uploadFileGroup(data, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, retryThrottledRequestMaxTimes, contentType, multipartChunkSize = defaultSettings.multipartChunkSize, baseCDN = defaultSettings.baseCDN, jsonpCallback, defaultEffects }) {
|
|
1312
|
+
function uploadFileGroup(data, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, contentType, multipartChunkSize = defaultSettings.multipartChunkSize, baseCDN = defaultSettings.baseCDN, jsonpCallback, defaultEffects }) {
|
|
1260
1313
|
if (!isFileDataArray(data) && !isUrlArray(data) && !isUuidArray(data)) {
|
|
1261
1314
|
throw new TypeError(`Group uploading from "${data}" is not supported`);
|
|
1262
1315
|
}
|
|
@@ -1285,12 +1338,13 @@ function uploadFileGroup(data, { publicKey, fileName, baseURL = defaultSettings.
|
|
|
1285
1338
|
onProgress: createProgressHandler(filesCount, index),
|
|
1286
1339
|
source,
|
|
1287
1340
|
integration,
|
|
1341
|
+
userAgent,
|
|
1288
1342
|
retryThrottledRequestMaxTimes,
|
|
1289
1343
|
contentType,
|
|
1290
1344
|
multipartChunkSize,
|
|
1291
1345
|
baseCDN
|
|
1292
|
-
}))).then(files => {
|
|
1293
|
-
const uuids = files.map(file => file.uuid);
|
|
1346
|
+
}))).then((files) => {
|
|
1347
|
+
const uuids = files.map((file) => file.uuid);
|
|
1294
1348
|
const addDefaultEffects = (file) => {
|
|
1295
1349
|
const cdnUrlModifiers = defaultEffects ? `-/${defaultEffects}` : null;
|
|
1296
1350
|
const cdnUrl = `${file.urlBase}${cdnUrlModifiers || ''}`;
|
|
@@ -1307,8 +1361,9 @@ function uploadFileGroup(data, { publicKey, fileName, baseURL = defaultSettings.
|
|
|
1307
1361
|
signal,
|
|
1308
1362
|
source,
|
|
1309
1363
|
integration,
|
|
1364
|
+
userAgent,
|
|
1310
1365
|
retryThrottledRequestMaxTimes
|
|
1311
|
-
}).then(groupInfo => new UploadcareGroup(groupInfo, filesInGroup));
|
|
1366
|
+
}).then((groupInfo) => new UploadcareGroup(groupInfo, filesInGroup));
|
|
1312
1367
|
});
|
|
1313
1368
|
}
|
|
1314
1369
|
|
|
@@ -1372,4 +1427,4 @@ class UploadClient {
|
|
|
1372
1427
|
}
|
|
1373
1428
|
}
|
|
1374
1429
|
|
|
1375
|
-
export { AbortController, UploadClient, base, fromUrl, fromUrlStatus, group, groupInfo, info, multipartComplete, multipartStart, multipartUpload, uploadFile, uploadFileGroup };
|
|
1430
|
+
export { AbortController, UploadClient, base, fromUrl, fromUrlStatus, group, groupInfo, info, multipartComplete, multipartStart, multipartUpload, uploadFromObject as uploadBase, uploadFile, uploadFileGroup, uploadFromUploaded, uploadFromUrl, uploadMultipart };
|