@uploadcare/upload-client 6.0.1-alpha.8 → 6.0.1-alpha.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.browser.js +179 -147
- package/dist/index.d.ts +62 -55
- package/dist/index.node.js +180 -144
- package/dist/index.react-native.js +206 -167
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -70,6 +70,42 @@ export declare type ContentInfo = {
|
|
|
70
70
|
image?: ImageInfo;
|
|
71
71
|
video?: VideoInfo;
|
|
72
72
|
};
|
|
73
|
+
export interface DefaultSettings {
|
|
74
|
+
baseCDN: string;
|
|
75
|
+
baseURL: string;
|
|
76
|
+
maxContentLength: number;
|
|
77
|
+
retryThrottledRequestMaxTimes: number;
|
|
78
|
+
retryNetworkErrorMaxTimes: number;
|
|
79
|
+
multipartMinFileSize: number;
|
|
80
|
+
multipartChunkSize: number;
|
|
81
|
+
multipartMinLastPartSize: number;
|
|
82
|
+
maxConcurrentRequests: number;
|
|
83
|
+
pollingTimeoutMilliseconds: number;
|
|
84
|
+
pusherKey: string;
|
|
85
|
+
}
|
|
86
|
+
export interface Settings extends Partial<DefaultSettings> {
|
|
87
|
+
publicKey: string;
|
|
88
|
+
fileName?: string;
|
|
89
|
+
contentType?: string;
|
|
90
|
+
store?: boolean;
|
|
91
|
+
secureSignature?: string;
|
|
92
|
+
secureExpire?: string;
|
|
93
|
+
integration?: string;
|
|
94
|
+
userAgent?: CustomUserAgent;
|
|
95
|
+
checkForUrlDuplicates?: boolean;
|
|
96
|
+
saveUrlForRecurrentUploads?: boolean;
|
|
97
|
+
source?: string;
|
|
98
|
+
jsonpCallback?: string;
|
|
99
|
+
}
|
|
100
|
+
export declare type BrowserFile = Blob | File;
|
|
101
|
+
export declare type NodeFile = Buffer;
|
|
102
|
+
export declare type ReactNativeAsset = {
|
|
103
|
+
type: string;
|
|
104
|
+
uri: string;
|
|
105
|
+
name?: string;
|
|
106
|
+
};
|
|
107
|
+
export declare type ReactNativeFile = ReactNativeAsset | Blob;
|
|
108
|
+
export declare type AnyFile = BrowserFile | NodeFile | ReactNativeFile;
|
|
73
109
|
export declare type FileInfo = {
|
|
74
110
|
size: number;
|
|
75
111
|
done: number;
|
|
@@ -112,18 +148,6 @@ export declare type ProgressCallback<T = ComputableProgressInfo | UnknownProgres
|
|
|
112
148
|
export declare type Metadata = {
|
|
113
149
|
[key: string]: string;
|
|
114
150
|
};
|
|
115
|
-
export declare type Headers = {
|
|
116
|
-
[key: string]: string | string[] | undefined;
|
|
117
|
-
};
|
|
118
|
-
export declare type ErrorRequestInfo = {
|
|
119
|
-
method?: string;
|
|
120
|
-
url: string;
|
|
121
|
-
query?: string;
|
|
122
|
-
data?: NodeFormData | FormData | BrowserFile | NodeFile;
|
|
123
|
-
headers?: Headers;
|
|
124
|
-
};
|
|
125
|
-
export declare type BrowserFile = Blob | File;
|
|
126
|
-
export declare type NodeFile = Buffer;
|
|
127
151
|
export declare type BaseResponse = {
|
|
128
152
|
file: Uuid;
|
|
129
153
|
};
|
|
@@ -148,7 +172,7 @@ export declare type BaseOptions = {
|
|
|
148
172
|
* Performs file uploading request to Uploadcare Upload API.
|
|
149
173
|
* Can be canceled and has progress.
|
|
150
174
|
*/
|
|
151
|
-
export function base(file:
|
|
175
|
+
export function base(file: AnyFile, { publicKey, fileName, contentType, baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, metadata }: BaseOptions): Promise<BaseResponse>;
|
|
152
176
|
declare enum TypeEnum {
|
|
153
177
|
Token = "token",
|
|
154
178
|
FileInfo = "file_info"
|
|
@@ -309,7 +333,7 @@ export declare type MultipartUploadResponse = {
|
|
|
309
333
|
/**
|
|
310
334
|
* Complete multipart uploading.
|
|
311
335
|
*/
|
|
312
|
-
export function multipartUpload(part:
|
|
336
|
+
export function multipartUpload(part: AnyFile, url: MultipartPart, { signal, onProgress, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes }: MultipartUploadOptions): Promise<MultipartUploadResponse>;
|
|
313
337
|
export declare type MultipartCompleteOptions = {
|
|
314
338
|
publicKey: string;
|
|
315
339
|
baseURL?: string;
|
|
@@ -362,13 +386,7 @@ export declare type DirectOptions = {
|
|
|
362
386
|
baseCDN?: string;
|
|
363
387
|
metadata?: Metadata;
|
|
364
388
|
};
|
|
365
|
-
export declare const uploadDirect: (file:
|
|
366
|
-
export declare type UploadFromUrlOptions = {
|
|
367
|
-
baseCDN?: string;
|
|
368
|
-
onProgress?: ProgressCallback;
|
|
369
|
-
pusherKey?: string;
|
|
370
|
-
} & FromUrlOptions;
|
|
371
|
-
export declare const uploadFromUrl: (sourceUrl: string, { publicKey, fileName, baseURL, baseCDN, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, pusherKey, metadata }: UploadFromUrlOptions) => Promise<UploadcareFile>;
|
|
389
|
+
export declare const uploadDirect: (file: AnyFile, { publicKey, fileName, baseURL, secureSignature, secureExpire, store, contentType, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, baseCDN, metadata }: DirectOptions) => Promise<UploadcareFile>;
|
|
372
390
|
export declare type FromUploadedOptions = {
|
|
373
391
|
publicKey: string;
|
|
374
392
|
fileName?: string;
|
|
@@ -383,6 +401,12 @@ export declare type FromUploadedOptions = {
|
|
|
383
401
|
baseCDN?: string;
|
|
384
402
|
};
|
|
385
403
|
export declare const uploadFromUploaded: (uuid: Uuid, { publicKey, fileName, baseURL, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, baseCDN }: FromUploadedOptions) => Promise<UploadcareFile>;
|
|
404
|
+
export declare type UploadFromUrlOptions = {
|
|
405
|
+
baseCDN?: string;
|
|
406
|
+
onProgress?: ProgressCallback;
|
|
407
|
+
pusherKey?: string;
|
|
408
|
+
} & FromUrlOptions;
|
|
409
|
+
export declare const uploadFromUrl: (sourceUrl: string, { publicKey, fileName, baseURL, baseCDN, checkForUrlDuplicates, saveUrlForRecurrentUploads, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, pusherKey, metadata }: UploadFromUrlOptions) => Promise<UploadcareFile>;
|
|
386
410
|
export declare type MultipartOptions = {
|
|
387
411
|
publicKey: string;
|
|
388
412
|
contentType?: string;
|
|
@@ -404,7 +428,7 @@ export declare type MultipartOptions = {
|
|
|
404
428
|
baseCDN?: string;
|
|
405
429
|
metadata?: Metadata;
|
|
406
430
|
};
|
|
407
|
-
export declare const uploadMultipart: (file:
|
|
431
|
+
export declare const uploadMultipart: (file: AnyFile, { publicKey, fileName, fileSize, baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, contentType, multipartChunkSize, maxConcurrentRequests, baseCDN, metadata }: MultipartOptions) => Promise<UploadcareFile>;
|
|
408
432
|
export declare type FileFromOptions = {
|
|
409
433
|
publicKey: string;
|
|
410
434
|
fileName?: string;
|
|
@@ -432,7 +456,7 @@ export declare type FileFromOptions = {
|
|
|
432
456
|
/**
|
|
433
457
|
* Uploads file from provided data.
|
|
434
458
|
*/
|
|
435
|
-
export declare function uploadFile(data:
|
|
459
|
+
export declare function uploadFile(data: AnyFile | Url | Uuid, { publicKey, fileName, baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, contentType, multipartMinFileSize, multipartChunkSize, maxConcurrentRequests, baseCDN, checkForUrlDuplicates, saveUrlForRecurrentUploads, pusherKey, metadata }: FileFromOptions): Promise<UploadcareFile>;
|
|
436
460
|
export declare class UploadcareGroup {
|
|
437
461
|
readonly uuid: GroupId;
|
|
438
462
|
readonly filesCount: string;
|
|
@@ -448,51 +472,34 @@ export declare class UploadcareGroup {
|
|
|
448
472
|
export declare type GroupFromOptions = {
|
|
449
473
|
jsonpCallback?: string;
|
|
450
474
|
};
|
|
451
|
-
export function uploadFileGroup(data:
|
|
452
|
-
export interface DefaultSettings {
|
|
453
|
-
baseCDN: string;
|
|
454
|
-
baseURL: string;
|
|
455
|
-
maxContentLength: number;
|
|
456
|
-
retryThrottledRequestMaxTimes: number;
|
|
457
|
-
retryNetworkErrorMaxTimes: number;
|
|
458
|
-
multipartMinFileSize: number;
|
|
459
|
-
multipartChunkSize: number;
|
|
460
|
-
multipartMinLastPartSize: number;
|
|
461
|
-
maxConcurrentRequests: number;
|
|
462
|
-
pollingTimeoutMilliseconds: number;
|
|
463
|
-
pusherKey: string;
|
|
464
|
-
}
|
|
465
|
-
export interface Settings extends Partial<DefaultSettings> {
|
|
466
|
-
publicKey: string;
|
|
467
|
-
fileName?: string;
|
|
468
|
-
contentType?: string;
|
|
469
|
-
store?: boolean;
|
|
470
|
-
secureSignature?: string;
|
|
471
|
-
secureExpire?: string;
|
|
472
|
-
integration?: string;
|
|
473
|
-
userAgent?: CustomUserAgent;
|
|
474
|
-
checkForUrlDuplicates?: boolean;
|
|
475
|
-
saveUrlForRecurrentUploads?: boolean;
|
|
476
|
-
source?: string;
|
|
477
|
-
jsonpCallback?: string;
|
|
478
|
-
}
|
|
475
|
+
export function uploadFileGroup(data: AnyFile[] | Url[] | Uuid[], { publicKey, fileName, baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, contentType, multipartChunkSize, baseCDN, jsonpCallback }: FileFromOptions & GroupFromOptions): Promise<UploadcareGroup>;
|
|
479
476
|
export declare class UploadClient {
|
|
480
477
|
private settings;
|
|
481
478
|
constructor(settings: Settings);
|
|
482
479
|
updateSettings(newSettings: Settings): void;
|
|
483
480
|
getSettings(): Settings;
|
|
484
|
-
base(file:
|
|
481
|
+
base(file: AnyFile, options?: Partial<BaseOptions>): Promise<BaseResponse>;
|
|
485
482
|
info(uuid: Uuid, options?: Partial<InfoOptions>): Promise<FileInfo>;
|
|
486
483
|
fromUrl(sourceUrl: Url, options?: Partial<FromUrlOptions>): Promise<FromUrlResponse>;
|
|
487
484
|
fromUrlStatus(token: Token, options?: Partial<FromUrlStatusOptions>): Promise<FromUrlStatusResponse>;
|
|
488
485
|
group(uuids: Uuid[], options?: Partial<GroupOptions>): Promise<GroupInfo>;
|
|
489
486
|
groupInfo(id: GroupId, options?: Partial<GroupInfoOptions>): Promise<GroupInfo>;
|
|
490
487
|
multipartStart(size: number, options?: Partial<MultipartStartOptions>): Promise<MultipartStartResponse>;
|
|
491
|
-
multipartUpload(part:
|
|
488
|
+
multipartUpload(part: BrowserFile | NodeFile, url: MultipartPart, options?: Partial<MultipartUploadOptions>): Promise<MultipartUploadResponse>;
|
|
492
489
|
multipartComplete(uuid: Uuid, options?: Partial<MultipartCompleteOptions>): Promise<FileInfo>;
|
|
493
|
-
uploadFile(data:
|
|
494
|
-
uploadFileGroup(data: (
|
|
490
|
+
uploadFile(data: AnyFile | Url | Uuid, options?: Partial<FileFromOptions>): Promise<UploadcareFile>;
|
|
491
|
+
uploadFileGroup(data: (AnyFile)[] | Url[] | Uuid[], options?: Partial<FileFromOptions & GroupFromOptions>): Promise<UploadcareGroup>;
|
|
495
492
|
}
|
|
493
|
+
export declare type Headers = {
|
|
494
|
+
[key: string]: string | string[] | undefined;
|
|
495
|
+
};
|
|
496
|
+
export declare type ErrorRequestInfo = {
|
|
497
|
+
method?: string;
|
|
498
|
+
url: string;
|
|
499
|
+
query?: string;
|
|
500
|
+
data?: NodeFormData | FormData | AnyFile;
|
|
501
|
+
headers?: Headers;
|
|
502
|
+
};
|
|
496
503
|
export declare type ErrorResponseInfo = {
|
|
497
504
|
error?: {
|
|
498
505
|
statusCode: number;
|
package/dist/index.node.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import http from 'http';
|
|
2
2
|
import https from 'https';
|
|
3
|
-
import { parse } from 'url';
|
|
4
3
|
import { Transform, Readable } from 'stream';
|
|
4
|
+
import { parse } from 'url';
|
|
5
5
|
import NodeFormData from 'form-data';
|
|
6
6
|
import WebSocket from 'ws';
|
|
7
7
|
|
|
@@ -164,6 +164,26 @@ const poll = ({ check, interval = DEFAULT_INTERVAL, timeout, signal }) => new Pr
|
|
|
164
164
|
tickTimeoutId = setTimeout(tick, 0);
|
|
165
165
|
});
|
|
166
166
|
|
|
167
|
+
/*
|
|
168
|
+
Settings for future support:
|
|
169
|
+
parallelDirectUploads: 10,
|
|
170
|
+
*/
|
|
171
|
+
const defaultSettings = {
|
|
172
|
+
baseCDN: 'https://ucarecdn.com',
|
|
173
|
+
baseURL: 'https://upload.uploadcare.com',
|
|
174
|
+
maxContentLength: 50 * 1024 * 1024,
|
|
175
|
+
retryThrottledRequestMaxTimes: 1,
|
|
176
|
+
retryNetworkErrorMaxTimes: 3,
|
|
177
|
+
multipartMinFileSize: 25 * 1024 * 1024,
|
|
178
|
+
multipartChunkSize: 5 * 1024 * 1024,
|
|
179
|
+
multipartMinLastPartSize: 1024 * 1024,
|
|
180
|
+
maxConcurrentRequests: 4,
|
|
181
|
+
pollingTimeoutMilliseconds: 10000,
|
|
182
|
+
pusherKey: '79ae88bd931ea68464d9'
|
|
183
|
+
};
|
|
184
|
+
const defaultContentType = 'application/octet-stream';
|
|
185
|
+
const defaultFilename = 'original';
|
|
186
|
+
|
|
167
187
|
// ProgressEmitter is a simple PassThrough-style transform stream which keeps
|
|
168
188
|
// track of the number of bytes which have been piped through it and will
|
|
169
189
|
// invoke the `onprogress` function whenever new number are available.
|
|
@@ -285,49 +305,24 @@ const getFileOptions = ({ name, contentType }) => [
|
|
|
285
305
|
const transformFile = identity;
|
|
286
306
|
var getFormData = () => new NodeFormData();
|
|
287
307
|
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
return false;
|
|
291
|
-
}
|
|
292
|
-
return uri.startsWith('file:') || uri.startsWith('content:');
|
|
308
|
+
const isBlob = (data) => {
|
|
309
|
+
return typeof Blob !== 'undefined' && data instanceof Blob;
|
|
293
310
|
};
|
|
294
|
-
const
|
|
295
|
-
return
|
|
296
|
-
typeof asset === 'object' &&
|
|
297
|
-
!Array.isArray(asset) &&
|
|
298
|
-
'uri' in asset &&
|
|
299
|
-
typeof asset.uri === 'string' &&
|
|
300
|
-
isReactNativeUri(asset.uri));
|
|
311
|
+
const isFile = (data) => {
|
|
312
|
+
return typeof File !== 'undefined' && data instanceof File;
|
|
301
313
|
};
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
* FileData type guard.
|
|
305
|
-
*/
|
|
306
|
-
const isFileData = (data) => {
|
|
307
|
-
return (data !== undefined &&
|
|
308
|
-
((typeof Blob !== 'undefined' && data instanceof Blob) ||
|
|
309
|
-
(typeof File !== 'undefined' && data instanceof File) ||
|
|
310
|
-
(typeof Buffer !== 'undefined' && data instanceof Buffer) ||
|
|
311
|
-
(typeof data === 'string' && isReactNativeUri(data)) ||
|
|
312
|
-
(typeof data === 'object' && isReactNativeAsset(data))));
|
|
314
|
+
const isBuffer = (data) => {
|
|
315
|
+
return typeof Buffer !== 'undefined' && data instanceof Buffer;
|
|
313
316
|
};
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
return !isFileData(data) && regExp.test(data);
|
|
317
|
+
const isReactNativeAsset = (data) => {
|
|
318
|
+
return (!!data &&
|
|
319
|
+
typeof data === 'object' &&
|
|
320
|
+
!Array.isArray(data) &&
|
|
321
|
+
'uri' in data &&
|
|
322
|
+
typeof data.uri === 'string');
|
|
321
323
|
};
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
*
|
|
325
|
-
* @param {NodeFile | BrowserFile | Url | Uuid} data
|
|
326
|
-
*/
|
|
327
|
-
const isUrl = (data) => {
|
|
328
|
-
const URL_REGEX = '^(?:\\w+:)?\\/\\/([^\\s\\.]+\\.\\S{2}|localhost[\\:?\\d]*)\\S*$';
|
|
329
|
-
const regExp = new RegExp(URL_REGEX);
|
|
330
|
-
return !isFileData(data) && regExp.test(data);
|
|
324
|
+
const isFileData = (data) => {
|
|
325
|
+
return (isBlob(data) || isFile(data) || isBuffer(data) || isReactNativeAsset(data));
|
|
331
326
|
};
|
|
332
327
|
|
|
333
328
|
const isSimpleValue = (value) => {
|
|
@@ -368,11 +363,9 @@ function getFormDataParams(options) {
|
|
|
368
363
|
return params;
|
|
369
364
|
}
|
|
370
365
|
function buildFormData(options) {
|
|
371
|
-
console.log('buildFormData', options);
|
|
372
366
|
const formData = getFormData();
|
|
373
367
|
const paramsList = getFormDataParams(options);
|
|
374
368
|
for (const params of paramsList) {
|
|
375
|
-
console.log('params', params);
|
|
376
369
|
const [key, value, ...rest] = params;
|
|
377
370
|
// node form-data has another signature for append
|
|
378
371
|
formData.append(key, value, ...rest);
|
|
@@ -380,6 +373,19 @@ function buildFormData(options) {
|
|
|
380
373
|
return formData;
|
|
381
374
|
}
|
|
382
375
|
|
|
376
|
+
class UploadClientError extends Error {
|
|
377
|
+
constructor(message, code, request, response, headers) {
|
|
378
|
+
super();
|
|
379
|
+
this.name = 'UploadClientError';
|
|
380
|
+
this.message = message;
|
|
381
|
+
this.code = code;
|
|
382
|
+
this.request = request;
|
|
383
|
+
this.response = response;
|
|
384
|
+
this.headers = headers;
|
|
385
|
+
Object.setPrototypeOf(this, UploadClientError.prototype);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
383
389
|
const buildSearchParams = (query) => {
|
|
384
390
|
const searchParams = new URLSearchParams();
|
|
385
391
|
for (const [key, value] of Object.entries(query)) {
|
|
@@ -411,26 +417,6 @@ const getUrl = (base, path, query) => {
|
|
|
411
417
|
return url.toString();
|
|
412
418
|
};
|
|
413
419
|
|
|
414
|
-
/*
|
|
415
|
-
Settings for future support:
|
|
416
|
-
parallelDirectUploads: 10,
|
|
417
|
-
*/
|
|
418
|
-
const defaultSettings = {
|
|
419
|
-
baseCDN: 'https://ucarecdn.com',
|
|
420
|
-
baseURL: 'https://upload.uploadcare.com',
|
|
421
|
-
maxContentLength: 50 * 1024 * 1024,
|
|
422
|
-
retryThrottledRequestMaxTimes: 1,
|
|
423
|
-
retryNetworkErrorMaxTimes: 3,
|
|
424
|
-
multipartMinFileSize: 25 * 1024 * 1024,
|
|
425
|
-
multipartChunkSize: 5 * 1024 * 1024,
|
|
426
|
-
multipartMinLastPartSize: 1024 * 1024,
|
|
427
|
-
maxConcurrentRequests: 4,
|
|
428
|
-
pollingTimeoutMilliseconds: 10000,
|
|
429
|
-
pusherKey: '79ae88bd931ea68464d9'
|
|
430
|
-
};
|
|
431
|
-
const defaultContentType = 'application/octet-stream';
|
|
432
|
-
const defaultFilename = 'original';
|
|
433
|
-
|
|
434
420
|
var version = '6.0.0';
|
|
435
421
|
|
|
436
422
|
const LIBRARY_NAME = 'UploadcareUploadClient';
|
|
@@ -443,19 +429,6 @@ function getUserAgent(options) {
|
|
|
443
429
|
});
|
|
444
430
|
}
|
|
445
431
|
|
|
446
|
-
class UploadClientError extends Error {
|
|
447
|
-
constructor(message, code, request, response, headers) {
|
|
448
|
-
super();
|
|
449
|
-
this.name = 'UploadClientError';
|
|
450
|
-
this.message = message;
|
|
451
|
-
this.code = code;
|
|
452
|
-
this.request = request;
|
|
453
|
-
this.response = response;
|
|
454
|
-
this.headers = headers;
|
|
455
|
-
Object.setPrototypeOf(this, UploadClientError.prototype);
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
|
|
459
432
|
const REQUEST_WAS_THROTTLED_CODE = 'RequestThrottledError';
|
|
460
433
|
const DEFAULT_RETRY_AFTER_TIMEOUT = 15000;
|
|
461
434
|
const DEFAULT_NETWORK_ERROR_TIMEOUT = 1000;
|
|
@@ -486,6 +459,31 @@ function retryIfFailed(fn, options) {
|
|
|
486
459
|
}));
|
|
487
460
|
}
|
|
488
461
|
|
|
462
|
+
const getContentType = (file) => {
|
|
463
|
+
if (isBlob(file) || isFile(file) || isReactNativeAsset(file)) {
|
|
464
|
+
return file.type || defaultContentType;
|
|
465
|
+
}
|
|
466
|
+
if (isBuffer(file)) {
|
|
467
|
+
return defaultFilename;
|
|
468
|
+
}
|
|
469
|
+
console.warn(`Unknown filename: ${file}. Using default filename: ${defaultFilename}`);
|
|
470
|
+
return defaultFilename;
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
const getFilename = (file) => {
|
|
474
|
+
if (isBlob(file) || isBuffer(file)) {
|
|
475
|
+
return defaultFilename;
|
|
476
|
+
}
|
|
477
|
+
if (isFile(file)) {
|
|
478
|
+
return file.name || defaultFilename;
|
|
479
|
+
}
|
|
480
|
+
if (isReactNativeAsset(file)) {
|
|
481
|
+
return file.name || defaultFilename;
|
|
482
|
+
}
|
|
483
|
+
console.warn(`Unknown file type: ${file}. Using default filename: ${defaultFilename}`);
|
|
484
|
+
return defaultFilename;
|
|
485
|
+
};
|
|
486
|
+
|
|
489
487
|
function getStoreValue(store) {
|
|
490
488
|
return typeof store === 'undefined' ? 'auto' : store ? '1' : '0';
|
|
491
489
|
}
|
|
@@ -501,13 +499,13 @@ function base(file, { publicKey, fileName, contentType, baseURL = defaultSetting
|
|
|
501
499
|
jsonerrors: 1
|
|
502
500
|
}),
|
|
503
501
|
headers: {
|
|
504
|
-
'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
|
|
502
|
+
'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
|
|
505
503
|
},
|
|
506
504
|
data: buildFormData({
|
|
507
505
|
file: {
|
|
508
506
|
data: file,
|
|
509
|
-
name: fileName
|
|
510
|
-
contentType: contentType
|
|
507
|
+
name: fileName || getFilename(file),
|
|
508
|
+
contentType: contentType || getContentType(file)
|
|
511
509
|
},
|
|
512
510
|
UPLOADCARE_PUB_KEY: publicKey,
|
|
513
511
|
UPLOADCARE_STORE: getStoreValue(store),
|
|
@@ -705,9 +703,9 @@ function multipartStart(size, { publicKey, contentType, fileName, multipartChunk
|
|
|
705
703
|
'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
|
|
706
704
|
},
|
|
707
705
|
data: buildFormData({
|
|
708
|
-
filename: fileName
|
|
706
|
+
filename: fileName || defaultFilename,
|
|
709
707
|
size: size,
|
|
710
|
-
content_type: contentType
|
|
708
|
+
content_type: contentType || defaultContentType,
|
|
711
709
|
part_size: multipartChunkSize,
|
|
712
710
|
UPLOADCARE_STORE: getStoreValue(store),
|
|
713
711
|
UPLOADCARE_PUB_KEY: publicKey,
|
|
@@ -784,6 +782,28 @@ function multipartComplete(uuid, { publicKey, baseURL = defaultSettings.baseURL,
|
|
|
784
782
|
}), { retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes });
|
|
785
783
|
}
|
|
786
784
|
|
|
785
|
+
function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, signal, onProgress }) {
|
|
786
|
+
return poll({
|
|
787
|
+
check: (signal) => info(file, {
|
|
788
|
+
publicKey,
|
|
789
|
+
baseURL,
|
|
790
|
+
signal,
|
|
791
|
+
source,
|
|
792
|
+
integration,
|
|
793
|
+
userAgent,
|
|
794
|
+
retryThrottledRequestMaxTimes,
|
|
795
|
+
retryNetworkErrorMaxTimes
|
|
796
|
+
}).then((response) => {
|
|
797
|
+
if (response.isReady) {
|
|
798
|
+
return response;
|
|
799
|
+
}
|
|
800
|
+
onProgress && onProgress({ isComputable: true, value: 1 });
|
|
801
|
+
return false;
|
|
802
|
+
}),
|
|
803
|
+
signal
|
|
804
|
+
});
|
|
805
|
+
}
|
|
806
|
+
|
|
787
807
|
class UploadcareFile {
|
|
788
808
|
constructor(fileInfo, { baseCDN, fileName }) {
|
|
789
809
|
this.name = null;
|
|
@@ -821,28 +841,6 @@ class UploadcareFile {
|
|
|
821
841
|
}
|
|
822
842
|
}
|
|
823
843
|
|
|
824
|
-
function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, signal, onProgress }) {
|
|
825
|
-
return poll({
|
|
826
|
-
check: (signal) => info(file, {
|
|
827
|
-
publicKey,
|
|
828
|
-
baseURL,
|
|
829
|
-
signal,
|
|
830
|
-
source,
|
|
831
|
-
integration,
|
|
832
|
-
userAgent,
|
|
833
|
-
retryThrottledRequestMaxTimes,
|
|
834
|
-
retryNetworkErrorMaxTimes
|
|
835
|
-
}).then((response) => {
|
|
836
|
-
if (response.isReady) {
|
|
837
|
-
return response;
|
|
838
|
-
}
|
|
839
|
-
onProgress && onProgress({ isComputable: true, value: 1 });
|
|
840
|
-
return false;
|
|
841
|
-
}),
|
|
842
|
-
signal
|
|
843
|
-
});
|
|
844
|
-
}
|
|
845
|
-
|
|
846
844
|
const uploadDirect = (file, { publicKey, fileName, baseURL, secureSignature, secureExpire, store, contentType, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, baseCDN, metadata }) => {
|
|
847
845
|
return base(file, {
|
|
848
846
|
publicKey,
|
|
@@ -878,6 +876,29 @@ const uploadDirect = (file, { publicKey, fileName, baseURL, secureSignature, sec
|
|
|
878
876
|
.then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN }));
|
|
879
877
|
};
|
|
880
878
|
|
|
879
|
+
const uploadFromUploaded = (uuid, { publicKey, fileName, baseURL, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, baseCDN }) => {
|
|
880
|
+
return info(uuid, {
|
|
881
|
+
publicKey,
|
|
882
|
+
baseURL,
|
|
883
|
+
signal,
|
|
884
|
+
source,
|
|
885
|
+
integration,
|
|
886
|
+
userAgent,
|
|
887
|
+
retryThrottledRequestMaxTimes,
|
|
888
|
+
retryNetworkErrorMaxTimes
|
|
889
|
+
})
|
|
890
|
+
.then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN, fileName }))
|
|
891
|
+
.then((result) => {
|
|
892
|
+
// hack for node ¯\_(ツ)_/¯
|
|
893
|
+
if (onProgress)
|
|
894
|
+
onProgress({
|
|
895
|
+
isComputable: true,
|
|
896
|
+
value: 1
|
|
897
|
+
});
|
|
898
|
+
return result;
|
|
899
|
+
});
|
|
900
|
+
};
|
|
901
|
+
|
|
881
902
|
const race = (fns, { signal } = {}) => {
|
|
882
903
|
let lastError = null;
|
|
883
904
|
let winnerIndex = null;
|
|
@@ -1215,35 +1236,30 @@ const uploadFromUrl = (sourceUrl, { publicKey, fileName, baseURL, baseCDN, check
|
|
|
1215
1236
|
}))
|
|
1216
1237
|
.then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN }));
|
|
1217
1238
|
|
|
1218
|
-
const
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
retryThrottledRequestMaxTimes,
|
|
1227
|
-
retryNetworkErrorMaxTimes
|
|
1228
|
-
})
|
|
1229
|
-
.then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN, fileName }))
|
|
1230
|
-
.then((result) => {
|
|
1231
|
-
// hack for node ¯\_(ツ)_/¯
|
|
1232
|
-
if (onProgress)
|
|
1233
|
-
onProgress({
|
|
1234
|
-
isComputable: true,
|
|
1235
|
-
value: 1
|
|
1236
|
-
});
|
|
1237
|
-
return result;
|
|
1238
|
-
});
|
|
1239
|
+
const memo = new WeakMap();
|
|
1240
|
+
const getReactNativeBlob = async (asset) => {
|
|
1241
|
+
if (memo.has(asset)) {
|
|
1242
|
+
return memo.get(asset);
|
|
1243
|
+
}
|
|
1244
|
+
const blob = await fetch(asset.uri).then((res) => res.blob());
|
|
1245
|
+
memo.set(asset, blob);
|
|
1246
|
+
return blob;
|
|
1239
1247
|
};
|
|
1240
1248
|
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1249
|
+
const getFileSize = async (file) => {
|
|
1250
|
+
if (isBuffer(file)) {
|
|
1251
|
+
return file.length;
|
|
1252
|
+
}
|
|
1253
|
+
if (isFile(file) || isBlob(file)) {
|
|
1254
|
+
return file.size;
|
|
1255
|
+
}
|
|
1256
|
+
if (isReactNativeAsset(file)) {
|
|
1257
|
+
const blob = await getReactNativeBlob(file);
|
|
1258
|
+
return blob.size;
|
|
1259
|
+
}
|
|
1260
|
+
throw new Error(`Failed to get file size for file: ${file}`);
|
|
1246
1261
|
};
|
|
1262
|
+
|
|
1247
1263
|
/**
|
|
1248
1264
|
* Check if FileData is multipart data.
|
|
1249
1265
|
*/
|
|
@@ -1251,15 +1267,24 @@ const isMultipart = (fileSize, multipartMinFileSize = defaultSettings.multipartM
|
|
|
1251
1267
|
return fileSize >= multipartMinFileSize;
|
|
1252
1268
|
};
|
|
1253
1269
|
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1270
|
+
/**
|
|
1271
|
+
* Uuid type guard.
|
|
1272
|
+
*/
|
|
1273
|
+
const isUuid = (data) => {
|
|
1274
|
+
const UUID_REGEX = '[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}';
|
|
1275
|
+
const regExp = new RegExp(UUID_REGEX);
|
|
1276
|
+
return !isFileData(data) && regExp.test(data);
|
|
1277
|
+
};
|
|
1278
|
+
/**
|
|
1279
|
+
* Url type guard.
|
|
1280
|
+
*
|
|
1281
|
+
* @param {AnyFile | Url | Uuid} data
|
|
1282
|
+
*/
|
|
1283
|
+
const isUrl = (data) => {
|
|
1284
|
+
const URL_REGEX = '^(?:\\w+:)?\\/\\/([^\\s\\.]+\\.\\S{2}|localhost[\\:?\\d]*)\\S*$';
|
|
1285
|
+
const regExp = new RegExp(URL_REGEX);
|
|
1286
|
+
return !isFileData(data) && regExp.test(data);
|
|
1258
1287
|
};
|
|
1259
|
-
|
|
1260
|
-
function prepareChunks(file, fileSize, chunkSize) {
|
|
1261
|
-
return (index) => sliceChunk(file, index, fileSize, chunkSize);
|
|
1262
|
-
}
|
|
1263
1288
|
|
|
1264
1289
|
const runWithConcurrency = (concurrency, tasks) => {
|
|
1265
1290
|
return new Promise((resolve, reject) => {
|
|
@@ -1296,6 +1321,16 @@ const runWithConcurrency = (concurrency, tasks) => {
|
|
|
1296
1321
|
});
|
|
1297
1322
|
};
|
|
1298
1323
|
|
|
1324
|
+
const sliceChunk = (file, index, fileSize, chunkSize) => {
|
|
1325
|
+
const start = chunkSize * index;
|
|
1326
|
+
const end = Math.min(start + chunkSize, fileSize);
|
|
1327
|
+
return file.slice(start, end);
|
|
1328
|
+
};
|
|
1329
|
+
|
|
1330
|
+
const prepareChunks = async (file, fileSize, chunkSize) => {
|
|
1331
|
+
return (index) => sliceChunk(file, index, fileSize, chunkSize);
|
|
1332
|
+
};
|
|
1333
|
+
|
|
1299
1334
|
const uploadPart = (chunk, url, { publicKey, onProgress, signal, integration, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes }) => multipartUpload(chunk, url, {
|
|
1300
1335
|
publicKey,
|
|
1301
1336
|
onProgress,
|
|
@@ -1304,8 +1339,8 @@ const uploadPart = (chunk, url, { publicKey, onProgress, signal, integration, re
|
|
|
1304
1339
|
retryThrottledRequestMaxTimes,
|
|
1305
1340
|
retryNetworkErrorMaxTimes
|
|
1306
1341
|
});
|
|
1307
|
-
const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, contentType, multipartChunkSize = defaultSettings.multipartChunkSize, maxConcurrentRequests = defaultSettings.maxConcurrentRequests, baseCDN, metadata }) => {
|
|
1308
|
-
const size = fileSize || getFileSize(file);
|
|
1342
|
+
const uploadMultipart = async (file, { publicKey, fileName, fileSize, baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, contentType, multipartChunkSize = defaultSettings.multipartChunkSize, maxConcurrentRequests = defaultSettings.maxConcurrentRequests, baseCDN, metadata }) => {
|
|
1343
|
+
const size = fileSize || await getFileSize(file);
|
|
1309
1344
|
let progressValues;
|
|
1310
1345
|
const createProgressHandler = (totalChunks, chunkIdx) => {
|
|
1311
1346
|
if (!onProgress)
|
|
@@ -1327,8 +1362,8 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
|
|
|
1327
1362
|
};
|
|
1328
1363
|
return multipartStart(size, {
|
|
1329
1364
|
publicKey,
|
|
1330
|
-
contentType,
|
|
1331
|
-
fileName: fileName
|
|
1365
|
+
contentType: contentType || getContentType(file),
|
|
1366
|
+
fileName: fileName || getFilename(file),
|
|
1332
1367
|
baseURL,
|
|
1333
1368
|
secureSignature,
|
|
1334
1369
|
secureExpire,
|
|
@@ -1341,8 +1376,8 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
|
|
|
1341
1376
|
retryNetworkErrorMaxTimes,
|
|
1342
1377
|
metadata
|
|
1343
1378
|
})
|
|
1344
|
-
.then(({ uuid, parts }) => {
|
|
1345
|
-
const getChunk = prepareChunks(file, size, multipartChunkSize);
|
|
1379
|
+
.then(async ({ uuid, parts }) => {
|
|
1380
|
+
const getChunk = await prepareChunks(file, size, multipartChunkSize);
|
|
1346
1381
|
return Promise.all([
|
|
1347
1382
|
uuid,
|
|
1348
1383
|
runWithConcurrency(maxConcurrentRequests, parts.map((url, index) => () => uploadPart(getChunk(index), url, {
|
|
@@ -1389,14 +1424,15 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
|
|
|
1389
1424
|
/**
|
|
1390
1425
|
* Uploads file from provided data.
|
|
1391
1426
|
*/
|
|
1392
|
-
function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, contentType, multipartMinFileSize, multipartChunkSize, maxConcurrentRequests, baseCDN = defaultSettings.baseCDN, checkForUrlDuplicates, saveUrlForRecurrentUploads, pusherKey, metadata }) {
|
|
1427
|
+
async function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, contentType, multipartMinFileSize, multipartChunkSize, maxConcurrentRequests, baseCDN = defaultSettings.baseCDN, checkForUrlDuplicates, saveUrlForRecurrentUploads, pusherKey, metadata }) {
|
|
1393
1428
|
if (isFileData(data)) {
|
|
1394
|
-
const fileSize = getFileSize(data);
|
|
1429
|
+
const fileSize = await getFileSize(data);
|
|
1395
1430
|
if (isMultipart(fileSize, multipartMinFileSize)) {
|
|
1396
1431
|
return uploadMultipart(data, {
|
|
1397
1432
|
publicKey,
|
|
1398
1433
|
contentType,
|
|
1399
1434
|
multipartChunkSize,
|
|
1435
|
+
fileSize,
|
|
1400
1436
|
fileName,
|
|
1401
1437
|
baseURL,
|
|
1402
1438
|
secureSignature,
|