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/companion: bump Node.js version support matrix #5035

Merged
merged 32 commits into from
Apr 22, 2024

Conversation

aduh95
Copy link
Contributor

@aduh95 aduh95 commented Mar 27, 2024

Node.js 14.x and 16.x are EOL, and it's about time we also support Node.js 20.x. I'm not including support for Node.js 21.x which will be EOL in June.

@aduh95 aduh95 added the 4.0 For the 4.0 major version label Mar 27, 2024
Copy link
Contributor

github-actions bot commented Mar 27, 2024

Diff output files
diff --git a/packages/@uppy/aws-s3/lib/index.js b/packages/@uppy/aws-s3/lib/index.js
index d6aa397..035736b 100644
--- a/packages/@uppy/aws-s3/lib/index.js
+++ b/packages/@uppy/aws-s3/lib/index.js
@@ -1,3 +1,4 @@
+let _Symbol$for;
 function _classPrivateFieldLooseBase(receiver, privateKey) {
   if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {
     throw new TypeError("attempted to use private field on non-instance");
@@ -76,6 +77,7 @@ var _upload = _classPrivateFieldLooseKey("upload");
 var _setCompanionHeaders = _classPrivateFieldLooseKey("setCompanionHeaders");
 var _setResumableUploadsCapability = _classPrivateFieldLooseKey("setResumableUploadsCapability");
 var _resetResumableCapability = _classPrivateFieldLooseKey("resetResumableCapability");
+_Symbol$for = Symbol.for("uppy test: getClient");
 export default class AwsS3Multipart extends BasePlugin {
   constructor(uppy, opts) {
     var _rateLimitedQueue;
@@ -234,7 +236,7 @@ export default class AwsS3Multipart extends BasePlugin {
     this.uploaderEvents = Object.create(null);
     this.uploaderSockets = Object.create(null);
   }
-  [Symbol.for("uppy test: getClient")]() {
+  [_Symbol$for]() {
     return _classPrivateFieldLooseBase(this, _client)[_client];
   }
   setOptions(newOptions) {
diff --git a/packages/@uppy/companion-client/lib/RequestClient.js b/packages/@uppy/companion-client/lib/RequestClient.js
index 5936b35..daa049e 100644
--- a/packages/@uppy/companion-client/lib/RequestClient.js
+++ b/packages/@uppy/companion-client/lib/RequestClient.js
@@ -1,3 +1,4 @@
+let _Symbol$for;
 function _classPrivateFieldLooseBase(receiver, privateKey) {
   if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {
     throw new TypeError("attempted to use private field on non-instance");
@@ -65,6 +66,7 @@ var _companionHeaders = _classPrivateFieldLooseKey("companionHeaders");
 var _getUrl = _classPrivateFieldLooseKey("getUrl");
 var _requestSocketToken = _classPrivateFieldLooseKey("requestSocketToken");
 var _awaitRemoteFileUpload = _classPrivateFieldLooseKey("awaitRemoteFileUpload");
+_Symbol$for = Symbol.for("uppy test: getCompanionHeaders");
 export default class RequestClient {
   constructor(uppy, opts) {
     Object.defineProperty(this, _awaitRemoteFileUpload, {
@@ -108,7 +110,7 @@ export default class RequestClient {
   setCompanionHeaders(headers) {
     _classPrivateFieldLooseBase(this, _companionHeaders)[_companionHeaders] = headers;
   }
-  [Symbol.for("uppy test: getCompanionHeaders")]() {
+  [_Symbol$for]() {
     return _classPrivateFieldLooseBase(this, _companionHeaders)[_companionHeaders];
   }
   get hostname() {
diff --git a/packages/@uppy/companion-client/lib/Socket.js b/packages/@uppy/companion-client/lib/Socket.js
index c4fdfe9..f4c26a9 100644
--- a/packages/@uppy/companion-client/lib/Socket.js
+++ b/packages/@uppy/companion-client/lib/Socket.js
@@ -1,3 +1,4 @@
+let _Symbol$for, _Symbol$for2;
 function _classPrivateFieldLooseBase(receiver, privateKey) {
   if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {
     throw new TypeError("attempted to use private field on non-instance");
@@ -14,6 +15,8 @@ var _emitter = _classPrivateFieldLooseKey("emitter");
 var _isOpen = _classPrivateFieldLooseKey("isOpen");
 var _socket = _classPrivateFieldLooseKey("socket");
 var _handleMessage = _classPrivateFieldLooseKey("handleMessage");
+_Symbol$for = Symbol.for("uppy test: getSocket");
+_Symbol$for2 = Symbol.for("uppy test: getQueued");
 export default class UppySocket {
   constructor(opts) {
     Object.defineProperty(this, _queued, {
@@ -51,10 +54,10 @@ export default class UppySocket {
   get isOpen() {
     return _classPrivateFieldLooseBase(this, _isOpen)[_isOpen];
   }
-  [Symbol.for("uppy test: getSocket")]() {
+  [_Symbol$for]() {
     return _classPrivateFieldLooseBase(this, _socket)[_socket];
   }
-  [Symbol.for("uppy test: getQueued")]() {
+  [_Symbol$for2]() {
     return _classPrivateFieldLooseBase(this, _queued)[_queued];
   }
   open() {
diff --git a/packages/@uppy/companion/lib/companion.d.ts b/packages/@uppy/companion/lib/companion.d.ts
index 626e76a..3802991 100644
--- a/packages/@uppy/companion/lib/companion.d.ts
+++ b/packages/@uppy/companion/lib/companion.d.ts
@@ -1,6 +1,5 @@
 /// <reference types="node" />
 /// <reference types="node/http" />
-/// <reference types="got/dist/source/core/utils/timed-out" />
 export namespace errors {
     export { ProviderApiError };
     export { ProviderUserError };
diff --git a/packages/@uppy/companion/lib/companion.js b/packages/@uppy/companion/lib/companion.js
index 0e490aa..468315f 100644
--- a/packages/@uppy/companion/lib/companion.js
+++ b/packages/@uppy/companion/lib/companion.js
@@ -71,10 +71,7 @@ module.exports.app = (optionsArg = {}) => {
   if (customProviders) {
     providerManager.addCustomProviders(customProviders, providers, grantConfig);
   }
-  const getAuthProvider = (providerName) => {
-    var _a;
-    return (_a = providers[providerName]) === null || _a === void 0 ? void 0 : _a.authProvider;
-  };
+  const getAuthProvider = (providerName) => providers[providerName]?.authProvider;
   providerManager.addProviderOptions(options, grantConfig, getAuthProvider);
   // mask provider secrets from log messages
   logger.setMaskables(getMaskableSecrets(options));
@@ -212,12 +209,11 @@ module.exports.app = (optionsArg = {}) => {
       // we would query based on parameters
       const { key, secret } = options.providerOptions[providerName];
       function getRedirectUri() {
-        var _a;
         const authProvider = getAuthProvider(providerName);
         if (!isOAuthProvider(authProvider)) {
           return undefined;
         }
-        return (_a = grantConfig[authProvider]) === null || _a === void 0 ? void 0 : _a.redirect_uri;
+        return grantConfig[authProvider]?.redirect_uri;
       }
       res.send({
         credentials: {
diff --git a/packages/@uppy/companion/lib/config/companion.js b/packages/@uppy/companion/lib/config/companion.js
index 257feca..400d9bc 100644
--- a/packages/@uppy/companion/lib/config/companion.js
+++ b/packages/@uppy/companion/lib/config/companion.js
@@ -42,7 +42,7 @@ function getMaskableSecrets(companionOptions) {
       }
     });
   }
-  if (s3 === null || s3 === void 0 ? void 0 : s3.secret) {
+  if (s3?.secret) {
     secrets.push(s3.secret);
   }
   return secrets;
diff --git a/packages/@uppy/companion/lib/server/Uploader.js b/packages/@uppy/companion/lib/server/Uploader.js
index e2185a6..de1d9db 100644
--- a/packages/@uppy/companion/lib/server/Uploader.js
+++ b/packages/@uppy/companion/lib/server/Uploader.js
@@ -1,41 +1,17 @@
 "use strict";
-var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function(receiver, state, kind, f) {
-  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
-  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) {
-    throw new TypeError("Cannot read private member from an object whose class did not declare it");
-  }
-  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
-};
-var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function(receiver, state, value, kind, f) {
-  if (kind === "m") throw new TypeError("Private method is not writable");
-  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
-  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) {
-    throw new TypeError("Cannot write private member to an object whose class did not declare it");
-  }
-  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
-};
-var _Uploader_instances,
-  _Uploader_uploadState,
-  _Uploader_canceled,
-  _Uploader_emitSuccess,
-  _Uploader_emitError,
-  _Uploader_uploadTus,
-  _Uploader_uploadMultipart,
-  _Uploader_uploadS3Multipart;
 Object.defineProperty(exports, "__esModule", { value: true });
 // eslint-disable-next-line max-classes-per-file
 const tus = require("tus-js-client");
 const { randomUUID } = require("node:crypto");
 const validator = require("validator");
-const got = require("got").default;
 const { pipeline: pipelineCb } = require("node:stream");
 const { join } = require("node:path");
 const fs = require("node:fs");
 const { promisify } = require("node:util");
-const FormData = require("form-data");
 const throttle = require("lodash/throttle");
 const { Upload } = require("@aws-sdk/lib-storage");
 const { rfc2047EncodeMetadata, getBucket } = require("./helpers/utils");
+const got = require("./got");
 // TODO move to `require('streams/promises').pipeline` when dropping support for Node.js 14.x.
 const pipeline = promisify(pipelineCb);
 const { createReadStream, createWriteStream, ReadStream } = fs;
@@ -144,6 +120,19 @@ const states = {
   paused: "paused",
   done: "done",
 };
+class StreamableBlob {
+  #stream;
+  constructor(stream) {
+    this.#stream = stream;
+  }
+  stream() {
+    return this.#stream;
+  }
+  // eslint-disable-next-line class-methods-use-this
+  get [Symbol.toStringTag]() {
+    return "File";
+  }
+}
 class Uploader {
   /**
    * Uploads file to destination based on the supplied protocol (tus, s3-multipart, multipart)
@@ -169,19 +158,6 @@ class Uploader {
    * @param {UploaderOptions} options
    */
   constructor(options) {
-    _Uploader_instances.add(this);
-    _Uploader_uploadState.set(this, states.idle);
-    _Uploader_canceled.set(this, false);
-    this.throttledEmitProgress = throttle(
-      (dataToEmit) => {
-        const { bytesUploaded, bytesTotal, progress } = dataToEmit.payload;
-        logger.debug(`${bytesUploaded} ${bytesTotal} ${progress}%`, "uploader.total.progress", this.shortToken);
-        this.saveState(dataToEmit);
-        emitter().emit(this.token, dataToEmit);
-      },
-      1000,
-      { trailing: false },
-    );
     validateOptions(options);
     this.options = options;
     this.token = randomUUID();
@@ -198,20 +174,20 @@ class Uploader {
     if (this.options.protocol === PROTOCOLS.tus) {
       emitter().on(`pause:${this.token}`, () => {
         logger.debug("Received from client: pause", "uploader", this.shortToken);
-        if (__classPrivateFieldGet(this, _Uploader_uploadState, "f") !== states.uploading) {
+        if (this.#uploadState !== states.uploading) {
           return;
         }
-        __classPrivateFieldSet(this, _Uploader_uploadState, states.paused, "f");
+        this.#uploadState = states.paused;
         if (this.tus) {
           this.tus.abort();
         }
       });
       emitter().on(`resume:${this.token}`, () => {
         logger.debug("Received from client: resume", "uploader", this.shortToken);
-        if (__classPrivateFieldGet(this, _Uploader_uploadState, "f") !== states.paused) {
+        if (this.#uploadState !== states.paused) {
           return;
         }
-        __classPrivateFieldSet(this, _Uploader_uploadState, states.uploading, "f");
+        this.#uploadState = states.uploading;
         if (this.tus) {
           this.tus.start();
         }
@@ -223,12 +199,14 @@ class Uploader {
         const shouldTerminate = !!this.tus.url;
         this.tus.abort(shouldTerminate).catch(() => {});
       }
-      __classPrivateFieldSet(this, _Uploader_canceled, true, "f");
+      this.#canceled = true;
       this.abortReadStream(new Error("Canceled"));
     });
   }
+  #uploadState = states.idle;
+  #canceled = false;
   abortReadStream(err) {
-    __classPrivateFieldSet(this, _Uploader_uploadState, states.done, "f");
+    this.#uploadState = states.done;
     if (this.readStream) {
       this.readStream.destroy(err);
     }
@@ -239,17 +217,11 @@ class Uploader {
     const protocol = this.options.protocol || PROTOCOLS.multipart;
     switch (protocol) {
       case PROTOCOLS.multipart:
-        return __classPrivateFieldGet(this, _Uploader_instances, "m", _Uploader_uploadMultipart).call(
-          this,
-          this.readStream,
-        );
+        return this.#uploadMultipart(this.readStream);
       case PROTOCOLS.s3Multipart:
-        return __classPrivateFieldGet(this, _Uploader_instances, "m", _Uploader_uploadS3Multipart).call(
-          this,
-          this.readStream,
-        );
+        return this.#uploadS3Multipart(this.readStream);
       case PROTOCOLS.tus:
-        return __classPrivateFieldGet(this, _Uploader_instances, "m", _Uploader_uploadTus).call(this, this.readStream);
+        return this.#uploadTus(this.readStream);
       default:
         throw new Error("Invalid protocol");
     }
@@ -281,13 +253,13 @@ class Uploader {
    */
   async uploadStream(stream) {
     try {
-      if (__classPrivateFieldGet(this, _Uploader_uploadState, "f") !== states.idle) {
+      if (this.#uploadState !== states.idle) {
         throw new Error("Can only start an upload in the idle state");
       }
       if (this.readStream) {
         throw new Error("Already uploading");
       }
-      __classPrivateFieldSet(this, _Uploader_uploadState, states.uploading, "f");
+      this.#uploadState = states.uploading;
       this.readStream = stream;
       if (this._needDownloadFirst()) {
         logger.debug("need to download the whole file first", "controller.get.provider.size", this.shortToken);
@@ -296,7 +268,7 @@ class Uploader {
         // The stream will then typically come from a "Transfer-Encoding: chunked" response
         await this._downloadStreamAsFile(this.readStream);
       }
-      if (__classPrivateFieldGet(this, _Uploader_uploadState, "f") !== states.uploading) {
+      if (this.#uploadState !== states.uploading) {
         return undefined;
       }
       const { url, extraData } = await Promise.race([
@@ -306,7 +278,7 @@ class Uploader {
       ]);
       return { url, extraData };
     } finally {
-      __classPrivateFieldSet(this, _Uploader_uploadState, states.done, "f");
+      this.#uploadState = states.done;
       logger.debug("cleanup", this.shortToken);
       if (this.readStream && !this.readStream.destroyed) {
         this.readStream.destroy();
@@ -330,14 +302,14 @@ class Uploader {
         return;
       }
       const { url, extraData } = ret;
-      __classPrivateFieldGet(this, _Uploader_instances, "m", _Uploader_emitSuccess).call(this, url, extraData);
+      this.#emitSuccess(url, extraData);
     } catch (err) {
-      if (__classPrivateFieldGet(this, _Uploader_canceled, "f")) {
+      if (this.#canceled) {
         logger.error("Aborted upload", "uploader.aborted", this.shortToken);
         return;
       }
       logger.error(err, "uploader.error", this.shortToken);
-      __classPrivateFieldGet(this, _Uploader_instances, "m", _Uploader_emitError).call(this, err);
+      this.#emitError(err);
     } finally {
       emitter().removeAllListeners(`pause:${this.token}`);
       emitter().removeAllListeners(`resume:${this.token}`);
@@ -433,6 +405,16 @@ class Uploader {
       EX: keyExpirySec,
     });
   }
+  throttledEmitProgress = throttle(
+    (dataToEmit) => {
+      const { bytesUploaded, bytesTotal, progress } = dataToEmit.payload;
+      logger.debug(`${bytesUploaded} ${bytesTotal} ${progress}%`, "uploader.total.progress", this.shortToken);
+      this.saveState(dataToEmit);
+      emitter().emit(this.token, dataToEmit);
+    },
+    1000,
+    { trailing: false },
+  );
   /**
    * @param {number} [bytesUploaded]
    * @param {number | null} [bytesTotalIn]
@@ -451,7 +433,7 @@ class Uploader {
       percentage = Math.min(Math.max(0, (combinedBytes / bytesTotal) * 100), 100);
     }
     const formattedPercentage = percentage.toFixed(2);
-    if (__classPrivateFieldGet(this, _Uploader_uploadState, "f") !== states.uploading) {
+    if (this.#uploadState !== states.uploading) {
       return;
     }
     const payload = { progress: formattedPercentage, bytesUploaded: combinedBytes, bytesTotal };
@@ -463,19 +445,22 @@ class Uploader {
     // flooding will cause reduced performance and possibly network issues
     this.throttledEmitProgress(dataToEmit);
   }
-}
-_Uploader_uploadState = new WeakMap(),
-  _Uploader_canceled = new WeakMap(),
-  _Uploader_instances = new WeakSet(),
-  _Uploader_emitSuccess = function _Uploader_emitSuccess(url, extraData) {
+  /**
+   * @param {string} url
+   * @param {object} extraData
+   */
+  #emitSuccess(url, extraData) {
     const emitData = {
       action: "success",
       payload: { ...extraData, complete: true, url },
     };
     this.saveState(emitData);
     emitter().emit(this.token, emitData);
-  },
-  _Uploader_emitError = function _Uploader_emitError(err) {
+  }
+  /**
+   * @param {Error} err
+   */
+  #emitError(err) {
     // delete stack to avoid sending server info to client
     // todo remove also extraData from serializedErr in next major,
     // see PR discussion https://github.com/transloadit/uppy/pull/3832
@@ -487,70 +472,68 @@ _Uploader_uploadState = new WeakMap(),
     };
     this.saveState(dataToEmit);
     emitter().emit(this.token, dataToEmit);
-  },
-  _Uploader_uploadTus =
-    /**
-     * start the tus upload
-     *
-     * @param {any} stream
-     */
-    async function _Uploader_uploadTus(stream) {
-      const uploader = this;
-      const isFileStream = stream instanceof ReadStream;
-      // chunkSize needs to be a finite value if the stream is not a file stream (fs.createReadStream)
-      // https://github.com/tus/tus-js-client/blob/4479b78032937ac14da9b0542e489ac6fe7e0bc7/lib/node/fileReader.js#L50
-      const chunkSize = this.options.chunkSize || (isFileStream ? Infinity : 50e6);
-      return new Promise((resolve, reject) => {
-        const tusOptions = {
-          endpoint: this.options.endpoint,
-          uploadUrl: this.options.uploadUrl,
-          uploadLengthDeferred: !isFileStream,
-          retryDelays: [0, 1000, 3000, 5000],
-          uploadSize: isFileStream ? this.size : undefined,
-          chunkSize,
-          headers: headerSanitize(this.options.headers),
-          addRequestId: true,
-          metadata: {
-            // file name and type as required by the tusd tus server
-            // https://github.com/tus/tusd/blob/5b376141903c1fd64480c06dde3dfe61d191e53d/unrouted_handler.go#L614-L646
-            filename: this.uploadFileName,
-            filetype: this.options.metadata.type,
-            ...this.options.metadata,
-          },
-          /**
-           * @param {Error} error
-           */
-          onError(error) {
-            logger.error(error, "uploader.tus.error");
-            // deleting tus originalRequest field because it uses the same http-agent
-            // as companion, and this agent may contain sensitive request details (e.g headers)
-            // previously made to providers. Deleting the field would prevent it from getting leaked
-            // to the frontend etc.
-            // @ts-ignore
-            // eslint-disable-next-line no-param-reassign
-            delete error.originalRequest;
-            // @ts-ignore
-            // eslint-disable-next-line no-param-reassign
-            delete error.originalResponse;
-            reject(error);
-          },
-          /**
-           * @param {number} [bytesUploaded]
-           * @param {number} [bytesTotal]
-           */
-          onProgress(bytesUploaded, bytesTotal) {
-            uploader.onProgress(bytesUploaded, bytesTotal);
-          },
-          onSuccess() {
-            resolve({ url: uploader.tus.url });
-          },
-        };
-        this.tus = new tus.Upload(stream, tusOptions);
-        this.tus.start();
-      });
-    },
-  _Uploader_uploadMultipart = async function _Uploader_uploadMultipart(stream) {
-    var _a, _b;
+  }
+  /**
+   * start the tus upload
+   *
+   * @param {any} stream
+   */
+  async #uploadTus(stream) {
+    const uploader = this;
+    const isFileStream = stream instanceof ReadStream;
+    // chunkSize needs to be a finite value if the stream is not a file stream (fs.createReadStream)
+    // https://github.com/tus/tus-js-client/blob/4479b78032937ac14da9b0542e489ac6fe7e0bc7/lib/node/fileReader.js#L50
+    const chunkSize = this.options.chunkSize || (isFileStream ? Infinity : 50e6);
+    return new Promise((resolve, reject) => {
+      const tusOptions = {
+        endpoint: this.options.endpoint,
+        uploadUrl: this.options.uploadUrl,
+        uploadLengthDeferred: !isFileStream,
+        retryDelays: [0, 1000, 3000, 5000],
+        uploadSize: isFileStream ? this.size : undefined,
+        chunkSize,
+        headers: headerSanitize(this.options.headers),
+        addRequestId: true,
+        metadata: {
+          // file name and type as required by the tusd tus server
+          // https://github.com/tus/tusd/blob/5b376141903c1fd64480c06dde3dfe61d191e53d/unrouted_handler.go#L614-L646
+          filename: this.uploadFileName,
+          filetype: this.options.metadata.type,
+          ...this.options.metadata,
+        },
+        /**
+         * @param {Error} error
+         */
+        onError(error) {
+          logger.error(error, "uploader.tus.error");
+          // deleting tus originalRequest field because it uses the same http-agent
+          // as companion, and this agent may contain sensitive request details (e.g headers)
+          // previously made to providers. Deleting the field would prevent it from getting leaked
+          // to the frontend etc.
+          // @ts-ignore
+          // eslint-disable-next-line no-param-reassign
+          delete error.originalRequest;
+          // @ts-ignore
+          // eslint-disable-next-line no-param-reassign
+          delete error.originalResponse;
+          reject(error);
+        },
+        /**
+         * @param {number} [bytesUploaded]
+         * @param {number} [bytesTotal]
+         */
+        onProgress(bytesUploaded, bytesTotal) {
+          uploader.onProgress(bytesUploaded, bytesTotal);
+        },
+        onSuccess() {
+          resolve({ url: uploader.tus.url });
+        },
+      };
+      this.tus = new tus.Upload(stream, tusOptions);
+      this.tus.start();
+    });
+  }
+  async #uploadMultipart(stream) {
     if (!this.options.endpoint) {
       throw new Error("No multipart endpoint set");
     }
@@ -575,14 +558,14 @@ _Uploader_uploadState = new WeakMap(),
       headers: headerSanitize(this.options.headers),
     };
     if (this.options.useFormData) {
-      // todo refactor once upgraded to got 12
       const formData = new FormData();
       Object.entries(this.options.metadata).forEach(([key, value]) => formData.append(key, value));
-      formData.append(this.options.fieldname, stream, {
-        filename: this.uploadFileName,
-        contentType: this.options.metadata.type,
-        knownLength: this.size,
-      });
+      formData.append(
+        this.options.fieldname,
+        // @ts-expect-error Our StreamableBlob is actually spec compliant enough for our purpose
+        new StreamableBlob(stream),
+        this.uploadFileName,
+      );
       reqOptions.body = formData;
     } else {
       reqOptions.headers["content-length"] = this.size;
@@ -590,7 +573,7 @@ _Uploader_uploadState = new WeakMap(),
     }
     try {
       const httpMethod = (this.options.httpMethod || "").toUpperCase() === "PUT" ? "put" : "post";
-      const runRequest = got[httpMethod];
+      const runRequest = (await got)[httpMethod];
       const response = await runRequest(url, reqOptions);
       if (bytesUploaded !== this.size) {
         const errMsg = `uploaded only ${bytesUploaded} of ${this.size} with status: ${response.statusCode}`;
@@ -599,7 +582,7 @@ _Uploader_uploadState = new WeakMap(),
       }
       let bodyURL = null;
       try {
-        bodyURL = (_a = JSON.parse(response.body)) === null || _a === void 0 ? void 0 : _a.url;
+        bodyURL = JSON.parse(response.body)?.url;
       } catch {
         // response.body can be undefined or an empty string
         // in that case we ignore and continue.
@@ -610,63 +593,63 @@ _Uploader_uploadState = new WeakMap(),
       };
     } catch (err) {
       logger.error(err, "upload.multipart.error");
-      const statusCode = (_b = err.response) === null || _b === void 0 ? void 0 : _b.statusCode;
+      const statusCode = err.response?.statusCode;
       if (statusCode != null) {
         throw Object.assign(new Error(err.statusMessage), {
           extraData: getRespObj(err.response),
         });
       }
-      throw new Error("Unknown multipart upload error");
+      throw new Error("Unknown multipart upload error", { cause: err });
     }
-  },
-  _Uploader_uploadS3Multipart =
+  }
+  /**
+   * Upload the file to S3 using a Multipart upload.
+   */
+  async #uploadS3Multipart(stream) {
+    if (!this.options.s3) {
+      throw new Error("The S3 client is not configured on this companion instance.");
+    }
+    const filename = this.uploadFileName;
     /**
-     * Upload the file to S3 using a Multipart upload.
+     * @type {{client: import('@aws-sdk/client-s3').S3Client, options: Record<string, any>}}
      */
-    async function _Uploader_uploadS3Multipart(stream) {
-      if (!this.options.s3) {
-        throw new Error("The S3 client is not configured on this companion instance.");
-      }
-      const filename = this.uploadFileName;
-      /**
-       * @type {{client: import('@aws-sdk/client-s3').S3Client, options: Record<string, any>}}
-       */
-      const s3Options = this.options.s3;
-      const { client, options } = s3Options;
-      const params = {
-        Bucket: getBucket(options.bucket, null, this.options.metadata),
-        Key: options.getKey(null, filename, this.options.metadata),
-        ContentType: this.options.metadata.type,
-        Metadata: rfc2047EncodeMetadata(this.options.metadata),
-        Body: stream,
-      };
-      if (options.acl != null) {
-        params.ACL = options.acl;
-      }
-      const upload = new Upload({
-        client,
-        params,
-        // using chunkSize as partSize too, see https://github.com/transloadit/uppy/pull/3511
-        partSize: this.options.chunkSize,
-        leavePartsOnError: true, // https://github.com/aws/aws-sdk-js-v3/issues/2311
-      });
-      upload.on("httpUploadProgress", ({ loaded, total }) => {
-        this.onProgress(loaded, total);
-      });
-      const data = await upload.done();
-      return {
-        // @ts-expect-error For some reason `|| null` is not enough for TS
-        url: (data === null || data === void 0 ? void 0 : data.Location) || null,
-        extraData: {
-          response: {
-            responseText: JSON.stringify(data),
-            headers: {
-              "content-type": "application/json",
-            },
+    const s3Options = this.options.s3;
+    const { client, options } = s3Options;
+    const params = {
+      Bucket: getBucket(options.bucket, null, this.options.metadata),
+      Key: options.getKey(null, filename, this.options.metadata),
+      ContentType: this.options.metadata.type,
+      Metadata: rfc2047EncodeMetadata(this.options.metadata),
+      Body: stream,
+    };
+    if (options.acl != null) {
+      params.ACL = options.acl;
+    }
+    const upload = new Upload({
+      client,
+      params,
+      // using chunkSize as partSize too, see https://github.com/transloadit/uppy/pull/3511
+      partSize: this.options.chunkSize,
+      leavePartsOnError: true, // https://github.com/aws/aws-sdk-js-v3/issues/2311
+    });
+    upload.on("httpUploadProgress", ({ loaded, total }) => {
+      this.onProgress(loaded, total);
+    });
+    const data = await upload.done();
+    return {
+      // @ts-expect-error For some reason `|| null` is not enough for TS
+      url: data?.Location || null,
+      extraData: {
+        response: {
+          responseText: JSON.stringify(data),
+          headers: {
+            "content-type": "application/json",
           },
         },
-      };
+      },
     };
+  }
+}
 Uploader.FILE_NAME_PREFIX = "uppy-file";
 Uploader.STORAGE_PREFIX = "companion";
 module.exports = Uploader;
diff --git a/packages/@uppy/companion/lib/server/controllers/callback.js b/packages/@uppy/companion/lib/server/controllers/callback.js
index d221109..8e36049 100644
--- a/packages/@uppy/companion/lib/server/controllers/callback.js
+++ b/packages/@uppy/companion/lib/server/controllers/callback.js
@@ -27,13 +27,12 @@ const closePageHtml = (origin) => `
  * @param {Function} next
  */
 module.exports = function callback(req, res, next) {
-  var _a;
   const { providerName } = req.params;
   const grant = req.session.grant || {};
   const grantDynamic = oAuthState.getGrantDynamicFromRequest(req);
   const origin = grantDynamic.state
     && oAuthState.getFromState(grantDynamic.state, "origin", req.companion.options.secret);
-  if (!((_a = grant.response) === null || _a === void 0 ? void 0 : _a.access_token)) {
+  if (!grant.response?.access_token) {
     logger.debug(`Did not receive access token for provider ${providerName}`, null, req.id);
     logger.debug(grant.response, "callback.oauth.resp", req.id);
     return res.status(400).send(closePageHtml(origin));
diff --git a/packages/@uppy/companion/lib/server/controllers/connect.js b/packages/@uppy/companion/lib/server/controllers/connect.js
index ceac203..08e799f 100644
--- a/packages/@uppy/companion/lib/server/controllers/connect.js
+++ b/packages/@uppy/companion/lib/server/controllers/connect.js
@@ -1,6 +1,5 @@
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
-const atob = require("atob");
 const oAuthState = require("../helpers/oauth-state");
 const queryString = (params, prefix = "?") => {
   const str = new URLSearchParams(params).toString();
@@ -13,7 +12,6 @@ const queryString = (params, prefix = "?") => {
  * @param {object} res
  */
 module.exports = function connect(req, res) {
-  var _a;
   const { secret } = req.companion.options;
   const stateObj = oAuthState.generateState();
   if (req.query.state) {
@@ -31,7 +29,7 @@ module.exports = function connect(req, res) {
   // pass along grant's dynamic config (if specified for the provider in its grant config `dynamic` section)
   // this is needed for things like custom oauth domain (e.g. webdav)
   const grantDynamicConfig = Object.fromEntries(
-    ((_a = providerGrantConfig.dynamic) === null || _a === void 0 ? void 0 : _a.flatMap((dynamicKey) => {
+    providerGrantConfig.dynamic?.flatMap((dynamicKey) => {
       const queryValue = req.query[dynamicKey];
       // note: when using credentialsURL (dynamic oauth credentials), dynamic has ['key', 'secret', 'redirect_uri']
       // but in that case, query string is empty, so we need to only fetch these parameters from QS if they exist.
@@ -42,7 +40,7 @@ module.exports = function connect(req, res) {
         dynamicKey,
         queryValue,
       ]];
-    })) || [],
+    }) || [],
   );
   const { authProvider } = providerClass;
   const qs = queryString({
diff --git a/packages/@uppy/companion/lib/server/controllers/s3.js b/packages/@uppy/companion/lib/server/controllers/s3.js
index 30abe93..0776a58 100644
--- a/packages/@uppy/companion/lib/server/controllers/s3.js
+++ b/packages/@uppy/companion/lib/server/controllers/s3.js
@@ -340,8 +340,7 @@ module.exports = function s3(config) {
     if (
       !Array.isArray(parts)
       || !parts.every(part =>
-        typeof part === "object" && typeof (part === null || part === void 0 ? void 0 : part.PartNumber) === "number"
-        && typeof part.ETag === "string"
+        typeof part === "object" && typeof part?.PartNumber === "number" && typeof part.ETag === "string"
       )
     ) {
       res.status(400).json({ error: "s3: `parts` must be an array of {ETag, PartNumber} objects." });
diff --git a/packages/@uppy/companion/lib/server/controllers/url.js b/packages/@uppy/companion/lib/server/controllers/url.js
index 4ab5695..4eec4d6 100644
--- a/packages/@uppy/companion/lib/server/controllers/url.js
+++ b/packages/@uppy/companion/lib/server/controllers/url.js
@@ -24,7 +24,7 @@ const downloadURL = async (url, blockLocalIPs, traceId) => {
   // TODO in next major, rename all blockLocalIPs to allowLocalUrls and invert the bool, to make it consistent
   // see discussion https://github.com/transloadit/uppy/pull/4554/files#r1268677162
   try {
-    const protectedGot = getProtectedGot({ blockLocalIPs });
+    const protectedGot = await getProtectedGot({ blockLocalIPs });
     const stream = protectedGot.stream.get(url, { responseType: "json" });
     await prepareStream(stream);
     return stream;
diff --git a/packages/@uppy/companion/lib/server/helpers/oauth-state.js b/packages/@uppy/companion/lib/server/helpers/oauth-state.js
index ccdc572..e7704f4 100644
--- a/packages/@uppy/companion/lib/server/helpers/oauth-state.js
+++ b/packages/@uppy/companion/lib/server/helpers/oauth-state.js
@@ -1,7 +1,6 @@
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 const crypto = require("node:crypto");
-const atob = require("atob");
 const { encrypt, decrypt } = require("./utils");
 module.exports.encodeState = (state, secret) => {
   const encodedState = Buffer.from(JSON.stringify(state)).toString("base64");
@@ -20,8 +19,5 @@ module.exports.getFromState = (state, name, secret) => {
   return decodeState(state, secret)[name];
 };
 module.exports.getGrantDynamicFromRequest = (req) => {
-  var _a, _b;
-  return (_b = (_a = req.session.grant) === null || _a === void 0 ? void 0 : _a.dynamic) !== null && _b !== void 0
-    ? _b
-    : {};
+  return req.session.grant?.dynamic ?? {};
 };
diff --git a/packages/@uppy/companion/lib/server/helpers/request.d.ts b/packages/@uppy/companion/lib/server/helpers/request.d.ts
index bce47b3..ae249b4 100644
--- a/packages/@uppy/companion/lib/server/helpers/request.d.ts
+++ b/packages/@uppy/companion/lib/server/helpers/request.d.ts
@@ -25,5 +25,5 @@ export function getProtectedHttpAgent({ protocol, blockLocalIPs }: {
 };
 export function getProtectedGot({ blockLocalIPs }: {
     blockLocalIPs: any;
-}): import("got").Got;
+}): Promise<import("got", { with: { "resolution-mode": "import" } }).Got>;
 import https = require("node:https");
diff --git a/packages/@uppy/companion/lib/server/helpers/request.js b/packages/@uppy/companion/lib/server/helpers/request.js
index 5e93503..b898ce3 100644
--- a/packages/@uppy/companion/lib/server/helpers/request.js
+++ b/packages/@uppy/companion/lib/server/helpers/request.js
@@ -5,10 +5,10 @@ const http = require("node:http");
 const https = require("node:https");
 const dns = require("node:dns");
 const ipaddr = require("ipaddr.js");
-const got = require("got").default;
 const path = require("node:path");
 const contentDisposition = require("content-disposition");
 const validator = require("validator");
+const got = require("../got");
 const FORBIDDEN_IP_ADDRESS = "Forbidden IP address";
 // Example scary IPs that should return false (ipv6-to-ipv4 mapped):
 // ::FFFF:127.0.0.1
@@ -78,13 +78,13 @@ const getProtectedHttpAgent = ({ protocol, blockLocalIPs }) => {
   };
 };
 module.exports.getProtectedHttpAgent = getProtectedHttpAgent;
-function getProtectedGot({ blockLocalIPs }) {
+async function getProtectedGot({ blockLocalIPs }) {
   const HttpAgent = getProtectedHttpAgent({ protocol: "http", blockLocalIPs });
   const HttpsAgent = getProtectedHttpAgent({ protocol: "https", blockLocalIPs });
   const httpAgent = new HttpAgent();
   const httpsAgent = new HttpsAgent();
   // @ts-ignore
-  return got.extend({ agent: { http: httpAgent, https: httpsAgent } });
+  return (await got).extend({ agent: { http: httpAgent, https: httpsAgent } });
 }
 module.exports.getProtectedGot = getProtectedGot;
 /**
@@ -96,7 +96,7 @@ module.exports.getProtectedGot = getProtectedGot;
  */
 exports.getURLMeta = async (url, blockLocalIPs = false) => {
   async function requestWithMethod(method) {
-    const protectedGot = getProtectedGot({ blockLocalIPs });
+    const protectedGot = await getProtectedGot({ blockLocalIPs });
     const stream = protectedGot.stream(url, { method, throwHttpErrors: false });
     return new Promise((resolve, reject) => (stream
       .on("response", (response) => {
diff --git a/packages/@uppy/companion/lib/server/helpers/utils.js b/packages/@uppy/companion/lib/server/helpers/utils.js
index 5b2a4a7..dd33ba5 100644
--- a/packages/@uppy/companion/lib/server/helpers/utils.js
+++ b/packages/@uppy/companion/lib/server/helpers/utils.js
@@ -129,6 +129,8 @@ module.exports.decrypt = (encrypted, secret) => {
 };
 module.exports.defaultGetKey = (req, filename) => `${crypto.randomUUID()}-${filename}`;
 class StreamHttpJsonError extends Error {
+  statusCode;
+  responseJson;
   constructor({ statusCode, responseJson }) {
     super(`Request failed with status ${statusCode}`);
     this.statusCode = statusCode;
@@ -147,13 +149,9 @@ module.exports.prepareStream = async (stream) =>
         resolve();
       })
       .on("error", (err) => {
-        var _a, _b;
         // In this case the error object is not a normal GOT HTTPError where json is already parsed,
         // we create our own StreamHttpJsonError error for this case
-        if (
-          typeof ((_a = err.response) === null || _a === void 0 ? void 0 : _a.body) === "string"
-          && typeof ((_b = err.response) === null || _b === void 0 ? void 0 : _b.statusCode) === "number"
-        ) {
+        if (typeof err.response?.body === "string" && typeof err.response?.statusCode === "number") {
           let responseJson;
           try {
             responseJson = JSON.parse(err.response.body);
diff --git a/packages/@uppy/companion/lib/server/jobs.js b/packages/@uppy/companion/lib/server/jobs.js
index 8751937..c1ad3bd 100644
--- a/packages/@uppy/companion/lib/server/jobs.js
+++ b/packages/@uppy/companion/lib/server/jobs.js
@@ -4,7 +4,7 @@ const schedule = require("node-schedule");
 const fs = require("node:fs");
 const path = require("node:path");
 const { promisify } = require("node:util");
-const got = require("got").default;
+const got = require("./got");
 const { FILE_NAME_PREFIX } = require("./Uploader");
 const logger = require("./logger");
 // TODO rewrite to use require('timers/promises').setTimeout when we support newer node versions
@@ -61,7 +61,7 @@ async function runPeriodicPing({ urls, payload, requestTimeout }) {
   // Run requests in parallel
   await Promise.all(urls.map(async (url) => {
     try {
-      await got.post(url, { json: payload, timeout: { request: requestTimeout } });
+      await (await got).post(url, { json: payload, timeout: { request: requestTimeout } });
     } catch (err) {
       logger.warn(err, "jobs.periodic.ping");
     }
diff --git a/packages/@uppy/companion/lib/server/middlewares.js b/packages/@uppy/companion/lib/server/middlewares.js
index cb892a2..ad99f4a 100644
--- a/packages/@uppy/companion/lib/server/middlewares.js
+++ b/packages/@uppy/companion/lib/server/middlewares.js
@@ -114,15 +114,8 @@ exports.cookieAuthToken = (req, res, next) => {
 exports.cors = (options = {}) => (req, res, next) => {
   // HTTP headers are not case sensitive, and express always handles them in lower case, so that's why we lower case them.
   // I believe that HTTP verbs are case sensitive, and should be uppercase.
-  var _a, _b;
   const existingExposeHeaders = res.get("Access-Control-Expose-Headers");
-  const exposeHeadersSet = new Set(
-    (_a = existingExposeHeaders === null || existingExposeHeaders === void 0
-          ? void 0
-          : existingExposeHeaders.split(",")) === null || _a === void 0
-      ? void 0
-      : _a.map((method) => method.trim().toLowerCase()),
-  );
+  const exposeHeadersSet = new Set(existingExposeHeaders?.split(",")?.map((method) => method.trim().toLowerCase()));
   // exposed so it can be accessed for our custom uppy client preflight
   exposeHeadersSet.add("access-control-allow-headers"); // todo remove in next major, see https://github.com/transloadit/uppy/pull/4462
   if (options.sendSelfEndpoint) {
@@ -148,12 +141,7 @@ exports.cors = (options = {}) => (req, res, next) => {
       : allowedHeaders,
   );
   const existingAllowMethods = res.get("Access-Control-Allow-Methods");
-  const allowMethodsSet = new Set(
-    (_b = existingAllowMethods === null || existingAllowMethods === void 0 ? void 0 : existingAllowMethods.split(","))
-        === null || _b === void 0
-      ? void 0
-      : _b.map((method) => method.trim().toUpperCase()),
-  );
+  const allowMethodsSet = new Set(existingAllowMethods?.split(",")?.map((method) => method.trim().toUpperCase()));
   // Needed for basic operation:
   allowMethodsSet.add("GET").add("POST").add("OPTIONS").add("DELETE");
   // If endpoint urls are specified, then we only allow those endpoints.
diff --git a/packages/@uppy/companion/lib/server/provider/box/index.js b/packages/@uppy/companion/lib/server/provider/box/index.js
index 49ef5d2..aecedbc 100644
--- a/packages/@uppy/companion/lib/server/provider/box/index.js
+++ b/packages/@uppy/companion/lib/server/provider/box/index.js
@@ -1,34 +1,26 @@
 "use strict";
-var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function(receiver, state, kind, f) {
-  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
-  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) {
-    throw new TypeError("Cannot read private member from an object whose class did not declare it");
-  }
-  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
-};
-var _Box_instances, _a, _Box_withErrorHandling;
+var _a;
 Object.defineProperty(exports, "__esModule", { value: true });
-const got = require("got").default;
 const Provider = require("../Provider");
 const adaptData = require("./adapter");
 const { withProviderErrorHandling } = require("../providerErrors");
 const { prepareStream } = require("../../helpers/utils");
+const got = require("../../got");
 const BOX_FILES_FIELDS = "id,modified_at,name,permissions,size,type";
 const BOX_THUMBNAIL_SIZE = 256;
-const getClient = ({ token }) =>
-  got.extend({
+const getClient = async ({ token }) =>
+  (await got).extend({
     prefixUrl: "https://api.box.com/2.0",
     headers: {
       authorization: `Bearer ${token}`,
     },
   });
 async function getUserInfo({ token }) {
-  return getClient({ token }).get("users/me", { responseType: "json" }).json();
+  return (await getClient({ token })).get("users/me", { responseType: "json" }).json();
 }
 async function list({ directory, query, token }) {
   const rootFolderID = "0";
-  // https://developer.box.com/reference/resources/items/
-  return getClient({ token }).get(`folders/${directory || rootFolderID}/items`, {
+  return (await getClient({ token })).get(`folders/${directory || rootFolderID}/items`, {
     searchParams: { fields: BOX_FILES_FIELDS, offset: query.cursor, limit: 1000 },
     responseType: "json",
   }).json();
@@ -39,7 +31,6 @@ async function list({ directory, query, token }) {
 class Box extends Provider {
   constructor(options) {
     super(options);
-    _Box_instances.add(this);
     // needed for the thumbnails fetched via companion
     this.needsCookieAuth = true;
   }
@@ -56,94 +47,72 @@ class Box extends Provider {
    * @param {unknown} options.companion
    */
   async list({ directory, token, query, companion }) {
-    return __classPrivateFieldGet(this, _Box_instances, "m", _Box_withErrorHandling).call(
-      this,
-      "provider.box.list.error",
-      async () => {
-        const [userInfo, files] = await Promise.all([
-          getUserInfo({ token }),
-          list({ directory, query, token }),
-        ]);
-        return adaptData(files, userInfo.login, companion);
-      },
-    );
+    return this.#withErrorHandling("provider.box.list.error", async () => {
+      const [userInfo, files] = await Promise.all([
+        getUserInfo({ token }),
+        list({ directory, query, token }),
+      ]);
+      return adaptData(files, userInfo.login, companion);
+    });
   }
   async download({ id, token }) {
-    return __classPrivateFieldGet(this, _Box_instances, "m", _Box_withErrorHandling).call(
-      this,
-      "provider.box.download.error",
-      async () => {
-        const stream = getClient({ token }).stream.get(`files/${id}/content`, { responseType: "json" });
-        await prepareStream(stream);
-        return { stream };
-      },
-    );
+    return this.#withErrorHandling("provider.box.download.error", async () => {
+      const stream = (await getClient({ token })).stream.get(`files/${id}/content`, { responseType: "json" });
+      await prepareStream(stream);
+      return { stream };
+    });
   }
   async thumbnail({ id, token }) {
-    return __classPrivateFieldGet(this, _Box_instances, "m", _Box_withErrorHandling).call(
-      this,
-      "provider.box.thumbnail.error",
-      async () => {
-        const extension = "jpg"; // you can set this to png to more easily reproduce http 202 retry-after
-        // From box API docs:
-        // Sometimes generating a thumbnail can take a few seconds.
-        // In these situations the API returns a Location-header pointing to a placeholder graphic
-        // for this file type.
-        // The placeholder graphic can be used in a user interface until the thumbnail generation has completed.
-        // The Retry-After-header indicates when to the thumbnail will be ready.
-        // At that time, retry this endpoint to retrieve the thumbnail.
-        //
-        // This can be reproduced more easily by changing extension to png and trying on a newly uploaded image
-        const stream = getClient({ token }).stream.get(`files/${id}/thumbnail.${extension}`, {
-          searchParams: { max_height: BOX_THUMBNAIL_SIZE, max_width: BOX_THUMBNAIL_SIZE },
-          responseType: "json",
-        });
-        await prepareStream(stream);
-        return { stream, contentType: "image/jpeg" };
-      },
-    );
+    return this.#withErrorHandling("provider.box.thumbnail.error", async () => {
+      const extension = "jpg"; // you can set this to png to more easily reproduce http 202 retry-after
+      // From box API docs:
+      // Sometimes generating a thumbnail can take a few seconds.
+      // In these situations the API returns a Location-header pointing to a placeholder graphic
+      // for this file type.
+      // The placeholder graphic can be used in a user interface until the thumbnail generation has completed.
+      // The Retry-After-header indicates when to the thumbnail will be ready.
+      // At that time, retry this endpoint to retrieve the thumbnail.
+      //
+      // This can be reproduced more easily by changing extension to png and trying on a newly uploaded image
+      const stream = (await getClient({ token })).stream.get(`files/${id}/thumbnail.${extension}`, {
+        searchParams: { max_height: BOX_THUMBNAIL_SIZE, max_width: BOX_THUMBNAIL_SIZE },
+        responseType: "json",
+      });
+      await prepareStream(stream);
+      return { stream, contentType: "image/jpeg" };
+    });
   }
   async size({ id, token }) {
-    return __classPrivateFieldGet(this, _Box_instances, "m", _Box_withErrorHandling).call(
-      this,
-      "provider.box.size.error",
-      async () => {
-        const { size } = await getClient({ token }).get(`files/${id}`, { responseType: "json" }).json();
-        return parseInt(size, 10);
-      },
-    );
+    return this.#withErrorHandling("provider.box.size.error", async () => {
+      const { size } = await (await getClient({ token })).get(`files/${id}`, { responseType: "json" }).json();
+      return parseInt(size, 10);
+    });
   }
   logout({ companion, token }) {
-    return __classPrivateFieldGet(this, _Box_instances, "m", _Box_withErrorHandling).call(
-      this,
-      "provider.box.logout.error",
-      async () => {
-        const { key, secret } = companion.options.providerOptions.box;
-        await getClient({ token }).post("oauth2/revoke", {
-          prefixUrl: "https://api.box.com",
-          form: {
-            client_id: key,
-            client_secret: secret,
-            token,
-          },
-          responseType: "json",
-        });
-        return { revoked: true };
-      },
-    );
+    return this.#withErrorHandling("provider.box.logout.error", async () => {
+      const { key, secret } = companion.options.providerOptions.box;
+      await (await getClient({ token })).post("oauth2/revoke", {
+        prefixUrl: "https://api.box.com",
+        form: {
+          client_id: key,
+          client_secret: secret,
+          token,
+        },
+        responseType: "json",
+      });
+      return { revoked: true };
+    });
+  }
+  // eslint-disable-next-line class-methods-use-this
+  async #withErrorHandling(tag, fn) {
+    return withProviderErrorHandling({
+      fn,
+      tag,
+      providerName: _a.authProvider,
+      isAuthError: (response) => response.statusCode === 401,
+      getJsonErrorMessage: (body) => body?.message,
+    });
   }
 }
-_a = Box,
-  _Box_instances = new WeakSet(),
-  _Box_withErrorHandling =
-    // eslint-disable-next-line class-methods-use-this
-    async function _Box_withErrorHandling(tag, fn) {
-      return withProviderErrorHandling({
-        fn,
-        tag,
-        providerName: _a.authProvider,
-        isAuthError: (response) => response.statusCode === 401,
-        getJsonErrorMessage: (body) => body === null || body === void 0 ? void 0 : body.message,
-      });
-    };
+_a = Box;
 module.exports = Box;
diff --git a/packages/@uppy/companion/lib/server/provider/credentials.js b/packages/@uppy/companion/lib/server/provider/credentials.js
index dce414f..ea3ed97 100644
--- a/packages/@uppy/companion/lib/server/provider/credentials.js
+++ b/packages/@uppy/companion/lib/server/provider/credentials.js
@@ -1,13 +1,12 @@
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
-const got = require("got").default;
-const atob = require("atob");
 const { htmlEscape } = require("escape-goat");
 const logger = require("../logger");
 const oAuthState = require("../helpers/oauth-state");
 const tokenService = require("../helpers/jwt");
 // eslint-disable-next-line
 const Provider = require("./Provider");
+const got = require("../got");
 /**
  * @param {string} url
  * @param {string} providerName
@@ -15,7 +14,7 @@ const Provider = require("./Provider");
  */
 async function fetchKeys(url, providerName, credentialRequestParams) {
   try {
-    const { credentials } = await got.post(url, {
+    const { credentials } = await (await got).post(url, {
       json: { provider: providerName, parameters: credentialRequestParams },
     }).json();
     if (!credentials) {
@@ -66,7 +65,6 @@ async function fetchProviderKeys(providerName, companionOptions, credentialReque
  */
 exports.getCredentialsOverrideMiddleware = (providers, companionOptions) => {
   return async (req, res, next) => {
-    var _a;
     try {
       const { authProvider, override } = req.params;
       const [providerName] = Object.keys(providers).filter((name) => providers[name].authProvider === authProvider);
@@ -74,9 +72,7 @@ exports.getCredentialsOverrideMiddleware = (providers, companionOptions) => {
         next();
         return;
       }
-      if (
-        !((_a = companionOptions.providerOptions[providerName]) === null || _a === void 0 ? void 0 : _a.credentialsURL)
-      ) {
+      if (!companionOptions.providerOptions[providerName]?.credentialsURL) {
         next();
         return;
       }
diff --git a/packages/@uppy/companion/lib/server/provider/drive/index.js b/packages/@uppy/companion/lib/server/provider/drive/index.js
index 994dece..ffab936 100644
--- a/packages/@uppy/companion/lib/server/provider/drive/index.js
+++ b/packages/@uppy/companion/lib/server/provider/drive/index.js
@@ -1,14 +1,6 @@
 "use strict";
-var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function(receiver, state, kind, f) {
-  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
-  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) {
-    throw new TypeError("Cannot read private member from an object whose class did not declare it");
-  }
-  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
-};
-var _Drive_instances, _a, _Drive_withErrorHandling;
+var _a;
 Object.defineProperty(exports, "__esModule", { value: true });
-const got = require("got").default;
 const Provider = require("../Provider");
 const logger = require("../../logger");
 const { VIRTUAL_SHARED_DIR, adaptData, isShortcut, isGsuiteFile, getGsuiteExportType } = require("./adapter");
@@ -16,6 +8,7 @@ const { withProviderErrorHandling } = require("../providerErrors");
 const { prepareStream } = require("../../helpers/utils");
 const { MAX_AGE_REFRESH_TOKEN } = require("../../helpers/jwt");
 const { ProviderAuthError } = require("../error");
+const got = require("../../got");
 // For testing refresh token:
 // first run a download with mockAccessTokenExpiredError = true
 // then when you want to test expiry, set to mockAccessTokenExpiredError to the logged access token
@@ -28,19 +21,19 @@ const DRIVE_FILE_FIELDS =
 const DRIVE_FILES_FIELDS = `kind,nextPageToken,incompleteSearch,files(${DRIVE_FILE_FIELDS})`;
 // using wildcard to get all 'drive' fields because specifying fields seems no to work for the /drives endpoint
 const SHARED_DRIVE_FIELDS = "*";
-const getClient = ({ token }) =>
-  got.extend({
+const getClient = async ({ token }) =>
+  (await got).extend({
     prefixUrl: "https://www.googleapis.com/drive/v3",
     headers: {
       authorization: `Bearer ${token}`,
     },
   });
-const getOauthClient = () =>
-  got.extend({
+const getOauthClient = async () =>
+  (await got).extend({
     prefixUrl: "https://oauth2.googleapis.com",
   });
 async function getStats({ id, token }) {
-  const client = getClient({ token });
+  const client = await getClient({ token });
   const getStatsInner = async (
     statsOfId,
   ) => (client.get(`files/${encodeURIComponent(statsOfId)}`, {
@@ -58,10 +51,6 @@ async function getStats({ id, token }) {
  * Adapter for API https://developers.google.com/drive/api/v3/
  */
 class Drive extends Provider {
-  constructor() {
-    super(...arguments);
-    _Drive_instances.add(this);
-  }
   static get authProvider() {
     return "google";
   }
@@ -69,72 +58,64 @@ class Drive extends Provider {
     return MAX_AGE_REFRESH_TOKEN;
   }
   async list(options) {
-    return __classPrivateFieldGet(this, _Drive_instances, "m", _Drive_withErrorHandling).call(
-      this,
-      "provider.drive.list.error",
-      async () => {
-        const directory = options.directory || "root";
-        const query = options.query || {};
-        const { token } = options;
-        const isRoot = directory === "root";
-        const isVirtualSharedDirRoot = directory === VIRTUAL_SHARED_DIR;
-        const client = getClient({ token });
-        async function fetchSharedDrives(pageToken = null) {
-          const shouldListSharedDrives = isRoot && !query.cursor;
-          if (!shouldListSharedDrives) {
-            return undefined;
-          }
-          const response = await client.get("drives", {
-            searchParams: { fields: SHARED_DRIVE_FIELDS, pageToken, pageSize: 100 },
-            responseType: "json",
-          }).json();
-          const { nextPageToken } = response;
-          if (nextPageToken) {
-            const nextResponse = await fetchSharedDrives(nextPageToken);
-            if (!nextResponse) {
-              return response;
-            }
-            return { ...nextResponse, drives: [...response.drives, ...nextResponse.drives] };
-          }
-          return response;
-        }
-        async function fetchFiles() {
-          // Shared with me items in root don't have any parents
-          const q = isVirtualSharedDirRoot
-            ? `sharedWithMe and trashed=false`
-            : `('${directory}' in parents) and trashed=false`;
-          const searchParams = {
-            fields: DRIVE_FILES_FIELDS,
-            pageToken: query.cursor,
-            q,
-            // We can only do a page size of 1000 because we do not request permissions in DRIVE_FILES_FIELDS.
-            // Otherwise we are limited to 100. Instead we get the user info from `this.user()`
-            pageSize: 1000,
-            orderBy: "folder,name",
-            includeItemsFromAllDrives: true,
-            supportsAllDrives: true,
-          };
-          return client.get("files", { searchParams, responseType: "json" }).json();
+    return this.#withErrorHandling("provider.drive.list.error", async () => {
+      const directory = options.directory || "root";
+      const query = options.query || {};
+      const { token } = options;
+      const isRoot = directory === "root";
+      const isVirtualSharedDirRoot = directory === VIRTUAL_SHARED_DIR;
+      const client = await getClient({ token });
+      async function fetchSharedDrives(pageToken = null) {
+        const shouldListSharedDrives = isRoot && !query.cursor;
+        if (!shouldListSharedDrives) {
+          return undefined;
         }
-        async function fetchAbout() {
-          const searchParams = { fields: "user" };
-          return client.get("about", { searchParams, responseType: "json" }).json();
+        const response = await client.get("drives", {
+          searchParams: { fields: SHARED_DRIVE_FIELDS, pageToken, pageSize: 100 },
+          responseType: "json",
+        }).json();
+        const { nextPageToken } = response;
+        if (nextPageToken) {
+          const nextResponse = await fetchSharedDrives(nextPageToken);
+          if (!nextResponse) {
+            return response;
+          }
+          return { ...nextResponse, drives: [...response.drives, ...nextResponse.drives] };
         }
-        const [sharedDrives, filesResponse, about] = await Promise.all([
-          fetchSharedDrives(),
-          fetchFiles(),
-          fetchAbout(),
-        ]);
-        return adaptData(
-          filesResponse,
-          sharedDrives,
-          directory,
-          query,
-          isRoot && !query.cursor, // we can only show it on the first page request, or else we will have duplicates of it
-          about,
-        );
-      },
-    );
+        return response;
+      }
+      async function fetchFiles() {
+        // Shared with me items in root don't have any parents
+        const q = isVirtualSharedDirRoot
+          ? `sharedWithMe and trashed=false`
+          : `('${directory}' in parents) and trashed=false`;
+        const searchParams = {
+          fields: DRIVE_FILES_FIELDS,
+          pageToken: query.cursor,
+          q,
+          // We can only do a page size of 1000 because we do not request permissions in DRIVE_FILES_FIELDS.
+          // Otherwise we are limited to 100. Instead we get the user info from `this.user()`
+          pageSize: 1000,
+          orderBy: "folder,name",
+          includeItemsFromAllDrives: true,
+          supportsAllDrives: true,
+        };
+        return client.get("files", { searchParams, responseType: "json" }).json();
+      }
+      async function fetchAbout() {
+        const searchParams = { fields: "user" };
+        return client.get("about", { searchParams, responseType: "json" }).json();
+      }
+      const [sharedDrives, filesResponse, about] = await Promise.all([fetchSharedDrives(), fetchFiles(), fetchAbout()]);
+      return adaptData(
+        filesResponse,
+        sharedDrives,
+        directory,
+        query,
+        isRoot && !query.cursor, // we can only show it on the first page request, or else we will have duplicates of it
+        about,
+      );
+    });
   }
   async download({ id: idIn, token }) {
     if (mockAccessTokenExpiredError != null) {
@@ -144,30 +125,26 @@ class Drive extends Provider {
         throw new ProviderAuthError();
       }
     }
-    return __classPrivateFieldGet(this, _Drive_instances, "m", _Drive_withErrorHandling).call(
-      this,
-      "provider.drive.download.error",
-      async () => {
-        const client = getClient({ token });
-        const { mimeType, id } = await getStats({ id: idIn, token });
-        let stream;
-        if (isGsuiteFile(mimeType)) {
-          const mimeType2 = getGsuiteExportType(mimeType);
-          logger.info(`calling google file export for ${id} to ${mimeType2}`, "provider.drive.export");
-          stream = client.stream.get(`files/${encodeURIComponent(id)}/export`, {
-            searchParams: { supportsAllDrives: true, mimeType: mimeType2 },
-            responseType: "json",
-          });
-        } else {
-          stream = client.stream.get(`files/${encodeURIComponent(id)}`, {
-            searchParams: { alt: "media", supportsAllDrives: true },
-            responseType: "json",
-          });
-        }
-        await prepareStream(stream);
-        return { stream };
-      },
-    );
+    return this.#withErrorHandling("provider.drive.download.error", async () => {
+      const client = await getClient({ token });
+      const { mimeType, id } = await getStats({ id: idIn, token });
+      let stream;
+      if (isGsuiteFile(mimeType)) {
+        const mimeType2 = getGsuiteExportType(mimeType);
+        logger.info(`calling google file export for ${id} to ${mimeType2}`, "provider.drive.export");
+        stream = client.stream.get(`files/${encodeURIComponent(id)}/export`, {
+          searchParams: { supportsAllDrives: true, mimeType: mimeType2 },
+          responseType: "json",
+        });
+      } else {
+        stream = client.stream.get(`files/${encodeURIComponent(id)}`, {
+          searchParams: { alt: "media", supportsAllDrives: true },
+          responseType: "json",
+        });
+      }
+      await prepareStream(stream);
+      return { stream };
+    });
   }
   // eslint-disable-next-line class-methods-use-this
   async thumbnail() {
@@ -176,75 +153,52 @@ class Drive extends Provider {
     throw new Error("call to thumbnail is not implemented");
   }
   async size({ id, token }) {
-    return __classPrivateFieldGet(this, _Drive_instances, "m", _Drive_withErrorHandling).call(
-      this,
-      "provider.drive.size.error",
-      async () => {
-        const { mimeType, size } = await getStats({ id, token });
-        if (isGsuiteFile(mimeType)) {
-          // GSuite file sizes cannot be predetermined (but are max 10MB)
-          // e.g. Transfer-Encoding: chunked
-          return undefined;
-        }
-        return parseInt(size, 10);
-      },
-    );
+    return this.#withErrorHandling("provider.drive.size.error", async () => {
+      const { mimeType, size } = await getStats({ id, token });
+      if (isGsuiteFile(mimeType)) {
+        // GSuite file sizes cannot be predetermined (but are max 10MB)
+        // e.g. Transfer-Encoding: chunked
+        return undefined;
+      }
+      return parseInt(size, 10);
+    });
   }
   logout({ token }) {
-    return __classPrivateFieldGet(this, _Drive_instances, "m", _Drive_withErrorHandling).call(
-      this,
-      "provider.drive.logout.error",
-      async () => {
-        await got.post("https://accounts.google.com/o/oauth2/revoke", {
-          searchParams: { token },
-          responseType: "json",
-        });
-        return { revoked: true };
-      },
-    );
+    return this.#withErrorHandling("provider.drive.logout.error", async () => {
+      await (await got).post("https://accounts.google.com/o/oauth2/revoke", {
+        searchParams: { token },
+        responseType: "json",
+      });
+      return { revoked: true };
+    });
   }
   async refreshToken({ clientId, clientSecret, refreshToken }) {
-    return __classPrivateFieldGet(this, _Drive_instances, "m", _Drive_withErrorHandling).call(
-      this,
-      "provider.drive.token.refresh.error",
-      async () => {
-        const { access_token: accessToken } = await getOauthClient().post("token", {
-          responseType: "json",
-          form: {
-            refresh_token: refreshToken,
-            grant_type: "refresh_token",
-            client_id: clientId,
-            client_secret: clientSecret,
-          },
-        }).json();
-        return { accessToken };
-      },
-    );
+    return this.#withErrorHandling("provider.drive.token.refresh.error", async () => {
+      const { access_token: accessToken } = await (await getOauthClient()).post("token", {
+        responseType: "json",
+        form: {
+          refresh_token: refreshToken,
+          grant_type: "refresh_token",
+          client_id: clientId,
+          client_secret: clientSecret,
+        },
+      }).json();
+      return { accessToken };
+    });
+  }
+  // eslint-disable-next-line class-methods-use-this
+  async #withErrorHandling(tag, fn) {
+    return withProviderErrorHandling({
+      fn,
+      tag,
+      providerName: _a.authProvider,
+      isAuthError: (response) => (
+        response.statusCode === 401
+        || (response.statusCode === 400 && response.body?.error === "invalid_grant") // Refresh token has expired or been revoked
+      ),
+      getJsonErrorMessage: (body) => body?.error?.message,
+    });
   }
 }
-_a = Drive,
-  _Drive_instances = new WeakSet(),
-  _Drive_withErrorHandling =
-    // eslint-disable-next-line class-methods-use-this
-    async function _Drive_withErrorHandling(tag, fn) {
-      return withProviderErrorHandling({
-        fn,
-        tag,
-        providerName: _a.authProvider,
-        isAuthError: (response) => {
-          var _b;
-          return (
-            response.statusCode === 401
-            || (response.statusCode === 400
-              && ((_b = response.body) === null || _b === void 0 ? void 0 : _b.error) === "invalid_grant") // Refresh token has expired or been revoked
-          );
-        },
-        getJsonErrorMessage: (body) => {
-          var _b;
-          return (_b = body === null || body === void 0 ? void 0 : body.error) === null || _b === void 0
-            ? void 0
-            : _b.message;
-        },
-      });
-    };
+_a = Drive;
 module.exports = Drive;
diff --git a/packages/@uppy/companion/lib/server/provider/dropbox/index.js b/packages/@uppy/companion/lib/server/provider/dropbox/index.js
index 237b171..b611a97 100644
--- a/packages/@uppy/companion/lib/server/provider/dropbox/index.js
+++ b/packages/@uppy/companion/lib/server/provider/dropbox/index.js
@@ -1,19 +1,12 @@
 "use strict";
-var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function(receiver, state, kind, f) {
-  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
-  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) {
-    throw new TypeError("Cannot read private member from an object whose class did not declare it");
-  }
-  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
-};
-var _DropBox_instances, _a, _DropBox_withErrorHandling;
+var _a;
 Object.defineProperty(exports, "__esModule", { value: true });
-const got = require("got").default;
 const Provider = require("../Provider");
 const adaptData = require("./adapter");
 const { withProviderErrorHandling } = require("../providerErrors");
 const { prepareStream } = require("../../helpers/utils");
 const { MAX_AGE_REFRESH_TOKEN } = require("../../helpers/jwt");
+const got = require("../../got");
 // From https://www.dropbox.com/developers/reference/json-encoding:
 //
 // This function is simple and has OK performance compared to more
@@ -24,25 +17,23 @@ function httpHeaderSafeJson(v) {
     return `\\u${(`000${c.charCodeAt(0).toString(16)}`).slice(-4)}`;
   });
 }
-const getClient = ({ token }) =>
-  got.extend({
+const getClient = async ({ token }) =>
+  (await got).extend({
     prefixUrl: "https://api.dropboxapi.com/2",
     headers: {
       authorization: `Bearer ${token}`,
     },
   });
-const getOauthClient = () =>
-  got.extend({
+const getOauthClient = async () =>
+  (await got).extend({
     prefixUrl: "https://api.dropboxapi.com/oauth2",
   });
 async function list({ directory, query, token }) {
+  const client = await getClient({ token });
   if (query.cursor) {
-    return getClient({ token }).post("files/list_folder/continue", {
-      json: { cursor: query.cursor },
-      responseType: "json",
-    }).json();
+    return client.post("files/list_folder/continue", { json: { cursor: query.cursor }, responseType: "json" }).json();
   }
-  return getClient({ token }).post("files/list_folder", {
+  return client.post("files/list_folder", {
     searchParams: query,
     json: {
       path: `${directory || ""}`,
@@ -54,7 +45,7 @@ async function list({ directory, query, token }) {
   }).json();
 }
 async function userInfo({ token }) {
-  return getClient({ token }).post("users/get_current_account", { responseType: "json" }).json();
+  return (await getClient({ token })).post("users/get_current_account", { responseType: "json" }).json();
 }
 /**
  * Adapter for API https://www.dropbox.com/developers/documentation/http/documentation
@@ -62,7 +53,6 @@ async function userInfo({ token }) {
 class DropBox extends Provider {
   constructor(options) {
     super(options);
-    _DropBox_instances.add(this);
     this.needsCookieAuth = true;
   }
   static get authProvider() {
@@ -75,113 +65,87 @@ class DropBox extends Provider {
    * @param {object} options
    */
   async list(options) {
-    return __classPrivateFieldGet(this, _DropBox_instances, "m", _DropBox_withErrorHandling).call(
-      this,
-      "provider.dropbox.list.error",
-      async () => {
-        const responses = await Promise.all([
-          list(options),
-          userInfo(options),
-        ]);
-        // @ts-ignore
-        const [stats, { email }] = responses;
-        return adaptData(stats, email, options.companion.buildURL);
-      },
-    );
+    return this.#withErrorHandling("provider.dropbox.list.error", async () => {
+      const responses = await Promise.all([
+        list(options),
+        userInfo(options),
+      ]);
+      // @ts-ignore
+      const [stats, { email }] = responses;
+      return adaptData(stats, email, options.companion.buildURL);
+    });
   }
   async download({ id, token }) {
-    return __classPrivateFieldGet(this, _DropBox_instances, "m", _DropBox_withErrorHandling).call(
-      this,
-      "provider.dropbox.download.error",
-      async () => {
-        const stream = getClient({ token }).stream.post("files/download", {
-          prefixUrl: "https://content.dropboxapi.com/2",
-          headers: {
-            "Dropbox-API-Arg": httpHeaderSafeJson({ path: String(id) }),
-            Connection: "keep-alive", // important because https://github.com/transloadit/uppy/issues/4357
-          },
-          body: Buffer.alloc(0), // if not, it will hang waiting for the writable stream
-          responseType: "json",
-        });
-        await prepareStream(stream);
-        return { stream };
-      },
-    );
+    return this.#withErrorHandling("provider.dropbox.download.error", async () => {
+      const stream = (await getClient({ token })).stream.post("files/download", {
+        prefixUrl: "https://content.dropboxapi.com/2",
+        headers: {
+          "Dropbox-API-Arg": httpHeaderSafeJson({ path: String(id) }),
+          Connection: "keep-alive", // important because https://github.com/transloadit/uppy/issues/4357
+        },
+        body: Buffer.alloc(0), // if not, it will hang waiting for the writable stream
+        responseType: "json",
+      });
+      await prepareStream(stream);
+      return { stream };
+    });
   }
   async thumbnail({ id, token }) {
-    return __classPrivateFieldGet(this, _DropBox_instances, "m", _DropBox_withErrorHandling).call(
-      this,
-      "provider.dropbox.thumbnail.error",
-      async () => {
-        const stream = getClient({ token }).stream.post("files/get_thumbnail_v2", {
-          prefixUrl: "https://content.dropboxapi.com/2",
-          headers: {
-            "Dropbox-API-Arg": httpHeaderSafeJson({
-              resource: { ".tag": "path", path: `${id}` },
-              size: "w256h256",
-              format: "jpeg",
-            }),
-          },
-          body: Buffer.alloc(0),
-          responseType: "json",
-        });
-        await prepareStream(stream);
-        return { stream, contentType: "image/jpeg" };
-      },
-    );
+    return this.#withErrorHandling("provider.dropbox.thumbnail.error", async () => {
+      const stream = (await getClient({ token })).stream.post("files/get_thumbnail_v2", {
+        prefixUrl: "https://content.dropboxapi.com/2",
+        headers: {
+          "Dropbox-API-Arg": httpHeaderSafeJson({
+            resource: { ".tag": "path", path: `${id}` },
+            size: "w256h256",
+            format: "jpeg",
+          }),
+        },
+        body: Buffer.alloc(0),
+        responseType: "json",
+      });
+      await prepareStream(stream);
+      return { stream, contentType: "image/jpeg" };
+    });
   }
   async size({ id, token }) {
-    return __classPrivateFieldGet(this, _DropBox_instances, "m", _DropBox_withErrorHandling).call(
-      this,
-      "provider.dropbox.size.error",
-      async () => {
-        const { size } = await getClient({ token }).post("files/get_metadata", {
-          json: { path: id },
-          responseType: "json",
-        }).json();
-        return parseInt(size, 10);
-      },
-    );
+    return this.#withErrorHandling("provider.dropbox.size.error", async () => {
+      const { size } = await (await getClient({ token })).post("files/get_metadata", {
+        json: { path: id },
+        responseType: "json",
+      }).json();
+      return parseInt(size, 10);
+    });
   }
   async logout({ token }) {
-    return __classPrivateFieldGet(this, _DropBox_instances, "m", _DropBox_withErrorHandling).call(
-      this,
-      "provider.dropbox.logout.error",
-      async () => {
-        await getClient({ token }).post("auth/token/revoke", { responseType: "json" });
-        return { revoked: true };
-      },
-    );
+    return this.#withErrorHandling("provider.dropbox.logout.error", async () => {
+      await (await getClient({ token })).post("auth/token/revoke", { responseType: "json" });
+      return { revoked: true };
+    });
   }
   async refreshToken({ clientId, clientSecret, refreshToken }) {
-    return __classPrivateFieldGet(this, _DropBox_instances, "m", _DropBox_withErrorHandling).call(
-      this,
-      "provider.dropbox.token.refresh.error",
-      async () => {
-        const { access_token: accessToken } = await getOauthClient().post("token", {
-          form: {
-            refresh_token: refreshToken,
-            grant_type: "refresh_token",
-            client_id: clientId,
-            client_secret: clientSecret,
-          },
-        }).json();
-        return { accessToken };
-      },
-    );
+    return this.#withErrorHandling("provider.dropbox.token.refresh.error", async () => {
+      const { access_token: accessToken } = await (await getOauthClient()).post("token", {
+        form: {
+          refresh_token: refreshToken,
+          grant_type: "refresh_token",
+          client_id: clientId,
+          client_secret: clientSecret,
+        },
+      }).json();
+      return { accessToken };
+    });
+  }
+  // eslint-disable-next-line class-methods-use-this
+  async #withErrorHandling(tag, fn) {
+    return withProviderErrorHandling({
+      fn,
+      tag,
+      providerName: _a.authProvider,
+      isAuthError: (response) => response.statusCode === 401,
+      getJsonErrorMessage: (body) => body?.error_summary,
+    });
   }
 }
-_a = DropBox,
-  _DropBox_instances = new WeakSet(),
-  _DropBox_withErrorHandling =
-    // eslint-disable-next-line class-methods-use-this
-    async function _DropBox_withErrorHandling(tag, fn) {
-      return withProviderErrorHandling({
-        fn,
-        tag,
-        providerName: _a.authProvider,
-        isAuthError: (response) => response.statusCode === 401,
-        getJsonErrorMessage: (body) => body === null || body === void 0 ? void 0 : body.error_summary,
-      });
-    };
+_a = DropBox;
 module.exports = DropBox;
diff --git a/packages/@uppy/companion/lib/server/provider/error.js b/packages/@uppy/companion/lib/server/provider/error.js
index c242ff1..48bd1d2 100644
--- a/packages/@uppy/companion/lib/server/provider/error.js
+++ b/packages/@uppy/companion/lib/server/provider/error.js
@@ -45,14 +45,14 @@ class ProviderAuthError extends ProviderApiError {
  */
 function errorToResponse(err) {
   // @ts-ignore
-  if (err === null || err === void 0 ? void 0 : err.isAuthError) {
+  if (err?.isAuthError) {
     return { code: 401, json: { message: err.message } };
   }
-  if ((err === null || err === void 0 ? void 0 : err.name) === "ProviderUserError") {
+  if (err?.name === "ProviderUserError") {
     // @ts-ignore
     return { code: 400, json: err.json };
   }
-  if ((err === null || err === void 0 ? void 0 : err.name) === "ProviderApiError") {
+  if (err?.name === "ProviderApiError") {
     // @ts-ignore
     if (err.statusCode >= 500) {
       // bad gateway i.e the provider APIs gateway
diff --git a/packages/@uppy/companion/lib/server/provider/facebook/index.js b/packages/@uppy/companion/lib/server/provider/facebook/index.js
index 6d794cd..55eec3c 100644
--- a/packages/@uppy/companion/lib/server/provider/facebook/index.js
+++ b/packages/@uppy/companion/lib/server/provider/facebook/index.js
@@ -1,30 +1,25 @@
 "use strict";
-var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function(receiver, state, kind, f) {
-  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
-  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) {
-    throw new TypeError("Cannot read private member from an object whose class did not declare it");
-  }
-  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
-};
-var _Facebook_instances, _a, _Facebook_withErrorHandling;
+var _a;
 Object.defineProperty(exports, "__esModule", { value: true });
-const got = require("got").default;
 const Provider = require("../Provider");
 const { getURLMeta } = require("../../helpers/request");
 const logger = require("../../logger");
 const { adaptData, sortImages } = require("./adapter");
 const { withProviderErrorHandling } = require("../providerErrors");
 const { prepareStream } = require("../../helpers/utils");
-const getClient = ({ token }) =>
-  got.extend({
+const got = require("../../got");
+const getClient = async ({ token }) =>
+  (await got).extend({
     prefixUrl: "https://graph.facebook.com",
     headers: {
       authorization: `Bearer ${token}`,
     },
   });
 async function getMediaUrl({ token, id }) {
-  const body = await getClient({ token }).get(String(id), { searchParams: { fields: "images" }, responseType: "json" })
-    .json();
+  const body = await (await getClient({ token })).get(String(id), {
+    searchParams: { fields: "images" },
+    responseType: "json",
+  }).json();
   const sortedImages = sortImages(body.images);
   return sortedImages[sortedImages.length - 1].source;
 }
@@ -32,47 +27,35 @@ async function getMediaUrl({ token, id }) {
  * Adapter for API https://developers.facebook.com/docs/graph-api/using-graph-api/
  */
 class Facebook extends Provider {
-  constructor() {
-    super(...arguments);
-    _Facebook_instances.add(this);
-  }
   static get authProvider() {
     return "facebook";
   }
   async list({ directory, token, query = { cursor: null } }) {
-    return __classPrivateFieldGet(this, _Facebook_instances, "m", _Facebook_withErrorHandling).call(
-      this,
-      "provider.facebook.list.error",
-      async () => {
-        const qs = { fields: "name,cover_photo,created_time,type" };
-        if (query.cursor) {
-          qs.after = query.cursor;
-        }
-        let path = "me/albums";
-        if (directory) {
-          path = `${directory}/photos`;
-          qs.fields = "icon,images,name,width,height,created_time";
-        }
-        const client = getClient({ token });
-        const [{ email }, list] = await Promise.all([
-          client.get("me", { searchParams: { fields: "email" }, responseType: "json" }).json(),
-          client.get(path, { searchParams: qs, responseType: "json" }).json(),
-        ]);
-        return adaptData(list, email, directory, query);
-      },
-    );
+    return this.#withErrorHandling("provider.facebook.list.error", async () => {
+      const qs = { fields: "name,cover_photo,created_time,type" };
+      if (query.cursor) {
+        qs.after = query.cursor;
+      }
+      let path = "me/albums";
+      if (directory) {
+        path = `${directory}/photos`;
+        qs.fields = "icon,images,name,width,height,created_time";
+      }
+      const client = await getClient({ token });
+      const [{ email }, list] = await Promise.all([
+        client.get("me", { searchParams: { fields: "email" }, responseType: "json" }).json(),
+        client.get(path, { searchParams: qs, responseType: "json" }).json(),
+      ]);
+      return adaptData(list, email, directory, query);
+    });
   }
   async download({ id, token }) {
-    return __classPrivateFieldGet(this, _Facebook_instances, "m", _Facebook_withErrorHandling).call(
-      this,
-      "provider.facebook.download.error",
-      async () => {
-        const url = await getMediaUrl({ token, id });
-        const stream = got.stream.get(url, { responseType: "json" });
-        await prepareStream(stream);
-        return { stream };
-      },
-    );
+    return this.#withErrorHandling("provider.facebook.download.error", async () => {
+      const url = await getMediaUrl({ token, id });
+      const stream = (await got).stream.get(url, { responseType: "json" });
+      await prepareStream(stream);
+      return { stream };
+    });
   }
   // eslint-disable-next-line class-methods-use-this
   async thumbnail() {
@@ -81,49 +64,28 @@ class Facebook extends Provider {
     throw new Error("call to thumbnail is not implemented");
   }
   async size({ id, token }) {
-    return __classPrivateFieldGet(this, _Facebook_instances, "m", _Facebook_withErrorHandling).call(
-      this,
-      "provider.facebook.size.error",
-      async () => {
-        const url = await getMediaUrl({ token, id });
-        const { size } = await getURLMeta(url, true);
-        return size;
-      },
-    );
+    return this.#withErrorHandling("provider.facebook.size.error", async () => {
+      const url = await getMediaUrl({ token, id });
+      const { size } = await getURLMeta(url, true);
+      return size;
+    });
   }
   async logout({ token }) {
-    return __classPrivateFieldGet(this, _Facebook_instances, "m", _Facebook_withErrorHandling).call(
-      this,
-      "provider.facebook.logout.error",
-      async () => {
-        await getClient({ token }).delete("me/permissions", { responseType: "json" }).json();
-        return { revoked: true };
-      },
-    );
+    return this.#withErrorHandling("provider.facebook.logout.error", async () => {
+      await (await getClient({ token })).delete("me/permissions", { responseType: "json" }).json();
+      return { revoked: true };
+    });
+  }
+  // eslint-disable-next-line class-methods-use-this
+  async #withErrorHandling(tag, fn) {
+    return withProviderErrorHandling({
+      fn,
+      tag,
+      providerName: _a.authProvider,
+      isAuthError: (response) => typeof response.body === "object" && response.body?.error?.code === 190, // Invalid OAuth 2.0 Access Token
+      getJsonErrorMessage: (body) => body?.error?.message,
+    });
   }
 }
-_a = Facebook,
-  _Facebook_instances = new WeakSet(),
-  _Facebook_withErrorHandling =
-    // eslint-disable-next-line class-methods-use-this
-    async function _Facebook_withErrorHandling(tag, fn) {
-      return withProviderErrorHandling({
-        fn,
-        tag,
-        providerName: _a.authProvider,
-        isAuthError: (response) => {
-          var _b, _c;
-          return typeof response.body === "object"
-            && ((_c = (_b = response.body) === null || _b === void 0 ? void 0 : _b.error) === null || _c === void 0
-                ? void 0
-                : _c.code) === 190;
-        }, // Invalid OAuth 2.0 Access Token
-        getJsonErrorMessage: (body) => {
-          var _b;
-          return (_b = body === null || body === void 0 ? void 0 : body.error) === null || _b === void 0
-            ? void 0
-            : _b.message;
-        },
-      });
-    };
+_a = Facebook;
 module.exports = Facebook;
diff --git a/packages/@uppy/companion/lib/server/provider/index.js b/packages/@uppy/companion/lib/server/provider/index.js
index de030b5..c9693ac 100644
--- a/packages/@uppy/companion/lib/server/provider/index.js
+++ b/packages/@uppy/companion/lib/server/provider/index.js
@@ -112,9 +112,7 @@ module.exports.addProviderOptions = (companionOptions, grantConfig, getAuthProvi
   const { oauthDomain } = server;
   const keys = Object.keys(providerOptions).filter((key) => key !== "server");
   keys.forEach((providerName) => {
-    const authProvider = getAuthProvider === null || getAuthProvider === void 0
-      ? void 0
-      : getAuthProvider(providerName);
+    const authProvider = getAuthProvider?.(providerName);
     if (isOAuthProvider(authProvider) && grantConfig[authProvider]) {
       // explicitly add providerOptions so users don't override other providerOptions.
       // eslint-disable-next-line no-param-reassign
diff --git a/packages/@uppy/companion/lib/server/provider/instagram/graph/index.js b/packages/@uppy/companion/lib/server/provider/instagram/graph/index.js
index 01c3b78..6a26f19 100644
--- a/packages/@uppy/companion/lib/server/provider/instagram/graph/index.js
+++ b/packages/@uppy/companion/lib/server/provider/instagram/graph/index.js
@@ -1,29 +1,22 @@
 "use strict";
-var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function(receiver, state, kind, f) {
-  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
-  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) {
-    throw new TypeError("Cannot read private member from an object whose class did not declare it");
-  }
-  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
-};
-var _Instagram_instances, _a, _Instagram_withErrorHandling;
+var _a;
 Object.defineProperty(exports, "__esModule", { value: true });
-const got = require("got").default;
 const Provider = require("../../Provider");
 const { getURLMeta } = require("../../../helpers/request");
 const logger = require("../../../logger");
 const adaptData = require("./adapter");
 const { withProviderErrorHandling } = require("../../providerErrors");
 const { prepareStream } = require("../../../helpers/utils");
-const getClient = ({ token }) =>
-  got.extend({
+const got = require("../../../got");
+const getClient = async ({ token }) =>
+  (await got).extend({
     prefixUrl: "https://graph.instagram.com",
     headers: {
       authorization: `Bearer ${token}`,
     },
   });
 async function getMediaUrl({ token, id }) {
-  const body = await getClient({ token }).get(String(id), {
+  const body = await (await getClient({ token })).get(String(id), {
     searchParams: { fields: "media_url" },
     responseType: "json",
   }).json();
@@ -33,10 +26,6 @@ async function getMediaUrl({ token, id }) {
  * Adapter for API https://developers.facebook.com/docs/instagram-api/overview
  */
 class Instagram extends Provider {
-  constructor() {
-    super(...arguments);
-    _Instagram_instances.add(this);
-  }
   // for "grant"
   static getExtraConfig() {
     return {
@@ -48,37 +37,29 @@ class Instagram extends Provider {
     return "instagram";
   }
   async list({ directory, token, query = { cursor: null } }) {
-    return __classPrivateFieldGet(this, _Instagram_instances, "m", _Instagram_withErrorHandling).call(
-      this,
-      "provider.instagram.list.error",
-      async () => {
-        const qs = {
-          fields:
-            "id,media_type,thumbnail_url,media_url,timestamp,children{media_type,media_url,thumbnail_url,timestamp}",
-        };
-        if (query.cursor) {
-          qs.after = query.cursor;
-        }
-        const client = getClient({ token });
-        const [{ username }, list] = await Promise.all([
-          client.get("me", { searchParams: { fields: "username" }, responseType: "json" }).json(),
-          client.get("me/media", { searchParams: qs, responseType: "json" }).json(),
-        ]);
-        return adaptData(list, username, directory, query);
-      },
-    );
+    return this.#withErrorHandling("provider.instagram.list.error", async () => {
+      const qs = {
+        fields:
+          "id,media_type,thumbnail_url,media_url,timestamp,children{media_type,media_url,thumbnail_url,timestamp}",
+      };
+      if (query.cursor) {
+        qs.after = query.cursor;
+      }
+      const client = await getClient({ token });
+      const [{ username }, list] = await Promise.all([
+        client.get("me", { searchParams: { fields: "username" }, responseType: "json" }).json(),
+        client.get("me/media", { searchParams: qs, responseType: "json" }).json(),
+      ]);
+      return adaptData(list, username, directory, query);
+    });
   }
   async download({ id, token }) {
-    return __classPrivateFieldGet(this, _Instagram_instances, "m", _Instagram_withErrorHandling).call(
-      this,
-      "provider.instagram.download.error",
-      async () => {
-        const url = await getMediaUrl({ token, id });
-        const stream = got.stream.get(url, { responseType: "json" });
-        await prepareStream(stream);
-        return { stream };
-      },
-    );
+    return this.#withErrorHandling("provider.instagram.download.error", async () => {
+      const url = await getMediaUrl({ token, id });
+      const stream = (await got).stream.get(url, { responseType: "json" });
+      await prepareStream(stream);
+      return { stream };
+    });
   }
   // eslint-disable-next-line class-methods-use-this
   async thumbnail() {
@@ -87,44 +68,27 @@ class Instagram extends Provider {
     throw new Error("call to thumbnail is not implemented");
   }
   async size({ id, token }) {
-    return __classPrivateFieldGet(this, _Instagram_instances, "m", _Instagram_withErrorHandling).call(
-      this,
-      "provider.instagram.size.error",
-      async () => {
-        const url = await getMediaUrl({ token, id });
-        const { size } = await getURLMeta(url, true);
-        return size;
-      },
-    );
+    return this.#withErrorHandling("provider.instagram.size.error", async () => {
+      const url = await getMediaUrl({ token, id });
+      const { size } = await getURLMeta(url, true);
+      return size;
+    });
   }
   // eslint-disable-next-line class-methods-use-this
   async logout() {
     // access revoke is not supported by Instagram's API
     return { revoked: false, manual_revoke_url: "https://www.instagram.com/accounts/manage_access/" };
   }
+  // eslint-disable-next-line class-methods-use-this
+  async #withErrorHandling(tag, fn) {
+    return withProviderErrorHandling({
+      fn,
+      tag,
+      providerName: _a.authProvider,
+      isAuthError: (response) => typeof response.body === "object" && response.body?.error?.code === 190, // Invalid OAuth 2.0 Access Token
+      getJsonErrorMessage: (body) => body?.error?.message,
+    });
+  }
 }
-_a = Instagram,
-  _Instagram_instances = new WeakSet(),
-  _Instagram_withErrorHandling =
-    // eslint-disable-next-line class-methods-use-this
-    async function _Instagram_withErrorHandling(tag, fn) {
-      return withProviderErrorHandling({
-        fn,
-        tag,
-        providerName: _a.authProvider,
-        isAuthError: (response) => {
-          var _b, _c;
-          return typeof response.body === "object"
-            && ((_c = (_b = response.body) === null || _b === void 0 ? void 0 : _b.error) === null || _c === void 0
-                ? void 0
-                : _c.code) === 190;
-        }, // Invalid OAuth 2.0 Access Token
-        getJsonErrorMessage: (body) => {
-          var _b;
-          return (_b = body === null || body === void 0 ? void 0 : body.error) === null || _b === void 0
-            ? void 0
-            : _b.message;
-        },
-      });
-    };
+_a = Instagram;
 module.exports = Instagram;
diff --git a/packages/@uppy/companion/lib/server/provider/onedrive/adapter.js b/packages/@uppy/companion/lib/server/provider/onedrive/adapter.js
index b532c04..4631ce6 100644
--- a/packages/@uppy/companion/lib/server/provider/onedrive/adapter.js
+++ b/packages/@uppy/companion/lib/server/provider/onedrive/adapter.js
@@ -47,7 +47,7 @@ const getNextPagePath = ({ res, query: currentQuery, directory }) => {
   }
   const skipToken = new URL(nextLink).searchParams.get("$skiptoken");
   const query = { ...currentQuery, cursor: skipToken };
-  return `${directory !== null && directory !== void 0 ? directory : ""}?${new URLSearchParams(query).toString()}`;
+  return `${directory ?? ""}?${new URLSearchParams(query).toString()}`;
 };
 module.exports = (res, username, query, directory) => {
   const data = { username, items: [] };
diff --git a/packages/@uppy/companion/lib/server/provider/onedrive/index.js b/packages/@uppy/companion/lib/server/provider/onedrive/index.js
index d5350a1..9baad68 100644
--- a/packages/@uppy/companion/lib/server/provider/onedrive/index.js
+++ b/packages/@uppy/companion/lib/server/provider/onedrive/index.js
@@ -1,28 +1,21 @@
 "use strict";
-var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function(receiver, state, kind, f) {
-  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
-  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) {
-    throw new TypeError("Cannot read private member from an object whose class did not declare it");
-  }
-  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
-};
-var _OneDrive_instances, _a, _OneDrive_withErrorHandling;
+var _a;
 Object.defineProperty(exports, "__esModule", { value: true });
-const got = require("got").default;
 const Provider = require("../Provider");
 const logger = require("../../logger");
 const adaptData = require("./adapter");
 const { withProviderErrorHandling } = require("../providerErrors");
 const { prepareStream } = require("../../helpers/utils");
-const getClient = ({ token }) =>
-  got.extend({
+const got = require("../../got");
+const getClient = async ({ token }) =>
+  (await got).extend({
     prefixUrl: "https://graph.microsoft.com/v1.0",
     headers: {
       authorization: `Bearer ${token}`,
     },
   });
-const getOauthClient = () =>
-  got.extend({
+const getOauthClient = async () =>
+  (await got).extend({
     prefixUrl: "https://login.live.com",
   });
 const getRootPath = (query) => (query.driveId ? `drives/${query.driveId}` : "me/drive");
@@ -30,10 +23,6 @@ const getRootPath = (query) => (query.driveId ? `drives/${query.driveId}` : "me/
  * Adapter for API https://docs.microsoft.com/en-us/onedrive/developer/rest-api/
  */
 class OneDrive extends Provider {
-  constructor() {
-    super(...arguments);
-    _OneDrive_instances.add(this);
-  }
   static get authProvider() {
     return "microsoft";
   }
@@ -47,39 +36,31 @@ class OneDrive extends Provider {
    * @param {string} options.token
    */
   async list({ directory, query, token }) {
-    return __classPrivateFieldGet(this, _OneDrive_instances, "m", _OneDrive_withErrorHandling).call(
-      this,
-      "provider.onedrive.list.error",
-      async () => {
-        const path = directory ? `items/${directory}` : "root";
-        // https://learn.microsoft.com/en-us/graph/query-parameters?tabs=http#top-parameter
-        const pageSize = 999;
-        // const pageSize = 20 // to test pagination easily
-        const qs = { $expand: "thumbnails", $top: pageSize };
-        if (query.cursor) {
-          qs.$skiptoken = query.cursor;
-        }
-        const client = getClient({ token });
-        const [{ mail, userPrincipalName }, list] = await Promise.all([
-          client.get("me", { responseType: "json" }).json(),
-          client.get(`${getRootPath(query)}/${path}/children`, { searchParams: qs, responseType: "json" }).json(),
-        ]);
-        return adaptData(list, mail || userPrincipalName, query, directory);
-      },
-    );
+    return this.#withErrorHandling("provider.onedrive.list.error", async () => {
+      const path = directory ? `items/${directory}` : "root";
+      // https://learn.microsoft.com/en-us/graph/query-parameters?tabs=http#top-parameter
+      const pageSize = 999;
+      // const pageSize = 20 // to test pagination easily
+      const qs = { $expand: "thumbnails", $top: pageSize };
+      if (query.cursor) {
+        qs.$skiptoken = query.cursor;
+      }
+      const client = await getClient({ token });
+      const [{ mail, userPrincipalName }, list] = await Promise.all([
+        client.get("me", { responseType: "json" }).json(),
+        client.get(`${getRootPath(query)}/${path}/children`, { searchParams: qs, responseType: "json" }).json(),
+      ]);
+      return adaptData(list, mail || userPrincipalName, query, directory);
+    });
   }
   async download({ id, token, query }) {
-    return __classPrivateFieldGet(this, _OneDrive_instances, "m", _OneDrive_withErrorHandling).call(
-      this,
-      "provider.onedrive.download.error",
-      async () => {
-        const stream = getClient({ token }).stream.get(`${getRootPath(query)}/items/${id}/content`, {
-          responseType: "json",
-        });
-        await prepareStream(stream);
-        return { stream };
-      },
-    );
+    return this.#withErrorHandling("provider.onedrive.download.error", async () => {
+      const stream = (await getClient({ token })).stream.get(`${getRootPath(query)}/items/${id}/content`, {
+        responseType: "json",
+      });
+      await prepareStream(stream);
+      return { stream };
+    });
   }
   // eslint-disable-next-line class-methods-use-this
   async thumbnail() {
@@ -88,15 +69,12 @@ class OneDrive extends Provider {
     throw new Error("call to thumbnail is not implemented");
   }
   async size({ id, query, token }) {
-    return __classPrivateFieldGet(this, _OneDrive_instances, "m", _OneDrive_withErrorHandling).call(
-      this,
-      "provider.onedrive.size.error",
-      async () => {
-        const { size } = await getClient({ token }).get(`${getRootPath(query)}/items/${id}`, { responseType: "json" })
-          .json();
-        return size;
-      },
-    );
+    return this.#withErrorHandling("provider.onedrive.size.error", async () => {
+      const { size } = await (await getClient({ token })).get(`${getRootPath(query)}/items/${id}`, {
+        responseType: "json",
+      }).json();
+      return size;
+    });
   }
   // eslint-disable-next-line class-methods-use-this
   async logout() {
@@ -104,47 +82,36 @@ class OneDrive extends Provider {
     return { revoked: false, manual_revoke_url: "https://account.live.com/consent/Manage" };
   }
   async refreshToken({ clientId, clientSecret, refreshToken, redirectUri }) {
-    return __classPrivateFieldGet(this, _OneDrive_instances, "m", _OneDrive_withErrorHandling).call(
-      this,
-      "provider.onedrive.token.refresh.error",
-      async () => {
-        const { access_token: accessToken } = await getOauthClient().post("oauth20_token.srf", {
-          responseType: "json",
-          form: {
-            refresh_token: refreshToken,
-            grant_type: "refresh_token",
-            client_id: clientId,
-            client_secret: clientSecret,
-            redirect_uri: redirectUri,
-          },
-        }).json();
-        return { accessToken };
-      },
-    );
+    return this.#withErrorHandling("provider.onedrive.token.refresh.error", async () => {
+      const { access_token: accessToken } = await (await getOauthClient()).post("oauth20_token.srf", {
+        responseType: "json",
+        form: {
+          refresh_token: refreshToken,
+          grant_type: "refresh_token",
+          client_id: clientId,
+          client_secret: clientSecret,
+          redirect_uri: redirectUri,
+        },
+      }).json();
+      return { accessToken };
+    });
+  }
+  // eslint-disable-next-line class-methods-use-this
+  async #withErrorHandling(tag, fn) {
+    return withProviderErrorHandling({
+      fn,
+      tag,
+      providerName: _a.authProvider,
+      isAuthError: (response) => response.statusCode === 401,
+      isUserFacingError: (response) => [400, 403].includes(response.statusCode),
+      // onedrive gives some errors here that the user might want to know about
+      // e.g. these happen if you try to login to a users in an organization,
+      // without an Office365 licence or OneDrive account setup completed
+      // 400: Tenant does not have a SPO license
+      // 403: You do not have access to create this personal site or you do not have a valid license
+      getJsonErrorMessage: (body) => body?.error?.message,
+    });
   }
 }
-_a = OneDrive,
-  _OneDrive_instances = new WeakSet(),
-  _OneDrive_withErrorHandling =
-    // eslint-disable-next-line class-methods-use-this
-    async function _OneDrive_withErrorHandling(tag, fn) {
-      return withProviderErrorHandling({
-        fn,
-        tag,
-        providerName: _a.authProvider,
-        isAuthError: (response) => response.statusCode === 401,
-        isUserFacingError: (response) => [400, 403].includes(response.statusCode),
-        // onedrive gives some errors here that the user might want to know about
-        // e.g. these happen if you try to login to a users in an organization,
-        // without an Office365 licence or OneDrive account setup completed
-        // 400: Tenant does not have a SPO license
-        // 403: You do not have access to create this personal site or you do not have a valid license
-        getJsonErrorMessage: (body) => {
-          var _b;
-          return (_b = body === null || body === void 0 ? void 0 : body.error) === null || _b === void 0
-            ? void 0
-            : _b.message;
-        },
-      });
-    };
+_a = OneDrive;
 module.exports = OneDrive;
diff --git a/packages/@uppy/companion/lib/server/provider/providerErrors.js b/packages/@uppy/companion/lib/server/provider/providerErrors.js
index 1595560..0b6dbc6 100644
--- a/packages/@uppy/companion/lib/server/provider/providerErrors.js
+++ b/packages/@uppy/companion/lib/server/provider/providerErrors.js
@@ -16,7 +16,6 @@ const { ProviderApiError, ProviderUserError, ProviderAuthError } = require("./er
 async function withProviderErrorHandling(
   { fn, tag, providerName, isAuthError = () => false, isUserFacingError = () => false, getJsonErrorMessage },
 ) {
-  var _a, _b;
   function getErrorMessage({ statusCode, body }) {
     if (typeof body === "object") {
       const message = getJsonErrorMessage(body);
@@ -34,10 +33,10 @@ async function withProviderErrorHandling(
   } catch (err) {
     let statusCode;
     let body;
-    if ((err === null || err === void 0 ? void 0 : err.name) === "HTTPError") {
-      statusCode = (_a = err.response) === null || _a === void 0 ? void 0 : _a.statusCode;
-      body = (_b = err.response) === null || _b === void 0 ? void 0 : _b.body;
-    } else if ((err === null || err === void 0 ? void 0 : err.name) === "StreamHttpJsonError") {
+    if (err?.name === "HTTPError") {
+      statusCode = err.response?.statusCode;
+      body = err.response?.body;
+    } else if (err?.name === "StreamHttpJsonError") {
       statusCode = err.statusCode;
       body = err.responseJson;
     }
diff --git a/packages/@uppy/companion/lib/server/provider/unsplash/index.js b/packages/@uppy/companion/lib/server/provider/unsplash/index.js
index 915644b..1d6b8b4 100644
--- a/packages/@uppy/companion/lib/server/provider/unsplash/index.js
+++ b/packages/@uppy/companion/lib/server/provider/unsplash/index.js
@@ -1,23 +1,15 @@
 "use strict";
-var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function(receiver, state, kind, f) {
-  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
-  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) {
-    throw new TypeError("Cannot read private member from an object whose class did not declare it");
-  }
-  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
-};
-var _Unsplash_instances, _Unsplash_withErrorHandling;
 Object.defineProperty(exports, "__esModule", { value: true });
-const got = require("got").default;
 const Provider = require("../Provider");
 const { getURLMeta } = require("../../helpers/request");
 const adaptData = require("./adapter");
 const { withProviderErrorHandling } = require("../providerErrors");
 const { prepareStream } = require("../../helpers/utils");
 const { ProviderApiError } = require("../error");
+const got = require("../../got");
 const BASE_URL = "https://api.unsplash.com";
-const getClient = ({ token }) =>
-  got.extend({
+const getClient = async ({ token }) =>
+  (await got).extend({
     prefixUrl: BASE_URL,
     headers: {
       authorization: `Client-ID ${token}`,
@@ -28,68 +20,52 @@ const getPhotoMeta = async (client, id) => client.get(`photos/${id}`, { response
  * Adapter for API https://api.unsplash.com
  */
 class Unsplash extends Provider {
-  constructor() {
-    super(...arguments);
-    _Unsplash_instances.add(this);
-  }
   async list({ token, query = { cursor: null, q: null } }) {
     if (typeof query.q !== "string") {
       throw new ProviderApiError("Search query missing", 400);
     }
-    return __classPrivateFieldGet(this, _Unsplash_instances, "m", _Unsplash_withErrorHandling).call(
-      this,
-      "provider.unsplash.list.error",
-      async () => {
-        const qs = { per_page: 40, query: query.q };
-        if (query.cursor) {
-          qs.page = query.cursor;
-        }
-        const response = await getClient({ token }).get("search/photos", { searchParams: qs, responseType: "json" })
-          .json();
-        return adaptData(response, query);
-      },
-    );
+    return this.#withErrorHandling("provider.unsplash.list.error", async () => {
+      const qs = { per_page: 40, query: query.q };
+      if (query.cursor) {
+        qs.page = query.cursor;
+      }
+      const response = await (await getClient({ token })).get("search/photos", {
+        searchParams: qs,
+        responseType: "json",
+      }).json();
+      return adaptData(response, query);
+    });
   }
   async download({ id, token }) {
-    return __classPrivateFieldGet(this, _Unsplash_instances, "m", _Unsplash_withErrorHandling).call(
-      this,
-      "provider.unsplash.download.error",
-      async () => {
-        const client = getClient({ token });
-        const { links: { download: url, download_location: attributionUrl } } = await getPhotoMeta(client, id);
-        const stream = got.stream.get(url, { responseType: "json" });
-        await prepareStream(stream);
-        // To attribute the author of the image, we call the `download_location`
-        // endpoint to increment the download count on Unsplash.
-        // https://help.unsplash.com/en/articles/2511258-guideline-triggering-a-download
-        await client.get(attributionUrl, { prefixUrl: "", responseType: "json" });
-        // finally, stream on!
-        return { stream };
-      },
-    );
+    return this.#withErrorHandling("provider.unsplash.download.error", async () => {
+      const client = await getClient({ token });
+      const { links: { download: url, download_location: attributionUrl } } = await getPhotoMeta(client, id);
+      const stream = (await got).stream.get(url, { responseType: "json" });
+      await prepareStream(stream);
+      // To attribute the author of the image, we call the `download_location`
+      // endpoint to increment the download count on Unsplash.
+      // https://help.unsplash.com/en/articles/2511258-guideline-triggering-a-download
+      await client.get(attributionUrl, { prefixUrl: "", responseType: "json" });
+      // finally, stream on!
+      return { stream };
+    });
   }
   async size({ id, token }) {
-    return __classPrivateFieldGet(this, _Unsplash_instances, "m", _Unsplash_withErrorHandling).call(
-      this,
-      "provider.unsplash.size.error",
-      async () => {
-        const { links: { download: url } } = await getPhotoMeta(getClient({ token }), id);
-        const { size } = await getURLMeta(url, true);
-        return size;
-      },
-    );
+    return this.#withErrorHandling("provider.unsplash.size.error", async () => {
+      const { links: { download: url } } = await getPhotoMeta(await getClient({ token }), id);
+      const { size } = await getURLMeta(url, true);
+      return size;
+    });
+  }
+  // eslint-disable-next-line class-methods-use-this
+  async #withErrorHandling(tag, fn) {
+    // @ts-ignore
+    return withProviderErrorHandling({
+      fn,
+      tag,
+      providerName: "Unsplash",
+      getJsonErrorMessage: (body) => body?.errors && String(body.errors),
+    });
   }
 }
-_Unsplash_instances = new WeakSet(),
-  _Unsplash_withErrorHandling =
-    // eslint-disable-next-line class-methods-use-this
-    async function _Unsplash_withErrorHandling(tag, fn) {
-      // @ts-ignore
-      return withProviderErrorHandling({
-        fn,
-        tag,
-        providerName: "Unsplash",
-        getJsonErrorMessage: (body) => (body === null || body === void 0 ? void 0 : body.errors) && String(body.errors),
-      });
-    };
 module.exports = Unsplash;
diff --git a/packages/@uppy/companion/lib/server/provider/zoom/index.js b/packages/@uppy/companion/lib/server/provider/zoom/index.js
index 9ee6e58..59b4017 100644
--- a/packages/@uppy/companion/lib/server/provider/zoom/index.js
+++ b/packages/@uppy/companion/lib/server/provider/zoom/index.js
@@ -1,24 +1,17 @@
 "use strict";
-var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function(receiver, state, kind, f) {
-  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
-  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) {
-    throw new TypeError("Cannot read private member from an object whose class did not declare it");
-  }
-  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
-};
-var _Zoom_instances, _a, _Zoom_withErrorHandling;
+var _a;
 Object.defineProperty(exports, "__esModule", { value: true });
-const got = require("got").default;
 const moment = require("moment-timezone");
 const Provider = require("../Provider");
 const { initializeData, adaptData } = require("./adapter");
 const { withProviderErrorHandling } = require("../providerErrors");
 const { prepareStream, getBasicAuthHeader } = require("../../helpers/utils");
+const got = require("../../got");
 const BASE_URL = "https://zoom.us/v2";
 const PAGE_SIZE = 300;
 const DEAUTH_EVENT_NAME = "app_deauthorized";
-const getClient = ({ token }) =>
-  got.extend({
+const getClient = async ({ token }) =>
+  (await got).extend({
     prefixUrl: BASE_URL,
     headers: {
       authorization: `Bearer ${token}`,
@@ -36,10 +29,6 @@ async function findFile({ client, meetingId, fileId, recordingStart }) {
  * Adapter for API https://marketplace.zoom.us/docs/api-reference/zoom-api
  */
 class Zoom extends Provider {
-  constructor() {
-    super(...arguments);
-    _Zoom_instances.add(this);
-  }
   static get authProvider() {
     return "zoom";
   }
@@ -48,141 +37,119 @@ class Zoom extends Provider {
     - drill down for specific files in each month
     */
   async list(options) {
-    return __classPrivateFieldGet(this, _Zoom_instances, "m", _Zoom_withErrorHandling).call(
-      this,
-      "provider.zoom.list.error",
-      async () => {
-        const { token } = options;
-        const query = options.query || {};
-        const { cursor, from, to } = query;
-        const meetingId = options.directory || "";
-        const client = getClient({ token });
-        const user = await client.get("users/me", { responseType: "json" }).json();
-        const { timezone } = user;
-        if (!from && !to && !meetingId) {
-          const end = cursor && moment.utc(cursor).endOf("day").tz(timezone || "UTC");
-          return initializeData(user, end);
-        }
-        if (from && to) {
-          /*  we need to convert local datetime to UTC date for Zoom query
+    return this.#withErrorHandling("provider.zoom.list.error", async () => {
+      const { token } = options;
+      const query = options.query || {};
+      const { cursor, from, to } = query;
+      const meetingId = options.directory || "";
+      const client = await getClient({ token });
+      const user = await client.get("users/me", { responseType: "json" }).json();
+      const { timezone } = user;
+      if (!from && !to && !meetingId) {
+        const end = cursor && moment.utc(cursor).endOf("day").tz(timezone || "UTC");
+        return initializeData(user, end);
+      }
+      if (from && to) {
+        /*  we need to convert local datetime to UTC date for Zoom query
                 eg: user in PST (UTC-08:00) wants 2020-08-01 (00:00) to 2020-08-31 (23:59)
                 => in UTC, that's 2020-07-31 (16:00) to 2020-08-31 (15:59)
                 */
-          const searchParams = {
-            page_size: PAGE_SIZE,
-            from: moment.tz(from, timezone || "UTC").startOf("day").tz("UTC").format("YYYY-MM-DD"),
-            to: moment.tz(to, timezone || "UTC").endOf("day").tz("UTC").format("YYYY-MM-DD"),
-          };
-          if (cursor) {
-            searchParams.next_page_token = cursor;
-          }
-          const meetingsInfo = await client.get("users/me/recordings", { searchParams, responseType: "json" }).json();
-          return adaptData(user, meetingsInfo, query);
-        }
-        if (meetingId) {
-          const recordingInfo = await client.get(`meetings/${encodeURIComponent(meetingId)}/recordings`, {
-            responseType: "json",
-          }).json();
-          return adaptData(user, recordingInfo, query);
+        const searchParams = {
+          page_size: PAGE_SIZE,
+          from: moment.tz(from, timezone || "UTC").startOf("day").tz("UTC").format("YYYY-MM-DD"),
+          to: moment.tz(to, timezone || "UTC").endOf("day").tz("UTC").format("YYYY-MM-DD"),
+        };
+        if (cursor) {
+          searchParams.next_page_token = cursor;
         }
-        throw new Error("Invalid list() arguments");
-      },
-    );
+        const meetingsInfo = await client.get("users/me/recordings", { searchParams, responseType: "json" }).json();
+        return adaptData(user, meetingsInfo, query);
+      }
+      if (meetingId) {
+        const recordingInfo = await client.get(`meetings/${encodeURIComponent(meetingId)}/recordings`, {
+          responseType: "json",
+        }).json();
+        return adaptData(user, recordingInfo, query);
+      }
+      throw new Error("Invalid list() arguments");
+    });
   }
   async download({ id: meetingId, token, query }) {
-    return __classPrivateFieldGet(this, _Zoom_instances, "m", _Zoom_withErrorHandling).call(
-      this,
-      "provider.zoom.download.error",
-      async () => {
-        // meeting id + file id required
-        // cc files don't have an ID or size
-        const { recordingStart, recordingId: fileId } = query;
-        const client = getClient({ token });
-        const foundFile = await findFile({ client, meetingId, fileId, recordingStart });
-        const url = foundFile === null || foundFile === void 0 ? void 0 : foundFile.download_url;
-        if (!url) {
-          throw new Error("Download URL not found");
-        }
-        const stream = client.stream.get(`${url}?access_token=${token}`, { prefixUrl: "", responseType: "json" });
-        await prepareStream(stream);
-        return { stream };
-      },
-    );
+    return this.#withErrorHandling("provider.zoom.download.error", async () => {
+      // meeting id + file id required
+      // cc files don't have an ID or size
+      const { recordingStart, recordingId: fileId } = query;
+      const client = await getClient({ token });
+      const foundFile = await findFile({ client, meetingId, fileId, recordingStart });
+      const url = foundFile?.download_url;
+      if (!url) {
+        throw new Error("Download URL not found");
+      }
+      const stream = client.stream.get(`${url}?access_token=${token}`, { prefixUrl: "", responseType: "json" });
+      await prepareStream(stream);
+      return { stream };
+    });
   }
   async size({ id: meetingId, token, query }) {
-    return __classPrivateFieldGet(this, _Zoom_instances, "m", _Zoom_withErrorHandling).call(
-      this,
-      "provider.zoom.size.error",
-      async () => {
-        const client = getClient({ token });
-        const { recordingStart, recordingId: fileId } = query;
-        const foundFile = await findFile({ client, meetingId, fileId, recordingStart });
-        if (!foundFile) {
-          throw new Error("File not found");
-        }
-        return foundFile.file_size; // Note: May be undefined.
-      },
-    );
+    return this.#withErrorHandling("provider.zoom.size.error", async () => {
+      const client = await getClient({ token });
+      const { recordingStart, recordingId: fileId } = query;
+      const foundFile = await findFile({ client, meetingId, fileId, recordingStart });
+      if (!foundFile) {
+        throw new Error("File not found");
+      }
+      return foundFile.file_size; // Note: May be undefined.
+    });
   }
   async logout({ companion, token }) {
-    return __classPrivateFieldGet(this, _Zoom_instances, "m", _Zoom_withErrorHandling).call(
-      this,
-      "provider.zoom.logout.error",
-      async () => {
-        const { key, secret } = await companion.getProviderCredentials();
-        const { status } = await got.post("https://zoom.us/oauth/revoke", {
-          searchParams: { token },
-          headers: { Authorization: getBasicAuthHeader(key, secret) },
-          responseType: "json",
-        }).json();
-        return { revoked: status === "success" };
-      },
-    );
+    return this.#withErrorHandling("provider.zoom.logout.error", async () => {
+      const { key, secret } = await companion.getProviderCredentials();
+      const { status } = await (await got).post("https://zoom.us/oauth/revoke", {
+        searchParams: { token },
+        headers: { Authorization: getBasicAuthHeader(key, secret) },
+        responseType: "json",
+      }).json();
+      return { revoked: status === "success" };
+    });
   }
   async deauthorizationCallback({ companion, body, headers }) {
-    return __classPrivateFieldGet(this, _Zoom_instances, "m", _Zoom_withErrorHandling).call(
-      this,
-      "provider.zoom.deauth.error",
-      async () => {
-        if (!body || body.event !== DEAUTH_EVENT_NAME) {
-          return { data: {}, status: 400 };
-        }
-        const { verificationToken, key, secret } = await companion.getProviderCredentials();
-        const tokenSupplied = headers.authorization;
-        if (!tokenSupplied || verificationToken !== tokenSupplied) {
-          return { data: {}, status: 400 };
-        }
-        await got.post("https://api.zoom.us/oauth/data/compliance", {
-          headers: { Authorization: getBasicAuthHeader(key, secret) },
-          json: {
-            client_id: key,
-            user_id: body.payload.user_id,
-            account_id: body.payload.account_id,
-            deauthorization_event_received: body.payload,
-            compliance_completed: true,
-          },
-          responseType: "json",
-        });
-        return {};
-      },
-    );
+    return this.#withErrorHandling("provider.zoom.deauth.error", async () => {
+      if (!body || body.event !== DEAUTH_EVENT_NAME) {
+        return { data: {}, status: 400 };
+      }
+      const { verificationToken, key, secret } = await companion.getProviderCredentials();
+      const tokenSupplied = headers.authorization;
+      if (!tokenSupplied || verificationToken !== tokenSupplied) {
+        return { data: {}, status: 400 };
+      }
+      await (await got).post("https://api.zoom.us/oauth/data/compliance", {
+        headers: { Authorization: getBasicAuthHeader(key, secret) },
+        json: {
+          client_id: key,
+          user_id: body.payload.user_id,
+          account_id: body.payload.account_id,
+          deauthorization_event_received: body.payload,
+          compliance_completed: true,
+        },
+        responseType: "json",
+      });
+      return {};
+    });
+  }
+  // eslint-disable-next-line class-methods-use-this
+  async #withErrorHandling(tag, fn) {
+    const authErrorCodes = [
+      124, // expired token
+      401,
+    ];
+    return withProviderErrorHandling({
+      fn,
+      tag,
+      providerName: _a.authProvider,
+      isAuthError: (response) => authErrorCodes.includes(response.statusCode),
+      getJsonErrorMessage: (body) => body?.message,
+    });
   }
 }
-_a = Zoom,
-  _Zoom_instances = new WeakSet(),
-  _Zoom_withErrorHandling =
-    // eslint-disable-next-line class-methods-use-this
-    async function _Zoom_withErrorHandling(tag, fn) {
-      const authErrorCodes = [
-        124, // expired token
-        401,
-      ];
-      return withProviderErrorHandling({
-        fn,
-        tag,
-        providerName: _a.authProvider,
-        isAuthError: (response) => authErrorCodes.includes(response.statusCode),
-        getJsonErrorMessage: (body) => body === null || body === void 0 ? void 0 : body.message,
-      });
-    };
+_a = Zoom;
 module.exports = Zoom;
diff --git a/packages/@uppy/companion/lib/server/redis.js b/packages/@uppy/companion/lib/server/redis.js
index 205a518..14e804f 100644
--- a/packages/@uppy/companion/lib/server/redis.js
+++ b/packages/@uppy/companion/lib/server/redis.js
@@ -30,10 +30,7 @@ function createClient(companionOptions) {
   return redisClient;
 }
 module.exports.client = (companionOptions) => {
-  if (
-    !(companionOptions === null || companionOptions === void 0 ? void 0 : companionOptions.redisUrl)
-    && !(companionOptions === null || companionOptions === void 0 ? void 0 : companionOptions.redisOptions)
-  ) {
+  if (!companionOptions?.redisUrl && !companionOptions?.redisOptions) {
     return redisClient;
   }
   return createClient(companionOptions);
diff --git a/packages/@uppy/core/lib/Uppy.js b/packages/@uppy/core/lib/Uppy.js
index 70dcf30..808a8e1 100644
--- a/packages/@uppy/core/lib/Uppy.js
+++ b/packages/@uppy/core/lib/Uppy.js
@@ -1,3 +1,4 @@
+let _Symbol$for, _Symbol$for2;
 function _classPrivateFieldLooseBase(receiver, privateKey) {
   if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {
     throw new TypeError("attempted to use private field on non-instance");
@@ -51,6 +52,8 @@ var _createUpload = _classPrivateFieldLooseKey("createUpload");
 var _getUpload = _classPrivateFieldLooseKey("getUpload");
 var _removeUpload = _classPrivateFieldLooseKey("removeUpload");
 var _runUpload = _classPrivateFieldLooseKey("runUpload");
+_Symbol$for = Symbol.for("uppy test: getPlugins");
+_Symbol$for2 = Symbol.for("uppy test: createUpload");
 export class Uppy {
   constructor(_opts) {
     Object.defineProperty(this, _runUpload, {
@@ -829,7 +832,7 @@ export class Uppy {
     }
     return undefined;
   }
-  [Symbol.for("uppy test: getPlugins")](type) {
+  [_Symbol$for](type) {
     return _classPrivateFieldLooseBase(this, _plugins)[_plugins][type];
   }
   iteratePlugins(method) {
@@ -939,7 +942,7 @@ export class Uppy {
     }
     return _classPrivateFieldLooseBase(this, _runUpload)[_runUpload](uploadID);
   }
-  [Symbol.for("uppy test: createUpload")]() {
+  [_Symbol$for2]() {
     return _classPrivateFieldLooseBase(this, _createUpload)[_createUpload](...arguments);
   }
   addResultData(uploadID, data) {
diff --git a/packages/@uppy/dashboard/lib/components/AddFiles.js b/packages/@uppy/dashboard/lib/components/AddFiles.js
index 07770cb..48fbe1b 100644
--- a/packages/@uppy/dashboard/lib/components/AddFiles.js
+++ b/packages/@uppy/dashboard/lib/components/AddFiles.js
@@ -1,4 +1,6 @@
+let _Symbol$for;
 import { Component, Fragment, h } from "preact";
+_Symbol$for = Symbol.for("uppy test: disable unused locale key warning");
 class AddFiles extends Component {
   constructor() {
     super(...arguments);
@@ -333,7 +335,7 @@ class AddFiles extends Component {
       );
     };
   }
-  [Symbol.for("uppy test: disable unused locale key warning")]() {
+  [_Symbol$for]() {
     this.props.i18nArray("dropPasteBoth");
     this.props.i18nArray("dropPasteFiles");
     this.props.i18nArray("dropPasteFolders");
diff --git a/packages/@uppy/store-redux/lib/index.js b/packages/@uppy/store-redux/lib/index.js
index cdef3c5..e69124d 100644
--- a/packages/@uppy/store-redux/lib/index.js
+++ b/packages/@uppy/store-redux/lib/index.js
@@ -1,3 +1,4 @@
+let _Symbol$for;
 function _classPrivateFieldLooseBase(receiver, privateKey) {
   if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {
     throw new TypeError("attempted to use private field on non-instance");
@@ -25,6 +26,7 @@ function getPatch(prev, next) {
 var _id = _classPrivateFieldLooseKey("id");
 var _selector = _classPrivateFieldLooseKey("selector");
 var _store = _classPrivateFieldLooseKey("store");
+_Symbol$for = Symbol.for("uppy test: get id");
 export class ReduxStore {
   constructor(opts) {
     Object.defineProperty(this, _id, {
@@ -68,7 +70,7 @@ export class ReduxStore {
       }
     });
   }
-  [Symbol.for("uppy test: get id")]() {
+  [_Symbol$for]() {
     return _classPrivateFieldLooseBase(this, _id)[_id];
   }
 }
diff --git a/packages/@uppy/url/lib/Url.js b/packages/@uppy/url/lib/Url.js
index 0bd182b..49e2ea9 100644
--- a/packages/@uppy/url/lib/Url.js
+++ b/packages/@uppy/url/lib/Url.js
@@ -1,4 +1,4 @@
-var _Url;
+var _class;
 import { RequestClient } from "@uppy/companion-client";
 import { UIPlugin } from "@uppy/core";
 import toArray from "@uppy/utils/lib/toArray";
@@ -165,7 +165,7 @@ export default class Url extends UIPlugin {
     this.unmount();
   }
 }
-_Url = Url;
+_class = Url;
 Url.VERSION = packageJson.version;
-Url.requestClientId = _Url.name;
+Url.requestClientId = _class.name;
 Url.prototype.canHandleRootDrop = canHandleRootDrop;

@Murderlon
Copy link
Member

CI failing though

This comment was marked as resolved.

@aduh95
Copy link
Contributor Author

aduh95 commented Mar 28, 2024

I'm not sure why the CI is failing. I'm able to reproduce the failure on Node.js 20.x and 21.x, but not on 18.x. Here's what I've tried:

  • Cherry-picking the commit from Mikael upgrading Got to 12.x
  • Upgrading to Got 13.x
  • Remove other deps that were polyfilling APIs already built-in the supported versions of Node.js.

I've also tried upgrading to Got 14.x (which has dropped support for 18.x) to see if it would resolve the 20.x failure, but no.

That command was useful for debugging the failing test: DEBUG=nock.* corepack yarn run test:companion uploader --no-coverage

@Murderlon
Copy link
Member

Maybe @mifi has some ideas

@mifi
Copy link
Contributor

mifi commented Apr 5, 2024

not obvious to me why it's failing. since you're able to reproduce it locally, it might be an idea to isolate each of the failing tests (one at a time) and then revert one change at a time and see when the test goes green (or binary search)

also adjust tests to match a different form data boundary:
`--form-data-boundary-[a-z0-9]+ instead of ----------------------------\d+`

note that `await blob(stream)` cannot be used because
it reads everything into memory
we don't know how many gigabytes the user is uploading so
we cannot read into memory
and upgrade jest/nock
because nock/nock#2595
the issue seems to have been introduced in node.js 20.10
taskcluster/taskcluster#6923
@mifi
Copy link
Contributor

mifi commented Apr 15, 2024

i managed to get everything working. note that i had to fix the node version to 20.9, because there seems to be an issue with newer node versions, see this commit for more info 9a66c5f

@aduh95
Copy link
Contributor Author

aduh95 commented Apr 16, 2024

As discussed in the Uppy call, let's try to get latest 20.x / 21.x working before merging (failures seems to be limited to dev dependencies we're using for the tests, so hopefully we can patch them).

@mifi
Copy link
Contributor

mifi commented Apr 16, 2024

I couldn't figure out how to patch got to emit the correct end event. I also tried to upgrade got to 14 but it's still failing, so the issue is clearly in nock.

Maybe we can just say that we support node.js 20.x, even though we don't run our CI unit tests for all node versions?

If not I could try to rewrite the 4 failing tests to use a node.js HTTP server instead of nock. Does anyone know of any library that allows easy mocking http server endpoints? i could use node http.createServer however i'm afraid I have to reinvent the wheel and I'm worried that the server's TCP socket is going to be stuck in the TIME_WAIT state between tests thereby failing in the next test.

@Murderlon
Copy link
Member

Maybe we can just say that we support node.js 20.x, even though we don't run our CI unit tests for all node versions?

This wouldn't work long-term, sooner of later we have to test with 20.x so might as well figure it out now.

How you tried different versions of nock, if that's the problem?

@aduh95 aduh95 requested review from Murderlon and mifi April 22, 2024 08:41
@aduh95 aduh95 merged commit a565c3e into 4.x Apr 22, 2024
14 checks passed
@aduh95 aduh95 deleted the companion-supported-versions branch April 22, 2024 13:44
github-actions bot added a commit that referenced this pull request Apr 29, 2024
| Package                |      Version | Package                |      Version |
| ---------------------- | ------------ | ---------------------- | ------------ |
| @uppy/angular          | 0.7.0-beta.4 | @uppy/instagram        | 4.0.0-beta.4 |
| @uppy/audio            | 2.0.0-beta.4 | @uppy/onedrive         | 4.0.0-beta.4 |
| @uppy/aws-s3-multipart | 4.0.0-beta.4 | @uppy/provider-views   | 4.0.0-beta.4 |
| @uppy/box              | 3.0.0-beta.4 | @uppy/react            | 4.0.0-beta.4 |
| @uppy/companion        | 5.0.0-beta.4 | @uppy/status-bar       | 4.0.0-beta.4 |
| @uppy/companion-client | 4.0.0-beta.4 | @uppy/store-redux      | 4.0.0-beta.2 |
| @uppy/compressor       | 2.0.0-beta.4 | @uppy/svelte           | 4.0.0-beta.2 |
| @uppy/core             | 4.0.0-beta.4 | @uppy/transloadit      | 4.0.0-beta.4 |
| @uppy/dashboard        | 4.0.0-beta.4 | @uppy/unsplash         | 4.0.0-beta.4 |
| @uppy/drop-target      | 3.0.0-beta.4 | @uppy/url              | 4.0.0-beta.4 |
| @uppy/dropbox          | 4.0.0-beta.4 | @uppy/utils            | 6.0.0-beta.4 |
| @uppy/facebook         | 4.0.0-beta.4 | @uppy/webcam           | 4.0.0-beta.4 |
| @uppy/file-input       | 4.0.0-beta.4 | @uppy/xhr-upload       | 4.0.0-beta.2 |
| @uppy/form             | 4.0.0-beta.2 | @uppy/zoom             | 3.0.0-beta.4 |
| @uppy/google-drive     | 4.0.0-beta.4 | uppy                   | 4.0.0-beta.4 |
| @uppy/image-editor     | 3.0.0-beta.2 |                        |              |

- meta: Upgrade Yarn to 4.x (Merlijn Vos / #4849)
- @uppy/utils: fix fetcher export (Murderlon)
- @uppy/xhr-upload: refactor to use `fetcher` (Merlijn Vos / #5074)
- docs: use StackBlitz for all examples/issue template (Merlijn Vos / #5125)
- meta: Update yarn.lock (Murderlon)
- @uppy/svelte: Add svelte 5 as peer dep (frederikhors / #5122)
- meta: Bump docker/setup-buildx-action from 2 to 3 (dependabot[bot] / #5124)
- meta: Bump actions/checkout from 3 to 4 (dependabot[bot] / #5123)
- @uppy/dashboard,@uppy/provider-views: Remove JSX global type everywhere (Merlijn Vos / #5117)
- @uppy/utils: improve return type of `dataURItoFile` (Antoine du Hamel / #5112)
- @uppy/drop-target: change drop event type to DragEvent (Alireza Heydari / #5107)
- @uppy/image-editor: fix label definitions (Antoine du Hamel / #5111)
- meta: bump Prettier version (Antoine du Hamel / #5114)
- @uppy/provider-views: bring back "loaded X files..." (Mikael Finstad / #5097)
- @uppy/dashboard: fix type of trigger option (Merlijn Vos / #5106)
- meta: fix linter (Antoine du Hamel)
- @uppy/companion: bump Node.js version support matrix (Antoine du Hamel / #5035)
- @uppy/form: fix `submitOnSuccess` and `triggerUploadOnSubmit` combination (Merlijn Vos / #5058)
- meta: Bump docker/build-push-action from 3 to 5 (dependabot[bot] / #5105)
- meta: Bump akhileshns/heroku-deploy from 3.12.12 to 3.13.15 (dependabot[bot] / #5102)
- meta: Bump docker/login-action from 2 to 3 (dependabot[bot] / #5101)
- meta: Bump actions/download-artifact from 3 to 4 (dependabot[bot])
- meta: Bump actions/upload-artifact from 3 to 4 (dependabot[bot])
- @uppy/react: remove `useUppy` & reintroduce `useUppyState` (Merlijn Vos / #5059)
- meta: docs: add back markdown files (Antoine du Hamel / #5064)
- meta: fix custom provider example (Merlijn Vos / #5079)
- @uppy/utils: add fetcher (Merlijn Vos / #5073)
- meta: Fix prettier (Murderlon)
- @uppy/dashboard: add missing `x-zip-compress` archive type (Younes / #5081)
- meta: Bump docker/metadata-action from 4 to 5 (dependabot[bot] / #5086)
- meta: Bump actions/setup-node from 3 to 4 (dependabot[bot] / #5087)
- meta: Bump docker/setup-qemu-action from 2 to 3 (dependabot[bot] / #5089)
- meta: bump supercharge/redis-github-action from 1.4.0 to 1.8.0 (dependabot[bot] / #5090)
- meta: bump actions/cache from 3 to 4 (dependabot[bot] / #5088)
- meta: add `dependabot.yml` to keep GHA up-to-date (Antoine du Hamel / #5083)
- @uppy/core: Release: [email protected] (github-actions[bot] / #5084)
- @uppy/core: fix `setOptions` not re-rendereing plugin UI (Antoine du Hamel / #5082)
- meta: bump vite from 5.0.12 to 5.0.13 (dependabot[bot] / #5060)
- meta: bump tar from 6.1.11 to 6.2.1 (dependabot[bot] / #5068)
- @uppy/companion,@uppy/file-input: Release: [email protected] (github-actions[bot] / #5069)
- @uppy/companion: upgrade redis (Mikael Finstad / #5065)
- meta: fix `watch:*` scripts (Antoine du Hamel / #5046)
- meta: include more packages in `compare_diff` CI (Antoine du Hamel / #5044)
- @uppy/file-input: add missing export (Antoine du Hamel / #5045)
- meta: Bump express from 4.18.1 to 4.19.2 in /packages/@uppy/companion (dependabot[bot] / #5036)
- @uppy/companion: Bump express from 4.18.1 to 4.19.2 (dependabot[bot] / #5037)





| Package                | Version | Package                | Version |
| ---------------------- | ------- | ---------------------- | ------- |
| @uppy/audio            |   1.1.9 | @uppy/instagram        |   3.3.1 |
| @uppy/aws-s3-multipart |  3.11.1 | @uppy/onedrive         |   3.3.1 |
| @uppy/box              |   2.3.1 | @uppy/provider-views   |  3.12.0 |
| @uppy/companion-client |   3.8.1 | @uppy/react            |   3.3.1 |
| @uppy/compressor       |   1.1.3 | @uppy/status-bar       |   3.3.2 |
| @uppy/core             |  3.11.0 | @uppy/svelte           |   3.1.4 |
| @uppy/dashboard        |   3.8.2 | @uppy/transloadit      |   3.6.1 |
| @uppy/drop-target      |   2.1.0 | @uppy/unsplash         |   3.3.1 |
| @uppy/dropbox          |   3.3.1 | @uppy/url              |   3.6.1 |
| @uppy/facebook         |   3.3.1 | @uppy/utils            |   5.9.0 |
| @uppy/file-input       |   3.1.2 | @uppy/webcam           |   3.4.1 |
| @uppy/form             |   3.2.1 | @uppy/xhr-upload       |   3.6.5 |
| @uppy/google-drive     |   3.5.1 | @uppy/zoom             |   2.3.1 |
| @uppy/image-editor     |   2.4.5 | uppy                   |  3.25.0 |

- meta: enforce use of `.js` extension in `import type` declarations (Antoine du Hamel / #5126)
- @uppy/core: add instance ID to generated IDs (Merlijn Vos / #5080)
- @uppy/core: reference updated i18n in Restricter (Merlijn Vos / #5118)
- @uppy/xhr-upload: refactor to use `fetcher` (Merlijn Vos / #5074)
- meta: docs: use StackBlitz for all examples/issue template (Merlijn Vos / #5125)
- meta: Update yarn.lock (Murderlon)
- @uppy/svelte: Add svelte 5 as peer dep (frederikhors / #5122)
- meta: Bump docker/setup-buildx-action from 2 to 3 (dependabot[bot] / #5124)
- meta: Bump actions/checkout from 3 to 4 (dependabot[bot] / #5123)
- @uppy/dashboard,@uppy/provider-views: Remove JSX global type everywhere (Merlijn Vos / #5117)
- @uppy/utils: improve return type of `dataURItoFile` (Antoine du Hamel / #5112)
- @uppy/drop-target: change drop event type to DragEvent (Alireza Heydari / #5107)
- @uppy/image-editor: fix label definitions (Antoine du Hamel / #5111)
- meta: bump Prettier version (Antoine du Hamel / #5114)
- @uppy/provider-views: bring back "loaded X files..." (Mikael Finstad / #5097)
- @uppy/dashboard: fix type of trigger option (Merlijn Vos / #5106)
- meta: fix linter (Antoine du Hamel)
- @uppy/form: fix `submitOnSuccess` and `triggerUploadOnSubmit` combination (Merlijn Vos / #5058)
- meta: Bump docker/build-push-action from 3 to 5 (dependabot[bot] / #5105)
- meta: Bump akhileshns/heroku-deploy from 3.12.12 to 3.13.15 (dependabot[bot] / #5102)
- meta: Bump docker/login-action from 2 to 3 (dependabot[bot] / #5101)
- meta: Bump actions/download-artifact from 3 to 4 (dependabot[bot])
- meta: Bump actions/upload-artifact from 3 to 4 (dependabot[bot])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
4.0 For the 4.0 major version
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants