diff --git a/apps/server/package.json b/apps/server/package.json index a44cf59e..90dce2b3 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -31,6 +31,7 @@ }, "dependencies": { "@aws-sdk/client-s3": "3.701.0", + "@aws-sdk/lib-storage": "^3.779.0", "@aws-sdk/s3-request-presigner": "3.701.0", "@casl/ability": "^6.7.3", "@fastify/cookie": "^11.0.2", diff --git a/apps/server/src/core/attachment/attachment.controller.ts b/apps/server/src/core/attachment/attachment.controller.ts index 4804fce6..d46a6b47 100644 --- a/apps/server/src/core/attachment/attachment.controller.ts +++ b/apps/server/src/core/attachment/attachment.controller.ts @@ -1,310 +1,314 @@ import { - BadRequestException, - Controller, - ForbiddenException, - Get, - HttpCode, - HttpStatus, - Logger, - NotFoundException, - Param, - Post, - Req, - Res, - UseGuards, - UseInterceptors, + BadRequestException, + Controller, + ForbiddenException, + Get, + HttpCode, + HttpStatus, + Logger, + NotFoundException, + Param, + Post, + Req, + Res, + UseGuards, + UseInterceptors, } from '@nestjs/common'; -import {AttachmentService} from './services/attachment.service'; -import {FastifyReply} from 'fastify'; -import {FileInterceptor} from '../../common/interceptors/file.interceptor'; +import { AttachmentService } from './services/attachment.service'; +import { FastifyReply, FastifyRequest } from 'fastify'; +import { FileInterceptor } from '../../common/interceptors/file.interceptor'; import * as bytes from 'bytes'; -import {AuthUser} from '../../common/decorators/auth-user.decorator'; -import {AuthWorkspace} from '../../common/decorators/auth-workspace.decorator'; -import {JwtAuthGuard} from '../../common/guards/jwt-auth.guard'; -import {User, Workspace} from '@docmost/db/types/entity.types'; -import {StorageService} from '../../integrations/storage/storage.service'; +import { AuthUser } from '../../common/decorators/auth-user.decorator'; +import { AuthWorkspace } from '../../common/decorators/auth-workspace.decorator'; +import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard'; +import { User, Workspace } from '@docmost/db/types/entity.types'; +import { StorageService } from '../../integrations/storage/storage.service'; import { - getAttachmentFolderPath, - validAttachmentTypes, + getAttachmentFolderPath, + validAttachmentTypes, } from './attachment.utils'; -import {getMimeType} from '../../common/helpers'; +import { getMimeType } from '../../common/helpers'; import { - AttachmentType, - inlineFileExtensions, - MAX_AVATAR_SIZE, + AttachmentType, + inlineFileExtensions, + MAX_AVATAR_SIZE, } from './attachment.constants'; import { - SpaceCaslAction, - SpaceCaslSubject, + SpaceCaslAction, + SpaceCaslSubject, } from '../casl/interfaces/space-ability.type'; import SpaceAbilityFactory from '../casl/abilities/space-ability.factory'; import { - WorkspaceCaslAction, - WorkspaceCaslSubject, + WorkspaceCaslAction, + WorkspaceCaslSubject, } from '../casl/interfaces/workspace-ability.type'; import WorkspaceAbilityFactory from '../casl/abilities/workspace-ability.factory'; -import {PageRepo} from '@docmost/db/repos/page/page.repo'; -import {AttachmentRepo} from '@docmost/db/repos/attachment/attachment.repo'; -import {validate as isValidUUID} from 'uuid'; -import {EnvironmentService} from "../../integrations/environment/environment.service"; +import { PageRepo } from '@docmost/db/repos/page/page.repo'; +import { AttachmentRepo } from '@docmost/db/repos/attachment/attachment.repo'; +import { validate as isValidUUID } from 'uuid'; +import { EnvironmentService } from '../../integrations/environment/environment.service'; @Controller() export class AttachmentController { - private readonly logger = new Logger(AttachmentController.name); + private readonly logger = new Logger(AttachmentController.name); - constructor( - private readonly attachmentService: AttachmentService, - private readonly storageService: StorageService, - private readonly workspaceAbility: WorkspaceAbilityFactory, - private readonly spaceAbility: SpaceAbilityFactory, - private readonly pageRepo: PageRepo, - private readonly attachmentRepo: AttachmentRepo, - private readonly environmentService: EnvironmentService, - ) { - } + constructor( + private readonly attachmentService: AttachmentService, + private readonly storageService: StorageService, + private readonly workspaceAbility: WorkspaceAbilityFactory, + private readonly spaceAbility: SpaceAbilityFactory, + private readonly pageRepo: PageRepo, + private readonly attachmentRepo: AttachmentRepo, + private readonly environmentService: EnvironmentService, + ) {} - @UseGuards(JwtAuthGuard) - @HttpCode(HttpStatus.OK) - @Post('files/upload') - @UseInterceptors(FileInterceptor) - async uploadFile( - @Req() req: any, - @Res() res: FastifyReply, - @AuthUser() user: User, - @AuthWorkspace() workspace: Workspace, - ) { - const maxFileSize = bytes(this.environmentService.getFileUploadSizeLimit()); + @UseGuards(JwtAuthGuard) + @HttpCode(HttpStatus.OK) + @Post('files/upload') + @UseInterceptors(FileInterceptor) + async uploadFile( + @Req() req: FastifyRequest, + @Res() res: FastifyReply, + @AuthUser() user: User, + @AuthWorkspace() workspace: Workspace, + ) { + //TODO: get file size + // Request hangs if file upload fails + // no workaround seem to work yet + // https://github.com/fastify/fastify-multipart/issues/497 + const maxFileSize = bytes(this.environmentService.getFileUploadSizeLimit()); - let file = null; - try { - file = await req.file({ - limits: {fileSize: maxFileSize, fields: 3, files: 1}, - }); - } catch (err: any) { - this.logger.error(err.message); - if (err?.statusCode === 413) { - throw new BadRequestException( - `File too large. Exceeds the ${this.environmentService.getFileUploadSizeLimit()} limit`, - ); - } - } + let file = null; + try { + file = await req.file({ + limits: { fileSize: maxFileSize, fields: 3, files: 1 }, + }); - if (!file) { - throw new BadRequestException('Failed to upload file'); - } - - const pageId = file.fields?.pageId?.value; - - if (!pageId) { - throw new BadRequestException('PageId is required'); - } - - const page = await this.pageRepo.findById(pageId); - - if (!page) { - throw new NotFoundException('Page not found'); - } - - const spaceAbility = await this.spaceAbility.createForUser( - user, - page.spaceId, + } catch (err: any) { + this.logger.error(err.message); + if (err?.statusCode === 413) { + throw new BadRequestException( + `File too large. Exceeds the ${this.environmentService.getFileUploadSizeLimit()} limit`, ); - if (spaceAbility.cannot(SpaceCaslAction.Manage, SpaceCaslSubject.Page)) { - throw new ForbiddenException(); - } - - const spaceId = page.spaceId; - - const attachmentId = file.fields?.attachmentId?.value; - if (attachmentId && !isValidUUID(attachmentId)) { - throw new BadRequestException('Invalid attachment id'); - } - - try { - const fileResponse = await this.attachmentService.uploadFile({ - filePromise: file, - pageId: pageId, - spaceId: spaceId, - userId: user.id, - workspaceId: workspace.id, - attachmentId: attachmentId, - }); - - return res.send(fileResponse); - } catch (err: any) { - if (err?.statusCode === 413) { - const errMessage = `File too large. Exceeds the ${this.environmentService.getFileUploadSizeLimit()} limit`; - this.logger.error(errMessage); - throw new BadRequestException(errMessage); - } - this.logger.error(err); - throw new BadRequestException('Error processing file upload.'); - } + } } - @UseGuards(JwtAuthGuard) - @Get('/files/:fileId/:fileName') - async getFile( - @Res() res: FastifyReply, - @AuthUser() user: User, - @AuthWorkspace() workspace: Workspace, - @Param('fileId') fileId: string, - @Param('fileName') fileName?: string, + if (!file) { + throw new BadRequestException('Failed to upload file'); + } + + const pageId = file.fields?.pageId?.value; + + if (!pageId) { + throw new BadRequestException('PageId is required'); + } + + const page = await this.pageRepo.findById(pageId); + + if (!page) { + throw new NotFoundException('Page not found'); + } + + const spaceAbility = await this.spaceAbility.createForUser( + user, + page.spaceId, + ); + if (spaceAbility.cannot(SpaceCaslAction.Manage, SpaceCaslSubject.Page)) { + throw new ForbiddenException(); + } + + const spaceId = page.spaceId; + + const attachmentId = file.fields?.attachmentId?.value; + if (attachmentId && !isValidUUID(attachmentId)) { + throw new BadRequestException('Invalid attachment id'); + } + + try { + const fileResponse = await this.attachmentService.uploadFile({ + filePromise: file, + pageId: pageId, + spaceId: spaceId, + userId: user.id, + workspaceId: workspace.id, + attachmentId: attachmentId, + }); + + return res.send(fileResponse); + } catch (err: any) { + if (err?.statusCode === 413) { + const errMessage = `File too large. Exceeds the ${this.environmentService.getFileUploadSizeLimit()} limit`; + this.logger.error(errMessage); + throw new BadRequestException(errMessage); + } + this.logger.error(err); + throw new BadRequestException('Error processing file upload.'); + } + } + + @UseGuards(JwtAuthGuard) + @Get('/files/:fileId/:fileName') + async getFile( + @Res() res: FastifyReply, + @AuthUser() user: User, + @AuthWorkspace() workspace: Workspace, + @Param('fileId') fileId: string, + @Param('fileName') fileName?: string, + ) { + if (!isValidUUID(fileId)) { + throw new NotFoundException('Invalid file id'); + } + + const attachment = await this.attachmentRepo.findById(fileId); + if ( + !attachment || + attachment.workspaceId !== workspace.id || + !attachment.pageId || + !attachment.spaceId ) { - if (!isValidUUID(fileId)) { - throw new NotFoundException('Invalid file id'); - } + throw new NotFoundException(); + } - const attachment = await this.attachmentRepo.findById(fileId); - if ( - !attachment || - attachment.workspaceId !== workspace.id || - !attachment.pageId || - !attachment.spaceId - ) { - throw new NotFoundException(); - } + const spaceAbility = await this.spaceAbility.createForUser( + user, + attachment.spaceId, + ); - const spaceAbility = await this.spaceAbility.createForUser( - user, - attachment.spaceId, + if (spaceAbility.cannot(SpaceCaslAction.Read, SpaceCaslSubject.Page)) { + throw new ForbiddenException(); + } + + try { + const fileStream = await this.storageService.read(attachment.filePath); + res.headers({ + 'Content-Type': attachment.mimeType, + 'Cache-Control': 'private, max-age=3600', + }); + + if (!inlineFileExtensions.includes(attachment.fileExt)) { + res.header( + 'Content-Disposition', + `attachment; filename="${encodeURIComponent(attachment.fileName)}"`, ); + } - if (spaceAbility.cannot(SpaceCaslAction.Read, SpaceCaslSubject.Page)) { - throw new ForbiddenException(); - } + return res.send(fileStream); + } catch (err) { + this.logger.error(err); + throw new NotFoundException('File not found'); + } + } - try { - const fileStream = await this.storageService.read(attachment.filePath); - res.headers({ - 'Content-Type': attachment.mimeType, - 'Cache-Control': 'private, max-age=3600', - }); + @UseGuards(JwtAuthGuard) + @HttpCode(HttpStatus.OK) + @Post('attachments/upload-image') + @UseInterceptors(FileInterceptor) + async uploadAvatarOrLogo( + @Req() req: any, + @Res() res: FastifyReply, + @AuthUser() user: User, + @AuthWorkspace() workspace: Workspace, + ) { + const maxFileSize = bytes(MAX_AVATAR_SIZE); - if (!inlineFileExtensions.includes(attachment.fileExt)) { - res.header( - 'Content-Disposition', - `attachment; filename="${encodeURIComponent(attachment.fileName)}"`, - ); - } - - return res.send(fileStream); - } catch (err) { - this.logger.error(err); - throw new NotFoundException('File not found'); - } + let file = null; + try { + file = await req.file({ + limits: { fileSize: maxFileSize, fields: 3, files: 1 }, + }); + } catch (err: any) { + if (err?.statusCode === 413) { + throw new BadRequestException( + `File too large. Exceeds the ${MAX_AVATAR_SIZE} limit`, + ); + } } - @UseGuards(JwtAuthGuard) - @HttpCode(HttpStatus.OK) - @Post('attachments/upload-image') - @UseInterceptors(FileInterceptor) - async uploadAvatarOrLogo( - @Req() req: any, - @Res() res: FastifyReply, - @AuthUser() user: User, - @AuthWorkspace() workspace: Workspace, + if (!file) { + throw new BadRequestException('Invalid file upload'); + } + + const attachmentType = file.fields?.type?.value; + const spaceId = file.fields?.spaceId?.value; + + if (!attachmentType) { + throw new BadRequestException('attachment type is required'); + } + + if ( + !validAttachmentTypes.includes(attachmentType) || + attachmentType === AttachmentType.File ) { - const maxFileSize = bytes(MAX_AVATAR_SIZE); - - let file = null; - try { - file = await req.file({ - limits: {fileSize: maxFileSize, fields: 3, files: 1}, - }); - } catch (err: any) { - if (err?.statusCode === 413) { - throw new BadRequestException( - `File too large. Exceeds the ${MAX_AVATAR_SIZE} limit`, - ); - } - } - - if (!file) { - throw new BadRequestException('Invalid file upload'); - } - - const attachmentType = file.fields?.type?.value; - const spaceId = file.fields?.spaceId?.value; - - if (!attachmentType) { - throw new BadRequestException('attachment type is required'); - } - - if ( - !validAttachmentTypes.includes(attachmentType) || - attachmentType === AttachmentType.File - ) { - throw new BadRequestException('Invalid image attachment type'); - } - - if (attachmentType === AttachmentType.WorkspaceLogo) { - const ability = this.workspaceAbility.createForUser(user, workspace); - if ( - ability.cannot( - WorkspaceCaslAction.Manage, - WorkspaceCaslSubject.Settings, - ) - ) { - throw new ForbiddenException(); - } - } - - if (attachmentType === AttachmentType.SpaceLogo) { - if (!spaceId) { - throw new BadRequestException('spaceId is required'); - } - - const spaceAbility = await this.spaceAbility.createForUser(user, spaceId); - if ( - spaceAbility.cannot(SpaceCaslAction.Manage, SpaceCaslSubject.Settings) - ) { - throw new ForbiddenException(); - } - } - - try { - const fileResponse = await this.attachmentService.uploadImage( - file, - attachmentType, - user.id, - workspace.id, - spaceId, - ); - - return res.send(fileResponse); - } catch (err: any) { - this.logger.error(err); - throw new BadRequestException('Error processing file upload.'); - } + throw new BadRequestException('Invalid image attachment type'); } - @Get('attachments/img/:attachmentType/:fileName') - async getLogoOrAvatar( - @Res() res: FastifyReply, - @AuthWorkspace() workspace: Workspace, - @Param('attachmentType') attachmentType: AttachmentType, - @Param('fileName') fileName?: string, + if (attachmentType === AttachmentType.WorkspaceLogo) { + const ability = this.workspaceAbility.createForUser(user, workspace); + if ( + ability.cannot( + WorkspaceCaslAction.Manage, + WorkspaceCaslSubject.Settings, + ) + ) { + throw new ForbiddenException(); + } + } + + if (attachmentType === AttachmentType.SpaceLogo) { + if (!spaceId) { + throw new BadRequestException('spaceId is required'); + } + + const spaceAbility = await this.spaceAbility.createForUser(user, spaceId); + if ( + spaceAbility.cannot(SpaceCaslAction.Manage, SpaceCaslSubject.Settings) + ) { + throw new ForbiddenException(); + } + } + + try { + const fileResponse = await this.attachmentService.uploadImage( + file, + attachmentType, + user.id, + workspace.id, + spaceId, + ); + + return res.send(fileResponse); + } catch (err: any) { + this.logger.error(err); + throw new BadRequestException('Error processing file upload.'); + } + } + + @Get('attachments/img/:attachmentType/:fileName') + async getLogoOrAvatar( + @Res() res: FastifyReply, + @AuthWorkspace() workspace: Workspace, + @Param('attachmentType') attachmentType: AttachmentType, + @Param('fileName') fileName?: string, + ) { + if ( + !validAttachmentTypes.includes(attachmentType) || + attachmentType === AttachmentType.File ) { - if ( - !validAttachmentTypes.includes(attachmentType) || - attachmentType === AttachmentType.File - ) { - throw new BadRequestException('Invalid image attachment type'); - } - - const filePath = `${getAttachmentFolderPath(attachmentType, workspace.id)}/${fileName}`; - - try { - const fileStream = await this.storageService.read(filePath); - res.headers({ - 'Content-Type': getMimeType(filePath), - 'Cache-Control': 'private, max-age=86400', - }); - return res.send(fileStream); - } catch (err) { - this.logger.error(err); - throw new NotFoundException('File not found'); - } + throw new BadRequestException('Invalid image attachment type'); } + + const filePath = `${getAttachmentFolderPath(attachmentType, workspace.id)}/${fileName}`; + + try { + const fileStream = await this.storageService.read(filePath); + res.headers({ + 'Content-Type': getMimeType(filePath), + 'Cache-Control': 'private, max-age=86400', + }); + return res.send(fileStream); + } catch (err) { + this.logger.error(err); + throw new NotFoundException('File not found'); + } + } } diff --git a/apps/server/src/core/attachment/attachment.utils.ts b/apps/server/src/core/attachment/attachment.utils.ts index 59b94dd0..35dcc8a4 100644 --- a/apps/server/src/core/attachment/attachment.utils.ts +++ b/apps/server/src/core/attachment/attachment.utils.ts @@ -1,11 +1,11 @@ import { MultipartFile } from '@fastify/multipart'; -import { randomBytes } from 'crypto'; import { sanitize } from 'sanitize-filename-ts'; import * as path from 'path'; import { AttachmentType } from './attachment.constants'; +import { Readable } from 'stream'; export interface PreparedFile { - buffer: Buffer; + stream: Readable; fileName: string; fileSize: number; fileExtension: string; @@ -22,16 +22,14 @@ export async function prepareFile( } try { - const rand = randomBytes(8).toString('hex'); - - const buffer = await file.toBuffer(); + const stream = file.file; const sanitizedFilename = sanitize(file.filename).replace(/ /g, '_'); const fileName = sanitizedFilename.slice(0, 255); - const fileSize = buffer.length; + const fileSize = 300; //buffer.length; const fileExtension = path.extname(file.filename).toLowerCase(); return { - buffer, + stream, fileName, fileSize, fileExtension, diff --git a/apps/server/src/core/attachment/services/attachment.service.ts b/apps/server/src/core/attachment/services/attachment.service.ts index b79c8c65..9ba54e73 100644 --- a/apps/server/src/core/attachment/services/attachment.service.ts +++ b/apps/server/src/core/attachment/services/attachment.service.ts @@ -76,7 +76,7 @@ export class AttachmentService { const filePath = `${getAttachmentFolderPath(AttachmentType.File, workspaceId)}/${attachmentId}/${preparedFile.fileName}`; - await this.uploadToDrive(filePath, preparedFile.buffer); + await this.uploadToDrive(filePath, preparedFile.stream); let attachment: Attachment = null; try { @@ -124,7 +124,7 @@ export class AttachmentService { const filePath = `${getAttachmentFolderPath(type, workspaceId)}/${preparedFile.fileName}`; - await this.uploadToDrive(filePath, preparedFile.buffer); + await this.uploadToDrive(filePath, preparedFile.stream); let attachment: Attachment = null; let oldFileName: string = null; diff --git a/apps/server/src/integrations/storage/drivers/local.driver.ts b/apps/server/src/integrations/storage/drivers/local.driver.ts index f2553733..ad64e6b9 100644 --- a/apps/server/src/integrations/storage/drivers/local.driver.ts +++ b/apps/server/src/integrations/storage/drivers/local.driver.ts @@ -3,8 +3,11 @@ import { LocalStorageConfig, StorageOption, } from '../interfaces'; -import { join } from 'path'; +import { join, dirname } from 'path'; import * as fs from 'fs-extra'; +import { pipeline } from 'stream/promises'; +import { createReadStream, createWriteStream } from 'node:fs'; +import { Readable } from 'stream'; export class LocalDriver implements StorageDriver { private readonly config: LocalStorageConfig; @@ -17,17 +20,19 @@ export class LocalDriver implements StorageDriver { return join(this.config.storagePath, filePath); } - async upload(filePath: string, file: Buffer): Promise { + async upload(filePath: string, file: Readable): Promise { try { - await fs.outputFile(this._fullPath(filePath), file); + const fullPath = this._fullPath(filePath); + await fs.mkdir(dirname(fullPath), { recursive: true }); + await pipeline(file, createWriteStream(fullPath)); } catch (err) { throw new Error(`Failed to upload file: ${(err as Error).message}`); } } - async read(filePath: string): Promise { + async read(filePath: string): Promise { try { - return await fs.readFile(this._fullPath(filePath)); + return createReadStream(this._fullPath(filePath)); } catch (err) { throw new Error(`Failed to read file: ${(err as Error).message}`); } diff --git a/apps/server/src/integrations/storage/drivers/s3.driver.ts b/apps/server/src/integrations/storage/drivers/s3.driver.ts index 78f7548c..68509427 100644 --- a/apps/server/src/integrations/storage/drivers/s3.driver.ts +++ b/apps/server/src/integrations/storage/drivers/s3.driver.ts @@ -4,13 +4,12 @@ import { GetObjectCommand, HeadObjectCommand, NoSuchKey, - PutObjectCommand, S3Client, } from '@aws-sdk/client-s3'; -import { streamToBuffer } from '../storage.utils'; import { Readable } from 'stream'; import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; import { getMimeType } from '../../../common/helpers'; +import { Upload } from '@aws-sdk/lib-storage'; export class S3Driver implements StorageDriver { private readonly s3Client: S3Client; @@ -21,25 +20,27 @@ export class S3Driver implements StorageDriver { this.s3Client = new S3Client(config as any); } - async upload(filePath: string, file: Buffer): Promise { + async upload(filePath: string, file: Readable): Promise { try { const contentType = getMimeType(filePath); - const command = new PutObjectCommand({ - Bucket: this.config.bucket, - Key: filePath, - Body: file, - ContentType: contentType, - // ACL: "public-read", + const upload = new Upload({ + client: this.s3Client, + params: { + Bucket: this.config.bucket, + Key: filePath, + Body: file, + ContentType: contentType, + }, }); - await this.s3Client.send(command); + await upload.done(); } catch (err) { throw new Error(`Failed to upload file: ${(err as Error).message}`); } } - async read(filePath: string): Promise { + async read(filePath: string): Promise { try { const command = new GetObjectCommand({ Bucket: this.config.bucket, @@ -48,7 +49,7 @@ export class S3Driver implements StorageDriver { const response = await this.s3Client.send(command); - return streamToBuffer(response.Body as Readable); + return response.Body as Readable; } catch (err) { throw new Error(`Failed to read file from S3: ${(err as Error).message}`); } diff --git a/apps/server/src/integrations/storage/interfaces/storage-driver.interface.ts b/apps/server/src/integrations/storage/interfaces/storage-driver.interface.ts index 419587f4..736d9de4 100644 --- a/apps/server/src/integrations/storage/interfaces/storage-driver.interface.ts +++ b/apps/server/src/integrations/storage/interfaces/storage-driver.interface.ts @@ -1,7 +1,9 @@ -export interface StorageDriver { - upload(filePath: string, file: Buffer): Promise; +import { Readable } from 'stream'; - read(filePath: string): Promise; +export interface StorageDriver { + upload(filePath: string, file: Readable): Promise; + + read(filePath: string): Promise; exists(filePath: string): Promise; diff --git a/apps/server/src/integrations/storage/storage.service.ts b/apps/server/src/integrations/storage/storage.service.ts index acbd2188..ef3c0c93 100644 --- a/apps/server/src/integrations/storage/storage.service.ts +++ b/apps/server/src/integrations/storage/storage.service.ts @@ -1,6 +1,7 @@ import { Inject, Injectable, Logger } from '@nestjs/common'; import { STORAGE_DRIVER_TOKEN } from './constants/storage.constants'; import { StorageDriver } from './interfaces'; +import { Readable } from 'stream'; @Injectable() export class StorageService { @@ -9,12 +10,12 @@ export class StorageService { @Inject(STORAGE_DRIVER_TOKEN) private storageDriver: StorageDriver, ) {} - async upload(filePath: string, fileContent: Buffer | any) { + async upload(filePath: string, fileContent: Readable) { await this.storageDriver.upload(filePath, fileContent); this.logger.debug(`File uploaded successfully. Path: ${filePath}`); } - async read(filePath: string): Promise { + async read(filePath: string): Promise { return this.storageDriver.read(filePath); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0a053674..ed093637 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -399,6 +399,9 @@ importers: '@aws-sdk/client-s3': specifier: 3.701.0 version: 3.701.0 + '@aws-sdk/lib-storage': + specifier: ^3.779.0 + version: 3.779.0(@aws-sdk/client-s3@3.701.0) '@aws-sdk/s3-request-presigner': specifier: 3.701.0 version: 3.701.0 @@ -766,6 +769,12 @@ packages: peerDependencies: '@aws-sdk/client-sts': ^3.696.0 + '@aws-sdk/lib-storage@3.779.0': + resolution: {integrity: sha512-AZfykrCgfnhlb5d5uyThHsqIwt41PYgnUTMyDuk4hbuKbiY8pfOiPdg8BYsC59iD2T4Iw9NujYhWUD+l8zNKcw==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@aws-sdk/client-s3': ^3.779.0 + '@aws-sdk/middleware-bucket-endpoint@3.696.0': resolution: {integrity: sha512-V07jishKHUS5heRNGFpCWCSTjRJyQLynS/ncUeE8ZYtG66StOOQWftTwDfFOSoXlIqrXgb4oT9atryzXq7Z4LQ==} engines: {node: '>=16.0.0'} @@ -3335,6 +3344,10 @@ packages: resolution: {integrity: sha512-yiW0WI30zj8ZKoSYNx90no7ugVn3khlyH/z5W8qtKBtVE6awRALbhSG+2SAHA1r6bO/6M9utxYKVZ3PCJ1rWxw==} engines: {node: '>=16.0.0'} + '@smithy/abort-controller@4.0.2': + resolution: {integrity: sha512-Sl/78VDtgqKxN2+1qduaVE140XF+Xg+TafkncspwM4jFP/LHr76ZHmIY/y3V1M0mMLNk+Je6IGbzxy23RSToMw==} + engines: {node: '>=18.0.0'} + '@smithy/chunked-blob-reader-native@3.0.1': resolution: {integrity: sha512-VEYtPvh5rs/xlyqpm5NRnfYLZn+q0SRPELbvBV+C/G7IQ+ouTuo+NKKa3ShG5OaFR8NYVMXls9hPYLTvIKKDrQ==} @@ -3349,6 +3362,10 @@ packages: resolution: {integrity: sha512-8olpW6mKCa0v+ibCjoCzgZHQx1SQmZuW/WkrdZo73wiTprTH6qhmskT60QLFdT9DRa5mXxjz89kQPZ7ZSsoqqg==} engines: {node: '>=16.0.0'} + '@smithy/core@3.2.0': + resolution: {integrity: sha512-k17bgQhVZ7YmUvA8at4af1TDpl0NDMBuBKJl8Yg0nrefwmValU+CnA5l/AriVdQNthU/33H3nK71HrLgqOPr1Q==} + engines: {node: '>=18.0.0'} + '@smithy/credential-provider-imds@3.2.8': resolution: {integrity: sha512-ZCY2yD0BY+K9iMXkkbnjo+08T2h8/34oHd0Jmh6BZUSZwaaGlGCyBT/3wnS7u7Xl33/EEfN4B6nQr3Gx5bYxgw==} engines: {node: '>=16.0.0'} @@ -3375,6 +3392,10 @@ packages: '@smithy/fetch-http-handler@4.1.3': resolution: {integrity: sha512-6SxNltSncI8s689nvnzZQc/dPXcpHQ34KUj6gR/HBroytKOd/isMG3gJF/zBE1TBmTT18TXyzhg3O3SOOqGEhA==} + '@smithy/fetch-http-handler@5.0.2': + resolution: {integrity: sha512-+9Dz8sakS9pe7f2cBocpJXdeVjMopUDLgZs1yWeu7h++WqSbjUYv/JAJwKwXw1HV6gq1jyWjxuyn24E2GhoEcQ==} + engines: {node: '>=18.0.0'} + '@smithy/hash-blob-browser@3.1.10': resolution: {integrity: sha512-elwslXOoNunmfS0fh55jHggyhccobFkexLYC1ZeZ1xP2BTSrcIBaHV2b4xUQOdctrSNOpMqOZH1r2XzWTEhyfA==} @@ -3397,6 +3418,10 @@ packages: resolution: {integrity: sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==} engines: {node: '>=16.0.0'} + '@smithy/is-array-buffer@4.0.0': + resolution: {integrity: sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==} + engines: {node: '>=18.0.0'} + '@smithy/md5-js@3.0.11': resolution: {integrity: sha512-3NM0L3i2Zm4bbgG6Ymi9NBcxXhryi3uE8fIfHJZIOfZVxOkGdjdgjR9A06SFIZCfnEIWKXZdm6Yq5/aPXFFhsQ==} @@ -3408,6 +3433,10 @@ packages: resolution: {integrity: sha512-OEJZKVUEhMOqMs3ktrTWp7UvvluMJEvD5XgQwRePSbDg1VvBaL8pX8mwPltFn6wk1GySbcVwwyldL8S+iqnrEQ==} engines: {node: '>=16.0.0'} + '@smithy/middleware-endpoint@4.1.0': + resolution: {integrity: sha512-xhLimgNCbCzsUppRTGXWkZywksuTThxaIB0HwbpsVLY5sceac4e1TZ/WKYqufQLaUy+gUSJGNdwD2jo3cXL0iA==} + engines: {node: '>=18.0.0'} + '@smithy/middleware-retry@3.0.34': resolution: {integrity: sha512-yVRr/AAtPZlUvwEkrq7S3x7Z8/xCd97m2hLDaqdz6ucP2RKHsBjEqaUA2ebNv2SsZoPEi+ZD0dZbOB1u37tGCA==} engines: {node: '>=16.0.0'} @@ -3416,34 +3445,66 @@ packages: resolution: {integrity: sha512-KzPAeySp/fOoQA82TpnwItvX8BBURecpx6ZMu75EZDkAcnPtO6vf7q4aH5QHs/F1s3/snQaSFbbUMcFFZ086Mw==} engines: {node: '>=16.0.0'} + '@smithy/middleware-serde@4.0.3': + resolution: {integrity: sha512-rfgDVrgLEVMmMn0BI8O+8OVr6vXzjV7HZj57l0QxslhzbvVfikZbVfBVthjLHqib4BW44QhcIgJpvebHlRaC9A==} + engines: {node: '>=18.0.0'} + '@smithy/middleware-stack@3.0.11': resolution: {integrity: sha512-1HGo9a6/ikgOMrTrWL/WiN9N8GSVYpuRQO5kjstAq4CvV59bjqnh7TbdXGQ4vxLD3xlSjfBjq5t1SOELePsLnA==} engines: {node: '>=16.0.0'} + '@smithy/middleware-stack@4.0.2': + resolution: {integrity: sha512-eSPVcuJJGVYrFYu2hEq8g8WWdJav3sdrI4o2c6z/rjnYDd3xH9j9E7deZQCzFn4QvGPouLngH3dQ+QVTxv5bOQ==} + engines: {node: '>=18.0.0'} + '@smithy/node-config-provider@3.1.12': resolution: {integrity: sha512-O9LVEu5J/u/FuNlZs+L7Ikn3lz7VB9hb0GtPT9MQeiBmtK8RSY3ULmsZgXhe6VAlgTw0YO+paQx4p8xdbs43vQ==} engines: {node: '>=16.0.0'} + '@smithy/node-config-provider@4.0.2': + resolution: {integrity: sha512-WgCkILRZfJwJ4Da92a6t3ozN/zcvYyJGUTmfGbgS/FkCcoCjl7G4FJaCDN1ySdvLvemnQeo25FdkyMSTSwulsw==} + engines: {node: '>=18.0.0'} + '@smithy/node-http-handler@3.3.3': resolution: {integrity: sha512-BrpZOaZ4RCbcJ2igiSNG16S+kgAc65l/2hmxWdmhyoGWHTLlzQzr06PXavJp9OBlPEG/sHlqdxjWmjzV66+BSQ==} engines: {node: '>=16.0.0'} + '@smithy/node-http-handler@4.0.4': + resolution: {integrity: sha512-/mdqabuAT3o/ihBGjL94PUbTSPSRJ0eeVTdgADzow0wRJ0rN4A27EOrtlK56MYiO1fDvlO3jVTCxQtQmK9dZ1g==} + engines: {node: '>=18.0.0'} + '@smithy/property-provider@3.1.11': resolution: {integrity: sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==} engines: {node: '>=16.0.0'} + '@smithy/property-provider@4.0.2': + resolution: {integrity: sha512-wNRoQC1uISOuNc2s4hkOYwYllmiyrvVXWMtq+TysNRVQaHm4yoafYQyjN/goYZS+QbYlPIbb/QRjaUZMuzwQ7A==} + engines: {node: '>=18.0.0'} + '@smithy/protocol-http@4.1.8': resolution: {integrity: sha512-hmgIAVyxw1LySOwkgMIUN0kjN8TG9Nc85LJeEmEE/cNEe2rkHDUWhnJf2gxcSRFLWsyqWsrZGw40ROjUogg+Iw==} engines: {node: '>=16.0.0'} + '@smithy/protocol-http@5.1.0': + resolution: {integrity: sha512-KxAOL1nUNw2JTYrtviRRjEnykIDhxc84qMBzxvu1MUfQfHTuBlCG7PA6EdVwqpJjH7glw7FqQoFxUJSyBQgu7g==} + engines: {node: '>=18.0.0'} + '@smithy/querystring-builder@3.0.11': resolution: {integrity: sha512-u+5HV/9uJaeLj5XTb6+IEF/dokWWkEqJ0XiaRRogyREmKGUgZnNecLucADLdauWFKUNbQfulHFEZEdjwEBjXRg==} engines: {node: '>=16.0.0'} + '@smithy/querystring-builder@4.0.2': + resolution: {integrity: sha512-NTOs0FwHw1vimmQM4ebh+wFQvOwkEf/kQL6bSM1Lock+Bv4I89B3hGYoUEPkmvYPkDKyp5UdXJYu+PoTQ3T31Q==} + engines: {node: '>=18.0.0'} + '@smithy/querystring-parser@3.0.11': resolution: {integrity: sha512-Je3kFvCsFMnso1ilPwA7GtlbPaTixa3WwC+K21kmMZHsBEOZYQaqxcMqeFFoU7/slFjKDIpiiPydvdJm8Q/MCw==} engines: {node: '>=16.0.0'} + '@smithy/querystring-parser@4.0.2': + resolution: {integrity: sha512-v6w8wnmZcVXjfVLjxw8qF7OwESD9wnpjp0Dqry/Pod0/5vcEA3qxCr+BhbOHlxS8O+29eLpT3aagxXGwIoEk7Q==} + engines: {node: '>=18.0.0'} + '@smithy/service-error-classification@3.0.11': resolution: {integrity: sha512-QnYDPkyewrJzCyaeI2Rmp7pDwbUETe+hU8ADkXmgNusO1bgHBH7ovXJiYmba8t0fNfJx75fE8dlM6SEmZxheog==} engines: {node: '>=16.0.0'} @@ -3452,6 +3513,10 @@ packages: resolution: {integrity: sha512-1xKSGI+U9KKdbG2qDvIR9dGrw3CNx+baqJfyr0igKEpjbHL5stsqAesYBzHChYHlelWtb87VnLWlhvfCz13H8Q==} engines: {node: '>=16.0.0'} + '@smithy/shared-ini-file-loader@4.0.2': + resolution: {integrity: sha512-J9/gTWBGVuFZ01oVA6vdb4DAjf1XbDhK6sLsu3OS9qmLrS6KB5ygpeHiM3miIbj1qgSJ96GYszXFWv6ErJ8QEw==} + engines: {node: '>=18.0.0'} + '@smithy/signature-v4@4.2.4': resolution: {integrity: sha512-5JWeMQYg81TgU4cG+OexAWdvDTs5JDdbEZx+Qr1iPbvo91QFGzjy0IkXAKaXUHqmKUJgSHK0ZxnCkgZpzkeNTA==} engines: {node: '>=16.0.0'} @@ -3460,6 +3525,10 @@ packages: resolution: {integrity: sha512-9wYrjAZFlqWhgVo3C4y/9kpc68jgiSsKUnsFPzr/MSiRL93+QRDafGTfhhKAb2wsr69Ru87WTiqSfQusSmWipA==} engines: {node: '>=16.0.0'} + '@smithy/smithy-client@4.2.0': + resolution: {integrity: sha512-Qs65/w30pWV7LSFAez9DKy0Koaoh3iHhpcpCCJ4waj/iqwsuSzJna2+vYwq46yBaqO5ZbP9TjUsATUNxrKeBdw==} + engines: {node: '>=18.0.0'} + '@smithy/types@3.7.2': resolution: {integrity: sha512-bNwBYYmN8Eh9RyjS1p2gW6MIhSO2rl7X9QeLM8iTdcGRP+eDiIWDt66c9IysCc22gefKszZv+ubV9qZc7hdESg==} engines: {node: '>=16.0.0'} @@ -3468,16 +3537,32 @@ packages: resolution: {integrity: sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==} engines: {node: '>=18.0.0'} + '@smithy/types@4.2.0': + resolution: {integrity: sha512-7eMk09zQKCO+E/ivsjQv+fDlOupcFUCSC/L2YUPgwhvowVGWbPQHjEFcmjt7QQ4ra5lyowS92SV53Zc6XD4+fg==} + engines: {node: '>=18.0.0'} + '@smithy/url-parser@3.0.11': resolution: {integrity: sha512-TmlqXkSk8ZPhfc+SQutjmFr5FjC0av3GZP4B/10caK1SbRwe/v+Wzu/R6xEKxoNqL+8nY18s1byiy6HqPG37Aw==} + '@smithy/url-parser@4.0.2': + resolution: {integrity: sha512-Bm8n3j2ScqnT+kJaClSVCMeiSenK6jVAzZCNewsYWuZtnBehEz4r2qP0riZySZVfzB+03XZHJeqfmJDkeeSLiQ==} + engines: {node: '>=18.0.0'} + '@smithy/util-base64@3.0.0': resolution: {integrity: sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==} engines: {node: '>=16.0.0'} + '@smithy/util-base64@4.0.0': + resolution: {integrity: sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg==} + engines: {node: '>=18.0.0'} + '@smithy/util-body-length-browser@3.0.0': resolution: {integrity: sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==} + '@smithy/util-body-length-browser@4.0.0': + resolution: {integrity: sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA==} + engines: {node: '>=18.0.0'} + '@smithy/util-body-length-node@3.0.0': resolution: {integrity: sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==} engines: {node: '>=16.0.0'} @@ -3490,6 +3575,10 @@ packages: resolution: {integrity: sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==} engines: {node: '>=16.0.0'} + '@smithy/util-buffer-from@4.0.0': + resolution: {integrity: sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==} + engines: {node: '>=18.0.0'} + '@smithy/util-config-provider@3.0.0': resolution: {integrity: sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==} engines: {node: '>=16.0.0'} @@ -3510,10 +3599,18 @@ packages: resolution: {integrity: sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==} engines: {node: '>=16.0.0'} + '@smithy/util-hex-encoding@4.0.0': + resolution: {integrity: sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==} + engines: {node: '>=18.0.0'} + '@smithy/util-middleware@3.0.11': resolution: {integrity: sha512-dWpyc1e1R6VoXrwLoLDd57U1z6CwNSdkM69Ie4+6uYh2GC7Vg51Qtan7ITzczuVpqezdDTKJGJB95fFvvjU/ow==} engines: {node: '>=16.0.0'} + '@smithy/util-middleware@4.0.2': + resolution: {integrity: sha512-6GDamTGLuBQVAEuQ4yDQ+ti/YINf/MEmIegrEeg7DdB/sld8BX1lqt9RRuIcABOhAGTA50bRbPzErez7SlDtDQ==} + engines: {node: '>=18.0.0'} + '@smithy/util-retry@3.0.11': resolution: {integrity: sha512-hJUC6W7A3DQgaee3Hp9ZFcOxVDZzmBIRBPlUAk8/fSOEl7pE/aX7Dci0JycNOnm9Mfr0KV2XjIlUOcGWXQUdVQ==} engines: {node: '>=16.0.0'} @@ -3522,10 +3619,18 @@ packages: resolution: {integrity: sha512-SGhGBG/KupieJvJSZp/rfHHka8BFgj56eek9px4pp7lZbOF+fRiVr4U7A3y3zJD8uGhxq32C5D96HxsTC9BckQ==} engines: {node: '>=16.0.0'} + '@smithy/util-stream@4.2.0': + resolution: {integrity: sha512-Vj1TtwWnuWqdgQI6YTUF5hQ/0jmFiOYsc51CSMgj7QfyO+RF4EnT2HNjoviNlOOmgzgvf3f5yno+EiC4vrnaWQ==} + engines: {node: '>=18.0.0'} + '@smithy/util-uri-escape@3.0.0': resolution: {integrity: sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==} engines: {node: '>=16.0.0'} + '@smithy/util-uri-escape@4.0.0': + resolution: {integrity: sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==} + engines: {node: '>=18.0.0'} + '@smithy/util-utf8@2.3.0': resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} engines: {node: '>=14.0.0'} @@ -3534,6 +3639,10 @@ packages: resolution: {integrity: sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==} engines: {node: '>=16.0.0'} + '@smithy/util-utf8@4.0.0': + resolution: {integrity: sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==} + engines: {node: '>=18.0.0'} + '@smithy/util-waiter@3.2.0': resolution: {integrity: sha512-PpjSboaDUE6yl+1qlg3Si57++e84oXdWGbuFUSAciXsVfEZJJJupR2Nb0QuXHiunt2vGR+1PTizOMvnUPaG2Qg==} engines: {node: '>=16.0.0'} @@ -4776,6 +4885,9 @@ packages: buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + buffer@5.6.0: + resolution: {integrity: sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==} + buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} @@ -8208,6 +8320,9 @@ packages: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} + stream-browserify@3.0.0: + resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} + streamsearch@1.1.0: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} engines: {node: '>=10.0.0'} @@ -9479,6 +9594,17 @@ snapshots: '@smithy/types': 3.7.2 tslib: 2.8.1 + '@aws-sdk/lib-storage@3.779.0(@aws-sdk/client-s3@3.701.0)': + dependencies: + '@aws-sdk/client-s3': 3.701.0 + '@smithy/abort-controller': 4.0.2 + '@smithy/middleware-endpoint': 4.1.0 + '@smithy/smithy-client': 4.2.0 + buffer: 5.6.0 + events: 3.3.0 + stream-browserify: 3.0.0 + tslib: 2.8.1 + '@aws-sdk/middleware-bucket-endpoint@3.696.0': dependencies: '@aws-sdk/types': 3.696.0 @@ -12099,7 +12225,7 @@ snapshots: nx: 20.4.5(@swc/core@1.5.25(@swc/helpers@0.5.5)) semver: 7.6.3 tmp: 0.2.1 - tslib: 2.8.0 + tslib: 2.8.1 yargs-parser: 21.1.1 '@nx/js@20.4.5(@babel/traverse@7.25.9)(@swc/core@1.5.25(@swc/helpers@0.5.5))(@types/node@22.13.4)(nx@20.4.5(@swc/core@1.5.25(@swc/helpers@0.5.5)))(typescript@5.7.3)': @@ -12181,7 +12307,7 @@ snapshots: chalk: 4.1.2 enquirer: 2.3.6 nx: 20.4.5(@swc/core@1.5.25(@swc/helpers@0.5.5)) - tslib: 2.8.0 + tslib: 2.8.1 yargs-parser: 21.1.1 transitivePeerDependencies: - '@swc-node/register' @@ -12405,6 +12531,11 @@ snapshots: '@smithy/types': 3.7.2 tslib: 2.8.1 + '@smithy/abort-controller@4.0.2': + dependencies: + '@smithy/types': 4.2.0 + tslib: 2.8.1 + '@smithy/chunked-blob-reader-native@3.0.1': dependencies: '@smithy/util-base64': 3.0.0 @@ -12433,6 +12564,17 @@ snapshots: '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 + '@smithy/core@3.2.0': + dependencies: + '@smithy/middleware-serde': 4.0.3 + '@smithy/protocol-http': 5.1.0 + '@smithy/types': 4.2.0 + '@smithy/util-body-length-browser': 4.0.0 + '@smithy/util-middleware': 4.0.2 + '@smithy/util-stream': 4.2.0 + '@smithy/util-utf8': 4.0.0 + tslib: 2.8.1 + '@smithy/credential-provider-imds@3.2.8': dependencies: '@smithy/node-config-provider': 3.1.12 @@ -12479,6 +12621,14 @@ snapshots: '@smithy/util-base64': 3.0.0 tslib: 2.8.1 + '@smithy/fetch-http-handler@5.0.2': + dependencies: + '@smithy/protocol-http': 5.1.0 + '@smithy/querystring-builder': 4.0.2 + '@smithy/types': 4.2.0 + '@smithy/util-base64': 4.0.0 + tslib: 2.8.1 + '@smithy/hash-blob-browser@3.1.10': dependencies: '@smithy/chunked-blob-reader': 4.0.0 @@ -12512,6 +12662,10 @@ snapshots: dependencies: tslib: 2.8.1 + '@smithy/is-array-buffer@4.0.0': + dependencies: + tslib: 2.8.1 + '@smithy/md5-js@3.0.11': dependencies: '@smithy/types': 3.7.2 @@ -12535,6 +12689,17 @@ snapshots: '@smithy/util-middleware': 3.0.11 tslib: 2.8.1 + '@smithy/middleware-endpoint@4.1.0': + dependencies: + '@smithy/core': 3.2.0 + '@smithy/middleware-serde': 4.0.3 + '@smithy/node-config-provider': 4.0.2 + '@smithy/shared-ini-file-loader': 4.0.2 + '@smithy/types': 4.2.0 + '@smithy/url-parser': 4.0.2 + '@smithy/util-middleware': 4.0.2 + tslib: 2.8.1 + '@smithy/middleware-retry@3.0.34': dependencies: '@smithy/node-config-provider': 3.1.12 @@ -12552,11 +12717,21 @@ snapshots: '@smithy/types': 3.7.2 tslib: 2.8.1 + '@smithy/middleware-serde@4.0.3': + dependencies: + '@smithy/types': 4.2.0 + tslib: 2.8.1 + '@smithy/middleware-stack@3.0.11': dependencies: '@smithy/types': 3.7.2 tslib: 2.8.1 + '@smithy/middleware-stack@4.0.2': + dependencies: + '@smithy/types': 4.2.0 + tslib: 2.8.1 + '@smithy/node-config-provider@3.1.12': dependencies: '@smithy/property-provider': 3.1.11 @@ -12564,6 +12739,13 @@ snapshots: '@smithy/types': 3.7.2 tslib: 2.8.1 + '@smithy/node-config-provider@4.0.2': + dependencies: + '@smithy/property-provider': 4.0.2 + '@smithy/shared-ini-file-loader': 4.0.2 + '@smithy/types': 4.2.0 + tslib: 2.8.1 + '@smithy/node-http-handler@3.3.3': dependencies: '@smithy/abort-controller': 3.1.9 @@ -12572,27 +12754,56 @@ snapshots: '@smithy/types': 3.7.2 tslib: 2.8.1 + '@smithy/node-http-handler@4.0.4': + dependencies: + '@smithy/abort-controller': 4.0.2 + '@smithy/protocol-http': 5.1.0 + '@smithy/querystring-builder': 4.0.2 + '@smithy/types': 4.2.0 + tslib: 2.8.1 + '@smithy/property-provider@3.1.11': dependencies: '@smithy/types': 3.7.2 tslib: 2.8.1 + '@smithy/property-provider@4.0.2': + dependencies: + '@smithy/types': 4.2.0 + tslib: 2.8.1 + '@smithy/protocol-http@4.1.8': dependencies: '@smithy/types': 3.7.2 tslib: 2.8.1 + '@smithy/protocol-http@5.1.0': + dependencies: + '@smithy/types': 4.2.0 + tslib: 2.8.1 + '@smithy/querystring-builder@3.0.11': dependencies: '@smithy/types': 3.7.2 '@smithy/util-uri-escape': 3.0.0 tslib: 2.8.1 + '@smithy/querystring-builder@4.0.2': + dependencies: + '@smithy/types': 4.2.0 + '@smithy/util-uri-escape': 4.0.0 + tslib: 2.8.1 + '@smithy/querystring-parser@3.0.11': dependencies: '@smithy/types': 3.7.2 tslib: 2.8.1 + '@smithy/querystring-parser@4.0.2': + dependencies: + '@smithy/types': 4.2.0 + tslib: 2.8.1 + '@smithy/service-error-classification@3.0.11': dependencies: '@smithy/types': 3.7.2 @@ -12602,6 +12813,11 @@ snapshots: '@smithy/types': 3.7.2 tslib: 2.8.1 + '@smithy/shared-ini-file-loader@4.0.2': + dependencies: + '@smithy/types': 4.2.0 + tslib: 2.8.1 + '@smithy/signature-v4@4.2.4': dependencies: '@smithy/is-array-buffer': 3.0.0 @@ -12623,6 +12839,16 @@ snapshots: '@smithy/util-stream': 3.3.4 tslib: 2.8.1 + '@smithy/smithy-client@4.2.0': + dependencies: + '@smithy/core': 3.2.0 + '@smithy/middleware-endpoint': 4.1.0 + '@smithy/middleware-stack': 4.0.2 + '@smithy/protocol-http': 5.1.0 + '@smithy/types': 4.2.0 + '@smithy/util-stream': 4.2.0 + tslib: 2.8.1 + '@smithy/types@3.7.2': dependencies: tslib: 2.8.1 @@ -12631,22 +12857,42 @@ snapshots: dependencies: tslib: 2.8.1 + '@smithy/types@4.2.0': + dependencies: + tslib: 2.8.1 + '@smithy/url-parser@3.0.11': dependencies: '@smithy/querystring-parser': 3.0.11 '@smithy/types': 3.7.2 tslib: 2.8.1 + '@smithy/url-parser@4.0.2': + dependencies: + '@smithy/querystring-parser': 4.0.2 + '@smithy/types': 4.2.0 + tslib: 2.8.1 + '@smithy/util-base64@3.0.0': dependencies: '@smithy/util-buffer-from': 3.0.0 '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 + '@smithy/util-base64@4.0.0': + dependencies: + '@smithy/util-buffer-from': 4.0.0 + '@smithy/util-utf8': 4.0.0 + tslib: 2.8.1 + '@smithy/util-body-length-browser@3.0.0': dependencies: tslib: 2.8.1 + '@smithy/util-body-length-browser@4.0.0': + dependencies: + tslib: 2.8.1 + '@smithy/util-body-length-node@3.0.0': dependencies: tslib: 2.8.1 @@ -12661,6 +12907,11 @@ snapshots: '@smithy/is-array-buffer': 3.0.0 tslib: 2.8.1 + '@smithy/util-buffer-from@4.0.0': + dependencies: + '@smithy/is-array-buffer': 4.0.0 + tslib: 2.8.1 + '@smithy/util-config-provider@3.0.0': dependencies: tslib: 2.8.1 @@ -12693,11 +12944,20 @@ snapshots: dependencies: tslib: 2.8.1 + '@smithy/util-hex-encoding@4.0.0': + dependencies: + tslib: 2.8.1 + '@smithy/util-middleware@3.0.11': dependencies: '@smithy/types': 3.7.2 tslib: 2.8.1 + '@smithy/util-middleware@4.0.2': + dependencies: + '@smithy/types': 4.2.0 + tslib: 2.8.1 + '@smithy/util-retry@3.0.11': dependencies: '@smithy/service-error-classification': 3.0.11 @@ -12715,10 +12975,25 @@ snapshots: '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 + '@smithy/util-stream@4.2.0': + dependencies: + '@smithy/fetch-http-handler': 5.0.2 + '@smithy/node-http-handler': 4.0.4 + '@smithy/types': 4.2.0 + '@smithy/util-base64': 4.0.0 + '@smithy/util-buffer-from': 4.0.0 + '@smithy/util-hex-encoding': 4.0.0 + '@smithy/util-utf8': 4.0.0 + tslib: 2.8.1 + '@smithy/util-uri-escape@3.0.0': dependencies: tslib: 2.8.1 + '@smithy/util-uri-escape@4.0.0': + dependencies: + tslib: 2.8.1 + '@smithy/util-utf8@2.3.0': dependencies: '@smithy/util-buffer-from': 2.2.0 @@ -12729,6 +13004,11 @@ snapshots: '@smithy/util-buffer-from': 3.0.0 tslib: 2.8.1 + '@smithy/util-utf8@4.0.0': + dependencies: + '@smithy/util-buffer-from': 4.0.0 + tslib: 2.8.1 + '@smithy/util-waiter@3.2.0': dependencies: '@smithy/abort-controller': 3.1.9 @@ -14214,6 +14494,11 @@ snapshots: buffer-from@1.1.2: {} + buffer@5.6.0: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + buffer@5.7.1: dependencies: base64-js: 1.5.1 @@ -18221,6 +18506,11 @@ snapshots: statuses@2.0.1: {} + stream-browserify@3.0.0: + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + streamsearch@1.1.0: {} string-length@4.0.2: