UNPKG

uppy

Version:

Almost as cute as a Puppy :dog:

423 lines (348 loc) 13.5 kB
'use strict'; 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