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