From 525e249d41085592b4c9d56ee27cb12f6ae6fd65 Mon Sep 17 00:00:00 2001
From: mike12345567 <me@michaeldrury.co.uk>
Date: Thu, 12 Dec 2024 18:14:53 +0000
Subject: [PATCH 01/14] First pass at migrating to AWS SDK v3.

---
 packages/backend-core/package.json            |    5 +-
 .../src/objectStore/buckets/app.ts            |    8 +-
 .../src/objectStore/buckets/global.ts         |    8 +-
 .../src/objectStore/buckets/plugins.ts        |   22 +-
 .../src/objectStore/buckets/tests/app.spec.ts |    8 +-
 .../objectStore/buckets/tests/global.spec.ts  |    8 +-
 .../src/objectStore/objectStore.ts            |  177 ++-
 .../backend-core/src/objectStore/utils.ts     |    9 +-
 packages/cli/src/backups/objectStore.ts       |   25 +-
 packages/server/package.json                  |    5 +-
 .../server/src/api/controllers/application.ts |    2 +-
 .../src/api/controllers/static/index.ts       |   26 +-
 .../src/automations/tests/createRow.spec.ts   |   18 +-
 packages/server/src/integrations/dynamodb.ts  |   38 +-
 packages/server/src/integrations/s3.ts        |   57 +-
 .../server/src/integrations/utils/utils.ts    |    2 +-
 .../src/utilities/rowProcessor/index.ts       |   14 +-
 .../src/api/controllers/global/configs.ts     |   46 +-
 yarn.lock                                     | 1143 ++++++++++++++++-
 19 files changed, 1352 insertions(+), 269 deletions(-)

diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json
index 3e1b5f324ba..4339ee0a949 100644
--- a/packages/backend-core/package.json
+++ b/packages/backend-core/package.json
@@ -30,6 +30,9 @@
     "test:watch": "jest --watchAll"
   },
   "dependencies": {
+    "@aws-sdk/client-s3": "3.709.0",
+    "@aws-sdk/lib-storage": "3.709.0",
+    "@aws-sdk/s3-request-presigner": "3.709.0",
     "@budibase/nano": "10.1.5",
     "@budibase/pouchdb-replication-stream": "1.2.11",
     "@budibase/shared-core": "*",
@@ -76,6 +79,7 @@
     "@types/chance": "1.1.3",
     "@types/cookies": "0.7.8",
     "@types/jest": "29.5.5",
+    "@types/koa": "2.13.4",
     "@types/lodash": "4.14.200",
     "@types/node-fetch": "2.6.4",
     "@types/pouchdb": "6.4.2",
@@ -83,7 +87,6 @@
     "@types/semver": "7.3.7",
     "@types/tar-fs": "2.0.1",
     "@types/uuid": "8.3.4",
-    "@types/koa": "2.13.4",
     "chance": "1.1.8",
     "ioredis-mock": "8.9.0",
     "jest": "29.7.0",
diff --git a/packages/backend-core/src/objectStore/buckets/app.ts b/packages/backend-core/src/objectStore/buckets/app.ts
index 43bc965c650..dbf49ca9940 100644
--- a/packages/backend-core/src/objectStore/buckets/app.ts
+++ b/packages/backend-core/src/objectStore/buckets/app.ts
@@ -13,7 +13,7 @@ export function clientLibraryPath(appId: string) {
  * due to issues with the domain we were unable to continue doing this - keeping
  * incase we are able to switch back to CDN path again in future.
  */
-export function clientLibraryCDNUrl(appId: string, version: string) {
+export async function clientLibraryCDNUrl(appId: string, version: string) {
   let file = clientLibraryPath(appId)
   if (env.CLOUDFRONT_CDN) {
     // append app version to bust the cache
@@ -24,7 +24,7 @@ export function clientLibraryCDNUrl(appId: string, version: string) {
     // file is public
     return cloudfront.getUrl(file)
   } else {
-    return objectStore.getPresignedUrl(env.APPS_BUCKET_NAME, file)
+    return await objectStore.getPresignedUrl(env.APPS_BUCKET_NAME, file)
   }
 }
 
@@ -44,10 +44,10 @@ export function clientLibraryUrl(appId: string, version: string) {
   return `/api/assets/client?${qs.encode(qsParams)}`
 }
 
-export function getAppFileUrl(s3Key: string) {
+export async function getAppFileUrl(s3Key: string) {
   if (env.CLOUDFRONT_CDN) {
     return cloudfront.getPresignedUrl(s3Key)
   } else {
-    return objectStore.getPresignedUrl(env.APPS_BUCKET_NAME, s3Key)
+    return await objectStore.getPresignedUrl(env.APPS_BUCKET_NAME, s3Key)
   }
 }
diff --git a/packages/backend-core/src/objectStore/buckets/global.ts b/packages/backend-core/src/objectStore/buckets/global.ts
index 69e201bb988..29c3347b051 100644
--- a/packages/backend-core/src/objectStore/buckets/global.ts
+++ b/packages/backend-core/src/objectStore/buckets/global.ts
@@ -5,7 +5,11 @@ import * as cloudfront from "../cloudfront"
 
 // URLs
 
-export const getGlobalFileUrl = (type: string, name: string, etag?: string) => {
+export const getGlobalFileUrl = async (
+  type: string,
+  name: string,
+  etag?: string
+) => {
   let file = getGlobalFileS3Key(type, name)
   if (env.CLOUDFRONT_CDN) {
     if (etag) {
@@ -13,7 +17,7 @@ export const getGlobalFileUrl = (type: string, name: string, etag?: string) => {
     }
     return cloudfront.getPresignedUrl(file)
   } else {
-    return objectStore.getPresignedUrl(env.GLOBAL_BUCKET_NAME, file)
+    return await objectStore.getPresignedUrl(env.GLOBAL_BUCKET_NAME, file)
   }
 }
 
diff --git a/packages/backend-core/src/objectStore/buckets/plugins.ts b/packages/backend-core/src/objectStore/buckets/plugins.ts
index 02be9345ab5..131f180f48d 100644
--- a/packages/backend-core/src/objectStore/buckets/plugins.ts
+++ b/packages/backend-core/src/objectStore/buckets/plugins.ts
@@ -6,23 +6,25 @@ import { Plugin } from "@budibase/types"
 
 // URLS
 
-export function enrichPluginURLs(plugins?: Plugin[]): Plugin[] {
+export async function enrichPluginURLs(plugins?: Plugin[]): Promise<Plugin[]> {
   if (!plugins || !plugins.length) {
     return []
   }
-  return plugins.map(plugin => {
-    const jsUrl = getPluginJSUrl(plugin)
-    const iconUrl = getPluginIconUrl(plugin)
-    return { ...plugin, jsUrl, iconUrl }
-  })
+  return await Promise.all(
+    plugins.map(async plugin => {
+      const jsUrl = await getPluginJSUrl(plugin)
+      const iconUrl = await getPluginIconUrl(plugin)
+      return { ...plugin, jsUrl, iconUrl }
+    })
+  )
 }
 
-function getPluginJSUrl(plugin: Plugin) {
+async function getPluginJSUrl(plugin: Plugin) {
   const s3Key = getPluginJSKey(plugin)
   return getPluginUrl(s3Key)
 }
 
-function getPluginIconUrl(plugin: Plugin): string | undefined {
+async function getPluginIconUrl(plugin: Plugin) {
   const s3Key = getPluginIconKey(plugin)
   if (!s3Key) {
     return
@@ -30,11 +32,11 @@ function getPluginIconUrl(plugin: Plugin): string | undefined {
   return getPluginUrl(s3Key)
 }
 
-function getPluginUrl(s3Key: string) {
+async function getPluginUrl(s3Key: string) {
   if (env.CLOUDFRONT_CDN) {
     return cloudfront.getPresignedUrl(s3Key)
   } else {
-    return objectStore.getPresignedUrl(env.PLUGIN_BUCKET_NAME, s3Key)
+    return await objectStore.getPresignedUrl(env.PLUGIN_BUCKET_NAME, s3Key)
   }
 }
 
diff --git a/packages/backend-core/src/objectStore/buckets/tests/app.spec.ts b/packages/backend-core/src/objectStore/buckets/tests/app.spec.ts
index 4a132ce54dd..1aeba8f2c24 100644
--- a/packages/backend-core/src/objectStore/buckets/tests/app.spec.ts
+++ b/packages/backend-core/src/objectStore/buckets/tests/app.spec.ts
@@ -109,9 +109,9 @@ describe("app", () => {
         )
       })
 
-      it("gets url with cloudfront + s3", () => {
+      it("gets url with cloudfront + s3", async () => {
         testEnv.withCloudfront()
-        const url = getAppFileUrl()
+        const url = await getAppFileUrl()
         // omit rest of signed params
         expect(
           url.includes("http://cf.example.com/app_123/attachments/image.jpeg?")
@@ -146,8 +146,8 @@ describe("app", () => {
 
       it("gets url with cloudfront + s3", async () => {
         testEnv.withCloudfront()
-        await testEnv.withTenant(() => {
-          const url = getAppFileUrl()
+        await testEnv.withTenant(async () => {
+          const url = await getAppFileUrl()
           // omit rest of signed params
           expect(
             url.includes(
diff --git a/packages/backend-core/src/objectStore/buckets/tests/global.spec.ts b/packages/backend-core/src/objectStore/buckets/tests/global.spec.ts
index 148a4c80bf5..be459a7a232 100644
--- a/packages/backend-core/src/objectStore/buckets/tests/global.spec.ts
+++ b/packages/backend-core/src/objectStore/buckets/tests/global.spec.ts
@@ -24,9 +24,9 @@ describe("global", () => {
         expect(url).toBe("http://s3.example.com/global/settings/logoUrl")
       })
 
-      it("gets url with cloudfront + s3", () => {
+      it("gets url with cloudfront + s3", async () => {
         testEnv.withCloudfront()
-        const url = getGlobalFileUrl()
+        const url = await getGlobalFileUrl()
         // omit rest of signed params
         expect(
           url.includes("http://cf.example.com/settings/logoUrl?etag=etag&")
@@ -59,8 +59,8 @@ describe("global", () => {
 
       it("gets url with cloudfront + s3", async () => {
         testEnv.withCloudfront()
-        await testEnv.withTenant(tenantId => {
-          const url = getGlobalFileUrl()
+        await testEnv.withTenant(async tenantId => {
+          const url = await getGlobalFileUrl()
           // omit rest of signed params
           expect(
             url.includes(
diff --git a/packages/backend-core/src/objectStore/objectStore.ts b/packages/backend-core/src/objectStore/objectStore.ts
index 79875b5e997..6acf2e21aec 100644
--- a/packages/backend-core/src/objectStore/objectStore.ts
+++ b/packages/backend-core/src/objectStore/objectStore.ts
@@ -1,6 +1,15 @@
 const sanitize = require("sanitize-s3-objectkey")
 
-import AWS from "aws-sdk"
+import {
+  HeadObjectCommandOutput,
+  PutObjectCommandInput,
+  S3,
+  S3ClientConfig,
+  GetObjectCommand,
+  _Object as S3Object,
+} from "@aws-sdk/client-s3"
+import { Upload } from "@aws-sdk/lib-storage"
+import { getSignedUrl } from "@aws-sdk/s3-request-presigner"
 import stream, { Readable } from "stream"
 import fetch from "node-fetch"
 import tar from "tar-fs"
@@ -13,7 +22,6 @@ import { bucketTTLConfig, budibaseTempDir } from "./utils"
 import { v4 } from "uuid"
 import { APP_PREFIX, APP_DEV_PREFIX } from "../db"
 import fsp from "fs/promises"
-import { HeadObjectOutput } from "aws-sdk/clients/s3"
 import { ReadableStream } from "stream/web"
 
 const streamPipeline = promisify(stream.pipeline)
@@ -84,26 +92,24 @@ export function sanitizeBucket(input: string) {
  * @constructor
  */
 export function ObjectStore(
-  bucket: string,
   opts: { presigning: boolean } = { presigning: false }
 ) {
-  const config: AWS.S3.ClientConfiguration = {
-    s3ForcePathStyle: true,
-    signatureVersion: "v4",
-    apiVersion: "2006-03-01",
-    accessKeyId: env.MINIO_ACCESS_KEY,
-    secretAccessKey: env.MINIO_SECRET_KEY,
+  const config: S3ClientConfig = {
+    forcePathStyle: true,
+    credentials: {
+      accessKeyId: env.MINIO_ACCESS_KEY!,
+      secretAccessKey: env.MINIO_SECRET_KEY!,
+    },
     region: env.AWS_REGION,
   }
-  if (bucket) {
-    config.params = {
-      Bucket: sanitizeBucket(bucket),
-    }
-  }
 
   // for AWS Credentials using temporary session token
   if (!env.MINIO_ENABLED && env.AWS_SESSION_TOKEN) {
-    config.sessionToken = env.AWS_SESSION_TOKEN
+    config.credentials = {
+      accessKeyId: env.MINIO_ACCESS_KEY!,
+      secretAccessKey: env.MINIO_SECRET_KEY!,
+      sessionToken: env.AWS_SESSION_TOKEN,
+    }
   }
 
   // custom S3 is in use i.e. minio
@@ -119,7 +125,7 @@ export function ObjectStore(
     }
   }
 
-  return new AWS.S3(config)
+  return new S3(config)
 }
 
 /**
@@ -132,7 +138,9 @@ export async function createBucketIfNotExists(
 ): Promise<{ created: boolean; exists: boolean }> {
   bucketName = sanitizeBucket(bucketName)
   try {
-    await client
+    await // The `.promise()` call might be on an JS SDK v2 client API.
+    // If yes, please remove .promise(). If not, remove this comment.
+    client
       .headBucket({
         Bucket: bucketName,
       })
@@ -147,11 +155,13 @@ export async function createBucketIfNotExists(
       return { created: false, exists: true }
     } else if (doesntExist || noAccess) {
       if (doesntExist) {
-        promises[bucketName] = client
-          .createBucket({
-            Bucket: bucketName,
-          })
-          .promise()
+        promises[bucketName] = // The `.promise()` call might be on an JS SDK v2 client API.
+          // If yes, please remove .promise(). If not, remove this comment.
+          client
+            .createBucket({
+              Bucket: bucketName,
+            })
+            .promise()
         await promises[bucketName]
         delete promises[bucketName]
         return { created: true, exists: false }
@@ -180,12 +190,12 @@ export async function upload({
 
   const fileBytes = path ? (await fsp.open(path)).createReadStream() : body
 
-  const objectStore = ObjectStore(bucketName)
+  const objectStore = ObjectStore()
   const bucketCreated = await createBucketIfNotExists(objectStore, bucketName)
 
   if (ttl && bucketCreated.created) {
     let ttlConfig = bucketTTLConfig(bucketName, ttl)
-    await objectStore.putBucketLifecycleConfiguration(ttlConfig).promise()
+    await objectStore.putBucketLifecycleConfiguration(ttlConfig)
   }
 
   let contentType = type
@@ -194,11 +204,12 @@ export async function upload({
       ? CONTENT_TYPE_MAP[extension.toLowerCase()]
       : CONTENT_TYPE_MAP.txt
   }
-  const config: any = {
+  const config: PutObjectCommandInput = {
     // windows file paths need to be converted to forward slashes for s3
+    Bucket: sanitizeBucket(bucketName),
     Key: sanitizeKey(filename),
-    Body: fileBytes,
-    ContentType: contentType,
+    Body: fileBytes as stream.Readable | Buffer,
+    ContentType: contentType!,
   }
   if (metadata && typeof metadata === "object") {
     // remove any nullish keys from the metadata object, as these may be considered invalid
@@ -207,10 +218,15 @@ export async function upload({
         delete metadata[key]
       }
     }
-    config.Metadata = metadata
+    config.Metadata = metadata as Record<string, string>
   }
 
-  return objectStore.upload(config).promise()
+  const upload = new Upload({
+    client: objectStore,
+    params: config,
+  })
+
+  return upload.done()
 }
 
 /**
@@ -229,12 +245,12 @@ export async function streamUpload({
     throw new Error("Stream to upload is invalid/undefined")
   }
   const extension = filename.split(".").pop()
-  const objectStore = ObjectStore(bucketName)
+  const objectStore = ObjectStore()
   const bucketCreated = await createBucketIfNotExists(objectStore, bucketName)
 
   if (ttl && bucketCreated.created) {
     let ttlConfig = bucketTTLConfig(bucketName, ttl)
-    await objectStore.putBucketLifecycleConfiguration(ttlConfig).promise()
+    await objectStore.putBucketLifecycleConfiguration(ttlConfig)
   }
 
   // Set content type for certain known extensions
@@ -267,13 +283,15 @@ export async function streamUpload({
     ...extra,
   }
 
-  const details = await objectStore.upload(params).promise()
-  const headDetails = await objectStore
-    .headObject({
-      Bucket: bucket,
-      Key: objKey,
-    })
-    .promise()
+  const upload = new Upload({
+    client: objectStore,
+    params,
+  })
+  const details = await upload.done()
+  const headDetails = await objectStore.headObject({
+    Bucket: bucket,
+    Key: objKey,
+  })
   return {
     ...details,
     ContentLength: headDetails.ContentLength,
@@ -284,35 +302,42 @@ export async function streamUpload({
  * retrieves the contents of a file from the object store, if it is a known content type it
  * will be converted, otherwise it will be returned as a buffer stream.
  */
-export async function retrieve(bucketName: string, filepath: string) {
-  const objectStore = ObjectStore(bucketName)
+export async function retrieve(
+  bucketName: string,
+  filepath: string
+): Promise<string | stream.Readable> {
+  const objectStore = ObjectStore()
   const params = {
     Bucket: sanitizeBucket(bucketName),
     Key: sanitizeKey(filepath),
   }
-  const response: any = await objectStore.getObject(params).promise()
+  const response = await objectStore.getObject(params)
+  if (!response.Body) {
+    throw new Error("Unable to retrieve object")
+  }
   // currently these are all strings
   if (STRING_CONTENT_TYPES.includes(response.ContentType)) {
-    return response.Body.toString("utf8")
+    return response.Body.toString()
   } else {
-    return response.Body
+    return response.Body as stream.Readable
   }
 }
 
-export async function listAllObjects(bucketName: string, path: string) {
-  const objectStore = ObjectStore(bucketName)
+export async function listAllObjects(
+  bucketName: string,
+  path: string
+): Promise<S3Object[]> {
+  const objectStore = ObjectStore()
   const list = (params: ListParams = {}) => {
-    return objectStore
-      .listObjectsV2({
-        ...params,
-        Bucket: sanitizeBucket(bucketName),
-        Prefix: sanitizeKey(path),
-      })
-      .promise()
+    return objectStore.listObjectsV2({
+      ...params,
+      Bucket: sanitizeBucket(bucketName),
+      Prefix: sanitizeKey(path),
+    })
   }
   let isTruncated = false,
     token,
-    objects: AWS.S3.Types.Object[] = []
+    objects: Object[] = []
   do {
     let params: ListParams = {}
     if (token) {
@@ -331,18 +356,19 @@ export async function listAllObjects(bucketName: string, path: string) {
 /**
  * Generate a presigned url with a default TTL of 1 hour
  */
-export function getPresignedUrl(
+export async function getPresignedUrl(
   bucketName: string,
   key: string,
   durationSeconds = 3600
 ) {
-  const objectStore = ObjectStore(bucketName, { presigning: true })
+  const objectStore = ObjectStore({ presigning: true })
   const params = {
     Bucket: sanitizeBucket(bucketName),
     Key: sanitizeKey(key),
-    Expires: durationSeconds,
   }
-  const url = objectStore.getSignedUrl("getObject", params)
+  const url = await getSignedUrl(objectStore, new GetObjectCommand(params), {
+    expiresIn: durationSeconds,
+  })
 
   if (!env.MINIO_ENABLED) {
     // return the full URL to the client
@@ -366,7 +392,11 @@ export async function retrieveToTmp(bucketName: string, filepath: string) {
   filepath = sanitizeKey(filepath)
   const data = await retrieve(bucketName, filepath)
   const outputPath = join(budibaseTempDir(), v4())
-  fs.writeFileSync(outputPath, data)
+  if (data instanceof stream.Readable) {
+    data.pipe(fs.createWriteStream(outputPath))
+  } else {
+    fs.writeFileSync(outputPath, data)
+  }
   return outputPath
 }
 
@@ -408,17 +438,17 @@ export async function retrieveDirectory(bucketName: string, path: string) {
  * Delete a single file.
  */
 export async function deleteFile(bucketName: string, filepath: string) {
-  const objectStore = ObjectStore(bucketName)
+  const objectStore = ObjectStore()
   await createBucketIfNotExists(objectStore, bucketName)
   const params = {
     Bucket: bucketName,
     Key: sanitizeKey(filepath),
   }
-  return objectStore.deleteObject(params).promise()
+  return objectStore.deleteObject(params)
 }
 
 export async function deleteFiles(bucketName: string, filepaths: string[]) {
-  const objectStore = ObjectStore(bucketName)
+  const objectStore = ObjectStore()
   await createBucketIfNotExists(objectStore, bucketName)
   const params = {
     Bucket: bucketName,
@@ -426,7 +456,7 @@ export async function deleteFiles(bucketName: string, filepaths: string[]) {
       Objects: filepaths.map((path: any) => ({ Key: sanitizeKey(path) })),
     },
   }
-  return objectStore.deleteObjects(params).promise()
+  return objectStore.deleteObjects(params)
 }
 
 /**
@@ -438,13 +468,16 @@ export async function deleteFolder(
 ): Promise<any> {
   bucketName = sanitizeBucket(bucketName)
   folder = sanitizeKey(folder)
-  const client = ObjectStore(bucketName)
+  const client = ObjectStore()
   const listParams = {
     Bucket: bucketName,
     Prefix: folder,
   }
 
-  const existingObjectsResponse = await client.listObjects(listParams).promise()
+  const existingObjectsResponse =
+    await // The `.promise()` call might be on an JS SDK v2 client API.
+    // If yes, please remove .promise(). If not, remove this comment.
+    client.listObjects(listParams)
   if (existingObjectsResponse.Contents?.length === 0) {
     return
   }
@@ -459,7 +492,7 @@ export async function deleteFolder(
     deleteParams.Delete.Objects.push({ Key: content.Key })
   })
 
-  const deleteResponse = await client.deleteObjects(deleteParams).promise()
+  const deleteResponse = await client.deleteObjects(deleteParams)
   // can only empty 1000 items at once
   if (deleteResponse.Deleted?.length === 1000) {
     return deleteFolder(bucketName, folder)
@@ -534,29 +567,33 @@ export async function getReadStream(
 ): Promise<Readable> {
   bucketName = sanitizeBucket(bucketName)
   path = sanitizeKey(path)
-  const client = ObjectStore(bucketName)
+  const client = ObjectStore()
   const params = {
     Bucket: bucketName,
     Key: path,
   }
-  return client.getObject(params).createReadStream()
+  const response = await client.getObject(params)
+  if (!response.Body || !(response.Body instanceof stream.Readable)) {
+    throw new Error("Unable to retrieve stream - invalid response")
+  }
+  return response.Body
 }
 
 export async function getObjectMetadata(
   bucket: string,
   path: string
-): Promise<HeadObjectOutput> {
+): Promise<HeadObjectCommandOutput> {
   bucket = sanitizeBucket(bucket)
   path = sanitizeKey(path)
 
-  const client = ObjectStore(bucket)
+  const client = ObjectStore()
   const params = {
     Bucket: bucket,
     Key: path,
   }
 
   try {
-    return await client.headObject(params).promise()
+    return await client.headObject(params)
   } catch (err: any) {
     throw new Error("Unable to retrieve metadata from object")
   }
diff --git a/packages/backend-core/src/objectStore/utils.ts b/packages/backend-core/src/objectStore/utils.ts
index 30c2fefbf11..2a9dd26e027 100644
--- a/packages/backend-core/src/objectStore/utils.ts
+++ b/packages/backend-core/src/objectStore/utils.ts
@@ -2,7 +2,10 @@ import path, { join } from "path"
 import { tmpdir } from "os"
 import fs from "fs"
 import env from "../environment"
-import { PutBucketLifecycleConfigurationRequest } from "aws-sdk/clients/s3"
+import {
+  LifecycleRule,
+  PutBucketLifecycleConfigurationCommandInput,
+} from "@aws-sdk/client-s3"
 import * as objectStore from "./objectStore"
 import {
   AutomationAttachment,
@@ -43,8 +46,8 @@ export function budibaseTempDir() {
 export const bucketTTLConfig = (
   bucketName: string,
   days: number
-): PutBucketLifecycleConfigurationRequest => {
-  const lifecycleRule = {
+): PutBucketLifecycleConfigurationCommandInput => {
+  const lifecycleRule: LifecycleRule = {
     ID: `${bucketName}-ExpireAfter${days}days`,
     Prefix: "",
     Status: "Enabled",
diff --git a/packages/cli/src/backups/objectStore.ts b/packages/cli/src/backups/objectStore.ts
index 2a24199603b..34e231b87bd 100644
--- a/packages/cli/src/backups/objectStore.ts
+++ b/packages/cli/src/backups/objectStore.ts
@@ -3,6 +3,7 @@ import fs from "fs"
 import { join } from "path"
 import { TEMP_DIR, MINIO_DIR } from "./utils"
 import { progressBar } from "../utils"
+import * as stream from "node:stream"
 
 const {
   ObjectStoreBuckets,
@@ -20,15 +21,21 @@ export async function exportObjects() {
   let fullList: any[] = []
   let errorCount = 0
   for (let bucket of bucketList) {
-    const client = ObjectStore(bucket)
+    const client = ObjectStore()
     try {
-      await client.headBucket().promise()
+      await client.headBucket({
+        Bucket: bucket,
+      })
     } catch (err) {
       errorCount++
       continue
     }
-    const list = (await client.listObjectsV2().promise()) as { Contents: any[] }
-    fullList = fullList.concat(list.Contents.map(el => ({ ...el, bucket })))
+    const list = await client.listObjectsV2({
+      Bucket: bucket,
+    })
+    fullList = fullList.concat(
+      list.Contents?.map(el => ({ ...el, bucket })) || []
+    )
   }
   if (errorCount === bucketList.length) {
     throw new Error("Unable to access MinIO/S3 - check environment config.")
@@ -43,7 +50,13 @@ export async function exportObjects() {
       const dirs = possiblePath.slice(0, possiblePath.length - 1)
       fs.mkdirSync(join(path, object.bucket, ...dirs), { recursive: true })
     }
-    fs.writeFileSync(join(path, object.bucket, ...possiblePath), data)
+    if (data instanceof stream.Readable) {
+      data.pipe(
+        fs.createWriteStream(join(path, object.bucket, ...possiblePath))
+      )
+    } else {
+      fs.writeFileSync(join(path, object.bucket, ...possiblePath), data)
+    }
     bar.update(++count)
   }
   bar.stop()
@@ -60,7 +73,7 @@ export async function importObjects() {
   const bar = progressBar(total)
   let count = 0
   for (let bucket of buckets) {
-    const client = ObjectStore(bucket)
+    const client = ObjectStore()
     await createBucketIfNotExists(client, bucket)
     const files = await uploadDirectory(bucket, join(path, bucket), "/")
     count += files.length
diff --git a/packages/server/package.json b/packages/server/package.json
index 1dd3df1d73b..7431d0ad54a 100644
--- a/packages/server/package.json
+++ b/packages/server/package.json
@@ -50,6 +50,10 @@
   "license": "GPL-3.0",
   "dependencies": {
     "@apidevtools/swagger-parser": "10.0.3",
+    "@aws-sdk/client-dynamodb": "3.709.0",
+    "@aws-sdk/client-s3": "3.709.0",
+    "@aws-sdk/lib-dynamodb": "3.709.0",
+    "@aws-sdk/s3-request-presigner": "3.709.0",
     "@azure/msal-node": "^2.5.1",
     "@budibase/backend-core": "*",
     "@budibase/client": "*",
@@ -70,7 +74,6 @@
     "airtable": "0.12.2",
     "arangojs": "7.2.0",
     "archiver": "7.0.1",
-    "aws-sdk": "2.1692.0",
     "bcrypt": "5.1.0",
     "bcryptjs": "2.4.3",
     "bson": "^6.9.0",
diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts
index d032f14150a..d05f6f2eaae 100644
--- a/packages/server/src/api/controllers/application.ts
+++ b/packages/server/src/api/controllers/application.ts
@@ -225,7 +225,7 @@ export async function fetchAppPackage(
   const license = await licensing.cache.getCachedLicense()
 
   // Enrich plugin URLs
-  application.usedPlugins = objectStore.enrichPluginURLs(
+  application.usedPlugins = await objectStore.enrichPluginURLs(
     application.usedPlugins
   )
 
diff --git a/packages/server/src/api/controllers/static/index.ts b/packages/server/src/api/controllers/static/index.ts
index 0dd5e77c507..8b5c61e8754 100644
--- a/packages/server/src/api/controllers/static/index.ts
+++ b/packages/server/src/api/controllers/static/index.ts
@@ -18,7 +18,8 @@ import {
   objectStore,
   utils,
 } from "@budibase/backend-core"
-import AWS from "aws-sdk"
+import { getSignedUrl } from "@aws-sdk/s3-request-presigner"
+import { PutObjectCommand, S3 } from "@aws-sdk/client-s3"
 import fs from "fs"
 import sdk from "../../../sdk"
 import * as pro from "@budibase/pro"
@@ -128,9 +129,9 @@ export const uploadFile = async function (
       return {
         size: file.size,
         name: file.name,
-        url: objectStore.getAppFileUrl(s3Key),
+        url: await objectStore.getAppFileUrl(s3Key),
         extension,
-        key: response.Key,
+        key: response.Key!,
       }
     })
   )
@@ -210,11 +211,11 @@ export const serveApp = async function (ctx: UserCtx<void, ServeAppResponse>) {
         usedPlugins: plugins,
         favicon:
           branding.faviconUrl !== ""
-            ? objectStore.getGlobalFileUrl("settings", "faviconUrl")
+            ? await objectStore.getGlobalFileUrl("settings", "faviconUrl")
             : "",
         logo:
           config?.logoUrl !== ""
-            ? objectStore.getGlobalFileUrl("settings", "logoUrl")
+            ? await objectStore.getGlobalFileUrl("settings", "logoUrl")
             : "",
         appMigrating: needMigrations,
         nonce: ctx.state.nonce,
@@ -243,7 +244,7 @@ export const serveApp = async function (ctx: UserCtx<void, ServeAppResponse>) {
         metaDescription: branding?.metaDescription || "",
         favicon:
           branding.faviconUrl !== ""
-            ? objectStore.getGlobalFileUrl("settings", "faviconUrl")
+            ? await objectStore.getGlobalFileUrl("settings", "faviconUrl")
             : "",
       })
 
@@ -334,16 +335,17 @@ export const getSignedUploadURL = async function (
       ctx.throw(400, "bucket and key values are required")
     }
     try {
-      const s3 = new AWS.S3({
+      const s3 = new S3({
         region: awsRegion,
         endpoint: datasource?.config?.endpoint || undefined,
-        accessKeyId: datasource?.config?.accessKeyId as string,
-        secretAccessKey: datasource?.config?.secretAccessKey as string,
-        apiVersion: "2006-03-01",
-        signatureVersion: "v4",
+
+        credentials: {
+          accessKeyId: datasource?.config?.accessKeyId as string,
+          secretAccessKey: datasource?.config?.secretAccessKey as string,
+        },
       })
       const params = { Bucket: bucket, Key: key }
-      signedUrl = s3.getSignedUrl("putObject", params)
+      signedUrl = await getSignedUrl(s3, new PutObjectCommand(params))
       if (datasource?.config?.endpoint) {
         publicUrl = `${datasource.config.endpoint}/${bucket}/${key}`
       } else {
diff --git a/packages/server/src/automations/tests/createRow.spec.ts b/packages/server/src/automations/tests/createRow.spec.ts
index bd78de2217a..42b69324e29 100644
--- a/packages/server/src/automations/tests/createRow.spec.ts
+++ b/packages/server/src/automations/tests/createRow.spec.ts
@@ -154,11 +154,12 @@ describe("test the create row action", () => {
     expect(result.steps[1].outputs.row.file_attachment[0]).toHaveProperty("key")
     let s3Key = result.steps[1].outputs.row.file_attachment[0].key
 
-    const client = objectStore.ObjectStore(objectStore.ObjectStoreBuckets.APPS)
+    const client = objectStore.ObjectStore()
 
-    const objectData = await client
-      .headObject({ Bucket: objectStore.ObjectStoreBuckets.APPS, Key: s3Key })
-      .promise()
+    const objectData = await client.headObject({
+      Bucket: objectStore.ObjectStoreBuckets.APPS,
+      Key: s3Key,
+    })
 
     expect(objectData).toBeDefined()
     expect(objectData.ContentLength).toBeGreaterThan(0)
@@ -229,11 +230,12 @@ describe("test the create row action", () => {
     )
     let s3Key = result.steps[1].outputs.row.single_file_attachment.key
 
-    const client = objectStore.ObjectStore(objectStore.ObjectStoreBuckets.APPS)
+    const client = objectStore.ObjectStore()
 
-    const objectData = await client
-      .headObject({ Bucket: objectStore.ObjectStoreBuckets.APPS, Key: s3Key })
-      .promise()
+    const objectData = await client.headObject({
+      Bucket: objectStore.ObjectStoreBuckets.APPS,
+      Key: s3Key,
+    })
 
     expect(objectData).toBeDefined()
     expect(objectData.ContentLength).toBeGreaterThan(0)
diff --git a/packages/server/src/integrations/dynamodb.ts b/packages/server/src/integrations/dynamodb.ts
index 424a3dfce07..96941ebb0eb 100644
--- a/packages/server/src/integrations/dynamodb.ts
+++ b/packages/server/src/integrations/dynamodb.ts
@@ -7,9 +7,15 @@ import {
   ConnectionInfo,
 } from "@budibase/types"
 
-import AWS from "aws-sdk"
+import {
+  DynamoDBDocument,
+  PutCommandInput,
+  GetCommandInput,
+  UpdateCommandInput,
+  DeleteCommandInput,
+} from "@aws-sdk/lib-dynamodb"
+import { DynamoDB } from "@aws-sdk/client-dynamodb"
 import { AWS_REGION } from "../constants"
-import { DocumentClient } from "aws-sdk/clients/dynamodb"
 
 interface DynamoDBConfig {
   region: string
@@ -151,7 +157,7 @@ class DynamoDBIntegration implements IntegrationBase {
       region: config.region || AWS_REGION,
       endpoint: config.endpoint || undefined,
     }
-    this.client = new AWS.DynamoDB.DocumentClient(this.config)
+    this.client = DynamoDBDocument.from(new DynamoDB(this.config))
   }
 
   async testConnection() {
@@ -159,8 +165,8 @@ class DynamoDBIntegration implements IntegrationBase {
       connected: false,
     }
     try {
-      const scanRes = await new AWS.DynamoDB(this.config).listTables().promise()
-      response.connected = !!scanRes.$response
+      const scanRes = await new DynamoDB(this.config).listTables()
+      response.connected = !!scanRes.$metadata
     } catch (e: any) {
       response.error = e.message as string
     }
@@ -169,13 +175,13 @@ class DynamoDBIntegration implements IntegrationBase {
 
   async create(query: {
     table: string
-    json: Omit<DocumentClient.PutItemInput, "TableName">
+    json: Omit<PutCommandInput, "TableName">
   }) {
     const params = {
       TableName: query.table,
       ...query.json,
     }
-    return this.client.put(params).promise()
+    return this.client.put(params)
   }
 
   async read(query: { table: string; json: object; index: null | string }) {
@@ -184,7 +190,7 @@ class DynamoDBIntegration implements IntegrationBase {
       IndexName: query.index ? query.index : undefined,
       ...query.json,
     }
-    const response = await this.client.query(params).promise()
+    const response = await this.client.query(params)
     if (response.Items) {
       return response.Items
     }
@@ -197,7 +203,7 @@ class DynamoDBIntegration implements IntegrationBase {
       IndexName: query.index ? query.index : undefined,
       ...query.json,
     }
-    const response = await this.client.scan(params).promise()
+    const response = await this.client.scan(params)
     if (response.Items) {
       return response.Items
     }
@@ -208,40 +214,40 @@ class DynamoDBIntegration implements IntegrationBase {
     const params = {
       TableName: query.table,
     }
-    return new AWS.DynamoDB(this.config).describeTable(params).promise()
+    return new DynamoDB(this.config).describeTable(params)
   }
 
   async get(query: {
     table: string
-    json: Omit<DocumentClient.GetItemInput, "TableName">
+    json: Omit<GetCommandInput, "TableName">
   }) {
     const params = {
       TableName: query.table,
       ...query.json,
     }
-    return this.client.get(params).promise()
+    return this.client.get(params)
   }
 
   async update(query: {
     table: string
-    json: Omit<DocumentClient.UpdateItemInput, "TableName">
+    json: Omit<UpdateCommandInput, "TableName">
   }) {
     const params = {
       TableName: query.table,
       ...query.json,
     }
-    return this.client.update(params).promise()
+    return this.client.update(params)
   }
 
   async delete(query: {
     table: string
-    json: Omit<DocumentClient.DeleteItemInput, "TableName">
+    json: Omit<DeleteCommandInput, "TableName">
   }) {
     const params = {
       TableName: query.table,
       ...query.json,
     }
-    return this.client.delete(params).promise()
+    return this.client.delete(params)
   }
 }
 
diff --git a/packages/server/src/integrations/s3.ts b/packages/server/src/integrations/s3.ts
index 0b7d7740483..488c22835a8 100644
--- a/packages/server/src/integrations/s3.ts
+++ b/packages/server/src/integrations/s3.ts
@@ -7,8 +7,9 @@ import {
   ConnectionInfo,
 } from "@budibase/types"
 
-import AWS from "aws-sdk"
+import { S3 } from "@aws-sdk/client-s3"
 import csv from "csvtojson"
+import stream from "stream"
 
 interface S3Config {
   region: string
@@ -167,7 +168,7 @@ class S3Integration implements IntegrationBase {
       delete this.config.endpoint
     }
 
-    this.client = new AWS.S3(this.config)
+    this.client = new S3(this.config)
   }
 
   async testConnection() {
@@ -175,7 +176,7 @@ class S3Integration implements IntegrationBase {
       connected: false,
     }
     try {
-      await this.client.listBuckets().promise()
+      await this.client.listBuckets()
       response.connected = true
     } catch (e: any) {
       response.error = e.message as string
@@ -209,7 +210,7 @@ class S3Integration implements IntegrationBase {
         LocationConstraint: query.location,
       }
     }
-    return await this.client.createBucket(params).promise()
+    return await this.client.createBucket(params)
   }
 
   async read(query: {
@@ -220,37 +221,39 @@ class S3Integration implements IntegrationBase {
     maxKeys: number
     prefix: string
   }) {
-    const response = await this.client
-      .listObjects({
-        Bucket: query.bucket,
-        Delimiter: query.delimiter,
-        Marker: query.marker,
-        MaxKeys: query.maxKeys,
-        Prefix: query.prefix,
-      })
-      .promise()
+    const response = await this.client.listObjects({
+      Bucket: query.bucket,
+      Delimiter: query.delimiter,
+      Marker: query.marker,
+      MaxKeys: query.maxKeys,
+      Prefix: query.prefix,
+    })
     return response.Contents
   }
 
   async readCsv(query: { bucket: string; key: string }) {
-    const stream = this.client
-      .getObject({
-        Bucket: query.bucket,
-        Key: query.key,
-      })
-      .createReadStream()
+    const response = await this.client.getObject({
+      Bucket: query.bucket,
+      Key: query.key,
+    })
+
+    const fileStream = response.Body?.transformToWebStream()
+
+    if (!fileStream || !(fileStream instanceof stream.Readable)) {
+      throw new Error("Unable to retrieve CSV - invalid stream")
+    }
 
     let csvError = false
     return new Promise((resolve, reject) => {
-      stream.on("error", (err: Error) => {
+      fileStream.on("error", (err: Error) => {
         reject(err)
       })
       const response = csv()
-        .fromStream(stream)
+        .fromStream(fileStream)
         .on("error", () => {
           csvError = true
         })
-      stream.on("finish", () => {
+      fileStream.on("finish", () => {
         resolve(response)
       })
     }).catch(err => {
@@ -263,12 +266,10 @@ class S3Integration implements IntegrationBase {
   }
 
   async delete(query: { bucket: string; delete: string }) {
-    return await this.client
-      .deleteObjects({
-        Bucket: query.bucket,
-        Delete: JSON.parse(query.delete),
-      })
-      .promise()
+    return await this.client.deleteObjects({
+      Bucket: query.bucket,
+      Delete: JSON.parse(query.delete),
+    })
   }
 }
 
diff --git a/packages/server/src/integrations/utils/utils.ts b/packages/server/src/integrations/utils/utils.ts
index 315a8010e81..db9148ae906 100644
--- a/packages/server/src/integrations/utils/utils.ts
+++ b/packages/server/src/integrations/utils/utils.ts
@@ -430,7 +430,7 @@ export async function handleFileResponse(
         size = details.ContentLength
       }
     }
-    presignedUrl = objectStore.getPresignedUrl(bucket, key)
+    presignedUrl = await objectStore.getPresignedUrl(bucket, key)
     return {
       data: {
         size,
diff --git a/packages/server/src/utilities/rowProcessor/index.ts b/packages/server/src/utilities/rowProcessor/index.ts
index 14b524fd95a..7c01c54f13b 100644
--- a/packages/server/src/utilities/rowProcessor/index.ts
+++ b/packages/server/src/utilities/rowProcessor/index.ts
@@ -359,9 +359,9 @@ export async function coreOutputProcessing(
         if (row[property] == null) {
           continue
         }
-        const process = (attachment: RowAttachment) => {
+        const process = async (attachment: RowAttachment) => {
           if (!attachment.url && attachment.key) {
-            attachment.url = objectStore.getAppFileUrl(attachment.key)
+            attachment.url = await objectStore.getAppFileUrl(attachment.key)
           }
           return attachment
         }
@@ -369,11 +369,13 @@ export async function coreOutputProcessing(
           row[property] = JSON.parse(row[property])
         }
         if (Array.isArray(row[property])) {
-          row[property].forEach((attachment: RowAttachment) => {
-            process(attachment)
-          })
+          await Promise.all(
+            row[property].map((attachment: RowAttachment) =>
+              process(attachment)
+            )
+          )
         } else {
-          process(row[property])
+          await process(row[property])
         }
       }
     } else if (
diff --git a/packages/worker/src/api/controllers/global/configs.ts b/packages/worker/src/api/controllers/global/configs.ts
index a10fce35f6d..4ee8dcbb246 100644
--- a/packages/worker/src/api/controllers/global/configs.ts
+++ b/packages/worker/src/api/controllers/global/configs.ts
@@ -322,27 +322,27 @@ export async function save(
   }
 }
 
-function enrichOIDCLogos(oidcLogos: OIDCLogosConfig) {
+async function enrichOIDCLogos(oidcLogos: OIDCLogosConfig) {
   if (!oidcLogos) {
     return
   }
-  oidcLogos.config = Object.keys(oidcLogos.config || {}).reduce(
-    (acc: any, key: string) => {
-      if (!key.endsWith("Etag")) {
-        const etag = oidcLogos.config[`${key}Etag`]
-        const objectStoreUrl = objectStore.getGlobalFileUrl(
-          oidcLogos.type,
-          key,
-          etag
-        )
-        acc[key] = objectStoreUrl
-      } else {
-        acc[key] = oidcLogos.config[key]
-      }
-      return acc
-    },
-    {}
-  )
+  const newConfig: Record<string, string> = {}
+  const keys = Object.keys(oidcLogos.config || {})
+
+  for (const key of keys) {
+    if (!key.endsWith("Etag")) {
+      const etag = oidcLogos.config[`${key}Etag`]
+      const objectStoreUrl = await objectStore.getGlobalFileUrl(
+        oidcLogos.type,
+        key,
+        etag
+      )
+      newConfig[key] = objectStoreUrl
+    } else {
+      newConfig[key] = oidcLogos.config[key]
+    }
+  }
+  oidcLogos.config = newConfig
 }
 
 export async function find(ctx: UserCtx<void, FindConfigResponse>) {
@@ -370,7 +370,7 @@ export async function find(ctx: UserCtx<void, FindConfigResponse>) {
 
 async function handleConfigType(type: ConfigType, config: Config) {
   if (type === ConfigType.OIDC_LOGOS) {
-    enrichOIDCLogos(config)
+    await enrichOIDCLogos(config)
   } else if (type === ConfigType.AI) {
     await handleAIConfig(config)
   }
@@ -396,7 +396,7 @@ export async function publicOidc(ctx: Ctx<void, GetPublicOIDCConfigResponse>) {
     const oidcCustomLogos = await configs.getOIDCLogosDoc()
 
     if (oidcCustomLogos) {
-      enrichOIDCLogos(oidcCustomLogos)
+      await enrichOIDCLogos(oidcCustomLogos)
     }
 
     if (!oidcConfig) {
@@ -427,7 +427,7 @@ export async function publicSettings(
 
     // enrich the logo url - empty url means deleted
     if (config.logoUrl && config.logoUrl !== "") {
-      config.logoUrl = objectStore.getGlobalFileUrl(
+      config.logoUrl = await objectStore.getGlobalFileUrl(
         "settings",
         "logoUrl",
         config.logoUrlEtag
@@ -437,7 +437,7 @@ export async function publicSettings(
     // enrich the favicon url - empty url means deleted
     const faviconUrl =
       branding.faviconUrl && branding.faviconUrl !== ""
-        ? objectStore.getGlobalFileUrl(
+        ? await objectStore.getGlobalFileUrl(
             "settings",
             "faviconUrl",
             branding.faviconUrlEtag
@@ -522,7 +522,7 @@ export async function upload(ctx: UserCtx<void, UploadConfigFileResponse>) {
 
   ctx.body = {
     message: "File has been uploaded and url stored to config.",
-    url: objectStore.getGlobalFileUrl(type, name, etag),
+    url: await objectStore.getGlobalFileUrl(type, name, etag),
   }
 }
 
diff --git a/yarn.lock b/yarn.lock
index aa409fe4a15..657a551f1f9 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -150,6 +150,121 @@
     "@smithy/util-utf8" "^2.0.0"
     tslib "^2.6.2"
 
+"@aws-sdk/client-dynamodb@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/client-dynamodb/-/client-dynamodb-3.709.0.tgz#589cfab9d27f7d0d2056f72e4674315ccd98b6bc"
+  integrity sha512-p/GVuEgfPccFUm5lxr7EPi5gQAsUO4SDdKcIV+v/dNwtH2SXEgnFN0o1TEIJtuVY3BsQyXyR1aMjeQ81O832kw==
+  dependencies:
+    "@aws-crypto/sha256-browser" "5.2.0"
+    "@aws-crypto/sha256-js" "5.2.0"
+    "@aws-sdk/client-sso-oidc" "3.709.0"
+    "@aws-sdk/client-sts" "3.709.0"
+    "@aws-sdk/core" "3.709.0"
+    "@aws-sdk/credential-provider-node" "3.709.0"
+    "@aws-sdk/middleware-endpoint-discovery" "3.709.0"
+    "@aws-sdk/middleware-host-header" "3.709.0"
+    "@aws-sdk/middleware-logger" "3.709.0"
+    "@aws-sdk/middleware-recursion-detection" "3.709.0"
+    "@aws-sdk/middleware-user-agent" "3.709.0"
+    "@aws-sdk/region-config-resolver" "3.709.0"
+    "@aws-sdk/types" "3.709.0"
+    "@aws-sdk/util-endpoints" "3.709.0"
+    "@aws-sdk/util-user-agent-browser" "3.709.0"
+    "@aws-sdk/util-user-agent-node" "3.709.0"
+    "@smithy/config-resolver" "^3.0.13"
+    "@smithy/core" "^2.5.5"
+    "@smithy/fetch-http-handler" "^4.1.2"
+    "@smithy/hash-node" "^3.0.11"
+    "@smithy/invalid-dependency" "^3.0.11"
+    "@smithy/middleware-content-length" "^3.0.13"
+    "@smithy/middleware-endpoint" "^3.2.5"
+    "@smithy/middleware-retry" "^3.0.30"
+    "@smithy/middleware-serde" "^3.0.11"
+    "@smithy/middleware-stack" "^3.0.11"
+    "@smithy/node-config-provider" "^3.1.12"
+    "@smithy/node-http-handler" "^3.3.2"
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/smithy-client" "^3.5.0"
+    "@smithy/types" "^3.7.2"
+    "@smithy/url-parser" "^3.0.11"
+    "@smithy/util-base64" "^3.0.0"
+    "@smithy/util-body-length-browser" "^3.0.0"
+    "@smithy/util-body-length-node" "^3.0.0"
+    "@smithy/util-defaults-mode-browser" "^3.0.30"
+    "@smithy/util-defaults-mode-node" "^3.0.30"
+    "@smithy/util-endpoints" "^2.1.7"
+    "@smithy/util-middleware" "^3.0.11"
+    "@smithy/util-retry" "^3.0.11"
+    "@smithy/util-utf8" "^3.0.0"
+    "@smithy/util-waiter" "^3.2.0"
+    "@types/uuid" "^9.0.1"
+    tslib "^2.6.2"
+    uuid "^9.0.1"
+
+"@aws-sdk/client-s3@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.709.0.tgz#ae27e18c5ced29f0d24857e4a28fb6947cdba3a4"
+  integrity sha512-IvC7coELoQ4YenTdULArVdL5yk6jNRVUALX1aqv9JlPdrXxb3Om6YrM9e7AlSTLxrULTsAe1ubm8i/DmcSY/Ng==
+  dependencies:
+    "@aws-crypto/sha1-browser" "5.2.0"
+    "@aws-crypto/sha256-browser" "5.2.0"
+    "@aws-crypto/sha256-js" "5.2.0"
+    "@aws-sdk/client-sso-oidc" "3.709.0"
+    "@aws-sdk/client-sts" "3.709.0"
+    "@aws-sdk/core" "3.709.0"
+    "@aws-sdk/credential-provider-node" "3.709.0"
+    "@aws-sdk/middleware-bucket-endpoint" "3.709.0"
+    "@aws-sdk/middleware-expect-continue" "3.709.0"
+    "@aws-sdk/middleware-flexible-checksums" "3.709.0"
+    "@aws-sdk/middleware-host-header" "3.709.0"
+    "@aws-sdk/middleware-location-constraint" "3.709.0"
+    "@aws-sdk/middleware-logger" "3.709.0"
+    "@aws-sdk/middleware-recursion-detection" "3.709.0"
+    "@aws-sdk/middleware-sdk-s3" "3.709.0"
+    "@aws-sdk/middleware-ssec" "3.709.0"
+    "@aws-sdk/middleware-user-agent" "3.709.0"
+    "@aws-sdk/region-config-resolver" "3.709.0"
+    "@aws-sdk/signature-v4-multi-region" "3.709.0"
+    "@aws-sdk/types" "3.709.0"
+    "@aws-sdk/util-endpoints" "3.709.0"
+    "@aws-sdk/util-user-agent-browser" "3.709.0"
+    "@aws-sdk/util-user-agent-node" "3.709.0"
+    "@aws-sdk/xml-builder" "3.709.0"
+    "@smithy/config-resolver" "^3.0.13"
+    "@smithy/core" "^2.5.5"
+    "@smithy/eventstream-serde-browser" "^3.0.14"
+    "@smithy/eventstream-serde-config-resolver" "^3.0.11"
+    "@smithy/eventstream-serde-node" "^3.0.13"
+    "@smithy/fetch-http-handler" "^4.1.2"
+    "@smithy/hash-blob-browser" "^3.1.10"
+    "@smithy/hash-node" "^3.0.11"
+    "@smithy/hash-stream-node" "^3.1.10"
+    "@smithy/invalid-dependency" "^3.0.11"
+    "@smithy/md5-js" "^3.0.11"
+    "@smithy/middleware-content-length" "^3.0.13"
+    "@smithy/middleware-endpoint" "^3.2.5"
+    "@smithy/middleware-retry" "^3.0.30"
+    "@smithy/middleware-serde" "^3.0.11"
+    "@smithy/middleware-stack" "^3.0.11"
+    "@smithy/node-config-provider" "^3.1.12"
+    "@smithy/node-http-handler" "^3.3.2"
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/smithy-client" "^3.5.0"
+    "@smithy/types" "^3.7.2"
+    "@smithy/url-parser" "^3.0.11"
+    "@smithy/util-base64" "^3.0.0"
+    "@smithy/util-body-length-browser" "^3.0.0"
+    "@smithy/util-body-length-node" "^3.0.0"
+    "@smithy/util-defaults-mode-browser" "^3.0.30"
+    "@smithy/util-defaults-mode-node" "^3.0.30"
+    "@smithy/util-endpoints" "^2.1.7"
+    "@smithy/util-middleware" "^3.0.11"
+    "@smithy/util-retry" "^3.0.11"
+    "@smithy/util-stream" "^3.3.2"
+    "@smithy/util-utf8" "^3.0.0"
+    "@smithy/util-waiter" "^3.2.0"
+    tslib "^2.6.2"
+
 "@aws-sdk/client-s3@^3.388.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.693.0.tgz#188b621498ffaeb7b1ea5794f61e3e8d9a4bcac2"
@@ -259,6 +374,51 @@
     "@smithy/util-utf8" "^3.0.0"
     tslib "^2.6.2"
 
+"@aws-sdk/client-sso-oidc@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.709.0.tgz#959e4df4070f1d059d8d0cd5b9028d9a46ac7ecf"
+  integrity sha512-1w6egz17QQy661lNCRmZZlqIANEbD6g2VFAQIJbVwSiu7brg+GUns+mT1eLLLHAMQc1sL0Ds8/ybSK2SrgGgIA==
+  dependencies:
+    "@aws-crypto/sha256-browser" "5.2.0"
+    "@aws-crypto/sha256-js" "5.2.0"
+    "@aws-sdk/core" "3.709.0"
+    "@aws-sdk/credential-provider-node" "3.709.0"
+    "@aws-sdk/middleware-host-header" "3.709.0"
+    "@aws-sdk/middleware-logger" "3.709.0"
+    "@aws-sdk/middleware-recursion-detection" "3.709.0"
+    "@aws-sdk/middleware-user-agent" "3.709.0"
+    "@aws-sdk/region-config-resolver" "3.709.0"
+    "@aws-sdk/types" "3.709.0"
+    "@aws-sdk/util-endpoints" "3.709.0"
+    "@aws-sdk/util-user-agent-browser" "3.709.0"
+    "@aws-sdk/util-user-agent-node" "3.709.0"
+    "@smithy/config-resolver" "^3.0.13"
+    "@smithy/core" "^2.5.5"
+    "@smithy/fetch-http-handler" "^4.1.2"
+    "@smithy/hash-node" "^3.0.11"
+    "@smithy/invalid-dependency" "^3.0.11"
+    "@smithy/middleware-content-length" "^3.0.13"
+    "@smithy/middleware-endpoint" "^3.2.5"
+    "@smithy/middleware-retry" "^3.0.30"
+    "@smithy/middleware-serde" "^3.0.11"
+    "@smithy/middleware-stack" "^3.0.11"
+    "@smithy/node-config-provider" "^3.1.12"
+    "@smithy/node-http-handler" "^3.3.2"
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/smithy-client" "^3.5.0"
+    "@smithy/types" "^3.7.2"
+    "@smithy/url-parser" "^3.0.11"
+    "@smithy/util-base64" "^3.0.0"
+    "@smithy/util-body-length-browser" "^3.0.0"
+    "@smithy/util-body-length-node" "^3.0.0"
+    "@smithy/util-defaults-mode-browser" "^3.0.30"
+    "@smithy/util-defaults-mode-node" "^3.0.30"
+    "@smithy/util-endpoints" "^2.1.7"
+    "@smithy/util-middleware" "^3.0.11"
+    "@smithy/util-retry" "^3.0.11"
+    "@smithy/util-utf8" "^3.0.0"
+    tslib "^2.6.2"
+
 "@aws-sdk/client-sso@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.693.0.tgz#9cd5e07e57013b8c7980512810d775d7b6f67e36"
@@ -303,6 +463,50 @@
     "@smithy/util-utf8" "^3.0.0"
     tslib "^2.6.2"
 
+"@aws-sdk/client-sso@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.709.0.tgz#b5b29161e07af6f82afd7a6e750c09b0158d19e3"
+  integrity sha512-Qxeo8cN0jNy6Wnbqq4wucffAGJM6sJjofoTgNtPA6cC7sPYx7aYC6OAAAo6NaMRY+WywOKdS9Wgjx2QYRxKx7w==
+  dependencies:
+    "@aws-crypto/sha256-browser" "5.2.0"
+    "@aws-crypto/sha256-js" "5.2.0"
+    "@aws-sdk/core" "3.709.0"
+    "@aws-sdk/middleware-host-header" "3.709.0"
+    "@aws-sdk/middleware-logger" "3.709.0"
+    "@aws-sdk/middleware-recursion-detection" "3.709.0"
+    "@aws-sdk/middleware-user-agent" "3.709.0"
+    "@aws-sdk/region-config-resolver" "3.709.0"
+    "@aws-sdk/types" "3.709.0"
+    "@aws-sdk/util-endpoints" "3.709.0"
+    "@aws-sdk/util-user-agent-browser" "3.709.0"
+    "@aws-sdk/util-user-agent-node" "3.709.0"
+    "@smithy/config-resolver" "^3.0.13"
+    "@smithy/core" "^2.5.5"
+    "@smithy/fetch-http-handler" "^4.1.2"
+    "@smithy/hash-node" "^3.0.11"
+    "@smithy/invalid-dependency" "^3.0.11"
+    "@smithy/middleware-content-length" "^3.0.13"
+    "@smithy/middleware-endpoint" "^3.2.5"
+    "@smithy/middleware-retry" "^3.0.30"
+    "@smithy/middleware-serde" "^3.0.11"
+    "@smithy/middleware-stack" "^3.0.11"
+    "@smithy/node-config-provider" "^3.1.12"
+    "@smithy/node-http-handler" "^3.3.2"
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/smithy-client" "^3.5.0"
+    "@smithy/types" "^3.7.2"
+    "@smithy/url-parser" "^3.0.11"
+    "@smithy/util-base64" "^3.0.0"
+    "@smithy/util-body-length-browser" "^3.0.0"
+    "@smithy/util-body-length-node" "^3.0.0"
+    "@smithy/util-defaults-mode-browser" "^3.0.30"
+    "@smithy/util-defaults-mode-node" "^3.0.30"
+    "@smithy/util-endpoints" "^2.1.7"
+    "@smithy/util-middleware" "^3.0.11"
+    "@smithy/util-retry" "^3.0.11"
+    "@smithy/util-utf8" "^3.0.0"
+    tslib "^2.6.2"
+
 "@aws-sdk/client-sts@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.693.0.tgz#9e2c418f4850269635632bee4d1a31057c04bcc5"
@@ -349,6 +553,52 @@
     "@smithy/util-utf8" "^3.0.0"
     tslib "^2.6.2"
 
+"@aws-sdk/client-sts@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.709.0.tgz#b9ad3c9c6419d0d149b28cdd6c115cc40c4e7906"
+  integrity sha512-cBAvlPg6yslXNL385UUGFPw+XY+lA9BzioNdIFkMo3fEUlTShogTtiWz4LsyLHoN6LhKojssP9DSmmWKWjCZIw==
+  dependencies:
+    "@aws-crypto/sha256-browser" "5.2.0"
+    "@aws-crypto/sha256-js" "5.2.0"
+    "@aws-sdk/client-sso-oidc" "3.709.0"
+    "@aws-sdk/core" "3.709.0"
+    "@aws-sdk/credential-provider-node" "3.709.0"
+    "@aws-sdk/middleware-host-header" "3.709.0"
+    "@aws-sdk/middleware-logger" "3.709.0"
+    "@aws-sdk/middleware-recursion-detection" "3.709.0"
+    "@aws-sdk/middleware-user-agent" "3.709.0"
+    "@aws-sdk/region-config-resolver" "3.709.0"
+    "@aws-sdk/types" "3.709.0"
+    "@aws-sdk/util-endpoints" "3.709.0"
+    "@aws-sdk/util-user-agent-browser" "3.709.0"
+    "@aws-sdk/util-user-agent-node" "3.709.0"
+    "@smithy/config-resolver" "^3.0.13"
+    "@smithy/core" "^2.5.5"
+    "@smithy/fetch-http-handler" "^4.1.2"
+    "@smithy/hash-node" "^3.0.11"
+    "@smithy/invalid-dependency" "^3.0.11"
+    "@smithy/middleware-content-length" "^3.0.13"
+    "@smithy/middleware-endpoint" "^3.2.5"
+    "@smithy/middleware-retry" "^3.0.30"
+    "@smithy/middleware-serde" "^3.0.11"
+    "@smithy/middleware-stack" "^3.0.11"
+    "@smithy/node-config-provider" "^3.1.12"
+    "@smithy/node-http-handler" "^3.3.2"
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/smithy-client" "^3.5.0"
+    "@smithy/types" "^3.7.2"
+    "@smithy/url-parser" "^3.0.11"
+    "@smithy/util-base64" "^3.0.0"
+    "@smithy/util-body-length-browser" "^3.0.0"
+    "@smithy/util-body-length-node" "^3.0.0"
+    "@smithy/util-defaults-mode-browser" "^3.0.30"
+    "@smithy/util-defaults-mode-node" "^3.0.30"
+    "@smithy/util-endpoints" "^2.1.7"
+    "@smithy/util-middleware" "^3.0.11"
+    "@smithy/util-retry" "^3.0.11"
+    "@smithy/util-utf8" "^3.0.0"
+    tslib "^2.6.2"
+
 "@aws-sdk/core@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.693.0.tgz#437969dd740895a59863d737bad14646bc2e1725"
@@ -366,6 +616,23 @@
     fast-xml-parser "4.4.1"
     tslib "^2.6.2"
 
+"@aws-sdk/core@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.709.0.tgz#d2b3d5b90f6614e3afc109ebdcaaedbb54c2d68b"
+  integrity sha512-7kuSpzdOTAE026j85wq/fN9UDZ70n0OHw81vFqMWwlEFtm5IQ/MRCLKcC4HkXxTdfy1PqFlmoXxWqeBa15tujw==
+  dependencies:
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/core" "^2.5.5"
+    "@smithy/node-config-provider" "^3.1.12"
+    "@smithy/property-provider" "^3.1.11"
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/signature-v4" "^4.2.4"
+    "@smithy/smithy-client" "^3.5.0"
+    "@smithy/types" "^3.7.2"
+    "@smithy/util-middleware" "^3.0.11"
+    fast-xml-parser "4.4.1"
+    tslib "^2.6.2"
+
 "@aws-sdk/credential-provider-env@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.693.0.tgz#f97feed9809fe2800216943470015fdaaba47c4f"
@@ -377,6 +644,17 @@
     "@smithy/types" "^3.7.0"
     tslib "^2.6.2"
 
+"@aws-sdk/credential-provider-env@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.709.0.tgz#a7f75375d8a413f9ab2bc42f743b943da6d3362d"
+  integrity sha512-ZMAp9LSikvHDFVa84dKpQmow6wsg956Um20cKuioPpX2GGreJFur7oduD+tRJT6FtIOHn+64YH+0MwiXLhsaIQ==
+  dependencies:
+    "@aws-sdk/core" "3.709.0"
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/property-provider" "^3.1.11"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@aws-sdk/credential-provider-http@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.693.0.tgz#5caad0ac47eded1edeb63f907280580ccfaadba3"
@@ -393,6 +671,22 @@
     "@smithy/util-stream" "^3.3.0"
     tslib "^2.6.2"
 
+"@aws-sdk/credential-provider-http@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.709.0.tgz#a378cbcc4cf373cc277944f1e84e9952f3884f5d"
+  integrity sha512-lIS7XLwCOyJnLD70f+VIRr8DNV1HPQe9oN6aguYrhoczqz7vDiVZLe3lh714cJqq9rdxzFypK5DqKHmcscMEPQ==
+  dependencies:
+    "@aws-sdk/core" "3.709.0"
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/fetch-http-handler" "^4.1.2"
+    "@smithy/node-http-handler" "^3.3.2"
+    "@smithy/property-provider" "^3.1.11"
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/smithy-client" "^3.5.0"
+    "@smithy/types" "^3.7.2"
+    "@smithy/util-stream" "^3.3.2"
+    tslib "^2.6.2"
+
 "@aws-sdk/credential-provider-ini@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.693.0.tgz#b4557ac1092657660a15c9bd55e17c27f79ec621"
@@ -411,6 +705,24 @@
     "@smithy/types" "^3.7.0"
     tslib "^2.6.2"
 
+"@aws-sdk/credential-provider-ini@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.709.0.tgz#b01c68d98ce4cc48f79405234e32a9de2f943ea1"
+  integrity sha512-qCF8IIGcPoUp+Ib3ANhbF5gElxFd+kIrtv2/1tKdvhudMANstQbMiWV0LTH47ZZR6c3as4iSrm09NZnpEoD/pA==
+  dependencies:
+    "@aws-sdk/core" "3.709.0"
+    "@aws-sdk/credential-provider-env" "3.709.0"
+    "@aws-sdk/credential-provider-http" "3.709.0"
+    "@aws-sdk/credential-provider-process" "3.709.0"
+    "@aws-sdk/credential-provider-sso" "3.709.0"
+    "@aws-sdk/credential-provider-web-identity" "3.709.0"
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/credential-provider-imds" "^3.2.8"
+    "@smithy/property-provider" "^3.1.11"
+    "@smithy/shared-ini-file-loader" "^3.1.12"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@aws-sdk/credential-provider-node@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.693.0.tgz#c5ceac64a69304d5b4db3fd68473480cafddb4a9"
@@ -429,6 +741,24 @@
     "@smithy/types" "^3.7.0"
     tslib "^2.6.2"
 
+"@aws-sdk/credential-provider-node@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.709.0.tgz#270a31aae394e6c8fe7d3fdd0b92e7c3a863b933"
+  integrity sha512-4HRX9KYWPSjO5O/Vg03YAsebKpvTjTvpK1n7zHYBmlLMBLxUrVsL1nNKKC5p2/7OW3RL8XR1ki3QkoV7kGRxUQ==
+  dependencies:
+    "@aws-sdk/credential-provider-env" "3.709.0"
+    "@aws-sdk/credential-provider-http" "3.709.0"
+    "@aws-sdk/credential-provider-ini" "3.709.0"
+    "@aws-sdk/credential-provider-process" "3.709.0"
+    "@aws-sdk/credential-provider-sso" "3.709.0"
+    "@aws-sdk/credential-provider-web-identity" "3.709.0"
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/credential-provider-imds" "^3.2.8"
+    "@smithy/property-provider" "^3.1.11"
+    "@smithy/shared-ini-file-loader" "^3.1.12"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@aws-sdk/credential-provider-process@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.693.0.tgz#e84e945f1a148f06ff697608d5309e73347e5aa9"
@@ -441,6 +771,18 @@
     "@smithy/types" "^3.7.0"
     tslib "^2.6.2"
 
+"@aws-sdk/credential-provider-process@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.709.0.tgz#2521f810590f0874c54cc842d3d56f455a728325"
+  integrity sha512-IAC+jPlGQII6jhIylHOwh3RgSobqlgL59nw2qYTURr8hMCI0Z1p5y2ee646HTVt4WeCYyzUAXfxr6YI/Vitv+Q==
+  dependencies:
+    "@aws-sdk/core" "3.709.0"
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/property-provider" "^3.1.11"
+    "@smithy/shared-ini-file-loader" "^3.1.12"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@aws-sdk/credential-provider-sso@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.693.0.tgz#72767389f533d9d17a14af63daaafcc8368ab43a"
@@ -455,6 +797,20 @@
     "@smithy/types" "^3.7.0"
     tslib "^2.6.2"
 
+"@aws-sdk/credential-provider-sso@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.709.0.tgz#f0cb855eed86748ff0c9afa06b3a234fb04b3206"
+  integrity sha512-rYdTDOxazS2GdGScelsRK5CAkktRLCCdRjlwXaxrcW57j749hEqxcF5uTv9RD6WBwInfedcSywErNZB+hylQlg==
+  dependencies:
+    "@aws-sdk/client-sso" "3.709.0"
+    "@aws-sdk/core" "3.709.0"
+    "@aws-sdk/token-providers" "3.709.0"
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/property-provider" "^3.1.11"
+    "@smithy/shared-ini-file-loader" "^3.1.12"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@aws-sdk/credential-provider-web-identity@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.693.0.tgz#b6133b5ef9d3582e36e02e9c66766714ff672a11"
@@ -466,6 +822,50 @@
     "@smithy/types" "^3.7.0"
     tslib "^2.6.2"
 
+"@aws-sdk/credential-provider-web-identity@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.709.0.tgz#c2b03541cb57ae4c7d6abdca98f99a6a56833ea6"
+  integrity sha512-2lbDfE0IQ6gma/7BB2JpkjW5G0wGe4AS0x80oybYAYYviJmUtIR3Cn2pXun6bnAWElt4wYKl4su7oC36rs5rNA==
+  dependencies:
+    "@aws-sdk/core" "3.709.0"
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/property-provider" "^3.1.11"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
+"@aws-sdk/endpoint-cache@3.693.0":
+  version "3.693.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/endpoint-cache/-/endpoint-cache-3.693.0.tgz#4b3f0bbc16dc2907e1b977e3d8ddfc7ba008fd12"
+  integrity sha512-/zK0ZZncBf5FbTfo8rJMcQIXXk4Ibhe5zEMiwFNivVPR2uNC0+oqfwXz7vjxwY0t6BPE3Bs4h9uFEz4xuGCY6w==
+  dependencies:
+    mnemonist "0.38.3"
+    tslib "^2.6.2"
+
+"@aws-sdk/lib-dynamodb@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.709.0.tgz#fd90b76bce67af1a3079524710f7bc19647829ad"
+  integrity sha512-piIyvQ1DhoUEosKmjGnMxLClUb9tv5rPPZfgh9J4MmSygsYbE9HvC3tstje0xUudVZjsmzZpNyibl/n0LA0gdQ==
+  dependencies:
+    "@aws-sdk/core" "3.709.0"
+    "@aws-sdk/util-dynamodb" "3.709.0"
+    "@smithy/core" "^2.5.5"
+    "@smithy/smithy-client" "^3.5.0"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
+"@aws-sdk/lib-storage@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/lib-storage/-/lib-storage-3.709.0.tgz#2b12e558880418c3348cbd8f1e4e7f8db424b7b7"
+  integrity sha512-TnP+QSsWdiaQYS5HuB3n9H947z49m6qSEv5fth4L9xinBldLepLyyF+cua3/GlagkWqpxcATISgR9pE1PB0mhQ==
+  dependencies:
+    "@smithy/abort-controller" "^3.1.9"
+    "@smithy/middleware-endpoint" "^3.2.5"
+    "@smithy/smithy-client" "^3.5.0"
+    buffer "5.6.0"
+    events "3.3.0"
+    stream-browserify "3.0.0"
+    tslib "^2.6.2"
+
 "@aws-sdk/middleware-bucket-endpoint@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.693.0.tgz#e4823a40935d34f5e58a4fbc830d8ff92e44fc99"
@@ -479,6 +879,31 @@
     "@smithy/util-config-provider" "^3.0.0"
     tslib "^2.6.2"
 
+"@aws-sdk/middleware-bucket-endpoint@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.709.0.tgz#a69bdebfebb7b5b174d3a396f2361f5025d168f4"
+  integrity sha512-03+tJOd7KIZOiqWH7Z8BOfQIWkKJgjcpKOJKZ6FR2KjWGUOE1G+bo11wF4UuHQ0RmpKnApt+pQghZmSnE7WEeg==
+  dependencies:
+    "@aws-sdk/types" "3.709.0"
+    "@aws-sdk/util-arn-parser" "3.693.0"
+    "@smithy/node-config-provider" "^3.1.12"
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/types" "^3.7.2"
+    "@smithy/util-config-provider" "^3.0.0"
+    tslib "^2.6.2"
+
+"@aws-sdk/middleware-endpoint-discovery@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.709.0.tgz#d5866603f2515f0da2c84ead99cd25b806d8ee5b"
+  integrity sha512-6CSHoAy3sVBJdeGiBpoRqVHpqLPqv5QuDxKsEMHoGdbGATmffyn2whTFfo5hfRYsN9WPz/XxUX2iynqQCnlrzw==
+  dependencies:
+    "@aws-sdk/endpoint-cache" "3.693.0"
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/node-config-provider" "^3.1.12"
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@aws-sdk/middleware-expect-continue@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.693.0.tgz#d8696cee9ebea1d973d8daf872fd913b41d62cf0"
@@ -489,6 +914,16 @@
     "@smithy/types" "^3.7.0"
     tslib "^2.6.2"
 
+"@aws-sdk/middleware-expect-continue@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.709.0.tgz#a7fec776da9de32e15088badfc09d69118f5d5ab"
+  integrity sha512-Tbl/DFvE4rHl8lMb9IzetwK4tf5R3VeHZkvEXQalsWoK0tbEQ8kXWi7wAYO4qbE7bFVvaxKX+irjJjTxf3BrCQ==
+  dependencies:
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@aws-sdk/middleware-flexible-checksums@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.693.0.tgz#80f07802d98ff33a6899a09c59cf51aab426aaac"
@@ -508,6 +943,25 @@
     "@smithy/util-utf8" "^3.0.0"
     tslib "^2.6.2"
 
+"@aws-sdk/middleware-flexible-checksums@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.709.0.tgz#f0fb543c2db724cb43bae215ff0aea942d06a967"
+  integrity sha512-wbYm9tkyCaqMeU82yjaXw7V5BxCSlSLNupENW63LC7Fvyo/aQzj6LjSMHcBpR2QwjBEhXCtF47L7aQ8SPTNhdw==
+  dependencies:
+    "@aws-crypto/crc32" "5.2.0"
+    "@aws-crypto/crc32c" "5.2.0"
+    "@aws-crypto/util" "5.2.0"
+    "@aws-sdk/core" "3.709.0"
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/is-array-buffer" "^3.0.0"
+    "@smithy/node-config-provider" "^3.1.12"
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/types" "^3.7.2"
+    "@smithy/util-middleware" "^3.0.11"
+    "@smithy/util-stream" "^3.3.2"
+    "@smithy/util-utf8" "^3.0.0"
+    tslib "^2.6.2"
+
 "@aws-sdk/middleware-host-header@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.693.0.tgz#69322909c0792df1e6be7c7fb5e2b6f76090a55c"
@@ -518,6 +972,16 @@
     "@smithy/types" "^3.7.0"
     tslib "^2.6.2"
 
+"@aws-sdk/middleware-host-header@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.709.0.tgz#f44f5c62f9bd7e5a443603fed68143d2d9725219"
+  integrity sha512-8gQYCYAaIw4lOCd5WYdf15Y/61MgRsAnrb2eiTl+icMlUOOzl8aOl5iDwm/Idp0oHZTflwxM4XSvGXO83PRWcw==
+  dependencies:
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@aws-sdk/middleware-location-constraint@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.693.0.tgz#1856eaaad64d41d1f8fa53ced58a6c7cf5eccc6e"
@@ -527,6 +991,15 @@
     "@smithy/types" "^3.7.0"
     tslib "^2.6.2"
 
+"@aws-sdk/middleware-location-constraint@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.709.0.tgz#4437d3d3cfbbdfca60664b1f237d600b94fd06a5"
+  integrity sha512-5YQWPXfZq7OE0jB2G0PP8K10GBod/YPJXb+1CfJS6FbQaglRoIm8KZmVEvJNnptSKyGtE62veeCcCQcfAUfFig==
+  dependencies:
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@aws-sdk/middleware-logger@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.693.0.tgz#fc10294e6963f8e5d58ba1ededd891e999f544a9"
@@ -536,6 +1009,15 @@
     "@smithy/types" "^3.7.0"
     tslib "^2.6.2"
 
+"@aws-sdk/middleware-logger@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.709.0.tgz#b9a0b016b7ae09cb502cc4faf45964d4b5745824"
+  integrity sha512-jDoGSccXv9zebnpUoisjWd5u5ZPIalrmm6TjvPzZ8UqzQt3Beiz0tnQwmxQD6KRc7ADweWP5Ntiqzbw9xpVajg==
+  dependencies:
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@aws-sdk/middleware-recursion-detection@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.693.0.tgz#88a8157293775e7116707da26501da4b5e042f51"
@@ -546,6 +1028,16 @@
     "@smithy/types" "^3.7.0"
     tslib "^2.6.2"
 
+"@aws-sdk/middleware-recursion-detection@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.709.0.tgz#d7dc253d4858d496caeb12dd6cddd87b250fb98b"
+  integrity sha512-PObL/wLr4lkfbQ0yXUWaoCWu/jcwfwZzCjsUiXW/H6hW9b/00enZxmx7OhtJYaR6xmh/Lcx5wbhIoDCbzdv0tw==
+  dependencies:
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@aws-sdk/middleware-sdk-s3@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.693.0.tgz#e0850854d5079f372786b2ccfe85729caa7a49d8"
@@ -566,6 +1058,26 @@
     "@smithy/util-utf8" "^3.0.0"
     tslib "^2.6.2"
 
+"@aws-sdk/middleware-sdk-s3@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.709.0.tgz#b6f22c77e64760869eb06255af58376f879742b2"
+  integrity sha512-FwtOG9t9xsLoLOQZ6qAdsWOjx9dsO6t28IjIDV1l6Ixiu2oC0Yks7goONjJUH0IDE4pDDDGzmuq0sn1XtHhheA==
+  dependencies:
+    "@aws-sdk/core" "3.709.0"
+    "@aws-sdk/types" "3.709.0"
+    "@aws-sdk/util-arn-parser" "3.693.0"
+    "@smithy/core" "^2.5.5"
+    "@smithy/node-config-provider" "^3.1.12"
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/signature-v4" "^4.2.4"
+    "@smithy/smithy-client" "^3.5.0"
+    "@smithy/types" "^3.7.2"
+    "@smithy/util-config-provider" "^3.0.0"
+    "@smithy/util-middleware" "^3.0.11"
+    "@smithy/util-stream" "^3.3.2"
+    "@smithy/util-utf8" "^3.0.0"
+    tslib "^2.6.2"
+
 "@aws-sdk/middleware-ssec@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.693.0.tgz#2ff779147d188090b3a6cda3ed12ca4085220a73"
@@ -575,6 +1087,15 @@
     "@smithy/types" "^3.7.0"
     tslib "^2.6.2"
 
+"@aws-sdk/middleware-ssec@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.709.0.tgz#bbf5253cdce45ed2759a108fd924fff4b8e049d5"
+  integrity sha512-2muiLe7YkmlwZp2SKz+goZrDThGfRq3o0FcJF3Puc0XGmcEPEDjih537mCoTrGgcXNFlBc7YChd84r3t72ySaQ==
+  dependencies:
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@aws-sdk/middleware-user-agent@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.693.0.tgz#4b55cfab3fc7e671b08e1ea63a98e45a1e13e6a5"
@@ -588,6 +1109,19 @@
     "@smithy/types" "^3.7.0"
     tslib "^2.6.2"
 
+"@aws-sdk/middleware-user-agent@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.709.0.tgz#2a467f14b3f4a9270bcdfde32e3d4e38701aaafe"
+  integrity sha512-ooc9ZJvgkjPhi9q05XwSfNTXkEBEIfL4hleo5rQBKwHG3aTHvwOM7LLzhdX56QZVa6sorPBp6fwULuRDSqiQHw==
+  dependencies:
+    "@aws-sdk/core" "3.709.0"
+    "@aws-sdk/types" "3.709.0"
+    "@aws-sdk/util-endpoints" "3.709.0"
+    "@smithy/core" "^2.5.5"
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@aws-sdk/node-http-handler@^3.374.0":
   version "3.374.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/node-http-handler/-/node-http-handler-3.374.0.tgz#8cd58b4d9814713e26034c12eabc119c113a5bc4"
@@ -608,6 +1142,32 @@
     "@smithy/util-middleware" "^3.0.9"
     tslib "^2.6.2"
 
+"@aws-sdk/region-config-resolver@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.709.0.tgz#64547b333842e5804e1793e4d6d29578c0b34a68"
+  integrity sha512-/NoCAMEVKAg3kBKOrNtgOfL+ECt6nrl+L7q2SyYmrcY4tVCmwuECVqewQaHc03fTnJijfKLccw0Fj+6wOCnB6w==
+  dependencies:
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/node-config-provider" "^3.1.12"
+    "@smithy/types" "^3.7.2"
+    "@smithy/util-config-provider" "^3.0.0"
+    "@smithy/util-middleware" "^3.0.11"
+    tslib "^2.6.2"
+
+"@aws-sdk/s3-request-presigner@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.709.0.tgz#d3c9d881158bdece69863be318d49e9d7d2c512f"
+  integrity sha512-WYmXU2ur/z6xBX9TcGwSWlSiS8rxrRl2f1HJXZzgSu9FWZ7fJssoQGvrk/w64wjNq1tEzKbd1iWXw9s9qexT3g==
+  dependencies:
+    "@aws-sdk/signature-v4-multi-region" "3.709.0"
+    "@aws-sdk/types" "3.709.0"
+    "@aws-sdk/util-format-url" "3.709.0"
+    "@smithy/middleware-endpoint" "^3.2.5"
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/smithy-client" "^3.5.0"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@aws-sdk/signature-v4-multi-region@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.693.0.tgz#85bd90bb78be1a98d5a5ca41033cb0703146c2c4"
@@ -620,6 +1180,18 @@
     "@smithy/types" "^3.7.0"
     tslib "^2.6.2"
 
+"@aws-sdk/signature-v4-multi-region@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.709.0.tgz#0c6f9d3e2978158163b63a4085356616237223c9"
+  integrity sha512-m0vhJEy6SLbjL11K9cHzX/ZhCIj//1GkTbYk2d4tTQFSuPyJEkjmoeHk9dYm2mJy0wH48j29OJadI1JUsR5bOw==
+  dependencies:
+    "@aws-sdk/middleware-sdk-s3" "3.709.0"
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/signature-v4" "^4.2.4"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@aws-sdk/token-providers@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.693.0.tgz#5ce7d6aa7a3437d4abdc0dca1be47f5158d15c85"
@@ -631,6 +1203,17 @@
     "@smithy/types" "^3.7.0"
     tslib "^2.6.2"
 
+"@aws-sdk/token-providers@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.709.0.tgz#56305ab187660a711fd172c329dc953ca754fa80"
+  integrity sha512-q5Ar6k71nci43IbULFgC8a89d/3EHpmd7HvBzqVGRcHnoPwh8eZDBfbBXKH83NGwcS1qPSRYiDbVfeWPm4/1jA==
+  dependencies:
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/property-provider" "^3.1.11"
+    "@smithy/shared-ini-file-loader" "^3.1.12"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@aws-sdk/types@3.692.0", "@aws-sdk/types@^3.222.0":
   version "3.692.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.692.0.tgz#c8f6c75b6ad659865b72759796d4d92c1b72069b"
@@ -639,6 +1222,14 @@
     "@smithy/types" "^3.7.0"
     tslib "^2.6.2"
 
+"@aws-sdk/types@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.709.0.tgz#f8d7ab07e253d3ed0e3b360e09fc67c7430a73b9"
+  integrity sha512-ArtLTMxgjf13Kfu3gWH3Ez9Q5TkDdcRZUofpKH3pMGB/C6KAbeSCtIIDKfoRTUABzyGlPyCrZdnFjKyH+ypIpg==
+  dependencies:
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@aws-sdk/util-arn-parser@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/util-arn-parser/-/util-arn-parser-3.693.0.tgz#8dae27eb822ab4f88be28bb3c0fc11f1f13d3948"
@@ -646,6 +1237,13 @@
   dependencies:
     tslib "^2.6.2"
 
+"@aws-sdk/util-dynamodb@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/util-dynamodb/-/util-dynamodb-3.709.0.tgz#12ced0849ff8f1ac8a1921f97fdb57813f22ec14"
+  integrity sha512-rGr9+Po6Ma2BHV2hIhfXdn8hWxLtmgFzFRqqtxOlRRIDN55wkb2AYXz/ydzf4kgb+PzT8sQxtn6hf7pDkl+yAg==
+  dependencies:
+    tslib "^2.6.2"
+
 "@aws-sdk/util-endpoints@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.693.0.tgz#99f56f83fc25bdc3321f5871d6354abd56768891"
@@ -656,6 +1254,26 @@
     "@smithy/util-endpoints" "^2.1.5"
     tslib "^2.6.2"
 
+"@aws-sdk/util-endpoints@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.709.0.tgz#32dfe339d78b699ada68392bbb3bec25441bae5c"
+  integrity sha512-Mbc7AtL5WGCTKC16IGeUTz+sjpC3ptBda2t0CcK0kMVw3THDdcSq6ZlNKO747cNqdbwUvW34oHteUiHv4/z88Q==
+  dependencies:
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/types" "^3.7.2"
+    "@smithy/util-endpoints" "^2.1.7"
+    tslib "^2.6.2"
+
+"@aws-sdk/util-format-url@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/util-format-url/-/util-format-url-3.709.0.tgz#6ac420c297cae442f6d4065214eefc0d977e1a10"
+  integrity sha512-HGR11hx1KeFfoub/TACf+Yyal37lR85791Di2QPaElQThaqztLlppxale3EohKboOFf7Q/zvslJyM0fmgrlpQw==
+  dependencies:
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/querystring-builder" "^3.0.11"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@aws-sdk/util-locate-window@^3.0.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.693.0.tgz#1160f6d055cf074ca198eb8ecf89b6311537ad6c"
@@ -673,6 +1291,16 @@
     bowser "^2.11.0"
     tslib "^2.6.2"
 
+"@aws-sdk/util-user-agent-browser@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.709.0.tgz#ad6e867bdd348923ec10ddd6c37740ce0986cd8f"
+  integrity sha512-/rL2GasJzdTWUURCQKFldw2wqBtY4k4kCiA2tVZSKg3y4Ey7zO34SW8ebaeCE2/xoWOyLR2/etdKyphoo4Zrtg==
+  dependencies:
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/types" "^3.7.2"
+    bowser "^2.11.0"
+    tslib "^2.6.2"
+
 "@aws-sdk/util-user-agent-node@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.693.0.tgz#b26c806faa2001d4fa1d515b146eeff411513dd9"
@@ -684,6 +1312,17 @@
     "@smithy/types" "^3.7.0"
     tslib "^2.6.2"
 
+"@aws-sdk/util-user-agent-node@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.709.0.tgz#7ff5a508bcad49963a550acadcced43d7af9960d"
+  integrity sha512-trBfzSCVWy7ILgqhEXgiuM7hfRCw4F4a8IK90tjk9YL0jgoJ6eJuOp7+DfCtHJaygoBxD3cdMFkOu+lluFmGBA==
+  dependencies:
+    "@aws-sdk/middleware-user-agent" "3.709.0"
+    "@aws-sdk/types" "3.709.0"
+    "@smithy/node-config-provider" "^3.1.12"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@aws-sdk/xml-builder@3.693.0":
   version "3.693.0"
   resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.693.0.tgz#709a46a3335b71144d9f7917a7cb3033b5a04e82"
@@ -692,6 +1331,14 @@
     "@smithy/types" "^3.7.0"
     tslib "^2.6.2"
 
+"@aws-sdk/xml-builder@3.709.0":
+  version "3.709.0"
+  resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.709.0.tgz#5841faa1e78afcea064557a1a56709978b325758"
+  integrity sha512-2GPCwlNxeHspoK/Mc8nbk9cBOkSpp3j2SJUQmFnyQK6V/pR6II2oPRyZkMomug1Rc10hqlBHByMecq4zhV2uUw==
+  dependencies:
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@azure/abort-controller@^1.0.0", "@azure/abort-controller@^1.0.4":
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/@azure/abort-controller/-/abort-controller-1.1.0.tgz#788ee78457a55af8a1ad342acb182383d2119249"
@@ -2088,47 +2735,6 @@
   resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
   integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
 
-"@budibase/backend-core@3.2.26":
-  version "0.0.0"
-  dependencies:
-    "@budibase/nano" "10.1.5"
-    "@budibase/pouchdb-replication-stream" "1.2.11"
-    "@budibase/shared-core" "*"
-    "@budibase/types" "*"
-    "@techpass/passport-openidconnect" "0.3.3"
-    aws-cloudfront-sign "3.0.2"
-    aws-sdk "2.1692.0"
-    bcrypt "5.1.0"
-    bcryptjs "2.4.3"
-    bull "4.10.1"
-    correlation-id "4.0.0"
-    dd-trace "5.26.0"
-    dotenv "16.0.1"
-    google-auth-library "^8.0.1"
-    google-spreadsheet "npm:@budibase/google-spreadsheet@4.1.5"
-    ioredis "5.3.2"
-    joi "17.6.0"
-    jsonwebtoken "9.0.2"
-    knex "2.4.2"
-    koa-passport "^6.0.0"
-    koa-pino-logger "4.0.0"
-    lodash "4.17.21"
-    node-fetch "2.6.7"
-    passport-google-oauth "2.0.0"
-    passport-local "1.0.0"
-    passport-oauth2-refresh "^2.1.0"
-    pino "8.11.0"
-    pino-http "8.3.3"
-    posthog-node "4.0.1"
-    pouchdb "9.0.0"
-    pouchdb-find "9.0.0"
-    redlock "4.2.0"
-    rotating-file-stream "3.1.0"
-    sanitize-s3-objectkey "0.0.1"
-    semver "^7.5.4"
-    tar-fs "2.1.1"
-    uuid "^8.3.2"
-
 "@budibase/handlebars-helpers@^0.13.2":
   version "0.13.2"
   resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.13.2.tgz#73ab51c464e91fd955b429017648e0257060db77"
@@ -2172,15 +2778,15 @@
     through2 "^2.0.0"
 
 "@budibase/pro@npm:@budibase/pro@latest":
-  version "3.2.26"
-  resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.2.26.tgz#3525535e07827ff820eefeeb94ad9e0e818ac698"
-  integrity sha512-+V04NbKSBN3Up6vcyBFFpecQ3MrJvVuXN74JE9yLj+KVxQXJ1kwCrMgea/XyJomSc72PWb9sQzXADWTe5i5STA==
+  version "3.2.28"
+  resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.2.28.tgz#59b5b37225715bb8fbf5b1c5c989140b10b58710"
+  integrity sha512-eDPeZpYFRZYQhCulcQAUwFoPk68c8+K9mIsB6QD3oMHmHTDA1P2ZcXvLNqDTIqHB94DqnWinqDf4hTuGYApgPA==
   dependencies:
     "@anthropic-ai/sdk" "^0.27.3"
-    "@budibase/backend-core" "3.2.26"
-    "@budibase/shared-core" "3.2.26"
-    "@budibase/string-templates" "3.2.26"
-    "@budibase/types" "3.2.26"
+    "@budibase/backend-core" "*"
+    "@budibase/shared-core" "*"
+    "@budibase/string-templates" "*"
+    "@budibase/types" "*"
     "@koa/router" "13.1.0"
     bull "4.10.1"
     dd-trace "5.26.0"
@@ -2193,25 +2799,6 @@
     scim-patch "^0.8.1"
     scim2-parse-filter "^0.2.8"
 
-"@budibase/shared-core@3.2.26":
-  version "0.0.0"
-  dependencies:
-    "@budibase/types" "*"
-    cron-validate "1.4.5"
-
-"@budibase/string-templates@3.2.26":
-  version "0.0.0"
-  dependencies:
-    "@budibase/handlebars-helpers" "^0.13.2"
-    dayjs "^1.10.8"
-    handlebars "^4.7.8"
-    lodash.clonedeep "^4.5.0"
-
-"@budibase/types@3.2.26":
-  version "0.0.0"
-  dependencies:
-    scim-patch "^0.8.1"
-
 "@bull-board/api@5.10.2":
   version "5.10.2"
   resolved "https://registry.yarnpkg.com/@bull-board/api/-/api-5.10.2.tgz#ae8ff6918b23897bf879a6ead3683f964374c4b3"
@@ -4284,6 +4871,14 @@
     "@smithy/types" "^3.7.1"
     tslib "^2.6.2"
 
+"@smithy/abort-controller@^3.1.9":
+  version "3.1.9"
+  resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-3.1.9.tgz#47d323f754136a489e972d7fd465d534d72fcbff"
+  integrity sha512-yiW0WI30zj8ZKoSYNx90no7ugVn3khlyH/z5W8qtKBtVE6awRALbhSG+2SAHA1r6bO/6M9utxYKVZ3PCJ1rWxw==
+  dependencies:
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@smithy/chunked-blob-reader-native@^3.0.1":
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-3.0.1.tgz#39045ed278ee1b6f4c12715c7565678557274c29"
@@ -4310,6 +4905,17 @@
     "@smithy/util-middleware" "^3.0.10"
     tslib "^2.6.2"
 
+"@smithy/config-resolver@^3.0.13":
+  version "3.0.13"
+  resolved "https://registry.yarnpkg.com/@smithy/config-resolver/-/config-resolver-3.0.13.tgz#653643a77a33d0f5907a5e7582353886b07ba752"
+  integrity sha512-Gr/qwzyPaTL1tZcq8WQyHhTZREER5R1Wytmz4WnVGL4onA3dNk6Btll55c8Vr58pLdvWZmtG8oZxJTw3t3q7Jg==
+  dependencies:
+    "@smithy/node-config-provider" "^3.1.12"
+    "@smithy/types" "^3.7.2"
+    "@smithy/util-config-provider" "^3.0.0"
+    "@smithy/util-middleware" "^3.0.11"
+    tslib "^2.6.2"
+
 "@smithy/core@^2.5.2", "@smithy/core@^2.5.3":
   version "2.5.3"
   resolved "https://registry.yarnpkg.com/@smithy/core/-/core-2.5.3.tgz#1d5723f676b0d6ec08c515272f0ac03aa59fac72"
@@ -4324,6 +4930,20 @@
     "@smithy/util-utf8" "^3.0.0"
     tslib "^2.6.2"
 
+"@smithy/core@^2.5.5":
+  version "2.5.5"
+  resolved "https://registry.yarnpkg.com/@smithy/core/-/core-2.5.5.tgz#c75b15caee9e58c800db3e6b99e9e373532d394a"
+  integrity sha512-G8G/sDDhXA7o0bOvkc7bgai6POuSld/+XhNnWAbpQTpLv2OZPvyqQ58tLPPlz0bSNsXktldDDREIv1LczFeNEw==
+  dependencies:
+    "@smithy/middleware-serde" "^3.0.11"
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/types" "^3.7.2"
+    "@smithy/util-body-length-browser" "^3.0.0"
+    "@smithy/util-middleware" "^3.0.11"
+    "@smithy/util-stream" "^3.3.2"
+    "@smithy/util-utf8" "^3.0.0"
+    tslib "^2.6.2"
+
 "@smithy/credential-provider-imds@^3.2.6", "@smithy/credential-provider-imds@^3.2.7":
   version "3.2.7"
   resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.7.tgz#6eedf87ba0238723ec46d8ce0f18e276685a702d"
@@ -4335,6 +4955,27 @@
     "@smithy/url-parser" "^3.0.10"
     tslib "^2.6.2"
 
+"@smithy/credential-provider-imds@^3.2.8":
+  version "3.2.8"
+  resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.8.tgz#27ed2747074c86a7d627a98e56f324a65cba88de"
+  integrity sha512-ZCY2yD0BY+K9iMXkkbnjo+08T2h8/34oHd0Jmh6BZUSZwaaGlGCyBT/3wnS7u7Xl33/EEfN4B6nQr3Gx5bYxgw==
+  dependencies:
+    "@smithy/node-config-provider" "^3.1.12"
+    "@smithy/property-provider" "^3.1.11"
+    "@smithy/types" "^3.7.2"
+    "@smithy/url-parser" "^3.0.11"
+    tslib "^2.6.2"
+
+"@smithy/eventstream-codec@^3.1.10":
+  version "3.1.10"
+  resolved "https://registry.yarnpkg.com/@smithy/eventstream-codec/-/eventstream-codec-3.1.10.tgz#0c1a3457e7a23b71cd71525ceb668f8569a84dad"
+  integrity sha512-323B8YckSbUH0nMIpXn7HZsAVKHYHFUODa8gG9cHo0ySvA1fr5iWaNT+iIL0UCqUzG6QPHA3BSsBtRQou4mMqQ==
+  dependencies:
+    "@aws-crypto/crc32" "5.2.0"
+    "@smithy/types" "^3.7.2"
+    "@smithy/util-hex-encoding" "^3.0.0"
+    tslib "^2.6.2"
+
 "@smithy/eventstream-codec@^3.1.9":
   version "3.1.9"
   resolved "https://registry.yarnpkg.com/@smithy/eventstream-codec/-/eventstream-codec-3.1.9.tgz#4271354e75e57d30771fca307da403896c657430"
@@ -4354,6 +4995,23 @@
     "@smithy/types" "^3.7.1"
     tslib "^2.6.2"
 
+"@smithy/eventstream-serde-browser@^3.0.14":
+  version "3.0.14"
+  resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.14.tgz#0c3584c7cde2e210aacdfbbd2b57c1d7e2ca3b95"
+  integrity sha512-kbrt0vjOIihW3V7Cqj1SXQvAI5BR8SnyQYsandva0AOR307cXAc+IhPngxIPslxTLfxwDpNu0HzCAq6g42kCPg==
+  dependencies:
+    "@smithy/eventstream-serde-universal" "^3.0.13"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
+"@smithy/eventstream-serde-config-resolver@^3.0.11":
+  version "3.0.11"
+  resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.11.tgz#5edceba836debea165ea93145231036f6286d67c"
+  integrity sha512-P2pnEp4n75O+QHjyO7cbw/vsw5l93K/8EWyjNCAAybYwUmj3M+hjSQZ9P5TVdUgEG08ueMAP5R4FkuSkElZ5tQ==
+  dependencies:
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@smithy/eventstream-serde-config-resolver@^3.0.9":
   version "3.0.10"
   resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.10.tgz#5c0b2ae0bb8e11cfa77851098e46f7350047ec8d"
@@ -4371,6 +5029,15 @@
     "@smithy/types" "^3.7.1"
     tslib "^2.6.2"
 
+"@smithy/eventstream-serde-node@^3.0.13":
+  version "3.0.13"
+  resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.13.tgz#5aebd7b553becee277e411a2b69f6af8c9d7b3a6"
+  integrity sha512-zqy/9iwbj8Wysmvi7Lq7XFLeDgjRpTbCfwBhJa8WbrylTAHiAu6oQTwdY7iu2lxigbc9YYr9vPv5SzYny5tCXQ==
+  dependencies:
+    "@smithy/eventstream-serde-universal" "^3.0.13"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@smithy/eventstream-serde-universal@^3.0.12":
   version "3.0.12"
   resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.12.tgz#803d7beb29a3de4a64e91af97331a4654741c35f"
@@ -4380,6 +5047,15 @@
     "@smithy/types" "^3.7.1"
     tslib "^2.6.2"
 
+"@smithy/eventstream-serde-universal@^3.0.13":
+  version "3.0.13"
+  resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.13.tgz#609c922ea14a0a3eed23a28ac110344c935704eb"
+  integrity sha512-L1Ib66+gg9uTnqp/18Gz4MDpJPKRE44geOjOQ2SVc0eiaO5l255ADziATZgjQjqumC7yPtp1XnjHlF1srcwjKw==
+  dependencies:
+    "@smithy/eventstream-codec" "^3.1.10"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@smithy/fetch-http-handler@^4.1.0", "@smithy/fetch-http-handler@^4.1.1":
   version "4.1.1"
   resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-4.1.1.tgz#cead80762af4cdea11e7eeb627ea1c4835265dfa"
@@ -4391,6 +5067,27 @@
     "@smithy/util-base64" "^3.0.0"
     tslib "^2.6.2"
 
+"@smithy/fetch-http-handler@^4.1.2":
+  version "4.1.2"
+  resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-4.1.2.tgz#f034ff16416b37d92908a1381ef5fddbf4ef1879"
+  integrity sha512-R7rU7Ae3ItU4rC0c5mB2sP5mJNbCfoDc8I5XlYjIZnquyUwec7fEo78F6DA3SmgJgkU1qTMcZJuGblxZsl10ZA==
+  dependencies:
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/querystring-builder" "^3.0.11"
+    "@smithy/types" "^3.7.2"
+    "@smithy/util-base64" "^3.0.0"
+    tslib "^2.6.2"
+
+"@smithy/hash-blob-browser@^3.1.10":
+  version "3.1.10"
+  resolved "https://registry.yarnpkg.com/@smithy/hash-blob-browser/-/hash-blob-browser-3.1.10.tgz#985e308189c2687a15004152b97506882ffb2b13"
+  integrity sha512-elwslXOoNunmfS0fh55jHggyhccobFkexLYC1ZeZ1xP2BTSrcIBaHV2b4xUQOdctrSNOpMqOZH1r2XzWTEhyfA==
+  dependencies:
+    "@smithy/chunked-blob-reader" "^4.0.0"
+    "@smithy/chunked-blob-reader-native" "^3.0.1"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@smithy/hash-blob-browser@^3.1.8":
   version "3.1.9"
   resolved "https://registry.yarnpkg.com/@smithy/hash-blob-browser/-/hash-blob-browser-3.1.9.tgz#1f2c3ef6afbb0ce3e58a0129753850bb9267aae8"
@@ -4401,6 +5098,16 @@
     "@smithy/types" "^3.7.1"
     tslib "^2.6.2"
 
+"@smithy/hash-node@^3.0.11":
+  version "3.0.11"
+  resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-3.0.11.tgz#99e09ead3fc99c8cd7ca0f254ea0e35714f2a0d3"
+  integrity sha512-emP23rwYyZhQBvklqTtwetkQlqbNYirDiEEwXl2v0GYWMnCzxst7ZaRAnWuy28njp5kAH54lvkdG37MblZzaHA==
+  dependencies:
+    "@smithy/types" "^3.7.2"
+    "@smithy/util-buffer-from" "^3.0.0"
+    "@smithy/util-utf8" "^3.0.0"
+    tslib "^2.6.2"
+
 "@smithy/hash-node@^3.0.9":
   version "3.0.10"
   resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-3.0.10.tgz#93c857b4bff3a48884886440fd9772924887e592"
@@ -4411,6 +5118,15 @@
     "@smithy/util-utf8" "^3.0.0"
     tslib "^2.6.2"
 
+"@smithy/hash-stream-node@^3.1.10":
+  version "3.1.10"
+  resolved "https://registry.yarnpkg.com/@smithy/hash-stream-node/-/hash-stream-node-3.1.10.tgz#94716b4556f4ccf2807e605f47bb5b018ed7dfb0"
+  integrity sha512-olomK/jZQ93OMayW1zfTHwcbwBdhcZOHsyWyiZ9h9IXvc1mCD/VuvzbLb3Gy/qNJwI4MANPLctTp2BucV2oU/Q==
+  dependencies:
+    "@smithy/types" "^3.7.2"
+    "@smithy/util-utf8" "^3.0.0"
+    tslib "^2.6.2"
+
 "@smithy/hash-stream-node@^3.1.8":
   version "3.1.9"
   resolved "https://registry.yarnpkg.com/@smithy/hash-stream-node/-/hash-stream-node-3.1.9.tgz#97eb416811b7e7b9d036f0271588151b619759e9"
@@ -4420,6 +5136,14 @@
     "@smithy/util-utf8" "^3.0.0"
     tslib "^2.6.2"
 
+"@smithy/invalid-dependency@^3.0.11":
+  version "3.0.11"
+  resolved "https://registry.yarnpkg.com/@smithy/invalid-dependency/-/invalid-dependency-3.0.11.tgz#8144d7b0af9d34ab5f672e1f674f97f8740bb9ae"
+  integrity sha512-NuQmVPEJjUX6c+UELyVz8kUx8Q539EDeNwbRyu4IIF8MeV7hUtq1FB3SHVyki2u++5XLMFqngeMKk7ccspnNyQ==
+  dependencies:
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@smithy/invalid-dependency@^3.0.9":
   version "3.0.10"
   resolved "https://registry.yarnpkg.com/@smithy/invalid-dependency/-/invalid-dependency-3.0.10.tgz#8616dee555916c24dec3e33b1e046c525efbfee3"
@@ -4442,6 +5166,15 @@
   dependencies:
     tslib "^2.6.2"
 
+"@smithy/md5-js@^3.0.11":
+  version "3.0.11"
+  resolved "https://registry.yarnpkg.com/@smithy/md5-js/-/md5-js-3.0.11.tgz#27e4dab616348ff94aed24dc75e4017c582df40f"
+  integrity sha512-3NM0L3i2Zm4bbgG6Ymi9NBcxXhryi3uE8fIfHJZIOfZVxOkGdjdgjR9A06SFIZCfnEIWKXZdm6Yq5/aPXFFhsQ==
+  dependencies:
+    "@smithy/types" "^3.7.2"
+    "@smithy/util-utf8" "^3.0.0"
+    tslib "^2.6.2"
+
 "@smithy/md5-js@^3.0.9":
   version "3.0.10"
   resolved "https://registry.yarnpkg.com/@smithy/md5-js/-/md5-js-3.0.10.tgz#52ab927cf03cd1d24fed82d8ba936faf5632436e"
@@ -4460,6 +5193,15 @@
     "@smithy/types" "^3.7.1"
     tslib "^2.6.2"
 
+"@smithy/middleware-content-length@^3.0.13":
+  version "3.0.13"
+  resolved "https://registry.yarnpkg.com/@smithy/middleware-content-length/-/middleware-content-length-3.0.13.tgz#6e08fe52739ac8fb3996088e0f8837e4b2ea187f"
+  integrity sha512-zfMhzojhFpIX3P5ug7jxTjfUcIPcGjcQYzB9t+rv0g1TX7B0QdwONW+ATouaLoD7h7LOw/ZlXfkq4xJ/g2TrIw==
+  dependencies:
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@smithy/middleware-endpoint@^3.2.2", "@smithy/middleware-endpoint@^3.2.3":
   version "3.2.3"
   resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-3.2.3.tgz#7dd3df0052fc55891522631a7751e613b6efd68a"
@@ -4474,6 +5216,20 @@
     "@smithy/util-middleware" "^3.0.10"
     tslib "^2.6.2"
 
+"@smithy/middleware-endpoint@^3.2.5":
+  version "3.2.5"
+  resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-3.2.5.tgz#bdcfdf1f342cf933b0b8a709996f9a8fbb8148f4"
+  integrity sha512-VhJNs/s/lyx4weiZdXSloBgoLoS8osV0dKIain8nGmx7of3QFKu5BSdEuk1z/U8x9iwes1i+XCiNusEvuK1ijg==
+  dependencies:
+    "@smithy/core" "^2.5.5"
+    "@smithy/middleware-serde" "^3.0.11"
+    "@smithy/node-config-provider" "^3.1.12"
+    "@smithy/shared-ini-file-loader" "^3.1.12"
+    "@smithy/types" "^3.7.2"
+    "@smithy/url-parser" "^3.0.11"
+    "@smithy/util-middleware" "^3.0.11"
+    tslib "^2.6.2"
+
 "@smithy/middleware-retry@^3.0.26":
   version "3.0.27"
   resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-3.0.27.tgz#2e4dda420178835cd2d416479505d313b601ba21"
@@ -4489,6 +5245,21 @@
     tslib "^2.6.2"
     uuid "^9.0.1"
 
+"@smithy/middleware-retry@^3.0.30":
+  version "3.0.30"
+  resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-3.0.30.tgz#2580322d0d28ad782b5b8c07c150b14efdc3b2f9"
+  integrity sha512-6323RL2BvAR3VQpTjHpa52kH/iSHyxd/G9ohb2MkBk2Ucu+oMtRXT8yi7KTSIS9nb58aupG6nO0OlXnQOAcvmQ==
+  dependencies:
+    "@smithy/node-config-provider" "^3.1.12"
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/service-error-classification" "^3.0.11"
+    "@smithy/smithy-client" "^3.5.0"
+    "@smithy/types" "^3.7.2"
+    "@smithy/util-middleware" "^3.0.11"
+    "@smithy/util-retry" "^3.0.11"
+    tslib "^2.6.2"
+    uuid "^9.0.1"
+
 "@smithy/middleware-serde@^3.0.10", "@smithy/middleware-serde@^3.0.9":
   version "3.0.10"
   resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-3.0.10.tgz#5f6c0b57b10089a21d355bd95e9b7d40378454d7"
@@ -4497,6 +5268,14 @@
     "@smithy/types" "^3.7.1"
     tslib "^2.6.2"
 
+"@smithy/middleware-serde@^3.0.11":
+  version "3.0.11"
+  resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-3.0.11.tgz#c7d54e0add4f83e05c6878a011fc664e21022f12"
+  integrity sha512-KzPAeySp/fOoQA82TpnwItvX8BBURecpx6ZMu75EZDkAcnPtO6vf7q4aH5QHs/F1s3/snQaSFbbUMcFFZ086Mw==
+  dependencies:
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@smithy/middleware-stack@^3.0.10", "@smithy/middleware-stack@^3.0.9":
   version "3.0.10"
   resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-3.0.10.tgz#73e2fde5d151440844161773a17ee13375502baf"
@@ -4505,6 +5284,14 @@
     "@smithy/types" "^3.7.1"
     tslib "^2.6.2"
 
+"@smithy/middleware-stack@^3.0.11":
+  version "3.0.11"
+  resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-3.0.11.tgz#453af2096924e4064d9da4e053cfdf65d9a36acc"
+  integrity sha512-1HGo9a6/ikgOMrTrWL/WiN9N8GSVYpuRQO5kjstAq4CvV59bjqnh7TbdXGQ4vxLD3xlSjfBjq5t1SOELePsLnA==
+  dependencies:
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@smithy/node-config-provider@^3.1.10", "@smithy/node-config-provider@^3.1.11":
   version "3.1.11"
   resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-3.1.11.tgz#95feba85a5cb3de3fe9adfff1060b35fd556d023"
@@ -4515,6 +5302,16 @@
     "@smithy/types" "^3.7.1"
     tslib "^2.6.2"
 
+"@smithy/node-config-provider@^3.1.12":
+  version "3.1.12"
+  resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-3.1.12.tgz#1b1d674fc83f943dc7b3017e37f16f374e878a6c"
+  integrity sha512-O9LVEu5J/u/FuNlZs+L7Ikn3lz7VB9hb0GtPT9MQeiBmtK8RSY3ULmsZgXhe6VAlgTw0YO+paQx4p8xdbs43vQ==
+  dependencies:
+    "@smithy/property-provider" "^3.1.11"
+    "@smithy/shared-ini-file-loader" "^3.1.12"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@smithy/node-http-handler@^1.0.2":
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-1.1.0.tgz#887cee930b520e08043c9f41e463f8d8f5dae127"
@@ -4537,6 +5334,17 @@
     "@smithy/types" "^3.7.1"
     tslib "^2.6.2"
 
+"@smithy/node-http-handler@^3.3.2":
+  version "3.3.2"
+  resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-3.3.2.tgz#b34685863b74dabdaf7860aa81b42d0d5437c7e0"
+  integrity sha512-t4ng1DAd527vlxvOfKFYEe6/QFBcsj7WpNlWTyjorwXXcKw3XlltBGbyHfSJ24QT84nF+agDha9tNYpzmSRZPA==
+  dependencies:
+    "@smithy/abort-controller" "^3.1.9"
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/querystring-builder" "^3.0.11"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@smithy/property-provider@^3.1.10", "@smithy/property-provider@^3.1.9":
   version "3.1.10"
   resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-3.1.10.tgz#ae00447c1060c194c3e1b9475f7c8548a70f8486"
@@ -4545,6 +5353,14 @@
     "@smithy/types" "^3.7.1"
     tslib "^2.6.2"
 
+"@smithy/property-provider@^3.1.11":
+  version "3.1.11"
+  resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-3.1.11.tgz#161cf1c2a2ada361e417382c57f5ba6fbca8acad"
+  integrity sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==
+  dependencies:
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@smithy/protocol-http@^1.2.0":
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-1.2.0.tgz#a554e4dabb14508f0bc2cdef9c3710e2b294be04"
@@ -4561,6 +5377,14 @@
     "@smithy/types" "^3.7.1"
     tslib "^2.6.2"
 
+"@smithy/protocol-http@^4.1.8":
+  version "4.1.8"
+  resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-4.1.8.tgz#0461758671335f65e8ff3fc0885ab7ed253819c9"
+  integrity sha512-hmgIAVyxw1LySOwkgMIUN0kjN8TG9Nc85LJeEmEE/cNEe2rkHDUWhnJf2gxcSRFLWsyqWsrZGw40ROjUogg+Iw==
+  dependencies:
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@smithy/querystring-builder@^1.1.0":
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-1.1.0.tgz#de6306104640ade34e59be33949db6cc64aa9d7f"
@@ -4579,6 +5403,15 @@
     "@smithy/util-uri-escape" "^3.0.0"
     tslib "^2.6.2"
 
+"@smithy/querystring-builder@^3.0.11":
+  version "3.0.11"
+  resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-3.0.11.tgz#2ed04adbe725671824c5613d0d6f9376d791a909"
+  integrity sha512-u+5HV/9uJaeLj5XTb6+IEF/dokWWkEqJ0XiaRRogyREmKGUgZnNecLucADLdauWFKUNbQfulHFEZEdjwEBjXRg==
+  dependencies:
+    "@smithy/types" "^3.7.2"
+    "@smithy/util-uri-escape" "^3.0.0"
+    tslib "^2.6.2"
+
 "@smithy/querystring-parser@^3.0.10":
   version "3.0.10"
   resolved "https://registry.yarnpkg.com/@smithy/querystring-parser/-/querystring-parser-3.0.10.tgz#62db744a1ed2cf90f4c08d2c73d365e033b4a11c"
@@ -4587,6 +5420,14 @@
     "@smithy/types" "^3.7.1"
     tslib "^2.6.2"
 
+"@smithy/querystring-parser@^3.0.11":
+  version "3.0.11"
+  resolved "https://registry.yarnpkg.com/@smithy/querystring-parser/-/querystring-parser-3.0.11.tgz#9d3177ea19ce8462f18d9712b395239e1ca1f969"
+  integrity sha512-Je3kFvCsFMnso1ilPwA7GtlbPaTixa3WwC+K21kmMZHsBEOZYQaqxcMqeFFoU7/slFjKDIpiiPydvdJm8Q/MCw==
+  dependencies:
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@smithy/service-error-classification@^3.0.10":
   version "3.0.10"
   resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-3.0.10.tgz#941c549daf0e9abb84d3def1d9e1e3f0f74f5ba6"
@@ -4594,6 +5435,13 @@
   dependencies:
     "@smithy/types" "^3.7.1"
 
+"@smithy/service-error-classification@^3.0.11":
+  version "3.0.11"
+  resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-3.0.11.tgz#d3d7fc0aacd2e60d022507367e55c7939e5bcb8a"
+  integrity sha512-QnYDPkyewrJzCyaeI2Rmp7pDwbUETe+hU8ADkXmgNusO1bgHBH7ovXJiYmba8t0fNfJx75fE8dlM6SEmZxheog==
+  dependencies:
+    "@smithy/types" "^3.7.2"
+
 "@smithy/shared-ini-file-loader@^3.1.10", "@smithy/shared-ini-file-loader@^3.1.11":
   version "3.1.11"
   resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.11.tgz#0b4f98c4a66480956fbbefc4627c5dc09d891aea"
@@ -4602,6 +5450,14 @@
     "@smithy/types" "^3.7.1"
     tslib "^2.6.2"
 
+"@smithy/shared-ini-file-loader@^3.1.12":
+  version "3.1.12"
+  resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.12.tgz#d98b1b663eb18935ce2cbc79024631d34f54042a"
+  integrity sha512-1xKSGI+U9KKdbG2qDvIR9dGrw3CNx+baqJfyr0igKEpjbHL5stsqAesYBzHChYHlelWtb87VnLWlhvfCz13H8Q==
+  dependencies:
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@smithy/signature-v4@^4.2.2":
   version "4.2.3"
   resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-4.2.3.tgz#abbca5e5fe9158422b3125b2956791a325a27f22"
@@ -4616,6 +5472,20 @@
     "@smithy/util-utf8" "^3.0.0"
     tslib "^2.6.2"
 
+"@smithy/signature-v4@^4.2.4":
+  version "4.2.4"
+  resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-4.2.4.tgz#3501d3d09fd82768867bfc00a7be4bad62f62f4d"
+  integrity sha512-5JWeMQYg81TgU4cG+OexAWdvDTs5JDdbEZx+Qr1iPbvo91QFGzjy0IkXAKaXUHqmKUJgSHK0ZxnCkgZpzkeNTA==
+  dependencies:
+    "@smithy/is-array-buffer" "^3.0.0"
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/types" "^3.7.2"
+    "@smithy/util-hex-encoding" "^3.0.0"
+    "@smithy/util-middleware" "^3.0.11"
+    "@smithy/util-uri-escape" "^3.0.0"
+    "@smithy/util-utf8" "^3.0.0"
+    tslib "^2.6.2"
+
 "@smithy/smithy-client@^3.4.3", "@smithy/smithy-client@^3.4.4":
   version "3.4.4"
   resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-3.4.4.tgz#460870dc97d945fa2f390890359cf09d01131e0f"
@@ -4629,6 +5499,19 @@
     "@smithy/util-stream" "^3.3.1"
     tslib "^2.6.2"
 
+"@smithy/smithy-client@^3.5.0":
+  version "3.5.0"
+  resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-3.5.0.tgz#65cff262801b009998c1196764ee69929ee06f8a"
+  integrity sha512-Y8FeOa7gbDfCWf7njrkoRATPa5eNLUEjlJS5z5rXatYuGkCb80LbHcu8AQR8qgAZZaNHCLyo2N+pxPsV7l+ivg==
+  dependencies:
+    "@smithy/core" "^2.5.5"
+    "@smithy/middleware-endpoint" "^3.2.5"
+    "@smithy/middleware-stack" "^3.0.11"
+    "@smithy/protocol-http" "^4.1.8"
+    "@smithy/types" "^3.7.2"
+    "@smithy/util-stream" "^3.3.2"
+    tslib "^2.6.2"
+
 "@smithy/types@^1.2.0":
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/@smithy/types/-/types-1.2.0.tgz#9dc65767b0ee3d6681704fcc67665d6fc9b6a34e"
@@ -4643,6 +5526,13 @@
   dependencies:
     tslib "^2.6.2"
 
+"@smithy/types@^3.7.2":
+  version "3.7.2"
+  resolved "https://registry.yarnpkg.com/@smithy/types/-/types-3.7.2.tgz#05cb14840ada6f966de1bf9a9c7dd86027343e10"
+  integrity sha512-bNwBYYmN8Eh9RyjS1p2gW6MIhSO2rl7X9QeLM8iTdcGRP+eDiIWDt66c9IysCc22gefKszZv+ubV9qZc7hdESg==
+  dependencies:
+    tslib "^2.6.2"
+
 "@smithy/url-parser@^3.0.10", "@smithy/url-parser@^3.0.9":
   version "3.0.10"
   resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-3.0.10.tgz#f389985a79766cff4a99af14979f01a17ce318da"
@@ -4652,6 +5542,15 @@
     "@smithy/types" "^3.7.1"
     tslib "^2.6.2"
 
+"@smithy/url-parser@^3.0.11":
+  version "3.0.11"
+  resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-3.0.11.tgz#e5f5ffabfb6230159167cf4cc970705fca6b8b2d"
+  integrity sha512-TmlqXkSk8ZPhfc+SQutjmFr5FjC0av3GZP4B/10caK1SbRwe/v+Wzu/R6xEKxoNqL+8nY18s1byiy6HqPG37Aw==
+  dependencies:
+    "@smithy/querystring-parser" "^3.0.11"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@smithy/util-base64@^3.0.0":
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/@smithy/util-base64/-/util-base64-3.0.0.tgz#f7a9a82adf34e27a72d0719395713edf0e493017"
@@ -4709,6 +5608,17 @@
     bowser "^2.11.0"
     tslib "^2.6.2"
 
+"@smithy/util-defaults-mode-browser@^3.0.30":
+  version "3.0.30"
+  resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.30.tgz#6c0d95af3f15bef8f1fe3f6217cc4f5ba8df5554"
+  integrity sha512-nLuGmgfcr0gzm64pqF2UT4SGWVG8UGviAdayDlVzJPNa6Z4lqvpDzdRXmLxtOdEjVlTOEdpZ9dd3ZMMu488mzg==
+  dependencies:
+    "@smithy/property-provider" "^3.1.11"
+    "@smithy/smithy-client" "^3.5.0"
+    "@smithy/types" "^3.7.2"
+    bowser "^2.11.0"
+    tslib "^2.6.2"
+
 "@smithy/util-defaults-mode-node@^3.0.26":
   version "3.0.27"
   resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.27.tgz#a7248c9d9cb620827ab57ef9d1867bfe8aef42d0"
@@ -4722,6 +5632,19 @@
     "@smithy/types" "^3.7.1"
     tslib "^2.6.2"
 
+"@smithy/util-defaults-mode-node@^3.0.30":
+  version "3.0.30"
+  resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.30.tgz#33cdb02f90944b9ff221e2f8e0904a63ac1e335f"
+  integrity sha512-OD63eWoH68vp75mYcfYyuVH+p7Li/mY4sYOROnauDrtObo1cS4uWfsy/zhOTW8F8ZPxQC1ZXZKVxoxvMGUv2Ow==
+  dependencies:
+    "@smithy/config-resolver" "^3.0.13"
+    "@smithy/credential-provider-imds" "^3.2.8"
+    "@smithy/node-config-provider" "^3.1.12"
+    "@smithy/property-provider" "^3.1.11"
+    "@smithy/smithy-client" "^3.5.0"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@smithy/util-endpoints@^2.1.5":
   version "2.1.6"
   resolved "https://registry.yarnpkg.com/@smithy/util-endpoints/-/util-endpoints-2.1.6.tgz#720cbd1a616ad7c099b77780f0cb0f1f9fc5d2df"
@@ -4731,6 +5654,15 @@
     "@smithy/types" "^3.7.1"
     tslib "^2.6.2"
 
+"@smithy/util-endpoints@^2.1.7":
+  version "2.1.7"
+  resolved "https://registry.yarnpkg.com/@smithy/util-endpoints/-/util-endpoints-2.1.7.tgz#a088ebfab946a7219dd4763bfced82709894b82d"
+  integrity sha512-tSfcqKcN/Oo2STEYCABVuKgJ76nyyr6skGl9t15hs+YaiU06sgMkN7QYjo0BbVw+KT26zok3IzbdSOksQ4YzVw==
+  dependencies:
+    "@smithy/node-config-provider" "^3.1.12"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@smithy/util-hex-encoding@^3.0.0":
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz#32938b33d5bf2a15796cd3f178a55b4155c535e6"
@@ -4746,6 +5678,14 @@
     "@smithy/types" "^3.7.1"
     tslib "^2.6.2"
 
+"@smithy/util-middleware@^3.0.11":
+  version "3.0.11"
+  resolved "https://registry.yarnpkg.com/@smithy/util-middleware/-/util-middleware-3.0.11.tgz#2ab5c17266b42c225e62befcffb048afa682b5bf"
+  integrity sha512-dWpyc1e1R6VoXrwLoLDd57U1z6CwNSdkM69Ie4+6uYh2GC7Vg51Qtan7ITzczuVpqezdDTKJGJB95fFvvjU/ow==
+  dependencies:
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@smithy/util-retry@^3.0.10", "@smithy/util-retry@^3.0.9":
   version "3.0.10"
   resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-3.0.10.tgz#fc13e1b30e87af0cbecadf29ca83b171e2040440"
@@ -4755,6 +5695,15 @@
     "@smithy/types" "^3.7.1"
     tslib "^2.6.2"
 
+"@smithy/util-retry@^3.0.11":
+  version "3.0.11"
+  resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-3.0.11.tgz#d267e5ccb290165cee69732547fea17b695a7425"
+  integrity sha512-hJUC6W7A3DQgaee3Hp9ZFcOxVDZzmBIRBPlUAk8/fSOEl7pE/aX7Dci0JycNOnm9Mfr0KV2XjIlUOcGWXQUdVQ==
+  dependencies:
+    "@smithy/service-error-classification" "^3.0.11"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@smithy/util-stream@^3.3.0", "@smithy/util-stream@^3.3.1":
   version "3.3.1"
   resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-3.3.1.tgz#a2636f435637ef90d64df2bb8e71cd63236be112"
@@ -4769,6 +5718,20 @@
     "@smithy/util-utf8" "^3.0.0"
     tslib "^2.6.2"
 
+"@smithy/util-stream@^3.3.2":
+  version "3.3.2"
+  resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-3.3.2.tgz#daeea26397e8541cf2499ce65bf0b8d528cba421"
+  integrity sha512-sInAqdiVeisUGYAv/FrXpmJ0b4WTFmciTRqzhb7wVuem9BHvhIG7tpiYHLDWrl2stOokNZpTTGqz3mzB2qFwXg==
+  dependencies:
+    "@smithy/fetch-http-handler" "^4.1.2"
+    "@smithy/node-http-handler" "^3.3.2"
+    "@smithy/types" "^3.7.2"
+    "@smithy/util-base64" "^3.0.0"
+    "@smithy/util-buffer-from" "^3.0.0"
+    "@smithy/util-hex-encoding" "^3.0.0"
+    "@smithy/util-utf8" "^3.0.0"
+    tslib "^2.6.2"
+
 "@smithy/util-uri-escape@^1.1.0":
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/@smithy/util-uri-escape/-/util-uri-escape-1.1.0.tgz#a8c5edaf19c0efdb9b51661e840549cf600a1808"
@@ -4808,6 +5771,15 @@
     "@smithy/types" "^3.7.1"
     tslib "^2.6.2"
 
+"@smithy/util-waiter@^3.2.0":
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/@smithy/util-waiter/-/util-waiter-3.2.0.tgz#1e52f870e77d2e5572025f7606053e6ff00df93d"
+  integrity sha512-PpjSboaDUE6yl+1qlg3Si57++e84oXdWGbuFUSAciXsVfEZJJJupR2Nb0QuXHiunt2vGR+1PTizOMvnUPaG2Qg==
+  dependencies:
+    "@smithy/abort-controller" "^3.1.9"
+    "@smithy/types" "^3.7.2"
+    tslib "^2.6.2"
+
 "@socket.io/component-emitter@~3.1.0":
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553"
@@ -6112,6 +7084,11 @@
   resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc"
   integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==
 
+"@types/uuid@^9.0.1":
+  version "9.0.8"
+  resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba"
+  integrity sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==
+
 "@types/webidl-conversions@*":
   version "7.0.0"
   resolved "https://registry.yarnpkg.com/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz#2b8e60e33906459219aa587e9d1a612ae994cfe7"
@@ -7520,6 +8497,14 @@ buffer@4.9.2:
     ieee754 "^1.1.4"
     isarray "^1.0.0"
 
+buffer@5.6.0:
+  version "5.6.0"
+  resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786"
+  integrity sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==
+  dependencies:
+    base64-js "^1.0.2"
+    ieee754 "^1.1.4"
+
 buffer@6.0.3, buffer@^6.0.3:
   version "6.0.3"
   resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
@@ -10228,7 +11213,7 @@ events@1.1.1:
   resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924"
   integrity sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==
 
-events@^3.0.0, events@^3.3.0:
+events@3.3.0, events@^3.0.0, events@^3.3.0:
   version "3.3.0"
   resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
   integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
@@ -11984,7 +12969,7 @@ inflight@^1.0.4:
     once "^1.3.0"
     wrappy "1"
 
-inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3:
+inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4:
   version "2.0.4"
   resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
   integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@@ -14808,6 +15793,13 @@ mlly@^1.1.0, mlly@^1.7.1:
     pkg-types "^1.1.1"
     ufo "^1.5.3"
 
+mnemonist@0.38.3:
+  version "0.38.3"
+  resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.3.tgz#35ec79c1c1f4357cfda2fe264659c2775ccd7d9d"
+  integrity sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==
+  dependencies:
+    obliterator "^1.6.1"
+
 modify-values@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022"
@@ -15600,6 +16592,11 @@ object.values@^1.1.7:
     define-properties "^1.2.0"
     es-abstract "^1.22.1"
 
+obliterator@^1.6.1:
+  version "1.6.1"
+  resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-1.6.1.tgz#dea03e8ab821f6c4d96a299e17aef6a3af994ef3"
+  integrity sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==
+
 omggif@^1.0.10:
   version "1.0.10"
   resolved "https://registry.yarnpkg.com/omggif/-/omggif-1.0.10.tgz#ddaaf90d4a42f532e9e7cb3a95ecdd47f17c7b19"
@@ -18645,6 +19642,14 @@ stoppable@^1.1.0:
   resolved "https://registry.yarnpkg.com/stoppable/-/stoppable-1.1.0.tgz#32da568e83ea488b08e4d7ea2c3bcc9d75015d5b"
   integrity sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==
 
+stream-browserify@3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-3.0.0.tgz#22b0a2850cdf6503e73085da1fc7b7d0c2122f2f"
+  integrity sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==
+  dependencies:
+    inherits "~2.0.4"
+    readable-stream "^3.5.0"
+
 stream-events@^1.0.5:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/stream-events/-/stream-events-1.0.5.tgz#bbc898ec4df33a4902d892333d47da9bf1c406d5"

From 544efaed6ea222719dfd9cd5b5282aca6b836d20 Mon Sep 17 00:00:00 2001
From: mike12345567 <me@michaeldrury.co.uk>
Date: Thu, 12 Dec 2024 18:25:49 +0000
Subject: [PATCH 02/14] Finishing off async code changes from pre-signing
 changes.

---
 .../objectStore/buckets/tests/plugins.spec.ts | 28 +++++++++----------
 packages/server/src/sdk/plugins/plugins.ts    |  2 +-
 .../server/src/utilities/fileSystem/app.ts    |  2 +-
 .../server/src/utilities/fileSystem/plugin.ts |  7 ++++-
 4 files changed, 22 insertions(+), 17 deletions(-)

diff --git a/packages/backend-core/src/objectStore/buckets/tests/plugins.spec.ts b/packages/backend-core/src/objectStore/buckets/tests/plugins.spec.ts
index fc2822314e0..0906ea91c22 100644
--- a/packages/backend-core/src/objectStore/buckets/tests/plugins.spec.ts
+++ b/packages/backend-core/src/objectStore/buckets/tests/plugins.spec.ts
@@ -6,8 +6,8 @@ describe("plugins", () => {
   describe("enrichPluginURLs", () => {
     const plugin = structures.plugins.plugin()
 
-    function getEnrichedPluginUrls() {
-      const enriched = plugins.enrichPluginURLs([plugin])[0]
+    async function getEnrichedPluginUrls() {
+      const enriched = (await plugins.enrichPluginURLs([plugin]))[0]
       return {
         jsUrl: enriched.jsUrl!,
         iconUrl: enriched.iconUrl!,
@@ -19,9 +19,9 @@ describe("plugins", () => {
         testEnv.singleTenant()
       })
 
-      it("gets url with embedded minio", () => {
+      it("gets url with embedded minio", async () => {
         testEnv.withMinio()
-        const urls = getEnrichedPluginUrls()
+        const urls = await getEnrichedPluginUrls()
         expect(urls.jsUrl).toBe(
           `/files/signed/plugins/${plugin.name}/plugin.min.js`
         )
@@ -30,9 +30,9 @@ describe("plugins", () => {
         )
       })
 
-      it("gets url with custom S3", () => {
+      it("gets url with custom S3", async () => {
         testEnv.withS3()
-        const urls = getEnrichedPluginUrls()
+        const urls = await getEnrichedPluginUrls()
         expect(urls.jsUrl).toBe(
           `http://s3.example.com/plugins/${plugin.name}/plugin.min.js`
         )
@@ -41,9 +41,9 @@ describe("plugins", () => {
         )
       })
 
-      it("gets url with cloudfront + s3", () => {
+      it("gets url with cloudfront + s3", async () => {
         testEnv.withCloudfront()
-        const urls = getEnrichedPluginUrls()
+        const urls = await getEnrichedPluginUrls()
         // omit rest of signed params
         expect(
           urls.jsUrl.includes(
@@ -65,8 +65,8 @@ describe("plugins", () => {
 
       it("gets url with embedded minio", async () => {
         testEnv.withMinio()
-        await testEnv.withTenant(tenantId => {
-          const urls = getEnrichedPluginUrls()
+        await testEnv.withTenant(async tenantId => {
+          const urls = await getEnrichedPluginUrls()
           expect(urls.jsUrl).toBe(
             `/files/signed/plugins/${tenantId}/${plugin.name}/plugin.min.js`
           )
@@ -78,8 +78,8 @@ describe("plugins", () => {
 
       it("gets url with custom S3", async () => {
         testEnv.withS3()
-        await testEnv.withTenant(tenantId => {
-          const urls = getEnrichedPluginUrls()
+        await testEnv.withTenant(async tenantId => {
+          const urls = await getEnrichedPluginUrls()
           expect(urls.jsUrl).toBe(
             `http://s3.example.com/plugins/${tenantId}/${plugin.name}/plugin.min.js`
           )
@@ -91,8 +91,8 @@ describe("plugins", () => {
 
       it("gets url with cloudfront + s3", async () => {
         testEnv.withCloudfront()
-        await testEnv.withTenant(tenantId => {
-          const urls = getEnrichedPluginUrls()
+        await testEnv.withTenant(async tenantId => {
+          const urls = await getEnrichedPluginUrls()
           // omit rest of signed params
           expect(
             urls.jsUrl.includes(
diff --git a/packages/server/src/sdk/plugins/plugins.ts b/packages/server/src/sdk/plugins/plugins.ts
index 63f2f22cd9e..bff24dcef76 100644
--- a/packages/server/src/sdk/plugins/plugins.ts
+++ b/packages/server/src/sdk/plugins/plugins.ts
@@ -18,7 +18,7 @@ export async function fetch(type?: PluginType): Promise<Plugin[]> {
     })
   )
   let plugins = response.rows.map((row: any) => row.doc) as Plugin[]
-  plugins = objectStore.enrichPluginURLs(plugins)
+  plugins = await objectStore.enrichPluginURLs(plugins)
   if (type) {
     return plugins.filter((plugin: Plugin) => plugin.schema?.type === type)
   } else {
diff --git a/packages/server/src/utilities/fileSystem/app.ts b/packages/server/src/utilities/fileSystem/app.ts
index 9bd88ba0b1d..642017d2daf 100644
--- a/packages/server/src/utilities/fileSystem/app.ts
+++ b/packages/server/src/utilities/fileSystem/app.ts
@@ -78,7 +78,7 @@ export const getComponentLibraryManifest = async (library: string) => {
     resp = await objectStore.retrieve(ObjectStoreBuckets.APPS, path)
   }
   if (typeof resp !== "string") {
-    resp = resp.toString("utf8")
+    resp = resp.toString()
   }
   return JSON.parse(resp)
 }
diff --git a/packages/server/src/utilities/fileSystem/plugin.ts b/packages/server/src/utilities/fileSystem/plugin.ts
index 3e1e9bef4d9..2949daef618 100644
--- a/packages/server/src/utilities/fileSystem/plugin.ts
+++ b/packages/server/src/utilities/fileSystem/plugin.ts
@@ -3,6 +3,7 @@ import { budibaseTempDir } from "../budibaseDir"
 import fs from "fs"
 import { join } from "path"
 import { objectStore } from "@budibase/backend-core"
+import stream from "stream"
 
 const DATASOURCE_PATH = join(budibaseTempDir(), "datasource")
 const AUTOMATION_PATH = join(budibaseTempDir(), "automation")
@@ -58,7 +59,11 @@ async function getPluginImpl(path: string, plugin: Plugin) {
     pluginKey
   )
 
-  fs.writeFileSync(filename, pluginJs)
+  if (pluginJs instanceof stream.Readable) {
+    pluginJs.pipe(fs.createWriteStream(filename))
+  } else {
+    fs.writeFileSync(filename, pluginJs)
+  }
   fs.writeFileSync(metadataName, hash)
 
   return require(filename)

From 49dca3b7c96d248d534700811a16f45d61afd39b Mon Sep 17 00:00:00 2001
From: mike12345567 <me@michaeldrury.co.uk>
Date: Thu, 19 Dec 2024 13:19:25 +0000
Subject: [PATCH 03/14] Some fixes for failing test cases.

---
 packages/backend-core/src/environment.ts             | 2 +-
 packages/backend-core/src/objectStore/objectStore.ts | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/packages/backend-core/src/environment.ts b/packages/backend-core/src/environment.ts
index 954fdd41353..9a467580628 100644
--- a/packages/backend-core/src/environment.ts
+++ b/packages/backend-core/src/environment.ts
@@ -154,7 +154,7 @@ const environment = {
   MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY,
   MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY,
   AWS_SESSION_TOKEN: process.env.AWS_SESSION_TOKEN,
-  AWS_REGION: process.env.AWS_REGION,
+  AWS_REGION: process.env.AWS_REGION || "eu-west-1",
   MINIO_URL: process.env.MINIO_URL,
   MINIO_ENABLED: process.env.MINIO_ENABLED || 1,
   INTERNAL_API_KEY: process.env.INTERNAL_API_KEY,
diff --git a/packages/backend-core/src/objectStore/objectStore.ts b/packages/backend-core/src/objectStore/objectStore.ts
index 6acf2e21aec..513ad03bb5b 100644
--- a/packages/backend-core/src/objectStore/objectStore.ts
+++ b/packages/backend-core/src/objectStore/objectStore.ts
@@ -119,7 +119,7 @@ export function ObjectStore(
       // Normally a signed url will need to be generated with a specified host in mind.
       // To support dynamic hosts, e.g. some unknown self-hosted installation url,
       // use a predefined host. The host 'minio-service' is also forwarded to minio requests via nginx
-      config.endpoint = "minio-service"
+      config.endpoint = "http://minio-service"
     } else {
       config.endpoint = env.MINIO_URL
     }

From 0f659635c75e55c2571bd80309b06f592c2dc460 Mon Sep 17 00:00:00 2001
From: mike12345567 <me@michaeldrury.co.uk>
Date: Thu, 19 Dec 2024 14:02:24 +0000
Subject: [PATCH 04/14] Fixing mocked test case.

---
 .../src/api/routes/tests/static.spec.ts       | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/packages/server/src/api/routes/tests/static.spec.ts b/packages/server/src/api/routes/tests/static.spec.ts
index c2808603e9b..872085c382b 100644
--- a/packages/server/src/api/routes/tests/static.spec.ts
+++ b/packages/server/src/api/routes/tests/static.spec.ts
@@ -1,12 +1,10 @@
 // Directly mock the AWS SDK
-jest.mock("aws-sdk", () => ({
-  S3: jest.fn(() => ({
-    getSignedUrl: jest.fn(
-      (operation, params) => `http://example.com/${params.Bucket}/${params.Key}`
-    ),
-    upload: jest.fn(() => ({ Contents: {} })),
-  })),
+jest.mock("@aws-sdk/s3-request-presigner", () => ({
+  getSignedUrl: jest.fn(() => {
+    return `http://example.com`
+  }),
 }))
+jest.mock("@aws-sdk/client-s3")
 
 import { Datasource, SourceName } from "@budibase/types"
 import { setEnv } from "../../../environment"
@@ -77,7 +75,10 @@ describe("/static", () => {
             type: "datasource",
             name: "Test",
             source: SourceName.S3,
-            config: {},
+            config: {
+              accessKeyId: "bb",
+              secretAccessKey: "bb",
+            },
           },
         })
       })
@@ -91,7 +92,7 @@ describe("/static", () => {
           .set(config.defaultHeaders())
           .expect("Content-Type", /json/)
           .expect(200)
-        expect(res.body.signedUrl).toEqual("http://example.com/foo/bar")
+        expect(res.body.signedUrl).toEqual("http://example.com")
         expect(res.body.publicUrl).toEqual(
           `https://${bucket}.s3.eu-west-1.amazonaws.com/${key}`
         )

From bb5361135cd5d7692a03faa1ea7dd68195bbdaff Mon Sep 17 00:00:00 2001
From: mike12345567 <me@michaeldrury.co.uk>
Date: Thu, 19 Dec 2024 14:41:31 +0000
Subject: [PATCH 05/14] Fixing more test that rely on mocks.

---
 .../src/integrations/tests/aws-sdk.mock.ts    | 76 -------------------
 .../src/integrations/tests/dynamodb.spec.ts   | 24 ++++--
 .../server/src/integrations/tests/s3.spec.ts  | 49 +++++++++++-
 3 files changed, 66 insertions(+), 83 deletions(-)
 delete mode 100644 packages/server/src/integrations/tests/aws-sdk.mock.ts

diff --git a/packages/server/src/integrations/tests/aws-sdk.mock.ts b/packages/server/src/integrations/tests/aws-sdk.mock.ts
deleted file mode 100644
index 0422adfd3c1..00000000000
--- a/packages/server/src/integrations/tests/aws-sdk.mock.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-const response = (body: any, extra?: any) => () => ({
-  promise: () => body,
-  ...extra,
-})
-
-class DocumentClient {
-  put = jest.fn(response({}))
-  query = jest.fn(
-    response({
-      Items: [],
-    })
-  )
-  scan = jest.fn(
-    response({
-      Items: [
-        {
-          Name: "test",
-        },
-      ],
-    })
-  )
-  get = jest.fn(response({}))
-  update = jest.fn(response({}))
-  delete = jest.fn(response({}))
-}
-
-class S3 {
-  listObjects = jest.fn(
-    response({
-      Contents: [],
-    })
-  )
-  createBucket = jest.fn(
-    response({
-      Contents: {},
-    })
-  )
-  deleteObjects = jest.fn(
-    response({
-      Contents: {},
-    })
-  )
-  getSignedUrl = jest.fn((operation, params) => {
-    return `http://example.com/${params.Bucket}/${params.Key}`
-  })
-  headBucket = jest.fn(
-    response({
-      Contents: {},
-    })
-  )
-  upload = jest.fn(
-    response({
-      Contents: {},
-    })
-  )
-  getObject = jest.fn(
-    response(
-      {
-        Body: "",
-      },
-      {
-        createReadStream: jest.fn().mockReturnValue("stream"),
-      }
-    )
-  )
-}
-
-module.exports = {
-  DynamoDB: {
-    DocumentClient,
-  },
-  S3,
-  config: {
-    update: jest.fn(),
-  },
-}
diff --git a/packages/server/src/integrations/tests/dynamodb.spec.ts b/packages/server/src/integrations/tests/dynamodb.spec.ts
index c992bc8bfde..75fb84ae608 100644
--- a/packages/server/src/integrations/tests/dynamodb.spec.ts
+++ b/packages/server/src/integrations/tests/dynamodb.spec.ts
@@ -1,4 +1,20 @@
-jest.mock("aws-sdk", () => require("./aws-sdk.mock"))
+jest.mock("@aws-sdk/lib-dynamodb", () => ({
+  DynamoDBDocument: {
+    from: jest.fn(() => ({
+      update: jest.fn(),
+      put: jest.fn(),
+      query: jest.fn(() => ({
+        Items: [],
+      })),
+      scan: jest.fn(() => ({
+        Items: [],
+      })),
+      delete: jest.fn(),
+      get: jest.fn(),
+    })),
+  },
+}))
+jest.mock("@aws-sdk/client-dynamodb")
 import { default as DynamoDBIntegration } from "../dynamodb"
 
 class TestConfiguration {
@@ -57,11 +73,7 @@ describe("DynamoDB Integration", () => {
       TableName: tableName,
       IndexName: indexName,
     })
-    expect(response).toEqual([
-      {
-        Name: "test",
-      },
-    ])
+    expect(response).toEqual([])
   })
 
   it("calls the get method with the correct params", async () => {
diff --git a/packages/server/src/integrations/tests/s3.spec.ts b/packages/server/src/integrations/tests/s3.spec.ts
index abe8fb9cf13..678f15bf17f 100644
--- a/packages/server/src/integrations/tests/s3.spec.ts
+++ b/packages/server/src/integrations/tests/s3.spec.ts
@@ -1,5 +1,52 @@
-jest.mock("aws-sdk", () => require("./aws-sdk.mock"))
 import { default as S3Integration } from "../s3"
+jest.mock("@aws-sdk/client-s3", () => {
+  class S3Mock {
+    response(body: any, extra?: any) {
+      return () => ({
+        promise: () => body,
+        ...extra,
+      })
+    }
+
+    listObjects = jest.fn(
+      this.response({
+        Contents: [],
+      })
+    )
+    createBucket = jest.fn(
+      this.response({
+        Contents: {},
+      })
+    )
+    deleteObjects = jest.fn(
+      this.response({
+        Contents: {},
+      })
+    )
+    headBucket = jest.fn(
+      this.response({
+        Contents: {},
+      })
+    )
+    upload = jest.fn(
+      this.response({
+        Contents: {},
+      })
+    )
+    getObject = jest.fn(
+      this.response(
+        {
+          Body: "",
+        },
+        {
+          createReadStream: jest.fn().mockReturnValue("stream"),
+        }
+      )
+    )
+  }
+
+  return { S3: S3Mock }
+})
 
 class TestConfiguration {
   integration: any

From cd2286e8cb55c19fe2112e05c6e2b895d1325497 Mon Sep 17 00:00:00 2001
From: mike12345567 <me@michaeldrury.co.uk>
Date: Thu, 19 Dec 2024 14:49:57 +0000
Subject: [PATCH 06/14] removing some extra .promise calls.

---
 .../src/objectStore/objectStore.ts            | 34 +++++++------------
 1 file changed, 13 insertions(+), 21 deletions(-)

diff --git a/packages/backend-core/src/objectStore/objectStore.ts b/packages/backend-core/src/objectStore/objectStore.ts
index 513ad03bb5b..adc974a1316 100644
--- a/packages/backend-core/src/objectStore/objectStore.ts
+++ b/packages/backend-core/src/objectStore/objectStore.ts
@@ -138,30 +138,25 @@ export async function createBucketIfNotExists(
 ): Promise<{ created: boolean; exists: boolean }> {
   bucketName = sanitizeBucket(bucketName)
   try {
-    await // The `.promise()` call might be on an JS SDK v2 client API.
-    // If yes, please remove .promise(). If not, remove this comment.
-    client
-      .headBucket({
-        Bucket: bucketName,
-      })
-      .promise()
+    await client.headBucket({
+      Bucket: bucketName,
+    })
     return { created: false, exists: true }
   } catch (err: any) {
-    const promises: any = STATE.bucketCreationPromises
-    const doesntExist = err.statusCode === 404,
-      noAccess = err.statusCode === 403
+    const statusCode = err.statusCode || err.$response?.statusCode
+    const promises: Record<string, Promise<any> | undefined> =
+      STATE.bucketCreationPromises
+    const doesntExist = statusCode === 404,
+      noAccess = statusCode === 403
     if (promises[bucketName]) {
       await promises[bucketName]
       return { created: false, exists: true }
     } else if (doesntExist || noAccess) {
       if (doesntExist) {
-        promises[bucketName] = // The `.promise()` call might be on an JS SDK v2 client API.
-          // If yes, please remove .promise(). If not, remove this comment.
-          client
-            .createBucket({
-              Bucket: bucketName,
-            })
-            .promise()
+        promises[bucketName] = client.createBucket({
+          Bucket: bucketName,
+        })
+
         await promises[bucketName]
         delete promises[bucketName]
         return { created: true, exists: false }
@@ -474,10 +469,7 @@ export async function deleteFolder(
     Prefix: folder,
   }
 
-  const existingObjectsResponse =
-    await // The `.promise()` call might be on an JS SDK v2 client API.
-    // If yes, please remove .promise(). If not, remove this comment.
-    client.listObjects(listParams)
+  const existingObjectsResponse = await client.listObjects(listParams)
   if (existingObjectsResponse.Contents?.length === 0) {
     return
   }

From 5b4f71ca08fa4090bac2952f4edc769eb33d91b7 Mon Sep 17 00:00:00 2001
From: mike12345567 <me@michaeldrury.co.uk>
Date: Thu, 19 Dec 2024 15:13:19 +0000
Subject: [PATCH 07/14] Fixing mocks in backend-core.

---
 .../__mocks__/@aws-sdk/client-s3.ts           | 33 +++++++++++++++++
 .../@aws-sdk/s3-request-presigner.ts          |  1 +
 packages/backend-core/__mocks__/aws-sdk.ts    | 19 ----------
 .../src/objectStore/buckets/tests/app.spec.ts | 36 -------------------
 4 files changed, 34 insertions(+), 55 deletions(-)
 create mode 100644 packages/backend-core/__mocks__/@aws-sdk/client-s3.ts
 create mode 100644 packages/backend-core/__mocks__/@aws-sdk/s3-request-presigner.ts
 delete mode 100644 packages/backend-core/__mocks__/aws-sdk.ts

diff --git a/packages/backend-core/__mocks__/@aws-sdk/client-s3.ts b/packages/backend-core/__mocks__/@aws-sdk/client-s3.ts
new file mode 100644
index 00000000000..f93b4934933
--- /dev/null
+++ b/packages/backend-core/__mocks__/@aws-sdk/client-s3.ts
@@ -0,0 +1,33 @@
+export class S3 {
+  headBucket() {
+    return jest.fn().mockReturnThis()
+  }
+  deleteObject() {
+    return jest.fn().mockReturnThis()
+  }
+  deleteObjects() {
+    return jest.fn().mockReturnThis()
+  }
+  createBucket() {
+    return jest.fn().mockReturnThis()
+  }
+  getObject() {
+    return jest.fn().mockReturnThis()
+  }
+  listObject() {
+    return jest.fn().mockReturnThis()
+  }
+  getSignedUrl() {
+    return jest.fn((operation: string, params: any) => {
+      return `http://s3.example.com/${params.Bucket}/${params.Key}`
+    })
+  }
+  promise() {
+    return jest.fn().mockReturnThis()
+  }
+  catch() {
+    return jest.fn()
+  }
+}
+
+export const GetObjectCommand = jest.fn()
diff --git a/packages/backend-core/__mocks__/@aws-sdk/s3-request-presigner.ts b/packages/backend-core/__mocks__/@aws-sdk/s3-request-presigner.ts
new file mode 100644
index 00000000000..1a39fd96ae2
--- /dev/null
+++ b/packages/backend-core/__mocks__/@aws-sdk/s3-request-presigner.ts
@@ -0,0 +1 @@
+export const getSignedUrl = jest.fn(() => "http://localhost:10000")
diff --git a/packages/backend-core/__mocks__/aws-sdk.ts b/packages/backend-core/__mocks__/aws-sdk.ts
deleted file mode 100644
index e3be511d082..00000000000
--- a/packages/backend-core/__mocks__/aws-sdk.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-const mockS3 = {
-  headBucket: jest.fn().mockReturnThis(),
-  deleteObject: jest.fn().mockReturnThis(),
-  deleteObjects: jest.fn().mockReturnThis(),
-  createBucket: jest.fn().mockReturnThis(),
-  getObject: jest.fn().mockReturnThis(),
-  listObject: jest.fn().mockReturnThis(),
-  getSignedUrl: jest.fn((operation: string, params: any) => {
-    return `http://s3.example.com/${params.Bucket}/${params.Key}`
-  }),
-  promise: jest.fn().mockReturnThis(),
-  catch: jest.fn(),
-}
-
-const AWS = {
-  S3: jest.fn(() => mockS3),
-}
-
-export default AWS
diff --git a/packages/backend-core/src/objectStore/buckets/tests/app.spec.ts b/packages/backend-core/src/objectStore/buckets/tests/app.spec.ts
index 1aeba8f2c24..d188d774bb2 100644
--- a/packages/backend-core/src/objectStore/buckets/tests/app.spec.ts
+++ b/packages/backend-core/src/objectStore/buckets/tests/app.spec.ts
@@ -93,22 +93,6 @@ describe("app", () => {
         testEnv.multiTenant()
       })
 
-      it("gets url with embedded minio", () => {
-        testEnv.withMinio()
-        const url = getAppFileUrl()
-        expect(url).toBe(
-          "/files/signed/prod-budi-app-assets/app_123/attachments/image.jpeg"
-        )
-      })
-
-      it("gets url with custom S3", () => {
-        testEnv.withS3()
-        const url = getAppFileUrl()
-        expect(url).toBe(
-          "http://s3.example.com/prod-budi-app-assets/app_123/attachments/image.jpeg"
-        )
-      })
-
       it("gets url with cloudfront + s3", async () => {
         testEnv.withCloudfront()
         const url = await getAppFileUrl()
@@ -124,26 +108,6 @@ describe("app", () => {
         testEnv.multiTenant()
       })
 
-      it("gets url with embedded minio", async () => {
-        testEnv.withMinio()
-        await testEnv.withTenant(() => {
-          const url = getAppFileUrl()
-          expect(url).toBe(
-            "/files/signed/prod-budi-app-assets/app_123/attachments/image.jpeg"
-          )
-        })
-      })
-
-      it("gets url with custom S3", async () => {
-        testEnv.withS3()
-        await testEnv.withTenant(() => {
-          const url = getAppFileUrl()
-          expect(url).toBe(
-            "http://s3.example.com/prod-budi-app-assets/app_123/attachments/image.jpeg"
-          )
-        })
-      })
-
       it("gets url with cloudfront + s3", async () => {
         testEnv.withCloudfront()
         await testEnv.withTenant(async () => {

From 6e6c3c7bacb10a6b226307ec268e41fbaa7a5989 Mon Sep 17 00:00:00 2001
From: mike12345567 <me@michaeldrury.co.uk>
Date: Thu, 19 Dec 2024 15:32:54 +0000
Subject: [PATCH 08/14] Fixing another test depending on mock behaviour.

---
 .../objectStore/buckets/tests/global.spec.ts  | 32 +------------------
 1 file changed, 1 insertion(+), 31 deletions(-)

diff --git a/packages/backend-core/src/objectStore/buckets/tests/global.spec.ts b/packages/backend-core/src/objectStore/buckets/tests/global.spec.ts
index be459a7a232..9d5ec07c7a4 100644
--- a/packages/backend-core/src/objectStore/buckets/tests/global.spec.ts
+++ b/packages/backend-core/src/objectStore/buckets/tests/global.spec.ts
@@ -3,7 +3,7 @@ import { testEnv } from "../../../../tests/extra"
 
 describe("global", () => {
   describe("getGlobalFileUrl", () => {
-    function getGlobalFileUrl() {
+    async function getGlobalFileUrl() {
       return global.getGlobalFileUrl("settings", "logoUrl", "etag")
     }
 
@@ -12,18 +12,6 @@ describe("global", () => {
         testEnv.singleTenant()
       })
 
-      it("gets url with embedded minio", () => {
-        testEnv.withMinio()
-        const url = getGlobalFileUrl()
-        expect(url).toBe("/files/signed/global/settings/logoUrl")
-      })
-
-      it("gets url with custom S3", () => {
-        testEnv.withS3()
-        const url = getGlobalFileUrl()
-        expect(url).toBe("http://s3.example.com/global/settings/logoUrl")
-      })
-
       it("gets url with cloudfront + s3", async () => {
         testEnv.withCloudfront()
         const url = await getGlobalFileUrl()
@@ -39,24 +27,6 @@ describe("global", () => {
         testEnv.multiTenant()
       })
 
-      it("gets url with embedded minio", async () => {
-        testEnv.withMinio()
-        await testEnv.withTenant(tenantId => {
-          const url = getGlobalFileUrl()
-          expect(url).toBe(`/files/signed/global/${tenantId}/settings/logoUrl`)
-        })
-      })
-
-      it("gets url with custom S3", async () => {
-        testEnv.withS3()
-        await testEnv.withTenant(tenantId => {
-          const url = getGlobalFileUrl()
-          expect(url).toBe(
-            `http://s3.example.com/global/${tenantId}/settings/logoUrl`
-          )
-        })
-      })
-
       it("gets url with cloudfront + s3", async () => {
         testEnv.withCloudfront()
         await testEnv.withTenant(async tenantId => {

From f9e144f25cd70dfc61e5bb17e39b55eb2b1be276 Mon Sep 17 00:00:00 2001
From: mike12345567 <me@michaeldrury.co.uk>
Date: Thu, 19 Dec 2024 15:43:04 +0000
Subject: [PATCH 09/14] Updating mocks.

---
 packages/backend-core/__mocks__/@aws-sdk/client-s3.ts      | 7 +------
 .../__mocks__/@aws-sdk/s3-request-presigner.ts             | 5 ++++-
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/packages/backend-core/__mocks__/@aws-sdk/client-s3.ts b/packages/backend-core/__mocks__/@aws-sdk/client-s3.ts
index f93b4934933..8f002f41a82 100644
--- a/packages/backend-core/__mocks__/@aws-sdk/client-s3.ts
+++ b/packages/backend-core/__mocks__/@aws-sdk/client-s3.ts
@@ -17,11 +17,6 @@ export class S3 {
   listObject() {
     return jest.fn().mockReturnThis()
   }
-  getSignedUrl() {
-    return jest.fn((operation: string, params: any) => {
-      return `http://s3.example.com/${params.Bucket}/${params.Key}`
-    })
-  }
   promise() {
     return jest.fn().mockReturnThis()
   }
@@ -30,4 +25,4 @@ export class S3 {
   }
 }
 
-export const GetObjectCommand = jest.fn()
+export const GetObjectCommand = jest.fn(inputs => ({ inputs }))
diff --git a/packages/backend-core/__mocks__/@aws-sdk/s3-request-presigner.ts b/packages/backend-core/__mocks__/@aws-sdk/s3-request-presigner.ts
index 1a39fd96ae2..3ed2c10595a 100644
--- a/packages/backend-core/__mocks__/@aws-sdk/s3-request-presigner.ts
+++ b/packages/backend-core/__mocks__/@aws-sdk/s3-request-presigner.ts
@@ -1 +1,4 @@
-export const getSignedUrl = jest.fn(() => "http://localhost:10000")
+export const getSignedUrl = jest.fn((_, cmd) => {
+  const { inputs } = cmd
+  return `http://s3.example.com/${inputs?.Bucket}/${inputs?.Key}`
+})

From 80a77d28a292bf56b7eeb55f13b07abfbe69d0d0 Mon Sep 17 00:00:00 2001
From: mike12345567 <me@michaeldrury.co.uk>
Date: Mon, 6 Jan 2025 17:37:58 +0000
Subject: [PATCH 10/14] PR comment fixes.

---
 .../src/objectStore/buckets/tests/app.spec.ts | 36 +++++++++++++++++++
 .../objectStore/buckets/tests/global.spec.ts  | 30 ++++++++++++++++
 .../src/objectStore/objectStore.ts            | 19 +++++-----
 3 files changed, 77 insertions(+), 8 deletions(-)

diff --git a/packages/backend-core/src/objectStore/buckets/tests/app.spec.ts b/packages/backend-core/src/objectStore/buckets/tests/app.spec.ts
index d188d774bb2..e36b36d39d3 100644
--- a/packages/backend-core/src/objectStore/buckets/tests/app.spec.ts
+++ b/packages/backend-core/src/objectStore/buckets/tests/app.spec.ts
@@ -93,6 +93,22 @@ describe("app", () => {
         testEnv.multiTenant()
       })
 
+      it("gets url with embedded minio", async () => {
+        testEnv.withMinio()
+        const url = await getAppFileUrl()
+        expect(url).toBe(
+          "/files/signed/prod-budi-app-assets/app_123/attachments/image.jpeg"
+        )
+      })
+
+      it("gets url with custom S3", async () => {
+        testEnv.withS3()
+        const url = await getAppFileUrl()
+        expect(url).toBe(
+          "http://s3.example.com/prod-budi-app-assets/app_123/attachments/image.jpeg"
+        )
+      })
+
       it("gets url with cloudfront + s3", async () => {
         testEnv.withCloudfront()
         const url = await getAppFileUrl()
@@ -108,6 +124,26 @@ describe("app", () => {
         testEnv.multiTenant()
       })
 
+      it("gets url with embedded minio", async () => {
+        testEnv.withMinio()
+        await testEnv.withTenant(async () => {
+          const url = await getAppFileUrl()
+          expect(url).toBe(
+            "/files/signed/prod-budi-app-assets/app_123/attachments/image.jpeg"
+          )
+        })
+      })
+
+      it("gets url with custom S3", async () => {
+        testEnv.withS3()
+        await testEnv.withTenant(async () => {
+          const url = await getAppFileUrl()
+          expect(url).toBe(
+            "http://s3.example.com/prod-budi-app-assets/app_123/attachments/image.jpeg"
+          )
+        })
+      })
+
       it("gets url with cloudfront + s3", async () => {
         testEnv.withCloudfront()
         await testEnv.withTenant(async () => {
diff --git a/packages/backend-core/src/objectStore/buckets/tests/global.spec.ts b/packages/backend-core/src/objectStore/buckets/tests/global.spec.ts
index 9d5ec07c7a4..c98d98e0167 100644
--- a/packages/backend-core/src/objectStore/buckets/tests/global.spec.ts
+++ b/packages/backend-core/src/objectStore/buckets/tests/global.spec.ts
@@ -12,6 +12,18 @@ describe("global", () => {
         testEnv.singleTenant()
       })
 
+      it("gets url with embedded minio", async () => {
+        testEnv.withMinio()
+        const url = await getGlobalFileUrl()
+        expect(url).toBe("/files/signed/global/settings/logoUrl")
+      })
+
+      it("gets url with custom S3", async () => {
+        testEnv.withS3()
+        const url = await getGlobalFileUrl()
+        expect(url).toBe("http://s3.example.com/global/settings/logoUrl")
+      })
+
       it("gets url with cloudfront + s3", async () => {
         testEnv.withCloudfront()
         const url = await getGlobalFileUrl()
@@ -27,6 +39,24 @@ describe("global", () => {
         testEnv.multiTenant()
       })
 
+      it("gets url with embedded minio", async () => {
+        testEnv.withMinio()
+        await testEnv.withTenant(async tenantId => {
+          const url = await getGlobalFileUrl()
+          expect(url).toBe(`/files/signed/global/${tenantId}/settings/logoUrl`)
+        })
+      })
+
+      it("gets url with custom S3", async () => {
+        testEnv.withS3()
+        await testEnv.withTenant(async tenantId => {
+          const url = await getGlobalFileUrl()
+          expect(url).toBe(
+            `http://s3.example.com/global/${tenantId}/settings/logoUrl`
+          )
+        })
+      })
+
       it("gets url with cloudfront + s3", async () => {
         testEnv.withCloudfront()
         await testEnv.withTenant(async tenantId => {
diff --git a/packages/backend-core/src/objectStore/objectStore.ts b/packages/backend-core/src/objectStore/objectStore.ts
index adc974a1316..4f07abe7e2a 100644
--- a/packages/backend-core/src/objectStore/objectStore.ts
+++ b/packages/backend-core/src/objectStore/objectStore.ts
@@ -23,6 +23,7 @@ import { v4 } from "uuid"
 import { APP_PREFIX, APP_DEV_PREFIX } from "../db"
 import fsp from "fs/promises"
 import { ReadableStream } from "stream/web"
+import { NodeJsRuntimeStreamingBlobPayloadOutputTypes } from "@smithy/types"
 
 const streamPipeline = promisify(stream.pipeline)
 // use this as a temporary store of buckets that are being created
@@ -194,17 +195,17 @@ export async function upload({
   }
 
   let contentType = type
-  if (!contentType) {
-    contentType = extension
-      ? CONTENT_TYPE_MAP[extension.toLowerCase()]
-      : CONTENT_TYPE_MAP.txt
-  }
+  const finalContentType = contentType
+    ? contentType
+    : extension
+    ? CONTENT_TYPE_MAP[extension.toLowerCase()]
+    : CONTENT_TYPE_MAP.txt
   const config: PutObjectCommandInput = {
     // windows file paths need to be converted to forward slashes for s3
     Bucket: sanitizeBucket(bucketName),
     Key: sanitizeKey(filename),
     Body: fileBytes as stream.Readable | Buffer,
-    ContentType: contentType!,
+    ContentType: finalContentType,
   }
   if (metadata && typeof metadata === "object") {
     // remove any nullish keys from the metadata object, as these may be considered invalid
@@ -310,11 +311,13 @@ export async function retrieve(
   if (!response.Body) {
     throw new Error("Unable to retrieve object")
   }
+  const nodeResponse =
+    response.Body as NodeJsRuntimeStreamingBlobPayloadOutputTypes
   // currently these are all strings
   if (STRING_CONTENT_TYPES.includes(response.ContentType)) {
-    return response.Body.toString()
+    return nodeResponse.toString()
   } else {
-    return response.Body as stream.Readable
+    return nodeResponse
   }
 }
 

From 766d095c9c3b38d34bd09bd0b6fce635e990a690 Mon Sep 17 00:00:00 2001
From: mike12345567 <me@michaeldrury.co.uk>
Date: Mon, 6 Jan 2025 17:53:14 +0000
Subject: [PATCH 11/14] Adding dependency.

---
 packages/backend-core/package.json |  1 +
 yarn.lock                          | 44 ++++++++++++++++++++++++++----
 2 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json
index 4339ee0a949..b380fca017c 100644
--- a/packages/backend-core/package.json
+++ b/packages/backend-core/package.json
@@ -74,6 +74,7 @@
   "devDependencies": {
     "@jest/types": "^29.6.3",
     "@shopify/jest-koa-mocks": "5.1.1",
+    "@smithy/types": "4.0.0",
     "@swc/core": "1.3.71",
     "@swc/jest": "0.2.27",
     "@types/chance": "1.1.3",
diff --git a/yarn.lock b/yarn.lock
index 599f5cdf2fa..fbae35bf368 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2778,9 +2778,9 @@
     through2 "^2.0.0"
 
 "@budibase/pro@npm:@budibase/pro@latest":
-  version "3.2.28"
-  resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.2.28.tgz#59b5b37225715bb8fbf5b1c5c989140b10b58710"
-  integrity sha512-eDPeZpYFRZYQhCulcQAUwFoPk68c8+K9mIsB6QD3oMHmHTDA1P2ZcXvLNqDTIqHB94DqnWinqDf4hTuGYApgPA==
+  version "3.2.32"
+  resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.2.32.tgz#f6abcd5a5524e7f33d958acb6e610e29995427bb"
+  integrity sha512-bF0pd17IjYugjll2yKYmb0RM+tfKZcCmRBc4XG2NZ4f/I47QaOovm9RqSw6tfqCFuzRewxR3SWmtmSseUc/e0w==
   dependencies:
     "@anthropic-ai/sdk" "^0.27.3"
     "@budibase/backend-core" "*"
@@ -5512,6 +5512,13 @@
     "@smithy/util-stream" "^3.3.2"
     tslib "^2.6.2"
 
+"@smithy/types@4.0.0":
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/@smithy/types/-/types-4.0.0.tgz#7458c1c4dde3c6cf23221370acf5acd03215de6e"
+  integrity sha512-aNwIGSOgDOhtTRY/rrn2aeuQeKw/IFrQ998yK5l6Ah853WeWIEmFPs/EO4OpfADEdcK+igWnZytm/oUgkLgUYg==
+  dependencies:
+    tslib "^2.6.2"
+
 "@smithy/types@^1.2.0":
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/@smithy/types/-/types-1.2.0.tgz#9dc65767b0ee3d6681704fcc67665d6fc9b6a34e"
@@ -19709,7 +19716,16 @@ string-length@^4.0.1:
     char-regex "^1.0.2"
     strip-ansi "^6.0.0"
 
-"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
+"string-width-cjs@npm:string-width@^4.2.0":
+  version "4.2.3"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+  integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+  dependencies:
+    emoji-regex "^8.0.0"
+    is-fullwidth-code-point "^3.0.0"
+    strip-ansi "^6.0.1"
+
+"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
   version "4.2.3"
   resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
   integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -19801,7 +19817,7 @@ stringify-object@^3.2.1:
     is-obj "^1.0.1"
     is-regexp "^1.0.0"
 
-"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
   version "6.0.1"
   resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
   integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -19815,6 +19831,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
   dependencies:
     ansi-regex "^4.1.0"
 
+strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+  version "6.0.1"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+  integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+  dependencies:
+    ansi-regex "^5.0.1"
+
 strip-ansi@^7.0.1:
   version "7.0.1"
   resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2"
@@ -21562,7 +21585,7 @@ worker-farm@1.7.0:
   dependencies:
     errno "~0.1.7"
 
-"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
   version "7.0.0"
   resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
   integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -21580,6 +21603,15 @@ wrap-ansi@^5.1.0:
     string-width "^3.0.0"
     strip-ansi "^5.0.0"
 
+wrap-ansi@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+  integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+  dependencies:
+    ansi-styles "^4.0.0"
+    string-width "^4.1.0"
+    strip-ansi "^6.0.0"
+
 wrap-ansi@^8.1.0:
   version "8.1.0"
   resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"

From d7b1b1a3671f7bab4f80cd825c4a8e98bc6cde03 Mon Sep 17 00:00:00 2001
From: Adria Navarro <adria@budibase.com>
Date: Tue, 7 Jan 2025 16:52:01 +0100
Subject: [PATCH 12/14] Fix issues when fetching view v1 data

---
 packages/client/src/api/patches.js            | 4 ++--
 packages/frontend-core/src/fetch/ViewFetch.js | 8 +++++++-
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/packages/client/src/api/patches.js b/packages/client/src/api/patches.js
index 5413379b72a..9203ac3c70f 100644
--- a/packages/client/src/api/patches.js
+++ b/packages/client/src/api/patches.js
@@ -85,9 +85,9 @@ export const patchAPI = API => {
     }
   }
   const fetchViewData = API.fetchViewData
-  API.fetchViewData = async params => {
+  API.fetchViewData = async (viewName, params) => {
     const tableId = params?.tableId
-    const rows = await fetchViewData(params)
+    const rows = await fetchViewData(viewName, params)
     return await enrichRows(rows, tableId)
   }
 
diff --git a/packages/frontend-core/src/fetch/ViewFetch.js b/packages/frontend-core/src/fetch/ViewFetch.js
index 272c222dd46..eb89f9b67a8 100644
--- a/packages/frontend-core/src/fetch/ViewFetch.js
+++ b/packages/frontend-core/src/fetch/ViewFetch.js
@@ -8,9 +8,15 @@ export default class ViewFetch extends DataFetch {
   async getData() {
     const { datasource } = this.options
     try {
-      const res = await this.API.fetchViewData(datasource.name)
+      const res = await this.API.fetchViewData(datasource.name, {
+        calculation: datasource.calculation,
+        field: datasource.field,
+        groupBy: datasource.groupBy,
+        tableId: datasource.tableId,
+      })
       return { rows: res || [] }
     } catch (error) {
+      console.error(error)
       return { rows: [] }
     }
   }

From 64471bd7337ede6fbc598cd7806728858474b569 Mon Sep 17 00:00:00 2001
From: Andrew Kingston <andrew@kingston.dev>
Date: Tue, 7 Jan 2025 17:12:56 +0000
Subject: [PATCH 13/14] Fix enrich endpoint in client

---
 packages/client/src/api/patches.js | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/packages/client/src/api/patches.js b/packages/client/src/api/patches.js
index 5413379b72a..6ea3b7c1831 100644
--- a/packages/client/src/api/patches.js
+++ b/packages/client/src/api/patches.js
@@ -66,10 +66,9 @@ export const patchAPI = API => {
     }
   }
   const fetchRelationshipData = API.fetchRelationshipData
-  API.fetchRelationshipData = async params => {
-    const tableId = params?.tableId
-    const rows = await fetchRelationshipData(params)
-    return await enrichRows(rows, tableId)
+  API.fetchRelationshipData = async (sourceId, rowId, fieldName) => {
+    const rows = await fetchRelationshipData(sourceId, rowId, fieldName)
+    return await enrichRows(rows, sourceId)
   }
   const fetchTableData = API.fetchTableData
   API.fetchTableData = async tableId => {

From 21bfb7a45da8b1b615c100d8d52d0e991e24eae5 Mon Sep 17 00:00:00 2001
From: Budibase Staging Release Bot <>
Date: Tue, 7 Jan 2025 17:47:14 +0000
Subject: [PATCH 14/14] Bump version to 3.2.34

---
 lerna.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lerna.json b/lerna.json
index 3afc2c60e97..bc3f3419793 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,6 +1,6 @@
 {
   "$schema": "node_modules/lerna/schemas/lerna-schema.json",
-  "version": "3.2.33",
+  "version": "3.2.34",
   "npmClient": "yarn",
   "concurrency": 20,
   "command": {