import { HttpException, HttpStatus, Module } from '@nestjs/common'; import { FilesS3Controller } from './files.controller'; import { MulterModule } from '@nestjs/platform-express'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { randomStringGenerator } from '@nestjs/common/utils/random-string-generator.util'; import { S3Client } from '@aws-sdk/client-s3'; import multerS3 from 'multer-s3'; import { AllConfigType } from 'src/config/config.type'; import { FilesS3Service } from './files.service'; import databaseConfig from 'src/database/config/database.config'; import { DatabaseConfig } from 'src/database/config/database-config.type'; import { DocumentFilePersistenceModule } from '../../persistence/document/document-persistence.module'; import { RelationalFilePersistenceModule } from '../../persistence/relational/relational-persistence.module'; const infrastructurePersistenceModule = (databaseConfig() as DatabaseConfig) .isDocumentDatabase ? DocumentFilePersistenceModule : RelationalFilePersistenceModule; @Module({ imports: [ infrastructurePersistenceModule, MulterModule.registerAsync({ imports: [ConfigModule], inject: [ConfigService], useFactory: (configService: ConfigService) => { const s3 = new S3Client({ region: configService.get('file.awsS3Region', { infer: true }), credentials: { accessKeyId: configService.getOrThrow('file.accessKeyId', { infer: true, }), secretAccessKey: configService.getOrThrow('file.secretAccessKey', { infer: true, }), }, }); return { fileFilter: (request, file, callback) => { if (!file.originalname.match(/\.(jpg|jpeg|png|gif)$/i)) { return callback( new HttpException( { status: HttpStatus.UNPROCESSABLE_ENTITY, errors: { file: `cantUploadFileType`, }, }, HttpStatus.UNPROCESSABLE_ENTITY, ), false, ); } callback(null, true); }, storage: multerS3({ s3: s3, bucket: configService.getOrThrow('file.awsDefaultS3Bucket', { infer: true, }), contentType: multerS3.AUTO_CONTENT_TYPE, key: (request, file, callback) => { callback( null, `${randomStringGenerator()}.${file.originalname .split('.') .pop() ?.toLowerCase()}`, ); }, }), limits: { fileSize: configService.get('file.maxFileSize', { infer: true }), }, }; }, }), ], controllers: [FilesS3Controller], providers: [FilesS3Service], exports: [FilesS3Service], }) export class FilesS3Module {}