@uppy/xhr-upload
Advanced tools
Comparing version 3.2.0 to 3.3.0
# @uppy/xhr-upload | ||
## 3.3.0 | ||
Released: 2023-06-19 | ||
Included in: Uppy v3.10.0 | ||
- @uppy/aws-s3-multipart,@uppy/aws-s3,@uppy/tus,@uppy/utils,@uppy/xhr-upload: When file is removed (or all are canceled), controller.abort queued requests (Artur Paikin / #4504) | ||
- @uppy/aws-s3-multipart,@uppy/tus,@uppy/xhr-upload: Don't close socket while upload is still in progress (Artur Paikin / #4479) | ||
- @uppy/xhr-upload: add support for arrays in metadata (Vasiliy Matyushin / #4431) | ||
## 3.2.0 | ||
@@ -4,0 +13,0 @@ |
234
lib/index.js
function _classPrivateFieldLooseBase(receiver, privateKey) { if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { throw new TypeError("attempted to use private field on non-instance"); } return receiver; } | ||
var id = 0; | ||
function _classPrivateFieldLooseKey(name) { return "__private_" + id++ + "_" + name; } | ||
import BasePlugin from '@uppy/core/lib/BasePlugin.js'; | ||
@@ -12,3 +9,3 @@ import { nanoid } from 'nanoid/non-secure'; | ||
import getSocketHost from '@uppy/utils/lib/getSocketHost'; | ||
import EventTracker from '@uppy/utils/lib/EventTracker'; | ||
import EventManager from '@uppy/utils/lib/EventManager'; | ||
import ProgressTimeout from '@uppy/utils/lib/ProgressTimeout'; | ||
@@ -20,13 +17,12 @@ import { RateLimitedQueue, internalRateLimitedQueue } from '@uppy/utils/lib/RateLimitedQueue'; | ||
const packageJson = { | ||
"version": "3.2.0" | ||
"version": "3.3.0" | ||
}; | ||
import locale from './locale.js'; | ||
function buildResponseError(xhr, err) { | ||
let error = err; // No error message | ||
if (!error) error = new Error('Upload error'); // Got an error message string | ||
if (typeof error === 'string') error = new Error(error); // Got something else | ||
let error = err; | ||
// No error message | ||
if (!error) error = new Error('Upload error'); | ||
// Got an error message string | ||
if (typeof error === 'string') error = new Error(error); | ||
// Got something else | ||
if (!(error instanceof Error)) { | ||
@@ -37,3 +33,2 @@ error = Object.assign(new Error('Upload error'), { | ||
} | ||
if (isNetworkError(xhr)) { | ||
@@ -43,6 +38,6 @@ error = new NetworkError(error, xhr); | ||
} | ||
error.request = xhr; | ||
return error; | ||
} | ||
/** | ||
@@ -56,4 +51,2 @@ * Set `data.type` in the blob to `file.meta.type`, | ||
*/ | ||
function setTypeInBlob(file) { | ||
@@ -63,19 +56,10 @@ const dataWithUpdatedType = file.data.slice(0, file.data.size, file.meta.type); | ||
} | ||
var _queueRequestSocketToken = /*#__PURE__*/_classPrivateFieldLooseKey("queueRequestSocketToken"); | ||
var _upload = /*#__PURE__*/_classPrivateFieldLooseKey("upload"); | ||
var _requestSocketToken = /*#__PURE__*/_classPrivateFieldLooseKey("requestSocketToken"); | ||
var _uploadRemote = /*#__PURE__*/_classPrivateFieldLooseKey("uploadRemote"); | ||
var _uploadBundle = /*#__PURE__*/_classPrivateFieldLooseKey("uploadBundle"); | ||
var _uploadFiles = /*#__PURE__*/_classPrivateFieldLooseKey("uploadFiles"); | ||
var _handleUpload = /*#__PURE__*/_classPrivateFieldLooseKey("handleUpload"); | ||
export default class XHRUpload extends BasePlugin { | ||
// eslint-disable-next-line global-require | ||
constructor(uppy, _opts) { | ||
@@ -89,2 +73,4 @@ super(uppy, _opts); | ||
}); | ||
// NOTE! Keep this duplicated code in sync with other plugins | ||
// TODO we should probably abstract this into a common function | ||
Object.defineProperty(this, _uploadRemote, { | ||
@@ -102,9 +88,11 @@ value: _uploadRemote2 | ||
writable: true, | ||
value: async file => { | ||
value: async (file, options) => { | ||
const opts = this.getOptions(file); | ||
const Client = file.remote.providerOptions.provider ? Provider : RequestClient; | ||
const client = new Client(this.uppy, file.remote.providerOptions); | ||
const allowedMetaFields = Array.isArray(opts.allowedMetaFields) ? opts.allowedMetaFields // Send along all fields by default. | ||
const allowedMetaFields = Array.isArray(opts.allowedMetaFields) ? opts.allowedMetaFields | ||
// Send along all fields by default. | ||
: Object.keys(file.meta); | ||
const res = await client.post(file.remote.url, { ...file.remote.body, | ||
const res = await client.post(file.remote.url, { | ||
...file.remote.body, | ||
protocol: 'multipart', | ||
@@ -118,3 +106,3 @@ endpoint: opts.endpoint, | ||
headers: opts.headers | ||
}); | ||
}, options); | ||
return res.token; | ||
@@ -129,10 +117,9 @@ } | ||
return; | ||
} // No limit configured by the user, and no RateLimitedQueue passed in by a "parent" plugin | ||
} | ||
// No limit configured by the user, and no RateLimitedQueue passed in by a "parent" plugin | ||
// (basically just AwsS3) using the internal symbol | ||
if (this.opts.limit === 0 && !this.opts[internalRateLimitedQueue]) { | ||
this.uppy.log('[XHRUpload] When uploading multiple files at once, consider setting the `limit` option (to `10` for example), to limit the number of concurrent uploads, which helps prevent memory and network issues: https://uppy.io/docs/xhr-upload/#limit-0', 'warning'); | ||
} | ||
this.uppy.log('[XHRUpload] Uploading...'); | ||
@@ -143,15 +130,11 @@ const files = this.uppy.getFilesByIds(fileIDs); | ||
this.uppy.emit('upload-start', filesToEmit); | ||
if (this.opts.bundle) { | ||
// if bundle: true, we don’t support remote uploads | ||
const isSomeFileRemote = filesFiltered.some(file => file.isRemote); | ||
if (isSomeFileRemote) { | ||
throw new Error('Can’t upload remote files when the `bundle: true` option is set'); | ||
} | ||
if (typeof this.opts.headers === 'function') { | ||
throw new TypeError('`headers` may not be a function when the `bundle: true` option is set'); | ||
} | ||
await _classPrivateFieldLooseBase(this, _uploadBundle)[_uploadBundle](filesFiltered); | ||
@@ -166,4 +149,5 @@ } else { | ||
this.title = 'XHRUpload'; | ||
this.defaultLocale = locale; // Default options | ||
this.defaultLocale = locale; | ||
// Default options | ||
const defaultOptions = { | ||
@@ -181,3 +165,2 @@ formData: true, | ||
responseType: '', | ||
/** | ||
@@ -188,3 +171,2 @@ * @param {string} responseText the response body string | ||
let parsedResponse = {}; | ||
try { | ||
@@ -195,6 +177,4 @@ parsedResponse = JSON.parse(responseText); | ||
} | ||
return parsedResponse; | ||
}, | ||
/** | ||
@@ -207,10 +187,7 @@ * | ||
let error = new Error('Upload error'); | ||
if (isNetworkError(response)) { | ||
error = new NetworkError(error, response); | ||
} | ||
return error; | ||
}, | ||
/** | ||
@@ -224,9 +201,10 @@ * Check if the response from the upload endpoint indicates that the upload was successful. | ||
} | ||
}; | ||
this.opts = { ...defaultOptions, | ||
this.opts = { | ||
...defaultOptions, | ||
..._opts | ||
}; | ||
this.i18nInit(); // Simultaneous upload limiting is shared across all uploads with this plugin. | ||
this.i18nInit(); | ||
// Simultaneous upload limiting is shared across all uploads with this plugin. | ||
if (internalRateLimitedQueue in this.opts) { | ||
@@ -237,11 +215,8 @@ this.requests = this.opts[internalRateLimitedQueue]; | ||
} | ||
if (this.opts.bundle && !this.opts.formData) { | ||
throw new Error('`opts.formData` must be true when `opts.bundle` is enabled.'); | ||
} | ||
if ((_opts == null ? void 0 : _opts.allowedMetaFields) === undefined && 'metaFields' in this.opts) { | ||
throw new Error('The `metaFields` option has been renamed to `allowedMetaFields`.'); | ||
} | ||
this.uploaderEvents = Object.create(null); | ||
@@ -252,3 +227,2 @@ _classPrivateFieldLooseBase(this, _queueRequestSocketToken)[_queueRequestSocketToken] = this.requests.wrapPromiseFunction(_classPrivateFieldLooseBase(this, _requestSocketToken)[_requestSocketToken], { | ||
} | ||
getOptions(file) { | ||
@@ -259,7 +233,9 @@ const overrides = this.uppy.getState().xhrUpload; | ||
} = this.opts; | ||
const opts = { ...this.opts, | ||
const opts = { | ||
...this.opts, | ||
...(overrides || {}), | ||
...(file.xhrUpload || {}), | ||
headers: {} | ||
}; // Support for `headers` as a function, only in the XHRUpload settings. | ||
}; | ||
// Support for `headers` as a function, only in the XHRUpload settings. | ||
// Options set by other plugins in Uppy state or on the files themselves are still merged in afterward. | ||
@@ -270,3 +246,2 @@ // | ||
// ``` | ||
if (typeof headers === 'function') { | ||
@@ -277,15 +252,12 @@ opts.headers = headers(file); | ||
} | ||
if (overrides) { | ||
Object.assign(opts.headers, overrides.headers); | ||
} | ||
if (file.xhrUpload) { | ||
Object.assign(opts.headers, file.xhrUpload.headers); | ||
} | ||
return opts; | ||
} // eslint-disable-next-line class-methods-use-this | ||
} | ||
// eslint-disable-next-line class-methods-use-this | ||
addMetadata(formData, meta, opts) { | ||
@@ -295,6 +267,11 @@ const allowedMetaFields = Array.isArray(opts.allowedMetaFields) ? opts.allowedMetaFields : Object.keys(meta); // Send along all fields by default. | ||
allowedMetaFields.forEach(item => { | ||
formData.append(item, meta[item]); | ||
if (Array.isArray(meta[item])) { | ||
// In this case we don't transform `item` to add brackets, it's up to | ||
// the user to add the brackets so it won't be overridden. | ||
meta[item].forEach(subItem => formData.append(item, subItem)); | ||
} else { | ||
formData.append(item, meta[item]); | ||
} | ||
}); | ||
} | ||
createFormDataUpload(file, opts) { | ||
@@ -304,3 +281,2 @@ const formPost = new FormData(); | ||
const dataWithUpdatedType = setTypeInBlob(file); | ||
if (file.name) { | ||
@@ -311,6 +287,4 @@ formPost.append(opts.fieldName, dataWithUpdatedType, file.meta.name); | ||
} | ||
return formPost; | ||
} | ||
createBundledUpload(files, opts) { | ||
@@ -325,3 +299,2 @@ const formPost = new FormData(); | ||
const dataWithUpdatedType = setTypeInBlob(file); | ||
if (file.name) { | ||
@@ -335,3 +308,2 @@ formPost.append(options.fieldName, dataWithUpdatedType, file.name); | ||
} | ||
async connectToServerSocket(file) { | ||
@@ -343,3 +315,2 @@ return new Promise((resolve, reject) => { | ||
let socket; | ||
const createSocket = () => { | ||
@@ -361,5 +332,3 @@ if (socket != null) return; | ||
queuedRequest.done(); // eslint-disable-line no-use-before-define | ||
socket.close(); | ||
if (this.uploaderEvents[file.id]) { | ||
@@ -369,3 +338,2 @@ this.uploaderEvents[file.id].remove(); | ||
} | ||
return resolve(); | ||
@@ -380,3 +348,3 @@ }); | ||
queuedRequest.done(); // eslint-disable-line no-use-before-define | ||
socket.close(); | ||
if (this.uploaderEvents[file.id]) { | ||
@@ -386,12 +354,9 @@ this.uploaderEvents[file.id].remove(); | ||
} | ||
reject(error); | ||
}); | ||
}; | ||
this.uploaderEvents[file.id] = new EventTracker(this.uppy); | ||
this.uploaderEvents[file.id] = new EventManager(this.uppy); | ||
let queuedRequest = this.requests.run(() => { | ||
if (file.isPaused) { | ||
var _socket; | ||
(_socket = socket) == null ? void 0 : _socket.send('pause', {}); | ||
@@ -401,9 +366,8 @@ } else { | ||
} | ||
return () => socket.close(); | ||
return () => {}; | ||
}); | ||
this.onFileRemove(file.id, () => { | ||
var _socket2; | ||
(_socket2 = socket) == null ? void 0 : _socket2.send('cancel', {}); | ||
socket.close(); | ||
queuedRequest.abort(); | ||
@@ -416,8 +380,7 @@ resolve(`upload ${file.id} was removed`); | ||
} = _temp === void 0 ? {} : _temp; | ||
if (reason === 'user') { | ||
var _socket3; | ||
(_socket3 = socket) == null ? void 0 : _socket3.send('cancel', {}); | ||
queuedRequest.abort(); | ||
// socket.close() | ||
} | ||
@@ -427,3 +390,2 @@ | ||
}); | ||
const onRetryRequest = () => { | ||
@@ -433,19 +395,11 @@ if (socket == null) { | ||
} else { | ||
socket.send('pause', {}); | ||
queuedRequest.done(); | ||
} | ||
queuedRequest = this.requests.run(() => { | ||
if (!file.isPaused) { | ||
if (socket == null) { | ||
createSocket(); | ||
} else { | ||
socket.send('resume', {}); | ||
} | ||
if (socket == null) { | ||
createSocket(); | ||
} | ||
return () => socket.close(); | ||
return () => {}; | ||
}); | ||
}; | ||
this.onRetry(file.id, onRetryRequest); | ||
@@ -458,3 +412,2 @@ this.onRetryAll(file.id, onRetryRequest); | ||
} | ||
onFileRemove(fileID, cb) { | ||
@@ -465,3 +418,2 @@ this.uploaderEvents[fileID].on('file-removed', file => { | ||
} | ||
onRetry(fileID, cb) { | ||
@@ -474,3 +426,2 @@ this.uploaderEvents[fileID].on('upload-retry', targetFileID => { | ||
} | ||
onRetryAll(fileID, cb) { | ||
@@ -482,6 +433,4 @@ this.uploaderEvents[fileID].on('retry-all', () => { | ||
} | ||
onCancelAll(fileID, eventHandler) { | ||
var _this = this; | ||
this.uploaderEvents[fileID].on('cancel-all', function () { | ||
@@ -492,3 +441,2 @@ if (!_this.uppy.getFile(fileID)) return; | ||
} | ||
install() { | ||
@@ -500,3 +448,4 @@ if (this.opts.bundle) { | ||
this.uppy.setState({ | ||
capabilities: { ...capabilities, | ||
capabilities: { | ||
...capabilities, | ||
individualCancellation: false | ||
@@ -506,6 +455,4 @@ } | ||
} | ||
this.uppy.addUploader(_classPrivateFieldLooseBase(this, _handleUpload)[_handleUpload]); | ||
} | ||
uninstall() { | ||
@@ -517,3 +464,4 @@ if (this.opts.bundle) { | ||
this.uppy.setState({ | ||
capabilities: { ...capabilities, | ||
capabilities: { | ||
...capabilities, | ||
individualCancellation: true | ||
@@ -523,8 +471,5 @@ } | ||
} | ||
this.uppy.removeUploader(_classPrivateFieldLooseBase(this, _handleUpload)[_handleUpload]); | ||
} | ||
} | ||
async function _upload2(file, current, total) { | ||
@@ -536,3 +481,3 @@ const opts = this.getOptions(file); | ||
const xhr = new XMLHttpRequest(); | ||
this.uploaderEvents[file.id] = new EventTracker(this.uppy); | ||
this.uploaderEvents[file.id] = new EventManager(this.uppy); | ||
let queuedRequest; | ||
@@ -550,7 +495,6 @@ const timer = new ProgressTimeout(opts.timeout, () => { | ||
xhr.upload.addEventListener('progress', ev => { | ||
this.uppy.log(`[XHRUpload] ${id} progress: ${ev.loaded} / ${ev.total}`); // Begin checking for timeouts when progress starts, instead of loading, | ||
this.uppy.log(`[XHRUpload] ${id} progress: ${ev.loaded} / ${ev.total}`); | ||
// Begin checking for timeouts when progress starts, instead of loading, | ||
// to avoid timing out requests on browser concurrency queue | ||
timer.progress(); | ||
if (ev.lengthComputable) { | ||
@@ -568,3 +512,2 @@ this.uppy.emit('upload-progress', file, { | ||
queuedRequest.done(); | ||
if (this.uploaderEvents[file.id]) { | ||
@@ -574,3 +517,2 @@ this.uploaderEvents[file.id].remove(); | ||
} | ||
if (opts.validateStatus(xhr.status, xhr.responseText, xhr)) { | ||
@@ -585,10 +527,7 @@ const body = opts.getResponseData(xhr.responseText, xhr); | ||
this.uppy.emit('upload-success', file, uploadResp); | ||
if (uploadURL) { | ||
this.uppy.log(`Download ${file.name} from ${uploadURL}`); | ||
} | ||
return resolve(file); | ||
} | ||
const body = opts.getResponseData(xhr.responseText, xhr); | ||
@@ -607,3 +546,2 @@ const error = buildResponseError(xhr, opts.getResponseError(xhr.responseText, xhr)); | ||
queuedRequest.done(); | ||
if (this.uploaderEvents[file.id]) { | ||
@@ -613,3 +551,2 @@ this.uploaderEvents[file.id].remove(); | ||
} | ||
const error = buildResponseError(xhr, opts.getResponseError(xhr.responseText, xhr)); | ||
@@ -619,11 +556,9 @@ this.uppy.emit('upload-error', file, error); | ||
}); | ||
xhr.open(opts.method.toUpperCase(), opts.endpoint, true); // IE10 does not allow setting `withCredentials` and `responseType` | ||
xhr.open(opts.method.toUpperCase(), opts.endpoint, true); | ||
// IE10 does not allow setting `withCredentials` and `responseType` | ||
// before `open()` is called. | ||
xhr.withCredentials = opts.withCredentials; | ||
if (opts.responseType !== '') { | ||
xhr.responseType = opts.responseType; | ||
} | ||
queuedRequest = this.requests.run(() => { | ||
@@ -652,7 +587,5 @@ // When using an authentication system like JWT, the bearer token goes as a header. This | ||
} = _ref; | ||
if (reason === 'user') { | ||
queuedRequest.abort(); | ||
} | ||
reject(new Error('Upload cancelled')); | ||
@@ -662,4 +595,3 @@ }); | ||
} | ||
async function _uploadRemote2(file) { | ||
async function _uploadRemote2(file, options) { | ||
// TODO: we could rewrite this to use server-sent events instead of creating WebSockets. | ||
@@ -670,4 +602,3 @@ try { | ||
} | ||
const serverToken = await _classPrivateFieldLooseBase(this, _queueRequestSocketToken)[_queueRequestSocketToken](file); | ||
const serverToken = await _classPrivateFieldLooseBase(this, _queueRequestSocketToken)[_queueRequestSocketToken](file, options).abortOn(options == null ? void 0 : options.signal); | ||
if (!this.uppy.getState().files[file.id]) return undefined; | ||
@@ -679,10 +610,14 @@ this.uppy.setFileState(file.id, { | ||
} catch (err) { | ||
this.uppy.setFileState(file.id, { | ||
serverToken: undefined | ||
}); | ||
this.uppy.emit('upload-error', file, err); | ||
throw err; | ||
var _err$cause; | ||
if ((err == null ? void 0 : (_err$cause = err.cause) == null ? void 0 : _err$cause.name) !== 'AbortError') { | ||
this.uppy.setFileState(file.id, { | ||
serverToken: undefined | ||
}); | ||
this.uppy.emit('upload-error', file, err); | ||
throw err; | ||
} | ||
// The file upload was aborted, it’s not an error | ||
return undefined; | ||
} | ||
} | ||
function _uploadBundle2(files) { | ||
@@ -697,7 +632,7 @@ return new Promise((resolve, reject) => { | ||
const optsFromState = this.uppy.getState().xhrUpload; | ||
const formData = this.createBundledUpload(files, { ...this.opts, | ||
const formData = this.createBundledUpload(files, { | ||
...this.opts, | ||
...(optsFromState || {}) | ||
}); | ||
const xhr = new XMLHttpRequest(); | ||
const emitError = error => { | ||
@@ -708,3 +643,2 @@ files.forEach(file => { | ||
}; | ||
const timer = new ProgressTimeout(this.opts.timeout, () => { | ||
@@ -733,3 +667,2 @@ const error = new Error(this.i18n('uploadStalled', { | ||
timer.done(); | ||
if (this.opts.validateStatus(ev.target.status, xhr.responseText, xhr)) { | ||
@@ -746,3 +679,2 @@ const body = this.opts.getResponseData(xhr.responseText, xhr); | ||
} | ||
const error = this.opts.getResponseError(xhr.responseText, xhr) || new Error('Upload error'); | ||
@@ -767,11 +699,9 @@ error.request = xhr; | ||
}); | ||
xhr.open(method.toUpperCase(), endpoint, true); // IE10 does not allow setting `withCredentials` and `responseType` | ||
xhr.open(method.toUpperCase(), endpoint, true); | ||
// IE10 does not allow setting `withCredentials` and `responseType` | ||
// before `open()` is called. | ||
xhr.withCredentials = this.opts.withCredentials; | ||
if (this.opts.responseType !== '') { | ||
xhr.responseType = this.opts.responseType; | ||
} | ||
Object.keys(this.opts.headers).forEach(header => { | ||
@@ -783,3 +713,2 @@ xhr.setRequestHeader(header, this.opts.headers[header]); | ||
} | ||
async function _uploadFiles2(files) { | ||
@@ -789,11 +718,22 @@ await Promise.allSettled(files.map((file, i) => { | ||
const total = files.length; | ||
if (file.isRemote) { | ||
return _classPrivateFieldLooseBase(this, _uploadRemote)[_uploadRemote](file, current, total); | ||
const controller = new AbortController(); | ||
const removedHandler = removedFile => { | ||
if (removedFile.id === file.id) controller.abort(); | ||
}; | ||
this.uppy.on('file-removed', removedHandler); | ||
const uploadPromise = _classPrivateFieldLooseBase(this, _uploadRemote)[_uploadRemote](file, { | ||
signal: controller.signal | ||
}); | ||
this.requests.wrapSyncFunction(() => { | ||
this.uppy.off('file-removed', removedHandler); | ||
}, { | ||
priority: -1 | ||
})(); | ||
return uploadPromise; | ||
} | ||
return _classPrivateFieldLooseBase(this, _upload)[_upload](file, current, total); | ||
})); | ||
} | ||
// eslint-disable-next-line global-require | ||
XHRUpload.VERSION = packageJson.version; |
{ | ||
"name": "@uppy/xhr-upload", | ||
"description": "Plain and simple classic HTML multipart form uploads with Uppy, as well as uploads using the HTTP PUT method.", | ||
"version": "3.2.0", | ||
"version": "3.3.0", | ||
"license": "MIT", | ||
@@ -29,3 +29,3 @@ "main": "lib/index.js", | ||
"@uppy/companion-client": "^3.1.3", | ||
"@uppy/utils": "^5.3.0", | ||
"@uppy/utils": "^5.4.0", | ||
"nanoid": "^4.0.0" | ||
@@ -38,4 +38,4 @@ }, | ||
"peerDependencies": { | ||
"@uppy/core": "^3.2.0" | ||
"@uppy/core": "^3.2.1" | ||
} | ||
} |
@@ -6,3 +6,3 @@ import BasePlugin from '@uppy/core/lib/BasePlugin.js' | ||
import getSocketHost from '@uppy/utils/lib/getSocketHost' | ||
import EventTracker from '@uppy/utils/lib/EventTracker' | ||
import EventManager from '@uppy/utils/lib/EventManager' | ||
import ProgressTimeout from '@uppy/utils/lib/ProgressTimeout' | ||
@@ -175,3 +175,9 @@ import { RateLimitedQueue, internalRateLimitedQueue } from '@uppy/utils/lib/RateLimitedQueue' | ||
allowedMetaFields.forEach((item) => { | ||
formData.append(item, meta[item]) | ||
if (Array.isArray(meta[item])) { | ||
// In this case we don't transform `item` to add brackets, it's up to | ||
// the user to add the brackets so it won't be overridden. | ||
meta[item].forEach(subItem => formData.append(item, subItem)) | ||
} else { | ||
formData.append(item, meta[item]) | ||
} | ||
}) | ||
@@ -227,3 +233,3 @@ } | ||
const xhr = new XMLHttpRequest() | ||
this.uploaderEvents[file.id] = new EventTracker(this.uppy) | ||
this.uploaderEvents[file.id] = new EventManager(this.uppy) | ||
let queuedRequest | ||
@@ -351,3 +357,3 @@ | ||
#requestSocketToken = async (file) => { | ||
#requestSocketToken = async (file, options) => { | ||
const opts = this.getOptions(file) | ||
@@ -370,3 +376,3 @@ const Client = file.remote.providerOptions.provider ? Provider : RequestClient | ||
headers: opts.headers, | ||
}) | ||
}, options) | ||
return res.token | ||
@@ -377,3 +383,3 @@ } | ||
// TODO we should probably abstract this into a common function | ||
async #uploadRemote (file) { | ||
async #uploadRemote (file, options) { | ||
// TODO: we could rewrite this to use server-sent events instead of creating WebSockets. | ||
@@ -384,3 +390,3 @@ try { | ||
} | ||
const serverToken = await this.#queueRequestSocketToken(file) | ||
const serverToken = await this.#queueRequestSocketToken(file, options).abortOn(options?.signal) | ||
@@ -392,5 +398,9 @@ if (!this.uppy.getState().files[file.id]) return undefined | ||
} catch (err) { | ||
this.uppy.setFileState(file.id, { serverToken: undefined }) | ||
this.uppy.emit('upload-error', file, err) | ||
throw err | ||
if (err?.cause?.name !== 'AbortError') { | ||
this.uppy.setFileState(file.id, { serverToken: undefined }) | ||
this.uppy.emit('upload-error', file, err) | ||
throw err | ||
} | ||
// The file upload was aborted, it’s not an error | ||
return undefined | ||
} | ||
@@ -440,2 +450,3 @@ } | ||
queuedRequest.done() // eslint-disable-line no-use-before-define | ||
socket.close() | ||
if (this.uploaderEvents[file.id]) { | ||
@@ -448,3 +459,3 @@ this.uploaderEvents[file.id].remove() | ||
} | ||
this.uploaderEvents[file.id] = new EventTracker(this.uppy) | ||
this.uploaderEvents[file.id] = new EventManager(this.uppy) | ||
@@ -458,3 +469,3 @@ let queuedRequest = this.requests.run(() => { | ||
return () => socket.close() | ||
return () => {} | ||
}) | ||
@@ -464,2 +475,3 @@ | ||
socket?.send('cancel', {}) | ||
socket.close() | ||
queuedRequest.abort() | ||
@@ -473,2 +485,3 @@ resolve(`upload ${file.id} was removed`) | ||
queuedRequest.abort() | ||
// socket.close() | ||
} | ||
@@ -482,15 +495,9 @@ resolve(`upload ${file.id} was canceled`) | ||
} else { | ||
socket.send('pause', {}) | ||
queuedRequest.done() | ||
} | ||
queuedRequest = this.requests.run(() => { | ||
if (!file.isPaused) { | ||
if (socket == null) { | ||
createSocket() | ||
} else { | ||
socket.send('resume', {}) | ||
} | ||
if (socket == null) { | ||
createSocket() | ||
} | ||
return () => socket.close() | ||
return () => {} | ||
}) | ||
@@ -606,3 +613,16 @@ } | ||
if (file.isRemote) { | ||
return this.#uploadRemote(file, current, total) | ||
const controller = new AbortController() | ||
const removedHandler = (removedFile) => { | ||
if (removedFile.id === file.id) controller.abort() | ||
} | ||
this.uppy.on('file-removed', removedHandler) | ||
const uploadPromise = this.#uploadRemote(file, { signal: controller.signal }) | ||
this.requests.wrapSyncFunction(() => { | ||
this.uppy.off('file-removed', removedHandler) | ||
}, { priority: -1 })() | ||
return uploadPromise | ||
} | ||
@@ -609,0 +629,0 @@ return this.#upload(file, current, total) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
109228
1421
Updated@uppy/utils@^5.4.0