Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@uppy/transloadit: simplify plugin to always run a single assembly #5158

Open
wants to merge 16 commits into
base: 4.x
Choose a base branch
from

Conversation

Murderlon
Copy link
Member

@Murderlon Murderlon commented May 13, 2024

Closes #4765

Tip

Click "Remove whitespace" and review by commit with the commits dropdown.

I tried to do atomic commits so you can review per commit to see the changes more in isolation. Tried to find a balance between removing enough complexity but going too far that there's a high risk of breaking things. More simplifications can be made, but these are the ones focussed on managing a single assembly instead of multiple.

I think it would be good if at least one other person tries to break this locally with pause/cancel/resume/local/remote states.

@Murderlon Murderlon self-assigned this May 13, 2024
Copy link
Contributor

github-actions bot commented May 13, 2024

Diff output files
diff --git a/packages/@uppy/transloadit/lib/Client.js b/packages/@uppy/transloadit/lib/Client.js
index 798d3da..fbfcef1 100644
--- a/packages/@uppy/transloadit/lib/Client.js
+++ b/packages/@uppy/transloadit/lib/Client.js
@@ -126,29 +126,9 @@ export default class Client {
       })
     );
   }
-  async updateNumberOfFilesInAssembly(assembly, num_expected_upload_files) {
-    const url = new URL(assembly.assembly_ssl_url);
-    url.pathname = "/update_assemblies";
-    const body = JSON.stringify({
-      assembly_updates: [{
-        assembly_id: assembly.assembly_id,
-        num_expected_upload_files,
-      }],
-    });
-    return _classPrivateFieldLooseBase(this, _fetchJSON)[_fetchJSON](url, {
-      method: "POST",
-      headers: _classPrivateFieldLooseBase(this, _headers)[_headers],
-      body,
-    }).catch(err =>
-      _classPrivateFieldLooseBase(this, _reportError)[_reportError](err, {
-        url,
-        type: "API_ERROR",
-      })
-    );
-  }
   async cancelAssembly(assembly) {
     const url = assembly.assembly_ssl_url;
-    return _classPrivateFieldLooseBase(this, _fetchJSON)[_fetchJSON](url, {
+    await _classPrivateFieldLooseBase(this, _fetchWithNetworkError)[_fetchWithNetworkError](url, {
       method: "DELETE",
       headers: _classPrivateFieldLooseBase(this, _headers)[_headers],
     }).catch(err =>
diff --git a/packages/@uppy/transloadit/lib/index.js b/packages/@uppy/transloadit/lib/index.js
index 123fa1f..037c0a8 100644
--- a/packages/@uppy/transloadit/lib/index.js
+++ b/packages/@uppy/transloadit/lib/index.js
@@ -14,22 +14,12 @@ import ErrorWithCause from "@uppy/utils/lib/ErrorWithCause";
 import hasProperty from "@uppy/utils/lib/hasProperty";
 import { RateLimitedQueue } from "@uppy/utils/lib/RateLimitedQueue";
 import Assembly from "./Assembly.js";
-import AssemblyOptionsBuilder from "./AssemblyOptions.js";
 import AssemblyWatcher from "./AssemblyWatcher.js";
 import Client from "./Client.js";
 import locale from "./locale.js";
 const packageJson = {
   "version": "4.0.0-beta.6",
 };
-const sendErrorToConsole = originalErr => err => {
-  const error = new ErrorWithCause("Failed to send error to the client", {
-    cause: err,
-  });
-  console.error(error, originalErr);
-};
-const COMPANION_URL = "https://api2.transloadit.com/companion";
-const COMPANION_ALLOWED_HOSTS = /\.transloadit\.com$/;
-const TL_COMPANION = /https?:\/\/api2(?:-\w+)?\.transloadit\.com\/companion/;
 const defaultOptions = {
   service: "https://api2.transloadit.com",
   errorReporting: true,
@@ -41,7 +31,37 @@ const defaultOptions = {
   retryDelays: [7000, 10000, 15000, 20000],
   clientName: null,
 };
+const sendErrorToConsole = originalErr => err => {
+  const error = new ErrorWithCause("Failed to send error to the client", {
+    cause: err,
+  });
+  console.error(error, originalErr);
+};
+function validateParams(params) {
+  if (params == null) {
+    throw new Error("Transloadit: The `params` option is required.");
+  }
+  if (typeof params === "string") {
+    try {
+      params = JSON.parse(params);
+    } catch (err) {
+      throw new ErrorWithCause("Transloadit: The `params` option is a malformed JSON string.", {
+        cause: 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/c/template-credentials",
+    );
+  }
+}
+const COMPANION_URL = "https://api2.transloadit.com/companion";
+const COMPANION_ALLOWED_HOSTS = /\.transloadit\.com$/;
+const TL_COMPANION = /https?:\/\/api2(?:-\w+)?\.transloadit\.com\/companion/;
 var _rateLimitedQueue = _classPrivateFieldLooseKey("rateLimitedQueue");
+var _watcher = _classPrivateFieldLooseKey("watcher");
 var _getClientVersion = _classPrivateFieldLooseKey("getClientVersion");
 var _attachAssemblyMetadata = _classPrivateFieldLooseKey("attachAssemblyMetadata");
 var _createAssembly = _classPrivateFieldLooseKey("createAssembly");
@@ -109,6 +129,10 @@ export default class Transloadit extends BasePlugin {
       writable: true,
       value: void 0,
     });
+    Object.defineProperty(this, _watcher, {
+      writable: true,
+      value: void 0,
+    });
     Object.defineProperty(this, _onFileUploadURLAvailable, {
       writable: true,
       value: rawFile => {
@@ -118,12 +142,11 @@ export default class Transloadit extends BasePlugin {
           return;
         }
         const {
-          assemblies,
-        } = this.getPluginState();
-        const assembly = assemblies[file.transloadit.assembly];
-        this.client.addFile(assembly, file).catch(err => {
+          status,
+        } = this.assembly;
+        this.client.addFile(status, file).catch(err => {
           this.uppy.log(err);
-          this.uppy.emit("transloadit:import-error", assembly, file.id, err);
+          this.uppy.emit("transloadit:import-error", status, file.id, err);
         });
       },
     });
@@ -131,14 +154,7 @@ export default class Transloadit extends BasePlugin {
       writable: true,
       value: async () => {
         try {
-          const {
-            uploadsAssemblies,
-          } = this.getPluginState();
-          const assemblyIDs = Object.values(uploadsAssemblies).flat(1);
-          const assemblies = assemblyIDs.map(assemblyID => this.getAssembly(assemblyID));
-          await Promise.all(
-            assemblies.map(assembly => _classPrivateFieldLooseBase(this, _cancelAssembly)[_cancelAssembly](assembly)),
-          );
+          await _classPrivateFieldLooseBase(this, _cancelAssembly)[_cancelAssembly](this.assembly.status);
         } catch (err) {
           this.uppy.log(err);
         }
@@ -147,90 +163,71 @@ export default class Transloadit extends BasePlugin {
     Object.defineProperty(this, _getPersistentData, {
       writable: true,
       value: setData => {
-        const {
-          assemblies,
-          uploadsAssemblies,
-        } = this.getPluginState();
-        setData({
-          [this.id]: {
-            assemblies,
-            uploadsAssemblies,
-          },
-        });
+        if (this.assembly) {
+          setData({
+            [this.id]: {
+              assemblyResponse: this.assembly.status,
+            },
+          });
+        }
       },
     });
     Object.defineProperty(this, _onRestored, {
       writable: true,
       value: pluginData => {
         const savedState = pluginData && pluginData[this.id] ? pluginData[this.id] : {};
-        const previousAssemblies = savedState.assemblies || {};
-        const uploadsAssemblies = savedState.uploadsAssemblies || {};
-        if (Object.keys(uploadsAssemblies).length === 0) {
+        const previousAssembly = savedState.assemblyResponse;
+        if (!previousAssembly) {
           return;
         }
-        const restoreState = assemblies => {
+        const restoreState = () => {
           const files = {};
           const results = [];
-          for (const [id, status] of Object.entries(assemblies)) {
-            status.uploads.forEach(uploadedFile => {
-              const file = _classPrivateFieldLooseBase(this, _findFile)[_findFile](uploadedFile);
-              files[uploadedFile.id] = {
-                id: file.id,
+          const {
+            assembly_id: id,
+          } = previousAssembly;
+          previousAssembly.uploads.forEach(uploadedFile => {
+            const file = _classPrivateFieldLooseBase(this, _findFile)[_findFile](uploadedFile);
+            files[uploadedFile.id] = {
+              id: file.id,
+              assembly: id,
+              uploadedFile,
+            };
+          });
+          const state = this.getPluginState();
+          Object.keys(previousAssembly.results).forEach(stepName => {
+            for (const result of previousAssembly.results[stepName]) {
+              const file = state.files[result.original_id];
+              result.localId = file ? file.id : null;
+              results.push({
+                id: result.id,
+                result,
+                stepName,
                 assembly: id,
-                uploadedFile,
-              };
-            });
-            const state = this.getPluginState();
-            Object.keys(status.results).forEach(stepName => {
-              for (const result of status.results[stepName]) {
-                const file = state.files[result.original_id];
-                result.localId = file ? file.id : null;
-                results.push({
-                  id: result.id,
-                  result,
-                  stepName,
-                  assembly: id,
-                });
-              }
-            });
-          }
+              });
+            }
+          });
+          this.assembly = new Assembly(
+            previousAssembly,
+            _classPrivateFieldLooseBase(this, _rateLimitedQueue)[_rateLimitedQueue],
+          );
+          this.assembly.status = previousAssembly;
           this.setPluginState({
-            assemblies,
             files,
             results,
-            uploadsAssemblies,
           });
         };
         const restoreAssemblies = () => {
-          const {
-            assemblies,
-            uploadsAssemblies,
-          } = this.getPluginState();
-          Object.keys(uploadsAssemblies).forEach(uploadID => {
-            const assemblyIDs = uploadsAssemblies[uploadID];
-            _classPrivateFieldLooseBase(this, _createAssemblyWatcher)[_createAssemblyWatcher](assemblyIDs, uploadID);
-          });
-          const allAssemblyIDs = Object.keys(assemblies);
-          allAssemblyIDs.forEach(id => {
-            const assembly = new Assembly(
-              assemblies[id],
-              _classPrivateFieldLooseBase(this, _rateLimitedQueue)[_rateLimitedQueue],
-            );
-            _classPrivateFieldLooseBase(this, _connectAssembly)[_connectAssembly](assembly);
-          });
+          _classPrivateFieldLooseBase(this, _createAssemblyWatcher)[_createAssemblyWatcher](
+            previousAssembly.assembly_id,
+          );
+          _classPrivateFieldLooseBase(this, _connectAssembly)[_connectAssembly](this.assembly);
         };
         const updateAssemblies = () => {
-          const {
-            assemblies,
-          } = this.getPluginState();
-          return Promise.all(
-            Object.keys(assemblies).map(id => {
-              return this.activeAssemblies[id].update();
-            }),
-          );
+          return this.assembly.update();
         };
         this.restored = Promise.resolve().then(() => {
-          restoreState(previousAssemblies);
+          restoreState();
           restoreAssemblies();
           updateAssemblies();
         });
@@ -241,74 +238,37 @@ export default class Transloadit extends BasePlugin {
     });
     Object.defineProperty(this, _prepareUpload, {
       writable: true,
-      value: async (fileIDs, uploadID) => {
-        const files = fileIDs.map(id => this.uppy.getFile(id));
-        const filesWithoutErrors = files.filter(file => {
-          if (!file.error) {
-            this.uppy.emit("preprocess-progress", file, {
-              mode: "indeterminate",
-              message: this.i18n("creatingAssembly"),
-            });
-            return true;
-          }
-          return false;
-        });
-        const createAssembly = async _ref => {
-          let {
+      value: async fileIDs => {
+        var _assemblyOptions$fiel;
+        const assemblyOptions = typeof this.opts.assemblyOptions === "function"
+          ? await this.opts.assemblyOptions()
+          : this.opts.assemblyOptions;
+        (_assemblyOptions$fiel = assemblyOptions.fields) != null ? _assemblyOptions$fiel : assemblyOptions.fields = {};
+        validateParams(assemblyOptions.params);
+        try {
+          const assembly = await _classPrivateFieldLooseBase(this, _createAssembly)[_createAssembly](
             fileIDs,
-            options,
-          } = _ref;
-          try {
-            const assembly = await _classPrivateFieldLooseBase(this, _createAssembly)[_createAssembly](
-              fileIDs,
-              uploadID,
-              options,
-            );
-            if (this.opts.importFromUploadURLs) {
-              await _classPrivateFieldLooseBase(this, _reserveFiles)[_reserveFiles](assembly, fileIDs);
-            }
-            fileIDs.forEach(fileID => {
-              const file = this.uppy.getFile(fileID);
-              this.uppy.emit("preprocess-complete", file);
-            });
-            return assembly;
-          } catch (err) {
-            fileIDs.forEach(fileID => {
-              const file = this.uppy.getFile(fileID);
-              this.uppy.emit("preprocess-complete", file);
-              this.uppy.emit("upload-error", file, err);
-            });
-            throw err;
+            assemblyOptions,
+          );
+          if (this.opts.importFromUploadURLs) {
+            await _classPrivateFieldLooseBase(this, _reserveFiles)[_reserveFiles](assembly, fileIDs);
           }
-        };
-        const {
-          uploadsAssemblies,
-        } = this.getPluginState();
-        this.setPluginState({
-          uploadsAssemblies: {
-            ...uploadsAssemblies,
-            [uploadID]: [],
-          },
-        });
-        const builder = new AssemblyOptionsBuilder(filesWithoutErrors, this.opts);
-        await builder.build().then(assemblies => Promise.all(assemblies.map(createAssembly))).then(
-          maybeCreatedAssemblies => {
-            const createdAssemblies = maybeCreatedAssemblies.filter(Boolean);
-            const assemblyIDs = createdAssemblies.map(assembly => assembly.status.assembly_id);
-            _classPrivateFieldLooseBase(this, _createAssemblyWatcher)[_createAssemblyWatcher](assemblyIDs, uploadID);
-            return Promise.all(
-              createdAssemblies.map(assembly =>
-                _classPrivateFieldLooseBase(this, _connectAssembly)[_connectAssembly](assembly)
-              ),
-            );
-          },
-        ).catch(err => {
-          filesWithoutErrors.forEach(file => {
+          fileIDs.forEach(fileID => {
+            const file = this.uppy.getFile(fileID);
+            this.uppy.emit("preprocess-complete", file);
+          });
+          _classPrivateFieldLooseBase(this, _createAssemblyWatcher)[_createAssemblyWatcher](
+            assembly.status.assembly_id,
+          );
+          _classPrivateFieldLooseBase(this, _connectAssembly)[_connectAssembly](assembly);
+        } catch (err) {
+          fileIDs.forEach(fileID => {
+            const file = this.uppy.getFile(fileID);
             this.uppy.emit("preprocess-complete", file);
             this.uppy.emit("upload-error", file, err);
           });
           throw err;
-        });
+        }
       },
     });
     Object.defineProperty(this, _afterUpload, {
@@ -316,29 +276,23 @@ export default class Transloadit extends BasePlugin {
       value: (fileIDs, uploadID) => {
         const files = fileIDs.map(fileID => this.uppy.getFile(fileID));
         const filteredFileIDs = files.filter(file => !file.error).map(file => file.id);
-        const state = this.getPluginState();
         if (this.restored) {
           return this.restored.then(() => {
             return _classPrivateFieldLooseBase(this, _afterUpload)[_afterUpload](filteredFileIDs, uploadID);
           });
         }
-        const assemblyIDs = state.uploadsAssemblies[uploadID];
+        const assemblyID = this.assembly.status.assembly_id;
         const closeSocketConnections = () => {
-          assemblyIDs.forEach(assemblyID => {
-            const assembly = this.activeAssemblies[assemblyID];
-            assembly.close();
-            delete this.activeAssemblies[assemblyID];
-          });
+          this.assembly.close();
         };
         if (!_classPrivateFieldLooseBase(this, _shouldWaitAfterUpload)[_shouldWaitAfterUpload]()) {
           closeSocketConnections();
-          const assemblies = assemblyIDs.map(id => this.getAssembly(id));
           this.uppy.addResultData(uploadID, {
-            transloadit: assemblies,
+            transloadit: [this.assembly.status],
           });
           return Promise.resolve();
         }
-        if (assemblyIDs.length === 0) {
+        if (!assemblyID) {
           this.uppy.addResultData(uploadID, {
             transloadit: [],
           });
@@ -351,44 +305,33 @@ export default class Transloadit extends BasePlugin {
             message: this.i18n("encoding"),
           });
         });
-        const watcher = this.assemblyWatchers[uploadID];
-        return watcher.promise.then(() => {
+        return _classPrivateFieldLooseBase(this, _watcher)[_watcher].promise.then(() => {
           closeSocketConnections();
-          const assemblies = assemblyIDs.map(id => this.getAssembly(id));
-          const uploadsAssemblies = {
-            ...this.getPluginState().uploadsAssemblies,
-          };
-          delete uploadsAssemblies[uploadID];
-          this.setPluginState({
-            uploadsAssemblies,
-          });
           this.uppy.addResultData(uploadID, {
-            transloadit: assemblies,
+            transloadit: [this.assembly.status],
           });
         });
       },
     });
     Object.defineProperty(this, _closeAssemblyIfExists, {
       writable: true,
-      value: assemblyID => {
-        var _this$activeAssemblie;
-        if (!assemblyID) return;
-        (_this$activeAssemblie = this.activeAssemblies[assemblyID]) == null || _this$activeAssemblie.close();
+      value: () => {
+        var _this$assembly;
+        (_this$assembly = this.assembly) == null || _this$assembly.close();
       },
     });
     Object.defineProperty(this, _onError, {
       writable: true,
       value: err => {
+        _classPrivateFieldLooseBase(this, _closeAssemblyIfExists)[_closeAssemblyIfExists]();
         this.client.submitError(err).catch(sendErrorToConsole(err));
       },
     });
     Object.defineProperty(this, _onTusError, {
       writable: true,
-      value: (file, err) => {
-        var _file$transloadit2, _err$message;
-        _classPrivateFieldLooseBase(this, _closeAssemblyIfExists)[_closeAssemblyIfExists](
-          file == null || (_file$transloadit2 = file.transloadit) == null ? void 0 : _file$transloadit2.assembly,
-        );
+      value: (_, err) => {
+        var _err$message;
+        _classPrivateFieldLooseBase(this, _closeAssemblyIfExists)[_closeAssemblyIfExists]();
         if (err != null && (_err$message = err.message) != null && _err$message.startsWith("tus: ")) {
           var _originalRequest;
           const endpoint = (_originalRequest = err.originalRequest) == null
@@ -412,8 +355,6 @@ export default class Transloadit extends BasePlugin {
       errorReporting: this.opts.errorReporting,
       rateLimitedQueue: _classPrivateFieldLooseBase(this, _rateLimitedQueue)[_rateLimitedQueue],
     });
-    this.activeAssemblies = {};
-    this.assemblyWatchers = {};
     this.completedFiles = Object.create(null);
   }
   install() {
@@ -439,8 +380,6 @@ export default class Transloadit extends BasePlugin {
     this.uppy.on("restore:get-data", _classPrivateFieldLooseBase(this, _getPersistentData)[_getPersistentData]);
     this.uppy.on("restored", _classPrivateFieldLooseBase(this, _onRestored)[_onRestored]);
     this.setPluginState({
-      assemblies: {},
-      uploadsAssemblies: {},
       files: {},
       results: [],
     });
@@ -474,16 +413,13 @@ export default class Transloadit extends BasePlugin {
       },
     });
   }
-  getAssembly(id) {
-    const {
-      assemblies,
-    } = this.getPluginState();
-    return assemblies[id];
+  getAssembly() {
+    return this.assembly.status;
   }
   getAssemblyFiles(assemblyID) {
     return this.uppy.getFiles().filter(file => {
-      var _file$transloadit3;
-      return (file == null || (_file$transloadit3 = file.transloadit) == null ? void 0 : _file$transloadit3.assembly)
+      var _file$transloadit2;
+      return (file == null || (_file$transloadit2 = file.transloadit) == null ? void 0 : _file$transloadit2.assembly)
         === assemblyID;
     });
   }
@@ -557,44 +493,27 @@ function _attachAssemblyMetadata2(file, status) {
   }
   return newFile;
 }
-function _createAssembly2(fileIDs, uploadID, assemblyOptions) {
+function _createAssembly2(fileIDs, assemblyOptions) {
   this.uppy.log("[Transloadit] Create Assembly");
   return this.client.createAssembly({
     ...assemblyOptions,
     expectedFiles: fileIDs.length,
   }).then(async newAssembly => {
-    const files = this.uppy.getFiles().filter(_ref2 => {
+    const files = this.uppy.getFiles().filter(_ref => {
       let {
         id,
-      } = _ref2;
+      } = _ref;
       return fileIDs.includes(id);
     });
-    if (files.length !== fileIDs.length) {
-      if (files.length === 0) {
-        await this.client.cancelAssembly(newAssembly);
-        return null;
-      }
-      await this.client.updateNumberOfFilesInAssembly(newAssembly, files.length);
+    if (files.length === 0) {
+      await this.client.cancelAssembly(newAssembly);
+      return null;
     }
     const assembly = new Assembly(newAssembly, _classPrivateFieldLooseBase(this, _rateLimitedQueue)[_rateLimitedQueue]);
     const {
       status,
     } = assembly;
     const assemblyID = status.assembly_id;
-    const {
-      assemblies,
-      uploadsAssemblies,
-    } = this.getPluginState();
-    this.setPluginState({
-      assemblies: {
-        ...assemblies,
-        [assemblyID]: status,
-      },
-      uploadsAssemblies: {
-        ...uploadsAssemblies,
-        [uploadID]: [...uploadsAssemblies[uploadID], assemblyID],
-      },
-    });
     const updatedFiles = {};
     files.forEach(file => {
       updatedFiles[file.id] = _classPrivateFieldLooseBase(this, _attachAssemblyMetadata)[_attachAssemblyMetadata](
@@ -608,19 +527,6 @@ function _createAssembly2(fileIDs, uploadID, assemblyOptions) {
         ...updatedFiles,
       },
     });
-    const fileRemovedHandler = fileRemoved => {
-      var _assembly$status;
-      if (((_assembly$status = assembly.status) == null ? void 0 : _assembly$status.ok) === "ASSEMBLY_COMPLETED") {
-        this.uppy.off("file-removed", fileRemovedHandler);
-        return;
-      }
-      if (fileRemoved.id in updatedFiles) {
-        delete updatedFiles[fileRemoved.id];
-        const nbOfRemainingFiles = Object.keys(updatedFiles).length;
-        this.client.updateNumberOfFilesInAssembly(newAssembly, nbOfRemainingFiles).catch(() => {});
-      }
-    };
-    this.uppy.on("file-removed", fileRemovedHandler);
     this.uppy.emit("transloadit:assembly-created", status, fileIDs);
     this.uppy.log(`[Transloadit] Created Assembly ${assemblyID}`);
     return assembly;
@@ -637,7 +543,7 @@ function _createAssembly2(fileIDs, uploadID, assemblyOptions) {
     throw wrapped;
   });
 }
-function _createAssemblyWatcher2(idOrArrayOfIds, uploadID) {
+function _createAssemblyWatcher2(idOrArrayOfIds) {
   const ids = Array.isArray(idOrArrayOfIds) ? idOrArrayOfIds : [idOrArrayOfIds];
   const watcher = new AssemblyWatcher(this.uppy, ids);
   watcher.on("assembly-complete", id => {
@@ -662,7 +568,7 @@ function _createAssemblyWatcher2(idOrArrayOfIds, uploadID) {
     });
     this.uppy.emit("error", error);
   });
-  this.assemblyWatchers[uploadID] = watcher;
+  _classPrivateFieldLooseBase(this, _watcher)[_watcher] = watcher;
 }
 function _shouldWaitAfterUpload2() {
   return this.opts.waitForEncoding || this.opts.waitForMetadata;
@@ -708,7 +614,7 @@ function _onFileUploadComplete2(assemblyId, uploadedFile) {
       },
     },
   });
-  this.uppy.emit("transloadit:upload", uploadedFile, this.getAssembly(assemblyId));
+  this.uppy.emit("transloadit:upload", uploadedFile, this.getAssembly());
 }
 function _onResult2(assemblyId, stepName, result) {
   const state = this.getPluginState();
@@ -723,19 +629,12 @@ function _onResult2(assemblyId, stepName, result) {
   this.setPluginState({
     results: [...state.results, entry],
   });
-  this.uppy.emit("transloadit:result", stepName, result, this.getAssembly(assemblyId));
+  this.uppy.emit("transloadit:result", stepName, result, this.getAssembly());
 }
 function _onAssemblyFinished2(status) {
   const url = status.assembly_ssl_url;
   this.client.getAssemblyStatus(url).then(finalStatus => {
-    const assemblyId = finalStatus.assembly_id;
-    const state = this.getPluginState();
-    this.setPluginState({
-      assemblies: {
-        ...state.assemblies,
-        [assemblyId]: finalStatus,
-      },
-    });
+    this.assembly.status = finalStatus;
     this.uppy.emit("transloadit:complete", finalStatus);
   });
 }
@@ -748,17 +647,9 @@ function _connectAssembly2(assembly) {
     status,
   } = assembly;
   const id = status.assembly_id;
-  this.activeAssemblies[id] = assembly;
+  this.assembly = assembly;
   assembly.on("status", newStatus => {
-    const {
-      assemblies,
-    } = this.getPluginState();
-    this.setPluginState({
-      assemblies: {
-        ...assemblies,
-        [id]: newStatus,
-      },
-    });
+    this.assembly.status = newStatus;
   });
   assembly.on("upload", file => {
     _classPrivateFieldLooseBase(this, _onFileUploadComplete)[_onFileUploadComplete](id, file);

* 4.x: (38 commits)
  docs: assume tree-shaking bundler is the most common case (#5160)
  @uppy/core: remove `reason` (#5159)
  Release: uppy@4.0.0-beta.9 (#5194)
  Release: uppy@3.25.5 (#5193)
  @uppy/companion: remove `chalk` from dependencies (#5178)
  @uppy/transloadit: do not cancel assembly when removing all files (#5191)
  @uppy/xhr-upload: fix regression for lowercase HTTP methods (#5179)
  meta: improve changelog generator (#5190)
  Release: uppy@4.0.0-beta.8 (#5189)
  examples: add SvelteKit example (#5181)
  @uppy/companion: fix missing `await`
  Release: uppy@3.25.4 (#5188)
  @uppy/svelte: do not attempt removing plugin before it's created (#5186)
  Update facebook.mdx
  fixup! @uppy/tus: fix no headers passed to companion if argument is a function (#5182)
  @uppy/core: resolve some (breaking) TODOs (#4824)
  @uppy/tus: fix no headers passed to companion if argument is a function (#5182)
  @uppy/companion: fix google drive gsuite export large size (#5144)
  @uppy/companion: encode `uploadId` (#5168)
  @uppy/companion: bump `express-session` (#5177)
  ...
@Murderlon Murderlon marked this pull request as ready for review May 29, 2024 11:08
@Murderlon Murderlon requested review from mifi and aduh95 May 29, 2024 11:08
cy.wait(['@createAssemblies']).then(() => {
// eslint-disable-next-line
// @ts-ignore fix me
expect(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was this removed? shouldn't we still verify that it polls the assembly and stops polling when assembly is cancelled?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what this test does:

it('should close assembly when cancelled', () => {
cy.intercept({ path: '/resumable/*', method: 'POST' }).as('tusCreate')
cy.intercept({ path: '/assemblies', method: 'POST' }).as('createAssemblies')
cy.intercept({ path: '/assemblies/*', method: 'DELETE' }).as('delete')
cy.intercept({ path: '/resumable/files/*', method: 'DELETE' }).as(
'tusDelete',
)
cy.window().then(({ uppy }) => {
cy.get('@file-input').selectFile(
[
'cypress/fixtures/images/cat.jpg',
'cypress/fixtures/images/traffic.jpg',
'cypress/fixtures/images/car.jpg',
],
{ force: true },
)
cy.get('.uppy-StatusBar-actionBtn--upload').click()
cy.wait(['@createAssemblies', '@tusCreate']).then(() => {
const plugin = getPlugin(uppy)
expect(plugin.assembly.closed).to.be.false
uppy.cancelAll()
cy.wait(['@delete', '@tusDelete']).then(() => {
expect(plugin.assembly.closed).to.be.true
})
})
})
})

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean check that the poll interval has been cleared as in the previous test

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poll interval is only meant to be a fallback for server-sent events. I think this is fine, assembly also can't be closed without resetting everything.

packages/@uppy/transloadit/src/index.ts Show resolved Hide resolved
packages/@uppy/transloadit/src/index.ts Outdated Show resolved Hide resolved
packages/@uppy/transloadit/src/index.ts Show resolved Hide resolved
packages/@uppy/transloadit/src/index.ts Outdated Show resolved Hide resolved
packages/@uppy/transloadit/src/index.ts Outdated Show resolved Hide resolved
Comment on lines +225 to +231
const sendErrorToConsole = (originalErr: Error) => (err: Error) => {
const error = new ErrorWithCause('Failed to send error to the client', {
cause: err,
})
// eslint-disable-next-line no-console
console.error(error, originalErr)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why move this? That seems to artificially increase the diff / polute the git blame with no clear benefit

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Half of the diff is from functions moved from the deleted file AssemblyOptions. I moved to rest to have all functions in a single place instead of between types and variables. slightly increased diff, but worth it.

Comment on lines +259 to +263
const COMPANION_URL = 'https://api2.transloadit.com/companion'
// Regex matching acceptable postMessage() origins for authentication feedback from companion.
const COMPANION_ALLOWED_HOSTS = /\.transloadit\.com$/
// Regex used to check if a Companion address is run by Transloadit.
const TL_COMPANION = /https?:\/\/api2(?:-\w+)?\.transloadit\.com\/companion/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

@@ -251,9 +275,9 @@ export default class Transloadit<

client: Client<M, B>

activeAssemblies: Record<string, Assembly>
assembly: Assembly
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to keep this public?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need it in tests. And since we no longer save the assembly response in state but inside Assembly, I think it's fine to allow people to access it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe let's mark it as readonly, so it's clear it's an internal field?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I do, then I get an error everywhere where we actually set assembly.

packages/@uppy/transloadit/src/index.ts Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants