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