@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.js
CHANGED
|
@@ -1,37 +1,18 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import { request as request$1 } from 'http';
|
|
4
|
-
import { request as request$2 } from 'https';
|
|
1
|
+
import http from 'http';
|
|
2
|
+
import https from 'https';
|
|
5
3
|
import { parse } from 'url';
|
|
6
4
|
import { Transform, Readable } from 'stream';
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
Settings for future support:
|
|
12
|
-
parallelDirectUploads: 10,
|
|
13
|
-
*/
|
|
14
|
-
const defaultSettings = {
|
|
15
|
-
baseCDN: 'https://ucarecdn.com',
|
|
16
|
-
baseURL: 'https://upload.uploadcare.com',
|
|
17
|
-
maxContentLength: 50 * 1024 * 1024,
|
|
18
|
-
retryThrottledRequestMaxTimes: 1,
|
|
19
|
-
multipartMinFileSize: 25 * 1024 * 1024,
|
|
20
|
-
multipartChunkSize: 5 * 1024 * 1024,
|
|
21
|
-
multipartMinLastPartSize: 1024 * 1024,
|
|
22
|
-
maxConcurrentRequests: 4,
|
|
23
|
-
multipartMaxAttempts: 3,
|
|
24
|
-
pollingTimeoutMilliseconds: 10000,
|
|
25
|
-
pusherKey: '79ae88bd931ea68464d9'
|
|
26
|
-
};
|
|
27
|
-
const defaultContentType = 'application/octet-stream';
|
|
28
|
-
const defaultFilename = 'original';
|
|
5
|
+
import NodeFormData from 'form-data';
|
|
6
|
+
import { AbortController } from 'abort-controller';
|
|
7
|
+
export { AbortController } from 'abort-controller';
|
|
8
|
+
import WebSocket from 'ws';
|
|
29
9
|
|
|
30
10
|
class UploadClientError extends Error {
|
|
31
|
-
constructor(message, request, response, headers) {
|
|
11
|
+
constructor(message, code, request, response, headers) {
|
|
32
12
|
super();
|
|
33
13
|
this.name = 'UploadClientError';
|
|
34
14
|
this.message = message;
|
|
15
|
+
this.code = code;
|
|
35
16
|
this.request = request;
|
|
36
17
|
this.response = response;
|
|
37
18
|
this.headers = headers;
|
|
@@ -102,7 +83,7 @@ const request = (params) => {
|
|
|
102
83
|
return undefined;
|
|
103
84
|
}
|
|
104
85
|
})
|
|
105
|
-
.then(length => new Promise((resolve, reject) => {
|
|
86
|
+
.then((length) => new Promise((resolve, reject) => {
|
|
106
87
|
const isFormData = !!length;
|
|
107
88
|
let aborted = false;
|
|
108
89
|
const options = parse(url);
|
|
@@ -115,19 +96,19 @@ const request = (params) => {
|
|
|
115
96
|
length || data.length;
|
|
116
97
|
}
|
|
117
98
|
const req = options.protocol !== 'https:'
|
|
118
|
-
? request
|
|
119
|
-
: request
|
|
99
|
+
? http.request(options)
|
|
100
|
+
: https.request(options);
|
|
120
101
|
onCancel(signal, () => {
|
|
121
102
|
aborted = true;
|
|
122
103
|
req.abort();
|
|
123
104
|
reject(cancelError());
|
|
124
105
|
});
|
|
125
|
-
req.on('response', res => {
|
|
106
|
+
req.on('response', (res) => {
|
|
126
107
|
if (aborted)
|
|
127
108
|
return;
|
|
128
109
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
129
110
|
const resChunks = [];
|
|
130
|
-
res.on('data', data => {
|
|
111
|
+
res.on('data', (data) => {
|
|
131
112
|
resChunks.push(data);
|
|
132
113
|
});
|
|
133
114
|
res.on('end', () => resolve({
|
|
@@ -137,7 +118,7 @@ const request = (params) => {
|
|
|
137
118
|
request: params
|
|
138
119
|
}));
|
|
139
120
|
});
|
|
140
|
-
req.on('error', err => {
|
|
121
|
+
req.on('error', (err) => {
|
|
141
122
|
if (aborted)
|
|
142
123
|
return;
|
|
143
124
|
reject(err);
|
|
@@ -156,18 +137,25 @@ const request = (params) => {
|
|
|
156
137
|
}));
|
|
157
138
|
};
|
|
158
139
|
|
|
140
|
+
function identity(obj) {
|
|
141
|
+
return obj;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const transformFile = identity;
|
|
159
145
|
var getFormData = () => new NodeFormData();
|
|
160
146
|
|
|
147
|
+
const isFileTuple = (tuple) => tuple[0] === 'file';
|
|
161
148
|
function buildFormData(body) {
|
|
162
149
|
const formData = getFormData();
|
|
163
|
-
const isTriple = (tuple) => tuple[0] === 'file';
|
|
164
150
|
for (const tuple of body) {
|
|
165
151
|
if (Array.isArray(tuple[1])) {
|
|
166
152
|
// refactor this
|
|
167
|
-
tuple[1].forEach(val => val && formData.append(tuple[0] + '[]', `${val}`));
|
|
153
|
+
tuple[1].forEach((val) => val && formData.append(tuple[0] + '[]', `${val}`));
|
|
168
154
|
}
|
|
169
|
-
else if (
|
|
170
|
-
|
|
155
|
+
else if (isFileTuple(tuple)) {
|
|
156
|
+
const name = tuple[2];
|
|
157
|
+
const file = transformFile(tuple[1]); // lgtm[js/superfluous-trailing-arguments]
|
|
158
|
+
formData.append(tuple[0], file, name);
|
|
171
159
|
}
|
|
172
160
|
else if (tuple[1] != null) {
|
|
173
161
|
formData.append(tuple[0], `${tuple[1]}`);
|
|
@@ -179,9 +167,9 @@ function buildFormData(body) {
|
|
|
179
167
|
const serializePair = (key, value) => typeof value !== 'undefined' ? `${key}=${encodeURIComponent(value)}` : null;
|
|
180
168
|
const createQuery = (query) => Object.entries(query)
|
|
181
169
|
.reduce((params, [key, value]) => params.concat(Array.isArray(value)
|
|
182
|
-
? value.map(value => serializePair(`${key}[]`, value))
|
|
170
|
+
? value.map((value) => serializePair(`${key}[]`, value))
|
|
183
171
|
: serializePair(key, value)), [])
|
|
184
|
-
.filter(x => !!x)
|
|
172
|
+
.filter((x) => !!x)
|
|
185
173
|
.join('&');
|
|
186
174
|
const getUrl = (base, path, query) => [
|
|
187
175
|
base,
|
|
@@ -192,15 +180,52 @@ const getUrl = (base, path, query) => [
|
|
|
192
180
|
.filter(Boolean)
|
|
193
181
|
.join('');
|
|
194
182
|
|
|
195
|
-
|
|
183
|
+
/*
|
|
184
|
+
Settings for future support:
|
|
185
|
+
parallelDirectUploads: 10,
|
|
186
|
+
*/
|
|
187
|
+
const defaultSettings = {
|
|
188
|
+
baseCDN: 'https://ucarecdn.com',
|
|
189
|
+
baseURL: 'https://upload.uploadcare.com',
|
|
190
|
+
maxContentLength: 50 * 1024 * 1024,
|
|
191
|
+
retryThrottledRequestMaxTimes: 1,
|
|
192
|
+
multipartMinFileSize: 25 * 1024 * 1024,
|
|
193
|
+
multipartChunkSize: 5 * 1024 * 1024,
|
|
194
|
+
multipartMinLastPartSize: 1024 * 1024,
|
|
195
|
+
maxConcurrentRequests: 4,
|
|
196
|
+
multipartMaxAttempts: 3,
|
|
197
|
+
pollingTimeoutMilliseconds: 10000,
|
|
198
|
+
pusherKey: '79ae88bd931ea68464d9'
|
|
199
|
+
};
|
|
200
|
+
const defaultContentType = 'application/octet-stream';
|
|
201
|
+
const defaultFilename = 'original';
|
|
202
|
+
|
|
203
|
+
var version = '2.0.0';
|
|
196
204
|
|
|
197
205
|
/**
|
|
198
206
|
* Returns User Agent based on version and settings.
|
|
199
207
|
*/
|
|
200
|
-
function getUserAgent({ publicKey = '', integration = '' } = {}) {
|
|
201
|
-
const
|
|
202
|
-
const
|
|
203
|
-
|
|
208
|
+
function getUserAgent({ userAgent, publicKey = '', integration = '' } = {}) {
|
|
209
|
+
const libraryName = 'UploadcareUploadClient';
|
|
210
|
+
const libraryVersion = version;
|
|
211
|
+
const languageName = 'JavaScript';
|
|
212
|
+
if (typeof userAgent === 'string') {
|
|
213
|
+
return userAgent;
|
|
214
|
+
}
|
|
215
|
+
if (typeof userAgent === 'function') {
|
|
216
|
+
return userAgent({
|
|
217
|
+
publicKey,
|
|
218
|
+
libraryName,
|
|
219
|
+
libraryVersion,
|
|
220
|
+
languageName,
|
|
221
|
+
integration
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
const mainInfo = [libraryName, libraryVersion, publicKey]
|
|
225
|
+
.filter(Boolean)
|
|
226
|
+
.join('/');
|
|
227
|
+
const additionInfo = [languageName, integration].filter(Boolean).join('; ');
|
|
228
|
+
return `${mainInfo} (${additionInfo})`;
|
|
204
229
|
}
|
|
205
230
|
|
|
206
231
|
const SEPARATOR = /\W|_/g;
|
|
@@ -234,7 +259,7 @@ function camelizeKeys(source) {
|
|
|
234
259
|
*
|
|
235
260
|
* @param {number} ms Timeout in milliseconds.
|
|
236
261
|
*/
|
|
237
|
-
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
262
|
+
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
238
263
|
|
|
239
264
|
const defaultOptions = {
|
|
240
265
|
factor: 2,
|
|
@@ -256,7 +281,7 @@ function retrier(fn, options = defaultOptions) {
|
|
|
256
281
|
return runAttempt(fn);
|
|
257
282
|
}
|
|
258
283
|
|
|
259
|
-
const REQUEST_WAS_THROTTLED_CODE =
|
|
284
|
+
const REQUEST_WAS_THROTTLED_CODE = 'RequestThrottledError';
|
|
260
285
|
const DEFAULT_RETRY_AFTER_TIMEOUT = 15000;
|
|
261
286
|
function getTimeoutFromThrottledRequest(error) {
|
|
262
287
|
const { headers } = error || {};
|
|
@@ -266,9 +291,8 @@ function getTimeoutFromThrottledRequest(error) {
|
|
|
266
291
|
}
|
|
267
292
|
function retryIfThrottled(fn, retryThrottledMaxTimes) {
|
|
268
293
|
return retrier(({ attempt, retry }) => fn().catch((error) => {
|
|
269
|
-
var _a;
|
|
270
294
|
if ('response' in error &&
|
|
271
|
-
(
|
|
295
|
+
(error === null || error === void 0 ? void 0 : error.code) === REQUEST_WAS_THROTTLED_CODE &&
|
|
272
296
|
attempt < retryThrottledMaxTimes) {
|
|
273
297
|
return retry(getTimeoutFromThrottledRequest(error));
|
|
274
298
|
}
|
|
@@ -280,7 +304,7 @@ function retryIfThrottled(fn, retryThrottledMaxTimes) {
|
|
|
280
304
|
* Performs file uploading request to Uploadcare Upload API.
|
|
281
305
|
* Can be canceled and has progress.
|
|
282
306
|
*/
|
|
283
|
-
function base(file, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source = 'local', integration, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
307
|
+
function base(file, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
284
308
|
return retryIfThrottled(() => {
|
|
285
309
|
var _a;
|
|
286
310
|
return request({
|
|
@@ -289,7 +313,7 @@ function base(file, { publicKey, fileName, baseURL = defaultSettings.baseURL, se
|
|
|
289
313
|
jsonerrors: 1
|
|
290
314
|
}),
|
|
291
315
|
headers: {
|
|
292
|
-
'X-UC-User-Agent': getUserAgent({ publicKey, integration })
|
|
316
|
+
'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
|
|
293
317
|
},
|
|
294
318
|
data: buildFormData([
|
|
295
319
|
['file', file, (_a = fileName !== null && fileName !== void 0 ? fileName : file.name) !== null && _a !== void 0 ? _a : defaultFilename],
|
|
@@ -307,7 +331,7 @@ function base(file, { publicKey, fileName, baseURL = defaultSettings.baseURL, se
|
|
|
307
331
|
}).then(({ data, headers, request }) => {
|
|
308
332
|
const response = camelizeKeys(JSON.parse(data));
|
|
309
333
|
if ('error' in response) {
|
|
310
|
-
throw new UploadClientError(
|
|
334
|
+
throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
|
|
311
335
|
}
|
|
312
336
|
else {
|
|
313
337
|
return response;
|
|
@@ -316,34 +340,6 @@ function base(file, { publicKey, fileName, baseURL = defaultSettings.baseURL, se
|
|
|
316
340
|
}, retryThrottledRequestMaxTimes);
|
|
317
341
|
}
|
|
318
342
|
|
|
319
|
-
/**
|
|
320
|
-
* Returns a JSON dictionary holding file info.
|
|
321
|
-
*/
|
|
322
|
-
/* eslint @typescript-eslint/camelcase: [2, {allow: ["pub_key", "file_id"]}] */
|
|
323
|
-
function info(uuid, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
324
|
-
return retryIfThrottled(() => request({
|
|
325
|
-
method: 'GET',
|
|
326
|
-
headers: {
|
|
327
|
-
'X-UC-User-Agent': getUserAgent({ publicKey, integration })
|
|
328
|
-
},
|
|
329
|
-
url: getUrl(baseURL, '/info/', {
|
|
330
|
-
jsonerrors: 1,
|
|
331
|
-
pub_key: publicKey,
|
|
332
|
-
file_id: uuid,
|
|
333
|
-
source
|
|
334
|
-
}),
|
|
335
|
-
signal
|
|
336
|
-
}).then(({ data, headers, request }) => {
|
|
337
|
-
const response = camelizeKeys(JSON.parse(data));
|
|
338
|
-
if ('error' in response) {
|
|
339
|
-
throw new UploadClientError(`[${response.error.statusCode}] ${response.error.content}`, request, response.error, headers);
|
|
340
|
-
}
|
|
341
|
-
else {
|
|
342
|
-
return response;
|
|
343
|
-
}
|
|
344
|
-
}), retryThrottledRequestMaxTimes);
|
|
345
|
-
}
|
|
346
|
-
|
|
347
343
|
var TypeEnum;
|
|
348
344
|
(function (TypeEnum) {
|
|
349
345
|
TypeEnum["Token"] = "token";
|
|
@@ -352,12 +348,11 @@ var TypeEnum;
|
|
|
352
348
|
/**
|
|
353
349
|
* Uploading files from URL.
|
|
354
350
|
*/
|
|
355
|
-
|
|
356
|
-
function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, store, fileName, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, source = 'url', signal, integration, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
351
|
+
function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, store, fileName, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, source = 'url', signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
357
352
|
return retryIfThrottled(() => request({
|
|
358
353
|
method: 'POST',
|
|
359
354
|
headers: {
|
|
360
|
-
'X-UC-User-Agent': getUserAgent({ publicKey, integration })
|
|
355
|
+
'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
|
|
361
356
|
},
|
|
362
357
|
url: getUrl(baseURL, '/from_url/', {
|
|
363
358
|
jsonerrors: 1,
|
|
@@ -375,7 +370,7 @@ function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, stor
|
|
|
375
370
|
}).then(({ data, headers, request }) => {
|
|
376
371
|
const response = camelizeKeys(JSON.parse(data));
|
|
377
372
|
if ('error' in response) {
|
|
378
|
-
throw new UploadClientError(
|
|
373
|
+
throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
|
|
379
374
|
}
|
|
380
375
|
else {
|
|
381
376
|
return response;
|
|
@@ -397,11 +392,17 @@ const isErrorResponse = (response) => {
|
|
|
397
392
|
/**
|
|
398
393
|
* Checking upload status and working with file tokens.
|
|
399
394
|
*/
|
|
400
|
-
function fromUrlStatus(token, { publicKey, baseURL = defaultSettings.baseURL, signal, integration, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes } = {}) {
|
|
395
|
+
function fromUrlStatus(token, { publicKey, baseURL = defaultSettings.baseURL, signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes } = {}) {
|
|
401
396
|
return retryIfThrottled(() => request({
|
|
402
397
|
method: 'GET',
|
|
403
398
|
headers: publicKey
|
|
404
|
-
? {
|
|
399
|
+
? {
|
|
400
|
+
'X-UC-User-Agent': getUserAgent({
|
|
401
|
+
publicKey,
|
|
402
|
+
integration,
|
|
403
|
+
userAgent
|
|
404
|
+
})
|
|
405
|
+
}
|
|
405
406
|
: undefined,
|
|
406
407
|
url: getUrl(baseURL, '/from_url/status/', {
|
|
407
408
|
jsonerrors: 1,
|
|
@@ -411,7 +412,7 @@ function fromUrlStatus(token, { publicKey, baseURL = defaultSettings.baseURL, si
|
|
|
411
412
|
}).then(({ data, headers, request }) => {
|
|
412
413
|
const response = camelizeKeys(JSON.parse(data));
|
|
413
414
|
if ('error' in response && !isErrorResponse(response)) {
|
|
414
|
-
throw new UploadClientError(
|
|
415
|
+
throw new UploadClientError(response.error.content, undefined, request, response, headers);
|
|
415
416
|
}
|
|
416
417
|
else {
|
|
417
418
|
return response;
|
|
@@ -422,12 +423,11 @@ function fromUrlStatus(token, { publicKey, baseURL = defaultSettings.baseURL, si
|
|
|
422
423
|
/**
|
|
423
424
|
* Create files group.
|
|
424
425
|
*/
|
|
425
|
-
|
|
426
|
-
function group(uuids, { publicKey, baseURL = defaultSettings.baseURL, jsonpCallback, secureSignature, secureExpire, signal, source, integration, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
426
|
+
function group(uuids, { publicKey, baseURL = defaultSettings.baseURL, jsonpCallback, secureSignature, secureExpire, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
427
427
|
return retryIfThrottled(() => request({
|
|
428
428
|
method: 'POST',
|
|
429
429
|
headers: {
|
|
430
|
-
'X-UC-User-Agent': getUserAgent({ publicKey, integration })
|
|
430
|
+
'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
|
|
431
431
|
},
|
|
432
432
|
url: getUrl(baseURL, '/group/', {
|
|
433
433
|
jsonerrors: 1,
|
|
@@ -442,7 +442,7 @@ function group(uuids, { publicKey, baseURL = defaultSettings.baseURL, jsonpCallb
|
|
|
442
442
|
}).then(({ data, headers, request }) => {
|
|
443
443
|
const response = camelizeKeys(JSON.parse(data));
|
|
444
444
|
if ('error' in response) {
|
|
445
|
-
throw new UploadClientError(
|
|
445
|
+
throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
|
|
446
446
|
}
|
|
447
447
|
else {
|
|
448
448
|
return response;
|
|
@@ -453,12 +453,11 @@ function group(uuids, { publicKey, baseURL = defaultSettings.baseURL, jsonpCallb
|
|
|
453
453
|
/**
|
|
454
454
|
* Get info about group.
|
|
455
455
|
*/
|
|
456
|
-
|
|
457
|
-
function groupInfo(id, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
456
|
+
function groupInfo(id, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
458
457
|
return retryIfThrottled(() => request({
|
|
459
458
|
method: 'GET',
|
|
460
459
|
headers: {
|
|
461
|
-
'X-UC-User-Agent': getUserAgent({ publicKey, integration })
|
|
460
|
+
'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
|
|
462
461
|
},
|
|
463
462
|
url: getUrl(baseURL, '/group/info/', {
|
|
464
463
|
jsonerrors: 1,
|
|
@@ -470,7 +469,7 @@ function groupInfo(id, { publicKey, baseURL = defaultSettings.baseURL, signal, s
|
|
|
470
469
|
}).then(({ data, headers, request }) => {
|
|
471
470
|
const response = camelizeKeys(JSON.parse(data));
|
|
472
471
|
if ('error' in response) {
|
|
473
|
-
throw new UploadClientError(
|
|
472
|
+
throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
|
|
474
473
|
}
|
|
475
474
|
else {
|
|
476
475
|
return response;
|
|
@@ -479,62 +478,62 @@ function groupInfo(id, { publicKey, baseURL = defaultSettings.baseURL, signal, s
|
|
|
479
478
|
}
|
|
480
479
|
|
|
481
480
|
/**
|
|
482
|
-
*
|
|
481
|
+
* Returns a JSON dictionary holding file info.
|
|
483
482
|
*/
|
|
484
|
-
function
|
|
483
|
+
function info(uuid, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
485
484
|
return retryIfThrottled(() => request({
|
|
486
|
-
method: '
|
|
487
|
-
url: getUrl(baseURL, '/multipart/start/', { jsonerrors: 1 }),
|
|
485
|
+
method: 'GET',
|
|
488
486
|
headers: {
|
|
489
|
-
'X-UC-User-Agent': getUserAgent({ publicKey, integration })
|
|
487
|
+
'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
|
|
490
488
|
},
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
['UPLOADCARE_PUB_KEY', publicKey],
|
|
498
|
-
['signature', secureSignature],
|
|
499
|
-
['expire', secureExpire],
|
|
500
|
-
['source', source]
|
|
501
|
-
]),
|
|
489
|
+
url: getUrl(baseURL, '/info/', {
|
|
490
|
+
jsonerrors: 1,
|
|
491
|
+
pub_key: publicKey,
|
|
492
|
+
file_id: uuid,
|
|
493
|
+
source
|
|
494
|
+
}),
|
|
502
495
|
signal
|
|
503
496
|
}).then(({ data, headers, request }) => {
|
|
504
497
|
const response = camelizeKeys(JSON.parse(data));
|
|
505
498
|
if ('error' in response) {
|
|
506
|
-
throw new UploadClientError(
|
|
499
|
+
throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
|
|
507
500
|
}
|
|
508
501
|
else {
|
|
509
|
-
// convert to array
|
|
510
|
-
response.parts = Object.keys(response.parts).map(key => response.parts[key]);
|
|
511
502
|
return response;
|
|
512
503
|
}
|
|
513
504
|
}), retryThrottledRequestMaxTimes);
|
|
514
505
|
}
|
|
515
506
|
|
|
516
507
|
/**
|
|
517
|
-
*
|
|
508
|
+
* Start multipart uploading.
|
|
518
509
|
*/
|
|
519
|
-
function
|
|
510
|
+
function multipartStart(size, { publicKey, contentType, fileName, multipartChunkSize = defaultSettings.multipartChunkSize, baseURL = '', secureSignature, secureExpire, store, signal, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
520
511
|
return retryIfThrottled(() => request({
|
|
521
512
|
method: 'POST',
|
|
522
|
-
url: getUrl(baseURL, '/multipart/
|
|
513
|
+
url: getUrl(baseURL, '/multipart/start/', { jsonerrors: 1 }),
|
|
523
514
|
headers: {
|
|
524
|
-
'X-UC-User-Agent': getUserAgent({ publicKey, integration })
|
|
515
|
+
'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
|
|
525
516
|
},
|
|
526
517
|
data: buildFormData([
|
|
527
|
-
['
|
|
518
|
+
['filename', fileName !== null && fileName !== void 0 ? fileName : defaultFilename],
|
|
519
|
+
['size', size],
|
|
520
|
+
['content_type', contentType !== null && contentType !== void 0 ? contentType : defaultContentType],
|
|
521
|
+
['part_size', multipartChunkSize],
|
|
522
|
+
['UPLOADCARE_STORE', store ? '' : 'auto'],
|
|
528
523
|
['UPLOADCARE_PUB_KEY', publicKey],
|
|
524
|
+
['signature', secureSignature],
|
|
525
|
+
['expire', secureExpire],
|
|
529
526
|
['source', source]
|
|
530
527
|
]),
|
|
531
528
|
signal
|
|
532
529
|
}).then(({ data, headers, request }) => {
|
|
533
530
|
const response = camelizeKeys(JSON.parse(data));
|
|
534
531
|
if ('error' in response) {
|
|
535
|
-
throw new UploadClientError(
|
|
532
|
+
throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
|
|
536
533
|
}
|
|
537
534
|
else {
|
|
535
|
+
// convert to array
|
|
536
|
+
response.parts = Object.keys(response.parts).map((key) => response.parts[key]);
|
|
538
537
|
return response;
|
|
539
538
|
}
|
|
540
539
|
}), retryThrottledRequestMaxTimes);
|
|
@@ -543,20 +542,15 @@ function multipartComplete(uuid, { publicKey, baseURL = defaultSettings.baseURL,
|
|
|
543
542
|
/**
|
|
544
543
|
* Complete multipart uploading.
|
|
545
544
|
*/
|
|
546
|
-
function multipartUpload(part, url, {
|
|
545
|
+
function multipartUpload(part, url, { signal, onProgress }) {
|
|
547
546
|
return request({
|
|
548
547
|
method: 'PUT',
|
|
549
548
|
url,
|
|
550
|
-
headers: {
|
|
551
|
-
'X-UC-User-Agent': publicKey
|
|
552
|
-
? getUserAgent({ publicKey, integration })
|
|
553
|
-
: undefined
|
|
554
|
-
},
|
|
555
549
|
data: part,
|
|
556
550
|
onProgress,
|
|
557
551
|
signal
|
|
558
552
|
})
|
|
559
|
-
.then(result => {
|
|
553
|
+
.then((result) => {
|
|
560
554
|
// hack for node ¯\_(ツ)_/¯
|
|
561
555
|
if (onProgress)
|
|
562
556
|
onProgress({ value: 1 });
|
|
@@ -565,12 +559,40 @@ function multipartUpload(part, url, { publicKey, signal, onProgress, integration
|
|
|
565
559
|
.then(({ status }) => ({ code: status }));
|
|
566
560
|
}
|
|
567
561
|
|
|
562
|
+
/**
|
|
563
|
+
* Complete multipart uploading.
|
|
564
|
+
*/
|
|
565
|
+
function multipartComplete(uuid, { publicKey, baseURL = defaultSettings.baseURL, source = 'local', signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
|
|
566
|
+
return retryIfThrottled(() => request({
|
|
567
|
+
method: 'POST',
|
|
568
|
+
url: getUrl(baseURL, '/multipart/complete/', { jsonerrors: 1 }),
|
|
569
|
+
headers: {
|
|
570
|
+
'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
|
|
571
|
+
},
|
|
572
|
+
data: buildFormData([
|
|
573
|
+
['uuid', uuid],
|
|
574
|
+
['UPLOADCARE_PUB_KEY', publicKey],
|
|
575
|
+
['source', source]
|
|
576
|
+
]),
|
|
577
|
+
signal
|
|
578
|
+
}).then(({ data, headers, request }) => {
|
|
579
|
+
const response = camelizeKeys(JSON.parse(data));
|
|
580
|
+
if ('error' in response) {
|
|
581
|
+
throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
|
|
582
|
+
}
|
|
583
|
+
else {
|
|
584
|
+
return response;
|
|
585
|
+
}
|
|
586
|
+
}), retryThrottledRequestMaxTimes);
|
|
587
|
+
}
|
|
588
|
+
|
|
568
589
|
class UploadcareFile {
|
|
569
590
|
constructor(fileInfo, { baseCDN, defaultEffects, fileName }) {
|
|
570
591
|
this.name = null;
|
|
571
592
|
this.size = null;
|
|
572
593
|
this.isStored = null;
|
|
573
594
|
this.isImage = null;
|
|
595
|
+
this.mimeType = null;
|
|
574
596
|
this.cdnUrl = null;
|
|
575
597
|
this.cdnUrlModifiers = null;
|
|
576
598
|
this.originalUrl = null;
|
|
@@ -589,6 +611,7 @@ class UploadcareFile {
|
|
|
589
611
|
this.size = fileInfo.size;
|
|
590
612
|
this.isStored = fileInfo.isStored;
|
|
591
613
|
this.isImage = fileInfo.isImage;
|
|
614
|
+
this.mimeType = fileInfo.mimeType;
|
|
592
615
|
this.cdnUrl = cdnUrl;
|
|
593
616
|
this.cdnUrlModifiers = cdnUrlModifiers;
|
|
594
617
|
this.originalUrl = originalUrl;
|
|
@@ -608,7 +631,7 @@ const poll = ({ check, interval = DEFAULT_INTERVAL, signal }) => new Promise((re
|
|
|
608
631
|
const tick = () => {
|
|
609
632
|
try {
|
|
610
633
|
Promise.resolve(check(signal))
|
|
611
|
-
.then(result => {
|
|
634
|
+
.then((result) => {
|
|
612
635
|
if (result) {
|
|
613
636
|
resolve(result);
|
|
614
637
|
}
|
|
@@ -616,7 +639,7 @@ const poll = ({ check, interval = DEFAULT_INTERVAL, signal }) => new Promise((re
|
|
|
616
639
|
timeoutId = setTimeout(tick, interval);
|
|
617
640
|
}
|
|
618
641
|
})
|
|
619
|
-
.catch(error => reject(error));
|
|
642
|
+
.catch((error) => reject(error));
|
|
620
643
|
}
|
|
621
644
|
catch (error) {
|
|
622
645
|
reject(error);
|
|
@@ -625,16 +648,17 @@ const poll = ({ check, interval = DEFAULT_INTERVAL, signal }) => new Promise((re
|
|
|
625
648
|
timeoutId = setTimeout(tick, 0);
|
|
626
649
|
});
|
|
627
650
|
|
|
628
|
-
function isReadyPoll({ file, publicKey, baseURL, source, integration, retryThrottledRequestMaxTimes, signal, onProgress }) {
|
|
651
|
+
function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent, retryThrottledRequestMaxTimes, signal, onProgress }) {
|
|
629
652
|
return poll({
|
|
630
|
-
check: signal => info(file, {
|
|
653
|
+
check: (signal) => info(file, {
|
|
631
654
|
publicKey,
|
|
632
655
|
baseURL,
|
|
633
656
|
signal,
|
|
634
657
|
source,
|
|
635
658
|
integration,
|
|
659
|
+
userAgent,
|
|
636
660
|
retryThrottledRequestMaxTimes
|
|
637
|
-
}).then(response => {
|
|
661
|
+
}).then((response) => {
|
|
638
662
|
if (response.isReady) {
|
|
639
663
|
return response;
|
|
640
664
|
}
|
|
@@ -645,7 +669,7 @@ function isReadyPoll({ file, publicKey, baseURL, source, integration, retryThrot
|
|
|
645
669
|
});
|
|
646
670
|
}
|
|
647
671
|
|
|
648
|
-
const uploadFromObject = (file, { publicKey, fileName, baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, retryThrottledRequestMaxTimes, baseCDN }) => {
|
|
672
|
+
const uploadFromObject = (file, { publicKey, fileName, baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, baseCDN }) => {
|
|
649
673
|
return base(file, {
|
|
650
674
|
publicKey,
|
|
651
675
|
fileName,
|
|
@@ -657,6 +681,7 @@ const uploadFromObject = (file, { publicKey, fileName, baseURL, secureSignature,
|
|
|
657
681
|
onProgress,
|
|
658
682
|
source,
|
|
659
683
|
integration,
|
|
684
|
+
userAgent,
|
|
660
685
|
retryThrottledRequestMaxTimes
|
|
661
686
|
})
|
|
662
687
|
.then(({ file }) => {
|
|
@@ -666,12 +691,13 @@ const uploadFromObject = (file, { publicKey, fileName, baseURL, secureSignature,
|
|
|
666
691
|
baseURL,
|
|
667
692
|
source,
|
|
668
693
|
integration,
|
|
694
|
+
userAgent,
|
|
669
695
|
retryThrottledRequestMaxTimes,
|
|
670
696
|
onProgress,
|
|
671
697
|
signal
|
|
672
698
|
});
|
|
673
699
|
})
|
|
674
|
-
.then(fileInfo => new UploadcareFile(fileInfo, { baseCDN }));
|
|
700
|
+
.then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN }));
|
|
675
701
|
};
|
|
676
702
|
|
|
677
703
|
const race = (fns, { signal } = {}) => {
|
|
@@ -683,21 +709,21 @@ const race = (fns, { signal } = {}) => {
|
|
|
683
709
|
controllers.forEach((controller, index) => index !== i && controller.abort());
|
|
684
710
|
};
|
|
685
711
|
onCancel(signal, () => {
|
|
686
|
-
controllers.forEach(controller => controller.abort());
|
|
712
|
+
controllers.forEach((controller) => controller.abort());
|
|
687
713
|
});
|
|
688
714
|
return Promise.all(fns.map((fn, i) => {
|
|
689
715
|
const stopRace = createStopRaceCallback(i);
|
|
690
716
|
return Promise.resolve()
|
|
691
717
|
.then(() => fn({ stopRace, signal: controllers[i].signal }))
|
|
692
|
-
.then(result => {
|
|
718
|
+
.then((result) => {
|
|
693
719
|
stopRace();
|
|
694
720
|
return result;
|
|
695
721
|
})
|
|
696
|
-
.catch(error => {
|
|
722
|
+
.catch((error) => {
|
|
697
723
|
lastError = error;
|
|
698
724
|
return null;
|
|
699
725
|
});
|
|
700
|
-
})).then(results => {
|
|
726
|
+
})).then((results) => {
|
|
701
727
|
if (winnerIndex === null) {
|
|
702
728
|
throw lastError;
|
|
703
729
|
}
|
|
@@ -713,7 +739,7 @@ class Events {
|
|
|
713
739
|
}
|
|
714
740
|
emit(event, data) {
|
|
715
741
|
var _a;
|
|
716
|
-
(_a = this.events[event]) === null || _a === void 0 ? void 0 : _a.forEach(fn => fn(data));
|
|
742
|
+
(_a = this.events[event]) === null || _a === void 0 ? void 0 : _a.forEach((fn) => fn(data));
|
|
717
743
|
}
|
|
718
744
|
on(event, callback) {
|
|
719
745
|
this.events[event] = this.events[event] || [];
|
|
@@ -721,7 +747,7 @@ class Events {
|
|
|
721
747
|
}
|
|
722
748
|
off(event, callback) {
|
|
723
749
|
if (callback) {
|
|
724
|
-
this.events[event] = this.events[event].filter(fn => fn !== callback);
|
|
750
|
+
this.events[event] = this.events[event].filter((fn) => fn !== callback);
|
|
725
751
|
}
|
|
726
752
|
else {
|
|
727
753
|
this.events[event] = [];
|
|
@@ -754,16 +780,16 @@ class Pusher {
|
|
|
754
780
|
if (!this.isConnected && !this.ws) {
|
|
755
781
|
const pusherUrl = `wss://ws.pusherapp.com/app/${this.key}?protocol=5&client=js&version=1.12.2`;
|
|
756
782
|
this.ws = new WebSocket(pusherUrl);
|
|
757
|
-
this.ws.addEventListener('error', error => {
|
|
783
|
+
this.ws.addEventListener('error', (error) => {
|
|
758
784
|
this.emmitter.emit('error', new Error(error.message));
|
|
759
785
|
});
|
|
760
786
|
this.emmitter.on('connected', () => {
|
|
761
787
|
this.isConnected = true;
|
|
762
|
-
this.queue.forEach(message => this.send(message.event, message.data));
|
|
788
|
+
this.queue.forEach((message) => this.send(message.event, message.data));
|
|
763
789
|
this.queue = [];
|
|
764
790
|
});
|
|
765
|
-
this.ws.addEventListener('message', e => {
|
|
766
|
-
const data = JSON.parse(e.data);
|
|
791
|
+
this.ws.addEventListener('message', (e) => {
|
|
792
|
+
const data = JSON.parse(e.data.toString());
|
|
767
793
|
switch (data.event) {
|
|
768
794
|
case 'pusher:connection_established': {
|
|
769
795
|
this.emmitter.emit('connected', undefined);
|
|
@@ -831,7 +857,7 @@ class Pusher {
|
|
|
831
857
|
this.send(message.event, message.data);
|
|
832
858
|
}
|
|
833
859
|
else {
|
|
834
|
-
this.queue = this.queue.filter(msg => msg.data.channel !== channel);
|
|
860
|
+
this.queue = this.queue.filter((msg) => msg.data.channel !== channel);
|
|
835
861
|
}
|
|
836
862
|
if (this.subscribers === 0) {
|
|
837
863
|
this.disconnect();
|
|
@@ -855,18 +881,19 @@ const preconnect = (key) => {
|
|
|
855
881
|
getPusher(key).connect();
|
|
856
882
|
};
|
|
857
883
|
|
|
858
|
-
function pollStrategy({ token, publicKey, baseURL, integration, retryThrottledRequestMaxTimes, onProgress, signal }) {
|
|
884
|
+
function pollStrategy({ token, publicKey, baseURL, integration, userAgent, retryThrottledRequestMaxTimes, onProgress, signal }) {
|
|
859
885
|
return poll({
|
|
860
|
-
check: signal => fromUrlStatus(token, {
|
|
886
|
+
check: (signal) => fromUrlStatus(token, {
|
|
861
887
|
publicKey,
|
|
862
888
|
baseURL,
|
|
863
889
|
integration,
|
|
890
|
+
userAgent,
|
|
864
891
|
retryThrottledRequestMaxTimes,
|
|
865
892
|
signal
|
|
866
|
-
}).then(response => {
|
|
893
|
+
}).then((response) => {
|
|
867
894
|
switch (response.status) {
|
|
868
895
|
case Status.Error: {
|
|
869
|
-
return new UploadClientError(response.error);
|
|
896
|
+
return new UploadClientError(response.error, response.errorCode);
|
|
870
897
|
}
|
|
871
898
|
case Status.Waiting: {
|
|
872
899
|
return false;
|
|
@@ -892,7 +919,7 @@ function pollStrategy({ token, publicKey, baseURL, integration, retryThrottledRe
|
|
|
892
919
|
signal
|
|
893
920
|
});
|
|
894
921
|
}
|
|
895
|
-
const pushStrategy = ({ token, pusherKey, signal,
|
|
922
|
+
const pushStrategy = ({ token, pusherKey, signal, onProgress }) => new Promise((resolve, reject) => {
|
|
896
923
|
const pusher = getPusher(pusherKey);
|
|
897
924
|
const unsubErrorHandler = pusher.onError(reject);
|
|
898
925
|
const destroy = () => {
|
|
@@ -901,10 +928,9 @@ const pushStrategy = ({ token, pusherKey, signal, stopRace, onProgress }) => new
|
|
|
901
928
|
};
|
|
902
929
|
onCancel(signal, () => {
|
|
903
930
|
destroy();
|
|
904
|
-
reject(cancelError('
|
|
931
|
+
reject(cancelError('pusher cancelled'));
|
|
905
932
|
});
|
|
906
|
-
pusher.subscribe(token, result => {
|
|
907
|
-
stopRace();
|
|
933
|
+
pusher.subscribe(token, (result) => {
|
|
908
934
|
switch (result.status) {
|
|
909
935
|
case Status.Progress: {
|
|
910
936
|
if (onProgress) {
|
|
@@ -921,12 +947,12 @@ const pushStrategy = ({ token, pusherKey, signal, stopRace, onProgress }) => new
|
|
|
921
947
|
}
|
|
922
948
|
case Status.Error: {
|
|
923
949
|
destroy();
|
|
924
|
-
reject(new UploadClientError(result.msg));
|
|
950
|
+
reject(new UploadClientError(result.msg, result.error_code));
|
|
925
951
|
}
|
|
926
952
|
}
|
|
927
953
|
});
|
|
928
954
|
});
|
|
929
|
-
const uploadFromUrl = (sourceUrl, { publicKey, fileName, baseURL, baseCDN, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, store, signal, onProgress, source, integration, retryThrottledRequestMaxTimes, pusherKey = defaultSettings.pusherKey }) => Promise.resolve(preconnect(pusherKey))
|
|
955
|
+
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))
|
|
930
956
|
.then(() => fromUrl(sourceUrl, {
|
|
931
957
|
publicKey,
|
|
932
958
|
fileName,
|
|
@@ -939,9 +965,15 @@ const uploadFromUrl = (sourceUrl, { publicKey, fileName, baseURL, baseCDN, check
|
|
|
939
965
|
signal,
|
|
940
966
|
source,
|
|
941
967
|
integration,
|
|
968
|
+
userAgent,
|
|
942
969
|
retryThrottledRequestMaxTimes
|
|
943
970
|
}))
|
|
944
|
-
.
|
|
971
|
+
.catch((error) => {
|
|
972
|
+
const pusher = getPusher(pusherKey);
|
|
973
|
+
pusher === null || pusher === void 0 ? void 0 : pusher.disconnect();
|
|
974
|
+
return Promise.reject(error);
|
|
975
|
+
})
|
|
976
|
+
.then((urlResponse) => {
|
|
945
977
|
if (urlResponse.type === TypeEnum.FileInfo) {
|
|
946
978
|
return urlResponse;
|
|
947
979
|
}
|
|
@@ -952,47 +984,49 @@ const uploadFromUrl = (sourceUrl, { publicKey, fileName, baseURL, baseCDN, check
|
|
|
952
984
|
publicKey,
|
|
953
985
|
baseURL,
|
|
954
986
|
integration,
|
|
987
|
+
userAgent,
|
|
955
988
|
retryThrottledRequestMaxTimes,
|
|
956
989
|
onProgress,
|
|
957
990
|
signal
|
|
958
991
|
}),
|
|
959
|
-
({
|
|
992
|
+
({ signal }) => pushStrategy({
|
|
960
993
|
token: urlResponse.token,
|
|
961
994
|
pusherKey,
|
|
962
|
-
stopRace,
|
|
963
995
|
signal,
|
|
964
996
|
onProgress
|
|
965
997
|
})
|
|
966
998
|
], { signal });
|
|
967
999
|
}
|
|
968
1000
|
})
|
|
969
|
-
.then(result => {
|
|
1001
|
+
.then((result) => {
|
|
970
1002
|
if (result instanceof UploadClientError)
|
|
971
1003
|
throw result;
|
|
972
1004
|
return result;
|
|
973
1005
|
})
|
|
974
|
-
.then(result => isReadyPoll({
|
|
1006
|
+
.then((result) => isReadyPoll({
|
|
975
1007
|
file: result.uuid,
|
|
976
1008
|
publicKey,
|
|
977
1009
|
baseURL,
|
|
978
1010
|
integration,
|
|
1011
|
+
userAgent,
|
|
979
1012
|
retryThrottledRequestMaxTimes,
|
|
980
1013
|
onProgress,
|
|
981
1014
|
signal
|
|
982
1015
|
}))
|
|
983
|
-
.then(fileInfo => new UploadcareFile(fileInfo, { baseCDN }));
|
|
1016
|
+
.then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN }));
|
|
984
1017
|
|
|
985
|
-
const uploadFromUploaded = (uuid, { publicKey, fileName, baseURL, signal, onProgress, source, integration, retryThrottledRequestMaxTimes, baseCDN }) => {
|
|
1018
|
+
const uploadFromUploaded = (uuid, { publicKey, fileName, baseURL, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, baseCDN }) => {
|
|
986
1019
|
return info(uuid, {
|
|
987
1020
|
publicKey,
|
|
988
1021
|
baseURL,
|
|
989
1022
|
signal,
|
|
990
1023
|
source,
|
|
991
1024
|
integration,
|
|
1025
|
+
userAgent,
|
|
992
1026
|
retryThrottledRequestMaxTimes
|
|
993
1027
|
})
|
|
994
|
-
.then(fileInfo => new UploadcareFile(fileInfo, { baseCDN, fileName }))
|
|
995
|
-
.then(result => {
|
|
1028
|
+
.then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN, fileName }))
|
|
1029
|
+
.then((result) => {
|
|
996
1030
|
// hack for node ¯\_(ツ)_/¯
|
|
997
1031
|
if (onProgress)
|
|
998
1032
|
onProgress({ value: 1 });
|
|
@@ -1041,6 +1075,16 @@ const isMultipart = (fileSize, multipartMinFileSize = defaultSettings.multipartM
|
|
|
1041
1075
|
return fileSize >= multipartMinFileSize;
|
|
1042
1076
|
};
|
|
1043
1077
|
|
|
1078
|
+
const sliceChunk = (file, index, fileSize, chunkSize) => {
|
|
1079
|
+
const start = chunkSize * index;
|
|
1080
|
+
const end = Math.min(start + chunkSize, fileSize);
|
|
1081
|
+
return file.slice(start, end);
|
|
1082
|
+
};
|
|
1083
|
+
|
|
1084
|
+
function prepareChunks(file, fileSize, chunkSize) {
|
|
1085
|
+
return (index) => sliceChunk(file, index, fileSize, chunkSize);
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1044
1088
|
const runWithConcurrency = (concurrency, tasks) => {
|
|
1045
1089
|
return new Promise((resolve, reject) => {
|
|
1046
1090
|
const results = [];
|
|
@@ -1064,7 +1108,7 @@ const runWithConcurrency = (concurrency, tasks) => {
|
|
|
1064
1108
|
resolve(results);
|
|
1065
1109
|
}
|
|
1066
1110
|
})
|
|
1067
|
-
.catch(error => {
|
|
1111
|
+
.catch((error) => {
|
|
1068
1112
|
rejected = true;
|
|
1069
1113
|
reject(error);
|
|
1070
1114
|
});
|
|
@@ -1076,23 +1120,18 @@ const runWithConcurrency = (concurrency, tasks) => {
|
|
|
1076
1120
|
});
|
|
1077
1121
|
};
|
|
1078
1122
|
|
|
1079
|
-
const getChunk = (file, index, fileSize, chunkSize) => {
|
|
1080
|
-
const start = chunkSize * index;
|
|
1081
|
-
const end = Math.min(start + chunkSize, fileSize);
|
|
1082
|
-
return file.slice(start, end);
|
|
1083
|
-
};
|
|
1084
1123
|
const uploadPartWithRetry = (chunk, url, { publicKey, onProgress, signal, integration, multipartMaxAttempts }) => retrier(({ attempt, retry }) => multipartUpload(chunk, url, {
|
|
1085
1124
|
publicKey,
|
|
1086
1125
|
onProgress,
|
|
1087
1126
|
signal,
|
|
1088
1127
|
integration
|
|
1089
|
-
}).catch(error => {
|
|
1128
|
+
}).catch((error) => {
|
|
1090
1129
|
if (attempt < multipartMaxAttempts) {
|
|
1091
1130
|
return retry();
|
|
1092
1131
|
}
|
|
1093
1132
|
throw error;
|
|
1094
1133
|
}));
|
|
1095
|
-
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 }) => {
|
|
1134
|
+
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 }) => {
|
|
1096
1135
|
const size = fileSize || getFileSize(file);
|
|
1097
1136
|
let progressValues;
|
|
1098
1137
|
const createProgressHandler = (size, index) => {
|
|
@@ -1118,26 +1157,31 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
|
|
|
1118
1157
|
signal,
|
|
1119
1158
|
source,
|
|
1120
1159
|
integration,
|
|
1160
|
+
userAgent,
|
|
1121
1161
|
retryThrottledRequestMaxTimes
|
|
1122
1162
|
})
|
|
1123
|
-
.then(({ uuid, parts }) =>
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1163
|
+
.then(({ uuid, parts }) => {
|
|
1164
|
+
const getChunk = prepareChunks(file, size, multipartChunkSize);
|
|
1165
|
+
return Promise.all([
|
|
1166
|
+
uuid,
|
|
1167
|
+
runWithConcurrency(maxConcurrentRequests, parts.map((url, index) => () => uploadPartWithRetry(getChunk(index), url, {
|
|
1168
|
+
publicKey,
|
|
1169
|
+
onProgress: createProgressHandler(parts.length, index),
|
|
1170
|
+
signal,
|
|
1171
|
+
integration,
|
|
1172
|
+
multipartMaxAttempts
|
|
1173
|
+
})))
|
|
1174
|
+
]);
|
|
1175
|
+
})
|
|
1133
1176
|
.then(([uuid]) => multipartComplete(uuid, {
|
|
1134
1177
|
publicKey,
|
|
1135
1178
|
baseURL,
|
|
1136
1179
|
source,
|
|
1137
1180
|
integration,
|
|
1181
|
+
userAgent,
|
|
1138
1182
|
retryThrottledRequestMaxTimes
|
|
1139
1183
|
}))
|
|
1140
|
-
.then(fileInfo => {
|
|
1184
|
+
.then((fileInfo) => {
|
|
1141
1185
|
if (fileInfo.isReady) {
|
|
1142
1186
|
return fileInfo;
|
|
1143
1187
|
}
|
|
@@ -1148,19 +1192,20 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
|
|
|
1148
1192
|
baseURL,
|
|
1149
1193
|
source,
|
|
1150
1194
|
integration,
|
|
1195
|
+
userAgent,
|
|
1151
1196
|
retryThrottledRequestMaxTimes,
|
|
1152
1197
|
onProgress,
|
|
1153
1198
|
signal
|
|
1154
1199
|
});
|
|
1155
1200
|
}
|
|
1156
1201
|
})
|
|
1157
|
-
.then(fileInfo => new UploadcareFile(fileInfo, { baseCDN }));
|
|
1202
|
+
.then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN }));
|
|
1158
1203
|
};
|
|
1159
1204
|
|
|
1160
1205
|
/**
|
|
1161
1206
|
* Uploads file from provided data.
|
|
1162
1207
|
*/
|
|
1163
|
-
function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, retryThrottledRequestMaxTimes, contentType, multipartChunkSize
|
|
1208
|
+
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 }) {
|
|
1164
1209
|
if (isFileData(data)) {
|
|
1165
1210
|
const fileSize = getFileSize(data);
|
|
1166
1211
|
if (isMultipart(fileSize)) {
|
|
@@ -1168,6 +1213,7 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
|
|
|
1168
1213
|
publicKey,
|
|
1169
1214
|
contentType,
|
|
1170
1215
|
multipartChunkSize,
|
|
1216
|
+
multipartMaxAttempts,
|
|
1171
1217
|
fileName,
|
|
1172
1218
|
baseURL,
|
|
1173
1219
|
secureSignature,
|
|
@@ -1177,6 +1223,8 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
|
|
|
1177
1223
|
onProgress,
|
|
1178
1224
|
source,
|
|
1179
1225
|
integration,
|
|
1226
|
+
userAgent,
|
|
1227
|
+
maxConcurrentRequests,
|
|
1180
1228
|
retryThrottledRequestMaxTimes,
|
|
1181
1229
|
baseCDN
|
|
1182
1230
|
});
|
|
@@ -1192,6 +1240,7 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
|
|
|
1192
1240
|
onProgress,
|
|
1193
1241
|
source,
|
|
1194
1242
|
integration,
|
|
1243
|
+
userAgent,
|
|
1195
1244
|
retryThrottledRequestMaxTimes,
|
|
1196
1245
|
baseCDN
|
|
1197
1246
|
});
|
|
@@ -1201,6 +1250,9 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
|
|
|
1201
1250
|
publicKey,
|
|
1202
1251
|
fileName,
|
|
1203
1252
|
baseURL,
|
|
1253
|
+
baseCDN,
|
|
1254
|
+
checkForUrlDuplicates,
|
|
1255
|
+
saveUrlForRecurrentUploads,
|
|
1204
1256
|
secureSignature,
|
|
1205
1257
|
secureExpire,
|
|
1206
1258
|
store,
|
|
@@ -1208,8 +1260,9 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
|
|
|
1208
1260
|
onProgress,
|
|
1209
1261
|
source,
|
|
1210
1262
|
integration,
|
|
1263
|
+
userAgent,
|
|
1211
1264
|
retryThrottledRequestMaxTimes,
|
|
1212
|
-
|
|
1265
|
+
pusherKey
|
|
1213
1266
|
});
|
|
1214
1267
|
}
|
|
1215
1268
|
if (isUuid(data)) {
|
|
@@ -1221,6 +1274,7 @@ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseU
|
|
|
1221
1274
|
onProgress,
|
|
1222
1275
|
source,
|
|
1223
1276
|
integration,
|
|
1277
|
+
userAgent,
|
|
1224
1278
|
retryThrottledRequestMaxTimes,
|
|
1225
1279
|
baseCDN
|
|
1226
1280
|
});
|
|
@@ -1235,8 +1289,7 @@ class UploadcareGroup {
|
|
|
1235
1289
|
this.filesCount = groupInfo.filesCount;
|
|
1236
1290
|
this.totalSize = Object.values(groupInfo.files).reduce((acc, file) => acc + file.size, 0);
|
|
1237
1291
|
this.isStored = !!groupInfo.datetimeStored;
|
|
1238
|
-
this.isImage = !!Object.values(groupInfo.files).filter(file => file.isImage)
|
|
1239
|
-
.length;
|
|
1292
|
+
this.isImage = !!Object.values(groupInfo.files).filter((file) => file.isImage).length;
|
|
1240
1293
|
this.cdnUrl = groupInfo.cdnUrl;
|
|
1241
1294
|
this.files = files;
|
|
1242
1295
|
this.createdAt = groupInfo.datetimeCreated;
|
|
@@ -1278,7 +1331,7 @@ const isUrlArray = (data) => {
|
|
|
1278
1331
|
return true;
|
|
1279
1332
|
};
|
|
1280
1333
|
|
|
1281
|
-
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 }) {
|
|
1334
|
+
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 }) {
|
|
1282
1335
|
if (!isFileDataArray(data) && !isUrlArray(data) && !isUuidArray(data)) {
|
|
1283
1336
|
throw new TypeError(`Group uploading from "${data}" is not supported`);
|
|
1284
1337
|
}
|
|
@@ -1307,12 +1360,13 @@ function uploadFileGroup(data, { publicKey, fileName, baseURL = defaultSettings.
|
|
|
1307
1360
|
onProgress: createProgressHandler(filesCount, index),
|
|
1308
1361
|
source,
|
|
1309
1362
|
integration,
|
|
1363
|
+
userAgent,
|
|
1310
1364
|
retryThrottledRequestMaxTimes,
|
|
1311
1365
|
contentType,
|
|
1312
1366
|
multipartChunkSize,
|
|
1313
1367
|
baseCDN
|
|
1314
|
-
}))).then(files => {
|
|
1315
|
-
const uuids = files.map(file => file.uuid);
|
|
1368
|
+
}))).then((files) => {
|
|
1369
|
+
const uuids = files.map((file) => file.uuid);
|
|
1316
1370
|
const addDefaultEffects = (file) => {
|
|
1317
1371
|
const cdnUrlModifiers = defaultEffects ? `-/${defaultEffects}` : null;
|
|
1318
1372
|
const cdnUrl = `${file.urlBase}${cdnUrlModifiers || ''}`;
|
|
@@ -1329,8 +1383,9 @@ function uploadFileGroup(data, { publicKey, fileName, baseURL = defaultSettings.
|
|
|
1329
1383
|
signal,
|
|
1330
1384
|
source,
|
|
1331
1385
|
integration,
|
|
1386
|
+
userAgent,
|
|
1332
1387
|
retryThrottledRequestMaxTimes
|
|
1333
|
-
}).then(groupInfo => new UploadcareGroup(groupInfo, filesInGroup));
|
|
1388
|
+
}).then((groupInfo) => new UploadcareGroup(groupInfo, filesInGroup));
|
|
1334
1389
|
});
|
|
1335
1390
|
}
|
|
1336
1391
|
|
|
@@ -1394,4 +1449,4 @@ class UploadClient {
|
|
|
1394
1449
|
}
|
|
1395
1450
|
}
|
|
1396
1451
|
|
|
1397
|
-
export { UploadClient, base, fromUrl, fromUrlStatus, group, groupInfo, info, multipartComplete, multipartStart, multipartUpload, uploadFile, uploadFileGroup };
|
|
1452
|
+
export { UploadClient, base, fromUrl, fromUrlStatus, group, groupInfo, info, multipartComplete, multipartStart, multipartUpload, uploadFromObject as uploadBase, uploadFile, uploadFileGroup, uploadFromUploaded, uploadFromUrl, uploadMultipart };
|