Socket
Socket
Sign inDemoInstall

@uppy/tus

Package Overview
Dependencies
Maintainers
5
Versions
115
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@uppy/tus - npm Package Compare versions

Comparing version 1.4.0 to 1.4.1

lib/getFingerprint.js

375

lib/index.js

@@ -25,6 +25,23 @@ var _class, _temp;

var limitPromises = require('@uppy/utils/lib/limitPromises'); // Extracted from https://github.com/tus/tus-js-client/blob/master/lib/upload.js#L13
// excepted we removed 'fingerprint' key to avoid adding more dependencies
var EventTracker = require('@uppy/utils/lib/EventTracker');
var RateLimitedQueue = require('@uppy/utils/lib/RateLimitedQueue');
var getFingerprint = require('./getFingerprint');
/** @typedef {import('..').TusOptions} TusOptions */
/** @typedef {import('@uppy/core').Uppy} Uppy */
/** @typedef {import('@uppy/core').UppyFile} UppyFile */
/** @typedef {import('@uppy/core').FailedUppyFile<{}>} FailedUppyFile */
/**
* Extracted from https://github.com/tus/tus-js-client/blob/master/lib/upload.js#L13
* excepted we removed 'fingerprint' key to avoid adding more dependencies
*
* @type {TusOptions}
*/
var tusDefaultOptions = {

@@ -45,30 +62,6 @@ endpoint: '',

/**
* Create a wrapper around an event emitter with a `remove` method to remove
* all events that were added using the wrapped emitter.
* Tus resumable file uploader
*/
};
function createEventTracker(emitter) {
var events = [];
return {
on: function on(event, fn) {
events.push([event, fn]);
return emitter.on(event, fn);
},
remove: function remove() {
events.forEach(function (_ref) {
var event = _ref[0],
fn = _ref[1];
emitter.off(event, fn);
});
}
};
}
/**
* Tus resumable file uploader
*
*/
module.exports = (_temp = _class =

@@ -79,2 +72,6 @@ /*#__PURE__*/

/**
* @param {Uppy} uppy
* @param {TusOptions} opts
*/
function Tus(uppy, opts) {

@@ -95,13 +92,13 @@ var _this;

/** @type {import("..").TusOptions} */
};
_this.opts = _extends({}, defaultOptions, opts); // Simultaneous upload limiting is shared across all uploads with this plugin.
_this.opts = _extends({}, defaultOptions, opts);
/**
* Simultaneous upload limiting is shared across all uploads with this plugin.
*
* @type {RateLimitedQueue}
*/
if (typeof _this.opts.limit === 'number' && _this.opts.limit !== 0) {
_this.limitUploads = limitPromises(_this.opts.limit);
} else {
_this.limitUploads = function (fn) {
return fn;
};
}
_this.requests = new RateLimitedQueue(_this.opts.limit);
_this.uploaders = Object.create(null);

@@ -138,2 +135,4 @@ _this.uploaderEvents = Object.create(null);

* any events related to the file, and the Companion WebSocket connection.
*
* @param {string} fileID
*/

@@ -159,8 +158,31 @@ ;

/**
* Create a new Tus upload
* Create a new Tus upload.
*
* @param {object} file for use with upload
* @param {integer} current file in a queue
* @param {integer} total number of files in a queue
* @returns {Promise}
* A lot can happen during an upload, so this is quite hard to follow!
* - First, the upload is started. If the file was already paused by the time the upload starts, nothing should happen.
* If the `limit` option is used, the upload must be queued onto the `this.requests` queue.
* When an upload starts, we store the tus.Upload instance, and an EventTracker instance that manages the event listeners
* for pausing, cancellation, removal, etc.
* - While the upload is in progress, it may be paused or cancelled.
* Pausing aborts the underlying tus.Upload, and removes the upload from the `this.requests` queue. All other state is
* maintained.
* Cancelling removes the upload from the `this.requests` queue, and completely aborts the upload--the tus.Upload instance
* is aborted and discarded, the EventTracker instance is destroyed (removing all listeners).
* Resuming the upload uses the `this.requests` queue as well, to prevent selectively pausing and resuming uploads from
* bypassing the limit.
* - After completing an upload, the tus.Upload and EventTracker instances are cleaned up, and the upload is marked as done
* in the `this.requests` queue.
* - When an upload completed with an error, the same happens as on successful completion, but the `upload()` promise is rejected.
*
* When working on this function, keep in mind:
* - When an upload is completed or cancelled for any reason, the tus.Upload and EventTracker instances need to be cleaned up using this.resetUploaderReferences().
* - When an upload is cancelled or paused, for any reason, it needs to be removed from the `this.requests` queue using `queuedRequest.abort()`.
* - When an upload is completed for any reason, including errors, it needs to be marked as such using `queuedRequest.done()`.
* - When an upload is started or resumed, it needs to go through the `this.requests` queue. The `queuedRequest` variable must be updated so the other uses of it are valid.
* - Before replacing the `queuedRequest` variable, the previous `queuedRequest` must be aborted, else it will keep taking up a spot in the queue.
*
* @param {UppyFile} file for use with upload
* @param {number} current file in a queue
* @param {number} total number of files in a queue
* @returns {Promise<void>}
*/

@@ -175,5 +197,13 @@ ;

return new Promise(function (resolve, reject) {
_this2.uppy.emit('upload-started', file);
var optsTus = _extends({}, tusDefaultOptions, _this2.opts, // Install file-specific upload overrides.
file.tus || {});
file.tus || {}); // We override tus fingerprint to uppy’s `file.id`, since the `file.id`
// now also includes `relativePath` for files added from folders.
// This means you can add 2 identical files, if one is in folder a,
// the other in folder b.
optsTus.fingerprint = getFingerprint(file);
optsTus.onError = function (err) {

@@ -188,2 +218,3 @@ _this2.uppy.log(err);

queuedRequest.done();
reject(err);

@@ -215,2 +246,3 @@ };

queuedRequest.done();
resolve(upload);

@@ -237,5 +269,21 @@ };

_this2.uploaders[file.id] = upload;
_this2.uploaderEvents[file.id] = createEventTracker(_this2.uppy);
_this2.uploaderEvents[file.id] = new EventTracker(_this2.uppy);
var queuedRequest = _this2.requests.run(function () {
if (!file.isPaused) {
upload.start();
} // Don't do anything here, the caller will take care of cancelling the upload itself
// using resetUploaderReferences(). This is because resetUploaderReferences() has to be
// called when this request is still in the queue, and has not been started yet, too. At
// that point this cancellation function is not going to be called.
// Also, we need to remove the request from the queue _without_ destroying everything
// related to this upload to handle pauses.
return function () {};
});
_this2.onFileRemove(file.id, function (targetFileID) {
queuedRequest.abort();
_this2.resetUploaderReferences(file.id);

@@ -248,5 +296,12 @@

if (isPaused) {
// Remove this file from the queue so another file can start in its place.
queuedRequest.abort();
upload.abort();
} else {
upload.start();
// Resuming an upload should be queued, else you could pause and then resume a queued upload to make it skip the queue.
queuedRequest.abort();
queuedRequest = _this2.requests.run(function () {
upload.start();
return function () {};
});
}

@@ -256,2 +311,3 @@ });

_this2.onPauseAll(file.id, function () {
queuedRequest.abort();
upload.abort();

@@ -261,2 +317,4 @@ });

_this2.onCancelAll(file.id, function () {
queuedRequest.abort();
_this2.resetUploaderReferences(file.id);

@@ -268,2 +326,4 @@

_this2.onResumeAll(file.id, function () {
queuedRequest.abort();
if (file.error) {

@@ -273,10 +333,20 @@ upload.abort();

upload.start();
queuedRequest = _this2.requests.run(function () {
upload.start();
return function () {};
});
});
}).catch(function (err) {
_this2.uppy.emit('upload-error', file, err);
if (!file.isPaused) {
upload.start();
}
throw err;
});
};
}
/**
* @param {UppyFile} file for use with upload
* @param {number} current file in a queue
* @param {number} total number of files in a queue
* @returns {Promise<void>}
*/
;

@@ -288,18 +358,20 @@ _proto.uploadRemote = function uploadRemote(file, current, total) {

var opts = _extends({}, this.opts, // Install file-specific upload overrides.
file.tus || {});
var opts = _extends({}, this.opts);
return new Promise(function (resolve, reject) {
_this3.uppy.log(file.remote.url);
if (file.tus) {
// Install file-specific upload overrides.
_extends(opts, file.tus);
}
if (file.serverToken) {
return _this3.connectToServerSocket(file).then(function () {
return resolve();
}).catch(reject);
}
this.uppy.emit('upload-started', file);
this.uppy.log(file.remote.url);
_this3.uppy.emit('upload-started', file);
if (file.serverToken) {
return this.connectToServerSocket(file);
}
return new Promise(function (resolve, reject) {
var Client = file.remote.providerOptions.provider ? Provider : RequestClient;
var client = new Client(_this3.uppy, file.remote.providerOptions);
var client = new Client(_this3.uppy, file.remote.providerOptions); // !! cancellation is NOT supported at this stage yet
client.post(file.remote.url, _extends({}, file.remote.body, {

@@ -317,4 +389,2 @@ endpoint: opts.endpoint,

file = _this3.uppy.getFile(file.id);
return file;
}).then(function (file) {
return _this3.connectToServerSocket(file);

@@ -327,3 +397,11 @@ }).then(function () {

});
};
}
/**
* See the comment on the upload() method.
*
* Additionally, when an upload is removed, completed, or cancelled, we need to close the WebSocket connection. This is handled by the resetUploaderReferences() function, so the same guidelines apply as in upload().
*
* @param {UppyFile} file
*/
;

@@ -337,9 +415,14 @@ _proto.connectToServerSocket = function connectToServerSocket(file) {

var socket = new Socket({
target: host + "/api/" + token
target: host + "/api/" + token,
autoOpen: false
});
_this4.uploaderSockets[file.id] = socket;
_this4.uploaderEvents[file.id] = createEventTracker(_this4.uppy);
_this4.uploaderEvents[file.id] = new EventTracker(_this4.uppy);
_this4.onFileRemove(file.id, function () {
queuedRequest.abort();
socket.send('pause', {});
_this4.resetUploaderReferences(file.id);
resolve("upload " + file.id + " was removed");

@@ -349,14 +432,33 @@ });

_this4.onPause(file.id, function (isPaused) {
isPaused ? socket.send('pause', {}) : socket.send('resume', {});
if (isPaused) {
// Remove this file from the queue so another file can start in its place.
queuedRequest.abort();
socket.send('pause', {});
} else {
// Resuming an upload should be queued, else you could pause and then resume a queued upload to make it skip the queue.
queuedRequest.abort();
queuedRequest = _this4.requests.run(function () {
socket.send('resume', {});
return function () {};
});
}
});
_this4.onPauseAll(file.id, function () {
return socket.send('pause', {});
queuedRequest.abort();
socket.send('pause', {});
});
_this4.onCancelAll(file.id, function () {
return socket.send('pause', {});
queuedRequest.abort();
socket.send('pause', {});
_this4.resetUploaderReferences(file.id);
resolve("upload " + file.id + " was canceled");
});
_this4.onResumeAll(file.id, function () {
queuedRequest.abort();
if (file.error) {

@@ -366,19 +468,27 @@ socket.send('pause', {});

socket.send('resume', {});
queuedRequest = _this4.requests.run(function () {
socket.send('resume', {});
return function () {};
});
});
_this4.onRetry(file.id, function () {
socket.send('pause', {});
socket.send('resume', {});
// Only do the retry if the upload is actually in progress;
// else we could try to send these messages when the upload is still queued.
// We may need a better check for this since the socket may also be closed
// for other reasons, like network failures.
if (socket.isOpen) {
socket.send('pause', {});
socket.send('resume', {});
}
});
_this4.onRetryAll(file.id, function () {
socket.send('pause', {});
socket.send('resume', {});
// See the comment in the onRetry() call
if (socket.isOpen) {
socket.send('pause', {});
socket.send('resume', {});
}
});
if (file.isPaused) {
socket.send('pause', {});
}
socket.on('progress', function (progressData) {

@@ -403,2 +513,4 @@ return emitSocketProgress(_this4, progressData, file);

});
} else {
socket.close();
}

@@ -408,2 +520,3 @@

queuedRequest.done();
reject(error);

@@ -420,4 +533,21 @@ });

queuedRequest.done();
resolve();
});
var queuedRequest = _this4.requests.run(function () {
socket.open();
if (file.isPaused) {
socket.send('pause', {});
} // Don't do anything here, the caller will take care of cancelling the upload itself
// using resetUploaderReferences(). This is because resetUploaderReferences() has to be
// called when this request is still in the queue, and has not been started yet, too. At
// that point this cancellation function is not going to be called.
// Also, we need to remove the request from the queue _without_ destroying everything
// related to this upload to handle pauses.
return function () {};
});
});

@@ -428,2 +558,5 @@ }

* restores state, we will continue uploading to the correct URL.
*
* @param {UppyFile} file
* @param {string} uploadURL
*/

@@ -444,3 +577,8 @@ ;

}
};
}
/**
* @param {string} fileID
* @param {function(string): void} cb
*/
;

@@ -451,3 +589,8 @@ _proto.onFileRemove = function onFileRemove(fileID, cb) {

});
};
}
/**
* @param {string} fileID
* @param {function(boolean): void} cb
*/
;

@@ -461,3 +604,8 @@ _proto.onPause = function onPause(fileID, cb) {

});
};
}
/**
* @param {string} fileID
* @param {function(): void} cb
*/
;

@@ -470,3 +618,8 @@ _proto.onRetry = function onRetry(fileID, cb) {

});
};
}
/**
* @param {string} fileID
* @param {function(): void} cb
*/
;

@@ -480,3 +633,8 @@ _proto.onRetryAll = function onRetryAll(fileID, cb) {

});
};
}
/**
* @param {string} fileID
* @param {function(): void} cb
*/
;

@@ -490,3 +648,8 @@ _proto.onPauseAll = function onPauseAll(fileID, cb) {

});
};
}
/**
* @param {string} fileID
* @param {function(): void} cb
*/
;

@@ -500,3 +663,8 @@ _proto.onCancelAll = function onCancelAll(fileID, cb) {

});
};
}
/**
* @param {string} fileID
* @param {function(): void} cb
*/
;

@@ -510,3 +678,7 @@ _proto.onResumeAll = function onResumeAll(fileID, cb) {

});
};
}
/**
* @param {(UppyFile | FailedUppyFile)[]} files
*/
;

@@ -516,29 +688,20 @@ _proto.uploadFiles = function uploadFiles(files) {

var actions = files.map(function (file, i) {
var current = parseInt(i, 10) + 1;
var promises = files.map(function (file, i) {
var current = i + 1;
var total = files.length;
if (file.error) {
return function () {
return Promise.reject(new Error(file.error));
};
if ('error' in file && file.error) {
return Promise.reject(new Error(file.error));
} else if (file.isRemote) {
// We emit upload-started here, so that it's also emitted for files
// that have to wait due to the `limit` option.
_this9.uppy.emit('upload-started', file);
return _this9.uploadRemote.bind(_this9, file, current, total);
return _this9.uploadRemote(file, current, total);
} else {
_this9.uppy.emit('upload-started', file);
return _this9.upload.bind(_this9, file, current, total);
return _this9.upload(file, current, total);
}
});
var promises = actions.map(function (action) {
var limitedAction = _this9.limitUploads(action);
return limitedAction();
});
return settle(promises);
};
}
/**
* @param {string[]} fileIDs
*/
;

@@ -594,2 +757,2 @@ _proto.handleUpload = function handleUpload(fileIDs) {

return Tus;
}(Plugin), _class.VERSION = "1.4.0", _temp);
}(Plugin), _class.VERSION = "1.4.1", _temp);
{
"name": "@uppy/tus",
"description": "Resumable uploads for Uppy using Tus.io",
"version": "1.4.0",
"version": "1.4.1",
"license": "MIT",

@@ -25,5 +25,5 @@ "main": "lib/index.js",

"dependencies": {
"@uppy/companion-client": "^1.3.0",
"@uppy/utils": "^1.3.0",
"tus-js-client": "^1.8.0-0"
"@uppy/companion-client": "^1.4.0",
"@uppy/utils": "^2.0.0",
"tus-js-client": "^1.8.0-2"
},

@@ -33,3 +33,3 @@ "peerDependencies": {

},
"gitHead": "056a7114a15fc7480a4014342d7f2c19305dc96c"
"gitHead": "4e32e61d7c7821ca5d8641a3df741487ea27f0bb"
}

@@ -7,6 +7,17 @@ const { Plugin } = require('@uppy/core')

const settle = require('@uppy/utils/lib/settle')
const limitPromises = require('@uppy/utils/lib/limitPromises')
const EventTracker = require('@uppy/utils/lib/EventTracker')
const RateLimitedQueue = require('@uppy/utils/lib/RateLimitedQueue')
const getFingerprint = require('./getFingerprint')
// Extracted from https://github.com/tus/tus-js-client/blob/master/lib/upload.js#L13
// excepted we removed 'fingerprint' key to avoid adding more dependencies
/** @typedef {import('..').TusOptions} TusOptions */
/** @typedef {import('@uppy/core').Uppy} Uppy */
/** @typedef {import('@uppy/core').UppyFile} UppyFile */
/** @typedef {import('@uppy/core').FailedUppyFile<{}>} FailedUppyFile */
/**
* Extracted from https://github.com/tus/tus-js-client/blob/master/lib/upload.js#L13
* excepted we removed 'fingerprint' key to avoid adding more dependencies
*
* @type {TusOptions}
*/
const tusDefaultOptions = {

@@ -29,23 +40,3 @@ endpoint: '',

/**
* Create a wrapper around an event emitter with a `remove` method to remove
* all events that were added using the wrapped emitter.
*/
function createEventTracker (emitter) {
const events = []
return {
on (event, fn) {
events.push([event, fn])
return emitter.on(event, fn)
},
remove () {
events.forEach(([event, fn]) => {
emitter.off(event, fn)
})
}
}
}
/**
* Tus resumable file uploader
*
*/

@@ -55,2 +46,6 @@ module.exports = class Tus extends Plugin {

/**
* @param {Uppy} uppy
* @param {TusOptions} opts
*/
constructor (uppy, opts) {

@@ -72,10 +67,11 @@ super(uppy, opts)

// merge default options with the ones set by user
/** @type {import("..").TusOptions} */
this.opts = Object.assign({}, defaultOptions, opts)
// Simultaneous upload limiting is shared across all uploads with this plugin.
if (typeof this.opts.limit === 'number' && this.opts.limit !== 0) {
this.limitUploads = limitPromises(this.opts.limit)
} else {
this.limitUploads = (fn) => fn
}
/**
* Simultaneous upload limiting is shared across all uploads with this plugin.
*
* @type {RateLimitedQueue}
*/
this.requests = new RateLimitedQueue(this.opts.limit)

@@ -107,2 +103,4 @@ this.uploaders = Object.create(null)

* any events related to the file, and the Companion WebSocket connection.
*
* @param {string} fileID
*/

@@ -125,8 +123,31 @@ resetUploaderReferences (fileID) {

/**
* Create a new Tus upload
* Create a new Tus upload.
*
* @param {object} file for use with upload
* @param {integer} current file in a queue
* @param {integer} total number of files in a queue
* @returns {Promise}
* A lot can happen during an upload, so this is quite hard to follow!
* - First, the upload is started. If the file was already paused by the time the upload starts, nothing should happen.
* If the `limit` option is used, the upload must be queued onto the `this.requests` queue.
* When an upload starts, we store the tus.Upload instance, and an EventTracker instance that manages the event listeners
* for pausing, cancellation, removal, etc.
* - While the upload is in progress, it may be paused or cancelled.
* Pausing aborts the underlying tus.Upload, and removes the upload from the `this.requests` queue. All other state is
* maintained.
* Cancelling removes the upload from the `this.requests` queue, and completely aborts the upload--the tus.Upload instance
* is aborted and discarded, the EventTracker instance is destroyed (removing all listeners).
* Resuming the upload uses the `this.requests` queue as well, to prevent selectively pausing and resuming uploads from
* bypassing the limit.
* - After completing an upload, the tus.Upload and EventTracker instances are cleaned up, and the upload is marked as done
* in the `this.requests` queue.
* - When an upload completed with an error, the same happens as on successful completion, but the `upload()` promise is rejected.
*
* When working on this function, keep in mind:
* - When an upload is completed or cancelled for any reason, the tus.Upload and EventTracker instances need to be cleaned up using this.resetUploaderReferences().
* - When an upload is cancelled or paused, for any reason, it needs to be removed from the `this.requests` queue using `queuedRequest.abort()`.
* - When an upload is completed for any reason, including errors, it needs to be marked as such using `queuedRequest.done()`.
* - When an upload is started or resumed, it needs to go through the `this.requests` queue. The `queuedRequest` variable must be updated so the other uses of it are valid.
* - Before replacing the `queuedRequest` variable, the previous `queuedRequest` must be aborted, else it will keep taking up a spot in the queue.
*
* @param {UppyFile} file for use with upload
* @param {number} current file in a queue
* @param {number} total number of files in a queue
* @returns {Promise<void>}
*/

@@ -138,2 +159,4 @@ upload (file, current, total) {

return new Promise((resolve, reject) => {
this.uppy.emit('upload-started', file)
const optsTus = Object.assign(

@@ -147,2 +170,8 @@ {},

// We override tus fingerprint to uppy’s `file.id`, since the `file.id`
// now also includes `relativePath` for files added from folders.
// This means you can add 2 identical files, if one is in folder a,
// the other in folder b.
optsTus.fingerprint = getFingerprint(file)
optsTus.onError = (err) => {

@@ -154,2 +183,3 @@ this.uppy.log(err)

this.resetUploaderReferences(file.id)
queuedRequest.done()
reject(err)

@@ -179,2 +209,3 @@ }

this.resetUploaderReferences(file.id)
queuedRequest.done()
resolve(upload)

@@ -209,5 +240,19 @@ }

this.uploaders[file.id] = upload
this.uploaderEvents[file.id] = createEventTracker(this.uppy)
this.uploaderEvents[file.id] = new EventTracker(this.uppy)
let queuedRequest = this.requests.run(() => {
if (!file.isPaused) {
upload.start()
}
// Don't do anything here, the caller will take care of cancelling the upload itself
// using resetUploaderReferences(). This is because resetUploaderReferences() has to be
// called when this request is still in the queue, and has not been started yet, too. At
// that point this cancellation function is not going to be called.
// Also, we need to remove the request from the queue _without_ destroying everything
// related to this upload to handle pauses.
return () => {}
})
this.onFileRemove(file.id, (targetFileID) => {
queuedRequest.abort()
this.resetUploaderReferences(file.id)

@@ -219,5 +264,12 @@ resolve(`upload ${targetFileID} was removed`)

if (isPaused) {
// Remove this file from the queue so another file can start in its place.
queuedRequest.abort()
upload.abort()
} else {
upload.start()
// Resuming an upload should be queued, else you could pause and then resume a queued upload to make it skip the queue.
queuedRequest.abort()
queuedRequest = this.requests.run(() => {
upload.start()
return () => {}
})
}

@@ -227,2 +279,3 @@ })

this.onPauseAll(file.id, () => {
queuedRequest.abort()
upload.abort()

@@ -232,2 +285,3 @@ })

this.onCancelAll(file.id, () => {
queuedRequest.abort()
this.resetUploaderReferences(file.id)

@@ -238,49 +292,54 @@ resolve(`upload ${file.id} was canceled`)

this.onResumeAll(file.id, () => {
queuedRequest.abort()
if (file.error) {
upload.abort()
}
upload.start()
queuedRequest = this.requests.run(() => {
upload.start()
return () => {}
})
})
if (!file.isPaused) {
upload.start()
}
}).catch((err) => {
this.uppy.emit('upload-error', file, err)
throw err
})
}
/**
* @param {UppyFile} file for use with upload
* @param {number} current file in a queue
* @param {number} total number of files in a queue
* @returns {Promise<void>}
*/
uploadRemote (file, current, total) {
this.resetUploaderReferences(file.id)
const opts = Object.assign(
{},
this.opts,
const opts = { ...this.opts }
if (file.tus) {
// Install file-specific upload overrides.
file.tus || {}
)
Object.assign(opts, file.tus)
}
this.uppy.emit('upload-started', file)
this.uppy.log(file.remote.url)
if (file.serverToken) {
return this.connectToServerSocket(file)
}
return new Promise((resolve, reject) => {
this.uppy.log(file.remote.url)
if (file.serverToken) {
return this.connectToServerSocket(file)
.then(() => resolve())
.catch(reject)
}
this.uppy.emit('upload-started', file)
const Client = file.remote.providerOptions.provider ? Provider : RequestClient
const client = new Client(this.uppy, file.remote.providerOptions)
client.post(
file.remote.url,
Object.assign({}, file.remote.body, {
endpoint: opts.endpoint,
uploadUrl: opts.uploadUrl,
protocol: 'tus',
size: file.data.size,
metadata: file.meta
})
).then((res) => {
// !! cancellation is NOT supported at this stage yet
client.post(file.remote.url, {
...file.remote.body,
endpoint: opts.endpoint,
uploadUrl: opts.uploadUrl,
protocol: 'tus',
size: file.data.size,
metadata: file.meta
}).then((res) => {
this.uppy.setFileState(file.id, { serverToken: res.token })
file = this.uppy.getFile(file.id)
return file
}).then((file) => {
return this.connectToServerSocket(file)

@@ -295,2 +354,9 @@ }).then(() => {

/**
* See the comment on the upload() method.
*
* Additionally, when an upload is removed, completed, or cancelled, we need to close the WebSocket connection. This is handled by the resetUploaderReferences() function, so the same guidelines apply as in upload().
*
* @param {UppyFile} file
*/
connectToServerSocket (file) {

@@ -300,8 +366,10 @@ return new Promise((resolve, reject) => {

const host = getSocketHost(file.remote.companionUrl)
const socket = new Socket({ target: `${host}/api/${token}` })
const socket = new Socket({ target: `${host}/api/${token}`, autoOpen: false })
this.uploaderSockets[file.id] = socket
this.uploaderEvents[file.id] = createEventTracker(this.uppy)
this.uploaderEvents[file.id] = new EventTracker(this.uppy)
this.onFileRemove(file.id, () => {
queuedRequest.abort()
socket.send('pause', {})
this.resetUploaderReferences(file.id)
resolve(`upload ${file.id} was removed`)

@@ -311,30 +379,58 @@ })

this.onPause(file.id, (isPaused) => {
isPaused ? socket.send('pause', {}) : socket.send('resume', {})
if (isPaused) {
// Remove this file from the queue so another file can start in its place.
queuedRequest.abort()
socket.send('pause', {})
} else {
// Resuming an upload should be queued, else you could pause and then resume a queued upload to make it skip the queue.
queuedRequest.abort()
queuedRequest = this.requests.run(() => {
socket.send('resume', {})
return () => {}
})
}
})
this.onPauseAll(file.id, () => socket.send('pause', {}))
this.onPauseAll(file.id, () => {
queuedRequest.abort()
socket.send('pause', {})
})
this.onCancelAll(file.id, () => socket.send('pause', {}))
this.onCancelAll(file.id, () => {
queuedRequest.abort()
socket.send('pause', {})
this.resetUploaderReferences(file.id)
resolve(`upload ${file.id} was canceled`)
})
this.onResumeAll(file.id, () => {
queuedRequest.abort()
if (file.error) {
socket.send('pause', {})
}
socket.send('resume', {})
queuedRequest = this.requests.run(() => {
socket.send('resume', {})
return () => {}
})
})
this.onRetry(file.id, () => {
socket.send('pause', {})
socket.send('resume', {})
// Only do the retry if the upload is actually in progress;
// else we could try to send these messages when the upload is still queued.
// We may need a better check for this since the socket may also be closed
// for other reasons, like network failures.
if (socket.isOpen) {
socket.send('pause', {})
socket.send('resume', {})
}
})
this.onRetryAll(file.id, () => {
socket.send('pause', {})
socket.send('resume', {})
// See the comment in the onRetry() call
if (socket.isOpen) {
socket.send('pause', {})
socket.send('resume', {})
}
})
if (file.isPaused) {
socket.send('pause', {})
}
socket.on('progress', (progressData) => emitSocketProgress(this, progressData, file))

@@ -354,5 +450,8 @@

})
} else {
socket.close()
}
this.uppy.emit('upload-error', file, error)
queuedRequest.done()
reject(error)

@@ -368,4 +467,20 @@ })

this.resetUploaderReferences(file.id)
queuedRequest.done()
resolve()
})
let queuedRequest = this.requests.run(() => {
socket.open()
if (file.isPaused) {
socket.send('pause', {})
}
// Don't do anything here, the caller will take care of cancelling the upload itself
// using resetUploaderReferences(). This is because resetUploaderReferences() has to be
// called when this request is still in the queue, and has not been started yet, too. At
// that point this cancellation function is not going to be called.
// Also, we need to remove the request from the queue _without_ destroying everything
// related to this upload to handle pauses.
return () => {}
})
})

@@ -377,2 +492,5 @@ }

* restores state, we will continue uploading to the correct URL.
*
* @param {UppyFile} file
* @param {string} uploadURL
*/

@@ -393,2 +511,6 @@ onReceiveUploadUrl (file, uploadURL) {

/**
* @param {string} fileID
* @param {function(string): void} cb
*/
onFileRemove (fileID, cb) {

@@ -400,2 +522,6 @@ this.uploaderEvents[fileID].on('file-removed', (file) => {

/**
* @param {string} fileID
* @param {function(boolean): void} cb
*/
onPause (fileID, cb) {

@@ -410,2 +536,6 @@ this.uploaderEvents[fileID].on('upload-pause', (targetFileID, isPaused) => {

/**
* @param {string} fileID
* @param {function(): void} cb
*/
onRetry (fileID, cb) {

@@ -419,2 +549,6 @@ this.uploaderEvents[fileID].on('upload-retry', (targetFileID) => {

/**
* @param {string} fileID
* @param {function(): void} cb
*/
onRetryAll (fileID, cb) {

@@ -427,2 +561,6 @@ this.uploaderEvents[fileID].on('retry-all', (filesToRetry) => {

/**
* @param {string} fileID
* @param {function(): void} cb
*/
onPauseAll (fileID, cb) {

@@ -435,2 +573,6 @@ this.uploaderEvents[fileID].on('pause-all', () => {

/**
* @param {string} fileID
* @param {function(): void} cb
*/
onCancelAll (fileID, cb) {

@@ -443,2 +585,6 @@ this.uploaderEvents[fileID].on('cancel-all', () => {

/**
* @param {string} fileID
* @param {function(): void} cb
*/
onResumeAll (fileID, cb) {

@@ -451,28 +597,25 @@ this.uploaderEvents[fileID].on('resume-all', () => {

/**
* @param {(UppyFile | FailedUppyFile)[]} files
*/
uploadFiles (files) {
const actions = files.map((file, i) => {
const current = parseInt(i, 10) + 1
const promises = files.map((file, i) => {
const current = i + 1
const total = files.length
if (file.error) {
return () => Promise.reject(new Error(file.error))
if ('error' in file && file.error) {
return Promise.reject(new Error(file.error))
} else if (file.isRemote) {
// We emit upload-started here, so that it's also emitted for files
// that have to wait due to the `limit` option.
this.uppy.emit('upload-started', file)
return this.uploadRemote.bind(this, file, current, total)
return this.uploadRemote(file, current, total)
} else {
this.uppy.emit('upload-started', file)
return this.upload.bind(this, file, current, total)
return this.upload(file, current, total)
}
})
const promises = actions.map((action) => {
const limitedAction = this.limitUploads(action)
return limitedAction()
})
return settle(promises)
}
/**
* @param {string[]} fileIDs
*/
handleUpload (fileIDs) {

@@ -479,0 +622,0 @@ if (fileIDs.length === 0) {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc