Skip to content

Migrate from Eslint/Prettier/Stylelint to Biome #5794

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

Open
wants to merge 10 commits into
base: from-babel-to-ts
Choose a base branch
from

Conversation

Murderlon
Copy link
Member

  • Remove all eslint, prettier, stylelint packages in favor of biome
  • Remove lint-staged. I've always disliked this. With VS Code workspace settings & recommended plugins, which set Biome to default formatter and suggests the plugin, there's really no need to always have this slowdown when your editor is configured already. Less dependencies is also better.
  • Remove lots of commands in favor of just check (lints, formats, organizes imports) and check:ci (only lint).
  • Update CI
  • Disable some recommended rules.
    • noUnusedImports/noUnusedFunctionParameters: unfortunately this is needed because we import { h } from 'preact' and React, as well as Biome not yet understanding that imports in <script> in Vue and Svelte are actually used inside the <template>.
    • noExplicitAny/noNonNullAssertion: we all know we shouldn't use them, but sometimes we have to.

@Murderlon Murderlon requested review from mifi and qxprakash June 26, 2025 13:45
@Murderlon Murderlon self-assigned this Jun 26, 2025
Copy link
Contributor

github-actions bot commented Jun 26, 2025

Diff output files
diff --git a/packages/@uppy/companion/lib/companion.js b/packages/@uppy/companion/lib/companion.js
index 45984f5..aa1a92a 100644
--- a/packages/@uppy/companion/lib/companion.js
+++ b/packages/@uppy/companion/lib/companion.js
@@ -54,7 +54,11 @@ const interceptGrantErrorResponse = interceptor((req, res) => {
   };
 });
 // make the errors available publicly for custom providers
-module.exports.errors = { ProviderApiError, ProviderUserError, ProviderAuthError };
+module.exports.errors = {
+  ProviderApiError,
+  ProviderUserError,
+  ProviderAuthError,
+};
 module.exports.socket = require("./server/socket");
 module.exports.setLoggerProcessName = setLoggerProcessName;
 /**
@@ -210,7 +214,9 @@ module.exports.app = (optionsArg = {}) => {
       const { providerName } = req.params;
       // for simplicity, we just return the normal credentials for the provider, but in a real-world scenario,
       // we would query based on parameters
-      const { key, secret } = options.providerOptions[providerName] ?? { __proto__: null };
+      const { key, secret } = options.providerOptions[providerName] ?? {
+        __proto__: null,
+      };
       function getTransloaditGateway() {
         const oauthProvider = getOauthProvider(providerName);
         if (!isOAuthProvider(oauthProvider)) {
diff --git a/packages/@uppy/companion/lib/config/companion.js b/packages/@uppy/companion/lib/config/companion.js
index 35ca4a9..5ff6318 100644
--- a/packages/@uppy/companion/lib/config/companion.js
+++ b/packages/@uppy/companion/lib/config/companion.js
@@ -37,7 +37,7 @@ function getMaskableSecrets(companionOptions) {
   });
   if (customProviders) {
     Object.keys(customProviders).forEach((provider) => {
-      if (customProviders[provider].config && customProviders[provider].config.secret) {
+      if (customProviders[provider].config?.secret) {
         secrets.push(customProviders[provider].config.secret);
       }
     });
@@ -59,7 +59,9 @@ const validateConfig = (companionOptions) => {
   /** @type {string[]} */
   const unspecified = [];
   mandatoryOptions.forEach((i) => {
-    const value = i.split(".").reduce((prev, curr) => (prev ? prev[curr] : undefined), companionOptions);
+    const value = i
+      .split(".")
+      .reduce((prev, curr) => (prev ? prev[curr] : undefined), companionOptions);
     if (!value) {
       unspecified.push(`"${i}"`);
     }
@@ -72,14 +74,14 @@ const validateConfig = (companionOptions) => {
   // validate that specified filePath is writeable/readable.
   try {
     // @ts-ignore
-    fs.accessSync(`${companionOptions.filePath}`, fs.R_OK | fs.W_OK); // eslint-disable-line no-bitwise
-  } catch (err) {
+    fs.accessSync(`${companionOptions.filePath}`, fs.R_OK | fs.W_OK);
+  } catch (_err) {
     throw new Error(
       `No access to "${companionOptions.filePath}". Please ensure the directory exists and with read/write permissions.`,
     );
   }
   const { providerOptions, periodicPingUrls, server } = companionOptions;
-  if (server && server.path) {
+  if (server?.path) {
     // see https://github.com/transloadit/uppy/issues/4271
     // todo fix the code so we can allow `/`
     if (server.path === "/") {
@@ -87,9 +89,13 @@ const validateConfig = (companionOptions) => {
     }
   }
   if (providerOptions) {
-    const deprecatedOptions = { microsoft: "providerOptions.onedrive", google: "providerOptions.drive", s3: "s3" };
+    const deprecatedOptions = {
+      microsoft: "providerOptions.onedrive",
+      google: "providerOptions.drive",
+      s3: "s3",
+    };
     Object.keys(deprecatedOptions).forEach((deprecated) => {
-      if (Object.prototype.hasOwnProperty.call(providerOptions, deprecated)) {
+      if (Object.hasOwn(providerOptions, deprecated)) {
         throw new Error(
           `The Provider option "providerOptions.${deprecated}" is no longer supported. Please use the option "${
             deprecatedOptions[deprecated]
@@ -98,7 +104,10 @@ const validateConfig = (companionOptions) => {
       }
     });
   }
-  if (companionOptions.uploadUrls == null || companionOptions.uploadUrls.length === 0) {
+  if (
+    companionOptions.uploadUrls == null
+    || companionOptions.uploadUrls.length === 0
+  ) {
     if (process.env.NODE_ENV === "production") {
       throw new Error("uploadUrls is required");
     }
@@ -114,9 +123,14 @@ const validateConfig = (companionOptions) => {
     throw new TypeError("Option corsOrigins cannot be \"*\". To disable security, pass true");
   }
   if (
-    periodicPingUrls != null && (!Array.isArray(periodicPingUrls)
+    periodicPingUrls != null
+    && (!Array.isArray(periodicPingUrls)
       || periodicPingUrls.some((url2) =>
-        !isURL(url2, { protocols: ["http", "https"], require_protocol: true, require_tld: false })
+        !isURL(url2, {
+          protocols: ["http", "https"],
+          require_protocol: true,
+          require_tld: false,
+        })
       ))
   ) {
     throw new TypeError("Invalid periodicPingUrls");
diff --git a/packages/@uppy/companion/lib/server/Uploader.js b/packages/@uppy/companion/lib/server/Uploader.js
index 848e1e9..7aa9699 100644
--- a/packages/@uppy/companion/lib/server/Uploader.js
+++ b/packages/@uppy/companion/lib/server/Uploader.js
@@ -1,5 +1,4 @@
 "use strict";
-// eslint-disable-next-line max-classes-per-file
 const tus = require("tus-js-client");
 const { randomUUID } = require("node:crypto");
 const validator = require("validator");
@@ -65,7 +64,10 @@ function validateOptions(options) {
   }
   // validate protocol
   // @todo this validation should not be conditional once the protocol field is mandatory
-  if (options.protocol && !Object.keys(PROTOCOLS).some((key) => PROTOCOLS[key] === options.protocol)) {
+  if (
+    options.protocol
+    && !Object.keys(PROTOCOLS).some((key) => PROTOCOLS[key] === options.protocol)
+  ) {
     throw new ValidationError("unsupported protocol specified");
   }
   // s3 uploads don't require upload destination
@@ -105,7 +107,6 @@ class StreamableBlob {
   stream() {
     return this.#stream;
   }
-  // eslint-disable-next-line class-methods-use-this
   get [Symbol.toStringTag]() {
     return "File";
   }
@@ -312,7 +313,7 @@ class Uploader {
     return token.substring(0, 8);
   }
   static reqToOptions(req, size) {
-    const useFormDataIsSet = Object.prototype.hasOwnProperty.call(req.body, "useFormData");
+    const useFormDataIsSet = Object.hasOwn(req.body, "useFormData");
     const useFormData = useFormDataIsSet ? req.body.useFormData : true;
     return {
       // Client provided info (must be validated and not blindly trusted):
@@ -397,7 +398,11 @@ class Uploader {
     if (this.#uploadState !== states.uploading) {
       return;
     }
-    const payload = { progress: formattedPercentage, bytesUploaded: combinedBytes, bytesTotal };
+    const payload = {
+      progress: formattedPercentage,
+      bytesUploaded: combinedBytes,
+      bytesTotal,
+    };
     const dataToEmit = {
       action: "progress",
       payload,
@@ -470,10 +475,8 @@ class Uploader {
           // 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);
         },
@@ -488,7 +491,10 @@ class Uploader {
           resolve({ url: uploader.tus.url });
         },
       };
-      if (this.options.companionOptions.tusDeferredUploadLength && !isFileStream) {
+      if (
+        this.options.companionOptions.tusDeferredUploadLength
+        && !isFileStream
+      ) {
         tusOptions.uploadLengthDeferred = true;
       } else {
         if (!this.size) {
@@ -504,6 +510,7 @@ class Uploader {
     if (this.size != null && this.tus._size !== this.size) {
       // @ts-ignore
       logger.warn(
+        // @ts-expect-error _size is not typed
         `Tus uploaded size ${this.tus._size} different from reported URL size ${this.size}`,
         "upload.tus.mismatch.error",
       );
diff --git a/packages/@uppy/companion/lib/server/controllers/connect.js b/packages/@uppy/companion/lib/server/controllers/connect.js
index f24933e..2f00373 100644
--- a/packages/@uppy/companion/lib/server/controllers/connect.js
+++ b/packages/@uppy/companion/lib/server/controllers/connect.js
@@ -9,7 +9,7 @@ const oAuthState = require("../helpers/oauth-state");
  */
 function isOriginAllowed(origin, allowedOrigins) {
   if (Array.isArray(allowedOrigins)) {
-    return allowedOrigins.some(allowedOrigin => isOriginAllowed(origin, allowedOrigin));
+    return allowedOrigins.some((allowedOrigin) => isOriginAllowed(origin, allowedOrigin));
   }
   if (typeof allowedOrigins === "string") {
     return origin === allowedOrigins;
@@ -34,10 +34,7 @@ function encodeStateAndRedirect(req, res, stateObj) {
       if (!queryValue) {
         return [];
       }
-      return [[
-        dynamicKey,
-        queryValue,
-      ]];
+      return [[dynamicKey, queryValue]];
     }) || [],
   );
   const { oauthProvider } = providerClass;
@@ -88,7 +85,10 @@ module.exports = function connect(req, res, next) {
   // Get the computed header generated by `cors` in a previous middleware.
   stateObj.origin = res.getHeader("Access-Control-Allow-Origin");
   let clientOrigin;
-  if (!stateObj.origin && (clientOrigin = getClientOrigin(req.query.state))) {
+  if (!stateObj.origin) {
+    clientOrigin = getClientOrigin(req.query.state);
+  }
+  if (!stateObj.origin && clientOrigin) {
     const { corsOrigins } = req.companion.options;
     if (typeof corsOrigins === "function") {
       corsOrigins(clientOrigin, (err, finalOrigin) => {
diff --git a/packages/@uppy/companion/lib/server/controllers/deauth-callback.js b/packages/@uppy/companion/lib/server/controllers/deauth-callback.js
index a1ae88b..067c6da 100644
--- a/packages/@uppy/companion/lib/server/controllers/deauth-callback.js
+++ b/packages/@uppy/companion/lib/server/controllers/deauth-callback.js
@@ -6,7 +6,11 @@ async function deauthCallback({ body, companion, headers }, res, next) {
   // It doesn't respond to Uppy client like other endpoints.
   // Instead it responds to the providers themselves.
   try {
-    const { data, status } = await companion.provider.deauthorizationCallback({ companion, body, headers });
+    const { data, status } = await companion.provider.deauthorizationCallback({
+      companion,
+      body,
+      headers,
+    });
     res.status(status || 200).json(data);
   } catch (err) {
     if (respondWithError(err, res)) {
diff --git a/packages/@uppy/companion/lib/server/controllers/get.js b/packages/@uppy/companion/lib/server/controllers/get.js
index 771c8d8..278a172 100644
--- a/packages/@uppy/companion/lib/server/controllers/get.js
+++ b/packages/@uppy/companion/lib/server/controllers/get.js
@@ -8,9 +8,20 @@ async function get(req, res) {
   const { accessToken } = providerUserSession;
   const { provider } = req.companion;
   async function getSize() {
-    return provider.size({ id, token: accessToken, providerUserSession, query: req.query });
+    return provider.size({
+      id,
+      token: accessToken,
+      providerUserSession,
+      query: req.query,
+    });
   }
-  const download = () => provider.download({ id, token: accessToken, providerUserSession, query: req.query });
+  const download = () =>
+    provider.download({
+      id,
+      token: accessToken,
+      providerUserSession,
+      query: req.query,
+    });
   try {
     await startDownUpload({ req, res, getSize, download });
   } catch (err) {
diff --git a/packages/@uppy/companion/lib/server/controllers/googlePicker.js b/packages/@uppy/companion/lib/server/controllers/googlePicker.js
index 07c3ced..f629ba5 100644
--- a/packages/@uppy/companion/lib/server/controllers/googlePicker.js
+++ b/packages/@uppy/companion/lib/server/controllers/googlePicker.js
@@ -26,7 +26,9 @@ const get = async (req, res) => {
       if (platform === "drive") {
         return streamGoogleFile({ token: accessToken, id: fileId });
       }
-      return downloadURL(req.body.url, allowLocalUrls, req.id, { headers: getAuthHeader(accessToken) });
+      return downloadURL(req.body.url, allowLocalUrls, req.id, {
+        headers: getAuthHeader(accessToken),
+      });
     };
     await startDownUpload({ req, res, download, getSize: undefined });
   } catch (err) {
@@ -37,6 +39,4 @@ const get = async (req, res) => {
     res.status(500).json({ message: "failed to fetch Google Picker URL" });
   }
 };
-module.exports = () =>
-  express.Router()
-    .post("/get", express.json(), get);
+module.exports = () => express.Router().post("/get", express.json(), get);
diff --git a/packages/@uppy/companion/lib/server/controllers/index.js b/packages/@uppy/companion/lib/server/controllers/index.js
index 395b11e..c79e63b 100644
--- a/packages/@uppy/companion/lib/server/controllers/index.js
+++ b/packages/@uppy/companion/lib/server/controllers/index.js
@@ -1,5 +1,4 @@
 "use strict";
-/* eslint-disable global-require */
 module.exports = {
   callback: require("./callback"),
   deauthorizationCallback: require("./deauth-callback"),
diff --git a/packages/@uppy/companion/lib/server/controllers/logout.js b/packages/@uppy/companion/lib/server/controllers/logout.js
index 84f0636..fdebd4c 100644
--- a/packages/@uppy/companion/lib/server/controllers/logout.js
+++ b/packages/@uppy/companion/lib/server/controllers/logout.js
@@ -21,7 +21,11 @@ async function logout(req, res, next) {
   }
   try {
     const { accessToken } = providerUserSession;
-    const data = await companion.provider.logout({ token: accessToken, providerUserSession, companion });
+    const data = await companion.provider.logout({
+      token: accessToken,
+      providerUserSession,
+      companion,
+    });
     delete companion.providerUserSession;
     tokenService.removeFromCookies(res, companion.options, companion.providerClass.oauthProvider);
     cleanSession();
diff --git a/packages/@uppy/companion/lib/server/controllers/oauth-redirect.js b/packages/@uppy/companion/lib/server/controllers/oauth-redirect.js
index 235e617..bf1f773 100644
--- a/packages/@uppy/companion/lib/server/controllers/oauth-redirect.js
+++ b/packages/@uppy/companion/lib/server/controllers/oauth-redirect.js
@@ -20,7 +20,7 @@ module.exports = function oauthRedirect(req, res) {
     return;
   }
   const handler = oAuthState.getFromState(state, "companionInstance", req.companion.options.secret);
-  const handlerHostName = (new URL(handler)).host;
+  const handlerHostName = new URL(handler).host;
   if (hasMatch(handlerHostName, req.companion.options.server.validHosts)) {
     const url = `${handler}/connect/${oauthProvider}/callback?${params}`;
     res.redirect(url);
diff --git a/packages/@uppy/companion/lib/server/controllers/refresh-token.js b/packages/@uppy/companion/lib/server/controllers/refresh-token.js
index e95284d..6a0b821 100644
--- a/packages/@uppy/companion/lib/server/controllers/refresh-token.js
+++ b/packages/@uppy/companion/lib/server/controllers/refresh-token.js
@@ -7,12 +7,15 @@ const logger = require("../logger");
 // https://github.com/simov/grant/issues/149
 async function refreshToken(req, res, next) {
   const { providerName } = req.params;
-  const { key: clientId, secret: clientSecret } = req.companion.options.providerOptions[providerName]
-    ?? { __proto__: null };
+  const { key: clientId, secret: clientSecret } = req.companion.options
+    .providerOptions[providerName] ?? { __proto__: null };
   const { redirect_uri: redirectUri } = req.companion.providerGrantConfig;
   const { providerUserSession } = req.companion;
   // not all providers have refresh tokens
-  if (providerUserSession.refreshToken == null || providerUserSession.refreshToken === "") {
+  if (
+    providerUserSession.refreshToken == null
+    || providerUserSession.refreshToken === ""
+  ) {
     logger.warn("Tried to refresh token without having a token");
     res.sendStatus(401);
     return;
diff --git a/packages/@uppy/companion/lib/server/controllers/s3.js b/packages/@uppy/companion/lib/server/controllers/s3.js
index 8f35b2d..9f8f57a 100644
--- a/packages/@uppy/companion/lib/server/controllers/s3.js
+++ b/packages/@uppy/companion/lib/server/controllers/s3.js
@@ -22,9 +22,13 @@ module.exports = function s3(config) {
     /**
      * @type {import('@aws-sdk/client-s3').S3Client}
      */
-    const client = createPresignedPostMode ? req.companion.s3ClientCreatePresignedPost : req.companion.s3Client;
+    const client = createPresignedPostMode
+      ? req.companion.s3ClientCreatePresignedPost
+      : req.companion.s3Client;
     if (!client) {
-      res.status(400).json({ error: "This Companion server does not support uploading to S3" });
+      res.status(400).json({
+        error: "This Companion server does not support uploading to S3",
+      });
     }
     return client;
   }
@@ -50,10 +54,17 @@ module.exports = function s3(config) {
     }
     const { metadata = {}, filename } = req.query;
     const truncatedFilename = truncateFilename(filename, req.companion.options.maxFilenameLength);
-    const bucket = getBucket({ bucketOrFn: config.bucket, req, filename: truncatedFilename, metadata });
+    const bucket = getBucket({
+      bucketOrFn: config.bucket,
+      req,
+      filename: truncatedFilename,
+      metadata,
+    });
     const key = config.getKey({ req, filename: truncatedFilename, metadata });
     if (typeof key !== "string") {
-      res.status(500).json({ error: "S3 uploads are misconfigured: filename returned from `getKey` must be a string" });
+      res.status(500).json({
+        error: "S3 uploads are misconfigured: filename returned from `getKey` must be a string",
+      });
       return;
     }
     const fields = {
@@ -72,7 +83,7 @@ module.exports = function s3(config) {
       Fields: fields,
       Conditions: config.conditions,
       Key: key,
-    }).then(data => {
+    }).then((data) => {
       res.json({
         method: "POST",
         url: data.url,
@@ -103,9 +114,16 @@ module.exports = function s3(config) {
     const { type, metadata = {}, filename } = req.body;
     const truncatedFilename = truncateFilename(filename, req.companion.options.maxFilenameLength);
     const key = config.getKey({ req, filename: truncatedFilename, metadata });
-    const bucket = getBucket({ bucketOrFn: config.bucket, req, filename: truncatedFilename, metadata });
+    const bucket = getBucket({
+      bucketOrFn: config.bucket,
+      req,
+      filename: truncatedFilename,
+      metadata,
+    });
     if (typeof key !== "string") {
-      res.status(500).json({ error: "s3: filename returned from `getKey` must be a string" });
+      res.status(500).json({
+        error: "s3: filename returned from `getKey` must be a string",
+      });
       return;
     }
     if (typeof type !== "string") {
@@ -158,24 +176,26 @@ module.exports = function s3(config) {
     const bucket = getBucket({ bucketOrFn: config.bucket, req });
     const parts = [];
     function listPartsPage(startAt) {
-      client.send(
-        new ListPartsCommand({
-          Bucket: bucket,
-          Key: key,
-          UploadId: uploadId,
-          PartNumberMarker: startAt,
-        }),
-      ).then(({ Parts, IsTruncated, NextPartNumberMarker }) => {
-        if (Parts) {
-          parts.push(...Parts);
-        }
-        if (IsTruncated) {
-          // Get the next page.
-          listPartsPage(NextPartNumberMarker);
-        } else {
-          res.json(parts);
-        }
-      }, next);
+      client
+        .send(
+          new ListPartsCommand({
+            Bucket: bucket,
+            Key: key,
+            UploadId: uploadId,
+            PartNumberMarker: startAt,
+          }),
+        )
+        .then(({ Parts, IsTruncated, NextPartNumberMarker }) => {
+          if (Parts) {
+            parts.push(...Parts);
+          }
+          if (IsTruncated) {
+            // Get the next page.
+            listPartsPage(NextPartNumberMarker);
+          } else {
+            res.json(parts);
+          }
+        }, next);
     }
     listPartsPage();
   }
@@ -204,7 +224,9 @@ module.exports = function s3(config) {
       return;
     }
     if (!parseInt(partNumber, 10)) {
-      res.status(400).json({ error: "s3: the part number must be a number between 1 and 10000." });
+      res.status(400).json({
+        error: "s3: the part number must be a number between 1 and 10000.",
+      });
       return;
     }
     const bucket = getBucket({ bucketOrFn: config.bucket, req });
@@ -218,7 +240,7 @@ module.exports = function s3(config) {
         Body: "",
       }),
       { expiresIn: config.expires },
-    ).then(url => {
+    ).then((url) => {
       res.json({ url, expires: config.expires });
     }, next);
   }
@@ -257,7 +279,9 @@ module.exports = function s3(config) {
     }
     const partNumbersArray = partNumbers.split(",");
     if (!partNumbersArray.every((partNumber) => parseInt(partNumber, 10))) {
-      res.status(400).json({ error: "s3: the part numbers must be a number between 1 and 10000." });
+      res.status(400).json({
+        error: "s3: the part numbers must be a number between 1 and 10000.",
+      });
       return;
     }
     const bucket = getBucket({ bucketOrFn: config.bucket, req });
@@ -273,13 +297,15 @@ module.exports = function s3(config) {
         }),
         { expiresIn: config.expires },
       );
-    })).then((urls) => {
-      const presignedUrls = Object.create(null);
-      for (let index = 0; index < partNumbersArray.length; index++) {
-        presignedUrls[partNumbersArray[index]] = urls[index];
-      }
-      res.json({ presignedUrls });
-    }).catch(next);
+    }))
+      .then((urls) => {
+        const presignedUrls = Object.create(null);
+        for (let index = 0; index < partNumbersArray.length; index++) {
+          presignedUrls[partNumbersArray[index]] = urls[index];
+        }
+        res.json({ presignedUrls });
+      })
+      .catch(next);
   }
   /**
    * Abort a multipart upload, deleting already uploaded parts.
@@ -305,13 +331,15 @@ module.exports = function s3(config) {
       return;
     }
     const bucket = getBucket({ bucketOrFn: config.bucket, req });
-    client.send(
-      new AbortMultipartUploadCommand({
-        Bucket: bucket,
-        Key: key,
-        UploadId: uploadId,
-      }),
-    ).then(() => res.json({}), next);
+    client
+      .send(
+        new AbortMultipartUploadCommand({
+          Bucket: bucket,
+          Key: key,
+          UploadId: uploadId,
+        }),
+      )
+      .then(() => res.json({}), next);
   }
   /**
    * Complete a multipart upload, combining all the parts into a single object in the S3 bucket.
@@ -341,39 +369,43 @@ module.exports = function s3(config) {
     }
     if (
       !Array.isArray(parts)
-      || !parts.every(part =>
-        typeof part === "object" && typeof part?.PartNumber === "number" && typeof part.ETag === "string"
+      || !parts.every((part) =>
+        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." });
+      res.status(400).json({
+        error: "s3: `parts` must be an array of {ETag, PartNumber} objects.",
+      });
       return;
     }
     const bucket = getBucket({ bucketOrFn: config.bucket, req });
-    client.send(
-      new CompleteMultipartUploadCommand({
-        Bucket: bucket,
-        Key: key,
-        UploadId: uploadId,
-        MultipartUpload: {
-          Parts: parts,
-        },
-      }),
-    ).then(data => {
-      res.json({
-        location: data.Location,
-        key: data.Key,
-        bucket: data.Bucket,
-      });
-    }, next);
+    client
+      .send(
+        new CompleteMultipartUploadCommand({
+          Bucket: bucket,
+          Key: key,
+          UploadId: uploadId,
+          MultipartUpload: {
+            Parts: parts,
+          },
+        }),
+      )
+      .then((data) => {
+        res.json({
+          location: data.Location,
+          key: data.Key,
+          bucket: data.Bucket,
+        });
+      }, next);
   }
   const policy = {
     Version: "2012-10-17", // latest at the time of writing
     Statement: [
       {
         Effect: "Allow",
-        Action: [
-          "s3:PutObject",
-        ],
+        Action: ["s3:PutObject"],
         Resource: [
           `arn:aws:s3:::${config.bucket}/*`,
           `arn:aws:s3:::${config.bucket}`,
@@ -408,38 +440,41 @@ module.exports = function s3(config) {
    * - region: the region where that bucket is stored.
    */
   function getTemporarySecurityCredentials(req, res, next) {
-    getSTSClient().send(
-      new GetFederationTokenCommand({
-        // Name of the federated user. The name is used as an identifier for the
-        // temporary security credentials (such as Bob). For example, you can
-        // reference the federated user name in a resource-based policy, such as
-        // in an Amazon S3 bucket policy.
-        // Companion is configured by default as an unprotected public endpoint,
-        // if you implement your own custom endpoint with user authentication you
-        // should probably use different names for each of your users.
-        Name: "companion",
-        // The duration, in seconds, of the role session. The value specified
-        // can range from 900 seconds (15 minutes) up to the maximum session
-        // duration set for the role.
-        DurationSeconds: config.expires,
-        Policy: JSON.stringify(policy),
-      }),
-    ).then(response => {
-      // This is a public unprotected endpoint.
-      // If you implement your own custom endpoint with user authentication you
-      // should probably use `private` instead of `public`.
-      res.setHeader("Cache-Control", `public,max-age=${config.expires - 300}`); // 300s is 5min.
-      res.json({
-        credentials: response.Credentials,
-        bucket: config.bucket,
-        region: config.region,
-      });
-    }, next);
+    getSTSClient()
+      .send(
+        new GetFederationTokenCommand({
+          // Name of the federated user. The name is used as an identifier for the
+          // temporary security credentials (such as Bob). For example, you can
+          // reference the federated user name in a resource-based policy, such as
+          // in an Amazon S3 bucket policy.
+          // Companion is configured by default as an unprotected public endpoint,
+          // if you implement your own custom endpoint with user authentication you
+          // should probably use different names for each of your users.
+          Name: "companion",
+          // The duration, in seconds, of the role session. The value specified
+          // can range from 900 seconds (15 minutes) up to the maximum session
+          // duration set for the role.
+          DurationSeconds: config.expires,
+          Policy: JSON.stringify(policy),
+        }),
+      )
+      .then((response) => {
+        // This is a public unprotected endpoint.
+        // If you implement your own custom endpoint with user authentication you
+        // should probably use `private` instead of `public`.
+        res.setHeader("Cache-Control", `public,max-age=${config.expires - 300}`); // 300s is 5min.
+        res.json({
+          credentials: response.Credentials,
+          bucket: config.bucket,
+          region: config.region,
+        });
+      }, next);
   }
   if (config.bucket == null) {
     return express.Router(); // empty router because s3 is not enabled
   }
-  return express.Router()
+  return (express
+    .Router()
     .get("/sts", getTemporarySecurityCredentials)
     .get("/params", getUploadParameters)
     .post("/multipart", express.json(), createMultipartUpload)
@@ -448,5 +483,5 @@ module.exports = function s3(config) {
     .get("/multipart/:uploadId/:partNumber", signPartUpload)
     // limit 1mb because maybe large upload with a lot of parts, see https://github.com/transloadit/uppy/issues/1945
     .post("/multipart/:uploadId/complete", express.json({ limit: "1mb" }), completeMultipartUpload)
-    .delete("/multipart/:uploadId", abortMultipartUpload);
+    .delete("/multipart/:uploadId", abortMultipartUpload));
 };
diff --git a/packages/@uppy/companion/lib/server/controllers/simple-auth.js b/packages/@uppy/companion/lib/server/controllers/simple-auth.js
index 540276c..7a342f2 100644
--- a/packages/@uppy/companion/lib/server/controllers/simple-auth.js
+++ b/packages/@uppy/companion/lib/server/controllers/simple-auth.js
@@ -5,7 +5,9 @@ const logger = require("../logger");
 async function simpleAuth(req, res, next) {
   const { providerName } = req.params;
   try {
-    const simpleAuthResponse = await req.companion.provider.simpleAuth({ requestBody: req.body });
+    const simpleAuthResponse = await req.companion.provider.simpleAuth({
+      requestBody: req.body,
+    });
     req.companion.providerUserSession = {
       ...req.companion.providerUserSession,
       ...simpleAuthResponse,
diff --git a/packages/@uppy/companion/lib/server/controllers/thumbnail.js b/packages/@uppy/companion/lib/server/controllers/thumbnail.js
index 9613155..ae03bd8 100644
--- a/packages/@uppy/companion/lib/server/controllers/thumbnail.js
+++ b/packages/@uppy/companion/lib/server/controllers/thumbnail.js
@@ -9,7 +9,11 @@ async function thumbnail(req, res, next) {
   const { provider, providerUserSession } = req.companion;
   const { accessToken } = providerUserSession;
   try {
-    const { stream, contentType } = await provider.thumbnail({ id, token: accessToken, providerUserSession });
+    const { stream, contentType } = await provider.thumbnail({
+      id,
+      token: accessToken,
+      providerUserSession,
+    });
     if (contentType != null) {
       res.set("Content-Type", contentType);
     }
diff --git a/packages/@uppy/companion/lib/server/controllers/url.js b/packages/@uppy/companion/lib/server/controllers/url.js
index 4ea0ece..0bf3508 100644
--- a/packages/@uppy/companion/lib/server/controllers/url.js
+++ b/packages/@uppy/companion/lib/server/controllers/url.js
@@ -63,6 +63,7 @@ const get = async (req, res) => {
   }
 };
 module.exports = () =>
-  express.Router()
+  express
+    .Router()
     .post("/meta", express.json(), meta)
     .post("/get", express.json(), get);
diff --git a/packages/@uppy/companion/lib/server/download.js b/packages/@uppy/companion/lib/server/download.js
index f7ff3d1..b4177c7 100644
--- a/packages/@uppy/companion/lib/server/download.js
+++ b/packages/@uppy/companion/lib/server/download.js
@@ -14,7 +14,10 @@ const { prepareStream } = require("./helpers/utils");
 const downloadURL = async (url, allowLocalIPs, traceId, options) => {
   try {
     const protectedGot = await getProtectedGot({ allowLocalIPs });
-    const stream = protectedGot.stream.get(url, { responseType: "json", ...options });
+    const stream = protectedGot.stream.get(url, {
+      responseType: "json",
+      ...options,
+    });
     const { size } = await prepareStream(stream);
     return { stream, size };
   } catch (err) {
diff --git a/packages/@uppy/companion/lib/server/emitter/index.js b/packages/@uppy/companion/lib/server/emitter/index.js
index 2b00725..caa8b1d 100644
--- a/packages/@uppy/companion/lib/server/emitter/index.js
+++ b/packages/@uppy/companion/lib/server/emitter/index.js
@@ -9,7 +9,9 @@ let emitter;
  */
 module.exports = (redisClient, redisPubSubScope) => {
   if (!emitter) {
-    emitter = redisClient ? redisEmitter(redisClient, redisPubSubScope) : nodeEmitter();
+    emitter = redisClient
+      ? redisEmitter(redisClient, redisPubSubScope)
+      : nodeEmitter();
   }
   return emitter;
 };
diff --git a/packages/@uppy/companion/lib/server/emitter/redis-emitter.js b/packages/@uppy/companion/lib/server/emitter/redis-emitter.js
index c2a19f7..6f0166f 100644
--- a/packages/@uppy/companion/lib/server/emitter/redis-emitter.js
+++ b/packages/@uppy/companion/lib/server/emitter/redis-emitter.js
@@ -22,9 +22,9 @@ module.exports = (redisClient, redisPubSubScope) => {
   const handleError = (err) => errorEmitter.emit("error", err);
   async function makeRedis() {
     const publisher = redisClient.duplicate({ lazyConnect: true });
-    publisher.on("error", err => logger.error("publisher redis error", err.toString()));
+    publisher.on("error", (err) => logger.error("publisher redis error", err.toString()));
     const subscriber = publisher.duplicate();
-    subscriber.on("error", err => logger.error("subscriber redis error", err.toString()));
+    subscriber.on("error", (err) => logger.error("subscriber redis error", err.toString()));
     await publisher.connect();
     await subscriber.connect();
     return { subscriber, publisher };
@@ -99,7 +99,7 @@ module.exports = (redisClient, redisPubSubScope) => {
       let args;
       try {
         args = JSON.parse(message);
-      } catch (ex) {
+      } catch (_ex) {
         handleError(new Error(`Invalid JSON received! Channel: ${eventName} Message: ${message}`));
         return;
       }
@@ -149,9 +149,9 @@ module.exports = (redisClient, redisPubSubScope) => {
    * @param {string} eventName name of the event
    */
   async function emit(eventName, ...args) {
-    await runWhenConnected(async (
-      { publisher },
-    ) => (publisher.publish(getPrefixedEventName(eventName), safeStringify(args, replacer))));
+    await runWhenConnected(async ({ publisher }) =>
+      publisher.publish(getPrefixedEventName(eventName), safeStringify(args, replacer))
+    );
   }
   /**
    * Remove all listeners of an event
diff --git a/packages/@uppy/companion/lib/server/got.js b/packages/@uppy/companion/lib/server/got.js
index b3daf75..2868785 100644
--- a/packages/@uppy/companion/lib/server/got.js
+++ b/packages/@uppy/companion/lib/server/got.js
@@ -1,4 +1,3 @@
 "use strict";
-// eslint-disable-next-line import/no-unresolved
 const gotPromise = import("got");
 module.exports = gotPromise.then((got) => got.default);
diff --git a/packages/@uppy/companion/lib/server/header-blacklist.js b/packages/@uppy/companion/lib/server/header-blacklist.js
index 690380a..6e932cd 100644
--- a/packages/@uppy/companion/lib/server/header-blacklist.js
+++ b/packages/@uppy/companion/lib/server/header-blacklist.js
@@ -45,7 +45,11 @@ const isForbiddenHeader = (header) => {
   return forbidden;
 };
 module.exports = (headers) => {
-  if (headers == null || typeof headers !== "object" || Array.isArray(headers)) {
+  if (
+    headers == null
+    || typeof headers !== "object"
+    || Array.isArray(headers)
+  ) {
     return {};
   }
   const headersCloned = { ...headers };
diff --git a/packages/@uppy/companion/lib/server/helpers/request.js b/packages/@uppy/companion/lib/server/helpers/request.js
index 658210a..e876866 100644
--- a/packages/@uppy/companion/lib/server/helpers/request.js
+++ b/packages/@uppy/companion/lib/server/helpers/request.js
@@ -1,5 +1,4 @@
 "use strict";
-// eslint-disable-next-line max-classes-per-file
 const http = require("node:http");
 const https = require("node:https");
 const dns = require("node:dns");
@@ -45,11 +44,15 @@ const getProtectedHttpAgent = ({ protocol, allowLocalIPs }) => {
         callback(err, addresses, maybeFamily);
         return;
       }
-      const toValidate = Array.isArray(addresses) ? addresses : [{ address: addresses }];
+      const toValidate = Array.isArray(addresses)
+        ? addresses
+        : [{ address: addresses }];
       // because dns.lookup seems to be called with option `all: true`, if we are on an ipv6 system,
       // `addresses` could contain a list of ipv4 addresses as well as ipv6 mapped addresses (rfc6052) which we cannot allow
       // however we should still allow any valid ipv4 addresses, so we filter out the invalid addresses
-      const validAddresses = allowLocalIPs ? toValidate : toValidate.filter(({ address }) => !isDisallowedIP(address));
+      const validAddresses = allowLocalIPs
+        ? toValidate
+        : toValidate.filter(({ address }) => !isDisallowedIP(address));
       // and check if there's anything left after we filtered:
       if (validAddresses.length === 0) {
         callback(
@@ -61,13 +64,21 @@ const getProtectedHttpAgent = ({ protocol, allowLocalIPs }) => {
         );
         return;
       }
-      const ret = Array.isArray(addresses) ? validAddresses : validAddresses[0].address;
+      const ret = Array.isArray(addresses)
+        ? validAddresses
+        : validAddresses[0].address;
       callback(err, ret, maybeFamily);
     });
   }
-  return class HttpAgent extends (protocol.startsWith("https") ? https : http).Agent {
+  return class HttpAgent extends (protocol.startsWith("https") ? https : http)
+    .Agent
+  {
     createConnection(options, callback) {
-      if (ipaddr.isValid(options.host) && !allowLocalIPs && isDisallowedIP(options.host)) {
+      if (
+        ipaddr.isValid(options.host)
+        && !allowLocalIPs
+        && isDisallowedIP(options.host)
+      ) {
         callback(new Error(FORBIDDEN_IP_ADDRESS));
         return undefined;
       }
@@ -79,7 +90,10 @@ const getProtectedHttpAgent = ({ protocol, allowLocalIPs }) => {
 module.exports.getProtectedHttpAgent = getProtectedHttpAgent;
 async function getProtectedGot({ allowLocalIPs }) {
   const HttpAgent = getProtectedHttpAgent({ protocol: "http", allowLocalIPs });
-  const HttpsAgent = getProtectedHttpAgent({ protocol: "https", allowLocalIPs });
+  const HttpsAgent = getProtectedHttpAgent({
+    protocol: "https",
+    allowLocalIPs,
+  });
   const httpAgent = new HttpAgent();
   const httpsAgent = new HttpsAgent();
   // @ts-ignore
@@ -96,29 +110,35 @@ module.exports.getProtectedGot = getProtectedGot;
 exports.getURLMeta = async (url, allowLocalIPs = false, options = undefined) => {
   async function requestWithMethod(method) {
     const protectedGot = await getProtectedGot({ allowLocalIPs });
-    const stream = protectedGot.stream(url, { method, throwHttpErrors: false, ...options });
-    return new Promise((resolve, reject) => (stream
-      .on("response", (response) => {
-        // Can be undefined for unknown length URLs, e.g. transfer-encoding: chunked
-        const contentLength = parseInt(response.headers["content-length"], 10);
-        // If Content-Disposition with file name is missing, fallback to the URL path for the name,
-        // but if multiple files are served via query params like foo.com?file=file-1, foo.com?file=file-2,
-        // we add random string to avoid duplicate files
-        const filename = response.headers["content-disposition"]
-          ? contentDisposition.parse(response.headers["content-disposition"]).parameters.filename
-          : path.basename(`${response.request.requestUrl}`);
-        // No need to get the rest of the response, as we only want header (not really relevant for HEAD, but why not)
-        stream.destroy();
-        resolve({
-          name: filename,
-          type: response.headers["content-type"],
-          size: Number.isNaN(contentLength) ? null : contentLength,
-          statusCode: response.statusCode,
-        });
-      })
-      .on("error", (err) => {
-        reject(err);
-      }))
+    const stream = protectedGot.stream(url, {
+      method,
+      throwHttpErrors: false,
+      ...options,
+    });
+    return new Promise((resolve, reject) =>
+      stream
+        .on("response", (response) => {
+          // Can be undefined for unknown length URLs, e.g. transfer-encoding: chunked
+          const contentLength = parseInt(response.headers["content-length"], 10);
+          // If Content-Disposition with file name is missing, fallback to the URL path for the name,
+          // but if multiple files are served via query params like foo.com?file=file-1, foo.com?file=file-2,
+          // we add random string to avoid duplicate files
+          const filename = response.headers["content-disposition"]
+            ? contentDisposition.parse(response.headers["content-disposition"])
+              .parameters.filename
+            : path.basename(`${response.request.requestUrl}`);
+          // No need to get the rest of the response, as we only want header (not really relevant for HEAD, but why not)
+          stream.destroy();
+          resolve({
+            name: filename,
+            type: response.headers["content-type"],
+            size: Number.isNaN(contentLength) ? null : contentLength,
+            statusCode: response.statusCode,
+          });
+        })
+        .on("error", (err) => {
+          reject(err);
+        })
     );
   }
   // We prefer to use a HEAD request, as it doesn't download the content. If the URL doesn't
diff --git a/packages/@uppy/companion/lib/server/helpers/upload.js b/packages/@uppy/companion/lib/server/helpers/upload.js
index b41e636..ea555d9 100644
--- a/packages/@uppy/companion/lib/server/helpers/upload.js
+++ b/packages/@uppy/companion/lib/server/helpers/upload.js
@@ -6,7 +6,11 @@ async function startDownUpload({ req, res, getSize, download }) {
   const { stream, size: maybeSize } = await download();
   let size;
   // if we already know the size from the GET response content-length header, we can use that
-  if (typeof maybeSize === "number" && !Number.isNaN(maybeSize) && maybeSize > 0) {
+  if (
+    typeof maybeSize === "number"
+    && !Number.isNaN(maybeSize)
+    && maybeSize > 0
+  ) {
     size = maybeSize;
   }
   // if not, we may need to explicitly get the size
diff --git a/packages/@uppy/companion/lib/server/helpers/utils.js b/packages/@uppy/companion/lib/server/helpers/utils.js
index 396bab2..db7a4ed 100644
--- a/packages/@uppy/companion/lib/server/helpers/utils.js
+++ b/packages/@uppy/companion/lib/server/helpers/utils.js
@@ -12,7 +12,7 @@ const ivLength = 12;
  */
 exports.hasMatch = (value, criteria) => {
   return criteria.some((i) => {
-    return value === i || (new RegExp(i)).test(value);
+    return value === i || new RegExp(i).test(value);
   });
 };
 /**
@@ -88,7 +88,9 @@ function createSecrets(secret, nonce) {
 module.exports.encrypt = (input, secret) => {
   const nonce = crypto.randomBytes(nonceLength);
   const { key, iv } = createSecrets(secret, nonce);
-  const cipher = crypto.createCipheriv("aes-256-ccm", key, iv, { authTagLength });
+  const cipher = crypto.createCipheriv("aes-256-ccm", key, iv, {
+    authTagLength,
+  });
   const encrypted = Buffer.concat([
     cipher.update(input, "utf8"),
     cipher.final(),
@@ -145,7 +147,9 @@ module.exports.decrypt = (encrypted, secret) => {
       throw new Error("Invalid encrypted value. Maybe it was generated with an old Companion version?");
     }
     const { key, iv } = createSecrets(secret, nonce);
-    const decipher = crypto.createDecipheriv("aes-256-ccm", key, iv, { authTagLength });
+    const decipher = crypto.createDecipheriv("aes-256-ccm", key, iv, {
+      authTagLength,
+    });
     decipher.setAuthTag(authTag);
     const decrypted = Buffer.concat([
       decipher.update(encryptionWithoutNonceAndTag),
@@ -181,7 +185,9 @@ module.exports.prepareStream = async (stream) =>
       .on("response", (response) => {
         const contentLengthStr = response.headers["content-length"];
         const contentLength = parseInt(contentLengthStr, 10);
-        const size = !Number.isNaN(contentLength) && contentLength >= 0 ? contentLength : undefined;
+        const size = !Number.isNaN(contentLength) && contentLength >= 0
+          ? contentLength
+          : undefined;
         // Don't allow any more data to flow yet.
         // https://github.com/request/request/issues/1990#issuecomment-184712275
         stream.pause();
@@ -190,15 +196,23 @@ module.exports.prepareStream = async (stream) =>
       .on("error", (err) => {
         // In this case the error object is not a normal GOT HTTPError where json is already parsed,
         // we use our own HttpError error for this scenario.
-        if (typeof err.response?.body === "string" && typeof err.response?.statusCode === "number") {
+        if (
+          typeof err.response?.body === "string"
+          && typeof err.response?.statusCode === "number"
+        ) {
           let responseJson;
           try {
             responseJson = JSON.parse(err.response.body);
-          } catch (err2) {
+          } catch (_err2) {
             reject(err);
             return;
           }
-          reject(new HttpError({ statusCode: err.response.statusCode, responseJson }));
+          reject(
+            new HttpError({
+              statusCode: err.response.statusCode,
+              responseJson,
+            }),
+          );
           return;
         }
         reject(err);
@@ -210,15 +224,14 @@ module.exports.getBasicAuthHeader = (key, secret) => {
 };
 const rfc2047Encode = (dataIn) => {
   const data = `${dataIn}`;
-  // eslint-disable-next-line no-control-regex
+  // biome-ignore lint/suspicious/noControlCharactersInRegex: leave it for now
   if (/^[\x00-\x7F]*$/.test(data)) {
     return data; // we return ASCII as is
   }
   return `=?UTF-8?B?${Buffer.from(data).toString("base64")}?=`; // We encode non-ASCII strings
 };
-module.exports.rfc2047EncodeMetadata = (
-  metadata,
-) => (Object.fromEntries(Object.entries(metadata).map((entry) => entry.map(rfc2047Encode))));
+module.exports.rfc2047EncodeMetadata = (metadata) =>
+  Object.fromEntries(Object.entries(metadata).map((entry) => entry.map(rfc2047Encode)));
 /**
  * @param {{
  * bucketOrFn: string | ((a: {
@@ -233,7 +246,9 @@ module.exports.rfc2047EncodeMetadata = (
  * @returns
  */
 module.exports.getBucket = ({ bucketOrFn, req, metadata, filename }) => {
-  const bucket = typeof bucketOrFn === "function" ? bucketOrFn({ req, metadata, filename }) : bucketOrFn;
+  const bucket = typeof bucketOrFn === "function"
+    ? bucketOrFn({ req, metadata, filename })
+    : bucketOrFn;
   if (typeof bucket !== "string" || bucket === "") {
     // This means a misconfiguration or bug
     throw new TypeError("s3: bucket key must be a string or a function resolving the bucket string");
diff --git a/packages/@uppy/companion/lib/server/jobs.d.ts b/packages/@uppy/companion/lib/server/jobs.d.ts
index 62c2271..24d8855 100644
--- a/packages/@uppy/companion/lib/server/jobs.d.ts
+++ b/packages/@uppy/companion/lib/server/jobs.d.ts
@@ -1,5 +1,5 @@
 export function startCleanUpJob(dirPath: string): void;
-export function startPeriodicPingJob({ urls, interval, count, staticPayload, version, processId }: {
+export function startPeriodicPingJob({ urls, interval, count, staticPayload, version, processId, }: {
     urls: any;
     interval?: number;
     count: any;
diff --git a/packages/@uppy/companion/lib/server/jobs.js b/packages/@uppy/companion/lib/server/jobs.js
index fe40483..eed260c 100644
--- a/packages/@uppy/companion/lib/server/jobs.js
+++ b/packages/@uppy/companion/lib/server/jobs.js
@@ -30,7 +30,7 @@ const cleanUpFinishedUploads = (dirPath) => {
           // but we also log the error
           logger.error(err2, "jobs.cleanup.stat.error");
           // @ts-ignore
-        } else if (((new Date()) - stats.mtime) < twelveHoursAgo) {
+        } else if (Date.now() - stats.mtime < twelveHoursAgo) {
           logger.info(`skipping file ${file}`, "jobs.cleanup.skip");
           return;
         }
@@ -58,7 +58,10 @@ async function runPeriodicPing({ urls, payload, requestTimeout }) {
   // Run requests in parallel
   await Promise.all(urls.map(async (url) => {
     try {
-      await (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");
     }
@@ -92,7 +95,12 @@ exports.startPeriodicPingJob = async ({ urls, interval = 60000, count, staticPay
     }
     try {
       requesting = true;
-      const payload = { version, processId, service: "companion", ...staticPayload };
+      const payload = {
+        version,
+        processId,
+        service: "companion",
+        ...staticPayload,
+      };
       await runPeriodicPing({ urls, payload, requestTimeout });
     } finally {
       requesting = false;
diff --git a/packages/@uppy/companion/lib/server/logger.js b/packages/@uppy/companion/lib/server/logger.js
index 1f343f2..b717c5e 100644
--- a/packages/@uppy/companion/lib/server/logger.js
+++ b/packages/@uppy/companion/lib/server/logger.js
@@ -53,7 +53,11 @@ const log = ({ arg, tag = "", level, traceId = "", color = [] }) => {
     // We don't need to log stack trace on special errors that we ourselves have produced
     // (to reduce log noise)
     // @ts-ignore
-    if ((arg instanceof Error && arg.name === "ProviderApiError") && typeof arg.message === "string") {
+    if (
+      arg instanceof Error
+      && arg.name === "ProviderApiError"
+      && typeof arg.message === "string"
+    ) {
       return arg.message;
     }
     if (typeof arg === "string") {
@@ -63,7 +67,6 @@ const log = ({ arg, tag = "", level, traceId = "", color = [] }) => {
   }
   const msgString = msgToString();
   const masked = maskMessage(msgString);
-  // eslint-disable-next-line no-console
   console.log(
     styleText(color, `${processName}: ${time} [${level}] ${traceId}${whitespace}${tag}`),
     styleText(color, masked),
diff --git a/packages/@uppy/companion/lib/server/middlewares.js b/packages/@uppy/companion/lib/server/middlewares.js
index bbe07df..074e252 100644
--- a/packages/@uppy/companion/lib/server/middlewares.js
+++ b/packages/@uppy/companion/lib/server/middlewares.js
@@ -115,7 +115,11 @@ 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.
   const existingExposeHeaders = res.get("Access-Control-Expose-Headers");
-  const exposeHeadersSet = new Set(existingExposeHeaders?.split(",")?.map((method) => method.trim().toLowerCase()));
+  const exposeHeadersSet = new Set(
+    existingExposeHeaders
+      ?.split(",")
+      ?.map((method) => method.trim().toLowerCase()),
+  );
   if (options.sendSelfEndpoint) {
     exposeHeadersSet.add("i-am");
   }
@@ -138,7 +142,11 @@ exports.cors = (options = {}) => (req, res, next) => {
       : allowedHeaders,
   );
   const existingAllowMethods = res.get("Access-Control-Allow-Methods");
-  const allowMethodsSet = new Set(existingAllowMethods?.split(",")?.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.
@@ -157,13 +165,19 @@ exports.cors = (options = {}) => (req, res, next) => {
   })(req, res, next);
 };
 exports.metrics = ({ path = undefined } = {}) => {
-  const metricsMiddleware = promBundle({ includeMethod: true, metricsPath: path ? `${path}/metrics` : undefined });
+  const metricsMiddleware = promBundle({
+    includeMethod: true,
+    metricsPath: path ? `${path}/metrics` : undefined,
+  });
   // @ts-ignore Not in the typings, but it does exist
   const { promClient } = metricsMiddleware;
   const { collectDefaultMetrics } = promClient;
   collectDefaultMetrics({ register: promClient.register });
   // Add version as a prometheus gauge
-  const versionGauge = new promClient.Gauge({ name: "companion_version", help: "npm version as an integer" });
+  const versionGauge = new promClient.Gauge({
+    name: "companion_version",
+    help: "npm version as an integer",
+  });
   const numberVersion = Number(version.replace(/\D/g, ""));
   versionGauge.set(numberVersion);
   return metricsMiddleware;
diff --git a/packages/@uppy/companion/lib/server/provider/Provider.js b/packages/@uppy/companion/lib/server/provider/Provider.js
index 491bfa9..2346204 100644
--- a/packages/@uppy/companion/lib/server/provider/Provider.js
+++ b/packages/@uppy/companion/lib/server/provider/Provider.js
@@ -13,6 +13,7 @@ class Provider {
     this.allowLocalUrls = allowLocalUrls;
     this.providerGrantConfig = providerGrantConfig;
     this.secret = secret;
+    // biome-ignore lint/correctness/noConstructorReturn: ...
     return this;
   }
   /**
@@ -27,7 +28,6 @@ class Provider {
    * @param {object} options
    * @returns {Promise}
    */
-  // eslint-disable-next-line class-methods-use-this,no-unused-vars
   async list(options) {
     throw new Error("method not implemented");
   }
@@ -37,7 +37,6 @@ class Provider {
    * @param {object} options
    * @returns {Promise}
    */
-  // eslint-disable-next-line class-methods-use-this,no-unused-vars
   async download(options) {
     throw new Error("method not implemented");
   }
@@ -47,7 +46,6 @@ class Provider {
    * @param {object} options
    * @returns {Promise}
    */
-  // eslint-disable-next-line class-methods-use-this,no-unused-vars
   async thumbnail(options) {
     throw new Error("method not implemented");
   }
@@ -59,7 +57,6 @@ class Provider {
    * @param {object} options
    * @returns {Promise}
    */
-  // eslint-disable-next-line class-methods-use-this,no-unused-vars
   async size(options) {
     return undefined;
   }
@@ -69,7 +66,6 @@ class Provider {
    * @param {object} options
    * @returns {Promise}
    */
-  // eslint-disable-next-line class-methods-use-this,no-unused-vars
   async deauthorizationCallback(options) {
     // @todo consider doing something like throw new NotImplementedError() instead
     throw new Error("method not implemented");
@@ -77,7 +73,6 @@ class Provider {
   /**
    * Generate a new access token based on the refresh token
    */
-  // eslint-disable-next-line class-methods-use-this,no-unused-vars
   async refreshToken(options) {
     throw new Error("method not implemented");
   }
@@ -85,7 +80,6 @@ class Provider {
    * @param {any} param0
    * @returns {Promise<any>}
    */
-  // eslint-disable-next-line no-unused-vars, class-methods-use-this
   async simpleAuth({ requestBody }) {
     throw new Error("method not implemented");
   }
@@ -97,7 +91,6 @@ class Provider {
   static get oauthProvider() {
     return undefined;
   }
-  // eslint-disable-next-line no-unused-vars
   static grantDynamicToUserSession({ grantDynamic }) {
     return {};
   }
diff --git a/packages/@uppy/companion/lib/server/provider/box/adapter.js b/packages/@uppy/companion/lib/server/provider/box/adapter.js
index b735d6a..a2a9374 100644
--- a/packages/@uppy/companion/lib/server/provider/box/adapter.js
+++ b/packages/@uppy/companion/lib/server/provider/box/adapter.js
@@ -32,7 +32,10 @@ const getItemThumbnailUrl = (item) => {
   return `/box/thumbnail/${getItemRequestPath(item)}`;
 };
 const getNextPagePath = (data) => {
-  if (data.total_count < data.limit || data.offset + data.limit > data.total_count) {
+  if (
+    data.total_count < data.limit
+    || data.offset + data.limit > data.total_count
+  ) {
     return null;
   }
   const query = { cursor: data.offset + data.limit };
diff --git a/packages/@uppy/companion/lib/server/provider/box/index.js b/packages/@uppy/companion/lib/server/provider/box/index.js
index d7fd745..2094fe3 100644
--- a/packages/@uppy/companion/lib/server/provider/box/index.js
+++ b/packages/@uppy/companion/lib/server/provider/box/index.js
@@ -15,14 +15,22 @@ const getClient = async ({ token }) =>
     },
   });
 async function getUserInfo({ token }) {
-  return (await 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";
-  return (await getClient({ token })).get(`folders/${directory || rootFolderID}/items`, {
-    searchParams: { fields: BOX_FILES_FIELDS, offset: query.cursor, limit: 1000 },
-    responseType: "json",
-  }).json();
+  return (await getClient({ token }))
+    .get(`folders/${directory || rootFolderID}/items`, {
+      searchParams: {
+        fields: BOX_FILES_FIELDS,
+        offset: query.cursor,
+        limit: 1000,
+      },
+      responseType: "json",
+    })
+    .json();
 }
 /**
  * Adapter for API https://developer.box.com/reference/
@@ -74,7 +82,10 @@ class Box extends Provider {
       //
       // 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 },
+        searchParams: {
+          max_height: BOX_THUMBNAIL_SIZE,
+          max_width: BOX_THUMBNAIL_SIZE,
+        },
         responseType: "json",
       });
       await prepareStream(stream);
@@ -83,7 +94,9 @@ class Box extends Provider {
   }
   async size({ id, token }) {
     return this.#withErrorHandling("provider.box.size.error", async () => {
-      const { size } = await (await getClient({ token })).get(`files/${id}`, { responseType: "json" }).json();
+      const { size } = await (await getClient({ token }))
+        .get(`files/${id}`, { responseType: "json" })
+        .json();
       return parseInt(size, 10);
     });
   }
@@ -102,7 +115,6 @@ class Box extends Provider {
       return { revoked: true };
     });
   }
-  // eslint-disable-next-line class-methods-use-this
   async #withErrorHandling(tag, fn) {
     return withProviderErrorHandling({
       fn,
diff --git a/packages/@uppy/companion/lib/server/provider/credentials.js b/packages/@uppy/companion/lib/server/provider/credentials.js
index b41330f..9985d97 100644
--- a/packages/@uppy/companion/lib/server/provider/credentials.js
+++ b/packages/@uppy/companion/lib/server/provider/credentials.js
@@ -4,7 +4,7 @@ const logger = require("../logger");
 const oAuthState = require("../helpers/oauth-state");
 const tokenService = require("../helpers/jwt");
 const { getURLBuilder, getRedirectPath } = require("../helpers/utils");
-// eslint-disable-next-line
+// biome-ignore lint/correctness/noUnusedVariables: used in types
 const Provider = require("./Provider");
 const got = require("../got");
 /**
@@ -14,9 +14,11 @@ const got = require("../got");
  */
 async function fetchKeys(url, providerName, credentialRequestParams) {
   try {
-    const { credentials } = await (await got).post(url, {
-      json: { provider: providerName, parameters: credentialRequestParams },
-    }).json();
+    const { credentials } = await (await got)
+      .post(url, {
+        json: { provider: providerName, parameters: credentialRequestParams },
+      })
+      .json();
     if (!credentials) {
       throw new Error("Received no remote credentials");
     }
@@ -39,7 +41,7 @@ async function fetchKeys(url, providerName, credentialRequestParams) {
 async function fetchProviderKeys(providerName, companionOptions, credentialRequestParams) {
   let providerConfig = companionOptions.providerOptions[providerName];
   if (!providerConfig) {
-    providerConfig = (companionOptions.customProviders[providerName] || {}).config;
+    providerConfig = companionOptions.customProviders[providerName]?.config;
   }
   if (!providerConfig) {
     return null;
@@ -92,7 +94,7 @@ exports.getCredentialsOverrideMiddleware = (providers, companionOptions) => {
       let payload;
       try {
         payload = tokenService.verifyEncryptedToken(preAuthToken, companionOptions.preAuthSecret);
-      } catch (err) {
+      } catch (_err) {
         next();
         return;
       }
@@ -102,7 +104,10 @@ exports.getCredentialsOverrideMiddleware = (providers, companionOptions) => {
       // token through window.postMessage (see comment in connect.js).
       // postMessage happens in send-token.js, which is a different request, so we need to put the allowed origins
       // on the encrypted session state to access it later there.
-      if (Array.isArray(credentials.origins) && credentials.origins.length > 0) {
+      if (
+        Array.isArray(credentials.origins)
+        && credentials.origins.length > 0
+      ) {
         const decodedState = oAuthState.decodeState(state, companionOptions.secret);
         decodedState.customerDefinedAllowedOrigins = credentials.origins;
         const newState = oAuthState.encodeState(decodedState, companionOptions.secret);
diff --git a/packages/@uppy/companion/lib/server/provider/dropbox/index.js b/packages/@uppy/companion/lib/server/provider/dropbox/index.js
index e402030..ee066c3 100644
--- a/packages/@uppy/companion/lib/server/provider/dropbox/index.js
+++ b/packages/@uppy/companion/lib/server/provider/dropbox/index.js
@@ -18,7 +18,9 @@ function httpHeaderSafeJson(v) {
   });
 }
 async function getUserInfo({ client }) {
-  return client.post("users/get_current_account", { responseType: "json" }).json();
+  return client
+    .post("users/get_current_account", { responseType: "json" })
+    .json();
 }
 async function getClient({ token, namespaced }) {
   const got = await gotPromise;
@@ -27,7 +29,14 @@ async function getClient({ token, namespaced }) {
       prefixUrl: "https://api.dropboxapi.com/2",
       headers: {
         authorization: `Bearer ${token}`,
-        ...(namespace ? { "Dropbox-API-Path-Root": JSON.stringify({ ".tag": "root", "root": namespace }) } : {}),
+        ...(namespace
+          ? {
+            "Dropbox-API-Path-Root": JSON.stringify({
+              ".tag": "root",
+              root: namespace,
+            }),
+          }
+          : {}),
       },
     });
   let client = makeClient();
@@ -37,8 +46,10 @@ async function getClient({ token, namespaced }) {
   // https://developers.dropbox.com/dbx-team-files-guide#namespaces
   // https://www.dropbox.com/developers/reference/path-root-header-modes
   if (
-    namespaced && userInfo.root_info != null
-    && userInfo.root_info.root_namespace_id !== userInfo.root_info.home_namespace_id
+    namespaced
+    && userInfo.root_info != null
+    && userInfo.root_info.root_namespace_id
+      !== userInfo.root_info.home_namespace_id
   ) {
     logger.debug("using root_namespace_id", userInfo.root_info.root_namespace_id);
     client = makeClient(userInfo.root_info.root_namespace_id);
@@ -54,18 +65,25 @@ const getOauthClient = async () =>
   });
 async function list({ client, directory, query }) {
   if (query.cursor) {
-    return client.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 client.post("files/list_folder", {
-    searchParams: query,
-    json: {
-      path: `${directory || ""}`,
-      include_non_downloadable_files: false,
-      // min=1, max=2000 (default: 500): The maximum number of results to return per request.
-      limit: 2000,
-    },
-    responseType: "json",
-  }).json();
+  return client
+    .post("files/list_folder", {
+      searchParams: query,
+      json: {
+        path: `${directory || ""}`,
+        include_non_downloadable_files: false,
+        // min=1, max=2000 (default: 500): The maximum number of results to return per request.
+        limit: 2000,
+      },
+      responseType: "json",
+    })
+    .json();
 }
 /**
  * Adapter for API https://www.dropbox.com/developers/documentation/http/documentation
@@ -86,7 +104,10 @@ class DropBox extends Provider {
    */
   async list(options) {
     return this.#withErrorHandling("provider.dropbox.list.error", async () => {
-      const { client, userInfo } = await getClient({ token: options.token, namespaced: true });
+      const { client, userInfo } = await getClient({
+        token: options.token,
+        namespaced: true,
+      });
       const stats = await list({ ...options, client });
       const { email } = userInfo;
       return adaptData(stats, email, options.companion.buildURL);
@@ -127,10 +148,12 @@ class DropBox extends Provider {
   }
   async size({ id, token }) {
     return this.#withErrorHandling("provider.dropbox.size.error", async () => {
-      const { size } = await (await getClient({ token, namespaced: true })).client.post("files/get_metadata", {
-        json: { path: id },
-        responseType: "json",
-      }).json();
+      const { size } = await (await getClient({ token, namespaced: true })).client
+        .post("files/get_metadata", {
+          json: { path: id },
+          responseType: "json",
+        })
+        .json();
       return parseInt(size, 10);
     });
   }
@@ -142,18 +165,19 @@ class DropBox extends Provider {
   }
   async refreshToken({ clientId, clientSecret, refreshToken }) {
     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();
+      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,
diff --git a/packages/@uppy/companion/lib/server/provider/error.js b/packages/@uppy/companion/lib/server/provider/error.js
index 5c6e4d4..807f209 100644
--- a/packages/@uppy/companion/lib/server/provider/error.js
+++ b/packages/@uppy/companion/lib/server/provider/error.js
@@ -1,5 +1,4 @@
 "use strict";
-/* eslint-disable max-classes-per-file */
 /**
  * ProviderApiError is error returned when an adapter encounters
  * an http error while communication with its corresponding provider
@@ -91,7 +90,10 @@ function errorToResponse(err) {
   const httpError = parseHttpError(err);
   if (httpError) {
     // We proxy the response purely for ease of debugging
-    return { code: 500, json: { statusCode: httpError.statusCode, body: httpError.body } };
+    return {
+      code: 500,
+      json: { statusCode: httpError.statusCode, body: httpError.body },
+    };
   }
   return undefined;
 }
@@ -103,4 +105,10 @@ function respondWithError(err, res) {
   }
   return false;
 }
-module.exports = { ProviderAuthError, ProviderApiError, ProviderUserError, respondWithError, parseHttpError };
+module.exports = {
+  ProviderAuthError,
+  ProviderApiError,
+  ProviderUserError,
+  respondWithError,
+  parseHttpError,
+};
diff --git a/packages/@uppy/companion/lib/server/provider/facebook/index.js b/packages/@uppy/companion/lib/server/provider/facebook/index.js
index 085f8c0..1a85ec1 100644
--- a/packages/@uppy/companion/lib/server/provider/facebook/index.js
+++ b/packages/@uppy/companion/lib/server/provider/facebook/index.js
@@ -12,7 +12,8 @@ async function runRequestBatch({ secret, token, requests }) {
   // https://developers.facebook.com/docs/facebook-login/security/#appsecret
   // couldn't get `appsecret_time` working, but it seems to be working without it
   // const time = Math.floor(Date.now() / 1000)
-  const appSecretProof = crypto.createHmac("sha256", secret)
+  const appSecretProof = crypto
+    .createHmac("sha256", secret)
     // .update(`${token}|${time}`)
     .update(token)
     .digest("hex");
@@ -22,11 +23,19 @@ async function runRequestBatch({ secret, token, requests }) {
     // appsecret_time: String(time),
     batch: JSON.stringify(requests),
   };
-  const responsesRaw = await (await got).post("https://graph.facebook.com", { form }).json();
-  const responses = responsesRaw.map((response) => ({ ...response, body: JSON.parse(response.body) }));
+  const responsesRaw = await (await got)
+    .post("https://graph.facebook.com", { form })
+    .json();
+  const responses = responsesRaw.map((response) => ({
+    ...response,
+    body: JSON.parse(response.body),
+  }));
   const errorResponse = responses.find((response) => response.code !== 200);
   if (errorResponse) {
-    throw new HttpError({ statusCode: errorResponse.code, responseJson: errorResponse.body });
+    throw new HttpError({
+      statusCode: errorResponse.code,
+      responseJson: errorResponse.body,
+    });
   }
   return responses;
 }
@@ -35,7 +44,10 @@ async function getMediaUrl({ secret, token, id }) {
     secret,
     token,
     requests: [
-      { method: "GET", relative_url: `${id}?${new URLSearchParams({ fields: "images" }).toString()}` },
+      {
+        method: "GET",
+        relative_url: `${id}?${new URLSearchParams({ fields: "images" }).toString()}`,
+      },
     ],
   });
   const sortedImages = sortImages(body.images);
@@ -63,7 +75,10 @@ class Facebook extends Provider {
         secret: this.secret,
         token,
         requests: [
-          { method: "GET", relative_url: `me?${new URLSearchParams({ fields: "email" }).toString()}` },
+          {
+            method: "GET",
+            relative_url: `me?${new URLSearchParams({ fields: "email" }).toString()}`,
+          },
           { method: "GET", relative_url: `${path}?${new URLSearchParams(qs)}` },
         ],
       });
@@ -80,7 +95,6 @@ class Facebook extends Provider {
       return { stream, size };
     });
   }
-  // eslint-disable-next-line class-methods-use-this
   async thumbnail() {
     // not implementing this because a public thumbnail from facebook will be used instead
     logger.error("call to thumbnail is not implemented", "provider.facebook.thumbnail.error");
@@ -91,14 +105,11 @@ class Facebook extends Provider {
       await runRequestBatch({
         secret: this.secret,
         token,
-        requests: [
-          { method: "DELETE", relative_url: "me/permissions" },
-        ],
+        requests: [{ method: "DELETE", relative_url: "me/permissions" }],
       });
       return { revoked: true };
     });
   }
-  // eslint-disable-next-line class-methods-use-this
   async #withErrorHandling(tag, fn) {
     return withProviderErrorHandling({
       fn,
diff --git a/packages/@uppy/companion/lib/server/provider/google/drive/adapter.js b/packages/@uppy/companion/lib/server/provider/google/drive/adapter.js
index 287492d..9a7fce4 100644
--- a/packages/@uppy/companion/lib/server/provider/google/drive/adapter.js
+++ b/packages/@uppy/companion/lib/server/provider/google/drive/adapter.js
@@ -4,13 +4,14 @@ const getUsername = (data) => {
   return data.user.emailAddress;
 };
 exports.isGsuiteFile = (mimeType) => {
-  return mimeType && mimeType.startsWith("application/vnd.google");
+  return mimeType?.startsWith("application/vnd.google");
 };
 const isSharedDrive = (item) => {
   return item.kind === "drive#drive";
 };
 const isFolder = (item) => {
-  return item.mimeType === "application/vnd.google-apps.folder" || isSharedDrive(item);
+  return (item.mimeType === "application/vnd.google-apps.folder"
+    || isSharedDrive(item));
 };
 exports.isShortcut = (mimeType) => {
   return mimeType === "application/vnd.google-apps.shortcut";
@@ -26,7 +27,10 @@ const getItemIcon = (item) => {
       ? item.backgroundImageLink.replace(sizeParamRegex, size)
       : `${item.backgroundImageLink}${size}`;
   }
-  if (item.thumbnailLink && !item.mimeType.startsWith("application/vnd.google")) {
+  if (
+    item.thumbnailLink
+    && !item.mimeType.startsWith("application/vnd.google")
+  ) {
     const smallerThumbnailLink = item.thumbnailLink.replace("s220", "s40");
     return smallerThumbnailLink;
   }
@@ -42,7 +46,9 @@ const getItemSubList = (item) => {
     "application/vnd.google-apps.shortcut",
   ];
   return item.files.filter((i) => {
-    return isFolder(i) || !exports.isGsuiteFile(i.mimeType) || allowedGSuiteTypes.includes(i.mimeType);
+    return (isFolder(i)
+      || !exports.isGsuiteFile(i.mimeType)
+      || allowedGSuiteTypes.includes(i.mimeType));
   });
 };
 const getItemName = (item) => {
@@ -101,13 +107,13 @@ const getNextPagePath = (data, currentQuery, currentPath) => {
   const query = { ...currentQuery, cursor: data.nextPageToken };
   return `${currentPath}?${querystring.stringify(query)}`;
 };
-const getImageHeight = (item) => item.imageMediaMetadata && item.imageMediaMetadata.height;
-const getImageWidth = (item) => item.imageMediaMetadata && item.imageMediaMetadata.width;
-const getImageRotation = (item) => item.imageMediaMetadata && item.imageMediaMetadata.rotation;
-const getImageDate = (item) => item.imageMediaMetadata && item.imageMediaMetadata.date;
-const getVideoHeight = (item) => item.videoMediaMetadata && item.videoMediaMetadata.height;
-const getVideoWidth = (item) => item.videoMediaMetadata && item.videoMediaMetadata.width;
-const getVideoDurationMillis = (item) => item.videoMediaMetadata && item.videoMediaMetadata.durationMillis;
+const getImageHeight = (item) => item.imageMediaMetadata?.height;
+const getImageWidth = (item) => item.imageMediaMetadata?.width;
+const getImageRotation = (item) => item.imageMediaMetadata?.rotation;
+const getImageDate = (item) => item.imageMediaMetadata?.date;
+const getVideoHeight = (item) => item.videoMediaMetadata?.height;
+const getVideoWidth = (item) => item.videoMediaMetadata?.width;
+const getVideoDurationMillis = (item) => item.videoMediaMetadata?.durationMillis;
 // Hopefully this name will not be used by Google
 exports.VIRTUAL_SHARED_DIR = "shared-with-me";
 exports.adaptData = (listFilesResp, sharedDrivesResp, directory, query, showSharedWithMe, about) => {
@@ -136,17 +142,17 @@ exports.adaptData = (listFilesResp, sharedDrivesResp, directory, query, showShar
   const sharedDrives = sharedDrivesResp ? sharedDrivesResp.drives || [] : [];
   // “Shared with me” is a list of shared documents,
   // not the same as sharedDrives
-  const virtualItem = showSharedWithMe && ({
+  const virtualItem = showSharedWithMe && {
     isFolder: true,
     icon: "folder",
     name: "Shared with me",
     mimeType: "application/vnd.google-apps.folder",
     id: exports.VIRTUAL_SHARED_DIR,
     requestPath: exports.VIRTUAL_SHARED_DIR,
-  });
+  };
   const adaptedItems = [
     ...(virtualItem ? [virtualItem] : []), // shared folder first
-    ...([...sharedDrives, ...items].map(adaptItem)),
+    ...[...sharedDrives, ...items].map(adaptItem),
   ];
   return {
     username: getUsername(about),
diff --git a/packages/@uppy/companion/lib/server/provider/google/drive/index.js b/packages/@uppy/companion/lib/server/provider/google/drive/index.js
index 9356621..e219eaf 100644
--- a/packages/@uppy/companion/lib/server/provider/google/drive/index.js
+++ b/packages/@uppy/companion/lib/server/provider/google/drive/index.js
@@ -29,12 +29,13 @@ const getClient = async ({ token }) =>
   });
 async function getStats({ id, token }) {
   const client = await getClient({ token });
-  const getStatsInner = async (
-    statsOfId,
-  ) => (client.get(`files/${encodeURIComponent(statsOfId)}`, {
-    searchParams: { fields: DRIVE_FILE_FIELDS, supportsAllDrives: true },
-    responseType: "json",
-  }).json());
+  const getStatsInner = async (statsOfId) =>
+    client
+      .get(`files/${encodeURIComponent(statsOfId)}`, {
+        searchParams: { fields: DRIVE_FILE_FIELDS, supportsAllDrives: true },
+        responseType: "json",
+      })
+      .json();
   const stats = await getStatsInner(id);
   // If it is a shortcut, we need to get stats again on the target
   if (isShortcut(stats.mimeType)) {
@@ -60,7 +61,9 @@ async function streamGoogleFile({ token, id: idIn }) {
           authorization: `Bearer ${token}`,
         },
       });
-      stream = gSuiteFilesClient.stream.get(mimeTypeExportLink, { responseType: "json" });
+      stream = gSuiteFilesClient.stream.get(mimeTypeExportLink, {
+        responseType: "json",
+      });
     } else {
       stream = client.stream.get(`files/${encodeURIComponent(id)}/export`, {
         searchParams: { supportsAllDrives: true, mimeType: mimeType2 },
@@ -86,7 +89,6 @@ class Drive extends Provider {
   static get authStateExpiry() {
     return MAX_AGE_REFRESH_TOKEN;
   }
-  // eslint-disable-next-line class-methods-use-this
   async list(options) {
     return withGoogleErrorHandling(Drive.oauthProvider, "provider.drive.list.error", async () => {
       const directory = options.directory || "root";
@@ -100,17 +102,26 @@ class Drive extends Provider {
         if (!shouldListSharedDrives) {
           return undefined;
         }
-        const response = await client.get("drives", {
-          searchParams: { fields: SHARED_DRIVE_FIELDS, pageToken, pageSize: 100 },
-          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] };
+          return {
+            ...nextResponse,
+            drives: [...response.drives, ...nextResponse.drives],
+          };
         }
         return response;
       }
@@ -130,13 +141,21 @@ class Drive extends Provider {
           includeItemsFromAllDrives: true,
           supportsAllDrives: true,
         };
-        return client.get("files", { searchParams, responseType: "json" }).json();
+        return client
+          .get("files", { searchParams, responseType: "json" })
+          .json();
       }
       async function fetchAbout() {
         const searchParams = { fields: "user" };
-        return client.get("about", { searchParams, responseType: "json" }).json();
+        return client
+          .get("about", { searchParams, responseType: "json" })
+          .json();
       }
-      const [sharedDrives, filesResponse, about] = await Promise.all([fetchSharedDrives(), fetchFiles(), fetchAbout()]);
+      const [sharedDrives, filesResponse, about] = await Promise.all([
+        fetchSharedDrives(),
+        fetchFiles(),
+        fetchAbout(),
+      ]);
       return adaptData(
         filesResponse,
         sharedDrives,
@@ -147,7 +166,6 @@ class Drive extends Provider {
       );
     });
   }
-  // eslint-disable-next-line class-methods-use-this
   async download({ id, token }) {
     if (mockAccessTokenExpiredError != null) {
       logger.warn(`Access token: ${token}`);
diff --git a/packages/@uppy/companion/lib/server/provider/google/index.d.ts b/packages/@uppy/companion/lib/server/provider/google/index.d.ts
index 4acf948..2b61b8a 100644
--- a/packages/@uppy/companion/lib/server/provider/google/index.d.ts
+++ b/packages/@uppy/companion/lib/server/provider/google/index.d.ts
@@ -1,4 +1,4 @@
-export function refreshToken({ clientId, clientSecret, refreshToken: theRefreshToken }: {
+export function refreshToken({ clientId, clientSecret, refreshToken: theRefreshToken, }: {
     clientId: any;
     clientSecret: any;
     refreshToken: any;
diff --git a/packages/@uppy/companion/lib/server/provider/google/index.js b/packages/@uppy/companion/lib/server/provider/google/index.js
index aa9b2af..74e4246 100644
--- a/packages/@uppy/companion/lib/server/provider/google/index.js
+++ b/packages/@uppy/companion/lib/server/provider/google/index.js
@@ -10,15 +10,17 @@ const getOauthClient = async () =>
   });
 async function refreshToken({ clientId, clientSecret, refreshToken: theRefreshToken }) {
   return withGoogleErrorHandling("google", "provider.google.token.refresh.error", async () => {
-    const { access_token: accessToken } = await (await getOauthClient()).post("token", {
-      responseType: "json",
-      form: {
-        refresh_token: theRefreshToken,
-        grant_type: "refresh_token",
-        client_id: clientId,
-        client_secret: clientSecret,
-      },
-    }).json();
+    const { access_token: accessToken } = await (await getOauthClient())
+      .post("token", {
+        responseType: "json",
+        form: {
+          refresh_token: theRefreshToken,
+          grant_type: "refresh_token",
+          client_id: clientId,
+          client_secret: clientSecret,
+        },
+      })
+      .json();
     return { accessToken };
   });
 }
diff --git a/packages/@uppy/companion/lib/server/provider/index.js b/packages/@uppy/companion/lib/server/provider/index.js
index 4128bc0..e8d796a 100644
--- a/packages/@uppy/companion/lib/server/provider/index.js
+++ b/packages/@uppy/companion/lib/server/provider/index.js
@@ -47,7 +47,12 @@ module.exports.getProviderMiddleware = (providers, grantConfig) => {
         req.companion.providerGrantConfig = providerGrantConfig;
       }
       const secret = providerOptions[providerName]?.secret;
-      req.companion.provider = new ProviderClass({ secret, providerName, providerGrantConfig, allowLocalUrls });
+      req.companion.provider = new ProviderClass({
+        secret,
+        providerName,
+        providerGrantConfig,
+        allowLocalUrls,
+      });
       req.companion.providerClass = ProviderClass;
     } else {
       logger.warn(
@@ -64,7 +69,17 @@ module.exports.getProviderMiddleware = (providers, grantConfig) => {
  * @returns {Record<string, typeof Provider>}
  */
 module.exports.getDefaultProviders = () => {
-  const providers = { dropbox, box, drive: Drive, facebook, onedrive, zoom, instagram, unsplash, webdav };
+  const providers = {
+    dropbox,
+    box,
+    drive: Drive,
+    facebook,
+    onedrive,
+    zoom,
+    instagram,
+    unsplash,
+    webdav,
+  };
   return providers;
 };
 /**
@@ -77,11 +92,9 @@ module.exports.getDefaultProviders = () => {
 module.exports.addCustomProviders = (customProviders, providers, grantConfig) => {
   Object.keys(customProviders).forEach((providerName) => {
     const customProvider = customProviders[providerName];
-    // eslint-disable-next-line no-param-reassign
     providers[providerName] = customProvider.module;
     const { oauthProvider } = customProvider.module;
     if (isOAuthProvider(oauthProvider)) {
-      // eslint-disable-next-line no-param-reassign
       grantConfig[oauthProvider] = {
         ...customProvider.config,
         // todo: consider setting these options from a universal point also used
@@ -104,7 +117,6 @@ module.exports.addProviderOptions = (companionOptions, grantConfig, getOauthProv
     logger.warn("invalid provider options detected. Providers will not be loaded", "provider.options.invalid");
     return;
   }
-  // eslint-disable-next-line no-param-reassign
   grantConfig.defaults = {
     host: server.host,
     protocol: server.protocol,
@@ -116,32 +128,30 @@ module.exports.addProviderOptions = (companionOptions, grantConfig, getOauthProv
     const oauthProvider = getOauthProvider?.(providerName);
     if (isOAuthProvider(oauthProvider) && grantConfig[oauthProvider]) {
       // explicitly add providerOptions so users don't override other providerOptions.
-      // eslint-disable-next-line no-param-reassign
       grantConfig[oauthProvider].key = providerOptions[providerName].key;
-      // eslint-disable-next-line no-param-reassign
       grantConfig[oauthProvider].secret = providerOptions[providerName].secret;
       if (providerOptions[providerName].credentialsURL) {
-        // eslint-disable-next-line no-param-reassign
-        grantConfig[oauthProvider].dynamic = ["key", "secret", "redirect_uri", "origins"];
+        grantConfig[oauthProvider].dynamic = [
+          "key",
+          "secret",
+          "redirect_uri",
+          "origins",
+        ];
       }
       const provider = exports.getDefaultProviders()[providerName];
       Object.assign(grantConfig[oauthProvider], provider.getExtraGrantConfig());
       // override grant.js redirect uri with companion's custom redirect url
       const isExternal = !!server.implicitPath;
       const redirectPath = getRedirectPath(providerName);
-      // eslint-disable-next-line no-param-reassign
       grantConfig[oauthProvider].redirect_uri = getURLBuilder(companionOptions)(redirectPath, isExternal);
       if (oauthDomain) {
         const fullRedirectPath = getURLBuilder(companionOptions)(redirectPath, isExternal, true);
-        // eslint-disable-next-line no-param-reassign
         grantConfig[oauthProvider].redirect_uri = `${server.protocol}://${oauthDomain}${fullRedirectPath}`;
       }
       if (server.implicitPath) {
         // no url builder is used for this because grant internally adds the path
-        // eslint-disable-next-line no-param-reassign
         grantConfig[oauthProvider].callback = `${server.implicitPath}${grantConfig[oauthProvider].callback}`;
       } else if (server.path) {
-        // eslint-disable-next-line no-param-reassign
         grantConfig[oauthProvider].callback = `${server.path}${grantConfig[oauthProvider].callback}`;
       }
     }
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 1d0d49a..c03616e 100644
--- a/packages/@uppy/companion/lib/server/provider/instagram/graph/index.js
+++ b/packages/@uppy/companion/lib/server/provider/instagram/graph/index.js
@@ -14,10 +14,12 @@ const getClient = async ({ token }) =>
     },
   });
 async function getMediaUrl({ token, id }) {
-  const body = await (await getClient({ token })).get(String(id), {
-    searchParams: { fields: "media_url" },
-    responseType: "json",
-  }).json();
+  const body = await (await getClient({ token }))
+    .get(String(id), {
+      searchParams: { fields: "media_url" },
+      responseType: "json",
+    })
+    .json();
   return body.media_url;
 }
 /**
@@ -45,8 +47,15 @@ class Instagram extends Provider {
       }
       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(),
+        client
+          .get("me", {
+            searchParams: { fields: "username" },
+            responseType: "json",
+          })
+          .json(),
+        client
+          .get("me/media", { searchParams: qs, responseType: "json" })
+          .json(),
       ]);
       return adaptData(list, username, directory, query);
     });
@@ -59,18 +68,18 @@ class Instagram extends Provider {
       return { stream, size };
     });
   }
-  // eslint-disable-next-line class-methods-use-this
   async thumbnail() {
     // not implementing this because a public thumbnail from instagram will be used instead
     logger.error("call to thumbnail is not implemented", "provider.instagram.thumbnail.error");
     throw new Error("call to thumbnail is not implemented");
   }
-  // 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/" };
+    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,
diff --git a/packages/@uppy/companion/lib/server/provider/onedrive/index.js b/packages/@uppy/companion/lib/server/provider/onedrive/index.js
index bce921d..2afebe7 100644
--- a/packages/@uppy/companion/lib/server/provider/onedrive/index.js
+++ b/packages/@uppy/companion/lib/server/provider/onedrive/index.js
@@ -17,7 +17,7 @@ const getOauthClient = async () =>
   (await got).extend({
     prefixUrl: "https://login.live.com",
   });
-const getRootPath = (query) => (query.driveId ? `drives/${query.driveId}` : "me/drive");
+const getRootPath = (query) => query.driveId ? `drives/${query.driveId}` : "me/drive";
 /**
  * Adapter for API https://docs.microsoft.com/en-us/onedrive/developer/rest-api/
  */
@@ -47,7 +47,12 @@ class OneDrive extends Provider {
       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(),
+        client
+          .get(`${getRootPath(query)}/${path}/children`, {
+            searchParams: qs,
+            responseType: "json",
+          })
+          .json(),
       ]);
       return adaptData(list, mail || userPrincipalName, query, directory);
     });
@@ -61,7 +66,6 @@ class OneDrive extends Provider {
       return { stream, size };
     });
   }
-  // eslint-disable-next-line class-methods-use-this
   async thumbnail() {
     // not implementing this because a public thumbnail from onedrive will be used instead
     logger.error("call to thumbnail is not implemented", "provider.onedrive.thumbnail.error");
@@ -69,33 +73,36 @@ class OneDrive extends Provider {
   }
   async size({ id, query, token }) {
     return this.#withErrorHandling("provider.onedrive.size.error", async () => {
-      const { size } = await (await getClient({ token })).get(`${getRootPath(query)}/items/${id}`, {
-        responseType: "json",
-      }).json();
+      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() {
     // apparently M$ doesn't support programmatic oauth2 revoke
-    return { revoked: false, manual_revoke_url: "https://account.live.com/consent/Manage" };
+    return {
+      revoked: false,
+      manual_revoke_url: "https://account.live.com/consent/Manage",
+    };
   }
   async refreshToken({ clientId, clientSecret, refreshToken, redirectUri }) {
     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();
+      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,
diff --git a/packages/@uppy/companion/lib/server/provider/providerErrors.js b/packages/@uppy/companion/lib/server/provider/providerErrors.js
index 21c3b64..af6e591 100644
--- a/packages/@uppy/companion/lib/server/provider/providerErrors.js
+++ b/packages/@uppy/companion/lib/server/provider/providerErrors.js
@@ -38,7 +38,9 @@ async function withProviderErrorHandling(
       if (isAuthError({ statusCode, body })) {
         knownErr = new ProviderAuthError();
       } else if (isUserFacingError({ statusCode, body })) {
-        knownErr = new ProviderUserError({ message: getErrorMessage({ statusCode, body }) });
+        knownErr = new ProviderUserError({
+          message: getErrorMessage({ statusCode, body }),
+        });
       } else {
         knownErr = new ProviderApiError(getErrorMessage({ statusCode, body }), statusCode);
       }
@@ -55,11 +57,14 @@ async function withGoogleErrorHandling(providerName, tag, fn) {
     fn,
     tag,
     providerName,
-    isAuthError: (response) => (
+    isAuthError: (response) =>
       response.statusCode === 401
-      || (response.statusCode === 400 && response.body?.error === "invalid_grant") // Refresh token has expired or been revoked
-    ),
+      || (response.statusCode === 400 && response.body?.error === "invalid_grant"), // Refresh token has expired or been revoked
     getJsonErrorMessage: (body) => body?.error?.message,
   });
 }
-module.exports = { withProviderErrorHandling, withGoogleErrorHandling, parseHttpError };
+module.exports = {
+  withProviderErrorHandling,
+  withGoogleErrorHandling,
+  parseHttpError,
+};
diff --git a/packages/@uppy/companion/lib/server/provider/unsplash/adapter.js b/packages/@uppy/companion/lib/server/provider/unsplash/adapter.js
index 1f671b9..8393b3b 100644
--- a/packages/@uppy/companion/lib/server/provider/unsplash/adapter.js
+++ b/packages/@uppy/companion/lib/server/provider/unsplash/adapter.js
@@ -64,8 +64,6 @@ module.exports = (body, currentQuery) => {
       author: getAuthor(item),
       size: null,
     })),
-    nextPageQuery: hasNextPage
-      ? getNextPageQuery(currentQuery)
-      : null,
+    nextPageQuery: hasNextPage ? getNextPageQuery(currentQuery) : null,
   };
 };
diff --git a/packages/@uppy/companion/lib/server/provider/unsplash/index.js b/packages/@uppy/companion/lib/server/provider/unsplash/index.js
index 6e0ee58..9aecb88 100644
--- a/packages/@uppy/companion/lib/server/provider/unsplash/index.js
+++ b/packages/@uppy/companion/lib/server/provider/unsplash/index.js
@@ -27,10 +27,9 @@ class Unsplash extends Provider {
       if (query.cursor) {
         qs.page = query.cursor;
       }
-      const response = await (await getClient({ token })).get("search/photos", {
-        searchParams: qs,
-        responseType: "json",
-      }).json();
+      const response = await (await getClient({ token }))
+        .get("search/photos", { searchParams: qs, responseType: "json" })
+        .json();
       return adaptData(response, query);
     });
   }
@@ -43,12 +42,14 @@ class Unsplash extends Provider {
       // 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" });
+      await client.get(attributionUrl, {
+        prefixUrl: "",
+        responseType: "json",
+      });
       // finally, stream on!
       return { stream, size };
     });
   }
-  // eslint-disable-next-line class-methods-use-this
   async #withErrorHandling(tag, fn) {
     // @ts-ignore
     return withProviderErrorHandling({
diff --git a/packages/@uppy/companion/lib/server/provider/webdav/index.js b/packages/@uppy/companion/lib/server/provider/webdav/index.js
index fee0952..eceaccc 100644
--- a/packages/@uppy/companion/lib/server/provider/webdav/index.js
+++ b/packages/@uppy/companion/lib/server/provider/webdav/index.js
@@ -12,7 +12,6 @@ class WebdavProvider extends Provider {
   static get hasSimpleAuth() {
     return true;
   }
-  // eslint-disable-next-line class-methods-use-this
   isAuthenticated({ providerUserSession }) {
     return providerUserSession.webdavUrl != null;
   }
@@ -25,7 +24,7 @@ class WebdavProvider extends Provider {
     // dynamic import because Companion currently uses CommonJS and webdav is shipped as ESM
     // todo implement as regular require as soon as Node 20.17 or 22 is required
     // or as regular import when Companion is ported to ESM
-    const { AuthType } = await import("webdav"); // eslint-disable-line import/no-unresolved
+    const { AuthType } = await import("webdav");
     // Is this an ownCloud or Nextcloud public link URL? e.g. https://example.com/s/kFy9Lek5sm928xP
     // they have specific urls that we can identify
     // todo not sure if this is the right way to support nextcloud and other webdavs
@@ -69,7 +68,10 @@ class WebdavProvider extends Provider {
       throw new Error("invalid webdav url");
     }
     const { protocol } = new URL(url);
-    const HttpAgentClass = getProtectedHttpAgent({ protocol, allowLocalIPs: !allowLocalUrls });
+    const HttpAgentClass = getProtectedHttpAgent({
+      protocol,
+      allowLocalIPs: !allowLocalUrls,
+    });
     // dynamic import because Companion currently uses CommonJS and webdav is shipped as ESM
     // todo implement as regular require as soon as Node 20.17 or 22 is required
     // or as regular import when Companion is ported to ESM
@@ -89,13 +91,13 @@ class WebdavProvider extends Provider {
       const client = await this.getClient({ providerUserSession });
       /** @type {any} */
       const dir = await client.getDirectoryContents(directory || "/");
-      dir.forEach(item => {
+      dir.forEach((item) => {
         const isFolder = item.type === "directory";
         const requestPath = encodeURIComponent(`${directory || ""}/${item.basename}`);
         let modifiedDate;
         try {
           modifiedDate = new Date(item.lastmod).toISOString();
-        } catch (e) {
+        } catch (_e) {
           // ignore invalid date from server
         }
         data.items.push({
@@ -123,13 +125,11 @@ class WebdavProvider extends Provider {
       return { stream, size: stat.size };
     });
   }
-  // eslint-disable-next-line
   async thumbnail({ id, providerUserSession }) {
     // not implementing this because a public thumbnail from webdav will be used instead
     logger.error("call to thumbnail is not implemented", "provider.webdav.thumbnail.error");
     throw new Error("call to thumbnail is not implemented");
   }
-  // eslint-disable-next-line class-methods-use-this
   async withErrorHandling(tag, fn) {
     try {
       return await fn();
diff --git a/packages/@uppy/companion/lib/server/provider/zoom/adapter.js b/packages/@uppy/companion/lib/server/provider/zoom/adapter.js
index d07b152..5b8fd72 100644
--- a/packages/@uppy/companion/lib/server/provider/zoom/adapter.js
+++ b/packages/@uppy/companion/lib/server/provider/zoom/adapter.js
@@ -33,11 +33,14 @@ const getIsFolder = (item) => {
   return !item.file_type;
 };
 const getItemName = (item, userResponse) => {
-  const start = moment.tz(item.start_time || item.recording_start, userResponse.timezone || "UTC")
+  const start = moment
+    .tz(item.start_time || item.recording_start, userResponse.timezone || "UTC")
     .format("YYYY-MM-DD, HH:mm");
   if (item.file_type) {
     const ext = EXT[item.file_type] ? `.${EXT[item.file_type]}` : "";
-    const itemType = item.recording_type ? ` - ${item.recording_type.split("_").join(" ")}` : "";
+    const itemType = item.recording_type
+      ? ` - ${item.recording_type.split("_").join(" ")}`
+      : "";
     return `${item.topic}${itemType} (${start})${ext}`;
   }
   return `${item.topic} (${start})`;
@@ -106,21 +109,26 @@ exports.adaptData = (userResponse, results) => {
   };
   let itemsToProcess = [];
   if (results.meetings) {
-    itemsToProcess = results.meetings
-      .filter(meeting =>
-        meeting.recording_files
-        && meeting.recording_files.some(file => !file.deleted_time && file.status === "completed" && file.download_url)
-      );
+    itemsToProcess = results.meetings.filter((meeting) =>
+      meeting.recording_files?.some((file) =>
+        !file.deleted_time
+        && file.status === "completed"
+        && file.download_url
+      )
+    );
   } else if (results.recording_files) {
     itemsToProcess = results.recording_files
-      .map(item => {
+      .map((item) => {
         return { ...item, topic: results.topic };
       })
-      .filter(file =>
-        file.file_type !== "TIMELINE" && !file.deleted_time && file.status === "completed" && file.download_url
+      .filter((file) =>
+        file.file_type !== "TIMELINE"
+        && !file.deleted_time
+        && file.status === "completed"
+        && file.download_url
       );
   }
-  itemsToProcess.forEach(item => {
+  itemsToProcess.forEach((item) => {
     data.items.push({
       isFolder: getIsFolder(item),
       icon: getIcon(item),
diff --git a/packages/@uppy/companion/lib/server/provider/zoom/index.js b/packages/@uppy/companion/lib/server/provider/zoom/index.js
index 70b6853..c05bc06 100644
--- a/packages/@uppy/companion/lib/server/provider/zoom/index.js
+++ b/packages/@uppy/companion/lib/server/provider/zoom/index.js
@@ -18,12 +18,15 @@ const getClient = async ({ token }) =>
     },
   });
 async function findFile({ client, meetingId, fileId, recordingStart }) {
-  const { recording_files: files } = await client.get(`meetings/${encodeURIComponent(meetingId)}/recordings`, {
-    responseType: "json",
-  }).json();
-  return files.find((
-    file,
-  ) => (fileId === file.id || (file.file_type === fileId && file.recording_start === recordingStart)));
+  const { recording_files: files } = await client
+    .get(`meetings/${encodeURIComponent(meetingId)}/recordings`, {
+      responseType: "json",
+    })
+    .json();
+  return files.find((file) =>
+    fileId === file.id
+    || (file.file_type === fileId && file.recording_start === recordingStart)
+  );
 }
 /**
  * Adapter for API https://marketplace.zoom.us/docs/api-reference/zoom-api
@@ -43,9 +46,11 @@ class Zoom extends Provider {
       const { timezone } = user;
       const userTz = timezone || "UTC";
       if (meetingId) {
-        const recordingInfo = await client.get(`meetings/${encodeURIComponent(meetingId)}/recordings`, {
-          responseType: "json",
-        }).json();
+        const recordingInfo = await client
+          .get(`meetings/${encodeURIComponent(meetingId)}/recordings`, {
+            responseType: "json",
+          })
+          .json();
         return adaptData(user, recordingInfo);
       }
       if (requestedYear) {
@@ -54,7 +59,9 @@ class Zoom extends Provider {
         const monthsToCheck = Array.from({ length: numMonths }, (_, i) => i); // in moment, months are 0-indexed
         // Run each month in parallel:
         const allMeetingsInYear = (await (await pMap).default(monthsToCheck, async (month) => {
-          const startDate = moment.tz({ year: requestedYear, month, day: 1 }, userTz).startOf("month");
+          const startDate = moment
+            .tz({ year: requestedYear, month, day: 1 }, userTz)
+            .startOf("month");
           const endDate = startDate.clone().endOf("month");
           const searchParams = {
             page_size: PAGE_SIZE,
@@ -63,10 +70,12 @@ class Zoom extends Provider {
           };
           const paginatedMeetings = [];
           do {
-            const currentChunkMeetingsInfo = await client.get("users/me/recordings", {
-              searchParams,
-              responseType: "json",
-            }).json();
+            const currentChunkMeetingsInfo = await client
+              .get("users/me/recordings", {
+                searchParams,
+                responseType: "json",
+              })
+              .json();
             paginatedMeetings.push(...(currentChunkMeetingsInfo.meetings ?? []));
             searchParams.next_page_token = currentChunkMeetingsInfo.next_page_token;
           } while (searchParams.next_page_token);
@@ -106,12 +115,20 @@ class Zoom extends Provider {
       // 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 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" });
+      const stream = client.stream.get(`${url}?access_token=${token}`, {
+        prefixUrl: "",
+        responseType: "json",
+      });
       const { size } = await prepareStream(stream);
       return { stream, size };
     });
@@ -120,7 +137,12 @@ class Zoom extends Provider {
     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 });
+      const foundFile = await findFile({
+        client,
+        meetingId,
+        fileId,
+        recordingStart,
+      });
       if (!foundFile) {
         throw new Error("File not found");
       }
@@ -130,11 +152,13 @@ class Zoom extends Provider {
   async logout({ companion, token }) {
     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();
+      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" };
     });
   }
@@ -162,7 +186,6 @@ class Zoom extends Provider {
       return {};
     });
   }
-  // eslint-disable-next-line class-methods-use-this
   async #withErrorHandling(tag, fn) {
     const authErrorCodes = [
       124, // expired token
diff --git a/packages/@uppy/companion/lib/server/redis.js b/packages/@uppy/companion/lib/server/redis.js
index afbb722..99e24b3 100644
--- a/packages/@uppy/companion/lib/server/redis.js
+++ b/packages/@uppy/companion/lib/server/redis.js
@@ -17,7 +17,7 @@ function createClient(redisUrl, redisOptions) {
     } else {
       redisClient = new Redis(redisOptions);
     }
-    redisClient.on("error", err => logger.error("redis error", err.toString()));
+    redisClient.on("error", (err) => logger.error("redis error", err.toString()));
   }
   return redisClient;
 }
diff --git a/packages/@uppy/companion/lib/server/s3-client.js b/packages/@uppy/companion/lib/server/s3-client.js
index 0d55ddc..3be46ae 100644
--- a/packages/@uppy/companion/lib/server/s3-client.js
+++ b/packages/@uppy/companion/lib/server/s3-client.js
@@ -16,7 +16,10 @@ module.exports = (companionOptions, createPresignedPostMode = false) => {
       );
     }
     const rawClientOptions = s3.awsClientOptions;
-    if (rawClientOptions && (rawClientOptions.accessKeyId || rawClientOptions.secretAccessKey)) {
+    if (
+      rawClientOptions
+      && (rawClientOptions.accessKeyId || rawClientOptions.secretAccessKey)
+    ) {
       throw new Error(
         "Found unsupported `providerOptions.s3.awsClientOptions.accessKeyId` or `providerOptions.s3.awsClientOptions.secretAccessKey` configuration. Please use the `providerOptions.s3.key` and `providerOptions.s3.secret` options instead.",
       );
@@ -24,7 +27,9 @@ module.exports = (companionOptions, createPresignedPostMode = false) => {
     let { endpoint } = s3;
     if (typeof endpoint === "string") {
       // TODO: deprecate those replacements in favor of what AWS SDK supports out of the box.
-      endpoint = endpoint.replace(/{service}/, "s3").replace(/{region}/, s3.region);
+      endpoint = endpoint
+        .replace(/{service}/, "s3")
+        .replace(/{region}/, s3.region);
     }
     /** @type {import('@aws-sdk/client-s3').S3ClientConfig} */
     let s3ClientOptions = {
@@ -43,13 +48,15 @@ module.exports = (companionOptions, createPresignedPostMode = false) => {
             endpoint: `https://${s3.bucket}.s3-accelerate.amazonaws.com/`,
           };
         }
-      } else { // normal useAccelerateEndpoint mode
+      } else {
+        // normal useAccelerateEndpoint mode
         s3ClientOptions = {
           ...s3ClientOptions,
           useAccelerateEndpoint: true,
         };
       }
-    } else { // no accelearate, we allow custom s3 endpoint
+    } else {
+      // no accelearate, we allow custom s3 endpoint
       s3ClientOptions = {
         ...s3ClientOptions,
         endpoint,
diff --git a/packages/@uppy/companion/lib/server/socket.js b/packages/@uppy/companion/lib/server/socket.js
index c805ea2..95056f1 100644
--- a/packages/@uppy/companion/lib/server/socket.js
+++ b/packages/@uppy/companion/lib/server/socket.js
@@ -35,21 +35,28 @@ module.exports = (server) => {
     // if the redisClient is available, then we attempt to check the storage
     // if we have any already stored state on the upload.
     if (redisClient) {
-      redisClient.get(`${STORAGE_PREFIX}:${token}`).then((data) => {
-        if (data) {
-          const dataObj = JSON.parse(data.toString());
-          if (dataObj.action) {
-            send(dataObj);
+      redisClient
+        .get(`${STORAGE_PREFIX}:${token}`)
+        .then((data) => {
+          if (data) {
+            const dataObj = JSON.parse(data.toString());
+            if (dataObj.action) {
+              send(dataObj);
+            }
           }
-        }
-      }).catch((err) => logger.error(err, "socket.redis.error", shortenToken(token)));
+        })
+        .catch((err) => logger.error(err, "socket.redis.error", shortenToken(token)));
     }
     emitter().emit(`connection:${token}`);
     emitter().on(token, send);
     ws.on("error", (err) => {
       // https://github.com/websockets/ws/issues/1543
       // https://github.com/websockets/ws/blob/b73b11828d166e9692a9bffe9c01a7e93bab04a8/test/receiver.test.js#L936
-      if (err?.name === "RangeError" && "code" in err && err.code === "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH") {
+      if (
+        err?.name === "RangeError"
+        && "code" in err
+        && err.code === "WS_ERR_UNSUPPORTED_MESSAGE_LENGTH"
+      ) {
         logger.error("WebSocket message too large", "websocket.error", shortenToken(token));
       } else {
         logger.error(err, "websocket.error", shortenToken(token));
diff --git a/packages/@uppy/companion/lib/standalone/helper.js b/packages/@uppy/companion/lib/standalone/helper.js
index 355d5a4..855f4d4 100644
--- a/packages/@uppy/companion/lib/standalone/helper.js
+++ b/packages/@uppy/companion/lib/standalone/helper.js
@@ -47,9 +47,9 @@ function getCorsOrigins() {
       case "*":
         return "*";
       default:
-        return process.env.COMPANION_CLIENT_ORIGINS
-          .split(",")
-          .map((url) => (hasProtocol(url) ? url : `${companionProtocol}://${url}`));
+        return process.env.COMPANION_CLIENT_ORIGINS.split(",").map((url) =>
+          hasProtocol(url) ? url : `${companionProtocol}://${url}`
+        );
     }
   }
   if (process.env.COMPANION_CLIENT_ORIGINS_REGEX) {
@@ -144,7 +144,8 @@ const getConfigFromEnv = () => {
     periodicPingInterval: process.env.COMPANION_PERIODIC_PING_INTERVAL
       ? parseInt(process.env.COMPANION_PERIODIC_PING_INTERVAL, 10)
       : undefined,
-    periodicPingStaticPayload: process.env.COMPANION_PERIODIC_PING_STATIC_JSON_PAYLOAD
+    periodicPingStaticPayload: process.env
+        .COMPANION_PERIODIC_PING_STATIC_JSON_PAYLOAD
       ? JSON.parse(process.env.COMPANION_PERIODIC_PING_STATIC_JSON_PAYLOAD)
       : undefined,
     periodicPingCount: process.env.COMPANION_PERIODIC_PING_COUNT
@@ -178,12 +179,17 @@ const getConfigFromEnv = () => {
     tusDeferredUploadLength: process.env.COMPANION_TUS_DEFERRED_UPLOAD_LENGTH
       ? process.env.COMPANION_TUS_DEFERRED_UPLOAD_LENGTH === "true"
       : true,
-    maxFileSize: process.env.COMPANION_MAX_FILE_SIZE ? parseInt(process.env.COMPANION_MAX_FILE_SIZE, 10) : undefined,
+    maxFileSize: process.env.COMPANION_MAX_FILE_SIZE
+      ? parseInt(process.env.COMPANION_MAX_FILE_SIZE, 10)
+      : undefined,
     maxFilenameLength: process.env.COMPANION_MAX_FILENAME_LENGTH
       ? parseInt(process.env.COMPANION_MAX_FILENAME_LENGTH, 10)
       : 500,
-    chunkSize: process.env.COMPANION_CHUNK_SIZE ? parseInt(process.env.COMPANION_CHUNK_SIZE, 10) : undefined,
-    clientSocketConnectTimeout: process.env.COMPANION_CLIENT_SOCKET_CONNECT_TIMEOUT
+    chunkSize: process.env.COMPANION_CHUNK_SIZE
+      ? parseInt(process.env.COMPANION_CHUNK_SIZE, 10)
+      : undefined,
+    clientSocketConnectTimeout: process.env
+        .COMPANION_CLIENT_SOCKET_CONNECT_TIMEOUT
       ? parseInt(process.env.COMPANION_CLIENT_SOCKET_CONNECT_TIMEOUT, 10)
       : undefined,
     metrics: process.env.COMPANION_HIDE_METRICS !== "true",
diff --git a/packages/@uppy/companion/lib/standalone/index.js b/packages/@uppy/companion/lib/standalone/index.js
index 9589eaa..c28f78d 100644
--- a/packages/@uppy/companion/lib/standalone/index.js
+++ b/packages/@uppy/companion/lib/standalone/index.js
@@ -76,7 +76,9 @@ module.exports = function server(inputCompanionOptions) {
   router.use(morgan("combined"));
   morgan.token("url", (req) => {
     const { query, censored } = censorQuery(req.query);
-    return censored ? `${req.path}?${qs.stringify(query)}` : req.originalUrl || req.url;
+    return censored
+      ? `${req.path}?${qs.stringify(query)}`
+      : req.originalUrl || req.url;
   });
   morgan.token("referrer", (req) => {
     const ref = req.headers.referer || req.headers.referrer;
@@ -89,7 +91,9 @@ module.exports = function server(inputCompanionOptions) {
       }
       const rawQuery = qs.parse(parsed.search.replace("?", ""));
       const { query, censored } = censorQuery(rawQuery);
-      return censored ? `${parsed.href.split("?")[0]}?${qs.stringify(query)}` : parsed.href;
+      return censored
+        ? `${parsed.href.split("?")[0]}?${qs.stringify(query)}`
+        : parsed.href;
     }
     return undefined;
   });
@@ -108,7 +112,8 @@ module.exports = function server(inputCompanionOptions) {
   if (redisClient) {
     sessionOptions.store = new RedisStore({
       client: redisClient,
-      prefix: process.env.COMPANION_REDIS_EXPRESS_SESSION_PREFIX || "companion-session:",
+      prefix: process.env.COMPANION_REDIS_EXPRESS_SESSION_PREFIX
+        || "companion-session:",
     });
   }
   if (process.env.COMPANION_COOKIE_DOMAIN) {
@@ -138,7 +143,10 @@ module.exports = function server(inputCompanionOptions) {
   // correct value for COMPANION_ONEDRIVE_KEY (i.e application ID). If there's a slightest possiblilty
   // that you might have mixed the values for COMPANION_ONEDRIVE_KEY and COMPANION_ONEDRIVE_SECRET,
   // please DO NOT set any value for COMPANION_ONEDRIVE_DOMAIN_VALIDATION
-  if (process.env.COMPANION_ONEDRIVE_DOMAIN_VALIDATION === "true" && process.env.COMPANION_ONEDRIVE_KEY) {
+  if (
+    process.env.COMPANION_ONEDRIVE_DOMAIN_VALIDATION === "true"
+    && process.env.COMPANION_ONEDRIVE_KEY
+  ) {
     router.get("/.well-known/microsoft-identity-association.json", (req, res) => {
       const content = JSON.stringify({
         associatedApplications: [
@@ -147,7 +155,6 @@ module.exports = function server(inputCompanionOptions) {
       });
       res.header("Content-Length", `${Buffer.byteLength(content, "utf8")}`);
       // use writeHead to prevent 'charset' from being appended
-      // eslint-disable-next-line max-len
       // https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-configure-publisher-domain#to-select-a-verified-domain
       res.writeHead(200, { "Content-Type": "application/json" });
       res.write(content);
@@ -166,10 +173,14 @@ module.exports = function server(inputCompanionOptions) {
       } else {
         logger.error(err, "root.error", req.id);
       }
-      res.status(500).json({ message: "Something went wrong", requestId: req.id });
+      res
+        .status(500)
+        .json({ message: "Something went wrong", requestId: req.id });
     } else {
       logger.error(err, "root.error", req.id);
-      res.status(500).json({ message: err.message, error: err, requestId: req.id });
+      res
+        .status(500)
+        .json({ message: err.message, error: err, requestId: req.id });
     }
   });
   return { app, companionOptions };

@Murderlon Murderlon marked this pull request as ready for review June 26, 2025 14:14
@Murderlon Murderlon mentioned this pull request Jun 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant