chore: uploader service

This commit is contained in:
Matin
2025-01-26 16:08:52 +03:30
parent d6985fff26
commit e4425a07d6
13 changed files with 1426 additions and 6 deletions
+2
View File
@@ -29,8 +29,10 @@
"prepare": "husky || true"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.735.0",
"@fastify/static": "^7.0.4",
"@keyv/redis": "^4.2.0",
"@nest-lab/fastify-multer": "^1.3.0",
"@nest-lab/throttler-storage-redis": "^1.0.0",
"@nestjs-modules/mailer": "^2.0.2",
"@nestjs/axios": "^4.0.0",
+1274
View File
File diff suppressed because it is too large Load Diff
+4
View File
@@ -1,3 +1,4 @@
import { FastifyMulterModule } from "@nest-lab/fastify-multer";
import { CacheModule } from "@nestjs/cache-manager";
import { MiddlewareConsumer, Module, NestModule } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
@@ -12,6 +13,7 @@ import { AnnoucementsModule } from "./modules/announcements/announcement.module"
import { AuthModule } from "./modules/auth/auth.module";
import { DanakServicesModule } from "./modules/danak-services/danak-services.module";
import { TicketsModule } from "./modules/tickets/tickets.module";
import { UploaderModule } from "./modules/uploader/uploader.module";
import { UsersModule } from "./modules/users/users.module";
@Module({
@@ -20,11 +22,13 @@ import { UsersModule } from "./modules/users/users.module";
ConfigModule.forRoot({ cache: true, isGlobal: true }),
CacheModule.registerAsync(cacheConfig()),
TypeOrmModule.forRootAsync(databaseConfigs()),
FastifyMulterModule,
UsersModule,
TicketsModule,
AuthModule,
DanakServicesModule,
AnnoucementsModule,
UploaderModule,
],
controllers: [],
providers: [],
+26
View File
@@ -0,0 +1,26 @@
import { ConfigService } from "@nestjs/config";
export function S3Configs() {
return {
inject: [ConfigService],
useFactory(configService: ConfigService) {
return {
accessKeyId: configService.getOrThrow<string>("BUCKET_ACCESS_KEY"),
secretAccessKey: configService.getOrThrow<string>("BUCKET_SECRET_KEY"),
endpoint: configService.getOrThrow<string>("BUCKET_URL"),
region: configService.getOrThrow<string>("BUCKET_REGION"),
bucket: configService.getOrThrow<string>("BUCKET_NAME"),
url: configService.getOrThrow<string>("BUCKET_UPLOAD_URL"),
};
},
};
}
export interface IS3Configs {
accessKeyId: string;
secretAccessKey: string;
endpoint: string;
region: string;
bucket: string;
url: string;
}
-2
View File
@@ -8,7 +8,6 @@ import { getSwaggerDocument } from "./configs/swagger.config";
import { HttpExceptionFilter } from "./core/exceptions/http.exceptions";
import { PaginationInterceptor } from "./core/interceptors/pagination.interceptor";
import { ResponseInterceptor } from "./core/interceptors/response.interceptor";
async function bootstrap() {
const logger = new Logger("APP");
const app = await NestFactory.create<NestFastifyApplication>(AppModule, new FastifyAdapter());
@@ -22,7 +21,6 @@ async function bootstrap() {
credentials: true,
optionsSuccessStatus: 204,
});
const configService = app.get<ConfigService>(ConfigService);
getSwaggerDocument(app);
@@ -0,0 +1,33 @@
import { FileInterceptor } from "@nest-lab/fastify-multer";
import { Controller, Post, UploadedFile, UseInterceptors } from "@nestjs/common";
import { ApiBody, ApiConsumes, ApiOperation, ApiTags } from "@nestjs/swagger";
import { UploaderService } from "./uploader.service";
import { IFile } from "../utils/interfaces/IFile";
@ApiTags("Uploader")
@Controller("uploader")
export class UploaderController {
constructor(private readonly uploaderService: UploaderService) {}
@ApiOperation({ summary: "Uploads a single file" })
@ApiConsumes("multipart/form-data")
@UseInterceptors(FileInterceptor("file"))
@ApiBody({
required: true,
schema: {
type: "object",
properties: {
file: {
type: "string",
format: "binary",
},
},
},
})
@Post("single-file")
async uploadFile(@UploadedFile() file: IFile) {
console.log(file);
return await this.uploaderService.upload(file);
}
}
+14
View File
@@ -0,0 +1,14 @@
import { Module } from "@nestjs/common";
import { UploaderController } from "./uploader.controller";
import { UploaderService } from "./uploader.service";
import { S3Service } from "../utils/providers/s3.service";
import { UtilsModule } from "../utils/utils.module";
@Module({
imports: [UtilsModule],
providers: [UploaderService, S3Service],
controllers: [UploaderController],
exports: [UploaderService],
})
export class UploaderModule {}
+12
View File
@@ -0,0 +1,12 @@
import { Injectable } from "@nestjs/common";
import { S3Service } from "../utils/providers/s3.service";
@Injectable()
export class UploaderService {
constructor(private s3Service: S3Service) {}
async upload(file: any) {
return await this.s3Service.upload(file);
}
}
+2 -2
View File
@@ -4,9 +4,9 @@ import { TypeOrmModule } from "@nestjs/typeorm";
import { Role } from "./entities/role.entity";
import { UserGroup } from "./entities/user-group.entity";
import { User } from "./entities/user.entity";
import { RoleRepository } from "./providers/roles.repository";
import { UserGroupRepository } from "./providers/user-group.repository";
import { UsersService } from "./providers/users.service";
import { RoleRepository } from "./repositories/roles.repository";
import { UserGroupRepository } from "./repositories/user-group.repository";
import { UserRepository } from "./repositories/users.repository";
import { UsersController } from "./users.controller";
+1
View File
@@ -1 +1,2 @@
export const SMS_CONFIG = "SMS_CONFIG";
export const S3_CONFIG = "S3_CONFIG";
+8
View File
@@ -0,0 +1,8 @@
export interface IFile {
fieldname: string;
originalname: string;
encoding: string;
mimetype: string;
buffer: Buffer;
size: number;
}
+40
View File
@@ -0,0 +1,40 @@
import { randomUUID } from "node:crypto";
import { extname } from "node:path";
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
import { Inject, Injectable } from "@nestjs/common";
import { IS3Configs } from "../../../configs/s3.config";
import { S3_CONFIG } from "../constants";
import { IFile } from "../interfaces/IFile";
@Injectable()
export class S3Service {
private client: S3Client;
constructor(@Inject(S3_CONFIG) private s3Configs: IS3Configs) {
this.client = new S3Client({
endpoint: this.s3Configs.endpoint,
region: this.s3Configs.region,
credentials: {
accessKeyId: this.s3Configs.accessKeyId,
secretAccessKey: this.s3Configs.secretAccessKey,
},
});
}
async upload(file: IFile) {
const extName = extname(file.originalname);
const params = {
Body: file.buffer,
Bucket: this.s3Configs.bucket,
Key: "images/" + randomUUID() + Date.now() + extName,
};
await this.client.send(new PutObjectCommand(params));
const url = `${this.s3Configs.url}/${params.Key}`;
return {
url,
originalname: file.originalname,
size: file.size,
};
}
}
+10 -2
View File
@@ -1,10 +1,12 @@
import { Module } from "@nestjs/common";
import { SMS_CONFIG } from "./constants";
import { S3_CONFIG, SMS_CONFIG } from "./constants";
import { CacheService } from "./providers/cache.service";
import { OTPService } from "./providers/otp.service";
import { PasswordService } from "./providers/password.service";
import { S3Service } from "./providers/s3.service";
import { SmsService } from "./providers/sms.service";
import { S3Configs } from "../../configs/s3.config";
import { smsConfigs } from "../../configs/sms.config";
@Module({
@@ -13,12 +15,18 @@ import { smsConfigs } from "../../configs/sms.config";
PasswordService,
CacheService,
SmsService,
S3Service,
{
provide: SMS_CONFIG,
useFactory: smsConfigs().useFactory,
inject: smsConfigs().inject,
},
{
provide: S3_CONFIG,
useFactory: S3Configs().useFactory,
inject: S3Configs().inject,
},
],
exports: [SMS_CONFIG, OTPService, PasswordService, CacheService, SmsService],
exports: [SMS_CONFIG, S3_CONFIG, S3Service, OTPService, PasswordService, CacheService, SmsService],
})
export class UtilsModule {}