@uploadcare/upload-client 3.1.2-alpha.0 → 4.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.
@@ -1,1547 +1,1530 @@
1
- class UploadClientError extends Error {
2
- constructor(message, code, request, response, headers) {
3
- super();
4
- this.name = 'UploadClientError';
5
- this.message = message;
6
- this.code = code;
7
- this.request = request;
8
- this.response = response;
9
- this.headers = headers;
10
- Object.setPrototypeOf(this, UploadClientError.prototype);
11
- }
12
- }
13
- const cancelError = (message = 'Request canceled') => {
14
- const error = new UploadClientError(message);
15
- error.isCancel = true;
16
- return error;
1
+ class UploadClientError extends Error {
2
+ constructor(message, code, request, response, headers) {
3
+ super();
4
+ this.name = 'UploadClientError';
5
+ this.message = message;
6
+ this.code = code;
7
+ this.request = request;
8
+ this.response = response;
9
+ this.headers = headers;
10
+ Object.setPrototypeOf(this, UploadClientError.prototype);
11
+ }
12
+ }
13
+ const cancelError = (message = 'Request canceled') => {
14
+ const error = new UploadClientError(message);
15
+ error.isCancel = true;
16
+ return error;
17
17
  };
18
18
 
19
- const onCancel = (signal, callback) => {
20
- if (signal) {
21
- if (signal.aborted) {
22
- Promise.resolve().then(callback);
23
- }
24
- else {
25
- signal.addEventListener('abort', () => callback(), { once: true });
26
- }
27
- }
19
+ const onCancel = (signal, callback) => {
20
+ if (signal) {
21
+ if (signal.aborted) {
22
+ Promise.resolve().then(callback);
23
+ }
24
+ else {
25
+ signal.addEventListener('abort', () => callback(), { once: true });
26
+ }
27
+ }
28
28
  };
29
29
 
30
- const request = ({ method, url, data, headers = {}, signal, onProgress }) => new Promise((resolve, reject) => {
31
- const xhr = new XMLHttpRequest();
32
- const requestMethod = (method === null || method === void 0 ? void 0 : method.toUpperCase()) || 'GET';
33
- let aborted = false;
34
- xhr.open(requestMethod, url);
35
- if (headers) {
36
- Object.entries(headers).forEach((entry) => {
37
- const [key, value] = entry;
38
- typeof value !== 'undefined' &&
39
- !Array.isArray(value) &&
40
- xhr.setRequestHeader(key, value);
41
- });
42
- }
43
- xhr.responseType = 'text';
44
- onCancel(signal, () => {
45
- aborted = true;
46
- xhr.abort();
47
- reject(cancelError());
48
- });
49
- xhr.onload = () => {
50
- if (xhr.status != 200) {
51
- // analyze HTTP status of the response
52
- reject(new Error(`Error ${xhr.status}: ${xhr.statusText}`)); // e.g. 404: Not Found
53
- }
54
- else {
55
- const request = {
56
- method: requestMethod,
57
- url,
58
- data,
59
- headers: headers || undefined,
60
- signal,
61
- onProgress
62
- };
63
- // Convert the header string into an array
64
- // of individual headers
65
- const headersArray = xhr
66
- .getAllResponseHeaders()
67
- .trim()
68
- .split(/[\r\n]+/);
69
- // Create a map of header names to values
70
- const responseHeaders = {};
71
- headersArray.forEach(function (line) {
72
- const parts = line.split(': ');
73
- const header = parts.shift();
74
- const value = parts.join(': ');
75
- if (header && typeof header !== 'undefined') {
76
- responseHeaders[header] = value;
77
- }
78
- });
79
- const responseData = xhr.response;
80
- const responseStatus = xhr.status;
81
- resolve({
82
- request,
83
- data: responseData,
84
- headers: responseHeaders,
85
- status: responseStatus
86
- });
87
- }
88
- };
89
- xhr.onerror = () => {
90
- if (aborted)
91
- return;
92
- // only triggers if the request couldn't be made at all
93
- reject(new Error('Network error'));
94
- };
95
- if (onProgress && typeof onProgress === 'function') {
96
- xhr.upload.onprogress = (event) => {
97
- if (event.lengthComputable) {
98
- onProgress({
99
- isComputable: true,
100
- value: event.loaded / event.total
101
- });
102
- }
103
- else {
104
- onProgress({ isComputable: false });
105
- }
106
- };
107
- }
108
- if (data) {
109
- xhr.send(data);
110
- }
111
- else {
112
- xhr.send();
113
- }
30
+ const request = ({ method, url, data, headers = {}, signal, onProgress }) => new Promise((resolve, reject) => {
31
+ const xhr = new XMLHttpRequest();
32
+ const requestMethod = (method === null || method === void 0 ? void 0 : method.toUpperCase()) || 'GET';
33
+ let aborted = false;
34
+ xhr.open(requestMethod, url);
35
+ if (headers) {
36
+ Object.entries(headers).forEach((entry) => {
37
+ const [key, value] = entry;
38
+ typeof value !== 'undefined' &&
39
+ !Array.isArray(value) &&
40
+ xhr.setRequestHeader(key, value);
41
+ });
42
+ }
43
+ xhr.responseType = 'text';
44
+ onCancel(signal, () => {
45
+ aborted = true;
46
+ xhr.abort();
47
+ reject(cancelError());
48
+ });
49
+ xhr.onload = () => {
50
+ if (xhr.status != 200) {
51
+ // analyze HTTP status of the response
52
+ reject(new Error(`Error ${xhr.status}: ${xhr.statusText}`)); // e.g. 404: Not Found
53
+ }
54
+ else {
55
+ const request = {
56
+ method: requestMethod,
57
+ url,
58
+ data,
59
+ headers: headers || undefined,
60
+ signal,
61
+ onProgress
62
+ };
63
+ // Convert the header string into an array
64
+ // of individual headers
65
+ const headersArray = xhr
66
+ .getAllResponseHeaders()
67
+ .trim()
68
+ .split(/[\r\n]+/);
69
+ // Create a map of header names to values
70
+ const responseHeaders = {};
71
+ headersArray.forEach(function (line) {
72
+ const parts = line.split(': ');
73
+ const header = parts.shift();
74
+ const value = parts.join(': ');
75
+ if (header && typeof header !== 'undefined') {
76
+ responseHeaders[header] = value;
77
+ }
78
+ });
79
+ const responseData = xhr.response;
80
+ const responseStatus = xhr.status;
81
+ resolve({
82
+ request,
83
+ data: responseData,
84
+ headers: responseHeaders,
85
+ status: responseStatus
86
+ });
87
+ }
88
+ };
89
+ xhr.onerror = () => {
90
+ if (aborted)
91
+ return;
92
+ // only triggers if the request couldn't be made at all
93
+ reject(new Error('Network error'));
94
+ };
95
+ if (onProgress && typeof onProgress === 'function') {
96
+ xhr.upload.onprogress = (event) => {
97
+ if (event.lengthComputable) {
98
+ onProgress({
99
+ isComputable: true,
100
+ value: event.loaded / event.total
101
+ });
102
+ }
103
+ else {
104
+ onProgress({ isComputable: false });
105
+ }
106
+ };
107
+ }
108
+ if (data) {
109
+ xhr.send(data);
110
+ }
111
+ else {
112
+ xhr.send();
113
+ }
114
114
  });
115
115
 
116
- function identity(obj) {
117
- return obj;
116
+ function identity(obj) {
117
+ return obj;
118
118
  }
119
119
 
120
- const getFileOptions = ({ name }) => name ? [name] : [];
121
- const transformFile = identity;
120
+ const getFileOptions = ({ name }) => name ? [name] : [];
121
+ const transformFile = identity;
122
122
  var getFormData = () => new FormData();
123
123
 
124
- /**
125
- * FileData type guard.
126
- */
127
- const isFileData = (data) => {
128
- return (data !== undefined &&
129
- ((typeof Blob !== 'undefined' && data instanceof Blob) ||
130
- (typeof File !== 'undefined' && data instanceof File) ||
131
- (typeof Buffer !== 'undefined' && data instanceof Buffer)));
132
- };
133
- /**
134
- * Uuid type guard.
135
- */
136
- const isUuid = (data) => {
137
- const UUID_REGEX = '[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}';
138
- const regExp = new RegExp(UUID_REGEX);
139
- return !isFileData(data) && regExp.test(data);
140
- };
141
- /**
142
- * Url type guard.
143
- *
144
- * @param {NodeFile | BrowserFile | Url | Uuid} data
145
- */
146
- const isUrl = (data) => {
147
- const URL_REGEX = '^(?:\\w+:)?\\/\\/([^\\s\\.]+\\.\\S{2}|localhost[\\:?\\d]*)\\S*$';
148
- const regExp = new RegExp(URL_REGEX);
149
- return !isFileData(data) && regExp.test(data);
124
+ /**
125
+ * FileData type guard.
126
+ */
127
+ const isFileData = (data) => {
128
+ return (data !== undefined &&
129
+ ((typeof Blob !== 'undefined' && data instanceof Blob) ||
130
+ (typeof File !== 'undefined' && data instanceof File) ||
131
+ (typeof Buffer !== 'undefined' && data instanceof Buffer)));
132
+ };
133
+ /**
134
+ * Uuid type guard.
135
+ */
136
+ const isUuid = (data) => {
137
+ const UUID_REGEX = '[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}';
138
+ const regExp = new RegExp(UUID_REGEX);
139
+ return !isFileData(data) && regExp.test(data);
140
+ };
141
+ /**
142
+ * Url type guard.
143
+ *
144
+ * @param {NodeFile | BrowserFile | Url | Uuid} data
145
+ */
146
+ const isUrl = (data) => {
147
+ const URL_REGEX = '^(?:\\w+:)?\\/\\/([^\\s\\.]+\\.\\S{2}|localhost[\\:?\\d]*)\\S*$';
148
+ const regExp = new RegExp(URL_REGEX);
149
+ return !isFileData(data) && regExp.test(data);
150
150
  };
151
151
 
152
- const isSimpleValue = (value) => {
153
- return (typeof value === 'string' ||
154
- typeof value === 'number' ||
155
- typeof value === 'undefined');
156
- };
157
- const isObjectValue = (value) => {
158
- return !!value && typeof value === 'object' && !Array.isArray(value);
159
- };
160
- const isFileValue = (value) => !!value &&
161
- typeof value === 'object' &&
162
- 'data' in value &&
163
- isFileData(value.data);
164
- function collectParams(params, inputKey, inputValue) {
165
- if (isFileValue(inputValue)) {
166
- const { name, contentType } = inputValue;
167
- const file = transformFile(inputValue.data); // lgtm [js/superfluous-trailing-arguments]
168
- const options = getFileOptions({ name, contentType });
169
- params.push([inputKey, file, ...options]);
170
- }
171
- else if (isObjectValue(inputValue)) {
172
- for (const [key, value] of Object.entries(inputValue)) {
173
- if (typeof value !== 'undefined') {
174
- params.push([`${inputKey}[${key}]`, String(value)]);
175
- }
176
- }
177
- }
178
- else if (isSimpleValue(inputValue) && inputValue) {
179
- params.push([inputKey, inputValue.toString()]);
180
- }
181
- }
182
- function getFormDataParams(options) {
183
- const params = [];
184
- for (const [key, value] of Object.entries(options)) {
185
- collectParams(params, key, value);
186
- }
187
- return params;
188
- }
189
- function buildFormData(options) {
190
- const formData = getFormData();
191
- const paramsList = getFormDataParams(options);
192
- for (const params of paramsList) {
193
- const [key, value, ...options] = params;
194
- // node form-data has another signature for append
195
- formData.append(key, value, ...options);
196
- }
197
- return formData;
152
+ const isSimpleValue = (value) => {
153
+ return (typeof value === 'string' ||
154
+ typeof value === 'number' ||
155
+ typeof value === 'undefined');
156
+ };
157
+ const isObjectValue = (value) => {
158
+ return !!value && typeof value === 'object' && !Array.isArray(value);
159
+ };
160
+ const isFileValue = (value) => !!value &&
161
+ typeof value === 'object' &&
162
+ 'data' in value &&
163
+ isFileData(value.data);
164
+ function collectParams(params, inputKey, inputValue) {
165
+ if (isFileValue(inputValue)) {
166
+ const { name, contentType } = inputValue;
167
+ const file = transformFile(inputValue.data); // lgtm [js/superfluous-trailing-arguments]
168
+ const options = getFileOptions({ name, contentType });
169
+ params.push([inputKey, file, ...options]);
170
+ }
171
+ else if (isObjectValue(inputValue)) {
172
+ for (const [key, value] of Object.entries(inputValue)) {
173
+ if (typeof value !== 'undefined') {
174
+ params.push([`${inputKey}[${key}]`, String(value)]);
175
+ }
176
+ }
177
+ }
178
+ else if (isSimpleValue(inputValue) && inputValue) {
179
+ params.push([inputKey, inputValue.toString()]);
180
+ }
181
+ }
182
+ function getFormDataParams(options) {
183
+ const params = [];
184
+ for (const [key, value] of Object.entries(options)) {
185
+ collectParams(params, key, value);
186
+ }
187
+ return params;
188
+ }
189
+ function buildFormData(options) {
190
+ const formData = getFormData();
191
+ const paramsList = getFormDataParams(options);
192
+ for (const params of paramsList) {
193
+ const [key, value, ...options] = params;
194
+ // node form-data has another signature for append
195
+ formData.append(key, value, ...options);
196
+ }
197
+ return formData;
198
198
  }
199
199
 
200
- const serializePair = (key, value) => typeof value !== 'undefined' ? `${key}=${encodeURIComponent(value)}` : null;
201
- // TODO: generalize value transforming logic and use it here and inside `buildFormData`
202
- const createQuery = (query) => Object.entries(query)
203
- .reduce((params, [key, value]) => {
204
- let param;
205
- if (typeof value === 'object' && !Array.isArray(value)) {
206
- param = Object.entries(value)
207
- .filter((entry) => typeof entry[1] !== 'undefined')
208
- .map((entry) => serializePair(`${key}[${entry[0]}]`, String(entry[1])));
209
- }
210
- else if (Array.isArray(value)) {
211
- param = value.map((val) => serializePair(`${key}[]`, val));
212
- }
213
- else {
214
- param = serializePair(key, value);
215
- }
216
- return params.concat(param);
217
- }, [])
218
- .filter((x) => !!x)
219
- .join('&');
220
- const getUrl = (base, path, query) => [
221
- base,
222
- path,
223
- query && Object.keys(query).length > 0 ? '?' : '',
224
- query && createQuery(query)
225
- ]
226
- .filter(Boolean)
200
+ const serializePair = (key, value) => typeof value !== 'undefined' ? `${key}=${encodeURIComponent(value)}` : null;
201
+ // TODO: generalize value transforming logic and use it here and inside `buildFormData`
202
+ const createQuery = (query) => Object.entries(query)
203
+ .reduce((params, [key, value]) => {
204
+ let param;
205
+ if (typeof value === 'object' && !Array.isArray(value)) {
206
+ param = Object.entries(value)
207
+ .filter((entry) => typeof entry[1] !== 'undefined')
208
+ .map((entry) => serializePair(`${key}[${entry[0]}]`, String(entry[1])));
209
+ }
210
+ else if (Array.isArray(value)) {
211
+ param = value.map((val) => serializePair(`${key}[]`, val));
212
+ }
213
+ else {
214
+ param = serializePair(key, value);
215
+ }
216
+ return params.concat(param);
217
+ }, [])
218
+ .filter((x) => !!x)
219
+ .join('&');
220
+ const getUrl = (base, path, query) => [
221
+ base,
222
+ path,
223
+ query && Object.keys(query).length > 0 ? '?' : '',
224
+ query && createQuery(query)
225
+ ]
226
+ .filter(Boolean)
227
227
  .join('');
228
228
 
229
- /*
230
- Settings for future support:
231
- parallelDirectUploads: 10,
232
- */
233
- const defaultSettings = {
234
- baseCDN: 'https://ucarecdn.com',
235
- baseURL: 'https://upload.uploadcare.com',
236
- maxContentLength: 50 * 1024 * 1024,
237
- retryThrottledRequestMaxTimes: 1,
238
- multipartMinFileSize: 25 * 1024 * 1024,
239
- multipartChunkSize: 5 * 1024 * 1024,
240
- multipartMinLastPartSize: 1024 * 1024,
241
- maxConcurrentRequests: 4,
242
- multipartMaxAttempts: 3,
243
- pollingTimeoutMilliseconds: 10000,
244
- pusherKey: '79ae88bd931ea68464d9'
245
- };
246
- const defaultContentType = 'application/octet-stream';
229
+ /*
230
+ Settings for future support:
231
+ parallelDirectUploads: 10,
232
+ */
233
+ const defaultSettings = {
234
+ baseCDN: 'https://ucarecdn.com',
235
+ baseURL: 'https://upload.uploadcare.com',
236
+ maxContentLength: 50 * 1024 * 1024,
237
+ retryThrottledRequestMaxTimes: 1,
238
+ multipartMinFileSize: 25 * 1024 * 1024,
239
+ multipartChunkSize: 5 * 1024 * 1024,
240
+ multipartMinLastPartSize: 1024 * 1024,
241
+ maxConcurrentRequests: 4,
242
+ multipartMaxAttempts: 3,
243
+ pollingTimeoutMilliseconds: 10000,
244
+ pusherKey: '79ae88bd931ea68464d9'
245
+ };
246
+ const defaultContentType = 'application/octet-stream';
247
247
  const defaultFilename = 'original';
248
248
 
249
249
  var version = '3.1.1';
250
250
 
251
- /**
252
- * Returns User Agent based on version and settings.
253
- */
254
- function getUserAgent({ userAgent, publicKey = '', integration = '' } = {}) {
255
- const libraryName = 'UploadcareUploadClient';
256
- const libraryVersion = version;
257
- const languageName = 'JavaScript';
258
- if (typeof userAgent === 'string') {
259
- return userAgent;
260
- }
261
- if (typeof userAgent === 'function') {
262
- return userAgent({
263
- publicKey,
264
- libraryName,
265
- libraryVersion,
266
- languageName,
267
- integration
268
- });
269
- }
270
- const mainInfo = [libraryName, libraryVersion, publicKey]
271
- .filter(Boolean)
272
- .join('/');
273
- const additionInfo = [languageName, integration].filter(Boolean).join('; ');
274
- return `${mainInfo} (${additionInfo})`;
251
+ /**
252
+ * Returns User Agent based on version and settings.
253
+ */
254
+ function getUserAgent({ userAgent, publicKey = '', integration = '' } = {}) {
255
+ const libraryName = 'UploadcareUploadClient';
256
+ const libraryVersion = version;
257
+ const languageName = 'JavaScript';
258
+ if (typeof userAgent === 'string') {
259
+ return userAgent;
260
+ }
261
+ if (typeof userAgent === 'function') {
262
+ return userAgent({
263
+ publicKey,
264
+ libraryName,
265
+ libraryVersion,
266
+ languageName,
267
+ integration
268
+ });
269
+ }
270
+ const mainInfo = [libraryName, libraryVersion, publicKey]
271
+ .filter(Boolean)
272
+ .join('/');
273
+ const additionInfo = [languageName, integration].filter(Boolean).join('; ');
274
+ return `${mainInfo} (${additionInfo})`;
275
275
  }
276
276
 
277
- const SEPARATOR = /\W|_/g;
278
- /**
279
- * Transforms a string to camelCased.
280
- */
281
- function camelize(text) {
282
- return text
283
- .split(SEPARATOR)
284
- .map((word, index) => word.charAt(0)[index > 0 ? 'toUpperCase' : 'toLowerCase']() +
285
- word.slice(1))
286
- .join('');
287
- }
288
- /**
289
- * Transforms keys of an object to camelCased recursively.
290
- */
291
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
292
- function camelizeKeys(source) {
293
- if (!source || typeof source !== 'object') {
294
- return source;
295
- }
296
- return Object.keys(source).reduce((accumulator, key) => {
297
- accumulator[camelize(key)] =
298
- typeof source[key] === 'object' ? camelizeKeys(source[key]) : source[key];
299
- return accumulator;
300
- }, {});
277
+ const SEPARATOR = /\W|_/g;
278
+ /**
279
+ * Transforms a string to camelCased.
280
+ */
281
+ function camelize(text) {
282
+ return text
283
+ .split(SEPARATOR)
284
+ .map((word, index) => word.charAt(0)[index > 0 ? 'toUpperCase' : 'toLowerCase']() +
285
+ word.slice(1))
286
+ .join('');
287
+ }
288
+ /**
289
+ * Transforms keys of an object to camelCased recursively.
290
+ */
291
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
292
+ function camelizeKeys(source) {
293
+ if (!source || typeof source !== 'object') {
294
+ return source;
295
+ }
296
+ return Object.keys(source).reduce((accumulator, key) => {
297
+ accumulator[camelize(key)] =
298
+ typeof source[key] === 'object' ? camelizeKeys(source[key]) : source[key];
299
+ return accumulator;
300
+ }, {});
301
301
  }
302
302
 
303
- /**
304
- * setTimeout as Promise.
305
- *
306
- * @param {number} ms Timeout in milliseconds.
307
- */
303
+ /**
304
+ * setTimeout as Promise.
305
+ *
306
+ * @param {number} ms Timeout in milliseconds.
307
+ */
308
308
  const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
309
309
 
310
- const defaultOptions = {
311
- factor: 2,
312
- time: 100
313
- };
314
- function retrier(fn, options = defaultOptions) {
315
- let attempts = 0;
316
- function runAttempt(fn) {
317
- const defaultDelayTime = Math.round(options.time * Math.pow(options.factor, attempts));
318
- const retry = (ms) => delay(ms !== null && ms !== void 0 ? ms : defaultDelayTime).then(() => {
319
- attempts += 1;
320
- return runAttempt(fn);
321
- });
322
- return fn({
323
- attempt: attempts,
324
- retry
325
- });
326
- }
327
- return runAttempt(fn);
310
+ const defaultOptions = {
311
+ factor: 2,
312
+ time: 100
313
+ };
314
+ function retrier(fn, options = defaultOptions) {
315
+ let attempts = 0;
316
+ function runAttempt(fn) {
317
+ const defaultDelayTime = Math.round(options.time * Math.pow(options.factor, attempts));
318
+ const retry = (ms) => delay(ms !== null && ms !== void 0 ? ms : defaultDelayTime).then(() => {
319
+ attempts += 1;
320
+ return runAttempt(fn);
321
+ });
322
+ return fn({
323
+ attempt: attempts,
324
+ retry
325
+ });
326
+ }
327
+ return runAttempt(fn);
328
328
  }
329
329
 
330
- const REQUEST_WAS_THROTTLED_CODE = 'RequestThrottledError';
331
- const DEFAULT_RETRY_AFTER_TIMEOUT = 15000;
332
- function getTimeoutFromThrottledRequest(error) {
333
- const { headers } = error || {};
334
- return ((headers &&
335
- Number.parseInt(headers['x-throttle-wait-seconds']) * 1000) ||
336
- DEFAULT_RETRY_AFTER_TIMEOUT);
337
- }
338
- function retryIfThrottled(fn, retryThrottledMaxTimes) {
339
- return retrier(({ attempt, retry }) => fn().catch((error) => {
340
- if ('response' in error &&
341
- (error === null || error === void 0 ? void 0 : error.code) === REQUEST_WAS_THROTTLED_CODE &&
342
- attempt < retryThrottledMaxTimes) {
343
- return retry(getTimeoutFromThrottledRequest(error));
344
- }
345
- throw error;
346
- }));
330
+ const REQUEST_WAS_THROTTLED_CODE = 'RequestThrottledError';
331
+ const DEFAULT_RETRY_AFTER_TIMEOUT = 15000;
332
+ function getTimeoutFromThrottledRequest(error) {
333
+ const { headers } = error || {};
334
+ return ((headers &&
335
+ Number.parseInt(headers['x-throttle-wait-seconds']) * 1000) ||
336
+ DEFAULT_RETRY_AFTER_TIMEOUT);
337
+ }
338
+ function retryIfThrottled(fn, retryThrottledMaxTimes) {
339
+ return retrier(({ attempt, retry }) => fn().catch((error) => {
340
+ if ('response' in error &&
341
+ (error === null || error === void 0 ? void 0 : error.code) === REQUEST_WAS_THROTTLED_CODE &&
342
+ attempt < retryThrottledMaxTimes) {
343
+ return retry(getTimeoutFromThrottledRequest(error));
344
+ }
345
+ throw error;
346
+ }));
347
347
  }
348
348
 
349
- function getStoreValue(store) {
350
- return typeof store === 'undefined' ? 'auto' : store ? '1' : '0';
349
+ function getStoreValue(store) {
350
+ return typeof store === 'undefined' ? 'auto' : store ? '1' : '0';
351
351
  }
352
352
 
353
- /**
354
- * Performs file uploading request to Uploadcare Upload API.
355
- * Can be canceled and has progress.
356
- */
357
- function base(file, { publicKey, fileName, contentType, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, metadata }) {
358
- return retryIfThrottled(() => {
359
- var _a;
360
- return request({
361
- method: 'POST',
362
- url: getUrl(baseURL, '/base/', {
363
- jsonerrors: 1
364
- }),
365
- headers: {
366
- 'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
367
- },
368
- data: buildFormData({
369
- file: {
370
- data: file,
371
- name: (_a = fileName !== null && fileName !== void 0 ? fileName : file.name) !== null && _a !== void 0 ? _a : defaultFilename,
372
- contentType
373
- },
374
- UPLOADCARE_PUB_KEY: publicKey,
375
- UPLOADCARE_STORE: getStoreValue(store),
376
- signature: secureSignature,
377
- expire: secureExpire,
378
- source: source,
379
- metadata
380
- }),
381
- signal,
382
- onProgress
383
- }).then(({ data, headers, request }) => {
384
- const response = camelizeKeys(JSON.parse(data));
385
- if ('error' in response) {
386
- throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
387
- }
388
- else {
389
- return response;
390
- }
391
- });
392
- }, retryThrottledRequestMaxTimes);
353
+ /**
354
+ * Performs file uploading request to Uploadcare Upload API.
355
+ * Can be canceled and has progress.
356
+ */
357
+ function base(file, { publicKey, fileName, contentType, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, metadata }) {
358
+ return retryIfThrottled(() => {
359
+ var _a;
360
+ return request({
361
+ method: 'POST',
362
+ url: getUrl(baseURL, '/base/', {
363
+ jsonerrors: 1
364
+ }),
365
+ headers: {
366
+ 'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
367
+ },
368
+ data: buildFormData({
369
+ file: {
370
+ data: file,
371
+ name: (_a = fileName !== null && fileName !== void 0 ? fileName : file.name) !== null && _a !== void 0 ? _a : defaultFilename,
372
+ contentType
373
+ },
374
+ UPLOADCARE_PUB_KEY: publicKey,
375
+ UPLOADCARE_STORE: getStoreValue(store),
376
+ signature: secureSignature,
377
+ expire: secureExpire,
378
+ source: source,
379
+ metadata
380
+ }),
381
+ signal,
382
+ onProgress
383
+ }).then(({ data, headers, request }) => {
384
+ const response = camelizeKeys(JSON.parse(data));
385
+ if ('error' in response) {
386
+ throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
387
+ }
388
+ else {
389
+ return response;
390
+ }
391
+ });
392
+ }, retryThrottledRequestMaxTimes);
393
393
  }
394
394
 
395
- var TypeEnum;
396
- (function (TypeEnum) {
397
- TypeEnum["Token"] = "token";
398
- TypeEnum["FileInfo"] = "file_info";
399
- })(TypeEnum || (TypeEnum = {}));
400
- /**
401
- * Uploading files from URL.
402
- */
403
- function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, store, fileName, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, source = 'url', signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, metadata }) {
404
- return retryIfThrottled(() => request({
405
- method: 'POST',
406
- headers: {
407
- 'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
408
- },
409
- url: getUrl(baseURL, '/from_url/', {
410
- jsonerrors: 1,
411
- pub_key: publicKey,
412
- source_url: sourceUrl,
413
- store: getStoreValue(store),
414
- filename: fileName,
415
- check_URL_duplicates: checkForUrlDuplicates ? 1 : undefined,
416
- save_URL_duplicates: saveUrlForRecurrentUploads ? 1 : undefined,
417
- signature: secureSignature,
418
- expire: secureExpire,
419
- source: source,
420
- metadata
421
- }),
422
- signal
423
- }).then(({ data, headers, request }) => {
424
- const response = camelizeKeys(JSON.parse(data));
425
- if ('error' in response) {
426
- throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
427
- }
428
- else {
429
- return response;
430
- }
431
- }), retryThrottledRequestMaxTimes);
395
+ var TypeEnum;
396
+ (function (TypeEnum) {
397
+ TypeEnum["Token"] = "token";
398
+ TypeEnum["FileInfo"] = "file_info";
399
+ })(TypeEnum || (TypeEnum = {}));
400
+ /**
401
+ * Uploading files from URL.
402
+ */
403
+ function fromUrl(sourceUrl, { publicKey, baseURL = defaultSettings.baseURL, store, fileName, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, source = 'url', signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, metadata }) {
404
+ return retryIfThrottled(() => request({
405
+ method: 'POST',
406
+ headers: {
407
+ 'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
408
+ },
409
+ url: getUrl(baseURL, '/from_url/', {
410
+ jsonerrors: 1,
411
+ pub_key: publicKey,
412
+ source_url: sourceUrl,
413
+ store: getStoreValue(store),
414
+ filename: fileName,
415
+ check_URL_duplicates: checkForUrlDuplicates ? 1 : undefined,
416
+ save_URL_duplicates: saveUrlForRecurrentUploads ? 1 : undefined,
417
+ signature: secureSignature,
418
+ expire: secureExpire,
419
+ source: source,
420
+ metadata
421
+ }),
422
+ signal
423
+ }).then(({ data, headers, request }) => {
424
+ const response = camelizeKeys(JSON.parse(data));
425
+ if ('error' in response) {
426
+ throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
427
+ }
428
+ else {
429
+ return response;
430
+ }
431
+ }), retryThrottledRequestMaxTimes);
432
432
  }
433
433
 
434
- var Status;
435
- (function (Status) {
436
- Status["Unknown"] = "unknown";
437
- Status["Waiting"] = "waiting";
438
- Status["Progress"] = "progress";
439
- Status["Error"] = "error";
440
- Status["Success"] = "success";
441
- })(Status || (Status = {}));
442
- const isErrorResponse = (response) => {
443
- return 'status' in response && response.status === Status.Error;
444
- };
445
- /**
446
- * Checking upload status and working with file tokens.
447
- */
448
- function fromUrlStatus(token, { publicKey, baseURL = defaultSettings.baseURL, signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes } = {}) {
449
- return retryIfThrottled(() => request({
450
- method: 'GET',
451
- headers: publicKey
452
- ? {
453
- 'X-UC-User-Agent': getUserAgent({
454
- publicKey,
455
- integration,
456
- userAgent
457
- })
458
- }
459
- : undefined,
460
- url: getUrl(baseURL, '/from_url/status/', {
461
- jsonerrors: 1,
462
- token
463
- }),
464
- signal
465
- }).then(({ data, headers, request }) => {
466
- const response = camelizeKeys(JSON.parse(data));
467
- if ('error' in response && !isErrorResponse(response)) {
468
- throw new UploadClientError(response.error.content, undefined, request, response, headers);
469
- }
470
- else {
471
- return response;
472
- }
473
- }), retryThrottledRequestMaxTimes);
434
+ var Status;
435
+ (function (Status) {
436
+ Status["Unknown"] = "unknown";
437
+ Status["Waiting"] = "waiting";
438
+ Status["Progress"] = "progress";
439
+ Status["Error"] = "error";
440
+ Status["Success"] = "success";
441
+ })(Status || (Status = {}));
442
+ const isErrorResponse = (response) => {
443
+ return 'status' in response && response.status === Status.Error;
444
+ };
445
+ /**
446
+ * Checking upload status and working with file tokens.
447
+ */
448
+ function fromUrlStatus(token, { publicKey, baseURL = defaultSettings.baseURL, signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes } = {}) {
449
+ return retryIfThrottled(() => request({
450
+ method: 'GET',
451
+ headers: publicKey
452
+ ? {
453
+ 'X-UC-User-Agent': getUserAgent({
454
+ publicKey,
455
+ integration,
456
+ userAgent
457
+ })
458
+ }
459
+ : undefined,
460
+ url: getUrl(baseURL, '/from_url/status/', {
461
+ jsonerrors: 1,
462
+ token
463
+ }),
464
+ signal
465
+ }).then(({ data, headers, request }) => {
466
+ const response = camelizeKeys(JSON.parse(data));
467
+ if ('error' in response && !isErrorResponse(response)) {
468
+ throw new UploadClientError(response.error.content, undefined, request, response, headers);
469
+ }
470
+ else {
471
+ return response;
472
+ }
473
+ }), retryThrottledRequestMaxTimes);
474
474
  }
475
475
 
476
- /**
477
- * Create files group.
478
- */
479
- function group(uuids, { publicKey, baseURL = defaultSettings.baseURL, jsonpCallback, secureSignature, secureExpire, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
480
- return retryIfThrottled(() => request({
481
- method: 'POST',
482
- headers: {
483
- 'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
484
- },
485
- url: getUrl(baseURL, '/group/', {
486
- jsonerrors: 1,
487
- pub_key: publicKey,
488
- files: uuids,
489
- callback: jsonpCallback,
490
- signature: secureSignature,
491
- expire: secureExpire,
492
- source
493
- }),
494
- signal
495
- }).then(({ data, headers, request }) => {
496
- const response = camelizeKeys(JSON.parse(data));
497
- if ('error' in response) {
498
- throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
499
- }
500
- else {
501
- return response;
502
- }
503
- }), retryThrottledRequestMaxTimes);
476
+ /**
477
+ * Create files group.
478
+ */
479
+ function group(uuids, { publicKey, baseURL = defaultSettings.baseURL, jsonpCallback, secureSignature, secureExpire, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
480
+ return retryIfThrottled(() => request({
481
+ method: 'POST',
482
+ headers: {
483
+ 'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
484
+ },
485
+ url: getUrl(baseURL, '/group/', {
486
+ jsonerrors: 1,
487
+ pub_key: publicKey,
488
+ files: uuids,
489
+ callback: jsonpCallback,
490
+ signature: secureSignature,
491
+ expire: secureExpire,
492
+ source
493
+ }),
494
+ signal
495
+ }).then(({ data, headers, request }) => {
496
+ const response = camelizeKeys(JSON.parse(data));
497
+ if ('error' in response) {
498
+ throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
499
+ }
500
+ else {
501
+ return response;
502
+ }
503
+ }), retryThrottledRequestMaxTimes);
504
504
  }
505
505
 
506
- /**
507
- * Get info about group.
508
- */
509
- function groupInfo(id, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
510
- return retryIfThrottled(() => request({
511
- method: 'GET',
512
- headers: {
513
- 'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
514
- },
515
- url: getUrl(baseURL, '/group/info/', {
516
- jsonerrors: 1,
517
- pub_key: publicKey,
518
- group_id: id,
519
- source
520
- }),
521
- signal
522
- }).then(({ data, headers, request }) => {
523
- const response = camelizeKeys(JSON.parse(data));
524
- if ('error' in response) {
525
- throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
526
- }
527
- else {
528
- return response;
529
- }
530
- }), retryThrottledRequestMaxTimes);
506
+ /**
507
+ * Get info about group.
508
+ */
509
+ function groupInfo(id, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
510
+ return retryIfThrottled(() => request({
511
+ method: 'GET',
512
+ headers: {
513
+ 'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
514
+ },
515
+ url: getUrl(baseURL, '/group/info/', {
516
+ jsonerrors: 1,
517
+ pub_key: publicKey,
518
+ group_id: id,
519
+ source
520
+ }),
521
+ signal
522
+ }).then(({ data, headers, request }) => {
523
+ const response = camelizeKeys(JSON.parse(data));
524
+ if ('error' in response) {
525
+ throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
526
+ }
527
+ else {
528
+ return response;
529
+ }
530
+ }), retryThrottledRequestMaxTimes);
531
531
  }
532
532
 
533
- /**
534
- * Returns a JSON dictionary holding file info.
535
- */
536
- function info(uuid, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
537
- return retryIfThrottled(() => request({
538
- method: 'GET',
539
- headers: {
540
- 'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
541
- },
542
- url: getUrl(baseURL, '/info/', {
543
- jsonerrors: 1,
544
- pub_key: publicKey,
545
- file_id: uuid,
546
- source
547
- }),
548
- signal
549
- }).then(({ data, headers, request }) => {
550
- const response = camelizeKeys(JSON.parse(data));
551
- if ('error' in response) {
552
- throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
553
- }
554
- else {
555
- return response;
556
- }
557
- }), retryThrottledRequestMaxTimes);
533
+ /**
534
+ * Returns a JSON dictionary holding file info.
535
+ */
536
+ function info(uuid, { publicKey, baseURL = defaultSettings.baseURL, signal, source, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
537
+ return retryIfThrottled(() => request({
538
+ method: 'GET',
539
+ headers: {
540
+ 'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
541
+ },
542
+ url: getUrl(baseURL, '/info/', {
543
+ jsonerrors: 1,
544
+ pub_key: publicKey,
545
+ file_id: uuid,
546
+ source
547
+ }),
548
+ signal
549
+ }).then(({ data, headers, request }) => {
550
+ const response = camelizeKeys(JSON.parse(data));
551
+ if ('error' in response) {
552
+ throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
553
+ }
554
+ else {
555
+ return response;
556
+ }
557
+ }), retryThrottledRequestMaxTimes);
558
558
  }
559
559
 
560
- /**
561
- * Start multipart uploading.
562
- */
563
- function multipartStart(size, { publicKey, contentType, fileName, multipartChunkSize = defaultSettings.multipartChunkSize, baseURL = '', secureSignature, secureExpire, store, signal, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, metadata }) {
564
- return retryIfThrottled(() => request({
565
- method: 'POST',
566
- url: getUrl(baseURL, '/multipart/start/', { jsonerrors: 1 }),
567
- headers: {
568
- 'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
569
- },
570
- data: buildFormData({
571
- filename: fileName !== null && fileName !== void 0 ? fileName : defaultFilename,
572
- size: size,
573
- content_type: contentType !== null && contentType !== void 0 ? contentType : defaultContentType,
574
- part_size: multipartChunkSize,
575
- UPLOADCARE_STORE: getStoreValue(store),
576
- UPLOADCARE_PUB_KEY: publicKey,
577
- signature: secureSignature,
578
- expire: secureExpire,
579
- source: source,
580
- metadata
581
- }),
582
- signal
583
- }).then(({ data, headers, request }) => {
584
- const response = camelizeKeys(JSON.parse(data));
585
- if ('error' in response) {
586
- throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
587
- }
588
- else {
589
- // convert to array
590
- response.parts = Object.keys(response.parts).map((key) => response.parts[key]);
591
- return response;
592
- }
593
- }), retryThrottledRequestMaxTimes);
560
+ /**
561
+ * Start multipart uploading.
562
+ */
563
+ function multipartStart(size, { publicKey, contentType, fileName, multipartChunkSize = defaultSettings.multipartChunkSize, baseURL = '', secureSignature, secureExpire, store, signal, source = 'local', integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes, metadata }) {
564
+ return retryIfThrottled(() => request({
565
+ method: 'POST',
566
+ url: getUrl(baseURL, '/multipart/start/', { jsonerrors: 1 }),
567
+ headers: {
568
+ 'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
569
+ },
570
+ data: buildFormData({
571
+ filename: fileName !== null && fileName !== void 0 ? fileName : defaultFilename,
572
+ size: size,
573
+ content_type: contentType !== null && contentType !== void 0 ? contentType : defaultContentType,
574
+ part_size: multipartChunkSize,
575
+ UPLOADCARE_STORE: getStoreValue(store),
576
+ UPLOADCARE_PUB_KEY: publicKey,
577
+ signature: secureSignature,
578
+ expire: secureExpire,
579
+ source: source,
580
+ metadata
581
+ }),
582
+ signal
583
+ }).then(({ data, headers, request }) => {
584
+ const response = camelizeKeys(JSON.parse(data));
585
+ if ('error' in response) {
586
+ throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
587
+ }
588
+ else {
589
+ // convert to array
590
+ response.parts = Object.keys(response.parts).map((key) => response.parts[key]);
591
+ return response;
592
+ }
593
+ }), retryThrottledRequestMaxTimes);
594
594
  }
595
595
 
596
- /**
597
- * Complete multipart uploading.
598
- */
599
- function multipartUpload(part, url, { signal, onProgress }) {
600
- return request({
601
- method: 'PUT',
602
- url,
603
- data: part,
604
- // Upload request can't be non-computable because we always know exact size
605
- onProgress: onProgress,
606
- signal
607
- })
608
- .then((result) => {
609
- // hack for node ¯\_(ツ)_/¯
610
- if (onProgress)
611
- onProgress({
612
- isComputable: true,
613
- value: 1
614
- });
615
- return result;
616
- })
617
- .then(({ status }) => ({ code: status }));
596
+ /**
597
+ * Complete multipart uploading.
598
+ */
599
+ function multipartUpload(part, url, { signal, onProgress }) {
600
+ return request({
601
+ method: 'PUT',
602
+ url,
603
+ data: part,
604
+ // Upload request can't be non-computable because we always know exact size
605
+ onProgress: onProgress,
606
+ signal
607
+ })
608
+ .then((result) => {
609
+ // hack for node ¯\_(ツ)_/¯
610
+ if (onProgress)
611
+ onProgress({
612
+ isComputable: true,
613
+ value: 1
614
+ });
615
+ return result;
616
+ })
617
+ .then(({ status }) => ({ code: status }));
618
618
  }
619
619
 
620
- /**
621
- * Complete multipart uploading.
622
- */
623
- function multipartComplete(uuid, { publicKey, baseURL = defaultSettings.baseURL, source = 'local', signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
624
- return retryIfThrottled(() => request({
625
- method: 'POST',
626
- url: getUrl(baseURL, '/multipart/complete/', { jsonerrors: 1 }),
627
- headers: {
628
- 'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
629
- },
630
- data: buildFormData({
631
- uuid: uuid,
632
- UPLOADCARE_PUB_KEY: publicKey,
633
- source: source
634
- }),
635
- signal
636
- }).then(({ data, headers, request }) => {
637
- const response = camelizeKeys(JSON.parse(data));
638
- if ('error' in response) {
639
- throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
640
- }
641
- else {
642
- return response;
643
- }
644
- }), retryThrottledRequestMaxTimes);
620
+ /**
621
+ * Complete multipart uploading.
622
+ */
623
+ function multipartComplete(uuid, { publicKey, baseURL = defaultSettings.baseURL, source = 'local', signal, integration, userAgent, retryThrottledRequestMaxTimes = defaultSettings.retryThrottledRequestMaxTimes }) {
624
+ return retryIfThrottled(() => request({
625
+ method: 'POST',
626
+ url: getUrl(baseURL, '/multipart/complete/', { jsonerrors: 1 }),
627
+ headers: {
628
+ 'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
629
+ },
630
+ data: buildFormData({
631
+ uuid: uuid,
632
+ UPLOADCARE_PUB_KEY: publicKey,
633
+ source: source
634
+ }),
635
+ signal
636
+ }).then(({ data, headers, request }) => {
637
+ const response = camelizeKeys(JSON.parse(data));
638
+ if ('error' in response) {
639
+ throw new UploadClientError(response.error.content, response.error.errorCode, request, response, headers);
640
+ }
641
+ else {
642
+ return response;
643
+ }
644
+ }), retryThrottledRequestMaxTimes);
645
645
  }
646
646
 
647
- class UploadcareFile {
648
- constructor(fileInfo, { baseCDN, defaultEffects, fileName }) {
649
- this.name = null;
650
- this.size = null;
651
- this.isStored = null;
652
- this.isImage = null;
653
- this.mimeType = null;
654
- this.cdnUrl = null;
655
- this.cdnUrlModifiers = null;
656
- this.originalUrl = null;
657
- this.originalFilename = null;
658
- this.imageInfo = null;
659
- this.videoInfo = null;
660
- this.contentInfo = null;
661
- this.metadata = null;
662
- const { uuid, s3Bucket } = fileInfo;
663
- const urlBase = s3Bucket
664
- ? `https://${s3Bucket}.s3.amazonaws.com/${uuid}/${fileInfo.filename}`
665
- : `${baseCDN}/${uuid}/`;
666
- const cdnUrlModifiers = defaultEffects ? `-/${defaultEffects}` : null;
667
- const cdnUrl = `${urlBase}${cdnUrlModifiers || ''}`;
668
- const originalUrl = uuid ? urlBase : null;
669
- this.uuid = uuid;
670
- this.name = fileName || fileInfo.filename;
671
- this.size = fileInfo.size;
672
- this.isStored = fileInfo.isStored;
673
- this.isImage = fileInfo.isImage;
674
- this.mimeType = fileInfo.mimeType;
675
- this.cdnUrl = cdnUrl;
676
- this.cdnUrlModifiers = cdnUrlModifiers;
677
- this.originalUrl = originalUrl;
678
- this.originalFilename = fileInfo.originalFilename;
679
- this.imageInfo = camelizeKeys(fileInfo.imageInfo);
680
- this.videoInfo = camelizeKeys(fileInfo.videoInfo);
681
- this.contentInfo = camelizeKeys(fileInfo.contentInfo);
682
- this.metadata = fileInfo.metadata || null;
683
- }
647
+ class UploadcareFile {
648
+ constructor(fileInfo, { baseCDN, fileName }) {
649
+ this.name = null;
650
+ this.size = null;
651
+ this.isStored = null;
652
+ this.isImage = null;
653
+ this.mimeType = null;
654
+ this.cdnUrl = null;
655
+ this.s3Url = null;
656
+ this.originalFilename = null;
657
+ this.imageInfo = null;
658
+ this.videoInfo = null;
659
+ this.contentInfo = null;
660
+ this.metadata = null;
661
+ this.s3Bucket = null;
662
+ const { uuid, s3Bucket } = fileInfo;
663
+ const cdnUrl = `${baseCDN}/${uuid}/`;
664
+ const s3Url = s3Bucket
665
+ ? `https://${s3Bucket}.s3.amazonaws.com/${uuid}/${fileInfo.filename}`
666
+ : null;
667
+ this.uuid = uuid;
668
+ this.name = fileName || fileInfo.filename;
669
+ this.size = fileInfo.size;
670
+ this.isStored = fileInfo.isStored;
671
+ this.isImage = fileInfo.isImage;
672
+ this.mimeType = fileInfo.mimeType;
673
+ this.cdnUrl = cdnUrl;
674
+ this.originalFilename = fileInfo.originalFilename;
675
+ this.imageInfo = camelizeKeys(fileInfo.imageInfo);
676
+ this.videoInfo = camelizeKeys(fileInfo.videoInfo);
677
+ this.contentInfo = camelizeKeys(fileInfo.contentInfo);
678
+ this.metadata = fileInfo.metadata || null;
679
+ this.s3Bucket = s3Bucket || null;
680
+ this.s3Url = s3Url;
681
+ }
684
682
  }
685
683
 
686
- const DEFAULT_INTERVAL = 500;
687
- const poll = ({ check, interval = DEFAULT_INTERVAL, signal }) => new Promise((resolve, reject) => {
688
- let timeoutId;
689
- onCancel(signal, () => {
690
- timeoutId && clearTimeout(timeoutId);
691
- reject(cancelError('Poll cancelled'));
692
- });
693
- const tick = () => {
694
- try {
695
- Promise.resolve(check(signal))
696
- .then((result) => {
697
- if (result) {
698
- resolve(result);
699
- }
700
- else {
701
- timeoutId = setTimeout(tick, interval);
702
- }
703
- })
704
- .catch((error) => reject(error));
705
- }
706
- catch (error) {
707
- reject(error);
708
- }
709
- };
710
- timeoutId = setTimeout(tick, 0);
684
+ const DEFAULT_INTERVAL = 500;
685
+ const poll = ({ check, interval = DEFAULT_INTERVAL, signal }) => new Promise((resolve, reject) => {
686
+ let timeoutId;
687
+ onCancel(signal, () => {
688
+ timeoutId && clearTimeout(timeoutId);
689
+ reject(cancelError('Poll cancelled'));
690
+ });
691
+ const tick = () => {
692
+ try {
693
+ Promise.resolve(check(signal))
694
+ .then((result) => {
695
+ if (result) {
696
+ resolve(result);
697
+ }
698
+ else {
699
+ timeoutId = setTimeout(tick, interval);
700
+ }
701
+ })
702
+ .catch((error) => reject(error));
703
+ }
704
+ catch (error) {
705
+ reject(error);
706
+ }
707
+ };
708
+ timeoutId = setTimeout(tick, 0);
711
709
  });
712
710
 
713
- function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent, retryThrottledRequestMaxTimes, signal, onProgress }) {
714
- return poll({
715
- check: (signal) => info(file, {
716
- publicKey,
717
- baseURL,
718
- signal,
719
- source,
720
- integration,
721
- userAgent,
722
- retryThrottledRequestMaxTimes
723
- }).then((response) => {
724
- if (response.isReady) {
725
- return response;
726
- }
727
- onProgress && onProgress({ isComputable: true, value: 1 });
728
- return false;
729
- }),
730
- signal
731
- });
711
+ function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent, retryThrottledRequestMaxTimes, signal, onProgress }) {
712
+ return poll({
713
+ check: (signal) => info(file, {
714
+ publicKey,
715
+ baseURL,
716
+ signal,
717
+ source,
718
+ integration,
719
+ userAgent,
720
+ retryThrottledRequestMaxTimes
721
+ }).then((response) => {
722
+ if (response.isReady) {
723
+ return response;
724
+ }
725
+ onProgress && onProgress({ isComputable: true, value: 1 });
726
+ return false;
727
+ }),
728
+ signal
729
+ });
732
730
  }
733
731
 
734
- const uploadFromObject = (file, { publicKey, fileName, baseURL, secureSignature, secureExpire, store, contentType, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, baseCDN, metadata }) => {
735
- return base(file, {
736
- publicKey,
737
- fileName,
738
- contentType,
739
- baseURL,
740
- secureSignature,
741
- secureExpire,
742
- store,
743
- signal,
744
- onProgress,
745
- source,
746
- integration,
747
- userAgent,
748
- retryThrottledRequestMaxTimes,
749
- metadata
750
- })
751
- .then(({ file }) => {
752
- return isReadyPoll({
753
- file,
754
- publicKey,
755
- baseURL,
756
- source,
757
- integration,
758
- userAgent,
759
- retryThrottledRequestMaxTimes,
760
- onProgress,
761
- signal
762
- });
763
- })
764
- .then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN }));
732
+ const uploadDirect = (file, { publicKey, fileName, baseURL, secureSignature, secureExpire, store, contentType, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, baseCDN, metadata }) => {
733
+ return base(file, {
734
+ publicKey,
735
+ fileName,
736
+ contentType,
737
+ baseURL,
738
+ secureSignature,
739
+ secureExpire,
740
+ store,
741
+ signal,
742
+ onProgress,
743
+ source,
744
+ integration,
745
+ userAgent,
746
+ retryThrottledRequestMaxTimes,
747
+ metadata
748
+ })
749
+ .then(({ file }) => {
750
+ return isReadyPoll({
751
+ file,
752
+ publicKey,
753
+ baseURL,
754
+ source,
755
+ integration,
756
+ userAgent,
757
+ retryThrottledRequestMaxTimes,
758
+ onProgress,
759
+ signal
760
+ });
761
+ })
762
+ .then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN }));
765
763
  };
766
764
 
767
- /*globals self, window */
768
-
769
- /*eslint-disable @mysticatea/prettier */
770
- const { AbortController, AbortSignal } =
771
- typeof self !== "undefined" ? self :
772
- typeof window !== "undefined" ? window :
773
- /* otherwise */ undefined;
774
-
775
- const race = (fns, { signal } = {}) => {
776
- let lastError = null;
777
- let winnerIndex = null;
778
- const controllers = fns.map(() => new AbortController());
779
- const createStopRaceCallback = (i) => () => {
780
- winnerIndex = i;
781
- controllers.forEach((controller, index) => index !== i && controller.abort());
782
- };
783
- onCancel(signal, () => {
784
- controllers.forEach((controller) => controller.abort());
785
- });
786
- return Promise.all(fns.map((fn, i) => {
787
- const stopRace = createStopRaceCallback(i);
788
- return Promise.resolve()
789
- .then(() => fn({ stopRace, signal: controllers[i].signal }))
790
- .then((result) => {
791
- stopRace();
792
- return result;
793
- })
794
- .catch((error) => {
795
- lastError = error;
796
- return null;
797
- });
798
- })).then((results) => {
799
- if (winnerIndex === null) {
800
- throw lastError;
801
- }
802
- else {
803
- return results[winnerIndex];
804
- }
805
- });
765
+ const race = (fns, { signal } = {}) => {
766
+ let lastError = null;
767
+ let winnerIndex = null;
768
+ const controllers = fns.map(() => new AbortController());
769
+ const createStopRaceCallback = (i) => () => {
770
+ winnerIndex = i;
771
+ controllers.forEach((controller, index) => index !== i && controller.abort());
772
+ };
773
+ onCancel(signal, () => {
774
+ controllers.forEach((controller) => controller.abort());
775
+ });
776
+ return Promise.all(fns.map((fn, i) => {
777
+ const stopRace = createStopRaceCallback(i);
778
+ return Promise.resolve()
779
+ .then(() => fn({ stopRace, signal: controllers[i].signal }))
780
+ .then((result) => {
781
+ stopRace();
782
+ return result;
783
+ })
784
+ .catch((error) => {
785
+ lastError = error;
786
+ return null;
787
+ });
788
+ })).then((results) => {
789
+ if (winnerIndex === null) {
790
+ throw lastError;
791
+ }
792
+ else {
793
+ return results[winnerIndex];
794
+ }
795
+ });
806
796
  };
807
797
 
808
798
  var WebSocket = window.WebSocket;
809
799
 
810
- class Events {
811
- constructor() {
812
- this.events = Object.create({});
813
- }
814
- emit(event, data) {
815
- var _a;
816
- (_a = this.events[event]) === null || _a === void 0 ? void 0 : _a.forEach((fn) => fn(data));
817
- }
818
- on(event, callback) {
819
- this.events[event] = this.events[event] || [];
820
- this.events[event].push(callback);
821
- }
822
- off(event, callback) {
823
- if (callback) {
824
- this.events[event] = this.events[event].filter((fn) => fn !== callback);
825
- }
826
- else {
827
- this.events[event] = [];
828
- }
829
- }
800
+ class Events {
801
+ constructor() {
802
+ this.events = Object.create({});
803
+ }
804
+ emit(event, data) {
805
+ var _a;
806
+ (_a = this.events[event]) === null || _a === void 0 ? void 0 : _a.forEach((fn) => fn(data));
807
+ }
808
+ on(event, callback) {
809
+ this.events[event] = this.events[event] || [];
810
+ this.events[event].push(callback);
811
+ }
812
+ off(event, callback) {
813
+ if (callback) {
814
+ this.events[event] = this.events[event].filter((fn) => fn !== callback);
815
+ }
816
+ else {
817
+ this.events[event] = [];
818
+ }
819
+ }
830
820
  }
831
821
 
832
- const response = (type, data) => {
833
- if (type === 'success') {
834
- return Object.assign({ status: Status.Success }, data);
835
- }
836
- if (type === 'progress') {
837
- return Object.assign({ status: Status.Progress }, data);
838
- }
839
- return Object.assign({ status: Status.Error }, data);
840
- };
841
- class Pusher {
842
- constructor(pusherKey, disconnectTime = 30000) {
843
- this.ws = undefined;
844
- this.queue = [];
845
- this.isConnected = false;
846
- this.subscribers = 0;
847
- this.emmitter = new Events();
848
- this.disconnectTimeoutId = null;
849
- this.key = pusherKey;
850
- this.disconnectTime = disconnectTime;
851
- }
852
- connect() {
853
- this.disconnectTimeoutId && clearTimeout(this.disconnectTimeoutId);
854
- if (!this.isConnected && !this.ws) {
855
- const pusherUrl = `wss://ws.pusherapp.com/app/${this.key}?protocol=5&client=js&version=1.12.2`;
856
- this.ws = new WebSocket(pusherUrl);
857
- this.ws.addEventListener('error', (error) => {
858
- this.emmitter.emit('error', new Error(error.message));
859
- });
860
- this.emmitter.on('connected', () => {
861
- this.isConnected = true;
862
- this.queue.forEach((message) => this.send(message.event, message.data));
863
- this.queue = [];
864
- });
865
- this.ws.addEventListener('message', (e) => {
866
- const data = JSON.parse(e.data.toString());
867
- switch (data.event) {
868
- case 'pusher:connection_established': {
869
- this.emmitter.emit('connected', undefined);
870
- break;
871
- }
872
- case 'pusher:ping': {
873
- this.send('pusher:pong', {});
874
- break;
875
- }
876
- case 'progress':
877
- case 'success':
878
- case 'fail': {
879
- this.emmitter.emit(data.channel, response(data.event, JSON.parse(data.data)));
880
- }
881
- }
882
- });
883
- }
884
- }
885
- disconnect() {
886
- const actualDisconect = () => {
887
- var _a;
888
- (_a = this.ws) === null || _a === void 0 ? void 0 : _a.close();
889
- this.ws = undefined;
890
- this.isConnected = false;
891
- };
892
- if (this.disconnectTime) {
893
- this.disconnectTimeoutId = setTimeout(() => {
894
- actualDisconect();
895
- }, this.disconnectTime);
896
- }
897
- else {
898
- actualDisconect();
899
- }
900
- }
901
- send(event, data) {
902
- var _a;
903
- const str = JSON.stringify({ event, data });
904
- (_a = this.ws) === null || _a === void 0 ? void 0 : _a.send(str);
905
- }
906
- subscribe(token, handler) {
907
- this.subscribers += 1;
908
- this.connect();
909
- const channel = `task-status-${token}`;
910
- const message = {
911
- event: 'pusher:subscribe',
912
- data: { channel }
913
- };
914
- this.emmitter.on(channel, handler);
915
- if (this.isConnected) {
916
- this.send(message.event, message.data);
917
- }
918
- else {
919
- this.queue.push(message);
920
- }
921
- }
922
- unsubscribe(token) {
923
- this.subscribers -= 1;
924
- const channel = `task-status-${token}`;
925
- const message = {
926
- event: 'pusher:unsubscribe',
927
- data: { channel }
928
- };
929
- this.emmitter.off(channel);
930
- if (this.isConnected) {
931
- this.send(message.event, message.data);
932
- }
933
- else {
934
- this.queue = this.queue.filter((msg) => msg.data.channel !== channel);
935
- }
936
- if (this.subscribers === 0) {
937
- this.disconnect();
938
- }
939
- }
940
- onError(callback) {
941
- this.emmitter.on('error', callback);
942
- return () => this.emmitter.off('error', callback);
943
- }
944
- }
945
- let pusher = null;
946
- const getPusher = (key) => {
947
- if (!pusher) {
948
- // no timeout for nodeJS and 30000 ms for browser
949
- const disconectTimeout = typeof window === 'undefined' ? 0 : 30000;
950
- pusher = new Pusher(key, disconectTimeout);
951
- }
952
- return pusher;
953
- };
954
- const preconnect = (key) => {
955
- getPusher(key).connect();
822
+ const response = (type, data) => {
823
+ if (type === 'success') {
824
+ return Object.assign({ status: Status.Success }, data);
825
+ }
826
+ if (type === 'progress') {
827
+ return Object.assign({ status: Status.Progress }, data);
828
+ }
829
+ return Object.assign({ status: Status.Error }, data);
830
+ };
831
+ class Pusher {
832
+ constructor(pusherKey, disconnectTime = 30000) {
833
+ this.ws = undefined;
834
+ this.queue = [];
835
+ this.isConnected = false;
836
+ this.subscribers = 0;
837
+ this.emmitter = new Events();
838
+ this.disconnectTimeoutId = null;
839
+ this.key = pusherKey;
840
+ this.disconnectTime = disconnectTime;
841
+ }
842
+ connect() {
843
+ this.disconnectTimeoutId && clearTimeout(this.disconnectTimeoutId);
844
+ if (!this.isConnected && !this.ws) {
845
+ const pusherUrl = `wss://ws.pusherapp.com/app/${this.key}?protocol=5&client=js&version=1.12.2`;
846
+ this.ws = new WebSocket(pusherUrl);
847
+ this.ws.addEventListener('error', (error) => {
848
+ this.emmitter.emit('error', new Error(error.message));
849
+ });
850
+ this.emmitter.on('connected', () => {
851
+ this.isConnected = true;
852
+ this.queue.forEach((message) => this.send(message.event, message.data));
853
+ this.queue = [];
854
+ });
855
+ this.ws.addEventListener('message', (e) => {
856
+ const data = JSON.parse(e.data.toString());
857
+ switch (data.event) {
858
+ case 'pusher:connection_established': {
859
+ this.emmitter.emit('connected', undefined);
860
+ break;
861
+ }
862
+ case 'pusher:ping': {
863
+ this.send('pusher:pong', {});
864
+ break;
865
+ }
866
+ case 'progress':
867
+ case 'success':
868
+ case 'fail': {
869
+ this.emmitter.emit(data.channel, response(data.event, JSON.parse(data.data)));
870
+ }
871
+ }
872
+ });
873
+ }
874
+ }
875
+ disconnect() {
876
+ const actualDisconect = () => {
877
+ var _a;
878
+ (_a = this.ws) === null || _a === void 0 ? void 0 : _a.close();
879
+ this.ws = undefined;
880
+ this.isConnected = false;
881
+ };
882
+ if (this.disconnectTime) {
883
+ this.disconnectTimeoutId = setTimeout(() => {
884
+ actualDisconect();
885
+ }, this.disconnectTime);
886
+ }
887
+ else {
888
+ actualDisconect();
889
+ }
890
+ }
891
+ send(event, data) {
892
+ var _a;
893
+ const str = JSON.stringify({ event, data });
894
+ (_a = this.ws) === null || _a === void 0 ? void 0 : _a.send(str);
895
+ }
896
+ subscribe(token, handler) {
897
+ this.subscribers += 1;
898
+ this.connect();
899
+ const channel = `task-status-${token}`;
900
+ const message = {
901
+ event: 'pusher:subscribe',
902
+ data: { channel }
903
+ };
904
+ this.emmitter.on(channel, handler);
905
+ if (this.isConnected) {
906
+ this.send(message.event, message.data);
907
+ }
908
+ else {
909
+ this.queue.push(message);
910
+ }
911
+ }
912
+ unsubscribe(token) {
913
+ this.subscribers -= 1;
914
+ const channel = `task-status-${token}`;
915
+ const message = {
916
+ event: 'pusher:unsubscribe',
917
+ data: { channel }
918
+ };
919
+ this.emmitter.off(channel);
920
+ if (this.isConnected) {
921
+ this.send(message.event, message.data);
922
+ }
923
+ else {
924
+ this.queue = this.queue.filter((msg) => msg.data.channel !== channel);
925
+ }
926
+ if (this.subscribers === 0) {
927
+ this.disconnect();
928
+ }
929
+ }
930
+ onError(callback) {
931
+ this.emmitter.on('error', callback);
932
+ return () => this.emmitter.off('error', callback);
933
+ }
934
+ }
935
+ let pusher = null;
936
+ const getPusher = (key) => {
937
+ if (!pusher) {
938
+ // no timeout for nodeJS and 30000 ms for browser
939
+ const disconectTimeout = typeof window === 'undefined' ? 0 : 30000;
940
+ pusher = new Pusher(key, disconectTimeout);
941
+ }
942
+ return pusher;
943
+ };
944
+ const preconnect = (key) => {
945
+ getPusher(key).connect();
956
946
  };
957
947
 
958
- function pollStrategy({ token, publicKey, baseURL, integration, userAgent, retryThrottledRequestMaxTimes, onProgress, signal }) {
959
- return poll({
960
- check: (signal) => fromUrlStatus(token, {
961
- publicKey,
962
- baseURL,
963
- integration,
964
- userAgent,
965
- retryThrottledRequestMaxTimes,
966
- signal
967
- }).then((response) => {
968
- switch (response.status) {
969
- case Status.Error: {
970
- return new UploadClientError(response.error, response.errorCode);
971
- }
972
- case Status.Waiting: {
973
- return false;
974
- }
975
- case Status.Unknown: {
976
- return new UploadClientError(`Token "${token}" was not found.`);
977
- }
978
- case Status.Progress: {
979
- if (onProgress) {
980
- if (response.total === 'unknown') {
981
- onProgress({ isComputable: false });
982
- }
983
- else {
984
- onProgress({
985
- isComputable: true,
986
- value: response.done / response.total
987
- });
988
- }
989
- }
990
- return false;
991
- }
992
- case Status.Success: {
993
- if (onProgress)
994
- onProgress({
995
- isComputable: true,
996
- value: response.done / response.total
997
- });
998
- return response;
999
- }
1000
- default: {
1001
- throw new Error('Unknown status');
1002
- }
1003
- }
1004
- }),
1005
- signal
1006
- });
1007
- }
1008
- const pushStrategy = ({ token, pusherKey, signal, onProgress }) => new Promise((resolve, reject) => {
1009
- const pusher = getPusher(pusherKey);
1010
- const unsubErrorHandler = pusher.onError(reject);
1011
- const destroy = () => {
1012
- unsubErrorHandler();
1013
- pusher.unsubscribe(token);
1014
- };
1015
- onCancel(signal, () => {
1016
- destroy();
1017
- reject(cancelError('pusher cancelled'));
1018
- });
1019
- pusher.subscribe(token, (result) => {
1020
- switch (result.status) {
1021
- case Status.Progress: {
1022
- if (onProgress) {
1023
- if (result.total === 'unknown') {
1024
- onProgress({ isComputable: false });
1025
- }
1026
- else {
1027
- onProgress({
1028
- isComputable: true,
1029
- value: result.done / result.total
1030
- });
1031
- }
1032
- }
1033
- break;
1034
- }
1035
- case Status.Success: {
1036
- destroy();
1037
- if (onProgress)
1038
- onProgress({
1039
- isComputable: true,
1040
- value: result.done / result.total
1041
- });
1042
- resolve(result);
1043
- break;
1044
- }
1045
- case Status.Error: {
1046
- destroy();
1047
- reject(new UploadClientError(result.msg, result.error_code));
1048
- }
1049
- }
1050
- });
1051
- });
1052
- const uploadFromUrl = (sourceUrl, { publicKey, fileName, baseURL, baseCDN, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, pusherKey = defaultSettings.pusherKey, metadata }) => Promise.resolve(preconnect(pusherKey))
1053
- .then(() => fromUrl(sourceUrl, {
1054
- publicKey,
1055
- fileName,
1056
- baseURL,
1057
- checkForUrlDuplicates,
1058
- saveUrlForRecurrentUploads,
1059
- secureSignature,
1060
- secureExpire,
1061
- store,
1062
- signal,
1063
- source,
1064
- integration,
1065
- userAgent,
1066
- retryThrottledRequestMaxTimes,
1067
- metadata
1068
- }))
1069
- .catch((error) => {
1070
- const pusher = getPusher(pusherKey);
1071
- pusher === null || pusher === void 0 ? void 0 : pusher.disconnect();
1072
- return Promise.reject(error);
1073
- })
1074
- .then((urlResponse) => {
1075
- if (urlResponse.type === TypeEnum.FileInfo) {
1076
- return urlResponse;
1077
- }
1078
- else {
1079
- return race([
1080
- ({ signal }) => pollStrategy({
1081
- token: urlResponse.token,
1082
- publicKey,
1083
- baseURL,
1084
- integration,
1085
- userAgent,
1086
- retryThrottledRequestMaxTimes,
1087
- onProgress,
1088
- signal
1089
- }),
1090
- ({ signal }) => pushStrategy({
1091
- token: urlResponse.token,
1092
- pusherKey,
1093
- signal,
1094
- onProgress
1095
- })
1096
- ], { signal });
1097
- }
1098
- })
1099
- .then((result) => {
1100
- if (result instanceof UploadClientError)
1101
- throw result;
1102
- return result;
1103
- })
1104
- .then((result) => isReadyPoll({
1105
- file: result.uuid,
1106
- publicKey,
1107
- baseURL,
1108
- integration,
1109
- userAgent,
1110
- retryThrottledRequestMaxTimes,
1111
- onProgress,
1112
- signal
1113
- }))
948
+ function pollStrategy({ token, publicKey, baseURL, integration, userAgent, retryThrottledRequestMaxTimes, onProgress, signal }) {
949
+ return poll({
950
+ check: (signal) => fromUrlStatus(token, {
951
+ publicKey,
952
+ baseURL,
953
+ integration,
954
+ userAgent,
955
+ retryThrottledRequestMaxTimes,
956
+ signal
957
+ }).then((response) => {
958
+ switch (response.status) {
959
+ case Status.Error: {
960
+ return new UploadClientError(response.error, response.errorCode);
961
+ }
962
+ case Status.Waiting: {
963
+ return false;
964
+ }
965
+ case Status.Unknown: {
966
+ return new UploadClientError(`Token "${token}" was not found.`);
967
+ }
968
+ case Status.Progress: {
969
+ if (onProgress) {
970
+ if (response.total === 'unknown') {
971
+ onProgress({ isComputable: false });
972
+ }
973
+ else {
974
+ onProgress({
975
+ isComputable: true,
976
+ value: response.done / response.total
977
+ });
978
+ }
979
+ }
980
+ return false;
981
+ }
982
+ case Status.Success: {
983
+ if (onProgress)
984
+ onProgress({
985
+ isComputable: true,
986
+ value: response.done / response.total
987
+ });
988
+ return response;
989
+ }
990
+ default: {
991
+ throw new Error('Unknown status');
992
+ }
993
+ }
994
+ }),
995
+ signal
996
+ });
997
+ }
998
+ const pushStrategy = ({ token, pusherKey, signal, onProgress }) => new Promise((resolve, reject) => {
999
+ const pusher = getPusher(pusherKey);
1000
+ const unsubErrorHandler = pusher.onError(reject);
1001
+ const destroy = () => {
1002
+ unsubErrorHandler();
1003
+ pusher.unsubscribe(token);
1004
+ };
1005
+ onCancel(signal, () => {
1006
+ destroy();
1007
+ reject(cancelError('pusher cancelled'));
1008
+ });
1009
+ pusher.subscribe(token, (result) => {
1010
+ switch (result.status) {
1011
+ case Status.Progress: {
1012
+ if (onProgress) {
1013
+ if (result.total === 'unknown') {
1014
+ onProgress({ isComputable: false });
1015
+ }
1016
+ else {
1017
+ onProgress({
1018
+ isComputable: true,
1019
+ value: result.done / result.total
1020
+ });
1021
+ }
1022
+ }
1023
+ break;
1024
+ }
1025
+ case Status.Success: {
1026
+ destroy();
1027
+ if (onProgress)
1028
+ onProgress({
1029
+ isComputable: true,
1030
+ value: result.done / result.total
1031
+ });
1032
+ resolve(result);
1033
+ break;
1034
+ }
1035
+ case Status.Error: {
1036
+ destroy();
1037
+ reject(new UploadClientError(result.msg, result.error_code));
1038
+ }
1039
+ }
1040
+ });
1041
+ });
1042
+ const uploadFromUrl = (sourceUrl, { publicKey, fileName, baseURL, baseCDN, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, pusherKey = defaultSettings.pusherKey, metadata }) => Promise.resolve(preconnect(pusherKey))
1043
+ .then(() => fromUrl(sourceUrl, {
1044
+ publicKey,
1045
+ fileName,
1046
+ baseURL,
1047
+ checkForUrlDuplicates,
1048
+ saveUrlForRecurrentUploads,
1049
+ secureSignature,
1050
+ secureExpire,
1051
+ store,
1052
+ signal,
1053
+ source,
1054
+ integration,
1055
+ userAgent,
1056
+ retryThrottledRequestMaxTimes,
1057
+ metadata
1058
+ }))
1059
+ .catch((error) => {
1060
+ const pusher = getPusher(pusherKey);
1061
+ pusher === null || pusher === void 0 ? void 0 : pusher.disconnect();
1062
+ return Promise.reject(error);
1063
+ })
1064
+ .then((urlResponse) => {
1065
+ if (urlResponse.type === TypeEnum.FileInfo) {
1066
+ return urlResponse;
1067
+ }
1068
+ else {
1069
+ return race([
1070
+ ({ signal }) => pollStrategy({
1071
+ token: urlResponse.token,
1072
+ publicKey,
1073
+ baseURL,
1074
+ integration,
1075
+ userAgent,
1076
+ retryThrottledRequestMaxTimes,
1077
+ onProgress,
1078
+ signal
1079
+ }),
1080
+ ({ signal }) => pushStrategy({
1081
+ token: urlResponse.token,
1082
+ pusherKey,
1083
+ signal,
1084
+ onProgress
1085
+ })
1086
+ ], { signal });
1087
+ }
1088
+ })
1089
+ .then((result) => {
1090
+ if (result instanceof UploadClientError)
1091
+ throw result;
1092
+ return result;
1093
+ })
1094
+ .then((result) => isReadyPoll({
1095
+ file: result.uuid,
1096
+ publicKey,
1097
+ baseURL,
1098
+ integration,
1099
+ userAgent,
1100
+ retryThrottledRequestMaxTimes,
1101
+ onProgress,
1102
+ signal
1103
+ }))
1114
1104
  .then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN }));
1115
1105
 
1116
- const uploadFromUploaded = (uuid, { publicKey, fileName, baseURL, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, baseCDN }) => {
1117
- return info(uuid, {
1118
- publicKey,
1119
- baseURL,
1120
- signal,
1121
- source,
1122
- integration,
1123
- userAgent,
1124
- retryThrottledRequestMaxTimes
1125
- })
1126
- .then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN, fileName }))
1127
- .then((result) => {
1128
- // hack for node ¯\_(ツ)_/¯
1129
- if (onProgress)
1130
- onProgress({
1131
- isComputable: true,
1132
- value: 1
1133
- });
1134
- return result;
1135
- });
1106
+ const uploadFromUploaded = (uuid, { publicKey, fileName, baseURL, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, baseCDN }) => {
1107
+ return info(uuid, {
1108
+ publicKey,
1109
+ baseURL,
1110
+ signal,
1111
+ source,
1112
+ integration,
1113
+ userAgent,
1114
+ retryThrottledRequestMaxTimes
1115
+ })
1116
+ .then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN, fileName }))
1117
+ .then((result) => {
1118
+ // hack for node ¯\_(ツ)_/¯
1119
+ if (onProgress)
1120
+ onProgress({
1121
+ isComputable: true,
1122
+ value: 1
1123
+ });
1124
+ return result;
1125
+ });
1136
1126
  };
1137
1127
 
1138
- /**
1139
- * Get file size.
1140
- */
1141
- const getFileSize = (file) => {
1142
- return file.length || file.size;
1143
- };
1144
- /**
1145
- * Check if FileData is multipart data.
1146
- */
1147
- const isMultipart = (fileSize, multipartMinFileSize = defaultSettings.multipartMinFileSize) => {
1148
- return fileSize >= multipartMinFileSize;
1128
+ /**
1129
+ * Get file size.
1130
+ */
1131
+ const getFileSize = (file) => {
1132
+ return file.length || file.size;
1133
+ };
1134
+ /**
1135
+ * Check if FileData is multipart data.
1136
+ */
1137
+ const isMultipart = (fileSize, multipartMinFileSize = defaultSettings.multipartMinFileSize) => {
1138
+ return fileSize >= multipartMinFileSize;
1149
1139
  };
1150
1140
 
1151
- const sliceChunk = (file, index, fileSize, chunkSize) => {
1152
- const start = chunkSize * index;
1153
- const end = Math.min(start + chunkSize, fileSize);
1154
- return file.slice(start, end);
1141
+ const sliceChunk = (file, index, fileSize, chunkSize) => {
1142
+ const start = chunkSize * index;
1143
+ const end = Math.min(start + chunkSize, fileSize);
1144
+ return file.slice(start, end);
1155
1145
  };
1156
1146
 
1157
- function prepareChunks(file, fileSize, chunkSize) {
1158
- return (index) => sliceChunk(file, index, fileSize, chunkSize);
1147
+ function prepareChunks(file, fileSize, chunkSize) {
1148
+ return (index) => sliceChunk(file, index, fileSize, chunkSize);
1159
1149
  }
1160
1150
 
1161
- const runWithConcurrency = (concurrency, tasks) => {
1162
- return new Promise((resolve, reject) => {
1163
- const results = [];
1164
- let rejected = false;
1165
- let settled = tasks.length;
1166
- const forRun = [...tasks];
1167
- const run = () => {
1168
- const index = tasks.length - forRun.length;
1169
- const next = forRun.shift();
1170
- if (next) {
1171
- next()
1172
- .then((result) => {
1173
- if (rejected)
1174
- return;
1175
- results[index] = result;
1176
- settled -= 1;
1177
- if (settled) {
1178
- run();
1179
- }
1180
- else {
1181
- resolve(results);
1182
- }
1183
- })
1184
- .catch((error) => {
1185
- rejected = true;
1186
- reject(error);
1187
- });
1188
- }
1189
- };
1190
- for (let i = 0; i < concurrency; i++) {
1191
- run();
1192
- }
1193
- });
1151
+ const runWithConcurrency = (concurrency, tasks) => {
1152
+ return new Promise((resolve, reject) => {
1153
+ const results = [];
1154
+ let rejected = false;
1155
+ let settled = tasks.length;
1156
+ const forRun = [...tasks];
1157
+ const run = () => {
1158
+ const index = tasks.length - forRun.length;
1159
+ const next = forRun.shift();
1160
+ if (next) {
1161
+ next()
1162
+ .then((result) => {
1163
+ if (rejected)
1164
+ return;
1165
+ results[index] = result;
1166
+ settled -= 1;
1167
+ if (settled) {
1168
+ run();
1169
+ }
1170
+ else {
1171
+ resolve(results);
1172
+ }
1173
+ })
1174
+ .catch((error) => {
1175
+ rejected = true;
1176
+ reject(error);
1177
+ });
1178
+ }
1179
+ };
1180
+ for (let i = 0; i < concurrency; i++) {
1181
+ run();
1182
+ }
1183
+ });
1194
1184
  };
1195
1185
 
1196
- const uploadPartWithRetry = (chunk, url, { publicKey, onProgress, signal, integration, multipartMaxAttempts }) => retrier(({ attempt, retry }) => multipartUpload(chunk, url, {
1197
- publicKey,
1198
- onProgress,
1199
- signal,
1200
- integration
1201
- }).catch((error) => {
1202
- if (attempt < multipartMaxAttempts) {
1203
- return retry();
1204
- }
1205
- throw error;
1206
- }));
1207
- 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, metadata }) => {
1208
- const size = fileSize || getFileSize(file);
1209
- let progressValues;
1210
- const createProgressHandler = (totalChunks, chunkIdx) => {
1211
- if (!onProgress)
1212
- return;
1213
- if (!progressValues) {
1214
- progressValues = Array(totalChunks).fill(0);
1215
- }
1216
- const sum = (values) => values.reduce((sum, next) => sum + next, 0);
1217
- return (info) => {
1218
- if (!info.isComputable) {
1219
- return;
1220
- }
1221
- progressValues[chunkIdx] = info.value;
1222
- onProgress({
1223
- isComputable: true,
1224
- value: sum(progressValues) / totalChunks
1225
- });
1226
- };
1227
- };
1228
- return multipartStart(size, {
1229
- publicKey,
1230
- contentType,
1231
- fileName: fileName !== null && fileName !== void 0 ? fileName : file.name,
1232
- baseURL,
1233
- secureSignature,
1234
- secureExpire,
1235
- store,
1236
- signal,
1237
- source,
1238
- integration,
1239
- userAgent,
1240
- retryThrottledRequestMaxTimes,
1241
- metadata
1242
- })
1243
- .then(({ uuid, parts }) => {
1244
- const getChunk = prepareChunks(file, size, multipartChunkSize);
1245
- return Promise.all([
1246
- uuid,
1247
- runWithConcurrency(maxConcurrentRequests, parts.map((url, index) => () => uploadPartWithRetry(getChunk(index), url, {
1248
- publicKey,
1249
- onProgress: createProgressHandler(parts.length, index),
1250
- signal,
1251
- integration,
1252
- multipartMaxAttempts
1253
- })))
1254
- ]);
1255
- })
1256
- .then(([uuid]) => multipartComplete(uuid, {
1257
- publicKey,
1258
- baseURL,
1259
- source,
1260
- integration,
1261
- userAgent,
1262
- retryThrottledRequestMaxTimes
1263
- }))
1264
- .then((fileInfo) => {
1265
- if (fileInfo.isReady) {
1266
- return fileInfo;
1267
- }
1268
- else {
1269
- return isReadyPoll({
1270
- file: fileInfo.uuid,
1271
- publicKey,
1272
- baseURL,
1273
- source,
1274
- integration,
1275
- userAgent,
1276
- retryThrottledRequestMaxTimes,
1277
- onProgress,
1278
- signal
1279
- });
1280
- }
1281
- })
1282
- .then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN }));
1186
+ const uploadPartWithRetry = (chunk, url, { publicKey, onProgress, signal, integration, multipartMaxAttempts }) => retrier(({ attempt, retry }) => multipartUpload(chunk, url, {
1187
+ publicKey,
1188
+ onProgress,
1189
+ signal,
1190
+ integration
1191
+ }).catch((error) => {
1192
+ if (attempt < multipartMaxAttempts) {
1193
+ return retry();
1194
+ }
1195
+ throw error;
1196
+ }));
1197
+ 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, metadata }) => {
1198
+ const size = fileSize || getFileSize(file);
1199
+ let progressValues;
1200
+ const createProgressHandler = (totalChunks, chunkIdx) => {
1201
+ if (!onProgress)
1202
+ return;
1203
+ if (!progressValues) {
1204
+ progressValues = Array(totalChunks).fill(0);
1205
+ }
1206
+ const sum = (values) => values.reduce((sum, next) => sum + next, 0);
1207
+ return (info) => {
1208
+ if (!info.isComputable) {
1209
+ return;
1210
+ }
1211
+ progressValues[chunkIdx] = info.value;
1212
+ onProgress({
1213
+ isComputable: true,
1214
+ value: sum(progressValues) / totalChunks
1215
+ });
1216
+ };
1217
+ };
1218
+ return multipartStart(size, {
1219
+ publicKey,
1220
+ contentType,
1221
+ fileName: fileName !== null && fileName !== void 0 ? fileName : file.name,
1222
+ baseURL,
1223
+ secureSignature,
1224
+ secureExpire,
1225
+ store,
1226
+ signal,
1227
+ source,
1228
+ integration,
1229
+ userAgent,
1230
+ retryThrottledRequestMaxTimes,
1231
+ metadata
1232
+ })
1233
+ .then(({ uuid, parts }) => {
1234
+ const getChunk = prepareChunks(file, size, multipartChunkSize);
1235
+ return Promise.all([
1236
+ uuid,
1237
+ runWithConcurrency(maxConcurrentRequests, parts.map((url, index) => () => uploadPartWithRetry(getChunk(index), url, {
1238
+ publicKey,
1239
+ onProgress: createProgressHandler(parts.length, index),
1240
+ signal,
1241
+ integration,
1242
+ multipartMaxAttempts
1243
+ })))
1244
+ ]);
1245
+ })
1246
+ .then(([uuid]) => multipartComplete(uuid, {
1247
+ publicKey,
1248
+ baseURL,
1249
+ source,
1250
+ integration,
1251
+ userAgent,
1252
+ retryThrottledRequestMaxTimes
1253
+ }))
1254
+ .then((fileInfo) => {
1255
+ if (fileInfo.isReady) {
1256
+ return fileInfo;
1257
+ }
1258
+ else {
1259
+ return isReadyPoll({
1260
+ file: fileInfo.uuid,
1261
+ publicKey,
1262
+ baseURL,
1263
+ source,
1264
+ integration,
1265
+ userAgent,
1266
+ retryThrottledRequestMaxTimes,
1267
+ onProgress,
1268
+ signal
1269
+ });
1270
+ }
1271
+ })
1272
+ .then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN }));
1283
1273
  };
1284
1274
 
1285
- /**
1286
- * Uploads file from provided data.
1287
- */
1288
- function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, contentType, multipartMinFileSize, multipartChunkSize, multipartMaxAttempts, maxConcurrentRequests, baseCDN = defaultSettings.baseCDN, checkForUrlDuplicates, saveUrlForRecurrentUploads, pusherKey, metadata }) {
1289
- if (isFileData(data)) {
1290
- const fileSize = getFileSize(data);
1291
- if (isMultipart(fileSize, multipartMinFileSize)) {
1292
- return uploadMultipart(data, {
1293
- publicKey,
1294
- contentType,
1295
- multipartChunkSize,
1296
- multipartMaxAttempts,
1297
- fileName,
1298
- baseURL,
1299
- secureSignature,
1300
- secureExpire,
1301
- store,
1302
- signal,
1303
- onProgress,
1304
- source,
1305
- integration,
1306
- userAgent,
1307
- maxConcurrentRequests,
1308
- retryThrottledRequestMaxTimes,
1309
- baseCDN,
1310
- metadata
1311
- });
1312
- }
1313
- return uploadFromObject(data, {
1314
- publicKey,
1315
- fileName,
1316
- contentType,
1317
- baseURL,
1318
- secureSignature,
1319
- secureExpire,
1320
- store,
1321
- signal,
1322
- onProgress,
1323
- source,
1324
- integration,
1325
- userAgent,
1326
- retryThrottledRequestMaxTimes,
1327
- baseCDN,
1328
- metadata
1329
- });
1330
- }
1331
- if (isUrl(data)) {
1332
- return uploadFromUrl(data, {
1333
- publicKey,
1334
- fileName,
1335
- baseURL,
1336
- baseCDN,
1337
- checkForUrlDuplicates,
1338
- saveUrlForRecurrentUploads,
1339
- secureSignature,
1340
- secureExpire,
1341
- store,
1342
- signal,
1343
- onProgress,
1344
- source,
1345
- integration,
1346
- userAgent,
1347
- retryThrottledRequestMaxTimes,
1348
- pusherKey,
1349
- metadata
1350
- });
1351
- }
1352
- if (isUuid(data)) {
1353
- return uploadFromUploaded(data, {
1354
- publicKey,
1355
- fileName,
1356
- baseURL,
1357
- signal,
1358
- onProgress,
1359
- source,
1360
- integration,
1361
- userAgent,
1362
- retryThrottledRequestMaxTimes,
1363
- baseCDN
1364
- });
1365
- }
1366
- throw new TypeError(`File uploading from "${data}" is not supported`);
1275
+ /**
1276
+ * Uploads file from provided data.
1277
+ */
1278
+ function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, contentType, multipartMinFileSize, multipartChunkSize, multipartMaxAttempts, maxConcurrentRequests, baseCDN = defaultSettings.baseCDN, checkForUrlDuplicates, saveUrlForRecurrentUploads, pusherKey, metadata }) {
1279
+ if (isFileData(data)) {
1280
+ const fileSize = getFileSize(data);
1281
+ if (isMultipart(fileSize, multipartMinFileSize)) {
1282
+ return uploadMultipart(data, {
1283
+ publicKey,
1284
+ contentType,
1285
+ multipartChunkSize,
1286
+ multipartMaxAttempts,
1287
+ fileName,
1288
+ baseURL,
1289
+ secureSignature,
1290
+ secureExpire,
1291
+ store,
1292
+ signal,
1293
+ onProgress,
1294
+ source,
1295
+ integration,
1296
+ userAgent,
1297
+ maxConcurrentRequests,
1298
+ retryThrottledRequestMaxTimes,
1299
+ baseCDN,
1300
+ metadata
1301
+ });
1302
+ }
1303
+ return uploadDirect(data, {
1304
+ publicKey,
1305
+ fileName,
1306
+ contentType,
1307
+ baseURL,
1308
+ secureSignature,
1309
+ secureExpire,
1310
+ store,
1311
+ signal,
1312
+ onProgress,
1313
+ source,
1314
+ integration,
1315
+ userAgent,
1316
+ retryThrottledRequestMaxTimes,
1317
+ baseCDN,
1318
+ metadata
1319
+ });
1320
+ }
1321
+ if (isUrl(data)) {
1322
+ return uploadFromUrl(data, {
1323
+ publicKey,
1324
+ fileName,
1325
+ baseURL,
1326
+ baseCDN,
1327
+ checkForUrlDuplicates,
1328
+ saveUrlForRecurrentUploads,
1329
+ secureSignature,
1330
+ secureExpire,
1331
+ store,
1332
+ signal,
1333
+ onProgress,
1334
+ source,
1335
+ integration,
1336
+ userAgent,
1337
+ retryThrottledRequestMaxTimes,
1338
+ pusherKey,
1339
+ metadata
1340
+ });
1341
+ }
1342
+ if (isUuid(data)) {
1343
+ return uploadFromUploaded(data, {
1344
+ publicKey,
1345
+ fileName,
1346
+ baseURL,
1347
+ signal,
1348
+ onProgress,
1349
+ source,
1350
+ integration,
1351
+ userAgent,
1352
+ retryThrottledRequestMaxTimes,
1353
+ baseCDN
1354
+ });
1355
+ }
1356
+ throw new TypeError(`File uploading from "${data}" is not supported`);
1367
1357
  }
1368
1358
 
1369
- class UploadcareGroup {
1370
- constructor(groupInfo, files) {
1371
- this.storedAt = null;
1372
- this.uuid = groupInfo.id;
1373
- this.filesCount = groupInfo.filesCount;
1374
- this.totalSize = Object.values(groupInfo.files).reduce((acc, file) => acc + file.size, 0);
1375
- this.isStored = !!groupInfo.datetimeStored;
1376
- this.isImage = !!Object.values(groupInfo.files).filter((file) => file.isImage).length;
1377
- this.cdnUrl = groupInfo.cdnUrl;
1378
- this.files = files;
1379
- this.createdAt = groupInfo.datetimeCreated;
1380
- this.storedAt = groupInfo.datetimeStored;
1381
- }
1359
+ class UploadcareGroup {
1360
+ constructor(groupInfo, files) {
1361
+ this.storedAt = null;
1362
+ this.uuid = groupInfo.id;
1363
+ this.filesCount = groupInfo.filesCount;
1364
+ this.totalSize = Object.values(groupInfo.files).reduce((acc, file) => acc + file.size, 0);
1365
+ this.isStored = !!groupInfo.datetimeStored;
1366
+ this.isImage = !!Object.values(groupInfo.files).filter((file) => file.isImage).length;
1367
+ this.cdnUrl = groupInfo.cdnUrl;
1368
+ this.files = files;
1369
+ this.createdAt = groupInfo.datetimeCreated;
1370
+ this.storedAt = groupInfo.datetimeStored;
1371
+ }
1382
1372
  }
1383
1373
 
1384
- /**
1385
- * FileData type guard.
1386
- */
1387
- const isFileDataArray = (data) => {
1388
- for (const item of data) {
1389
- if (!isFileData(item)) {
1390
- return false;
1391
- }
1392
- }
1393
- return true;
1394
- };
1395
- /**
1396
- * Uuid type guard.
1397
- */
1398
- const isUuidArray = (data) => {
1399
- for (const item of data) {
1400
- if (!isUuid(item)) {
1401
- return false;
1402
- }
1403
- }
1404
- return true;
1405
- };
1406
- /**
1407
- * Url type guard.
1408
- */
1409
- const isUrlArray = (data) => {
1410
- for (const item of data) {
1411
- if (!isUrl(item)) {
1412
- return false;
1413
- }
1414
- }
1415
- return true;
1374
+ /**
1375
+ * FileData type guard.
1376
+ */
1377
+ const isFileDataArray = (data) => {
1378
+ for (const item of data) {
1379
+ if (!isFileData(item)) {
1380
+ return false;
1381
+ }
1382
+ }
1383
+ return true;
1384
+ };
1385
+ /**
1386
+ * Uuid type guard.
1387
+ */
1388
+ const isUuidArray = (data) => {
1389
+ for (const item of data) {
1390
+ if (!isUuid(item)) {
1391
+ return false;
1392
+ }
1393
+ }
1394
+ return true;
1395
+ };
1396
+ /**
1397
+ * Url type guard.
1398
+ */
1399
+ const isUrlArray = (data) => {
1400
+ for (const item of data) {
1401
+ if (!isUrl(item)) {
1402
+ return false;
1403
+ }
1404
+ }
1405
+ return true;
1416
1406
  };
1417
1407
 
1418
- 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 }) {
1419
- if (!isFileDataArray(data) && !isUrlArray(data) && !isUuidArray(data)) {
1420
- throw new TypeError(`Group uploading from "${data}" is not supported`);
1421
- }
1422
- let progressValues;
1423
- let isStillComputable = true;
1424
- const filesCount = data.length;
1425
- const createProgressHandler = (size, index) => {
1426
- if (!onProgress)
1427
- return;
1428
- if (!progressValues) {
1429
- progressValues = Array(size).fill(0);
1430
- }
1431
- const normalize = (values) => values.reduce((sum, next) => sum + next) / size;
1432
- return (info) => {
1433
- if (!info.isComputable || !isStillComputable) {
1434
- isStillComputable = false;
1435
- onProgress({ isComputable: false });
1436
- return;
1437
- }
1438
- progressValues[index] = info.value;
1439
- onProgress({ isComputable: true, value: normalize(progressValues) });
1440
- };
1441
- };
1442
- return Promise.all(data.map((file, index) => uploadFile(file, {
1443
- publicKey,
1444
- fileName,
1445
- baseURL,
1446
- secureSignature,
1447
- secureExpire,
1448
- store,
1449
- signal,
1450
- onProgress: createProgressHandler(filesCount, index),
1451
- source,
1452
- integration,
1453
- userAgent,
1454
- retryThrottledRequestMaxTimes,
1455
- contentType,
1456
- multipartChunkSize,
1457
- baseCDN
1458
- }))).then((files) => {
1459
- const uuids = files.map((file) => file.uuid);
1460
- const addDefaultEffects = (file) => {
1461
- const cdnUrlModifiers = defaultEffects ? `-/${defaultEffects}` : null;
1462
- const cdnUrl = `${file.urlBase}${cdnUrlModifiers || ''}`;
1463
- return Object.assign(Object.assign({}, file), { cdnUrlModifiers,
1464
- cdnUrl });
1465
- };
1466
- const filesInGroup = defaultEffects ? files.map(addDefaultEffects) : files;
1467
- return group(uuids, {
1468
- publicKey,
1469
- baseURL,
1470
- jsonpCallback,
1471
- secureSignature,
1472
- secureExpire,
1473
- signal,
1474
- source,
1475
- integration,
1476
- userAgent,
1477
- retryThrottledRequestMaxTimes
1478
- })
1479
- .then((groupInfo) => new UploadcareGroup(groupInfo, filesInGroup))
1480
- .then((group) => {
1481
- onProgress && onProgress({ isComputable: true, value: 1 });
1482
- return group;
1483
- });
1484
- });
1408
+ 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 }) {
1409
+ if (!isFileDataArray(data) && !isUrlArray(data) && !isUuidArray(data)) {
1410
+ throw new TypeError(`Group uploading from "${data}" is not supported`);
1411
+ }
1412
+ let progressValues;
1413
+ let isStillComputable = true;
1414
+ const filesCount = data.length;
1415
+ const createProgressHandler = (size, index) => {
1416
+ if (!onProgress)
1417
+ return;
1418
+ if (!progressValues) {
1419
+ progressValues = Array(size).fill(0);
1420
+ }
1421
+ const normalize = (values) => values.reduce((sum, next) => sum + next) / size;
1422
+ return (info) => {
1423
+ if (!info.isComputable || !isStillComputable) {
1424
+ isStillComputable = false;
1425
+ onProgress({ isComputable: false });
1426
+ return;
1427
+ }
1428
+ progressValues[index] = info.value;
1429
+ onProgress({ isComputable: true, value: normalize(progressValues) });
1430
+ };
1431
+ };
1432
+ return Promise.all(data.map((file, index) => uploadFile(file, {
1433
+ publicKey,
1434
+ fileName,
1435
+ baseURL,
1436
+ secureSignature,
1437
+ secureExpire,
1438
+ store,
1439
+ signal,
1440
+ onProgress: createProgressHandler(filesCount, index),
1441
+ source,
1442
+ integration,
1443
+ userAgent,
1444
+ retryThrottledRequestMaxTimes,
1445
+ contentType,
1446
+ multipartChunkSize,
1447
+ baseCDN
1448
+ }))).then((files) => {
1449
+ const uuids = files.map((file) => file.uuid);
1450
+ return group(uuids, {
1451
+ publicKey,
1452
+ baseURL,
1453
+ jsonpCallback,
1454
+ secureSignature,
1455
+ secureExpire,
1456
+ signal,
1457
+ source,
1458
+ integration,
1459
+ userAgent,
1460
+ retryThrottledRequestMaxTimes
1461
+ })
1462
+ .then((groupInfo) => new UploadcareGroup(groupInfo, files))
1463
+ .then((group) => {
1464
+ onProgress && onProgress({ isComputable: true, value: 1 });
1465
+ return group;
1466
+ });
1467
+ });
1485
1468
  }
1486
1469
 
1487
- /**
1488
- * Populate options with settings.
1489
- */
1490
- const populateOptionsWithSettings = (options, settings) => (Object.assign(Object.assign({}, settings), options));
1491
- class UploadClient {
1492
- constructor(settings) {
1493
- this.settings = Object.assign({}, defaultSettings, settings);
1494
- }
1495
- updateSettings(newSettings) {
1496
- this.settings = Object.assign(this.settings, newSettings);
1497
- }
1498
- getSettings() {
1499
- return this.settings;
1500
- }
1501
- base(file, options) {
1502
- const settings = this.getSettings();
1503
- return base(file, populateOptionsWithSettings(options, settings));
1504
- }
1505
- info(uuid, options) {
1506
- const settings = this.getSettings();
1507
- return info(uuid, populateOptionsWithSettings(options, settings));
1508
- }
1509
- fromUrl(sourceUrl, options) {
1510
- const settings = this.getSettings();
1511
- return fromUrl(sourceUrl, populateOptionsWithSettings(options, settings));
1512
- }
1513
- fromUrlStatus(token, options) {
1514
- const settings = this.getSettings();
1515
- return fromUrlStatus(token, populateOptionsWithSettings(options, settings));
1516
- }
1517
- group(uuids, options) {
1518
- const settings = this.getSettings();
1519
- return group(uuids, populateOptionsWithSettings(options, settings));
1520
- }
1521
- groupInfo(id, options) {
1522
- const settings = this.getSettings();
1523
- return groupInfo(id, populateOptionsWithSettings(options, settings));
1524
- }
1525
- multipartStart(size, options) {
1526
- const settings = this.getSettings();
1527
- return multipartStart(size, populateOptionsWithSettings(options, settings));
1528
- }
1529
- multipartUpload(part, url, options) {
1530
- const settings = this.getSettings();
1531
- return multipartUpload(part, url, populateOptionsWithSettings(options, settings));
1532
- }
1533
- multipartComplete(uuid, options) {
1534
- const settings = this.getSettings();
1535
- return multipartComplete(uuid, populateOptionsWithSettings(options, settings));
1536
- }
1537
- uploadFile(data, options) {
1538
- const settings = this.getSettings();
1539
- return uploadFile(data, populateOptionsWithSettings(options, settings));
1540
- }
1541
- uploadFileGroup(data, options) {
1542
- const settings = this.getSettings();
1543
- return uploadFileGroup(data, populateOptionsWithSettings(options, settings));
1544
- }
1470
+ /**
1471
+ * Populate options with settings.
1472
+ */
1473
+ const populateOptionsWithSettings = (options, settings) => (Object.assign(Object.assign({}, settings), options));
1474
+ class UploadClient {
1475
+ constructor(settings) {
1476
+ this.settings = Object.assign({}, defaultSettings, settings);
1477
+ }
1478
+ updateSettings(newSettings) {
1479
+ this.settings = Object.assign(this.settings, newSettings);
1480
+ }
1481
+ getSettings() {
1482
+ return this.settings;
1483
+ }
1484
+ base(file, options = {}) {
1485
+ const settings = this.getSettings();
1486
+ return base(file, populateOptionsWithSettings(options, settings));
1487
+ }
1488
+ info(uuid, options = {}) {
1489
+ const settings = this.getSettings();
1490
+ return info(uuid, populateOptionsWithSettings(options, settings));
1491
+ }
1492
+ fromUrl(sourceUrl, options = {}) {
1493
+ const settings = this.getSettings();
1494
+ return fromUrl(sourceUrl, populateOptionsWithSettings(options, settings));
1495
+ }
1496
+ fromUrlStatus(token, options = {}) {
1497
+ const settings = this.getSettings();
1498
+ return fromUrlStatus(token, populateOptionsWithSettings(options, settings));
1499
+ }
1500
+ group(uuids, options = {}) {
1501
+ const settings = this.getSettings();
1502
+ return group(uuids, populateOptionsWithSettings(options, settings));
1503
+ }
1504
+ groupInfo(id, options = {}) {
1505
+ const settings = this.getSettings();
1506
+ return groupInfo(id, populateOptionsWithSettings(options, settings));
1507
+ }
1508
+ multipartStart(size, options = {}) {
1509
+ const settings = this.getSettings();
1510
+ return multipartStart(size, populateOptionsWithSettings(options, settings));
1511
+ }
1512
+ multipartUpload(part, url, options = {}) {
1513
+ const settings = this.getSettings();
1514
+ return multipartUpload(part, url, populateOptionsWithSettings(options, settings));
1515
+ }
1516
+ multipartComplete(uuid, options = {}) {
1517
+ const settings = this.getSettings();
1518
+ return multipartComplete(uuid, populateOptionsWithSettings(options, settings));
1519
+ }
1520
+ uploadFile(data, options = {}) {
1521
+ const settings = this.getSettings();
1522
+ return uploadFile(data, populateOptionsWithSettings(options, settings));
1523
+ }
1524
+ uploadFileGroup(data, options = {}) {
1525
+ const settings = this.getSettings();
1526
+ return uploadFileGroup(data, populateOptionsWithSettings(options, settings));
1527
+ }
1545
1528
  }
1546
1529
 
1547
- export { AbortController, UploadClient, UploadClientError, UploadcareFile, UploadcareGroup, base, fromUrl, fromUrlStatus, group, groupInfo, info, multipartComplete, multipartStart, multipartUpload, uploadFromObject as uploadBase, uploadFile, uploadFileGroup, uploadFromUploaded, uploadFromUrl, uploadMultipart };
1530
+ export { UploadClient, UploadClientError, UploadcareFile, UploadcareGroup, base, fromUrl, fromUrlStatus, group, groupInfo, info, multipartComplete, multipartStart, multipartUpload, uploadDirect, uploadFile, uploadFileGroup, uploadFromUploaded, uploadFromUrl, uploadMultipart };