diff --git a/.env.template b/.env.template index 41414d81f5..8ba10e9c11 100644 --- a/.env.template +++ b/.env.template @@ -52,3 +52,9 @@ SEPAL_PASSWORD="password" GEE_PRIVATE_KEY='private key json content' FRA_MAIL_ENABLED=false + +# File S3 +AWS_ACCESS_KEY_ID=your-access-key-id +AWS_SECRET_ACCESS_KEY=your-secret-access-key +AWS_REGION=eu-west-1 +S3_BUCKET_NAME=fra-platform-s3 diff --git a/package.json b/package.json index cfe0e9c307..69a798f270 100644 --- a/package.json +++ b/package.json @@ -158,6 +158,7 @@ "webpack-dev-server": "^4.7.4" }, "dependencies": { + "@aws-sdk/client-s3": "^3.637.0", "@google/earthengine": "^0.1.316", "@googlemaps/js-api-loader": "^1.13.10", "@googlemaps/react-wrapper": "^1.1.29", diff --git a/src/meta/file/file.ts b/src/meta/file/file.ts index cb2ab0a2c3..8d99a04519 100644 --- a/src/meta/file/file.ts +++ b/src/meta/file/file.ts @@ -1,16 +1,18 @@ +import { Readable } from 'stream' + import { Label } from 'meta/assessment' export type FileSummary = { readonly createdAt: string readonly id: number readonly name: string - readonly size: number + size: number readonly uuid: string readonly repositoryItemUuid: string } export type File = FileSummary & { - readonly file: Buffer + file: Readable } export type FileUsage = { diff --git a/src/meta/user/userProfilePicture.ts b/src/meta/user/userProfilePicture.ts index acc700f446..91d6b28194 100644 --- a/src/meta/user/userProfilePicture.ts +++ b/src/meta/user/userProfilePicture.ts @@ -1,4 +1,7 @@ +import { Readable } from 'stream' + export interface UserProfilePicture { name: string - data: string + uuid: string + data?: Readable } diff --git a/src/server/api/cycleData/print/report.ts b/src/server/api/cycleData/print/report.ts index 4c8fcfd666..9f703d53ea 100644 --- a/src/server/api/cycleData/print/report.ts +++ b/src/server/api/cycleData/print/report.ts @@ -75,7 +75,14 @@ const getPdf = async (req: Request, fileName: string): Promise => { return pdfBuffer } - return cachedPdfInfo.file.file + // Convert Readable to Buffer + const chunks = [] + // eslint-disable-next-line no-restricted-syntax + for await (const chunk of cachedPdfInfo.file.file) { + chunks.push(chunk) + } + + return Buffer.concat(chunks) } export const report = async (req: Request, res: Response) => { diff --git a/src/server/api/cycleData/repository/getRepositoryFile.ts b/src/server/api/cycleData/repository/getRepositoryFile.ts index 5d5a123325..0e71ef10d2 100644 --- a/src/server/api/cycleData/repository/getRepositoryFile.ts +++ b/src/server/api/cycleData/repository/getRepositoryFile.ts @@ -6,6 +6,7 @@ import { Translations } from 'meta/translation' import { AssessmentController } from 'server/controller/assessment' import { CycleDataController } from 'server/controller/cycleData' +import { FileStorage, FileStorageUtils } from 'server/service/fileStorage' import Requests from 'server/utils/requests' import { Responses } from 'server/utils/responses' @@ -26,7 +27,10 @@ export const getRepositoryFile = async (req: Request, res: Response) => { const extension = file.name.split('.').pop() const fileName = `${label}.${extension}` - Responses.sendFile(res, fileName, file.file) + const key = repositoryItem.fileUuid + const fileStream = await FileStorage.getFile({ key }) + + Responses.sendFileStream(res, fileName, fileStream, FileStorageUtils.getContentType(extension)) } catch (e) { Requests.sendErr(res, e) } diff --git a/src/server/api/file/get.ts b/src/server/api/file/get.ts index 61ce74a459..35cf064be0 100644 --- a/src/server/api/file/get.ts +++ b/src/server/api/file/get.ts @@ -1,6 +1,6 @@ import { Request, Response } from 'express' -import { FileRepository, fileTypes } from 'server/service/file' +import { FileRepository, fileTypes } from 'server/service/file_deprecated' type Query = { countryIso: string diff --git a/src/server/api/file/getBiomassStockFile.ts b/src/server/api/file/getBiomassStockFile.ts index be783f4482..dd61af2eaf 100644 --- a/src/server/api/file/getBiomassStockFile.ts +++ b/src/server/api/file/getBiomassStockFile.ts @@ -2,7 +2,7 @@ import { Response } from 'express' import { BiomassStockFileRequest } from 'meta/api/request' -import { FileRepository, fileTypes } from 'server/service/file' +import { FileRepository, fileTypes } from 'server/service/file_deprecated' import { Requests } from 'server/utils' export const getBiomassStockFile = async (req: BiomassStockFileRequest, res: Response) => { diff --git a/src/server/api/file/getDataDownloadFile.ts b/src/server/api/file/getDataDownloadFile.ts index f9620ca323..18fb692c1c 100644 --- a/src/server/api/file/getDataDownloadFile.ts +++ b/src/server/api/file/getDataDownloadFile.ts @@ -2,7 +2,7 @@ import { Response } from 'express' import { CycleRequest } from 'meta/api/request' -import { FileRepository, fileTypes } from 'server/service/file' +import { FileRepository, fileTypes } from 'server/service/file_deprecated' type Request = CycleRequest<{ fileName: string diff --git a/src/server/api/file/getSdgMetadata.ts b/src/server/api/file/getSdgMetadata.ts index a851427478..6241cbb738 100644 --- a/src/server/api/file/getSdgMetadata.ts +++ b/src/server/api/file/getSdgMetadata.ts @@ -3,7 +3,7 @@ import { Response } from 'express' import { CycleDataRequest } from 'meta/api/request' import { Lang } from 'meta/lang' -import { FileRepository, fileTypes } from 'server/service/file' +import { FileRepository, fileTypes } from 'server/service/file_deprecated' import { Requests } from 'server/utils' type Request = CycleDataRequest<{ key: 'Metadata-15-01-01' | 'Metadata-15-02-01' }> diff --git a/src/server/api/file/getUserGuide.ts b/src/server/api/file/getUserGuide.ts index f266acb3bd..ffc0693d8c 100644 --- a/src/server/api/file/getUserGuide.ts +++ b/src/server/api/file/getUserGuide.ts @@ -1,6 +1,6 @@ import { Request, Response } from 'express' -import { FileRepository, fileTypes } from 'server/service/file' +import { FileRepository, fileTypes } from 'server/service/file_deprecated' type Query = { language: string diff --git a/src/server/api/user/getProfilePicture.ts b/src/server/api/user/getProfilePicture.ts index 8ec91efb6c..372cd16c58 100644 --- a/src/server/api/user/getProfilePicture.ts +++ b/src/server/api/user/getProfilePicture.ts @@ -1,14 +1,15 @@ -import { Request, Response } from 'express' import * as path from 'path' -import Requests from 'server/utils/requests' +import { Request, Response } from 'express' + import { UserController } from 'server/controller/user' +import Requests from 'server/utils/requests' export const getProfilePicture = async (req: Request, res: Response) => { const { id } = req.params try { const profilePicture = await UserController.getProfilePicture({ id: Number(id) }) if (profilePicture && profilePicture.data) { - res.end(profilePicture.data, 'binary') + profilePicture.data.pipe(res) } else { res.sendFile(path.resolve(__dirname, '..', '..', 'static', 'avatar.png')) } diff --git a/src/server/controller/cycleData/report/create.ts b/src/server/controller/cycleData/report/create.ts index 25b78c8e80..da87a64cb4 100644 --- a/src/server/controller/cycleData/report/create.ts +++ b/src/server/controller/cycleData/report/create.ts @@ -6,6 +6,7 @@ import { FileSummary } from 'meta/file' import { BaseProtocol, DB } from 'server/db' import { RepositoryRepository } from 'server/repository/assessmentCycle/repository' import { FileRepository } from 'server/repository/public/file' +import { FileStorage } from 'server/service/fileStorage' import { bufferToPdfMulterFile } from './utils' @@ -30,7 +31,10 @@ export const create = async (props: Props): Promise => { const pdfMulterFile = bufferToPdfMulterFile({ buffer, fileName }) return DB.tx(async (t: BaseProtocol) => { - const file = await FileRepository.create({ file: pdfMulterFile }, t) + const file = await FileRepository.create({ fileName: pdfMulterFile.originalname }, t) + const { uuid: key } = file + const body = pdfMulterFile.buffer + await FileStorage.uploadFile({ key, body }) const repositoryItemProps: Partial = { countryIso, diff --git a/src/server/controller/cycleData/report/getOne.ts b/src/server/controller/cycleData/report/getOne.ts index e8e5f5b0ab..92ee80b2e2 100644 --- a/src/server/controller/cycleData/report/getOne.ts +++ b/src/server/controller/cycleData/report/getOne.ts @@ -6,6 +6,7 @@ import { File } from 'meta/file' import { RepositoryRepository } from 'server/repository/assessmentCycle/repository' import { FileRepository } from 'server/repository/public/file' +import { FileStorage } from 'server/service/fileStorage' type Props = { assessment: Assessment @@ -25,7 +26,10 @@ export const getOne = async (props: Props): Promise => { const repositoryItem = await RepositoryRepository.getOne(props) const fileRepositoryProps = { fileUuid: repositoryItem.fileUuid } - const file = await FileRepository.getOne(fileRepositoryProps) + const fileSummary = await FileRepository.getOne(fileRepositoryProps) + const { uuid: key } = fileSummary + const fileData = await FileStorage.getFile({ key }) + const file = { ...fileSummary, file: fileData } return { file, repositoryItem } } catch (error) { diff --git a/src/server/controller/cycleData/report/updateFile.ts b/src/server/controller/cycleData/report/updateFile.ts index 4b9b9d2acc..57700efd18 100644 --- a/src/server/controller/cycleData/report/updateFile.ts +++ b/src/server/controller/cycleData/report/updateFile.ts @@ -6,6 +6,7 @@ import { FileSummary } from 'meta/file' import { BaseProtocol, DB } from 'server/db' import { RepositoryRepository } from 'server/repository/assessmentCycle/repository' import { FileRepository } from 'server/repository/public/file' +import { FileStorage } from 'server/service/fileStorage' import { bufferToPdfMulterFile } from './utils' @@ -30,7 +31,10 @@ export const updateFile = async (props: Props): Promise => { const repositoryItem = await RepositoryRepository.getOne(getRepositoryItemProps, t) const pdfMulterFile = bufferToPdfMulterFile({ buffer, fileName }) - const newFile = await FileRepository.create({ file: pdfMulterFile }, t) + const newFile = await FileRepository.create({ fileName: pdfMulterFile.originalname }, t) + const { uuid: key } = newFile + const body = pdfMulterFile.buffer + await FileStorage.uploadFile({ key, body }) const updateRepositoryItemProps: RepositoryItem = { ...repositoryItem, fileUuid: newFile.uuid } const updateRepositoryProps = { assessment, cycle, repositoryItem: updateRepositoryItemProps } diff --git a/src/server/controller/cycleData/repository/getFileMeta.ts b/src/server/controller/cycleData/repository/getFileMeta.ts index e7863a7e6c..832a77f4b5 100644 --- a/src/server/controller/cycleData/repository/getFileMeta.ts +++ b/src/server/controller/cycleData/repository/getFileMeta.ts @@ -3,6 +3,7 @@ import { FileMeta } from 'meta/file' import { RepositoryRepository } from 'server/repository/assessmentCycle/repository' import { FileRepository } from 'server/repository/public/file' +import { FileStorage } from 'server/service/fileStorage' type Props = { assessment: Assessment @@ -24,6 +25,8 @@ export const getFileMeta = async (props: Props): Promise => { FileRepository.getSummary({ fileUuid: repositoryItem.fileUuid }), ]) + summary.size = await FileStorage.getFileSize({ key: repositoryItem.fileUuid }) + return { usages, summary: { ...summary, repositoryItemUuid: repositoryItem.uuid }, diff --git a/src/server/controller/cycleData/repository/getManyFiles.ts b/src/server/controller/cycleData/repository/getManyFiles.ts index dee5e4ce47..11d38f57a2 100644 --- a/src/server/controller/cycleData/repository/getManyFiles.ts +++ b/src/server/controller/cycleData/repository/getManyFiles.ts @@ -1,3 +1,5 @@ +import { Readable } from 'stream' + import { CountryIso } from 'meta/area' import { Assessment, Cycle } from 'meta/assessment' import { Lang } from 'meta/lang' @@ -5,6 +7,7 @@ import { Translations } from 'meta/translation' import { RepositoryRepository } from 'server/repository/assessmentCycle/repository' import { FileRepository } from 'server/repository/public/file' +import { FileStorage } from 'server/service/fileStorage' type Props = { assessment: Assessment @@ -15,7 +18,7 @@ type Props = { type Returned = Array<{ fileName: string - file: Buffer + file: Readable }> export const getManyFiles = async (props: Props): Promise => { @@ -27,6 +30,12 @@ export const getManyFiles = async (props: Props): Promise => { const repositoryProps = { fileUuids: repositoryItems.map((item) => item.fileUuid) } const files = await FileRepository.getMany(repositoryProps) + // eslint-disable-next-line no-restricted-syntax + for await (const file of files) { + const { uuid: key } = file + file.file = await FileStorage.getFile({ key }) + } + return files.map((file) => { const repositoryItem = repositoryItems.find((item) => item.fileUuid === file.uuid) const label = Translations.getLabel({ translation: repositoryItem.props.translation, language: Lang.en }) diff --git a/src/server/controller/file/createMany.ts b/src/server/controller/file/createMany.ts index 41beb1c06e..d9cf745c23 100644 --- a/src/server/controller/file/createMany.ts +++ b/src/server/controller/file/createMany.ts @@ -5,6 +5,7 @@ import { User } from 'meta/user' import { BaseProtocol, DB } from 'server/db' import { ActivityLogRepository } from 'server/repository/public/activityLog' import { FileRepository } from 'server/repository/public/file' +import { FileStorage } from 'server/service/fileStorage' type Props = { assessment: Assessment @@ -19,9 +20,14 @@ export const createMany = async (props: Props, client: BaseProtocol = DB): Promi return client.tx(async (t) => { return Promise.all( files.map(async (multerFile) => { - const file = await FileRepository.create({ ...props, file: multerFile }, t) + const fileName = multerFile.originalname + const file = await FileRepository.create({ ...props, fileName }, t) + const { uuid } = file + const key = uuid + const body = multerFile.buffer + await FileStorage.uploadFile({ key, body }) - const target = { fileName: file.name, uuid: file.uuid } + const target = { fileName, uuid } const message = ActivityLogMessage.fileCreate const activityLog = { target, section: 'assessment', message, user } const activityLogParams = { activityLog, assessment, cycle } diff --git a/src/server/controller/user/getProfilePicture.ts b/src/server/controller/user/getProfilePicture.ts new file mode 100644 index 0000000000..a4a3d566d1 --- /dev/null +++ b/src/server/controller/user/getProfilePicture.ts @@ -0,0 +1,21 @@ +import { UserProfilePicture } from 'meta/user/userProfilePicture' + +import { BaseProtocol, DB } from 'server/db' +import { UserRepository } from 'server/repository/public/user' +import { FileStorage } from 'server/service/fileStorage' + +export const getProfilePicture = async ( + props: { + id: number + }, + client: BaseProtocol = DB +): Promise => { + const { id } = props + const userProfilePicture = await UserRepository.getProfilePicture({ id }, client) + const key = userProfilePicture.uuid + const data = await FileStorage.getFile({ key }) + return { + ...userProfilePicture, + data, + } +} diff --git a/src/server/controller/user/index.ts b/src/server/controller/user/index.ts index 3841b75965..bac0c1cc7c 100644 --- a/src/server/controller/user/index.ts +++ b/src/server/controller/user/index.ts @@ -8,6 +8,7 @@ import { create } from './create' import { createResetPassword } from './createResetPassword' import { findByInvitation } from './findByInvitation' import { findByResetPassword } from './findByResetPassword' +import { getProfilePicture } from './getProfilePicture' import { invite } from './invite' import { remove } from './remove' import { removeInvitation } from './removeInvitation' @@ -24,7 +25,7 @@ export const UserController = { getManyInvitations: UserInvitationRepository.getMany, getCountInvitations: UserInvitationRepository.getCount, getOne: UserRepository.getOne, - getProfilePicture: UserRepository.getProfilePicture, + getProfilePicture, remove, invite, acceptInvitation, diff --git a/src/server/controller/user/update.ts b/src/server/controller/user/update.ts index 913a4c1f9c..8841e87eb1 100644 --- a/src/server/controller/user/update.ts +++ b/src/server/controller/user/update.ts @@ -5,6 +5,7 @@ import { BaseProtocol, DB } from 'server/db' import { ActivityLogRepository } from 'server/repository/public/activityLog' import { FileRepository } from 'server/repository/public/file' import { UserRepository } from 'server/repository/public/user' +import { FileStorage } from 'server/service/fileStorage' export const update = async ( props: { @@ -18,7 +19,10 @@ export const update = async ( return client.tx(async (t) => { if (profilePicture) { - const createdFile = await FileRepository.create({ file: profilePicture }, client) + const createdFile = await FileRepository.create({ fileName: profilePicture.originalname }, client) + const { uuid: key } = createdFile + + await FileStorage.uploadFile({ key, body: profilePicture.buffer }) userToUpdate.profilePictureFileUuid = createdFile.uuid } diff --git a/src/server/repository/adapter/file.ts b/src/server/repository/adapter/file.ts index d504cc24db..e84f6fd89b 100644 --- a/src/server/repository/adapter/file.ts +++ b/src/server/repository/adapter/file.ts @@ -4,7 +4,6 @@ import { File } from 'meta/file' export type FileDB = { created_at: string - file?: Buffer id: number name: string size: number @@ -12,10 +11,5 @@ export type FileDB = { } export const FileAdapter = (fileDB: FileDB): File => { - const { file, ...rest } = fileDB - - return { - ...Objects.camelize(rest), - file, - } + return Objects.camelize(fileDB) } diff --git a/src/server/repository/public/file/create.ts b/src/server/repository/public/file/create.ts index c85f346661..bc353c5e29 100644 --- a/src/server/repository/public/file/create.ts +++ b/src/server/repository/public/file/create.ts @@ -6,18 +6,18 @@ import { FileAdapter } from 'server/repository/adapter' import { fieldsFileSummary } from './fields' type Props = { - file: Express.Multer.File + fileName: string } export const create = async (props: Props, client: BaseProtocol = DB): Promise => { - const { file } = props + const { fileName } = props return client.one( ` - insert into public.file (name, file) - values ($1, $2) + insert into public.file (name) + values ($1) returning ${fieldsFileSummary.join(', ')}`, - [file.originalname, file.buffer], + [fileName], FileAdapter ) } diff --git a/src/server/repository/public/file/fields.ts b/src/server/repository/public/file/fields.ts index 253e3669a7..3749db13c7 100644 --- a/src/server/repository/public/file/fields.ts +++ b/src/server/repository/public/file/fields.ts @@ -1,2 +1 @@ -export const fieldsFileSummary = ['id', 'name', 'uuid', 'created_at', 'length(file) as size'] -export const fieldsFile = [...fieldsFileSummary, 'file'] +export const fieldsFileSummary = ['id', 'name', 'uuid', 'created_at'] diff --git a/src/server/repository/public/file/getMany.ts b/src/server/repository/public/file/getMany.ts index f52f824fe2..e4924b9238 100644 --- a/src/server/repository/public/file/getMany.ts +++ b/src/server/repository/public/file/getMany.ts @@ -2,7 +2,7 @@ import type { File } from 'meta/file' import { BaseProtocol, DB } from 'server/db' import { FileAdapter } from 'server/repository/adapter' -import { fieldsFile } from 'server/repository/public/file/fields' +import { fieldsFileSummary } from 'server/repository/public/file/fields' type Props = { fileUuids: Array @@ -13,7 +13,7 @@ export const getMany = async (props: Props, client: BaseProtocol = DB): Promise< return client.map( ` - select ${fieldsFile.join(', ')} + select ${fieldsFileSummary.join(', ')} from public.file where uuid in ($1:list) `, diff --git a/src/server/repository/public/file/getOne.ts b/src/server/repository/public/file/getOne.ts index ddf4b30963..f8bb09bc27 100644 --- a/src/server/repository/public/file/getOne.ts +++ b/src/server/repository/public/file/getOne.ts @@ -2,7 +2,7 @@ import type { File } from 'meta/file' import { BaseProtocol, DB } from 'server/db' import { FileAdapter } from 'server/repository/adapter' -import { fieldsFile } from 'server/repository/public/file/fields' +import { fieldsFileSummary } from 'server/repository/public/file/fields' type Props = | { @@ -16,7 +16,7 @@ export const getOne = async (props: Props, client: BaseProtocol = DB): Promise( ` - select f.file as data, f.name + select f.uuid, f.name from public.users u left join file f on u.profile_picture_file_uuid = f.uuid ${where} diff --git a/src/server/service/fileStorage/fileStorage.ts b/src/server/service/fileStorage/fileStorage.ts new file mode 100644 index 0000000000..98c7eb18f9 --- /dev/null +++ b/src/server/service/fileStorage/fileStorage.ts @@ -0,0 +1,77 @@ +import { Readable } from 'stream' +import { GetObjectCommand, HeadObjectCommand, PutObjectCommand, S3Client } from '@aws-sdk/client-s3' + +import { ProcessEnv } from 'server/utils' + +const s3Client = new S3Client({ + region: ProcessEnv.awsRegion, + credentials: { + accessKeyId: ProcessEnv.awsAccessKeyId, + secretAccessKey: ProcessEnv.awsSecretAccessKey, + }, +}) + +const getFile = async (props: { key: string; bucket?: string; path?: string }): Promise => { + const { key, bucket = ProcessEnv.s3BucketName, path = 'public' } = props + const command = new GetObjectCommand({ + Bucket: bucket, + Key: `${path}/${key}`, + }) + + const response = await s3Client.send(command) + return response.Body as Readable +} + +const uploadFile = async (props: { + key: string + body: Buffer | Readable + bucket?: string + contentType?: string + path?: string +}): Promise => { + const { key, body, bucket = ProcessEnv.s3BucketName, contentType, path = 'public' } = props + const command = new PutObjectCommand({ + Bucket: bucket, + Key: `${path}/${key}`, + Body: body, + ContentType: contentType, + }) + + await s3Client.send(command) +} + +const getFileSize = async (props: { key: string; bucket?: string; path?: string }): Promise => { + const { key, bucket = ProcessEnv.s3BucketName, path = 'public' } = props + const command = new HeadObjectCommand({ + Bucket: bucket, + Key: `${path}/${key}`, + }) + + const response = await s3Client.send(command) + return response.ContentLength || 0 +} + +const fileExists = async (props: { key: string; bucket?: string; path?: string }): Promise => { + const { key, bucket = ProcessEnv.s3BucketName, path = 'public' } = props + const command = new HeadObjectCommand({ + Bucket: bucket, + Key: `${path}/${key}`, + }) + + try { + await s3Client.send(command) + return true + } catch (error) { + if (error.name === 'NotFound') { + return false + } + throw error + } +} + +export const FileStorage = { + getFile, + uploadFile, + getFileSize, + fileExists, +} diff --git a/src/server/service/fileStorage/fileStorageUtils.ts b/src/server/service/fileStorage/fileStorageUtils.ts new file mode 100644 index 0000000000..b697fa51bd --- /dev/null +++ b/src/server/service/fileStorage/fileStorageUtils.ts @@ -0,0 +1,27 @@ +const mimeTypes: Record = { + zip: 'application/zip', + xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + xlsm: 'application/vnd.ms-excel.sheet.macroEnabled.12', + xls: 'application/vnd.ms-excel', + tsv: 'text/tab-separated-values', + pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + png: 'image/png', + pdf: 'application/pdf', + jpg: 'image/jpeg', + jpeg: 'image/jpeg', + jfif: 'image/jpeg', + gif: 'image/gif', + docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + doc: 'application/msword', + csv: 'text/csv', + crdownload: 'application/octet-stream', + bmp: 'image/bmp', +} + +function getContentType(extension: string): string { + return mimeTypes[extension] || 'application/octet-stream' +} + +export const FileStorageUtils = { + getContentType, +} diff --git a/src/server/service/fileStorage/index.ts b/src/server/service/fileStorage/index.ts new file mode 100644 index 0000000000..a23e9d79d3 --- /dev/null +++ b/src/server/service/fileStorage/index.ts @@ -0,0 +1,2 @@ +export { FileStorage } from './fileStorage' +export { FileStorageUtils } from './fileStorageUtils' diff --git a/src/server/service/file/index.ts b/src/server/service/file_deprecated/index.ts similarity index 100% rename from src/server/service/file/index.ts rename to src/server/service/file_deprecated/index.ts diff --git a/src/server/utils/processEnv.ts b/src/server/utils/processEnv.ts index 85aad3f34b..0bbed85246 100644 --- a/src/server/utils/processEnv.ts +++ b/src/server/utils/processEnv.ts @@ -21,6 +21,12 @@ export const ProcessEnv = { appUri: process.env.APP_URI ?? 'http://localhost:9001', port: process.env.PORT ? Number(process.env.PORT) : 80, + // aws/s3 + awsAccessKeyId: process.env.AWS_ACCESS_KEY_ID, + awsRegion: process.env.AWS_REGION, + awsSecretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, + s3BucketName: process.env.S3_BUCKET_NAME, + // dev debug: process.env.DEBUG === 'true', nodeEnv: process.env.NODE_ENV || NodeEnv.development, diff --git a/src/server/utils/responses.ts b/src/server/utils/responses.ts index 1db3975801..ae8565ef82 100644 --- a/src/server/utils/responses.ts +++ b/src/server/utils/responses.ts @@ -1,3 +1,4 @@ +import { Readable } from 'stream' import { Response } from 'express' import * as JSZip from 'jszip' @@ -13,7 +14,7 @@ const sendFile = (res: Response, fileName: string, file: Buffer): void => { } } -const sendZip = async (res: Response, files: Array<{ fileName: string; file: Buffer }>): Promise => { +const sendZip = async (res: Response, files: Array<{ fileName: string; file: Readable }>): Promise => { const zip = new JSZip() files.forEach(({ fileName, file }) => { @@ -28,7 +29,15 @@ const sendZip = async (res: Response, files: Array<{ fileName: string; file: Buf res.end(zipFile) } +const sendFileStream = (res: Response, fileName: string, stream: Readable, contentType?: string): void => { + const _fileName = encodeURIComponent(fileName) + res.setHeader('Content-Disposition', `attachment; filename="${_fileName}"; filename*=utf-8''${_fileName}`) + res.setHeader('Content-Type', contentType || 'application/octet-stream') + stream.pipe(res) +} + export const Responses = { sendFile, sendZip, + sendFileStream, } diff --git a/src/test/migrations/steps/20240829112027-step-files-to-s3.ts b/src/test/migrations/steps/20240829112027-step-files-to-s3.ts new file mode 100644 index 0000000000..2147291be5 --- /dev/null +++ b/src/test/migrations/steps/20240829112027-step-files-to-s3.ts @@ -0,0 +1,96 @@ +import * as path from 'path' +import { Promises } from 'utils/promises' + +import { BaseProtocol, DB } from 'server/db' +import { FileStorage, FileStorageUtils } from 'server/service/fileStorage' +import { Logger } from 'server/utils/logger' +import { ProcessEnv } from 'server/utils/processEnv' + +// TODO: Restrict these +const allowedExtensions = [ + 'zip', + 'xlsx', + 'xlsm', + 'xls', + 'tsv', + 'pptx', + 'png', + 'pdf', + 'jpg', + 'jpeg', + 'jfif', + 'gif', + 'docx', + 'doc', + 'csv', + 'crdownload', // eg. half downloaded file should be removed from both cycleSchema.repository and + 'bmp', +] + +const client: BaseProtocol = DB + +export default async () => { + try { + // Check if _legacy.file table exists + const legacyTableExists = await client.query(` + SELECT EXISTS ( + SELECT FROM information_schema.tables + WHERE table_schema = 'public' + AND table_name = '_legacy.file' + ); + `) + + if (!legacyTableExists[0].exists) { + // Create a copy of the public.file table as _legacy.file + await client.query(` + CREATE TABLE _legacy.file AS + TABLE public.file; + `) + } else { + Logger.debug('_legacy.file table already exists, skipping creation.') + } + + // This should be changed to all files, + // left for testing purpose (all files 5.7gb, this subset around 80mb) + const files = await client.query(` + select * from public.file + where + octet_length(file) / 1024.0 / 1024.0 < 2 + and name ilike '%fin%'; + `) + + await Promises.each(files, async (fileRecord: any) => { + const { id, uuid, name, file } = fileRecord + const fileExtension = path.extname(name).slice(1).toLowerCase() + + if (allowedExtensions.includes(fileExtension)) { + const s3Key = `public/${uuid}` + const fileExists = await FileStorage.fileExists({ key: s3Key }) + + if (!fileExists) { + await FileStorage.uploadFile({ + key: s3Key, + body: Buffer.from(file), + bucket: ProcessEnv.s3BucketName, + contentType: FileStorageUtils.getContentType(fileExtension), + }) + // Logger.debug(`File ${name} (ID: ${id}) migrated successfully.`) + } else { + Logger.debug(`File ${name} (ID: ${id}) already exists in S3, skipping upload.`) + } + } else { + Logger.debug(`File ${name} (ID: ${id}) skipped due to unsupported file type.`) + } + }) + + // Remove the 'file' column from the 'public.file' table + await client.query(` + ALTER TABLE public.file + DROP COLUMN file; + `) + + Logger.debug('File migration completed and file column removed.') + } catch (err) { + Logger.error('Error migrating files:', err) + } +} diff --git a/src/tools/uploadToS3/index.ts b/src/tools/uploadToS3/index.ts new file mode 100644 index 0000000000..34dca54323 --- /dev/null +++ b/src/tools/uploadToS3/index.ts @@ -0,0 +1,42 @@ +import 'tsconfig-paths/register' +import 'dotenv/config' + +import * as fs from 'fs' +import * as path from 'path' + +import { FileStorage } from 'server/service/fileStorage' +import { Logger } from 'server/utils/logger' +import { ProcessEnv } from 'server/utils/processEnv' + +const BUCKET_NAME = ProcessEnv.s3BucketName + +if (!BUCKET_NAME) { + Logger.error('S3_BUCKET_NAME must be defined in the .env file.\nCheck .env.template for example') + process.exit(1) +} + +/** + * Uploads a file to an S3 bucket. + * @param filePath - The path to the file to upload. + */ +const uploadFileToS3 = async (filePath: string): Promise => { + try { + const fileContent = fs.readFileSync(filePath) + const key = path.basename(filePath) + + await FileStorage.uploadFile({ key, body: fileContent, bucket: BUCKET_NAME }) + Logger.debug(`File uploaded successfully to ${key}`) + } catch (err) { + Logger.error('Error uploading file to S3:', err) + } +} + +// Get the file path from command line arguments +const filePath = process.argv[2] + +if (!filePath) { + Logger.error('Please provide a file path as an argument.') + process.exit(1) +} + +uploadFileToS3(filePath) diff --git a/yarn.lock b/yarn.lock index 159ed835f0..6c1061eea8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,6 +10,593 @@ "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" +"@aws-crypto/crc32@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/crc32/-/crc32-5.2.0.tgz#cfcc22570949c98c6689cfcbd2d693d36cdae2e1" + integrity sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/crc32c@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz#4e34aab7f419307821509a98b9b08e84e0c1917e" + integrity sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/sha1-browser@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz#b0ee2d2821d3861f017e965ef3b4cb38e3b6a0f4" + integrity sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg== + dependencies: + "@aws-crypto/supports-web-crypto" "^5.2.0" + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-crypto/sha256-browser@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz#153895ef1dba6f9fce38af550e0ef58988eb649e" + integrity sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw== + dependencies: + "@aws-crypto/sha256-js" "^5.2.0" + "@aws-crypto/supports-web-crypto" "^5.2.0" + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-crypto/sha256-js@5.2.0", "@aws-crypto/sha256-js@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz#c4fdb773fdbed9a664fc1a95724e206cf3860042" + integrity sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/supports-web-crypto@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz#a1e399af29269be08e695109aa15da0a07b5b5fb" + integrity sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg== + dependencies: + tslib "^2.6.2" + +"@aws-crypto/util@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/util/-/util-5.2.0.tgz#71284c9cffe7927ddadac793c14f14886d3876da" + integrity sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ== + dependencies: + "@aws-sdk/types" "^3.222.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-s3@^3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.637.0.tgz#2879bd8ddef84397b65fa9e61bca10bb4ba08211" + integrity sha512-y6UC94fsMvhKbf0dzfnjVP1HePeGjplfcYfilZU1COIJLyTkMcUv4XcT4I407CGIrvgEafONHkiC09ygqUauNA== + 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.637.0" + "@aws-sdk/client-sts" "3.637.0" + "@aws-sdk/core" "3.635.0" + "@aws-sdk/credential-provider-node" "3.637.0" + "@aws-sdk/middleware-bucket-endpoint" "3.620.0" + "@aws-sdk/middleware-expect-continue" "3.620.0" + "@aws-sdk/middleware-flexible-checksums" "3.620.0" + "@aws-sdk/middleware-host-header" "3.620.0" + "@aws-sdk/middleware-location-constraint" "3.609.0" + "@aws-sdk/middleware-logger" "3.609.0" + "@aws-sdk/middleware-recursion-detection" "3.620.0" + "@aws-sdk/middleware-sdk-s3" "3.635.0" + "@aws-sdk/middleware-ssec" "3.609.0" + "@aws-sdk/middleware-user-agent" "3.637.0" + "@aws-sdk/region-config-resolver" "3.614.0" + "@aws-sdk/signature-v4-multi-region" "3.635.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.637.0" + "@aws-sdk/util-user-agent-browser" "3.609.0" + "@aws-sdk/util-user-agent-node" "3.614.0" + "@aws-sdk/xml-builder" "3.609.0" + "@smithy/config-resolver" "^3.0.5" + "@smithy/core" "^2.4.0" + "@smithy/eventstream-serde-browser" "^3.0.6" + "@smithy/eventstream-serde-config-resolver" "^3.0.3" + "@smithy/eventstream-serde-node" "^3.0.5" + "@smithy/fetch-http-handler" "^3.2.4" + "@smithy/hash-blob-browser" "^3.1.2" + "@smithy/hash-node" "^3.0.3" + "@smithy/hash-stream-node" "^3.1.2" + "@smithy/invalid-dependency" "^3.0.3" + "@smithy/md5-js" "^3.0.3" + "@smithy/middleware-content-length" "^3.0.5" + "@smithy/middleware-endpoint" "^3.1.0" + "@smithy/middleware-retry" "^3.0.15" + "@smithy/middleware-serde" "^3.0.3" + "@smithy/middleware-stack" "^3.0.3" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/node-http-handler" "^3.1.4" + "@smithy/protocol-http" "^4.1.0" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + "@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.15" + "@smithy/util-defaults-mode-node" "^3.0.15" + "@smithy/util-endpoints" "^2.0.5" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-retry" "^3.0.3" + "@smithy/util-stream" "^3.1.3" + "@smithy/util-utf8" "^3.0.0" + "@smithy/util-waiter" "^3.1.2" + tslib "^2.6.2" + +"@aws-sdk/client-sso-oidc@3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.637.0.tgz#d7e22ce6627c3285bf311e6c9e64c22b99bbd76a" + integrity sha512-27bHALN6Qb6m6KZmPvRieJ/QRlj1lyac/GT2Rn5kJpre8Mpp+yxrtvp3h9PjNBty4lCeFEENfY4dGNSozBuBcw== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.635.0" + "@aws-sdk/credential-provider-node" "3.637.0" + "@aws-sdk/middleware-host-header" "3.620.0" + "@aws-sdk/middleware-logger" "3.609.0" + "@aws-sdk/middleware-recursion-detection" "3.620.0" + "@aws-sdk/middleware-user-agent" "3.637.0" + "@aws-sdk/region-config-resolver" "3.614.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.637.0" + "@aws-sdk/util-user-agent-browser" "3.609.0" + "@aws-sdk/util-user-agent-node" "3.614.0" + "@smithy/config-resolver" "^3.0.5" + "@smithy/core" "^2.4.0" + "@smithy/fetch-http-handler" "^3.2.4" + "@smithy/hash-node" "^3.0.3" + "@smithy/invalid-dependency" "^3.0.3" + "@smithy/middleware-content-length" "^3.0.5" + "@smithy/middleware-endpoint" "^3.1.0" + "@smithy/middleware-retry" "^3.0.15" + "@smithy/middleware-serde" "^3.0.3" + "@smithy/middleware-stack" "^3.0.3" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/node-http-handler" "^3.1.4" + "@smithy/protocol-http" "^4.1.0" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + "@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.15" + "@smithy/util-defaults-mode-node" "^3.0.15" + "@smithy/util-endpoints" "^2.0.5" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-retry" "^3.0.3" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-sso@3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.637.0.tgz#ae152759a5e1e576e1df6b8f4edaf59796e1758e" + integrity sha512-+KjLvgX5yJYROWo3TQuwBJlHCY0zz9PsLuEolmXQn0BVK1L/m9GteZHtd+rEdAoDGBpE0Xqjy1oz5+SmtsaRUw== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.635.0" + "@aws-sdk/middleware-host-header" "3.620.0" + "@aws-sdk/middleware-logger" "3.609.0" + "@aws-sdk/middleware-recursion-detection" "3.620.0" + "@aws-sdk/middleware-user-agent" "3.637.0" + "@aws-sdk/region-config-resolver" "3.614.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.637.0" + "@aws-sdk/util-user-agent-browser" "3.609.0" + "@aws-sdk/util-user-agent-node" "3.614.0" + "@smithy/config-resolver" "^3.0.5" + "@smithy/core" "^2.4.0" + "@smithy/fetch-http-handler" "^3.2.4" + "@smithy/hash-node" "^3.0.3" + "@smithy/invalid-dependency" "^3.0.3" + "@smithy/middleware-content-length" "^3.0.5" + "@smithy/middleware-endpoint" "^3.1.0" + "@smithy/middleware-retry" "^3.0.15" + "@smithy/middleware-serde" "^3.0.3" + "@smithy/middleware-stack" "^3.0.3" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/node-http-handler" "^3.1.4" + "@smithy/protocol-http" "^4.1.0" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + "@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.15" + "@smithy/util-defaults-mode-node" "^3.0.15" + "@smithy/util-endpoints" "^2.0.5" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-retry" "^3.0.3" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-sts@3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.637.0.tgz#6dcde6640d8a5e60dd4a2df8557284a0226d182c" + integrity sha512-xUi7x4qDubtA8QREtlblPuAcn91GS/09YVEY/RwU7xCY0aqGuFwgszAANlha4OUIqva8oVj2WO4gJuG+iaSnhw== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/client-sso-oidc" "3.637.0" + "@aws-sdk/core" "3.635.0" + "@aws-sdk/credential-provider-node" "3.637.0" + "@aws-sdk/middleware-host-header" "3.620.0" + "@aws-sdk/middleware-logger" "3.609.0" + "@aws-sdk/middleware-recursion-detection" "3.620.0" + "@aws-sdk/middleware-user-agent" "3.637.0" + "@aws-sdk/region-config-resolver" "3.614.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.637.0" + "@aws-sdk/util-user-agent-browser" "3.609.0" + "@aws-sdk/util-user-agent-node" "3.614.0" + "@smithy/config-resolver" "^3.0.5" + "@smithy/core" "^2.4.0" + "@smithy/fetch-http-handler" "^3.2.4" + "@smithy/hash-node" "^3.0.3" + "@smithy/invalid-dependency" "^3.0.3" + "@smithy/middleware-content-length" "^3.0.5" + "@smithy/middleware-endpoint" "^3.1.0" + "@smithy/middleware-retry" "^3.0.15" + "@smithy/middleware-serde" "^3.0.3" + "@smithy/middleware-stack" "^3.0.3" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/node-http-handler" "^3.1.4" + "@smithy/protocol-http" "^4.1.0" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + "@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.15" + "@smithy/util-defaults-mode-node" "^3.0.15" + "@smithy/util-endpoints" "^2.0.5" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-retry" "^3.0.3" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/core@3.635.0": + version "3.635.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.635.0.tgz#74b7d0d7fa3aa39f87ea5cf4e6c97d4d84f4ef14" + integrity sha512-i1x/E/sgA+liUE1XJ7rj1dhyXpAKO1UKFUcTTHXok2ARjWTvszHnSXMOsB77aPbmn0fUp1JTx2kHUAZ1LVt5Bg== + dependencies: + "@smithy/core" "^2.4.0" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/property-provider" "^3.1.3" + "@smithy/protocol-http" "^4.1.0" + "@smithy/signature-v4" "^4.1.0" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + "@smithy/util-middleware" "^3.0.3" + fast-xml-parser "4.4.1" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-env@3.620.1": + version "3.620.1" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.620.1.tgz#d4692c49a65ebc11dae3f7f8b053fee9268a953c" + integrity sha512-ExuILJ2qLW5ZO+rgkNRj0xiAipKT16Rk77buvPP8csR7kkCflT/gXTyzRe/uzIiETTxM7tr8xuO9MP/DQXqkfg== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-http@3.635.0": + version "3.635.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.635.0.tgz#083439af1336693049958e4b61695e4712b30fd4" + integrity sha512-iJyRgEjOCQlBMXqtwPLIKYc7Bsc6nqjrZybdMDenPDa+kmLg7xh8LxHsu9088e+2/wtLicE34FsJJIfzu3L82g== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/fetch-http-handler" "^3.2.4" + "@smithy/node-http-handler" "^3.1.4" + "@smithy/property-provider" "^3.1.3" + "@smithy/protocol-http" "^4.1.0" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + "@smithy/util-stream" "^3.1.3" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-ini@3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.637.0.tgz#dae0d8b05c8b9480da5a92beb4dd244985ecbd70" + integrity sha512-h+PFCWfZ0Q3Dx84SppET/TFpcQHmxFW8/oV9ArEvMilw4EBN+IlxgbL0CnHwjHW64szcmrM0mbebjEfHf4FXmw== + dependencies: + "@aws-sdk/credential-provider-env" "3.620.1" + "@aws-sdk/credential-provider-http" "3.635.0" + "@aws-sdk/credential-provider-process" "3.620.1" + "@aws-sdk/credential-provider-sso" "3.637.0" + "@aws-sdk/credential-provider-web-identity" "3.621.0" + "@aws-sdk/types" "3.609.0" + "@smithy/credential-provider-imds" "^3.2.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-node@3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.637.0.tgz#0ac6678ab31783adf5b1cf03add5d1da101ea946" + integrity sha512-yoEhoxJJfs7sPVQ6Is939BDQJZpZCoUgKr/ySse4YKOZ24t4VqgHA6+wV7rYh+7IW24Rd91UTvEzSuHYTlxlNA== + dependencies: + "@aws-sdk/credential-provider-env" "3.620.1" + "@aws-sdk/credential-provider-http" "3.635.0" + "@aws-sdk/credential-provider-ini" "3.637.0" + "@aws-sdk/credential-provider-process" "3.620.1" + "@aws-sdk/credential-provider-sso" "3.637.0" + "@aws-sdk/credential-provider-web-identity" "3.621.0" + "@aws-sdk/types" "3.609.0" + "@smithy/credential-provider-imds" "^3.2.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-process@3.620.1": + version "3.620.1" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.620.1.tgz#10387cf85400420bb4bbda9cc56937dcc6d6d0ee" + integrity sha512-hWqFMidqLAkaV9G460+1at6qa9vySbjQKKc04p59OT7lZ5cO5VH5S4aI05e+m4j364MBROjjk2ugNvfNf/8ILg== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-sso@3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.637.0.tgz#13acf77579df026e89ced33501489defd06a0518" + integrity sha512-Mvz+h+e62/tl+dVikLafhv+qkZJ9RUb8l2YN/LeKMWkxQylPT83CPk9aimVhCV89zth1zpREArl97+3xsfgQvA== + dependencies: + "@aws-sdk/client-sso" "3.637.0" + "@aws-sdk/token-providers" "3.614.0" + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-web-identity@3.621.0": + version "3.621.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.621.0.tgz#b25878c0a05dad60cd5f91e7e5a31a145c2f14be" + integrity sha512-w7ASSyfNvcx7+bYGep3VBgC3K6vEdLmlpjT7nSIHxxQf+WSdvy+HynwJosrpZax0sK5q0D1Jpn/5q+r5lwwW6w== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-bucket-endpoint@3.620.0": + version "3.620.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.620.0.tgz#c5dc0e98b6209a91479cad6c2c74fbc5a3429fab" + integrity sha512-eGLL0W6L3HDb3OACyetZYOWpHJ+gLo0TehQKeQyy2G8vTYXqNTeqYhuI6up9HVjBzU9eQiULVQETmgQs7TFaRg== + dependencies: + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-arn-parser" "3.568.0" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/protocol-http" "^4.1.0" + "@smithy/types" "^3.3.0" + "@smithy/util-config-provider" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-expect-continue@3.620.0": + version "3.620.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.620.0.tgz#6a362c0f0696dc6749108a33de9998e0fa6b50ec" + integrity sha512-QXeRFMLfyQ31nAHLbiTLtk0oHzG9QLMaof5jIfqcUwnOkO8YnQdeqzakrg1Alpy/VQ7aqzIi8qypkBe2KXZz0A== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/protocol-http" "^4.1.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-flexible-checksums@3.620.0": + version "3.620.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.620.0.tgz#42cd48cdc0ad9639545be000bf537969210ce8c5" + integrity sha512-ftz+NW7qka2sVuwnnO1IzBku5ccP+s5qZGeRTPgrKB7OzRW85gthvIo1vQR2w+OwHFk7WJbbhhWwbCbktnP4UA== + dependencies: + "@aws-crypto/crc32" "5.2.0" + "@aws-crypto/crc32c" "5.2.0" + "@aws-sdk/types" "3.609.0" + "@smithy/is-array-buffer" "^3.0.0" + "@smithy/protocol-http" "^4.1.0" + "@smithy/types" "^3.3.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-host-header@3.620.0": + version "3.620.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.620.0.tgz#b561d419a08a984ba364c193376b482ff5224d74" + integrity sha512-VMtPEZwqYrII/oUkffYsNWY9PZ9xpNJpMgmyU0rlDQ25O1c0Hk3fJmZRe6pEkAJ0omD7kLrqGl1DUjQVxpd/Rg== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/protocol-http" "^4.1.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-location-constraint@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.609.0.tgz#7ed82d71e5ddcd50683ef2bbde10d1cc2492057e" + integrity sha512-xzsdoTkszGVqGVPjUmgoP7TORiByLueMHieI1fhQL888WPdqctwAx3ES6d/bA9Q/i8jnc6hs+Fjhy8UvBTkE9A== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-logger@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.609.0.tgz#ed44d201f091b8bac908cbf14724c7a4d492553f" + integrity sha512-S62U2dy4jMDhDFDK5gZ4VxFdWzCtLzwbYyFZx2uvPYTECkepLUfzLic2BHg2Qvtu4QjX+oGE3P/7fwaGIsGNuQ== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-recursion-detection@3.620.0": + version "3.620.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.620.0.tgz#f8270dfff843fd756be971e5673f89c6a24c6513" + integrity sha512-nh91S7aGK3e/o1ck64sA/CyoFw+gAYj2BDOnoNa6ouyCrVJED96ZXWbhye/fz9SgmNUZR2g7GdVpiLpMKZoI5w== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/protocol-http" "^4.1.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-sdk-s3@3.635.0": + version "3.635.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.635.0.tgz#be7f61c6033a803cde59ec5a29db266b42fdbc01" + integrity sha512-RLdYJPEV4JL/7NBoFUs7VlP90X++5FlJdxHz0DzCjmiD3qCviKy+Cym3qg1gBgHwucs5XisuClxDrGokhAdTQw== + dependencies: + "@aws-sdk/core" "3.635.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-arn-parser" "3.568.0" + "@smithy/core" "^2.4.0" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/protocol-http" "^4.1.0" + "@smithy/signature-v4" "^4.1.0" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + "@smithy/util-config-provider" "^3.0.0" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-stream" "^3.1.3" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-ssec@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.609.0.tgz#b87a8bc6133f3f6bdc6801183d0f9dad3f93cf9f" + integrity sha512-GZSD1s7+JswWOTamVap79QiDaIV7byJFssBW68GYjyRS5EBjNfwA/8s+6uE6g39R3ojyTbYOmvcANoZEhSULXg== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-user-agent@3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.637.0.tgz#2b00de72b00953a477bcc02a68d8cbb5e9670c44" + integrity sha512-EYo0NE9/da/OY8STDsK2LvM4kNa79DBsf4YVtaG4P5pZ615IeFsD8xOHZeuJmUrSMlVQ8ywPRX7WMucUybsKug== + dependencies: + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.637.0" + "@smithy/protocol-http" "^4.1.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/region-config-resolver@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.614.0.tgz#9cebb31a5bcfea2a41891fff7f28d0164cde179a" + integrity sha512-vDCeMXvic/LU0KFIUjpC3RiSTIkkvESsEfbVHiHH0YINfl8HnEqR5rj+L8+phsCeVg2+LmYwYxd5NRz4PHxt5g== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/types" "^3.3.0" + "@smithy/util-config-provider" "^3.0.0" + "@smithy/util-middleware" "^3.0.3" + tslib "^2.6.2" + +"@aws-sdk/signature-v4-multi-region@3.635.0": + version "3.635.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.635.0.tgz#76e8eb66bfd9b661b4f9768b18aca2e04dd781a2" + integrity sha512-J6QY4/invOkpogCHjSaDON1hF03viPpOnsrzVuCvJMmclS/iG62R4EY0wq1alYll0YmSdmKlpJwHMWwGtqK63Q== + dependencies: + "@aws-sdk/middleware-sdk-s3" "3.635.0" + "@aws-sdk/types" "3.609.0" + "@smithy/protocol-http" "^4.1.0" + "@smithy/signature-v4" "^4.1.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/token-providers@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.614.0.tgz#88da04f6d4ce916b0b0f6e045676d04201fb47fd" + integrity sha512-okItqyY6L9IHdxqs+Z116y5/nda7rHxLvROxtAJdLavWTYDydxrZstImNgGWTeVdmc0xX2gJCI77UYUTQWnhRw== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/types@3.609.0", "@aws-sdk/types@^3.222.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.609.0.tgz#06b39d799c9f197a7b43670243e8e78a3bf7d6a5" + integrity sha512-+Tqnh9w0h2LcrUsdXyT1F8mNhXz+tVYBtP19LpeEGntmvHwa2XzvLUCWpoIAIVsHp5+HdB2X9Sn0KAtmbFXc2Q== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/util-arn-parser@3.568.0": + version "3.568.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-arn-parser/-/util-arn-parser-3.568.0.tgz#6a19a8c6bbaa520b6be1c278b2b8c17875b91527" + integrity sha512-XUKJWWo+KOB7fbnPP0+g/o5Ulku/X53t7i/h+sPHr5xxYTJJ9CYnbToo95mzxe7xWvkLrsNtJ8L+MnNn9INs2w== + dependencies: + tslib "^2.6.2" + +"@aws-sdk/util-endpoints@3.637.0": + version "3.637.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.637.0.tgz#e20bcb69028039fdbc06e98a3028c7f8d8e8adaa" + integrity sha512-pAqOKUHeVWHEXXDIp/qoMk/6jyxIb6GGjnK1/f8dKHtKIEs4tKsnnL563gceEvdad53OPXIt86uoevCcCzmBnw== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/types" "^3.3.0" + "@smithy/util-endpoints" "^2.0.5" + tslib "^2.6.2" + +"@aws-sdk/util-locate-window@^3.0.0": + version "3.568.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.568.0.tgz#2acc4b2236af0d7494f7e517401ba6b3c4af11ff" + integrity sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig== + dependencies: + tslib "^2.6.2" + +"@aws-sdk/util-user-agent-browser@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.609.0.tgz#aa15421b2e32ae8bc589dac2bd6e8969832ce588" + integrity sha512-fojPU+mNahzQ0YHYBsx0ZIhmMA96H+ZIZ665ObU9tl+SGdbLneVZVikGve+NmHTQwHzwkFsZYYnVKAkreJLAtA== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/types" "^3.3.0" + bowser "^2.11.0" + tslib "^2.6.2" + +"@aws-sdk/util-user-agent-node@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.614.0.tgz#1e3f49a80f841a3f21647baed2adce01aac5beb5" + integrity sha512-15ElZT88peoHnq5TEoEtZwoXTXRxNrk60TZNdpl/TUBJ5oNJ9Dqb5Z4ryb8ofN6nm9aFf59GVAerFDz8iUoHBA== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/xml-builder@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.609.0.tgz#eeb3d5cde000a23cfeeefe0354b6193440dc7d87" + integrity sha512-l9XxNcA4HX98rwCC2/KoiWcmEiRfZe4G+mYwDbCFT87JIMj6GBhLDkAzr/W8KAaA2IDr8Vc6J8fZPgVulxxfMA== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + "@babel/cli@^7.17.6": version "7.19.3" resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.19.3.tgz#55914ed388e658e0b924b3a95da1296267e278e2" @@ -1848,6 +2435,496 @@ dependencies: "@sinonjs/commons" "^1.7.0" +"@smithy/abort-controller@^3.1.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-3.1.1.tgz#291210611ff6afecfc198d0ca72d5771d8461d16" + integrity sha512-MBJBiidoe+0cTFhyxT8g+9g7CeVccLM0IOKKUMCNQ1CNMJ/eIfoo0RTfVrXOONEI1UCN1W+zkiHSbzUNE9dZtQ== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/chunked-blob-reader-native@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-3.0.0.tgz#f1104b30030f76f9aadcbd3cdca4377bd1ba2695" + integrity sha512-VDkpCYW+peSuM4zJip5WDfqvg2Mo/e8yxOv3VF1m11y7B8KKMKVFtmZWDe36Fvk8rGuWrPZHHXZ7rR7uM5yWyg== + dependencies: + "@smithy/util-base64" "^3.0.0" + tslib "^2.6.2" + +"@smithy/chunked-blob-reader@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader/-/chunked-blob-reader-3.0.0.tgz#e5d3b04e9b273ba8b7ede47461e2aa96c8aa49e0" + integrity sha512-sbnURCwjF0gSToGlsBiAmd1lRCmSn72nu9axfJu5lIx6RUEgHu6GwTMbqCdhQSi0Pumcm5vFxsi9XWXb2mTaoA== + dependencies: + tslib "^2.6.2" + +"@smithy/config-resolver@^3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@smithy/config-resolver/-/config-resolver-3.0.5.tgz#727978bba7ace754c741c259486a19d3083431fd" + integrity sha512-SkW5LxfkSI1bUC74OtfBbdz+grQXYiPYolyu8VfpLIjEoN/sHVBlLeGXMQ1vX4ejkgfv6sxVbQJ32yF2cl1veA== + dependencies: + "@smithy/node-config-provider" "^3.1.4" + "@smithy/types" "^3.3.0" + "@smithy/util-config-provider" "^3.0.0" + "@smithy/util-middleware" "^3.0.3" + tslib "^2.6.2" + +"@smithy/core@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@smithy/core/-/core-2.4.0.tgz#56e917b6ab2dffeba681a05395c40a757d681147" + integrity sha512-cHXq+FneIF/KJbt4q4pjN186+Jf4ZB0ZOqEaZMBhT79srEyGDDBV31NqBRBjazz8ppQ1bJbDJMY9ba5wKFV36w== + dependencies: + "@smithy/middleware-endpoint" "^3.1.0" + "@smithy/middleware-retry" "^3.0.15" + "@smithy/middleware-serde" "^3.0.3" + "@smithy/protocol-http" "^4.1.0" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/credential-provider-imds@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.0.tgz#0e0e7ddaff1a8633cb927aee1056c0ab506b7ecf" + integrity sha512-0SCIzgd8LYZ9EJxUjLXBmEKSZR/P/w6l7Rz/pab9culE/RWuqelAKGJvn5qUOl8BgX8Yj5HWM50A5hiB/RzsgA== + dependencies: + "@smithy/node-config-provider" "^3.1.4" + "@smithy/property-provider" "^3.1.3" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + tslib "^2.6.2" + +"@smithy/eventstream-codec@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-codec/-/eventstream-codec-3.1.2.tgz#4a1c72b34400631b829241151984a1ad8c4f963c" + integrity sha512-0mBcu49JWt4MXhrhRAlxASNy0IjDRFU+aWNDRal9OtUJvJNiwDuyKMUONSOjLjSCeGwZaE0wOErdqULer8r7yw== + dependencies: + "@aws-crypto/crc32" "5.2.0" + "@smithy/types" "^3.3.0" + "@smithy/util-hex-encoding" "^3.0.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-browser@^3.0.6": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.6.tgz#a4ab4f7cfbd137bcaa54c375276f9214e568fd8f" + integrity sha512-2hM54UWQUOrki4BtsUI1WzmD13/SeaqT/AB3EUJKbcver/WgKNaiJ5y5F5XXuVe6UekffVzuUDrBZVAA3AWRpQ== + dependencies: + "@smithy/eventstream-serde-universal" "^3.0.5" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-config-resolver@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.3.tgz#f852e096d0ad112363b4685e1d441088d1fce67a" + integrity sha512-NVTYjOuYpGfrN/VbRQgn31x73KDLfCXCsFdad8DiIc3IcdxL+dYA9zEQPyOP7Fy2QL8CPy2WE4WCUD+ZsLNfaQ== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-node@^3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.5.tgz#2bbf5c9312a28f23bc55ae284efa9499f8b8f982" + integrity sha512-+upXvnHNyZP095s11jF5dhGw/Ihzqwl5G+/KtMnoQOpdfC3B5HYCcDVG9EmgkhJMXJlM64PyN5gjJl0uXFQehQ== + dependencies: + "@smithy/eventstream-serde-universal" "^3.0.5" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-universal@^3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.5.tgz#e1cc2f71f4d174a03e00ce4b563395a81dd17bec" + integrity sha512-5u/nXbyoh1s4QxrvNre9V6vfyoLWuiVvvd5TlZjGThIikc3G+uNiG9uOTCWweSRjv1asdDIWK7nOmN7le4RYHQ== + dependencies: + "@smithy/eventstream-codec" "^3.1.2" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/fetch-http-handler@^3.2.4": + version "3.2.4" + resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.4.tgz#c754de7e0ff2541b73ac9ba7cc955940114b3d62" + integrity sha512-kBprh5Gs5h7ug4nBWZi1FZthdqSM+T7zMmsZxx0IBvWUn7dK3diz2SHn7Bs4dQGFDk8plDv375gzenDoNwrXjg== + dependencies: + "@smithy/protocol-http" "^4.1.0" + "@smithy/querystring-builder" "^3.0.3" + "@smithy/types" "^3.3.0" + "@smithy/util-base64" "^3.0.0" + tslib "^2.6.2" + +"@smithy/hash-blob-browser@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@smithy/hash-blob-browser/-/hash-blob-browser-3.1.2.tgz#90281c1f183d93686fb4f26107f1819644d68829" + integrity sha512-hAbfqN2UbISltakCC2TP0kx4LqXBttEv2MqSPE98gVuDFMf05lU+TpC41QtqGP3Ff5A3GwZMPfKnEy0VmEUpmg== + dependencies: + "@smithy/chunked-blob-reader" "^3.0.0" + "@smithy/chunked-blob-reader-native" "^3.0.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/hash-node@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-3.0.3.tgz#82c5cb7b0f1a29ee7319081853d2d158c07dff24" + integrity sha512-2ctBXpPMG+B3BtWSGNnKELJ7SH9e4TNefJS0cd2eSkOOROeBnnVBnAy9LtJ8tY4vUEoe55N4CNPxzbWvR39iBw== + dependencies: + "@smithy/types" "^3.3.0" + "@smithy/util-buffer-from" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/hash-stream-node@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@smithy/hash-stream-node/-/hash-stream-node-3.1.2.tgz#89f0290ae44b113863878e75b10c484ff48af71c" + integrity sha512-PBgDMeEdDzi6JxKwbfBtwQG9eT9cVwsf0dZzLXoJF4sHKHs5HEo/3lJWpn6jibfJwT34I1EBXpBnZE8AxAft6g== + dependencies: + "@smithy/types" "^3.3.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/invalid-dependency@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/invalid-dependency/-/invalid-dependency-3.0.3.tgz#8d9fd70e3a94b565a4eba4ffbdc95238e1930528" + integrity sha512-ID1eL/zpDULmHJbflb864k72/SNOZCADRc9i7Exq3RUNJw6raWUSlFEQ+3PX3EYs++bTxZB2dE9mEHTQLv61tw== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/is-array-buffer@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz#f84f0d9f9a36601a9ca9381688bd1b726fd39111" + integrity sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA== + dependencies: + tslib "^2.6.2" + +"@smithy/is-array-buffer@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz#9a95c2d46b8768946a9eec7f935feaddcffa5e7a" + integrity sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ== + dependencies: + tslib "^2.6.2" + +"@smithy/md5-js@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/md5-js/-/md5-js-3.0.3.tgz#55ee40aa24075b096c39f7910590c18ff7660c98" + integrity sha512-O/SAkGVwpWmelpj/8yDtsaVe6sINHLB1q8YE/+ZQbDxIw3SRLbTZuRaI10K12sVoENdnHqzPp5i3/H+BcZ3m3Q== + dependencies: + "@smithy/types" "^3.3.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/middleware-content-length@^3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@smithy/middleware-content-length/-/middleware-content-length-3.0.5.tgz#1680aa4fb2a1c0505756103c9a5c2916307d9035" + integrity sha512-ILEzC2eyxx6ncej3zZSwMpB5RJ0zuqH7eMptxC4KN3f+v9bqT8ohssKbhNR78k/2tWW+KS5Spw+tbPF4Ejyqvw== + dependencies: + "@smithy/protocol-http" "^4.1.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/middleware-endpoint@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-3.1.0.tgz#9b8a496d87a68ec43f3f1a0139868d6765a88119" + integrity sha512-5y5aiKCEwg9TDPB4yFE7H6tYvGFf1OJHNczeY10/EFF8Ir8jZbNntQJxMWNfeQjC1mxPsaQ6mR9cvQbf+0YeMw== + dependencies: + "@smithy/middleware-serde" "^3.0.3" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/shared-ini-file-loader" "^3.1.4" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + "@smithy/util-middleware" "^3.0.3" + tslib "^2.6.2" + +"@smithy/middleware-retry@^3.0.15": + version "3.0.15" + resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-3.0.15.tgz#9b96900cde70d8aafd267e13f4e79241be90e0c7" + integrity sha512-iTMedvNt1ApdvkaoE8aSDuwaoc+BhvHqttbA/FO4Ty+y/S5hW6Ci/CTScG7vam4RYJWZxdTElc3MEfHRVH6cgQ== + dependencies: + "@smithy/node-config-provider" "^3.1.4" + "@smithy/protocol-http" "^4.1.0" + "@smithy/service-error-classification" "^3.0.3" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-retry" "^3.0.3" + tslib "^2.6.2" + uuid "^9.0.1" + +"@smithy/middleware-serde@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-3.0.3.tgz#74d974460f74d99f38c861e6862984543a880a66" + integrity sha512-puUbyJQBcg9eSErFXjKNiGILJGtiqmuuNKEYNYfUD57fUl4i9+mfmThtQhvFXU0hCVG0iEJhvQUipUf+/SsFdA== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/middleware-stack@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-3.0.3.tgz#91845c7e61e6f137fa912b623b6def719a4f6ce7" + integrity sha512-r4klY9nFudB0r9UdSMaGSyjyQK5adUyPnQN/ZM6M75phTxOdnc/AhpvGD1fQUvgmqjQEBGCwpnPbDm8pH5PapA== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/node-config-provider@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-3.1.4.tgz#05647bed666aa8036a1ad72323c1942e5d421be1" + integrity sha512-YvnElQy8HR4vDcAjoy7Xkx9YT8xZP4cBXcbJSgm/kxmiQu08DwUwj8rkGnyoJTpfl/3xYHH+d8zE+eHqoDCSdQ== + dependencies: + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/node-http-handler@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-3.1.4.tgz#be4195e45639e690d522cd5f11513ea822ff9d5f" + integrity sha512-+UmxgixgOr/yLsUxcEKGH0fMNVteJFGkmRltYFHnBMlogyFdpzn2CwqWmxOrfJELhV34v0WSlaqG1UtE1uXlJg== + dependencies: + "@smithy/abort-controller" "^3.1.1" + "@smithy/protocol-http" "^4.1.0" + "@smithy/querystring-builder" "^3.0.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/property-provider@^3.1.3": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-3.1.3.tgz#afd57ea82a3f6c79fbda95e3cb85c0ee0a79f39a" + integrity sha512-zahyOVR9Q4PEoguJ/NrFP4O7SMAfYO1HLhB18M+q+Z4KFd4V2obiMnlVoUFzFLSPeVt1POyNWneHHrZaTMoc/g== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/protocol-http@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-4.1.0.tgz#23519d8f45bf4f33960ea5415847bc2b620a010b" + integrity sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/querystring-builder@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-3.0.3.tgz#6b0e566f885bb84938d077c69e8f8555f686af13" + integrity sha512-vyWckeUeesFKzCDaRwWLUA1Xym9McaA6XpFfAK5qI9DKJ4M33ooQGqvM4J+LalH4u/Dq9nFiC8U6Qn1qi0+9zw== + dependencies: + "@smithy/types" "^3.3.0" + "@smithy/util-uri-escape" "^3.0.0" + tslib "^2.6.2" + +"@smithy/querystring-parser@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/querystring-parser/-/querystring-parser-3.0.3.tgz#272a6b83f88dfcbbec8283d72a6bde850cc00091" + integrity sha512-zahM1lQv2YjmznnfQsWbYojFe55l0SLG/988brlLv1i8z3dubloLF+75ATRsqPBboUXsW6I9CPGE5rQgLfY0vQ== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/service-error-classification@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-3.0.3.tgz#73484255060a094aa9372f6cd972dcaf97e3ce80" + integrity sha512-Jn39sSl8cim/VlkLsUhRFq/dKDnRUFlfRkvhOJaUbLBXUsLRLNf9WaxDv/z9BjuQ3A6k/qE8af1lsqcwm7+DaQ== + dependencies: + "@smithy/types" "^3.3.0" + +"@smithy/shared-ini-file-loader@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.4.tgz#7dceaf5a5307a2ee347ace8aba17312a1a3ede15" + integrity sha512-qMxS4hBGB8FY2GQqshcRUy1K6k8aBWP5vwm8qKkCT3A9K2dawUwOIJfqh9Yste/Bl0J2lzosVyrXDj68kLcHXQ== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/signature-v4@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-4.1.0.tgz#251ff43dc1f4ad66776122732fea9e56efc56443" + integrity sha512-aRryp2XNZeRcOtuJoxjydO6QTaVhxx/vjaR+gx7ZjaFgrgPRyZ3HCTbfwqYj6ZWEBHkCSUfcaymKPURaByukag== + dependencies: + "@smithy/is-array-buffer" "^3.0.0" + "@smithy/protocol-http" "^4.1.0" + "@smithy/types" "^3.3.0" + "@smithy/util-hex-encoding" "^3.0.0" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-uri-escape" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/smithy-client@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-3.2.0.tgz#6db94024e4bdaefa079ac68dbea23dafbea230c8" + integrity sha512-pDbtxs8WOhJLJSeaF/eAbPgXg4VVYFlRcL/zoNYA5WbG3wBL06CHtBSg53ppkttDpAJ/hdiede+xApip1CwSLw== + dependencies: + "@smithy/middleware-endpoint" "^3.1.0" + "@smithy/middleware-stack" "^3.0.3" + "@smithy/protocol-http" "^4.1.0" + "@smithy/types" "^3.3.0" + "@smithy/util-stream" "^3.1.3" + tslib "^2.6.2" + +"@smithy/types@^3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-3.3.0.tgz#fae037c733d09bc758946a01a3de0ef6e210b16b" + integrity sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA== + dependencies: + tslib "^2.6.2" + +"@smithy/url-parser@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-3.0.3.tgz#e8a060d9810b24b1870385fc2b02485b8a6c5955" + integrity sha512-pw3VtZtX2rg+s6HMs6/+u9+hu6oY6U7IohGhVNnjbgKy86wcIsSZwgHrFR+t67Uyxvp4Xz3p3kGXXIpTNisq8A== + dependencies: + "@smithy/querystring-parser" "^3.0.3" + "@smithy/types" "^3.3.0" + 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" + integrity sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ== + dependencies: + "@smithy/util-buffer-from" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-body-length-browser@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz#86ec2f6256310b4845a2f064e2f571c1ca164ded" + integrity sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-body-length-node@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz#99a291bae40d8932166907fe981d6a1f54298a6d" + integrity sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA== + dependencies: + tslib "^2.6.2" + +"@smithy/util-buffer-from@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz#6fc88585165ec73f8681d426d96de5d402021e4b" + integrity sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA== + dependencies: + "@smithy/is-array-buffer" "^2.2.0" + tslib "^2.6.2" + +"@smithy/util-buffer-from@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz#559fc1c86138a89b2edaefc1e6677780c24594e3" + integrity sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA== + dependencies: + "@smithy/is-array-buffer" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-config-provider@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz#62c6b73b22a430e84888a8f8da4b6029dd5b8efe" + integrity sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-defaults-mode-browser@^3.0.15": + version "3.0.15" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.15.tgz#df73b9ae3dddc9126e0bb93ebc720b09d7163858" + integrity sha512-FZ4Psa3vjp8kOXcd3HJOiDPBCWtiilLl57r0cnNtq/Ga9RSDrM5ERL6xt+tO43+2af6Pn5Yp92x2n5vPuduNfg== + dependencies: + "@smithy/property-provider" "^3.1.3" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + bowser "^2.11.0" + tslib "^2.6.2" + +"@smithy/util-defaults-mode-node@^3.0.15": + version "3.0.15" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.15.tgz#d52476e1f2e66525d918b51f8d5a9b0972bf518e" + integrity sha512-KSyAAx2q6d0t6f/S4XB2+3+6aQacm3aLMhs9aLMqn18uYGUepbdssfogW5JQZpc6lXNBnp0tEnR5e9CEKmEd7A== + dependencies: + "@smithy/config-resolver" "^3.0.5" + "@smithy/credential-provider-imds" "^3.2.0" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/property-provider" "^3.1.3" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/util-endpoints@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@smithy/util-endpoints/-/util-endpoints-2.0.5.tgz#e3a7a4d1c41250bfd2b2d890d591273a7d8934be" + integrity sha512-ReQP0BWihIE68OAblC/WQmDD40Gx+QY1Ez8mTdFMXpmjfxSyz2fVQu3A4zXRfQU9sZXtewk3GmhfOHswvX+eNg== + dependencies: + "@smithy/node-config-provider" "^3.1.4" + "@smithy/types" "^3.3.0" + 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" + integrity sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-middleware@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/util-middleware/-/util-middleware-3.0.3.tgz#07bf9602682f5a6c55bc2f0384303f85fc68c87e" + integrity sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/util-retry@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-3.0.3.tgz#9b2ac0dbb1c81f69812a8affa4d772bebfc0e049" + integrity sha512-AFw+hjpbtVApzpNDhbjNG5NA3kyoMs7vx0gsgmlJF4s+yz1Zlepde7J58zpIRIsdjc+emhpAITxA88qLkPF26w== + dependencies: + "@smithy/service-error-classification" "^3.0.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/util-stream@^3.1.3": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-3.1.3.tgz#699ee2397cc1d474e46d2034039d5263812dca64" + integrity sha512-FIv/bRhIlAxC0U7xM1BCnF2aDRPq0UaelqBHkM2lsCp26mcBbgI0tCVTv+jGdsQLUmAMybua/bjDsSu8RQHbmw== + dependencies: + "@smithy/fetch-http-handler" "^3.2.4" + "@smithy/node-http-handler" "^3.1.4" + "@smithy/types" "^3.3.0" + "@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@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz#e43358a78bf45d50bb736770077f0f09195b6f54" + integrity sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg== + dependencies: + tslib "^2.6.2" + +"@smithy/util-utf8@^2.0.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-2.3.0.tgz#dd96d7640363259924a214313c3cf16e7dd329c5" + integrity sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A== + dependencies: + "@smithy/util-buffer-from" "^2.2.0" + tslib "^2.6.2" + +"@smithy/util-utf8@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-3.0.0.tgz#1a6a823d47cbec1fd6933e5fc87df975286d9d6a" + integrity sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA== + dependencies: + "@smithy/util-buffer-from" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-waiter@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@smithy/util-waiter/-/util-waiter-3.1.2.tgz#2d40c3312f3537feee763459a19acafab4c75cf3" + integrity sha512-4pP0EV3iTsexDx+8PPGAKCQpd/6hsQBaQhqWzU4hqKPHN5epPsxKbvUTIiYIHTxaKt6/kEaqPBpu/ufvfbrRzw== + dependencies: + "@smithy/abort-controller" "^3.1.1" + "@smithy/types" "^3.3.0" + 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" @@ -3843,6 +4920,11 @@ boolbase@^1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== +bowser@^2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" + integrity sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA== + bplist-parser@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.2.0.tgz#43a9d183e5bf9d545200ceac3e712f79ebbe8d0e" @@ -6614,6 +7696,13 @@ fast-text-encoding@^1.0.0: resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz#0aa25f7f638222e3396d72bf936afcf1d42d6867" integrity sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w== +fast-xml-parser@4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz#86dbf3f18edf8739326447bcaac31b4ae7f6514f" + integrity sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw== + dependencies: + strnum "^1.0.5" + fastest-levenshtein@^1.0.12: version "1.0.16" resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" @@ -12952,6 +14041,11 @@ strip-json-comments@^2.0.0, strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== +strnum@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + style-loader@^3.0.0: version "3.3.1" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.1.tgz#057dfa6b3d4d7c7064462830f9113ed417d38575" @@ -13472,6 +14566,11 @@ tslib@^2.5.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.2.tgz#1b6f07185c881557b0ffa84b111a0106989e8338" integrity sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA== +tslib@^2.6.2: + version "2.7.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" + integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -13856,6 +14955,11 @@ uuid@^9.0.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg== +uuid@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + v8-compile-cache-lib@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"