uppy
Version:
Extensible JavaScript file upload widget with support for drag&drop, resumable uploads, previews, restrictions, file processing/encoding, remote providers like Instagram, Dropbox, Google Drive, S3 and more :dog:
899 lines (757 loc) • 32.2 kB
JavaScript
'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 Translator = require('../../core/Translator');
var Plugin = require('../../core/Plugin');
var Tus = require('../Tus');
var Client = require('./Client');
var StatusSocket = require('./Socket');
function defaultGetAssemblyOptions(file, options) {
return {
params: options.params,
signature: options.signature,
fields: options.fields
};
}
/**
* Upload files to Transloadit using Tus.
*/
module.exports = function (_Plugin) {
_inherits(Transloadit, _Plugin);
function Transloadit(uppy, opts) {
_classCallCheck(this, Transloadit);
var _this = _possibleConstructorReturn(this, _Plugin.call(this, uppy, opts));
_this.type = 'uploader';
_this.id = 'Transloadit';
_this.title = 'Transloadit';
var defaultLocale = {
strings: {
creatingAssembly: 'Preparing upload...',
creatingAssemblyFailed: 'Transloadit: Could not create assembly',
encoding: 'Encoding...'
}
};
var defaultOptions = {
service: 'https://api2.transloadit.com',
waitForEncoding: false,
waitForMetadata: false,
alwaysRunAssembly: false,
importFromUploadURLs: false,
signature: null,
params: null,
fields: {},
getAssemblyOptions: defaultGetAssemblyOptions,
locale: defaultLocale
};
_this.opts = _extends({}, defaultOptions, opts);
_this.locale = _extends({}, defaultLocale, _this.opts.locale);
_this.locale.strings = _extends({}, defaultLocale.strings, _this.opts.locale.strings);
_this.translator = new Translator({ locale: _this.locale });
_this.i18n = _this.translator.translate.bind(_this.translator);
_this.prepareUpload = _this.prepareUpload.bind(_this);
_this.afterUpload = _this.afterUpload.bind(_this);
_this.onFileUploadURLAvailable = _this.onFileUploadURLAvailable.bind(_this);
_this.onRestored = _this.onRestored.bind(_this);
_this.getPersistentData = _this.getPersistentData.bind(_this);
if (_this.opts.params) {
_this.validateParams(_this.opts.params);
}
_this.client = new Client({
service: _this.opts.service
});
_this.sockets = {};
return _this;
}
Transloadit.prototype.validateParams = function validateParams(params) {
if (!params) {
throw new Error('Transloadit: The `params` option is required.');
}
if (typeof params === 'string') {
try {
params = JSON.parse(params);
} catch (err) {
// Tell the user that this is not an Uppy bug!
err.message = 'Transloadit: The `params` option is a malformed JSON string: ' + err.message;
throw err;
}
}
if (!params.auth || !params.auth.key) {
throw new Error('Transloadit: The `params.auth.key` option is required. ' + 'You can find your Transloadit API key at https://transloadit.com/accounts/credentials.');
}
};
Transloadit.prototype.getAssemblyOptions = function getAssemblyOptions(fileIDs) {
var _this2 = this;
var options = this.opts;
var normalizeAssemblyOptions = function normalizeAssemblyOptions(file, assemblyOptions) {
if (Array.isArray(assemblyOptions.fields)) {
var fieldNames = assemblyOptions.fields;
assemblyOptions.fields = {};
fieldNames.forEach(function (fieldName) {
assemblyOptions.fields[fieldName] = file.meta[fieldName];
});
}
if (!assemblyOptions.fields) {
assemblyOptions.fields = {};
}
return assemblyOptions;
};
return _Promise.all(fileIDs.map(function (fileID) {
var file = _this2.uppy.getFile(fileID);
var promise = _Promise.resolve().then(function () {
return options.getAssemblyOptions(file, options);
}).then(function (assemblyOptions) {
return normalizeAssemblyOptions(file, assemblyOptions);
});
return promise.then(function (assemblyOptions) {
_this2.validateParams(assemblyOptions.params);
return {
fileIDs: [fileID],
options: assemblyOptions
};
});
}));
};
Transloadit.prototype.dedupeAssemblyOptions = function dedupeAssemblyOptions(list) {
var dedupeMap = Object.create(null);
list.forEach(function (_ref) {
var fileIDs = _ref.fileIDs,
options = _ref.options;
var id = JSON.stringify(options);
if (dedupeMap[id]) {
var _dedupeMap$id$fileIDs;
(_dedupeMap$id$fileIDs = dedupeMap[id].fileIDs).push.apply(_dedupeMap$id$fileIDs, fileIDs);
} else {
dedupeMap[id] = {
options: options,
fileIDs: [].concat(fileIDs)
};
}
});
return Object.keys(dedupeMap).map(function (id) {
return dedupeMap[id];
});
};
Transloadit.prototype.createAssembly = function createAssembly(fileIDs, uploadID, options) {
var _this3 = this;
var pluginOptions = this.opts;
this.uppy.log('[Transloadit] create assembly');
return this.client.createAssembly({
params: options.params,
fields: options.fields,
expectedFiles: fileIDs.length,
signature: options.signature
}).then(function (assembly) {
var _extends2, _extends3;
// Store the list of assemblies related to this upload.
var state = _this3.getPluginState();
var assemblyList = state.uploadsAssemblies[uploadID];
var uploadsAssemblies = _extends({}, state.uploadsAssemblies, (_extends2 = {}, _extends2[uploadID] = assemblyList.concat([assembly.assembly_id]), _extends2));
_this3.setPluginState({
assemblies: _extends(state.assemblies, (_extends3 = {}, _extends3[assembly.assembly_id] = assembly, _extends3)),
uploadsAssemblies: uploadsAssemblies
});
function attachAssemblyMetadata(file, assembly) {
// Attach meta parameters for the Tus plugin. See:
// https://github.com/tus/tusd/wiki/Uploading-to-Transloadit-using-tus#uploading-using-tus
var tlMeta = {
assembly_url: assembly.assembly_url,
filename: file.name,
fieldname: 'file'
};
var meta = _extends({}, file.meta, tlMeta);
// Add assembly-specific Tus endpoint.
var tus = _extends({}, file.tus, {
endpoint: assembly.tus_url
});
// Set uppy server location.
// we only add this, if 'file' has the attribute remote, because
// this is the criteria to identify remote files. If we add it without
// the check, then the file automatically becomes a remote file.
// @TODO: this is quite hacky. Please fix this later
var remote = void 0;
if (file.remote) {
var newHost = assembly.uppyserver_url;
// remove tailing slash
if (newHost.endsWith('/')) {
newHost = newHost.slice(0, -1);
}
var path = file.remote.url.replace(file.remote.host, '');
// remove leading slash
if (path.startsWith('/')) {
path = path.slice(1);
}
remote = _extends({}, file.remote, {
host: newHost,
url: newHost + '/' + path
});
}
var transloadit = {
assembly: assembly.assembly_id
};
var newFile = _extends({}, file, { transloadit: transloadit });
// Only configure the Tus plugin if we are uploading straight to Transloadit (the default).
if (!pluginOptions.importFromUploadURLs) {
_extends(newFile, { meta: meta, tus: tus, remote: remote });
}
return newFile;
}
var files = _extends({}, _this3.uppy.state.files);
fileIDs.forEach(function (id) {
files[id] = attachAssemblyMetadata(files[id], assembly);
});
_this3.uppy.setState({ files: files });
_this3.uppy.emit('transloadit:assembly-created', assembly, fileIDs);
return _this3.connectSocket(assembly).then(function () {
return assembly;
});
}).then(function (assembly) {
_this3.uppy.log('[Transloadit] Created assembly');
return assembly;
}).catch(function (err) {
_this3.uppy.info(_this3.i18n('creatingAssemblyFailed'), 'error', 0);
// Reject the promise.
throw err;
});
};
Transloadit.prototype.shouldWait = function shouldWait() {
return this.opts.waitForEncoding || this.opts.waitForMetadata;
};
/**
* Used when `importFromUploadURLs` is enabled: reserves all files in
* the assembly.
*/
Transloadit.prototype.reserveFiles = function reserveFiles(assembly, fileIDs) {
var _this4 = this;
return _Promise.all(fileIDs.map(function (fileID) {
var file = _this4.uppy.getFile(fileID);
return _this4.client.reserveFile(assembly, file);
}));
};
/**
* Used when `importFromUploadURLs` is enabled: adds files to the assembly
* once they have been fully uploaded.
*/
Transloadit.prototype.onFileUploadURLAvailable = function onFileUploadURLAvailable(file) {
var _this5 = this;
if (!file || !file.transloadit || !file.transloadit.assembly) {
return;
}
var state = this.getPluginState();
var assembly = state.assemblies[file.transloadit.assembly];
this.client.addFile(assembly, file).catch(function (err) {
_this5.uppy.log(err);
_this5.uppy.emit('transloadit:import-error', assembly, file.id, err);
});
};
Transloadit.prototype.findFile = function findFile(uploadedFile) {
var files = this.uppy.state.files;
for (var id in files) {
if (!files.hasOwnProperty(id)) {
continue;
}
// Completed file upload.
if (files[id].uploadURL === uploadedFile.tus_upload_url) {
return files[id];
}
// In-progress file upload.
if (files[id].tus && files[id].tus.uploadUrl === uploadedFile.tus_upload_url) {
return files[id];
}
if (!uploadedFile.is_tus_file) {
// Fingers-crossed check for non-tus uploads, eg imported from S3.
if (files[id].name === uploadedFile.name && files[id].size === uploadedFile.size) {
return files[id];
}
}
}
};
Transloadit.prototype.onFileUploadComplete = function onFileUploadComplete(assemblyId, uploadedFile) {
var _extends4;
var state = this.getPluginState();
var file = this.findFile(uploadedFile);
if (!file) {
this.uppy.log('[Transloadit] Couldn’t file the file, it was likely removed in the process');
return;
}
this.setPluginState({
files: _extends({}, state.files, (_extends4 = {}, _extends4[uploadedFile.id] = {
assembly: assemblyId,
id: file.id,
uploadedFile: uploadedFile
}, _extends4))
});
this.uppy.emit('transloadit:upload', uploadedFile, this.getAssembly(assemblyId));
};
Transloadit.prototype.onResult = function onResult(assemblyId, stepName, result) {
var state = this.getPluginState();
var file = state.files[result.original_id];
// The `file` may not exist if an import robot was used instead of a file upload.
result.localId = file ? file.id : null;
var entry = {
result: result,
stepName: stepName,
id: result.id,
assembly: assemblyId
};
this.setPluginState({
results: [].concat(state.results, [entry])
});
this.uppy.emit('transloadit:result', stepName, result, this.getAssembly(assemblyId));
};
Transloadit.prototype.onAssemblyFinished = function onAssemblyFinished(url) {
var _this6 = this;
this.client.getAssemblyStatus(url).then(function (assembly) {
var _extends5;
var state = _this6.getPluginState();
_this6.setPluginState({
assemblies: _extends({}, state.assemblies, (_extends5 = {}, _extends5[assembly.assembly_id] = assembly, _extends5))
});
_this6.uppy.emit('transloadit:complete', assembly);
});
};
Transloadit.prototype.getPersistentData = function getPersistentData(setData) {
var _setData;
var state = this.getPluginState();
var assemblies = state.assemblies;
var uploadsAssemblies = state.uploadsAssemblies;
var uploads = Object.keys(state.files);
var results = state.results.map(function (result) {
return result.id;
});
setData((_setData = {}, _setData[this.id] = {
assemblies: assemblies,
uploadsAssemblies: uploadsAssemblies,
uploads: uploads,
results: results
}, _setData));
};
/**
* Emit the necessary events that must have occured to get from the `prevState`,
* to the current state.
* For completed uploads, `transloadit:upload` is emitted.
* For new results, `transloadit:result` is emitted.
* For completed or errored assemblies, `transloadit:complete` or `transloadit:assembly-error` is emitted.
*/
Transloadit.prototype.emitEventsDiff = function emitEventsDiff(prevState) {
var _this7 = this;
var opts = this.opts;
var state = this.getPluginState();
var emitMissedEvents = function emitMissedEvents() {
// Emit events for completed uploads and completed results
// that we've missed while we were away.
var newUploads = Object.keys(state.files).filter(function (fileID) {
return !prevState.files.hasOwnProperty(fileID);
}).map(function (fileID) {
return state.files[fileID];
});
var newResults = state.results.filter(function (result) {
return !prevState.results.some(function (prev) {
return prev.id === result.id;
});
});
_this7.uppy.log('[Transloadit] New fully uploaded files since restore:');
_this7.uppy.log(newUploads);
newUploads.forEach(function (_ref2) {
var assembly = _ref2.assembly,
uploadedFile = _ref2.uploadedFile;
_this7.uppy.log('[Transloadit] emitting transloadit:upload ' + uploadedFile.id);
_this7.uppy.emit('transloadit:upload', uploadedFile, _this7.getAssembly(assembly));
});
_this7.uppy.log('[Transloadit] New results since restore:');
_this7.uppy.log(newResults);
newResults.forEach(function (_ref3) {
var assembly = _ref3.assembly,
stepName = _ref3.stepName,
result = _ref3.result,
id = _ref3.id;
_this7.uppy.log('[Transloadit] emitting transloadit:result ' + stepName + ', ' + id);
_this7.uppy.emit('transloadit:result', stepName, result, _this7.getAssembly(assembly));
});
var newAssemblies = state.assemblies;
var previousAssemblies = prevState.assemblies;
_this7.uppy.log('[Transloadit] Current assembly status after restore');
_this7.uppy.log(newAssemblies);
_this7.uppy.log('[Transloadit] Assembly status before restore');
_this7.uppy.log(previousAssemblies);
Object.keys(newAssemblies).forEach(function (assemblyId) {
var oldAssembly = previousAssemblies[assemblyId];
diffAssemblyStatus(oldAssembly, newAssemblies[assemblyId]);
});
};
// Emit events for assemblies that have completed or errored while we were away.
var diffAssemblyStatus = function diffAssemblyStatus(prev, next) {
_this7.uppy.log('[Transloadit] Diff assemblies');
_this7.uppy.log(prev);
_this7.uppy.log(next);
if (opts.waitForEncoding && next.ok === 'ASSEMBLY_COMPLETED' && prev.ok !== 'ASSEMBLY_COMPLETED') {
_this7.uppy.log('[Transloadit] Emitting transloadit:complete for ' + next.assembly_id);
_this7.uppy.log(next);
_this7.uppy.emit('transloadit:complete', next);
} else if (opts.waitForMetadata && next.upload_meta_data_extracted && !prev.upload_meta_data_extracted) {
_this7.uppy.log('[Transloadit] Emitting transloadit:complete after metadata extraction for ' + next.assembly_id);
_this7.uppy.log(next);
_this7.uppy.emit('transloadit:complete', next);
}
if (next.error && !prev.error) {
_this7.uppy.log('[Transloadit] !!! Emitting transloadit:assembly-error for ' + next.assembly_id);
_this7.uppy.log(next);
_this7.uppy.emit('transloadit:assembly-error', next, new Error(next.message));
}
};
emitMissedEvents();
};
Transloadit.prototype.onRestored = function onRestored(pluginData) {
var _this8 = this;
var savedState = pluginData && pluginData[this.id] ? pluginData[this.id] : {};
var knownUploads = savedState.files || [];
var knownResults = savedState.results || [];
var previousAssemblies = savedState.assemblies || {};
var uploadsAssemblies = savedState.uploadsAssemblies || {};
if (Object.keys(uploadsAssemblies).length === 0) {
// Nothing to restore.
return;
}
// Fetch up-to-date assembly statuses.
var loadAssemblies = function loadAssemblies() {
var assemblyIDs = [];
Object.keys(uploadsAssemblies).forEach(function (uploadID) {
assemblyIDs.push.apply(assemblyIDs, uploadsAssemblies[uploadID]);
});
return _Promise.all(assemblyIDs.map(function (assemblyID) {
var url = 'https://api2.transloadit.com/assemblies/' + assemblyID;
return _this8.client.getAssemblyStatus(url);
}));
};
var reconnectSockets = function reconnectSockets(assemblies) {
return _Promise.all(assemblies.map(function (assembly) {
// No need to connect to the socket if the assembly has completed by now.
if (assembly.ok === 'ASSEMBLY_COMPLETE') {
return null;
}
return _this8.connectSocket(assembly);
}));
};
// Convert loaded assembly statuses to a Transloadit plugin state object.
var restoreState = function restoreState(assemblies) {
var assembliesById = {};
var files = {};
var results = [];
assemblies.forEach(function (assembly) {
assembliesById[assembly.assembly_id] = assembly;
assembly.uploads.forEach(function (uploadedFile) {
var file = _this8.findFile(uploadedFile);
files[uploadedFile.id] = {
id: file.id,
assembly: assembly.assembly_id,
uploadedFile: uploadedFile
};
});
var state = _this8.getPluginState();
Object.keys(assembly.results).forEach(function (stepName) {
assembly.results[stepName].forEach(function (result) {
var file = state.files[result.original_id];
result.localId = file ? file.id : null;
results.push({
id: result.id,
result: result,
stepName: stepName,
assembly: assembly.assembly_id
});
});
});
});
_this8.setPluginState({
assemblies: assembliesById,
files: files,
results: results,
uploadsAssemblies: uploadsAssemblies
});
};
// Restore all assembly state.
this.restored = _Promise.resolve().then(loadAssemblies).then(function (assemblies) {
restoreState(assemblies);
return reconnectSockets(assemblies);
}).then(function () {
// Return a callback that will be called by `afterUpload`
// once it has attached event listeners etc.
var newState = _this8.getPluginState();
var previousFiles = {};
knownUploads.forEach(function (id) {
previousFiles[id] = newState.files[id];
});
return function () {
return _this8.emitEventsDiff({
assemblies: previousAssemblies,
files: previousFiles,
results: newState.results.filter(function (_ref4) {
var id = _ref4.id;
return knownResults.indexOf(id) !== -1;
}),
uploadsAssemblies: uploadsAssemblies
});
};
});
this.restored.then(function () {
_this8.restored = null;
});
};
Transloadit.prototype.connectSocket = function connectSocket(assembly) {
var _this9 = this;
var socket = new StatusSocket(assembly.websocket_url, assembly);
this.sockets[assembly.assembly_id] = socket;
socket.on('upload', this.onFileUploadComplete.bind(this, assembly.assembly_id));
socket.on('error', function (error) {
_this9.uppy.emit('transloadit:assembly-error', assembly, error);
});
socket.on('executing', function () {
_this9.uppy.emit('transloadit:assembly-executing', assembly);
});
if (this.opts.waitForEncoding) {
socket.on('result', this.onResult.bind(this, assembly.assembly_id));
}
if (this.opts.waitForEncoding) {
socket.on('finished', function () {
_this9.onAssemblyFinished(assembly.assembly_ssl_url);
});
} else if (this.opts.waitForMetadata) {
socket.on('metadata', function () {
_this9.onAssemblyFinished(assembly.assembly_ssl_url);
});
}
return new _Promise(function (resolve, reject) {
socket.on('connect', resolve);
socket.on('error', reject);
}).then(function () {
_this9.uppy.log('[Transloadit] Socket is ready');
});
};
Transloadit.prototype.prepareUpload = function prepareUpload(fileIDs, uploadID) {
var _this10 = this,
_extends6;
// Only use files without errors
fileIDs = fileIDs.filter(function (file) {
return !file.error;
});
fileIDs.forEach(function (fileID) {
var file = _this10.uppy.getFile(fileID);
_this10.uppy.emit('preprocess-progress', file, {
mode: 'indeterminate',
message: _this10.i18n('creatingAssembly')
});
});
var createAssembly = function createAssembly(_ref5) {
var fileIDs = _ref5.fileIDs,
options = _ref5.options;
return _this10.createAssembly(fileIDs, uploadID, options).then(function (assembly) {
if (_this10.opts.importFromUploadURLs) {
return _this10.reserveFiles(assembly, fileIDs);
}
}).then(function () {
fileIDs.forEach(function (fileID) {
var file = _this10.uppy.getFile(fileID);
_this10.uppy.emit('preprocess-complete', file);
});
}).catch(function (err) {
// Clear preprocessing state when the assembly could not be created,
// otherwise the UI gets confused about the lingering progress keys
fileIDs.forEach(function (fileID) {
var file = _this10.uppy.getFile(fileID);
_this10.uppy.emit('preprocess-complete', file);
_this10.uppy.emit('upload-error', file, err);
});
throw err;
});
};
var state = this.getPluginState();
var uploadsAssemblies = _extends({}, state.uploadsAssemblies, (_extends6 = {}, _extends6[uploadID] = [], _extends6));
this.setPluginState({ uploadsAssemblies: uploadsAssemblies });
var optionsPromise = void 0;
if (fileIDs.length > 0) {
optionsPromise = this.getAssemblyOptions(fileIDs).then(function (allOptions) {
return _this10.dedupeAssemblyOptions(allOptions);
});
} else if (this.opts.alwaysRunAssembly) {
optionsPromise = _Promise.resolve(this.opts.getAssemblyOptions(null, this.opts)).then(function (options) {
_this10.validateParams(options.params);
return [{ fileIDs: fileIDs, options: options }];
});
} else {
// If there are no files and we do not `alwaysRunAssembly`,
// don't do anything.
return _Promise.resolve();
}
return optionsPromise.then(function (assemblies) {
return _Promise.all(assemblies.map(createAssembly));
});
};
Transloadit.prototype.afterUpload = function afterUpload(fileIDs, uploadID) {
var _this11 = this;
// Only use files without errors
fileIDs = fileIDs.filter(function (file) {
return !file.error;
});
var state = this.getPluginState();
// If we're still restoring state, wait for that to be done.
if (this.restored) {
return this.restored.then(function (emitMissedEvents) {
var promise = _this11.afterUpload(fileIDs, uploadID);
emitMissedEvents();
return promise;
});
}
var assemblyIDs = state.uploadsAssemblies[uploadID];
// If we don't have to wait for encoding metadata or results, we can close
// the socket immediately and finish the upload.
if (!this.shouldWait()) {
assemblyIDs.forEach(function (assemblyID) {
var socket = _this11.sockets[assemblyID];
socket.close();
});
var assemblies = assemblyIDs.map(function (id) {
return _this11.getAssembly(id);
});
this.uppy.addResultData(uploadID, { transloadit: assemblies });
return _Promise.resolve();
}
// If no assemblies were created for this upload, we also do not have to wait.
// There's also no sockets or anything to close, so just return immediately.
if (assemblyIDs.length === 0) {
this.uppy.addResultData(uploadID, { transloadit: [] });
return _Promise.resolve();
}
var finishedAssemblies = 0;
return new _Promise(function (resolve, reject) {
fileIDs.forEach(function (fileID) {
var file = _this11.uppy.getFile(fileID);
_this11.uppy.emit('postprocess-progress', file, {
mode: 'indeterminate',
message: _this11.i18n('encoding')
});
});
var onAssemblyFinished = function onAssemblyFinished(assembly) {
// An assembly for a different upload just finished. We can ignore it.
if (assemblyIDs.indexOf(assembly.assembly_id) === -1) {
_this11.uppy.log('[Transloadit] afterUpload(): Ignoring finished assembly ' + assembly.assembly_id);
return;
}
_this11.uppy.log('[Transloadit] afterUpload(): Got assembly finish ' + assembly.assembly_id);
// TODO set the `file.uploadURL` to a result?
// We will probably need an option here so the plugin user can tell us
// which result to pick…?
var files = _this11.getAssemblyFiles(assembly.assembly_id);
files.forEach(function (file) {
_this11.uppy.emit('postprocess-complete', file);
});
checkAllComplete();
};
var onAssemblyError = function onAssemblyError(assembly, error) {
// An assembly for a different upload just errored. We can ignore it.
if (assemblyIDs.indexOf(assembly.assembly_id) === -1) {
_this11.uppy.log('[Transloadit] afterUpload(): Ignoring errored assembly ' + assembly.assembly_id);
return;
}
_this11.uppy.log('[Transloadit] afterUpload(): Got assembly error ' + assembly.assembly_id);
_this11.uppy.log(error);
// Clear postprocessing state for all our files.
var files = _this11.getAssemblyFiles(assembly.assembly_id);
files.forEach(function (file) {
// TODO Maybe make a postprocess-error event here?
_this11.uppy.emit('upload-error', file, error);
_this11.uppy.emit('postprocess-complete', file);
});
checkAllComplete();
};
var onImportError = function onImportError(assembly, fileID, error) {
if (assemblyIDs.indexOf(assembly.assembly_id) === -1) {
return;
}
// Not sure if we should be doing something when it's just one file failing.
// ATM, the only options are 1) ignoring or 2) failing the entire upload.
// I think failing the upload is better than silently ignoring.
// In the future we should maybe have a way to resolve uploads with some failures,
// like returning an object with `{ successful, failed }` uploads.
onAssemblyError(assembly, error);
};
var checkAllComplete = function checkAllComplete() {
finishedAssemblies += 1;
if (finishedAssemblies === assemblyIDs.length) {
// We're done, these listeners can be removed
removeListeners();
var _assemblies = assemblyIDs.map(function (id) {
return _this11.getAssembly(id);
});
_this11.uppy.addResultData(uploadID, { transloadit: _assemblies });
resolve();
}
};
var removeListeners = function removeListeners() {
_this11.uppy.off('transloadit:complete', onAssemblyFinished);
_this11.uppy.off('transloadit:assembly-error', onAssemblyError);
_this11.uppy.off('transloadit:import-error', onImportError);
};
_this11.uppy.on('transloadit:complete', onAssemblyFinished);
_this11.uppy.on('transloadit:assembly-error', onAssemblyError);
_this11.uppy.on('transloadit:import-error', onImportError);
}).then(function (result) {
// Clean up uploadID → assemblyIDs, they're no longer going to be used anywhere.
var state = _this11.getPluginState();
var uploadsAssemblies = _extends({}, state.uploadsAssemblies);
delete uploadsAssemblies[uploadID];
_this11.setPluginState({ uploadsAssemblies: uploadsAssemblies });
return result;
});
};
Transloadit.prototype.install = function install() {
this.uppy.addPreProcessor(this.prepareUpload);
this.uppy.addPostProcessor(this.afterUpload);
if (this.opts.importFromUploadURLs) {
// No uploader needed when importing; instead we take the upload URL from an existing uploader.
this.uppy.on('upload-success', this.onFileUploadURLAvailable);
} else {
this.uppy.use(Tus, {
// Disable tus-js-client fingerprinting, otherwise uploading the same file at different times
// will upload to the same assembly.
resume: false,
// Only send assembly metadata to the tus endpoint.
metaFields: ['assembly_url', 'filename', 'fieldname']
});
}
this.uppy.on('restore:get-data', this.getPersistentData);
this.uppy.on('restored', this.onRestored);
this.setPluginState({
// Contains assembly status objects, indexed by their ID.
assemblies: {},
// Contains arrays of assembly IDs, indexed by the upload ID that they belong to.
uploadsAssemblies: {},
// Contains file data from Transloadit, indexed by their Transloadit-assigned ID.
files: {},
// Contains result data from Transloadit.
results: []
});
};
Transloadit.prototype.uninstall = function uninstall() {
this.uppy.removePreProcessor(this.prepareUpload);
this.uppy.removePostProcessor(this.afterUpload);
if (this.opts.importFromUploadURLs) {
this.uppy.off('upload-success', this.onFileUploadURLAvailable);
}
};
Transloadit.prototype.getAssembly = function getAssembly(id) {
var state = this.getPluginState();
return state.assemblies[id];
};
Transloadit.prototype.getAssemblyFiles = function getAssemblyFiles(assemblyID) {
var _this12 = this;
var fileIDs = Object.keys(this.uppy.state.files);
return fileIDs.map(function (fileID) {
return _this12.uppy.getFile(fileID);
}).filter(function (file) {
return file && file.transloadit && file.transloadit.assembly === assemblyID;
});
};
return Transloadit;
}(Plugin);
//# sourceMappingURL=index.js.map