uppy
Version:
Almost as cute as a Puppy :dog:
423 lines (348 loc) • 13.5 kB
JavaScript
;
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var _Promise = typeof Promise === 'undefined' ? require('es6-promise').Promise : Promise;
var Plugin = require('./Plugin');
var tus = require('tus-js-client');
var settle = require('promise-settle');
var UppySocket = require('../core/UppySocket');
var Utils = require('../core/Utils');
require('whatwg-fetch'
// 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 tusDefaultOptions = {
endpoint: '',
resume: true,
onProgress: null,
onChunkComplete: null,
onSuccess: null,
onError: null,
headers: {},
chunkSize: Infinity,
withCredentials: false,
uploadUrl: null,
uploadSize: null,
overridePatchMethod: false,
retryDelays: null
/**
* Tus resumable file uploader
*
*/
};module.exports = function (_Plugin) {
_inherits(Tus10, _Plugin);
function Tus10(core, opts) {
_classCallCheck(this, Tus10);
var _this = _possibleConstructorReturn(this, _Plugin.call(this, core, opts));
_this.type = 'uploader';
_this.id = 'Tus';
_this.title = 'Tus';
// set default options
var defaultOptions = {
resume: true,
autoRetry: true,
retryDelays: [0, 1000, 3000, 5000]
// merge default options with the ones set by user
};_this.opts = _extends({}, defaultOptions, opts);
_this.handlePauseAll = _this.handlePauseAll.bind(_this);
_this.handleResumeAll = _this.handleResumeAll.bind(_this);
_this.handleResetProgress = _this.handleResetProgress.bind(_this);
_this.handleUpload = _this.handleUpload.bind(_this);
return _this;
}
Tus10.prototype.pauseResume = function pauseResume(action, fileID) {
var updatedFiles = _extends({}, this.core.getState().files);
var inProgressUpdatedFiles = Object.keys(updatedFiles).filter(function (file) {
return !updatedFiles[file].progress.uploadComplete && updatedFiles[file].progress.uploadStarted;
});
switch (action) {
case 'toggle':
if (updatedFiles[fileID].uploadComplete) return;
var wasPaused = updatedFiles[fileID].isPaused || false;
var isPaused = !wasPaused;
var updatedFile = void 0;
if (wasPaused) {
updatedFile = _extends({}, updatedFiles[fileID], {
isPaused: false
});
} else {
updatedFile = _extends({}, updatedFiles[fileID], {
isPaused: true
});
}
updatedFiles[fileID] = updatedFile;
this.core.setState({ files: updatedFiles });
return isPaused;
case 'pauseAll':
inProgressUpdatedFiles.forEach(function (file) {
var updatedFile = _extends({}, updatedFiles[file], {
isPaused: true
});
updatedFiles[file] = updatedFile;
});
this.core.setState({ files: updatedFiles });
return;
case 'resumeAll':
inProgressUpdatedFiles.forEach(function (file) {
var updatedFile = _extends({}, updatedFiles[file], {
isPaused: false
});
updatedFiles[file] = updatedFile;
});
this.core.setState({ files: updatedFiles });
return;
}
};
Tus10.prototype.handlePauseAll = function handlePauseAll() {
this.pauseResume('pauseAll');
};
Tus10.prototype.handleResumeAll = function handleResumeAll() {
this.pauseResume('resumeAll');
};
Tus10.prototype.handleResetProgress = function handleResetProgress() {
var files = _extends({}, this.core.state.files);
Object.keys(files).forEach(function (fileID) {
// Only clone the file object if it has a Tus `uploadUrl` attached.
if (files[fileID].tus && files[fileID].tus.uploadUrl) {
var tusState = _extends({}, files[fileID].tus);
delete tusState.uploadUrl;
files[fileID] = _extends({}, files[fileID], { tus: tusState });
}
});
this.core.setState({ files: files });
};
/**
* 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}
*/
Tus10.prototype.upload = function upload(file, current, total) {
var _this2 = this;
this.core.log('uploading ' + current + ' of ' + total
// Create a new tus upload
);return new _Promise(function (resolve, reject) {
var optsTus = _extends({}, tusDefaultOptions, _this2.opts,
// Install file-specific upload overrides.
file.tus || {});
optsTus.onError = function (err) {
_this2.core.log(err);
_this2.core.emit('core:upload-error', file.id, err);
reject('Failed because: ' + err);
};
optsTus.onProgress = function (bytesUploaded, bytesTotal) {
_this2.onReceiveUploadUrl(file, upload.url);
_this2.core.emit('core:upload-progress', {
uploader: _this2,
id: file.id,
bytesUploaded: bytesUploaded,
bytesTotal: bytesTotal
});
};
optsTus.onSuccess = function () {
_this2.core.emit('core:upload-success', file.id, upload, upload.url);
if (upload.url) {
_this2.core.log('Download ' + upload.file.name + ' from ' + upload.url);
}
resolve(upload);
};
optsTus.metadata = file.meta;
var upload = new tus.Upload(file.data, optsTus);
_this2.onFileRemove(file.id, function (targetFileID) {
// this.core.log(`removing file: ${targetFileID}`)
upload.abort();
resolve('upload ' + targetFileID + ' was removed');
});
_this2.onPause(file.id, function (isPaused) {
isPaused ? upload.abort() : upload.start();
});
_this2.onPauseAll(file.id, function () {
upload.abort();
});
_this2.onResumeAll(file.id, function () {
upload.start();
});
_this2.core.on('core:retry-started', function () {
var files = _this2.core.getState().files;
if (files[file.id].progress.uploadComplete || !files[file.id].progress.uploadStarted || files[file.id].isPaused) {
return;
}
upload.start();
});
upload.start();
_this2.core.emit('core:upload-started', file.id, upload);
});
};
Tus10.prototype.uploadRemote = function uploadRemote(file, current, total) {
var _this3 = this;
return new _Promise(function (resolve, reject) {
_this3.core.log(file.remote.url);
if (file.serverToken) {
_this3.connectToServerSocket(file);
} else {
var endpoint = _this3.opts.endpoint;
if (file.tus && file.tus.endpoint) {
endpoint = file.tus.endpoint;
}
_this3.core.emitter.emit('core:upload-started', file.id);
fetch(file.remote.url, {
method: 'post',
credentials: 'include',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(_extends({}, file.remote.body, {
endpoint: endpoint,
protocol: 'tus',
size: file.data.size,
metadata: file.meta
}))
}).then(function (res) {
if (res.status < 200 && res.status > 300) {
return reject(res.statusText);
}
res.json().then(function (data) {
var token = data.token;
file = _this3.getFile(file.id);
file.serverToken = token;
_this3.updateFile(file);
_this3.connectToServerSocket(file);
resolve();
});
});
}
});
};
Tus10.prototype.connectToServerSocket = function connectToServerSocket(file) {
var _this4 = this;
var token = file.serverToken;
var host = Utils.getSocketHost(file.remote.host);
var socket = new UppySocket({ target: host + '/api/' + token });
this.onFileRemove(file.id, function () {
return socket.send('pause', {});
});
this.onPause(file.id, function (isPaused) {
isPaused ? socket.send('pause', {}) : socket.send('resume', {});
});
this.onPauseAll(file.id, function () {
return socket.send('pause', {});
});
this.onResumeAll(file.id, function () {
return socket.send('resume', {});
});
socket.on('progress', function (progressData) {
return Utils.emitSocketProgress(_this4, progressData, file);
});
socket.on('success', function (data) {
_this4.core.emitter.emit('core:upload-success', file.id, data, data.url);
socket.close();
});
};
Tus10.prototype.getFile = function getFile(fileID) {
return this.core.state.files[fileID];
};
Tus10.prototype.updateFile = function updateFile(file) {
var _extends2;
var files = _extends({}, this.core.state.files, (_extends2 = {}, _extends2[file.id] = file, _extends2));
this.core.setState({ files: files });
};
Tus10.prototype.onReceiveUploadUrl = function onReceiveUploadUrl(file, uploadURL) {
var currentFile = this.getFile(file.id);
if (!currentFile) return;
// Only do the update if we didn't have an upload URL yet.
if (!currentFile.tus || currentFile.tus.uploadUrl !== uploadURL) {
var newFile = _extends({}, currentFile, {
tus: _extends({}, currentFile.tus, {
uploadUrl: uploadURL
})
});
this.updateFile(newFile);
}
};
Tus10.prototype.onFileRemove = function onFileRemove(fileID, cb) {
this.core.on('core:file-removed', function (targetFileID) {
if (fileID === targetFileID) cb(targetFileID);
});
};
Tus10.prototype.onPause = function onPause(fileID, cb) {
var _this5 = this;
this.core.on('core:upload-pause', function (targetFileID) {
if (fileID === targetFileID) {
var isPaused = _this5.pauseResume('toggle', fileID);
cb(isPaused);
}
});
};
Tus10.prototype.onPauseAll = function onPauseAll(fileID, cb) {
var _this6 = this;
this.core.on('core:pause-all', function () {
if (!_this6.core.getFile(fileID)) return;
cb();
});
};
Tus10.prototype.onResumeAll = function onResumeAll(fileID, cb) {
var _this7 = this;
this.core.on('core:resume-all', function () {
if (!_this7.core.getFile(fileID)) return;
cb();
});
};
Tus10.prototype.uploadFiles = function uploadFiles(files) {
var _this8 = this;
return settle(files.map(function (file, index) {
var current = parseInt(index, 10) + 1;
var total = files.length;
if (!file.isRemote) {
return _this8.upload(file, current, total);
} else {
return _this8.uploadRemote(file, current, total);
}
}));
};
Tus10.prototype.handleUpload = function handleUpload(fileIDs) {
var _this9 = this;
if (fileIDs.length === 0) {
this.core.log('Tus: no files to upload!');
return Promise.resolve();
}
this.core.log('Tus is uploading...');
var filesToUpload = fileIDs.map(function (fileID) {
return _this9.core.getFile(fileID);
});
return this.uploadFiles(filesToUpload);
};
Tus10.prototype.actions = function actions() {
var _this10 = this;
this.core.on('core:pause-all', this.handlePauseAll);
this.core.on('core:resume-all', this.handleResumeAll);
this.core.on('core:reset-progress', this.handleResetProgress);
if (this.opts.autoRetry) {
this.core.on('back-online', function () {
_this10.core.emit('core:retry-started');
});
}
};
Tus10.prototype.addResumableUploadsCapabilityFlag = function addResumableUploadsCapabilityFlag() {
var newCapabilities = _extends({}, this.core.getState().capabilities);
newCapabilities.resumableUploads = true;
this.core.setState({
capabilities: newCapabilities
});
};
Tus10.prototype.install = function install() {
this.addResumableUploadsCapabilityFlag();
this.core.addUploader(this.handleUpload);
this.actions();
};
Tus10.prototype.uninstall = function uninstall() {
this.core.removeUploader(this.handleUpload);
this.core.off('core:pause-all', this.handlePauseAll);
this.core.off('core:resume-all', this.handleResumeAll);
};
return Tus10;
}(Plugin);
//# sourceMappingURL=Tus10.js.map